draken 0.1.6 → 0.3.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/ACCEPTANCE.md +34 -0
- package/CHANGELOG.md +65 -0
- package/CONTRIBUTING.md +129 -0
- package/MEMORY.md +118 -0
- package/PERSONA.md +67 -0
- package/README.md +168 -78
- package/SETUP.md +111 -0
- package/SOURCES.md +75 -0
- package/TRAY.md +54 -0
- package/VOICE.md +126 -0
- package/dist/auth/middleware.d.ts +3 -1
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +20 -15
- package/dist/auth/middleware.js.map +1 -1
- package/dist/cli.js +77 -113
- package/dist/cli.js.map +1 -1
- package/dist/db/agent-migration.d.ts +7 -0
- package/dist/db/agent-migration.d.ts.map +1 -0
- package/dist/db/agent-migration.js +36 -0
- package/dist/db/agent-migration.js.map +1 -0
- package/dist/db/evidence.d.ts +37 -0
- package/dist/db/evidence.d.ts.map +1 -0
- package/dist/db/evidence.js +110 -0
- package/dist/db/evidence.js.map +1 -0
- package/dist/db/pointer-migration.d.ts +7 -0
- package/dist/db/pointer-migration.d.ts.map +1 -0
- package/dist/db/pointer-migration.js +117 -0
- package/dist/db/pointer-migration.js.map +1 -0
- package/dist/db/retained-text.d.ts +8 -0
- package/dist/db/retained-text.d.ts.map +1 -0
- package/dist/db/retained-text.js +36 -0
- package/dist/db/retained-text.js.map +1 -0
- package/dist/db/schema.d.ts +1 -5
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +206 -55
- package/dist/db/schema.js.map +1 -1
- package/dist/db/snapshot-pointers.d.ts +5 -0
- package/dist/db/snapshot-pointers.d.ts.map +1 -0
- package/dist/db/snapshot-pointers.js +174 -0
- package/dist/db/snapshot-pointers.js.map +1 -0
- package/dist/memory/automatic.d.ts +38 -0
- package/dist/memory/automatic.d.ts.map +1 -0
- package/dist/memory/automatic.js +155 -0
- package/dist/memory/automatic.js.map +1 -0
- package/dist/memory/context.d.ts +12 -0
- package/dist/memory/context.d.ts.map +1 -0
- package/dist/memory/context.js +107 -0
- package/dist/memory/context.js.map +1 -0
- package/dist/memory/embedding-pool.d.ts +28 -0
- package/dist/memory/embedding-pool.d.ts.map +1 -0
- package/dist/memory/embedding-pool.js +135 -0
- package/dist/memory/embedding-pool.js.map +1 -0
- package/dist/memory/embedding-worker.d.ts +2 -0
- package/dist/memory/embedding-worker.d.ts.map +1 -0
- package/dist/memory/embedding-worker.js +32 -0
- package/dist/memory/embedding-worker.js.map +1 -0
- package/dist/memory/index.d.ts +32 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +441 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/model-files.d.ts +9 -0
- package/dist/memory/model-files.d.ts.map +1 -0
- package/dist/memory/model-files.js +13 -0
- package/dist/memory/model-files.js.map +1 -0
- package/dist/memory/model.d.ts +15 -0
- package/dist/memory/model.d.ts.map +1 -0
- package/dist/memory/model.js +147 -0
- package/dist/memory/model.js.map +1 -0
- package/dist/memory/readiness.d.ts +16 -0
- package/dist/memory/readiness.d.ts.map +1 -0
- package/dist/memory/readiness.js +131 -0
- package/dist/memory/readiness.js.map +1 -0
- package/dist/memory/reconcile.d.ts +11 -0
- package/dist/memory/reconcile.d.ts.map +1 -0
- package/dist/memory/reconcile.js +132 -0
- package/dist/memory/reconcile.js.map +1 -0
- package/dist/memory/service.d.ts +10 -0
- package/dist/memory/service.d.ts.map +1 -0
- package/dist/memory/service.js +243 -0
- package/dist/memory/service.js.map +1 -0
- package/dist/memory/sources.d.ts +15 -0
- package/dist/memory/sources.d.ts.map +1 -0
- package/dist/memory/sources.js +94 -0
- package/dist/memory/sources.js.map +1 -0
- package/dist/memory/stamps.d.ts +13 -0
- package/dist/memory/stamps.d.ts.map +1 -0
- package/dist/memory/stamps.js +101 -0
- package/dist/memory/stamps.js.map +1 -0
- package/dist/memory/storage.d.ts +5 -0
- package/dist/memory/storage.d.ts.map +1 -0
- package/dist/memory/storage.js +116 -0
- package/dist/memory/storage.js.map +1 -0
- package/dist/memory/types.d.ts +89 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +8 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/memory/worker.d.ts +2 -0
- package/dist/memory/worker.d.ts.map +1 -0
- package/dist/memory/worker.js +84 -0
- package/dist/memory/worker.js.map +1 -0
- package/dist/npm-cli.d.ts +4 -0
- package/dist/npm-cli.d.ts.map +1 -0
- package/dist/npm-cli.js +36 -0
- package/dist/npm-cli.js.map +1 -0
- package/dist/pi/runtime.d.ts +34 -0
- package/dist/pi/runtime.d.ts.map +1 -0
- package/dist/pi/runtime.js +210 -0
- package/dist/pi/runtime.js.map +1 -0
- package/dist/pi/setup.d.ts +5 -0
- package/dist/pi/setup.d.ts.map +1 -0
- package/dist/pi/setup.js +147 -0
- package/dist/pi/setup.js.map +1 -0
- package/dist/routes/auth.d.ts.map +1 -1
- package/dist/routes/auth.js +3 -1
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/live-voice.d.ts +3 -0
- package/dist/routes/live-voice.d.ts.map +1 -0
- package/dist/routes/live-voice.js +49 -0
- package/dist/routes/live-voice.js.map +1 -0
- package/dist/routes/{browse.d.ts → memory.d.ts} +1 -1
- package/dist/routes/memory.d.ts.map +1 -0
- package/dist/routes/memory.js +18 -0
- package/dist/routes/memory.js.map +1 -0
- package/dist/routes/{tasks.d.ts → sync.d.ts} +1 -1
- package/dist/routes/sync.d.ts.map +1 -0
- package/dist/routes/sync.js +145 -0
- package/dist/routes/sync.js.map +1 -0
- package/dist/routes/{projects.d.ts → voice.d.ts} +1 -1
- package/dist/routes/voice.d.ts.map +1 -0
- package/dist/routes/voice.js +35 -0
- package/dist/routes/voice.js.map +1 -0
- package/dist/server-state.d.ts +30 -0
- package/dist/server-state.d.ts.map +1 -0
- package/dist/server-state.js +113 -0
- package/dist/server-state.js.map +1 -0
- package/dist/server-status.d.ts +7 -0
- package/dist/server-status.d.ts.map +1 -0
- package/dist/server-status.js +34 -0
- package/dist/server-status.js.map +1 -0
- package/dist/server.d.ts +5 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +148 -46
- package/dist/server.js.map +1 -1
- package/dist/sources/adapters.d.ts +15 -0
- package/dist/sources/adapters.d.ts.map +1 -0
- package/dist/sources/adapters.js +159 -0
- package/dist/sources/adapters.js.map +1 -0
- package/dist/sources/registry.d.ts +17 -0
- package/dist/sources/registry.d.ts.map +1 -0
- package/dist/sources/registry.js +56 -0
- package/dist/sources/registry.js.map +1 -0
- package/dist/sync/collector.d.ts +3 -0
- package/dist/sync/collector.d.ts.map +1 -0
- package/dist/sync/collector.js +324 -0
- package/dist/sync/collector.js.map +1 -0
- package/dist/sync/cost.d.ts +7 -0
- package/dist/sync/cost.d.ts.map +1 -0
- package/dist/sync/cost.js +31 -0
- package/dist/sync/cost.js.map +1 -0
- package/dist/sync/jsonl.d.ts +34 -0
- package/dist/sync/jsonl.d.ts.map +1 -0
- package/dist/sync/jsonl.js +161 -0
- package/dist/sync/jsonl.js.map +1 -0
- package/dist/sync/manager.d.ts +15 -0
- package/dist/sync/manager.d.ts.map +1 -0
- package/dist/sync/manager.js +287 -0
- package/dist/sync/manager.js.map +1 -0
- package/dist/sync/normalize.d.ts +22 -0
- package/dist/sync/normalize.d.ts.map +1 -0
- package/dist/sync/normalize.js +107 -0
- package/dist/sync/normalize.js.map +1 -0
- package/dist/sync/pi-output.d.ts +33 -0
- package/dist/sync/pi-output.d.ts.map +1 -0
- package/dist/sync/pi-output.js +186 -0
- package/dist/sync/pi-output.js.map +1 -0
- package/dist/sync/pi.d.ts +15 -0
- package/dist/sync/pi.d.ts.map +1 -0
- package/dist/sync/pi.js +149 -0
- package/dist/sync/pi.js.map +1 -0
- package/dist/sync/recap.d.ts +25 -0
- package/dist/sync/recap.d.ts.map +1 -0
- package/dist/sync/recap.js +118 -0
- package/dist/sync/recap.js.map +1 -0
- package/dist/sync/reconciliation.d.ts +16 -0
- package/dist/sync/reconciliation.d.ts.map +1 -0
- package/dist/sync/reconciliation.js +22 -0
- package/dist/sync/reconciliation.js.map +1 -0
- package/dist/sync/references.d.ts +10 -0
- package/dist/sync/references.d.ts.map +1 -0
- package/dist/sync/references.js +50 -0
- package/dist/sync/references.js.map +1 -0
- package/dist/sync/source-files.d.ts +16 -0
- package/dist/sync/source-files.d.ts.map +1 -0
- package/dist/sync/source-files.js +56 -0
- package/dist/sync/source-files.js.map +1 -0
- package/dist/sync/store.d.ts +36 -0
- package/dist/sync/store.d.ts.map +1 -0
- package/dist/sync/store.js +359 -0
- package/dist/sync/store.js.map +1 -0
- package/dist/sync/summary-budget.d.ts +19 -0
- package/dist/sync/summary-budget.d.ts.map +1 -0
- package/dist/sync/summary-budget.js +39 -0
- package/dist/sync/summary-budget.js.map +1 -0
- package/dist/sync/tree.d.ts +69 -0
- package/dist/sync/tree.d.ts.map +1 -0
- package/dist/sync/tree.js +599 -0
- package/dist/sync/tree.js.map +1 -0
- package/dist/tray/controller.d.ts +51 -0
- package/dist/tray/controller.d.ts.map +1 -0
- package/dist/tray/controller.js +178 -0
- package/dist/tray/controller.js.map +1 -0
- package/dist/tray/launcher.d.ts +3 -0
- package/dist/tray/launcher.d.ts.map +1 -0
- package/dist/tray/launcher.js +47 -0
- package/dist/tray/launcher.js.map +1 -0
- package/dist/tray/native.d.ts +12 -0
- package/dist/tray/native.d.ts.map +1 -0
- package/dist/tray/native.js +93 -0
- package/dist/tray/native.js.map +1 -0
- package/dist/tray/processes.d.ts +5 -0
- package/dist/tray/processes.d.ts.map +1 -0
- package/dist/tray/processes.js +99 -0
- package/dist/tray/processes.js.map +1 -0
- package/dist/tray/worker.d.ts +4 -0
- package/dist/tray/worker.d.ts.map +1 -0
- package/dist/tray/worker.js +150 -0
- package/dist/tray/worker.js.map +1 -0
- package/dist/types.d.ts +221 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/voice/continuation.d.ts +25 -0
- package/dist/voice/continuation.d.ts.map +1 -0
- package/dist/voice/continuation.js +95 -0
- package/dist/voice/continuation.js.map +1 -0
- package/dist/voice/history-focus.d.ts +14 -0
- package/dist/voice/history-focus.d.ts.map +1 -0
- package/dist/voice/history-focus.js +39 -0
- package/dist/voice/history-focus.js.map +1 -0
- package/dist/voice/legacy-history.d.ts +5 -0
- package/dist/voice/legacy-history.d.ts.map +1 -0
- package/dist/voice/legacy-history.js +34 -0
- package/dist/voice/legacy-history.js.map +1 -0
- package/dist/voice/live-context.d.ts +14 -0
- package/dist/voice/live-context.d.ts.map +1 -0
- package/dist/voice/live-context.js +137 -0
- package/dist/voice/live-context.js.map +1 -0
- package/dist/voice/live.d.ts +37 -0
- package/dist/voice/live.d.ts.map +1 -0
- package/dist/voice/live.js +462 -0
- package/dist/voice/live.js.map +1 -0
- package/dist/voice/preparation.d.ts +8 -0
- package/dist/voice/preparation.d.ts.map +1 -0
- package/dist/voice/preparation.js +59 -0
- package/dist/voice/preparation.js.map +1 -0
- package/package.json +49 -16
- package/public/assets/index-BQFBaSKm.js +40 -0
- package/public/assets/index-CYCbTSh1.js +131 -0
- package/public/assets/index-DntUQtGK.css +1 -0
- package/public/assets/persona-BVIfx5k8.js +1 -0
- package/public/assets/persona-C_m1CVKe.css +1 -0
- package/public/assets/scene-CBV2oPhA.js +3854 -0
- package/public/index.html +6 -8
- package/public/persona/THREE-LICENSE.txt +21 -0
- package/public/persona/call-poster.webp +0 -0
- package/public/persona/chat-avatar.webp +0 -0
- package/public/persona/reference.jpg +0 -0
- package/public/persona/sample.wav +0 -0
- package/public/persona.html +7 -0
- package/runtime/pi/package-lock.json +1549 -0
- package/runtime/pi/package.json +12 -0
- package/tests/fixtures/voice-question.wav +0 -0
- package/tray/assets/error.ico +0 -0
- package/tray/assets/error.png +0 -0
- package/tray/assets/running.ico +0 -0
- package/tray/assets/running.png +0 -0
- package/tray/assets/starting.ico +0 -0
- package/tray/assets/starting.png +0 -0
- package/tray/assets/stopped.ico +0 -0
- package/tray/assets/stopped.png +0 -0
- package/tray/assets/stopping.ico +0 -0
- package/tray/assets/stopping.png +0 -0
- package/tray/macos.js +72 -0
- package/tray/windows.ps1 +104 -0
- package/voice/realtime/README.md +84 -0
- package/voice/realtime/backend.mjs +81 -0
- package/voice/realtime/native.mjs +210 -0
- package/voice/realtime/peer.d.mts +15 -0
- package/voice/realtime/peer.mjs +116 -0
- package/voice/realtime/probe-browser.mjs +81 -0
- package/voice/realtime/probe-server.mjs +86 -0
- package/voice/realtime/probe.html +11 -0
- package/voice/realtime/probe.mjs +42 -0
- package/voice/realtime/rpc.mjs +118 -0
- package/voice/realtime/setup.mjs +32 -0
- package/voice/tls.mjs +49 -0
- package/dist/db/queries.d.ts +0 -16
- package/dist/db/queries.d.ts.map +0 -1
- package/dist/db/queries.js +0 -91
- package/dist/db/queries.js.map +0 -1
- package/dist/docker/dockerfile.d.ts +0 -50
- package/dist/docker/dockerfile.d.ts.map +0 -1
- package/dist/docker/dockerfile.js +0 -160
- package/dist/docker/dockerfile.js.map +0 -1
- package/dist/docker/manager.d.ts +0 -42
- package/dist/docker/manager.d.ts.map +0 -1
- package/dist/docker/manager.js +0 -421
- package/dist/docker/manager.js.map +0 -1
- package/dist/git/status.d.ts +0 -76
- package/dist/git/status.d.ts.map +0 -1
- package/dist/git/status.js +0 -332
- package/dist/git/status.js.map +0 -1
- package/dist/routes/browse.d.ts.map +0 -1
- package/dist/routes/browse.js +0 -49
- package/dist/routes/browse.js.map +0 -1
- package/dist/routes/git.d.ts +0 -9
- package/dist/routes/git.d.ts.map +0 -1
- package/dist/routes/git.js +0 -338
- package/dist/routes/git.js.map +0 -1
- package/dist/routes/projects.d.ts.map +0 -1
- package/dist/routes/projects.js +0 -220
- package/dist/routes/projects.js.map +0 -1
- package/dist/routes/tasks.d.ts.map +0 -1
- package/dist/routes/tasks.js +0 -313
- package/dist/routes/tasks.js.map +0 -1
- package/draken.dockerfile.template +0 -18
- package/public/assets/index-3ngsG5kF.css +0 -1
- package/public/assets/index-B3YSD0ee.js +0 -252
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initHistoryStorage = initHistoryStorage;
|
|
4
|
+
/** One physical passage/vector, many scoped occurrences. `chunks` and
|
|
5
|
+
* `embedding_cache` are read views, not additional text/vector stores. */
|
|
6
|
+
function initHistoryStorage(db, fingerprint) {
|
|
7
|
+
const version = 'history-index-v3-contentless';
|
|
8
|
+
if (db.prepare("SELECT 1 FROM sqlite_schema WHERE type='table' AND name='meta'").get()) {
|
|
9
|
+
const get = db.prepare('SELECT value FROM meta WHERE key=?');
|
|
10
|
+
// A cold prepared-only voice lookup must not perform even no-op schema
|
|
11
|
+
// writes. Real migrations/model changes still take the transactional path.
|
|
12
|
+
if (get.get('schema')?.value === version
|
|
13
|
+
&& get.get('model')?.value === fingerprint
|
|
14
|
+
&& get.get('covered-tails-removed')?.value === '1')
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
db.exec("CREATE TABLE IF NOT EXISTS meta(key TEXT PRIMARY KEY,value TEXT NOT NULL)");
|
|
18
|
+
const prior = db.prepare("SELECT value FROM meta WHERE key='schema'").get()?.value;
|
|
19
|
+
if ((prior && !['history-index-v1', 'history-index-v2-pointers', version].includes(prior)) || (!prior && db.prepare("SELECT 1 FROM sqlite_schema WHERE name IN ('records','chunks','vectors','passages')").get()))
|
|
20
|
+
throw new Error('Unknown history storage version; existing data was not reset');
|
|
21
|
+
db.transaction(() => {
|
|
22
|
+
db.exec(`
|
|
23
|
+
CREATE TABLE IF NOT EXISTS records(ref TEXT PRIMARY KEY,json TEXT NOT NULL,session_id TEXT,sync_id INTEGER,at TEXT,group_id TEXT NOT NULL,position INTEGER NOT NULL);
|
|
24
|
+
CREATE INDEX IF NOT EXISTS records_group ON records(group_id,at,position);
|
|
25
|
+
CREATE TABLE IF NOT EXISTS passages(id INTEGER PRIMARY KEY AUTOINCREMENT,hash TEXT NOT NULL UNIQUE,body TEXT,embedded INTEGER NOT NULL DEFAULT 0);
|
|
26
|
+
CREATE TABLE IF NOT EXISTS chunk_links(id INTEGER PRIMARY KEY AUTOINCREMENT,ref TEXT NOT NULL REFERENCES records(ref) ON DELETE CASCADE,offset INTEGER NOT NULL,passage_id INTEGER NOT NULL REFERENCES passages(id));
|
|
27
|
+
CREATE INDEX IF NOT EXISTS links_ref ON chunk_links(ref);
|
|
28
|
+
CREATE INDEX IF NOT EXISTS links_passage ON chunk_links(passage_id);
|
|
29
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS passage_vectors USING vec0(embedding float[384] distance_metric=cosine);
|
|
30
|
+
`);
|
|
31
|
+
if (prior === 'history-index-v1') {
|
|
32
|
+
const sequence = db.prepare("SELECT seq FROM sqlite_sequence WHERE name='chunks'").get()?.seq || 0;
|
|
33
|
+
const insert = db.prepare('INSERT OR IGNORE INTO passages(hash,body) VALUES(?,?)');
|
|
34
|
+
const id = db.prepare('SELECT id,body FROM passages WHERE hash=?');
|
|
35
|
+
const link = db.prepare('INSERT INTO chunk_links(id,ref,offset,passage_id) VALUES(?,?,?,?)');
|
|
36
|
+
for (const row of db.prepare('SELECT * FROM chunks ORDER BY id').all()) {
|
|
37
|
+
insert.run(row.hash, row.body);
|
|
38
|
+
const passage = id.get(row.hash);
|
|
39
|
+
if (passage.body !== row.body)
|
|
40
|
+
throw new Error('Conflicting passage hash');
|
|
41
|
+
link.run(row.id, row.ref, row.offset, passage.id);
|
|
42
|
+
}
|
|
43
|
+
if (!db.prepare("UPDATE sqlite_sequence SET seq=MAX(seq,?) WHERE name='chunk_links'").run(sequence).changes && sequence)
|
|
44
|
+
db.prepare('INSERT INTO sqlite_sequence(name,seq) VALUES(?,?)').run('chunk_links', sequence);
|
|
45
|
+
const cache = db.prepare('SELECT embedding FROM embedding_cache WHERE hash=?');
|
|
46
|
+
const vector = db.prepare('SELECT embedding FROM vectors WHERE rowid=?');
|
|
47
|
+
const save = db.prepare('INSERT INTO passage_vectors(rowid,embedding) VALUES(?,?)');
|
|
48
|
+
// Cache-only rows are retained too; ordinary admission refresh may later
|
|
49
|
+
// prune genuinely unreferenced data, just as before this migration.
|
|
50
|
+
for (const row of db.prepare('SELECT hash FROM embedding_cache').all())
|
|
51
|
+
insert.run(row.hash, null);
|
|
52
|
+
for (const passage of db.prepare('SELECT id,hash FROM passages ORDER BY id').all()) {
|
|
53
|
+
let bytes = cache.get(passage.hash)?.embedding;
|
|
54
|
+
for (const row of db.prepare('SELECT id FROM chunks WHERE hash=? AND embedded=1').all(passage.hash)) {
|
|
55
|
+
const saved = vector.get(BigInt(row.id))?.embedding;
|
|
56
|
+
if (!saved || (bytes && !saved.equals(bytes)))
|
|
57
|
+
throw new Error('Existing embeddings disagree; migration refused');
|
|
58
|
+
bytes ||= saved;
|
|
59
|
+
}
|
|
60
|
+
if (!bytes)
|
|
61
|
+
continue;
|
|
62
|
+
if (bytes.length !== 1536 || [...new Float32Array(Uint8Array.from(bytes).buffer)].some(value => !Number.isFinite(value)))
|
|
63
|
+
throw new Error('Invalid retained embedding');
|
|
64
|
+
save.run(BigInt(passage.id), bytes);
|
|
65
|
+
db.prepare('UPDATE passages SET embedded=1 WHERE id=?').run(passage.id);
|
|
66
|
+
}
|
|
67
|
+
// Preserve the external-content FTS index and occurrence IDs, including
|
|
68
|
+
// its document frequencies. Only its backing table becomes a join view.
|
|
69
|
+
db.exec('DROP TRIGGER IF EXISTS chunks_insert; DROP TRIGGER IF EXISTS chunks_delete; DROP TABLE chunks; DROP TABLE vectors; DROP TABLE embedding_cache');
|
|
70
|
+
if (!db.prepare("SELECT 1 FROM meta WHERE key='covered-tails-removed'").get()) {
|
|
71
|
+
const remove = db.prepare('DELETE FROM chunk_links WHERE id=?');
|
|
72
|
+
for (const row of db.prepare(`SELECT c.id,c.offset,r.json FROM chunk_links c JOIN records r ON r.ref=c.ref
|
|
73
|
+
WHERE c.offset>0 AND NOT EXISTS(SELECT 1 FROM chunk_links n WHERE n.ref=c.ref AND n.offset>c.offset)
|
|
74
|
+
AND EXISTS(SELECT 1 FROM chunk_links p WHERE p.ref=c.ref AND p.offset=c.offset-700)`).all()) {
|
|
75
|
+
const text = JSON.parse(row.json).text;
|
|
76
|
+
if (typeof text === 'string' && row.offset + 100 >= text.length) {
|
|
77
|
+
// External-content FTS needs an explicit delete before its link is removed.
|
|
78
|
+
const body = db.prepare('SELECT body FROM passages p JOIN chunk_links c ON p.id=c.passage_id WHERE c.id=?').get(row.id).body;
|
|
79
|
+
db.prepare("INSERT INTO words(words,rowid,body) VALUES('delete',?,?)").run(row.id, body);
|
|
80
|
+
remove.run(row.id);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
db.exec("UPDATE records SET json=json_remove(json,'$.text')");
|
|
85
|
+
}
|
|
86
|
+
if (db.pragma('table_info(passages)').some(column => column.name === 'body')) {
|
|
87
|
+
if (db.prepare('SELECT 1 FROM chunk_links c JOIN passages p ON p.id=c.passage_id WHERE p.body IS NULL LIMIT 1').get())
|
|
88
|
+
throw new Error('A stored search passage is missing; conversion refused');
|
|
89
|
+
// FTS retains token postings/positions, not original passage strings.
|
|
90
|
+
// Re-tokenize existing inputs only; vector bytes and IDs do not change.
|
|
91
|
+
db.exec(`CREATE VIRTUAL TABLE words_source USING fts5(body,content='',contentless_delete=1);
|
|
92
|
+
INSERT INTO words_source(rowid,body) SELECT c.id,p.body FROM chunk_links c JOIN passages p ON p.id=c.passage_id;
|
|
93
|
+
DROP TRIGGER IF EXISTS links_insert; DROP TRIGGER IF EXISTS links_delete;
|
|
94
|
+
DROP VIEW IF EXISTS chunks; DROP TABLE IF EXISTS words;
|
|
95
|
+
ALTER TABLE words_source RENAME TO words;
|
|
96
|
+
ALTER TABLE passages DROP COLUMN body;`);
|
|
97
|
+
}
|
|
98
|
+
db.exec(`
|
|
99
|
+
CREATE VIEW IF NOT EXISTS chunks AS SELECT c.id,c.ref,c.offset,p.hash,p.embedded FROM chunk_links c JOIN passages p ON p.id=c.passage_id;
|
|
100
|
+
CREATE VIEW IF NOT EXISTS embedding_cache AS SELECT p.hash,v.embedding FROM passages p JOIN passage_vectors v ON v.rowid=p.id;
|
|
101
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS words USING fts5(body,content='',contentless_delete=1);
|
|
102
|
+
CREATE TRIGGER IF NOT EXISTS links_delete AFTER DELETE ON chunk_links BEGIN DELETE FROM words WHERE rowid=old.id; END;
|
|
103
|
+
CREATE TRIGGER IF NOT EXISTS passage_delete AFTER DELETE ON passages BEGIN DELETE FROM passage_vectors WHERE rowid=old.id; END;
|
|
104
|
+
`);
|
|
105
|
+
const oldModel = db.prepare("SELECT value FROM meta WHERE key='model'").get()?.value;
|
|
106
|
+
if (oldModel && oldModel !== fingerprint) {
|
|
107
|
+
// A real fingerprint change invalidates derived passages, never canonical records.
|
|
108
|
+
db.exec('DELETE FROM records; DELETE FROM passages');
|
|
109
|
+
}
|
|
110
|
+
const metadata = db.prepare('INSERT INTO meta(key,value) VALUES(?,?) ON CONFLICT(key) DO UPDATE SET value=excluded.value WHERE meta.value!=excluded.value');
|
|
111
|
+
metadata.run('schema', version);
|
|
112
|
+
metadata.run('model', fingerprint);
|
|
113
|
+
db.prepare("INSERT OR IGNORE INTO meta VALUES('covered-tails-removed','1')").run();
|
|
114
|
+
})();
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/memory/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export interface HistoryRecord {
|
|
2
|
+
ref: string;
|
|
3
|
+
kind: 'session' | 'snapshot' | 'discussion' | 'decisions' | 'carry_forward';
|
|
4
|
+
session_id: string | null;
|
|
5
|
+
sync_id: number | null;
|
|
6
|
+
origin_ref: string | null;
|
|
7
|
+
title: string;
|
|
8
|
+
workspace: string;
|
|
9
|
+
role: string;
|
|
10
|
+
at: string | null;
|
|
11
|
+
qualification: string;
|
|
12
|
+
text: string;
|
|
13
|
+
/** Comparable only within one original source session. */
|
|
14
|
+
sequence?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface HistoryQuery {
|
|
17
|
+
question: string;
|
|
18
|
+
session_id?: string;
|
|
19
|
+
session_ids?: string[];
|
|
20
|
+
kind?: 'sources' | 'conversation';
|
|
21
|
+
recent?: boolean;
|
|
22
|
+
/** Bounded status follow-ups; intended for the larger text-answer packet. */
|
|
23
|
+
reconcile?: boolean;
|
|
24
|
+
topics?: string[];
|
|
25
|
+
sync_id?: number;
|
|
26
|
+
before?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface HistoryResults {
|
|
29
|
+
mode: 'hybrid';
|
|
30
|
+
results: (HistoryRecord & {
|
|
31
|
+
offset: number;
|
|
32
|
+
score: number;
|
|
33
|
+
lead?: string;
|
|
34
|
+
})[];
|
|
35
|
+
limitations: string;
|
|
36
|
+
reconciliation?: {
|
|
37
|
+
checked_narratives: number;
|
|
38
|
+
omitted_narratives: number;
|
|
39
|
+
omitted_threads: number;
|
|
40
|
+
threads: {
|
|
41
|
+
earlier_ref: string;
|
|
42
|
+
later_refs: string[];
|
|
43
|
+
matched_terms: string[];
|
|
44
|
+
other_candidates: number;
|
|
45
|
+
}[];
|
|
46
|
+
qualification: string;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export interface HistoryPage {
|
|
50
|
+
record: HistoryRecord;
|
|
51
|
+
offset: number;
|
|
52
|
+
total: number;
|
|
53
|
+
neighbors: HistoryRecord[];
|
|
54
|
+
}
|
|
55
|
+
export interface HistoryUpdate {
|
|
56
|
+
stage: 'scanning' | 'downloading' | 'loading' | 'indexing' | 'searching' | 'reading';
|
|
57
|
+
completed: number;
|
|
58
|
+
total: number;
|
|
59
|
+
reused: number;
|
|
60
|
+
parallelism?: {
|
|
61
|
+
workers: number;
|
|
62
|
+
threads: number;
|
|
63
|
+
};
|
|
64
|
+
remaining_seconds: number | null;
|
|
65
|
+
downloaded_bytes: number;
|
|
66
|
+
download_total_bytes: number;
|
|
67
|
+
}
|
|
68
|
+
export interface HistoryProgress {
|
|
69
|
+
active: boolean;
|
|
70
|
+
background?: boolean;
|
|
71
|
+
queued: number;
|
|
72
|
+
elapsed_ms: number;
|
|
73
|
+
updated_at: number | null;
|
|
74
|
+
work: HistoryUpdate | null;
|
|
75
|
+
}
|
|
76
|
+
export type ReportHistory = (update: HistoryUpdate) => void;
|
|
77
|
+
export declare const historyUpdate: (stage: HistoryUpdate["stage"], fields?: Partial<Omit<HistoryUpdate, "stage">>) => HistoryUpdate;
|
|
78
|
+
export interface Embedder {
|
|
79
|
+
readonly fingerprint: string;
|
|
80
|
+
ready(): boolean;
|
|
81
|
+
setup(report?: ReportHistory, allowDownload?: boolean): Promise<void>;
|
|
82
|
+
embed(text: string, query: boolean): Promise<Float32Array>;
|
|
83
|
+
embedMany?(texts: string[], parallel?: boolean): Promise<Float32Array[]>;
|
|
84
|
+
readonly parallelism?: {
|
|
85
|
+
workers: number;
|
|
86
|
+
threads: number;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.historyUpdate = void 0;
|
|
4
|
+
const historyUpdate = (stage, fields = {}) => ({
|
|
5
|
+
stage, completed: 0, total: 0, reused: 0, remaining_seconds: null, downloaded_bytes: 0, download_total_bytes: 0, ...fields,
|
|
6
|
+
});
|
|
7
|
+
exports.historyUpdate = historyUpdate;
|
|
8
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":";;;AAgEO,MAAM,aAAa,GAAG,CAAC,KAA6B,EAAE,SAAgD,EAAE,EAAiB,EAAE,CAAC,CAAC;IAClI,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,GAAG,MAAM;CAC3H,CAAC,CAAC;AAFU,QAAA,aAAa,iBAEvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/memory/worker.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
9
|
+
const index_1 = require("./index");
|
|
10
|
+
const embedding_pool_1 = require("./embedding-pool");
|
|
11
|
+
const types_1 = require("./types");
|
|
12
|
+
const registry_1 = require("../sources/registry");
|
|
13
|
+
// A private IPC child, not an HTTP service or tool runner. Native SQLite/vector
|
|
14
|
+
// work and embedding WASM cannot block the dashboard or audio event loop.
|
|
15
|
+
process.umask(0o077);
|
|
16
|
+
const directory = process.argv[2];
|
|
17
|
+
if (!process.send || !directory || !path_1.default.isAbsolute(directory) || !process.argv[3])
|
|
18
|
+
process.exit(1);
|
|
19
|
+
const roots = (0, registry_1.sourceRoots)(JSON.parse(process.argv[3]));
|
|
20
|
+
const folder = path_1.default.join(directory, 'memory');
|
|
21
|
+
fs_1.default.mkdirSync(folder, { recursive: true, mode: 0o700 });
|
|
22
|
+
const source = new better_sqlite3_1.default(path_1.default.join(directory, 'draken.db'), { readonly: true, fileMustExist: true });
|
|
23
|
+
source.pragma('query_only = ON');
|
|
24
|
+
source.pragma('busy_timeout = 5000');
|
|
25
|
+
const file = path_1.default.join(folder, 'index.sqlite'), db = new better_sqlite3_1.default(file);
|
|
26
|
+
fs_1.default.chmodSync(file, 0o600);
|
|
27
|
+
const model = new embedding_pool_1.EmbeddingPool(path_1.default.join(folder, 'model'));
|
|
28
|
+
const index = new index_1.HistoryIndex(db, source, model, roots);
|
|
29
|
+
let busy = false;
|
|
30
|
+
process.on('message', async (message) => {
|
|
31
|
+
if (busy || !message || !Number.isSafeInteger(message.id))
|
|
32
|
+
return;
|
|
33
|
+
busy = true;
|
|
34
|
+
try {
|
|
35
|
+
let lastSent = 0, stage = '';
|
|
36
|
+
const report = progress => {
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
if (progress.stage !== stage || now - lastSent >= 250 || (progress.total > 0 && progress.completed === progress.total)) {
|
|
39
|
+
stage = progress.stage;
|
|
40
|
+
lastSent = now;
|
|
41
|
+
process.send?.({ id: message.id, progress });
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
let value;
|
|
45
|
+
if (message.method === 'prepare') {
|
|
46
|
+
await index.prepare({ before: message.before }, report, true);
|
|
47
|
+
value = null;
|
|
48
|
+
}
|
|
49
|
+
else if (message.method === 'search')
|
|
50
|
+
value = await index.search(message.query, report);
|
|
51
|
+
else if (message.method === 'search-prepared')
|
|
52
|
+
value = await index.search(message.query, report, true);
|
|
53
|
+
else if (message.method === 'read' || message.method === 'read-prepared') {
|
|
54
|
+
report((0, types_1.historyUpdate)('reading'));
|
|
55
|
+
value = index.read(message.ref, message.offset, message.method === 'read-prepared' ? message.before : undefined);
|
|
56
|
+
}
|
|
57
|
+
else
|
|
58
|
+
throw new Error('Unknown history operation');
|
|
59
|
+
process.send?.({ id: message.id, value });
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Never emit private source text, a model input, filesystem error or rejected
|
|
63
|
+
// request diagnostics. The parent provides action-specific recovery wording.
|
|
64
|
+
process.send?.({ id: message.id, error: true });
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
busy = false;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
async function close() {
|
|
71
|
+
// Let SQLite finish its normal checkpoint on orderly retirement. Abrupt exit
|
|
72
|
+
// still leaves committed WAL work recoverable; no VACUUM or history pruning.
|
|
73
|
+
try {
|
|
74
|
+
await model.close();
|
|
75
|
+
db.close();
|
|
76
|
+
source.close();
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
process.once('SIGTERM', close);
|
|
83
|
+
process.once('disconnect', close);
|
|
84
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/memory/worker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Run npm's JS entry under the current Node, never a Windows command shim or
|
|
2
|
+
* a shell command. Paths with spaces/metacharacters remain individual argv. */
|
|
3
|
+
export declare function npmCli(env?: NodeJS.ProcessEnv, node?: string): string;
|
|
4
|
+
//# sourceMappingURL=npm-cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm-cli.d.ts","sourceRoot":"","sources":["../src/npm-cli.ts"],"names":[],"mappings":"AAGA;+EAC+E;AAC/E,wBAAgB,MAAM,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,IAAI,SAAmB,GAAG,MAAM,CAkB5F"}
|
package/dist/npm-cli.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.npmCli = npmCli;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
/** Run npm's JS entry under the current Node, never a Windows command shim or
|
|
10
|
+
* a shell command. Paths with spaces/metacharacters remain individual argv. */
|
|
11
|
+
function npmCli(env = process.env, node = process.execPath) {
|
|
12
|
+
const candidates = [env.npm_execpath,
|
|
13
|
+
path_1.default.join(path_1.default.dirname(node), 'node_modules/npm/bin/npm-cli.js'),
|
|
14
|
+
path_1.default.resolve(path_1.default.dirname(node), '../lib/node_modules/npm/bin/npm-cli.js')];
|
|
15
|
+
for (const directory of (env.PATH || '').split(path_1.default.delimiter).filter(Boolean)) {
|
|
16
|
+
for (const name of ['npm', 'npm.cmd']) {
|
|
17
|
+
try {
|
|
18
|
+
const file = fs_1.default.realpathSync(path_1.default.join(directory, name));
|
|
19
|
+
candidates.push(file, path_1.default.join(path_1.default.dirname(file), 'node_modules/npm/bin/npm-cli.js'), path_1.default.join(directory, 'node_modules/npm/bin/npm-cli.js'));
|
|
20
|
+
}
|
|
21
|
+
catch { /* Try the other known npm installation layouts. */ }
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const found = candidates.find(file => {
|
|
25
|
+
try {
|
|
26
|
+
return file && path_1.default.basename(file) === 'npm-cli.js' && fs_1.default.statSync(file).isFile();
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
if (!found)
|
|
33
|
+
throw new Error('npm was not found. Install Node.js 22.19+ with npm, then run setup again.');
|
|
34
|
+
return found;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=npm-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm-cli.js","sourceRoot":"","sources":["../src/npm-cli.ts"],"names":[],"mappings":";;;;;AAKA,wBAkBC;AAvBD,4CAAoB;AACpB,gDAAwB;AAExB;+EAC+E;AAC/E,SAAgB,MAAM,CAAC,MAAyB,OAAO,CAAC,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,QAAQ;IAClF,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,YAAY;QAClC,cAAI,CAAC,IAAI,CAAC,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,iCAAiC,CAAC;QAChE,cAAI,CAAC,OAAO,CAAC,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,wCAAwC,CAAC,CAAC,CAAC;IAC9E,KAAK,MAAM,SAAS,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,cAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/E,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,YAAE,CAAC,YAAY,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;gBACzD,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,cAAI,CAAC,IAAI,CAAC,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,iCAAiC,CAAC,EACpF,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iCAAiC,CAAC,CAAC,CAAC;YAC7D,CAAC;YAAC,MAAM,CAAC,CAAC,mDAAmD,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACnC,IAAI,CAAC;YAAC,OAAO,IAAI,IAAI,cAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,YAAY,IAAI,YAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IACpH,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IACzG,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const PI_VERSION = "1.5.0";
|
|
2
|
+
export declare const PI_PACKAGE = "@earendil-works/pi-coding-agent";
|
|
3
|
+
export declare const isolatedFlags: string[];
|
|
4
|
+
import type { PiSetupStatus } from '../types';
|
|
5
|
+
export declare function piPaths(): {
|
|
6
|
+
root: string;
|
|
7
|
+
agent: string;
|
|
8
|
+
home: string;
|
|
9
|
+
work: string;
|
|
10
|
+
selected: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function managedEnvironment(): NodeJS.ProcessEnv;
|
|
13
|
+
/** Refuse symlinked private subdirectories, without creating anything during GET/status. */
|
|
14
|
+
export declare function privateDirectory(directory: string, create?: boolean): void;
|
|
15
|
+
export declare function executable(name: string): string | undefined;
|
|
16
|
+
export declare function selectedPi(): {
|
|
17
|
+
source: "managed";
|
|
18
|
+
binary: string;
|
|
19
|
+
prefix: string[];
|
|
20
|
+
env: NodeJS.ProcessEnv;
|
|
21
|
+
agent: string;
|
|
22
|
+
} | {
|
|
23
|
+
source: "external";
|
|
24
|
+
binary: string;
|
|
25
|
+
prefix: string[];
|
|
26
|
+
env: {
|
|
27
|
+
[key: string]: string | undefined;
|
|
28
|
+
TZ?: string | undefined;
|
|
29
|
+
};
|
|
30
|
+
agent: string;
|
|
31
|
+
};
|
|
32
|
+
export declare function stopPiChecks(): Promise<void>;
|
|
33
|
+
export declare function piSetupStatus(fresh?: boolean): Promise<PiSetupStatus>;
|
|
34
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/pi/runtime.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,UAAU,UAAU,CAAC;AAClC,eAAO,MAAM,UAAU,oCAAoC,CAAC;AAC5D,eAAO,MAAM,aAAa,UAA0K,CAAC;AACrM,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,wBAAgB,OAAO;;;;;;EAGtB;AAKD,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,UAAU,CAKtD;AAED,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,IAAI,CAUxE;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK3D;AAED,wBAAgB,UAAU;;;;;;;;;;;;;;;EA0BzB;AAID,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAMlD;AAmDD,wBAAgB,aAAa,CAAC,KAAK,UAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAOnE"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isolatedFlags = exports.PI_PACKAGE = exports.PI_VERSION = void 0;
|
|
7
|
+
exports.piPaths = piPaths;
|
|
8
|
+
exports.managedEnvironment = managedEnvironment;
|
|
9
|
+
exports.privateDirectory = privateDirectory;
|
|
10
|
+
exports.executable = executable;
|
|
11
|
+
exports.selectedPi = selectedPi;
|
|
12
|
+
exports.stopPiChecks = stopPiChecks;
|
|
13
|
+
exports.piSetupStatus = piSetupStatus;
|
|
14
|
+
const fs_1 = __importDefault(require("fs"));
|
|
15
|
+
const os_1 = __importDefault(require("os"));
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const child_process_1 = require("child_process");
|
|
18
|
+
const schema_1 = require("../db/schema");
|
|
19
|
+
const store_1 = require("../sync/store");
|
|
20
|
+
exports.PI_VERSION = '1.5.0';
|
|
21
|
+
exports.PI_PACKAGE = '@earendil-works/pi-coding-agent';
|
|
22
|
+
exports.isolatedFlags = ['--no-session', '--no-tools', '--no-extensions', '--no-mcp', '--no-skills', '--no-prompt-templates', '--no-themes', '--no-context-files', '--no-approve', '--offline'];
|
|
23
|
+
function piPaths() {
|
|
24
|
+
const root = path_1.default.join((0, schema_1.getDataDir)(), 'pi');
|
|
25
|
+
return { root, agent: path_1.default.join(root, 'agent'), home: path_1.default.join(root, 'home'), work: path_1.default.join(root, 'workspace'), selected: path_1.default.join(root, 'selected.json') };
|
|
26
|
+
}
|
|
27
|
+
// Managed children must not inherit unrelated provider keys, pi ownership, custom
|
|
28
|
+
// model URLs, preload hooks or the user's global pi configuration. A private HOME
|
|
29
|
+
// also prevents ambient cloud-credential lookup. This is not an OS sandbox.
|
|
30
|
+
function managedEnvironment() {
|
|
31
|
+
const paths = piPaths(), env = {};
|
|
32
|
+
for (const key of ['PATH', 'PATHEXT', 'SYSTEMROOT', 'WINDIR', 'COMSPEC', 'LANG', 'LC_ALL', 'TERM', 'COLORTERM', 'TMPDIR', 'TMP', 'TEMP'])
|
|
33
|
+
if (process.env[key])
|
|
34
|
+
env[key] = process.env[key];
|
|
35
|
+
return { ...env, HOME: paths.home, USERPROFILE: paths.home, APPDATA: path_1.default.join(paths.home, 'AppData', 'Roaming'), LOCALAPPDATA: path_1.default.join(paths.home, 'AppData', 'Local'),
|
|
36
|
+
PI_CODING_AGENT_DIR: paths.agent, PI_OFFLINE: '1', PI_SKIP_VERSION_CHECK: '1', PI_TELEMETRY: '0' };
|
|
37
|
+
}
|
|
38
|
+
/** Refuse symlinked private subdirectories, without creating anything during GET/status. */
|
|
39
|
+
function privateDirectory(directory, create = false) {
|
|
40
|
+
const base = (0, schema_1.getDataDir)(), relative = path_1.default.relative(base, directory);
|
|
41
|
+
if (!relative || relative.startsWith('..') || path_1.default.isAbsolute(relative))
|
|
42
|
+
throw new Error('Invalid private pi directory');
|
|
43
|
+
if (create)
|
|
44
|
+
fs_1.default.mkdirSync(base, { recursive: true, mode: 0o700 });
|
|
45
|
+
let current = base;
|
|
46
|
+
for (const part of relative.split(path_1.default.sep)) {
|
|
47
|
+
current = path_1.default.join(current, part);
|
|
48
|
+
try {
|
|
49
|
+
const stat = fs_1.default.lstatSync(current);
|
|
50
|
+
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
51
|
+
throw new Error('Private pi directories must not be symlinks or files');
|
|
52
|
+
if (create)
|
|
53
|
+
fs_1.default.chmodSync(current, 0o700);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (error.code !== 'ENOENT')
|
|
57
|
+
throw error;
|
|
58
|
+
if (create)
|
|
59
|
+
fs_1.default.mkdirSync(current, { mode: 0o700 });
|
|
60
|
+
else
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function executable(name) {
|
|
66
|
+
const candidates = name.includes('/') || name.includes('\\') ? [path_1.default.resolve(name)]
|
|
67
|
+
: (process.env.PATH || '').split(path_1.default.delimiter).filter(Boolean).flatMap(dir => process.platform === 'win32'
|
|
68
|
+
? ['', '.exe', '.cmd', '.bat'].map(ext => path_1.default.join(dir, name + ext)) : [path_1.default.join(dir, name)]);
|
|
69
|
+
return candidates.find(file => { try {
|
|
70
|
+
fs_1.default.accessSync(file, process.platform === 'win32' ? fs_1.default.constants.F_OK : fs_1.default.constants.X_OK);
|
|
71
|
+
return fs_1.default.statSync(file).isFile();
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
} });
|
|
76
|
+
}
|
|
77
|
+
function selectedPi() {
|
|
78
|
+
const paths = piPaths();
|
|
79
|
+
if (!process.env.DRAKEN_PI_BIN && fs_1.default.existsSync(paths.selected)) {
|
|
80
|
+
privateDirectory(paths.root);
|
|
81
|
+
privateDirectory(paths.agent);
|
|
82
|
+
privateDirectory(paths.home);
|
|
83
|
+
privateDirectory(paths.work);
|
|
84
|
+
for (const name of ['auth.json', 'settings.json', 'models.json', 'models-store.json', 'trust.json']) {
|
|
85
|
+
try {
|
|
86
|
+
if (fs_1.default.lstatSync(path_1.default.join(paths.agent, name)).isSymbolicLink())
|
|
87
|
+
throw new Error('Private pi configuration files must not be symlinks');
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
if (error.code !== 'ENOENT')
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (fs_1.default.lstatSync(paths.selected).isSymbolicLink() || fs_1.default.statSync(paths.selected).size > 1024)
|
|
95
|
+
throw new Error('Invalid private pi selection; run draken setup to repair it.');
|
|
96
|
+
const selected = JSON.parse(fs_1.default.readFileSync(paths.selected, 'utf8'));
|
|
97
|
+
if (selected.version !== 1 || typeof selected.runtime !== 'string' || !/^\d+\.\d+\.\d+-[a-f0-9]{16}$/.test(selected.runtime))
|
|
98
|
+
throw new Error('Invalid private pi selection; run draken setup to repair it.');
|
|
99
|
+
const runtime = path_1.default.join(paths.root, 'runtime', selected.runtime);
|
|
100
|
+
privateDirectory(runtime);
|
|
101
|
+
const cli = path_1.default.join(runtime, 'node_modules', exports.PI_PACKAGE, 'dist', 'cli.js');
|
|
102
|
+
if (!fs_1.default.existsSync(cli))
|
|
103
|
+
throw new Error('Private pi is incomplete. Run draken setup; credentials will be kept.');
|
|
104
|
+
const relative = path_1.default.relative(fs_1.default.realpathSync(runtime), fs_1.default.realpathSync(cli));
|
|
105
|
+
if (relative.startsWith('..') || path_1.default.isAbsolute(relative))
|
|
106
|
+
throw new Error('Private pi executable is outside its runtime');
|
|
107
|
+
return { source: 'managed', binary: process.execPath, prefix: [cli], env: managedEnvironment(), agent: paths.agent };
|
|
108
|
+
}
|
|
109
|
+
const name = process.env.DRAKEN_PI_BIN || 'pi', binary = executable(name) || name;
|
|
110
|
+
const env = { ...process.env };
|
|
111
|
+
delete env.PI_SESSION_ID;
|
|
112
|
+
delete env.PI_SESSION_FILE;
|
|
113
|
+
// npm's Windows command shims cannot be spawned without a shell. Resolve only
|
|
114
|
+
// the known pi package next to the shim; never evaluate .cmd text.
|
|
115
|
+
const candidate = /\.cmd$/i.test(binary) ? path_1.default.join(path_1.default.dirname(binary), 'node_modules', exports.PI_PACKAGE, 'dist', 'cli.js') : '';
|
|
116
|
+
return { source: 'external', binary: candidate && fs_1.default.existsSync(candidate) ? process.execPath : binary,
|
|
117
|
+
prefix: candidate && fs_1.default.existsSync(candidate) ? [candidate] : [], env,
|
|
118
|
+
agent: process.env.PI_CODING_AGENT_DIR || path_1.default.join(os_1.default.homedir(), '.pi', 'agent') };
|
|
119
|
+
}
|
|
120
|
+
const checks = new Set();
|
|
121
|
+
let checksStopping = false;
|
|
122
|
+
async function stopPiChecks() {
|
|
123
|
+
checksStopping = true;
|
|
124
|
+
await Promise.all([...checks].map(child => new Promise(resolve => {
|
|
125
|
+
const timer = setTimeout(() => child.kill('SIGKILL'), 1000);
|
|
126
|
+
timer.unref();
|
|
127
|
+
child.once('close', () => { clearTimeout(timer); resolve(); });
|
|
128
|
+
child.kill('SIGTERM');
|
|
129
|
+
})));
|
|
130
|
+
}
|
|
131
|
+
/** Bounded protocol-only subprocess. Never return raw stderr or credential output. */
|
|
132
|
+
async function inspect(args) {
|
|
133
|
+
if (checksStopping)
|
|
134
|
+
throw new Error('Pi status checks are stopping');
|
|
135
|
+
const pi = selectedPi();
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
const child = (0, child_process_1.spawn)(pi.binary, [...pi.prefix, ...args], { env: { ...pi.env, PI_OFFLINE: '1', PI_SKIP_VERSION_CHECK: '1' },
|
|
138
|
+
cwd: fs_1.default.existsSync((0, schema_1.getDataDir)()) ? (0, schema_1.getDataDir)() : os_1.default.tmpdir(), shell: false, stdio: ['ignore', 'pipe', 'ignore'] });
|
|
139
|
+
checks.add(child);
|
|
140
|
+
let text = '', failed = false, kill;
|
|
141
|
+
const terminate = () => { failed = true; child.kill('SIGTERM'); kill = setTimeout(() => child.kill('SIGKILL'), 1000); kill.unref(); };
|
|
142
|
+
const timer = setTimeout(terminate, 8000);
|
|
143
|
+
timer.unref();
|
|
144
|
+
child.stdout.setEncoding('utf8');
|
|
145
|
+
child.stdout.on('data', chunk => { if (failed)
|
|
146
|
+
return; if (Buffer.byteLength(text) + Buffer.byteLength(chunk) > 8192)
|
|
147
|
+
terminate();
|
|
148
|
+
else
|
|
149
|
+
text += chunk; });
|
|
150
|
+
child.once('error', error => { clearTimeout(timer); if (kill)
|
|
151
|
+
clearTimeout(kill); reject(error); });
|
|
152
|
+
child.once('close', code => { checks.delete(child); clearTimeout(timer); if (kill)
|
|
153
|
+
clearTimeout(kill); if (failed)
|
|
154
|
+
reject(new Error('Pi status check did not finish safely'));
|
|
155
|
+
else
|
|
156
|
+
resolve({ code, text }); });
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
async function diagnose() {
|
|
160
|
+
let selected;
|
|
161
|
+
try {
|
|
162
|
+
selected = selectedPi();
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return { source: 'managed', state: 'error', version: null, agent_dir: piPaths().agent, models: [], message: 'Private pi is incomplete or its selection is invalid. Run draken setup to repair it; credentials are retained.' };
|
|
166
|
+
}
|
|
167
|
+
const result = { source: selected.source, state: 'missing', version: null, agent_dir: selected.agent, models: [], message: '' };
|
|
168
|
+
try {
|
|
169
|
+
const version = await inspect(['--version']), match = /^(\d+)\.(\d+)\.(\d+)\s*$/.exec(version.text.trim());
|
|
170
|
+
if (version.code !== 0 || !match || Number(match[1]) < 1 || (Number(match[1]) === 1 && Number(match[2]) < 4)) {
|
|
171
|
+
return { ...result, state: 'incompatible', message: 'Pi 1.4+ is required. Run draken setup for the pinned private runtime, or update your explicit DRAKEN_PI_BIN.' };
|
|
172
|
+
}
|
|
173
|
+
result.version = match[0].trim();
|
|
174
|
+
const models = (0, store_1.defaultModels)();
|
|
175
|
+
for (const model of [...new Set([models.summary, models.final])]) {
|
|
176
|
+
const check = await inspect(['auth', 'check', '--model', model, '--json', '--no-refresh']);
|
|
177
|
+
let state = 'unavailable';
|
|
178
|
+
try {
|
|
179
|
+
const value = JSON.parse(check.text);
|
|
180
|
+
if (check.code === 0 && value.status === 'ready')
|
|
181
|
+
state = 'configured';
|
|
182
|
+
else if (check.code === 1 && value.status === 'not_ready' && value.reason === 'credentials_not_configured')
|
|
183
|
+
state = 'needs_login';
|
|
184
|
+
}
|
|
185
|
+
catch { /* Unsupported model/status protocol, not known-ready. */ }
|
|
186
|
+
result.models.push({ model, state });
|
|
187
|
+
}
|
|
188
|
+
result.state = result.models.every(model => model.state === 'configured') ? 'configured' : result.models.some(model => model.state === 'unavailable') ? 'error' : 'needs_login';
|
|
189
|
+
result.message = result.state === 'configured' ? 'Pi credentials are configured. Model access and billing are not verified by this local check.'
|
|
190
|
+
: result.state === 'needs_login' ? 'Run draken login in a terminal on this server, then use /login in pi. Sign in to the provider used by the configured summary models.'
|
|
191
|
+
: 'Pi could not resolve the configured models or credentials. Run draken doctor and check model configuration; no provider or model was substituted.';
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
result.state = error.code === 'ENOENT' ? 'missing' : 'error';
|
|
195
|
+
result.message = result.state === 'missing' ? 'Summarization needs pi. Run draken setup to install a private copy, then draken login.' : 'Pi status could not be checked. Run draken doctor in a terminal on this server.';
|
|
196
|
+
}
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
let cached;
|
|
200
|
+
function piSetupStatus(fresh = false) {
|
|
201
|
+
const key = JSON.stringify([(0, schema_1.getDataDir)(), process.env.DRAKEN_PI_BIN, process.env.PATH, process.env.PI_CODING_AGENT_DIR, (0, store_1.defaultModels)()]);
|
|
202
|
+
if (cached?.key === key && (cached.pending || !fresh && cached.until > Date.now()))
|
|
203
|
+
return cached.value;
|
|
204
|
+
const value = diagnose();
|
|
205
|
+
const entry = { key, until: Date.now() + 30_000, pending: true, value };
|
|
206
|
+
cached = entry;
|
|
207
|
+
void value.then(() => { entry.pending = false; }, () => { entry.pending = false; });
|
|
208
|
+
return value;
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=runtime.js.map
|