@vibelet/cli 0.1.34 → 0.1.36
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/app.json +5 -0
- package/dist/advertised-hosts.d.ts +34 -0
- package/dist/advertised-hosts.d.ts.map +1 -0
- package/dist/advertised-hosts.js +176 -0
- package/dist/advertised-hosts.js.map +1 -0
- package/dist/advertised-hosts.test.d.ts +2 -0
- package/dist/advertised-hosts.test.d.ts.map +1 -0
- package/dist/advertised-hosts.test.js +96 -0
- package/dist/advertised-hosts.test.js.map +1 -0
- package/dist/audit.d.ts +30 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +73 -0
- package/dist/audit.js.map +1 -0
- package/dist/audit.test.d.ts +2 -0
- package/dist/audit.test.d.ts.map +1 -0
- package/dist/audit.test.js +33 -0
- package/dist/audit.test.js.map +1 -0
- package/dist/auth.d.ts +6 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +27 -0
- package/dist/auth.js.map +1 -0
- package/dist/claude-hooks.d.ts +58 -0
- package/dist/claude-hooks.d.ts.map +1 -0
- package/dist/claude-hooks.js +129 -0
- package/dist/claude-hooks.js.map +1 -0
- package/dist/cli-version.d.ts +3 -0
- package/dist/cli-version.d.ts.map +1 -0
- package/dist/cli-version.js +35 -0
- package/dist/cli-version.js.map +1 -0
- package/dist/cli-version.test.d.ts +2 -0
- package/dist/cli-version.test.d.ts.map +1 -0
- package/dist/cli-version.test.js +38 -0
- package/dist/cli-version.test.js.map +1 -0
- package/dist/config.d.ts +30 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +327 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +184 -0
- package/dist/config.test.js.map +1 -0
- package/dist/dev-auth.test.d.ts +2 -0
- package/dist/dev-auth.test.d.ts.map +1 -0
- package/dist/dev-auth.test.js +154 -0
- package/dist/dev-auth.test.js.map +1 -0
- package/dist/dev-script.test.d.ts +2 -0
- package/dist/dev-script.test.d.ts.map +1 -0
- package/dist/dev-script.test.js +412 -0
- package/dist/dev-script.test.js.map +1 -0
- package/dist/drivers/claude.d.ts +34 -0
- package/dist/drivers/claude.d.ts.map +1 -0
- package/dist/drivers/claude.js +413 -0
- package/dist/drivers/claude.js.map +1 -0
- package/dist/drivers/claude.test.d.ts +2 -0
- package/dist/drivers/claude.test.d.ts.map +1 -0
- package/dist/drivers/claude.test.js +951 -0
- package/dist/drivers/claude.test.js.map +1 -0
- package/dist/drivers/codex.d.ts +38 -0
- package/dist/drivers/codex.d.ts.map +1 -0
- package/dist/drivers/codex.js +771 -0
- package/dist/drivers/codex.js.map +1 -0
- package/dist/drivers/codex.test.d.ts +2 -0
- package/dist/drivers/codex.test.d.ts.map +1 -0
- package/dist/drivers/codex.test.js +939 -0
- package/dist/drivers/codex.test.js.map +1 -0
- package/dist/drivers/types.d.ts +14 -0
- package/dist/drivers/types.d.ts.map +1 -0
- package/dist/drivers/types.js +2 -0
- package/dist/drivers/types.js.map +1 -0
- package/dist/e2e.test.d.ts +2 -0
- package/dist/e2e.test.d.ts.map +1 -0
- package/dist/e2e.test.js +111 -0
- package/dist/e2e.test.js.map +1 -0
- package/dist/identity.d.ts +10 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +66 -0
- package/dist/identity.js.map +1 -0
- package/dist/identity.test.d.ts +2 -0
- package/dist/identity.test.d.ts.map +1 -0
- package/dist/identity.test.js +25 -0
- package/dist/identity.test.js.map +1 -0
- package/dist/index-entry.test.d.ts +2 -0
- package/dist/index-entry.test.d.ts.map +1 -0
- package/dist/index-entry.test.js +272 -0
- package/dist/index-entry.test.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +707 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +31 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +75 -0
- package/dist/logger.js.map +1 -0
- package/dist/metrics.d.ts +52 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +89 -0
- package/dist/metrics.js.map +1 -0
- package/dist/pairing-store.d.ts +29 -0
- package/dist/pairing-store.d.ts.map +1 -0
- package/dist/pairing-store.js +131 -0
- package/dist/pairing-store.js.map +1 -0
- package/dist/pairing-store.test.d.ts +2 -0
- package/dist/pairing-store.test.d.ts.map +1 -0
- package/dist/pairing-store.test.js +47 -0
- package/dist/pairing-store.test.js.map +1 -0
- package/dist/paths.d.ts +16 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +18 -0
- package/dist/paths.js.map +1 -0
- package/dist/perf-compare.d.ts +13 -0
- package/dist/perf-compare.d.ts.map +1 -0
- package/dist/perf-compare.js +125 -0
- package/dist/perf-compare.js.map +1 -0
- package/dist/port-conflict.d.ts +9 -0
- package/dist/port-conflict.d.ts.map +1 -0
- package/dist/port-conflict.js +33 -0
- package/dist/port-conflict.js.map +1 -0
- package/dist/port-conflict.test.d.ts +2 -0
- package/dist/port-conflict.test.d.ts.map +1 -0
- package/dist/port-conflict.test.js +38 -0
- package/dist/port-conflict.test.js.map +1 -0
- package/dist/process-scanner.d.ts +43 -0
- package/dist/process-scanner.d.ts.map +1 -0
- package/dist/process-scanner.js +453 -0
- package/dist/process-scanner.js.map +1 -0
- package/dist/process-scanner.perf.test.d.ts +2 -0
- package/dist/process-scanner.perf.test.d.ts.map +1 -0
- package/dist/process-scanner.perf.test.js +186 -0
- package/dist/process-scanner.perf.test.js.map +1 -0
- package/dist/process-scanner.test.d.ts +2 -0
- package/dist/process-scanner.test.d.ts.map +1 -0
- package/dist/process-scanner.test.js +399 -0
- package/dist/process-scanner.test.js.map +1 -0
- package/dist/push-protocol.d.ts +15 -0
- package/dist/push-protocol.d.ts.map +1 -0
- package/dist/push-protocol.js +23 -0
- package/dist/push-protocol.js.map +1 -0
- package/dist/push-protocol.test.d.ts +2 -0
- package/dist/push-protocol.test.d.ts.map +1 -0
- package/dist/push-protocol.test.js +57 -0
- package/dist/push-protocol.test.js.map +1 -0
- package/dist/push-store.d.ts +22 -0
- package/dist/push-store.d.ts.map +1 -0
- package/dist/push-store.js +103 -0
- package/dist/push-store.js.map +1 -0
- package/dist/push-store.test.d.ts +2 -0
- package/dist/push-store.test.d.ts.map +1 -0
- package/dist/push-store.test.js +79 -0
- package/dist/push-store.test.js.map +1 -0
- package/dist/push.d.ts +65 -0
- package/dist/push.d.ts.map +1 -0
- package/dist/push.js +202 -0
- package/dist/push.js.map +1 -0
- package/dist/push.test.d.ts +2 -0
- package/dist/push.test.d.ts.map +1 -0
- package/dist/push.test.js +199 -0
- package/dist/push.test.js.map +1 -0
- package/dist/safe-stdio.d.ts +3 -0
- package/dist/safe-stdio.d.ts.map +1 -0
- package/dist/safe-stdio.js +46 -0
- package/dist/safe-stdio.js.map +1 -0
- package/dist/scanner.d.ts +30 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +859 -0
- package/dist/scanner.js.map +1 -0
- package/dist/scanner.perf.test.d.ts +2 -0
- package/dist/scanner.perf.test.d.ts.map +1 -0
- package/dist/scanner.perf.test.js +320 -0
- package/dist/scanner.perf.test.js.map +1 -0
- package/dist/scanner.test.d.ts +2 -0
- package/dist/scanner.test.d.ts.map +1 -0
- package/dist/scanner.test.js +948 -0
- package/dist/scanner.test.js.map +1 -0
- package/dist/session-inventory.d.ts +63 -0
- package/dist/session-inventory.d.ts.map +1 -0
- package/dist/session-inventory.js +525 -0
- package/dist/session-inventory.js.map +1 -0
- package/dist/session-inventory.perf.test.d.ts +2 -0
- package/dist/session-inventory.perf.test.d.ts.map +1 -0
- package/dist/session-inventory.perf.test.js +220 -0
- package/dist/session-inventory.perf.test.js.map +1 -0
- package/dist/session-inventory.test.d.ts +2 -0
- package/dist/session-inventory.test.d.ts.map +1 -0
- package/dist/session-inventory.test.js +712 -0
- package/dist/session-inventory.test.js.map +1 -0
- package/dist/session-manager.d.ts +75 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +1515 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/session-manager.test.d.ts +2 -0
- package/dist/session-manager.test.d.ts.map +1 -0
- package/dist/session-manager.test.js +2861 -0
- package/dist/session-manager.test.js.map +1 -0
- package/dist/session-store.d.ts +42 -0
- package/dist/session-store.d.ts.map +1 -0
- package/dist/session-store.js +163 -0
- package/dist/session-store.js.map +1 -0
- package/dist/session-store.test.d.ts +2 -0
- package/dist/session-store.test.d.ts.map +1 -0
- package/dist/session-store.test.js +236 -0
- package/dist/session-store.test.js.map +1 -0
- package/dist/session-title.d.ts +6 -0
- package/dist/session-title.d.ts.map +1 -0
- package/dist/session-title.js +105 -0
- package/dist/session-title.js.map +1 -0
- package/dist/session-title.perf.test.d.ts +2 -0
- package/dist/session-title.perf.test.d.ts.map +1 -0
- package/dist/session-title.perf.test.js +99 -0
- package/dist/session-title.perf.test.js.map +1 -0
- package/dist/session-title.test.d.ts +2 -0
- package/dist/session-title.test.d.ts.map +1 -0
- package/dist/session-title.test.js +199 -0
- package/dist/session-title.test.js.map +1 -0
- package/dist/shutdown-endpoint.test.d.ts +2 -0
- package/dist/shutdown-endpoint.test.d.ts.map +1 -0
- package/dist/shutdown-endpoint.test.js +93 -0
- package/dist/shutdown-endpoint.test.js.map +1 -0
- package/dist/storage-housekeeping.d.ts +28 -0
- package/dist/storage-housekeeping.d.ts.map +1 -0
- package/dist/storage-housekeeping.js +76 -0
- package/dist/storage-housekeeping.js.map +1 -0
- package/dist/storage-housekeeping.test.d.ts +2 -0
- package/dist/storage-housekeeping.test.d.ts.map +1 -0
- package/dist/storage-housekeeping.test.js +65 -0
- package/dist/storage-housekeeping.test.js.map +1 -0
- package/dist/test-daemon-harness.d.ts +31 -0
- package/dist/test-daemon-harness.d.ts.map +1 -0
- package/dist/test-daemon-harness.js +337 -0
- package/dist/test-daemon-harness.js.map +1 -0
- package/dist/token-auth.test.d.ts +2 -0
- package/dist/token-auth.test.d.ts.map +1 -0
- package/dist/token-auth.test.js +52 -0
- package/dist/token-auth.test.js.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +40 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.test.d.ts +2 -0
- package/dist/utils.test.d.ts.map +1 -0
- package/dist/utils.test.js +54 -0
- package/dist/utils.test.js.map +1 -0
- package/dist/ws-data.d.ts +4 -0
- package/dist/ws-data.d.ts.map +1 -0
- package/dist/ws-data.js +20 -0
- package/dist/ws-data.js.map +1 -0
- package/dist/ws-data.test.d.ts +2 -0
- package/dist/ws-data.test.d.ts.map +1 -0
- package/dist/ws-data.test.js +17 -0
- package/dist/ws-data.test.js.map +1 -0
- package/package.json +24 -27
- package/perf-reporter.mjs +138 -0
- package/scripts/build-release.mjs +41 -0
- package/scripts/dev.mjs +537 -0
- package/src/advertised-hosts.test.ts +125 -0
- package/src/advertised-hosts.ts +225 -0
- package/src/audit.test.ts +38 -0
- package/src/audit.ts +117 -0
- package/src/auth.ts +31 -0
- package/src/claude-hooks.ts +195 -0
- package/src/cli-version.test.ts +36 -0
- package/src/cli-version.ts +46 -0
- package/src/config.test.ts +254 -0
- package/src/config.ts +324 -0
- package/src/dev-auth.test.ts +183 -0
- package/src/dev-script.test.ts +511 -0
- package/src/drivers/claude.test.ts +1186 -0
- package/src/drivers/claude.ts +443 -0
- package/src/drivers/codex.test.ts +1096 -0
- package/src/drivers/codex.ts +879 -0
- package/src/drivers/types.ts +15 -0
- package/src/e2e.test.ts +139 -0
- package/src/identity.test.ts +26 -0
- package/src/identity.ts +82 -0
- package/src/index-entry.test.ts +336 -0
- package/src/index.ts +781 -0
- package/src/logger.ts +112 -0
- package/src/metrics.ts +117 -0
- package/src/pairing-store.test.ts +53 -0
- package/src/pairing-store.ts +154 -0
- package/src/paths.ts +19 -0
- package/src/perf-compare.ts +164 -0
- package/src/port-conflict.test.ts +45 -0
- package/src/port-conflict.ts +44 -0
- package/src/process-scanner.perf.test.ts +222 -0
- package/src/process-scanner.test.ts +575 -0
- package/src/process-scanner.ts +514 -0
- package/src/push-protocol.test.ts +74 -0
- package/src/push-protocol.ts +36 -0
- package/src/push-store.test.ts +89 -0
- package/src/push-store.ts +126 -0
- package/src/push.test.ts +234 -0
- package/src/push.ts +318 -0
- package/src/safe-stdio.ts +51 -0
- package/src/scanner.perf.test.ts +359 -0
- package/src/scanner.test.ts +1045 -0
- package/src/scanner.ts +924 -0
- package/src/session-inventory.perf.test.ts +250 -0
- package/src/session-inventory.test.ts +1002 -0
- package/src/session-inventory.ts +721 -0
- package/src/session-manager.test.ts +3430 -0
- package/src/session-manager.ts +1775 -0
- package/src/session-store.test.ts +276 -0
- package/src/session-store.ts +202 -0
- package/src/session-title.perf.test.ts +118 -0
- package/src/session-title.test.ts +286 -0
- package/src/session-title.ts +108 -0
- package/src/shutdown-endpoint.test.ts +95 -0
- package/src/storage-housekeeping.test.ts +78 -0
- package/src/storage-housekeeping.ts +111 -0
- package/src/test-daemon-harness.ts +410 -0
- package/src/token-auth.test.ts +67 -0
- package/src/utils.test.ts +65 -0
- package/src/utils.ts +47 -0
- package/src/ws-data.test.ts +20 -0
- package/src/ws-data.ts +26 -0
- package/tsconfig.json +12 -0
- package/README.md +0 -80
- package/bin/cloudflared-quick-tunnel.mjs +0 -11
- package/bin/cloudflared-resolver.mjs +0 -68
- package/bin/vibelet-runtime-policy.mjs +0 -36
- package/bin/vibelet.cjs +0 -12
- package/bin/vibelet.mjs +0 -1019
- package/dist/index.cjs +0 -123
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { homedir } from 'os';
|
|
6
|
+
import { isTransientPath, buildSanitizedEnv, execViaLoginShell, config } from './config.js';
|
|
7
|
+
|
|
8
|
+
const configModuleUrl = new URL('./config.ts', import.meta.url).href;
|
|
9
|
+
|
|
10
|
+
function buildChildEnv(overrides: Record<string, string | undefined>): NodeJS.ProcessEnv {
|
|
11
|
+
const nextEnv: NodeJS.ProcessEnv = { ...process.env };
|
|
12
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
13
|
+
if (value === undefined) {
|
|
14
|
+
delete nextEnv[key];
|
|
15
|
+
} else {
|
|
16
|
+
nextEnv[key] = value;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return nextEnv;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function readConfigValueInIsolatedProcess(
|
|
23
|
+
overrides: Record<string, string | undefined>,
|
|
24
|
+
expression: string,
|
|
25
|
+
): string {
|
|
26
|
+
return execFileSync(
|
|
27
|
+
process.execPath,
|
|
28
|
+
[
|
|
29
|
+
'--import',
|
|
30
|
+
'tsx',
|
|
31
|
+
'-e',
|
|
32
|
+
`import { config } from ${JSON.stringify(configModuleUrl)}; process.stdout.write(String(${expression}));`,
|
|
33
|
+
],
|
|
34
|
+
{
|
|
35
|
+
env: buildChildEnv(overrides),
|
|
36
|
+
encoding: 'utf8',
|
|
37
|
+
},
|
|
38
|
+
).trim();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
test('isTransientPath: detects fnm_multishells as transient', () => {
|
|
42
|
+
assert.equal(isTransientPath('/tmp/fnm_multishells/12345/bin/codex'), true);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('isTransientPath: returns false for normal paths', () => {
|
|
46
|
+
assert.equal(isTransientPath('/usr/local/bin/codex'), false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('isTransientPath: returns false for home directory paths', () => {
|
|
50
|
+
assert.equal(isTransientPath('/Users/test/.local/bin/claude'), false);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('isTransientPath: returns false for empty string', () => {
|
|
54
|
+
assert.equal(isTransientPath(''), false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// buildSanitizedEnv tests
|
|
58
|
+
|
|
59
|
+
test('buildSanitizedEnv: returns an object with PATH key', () => {
|
|
60
|
+
const env = buildSanitizedEnv();
|
|
61
|
+
assert.ok('PATH' in env);
|
|
62
|
+
assert.equal(typeof env.PATH, 'string');
|
|
63
|
+
assert.ok(env.PATH.length > 0);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('buildSanitizedEnv: PATH includes extra directories', () => {
|
|
67
|
+
const env = buildSanitizedEnv();
|
|
68
|
+
assert.ok(env.PATH.includes('/usr/local/bin'));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('buildSanitizedEnv: HOME is set', () => {
|
|
72
|
+
const env = buildSanitizedEnv();
|
|
73
|
+
assert.ok('HOME' in env);
|
|
74
|
+
assert.equal(typeof env.HOME, 'string');
|
|
75
|
+
assert.ok(env.HOME.length > 0);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('buildSanitizedEnv: CLAUDE_CODE_ENTRYPOINT is removed', () => {
|
|
79
|
+
process.env.CLAUDE_CODE_ENTRYPOINT = 'test_value';
|
|
80
|
+
const env = buildSanitizedEnv();
|
|
81
|
+
assert.equal(env.CLAUDE_CODE_ENTRYPOINT, undefined);
|
|
82
|
+
delete process.env.CLAUDE_CODE_ENTRYPOINT;
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('buildSanitizedEnv: CLAUDECODE is removed', () => {
|
|
86
|
+
process.env.CLAUDECODE = 'test_value';
|
|
87
|
+
const env = buildSanitizedEnv();
|
|
88
|
+
assert.equal(env.CLAUDECODE, undefined);
|
|
89
|
+
delete process.env.CLAUDECODE;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('buildSanitizedEnv: contains process.env values', () => {
|
|
93
|
+
const testKey = 'VIBE_TEST_UNIQUE_KEY_' + Date.now();
|
|
94
|
+
process.env[testKey] = 'test_value_123';
|
|
95
|
+
const env = buildSanitizedEnv();
|
|
96
|
+
assert.equal(env[testKey], 'test_value_123');
|
|
97
|
+
delete process.env[testKey];
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// execViaLoginShell tests
|
|
101
|
+
|
|
102
|
+
test('execViaLoginShell: returns correct command (a shell path)', () => {
|
|
103
|
+
const result = execViaLoginShell('claude', ['--help']);
|
|
104
|
+
assert.equal(typeof result.command, 'string');
|
|
105
|
+
assert.ok(result.command.startsWith('/'));
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('execViaLoginShell: args contain -lc flag', () => {
|
|
109
|
+
const result = execViaLoginShell('claude', ['--help']);
|
|
110
|
+
assert.equal(result.args[0], '-lc');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('execViaLoginShell: includes the passed cmd in the shell command string', () => {
|
|
114
|
+
const result = execViaLoginShell('claude', ['--help', '--verbose']);
|
|
115
|
+
assert.ok(result.args[1].includes('claude'));
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test('execViaLoginShell: includes the passed args after -- separator', () => {
|
|
119
|
+
const result = execViaLoginShell('claude', ['--help', '--verbose']);
|
|
120
|
+
const dashDashIndex = result.args.indexOf('--');
|
|
121
|
+
assert.ok(dashDashIndex >= 0);
|
|
122
|
+
assert.equal(result.args[dashDashIndex + 1], '--help');
|
|
123
|
+
assert.equal(result.args[dashDashIndex + 2], '--verbose');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// config object tests
|
|
127
|
+
|
|
128
|
+
test('config.port: defaults to 9876 when VIBE_PORT not set', () => {
|
|
129
|
+
assert.equal(config.port, 9876);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test('config.legacyToken: defaults to an empty string', () => {
|
|
133
|
+
assert.equal(config.legacyToken, '');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('config.legacyToken: respects VIBE_TOKEN env override on fresh import', async () => {
|
|
137
|
+
const original = process.env.VIBE_TOKEN;
|
|
138
|
+
process.env.VIBE_TOKEN = 'legacy-secret';
|
|
139
|
+
try {
|
|
140
|
+
const freshModule = await import(`./config.ts?test=${Date.now()}`);
|
|
141
|
+
assert.equal(freshModule.config.legacyToken, 'legacy-secret');
|
|
142
|
+
} finally {
|
|
143
|
+
if (original == null) {
|
|
144
|
+
delete process.env.VIBE_TOKEN;
|
|
145
|
+
} else {
|
|
146
|
+
process.env.VIBE_TOKEN = original;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('config.idleTimeoutMs: allows disabling idle sweep with 0', () => {
|
|
152
|
+
assert.equal(
|
|
153
|
+
readConfigValueInIsolatedProcess(
|
|
154
|
+
{ VIBE_IDLE_TIMEOUT_MS: '0' },
|
|
155
|
+
'config.idleTimeoutMs',
|
|
156
|
+
),
|
|
157
|
+
'0',
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('config.turnStallTimeoutMs: defaults to 5 minutes', () => {
|
|
162
|
+
assert.equal(config.turnStallTimeoutMs, 5 * 60 * 1000);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test('config.turnStallTimeoutMs: allows disabling stall sweep with 0', () => {
|
|
166
|
+
assert.equal(
|
|
167
|
+
readConfigValueInIsolatedProcess(
|
|
168
|
+
{ VIBE_TURN_STALL_TIMEOUT_MS: '0' },
|
|
169
|
+
'config.turnStallTimeoutMs',
|
|
170
|
+
),
|
|
171
|
+
'0',
|
|
172
|
+
);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test('config.turnStallTimeoutMs: respects env override on fresh import', () => {
|
|
176
|
+
assert.equal(
|
|
177
|
+
readConfigValueInIsolatedProcess(
|
|
178
|
+
{ VIBE_TURN_STALL_TIMEOUT_MS: '120000' },
|
|
179
|
+
'config.turnStallTimeoutMs',
|
|
180
|
+
),
|
|
181
|
+
'120000',
|
|
182
|
+
);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('config.isTransientPath: is the isTransientPath function', () => {
|
|
186
|
+
assert.equal(config.isTransientPath, isTransientPath);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test('config.buildSanitizedEnv: is the buildSanitizedEnv function', () => {
|
|
190
|
+
assert.equal(config.buildSanitizedEnv, buildSanitizedEnv);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Binary detection / cached resolver tests
|
|
194
|
+
|
|
195
|
+
test('config.claudePath: returns a path string', () => {
|
|
196
|
+
// This may resolve to a real path or fall back to 'claude'
|
|
197
|
+
const path = config.claudePath;
|
|
198
|
+
assert.equal(typeof path, 'string');
|
|
199
|
+
assert.ok(path.length > 0);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test('config.codexPath: returns a path string', () => {
|
|
203
|
+
const path = config.codexPath;
|
|
204
|
+
assert.equal(typeof path, 'string');
|
|
205
|
+
assert.ok(path.length > 0);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test('config.claudePath: respects CLAUDE_PATH env override', () => {
|
|
209
|
+
assert.equal(
|
|
210
|
+
readConfigValueInIsolatedProcess(
|
|
211
|
+
{ CLAUDE_PATH: '/custom/path/to/claude' },
|
|
212
|
+
'config.claudePath',
|
|
213
|
+
),
|
|
214
|
+
'/custom/path/to/claude',
|
|
215
|
+
);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test('config.codexPath: respects CODEX_PATH env override', () => {
|
|
219
|
+
assert.equal(
|
|
220
|
+
readConfigValueInIsolatedProcess(
|
|
221
|
+
{ CODEX_PATH: '/custom/path/to/codex' },
|
|
222
|
+
'config.codexPath',
|
|
223
|
+
),
|
|
224
|
+
'/custom/path/to/codex',
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test('buildSanitizedEnv: PATH includes all required extra directories', () => {
|
|
229
|
+
const env = buildSanitizedEnv();
|
|
230
|
+
const home = homedir();
|
|
231
|
+
const requiredDirs = [
|
|
232
|
+
'/usr/local/bin',
|
|
233
|
+
'/opt/homebrew/bin',
|
|
234
|
+
join(home, '.npm-global', 'bin'),
|
|
235
|
+
join(home, '.local', 'bin'),
|
|
236
|
+
join(home, '.claude', 'bin'),
|
|
237
|
+
];
|
|
238
|
+
for (const dir of requiredDirs) {
|
|
239
|
+
assert.ok(env.PATH.includes(dir), `PATH should include ${dir}`);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test('buildSanitizedEnv: includes home-relative paths', () => {
|
|
244
|
+
const env = buildSanitizedEnv();
|
|
245
|
+
const home = homedir();
|
|
246
|
+
assert.ok(env.PATH.includes(join(home, '.local', 'bin')) || env.PATH.includes('.local/bin'));
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test('execViaLoginShell: works with codex command', () => {
|
|
250
|
+
const result = execViaLoginShell('codex', ['app-server', '--listen', 'stdio://']);
|
|
251
|
+
assert.ok(result.args[1].includes('codex'));
|
|
252
|
+
const dashDashIndex = result.args.indexOf('--');
|
|
253
|
+
assert.equal(result.args[dashDashIndex + 1], 'app-server');
|
|
254
|
+
});
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { join, delimiter } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
import { logger as rootLogger } from './logger.js';
|
|
6
|
+
|
|
7
|
+
const TRANSIENT_PATH_MARKERS = ['fnm_multishells'];
|
|
8
|
+
const CACHE_TTL = 60_000;
|
|
9
|
+
const IS_WIN32 = process.platform === 'win32';
|
|
10
|
+
const log = rootLogger.child({ module: 'config' });
|
|
11
|
+
|
|
12
|
+
export function isTransientPath(p: string): boolean {
|
|
13
|
+
return TRANSIENT_PATH_MARKERS.some(marker => p.includes(marker));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getLoginShellCandidates(): string[] {
|
|
17
|
+
if (IS_WIN32) return []; // No login shell on Windows
|
|
18
|
+
return [process.env.SHELL, '/bin/zsh', '/bin/bash', '/bin/sh']
|
|
19
|
+
.filter((s): s is string => !!s)
|
|
20
|
+
.filter((s, i, a) => a.indexOf(s) === i);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ===== Shell Environment =====
|
|
24
|
+
|
|
25
|
+
let cachedShellEnv: Record<string, string> | null = null;
|
|
26
|
+
|
|
27
|
+
function loadUserShellEnv(): Record<string, string> {
|
|
28
|
+
if (cachedShellEnv && !isTransientPath(cachedShellEnv.PATH ?? '')) return cachedShellEnv;
|
|
29
|
+
|
|
30
|
+
for (const shell of getLoginShellCandidates()) {
|
|
31
|
+
try {
|
|
32
|
+
const result = execFileSync(shell, ['-ilc', 'env'], {
|
|
33
|
+
timeout: 5000, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'],
|
|
34
|
+
});
|
|
35
|
+
const env: Record<string, string> = {};
|
|
36
|
+
for (const line of result.split('\n')) {
|
|
37
|
+
const idx = line.indexOf('=');
|
|
38
|
+
if (idx > 0) env[line.slice(0, idx)] = line.slice(idx + 1);
|
|
39
|
+
}
|
|
40
|
+
if (!isTransientPath(env.PATH ?? '')) {
|
|
41
|
+
cachedShellEnv = env;
|
|
42
|
+
} else {
|
|
43
|
+
cachedShellEnv = null;
|
|
44
|
+
}
|
|
45
|
+
return env;
|
|
46
|
+
} catch { /* next */ }
|
|
47
|
+
}
|
|
48
|
+
cachedShellEnv = {};
|
|
49
|
+
return {};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getExpandedPath(shellEnv: Record<string, string> = loadUserShellEnv()): string {
|
|
53
|
+
const home = homedir();
|
|
54
|
+
const pnpmHome = shellEnv.PNPM_HOME || process.env.PNPM_HOME || (IS_WIN32 ? join(home, 'pnpm') : join(home, 'Library', 'pnpm'));
|
|
55
|
+
const basePath = shellEnv.PATH || process.env.PATH || '';
|
|
56
|
+
const extra = IS_WIN32
|
|
57
|
+
? [
|
|
58
|
+
join(home, '.npm-global', 'bin'),
|
|
59
|
+
join(home, '.local', 'bin'),
|
|
60
|
+
join(home, '.claude', 'bin'),
|
|
61
|
+
pnpmHome,
|
|
62
|
+
join(home, 'AppData', 'Roaming', 'npm'),
|
|
63
|
+
join(home, 'AppData', 'Local', 'Programs', 'node'),
|
|
64
|
+
]
|
|
65
|
+
: [
|
|
66
|
+
'/usr/local/bin', '/opt/homebrew/bin', '/usr/bin', '/bin',
|
|
67
|
+
join(home, '.npm-global', 'bin'),
|
|
68
|
+
join(home, '.local', 'bin'),
|
|
69
|
+
join(home, '.claude', 'bin'),
|
|
70
|
+
pnpmHome,
|
|
71
|
+
];
|
|
72
|
+
const current = basePath.split(delimiter).filter(Boolean);
|
|
73
|
+
const seen = new Set(current);
|
|
74
|
+
for (const p of extra) {
|
|
75
|
+
if (!seen.has(p)) { current.push(p); seen.add(p); }
|
|
76
|
+
}
|
|
77
|
+
return current.join(delimiter);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function getPositiveNumberEnv(name: string, fallback: number): number {
|
|
81
|
+
const raw = process.env[name];
|
|
82
|
+
if (!raw) return fallback;
|
|
83
|
+
const parsed = Number(raw);
|
|
84
|
+
return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : fallback;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function getNonNegativeNumberEnv(name: string, fallback: number): number {
|
|
88
|
+
const raw = process.env[name];
|
|
89
|
+
if (raw == null || raw === '') return fallback;
|
|
90
|
+
const parsed = Number(raw);
|
|
91
|
+
return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : fallback;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function buildSanitizedEnv(): Record<string, string> {
|
|
95
|
+
const shellEnv = loadUserShellEnv();
|
|
96
|
+
const merged: Record<string, string> = {};
|
|
97
|
+
for (const [k, v] of Object.entries(process.env)) {
|
|
98
|
+
if (typeof v === 'string') merged[k] = v;
|
|
99
|
+
}
|
|
100
|
+
for (const [k, v] of Object.entries(shellEnv)) {
|
|
101
|
+
if (typeof v === 'string') merged[k] = v;
|
|
102
|
+
}
|
|
103
|
+
merged.PATH = getExpandedPath(shellEnv);
|
|
104
|
+
if (!merged.HOME) merged.HOME = homedir();
|
|
105
|
+
delete merged.CLAUDE_CODE_ENTRYPOINT;
|
|
106
|
+
delete merged.CLAUDECODE;
|
|
107
|
+
return merged;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ===== Binary Detection =====
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* On Windows, resolve a bare command name like "codex" to its real executable
|
|
114
|
+
* path (e.g. codex.exe) using `where.exe`. This avoids the common issue where
|
|
115
|
+
* Node's `spawn('codex')` fails with ENOENT because it doesn't search PATH
|
|
116
|
+
* for `.cmd`/`.ps1`/`.exe` extensions the way PowerShell/cmd do.
|
|
117
|
+
*/
|
|
118
|
+
function resolveViaWhere(name: string): string | undefined {
|
|
119
|
+
if (!IS_WIN32) return undefined;
|
|
120
|
+
try {
|
|
121
|
+
const output = execFileSync('where.exe', [name], {
|
|
122
|
+
timeout: 3000, stdio: 'pipe', encoding: 'utf-8',
|
|
123
|
+
}).trim();
|
|
124
|
+
// `where` returns one result per line. Prefer .exe over .cmd/.ps1
|
|
125
|
+
const lines = output.split(/\r?\n/).filter(Boolean);
|
|
126
|
+
const exe = lines.find(l => l.endsWith('.exe'));
|
|
127
|
+
return exe ?? lines[0];
|
|
128
|
+
} catch { return undefined; }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function runVersionSync(binaryPath: string, timeout = 3000): string | null {
|
|
132
|
+
try {
|
|
133
|
+
return execFileSync(binaryPath, ['--version'], {
|
|
134
|
+
timeout, stdio: 'pipe', encoding: 'utf-8', env: buildSanitizedEnv(),
|
|
135
|
+
...(IS_WIN32 ? { shell: true } : {}),
|
|
136
|
+
}).trim() || null;
|
|
137
|
+
} catch { return null; }
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function runViaLoginShellSync(cmd: string, args: string[], timeout = 5000): string | null {
|
|
141
|
+
for (const shell of getLoginShellCandidates()) {
|
|
142
|
+
try {
|
|
143
|
+
return execFileSync(shell, ['-ilc', `command -v ${cmd} >/dev/null 2>&1 && exec ${cmd} "$@"`, '--', ...args], {
|
|
144
|
+
timeout, stdio: ['pipe', 'pipe', 'pipe'], encoding: 'utf-8',
|
|
145
|
+
}).trim() || null;
|
|
146
|
+
} catch { /* next */ }
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function findViaLoginShell(cmd: string): string | undefined {
|
|
152
|
+
for (const shell of getLoginShellCandidates()) {
|
|
153
|
+
try {
|
|
154
|
+
const result = execFileSync(shell, ['-ilc', `command -v ${cmd}`], {
|
|
155
|
+
timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'], encoding: 'utf-8',
|
|
156
|
+
}).trim();
|
|
157
|
+
if (result) return result;
|
|
158
|
+
} catch { /* next */ }
|
|
159
|
+
}
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ===== Claude Detection =====
|
|
164
|
+
|
|
165
|
+
function getClaudeCandidates(): string[] {
|
|
166
|
+
const home = homedir();
|
|
167
|
+
return [
|
|
168
|
+
join(home, '.local', 'bin', 'claude'),
|
|
169
|
+
join(home, '.claude', 'bin', 'claude'),
|
|
170
|
+
'/usr/local/bin/claude',
|
|
171
|
+
'/opt/homebrew/bin/claude',
|
|
172
|
+
join(home, '.npm-global', 'bin', 'claude'),
|
|
173
|
+
];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function findClaudeUncached(): string | undefined {
|
|
177
|
+
// On Windows, use `where.exe` instead of known Unix paths
|
|
178
|
+
if (IS_WIN32) {
|
|
179
|
+
const found = resolveViaWhere('claude');
|
|
180
|
+
if (found && runVersionSync(found)) return found;
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
// Check known paths
|
|
184
|
+
for (const p of getClaudeCandidates()) {
|
|
185
|
+
if (runVersionSync(p)) return p;
|
|
186
|
+
}
|
|
187
|
+
// which (with sanitized env that has expanded PATH)
|
|
188
|
+
try {
|
|
189
|
+
const result = execFileSync('/usr/bin/which', ['claude'], {
|
|
190
|
+
timeout: 3000, stdio: 'pipe', encoding: 'utf-8', env: buildSanitizedEnv(),
|
|
191
|
+
}).trim();
|
|
192
|
+
// Skip cmux wrappers
|
|
193
|
+
if (result && !result.includes('cmux') && runVersionSync(result)) return result;
|
|
194
|
+
} catch { /* not found */ }
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ===== Codex Detection =====
|
|
199
|
+
|
|
200
|
+
function getCodexCandidates(): string[] {
|
|
201
|
+
const home = homedir();
|
|
202
|
+
const pnpmHomes = [process.env.PNPM_HOME, join(home, 'Library', 'pnpm')]
|
|
203
|
+
.filter((p): p is string => !!p);
|
|
204
|
+
return [
|
|
205
|
+
'/usr/local/bin/codex',
|
|
206
|
+
'/opt/homebrew/bin/codex',
|
|
207
|
+
join(home, '.npm-global', 'bin', 'codex'),
|
|
208
|
+
join(home, '.local', 'bin', 'codex'),
|
|
209
|
+
...pnpmHomes.map(p => join(p, 'codex')),
|
|
210
|
+
];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function findCodexUncached(): string | undefined {
|
|
214
|
+
// On Windows, use `where.exe` to find the real executable
|
|
215
|
+
if (IS_WIN32) {
|
|
216
|
+
const found = resolveViaWhere('codex');
|
|
217
|
+
if (found && runVersionSync(found)) return found;
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
let transientFallback: string | undefined;
|
|
221
|
+
// Check known paths
|
|
222
|
+
for (const p of getCodexCandidates()) {
|
|
223
|
+
if (!runVersionSync(p)) continue;
|
|
224
|
+
if (!isTransientPath(p)) return p;
|
|
225
|
+
transientFallback = p;
|
|
226
|
+
}
|
|
227
|
+
// which with sanitized env
|
|
228
|
+
try {
|
|
229
|
+
const result = execFileSync('/usr/bin/which', ['codex'], {
|
|
230
|
+
timeout: 3000, stdio: 'pipe', encoding: 'utf-8', env: buildSanitizedEnv(),
|
|
231
|
+
}).trim();
|
|
232
|
+
if (result && runVersionSync(result)) {
|
|
233
|
+
if (!isTransientPath(result)) return result;
|
|
234
|
+
transientFallback = transientFallback ?? result;
|
|
235
|
+
}
|
|
236
|
+
} catch { /* not found */ }
|
|
237
|
+
// Login shell fallback
|
|
238
|
+
const found = findViaLoginShell('codex');
|
|
239
|
+
if (found && runVersionSync(found)) {
|
|
240
|
+
if (!isTransientPath(found)) return found;
|
|
241
|
+
transientFallback = transientFallback ?? found;
|
|
242
|
+
}
|
|
243
|
+
return transientFallback;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// ===== Cached Resolvers =====
|
|
247
|
+
|
|
248
|
+
function createCachedResolver(finder: () => string | undefined, name: string) {
|
|
249
|
+
let cached: string | null = null;
|
|
250
|
+
let timestamp = 0;
|
|
251
|
+
return (): string => {
|
|
252
|
+
const envKey = name === 'claude' ? 'CLAUDE_PATH' : 'CODEX_PATH';
|
|
253
|
+
if (process.env[envKey]) return process.env[envKey]!;
|
|
254
|
+
|
|
255
|
+
const now = Date.now();
|
|
256
|
+
// Re-resolve if expired, missing, or transient
|
|
257
|
+
if (!cached || now - timestamp > CACHE_TTL || !existsSync(cached) || isTransientPath(cached)) {
|
|
258
|
+
const found = finder();
|
|
259
|
+
cached = found ?? name;
|
|
260
|
+
timestamp = now;
|
|
261
|
+
log.info({ name, path: cached, transient: isTransientPath(cached) }, 'binary resolved');
|
|
262
|
+
}
|
|
263
|
+
return cached;
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const resolveClaude = createCachedResolver(findClaudeUncached, 'claude');
|
|
268
|
+
const resolveCodex = createCachedResolver(findCodexUncached, 'codex');
|
|
269
|
+
|
|
270
|
+
// ===== CLI Args =====
|
|
271
|
+
|
|
272
|
+
function parseCliArgs(): Record<string, string> {
|
|
273
|
+
const result: Record<string, string> = {};
|
|
274
|
+
const args = process.argv.slice(2);
|
|
275
|
+
for (let i = 0; i < args.length; i++) {
|
|
276
|
+
const arg = args[i];
|
|
277
|
+
if (arg.startsWith('--') && i + 1 < args.length) {
|
|
278
|
+
const key = arg.slice(2);
|
|
279
|
+
result[key] = args[++i];
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return result;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const cliArgs = parseCliArgs();
|
|
286
|
+
|
|
287
|
+
// ===== Export =====
|
|
288
|
+
|
|
289
|
+
export function execViaLoginShell(cmd: string, args: string[]): { command: string; args: string[] } {
|
|
290
|
+
if (IS_WIN32) {
|
|
291
|
+
// On Windows, resolve via where.exe and spawn directly
|
|
292
|
+
const resolved = resolveViaWhere(cmd);
|
|
293
|
+
return { command: resolved ?? cmd, args };
|
|
294
|
+
}
|
|
295
|
+
const shell = getLoginShellCandidates()[0] ?? '/bin/zsh';
|
|
296
|
+
return {
|
|
297
|
+
command: shell,
|
|
298
|
+
args: ['-lc', `command -v ${cmd} >/dev/null 2>&1 && exec ${cmd} "$@"`, '--', ...args],
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export const config = {
|
|
303
|
+
port: Number(process.env.VIBE_PORT) || 9876,
|
|
304
|
+
legacyToken: process.env.VIBE_TOKEN || '',
|
|
305
|
+
canonicalHost: cliArgs['host'] || process.env.VIBELET_CANONICAL_HOST || process.env.VIBELET_HOST || '',
|
|
306
|
+
fallbackHosts: cliArgs['fallback-hosts'] || process.env.VIBELET_FALLBACK_HOSTS || '',
|
|
307
|
+
/** Public relay URL (e.g. https://abc.trycloudflare.com). Overrides host/port in QR pairing payload. */
|
|
308
|
+
relayUrl: process.env.VIBELET_RELAY_URL || '',
|
|
309
|
+
/** Idle timeout in ms before a driver is automatically released. Default: 30 minutes. 0 = disabled. */
|
|
310
|
+
idleTimeoutMs: getNonNegativeNumberEnv('VIBE_IDLE_TIMEOUT_MS', 30 * 60 * 1000),
|
|
311
|
+
/** Maximum inactivity in ms for an in-flight turn before it is failed and the driver is stopped. 0 = disabled. */
|
|
312
|
+
turnStallTimeoutMs: getNonNegativeNumberEnv('VIBE_TURN_STALL_TIMEOUT_MS', 5 * 60 * 1000),
|
|
313
|
+
/** Maximum size for ~/.vibelet/data/audit.jsonl before it is trimmed in place. */
|
|
314
|
+
auditMaxBytes: getPositiveNumberEnv('VIBE_AUDIT_MAX_BYTES', 8 * 1024 * 1024),
|
|
315
|
+
/** Maximum size for each ~/.vibelet/logs/daemon.*.log file before it is trimmed in place. */
|
|
316
|
+
daemonLogMaxBytes: getPositiveNumberEnv('VIBE_DAEMON_LOG_MAX_BYTES', 16 * 1024 * 1024),
|
|
317
|
+
/** How often the daemon trims its own stdout/stderr logs. */
|
|
318
|
+
storageHousekeepingIntervalMs: getPositiveNumberEnv('VIBE_STORAGE_HOUSEKEEPING_INTERVAL_MS', 5 * 60 * 1000),
|
|
319
|
+
get claudePath() { return resolveClaude(); },
|
|
320
|
+
get codexPath() { return resolveCodex(); },
|
|
321
|
+
isTransientPath,
|
|
322
|
+
execViaLoginShell,
|
|
323
|
+
buildSanitizedEnv,
|
|
324
|
+
};
|