@bash0816/claude-code 2.1.227 → 2.1.231
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
|
@@ -670,6 +670,24 @@
|
|
|
670
670
|
"entry_end_offset": 293584486,
|
|
671
671
|
"tarball_integrity": "sha512-vqM0t4yu6X1ggUFlNE5Tcj8xpVxWkwuous/LEdVEEP3FKdA5NPoIUAIJC4zUPaqycTPeX8KLoXrZ1N8Qb413AA==",
|
|
672
672
|
"tarball_sha256": "865b9118c4b69c87fbb5cf83295703f88b044eba9fdf573c3926bfbae8216c60",
|
|
673
|
+
"status": "termux_verified"
|
|
674
|
+
},
|
|
675
|
+
"2.1.228": {
|
|
676
|
+
"wrapper_spec": "@anthropic-ai/claude-code@2.1.228",
|
|
677
|
+
"native_spec": "@anthropic-ai/claude-code-linux-arm64@2.1.228",
|
|
678
|
+
"entry_js_offset": 272828804,
|
|
679
|
+
"entry_end_offset": 297826425,
|
|
680
|
+
"tarball_integrity": "sha512-rWSzUqON6kyIXUVz9KDU+9R6FdO11IVCO94D7kkWWyRPzFqzaAB80RmfgP//QgTIVFApEUzEUH2tfAGsUhD6ug==",
|
|
681
|
+
"tarball_sha256": "31295a318aef235b1b818a8b46982757467fb4d13030520ac66d16a58c0d7e27",
|
|
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",
|
|
673
691
|
"status": "offset_discovered"
|
|
674
692
|
}
|
|
675
693
|
}
|
|
@@ -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.228",
|
|
5
|
+
"latest_candidate_version": "2.1.231",
|
|
6
|
+
"previous_stable_version": "2.1.227",
|
|
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
|
}
|
|
@@ -680,6 +680,58 @@ async function main() {
|
|
|
680
680
|
}
|
|
681
681
|
const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
|
|
682
682
|
|
|
683
|
+
function installPlainTextWriteWatcher() {
|
|
684
|
+
const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
|
|
685
|
+
const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
|
|
686
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
687
|
+
let foundOutput = false;
|
|
688
|
+
let resultPromiseResolve = null;
|
|
689
|
+
let restored = false;
|
|
690
|
+
|
|
691
|
+
process.stdout.write = function wrappedWrite(chunk, encoding, callback) {
|
|
692
|
+
let cb = callback;
|
|
693
|
+
let enc = encoding;
|
|
694
|
+
if (typeof encoding === 'function') {
|
|
695
|
+
cb = encoding;
|
|
696
|
+
enc = undefined;
|
|
697
|
+
}
|
|
698
|
+
const combinedCallback = (err) => {
|
|
699
|
+
if (!err && !foundOutput) {
|
|
700
|
+
const len = typeof chunk === 'string'
|
|
701
|
+
? Buffer.byteLength(chunk, typeof enc === 'string' ? enc : 'utf8')
|
|
702
|
+
: (Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(String(chunk ?? ''), 'utf8'));
|
|
703
|
+
if (len > 0) {
|
|
704
|
+
foundOutput = true;
|
|
705
|
+
if (typeof resultPromiseResolve === 'function') resultPromiseResolve();
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
if (typeof cb === 'function') cb(err);
|
|
709
|
+
};
|
|
710
|
+
return originalWrite(chunk, enc, combinedCallback);
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
return {
|
|
714
|
+
waitForResult() {
|
|
715
|
+
if (foundOutput) return Promise.resolve();
|
|
716
|
+
return new Promise((resolve) => {
|
|
717
|
+
resultPromiseResolve = resolve;
|
|
718
|
+
});
|
|
719
|
+
},
|
|
720
|
+
hasOutput() {
|
|
721
|
+
return foundOutput;
|
|
722
|
+
},
|
|
723
|
+
restore() {
|
|
724
|
+
if (restored) return;
|
|
725
|
+
restored = true;
|
|
726
|
+
if (hadOwnWrite) {
|
|
727
|
+
Object.defineProperty(process.stdout, 'write', originalWriteDescriptor);
|
|
728
|
+
} else {
|
|
729
|
+
delete process.stdout.write;
|
|
730
|
+
}
|
|
731
|
+
},
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
|
|
683
735
|
function installStreamJsonTerminalWatcher() {
|
|
684
736
|
const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
|
|
685
737
|
const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
|
|
@@ -768,6 +820,25 @@ async function main() {
|
|
|
768
820
|
}
|
|
769
821
|
return;
|
|
770
822
|
}
|
|
823
|
+
if (streamJsonWatcher && typeof streamJsonWatcher.hasOutput === 'function') {
|
|
824
|
+
if (streamJsonWatcher.hasOutput()) {
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
const gatingExitCode = process.exitCode;
|
|
828
|
+
const rawResultTimeoutMs = Number(process.env.CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS);
|
|
829
|
+
const extendedTimeoutMs = (Number.isFinite(rawResultTimeoutMs) && rawResultTimeoutMs > 0) ? rawResultTimeoutMs : 300000;
|
|
830
|
+
const noOutputTimeoutMs = (gatingExitCode !== undefined && gatingExitCode !== 0) ? printWaitMs : extendedTimeoutMs;
|
|
831
|
+
let timeoutHandle;
|
|
832
|
+
const timeoutPromise = new Promise(resolve => {
|
|
833
|
+
timeoutHandle = setTimeout(resolve, noOutputTimeoutMs);
|
|
834
|
+
});
|
|
835
|
+
try {
|
|
836
|
+
await Promise.race([streamJsonWatcher.waitForResult(), timeoutPromise]);
|
|
837
|
+
} finally {
|
|
838
|
+
clearTimeout(timeoutHandle);
|
|
839
|
+
}
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
771
842
|
if (Number.isFinite(printWaitMs) && printWaitMs > 0) {
|
|
772
843
|
await new Promise(resolve => setTimeout(resolve, printWaitMs));
|
|
773
844
|
}
|
|
@@ -882,6 +953,8 @@ async function main() {
|
|
|
882
953
|
|
|
883
954
|
if (isStreamJsonPrintMode(argv)) {
|
|
884
955
|
streamJsonWatcher = installStreamJsonTerminalWatcher();
|
|
956
|
+
} else {
|
|
957
|
+
streamJsonWatcher = installPlainTextWriteWatcher();
|
|
885
958
|
}
|
|
886
959
|
|
|
887
960
|
const moduleLike = { exports: {} };
|
|
@@ -1561,6 +1634,58 @@ async function main() {
|
|
|
1561
1634
|
asyncErrors.push(error);
|
|
1562
1635
|
}
|
|
1563
1636
|
|
|
1637
|
+
function installPlainTextWriteWatcher() {
|
|
1638
|
+
const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
|
|
1639
|
+
const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
|
|
1640
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
1641
|
+
let foundOutput = false;
|
|
1642
|
+
let resultPromiseResolve = null;
|
|
1643
|
+
let restored = false;
|
|
1644
|
+
|
|
1645
|
+
process.stdout.write = function wrappedWrite(chunk, encoding, callback) {
|
|
1646
|
+
let cb = callback;
|
|
1647
|
+
let enc = encoding;
|
|
1648
|
+
if (typeof encoding === 'function') {
|
|
1649
|
+
cb = encoding;
|
|
1650
|
+
enc = undefined;
|
|
1651
|
+
}
|
|
1652
|
+
const combinedCallback = (err) => {
|
|
1653
|
+
if (!err && !foundOutput) {
|
|
1654
|
+
const len = typeof chunk === 'string'
|
|
1655
|
+
? Buffer.byteLength(chunk, typeof enc === 'string' ? enc : 'utf8')
|
|
1656
|
+
: (Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(String(chunk ?? ''), 'utf8'));
|
|
1657
|
+
if (len > 0) {
|
|
1658
|
+
foundOutput = true;
|
|
1659
|
+
if (typeof resultPromiseResolve === 'function') resultPromiseResolve();
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
if (typeof cb === 'function') cb(err);
|
|
1663
|
+
};
|
|
1664
|
+
return originalWrite(chunk, enc, combinedCallback);
|
|
1665
|
+
};
|
|
1666
|
+
|
|
1667
|
+
return {
|
|
1668
|
+
waitForResult() {
|
|
1669
|
+
if (foundOutput) return Promise.resolve();
|
|
1670
|
+
return new Promise((resolve) => {
|
|
1671
|
+
resultPromiseResolve = resolve;
|
|
1672
|
+
});
|
|
1673
|
+
},
|
|
1674
|
+
hasOutput() {
|
|
1675
|
+
return foundOutput;
|
|
1676
|
+
},
|
|
1677
|
+
restore() {
|
|
1678
|
+
if (restored) return;
|
|
1679
|
+
restored = true;
|
|
1680
|
+
if (hadOwnWrite) {
|
|
1681
|
+
Object.defineProperty(process.stdout, 'write', originalWriteDescriptor);
|
|
1682
|
+
} else {
|
|
1683
|
+
delete process.stdout.write;
|
|
1684
|
+
}
|
|
1685
|
+
},
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1564
1689
|
function installStreamJsonTerminalWatcher() {
|
|
1565
1690
|
const hadOwnWrite = Object.prototype.hasOwnProperty.call(process.stdout, 'write');
|
|
1566
1691
|
const originalWriteDescriptor = hadOwnWrite ? Object.getOwnPropertyDescriptor(process.stdout, 'write') : undefined;
|
|
@@ -1650,6 +1775,26 @@ async function main() {
|
|
|
1650
1775
|
}
|
|
1651
1776
|
return;
|
|
1652
1777
|
}
|
|
1778
|
+
if (streamJsonWatcher && typeof streamJsonWatcher.hasOutput === 'function') {
|
|
1779
|
+
if (streamJsonWatcher.hasOutput()) {
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
|
|
1783
|
+
const gatingExitCode = process.exitCode;
|
|
1784
|
+
const rawResultTimeoutMs = Number(process.env.CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS);
|
|
1785
|
+
const extendedTimeoutMs = (Number.isFinite(rawResultTimeoutMs) && rawResultTimeoutMs > 0) ? rawResultTimeoutMs : 300000;
|
|
1786
|
+
const noOutputTimeoutMs = (gatingExitCode !== undefined && gatingExitCode !== 0) ? printWaitMs : extendedTimeoutMs;
|
|
1787
|
+
let timeoutHandle;
|
|
1788
|
+
const timeoutPromise = new Promise(resolve => {
|
|
1789
|
+
timeoutHandle = setTimeout(resolve, noOutputTimeoutMs);
|
|
1790
|
+
});
|
|
1791
|
+
try {
|
|
1792
|
+
await Promise.race([streamJsonWatcher.waitForResult(), timeoutPromise]);
|
|
1793
|
+
} finally {
|
|
1794
|
+
clearTimeout(timeoutHandle);
|
|
1795
|
+
}
|
|
1796
|
+
return;
|
|
1797
|
+
}
|
|
1653
1798
|
const printWaitMs = Number(process.env.CLAUDE_TERMUX_PRINT_WAIT_MS || 5000);
|
|
1654
1799
|
if (Number.isFinite(printWaitMs) && printWaitMs > 0) {
|
|
1655
1800
|
await new Promise(resolve => setTimeout(resolve, printWaitMs));
|
|
@@ -1765,6 +1910,8 @@ async function main() {
|
|
|
1765
1910
|
|
|
1766
1911
|
if (isStreamJsonPrintMode(argv)) {
|
|
1767
1912
|
streamJsonWatcher = installStreamJsonTerminalWatcher();
|
|
1913
|
+
} else if (process.env.CLAUDE_TERMUX_PRINT_MODE === '1') {
|
|
1914
|
+
streamJsonWatcher = installPlainTextWriteWatcher();
|
|
1768
1915
|
}
|
|
1769
1916
|
|
|
1770
1917
|
const moduleLike = { exports: {} };
|
|
@@ -709,11 +709,22 @@ function buildScenarioFixtureSource() {
|
|
|
709
709
|
process.exit(0);
|
|
710
710
|
return;
|
|
711
711
|
}
|
|
712
|
+
if (scenario === 'plain-late-write') {
|
|
713
|
+
setTimeout(() => { process.stdout.write('late-output'); }, 800);
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
if (scenario === 'plain-no-output-error') {
|
|
717
|
+
process.exitCode = 1;
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
if (scenario === 'plain-no-output-success') {
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
712
723
|
process.stdout.write('ok');
|
|
713
724
|
}`;
|
|
714
725
|
}
|
|
715
726
|
|
|
716
|
-
function runScenario({ printMode, stdinInherit, scenario, extraArgs }) {
|
|
727
|
+
function runScenario({ printMode, stdinInherit, scenario, extraArgs, extraEnv }) {
|
|
717
728
|
const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), 'claude-stdin-test-'));
|
|
718
729
|
const sourceBin = path.join(tmpBase, 'fake-source.js');
|
|
719
730
|
const fixtureSource = buildScenarioFixtureSource();
|
|
@@ -735,6 +746,7 @@ function runScenario({ printMode, stdinInherit, scenario, extraArgs }) {
|
|
|
735
746
|
CLAUDE_TERMUX_PRINT_WAIT_MS: '300',
|
|
736
747
|
TMPDIR: tmpBase,
|
|
737
748
|
TEST_SCENARIO: scenario,
|
|
749
|
+
...(extraEnv || {}),
|
|
738
750
|
};
|
|
739
751
|
if (stdinInherit) env.CLAUDE_TERMUX_STDIN = 'inherit';
|
|
740
752
|
else delete env.CLAUDE_TERMUX_STDIN;
|
|
@@ -808,15 +820,82 @@ test('bootstrap branch (-p + CLAUDE_TERMUX_STDIN=inherit): normal/sync-exit/asyn
|
|
|
808
820
|
try {
|
|
809
821
|
assert.ok((r.stdout || '').includes('ok'), `scenario=${scenario} stdout=${r.stdout} stderr=${r.stderr}`);
|
|
810
822
|
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
823
|
} finally {
|
|
815
824
|
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
816
825
|
}
|
|
817
826
|
}
|
|
818
827
|
});
|
|
819
828
|
|
|
829
|
+
test('helper branch plain mode waits for late write beyond default printWaitMs', () => {
|
|
830
|
+
const r = runScenario({ printMode: true, stdinInherit: false, scenario: 'plain-late-write' });
|
|
831
|
+
try {
|
|
832
|
+
assert.ok((r.stdout || '').includes('late-output'), `stdout=${r.stdout} stderr=${r.stderr}`);
|
|
833
|
+
assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
|
|
834
|
+
} finally {
|
|
835
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
test('bootstrap branch plain mode waits for late write beyond default printWaitMs', () => {
|
|
840
|
+
const r = runScenario({ printMode: true, stdinInherit: true, scenario: 'plain-late-write' });
|
|
841
|
+
try {
|
|
842
|
+
assert.ok((r.stdout || '').includes('late-output'), `stdout=${r.stdout} stderr=${r.stderr}`);
|
|
843
|
+
assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
|
|
844
|
+
} finally {
|
|
845
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
|
|
849
|
+
test('helper branch plain mode with no output and non-zero exitCode exits promptly (no extended wait)', () => {
|
|
850
|
+
const r = runScenario({ printMode: true, stdinInherit: false, scenario: 'plain-no-output-error' });
|
|
851
|
+
try {
|
|
852
|
+
assert.equal(r.status, 1, `status=${r.status} stderr=${r.stderr}`);
|
|
853
|
+
assert.ok(r.elapsedMs < 5000, `expected prompt exit, got elapsedMs=${r.elapsedMs}`);
|
|
854
|
+
} finally {
|
|
855
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
856
|
+
}
|
|
857
|
+
});
|
|
858
|
+
|
|
859
|
+
test('bootstrap branch plain mode with no output and non-zero exitCode exits promptly (no extended wait)', () => {
|
|
860
|
+
const r = runScenario({ printMode: true, stdinInherit: true, scenario: 'plain-no-output-error' });
|
|
861
|
+
try {
|
|
862
|
+
assert.equal(r.status, 1, `status=${r.status} stderr=${r.stderr}`);
|
|
863
|
+
assert.ok(r.elapsedMs < 5000, `expected prompt exit, got elapsedMs=${r.elapsedMs}`);
|
|
864
|
+
} finally {
|
|
865
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
866
|
+
}
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
test('helper branch plain mode with no output and successful exit waits up to configured ceiling', () => {
|
|
870
|
+
const r = runScenario({
|
|
871
|
+
printMode: true,
|
|
872
|
+
stdinInherit: false,
|
|
873
|
+
scenario: 'plain-no-output-success',
|
|
874
|
+
extraEnv: { CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS: '400' },
|
|
875
|
+
});
|
|
876
|
+
try {
|
|
877
|
+
assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
|
|
878
|
+
assert.ok(r.elapsedMs >= 350, `expected extended wait close to 400ms ceiling, got elapsedMs=${r.elapsedMs}`);
|
|
879
|
+
} finally {
|
|
880
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
|
|
884
|
+
test('bootstrap branch plain mode with no output and successful exit waits up to configured ceiling', () => {
|
|
885
|
+
const r = runScenario({
|
|
886
|
+
printMode: true,
|
|
887
|
+
stdinInherit: true,
|
|
888
|
+
scenario: 'plain-no-output-success',
|
|
889
|
+
extraEnv: { CLAUDE_TERMUX_PRINT_RESULT_TIMEOUT_MS: '400' },
|
|
890
|
+
});
|
|
891
|
+
try {
|
|
892
|
+
assert.equal(r.status, 0, `status=${r.status} stderr=${r.stderr}`);
|
|
893
|
+
assert.ok(r.elapsedMs >= 350, `expected extended wait close to 400ms ceiling, got elapsedMs=${r.elapsedMs}`);
|
|
894
|
+
} finally {
|
|
895
|
+
fs.rmSync(r.tmpBase, { recursive: true, force: true });
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
|
|
820
899
|
test('helper branch intercepts self-directed SIGKILL (string signal) and exits with proper code', () => {
|
|
821
900
|
const r = runScenario({ printMode: true, stdinInherit: false, scenario: 'self-sigkill-fallback-string' });
|
|
822
901
|
try {
|
|
@@ -1075,6 +1154,31 @@ test('helper and bootstrap installStreamJsonTerminalWatcher helpers stay identic
|
|
|
1075
1154
|
assert.equal(helperWatcher, bootstrapWatcher, 'installStreamJsonTerminalWatcher must be identical in both heredocs');
|
|
1076
1155
|
});
|
|
1077
1156
|
|
|
1157
|
+
test('helper and bootstrap installPlainTextWriteWatcher helpers stay identical', () => {
|
|
1158
|
+
const helperBlock = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1159
|
+
const bootstrapBlock = extractBlock('cat <<\'NODE\' > "$_bootstrap"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1160
|
+
|
|
1161
|
+
const extractFn = (block) => {
|
|
1162
|
+
const startMarker = 'function installPlainTextWriteWatcher() {';
|
|
1163
|
+
const start = block.indexOf(startMarker);
|
|
1164
|
+
assert.ok(start > -1, 'installPlainTextWriteWatcher function not found');
|
|
1165
|
+
let depth = 0;
|
|
1166
|
+
let i = start + startMarker.length - 1;
|
|
1167
|
+
for (; i < block.length; i++) {
|
|
1168
|
+
if (block[i] === '{') depth++;
|
|
1169
|
+
if (block[i] === '}') {
|
|
1170
|
+
depth--;
|
|
1171
|
+
if (depth === 0) break;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
return block.slice(start, i + 1);
|
|
1175
|
+
};
|
|
1176
|
+
|
|
1177
|
+
const helperFn = extractFn(helperBlock);
|
|
1178
|
+
const bootstrapFn = extractFn(bootstrapBlock);
|
|
1179
|
+
assert.equal(helperFn, bootstrapFn, 'installPlainTextWriteWatcher must be identical in helper and bootstrap');
|
|
1180
|
+
});
|
|
1181
|
+
|
|
1078
1182
|
test('helper and bootstrap forceTimeoutExit helpers stay identical', () => {
|
|
1079
1183
|
const helperBlock = extractBlock('cat <<\'NODE\' > "$_helper"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|
|
1080
1184
|
const bootstrapBlock = extractBlock('cat <<\'NODE\' > "$_bootstrap"', '\n export ENABLE_CLAUDEAI_MCP_SERVERS=');
|