refactor: remove executeCommand in favor of standard run/stream path
This commit is contained in:
@@ -31,7 +31,6 @@ import type {
|
||||
PaseoWorktreeArchiveResponse,
|
||||
ProjectIconResponse,
|
||||
ListCommandsResponse,
|
||||
ExecuteCommandResponse,
|
||||
ListProviderModelsResponseMessage,
|
||||
ListAvailableProvidersResponse,
|
||||
SpeechModelsListResponse,
|
||||
@@ -208,7 +207,6 @@ type ListAvailableProvidersPayload = ListAvailableProvidersResponse["payload"];
|
||||
type SpeechModelsListPayload = SpeechModelsListResponse["payload"];
|
||||
type SpeechModelsDownloadPayload = SpeechModelsDownloadResponse["payload"];
|
||||
type ListCommandsPayload = ListCommandsResponse["payload"];
|
||||
type ExecuteCommandPayload = ExecuteCommandResponse["payload"];
|
||||
type ListCommandsDraftConfig = Pick<
|
||||
AgentSessionConfig,
|
||||
"provider" | "cwd" | "modeId" | "model" | "thinkingOptionId"
|
||||
@@ -2209,25 +2207,6 @@ export class DaemonClient {
|
||||
});
|
||||
}
|
||||
|
||||
async executeCommand(
|
||||
agentId: string,
|
||||
commandName: string,
|
||||
args?: string,
|
||||
requestId?: string
|
||||
): Promise<ExecuteCommandPayload> {
|
||||
return this.sendCorrelatedSessionRequest({
|
||||
requestId,
|
||||
message: {
|
||||
type: "execute_command_request",
|
||||
agentId,
|
||||
commandName,
|
||||
args,
|
||||
},
|
||||
responseType: "execute_command_response",
|
||||
timeout: 30000,
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Permissions
|
||||
// ============================================================================
|
||||
|
||||
@@ -281,15 +281,6 @@ export type AgentSlashCommand = {
|
||||
argumentHint: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Result from executing a slash command.
|
||||
*/
|
||||
export type AgentCommandResult = {
|
||||
text: string;
|
||||
timeline: AgentTimelineItem[];
|
||||
usage?: AgentUsage;
|
||||
};
|
||||
|
||||
export type ListPersistedAgentsOptions = {
|
||||
limit?: number;
|
||||
};
|
||||
@@ -353,13 +344,6 @@ export interface AgentSession {
|
||||
* Commands are provider-specific - Claude supports skills and built-in commands.
|
||||
*/
|
||||
listCommands?(): Promise<AgentSlashCommand[]>;
|
||||
/**
|
||||
* Execute a slash command by name.
|
||||
* The command name should NOT include the leading "/" - it will be added automatically.
|
||||
* @param commandName The command name (e.g., "help", "context")
|
||||
* @param args Optional arguments to pass to the command
|
||||
*/
|
||||
executeCommand?(commandName: string, args?: string): Promise<AgentCommandResult>;
|
||||
/**
|
||||
* Update the model used for subsequent turns (if supported by provider).
|
||||
*/
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
* Tests the ability to:
|
||||
* 1. List available slash commands from a ClaudeAgentSession
|
||||
* 2. Execute slash commands through ClaudeAgentSession
|
||||
*
|
||||
* These tests verify that the agent abstraction layer properly exposes
|
||||
* the Claude Agent SDK's command capabilities.
|
||||
@@ -91,77 +90,4 @@ const hasClaudeCredentials =
|
||||
}, 30000);
|
||||
});
|
||||
|
||||
describe("executeCommand()", () => {
|
||||
it("should execute a command and return a result", async () => {
|
||||
session = await client.createSession(testConfig);
|
||||
|
||||
// The session should have an executeCommand method
|
||||
expect(typeof session.executeCommand).toBe("function");
|
||||
|
||||
// First get available commands to use one that exists
|
||||
const commands = await session.listCommands!();
|
||||
expect(commands.length).toBeGreaterThan(0);
|
||||
|
||||
// Execute one of the available commands
|
||||
const firstCommand = commands[0];
|
||||
const result = await session.executeCommand!(firstCommand.name);
|
||||
|
||||
// Should return a result object
|
||||
expect(result).toBeDefined();
|
||||
expect(typeof result.text).toBe("string");
|
||||
// Note: Some commands may return empty text (e.g., plugin descriptions)
|
||||
|
||||
await session.close();
|
||||
}, 60000);
|
||||
|
||||
it("should return non-empty output for /context command", async () => {
|
||||
session = await client.createSession(testConfig);
|
||||
|
||||
// Execute /context - a local command that returns token usage info
|
||||
const result = await session.executeCommand!("context");
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(typeof result.text).toBe("string");
|
||||
|
||||
// /context MUST return actual content - this is the key test
|
||||
// If this fails, user messages from SDK are not being captured
|
||||
expect(result.text.length).toBeGreaterThan(0);
|
||||
expect(result.text).toContain("Context");
|
||||
|
||||
await session.close();
|
||||
}, 60000);
|
||||
|
||||
it("should include timeline items in result", async () => {
|
||||
session = await client.createSession(testConfig);
|
||||
|
||||
// First get available commands to use one that exists
|
||||
const commands = await session.listCommands!();
|
||||
expect(commands.length).toBeGreaterThan(0);
|
||||
|
||||
const firstCommand = commands[0];
|
||||
const result = await session.executeCommand!(firstCommand.name);
|
||||
|
||||
// Result should include timeline items from the command execution
|
||||
expect(Array.isArray(result.timeline)).toBe(true);
|
||||
|
||||
// Timeline may or may not have items depending on command execution
|
||||
// Just verify the structure is correct
|
||||
|
||||
await session.close();
|
||||
}, 60000);
|
||||
|
||||
it("should throw for non-existent command", async () => {
|
||||
session = await client.createSession(testConfig);
|
||||
|
||||
// Non-existent commands should still work (they get sent as prompts)
|
||||
// but the response should indicate the command doesn't exist
|
||||
// This is how the SDK works - invalid commands become regular prompts
|
||||
const result = await session.executeCommand!("nonexistent_command_xyz");
|
||||
|
||||
// The result should exist (command is treated as a prompt)
|
||||
expect(result).toBeDefined();
|
||||
|
||||
await session.close();
|
||||
}, 60000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,7 +33,6 @@ import {
|
||||
import type {
|
||||
AgentCapabilityFlags,
|
||||
AgentClient,
|
||||
AgentCommandResult,
|
||||
AgentMetadata,
|
||||
AgentMode,
|
||||
AgentModelDefinition,
|
||||
@@ -1015,45 +1014,6 @@ class ClaudeAgentSession implements AgentSession {
|
||||
}));
|
||||
}
|
||||
|
||||
async executeCommand(commandName: string, args?: string): Promise<AgentCommandResult> {
|
||||
const commandPrompt = args ? `/${commandName} ${args}` : `/${commandName}`;
|
||||
|
||||
// Commands return their output in a user message with <local-command-stdout> tags,
|
||||
// NOT as an assistant message. We need to extract that specifically.
|
||||
const events = this.stream(commandPrompt);
|
||||
const timeline: AgentTimelineItem[] = [];
|
||||
let commandOutput = "";
|
||||
let usage: AgentUsage | undefined;
|
||||
|
||||
for await (const event of events) {
|
||||
if (event.type === "timeline") {
|
||||
timeline.push(event.item);
|
||||
// Check for command output in user messages
|
||||
if (event.item.type === "user_message") {
|
||||
const text = event.item.text;
|
||||
const match = text.match(/<local-command-stdout>([\s\S]*?)<\/local-command-stdout>/);
|
||||
if (match) {
|
||||
commandOutput = match[1].trim();
|
||||
}
|
||||
}
|
||||
// Also capture assistant messages (some commands may produce both)
|
||||
if (event.item.type === "assistant_message" && !commandOutput) {
|
||||
commandOutput = event.item.text;
|
||||
}
|
||||
} else if (event.type === "turn_completed") {
|
||||
usage = event.usage;
|
||||
} else if (event.type === "turn_failed") {
|
||||
throw new Error(event.error);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
text: commandOutput,
|
||||
timeline,
|
||||
usage,
|
||||
};
|
||||
}
|
||||
|
||||
private async primeSelectableModelIds(query: Query): Promise<void> {
|
||||
try {
|
||||
const models = await query.supportedModels();
|
||||
|
||||
@@ -516,7 +516,7 @@ describe("Codex app-server provider (integration)", () => {
|
||||
}, 120000);
|
||||
|
||||
test.runIf(isCodexInstalled())(
|
||||
"listCommands includes custom prompts and executeCommand matches run('/prompts:*') expansion",
|
||||
"listCommands includes custom prompts and run('/prompts:*') expands them",
|
||||
async () => {
|
||||
const cleanup = useTempCodexSessionDir();
|
||||
const codexHome = process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex");
|
||||
@@ -553,9 +553,6 @@ describe("Codex app-server provider (integration)", () => {
|
||||
|
||||
const executeArgs = "NAME=world extra_value";
|
||||
const expectedExpanded = `${token}::name=world::pos1=extra_value::dollar=$`;
|
||||
const executeResult = await session.executeCommand?.("prompts:test", executeArgs);
|
||||
expect(executeResult?.text).toContain(expectedExpanded);
|
||||
|
||||
const rawSlashInput = "/prompts:test NAME=world extra_value";
|
||||
const runResult = await session.run(rawSlashInput);
|
||||
expect(runResult.finalText).toContain(expectedExpanded);
|
||||
@@ -571,6 +568,63 @@ describe("Codex app-server provider (integration)", () => {
|
||||
120000
|
||||
);
|
||||
|
||||
test.runIf(isCodexInstalled())(
|
||||
"slash prompt run streams live turn events (turn_started/turn_completed)",
|
||||
async () => {
|
||||
const cleanup = useTempCodexSessionDir();
|
||||
const codexHome = process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex");
|
||||
const promptsDir = path.join(codexHome, "prompts");
|
||||
const promptPath = path.join(promptsDir, "stream-test.md");
|
||||
const cwd = tmpCwd("codex-cmd-stream-");
|
||||
const token = `PASEO_STREAM_TOKEN_${Date.now()}`;
|
||||
|
||||
mkdirSync(promptsDir, { recursive: true });
|
||||
writeFileSync(
|
||||
promptPath,
|
||||
[
|
||||
"---",
|
||||
"description: Stream Test Prompt",
|
||||
"---",
|
||||
`Reply with exactly: ${token}`,
|
||||
].join("\n"),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
try {
|
||||
const client = new CodexAppServerAgentClient(logger);
|
||||
const session = await client.createSession({
|
||||
provider: "codex",
|
||||
cwd,
|
||||
modeId: "auto",
|
||||
model: CODEX_TEST_MODEL,
|
||||
thinkingOptionId: CODEX_TEST_THINKING_OPTION_ID,
|
||||
});
|
||||
try {
|
||||
const events = session.stream("/prompts:stream-test");
|
||||
const seenTypes = new Set<string>();
|
||||
const assistantChunks: string[] = [];
|
||||
for await (const event of events) {
|
||||
seenTypes.add(event.type);
|
||||
if (event.type === "timeline" && event.item.type === "assistant_message") {
|
||||
assistantChunks.push(event.item.text);
|
||||
}
|
||||
}
|
||||
|
||||
expect(seenTypes.has("turn_started")).toBe(true);
|
||||
expect(seenTypes.has("turn_completed")).toBe(true);
|
||||
expect(assistantChunks.join("")).toContain(token);
|
||||
} finally {
|
||||
await session.close();
|
||||
}
|
||||
} finally {
|
||||
cleanup();
|
||||
rmSync(cwd, { recursive: true, force: true });
|
||||
rmSync(promptPath, { force: true });
|
||||
}
|
||||
},
|
||||
120000
|
||||
);
|
||||
|
||||
test.runIf(isCodexInstalled())("command approval flow requests permission and runs command", async () => {
|
||||
const cleanup = useTempCodexSessionDir();
|
||||
const cwd = tmpCwd("codex-cmd-approval-");
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type {
|
||||
AgentCapabilityFlags,
|
||||
AgentClient,
|
||||
AgentCommandResult,
|
||||
AgentMode,
|
||||
AgentModelDefinition,
|
||||
McpServerConfig,
|
||||
@@ -2034,17 +2033,48 @@ class CodexAppServerAgentSession implements AgentSession {
|
||||
}
|
||||
}
|
||||
|
||||
private async buildCommandPromptInput(
|
||||
commandName: string,
|
||||
args?: string
|
||||
): Promise<AgentPromptInput> {
|
||||
if (commandName.startsWith("prompts:")) {
|
||||
const promptName = commandName.slice("prompts:".length);
|
||||
const codexHome = resolveCodexHomeDir();
|
||||
const promptPath = path.join(codexHome, "prompts", `${promptName}.md`);
|
||||
const raw = await fs.readFile(promptPath, "utf8");
|
||||
const parsed = parseFrontMatter(raw);
|
||||
return expandCodexCustomPrompt(parsed.body, args);
|
||||
}
|
||||
|
||||
if (!this.connected) {
|
||||
await this.connect();
|
||||
} else {
|
||||
await this.loadSkills();
|
||||
}
|
||||
const skill = this.cachedSkills.find((entry) => entry.name === commandName);
|
||||
if (skill) {
|
||||
const input = [
|
||||
{ type: "skill", name: skill.name, path: skill.path },
|
||||
] as unknown as AgentPromptContentBlock[];
|
||||
if (args && args.trim().length > 0) {
|
||||
input.push({ type: "text", text: args.trim() });
|
||||
} else {
|
||||
input.push({ type: "text", text: `$${skill.name}` });
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
return args ? `$${commandName} ${args}` : `$${commandName}`;
|
||||
}
|
||||
|
||||
async run(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<AgentRunResult> {
|
||||
const slashCommand = await this.resolveSlashCommandInvocation(prompt);
|
||||
if (slashCommand) {
|
||||
const result = await this.executeCommand(slashCommand.commandName, slashCommand.args);
|
||||
const info = await this.getRuntimeInfo();
|
||||
return {
|
||||
sessionId: info.sessionId ?? "",
|
||||
finalText: result.text,
|
||||
usage: result.usage,
|
||||
timeline: result.timeline,
|
||||
};
|
||||
const commandInput = await this.buildCommandPromptInput(
|
||||
slashCommand.commandName,
|
||||
slashCommand.args
|
||||
);
|
||||
return this.runInternal(commandInput, options);
|
||||
}
|
||||
return this.runInternal(prompt, options);
|
||||
}
|
||||
@@ -2086,15 +2116,11 @@ class CodexAppServerAgentSession implements AgentSession {
|
||||
): AsyncGenerator<AgentStreamEvent> {
|
||||
const slashCommand = await this.resolveSlashCommandInvocation(prompt);
|
||||
if (slashCommand) {
|
||||
const result = await this.executeCommand(slashCommand.commandName, slashCommand.args);
|
||||
for (const item of result.timeline) {
|
||||
yield { type: "timeline", provider: CODEX_PROVIDER, item };
|
||||
}
|
||||
yield {
|
||||
type: "turn_completed",
|
||||
provider: CODEX_PROVIDER,
|
||||
usage: result.usage,
|
||||
};
|
||||
const commandInput = await this.buildCommandPromptInput(
|
||||
slashCommand.commandName,
|
||||
slashCommand.args
|
||||
);
|
||||
yield* this.streamInternal(commandInput, options);
|
||||
return;
|
||||
}
|
||||
yield* this.streamInternal(prompt, options);
|
||||
@@ -2404,42 +2430,6 @@ class CodexAppServerAgentSession implements AgentSession {
|
||||
);
|
||||
}
|
||||
|
||||
async executeCommand(commandName: string, args?: string): Promise<AgentCommandResult> {
|
||||
if (commandName.startsWith("prompts:")) {
|
||||
const promptName = commandName.slice("prompts:".length);
|
||||
const codexHome = resolveCodexHomeDir();
|
||||
const promptPath = path.join(codexHome, "prompts", `${promptName}.md`);
|
||||
const raw = await fs.readFile(promptPath, "utf8");
|
||||
const parsed = parseFrontMatter(raw);
|
||||
const expanded = expandCodexCustomPrompt(parsed.body, args);
|
||||
const result = await this.runInternal(expanded);
|
||||
return { text: result.finalText, timeline: result.timeline, usage: result.usage };
|
||||
}
|
||||
|
||||
if (!this.connected) {
|
||||
await this.connect();
|
||||
} else {
|
||||
await this.loadSkills();
|
||||
}
|
||||
const skill = this.cachedSkills.find((entry) => entry.name === commandName);
|
||||
if (skill) {
|
||||
const input = [
|
||||
{ type: "skill", name: skill.name, path: skill.path },
|
||||
] as unknown as AgentPromptContentBlock[];
|
||||
if (args && args.trim().length > 0) {
|
||||
input.push({ type: "text", text: args.trim() });
|
||||
} else {
|
||||
input.push({ type: "text", text: `$${skill.name}` });
|
||||
}
|
||||
const result = await this.runInternal(input);
|
||||
return { text: result.finalText, timeline: result.timeline, usage: result.usage };
|
||||
}
|
||||
|
||||
const skillPrompt = args ? `$${commandName} ${args}` : `$${commandName}`;
|
||||
const result = await this.runInternal(skillPrompt);
|
||||
return { text: result.finalText, timeline: result.timeline, usage: result.usage };
|
||||
}
|
||||
|
||||
private async ensureThread(): Promise<void> {
|
||||
if (!this.client) return;
|
||||
if (this.currentThreadId) return;
|
||||
|
||||
@@ -77,7 +77,7 @@ describe("codex agent commands E2E", () => {
|
||||
rmSync(codexHome, { recursive: true, force: true });
|
||||
}, 30_000);
|
||||
|
||||
test("executes a custom prompt command (prompts:*)", async () => {
|
||||
test("executes a custom prompt via normal sendMessage path (prompts:*)", async () => {
|
||||
const codexHome = process.env.CODEX_HOME ?? path.join(process.env.HOME ?? "/tmp", ".codex");
|
||||
|
||||
const promptsDir = path.join(codexHome, "prompts");
|
||||
@@ -95,18 +95,19 @@ describe("codex agent commands E2E", () => {
|
||||
title: "Codex Prompt Execute Test Agent",
|
||||
});
|
||||
|
||||
const result = await ctx.client.executeCommand(
|
||||
await ctx.client.sendMessage(
|
||||
agent.id,
|
||||
"prompts:paseo-test-sayok",
|
||||
"NAME=world"
|
||||
"/prompts:paseo-test-sayok NAME=world"
|
||||
);
|
||||
expect(result.error).toBeNull();
|
||||
expect(result.result?.text).toContain("PASEO_OK");
|
||||
const state = await ctx.client.waitForFinish(agent.id, 30_000);
|
||||
|
||||
expect(state.status).toBe("idle");
|
||||
expect(state.lastMessage).toContain("PASEO_OK");
|
||||
|
||||
rmSync(promptPath, { force: true });
|
||||
}, 30_000);
|
||||
|
||||
test("sendMessage routes known slash commands through executeCommand", async () => {
|
||||
test("sendMessage routes known slash commands through standard run/stream", async () => {
|
||||
const prevCodexHome = process.env.CODEX_HOME;
|
||||
const codexHome = tmpDir("codex-home-send-command-");
|
||||
const promptsDir = path.join(codexHome, "prompts");
|
||||
|
||||
@@ -1527,15 +1527,6 @@ export class Session {
|
||||
await this.handleListCommandsRequest(msg);
|
||||
break;
|
||||
|
||||
case "execute_command_request":
|
||||
await this.handleExecuteCommandRequest(
|
||||
msg.agentId,
|
||||
msg.commandName,
|
||||
msg.args,
|
||||
msg.requestId
|
||||
);
|
||||
break;
|
||||
|
||||
case "register_push_token":
|
||||
this.handleRegisterPushToken(msg.token);
|
||||
break;
|
||||
@@ -3553,79 +3544,6 @@ export class Session {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle execute command request for an agent
|
||||
*/
|
||||
private async handleExecuteCommandRequest(
|
||||
agentId: string,
|
||||
commandName: string,
|
||||
args: string | undefined,
|
||||
requestId: string
|
||||
): Promise<void> {
|
||||
this.sessionLogger.debug(
|
||||
{ agentId, commandName },
|
||||
`Handling execute command request for agent ${agentId}`
|
||||
);
|
||||
|
||||
try {
|
||||
const agents = this.agentManager.listAgents();
|
||||
const agent = agents.find((a) => a.id === agentId);
|
||||
|
||||
if (!agent) {
|
||||
this.emit({
|
||||
type: "execute_command_response",
|
||||
payload: {
|
||||
agentId,
|
||||
result: null,
|
||||
error: `Agent not found: ${agentId}`,
|
||||
requestId,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const session = agent.session;
|
||||
if (!session || !session.executeCommand) {
|
||||
this.emit({
|
||||
type: "execute_command_response",
|
||||
payload: {
|
||||
agentId,
|
||||
result: null,
|
||||
error: `Agent does not support executing commands`,
|
||||
requestId,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await session.executeCommand(commandName, args);
|
||||
|
||||
this.emit({
|
||||
type: "execute_command_response",
|
||||
payload: {
|
||||
agentId,
|
||||
result,
|
||||
error: null,
|
||||
requestId,
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
this.sessionLogger.error(
|
||||
{ err: error, agentId, commandName },
|
||||
"Failed to execute command"
|
||||
);
|
||||
this.emit({
|
||||
type: "execute_command_response",
|
||||
payload: {
|
||||
agentId,
|
||||
result: null,
|
||||
error: error.message,
|
||||
requestId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle agent permission response from user
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,6 @@ import type {
|
||||
AgentSessionConfig,
|
||||
AgentStreamEvent,
|
||||
AgentSlashCommand,
|
||||
AgentCommandResult,
|
||||
AgentUsage,
|
||||
ListModelsOptions,
|
||||
} from "../agent/agent-sdk-types.js";
|
||||
@@ -251,7 +250,7 @@ class FakeAgentSession implements AgentSession {
|
||||
async run(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<AgentRunResult> {
|
||||
const slashCommand = await this.resolveSlashCommandInput(prompt);
|
||||
if (slashCommand) {
|
||||
const result = await this.executeCommand(
|
||||
const result = await this.runSlashCommand(
|
||||
slashCommand.commandName,
|
||||
slashCommand.args
|
||||
);
|
||||
@@ -290,7 +289,7 @@ class FakeAgentSession implements AgentSession {
|
||||
await this.appendHistoryEvent(turnStarted);
|
||||
yield turnStarted;
|
||||
|
||||
const result = await this.executeCommand(
|
||||
const result = await this.runSlashCommand(
|
||||
slashCommand.commandName,
|
||||
slashCommand.args
|
||||
);
|
||||
@@ -578,7 +577,14 @@ class FakeAgentSession implements AgentSession {
|
||||
];
|
||||
}
|
||||
|
||||
async executeCommand(commandName: string, args?: string): Promise<AgentCommandResult> {
|
||||
private async runSlashCommand(
|
||||
commandName: string,
|
||||
args?: string
|
||||
): Promise<{
|
||||
text: string;
|
||||
timeline: AgentRunResult["timeline"];
|
||||
usage: AgentUsage;
|
||||
}> {
|
||||
const fullName = commandName.trim();
|
||||
if (this.providerName === "codex" && fullName.startsWith("prompts:")) {
|
||||
const promptId = fullName.slice("prompts:".length);
|
||||
|
||||
@@ -941,14 +941,6 @@ export const ListCommandsRequestSchema = z.object({
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
export const ExecuteCommandRequestSchema = z.object({
|
||||
type: z.literal("execute_command_request"),
|
||||
agentId: z.string(),
|
||||
commandName: z.string(),
|
||||
args: z.string().optional(),
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
export const RegisterPushTokenMessageSchema = z.object({
|
||||
type: z.literal("register_push_token"),
|
||||
token: z.string(),
|
||||
@@ -1082,7 +1074,6 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
||||
ClientHeartbeatMessageSchema,
|
||||
PingMessageSchema,
|
||||
ListCommandsRequestSchema,
|
||||
ExecuteCommandRequestSchema,
|
||||
RegisterPushTokenMessageSchema,
|
||||
ListTerminalsRequestSchema,
|
||||
SubscribeTerminalsRequestSchema,
|
||||
@@ -1868,22 +1859,6 @@ export const ListCommandsResponseSchema = z.object({
|
||||
}),
|
||||
});
|
||||
|
||||
const AgentCommandResultSchema = z.object({
|
||||
text: z.string(),
|
||||
timeline: z.array(AgentTimelineItemPayloadSchema),
|
||||
usage: AgentUsageSchema.optional(),
|
||||
});
|
||||
|
||||
export const ExecuteCommandResponseSchema = z.object({
|
||||
type: z.literal("execute_command_response"),
|
||||
payload: z.object({
|
||||
agentId: z.string(),
|
||||
result: AgentCommandResultSchema.nullable(),
|
||||
error: z.string().nullable(),
|
||||
requestId: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Terminal Outbound Messages
|
||||
// ============================================================================
|
||||
@@ -2050,7 +2025,6 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
||||
SpeechModelsListResponseSchema,
|
||||
SpeechModelsDownloadResponseSchema,
|
||||
ListCommandsResponseSchema,
|
||||
ExecuteCommandResponseSchema,
|
||||
ListTerminalsResponseSchema,
|
||||
TerminalsChangedSchema,
|
||||
CreateTerminalResponseSchema,
|
||||
@@ -2191,8 +2165,6 @@ export type ClearAgentAttentionMessage = z.infer<typeof ClearAgentAttentionMessa
|
||||
export type ClientHeartbeatMessage = z.infer<typeof ClientHeartbeatMessageSchema>;
|
||||
export type ListCommandsRequest = z.infer<typeof ListCommandsRequestSchema>;
|
||||
export type ListCommandsResponse = z.infer<typeof ListCommandsResponseSchema>;
|
||||
export type ExecuteCommandRequest = z.infer<typeof ExecuteCommandRequestSchema>;
|
||||
export type ExecuteCommandResponse = z.infer<typeof ExecuteCommandResponseSchema>;
|
||||
export type RegisterPushTokenMessage = z.infer<typeof RegisterPushTokenMessageSchema>;
|
||||
|
||||
// Terminal message types
|
||||
|
||||
Reference in New Issue
Block a user