Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
1 line
6.4 KiB
JSON
1 line
6.4 KiB
JSON
{"repo": "cc01cc/cmtx-project", "files": {"packages/ai/tests/integration/generate-slug.integration.test.ts": {"73132945e593bbeafd054539146039615f2eb302": {"t": 1786068277.1428332, "n": 5882, "h": "3bf30feee9edf3a9", "c": "import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { describe, expect, it } from \"vitest\";\nimport { generateSlug } from \"../../src/slug/generator.js\";\n\ninterface ProviderTestConfig {\n enabled: boolean;\n apiKey: string;\n model: string;\n baseURL: string;\n}\n\ninterface TestConfig {\n deepseek: ProviderTestConfig;\n alibaba: ProviderTestConfig;\n}\n\nconst CONFIG_PATH = join(__dirname, \"../../../../tests/integration/config.jsonc\");\n\nconst AI_PROVIDER_ENV = {\n deepseek: {\n apiKey: \"TEST_CMTX_DEEPSEEK_API_KEY\",\n model: \"TEST_CMTX_DEEPSEEK_MODEL\",\n baseURL: \"TEST_CMTX_DEEPSEEK_BASE_URL\",\n },\n alibaba: {\n apiKey: \"TEST_CMTX_ALIBABA_API_KEY\",\n model: \"TEST_CMTX_ALIBABA_MODEL\",\n baseURL: \"TEST_CMTX_ALIBABA_BASE_URL\",\n },\n} as const;\n\nfunction stripJsoncComments(raw: string): string {\n return raw.replace(/\\/\\/.*$/gm, \"\").replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n}\n\ninterface AIProviderEnvDef {\n apiKey: string;\n model: string;\n baseURL: string;\n}\n\nfunction collectAIProvider(\n def: AIProviderEnvDef,\n label: string,\n): { config: ProviderTestConfig | null; errors: string[] } {\n const apiKey = process.env[def.apiKey];\n const model = process.env[def.model];\n const baseURL = process.env[def.baseURL];\n const missing: string[] = [];\n\n if (!apiKey) missing.push(def.apiKey);\n if (!model) missing.push(def.model);\n\n if (missing.length === 2) {\n return { config: null, errors: [] };\n }\n if (missing.length > 0) {\n return {\n config: null,\n errors: [`${label} 环境变量配置不完整,缺少:${missing.join(\", \")}`],\n };\n }\n\n return {\n config: { enabled: true, apiKey: apiKey!, model: model!, baseURL: baseURL ?? \"\" },\n errors: [],\n };\n}\n\nfunction loadTestConfig(): TestConfig | null {\n const errors: string[] = [];\n\n const deepseek = collectAIProvider(AI_PROVIDER_ENV.deepseek, \"DeepSeek\");\n errors.push(...deepseek.errors);\n\n const alibaba = collectAIProvider(AI_PROVIDER_ENV.alibaba, \"Alibaba/Qwen\");\n errors.push(...alibaba.errors);\n\n if (errors.length > 0) {\n throw new Error(\n `AI 集成测试环境变量配置有误:\\n ${errors.join(\"\\n \")}\\n\\n` +\n `设置方式:\\n` +\n ` 1. 在项目根目录创建 .env 文件,写入变量后执行:export $(cat .env | xargs)\\n` +\n ` 2. 或直接 export 每个变量:export TEST_CMTX_DEEPSEEK_API_KEY=...\\n` +\n ` 3. devcontainer 用户:在 .devcontainer/.env 中配置(docker-compose 自动注入)`,\n );\n }\n\n if (deepseek.config || alibaba.config) {\n return {\n deepseek: deepseek.config ?? { enabled: false, apiKey: \"\", model: \"\", baseURL: \"\" },\n alibaba: alibaba.config ?? { enabled: false, apiKey: \"\", model: \"\", baseURL: \"\" },\n };\n }\n\n if (!existsSync(CONFIG_PATH)) return null;\n\n const content = readFileSync(CONFIG_PATH, \"utf-8\");\n const parsed = JSON.parse(stripJsoncComments(content));\n return parsed.ai as TestConfig;\n}\n\nconst testConfig = loadTestConfig();\n\nconst deepseekEnabled = testConfig?.deepseek?.enabled === true && !!testConfig.deepseek.apiKey;\nconst alibabaEnabled = testConfig?.alibaba?.enabled === true && !!testConfig.alibaba.apiKey;\n\ndescribe.skipIf(!deepseekEnabled)(\"generateSlug with DeepSeek\", () => {\n it(\"generates a slug from a Chinese title\", async () => {\n const slug = await generateSlug(\n {\n provider: \"deepseek\",\n model: testConfig!.deepseek.model,\n apiKey: testConfig!.deepseek.apiKey,\n baseURL: testConfig!.deepseek.baseURL,\n },\n \"OpenClaw 安装避坑不完全指南\",\n undefined,\n { temperature: 0.3, maxTokens: 300 },\n );\n\n expect(slug).toBeTruthy();\n expect(slug).toMatch(/^[a-z0-9-]+$/);\n expect(slug.length).toBeGreaterThanOrEqual(5);\n }, 30000);\n\n it(\"generates a slug from an English title\", async () => {\n const slug = await generateSlug(\n {\n provider: \"deepseek\",\n model: testConfig!.deepseek.model,\n apiKey: testConfig!.deepseek.apiKey,\n baseURL: testConfig!.deepseek.baseURL,\n },\n \"Getting Started with TypeScript 5.0\",\n undefined,\n { temperature: 0.3, maxTokens: 200 },\n );\n\n expect(slug).toBeTruthy();\n expect(slug).toMatch(/^[a-z0-9-]+$/);\n }, 30000);\n});\n\ndescribe.skipIf(!alibabaEnabled)(\"generateSlug with Alibaba/Qwen\", () => {\n it(\"generates a slug from a Chinese title\", async () => {\n try {\n const slug = await generateSlug(\n {\n provider: \"alibaba\",\n model: testConfig!.alibaba.model,\n apiKey: testConfig!.alibaba.apiKey,\n baseURL: testConfig!.alibaba.baseURL,\n },\n \"OpenClaw 安装避坑不完全指南\",\n undefined,\n { temperature: 0.3, maxTokens: 300 },\n );\n\n expect(slug).toBeTruthy();\n expect(slug).toMatch(/^[a-z0-9-]+$/);\n } catch (error: unknown) {\n const err = error as {\n statusCode?: number;\n responseBody?: string;\n data?: unknown;\n message?: string;\n url?: string;\n };\n console.error(\"[ERROR] Alibaba API call failed:\");\n console.error(` message: ${err.message ?? \"unknown\"}`);\n console.error(` url: ${err.url ?? \"N/A\"}`);\n console.error(` statusCode: ${err.statusCode ?? \"N/A\"}`);\n console.error(` responseBody: ${err.responseBody ?? \"N/A\"}`);\n console.error(` data: ${JSON.stringify(err.data)}`);\n throw error;\n }\n }, 30000);\n});\n"}}}} |