pi-quiver 4.4.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +103 -25
- package/extensions/fast-mode.ts +1 -1
- package/extensions/provider-stall-watchdog.ts +3 -3
- package/extensions/session-name.ts +1 -1
- package/extensions/slack.ts +430 -0
- package/extensions/sword-header.ts +1 -1
- package/lib/extension-config.ts +46 -3
- package/lib/slack-cache.ts +338 -0
- package/lib/slack-core.ts +994 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,14 @@ Published to npm as `pi-quiver` (`pi install npm:pi-quiver`). Pushing a
|
|
|
8
8
|
via OIDC trusted publishing. The release helper at
|
|
9
9
|
`.agents/skills/release/scripts/release.sh` cuts the tag; CI publishes.
|
|
10
10
|
|
|
11
|
+
## v5.0.0 - 2026-08-29
|
|
12
|
+
|
|
13
|
+
- **New opt-in `slack` extension** (#7): eight `slack_*` tools (search, thread, post, update, delete, pin, upload, cache refresh) for context-safe Slack search/threads/posting. Dual `user`/`bot` token identities resolved per call from process env or the repo's `.env`, never cross-identity fallback. Workspace-keyed channel/user name->ID cache with a repo-overridable `cachePath`. Fetch-style output size gating on search/thread reads. `slack_post`'s `thread_body` (no `thread_ts`) posts a transactional headline+thread announce - oversized detail bodies upload as a file - with a documented recovery path on delivery failure. OFF by default; nested-only `quiver.slack` config, no legacy flat form. See [doc/slack.md](doc/slack.md).
|
|
14
|
+
|
|
15
|
+
## v4.5.0 - 2026-08-29
|
|
16
|
+
|
|
17
|
+
- Settings resolution: every pi-quiver setting is now read from an optional `"quiver"` root object in `settings.json` (`quiver.<key>`), grouping the four legacy flat keys (`fastMode`, `sessionAutoName`, `swordHeader`, `providerStallWatchdog`) plus any future key. The flat top-level form keeps working, but only for those four legacy keys - it is frozen there and never extended to new settings. Within a layer, `quiver.<key>` wins over flat `<key>` by presence; malformed values and flat/nested duplicates now emit a warning instead of resolving silently.
|
|
18
|
+
|
|
11
19
|
## v4.4.0 - 2026-08-26
|
|
12
20
|
|
|
13
21
|
- doc_to_md: backend ladder now tries a system Python >= 3.12 with `pymupdf4llm` importable, then a one-time managed venv (bootstrapped at the version pin into a per-OS cache dir) between the existing `uv` and `unpdf` rungs. Data plane extracted to pi-free `lib/doc-to-md-core.ts`; new `pi-quiver doc-to-md <path>` CLI subcommand and `doc-to-md` Claude Code skill. `uv`/`soffice` detection is now spawn-based (Windows-correct). The bundled Python conversion script is now resolved from the package root, fixing a path bug that broke it under the bundled CLI.
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ But the moment an agent does that, one `fetch` or PDF read can dump hundreds of
|
|
|
18
18
|
|
|
19
19
|
`fetch` and `doc_to_md` bring real web pages, GitHub issues/PRs, and local PDF/DOCX/PPTX files into context - and every result is size-gated by construction: over 32 KB or 1000 lines spills to a temp file with a preview and a grep/read hint, so a single call can never flood the window. Ingestion is what makes data-driven work possible; the gate is what keeps it safe.
|
|
20
20
|
|
|
21
|
-
`session-name`, `sword-header`, `fast-mode`,
|
|
21
|
+
`session-name`, `sword-header`, `fast-mode`, `provider-stall-watchdog`, and `slack` are opt-in ergonomics, recovery, and integration controls: session labeling, a themed startup header, Anthropic fast mode, semantic-stall recovery, and context-safe Slack search/threads/posting.
|
|
22
22
|
|
|
23
23
|
## Part of the pi agent toolkit
|
|
24
24
|
|
|
@@ -33,7 +33,7 @@ No code dependency between them. pi-quiver is call-level: it gates the size of w
|
|
|
33
33
|
|
|
34
34
|
## Mental model
|
|
35
35
|
|
|
36
|
-
Every ingestion extension here is context-safe by construction, not by convention: the size check runs on every call, there's no flag to forget. `fetch` and `doc_to_md` bring real sources in; `session-name`, `sword-header`, `fast-mode`,
|
|
36
|
+
Every ingestion extension here is context-safe by construction, not by convention: the size check runs on every call, there's no flag to forget. `fetch` and `doc_to_md` bring real sources in; `session-name`, `sword-header`, `fast-mode`, `provider-stall-watchdog`, and `slack` are opt-in.
|
|
37
37
|
|
|
38
38
|
```mermaid
|
|
39
39
|
flowchart LR
|
|
@@ -68,8 +68,9 @@ A 300 KB changelog page never touches your context window - you get a preview an
|
|
|
68
68
|
| `extensions/sword-header.ts` | `/builtin-header` | Themed ASCII startup header replacing pi's default logo. OFF by default. |
|
|
69
69
|
| `extensions/fast-mode.ts` | `/fast` | Inject Anthropic fast-mode (`speed: "fast"` + `anthropic-beta: fast-mode-2026-02-01`) into every Claude Opus 4.8 / Opus 5 request, any thinking level. `--fast` flag + `/fast [on\|off\|status]`. OFF by default. |
|
|
70
70
|
| `extensions/provider-stall-watchdog.ts` | - | Opt-in provider-stall recovery, in two tiers: a pre-first-event deadline (`firstEventMs`, 20s) on every provider request in every mode, and the mid-stream pair (warn at 2 min, recover at 4 min) in TUI runs only. Policy D offers each stall to Pi's retry loop until the stall retry budget (`maxStallRetries`, default = `retry.maxRetries`) is exhausted. OFF by default. |
|
|
71
|
+
| `extensions/slack.ts` | `slack_search`, `slack_thread`, `slack_post`, `slack_update`, `slack_delete`, `slack_pin`, `slack_upload`, `slack_cache_refresh` | Context-safe Slack search/threads/posting with dual `user`/`bot` token identities, a workspace-keyed channel/user name->ID cache, fetch-style output size gating, and a transactional headline+detail-thread announce protocol with a documented recovery path. OFF by default. Behavior lives in `lib/slack-core.ts` and `lib/slack-cache.ts`. |
|
|
71
72
|
|
|
72
|
-
Full routing rules, size-gate mechanics, and config: [doc/fetch.md](doc/fetch.md), [doc/doc-to-md.md](doc/doc-to-md.md).
|
|
73
|
+
Full routing rules, size-gate mechanics, and config: [doc/fetch.md](doc/fetch.md), [doc/doc-to-md.md](doc/doc-to-md.md), [doc/slack.md](doc/slack.md).
|
|
73
74
|
|
|
74
75
|
## Key concepts
|
|
75
76
|
|
|
@@ -78,7 +79,7 @@ Full routing rules, size-gate mechanics, and config: [doc/fetch.md](doc/fetch.md
|
|
|
78
79
|
| Size gate | Text/Markdown/JSON output over 32 KB or 1000 lines spills to a temp file with a 60-line preview instead of inlining. |
|
|
79
80
|
| Content routing | HTML -> Markdown, binary -> untouched file, GitHub URLs -> `gh` CLI (failed runs/jobs get failed-step logs appended), everything else -> the size gate. |
|
|
80
81
|
| Graceful degradation | Optional binaries (`gh`, `uv`, LibreOffice) are never hard install-time deps; each has a defined, documented fallback or failure mode. |
|
|
81
|
-
| Opt-in extensions | `session-name`, `sword-header`, `fast-mode`,
|
|
82
|
+
| Opt-in extensions | `session-name`, `sword-header`, `fast-mode`, `provider-stall-watchdog`, and `slack` do nothing until explicitly enabled in `settings.json`. |
|
|
82
83
|
| Provider stall recovery | The watchdog detects a missing first stream event and missing parsed semantic progress, not network liveness. The pre-first-event tier covers every mode and origin; the mid-stream tier is TUI-only. |
|
|
83
84
|
|
|
84
85
|
## When to use
|
|
@@ -137,45 +138,72 @@ None is a hard install-time dependency of the package; they are tools you provid
|
|
|
137
138
|
|
|
138
139
|
### Opt-in extension config
|
|
139
140
|
|
|
140
|
-
These extensions are opt-in via `settings.json` (project `.pi/settings.json` overrides the global agent-dir layer):
|
|
141
|
+
These extensions are opt-in via `settings.json` (project `.pi/settings.json` overrides the global agent-dir layer), nested under an optional `"quiver"` root:
|
|
141
142
|
|
|
142
143
|
```jsonc
|
|
143
144
|
{
|
|
144
|
-
"
|
|
145
|
-
"
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
145
|
+
"quiver": {
|
|
146
|
+
"sessionAutoName": {
|
|
147
|
+
"enabled": false,
|
|
148
|
+
"ghosttyTab": true,
|
|
149
|
+
"rules": [],
|
|
150
|
+
"deny": [],
|
|
151
|
+
"revisitFirstTurn": 0,
|
|
152
|
+
"revisitEveryTurns": 0
|
|
153
|
+
}, // or boolean shorthand
|
|
154
|
+
"swordHeader": false, // or { "enabled": true }
|
|
155
|
+
"fastMode": false, // or { "enabled": true }
|
|
156
|
+
"providerStallWatchdog": false, // or { "enabled": true }
|
|
157
|
+
"slack": false // or { "enabled": true, ... }
|
|
158
|
+
}
|
|
155
159
|
}
|
|
156
160
|
```
|
|
157
161
|
|
|
162
|
+
Each key resolves independently: within a layer, `quiver.<key>` wins over a
|
|
163
|
+
flat top-level `<key>` by presence alone (even when the winning value is
|
|
164
|
+
malformed); across layers, each layer's candidate is validated into a partial
|
|
165
|
+
patch and `Object.assign`ed over the accumulator in layer order (project
|
|
166
|
+
last), so project fields override matching global fields while unmatched
|
|
167
|
+
global fields survive - a flat-vs-nested shape difference between layers
|
|
168
|
+
never changes this. The flat top-level form still works, but only for four
|
|
169
|
+
legacy keys, frozen at `fastMode`, `sessionAutoName`, `swordHeader`, and
|
|
170
|
+
`providerStallWatchdog` - never extended to new settings (see [Migrating from
|
|
171
|
+
flat keys](#migrating-from-flat-keys)).
|
|
172
|
+
|
|
173
|
+
Worked mixed-shape example: global `settings.json` has flat
|
|
174
|
+
`"fastMode": false`, project `.pi/settings.json` has
|
|
175
|
+
`"quiver": { "fastMode": { "enabled": true } }`. The project layer's
|
|
176
|
+
patch (`{ "enabled": true }`) is `Object.assign`ed over the accumulator
|
|
177
|
+
seeded from global's patch, so the resolved config is `{ "enabled": true }` -
|
|
178
|
+
same outcome here because `enabled` is the only field either layer sets, but
|
|
179
|
+
the merge is per-field: a global field with no project counterpart would
|
|
180
|
+
survive untouched.
|
|
181
|
+
|
|
158
182
|
`sessionAutoName.enabled` makes one extra short LLM call per session (once, after the first turn) to title it; `false` (default) makes no model calls. `rules` appends house conventions to the naming prompt (later rules win when they conflict with the built-ins). Literal, case-insensitive `deny` phrases are stripped from every name; whitespace inside a phrase is loose, so `"acme corp"` also catches `AcmeCorp`. `revisitFirstTurn` re-evaluates the name once that many model round trips have completed, while `revisitEveryTurns` does so at every multiple; both default to `0` (off) because each revisit costs another short LLM call. For example, `10` and `100` mark round trips 10, 100, 200, 300. Revisits only run when the agent has fully settled (idle, nothing queued) - an automated multi-turn run such as a subagent chain is never renamed or delayed mid-flight; cadence points it crossed fire once, at the settle. A machine-generated name is replaced when stale. A name set by a human is never overwritten: the extension strongly prefers it, and announces a suggestion only when the work has clearly moved on. Counts come from the persisted transcript, so they survive resume.
|
|
159
183
|
|
|
160
184
|
`fastMode` only affects `claude-opus-4-8` and `claude-opus-5` requests on Anthropic's `anthropic-messages` API; enabling it opts into premium fast-mode pricing. `--fast` forces it on for one launch; `/fast on|off` toggles live. Proxy providers (opencode, cloudflare-ai-gateway) are excluded. `fastMode`'s header injection needs the `before_provider_headers` hook (pi bundling `@earendil-works/pi-coding-agent` >= 0.80.5); on older pi the beta header is silently not sent. See [doc/fetch.md](doc/fetch.md) and [doc/doc-to-md.md](doc/doc-to-md.md) for the ingestion tools' full reference; session-name/sword-header behavior above is complete.
|
|
161
185
|
|
|
162
186
|
`pi-ai` prices every fast request at standard rates - it has no `usage.speed` support and no request-level pricing modifier - so `fastMode` corrects the reported cost itself: a `message_end` handler scales all four `usage.cost` components by `FAST_MODE_COST_MULTIPLIER` (2x) and returns the corrected message. Persisted session JSONL and pi's own native cost display are always exact, since they're written from this corrected message. pi-cohort's live `Σ$` reflects the correction only when pi-quiver's `message_end` handler runs before pi-cohort's - best-effort, depending on extension load order - and is reconciled on pi-cohort's next `session_start` regardless. The upstream fix (teaching `pi-ai`'s `Usage`/`calculateCost` about `usage.speed`) is the better long-term path and is tracked separately.
|
|
163
187
|
|
|
164
|
-
Recommended explicit retry and watchdog settings
|
|
188
|
+
Recommended explicit retry and watchdog settings - `providerStallWatchdog`
|
|
189
|
+
nests under `quiver`, while pi-core's own `retry` stays flat beside it (it is
|
|
190
|
+
not a pi-quiver setting and is never nested):
|
|
165
191
|
|
|
166
192
|
```json
|
|
167
193
|
{
|
|
194
|
+
"quiver": {
|
|
195
|
+
"providerStallWatchdog": {
|
|
196
|
+
"enabled": true,
|
|
197
|
+
"firstEventMs": 20000,
|
|
198
|
+
"warningMs": 120000,
|
|
199
|
+
"recoveryMs": 240000,
|
|
200
|
+
"maxStallRetries": 3
|
|
201
|
+
}
|
|
202
|
+
},
|
|
168
203
|
"retry": {
|
|
169
204
|
"enabled": true,
|
|
170
205
|
"maxRetries": 3,
|
|
171
206
|
"baseDelayMs": 2000
|
|
172
|
-
},
|
|
173
|
-
"providerStallWatchdog": {
|
|
174
|
-
"enabled": true,
|
|
175
|
-
"firstEventMs": 20000,
|
|
176
|
-
"warningMs": 120000,
|
|
177
|
-
"recoveryMs": 240000,
|
|
178
|
-
"maxStallRetries": 3
|
|
179
207
|
}
|
|
180
208
|
}
|
|
181
209
|
```
|
|
@@ -205,13 +233,63 @@ Operational notes:
|
|
|
205
233
|
- **A watchdog abort that the provider ignores escalates after a fixed 10s.** Any post-abort stream event re-arms that deadline (bytes prove only that the connection was alive at that instant), so a stream that emits a straggler and then wedges still escalates 10s after its last event. This reduces the hang; it cannot force the provider to stop, and undici's timeouts remain the final backstop.
|
|
206
234
|
- **Headless runs report on stderr.** In `print`/`json` mode pi binds a no-op UI, so watchdog notices go out via `console.warn`. Nothing is ever written to stdout, which `json` mode uses for its protocol. In TUI and RPC the notices render as main-window notifications, not the bottom status line.
|
|
207
235
|
|
|
236
|
+
`slack` is OFF by default and, once enabled, adds eight `slack_*` tools (search, thread, post, update, delete, pin, upload, cache refresh) covering context-safe Slack search/threads/posting under dual `user`/`bot` token identities. Nested-only from day one (no legacy flat form):
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"quiver": {
|
|
241
|
+
"slack": {
|
|
242
|
+
"enabled": true,
|
|
243
|
+
"cachePath": ".pi/slack-cache.json",
|
|
244
|
+
"userTokenEnv": "SLACK_USER_TOKEN",
|
|
245
|
+
"botTokenEnv": "SLACK_BOT_TOKEN",
|
|
246
|
+
"uploadThresholdChars": 4000
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
| Key | Default | Meaning |
|
|
253
|
+
| --- | --- | --- |
|
|
254
|
+
| `enabled` | `false` | Master switch, checked at `session_start`; toggling takes effect next session. |
|
|
255
|
+
| `cachePath` | user-scope per-OS cache dir | Overrides where the workspace-keyed channel/user name->ID cache file is written; relative paths resolve against the repo root. |
|
|
256
|
+
| `userTokenEnv` | `SLACK_USER_TOKEN` | Env var name holding the user token (required for `slack_search`/`slack_thread`, no bot fallback). |
|
|
257
|
+
| `botTokenEnv` | `SLACK_BOT_TOKEN` | Env var name holding the bot token. |
|
|
258
|
+
| `uploadThresholdChars` | `4000` | Link-collapsed length above which an announce/thread detail body is delivered as a file upload instead of inline text. |
|
|
259
|
+
|
|
260
|
+
Each setting can also be overridden per-process via `PI_QUIVER_SLACK_ENABLED`, `PI_QUIVER_SLACK_CACHE_PATH`, `PI_QUIVER_SLACK_USER_TOKEN_ENV`, `PI_QUIVER_SLACK_BOT_TOKEN_ENV`, and `PI_QUIVER_SLACK_UPLOAD_THRESHOLD_CHARS` - applied on top of the resolved `settings.json` layers, same override rung the extension's config resolver defines. Tokens themselves are resolved per call: process env first, then the repo's `.env` file (or the primary checkout's, for a worktree with none) - never a fallback across identities. Full reference incl. cache layering, the announce protocol, and the `search.messages`/`conversations.replies` throttle caveats: [doc/slack.md](doc/slack.md).
|
|
261
|
+
|
|
262
|
+
### Migrating from flat keys
|
|
263
|
+
|
|
264
|
+
The flat top-level form (`"fastMode": ...` etc. directly under `settings.json`)
|
|
265
|
+
is the outdated configuration style. It is legacy-frozen to exactly the four
|
|
266
|
+
keys above - `fastMode`, `sessionAutoName`, `swordHeader`,
|
|
267
|
+
`providerStallWatchdog` - and will never gain a fifth. To migrate, wrap your
|
|
268
|
+
existing keys under `"quiver": { ... }` and delete the flat copies:
|
|
269
|
+
|
|
270
|
+
```jsonc
|
|
271
|
+
// before
|
|
272
|
+
{ "fastMode": true }
|
|
273
|
+
|
|
274
|
+
// after
|
|
275
|
+
{ "quiver": { "fastMode": true } }
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Until you delete the flat copy, having both set is not an error - the
|
|
279
|
+
duplicate resolves per the precedence above (nested wins within a layer) -
|
|
280
|
+
but it emits a warning notification, deduped per process (each unique
|
|
281
|
+
message fires at most once per pi process - in practice once per interactive
|
|
282
|
+
session) until the flat entry is removed. Every new pi-quiver setting introduced after this change
|
|
283
|
+
(for example a future `slack` key) is nested-only from day one: it has no
|
|
284
|
+
flat form to fall back to.
|
|
285
|
+
|
|
208
286
|
## Claude Code support
|
|
209
287
|
|
|
210
288
|
`fetch`'s core (`lib/fetch-core.ts`) is also published as a CLI, so Claude Code can use the same routing, size gate, and spill behavior as pi's native tool - without pi ever seeing Claude-only files.
|
|
211
289
|
|
|
212
290
|
**Exposed:** the `quiver` plugin, served from this repo's `.claude-plugin/marketplace.json`, with two skills: `fetch` (invoked as `quiver:fetch` / `/quiver:fetch`) and `doc-to-md` (invoked as `quiver:doc-to-md` / `/quiver:doc-to-md`). The `fetch` skill runs `npx -y pi-quiver@latest fetch <url> [flags]` via Bash - full parameter parity with the pi tool (`--method`, `--header`, `--body`, `--raw`, `--timeout-ms`), same GitHub `gh` routing (including failed-step logs on failed runs/jobs), same size gate, same binary-to-temp-file handling. See [doc/fetch.md](doc/fetch.md#claude-code-cli-pi-quiver-fetch) for exit codes and flags. The `doc-to-md` skill runs `npx -y pi-quiver@latest doc-to-md <path>` via Bash - same backend ladder, size gate, and degraded-fallback marking as the pi tool. See [doc/doc-to-md.md](doc/doc-to-md.md#cli-pi-quiver-doc-to-md) for exit codes.
|
|
213
291
|
|
|
214
|
-
**Not exposed:** the other pi extensions in this package (`session-name`, `sword-header`, `fast-mode`, `provider-stall-watchdog`) - the marketplace allowlists only `./skills/fetch` and `./skills/doc-to-md`, and the npm tarball never ships `skills/` or `.claude-plugin/` (pi's own `files` allowlist excludes them, and pi's explicit `pi.extensions` manifest makes them invisible to pi's convention-directory auto-discovery either way).
|
|
292
|
+
**Not exposed:** the other pi extensions in this package (`session-name`, `sword-header`, `fast-mode`, `provider-stall-watchdog`, `slack`) - the marketplace allowlists only `./skills/fetch` and `./skills/doc-to-md`, and the npm tarball never ships `skills/` or `.claude-plugin/` (pi's own `files` allowlist excludes them, and pi's explicit `pi.extensions` manifest makes them invisible to pi's convention-directory auto-discovery either way).
|
|
215
293
|
|
|
216
294
|
Add the marketplace and enable the plugin in `.claude/settings.json`:
|
|
217
295
|
|
package/extensions/fast-mode.ts
CHANGED
|
@@ -116,7 +116,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
116
116
|
const readFlag = (): boolean => pi.getFlag("fast") === true;
|
|
117
117
|
|
|
118
118
|
const resolveState = (ctx: ExtensionContext): boolean => {
|
|
119
|
-
const config = resolveConfig(ctx.cwd, "fastMode", DEFAULT_CONFIG, coerce).enabled;
|
|
119
|
+
const config = resolveConfig(ctx.cwd, "fastMode", DEFAULT_CONFIG, coerce, (m) => ctx.ui.notify(m, "warning")).enabled;
|
|
120
120
|
enabled = resolveEnabled({ config, flag: readFlag(), live: liveOverride });
|
|
121
121
|
return enabled;
|
|
122
122
|
};
|
|
@@ -91,8 +91,8 @@ export function resolveRetryMaxRetries(cwd: string): number {
|
|
|
91
91
|
return maxRetries;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
export function resolveWatchdogConfig(cwd: string): ConfigValidation {
|
|
95
|
-
const candidate = resolveConfig(cwd, "providerStallWatchdog", DEFAULT_CANDIDATE, coerce);
|
|
94
|
+
export function resolveWatchdogConfig(cwd: string, warn?: (msg: string) => void): ConfigValidation {
|
|
95
|
+
const candidate = resolveConfig(cwd, "providerStallWatchdog", DEFAULT_CANDIDATE, coerce, warn);
|
|
96
96
|
if (candidate.blockIsObject === true && candidate.maxStallRetries === undefined) {
|
|
97
97
|
candidate.maxStallRetries = resolveRetryMaxRetries(cwd);
|
|
98
98
|
}
|
|
@@ -278,7 +278,7 @@ export function createProviderStallWatchdog(runtime: WatchdogRuntime = defaultRu
|
|
|
278
278
|
ui = ctx.ui;
|
|
279
279
|
hasUI = ctx.hasUI;
|
|
280
280
|
if (!config) {
|
|
281
|
-
const resolved = resolveWatchdogConfig(ctx.cwd);
|
|
281
|
+
const resolved = resolveWatchdogConfig(ctx.cwd, (m) => announce(m, "warning"));
|
|
282
282
|
if (!resolved.ok) {
|
|
283
283
|
disabled = true;
|
|
284
284
|
announce(`providerStallWatchdog disabled: ${resolved.error}`, "warning");
|
|
@@ -96,7 +96,7 @@ export function coerce(raw: unknown): Partial<Config> | undefined {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
function loadConfig(ctx: ExtensionContext): Config {
|
|
99
|
-
return resolveConfig(ctx.cwd, "sessionAutoName", DEFAULT_CONFIG, coerce);
|
|
99
|
+
return resolveConfig(ctx.cwd, "sessionAutoName", DEFAULT_CONFIG, coerce, (m) => ctx.ui.notify(m, "warning"));
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
type ContentBlock = { type?: string; text?: string };
|