feat: bridge AgentRun Kafka events to HWLAB stream
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
|
||||
import path from "node:path";
|
||||
import { spawn, poll, getResult, getTrace } from "./src/client.ts";
|
||||
import { queryKafkaEventStream } from "../../../internal/cloud/kafka-event-bridge.ts";
|
||||
|
||||
const argv = process.argv.slice(2);
|
||||
const cmd = argv[0];
|
||||
@@ -63,6 +64,15 @@ async function main() {
|
||||
await getTrace(traceId, parseArgs(2));
|
||||
break;
|
||||
}
|
||||
case "kafka": {
|
||||
const subcommand = argv[1] || "tail";
|
||||
if (subcommand !== "tail" && subcommand !== "query") {
|
||||
process.stderr.write(JSON.stringify({ ok: false, error: { code: "usage", message: "kafka tail [--stream hwlab|agentrun] [--trace-id TRACE_ID] [--session-id SESSION_ID] [--run-id RUN_ID] [--command-id COMMAND_ID]" } }) + "\n");
|
||||
process.exit(1);
|
||||
}
|
||||
await kafkaTail(parseArgs(2));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
process.stderr.write(JSON.stringify({
|
||||
ok: false,
|
||||
@@ -70,13 +80,77 @@ async function main() {
|
||||
spawn: "HWLAB_CODE_AGENT_PROVIDER_PROFILE=PROFILE bun scripts/hwlab-code-agent-cli.ts spawn --message '...' [--profile PROFILE]",
|
||||
poll: "bun scripts/hwlab-code-agent-cli.ts poll <traceId> [--timeout 600000]",
|
||||
result: "bun scripts/hwlab-code-agent-cli.ts result <traceId>",
|
||||
trace: "bun scripts/hwlab-code-agent-cli.ts trace <traceId> [--full]"
|
||||
trace: "bun scripts/hwlab-code-agent-cli.ts trace <traceId> [--full]",
|
||||
kafka: "bun tools/hwlab-code-agent kafka tail --stream hwlab --trace-id trc_... --limit 20"
|
||||
}
|
||||
}, null, 2) + "\n");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async function kafkaTail(args: Record<string, string | undefined>) {
|
||||
const result = await queryKafkaEventStream({
|
||||
env: process.env,
|
||||
stream: args.stream || "hwlab",
|
||||
topic: args.topic || null,
|
||||
traceId: args["trace-id"] || args.traceId || null,
|
||||
sessionId: args["session-id"] || args.sessionId || null,
|
||||
runId: args["run-id"] || args.runId || null,
|
||||
commandId: args["command-id"] || args.commandId || null,
|
||||
limit: boundedInteger(args.limit, 20, 1, 500),
|
||||
timeoutMs: boundedInteger(args["timeout-ms"] || args.timeoutMs, 5000, 250, 60000),
|
||||
fromBeginning: args["from-end"] === "true" || args.fromEnd === "true" ? false : true
|
||||
});
|
||||
process.stdout.write(JSON.stringify({
|
||||
ok: true,
|
||||
action: "hwlab-code-agent.kafka.tail",
|
||||
stream: result.stream,
|
||||
topic: result.topic,
|
||||
count: result.count,
|
||||
limit: result.limit,
|
||||
timeoutMs: result.timeoutMs,
|
||||
filters: result.filters,
|
||||
rows: result.events.map(kafkaEventRow),
|
||||
events: args.full === "true" ? result.events : undefined,
|
||||
valuesPrinted: false
|
||||
}, null, 2) + "\n");
|
||||
}
|
||||
|
||||
function kafkaEventRow(record: any) {
|
||||
const value = record?.value && typeof record.value === "object" ? record.value : {};
|
||||
const event = value.event && typeof value.event === "object" ? value.event : {};
|
||||
const context = value.context && typeof value.context === "object" ? value.context : {};
|
||||
return clean({
|
||||
topic: record.topic,
|
||||
partition: record.partition,
|
||||
offset: record.offset,
|
||||
key: record.key,
|
||||
producedAt: text(value.producedAt),
|
||||
eventType: text(value.eventType ?? event.eventType),
|
||||
traceId: text(value.traceId ?? event.traceId),
|
||||
sessionId: text(value.sessionId ?? event.sessionId),
|
||||
runId: text(context.runId ?? event.runId ?? value.runId),
|
||||
commandId: text(context.commandId ?? event.commandId ?? value.commandId),
|
||||
label: text(event.label),
|
||||
status: text(event.status),
|
||||
sourceSeq: context.sourceSeq ?? event.sourceSeq
|
||||
});
|
||||
}
|
||||
|
||||
function boundedInteger(value: unknown, fallback: number, min: number, max: number) {
|
||||
const parsed = Number.parseInt(String(value ?? ""), 10);
|
||||
const selected = Number.isFinite(parsed) ? parsed : fallback;
|
||||
return Math.min(max, Math.max(min, selected));
|
||||
}
|
||||
|
||||
function text(value: unknown) {
|
||||
return String(value ?? "").trim();
|
||||
}
|
||||
|
||||
function clean(value: Record<string, unknown>) {
|
||||
return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined && item !== "" && item !== null));
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
process.stderr.write(JSON.stringify({ ok: false, error: { code: "unhandled", message: e.message } }) + "\n");
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user