580e4dd87f
将 process-session fixture 改为不依赖控制面和 namespace 身份的纯 PTY 协议 使用 durable start、readiness、cursor、stdin 哈希和 cwd 进程归零校验交互链 新增真实 Node 子进程 smoke 覆盖 readiness、精确回显与停止状态 记录 Provider 瞬态失败和可信 exec-ready 两阶段协议 同步长期决策、技术方案与沙箱验收踩坑
56 lines
1.5 KiB
JavaScript
56 lines
1.5 KiB
JavaScript
export function buildProcessSessionFixtureSource({
|
|
readyPrefix,
|
|
echoPrefix,
|
|
stoppedMarker,
|
|
}) {
|
|
for (const [name, value] of Object.entries({
|
|
readyPrefix,
|
|
echoPrefix,
|
|
stoppedMarker,
|
|
})) {
|
|
if (
|
|
typeof value !== 'string' ||
|
|
value.length === 0 ||
|
|
/[\r\n]/u.test(value)
|
|
) {
|
|
throw new Error(`invalid process fixture marker: ${name}`);
|
|
}
|
|
}
|
|
|
|
return [
|
|
"import { randomBytes } from 'node:crypto';",
|
|
'',
|
|
`const readyPrefix = ${JSON.stringify(readyPrefix)};`,
|
|
`const echoPrefix = ${JSON.stringify(echoPrefix)};`,
|
|
`const stoppedMarker = ${JSON.stringify(stoppedMarker)};`,
|
|
"const challenge = randomBytes(18).toString('hex');",
|
|
'let echoed = false;',
|
|
'let stopping = false;',
|
|
'',
|
|
'function stop() {',
|
|
' if (stopping) return;',
|
|
' stopping = true;',
|
|
' console.log(stoppedMarker);',
|
|
' process.exit(0);',
|
|
'}',
|
|
"for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP']) process.on(signal, stop);",
|
|
"console.log(readyPrefix + ' challenge=' + challenge);",
|
|
'',
|
|
"process.stdin.setEncoding('utf8');",
|
|
"let buffered = '';",
|
|
"process.stdin.on('data', (chunk) => {",
|
|
' buffered += chunk;',
|
|
' const lines = buffered.split(/\\r?\\n/u);',
|
|
" buffered = lines.pop() ?? '';",
|
|
' for (const line of lines) {',
|
|
' if (!echoed && line === challenge) {',
|
|
' echoed = true;',
|
|
" console.log(echoPrefix + ' ' + challenge);",
|
|
' }',
|
|
' }',
|
|
'});',
|
|
'process.stdin.resume();',
|
|
'',
|
|
].join('\n');
|
|
}
|