@cnrai/pave 0.3.33 → 0.3.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MARKETPLACE.md +406 -0
- package/README.md +218 -21
- package/build-binary.js +591 -0
- package/build-npm.js +537 -0
- package/build.js +230 -0
- package/check-binary.js +26 -0
- package/deploy.sh +95 -0
- package/index.js +5775 -0
- package/lib/agent-registry.js +1037 -0
- package/lib/args-parser.js +837 -0
- package/lib/blessed-widget-patched.js +93 -0
- package/lib/cli-markdown.js +590 -0
- package/lib/compaction.js +153 -0
- package/lib/duration.js +94 -0
- package/lib/hash.js +22 -0
- package/lib/marketplace.js +866 -0
- package/lib/memory-config.js +166 -0
- package/lib/skill-manager.js +891 -0
- package/lib/soul.js +31 -0
- package/lib/tool-output-formatter.js +180 -0
- package/package.json +35 -32
- package/start-pave.sh +149 -0
- package/status.js +271 -0
- package/test/abort-stream.test.js +445 -0
- package/test/agent-auto-compaction.test.js +552 -0
- package/test/agent-comm-abort.test.js +95 -0
- package/test/agent-comm.test.js +598 -0
- package/test/agent-inbox.test.js +576 -0
- package/test/agent-init.test.js +264 -0
- package/test/agent-interrupt.test.js +314 -0
- package/test/agent-lifecycle.test.js +520 -0
- package/test/agent-log-files.test.js +349 -0
- package/test/agent-mode.manual-test.js +392 -0
- package/test/agent-parsing.test.js +228 -0
- package/test/agent-post-stream-idle.test.js +762 -0
- package/test/agent-registry.test.js +359 -0
- package/test/agent-rm.test.js +442 -0
- package/test/agent-spawn.test.js +933 -0
- package/test/agent-status-api.test.js +624 -0
- package/test/agent-update.test.js +435 -0
- package/test/args-parser.test.js +391 -0
- package/test/auto-compaction-chat.manual-test.js +227 -0
- package/test/auto-compaction.test.js +941 -0
- package/test/build-config.test.js +120 -0
- package/test/build-npm.test.js +388 -0
- package/test/chat-command.test.js +137 -0
- package/test/chat-leading-lines.test.js +159 -0
- package/test/config-flag.test.js +272 -0
- package/test/cursor-drift.test.js +135 -0
- package/test/debug-require.js +23 -0
- package/test/dir-migration.test.js +323 -0
- package/test/duration.test.js +229 -0
- package/test/ghostty-term.test.js +202 -0
- package/test/http500-backoff.test.js +854 -0
- package/test/integration.test.js +86 -0
- package/test/memory-guard-env.test.js +220 -0
- package/test/pr233-fixes.test.js +259 -0
- package/test/run-agent-init.js +297 -0
- package/test/run-all.js +64 -0
- package/test/run-config-flag.js +159 -0
- package/test/run-cursor-drift.js +82 -0
- package/test/run-session-path.js +154 -0
- package/test/run-tests.js +643 -0
- package/test/sandbox-redirect.test.js +202 -0
- package/test/session-path.test.js +132 -0
- package/test/shebang-strip.test.js +241 -0
- package/test/soul-reinject.test.js +1027 -0
- package/test/soul-reread.test.js +281 -0
- package/test/tool-output-formatter.test.js +486 -0
- package/test/tool-output-gating.test.js +143 -0
- package/test/tool-states.test.js +167 -0
- package/test/tools-flag.test.js +65 -0
- package/test/tui-attach.test.js +1255 -0
- package/test/tui-compaction.test.js +354 -0
- package/test/tui-wrap.test.js +568 -0
- package/test-binary.js +52 -0
- package/test-binary2.js +36 -0
- package/LICENSE +0 -21
- package/pave.js +0 -3
- package/sandbox/SandboxRunner.js +0 -1
- package/sandbox/pave-run.js +0 -2
- package/sandbox/permission.js +0 -1
- package/sandbox/utils/yaml.js +0 -1
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Tests for agent log file redirection and session file location (Issue #99).
|
|
4
|
+
*
|
|
5
|
+
* Verifies that:
|
|
6
|
+
* 1. Agent command writes pave.log to --config directory (not silencing console)
|
|
7
|
+
* 2. Agent command writes debug.log when DEBUG=1
|
|
8
|
+
* 3. Agent session file is stored in cwd as .pave-session.json (not config dir, see #108)
|
|
9
|
+
* 4. Log directory defaults to $(cwd)/.pave when --config is not specified
|
|
10
|
+
*
|
|
11
|
+
* Runs under `npm test` via test/run-tests.js
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const os = require('os');
|
|
17
|
+
|
|
18
|
+
let passed = 0;
|
|
19
|
+
let failed = 0;
|
|
20
|
+
|
|
21
|
+
function runTest(name, testFn) {
|
|
22
|
+
try {
|
|
23
|
+
testFn();
|
|
24
|
+
passed++;
|
|
25
|
+
console.log(`✅ ${name}`);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
failed++;
|
|
28
|
+
console.log(`❌ ${name}: ${error.message}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function assertEqual(actual, expected, message) {
|
|
33
|
+
if (actual !== expected) {
|
|
34
|
+
throw new Error(`${message || 'Assertion'}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function assertContains(str, substr, message) {
|
|
39
|
+
if (typeof str !== 'string' || str.indexOf(substr) < 0) {
|
|
40
|
+
throw new Error(`${message || 'Assertion'}: expected ${JSON.stringify(str)} to contain ${JSON.stringify(substr)}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log('\n=== Agent Log Files Tests (Issue #99) ===\n');
|
|
45
|
+
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Test: Log directory resolution logic
|
|
48
|
+
// ============================================================================
|
|
49
|
+
console.log('--- Log directory resolution ---');
|
|
50
|
+
|
|
51
|
+
runTest('Default log directory should resolve ./.pave (args-parser default)', () => {
|
|
52
|
+
// args.config defaults to './.pave' from args-parser (always truthy)
|
|
53
|
+
const argsConfig = './.pave';
|
|
54
|
+
const logDir = path.resolve(argsConfig);
|
|
55
|
+
assertEqual(logDir, path.resolve('./.pave'), 'log dir');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
runTest('Log directory should use --config path when specified', () => {
|
|
59
|
+
const argsConfig = '/tmp/myproject/.pave';
|
|
60
|
+
const logDir = path.resolve(argsConfig);
|
|
61
|
+
assertEqual(logDir, path.resolve('/tmp/myproject/.pave'), 'log dir');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
runTest('Log directory should resolve relative --config paths', () => {
|
|
65
|
+
const argsConfig = './custom-config';
|
|
66
|
+
const logDir = path.resolve(argsConfig);
|
|
67
|
+
assertEqual(logDir, path.resolve('./custom-config'), 'log dir');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
runTest('pave.log path should be inside log directory', () => {
|
|
71
|
+
const logDir = '/tmp/test-config';
|
|
72
|
+
const logFile = path.join(logDir, 'pave.log');
|
|
73
|
+
assertEqual(logFile, path.join('/tmp/test-config', 'pave.log'), 'pave.log path');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
runTest('debug.log path should be inside log directory', () => {
|
|
77
|
+
const logDir = '/tmp/test-config';
|
|
78
|
+
const debugLog = path.join(logDir, 'debug.log');
|
|
79
|
+
assertEqual(debugLog, path.join('/tmp/test-config', 'debug.log'), 'debug.log path');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// ============================================================================
|
|
83
|
+
// Test: Session file location
|
|
84
|
+
// ============================================================================
|
|
85
|
+
console.log('\n--- Session file location ---');
|
|
86
|
+
|
|
87
|
+
runTest('Session file should use resolveSessionFile (not direct path, #108 + #174)', () => {
|
|
88
|
+
// Verify from source code that agent SESSION_FILE uses resolveSessionFile
|
|
89
|
+
const source = fs.readFileSync(path.join(__dirname, '..', 'index.js'), 'utf8');
|
|
90
|
+
const agentBody = extractHandleAgentCommand(source);
|
|
91
|
+
|
|
92
|
+
// Agent should use resolveSessionFile(configDir) not path.join(process.cwd(), ...)
|
|
93
|
+
assertContains(agentBody, 'resolveSessionFile(configDir)', 'agent uses resolveSessionFile');
|
|
94
|
+
if (agentBody.indexOf("path.join(process.cwd(), '.pave-session.json')") >= 0) {
|
|
95
|
+
throw new Error('agent SESSION_FILE should not use direct .pave-session.json path');
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
runTest('Session file resolves to .pave/session.json', () => {
|
|
100
|
+
// The new session file is inside the config directory
|
|
101
|
+
const configDir = path.join(process.cwd(), '.pave');
|
|
102
|
+
const sessionFile = path.join(configDir, 'session.json');
|
|
103
|
+
assertContains(sessionFile, 'session.json', 'config dir session file');
|
|
104
|
+
assertEqual(path.basename(sessionFile), 'session.json', 'filename');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
runTest('Only one session file path (no dual writes, #108)', () => {
|
|
108
|
+
// After #108, there should be no CWD_SESSION_FILE — session is now at .pave/session.json
|
|
109
|
+
// (migrated from .pave-session.json in #174, resolved via resolveSessionFile helper)
|
|
110
|
+
const source = fs.readFileSync(path.join(__dirname, '..', 'index.js'), 'utf8');
|
|
111
|
+
if (source.indexOf('CWD_SESSION_FILE') >= 0) {
|
|
112
|
+
throw new Error('CWD_SESSION_FILE should not exist after #108');
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// ============================================================================
|
|
117
|
+
// Test: Debug logging enablement
|
|
118
|
+
// ============================================================================
|
|
119
|
+
console.log('\n--- Debug logging enablement ---');
|
|
120
|
+
|
|
121
|
+
// Helper that mirrors the actual debugEnabled logic in handleAgentCommand
|
|
122
|
+
function isDebugEnabled(envDebug, envPaveDebug, argsDebug) {
|
|
123
|
+
return envDebug === '1' || envPaveDebug === '1' || Boolean(argsDebug);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
runTest('Debug is enabled when DEBUG=1', () => {
|
|
127
|
+
assertEqual(isDebugEnabled('1', undefined, false), true, 'DEBUG=1');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
runTest('Debug is enabled when PAVE_DEBUG=1', () => {
|
|
131
|
+
assertEqual(isDebugEnabled(undefined, '1', false), true, 'PAVE_DEBUG=1');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
runTest('Debug is enabled when --debug flag is set', () => {
|
|
135
|
+
assertEqual(isDebugEnabled(undefined, undefined, true), true, '--debug');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
runTest('Debug is disabled when no debug flag', () => {
|
|
139
|
+
assertEqual(isDebugEnabled(undefined, undefined, false), false, 'no debug');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
runTest('Debug is disabled when env vars are not "1"', () => {
|
|
143
|
+
assertEqual(isDebugEnabled('0', '0', false), false, 'DEBUG=0');
|
|
144
|
+
assertEqual(isDebugEnabled('true', 'true', false), false, 'DEBUG=true (not "1")');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// Test: Log stream writeToAgentLog format
|
|
149
|
+
// ============================================================================
|
|
150
|
+
console.log('\n--- Log format ---');
|
|
151
|
+
|
|
152
|
+
runTest('Log format should include timestamp, level, and message', () => {
|
|
153
|
+
// Simulate the writeToAgentLog format
|
|
154
|
+
const ts = new Date().toISOString();
|
|
155
|
+
const level = "[LOG]";
|
|
156
|
+
const msg = "test message";
|
|
157
|
+
const line = "[" + ts + "] " + level + " " + msg + "\n";
|
|
158
|
+
|
|
159
|
+
assertContains(line, "[LOG]", 'contains level');
|
|
160
|
+
assertContains(line, "test message", 'contains message');
|
|
161
|
+
assertContains(line, "T", 'contains ISO timestamp T separator');
|
|
162
|
+
if (!line.endsWith("\n")) {
|
|
163
|
+
throw new Error('log line should end with newline');
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
runTest('Debug log format should include [agent] prefix', () => {
|
|
168
|
+
const ts = new Date().toISOString();
|
|
169
|
+
const msg = "Starting iteration 1";
|
|
170
|
+
const line = "[" + ts + "] [agent] " + msg + "\n";
|
|
171
|
+
|
|
172
|
+
assertContains(line, "[agent]", 'contains agent prefix');
|
|
173
|
+
assertContains(line, "Starting iteration 1", 'contains message');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// ============================================================================
|
|
177
|
+
// Test: Actual file I/O (write and read log files)
|
|
178
|
+
// ============================================================================
|
|
179
|
+
console.log('\n--- File I/O ---');
|
|
180
|
+
|
|
181
|
+
runTest('Should create log directory and write pave.log', () => {
|
|
182
|
+
const tmpDir = path.join(os.tmpdir(), 'pave-test-log-' + Date.now());
|
|
183
|
+
try {
|
|
184
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
185
|
+
const logFile = path.join(tmpDir, 'pave.log');
|
|
186
|
+
fs.appendFileSync(logFile, "[2026-01-01T00:00:00.000Z] [LOG] test log entry\n");
|
|
187
|
+
fs.appendFileSync(logFile, "[2026-01-01T00:00:01.000Z] [INF] second entry\n");
|
|
188
|
+
const content = fs.readFileSync(logFile, 'utf8');
|
|
189
|
+
assertContains(content, 'second entry', 'log file contains entry');
|
|
190
|
+
// Cleanup
|
|
191
|
+
try { fs.unlinkSync(logFile); fs.rmdirSync(tmpDir); } catch (e) { /* ignore */ }
|
|
192
|
+
} catch (e) {
|
|
193
|
+
if (e.message && e.message.indexOf('not a function') >= 0) {
|
|
194
|
+
throw new Error('SKIP: fs.mkdirSync not available in sandbox');
|
|
195
|
+
}
|
|
196
|
+
throw e;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
runTest('Should write debug.log when debug is enabled', () => {
|
|
201
|
+
const tmpDir = path.join(os.tmpdir(), 'pave-test-debug-' + Date.now());
|
|
202
|
+
try {
|
|
203
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
204
|
+
const debugLog = path.join(tmpDir, 'debug.log');
|
|
205
|
+
const ts = new Date().toISOString();
|
|
206
|
+
fs.appendFileSync(debugLog, "[" + ts + "] [agent] Starting iteration 1\n");
|
|
207
|
+
fs.appendFileSync(debugLog, "[" + ts + "] [exit] agent cleanup called\n");
|
|
208
|
+
|
|
209
|
+
const content = fs.readFileSync(debugLog, 'utf8');
|
|
210
|
+
assertContains(content, '[agent] Starting iteration 1', 'debug log agent entry');
|
|
211
|
+
assertContains(content, '[exit] agent cleanup called', 'debug log exit entry');
|
|
212
|
+
// Cleanup
|
|
213
|
+
try { fs.unlinkSync(debugLog); fs.rmdirSync(tmpDir); } catch (e) { /* ignore */ }
|
|
214
|
+
} catch (e) {
|
|
215
|
+
if (e.message && e.message.indexOf('not a function') >= 0) {
|
|
216
|
+
throw new Error('SKIP: fs.mkdirSync not available in sandbox');
|
|
217
|
+
}
|
|
218
|
+
throw e;
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
runTest('Should write session.json to .pave/ directory (#174)', () => {
|
|
223
|
+
const tmpDir = path.join(os.tmpdir(), 'pave-test-session-' + Date.now());
|
|
224
|
+
try {
|
|
225
|
+
const configDir = path.join(tmpDir, '.pave');
|
|
226
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
227
|
+
// Session file goes in .pave/ directory
|
|
228
|
+
const sessionFile = path.join(configDir, 'session.json');
|
|
229
|
+
fs.writeFileSync(sessionFile, JSON.stringify({ sessionId: 'test-123', agentName: 'test' }, null, 2));
|
|
230
|
+
|
|
231
|
+
const data = JSON.parse(fs.readFileSync(sessionFile, 'utf8'));
|
|
232
|
+
assertEqual(data.sessionId, 'test-123', 'session ID');
|
|
233
|
+
assertEqual(data.agentName, 'test', 'agent name');
|
|
234
|
+
// Verify session file IS inside the .pave subdirectory
|
|
235
|
+
assertEqual(path.basename(path.dirname(sessionFile)), '.pave', 'in .pave subdir');
|
|
236
|
+
// Cleanup
|
|
237
|
+
try { fs.unlinkSync(sessionFile); fs.rmdirSync(configDir); fs.rmdirSync(tmpDir); } catch (e) { /* ignore */ }
|
|
238
|
+
} catch (e) {
|
|
239
|
+
if (e.message && e.message.indexOf('not a function') >= 0) {
|
|
240
|
+
throw new Error('SKIP: fs.mkdirSync not available in sandbox');
|
|
241
|
+
}
|
|
242
|
+
throw e;
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// ============================================================================
|
|
247
|
+
// Test: Source code verification
|
|
248
|
+
// ============================================================================
|
|
249
|
+
console.log('\n--- Source code verification ---');
|
|
250
|
+
|
|
251
|
+
runTest('handleAgentCommand should reference AGENT_LOG_DIR and pave.log', () => {
|
|
252
|
+
try {
|
|
253
|
+
const source = fs.readFileSync(path.join(__dirname, '..', 'index.js'), 'utf8');
|
|
254
|
+
assertContains(source, 'AGENT_LOG_DIR', 'source contains AGENT_LOG_DIR');
|
|
255
|
+
assertContains(source, 'AGENT_LOG_FILE', 'source contains AGENT_LOG_FILE');
|
|
256
|
+
assertContains(source, "pave.log", 'source references pave.log');
|
|
257
|
+
assertContains(source, 'agentLogStream', 'source contains agentLogStream');
|
|
258
|
+
} catch (e) {
|
|
259
|
+
if (e.code === 'ENOENT') {
|
|
260
|
+
throw new Error('Could not read index.js for verification');
|
|
261
|
+
}
|
|
262
|
+
throw e;
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
runTest('handleAgentCommand should reference DEBUG_LOG_FILE and debug.log', () => {
|
|
267
|
+
try {
|
|
268
|
+
const source = fs.readFileSync(path.join(__dirname, '..', 'index.js'), 'utf8');
|
|
269
|
+
assertContains(source, 'DEBUG_LOG_FILE', 'source contains DEBUG_LOG_FILE');
|
|
270
|
+
assertContains(source, "debug.log", 'source references debug.log');
|
|
271
|
+
assertContains(source, 'debugLog(', 'source contains debugLog helper calls');
|
|
272
|
+
assertContains(source, 'debugEnabled', 'source contains debugEnabled check');
|
|
273
|
+
} catch (e) {
|
|
274
|
+
if (e.code === 'ENOENT') {
|
|
275
|
+
throw new Error('Could not read index.js for verification');
|
|
276
|
+
}
|
|
277
|
+
throw e;
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Helper: extract the full body of handleAgentCommand by brace matching
|
|
282
|
+
function extractHandleAgentCommand(source) {
|
|
283
|
+
const funcStart = source.indexOf('async function handleAgentCommand');
|
|
284
|
+
if (funcStart < 0) throw new Error('handleAgentCommand not found in source');
|
|
285
|
+
// Find the opening brace of the function
|
|
286
|
+
const braceStart = source.indexOf('{', funcStart);
|
|
287
|
+
if (braceStart < 0) throw new Error('Could not find opening brace of handleAgentCommand');
|
|
288
|
+
let depth = 0;
|
|
289
|
+
let end = braceStart;
|
|
290
|
+
for (let i = braceStart; i < source.length; i++) {
|
|
291
|
+
if (source[i] === '{') depth++;
|
|
292
|
+
else if (source[i] === '}') {
|
|
293
|
+
depth--;
|
|
294
|
+
if (depth === 0) { end = i + 1; break; }
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return source.substring(funcStart, end);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
runTest('handleAgentCommand should NOT use crypto for session hash', () => {
|
|
301
|
+
try {
|
|
302
|
+
const source = fs.readFileSync(path.join(__dirname, '..', 'index.js'), 'utf8');
|
|
303
|
+
const agentBody = extractHandleAgentCommand(source);
|
|
304
|
+
// Remove comments before checking for crypto
|
|
305
|
+
const codeOnly = agentBody.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '');
|
|
306
|
+
if (codeOnly.indexOf("require(\"crypto\")") >= 0 || codeOnly.indexOf("require('crypto')") >= 0) {
|
|
307
|
+
throw new Error('handleAgentCommand should not require crypto (session hash removed)');
|
|
308
|
+
}
|
|
309
|
+
} catch (e) {
|
|
310
|
+
if (e.message && (e.message.indexOf('handleAgentCommand') >= 0 || e.message.indexOf('crypto') >= 0)) throw e;
|
|
311
|
+
if (e.code === 'ENOENT') throw new Error('Could not read index.js');
|
|
312
|
+
throw e;
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
runTest('Session file should use resolveSessionFile not agent-session-*.json', () => {
|
|
317
|
+
try {
|
|
318
|
+
const source = fs.readFileSync(path.join(__dirname, '..', 'index.js'), 'utf8');
|
|
319
|
+
const agentBody = extractHandleAgentCommand(source);
|
|
320
|
+
|
|
321
|
+
// Check that resolveSessionFile is used
|
|
322
|
+
assertContains(agentBody, 'resolveSessionFile', 'uses resolveSessionFile');
|
|
323
|
+
|
|
324
|
+
// Check that agent-session-*.json is NOT used in code (only in comments)
|
|
325
|
+
const codeOnly = agentBody.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '');
|
|
326
|
+
if (codeOnly.indexOf('agent-session-') >= 0) {
|
|
327
|
+
throw new Error('Should not reference agent-session-*.json pattern in code');
|
|
328
|
+
}
|
|
329
|
+
} catch (e) {
|
|
330
|
+
if (e.message && (e.message.indexOf('agent-session') >= 0 || e.message.indexOf('resolveSessionFile') >= 0 || e.message.indexOf('handleAgentCommand') >= 0)) throw e;
|
|
331
|
+
if (e.code === 'ENOENT') throw new Error('Could not read index.js');
|
|
332
|
+
throw e;
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// ============================================================================
|
|
337
|
+
// Summary
|
|
338
|
+
// ============================================================================
|
|
339
|
+
console.log('\n=== Results: ' + passed + ' passed, ' + failed + ' failed ===\n');
|
|
340
|
+
if (failed > 0) process.exitCode = 1;
|
|
341
|
+
|
|
342
|
+
// Export for run-tests.js integration
|
|
343
|
+
if (typeof module !== 'undefined') {
|
|
344
|
+
module.exports = {
|
|
345
|
+
runAgentLogTests() {
|
|
346
|
+
return { passed, failed, total: passed + failed };
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
}
|