Files
lms-fe/scripts/test-agent-workspace-routing.cjs
T

69 lines
3.8 KiB
JavaScript

const { test } = require('node:test')
const assert = require('node:assert/strict')
const fs = require('node:fs')
const ts = require('typescript')
const vm = require('node:vm')
const app = ts.createSourceFile('App.tsx', fs.readFileSync(require.resolve('../src/renderer/src/App.tsx'), 'utf8'), ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX)
const declarations = new Map()
function visit(node) {
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) declarations.set(node.name.text, node.initializer?.getText(app))
ts.forEachChild(node, visit)
}
visit(app)
const plain = value => JSON.parse(JSON.stringify(value))
function harness(remoteWorkspace) {
const executions = []
const calls = []
const errors = []
const target = { host: '100.64.0.10', user: 'fixture', workspaceRoot: '/fixture/workspace' }
const live = [{ name: 'NAV2-MKMini', folderName: 'vehicle', state: 'running', parameters: ['sim_mode:=false', 'robot:=mkmini'] }]
const readTool = backend => async (...args) => { executions.push({ backend, args: plain(args) }); return { status: 'ok', data: '{"content":"remote source"}' } }
const exports = {}
const globals = {
exports, remoteWorkspace, availableModules: [{ ...live[0], state: 'stopped', parameters: ['sim_mode:=true'] }],
clonePathPreview: '/local/workspace', runtimeModules: [], agentActionControllerRef: { current: null }, agentApplying: false,
getRemoteWorkspaceTarget: () => target, applyModuleParameterOverrides: modules => modules,
validateAgentTool: request => request, AGENT_PRACTICE_PROFILES: [],
window: {
remoteWorkspace: { modules: { list: async () => ({ modules: live }) }, agent: { readTool: readTool('remote') } },
localWorkspace: { modules: { list: async () => ({ modules: live }) }, agent: { readTool: readTool('local') } }
},
requestAgentPlan: async (...args) => { calls.push(args) },
onTitlebarNotice: (...args) => { errors.push(args) }, console: { error: () => {} },
loadAgentRequestedContext: async () => ({ modules: [], runtimeLogs: [] })
}
const names = ['collectAgentWorkspace', 'readAgentModules', 'executeWorkspaceAgentTool', 'submitAgentRequest']
vm.runInNewContext(ts.transpileModule(names.map(name => `const ${name} = ${declarations.get(name)}; exports.${name} = ${name}`).join('\n'), {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 }
}).outputText, globals)
return { ...exports, executions, calls, errors }
}
for (const remote of [false, true]) {
test(`${remote ? 'remote' : 'local'}: a new question refreshes state and start settings before sending context`, async () => {
const h = harness(remote)
await h.submitAgentRequest('최대 속도 제한 코드 위치')
assert.deepEqual(h.errors, [])
assert.equal(h.calls.length, 1)
const [, modules, , options] = h.calls[0]
assert.equal(modules[0].state, 'running')
assert.deepEqual(plain(modules[0].parameters), ['sim_mode:=false', 'robot:=mkmini'])
assert.deepEqual(plain(modules[0].files), [])
assert.equal(options.environment, remote ? 'remote' : 'local')
assert.equal(options.workspaceTarget, remote ? 'ssh:100.64.0.10' : 'local-host')
})
test(`${remote ? 'remote' : 'local'}: source reads use only the connected workspace transport and module folder`, async () => {
const h = harness(remote)
const tool = { id: 'read-1', name: 'files.read', moduleName: 'NAV2-MKMini', args: { path: 'src/profiles.py', startLine: 10, lineCount: 20 } }
await h.executeWorkspaceAgentTool(tool)
assert.equal(h.executions.length, 1)
assert.equal(h.executions[0].backend, remote ? 'remote' : 'local')
const args = h.executions[0].args
assert.deepEqual(args[remote ? 1 : 0], tool)
assert.equal(args[2], 'vehicle')
assert.equal(remote ? args[0].host : args[1], remote ? '100.64.0.10' : '/local/workspace')
})
}