eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
144 lines (143 loc) • 6.26 kB
TypeScript
import type { ChannelSetupChoice, ChannelSetupChoiceOptions } from "#setup/cli/index.js";
import type { SearchActionOption } from "#setup/cli/select-state.js";
import type { ModelSettingsRequest, ModelSettingsResult } from "#setup/flows/model.js";
import type { ProviderPickerChoice, ProviderPickerRequest } from "#setup/flows/provider.js";
import type { PlannerNavigation, SelectMetadata, SelectNotice } from "#setup/prompter.js";
import type { SetupPanelOption } from "./setup-panel.js";
export type SetupEditableSelectResult = {
kind: "selected";
value: string;
} | {
kind: "edited";
value: string;
text: string;
};
/** Animation shown while a setup flow is between questions. */
export type SetupFlowIndicator = "spinner" | "pulse";
/** Ephemeral setup status, with external user action distinct from background work. */
export type SetupFlowStatus = string | {
kind: "external-action";
text: string;
emphasis: string;
};
interface SetupSelectRequestBase {
message: string;
description?: string;
metadata?: readonly SelectMetadata[];
options: readonly SetupPanelOption[];
notices?: readonly SelectNotice[];
navigation?: PlannerNavigation;
}
interface SetupSingleSelectRequest extends SetupSelectRequestBase {
kind: "single" | "stacked" | "task-list";
initialValue?: string;
}
interface SetupSearchAction extends SearchActionOption {
load?(query: string): Promise<readonly SetupPanelOption[]>;
}
interface SetupSearchSelectRequest extends SetupSelectRequestBase {
kind: "search";
layout?: "task-list";
initialValue?: string;
placeholder?: string;
searchAction?: SetupSearchAction;
}
interface SetupMultiSelectRequest extends SetupSelectRequestBase {
kind: "multi";
initialValues?: readonly string[];
required: boolean;
}
interface SetupSearchableMultiSelectRequest extends SetupSelectRequestBase {
kind: "searchable-multi";
layout?: "stacked";
initialValues?: readonly string[];
placeholder?: string;
required: boolean;
}
/**
* A setup select's complete interaction grammar. The discriminant prevents
* callers from combining incompatible modes; searchable multi-select supports
* the stable stacked checklist layout but not single-select task actions.
*/
export type SetupSelectRequest = SetupSingleSelectRequest | SetupSearchSelectRequest | SetupMultiSelectRequest | SetupSearchableMultiSelectRequest;
export type SetupSelectResult = readonly string[] | {
kind: "navigate";
direction: "back" | "forward";
values: readonly string[];
} | undefined;
export type SetupFlowInterrupt = "escape" | "ctrl-c";
export interface SetupFlowRenderer {
begin(title: string, indicator?: SetupFlowIndicator): void;
/** Sets progress owned by an enclosing setup journey, independent of its active question. */
setNavigation?(navigation: PlannerNavigation | undefined): void;
end(options?: {
preserveDiagnostics?: boolean;
}): void;
readSelect(options: SetupSelectRequest): Promise<SetupSelectResult>;
readEditableSelect(options: {
message: string;
options: readonly SetupPanelOption[];
initialValue?: string;
editable: {
value: string;
defaultValue: string;
formatHint: (value: string) => string;
validate?: (value: string) => string | undefined;
};
}): Promise<SetupEditableSelectResult | undefined>;
/** Provider-only picker with masked async validation. Not part of Prompter. */
readProviderPicker(options: ProviderPickerRequest): Promise<ProviderPickerChoice | undefined>;
/** Model, speed, and reasoning picker. Not part of Prompter. */
readModelPicker(options: ModelSettingsRequest): Promise<ModelSettingsResult | undefined>;
readText(options: {
message: string;
placeholder?: string;
defaultValue?: string;
mask?: boolean;
validate?: (value: string) => string | undefined;
notices?: readonly SelectNotice[];
}): Promise<string | undefined>;
readAcknowledge(options: {
message: string;
lines: readonly string[];
}): Promise<void>;
/**
* Presents an inert context row and a separate action menu beside the live
* flow indicator. Returns the choice plus a `close()` that dismisses the menu
* when a concurrent wait resolves first. Used by the Slack install wait for
* "Try again" / "Cancel": the poll keeps running while the prompt is up, and
* whichever settles first wins.
*/
readChoice(options: ChannelSetupChoiceOptions): ChannelSetupChoice;
setStatus(status: SetupFlowStatus | undefined): void;
renderLine(text: string, tone: "info" | "success" | "warning" | "error"): void;
replaceContent?(content?: {
headline: string;
facts: readonly {
label: string;
value: string;
}[];
}): void;
renderOutput(text: string): void;
/** Temporarily restores the terminal while a child process inherits stdio. */
withInheritedStdio<T>(task: () => Promise<T>): Promise<T>;
/** Gives a setup subprocess exclusive terminal and development-host ownership. */
withExclusiveTerminal?<T>(task: () => Promise<T>): Promise<T>;
/**
* Arms a key trap for the flow's working state — the status indicator between
* questions, where no prompt is consuming keys. Ctrl-C or Esc resolves the
* promise so the command can abandon an in-flight flow (e.g. a parked
* `vercel connect create` browser OAuth). Open questions own their keys; the
* trap covers only the gaps. `interruptible: false` still consumes and
* discards input but does not cancel non-abortable work. `dispose` releases
* the trap; the promise then never resolves.
*/
waitForInterrupt(options?: {
interruptible?: boolean;
}): {
promise: Promise<SetupFlowInterrupt>;
dispose(): void;
};
}
export type SetupFlowPrompterRenderer = Pick<SetupFlowRenderer, "readSelect" | "readEditableSelect" | "readText" | "readAcknowledge" | "readChoice" | "setStatus" | "renderLine" | "replaceContent" | "renderOutput" | "withInheritedStdio" | "withExclusiveTerminal">;
export {};