quilltap 4.4.0-dev.99 → 4.4.0
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/bin/quilltap.js +35 -0
- package/lib/memory-diff-command.js +29 -7
- package/package.json +5 -3
package/bin/quilltap.js
CHANGED
|
@@ -169,6 +169,19 @@ function ensureNativeModules() {
|
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
// Check node-pty: backs the Ariel terminal feature. Loaded dynamically by
|
|
173
|
+
// pty-manager in the standalone server, so resolution must succeed and the
|
|
174
|
+
// native binding's NODE_MODULE_VERSION must match the runtime.
|
|
175
|
+
try {
|
|
176
|
+
require('node-pty');
|
|
177
|
+
} catch (err) {
|
|
178
|
+
if (err.message && err.message.includes('NODE_MODULE_VERSION')) {
|
|
179
|
+
needsRebuild.push('node-pty');
|
|
180
|
+
} else if (err.code === 'MODULE_NOT_FOUND') {
|
|
181
|
+
needsRebuild.push('node-pty');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
172
185
|
if (needsRebuild.length === 0) return;
|
|
173
186
|
|
|
174
187
|
console.log(` Rebuilding native modules for Node.js ${process.version}...`);
|
|
@@ -238,6 +251,28 @@ function linkNativeModules(standaloneDir) {
|
|
|
238
251
|
|| resolveModuleDir('better-sqlite3');
|
|
239
252
|
linkModule('better-sqlite3', betterSqlite3Dir);
|
|
240
253
|
|
|
254
|
+
// Link node-pty — the standalone tarball strips it (platform-specific),
|
|
255
|
+
// and pty-manager loads it via a dynamic require, so it needs to resolve
|
|
256
|
+
// from standaloneDir/node_modules.
|
|
257
|
+
const nodePtyDir = resolveModuleDir('node-pty');
|
|
258
|
+
linkModule('node-pty', nodePtyDir);
|
|
259
|
+
if (nodePtyDir) {
|
|
260
|
+
// Some npm cache extractions strip the executable bit on spawn-helper,
|
|
261
|
+
// causing pty.spawn() to fail with `posix_spawnp failed`. Restore it.
|
|
262
|
+
const prebuildsDir = path.join(nodePtyDir, 'prebuilds');
|
|
263
|
+
if (fs.existsSync(prebuildsDir)) {
|
|
264
|
+
try {
|
|
265
|
+
for (const entry of fs.readdirSync(prebuildsDir, { withFileTypes: true })) {
|
|
266
|
+
if (!entry.isDirectory()) continue;
|
|
267
|
+
const helper = path.join(prebuildsDir, entry.name, 'spawn-helper');
|
|
268
|
+
if (fs.existsSync(helper)) {
|
|
269
|
+
try { fs.chmodSync(helper, 0o755); } catch { /* best-effort */ }
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
} catch { /* best-effort */ }
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
241
276
|
// Link sharp
|
|
242
277
|
const sharpDir = resolveModuleDir('sharp');
|
|
243
278
|
linkModule('sharp', sharpDir);
|
|
@@ -38,16 +38,20 @@ Nothing is persisted; the server runs the extraction passes in dry-run mode
|
|
|
38
38
|
so the comparison is non-destructive.
|
|
39
39
|
|
|
40
40
|
Options:
|
|
41
|
-
-d, --data-dir <path>
|
|
42
|
-
--passphrase <pass>
|
|
43
|
-
--port <number>
|
|
44
|
-
--out <dir>
|
|
45
|
-
|
|
41
|
+
-d, --data-dir <path> Override data directory (instance root)
|
|
42
|
+
--passphrase <pass> Decrypt .dbkey if peppered
|
|
43
|
+
--port <number> Server port for API calls (default: 3000)
|
|
44
|
+
--out <dir> Output directory (default: cwd)
|
|
45
|
+
--concurrency <number> Parallel turns to process (default: 4, max: 32).
|
|
46
|
+
Cloud cheap-LLMs can handle 8–16; keep this low
|
|
47
|
+
for local Ollama to avoid saturating the model.
|
|
48
|
+
-h, --help Show this help
|
|
46
49
|
|
|
47
50
|
Examples:
|
|
48
51
|
quilltap memory-diff <chatId>
|
|
49
52
|
quilltap memory-diff <chatId> --data-dir ~/iCloud/Quilltap/Friday
|
|
50
53
|
quilltap memory-diff <chatId> --out /tmp/extract-diff
|
|
54
|
+
quilltap memory-diff <chatId> --concurrency 8 # cloud cheap-LLM
|
|
51
55
|
`);
|
|
52
56
|
}
|
|
53
57
|
|
|
@@ -57,6 +61,7 @@ function parseFlags(args) {
|
|
|
57
61
|
passphrase: '',
|
|
58
62
|
port: 3000,
|
|
59
63
|
out: process.cwd(),
|
|
64
|
+
concurrency: 4,
|
|
60
65
|
help: false,
|
|
61
66
|
};
|
|
62
67
|
const positional = [];
|
|
@@ -80,6 +85,15 @@ function parseFlags(args) {
|
|
|
80
85
|
flags.port = p;
|
|
81
86
|
break;
|
|
82
87
|
}
|
|
88
|
+
case '--concurrency': {
|
|
89
|
+
const n = parseInt(args[++i], 10);
|
|
90
|
+
if (isNaN(n) || n < 1 || n > 32) {
|
|
91
|
+
console.error('Error: --concurrency must be between 1 and 32');
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
flags.concurrency = n;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
83
97
|
case '--out':
|
|
84
98
|
flags.out = args[++i];
|
|
85
99
|
break;
|
|
@@ -245,8 +259,12 @@ async function memoryDiffCommand(args) {
|
|
|
245
259
|
process.stderr.write(` wrote ${GREEN}${existing.length}${RESET} memories to ${existingPath}\n`);
|
|
246
260
|
|
|
247
261
|
// -------- 2. Stream dry-run re-extraction from the server ----------------
|
|
248
|
-
const url =
|
|
249
|
-
|
|
262
|
+
const url =
|
|
263
|
+
`http://localhost:${flags.port}/api/v1/chats/${encodeURIComponent(chatId)}` +
|
|
264
|
+
`?action=extract-memories-dry-run&concurrency=${flags.concurrency}`;
|
|
265
|
+
process.stderr.write(
|
|
266
|
+
`${BOLD}Streaming re-extraction${RESET} (concurrency ${CYAN}${flags.concurrency}${RESET}) from ${DIM}${url}${RESET}\n`
|
|
267
|
+
);
|
|
250
268
|
|
|
251
269
|
let res;
|
|
252
270
|
try {
|
|
@@ -299,6 +317,10 @@ async function memoryDiffCommand(args) {
|
|
|
299
317
|
` ${RED}[${event.index + 1}/${turnCount}] FAILED${RESET}: ${event.error}\n`
|
|
300
318
|
);
|
|
301
319
|
break;
|
|
320
|
+
case 'ping':
|
|
321
|
+
// Server-side heartbeat keeping the connection warm during long
|
|
322
|
+
// first-turn LLM passes; nothing to display.
|
|
323
|
+
break;
|
|
302
324
|
case 'done':
|
|
303
325
|
totalCandidates = event.totalCandidates;
|
|
304
326
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quilltap",
|
|
3
|
-
"version": "4.4.0
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "Self-hosted AI workspace for writers, worldbuilders, and roleplayers. Run with npx quilltap.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Charles Sebold",
|
|
@@ -33,12 +33,14 @@
|
|
|
33
33
|
"README.md"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
+
"@napi-rs/canvas": "^0.1.100",
|
|
36
37
|
"better-sqlite3-multiple-ciphers": "^12.9.0",
|
|
38
|
+
"node-pty": "^1.1.0",
|
|
37
39
|
"sharp": "^0.34.5",
|
|
38
|
-
"tar": "^7.5.
|
|
40
|
+
"tar": "^7.5.15",
|
|
39
41
|
"yauzl": "^3.3.0"
|
|
40
42
|
},
|
|
41
43
|
"engines": {
|
|
42
|
-
"node": ">=
|
|
44
|
+
"node": ">=24.0.0"
|
|
43
45
|
}
|
|
44
46
|
}
|