experimental-ash 0.33.1 → 0.34.0
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 +6 -0
- package/dist/docs/public/auth-and-route-protection.md +18 -7
- package/dist/docs/public/channels/README.md +7 -3
- package/dist/docs/public/channels/slack.md +10 -4
- package/dist/src/cli/commands/channel-add-conflicts.d.ts +21 -0
- package/dist/src/cli/commands/channel-add-conflicts.js +1 -0
- package/dist/src/cli/commands/channels.d.ts +9 -1
- package/dist/src/cli/commands/channels.js +1 -3
- package/dist/src/cli/dev/repl.js +1 -1
- package/dist/src/cli/run.js +1 -1
- package/dist/src/compiler/compile-agent.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/host/start-production-server.js +1 -1
- package/dist/src/node_modules/.pnpm/@clack_core@1.3.1/node_modules/@clack/core/dist/index.js +10 -0
- package/dist/src/node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js +1 -0
- package/dist/src/node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js +1 -0
- package/dist/src/node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js +1 -0
- package/dist/src/node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js +5 -0
- package/dist/src/node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js +1 -0
- package/dist/src/node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js +1 -0
- package/dist/src/packages/ash-scaffold/src/channels.js +12 -2
- package/dist/src/packages/ash-scaffold/src/cli/channel-add-prompter.js +1 -0
- package/dist/src/packages/ash-scaffold/src/cli/channel-setup-prompter.js +1 -0
- package/dist/src/packages/ash-scaffold/src/cli/command-output.js +1 -0
- package/dist/src/packages/ash-scaffold/src/cli/index.js +1 -0
- package/dist/src/packages/ash-scaffold/src/cli/prompt-ui.js +3 -0
- package/dist/src/packages/ash-scaffold/src/cli/rail-log.js +2 -0
- package/dist/src/packages/ash-scaffold/src/primitives/detect-deployment.js +1 -0
- package/dist/src/packages/ash-scaffold/src/primitives/index.js +1 -0
- package/dist/src/packages/ash-scaffold/src/primitives/pnpm-invocation.js +1 -0
- package/dist/src/packages/ash-scaffold/src/primitives/process-output.js +1 -0
- package/dist/src/packages/ash-scaffold/src/primitives/run-pnpm.js +1 -0
- package/dist/src/packages/ash-scaffold/src/primitives/run-vercel.js +1 -0
- package/dist/src/packages/ash-scaffold/src/primitives/update-slack-channel.js +1 -0
- package/dist/src/packages/ash-scaffold/src/project.js +1 -1
- package/dist/src/packages/ash-scaffold/src/steps/deploy-to-vercel.js +1 -0
- package/dist/src/packages/ash-scaffold/src/steps/index.js +1 -0
- package/dist/src/packages/ash-scaffold/src/steps/run-add-to-agent.js +2 -0
- package/dist/src/packages/ash-scaffold/src/steps/setup-slackbot.js +1 -0
- package/dist/src/packages/ash-scaffold/src/web-template.js +4713 -0
- package/dist/src/public/next/server.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -15,23 +15,34 @@ These settings apply to:
|
|
|
15
15
|
- `POST /ash/v1/session/:sessionId`
|
|
16
16
|
- `GET /ash/v1/session/:sessionId/stream`
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## Generated Web Chat Auth
|
|
19
19
|
|
|
20
|
-
`pnpm create experimental-ash-agent` scaffolds `agent/channels/ash.ts`
|
|
21
|
-
|
|
20
|
+
`pnpm create experimental-ash-agent` scaffolds `agent/channels/ash.ts` from the Web Chat example.
|
|
21
|
+
It permits Vercel OIDC and localhost requests and leaves end-user production auth as an explicit
|
|
22
|
+
placeholder:
|
|
22
23
|
|
|
23
24
|
```ts
|
|
24
25
|
// agent/channels/ash.ts
|
|
25
26
|
import { ashChannel } from "experimental-ash/channels/ash";
|
|
26
|
-
import { localDev, vercelOidc } from "experimental-ash/channels/auth";
|
|
27
|
+
import { type AuthFn, localDev, vercelOidc } from "experimental-ash/channels/auth";
|
|
28
|
+
|
|
29
|
+
function exampleProductionAuth(): AuthFn<Request> {
|
|
30
|
+
return () => {
|
|
31
|
+
if (process.env.VERCEL_ENV === "production") {
|
|
32
|
+
throw new Error("Configure production auth in agent/channels/ash.ts.");
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
27
37
|
|
|
28
38
|
export default ashChannel({
|
|
29
|
-
auth: [localDev(),
|
|
39
|
+
auth: [vercelOidc(), localDev(), exampleProductionAuth()],
|
|
30
40
|
});
|
|
31
41
|
```
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
43
|
+
Replace `exampleProductionAuth()` before a browser user submits a production request. If you
|
|
44
|
+
delete the authored file, Ash falls back to its framework default `[localDev(), vercelOidc()]`;
|
|
45
|
+
that default also does not accept browser-user traffic in production.
|
|
35
46
|
|
|
36
47
|
## Walking The Auth Array
|
|
37
48
|
|
|
@@ -111,9 +111,13 @@ export default ashChannel({
|
|
|
111
111
|
});
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
`pnpm create experimental-ash-agent` scaffolds
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
`pnpm create experimental-ash-agent` scaffolds the Web Chat example channel at
|
|
115
|
+
`agent/channels/ash.ts`. It permits Vercel OIDC and localhost requests and includes an
|
|
116
|
+
`exampleProductionAuth()` placeholder that throws in production until you replace it
|
|
117
|
+
with end-user auth. If you delete the authored file, Ash falls back to
|
|
118
|
+
`[localDev(), vercelOidc()]`; that default does not admit browser users in production.
|
|
119
|
+
See [Auth and Route Protection](../auth-and-route-protection.md) for the full walking
|
|
120
|
+
semantics and helper reference.
|
|
117
121
|
|
|
118
122
|
## Slack Channels
|
|
119
123
|
|
|
@@ -72,7 +72,7 @@ npx skills add https://github.com/vercel/connect --skill vercel-connect
|
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
Then create the Slack client from the project or agent folder that will use it, and attach this
|
|
75
|
-
project as the trigger destination
|
|
75
|
+
project as the trigger destination at the route Ash serves:
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
78
|
vercel connect create slack --triggers
|
|
@@ -85,9 +85,9 @@ but Slack never delivers `app_mention` or `message.im` events to the Connect web
|
|
|
85
85
|
step also auto-attaches the linked project at Connect's default trigger path, so detach it before
|
|
86
86
|
attaching the Ash path. `attach --triggers` then registers the currently-linked Vercel project as
|
|
87
87
|
the destination Connect forwards verified webhooks to. The `--trigger-path /ash/v1/slack` value
|
|
88
|
-
must match Ash's Slack channel route; the default Connect trigger path is not served by Ash.
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
must match Ash's Slack channel route; the default Connect trigger path is not served by Ash. You
|
|
89
|
+
can register this destination before the first production deploy. Deploy after the channel file
|
|
90
|
+
and dependencies below are ready.
|
|
91
91
|
|
|
92
92
|
Run Connect commands from the directory containing the agent's `package.json` or `vercel.json`.
|
|
93
93
|
Connect uses that project context to configure project access, webhooks, and triggers. The command
|
|
@@ -122,6 +122,12 @@ export default slackChannel({
|
|
|
122
122
|
|
|
123
123
|
Replace `slack/my-agent` with the UID from the Connect client.
|
|
124
124
|
|
|
125
|
+
Deploy the completed project after the Connect trigger destination and channel code are ready:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
VERCEL_USE_EXPERIMENTAL_FRAMEWORKS=1 vercel deploy --prod
|
|
129
|
+
```
|
|
130
|
+
|
|
125
131
|
The helper returns a complete Slack credentials object:
|
|
126
132
|
|
|
127
133
|
- `botToken` resolves an app-scoped Slack token through Connect for outbound posts.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ChannelKind } from "@vercel/ash-scaffold";
|
|
2
|
+
import type { DisabledChannelReasons } from "@vercel/ash-scaffold/cli";
|
|
3
|
+
/**
|
|
4
|
+
* Existing authored registrations that affect the scaffolded channel picker
|
|
5
|
+
* or would conflict with a generated channel module.
|
|
6
|
+
*/
|
|
7
|
+
export interface ExistingChannelRegistrations {
|
|
8
|
+
readonly disabledChannelReasons: DisabledChannelReasons;
|
|
9
|
+
readonly webRouteOwners: readonly string[];
|
|
10
|
+
readonly slackOwners: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Inspects compiled authored channels so custom filenames still disable the
|
|
14
|
+
* scaffold option for the channel behavior they register.
|
|
15
|
+
*/
|
|
16
|
+
export declare function inspectExistingChannelRegistrations(projectRoot: string): Promise<ExistingChannelRegistrations>;
|
|
17
|
+
/**
|
|
18
|
+
* Rejects scaffolding when another authored module already owns behavior
|
|
19
|
+
* emitted by the generated channel module.
|
|
20
|
+
*/
|
|
21
|
+
export declare function assertCanAddSelectedChannels(selectedChannels: readonly ChannelKind[], registrations: ExistingChannelRegistrations): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ASH_CREATE_SESSION_ROUTE_PATH}from"#protocol/routes.js";import{join}from"node:path";import{compileChannelDefinition}from"#compiler/normalize-channel.js";import{discoverAgent}from"#discover/discover-agent.js";const SCAFFOLDED_WEB_CHANNEL_LOGICAL_PATH=`channels/ash.ts`;async function inspectExistingChannelRegistrations(a){let o=join(a,`agent`),{manifest:s}=await discoverAgent({agentRoot:o,appRoot:a}),c=new Set,l=new Set;for(let t of s.channels){let r=await compileChannelDefinition(o,t),i=Array.isArray(r)?r:[r];for(let n of i)n.kind===`channel`&&(n.method===`POST`&&n.urlPath===ASH_CREATE_SESSION_ROUTE_PATH&&c.add(t.logicalPath),n.adapterKind===`slack`&&l.add(t.logicalPath))}let u={};return[...c].some(e=>e!==SCAFFOLDED_WEB_CHANNEL_LOGICAL_PATH)&&(u.web=`POST ${ASH_CREATE_SESSION_ROUTE_PATH} already registered`),l.size>0&&(u.slack=`Slack channel already registered`),{disabledChannelReasons:u,webRouteOwners:[...c],slackOwners:[...l]}}function assertCanAddSelectedChannels(t,n){if(t.includes(`web`)){let t=n.webRouteOwners.find(e=>e!==SCAFFOLDED_WEB_CHANNEL_LOGICAL_PATH);if(t!==void 0)throw Error(`Cannot scaffold Web Chat because agent/${t} already defines POST ${ASH_CREATE_SESSION_ROUTE_PATH}. Web Chat scaffolds the same Ash session routes.`)}if(t.includes(`slack`)){let e=n.slackOwners.find(e=>e!==`channels/slack.ts`);if(e!==void 0)throw Error(`Cannot scaffold Slack because agent/${e} already defines a Slack channel. Slack scaffolding would register the channel again.`)}}export{assertCanAddSelectedChannels,inspectExistingChannelRegistrations};
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { type RunAddToAgentOptions } from "@vercel/ash-scaffold/steps";
|
|
2
|
+
import { type ChannelAddPrompter } from "@vercel/ash-scaffold/cli";
|
|
3
|
+
import { type DeploymentInfo } from "@vercel/ash-scaffold/primitives";
|
|
1
4
|
export interface CliLogger {
|
|
2
5
|
error(message: string): void;
|
|
3
6
|
log(message: string): void;
|
|
@@ -5,10 +8,15 @@ export interface CliLogger {
|
|
|
5
8
|
export interface AddChannelCommandOptions {
|
|
6
9
|
force?: boolean;
|
|
7
10
|
}
|
|
11
|
+
export interface ChannelsAddDependencies {
|
|
12
|
+
createPrompter?: () => ChannelAddPrompter;
|
|
13
|
+
detectDeployment(projectPath: string): Promise<DeploymentInfo>;
|
|
14
|
+
runAddToAgent(options: RunAddToAgentOptions): Promise<void>;
|
|
15
|
+
}
|
|
8
16
|
export declare function runChannelsAddCommand(logger: CliLogger, appRoot: string, args: {
|
|
9
17
|
kind?: string;
|
|
10
18
|
options: AddChannelCommandOptions;
|
|
11
|
-
}): Promise<void>;
|
|
19
|
+
}, dependencies?: ChannelsAddDependencies): Promise<void>;
|
|
12
20
|
export interface ListChannelsCommandOptions {
|
|
13
21
|
json?: boolean;
|
|
14
22
|
}
|
|
@@ -1,3 +1 @@
|
|
|
1
|
-
import{isAshProject}from"../../packages/ash-scaffold/src/project.js";import{
|
|
2
|
-
`)}function renderExistingSlackChannelNextSteps(e){return[`Next steps:`,` Review ${e} for the configured Slack connector UID.`,` Run Vercel Connect commands only for the UID already used by that file.`].join(`
|
|
3
|
-
`)}function formatProjectPath(e,t){let n=relative(e,t);return n.length===0||n.startsWith(`..`)?t:n}function logPackageJsonMutations(e,t,n){for(let r of n.packageJsonUpdated)e.log(`Updated ${formatProjectPath(t,r.path)} with ${r.dependencies.join(`, `)}.`)}function assertUnhandledChannelMutation(e){throw Error(`Unhandled channel mutation result: ${JSON.stringify(e)}`)}async function runChannelsAddCommand(t,r,i){if(!await isAshProject(r)){t.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}try{let e=i.kind===void 0?await promptChannelKind():parseChannelKind(i.kind),a=await ensureChannel({projectRoot:r,kind:e,force:i.options.force});switch(logPackageJsonMutations(t,r,a),a.action){case`created`:t.log(`Scaffolded channel: ${e}`),t.log(renderSlackNextSteps(a.slackConnectorSlug));break;case`overwritten`:t.log(`Overwrote channel: ${e}`),t.log(renderSlackNextSteps(a.slackConnectorSlug));break;case`skipped`:{let n=a.filesSkipped[0];t.log(`Channel "${e}" already exists; left existing files unchanged.`),t.log(renderExistingSlackChannelNextSteps(formatProjectPath(r,n)));break}default:assertUnhandledChannelMutation(a)}}catch(e){t.error(e instanceof Error?e.message:String(e)),process.exitCode=1}}async function runChannelsListCommand(t,n,i){if(!await isAshProject(n)){t.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}let a=await listAuthoredChannels(n);if(i.json){t.log(JSON.stringify({channels:a},null,2));return}if(a.length===0){t.log("No channels defined. Run `ash channels add slack` to add one.");return}for(let e of a)t.log(e)}export{runChannelsAddCommand,runChannelsListCommand};
|
|
1
|
+
import{assertCanAddSelectedChannels,inspectExistingChannelRegistrations}from"./channel-add-conflicts.js";import{isAshProject}from"../../packages/ash-scaffold/src/project.js";import{listAuthoredChannels}from"../../packages/ash-scaffold/src/channels.js";import"../../packages/ash-scaffold/src/index.js";import{detectDeployment}from"../../packages/ash-scaffold/src/primitives/detect-deployment.js";import{createAddToAgentState,runAddToAgent}from"../../packages/ash-scaffold/src/steps/run-add-to-agent.js";import"../../packages/ash-scaffold/src/steps/index.js";import{ChannelAddCancelledError,createChannelAddPrompter}from"../../packages/ash-scaffold/src/cli/channel-add-prompter.js";import"../../packages/ash-scaffold/src/cli/index.js";import"../../packages/ash-scaffold/src/primitives/index.js";const NOT_AN_AGENT_MESSAGE="No Ash agent in this directory. Run `pnpm create experimental-ash-agent`, then run this command from inside the new project.",KNOWN_CHANNEL_KINDS=[`slack`,`web`];function isChannelKind(e){return KNOWN_CHANNEL_KINDS.includes(e)}function parseChannelKind(e){if(!isChannelKind(e))throw Error(`Unknown channel kind "${e}". Known: ${KNOWN_CHANNEL_KINDS.join(`, `)}.`);return e}const defaultChannelsAddDependencies={detectDeployment,runAddToAgent};async function runAddChannelsFlow(n,r,i,o){if(r===void 0&&(!process.stdin.isTTY||!process.stdout.isTTY))throw Error(`Pass a channel kind: \`ash channels add <${KNOWN_CHANNEL_KINDS.join(`|`)}>\`.`);let s=o.createPrompter?.()??createChannelAddPrompter();s.intro(`Add channels to your Ash agent`),s.log.message(`Checking the current Vercel project...`);let c=createAddToAgentState(await o.detectDeployment(n)),l;function inspectRegistrations(){return l===void 0&&(s.log.message(`Inspecting existing channel registrations...`),l=inspectExistingChannelRegistrations(n)),l}let u=r===void 0?(await inspectRegistrations()).disabledChannelReasons:void 0;await o.runAddToAgent({prompter:s,projectPath:n,state:c,presetChannels:r===void 0?void 0:[r],disabledChannelReasons:u,force:i.force,validateSelectedChannels:async t=>{!t.includes(`web`)&&!t.includes(`slack`)||assertCanAddSelectedChannels(t,await inspectRegistrations())}}),s.outro(c.channels.length===0?`No channels added.`:`Channels added.`)}async function runChannelsAddCommand(e,t,r,i=defaultChannelsAddDependencies){if(!await isAshProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}try{await runAddChannelsFlow(t,r.kind===void 0?void 0:parseChannelKind(r.kind),r.options,i)}catch(t){if(t instanceof ChannelAddCancelledError)return;e.error(t instanceof Error?t.message:String(t)),process.exitCode=1}}async function runChannelsListCommand(e,t,i){if(!await isAshProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}let a=await listAuthoredChannels(t);if(i.json){e.log(JSON.stringify({channels:a},null,2));return}if(a.length===0){e.log("No channels defined. Run `ash channels add` to add one.");return}for(let t of a)e.log(t)}export{runChannelsAddCommand,runChannelsListCommand};
|
package/dist/src/cli/dev/repl.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ASH_CONTINUE_SESSION_ROUTE_PATTERN,ASH_CREATE_SESSION_ROUTE_PATH,ASH_MESSAGE_STREAM_ROUTE_PATTERN,createAshMessageStreamRoutePath}from"#protocol/routes.js";import{createCliTheme,renderCliBanner,renderCliSection,renderCliSpeakerLine,renderCliTaggedLine}from"#cli/ui/output.js";import{
|
|
1
|
+
import{ASH_CONTINUE_SESSION_ROUTE_PATTERN,ASH_CREATE_SESSION_ROUTE_PATH,ASH_MESSAGE_STREAM_ROUTE_PATTERN,createAshMessageStreamRoutePath}from"#protocol/routes.js";import{createInterface,emitKeypressEvents}from"node:readline";import{createCliTheme,renderCliBanner,renderCliSection,renderCliSpeakerLine,renderCliTaggedLine}from"#cli/ui/output.js";import{openStreamIterable}from"#client/open-stream.js";import{isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{toErrorMessage}from"#shared/errors.js";import{createDevelopmentRequestHeadersAsync}from"#services/dev-client/request-headers.js";import{extractCurrentTurnBoundaryEvent}from"#services/dev-client/stream.js";import{resolveDevelopmentServerResourceUrl}from"#services/dev-client/url.js";import{formatVercelAuthChallengeMessage,isVercelAuthChallenge}from"#services/dev-client/vercel-auth-error.js";import{createDevClient}from"#services/dev-client.js";import{parseDevReplInput}from"#cli/dev/input.js";import{ESCAPED_RUNTIME_INPUT_PROMPT,extractPendingRuntimeInputRequests,promptForRuntimeInputRequests}from"#cli/dev/input-requests.js";import{createDevelopmentTerminal}from"#cli/dev/terminal.js";function renderConnectionRows(r){let i=[{label:`Server`,tone:`info`,value:r.serverUrl},{label:`Create`,tone:`info`,value:`POST ${ASH_CREATE_SESSION_ROUTE_PATH}`},{label:`Continue`,tone:`info`,value:`POST ${ASH_CONTINUE_SESSION_ROUTE_PATTERN}`},{label:`Stream`,tone:`info`,value:`GET ${ASH_MESSAGE_STREAM_ROUTE_PATTERN}`}];return i.push({label:`Session`,value:`Follow-up messages reuse the active continuation token.`}),i}function renderCommandRows(){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 renderIntro(e,t){return[renderCliBanner(e,{subtitle:`Interactive development REPL for the active Ash server.`,title:`Ash Dev`}),``,renderCliSection(e,{rows:renderConnectionRows(t),title:`Connection`}),``,renderCliSection(e,{rows:renderCommandRows(),title:`Commands`})].join(`
|
|
2
2
|
`)}function normalizeStepMessage(e){let t=e.trim();return t.length>0?t:null}function getRenderTag(e){return e.options?.isSubagent===!0?`subagent`:e.fallback}function getRenderTone(e){return e.options?.isSubagent===!0?`subagent`:e.fallback}function prefixSourceLabel(e){return e.options?.sourceLabel===void 0?e.message:`${e.options.sourceLabel}${e.separator??` `}${e.message}`}function formatContentEvent(e,t,n){switch(t.type){case`message.appended`:return{finalized:!1,kind:`message`,line:renderCliSpeakerLine(e,{message:t.data.messageSoFar,speaker:n?.sourceLabel??`agent`,tone:getRenderTone({fallback:`accent`,options:n})})};case`message.completed`:if(t.data.message===null)return;if(t.data.finishReason===`tool-calls`){let r=normalizeStepMessage(t.data.message);return r===null?void 0:{finalized:!0,kind:`message`,line:renderCliTaggedLine(e,{message:prefixSourceLabel({message:r,options:n,separator:`: `}),tag:getRenderTag({fallback:`step`,options:n}),tone:getRenderTone({fallback:`accent`,options:n})})}}return{finalized:!0,kind:`message`,line:renderCliSpeakerLine(e,{message:t.data.message,speaker:n?.sourceLabel??`agent`,tone:getRenderTone({fallback:`accent`,options:n})})};case`reasoning.appended`:return{finalized:!1,kind:`reasoning`,line:renderCliTaggedLine(e,{message:prefixSourceLabel({message:t.data.reasoningSoFar,options:n,separator:`: `}),tag:getRenderTag({fallback:`reasoning`,options:n}),tone:getRenderTone({fallback:`info`,options:n})})};case`reasoning.completed`:return{finalized:!0,kind:`reasoning`,line:renderCliTaggedLine(e,{message:prefixSourceLabel({message:t.data.reasoning,options:n,separator:`: `}),tag:getRenderTag({fallback:`reasoning`,options:n}),tone:getRenderTone({fallback:`info`,options:n})})};default:return}}function formatEvent(e,t,n){let r=formatContentEvent(e,t,n);if(r!==void 0)return r.line;switch(t.type){case`message.received`:return;case`actions.requested`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.actions.length} action${t.data.actions.length===1?``:`s`})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`muted`,options:n})});case`input.requested`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.requests.length} request${t.data.requests.length===1?``:`s`})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`info`,options:n})});case`action.result`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${formatActionResultLabel(t.data.result)})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`muted`,options:n})});case`session.waiting`:case`session.completed`:return;case`authorization.required`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.name}: ${t.data.description}${formatAuthorizationChallengeSuffix(t.data.authorization)})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`warning`,options:n})});case`compaction.requested`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`compacting conversation history`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`muted`,options:n})});case`compaction.completed`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`conversation history compacted`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`muted`,options:n})});case`step.failed`:case`turn.failed`:case`session.failed`:return;case`subagent.called`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.name} -> ${t.data.childSessionId})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`info`,options:n})});case`subagent.started`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.subagentName})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`info`,options:n})});case`subagent.event`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.subagentName}: ${formatNestedSubagentEventLabel(t.data.event)})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`muted`,options:n})});case`subagent.completed`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.subagentName})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`info`,options:n})});default:return}}function getEventDisplayBlockKind(e){switch(e.type){case`message.appended`:case`message.completed`:case`reasoning.appended`:case`reasoning.completed`:return`content`;default:return`meta`}}function createTurnDisplayState(){return{activeLiveContentKind:null,lastPrintedBlockKind:null}}function printDisplayLine(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 renderTurnEvent(e){let t=formatContentEvent(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=formatEvent(e.theme,e.event,e.options);return n===void 0?e.state:printDisplayLine({kind:getEventDisplayBlockKind(e.event),line:n,state:e.state,terminal:e.terminal})}function isAbortLikeError(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}function shouldDrainSubagentStreamsOnBoundary(e){return e.length===0}var ReplSubagentStreamManager=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(e){let t=resolveDevelopmentServerResourceUrl({resource:createAshMessageStreamRoutePath(e.sessionId),serverUrl:this.#n});try{for await(let n of openStreamIterable({host:this.#n,maxReconnectAttempts:3,resolveHeaders:async()=>await createDevelopmentRequestHeadersAsync({resourceUrl:t}),sessionId:e.sessionId,signal:e.controller.signal,startIndex:0}))if(this.#t.current=renderTurnEvent({event:n,options:{isSubagent:!0,sourceLabel:e.subagentName},state:this.#t.current,terminal:this.#r,theme:this.#i}),n.type===`subagent.called`&&this.subscribe({sessionId:n.data.childSessionId,subagentName:n.data.name}),isCurrentTurnBoundaryEvent(n))return}catch(t){if(isAbortLikeError(t))return;let n=toErrorMessage(t);this.#t.current=printDisplayLine({kind:`meta`,line:renderCliTaggedLine(this.#i,{message:`${e.subagentName} stream failed: ${n}`,tag:`subagent`,tone:`danger`}),state:this.#t.current,terminal:this.#r})}finally{e.controller.abort()}}};function formatActionResultLabel(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 formatAuthorizationChallengeSuffix(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 formatNestedSubagentEventLabel(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} (${formatActionResultLabel(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 formatDispatch(e,t){return t.continuationToken?renderCliTaggedLine(e,{message:`resuming session ${t.continuationToken}`,tag:`session`,tone:`info`}):renderCliTaggedLine(e,{message:`starting a new session`,tag:`session`,tone:`info`})}function formatTurnDispatch(e,t){return t.turn.inputResponses!==void 0&&t.turn.message===void 0?renderCliTaggedLine(e,{message:`responding to pending input request${t.turn.inputResponses.length===1?``:`s`}`,tag:`session`,tone:`info`}):formatDispatch(e,t.session)}function formatSessionBoundary(e,t){let n=extractCurrentTurnBoundaryEvent(t),r=extractPendingRuntimeInputRequests(t);switch(n?.type){case`session.waiting`:return[renderCliTaggedLine(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[renderCliTaggedLine(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[renderCliTaggedLine(e,{message:t?`session failed (${t}): ${n.data.message}`:`session failed: ${n.data.message}`,tag:`session`,tone:`danger`}),renderCliTaggedLine(e,{message:`cleared; the next input starts a new session`,tag:`session`,tone:`warning`})]}default:return[]}}async function waitForInputLine(e,t,n={}){return await new Promise(r=>{let i=e.input,cleanup=()=>{e.off(`close`,handleClose),e.off(`line`,handleLine),i.off(`keypress`,handleKeypress)},handleClose=()=>{cleanup(),r(void 0)},handleLine=e=>{cleanup(),r(e)},handleKeypress=(t,i)=>{n.allowEscape!==!0||i.name!==`escape`||(cleanup(),e.write(null,{ctrl:!0,name:`u`}),r(ESCAPED_RUNTIME_INPUT_PROMPT))};e.setPrompt(t),e.once(`close`,handleClose),e.once(`line`,handleLine),n.allowEscape&&(emitKeypressEvents(i,e),i.on(`keypress`,handleKeypress)),e.prompt()})}async function runTurn(e){let t=e.turn,n={current:createTurnDisplayState()},i=new ReplSubagentStreamManager({displayStateRef:n,serverUrl:e.serverUrl,terminal:e.terminal,theme:e.theme}),ask=async t=>{e.terminal.startPrompt(e.rl,t);let n=await waitForInputLine(e.rl,t,{allowEscape:!0});return e.terminal.stopPrompt(),n};try{for(;;){let a=e.client.getSession();n.current=printDisplayLine({kind:`meta`,line:formatTurnDispatch(e.theme,{session:a,turn:t}),state:n.current,terminal:e.terminal});let o=await e.client.send({inputResponses:t.inputResponses,message:t.message,onEvent(t){n.current=renderTurnEvent({event:t,state:n.current,terminal:e.terminal,theme:e.theme}),t.type===`subagent.called`&&i.subscribe({sessionId:t.data.childSessionId,subagentName:t.data.name})},onResponseStart(t){t.sessionId&&a.sessionId!==t.sessionId&&(n.current=printDisplayLine({kind:`meta`,line:renderCliTaggedLine(e.theme,{message:t.sessionId,tag:`session`,tone:`accent`}),state:n.current,terminal:e.terminal}),n.current=printDisplayLine({kind:`meta`,line:renderCliTaggedLine(e.theme,{message:resolveDevelopmentServerResourceUrl({resource:createAshMessageStreamRoutePath(t.sessionId),serverUrl:e.serverUrl}).toString(),tag:`stream`,tone:`info`}),state:n.current,terminal:e.terminal}))}}),s=extractPendingRuntimeInputRequests(o.events);if(shouldDrainSubagentStreamsOnBoundary(s)){await i.waitForIdle();for(let t of formatSessionBoundary(e.theme,o.events))n.current=printDisplayLine({kind:`meta`,line:t,state:n.current,terminal:e.terminal});return`continue`}let c=await promptForRuntimeInputRequests({ask,print(t){n.current=printDisplayLine({kind:`meta`,line:t,state:n.current,terminal:e.terminal})},requests:s,theme:e.theme});if(c.kind===`aborted`)return`exit`;if(c.kind===`deferred`)return n.current=printDisplayLine({kind:`meta`,line:renderCliTaggedLine(e.theme,{message:`left pending input requests unresolved; send a new message to ignore them`,tag:`session`,tone:`warning`}),state:n.current,terminal:e.terminal}),`continue`;t={inputResponses:c.inputResponses}}}finally{await i.close()}}async function runDevelopmentRepl(e){let t=createDevelopmentTerminal(),n=createCliTheme({color:!0}),r=createInterface({input:process.stdin,output:t.output,terminal:!0});r.on(`SIGINT`,()=>{r.close()});let a=createDevClient({serverUrl:e.serverUrl});try{for(t.print(renderIntro(n,e)),t.print(``);;){t.print(``),t.startPrompt(r,`you> `);let i=await waitForInputLine(r,`you> `);if(t.stopPrompt(),i===void 0)return;let o=parseDevReplInput(i);switch(o.kind!==`empty`&&o.kind!==`exit`&&t.print(``),o.kind){case`empty`:continue;case`help`:t.print(renderIntro(n,e)),t.print(``);continue;case`exit`:return;case`new`:await a.clear(),t.print(renderCliTaggedLine(n,{message:`cleared; the next input starts a new session`,tag:`session`,tone:`warning`})),t.print(``);continue;case`message`:try{if(await runTurn({client:a,rl:r,serverUrl:e.serverUrl,terminal:t,theme:n,turn:{message:o.message}})===`exit`)return}catch(r){isVercelAuthChallenge(r)?t.printError(renderCliTaggedLine(n,{message:formatVercelAuthChallengeMessage({serverUrl:e.serverUrl}),tag:`auth`,tone:`warning`})):t.printError(renderCliTaggedLine(n,{message:toErrorMessage(r),tag:`error`,tone:`danger`}))}t.print(``)}}}finally{await a.close(),r.close(),t.dispose()}}export{createTurnDisplayState,formatContentEvent,formatEvent,renderTurnEvent,runDevelopmentRepl,shouldDrainSubagentStreamsOnBoundary};
|
package/dist/src/cli/run.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createCliTheme,renderCliTaggedLine}from"#cli/ui/output.js";import{Command,CommanderError,InvalidArgumentError}from"#compiled/commander/index.js";import{resolveApplicationRoot}from"#internal/application/paths.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{parseDevelopmentServerUrl}from"#cli/dev/url.js";async function loadBuildHost(){return(await import(`#internal/nitro/host.js`)).buildApplication}async function loadPrintApplicationInfo(){return(await import(`#cli/commands/info.js`)).printApplicationInfo}async function loadRunDevelopmentRepl(){return(await import(`#cli/dev/repl.js`)).runDevelopmentRepl}async function loadRunEvalCommand(){return(await import(`#evals/cli/eval.js`)).runEvalCommand}async function loadStartHost(){return(await import(`#internal/nitro/host.js`)).startDevelopmentServer}async function loadStartProductionHost(){return(await import(`#internal/nitro/host.js`)).startProductionServer}function shouldPrintCliBootBanner(e){return e.name()===`info`||e.name()===`dev`}async function waitForShutdownSignal(e){await new Promise((t,n)=>{let r=!1,cleanup=()=>{process.off(`SIGINT`,handleSignal),process.off(`SIGTERM`,handleSignal)},handleSignal=()=>{r||(r=!0,cleanup(),e.close().then(t,n))};process.once(`SIGINT`,handleSignal),process.once(`SIGTERM`,handleSignal)})}async function waitForProductionServer(e){await Promise.race([e.wait(),waitForShutdownSignal({close:()=>e.close()})])}function parsePortOption(e){if(!/^-?\d+$/.test(e))throw new InvalidArgumentError(`Expected a numeric port, received "${e}".`);let t=Number(e);if(t<0||t>65535)throw new InvalidArgumentError(`Expected a port between 0 and 65535, received "${e}".`);return t}function hasInteractiveTerminal(){return!!(process.stdin.isTTY&&process.stdout.isTTY)}function rewriteDevelopmentUrlShorthand(e){let t=e[1];return e[0]!==`dev`||e.length!==2||t===void 0||t.startsWith(`-`)?[...e]:[`dev`,`--url`,t]}function resolveRemoteDevelopmentServerUrl(e){if(e.url){if(e.host!==void 0)throw new InvalidArgumentError(`The --host option cannot be used with --url.`);if(e.port!==void 0)throw new InvalidArgumentError(`The --port option cannot be used with --url.`);if(e.repl===!1)throw new InvalidArgumentError(`The --no-repl option cannot be used with --url.`);return e.url}}function createCliProgram(r,i){let c=resolveApplicationRoot(),l=resolveInstalledPackageInfo().version,u=new Command,d=createCliTheme();u.name(`ash`).description(`Build and run an Ash application.`).version(l).showHelpAfterError().exitOverride().hook(`preAction`,(e,t)=>{shouldPrintCliBootBanner(t)&&r.log(`Ash (v${l})`)}).configureOutput({writeErr:e=>{r.error(e.trimEnd())},writeOut:e=>{r.log(e.trimEnd())}});let f=u.command(`channels`).description(`Manage user-authored channels in the current project.`);return f.command(`add [kind]`).description(`
|
|
1
|
+
import{createCliTheme,renderCliTaggedLine}from"#cli/ui/output.js";import{Command,CommanderError,InvalidArgumentError}from"#compiled/commander/index.js";import{resolveApplicationRoot}from"#internal/application/paths.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{parseDevelopmentServerUrl}from"#cli/dev/url.js";async function loadBuildHost(){return(await import(`#internal/nitro/host.js`)).buildApplication}async function loadPrintApplicationInfo(){return(await import(`#cli/commands/info.js`)).printApplicationInfo}async function loadRunDevelopmentRepl(){return(await import(`#cli/dev/repl.js`)).runDevelopmentRepl}async function loadRunEvalCommand(){return(await import(`#evals/cli/eval.js`)).runEvalCommand}async function loadStartHost(){return(await import(`#internal/nitro/host.js`)).startDevelopmentServer}async function loadStartProductionHost(){return(await import(`#internal/nitro/host.js`)).startProductionServer}function shouldPrintCliBootBanner(e){return e.name()===`info`||e.name()===`dev`}async function waitForShutdownSignal(e){await new Promise((t,n)=>{let r=!1,cleanup=()=>{process.off(`SIGINT`,handleSignal),process.off(`SIGTERM`,handleSignal)},handleSignal=()=>{r||(r=!0,cleanup(),e.close().then(t,n))};process.once(`SIGINT`,handleSignal),process.once(`SIGTERM`,handleSignal)})}async function waitForProductionServer(e){await Promise.race([e.wait(),waitForShutdownSignal({close:()=>e.close()})])}function parsePortOption(e){if(!/^-?\d+$/.test(e))throw new InvalidArgumentError(`Expected a numeric port, received "${e}".`);let t=Number(e);if(t<0||t>65535)throw new InvalidArgumentError(`Expected a port between 0 and 65535, received "${e}".`);return t}function hasInteractiveTerminal(){return!!(process.stdin.isTTY&&process.stdout.isTTY)}function rewriteDevelopmentUrlShorthand(e){let t=e[1];return e[0]!==`dev`||e.length!==2||t===void 0||t.startsWith(`-`)?[...e]:[`dev`,`--url`,t]}function resolveRemoteDevelopmentServerUrl(e){if(e.url){if(e.host!==void 0)throw new InvalidArgumentError(`The --host option cannot be used with --url.`);if(e.port!==void 0)throw new InvalidArgumentError(`The --port option cannot be used with --url.`);if(e.repl===!1)throw new InvalidArgumentError(`The --no-repl option cannot be used with --url.`);return e.url}}function createCliProgram(r,i){let c=resolveApplicationRoot(),l=resolveInstalledPackageInfo().version,u=new Command,d=createCliTheme();u.name(`ash`).description(`Build and run an Ash application.`).version(l).showHelpAfterError().exitOverride().hook(`preAction`,(e,t)=>{shouldPrintCliBootBanner(t)&&r.log(`Ash (v${l})`)}).configureOutput({writeErr:e=>{r.error(e.trimEnd())},writeOut:e=>{r.log(e.trimEnd())}});let f=u.command(`channels`).description(`Manage user-authored channels in the current project.`);return f.command(`add [kind]`).description(`Add channels interactively, or scaffold a channel kind (slack | web).`).option(`-f, --force`,`Overwrite existing channel files`).action(async(e,t)=>{let{runChannelsAddCommand:n}=await import(`#cli/commands/channels.js`);await n(r,c,{kind:e,options:t})}),f.command(`list`).description(`List user-authored channels in the current project.`).option(`--json`,`Output as JSON`).action(async e=>{let{runChannelsListCommand:t}=await import(`#cli/commands/channels.js`);await t(r,c,e)}),u.command(`build`).description(`Build the current Ash application.`).action(async()=>{let{loadDevelopmentEnvironmentFiles:e}=await import(`#cli/dev/environment.js`);e(c);let n=await(i.buildHost??await loadBuildHost())(c);r.log(renderCliTaggedLine(d,{message:`built output at ${n}`,tag:`build`,tone:`success`}))}),u.command(`start`).description(`Start a built Ash application.`).option(`--host <host>`,`Host interface to bind`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 3000)`,parsePortOption).action(async e=>{let{loadDevelopmentEnvironmentFiles:n}=await import(`#cli/dev/environment.js`);n(c);let a=await(i.startProductionHost??await loadStartProductionHost())(c,{host:e.host,port:e.port});r.log(renderCliTaggedLine(d,{message:`server listening at ${a.url}`,tag:`start`,tone:`success`})),await waitForProductionServer(a)}),u.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)`,parsePortOption).option(`-u, --url <url>`,`Connect the REPL to an existing server URL`,parseDevelopmentServerUrl).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 n=resolveRemoteDevelopmentServerUrl(e),{loadDevelopmentEnvironmentFiles:a}=await import(`#cli/dev/environment.js`);if(a(c),n){if(r.log(renderCliTaggedLine(d,{message:`REPL connecting to ${n}`,tag:`dev`,tone:`info`})),!hasInteractiveTerminal()){r.log(renderCliTaggedLine(d,{message:`Interactive REPL disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`}));return}r.log(``),await(i.runDevelopmentRepl??await loadRunDevelopmentRepl())({serverUrl:n});return}let o=await(i.startHost??await loadStartHost())(c,{host:e.host,port:e.port}),s=!1,closeServer=async()=>{s||(s=!0,await o.close())};try{if(r.log(renderCliTaggedLine(d,{message:`server listening at ${o.url}`,tag:`dev`,tone:`success`})),e.repl===!1)return await waitForShutdownSignal({close:closeServer});if(!hasInteractiveTerminal())return r.log(renderCliTaggedLine(d,{message:`Interactive REPL disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`})),await waitForShutdownSignal({close:closeServer});r.log(``),await(i.runDevelopmentRepl??await loadRunDevelopmentRepl())({serverUrl:o.url})}finally{await closeServer()}}),u.command(`info`).description(`Print resolved application information.`).action(async()=>{await(i.printApplicationInfo??await loadPrintApplicationInfo())(r,c)}),u.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(`--skip-report`,`Skip suite-defined reporters (e.g. Braintrust)`).action(async e=>{await(i.runEvalCommand??await loadRunEvalCommand())(e,r)}),u}async function runCli(e=process.argv.slice(2),t=console,n={}){let i=createCliProgram(t,n),a=e.length===0?[`info`]:rewriteDevelopmentUrlShorthand(e);try{await i.parseAsync(a,{from:`user`})}catch(e){if(e instanceof CommanderError){if(e.exitCode===0)return;throw Error(e.message)}throw e}}export{runCli};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{discoverAgent}from"#discover/discover-agent.js";import{hasDiscoverErrors,summarizeDiscoverDiagnostics}from"#discover/diagnostics.js";import{resolveDiscoveryProject}from"#discover/project.js";import{createDiskProjectSource}from"#discover/project-source.js";import{writeCompilerArtifacts}from"#compiler/artifacts.js";var CompileAgentError=class extends Error{result;constructor(e){super(formatCompileAgentErrorMessage({diagnostics:e.diagnostics,diagnosticsPath:e.paths.diagnosticsPath})),this.name=`CompileAgentError`,this.result=e}};async function compileAgent(n={}){let i=n.source??createDiskProjectSource(),a=await resolveDiscoveryProject(n.startPath,{source:i}),o=await discoverAgent({...a,source:i}),s=await writeCompilerArtifacts({appRoot:a.appRoot,diagnostics:o.diagnostics,manifest:o.manifest}),c={diagnostics:o.diagnostics,manifest:s.compiledManifest,metadata:s.metadata,paths:s.paths,project:a};if(hasDiscoverErrors(o.diagnostics))throw new CompileAgentError(c);return reportDiscoverWarnings(o.diagnostics),c}function reportDiscoverWarnings(e){let t=e.filter(e=>e.severity===`warning`);if(t.length!==0)for(let e of t)console.warn(`Warning [${e.code}]: ${e.message}\n source: ${e.sourcePath}`)}function formatCompileAgentErrorMessage(e){let t=summarizeDiscoverDiagnostics(e.diagnostics),r=[`Discovery failed with ${t.errors} error(s) and ${t.warnings} warning(s).`];if(e.diagnosticsPath!==void 0&&r.push(`Diagnostics artifact: ${e.diagnosticsPath}`),e.diagnostics.length===0)return r.join(`
|
|
2
2
|
`);r.push(`Discovery diagnostics:`);for(let t of e.diagnostics)r.push(`- ${formatDiagnosticSeverity(t.severity)}: ${t.message}`),r.push(` source: ${t.sourcePath}`);return r.join(`
|
|
3
3
|
`)}function formatDiagnosticSeverity(e){return e===`error`?`Error`:`Warning`}export{CompileAgentError,compileAgent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ROOT_COMPILED_AGENT_NODE_ID,createCompiledAgentManifest,createCompiledAgentNodeManifest}from"#compiler/manifest.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{compileAgentConfig}from"#compiler/normalize-agent-config.js";import{
|
|
1
|
+
import{compileChannelDefinition}from"#compiler/normalize-channel.js";import{ROOT_COMPILED_AGENT_NODE_ID,createCompiledAgentManifest,createCompiledAgentNodeManifest}from"#compiler/manifest.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{compileAgentConfig}from"#compiler/normalize-agent-config.js";import{compileConnectionDefinition}from"#compiler/normalize-connection.js";import{compileHookEntry}from"#compiler/normalize-hook.js";import{compileSandboxDefinition}from"#compiler/normalize-sandbox.js";import{compileInstructions}from"#compiler/normalize-instructions.js";import{compileScheduleDefinition}from"#compiler/normalize-schedule.js";import{compileSkillSource}from"#compiler/normalize-skill.js";import{compileSubagentGraph}from"#compiler/normalize-subagent.js";import{compileToolEntry}from"#compiler/normalize-tool.js";async function compileAgentManifest(e){let r={modelCatalog:createCompiledRuntimeModelCatalogLoader(e.appRoot)},[a,o]=await Promise.all([compileAgentNodeManifest(e,r),compileSubagentGraph({appRoot:e.appRoot,compileAgentNodeManifest,context:r,parentNodeId:ROOT_COMPILED_AGENT_NODE_ID,subagents:e.subagents})]);return createCompiledAgentManifest({...a,remoteAgents:o.remoteAgents,subagentEdges:o.edges,subagents:o.nodes})}async function compileAgentNodeManifest(t,n){let i=await Promise.all(t.tools.map(e=>compileToolEntry(t.agentRoot,e))),s=[],c=[];for(let e of i)e.kind===`tool`?s.push(e.definition):c.push(e.name);let l=(await Promise.all(t.channels.map(n=>compileChannelDefinition(t.agentRoot,n)))).flat();return createCompiledAgentNodeManifest({agentRoot:t.agentRoot,appRoot:t.appRoot,channels:l,config:await compileAgentConfig(t,n),connections:await Promise.all(t.connections.map(e=>compileConnectionDefinition(t.agentRoot,e))),diagnosticsSummary:t.diagnosticsSummary,disabledFrameworkTools:c,hooks:t.hooks.map(e=>compileHookEntry(e)),sandbox:t.sandbox===null?null:await compileSandboxDefinition(t.agentRoot,t.sandbox),sandboxWorkspaces:t.sandboxWorkspaces.map(e=>({logicalPath:e.logicalPath,rootEntries:[...e.rootEntries],sourceId:e.sourceId,sourcePath:e.sourcePath})),schedules:await Promise.all(t.schedules.map(e=>compileScheduleDefinition(t.agentRoot,e))),skills:await Promise.all(t.skills.map(e=>compileSkillSource(t.agentRoot,e))),instructions:t.instructions===void 0?void 0:await compileInstructions(t.agentRoot,t.instructions),tools:s})}export{compileAgentManifest};
|
|
@@ -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.
|
|
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.34.0`}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 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,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{ASH_HEALTH_ROUTE_PATH}from"#protocol/routes.js";import{join,resolve}from"node:path";import{existsSync}from"node:fs";import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{
|
|
1
|
+
import{ASH_HEALTH_ROUTE_PATH}from"#protocol/routes.js";import{join,resolve}from"node:path";import{spawn}from"node:child_process";import{existsSync}from"node:fs";import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{prewarmBuiltAppSandboxes}from"#execution/sandbox/prewarm.js";import{createServer}from"node:net";import{setTimeout}from"node:timers/promises";const HEALTH_TIMEOUT_MS=6e4,LOCAL_SERVER_URL_PATTERN=/https?:\/\/(?:\[[^\]\s]+\]|[^\s/:[\]]+)(?::\d+)?/,WILDCARD_LISTEN_HOSTNAMES=new Set([`[::]`,`::`,`0.0.0.0`]);function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function isAddressInUseError(e){return e instanceof Error&&`code`in e&&e.code===`EADDRINUSE`}function resolveOutputServerEntry(e){return join(resolve(e),`.output`,`server`,`index.mjs`)}function readEnvironmentPort(){let e=process.env.PORT;if(e===void 0||e.trim()===``)return;let t=Number(e);if(!Number.isInteger(t)||t<0||t>65535)throw Error(`Invalid PORT environment variable "${e}". Expected an integer between 0 and 65535.`);return t}function normalizeServerClientUrl(e){let t=new URL(e);return WILDCARD_LISTEN_HOSTNAMES.has(t.hostname)&&(t.hostname=`127.0.0.1`),t.toString()}function formatClientHost(e){return WILDCARD_LISTEN_HOSTNAMES.has(e)?`127.0.0.1`:e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function createKnownPortUrl(e){return`http://${formatClientHost(e.host)}:${String(e.port)}/`}async function resolveListenPort(e){if(e.port!==0)return e.port;let t=createServer();return await new Promise((n,r)=>{t.once(`error`,r),t.listen(0,e.host,()=>{let e=t.address();t.close(t=>{if(t){r(t);return}if(e===null||typeof e==`string`){r(Error(`Failed to resolve an available port for ash start.`));return}n(e.port)})})})}function parseServerUrlFromOutput(e){let t=LOCAL_SERVER_URL_PATTERN.exec(e);if(t!==null)return normalizeServerClientUrl(t[0])}async function waitForHealth(t){let{child:n,url:r}=t,i=new URL(ASH_HEALTH_ROUTE_PATH,r).toString(),a=Date.now()+HEALTH_TIMEOUT_MS;for(;Date.now()<a;){let e=t.getStartError();if(e!==void 0)throw e;if(n.exitCode!==null||n.signalCode!==null)throw Error(`Built server process exited (code=${String(n.exitCode)}, signal=${String(n.signalCode)}) before becoming healthy.`);try{if((await fetch(i,{signal:AbortSignal.timeout(2e3)})).ok)return new URL(r).toString()}catch(e){if(isAddressInUseError(e))throw e}await setTimeout(250)}throw Error(`Built server did not become healthy within ${HEALTH_TIMEOUT_MS/1e3}s at ${i}.`)}async function waitForReady(e){let t=Date.now()+HEALTH_TIMEOUT_MS;for(;Date.now()<t;){let t=e.getStartError();if(t!==void 0)throw t;let n=parseServerUrlFromOutput(e.getOutput())??e.knownUrl;if(n!==void 0)return await waitForHealth({child:e.child,getStartError:e.getStartError,url:n});if(e.child.exitCode!==null||e.child.signalCode!==null)throw Error(`Built server process exited (code=${String(e.child.exitCode)}, signal=${String(e.child.signalCode)}) before printing its URL.`);await setTimeout(250)}throw Error([`Built server did not become ready within ${HEALTH_TIMEOUT_MS/1e3}s.`,`Output:`,e.getOutput()].join(`
|
|
2
2
|
`))}async function terminate(e){e.exitCode!==null||e.killed||(e.kill(`SIGTERM`),await Promise.race([once(e,`exit`),setTimeout(5e3).then(()=>`timeout`)])===`timeout`&&e.exitCode===null&&(e.kill(`SIGKILL`),await once(e,`exit`)),e.stdout?.destroy(),e.stderr?.destroy())}function once(e,t){return new Promise(n=>{e.once(t,()=>n())})}async function startProductionServer(e,t={}){let o=resolve(e),s=resolveOutputServerEntry(o);if(!existsSync(s))throw Error(`Missing Ash build output at ${s}. Run "ash build" before "ash start".`);loadDevelopmentEnvironmentFiles(o),await prewarmBuiltAppSandboxes({appRoot:o,log:e=>console.log(e)});let c=t.host??`0.0.0.0`,l=await resolveListenPort({host:c,port:t.port??readEnvironmentPort()??3e3}),u=createKnownPortUrl({host:c,port:l}),d=``,f=!1,p,m=spawn(process.execPath,[s],{cwd:o,env:{...process.env,HOST:c,NITRO_HOST:c,NITRO_PORT:String(l),PORT:String(l)},stdio:[`ignore`,`pipe`,`pipe`]});m.stdout?.on(`data`,e=>{d+=e.toString(`utf8`),process.stdout.write(e)}),m.stderr?.on(`data`,e=>{d+=e.toString(`utf8`),process.stderr.write(e)});let h=new Promise((e,t)=>{m.once(`error`,e=>{p=e,t(e)}),m.once(`exit`,(n,r)=>{if(f||n===0){e();return}t(Error([`Built server process exited unexpectedly (code=${String(n)}, signal=${String(r)}).`,d].join(`
|
|
3
3
|
`)))})});h.catch(()=>void 0);try{return{async close(){f=!0,await terminate(m)},url:await waitForReady({child:m,getStartError:()=>p,getOutput:()=>d,knownUrl:u}),async wait(){await h}}}catch(e){throw f=!0,await terminate(m),isRecord(e)&&e.name===`AbortError`?Error(`Timed out waiting for built Ash server to respond.`,{cause:e}):e}}export{startProductionServer};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import{wrapAnsi}from"../../../../../fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js";import{require_src}from"../../../../../sisteransi@1.0.5/node_modules/sisteransi/src/index.js";import"node:util";import{stdin,stdout}from"node:process";import"node:readline";import E from"node:readline";import"node:tty";var import_src=require_src();function f(e,t,n){if(!n.some(e=>!e.disabled))return e;let r=e+t,i=Math.max(n.length-1,0),a=r<0?i:r>i?0:r;return n[a].disabled?f(a,t<0?-1:1,n):a}const h={actions:new Set([`up`,`down`,`left`,`right`,`space`,`enter`,`cancel`]),aliases:new Map([[`k`,`up`],[`j`,`down`],[`h`,`left`],[`l`,`right`],[``,`cancel`],[`escape`,`cancel`]]),messages:{cancel:`Canceled`,error:`Something went wrong`},withGuide:!0,date:{monthNames:[`January`,`February`,`March`,`April`,`May`,`June`,`July`,`August`,`September`,`October`,`November`,`December`],messages:{required:`Please enter a valid date`,invalidMonth:`There are only 12 months in a year`,invalidDay:(e,t)=>`There are only ${e} days in ${t}`,afterMin:e=>`Date must be on or after ${e.toISOString().slice(0,10)}`,beforeMax:e=>`Date must be on or before ${e.toISOString().slice(0,10)}`}}};function C(e,t){if(typeof e==`string`)return h.aliases.get(e)===t;for(let n of e)if(n!==void 0&&C(n,t))return!0;return!1}function z(e,t){if(e===t)return;let n=e.split(`
|
|
2
|
+
`),r=t.split(`
|
|
3
|
+
`),i=Math.max(n.length,r.length),a=[];for(let e=0;e<i;e++)n[e]!==r[e]&&a.push(e);return{lines:a,numLinesBefore:n.length,numLinesAfter:r.length,numLines:i}}globalThis.process.platform.startsWith(`win`);const k=Symbol(`clack:cancel`);function q(e){return e===k}function w(e,t){let n=e;n.isTTY&&n.setRawMode(t)}const A=e=>`columns`in e&&typeof e.columns==`number`?e.columns:80,L=e=>`rows`in e&&typeof e.rows==`number`?e.rows:20;function W(t,n,i,a=i,o=i,s){return wrapAnsi(n,A(t??stdout)-i.length,{hard:!0,trim:!1}).split(`
|
|
4
|
+
`).map((e,t,n)=>{let r=s?s(e,t):e;return t===0?`${a}${r}`:t===n.length-1?`${o}${r}`:`${i}${r}`}).join(`
|
|
5
|
+
`)}let m=class{input;output;_abortSignal;rl;opts;_render;_track=!1;_prevFrame=``;_subscribers=new Map;_cursor=0;state=`initial`;error=``;value;userInput=``;constructor(e,t=!0){let{input:i=stdin,output:a=stdout,render:o,signal:s,...c}=e;this.opts=c,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=o.bind(this),this._track=t,this._abortSignal=s,this.input=i,this.output=a}unsubscribe(){this._subscribers.clear()}setSubscriber(e,t){let n=this._subscribers.get(e)??[];n.push(t),this._subscribers.set(e,n)}on(e,t){this.setSubscriber(e,{cb:t})}once(e,t){this.setSubscriber(e,{cb:t,once:!0})}emit(e,...t){let n=this._subscribers.get(e)??[],r=[];for(let e of n)e.cb(...t),e.once&&r.push(()=>n.splice(n.indexOf(e),1));for(let e of r)e()}prompt(){return new Promise(e=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state=`cancel`,this.close(),e(k);this._abortSignal.addEventListener(`abort`,()=>{this.state=`cancel`,this.close()},{once:!0})}this.rl=E.createInterface({input:this.input,tabSize:2,prompt:``,escapeCodeTimeout:50,terminal:!0}),this.rl.prompt(),this.opts.initialUserInput!==void 0&&this._setUserInput(this.opts.initialUserInput,!0),this.input.on(`keypress`,this.onKeypress),w(this.input,!0),this.output.on(`resize`,this.render),this.render(),this.once(`submit`,()=>{this.output.write(import_src.cursor.show),this.output.off(`resize`,this.render),w(this.input,!1),e(this.value)}),this.once(`cancel`,()=>{this.output.write(import_src.cursor.show),this.output.off(`resize`,this.render),w(this.input,!1),e(k)})})}_isActionKey(e,t){return e===` `}_shouldSubmit(e,t){return!0}_setValue(e){this.value=e,this.emit(`value`,this.value)}_setUserInput(e,t){this.userInput=e??``,this.emit(`userInput`,this.userInput),t&&this._track&&this.rl&&(this.rl.write(this.userInput),this._cursor=this.rl.cursor)}_clearUserInput(){this.rl?.write(null,{ctrl:!0,name:`u`}),this._setUserInput(``)}onKeypress(e,t){if(this._track&&t.name!==`return`&&(t.name&&this._isActionKey(e,t)&&this.rl?.write(null,{ctrl:!0,name:`h`}),this._cursor=this.rl?.cursor??0,this._setUserInput(this.rl?.line)),this.state===`error`&&(this.state=`active`),t?.name&&(!this._track&&h.aliases.has(t.name)&&this.emit(`cursor`,h.aliases.get(t.name)),h.actions.has(t.name)&&this.emit(`cursor`,t.name)),e&&(e.toLowerCase()===`y`||e.toLowerCase()===`n`)&&this.emit(`confirm`,e.toLowerCase()===`y`),this.emit(`key`,e?.toLowerCase(),t),t?.name===`return`&&this._shouldSubmit(e,t)){if(this.opts.validate){let e=this.opts.validate(this.value);e&&(this.error=e instanceof Error?e.message:e,this.state=`error`,this.rl?.write(this.userInput))}this.state!==`error`&&(this.state=`submit`)}C([e,t?.name,t?.sequence],`cancel`)&&(this.state=`cancel`),(this.state===`submit`||this.state===`cancel`)&&this.emit(`finalize`),this.render(),(this.state===`submit`||this.state===`cancel`)&&this.close()}close(){this.input.unpipe(),this.input.removeListener(`keypress`,this.onKeypress),this.output.write(`
|
|
6
|
+
`),w(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){let t=wrapAnsi(this._prevFrame,process.stdout.columns,{hard:!0,trim:!1}).split(`
|
|
7
|
+
`).length-1;this.output.write(import_src.cursor.move(-999,t*-1))}render(){let t=wrapAnsi(this._render(this)??``,process.stdout.columns,{hard:!0,trim:!1});if(t!==this._prevFrame){if(this.state===`initial`)this.output.write(import_src.cursor.hide);else{let e=z(this._prevFrame,t),n=L(this.output);if(this.restoreCursor(),e){let r=Math.max(0,e.numLinesAfter-n),i=Math.max(0,e.numLinesBefore-n),o=e.lines.find(e=>e>=r);if(o===void 0){this._prevFrame=t;return}if(e.lines.length===1){this.output.write(import_src.cursor.move(0,o-i)),this.output.write(import_src.erase.lines(1));let e=t.split(`
|
|
8
|
+
`);this.output.write(e[o]),this._prevFrame=t,this.output.write(import_src.cursor.move(0,e.length-o-1));return}else if(e.lines.length>1){if(r<i)o=r;else{let e=o-i;e>0&&this.output.write(import_src.cursor.move(0,e))}this.output.write(import_src.erase.down());let e=t.split(`
|
|
9
|
+
`).slice(o);this.output.write(e.join(`
|
|
10
|
+
`)),this._prevFrame=t;return}}this.output.write(import_src.erase.down())}this.output.write(t),this.state===`initial`&&(this.state=`active`),this._prevFrame=t}}},nt=class extends m{options;cursor=0;get _value(){return this.options[this.cursor].value}get _enabledOptions(){return this.options.filter(e=>e.disabled!==!0)}toggleAll(){let e=this._enabledOptions,t=this.value!==void 0&&this.value.length===e.length;this.value=t?[]:e.map(e=>e.value)}toggleInvert(){let e=this.value;if(!e)return;let t=this._enabledOptions.filter(t=>!e.includes(t.value));this.value=t.map(e=>e.value)}toggleValue(){this.value===void 0&&(this.value=[]);let e=this.value.includes(this._value);this.value=e?this.value.filter(e=>e!==this._value):[...this.value,this._value]}constructor(e){super(e,!1),this.options=e.options,this.value=[...e.initialValues??[]];let t=Math.max(this.options.findIndex(({value:t})=>t===e.cursorAt),0);this.cursor=this.options[t].disabled?f(t,1,this.options):t,this.on(`key`,e=>{e===`a`&&this.toggleAll(),e===`i`&&this.toggleInvert()}),this.on(`cursor`,e=>{switch(e){case`left`:case`up`:this.cursor=f(this.cursor,-1,this.options);break;case`down`:case`right`:this.cursor=f(this.cursor,1,this.options);break;case`space`:this.toggleValue();break}})}};var ut=class extends m{options;cursor=0;get _selectedValue(){return this.options[this.cursor]}changeValue(){this.value=this._selectedValue.value}constructor(e){super(e,!1),this.options=e.options;let t=this.options.findIndex(({value:t})=>t===e.initialValue),n=t===-1?0:t;this.cursor=this.options[n].disabled?f(n,1,this.options):n,this.changeValue(),this.on(`cursor`,e=>{switch(e){case`left`:case`up`:this.cursor=f(this.cursor,-1,this.options);break;case`down`:case`right`:this.cursor=f(this.cursor,1,this.options);break}this.changeValue()})}};export{W,nt,q,ut};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getCodePointsLength,isFullWidth,isWideNotCJKTNotEmoji}from"./utils.js";const ANSI_RE=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,CONTROL_RE=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,CJKT_WIDE_RE=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy,TAB_RE=/\t{1,1000}/y,EMOJI_RE=/[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy,LATIN_RE=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,MODIFIER_RE=/\p{M}+/gu,NO_TRUNCATION={limit:1/0,ellipsis:``},getStringTruncatedWidth=(i,a={},o={})=>{let s=a.limit??1/0,c=a.ellipsis??``,l=a?.ellipsisWidth??(c?getStringTruncatedWidth(c,NO_TRUNCATION,o).width:0),u=o.controlWidth??0,d=o.tabWidth??8,f=o.emojiWidth??2,p=o.regularWidth??1,m=o.wideWidth??2,h=[[LATIN_RE,p],[ANSI_RE,0],[CONTROL_RE,u],[TAB_RE,d],[EMOJI_RE,f],[CJKT_WIDE_RE,m]],g=0,_=0,v=i.length,y=0,b=!1,x=v,S=Math.max(0,s-l),C=0,w=0,T=0,E=0;outer:for(;;){if(w>C||_>=v&&_>g){let e=i.slice(C,w)||i.slice(g,_);y=0;for(let r of e.replaceAll(MODIFIER_RE,``)){let e=r.codePointAt(0)||0;if(E=isFullWidth(e)?2:isWideNotCJKTNotEmoji(e)?m:p,T+E>S&&(x=Math.min(x,Math.max(C,g)+y)),T+E>s){b=!0;break outer}y+=r.length,T+=E}C=w=0}if(_>=v)break outer;for(let t=0,n=h.length;t<n;t++){let[n,r]=h[t];if(n.lastIndex=_,n.test(i)){if(y=n===CJKT_WIDE_RE?getCodePointsLength(i.slice(_,n.lastIndex)):n===EMOJI_RE?1:n.lastIndex-_,E=y*r,T+E>S&&(x=Math.min(x,_+Math.floor((S-T)/r))),T+E>s){b=!0;break outer}T+=E,C=g,w=_,_=g=n.lastIndex;continue outer}}_+=1}return{width:b?S:T,index:b?x:v,truncated:b,ellipsed:b&&s>=l}};export{getStringTruncatedWidth as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const getCodePointsLength=(()=>{let e=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return t=>{let n=0;for(e.lastIndex=0;e.test(t);)n+=1;return t.length-n}})(),isFullWidth=e=>e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510,isWideNotCJKTNotEmoji=e=>e===8987||e===9001||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e>=131072&&e<=196605||e>=196608&&e<=262141;export{getCodePointsLength,isFullWidth,isWideNotCJKTNotEmoji};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import getStringTruncatedWidth from"../../../../fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js";const NO_TRUNCATION={limit:1/0,ellipsis:``,ellipsisWidth:0},fastStringWidth=(e,t={})=>getStringTruncatedWidth(e,NO_TRUNCATION,t).width;export{fastStringWidth as default};
|
package/dist/src/node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import fastStringWidth from"../../../../fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js";const ANSI_ESCAPE_LINK=`]8;;`,GROUP_REGEX=RegExp(`(?:\\[(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*))`,`y`),getClosingCode=e=>{if(e>=30&&e<=37||e>=90&&e<=97)return 39;if(e>=40&&e<=47||e>=100&&e<=107)return 49;if(e===1||e===2)return 22;if(e===3)return 23;if(e===4)return 24;if(e===7)return 27;if(e===8)return 28;if(e===9)return 29;if(e===0)return 0},wrapAnsiCode=e=>`[${e}m`,wrapAnsiHyperlink=e=>`${ANSI_ESCAPE_LINK}${e}`,wrapWord=(n,r,i)=>{let a=r[Symbol.iterator](),o=!1,s=!1,c=n.at(-1),l=c===void 0?0:fastStringWidth(c),u=a.next(),d=a.next(),f=0;for(;!u.done;){let c=u.value,p=fastStringWidth(c);l+p<=i?n[n.length-1]+=c:(n.push(c),l=0),(c===`\x1B`||c===``)&&(o=!0,s=r.startsWith(ANSI_ESCAPE_LINK,f+1)),o?s?c===`\x07`&&(o=!1,s=!1):c===`m`&&(o=!1):(l+=p,l===i&&!d.done&&(n.push(``),l=0)),u=d,d=a.next(),f+=c.length}c=n.at(-1),!l&&c!==void 0&&c.length&&n.length>1&&(n[n.length-2]+=n.pop())},stringVisibleTrimSpacesRight=t=>{let n=t.split(` `),r=n.length;for(;r&&!fastStringWidth(n[r-1]);)r--;return r===n.length?t:n.slice(0,r).join(` `)+n.slice(r).join(``)},exec=(t,r,i={})=>{if(i.trim!==!1&&t.trim()===``)return``;let a=``,o,s,c=t.split(` `),l=[``],u=0;for(let t=0;t<c.length;t++){let n=c[t];if(i.trim!==!1){let t=l.at(-1)??``,n=t.trimStart();t.length!==n.length&&(l[l.length-1]=n,u=fastStringWidth(n))}t!==0&&(u>=r&&(i.wordWrap===!1||i.trim===!1)&&(l.push(``),u=0),(u||i.trim===!1)&&(l[l.length-1]+=` `,u++));let a=fastStringWidth(n);if(i.hard&&a>r){let t=r-u,i=1+Math.floor((a-t-1)/r);Math.floor((a-1)/r)<i&&l.push(``),wrapWord(l,n,r),u=fastStringWidth(l.at(-1)??``);continue}if(u+a>r&&u&&a){if(i.wordWrap===!1&&u<r){wrapWord(l,n,r),u=fastStringWidth(l.at(-1)??``);continue}l.push(``),u=0}if(u+a>r&&i.wordWrap===!1){wrapWord(l,n,r),u=fastStringWidth(l.at(-1)??``);continue}l[l.length-1]+=n,u+=a}i.trim!==!1&&(l=l.map(e=>stringVisibleTrimSpacesRight(e)));let d=l.join(`
|
|
2
|
+
`),f=!1;for(let e=0;e<d.length;e++){let t=d[e];if(a+=t,f)f=!1;else if(f=t>=`\ud800`&&t<=`\udbff`,f)continue;if(t===`\x1B`||t===``){GROUP_REGEX.lastIndex=e+1;let t=GROUP_REGEX.exec(d)?.groups;if(t?.code!==void 0){let e=Number.parseFloat(t.code);o=e===39?void 0:e}else t?.uri!==void 0&&(s=t.uri.length===0?void 0:t.uri)}if(d[e+1]===`
|
|
3
|
+
`){s&&(a+=wrapAnsiHyperlink(``));let e=o?getClosingCode(o):void 0;o&&e&&(a+=wrapAnsiCode(e))}else t===`
|
|
4
|
+
`&&(o&&getClosingCode(o)&&(a+=wrapAnsiCode(o)),s&&(a+=wrapAnsiHyperlink(s)))}return a},CRLF_OR_LF=/\r?\n/;function wrapAnsi(e,t,n){return String(e).normalize().split(CRLF_OR_LF).map(e=>exec(e,t,n)).join(`
|
|
5
|
+
`)}export{wrapAnsi};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{__commonJSMin}from"../../../../../_virtual/_rolldown/runtime.js";var require_picocolors=__commonJSMin(((e,t)=>{let n=process||{},r=n.argv||[],i=n.env||{},a=!(i.NO_COLOR||r.includes(`--no-color`))&&(!!i.FORCE_COLOR||r.includes(`--color`)||n.platform===`win32`||(n.stdout||{}).isTTY&&i.TERM!==`dumb`||!!i.CI),formatter=(e,t,n=e)=>r=>{let i=``+r,a=i.indexOf(t,e.length);return~a?e+replaceClose(i,t,n,a)+t:e+i+t},replaceClose=(e,t,n,r)=>{let i=``,a=0;do i+=e.substring(a,r)+n,a=r+t.length,r=e.indexOf(t,a);while(~r);return i+e.substring(a)},createColors=(e=a)=>{let t=e?formatter:()=>String;return{isColorSupported:e,reset:t(`\x1B[0m`,`\x1B[0m`),bold:t(`\x1B[1m`,`\x1B[22m`,`\x1B[22m\x1B[1m`),dim:t(`\x1B[2m`,`\x1B[22m`,`\x1B[22m\x1B[2m`),italic:t(`\x1B[3m`,`\x1B[23m`),underline:t(`\x1B[4m`,`\x1B[24m`),inverse:t(`\x1B[7m`,`\x1B[27m`),hidden:t(`\x1B[8m`,`\x1B[28m`),strikethrough:t(`\x1B[9m`,`\x1B[29m`),black:t(`\x1B[30m`,`\x1B[39m`),red:t(`\x1B[31m`,`\x1B[39m`),green:t(`\x1B[32m`,`\x1B[39m`),yellow:t(`\x1B[33m`,`\x1B[39m`),blue:t(`\x1B[34m`,`\x1B[39m`),magenta:t(`\x1B[35m`,`\x1B[39m`),cyan:t(`\x1B[36m`,`\x1B[39m`),white:t(`\x1B[37m`,`\x1B[39m`),gray:t(`\x1B[90m`,`\x1B[39m`),bgBlack:t(`\x1B[40m`,`\x1B[49m`),bgRed:t(`\x1B[41m`,`\x1B[49m`),bgGreen:t(`\x1B[42m`,`\x1B[49m`),bgYellow:t(`\x1B[43m`,`\x1B[49m`),bgBlue:t(`\x1B[44m`,`\x1B[49m`),bgMagenta:t(`\x1B[45m`,`\x1B[49m`),bgCyan:t(`\x1B[46m`,`\x1B[49m`),bgWhite:t(`\x1B[47m`,`\x1B[49m`),blackBright:t(`\x1B[90m`,`\x1B[39m`),redBright:t(`\x1B[91m`,`\x1B[39m`),greenBright:t(`\x1B[92m`,`\x1B[39m`),yellowBright:t(`\x1B[93m`,`\x1B[39m`),blueBright:t(`\x1B[94m`,`\x1B[39m`),magentaBright:t(`\x1B[95m`,`\x1B[39m`),cyanBright:t(`\x1B[96m`,`\x1B[39m`),whiteBright:t(`\x1B[97m`,`\x1B[39m`),bgBlackBright:t(`\x1B[100m`,`\x1B[49m`),bgRedBright:t(`\x1B[101m`,`\x1B[49m`),bgGreenBright:t(`\x1B[102m`,`\x1B[49m`),bgYellowBright:t(`\x1B[103m`,`\x1B[49m`),bgBlueBright:t(`\x1B[104m`,`\x1B[49m`),bgMagentaBright:t(`\x1B[105m`,`\x1B[49m`),bgCyanBright:t(`\x1B[106m`,`\x1B[49m`),bgWhiteBright:t(`\x1B[107m`,`\x1B[49m`)}};t.exports=createColors(),t.exports.createColors=createColors}));export default require_picocolors();export{require_picocolors};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{__commonJSMin}from"../../../../../../_virtual/_rolldown/runtime.js";var require_src=__commonJSMin(((e,t)=>{let n={to(e,t){return t?`[${t+1};${e+1}H`:`[${e+1}G`},move(e,t){let n=``;return e<0?n+=`[${-e}D`:e>0&&(n+=`[${e}C`),t<0?n+=`[${-t}A`:t>0&&(n+=`[${t}B`),n},up:(e=1)=>`[${e}A`,down:(e=1)=>`[${e}B`,forward:(e=1)=>`[${e}C`,backward:(e=1)=>`[${e}D`,nextLine:(e=1)=>`\x1B[E`.repeat(e),prevLine:(e=1)=>`\x1B[F`.repeat(e),left:`\x1B[G`,hide:`\x1B[?25l`,show:`\x1B[?25h`,save:`\x1B7`,restore:`\x1B8`};t.exports={cursor:n,scroll:{up:(e=1)=>`\x1B[S`.repeat(e),down:(e=1)=>`\x1B[T`.repeat(e)},erase:{screen:`\x1B[2J`,up:(e=1)=>`\x1B[1J`.repeat(e),down:(e=1)=>`\x1B[J`.repeat(e),line:`\x1B[2K`,lineEnd:`\x1B[K`,lineStart:`\x1B[1K`,lines(e){let t=``;for(let r=0;r<e;r++)t+=this.line+(r<e-1?n.up():``);return e&&(t+=n.left),t}},beep:`\x07`}}));export default require_src();export{require_src};
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"./files.js";import"./project.js";import{patchPackageJson}from"./package-json.js";import{basename,join,resolve}from"node:path";import{readFile,readdir}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/ash/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent
|
|
1
|
+
import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{pathExists,writeTextFile}from"./files.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_ASH_RELEASE_AGE_EXCLUSION=` - experimental-ash`,WEB_SHARP_BUILD_POLICY=` sharp: false`,WEB_VERCEL_JSON_PATH=`vercel.json`,WEB_VERCEL_JSON_SCHEMA=`https://openapi.vercel.sh/vercel.json`,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.34.0`,aiPackageVersion:e?.aiPackageVersion??`7.0.0-canary.154`,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},s=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts;return await patchPackageJson(e,{dependencies:r,devDependencies:i,scripts:s}),[{path:e,dependencies:Object.keys(r),devDependencies:Object.keys(i),scripts:Object.keys(s)}]}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({
|
|
5
5
|
credentials: connectSlackCredentials("slack/${e}"),
|
|
6
6
|
});
|
|
7
|
-
`}function
|
|
7
|
+
`}function renderWebAppTemplate(e,t){return e.replaceAll(`__ASH_INIT_APP_NAME__`,t)}function findYamlBlockEnd(e,t){let n=t+1;for(;n<e.length;){let t=e[n]??``;if(t.length>0&&!t.startsWith(` `)&&!t.startsWith(` `))break;n+=1}return n}function withSharpBuildPolicy(e){let t=e.endsWith(`
|
|
8
|
+
`)?e:`${e}\n`,n=t.split(`
|
|
9
|
+
`),r=n.findIndex(e=>e===`allowBuilds:`);if(r<0)return`${t.trim().length===0?``:`${t}\n`}allowBuilds:\n${WEB_SHARP_BUILD_POLICY}\n`;let i=findYamlBlockEnd(n,r);if(n.slice(r+1,i).some(e=>/^\s+sharp:/.test(e)))return e;let a=i;for(;a>r+1&&n[a-1]===``;)--a;return n.splice(a,0,WEB_SHARP_BUILD_POLICY),n.join(`
|
|
10
|
+
`)}function withExperimentalAshReleaseAgeExclusion(e){let t=e.endsWith(`
|
|
11
|
+
`)?e:`${e}\n`,n=t.split(`
|
|
12
|
+
`),r=n.findIndex(e=>e===`minimumReleaseAgeExclude:`);if(r<0)return`${t.trim().length===0?``:`${t}\n`}minimumReleaseAgeExclude:\n${WEB_ASH_RELEASE_AGE_EXCLUSION}\n`;let i=findYamlBlockEnd(n,r);if(n.slice(r+1,i).some(e=>e.trim()===`- experimental-ash`))return e;let a=i;for(;a>r+1&&n[a-1]===``;)--a;return n.splice(a,0,WEB_ASH_RELEASE_AGE_EXCLUSION),n.join(`
|
|
13
|
+
`)}async function ensureWebPnpmWorkspacePolicy(e,t){if(!await pathExists(e))return await writeTextFile(e,t,{force:!0}),`written`;let i=await readFile(e,`utf8`),a=withExperimentalAshReleaseAgeExclusion(withSharpBuildPolicy(i));return a===i?`skipped`:(await writeFile(e,a,`utf8`),`written`)}function withWebVercelServices(e){let t=JSON.parse(e);if(!isJsonObject(t))throw Error(`${WEB_VERCEL_JSON_PATH} must contain a JSON object.`);let n=t.experimentalServices;if(n!==void 0&&!isJsonObject(n))throw Error(`${WEB_VERCEL_JSON_PATH} experimentalServices must contain a JSON object.`);let r={...t,$schema:typeof t.$schema==`string`?t.$schema:WEB_VERCEL_JSON_SCHEMA,experimentalServices:{...n,web:n?.web??WEB_DEFAULT_VERCEL_SERVICES.web,ash:n?.ash??WEB_DEFAULT_VERCEL_SERVICES.ash}};return JSON.stringify(t)===JSON.stringify(r)?e:`${JSON.stringify(r,null,2)}\n`}async function ensureWebVercelServices(e){if(!await pathExists(e))return await writeTextFile(e,`${JSON.stringify({$schema:WEB_VERCEL_JSON_SCHEMA,experimentalServices:WEB_DEFAULT_VERCEL_SERVICES},null,2)}\n`,{force:!0}),`written`;let t=await readFile(e,`utf8`),i=withWebVercelServices(t);return i===t?`skipped`:(await writeFile(e,i,`utf8`),`written`)}function assertStampedVersion(e,t){if(t.startsWith(`__`))throw Error(`Channel scaffold received unstamped version token (${e}=${t}). Build @vercel/ash-scaffold before using its dist entrypoint.`)}async function ensureChannel(e){switch(e.kind){case`slack`:return ensureSlackChannel({...e,kind:`slack`});case`web`:return ensureWebChannel({...e,kind:`web`})}}async function ensureWebChannel(e){let t=join(e.projectRoot,`package.json`),a=await pathExists(join(e.projectRoot,`app/page.tsx`));if(!e.force&&await hasPackageDependency(t,`next`))return{kind:`web`,action:`skipped`,skipReason:`nextjs-project`,filesWritten:[],filesSkipped:[t],packageJsonUpdated:[]};let o=await patchWebPackageJson(t,resolveWebPackageVersions(e.webPackageVersions)),c=[],l=[],u=basename(resolve(e.projectRoot)),d=join(e.projectRoot,WEB_VERCEL_JSON_PATH);await ensureWebVercelServices(d)===`written`?c.push(d):l.push(d);let f=join(e.projectRoot,`pnpm-workspace.yaml`);await ensureWebPnpmWorkspacePolicy(f,`minimumReleaseAgeExclude:
|
|
14
|
+
- experimental-ash
|
|
15
|
+
allowBuilds:
|
|
16
|
+
sharp: false
|
|
17
|
+
`)===`written`?c.push(f):l.push(f);for(let[t,a]of Object.entries(WEB_APP_TEMPLATE_FILES)){let i=join(e.projectRoot,t);if(t===`agent/channels/ash.ts`&&!e.force&&await pathExists(i)){l.push(i);continue}await writeTextFile(i,renderWebAppTemplate(a,u),{force:!0}),c.push(i)}return{kind:`web`,action:a?`overwritten`:`created`,filesWritten:c,filesSkipped:l,packageJsonUpdated:o}}async function ensureSlackChannel(e){let t=join(e.projectRoot,`agent/channels/slack.ts`),i=await pathExists(t);if(!e.force&&i)return{kind:`slack`,action:`skipped`,filesWritten:[],filesSkipped:[t],packageJsonUpdated:[]};let a=e.connectPackageVersion??`0.0.6-alpha.1`;assertStampedVersion(`connectPackageVersion`,a);let o=await ensurePackageDependency(join(e.projectRoot,`package.json`),`@vercel/connect`,a),s=e.slackConnectorSlug??await deriveSlackConnectorSlug(e.projectRoot);return await writeTextFile(t,buildSlackTemplate(s),{force:e.force}),{kind:`slack`,action:i?`overwritten`:`created`,filesWritten:[t],filesSkipped:[],packageJsonUpdated:o,slackConnectorSlug:s}}async function listAuthoredChannels(n){let r=join(n,`agent/channels`),i;try{i=await readdir(r,{withFileTypes:!0})}catch(e){if(e.code===`ENOENT`)return[];throw e}let a=[];for(let n of i){if(n.isFile()){let t=getSupportedModuleBaseName(n.name);t!==null&&a.push(t);continue}if(n.isDirectory())try{(await readdir(join(r,n.name))).some(e=>matchesSupportedModuleBaseName(e,`connection`))&&a.push(n.name)}catch{}}return a.sort()}export{DEFAULT_SLACK_CONNECTOR_SLUG,SLACK_CHANNEL_DEFAULT_ROUTE,deriveSlackConnectorSlug,ensureChannel,listAuthoredChannels,normalizeSlackConnectorSlug};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{__toESM}from"../../../../_virtual/_rolldown/runtime.js";import{nt,q,ut}from"../../../../node_modules/.pnpm/@clack_core@1.3.1/node_modules/@clack/core/dist/index.js";import{formatPromptCancellation,formatPromptOpener,formatPromptOutro,renderMultiselectPrompt,renderSelectPrompt}from"./prompt-ui.js";import{createRailLog}from"./rail-log.js";import{require_picocolors}from"../../../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";var import_picocolors=__toESM(require_picocolors(),1),ChannelAddCancelledError=class extends Error{constructor(){super(`Channel setup cancelled.`),this.name=`ChannelAddCancelledError`}};function toPromptState(e){return e}function guardCancel(e){if(q(e))throw process.stdout.write(formatPromptCancellation(`Channel setup cancelled.`,import_picocolors.default)),new ChannelAddCancelledError;return e}function selectPrompt(e){let t=e.options.findIndex(e=>!e.disabled);if(t<0)return Promise.reject(Error(`Every select option is disabled.`));let n=t;if(e.initialValue!==void 0){let t=e.options.findIndex(t=>!t.disabled&&t.value===e.initialValue);t>=0&&(n=t)}let i=new ut({options:e.options,render(){return renderSelectPrompt({colors:import_picocolors.default,cursor:this.cursor,leadingRail:`green`,message:e.message,options:this.options,state:toPromptState(this.state)})}});return i.cursor=n,i.prompt()}function multiselectPrompt(e){if(e.options.every(e=>e.disabled))return process.stdout.write(renderMultiselectPrompt({colors:import_picocolors.default,cursor:0,leadingRail:`green`,message:e.message,options:e.options,selectedValues:[],state:`active`})),Promise.resolve([]);let n,r=new nt({options:e.options,required:e.required??!1,initialValues:[],render(){if(!n)return``;let t=n;return renderMultiselectPrompt({colors:import_picocolors.default,cursor:t.cursor,error:t.error,leadingRail:`green`,message:e.message,options:t.options,selectedValues:t.value??[],state:toPromptState(t.state)})}});return n=r,r.prompt()}function createChannelAddPrompter(){let e=createRailLog({colors:import_picocolors.default,output:process.stdout});return{intro(t,n=`Vercel Agent Framework: like Next.js, but for agents.`){e.settle(),process.stdout.write(formatPromptOpener(t,n,import_picocolors.default))},outro(t){e.settle(),process.stdout.write(formatPromptOutro(t,import_picocolors.default))},async multiselect(t){return e.settle(),guardCancel(await multiselectPrompt(t))},async select(t){return e.settle(),guardCancel(await selectPrompt(t))},log:e}}export{ChannelAddCancelledError,createChannelAddPrompter};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function createPromptCommandOutput(e){return({text:t})=>e.commandOutput(t)}export{createPromptCommandOutput};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./command-output.js";import"./prompt-ui.js";import"./rail-log.js";import"./channel-add-prompter.js";export{};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{W}from"../../../../node_modules/.pnpm/@clack_core@1.3.1/node_modules/@clack/core/dist/index.js";function bulletFor(e,t){switch(e){case`initial`:case`active`:return t.green(`△`);case`submit`:return t.green(`▲`);case`cancel`:return t.gray(`▲`);case`error`:return t.red(`▲`)}}function railFor(e,t){switch(e){case`initial`:case`active`:return t.white(`│`);case`submit`:return t.green(`│`);case`cancel`:return t.gray(`│`);case`error`:return t.red(`│`)}}function cornerFor(e,t){switch(e){case`initial`:case`active`:return t.white(`└`);case`submit`:return t.green(`└`);case`cancel`:return t.gray(`└`);case`error`:return t.red(`└`)}}function formatPromptHeader(e,t,n){return`${n.leadingRail===`green`?n.colors.green(`│`):n.colors.white(`│`)}\n${bulletFor(e,n.colors)} ${t}\n`}function formatPromptOpener(e,t,n){return`\n${n.bold(n.white(`▲`))} ${n.bold(e)}\n ${n.dim(t)}\n${n.white(`│`)}\n`}function formatPromptOutro(e,t){let n=e.replace(/\n/g,`
|
|
2
|
+
`);return`${t.green(`│`)}\n${t.green(`●`)} ${n}\n`}function formatPromptCancellation(e,t){let n=e.replace(/\n/g,`
|
|
3
|
+
`);return`${t.red(`│`)}\n${t.red(`●`)} ${t.red(n)}\n`}function formatRailLine(t,n,r){return t===``?`${n.green(`│`)}\n`:`${W(r,t,`${n.green(`│`)} `)}\n`}function renderMultiselectPrompt(e){let t=railFor(e.state,e.colors),n=formatPromptHeader(e.state,e.message,{colors:e.colors,leadingRail:e.leadingRail}),r=new Set(e.selectedValues),i=e.options.some(e=>!e.disabled);switch(e.state){case`submit`:{if(r.size===0)return`${n}${t} ${e.colors.dim(`(none selected)`)}`;let i=e.options.filter(e=>r.has(e.value)).map(e=>e.label).join(`, `);return`${n}${t} ${e.colors.dim(i)}`}case`cancel`:return`${n}${t} ${e.colors.strikethrough(e.colors.dim(`cancelled`))}\n${t}`;case`error`:{let r=renderMultiselectRows({...e,rail:t});return`${n.trim()}\n${t} ${r}${multiselectHelpLine(t,e.colors,i)}\n${cornerFor(e.state,e.colors)} ${e.colors.red(e.error??``)}\n`}case`initial`:case`active`:return`${n}${t} ${renderMultiselectRows({...e,rail:t})}${multiselectHelpLine(t,e.colors,i)}\n${cornerFor(e.state,e.colors)}\n`}}function renderSelectPrompt(e){let t=railFor(e.state,e.colors),n=formatPromptHeader(e.state,e.message,{colors:e.colors,leadingRail:e.leadingRail}),r=e.options[e.cursor];switch(e.state){case`submit`:return`${n}${t} ${r?renderSelectOption(r,`selected`,e.colors):``}`;case`cancel`:return`${n}${t} ${r?e.colors.strikethrough(e.colors.dim(r.label)):``}\n${t}`;case`initial`:case`active`:case`error`:return`${n}${t} ${e.options.map((t,n)=>renderSelectOption(t,t.disabled?`disabled`:n===e.cursor?`active`:`inactive`,e.colors)).join(`\n${t} `)}\n${cornerFor(e.state,e.colors)}\n`}}function renderSelectOption(e,t,n){if(t===`disabled`)return`${n.dim(`○`)} ${n.dim(e.label)}`;let r=e.hint?n.dim(` (${e.hint})`):``;switch(t){case`selected`:return n.dim(e.label);case`active`:return`${n.green(`●`)} ${e.label}${r}`;case`inactive`:return`${n.dim(`○`)} ${n.dim(e.label)}`}}function renderMultiselectRows(e){let t=new Set(e.selectedValues);return e.options.map((n,r)=>renderMultiselectRow({colors:e.colors,isCursor:r===e.cursor,isSelected:t.has(n.value),option:n})).join(`\n${e.rail} `)}function renderMultiselectRow(e){if(e.option.disabled){let t=e.option.disabledReason?e.colors.dim(` (${e.option.disabledReason})`):``;return` ${e.colors.dim(`□`)} ${e.colors.dim(e.option.label)}${t}`}let t=e.isSelected?e.colors.green(`◼`):e.colors.dim(`□`),n=e.isCursor&&e.option.hint?e.colors.dim(` (${e.option.hint})`):``,r=e.isCursor?e.option.label:e.colors.dim(e.option.label);return`${e.isCursor?e.colors.green(`›`):` `} ${t} ${r}${n}`}function multiselectHelpLine(e,t,n){return n?`\n${e}\n${e} ${t.dim(`(`)}${t.cyan(`space`)} ${t.dim(`to select · `)}${t.cyan(`enter`)} ${t.dim(`to confirm or skip`)}${t.dim(`)`)}`:`\n${e}\n${e} ${t.dim(`(no channels available to add)`)}`}export{bulletFor,cornerFor,formatPromptCancellation,formatPromptHeader,formatPromptOpener,formatPromptOutro,formatRailLine,railFor,renderMultiselectPrompt,renderSelectPrompt};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{formatRailLine}from"./prompt-ui.js";function countRows(e){return e.split(`
|
|
2
|
+
`).length-1}function createRailLog(t){let n={kind:`idle`},r=t.output.isTTY===!0;function writeLine(n){t.output.write(formatRailLine(n,t.colors,t.output))}function clearPreview(){!r||n.kind===`idle`||n.previewRows===0||(t.output.write(`\u001B[${n.previewRows}A\u001B[J`),n.previewRows=0)}function settleStatus(e){if(n.kind!==`idle`){if(r&&(clearPreview(),e))for(let e of n.commandLines)writeLine(t.colors.dim(e));n={kind:`idle`}}}return{message(e){settleStatus(!1),writeLine(e),n={kind:`active`,commandLines:[],previewRows:0}},info(e){settleStatus(!1),writeLine(t.colors.dim(e))},success(e){settleStatus(!1),writeLine(t.colors.dim(e))},warning(e){settleStatus(!0),writeLine(t.colors.yellow(e))},error(e){settleStatus(!0),writeLine(t.colors.red(e))},commandOutput(i){if(n.kind===`idle`){writeLine(t.colors.dim(i));return}if(n.commandLines.push(i),!r){writeLine(t.colors.dim(i));return}clearPreview();let a=formatRailLine(t.colors.dim(i),t.colors,t.output);t.output.write(a),n.previewRows=countRows(a)},settle(){settleStatus(!1)}}}export{createRailLog};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{captureVercel}from"./run-vercel.js";import{join}from"node:path";import{readFile}from"node:fs/promises";function pickShortestAlias(e){if(!Array.isArray(e))return;let t;for(let n of e)typeof n!=`string`||n.length===0||(t===void 0||n.length<t.length)&&(t=n);return t}async function fetchProductionAlias(t,n,r){let i=await captureVercel([`api`,`/v9/projects/${t}?teamId=${n}`,`--scope`,n],{cwd:r});if(i!==void 0)try{let e=pickShortestAlias(JSON.parse(i).targets?.production?.alias);return e?`https://${e}`:void 0}catch{return}}async function detectDeployment(e){let r;try{r=await readFile(join(e,`.vercel`,`project.json`),`utf8`)}catch{return{state:`unlinked`}}let i;try{i=JSON.parse(r)}catch{return{state:`unlinked`}}let a=typeof i.projectId==`string`?i.projectId:void 0,o=typeof i.orgId==`string`?i.orgId:void 0;if(!a||!o)return{state:`unlinked`};let s=await fetchProductionAlias(a,o,e);return{state:s?`deployed`:`linked`,projectId:a,orgId:o,productionUrl:s}}export{detectDeployment};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./run-vercel.js";import"./detect-deployment.js";import"./run-pnpm.js";export{};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{extname,join}from"node:path";import{existsSync}from"node:fs";function resolvePnpmInvocation(n){let r=process.env.PNPM_HOME;if(r!==void 0){let e=join(r,process.platform===`win32`?`pnpm.CMD`:`pnpm`);if(existsSync(e))return{args:n,command:e,shell:process.platform===`win32`}}let i=process.env.npm_execpath;if(i!==void 0&&i.toLowerCase().includes(`pnpm`)){let t=extname(i).toLowerCase();return t===`.cjs`||t===`.js`?{args:[i,...n],command:process.execPath}:{args:n,command:i,shell:process.platform===`win32`}}return{args:n,command:`pnpm`}}export{resolvePnpmInvocation};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function createProcessOutputBuffer(e){let t={stdout:``,stderr:``};return{write(n,r){let i=`${t[n]}${r.toString(`utf8`)}`.split(/\r\n|\r|\n/);t[n]=i.pop()??``;for(let t of i)e({stream:n,text:t})},flush(){for(let n of[`stdout`,`stderr`]){let r=t[n];r!==``&&(e({stream:n,text:r}),t[n]=``)}}}}export{createProcessOutputBuffer};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createProcessOutputBuffer}from"./process-output.js";import{resolvePnpmInvocation}from"./pnpm-invocation.js";import{join}from"node:path";import{spawn}from"node:child_process";import{existsSync}from"node:fs";function spawnPnpm(n,r,i={}){return new Promise(a=>{let o=resolvePnpmInvocation([`--dir`,r,...existsSync(join(r,`pnpm-workspace.yaml`))?[]:[`--ignore-workspace`],...n]),s=i.onOutput&&createProcessOutputBuffer(i.onOutput),c=spawn(o.command,[...o.args],{cwd:r,stdio:i.onOutput?[`inherit`,`pipe`,`pipe`]:`inherit`,shell:o.shell});c.stdout?.on(`data`,e=>s?.write(`stdout`,e)),c.stderr?.on(`data`,e=>s?.write(`stderr`,e));let l=!1;function settle(e){l||(l=!0,s?.flush(),a(e))}function reportFailure(e){i.onOutput?i.onOutput({stream:`stderr`,text:e}):process.stderr.write(`\n${e}\n`)}c.on(`error`,e=>{e.code===`ENOENT`?reportFailure(`pnpm not found. Install it before running this step.`):reportFailure(`pnpm ${n.join(` `)} failed: ${e.message}`),settle(null)}),c.on(`close`,e=>settle(e))})}async function runPnpmInstall(e,t={}){return await spawnPnpm([`install`,`--no-frozen-lockfile`],e,t)===0}export{runPnpmInstall};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createProcessOutputBuffer}from"./process-output.js";import{spawn}from"node:child_process";const CONNECT_FEATURE_FLAG_ENV={FF_CONNECT_ENABLED:`1`},VERCEL_NOT_FOUND_MESSAGE=`Vercel CLI not found. Install with: npm i -g vercel@latest`;function buildSpawnEnv(e){return{...process.env,...CONNECT_FEATURE_FLAG_ENV,...e}}async function runVercel(t,n){return new Promise(r=>{let i=n.onOutput&&createProcessOutputBuffer(n.onOutput),a=spawn(`vercel`,t,{cwd:n.cwd,stdio:n.onOutput?[`inherit`,`pipe`,`pipe`]:`inherit`,env:buildSpawnEnv(n.extraEnv??{})});a.stdout?.on(`data`,e=>i?.write(`stdout`,e)),a.stderr?.on(`data`,e=>i?.write(`stderr`,e));let o=!1;function settle(e){o||(o=!0,i?.flush(),r(e))}function reportFailure(e){n.onOutput?n.onOutput({stream:`stderr`,text:e}):process.stderr.write(`\n${e}\n`)}a.on(`error`,e=>{e.code===`ENOENT`?reportFailure(VERCEL_NOT_FOUND_MESSAGE):reportFailure(`vercel ${t.join(` `)} failed: ${e.message}`),settle(!1)}),a.on(`close`,e=>{e!==0&&e!==null&&(i?.flush(),reportFailure(`vercel ${t.join(` `)} exited with code ${e}.`)),settle(e===0)})})}async function captureVercel(t,n){return new Promise(r=>{let i=n.onOutput&&createProcessOutputBuffer(n.onOutput),a=spawn(`vercel`,t,{cwd:n.cwd,stdio:[`ignore`,`pipe`,n.onOutput?`pipe`:`ignore`],env:buildSpawnEnv(n.extraEnv??{})}),o=[];a.stdout?.on(`data`,e=>o.push(e.toString(`utf8`))),a.stderr?.on(`data`,e=>i?.write(`stderr`,e));let s=!1;function settle(e){s||(s=!0,r(e))}function reportFailure(e){n.onOutput?.({stream:`stderr`,text:e})}a.on(`error`,e=>{n.onOutput&&reportFailure(e.code===`ENOENT`?VERCEL_NOT_FOUND_MESSAGE:`vercel ${t.join(` `)} failed: ${e.message}`),settle(void 0)}),a.on(`close`,e=>{if(e!==0&&e!==null){i?.flush(),reportFailure(`vercel ${t.join(` `)} exited with code ${e}.`),settle(void 0);return}settle(o.join(``))})})}export{captureVercel,runVercel};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readFile,writeFile}from"node:fs/promises";const CONNECT_SLACK_CREDENTIALS_REGEX=/(connectSlackCredentials\(\s*)(["'`])([^"'`]+)\2/;async function updateSlackChannelConnectorUid(r,i){let a;try{a=await readFile(r,`utf8`)}catch{return{patched:!1}}return CONNECT_SLACK_CREDENTIALS_REGEX.test(a)?(await writeFile(r,a.replace(CONNECT_SLACK_CREDENTIALS_REGEX,(e,t,n)=>`${t}${n}${i}${n}`),`utf8`),{patched:!0}):{patched:!1}}export{updateSlackChannelConnectorUid};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"./module-files.js";import"./files.js";import{join}from"node:path";import{stat}from"node:fs/promises";new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]);async function isAshProject(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${t}`)),!0}catch{}return!1}export{isAshProject};
|
|
1
|
+
import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"./module-files.js";import"./files.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{join}from"node:path";import{stat}from"node:fs/promises";new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),WEB_APP_TEMPLATE_FILES[`agent/channels/ash.ts`];async function isAshProject(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${t}`)),!0}catch{}return!1}export{isAshProject};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createPromptCommandOutput}from"../cli/command-output.js";import{runVercel}from"../primitives/run-vercel.js";import{detectDeployment}from"../primitives/detect-deployment.js";const VERCEL_DEPLOY_ENV={VERCEL_USE_EXPERIMENTAL_FRAMEWORKS:`1`};async function deployToVercel(e,t,n={}){let r=n.presetDeploy;if(r===void 0&&(r=await e.select({message:`Deploy to Vercel to set up remote agent`,options:[{value:`deploy`,label:`Deploy to Vercel`},{value:`skip`,label:`Skip and deploy later`}]})===`deploy`),!r)return e.log.info("Skipping deployment. Run `vercel deploy --prod` later when ready."),{deployed:!1};let i=createPromptCommandOutput(e.log);if(e.log.message(`Deploying the agent to Vercel production...`),!await runVercel([`deploy`,`--prod`],{cwd:t,extraEnv:VERCEL_DEPLOY_ENV,onOutput:i}))return{deployed:!1};e.log.message(`Pulling Vercel environment variables into .env.local...`),await runVercel([`env`,`pull`,`--yes`],{cwd:t,onOutput:i})||e.log.warning(`Deployment succeeded, but pulling Vercel environment variables did not complete.`);let a=await detectDeployment(t);return a.state===`deployed`&&a.productionUrl!==void 0&&e.log.info(`Production URL: ${a.productionUrl}`),{deployed:a.state===`deployed`,productionUrl:a.productionUrl}}export{deployToVercel};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./deploy-to-vercel.js";import"./run-add-to-agent.js";export{};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{deriveSlackConnectorSlug,ensureChannel}from"../channels.js";import{createPromptCommandOutput}from"../cli/command-output.js";import{runVercel}from"../primitives/run-vercel.js";import{deployToVercel}from"./deploy-to-vercel.js";import"../cli/channel-setup-prompter.js";import{runPnpmInstall}from"../primitives/run-pnpm.js";import{reconcileSlackUid,setupSlackbot}from"./setup-slackbot.js";const CHANNEL_OPTIONS=[{value:`web`,label:`Web Chat`,hint:`next.js`},{value:`slack`,label:`Slack`,hint:`creates slackbot and deploys to Vercel`}];function selectableChannels(e){return CHANNEL_OPTIONS.map(t=>{let n=e?.[t.value];return n===void 0?t:{...t,disabled:!0,disabledReason:n}})}function createAddToAgentState(e={state:`unlinked`}){return{channels:[],webScaffolded:!1,slackScaffolded:!1,slackDependenciesInstalled:!1,projectLinked:e.state!==`unlinked`,deployed:e.state===`deployed`,slackDeploymentPending:!1,productionUrl:e.productionUrl,slackbotCreated:!1,slackbotAttached:!1,slackConnectorUid:void 0,slackWorkspaceUrl:void 0,slackWorkspaceName:void 0}}function recordScaffoldedChannel(e,t){e.channels.includes(t)||e.channels.push(t)}async function promptCreateSlackbot(e){return await e.select({message:`Do you want to create your slackbot?`,options:[{value:`yes`,label:`Yes`,hint:`connects Slack, then deploys`},{value:`no`,label:`No`}]})===`yes`}async function installSlackDependencies(e,t,r){if(!r.slackDependenciesInstalled){if(e.log.message(`Installing project dependencies before deployment (pnpm install)...`),!await runPnpmInstall(t,{onOutput:createPromptCommandOutput(e.log)}))throw Error(`Dependency installation failed. Deployment did not start.`);r.slackDependenciesInstalled=!0}}async function linkProjectForSlackbot(e){if(e.state.projectLinked)return;let t;if(e.linkProjectForSlackbot===void 0?(e.prompter.log.message(`Linking this directory to a Vercel project...`),t=await runVercel([`link`],{cwd:e.projectPath})):t=await e.linkProjectForSlackbot(),!t)throw Error(`Vercel project linking failed. Slackbot creation did not start.`);e.state.projectLinked=!0}async function scaffoldSlackChannel(e,n){let{prompter:r,projectPath:i,state:a}=e;if(!a.slackScaffolded){r.log.message(`Scaffolding Slack channel files...`);let o=await ensureChannel({projectRoot:i,kind:`slack`,slackConnectorSlug:n,force:e.force});o.action===`created`||o.action===`overwritten`?r.log.success(`Scaffolded channel: slack`):r.log.info(`Channel "slack" already exists. Skipping file creation.`),a.slackScaffolded=!0}recordScaffoldedChannel(a,`slack`)}async function deployAttachedSlackChannel(e,t,n){await installSlackDependencies(e,t,n);let r=await deployToVercel(e,t,{presetDeploy:!0});if(n.deployed=r.deployed,n.productionUrl=r.productionUrl??n.productionUrl,!n.deployed)throw Error(`Deployment failed after Slack attachment.`);n.slackDeploymentPending=!1}async function reconcilePreparedSlackChannel(e,t,n,r){let i=n.slackConnectorUid;if(i===void 0)throw Error(`Slack connector UID was not resolved. Slack deployment did not start.`);if(!await reconcileSlackUid(e,t,{kind:`attached`,created:!0,attached:!0,connectorUid:i},r))throw Error(`Slack connector UID update is required before deployment.`)}function recordAttachedSlackbot(e,t){e.slackbotCreated=!0,e.slackbotAttached=!0,e.slackConnectorUid=t.connectorUid,e.slackWorkspaceUrl=t.workspaceUrl,e.slackWorkspaceName=t.workspaceName}async function runAddToAgentOnce(n,r){let{prompter:i,projectPath:a,projectName:o,state:s}=n;if(r.includes(`web`))if(s.webScaffolded)recordScaffoldedChannel(s,`web`);else{i.log.message(`Scaffolding Web Chat channel files...`);let e=await ensureChannel({projectRoot:a,kind:`web`,force:n.force,webPackageVersions:n.webPackageVersions});e.action===`created`||e.action===`overwritten`?(i.log.success(`Scaffolded channel: web`),s.webScaffolded=!0,recordScaffoldedChannel(s,`web`)):i.log.info(`Next.js project detected. Skipping Web Chat scaffolding.`)}if(!r.includes(`slack`))return;let c=await deriveSlackConnectorSlug(a,o);if(s.slackbotCreated){if(!s.slackbotAttached)throw Error(`Slackbot provisioning did not attach this project. Slack channel was not added.`);s.slackDeploymentPending&&(await scaffoldSlackChannel(n,c),await reconcilePreparedSlackChannel(i,a,s,`slack/${c}`),await deployAttachedSlackChannel(i,a,s));return}if(!(n.presetCreateSlackbot??await promptCreateSlackbot(i))){i.log.info(`Slack channel was not added because Slackbot setup was skipped.`);return}await linkProjectForSlackbot(n);let l=await setupSlackbot(i,a,{presetCreate:!0,slackbotName:c});if(!l.created)throw Error(`Slackbot creation failed.`);if(l.kind!==`attached`)throw Error(`Slackbot provisioning did not attach this project. Slack channel was not added.`);recordAttachedSlackbot(s,l),s.slackDeploymentPending=!0,await scaffoldSlackChannel(n,c),await reconcilePreparedSlackChannel(i,a,s,`slack/${c}`),await deployAttachedSlackChannel(i,a,s)}async function runAddToAgent(e){for(;;){let t=e.presetChannels??await e.prompter.multiselect({message:`Add to agent`,options:selectableChannels(e.disabledChannelReasons),required:!1});await e.validateSelectedChannels?.(t);try{await runAddToAgentOnce(e,t);return}catch(t){if(t instanceof Error&&(t.name===`WizardCancelledError`||t.name===`ChannelAddCancelledError`))throw t;let n=t instanceof Error?t.message:String(t),r=n.split(`
|
|
2
|
+
`)[0]?.trim()??n;if(e.prompter.log.error(r),e.presetChannels!==void 0)throw t}}}export{createAddToAgentState,runAddToAgent};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{SLACK_CHANNEL_DEFAULT_ROUTE}from"../channels.js";import{createPromptCommandOutput}from"../cli/command-output.js";import{captureVercel,runVercel}from"../primitives/run-vercel.js";import{updateSlackChannelConnectorUid}from"../primitives/update-slack-channel.js";import{join}from"node:path";import{readFile}from"node:fs/promises";async function runVercelConnectCreateSlack(e,t){let n=[`connect`,`create`,`slack`,`--triggers`];return t&&n.push(`--name`,t),runVercel(n,{cwd:e})}async function readProjectId(e){try{let t=await readFile(join(e,`.vercel`,`project.json`),`utf8`),n=JSON.parse(t);return typeof n.projectId==`string`?n.projectId:void 0}catch{return}}function pickSlackConnector(e,t,n){if(typeof e!=`object`||!e)return;let r=e.clients;if(!Array.isArray(r))return;let i;for(let e of r){if(e.type!==`slack`||typeof e.uid!=`string`||typeof e.id!=`string`)continue;let r={uid:e.uid,id:e.id};if(n!==void 0&&r.uid===n)return r;let a=typeof e.createdAt==`number`?e.createdAt:0;t!==void 0&&Array.isArray(e.projects)&&e.projects.some(e=>typeof e==`object`&&!!e&&e.id===t)&&(!i||a>i.createdAt)&&(i={ref:r,createdAt:a})}return i?.ref}function parseInstallation(e){if(typeof e!=`object`||!e)return;let t=e.installations;if(!Array.isArray(t)||t.length===0)return;let n=t[0];if(typeof n.tenantUrl==`string`)return{workspaceUrl:n.tenantUrl,workspaceName:typeof n.tenantName==`string`?n.tenantName:void 0}}async function findSlackConnector(e,t,r,i){let a=await captureVercel([`connect`,`list`,`-F`,`json`,`--all-projects`],{cwd:e,onOutput:i});if(a)try{return pickSlackConnector(JSON.parse(a),t,r)}catch{return}}async function fetchInstallationInfo(e,t,r){let i=await captureVercel([`api`,`/v1/connex/clients/${t}/installations`],{cwd:e,onOutput:r});if(i)try{return parseInstallation(JSON.parse(i))}catch{return}}async function setupSlackbot(n,i,a={}){let o=a.presetCreate;if(o===void 0&&(o=await n.select({message:`Do you want to create your slackbot?`,options:[{value:`yes`,label:`Yes`},{value:`no`,label:`No`}]})===`yes`),!o)return n.log.info("Skipping slackbot creation. Run `vercel connect create slack` later when ready."),{kind:`skipped`,created:!1,attached:!1};let s=createPromptCommandOutput(n.log);if(n.log.message(`Creating a Slackbot through Vercel Connect...`),!await runVercelConnectCreateSlack(i,a.slackbotName))return{kind:`create-failed`,created:!1,attached:!1};n.log.success(`Slackbot created via Vercel Connect.`),n.log.message(`Locating the Slack connector...`);let c=await findSlackConnector(i,await readProjectId(i),a.slackbotName?`slack/${a.slackbotName}`:void 0,s);if(!c)return n.log.warning("Could not locate the new Slack connector. Run `vercel connect list --all-projects` to find its UID."),{kind:`connector-unresolved`,created:!0,attached:!1};if(n.log.info(`Slack connector: ${c.uid}`),n.log.message(`Configuring Slack event delivery for this agent...`),await runVercel([`connect`,`detach`,c.uid,`--yes`],{cwd:i,onOutput:s}),!await runVercel([`connect`,`attach`,c.uid,`--triggers`,`--trigger-path`,SLACK_CHANNEL_DEFAULT_ROUTE,`--yes`],{cwd:i,onOutput:s}))return n.log.warning(`Could not register this project as a trigger destination. Run \`vercel connect attach ${c.uid} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes\` to enable event delivery.`),{kind:`attach-failed`,created:!0,attached:!1,connectorUid:c.uid};n.log.message(`Reading Slack workspace details...`);let l=await fetchInstallationInfo(i,c.id,s);return l?{kind:`attached`,created:!0,attached:!0,connectorUid:c.uid,workspaceUrl:l.workspaceUrl,workspaceName:l.workspaceName}:{kind:`attached`,created:!0,attached:!0,connectorUid:c.uid}}async function reconcileSlackUid(e,t,n,r){if(n.kind!==`attached`||n.connectorUid===r)return!0;e.log.info(`Connect assigned UID ${n.connectorUid} (expected ${r}). Updating agent/channels/slack.ts before deployment...`);let{patched:o}=await updateSlackChannelConnectorUid(join(t,`agent/channels/slack.ts`),n.connectorUid);return o?!0:(e.log.warning(`Could not patch agent/channels/slack.ts automatically. Update \`connectSlackCredentials("...")\` to \`"${n.connectorUid}"\` and run \`vercel deploy --prod\`.`),!1)}export{reconcileSlackUid,setupSlackbot};
|