quilltap 4.10.0-dev.100 → 4.10.0-dev.105
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 +1 -1
- package/bin/quilltap.js +4 -0
- package/lib/text-codec.js +30 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -193,7 +193,7 @@ quilltap db --mount-points --tables # Target the mount index DB
|
|
|
193
193
|
|
|
194
194
|
The database is opened **read-only by default**. Add `--write` to make changes: it opens the database read-write, **claims the instance lock** (`<dataDir>/quilltap.lock`) for the duration, and releases it on exit. It **refuses — with no override — if a running server or another instance holds the lock**, so stop the server first. `--repl` is read-only unless combined with `--write`. Attempting a write without `--write` fails with a hint to re-run with the flag. What "held" means, and how to tell a live lock from a stale one, is [below](#locking).
|
|
195
195
|
|
|
196
|
-
Compressed text columns (`chat_messages.content`, `llm_logs.request` / `response` and friends) are stored as BLOBs.
|
|
196
|
+
Compressed text columns (`chat_messages.content`, `llm_logs.request` / `response` and friends) are stored as BLOBs. A raw query's output decodes them for display, so `SELECT content …` prints text. Inside SQL — `WHERE`, `LIKE`, `substr`, `json_extract` — wrap the column in `qt_text()` to work on the text: `SELECT json_extract(qt_text(response), '$.error') …`.
|
|
197
197
|
|
|
198
198
|
In the REPL, `.cols <table>` and `.find <text>` mirror the subcommand helpers.
|
|
199
199
|
|
package/bin/quilltap.js
CHANGED
|
@@ -14,6 +14,7 @@ const {
|
|
|
14
14
|
openEncryptedDb,
|
|
15
15
|
} = require('../lib/db-helpers');
|
|
16
16
|
const { resolveInstance } = require('../lib/instances');
|
|
17
|
+
const { decodeCompressedTextInRows } = require('../lib/text-codec');
|
|
17
18
|
const { resolveModuleDir, ensureNativeModules, ensureDatabaseNativeModule } = require('../lib/native-modules');
|
|
18
19
|
|
|
19
20
|
const PACKAGE_DIR = path.resolve(__dirname, '..');
|
|
@@ -1042,6 +1043,8 @@ async function dbCommand(args) {
|
|
|
1042
1043
|
const stmt = db.prepare(sql);
|
|
1043
1044
|
if (stmt.reader) {
|
|
1044
1045
|
const rows = stmt.all();
|
|
1046
|
+
// Compressed text columns arrive as Buffers; print them as text (bug 173).
|
|
1047
|
+
decodeCompressedTextInRows(rows);
|
|
1045
1048
|
if (asJson) {
|
|
1046
1049
|
console.log(JSON.stringify(rows, null, 2));
|
|
1047
1050
|
} else if (rows.length === 0) {
|
|
@@ -1110,6 +1113,7 @@ async function dbCommand(args) {
|
|
|
1110
1113
|
const stmt = db.prepare(trimmed);
|
|
1111
1114
|
if (stmt.reader) {
|
|
1112
1115
|
const rows = stmt.all();
|
|
1116
|
+
decodeCompressedTextInRows(rows);
|
|
1113
1117
|
if (rows.length === 0) console.log('(no results)');
|
|
1114
1118
|
else console.table(rows);
|
|
1115
1119
|
} else {
|
package/lib/text-codec.js
CHANGED
|
@@ -58,4 +58,33 @@ function registerTextCodecFunction(db) {
|
|
|
58
58
|
db.function('qt_text', { deterministic: true }, (value) => decodeText(value));
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Decode every compressed-text value in a set of result rows, in place, for
|
|
63
|
+
* printing. Raw SQL (`quilltap db "SELECT content …"`, `--repl`) hands BLOBs to
|
|
64
|
+
* `JSON.stringify` / `console.table` as Buffers, which print as
|
|
65
|
+
* `{"type":"Buffer","data":[…]}` and read as data loss (bug 173). Only values
|
|
66
|
+
* carrying the `0x51 0x01 0x01` header are touched — embedding BLOBs and other
|
|
67
|
+
* binary columns pass through unchanged, as does anything already text
|
|
68
|
+
* (including an explicit `qt_text()`). Returns the number of values decoded.
|
|
69
|
+
*/
|
|
70
|
+
function decodeCompressedTextInRows(rows) {
|
|
71
|
+
let decoded = 0;
|
|
72
|
+
if (!Array.isArray(rows)) return decoded;
|
|
73
|
+
for (const row of rows) {
|
|
74
|
+
if (!row || typeof row !== 'object') continue;
|
|
75
|
+
for (const key of Object.keys(row)) {
|
|
76
|
+
if (isCompressedTextBlob(row[key])) {
|
|
77
|
+
row[key] = decodeText(row[key]);
|
|
78
|
+
decoded++;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return decoded;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = {
|
|
86
|
+
decodeText,
|
|
87
|
+
decodeCompressedTextInRows,
|
|
88
|
+
isCompressedTextBlob,
|
|
89
|
+
registerTextCodecFunction,
|
|
90
|
+
};
|
package/package.json
CHANGED