feat: publish AgentRun Kafka event streams

This commit is contained in:
root
2026-07-09 19:25:31 +02:00
parent 4466ba6eb6
commit 120360090c
8 changed files with 560 additions and 65 deletions
+35
View File
@@ -16,6 +16,7 @@ import type { RunnerOnceOptions } from "../../src/runner/run-once.js";
import { backendProfileSpec, isBackendProfile } from "../../src/common/backend-profiles.js";
import { outputBytesFromPayload, outputTruncatedFromPayload } from "../../src/common/output.js";
import { redactJson, redactText } from "../../src/common/redaction.js";
import { tailAgentRunKafka } from "../../src/common/kafka-events.js";
interface ParsedArgs {
positional: string[];
@@ -52,6 +53,7 @@ async function dispatch(args: ParsedArgs): Promise<CliResult> {
if (args.flags.get("help") === true) return help(args, group);
if (command === "help" || command === "--help") return help(args, group);
if (group === "manager" && (command === "url" || command === "resolve-url" || command === "status")) return managerEndpoint(args);
if (group === "kafka" && (command === "tail" || command === "events")) return kafkaTail(args);
if (group === "server" && command === "start") return startServer(args);
if (group === "server" && command === "status") return serverStatus(args);
if (group === "server" && command === "logs") return serverLogs(args);
@@ -159,6 +161,29 @@ async function listRunnerJobs(args: ParsedArgs): Promise<JsonValue> {
return client(args).get(`/api/v1/runs/${encodeURIComponent(runId)}/runner-jobs${commandId ? `?commandId=${encodeURIComponent(commandId)}` : ""}`);
}
async function kafkaTail(args: ParsedArgs): Promise<JsonValue> {
const stream = optionalFlag(args, "stream") ?? args.positional[2] ?? null;
const topic = optionalFlag(args, "topic");
const limit = optionalNumberFlag(args, "limit");
const timeoutMs = optionalNumberFlag(args, "timeout-ms");
return await tailAgentRunKafka({
brokers: optionalFlag(args, "brokers") ?? undefined,
stream: stream ?? undefined,
topic: topic ?? undefined,
groupId: optionalFlag(args, "group-id") ?? undefined,
limit: limit ?? undefined,
timeoutMs: timeoutMs ?? undefined,
fromBeginning: args.flags.get("latest") === true ? false : true,
values: args.flags.get("values") === true || args.flags.get("raw-values") === true,
filter: {
traceId: optionalFlag(args, "trace-id"),
sessionId: optionalFlag(args, "session-id"),
runId: optionalFlag(args, "run-id"),
commandId: optionalFlag(args, "command-id"),
},
}) as JsonValue;
}
async function showRun(args: ParsedArgs, runId: string): Promise<JsonValue> {
const run = await client(args).get(`/api/v1/runs/${encodeURIComponent(runId)}`);
if (wantsExpandedOutput(args)) return run;
@@ -2039,6 +2064,14 @@ function optionalFlag(args: ParsedArgs, name: string): string | null {
return typeof value === "string" && value.length > 0 ? value : null;
}
function optionalNumberFlag(args: ParsedArgs, name: string): number | null {
const value = optionalFlag(args, name);
if (value === null) return null;
const parsed = Number(value);
if (!Number.isFinite(parsed)) throw new AgentRunError("schema-invalid", `--${name} must be a finite number`, { httpStatus: 2 });
return parsed;
}
function cancelBody(args: ParsedArgs): JsonRecord {
const reason = optionalFlag(args, "reason");
return reason ? { reason } : {};
@@ -2051,6 +2084,8 @@ function help(args: ParsedArgs, group?: string): JsonRecord {
"runs events <runId> --after-seq <n> --limit <n> [--summary|--tail-summary] [--tail <n>] [--summary-chars <n>] [--format json|tsv]",
"runs result <runId> [--command-id <commandId>]",
"runs cancel <runId> [--reason <text>]",
"kafka tail [agentrun|stdio] [--topic <topic>] [--brokers <host:port,...>] [--limit <n>] [--timeout-ms <ms>] [--run-id <id>] [--session-id <id>] [--command-id <id>] [--trace-id <id>] [--values]",
"kafka events [agentrun|stdio] [--topic <topic>] [--brokers <host:port,...>] [--limit <n>] [--timeout-ms <ms>]",
"sessions ps [--state default|running|unread|terminal|idle|all] [--profile codex|deepseek|minimax-m3|dsflash-go|<dynamic-profile>|M3] [--reader-id <reader>]",
"sessions create [sessionId] [--profile codex|deepseek|minimax-m3|dsflash-go|<dynamic-profile>|M3] [--expires-in-days <n>]",
"sessions storage <sessionId>",