pi-tuck 1.0.26 → 1.0.28
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 +47 -0
- package/README.md +9 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +37 -24
- package/dist/src/build-id.d.ts +1 -1
- package/dist/src/build-id.js +1 -1
- package/dist/src/compaction.d.ts +4 -0
- package/dist/src/compaction.js +156 -172
- package/dist/src/diagnostics.d.ts +1 -1
- package/dist/src/request-capacity.d.ts +8 -3
- package/dist/src/request-capacity.js +19 -14
- package/dist/src/run.d.ts +52 -0
- package/dist/src/run.js +89 -0
- package/dist/src/semantic-recall.d.ts +72 -2
- package/dist/src/semantic-recall.js +58 -12
- package/dist/src/status.d.ts +1 -0
- package/dist/src/status.js +2 -1
- package/dist/src/tuck.js +33 -27
- package/index.ts +31 -22
- package/package.json +1 -1
- package/src/build-id.ts +1 -1
- package/src/compaction.ts +137 -155
- package/src/request-capacity.ts +18 -12
- package/src/run.ts +91 -0
- package/src/semantic-recall.ts +46 -14
- package/src/status.ts +3 -1
- package/src/tuck.ts +32 -25
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,53 @@
|
|
|
3
3
|
All notable changes to pi-tuck. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
4
4
|
[Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [1.0.28] - 2026-11-10
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- **One owner for each piece of state that had several, the user-approved state refactor.** Requests are unchanged.
|
|
11
|
+
- The **pending cut** has one view, which every consumer reads: the request, `tuck_search`, the history tools, Pi's threshold path, the
|
|
12
|
+
band, the boundary save, `/tuck`, and the clamp, deepest-cut and retry previews.
|
|
13
|
+
- The **run** is one record, reset in one place. It holds the starting prompt as an entry, a typed prompt or a custom message.
|
|
14
|
+
- **Reply fit** has one reader behind the reserve and the floor.
|
|
15
|
+
- **Semantic setup** has an explicit state, which `/tuck` and the notices derive from.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **A plan made for a prompt that another extension handled could still answer Pi's own compaction check before a later run.** A plan now
|
|
20
|
+
answers that check only until the next tick, unless its own run starts. The cut it made was valid but deeper than needed.
|
|
21
|
+
|
|
22
|
+
### Release gates
|
|
23
|
+
|
|
24
|
+
- **Shipped without a live gate, because its replay matches 1.0.27:** 13,946 requests on 29 recordings, 0 lost and 0 dead tasks, clips
|
|
25
|
+
17 → 17. In the final run, one recording (live32-t02-M) showed 32 differing requests. Two more runs of this build on that recording matched
|
|
26
|
+
1.0.27 exactly, as did two more runs of 1.0.27, so it was noise.
|
|
27
|
+
- **Strict stress:** 0 findings.
|
|
28
|
+
- **The lifecycle sequence test:** 41 seeds and 1,107 events, clean.
|
|
29
|
+
- **An independent review** found 2 notice-only differences from 1.0.27, both fixed with tests: the length-stop notice after a tree move
|
|
30
|
+
inside another extension's settle, and the "set up" notice for a setup that finishes in a later session.
|
|
31
|
+
- Tests (802) and CI. The packed tarball loaded in the real installed Pi.
|
|
32
|
+
|
|
33
|
+
## [1.0.27] - 2026-11-10
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- **A run that a custom message started could lose that message after a cut in the middle of the run.** pi-tuck protected only a prompt the
|
|
38
|
+
user typed. A tool-loop cut in a run that an extension started with a custom message kept the message neither whole nor quoted, so later
|
|
39
|
+
requests lacked the instruction that started the run. Now such a message gets the same protection as a typed prompt: it is kept, or
|
|
40
|
+
quoted whole in the summary, and the guard checks it. Runs started by typed prompts are unchanged. A custom message with no text has
|
|
41
|
+
nothing to quote and stays unprotected, as before.
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
|
|
45
|
+
- A seeded lifecycle sequence test drives real Pi through orders of prompts, handled prompts, custom-message runs, tree moves, new
|
|
46
|
+
sessions, compactions and aborts. It checks invariants read from outputs only. It reproduces 1.0.23's stale-cut bug and found this one.
|
|
47
|
+
|
|
48
|
+
### Release gates
|
|
49
|
+
|
|
50
|
+
- **Shipped without a live gate, because its replay matches 1.0.26 exactly:** 13,946 requests, 0 different, 0 dead tasks, clips 17 → 17.
|
|
51
|
+
Strict stress: 0 findings. Tests (745) and CI. The packed tarball loaded in the real installed Pi.
|
|
52
|
+
|
|
6
53
|
## [1.0.26] - 2026-11-10
|
|
7
54
|
|
|
8
55
|
### Fixed
|
package/README.md
CHANGED
|
@@ -64,8 +64,8 @@ Then start a new Pi session. That is all. pi-tuck takes over Pi's compaction, bo
|
|
|
64
64
|
|
|
65
65
|
- Needs Pi 1.2.0 or later (tested on 1.2.0 and 1.4.0), on macOS or Linux. On an older Pi, pi-tuck stays off, Pi's own compaction runs, and pi-tuck says so once. Full features on macOS with Apple silicon; elsewhere, compaction and word recall.
|
|
66
66
|
- On macOS with Apple silicon, the first session also downloads a local search model in the background (about 390 MB, once), and says once when it is set up. Until it is ready, search works by keyword. See [Semantic search](#semantic-search).
|
|
67
|
-
- Prefer GitHub? `pi install git:github.com/galyavin/pi-tuck@v1.0.
|
|
68
|
-
- To pin a version, add it: `pi install npm:pi-tuck@1.0.
|
|
67
|
+
- Prefer GitHub? `pi install git:github.com/galyavin/pi-tuck@v1.0.27`.
|
|
68
|
+
- To pin a version, add it: `pi install npm:pi-tuck@1.0.27`.
|
|
69
69
|
|
|
70
70
|
## Uninstall
|
|
71
71
|
|
|
@@ -102,7 +102,7 @@ pi-tuck's tools appear only after its first cut. Before that there is nothing ou
|
|
|
102
102
|
|
|
103
103
|
| Command | Does |
|
|
104
104
|
|---|---|
|
|
105
|
-
| `/tuck` | Says in words what pi-tuck is doing in this session: the version this session loaded (an open session keeps it until Pi restarts), how many cuts pi-tuck made and the last
|
|
105
|
+
| `/tuck` | Says in words what pi-tuck is doing in this session: the version this session loaded (an open session keeps it until Pi restarts), how many cuts and retries pi-tuck made and the last cut's size before and after, whether the cut point adapts or is fixed by `cutAt`, and how search works here. It is for you; the model sees nothing new. |
|
|
106
106
|
| `/tuck-semantic on\|off\|status` | Turns semantic search on or off for this session, or shows its state. |
|
|
107
107
|
| `/tuck-incident on\|next\|off\|status` | Records this session's compaction decisions to a file you can attach to a bug report. |
|
|
108
108
|
|
|
@@ -131,8 +131,11 @@ Known limits today:
|
|
|
131
131
|
- A host that patches a large section into the system prompt could get a refusal that a cut would have fit (1.0.0 to 1.0.16; fixed in 1.0.17). pi-tuck plans a prompt's cut when the prompt arrives, before other extensions change the system prompt. A host engine that adds a section of thousands of tokens for one turn could push that turn's first request over the room, and the final guard refused it. Now the guard plans the cut against the system prompt as finally sent, and refuses only if that cut does not fit either ([`CHANGELOG.md`](CHANGELOG.md) 1.0.17).
|
|
132
132
|
- Semantic recall never started in `pi -p` (1.0.0 to 1.0.20; fixed in 1.0.21). pi-tuck skipped semantic recall whenever Pi ran with no UI, to keep a one-shot run from starting the first-time download, and that also skipped a runtime that was already installed. Jobs run with `pi -p` searched by keyword only, while `tuck_search` said semantic recall was being set up. RPC mode was not affected ([`CHANGELOG.md`](CHANGELOG.md) 1.0.21).
|
|
133
133
|
- pi-tuck refused requests that fit the window, and could strand a session (1.0.0 to 1.0.21; fixed in 1.0.22). It refused at the room, the window less the full reply reserve, where native Pi still sends. With Pi's defaults and a large setup, a session could be refused at every prompt. The final refusal now sits at the window less a reply floor ([`CHANGELOG.md`](CHANGELOG.md) 1.0.22).
|
|
134
|
+
- pi-tuck 1.0.25 failed to load in an installed Pi ("Cannot find module '@earendil-works/pi-ai/utils/estimate'"); fixed in 1.0.26, and 1.0.25 is deprecated. Since 1.0.23, the check of Pi's own reply cap also never ran in an installed Pi, for the same reason: Pi's extension loader resolves only a few pi-ai entry points for an installed package. It loaded only in tests and the eval harness, and the installed package fell back to the same 4,096-token margin without it. Fixed in 1.0.26, which was loaded in a real installed Pi before publishing ([`CHANGELOG.md`](CHANGELOG.md) 1.0.26).
|
|
135
|
+
- A request above the room could be admitted and then refused, leaving the session stuck where native Pi would have sent (1.0.22 to 1.0.24; fixed in 1.0.25). pi-tuck checked its line in its own corrected token count, while Pi's reply cap uses Pi's own estimate, which is higher when the provider counts fewer tokens than pi-tuck's raw measure ([`CHANGELOG.md`](CHANGELOG.md) 1.0.25).
|
|
134
136
|
- Near the 1.0.22 refusal line, replies were cut to a few hundred tokens (1.0.22; fixed in 1.0.23). 1.0.22 left only its reply floor and did not count Pi's 4,096-token margin on the reply cap ([`CHANGELOG.md`](CHANGELOG.md) 1.0.23).
|
|
135
137
|
- Cost of the 1.0.22 change: between the room and the window, the reply reserve no longer cushions a wrong count. At a cold start an undercount can reach the provider. A provider that errors is caught and learned from; a server that truncates silently truncates, as it does for native Pi. With a setup above the room, cuts are forced and frequent, each freeing little, which beats a stranded session ([`CHANGELOG.md`](CHANGELOG.md) 1.0.22).
|
|
138
|
+
- A run that a custom message started could lose that message after a cut in the middle of the run (fixed in 1.0.27). pi-tuck protected only a prompt the user typed, so a tool-loop cut in a run an extension started with a custom message kept the message neither whole nor quoted, and later requests lacked the instruction that started the run. Now such a message gets the same protection as a typed prompt: it is kept, or quoted whole in the summary, and the guard checks it. A custom message with no text has nothing to quote and stays unprotected ([`CHANGELOG.md`](CHANGELOG.md) 1.0.27).
|
|
136
139
|
- A prompt's cut could reach a run it was not planned for (fixed in 1.0.24). pi-tuck plans a prompt's cut when the prompt arrives. When another extension handled that prompt, no run started, and the plan waited for the next run. A run started by a custom message carried a cut sized for the prompt that never ran, deeper than needed. After a move in the session tree (`/tree`), the plan was applied on the new branch, where its kept entry was not present, so the request lost the custom message that started the run, even on a branch that needed no cut ([`CHANGELOG.md`](CHANGELOG.md) 1.0.24).
|
|
137
140
|
- Four `tuck_search` faults, fixed in 1.0.23: it said semantic recall was still indexing when the history was fully indexed; in the turn after a prompt's cut it ranked nothing ("nothing is out of view"); a keyword-search timeout on a very long history failed the whole search, where now the semantic results still answer; and the timeout message named a pattern instead of the history's size ([`CHANGELOG.md`](CHANGELOG.md) 1.0.23).
|
|
138
141
|
- pi-tuck cut earlier than native Pi when a model's reply cap is above Pi's reserve (1.0.0 to 1.0.19; fixed in 1.0.20). It reserved the larger of Pi's `compaction.reserveTokens` and the model's `maxTokens`: with `maxTokens` 32,768 and a reserve of 16,384 on an 81,920 window, its room fell to 49,152 tokens, where native Pi compacts at 65,536 ([`CHANGELOG.md`](CHANGELOG.md) 1.0.20).
|
|
@@ -193,7 +196,9 @@ A bad file is reported at session start, and pi-tuck uses the defaults.
|
|
|
193
196
|
|
|
194
197
|
pi-tuck keeps room for the model's reply. Since 1.0.20 that room is Pi's `compaction.reserveTokens` (default 16,384), the same as native Pi. It rises to the model's `maxTokens` for the rest of the branch only after a reply on that branch did not fit: a reply that stopped for length, or a request refused as a context overflow. A transient error such as a 503 keeps the native room. This is read from the current branch at each decision, so resume, fork and `/tree` follow the branch, and a new session starts at `reserveTokens` again. A host that passes its own reserve keeps its own. Before 1.0.20, pi-tuck always reserved the larger of the two, so with a large `maxTokens` it cut earlier than native Pi.
|
|
195
198
|
|
|
196
|
-
Since 1.0.22, pi-tuck refuses a request only past a line near the window. Pi sets each request's reply cap to the window less its own estimate of the request less a 4,096-token safety margin, and since 1.0.
|
|
199
|
+
Since 1.0.22, pi-tuck refuses a request only past a line near the window. Pi sets each request's reply cap to the window less its own estimate of the request less a 4,096-token safety margin, and since 1.0.26 pi-tuck loads Pi's own reply clamp and estimator from the running Pi's install (a host that embeds Pi falls back to the same 4,096-token margin). Since 1.0.25, each point that sends a request above the room checks Pi's own cap on the request it would send. When that leaves less than the reply floor, pi-tuck cuts deeper, with up to three re-plans and then the deepest cut that still carries the whole prompt, and refuses only if that leaves less than the floor too. The floor is the larger of the biggest reply seen on the branch and 3,584 tokens, capped at the model's own reply cap. After a reply that stopped for length or was refused as a context overflow, the floor is the reserve. The line never sits below the room, where 1.0.21 also sends. Before it refuses, pi-tuck cuts to the band, cuts to the room, makes a smaller summary and clips a fresh tool result, in that order. A run's request always carries the whole prompt that started the run: if it cannot fit after every reduction, pi-tuck stops the run with a notice saying to shorten the prompt or use a larger window. Each refusal, and each request sent above the room, leaves one `pi-tuck-capacity` entry in the session; it is never sent to the model, and never appears in summaries or recall.
|
|
200
|
+
|
|
201
|
+
Since 1.0.25, after a reply that stops for length with thinking only, pi-tuck retries the turn once, leaving the stopped reply out of the request. It uses the deepest cut that still carries the whole prompt when that gives the reply more room, and otherwise retries uncut. A retried reply that stops again ends the run. When a run ends on a reply cut at the output limit, pi-tuck says so ("the last reply stopped at the model's output limit and may be cut off"): in the interface, or on stderr when there is no UI. The notice never enters the model's context.
|
|
197
202
|
|
|
198
203
|
pi-tuck estimates the request's size, and it scales that estimate by the worst gap it has seen between its count and the provider's. In a small window, an upstream that spends far more context on tool schemas (some OpenRouter upstreams do) can leave too little room. If a small window refuses, use a larger window, or pin one upstream as below.
|
|
199
204
|
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export type { CompactionOptions } from "./src/compaction.js";
|
|
|
3
3
|
export { installCompaction } from "./src/compaction.js";
|
|
4
4
|
export { inspectIncident, readableIncident } from "./src/diagnostic-replay.js";
|
|
5
5
|
export { createSemanticRecall, SemanticRecallController } from "./src/semantic-recall.js";
|
|
6
|
-
export type { SemanticRecallConfig, PriorResult, SemanticState } from "./src/semantic-recall.js";
|
|
6
|
+
export type { SemanticRecallConfig, PriorResult, SemanticState, SemanticSetup } from "./src/semantic-recall.js";
|
|
7
7
|
export { ensureSemanticRuntime } from "./src/setup.js";
|
|
8
8
|
/** pi-tuck as a Pi extension: compaction and history recall always; semantic recall too, unless `pi-tuck.json` in Pi's agent folder
|
|
9
9
|
* says `{"semanticRecall": false}`. Its runtime is set up in the background the first time a session starts. The same file's `"cutAt"`
|
package/dist/index.js
CHANGED
|
@@ -43,14 +43,21 @@ export default async function (pi) {
|
|
|
43
43
|
}
|
|
44
44
|
const semanticRecall = createSemanticRecall();
|
|
45
45
|
// `/tuck-semantic off` holds for the rest of the session, including over a setup that finishes later.
|
|
46
|
-
let off = false;
|
|
47
46
|
const settings = readSettings(join(getAgentDir(), "pi-tuck.json"));
|
|
48
47
|
// Semantic recall runs on Metal, so only on Apple silicon; elsewhere the model is not offered tuck_search at all.
|
|
49
48
|
const appleSilicon = process.platform === "darwin" && process.arch === "arm64";
|
|
50
|
-
const handle = await installCompaction(pi, { semanticRecall, search: appleSilicon, cutAt: settings.cutAt, onSemanticSetting: async (enabled) => {
|
|
51
|
-
|
|
49
|
+
const handle = await installCompaction(pi, { semanticRecall, search: appleSilicon, cutAt: settings.cutAt, onSemanticSetting: async (enabled) => {
|
|
50
|
+
if (!enabled)
|
|
51
|
+
semanticRecall.setSetup("off-user");
|
|
52
|
+
else if (semanticRecall.status().setup === "off-user")
|
|
53
|
+
semanticRecall.setSetup("starting", { installed: existsSync(runtimeConfigPath(defaultRoot())) });
|
|
54
|
+
} });
|
|
55
|
+
if (settings.semanticRecall === false) {
|
|
56
|
+
semanticRecall.setSetup("off-settings");
|
|
57
|
+
pi.on("session_start", () => { semanticRecall.setSetup("off-settings"); });
|
|
52
58
|
return;
|
|
53
|
-
|
|
59
|
+
}
|
|
60
|
+
let session = 0, said = "", announced = false, setup;
|
|
54
61
|
// A context outlives its session (a setup can finish after /new); a notice to an ended session is dropped.
|
|
55
62
|
// With no UI (pi -p), Pi shows no notices, so a settings error or an off or failing semantic recall would go unsaid: write each to stderr
|
|
56
63
|
// instead, once per session. stderr is the operator's; it never enters the model's context.
|
|
@@ -75,49 +82,55 @@ export default async function (pi) {
|
|
|
75
82
|
said = message;
|
|
76
83
|
say(ctx, message, level);
|
|
77
84
|
} };
|
|
85
|
+
const announce = (ctx, state, detail) => {
|
|
86
|
+
semanticRecall.setSetup(state, detail);
|
|
87
|
+
const notice = semanticRecall.setupNotice();
|
|
88
|
+
if (notice)
|
|
89
|
+
(state === "off-platform" || state === "off-project" ? once : say)(ctx, notice.message, notice.level);
|
|
90
|
+
};
|
|
78
91
|
pi.on("session_shutdown", () => { session++; });
|
|
79
92
|
pi.on("session_start", (_event, ctx) => {
|
|
80
93
|
const current = ++session;
|
|
81
|
-
off = false;
|
|
82
94
|
stderrSaid.clear();
|
|
83
95
|
if (settings.error)
|
|
84
96
|
once(ctx, `pi-tuck: ${settings.error}; using the defaults.`, "warning");
|
|
85
97
|
if (!appleSilicon)
|
|
86
|
-
return
|
|
98
|
+
return announce(ctx, "off-platform");
|
|
87
99
|
// Semantic recall keeps its runtime and indexes outside the project it serves, so not when Pi runs in a folder that holds its
|
|
88
100
|
// agent folder, such as the home folder.
|
|
89
101
|
if (within(real(getAgentDir()), real(ctx.cwd)))
|
|
90
|
-
return
|
|
102
|
+
return announce(ctx, "off-project");
|
|
91
103
|
// A run with no UI (pi -p, RPC, JSON) uses a runtime that is already installed: that needs no download. It does not start a first-time
|
|
92
104
|
// setup, which would outlast a one-shot run, and it says why, so tuck_search and /tuck name the real state.
|
|
93
105
|
const installed = existsSync(runtimeConfigPath(defaultRoot()));
|
|
94
|
-
if (!ctx.hasUI && !installed)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
if (!ctx.hasUI && !installed)
|
|
107
|
+
return announce(ctx, "not-installed");
|
|
108
|
+
// The download's announcement outlives the session that made it: a session that starts while the shared setup is still running
|
|
109
|
+
// owes the "set up" notice once, as before the refactor.
|
|
110
|
+
semanticRecall.setSetup("starting", { installed, announced });
|
|
111
|
+
setup ??= ensureSemanticRuntime(defaultRoot(), message => {
|
|
112
|
+
announced = true;
|
|
113
|
+
if (current === session && semanticRecall.status().setup !== "off-user")
|
|
114
|
+
announce(ctx, "starting", { installed, notice: message, announced: true });
|
|
115
|
+
});
|
|
101
116
|
setup.then(async () => {
|
|
102
|
-
if (current !== session || off)
|
|
117
|
+
if (current !== session || semanticRecall.status().setup === "off-user")
|
|
103
118
|
return;
|
|
104
119
|
try {
|
|
105
|
-
await handle.setSemanticEnabled(true, ctx);
|
|
106
|
-
|
|
107
|
-
|
|
120
|
+
await handle.setSemanticEnabled(true, ctx);
|
|
121
|
+
if (current === session && semanticRecall.status().setup !== "off-user") {
|
|
122
|
+
announce(ctx, "ready", { announced });
|
|
108
123
|
announced = false;
|
|
109
|
-
say(ctx, "pi-tuck: semantic recall is set up. Search by meaning works from the first cut on.", "info");
|
|
110
124
|
}
|
|
111
125
|
}
|
|
112
126
|
catch (error) {
|
|
113
|
-
if (current === session)
|
|
114
|
-
|
|
127
|
+
if (current === session && semanticRecall.status().setup !== "off-user")
|
|
128
|
+
announce(ctx, "failed", { stage: "start", reason: reason(error) });
|
|
115
129
|
}
|
|
116
130
|
}, error => {
|
|
117
131
|
setup = undefined; // the next session start tries again
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
say(ctx, `pi-tuck: semantic recall setup failed (${reason(error)}). Word recall works; setup retries when a session starts.`, "warning");
|
|
132
|
+
if (current === session && semanticRecall.status().setup !== "off-user")
|
|
133
|
+
announce(ctx, "failed", { stage: "setup", reason: reason(error) });
|
|
121
134
|
});
|
|
122
135
|
});
|
|
123
136
|
}
|
package/dist/src/build-id.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const BUILD_ID = "
|
|
1
|
+
export declare const BUILD_ID = "e9c750b757776bf44ad79939b633f178ef9a8f14acfab1c8bb6311d692c79e61";
|
package/dist/src/build-id.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const BUILD_ID = "
|
|
1
|
+
export const BUILD_ID = "e9c750b757776bf44ad79939b633f178ef9a8f14acfab1c8bb6311d692c79e61";
|
package/dist/src/compaction.d.ts
CHANGED
|
@@ -74,6 +74,8 @@ export declare function installCompaction(pi: ExtensionAPI, options?: Compaction
|
|
|
74
74
|
close: () => Promise<void>;
|
|
75
75
|
semanticRecall: SemanticRecallController;
|
|
76
76
|
setSemanticEnabled: (enabled: boolean, ctx: ExtensionContext) => Promise<{
|
|
77
|
+
setup: import("./semantic-recall.js").SemanticSetup;
|
|
78
|
+
setupMessage: string | null;
|
|
77
79
|
enabled: boolean;
|
|
78
80
|
configured: boolean;
|
|
79
81
|
cleanupError: string | null;
|
|
@@ -119,6 +121,8 @@ export declare function installCompaction(pi: ExtensionAPI, options?: Compaction
|
|
|
119
121
|
semanticStatus: () => {
|
|
120
122
|
host?: unknown;
|
|
121
123
|
local: {
|
|
124
|
+
setup: import("./semantic-recall.js").SemanticSetup;
|
|
125
|
+
setupMessage: string | null;
|
|
122
126
|
enabled: boolean;
|
|
123
127
|
configured: boolean;
|
|
124
128
|
cleanupError: string | null;
|