Files
memind/dsh-agent-launch.mjs
T

118 lines
3.1 KiB
JavaScript
Raw Normal View History

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.',
],
};
}