eve 0.12.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/src/chunks/{use-eve-agent-D9ZhQhyV.js → use-eve-agent-DEm_Jg4k.js} +18 -4
- package/dist/src/chunks/{use-eve-agent-DFI0POM9.js → use-eve-agent-DsXOQMFZ.js} +18 -4
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/dev/tui/command-typeahead.d.ts +1 -1
- package/dist/src/cli/dev/tui/command-typeahead.js +1 -1
- package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +6 -2
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/setup-commands.d.ts +6 -2
- package/dist/src/cli/dev/tui/setup-commands.js +2 -2
- package/dist/src/cli/dev/tui/setup-issues.d.ts +16 -2
- package/dist/src/cli/dev/tui/setup-issues.js +1 -1
- package/dist/src/cli/dev/tui/setup-panel.js +2 -2
- package/dist/src/cli/dev/tui/target.d.ts +21 -0
- package/dist/src/cli/dev/tui/target.js +1 -0
- package/dist/src/cli/dev/tui/terminal-renderer.js +3 -3
- package/dist/src/cli/dev/tui/test/fake-setup-flow-renderer.d.ts +2 -0
- package/dist/src/cli/dev/tui/test/fake-setup-flow-renderer.js +1 -0
- package/dist/src/cli/dev/tui/theme.d.ts +3 -1
- package/dist/src/cli/dev/tui/theme.js +1 -1
- package/dist/src/cli/dev/tui/tui.d.ts +4 -14
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/dev/url.js +1 -1
- package/dist/src/cli/run.d.ts +0 -12
- package/dist/src/cli/run.js +2 -2
- package/dist/src/client/client.js +1 -1
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/open-stream.d.ts +2 -0
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/session.d.ts +2 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/types.d.ts +9 -0
- package/dist/src/evals/cli/eval-client.d.ts +12 -16
- package/dist/src/evals/cli/eval-client.js +1 -1
- package/dist/src/evals/cli/eval.js +1 -1
- package/dist/src/harness/compaction.d.ts +2 -3
- package/dist/src/harness/compaction.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/nitro/host/dev-authored-source-watcher.js +1 -1
- package/dist/src/internal/nitro/host/start-development-server.js +2 -2
- package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
- package/dist/src/services/dev-client/client-options.d.ts +9 -4
- package/dist/src/services/dev-client/client-options.js +1 -1
- package/dist/src/services/dev-client/credential-gate.d.ts +19 -0
- package/dist/src/services/dev-client/credential-gate.js +1 -0
- package/dist/src/services/dev-client/local-host.d.ts +4 -0
- package/dist/src/services/dev-client/local-host.js +1 -0
- package/dist/src/services/dev-client/request-headers.d.ts +38 -56
- package/dist/src/services/dev-client/request-headers.js +1 -1
- package/dist/src/services/dev-client/runtime-artifacts.js +1 -1
- package/dist/src/services/dev-client/vercel-auth-error.d.ts +2 -0
- package/dist/src/services/dev-client/vercel-auth-error.js +2 -2
- package/dist/src/services/dev-client.js +1 -1
- package/dist/src/setup/cli/option-row.d.ts +11 -5
- package/dist/src/setup/cli/option-row.js +1 -1
- package/dist/src/setup/cli/prompt-ui.d.ts +6 -6
- package/dist/src/setup/cli/prompt-ui.js +2 -2
- package/dist/src/setup/flows/model.d.ts +2 -0
- package/dist/src/setup/flows/model.js +1 -1
- package/dist/src/setup/project-resolution.d.ts +13 -0
- package/dist/src/setup/project-resolution.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/index.d.ts +1 -1
- package/dist/src/setup/scaffold/index.js +1 -1
- package/dist/src/setup/scaffold/update/channels.d.ts +8 -1
- package/dist/src/setup/scaffold/update/channels.js +2 -2
- package/dist/src/setup/vercel-deployment.d.ts +53 -0
- package/dist/src/setup/vercel-deployment.js +1 -0
- package/dist/src/setup/vercel-project.js +1 -1
- package/dist/src/setup/verified-remote-client.d.ts +23 -0
- package/dist/src/setup/verified-remote-client.js +1 -0
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/evals/targets.mdx +7 -5
- package/docs/guides/client/overview.mdx +3 -0
- package/docs/guides/dev-tui.md +5 -5
- package/package.json +1 -1
- package/dist/src/harness/tool-result-pruning.d.ts +0 -8
- package/dist/src/harness/tool-result-pruning.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.12.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 3f3a86b: Improve conversation compaction for longer, more reliable sessions.
|
|
8
|
+
- e296fb8: The dev TUI now opens `/model` when the runtime confirms no model provider is configured and refreshes model access after setup. Selected rows now use padded inverse labels with a filled arrow.
|
|
9
|
+
- f68ecbe: Set the Eve Vercel framework preset when creating standalone Eve projects.
|
|
10
|
+
- c084232: Verify remote Vercel deployment origins against the owner and project supplied by `VERCEL_ORG_ID` and `VERCEL_PROJECT_ID`, or by a local project link, before sending ambient credentials. Remote dev and eval clients now refresh scoped OIDC tokens per request and refuse to forward credentials across redirects. Remote `eve dev` and `eve eval --url` targets now require `https://` (loopback hosts may still use `http://`).
|
|
11
|
+
|
|
3
12
|
## 0.12.0
|
|
4
13
|
|
|
5
14
|
### Minor Changes
|
|
@@ -301,6 +301,7 @@ async function openStreamBody(input) {
|
|
|
301
301
|
const headers = await input.resolveHeaders();
|
|
302
302
|
const response = await fetch(url, {
|
|
303
303
|
headers,
|
|
304
|
+
redirect: input.redirect,
|
|
304
305
|
signal: input.signal ?? null
|
|
305
306
|
});
|
|
306
307
|
if (response.ok) {
|
|
@@ -362,6 +363,7 @@ var ClientSession = class {
|
|
|
362
363
|
body: JSON.stringify(body),
|
|
363
364
|
headers,
|
|
364
365
|
mustDeliver: (input.inputResponses?.length ?? 0) > 0,
|
|
366
|
+
redirect: this.#context.redirect,
|
|
365
367
|
signal: input.signal,
|
|
366
368
|
url
|
|
367
369
|
});
|
|
@@ -413,6 +415,7 @@ var ClientSession = class {
|
|
|
413
415
|
return await openStreamBody({
|
|
414
416
|
host: this.#context.host,
|
|
415
417
|
resolveHeaders: () => this.#context.resolveHeaders(headers),
|
|
418
|
+
redirect: this.#context.redirect,
|
|
416
419
|
sessionId,
|
|
417
420
|
signal,
|
|
418
421
|
startIndex
|
|
@@ -427,6 +430,7 @@ var ClientSession = class {
|
|
|
427
430
|
host: this.#context.host,
|
|
428
431
|
maxReconnectAttempts: this.#context.maxReconnectAttempts,
|
|
429
432
|
resolveHeaders: () => this.#context.resolveHeaders(),
|
|
433
|
+
redirect: this.#context.redirect,
|
|
430
434
|
sessionId,
|
|
431
435
|
signal: options?.signal,
|
|
432
436
|
startIndex: streamIndex
|
|
@@ -458,6 +462,7 @@ async function postTurnWithRetry(input) {
|
|
|
458
462
|
body: input.body,
|
|
459
463
|
headers: input.headers,
|
|
460
464
|
method: "POST",
|
|
465
|
+
redirect: input.redirect,
|
|
461
466
|
signal: input.signal ?? null
|
|
462
467
|
});
|
|
463
468
|
if (response.ok) return response;
|
|
@@ -498,17 +503,19 @@ var Client = class {
|
|
|
498
503
|
#host;
|
|
499
504
|
#maxReconnectAttempts;
|
|
500
505
|
#preserveCompletedSessions;
|
|
506
|
+
#redirect;
|
|
501
507
|
constructor(options) {
|
|
502
508
|
this.#host = options.host;
|
|
503
509
|
this.#auth = options.auth;
|
|
504
510
|
this.#headers = options.headers;
|
|
505
511
|
this.#maxReconnectAttempts = options.maxReconnectAttempts ?? 3;
|
|
506
512
|
this.#preserveCompletedSessions = options.preserveCompletedSessions ?? false;
|
|
513
|
+
this.#redirect = options.redirect;
|
|
507
514
|
}
|
|
508
515
|
async health() {
|
|
509
516
|
const url = createClientUrl(this.#host, EVE_HEALTH_ROUTE_PATH);
|
|
510
517
|
const headers = await this.#resolveHeaders();
|
|
511
|
-
const response = await fetch(url, { headers });
|
|
518
|
+
const response = await fetch(url, withRedirectPolicy({ headers }, this.#redirect));
|
|
512
519
|
if (!response.ok) {
|
|
513
520
|
const body = await response.text();
|
|
514
521
|
throw new ClientError(response.status, body);
|
|
@@ -518,7 +525,7 @@ var Client = class {
|
|
|
518
525
|
async info() {
|
|
519
526
|
const url = createClientUrl(this.#host, EVE_INFO_ROUTE_PATH);
|
|
520
527
|
const headers = await this.#resolveHeaders();
|
|
521
|
-
const response = await fetch(url, { headers });
|
|
528
|
+
const response = await fetch(url, withRedirectPolicy({ headers }, this.#redirect));
|
|
522
529
|
if (!response.ok) {
|
|
523
530
|
const body = await response.text();
|
|
524
531
|
throw new ClientError(response.status, body);
|
|
@@ -528,10 +535,10 @@ var Client = class {
|
|
|
528
535
|
async fetch(path, init = {}) {
|
|
529
536
|
const url = createClientUrl(this.#host, path);
|
|
530
537
|
const headers = await this.#resolveHeaders(headersInitToRecord(init.headers));
|
|
531
|
-
return await fetch(url, {
|
|
538
|
+
return await fetch(url, withRedirectPolicy({
|
|
532
539
|
...init,
|
|
533
540
|
headers
|
|
534
|
-
});
|
|
541
|
+
}, this.#redirect));
|
|
535
542
|
}
|
|
536
543
|
session(state) {
|
|
537
544
|
let resolved;
|
|
@@ -545,6 +552,7 @@ var Client = class {
|
|
|
545
552
|
host: this.#host,
|
|
546
553
|
maxReconnectAttempts: this.#maxReconnectAttempts,
|
|
547
554
|
preserveCompletedSessions: this.#preserveCompletedSessions,
|
|
555
|
+
redirect: this.#redirect,
|
|
548
556
|
resolveHeaders: (perRequest) => this.#resolveHeaders(perRequest)
|
|
549
557
|
}, resolved);
|
|
550
558
|
}
|
|
@@ -582,6 +590,12 @@ function headersInitToRecord(headers) {
|
|
|
582
590
|
if (headers === void 0) return {};
|
|
583
591
|
return Object.fromEntries(new Headers(headers).entries());
|
|
584
592
|
}
|
|
593
|
+
function withRedirectPolicy(init, redirect) {
|
|
594
|
+
return redirect === void 0 ? init : {
|
|
595
|
+
...init,
|
|
596
|
+
redirect
|
|
597
|
+
};
|
|
598
|
+
}
|
|
585
599
|
function encodeBasicCredentials(username, password) {
|
|
586
600
|
const bytes = new TextEncoder().encode(`${username}:${password}`);
|
|
587
601
|
const binaryString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
|
|
@@ -301,6 +301,7 @@ async function openStreamBody(input) {
|
|
|
301
301
|
const headers = await input.resolveHeaders();
|
|
302
302
|
const response = await fetch(url, {
|
|
303
303
|
headers,
|
|
304
|
+
redirect: input.redirect,
|
|
304
305
|
signal: input.signal ?? null
|
|
305
306
|
});
|
|
306
307
|
if (response.ok) {
|
|
@@ -362,6 +363,7 @@ var ClientSession = class {
|
|
|
362
363
|
body: JSON.stringify(body),
|
|
363
364
|
headers,
|
|
364
365
|
mustDeliver: (input.inputResponses?.length ?? 0) > 0,
|
|
366
|
+
redirect: this.#context.redirect,
|
|
365
367
|
signal: input.signal,
|
|
366
368
|
url
|
|
367
369
|
});
|
|
@@ -413,6 +415,7 @@ var ClientSession = class {
|
|
|
413
415
|
return await openStreamBody({
|
|
414
416
|
host: this.#context.host,
|
|
415
417
|
resolveHeaders: () => this.#context.resolveHeaders(headers),
|
|
418
|
+
redirect: this.#context.redirect,
|
|
416
419
|
sessionId,
|
|
417
420
|
signal,
|
|
418
421
|
startIndex
|
|
@@ -427,6 +430,7 @@ var ClientSession = class {
|
|
|
427
430
|
host: this.#context.host,
|
|
428
431
|
maxReconnectAttempts: this.#context.maxReconnectAttempts,
|
|
429
432
|
resolveHeaders: () => this.#context.resolveHeaders(),
|
|
433
|
+
redirect: this.#context.redirect,
|
|
430
434
|
sessionId,
|
|
431
435
|
signal: options?.signal,
|
|
432
436
|
startIndex: streamIndex
|
|
@@ -458,6 +462,7 @@ async function postTurnWithRetry(input) {
|
|
|
458
462
|
body: input.body,
|
|
459
463
|
headers: input.headers,
|
|
460
464
|
method: "POST",
|
|
465
|
+
redirect: input.redirect,
|
|
461
466
|
signal: input.signal ?? null
|
|
462
467
|
});
|
|
463
468
|
if (response.ok) return response;
|
|
@@ -498,17 +503,19 @@ var Client = class {
|
|
|
498
503
|
#host;
|
|
499
504
|
#maxReconnectAttempts;
|
|
500
505
|
#preserveCompletedSessions;
|
|
506
|
+
#redirect;
|
|
501
507
|
constructor(options) {
|
|
502
508
|
this.#host = options.host;
|
|
503
509
|
this.#auth = options.auth;
|
|
504
510
|
this.#headers = options.headers;
|
|
505
511
|
this.#maxReconnectAttempts = options.maxReconnectAttempts ?? 3;
|
|
506
512
|
this.#preserveCompletedSessions = options.preserveCompletedSessions ?? false;
|
|
513
|
+
this.#redirect = options.redirect;
|
|
507
514
|
}
|
|
508
515
|
async health() {
|
|
509
516
|
const url = createClientUrl(this.#host, EVE_HEALTH_ROUTE_PATH);
|
|
510
517
|
const headers = await this.#resolveHeaders();
|
|
511
|
-
const response = await fetch(url, { headers });
|
|
518
|
+
const response = await fetch(url, withRedirectPolicy({ headers }, this.#redirect));
|
|
512
519
|
if (!response.ok) {
|
|
513
520
|
const body = await response.text();
|
|
514
521
|
throw new ClientError(response.status, body);
|
|
@@ -518,7 +525,7 @@ var Client = class {
|
|
|
518
525
|
async info() {
|
|
519
526
|
const url = createClientUrl(this.#host, EVE_INFO_ROUTE_PATH);
|
|
520
527
|
const headers = await this.#resolveHeaders();
|
|
521
|
-
const response = await fetch(url, { headers });
|
|
528
|
+
const response = await fetch(url, withRedirectPolicy({ headers }, this.#redirect));
|
|
522
529
|
if (!response.ok) {
|
|
523
530
|
const body = await response.text();
|
|
524
531
|
throw new ClientError(response.status, body);
|
|
@@ -528,10 +535,10 @@ var Client = class {
|
|
|
528
535
|
async fetch(path, init = {}) {
|
|
529
536
|
const url = createClientUrl(this.#host, path);
|
|
530
537
|
const headers = await this.#resolveHeaders(headersInitToRecord(init.headers));
|
|
531
|
-
return await fetch(url, {
|
|
538
|
+
return await fetch(url, withRedirectPolicy({
|
|
532
539
|
...init,
|
|
533
540
|
headers
|
|
534
|
-
});
|
|
541
|
+
}, this.#redirect));
|
|
535
542
|
}
|
|
536
543
|
session(state) {
|
|
537
544
|
let resolved;
|
|
@@ -545,6 +552,7 @@ var Client = class {
|
|
|
545
552
|
host: this.#host,
|
|
546
553
|
maxReconnectAttempts: this.#maxReconnectAttempts,
|
|
547
554
|
preserveCompletedSessions: this.#preserveCompletedSessions,
|
|
555
|
+
redirect: this.#redirect,
|
|
548
556
|
resolveHeaders: (perRequest) => this.#resolveHeaders(perRequest)
|
|
549
557
|
}, resolved);
|
|
550
558
|
}
|
|
@@ -582,6 +590,12 @@ function headersInitToRecord(headers) {
|
|
|
582
590
|
if (headers === void 0) return {};
|
|
583
591
|
return Object.fromEntries(new Headers(headers).entries());
|
|
584
592
|
}
|
|
593
|
+
function withRedirectPolicy(init, redirect) {
|
|
594
|
+
return redirect === void 0 ? init : {
|
|
595
|
+
...init,
|
|
596
|
+
redirect
|
|
597
|
+
};
|
|
598
|
+
}
|
|
585
599
|
function encodeBasicCredentials(username, password) {
|
|
586
600
|
const bytes = new TextEncoder().encode(`${username}:${password}`);
|
|
587
601
|
const binaryString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
|
|
@@ -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{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
|
|
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 c=resolve(e),l=t===`.`,d=l?c:join(c,t);if(l)await assertCanScaffoldInPlace(d);else if(await pathExists(d))throw Error(`Cannot create project because "${d}" already exists.`);let m=await mkdtemp(join(c,`.eve-init-`));try{let e={projectName:l?basename(d):t,model:DEFAULT_AGENT_MODEL_ID,evePackage:a,targetDirectory:m,packageManager:n},s=await i.scaffoldBaseProject(e);return r.channelWebNextjs===!0&&await i.ensureChannel({projectRoot:s,kind:`web`,packageManager:n,configureVercelServices:!1}),l?await moveDirectoryContents(s,d):await rename(s,d),d}finally{await rm(m,{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,c=isLogLevelEnabled(`debug`),l=startCliLiveRow(n);l.update(`Preparing project`);try{let e=await t.isCodingAgentLaunch(),a=o??`.`,u=isCurrentDirectoryTarget(a),d=u?await pathExists(join(resolve(i),`package.json`))?resolve(i):void 0:await resolveTargetDirectory(i,a),f=resolveInitEvePackageOverride(),p=d===void 0?`creating agent`:`adding agent`;l.update(d===void 0?`Creating agent`:`Adding agent`),initLog.debug(p);let m=t.now(),h;if(d===void 0){let e=u?`.`:parseProjectName(a),n=resolve(i),o=await resolveScaffoldPackageManager(e===`.`?n:join(n,e),t);h={kind:`created`,packageManager:o,projectPath:await scaffoldProject(i,e,o,r,t,f)}}else{let e=await addToExistingProject(d,r,t,f);h=e.nodeEngineOverride===void 0?{kind:`added`,packageManager:e.packageManager,projectPath:d}:{kind:`added`,nodeEngineOverride:e.nodeEngineOverride,packageManager:e.packageManager,projectPath:d}}let g=t.now()-m;initLog.debug(`${p} done`,{ms:g}),l.update(`Installing dependencies`,`${h.packageManager} install`),initLog.debug(`installing dependencies with ${h.packageManager}`);let _=t.now(),v=[],y=[],b=await t.runPackageManagerInstall(h.packageManager,h.projectPath,{bypassMinimumReleaseAge:!0,progressDetails:process.stdout.isTTY===!0&&!c,onOutput:e=>{e.text.trim()!==``&&(y.push(e.text),y.length>20&&y.shift(),NPM_NOISE_LINE.test(e.text)||v.push(e.text)),c&&initLog.debug(e.text);let t=installProgressDetail(h.packageManager,e);t!==void 0&&l.update(`Installing dependencies`,t)}}),x=t.now()-_;if(!b){initLog.debug(`dependency installation failed`,{ms:x}),l.stop();let e=v.length>0?v:y;for(let t of e)n.error(t);throw Error(`Failed to install dependencies in "${h.projectPath}".`)}return initLog.debug(`dependencies installed`,{ms:x}),h.kind===`created`?(l.update(`Initializing Git repository`),initLog.debug(`initializing git repository`),{...h,agentElapsedMs:g,agentLaunched:e,gitResult:await t.tryInitializeGit(h.projectPath),installElapsedMs:x}):{...h,agentElapsedMs:g,agentLaunched:e,installElapsedMs:x}}finally{l.stop()}}async function runInitCommand(e,t,r,i,a=defaultDependencies){let o=await runInitSteps({dependencies:a,logger:e,options:i,parentDirectory:t,target:r});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 s=eveDevArguments(o.packageManager);if(e.log(import_picocolors.default.dim(`$ eve dev`)),!await a.spawnPackageManager(o.packageManager,o.projectPath,s))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};
|
|
@@ -49,7 +49,7 @@ export declare function typeaheadCompletion(spec: PromptCommandSpec): string;
|
|
|
49
49
|
export declare function inlineCommandHint(state: CommandTypeaheadState): string | undefined;
|
|
50
50
|
/**
|
|
51
51
|
* Paints the suggestion rows (the select-question grammar): the highlight
|
|
52
|
-
* carries the cursor glyph and
|
|
52
|
+
* carries the cursor glyph and inverse-blue name, every row shows its aliases and
|
|
53
53
|
* description dim, and overflow windows around the highlight. The argument
|
|
54
54
|
* hint is held back for the inline exact-match view ({@link inlineCommandHint})
|
|
55
55
|
* — it only earns space once a single command is committed to.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sliceVisible,visibleLength}from"./terminal-text.js";function typeaheadFor(e,t,n){let r=matchingCommands(e,t),i=n===void 0?void 0:n.matches[n.selectedIndex],a=i===void 0?-1:r.indexOf(i);return{query:t,matches:r,selectedIndex:a>=0?a:0,dismissed:n!==void 0&&n.dismissed&&n.query===t}}function matchingCommands(e,t){if(!t.startsWith(`/`)||/\s/.test(t))return[];let n=t.slice(1);return e.filter(e=>[e.name,...e.aliases].some(e=>e.startsWith(n)))}function isTypeaheadOpen(e){return e.matches.length>0&&!e.dismissed}function moveTypeaheadSelection(e,t){let n=e.matches.length;if(n===0)return e;let r=(e.selectedIndex+t+n)%n;return{...e,selectedIndex:r}}function dismissTypeahead(e){return e.dismissed?e:{...e,dismissed:!0}}function selectedTypeaheadCommand(e){return e.matches[e.selectedIndex]}function typeaheadCompletion(e){return`/${e.name}${e.takesArgument?` `:``}`}function inlineCommandHint(e){if(e.dismissed||e.matches.length!==1)return;let t=e.matches[0],n=e.query.startsWith(`/`)?e.query.slice(1):e.query;if([t.name,...t.aliases].includes(n))return t.argumentHint??``}function renderCommandSuggestions(
|
|
1
|
+
import{sliceVisible,visibleLength}from"./terminal-text.js";import{renderCursorRow}from"#setup/cli/option-row.js";function typeaheadFor(e,t,n){let r=matchingCommands(e,t),i=n===void 0?void 0:n.matches[n.selectedIndex],a=i===void 0?-1:r.indexOf(i);return{query:t,matches:r,selectedIndex:a>=0?a:0,dismissed:n!==void 0&&n.dismissed&&n.query===t}}function matchingCommands(e,t){if(!t.startsWith(`/`)||/\s/.test(t))return[];let n=t.slice(1);return e.filter(e=>[e.name,...e.aliases].some(e=>e.startsWith(n)))}function isTypeaheadOpen(e){return e.matches.length>0&&!e.dismissed}function moveTypeaheadSelection(e,t){let n=e.matches.length;if(n===0)return e;let r=(e.selectedIndex+t+n)%n;return{...e,selectedIndex:r}}function dismissTypeahead(e){return e.dismissed?e:{...e,dismissed:!0}}function selectedTypeaheadCommand(e){return e.matches[e.selectedIndex]}function typeaheadCompletion(e){return`/${e.name}${e.takesArgument?` `:``}`}function inlineCommandHint(e){if(e.dismissed||e.matches.length!==1)return;let t=e.matches[0],n=e.query.startsWith(`/`)?e.query.slice(1):e.query;if([t.name,...t.aliases].includes(n))return t.argumentHint??``}function renderCommandSuggestions(r,i,a){let o=i.colors,s=r.matches.length,c=Math.min(s,10),l=Math.max(0,Math.min(r.selectedIndex-Math.floor(c/2),s-c)),u=Math.min(l+c,s),d=r.matches.slice(l,u),invocation=e=>{let t=e.aliases.map(e=>` (/${e})`).join(``);return`/${e.name}${t}`},f=Math.max(...d.map(e=>invocation(e).length))+2;return d.map((e,t)=>{let a=l+t===r.selectedIndex,s=`/${e.name}`,c=renderCursorRow(a?`${i.glyph.selectedPointer} ${s}`:` ${s}`,a,o),u=invocation(e).slice(`/${e.name}`.length),d=` `.repeat(f-invocation(e).length);return a&&(u.startsWith(` `)?u=u.slice(1):d=d.slice(1)),`${c}${o.dim(u)}${d}${o.dim(e.description)}`}).map(n=>visibleLength(n)>a?sliceVisible(n,a):n)}export{dismissTypeahead,inlineCommandHint,isTypeaheadOpen,moveTypeaheadSelection,renderCommandSuggestions,selectedTypeaheadCommand,typeaheadCompletion,typeaheadFor};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{toErrorMessage}from"#shared/errors.js";function createPromptCommandHandler(t){return{async handle(n,r){let i=t.appRoot;if(i===void 0)return{message:`/${n.name} needs eve dev running the local server (it is not available with --url).`};if(n.name===`model`&&n.argument.length>0)try{let{changeAgentModel:e,formatApplyModelOutcome:r,modelChangeRefusalForUneditableModel:a}=await import(`#setup/flows/model.js`),o=await(t.modelChangeRefusal??a)(i);return o===null?{message:r(await(t.applyModel??e)({appRoot:i,slug:n.argument}))}:{message:o}}catch(t){return{message:`Couldn't change the model: ${toErrorMessage(t)}`}}let a=r.renderer.setupFlow;if(a===void 0)return{message:`/${n.name} is not supported by this renderer.`};let o;try{o=await import(`./setup-commands.js`)}catch(t){return{message:`/${n.name} failed: ${toErrorMessage(t)}`}}let{runTuiSetupCommand:s,SETUP_FLOW_TITLES:c}=o;a.begin(c[n.name]);let l=!0;try{let e={command:n.name,appRoot:i,renderer:a};t.flows!==void 0&&(e.flows=t.flows);let
|
|
1
|
+
import{toErrorMessage}from"#shared/errors.js";function createPromptCommandHandler(t){return{async handle(n,r){let i=t.appRoot;if(i===void 0)return{message:`/${n.name} needs eve dev running the local server (it is not available with --url).`};if(n.name===`model`&&n.argument.length>0)try{let{changeAgentModel:e,formatApplyModelOutcome:r,modelChangeRefusalForUneditableModel:a}=await import(`#setup/flows/model.js`),o=await(t.modelChangeRefusal??a)(i);return o===null?{message:r(await(t.applyModel??e)({appRoot:i,slug:n.argument}))}:{message:o}}catch(t){return{message:`Couldn't change the model: ${toErrorMessage(t)}`}}let a=r.renderer.setupFlow;if(a===void 0)return{message:`/${n.name} is not supported by this renderer.`};let o;try{o=await import(`./setup-commands.js`)}catch(t){return{message:`/${n.name} failed: ${toErrorMessage(t)}`}}let{runTuiSetupCommand:s,SETUP_FLOW_TITLES:c}=o;a.begin(c[n.name]);let l=!0;try{let e={command:n.name,appRoot:i,renderer:a};r.initialModelStep!==void 0&&(e.initialModelStep=r.initialModelStep),t.flows!==void 0&&(e.flows=t.flows);let o=await s(e);l=o.preserveFlowDiagnostics;let c={message:o.message};return o.effect!==void 0&&(c.effect=o.effect),c}finally{a.end({preserveDiagnostics:l})}}}}export{createPromptCommandHandler};
|
|
@@ -221,13 +221,17 @@ export type AgentTUIRenderer = {
|
|
|
221
221
|
export interface PromptCommandHandlerContext {
|
|
222
222
|
readonly renderer: AgentTUIRenderer;
|
|
223
223
|
readonly title: string;
|
|
224
|
+
/** Provider entry authorized by confirmed boot-time model-access evidence. */
|
|
225
|
+
readonly initialModelStep?: "provider";
|
|
224
226
|
}
|
|
225
227
|
/** What one handled slash command leaves behind for the runner to apply. */
|
|
226
228
|
export interface PromptCommandOutcome {
|
|
227
229
|
/** Outcome line rendered under the echoed command; absent renders nothing. */
|
|
228
230
|
message?: string;
|
|
229
|
-
/**
|
|
230
|
-
|
|
231
|
+
/** Post-command work; model access also re-probes the Vercel identity. */
|
|
232
|
+
effect?: VercelStatusEffect | {
|
|
233
|
+
kind: "model-access-changed";
|
|
234
|
+
};
|
|
231
235
|
}
|
|
232
236
|
export interface PromptCommandHandler {
|
|
233
237
|
handle(command: Extract<PromptCommand, {
|
|
@@ -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{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
|
+
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,automaticSetupCommand,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{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.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(){if(this.#f===void 0){this.#I(),await this.#V(void 0);return}let e;try{e=await devBootPhase(`connecting to agent`,()=>this.#t?this.#t.info():Promise.resolve(void 0),this.#v)}catch{e=void 0}this.#I(),this.#F(e),await this.#V(e)}#F(e){this.#E=e;let t=this.#f;if(t===void 0)return;let n={name:this.#r,serverUrl:t};e!==void 0&&(n.info=e),this.#p!==void 0&&(n.tip=this.#T),this.#n.renderAgentHeader?.(n)}#I(){let e=this.#v;this.#v=void 0,e?.({type:`before-first-paint`})}async run(){try{await this.#L()}finally{this.#y=!0,this.#b.abort(),this.#N?.(),this.#N=void 0,this.#n.shutdown?.(),this.#w?.dispose()}}async#L(){let e=this.#r,r,i,a,o=!1,s=!1,c=this.#m;for(await this.#P(),this.#G(),this.#w?.refreshIdentity(),this.#h!==void 0&&this.#n.setupFlow!==void 0&&(i=automaticSetupCommand(this.#S),r=i?.prompt);;){if(!s){if(r==null){if(!this.#n.readPrompt){if(o)return;throw Error(`No prompt was provided and the renderer does not support prompt input.`)}let t={title:e};c!==void 0&&(t.initialDraft=c,c=void 0);try{r=await this.#z(t)}catch(e){if(isInterruptedError(e))return;throw e}if(r==null)return}let u=parsePromptCommand(r);if(u?.type===`exit`)return;if(u?.type===`new`){this.#R(),a=void 0,s=!1,r=void 0,this.#n.reset?.();continue}if(u?.type===`help`){this.#K(formatPromptCommandHelp()),a=void 0,s=!1,r=void 0;continue}if(u?.type===`loglevel`){this.#K(this.#q(u.argument)),a=void 0,s=!1,r=void 0;continue}if(u?.type===`extension`){try{let t=u.name===`model`?i?.initialModelStep:void 0,n=t===void 0?{renderer:this.#n,title:e}:{renderer:this.#n,title:e,initialModelStep:t};i=void 0;let r=this.#h===void 0?{message:`/${u.name} is not available in this session.`}:await this.#h.handle(u,n);r?.message!==void 0&&this.#K(r.message);let a=r?.effect;a?.kind===`model-access-changed`?(this.#w?.applyEffect({kind:`refresh-identity`}),this.#x=!0,await this.#J()):a!==void 0&&(this.#w?.applyEffect(a),this.#x=!0,this.#W(this.#E))}catch(e){if(isInterruptedError(e))return;throw e}a=void 0,r=void 0,s=!1;continue}o=!0}let u=await this.#B({prompt:s?void 0:r,inputResponses:a});try{await this.#n.renderStream(u,{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=u.turnState?.pendingApprovals??[],n=u.turnState?.pendingQuestions??[];if(t.length>0||n.length>0){let i=[];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});i.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 a={requestId:t.requestId};r.optionId!==void 0&&(a.optionId=r.optionId),r.text!==void 0&&(a.text=r.text),i.push(a),this.#D.delete(t.requestId)}}s=!0,a=i,r=void 0;continue}u.turnState&&u.turnState.boundaryEvent===void 0&&(this.#M=!0)}catch(e){if(isInterruptedError(e))return;throw e}s=!1,a=void 0,r=void 0,this.#M&&(this.#M=!1,this.#R(),this.#n.renderNotice?.(`Session ended — started a new session. Earlier context was cleared.`))}}#R(){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#z(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.#X(),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#B(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.#X(),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.#ee(e),onSubagentCompleted:e=>this.#ne(e),onConnectionAuthRequired:e=>this.#Z(e),onConnectionAuthCompleted:e=>this.#Q(e),onTerminalFailure:()=>{this.#M=!0},failureOverride:this.#p===void 0?void 0:e=>isGatewayAuthFailure(e)?formatGatewayAuthFailureNotice(e):void 0}),turnState:i}}async#V(e){if(this.#p===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.#n.renderSetupWarning!==void 0&&(this.#H(),this.#U())}#H(){let e=orderedSetupIssues(this.#S,this.#C);e.length>0?this.#n.renderSetupWarning?.(formatSetupIssuesLine(e)):this.#n.clearSetupWarning?.()}async#U(){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.#H())}async#W(e){let t=this.#p;if(t===void 0||this.#n.renderSetupWarning===void 0)return;let n={appRoot:t,env:process.env};e!==void 0&&(n.info=e);try{this.#S=await detectSetupIssues(n,this.#g);let e=await this.#_(t,{signal:this.#b.signal});this.#C=authIssueForStatus(e)}catch{return}this.#y||this.#H()}#G(){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)}))}#K(e){if(this.#n.renderCommandResult!==void 0){this.#n.renderCommandResult(e);return}this.#n.renderNotice?.(e)}#q(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#J(){let e=this.#p;if(e===void 0)return;loadDevelopmentEnvironmentFiles(e);let t=await this.#Y();this.#F(t),this.#W(t)}async#Y(){try{return await this.#t?.info()}catch{return}}async#X(){let e=this.#E,t=await this.#Y();t!==void 0&&this.#F(t),(!this.#n.renderAgentHeader||t===void 0)&&this.#n.renderNotice?.(formatAgentUpdateNotice(e,t))}#Z(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.#$(t)}#Q(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.#$(t),this.#n.setConnectionAuthPendingCount?.(this.#j.size)}#$(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)}#ee(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.#re(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)}})()}#te(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})}#ne(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}}#re(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.#te(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.#te(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};
|
|
@@ -25,6 +25,8 @@ export interface TuiSetupCommandInput {
|
|
|
25
25
|
appRoot: string;
|
|
26
26
|
/** The renderer surface the TUI-native prompter drives. */
|
|
27
27
|
renderer: TuiSetupCommandRenderer;
|
|
28
|
+
/** Initial model-flow step authorized by the runner's boot evidence. */
|
|
29
|
+
initialModelStep?: "provider";
|
|
28
30
|
/** Test seam; defaults to the real TUI-native prompter over `renderer`. */
|
|
29
31
|
createPrompter?: (renderer: TuiPrompterRenderer) => Prompter;
|
|
30
32
|
/** Test seam; defaults to the real setup flows. */
|
|
@@ -42,8 +44,10 @@ export interface TuiSetupCommandResult {
|
|
|
42
44
|
message: string;
|
|
43
45
|
/** Keep warning/error lines after the bordered panel closes. */
|
|
44
46
|
preserveFlowDiagnostics: boolean;
|
|
45
|
-
/** Status
|
|
46
|
-
|
|
47
|
+
/** Status refresh required after the command settles. */
|
|
48
|
+
effect?: VercelStatusEffect | {
|
|
49
|
+
kind: "model-access-changed";
|
|
50
|
+
};
|
|
47
51
|
}
|
|
48
52
|
/**
|
|
49
53
|
* Runs one TUI setup command (/model, /channels, /deploy) over the
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createTuiPrompter}from"./tui-prompter.js";import{runDeployFlow}from"#setup/flows/deploy.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{runChannelsFlow}from"#setup/flows/channels.js";import{runInstallVercelCliFlow}from"#setup/flows/install-vercel-cli.js";import{runLoginFlow}from"#setup/flows/login.js";import{runModelFlow}from"#setup/flows/model.js";import{openUrl}from"#setup/primitives/open-url.js";import{slackMessageDeepLink}from"#setup/slack-connect.js";import{WizardCancelledError}from"#setup/step.js";const SETUP_FLOW_TITLES={vc:`Install the Vercel CLI`,login:`Log in to Vercel`,model:`Configure the agent model`,channels:`Agent channels`,deploy:`Deploy to Vercel`};function muteableRenderer(e,t){return{readSelect:n=>t()?Promise.resolve(void 0):e.readSelect(n),readEditableSelect:n=>t()?Promise.resolve(void 0):e.readEditableSelect(n),readText:n=>t()?Promise.resolve(void 0):e.readText(n),readAcknowledge:n=>t()?Promise.resolve():e.readAcknowledge(n),readChoice:n=>t()?{choice:Promise.resolve(void 0),close:()=>{}}:e.readChoice(n),setStatus:n=>{t()||e.setStatus(n)},renderLine:(n,r)=>{(!t()||r===`warning`||r===`error`)&&e.renderLine(n,r)},renderOutput:n=>{t()||e.renderOutput(n)}}}async function runTuiSetupCommand(t){let{command:n}=t,r=!1,i=new AbortController,a=(t.createPrompter??createTuiPrompter)(muteableRenderer(t.renderer,()=>r)),o=t.renderer.waitForInterrupt(),s=Symbol(`interrupted`),c=executeSetupCommand(t,a,i.signal);try{let e=await Promise.race([c,o.promise.then(()=>s)]);
|
|
2
|
-
`),preserveFlowDiagnostics:!1};return
|
|
1
|
+
import{createTuiPrompter}from"./tui-prompter.js";import{runDeployFlow}from"#setup/flows/deploy.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{runChannelsFlow}from"#setup/flows/channels.js";import{runInstallVercelCliFlow}from"#setup/flows/install-vercel-cli.js";import{runLoginFlow}from"#setup/flows/login.js";import{runModelFlow}from"#setup/flows/model.js";import{openUrl}from"#setup/primitives/open-url.js";import{slackMessageDeepLink}from"#setup/slack-connect.js";import{WizardCancelledError}from"#setup/step.js";const SETUP_FLOW_TITLES={vc:`Install the Vercel CLI`,login:`Log in to Vercel`,model:`Configure the agent model`,channels:`Agent channels`,deploy:`Deploy to Vercel`};function muteableRenderer(e,t){return{readSelect:n=>t()?Promise.resolve(void 0):e.readSelect(n),readEditableSelect:n=>t()?Promise.resolve(void 0):e.readEditableSelect(n),readText:n=>t()?Promise.resolve(void 0):e.readText(n),readAcknowledge:n=>t()?Promise.resolve():e.readAcknowledge(n),readChoice:n=>t()?{choice:Promise.resolve(void 0),close:()=>{}}:e.readChoice(n),setStatus:n=>{t()||e.setStatus(n)},renderLine:(n,r)=>{(!t()||r===`warning`||r===`error`)&&e.renderLine(n,r)},renderOutput:n=>{t()||e.renderOutput(n)}}}async function runTuiSetupCommand(t){let{command:n}=t,r=!1,i=new AbortController,a=(t.createPrompter??createTuiPrompter)(muteableRenderer(t.renderer,()=>r)),o=t.renderer.waitForInterrupt(),s=Symbol(`interrupted`),c=executeSetupCommand(t,a,i.signal);try{let e=await Promise.race([c,o.promise.then(()=>s)]);return e===s?(r=!0,i.abort(new WizardCancelledError),{...await c,message:`/${n} interrupted.`,preserveFlowDiagnostics:!0}):e}finally{o.dispose(),t.renderer.setStatus(void 0)}}async function executeSetupCommand(e,n,s){let{command:c,appRoot:l}=e,u={runInstallVercelCliFlow,runLoginFlow,runModelFlow,runChannelsFlow,runDeployFlow,...e.flows};try{switch(c){case`vc`:return installVercelCliResultMessage(await u.runInstallVercelCliFlow({appRoot:l,prompter:n,signal:s}));case`login`:return loginResultMessage(await u.runLoginFlow({appRoot:l,prompter:n,signal:s}));case`model`:{let t={appRoot:l,prompter:n,signal:s};e.initialModelStep!==void 0&&(t.initialStep=e.initialModelStep);let r=await u.runModelFlow(t);if(r.kind===`cancelled`)return{message:`/model cancelled.`,preserveFlowDiagnostics:!1};let i=[];r.modelMessage!==void 0&&i.push(r.modelMessage),r.providerOutcome!==void 0&&i.push(providerOutcomeMessage(r.providerOutcome));let a={message:i.join(`
|
|
2
|
+
`),preserveFlowDiagnostics:!1};return r.providerOutcome!==void 0&&(a.effect={kind:`model-access-changed`}),a}case`channels`:{let e=await u.runChannelsFlow({appRoot:l,prompter:n,signal:s});switch(e.kind){case`failed`:return pendingChannelsResult(`Channel files changed, but /channels failed: ${e.message}`);case`cancelled`:return{message:`/channels cancelled.`,preserveFlowDiagnostics:!0};case`deploy-and-chat`:return await runDeployAndChat(u,{appRoot:l,prompter:n,signal:s},e.chat);case`done`:return e.addedChannels.length===0?{message:`No channels added.`,preserveFlowDiagnostics:!0}:{message:`Channels added: ${e.addedChannels.join(`, `)} — run /deploy to ship them.`,preserveFlowDiagnostics:!0,effect:{kind:`channels-added`}}}}case`deploy`:{let e=await u.runDeployFlow({appRoot:l,prompter:n,interactive:!0,signal:s});return e.kind===`cancelled`?{message:`/deploy cancelled.`,preserveFlowDiagnostics:!0}:e.kind===`needs-link`?{message:`Not linked to a Vercel project — run /model to connect one first.`,preserveFlowDiagnostics:!0}:{message:e.productionUrl===void 0?`Deployed.`:`Deployed: ${e.productionUrl}`,preserveFlowDiagnostics:!0,effect:{kind:`deployed`}}}}}catch(e){if(e instanceof WizardCancelledError)return{message:`/${c} cancelled.`,preserveFlowDiagnostics:c!==`model`};let t=vercelActionOutcome(e,c);return t===void 0?{message:`/${c} failed: ${e instanceof Error?e.message:String(e)}`,preserveFlowDiagnostics:!0}:t}}function vercelActionOutcome(e,t){if(!(e instanceof HumanActionRequiredError))return;let r=vercelActionMessage(e.action.kind,t);return r===void 0?void 0:{message:r,preserveFlowDiagnostics:!0}}function vercelActionMessage(e,t){switch(e){case`vercel-login`:return`You're not logged in to Vercel — run /login, then retry /${t}.`;case`vercel-forbidden`:return`Vercel denied access to that team — run /login to re-authenticate (for example to complete SSO), or pick a team you can access, then retry /${t}.`;case`vercel-cli-missing`:return`The Vercel CLI isn't installed — run /vc to install it, then retry /${t}.`;default:return}}async function runDeployAndChat(e,t,n){let r;try{r=await e.runDeployFlow({...t,interactive:!0})}catch(e){if(e instanceof WizardCancelledError)return pendingChannelsResult(`Channels added, but /deploy was cancelled. Run /deploy to ship them.`);let t=vercelActionOutcome(e,`deploy`);return pendingChannelsResult(t===void 0?`Channels added, but /deploy failed: ${e instanceof Error?e.message:String(e)}`:`Channels added. ${t.message}`)}if(r.kind===`cancelled`)return pendingChannelsResult(`Channels added, but /deploy was cancelled. Run /deploy to ship them.`);if(r.kind===`needs-link`)return pendingChannelsResult(`Channels added, but this directory is not linked to Vercel. Run /model, then /deploy.`);let i=r.productionUrl===void 0?`Deployed.`:`Deployed: ${r.productionUrl}`,a;if(n.chatUrl===void 0)a=`Message your agent in Slack to see it live.`;else{let e=slackMessageDeepLink(n.chatUrl);openUrl(e),a=`Chat with your agent in Slack: ${e}`}return{message:`${i}\n${a}`,preserveFlowDiagnostics:!0,effect:{kind:`deployed`}}}function installVercelCliResultMessage(e){switch(e.kind){case`cancelled`:return{message:`/vc cancelled.`,preserveFlowDiagnostics:!1};case`already`:return{message:`The Vercel CLI is already installed.`,preserveFlowDiagnostics:!1};case`failed`:return{message:"Couldn't install the Vercel CLI — install it manually with `npm i -g vercel@latest`.",preserveFlowDiagnostics:!0};case`installed`:return{message:`Installed the Vercel CLI. Run /login next.`,preserveFlowDiagnostics:!1,effect:{kind:`refresh-identity`}}}}function loginResultMessage(e){switch(e.kind){case`cancelled`:return{message:`/login cancelled.`,preserveFlowDiagnostics:!1};case`already`:return{message:`You're already logged in to Vercel.`,preserveFlowDiagnostics:!1};case`cli-missing`:return{message:`The Vercel CLI isn't installed — run /vc to install it, then retry /login.`,preserveFlowDiagnostics:!0};case`failed`:return{message:`Vercel login didn't complete — run /login to try again.`,preserveFlowDiagnostics:!0};case`logged-in`:return{message:`Logged in to Vercel.`,preserveFlowDiagnostics:!1,effect:{kind:`refresh-identity`}};case`unavailable`:return{message:`Couldn't reach Vercel — check your connection, then retry /login.`,preserveFlowDiagnostics:!0}}}function pendingChannelsResult(e){return{message:e,preserveFlowDiagnostics:!0,effect:{kind:`channels-added`}}}function providerOutcomeMessage(e){let{credential:t,status:n}=e;return n.kind===`gateway-project`?t===void 0?`Project linked. No model credential found; set AI_GATEWAY_API_KEY in .env.local.`:`Project linked. Connected to AI Gateway via ${t}.`:n.kind===`gateway-key`?`Connected to AI Gateway via ${n.envKey} in ${n.envFile}.`:`Provider updated — no gateway credential detected; set AI_GATEWAY_API_KEY in .env.local.`}export{SETUP_FLOW_TITLES,runTuiSetupCommand};
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import type { AgentInfoResult } from "#client/index.js";
|
|
2
2
|
/** One boot-time setup problem the TUI can point at a fixing command. */
|
|
3
|
-
export
|
|
3
|
+
export type SetupIssue = {
|
|
4
|
+
/** Diagnostics never authorize a command by themselves. */
|
|
5
|
+
kind: "attention";
|
|
4
6
|
/** Short category label, e.g. "AI Gateway credentials". */
|
|
5
7
|
label: string;
|
|
6
8
|
/** The slash command that fixes it, e.g. "/model". */
|
|
7
9
|
command: string;
|
|
8
|
-
}
|
|
10
|
+
} | {
|
|
11
|
+
/** Positive runtime evidence that no model provider is configured. */
|
|
12
|
+
kind: "model-provider-unconfigured";
|
|
13
|
+
label: string;
|
|
14
|
+
command: "/model";
|
|
15
|
+
};
|
|
9
16
|
/** What a boot detection may inspect. */
|
|
10
17
|
export interface BootDetectionContext {
|
|
11
18
|
/** The local project the in-process dev server is running. */
|
|
@@ -49,6 +56,13 @@ export declare const CLI_MISSING_SETUP_ISSUE: SetupIssue;
|
|
|
49
56
|
export declare function detectSetupIssues(context: BootDetectionContext, detections?: readonly BootDetection[]): Promise<SetupIssue[]>;
|
|
50
57
|
/** Places the auth issue before boot-time setup issues. */
|
|
51
58
|
export declare function orderedSetupIssues(bootIssues: readonly SetupIssue[], authIssue: SetupIssue | undefined): SetupIssue[];
|
|
59
|
+
/** The command and entry step authorized by positive setup evidence. */
|
|
60
|
+
export interface AutomaticSetupCommand {
|
|
61
|
+
prompt: "/model";
|
|
62
|
+
initialModelStep: "provider";
|
|
63
|
+
}
|
|
64
|
+
/** Returns the only command authorized to run from positive setup evidence. */
|
|
65
|
+
export declare function automaticSetupCommand(issues: readonly SetupIssue[]): AutomaticSetupCommand | undefined;
|
|
52
66
|
/**
|
|
53
67
|
* The attention line's body, mirroring Claude Code's
|
|
54
68
|
* `1 setup issue: MCP · /doctor` shape; the renderer prefixes the warning
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join}from"node:path";import{pathExists}from"#setup/path-exists.js";const BOOT_DETECTIONS=[{id:`model-provider`,async detect({appRoot:n,env:r,info:i}){let a=
|
|
1
|
+
import{join}from"node:path";import{pathExists}from"#setup/path-exists.js";function modelProviderAccess(e){let t=e.info?.agent.model.endpoint;return t?.kind===`external`?`configured`:t?.kind===`gateway`?t.connected?`configured`:`unconfigured`:e.info?.agent.model.routing?.kind===`external`||e.env.AI_GATEWAY_API_KEY||e.env.VERCEL_OIDC_TOKEN?`configured`:`unknown`}const BOOT_DETECTIONS=[{id:`model-provider`,async detect({appRoot:n,env:r,info:i}){let a=modelProviderAccess({env:r,info:i});if(a===`configured`)return[];let o=await pathExists(join(n,`.vercel`,`project.json`));return a===`unconfigured`?[{kind:`model-provider-unconfigured`,label:o?`AI Gateway credentials missing`:`model provider not linked`,command:`/model`}]:o?[{kind:`attention`,label:`AI Gateway credentials missing`,command:`/model`}]:[{kind:`attention`,label:`model provider not linked`,command:`/model`}]}}],LOGIN_SETUP_ISSUE={kind:`attention`,label:`not logged in`,command:`/login`},CLI_MISSING_SETUP_ISSUE={kind:`attention`,label:`Vercel CLI not found`,command:`/vc`};async function detectSetupIssues(e,t=BOOT_DETECTIONS){return(await Promise.all(t.map(async t=>{try{return await t.detect(e)}catch{return[]}}))).flat()}function orderedSetupIssues(e,t){return t===void 0?[...e]:[t,...e]}function automaticSetupCommand(e){return e.some(e=>e.kind===`model-provider-unconfigured`)?{prompt:`/model`,initialModelStep:`provider`}:void 0}function formatSetupIssuesLine(e){let t=e.length===1?`setup issue`:`setup issues`,n=e.map(e=>`${e.label} · ${e.command}`).join(`, `);return`${e.length} ${t}: ${n}`}export{BOOT_DETECTIONS,CLI_MISSING_SETUP_ISSUE,LOGIN_SETUP_ISSUE,automaticSetupCommand,detectSetupIssues,formatSetupIssuesLine,orderedSetupIssues};
|
|
@@ -1,3 +1,3 @@
|
|
|
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:
|
|
1
|
+
import{clipVisible,renderInputText,visibleLength,wrapVisibleLine}from"./terminal-text.js";import{visibleLine}from"./line-editor.js";import{graphemes}from"#shared/text-boundaries.js";import{renderCursorRow,renderOptionRow,renderOptionRowContinuation,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,selectedPointer:n.glyph.selectedPointer,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:l,theme:u}=e,d=u.colors;for(let e=a;e<o;e+=1){let f=i[e],p=e===s;r.layout===`task-list`&&e===o-1&&e>a&&t.push(``);let{option:m,stackedHint:h}=optionWithoutStackedHint(editableOption(f,p,r.edit,u),r.layout);t.push(` ${optionRow({option:m,isCursor:p,isChecked:r.selection===`multiple`&&n.select.selected.has(f.value),placeholder:optionUsesPlaceholder(r,e,i.length),hintPadding:l-f.label.length,theme:u})}`),h!==void 0&&t.push(` ${renderOptionRowContinuation(dimWithEmphasis(h,u))}`),f.description!==void 0&&(f.disabled===!0||p)&&t.push(` ${d.dim(f.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.glyph.selectedPointer} ${r.colors.bold(`Submit`)}`:` Submit`;e.push(``,` ${renderCursorRow(a,i,r.colors)}`)}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,c=selectMessageRows(e.message,i.layout,t);i.filter!==void 0&&c.push(` ${searchFilter(e.select.filter,i.filter.placeholder,t)}`);let l=0;for(;a[l]?.featured;)l+=1;let f=selectViewSize({search:i.filter!==void 0,filter:e.select.filter,featuredLead:l,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&&c.push(` ${r.dim(`(no matches)`)}`),appendSelectOptionRows({rows:c,state:e,presentation:i,visible:a,start:p,end:m,cursor:s,visibleLabelWidth:h,theme:t}),appendSubmitRow(c,s,o,t),a.length>m-p&&c.push(` ${r.dim(`↑↓ ${a.length} options, showing ${p+1}–${m}`)}`),appendSelectNotices(c,e.notices,i.layout,t,n),e.error!==void 0&&c.push(``,` ${r.red(e.error)}`),c.push(...questionFooter(selectFooterHints(i,a,s),t)),c.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
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};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface DevelopmentTargetBase {
|
|
2
|
+
readonly serverUrl: string;
|
|
3
|
+
/** Local workspace root for app files and the fallback Vercel project link. */
|
|
4
|
+
readonly workspaceRoot: string;
|
|
5
|
+
}
|
|
6
|
+
/** A development TUI session backed by the local `eve dev` server. */
|
|
7
|
+
export interface LocalDevelopmentTarget extends DevelopmentTargetBase {
|
|
8
|
+
readonly kind: "local";
|
|
9
|
+
}
|
|
10
|
+
/** A development TUI session connected to an existing remote server. */
|
|
11
|
+
export interface RemoteDevelopmentTarget extends DevelopmentTargetBase {
|
|
12
|
+
readonly kind: "remote";
|
|
13
|
+
}
|
|
14
|
+
/** Local or remote server backing one development TUI session. */
|
|
15
|
+
export type DevelopmentTuiTarget = LocalDevelopmentTarget | RemoteDevelopmentTarget;
|
|
16
|
+
/** Resolves the explicit name, remote host, or humanized local folder shown by the TUI. */
|
|
17
|
+
export declare function resolveTuiTitle(input: {
|
|
18
|
+
readonly name: string | undefined;
|
|
19
|
+
readonly target: DevelopmentTuiTarget;
|
|
20
|
+
}): string | undefined;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{basename}from"node:path";function resolveTuiTitle(t){if(t.name!==void 0&&t.name.length>0)return t.name;if(t.target.kind===`remote`)try{return new URL(t.target.serverUrl).host}catch{return}let n=basename(t.target.workspaceRoot).replace(/[-_.]+/gu,` `).trim().split(/\s+/u).filter(e=>e.length>0).map(e=>e[0].toUpperCase()+e.slice(1)).join(` `);return n.length>0?n:void 0}export{resolveTuiTitle};
|