eve 0.13.5 → 0.13.7
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 +26 -0
- package/dist/src/channel/send.d.ts +3 -1
- package/dist/src/channel/send.js +1 -1
- package/dist/src/channel/types.d.ts +6 -0
- package/dist/src/chunks/{use-eve-agent-_dbX0ASK.js → use-eve-agent-8X2UMr8q.js} +26 -2
- package/dist/src/chunks/{use-eve-agent-BjAM8_a3.js → use-eve-agent-9ZNiSFMb.js} +26 -2
- package/dist/src/cli/banner.d.ts +2 -4
- package/dist/src/cli/banner.js +1 -1
- package/dist/src/cli/commands/agent-prompt/build-and-verify.md +7 -4
- package/dist/src/cli/dev/tui/agent-header.js +1 -1
- package/dist/src/cli/dev/tui/blocks.d.ts +1 -1
- package/dist/src/cli/dev/tui/blocks.js +1 -1
- package/dist/src/cli/dev/tui/prompt-command-handler.d.ts +5 -1
- package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
- package/dist/src/cli/dev/tui/prompt-commands.d.ts +7 -7
- package/dist/src/cli/dev/tui/prompt-commands.js +2 -2
- package/dist/src/cli/dev/tui/remote-auth-command.d.ts +11 -0
- package/dist/src/cli/dev/tui/remote-auth-command.js +3 -0
- package/dist/src/cli/dev/tui/remote-auth-result.d.ts +5 -0
- package/dist/src/cli/dev/tui/remote-auth-result.js +2 -1
- package/dist/src/cli/dev/tui/remote-auth.d.ts +30 -0
- package/dist/src/cli/dev/tui/remote-auth.js +1 -0
- package/dist/src/cli/dev/tui/remote-connection-probe.d.ts +3 -1
- package/dist/src/cli/dev/tui/remote-connection-probe.js +1 -1
- package/dist/src/cli/dev/tui/remote-connection-types.d.ts +2 -1
- package/dist/src/cli/dev/tui/remote-connection.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +18 -1
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/setup-commands.d.ts +4 -4
- package/dist/src/cli/dev/tui/setup-commands.js +2 -2
- package/dist/src/cli/dev/tui/setup-issues.d.ts +1 -1
- package/dist/src/cli/dev/tui/setup-issues.js +1 -1
- package/dist/src/cli/dev/tui/status-line.d.ts +6 -14
- package/dist/src/cli/dev/tui/status-line.js +1 -1
- package/dist/src/cli/dev/tui/terminal-renderer.d.ts +8 -1
- package/dist/src/cli/dev/tui/terminal-renderer.js +9 -9
- package/dist/src/cli/dev/tui/test/index.d.ts +1 -0
- package/dist/src/cli/dev/tui/test/index.js +1 -1
- package/dist/src/cli/dev/tui/tui.d.ts +1 -1
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/dev/tui/vercel-trusted-sources.js +1 -1
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/agent-info-error.d.ts +17 -0
- package/dist/src/client/agent-info-error.js +1 -0
- package/dist/src/client/client.d.ts +4 -0
- package/dist/src/client/client.js +1 -1
- package/dist/src/client/index.d.ts +1 -0
- package/dist/src/client/index.js +1 -1
- package/dist/src/client/ndjson.js +3 -3
- package/dist/src/context/build-dynamic-tools.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/context/keys.d.ts +2 -0
- package/dist/src/context/keys.js +1 -1
- package/dist/src/evals/cli/eval-client.js +1 -1
- package/dist/src/execution/delegated-parent-notification.js +1 -1
- package/dist/src/execution/durable-session-store.js +1 -1
- package/dist/src/execution/eve-workflow-attributes.d.ts +8 -0
- package/dist/src/execution/eve-workflow-attributes.js +1 -1
- package/dist/src/execution/ndjson-stream.d.ts +19 -0
- package/dist/src/execution/ndjson-stream.js +3 -0
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/subagent-adapter.js +1 -1
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -3
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/connection.js +1 -1
- package/dist/src/internal/nitro/host/configure-nitro-routes.js +1 -1
- package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
- package/dist/src/internal/workflow/configure-world.js +1 -1
- package/dist/src/internal/workflow/queue-namespace.d.ts +0 -1
- package/dist/src/internal/workflow/queue-namespace.js +1 -1
- package/dist/src/internal/workflow/runtime.d.ts +4 -0
- package/dist/src/internal/workflow/runtime.js +1 -0
- package/dist/src/internal/workflow-bundle/builder-support.js +6 -6
- package/dist/src/internal/workflow-bundle/builder.js +2 -2
- package/dist/src/internal/workflow-bundle/vercel-workflow-output.js +1 -1
- package/dist/src/public/channels/github/dispatch.d.ts +22 -1
- package/dist/src/public/channels/github/dispatch.js +1 -1
- package/dist/src/public/channels/github/githubChannel.d.ts +21 -3
- package/dist/src/public/channels/github/githubChannel.js +1 -1
- package/dist/src/public/channels/github/inbound.d.ts +46 -1
- package/dist/src/public/channels/github/inbound.js +2 -2
- package/dist/src/public/channels/github/index.d.ts +1 -1
- package/dist/src/public/channels/github/state.d.ts +3 -1
- package/dist/src/public/channels/github/state.js +1 -1
- package/dist/src/public/channels/slack/interactions.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/runtime/connections/callback-route.js +1 -1
- package/dist/src/runtime/connections/principal.js +1 -1
- package/dist/src/runtime/session-callback-route.js +1 -1
- package/dist/src/services/dev-client/request-headers.d.ts +2 -0
- package/dist/src/services/dev-client/request-headers.js +1 -1
- package/dist/src/services/dev-client/vercel-auth-error.d.ts +12 -14
- package/dist/src/services/dev-client/vercel-auth-error.js +9 -2
- package/dist/src/setup/flows/install-vercel-cli.d.ts +1 -1
- package/dist/src/setup/flows/login.d.ts +3 -1
- package/dist/src/setup/flows/login.js +1 -1
- package/dist/src/setup/primitives/run-vercel.d.ts +8 -0
- package/dist/src/setup/primitives/run-vercel.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +6 -2
- package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
- package/dist/src/setup/scaffold/create/web-template.js +0 -17
- package/dist/src/setup/vercel-deployment.d.ts +12 -5
- package/dist/src/setup/vercel-deployment.js +1 -1
- package/dist/src/setup/vercel-project-api.d.ts +13 -2
- package/dist/src/setup/vercel-project-api.js +1 -1
- package/dist/src/setup/vercel-project.d.ts +5 -1
- package/dist/src/setup/vercel-project.js +0 -0
- package/dist/src/setup/verified-remote-client.js +1 -1
- 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/README.md +2 -2
- package/docs/channels/github.mdx +13 -1
- package/docs/channels/linear.mdx +1 -1
- package/docs/channels/slack.mdx +1 -1
- package/docs/connections/mcp.mdx +61 -0
- package/docs/connections/meta.json +4 -0
- package/docs/connections/openapi.mdx +68 -0
- package/docs/{connections.mdx → connections/overview.mdx} +28 -63
- package/docs/getting-started.mdx +0 -6
- package/docs/guides/dev-tui.md +22 -12
- package/docs/introduction.mdx +2 -8
- package/docs/reference/typescript-api.md +20 -19
- package/docs/tutorial/connect-a-warehouse.mdx +3 -3
- package/docs/tutorial/ship-it.mdx +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.13.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c8014d1: Improve Vercel Connect-backed connection auth by allowing authored definitions to include the `evict` hook and clarifying `principal_required` guidance when user-scoped connections run without an authenticated user principal.
|
|
8
|
+
- ff44c4c: Clarify scaffolded guidance for locating bundled eve package docs in workspaces and local installs.
|
|
9
|
+
- 30c5965: Preserve dynamic tool approval gates when session- and turn-scoped tools are replayed from durable metadata. If a replayed approval callback cannot be recovered, eve now requires approval by default instead of silently running the tool unguarded.
|
|
10
|
+
- 55af52e: Acknowledge Slack view submissions with an empty response body so submitted modals close without an error.
|
|
11
|
+
- dd960df: Fix Vercel CLI detection on Windows by invoking npm's command shims through `cmd.exe`, so an installed `vercel` command is no longer misreported as missing.
|
|
12
|
+
|
|
13
|
+
## 0.13.6
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 7f66a06: Add opt-in GitHub channel hooks for check suite, check run, and workflow run webhooks, with normalized CI metadata and pull request dispatch.
|
|
18
|
+
- a63dfa2: Project search now resolves exact names directly and ranks one fallback result page, avoiding unbounded substring-match pagination for short queries.
|
|
19
|
+
- a63dfa2: Fixed remote `/vc:login` rejecting a freshly resolved Vercel project with "The local Vercel OIDC token does not match the resolved deployment: owner_id." The verified deployment now takes its owner id from Vercel's response instead of the team slug used to scope the lookup, so it matches the OIDC token's `owner_id` claim.
|
|
20
|
+
- a63dfa2: In remote sessions, `/vc:login` resolves the target Vercel project and owning team from the deployment URL. When the target requires authentication and Vercel cannot resolve its host in the active scope, the flow asks you to select another team, then reruns the lookup in that scope. When access is denied, for example because a team SSO session expired, it re-authenticates and retries.
|
|
21
|
+
- a63dfa2: Remote `eve dev --url` now treats `/eve/v1/info` as best-effort inspection rather than a connection gate. Once authentication succeeds and the deployment is reachable, the session connects even when the agent info route is absent (confirmed via the public health route) or returns an unrecognized shape (e.g. a deployment built from an older eve). Inspection-only data is simply omitted from the header in that case, and the underlying parse failure now names the offending fields instead of an opaque message.
|
|
22
|
+
- a63dfa2: Remote `eve dev --url` sessions now show deployment and authentication state, try refreshed project-scoped OIDC credentials at startup, and open a cancellable `/vc:login` recovery flow when access is rejected. The flow can update the target project's Trusted Sources after confirmation.
|
|
23
|
+
- c5071e6: Ensure every eve Workflow runtime entrypoint installs the eve queue namespace through a single guarded boundary.
|
|
24
|
+
- c9e895b: Fix `eve dev` streaming throughput and time-to-first-token degrading as parked (`ask_question` / HITL) sessions accumulate. The dev runtime's NDJSON event-stream reader now forwards cancellation to the underlying run stream, so disconnecting from a parked session no longer leaks a filesystem polling loop for the life of the dev server.
|
|
25
|
+
- c6b2da8: Add `$eve.channel_request_id` workflow attributes from Vercel's `x-vercel-id` header so session and turn workflow runs can be joined back to the inbound request that started or resumed them.
|
|
26
|
+
- ab3e6e8: Give each threadless proactive Slack session a unique temporary continuation token so overlapping scheduled runs targeting the same channel do not conflict before they anchor to a Slack thread.
|
|
27
|
+
- a63dfa2: The dev TUI's `/vc` and `/login` commands are now `/vc:install` and `/vc:login`. `/vc:login` is the single Vercel authentication command: it logs in locally and, in remote (`eve dev --url`) sessions, recovers access with Vercel OIDC.
|
|
28
|
+
|
|
3
29
|
## 0.13.5
|
|
4
30
|
|
|
5
31
|
### Patch Changes
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { ChannelAdapter } from "#channel/adapter.js";
|
|
2
2
|
import type { Runtime } from "#channel/types.js";
|
|
3
3
|
import type { SendFn } from "#channel/routes.js";
|
|
4
|
-
export declare function createSendFn<TState = undefined>(runtime: Runtime, adapter: ChannelAdapter<any>, channelName: string
|
|
4
|
+
export declare function createSendFn<TState = undefined>(runtime: Runtime, adapter: ChannelAdapter<any>, channelName: string, metadata?: {
|
|
5
|
+
readonly requestId?: string;
|
|
6
|
+
}): SendFn<TState>;
|
package/dist/src/channel/send.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createSession}from"#channel/session.js";import{createLogger}from"#internal/logging.js";import{isRuntimeNoActiveSessionError}from"#execution/runtime-errors.js";import{serializeUrlFilePart}from"#internal/attachments/url-refs.js";const log=createLogger(`channel.send`);function createSendFn(t,r,i){return async(
|
|
1
|
+
import{createSession}from"#channel/session.js";import{createLogger}from"#internal/logging.js";import{isRuntimeNoActiveSessionError}from"#execution/runtime-errors.js";import{serializeUrlFilePart}from"#internal/attachments/url-refs.js";const log=createLogger(`channel.send`);function createSendFn(t,r,i,a={}){return async(o,s)=>{let c=s.auth,l=s.callback,u=s.mode??`conversation`,d=s.state,f=s.continuationToken,p=`${i}:${f}`,{message:m,inputResponses:h,context:g,outputSchema:_}=normalizeSendInput(o),v=serializeUrlFilePartsInMessage(m);try{let n={auth:c,continuationToken:p,requestId:a.requestId,payload:{inputResponses:h,message:v,context:g,outputSchema:_}},{sessionId:r}=await t.deliver(n);return createSession(r,f,t)}catch(e){isRuntimeNoActiveSessionError(e)||log.warn(`deliver failed, falling back to starting a new session`,{continuationToken:p})}if(h&&h.length>0)throw Error(`Cannot deliver inputResponses — the target session was not found via continuation token.`);let y={adapter:d?{...r,state:{...r.state,...d}}:r,auth:c,capabilities:u===`conversation`?{requestInput:!0}:void 0,channelName:i,callback:l,continuationToken:p,input:{message:v??``,context:g,outputSchema:_},mode:u,requestId:a.requestId};return createSession((await t.run(y)).sessionId,f,t)}}function serializeUrlFilePartsInMessage(e){if(e===void 0||typeof e==`string`)return e;let t=!1,n=e.map(e=>e.type===`file`&&e.data instanceof URL&&e.data.protocol!==`data:`?(t=!0,{...e,data:serializeUrlFilePart(e.data)}):e);return t?n:e}function normalizeSendInput(e){return typeof e==`string`||Array.isArray(e)?{message:e}:e}export{createSendFn};
|
|
@@ -87,6 +87,8 @@ export interface DeliverPayload {
|
|
|
87
87
|
*/
|
|
88
88
|
export interface DeliverHookPayload {
|
|
89
89
|
readonly auth?: SessionAuthContext | null;
|
|
90
|
+
/** Inbound channel request id used only for workflow attributes. */
|
|
91
|
+
readonly requestId?: string;
|
|
90
92
|
readonly kind: "deliver";
|
|
91
93
|
readonly payloads: readonly DeliverPayload[];
|
|
92
94
|
}
|
|
@@ -193,6 +195,8 @@ export interface RunInput {
|
|
|
193
195
|
* leave this undefined.
|
|
194
196
|
*/
|
|
195
197
|
readonly capabilities?: SessionCapabilities;
|
|
198
|
+
/** Inbound channel request id used to correlate workflow attributes. */
|
|
199
|
+
readonly requestId?: string;
|
|
196
200
|
/**
|
|
197
201
|
* Optional terminal callback. When present, the runtime posts a single
|
|
198
202
|
* callback when the session completes or fails.
|
|
@@ -229,6 +233,8 @@ export interface DeliverInput {
|
|
|
229
233
|
* this field before calling the adapter's hooks.
|
|
230
234
|
*/
|
|
231
235
|
readonly auth?: SessionAuthContext | null;
|
|
236
|
+
/** Inbound channel request id used to correlate workflow attributes. */
|
|
237
|
+
readonly requestId?: string;
|
|
232
238
|
readonly continuationToken: string;
|
|
233
239
|
readonly payload: DeliverPayload;
|
|
234
240
|
}
|
|
@@ -20,6 +20,18 @@ function createEveContinueSessionRoutePath(sessionId) {
|
|
|
20
20
|
return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}`;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/client/agent-info-error.ts
|
|
25
|
+
var AgentInfoResponseError = class extends Error {
|
|
26
|
+
issues;
|
|
27
|
+
constructor(issues = []) {
|
|
28
|
+
const detail = issues.length === 0 ? "" : ` (${issues.join("; ")})`;
|
|
29
|
+
super(`The server returned an unrecognized response from the eve agent info route.${detail}`);
|
|
30
|
+
this.name = "AgentInfoResponseError";
|
|
31
|
+
this.issues = issues;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
23
35
|
//#endregion
|
|
24
36
|
//#region src/client/agent-info-schema.ts
|
|
25
37
|
const source = z.object({
|
|
@@ -397,10 +409,12 @@ async function* readNdjsonStream(body) {
|
|
|
397
409
|
const reader = body.getReader();
|
|
398
410
|
const decoder = new TextDecoder();
|
|
399
411
|
let buffer = "";
|
|
412
|
+
let reachedEof = false;
|
|
400
413
|
try {
|
|
401
414
|
while (true) {
|
|
402
415
|
const result = await reader.read();
|
|
403
416
|
if (result.done) {
|
|
417
|
+
reachedEof = true;
|
|
404
418
|
buffer += decoder.decode();
|
|
405
419
|
break;
|
|
406
420
|
}
|
|
@@ -416,6 +430,7 @@ async function* readNdjsonStream(body) {
|
|
|
416
430
|
const trailing = buffer.trim();
|
|
417
431
|
if (trailing.length > 0) yield JSON.parse(trailing);
|
|
418
432
|
} finally {
|
|
433
|
+
if (!reachedEof) await reader.cancel().catch(() => {});
|
|
419
434
|
reader.releaseLock();
|
|
420
435
|
}
|
|
421
436
|
}
|
|
@@ -720,8 +735,17 @@ var Client = class {
|
|
|
720
735
|
const body = await response.text();
|
|
721
736
|
throw new ClientError(response.status, body);
|
|
722
737
|
}
|
|
723
|
-
|
|
724
|
-
|
|
738
|
+
let payload;
|
|
739
|
+
try {
|
|
740
|
+
payload = await response.json();
|
|
741
|
+
} catch {
|
|
742
|
+
throw new AgentInfoResponseError();
|
|
743
|
+
}
|
|
744
|
+
const result = AgentInfoResultSchema.safeParse(payload);
|
|
745
|
+
if (!result.success) throw new AgentInfoResponseError(result.error.issues.slice(0, 5).map((issue) => {
|
|
746
|
+
const path = issue.path.join(".");
|
|
747
|
+
return path.length === 0 ? issue.message : `${path}: ${issue.message}`;
|
|
748
|
+
}));
|
|
725
749
|
return result.data;
|
|
726
750
|
}
|
|
727
751
|
async fetch(path, init = {}) {
|
|
@@ -20,6 +20,18 @@ function createEveContinueSessionRoutePath(sessionId) {
|
|
|
20
20
|
return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}`;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/client/agent-info-error.ts
|
|
25
|
+
var AgentInfoResponseError = class extends Error {
|
|
26
|
+
issues;
|
|
27
|
+
constructor(issues = []) {
|
|
28
|
+
const detail = issues.length === 0 ? "" : ` (${issues.join("; ")})`;
|
|
29
|
+
super(`The server returned an unrecognized response from the eve agent info route.${detail}`);
|
|
30
|
+
this.name = "AgentInfoResponseError";
|
|
31
|
+
this.issues = issues;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
23
35
|
//#endregion
|
|
24
36
|
//#region src/client/agent-info-schema.ts
|
|
25
37
|
const source = z.object({
|
|
@@ -397,10 +409,12 @@ async function* readNdjsonStream(body) {
|
|
|
397
409
|
const reader = body.getReader();
|
|
398
410
|
const decoder = new TextDecoder();
|
|
399
411
|
let buffer = "";
|
|
412
|
+
let reachedEof = false;
|
|
400
413
|
try {
|
|
401
414
|
while (true) {
|
|
402
415
|
const result = await reader.read();
|
|
403
416
|
if (result.done) {
|
|
417
|
+
reachedEof = true;
|
|
404
418
|
buffer += decoder.decode();
|
|
405
419
|
break;
|
|
406
420
|
}
|
|
@@ -416,6 +430,7 @@ async function* readNdjsonStream(body) {
|
|
|
416
430
|
const trailing = buffer.trim();
|
|
417
431
|
if (trailing.length > 0) yield JSON.parse(trailing);
|
|
418
432
|
} finally {
|
|
433
|
+
if (!reachedEof) await reader.cancel().catch(() => {});
|
|
419
434
|
reader.releaseLock();
|
|
420
435
|
}
|
|
421
436
|
}
|
|
@@ -720,8 +735,17 @@ var Client = class {
|
|
|
720
735
|
const body = await response.text();
|
|
721
736
|
throw new ClientError(response.status, body);
|
|
722
737
|
}
|
|
723
|
-
|
|
724
|
-
|
|
738
|
+
let payload;
|
|
739
|
+
try {
|
|
740
|
+
payload = await response.json();
|
|
741
|
+
} catch {
|
|
742
|
+
throw new AgentInfoResponseError();
|
|
743
|
+
}
|
|
744
|
+
const result = AgentInfoResultSchema.safeParse(payload);
|
|
745
|
+
if (!result.success) throw new AgentInfoResponseError(result.error.issues.slice(0, 5).map((issue) => {
|
|
746
|
+
const path = issue.path.join(".");
|
|
747
|
+
return path.length === 0 ? issue.message : `${path}: ${issue.message}`;
|
|
748
|
+
}));
|
|
725
749
|
return result.data;
|
|
726
750
|
}
|
|
727
751
|
async fetch(path, init = {}) {
|
package/dist/src/cli/banner.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export declare const EVE_WORDMARK = "eve";
|
|
2
|
-
export declare const EVE_BETA_TERMS_URL = "https://vercel.com/docs/release-phases/public-beta-agreement";
|
|
3
2
|
/**
|
|
4
3
|
* The boot banner shared by every CLI command that announces itself: the eve
|
|
5
|
-
* badge plus the installed version
|
|
6
|
-
*
|
|
7
|
-
* own variant.
|
|
4
|
+
* badge plus the installed version. Printed only by the CLI program's
|
|
5
|
+
* pre-action hook so commands never compose their own variant.
|
|
8
6
|
*/
|
|
9
7
|
export declare function eveCliBanner(): string;
|
package/dist/src/cli/banner.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{__toESM}from"../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";var import_picocolors=__toESM(require_picocolors(),1);const EVE_WORDMARK=`eve
|
|
1
|
+
import{__toESM}from"../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";var import_picocolors=__toESM(require_picocolors(),1);const EVE_WORDMARK=`eve`;function eveCliBanner(){let{version:e}=resolveInstalledPackageInfo();return`${import_picocolors.default.bgBlack(import_picocolors.default.white(`☰eve `))} ${import_picocolors.default.dim(`v${e}`)}`}export{EVE_WORDMARK,eveCliBanner};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
## Build it out, then verify
|
|
2
2
|
|
|
3
3
|
Work from the project directory. Once eve is installed, the full docs are bundled
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
with the installed package and match its version exactly. In most installs, they
|
|
5
|
+
are at `node_modules/eve/docs/`. In workspaces or local package installs, resolve
|
|
6
|
+
the installed `eve` package location first and read its `docs/` directory. If
|
|
7
|
+
package docs are unavailable, use https://eve.dev/docs as a fallback. Read
|
|
8
|
+
`README.md` in the package docs first, then the guide for what you're adding,
|
|
9
|
+
such as `connections`, `channels/slack`, or `guides/auth-and-route-protection`
|
|
10
|
+
for the Vercel Connect flow.
|
|
8
11
|
|
|
9
12
|
- Put the purpose in `agent/instructions.md` (the always-on system prompt),
|
|
10
13
|
replacing the scaffold's placeholder with what the user said the agent should
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{truncate}from"./tool-format.js";
|
|
1
|
+
import{truncate}from"./tool-format.js";const AGENT_HEADER_TIPS=[`Use /channels to add more ways to reach your agent.`,`Use /deploy to see your agent go live.`,`Type /help to see every command.`];function pickAgentHeaderTip(e=Math.random){return AGENT_HEADER_TIPS[Math.min(AGENT_HEADER_TIPS.length-1,Math.floor(e()*AGENT_HEADER_TIPS.length))]}function buildAgentHeader(t){let{theme:n,info:r,name:i,width:a}=t,o=n.colors,s=[],c=o.bold(`eve`);if(s.push(` ${c} ${o.dim(truncate(i,Math.max(8,a-8)))}`),r&&(r.diagnostics.discoveryErrors>0||r.diagnostics.discoveryWarnings>0)){let e=[];r.diagnostics.discoveryErrors>0&&e.push(o.red(`${r.diagnostics.discoveryErrors} error${plural(r.diagnostics.discoveryErrors)}`)),r.diagnostics.discoveryWarnings>0&&e.push(o.yellow(`${r.diagnostics.discoveryWarnings} warning${plural(r.diagnostics.discoveryWarnings)}`)),s.push(` ${o.dim(n.glyph.warning)} ${e.join(o.dim(` · `))}`)}return t.tip!==void 0&&s.push(` ${o.dim(truncate(t.tip,Math.max(8,a-2)))}`),s}function plural(e){return e===1?``:`s`}export{AGENT_HEADER_TIPS,buildAgentHeader,pickAgentHeaderTip};
|
|
@@ -39,7 +39,7 @@ export interface Block {
|
|
|
39
39
|
* rendered dim beneath the headline, capped to a handful of lines.
|
|
40
40
|
*/
|
|
41
41
|
detail?: string;
|
|
42
|
-
/** Tool
|
|
42
|
+
/** Tool, connection, or synthetic command lifecycle status. */
|
|
43
43
|
status?: ToolStatus;
|
|
44
44
|
/** When true, treat `body` as pre-styled and only wrap + indent it. */
|
|
45
45
|
preformatted?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import{sliceVisible,visibleLength,wrapVisibleLine}from"./terminal-text.js";import{formatValuePretty,truncate}from"./tool-format.js";import{renderMarkdown}from"./markdown.js";import{isPromptControlCommand}from"./prompt-commands.js";function renderBlockLines(e,n,r,i){let a=nestingPrefix(e.depth??0,r);return renderBody(e,Math.max(8,n-visibleLength(a)),r,i).map(e=>`${a}${e}`)}function nestingPrefix(e,t){return e<=0?``:`${t.colors.orange(t.glyph.rule)} `.repeat(e)}function renderBody(e,t,n,r){switch(e.kind){case`user`:return renderUser(e,t,n);case`assistant`:case`subagent-step`:return renderProse(e,t,n);case`reasoning`:return renderReasoning(e,t,n);case`tool`:case`subagent-tool`:return renderTool(e,t,n,r);case`error`:return renderError(e,t,n);case`notice`:return renderNotice(e,t,n);case`warning`:return renderWarning(e,t,n);case`result`:return renderResult(e,t,n);case`flow`:return renderFlow(e,t,n);case`command`:return renderCommand(e,n);case`question`:case`connection-auth`:return renderPreformatted(e,t,n);case`sandbox`:return renderSandbox(e,t,n,r);case`log`:return renderLog(e,t,n,r);case`subagent`:return renderSubagentHeader(e,t,n);case`agent-header`:return(e.body??``).split(`
|
|
2
2
|
`)}}function renderUser(e,t,n){let r=n.colors.cyan(n.glyph.user);return wrap(e.body??``,t-2).map(e=>`${r} ${e}`)}function renderProse(e,t,r){let i=[],o=e.kind===`subagent-step`,s=o?``:`${r.colors.bold(r.colors.white(r.glyph.brand))} `,c=o?``:` `;e.reasoning&&e.reasoning.trim().length>0&&i.push(...renderReasoningLines(e.reasoning,t,r));let l=(e.body??``).trim();return l.length===0&&i.length===0?[`${s}${r.colors.dim(`thinking${r.glyph.ellipsis}`)}`]:(l.length>0&&renderMarkdown(l).split(`
|
|
3
3
|
`).flatMap(e=>wrapVisibleLine(e,t-c.length)).forEach((e,t)=>{t===0&&!o&&i.length===0?i.push(`${s}${e}`):i.push(`${c}${e}`)}),i.length>0?i:[`${s}`])}function renderReasoning(e,t,n){return e.collapsed?[`${n.colors.gray(n.glyph.reasoning)} ${n.colors.dim(`thinking`)}`]:renderReasoningLines(e.body??``,t,n,n.glyph.reasoning)}function renderReasoningLines(e,t,n,r){let i=r?2:0,a=wrap(e.trim(),t-i);return a.length===0?[]:a.map((e,t)=>`${r?t===0?`${n.colors.gray(r)} `:` `:``}${n.colors.dim(n.colors.italic(e))}`)}function renderTool(e,t,n,r){let{icon:a,accent:o}=toolGlyph(e.status??`running`,n,r),s=e.title??`tool`,c=t-2,l=truncatePlain(s,c),u=`${a} ${n.colors.bold(l)}`,d=c-l.length-2,f=e.subtitle??``;f.length>0&&d>=6&&(u+=` ${n.colors.gray(truncate(f,d))}`);let p=[u];return e.expanded?p.push(...renderToolExpanded(e,t,n)):e.status===`done`&&e.result&&e.result.length>0?p.push(resultLine(n.glyph.arrow,e.result,t,n,o)):e.status===`error`&&e.result?p.push(resultLine(n.glyph.arrow,e.result,t,n,n.colors.red)):e.status===`denied`&&p.push(resultLine(n.glyph.arrow,`denied`,t,n,n.colors.yellow)),p}function renderToolExpanded(e,t,n){let i=[],push=(e,a,o)=>{if(a!==void 0){i.push(` ${n.colors.dim(e)}`);for(let e of wrap(formatValuePretty(a),t-4))i.push(` ${o(e)}`)}};return push(`input`,e.toolInput,n.colors.gray),e.status===`error`&&e.result?push(`error`,e.result,n.colors.red):push(`output`,e.toolOutput,n.colors.gray),i}function resultLine(e,t,n,r,a){let o=n-4;return` ${r.colors.dim(e)} ${a(truncate(t,o))}`}function toolGlyph(e,t,n){switch(e){case`done`:return{icon:t.colors.green(t.glyph.success),accent:t.colors.gray};case`error`:return{icon:t.colors.red(t.glyph.error),accent:t.colors.red};case`denied`:return{icon:t.colors.yellow(t.glyph.warning),accent:t.colors.yellow};case`approval`:return{icon:t.colors.yellow(t.glyph.question),accent:t.colors.yellow};default:return{icon:t.colors.yellow(n.spinner),accent:t.colors.gray}}}function renderError(e,t,n){let r=n.colors.red(n.colors.bold(n.glyph.error)),i=e.title??`Error`,a=[`${r} ${n.colors.red(n.colors.bold(i))}`];for(let r of wrap(e.body??``,t-2))a.push(` ${colorizeError(r,n)}`);return a.push(...renderErrorDetail(e.detail,t,n)),a}function renderErrorDetail(e,t,n){if(e===void 0||e.trim().length===0)return[];let r=e.split(`
|
|
4
|
-
`),i=r.slice(0,12),a=i.map(e=>` ${n.colors.dim(truncatePlain(e,Math.max(1,t-2)))}`),o=r.length-i.length;return o>0&&a.push(` ${n.colors.dim(`${n.glyph.ellipsis} +${o} more line${o===1?``:`s`}`)}`),a}const URL_PATTERN=/(https?:\/\/\S+)/u;function colorizeError(e,t){return URL_PATTERN.test(e)?e.split(URL_PATTERN).map((e,n)=>n%2==1?t.colors.cyan(e):t.colors.red(e)).join(``):t.colors.red(e)}function renderNotice(e,t,n){let r=n.colors.dim(n.glyph.dot),i=wrap(e.body??``,t-2);return i.length===0?[r]:i.map(e=>`${r} ${n.colors.dim(e)}`)}function renderAttentionRows(e,t,n){let r=n.colors.yellow(n.glyph.warning);return wrap(e,t-2).map((e,t)=>`${t===0?r:` `} ${paintCommands(e,n)}`)}function renderWarning(e,t,n){return renderAttentionRows(e.body??``,t,n)}function paintCommands(e,t){return e.replace(/\/[a-z
|
|
4
|
+
`),i=r.slice(0,12),a=i.map(e=>` ${n.colors.dim(truncatePlain(e,Math.max(1,t-2)))}`),o=r.length-i.length;return o>0&&a.push(` ${n.colors.dim(`${n.glyph.ellipsis} +${o} more line${o===1?``:`s`}`)}`),a}const URL_PATTERN=/(https?:\/\/\S+)/u;function colorizeError(e,t){return URL_PATTERN.test(e)?e.split(URL_PATTERN).map((e,n)=>n%2==1?t.colors.cyan(e):t.colors.red(e)).join(``):t.colors.red(e)}function renderNotice(e,t,n){let r=n.colors.dim(n.glyph.dot),i=wrap(e.body??``,t-2);return i.length===0?[r]:i.map(e=>`${r} ${n.colors.dim(e)}`)}function renderAttentionRows(e,t,n){let r=n.colors.yellow(n.glyph.warning);return wrap(e,t-2).map((e,t)=>`${t===0?r:` `} ${paintCommands(e,n)}`)}function renderWarning(e,t,n){return renderAttentionRows(e.body??``,t,n)}function paintCommands(e,t){return e.replace(/\/[a-z:-]+/g,e=>isPromptControlCommand(e)?t.colors.blue(e):e)}function renderCommand(e,t){let n=t.colors,r=e.status===`error`?`${n.red(t.glyph.error)} `:``;return[`${n.cyan(t.glyph.user)} ${r}${n.blue(e.body??``)}`]}function renderFlow(e,t,n){let r=n.colors,i=e.title??`info`,a=i===`success`?r.green(n.glyph.success):i===`warning`?r.yellow(n.glyph.warning):i===`error`?r.red(n.glyph.error):r.dim(n.glyph.dot),o=wrap(e.body??``,t-2),paint=e=>i===`info`?r.dim(e):e;return o.map((e,t)=>`${t===0?a:` `} ${paint(e)}`)}function renderResult(e,t,n){let r=n.colors.dim(n.glyph.elbow),i=wrap(e.body??``,t-7);if(i.length===0)return[` ${r}`];let dim=e=>n.colors.dim(e.replaceAll(`\x1B[22m`,`\x1B[22m\x1B[2m`));return i.map((e,t)=>t===0?` ${r} ${dim(e)}`:` ${dim(e)}`)}function renderPreformatted(e,t,r){let i=e.kind===`connection-auth`?r.colors.yellow(r.glyph.connection):r.colors.yellow(r.colors.bold(r.glyph.question)),a=wrap(e.title??``,t-2),o=a.length===0?[`${i} `]:a.map((e,t)=>t===0?`${i} ${r.colors.bold(e)}`:` ${r.colors.bold(e)}`);for(let r of(e.body??``).split(`
|
|
5
5
|
`))for(let e of wrapVisibleLine(r,t-2))o.push(` ${e}`);return o}function renderSandbox(e,r,i,a){let o=i.colors.cyan(i.glyph.rule),s=i.colors.dim(`sandbox ${i.glyph.dot} `),c=visibleLength(s),l=` `.repeat(c),u=a.previous?.kind===`sandbox`,d=(e.body??``).split(`
|
|
6
6
|
`),f=[];for(let e of d){let t=wrapVisibleLine(e,Math.max(1,r-2-c));for(let e of t){let t=f.length===0&&!u?s:l;f.push(`${o} ${t}${i.colors.gray(e)}`)}}return f.length>0?f:[`${o}`]}function renderLog(e,r,i,a){let o=e.title===`stderr`,s=o?i.colors.red:i.colors.gray,c=i.colors.dim(i.glyph.rule),l=o?`stderr`:`stdout`,u=i.colors.dim(`${l} ${i.glyph.dot} `),d=visibleLength(u),f=` `.repeat(d),p=a.previous?.kind===`log`&&a.previous.title===e.title,m=(e.body??``).split(`
|
|
7
7
|
`),h=[];for(let e of m){let t=wrapVisibleLine(e,Math.max(1,r-2-d));for(let e of t){let t=h.length===0&&!p?u:f;h.push(`${c} ${t}${i.colors.dim(s(e))}`)}}return h.length>0?h:[`${c}`]}function renderSubagentHeader(e,t,n){let r=truncatePlain(e.title??`subagent`,Math.max(8,t-14));return[`${n.colors.orange(n.glyph.subagent)} ${n.colors.bold(r)} ${n.colors.dim(`subagent`)}`]}function wrap(e,t){return e.trim().length===0?[]:e.split(`
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { ApplyModelOutcome } from "#setup/flows/model.js";
|
|
2
2
|
import type { PromptCommandHandler } from "./runner.js";
|
|
3
|
+
import type { RemoteAuthFlow } from "./remote-auth.js";
|
|
3
4
|
import type { TuiSetupFlows } from "./setup-commands.js";
|
|
5
|
+
import type { DevelopmentTuiTarget } from "./target.js";
|
|
4
6
|
export interface PromptCommandHandlerOptions {
|
|
5
|
-
readonly
|
|
7
|
+
readonly target: DevelopmentTuiTarget;
|
|
6
8
|
/** Test seam; defaults to the model flow's shared source-change apply. */
|
|
7
9
|
readonly applyModel?: (input: {
|
|
8
10
|
appRoot: string;
|
|
@@ -12,5 +14,7 @@ export interface PromptCommandHandlerOptions {
|
|
|
12
14
|
readonly modelChangeRefusal?: (appRoot: string) => Promise<string | null>;
|
|
13
15
|
/** Test seam; forwarded to runTuiSetupCommand's injectable flows. */
|
|
14
16
|
readonly flows?: Partial<TuiSetupFlows>;
|
|
17
|
+
/** Test seam for remote authentication. */
|
|
18
|
+
readonly remoteAuthFlow?: RemoteAuthFlow;
|
|
15
19
|
}
|
|
16
20
|
export declare function createPromptCommandHandler(options: PromptCommandHandlerOptions): PromptCommandHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{toErrorMessage}from"#shared/errors.js";function createPromptCommandHandler(
|
|
1
|
+
import{isPromptCommandAvailableFor}from"./prompt-commands.js";import{toErrorMessage}from"#shared/errors.js";function createPromptCommandHandler(n){return{async handle(r,i){let{target:a}=n;if(a.kind===`remote`&&!isPromptCommandAvailableFor(r.name,`remote`))return{message:`/${r.name} needs eve dev running the local server (it is not available with --url).`};if(r.name===`model`&&r.argument.length>0){if(a.kind!==`local`)return{message:`/model needs eve dev running the local server (it is not available with --url).`};let e=a.workspaceRoot;try{let{changeAgentModel:t,formatApplyModelOutcome:i,modelChangeRefusalForUneditableModel:a}=await import(`#setup/flows/model.js`),o=await(n.modelChangeRefusal??a)(e);return o===null?{message:i(await(n.applyModel??t)({appRoot:e,slug:r.argument}))}:{message:o}}catch(e){return{message:`Couldn't change the model: ${toErrorMessage(e)}`}}}let o=i.renderer.setupFlow;if(o===void 0)return{message:`/${r.name} is not supported by this renderer.`};if(r.name===`vc:login`&&a.kind===`remote`){if(i.remoteConnection===void 0)return{message:`/vc:login is not available in this session.`};let e;try{({runRemoteAuthCommand:e}=await import(`./remote-auth-command.js`))}catch(e){return{message:`/vc:login failed: ${toErrorMessage(e)}`}}return{message:await e({connection:i.remoteConnection,flow:n.remoteAuthFlow,renderer:o})}}let s;try{s=await import(`./setup-commands.js`)}catch(e){return{message:`/${r.name} failed: ${toErrorMessage(e)}`}}let{runTuiSetupCommand:c,SETUP_FLOW_CONFIG:l}=s,u=l[r.name];o.begin(u.title,u.indicator);let d=!0;try{let e={command:r.name,appRoot:a.workspaceRoot,renderer:o};i.initialModelStep!==void 0&&(e.initialModelStep=i.initialModelStep),n.flows!==void 0&&(e.flows=n.flows);let t=await c(e);d=t.preserveFlowDiagnostics;let s={message:t.message};return t.effect!==void 0&&(s.effect=t.effect),s}finally{o.end({preserveDiagnostics:d})}}}}export{createPromptCommandHandler};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export type PromptCommandExtensionName = "model" | "channels" | "deploy" | "
|
|
1
|
+
export type PromptCommandExtensionName = "model" | "channels" | "deploy" | "vc:install" | "vc:login";
|
|
2
|
+
type PromptCommandTarget = "local" | "remote";
|
|
2
3
|
/** The slash commands the prompt accepts. */
|
|
3
4
|
export type PromptCommand = {
|
|
4
5
|
type: "new";
|
|
@@ -32,12 +33,10 @@ export interface PromptCommandSpec {
|
|
|
32
33
|
/** Maps a recognized invocation to its parsed command. */
|
|
33
34
|
readonly build: (argument: string) => PromptCommand;
|
|
34
35
|
}
|
|
35
|
-
/**
|
|
36
|
-
* Every slash command the prompt accepts, in typeahead display order. One
|
|
37
|
-
* module owns the command list so the runner's dispatch, the renderer's
|
|
38
|
-
* transcript-echo suppression, and command discovery cannot drift apart.
|
|
39
|
-
*/
|
|
40
36
|
export declare const PROMPT_COMMANDS: readonly PromptCommandSpec[];
|
|
37
|
+
export declare function promptCommandsFor(target: PromptCommandTarget): readonly PromptCommandSpec[];
|
|
38
|
+
/** Whether a command runs against this target — the one authority dispatch shares with discovery. */
|
|
39
|
+
export declare function isPromptCommandAvailableFor(name: PromptCommandExtensionName, target: PromptCommandTarget): boolean;
|
|
41
40
|
/**
|
|
42
41
|
* Recognizes the slash commands the prompt accepts. `/new` clears the
|
|
43
42
|
* session and transcript; `/exit` (and `/quit`) terminate the TUI like
|
|
@@ -51,4 +50,5 @@ export declare function isPromptControlCommand(prompt: string): boolean;
|
|
|
51
50
|
* The table `/help` prints: one line per command — slash name, argument
|
|
52
51
|
* hint, and aliases padded into a column, description after.
|
|
53
52
|
*/
|
|
54
|
-
export declare function formatPromptCommandHelp(): string;
|
|
53
|
+
export declare function formatPromptCommandHelp(commands?: readonly PromptCommandSpec[]): string;
|
|
54
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const
|
|
2
|
-
`)}export{PROMPT_COMMANDS,formatPromptCommandHelp,isPromptControlCommand,parsePromptCommand};
|
|
1
|
+
const PROMPT_COMMAND_DEFINITIONS=[{name:`help`,aliases:[],description:`Show available commands`,takesArgument:!1,build:()=>({type:`help`}),targets:[`local`,`remote`]},{name:`new`,aliases:[],description:`Start a fresh session`,takesArgument:!1,build:()=>({type:`new`}),targets:[`local`,`remote`]},{name:`vc:install`,aliases:[],description:`Install the Vercel CLI`,takesArgument:!1,build:()=>({type:`extension`,name:`vc:install`,argument:``}),targets:[`local`,`remote`]},{name:`vc:login`,aliases:[],description:`Authenticate with Vercel`,takesArgument:!1,build:()=>({type:`extension`,name:`vc:login`,argument:``}),targets:[`local`,`remote`]},{name:`model`,aliases:[],description:`Configure the agent's model and provider`,argumentHint:`[provider/model]`,takesArgument:!0,build:e=>({type:`extension`,name:`model`,argument:e}),targets:[`local`]},{name:`loglevel`,aliases:[],description:`Show or hide captured stdout/stderr/sandbox logs`,argumentHint:`[all|stderr|sandbox|none]`,takesArgument:!0,build:e=>({type:`loglevel`,argument:e}),targets:[`local`,`remote`]},{name:`channels`,aliases:[],description:`Add chat channels to the agent`,takesArgument:!1,build:()=>({type:`extension`,name:`channels`,argument:``}),targets:[`local`]},{name:`deploy`,aliases:[],description:`Deploy the agent to Vercel`,takesArgument:!1,build:()=>({type:`extension`,name:`deploy`,argument:``}),targets:[`local`]},{name:`exit`,aliases:[`quit`],description:`Quit the TUI`,takesArgument:!1,build:()=>({type:`exit`}),targets:[`local`,`remote`]}],PROMPT_COMMANDS=PROMPT_COMMAND_DEFINITIONS;function promptCommandsFor(t){return PROMPT_COMMAND_DEFINITIONS.filter(e=>e.targets.some(e=>e===t))}function isPromptCommandAvailableFor(t,n){return(PROMPT_COMMAND_DEFINITIONS.find(e=>e.name===t)?.targets)?.includes(n)??!1}function parsePromptCommand(e){let n=e.trim();if(!n.startsWith(`/`))return null;for(let e of PROMPT_COMMANDS)for(let t of[e.name,...e.aliases]){let r=`/${t}`;if(n===r)return e.build(``);if(e.takesArgument&&n.startsWith(`${r} `))return e.build(n.slice(r.length).trim())}return null}function isPromptControlCommand(e){return parsePromptCommand(e)!==null}function formatPromptCommandHelp(e=PROMPT_COMMANDS){let n=e.map(e=>{let t=e.argumentHint===void 0?``:` ${e.argumentHint}`,n=e.aliases.map(e=>` (/${e})`).join(``);return{invocation:`/${e.name}${t}${n}`,description:e.description}}),r=Math.max(...n.map(e=>e.invocation.length))+2;return n.map(e=>e.invocation.padEnd(r)+e.description).join(`
|
|
2
|
+
`)}export{PROMPT_COMMANDS,formatPromptCommandHelp,isPromptCommandAvailableFor,isPromptControlCommand,parsePromptCommand,promptCommandsFor};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type RemoteAuthFlow } from "./remote-auth.js";
|
|
2
|
+
import type { RemoteConnectionController } from "./remote-connection.js";
|
|
3
|
+
import type { SetupFlowRenderer } from "./setup-flow.js";
|
|
4
|
+
interface RemoteAuthCommandInput {
|
|
5
|
+
readonly connection: RemoteConnectionController;
|
|
6
|
+
readonly flow?: RemoteAuthFlow;
|
|
7
|
+
readonly renderer: SetupFlowRenderer;
|
|
8
|
+
}
|
|
9
|
+
/** Runs remote `/vc:login` through one TUI panel, connection operation, and auth flow. */
|
|
10
|
+
export declare function runRemoteAuthCommand(input: RemoteAuthCommandInput): Promise<string>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{createTuiPrompter}from"./tui-prompter.js";import{describeRemoteAuthCompletedMutations}from"./remote-auth-result.js";import{runRemoteAuthFlow}from"./remote-auth.js";import{remoteHost}from"./target.js";import{WizardCancelledError}from"#setup/step.js";function shouldConfigureTrustedSources(e){switch(e.state){case`auth-required`:case`auth-failed`:return e.challenge.kind===`vercel-deployment-protection`;case`unavailable`:return e.failure.code===`TRUSTED_SOURCES_ENVIRONMENT_MISMATCH`;case`checking`:case`authenticating`:case`ready`:return!1}}function unavailableAfterAuthentication(e,t){let[n=t,...r]=t.split(/\n\s*\n/u);return[`Authentication was refreshed, but ${e} is unavailable: ${/[.!?]$/u.test(n.trim())?n.trim():`${n.trim()}.`}`,...r.map(e=>e.trim()).filter(e=>e.length>0)].join(`
|
|
2
|
+
|
|
3
|
+
`)}function mutedRenderer(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 runRemoteAuthCommand(i){i.renderer.begin(`Authenticate via Vercel OIDC`,`pulse`);let a=!0,o=!1,s=new AbortController,c=i.renderer.waitForInterrupt(),l=i.connection.current().target;try{let u=i.flow??runRemoteAuthFlow,d=shouldConfigureTrustedSources(i.connection.current().connection),f=createTuiPrompter(mutedRenderer(i.renderer,()=>o)),p=i.connection.authenticate(async e=>{let t=await u({workspaceRoot:l.workspaceRoot,serverUrl:l.serverUrl,configureTrustedSources:d,prompter:f,signal:e});return a=t.kind===`failed`,t},s.signal),m=await Promise.race([p.then(e=>({kind:`completed`,outcome:e})),c.promise.then(()=>({kind:`interrupted`}))]);m.kind===`interrupted`&&(o=!0,a=!0,s.abort(new WizardCancelledError));let h=m.kind===`completed`?m.outcome:await p;switch(h.kind){case`authenticated`:return`Authenticated ${remoteHost(l)} via Vercel OIDC.`;case`cancelled`:if(o){let e=describeRemoteAuthCompletedMutations(h.completedMutations);return e.length===0?`/vc:login interrupted.`:`/vc:login interrupted. Completed before interruption: ${e.join(`, `)}.`}return h.completedMutations.some(e=>e.kind===`vercel-login`)?`/vc:login cancelled after logging in to Vercel.`:`/vc:login cancelled.`;case`failed`:return h.message;case`unavailable`:return unavailableAfterAuthentication(remoteHost(l),h.failure.message)}}finally{c.dispose(),i.renderer.setStatus(void 0),i.renderer.end({preserveDiagnostics:a})}}export{runRemoteAuthCommand};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { VerifiedVercelTarget } from "#setup/vercel-deployment.js";
|
|
2
2
|
export type RemoteAuthCompletedMutation = {
|
|
3
3
|
readonly kind: "vercel-login";
|
|
4
|
+
} | {
|
|
5
|
+
readonly kind: "trusted-sources-updated";
|
|
6
|
+
readonly targetProjectName: string;
|
|
4
7
|
};
|
|
5
8
|
export type RemoteAuthPreparation = {
|
|
6
9
|
readonly kind: "prepared";
|
|
@@ -19,3 +22,5 @@ export type RemoteAuthPreparation = {
|
|
|
19
22
|
export declare function describeRemoteAuthCompletedMutations(completedMutations: readonly RemoteAuthCompletedMutation[]): string[];
|
|
20
23
|
/** Adds the mutations that cannot be rolled back to an authentication failure. */
|
|
21
24
|
export declare function appendRemoteAuthMutationSummary(message: string, completedMutations: readonly RemoteAuthCompletedMutation[]): string;
|
|
25
|
+
/** Formats a Vercel Deployment Protection challenge for the remote TUI. */
|
|
26
|
+
export declare function formatRemoteAuthChallengeMessage(serverUrl: string): string;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
function describeRemoteAuthCompletedMutations(e){return e.map(e=>{switch(e.kind){case`vercel-login`:return`logged in to Vercel`}})}function appendRemoteAuthMutationSummary(e,t){let n=describeRemoteAuthCompletedMutations(t);return n.length===0?e:`${e} Completed before the failure: ${n.join(`, `)}.`}
|
|
1
|
+
function describeRemoteAuthCompletedMutations(e){return e.map(e=>{switch(e.kind){case`vercel-login`:return`logged in to Vercel`;case`trusted-sources-updated`:return`updated Trusted Sources for ${e.targetProjectName}`}})}function appendRemoteAuthMutationSummary(e,t){let n=describeRemoteAuthCompletedMutations(t);return n.length===0?e:`${e} Completed before the failure: ${n.join(`, `)}.`}function formatRemoteAuthChallengeMessage(e){return[`Vercel Deployment Protection blocked the request to ${e}.`,``,"To access the deployment from `eve dev`, do one of:"," • Run `/vc:login` to authenticate this remote via Vercel OIDC.",` • Set VERCEL_AUTOMATION_BYPASS_SECRET to a Protection Bypass for`,` Automation token (Project Settings → Deployment Protection).`,` • Disable Deployment Protection on the target deployment.`,``,`Docs: https://vercel.com/docs/deployment-protection`].join(`
|
|
2
|
+
`)}export{appendRemoteAuthMutationSummary,describeRemoteAuthCompletedMutations,formatRemoteAuthChallengeMessage};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { resolveDevelopmentOidcToken } from "#services/dev-client/request-headers.js";
|
|
2
|
+
import { runLoginFlow } from "#setup/flows/login.js";
|
|
3
|
+
import type { Prompter } from "#setup/prompter.js";
|
|
4
|
+
import { pickTeam } from "#setup/vercel-project.js";
|
|
5
|
+
import { resolveVercelDeployment } from "#setup/vercel-deployment.js";
|
|
6
|
+
import { applyVercelTrustedSourceAccess, prepareVercelTrustedSourceAccess } from "./vercel-trusted-sources.js";
|
|
7
|
+
import { type RemoteAuthPreparation } from "./remote-auth-result.js";
|
|
8
|
+
/** Injectable entry point for the remote authentication flow. */
|
|
9
|
+
export type RemoteAuthFlow = typeof runRemoteAuthFlow;
|
|
10
|
+
export interface RemoteAuthFlowDeps {
|
|
11
|
+
readonly runLoginFlow: typeof runLoginFlow;
|
|
12
|
+
readonly pickTeam: typeof pickTeam;
|
|
13
|
+
readonly resolveVercelDeployment: typeof resolveVercelDeployment;
|
|
14
|
+
readonly resolveOidcToken: typeof resolveDevelopmentOidcToken;
|
|
15
|
+
readonly prepareVercelTrustedSourceAccess: typeof prepareVercelTrustedSourceAccess;
|
|
16
|
+
readonly applyVercelTrustedSourceAccess: typeof applyVercelTrustedSourceAccess;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Authenticates a remote by resolving its deployment URL to the owning Vercel
|
|
20
|
+
* project, updating Trusted Sources when needed and keeping the resolved
|
|
21
|
+
* credential in this TUI session.
|
|
22
|
+
*/
|
|
23
|
+
export declare function runRemoteAuthFlow(input: {
|
|
24
|
+
readonly workspaceRoot: string;
|
|
25
|
+
readonly serverUrl: string;
|
|
26
|
+
readonly configureTrustedSources?: boolean;
|
|
27
|
+
readonly prompter: Prompter;
|
|
28
|
+
readonly signal?: AbortSignal;
|
|
29
|
+
readonly deps?: Partial<RemoteAuthFlowDeps>;
|
|
30
|
+
}): Promise<RemoteAuthPreparation>;
|
|
@@ -0,0 +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{applyVercelTrustedSourceAccess,prepareVercelTrustedSourceAccess}from"./vercel-trusted-sources.js";import{appendRemoteAuthMutationSummary}from"./remote-auth-result.js";import{WizardCancelledError}from"#setup/step.js";import{toErrorMessage}from"#shared/errors.js";import{resolveDevelopmentOidcToken}from"#services/dev-client/request-headers.js";import{formatDevelopmentOidcTokenFailure}from"#services/dev-client/vercel-auth-error.js";import{runLoginFlow}from"#setup/flows/login.js";import{pickTeam}from"#setup/vercel-project.js";import{resolveVercelDeployment}from"#setup/vercel-deployment.js";var import_picocolors=__toESM(require_picocolors(),1);const defaultDeps={runLoginFlow,pickTeam,resolveVercelDeployment,resolveOidcToken:resolveDevelopmentOidcToken,prepareVercelTrustedSourceAccess,applyVercelTrustedSourceAccess};function failed(e,t=[]){return{kind:`failed`,message:appendRemoteAuthMutationSummary(e,t),completedMutations:[...t]}}function cancelled(e=[]){return{kind:`cancelled`,completedMutations:[...e]}}function loginFailure(e){switch(e.kind){case`already`:case`logged-in`:return;case`cancelled`:return cancelled();case`cli-missing`:return failed("The Vercel CLI is not installed. Install it with `npm i -g vercel@latest`, then retry /vc:login.");case`failed`:return failed(`Vercel login did not complete. Retry /vc:login.`);case`unavailable`:return failed(`Vercel could not verify your account. Check your connection, then retry /vc:login.`)}}function deploymentFailureMessage(e){return e.cause===`vercel`?e.failure.message:e.message}async function selectVercelDeploymentScope(e,t,n,r,i){return await e.pickTeam(r,t,void 0,{signal:i,selectMessage:e=>`${import_picocolors.default.blue(n)} is not accessible via current team (${import_picocolors.default.bold(e)})\nYou can try selecting another team:`})}async function runRemoteAuthFlow(e){let{workspaceRoot:t,serverUrl:n,prompter:r,signal:i}=e,a=new URL(n).host,o={...defaultDeps,...e.deps},s=[],c=!1;try{let n=await o.runLoginFlow({appRoot:t,prompter:r,signal:i}),l=loginFailure(n);if(l!==void 0)return l;n.kind===`logged-in`&&s.push({kind:`vercel-login`});let u=await o.resolveVercelDeployment({workspaceRoot:t,host:a,signal:i});if(u.kind===`forbidden`){let e=await o.runLoginFlow({appRoot:t,force:!0,prompter:r,signal:i}),n=loginFailure(e);if(n!==void 0)return n;e.kind===`logged-in`&&s.push({kind:`vercel-login`}),i?.throwIfAborted(),u=await o.resolveVercelDeployment({workspaceRoot:t,host:a,signal:i})}if(u.kind===`not-found`)try{let e=await selectVercelDeploymentScope(o,t,a,r,i);i?.throwIfAborted(),u=await o.resolveVercelDeployment({workspaceRoot:t,host:a,scope:e,signal:i})}catch(e){return e instanceof WizardCancelledError?cancelled(s):(i?.throwIfAborted(),failed(`Could not select a Vercel team: ${toErrorMessage(e)}`,s))}let d;switch(u.kind){case`resolved`:d=u.target;break;case`cancelled`:return cancelled(s);case`forbidden`:return failed(`Could not access ${a}. Re-authenticate (for example to complete a team's SSO), then retry /vc:login.`,s);case`not-found`:return failed(`Vercel did not resolve ${a} for the selected Vercel team.`,s);case`project-mismatch`:return failed(`Could not verify ${a}: Vercel resolved project ${u.actualProjectId}, not ${u.expectedProjectId}.`,s);case`failed`:return failed(`Could not verify ${a} through Vercel: ${deploymentFailureMessage(u.failure)}`,s)}let f;if(e.configureTrustedSources===!0){let e=await o.prepareVercelTrustedSourceAccess({workspaceRoot:t,target:d,prompter:r,signal:i});if(i?.throwIfAborted(),e.kind===`cancelled`)return cancelled(s);if(e.kind===`failed`)return failed(e.message,s);e.kind===`approved`&&(f=e.grant)}if(i?.throwIfAborted(),f!==void 0){c=!0;let e=await o.applyVercelTrustedSourceAccess({workspaceRoot:t,grant:f,signal:i});if(e.kind===`failed`)return failed(e.message,s);e.kind===`updated`&&s.push({kind:`trusted-sources-updated`,targetProjectName:e.targetProjectName})}let p=await o.resolveOidcToken({ownerId:d.deployment.ownerId,projectId:d.deployment.projectId,forceRefresh:!0});if(i?.throwIfAborted(),p.kind!==`resolved`)return failed(formatDevelopmentOidcTokenFailure(p),s);let m=p.token.trim();return{kind:`prepared`,target:d,resolveToken:async()=>{let e=await o.resolveOidcToken(d.deployment);return e.kind===`resolved`&&(m=e.token.trim()),m},completedMutations:[...s]}}catch(e){return!c&&(e instanceof WizardCancelledError||i?.aborted===!0)?cancelled(s):failed(`Could not authenticate ${a}: ${toErrorMessage(e)}`,s)}}export{runRemoteAuthFlow};
|
|
@@ -3,7 +3,9 @@ import type { RemoteConnectionState } from "./remote-connection-types.js";
|
|
|
3
3
|
export type RemoteProbeResult = Extract<RemoteConnectionState, {
|
|
4
4
|
state: "ready" | "auth-required" | "unavailable";
|
|
5
5
|
}>;
|
|
6
|
-
export
|
|
6
|
+
export type RemoteProbePhase = "connection-check" | "authentication-verification";
|
|
7
|
+
export declare function classifyRemoteError(error: unknown, phase: RemoteProbePhase): RemoteProbeResult;
|
|
7
8
|
export declare function probeRemoteInfo(input: {
|
|
8
9
|
readonly client: Client;
|
|
10
|
+
readonly phase: RemoteProbePhase;
|
|
9
11
|
}): Promise<RemoteProbeResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isObject}from"#shared/guards.js";import{toErrorMessage}from"#shared/errors.js";import{
|
|
1
|
+
import{isObject}from"#shared/guards.js";import{toErrorMessage}from"#shared/errors.js";import{formatVercelTrustedSourcesFailure,isVercelAuthChallenge,vercelTrustedSourcesErrorCode}from"#services/dev-client/vercel-auth-error.js";import{AgentInfoResponseError,ClientError}from"#client/index.js";function isEveOidcChallenge(t){if(!(t instanceof ClientError)||t.status!==401)return!1;try{let n=JSON.parse(t.body);return isObject(n)&&n.ok===!1&&n.code===`unauthorized`&&n.error===`Authorization is required for this route.`}catch{return!1}}function classifyRemoteError(e,i){if(isVercelAuthChallenge(e))return{state:`auth-required`,challenge:{kind:`vercel-deployment-protection`}};if(isEveOidcChallenge(e))return{state:`auth-required`,challenge:{kind:`eve-oidc`}};if(e instanceof ClientError){let t=vercelTrustedSourcesErrorCode(e.message);if(i===`connection-check`&&e.status===403&&t===`TRUSTED_SOURCES_ENVIRONMENT_MISMATCH`)return{state:`auth-required`,challenge:{kind:`vercel-deployment-protection`}};let r={message:formatVercelTrustedSourcesFailure(e.message)};return{state:`unavailable`,failure:t===void 0?r:{...r,code:t}}}return{state:`unavailable`,failure:{message:toErrorMessage(e)}}}async function probeDeploymentHealth(t){try{let n=await t.health();return isObject(n)&&n.ok===!0}catch{return!1}}async function probeRemoteInfo(e){try{return{state:`ready`,info:await e.client.info()}}catch(t){return(t instanceof AgentInfoResponseError||t instanceof ClientError&&t.status===404)&&await probeDeploymentHealth(e.client)?{state:`ready`}:classifyRemoteError(t,e.phase)}}export{classifyRemoteError,probeRemoteInfo};
|
|
@@ -10,13 +10,14 @@ export type RemoteAuthChallenge = {
|
|
|
10
10
|
readonly kind: "vercel-deployment-protection";
|
|
11
11
|
};
|
|
12
12
|
interface RemoteRequestFailure {
|
|
13
|
+
readonly code?: string;
|
|
13
14
|
readonly message: string;
|
|
14
15
|
}
|
|
15
16
|
export type RemoteConnectionState = {
|
|
16
17
|
readonly state: "checking";
|
|
17
18
|
} | {
|
|
18
19
|
readonly state: "ready";
|
|
19
|
-
readonly info
|
|
20
|
+
readonly info?: AgentInfoResult;
|
|
20
21
|
} | {
|
|
21
22
|
readonly state: "auth-required";
|
|
22
23
|
readonly challenge: RemoteAuthChallenge;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{appendRemoteAuthMutationSummary}from"./remote-auth-result.js";import{
|
|
1
|
+
import{appendRemoteAuthMutationSummary}from"./remote-auth-result.js";import{remoteHost}from"./target.js";import{classifyRemoteError,probeRemoteInfo}from"./remote-connection-probe.js";import{toErrorMessage}from"#shared/errors.js";function challengeFor(e){switch(e.state){case`auth-required`:case`authenticating`:case`auth-failed`:return e.challenge;case`checking`:case`ready`:return{kind:`eve-oidc`};case`unavailable`:return e.failure.code===`TRUSTED_SOURCES_ENVIRONMENT_MISMATCH`?{kind:`vercel-deployment-protection`}:{kind:`eve-oidc`}}}function createRemoteConnectionController(i){let a={state:`checking`},o,s,restoreActiveCredentials,c=0,l=!1,snapshot=()=>o===void 0?{target:i.target,connection:a}:{target:i.target,connection:a,deployment:o},update=e=>(a=e,l||i.onChange(snapshot()),e),beginOperation=e=>{s?.abort();let t=new AbortController;s=t;let n=e===void 0?t.signal:AbortSignal.any([t.signal,e]);return{generation:++c,signal:n}},isCurrent=e=>!l&&e===c,publishTarget=e=>{o=e.deployment,l||i.onChange(snapshot())},authorizeResolvedTarget=async(e,t)=>{let n=i.resolveDeployment;if(n!==void 0)try{let r=await n(e);return!isCurrent(t)||e.aborted||r.kind!==`resolved`?void 0:(publishTarget(r.target),i.credentials.authorize({target:r.target,resolveToken:async()=>await i.resolveOidcToken?.(r.target.deployment)??``}))}catch{}};return i.onChange(snapshot()),{current:snapshot,async check(){let e=beginOperation();restoreActiveCredentials?.(),restoreActiveCredentials=void 0,o=void 0,update({state:`checking`});let t=await authorizeResolvedTarget(e.signal,e.generation);if(!isCurrent(e.generation))return t?.(),a;restoreActiveCredentials=t;let n=await probeRemoteInfo({client:i.client,phase:`connection-check`});return isCurrent(e.generation)?update(n):a},async authenticate(n,o){let s=beginOperation(o),c=a,l=challengeFor(a);update({state:`authenticating`,challenge:l});let u;try{u=await n(s.signal)}catch(e){u={kind:`failed`,message:toErrorMessage(e),completedMutations:[]}}if(!isCurrent(s.generation))return{kind:`cancelled`,completedMutations:u.completedMutations};if(u.kind===`cancelled`)return update(c),{kind:`cancelled`,completedMutations:u.completedMutations};if(u.kind===`failed`)return update(c.state===`ready`?c:{state:`auth-failed`,challenge:l}),{kind:`failed`,message:u.message};if(s.signal.aborted)return update(c),{kind:`cancelled`,completedMutations:u.completedMutations};let d=restoreActiveCredentials,f;try{f=i.credentials.authorize({target:u.target,resolveToken:u.resolveToken})}catch(t){let n=appendRemoteAuthMutationSummary(toErrorMessage(t),u.completedMutations);return update({state:`auth-failed`,challenge:l}),{kind:`failed`,message:n}}let p=await probeRemoteInfo({client:i.client,phase:`authentication-verification`});if(!isCurrent(s.generation))return f(),{kind:`cancelled`,completedMutations:u.completedMutations};if(s.signal.aborted)return f(),update(c),{kind:`cancelled`,completedMutations:u.completedMutations};if(p.state===`ready`)return publishTarget(u.target),restoreActiveCredentials=()=>{f(),d?.()},update(p),{kind:`authenticated`};if(f(),p.state===`auth-required`){let n=appendRemoteAuthMutationSummary(`The selected Vercel project did not authorize ${remoteHost(i.target)}.`,u.completedMutations);return update({state:`auth-failed`,challenge:p.challenge}),{kind:`failed`,message:n}}let m={...p.failure,message:appendRemoteAuthMutationSummary(p.failure.message,u.completedMutations)};return update({state:`unavailable`,failure:m}),{kind:`unavailable`,failure:m}},reportFailure(e){return s?.abort(),c+=1,update(classifyRemoteError(e,`connection-check`))},dispose(){l=!0,c+=1,s?.abort(),s=void 0,restoreActiveCredentials?.(),restoreActiveCredentials=void 0}}}export{createRemoteConnectionController};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { type AgentInfoResult, type ConnectionAuthorizationOutcome, type InputRequest, Client, ClientSession } from "#client/index.js";
|
|
2
2
|
import { type DevBootProgressReporter } from "#internal/dev-boot-progress.js";
|
|
3
|
-
import { type PromptCommand } from "./prompt-commands.js";
|
|
3
|
+
import { type PromptCommand, type PromptCommandSpec } from "./prompt-commands.js";
|
|
4
|
+
import { type RemoteConnectionController, type RemoteConnectionControllerOptions, type RemoteConnectionSnapshot } from "./remote-connection.js";
|
|
5
|
+
import type { DevelopmentCredentialGate } from "#services/dev-client/credential-gate.js";
|
|
4
6
|
import { type BootDetection } from "./setup-issues.js";
|
|
5
7
|
import type { SetupFlowRenderer } from "./setup-flow.js";
|
|
8
|
+
import type { RemoteDevelopmentTarget } from "./target.js";
|
|
6
9
|
import type { AssistantResponseStatsMode, LogDisplayMode, TerminalPartDisplayMode, TuiDisplayOptions } from "./types.js";
|
|
7
10
|
import { type TerminalInput, type TerminalOutput } from "./terminal-renderer.js";
|
|
8
11
|
import { type VercelStatusEffect, type VercelStatusSnapshot } from "./vercel-status.js";
|
|
@@ -141,6 +144,8 @@ export type AgentTUIRenderer = {
|
|
|
141
144
|
renderSetupWarning?(text: string): void;
|
|
142
145
|
/** Clears the setup attention line once its issue is resolved. */
|
|
143
146
|
clearSetupWarning?(): void;
|
|
147
|
+
/** Commits the startup `/vc:login` invocation to the transcript. */
|
|
148
|
+
renderCommandInvocation?(text: string, status?: "failed"): void;
|
|
144
149
|
renderCommandResult?(text: string): void;
|
|
145
150
|
readonly setupFlow?: SetupFlowRenderer;
|
|
146
151
|
readPrompt?(options?: AgentTUISessionOptions): Promise<string | undefined>;
|
|
@@ -206,6 +211,8 @@ export type AgentTUIRenderer = {
|
|
|
206
211
|
* line ignore it.
|
|
207
212
|
*/
|
|
208
213
|
setVercelStatus?(status: VercelStatusSnapshot): void;
|
|
214
|
+
/** Sets the remote deployment badge and its current connection/authentication state. */
|
|
215
|
+
setRemoteConnectionStatus?(status: RemoteConnectionSnapshot): void;
|
|
209
216
|
/**
|
|
210
217
|
* Clears the rendered transcript and resets per-conversation display
|
|
211
218
|
* state, leaving the UI interactive on a fresh screen. Used by the
|
|
@@ -223,6 +230,7 @@ export interface PromptCommandHandlerContext {
|
|
|
223
230
|
readonly title: string;
|
|
224
231
|
/** Provider entry authorized by confirmed boot-time model-access evidence. */
|
|
225
232
|
readonly initialModelStep?: "provider";
|
|
233
|
+
readonly remoteConnection?: RemoteConnectionController;
|
|
226
234
|
}
|
|
227
235
|
/** What one handled slash command leaves behind for the runner to apply. */
|
|
228
236
|
export interface PromptCommandOutcome {
|
|
@@ -275,6 +283,15 @@ export type EveTUIRunnerOptions = TuiDisplayOptions & {
|
|
|
275
283
|
initialInput?: string;
|
|
276
284
|
/** Handles non-core slash commands without adding feature branches to the runner. */
|
|
277
285
|
promptCommandHandler?: PromptCommandHandler;
|
|
286
|
+
/** Commands shown in discovery for this local or remote session. */
|
|
287
|
+
availablePromptCommands?: readonly PromptCommandSpec[];
|
|
288
|
+
/** Remote target and mutable OIDC token source, when connected through `--url`. */
|
|
289
|
+
remote?: {
|
|
290
|
+
readonly target: RemoteDevelopmentTarget;
|
|
291
|
+
readonly credentials: DevelopmentCredentialGate;
|
|
292
|
+
readonly resolveOidcToken: NonNullable<RemoteConnectionControllerOptions["resolveOidcToken"]>;
|
|
293
|
+
readonly resolveDeployment: NonNullable<RemoteConnectionControllerOptions["resolveDeployment"]>;
|
|
294
|
+
};
|
|
278
295
|
/** Boot-time installation-state checks; defaults to the built-ins. */
|
|
279
296
|
bootDetections?: readonly BootDetection[];
|
|
280
297
|
/** Test seam for the status line's Vercel link probe; defaults to the real one. */
|