From b958f6b726b48461b747b522cf3524e4e321866d Mon Sep 17 00:00:00 2001 From: Mohammed Alkindi Date: Fri, 18 Sep 2026 08:59:08 -0700 Subject: [PATCH 1/3] fix(interactive): skip comment lines when reading requests from a file The Python port filters lines starting with '# ' before dispatching; the TypeScript one did not, so the header comments in the shipped healthData input.txt were sent to the translator as requests. --- typescript/src/interactive/interactive.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/src/interactive/interactive.ts b/typescript/src/interactive/interactive.ts index 16f1c541..e233773d 100644 --- a/typescript/src/interactive/interactive.ts +++ b/typescript/src/interactive/interactive.ts @@ -13,7 +13,7 @@ export async function processRequests(interactivePrompt: string, inputFileName: if (inputFileName) { const lines = fs.readFileSync(inputFileName).toString().split(/\r?\n/); for (const line of lines) { - if (line.length) { + if (line.length && !line.startsWith("# ")) { console.log(interactivePrompt + line); await processRequest(line); } From 19bcfefd11c8810cdef8acd74e0f0c1d9440fe4a Mon Sep 17 00:00:00 2001 From: Mohammed Alkindi Date: Tue, 6 Oct 2026 18:34:24 -0700 Subject: [PATCH 2/3] test(interactive): cover processRequests input-file handling --- typescript/package.json | 2 +- typescript/test/interactive.test.ts | 56 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 typescript/test/interactive.test.ts diff --git a/typescript/package.json b/typescript/package.json index dd10ea6b..7114a577 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -21,7 +21,7 @@ }, "scripts": { "build": "tsc -p src", - "test": "npm run build && tsc -p test && node --test out/validate.test.js out/zod.test.js out/program.test.js tests/model.test.mjs", + "test": "npm run build && tsc -p test && node --test out/validate.test.js out/zod.test.js out/program.test.js out/interactive.test.js tests/model.test.mjs", "build-all": "npm run build --workspaces", "prepare": "npm run build-all", "prepublishOnly": "node -e \"require('fs').copyFileSync('../SECURITY.md','SECURITY.md')\"", diff --git a/typescript/test/interactive.test.ts b/typescript/test/interactive.test.ts new file mode 100644 index 00000000..9d1b503e --- /dev/null +++ b/typescript/test/interactive.test.ts @@ -0,0 +1,56 @@ +import { describe, it } from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { processRequests } from "../dist/interactive/index.js"; + +// --------------------------------------------------------------------------- +// processRequests reading requests from an input file +// --------------------------------------------------------------------------- + +describe("processRequests with an input file", () => { + async function run(text: string) { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "typechat-interactive-")); + const inputFile = path.join(dir, "input.txt"); + fs.writeFileSync(inputFile, text); + const requests: string[] = []; + const echoed: string[] = []; + const log = console.log; + console.log = (message: string) => { echoed.push(message); }; + try { + await processRequests("> ", inputFile, async request => { requests.push(request); }); + } + finally { + console.log = log; + fs.rmSync(dir, { recursive: true, force: true }); + } + return { requests, echoed }; + } + + it("processes each line in order and echoes it after the prompt", async () => { + const { requests, echoed } = await run("first request\nsecond request\n"); + assert.deepEqual(requests, ["first request", "second request"]); + assert.deepEqual(echoed, ["> first request", "> second request"]); + }); + + it("skips blank lines", async () => { + const { requests } = await run("\nfirst request\n\n\nsecond request\n\n"); + assert.deepEqual(requests, ["first request", "second request"]); + }); + + it("skips comment lines", async () => { + const { requests } = await run("# a comment\nfirst request\n# another comment\nsecond request\n"); + assert.deepEqual(requests, ["first request", "second request"]); + }); + + it("keeps a request that only starts with #", async () => { + const { requests } = await run("#1 priority order\n"); + assert.deepEqual(requests, ["#1 priority order"]); + }); + + it("splits CRLF line endings", async () => { + const { requests } = await run("# a comment\r\nfirst request\r\nsecond request\r\n"); + assert.deepEqual(requests, ["first request", "second request"]); + }); +}); From d364e1eef5d4687dcfde9dbc211d839fb19e7e63 Mon Sep 17 00:00:00 2001 From: Mohammed Alkindi Date: Fri, 9 Oct 2026 20:30:50 -0700 Subject: [PATCH 3/3] fix(interactive): also skip a comment line that is only # --- typescript/src/interactive/interactive.ts | 2 +- typescript/test/interactive.test.ts | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/typescript/src/interactive/interactive.ts b/typescript/src/interactive/interactive.ts index e233773d..20d52013 100644 --- a/typescript/src/interactive/interactive.ts +++ b/typescript/src/interactive/interactive.ts @@ -13,7 +13,7 @@ export async function processRequests(interactivePrompt: string, inputFileName: if (inputFileName) { const lines = fs.readFileSync(inputFileName).toString().split(/\r?\n/); for (const line of lines) { - if (line.length && !line.startsWith("# ")) { + if (line.length && line !== "#" && !line.startsWith("# ")) { console.log(interactivePrompt + line); await processRequest(line); } diff --git a/typescript/test/interactive.test.ts b/typescript/test/interactive.test.ts index 9d1b503e..8c4cf4de 100644 --- a/typescript/test/interactive.test.ts +++ b/typescript/test/interactive.test.ts @@ -44,6 +44,11 @@ describe("processRequests with an input file", () => { assert.deepEqual(requests, ["first request", "second request"]); }); + it("skips a comment line that is only #", async () => { + const { requests } = await run("#\n# a comment\nfirst request\n#\n"); + assert.deepEqual(requests, ["first request"]); + }); + it("keeps a request that only starts with #", async () => { const { requests } = await run("#1 priority order\n"); assert.deepEqual(requests, ["#1 priority order"]);