Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/components/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ import { DeployProjectScreen } from "../handlers/project/deploy/screen.tsx";
import { ProjectCreateScreen } from "../handlers/project/create/screen.tsx";
import { ProjectInvokePickerScreen } from "../handlers/project/invoke/screen.tsx";
import { AddRuntimeScreen } from "../handlers/project/add/runtime/screen.tsx";
import { AddRuntimeEndpointScreen } from "../handlers/project/add/runtime-endpoint/screen.tsx";
import { AddMemoryScreen } from "../handlers/project/add/memory/screen.tsx";
import { AddGatewayScreen } from "../handlers/project/add/gateway/screen.tsx";
import { AddGatewayTargetScreen } from "../handlers/project/add/gateway-target/screen.tsx";
Expand Down Expand Up @@ -914,6 +915,10 @@ function RouteTable({ ctx, core }: ScreenProps) {
<Route path="agentcore/create" element={<ProjectCreateScreen ctx={ctx} core={core} />} />
<Route path="agentcore/status" element={<ProjectStatusScreen ctx={ctx} core={core} />} />
<Route path="agentcore/add/runtime" element={<AddRuntimeScreen ctx={ctx} core={core} />} />
<Route
path="agentcore/add/runtime-endpoint"
element={<AddRuntimeEndpointScreen ctx={ctx} core={core} />}
/>
<Route path="agentcore/add/memory" element={<AddMemoryScreen ctx={ctx} core={core} />} />
<Route path="agentcore/add/gateway" element={<AddGatewayScreen ctx={ctx} core={core} />} />
<Route
Expand Down
4 changes: 4 additions & 0 deletions src/components/wizard/fields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,9 @@ export type TextInputSpec = {
onChange: (value: string) => void;
required?: boolean;
schema?: z.ZodType;
// number makes validation fail unless the value is all digits, and hands the
// schema a Number rather than the string; typing itself is not restricted.
number?: boolean;
};

export type MultiTextFieldProps = {
Expand Down Expand Up @@ -465,6 +468,7 @@ export function MultiTextField({ inputs }: MultiTextFieldProps) {
label: input.label,
required: input.required ?? false,
schema: input.schema,
number: input.number ?? false,
});

useInput((_input, key) => {
Expand Down
1 change: 1 addition & 0 deletions src/handlers/project/add/add.screen.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function addSubcommands(): string[] {
// "cli" divider and opens its help instead.
const WITH_SCREENS = [
"runtime",
"runtime-endpoint",
"memory",
"gateway",
"gateway-target",
Expand Down
1 change: 1 addition & 0 deletions src/handlers/project/add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function createAddProjectResourceHandler(
// CliOnlyScreen).
const projectAdd = new Router("add", "add project resources").supportedTuiCommands(
"runtime",
"runtime-endpoint",
"memory",
"gateway",
"gateway-target",
Expand Down
51 changes: 39 additions & 12 deletions src/handlers/project/add/runtime-endpoint/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,38 @@
import z from "zod";
import { createHandler, flag, ProjectKey } from "../../../../router";
import type { AddResourceInput } from "../../types";
import type { AddProjectResourceConfig } from "../types";
import { addProjectResource } from "../shared";

// The version an endpoint points to when none is given — what --version
// documents as its default, and what the wizard prefills.
export const DEFAULT_ENDPOINT_VERSION = 1;

// RuntimeEndpointInput is the endpoint as the flags state it.
export type RuntimeEndpointInput = {
runtime: string;
name: string;
version?: number;
description?: string;
};

type AddRuntimeEndpoint = Extract<AddResourceInput, { resourceType: "runtime-endpoint" }>;

// toAddRuntimeEndpointInput is the one place a runtime endpoint is built from
// user input — the flags, or the wizard's answers — so both default the version
// and drop an empty description the same way.
export function toAddRuntimeEndpointInput(input: RuntimeEndpointInput): AddRuntimeEndpoint {
return {
resourceType: "runtime-endpoint",
runtimeName: input.runtime,
resourceConfig: {
name: input.name,
version: input.version ?? DEFAULT_ENDPOINT_VERSION,
...(input.description ? { description: input.description } : {}),
},
};
}

export const createAddRuntimeEndpointHandler = (config: AddProjectResourceConfig) =>
createHandler({
name: "runtime-endpoint",
Expand All @@ -12,29 +42,26 @@ export const createAddRuntimeEndpointHandler = (config: AddProjectResourceConfig
flag("name", "the endpoint name (e.g., prod, staging)", z.string().min(1)),
flag(
"version",
"the runtime version this endpoint points to (default: 1)",
`the runtime version this endpoint points to (default: ${DEFAULT_ENDPOINT_VERSION})`,
z.number().int().min(1).optional(),
),
flag("description", "description of the endpoint", z.string().optional()),
],
handle: async (ctx, flags) => {
const project = ctx.require(ProjectKey);
const version = flags.version ?? 1;
const input = toAddRuntimeEndpointInput({
runtime: flags.runtime,
name: flags.name,
version: flags.version,
description: flags.description,
});

await addProjectResource(
ctx,
config,
project,
{
resourceType: "runtime-endpoint",
runtimeName: flags.runtime,
resourceConfig: {
name: flags.name,
version,
...(flags.description ? { description: flags.description } : {}),
},
},
`added runtime endpoint '${flags.name}' (version ${version}) to runtime '${flags.runtime}' in '${project.name}'`,
input,
`added runtime endpoint '${flags.name}' (version ${input.resourceConfig.version}) to runtime '${flags.runtime}' in '${project.name}'`,
);
},
});
Loading
Loading