opencode-diane 0.0.5
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/CHANGELOG.md +180 -0
- package/LICENSE +21 -0
- package/README.md +206 -0
- package/WIKI.md +1430 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +1632 -0
- package/dist/ingest/adaptive.d.ts +47 -0
- package/dist/ingest/adaptive.js +182 -0
- package/dist/ingest/code-health.d.ts +58 -0
- package/dist/ingest/code-health.js +202 -0
- package/dist/ingest/code-map.d.ts +71 -0
- package/dist/ingest/code-map.js +670 -0
- package/dist/ingest/cross-refs.d.ts +59 -0
- package/dist/ingest/cross-refs.js +1207 -0
- package/dist/ingest/docs.d.ts +49 -0
- package/dist/ingest/docs.js +325 -0
- package/dist/ingest/git.d.ts +77 -0
- package/dist/ingest/git.js +390 -0
- package/dist/ingest/live-session.d.ts +101 -0
- package/dist/ingest/live-session.js +173 -0
- package/dist/ingest/project-notes.d.ts +28 -0
- package/dist/ingest/project-notes.js +102 -0
- package/dist/ingest/project.d.ts +35 -0
- package/dist/ingest/project.js +430 -0
- package/dist/ingest/session-snapshot.d.ts +63 -0
- package/dist/ingest/session-snapshot.js +94 -0
- package/dist/ingest/sessions.d.ts +29 -0
- package/dist/ingest/sessions.js +164 -0
- package/dist/ingest/tables.d.ts +52 -0
- package/dist/ingest/tables.js +360 -0
- package/dist/mining/skill-miner.d.ts +53 -0
- package/dist/mining/skill-miner.js +234 -0
- package/dist/search/bm25.d.ts +81 -0
- package/dist/search/bm25.js +334 -0
- package/dist/search/e5-embedder.d.ts +30 -0
- package/dist/search/e5-embedder.js +91 -0
- package/dist/search/embed-pass.d.ts +26 -0
- package/dist/search/embed-pass.js +43 -0
- package/dist/search/embedder.d.ts +58 -0
- package/dist/search/embedder.js +85 -0
- package/dist/search/inverted-index.d.ts +51 -0
- package/dist/search/inverted-index.js +139 -0
- package/dist/search/ppr.d.ts +44 -0
- package/dist/search/ppr.js +118 -0
- package/dist/search/tokenize.d.ts +26 -0
- package/dist/search/tokenize.js +98 -0
- package/dist/store/eviction.d.ts +16 -0
- package/dist/store/eviction.js +37 -0
- package/dist/store/repository.d.ts +222 -0
- package/dist/store/repository.js +420 -0
- package/dist/store/sqlite-store.d.ts +89 -0
- package/dist/store/sqlite-store.js +252 -0
- package/dist/store/vector-store.d.ts +66 -0
- package/dist/store/vector-store.js +160 -0
- package/dist/types.d.ts +385 -0
- package/dist/types.js +9 -0
- package/dist/utils/file-log.d.ts +87 -0
- package/dist/utils/file-log.js +215 -0
- package/dist/utils/peer-detection.d.ts +45 -0
- package/dist/utils/peer-detection.js +90 -0
- package/dist/utils/shell.d.ts +43 -0
- package/dist/utils/shell.js +110 -0
- package/dist/utils/usage-skill.d.ts +42 -0
- package/dist/utils/usage-skill.js +129 -0
- package/dist/utils/xlsx.d.ts +36 -0
- package/dist/utils/xlsx.js +270 -0
- package/grammars/tree-sitter-c.wasm +0 -0
- package/grammars/tree-sitter-c_sharp.wasm +0 -0
- package/grammars/tree-sitter-cpp.wasm +0 -0
- package/grammars/tree-sitter-css.wasm +0 -0
- package/grammars/tree-sitter-go.wasm +0 -0
- package/grammars/tree-sitter-html.wasm +0 -0
- package/grammars/tree-sitter-java.wasm +0 -0
- package/grammars/tree-sitter-javascript.wasm +0 -0
- package/grammars/tree-sitter-json.wasm +0 -0
- package/grammars/tree-sitter-php.wasm +0 -0
- package/grammars/tree-sitter-python.wasm +0 -0
- package/grammars/tree-sitter-rust.wasm +0 -0
- package/grammars/tree-sitter-typescript.wasm +0 -0
- package/package.json +80 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* opencode-diane — type definitions.
|
|
3
|
+
*
|
|
4
|
+
* The store is hierarchical: top-level `category` partitions the
|
|
5
|
+
* memory set, each entry has a `subject` (mid-level slug for
|
|
6
|
+
* coarse filtering) and a free-form `content` body that's the
|
|
7
|
+
* leaf-level text searched by BM25.
|
|
8
|
+
*/
|
|
9
|
+
export type Category = "git-history" | "project-facts" | "code-health" | "code-map" | "session-trace" | "session-snapshot" | "agent-note" | "skill-mined" | "custom";
|
|
10
|
+
/** A single memory entry — a leaf in the hierarchy. */
|
|
11
|
+
export interface Memory {
|
|
12
|
+
/** Stable id, e.g. `mem_000123`. */
|
|
13
|
+
id: string;
|
|
14
|
+
category: Category;
|
|
15
|
+
/** Human-readable slug grouping related entries (file path, task name, etc.). */
|
|
16
|
+
subject: string;
|
|
17
|
+
/** The actual text searched by BM25 and shown to the agent. */
|
|
18
|
+
content: string;
|
|
19
|
+
/** Optional tags for filtering (e.g. "bugfix", "framework:django"). */
|
|
20
|
+
tags: string[];
|
|
21
|
+
/** Where this memory came from (e.g. `git:abc123`, `session:sess_xyz`, `agent`). */
|
|
22
|
+
source: string;
|
|
23
|
+
/** Epoch ms. */
|
|
24
|
+
createdAt: number;
|
|
25
|
+
/** Last time the entry was returned by a recall query. */
|
|
26
|
+
usedAt: number;
|
|
27
|
+
/** Number of recalls that returned this entry. */
|
|
28
|
+
useCount: number;
|
|
29
|
+
/** Approx byte size of content + subject + tags JSON — used for budget. */
|
|
30
|
+
sizeBytes: number;
|
|
31
|
+
/** If true, never evicted regardless of budget. */
|
|
32
|
+
pinned?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/** On-disk JSON representation. */
|
|
35
|
+
export interface MemoryStoreFile {
|
|
36
|
+
version: 1;
|
|
37
|
+
memories: Memory[];
|
|
38
|
+
meta: {
|
|
39
|
+
ingestedAt: Record<string, number>;
|
|
40
|
+
lastEvictionAt: number | null;
|
|
41
|
+
schema: 1;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Result of a recall query. */
|
|
45
|
+
export interface RecallHit {
|
|
46
|
+
memory: Memory;
|
|
47
|
+
score: number;
|
|
48
|
+
}
|
|
49
|
+
/** Plugin-level configuration (everything optional with defaults). */
|
|
50
|
+
export interface UserConfig {
|
|
51
|
+
/** Max disk usage for memory store, in megabytes. Default 50. */
|
|
52
|
+
maxMemoryDiskMB?: number;
|
|
53
|
+
/** Run ingest on plugin startup. Default true. */
|
|
54
|
+
autoIngestOnStartup?: boolean;
|
|
55
|
+
/** Cap on commits walked by the git ingester. Default 500. */
|
|
56
|
+
gitHistoryDepth?: number;
|
|
57
|
+
/** If true, run even when the directory isn't a detected workable repo. Default false. */
|
|
58
|
+
forceActive?: boolean;
|
|
59
|
+
/** Where to write SKILL.md files (relative to project root). Default ".opencode/skills". */
|
|
60
|
+
skillsOutputDir?: string;
|
|
61
|
+
/** Min cluster size to mine a skill. Default 3. */
|
|
62
|
+
skillMiningMinCluster?: number;
|
|
63
|
+
/** Whether to ingest other OpenCode sessions for this project. Default true. */
|
|
64
|
+
ingestSessions?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Build a tree-sitter "code map" of file signatures (Aider-style).
|
|
67
|
+
* Default `true` since v0.0.4. Web-tree-sitter plus vendored grammar
|
|
68
|
+
* wasm (~10.3 MB across thirteen languages) ships with the package
|
|
69
|
+
* regardless; this flag controls whether the ingester RUNS at
|
|
70
|
+
* startup. Set `false` to disable if you don't want structural
|
|
71
|
+
* signatures in the store.
|
|
72
|
+
*/
|
|
73
|
+
enableCodeMap?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* On first startup, write `<skillsOutputDir>/<prefix>using-memory/SKILL.md`
|
|
76
|
+
* so OpenCode surfaces a "call memory_recall first" instruction to
|
|
77
|
+
* the agent at session start. The plugin's nudge hook and tool
|
|
78
|
+
* descriptions already point the same way; this is the one-time
|
|
79
|
+
* upfront push.
|
|
80
|
+
*
|
|
81
|
+
* Defaults to `true` since v0.0.4. Set `false` to never install it.
|
|
82
|
+
* The file is written only when it does not already exist, so a
|
|
83
|
+
* user can edit it and the edits survive every subsequent startup
|
|
84
|
+
* — and a user can delete it (with this option still true) to opt
|
|
85
|
+
* out for the lifetime of that checkout.
|
|
86
|
+
*/
|
|
87
|
+
installUsageSkill?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Walk `<root>/docs/` (and conventional root-level docs like
|
|
90
|
+
* CHANGELOG.md, CONTRIBUTING.md, ARCHITECTURE.md, …) and index
|
|
91
|
+
* each H1/H2/H3 heading as a recallable section pointer
|
|
92
|
+
* (`<path>:<line> # <heading>` + first paragraph). Default `true`.
|
|
93
|
+
*/
|
|
94
|
+
ingestDocs?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Index root-level agent-instruction files (AGENTS.md, CLAUDE.md,
|
|
97
|
+
* GEMINI.md, COPILOT.md, CONVENTIONS.md, .cursorrules,
|
|
98
|
+
* .windsurfrules, .clinerules) as project facts so the agent sees
|
|
99
|
+
* the repo's house rules within the first recall. Default `true`.
|
|
100
|
+
*/
|
|
101
|
+
ingestProjectNotes?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Walk for `.csv`, `.tsv`, `.xlsx`, `.xls`, `.xlsm` files and index
|
|
104
|
+
* their column headers (first row only — never row data). XLSX/XLS
|
|
105
|
+
* files are handled via SheetJS, lazy-loaded only when a spreadsheet
|
|
106
|
+
* is actually encountered (projects with no spreadsheets pay no
|
|
107
|
+
* module-load cost). Default `true`.
|
|
108
|
+
*/
|
|
109
|
+
ingestTableHeaders?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Run the grammar-agnostic cross-reference ingester: detects file-to-
|
|
112
|
+
* file connections in any language (Pascal, Ruby, Perl, Lua, …) and
|
|
113
|
+
* config DSLs (JSON / YAML / TOML) where one file references another
|
|
114
|
+
* by path. Multi-signal corroborated; filesystem-grounded signals
|
|
115
|
+
* (path resolves to existing file) emit edges alone, lexical signals
|
|
116
|
+
* (identifier mention) require an orthogonal corroboration before
|
|
117
|
+
* emitting. Default `true`.
|
|
118
|
+
*/
|
|
119
|
+
ingestCrossRefs?: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Rarity threshold for the grammar-agnostic cross-reference ingester.
|
|
122
|
+
* An identifier that is defined in *more than this many* files is
|
|
123
|
+
* treated as too generic to use as a corroboration signal. Reduce to
|
|
124
|
+
* tighten confidence (fewer, higher-quality edges); raise for large
|
|
125
|
+
* monorepos where the same class name spans many packages. Default 3.
|
|
126
|
+
*/
|
|
127
|
+
crossRefsRarityThreshold?: number;
|
|
128
|
+
/**
|
|
129
|
+
* Maximum number of files the cross-reference ingester walks in one
|
|
130
|
+
* prefill pass. Raise for monorepos with hundreds of thousands of
|
|
131
|
+
* files; lower for speed. Default `2000`.
|
|
132
|
+
*/
|
|
133
|
+
crossRefsMaxFiles?: number;
|
|
134
|
+
/**
|
|
135
|
+
* Hard cap on total cross-reference edges emitted per prefill pass.
|
|
136
|
+
* Lower values keep the memory store leaner; higher values give more
|
|
137
|
+
* complete coverage on dense codebases. Default `10000`.
|
|
138
|
+
*/
|
|
139
|
+
crossRefsMaxEdges?: number;
|
|
140
|
+
/**
|
|
141
|
+
* Maximum number of files the docs ingester walks in one pass
|
|
142
|
+
* (`docs/` tree + conventional root docs). Raise for documentation-
|
|
143
|
+
* heavy repos. Default `200`.
|
|
144
|
+
*/
|
|
145
|
+
docsMaxFiles?: number;
|
|
146
|
+
/**
|
|
147
|
+
* Number of characters of body text captured after each heading as
|
|
148
|
+
* context in the recall snippet. A longer value gives richer
|
|
149
|
+
* snippets at the cost of larger memory entries. Default `240`.
|
|
150
|
+
*/
|
|
151
|
+
docsBodyChars?: number;
|
|
152
|
+
/**
|
|
153
|
+
* Deepest heading level to index. `3` indexes H1–H3; `2` indexes
|
|
154
|
+
* only H1–H2; `4` or `5` captures deeper structure. Default `3`.
|
|
155
|
+
*/
|
|
156
|
+
docsMaxHeadingLevel?: number;
|
|
157
|
+
/**
|
|
158
|
+
* Maximum number of table files (CSV, TSV, XLSX) walked per prefill
|
|
159
|
+
* pass. Default `200`.
|
|
160
|
+
*/
|
|
161
|
+
tablesMaxFiles?: number;
|
|
162
|
+
/**
|
|
163
|
+
* Skip XLSX/XLS files larger than this, in megabytes. Very large
|
|
164
|
+
* spreadsheets are usually data dumps whose headers are rarely worth
|
|
165
|
+
* indexing. Set `0` to skip ALL spreadsheets. Default `50`.
|
|
166
|
+
*/
|
|
167
|
+
tablesMaxXlsxMB?: number;
|
|
168
|
+
/**
|
|
169
|
+
* Maximum number of column headers to list per table / sheet in the
|
|
170
|
+
* memory content. Wide tables beyond this threshold get a
|
|
171
|
+
* "(N more)" note. Default `40`.
|
|
172
|
+
*/
|
|
173
|
+
tablesMaxColumns?: number;
|
|
174
|
+
/**
|
|
175
|
+
* Maximum bytes of content read from each agent-instruction file
|
|
176
|
+
* (AGENTS.md, CLAUDE.md, .cursorrules, …). Teams with detailed
|
|
177
|
+
* instructions should raise this. Default `6144` (6 KB).
|
|
178
|
+
*/
|
|
179
|
+
notesMaxBytes?: number;
|
|
180
|
+
/**
|
|
181
|
+
* Minimum number of times two files must appear in the same commit
|
|
182
|
+
* before a co-change edge is recorded. Lower values add more
|
|
183
|
+
* connections on new or small repos; higher values keep the graph
|
|
184
|
+
* tight. Default `3`.
|
|
185
|
+
*/
|
|
186
|
+
coChangeMinOccurrences?: number;
|
|
187
|
+
/**
|
|
188
|
+
* Maximum number of source files the code-map ingester parses per
|
|
189
|
+
* pass. By default this is set adaptively (1500 small / 4000 medium
|
|
190
|
+
* / 10000 large), based on a one-shot measurement of the repo at
|
|
191
|
+
* startup. Setting this explicitly *overrides the adaptive
|
|
192
|
+
* decision* — useful when you know your repo's right size and want
|
|
193
|
+
* deterministic behaviour. Set to a small value to speed up
|
|
194
|
+
* startup at the cost of code-map completeness; raise for very
|
|
195
|
+
* large monorepos. Default `4000` (medium tier).
|
|
196
|
+
*/
|
|
197
|
+
codeMapMaxFiles?: number;
|
|
198
|
+
/**
|
|
199
|
+
* Maximum number of git commits the co-change graph builder
|
|
200
|
+
* scans per pass. By default adaptive (1000 small / 5000 medium /
|
|
201
|
+
* 20000 large). Setting this explicitly overrides the adaptive
|
|
202
|
+
* choice. Lower for faster startup at the cost of co-change graph
|
|
203
|
+
* density; raise for repos where you want deeper history coverage.
|
|
204
|
+
* Default `5000` (medium tier).
|
|
205
|
+
*/
|
|
206
|
+
coChangeMaxCommits?: number;
|
|
207
|
+
/**
|
|
208
|
+
* The recall-first nudge: a tool.execute.before/after hook pair that
|
|
209
|
+
* appends ONE reminder to a discovery tool's output if the agent
|
|
210
|
+
* does raw discovery without checking memory. Default TRUE.
|
|
211
|
+
*
|
|
212
|
+
* Set FALSE if another plugin (e.g. oh-my-opencode, which registers
|
|
213
|
+
* many lifecycle hooks) also post-processes tool output and you'd
|
|
214
|
+
* rather avoid two plugins touching `output.output`. The directive
|
|
215
|
+
* tool descriptions still encourage recall-first; only the
|
|
216
|
+
* output-mutating hook is disabled.
|
|
217
|
+
*/
|
|
218
|
+
enableNudgeHook?: boolean;
|
|
219
|
+
/**
|
|
220
|
+
* Adapt size-derived settings to the repository. Default TRUE.
|
|
221
|
+
*
|
|
222
|
+
* When on, prefill measures one cheap signal — commit count (or
|
|
223
|
+
* file count when there's no git) — classifies the repo as small /
|
|
224
|
+
* medium / large, and scales `gitHistoryDepth`, the code-map file
|
|
225
|
+
* cap, and the co-change cutoff accordingly. (The disk budget is
|
|
226
|
+
* deliberately not tier-scaled — the 50 MB default is generous
|
|
227
|
+
* enough for every realistic repo.) The chosen tier is logged
|
|
228
|
+
* every run.
|
|
229
|
+
*
|
|
230
|
+
* Adaptation only fills knobs the user did NOT set explicitly — any
|
|
231
|
+
* value you pass in config always wins. Set FALSE to pin every
|
|
232
|
+
* setting to its fixed default regardless of repo size.
|
|
233
|
+
*/
|
|
234
|
+
adaptive?: boolean;
|
|
235
|
+
/**
|
|
236
|
+
* Opt-in cross-lingual semantic search. Default FALSE.
|
|
237
|
+
*
|
|
238
|
+
* When on, the plugin also embeds each memory with a small
|
|
239
|
+
* multilingual e5 model (via the optional `@huggingface/transformers`
|
|
240
|
+
* dependency, downloaded on demand) and fuses vector similarity with
|
|
241
|
+
* the BM25 lexical ranking. This lets a query in one language
|
|
242
|
+
* (e.g. Chinese, Russian) retrieve code and comments written in
|
|
243
|
+
* another (e.g. English) — something pure lexical search cannot do.
|
|
244
|
+
*
|
|
245
|
+
* It is fully additive: when off, no model is downloaded, no runtime
|
|
246
|
+
* is loaded, and retrieval is byte-for-byte the lexical path. When
|
|
247
|
+
* on but the optional dependency is absent, the plugin logs that and
|
|
248
|
+
* falls back to lexical search rather than failing.
|
|
249
|
+
*/
|
|
250
|
+
enableSemanticSearch?: boolean;
|
|
251
|
+
/**
|
|
252
|
+
* The embedding model id (a transformers.js-compatible model).
|
|
253
|
+
* Default "Xenova/multilingual-e5-small". Only consulted when
|
|
254
|
+
* `enableSemanticSearch` is true.
|
|
255
|
+
*/
|
|
256
|
+
embeddingModel?: string;
|
|
257
|
+
/**
|
|
258
|
+
* Use Personalized PageRank for the co-change boost in recall,
|
|
259
|
+
* instead of the default single-hop propagation. Default FALSE.
|
|
260
|
+
*
|
|
261
|
+
* The co-change graph (files historically changed together) feeds a
|
|
262
|
+
* boost that surfaces structurally-related context a query alone
|
|
263
|
+
* would miss. By default that boost is one hop — the direct
|
|
264
|
+
* neighbours of the textual hits. With this on, it is instead a
|
|
265
|
+
* restart-biased random walk over the whole graph: relevance
|
|
266
|
+
* reaches multi-hop files, graded by graph distance.
|
|
267
|
+
*
|
|
268
|
+
* The tradeoff: PPR is a per-recall iterative computation (a few ms
|
|
269
|
+
* on a large graph) and is less trivially inspectable than the one
|
|
270
|
+
* hop. It is opt-in for that reason; the default stays cheap and
|
|
271
|
+
* fully traceable. See WIKI: "How it compares".
|
|
272
|
+
*/
|
|
273
|
+
personalizedPageRank?: boolean;
|
|
274
|
+
/**
|
|
275
|
+
* Record the current session's activity (file edits + bash commands)
|
|
276
|
+
* as a single rolling memory under `session-trace` →
|
|
277
|
+
* `live:${sessionId}`. Lets the current session recall what it has
|
|
278
|
+
* already touched without scanning the OpenCode SDK, and pre-seeds
|
|
279
|
+
* the trace for the moment this session becomes "past" to a
|
|
280
|
+
* successor session. Default TRUE.
|
|
281
|
+
*
|
|
282
|
+
* Set FALSE to opt out of recording — the JSONL log still captures
|
|
283
|
+
* the same events for offline inspection. Disabling this is mostly
|
|
284
|
+
* useful in tests or when running against very locked-down stores
|
|
285
|
+
* where any extra write is unwelcome.
|
|
286
|
+
*/
|
|
287
|
+
recordSessionActivity?: boolean;
|
|
288
|
+
/**
|
|
289
|
+
* Maximum number of files re-indexed after a single `bash` tool
|
|
290
|
+
* call. After a `bash` call the plugin runs `git status` to find
|
|
291
|
+
* what changed in the working tree and refreshes the code-map for
|
|
292
|
+
* each touched file. A bash command that triggers a branch switch
|
|
293
|
+
* or large reformat can change thousands of files at once; this cap
|
|
294
|
+
* keeps post-hook latency bounded. Default `20` — enough for typical
|
|
295
|
+
* commit/format/codegen workflows, low enough that even a mass
|
|
296
|
+
* checkout doesn't stall the next tool call.
|
|
297
|
+
*/
|
|
298
|
+
bashFileTrackingMaxFiles?: number;
|
|
299
|
+
/**
|
|
300
|
+
* Auto-detect git ref movement (HEAD changing as a side effect of a
|
|
301
|
+
* bash command like `git pull`, `git merge`, `git rebase`,
|
|
302
|
+
* `git checkout`, or `git reset`) and re-run the git-history ingester
|
|
303
|
+
* in the background when it happens. Re-ingestion is idempotent —
|
|
304
|
+
* already-known commits are skipped via `insertIfMissing` — so the
|
|
305
|
+
* cost is roughly linear in the number of NEW commits.
|
|
306
|
+
*
|
|
307
|
+
* Without this, new commits arriving mid-session are invisible to
|
|
308
|
+
* `memory_recall` until the next session start. With it on, a HEAD
|
|
309
|
+
* change is detected after every `bash` call and a re-ingest is
|
|
310
|
+
* queued (de-duplicated: only one re-ingest runs at a time; further
|
|
311
|
+
* detections coalesce into the next pass). Default TRUE.
|
|
312
|
+
*
|
|
313
|
+
* The `memory_ingest_git` tool exposes the same behaviour as an
|
|
314
|
+
* explicit, on-demand call for cases where HEAD doesn't move
|
|
315
|
+
* (e.g. fetch without merge, or running outside a bash tool).
|
|
316
|
+
*/
|
|
317
|
+
autoReingestGitOnHeadChange?: boolean;
|
|
318
|
+
}
|
|
319
|
+
export interface ResolvedConfig {
|
|
320
|
+
maxMemoryBytes: number;
|
|
321
|
+
autoIngestOnStartup: boolean;
|
|
322
|
+
gitHistoryDepth: number;
|
|
323
|
+
forceActive: boolean;
|
|
324
|
+
skillsOutputDir: string;
|
|
325
|
+
/**
|
|
326
|
+
* Prefix applied to mined skill subdirectory names AND to the
|
|
327
|
+
* subjects of the memories that point at them. Default `""` — the
|
|
328
|
+
* standalone behaviour, paths unchanged. Set to `"diane-"` at
|
|
329
|
+
* startup when a coexisting plugin (caveman, oh-my-opencode) writes
|
|
330
|
+
* into the same `.opencode/skills/` directory; this namespaces our
|
|
331
|
+
* subdirs so they don't collide with the peer's slugs (`caveman`,
|
|
332
|
+
* `caveman-commit`, …) and ensures `memory_skill` surfaces only
|
|
333
|
+
* ours, not the peer's.
|
|
334
|
+
*/
|
|
335
|
+
minedSkillPrefix: string;
|
|
336
|
+
skillMiningMinCluster: number;
|
|
337
|
+
ingestSessions: boolean;
|
|
338
|
+
enableCodeMap: boolean;
|
|
339
|
+
installUsageSkill: boolean;
|
|
340
|
+
ingestDocs: boolean;
|
|
341
|
+
ingestProjectNotes: boolean;
|
|
342
|
+
ingestTableHeaders: boolean;
|
|
343
|
+
ingestCrossRefs: boolean;
|
|
344
|
+
/** See `UserConfig.crossRefsRarityThreshold`. */
|
|
345
|
+
crossRefsRarityThreshold: number;
|
|
346
|
+
crossRefsMaxFiles: number;
|
|
347
|
+
crossRefsMaxEdges: number;
|
|
348
|
+
docsMaxFiles: number;
|
|
349
|
+
docsBodyChars: number;
|
|
350
|
+
docsMaxHeadingLevel: number;
|
|
351
|
+
tablesMaxFiles: number;
|
|
352
|
+
tablesMaxXlsxMB: number;
|
|
353
|
+
tablesMaxColumns: number;
|
|
354
|
+
notesMaxBytes: number;
|
|
355
|
+
coChangeMinOccurrences: number;
|
|
356
|
+
enableNudgeHook: boolean;
|
|
357
|
+
adaptive: boolean;
|
|
358
|
+
enableSemanticSearch: boolean;
|
|
359
|
+
embeddingModel: string;
|
|
360
|
+
personalizedPageRank: boolean;
|
|
361
|
+
recordSessionActivity: boolean;
|
|
362
|
+
bashFileTrackingMaxFiles: number;
|
|
363
|
+
autoReingestGitOnHeadChange: boolean;
|
|
364
|
+
/**
|
|
365
|
+
* Names of the keys the user set explicitly in opencode.json.
|
|
366
|
+
* Adaptive tuning consults this so it never overrides a value the
|
|
367
|
+
* user chose deliberately — it only fills in size-derived defaults.
|
|
368
|
+
*/
|
|
369
|
+
explicitKeys: ReadonlySet<keyof UserConfig>;
|
|
370
|
+
/**
|
|
371
|
+
* Size adaptation knobs not exposed as user config — set by
|
|
372
|
+
* `applyAdaptiveTuning` from the measured repo signal, read by the
|
|
373
|
+
* ingesters. When `adaptive` is false these stay at fixed defaults.
|
|
374
|
+
*/
|
|
375
|
+
codeMapMaxFiles: number;
|
|
376
|
+
/** Skip the O(commits × files²) co-change pass above this commit count. */
|
|
377
|
+
coChangeMaxCommits: number;
|
|
378
|
+
}
|
|
379
|
+
/** Returned by tools that perform background operations. */
|
|
380
|
+
export interface BackgroundJobHandle {
|
|
381
|
+
job: string;
|
|
382
|
+
startedAt: number;
|
|
383
|
+
/** Caller is told the job is running async; this is for the agent's reference. */
|
|
384
|
+
note: string;
|
|
385
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* opencode-diane — type definitions.
|
|
3
|
+
*
|
|
4
|
+
* The store is hierarchical: top-level `category` partitions the
|
|
5
|
+
* memory set, each entry has a `subject` (mid-level slug for
|
|
6
|
+
* coarse filtering) and a free-form `content` body that's the
|
|
7
|
+
* leaf-level text searched by BM25.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rich, structured logging to disk. A second log sink alongside
|
|
3
|
+
* OpenCode's own session log channel — the existing `log()` callback
|
|
4
|
+
* keeps piping human-readable lines into OpenCode's UI, and this
|
|
5
|
+
* module mirrors them (plus structured events) to a JSONL file under
|
|
6
|
+
* `os.tmpdir()/opencode-diane/` by default, or `$OPENCODE_DIANE_LOG_DIR`
|
|
7
|
+
* if set (use the env var when running inside Docker — point it at a
|
|
8
|
+
* mounted volume and your logs survive the container). The file is
|
|
9
|
+
* per-session and per-PID, so parallel OpenCode sessions never
|
|
10
|
+
* interleave; each line is a standalone JSON object so the whole file
|
|
11
|
+
* is greppable AND `jq`-able.
|
|
12
|
+
*
|
|
13
|
+
* Why not into OpenCode's log alone:
|
|
14
|
+
* - OpenCode's log is human-oriented (single-line strings) and is
|
|
15
|
+
* scoped to a session's UI panel — easy to lose between turns.
|
|
16
|
+
* - For debugging the plugin itself (a flush that took 200ms, an
|
|
17
|
+
* ingester that skipped half its commits, an eviction that fired
|
|
18
|
+
* under budget) you want timestamped, machine-readable, persistent
|
|
19
|
+
* records you can keep across sessions and diff.
|
|
20
|
+
*
|
|
21
|
+
* Why JSONL not a text log:
|
|
22
|
+
* - One line per record, never multi-line, so `tail -f` works.
|
|
23
|
+
* - Each line is valid JSON, so `jq '.event == "ingest.git"'` works.
|
|
24
|
+
* - Streams append cleanly even from multiple writers (each line is
|
|
25
|
+
* atomic on POSIX up to PIPE_BUF, and our records are well under).
|
|
26
|
+
*
|
|
27
|
+
* Failure model: every disk operation can fail (full disk, permission
|
|
28
|
+
* lost, tmpdir on a flaky volume). A failure HERE must never propagate
|
|
29
|
+
* to the host plugin — the file logger is a debugging aid, not a
|
|
30
|
+
* correctness dependency. We try once, drop the stream on any error,
|
|
31
|
+
* and go silent. The OpenCode log channel is unaffected.
|
|
32
|
+
*
|
|
33
|
+
* Retention is the user's problem: we never delete; files accumulate
|
|
34
|
+
* in `os.tmpdir()/opencode-diane/` until the OS clears tmp. On Linux
|
|
35
|
+
* that's typically at reboot or via systemd-tmpfiles; on macOS every
|
|
36
|
+
* few days. Documented in WIKI.
|
|
37
|
+
*/
|
|
38
|
+
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
39
|
+
/**
|
|
40
|
+
* Public surface. `log()` writes a line message (mirrors what
|
|
41
|
+
* OpenCode's own log channel takes); `event()` writes a structured
|
|
42
|
+
* record with a name and a typed payload. `path()` returns the file
|
|
43
|
+
* the logger is writing to — useful at startup to print "rich logs at
|
|
44
|
+
* <path>" so the user can find them. `close()` drains the stream.
|
|
45
|
+
*/
|
|
46
|
+
export interface FileLogger {
|
|
47
|
+
log(level: LogLevel, message: string): void;
|
|
48
|
+
event(name: string, data?: Record<string, unknown>): void;
|
|
49
|
+
path(): string;
|
|
50
|
+
close(): void;
|
|
51
|
+
}
|
|
52
|
+
export interface CreateFileLoggerOptions {
|
|
53
|
+
/** Service name — used in the filename and on every record. */
|
|
54
|
+
service: string;
|
|
55
|
+
/**
|
|
56
|
+
* Fields included on EVERY record (e.g. `{ root: "/path/to/repo" }`).
|
|
57
|
+
* Kept small — they multiply across every line of the file.
|
|
58
|
+
*/
|
|
59
|
+
base?: Record<string, unknown>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Directory the logger writes into.
|
|
63
|
+
*
|
|
64
|
+
* Honours `OPENCODE_DIANE_LOG_DIR` if set — point it at a mounted
|
|
65
|
+
* volume when running under Docker (`-e OPENCODE_DIANE_LOG_DIR=/logs
|
|
66
|
+
* -v $PWD/logs:/logs`) so logs survive the container and can be read
|
|
67
|
+
* with `analyze-logs.py --dir /logs` from outside. Falls back to
|
|
68
|
+
* `os.tmpdir()/opencode-diane/` everywhere else; on a fresh host that
|
|
69
|
+
* is `/tmp/opencode-diane/` on Linux and a per-user temp folder on
|
|
70
|
+
* macOS / Windows. Exported for tests + docs.
|
|
71
|
+
*/
|
|
72
|
+
export declare function richLogsDir(): string;
|
|
73
|
+
/**
|
|
74
|
+
* Best-effort sanitiser for values put on a structured event payload —
|
|
75
|
+
* trims long strings to keep the log file manageable and caps arrays
|
|
76
|
+
* at a sensible length. Used to shape the `args` field of a
|
|
77
|
+
* `tool.call` event before it lands on disk: a tool's free-form
|
|
78
|
+
* `query` or `content` field could in principle be many KB, and we
|
|
79
|
+
* don't want a single log line to dominate the file. The marker
|
|
80
|
+
* `…(+N chars)` / `…(+N items)` is preserved so a reader knows the
|
|
81
|
+
* truncation happened. Returns the trimmed value; doesn't mutate the
|
|
82
|
+
* input. Shallow-recurses through plain objects and arrays — there's
|
|
83
|
+
* no cycle protection because tool args are flat data, but a try
|
|
84
|
+
* around the caller's `JSON.stringify` still catches anything weird.
|
|
85
|
+
*/
|
|
86
|
+
export declare function truncateForLog(value: unknown, maxStringLength?: number): unknown;
|
|
87
|
+
export declare function createFileLogger(opts: CreateFileLoggerOptions): FileLogger;
|