@bash0816/claude-code 2.1.228 → 2.1.232
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/README.md
CHANGED
|
@@ -679,7 +679,25 @@
|
|
|
679
679
|
"entry_end_offset": 297826425,
|
|
680
680
|
"tarball_integrity": "sha512-rWSzUqON6kyIXUVz9KDU+9R6FdO11IVCO94D7kkWWyRPzFqzaAB80RmfgP//QgTIVFApEUzEUH2tfAGsUhD6ug==",
|
|
681
681
|
"tarball_sha256": "31295a318aef235b1b818a8b46982757467fb4d13030520ac66d16a58c0d7e27",
|
|
682
|
-
"status": "
|
|
682
|
+
"status": "termux_verified"
|
|
683
|
+
},
|
|
684
|
+
"2.1.231": {
|
|
685
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.231",
|
|
686
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.231",
|
|
687
|
+
"entry_js_offset": 273809585,
|
|
688
|
+
"entry_end_offset": 299210420,
|
|
689
|
+
"tarball_integrity": "sha512-a0YGXTjk6N5yRWE30dkbtS0tTZ5hOEXFCjTTX2slSa7XULMlJJLQ1X8oFJwpXmlvZu9FHx1YRLKJnni05uNIQQ==",
|
|
690
|
+
"tarball_sha256": "f50fa4b2270707208a3ae870deae8c562ec6b2f4d7bf778fca6275d13908b714",
|
|
691
|
+
"status": "termux_verified"
|
|
692
|
+
},
|
|
693
|
+
"2.1.232": {
|
|
694
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.232",
|
|
695
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.232",
|
|
696
|
+
"entry_js_offset": 284086193,
|
|
697
|
+
"entry_end_offset": 310581163,
|
|
698
|
+
"tarball_integrity": "sha512-5Aub8i5pjCVlDBP/tIpHwO/8owfNBu2+FP+w0U8Jmy9s6cEhg/HB7Nyp9KyADhN74w6t0TVGvzUdnFXVMANI4Q==",
|
|
699
|
+
"tarball_sha256": "97322189ff3c884e86d2ba2981d21c9874ca78261a8bff65a4ef6f673ef98fa6",
|
|
700
|
+
"status": "termux_verified"
|
|
683
701
|
}
|
|
684
702
|
}
|
|
685
703
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 1,
|
|
3
3
|
"package_name": "@bash0816/claude-code",
|
|
4
|
-
"latest_audited_version": "2.1.
|
|
5
|
-
"latest_candidate_version": "2.1.
|
|
6
|
-
"previous_stable_version": "2.1.
|
|
4
|
+
"latest_audited_version": "2.1.232",
|
|
5
|
+
"latest_candidate_version": "2.1.232",
|
|
6
|
+
"previous_stable_version": "2.1.231",
|
|
7
7
|
"stable_pinned_version": "2.1.220-2",
|
|
8
8
|
"manifest_url": "https://raw.githubusercontent.com/bash0816/ClaudeCode-Termux/main/config/claude-termux-release-manifest.json"
|
|
9
9
|
}
|
|
@@ -599,6 +599,7 @@ function rewriteNativeChunkSource(source) {
|
|
|
599
599
|
const _bunPropertyAccessExpected = (() => {
|
|
600
600
|
const _ver = String(process.env.CURRENT_CLAUDE_VERSION || '');
|
|
601
601
|
const _m = _ver.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
602
|
+
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 232)) return 45;
|
|
602
603
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 224)) return 44;
|
|
603
604
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 223)) return 43;
|
|
604
605
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 219)) return 42;
|
|
@@ -680,6 +681,58 @@ async function main() {
|
|
|
680
681
|
}
|
|
681
682
|
const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
|
|
682
683
|
|
|
684
|
+
function installPlainTextWriteWatcher() {
|
|
685
|
+
const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
|
|
686
|
+
const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
|
|
687
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
688
|
+
let foundOutput = false;
|
|
689
|
+
let resultPromiseResolve = null;
|
|
690
|
+
let restored = false;
|
|
691
|
+
|
|
692
|
+
process.stdout.write = function wrappedWrite(chunk, encoding, callback) {
|
|
693
|
+
let cb = callback;
|
|
694
|
+
let enc = encoding;
|
|
695
|
+
if (typeof encoding === 'function') {
|
|
696
|
+
cb = encoding;
|
|
697
|
+
enc = undefined;
|
|
698
|
+
}
|
|
699
|
+
const combinedCallback = (err) => {
|
|
700
|
+
if (!err && !foundOutput) {
|
|
701
|
+
const len = typeof chunk === 'string'
|
|
702
|
+
? Buffer.byteLength(chunk, typeof enc === 'string' ? enc : 'utf8')
|
|
703
|
+
: (Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(String(chunk ?? ''), 'utf8'));
|
|
704
|
+
if (len > 0) {
|
|
705
|
+
foundOutput = true;
|
|
706
|
+
if (typeof resultPromiseResolve === 'function') resultPromiseResolve();
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
if (typeof cb === 'function') cb(err);
|
|
710
|
+
};
|
|
711
|
+
return originalWrite(chunk, enc, combinedCallback);
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
return {
|
|
715
|
+
waitForResult() {
|
|
716
|
+
if (foundOutput) return Promise.resolve();
|
|
717
|
+
return new Promise((resolve) => {
|
|
718
|
+
resultPromiseResolve = resolve;
|
|
719
|
+
});
|
|
720
|
+
},
|
|
721
|
+
hasOutput() {
|
|
722
|
+
return foundOutput;
|
|
723
|
+
},
|
|
724
|
+
restore() {
|
|
725
|
+
if (restored) return;
|
|
726
|
+
restored = true;
|
|
727
|
+
if (hadOwnWrite) {
|
|
728
|
+
Object.defineProperty(process.stdout, 'write', originalWriteDescriptor);
|
|
729
|
+
} else {
|
|
730
|
+
delete process.stdout.write;
|
|
731
|
+
}
|
|
732
|
+
},
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
|
|
683
736
|
function installStreamJsonTerminalWatcher() {
|
|
684
737
|
const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
|
|
685
738
|
const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
|
|
@@ -768,6 +821,25 @@ async function main() {
|
|
|
768
821
|
}
|
|
769
822
|
return;
|
|
770
823
|
}
|
|
824
|
+
if (streamJsonWatcher && typeof streamJsonWatcher.hasOutput === 'function') {
|
|
825
|
+
if (streamJsonWatcher.hasOutput()) {
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
const gatingExitCode = process.exitCode;
|
|
829
|
+
const rawResultTimeoutMs = Number(process.env.CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS);
|
|
830
|
+
const extendedTimeoutMs = (Number.isFinite(rawResultTimeoutMs) && rawResultTimeoutMs > 0) ? rawResultTimeoutMs : 300000;
|
|
831
|
+
const noOutputTimeoutMs = (gatingExitCode !== undefined && gatingExitCode !== 0) ? printWaitMs : extendedTimeoutMs;
|
|
832
|
+
let timeoutHandle;
|
|
833
|
+
const timeoutPromise = new Promise(resolve => {
|
|
834
|
+
timeoutHandle = setTimeout(resolve, noOutputTimeoutMs);
|
|
835
|
+
});
|
|
836
|
+
try {
|
|
837
|
+
await Promise.race([streamJsonWatcher.waitForResult(), timeoutPromise]);
|
|
838
|
+
} finally {
|
|
839
|
+
clearTimeout(timeoutHandle);
|
|
840
|
+
}
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
771
843
|
if (Number.isFinite(printWaitMs) && printWaitMs > 0) {
|
|
772
844
|
await new Promise(resolve => setTimeout(resolve, printWaitMs));
|
|
773
845
|
}
|
|
@@ -882,6 +954,8 @@ async function main() {
|
|
|
882
954
|
|
|
883
955
|
if (isStreamJsonPrintMode(argv)) {
|
|
884
956
|
streamJsonWatcher = installStreamJsonTerminalWatcher();
|
|
957
|
+
} else {
|
|
958
|
+
streamJsonWatcher = installPlainTextWriteWatcher();
|
|
885
959
|
}
|
|
886
960
|
|
|
887
961
|
const moduleLike = { exports: {} };
|
|
@@ -1481,6 +1555,7 @@ function rewriteNativeChunkSource(source) {
|
|
|
1481
1555
|
const _bunPropertyAccessExpected = (() => {
|
|
1482
1556
|
const _ver = String(process.env.CURRENT_CLAUDE_VERSION || '');
|
|
1483
1557
|
const _m = _ver.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
1558
|
+
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 232)) return 45;
|
|
1484
1559
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 224)) return 44;
|
|
1485
1560
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 223)) return 43;
|
|
1486
1561
|
if (_m && (Number(_m[1]) > 2 || Number(_m[2]) > 1 || Number(_m[3]) >= 219)) return 42;
|
|
@@ -1561,6 +1636,58 @@ async function main() {
|
|
|
1561
1636
|
asyncErrors.push(error);
|
|
1562
1637
|
}
|
|
1563
1638
|
|
|
1639
|
+
function installPlainTextWriteWatcher() {
|
|
1640
|
+
const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
|
|
1641
|
+
const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
|
|
1642
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
1643
|
+
let foundOutput = false;
|
|
1644
|
+
let resultPromiseResolve = null;
|
|
1645
|
+
let restored = false;
|
|
1646
|
+
|
|
1647
|
+
process.stdout.write = function wrappedWrite(chunk, encoding, callback) {
|
|
1648
|
+
let cb = callback;
|
|
1649
|
+
let enc = encoding;
|
|
1650
|
+
if (typeof encoding === 'function') {
|
|
1651
|
+
cb = encoding;
|
|
1652
|
+
enc = undefined;
|
|
1653
|
+
}
|
|
1654
|
+
const combinedCallback = (err) => {
|
|
1655
|
+
if (!err && !foundOutput) {
|
|
1656
|
+
const len = typeof chunk === 'string'
|
|
1657
|
+
? Buffer.byteLength(chunk, typeof enc === 'string' ? enc : 'utf8')
|
|
1658
|
+
: (Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(String(chunk ?? ''), 'utf8'));
|
|
1659
|
+
if (len > 0) {
|
|
1660
|
+
foundOutput = true;
|
|
1661
|
+
if (typeof resultPromiseResolve === 'function') resultPromiseResolve();
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
if (typeof cb === 'function') cb(err);
|
|
1665
|
+
};
|
|
1666
|
+
return originalWrite(chunk, enc, combinedCallback);
|
|
1667
|
+
};
|
|
1668
|
+
|
|
1669
|
+
return {
|
|
1670
|
+
waitForResult() {
|
|
1671
|
+
if (foundOutput) return Promise.resolve();
|
|
1672
|
+
return new Promise((resolve) => {
|
|
1673
|
+
resultPromiseResolve = resolve;
|
|
1674
|
+
});
|
|
1675
|
+
},
|
|
1676
|
+
hasOutput() {
|
|
1677
|
+
return foundOutput;
|
|
1678
|
+
},
|
|
1679
|
+
restore() {
|
|
1680
|
+
if (restored) return;
|
|
1681
|
+
restored = true;
|
|
1682
|
+
if (hadOwnWrite) {
|
|
1683
|
+
Object.defineProperty(process.stdout, 'write', originalWriteDescriptor);
|
|
1684
|
+
} else {
|
|
1685
|
+
delete process.stdout.write;
|
|
1686
|
+
}
|
|
1687
|
+
},
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1564
1691
|
function installStreamJsonTerminalWatcher() {
|
|
1565
1692
|
const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
|
|
1566
1693
|
const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
|
|
@@ -1650,6 +1777,26 @@ async function main() {
|
|
|
1650
1777
|
}
|
|
1651
1778
|
return;
|
|
1652
1779
|
}
|
|
1780
|
+
if (streamJsonWatcher && typeof streamJsonWatcher.hasOutput === 'function') {
|
|
1781
|
+
if (streamJsonWatcher.hasOutput()) {
|
|
1782
|
+
return;
|
|
1783
|
+
}
|
|
1784
|
+
const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
|
|
1785
|
+
const gatingExitCode = process.exitCode;
|
|
1786
|
+
const rawResultTimeoutMs = Number(process.env.CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS);
|
|
1787
|
+
const extendedTimeoutMs = (Number.isFinite(rawResultTimeoutMs) && rawResultTimeoutMs > 0) ? rawResultTimeoutMs : 300000;
|
|
1788
|
+
const noOutputTimeoutMs = (gatingExitCode !== undefined && gatingExitCode !== 0) ? printWaitMs : extendedTimeoutMs;
|
|
1789
|
+
let timeoutHandle;
|
|
1790
|
+
const timeoutPromise = new Promise(resolve => {
|
|
1791
|
+
timeoutHandle = setTimeout(resolve, noOutputTimeoutMs);
|
|
1792
|
+
});
|
|
1793
|
+
try {
|
|
1794
|
+
await Promise.race([streamJsonWatcher.waitForResult(), timeoutPromise]);
|
|
1795
|
+
} finally {
|
|
1796
|
+
clearTimeout(timeoutHandle);
|
|
1797
|
+
}
|
|
1798
|
+
return;
|
|
1799
|
+
}
|
|
1653
1800
|
const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
|
|
1654
1801
|
if (Number.isFinite(printWaitMs) && printWaitMs > 0) {
|
|
1655
1802
|
await new Promise(resolve => setTimeout(resolve, printWaitMs));
|
|
@@ -1765,6 +1912,8 @@ async function main() {
|
|
|
1765
1912
|
|
|
1766
1913
|
if (isStreamJsonPrintMode(argv)) {
|
|
1767
1914
|
streamJsonWatcher = installStreamJsonTerminalWatcher();
|
|
1915
|
+
} else if (process.env.CLAUDE_TERMUX_PRINT_MODE === '1') {
|
|
1916
|
+
streamJsonWatcher = installPlainTextWriteWatcher();
|
|
1768
1917
|
}
|
|
1769
1918
|
|
|
1770
1919
|
const moduleLike = { exports: {} };
|
|
@@ -605,6 +605,43 @@ test('rewriteNativeChunkSource rejects stale Bun property access count for versi
|
|
|
605
605
|
}
|
|
606
606
|
});
|
|
607
607
|
|
|
608
|
+
test('rewriteNativeChunkSource rewrites the synthetic bundle slice (version 2.1.232)', () => {
|
|
609
|
+
process.env.CURRENT_CLAUDE_VERSION = '2.1.232';
|
|
610
|
+
try {
|
|
611
|
+
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
612
|
+
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
613
|
+
const bunProps = Array.from({ length: 45 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
614
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
615
|
+
const patched = rewriteNativeChunkSource(source);
|
|
616
|
+
|
|
617
|
+
assert.match(patched, /var __claudeBun = globalThis\.__claudeBunShim;/);
|
|
618
|
+
assert.match(patched, /typeof __claudeBun/);
|
|
619
|
+
assert.match(patched, /typeof globalThis\.__claudeBun/);
|
|
620
|
+
assert.match(patched, /globalThis\.__claudeBun/);
|
|
621
|
+
assert.match(patched, /__claudeBun\./);
|
|
622
|
+
assert.equal((patched.match(/__claudeBun\./g) || []).length, 45);
|
|
623
|
+
} finally {
|
|
624
|
+
delete process.env.CURRENT_CLAUDE_VERSION;
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
test('rewriteNativeChunkSource rejects stale Bun property access count for version 2.1.232', () => {
|
|
629
|
+
process.env.CURRENT_CLAUDE_VERSION = '2.1.232';
|
|
630
|
+
try {
|
|
631
|
+
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
632
|
+
const typeofBun = Array.from({ length: 7 }, () => 'typeof Bun').join('; ');
|
|
633
|
+
const bunProps = Array.from({ length: 44 }, (_, index) => `Bun.p${index}`).join('; ');
|
|
634
|
+
const source = `function(exports, require, module, __filename, __dirname) { ${typeofBun}; typeof globalThis.Bun; globalThis.Bun; ${bunProps}; npmInstallDeprecated:!0; npmInstallDeprecated:!0; function dYs(){return(e,t,r)=>{let{cmd:n,prefixArgs:o}=ox({pinToCurrentBinary:!0}),i=[n,...o,"--bg-pty-host",r.ptySock];return i}} }`;
|
|
635
|
+
|
|
636
|
+
assert.throws(
|
|
637
|
+
() => rewriteNativeChunkSource(source),
|
|
638
|
+
/unexpected Bun property access count 44/,
|
|
639
|
+
);
|
|
640
|
+
} finally {
|
|
641
|
+
delete process.env.CURRENT_CLAUDE_VERSION;
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
|
|
608
645
|
test('rewriteNativeChunkSource rejects unexpected replacement counts', () => {
|
|
609
646
|
const { rewriteNativeChunkSource } = loadHelperApi();
|
|
610
647
|
const source = buildSyntheticBundleSource().replace('Bun.p30;', '');
|
|
@@ -709,11 +746,22 @@ function buildScenarioFixtureSource() {
|
|
|
709
746
|
process.exit(0);
|
|
710
747
|
return;
|
|
711
748
|
}
|
|
749
|
+
if (scenario === 'plain-late-write') {
|
|
750
|
+
setTimeout(() => { process.stdout.write('late-output'); }, 800);
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
if (scenario === 'plain-no-output-error') {
|
|
754
|
+
process.exitCode = 1;
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
if (scenario === 'plain-no-output-success') {
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
712
760
|
process.stdout.write('ok');
|
|
713
761
|
}`;
|
|
714
762
|
}
|
|
715
763
|
|
|
716
|
-
function runScenario({ printMode, stdinInherit, scenario, extraArgs }) {
|
|
764
|
+
function runScenario({ printMode, stdinInherit, scenario, extraArgs, extraEnv }) {
|
|
717
765
|
const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'claude-stdin-test-'));
|
|
718
766
|
const sourceBin = path.join(tmpBase, 'fake-source.js');
|
|
719
767
|
const fixtureSource = buildScenarioFixtureSource();
|
|
@@ -735,6 +783,7 @@ function runScenario({ printMode, stdinInherit, scenario, extraArgs }) {
|
|
|
735
783
|
CLAUDE_TERMUX_PRINT_WAIT_MS: '300',
|
|
736
784
|
TMPDIR: tmpBase,
|
|
737
785
|
TEST_SCENARIO: scenario,
|
|
786
|
+
...(extraEnv || {}),
|
|
738
787
|
};
|
|
739
788
|
if (stdinInherit) env.CLAUDE_TERMUX_STDIN = 'inherit';
|
|
740
789
|
else delete env.CLAUDE_TERMUX_STDIN;
|
|
@@ -808,15 +857,82 @@ test('bootstrap branch (-p + CLAUDE_TERMUX_STDIN=inherit): normal/sync-exit/asyn
|
|
|
808
857
|
try {
|
|
809
858
|
assert.ok((r.stdout || '').includes('ok'), `scenario=${scenario} stdout=${r.stdout} stderr=${r.stderr}`);
|
|
810
859
|
assert.equal(r.status, 0, `scenario=${scenario} status=${r.status} stderr=${r.stderr}`);
|
|
811
|
-
if (scenario === 'async-exit') {
|
|
812
|
-
assert.ok(r.elapsedMs >= 250, `expected wait >= 250ms, got ${r.elapsedMs}ms`);
|
|
813
|
-
}
|
|
814
860
|
} finally {
|
|
815
861
|
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
816
862
|
}
|
|
817
863
|
}
|
|
818
864
|
});
|
|
819
865
|
|
|
866
|
+
test('helper branch plain mode waits for late write beyond default printWaitMs', () => {
|
|
867
|
+
const r = runScenario({ printMode: true, stdinInherit: false, scenario: 'plain-late-write' });
|
|
868
|
+
try {
|
|
869
|
+
assert.ok((r.stdout || '').includes('late-output'), `stdout=${r.stdout} stderr=${r.stderr}`);
|
|
870
|
+
assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
|
|
871
|
+
} finally {
|
|
872
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
test('bootstrap branch plain mode waits for late write beyond default printWaitMs', () => {
|
|
877
|
+
const r = runScenario({ printMode: true, stdinInherit: true, scenario: 'plain-late-write' });
|
|
878
|
+
try {
|
|
879
|
+
assert.ok((r.stdout || '').includes('late-output'), `stdout=${r.stdout} stderr=${r.stderr}`);
|
|
880
|
+
assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
|
|
881
|
+
} finally {
|
|
882
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
|
|
886
|
+
test('helper branch plain mode with no output and non-zero exitCode exits promptly (no extended wait)', () => {
|
|
887
|
+
const r = runScenario({ printMode: true, stdinInherit: false, scenario: 'plain-no-output-error' });
|
|
888
|
+
try {
|
|
889
|
+
assert.equal(r.status, 1, `status=${r.status} stderr=${r.stderr}`);
|
|
890
|
+
assert.ok(r.elapsedMs < 5000, `expected prompt exit, got elapsedMs=${r.elapsedMs}`);
|
|
891
|
+
} finally {
|
|
892
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
893
|
+
}
|
|
894
|
+
});
|
|
895
|
+
|
|
896
|
+
test('bootstrap branch plain mode with no output and non-zero exitCode exits promptly (no extended wait)', () => {
|
|
897
|
+
const r = runScenario({ printMode: true, stdinInherit: true, scenario: 'plain-no-output-error' });
|
|
898
|
+
try {
|
|
899
|
+
assert.equal(r.status, 1, `status=${r.status} stderr=${r.stderr}`);
|
|
900
|
+
assert.ok(r.elapsedMs < 5000, `expected prompt exit, got elapsedMs=${r.elapsedMs}`);
|
|
901
|
+
} finally {
|
|
902
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
903
|
+
}
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
test('helper branch plain mode with no output and successful exit waits up to configured ceiling', () => {
|
|
907
|
+
const r = runScenario({
|
|
908
|
+
printMode: true,
|
|
909
|
+
stdinInherit: false,
|
|
910
|
+
scenario: 'plain-no-output-success',
|
|
911
|
+
extraEnv: { CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS: '400' },
|
|
912
|
+
});
|
|
913
|
+
try {
|
|
914
|
+
assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
|
|
915
|
+
assert.ok(r.elapsedMs >= 350, `expected extended wait close to 400ms ceiling, got elapsedMs=${r.elapsedMs}`);
|
|
916
|
+
} finally {
|
|
917
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
test('bootstrap branch plain mode with no output and successful exit waits up to configured ceiling', () => {
|
|
922
|
+
const r = runScenario({
|
|
923
|
+
printMode: true,
|
|
924
|
+
stdinInherit: true,
|
|
925
|
+
scenario: 'plain-no-output-success',
|
|
926
|
+
extraEnv: { CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS: '400' },
|
|
927
|
+
});
|
|
928
|
+
try {
|
|
929
|
+
assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
|
|
930
|
+
assert.ok(r.elapsedMs >= 350, `expected extended wait close to 400ms ceiling, got elapsedMs=${r.elapsedMs}`);
|
|
931
|
+
} finally {
|
|
932
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
|
|
820
936
|
test('helper branch intercepts self-directed SIGKILL (string signal) and exits with proper code', () => {
|
|
821
937
|
const r = runScenario({ printMode: true, stdinInherit: false, scenario: 'self-sigkill-fallback-string' });
|
|
822
938
|
try {
|
|
@@ -1075,6 +1191,31 @@ test('helper and bootstrap installStreamJsonTerminalWatcher helpers stay identic
|
|
|
1075
1191
|
assert.equal(helperWatcher, bootstrapWatcher, 'installStreamJsonTerminalWatcher must be identical in both heredocs');
|
|
1076
1192
|
});
|
|
1077
1193
|
|
|
1194
|
+
test('helper and bootstrap installPlainTextWriteWatcher helpers stay identical', () => {
|
|
1195
|
+
const helperBlock = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1196
|
+
const bootstrapBlock = extractBlock('cat <<\'NODE\' > "$_bootstrap"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1197
|
+
|
|
1198
|
+
const extractFn = (block) => {
|
|
1199
|
+
const startMarker = 'function installPlainTextWriteWatcher() {';
|
|
1200
|
+
const start = block.indexOf(startMarker);
|
|
1201
|
+
assert.ok(start > -1, 'installPlainTextWriteWatcher function not found');
|
|
1202
|
+
let depth = 0;
|
|
1203
|
+
let i = start + startMarker.length - 1;
|
|
1204
|
+
for (; i < block.length; i++) {
|
|
1205
|
+
if (block[i] === '{') depth++;
|
|
1206
|
+
if (block[i] === '}') {
|
|
1207
|
+
depth--;
|
|
1208
|
+
if (depth === 0) break;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
return block.slice(start, i + 1);
|
|
1212
|
+
};
|
|
1213
|
+
|
|
1214
|
+
const helperFn = extractFn(helperBlock);
|
|
1215
|
+
const bootstrapFn = extractFn(bootstrapBlock);
|
|
1216
|
+
assert.equal(helperFn, bootstrapFn, 'installPlainTextWriteWatcher must be identical in helper and bootstrap');
|
|
1217
|
+
});
|
|
1218
|
+
|
|
1078
1219
|
test('helper and bootstrap forceTimeoutExit helpers stay identical', () => {
|
|
1079
1220
|
const helperBlock = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1080
1221
|
const bootstrapBlock = extractBlock('cat <<\'NODE\' > "$_bootstrap"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|