import assert from 'node:assert/strict' import { mkdtemp, readFile, rm } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { executeTool, toolSpecs } from '../src/main/agent/tools' const workspace = await mkdtemp(join(tmpdir(), 'ycode-host-tools-')) let approvals = 0 const context = { workspaceRoot: workspace, permissionMode: 'default-sandbox' as const, approve: async () => { approvals += 1 return false } } try { const specs = toolSpecs() const names = specs.map(spec => spec.function.name) assert.equal(names.includes('sandbox_workspace'), false) assert.equal(names.includes('sandbox_git'), false) const command = specs.find(spec => spec.function.name === 'execute_command') const properties = command?.function.parameters.properties as Record | undefined assert.deepEqual(Object.keys(properties ?? {}), ['command']) const written = await executeTool('write_file', { path: 'nested/file.txt', content: 'first' }, context) assert.equal(written.ok, true) assert.equal(await readFile(join(workspace, 'nested/file.txt'), 'utf8'), 'first') assert.equal(approvals, 0) const edited = await executeTool('edit_file', { path: 'nested/file.txt', oldText: 'first', newText: 'second' }, context) assert.equal(edited.ok, true) assert.equal(await readFile(join(workspace, 'nested/file.txt'), 'utf8'), 'second') const commandResult = await executeTool('execute_command', { command: `${JSON.stringify(process.execPath)} -e "require('node:fs').writeFileSync('host-command.txt','host')"` }, context) assert.equal(commandResult.ok, true) assert.equal(await readFile(join(workspace, 'host-command.txt'), 'utf8'), 'host') assert.equal(JSON.stringify(commandResult.data).includes('windows-appcontainer'), false) assert.equal(JSON.stringify(commandResult.data).includes('sandbox'), false) assert.equal(approvals, 0) const outside = await executeTool('read_file', { path: '../outside.txt' }, context) assert.equal(outside.ok, false) assert.match(outside.content, /工作区/) console.log('sandbox-disabled-regression: host tools are active and legacy sandbox modes are inert') } finally { await rm(workspace, { recursive: true, force: true }) }