fix: route claudeqq notifications through k3s

This commit is contained in:
Codex
2026-05-16 18:06:06 +00:00
parent 919bdb6b4b
commit 611f287c12
15 changed files with 414 additions and 65 deletions
+2 -2
View File
@@ -286,9 +286,9 @@ export function ClaudeQqPage({ microservices, onRaw, apiBaseUrl = "/api" }: AnyR
h("code", null, repository.commitId || "--"),
),
h("div", { className: "microservice-ref-card" },
h("span", null, "D601 Docker"),
h("span", null, "D601 k3s Service"),
h("strong", null, `${backend.nodeBindHost || "--"}:${backend.nodePort || "--"}`),
h("code", null, `${repository.composeFile || "--"} / ${repository.composeService || "--"}`),
h("code", null, `${backend.proxyMode || "--"} / ${repository.composeFile || "--"}`),
),
),
h(UniDeskErrorBanner, { error: state.error, wide: true }),
@@ -50,15 +50,15 @@ services:
CODE_QUEUE_DEV_CONTAINER_WORKDIR: "${CODE_QUEUE_DEV_CONTAINER_WORKDIR:-/home/ubuntu}"
CODE_QUEUE_EGRESS_PROXY_ENABLED: "${CODE_QUEUE_EGRESS_PROXY_ENABLED:-true}"
CODE_QUEUE_EGRESS_PROXY_URL: "${CODE_QUEUE_EGRESS_PROXY_URL:-http://unidesk-provider-gateway-D601:18789}"
CODE_QUEUE_EGRESS_PROXY_NO_PROXY: "${CODE_QUEUE_EGRESS_PROXY_NO_PROXY:-localhost,127.0.0.1,::1,host.docker.internal,unidesk-provider-gateway-D601,74.48.78.17,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com}"
CODE_QUEUE_EGRESS_PROXY_NO_PROXY: "${CODE_QUEUE_EGRESS_PROXY_NO_PROXY:-localhost,127.0.0.1,::1,host.docker.internal,claudeqq,claudeqq.unidesk,claudeqq.unidesk.svc,claudeqq.unidesk.svc.cluster.local,unidesk-provider-gateway-D601,74.48.78.17,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com}"
HTTP_PROXY: "${CODE_QUEUE_EGRESS_PROXY_URL:-http://unidesk-provider-gateway-D601:18789}"
HTTPS_PROXY: "${CODE_QUEUE_EGRESS_PROXY_URL:-http://unidesk-provider-gateway-D601:18789}"
ALL_PROXY: "${CODE_QUEUE_EGRESS_PROXY_URL:-http://unidesk-provider-gateway-D601:18789}"
http_proxy: "${CODE_QUEUE_EGRESS_PROXY_URL:-http://unidesk-provider-gateway-D601:18789}"
https_proxy: "${CODE_QUEUE_EGRESS_PROXY_URL:-http://unidesk-provider-gateway-D601:18789}"
all_proxy: "${CODE_QUEUE_EGRESS_PROXY_URL:-http://unidesk-provider-gateway-D601:18789}"
NO_PROXY: "${CODE_QUEUE_EGRESS_PROXY_NO_PROXY:-localhost,127.0.0.1,::1,host.docker.internal,unidesk-provider-gateway-D601,74.48.78.17,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com}"
no_proxy: "${CODE_QUEUE_EGRESS_PROXY_NO_PROXY:-localhost,127.0.0.1,::1,host.docker.internal,unidesk-provider-gateway-D601,74.48.78.17,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com}"
NO_PROXY: "${CODE_QUEUE_EGRESS_PROXY_NO_PROXY:-localhost,127.0.0.1,::1,host.docker.internal,claudeqq,claudeqq.unidesk,claudeqq.unidesk.svc,claudeqq.unidesk.svc.cluster.local,unidesk-provider-gateway-D601,74.48.78.17,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com}"
no_proxy: "${CODE_QUEUE_EGRESS_PROXY_NO_PROXY:-localhost,127.0.0.1,::1,host.docker.internal,claudeqq,claudeqq.unidesk,claudeqq.unidesk.svc,claudeqq.unidesk.svc.cluster.local,unidesk-provider-gateway-D601,74.48.78.17,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com}"
CODE_QUEUE_WINDOWS_NATIVE_CODEX_DEFAULT_WORKDIR: "${CODE_QUEUE_WINDOWS_NATIVE_CODEX_DEFAULT_WORKDIR:-/mnt/f/Work/ConStart}"
CODE_QUEUE_WINDOWS_NATIVE_CODEX_BRIDGE_DIR: "${CODE_QUEUE_WINDOWS_NATIVE_CODEX_BRIDGE_DIR:-/home/ubuntu/.unidesk/code-queue/windows-native-codex}"
CODE_QUEUE_WINDOWS_NATIVE_CODEX_COMMAND: "${CODE_QUEUE_WINDOWS_NATIVE_CODEX_COMMAND:-codex app-server --listen stdio://}"
@@ -66,7 +66,7 @@ services:
CODE_QUEUE_WINDOWS_NATIVE_CODEX_IDLE_TIMEOUT_MS: "${CODE_QUEUE_WINDOWS_NATIVE_CODEX_IDLE_TIMEOUT_MS:-600000}"
OA_EVENT_FLOW_BASE_URL: "${OA_EVENT_FLOW_BASE_URL:-http://74.48.78.17:4255}"
CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED:-true}"
CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL:-http://host.docker.internal:3290}"
CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL:-http://claudeqq.unidesk.svc.cluster.local:3290}"
CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE:-private}"
CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID:-645275593}"
CODE_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID: "${CODE_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID:-}"
@@ -384,7 +384,7 @@ function readConfig(): RuntimeConfig {
databaseFlushIntervalMs: Math.max(100, Math.min(10_000, envNumber("CODE_QUEUE_DATABASE_FLUSH_INTERVAL_MS", 1000))),
oaEventFlowBaseUrl: envString("OA_EVENT_FLOW_BASE_URL", "http://oa-event-flow:4255").replace(/\/+$/u, ""),
notifyClaudeQqEnabled: envBool("CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED", false),
notifyClaudeQqBaseUrl: envString("CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL", "http://backend-core:8080/api/microservices/claudeqq/proxy").replace(/\/+$/u, ""),
notifyClaudeQqBaseUrl: envString("CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL", "http://claudeqq.unidesk.svc.cluster.local:3290").replace(/\/+$/u, ""),
notifyClaudeQqTargetType: notifyTargetTypeRaw === "group" ? "group" : "private",
notifyClaudeQqUserId: envString("CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID", "645275593").trim(),
notifyClaudeQqGroupId: envString("CODE_QUEUE_NOTIFY_CLAUDEQQ_GROUP_ID", "").trim(),
@@ -39,7 +39,7 @@ services:
K3SCTL_NATIVE_SERVICE_TUNNEL_CONNECT_TIMEOUT_MS: "${K3SCTL_NATIVE_SERVICE_TUNNEL_CONNECT_TIMEOUT_MS:-3000}"
K3SCTL_NATIVE_SERVICE_URL_CODE_QUEUE: "${K3SCTL_NATIVE_SERVICE_URL_CODE_QUEUE:-}"
K3SCTL_NATIVE_SERVICE_URL_MDTODO: "${K3SCTL_NATIVE_SERVICE_URL_MDTODO:-}"
K3SCTL_MANIFEST_PATHS: "${K3SCTL_MANIFEST_PATHS:-k3s/code-queue.k3s.json,k3s/mdtodo.k3s.json}"
K3SCTL_MANIFEST_PATHS: "${K3SCTL_MANIFEST_PATHS:-k3s/code-queue.k3s.json,k3s/mdtodo.k3s.json,k3s/claudeqq.k3s.json}"
K3SCTL_SERVICES_JSON: "${K3SCTL_SERVICES_JSON:-[]}"
UNIDESK_LOG_RETENTION_BYTES: "${UNIDESK_LOG_RETENTION_BYTES:-512MiB}"
volumes:
@@ -0,0 +1,37 @@
{
"apiVersion": "unidesk.ai/k3s/v1",
"kind": "ManagedKubernetesService",
"metadata": {
"name": "claudeqq",
"namespace": "unidesk"
},
"spec": {
"adapterServiceId": "k3sctl-adapter",
"controlPlane": {
"type": "kubernetes",
"cluster": "unidesk-k3s",
"context": "unidesk-k3s"
},
"route": {
"kind": "kubernetes-service",
"serviceName": "claudeqq",
"servicePort": 3290
},
"activeInstanceId": "D601",
"singleWriter": true,
"expectedNodeIds": [
"D601"
],
"instances": [
{
"id": "D601",
"nodeId": "D601",
"role": "primary",
"baseUrl": "kubernetes://unidesk/services/claudeqq:3290",
"healthPath": "/health",
"healthMode": "service-proxy"
}
],
"requireAllInstancesHealthy": true
}
}
@@ -0,0 +1,213 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: claudeqq
namespace: unidesk
labels:
app.kubernetes.io/name: claudeqq
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
unidesk.ai/instance-id: D601
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: claudeqq
unidesk.ai/instance-id: D601
template:
metadata:
labels:
app.kubernetes.io/name: claudeqq
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
unidesk.ai/instance-id: D601
unidesk.ai/node-id: D601
spec:
nodeSelector:
unidesk.ai/node-id: D601
terminationGracePeriodSeconds: 30
containers:
- name: napcat
image: mlikiowa/napcat-docker:latest
imagePullPolicy: IfNotPresent
ports:
- name: napcat-http
containerPort: 3000
- name: napcat-ws
containerPort: 3001
- name: napcat-webui
containerPort: 6099
env:
- name: WEBUI_PREFIX
value: "/webui"
- name: WEBUI_TOKEN
value: "unidesk-napcat"
- name: NAPCAT_UID
value: "1000"
- name: NAPCAT_GID
value: "1000"
- name: ACCOUNT
value: "763382329"
volumeMounts:
- name: napcat-qq
mountPath: /app/.config/QQ
- name: napcat-config
mountPath: /app/napcat/config
- name: napcat-cache
mountPath: /app/napcat/cache
readinessProbe:
tcpSocket:
port: napcat-http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 12
livenessProbe:
tcpSocket:
port: napcat-http
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 12
- name: claudeqq
image: unidesk-claudeqq:d601
imagePullPolicy: IfNotPresent
workingDir: /app/scripts/src/server_ts
command:
- node
- dist/index.js
- --max-restarts
- "0"
ports:
- name: http
containerPort: 3290
env:
- name: CLAUDEQQ_HOST
value: "0.0.0.0"
- name: CLAUDEQQ_PORT
value: "3290"
- name: CLAUDEQQ_WORKSPACE_DIR
value: "/bot_workspace"
- name: CLAUDEQQ_AUTO_REPLY
value: "false"
- name: CLAUDEQQ_NAPCAT_HTTP_HOST
value: "127.0.0.1"
- name: CLAUDEQQ_NAPCAT_HTTP_PORT
value: "3000"
- name: CLAUDEQQ_NAPCAT_WS_HOST
value: "127.0.0.1"
- name: CLAUDEQQ_NAPCAT_WS_PORT
value: "3001"
- name: CLAUDEQQ_NAPCAT_ACCOUNT
value: "763382329"
- name: CLAUDEQQ_NAPCAT_DATA_DIR
value: "/napcat"
- name: CLAUDEQQ_NAPCAT_WEBUI_URL
value: "http://127.0.0.1:6099/webui"
- name: CLAUDEQQ_ONLINE_NOTICE_ENABLED
value: "true"
- name: CLAUDEQQ_ONLINE_NOTICE_USER_ID
value: "645275593"
- name: CLAUDEQQ_LOGIN_MONITOR_INTERVAL_MS
value: "10000"
- name: UNIDESK_DEPLOY_SERVICE_ID
value: "claudeqq"
volumeMounts:
- name: config-json
mountPath: /app/config.json
readOnly: true
- name: bot-workspace
mountPath: /bot_workspace
- name: logs
mountPath: /app/logs
- name: state
mountPath: /app/.state
- name: napcat-root
mountPath: /napcat
readOnly: true
- name: napcat-shell
mountPath: /app/NapCat.Shell.Windows.OneKey
readOnly: true
readinessProbe:
httpGet:
path: /health
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 20
livenessProbe:
httpGet:
path: /health
port: http
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 12
startupProbe:
httpGet:
path: /health
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 60
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 1Gi
volumes:
- name: config-json
hostPath:
path: /home/ubuntu/.agents/skills/claudeqq/config.json
type: File
- name: bot-workspace
hostPath:
path: /home/ubuntu/.agents/skills/claudeqq/bot_workspace
type: DirectoryOrCreate
- name: logs
hostPath:
path: /home/ubuntu/.agents/skills/claudeqq/logs
type: DirectoryOrCreate
- name: state
hostPath:
path: /home/ubuntu/.agents/skills/claudeqq/.state
type: DirectoryOrCreate
- name: napcat-root
hostPath:
path: /home/ubuntu/.agents/skills/claudeqq/napcat
type: DirectoryOrCreate
- name: napcat-qq
hostPath:
path: /home/ubuntu/.agents/skills/claudeqq/napcat/qq
type: DirectoryOrCreate
- name: napcat-config
hostPath:
path: /home/ubuntu/.agents/skills/claudeqq/napcat/config
type: DirectoryOrCreate
- name: napcat-cache
hostPath:
path: /home/ubuntu/.agents/skills/claudeqq/napcat/cache
type: DirectoryOrCreate
- name: napcat-shell
hostPath:
path: /home/ubuntu/.agents/skills/claudeqq/NapCat.Shell.Windows.OneKey
type: DirectoryOrCreate
---
apiVersion: v1
kind: Service
metadata:
name: claudeqq
namespace: unidesk
labels:
app.kubernetes.io/name: claudeqq
app.kubernetes.io/part-of: unidesk
unidesk.ai/deployment-mode: k3sctl-managed
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: claudeqq
unidesk.ai/instance-id: D601
ports:
- name: http
port: 3290
targetPort: http
@@ -988,7 +988,7 @@ spec:
- name: CODE_QUEUE_EGRESS_PROXY_URL
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: CODE_QUEUE_EGRESS_PROXY_NO_PROXY
value: "localhost,127.0.0.1,::1,host.docker.internal,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,172.25.0.3,unidesk-provider-gateway-D601,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com"
value: "localhost,127.0.0.1,::1,host.docker.internal,claudeqq,claudeqq.unidesk,claudeqq.unidesk.svc,claudeqq.unidesk.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,172.25.0.3,unidesk-provider-gateway-D601,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com"
- name: HTTP_PROXY
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: HTTPS_PROXY
@@ -1002,15 +1002,15 @@ spec:
- name: all_proxy
value: "http://d601-provider-egress-proxy.unidesk.svc.cluster.local:18789"
- name: NO_PROXY
value: "localhost,127.0.0.1,::1,host.docker.internal,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,172.25.0.3,unidesk-provider-gateway-D601,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com"
value: "localhost,127.0.0.1,::1,host.docker.internal,claudeqq,claudeqq.unidesk,claudeqq.unidesk.svc,claudeqq.unidesk.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,172.25.0.3,unidesk-provider-gateway-D601,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com"
- name: no_proxy
value: "localhost,127.0.0.1,::1,host.docker.internal,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,172.25.0.3,unidesk-provider-gateway-D601,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com"
value: "localhost,127.0.0.1,::1,host.docker.internal,claudeqq,claudeqq.unidesk,claudeqq.unidesk.svc,claudeqq.unidesk.svc.cluster.local,d601-provider-egress-proxy,d601-provider-egress-proxy.unidesk,d601-provider-egress-proxy.unidesk.svc,d601-provider-egress-proxy.unidesk.svc.cluster.local,d601-tcp-egress-gateway,d601-tcp-egress-gateway.unidesk,d601-tcp-egress-gateway.unidesk.svc,d601-tcp-egress-gateway.unidesk.svc.cluster.local,172.25.0.3,unidesk-provider-gateway-D601,backend-core,oa-event-flow,database,hyueapi.com,.hyueapi.com"
- name: OA_EVENT_FLOW_BASE_URL
value: "http://d601-tcp-egress-gateway.unidesk.svc.cluster.local:4255"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED
value: "true"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_BASE_URL
value: "http://host.docker.internal:3290"
value: "http://claudeqq.unidesk.svc.cluster.local:3290"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_TARGET_TYPE
value: "private"
- name: CODE_QUEUE_NOTIFY_CLAUDEQQ_USER_ID
@@ -274,7 +274,7 @@ function mergeServices(services: ManagedService[]): ManagedService[] {
}
function readConfig(): RuntimeConfig {
const paths = manifestPaths(envString("K3SCTL_MANIFEST_PATHS", "k3s/code-queue.k3s.json"));
const paths = manifestPaths(envString("K3SCTL_MANIFEST_PATHS", "k3s/code-queue.k3s.json,k3s/mdtodo.k3s.json,k3s/claudeqq.k3s.json"));
const inlineServices = parseServices(envString("K3SCTL_SERVICES_JSON", "[]"));
const manifestServices = readManifestServices(paths);
return {