omp-vcc 0.1.7 → 0.1.8
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/README.md +5 -3
- package/extensions/main.ts +3 -1
- package/extensions/vcc-core/core/settings.ts +77 -0
- package/extensions/vcc-core/hook.ts +28 -1
- package/package.json +1 -1
- package/scripts/smoke.ts +4 -0
- package/skills/omp-vcc/SKILL.md +1 -0
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ New here → [`docs/setup.md`](docs/setup.md).
|
|
|
26
26
|
| `/vcc-recall [query] [scope:all] [page:N] [mode:touched]` | Search compacted history |
|
|
27
27
|
| `/pi-vcc-recall` | Legacy alias for `/vcc-recall` |
|
|
28
28
|
| `/vcc-stats [history\|all]` | Last savings + history table (single, no alias) |
|
|
29
|
+
| `/vcc-config` | Effective config with per-key source (`file` / `host overlay` / `default`) plus resolved file path. Args ignored. |
|
|
29
30
|
|
|
30
31
|
Tools: `vcc_recall`, `vcc_stats` (approval `read`). Extension-only — no `commands/*.md` file slash commands (avoids duplicate `/omp-vcc`).
|
|
31
32
|
|
|
@@ -53,7 +54,7 @@ File `~/.omp/omp-vcc/config.json` — XDG: `$OMP_VCC_CONFIG_PATH` > `$PI_VCC_CON
|
|
|
53
54
|
| `debug` | `false` | Write `/tmp/omp-vcc-debug.json` per compaction. |
|
|
54
55
|
| `chainShakeHint` | `false` | Eager post-VCC `shake` chain. Host rescue already auto-shakes on dead-end; this forces it. |
|
|
55
56
|
|
|
56
|
-
Toggle live: `omp config set plugins."@zhulinchng/omp-vcc".debug true` or `/settings` → `@zhulinchng/omp-vcc`. File is source of truth; `ctx.settings` overlays at runtime.
|
|
57
|
+
Toggle live: `omp config set plugins."@zhulinchng/omp-vcc".debug true` or `/settings` → `@zhulinchng/omp-vcc`. File is source of truth; `ctx.settings` overlays at runtime. `/vcc-config` shows the merged result — use it to confirm a toggle took effect.
|
|
57
58
|
|
|
58
59
|
## How it works
|
|
59
60
|
|
|
@@ -82,9 +83,9 @@ Additive VCC+shake is automatic. Eager chain: `chainShakeHint:true`. Explicit mo
|
|
|
82
83
|
|
|
83
84
|
```sh
|
|
84
85
|
bunx tsc --noEmit
|
|
85
|
-
bun test #
|
|
86
|
+
bun test # 619 tests, 55 files, 1876 expects, 0 fail
|
|
86
87
|
bun test tests/e2e --timeout 120000 # 111 E2E
|
|
87
|
-
bun run smoke #
|
|
88
|
+
bun run smoke # 13 checks: 3 hooks + 6 cmds + 2 tools + dedup (+ pipeline)
|
|
88
89
|
omp plugin link . && omp plugin doctor
|
|
89
90
|
```
|
|
90
91
|
|
|
@@ -97,6 +98,7 @@ bunx tsc --noEmit && bun test && bun run smoke
|
|
|
97
98
|
omp -e @zhulinchng/omp-vcc
|
|
98
99
|
/omp-vcc keep:1 # expect [Session Goal] + toast omp-vcc: kept 1/2 turns
|
|
99
100
|
/vcc-stats # table + history
|
|
101
|
+
/vcc-config # effective config card with per-key source
|
|
100
102
|
cat /tmp/omp-vcc-debug.json # when debug:true
|
|
101
103
|
```
|
|
102
104
|
|
package/extensions/main.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
scheduleCompactionStatsNotify,
|
|
20
20
|
registerVccStatsTool as registerVccStatsToolHook,
|
|
21
21
|
registerVccStatsCommand as registerVccStatsCommandHook,
|
|
22
|
+
registerVccConfigCommand as registerVccConfigCommandHook,
|
|
22
23
|
} from "./vcc-core/hook";
|
|
23
24
|
import { searchEntriesDetailed, getTouchedFiles } from "./vcc-core/core/search-entries";
|
|
24
25
|
import { formatRecallOutput, formatTouchedOutput } from "./vcc-core/core/format-recall";
|
|
@@ -342,9 +343,10 @@ export default function (pi: ExtensionAPI): void {
|
|
|
342
343
|
});
|
|
343
344
|
// ── /vcc-stats commands — show savings table (PR3) ──
|
|
344
345
|
registerVccStatsCommandHook(pi);
|
|
346
|
+
registerVccConfigCommandHook(pi);
|
|
345
347
|
|
|
346
348
|
}
|
|
347
349
|
// ── Re-exports for pi-vcc test compatibility (not dead: tests import via hook directly,
|
|
348
350
|
// but external consumers and the `vcc-recall` shim may import via main) ──
|
|
349
|
-
export { registerBeforeCompactHook, PI_VCC_COMPACT_INSTRUCTION, OMP_VCC_COMPACT_INSTRUCTION, getLastCompactionStats, getCompactionHistory, formatCompactionStats, formatStatsTable, formatLastStatsDetail, scheduleCompactionStatsNotify, AUTO_CONTINUE_CUSTOM_TYPE, LEGACY_AUTO_CONTINUE_CUSTOM_TYPE, invalidExpandIndices, registerRecallTool, registerVccRecallCommand, registerPiVccCommand, registerVccStatsTool, registerVccStatsCommand, clearCompactionHistoryForTests } from "./vcc-core/hook";
|
|
351
|
+
export { registerBeforeCompactHook, PI_VCC_COMPACT_INSTRUCTION, OMP_VCC_COMPACT_INSTRUCTION, getLastCompactionStats, getCompactionHistory, formatCompactionStats, formatStatsTable, formatLastStatsDetail, scheduleCompactionStatsNotify, AUTO_CONTINUE_CUSTOM_TYPE, LEGACY_AUTO_CONTINUE_CUSTOM_TYPE, invalidExpandIndices, registerRecallTool, registerVccRecallCommand, registerPiVccCommand, registerVccStatsTool, registerVccStatsCommand, registerVccConfigCommand, clearCompactionHistoryForTests } from "./vcc-core/hook";
|
|
350
352
|
export { buildPiVccCustomInstructions, parseKeepAndPrompt } from "./vcc-core/core/compact-args";
|
|
@@ -166,3 +166,80 @@ export function scaffoldSettings(): void {
|
|
|
166
166
|
// best-effort; never crash extension load
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
|
+
/** Live-resolved config path. Unlike the `SETTINGS_PATH` const (frozen at import
|
|
170
|
+
* time), this reflects the current `OMP_VCC_CONFIG_PATH` / `PI_VCC_CONFIG_PATH` env. */
|
|
171
|
+
export function getSettingsPath(): string {
|
|
172
|
+
return settingsPath();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export type VccSettingSource = "file" | "overlay" | "default";
|
|
176
|
+
|
|
177
|
+
export interface VccConfigView {
|
|
178
|
+
/** Live primary path — where a config file WOULD live. */
|
|
179
|
+
path: string;
|
|
180
|
+
/** Actual file parsed (primary, XDG/legacy fallback, or null when none). */
|
|
181
|
+
readPath: string | null;
|
|
182
|
+
/** True when a candidate file exists (even if unparseable). */
|
|
183
|
+
filePresent: boolean;
|
|
184
|
+
/** True when a candidate file parsed as a JSON object. */
|
|
185
|
+
fileValid: boolean;
|
|
186
|
+
/** Effective values — same merge as `loadSettings` (defaults ← file ← ctx overlay). */
|
|
187
|
+
values: PiVccSettings;
|
|
188
|
+
/** Per-key provenance. Presence check is `key in parsed`, so a file key that
|
|
189
|
+
* happens to equal the default still counts as `file`. */
|
|
190
|
+
sources: Record<keyof PiVccSettings, VccSettingSource>;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* `loadSettings` plus provenance for `/vcc-config`. Read-only: never creates or
|
|
195
|
+
* repairs files (`scaffoldSettings` owns that). Merge order mirrors `loadSettings`
|
|
196
|
+
* exactly — defaults, then the first readable candidate (primary, else the same
|
|
197
|
+
* `fallbackReadPath()` order), then the identical ctx overlay chain.
|
|
198
|
+
*/
|
|
199
|
+
export function loadSettingsWithSources(ctx?: unknown): VccConfigView {
|
|
200
|
+
const path = settingsPath();
|
|
201
|
+
const primaryParsed = readJson(path);
|
|
202
|
+
let parsed: Record<string, unknown> | null = primaryParsed;
|
|
203
|
+
let readPath: string | null = primaryParsed ? path : null;
|
|
204
|
+
if (!parsed) {
|
|
205
|
+
const fb = fallbackReadPath();
|
|
206
|
+
if (fb && fb !== path) {
|
|
207
|
+
const fbParsed = readJson(fb);
|
|
208
|
+
if (fbParsed) {
|
|
209
|
+
parsed = fbParsed;
|
|
210
|
+
readPath = fb;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const candidateExists = fallbackReadPath() !== null;
|
|
215
|
+
const valid = !!parsed && typeof parsed === "object";
|
|
216
|
+
const values: PiVccSettings =
|
|
217
|
+
valid && parsed
|
|
218
|
+
? { ...DEFAULT_SETTINGS, ...(parsed as Partial<PiVccSettings>) }
|
|
219
|
+
: { ...DEFAULT_SETTINGS };
|
|
220
|
+
const sources = {} as Record<keyof PiVccSettings, VccSettingSource>;
|
|
221
|
+
for (const k of Object.keys(DEFAULT_SETTINGS) as (keyof PiVccSettings)[]) {
|
|
222
|
+
sources[k] = valid && parsed && k in parsed ? "file" : "default";
|
|
223
|
+
}
|
|
224
|
+
if (ctx) {
|
|
225
|
+
const tryGet = (key: string): unknown => {
|
|
226
|
+
try {
|
|
227
|
+
const c = ctx as any;
|
|
228
|
+
if (!c) return undefined;
|
|
229
|
+
if (c.settings?.get) return c.settings.get(key);
|
|
230
|
+
if (c.config?.get) return c.config.get(key);
|
|
231
|
+
if (c.settings && typeof c.settings === "object" && key in c.settings) return c.settings[key];
|
|
232
|
+
if (c.config && typeof c.config === "object" && key in c.config) return c.config[key];
|
|
233
|
+
} catch {}
|
|
234
|
+
return undefined;
|
|
235
|
+
};
|
|
236
|
+
for (const k of Object.keys(DEFAULT_SETTINGS) as (keyof PiVccSettings)[]) {
|
|
237
|
+
const v = tryGet(`plugins.@zhulinchng/omp-vcc.${k}`) ?? tryGet(`plugins.omp-vcc.${k}`) ?? tryGet(`omp-vcc.${k}`) ?? tryGet(k);
|
|
238
|
+
if (v !== undefined) {
|
|
239
|
+
(values as any)[k] = v;
|
|
240
|
+
sources[k] = "overlay";
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return { path, readPath, filePresent: candidateExists, fileValid: valid, values, sources };
|
|
245
|
+
}
|
|
@@ -4,7 +4,7 @@ import { createRequire } from "node:module";
|
|
|
4
4
|
import { writeFileSync } from "fs";
|
|
5
5
|
import { compileRanked } from "./core/summarize";
|
|
6
6
|
import { buildPiVccCustomInstructions, parseKeepAndPrompt, PI_VCC_COMPACT_INSTRUCTION } from "./core/compact-args";
|
|
7
|
-
import { loadSettings, type PiVccSettings } from "./core/settings";
|
|
7
|
+
import { loadSettings, loadSettingsWithSources, DEFAULT_SETTINGS, type PiVccSettings, type VccConfigView } from "./core/settings";
|
|
8
8
|
import { calibrateCharsPerToken, estimateMessageContentChars, estimateMessageContentTokens, estimateTokensFromChars, collectUsageStats } from "./core/token-estimate";
|
|
9
9
|
import type { PiVccCompactionDetails } from "./details";
|
|
10
10
|
import type { CompactionReason } from "./types";
|
|
@@ -1332,4 +1332,31 @@ export const registerVccStatsCommand = (pi: any) => {
|
|
|
1332
1332
|
try { ctx?.ui?.notify?.(`vcc_stats: ${history.length} compaction(s)`, "info"); } catch {}
|
|
1333
1333
|
};
|
|
1334
1334
|
pi.registerCommand("vcc-stats", { description: "Show omp-vcc compaction savings (last + history)", handler });
|
|
1335
|
+
};
|
|
1336
|
+
// ── /vcc-config command — show effective configuration with per-key source ──
|
|
1337
|
+
export const formatVccConfigCard = (view: VccConfigView): string => {
|
|
1338
|
+
const header = `**omp-vcc config** (\`${view.path}\`)`;
|
|
1339
|
+
const status = !view.filePresent
|
|
1340
|
+
? "No config file found — showing defaults."
|
|
1341
|
+
: !view.fileValid
|
|
1342
|
+
? "Config file unparseable — showing defaults."
|
|
1343
|
+
: view.readPath === view.path
|
|
1344
|
+
? `Source: file ${view.readPath}`
|
|
1345
|
+
: `Source: fallback file ${view.readPath}`;
|
|
1346
|
+
const lines = (Object.keys(DEFAULT_SETTINGS) as (keyof PiVccSettings)[]).map(
|
|
1347
|
+
(k) => `- ${k}: ${view.values[k] ? "on" : "off"} (${view.sources[k] === "overlay" ? "host overlay" : view.sources[k]})`,
|
|
1348
|
+
);
|
|
1349
|
+
return [header, status, ...lines].join("\n");
|
|
1350
|
+
};
|
|
1351
|
+
|
|
1352
|
+
export const registerVccConfigCommand = (pi: any) => {
|
|
1353
|
+
const handler = async (_args: string, ctx: any) => {
|
|
1354
|
+
// args deliberately ignored — always show the effective config
|
|
1355
|
+
const view = loadSettingsWithSources(ctx);
|
|
1356
|
+
const output = formatVccConfigCard(view);
|
|
1357
|
+
const piAny = pi as unknown as { sendMessage?: (msg: unknown, opts?: unknown) => void };
|
|
1358
|
+
try { piAny.sendMessage?.({ customType: "vcc-config", content: output, display: true }, { triggerTurn: false }); } catch {}
|
|
1359
|
+
try { ctx?.ui?.notify?.(`vcc_config: ${Object.keys(view.values).length} keys from ${view.readPath ?? "defaults"}`, "info"); } catch {}
|
|
1360
|
+
};
|
|
1361
|
+
pi.registerCommand("vcc-config", { description: "Show omp-vcc effective configuration with per-key source", handler });
|
|
1335
1362
|
};
|
package/package.json
CHANGED
package/scripts/smoke.ts
CHANGED
|
@@ -75,6 +75,10 @@ try {
|
|
|
75
75
|
"vcc-stats command registered",
|
|
76
76
|
commands.some((c) => c.name === "vcc-stats"),
|
|
77
77
|
);
|
|
78
|
+
check(
|
|
79
|
+
"vcc-config command registered",
|
|
80
|
+
commands.some((c) => c.name === "vcc-config"),
|
|
81
|
+
);
|
|
78
82
|
check(
|
|
79
83
|
"no omp-vcc-stats duplicate",
|
|
80
84
|
!commands.some((c) => c.name === "omp-vcc-stats"),
|
package/skills/omp-vcc/SKILL.md
CHANGED
|
@@ -49,6 +49,7 @@ Use `vcc_recall` to search for prior work … Do not redo work already completed
|
|
|
49
49
|
| Task | How | Notes |
|
|
50
50
|
|---|---|---|
|
|
51
51
|
| **Check savings** | `/vcc-stats` · `vcc_stats({history:true})` | Last + history table (50-capped, no `omp-vcc-stats` alias). `/omp-vcc` toast is single line only; detailed savings via `/vcc-stats`. Use to confirm headroom before long edits. |
|
|
52
|
+
| **View config** | `/vcc-config` | Effective config with per-key source (`file` / `host overlay` / `default`) plus resolved file path. Args ignored. Use to confirm a `/settings` toggle took effect. |
|
|
52
53
|
| **Recall search** | `/vcc-recall <query> [scope:all] [page:2]` · alias `/pi-vcc-recall` · tool `vcc_recall({query, scope, mode, page, expand})` | 5 hits/page, up to 50 total. See cookbook below. |
|
|
53
54
|
| **Stats tool** | `vcc_stats({history?: boolean})` | Same as `/vcc-stats`. `history:true` = full 50-row table. |
|
|
54
55
|
|