refactor: remove parseArgs value casts in subcommands (#1157)

This commit is contained in:
Devansh Jain
2026-02-25 20:15:15 -08:00
committed by GitHub
parent cca57b1759
commit 2c243151c6
4 changed files with 122 additions and 88 deletions

View File

@@ -38,23 +38,29 @@ function parseTags(value: unknown): string[] | undefined {
return tags.length > 0 ? tags : undefined; return tags.length > 0 ? tags : undefined;
} }
const AGENTS_OPTIONS = {
help: { type: "boolean", short: "h" },
name: { type: "string" },
query: { type: "string" },
tags: { type: "string" },
"match-all-tags": { type: "boolean" },
"include-blocks": { type: "boolean" },
limit: { type: "string" },
} as const;
function parseAgentsArgs(argv: string[]) {
return parseArgs({
args: argv,
options: AGENTS_OPTIONS,
strict: true,
allowPositionals: true,
});
}
export async function runAgentsSubcommand(argv: string[]): Promise<number> { export async function runAgentsSubcommand(argv: string[]): Promise<number> {
let parsed: ReturnType<typeof parseArgs>; let parsed: ReturnType<typeof parseAgentsArgs>;
try { try {
parsed = parseArgs({ parsed = parseAgentsArgs(argv);
args: argv,
options: {
help: { type: "boolean", short: "h" },
name: { type: "string" },
query: { type: "string" },
tags: { type: "string" },
"match-all-tags": { type: "boolean" },
"include-blocks": { type: "boolean" },
limit: { type: "string" },
},
strict: true,
allowPositionals: true,
});
} catch (error) { } catch (error) {
const message = error instanceof Error ? error.message : String(error); const message = error instanceof Error ? error.message : String(error);
console.error(`Error: ${message}`); console.error(`Error: ${message}`);

View File

@@ -27,6 +27,26 @@ function getAgentId(agentFromArgs?: string, agentIdFromArgs?: string): string {
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || ""; return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
} }
const BLOCKS_OPTIONS = {
help: { type: "boolean", short: "h" },
agent: { type: "string" },
"agent-id": { type: "string" },
limit: { type: "string" },
"block-id": { type: "string" },
label: { type: "string" },
override: { type: "boolean" },
"read-only": { type: "boolean" },
} as const;
function parseBlocksArgs(argv: string[]) {
return parseArgs({
args: argv,
options: BLOCKS_OPTIONS,
strict: true,
allowPositionals: true,
});
}
type CopyBlockResult = { type CopyBlockResult = {
sourceBlock: Awaited< sourceBlock: Awaited<
ReturnType<Awaited<ReturnType<typeof getClient>>["blocks"]["retrieve"]> ReturnType<Awaited<ReturnType<typeof getClient>>["blocks"]["retrieve"]>
@@ -253,23 +273,9 @@ async function attachBlock(
} }
export async function runBlocksSubcommand(argv: string[]): Promise<number> { export async function runBlocksSubcommand(argv: string[]): Promise<number> {
let parsed: ReturnType<typeof parseArgs>; let parsed: ReturnType<typeof parseBlocksArgs>;
try { try {
parsed = parseArgs({ parsed = parseBlocksArgs(argv);
args: argv,
options: {
help: { type: "boolean", short: "h" },
agent: { type: "string" },
"agent-id": { type: "string" },
limit: { type: "string" },
"block-id": { type: "string" },
label: { type: "string" },
override: { type: "boolean" },
"read-only": { type: "boolean" },
},
strict: true,
allowPositionals: true,
});
} catch (error) { } catch (error) {
const message = error instanceof Error ? error.message : String(error); const message = error instanceof Error ? error.message : String(error);
console.error(`Error: ${message}`); console.error(`Error: ${message}`);
@@ -306,8 +312,8 @@ export async function runBlocksSubcommand(argv: string[]): Promise<number> {
return 1; return 1;
} }
const agentId = getAgentId( const agentId = getAgentId(
parsed.values.agent as string | undefined, parsed.values.agent,
parsed.values["agent-id"] as string | undefined, parsed.values["agent-id"],
); );
const result = await copyBlock(client, blockId, { const result = await copyBlock(client, blockId, {
labelOverride: labelOverride:
@@ -328,8 +334,8 @@ export async function runBlocksSubcommand(argv: string[]): Promise<number> {
return 1; return 1;
} }
const agentId = getAgentId( const agentId = getAgentId(
parsed.values.agent as string | undefined, parsed.values.agent,
parsed.values["agent-id"] as string | undefined, parsed.values["agent-id"],
); );
const result = await attachBlock(client, blockId, { const result = await attachBlock(client, blockId, {
readOnly: parsed.values["read-only"] === true, readOnly: parsed.values["read-only"] === true,

View File

@@ -40,6 +40,24 @@ function getAgentId(agentFromArgs?: string, agentIdFromArgs?: string): string {
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || ""; return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
} }
const MEMFS_OPTIONS = {
help: { type: "boolean", short: "h" },
agent: { type: "string" },
"agent-id": { type: "string" },
from: { type: "string" },
force: { type: "boolean" },
out: { type: "string" },
} as const;
function parseMemfsArgs(argv: string[]) {
return parseArgs({
args: argv,
options: MEMFS_OPTIONS,
strict: true,
allowPositionals: true,
});
}
function getMemoryRoot(agentId: string): string { function getMemoryRoot(agentId: string): string {
return join(homedir(), ".letta", "agents", agentId, "memory"); return join(homedir(), ".letta", "agents", agentId, "memory");
} }
@@ -97,21 +115,9 @@ function resolveBackupPath(agentId: string, from: string): string {
} }
export async function runMemfsSubcommand(argv: string[]): Promise<number> { export async function runMemfsSubcommand(argv: string[]): Promise<number> {
let parsed: ReturnType<typeof parseArgs>; let parsed: ReturnType<typeof parseMemfsArgs>;
try { try {
parsed = parseArgs({ parsed = parseMemfsArgs(argv);
args: argv,
options: {
help: { type: "boolean", short: "h" },
agent: { type: "string" },
"agent-id": { type: "string" },
from: { type: "string" },
force: { type: "boolean" },
out: { type: "string" },
},
strict: true,
allowPositionals: true,
});
} catch (error) { } catch (error) {
const message = error instanceof Error ? error.message : String(error); const message = error instanceof Error ? error.message : String(error);
console.error(`Error: ${message}`); console.error(`Error: ${message}`);
@@ -126,10 +132,7 @@ export async function runMemfsSubcommand(argv: string[]): Promise<number> {
return 0; return 0;
} }
const agentId = getAgentId( const agentId = getAgentId(parsed.values.agent, parsed.values["agent-id"]);
parsed.values.agent as string | undefined,
parsed.values["agent-id"] as string | undefined,
);
if (!agentId) { if (!agentId) {
console.error( console.error(
@@ -204,7 +207,7 @@ export async function runMemfsSubcommand(argv: string[]): Promise<number> {
} }
if (action === "restore") { if (action === "restore") {
const from = parsed.values.from as string | undefined; const from = parsed.values.from;
if (!from) { if (!from) {
console.error("Missing --from <backup>."); console.error("Missing --from <backup>.");
return 1; return 1;
@@ -231,7 +234,7 @@ export async function runMemfsSubcommand(argv: string[]): Promise<number> {
} }
if (action === "export") { if (action === "export") {
const out = parsed.values.out as string | undefined; const out = parsed.values.out;
if (!out) { if (!out) {
console.error("Missing --out <dir>."); console.error("Missing --out <dir>.");
return 1; return 1;

View File

@@ -2,6 +2,7 @@ import { parseArgs } from "node:util";
import { getClient } from "../../agent/client"; import { getClient } from "../../agent/client";
type SearchMode = "vector" | "fts" | "hybrid"; type SearchMode = "vector" | "fts" | "hybrid";
type ListOrder = "asc" | "desc";
function printUsage(): void { function printUsage(): void {
console.log( console.log(
@@ -52,32 +53,45 @@ function parseMode(value: unknown): SearchMode | undefined {
return undefined; return undefined;
} }
function parseOrder(value: unknown): ListOrder | undefined {
if (typeof value === "string" && (value === "asc" || value === "desc")) {
return value;
}
return undefined;
}
function getAgentId(agentFromArgs?: string, agentIdFromArgs?: string): string { function getAgentId(agentFromArgs?: string, agentIdFromArgs?: string): string {
return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || ""; return agentFromArgs || agentIdFromArgs || process.env.LETTA_AGENT_ID || "";
} }
const MESSAGES_OPTIONS = {
help: { type: "boolean", short: "h" },
query: { type: "string" },
mode: { type: "string" },
"start-date": { type: "string" },
"end-date": { type: "string" },
limit: { type: "string" },
"all-agents": { type: "boolean" },
agent: { type: "string" },
"agent-id": { type: "string" },
after: { type: "string" },
before: { type: "string" },
order: { type: "string" },
} as const;
function parseMessagesArgs(argv: string[]) {
return parseArgs({
args: argv,
options: MESSAGES_OPTIONS,
strict: true,
allowPositionals: true,
});
}
export async function runMessagesSubcommand(argv: string[]): Promise<number> { export async function runMessagesSubcommand(argv: string[]): Promise<number> {
let parsed: ReturnType<typeof parseArgs>; let parsed: ReturnType<typeof parseMessagesArgs>;
try { try {
parsed = parseArgs({ parsed = parseMessagesArgs(argv);
args: argv,
options: {
help: { type: "boolean", short: "h" },
query: { type: "string" },
mode: { type: "string" },
"start-date": { type: "string" },
"end-date": { type: "string" },
limit: { type: "string" },
"all-agents": { type: "boolean" },
agent: { type: "string" },
"agent-id": { type: "string" },
after: { type: "string" },
before: { type: "string" },
order: { type: "string" },
},
strict: true,
allowPositionals: true,
});
} catch (error) { } catch (error) {
const message = error instanceof Error ? error.message : String(error); const message = error instanceof Error ? error.message : String(error);
console.error(`Error: ${message}`); console.error(`Error: ${message}`);
@@ -103,8 +117,8 @@ export async function runMessagesSubcommand(argv: string[]): Promise<number> {
const allAgents = parsed.values["all-agents"] ?? false; const allAgents = parsed.values["all-agents"] ?? false;
const agentId = getAgentId( const agentId = getAgentId(
parsed.values.agent as string | undefined, parsed.values.agent,
parsed.values["agent-id"] as string | undefined, parsed.values["agent-id"],
); );
if (!allAgents && !agentId) { if (!allAgents && !agentId) {
console.error( console.error(
@@ -117,8 +131,8 @@ export async function runMessagesSubcommand(argv: string[]): Promise<number> {
query, query,
agent_id: allAgents ? undefined : agentId, agent_id: allAgents ? undefined : agentId,
search_mode: parseMode(parsed.values.mode) ?? "hybrid", search_mode: parseMode(parsed.values.mode) ?? "hybrid",
start_date: parsed.values["start-date"] as string | undefined, start_date: parsed.values["start-date"],
end_date: parsed.values["end-date"] as string | undefined, end_date: parsed.values["end-date"],
limit: parseLimit(parsed.values.limit, 10), limit: parseLimit(parsed.values.limit, 10),
}); });
@@ -128,8 +142,8 @@ export async function runMessagesSubcommand(argv: string[]): Promise<number> {
if (action === "list") { if (action === "list") {
const agentId = getAgentId( const agentId = getAgentId(
parsed.values.agent as string | undefined, parsed.values.agent,
parsed.values["agent-id"] as string | undefined, parsed.values["agent-id"],
); );
if (!agentId) { if (!agentId) {
console.error( console.error(
@@ -138,11 +152,18 @@ export async function runMessagesSubcommand(argv: string[]): Promise<number> {
return 1; return 1;
} }
const orderRaw = parsed.values.order;
const order = parseOrder(orderRaw);
if (orderRaw !== undefined && !order) {
console.error(`Invalid --order "${orderRaw}". Use "asc" or "desc".`);
return 1;
}
const response = await client.agents.messages.list(agentId, { const response = await client.agents.messages.list(agentId, {
limit: parseLimit(parsed.values.limit, 20), limit: parseLimit(parsed.values.limit, 20),
after: parsed.values.after as string | undefined, after: parsed.values.after,
before: parsed.values.before as string | undefined, before: parsed.values.before,
order: parsed.values.order as "asc" | "desc" | undefined, order,
}); });
const messages = response.items ?? []; const messages = response.items ?? [];
@@ -151,11 +172,9 @@ export async function runMessagesSubcommand(argv: string[]): Promise<number> {
let filtered = messages; let filtered = messages;
if (startDate || endDate) { if (startDate || endDate) {
const startTime = startDate const startTime = startDate ? new Date(startDate).getTime() : 0;
? new Date(startDate as string).getTime()
: 0;
const endTime = endDate const endTime = endDate
? new Date(endDate as string).getTime() ? new Date(endDate).getTime()
: Number.POSITIVE_INFINITY; : Number.POSITIVE_INFINITY;
filtered = messages.filter((msg) => { filtered = messages.filter((msg) => {
if (!("date" in msg) || !msg.date) return true; if (!("date" in msg) || !msg.date) return true;