Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions scripts/test_completion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,20 @@ total="$(printf '%s\n' "$line" | sed 's|COMPTEST ||' | cut -d/ -f2)"
if printf '%s\n' "$out" | grep -q 'FAIL' || [ "$passed" != "$total" ]; then
echo "RESULT: FAIL ($line)"; exit 1
fi
# ── #166: piped stdin must be read to EOF, not truncated to the first line ──────────
# QWISP_FAKE=1 uses FakeBackend: no model weights, no GPU — only the tokenizer this gate
# already requires. Asserts a strict increase rather than an exact count so it does not
# encode the tokenizer's segmentation. Before the fix both arms reported 11 tok.
tok_of() {
printf '%b' "$1" | QWISP_FAKE=1 QWISP_MODEL="$MODEL" "$BIN" chat --max-tokens 2 2>&1 \
| sed -n 's/.*prompt \([0-9]*\) tok.*/\1/p'
}
one="$(tok_of 'alpha\n')"
two="$(tok_of 'alpha\nbeta gamma delta epsilon zeta eta theta iota kappa lambda\n')"
if [ -z "$one" ] || [ -z "$two" ] || [ "$two" -le "$one" ]; then
echo "RESULT: FAIL (piped stdin truncated to line 1: 1-line=${one:-NA} tok, 2-line=${two:-NA} tok — #166)"
exit 1
fi
echo "[stdin] piped multi-line read to EOF: 1-line=$one tok < 2-line=$two tok ok"

echo "RESULT: PASS ($line)"
16 changes: 15 additions & 1 deletion swift/Sources/qwisp/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,21 @@ case "chat":
}
}
let promptText = rest.joined(separator: " ")
let prompt = promptText.isEmpty ? (readLine(strippingNewline: true) ?? "") : promptText
// Piped stdin is a documented input path ("or pipe text via stdin" in the usage line), and
// readLine() takes only the FIRST line — `cat spec.md | qwisp chat` silently answered on
// line 1 and exited 0 (#166; it ingested 52 tokens of a 35K-token file while reporting a
// healthy run). Read to EOF when stdin is not a TTY; keep readLine() interactively, where
// one line IS what the user means and reading to EOF would block until ^D.
let prompt: String
if !promptText.isEmpty {
prompt = promptText
} else if isatty(FileHandle.standardInput.fileDescriptor) == 1 {
prompt = readLine(strippingNewline: true) ?? ""
} else {
let piped = FileHandle.standardInput.readDataToEndOfFile()
prompt = String(decoding: piped, as: UTF8.self)
.trimmingCharacters(in: .whitespacesAndNewlines)
}
if prompt.isEmpty {
print("usage: qwisp chat [--max-tokens N] [--lossless] <prompt> (or pipe text via stdin)")
} else {
Expand Down
Loading