import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; function envFlag(value, fallback = false) { const raw = String(value ?? '').trim().toLowerCase(); if (!raw) return fallback; return ['1', 'true', 'yes', 'on'].includes(raw); } export function dshExecutorEnabled(env = process.env) { return envFlag(env.MEMIND_TOOL_GATEWAY_DSH_ENABLED, false); } export function expandHome(value) { const text = String(value ?? '').trim(); if (!text) return text; if (text.startsWith('~/')) return path.join(os.homedir(), text.slice(2)); if (text === '~') return os.homedir(); return text; } export function resolveDshCommand(env = process.env) { if (envFlag(env.MEMIND_DSH_FORCE_NPX, false)) { return { command: String(env.MEMIND_DSH_NPX_BIN ?? 'npx').trim() || 'npx', viaNpx: true, }; } const fileCandidates = [ env.MEMIND_DSH_BIN, env.DSH_BIN, '~/.local/bin/dsh', ].map((item) => expandHome(String(item ?? '').trim())).filter(Boolean); for (const candidate of fileCandidates) { if (fs.existsSync(candidate)) { return { command: candidate, viaNpx: false }; } } const bare = String(env.DSH_BIN ?? 'dsh').trim(); if (bare && !bare.includes('/')) { return { command: bare, viaNpx: false }; } return { command: String(env.MEMIND_DSH_NPX_BIN ?? 'npx').trim() || 'npx', viaNpx: true, }; } export function buildDshExecutorInstruction(instruction) { const base = String(instruction ?? '').trim(); if (!base) return base; return [ base, '', 'Execution constraints:', '- Work only inside the provided workspace cwd', '- Do not run git commit/push or production deploy commands', '- Prefer minimal, reviewable diffs', '- Summarize changed files in the final answer', ].join('\n'); } export function buildDshExecutorLaunchPlan({ cwd, instruction, env = process.env, runtimeEnv = {}, } = {}) { if (!dshExecutorEnabled(env)) { return { ok: false, executor: 'dsh', message: 'DeepSeek Harness 执行器未启用(MEMIND_TOOL_GATEWAY_DSH_ENABLED)', }; } const workspace = path.resolve(String(cwd ?? env.MEMIND_DSH_EXECUTOR_WORKSPACE ?? process.cwd())); const prompt = buildDshExecutorInstruction(instruction); if (!prompt) { return { ok: false, executor: 'dsh', message: 'DeepSeek Harness 执行器需要 instruction', }; } const resolved = resolveDshCommand(env); const args = resolved.viaNpx ? ['-y', '@deepseek-ai/dsh', '--profile', 'headless', prompt] : ['--profile', 'headless', prompt]; const launchEnv = { ...runtimeEnv, }; if (!launchEnv.DEEPSEEK_API_KEY && env.DEEPSEEK_API_KEY) { launchEnv.DEEPSEEK_API_KEY = env.DEEPSEEK_API_KEY; } return { ok: true, executor: 'dsh', executorLabel: 'DeepSeek Harness', cwd: workspace, command: resolved.command, args, env: launchEnv, notes: [ 'DeepSeek Harness headless one-shot task via dsh --profile headless.', 'Developer preview: keep disabled by default and route only whitelisted task types.', ], }; }