@underactive/pi-topping 0.1.1 → 0.2.1
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 -2
- package/index.ts +5 -462
- package/package.json +2 -2
- package/{activity-meter.ts → src/activity-meter.ts} +31 -5
- package/src/format.ts +149 -0
- package/{menu.ts → src/menu.ts} +89 -61
- package/src/preview.ts +47 -0
- package/src/session.ts +43 -0
- package/src/settings.ts +215 -0
- package/src/words.ts +207 -0
- package/format.ts +0 -71
- package/settings.ts +0 -106
- package/words.ts +0 -195
package/src/words.ts
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activity word list for the randomized "Working..." indicator.
|
|
3
|
+
*
|
|
4
|
+
* A random word is picked on prompt and on tool execution start
|
|
5
|
+
* (see index.ts).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface WordEntry {
|
|
9
|
+
present_tense: string;
|
|
10
|
+
past_tense: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function pickRawWord(): WordEntry {
|
|
14
|
+
return WORDS[Math.floor(Math.random() * WORDS.length)]!;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function pickRandomWord(): string {
|
|
18
|
+
return `${pickRawWord().present_tense}…`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const WORDS: WordEntry[] = [
|
|
22
|
+
{ present_tense: "Accomplishing", past_tense: "Accomplished" },
|
|
23
|
+
{ present_tense: "Actioning", past_tense: "Actioned" },
|
|
24
|
+
{ present_tense: "Actualizing", past_tense: "Actualized" },
|
|
25
|
+
{ present_tense: "Architecting", past_tense: "Architected" },
|
|
26
|
+
{ present_tense: "Baking", past_tense: "Baked" },
|
|
27
|
+
{ present_tense: "Beaming", past_tense: "Beamed" },
|
|
28
|
+
{ present_tense: "Beboppin'", past_tense: "Bebopped" },
|
|
29
|
+
{ present_tense: "Befuddling", past_tense: "Befuddled" },
|
|
30
|
+
{ present_tense: "Billowing", past_tense: "Billowed" },
|
|
31
|
+
{ present_tense: "Blanching", past_tense: "Blanched" },
|
|
32
|
+
{ present_tense: "Bloviating", past_tense: "Bloviated" },
|
|
33
|
+
{ present_tense: "Boogieing", past_tense: "Boogied" },
|
|
34
|
+
{ present_tense: "Boondoggling", past_tense: "Boondoggled" },
|
|
35
|
+
{ present_tense: "Booping", past_tense: "Booped" },
|
|
36
|
+
{ present_tense: "Bootstrapping", past_tense: "Bootstrapped" },
|
|
37
|
+
{ present_tense: "Brewing", past_tense: "Brewed" },
|
|
38
|
+
{ present_tense: "Bunning", past_tense: "Bunned" },
|
|
39
|
+
{ present_tense: "Burrowing", past_tense: "Burrowed" },
|
|
40
|
+
{ present_tense: "Calculating", past_tense: "Calculated" },
|
|
41
|
+
{ present_tense: "Canoodling", past_tense: "Canoodled" },
|
|
42
|
+
{ present_tense: "Caramelizing", past_tense: "Caramelized" },
|
|
43
|
+
{ present_tense: "Cascading", past_tense: "Cascaded" },
|
|
44
|
+
{ present_tense: "Catapulting", past_tense: "Catapulted" },
|
|
45
|
+
{ present_tense: "Cerebrating", past_tense: "Cerebrated" },
|
|
46
|
+
{ present_tense: "Channeling", past_tense: "Channeled" },
|
|
47
|
+
{ present_tense: "Choreographing", past_tense: "Choreographed" },
|
|
48
|
+
{ present_tense: "Churning", past_tense: "Churned" },
|
|
49
|
+
{ present_tense: "Clauding", past_tense: "Clauded" },
|
|
50
|
+
{ present_tense: "Coalescing", past_tense: "Coalesced" },
|
|
51
|
+
{ present_tense: "Cogitating", past_tense: "Cogitated" },
|
|
52
|
+
{ present_tense: "Combobulating", past_tense: "Combobulated" },
|
|
53
|
+
{ present_tense: "Composing", past_tense: "Composed" },
|
|
54
|
+
{ present_tense: "Computing", past_tense: "Computed" },
|
|
55
|
+
{ present_tense: "Concocting", past_tense: "Concocted" },
|
|
56
|
+
{ present_tense: "Considering", past_tense: "Considered" },
|
|
57
|
+
{ present_tense: "Contemplating", past_tense: "Contemplated" },
|
|
58
|
+
{ present_tense: "Cooking", past_tense: "Cooked" },
|
|
59
|
+
{ present_tense: "Crafting", past_tense: "Crafted" },
|
|
60
|
+
{ present_tense: "Creating", past_tense: "Created" },
|
|
61
|
+
{ present_tense: "Crunching", past_tense: "Crunched" },
|
|
62
|
+
{ present_tense: "Crystallizing", past_tense: "Crystallized" },
|
|
63
|
+
{ present_tense: "Cultivating", past_tense: "Cultivated" },
|
|
64
|
+
{ present_tense: "Deciphering", past_tense: "Deciphered" },
|
|
65
|
+
{ present_tense: "Deliberating", past_tense: "Deliberated" },
|
|
66
|
+
{ present_tense: "Determining", past_tense: "Determined" },
|
|
67
|
+
{ present_tense: "Dilly-dallying", past_tense: "Dilly-dallied" },
|
|
68
|
+
{ present_tense: "Discombobulating", past_tense: "Discombobulated" },
|
|
69
|
+
{ present_tense: "Doing", past_tense: "Done" },
|
|
70
|
+
{ present_tense: "Doodling", past_tense: "Doodled" },
|
|
71
|
+
{ present_tense: "Drizzling", past_tense: "Drizzled" },
|
|
72
|
+
{ present_tense: "Ebbing", past_tense: "Ebbed" },
|
|
73
|
+
{ present_tense: "Effecting", past_tense: "Effected" },
|
|
74
|
+
{ present_tense: "Elucidating", past_tense: "Elucidated" },
|
|
75
|
+
{ present_tense: "Embellishing", past_tense: "Embellished" },
|
|
76
|
+
{ present_tense: "Enchanting", past_tense: "Enchanted" },
|
|
77
|
+
{ present_tense: "Envisioning", past_tense: "Envisioned" },
|
|
78
|
+
{ present_tense: "Fermenting", past_tense: "Fermented" },
|
|
79
|
+
{ present_tense: "Fiddle-faddling", past_tense: "Fiddle-faddled" },
|
|
80
|
+
{ present_tense: "Finagling", past_tense: "Finagled" },
|
|
81
|
+
{ present_tense: "Flambéing", past_tense: "Flambéed" },
|
|
82
|
+
{ present_tense: "Flibbertigibbeting", past_tense: "Flibbertigibbeted" },
|
|
83
|
+
{ present_tense: "Flowing", past_tense: "Flowed" },
|
|
84
|
+
{ present_tense: "Flummoxing", past_tense: "Flummoxed" },
|
|
85
|
+
{ present_tense: "Fluttering", past_tense: "Fluttered" },
|
|
86
|
+
{ present_tense: "Forging", past_tense: "Forged" },
|
|
87
|
+
{ present_tense: "Forming", past_tense: "Formed" },
|
|
88
|
+
{ present_tense: "Frolicking", past_tense: "Frolicked" },
|
|
89
|
+
{ present_tense: "Frosting", past_tense: "Frosted" },
|
|
90
|
+
{ present_tense: "Gallivanting", past_tense: "Gallivanted" },
|
|
91
|
+
{ present_tense: "Galloping", past_tense: "Galloped" },
|
|
92
|
+
{ present_tense: "Garnishing", past_tense: "Garnished" },
|
|
93
|
+
{ present_tense: "Generating", past_tense: "Generated" },
|
|
94
|
+
{ present_tense: "Gesticulating", past_tense: "Gesticulated" },
|
|
95
|
+
{ present_tense: "Germinating", past_tense: "Germinated" },
|
|
96
|
+
{ present_tense: "Gitifying", past_tense: "Gitified" },
|
|
97
|
+
{ present_tense: "Grooving", past_tense: "Grooved" },
|
|
98
|
+
{ present_tense: "Gusting", past_tense: "Gusted" },
|
|
99
|
+
{ present_tense: "Harmonizing", past_tense: "Harmonized" },
|
|
100
|
+
{ present_tense: "Hashing", past_tense: "Hashed" },
|
|
101
|
+
{ present_tense: "Hatching", past_tense: "Hatched" },
|
|
102
|
+
{ present_tense: "Herding", past_tense: "Herded" },
|
|
103
|
+
{ present_tense: "Honking", past_tense: "Honked" },
|
|
104
|
+
{ present_tense: "Hullaballooing", past_tense: "Hullaballooed" },
|
|
105
|
+
{ present_tense: "Hyperspacing", past_tense: "Hyperspaced" },
|
|
106
|
+
{ present_tense: "Ideating", past_tense: "Ideated" },
|
|
107
|
+
{ present_tense: "Imagining", past_tense: "Imagined" },
|
|
108
|
+
{ present_tense: "Improvising", past_tense: "Improvised" },
|
|
109
|
+
{ present_tense: "Incubating", past_tense: "Incubated" },
|
|
110
|
+
{ present_tense: "Inferring", past_tense: "Inferred" },
|
|
111
|
+
{ present_tense: "Infusing", past_tense: "Infused" },
|
|
112
|
+
{ present_tense: "Ionizing", past_tense: "Ionized" },
|
|
113
|
+
{ present_tense: "Jitterbugging", past_tense: "Jitterbugged" },
|
|
114
|
+
{ present_tense: "Julienning", past_tense: "Julienned" },
|
|
115
|
+
{ present_tense: "Kneading", past_tense: "Kneaded" },
|
|
116
|
+
{ present_tense: "Leavening", past_tense: "Leavened" },
|
|
117
|
+
{ present_tense: "Levitating", past_tense: "Levitated" },
|
|
118
|
+
{ present_tense: "Lollygagging", past_tense: "Lollygagged" },
|
|
119
|
+
{ present_tense: "Manifesting", past_tense: "Manifested" },
|
|
120
|
+
{ present_tense: "Marinating", past_tense: "Marinated" },
|
|
121
|
+
{ present_tense: "Meandering", past_tense: "Meandered" },
|
|
122
|
+
{ present_tense: "Metamorphosing", past_tense: "Metamorphosed" },
|
|
123
|
+
{ present_tense: "Misting", past_tense: "Misted" },
|
|
124
|
+
{ present_tense: "Moonwalking", past_tense: "Moonwalked" },
|
|
125
|
+
{ present_tense: "Moseying", past_tense: "Moseyed" },
|
|
126
|
+
{ present_tense: "Mulling", past_tense: "Mulled" },
|
|
127
|
+
{ present_tense: "Mustering", past_tense: "Mustered" },
|
|
128
|
+
{ present_tense: "Musing", past_tense: "Mused" },
|
|
129
|
+
{ present_tense: "Nebulizing", past_tense: "Nebulized" },
|
|
130
|
+
{ present_tense: "Nesting", past_tense: "Nested" },
|
|
131
|
+
{ present_tense: "Newspapering", past_tense: "Newspapered" },
|
|
132
|
+
{ present_tense: "Noodling", past_tense: "Noodled" },
|
|
133
|
+
{ present_tense: "Nucleating", past_tense: "Nucleated" },
|
|
134
|
+
{ present_tense: "Orbiting", past_tense: "Orbited" },
|
|
135
|
+
{ present_tense: "Orchestrating", past_tense: "Orchestrated" },
|
|
136
|
+
{ present_tense: "Osmosing", past_tense: "Osmosed" },
|
|
137
|
+
{ present_tense: "Perambulating", past_tense: "Perambulated" },
|
|
138
|
+
{ present_tense: "Percolating", past_tense: "Percolated" },
|
|
139
|
+
{ present_tense: "Perusing", past_tense: "Perused" },
|
|
140
|
+
{ present_tense: "Philosophising", past_tense: "Philosophised" },
|
|
141
|
+
{ present_tense: "Photosynthesizing", past_tense: "Photosynthesized" },
|
|
142
|
+
{ present_tense: "Pollinating", past_tense: "Pollinated" },
|
|
143
|
+
{ present_tense: "Pondering", past_tense: "Pondered" },
|
|
144
|
+
{ present_tense: "Pontificating", past_tense: "Pontificated" },
|
|
145
|
+
{ present_tense: "Pouncing", past_tense: "Pounced" },
|
|
146
|
+
{ present_tense: "Precipitating", past_tense: "Precipitated" },
|
|
147
|
+
{ present_tense: "Prestidigitating", past_tense: "Prestidigitated" },
|
|
148
|
+
{ present_tense: "Processing", past_tense: "Processed" },
|
|
149
|
+
{ present_tense: "Proofing", past_tense: "Proofed" },
|
|
150
|
+
{ present_tense: "Propagating", past_tense: "Propagated" },
|
|
151
|
+
{ present_tense: "Puttering", past_tense: "Puttered" },
|
|
152
|
+
{ present_tense: "Puzzling", past_tense: "Puzzled" },
|
|
153
|
+
{ present_tense: "Quantumizing", past_tense: "Quantumized" },
|
|
154
|
+
{ present_tense: "Razzle-dazzling", past_tense: "Razzle-dazzled" },
|
|
155
|
+
{ present_tense: "Razzmatazzing", past_tense: "Razzmatazzed" },
|
|
156
|
+
{ present_tense: "Recombobulating", past_tense: "Recombobulated" },
|
|
157
|
+
{ present_tense: "Reticulating", past_tense: "Reticulated" },
|
|
158
|
+
{ present_tense: "Roosting", past_tense: "Roosted" },
|
|
159
|
+
{ present_tense: "Ruminating", past_tense: "Ruminated" },
|
|
160
|
+
{ present_tense: "Sautéing", past_tense: "Sautéed" },
|
|
161
|
+
{ present_tense: "Scampering", past_tense: "Scampered" },
|
|
162
|
+
{ present_tense: "Schlepping", past_tense: "Schlepped" },
|
|
163
|
+
{ present_tense: "Scurrying", past_tense: "Scurried" },
|
|
164
|
+
{ present_tense: "Seasoning", past_tense: "Seasoned" },
|
|
165
|
+
{ present_tense: "Shenaniganing", past_tense: "Shenaniganed" },
|
|
166
|
+
{ present_tense: "Shimmying", past_tense: "Shimmied" },
|
|
167
|
+
{ present_tense: "Simmering", past_tense: "Simmered" },
|
|
168
|
+
{ present_tense: "Skedaddling", past_tense: "Skedaddled" },
|
|
169
|
+
{ present_tense: "Sketching", past_tense: "Sketched" },
|
|
170
|
+
{ present_tense: "Slithering", past_tense: "Slithered" },
|
|
171
|
+
{ present_tense: "Smooshing", past_tense: "Smooshed" },
|
|
172
|
+
{ present_tense: "Sock-hopping", past_tense: "Sock-hopped" },
|
|
173
|
+
{ present_tense: "Spelunking", past_tense: "Spelunked" },
|
|
174
|
+
{ present_tense: "Spinning", past_tense: "Spun" },
|
|
175
|
+
{ present_tense: "Sprouting", past_tense: "Sprouted" },
|
|
176
|
+
{ present_tense: "Stewing", past_tense: "Stewed" },
|
|
177
|
+
{ present_tense: "Sublimating", past_tense: "Sublimated" },
|
|
178
|
+
{ present_tense: "Swirling", past_tense: "Swirled" },
|
|
179
|
+
{ present_tense: "Swooping", past_tense: "Swooped" },
|
|
180
|
+
{ present_tense: "Symbioting", past_tense: "Symbioted" },
|
|
181
|
+
{ present_tense: "Synthesizing", past_tense: "Synthesized" },
|
|
182
|
+
{ present_tense: "Tempering", past_tense: "Tempered" },
|
|
183
|
+
{ present_tense: "Thinking", past_tense: "Thought" },
|
|
184
|
+
{ present_tense: "Thundering", past_tense: "Thundered" },
|
|
185
|
+
{ present_tense: "Tinkering", past_tense: "Tinkered" },
|
|
186
|
+
{ present_tense: "Tomfoolering", past_tense: "Tomfoolered" },
|
|
187
|
+
{ present_tense: "Topsy-turvying", past_tense: "Topsy-turvied" },
|
|
188
|
+
{ present_tense: "Transfiguring", past_tense: "Transfigured" },
|
|
189
|
+
{ present_tense: "Transmuting", past_tense: "Transmuted" },
|
|
190
|
+
{ present_tense: "Twisting", past_tense: "Twisted" },
|
|
191
|
+
{ present_tense: "Undulating", past_tense: "Undulated" },
|
|
192
|
+
{ present_tense: "Unfurling", past_tense: "Unfurled" },
|
|
193
|
+
{ present_tense: "Unravelling", past_tense: "Unravelled" },
|
|
194
|
+
{ present_tense: "Vibing", past_tense: "Vibed" },
|
|
195
|
+
{ present_tense: "Waddling", past_tense: "Waddled" },
|
|
196
|
+
{ present_tense: "Wandering", past_tense: "Wandered" },
|
|
197
|
+
{ present_tense: "Warping", past_tense: "Warped" },
|
|
198
|
+
{ present_tense: "Whatchamacalliting", past_tense: "Whatchamacallited" },
|
|
199
|
+
{ present_tense: "Whirlpooling", past_tense: "Whirlpooled" },
|
|
200
|
+
{ present_tense: "Whirring", past_tense: "Whirred" },
|
|
201
|
+
{ present_tense: "Whisking", past_tense: "Whisked" },
|
|
202
|
+
{ present_tense: "Wibbling", past_tense: "Wibbled" },
|
|
203
|
+
{ present_tense: "Working", past_tense: "Worked" },
|
|
204
|
+
{ present_tense: "Wrangling", past_tense: "Wrangled" },
|
|
205
|
+
{ present_tense: "Zesting", past_tense: "Zested" },
|
|
206
|
+
{ present_tense: "Zigzagging", past_tense: "Zigzagged" },
|
|
207
|
+
];
|
package/format.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/** Format an output-token count for the working indicator. */
|
|
2
|
-
export function formatTokens(count: number): string {
|
|
3
|
-
if (count < 1000) return count.toString();
|
|
4
|
-
const UNITS = [
|
|
5
|
-
{ threshold: 10_000, divisor: 1_000, decimals: 1, suffix: "k" },
|
|
6
|
-
{ threshold: 1_000_000, divisor: 1_000, decimals: 0, suffix: "k" },
|
|
7
|
-
{ threshold: 10_000_000, divisor: 1_000_000, decimals: 1, suffix: "M" },
|
|
8
|
-
];
|
|
9
|
-
const unit = UNITS.find(u => count < u.threshold);
|
|
10
|
-
if (unit) {
|
|
11
|
-
const value = unit.decimals > 0
|
|
12
|
-
? (count / unit.divisor).toFixed(unit.decimals)
|
|
13
|
-
: `${Math.round(count / unit.divisor)}`;
|
|
14
|
-
return `${value}${unit.suffix}`;
|
|
15
|
-
}
|
|
16
|
-
return `${Math.round(count / 1_000_000)}M`;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** Format elapsed milliseconds as minutes and zero-padded seconds. */
|
|
20
|
-
export function formatElapsed(ms: number): string {
|
|
21
|
-
const totalSeconds = Math.max(0, Math.floor(ms / 1000));
|
|
22
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
23
|
-
const seconds = totalSeconds % 60;
|
|
24
|
-
return `${minutes}m ${seconds.toString().padStart(2, "0")}s`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Incremental whitespace-boundary word counter.
|
|
29
|
-
*
|
|
30
|
-
* The in-word state is retained across streaming chunks so a word split across
|
|
31
|
-
* multiple deltas is counted exactly once.
|
|
32
|
-
*/
|
|
33
|
-
export class StreamingWordCounter {
|
|
34
|
-
#inWordByStream = new Map<string, boolean>();
|
|
35
|
-
|
|
36
|
-
count(text: string, stream = "default"): number {
|
|
37
|
-
let inWord = this.#inWordByStream.get(stream) ?? false;
|
|
38
|
-
let count = 0;
|
|
39
|
-
for (let i = 0; i < text.length; i++) {
|
|
40
|
-
const code = text.charCodeAt(i);
|
|
41
|
-
if (isWhitespace(code)) {
|
|
42
|
-
inWord = false;
|
|
43
|
-
} else if (!inWord) {
|
|
44
|
-
count++;
|
|
45
|
-
inWord = true;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
this.#inWordByStream.set(stream, inWord);
|
|
49
|
-
return count;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
reset(): void {
|
|
53
|
-
this.#inWordByStream.clear();
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function isWhitespace(code: number): boolean {
|
|
58
|
-
return (
|
|
59
|
-
code === 32 ||
|
|
60
|
-
(code >= 9 && code <= 13) ||
|
|
61
|
-
code === 160 ||
|
|
62
|
-
code === 0x1680 ||
|
|
63
|
-
(code >= 0x2000 && code <= 0x200a) ||
|
|
64
|
-
code === 0x2028 ||
|
|
65
|
-
code === 0x2029 ||
|
|
66
|
-
code === 0x202f ||
|
|
67
|
-
code === 0x205f ||
|
|
68
|
-
code === 0x3000 ||
|
|
69
|
-
code === 0xfeff
|
|
70
|
-
);
|
|
71
|
-
}
|
package/settings.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* settings.ts
|
|
3
|
-
*
|
|
4
|
-
* Persistent, per-user settings for pi-topping, stored at
|
|
5
|
-
* `~/.pi/agent/pi-topping/settings.json`. All six toggles
|
|
6
|
-
* default to enabled so behavior is unchanged for users who never open
|
|
7
|
-
* `/topping-settings`.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
11
|
-
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
12
|
-
import { dirname, join } from "node:path";
|
|
13
|
-
|
|
14
|
-
export interface DecoratorSettings {
|
|
15
|
-
decorations: {
|
|
16
|
-
animatedSpinner: boolean;
|
|
17
|
-
shimmer: boolean;
|
|
18
|
-
tokenActivityMonitor: boolean;
|
|
19
|
-
};
|
|
20
|
-
features: {
|
|
21
|
-
substituteDefaultMessage: boolean;
|
|
22
|
-
elapsedTime: boolean;
|
|
23
|
-
outputTokens: boolean;
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const DEFAULT_SETTINGS: DecoratorSettings = {
|
|
28
|
-
decorations: {
|
|
29
|
-
animatedSpinner: true,
|
|
30
|
-
shimmer: true,
|
|
31
|
-
tokenActivityMonitor: true,
|
|
32
|
-
},
|
|
33
|
-
features: {
|
|
34
|
-
substituteDefaultMessage: true,
|
|
35
|
-
elapsedTime: true,
|
|
36
|
-
outputTokens: true,
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/** Resolve the absolute path to this extension's settings file. */
|
|
41
|
-
export function settingsPath(): string {
|
|
42
|
-
return join(getAgentDir(), "pi-topping", "settings.json");
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* True for plain `{}`-style objects only -- excludes `null`, arrays, and
|
|
47
|
-
* primitives. Used to guard against malformed/hand-edited settings.json
|
|
48
|
-
* content (e.g. `"decorations": "oops"` or `"decorations": [1,2,3]`) before
|
|
49
|
-
* spreading it onto the defaults, so a wrong-shaped field can't leak stray
|
|
50
|
-
* properties (like numeric-string keys from spreading a string) into the
|
|
51
|
-
* merged settings object.
|
|
52
|
-
*/
|
|
53
|
-
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
54
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function cloneDefaults(): DecoratorSettings {
|
|
58
|
-
return {
|
|
59
|
-
decorations: { ...DEFAULT_SETTINGS.decorations },
|
|
60
|
-
features: { ...DEFAULT_SETTINGS.features },
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Load settings from disk, deep-merging any persisted values onto the
|
|
66
|
-
* defaults. Returns a fresh clone of `DEFAULT_SETTINGS` if the file is
|
|
67
|
-
* missing or contains malformed JSON -- this function never throws.
|
|
68
|
-
*/
|
|
69
|
-
export function loadSettings(): DecoratorSettings {
|
|
70
|
-
const defaults = cloneDefaults();
|
|
71
|
-
let raw: string;
|
|
72
|
-
try {
|
|
73
|
-
raw = readFileSync(settingsPath(), "utf8");
|
|
74
|
-
} catch {
|
|
75
|
-
return defaults;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
const parsed = JSON.parse(raw) as Partial<DecoratorSettings> | null;
|
|
80
|
-
if (!isPlainObject(parsed)) return defaults;
|
|
81
|
-
return {
|
|
82
|
-
decorations: { ...defaults.decorations, ...(isPlainObject(parsed.decorations) ? parsed.decorations : undefined) },
|
|
83
|
-
features: { ...defaults.features, ...(isPlainObject(parsed.features) ? parsed.features : undefined) },
|
|
84
|
-
};
|
|
85
|
-
} catch {
|
|
86
|
-
return defaults;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Persist settings to disk, creating the parent directory if needed.
|
|
92
|
-
* Writes to a temp file and renames it into place so a crash mid-write
|
|
93
|
-
* (kill -9, OOM, disk full) can never leave `settings.json` truncated or
|
|
94
|
-
* corrupt -- `renameSync` is atomic on POSIX filesystems when source and
|
|
95
|
-
* destination are on the same directory/filesystem, which they always are
|
|
96
|
-
* here. A stale `.tmp` file left behind by a crash is harmless: the next
|
|
97
|
-
* successful `saveSettings()` call overwrites it, and `loadSettings()`
|
|
98
|
-
* never reads it.
|
|
99
|
-
*/
|
|
100
|
-
export function saveSettings(settings: DecoratorSettings): void {
|
|
101
|
-
const path = settingsPath();
|
|
102
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
103
|
-
const tmpPath = `${path}.tmp`;
|
|
104
|
-
writeFileSync(tmpPath, `${JSON.stringify(settings, null, 2)}\n`);
|
|
105
|
-
renameSync(tmpPath, path);
|
|
106
|
-
}
|
package/words.ts
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Activity word list for the randomized "Working..." indicator.
|
|
3
|
-
*
|
|
4
|
-
* A random word is picked on prompt and on tool execution start
|
|
5
|
-
* (see index.ts).
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export const WORDS: string[] = [
|
|
9
|
-
"Accomplishing",
|
|
10
|
-
"Actioning",
|
|
11
|
-
"Actualizing",
|
|
12
|
-
"Architecting",
|
|
13
|
-
"Baking",
|
|
14
|
-
"Beaming",
|
|
15
|
-
"Beboppin'",
|
|
16
|
-
"Befuddling",
|
|
17
|
-
"Billowing",
|
|
18
|
-
"Blanching",
|
|
19
|
-
"Bloviating",
|
|
20
|
-
"Boogieing",
|
|
21
|
-
"Boondoggling",
|
|
22
|
-
"Booping",
|
|
23
|
-
"Bootstrapping",
|
|
24
|
-
"Brewing",
|
|
25
|
-
"Bunning",
|
|
26
|
-
"Burrowing",
|
|
27
|
-
"Calculating",
|
|
28
|
-
"Canoodling",
|
|
29
|
-
"Caramelizing",
|
|
30
|
-
"Cascading",
|
|
31
|
-
"Catapulting",
|
|
32
|
-
"Cerebrating",
|
|
33
|
-
"Channeling",
|
|
34
|
-
"Channelling",
|
|
35
|
-
"Choreographing",
|
|
36
|
-
"Churning",
|
|
37
|
-
"Clauding",
|
|
38
|
-
"Coalescing",
|
|
39
|
-
"Cogitating",
|
|
40
|
-
"Combobulating",
|
|
41
|
-
"Composing",
|
|
42
|
-
"Computing",
|
|
43
|
-
"Concocting",
|
|
44
|
-
"Considering",
|
|
45
|
-
"Contemplating",
|
|
46
|
-
"Cooking",
|
|
47
|
-
"Crafting",
|
|
48
|
-
"Creating",
|
|
49
|
-
"Crunching",
|
|
50
|
-
"Crystallizing",
|
|
51
|
-
"Cultivating",
|
|
52
|
-
"Deciphering",
|
|
53
|
-
"Deliberating",
|
|
54
|
-
"Determining",
|
|
55
|
-
"Dilly-dallying",
|
|
56
|
-
"Discombobulating",
|
|
57
|
-
"Doing",
|
|
58
|
-
"Doodling",
|
|
59
|
-
"Drizzling",
|
|
60
|
-
"Ebbing",
|
|
61
|
-
"Effecting",
|
|
62
|
-
"Elucidating",
|
|
63
|
-
"Embellishing",
|
|
64
|
-
"Enchanting",
|
|
65
|
-
"Envisioning",
|
|
66
|
-
"Fermenting",
|
|
67
|
-
"Fiddle-faddling",
|
|
68
|
-
"Finagling",
|
|
69
|
-
"Flambéing",
|
|
70
|
-
"Flibbertigibbeting",
|
|
71
|
-
"Flowing",
|
|
72
|
-
"Flummoxing",
|
|
73
|
-
"Fluttering",
|
|
74
|
-
"Forging",
|
|
75
|
-
"Forming",
|
|
76
|
-
"Frolicking",
|
|
77
|
-
"Frosting",
|
|
78
|
-
"Gallivanting",
|
|
79
|
-
"Galloping",
|
|
80
|
-
"Garnishing",
|
|
81
|
-
"Generating",
|
|
82
|
-
"Gesticulating",
|
|
83
|
-
"Germinating",
|
|
84
|
-
"Gitifying",
|
|
85
|
-
"Grooving",
|
|
86
|
-
"Gusting",
|
|
87
|
-
"Harmonizing",
|
|
88
|
-
"Hashing",
|
|
89
|
-
"Hatching",
|
|
90
|
-
"Herding",
|
|
91
|
-
"Honking",
|
|
92
|
-
"Hullaballooing",
|
|
93
|
-
"Hyperspacing",
|
|
94
|
-
"Ideating",
|
|
95
|
-
"Imagining",
|
|
96
|
-
"Improvising",
|
|
97
|
-
"Incubating",
|
|
98
|
-
"Inferring",
|
|
99
|
-
"Infusing",
|
|
100
|
-
"Ionizing",
|
|
101
|
-
"Jitterbugging",
|
|
102
|
-
"Julienning",
|
|
103
|
-
"Kneading",
|
|
104
|
-
"Leavening",
|
|
105
|
-
"Levitating",
|
|
106
|
-
"Lollygagging",
|
|
107
|
-
"Manifesting",
|
|
108
|
-
"Marinating",
|
|
109
|
-
"Meandering",
|
|
110
|
-
"Metamorphosing",
|
|
111
|
-
"Misting",
|
|
112
|
-
"Moonwalking",
|
|
113
|
-
"Moseying",
|
|
114
|
-
"Mulling",
|
|
115
|
-
"Mustering",
|
|
116
|
-
"Musing",
|
|
117
|
-
"Nebulizing",
|
|
118
|
-
"Nesting",
|
|
119
|
-
"Newspapering",
|
|
120
|
-
"Noodling",
|
|
121
|
-
"Nucleating",
|
|
122
|
-
"Orbiting",
|
|
123
|
-
"Orchestrating",
|
|
124
|
-
"Osmosing",
|
|
125
|
-
"Perambulating",
|
|
126
|
-
"Percolating",
|
|
127
|
-
"Perusing",
|
|
128
|
-
"Philosophising",
|
|
129
|
-
"Photosynthesizing",
|
|
130
|
-
"Pollinating",
|
|
131
|
-
"Pondering",
|
|
132
|
-
"Pontificating",
|
|
133
|
-
"Pouncing",
|
|
134
|
-
"Precipitating",
|
|
135
|
-
"Prestidigitating",
|
|
136
|
-
"Processing",
|
|
137
|
-
"Proofing",
|
|
138
|
-
"Propagating",
|
|
139
|
-
"Puttering",
|
|
140
|
-
"Puzzling",
|
|
141
|
-
"Quantumizing",
|
|
142
|
-
"Razzle-dazzling",
|
|
143
|
-
"Razzmatazzing",
|
|
144
|
-
"Recombobulating",
|
|
145
|
-
"Reticulating",
|
|
146
|
-
"Roosting",
|
|
147
|
-
"Ruminating",
|
|
148
|
-
"Sautéing",
|
|
149
|
-
"Scampering",
|
|
150
|
-
"Schlepping",
|
|
151
|
-
"Scurrying",
|
|
152
|
-
"Seasoning",
|
|
153
|
-
"Shenaniganing",
|
|
154
|
-
"Shimmying",
|
|
155
|
-
"Simmering",
|
|
156
|
-
"Skedaddling",
|
|
157
|
-
"Sketching",
|
|
158
|
-
"Slithering",
|
|
159
|
-
"Smooshing",
|
|
160
|
-
"Sock-hopping",
|
|
161
|
-
"Spelunking",
|
|
162
|
-
"Spinning",
|
|
163
|
-
"Sprouting",
|
|
164
|
-
"Stewing",
|
|
165
|
-
"Sublimating",
|
|
166
|
-
"Swirling",
|
|
167
|
-
"Swooping",
|
|
168
|
-
"Symbioting",
|
|
169
|
-
"Synthesizing",
|
|
170
|
-
"Tempering",
|
|
171
|
-
"Thinking",
|
|
172
|
-
"Thundering",
|
|
173
|
-
"Tinkering",
|
|
174
|
-
"Tomfoolering",
|
|
175
|
-
"Topsy-turvying",
|
|
176
|
-
"Transfiguring",
|
|
177
|
-
"Transmuting",
|
|
178
|
-
"Twisting",
|
|
179
|
-
"Undulating",
|
|
180
|
-
"Unfurling",
|
|
181
|
-
"Unravelling",
|
|
182
|
-
"Vibing",
|
|
183
|
-
"Waddling",
|
|
184
|
-
"Wandering",
|
|
185
|
-
"Warping",
|
|
186
|
-
"Whatchamacalliting",
|
|
187
|
-
"Whirlpooling",
|
|
188
|
-
"Whirring",
|
|
189
|
-
"Whisking",
|
|
190
|
-
"Wibbling",
|
|
191
|
-
"Working",
|
|
192
|
-
"Wrangling",
|
|
193
|
-
"Zesting",
|
|
194
|
-
"Zigzagging",
|
|
195
|
-
];
|