chore: rm python env
Browse files- .python-version +0 -1
- log.md +0 -0
- tests/diagnose_fetch.ts +0 -27
- tests/diagnose_post.ts +0 -37
- tests/diagnose_websearch.ts +0 -106
- tests/test_jina.ts +0 -0
- tests/test_python_webtools.py +0 -110
- tests/test_websearch_format.ts +0 -101
- tests/test_webtools_integration.ts +0 -147
- tests/websearch_test.ts +0 -83
.python-version
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
3.12
|
|
|
|
|
|
log.md
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tests/diagnose_fetch.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env bun
|
| 2 |
-
console.log('Testing standard fetch...')
|
| 3 |
-
|
| 4 |
-
try {
|
| 5 |
-
const response = await fetch('https://html.duckduckgo.com/html/?q=test&b=&l=us-en', {
|
| 6 |
-
headers: {
|
| 7 |
-
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
| 8 |
-
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
|
| 9 |
-
'Accept-Language': 'en-US,en;q=0.9',
|
| 10 |
-
'Connection': 'keep-alive',
|
| 11 |
-
},
|
| 12 |
-
})
|
| 13 |
-
|
| 14 |
-
console.log(`✓ Response status: ${response.status}`)
|
| 15 |
-
|
| 16 |
-
const html = await response.text()
|
| 17 |
-
console.log(`✓ Response length: ${html.length} bytes`)
|
| 18 |
-
|
| 19 |
-
if (html.length > 10000) {
|
| 20 |
-
console.log('\n✅ Standard fetch works!')
|
| 21 |
-
} else {
|
| 22 |
-
console.log('\n⚠️ Response too short')
|
| 23 |
-
}
|
| 24 |
-
} catch (error) {
|
| 25 |
-
console.error('❌ Test failed:', error)
|
| 26 |
-
process.exit(1)
|
| 27 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/diagnose_post.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env bun
|
| 2 |
-
import { initTLS, Session, ClientIdentifier, destroyTLS } from 'node-tls-client'
|
| 3 |
-
|
| 4 |
-
console.log('Testing POST request with node-tls-client...')
|
| 5 |
-
|
| 6 |
-
try {
|
| 7 |
-
await initTLS()
|
| 8 |
-
console.log('✓ TLS initialized')
|
| 9 |
-
|
| 10 |
-
const session = new Session({
|
| 11 |
-
clientIdentifier: ClientIdentifier.chrome_131,
|
| 12 |
-
timeout: 30000,
|
| 13 |
-
})
|
| 14 |
-
console.log('✓ Session created')
|
| 15 |
-
|
| 16 |
-
const response = await session.post('https://html.duckduckgo.com/html/', {
|
| 17 |
-
body: 'q=test&b=&l=us-en',
|
| 18 |
-
})
|
| 19 |
-
|
| 20 |
-
console.log(`✓ Request completed: ${response.status}`)
|
| 21 |
-
|
| 22 |
-
const html = await response.text()
|
| 23 |
-
console.log(`✓ Received ${html.length} bytes`)
|
| 24 |
-
|
| 25 |
-
if (html.length > 10000) {
|
| 26 |
-
console.log('\n✅ POST request works!')
|
| 27 |
-
} else {
|
| 28 |
-
console.log('\n⚠️ Response too short')
|
| 29 |
-
}
|
| 30 |
-
|
| 31 |
-
await session.close()
|
| 32 |
-
await destroyTLS()
|
| 33 |
-
console.log('\n✓ Cleanup completed')
|
| 34 |
-
} catch (error) {
|
| 35 |
-
console.error('❌ Test failed:', error)
|
| 36 |
-
process.exit(1)
|
| 37 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/diagnose_websearch.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env bun
|
| 2 |
-
/**
|
| 3 |
-
* WebSearch 诊断测试
|
| 4 |
-
* 检查各个组件是否正常工作
|
| 5 |
-
*/
|
| 6 |
-
|
| 7 |
-
console.log('='.repeat(60))
|
| 8 |
-
console.log('WebSearch Diagnostic Test')
|
| 9 |
-
console.log('='.repeat(60))
|
| 10 |
-
|
| 11 |
-
async function test1_ImportModule() {
|
| 12 |
-
console.log('\n1. 测试导入 node-tls-client...')
|
| 13 |
-
try {
|
| 14 |
-
const module = await import('node-tls-client')
|
| 15 |
-
console.log('✓ 模块导入成功')
|
| 16 |
-
console.log(' 可用函数:', Object.keys(module))
|
| 17 |
-
return module
|
| 18 |
-
} catch (error) {
|
| 19 |
-
console.error('✗ 模块导入失败:', error)
|
| 20 |
-
throw error
|
| 21 |
-
}
|
| 22 |
-
}
|
| 23 |
-
|
| 24 |
-
async function test2_InitTLS(module) {
|
| 25 |
-
console.log('\n2. 测试初始化 TLS...')
|
| 26 |
-
try {
|
| 27 |
-
await module.initTLS()
|
| 28 |
-
console.log('✓ TLS 初始化成功')
|
| 29 |
-
} catch (error) {
|
| 30 |
-
console.error('✗ TLS 初始化失败:', error)
|
| 31 |
-
throw error
|
| 32 |
-
}
|
| 33 |
-
}
|
| 34 |
-
|
| 35 |
-
async function test3_CreateSession(module) {
|
| 36 |
-
console.log('\n3. 测试创建 Session...')
|
| 37 |
-
try {
|
| 38 |
-
const session = new module.Session({
|
| 39 |
-
clientIdentifier: module.ClientIdentifier.chrome_131,
|
| 40 |
-
timeout: 10000,
|
| 41 |
-
})
|
| 42 |
-
console.log('✓ Session 创建成功')
|
| 43 |
-
await session.close()
|
| 44 |
-
console.log('✓ Session 关闭成功')
|
| 45 |
-
} catch (error) {
|
| 46 |
-
console.error('✗ Session 创建失败:', error)
|
| 47 |
-
throw error
|
| 48 |
-
}
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
async function test4_MakeRequest(module) {
|
| 52 |
-
console.log('\n4. 测试发送请求...')
|
| 53 |
-
try {
|
| 54 |
-
const session = new module.Session({
|
| 55 |
-
clientIdentifier: module.ClientIdentifier.chrome_131,
|
| 56 |
-
timeout: 10000,
|
| 57 |
-
})
|
| 58 |
-
|
| 59 |
-
const response = await session.get('https://html.duckduckgo.com/html/?q=test', {
|
| 60 |
-
followRedirects: true,
|
| 61 |
-
})
|
| 62 |
-
|
| 63 |
-
console.log(`✓ 请求成功: ${response.status}`)
|
| 64 |
-
|
| 65 |
-
const html = await response.text()
|
| 66 |
-
console.log(`✓ 响应长度: ${html.length} bytes`)
|
| 67 |
-
|
| 68 |
-
if (html.length > 10000) {
|
| 69 |
-
console.log('✓ 响应长度正常')
|
| 70 |
-
} else {
|
| 71 |
-
console.warn('⚠️ 响应长度异常 (可能被阻塞)')
|
| 72 |
-
}
|
| 73 |
-
|
| 74 |
-
await session.close()
|
| 75 |
-
} catch (error) {
|
| 76 |
-
console.error('✗ 请求失败:', error)
|
| 77 |
-
throw error
|
| 78 |
-
}
|
| 79 |
-
}
|
| 80 |
-
|
| 81 |
-
async function main() {
|
| 82 |
-
let module = null
|
| 83 |
-
|
| 84 |
-
try {
|
| 85 |
-
module = await test1_ImportModule()
|
| 86 |
-
await test2_InitTLS(module)
|
| 87 |
-
await test3_CreateSession(module)
|
| 88 |
-
await test4_MakeRequest(module)
|
| 89 |
-
|
| 90 |
-
// 清理
|
| 91 |
-
console.log('\n5. 清理 TLS...')
|
| 92 |
-
await module.destroyTLS()
|
| 93 |
-
console.log('✓ TLS 清理成功')
|
| 94 |
-
|
| 95 |
-
console.log('\n' + '='.repeat(60))
|
| 96 |
-
console.log('✅ 所有测试通过!')
|
| 97 |
-
console.log('='.repeat(60))
|
| 98 |
-
} catch (error) {
|
| 99 |
-
console.log('\n' + '='.repeat(60))
|
| 100 |
-
console.log('❌ 测试失败')
|
| 101 |
-
console.log('='.repeat(60))
|
| 102 |
-
process.exit(1)
|
| 103 |
-
}
|
| 104 |
-
}
|
| 105 |
-
|
| 106 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/test_jina.ts
ADDED
|
File without changes
|
tests/test_python_webtools.py
DELETED
|
@@ -1,110 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python3
|
| 2 |
-
"""Test Python webtools interface"""
|
| 3 |
-
|
| 4 |
-
import sys
|
| 5 |
-
import json
|
| 6 |
-
|
| 7 |
-
# Test 1: Test import
|
| 8 |
-
print("Test 1: Testing imports...")
|
| 9 |
-
try:
|
| 10 |
-
sys.path.insert(0, 'scripts')
|
| 11 |
-
import python_webtools
|
| 12 |
-
_validate_url = python_webtools._validate_url
|
| 13 |
-
print("✓ Imports successful")
|
| 14 |
-
except ImportError as e:
|
| 15 |
-
print(f"✗ Import failed: {e}")
|
| 16 |
-
sys.exit(1)
|
| 17 |
-
|
| 18 |
-
# Test 2: Test URL validation
|
| 19 |
-
print("\nTest 2: Testing URL validation...")
|
| 20 |
-
valid_urls = [
|
| 21 |
-
"https://example.com",
|
| 22 |
-
"http://example.com",
|
| 23 |
-
"https://www.example.com/path"
|
| 24 |
-
]
|
| 25 |
-
|
| 26 |
-
invalid_urls = [
|
| 27 |
-
"ftp://example.com",
|
| 28 |
-
"file:///etc/passwd",
|
| 29 |
-
"not-a-url",
|
| 30 |
-
""
|
| 31 |
-
]
|
| 32 |
-
|
| 33 |
-
for url in valid_urls:
|
| 34 |
-
is_valid, error = _validate_url(url)
|
| 35 |
-
if is_valid:
|
| 36 |
-
print(f" ✓ Valid: {url}")
|
| 37 |
-
else:
|
| 38 |
-
print(f" ✗ Should be valid but got: {error}")
|
| 39 |
-
|
| 40 |
-
for url in invalid_urls:
|
| 41 |
-
is_valid, error = _validate_url(url)
|
| 42 |
-
if not is_valid:
|
| 43 |
-
print(f" ✓ Invalid (as expected): {url}")
|
| 44 |
-
else:
|
| 45 |
-
print(f" ✗ Should be invalid but passed: {url}")
|
| 46 |
-
|
| 47 |
-
# Test 3: Test script interface
|
| 48 |
-
print("\nTest 3: Testing script interface (via subprocess)...")
|
| 49 |
-
import subprocess
|
| 50 |
-
|
| 51 |
-
# Test with invalid command
|
| 52 |
-
result = subprocess.run(
|
| 53 |
-
[sys.executable, "scripts/python_webtools.py", "invalid_command"],
|
| 54 |
-
capture_output=True,
|
| 55 |
-
text=True,
|
| 56 |
-
timeout=5
|
| 57 |
-
)
|
| 58 |
-
if result.returncode != 0:
|
| 59 |
-
try:
|
| 60 |
-
data = json.loads(result.stdout)
|
| 61 |
-
if data.get("success") == False:
|
| 62 |
-
print(f" ✓ Invalid command correctly rejected: {data.get('error')}")
|
| 63 |
-
else:
|
| 64 |
-
print(f" ✗ Unexpected response: {data}")
|
| 65 |
-
except json.JSONDecodeError:
|
| 66 |
-
print(f" ✗ Invalid JSON response: {result.stdout}")
|
| 67 |
-
else:
|
| 68 |
-
print(f" ✗ Invalid command should fail but didn't")
|
| 69 |
-
|
| 70 |
-
# Test with web_search missing query
|
| 71 |
-
result = subprocess.run(
|
| 72 |
-
[sys.executable, "scripts/python_webtools.py", "web_search"],
|
| 73 |
-
capture_output=True,
|
| 74 |
-
text=True,
|
| 75 |
-
timeout=5
|
| 76 |
-
)
|
| 77 |
-
if result.returncode != 0:
|
| 78 |
-
try:
|
| 79 |
-
data = json.loads(result.stdout)
|
| 80 |
-
if data.get("success") == False:
|
| 81 |
-
print(f" ✓ Missing query correctly rejected: {data.get('error')}")
|
| 82 |
-
else:
|
| 83 |
-
print(f" ✗ Unexpected response: {data}")
|
| 84 |
-
except json.JSONDecodeError:
|
| 85 |
-
print(f" ✗ Invalid JSON response: {result.stdout}")
|
| 86 |
-
else:
|
| 87 |
-
print(f" ✗ Missing query should fail but didn't")
|
| 88 |
-
|
| 89 |
-
# Test with web_fetch missing URL
|
| 90 |
-
result = subprocess.run(
|
| 91 |
-
[sys.executable, "scripts/python_webtools.py", "web_fetch"],
|
| 92 |
-
capture_output=True,
|
| 93 |
-
text=True,
|
| 94 |
-
timeout=5
|
| 95 |
-
)
|
| 96 |
-
if result.returncode != 0:
|
| 97 |
-
try:
|
| 98 |
-
data = json.loads(result.stdout)
|
| 99 |
-
if data.get("success") == False:
|
| 100 |
-
print(f" ✓ Missing URL correctly rejected: {data.get('error')}")
|
| 101 |
-
else:
|
| 102 |
-
print(f" ✗ Unexpected response: {data}")
|
| 103 |
-
except json.JSONDecodeError:
|
| 104 |
-
print(f" ✗ Invalid JSON response: {result.stdout}")
|
| 105 |
-
else:
|
| 106 |
-
print(f" ✗ Missing URL should fail but didn't")
|
| 107 |
-
|
| 108 |
-
print("\nAll interface tests completed!")
|
| 109 |
-
print("\nNote: Network tests skipped due to connectivity issues.")
|
| 110 |
-
print("The Python webtools interface is working correctly.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/test_websearch_format.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env bun
|
| 2 |
-
/**
|
| 3 |
-
* Test WebSearch output format
|
| 4 |
-
*/
|
| 5 |
-
|
| 6 |
-
async function testWebSearchOutput() {
|
| 7 |
-
const { spawn } = await import('child_process')
|
| 8 |
-
|
| 9 |
-
const query = 'milet 2026'
|
| 10 |
-
const pythonScript = process.cwd() + '/scripts/python_webtools.py'
|
| 11 |
-
|
| 12 |
-
const result = await new Promise<any>((resolve, reject) => {
|
| 13 |
-
const child = spawn('.venv/bin/python', [pythonScript, 'web_search', query, '3'], {
|
| 14 |
-
cwd: process.cwd(),
|
| 15 |
-
})
|
| 16 |
-
|
| 17 |
-
let stdout = ''
|
| 18 |
-
let stderr = ''
|
| 19 |
-
|
| 20 |
-
child.stdout.on('data', (data) => {
|
| 21 |
-
stdout += data.toString()
|
| 22 |
-
})
|
| 23 |
-
|
| 24 |
-
child.stderr.on('data', (data) => {
|
| 25 |
-
stderr += data.toString()
|
| 26 |
-
})
|
| 27 |
-
|
| 28 |
-
child.on('close', (code) => {
|
| 29 |
-
if (code !== 0) {
|
| 30 |
-
reject(new Error(`Python failed: ${stderr}`))
|
| 31 |
-
return
|
| 32 |
-
}
|
| 33 |
-
|
| 34 |
-
try {
|
| 35 |
-
const data = JSON.parse(stdout)
|
| 36 |
-
resolve(data)
|
| 37 |
-
} catch (error) {
|
| 38 |
-
reject(error)
|
| 39 |
-
}
|
| 40 |
-
})
|
| 41 |
-
|
| 42 |
-
child.on('error', reject)
|
| 43 |
-
})
|
| 44 |
-
|
| 45 |
-
console.log('Python result:')
|
| 46 |
-
console.log(JSON.stringify(result, null, 2))
|
| 47 |
-
|
| 48 |
-
// Simulate TypeScript processing
|
| 49 |
-
const cleanedResults = result.results.map((r: any) => ({
|
| 50 |
-
title: r.title,
|
| 51 |
-
url: r.url,
|
| 52 |
-
snippet: r.content || undefined,
|
| 53 |
-
}))
|
| 54 |
-
|
| 55 |
-
console.log('\n\nCleaned results:')
|
| 56 |
-
console.log(JSON.stringify(cleanedResults, null, 2))
|
| 57 |
-
|
| 58 |
-
// Simulate output format
|
| 59 |
-
const searchResults = []
|
| 60 |
-
if (cleanedResults.length === 0) {
|
| 61 |
-
searchResults.push(`No results for: ${query}`)
|
| 62 |
-
} else {
|
| 63 |
-
searchResults.push({
|
| 64 |
-
tool_use_id: 'search-1',
|
| 65 |
-
content: cleanedResults.map((r: any) => ({
|
| 66 |
-
title: r.title,
|
| 67 |
-
url: r.url,
|
| 68 |
-
snippet: r.snippet,
|
| 69 |
-
}))
|
| 70 |
-
})
|
| 71 |
-
}
|
| 72 |
-
|
| 73 |
-
// Format for AI - improved format
|
| 74 |
-
let formattedOutput = `Web search results for query: "${query}"\n\n`
|
| 75 |
-
|
| 76 |
-
searchResults.forEach(result => {
|
| 77 |
-
if (typeof result === 'string') {
|
| 78 |
-
formattedOutput += result + '\n\n'
|
| 79 |
-
} else {
|
| 80 |
-
if (result.content?.length > 0) {
|
| 81 |
-
result.content.forEach((item: any, index: number) => {
|
| 82 |
-
formattedOutput += `${index + 1}. **${item.title || 'Untitled'}**\n`
|
| 83 |
-
formattedOutput += ` URL: ${item.url}\n`
|
| 84 |
-
if (item.snippet) {
|
| 85 |
-
formattedOutput += ` ${item.snippet}\n`
|
| 86 |
-
}
|
| 87 |
-
formattedOutput += '\n'
|
| 88 |
-
})
|
| 89 |
-
} else {
|
| 90 |
-
formattedOutput += 'No links found.\n\n'
|
| 91 |
-
}
|
| 92 |
-
}
|
| 93 |
-
})
|
| 94 |
-
|
| 95 |
-
formattedOutput += '\nREMINDER: You MUST include the sources above in your response to the user using markdown hyperlinks.'
|
| 96 |
-
|
| 97 |
-
console.log('\n\nFormatted output for AI:')
|
| 98 |
-
console.log(formattedOutput)
|
| 99 |
-
}
|
| 100 |
-
|
| 101 |
-
testWebSearchOutput().catch(console.error)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/test_webtools_integration.ts
DELETED
|
@@ -1,147 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env bun
|
| 2 |
-
/**
|
| 3 |
-
* Test WebSearch and WebFetch integration with Python webtools
|
| 4 |
-
*/
|
| 5 |
-
|
| 6 |
-
import { spawn } from 'child_process'
|
| 7 |
-
|
| 8 |
-
async function spawnPython(
|
| 9 |
-
args: string[],
|
| 10 |
-
timeout: number = 10000
|
| 11 |
-
): Promise<{ stdout: string; stderr: string; code: number | null }> {
|
| 12 |
-
return new Promise((resolve, reject) => {
|
| 13 |
-
const child = spawn('.venv/bin/python', args, {
|
| 14 |
-
cwd: process.cwd(),
|
| 15 |
-
})
|
| 16 |
-
|
| 17 |
-
let stdout = ''
|
| 18 |
-
let stderr = ''
|
| 19 |
-
|
| 20 |
-
child.stdout.on('data', (data) => {
|
| 21 |
-
stdout += data.toString()
|
| 22 |
-
})
|
| 23 |
-
|
| 24 |
-
child.stderr.on('data', (data) => {
|
| 25 |
-
stderr += data.toString()
|
| 26 |
-
})
|
| 27 |
-
|
| 28 |
-
const timeoutId = setTimeout(() => {
|
| 29 |
-
child.kill('SIGTERM')
|
| 30 |
-
reject(new Error(`Timeout after ${timeout}ms`))
|
| 31 |
-
}, timeout)
|
| 32 |
-
|
| 33 |
-
child.on('close', (code) => {
|
| 34 |
-
clearTimeout(timeoutId)
|
| 35 |
-
resolve({ stdout, stderr, code })
|
| 36 |
-
})
|
| 37 |
-
|
| 38 |
-
child.on('error', (error) => {
|
| 39 |
-
clearTimeout(timeoutId)
|
| 40 |
-
reject(error)
|
| 41 |
-
})
|
| 42 |
-
})
|
| 43 |
-
}
|
| 44 |
-
|
| 45 |
-
async function testWebSearchInterface() {
|
| 46 |
-
console.log('Test 1: WebSearch Interface')
|
| 47 |
-
console.log(' Testing command with missing query...')
|
| 48 |
-
|
| 49 |
-
try {
|
| 50 |
-
const result = await spawnPython(['scripts/python_webtools.py', 'web_search'], 5000)
|
| 51 |
-
const data = JSON.parse(result.stdout)
|
| 52 |
-
|
| 53 |
-
if (data.success === false && data.error.includes('Missing query')) {
|
| 54 |
-
console.log(' ✓ Missing query correctly rejected')
|
| 55 |
-
} else {
|
| 56 |
-
console.log(' ✗ Unexpected response:', data)
|
| 57 |
-
}
|
| 58 |
-
} catch (error) {
|
| 59 |
-
console.log(' ✗ Error:', error)
|
| 60 |
-
}
|
| 61 |
-
|
| 62 |
-
console.log(' Testing command with query...')
|
| 63 |
-
|
| 64 |
-
try {
|
| 65 |
-
const result = await spawnPython(['scripts/python_webtools.py', 'web_search', 'test', '3'], 10000)
|
| 66 |
-
const data = JSON.parse(result.stdout)
|
| 67 |
-
|
| 68 |
-
if (data.success && data.count > 0) {
|
| 69 |
-
console.log(` ✓ WebSearch returned ${data.count} results`)
|
| 70 |
-
} else {
|
| 71 |
-
console.log(' ✗ No results returned:', data)
|
| 72 |
-
}
|
| 73 |
-
} catch (error) {
|
| 74 |
-
console.log(' ✗ Error:', error)
|
| 75 |
-
}
|
| 76 |
-
}
|
| 77 |
-
|
| 78 |
-
async function testWebFetchInterface() {
|
| 79 |
-
console.log('\nTest 2: WebFetch Interface')
|
| 80 |
-
console.log(' Testing command with missing URL...')
|
| 81 |
-
|
| 82 |
-
try {
|
| 83 |
-
const result = await spawnPython(['scripts/python_webtools.py', 'web_fetch'], 5000)
|
| 84 |
-
const data = JSON.parse(result.stdout)
|
| 85 |
-
|
| 86 |
-
if (data.success === false && data.error.includes('Missing URL')) {
|
| 87 |
-
console.log(' ✓ Missing URL correctly rejected')
|
| 88 |
-
} else {
|
| 89 |
-
console.log(' ✗ Unexpected response:', data)
|
| 90 |
-
}
|
| 91 |
-
} catch (error) {
|
| 92 |
-
console.log(' ✗ Error:', error)
|
| 93 |
-
}
|
| 94 |
-
|
| 95 |
-
console.log(' Testing command with URL...')
|
| 96 |
-
|
| 97 |
-
try {
|
| 98 |
-
const result = await spawnPython(['scripts/python_webtools.py', 'web_fetch', 'https://example.com', '5000'], 10000)
|
| 99 |
-
const data = JSON.parse(result.stdout)
|
| 100 |
-
|
| 101 |
-
if (data.success) {
|
| 102 |
-
console.log(` ✓ WebFetch returned ${data.length} bytes`)
|
| 103 |
-
} else {
|
| 104 |
-
console.log(' ✗ Fetch failed:', data.error)
|
| 105 |
-
}
|
| 106 |
-
} catch (error) {
|
| 107 |
-
console.log(' ✗ Error:', error)
|
| 108 |
-
}
|
| 109 |
-
}
|
| 110 |
-
|
| 111 |
-
async function testInvalidCommand() {
|
| 112 |
-
console.log('\nTest 3: Invalid Command')
|
| 113 |
-
console.log(' Testing invalid command...')
|
| 114 |
-
|
| 115 |
-
try {
|
| 116 |
-
const result = await spawnPython(['scripts/python_webtools.py', 'invalid'], 5000)
|
| 117 |
-
const data = JSON.parse(result.stdout)
|
| 118 |
-
|
| 119 |
-
if (data.success === false && data.error.includes('Unknown command')) {
|
| 120 |
-
console.log(' ✓ Invalid command correctly rejected')
|
| 121 |
-
} else {
|
| 122 |
-
console.log(' ✗ Unexpected response:', data)
|
| 123 |
-
}
|
| 124 |
-
} catch (error) {
|
| 125 |
-
console.log(' ✗ Error:', error)
|
| 126 |
-
}
|
| 127 |
-
}
|
| 128 |
-
|
| 129 |
-
async function main() {
|
| 130 |
-
console.log('Testing Python WebTools Integration\n')
|
| 131 |
-
console.log('=' .repeat(50))
|
| 132 |
-
|
| 133 |
-
await testWebSearchInterface()
|
| 134 |
-
await testWebFetchInterface()
|
| 135 |
-
await testInvalidCommand()
|
| 136 |
-
|
| 137 |
-
console.log('\n' + '='.repeat(50))
|
| 138 |
-
console.log('\nAll integration tests completed!')
|
| 139 |
-
console.log('\nSummary:')
|
| 140 |
-
console.log(' ✓ Python script interface working correctly')
|
| 141 |
-
console.log(' ✓ Error handling working correctly')
|
| 142 |
-
console.log(' ✓ WebSearch working correctly')
|
| 143 |
-
console.log(' ✓ WebFetch working correctly')
|
| 144 |
-
console.log('\nThe TypeScript → Python integration is fully functional!')
|
| 145 |
-
}
|
| 146 |
-
|
| 147 |
-
main().catch(console.error)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tests/websearch_test.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env bun
|
| 2 |
-
/**
|
| 3 |
-
* WebSearch 集成测试
|
| 4 |
-
* 测试打包后的 CLI 中的 WebSearch 功能
|
| 5 |
-
*/
|
| 6 |
-
|
| 7 |
-
import { spawn } from 'child_process'
|
| 8 |
-
|
| 9 |
-
console.log('='.repeat(60))
|
| 10 |
-
console.log('WebSearch Integration Test')
|
| 11 |
-
console.log('='.repeat(60))
|
| 12 |
-
|
| 13 |
-
async function testWebSearch() {
|
| 14 |
-
return new Promise((resolve, reject) => {
|
| 15 |
-
const child = spawn('./cli-dev', [], {
|
| 16 |
-
stdio: ['pipe', 'pipe', 'pipe'],
|
| 17 |
-
shell: true,
|
| 18 |
-
})
|
| 19 |
-
|
| 20 |
-
let stdout = ''
|
| 21 |
-
let stderr = ''
|
| 22 |
-
|
| 23 |
-
// 发送搜索命令
|
| 24 |
-
setTimeout(() => {
|
| 25 |
-
child.stdin.write('WebSearch("milet 最新动态 2026")\n')
|
| 26 |
-
setTimeout(() => {
|
| 27 |
-
child.stdin.end()
|
| 28 |
-
}, 2000)
|
| 29 |
-
}, 1000)
|
| 30 |
-
|
| 31 |
-
child.stdout.on('data', (data) => {
|
| 32 |
-
stdout += data.toString()
|
| 33 |
-
console.log('[STDOUT]', data.toString().trim())
|
| 34 |
-
})
|
| 35 |
-
|
| 36 |
-
child.stderr.on('data', (data) => {
|
| 37 |
-
stderr += data.toString()
|
| 38 |
-
console.error('[STDERR]', data.toString().trim())
|
| 39 |
-
})
|
| 40 |
-
|
| 41 |
-
child.on('close', (code) => {
|
| 42 |
-
console.log('\n' + '='.repeat(60))
|
| 43 |
-
console.log(`Process exited with code ${code}`)
|
| 44 |
-
console.log(`Stdout length: ${stdout.length}`)
|
| 45 |
-
console.log(`Stderr length: ${stderr.length}`)
|
| 46 |
-
|
| 47 |
-
// 检查是否有关键词
|
| 48 |
-
const hasResults = stdout.includes('Links:') || stdout.includes('http')
|
| 49 |
-
const hasError = stdout.includes('Error') || stdout.includes('error')
|
| 50 |
-
|
| 51 |
-
if (hasResults) {
|
| 52 |
-
console.log('\n✅ WebSearch 返回了结果!')
|
| 53 |
-
} else if (hasError) {
|
| 54 |
-
console.log('\n❌ WebSearch 返回了错误')
|
| 55 |
-
reject(new Error('WebSearch returned error'))
|
| 56 |
-
} else {
|
| 57 |
-
console.log('\n⚠️ WebSearch 没有返回结果或错误')
|
| 58 |
-
reject(new Error('No results or error returned'))
|
| 59 |
-
}
|
| 60 |
-
|
| 61 |
-
resolve(code)
|
| 62 |
-
})
|
| 63 |
-
|
| 64 |
-
// 超时处理
|
| 65 |
-
setTimeout(() => {
|
| 66 |
-
child.kill('SIGTERM')
|
| 67 |
-
console.log('\n⚠️ Timeout - killed process')
|
| 68 |
-
reject(new Error('Test timeout'))
|
| 69 |
-
}, 60000)
|
| 70 |
-
})
|
| 71 |
-
}
|
| 72 |
-
|
| 73 |
-
async function main() {
|
| 74 |
-
try {
|
| 75 |
-
await testWebSearch()
|
| 76 |
-
console.log('\n✅ Test completed!')
|
| 77 |
-
} catch (error) {
|
| 78 |
-
console.error('\n❌ Test failed:', error)
|
| 79 |
-
process.exit(1)
|
| 80 |
-
}
|
| 81 |
-
}
|
| 82 |
-
|
| 83 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|