@aiwayds/dsh-tui-pi 0.11.2 → 0.13.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/lib/usage.d.ts ADDED
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Slash-command / skill usage memory for frequency-sorted completions.
3
+ *
4
+ * Every successful command execution and every `/name` skill gesture bumps a
5
+ * per-name counter; the generic `/` completion dropdown orders candidates by
6
+ * that count (most used first) instead of plain name order, and the ordering
7
+ * survives the query filter (whatever remains after prefix filtering is still
8
+ * frequency-first).
9
+ *
10
+ * Persistence: `$DSH_HOME/tui-command-usage.json` — a small JSON document the
11
+ * TUI owns outright (it never touches settings.yaml or any other live dsh
12
+ * file). The disk copy is authoritative across restarts AND across /reload:
13
+ * the reload swaps the plugin fiber, a fresh tracker is constructed by the new
14
+ * fiber and simply re-reads the file. Reads never throw (a missing or corrupt
15
+ * file degrades to an empty table); writes are atomic (tmp sibling + rename)
16
+ * and best-effort silent — a failed write must never take the UI down.
17
+ *
18
+ * Write policy: synchronous save on every record, no timer/flush queue.
19
+ * Usage events are inherently low-frequency (one human-invoked command or
20
+ * skill at a time) and the file stays tiny (bounded by MAX_ENTRIES), so the
21
+ * simplicity of write-through beats batching — and avoids teardown hazards
22
+ * for timers across hot-reload. Concurrent dsh processes share one store:
23
+ * each write merges only its own unsaved delta onto a fresh read of the
24
+ * file (baseline+delta, see CommandUsageTracker.persist) instead of
25
+ * clobbering the whole table with this fiber's in-memory view.
26
+ */
27
+ /** On-disk schema version; bump only for breaking changes. */
28
+ export declare const USAGE_FILE_VERSION = 1;
29
+ /** One name's usage record: how often + how recently it was invoked. */
30
+ export interface UsageEntry {
31
+ /** Successful invocation count (>= 1 for every stored entry). */
32
+ count: number;
33
+ /** Epoch ms of the most recent invocation. */
34
+ lastUsed: number;
35
+ }
36
+ /** Name → count view handed to the completion sort (no recency exposed). */
37
+ export type UsageSnapshot = ReadonlyMap<string, number>;
38
+ /**
39
+ * Structural consumer contract so CommandService stays stub-friendly in
40
+ * tests (and decoupled from the concrete tracker's file concerns).
41
+ */
42
+ export interface UsageRecorder {
43
+ /** Count one invocation of `name` (leading slash tolerated, stripped). */
44
+ record(name: string): void;
45
+ /** Current name → count table (may be empty). */
46
+ snapshot(): UsageSnapshot;
47
+ }
48
+ /** Storage cap: above this many names, lowest-count entries are evicted. */
49
+ export declare const MAX_USAGE_ENTRIES = 500;
50
+ /** `$DSH_HOME/tui-command-usage.json` (or an explicit home override). */
51
+ export declare function commandUsagePath(home?: string): string;
52
+ /**
53
+ * Read + validate a usage file into entries. Never throws: a missing,
54
+ * corrupt, wrong-version or malformed document yields an empty table.
55
+ * Individual bad entries are skipped, good siblings kept.
56
+ */
57
+ export declare function loadUsageEntries(path: string): Map<string, UsageEntry>;
58
+ /**
59
+ * Atomically persist entries as `{ version, counts }`. Creates the target
60
+ * directory when missing (a fresh DSH_HOME must not silently drop the first
61
+ * record), writes a tmp sibling then renames over the target so a crash
62
+ * never leaves half a file; on any failure the tmp sibling is cleaned up and
63
+ * the error swallowed (the caller treats persistence as best-effort — the
64
+ * in-memory table keeps working). Returns whether the write landed.
65
+ */
66
+ export declare function saveUsageEntries(path: string, entries: ReadonlyMap<string, UsageEntry>): boolean;
67
+ /**
68
+ * Evict entries beyond `maxEntries`, lowest count first, oldest use first
69
+ * among equal counts. A freshly recorded entry always survives within its
70
+ * count tier (its lastUsed is the newest of that tier).
71
+ */
72
+ export declare function pruneUsageEntries(entries: Map<string, UsageEntry>, maxEntries?: number): void;
73
+ /**
74
+ * In-memory usage table persisted through `path`. Constructed once per
75
+ * plugin fiber (so a /reload re-reads the authoritative disk state) and
76
+ * shared by the CommandService for both recording and completion sorting.
77
+ *
78
+ * Several dsh processes can run concurrently against the same $DSH_HOME, so
79
+ * persistence is baseline+delta instead of whole-table clobber: the tracker
80
+ * remembers what the file looked like at its last synchronization and each
81
+ * write folds only its own unsaved increments on top of a fresh read of the
82
+ * file (see `persist`).
83
+ */
84
+ export declare class CommandUsageTracker implements UsageRecorder {
85
+ private readonly path;
86
+ private readonly maxEntries;
87
+ private readonly now;
88
+ /** Working table, including this fiber's not-yet-flushed increments. */
89
+ private entries;
90
+ /** Per-name counts the file had at the last successful sync — the delta zero-point. */
91
+ private baseline;
92
+ constructor(path: string, options?: {
93
+ maxEntries?: number;
94
+ now?: () => number;
95
+ });
96
+ /** Count one invocation of `name` and persist synchronously (best-effort). */
97
+ record(name: string): void;
98
+ /** Current name → count table for the completion sort. */
99
+ snapshot(): UsageSnapshot;
100
+ /**
101
+ * Fold this fiber's unsaved delta onto a fresh read of the file and write
102
+ * the union back atomically.
103
+ *
104
+ * Per-name arithmetic is `file_count + (memory_count - baseline_count)`
105
+ * clamped at zero: plain max() would drop this fiber's unsaved increments,
106
+ * blind summing would double-count what this fiber already flushed. An
107
+ * entry this fiber pruned away contributes a zero delta, so peer-process
108
+ * counts survive untouched.
109
+ *
110
+ * Loss model: the read-modify-write below is deliberately not locked —
111
+ * another process writing between our read and our rename loses exactly
112
+ * that one concurrent record (bounded, single-record granularity; accepted
113
+ * for a UX-ordering hint). If the file is unreadable/corrupt at read time,
114
+ * the merge degrades to this fiber's own table for that pass.
115
+ */
116
+ private persist;
117
+ }
package/lib/usage.js ADDED
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Slash-command / skill usage memory for frequency-sorted completions.
3
+ *
4
+ * Every successful command execution and every `/name` skill gesture bumps a
5
+ * per-name counter; the generic `/` completion dropdown orders candidates by
6
+ * that count (most used first) instead of plain name order, and the ordering
7
+ * survives the query filter (whatever remains after prefix filtering is still
8
+ * frequency-first).
9
+ *
10
+ * Persistence: `$DSH_HOME/tui-command-usage.json` — a small JSON document the
11
+ * TUI owns outright (it never touches settings.yaml or any other live dsh
12
+ * file). The disk copy is authoritative across restarts AND across /reload:
13
+ * the reload swaps the plugin fiber, a fresh tracker is constructed by the new
14
+ * fiber and simply re-reads the file. Reads never throw (a missing or corrupt
15
+ * file degrades to an empty table); writes are atomic (tmp sibling + rename)
16
+ * and best-effort silent — a failed write must never take the UI down.
17
+ *
18
+ * Write policy: synchronous save on every record, no timer/flush queue.
19
+ * Usage events are inherently low-frequency (one human-invoked command or
20
+ * skill at a time) and the file stays tiny (bounded by MAX_ENTRIES), so the
21
+ * simplicity of write-through beats batching — and avoids teardown hazards
22
+ * for timers across hot-reload. Concurrent dsh processes share one store:
23
+ * each write merges only its own unsaved delta onto a fresh read of the
24
+ * file (baseline+delta, see CommandUsageTracker.persist) instead of
25
+ * clobbering the whole table with this fiber's in-memory view.
26
+ */
27
+ import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
28
+ import { dirname, join } from 'node:path';
29
+ import { dshHome } from "./append-system.js";
30
+ /** On-disk schema version; bump only for breaking changes. */
31
+ export const USAGE_FILE_VERSION = 1;
32
+ /** Storage cap: above this many names, lowest-count entries are evicted. */
33
+ export const MAX_USAGE_ENTRIES = 500;
34
+ /** `$DSH_HOME/tui-command-usage.json` (or an explicit home override). */
35
+ export function commandUsagePath(home = dshHome()) {
36
+ return join(home, 'tui-command-usage.json');
37
+ }
38
+ /** Normalize one usage key: completion-name form (no leading slashes), non-empty. */
39
+ function normalizeUsageName(name) {
40
+ const key = name.replace(/^\/+/, '');
41
+ return key === '' ? undefined : key;
42
+ }
43
+ /**
44
+ * Read + validate a usage file into entries. Never throws: a missing,
45
+ * corrupt, wrong-version or malformed document yields an empty table.
46
+ * Individual bad entries are skipped, good siblings kept.
47
+ */
48
+ export function loadUsageEntries(path) {
49
+ const empty = new Map();
50
+ let text;
51
+ try {
52
+ text = readFileSync(path, 'utf8');
53
+ }
54
+ catch {
55
+ return empty;
56
+ }
57
+ let raw;
58
+ try {
59
+ raw = JSON.parse(text);
60
+ }
61
+ catch {
62
+ return empty;
63
+ }
64
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw))
65
+ return empty;
66
+ const doc = raw;
67
+ if (doc.version !== USAGE_FILE_VERSION)
68
+ return empty;
69
+ const counts = doc.counts;
70
+ if (counts === null || typeof counts !== 'object' || Array.isArray(counts))
71
+ return empty;
72
+ const entries = new Map();
73
+ for (const [name, value] of Object.entries(counts)) {
74
+ const key = normalizeUsageName(name);
75
+ if (key === undefined || value === null || typeof value !== 'object')
76
+ continue;
77
+ const { count, lastUsed } = value;
78
+ if (typeof count !== 'number' || !Number.isInteger(count) || count <= 0)
79
+ continue;
80
+ entries.set(key, {
81
+ count,
82
+ lastUsed: typeof lastUsed === 'number' && Number.isFinite(lastUsed) && lastUsed >= 0 ? lastUsed : 0,
83
+ });
84
+ }
85
+ return entries;
86
+ }
87
+ /**
88
+ * Atomically persist entries as `{ version, counts }`. Creates the target
89
+ * directory when missing (a fresh DSH_HOME must not silently drop the first
90
+ * record), writes a tmp sibling then renames over the target so a crash
91
+ * never leaves half a file; on any failure the tmp sibling is cleaned up and
92
+ * the error swallowed (the caller treats persistence as best-effort — the
93
+ * in-memory table keeps working). Returns whether the write landed.
94
+ */
95
+ export function saveUsageEntries(path, entries) {
96
+ const doc = {
97
+ version: USAGE_FILE_VERSION,
98
+ counts: Object.fromEntries(entries),
99
+ };
100
+ const dir = dirname(path);
101
+ const pathBase = path.split('/').pop() ?? 'tui-command-usage.json';
102
+ const tmp = join(dir, `.${pathBase}.tmp-${process.pid}`);
103
+ try {
104
+ mkdirSync(dir, { recursive: true });
105
+ writeFileSync(tmp, JSON.stringify(doc));
106
+ renameSync(tmp, path);
107
+ return true;
108
+ }
109
+ catch {
110
+ // A failed write/rename can leave the `.…tmp-<pid>` sibling behind; clean
111
+ // up so no stray dotfile accumulates next to the store.
112
+ try {
113
+ rmSync(tmp, { force: true });
114
+ }
115
+ catch {
116
+ // Best-effort — persistence failures stay silent by design.
117
+ }
118
+ return false;
119
+ }
120
+ }
121
+ /**
122
+ * Evict entries beyond `maxEntries`, lowest count first, oldest use first
123
+ * among equal counts. A freshly recorded entry always survives within its
124
+ * count tier (its lastUsed is the newest of that tier).
125
+ */
126
+ export function pruneUsageEntries(entries, maxEntries = MAX_USAGE_ENTRIES) {
127
+ if (entries.size <= maxEntries)
128
+ return;
129
+ const ordered = [...entries.entries()].sort((a, b) => a[1].count - b[1].count || a[1].lastUsed - b[1].lastUsed);
130
+ for (let i = 0; i < ordered.length - maxEntries; i++)
131
+ entries.delete(ordered[i][0]);
132
+ }
133
+ /**
134
+ * In-memory usage table persisted through `path`. Constructed once per
135
+ * plugin fiber (so a /reload re-reads the authoritative disk state) and
136
+ * shared by the CommandService for both recording and completion sorting.
137
+ *
138
+ * Several dsh processes can run concurrently against the same $DSH_HOME, so
139
+ * persistence is baseline+delta instead of whole-table clobber: the tracker
140
+ * remembers what the file looked like at its last synchronization and each
141
+ * write folds only its own unsaved increments on top of a fresh read of the
142
+ * file (see `persist`).
143
+ */
144
+ export class CommandUsageTracker {
145
+ path;
146
+ maxEntries;
147
+ now;
148
+ /** Working table, including this fiber's not-yet-flushed increments. */
149
+ entries;
150
+ /** Per-name counts the file had at the last successful sync — the delta zero-point. */
151
+ baseline;
152
+ constructor(path, options) {
153
+ this.path = path;
154
+ this.maxEntries = Math.max(1, options?.maxEntries ?? MAX_USAGE_ENTRIES);
155
+ this.now = options?.now ?? Date.now;
156
+ const loaded = loadUsageEntries(path);
157
+ // Deep-copy into `entries`: record() mutates entry objects in place and
158
+ // must never disturb the frozen baseline. A hand-edited or pre-cap file
159
+ // may exceed the cap — normalize the working set on load.
160
+ this.entries = new Map([...loaded].map(([key, entry]) => [key, { ...entry }]));
161
+ this.baseline = loaded;
162
+ pruneUsageEntries(this.entries, this.maxEntries);
163
+ }
164
+ /** Count one invocation of `name` and persist synchronously (best-effort). */
165
+ record(name) {
166
+ const key = normalizeUsageName(name);
167
+ if (key === undefined)
168
+ return;
169
+ const entry = this.entries.get(key) ?? { count: 0, lastUsed: 0 };
170
+ entry.count += 1;
171
+ entry.lastUsed = this.now();
172
+ this.entries.set(key, entry);
173
+ this.persist();
174
+ }
175
+ /** Current name → count table for the completion sort. */
176
+ snapshot() {
177
+ return new Map([...this.entries].map(([name, entry]) => [name, entry.count]));
178
+ }
179
+ /**
180
+ * Fold this fiber's unsaved delta onto a fresh read of the file and write
181
+ * the union back atomically.
182
+ *
183
+ * Per-name arithmetic is `file_count + (memory_count - baseline_count)`
184
+ * clamped at zero: plain max() would drop this fiber's unsaved increments,
185
+ * blind summing would double-count what this fiber already flushed. An
186
+ * entry this fiber pruned away contributes a zero delta, so peer-process
187
+ * counts survive untouched.
188
+ *
189
+ * Loss model: the read-modify-write below is deliberately not locked —
190
+ * another process writing between our read and our rename loses exactly
191
+ * that one concurrent record (bounded, single-record granularity; accepted
192
+ * for a UX-ordering hint). If the file is unreadable/corrupt at read time,
193
+ * the merge degrades to this fiber's own table for that pass.
194
+ */
195
+ persist() {
196
+ const disk = loadUsageEntries(this.path);
197
+ const merged = new Map();
198
+ for (const key of new Set([...disk.keys(), ...this.entries.keys()])) {
199
+ const mine = this.entries.get(key);
200
+ const baseCount = this.baseline.get(key)?.count ?? 0;
201
+ const delta = Math.max(0, (mine?.count ?? 0) - baseCount);
202
+ const theirs = disk.get(key);
203
+ if (theirs === undefined && delta === 0)
204
+ continue;
205
+ merged.set(key, {
206
+ count: (theirs?.count ?? 0) + delta,
207
+ lastUsed: Math.max(theirs?.lastUsed ?? 0, mine?.lastUsed ?? 0),
208
+ });
209
+ }
210
+ pruneUsageEntries(merged, this.maxEntries);
211
+ if (!saveUsageEntries(this.path, merged))
212
+ return;
213
+ // Success: the written table becomes both the working set and the new
214
+ // delta zero-point. `entries` gets its own copies so later in-place
215
+ // record mutations leave the frozen baseline intact.
216
+ this.baseline = merged;
217
+ this.entries = new Map([...merged].map(([key, entry]) => [key, { ...entry }]));
218
+ }
219
+ }
220
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwayds/dsh-tui-pi",
3
- "version": "0.11.2",
3
+ "version": "0.13.0",
4
4
  "description": "pi-style terminal UI for DeepSeek Harness (dsh) — pi-tui look & feel, dsh slash commands, GitHub light/dark themes, powerline footer",
5
5
  "repository": {
6
6
  "type": "git",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "@aiwayds/dsh-dcp": "0.5.1",
49
- "@aiwayds/dsh-subagent-registry": "0.2.0",
49
+ "@aiwayds/dsh-subagent-registry": "0.3.0",
50
50
  "@earendil-works/pi-tui": "0.84.2"
51
51
  },
52
52
  "devDependencies": {