@pennixrv/trellis-core 0.6.17
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/LICENSE +235 -0
- package/dist/channel/api/assert.d.ts +3 -0
- package/dist/channel/api/assert.d.ts.map +1 -0
- package/dist/channel/api/assert.js +11 -0
- package/dist/channel/api/assert.js.map +1 -0
- package/dist/channel/api/context.d.ts +21 -0
- package/dist/channel/api/context.d.ts.map +1 -0
- package/dist/channel/api/context.js +99 -0
- package/dist/channel/api/context.js.map +1 -0
- package/dist/channel/api/create.d.ts +9 -0
- package/dist/channel/api/create.d.ts.map +1 -0
- package/dist/channel/api/create.js +104 -0
- package/dist/channel/api/create.js.map +1 -0
- package/dist/channel/api/inbox.d.ts +51 -0
- package/dist/channel/api/inbox.d.ts.map +1 -0
- package/dist/channel/api/inbox.js +176 -0
- package/dist/channel/api/inbox.js.map +1 -0
- package/dist/channel/api/interrupt.d.ts +31 -0
- package/dist/channel/api/interrupt.d.ts.map +1 -0
- package/dist/channel/api/interrupt.js +102 -0
- package/dist/channel/api/interrupt.js.map +1 -0
- package/dist/channel/api/post-thread.d.ts +14 -0
- package/dist/channel/api/post-thread.d.ts.map +1 -0
- package/dist/channel/api/post-thread.js +109 -0
- package/dist/channel/api/post-thread.js.map +1 -0
- package/dist/channel/api/read.d.ts +17 -0
- package/dist/channel/api/read.d.ts.map +1 -0
- package/dist/channel/api/read.js +44 -0
- package/dist/channel/api/read.js.map +1 -0
- package/dist/channel/api/resolve.d.ts +21 -0
- package/dist/channel/api/resolve.d.ts.map +1 -0
- package/dist/channel/api/resolve.js +28 -0
- package/dist/channel/api/resolve.js.map +1 -0
- package/dist/channel/api/runtime.d.ts +70 -0
- package/dist/channel/api/runtime.d.ts.map +1 -0
- package/dist/channel/api/runtime.js +11 -0
- package/dist/channel/api/runtime.js.map +1 -0
- package/dist/channel/api/send.d.ts +4 -0
- package/dist/channel/api/send.d.ts.map +1 -0
- package/dist/channel/api/send.js +52 -0
- package/dist/channel/api/send.js.map +1 -0
- package/dist/channel/api/spawn.d.ts +13 -0
- package/dist/channel/api/spawn.d.ts.map +1 -0
- package/dist/channel/api/spawn.js +74 -0
- package/dist/channel/api/spawn.js.map +1 -0
- package/dist/channel/api/title.d.ts +5 -0
- package/dist/channel/api/title.d.ts.map +1 -0
- package/dist/channel/api/title.js +40 -0
- package/dist/channel/api/title.js.map +1 -0
- package/dist/channel/api/types.d.ts +65 -0
- package/dist/channel/api/types.d.ts.map +1 -0
- package/dist/channel/api/types.js +2 -0
- package/dist/channel/api/types.js.map +1 -0
- package/dist/channel/api/watch-channels.d.ts +40 -0
- package/dist/channel/api/watch-channels.d.ts.map +1 -0
- package/dist/channel/api/watch-channels.js +143 -0
- package/dist/channel/api/watch-channels.js.map +1 -0
- package/dist/channel/api/watch.d.ts +11 -0
- package/dist/channel/api/watch.d.ts.map +1 -0
- package/dist/channel/api/watch.js +17 -0
- package/dist/channel/api/watch.js.map +1 -0
- package/dist/channel/api/workers.d.ts +69 -0
- package/dist/channel/api/workers.d.ts.map +1 -0
- package/dist/channel/api/workers.js +145 -0
- package/dist/channel/api/workers.js.map +1 -0
- package/dist/channel/index.d.ts +38 -0
- package/dist/channel/index.d.ts.map +1 -0
- package/dist/channel/index.js +23 -0
- package/dist/channel/index.js.map +1 -0
- package/dist/channel/internal/store/channel-metadata.d.ts +23 -0
- package/dist/channel/internal/store/channel-metadata.d.ts.map +1 -0
- package/dist/channel/internal/store/channel-metadata.js +94 -0
- package/dist/channel/internal/store/channel-metadata.js.map +1 -0
- package/dist/channel/internal/store/delivery.d.ts +27 -0
- package/dist/channel/internal/store/delivery.d.ts.map +1 -0
- package/dist/channel/internal/store/delivery.js +37 -0
- package/dist/channel/internal/store/delivery.js.map +1 -0
- package/dist/channel/internal/store/events.d.ts +215 -0
- package/dist/channel/internal/store/events.d.ts.map +1 -0
- package/dist/channel/internal/store/events.js +209 -0
- package/dist/channel/internal/store/events.js.map +1 -0
- package/dist/channel/internal/store/filter.d.ts +21 -0
- package/dist/channel/internal/store/filter.d.ts.map +1 -0
- package/dist/channel/internal/store/filter.js +75 -0
- package/dist/channel/internal/store/filter.js.map +1 -0
- package/dist/channel/internal/store/inbox.d.ts +17 -0
- package/dist/channel/internal/store/inbox.d.ts.map +1 -0
- package/dist/channel/internal/store/inbox.js +30 -0
- package/dist/channel/internal/store/inbox.js.map +1 -0
- package/dist/channel/internal/store/lock.d.ts +17 -0
- package/dist/channel/internal/store/lock.d.ts.map +1 -0
- package/dist/channel/internal/store/lock.js +88 -0
- package/dist/channel/internal/store/lock.js.map +1 -0
- package/dist/channel/internal/store/paths.d.ts +57 -0
- package/dist/channel/internal/store/paths.d.ts.map +1 -0
- package/dist/channel/internal/store/paths.js +264 -0
- package/dist/channel/internal/store/paths.js.map +1 -0
- package/dist/channel/internal/store/schema.d.ts +77 -0
- package/dist/channel/internal/store/schema.d.ts.map +1 -0
- package/dist/channel/internal/store/schema.js +127 -0
- package/dist/channel/internal/store/schema.js.map +1 -0
- package/dist/channel/internal/store/seq.d.ts +23 -0
- package/dist/channel/internal/store/seq.d.ts.map +1 -0
- package/dist/channel/internal/store/seq.js +175 -0
- package/dist/channel/internal/store/seq.js.map +1 -0
- package/dist/channel/internal/store/thread-state.d.ts +37 -0
- package/dist/channel/internal/store/thread-state.d.ts.map +1 -0
- package/dist/channel/internal/store/thread-state.js +206 -0
- package/dist/channel/internal/store/thread-state.js.map +1 -0
- package/dist/channel/internal/store/watch.d.ts +10 -0
- package/dist/channel/internal/store/watch.d.ts.map +1 -0
- package/dist/channel/internal/store/watch.js +129 -0
- package/dist/channel/internal/store/watch.js.map +1 -0
- package/dist/channel/internal/store/worker-state.d.ts +56 -0
- package/dist/channel/internal/store/worker-state.d.ts.map +1 -0
- package/dist/channel/internal/store/worker-state.js +220 -0
- package/dist/channel/internal/store/worker-state.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/mem/adapters/claude.d.ts +22 -0
- package/dist/mem/adapters/claude.d.ts.map +1 -0
- package/dist/mem/adapters/claude.js +209 -0
- package/dist/mem/adapters/claude.js.map +1 -0
- package/dist/mem/adapters/codex.d.ts +55 -0
- package/dist/mem/adapters/codex.d.ts.map +1 -0
- package/dist/mem/adapters/codex.js +344 -0
- package/dist/mem/adapters/codex.js.map +1 -0
- package/dist/mem/adapters/grok.d.ts +41 -0
- package/dist/mem/adapters/grok.d.ts.map +1 -0
- package/dist/mem/adapters/grok.js +202 -0
- package/dist/mem/adapters/grok.js.map +1 -0
- package/dist/mem/adapters/opencode.d.ts +35 -0
- package/dist/mem/adapters/opencode.d.ts.map +1 -0
- package/dist/mem/adapters/opencode.js +437 -0
- package/dist/mem/adapters/opencode.js.map +1 -0
- package/dist/mem/adapters/pi.d.ts +24 -0
- package/dist/mem/adapters/pi.d.ts.map +1 -0
- package/dist/mem/adapters/pi.js +290 -0
- package/dist/mem/adapters/pi.js.map +1 -0
- package/dist/mem/adapters/zcode.d.ts +76 -0
- package/dist/mem/adapters/zcode.d.ts.map +1 -0
- package/dist/mem/adapters/zcode.js +434 -0
- package/dist/mem/adapters/zcode.js.map +1 -0
- package/dist/mem/context.d.ts +23 -0
- package/dist/mem/context.d.ts.map +1 -0
- package/dist/mem/context.js +120 -0
- package/dist/mem/context.js.map +1 -0
- package/dist/mem/dialogue.d.ts +32 -0
- package/dist/mem/dialogue.d.ts.map +1 -0
- package/dist/mem/dialogue.js +0 -0
- package/dist/mem/dialogue.js.map +1 -0
- package/dist/mem/filter.d.ts +31 -0
- package/dist/mem/filter.d.ts.map +1 -0
- package/dist/mem/filter.js +66 -0
- package/dist/mem/filter.js.map +1 -0
- package/dist/mem/index.d.ts +18 -0
- package/dist/mem/index.d.ts.map +1 -0
- package/dist/mem/index.js +17 -0
- package/dist/mem/index.js.map +1 -0
- package/dist/mem/internal/jsonl.d.ts +35 -0
- package/dist/mem/internal/jsonl.d.ts.map +1 -0
- package/dist/mem/internal/jsonl.js +125 -0
- package/dist/mem/internal/jsonl.js.map +1 -0
- package/dist/mem/internal/paths.d.ts +67 -0
- package/dist/mem/internal/paths.d.ts.map +1 -0
- package/dist/mem/internal/paths.js +194 -0
- package/dist/mem/internal/paths.js.map +1 -0
- package/dist/mem/internal/sqlite-readonly.d.ts +77 -0
- package/dist/mem/internal/sqlite-readonly.d.ts.map +1 -0
- package/dist/mem/internal/sqlite-readonly.js +797 -0
- package/dist/mem/internal/sqlite-readonly.js.map +1 -0
- package/dist/mem/phase.d.ts +45 -0
- package/dist/mem/phase.d.ts.map +1 -0
- package/dist/mem/phase.js +220 -0
- package/dist/mem/phase.js.map +1 -0
- package/dist/mem/projects.d.ts +13 -0
- package/dist/mem/projects.d.ts.map +1 -0
- package/dist/mem/projects.js +47 -0
- package/dist/mem/projects.js.map +1 -0
- package/dist/mem/search.d.ts +39 -0
- package/dist/mem/search.d.ts.map +1 -0
- package/dist/mem/search.js +133 -0
- package/dist/mem/search.js.map +1 -0
- package/dist/mem/sessions.d.ts +38 -0
- package/dist/mem/sessions.d.ts.map +1 -0
- package/dist/mem/sessions.js +318 -0
- package/dist/mem/sessions.js.map +1 -0
- package/dist/mem/types.d.ts +188 -0
- package/dist/mem/types.d.ts.map +1 -0
- package/dist/mem/types.js +10 -0
- package/dist/mem/types.js.map +1 -0
- package/dist/task/index.d.ts +9 -0
- package/dist/task/index.d.ts.map +1 -0
- package/dist/task/index.js +9 -0
- package/dist/task/index.js.map +1 -0
- package/dist/task/paths.d.ts +37 -0
- package/dist/task/paths.d.ts.map +1 -0
- package/dist/task/paths.js +49 -0
- package/dist/task/paths.js.map +1 -0
- package/dist/task/phase.d.ts +27 -0
- package/dist/task/phase.d.ts.map +1 -0
- package/dist/task/phase.js +24 -0
- package/dist/task/phase.js.map +1 -0
- package/dist/task/records.d.ts +39 -0
- package/dist/task/records.d.ts.map +1 -0
- package/dist/task/records.js +89 -0
- package/dist/task/records.js.map +1 -0
- package/dist/task/schema.d.ts +77 -0
- package/dist/task/schema.d.ts.map +1 -0
- package/dist/task/schema.js +220 -0
- package/dist/task/schema.js.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +4 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode 1.2+ persisted-session reader.
|
|
3
|
+
*
|
|
4
|
+
* OpenCode stores sessions in a WAL-mode SQLite database under its XDG data
|
|
5
|
+
* dir (see `internal/paths.ts:opencodeDbPath`). The three tables this adapter
|
|
6
|
+
* reads, confirmed against a live 1.18 store:
|
|
7
|
+
*
|
|
8
|
+
* - `session` — id / parent_id (sub-agent chain) / title / directory
|
|
9
|
+
* (workspace cwd) / time_created / time_updated
|
|
10
|
+
* - `message` — id / session_id / time_created / data (JSON: {role, ...})
|
|
11
|
+
* - `part` — message_id / session_id / time_created /
|
|
12
|
+
* data (JSON: {type: "text"|"tool"|"reasoning"|..., ...})
|
|
13
|
+
*
|
|
14
|
+
* SQLite access is via the zero-dependency parser in
|
|
15
|
+
* `internal/sqlite-readonly.ts`. A `better-sqlite3`-backed reader shipped in
|
|
16
|
+
* 0.6.0-beta.3 and was reverted one release later because its prebuild
|
|
17
|
+
* download + node-gyp fallback broke `npm install` on Windows and restricted
|
|
18
|
+
* networks; no native module, WASM blob, system `sqlite3`, or install-time
|
|
19
|
+
* build step may come back with this adapter.
|
|
20
|
+
*
|
|
21
|
+
* Everything here is read-only: the database is snapshotted and parsed, never
|
|
22
|
+
* opened for write, locked, checkpointed, or copied over.
|
|
23
|
+
*/
|
|
24
|
+
import * as fs from "node:fs";
|
|
25
|
+
import { compactionBoundaryTurn, stripInjectionTags, isBootstrapTurn, } from "../dialogue.js";
|
|
26
|
+
import { inRangeOverlap, sameProject } from "../filter.js";
|
|
27
|
+
import { openSqliteReadOnly, SqliteParseError, SqliteSnapshotUnstableError, } from "../internal/sqlite-readonly.js";
|
|
28
|
+
import { opencodeDbPath } from "../internal/paths.js";
|
|
29
|
+
import { searchInDialogue } from "../search.js";
|
|
30
|
+
function parseDialogueRole(v) {
|
|
31
|
+
return v === "user" || v === "assistant" ? v : undefined;
|
|
32
|
+
}
|
|
33
|
+
/** Safely parse the JSON stored in a `data` column. Returns null on failure —
|
|
34
|
+
* a row carrying hostile or truncated JSON is dropped, never thrown on. */
|
|
35
|
+
function parseDataJson(raw) {
|
|
36
|
+
if (typeof raw !== "string")
|
|
37
|
+
return null;
|
|
38
|
+
try {
|
|
39
|
+
const v = JSON.parse(raw);
|
|
40
|
+
return v && typeof v === "object" && !Array.isArray(v)
|
|
41
|
+
? v
|
|
42
|
+
: null;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// ---------- schema contract ----------
|
|
49
|
+
const SESSION_TABLE = "session";
|
|
50
|
+
const MESSAGE_TABLE = "message";
|
|
51
|
+
const PART_TABLE = "part";
|
|
52
|
+
/** Accepted spellings for the session's workspace directory, in preference
|
|
53
|
+
* order. Current OpenCode uses `directory`; `cwd` is accepted so an older or
|
|
54
|
+
* renamed store still lists rather than failing closed. */
|
|
55
|
+
const SESSION_CWD_COLUMNS = ["directory", "cwd"];
|
|
56
|
+
/**
|
|
57
|
+
* Thrown when the store is a readable SQLite file whose tables/columns do not
|
|
58
|
+
* match anything this adapter knows how to interpret. Kept distinct from a
|
|
59
|
+
* corrupt file so the CLI can tell "OpenCode changed its schema" apart from
|
|
60
|
+
* "this database is damaged" — both degrade to an empty result.
|
|
61
|
+
*/
|
|
62
|
+
class OpencodeSchemaError extends SqliteParseError {
|
|
63
|
+
constructor(message) {
|
|
64
|
+
super(message);
|
|
65
|
+
this.name = "OpencodeSchemaError";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const DB_UNREADABLE_WARNING_CODE = "opencode-db-unreadable";
|
|
69
|
+
const DB_SNAPSHOT_UNSTABLE_WARNING_CODE = "opencode-db-snapshot-unstable";
|
|
70
|
+
const DB_SCHEMA_WARNING_CODE = "opencode-db-schema-unsupported";
|
|
71
|
+
/** Record one degradation per condition per command — repeated failures while
|
|
72
|
+
* scanning many sessions must not produce repeated terminal noise. */
|
|
73
|
+
function pushDbWarning(warnings, dbPath, error) {
|
|
74
|
+
const code = error instanceof SqliteSnapshotUnstableError
|
|
75
|
+
? DB_SNAPSHOT_UNSTABLE_WARNING_CODE
|
|
76
|
+
: error instanceof OpencodeSchemaError
|
|
77
|
+
? DB_SCHEMA_WARNING_CODE
|
|
78
|
+
: DB_UNREADABLE_WARNING_CODE;
|
|
79
|
+
if (warnings.some((warning) => warning.code === code))
|
|
80
|
+
return;
|
|
81
|
+
const message = code === DB_SNAPSHOT_UNSTABLE_WARNING_CODE
|
|
82
|
+
? `OpenCode is writing to its session database; retry in a moment (${dbPath})`
|
|
83
|
+
: code === DB_SCHEMA_WARNING_CODE
|
|
84
|
+
? `unsupported OpenCode session schema (${dbPath}): ${error.message}`
|
|
85
|
+
: `cannot read OpenCode session database (${dbPath}): ${error.message}`;
|
|
86
|
+
warnings.push({ code, message });
|
|
87
|
+
}
|
|
88
|
+
function findTable(db, name) {
|
|
89
|
+
const table = db.listTables().find((item) => item.name === name);
|
|
90
|
+
if (!table) {
|
|
91
|
+
throw new OpencodeSchemaError(`missing table: ${name}`);
|
|
92
|
+
}
|
|
93
|
+
return table;
|
|
94
|
+
}
|
|
95
|
+
/** True when `CREATE TABLE` sql declares a column of this exact name. Column
|
|
96
|
+
* semantics are matched by name only — never by position, so a reordered or
|
|
97
|
+
* extended schema cannot silently shift values into the wrong field. */
|
|
98
|
+
function declaresColumn(table, name) {
|
|
99
|
+
const pattern = new RegExp(`(?:\\(|,)\\s*["\`\\[]?${name}(?:["\`\\]]|\\b)`, "i");
|
|
100
|
+
return pattern.test(table.sql);
|
|
101
|
+
}
|
|
102
|
+
function requireColumns(table, names) {
|
|
103
|
+
const missing = names.filter((name) => !declaresColumn(table, name));
|
|
104
|
+
if (missing.length > 0) {
|
|
105
|
+
throw new OpencodeSchemaError(`table ${table.name} is missing column(s): ${missing.join(", ")}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/** Pick the first accepted spelling a table actually declares. */
|
|
109
|
+
function requireOneOfColumns(table, candidates) {
|
|
110
|
+
const found = candidates.find((name) => declaresColumn(table, name));
|
|
111
|
+
if (!found) {
|
|
112
|
+
throw new OpencodeSchemaError(`table ${table.name} has none of the expected column(s): ${candidates.join(" / ")}`);
|
|
113
|
+
}
|
|
114
|
+
return found;
|
|
115
|
+
}
|
|
116
|
+
/** The declared schema and the decoded rows can disagree when the sql failed to
|
|
117
|
+
* parse; re-check against a real row before trusting any of it. */
|
|
118
|
+
function requireRowColumns(rows, tableName, names) {
|
|
119
|
+
const first = rows[0];
|
|
120
|
+
if (!first)
|
|
121
|
+
return;
|
|
122
|
+
const missing = names.filter((name) => !(name in first));
|
|
123
|
+
if (missing.length > 0) {
|
|
124
|
+
throw new OpencodeSchemaError(`table ${tableName} is missing column(s): ${missing.join(", ")}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function emptySessionStore() {
|
|
128
|
+
return { messagesBySession: new Map(), partsByMsg: new Map() };
|
|
129
|
+
}
|
|
130
|
+
/** Scan position breaks ties so rows written in the same millisecond still
|
|
131
|
+
* order the same way on every run. */
|
|
132
|
+
function byTimeThenScan(a, b) {
|
|
133
|
+
return a.time_created !== b.time_created
|
|
134
|
+
? a.time_created - b.time_created
|
|
135
|
+
: a.seq - b.seq;
|
|
136
|
+
}
|
|
137
|
+
function buildSessionStore(allMessages, allParts) {
|
|
138
|
+
const messagesBySession = new Map();
|
|
139
|
+
for (let i = 0; i < allMessages.length; i++) {
|
|
140
|
+
const row = allMessages[i];
|
|
141
|
+
if (!row)
|
|
142
|
+
continue;
|
|
143
|
+
const sessionId = typeof row.session_id === "string" ? row.session_id : "";
|
|
144
|
+
const id = typeof row.id === "string" ? row.id : "";
|
|
145
|
+
if (!sessionId || !id)
|
|
146
|
+
continue;
|
|
147
|
+
const data = parseDataJson(row.data);
|
|
148
|
+
const role = parseDialogueRole(data?.role);
|
|
149
|
+
if (!role)
|
|
150
|
+
continue;
|
|
151
|
+
const list = messagesBySession.get(sessionId) ?? [];
|
|
152
|
+
list.push({
|
|
153
|
+
id,
|
|
154
|
+
time_created: typeof row.time_created === "number" ? row.time_created : 0,
|
|
155
|
+
seq: i,
|
|
156
|
+
role,
|
|
157
|
+
});
|
|
158
|
+
messagesBySession.set(sessionId, list);
|
|
159
|
+
}
|
|
160
|
+
const partsByMsg = new Map();
|
|
161
|
+
for (let i = 0; i < allParts.length; i++) {
|
|
162
|
+
const row = allParts[i];
|
|
163
|
+
if (!row)
|
|
164
|
+
continue;
|
|
165
|
+
const msgId = typeof row.message_id === "string" ? row.message_id : "";
|
|
166
|
+
if (!msgId)
|
|
167
|
+
continue;
|
|
168
|
+
const data = parseDataJson(row.data);
|
|
169
|
+
if (!data)
|
|
170
|
+
continue;
|
|
171
|
+
const list = partsByMsg.get(msgId) ?? [];
|
|
172
|
+
list.push({
|
|
173
|
+
time_created: typeof row.time_created === "number" ? row.time_created : 0,
|
|
174
|
+
seq: i,
|
|
175
|
+
data,
|
|
176
|
+
});
|
|
177
|
+
partsByMsg.set(msgId, list);
|
|
178
|
+
}
|
|
179
|
+
for (const list of messagesBySession.values())
|
|
180
|
+
list.sort(byTimeThenScan);
|
|
181
|
+
for (const list of partsByMsg.values())
|
|
182
|
+
list.sort(byTimeThenScan);
|
|
183
|
+
return { messagesBySession, partsByMsg };
|
|
184
|
+
}
|
|
185
|
+
/** Validate `message` / `part` and return the rows selected by `sessionId`, or
|
|
186
|
+
* every row when `sessionId` is undefined (the search store). */
|
|
187
|
+
function scanMessagesAndParts(db, sessionId) {
|
|
188
|
+
const messageTable = findTable(db, MESSAGE_TABLE);
|
|
189
|
+
requireColumns(messageTable, ["id", "session_id", "data"]);
|
|
190
|
+
const partTable = findTable(db, PART_TABLE);
|
|
191
|
+
requireColumns(partTable, ["message_id", "data"]);
|
|
192
|
+
const messages = sessionId === undefined
|
|
193
|
+
? db.scanTable(MESSAGE_TABLE)
|
|
194
|
+
: db.scanTable(MESSAGE_TABLE, (row) => row.session_id === sessionId);
|
|
195
|
+
requireRowColumns(messages, MESSAGE_TABLE, ["id", "session_id", "data"]);
|
|
196
|
+
let parts;
|
|
197
|
+
if (sessionId === undefined) {
|
|
198
|
+
parts = db.scanTable(PART_TABLE);
|
|
199
|
+
}
|
|
200
|
+
else if (declaresColumn(partTable, "session_id")) {
|
|
201
|
+
// Current OpenCode denormalizes `session_id` onto `part`, so one session's
|
|
202
|
+
// parts can be selected without first materializing its message ids.
|
|
203
|
+
parts = db.scanTable(PART_TABLE, (row) => row.session_id === sessionId);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
const messageIds = new Set(messages
|
|
207
|
+
.map((row) => row.id)
|
|
208
|
+
.filter((id) => typeof id === "string"));
|
|
209
|
+
parts = db.scanTable(PART_TABLE, (row) => typeof row.message_id === "string" && messageIds.has(row.message_id));
|
|
210
|
+
}
|
|
211
|
+
requireRowColumns(parts, PART_TABLE, ["message_id", "data"]);
|
|
212
|
+
return buildSessionStore(messages, parts);
|
|
213
|
+
}
|
|
214
|
+
/** Search-scoped whole-db store, prepared and released by the orchestrator.
|
|
215
|
+
* One-session extract / context calls never populate it. */
|
|
216
|
+
let preparedStore = null;
|
|
217
|
+
export function prepareOpencodeSessionStore(dbPath, warnings = []) {
|
|
218
|
+
let store = emptySessionStore();
|
|
219
|
+
if (fs.existsSync(dbPath)) {
|
|
220
|
+
try {
|
|
221
|
+
const db = openSqliteReadOnly(dbPath);
|
|
222
|
+
try {
|
|
223
|
+
store = scanMessagesAndParts(db, undefined);
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
db.close();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
if (!(error instanceof SqliteParseError))
|
|
231
|
+
throw error;
|
|
232
|
+
pushDbWarning(warnings, dbPath, error);
|
|
233
|
+
store = emptySessionStore();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
preparedStore = { dbPath, store };
|
|
237
|
+
}
|
|
238
|
+
export function releaseOpencodeSessionStore() {
|
|
239
|
+
preparedStore = null;
|
|
240
|
+
}
|
|
241
|
+
/** Read one session's messages + parts, reusing the search-scoped store when
|
|
242
|
+
* the orchestrator prepared one for this same database. */
|
|
243
|
+
function readSessionMessages(dbPath, sessionId, warnings) {
|
|
244
|
+
if (preparedStore?.dbPath === dbPath) {
|
|
245
|
+
return {
|
|
246
|
+
messages: preparedStore.store.messagesBySession.get(sessionId) ?? [],
|
|
247
|
+
partsByMsg: preparedStore.store.partsByMsg,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
if (!fs.existsSync(dbPath))
|
|
251
|
+
return { messages: [], partsByMsg: new Map() };
|
|
252
|
+
let store;
|
|
253
|
+
try {
|
|
254
|
+
const db = openSqliteReadOnly(dbPath);
|
|
255
|
+
try {
|
|
256
|
+
store = scanMessagesAndParts(db, sessionId);
|
|
257
|
+
}
|
|
258
|
+
finally {
|
|
259
|
+
db.close();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
if (!(error instanceof SqliteParseError))
|
|
264
|
+
throw error;
|
|
265
|
+
pushDbWarning(warnings, dbPath, error);
|
|
266
|
+
return { messages: [], partsByMsg: new Map() };
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
messages: store.messagesBySession.get(sessionId) ?? [],
|
|
270
|
+
partsByMsg: store.partsByMsg,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
// ---------- compaction ----------
|
|
274
|
+
function isRecord(value) {
|
|
275
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
276
|
+
}
|
|
277
|
+
function isCompactionSummaryPart(data) {
|
|
278
|
+
return (data.type === "compaction" &&
|
|
279
|
+
(typeof data.tail_start_id === "string" || isRecord(data.compactBoundary)));
|
|
280
|
+
}
|
|
281
|
+
function compactionMarkerSummaryId(data) {
|
|
282
|
+
return data.type === "compaction" &&
|
|
283
|
+
data.replace === true &&
|
|
284
|
+
typeof data.summaryMessageId === "string"
|
|
285
|
+
? data.summaryMessageId
|
|
286
|
+
: undefined;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Identify the messages that carry a compaction summary. The compacted turns
|
|
290
|
+
* remain as rows in the same database, so they stay in the dialogue and the
|
|
291
|
+
* summary message is rendered as a boundary marker in place.
|
|
292
|
+
*
|
|
293
|
+
* The marker shape (`{type:"compaction", replace, summaryMessageId}` plus a
|
|
294
|
+
* summary part with `tail_start_id` / `compactBoundary`) is the one ZCode
|
|
295
|
+
* inherited from its OpenCode fork. If OpenCode never writes it, no message is
|
|
296
|
+
* classified as a summary and every turn reads as ordinary dialogue.
|
|
297
|
+
*/
|
|
298
|
+
function compactSummaryMessageIds(messages, partsByMsg) {
|
|
299
|
+
const summaryIds = new Set();
|
|
300
|
+
const markerSummaryIds = new Set();
|
|
301
|
+
for (const msg of messages) {
|
|
302
|
+
if (markerSummaryIds.has(msg.id))
|
|
303
|
+
summaryIds.add(msg.id);
|
|
304
|
+
for (const part of partsByMsg.get(msg.id) ?? []) {
|
|
305
|
+
const markerSummaryId = compactionMarkerSummaryId(part.data);
|
|
306
|
+
if (markerSummaryId)
|
|
307
|
+
markerSummaryIds.add(markerSummaryId);
|
|
308
|
+
if (isCompactionSummaryPart(part.data)) {
|
|
309
|
+
summaryIds.add(msg.id);
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return summaryIds;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* One message becomes one turn: its `text` parts concatenated, then cleaned.
|
|
318
|
+
* `reasoning`, `tool`, `step-start` and `step-finish` parts are not dialogue
|
|
319
|
+
* and are skipped. Messages left with no text are dropped.
|
|
320
|
+
*/
|
|
321
|
+
function buildTextTurn(msg, parts, compactSummaryIds) {
|
|
322
|
+
const collected = [];
|
|
323
|
+
let totalRaw = 0;
|
|
324
|
+
for (const part of parts) {
|
|
325
|
+
const pd = part.data;
|
|
326
|
+
if (pd.type !== "text")
|
|
327
|
+
continue;
|
|
328
|
+
const txt = typeof pd.text === "string" ? pd.text : "";
|
|
329
|
+
if (!txt)
|
|
330
|
+
continue;
|
|
331
|
+
totalRaw += txt.length;
|
|
332
|
+
collected.push(stripInjectionTags(txt));
|
|
333
|
+
}
|
|
334
|
+
if (!collected.length)
|
|
335
|
+
return null;
|
|
336
|
+
const merged = collected.join("\n\n");
|
|
337
|
+
if (compactSummaryIds.has(msg.id)) {
|
|
338
|
+
return compactionBoundaryTurn("context compacted here; the turns above are still in the OpenCode database", merged);
|
|
339
|
+
}
|
|
340
|
+
if (isBootstrapTurn(merged, totalRaw))
|
|
341
|
+
return null;
|
|
342
|
+
return merged.trim() ? { role: msg.role, text: merged } : null;
|
|
343
|
+
}
|
|
344
|
+
// ---------- list ----------
|
|
345
|
+
/** Largest absolute time value an ECMAScript Date can represent. */
|
|
346
|
+
const MAX_TIME_VALUE = 8.64e15;
|
|
347
|
+
function toIso(epochMs) {
|
|
348
|
+
// A corrupt or hostile timestamp must degrade to "no timestamp", not throw
|
|
349
|
+
// RangeError out of the row loop and fail the whole command.
|
|
350
|
+
if (typeof epochMs !== "number" || !Number.isFinite(epochMs))
|
|
351
|
+
return undefined;
|
|
352
|
+
if (epochMs <= 0 || epochMs > MAX_TIME_VALUE)
|
|
353
|
+
return undefined;
|
|
354
|
+
return new Date(epochMs).toISOString();
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* List OpenCode sessions from the `session` table only — listing never touches
|
|
358
|
+
* `message` or `part`. A machine with no OpenCode store lists nothing and
|
|
359
|
+
* warns about nothing.
|
|
360
|
+
*/
|
|
361
|
+
export function opencodeListSessions(f, warnings = []) {
|
|
362
|
+
const dbPath = opencodeDbPath();
|
|
363
|
+
if (dbPath === undefined || !fs.existsSync(dbPath))
|
|
364
|
+
return [];
|
|
365
|
+
let rows;
|
|
366
|
+
let cwdColumn;
|
|
367
|
+
try {
|
|
368
|
+
const db = openSqliteReadOnly(dbPath);
|
|
369
|
+
try {
|
|
370
|
+
const table = findTable(db, SESSION_TABLE);
|
|
371
|
+
requireColumns(table, ["id", "time_created", "time_updated"]);
|
|
372
|
+
cwdColumn = requireOneOfColumns(table, SESSION_CWD_COLUMNS);
|
|
373
|
+
rows = db.scanTable(SESSION_TABLE);
|
|
374
|
+
requireRowColumns(rows, SESSION_TABLE, [
|
|
375
|
+
"id",
|
|
376
|
+
cwdColumn,
|
|
377
|
+
"time_created",
|
|
378
|
+
"time_updated",
|
|
379
|
+
]);
|
|
380
|
+
}
|
|
381
|
+
finally {
|
|
382
|
+
db.close();
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
if (!(error instanceof SqliteParseError))
|
|
387
|
+
throw error;
|
|
388
|
+
pushDbWarning(warnings, dbPath, error);
|
|
389
|
+
return [];
|
|
390
|
+
}
|
|
391
|
+
const out = [];
|
|
392
|
+
for (const row of rows) {
|
|
393
|
+
const id = typeof row.id === "string" ? row.id : "";
|
|
394
|
+
if (!id)
|
|
395
|
+
continue;
|
|
396
|
+
const directory = typeof row[cwdColumn] === "string"
|
|
397
|
+
? row[cwdColumn]
|
|
398
|
+
: undefined;
|
|
399
|
+
if (f.cwd && !sameProject(directory, f.cwd))
|
|
400
|
+
continue;
|
|
401
|
+
const created = toIso(row.time_created);
|
|
402
|
+
const updated = toIso(row.time_updated) ?? created;
|
|
403
|
+
if (!inRangeOverlap(created, updated, f))
|
|
404
|
+
continue;
|
|
405
|
+
out.push({
|
|
406
|
+
platform: "opencode",
|
|
407
|
+
id,
|
|
408
|
+
title: typeof row.title === "string" ? row.title : undefined,
|
|
409
|
+
cwd: directory,
|
|
410
|
+
created,
|
|
411
|
+
updated,
|
|
412
|
+
filePath: dbPath,
|
|
413
|
+
// Sub-agent sessions point at their dispatcher; `--include-children`
|
|
414
|
+
// merges them into the parent.
|
|
415
|
+
...(typeof row.parent_id === "string" && row.parent_id
|
|
416
|
+
? { parent_id: row.parent_id }
|
|
417
|
+
: {}),
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
return out;
|
|
421
|
+
}
|
|
422
|
+
// ---------- extract / search ----------
|
|
423
|
+
export function opencodeExtractDialogue(s, warnings = []) {
|
|
424
|
+
const { messages, partsByMsg } = readSessionMessages(s.filePath, s.id, warnings);
|
|
425
|
+
const summaryIds = compactSummaryMessageIds(messages, partsByMsg);
|
|
426
|
+
const turns = [];
|
|
427
|
+
for (const msg of messages) {
|
|
428
|
+
const turn = buildTextTurn(msg, partsByMsg.get(msg.id) ?? [], summaryIds);
|
|
429
|
+
if (turn)
|
|
430
|
+
turns.push(turn);
|
|
431
|
+
}
|
|
432
|
+
return turns;
|
|
433
|
+
}
|
|
434
|
+
export function opencodeSearch(s, kw, warnings = []) {
|
|
435
|
+
return searchInDialogue(opencodeExtractDialogue(s, warnings), kw);
|
|
436
|
+
}
|
|
437
|
+
//# sourceMappingURL=opencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../src/mem/adapters/opencode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persisted Pi Agent session reader.
|
|
3
|
+
*
|
|
4
|
+
* Layout: `~/.pi/agent/sessions/--<encoded-cwd>--/<timestamp>_<id>.jsonl`
|
|
5
|
+
* for the default store, or direct `.jsonl` files under an env/settings
|
|
6
|
+
* configured custom session directory. Entries form a tree via `id` / `parentId`;
|
|
7
|
+
* extraction follows the whole active branch (last entry leaf).
|
|
8
|
+
*
|
|
9
|
+
* Compaction: Pi writes a `compaction` entry naming the first entry it kept.
|
|
10
|
+
* That is Pi's context rule, not a record of what was said — every earlier
|
|
11
|
+
* entry is still on the active path. Extraction keeps the full path and renders
|
|
12
|
+
* the compaction entry as a boundary marker in place.
|
|
13
|
+
*/
|
|
14
|
+
import type { DialogueTurn, MemFilter, MemSessionInfo, SearchHit, TaskPyEvent } from "../types.js";
|
|
15
|
+
interface PiBuilt {
|
|
16
|
+
turns: DialogueTurn[];
|
|
17
|
+
events: TaskPyEvent[];
|
|
18
|
+
}
|
|
19
|
+
export declare function piListSessions(f: MemFilter): MemSessionInfo[];
|
|
20
|
+
export declare function piExtractDialogue(s: MemSessionInfo): DialogueTurn[];
|
|
21
|
+
export declare function piSearch(s: MemSessionInfo, kw: string): SearchHit;
|
|
22
|
+
export declare function collectPiTurnsAndEvents(s: MemSessionInfo): PiBuilt;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=pi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.d.ts","sourceRoot":"","sources":["../../../src/mem/adapters/pi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAoBH,OAAO,KAAK,EAEV,YAAY,EACZ,SAAS,EACT,cAAc,EACd,SAAS,EACT,WAAW,EACZ,MAAM,aAAa,CAAC;AAwCrB,UAAU,OAAO;IACf,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAID,wBAAgB,cAAc,CAAC,CAAC,EAAE,SAAS,GAAG,cAAc,EAAE,CAwD7D;AA2CD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,cAAc,GAAG,YAAY,EAAE,CAEnE;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,CAEjE;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAElE"}
|