@joe-broadhead/opencode-history 0.0.2 → 0.0.3
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 +44 -0
- package/README.md +12 -31
- package/dist/index.js +493 -587
- package/dist/tui.js +6 -7
- package/package.json +3 -7
- package/skills/history-recall/SKILL.md +56 -24
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
|
+
## [0.0.3] - 2026-11-05
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Status names any skill with the id `history-recall` that OpenCode loads instead of the plugin's own, such as one in your own skills folder: a `Skill:` row, `shadowedSkills` in the status RPC, and the next step "Rename or move the skill at <path>, …".
|
|
10
|
+
- `history_sql` results carry the same `index` object as search, sessions, files and recall, and their text warns when the index is still building or the source is partial.
|
|
11
|
+
- `history_files` results have `truncated`, true when more paths matched than `limit`. The text then asks for the folder that makes the path unique, since a bare `README.md` matches that file in every repository.
|
|
12
|
+
- `history_sessions`, `history_files` and `history_sql` are pinned in Code Mode, like search, brief and read, so a model sees them without a namespace search.
|
|
13
|
+
- `SQL_FAILED` names the column, table or function SQLite could not find, or the ambiguous column, as in `it names a column the views do not have: nope`, when that name is a plain identifier. Nothing else of the statement is repeated.
|
|
14
|
+
- The tool descriptions and results say how to cite a past session, `(ses_… #seq)`, and the `history` namespace line names the sessions, files and SQL tools and the `history-recall` skill.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- The `history-recall` skill is rewritten. It now loads for requests such as "how did we fix…", "what did I work on yesterday" and "which sessions changed <file>". It picks the tool by the question (search, sessions, files, recall or SQL), shows a local day with its UTC offset, and asks for every citation in full. It is not meant for meetings, chat or saved memory notes.
|
|
19
|
+
- The tool text now says more:
|
|
20
|
+
- `since` and `until` say that a bare date is a UTC day, and how to ask for the user's local day.
|
|
21
|
+
- The `path` filter says it matches anything under a folder, and that globs work.
|
|
22
|
+
- `history_files` asks for a path with its repository folder.
|
|
23
|
+
- `sort: "cost"` and `v_sessions.cost` say that cost is the session's own spend in USD, and that subagents are separate sessions.
|
|
24
|
+
- The next step for agents without the default rules now reads: "Put the default rules shown by /history-status first in each listed agent's own permissions, in opencode.json or the agent's Markdown file, followed by your top-level rules for History tools."
|
|
25
|
+
- The next steps of `STATUS_UNAVAILABLE`, `INDEX_FAILED`, `CONTRACT_MISMATCH` and `OPERATION_FAILED`, and the index warnings in results, point at `/history-status` instead of a tool.
|
|
26
|
+
- `SQL_REJECTED` reads "The SQL was refused: <why>." Its next step allows a `WITH` statement and names the `docs_words` and `docs_sub` tables.
|
|
27
|
+
- The `history_sql` description says how times are stored (UTC `YYYY-MM-DD HH:MM:SS`, with a space) and how to compare them, with `datetime(created) >= datetime(?)`, since an ISO value with a `T` sorts after the stored form and shifts a window. It also says its column list is complete, so there is no need to probe with `select *`.
|
|
28
|
+
- Each `history_sessions` row carries the first 200 characters of the first prompt, not 500, so a page of 100 sessions stays small. `history_brief` still has 500.
|
|
29
|
+
- `history_read`'s cut marker reads `…[N chars cut; full: true shows them]…`.
|
|
30
|
+
- The README's Update steps are now part of Install, and Troubleshooting lists only the status rows and the setup codes. The full error table stays in `docs/configuration.md`.
|
|
31
|
+
|
|
32
|
+
### Removed
|
|
33
|
+
|
|
34
|
+
- The `history_status` tool. Run `/history-status`, or open `/history` in the terminal UI, for the same status. The model reads index progress from the `index` object every result carries. Drop `history_status` from your permission rules, which no longer match anything. Jelly no longer lists it.
|
|
35
|
+
- Recall answers:
|
|
36
|
+
- the `synthesize` input of `history_recall`, and the `answer` field of its result;
|
|
37
|
+
- the `recall.synthesize` and `recall.model` plugin options;
|
|
38
|
+
- the `Recall answers` status row, and `recall` in the status RPC;
|
|
39
|
+
- the `RECALL_MODEL_UNAVAILABLE` and `RECALL_FAILED` codes.
|
|
40
|
+
|
|
41
|
+
`history_recall` now returns quoted evidence only, and the calling agent answers from it, so the plugin makes no model call of its own. Remove `recall` from your plugin options: it now fails setup with `OPTIONS_INVALID`.
|
|
42
|
+
- `kinds` on `history_files`, which it ignored: a call with it is now refused. `title` in `history_read`'s `kinds`, which never matched a message.
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- `history_read`'s `kinds` said "Default: all", but reasoning is shown only with `full: true`. It now says so.
|
|
47
|
+
- `docs/configuration.md` said no tool asserts a permission, and `SECURITY.md` said the plugin adds no permission rules. Every call asserts its action, and the plugin inserts its default rules after each agent's base allow.
|
|
48
|
+
|
|
5
49
|
## [0.0.2] - 2026-11-04
|
|
6
50
|
|
|
7
51
|
### Added
|
package/README.md
CHANGED
|
@@ -18,14 +18,7 @@ opencode plugin add @joe-broadhead/opencode-history
|
|
|
18
18
|
|
|
19
19
|
Run `opencode reload`, or restart OpenCode. Then run `/history-status`. On first start the plugin indexes every session in OpenCode's database in the background, newest first. The tools work while it runs, over the sessions indexed so far. `/history-status`, or `/history` in the terminal UI, shows the progress.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```sh
|
|
24
|
-
opencode plugin update @joe-broadhead/opencode-history
|
|
25
|
-
opencode reload
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
An entry pinned to a version (`@joe-broadhead/opencode-history@0.0.1`) does not update: remove the `@version` from `plugins` first. The index is kept; when a new version changes its layout, the plugin rebuilds it in the background.
|
|
21
|
+
To update, run `opencode plugin update @joe-broadhead/opencode-history`, then `opencode reload`. An entry pinned to a version, such as `@joe-broadhead/opencode-history@0.0.1`, does not update: remove the `@version` from `plugins` first. The index is kept; when a new version changes its layout, the plugin rebuilds it in the background.
|
|
29
22
|
|
|
30
23
|
## Sign in
|
|
31
24
|
|
|
@@ -43,21 +36,19 @@ await tools.history.sessions({ since: "7d", sort: "cost" })
|
|
|
43
36
|
await tools.history.files({ path: "src/auth/login.ts" })
|
|
44
37
|
await tools.history.recall({ question: "How did we fix the flaky upload test?", queries: ["flaky upload test", "upload test timeout"] })
|
|
45
38
|
await tools.history.sql({ sql: "select date(created) as day, round(sum(cost), 2) as cost from v_sessions group by day order by day desc", limit: 14 })
|
|
46
|
-
await tools.history.status({})
|
|
47
39
|
```
|
|
48
40
|
|
|
49
|
-
- **Search, brief, read.** The usual lookup. `history_search` ranks sessions for two to four phrasings of one topic and returns excerpts, each with a `seq`. `history_brief` summarises one session: first prompt, compaction summaries, last reply, outcome, files edited, commands, subagents and todos. `history_read` reads the messages around a `seq`, with paging; with `kinds`, a window with none of those kinds widens to the nearest messages that have them. These three
|
|
41
|
+
- **Search, brief, read.** The usual lookup. `history_search` ranks sessions for two to four phrasings of one topic and returns excerpts, each with a `seq`. `history_brief` summarises one session: first prompt, compaction summaries, last reply, outcome, files edited, commands, subagents and todos. `history_read` reads the messages around a `seq`, with paging; with `kinds`, a window with none of those kinds widens to the nearest messages that have them. These three are pinned, with `history_sessions`, `history_files` and `history_sql`, so a model sees them without searching for them.
|
|
50
42
|
- **Sessions and files.** `history_sessions` lists sessions without a query, by last update, creation, cost or size. `history_files` lists the sessions that read or changed a file or folder, with counts per operation and the `seq` of the first touch.
|
|
51
|
-
- **Recall.** `history_recall` searches, takes the best sessions and returns quoted evidence with session IDs and `seq`s
|
|
43
|
+
- **Recall.** `history_recall` searches, takes the best sessions and returns quoted evidence with session IDs and `seq`s, for the agent to answer from.
|
|
52
44
|
- **SQL.** `history_sql` runs one read-only `SELECT` or `WITH` statement over the index, for counts and reports. Its stable interface is four views, `v_sessions`, `v_docs`, `v_files` and `v_links`, and two full-text tables, `docs_words` (`MATCH`) and `docs_sub` (`text LIKE '%substring%'`). The other tables can change between versions.
|
|
53
45
|
- **Pin.** `history_pin` keeps a past session's brief, or a range of its messages, in the current session's instructions, so it stays in view through compactions. It is not in Code Mode, because it changes the current session.
|
|
54
|
-
- **Status.** `history_status` shows index progress, the source and the options in effect.
|
|
55
46
|
|
|
56
47
|
Search, sessions, files and recall look in the current project by default. They leave out the current session, subagent sessions and archived sessions unless you ask for them. The filters are `scope` (`project`, `directory`, `all` or `session`), `since` and `until` (an ISO date, or an age such as `36h`, `7d`, `3w`, `2m` or `1y`), `kinds`, `tool`, `agent`, `path`, `sessionID`, `includeSubagents`, `includeCurrent` and `includeArchived`.
|
|
57
48
|
|
|
58
|
-
Search has three modes
|
|
49
|
+
Search has three modes: `words`, the default, matches stemmed words in any order, with `"exact phrases"`, `-excluded` terms, `prefix*` and `OR`; `substring` matches exact text of at least three characters, for identifiers, paths and error messages; `regex` takes a JavaScript regular expression. [The search reference](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/configuration.md#search) has the full syntax and limits.
|
|
59
50
|
|
|
60
|
-
|
|
51
|
+
Sessions with only some words of a phrasing show below full matches, marked `near match`; runs of the same thing in one directory, such as one scheduled prompt's runs, show once with a `similar` count. When a search, `history_sessions` or `history_files` finds nothing, the result names the input that would show what the default filters left out.
|
|
61
52
|
|
|
62
53
|
One skill, `history-recall`, teaches the search, brief, read pattern and how to cite a session as `(ses_… #seq)`.
|
|
63
54
|
|
|
@@ -93,7 +84,7 @@ The plugin puts a default block after each agent's base `* * allow` rule:
|
|
|
93
84
|
|
|
94
85
|
| Tool | Default |
|
|
95
86
|
|---|---|
|
|
96
|
-
| `history_search`, `history_read`, `history_brief`, `history_sessions`, `history_files`, `history_recall`, `history_sql
|
|
87
|
+
| `history_search`, `history_read`, `history_brief`, `history_sessions`, `history_files`, `history_recall`, `history_sql` | allow |
|
|
97
88
|
| `history_pin`, which changes the current session's instructions | ask |
|
|
98
89
|
| any other `history_*` tool | ask |
|
|
99
90
|
|
|
@@ -123,14 +114,13 @@ Options go on the plugin entry in `opencode.json`:
|
|
|
123
114
|
"package": "@joe-broadhead/opencode-history",
|
|
124
115
|
"options": {
|
|
125
116
|
"defaultScope": "project",
|
|
126
|
-
"mask": ["internal-token-[0-9a-f]{32}"]
|
|
127
|
-
"recall": { "synthesize": false }
|
|
117
|
+
"mask": ["internal-token-[0-9a-f]{32}"]
|
|
128
118
|
}
|
|
129
119
|
}]
|
|
130
120
|
}
|
|
131
121
|
```
|
|
132
122
|
|
|
133
|
-
`database` points at OpenCode's database and `indexPath` moves the index. `indexPath` must be a new file or an existing History index, outside OpenCode's data folder and outside the project; anything else fails setup with `INDEX_PATH_REFUSED` and is left untouched, whichever config sets it. `defaultScope` is the scope when a call names none. `index.reasoning`, `index.toolResults` and `index.maxDocChars` choose what is indexed. Built-in patterns mask common credentials before text is stored or shown
|
|
123
|
+
`database` points at OpenCode's database and `indexPath` moves the index. `indexPath` must be a new file or an existing History index, outside OpenCode's data folder and outside the project; anything else fails setup with `INDEX_PATH_REFUSED` and is left untouched, whichever config sets it. `defaultScope` is the scope when a call names none. `index.reasoning`, `index.toolResults` and `index.maxDocChars` choose what is indexed. Built-in patterns mask common credentials before text is stored or shown ([the list](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/configuration.md#built-in-patterns)). `mask` adds your own patterns, and `maskDefaults: false` turns the built-in ones off. `allowUntestedHost` loads on an untested OpenCode version, with a warning in status. An invalid option fails setup and names the key, never the value. The full reference, with every limit and error code, is [docs/configuration.md](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/configuration.md).
|
|
134
124
|
|
|
135
125
|
The `index` options, `mask` and `maskDefaults` apply to text indexed from then on. After you change them, run `/history-reindex rebuild` so the text already in the index follows them too.
|
|
136
126
|
|
|
@@ -151,37 +141,28 @@ There is nothing to sign in to and no client ID to set. `mask` adds patterns tha
|
|
|
151
141
|
|
|
152
142
|
## Troubleshooting
|
|
153
143
|
|
|
154
|
-
Start with `/history-status
|
|
144
|
+
Start with `/history-status`. It ends with one next step. Errors read `CODE: what happened. Next step: What to do.`
|
|
155
145
|
|
|
156
146
|
| State or code | What to do |
|
|
157
147
|
| --- | --- |
|
|
158
148
|
| `Source: plugin session API (partial)` | Status names the cause. `SOURCE_UNAVAILABLE`: point `database` at OpenCode's `opencode.db`, then restart OpenCode. `SOURCE_SCHEMA_UNKNOWN`: OpenCode's database has a layout this version does not know, so update the plugin or use a tested OpenCode. |
|
|
159
149
|
| `Connection: connecting`, `Index: building` | The first indexing pass is still running, and results cover only the sessions indexed so far. Wait for it to finish. |
|
|
160
150
|
| `Connection: failed` | The history is partial (see `Source`) or the index belongs to another plugin version (`INDEX_MISMATCH`). Follow the next step. |
|
|
161
|
-
| `Agents without default rules: …` | Those agents run every History tool, `history_pin` included, without asking. Put the
|
|
151
|
+
| `Agents without default rules: …` | Those agents run every History tool, `history_pin` included, without asking. Put the default rules shown by `/history-status` first in each listed agent's own permissions, in `opencode.json` or the agent's Markdown file, followed by your top-level rules for History tools. |
|
|
162
152
|
| `Index: ..., 35 s behind` | Seconds since the index was last in step with OpenCode. The next search, sessions or recall call catches up, or run `/history-reindex`. |
|
|
163
153
|
| A recent session is missing | Search, sessions and recall catch up for up to about 200 ms before they answer. A longer catch-up finishes in the background, so run `/history-reindex` to wait for it. |
|
|
164
154
|
| `HOST_UNTESTED`, `OpenCode: … (untested; …)` | The OpenCode release is not one of the tested 2.2.3, 2.2.4 and 2.2.5. Inside `>=2.2.3 <2.3.0` the plugin runs normally; outside it, it starts only with `allowUntestedHost: true`. If something fails, use a tested release. |
|
|
155
|
+
| `Skill: history-recall is hidden by <path>` | A skill with the same id, such as one in your own skills folder, loads instead of the plugin's. Rename or move the skill at that path. |
|
|
165
156
|
| `Masks: changed since text was indexed` | You changed `mask` or `maskDefaults` after text was indexed. Results already use the new patterns, but the index file holds the old text: run `/history-reindex rebuild`. |
|
|
166
157
|
| A large index file | The index takes about 2.7 times the text it holds, about 500 MB for 200,000 indexed texts, and status shows its size in the `Index file` row. It grows with your history; a deleted session leaves it, but the file keeps its size and reuses the space. To make it smaller, set `index.toolResults: false`, which leaves out tool output, or a lower `index.maxDocChars`, then delete the index file (with its `-wal` and `-shm` files) and restart OpenCode: the plugin builds a new one. |
|
|
167
158
|
| `OPTIONS_INVALID` | The message names the option. Fix it in the plugin entry and restart. |
|
|
168
|
-
| `SOURCE_UNAVAILABLE` | OpenCode's database stopped answering. Check that `database` points at OpenCode's `opencode.db`, then restart OpenCode. |
|
|
169
159
|
| `INDEX_UNAVAILABLE` | `indexPath` must be a file the plugin can create and write. Fix it and restart. |
|
|
170
160
|
| `INDEX_PATH_REFUSED` | `indexPath` names OpenCode's database or data folder, a file inside the project, or an existing file that is not a History index. The file was left as it was. Set `indexPath` to a new file elsewhere, or remove it, and restart. |
|
|
171
|
-
| `INDEX_BUSY` | Another process, such as a second OpenCode, is writing the index. Retry in a moment. |
|
|
172
161
|
| `INDEX_FAILED` | Run `/history-status`, and if it persists, delete the index file and restart OpenCode. |
|
|
173
162
|
| `INDEX_MISMATCH`, `Index schema: ...` | Another OpenCode process running another version of the plugin rebuilt the index for its own version; status shows both versions. Restart every OpenCode process so they all run one version; the index is then rebuilt for it. |
|
|
174
|
-
| `SESSION_NOT_FOUND` | Find the session ID with `history_search` or `history_sessions`. |
|
|
175
|
-
| `QUERY_INVALID` | Fix what the message names: a substring of at least 3 characters, the regular expression, the date, the path or another filter. The next step fits the mistake. |
|
|
176
|
-
| `SQL_REJECTED`, `SQL_FAILED` | Write one read-only `SELECT` or `WITH` statement, best over the `v_*` views. The message says what was wrong. |
|
|
177
|
-
| `SQL_TIMEOUT` | The statement ran longer than 10 seconds and was stopped. Filter by time or session, and bound a recursive `WITH`. |
|
|
178
|
-
| `PERMISSION_DENIED`, `SESSION_UNKNOWN`, `SESSION_AGENT_REQUIRED` | Scripts only: the session's agent may not use the tool, the session does not exist, or it names no agent. See [Scripting](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/scripting.md). |
|
|
179
|
-
| `RECALL_MODEL_UNAVAILABLE` | OpenCode has no model to write the answer. Set `recall.model` to a model OpenCode can use, or call `history_recall` with `synthesize: false`. |
|
|
180
|
-
| `RECALL_FAILED` | The model call failed. Call `history_recall` with `synthesize: false` for the evidence only. |
|
|
181
|
-
| `PIN_TOO_LARGE` | Pin a shorter range, or a lower `maxChars`. |
|
|
182
163
|
| `OPERATION_FAILED` | Something unexpected failed. Retry, and if it persists, the OpenCode server log has one `opencode-history:` line with the error's class, its SQLite code and where it was thrown, to report. |
|
|
183
164
|
|
|
184
|
-
The
|
|
165
|
+
The codes a tool call can return, each with its next step, are in [docs/configuration.md](https://github.com/joe-broadhead/opencode-history/blob/HEAD/docs/configuration.md#errors). Error and status text never contains your input, session text or SQLite's own message.
|
|
185
166
|
|
|
186
167
|
## Uninstall
|
|
187
168
|
|