eve 0.11.9 → 0.12.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 +22 -0
- package/dist/src/cli/banner.js +1 -1
- package/dist/src/cli/commands/init-git.d.ts +1 -1
- package/dist/src/cli/commands/init-git.js +1 -1
- package/dist/src/cli/commands/init.d.ts +1 -0
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/dev/tui/line-editor.d.ts +53 -19
- package/dist/src/cli/dev/tui/line-editor.js +6 -1
- package/dist/src/cli/dev/tui/live-region.d.ts +2 -0
- package/dist/src/cli/dev/tui/live-region.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +3 -0
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/setup-panel.js +3 -3
- package/dist/src/cli/dev/tui/setup-selection-input.js +2 -1
- package/dist/src/cli/dev/tui/stream-format.d.ts +21 -2
- package/dist/src/cli/dev/tui/stream-format.js +4 -2
- package/dist/src/cli/dev/tui/terminal-renderer.js +10 -10
- package/dist/src/cli/dev/tui/terminal-text.d.ts +11 -0
- package/dist/src/cli/dev/tui/terminal-text.js +1 -1
- package/dist/src/cli/dev/tui/theme.d.ts +2 -0
- package/dist/src/cli/dev/tui/theme.js +1 -1
- package/dist/src/cli/dev/tui/tui.d.ts +3 -0
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/format-elapsed.d.ts +2 -0
- package/dist/src/cli/format-elapsed.js +1 -0
- package/dist/src/cli/run.d.ts +4 -18
- package/dist/src/cli/run.js +2 -2
- package/dist/src/cli/ui/live-row.d.ts +19 -0
- package/dist/src/cli/ui/live-row.js +1 -0
- package/dist/src/context/dynamic-skill-lifecycle.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/evals/assertions/run.d.ts +7 -1
- package/dist/src/evals/assertions/run.js +2 -2
- package/dist/src/evals/context.js +1 -1
- package/dist/src/evals/index.d.ts +1 -1
- package/dist/src/evals/match.d.ts +6 -0
- package/dist/src/evals/types.d.ts +3 -1
- package/dist/src/execution/node-step.d.ts +2 -1
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/code-mode.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/dev-boot-progress.d.ts +13 -0
- package/dist/src/internal/dev-boot-progress.js +1 -0
- package/dist/src/internal/logging.d.ts +9 -0
- package/dist/src/internal/logging.js +1 -1
- package/dist/src/internal/nitro/host/start-development-server.d.ts +2 -5
- package/dist/src/internal/nitro/host/start-development-server.js +2 -2
- package/dist/src/internal/nitro/host/types.d.ts +6 -0
- package/dist/src/internal/nitro/host.d.ts +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
- package/dist/src/public/definitions/connections/openapi.d.ts +1 -1
- package/dist/src/public/definitions/tool.d.ts +6 -0
- package/dist/src/runtime/agent/mock-model-adapter.js +2 -2
- package/dist/src/runtime/agent/resolve-model.d.ts +7 -4
- package/dist/src/runtime/agent/resolve-model.js +1 -1
- package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
- package/dist/src/runtime/framework-tools/skill.js +1 -1
- package/dist/src/runtime/prompt/connections.js +1 -1
- package/dist/src/runtime/resolve-agent-graph.js +1 -1
- package/dist/src/runtime/skills/sandbox-access.d.ts +3 -2
- package/dist/src/runtime/skills/sandbox-access.js +1 -1
- package/dist/src/setup/cli/select-state.js +1 -1
- package/dist/src/setup/primitives/pm/npm.js +1 -1
- package/dist/src/setup/primitives/pm/run.js +1 -1
- package/dist/src/setup/primitives/pm/types.d.ts +2 -0
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/slack-connect-create.js +1 -1
- package/dist/src/setup/slackbot.js +1 -1
- package/dist/src/shared/text-boundaries.d.ts +19 -0
- package/dist/src/shared/text-boundaries.js +1 -0
- package/docs/concepts/default-harness.md +1 -1
- package/docs/connections.mdx +4 -4
- package/docs/evals/assertions.mdx +1 -0
- package/docs/guides/dev-tui.md +10 -7
- package/docs/guides/dynamic-capabilities.md +12 -7
- package/docs/subagents.mdx +1 -1
- package/docs/tutorial/connect-a-warehouse.mdx +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 7df41e1: Dynamic map resolvers no longer auto-prefix entries with the file slug — the map key is the tool/skill name verbatim (a single `defineTool`/`defineSkill` is still named after the file slug). Namespace keys yourself (e.g. `team__playbook`) when a bare name might collide. A dynamic tool/skill overrides a same-named authored one; two dynamic resolvers emitting the same name now throw, recommending manual namespacing. Connection tools are renamed accordingly: the search tool is `connection_search` and discovered tools are `<connection>__<tool>` (e.g. `linear__list_issues`).
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 10e9237: Fix code-defined models under `eve dev`, including NodeNext `.js` imports that target authored `.ts` files. Runtime model resolution now reuses the active agent bundle's module map and node scope, so child agents resolve their own models without rebuilding authored modules on each step.
|
|
12
|
+
|
|
13
|
+
## 0.11.10
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- c707ca3: Keep `eve init` and local `eve dev` progress on one terminal row. Init now includes elapsed completion times and preserves useful package-manager diagnostics on failure. With `EVE_LOG_LEVEL=debug`, both commands use plain phase logs instead of animation.
|
|
18
|
+
- 2197c14: Dynamic skill resolvers that return a map now name every entry `<slug>__<key>` even when the map holds a single entry, matching dynamic tools and the documented contract. Previously a one-entry map was advertised and materialized under the bare resolver slug, so `load_skill` failed to find it and adding a second skill silently renamed the first. `load_skill` failures now also list the available skill names so the model can correct a wrong id.
|
|
19
|
+
|
|
20
|
+
Adds a `t.loadedSkill(skill, opts?)` eval assertion — sugar for `t.calledTool("load_skill", { input: { skill }, ... })`.
|
|
21
|
+
|
|
22
|
+
- d22fd04: In the dev TUI, Ctrl+C now clears a non-empty chat or freeform `ask_question` prompt instead of quitting. On an empty prompt it still quits, and during a running turn it still interrupts.
|
|
23
|
+
- d22fd04: The dev TUI prompt now takes multi-line input in both chat and freeform `ask_question` fields. Pasting multi-line text inserts it intact instead of submitting at the first line, `Shift+Enter` inserts a newline, a tall prompt scrolls within the terminal height, and editing moves by whole graphemes so wide and emoji characters aren't split.
|
|
24
|
+
|
|
3
25
|
## 0.11.9
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/dist/src/cli/banner.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{__toESM}from"../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";var import_picocolors=__toESM(require_picocolors(),1);const EVE_WORDMARK=`eve`,EVE_BETA_TERMS_URL=`https://vercel.com/docs/release-phases/public-beta-agreement`;function eveCliBanner(){let{version:e}=resolveInstalledPackageInfo();return`${import_picocolors.default.bgBlack(import_picocolors.default.white(
|
|
1
|
+
import{__toESM}from"../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";var import_picocolors=__toESM(require_picocolors(),1);const EVE_WORDMARK=`eve`,EVE_BETA_TERMS_URL=`https://vercel.com/docs/release-phases/public-beta-agreement`;function eveCliBanner(){let{version:e}=resolveInstalledPackageInfo();return`${import_picocolors.default.bgBlack(import_picocolors.default.white(`☰eve `))} ${import_picocolors.default.dim(`v${e}`)}`}export{EVE_BETA_TERMS_URL,EVE_WORDMARK,eveCliBanner};
|
|
@@ -12,4 +12,4 @@ export type GitInitResult = {
|
|
|
12
12
|
* initialization is removed and returned as a `failed` result; presenting the
|
|
13
13
|
* failure (without failing `eve init`) is the caller's job.
|
|
14
14
|
*/
|
|
15
|
-
export declare function tryInitializeGit(projectPath: string): GitInitResult
|
|
15
|
+
export declare function tryInitializeGit(projectPath: string): Promise<GitInitResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{join}from"node:path";import{execFile}from"node:child_process";import{rm}from"node:fs/promises";import{promisify}from"node:util";const GIT_TIMEOUT_MS=5e3,runFile=promisify(execFile);async function commandSucceeds(e,t,n){try{let r={timeout:GIT_TIMEOUT_MS,windowsHide:!0};return n!==void 0&&(r.cwd=n),await runFile(e,[...t],r),!0}catch{return!1}}function isGitAvailable(){return commandSucceeds(`git`,[`--version`])}async function isInsideExistingRepository(e){return await commandSucceeds(`git`,[`rev-parse`,`--is-inside-work-tree`],e)||await commandSucceeds(`hg`,[`--cwd`,`.`,`root`],e)}function hasConfiguredDefaultBranch(e){return commandSucceeds(`git`,[`config`,`init.defaultBranch`],e)}async function runGit(e,t){await runFile(`git`,[...t],{cwd:e,timeout:GIT_TIMEOUT_MS,windowsHide:!0})}async function tryInitializeGit(t){if(!await isGitAvailable()||await isInsideExistingRepository(t))return{kind:`skipped`};let r=!1;try{return await runGit(t,[`init`]),r=!0,await hasConfiguredDefaultBranch(t)||await runGit(t,[`checkout`,`-b`,`main`]),await runGit(t,[`add`,`-A`]),await runGit(t,[`commit`,`-m`,`Initial commit from eve`]),{kind:`initialized`}}catch(i){return r&&await rm(join(t,`.git`),{recursive:!0,force:!0}).catch(()=>{}),{kind:`failed`,reason:i instanceof Error?i.message:String(i)}}}export{tryInitializeGit};
|
|
@@ -18,6 +18,7 @@ export interface InitCommandDependencies {
|
|
|
18
18
|
detectPackageManager: typeof detectPackageManager;
|
|
19
19
|
ensureChannel: typeof ensureChannel;
|
|
20
20
|
isCodingAgentLaunch: typeof isCodingAgentLaunch;
|
|
21
|
+
now: () => number;
|
|
21
22
|
runPackageManagerInstall: typeof runPackageManagerInstall;
|
|
22
23
|
scaffoldBaseProject: typeof scaffoldBaseProject;
|
|
23
24
|
spawnPackageManager: typeof spawnPackageManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{initAgentDevHandoff}from"./agent-instructions.js";import{tryInitializeGit}from"./init-git.js";import{basename,join,resolve}from"node:path";import{ensureChannel,scaffoldBaseProject}from"#setup/scaffold/index.js";import{mkdtemp,readdir,rename,rm,stat}from"node:fs/promises";import{isCodingAgentLaunch}from"#cli/agent-detection.js";import{EVE_WORDMARK}from"#cli/banner.js";import{
|
|
1
|
+
import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{initAgentDevHandoff}from"./agent-instructions.js";import{tryInitializeGit}from"./init-git.js";import{createLogger,isLogLevelEnabled}from"#internal/logging.js";import{basename,join,resolve}from"node:path";import{ensureChannel,scaffoldBaseProject}from"#setup/scaffold/index.js";import{mkdtemp,readdir,rename,rm,stat}from"node:fs/promises";import{performance}from"node:perf_hooks";import{isCodingAgentLaunch}from"#cli/agent-detection.js";import{EVE_WORDMARK}from"#cli/banner.js";import{formatElapsed}from"#cli/format-elapsed.js";import{startCliLiveRow}from"#cli/ui/live-row.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{formatNodeEngineOverrideWarning}from"#setup/node-engine.js";import{detectInvokingPackageManager,detectPackageManager}from"#setup/package-manager.js";import{pathExists}from"#setup/path-exists.js";import{parseProjectName}from"#setup/project-name.js";import{eveDevArguments,runPackageManagerInstall,spawnPackageManager}from"#setup/primitives/index.js";import{addAgentToProject}from"#setup/scaffold/create/add-to-project.js";import{DEFAULT_EVE_PACKAGE_CONTRACT}from"#setup/scaffold/create/project.js";var import_picocolors=__toESM(require_picocolors(),1);const defaultDependencies={addAgentToProject,detectInvokingPackageManager,detectPackageManager,ensureChannel,isCodingAgentLaunch,now:()=>performance.now(),runPackageManagerInstall,scaffoldBaseProject,spawnPackageManager,tryInitializeGit},ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),EVE_INIT_PACKAGE_SPEC_ENV=`EVE_INIT_PACKAGE_SPEC`,initLog=createLogger(`init`);async function resolveTargetDirectory(e,t){let n=resolve(e,t);return(await stat(n).catch(()=>void 0))?.isDirectory()?n:void 0}function isCurrentDirectoryTarget(e){return/^\.(?:[/\\]+\.?)*$/u.test(e.trim())}async function assertCanScaffoldInPlace(e){let t=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(t.length===0)return;let n=t.slice(0,5).join(`, `),r=t.length>5?`, and ${t.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${n}${r}. Use an empty directory.`)}async function moveDirectoryContents(e,t){for(let n of await readdir(e))await rename(join(e,n),join(t,n))}async function addToExistingProject(e,t,n,r){if(t.channelWebNextjs===!0)throw Error("`--channel-web-nextjs` is not supported when adding an agent to an existing project. Run `eve channels add web` from the project afterwards instead.");let i=await n.detectPackageManager(e),a=await n.addAgentToProject({projectRoot:e,model:DEFAULT_AGENT_MODEL_ID,packageManager:i.kind,evePackage:r});return{packageManager:i.kind,nodeEngineOverride:a.nodeEngineOverride}}async function resolveScaffoldPackageManager(e,t){let n=await t.detectPackageManager(e);return n.source==="default"?t.detectInvokingPackageManager()??`pnpm`:n.kind}async function scaffoldProject(e,t,n,r,i,a){let l=resolve(e),u=t===`.`,f=u?l:join(l,t);if(u)await assertCanScaffoldInPlace(f);else if(await pathExists(f))throw Error(`Cannot create project because "${f}" already exists.`);let h=await mkdtemp(join(l,`.eve-init-`));try{let e={projectName:u?basename(f):t,model:DEFAULT_AGENT_MODEL_ID,evePackage:a,targetDirectory:h,packageManager:n},s=await i.scaffoldBaseProject(e);return r.channelWebNextjs===!0&&await i.ensureChannel({projectRoot:s,kind:`web`,packageManager:n,configureVercelServices:!1}),u?await moveDirectoryContents(s,f):await rename(s,f),f}finally{await rm(h,{recursive:!0,force:!0})}}function installProgressDetail(e,t){let n=t.text.trim();if(n===``||e!==`npm`)return n||void 0;let r=/^npm silly fetch manifest (.+)$/u.exec(n);if(r!==null)return`Resolving ${r[1]}`;let i=/^npm http fetch \S+ \S+ attempt (\d+) failed with (\S+)$/u.exec(n);if(i!==null)return`npm registry · attempt ${i[1]} failed: ${i[2]}`;if(t.stream===`stdout`||/^npm (?:error|warn)\b/u.test(n))return n}const NPM_NOISE_LINE=/^\s*npm (?:silly|verbose|http|timing)\b/u;async function runInitSteps(e){let{dependencies:t,logger:n,options:r,parentDirectory:i,target:o}=e,l=isLogLevelEnabled(`debug`),u=startCliLiveRow(n);u.update(`Preparing project`);try{let e=await t.isCodingAgentLaunch(),a=o??`.`,d=isCurrentDirectoryTarget(a),f=d?await pathExists(join(resolve(i),`package.json`))?resolve(i):void 0:await resolveTargetDirectory(i,a),p=resolveInitEvePackageOverride(),m=f===void 0?`creating agent`:`adding agent`;u.update(f===void 0?`Creating agent`:`Adding agent`),initLog.debug(m);let h=t.now(),g;if(f===void 0){let e=d?`.`:parseProjectName(a),n=resolve(i),o=await resolveScaffoldPackageManager(e===`.`?n:join(n,e),t);g={kind:`created`,packageManager:o,projectPath:await scaffoldProject(i,e,o,r,t,p)}}else{let e=await addToExistingProject(f,r,t,p);g=e.nodeEngineOverride===void 0?{kind:`added`,packageManager:e.packageManager,projectPath:f}:{kind:`added`,nodeEngineOverride:e.nodeEngineOverride,packageManager:e.packageManager,projectPath:f}}let _=t.now()-h;initLog.debug(`${m} done`,{ms:_}),u.update(`Installing dependencies`,`${g.packageManager} install`),initLog.debug(`installing dependencies with ${g.packageManager}`);let v=t.now(),y=[],b=[],x=await t.runPackageManagerInstall(g.packageManager,g.projectPath,{bypassMinimumReleaseAge:!0,progressDetails:process.stdout.isTTY===!0&&!l,onOutput:e=>{e.text.trim()!==``&&(b.push(e.text),b.length>20&&b.shift(),NPM_NOISE_LINE.test(e.text)||y.push(e.text)),l&&initLog.debug(e.text);let t=installProgressDetail(g.packageManager,e);t!==void 0&&u.update(`Installing dependencies`,t)}}),S=t.now()-v;if(!x){initLog.debug(`dependency installation failed`,{ms:S}),u.stop();let e=y.length>0?y:b;for(let t of e)n.error(t);throw Error(`Failed to install dependencies in "${g.projectPath}".`)}return initLog.debug(`dependencies installed`,{ms:S}),g.kind===`created`?(u.update(`Initializing Git repository`),initLog.debug(`initializing git repository`),{...g,agentElapsedMs:_,agentLaunched:e,gitResult:await t.tryInitializeGit(g.projectPath),installElapsedMs:S}):{...g,agentElapsedMs:_,agentLaunched:e,installElapsedMs:S}}finally{u.stop()}}async function runInitCommand(e,t,r,i,a=defaultDependencies){let o=await runInitSteps({dependencies:a,logger:e,options:i,parentDirectory:t,target:r}),s=o.kind===`created`;if(o.kind===`created`?e.log(`${import_picocolors.default.green(`✓`)} Created an ${EVE_WORDMARK} agent in ${import_picocolors.default.bold(o.projectPath)} ${import_picocolors.default.dim(`in ${formatElapsed(o.agentElapsedMs)}`)}`):(e.log(`${import_picocolors.default.green(`✓`)} Added an ${EVE_WORDMARK} agent to ${import_picocolors.default.bold(o.projectPath)} ${import_picocolors.default.dim(`in ${formatElapsed(o.agentElapsedMs)}`)}`),o.nodeEngineOverride!==void 0&&e.log(import_picocolors.default.yellow(`⚠ ${formatNodeEngineOverrideWarning(o.nodeEngineOverride)}`))),e.log(`${import_picocolors.default.green(`✓`)} Installed dependencies ${import_picocolors.default.dim(`in ${formatElapsed(o.installElapsedMs)}`)}`),o.kind===`created`&&o.gitResult.kind===`failed`&&e.error(import_picocolors.default.yellow(`Git initialization failed: ${o.gitResult.reason}`)),o.agentLaunched){e.log(initAgentDevHandoff({projectPath:o.projectPath,devCommand:[o.packageManager,...eveDevArguments(o.packageManager)].join(` `)}));return}let c=s?[...eveDevArguments(o.packageManager),`--input`,`/model`]:eveDevArguments(o.packageManager);if(e.log(import_picocolors.default.dim(s?`$ eve dev --input /model`:`$ eve dev`)),!await a.spawnPackageManager(o.packageManager,o.projectPath,c))throw Error(`Development server exited unsuccessfully in "${o.projectPath}".`)}function resolveInitEvePackageOverride(){let e=process.env[EVE_INIT_PACKAGE_SPEC_ENV]?.trim();if(!(e===void 0||e.length===0))return{nodeEngine:DEFAULT_EVE_PACKAGE_CONTRACT.nodeEngine,version:e}}export{EVE_INIT_PACKAGE_SPEC_ENV,runInitCommand};
|
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A tiny, dependency-free line-editing model for the prompt input.
|
|
3
3
|
*
|
|
4
|
-
* The renderer owns the terminal; this module owns the *text* —
|
|
5
|
-
*
|
|
6
|
-
* common readline-style edits (insert, delete,
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* The renderer owns the terminal; this module owns the *text* — buffer plus
|
|
5
|
+
* caret position, where the buffer may carry embedded newlines — and exposes
|
|
6
|
+
* pure transforms for the common readline-style edits (insert, delete,
|
|
7
|
+
* word/line kill, cursor moves), a {@link visibleLine} helper that windows a
|
|
8
|
+
* long line around the caret, and {@link layoutPromptInput} which splits a
|
|
9
|
+
* multi-line buffer into logical rows. Keeping it pure makes the editing rules
|
|
10
|
+
* trivial to unit test without a TTY.
|
|
10
11
|
*/
|
|
11
12
|
import type { TerminalKey } from "./stream-format.js";
|
|
12
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Editor text and a caret at a grapheme boundary, represented as a UTF-16
|
|
15
|
+
* offset so it can be passed directly to `String.slice`.
|
|
16
|
+
*/
|
|
13
17
|
export interface LineState {
|
|
14
18
|
readonly text: string;
|
|
15
19
|
readonly cursor: number;
|
|
16
20
|
}
|
|
17
|
-
/** The empty
|
|
21
|
+
/** The empty editor buffer with the caret at offset 0. */
|
|
18
22
|
export declare const EMPTY_LINE: LineState;
|
|
19
23
|
/** Builds a line from `text` with the caret placed at the end. */
|
|
20
24
|
export declare function lineOf(text: string): LineState;
|
|
21
25
|
/** Inserts `value` at the caret and advances the caret past it. */
|
|
22
26
|
export declare function insert(state: LineState, value: string): LineState;
|
|
23
|
-
/** Deletes the
|
|
27
|
+
/** Deletes the grapheme before the caret (Backspace). */
|
|
24
28
|
export declare function backspace(state: LineState): LineState;
|
|
25
|
-
/** Deletes the
|
|
29
|
+
/** Deletes the grapheme at the caret (Delete / Ctrl+D mid-line). */
|
|
26
30
|
export declare function deleteForward(state: LineState): LineState;
|
|
27
|
-
/** Moves the caret one
|
|
31
|
+
/** Moves the caret one grapheme left. */
|
|
28
32
|
export declare function moveLeft(state: LineState): LineState;
|
|
29
|
-
/** Moves the caret one
|
|
33
|
+
/** Moves the caret one grapheme right. */
|
|
30
34
|
export declare function moveRight(state: LineState): LineState;
|
|
31
35
|
/** Moves the caret to the start of the line (Home / Ctrl+A). */
|
|
32
36
|
export declare function moveHome(state: LineState): LineState;
|
|
@@ -38,22 +42,51 @@ export declare function killToEnd(state: LineState): LineState;
|
|
|
38
42
|
export declare function killToStart(state: LineState): LineState;
|
|
39
43
|
/** Deletes the whitespace-delimited word before the caret (Ctrl+W). */
|
|
40
44
|
export declare function deleteWord(state: LineState): LineState;
|
|
45
|
+
/** Options for {@link applyLineEditorKey}. */
|
|
46
|
+
interface LineEditorOptions {
|
|
47
|
+
/** Single-line inputs flatten pasted newlines and ignore Shift+Enter. */
|
|
48
|
+
readonly multiline?: boolean;
|
|
49
|
+
}
|
|
41
50
|
/**
|
|
42
|
-
* Applies a key owned by the
|
|
43
|
-
*
|
|
51
|
+
* Applies a key owned by the line editor. Returns `undefined` when the key
|
|
52
|
+
* belongs to the surrounding controller (submit, cancel, history, menus), which
|
|
53
|
+
* on a single-line input includes Shift+Enter.
|
|
44
54
|
*/
|
|
45
|
-
export declare function applyLineEditorKey(state: LineState, key: TerminalKey): LineState | undefined;
|
|
55
|
+
export declare function applyLineEditorKey(state: LineState, key: TerminalKey, options?: LineEditorOptions): LineState | undefined;
|
|
46
56
|
/**
|
|
47
57
|
* The portion of `state.text` to draw within `budget` columns, split at the
|
|
48
|
-
* caret so the renderer can
|
|
49
|
-
*
|
|
50
|
-
*
|
|
58
|
+
* caret so the renderer can highlight `under` without slicing a grapheme.
|
|
59
|
+
* When the line is wider than `budget` it is windowed around the caret,
|
|
60
|
+
* marking truncated ends with `…` so the caret is always visible.
|
|
51
61
|
*/
|
|
52
|
-
|
|
62
|
+
interface VisibleLine {
|
|
53
63
|
readonly before: string;
|
|
64
|
+
readonly under: string;
|
|
54
65
|
readonly after: string;
|
|
55
66
|
}
|
|
56
67
|
export declare function visibleLine(state: LineState, budget: number, ellipsis?: string): VisibleLine;
|
|
68
|
+
/** One logical prompt row and the UTF-16 offset where it starts in the buffer. */
|
|
69
|
+
interface PromptLogicalRow {
|
|
70
|
+
readonly text: string;
|
|
71
|
+
readonly start: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* A multi-line prompt split into logical rows. `caretRow` indexes {@link rows};
|
|
75
|
+
* `caretOffset` is a UTF-16 offset within that row.
|
|
76
|
+
*/
|
|
77
|
+
interface PromptLayout {
|
|
78
|
+
readonly rows: PromptLogicalRow[];
|
|
79
|
+
readonly caretRow: number;
|
|
80
|
+
readonly caretOffset: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Splits a prompt buffer on newlines and locates the caret. This function does
|
|
84
|
+
* not measure terminal columns or wrap rows; the renderer windows each logical
|
|
85
|
+
* row to the available width.
|
|
86
|
+
*/
|
|
87
|
+
export declare function layoutPromptInput(state: LineState): PromptLayout;
|
|
88
|
+
/** Moves to the adjacent logical line while preserving the terminal column where possible. */
|
|
89
|
+
export declare function movePromptLine(state: LineState, direction: "up" | "down"): LineState | undefined;
|
|
57
90
|
/**
|
|
58
91
|
* In-memory, append-only prompt history with shell-style up/down navigation.
|
|
59
92
|
*
|
|
@@ -72,3 +105,4 @@ export declare class PromptHistory {
|
|
|
72
105
|
/** The next (newer) entry, or the stashed draft once past the newest entry. */
|
|
73
106
|
next(): string | undefined;
|
|
74
107
|
}
|
|
108
|
+
export {};
|
|
@@ -1 +1,6 @@
|
|
|
1
|
-
const EMPTY_LINE={text:``,cursor:0};function lineOf(e){return{text:e,cursor:e.length}}function insert(e,t){
|
|
1
|
+
import{inputTextWidth,offsetAtVisibleColumn}from"./terminal-text.js";import{graphemeBoundaryAtOrAfter,graphemes,nextGraphemeBoundary,previousGraphemeBoundary}from"#shared/text-boundaries.js";const EMPTY_LINE={text:``,cursor:0};function lineOf(e){return{text:e,cursor:e.length}}function insert(e,t){if(t.length===0)return e;let r=e.text.slice(0,e.cursor)+t+e.text.slice(e.cursor);return{text:r,cursor:graphemeBoundaryAtOrAfter(r,e.cursor+t.length)}}function backspace(e){if(e.cursor===0)return e;let t=previousGraphemeBoundary(e.text,e.cursor),r=e.text.slice(0,t)+e.text.slice(e.cursor);return{text:r,cursor:graphemeBoundaryAtOrAfter(r,t)}}function deleteForward(e){if(e.cursor>=e.text.length)return e;let t=nextGraphemeBoundary(e.text,e.cursor),r=e.text.slice(0,e.cursor)+e.text.slice(t);return{text:r,cursor:graphemeBoundaryAtOrAfter(r,e.cursor)}}function moveLeft(e){return e.cursor===0?e:{text:e.text,cursor:previousGraphemeBoundary(e.text,e.cursor)}}function moveRight(e){return e.cursor>=e.text.length?e:{text:e.text,cursor:nextGraphemeBoundary(e.text,e.cursor)}}function moveHome(e){let t=logicalLineStart(e.text,e.cursor);return e.cursor===t?e:{text:e.text,cursor:t}}function moveEnd(e){let t=logicalLineEnd(e.text,e.cursor);return e.cursor===t?e:{text:e.text,cursor:t}}function killToEnd(e){let t=logicalLineEnd(e.text,e.cursor);return e.cursor>=t?e:{text:e.text.slice(0,e.cursor)+e.text.slice(t),cursor:e.cursor}}function killToStart(e){let t=logicalLineStart(e.text,e.cursor);return e.cursor<=t?e:{text:e.text.slice(0,t)+e.text.slice(e.cursor),cursor:t}}function deleteWord(e){if(e.cursor===0)return e;let t=logicalLineStart(e.text,e.cursor),r=e.cursor;for(;r>t;){let t=previousGraphemeBoundary(e.text,r);if(!isWhitespace(e.text.slice(t,r)))break;r=t}for(;r>t;){let t=previousGraphemeBoundary(e.text,r);if(isWhitespace(e.text.slice(t,r)))break;r=t}let i=e.text.slice(0,r)+e.text.slice(e.cursor);return{text:i,cursor:graphemeBoundaryAtOrAfter(i,r)}}function logicalLineStart(e,t){return t===0?0:e.lastIndexOf(`
|
|
2
|
+
`,t-1)+1}function logicalLineEnd(e,t){let n=e.indexOf(`
|
|
3
|
+
`,t);return n===-1?e.length:n}function applyLineEditorKey(e,t,n){let r=n?.multiline??!1;switch(t.type){case`text`:return insert(e,r?t.value:t.value.replaceAll(`
|
|
4
|
+
`,` `));case`newline`:return r?insert(e,`
|
|
5
|
+
`):void 0;case`backspace`:return backspace(e);case`delete`:return deleteForward(e);case`left`:return moveLeft(e);case`right`:return moveRight(e);case`home`:case`ctrl-a`:return moveHome(e);case`end`:case`ctrl-e`:return moveEnd(e);case`ctrl-k`:return killToEnd(e);case`ctrl-u`:return killToStart(e);case`ctrl-w`:return deleteWord(e);default:return}}function isWhitespace(e){return/^\s+$/u.test(e)}function visibleLine(t,n,i=`…`){let a=Math.max(1,n),{text:o,cursor:s}=t,c=graphemes(o),l=c.findIndex(e=>e.start===s),u=l===-1?c.length:l,d=c[u]?.text??``;if(inputTextWidth(o)<=a)return{before:o.slice(0,s),under:d,after:o.slice(s+d.length)};let f=u,p=u+ +(d.length>0),windowWidth=(t,n)=>{let r=c[t]?.start??o.length,a=c[n]?.start??o.length;return inputTextWidth(o.slice(r,a))+(t>0?inputTextWidth(i):0)+(n<c.length?inputTextWidth(i):0)},m=!0;for(;;){let e=f>0&&windowWidth(f-1,p)<=a,t=p<c.length&&windowWidth(f,p+1)<=a;if(!e&&!t)break;m&&e||!t?--f:p+=1,m=!m}let h=c[f]?.start??o.length,g=c[p]?.start??o.length;return{before:`${f>0?i:``}${o.slice(h,s)}`,under:d,after:`${o.slice(s+d.length,g)}${p<c.length?i:``}`}}function layoutPromptInput(e){let t=[],n=0,r=0,i=0;for(let a of e.text.split(`
|
|
6
|
+
`))e.cursor>=i&&e.cursor<=i+a.length&&(n=t.length,r=e.cursor-i),t.push({text:a,start:i}),i+=a.length+1;return{rows:t,caretRow:n,caretOffset:r}}function movePromptLine(n,r){let i=layoutPromptInput(n),a=r===`up`?i.caretRow-1:i.caretRow+1;if(a<0||a>=i.rows.length)return;let o=i.rows[i.caretRow],s=i.rows[a],c=inputTextWidth(o.text.slice(0,i.caretOffset));return{text:n.text,cursor:s.start+offsetAtVisibleColumn(s.text,c)}}var PromptHistory=class{#e=[];#t=0;#n=``;add(e){if(e.trim().length!==0){if(this.#e.at(-1)===e){this.#r();return}this.#e.push(e),this.#r()}}begin(e){this.#t=this.#e.length,this.#n=e}previous(e){if(this.#e.length!==0&&(this.#t===this.#e.length&&(this.#n=e),this.#t!==0))return--this.#t,this.#e[this.#t]}next(){if(!(this.#t>=this.#e.length))return this.#t+=1,this.#t===this.#e.length?this.#n:this.#e[this.#t]}#r(){this.#t=this.#e.length,this.#n=``}};export{EMPTY_LINE,PromptHistory,applyLineEditorKey,backspace,deleteForward,deleteWord,insert,killToEnd,killToStart,layoutPromptInput,lineOf,moveEnd,moveHome,moveLeft,movePromptLine,moveRight,visibleLine};
|
|
@@ -32,6 +32,8 @@ export declare class LiveRegion {
|
|
|
32
32
|
/** Hides the hardware cursor; the renderer draws its own caret. */
|
|
33
33
|
hideCursor(): void;
|
|
34
34
|
showCursor(): void;
|
|
35
|
+
/** Toggles bracketed paste through the original write, bypassing foreign-output capture. */
|
|
36
|
+
emitBracketedPaste(enabled: boolean): void;
|
|
35
37
|
/** Writes a newline through the bound (original) write. */
|
|
36
38
|
newline(): void;
|
|
37
39
|
/**
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const CLEAR_TO_END=`\x1B[0J`;var LiveRegion=class{#e;#t;#n=0;constructor(e,t){this.#e=e.write.bind(e),this.#t=t?.synchronized??!0}hideCursor(){this.#e(`\x1B[?25l`)}showCursor(){this.#e(`\x1B[?25h`)}newline(){this.#e(`
|
|
1
|
+
const CLEAR_TO_END=`\x1B[0J`;var LiveRegion=class{#e;#t;#n=0;constructor(e,t){this.#e=e.write.bind(e),this.#t=t?.synchronized??!0}hideCursor(){this.#e(`\x1B[?25l`)}showCursor(){this.#e(`\x1B[?25h`)}emitBracketedPaste(e){this.#e(e?`\x1B[?2004h`:`\x1B[?2004l`)}newline(){this.#e(`
|
|
2
2
|
`)}update(e){this.#r([],e)}flush(e,t){this.#r(e,t)}clear(){if(this.#n===0){this.#e(`\r`),this.#e(CLEAR_TO_END);return}this.#e(`${this.#i()}${CLEAR_TO_END}`),this.#n=0}clearAll(){this.#e(`\x1B[3J\x1B[2J\x1B[H`),this.#n=0}reset(){this.#n=0}#r(t,n){let r=this.#i()+CLEAR_TO_END+t.map(e=>`${e}\n`).join(``)+n.join(`
|
|
3
3
|
`);this.#e(this.#t?`[?2026h${r}[?2026l`:r),this.#n=n.length}#i(){return this.#n<=1?`\r`:`[${this.#n-1}F`}};export{LiveRegion};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type AgentInfoResult, type ConnectionAuthorizationOutcome, type InputRequest, Client, ClientSession } from "#client/index.js";
|
|
2
|
+
import { type DevBootProgressReporter } from "#internal/dev-boot-progress.js";
|
|
2
3
|
import { type PromptCommand } from "./prompt-commands.js";
|
|
3
4
|
import { type BootDetection } from "./setup-issues.js";
|
|
4
5
|
import type { SetupFlowRenderer } from "./setup-flow.js";
|
|
@@ -276,6 +277,8 @@ export type EveTUIRunnerOptions = TuiDisplayOptions & {
|
|
|
276
277
|
detectProjectIdentity?: typeof detectProjectIdentity;
|
|
277
278
|
/** Test seam for the off-critical-path boot login probe; defaults to the real one. */
|
|
278
279
|
getVercelAuthStatus?: typeof getVercelAuthStatus;
|
|
280
|
+
/** Reports phases from this runner's initial local-dev connection. */
|
|
281
|
+
onBootProgress?: DevBootProgressReporter;
|
|
279
282
|
};
|
|
280
283
|
export declare class EveTUIRunner {
|
|
281
284
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{pickAgentHeaderTip}from"./agent-header.js";import{formatPromptCommandHelp,parsePromptCommand}from"./prompt-commands.js";import{failureKey,formatFailureDetail,formatFailureMessage,formatGatewayAuthFailureNotice,isAbortLikeError,isGatewayAuthFailure,isInterruptedError}from"./errors.js";import{parseLogDisplayMode}from"./log-display-mode.js";import{BOOT_DETECTIONS,CLI_MISSING_SETUP_ISSUE,LOGIN_SETUP_ISSUE,detectSetupIssues,formatSetupIssuesLine,orderedSetupIssues}from"./setup-issues.js";import{TerminalRenderer}from"./terminal-renderer.js";import{createVercelStatusTracker}from"./vercel-status.js";import{toErrorMessage}from"#shared/errors.js";import{isCurrentTurnBoundaryEvent}from"#client/index.js";import{subscribeDevelopmentSandboxPrewarmLogs}from"#execution/sandbox/development-prewarm.js";import{createDevelopmentRuntimeArtifactSessionRefresher}from"#services/dev-client.js";import{getVercelAuthStatus}from"#setup/vercel-project.js";function authIssueForStatus(e){if(e===`logged-out`)return LOGIN_SETUP_ISSUE;if(e===`cli-missing`)return CLI_MISSING_SETUP_ISSUE}var EveTUIRunner=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p;#m;#h;#g;#_;#v=!1;#y=new AbortController;#b=!1;#x=[];#S;#C;#w=pickAgentHeaderTip();#T;#E=new Map;#D=new Map;#O=new Map;#k=new Map;#A=new Set;#j=!1;#M;constructor(e){if(this.#e=e.session,e.client!==void 0&&(this.#t=e.client),this.#n=createRenderer(e),this.#r=e.name??`eve`,this.#i=e.tools??`full`,this.#a=e.reasoning??`full`,this.#o=e.subagents??`full`,this.#s=e.connectionAuth??`full`,this.#c=e.assistantResponseStats??`tokensPerSecond`,this.#l=e.contextSize,this.#u=e.formatTransportError??toErrorMessage,e.initialInput!==void 0&&(this.#m=e.initialInput),e.appRoot!==void 0){this.#p=e.appRoot;let t={appRoot:e.appRoot,onChange:e=>this.#n.setVercelStatus?.(e)};e.detectProjectIdentity!==void 0&&(t.detectIdentity=e.detectProjectIdentity),this.#C=createVercelStatusTracker(t)}e.promptCommandHandler!==void 0&&(this.#h=e.promptCommandHandler),this.#g=e.bootDetections??BOOT_DETECTIONS,this.#_=e.getVercelAuthStatus??getVercelAuthStatus,e.serverUrl!==void 0&&(this.#f=e.serverUrl,this.#d=createDevelopmentRuntimeArtifactSessionRefresher({serverUrl:e.serverUrl}))}async#N(){let e=this.#f;if(e===void 0){await this.#R(void 0);return}let t;try{t=await this.#t?.info()}catch{t=void 0}this.#T=t;let n={name:this.#r,serverUrl:e};t!==void 0&&(n.info=t),this.#p!==void 0&&(n.tip=this.#w),this.#n.renderAgentHeader?.(n),await this.#R(t)}async run(){try{await this.#P()}finally{this.#v=!0,this.#y.abort(),this.#M?.(),this.#M=void 0,this.#n.shutdown?.(),this.#C?.dispose()}}async#P(){let e=this.#r,r,i,a=!1,o=!1,s=this.#m;for(await this.#N(),this.#H(),this.#C?.refreshIdentity();;){if(!o){if(r==null){if(!this.#n.readPrompt){if(a)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}let t={title:e};s!==void 0&&(t.initialDraft=s,s=void 0);try{r=await this.#I(t)}catch(e){if(isInterruptedError(e))return;throw e}if(r==null)return}let c=parsePromptCommand(r);if(c?.type===`exit`)return;if(c?.type===`new`){this.#F(),i=void 0,o=!1,r=void 0,this.#n.reset?.();continue}if(c?.type===`help`){this.#U(formatPromptCommandHelp()),i=void 0,o=!1,r=void 0;continue}if(c?.type===`loglevel`){this.#U(this.#W(c.argument)),i=void 0,o=!1,r=void 0;continue}if(c?.type===`extension`){try{let t=this.#h===void 0?{message:`/${c.name} is not available in this session.`}:await this.#h.handle(c,{renderer:this.#n,title:e});t?.message!==void 0&&this.#U(t.message),t?.vercelEffect!==void 0&&(this.#C?.applyEffect(t.vercelEffect),this.#b=!0,this.#V())}catch(e){if(isInterruptedError(e))return;throw e}i=void 0,r=void 0,o=!1;continue}a=!0}let c=await this.#L({prompt:o?void 0:r,inputResponses:i});try{await this.#n.renderStream(c,{title:e,submittedPrompt:r,continueSession:!!this.#n.readPrompt,tools:this.#i,reasoning:this.#a,subagents:this.#o,connectionAuth:this.#s,assistantResponseStats:this.#c,contextSize:this.#l});let t=c.turnState?.pendingApprovals??[],n=c.turnState?.pendingQuestions??[];if(t.length>0||n.length>0){let a=[];if(t.length>0){if(!this.#n.readToolApproval)throw Error(`Tool approval was requested, but the renderer does not support tool approval input.`);for(let n of t){let t=await this.#n.readToolApproval(n,{title:e});a.push({requestId:n.approvalId,optionId:t.approved?`approve`:`deny`}),this.#E.delete(n.approvalId)}}if(n.length>0){if(!this.#n.readInputQuestion)throw Error(`An interactive question was requested, but the renderer does not support input questions.`);for(let t of n){let n=toAgentTUIInputQuestion(t),r=await this.#n.readInputQuestion(n,{title:e});if(r===void 0)continue;let i={requestId:t.requestId};r.optionId!==void 0&&(i.optionId=r.optionId),r.text!==void 0&&(i.text=r.text),a.push(i),this.#E.delete(t.requestId)}}o=!0,i=a,r=void 0;continue}c.turnState&&c.turnState.boundaryEvent===void 0&&(this.#j=!0)}catch(e){if(isInterruptedError(e))return;throw e}o=!1,i=void 0,r=void 0,this.#j&&(this.#j=!1,this.#F(),this.#n.renderNotice?.(`Session ended — started a new session. Earlier context was cleared.`))}}#F(){for(let e of this.#O.values())e.abort();this.#O.clear(),this.#D.clear(),this.#E.clear(),this.#k.clear(),this.#A.clear(),this.#t&&(this.#e=this.#t.session()),this.#d?.clear()}async#I(e){if(!this.#n.readPrompt)return;let t=this.#n.readPrompt(e),n=this.#t,r=this.#d;if(n===void 0||r===void 0)return await t;let i=!1,a=!1,o,refresh=async()=>{if(!(i||a)){a=!0;try{this.#e=await r.refreshIdle({createSession:()=>n.session(),onRuntimeArtifactsChanged:()=>this.#G(),session:this.#e})}finally{a=!1}}},startRefresh=()=>{if(i||a)return;let e=refresh().finally(()=>{o===e&&(o=void 0)});o=e};startRefresh();let s=setInterval(()=>{startRefresh()},500);s.unref?.();try{return await t}finally{i=!0,clearInterval(s),await o}}async#L(e){let t=new AbortController,n={signal:t.signal};e.prompt!==void 0&&(n.message=e.prompt),e.inputResponses!==void 0&&e.inputResponses.length>0&&(n.inputResponses=e.inputResponses);let r;try{let e=this.#t;e!==void 0&&this.#d!==void 0&&(this.#e=await this.#d.refresh({createSession:()=>e.session(),inputResponses:n.inputResponses,message:n.message,onRuntimeArtifactsChanged:()=>this.#G(),session:this.#e})),n.message!==void 0&&(n.inputResponses?.length??0)===0&&this.#n.flushDelayedDevBuildErrors?.(),r=await this.#e.send(n)}catch(e){if(isInterruptedError(e))throw e;return this.#j=!0,{events:errorOnlyTUIStream({errorText:this.#u(e)}),turnState:createTurnState()}}let i=createTurnState();return{abort:()=>t.abort(),events:eveEventsToTUIStream({events:r,pendingInputRequests:this.#E,subagentRuns:this.#D,turnState:i,onSubagentCalled:e=>this.#Y(e),onSubagentCompleted:e=>this.#Z(e),onConnectionAuthRequired:e=>this.#K(e),onConnectionAuthCompleted:e=>this.#q(e),onTerminalFailure:()=>{this.#j=!0},failureOverride:this.#p===void 0?void 0:e=>isGatewayAuthFailure(e)?formatGatewayAuthFailureNotice(e):void 0}),turnState:i}}async#R(e){if(this.#p===void 0||this.#n.renderSetupWarning===void 0)return;let t={appRoot:this.#p,env:process.env};e!==void 0&&(t.info=e),this.#x=await detectSetupIssues(t,this.#g),this.#z(),this.#B()}#z(){let e=orderedSetupIssues(this.#x,this.#S);e.length>0?this.#n.renderSetupWarning?.(formatSetupIssuesLine(e)):this.#n.clearSetupWarning?.()}async#B(){let e=this.#p;if(e===void 0)return;let t;try{t=await this.#_(e,{signal:this.#y.signal})}catch{return}this.#v||this.#b||(this.#S=authIssueForStatus(t),this.#z())}async#V(){let e=this.#p;if(e===void 0||this.#n.renderSetupWarning===void 0)return;let t={appRoot:e,env:process.env};this.#T!==void 0&&(t.info=this.#T);try{this.#x=await detectSetupIssues(t,this.#g);let n=await this.#_(e,{signal:this.#y.signal});this.#S=authIssueForStatus(n)}catch{return}this.#v||this.#z()}#H(){this.#p===void 0||this.#n.renderSandboxLog===void 0||this.#M===void 0&&(this.#M=subscribeDevelopmentSandboxPrewarmLogs({appRoot:this.#p,log:e=>this.#n.renderSandboxLog?.(e)}))}#U(e){if(this.#n.renderCommandResult!==void 0){this.#n.renderCommandResult(e);return}this.#n.renderNotice?.(e)}#W(e){let t=this.#n;if(t.logDisplayMode===void 0||t.setLogDisplayMode===void 0)return`/loglevel is not available in this session.`;if(e===``)return`Logs: ${t.logDisplayMode()}. Use /loglevel all|stderr|sandbox|none — logs stay buffered, so switching also hides or restores past lines.`;let n=parseLogDisplayMode(e);if(n===void 0)return`Unknown log level "${e}". Use all, stderr, sandbox, or none.`;if(n===t.logDisplayMode())return`Logs already set to ${n}.`;switch(t.setLogDisplayMode(n),n){case`none`:return`Logs hidden. Output stays buffered — /loglevel all restores it.`;case`stderr`:return`Showing stderr logs only.`;case`sandbox`:return`Showing sandbox logs only.`;case`all`:return`Showing all logs.`}}async#G(){let e=this.#T,t;try{t=await this.#t?.info()}catch{t=void 0}if(t!==void 0&&(this.#T=t,this.#f!==void 0)){let e={info:t,name:this.#r,serverUrl:this.#f};this.#p!==void 0&&(e.tip=this.#w),this.#n.renderAgentHeader?.(e)}(!this.#n.renderAgentHeader||t===void 0)&&this.#n.renderNotice?.(formatAgentUpdateNotice(e,t))}#K(e){let t={name:e.data.name,description:e.data.description,state:`required`};e.data.authorization!==void 0&&(t.challenge=e.data.authorization),e.data.webhookUrl!==void 0&&(t.webhookUrl=e.data.webhookUrl),this.#k.set(e.data.name,t),this.#J(t)}#q(e){let t=this.#k.get(e.data.name)??{name:e.data.name,description:``,state:e.data.outcome};t.state=e.data.outcome,e.data.reason!==void 0&&(t.reason=e.data.reason),this.#k.set(e.data.name,t),this.#A.delete(e.data.name),this.#J(t),this.#n.setConnectionAuthPendingCount?.(this.#A.size)}#J(e){let t={name:e.name,description:e.description,state:e.state};e.challenge!==void 0&&(t.challenge=e.challenge),e.reason!==void 0&&(t.reason=e.reason),this.#n.upsertConnectionAuth?.(t)}#Y(e){let t=e.data.callId;if(this.#O.has(t))return;let n=this.#t;if(!n)return;let r=new AbortController;this.#O.set(t,r),(async()=>{try{let i=n.session({sessionId:e.data.childSessionId,streamIndex:0}).stream({signal:r.signal});for await(let e of i)if(r.signal.aborted||(this.#Q(t,e),isCurrentTurnBoundaryEvent(e)))break}catch(e){if(!isAbortLikeError(e)){let n=toErrorMessage(e),r=this.#D.get(t);if(r){let{key:e,step:i}=openCurrentSubagentSection(r);i.message=i.message?`${i.message}\n\nstream error: ${n}`:`stream error: ${n}`,i.finalized=!0,r.currentSectionKey=null,this.#n.upsertSubagentStep?.({callId:t,subagentName:r.name,sectionKey:e,reasoning:i.reasoning,message:i.message,finalized:!0})}}}finally{this.#O.delete(t)}})()}#X(e,t,n){let r=t.tools.get(n.childCallId),i=r??{toolName:n.toolName,input:n.input,status:n.status};if(r){let e={"approval-requested":0,executing:1,done:2,failed:2};e[n.status]>e[r.status]&&(r.status=n.status),r.input=n.input}else t.tools.set(n.childCallId,i);this.#n.markChildToolCallId?.(n.childCallId),this.#n.upsertSubagentTool?.({callId:e,subagentName:t.name,childCallId:n.childCallId,toolName:i.toolName,input:i.input,status:i.status})}#Z(e){let t=this.#D.get(e);if(t){for(let[n,r]of t.steps)r.finalized||(r.finalized=!0,this.#n.upsertSubagentStep?.({callId:e,subagentName:t.name,sectionKey:n,reasoning:r.reasoning,message:r.message,finalized:!0}));t.currentSectionKey=null}}#Q(e,t){let n=this.#D.get(e);if(!n)return;let r=this.#n,emit=(t,i)=>{r.upsertSubagentStep?.({callId:e,subagentName:n.name,sectionKey:t,reasoning:i.reasoning,message:i.message,finalized:i.finalized})},finalizeCurrent=()=>{if(n.currentSectionKey===null)return;let e=n.steps.get(n.currentSectionKey);e&&(e.finalized=!0,emit(n.currentSectionKey,e)),n.currentSectionKey=null};switch(t.type){case`reasoning.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.reasoning+=t.data.reasoningDelta,emit(e,r);break}case`reasoning.completed`:break;case`message.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.message+=t.data.messageDelta,emit(e,r);break}case`message.completed`:{let{key:e,step:r}=openCurrentSubagentSection(n);t.data.message!==null&&r.message.length===0&&(r.message=t.data.message),r.finalized=!0,emit(e,r),n.currentSectionKey=null;break}case`step.completed`:finalizeCurrent();break;case`actions.requested`:finalizeCurrent();for(let r of t.data.actions)r.kind===`tool-call`&&this.#X(e,n,{childCallId:r.callId,toolName:r.toolName,input:r.input,status:`executing`});break;case`input.requested`:finalizeCurrent();for(let r of t.data.requests)r.action.kind===`tool-call`&&this.#X(e,n,{childCallId:r.action.callId,toolName:r.action.toolName,input:r.action.input,status:`approval-requested`});break;case`action.result`:{let i=t.data.result;if(i.kind!==`tool-result`)break;let a=n.tools.get(i.callId);if(!a)break;t.data.status===`failed`?(a.status=`failed`,a.errorText=formatActionResultError(t)):(a.status=`done`,a.output=i.output);let o={callId:e,subagentName:n.name,childCallId:i.callId,toolName:a.toolName,input:a.input,status:a.status};a.output!==void 0&&(o.output=a.output),a.errorText!==void 0&&(o.errorText=a.errorText),r.upsertSubagentTool?.(o);break}default:break}}};function createRenderer(e){return e.renderer?e.renderer:new TerminalRenderer({tools:e.tools,reasoning:e.reasoning,subagents:e.subagents,connectionAuth:e.connectionAuth,assistantResponseStats:e.assistantResponseStats,contextSize:e.contextSize,logs:e.logs,input:e.userInput,output:e.screen})}function formatAgentUpdateNotice(e,t){let n=e?.agent.model.id,r=t?.agent.model.id;return n!==void 0&&r!==void 0&&n!==r?`Agent updated: Model ${n} -> ${r}`:`Agent updated.`}async function*eveEventsToTUIStream(e){let{events:t,pendingInputRequests:n,subagentRuns:r,turnState:i,onSubagentCalled:a,onSubagentCompleted:o,onConnectionAuthRequired:s,onConnectionAuthCompleted:c,onTerminalFailure:l,failureOverride:u}=e,d=new Map,f=new Map,p=0,m=new Set,h=new Set,g=new Set,_=new Set,v=!1,y=!1,b;for await(let e of t)if(!(y&&isPostTurnVisibleEvent(e)))switch(e.type){case`session.started`:case`turn.started`:case`message.received`:break;case`step.started`:p+=1,yield{type:`step-start`};break;case`step.completed`:{let t=e;b=t.data.usage,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`step-finish`,usage:t.data.usage};break}case`message.appended`:{let t=e,n=textPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(d,n),i=t.data.messageSoFar;if(r.completed){if(r.text.startsWith(i)||p<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`assistant-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`message.completed`:{let t=textPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(d,t),r=e.data.message;if(n.completed){if(r===null||r===n.text||p<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=p,yield{type:`assistant-complete`,id:partGenerationId(t,n.generation),text:r};break}let i=partGenerationId(t,n.generation);if(r!==null){if(n.text.length===0)n.text=r,n.completed=!0,n.completedEpoch=p,yield{type:`assistant-complete`,id:i,text:r};else if(r.startsWith(n.text)){let e=r.slice(n.text.length);e.length>0&&(yield{type:`assistant-delta`,id:i,delta:e}),n.text=r,n.completed=!0,n.completedEpoch=p,yield{type:`assistant-complete`,id:i}}}else n.text.length>0&&(n.completed=!0,n.completedEpoch=p,yield{type:`assistant-complete`,id:i});break}case`reasoning.appended`:{let t=e,n=reasoningPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(f,n),i=t.data.reasoningSoFar;if(r.completed){if(r.text.startsWith(i)||p<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`reasoning-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`reasoning.completed`:{let t=reasoningPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(f,t),r=e.data.reasoning;if(n.completed){if(r.length===0||r===n.text||n.text.startsWith(r)||p<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=p;let e=partGenerationId(t,n.generation);yield{type:`reasoning-delta`,id:e,delta:r},yield{type:`reasoning-complete`,id:e};break}let i=partGenerationId(t,n.generation);if(n.text.length===0&&r.length>0)n.text=r,yield{type:`reasoning-delta`,id:i,delta:r};else if(r.length>0&&!r.startsWith(n.text))break;n.completed=!0,n.completedEpoch=p,yield{type:`reasoning-complete`,id:i};break}case`actions.requested`:{let t=e.data,n=t.actions.filter(e=>e.kind===`tool-call`);if(n.length===0)break;let r=toolBatchKey(`actions.requested`,t.turnId,t.stepIndex,n);if(g.has(r)){for(let e of n)m.has(e.callId)||h.add(e.callId);break}g.add(r);for(let e of n)m.has(e.callId)||(m.add(e.callId),yield{type:`tool-call`,toolCallId:e.callId,toolName:e.toolName,input:e.input});break}case`input.requested`:{let t=e.data,r=t.requests.filter(e=>e.action.kind===`tool-call`);if(r.length===0)break;let a=inputRequestBatchKey(t.turnId,t.stepIndex,r);if(g.has(a)){for(let e of r)m.has(e.action.callId)||h.add(e.action.callId);break}g.add(a);for(let e of r){let t=e.action.callId;if(m.has(t)||(m.add(t),yield{type:`tool-call`,toolCallId:t,toolName:e.action.toolName,input:e.action.input}),n.set(e.requestId,e),isQuestionRequest(e)){upsertPendingQuestion(i,e);continue}upsertPendingApproval(i,e),yield{type:`tool-approval-request`,approvalId:e.requestId,toolCallId:t}}break}case`action.result`:{let t=e;if(t.data.result.kind!==`tool-result`)break;let n=t.data.result.callId;if(h.has(n)||!m.has(n))break;t.data.status===`failed`?yield{type:`tool-error`,toolCallId:n,errorText:formatActionResultError(t)}:yield{type:`tool-result`,toolCallId:n,output:t.data.result.output};break}case`step.failed`:case`turn.failed`:{let t=toFailureEvent(e,_,u);t&&(yield t);break}case`session.failed`:{i.sawSessionFailure=!0,l?.(e);let t=toFailureEvent(e,_,u);t&&(yield t),i.boundaryEvent=e.type,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b},v=!0;return}case`session.waiting`:case`session.completed`:i.boundaryEvent=e.type,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b},v=!0;return;case`turn.completed`:y=!0,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p);break;case`subagent.called`:{let t=e;if(!r.has(t.data.callId))r.set(t.data.callId,{name:t.data.name,steps:new Map,currentSectionKey:null,nextSectionKey:0,tools:new Map});else{let e=r.get(t.data.callId);e&&(e.name=t.data.name)}a?.(t);break}case`subagent.started`:case`subagent.event`:break;case`subagent.completed`:o?.(e.data.callId);break;case`authorization.required`:s?.(e);break;case`authorization.completed`:c?.(e);break;default:break}v||(yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b})}async function*errorOnlyTUIStream(e){yield{type:`error`,errorText:e.errorText},yield{type:`finish`}}function createTurnState(){return{pendingApprovals:[],pendingQuestions:[],sawSessionFailure:!1}}function upsertPendingApproval(e,t){let n=toAgentTUIToolApprovalRequest(t),r=e.pendingApprovals.findIndex(e=>e.approvalId===n.approvalId);r===-1?e.pendingApprovals.push(n):e.pendingApprovals[r]=n}function toAgentTUIToolApprovalRequest(e){return{approvalId:e.requestId,toolCallId:e.action.callId,toolName:e.action.toolName,input:e.action.input}}function upsertPendingQuestion(e,t){let n=e.pendingQuestions.findIndex(e=>e.requestId===t.requestId);n===-1?e.pendingQuestions.push(t):e.pendingQuestions[n]=t}function textPartId(e,t){return`text:${e}:${t}`}function reasoningPartId(e,t){return`reasoning:${e}:${t}`}function partStateFor(e,t){let n=e.get(t);return n===void 0&&(n={generation:0,text:``,completed:!1,completedEpoch:0},e.set(t,n)),n}function partGenerationId(e,t){return t===0?e:`${e}#${t}`}function*closeOpenParts(e,t,n){for(let[r,i]of e)i.completed||i.text.length===0||(i.completed=!0,i.completedEpoch=n,yield{type:t,id:partGenerationId(r,i.generation)})}function isPostTurnVisibleEvent(e){switch(e.type){case`actions.requested`:case`authorization.completed`:case`authorization.required`:case`input.requested`:case`message.appended`:case`message.completed`:case`reasoning.appended`:case`reasoning.completed`:case`result.completed`:case`step.completed`:case`step.failed`:case`step.started`:case`subagent.called`:case`subagent.completed`:case`subagent.event`:case`subagent.started`:case`turn.completed`:case`turn.failed`:return!0;default:return!1}}function toolBatchKey(e,t,n,r){return`${e}:${t}:${String(n)}:${stableStringify(r.map(e=>({input:e.input,toolName:e.toolName})))}`}function inputRequestBatchKey(e,t,n){return toolBatchKey(`input.requested`,e,t,n.map(e=>({input:e.action.input,toolName:e.action.toolName})))}function stableStringify(e){return JSON.stringify(toStableJson(e))??`undefined`}function toStableJson(e,t=new WeakSet){if(typeof e!=`object`||!e)return e;if(t.has(e))return`[Circular]`;if(t.add(e),Array.isArray(e))return e.map(e=>toStableJson(e,t));let n=e,r={};for(let e of Object.keys(n).sort())r[e]=toStableJson(n[e],t);return r}function formatActionResultError(e){if(e.data.error?.message)return e.data.error.message;let t=e.data.result.output;if(typeof t==`string`)return t;try{return JSON.stringify(t)}catch{return`Tool execution failed.`}}function toFailureEvent(e,t,n){let o=failureKey(e);if(t.has(o))return;t.add(o);let s=n?.(e),c={type:`error`,errorText:s??formatFailureMessage(e)};if(s!==void 0)return c;let l=formatFailureDetail(e);return l!==void 0&&(c.detail=l),c}function isQuestionRequest(e){return e.display===`select`||e.display===`text`?!0:e.display===`confirmation`?!1:e.options!==void 0&&e.options.length>0}function toAgentTUIInputQuestion(e){let t=e.display===`text`?`text`:e.display===`select`||e.options!==void 0&&e.options.length>0?`select`:`text`,n={requestId:e.requestId,prompt:e.prompt,display:t};return e.options!==void 0&&(n.options=e.options.map(e=>{let t={id:e.id,label:e.label};return e.description!==void 0&&(t.description=e.description),e.style!==void 0&&(t.style=e.style),t})),e.allowFreeform!==void 0&&(n.allowFreeform=e.allowFreeform),n}function openCurrentSubagentSection(e){e.currentSectionKey===null&&(e.currentSectionKey=e.nextSectionKey++,e.steps.set(e.currentSectionKey,{reasoning:``,message:``,finalized:!1}));let t=e.steps.get(e.currentSectionKey);if(!t)throw Error(`invariant: subagent section state missing for current key`);return{key:e.currentSectionKey,step:t}}export{EveTUIRunner,parsePromptCommand};
|
|
1
|
+
import{pickAgentHeaderTip}from"./agent-header.js";import{formatPromptCommandHelp,parsePromptCommand}from"./prompt-commands.js";import{failureKey,formatFailureDetail,formatFailureMessage,formatGatewayAuthFailureNotice,isAbortLikeError,isGatewayAuthFailure,isInterruptedError}from"./errors.js";import{parseLogDisplayMode}from"./log-display-mode.js";import{BOOT_DETECTIONS,CLI_MISSING_SETUP_ISSUE,LOGIN_SETUP_ISSUE,detectSetupIssues,formatSetupIssuesLine,orderedSetupIssues}from"./setup-issues.js";import{TerminalRenderer}from"./terminal-renderer.js";import{createVercelStatusTracker}from"./vercel-status.js";import{toErrorMessage}from"#shared/errors.js";import{isCurrentTurnBoundaryEvent}from"#client/index.js";import{subscribeDevelopmentSandboxPrewarmLogs}from"#execution/sandbox/development-prewarm.js";import{createDevelopmentRuntimeArtifactSessionRefresher}from"#services/dev-client.js";import{devBootPhase}from"#internal/dev-boot-progress.js";import{getVercelAuthStatus}from"#setup/vercel-project.js";function authIssueForStatus(e){if(e===`logged-out`)return LOGIN_SETUP_ISSUE;if(e===`cli-missing`)return CLI_MISSING_SETUP_ISSUE}var EveTUIRunner=class{#e;#t;#n;#r;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p;#m;#h;#g;#_;#v;#y=!1;#b=new AbortController;#x=!1;#S=[];#C;#w;#T=pickAgentHeaderTip();#E;#D=new Map;#O=new Map;#k=new Map;#A=new Map;#j=new Set;#M=!1;#N;constructor(e){if(this.#e=e.session,e.client!==void 0&&(this.#t=e.client),this.#n=createRenderer(e),this.#r=e.name??`eve`,this.#i=e.tools??`full`,this.#a=e.reasoning??`full`,this.#o=e.subagents??`full`,this.#s=e.connectionAuth??`full`,this.#c=e.assistantResponseStats??`tokensPerSecond`,this.#l=e.contextSize,this.#u=e.formatTransportError??toErrorMessage,e.initialInput!==void 0&&(this.#m=e.initialInput),e.appRoot!==void 0){this.#p=e.appRoot;let t={appRoot:e.appRoot,onChange:e=>this.#n.setVercelStatus?.(e)};e.detectProjectIdentity!==void 0&&(t.detectIdentity=e.detectProjectIdentity),this.#w=createVercelStatusTracker(t)}e.promptCommandHandler!==void 0&&(this.#h=e.promptCommandHandler),this.#g=e.bootDetections??BOOT_DETECTIONS,this.#_=e.getVercelAuthStatus??getVercelAuthStatus,e.onBootProgress!==void 0&&(this.#v=e.onBootProgress),e.serverUrl!==void 0&&(this.#f=e.serverUrl,this.#d=createDevelopmentRuntimeArtifactSessionRefresher({serverUrl:e.serverUrl}))}async#P(){let e=this.#f;if(e===void 0){this.#F(),await this.#B(void 0);return}let t;try{t=await devBootPhase(`connecting to agent`,()=>this.#t?this.#t.info():Promise.resolve(void 0),this.#v)}catch{t=void 0}this.#E=t;let n={name:this.#r,serverUrl:e};t!==void 0&&(n.info=t),this.#p!==void 0&&(n.tip=this.#T),this.#F(),this.#n.renderAgentHeader?.(n),await this.#B(t)}#F(){let e=this.#v;this.#v=void 0,e?.({type:`before-first-paint`})}async run(){try{await this.#I()}finally{this.#y=!0,this.#b.abort(),this.#N?.(),this.#N=void 0,this.#n.shutdown?.(),this.#w?.dispose()}}async#I(){let e=this.#r,r,i,a=!1,o=!1,s=this.#m;for(await this.#P(),this.#W(),this.#w?.refreshIdentity();;){if(!o){if(r==null){if(!this.#n.readPrompt){if(a)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}let t={title:e};s!==void 0&&(t.initialDraft=s,s=void 0);try{r=await this.#R(t)}catch(e){if(isInterruptedError(e))return;throw e}if(r==null)return}let c=parsePromptCommand(r);if(c?.type===`exit`)return;if(c?.type===`new`){this.#L(),i=void 0,o=!1,r=void 0,this.#n.reset?.();continue}if(c?.type===`help`){this.#G(formatPromptCommandHelp()),i=void 0,o=!1,r=void 0;continue}if(c?.type===`loglevel`){this.#G(this.#K(c.argument)),i=void 0,o=!1,r=void 0;continue}if(c?.type===`extension`){try{let t=this.#h===void 0?{message:`/${c.name} is not available in this session.`}:await this.#h.handle(c,{renderer:this.#n,title:e});t?.message!==void 0&&this.#G(t.message),t?.vercelEffect!==void 0&&(this.#w?.applyEffect(t.vercelEffect),this.#x=!0,this.#U())}catch(e){if(isInterruptedError(e))return;throw e}i=void 0,r=void 0,o=!1;continue}a=!0}let c=await this.#z({prompt:o?void 0:r,inputResponses:i});try{await this.#n.renderStream(c,{title:e,submittedPrompt:r,continueSession:!!this.#n.readPrompt,tools:this.#i,reasoning:this.#a,subagents:this.#o,connectionAuth:this.#s,assistantResponseStats:this.#c,contextSize:this.#l});let t=c.turnState?.pendingApprovals??[],n=c.turnState?.pendingQuestions??[];if(t.length>0||n.length>0){let a=[];if(t.length>0){if(!this.#n.readToolApproval)throw Error(`Tool approval was requested, but the renderer does not support tool approval input.`);for(let n of t){let t=await this.#n.readToolApproval(n,{title:e});a.push({requestId:n.approvalId,optionId:t.approved?`approve`:`deny`}),this.#D.delete(n.approvalId)}}if(n.length>0){if(!this.#n.readInputQuestion)throw Error(`An interactive question was requested, but the renderer does not support input questions.`);for(let t of n){let n=toAgentTUIInputQuestion(t),r=await this.#n.readInputQuestion(n,{title:e});if(r===void 0)continue;let i={requestId:t.requestId};r.optionId!==void 0&&(i.optionId=r.optionId),r.text!==void 0&&(i.text=r.text),a.push(i),this.#D.delete(t.requestId)}}o=!0,i=a,r=void 0;continue}c.turnState&&c.turnState.boundaryEvent===void 0&&(this.#M=!0)}catch(e){if(isInterruptedError(e))return;throw e}o=!1,i=void 0,r=void 0,this.#M&&(this.#M=!1,this.#L(),this.#n.renderNotice?.(`Session ended — started a new session. Earlier context was cleared.`))}}#L(){for(let e of this.#k.values())e.abort();this.#k.clear(),this.#O.clear(),this.#D.clear(),this.#A.clear(),this.#j.clear(),this.#t&&(this.#e=this.#t.session()),this.#d?.clear()}async#R(e){if(!this.#n.readPrompt)return;let t=this.#n.readPrompt(e),n=this.#t,r=this.#d;if(n===void 0||r===void 0)return await t;let i=!1,a=!1,o,refresh=async()=>{if(!(i||a)){a=!0;try{this.#e=await r.refreshIdle({createSession:()=>n.session(),onRuntimeArtifactsChanged:()=>this.#q(),session:this.#e})}finally{a=!1}}},startRefresh=()=>{if(i||a)return;let e=refresh().finally(()=>{o===e&&(o=void 0)});o=e};startRefresh();let s=setInterval(()=>{startRefresh()},500);s.unref?.();try{return await t}finally{i=!0,clearInterval(s),await o}}async#z(e){let t=new AbortController,n={signal:t.signal};e.prompt!==void 0&&(n.message=e.prompt),e.inputResponses!==void 0&&e.inputResponses.length>0&&(n.inputResponses=e.inputResponses);let r;try{let e=this.#t;e!==void 0&&this.#d!==void 0&&(this.#e=await this.#d.refresh({createSession:()=>e.session(),inputResponses:n.inputResponses,message:n.message,onRuntimeArtifactsChanged:()=>this.#q(),session:this.#e})),n.message!==void 0&&(n.inputResponses?.length??0)===0&&this.#n.flushDelayedDevBuildErrors?.(),r=await this.#e.send(n)}catch(e){if(isInterruptedError(e))throw e;return this.#M=!0,{events:errorOnlyTUIStream({errorText:this.#u(e)}),turnState:createTurnState()}}let i=createTurnState();return{abort:()=>t.abort(),events:eveEventsToTUIStream({events:r,pendingInputRequests:this.#D,subagentRuns:this.#O,turnState:i,onSubagentCalled:e=>this.#Z(e),onSubagentCompleted:e=>this.#$(e),onConnectionAuthRequired:e=>this.#J(e),onConnectionAuthCompleted:e=>this.#Y(e),onTerminalFailure:()=>{this.#M=!0},failureOverride:this.#p===void 0?void 0:e=>isGatewayAuthFailure(e)?formatGatewayAuthFailureNotice(e):void 0}),turnState:i}}async#B(e){if(this.#p===void 0||this.#n.renderSetupWarning===void 0)return;let t={appRoot:this.#p,env:process.env};e!==void 0&&(t.info=e),this.#S=await detectSetupIssues(t,this.#g),this.#V(),this.#H()}#V(){let e=orderedSetupIssues(this.#S,this.#C);e.length>0?this.#n.renderSetupWarning?.(formatSetupIssuesLine(e)):this.#n.clearSetupWarning?.()}async#H(){let e=this.#p;if(e===void 0)return;let t;try{t=await this.#_(e,{signal:this.#b.signal})}catch{return}this.#y||this.#x||(this.#C=authIssueForStatus(t),this.#V())}async#U(){let e=this.#p;if(e===void 0||this.#n.renderSetupWarning===void 0)return;let t={appRoot:e,env:process.env};this.#E!==void 0&&(t.info=this.#E);try{this.#S=await detectSetupIssues(t,this.#g);let n=await this.#_(e,{signal:this.#b.signal});this.#C=authIssueForStatus(n)}catch{return}this.#y||this.#V()}#W(){this.#p===void 0||this.#n.renderSandboxLog===void 0||this.#N===void 0&&(this.#N=subscribeDevelopmentSandboxPrewarmLogs({appRoot:this.#p,log:e=>this.#n.renderSandboxLog?.(e)}))}#G(e){if(this.#n.renderCommandResult!==void 0){this.#n.renderCommandResult(e);return}this.#n.renderNotice?.(e)}#K(e){let t=this.#n;if(t.logDisplayMode===void 0||t.setLogDisplayMode===void 0)return`/loglevel is not available in this session.`;if(e===``)return`Logs: ${t.logDisplayMode()}. Use /loglevel all|stderr|sandbox|none — logs stay buffered, so switching also hides or restores past lines.`;let n=parseLogDisplayMode(e);if(n===void 0)return`Unknown log level "${e}". Use all, stderr, sandbox, or none.`;if(n===t.logDisplayMode())return`Logs already set to ${n}.`;switch(t.setLogDisplayMode(n),n){case`none`:return`Logs hidden. Output stays buffered — /loglevel all restores it.`;case`stderr`:return`Showing stderr logs only.`;case`sandbox`:return`Showing sandbox logs only.`;case`all`:return`Showing all logs.`}}async#q(){let e=this.#E,t;try{t=await this.#t?.info()}catch{t=void 0}if(t!==void 0&&(this.#E=t,this.#f!==void 0)){let e={info:t,name:this.#r,serverUrl:this.#f};this.#p!==void 0&&(e.tip=this.#T),this.#n.renderAgentHeader?.(e)}(!this.#n.renderAgentHeader||t===void 0)&&this.#n.renderNotice?.(formatAgentUpdateNotice(e,t))}#J(e){let t={name:e.data.name,description:e.data.description,state:`required`};e.data.authorization!==void 0&&(t.challenge=e.data.authorization),e.data.webhookUrl!==void 0&&(t.webhookUrl=e.data.webhookUrl),this.#A.set(e.data.name,t),this.#X(t)}#Y(e){let t=this.#A.get(e.data.name)??{name:e.data.name,description:``,state:e.data.outcome};t.state=e.data.outcome,e.data.reason!==void 0&&(t.reason=e.data.reason),this.#A.set(e.data.name,t),this.#j.delete(e.data.name),this.#X(t),this.#n.setConnectionAuthPendingCount?.(this.#j.size)}#X(e){let t={name:e.name,description:e.description,state:e.state};e.challenge!==void 0&&(t.challenge=e.challenge),e.reason!==void 0&&(t.reason=e.reason),this.#n.upsertConnectionAuth?.(t)}#Z(e){let t=e.data.callId;if(this.#k.has(t))return;let n=this.#t;if(!n)return;let r=new AbortController;this.#k.set(t,r),(async()=>{try{let i=n.session({sessionId:e.data.childSessionId,streamIndex:0}).stream({signal:r.signal});for await(let e of i)if(r.signal.aborted||(this.#ee(t,e),isCurrentTurnBoundaryEvent(e)))break}catch(e){if(!isAbortLikeError(e)){let n=toErrorMessage(e),r=this.#O.get(t);if(r){let{key:e,step:i}=openCurrentSubagentSection(r);i.message=i.message?`${i.message}\n\nstream error: ${n}`:`stream error: ${n}`,i.finalized=!0,r.currentSectionKey=null,this.#n.upsertSubagentStep?.({callId:t,subagentName:r.name,sectionKey:e,reasoning:i.reasoning,message:i.message,finalized:!0})}}}finally{this.#k.delete(t)}})()}#Q(e,t,n){let r=t.tools.get(n.childCallId),i=r??{toolName:n.toolName,input:n.input,status:n.status};if(r){let e={"approval-requested":0,executing:1,done:2,failed:2};e[n.status]>e[r.status]&&(r.status=n.status),r.input=n.input}else t.tools.set(n.childCallId,i);this.#n.markChildToolCallId?.(n.childCallId),this.#n.upsertSubagentTool?.({callId:e,subagentName:t.name,childCallId:n.childCallId,toolName:i.toolName,input:i.input,status:i.status})}#$(e){let t=this.#O.get(e);if(t){for(let[n,r]of t.steps)r.finalized||(r.finalized=!0,this.#n.upsertSubagentStep?.({callId:e,subagentName:t.name,sectionKey:n,reasoning:r.reasoning,message:r.message,finalized:!0}));t.currentSectionKey=null}}#ee(e,t){let n=this.#O.get(e);if(!n)return;let r=this.#n,emit=(t,i)=>{r.upsertSubagentStep?.({callId:e,subagentName:n.name,sectionKey:t,reasoning:i.reasoning,message:i.message,finalized:i.finalized})},finalizeCurrent=()=>{if(n.currentSectionKey===null)return;let e=n.steps.get(n.currentSectionKey);e&&(e.finalized=!0,emit(n.currentSectionKey,e)),n.currentSectionKey=null};switch(t.type){case`reasoning.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.reasoning+=t.data.reasoningDelta,emit(e,r);break}case`reasoning.completed`:break;case`message.appended`:{let{key:e,step:r}=openCurrentSubagentSection(n);r.message+=t.data.messageDelta,emit(e,r);break}case`message.completed`:{let{key:e,step:r}=openCurrentSubagentSection(n);t.data.message!==null&&r.message.length===0&&(r.message=t.data.message),r.finalized=!0,emit(e,r),n.currentSectionKey=null;break}case`step.completed`:finalizeCurrent();break;case`actions.requested`:finalizeCurrent();for(let r of t.data.actions)r.kind===`tool-call`&&this.#Q(e,n,{childCallId:r.callId,toolName:r.toolName,input:r.input,status:`executing`});break;case`input.requested`:finalizeCurrent();for(let r of t.data.requests)r.action.kind===`tool-call`&&this.#Q(e,n,{childCallId:r.action.callId,toolName:r.action.toolName,input:r.action.input,status:`approval-requested`});break;case`action.result`:{let i=t.data.result;if(i.kind!==`tool-result`)break;let a=n.tools.get(i.callId);if(!a)break;t.data.status===`failed`?(a.status=`failed`,a.errorText=formatActionResultError(t)):(a.status=`done`,a.output=i.output);let o={callId:e,subagentName:n.name,childCallId:i.callId,toolName:a.toolName,input:a.input,status:a.status};a.output!==void 0&&(o.output=a.output),a.errorText!==void 0&&(o.errorText=a.errorText),r.upsertSubagentTool?.(o);break}default:break}}};function createRenderer(e){return e.renderer?e.renderer:new TerminalRenderer({tools:e.tools,reasoning:e.reasoning,subagents:e.subagents,connectionAuth:e.connectionAuth,assistantResponseStats:e.assistantResponseStats,contextSize:e.contextSize,logs:e.logs,input:e.userInput,output:e.screen})}function formatAgentUpdateNotice(e,t){let n=e?.agent.model.id,r=t?.agent.model.id;return n!==void 0&&r!==void 0&&n!==r?`Agent updated: Model ${n} -> ${r}`:`Agent updated.`}async function*eveEventsToTUIStream(e){let{events:t,pendingInputRequests:n,subagentRuns:r,turnState:i,onSubagentCalled:a,onSubagentCompleted:o,onConnectionAuthRequired:s,onConnectionAuthCompleted:c,onTerminalFailure:l,failureOverride:u}=e,d=new Map,f=new Map,p=0,m=new Set,h=new Set,g=new Set,_=new Set,v=!1,y=!1,b;for await(let e of t)if(!(y&&isPostTurnVisibleEvent(e)))switch(e.type){case`session.started`:case`turn.started`:case`message.received`:break;case`step.started`:p+=1,yield{type:`step-start`};break;case`step.completed`:{let t=e;b=t.data.usage,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`step-finish`,usage:t.data.usage};break}case`message.appended`:{let t=e,n=textPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(d,n),i=t.data.messageSoFar;if(r.completed){if(r.text.startsWith(i)||p<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`assistant-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`message.completed`:{let t=textPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(d,t),r=e.data.message;if(n.completed){if(r===null||r===n.text||p<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=p,yield{type:`assistant-complete`,id:partGenerationId(t,n.generation),text:r};break}let i=partGenerationId(t,n.generation);if(r!==null){if(n.text.length===0)n.text=r,n.completed=!0,n.completedEpoch=p,yield{type:`assistant-complete`,id:i,text:r};else if(r.startsWith(n.text)){let e=r.slice(n.text.length);e.length>0&&(yield{type:`assistant-delta`,id:i,delta:e}),n.text=r,n.completed=!0,n.completedEpoch=p,yield{type:`assistant-complete`,id:i}}}else n.text.length>0&&(n.completed=!0,n.completedEpoch=p,yield{type:`assistant-complete`,id:i});break}case`reasoning.appended`:{let t=e,n=reasoningPartId(t.data.turnId,t.data.stepIndex),r=partStateFor(f,n),i=t.data.reasoningSoFar;if(r.completed){if(r.text.startsWith(i)||p<=r.completedEpoch)break;r.generation+=1,r.text=``,r.completed=!1}if(!i.startsWith(r.text)||i.length<=r.text.length)break;let a=i.slice(r.text.length);r.text=i,yield{type:`reasoning-delta`,id:partGenerationId(n,r.generation),delta:a};break}case`reasoning.completed`:{let t=reasoningPartId(e.data.turnId,e.data.stepIndex),n=partStateFor(f,t),r=e.data.reasoning;if(n.completed){if(r.length===0||r===n.text||n.text.startsWith(r)||p<=n.completedEpoch)break;n.generation+=1,n.text=r,n.completedEpoch=p;let e=partGenerationId(t,n.generation);yield{type:`reasoning-delta`,id:e,delta:r},yield{type:`reasoning-complete`,id:e};break}let i=partGenerationId(t,n.generation);if(n.text.length===0&&r.length>0)n.text=r,yield{type:`reasoning-delta`,id:i,delta:r};else if(r.length>0&&!r.startsWith(n.text))break;n.completed=!0,n.completedEpoch=p,yield{type:`reasoning-complete`,id:i};break}case`actions.requested`:{let t=e.data,n=t.actions.filter(e=>e.kind===`tool-call`);if(n.length===0)break;let r=toolBatchKey(`actions.requested`,t.turnId,t.stepIndex,n);if(g.has(r)){for(let e of n)m.has(e.callId)||h.add(e.callId);break}g.add(r);for(let e of n)m.has(e.callId)||(m.add(e.callId),yield{type:`tool-call`,toolCallId:e.callId,toolName:e.toolName,input:e.input});break}case`input.requested`:{let t=e.data,r=t.requests.filter(e=>e.action.kind===`tool-call`);if(r.length===0)break;let a=inputRequestBatchKey(t.turnId,t.stepIndex,r);if(g.has(a)){for(let e of r)m.has(e.action.callId)||h.add(e.action.callId);break}g.add(a);for(let e of r){let t=e.action.callId;if(m.has(t)||(m.add(t),yield{type:`tool-call`,toolCallId:t,toolName:e.action.toolName,input:e.action.input}),n.set(e.requestId,e),isQuestionRequest(e)){upsertPendingQuestion(i,e);continue}upsertPendingApproval(i,e),yield{type:`tool-approval-request`,approvalId:e.requestId,toolCallId:t}}break}case`action.result`:{let t=e;if(t.data.result.kind!==`tool-result`)break;let n=t.data.result.callId;if(h.has(n)||!m.has(n))break;t.data.status===`failed`?yield{type:`tool-error`,toolCallId:n,errorText:formatActionResultError(t)}:yield{type:`tool-result`,toolCallId:n,output:t.data.result.output};break}case`step.failed`:case`turn.failed`:{let t=toFailureEvent(e,_,u);t&&(yield t);break}case`session.failed`:{i.sawSessionFailure=!0,l?.(e);let t=toFailureEvent(e,_,u);t&&(yield t),i.boundaryEvent=e.type,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b},v=!0;return}case`session.waiting`:case`session.completed`:i.boundaryEvent=e.type,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b},v=!0;return;case`turn.completed`:y=!0,yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p);break;case`subagent.called`:{let t=e;if(!r.has(t.data.callId))r.set(t.data.callId,{name:t.data.name,steps:new Map,currentSectionKey:null,nextSectionKey:0,tools:new Map});else{let e=r.get(t.data.callId);e&&(e.name=t.data.name)}a?.(t);break}case`subagent.started`:case`subagent.event`:break;case`subagent.completed`:o?.(e.data.callId);break;case`authorization.required`:s?.(e);break;case`authorization.completed`:c?.(e);break;default:break}v||(yield*closeOpenParts(d,`assistant-complete`,p),yield*closeOpenParts(f,`reasoning-complete`,p),yield{type:`finish`,usage:b})}async function*errorOnlyTUIStream(e){yield{type:`error`,errorText:e.errorText},yield{type:`finish`}}function createTurnState(){return{pendingApprovals:[],pendingQuestions:[],sawSessionFailure:!1}}function upsertPendingApproval(e,t){let n=toAgentTUIToolApprovalRequest(t),r=e.pendingApprovals.findIndex(e=>e.approvalId===n.approvalId);r===-1?e.pendingApprovals.push(n):e.pendingApprovals[r]=n}function toAgentTUIToolApprovalRequest(e){return{approvalId:e.requestId,toolCallId:e.action.callId,toolName:e.action.toolName,input:e.action.input}}function upsertPendingQuestion(e,t){let n=e.pendingQuestions.findIndex(e=>e.requestId===t.requestId);n===-1?e.pendingQuestions.push(t):e.pendingQuestions[n]=t}function textPartId(e,t){return`text:${e}:${t}`}function reasoningPartId(e,t){return`reasoning:${e}:${t}`}function partStateFor(e,t){let n=e.get(t);return n===void 0&&(n={generation:0,text:``,completed:!1,completedEpoch:0},e.set(t,n)),n}function partGenerationId(e,t){return t===0?e:`${e}#${t}`}function*closeOpenParts(e,t,n){for(let[r,i]of e)i.completed||i.text.length===0||(i.completed=!0,i.completedEpoch=n,yield{type:t,id:partGenerationId(r,i.generation)})}function isPostTurnVisibleEvent(e){switch(e.type){case`actions.requested`:case`authorization.completed`:case`authorization.required`:case`input.requested`:case`message.appended`:case`message.completed`:case`reasoning.appended`:case`reasoning.completed`:case`result.completed`:case`step.completed`:case`step.failed`:case`step.started`:case`subagent.called`:case`subagent.completed`:case`subagent.event`:case`subagent.started`:case`turn.completed`:case`turn.failed`:return!0;default:return!1}}function toolBatchKey(e,t,n,r){return`${e}:${t}:${String(n)}:${stableStringify(r.map(e=>({input:e.input,toolName:e.toolName})))}`}function inputRequestBatchKey(e,t,n){return toolBatchKey(`input.requested`,e,t,n.map(e=>({input:e.action.input,toolName:e.action.toolName})))}function stableStringify(e){return JSON.stringify(toStableJson(e))??`undefined`}function toStableJson(e,t=new WeakSet){if(typeof e!=`object`||!e)return e;if(t.has(e))return`[Circular]`;if(t.add(e),Array.isArray(e))return e.map(e=>toStableJson(e,t));let n=e,r={};for(let e of Object.keys(n).sort())r[e]=toStableJson(n[e],t);return r}function formatActionResultError(e){if(e.data.error?.message)return e.data.error.message;let t=e.data.result.output;if(typeof t==`string`)return t;try{return JSON.stringify(t)}catch{return`Tool execution failed.`}}function toFailureEvent(e,t,n){let o=failureKey(e);if(t.has(o))return;t.add(o);let s=n?.(e),c={type:`error`,errorText:s??formatFailureMessage(e)};if(s!==void 0)return c;let l=formatFailureDetail(e);return l!==void 0&&(c.detail=l),c}function isQuestionRequest(e){return e.display===`select`||e.display===`text`?!0:e.display===`confirmation`?!1:e.options!==void 0&&e.options.length>0}function toAgentTUIInputQuestion(e){let t=e.display===`text`?`text`:e.display===`select`||e.options!==void 0&&e.options.length>0?`select`:`text`,n={requestId:e.requestId,prompt:e.prompt,display:t};return e.options!==void 0&&(n.options=e.options.map(e=>{let t={id:e.id,label:e.label};return e.description!==void 0&&(t.description=e.description),e.style!==void 0&&(t.style=e.style),t})),e.allowFreeform!==void 0&&(n.allowFreeform=e.allowFreeform),n}function openCurrentSubagentSection(e){e.currentSectionKey===null&&(e.currentSectionKey=e.nextSectionKey++,e.steps.set(e.currentSectionKey,{reasoning:``,message:``,finalized:!1}));let t=e.steps.get(e.currentSectionKey);if(!t)throw Error(`invariant: subagent section state missing for current key`);return{key:e.currentSectionKey,step:t}}export{EveTUIRunner,parsePromptCommand};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`).map((e,r)=>` ${t===`stacked`||r>0?n.colors.bold(e):e}`);return r.push(``),r}function searchFilter(e,t,n){return e.length>0?e+n.colors.dim(n.glyph.caret):t===void 0?n.colors.dim(n.glyph.caret):n.colors.dim(`> ${t}`)}function selectViewSize(e){return e.search?e.filter===``&&e.featuredLead>0?Math.min(e.featuredLead,8):8:e.optionCount}function noticeBody(e,t,n){return e.tone===`info`?n.colors.dim(e.text):e.tone===`success`&&t===`task-list`?n.colors.bold(e.text):e.text}function editableOption(e,t,n,r){if(!t||n?.optionValue!==e.value)return e;let i=n.editor.text||n.defaultValue,a=n.editor.text.length===0?i.length:n.editor.cursor,o=n.caretVisible?r.colors.cyan(r.glyph.caret):``,s=`${i.slice(0,a)}${o}${i.slice(a)}`;return{...e,hint:n.formatHint(s)}}function optionWithoutStackedHint(e,t){if(t!==`stacked`||e.hint===void 0)return{option:e,stackedHint:void 0};let{hint:n,...r}=e;return{option:r,stackedHint:n}}function optionUsesPlaceholder(e,t,n){let r=e.filter!==void 0,i=e.layout===`task-list`&&t===n-1,a=e.selection===`multiple`,o=e.layout!==`plain`;return!r&&!i&&(a||o)}function appendSelectOptionRows(e){let{rows:t,state:n,presentation:r,visible:i,start:a,end:o,cursor:s,visibleLabelWidth:c,theme:l}=e,u=l.colors;for(let e=a;e<o;e+=1){let d=i[e],f=e===s;r.layout===`task-list`&&e===o-1&&e>a&&t.push(``);let{option:p,stackedHint:m}=optionWithoutStackedHint(editableOption(d,f,r.edit,l),r.layout);t.push(` ${optionRow({option:p,isCursor:f,isChecked:r.selection===`multiple`&&n.select.selected.has(d.value),placeholder:optionUsesPlaceholder(r,e,i.length),hintPadding:c-d.label.length,theme:l})}`),m!==void 0&&t.push(`${` `.repeat(4)}${dimWithEmphasis(m,l)}`),d.description!==void 0&&(d.disabled===!0||f)&&t.push(` ${u.dim(d.description)}`),r.layout===`stacked`&&e<o-1&&t.push(``)}}function appendSubmitRow(e,t,n,r){if(n<0)return;let i=t===n,a=i?r.colors.cyan(r.glyph.pointer):` `,o=i?r.colors.cyan(r.colors.bold(`Submit`)):`Submit`;e.push(``,` ${a} ${o}`)}function appendSelectNotices(e,
|
|
3
|
-
`).map(e=>` ${
|
|
1
|
+
import{clipVisible,renderInputText,visibleLength,wrapVisibleLine}from"./terminal-text.js";import{visibleLine}from"./line-editor.js";import{graphemes}from"#shared/text-boundaries.js";import{renderOptionRow,resolveOptionRowState}from"#setup/cli/option-row.js";import{filterOptions,submitRowIndex}from"#setup/cli/select-state.js";function clip(t,n){return clipVisible(t,n)}function questionFooter(e,t){let n=t.colors;return[``,` ${n.dim(n.italic(e.join(` ${t.glyph.dot} `)))}`]}const BOLD_OR_DIM_CLOSE=`\x1B[22m`;function dimWithEmphasis(e,t){return t.colors.dim(e.replaceAll(BOLD_OR_DIM_CLOSE,`${BOLD_OR_DIM_CLOSE}[2m`))}function toneGlyph(e,t){let n=t.colors;switch(e){case`success`:return n.green(t.glyph.success);case`warning`:return n.yellow(t.glyph.warning);case`error`:return n.red(t.glyph.error);case`info`:return n.dim(t.glyph.dot)}}function renderFlowPanel(e,t,n){let r=t.colors,i=[r.dim(t.glyph.hrule.repeat(Math.max(1,n)))];e.title.length>0&&i.push(` ${r.bold(e.title)}`),i.push(``);let a=e.lines.slice(-6);for(let e of a){let n=e.tone===`info`?r.dim(e.text):e.text;i.push(` ${toneGlyph(e.tone,t)} ${n}`)}switch(a.length>0&&i.push(``),e.content.kind){case`question`:e.content.status!==void 0&&i.push(` ${r.yellow(e.content.status.frame)} ${r.dim(e.content.status.text)}`,``),i.push(...e.content.rows);break;case`status`:i.push(` ${r.yellow(e.content.status.frame)} ${r.dim(e.content.status.text)}`),e.content.preview!==void 0&&i.push(` ${r.dim(e.content.preview)}`);break;case`preview`:i.push(` ${r.yellow(e.content.frame)} ${r.dim(e.content.text)}`);break;case`idle`:i.push(` ${r.yellow(e.content.frame)} ${r.dim(`Working…`)}`);break}return i.map((e,t)=>t===0||e.length===0?clip(e,n):clip(` ${e}`,n))}function optionRow(e){let{option:t,theme:n}=e;return renderOptionRow({colors:n.colors,glyphs:{pointer:n.glyph.pointer,success:n.glyph.success,placeholder:n.glyph.option,dot:n.glyph.dot},label:t.label,hint:t.hint,focusHint:t.focusHint,accent:t.accent,isCursor:e.isCursor,state:resolveOptionRowState(t,e.isChecked),placeholder:e.placeholder,hintPadding:e.hintPadding})}function selectPresentation(e){switch(e.kind){case`single`:return{selection:`single`,filter:void 0,layout:`plain`,edit:void 0};case`search`:return{selection:`single`,filter:{placeholder:e.placeholder},layout:`plain`,edit:void 0};case`multi`:return{selection:`multiple`,filter:void 0,layout:`plain`,edit:void 0};case`searchable-multi`:return{selection:`multiple`,filter:{placeholder:e.placeholder},layout:`plain`,edit:void 0};case`stacked`:return{selection:`single`,filter:void 0,layout:`stacked`,edit:void 0};case`task-list`:return{selection:`single`,filter:void 0,layout:`task-list`,edit:void 0};case`editable`:return{selection:`single`,filter:void 0,layout:`task-list`,edit:e.edit}}}function selectMessageRows(e,t,n){if(e===``)return[];let r=e.split(`
|
|
2
|
+
`).map((e,r)=>` ${t===`stacked`||r>0?n.colors.bold(e):e}`);return r.push(``),r}function searchFilter(e,t,n){return e.length>0?e+n.colors.dim(n.glyph.caret):t===void 0?n.colors.dim(n.glyph.caret):n.colors.dim(`> ${t}`)}function selectViewSize(e){return e.search?e.filter===``&&e.featuredLead>0?Math.min(e.featuredLead,8):8:e.optionCount}function noticeBody(e,t,n){return e.tone===`info`?n.colors.dim(e.text):e.tone===`success`&&t===`task-list`?n.colors.bold(e.text):e.text}function editableOption(e,t,n,r){if(!t||n?.optionValue!==e.value)return e;let i=n.editor.text||n.defaultValue,a=n.editor.text.length===0?i.length:n.editor.cursor,o=n.caretVisible?r.colors.cyan(r.glyph.caret):``,s=`${i.slice(0,a)}${o}${i.slice(a)}`;return{...e,hint:n.formatHint(s)}}function optionWithoutStackedHint(e,t){if(t!==`stacked`||e.hint===void 0)return{option:e,stackedHint:void 0};let{hint:n,...r}=e;return{option:r,stackedHint:n}}function optionUsesPlaceholder(e,t,n){let r=e.filter!==void 0,i=e.layout===`task-list`&&t===n-1,a=e.selection===`multiple`,o=e.layout!==`plain`;return!r&&!i&&(a||o)}function appendSelectOptionRows(e){let{rows:t,state:n,presentation:r,visible:i,start:a,end:o,cursor:s,visibleLabelWidth:c,theme:l}=e,u=l.colors;for(let e=a;e<o;e+=1){let d=i[e],f=e===s;r.layout===`task-list`&&e===o-1&&e>a&&t.push(``);let{option:p,stackedHint:m}=optionWithoutStackedHint(editableOption(d,f,r.edit,l),r.layout);t.push(` ${optionRow({option:p,isCursor:f,isChecked:r.selection===`multiple`&&n.select.selected.has(d.value),placeholder:optionUsesPlaceholder(r,e,i.length),hintPadding:c-d.label.length,theme:l})}`),m!==void 0&&t.push(`${` `.repeat(4)}${dimWithEmphasis(m,l)}`),d.description!==void 0&&(d.disabled===!0||f)&&t.push(` ${u.dim(d.description)}`),r.layout===`stacked`&&e<o-1&&t.push(``)}}function appendSubmitRow(e,t,n,r){if(n<0)return;let i=t===n,a=i?r.colors.cyan(r.glyph.pointer):` `,o=i?r.colors.cyan(r.colors.bold(`Submit`)):`Submit`;e.push(``,` ${a} ${o}`)}function appendSelectNotices(e,t,i,a,o){if(!(t===void 0||t.length===0)){e.push(``);for(let s of t){let t=toneGlyph(s.tone,a),c=` `.repeat(visibleLength(t)+1),l=Math.max(1,o-2-visibleLength(t)-1),u=wrapVisibleLine(s.text,l);for(let[n,r]of u.entries()){let o=noticeBody({...s,text:r},i,a);e.push(n===0?` ${t} ${o}`:` ${c}${o}`)}}}}function selectFooterHints(e,t,n){let r=[];return e.edit!==void 0&&t[n]?.value===e.edit.optionValue&&r.push(`type to rename`),e.filter!==void 0&&r.push(`type to filter`),r.push(`↑/↓ move`),r.push(e.selection===`multiple`?`space to toggle`:`enter to select`),e.selection===`multiple`&&r.push(`enter on Submit to confirm`),r.push(`esc to cancel`),r}function renderActionQuestion(e,t,n){let r=[` ${t.colors.dim(`${t.glyph.dot} ${e.context}`)}`,``];for(let[n,i]of e.actions.entries())r.push(` ${optionRow({option:i,isCursor:n===e.cursor,isChecked:!1,placeholder:!0,hintPadding:0,theme:t})}`);return r.push(...questionFooter([`↑/↓ move`,`enter to select`,`esc to cancel`],t)),r.map(e=>clip(e,n))}function renderSelectQuestion(e,t,n){if(e.kind===`actions`)return renderActionQuestion(e,t,n);let r=t.colors,i=selectPresentation(e),a=i.filter?filterOptions(e.options,e.select.filter):e.options,o=i.selection===`multiple`?submitRowIndex(a):-1,s=e.select.cursor,u=selectMessageRows(e.message,i.layout,t);i.filter!==void 0&&u.push(` ${searchFilter(e.select.filter,i.filter.placeholder,t)}`);let d=0;for(;a[d]?.featured;)d+=1;let f=selectViewSize({search:i.filter!==void 0,filter:e.select.filter,featuredLead:d,optionCount:a.length}),p=Math.max(0,Math.min(s-Math.floor(f/2),Math.max(0,a.length-f))),m=Math.min(p+f,a.length),h=a.slice(p,m).filter(e=>e.hint!==void 0||e.focusHint!==void 0).reduce((e,t)=>Math.max(e,t.label.length),0);return a.length===0&&u.push(` ${r.dim(`(no matches)`)}`),appendSelectOptionRows({rows:u,state:e,presentation:i,visible:a,start:p,end:m,cursor:s,visibleLabelWidth:h,theme:t}),appendSubmitRow(u,s,o,t),a.length>m-p&&u.push(` ${r.dim(`↑↓ ${a.length} options, showing ${p+1}–${m}`)}`),appendSelectNotices(u,e.notices,i.layout,t,n),e.error!==void 0&&u.push(``,` ${r.red(e.error)}`),u.push(...questionFooter(selectFooterHints(i,a,s),t)),u.map(e=>clip(e,n))}function renderTextQuestion(e,n,r,o){let s=n.colors,c=[];for(let t of e.notices??[]){let e=t.tone===`info`?s.dim(t.text):t.text;c.push(`${toneGlyph(t.tone,n)} ${e}`)}c.push(...e.message.split(`
|
|
3
|
+
`).map(e=>` ${s.bold(e)}`));let l=Math.max(4,r-4),{before:u,under:d,after:f}=visibleLine(e.mask?{text:`•`.repeat(graphemes(e.editor.text).length),cursor:graphemes(e.editor.text.slice(0,e.editor.cursor)).length}:{text:e.editor.text,cursor:e.editor.cursor},l,n.glyph.ellipsis),p=o?s.cyan(n.glyph.caret):` `,m=e.editor.text.length===0&&e.placeholder!==void 0?`${p}${s.dim(e.placeholder)}`:`${renderInputText(u)}${p}${renderInputText(d)}${renderInputText(f)}`;return c.push(` ${m}`),e.error!==void 0&&c.push(``,` ${s.red(e.error)}`),c.push(...questionFooter([`enter to submit`,`esc to cancel`],n)),c.map(e=>clip(e,r))}function renderAcknowledgeQuestion(e,t,n){let r=t.colors,i=[` ${r.bold(e.message)}`];if(e.lines.length>0){i.push(``);for(let t of e.lines)i.push(` ${r.dim(t)}`)}return i.push(...questionFooter([`enter to continue`],t)),i.map(e=>clip(e,n))}export{renderAcknowledgeQuestion,renderFlowPanel,renderSelectQuestion,renderTextQuestion};
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{filterOptions,orderedSelection,reduceSelect,selectValueAtCursor,submitRowIndex}from"#setup/cli/select-state.js";function setupSelectionIntent(e){switch(e.type){case`ctrl-c`:case`escape`:return{kind:`cancel`};case`up`:return{kind:`move`,direction:`up`};case`down`:return{kind:`move`,direction:`down`};case`ctrl-r`:return{kind:`repaint`};case`enter`:return{kind:`submit`};default:return}}function isMultiSelect(e){return e.kind===`multi`||e.kind===`searchable-multi`}function isSearchableSelect(e){return e.kind===`search`||e.kind===`searchable-multi`}function updatedSelect(e,t){return{kind:`update`,select:reduceSelect(e.select,t,{options:e.options,submitRow:isMultiSelect(e)})}}function submitSetupSelect(n){let a=isSearchableSelect(n)?filterOptions(n.options,n.select.filter):[...n.options];if(isMultiSelect(n))return n.select.cursor===submitRowIndex(a)?n.required&&n.select.selected.size===0?{kind:`error`,message:`Select at least one option, then submit.`}:{kind:`submit`,values:orderedSelection(n.options,n.select.selected)}:updatedSelect(n,{type:`toggle`});let o=selectValueAtCursor(a,n.select.cursor);return o===void 0?a[n.select.cursor]?.completed?{kind:`ignore`}:{kind:`error`,message:`Type to match an option, then press enter.`}:{kind:`submit`,values:[o]}}function editSetupSelect(e){switch(e.key.type){case`backspace`:return isSearchableSelect(e)?updatedSelect(e,{type:`backspace`}):{kind:`ignore`};case`
|
|
1
|
+
import{filterOptions,orderedSelection,reduceSelect,selectValueAtCursor,submitRowIndex}from"#setup/cli/select-state.js";function setupSelectionIntent(e){switch(e.type){case`ctrl-c`:case`escape`:return{kind:`cancel`};case`up`:return{kind:`move`,direction:`up`};case`down`:return{kind:`move`,direction:`down`};case`ctrl-r`:return{kind:`repaint`};case`enter`:return{kind:`submit`};default:return}}function isMultiSelect(e){return e.kind===`multi`||e.kind===`searchable-multi`}function isSearchableSelect(e){return e.kind===`search`||e.kind===`searchable-multi`}function updatedSelect(e,t){return{kind:`update`,select:reduceSelect(e.select,t,{options:e.options,submitRow:isMultiSelect(e)})}}function submitSetupSelect(n){let a=isSearchableSelect(n)?filterOptions(n.options,n.select.filter):[...n.options];if(isMultiSelect(n))return n.select.cursor===submitRowIndex(a)?n.required&&n.select.selected.size===0?{kind:`error`,message:`Select at least one option, then submit.`}:{kind:`submit`,values:orderedSelection(n.options,n.select.selected)}:updatedSelect(n,{type:`toggle`});let o=selectValueAtCursor(a,n.select.cursor);return o===void 0?a[n.select.cursor]?.completed?{kind:`ignore`}:{kind:`error`,message:`Type to match an option, then press enter.`}:{kind:`submit`,values:[o]}}function editSetupSelect(e){switch(e.key.type){case`backspace`:return isSearchableSelect(e)?updatedSelect(e,{type:`backspace`}):{kind:`ignore`};case`text`:{if(e.key.framing===`unframed`&&isMultiSelect(e)&&e.key.value===` `)return updatedSelect(e,{type:`toggle`});if(!isSearchableSelect(e))return{kind:`ignore`};let t=e.select,r={options:e.options,submitRow:isMultiSelect(e)};for(let i of e.key.value.replaceAll(`
|
|
2
|
+
`,` `))i>=` `&&i!==``&&(t=reduceSelect(t,{type:`char`,char:i},r));return{kind:`update`,select:t}}default:return{kind:`ignore`}}}function reduceSetupSelectInput(e){let t=setupSelectionIntent(e.key);switch(t?.kind){case`cancel`:return{kind:`cancel`};case`repaint`:return{kind:`repaint`};case`move`:return updatedSelect(e,{type:t.direction});case`submit`:return submitSetupSelect(e);case void 0:return editSetupSelect(e)}}export{reduceSetupSelectInput,setupSelectionIntent};
|
|
@@ -5,8 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { AssistantResponseStatsMode } from "./types.js";
|
|
7
7
|
export type TerminalKey = {
|
|
8
|
-
type: "
|
|
8
|
+
type: "text";
|
|
9
9
|
value: string;
|
|
10
|
+
/** Terminal framing, not proof that the text came from a physical keypress. */
|
|
11
|
+
framing: "unframed" | "bracketed-paste";
|
|
12
|
+
} | {
|
|
13
|
+
type: "newline";
|
|
10
14
|
} | {
|
|
11
15
|
type: "backspace";
|
|
12
16
|
} | {
|
|
@@ -50,13 +54,28 @@ export type TerminalKey = {
|
|
|
50
54
|
} | {
|
|
51
55
|
type: "ignore";
|
|
52
56
|
};
|
|
53
|
-
/** One decoded key plus
|
|
57
|
+
/** One decoded key plus the UTF-16 code units it consumed from the input buffer. */
|
|
54
58
|
export interface KeyToken {
|
|
55
59
|
key?: TerminalKey;
|
|
56
60
|
consumed: number;
|
|
57
61
|
/** The buffer ends mid-sequence; wait for more bytes before decoding. */
|
|
58
62
|
incomplete?: boolean;
|
|
59
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Preserves newlines and tabs, normalizes CR to LF, and drops C0, DEL, and C1
|
|
66
|
+
* controls. The first end marker closes the frame. This prevents escape
|
|
67
|
+
* injection, not display spoofing by bidi or zero-width characters.
|
|
68
|
+
*/
|
|
69
|
+
export declare function sanitizePastedText(text: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* True when `buffer` is a bracketed paste whose closing marker hasn't arrived.
|
|
72
|
+
* {@link nextKey} reports such a buffer as `incomplete` indefinitely, so the
|
|
73
|
+
* caller needs this to recover if the end marker never comes (a process that
|
|
74
|
+
* emits a bare start marker and dies, a malformed terminal).
|
|
75
|
+
*/
|
|
76
|
+
export declare function isIncompletePaste(buffer: string): boolean;
|
|
77
|
+
/** Drops a leading bracketed-paste start marker, leaving the buffered payload. */
|
|
78
|
+
export declare function stripPasteStart(buffer: string): string;
|
|
60
79
|
/** Removes C0 control characters and DEL from text intended for the prompt. */
|
|
61
80
|
export declare function stripPromptControlCharacters(text: string): string;
|
|
62
81
|
/**
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
const CSI_FINAL=/[\u0040-\u007e]/u
|
|
2
|
-
|
|
1
|
+
const CSI_FINAL=/[\u0040-\u007e]/u,PASTE_START=`\x1B[200~`,PASTE_END=`\x1B[201~`;function sanitizePastedText(e){let t=``;for(let n of e.replace(/\r\n?/gu,`
|
|
2
|
+
`)){if(n===`
|
|
3
|
+
`||n===` `){t+=n;continue}let e=n.codePointAt(0);e!==void 0&&(e<32||e===127||e>=128&&e<=159||(t+=n))}return t}function isIncompletePaste(e){return e.startsWith(PASTE_START)&&!e.includes(PASTE_END,6)}function stripPasteStart(e){return e.startsWith(PASTE_START)?e.slice(6):e}function stripPromptControlCharacters(e){let t=``;for(let n of e)n>=` `&&n!==``&&(t+=n);return t}function nextKey(r){let i=r[0];if(i===void 0)return{consumed:0,incomplete:!0};if(i===`\x1B`){if(r.length===1)return{consumed:0,incomplete:!0};let i=r[1];if(i===`O`)return r.length<3?{consumed:0,incomplete:!0}:{key:parseKey(Buffer.from(r.slice(0,3))),consumed:3};if(i===`[`){if(r.startsWith(PASTE_START)){let e=r.indexOf(PASTE_END,6);return e===-1?{consumed:0,incomplete:!0}:{key:{type:`text`,value:sanitizePastedText(r.slice(6,e)),framing:`bracketed-paste`},consumed:e+6}}for(let t=2;t<r.length;t+=1)if(CSI_FINAL.test(r[t]))return{key:parseKey(Buffer.from(r.slice(0,t+1))),consumed:t+1};return{consumed:0,incomplete:!0}}return{key:{type:`escape`},consumed:1}}if(i<` `||i===``)return{key:parseKey(Buffer.from(i)),consumed:1};let a=1;for(;a<r.length;){let e=r[a];if(e===`\x1B`||e<` `||e===``)break;a+=1}return{key:parseKey(Buffer.from(r.slice(0,a))),consumed:a}}function parseKey(e){let t=e.toString(`utf8`);switch(t){case``:return{type:`ctrl-a`};case``:return{type:`ctrl-e`};case``:return{type:`ctrl-d`};case`\v`:return{type:`ctrl-k`};case`\f`:return{type:`ctrl-l`};case``:return{type:`ctrl-r`};case``:return{type:`ctrl-u`};case``:return{type:`ctrl-w`};case``:return{type:`ctrl-c`};case`\r`:case`
|
|
4
|
+
`:return{type:`enter`};case`\x1B[27;2;13~`:case`\x1B[13;2u`:return{type:`newline`};case``:case`\b`:return{type:`backspace`};case`\x1B[A`:case`\x1BOA`:return{type:`up`};case`\x1B[B`:case`\x1BOB`:return{type:`down`};case`\x1B[C`:case`\x1BOC`:return{type:`right`};case`\x1B[D`:case`\x1BOD`:return{type:`left`};case`\x1B[H`:case`\x1BOH`:case`\x1B[1~`:return{type:`home`};case`\x1B[F`:case`\x1BOF`:case`\x1B[4~`:return{type:`end`};case`\x1B[3~`:return{type:`delete`};case` `:return{type:`tab`};case`\x1B`:return{type:`escape`};default:{let e=stripPromptControlCharacters(t);return e.length>0?{type:`text`,value:e,framing:`unframed`}:{type:`ignore`}}}}async function*takeUntil(e,t){let n=e[Symbol.asyncIterator](),r=t.then(()=>({done:!0,value:void 0}));try{for(;;){let e=n.next();e.catch(()=>{});let t=await Promise.race([e,r]);if(t.done)break;yield t.value}}finally{n.return?.()?.catch(()=>{})}}function formatCompactTokenCount(e){if(e<1e3)return`${e}`;let t=e<1e6?e/1e3:e/1e6,n=e<1e6?`K`:`M`;return`${t.toFixed(1).replace(/\.0$/,``)}${n}`}function formatTokenFlow(e,t){let n=formatCompactTokenCount(e.inputTokens),r=formatCompactTokenCount(e.outputTokens),i=`${t.arrowUp} ${n} ${t.arrowDown} ${r}`,a=formatContextPercentage(e.inputTokens,e.contextSize);return a==null?i:`${i} ${a}`}function formatContextPercentage(e,t){if(!(t==null||t<=0||!Number.isFinite(t)))return`${Math.round(e/t*100).toLocaleString()}%`}function formatAssistantResponseStats(e,t){if(t===`tokensPerSecond`)return formatTokensPerSecond(e.tokensPerSecond);if(e.outputTokens!=null)return`${e.outputTokens.toLocaleString()} output tokens`}function formatTokensPerSecond(e){if(e!=null)return`${formatNumber(e)} tok/s`}function formatNumber(e){return Number.isInteger(e)?e.toLocaleString():e.toLocaleString(void 0,{maximumFractionDigits:1})}export{formatAssistantResponseStats,formatCompactTokenCount,formatTokenFlow,isIncompletePaste,nextKey,parseKey,sanitizePastedText,stripPasteStart,stripPromptControlCharacters,takeUntil};
|