wip: 2026-08-11 工作树快照(docs/memory/h5.py/scripts 等 447 项未评审改动,安全提交到 feat 分支)
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
CREATE (i1:Issue {name: "打印机驱动安装", category: "硬件问题", uuid: "issue-001"})
|
||||
CREATE (a1:Action {name: "打印机驱动安装步骤", description: "1. 打开控制面板 2. 添加打印机 3. 选择手动添加"})
|
||||
CREATE (i1)-[:HAS_ACTION]->(a1)
|
||||
RETURN "done"
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# 构建 P2/P3 前端
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# 设置 npm 镜像
|
||||
$env:NPM_CONFIG_REGISTRY = "https://registry.npmmirror.com"
|
||||
|
||||
# 构建 frontend-agent
|
||||
Write-Host "Building frontend-agent..."
|
||||
Set-Location "D:\资料\03-项目开发\wecom_it_smart_desk\frontend-agent"
|
||||
& "C:\Users\simon\.workbuddy\binaries\node\versions\22.22.2\node.exe" "C:\Users\simon\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js" install
|
||||
if ($LASTEXITCODE -ne 0) { throw "npm install failed" }
|
||||
|
||||
& "C:\Users\simon\.workbuddy\binaries\node\versions\22.22.2\node.exe" "C:\Users\simon\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js" run build
|
||||
if ($LASTEXITCODE -ne 0) { throw "npm run build failed" }
|
||||
|
||||
Write-Host "frontend-agent built successfully!"
|
||||
|
||||
# 构建 frontend-h5
|
||||
Write-Host "Building frontend-h5..."
|
||||
Set-Location "D:\资料\03-项目开发\wecom_it_smart_desk\frontend-h5"
|
||||
& "C:\Users\simon\.workbuddy\binaries\node\versions\22.22.2\node.exe" "C:\Users\simon\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js" install
|
||||
if ($LASTEXITCODE -ne 0) { throw "npm install failed" }
|
||||
|
||||
& "C:\Users\simon\.workbuddy\binaries\node\versions\22.22.2\node.exe" "C:\Users\simon\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js" run build
|
||||
if ($LASTEXITCODE -ne 0) { throw "npm run build failed" }
|
||||
|
||||
Write-Host "frontend-h5 built successfully!"
|
||||
|
||||
Write-Host "All done!"
|
||||
@@ -0,0 +1,2 @@
|
||||
-- 查询坐席状态
|
||||
SELECT id, name, status FROM agents;
|
||||
@@ -0,0 +1,5 @@
|
||||
SELECT id, created_at, message_type, sender_type, content
|
||||
FROM messages
|
||||
WHERE sender_type = 'ai'
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 10;
|
||||
@@ -0,0 +1 @@
|
||||
SELECT column_name FROM information_schema.columns WHERE table_name = 'messages' AND column_name LIKE '%source%';
|
||||
@@ -0,0 +1,26 @@
|
||||
import asyncio
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
async def test():
|
||||
from app.services.neo4j_client import get_neo4j_client
|
||||
|
||||
neo4j_client = await get_neo4j_client()
|
||||
keyword = "打印机驱动安装"
|
||||
|
||||
# 直接测试 Cypher 查询
|
||||
try:
|
||||
data = await neo4j_client.execute_read_query(
|
||||
"MATCH (i:Issue) WHERE i.name CONTAINS $keyword RETURN i.uuid AS uuid, i.name AS name, i.category AS category LIMIT 5",
|
||||
{"keyword": keyword}
|
||||
)
|
||||
print(f"Data type: {type(data)}")
|
||||
print(f"Data: {data}")
|
||||
if data:
|
||||
print(f"First record uuid: {data[0].get('uuid')}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
asyncio.run(test())
|
||||
@@ -0,0 +1,27 @@
|
||||
import asyncio
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
async def test():
|
||||
from app.services.graph_query_service import get_graph_query_service
|
||||
from app.services.neo4j_client import get_neo4j_client
|
||||
|
||||
neo4j_client = await get_neo4j_client()
|
||||
graph_service = await get_graph_query_service(neo4j_client)
|
||||
|
||||
# 测试关键词提取
|
||||
question = "打印机驱动安装"
|
||||
keywords = graph_service._extract_keywords(question)
|
||||
print(f"Question: {question}")
|
||||
print(f"Keywords: {keywords}")
|
||||
|
||||
# 测试每个关键词的查询
|
||||
for kw in keywords:
|
||||
print(f"\n=== Querying keyword: {kw} ===")
|
||||
try:
|
||||
result = await graph_service._query_by_keyword(kw)
|
||||
print(f"Result: {result}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
asyncio.run(test())
|
||||
@@ -0,0 +1,27 @@
|
||||
import asyncio
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
async def test():
|
||||
from app.services.graph_query_service import get_graph_query_service
|
||||
from app.services.neo4j_client import get_neo4j_client
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
neo4j_client = await get_neo4j_client()
|
||||
graph_service = await get_graph_query_service(neo4j_client)
|
||||
|
||||
keyword = "打印机驱动安装"
|
||||
print(f"Querying keyword: {keyword}")
|
||||
|
||||
# 直接调用 Neo4j 查询
|
||||
try:
|
||||
data = await neo4j_client.execute_read_query(
|
||||
"""MATCH (i:Issue) WHERE i.name CONTAINS $keyword RETURN i.uuid AS uuid, i.name AS name, i.category AS category LIMIT 5""",
|
||||
{"keyword": keyword}
|
||||
)
|
||||
print(f"Raw data: {data}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
asyncio.run(test())
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# /itdesk/ 500 错误诊断脚本
|
||||
# 在生产服务器 10.90.5.110 上跑(PuTTY 登录后):
|
||||
# cd /opt/wecom-it-desk
|
||||
# bash diagnose-500.sh > /tmp/diag.log 2>&1
|
||||
# cat /tmp/diag.log
|
||||
# =============================================================================
|
||||
|
||||
echo "========== 1. 容器状态 =========="
|
||||
docker compose ps
|
||||
|
||||
echo ""
|
||||
echo "========== 2. /opt/wecom-it-desk 目录结构 =========="
|
||||
ls -la /opt/wecom-it-desk/ 2>&1 | head -20
|
||||
echo "--- frontend-h5/dist ---"
|
||||
ls -la /opt/wecom-it-desk/frontend-h5/dist/ 2>&1 | head -10
|
||||
echo "--- frontend-h5/dist/assets ---"
|
||||
ls -la /opt/wecom-it-desk/frontend-h5/dist/assets/ 2>&1 | head -10
|
||||
echo "--- frontend-agent/dist/assets ---"
|
||||
ls -la /opt/wecom-it-desk/frontend-agent/dist/assets/ 2>&1 | head -10
|
||||
echo "--- frontend-portal/dist/assets ---"
|
||||
ls -la /opt/wecom-it-desk/frontend-portal/dist/assets/ 2>&1 | head -10
|
||||
echo "--- frontend-admin/dist/assets ---"
|
||||
ls -la /opt/wecom-it-desk/frontend-admin/dist/assets/ 2>&1 | head -10
|
||||
|
||||
echo ""
|
||||
echo "========== 3. nginx 容器内文件检查 =========="
|
||||
docker compose exec nginx ls -la /usr/share/nginx/html/ 2>&1 | head -20
|
||||
echo "--- /usr/share/nginx/html/itdesk ---"
|
||||
docker compose exec nginx ls -la /usr/share/nginx/html/itdesk/ 2>&1 | head -10
|
||||
echo "--- /usr/share/nginx/html/itdesk/assets ---"
|
||||
docker compose exec nginx ls -la /usr/share/nginx/html/itdesk/assets/ 2>&1 | head -10
|
||||
echo "--- /usr/share/nginx/ssl/ ---"
|
||||
docker compose exec nginx ls -la /etc/nginx/ssl/ 2>&1 | head -10
|
||||
|
||||
echo ""
|
||||
echo "========== 4. nginx 配置实际生效版本(头部 50 行)=========="
|
||||
docker compose exec nginx cat /etc/nginx/nginx.conf 2>&1 | head -50
|
||||
|
||||
echo ""
|
||||
echo "========== 5. nginx 容器端口监听 =========="
|
||||
docker compose exec nginx netstat -tlnp 2>&1 | head -10
|
||||
echo "(没 netstat 用 ss:)"
|
||||
docker compose exec nginx ss -tlnp 2>&1 | head -10
|
||||
|
||||
echo ""
|
||||
echo "========== 6. 直接 curl 测试各路径 =========="
|
||||
echo "--- /itdesk/ (容器内) ---"
|
||||
docker compose exec nginx curl -ksI https://localhost/itdesk/ 2>&1 | head -20
|
||||
echo "--- /itdesk/ (容器外主机 443) ---"
|
||||
curl -ksI https://localhost:443/itdesk/ 2>&1 | head -20
|
||||
echo "--- /itportal/ ---"
|
||||
curl -ksI https://localhost:443/itportal/ 2>&1 | head -20
|
||||
echo "--- /itdesk/assets/ (探 404) ---"
|
||||
curl -ksI https://localhost:443/itdesk/assets/ 2>&1 | head -20
|
||||
|
||||
echo ""
|
||||
echo "========== 7. 主机实际 URL 域名 =========="
|
||||
curl -ksI https://itsupport.servyou.com.cn/itdesk/ 2>&1 | head -20
|
||||
echo "---"
|
||||
curl -ksI https://itsupport.servyou.com.cn/itportal/ 2>&1 | head -20
|
||||
echo "---"
|
||||
curl -ksI https://itsupport.servyou.com.cn/itagent/ 2>&1 | head -20
|
||||
echo "---"
|
||||
curl -ksI https://itsupport.servyou.com.cn/itadmin/ 2>&1 | head -20
|
||||
|
||||
echo ""
|
||||
echo "========== 8. nginx access log 最近 30 行(找 500 请求)=========="
|
||||
docker compose exec nginx tail -30 /var/log/nginx/access.log 2>&1
|
||||
echo ""
|
||||
echo "========== 9. nginx error log 最近 30 行 =========="
|
||||
docker compose exec nginx tail -30 /var/log/nginx/error.log 2>&1
|
||||
|
||||
echo ""
|
||||
echo "========== 10. backend 容器健康 =========="
|
||||
docker compose ps backend
|
||||
echo "--- backend health endpoint ---"
|
||||
docker compose exec backend curl -ks http://localhost:8000/api/health 2>&1 | head -5
|
||||
|
||||
echo ""
|
||||
echo "========== 11. 看一下后端访问 /api/h5/me (H5 启动时会调)=========="
|
||||
echo "--- /api/h5/me 无 token ---"
|
||||
curl -ks -i -X GET https://itsupport.servyou.com.cn/api/h5/me 2>&1 | head -10
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
set +e # collect everything, don't bail
|
||||
|
||||
echo '############ STEP 1: Locate project directory ############'
|
||||
cd /opt/wecom-it-desk 2>&1
|
||||
echo "Current dir: $(pwd)"
|
||||
ls -la docker-compose.yml 2>&1
|
||||
echo ''
|
||||
|
||||
echo '############ STEP 2: Diagnose (READ-ONLY) ############'
|
||||
echo '--- All wecom_it_ containers ---'
|
||||
docker ps -a --format "table {{.Names}}\t{{.Status}}" | grep -E "wecom_it_|NAMES"
|
||||
echo ''
|
||||
echo '--- Disk space ---'
|
||||
df -h /opt 2>&1
|
||||
echo ''
|
||||
echo '--- backend last 60 log lines ---'
|
||||
docker logs wecom_it_backend --tail 60 2>&1
|
||||
echo ''
|
||||
echo '--- backend internal health check ---'
|
||||
docker exec wecom_it_backend curl -s -o - -w "\nHTTP_CODE: %{http_code}\n" --max-time 5 http://localhost:8000/health 2>&1
|
||||
echo ''
|
||||
|
||||
echo '############ STEP 3: Restart from correct directory ############'
|
||||
cd /opt/wecom-it-desk
|
||||
docker compose up -d 2>&1
|
||||
echo ''
|
||||
echo 'Waiting 15s for services to stabilize...'
|
||||
sleep 15
|
||||
echo ''
|
||||
echo '--- Containers after restart ---'
|
||||
docker ps -a --format "table {{.Names}}\t{{.Status}}" | grep -E "wecom_it_|NAMES"
|
||||
echo ''
|
||||
|
||||
echo '############ STEP 4: End-to-end verification ############'
|
||||
echo '--- backend /health ---'
|
||||
curl -s -o - -w "\nHTTP_CODE: %{http_code}\n" --max-time 5 http://localhost:8000/health
|
||||
echo ''
|
||||
echo '--- nginx routes (expect 200/301/302) ---'
|
||||
for path in / /itagent/ /ith5/ /itadmin/; do
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "http://localhost${path}")
|
||||
echo " $path -> HTTP $code"
|
||||
done
|
||||
echo ''
|
||||
echo '############ DONE ############'
|
||||
echo 'Paste ALL output above back to Claude for diagnosis'
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE alembic_version SET version_num = '041_message_server_timestamp';
|
||||
@@ -0,0 +1,14 @@
|
||||
// 添加测试数据到 Neo4j 图谱
|
||||
CREATE (i1:Issue {name: "打印机驱动安装", category: "硬件问题"})
|
||||
CREATE (a1:Action {name: "打印机驱动安装步骤", description: "1. 打开控制面板 2. 添加打印机 3. 选择手动添加"})
|
||||
CREATE (i1)-[:HAS_ACTION]->(a1)
|
||||
|
||||
CREATE (i2:Issue {name: "网络连不上", category: "网络问题"})
|
||||
CREATE (a2:Action {name: "网络诊断步骤", description: "1. 检查网线 2. 重启路由器 3. 检查IP配置"})
|
||||
CREATE (i2)-[:HAS_ACTION]->(a2)
|
||||
|
||||
CREATE (i3:Issue {name: "邮箱无法收发", category: "软件问题"})
|
||||
CREATE (a3:Action {name: "邮箱故障排除", description: "1. 检查网络 2. 清除缓存 3. 重新登录"})
|
||||
CREATE (i3)-[:HAS_ACTION]->(a3)
|
||||
|
||||
RETURN "测试数据添加完成"
|
||||
@@ -0,0 +1,26 @@
|
||||
// 添加更多测试数据到 Neo4j 图谱
|
||||
CREATE (i1:Issue {name: "打印机驱动安装", category: "硬件问题"})
|
||||
CREATE (a1:Action {name: "打印机驱动安装步骤", description: "1. 打开控制面板 2. 添加打印机 3. 选择手动添加"})
|
||||
CREATE (i1)-[:HAS_ACTION]->(a1)
|
||||
|
||||
CREATE (i2:Issue {name: "网络连不上", category: "网络问题"})
|
||||
CREATE (a2:Action {name: "网络诊断步骤", description: "1. 检查网线是否插好 2. 重启路由器 3. 检查IP配置"})
|
||||
CREATE (i2)-[:HAS_ACTION]->(a2)
|
||||
|
||||
CREATE (i3:Issue {name: "邮箱无法收发", category: "软件问题"})
|
||||
CREATE (a3:Action {name: "邮箱故障排除", description: "1. 检查网络连接 2. 清除浏览器缓存 3. 重新登录邮箱"})
|
||||
CREATE (i3)-[:HAS_ACTION]->(a3)
|
||||
|
||||
CREATE (i4:Issue {name: "VPN连接失败", category: "网络问题"})
|
||||
CREATE (a4:Action {name: "VPN问题排查", description: "1. 检查VPN客户端是否最新 2. 确认账号密码正确 3. 尝试更换VPN服务器"})
|
||||
CREATE (i4)-[:HAS_ACTION]->(a4)
|
||||
|
||||
CREATE (i5:Issue {name: "电脑蓝屏", category: "系统问题"})
|
||||
CREATE (a5:Action {name: "蓝屏解决方案", description: "1. 记录蓝屏错误代码 2. 重启电脑进入安全模式 3. 检查最近安装的软件"})
|
||||
CREATE (i5)-[:HAS_ACTION]->(a5)
|
||||
|
||||
CREATE (i6:Issue {name: "打印机无法连接", category: "硬件问题"})
|
||||
CREATE (a6:Action {name: "打印机连接排查", description: "1. 检查打印机电源 2. 确认网络连接 3. 重新安装打印机驱动"})
|
||||
CREATE (i6)-[:HAS_ACTION]->(a6)
|
||||
|
||||
RETURN "更多测试数据添加完成"
|
||||
@@ -0,0 +1,64 @@
|
||||
# NAS full /volume1/ scan with sudo (English-only)
|
||||
# Step 1: User runs `sudo -v` first (password stays local, never enters Claude)
|
||||
# Step 2: This script reuses that 15-min sudo session
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
$outputFile = "$PSScriptRoot\nas_volumes.txt"
|
||||
|
||||
chcp 65001 | Out-Null
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host " NAS Full Scan (with sudo)" -ForegroundColor Cyan
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "PREREQUISITE: open another terminal and run:" -ForegroundColor Yellow
|
||||
Write-Host " ssh simon@100.85.152.112" -ForegroundColor White
|
||||
Write-Host " sudo -v <- enter simon's password here, password NOT sent to Claude" -ForegroundColor White
|
||||
Write-Host " (keep that SSH session open for 15 min, sudo session cached)" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Read-Host "Press Enter after you have done sudo -v above"
|
||||
|
||||
# Force allocation so sudo can read password from terminal if needed
|
||||
$cmd = @"
|
||||
sudo bash <<'NAS_EOF'
|
||||
echo '===== [1] All top-level entries under /volume1/ ====='
|
||||
ls -la /volume1/ 2>&1
|
||||
echo ''
|
||||
echo '===== [2] Direct children sizes (1-3 minutes) ====='
|
||||
du -sh /volume1/*/ 2>/dev/null | sort -rh
|
||||
echo ''
|
||||
echo '===== [3] Disk space ====='
|
||||
df -h /volume1 2>&1 | head -3
|
||||
echo ''
|
||||
echo '===== [4] /volume1/homes/ ====='
|
||||
ls -la /volume1/homes/ 2>&1 | head -20
|
||||
echo ''
|
||||
echo '===== [5] /volume1/homes/simon/ top dirs by size ====='
|
||||
du -sh /volume1/homes/simon/*/ 2>/dev/null | sort -rh | head -20
|
||||
echo ''
|
||||
echo '===== [6] /volume1/docker/ top dirs by size (likely big) ====='
|
||||
du -sh /volume1/docker/*/ 2>/dev/null | sort -rh | head -20
|
||||
echo ''
|
||||
echo '===== [7] Largest top-level dirs (top 15) ====='
|
||||
du -sh /volume1/* 2>/dev/null | sort -rh | head -15
|
||||
echo ''
|
||||
echo '===== [8] Mounts / storage pools ====='
|
||||
mount | grep -E 'volume|tank' 2>&1 | head -10
|
||||
echo ''
|
||||
echo '===== DONE ====='
|
||||
NAS_EOF
|
||||
"@
|
||||
|
||||
ssh -t simon@100.85.152.112 "$cmd" 2>&1 | Tee-Object -FilePath $outputFile -Encoding UTF8
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host " Done. Output saved to:" -ForegroundColor Green
|
||||
Write-Host " $outputFile" -ForegroundColor White
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "Please paste the ENTIRE contents of nas_volumes.txt back" -ForegroundColor Yellow
|
||||
Write-Host "(or just tell me which top-level dir is largest)" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Read-Host "Press Enter to close"
|
||||
@@ -0,0 +1,43 @@
|
||||
# NAS /volume1/ directory listing scan script
|
||||
# Double-click or run in PowerShell, lists all top-level dirs with sizes
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
$outputFile = "$PSScriptRoot\nas_volumes.txt"
|
||||
|
||||
# Force UTF-8 console encoding for SSH output
|
||||
chcp 65001 | Out-Null
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host " NAS /volume1/ Directory Scan" -ForegroundColor Cyan
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "Scanning... du on large dirs may take 1-3 minutes" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
$cmd = @"
|
||||
echo '===== Top-level dirs in /volume1/ ====='
|
||||
ls -la /volume1/ 2>&1 | grep -v '^total'
|
||||
echo ''
|
||||
echo '===== Size by dir (largest first, may take minutes) ====='
|
||||
du -sh /volume1/*/ 2>/dev/null | sort -rh
|
||||
echo ''
|
||||
echo '===== /volume1/homes/ ====='
|
||||
ls -la /volume1/homes/ 2>/dev/null | head -20
|
||||
echo ''
|
||||
echo '===== /volume1/homes/simon/ content ====='
|
||||
ls -la /volume1/homes/simon/ 2>/dev/null | head -30
|
||||
du -sh /volume1/homes/simon/*/ 2>/dev/null | sort -rh | head -20
|
||||
echo ''
|
||||
echo '===== DONE ====='
|
||||
"@
|
||||
|
||||
ssh simon@100.85.152.112 $cmd 2>&1 | Tee-Object -FilePath $outputFile -Encoding UTF8
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host " Done. Output saved to:" -ForegroundColor Green
|
||||
Write-Host " $outputFile" -ForegroundColor White
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Read-Host "Press Enter to close"
|
||||
@@ -0,0 +1,70 @@
|
||||
# NAS probe script (English-only, prevents PowerShell 5.1 GBK encoding issue)
|
||||
# Output saved to nas_probe_output.txt
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
$outputFile = "$PSScriptRoot\nas_probe_output.txt"
|
||||
|
||||
chcp 65001 | Out-Null
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host " NAS Probe Script" -ForegroundColor Cyan
|
||||
Write-Host "===================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "Connecting via Tailscale: simon@100.85.152.112" -ForegroundColor Yellow
|
||||
Write-Host "Read-only probe, output saved to:" -ForegroundColor Yellow
|
||||
Write-Host " $outputFile" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "SSH will prompt for the simon user password..." -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
$cmd = @"
|
||||
echo '===== [1] DSM Version ====='
|
||||
cat /etc.defaults/VERSION 2>/dev/null | head -10
|
||||
uname -a
|
||||
echo ''
|
||||
echo '===== [2] Docker availability ====='
|
||||
which docker && docker --version
|
||||
ls /var/packages/ContainerManager/target/usr/bin/docker 2>/dev/null
|
||||
/var/packages/ContainerManager/target/usr/bin/docker --version 2>&1
|
||||
echo ''
|
||||
echo '===== [3] All containers (running + stopped) ====='
|
||||
/var/packages/ContainerManager/target/usr/bin/docker ps -a --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}' 2>&1 | head -40
|
||||
echo ''
|
||||
echo '===== [4] /volume1/docker structure ====='
|
||||
ls -la /volume1/docker/ 2>&1 | head -40
|
||||
echo '--- sub-dir sizes ---'
|
||||
du -sh /volume1/docker/*/ 2>/dev/null | head -30
|
||||
echo ''
|
||||
echo '===== [5] Listening ports (22/80/443/3000/3022/18080) ====='
|
||||
ss -tln 2>&1 | head -30
|
||||
echo ''
|
||||
echo '===== [6] Tailscale ====='
|
||||
ls /var/packages/Tailscale/target/bin/ 2>/dev/null
|
||||
/var/packages/Tailscale/target/bin/tailscale status 2>/dev/null | head -10
|
||||
echo ''
|
||||
echo '===== [7] Existing Gitea ====='
|
||||
/var/packages/ContainerManager/target/usr/bin/docker ps -a | grep -i gitea
|
||||
ls -la /volume1/docker/gitea 2>&1 | head -10
|
||||
echo ''
|
||||
echo '===== [8] Disk space ====='
|
||||
df -h /volume1 2>&1 | head -3
|
||||
echo ''
|
||||
echo '===== [9] User and permissions ====='
|
||||
id
|
||||
echo ''
|
||||
echo '===== [10] Installed packages ====='
|
||||
ls /var/packages/ 2>/dev/null | grep -iE 'docker|container|tail|portain'
|
||||
echo ''
|
||||
echo '===== DONE ====='
|
||||
"@
|
||||
|
||||
ssh simon@100.85.152.112 $cmd 2>&1 | Tee-Object -FilePath $outputFile -Encoding UTF8
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host " Done. Output saved to:" -ForegroundColor Green
|
||||
Write-Host " $outputFile" -ForegroundColor White
|
||||
Write-Host "===================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Read-Host "Press Enter to close"
|
||||
@@ -0,0 +1,3 @@
|
||||
SELECT id, created_at, sender_type, content, extra_data
|
||||
FROM messages
|
||||
WHERE id = 'd212b1eb-6fdb-49b9-986e-3023680b4137';
|
||||
@@ -0,0 +1,4 @@
|
||||
MATCH (n:Document)
|
||||
WHERE n.content CONTAINS "余额"
|
||||
RETURN n.title, n.content
|
||||
LIMIT 5;
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE agents SET status = 'offline' WHERE id = 'agent-sxn-001';
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
"""在服务器上执行数据库迁移"""
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
cmd = [
|
||||
"python",
|
||||
"C:\\Users\\simon\\.workbuddy\\skills\\jumpserver-ops\\scripts\\jms_ops.py",
|
||||
"exec",
|
||||
"-c",
|
||||
"cd /opt/wecom-it-desk && docker compose exec -T backend alembic current"
|
||||
]
|
||||
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
print(result.stdout)
|
||||
print(result.stderr)
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE agents SET status = 'offline' WHERE id = 'agent-sxn-001';
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE agents SET status = 'offline' WHERE id = 'agent-sxn-001';
|
||||
@@ -0,0 +1,8 @@
|
||||
$b = [System.IO.File]::ReadAllText('fix-prod.b64').Trim()
|
||||
$n = $b.Length
|
||||
$half = [int]($n / 2)
|
||||
$s1 = $b.Substring(0, $half)
|
||||
$s2 = $b.Substring($half)
|
||||
[System.IO.File]::WriteAllText('fix-prod.s1', $s1)
|
||||
[System.IO.File]::WriteAllText('fix-prod.s2', $s2)
|
||||
Write-Host "Total=$n seg1=$($s1.Length) seg2=$($s2.Length)"
|
||||
@@ -0,0 +1,78 @@
|
||||
cat > /tmp/gitea-stage1.sh <<'NAS_EOF'
|
||||
#!/bin/bash
|
||||
set +e # don't bail on error, collect everything
|
||||
|
||||
DOCKER=/var/packages/ContainerManager/target/usr/bin/docker
|
||||
|
||||
echo '===== [1] Disk space ====='
|
||||
df -h /volume1
|
||||
|
||||
echo ''
|
||||
echo '===== [2] Docker version ====='
|
||||
$DOCKER --version 2>&1
|
||||
$DOCKER info 2>&1 | head -20
|
||||
|
||||
echo ''
|
||||
echo '===== [3] Existing containers (running + stopped) ====='
|
||||
$DOCKER ps -a --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}' 2>&1
|
||||
|
||||
echo ''
|
||||
echo '===== [4] Existing images (gitea-related highlighted) ====='
|
||||
$DOCKER images --format 'table {{.Repository}}\t{{.Tag}}\t{{.Size}}' 2>&1
|
||||
echo '--- gitea images only ---'
|
||||
$DOCKER images 2>&1 | grep -i gitea
|
||||
|
||||
echo ''
|
||||
echo '===== [5] /volume1/docker structure (top-level) ====='
|
||||
ls -la /volume1/docker/ 2>&1 | head -30
|
||||
echo '--- sub-dir sizes (top 20) ---'
|
||||
sudo du -sh /volume1/docker/*/ 2>/dev/null | sort -rh | head -20
|
||||
|
||||
echo ''
|
||||
echo '===== [6] /volume1/docker/gitea exists? ====='
|
||||
ls -la /volume1/docker/gitea 2>&1
|
||||
|
||||
echo ''
|
||||
echo '===== [7] Listening ports (3000/2222 must be free) ====='
|
||||
ss -tln 2>&1 | grep -E ':3000|:2222|:80|:443' || echo '(none of 3000/2222/80/443 in use)'
|
||||
|
||||
echo ''
|
||||
echo '===== [8] Tailscale ====='
|
||||
/var/packages/Tailscale/target/bin/tailscale status 2>&1 | head -10
|
||||
ip -4 addr show tailscale0 2>&1 | grep inet
|
||||
|
||||
echo ''
|
||||
echo '===== [9] Docker daemon registry config ====='
|
||||
cat /var/packages/ContainerManager/etc/docker/daemon.json 2>&1
|
||||
|
||||
echo ''
|
||||
echo '===== [10] Test Docker Hub reachability ====='
|
||||
curl -s -o /dev/null -w 'docker.io: HTTP %{http_code}, time %{time_total}s\n' \
|
||||
--max-time 8 https://registry-1.docker.io/v2/ 2>&1
|
||||
curl -s -o /dev/null -w 'gcr.io: HTTP %{http_code}, time %{time_total}s\n' \
|
||||
--max-time 8 https://gcr.io/v2/ 2>&1
|
||||
curl -s -o /dev/null -w 'tencentyun mirror: HTTP %{http_code}, time %{time_total}s\n' \
|
||||
--max-time 8 https://mirror.ccs.tencentyun.com/v2/ 2>&1
|
||||
|
||||
echo ''
|
||||
echo '===== [11] User & groups (is simon in docker group?) ====='
|
||||
id
|
||||
groups
|
||||
|
||||
echo ''
|
||||
echo '===== [12] CPU / memory ====='
|
||||
free -h
|
||||
nproc
|
||||
|
||||
echo ''
|
||||
echo '===== STAGE 1 DONE ====='
|
||||
NAS_EOF
|
||||
|
||||
chmod +x /tmp/gitea-stage1.sh
|
||||
echo '=== SCRIPT WRITTEN: /tmp/gitea-stage1.sh ==='
|
||||
echo '=== Press ENTER to execute (sudo will prompt for password) ==='
|
||||
read
|
||||
sudo bash /tmp/gitea-stage1.sh 2>&1 | tee /tmp/gitea-stage1.log
|
||||
echo ''
|
||||
echo '=== LOG SAVED: /tmp/gitea-stage1.log ==='
|
||||
echo '=== Paste the entire output above back to Claude ==='
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
docker run -d \
|
||||
--name wecom_it_backend \
|
||||
--network wecom-it-desk_it-desk-internal \
|
||||
-e DATABASE_URL=postgresql://wecom:wecom_secret_2026@postgres:5432/wecom_it_desk \
|
||||
-e REDIS_URL=redis://:R3dIs2026Secure@redis:6379/0 \
|
||||
-e WECOM_CORP_ID=wwa8c87970b2011f41 \
|
||||
-e WECOM_AGENT_ID=1000133 \
|
||||
-e WECOM_SECRET=EOtQslW7WD8Rna8Nm9WnwCW-ozHP3tustL4mFnet6O8 \
|
||||
-e WECOM_TOKEN=wAqMCP \
|
||||
-e WECOM_ENCODING_AES_KEY=KQY3cEsBc3rdi3xua9rPd5WxH8kYOhyASzWZQf75aJS \
|
||||
-e CORS_ORIGINS=https://itsupport.servyou.com.cn,http://itsupport.servyou.com.cn \
|
||||
wecom-it-desk-backend:latest \
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2
|
||||
@@ -0,0 +1,6 @@
|
||||
SELECT id, created_at, message_type, sender_type, content
|
||||
FROM messages
|
||||
WHERE content LIKE '%余额%'
|
||||
AND created_at > NOW() - INTERVAL '7 days'
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 5;
|
||||
@@ -0,0 +1,3 @@
|
||||
import requests
|
||||
r = requests.get('http://127.0.0.1:8000/h5/agents/online-status')
|
||||
print(r.text)
|
||||
@@ -0,0 +1,3 @@
|
||||
import requests
|
||||
r = requests.get('http://127.0.0.1:8000/api/h5/agents/online-status')
|
||||
print(r.text)
|
||||
@@ -0,0 +1,3 @@
|
||||
import requests
|
||||
r = requests.get('http://127.0.0.1:8000/h5/agents/online-status')
|
||||
print(r.text)
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verify WeCom contact sync works after IP whitelist configuration."""
|
||||
import httpx
|
||||
import json
|
||||
|
||||
CORP_ID = "wwa8c87970b2011f41"
|
||||
CONTACT_SECRET = "BM6iosc3gKnPqkEXmsQN3ErJUpfO-whfMUN646eezB8"
|
||||
|
||||
# Step 1: Get contact access token
|
||||
print("=" * 60)
|
||||
print("Step 1: Get contact access token")
|
||||
resp = httpx.get(f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={CORP_ID}&corpsecret={CONTACT_SECRET}", timeout=10)
|
||||
token_data = resp.json()
|
||||
print(f" errcode: {token_data.get('errcode')}")
|
||||
print(f" errmsg: {token_data.get('errmsg')}")
|
||||
|
||||
if 'access_token' not in token_data:
|
||||
print(" FAILED: No access token returned")
|
||||
exit(1)
|
||||
|
||||
token = token_data['access_token']
|
||||
print(f" access_token: {token[:30]}...")
|
||||
|
||||
# Step 2: Get department list
|
||||
print("\n" + "=" * 60)
|
||||
print("Step 2: Get department list")
|
||||
resp2 = httpx.get(f"https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token={token}", timeout=10)
|
||||
dept_data = resp2.json()
|
||||
print(f" errcode: {dept_data.get('errcode')}")
|
||||
print(f" errmsg: {dept_data.get('errmsg')}")
|
||||
departments = dept_data.get('department', [])
|
||||
print(f" department count: {len(departments)}")
|
||||
if departments:
|
||||
print(f" first 5 departments:")
|
||||
for d in departments[:5]:
|
||||
print(f" - id={d.get('id')}, name={d.get('name')}, parentid={d.get('parentid')}")
|
||||
|
||||
# Step 3: Get members of root department (id=1)
|
||||
print("\n" + "=" * 60)
|
||||
print("Step 3: Get members of root department (id=1)")
|
||||
resp3 = httpx.get(f"https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token={token}&department_id=1&fetch_child=1", timeout=15)
|
||||
user_data = resp3.json()
|
||||
print(f" errcode: {user_data.get('errcode')}")
|
||||
print(f" errmsg: {user_data.get('errmsg')}")
|
||||
users = user_data.get('userlist', [])
|
||||
print(f" user count: {len(users)}")
|
||||
if users:
|
||||
print(f" first 3 users:")
|
||||
for u in users[:3]:
|
||||
print(f" - userid={u.get('userid')}, name={u.get('name')}, department={u.get('department')}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("SUMMARY:")
|
||||
print(f" Token: OK")
|
||||
print(f" Departments: {len(departments)}")
|
||||
print(f" Users: {len(users)}")
|
||||
if dept_data.get('errcode') == 0 and len(departments) > 0:
|
||||
print(" RESULT: SUCCESS - Contact sync is working!")
|
||||
else:
|
||||
print(" RESULT: STILL FAILING")
|
||||
@@ -0,0 +1,3 @@
|
||||
MATCH (i:Issue)
|
||||
WHERE i.name CONTAINS '打印机驱动'
|
||||
RETURN i.name
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test the approval detect-intent API endpoint."""
|
||||
import json
|
||||
import httpx
|
||||
|
||||
# Test the API endpoint from inside the container
|
||||
url = "https://localhost/api/approval/detect-intent"
|
||||
|
||||
test_messages = [
|
||||
"我要申请VPN",
|
||||
"我的电脑坏了",
|
||||
"我要申请办公用品",
|
||||
"你好,今天天气怎么样?",
|
||||
]
|
||||
|
||||
for msg in test_messages:
|
||||
print(f"\n=== Testing: {msg} ===")
|
||||
try:
|
||||
resp = httpx.post(
|
||||
url,
|
||||
json={"text": msg},
|
||||
headers={"Content-Type": "application/json"},
|
||||
timeout=30.0,
|
||||
verify=False, # self-signed cert
|
||||
)
|
||||
print(f" HTTP: {resp.status_code}")
|
||||
print(f" Response: {resp.text[:500]}")
|
||||
if resp.status_code == 200:
|
||||
data = resp.json()
|
||||
result = data.get("data", data)
|
||||
print(f" is_approval: {result.get('is_approval_request')}")
|
||||
print(f" confidence: {result.get('confidence')}")
|
||||
print(f" type: {result.get('approval_type')}")
|
||||
print(f" source: {result.get('source')}")
|
||||
except Exception as e:
|
||||
print(f" ERROR: {type(e).__name__}: {e}")
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test detect-intent API from inside backend container (direct FastAPI)."""
|
||||
import json
|
||||
import httpx
|
||||
|
||||
# Backend FastAPI listens on 8000 inside the container
|
||||
url = "http://localhost:8000/api/approval/detect-intent"
|
||||
|
||||
test_messages = [
|
||||
"我要申请VPN",
|
||||
"我的电脑坏了",
|
||||
"我要申请办公用品",
|
||||
"你好,今天天气怎么样?",
|
||||
]
|
||||
|
||||
for msg in test_messages:
|
||||
print(f"\n=== Testing: {msg} ===")
|
||||
try:
|
||||
resp = httpx.post(
|
||||
url,
|
||||
json={"text": msg},
|
||||
timeout=30.0,
|
||||
)
|
||||
print(f" HTTP: {resp.status_code}")
|
||||
print(f" Response: {resp.text[:500]}")
|
||||
if resp.status_code == 200:
|
||||
data = resp.json()
|
||||
result = data.get("data", data)
|
||||
print(f" is_approval: {result.get('is_approval_request')}")
|
||||
print(f" confidence: {result.get('confidence')}")
|
||||
print(f" type: {result.get('approval_type')}")
|
||||
print(f" source: {result.get('source')}")
|
||||
except Exception as e:
|
||||
print(f" ERROR: {type(e).__name__}: {e}")
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test detect-intent API - correct path without /api prefix."""
|
||||
import json
|
||||
import httpx
|
||||
|
||||
# Backend routes are at root level (no /api prefix, nginx adds it)
|
||||
url = "http://localhost:8000/approval/detect-intent"
|
||||
|
||||
test_messages = [
|
||||
"我要申请VPN",
|
||||
"我的电脑坏了",
|
||||
"我要申请办公用品",
|
||||
"你好,今天天气怎么样?",
|
||||
]
|
||||
|
||||
for msg in test_messages:
|
||||
print(f"\n=== Testing: {msg} ===")
|
||||
try:
|
||||
resp = httpx.post(
|
||||
url,
|
||||
json={"text": msg},
|
||||
timeout=30.0,
|
||||
)
|
||||
print(f" HTTP: {resp.status_code}")
|
||||
print(f" Response: {resp.text[:500]}")
|
||||
if resp.status_code == 200:
|
||||
data = resp.json()
|
||||
result = data.get("data", data)
|
||||
print(f" is_approval: {result.get('is_approval_request')}")
|
||||
print(f" confidence: {result.get('confidence')}")
|
||||
print(f" type: {result.get('approval_type')}")
|
||||
print(f" source: {result.get('source')}")
|
||||
except Exception as e:
|
||||
print(f" ERROR: {type(e).__name__}: {e}")
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试 Dify API 连接"""
|
||||
import httpx
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
async def test_dify():
|
||||
url = "http://yw-dify.dc.servyou-it.com/v1/chat-messages"
|
||||
headers = {"Authorization": "Bearer app-7jkRkAzvX4QM9v9SM3P8mMEO"}
|
||||
payload = {
|
||||
"query": "test",
|
||||
"user": "test_user",
|
||||
"response_mode": "blocking"
|
||||
}
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=15) as client:
|
||||
print(f"Testing Dify API: {url}")
|
||||
response = await client.post(url, json=payload, headers=headers)
|
||||
print(f"Status: {response.status_code}")
|
||||
print(f"Response: {response.text[:500]}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(test_dify())
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试 Dify API v1 端点"""
|
||||
import httpx
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
async def test_dify():
|
||||
# Test the base URL
|
||||
async with httpx.AsyncClient(timeout=5) as client:
|
||||
print("=== Test 1: Base URL ===")
|
||||
r = await client.get("http://yw-dify.dc.servyou-it.com/")
|
||||
print(f"Status: {r.status_code}, Location: {r.headers.get('location', 'N/A')}")
|
||||
|
||||
print("\n=== Test 2: API v1/chat-messages ===")
|
||||
url = "http://yw-dify.dc.servyou-it.com/v1/chat-messages"
|
||||
headers = {"Authorization": "Bearer app-7jkRkAzvX4QM9v9SM3P8mMEO"}
|
||||
payload = {
|
||||
"query": "hello",
|
||||
"user": "test",
|
||||
"response_mode": "blocking"
|
||||
}
|
||||
r = await client.post(url, json=payload, headers=headers)
|
||||
print(f"Status: {r.status_code}")
|
||||
print(f"Response: {r.text[:500]}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(test_dify())
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test Dify approval intent detection API directly."""
|
||||
import json
|
||||
import sys
|
||||
import httpx
|
||||
|
||||
BASE_URL = "http://yw-dify.dc.servyou-it.com/dify2openai"
|
||||
API_KEY = "app-JWI7u1LTn9XPVe95KL6dHzPx"
|
||||
|
||||
url = f"{BASE_URL.rstrip('/')}/v1/chat/completions"
|
||||
body = {
|
||||
"model": "dify",
|
||||
"messages": [
|
||||
{"role": "system", "content": "你是IT服务台审批意图识别器。"},
|
||||
{"role": "user", "content": "我要申请VPN"},
|
||||
],
|
||||
"temperature": 0,
|
||||
}
|
||||
headers = {
|
||||
"Authorization": f"Bearer {API_KEY}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
print(f"URL: {url}")
|
||||
print(f"Body: {json.dumps(body, ensure_ascii=False)}")
|
||||
print("---")
|
||||
|
||||
try:
|
||||
resp = httpx.post(url, json=body, headers=headers, timeout=30.0)
|
||||
print(f"HTTP Status: {resp.status_code}")
|
||||
print(f"Response Headers: {dict(resp.headers)}")
|
||||
print(f"Response Body (raw): {resp.text[:2000]}")
|
||||
print("---")
|
||||
|
||||
# Try parsing as JSON
|
||||
try:
|
||||
data = resp.json()
|
||||
print(f"Response JSON: {json.dumps(data, ensure_ascii=False, indent=2)[:2000]}")
|
||||
choices = data.get("choices") or []
|
||||
if choices:
|
||||
content = choices[0].get("message", {}).get("content", "")
|
||||
print(f"Content: {content[:500]}")
|
||||
# Try parsing content as JSON
|
||||
try:
|
||||
parsed = json.loads(content)
|
||||
print(f"Parsed: {json.dumps(parsed, ensure_ascii=False, indent=2)}")
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Content is NOT valid JSON: {e}")
|
||||
else:
|
||||
print("No choices in response")
|
||||
except Exception as e:
|
||||
print(f"Response is not JSON: {e}")
|
||||
except Exception as e:
|
||||
print(f"Request FAILED: {type(e).__name__}: {e}")
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test Dify API with composite API key format."""
|
||||
import json
|
||||
import os
|
||||
import httpx
|
||||
|
||||
# The proxy expects composite format: <dify_base_url>|<api_key>|<app_type>
|
||||
# Main Dify uses: http://yw-dify.dc.servyou-it.com/v1|app-UaTWYdBSwN6VktKQlbh5YN5H|Chat
|
||||
# Approval should use: http://yw-dify.dc.servyou-it.com/v1|app-JWI7u1LTn9XPVe95KL6dHzPx|Chat
|
||||
|
||||
PROXY_URL = "http://yw-dify.dc.servyou-it.com/dify2openai/v1/chat/completions"
|
||||
APPROVAL_KEY_RAW = "app-JWI7u1LTn9XPVe95KL6dHzPx"
|
||||
APPROVAL_KEY_COMPOSITE = "http://yw-dify.dc.servyou-it.com/v1|app-JWI7u1LTn9XPVe95KL6dHzPx|Chat"
|
||||
|
||||
body = {
|
||||
"model": "dify",
|
||||
"messages": [
|
||||
{"role": "user", "content": "我要申请VPN"},
|
||||
],
|
||||
"temperature": 0,
|
||||
}
|
||||
|
||||
# Test 1: Raw API key (current, failing)
|
||||
print("=== Test 1: Raw API key (current) ===")
|
||||
headers = {"Authorization": f"Bearer {APPROVAL_KEY_RAW}", "Content-Type": "application/json"}
|
||||
try:
|
||||
resp = httpx.post(PROXY_URL, json=body, headers=headers, timeout=15.0)
|
||||
print(f" HTTP: {resp.status_code}")
|
||||
print(f" Body: {resp.text[:300]}")
|
||||
except Exception as e:
|
||||
print(f" ERROR: {e}")
|
||||
|
||||
# Test 2: Composite API key
|
||||
print("\n=== Test 2: Composite API key ===")
|
||||
headers = {"Authorization": f"Bearer {APPROVAL_KEY_COMPOSITE}", "Content-Type": "application/json"}
|
||||
try:
|
||||
resp = httpx.post(PROXY_URL, json=body, headers=headers, timeout=30.0)
|
||||
print(f" HTTP: {resp.status_code}")
|
||||
print(f" Body: {resp.text[:500]}")
|
||||
if resp.status_code == 200:
|
||||
data = resp.json()
|
||||
choices = data.get("choices") or []
|
||||
if choices:
|
||||
content = choices[0].get("message", {}).get("content", "")
|
||||
print(f" Content: {content[:300]}")
|
||||
try:
|
||||
parsed = json.loads(content)
|
||||
print(f" Parsed JSON: {json.dumps(parsed, ensure_ascii=False, indent=2)}")
|
||||
except:
|
||||
print(f" Content is not JSON")
|
||||
except Exception as e:
|
||||
print(f" ERROR: {e}")
|
||||
|
||||
# Test 3: Check main Dify key format
|
||||
print("\n=== Test 3: Main Dify env vars ===")
|
||||
print(f" DIFY_API_KEY = {os.environ.get('DIFY_API_KEY', 'NOT SET')}")
|
||||
print(f" DIFY_API_URL = {os.environ.get('DIFY_API_URL', 'NOT SET')}")
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试 Dify DNS 解析"""
|
||||
import socket
|
||||
|
||||
host = "yw-dify.dc.servyou-it.com"
|
||||
try:
|
||||
ip = socket.gethostbyname(host)
|
||||
print(f"{host} -> {ip}")
|
||||
except Exception as e:
|
||||
print(f"DNS lookup failed: {e}")
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试容器能否访问 Dify"""
|
||||
import httpx
|
||||
import socket
|
||||
|
||||
# 测试 DNS 解析
|
||||
try:
|
||||
ip = socket.gethostbyname('yw-dify.dc.servyou-it.com')
|
||||
print(f"DNS resolved: yw-dify.dc.servyou-it.com -> {ip}")
|
||||
except Exception as e:
|
||||
print(f"DNS failed: {e}")
|
||||
|
||||
# 测试 HTTP 连接
|
||||
async def test_dify():
|
||||
async with httpx.AsyncClient(timeout=10) as client:
|
||||
# 测试根路径
|
||||
try:
|
||||
r = await client.get('http://yw-dify.dc.servyou-it.com/')
|
||||
print(f"GET / -> {r.status_code}")
|
||||
except Exception as e:
|
||||
print(f"GET / failed: {type(e).__name__}: {e}")
|
||||
|
||||
# 测试 API 端点
|
||||
try:
|
||||
r = await client.post(
|
||||
'http://yw-dify.dc.servyou-it.com/v1/chat-messages',
|
||||
json={"inputs": {}, "query": "test", "response_mode": "blocking", "user": "test"}
|
||||
)
|
||||
print(f"POST /v1/chat-messages -> {r.status_code}")
|
||||
except Exception as e:
|
||||
print(f"POST /v1/chat-messages failed: {type(e).__name__}: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import asyncio
|
||||
asyncio.run(test_dify())
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试内部网络 Dify 服务"""
|
||||
import httpx
|
||||
import asyncio
|
||||
|
||||
async def test_internal():
|
||||
async with httpx.AsyncClient(timeout=10) as client:
|
||||
# 测试 RAGFlow (有 Dify API)
|
||||
print("=== RAGFlow 8080 (Dify API) ===")
|
||||
try:
|
||||
r = await client.post(
|
||||
"http://10.80.0.85:8080/v1/chat-messages",
|
||||
json={"query": "hello", "user": "test"},
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
print(f"Status: {r.status_code}")
|
||||
print(f"Response: {r.text[:200]}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
print()
|
||||
|
||||
# 测试内部 Dify 服务 (尝试常见内网地址)
|
||||
print("=== Try Internal Dify Services ===")
|
||||
candidates = [
|
||||
"http://10.80.0.85:8081",
|
||||
"http://10.80.0.86:8080",
|
||||
"http://dify:8080",
|
||||
"http://dify:80",
|
||||
]
|
||||
for url in candidates:
|
||||
try:
|
||||
r = await client.get(url)
|
||||
print(f"{url}: {r.status_code}")
|
||||
except Exception as e:
|
||||
print(f"{url}: FAIL - {type(e).__name__}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(test_internal())
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试 Dify 直接通过 IP 访问"""
|
||||
import httpx
|
||||
import asyncio
|
||||
|
||||
async def test_by_ip():
|
||||
async with httpx.AsyncClient(timeout=30) as client:
|
||||
# 直接通过 IP 访问
|
||||
print("=== Direct IP: 10.80.0.240 ===")
|
||||
try:
|
||||
r = await client.post(
|
||||
"http://10.80.0.240/v1/chat-messages",
|
||||
json={"query": "hello", "user": "test"},
|
||||
headers={
|
||||
"Authorization": "Bearer app-7jkRkAzvX4QM9v9SM3P8mMEO",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
)
|
||||
print(f"Status: {r.status_code}")
|
||||
print(f"Response: {r.text[:300]}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(test_by_ip())
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test multiple Dify API keys to find a working one"""
|
||||
import httpx
|
||||
import json
|
||||
import time
|
||||
|
||||
base_url = "http://yw-dify.dc.servyou-it.com"
|
||||
|
||||
# Test multiple API keys
|
||||
api_keys = [
|
||||
("app-7jkRkAzvX4QM9v9SM3P8mMEO", "审批意图副本"),
|
||||
("app-J3s8sHarZQ2SCaNF3xCppliL", "自建应用"),
|
||||
("app-z3S9AEUUAVPbtR2rioxpiIvp", "分诊应用"),
|
||||
]
|
||||
|
||||
for api_key, name in api_keys:
|
||||
url = f"{base_url}/v1/chat-messages"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
payload = {
|
||||
"inputs": {},
|
||||
"query": "密码忘记了怎么办",
|
||||
"response_mode": "blocking",
|
||||
"user": "test_verify"
|
||||
}
|
||||
|
||||
print(f"=== Testing: {name} ({api_key[:20]}...) ===")
|
||||
start = time.time()
|
||||
try:
|
||||
with httpx.Client(timeout=httpx.Timeout(30.0)) as client:
|
||||
resp = client.post(url, headers=headers, json=payload)
|
||||
elapsed = (time.time() - start) * 1000
|
||||
print(f"Status: {resp.status_code}, Time: {elapsed:.0f}ms")
|
||||
|
||||
if resp.status_code == 200:
|
||||
data = resp.json()
|
||||
answer = data.get('answer', '')
|
||||
print(f"conversation_id: {data.get('conversation_id', 'N/A')}")
|
||||
print(f"answer (first 300 chars): {answer[:300]}")
|
||||
|
||||
# Try JSON parse
|
||||
try:
|
||||
parsed = json.loads(answer)
|
||||
print(f"JSON Parse: SUCCESS - keys: {list(parsed.keys())}")
|
||||
except:
|
||||
print(f"JSON Parse: FAILED (plain text)")
|
||||
else:
|
||||
print(f"Error: {resp.text[:300]}")
|
||||
except Exception as e:
|
||||
print(f"Exception: {type(e).__name__}: {e}")
|
||||
|
||||
print()
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test Dify API with different model parameter formats."""
|
||||
import json
|
||||
import httpx
|
||||
|
||||
BASE_URL = "http://yw-dify.dc.servyou-it.com/dify2openai"
|
||||
API_KEY = "app-JWI7u1LTn9XPVe95KL6dHzPx"
|
||||
url = f"{BASE_URL.rstrip('/')}/v1/chat/completions"
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {API_KEY}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
# Test different model parameter formats
|
||||
test_models = [
|
||||
"dify",
|
||||
"", # empty string
|
||||
"gpt-3.5-turbo",
|
||||
"deepseek-chat",
|
||||
"default",
|
||||
]
|
||||
|
||||
for model in test_models:
|
||||
body = {
|
||||
"model": model,
|
||||
"messages": [
|
||||
{"role": "user", "content": "我要申请VPN"},
|
||||
],
|
||||
"temperature": 0,
|
||||
}
|
||||
print(f"\n=== model={repr(model)} ===")
|
||||
try:
|
||||
resp = httpx.post(url, json=body, headers=headers, timeout=15.0)
|
||||
print(f" HTTP Status: {resp.status_code}")
|
||||
body_text = resp.text[:500]
|
||||
print(f" Response: {body_text}")
|
||||
except Exception as e:
|
||||
print(f" ERROR: {type(e).__name__}: {e}")
|
||||
|
||||
# Also test without model parameter at all
|
||||
print(f"\n=== No model parameter ===")
|
||||
body = {
|
||||
"messages": [
|
||||
{"role": "user", "content": "我要申请VPN"},
|
||||
],
|
||||
"temperature": 0,
|
||||
}
|
||||
try:
|
||||
resp = httpx.post(url, json=body, headers=headers, timeout=15.0)
|
||||
print(f" HTTP Status: {resp.status_code}")
|
||||
print(f" Response: {resp.text[:500]}")
|
||||
except Exception as e:
|
||||
print(f" ERROR: {type(e).__name__}: {e}")
|
||||
|
||||
# Test with the main AI chat API key to compare
|
||||
# First, check what API key the main Dify uses
|
||||
print(f"\n=== Check main Dify config ===")
|
||||
import os
|
||||
main_key = os.environ.get("DIFY_API_KEY", "")
|
||||
main_base = os.environ.get("DIFY_BASE_URL", "")
|
||||
print(f" DIFY_API_KEY: {main_key[:20]}..." if main_key else " DIFY_API_KEY: not set")
|
||||
print(f" DIFY_BASE_URL: {main_base}")
|
||||
|
||||
if main_key:
|
||||
main_url = f"{main_base.rstrip('/')}/v1/chat/completions" if main_base else url
|
||||
main_headers = {"Authorization": f"Bearer {main_key}", "Content-Type": "application/json"}
|
||||
body = {
|
||||
"model": "dify",
|
||||
"messages": [{"role": "user", "content": "你好"}],
|
||||
"temperature": 0,
|
||||
}
|
||||
print(f"\n=== Test main Dify API with model='dify' ===")
|
||||
try:
|
||||
resp = httpx.post(main_url, json=body, headers=main_headers, timeout=15.0)
|
||||
print(f" HTTP Status: {resp.status_code}")
|
||||
print(f" Response: {resp.text[:500]}")
|
||||
except Exception as e:
|
||||
print(f" ERROR: {type(e).__name__}: {e}")
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试 Dify 原生 API 和 dify2openai 代理"""
|
||||
import httpx
|
||||
import asyncio
|
||||
|
||||
async def test_dify():
|
||||
async with httpx.AsyncClient(timeout=30) as client:
|
||||
# 1. 测试原生 API 路径
|
||||
print("=== Test 1: Dify Native API (v1/chat-messages) ===")
|
||||
url1 = "http://yw-dify.dc.servyou-it.com/v1/chat-messages"
|
||||
headers1 = {
|
||||
"Authorization": "Bearer app-7jkRkAzvX4QM9v9SM3P8mMEO",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
payload1 = {
|
||||
"inputs": {"user_query": "hello"},
|
||||
"query": "hello",
|
||||
"response_mode": "blocking",
|
||||
"user": "test-user-001"
|
||||
}
|
||||
try:
|
||||
r1 = await client.post(url1, json=payload1, headers=headers1)
|
||||
print(f"Status: {r1.status_code}")
|
||||
print(f"Response: {r1.text[:300]}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
print()
|
||||
|
||||
# 2. 测试 dify2openai 代理路径
|
||||
print("=== Test 2: dify2openai Proxy ===")
|
||||
url2 = "http://yw-dify.dc.servyou-it.com/dify2openai/v1/chat/completions"
|
||||
headers2 = {
|
||||
"Authorization": "Bearer http://yw-dify.dc.servyou-it.com/v1|app-7jkRkAzvX4QM9v9SM3P8mMEO|Chat",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
payload2 = {
|
||||
"model": "Chat",
|
||||
"messages": [{"role": "user", "content": "hello"}],
|
||||
"stream": False
|
||||
}
|
||||
try:
|
||||
r2 = await client.post(url2, json=payload2, headers=headers2)
|
||||
print(f"Status: {r2.status_code}")
|
||||
print(f"Response: {r2.text[:300]}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
print()
|
||||
|
||||
# 3. 测试 Dify 健康检查
|
||||
print("=== Test 3: Dify Health Check ===")
|
||||
try:
|
||||
r3 = await client.get("http://yw-dify.dc.servyou-it.com/")
|
||||
print(f"Status: {r3.status_code}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(test_dify())
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试 Dify 多个端口"""
|
||||
import httpx
|
||||
import asyncio
|
||||
|
||||
async def test_ports():
|
||||
async with httpx.AsyncClient(timeout=10) as client:
|
||||
ports = [80, 8080, 3000, 5000]
|
||||
for port in ports:
|
||||
url = f"http://10.80.0.240:{port}/"
|
||||
try:
|
||||
r = await client.get(url)
|
||||
print(f"Port {port}: {r.status_code}")
|
||||
except Exception as e:
|
||||
print(f"Port {port}: FAIL - {type(e).__name__}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(test_ports())
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
"""测试 Dify dify2openai 代理"""
|
||||
import httpx
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
async def test_dify_proxy():
|
||||
# Test the dify2openai proxy path
|
||||
async with httpx.AsyncClient(timeout=15) as client:
|
||||
print("=== Test dify2openai proxy ===")
|
||||
url = "http://yw-dify.dc.servyou-it.com/dify2openai/v1/chat/completions"
|
||||
headers = {
|
||||
"Authorization": "Bearer http://yw-dify.dc.servyou-it.com/v1|app-7jkRkAzvX4QM9v9SM3P8mMEO|Chat",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
payload = {
|
||||
"model": "Chat",
|
||||
"messages": [{"role": "user", "content": "hello"}],
|
||||
"stream": False
|
||||
}
|
||||
r = await client.post(url, json=payload, headers=headers)
|
||||
print(f"Status: {r.status_code}")
|
||||
print(f"Response: {r.text[:500]}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(test_dify_proxy())
|
||||
@@ -0,0 +1,25 @@
|
||||
import asyncio
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
async def test():
|
||||
from app.services.graph_query_service import get_graph_query_service
|
||||
from app.services.neo4j_client import get_neo4j_client
|
||||
|
||||
neo4j_client = await get_neo4j_client()
|
||||
graph_service = await get_graph_query_service(neo4j_client)
|
||||
|
||||
keyword = "打印机驱动安装"
|
||||
print(f"Testing find_issues_by_keyword for: {keyword}")
|
||||
|
||||
try:
|
||||
issues = await neo4j_client.find_issues_by_keyword(keyword, limit=5)
|
||||
print(f"Issues found: {len(issues)}")
|
||||
for issue in issues:
|
||||
print(f" - uuid: {issue.uuid}, name: {issue.name}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
asyncio.run(test())
|
||||
@@ -0,0 +1,48 @@
|
||||
import asyncio
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
async def test():
|
||||
from app.services.graph_query_service import get_graph_query_service
|
||||
from app.services.neo4j_client import get_neo4j_client
|
||||
|
||||
neo4j_client = await get_neo4j_client()
|
||||
graph_service = await get_graph_query_service(neo4j_client)
|
||||
|
||||
keyword = "打印机驱动安装"
|
||||
print(f"=== Full test for keyword: {keyword} ===")
|
||||
|
||||
# Step 1: find_issues_by_keyword
|
||||
issues = await neo4j_client.find_issues_by_keyword(keyword, limit=5)
|
||||
print(f"1. find_issues_by_keyword: {len(issues)} issues")
|
||||
if not issues:
|
||||
print("No issues found!")
|
||||
return
|
||||
|
||||
issue = issues[0]
|
||||
print(f" Issue: uuid={issue.uuid}, name={issue.name}")
|
||||
|
||||
# Step 2: find_actions_by_issue
|
||||
print(f"2. Calling find_actions_by_issue with uuid={issue.uuid}")
|
||||
actions = await neo4j_client.find_actions_by_issue(issue.uuid)
|
||||
print(f" find_actions_by_issue: {len(actions)} actions")
|
||||
|
||||
if not actions:
|
||||
print("No actions found!")
|
||||
return
|
||||
|
||||
action = actions[0]
|
||||
print(f" Action: name={action.name}, description={action.description[:30]}...")
|
||||
|
||||
# Step 3: Build result
|
||||
from app.services.graph_query_service import SolutionResult
|
||||
result = SolutionResult(
|
||||
issue_name=issue.name,
|
||||
issue_uuid=issue.uuid,
|
||||
solution=action.description or action.name,
|
||||
action_name=action.name,
|
||||
confidence=0.8
|
||||
)
|
||||
print(f"3. SolutionResult: {result}")
|
||||
|
||||
asyncio.run(test())
|
||||
@@ -0,0 +1,29 @@
|
||||
import asyncio
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
async def test():
|
||||
from app.services.graph_query_service import get_graph_query_service
|
||||
from app.services.neo4j_client import get_neo4j_client
|
||||
|
||||
neo4j_client = await get_neo4j_client()
|
||||
print(f'Neo4j client: {neo4j_client}')
|
||||
|
||||
if neo4j_client:
|
||||
graph_service = await get_graph_query_service(neo4j_client)
|
||||
print(f'Graph service: {graph_service}')
|
||||
|
||||
# 测试查询
|
||||
question = "打印机驱动安装"
|
||||
print(f'Querying: {question}')
|
||||
result = await graph_service.find_solution_by_question(question)
|
||||
print(f'Result: {result}')
|
||||
|
||||
if result:
|
||||
print(f"图谱命中! action_name={result.action_name}, solution={result.solution[:50]}")
|
||||
else:
|
||||
print("图谱未命中")
|
||||
else:
|
||||
print('Neo4j client is None')
|
||||
|
||||
asyncio.run(test())
|
||||
@@ -0,0 +1,9 @@
|
||||
import sys
|
||||
sys.path.insert(0, 'backend')
|
||||
from app.services.asset_recommend_service import AssetRecommendService
|
||||
|
||||
svc = AssetRecommendService()
|
||||
cards = svc.match_keywords('VPN连不上怎么办')
|
||||
print(f'Found {len(cards)} cards')
|
||||
for c in cards:
|
||||
print(f' - {c.title}: {c.description}')
|
||||
@@ -0,0 +1,9 @@
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
from app.services.asset_recommend_service import AssetRecommendService
|
||||
|
||||
svc = AssetRecommendService()
|
||||
cards = svc.match_keywords('VPN连不上怎么办')
|
||||
print(f'Found {len(cards)} cards')
|
||||
for c in cards:
|
||||
print(f' - {c.title}: {c.description}')
|
||||
@@ -0,0 +1,16 @@
|
||||
import asyncio
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
from app.services.neo4j_client import get_neo4j_client
|
||||
|
||||
async def test():
|
||||
client = await get_neo4j_client()
|
||||
print(f'Neo4j client: {client}')
|
||||
if client:
|
||||
healthy = await client.health_check()
|
||||
print(f'Health check: {healthy}')
|
||||
else:
|
||||
print('Neo4j client is None')
|
||||
|
||||
asyncio.run(test())
|
||||
@@ -0,0 +1,18 @@
|
||||
import asyncio
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
|
||||
async def test():
|
||||
from app.services.neo4j_client import get_neo4j_client
|
||||
client = await get_neo4j_client()
|
||||
print(f'Neo4j client: {client}')
|
||||
if client:
|
||||
try:
|
||||
healthy = await client.health_check()
|
||||
print(f'Health check: {healthy}')
|
||||
except Exception as e:
|
||||
print(f'Health check error: {e}')
|
||||
else:
|
||||
print('Neo4j client is None - connection failed')
|
||||
|
||||
asyncio.run(test())
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test old Dify key - show full response"""
|
||||
import httpx
|
||||
import json
|
||||
import time
|
||||
|
||||
base_url = "http://yw-dify.dc.servyou-it.com"
|
||||
api_key = "app-UaTWYdBSwN6VktKQlbh5YN5H"
|
||||
|
||||
url = f"{base_url}/v1/chat-messages"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
payload = {
|
||||
"inputs": {},
|
||||
"query": "密码忘记了怎么办",
|
||||
"response_mode": "blocking",
|
||||
"user": "test_verify"
|
||||
}
|
||||
|
||||
print(f"=== Testing old key with full response ===")
|
||||
start = time.time()
|
||||
try:
|
||||
with httpx.Client(timeout=httpx.Timeout(30.0)) as client:
|
||||
resp = client.post(url, headers=headers, json=payload)
|
||||
elapsed = (time.time() - start) * 1000
|
||||
print(f"Status: {resp.status_code}, Time: {elapsed:.0f}ms")
|
||||
print()
|
||||
|
||||
data = resp.json()
|
||||
print(f"conversation_id: {data.get('conversation_id', 'N/A')}")
|
||||
answer = data.get('answer', '')
|
||||
print(f"answer (first 800 chars):")
|
||||
print(answer[:800])
|
||||
print()
|
||||
|
||||
# Try JSON parse
|
||||
try:
|
||||
parsed = json.loads(answer)
|
||||
print("=== JSON Parse: SUCCESS ===")
|
||||
print(f"Keys: {list(parsed.keys())}")
|
||||
for k, v in parsed.items():
|
||||
print(f" {k}: {str(v)[:200]}")
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"=== JSON Parse: FAILED ===")
|
||||
print(f"Error: {e}")
|
||||
print("Answer is plain text, not JSON")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Exception: {type(e).__name__}: {e}")
|
||||
@@ -0,0 +1,2 @@
|
||||
UPDATE agents SET mfa_enabled = true, mfa_secret = 'JBSWY3DPEHPK3PXP' WHERE user_id = 'sxn';
|
||||
SELECT user_id, mfa_enabled, mfa_secret FROM agents WHERE user_id = 'sxn';
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE agents SET mfa_enabled = true, mfa_secret = 'JBSWY3DPEHPK3PXP' WHERE user_id = 'sxn'
|
||||
@@ -0,0 +1 @@
|
||||
UPDATE agents SET status = 'offline';
|
||||
Reference in New Issue
Block a user