diff --git a/typescript/package.json b/typescript/package.json index 1654f47e..abb712a9 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 tests/examples.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 tests/examples.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/src/interactive/interactive.ts b/typescript/src/interactive/interactive.ts index 16f1c541..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) { + 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 new file mode 100644 index 00000000..8c4cf4de --- /dev/null +++ b/typescript/test/interactive.test.ts @@ -0,0 +1,61 @@ +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("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"]); + }); + + 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"]); + }); +});