diff --git a/config/agentrun.yaml b/config/agentrun.yaml index d25e4117..b74e1eed 100644 --- a/config/agentrun.yaml +++ b/config/agentrun.yaml @@ -605,6 +605,11 @@ controlPlane: AGENTRUN_MANAGER_RECONCILER_BATCH_SIZE: "20" AGENTRUN_MANAGER_RECONCILER_ENABLED: "true" AGENTRUN_MANAGER_RECONCILER_INTERVAL_MS: "30000" + AGENTRUN_KAFKA_SHADOW_PRODUCE_ENABLED: "true" + AGENTRUN_KAFKA_SHADOW_CONSUME_ENABLED: "false" + AGENTRUN_KAFKA_BOOTSTRAP_SERVERS: platform-infra-kafka-kafka-bootstrap.platform-infra.svc.cluster.local:9092 + AGENTRUN_KAFKA_EVENT_TOPIC: agentrun.hwlab.event.v1 + AGENTRUN_KAFKA_CLIENT_ID: agentrun-v02-manager OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: http://otel-collector.platform-infra.svc.cluster.local:4318/v1/traces OTEL_SERVICE_NAME: agentrun-manager UNIDESK_NODE_ID: D518 diff --git a/config/hwlab-node-lanes.yaml b/config/hwlab-node-lanes.yaml index 850b17ed..ef669e7e 100644 --- a/config/hwlab-node-lanes.yaml +++ b/config/hwlab-node-lanes.yaml @@ -710,6 +710,14 @@ lanes: providerIdFrom: runtimeNodeId defaultProviderProfile: fake-echo codexStdioSupervisor: repo-owned + kafkaShadowProducer: + enabled: true + mode: shadow-produce-only + consumeEnabled: false + configRef: config/platform-infra/kafka.yaml#clients.hwlab-v03-cloud-api + bootstrapServers: platform-infra-kafka-kafka-bootstrap.platform-infra.svc.cluster.local:9092 + commandTopic: hwlab.agentrun.command.v1 + clientId: hwlab-v03-cloud-api publicExposure: mode: pk01-caddy-frp publicBaseUrl: https://hwlab.pikapython.com diff --git a/config/platform-infra/kafka.yaml b/config/platform-infra/kafka.yaml index 4fcfb3e6..d770a72b 100644 --- a/config/platform-infra/kafka.yaml +++ b/config/platform-infra/kafka.yaml @@ -13,7 +13,7 @@ defaults: switch: enabled: true mode: shadow-produce-only - appIntegrationEnabled: false + appIntegrationEnabled: true shadowProduceEnabled: true shadowConsumeEnabled: false @@ -104,7 +104,7 @@ clients: - agentrun.hwlab.event.dlq.v1 - id: agentrun-v02-manager namespace: agentrun-v02 - serviceAccountName: agentrun-manager + serviceAccountName: agentrun-d518-v02-mgr kafkaUserName: agentrun-v02-manager secretName: agentrun-v02-manager produceTopics: diff --git a/scripts/src/hwlab-node-lanes.ts b/scripts/src/hwlab-node-lanes.ts index 24831e94..334f87e9 100644 --- a/scripts/src/hwlab-node-lanes.ts +++ b/scripts/src/hwlab-node-lanes.ts @@ -322,6 +322,16 @@ export interface HwlabRuntimeCodeAgentProviderSpec { readonly opencodeSourceKey?: string; } +export interface HwlabRuntimeKafkaShadowProducerSpec { + readonly enabled: boolean; + readonly mode: "shadow-produce-only"; + readonly consumeEnabled: false; + readonly configRef: string; + readonly bootstrapServers: string; + readonly commandTopic: string; + readonly clientId: string; +} + export interface HwlabRuntimeCodeAgentRuntimeSpec { readonly enabled: boolean; readonly adapter: string; @@ -334,6 +344,7 @@ export interface HwlabRuntimeCodeAgentRuntimeSpec { readonly providerIdFrom: "runtimeNodeId"; readonly defaultProviderProfile: string; readonly codexStdioSupervisor: "repo-owned"; + readonly kafkaShadowProducer?: HwlabRuntimeKafkaShadowProducerSpec; } export interface HwlabRuntimeSourceWorkspaceSpec { @@ -795,6 +806,25 @@ function codeAgentRuntimeConfig(value: unknown, path: string): HwlabRuntimeCodeA providerIdFrom: enumStringField(raw, "providerIdFrom", path, ["runtimeNodeId"]), defaultProviderProfile: stringField(raw, "defaultProviderProfile", path), codexStdioSupervisor: enumStringField(raw, "codexStdioSupervisor", path, ["repo-owned"]), + ...(raw.kafkaShadowProducer === undefined + ? {} + : { kafkaShadowProducer: codeAgentKafkaShadowProducerConfig(raw.kafkaShadowProducer, `${path}.kafkaShadowProducer`) }), + }; +} + +function codeAgentKafkaShadowProducerConfig(value: unknown, path: string): HwlabRuntimeKafkaShadowProducerSpec { + const raw = asRecord(value, path); + const mode = enumStringField(raw, "mode", path, ["shadow-produce-only"]); + const consumeEnabled = booleanField(raw, "consumeEnabled", path); + if (consumeEnabled !== false) throw new Error(`${path}.consumeEnabled must be false during shadow-produce-only stage`); + return { + enabled: booleanField(raw, "enabled", path), + mode, + consumeEnabled, + configRef: stringField(raw, "configRef", path), + bootstrapServers: stringField(raw, "bootstrapServers", path), + commandTopic: stringField(raw, "commandTopic", path), + clientId: stringField(raw, "clientId", path), }; } diff --git a/scripts/src/hwlab-node/plan.ts b/scripts/src/hwlab-node/plan.ts index b777c147..f3c01771 100644 --- a/scripts/src/hwlab-node/plan.ts +++ b/scripts/src/hwlab-node/plan.ts @@ -158,6 +158,7 @@ export function nodeRuntimeExpected(spec: HwlabRuntimeLaneSpec): Record volume && volume.name === 'hwlab-metrics-sidecar')) metricsRefs.push(workloadRef(item, file, { name: 'volume/hwlab-metrics-sidecar' }));", diff --git a/scripts/src/hwlab-node/web-probe.ts b/scripts/src/hwlab-node/web-probe.ts index 2455994f..fab8ffe7 100644 --- a/scripts/src/hwlab-node/web-probe.ts +++ b/scripts/src/hwlab-node/web-probe.ts @@ -108,6 +108,7 @@ export function nodeRuntimeRenderOverlay(spec: HwlabRuntimeLaneSpec): Record