@promptctl/cc-candybar 1.37.0 → 1.39.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/dist/index.mjs +96 -93
- package/package.json +5 -5
- package/schema/cc-candybar.schema.json +124 -0
- package/src/click/wire.ts +10 -1
- package/src/config/action.ts +110 -1
- package/src/config/default-dsl-config.ts +77 -246
- package/src/config/disclosure.ts +54 -0
- package/src/config/edit-chrome.ts +15 -1
- package/src/config/loader/actions.ts +138 -61
- package/src/config/loader/cross-ref.ts +48 -10
- package/src/config/loader/globals.ts +40 -0
- package/src/config/loader/menu-synth.ts +69 -18
- package/src/config/settings-menu.ts +339 -16
- package/src/daemon/verbs/config-validators.ts +14 -11
- package/src/daemon/verbs/index.ts +39 -3
- package/src/daemon/verbs/state-validators.ts +26 -8
- package/src/help-text.ts +6 -3
- package/src/install/index.ts +2 -2
- package/src/render/action.ts +210 -54
- package/src/render/menu.ts +75 -21
- package/src/render/picker.ts +39 -35
- package/src/themes/policy.ts +21 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promptctl/cc-candybar",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.39.0",
|
|
4
4
|
"description": "Statusline renderer for Claude Code — a JSON5-configurable DSL with daemon-cached data sources, byte-clean palette-aware composition, and OSC8 click verbs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
@@ -91,9 +91,9 @@
|
|
|
91
91
|
"mobx": "^6.15.0"
|
|
92
92
|
},
|
|
93
93
|
"optionalDependencies": {
|
|
94
|
-
"@promptctl/cc-candybar-darwin-arm64": "1.
|
|
95
|
-
"@promptctl/cc-candybar-darwin-x64": "1.
|
|
96
|
-
"@promptctl/cc-candybar-linux-x64": "1.
|
|
97
|
-
"@promptctl/cc-candybar-linux-arm64": "1.
|
|
94
|
+
"@promptctl/cc-candybar-darwin-arm64": "1.39.0",
|
|
95
|
+
"@promptctl/cc-candybar-darwin-x64": "1.39.0",
|
|
96
|
+
"@promptctl/cc-candybar-linux-x64": "1.39.0",
|
|
97
|
+
"@promptctl/cc-candybar-linux-arm64": "1.39.0"
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -1405,6 +1405,130 @@
|
|
|
1405
1405
|
],
|
|
1406
1406
|
"additionalProperties": false
|
|
1407
1407
|
},
|
|
1408
|
+
{
|
|
1409
|
+
"type": "object",
|
|
1410
|
+
"properties": {
|
|
1411
|
+
"set": {
|
|
1412
|
+
"type": "string"
|
|
1413
|
+
},
|
|
1414
|
+
"persist": {
|
|
1415
|
+
"type": "string"
|
|
1416
|
+
},
|
|
1417
|
+
"persistWhen": {
|
|
1418
|
+
"type": "string"
|
|
1419
|
+
},
|
|
1420
|
+
"to": {
|
|
1421
|
+
"type": "string"
|
|
1422
|
+
}
|
|
1423
|
+
},
|
|
1424
|
+
"required": [
|
|
1425
|
+
"set",
|
|
1426
|
+
"persist",
|
|
1427
|
+
"persistWhen",
|
|
1428
|
+
"to"
|
|
1429
|
+
],
|
|
1430
|
+
"additionalProperties": false
|
|
1431
|
+
},
|
|
1432
|
+
{
|
|
1433
|
+
"type": "object",
|
|
1434
|
+
"properties": {
|
|
1435
|
+
"set": {
|
|
1436
|
+
"type": "string"
|
|
1437
|
+
},
|
|
1438
|
+
"persist": {
|
|
1439
|
+
"type": "string"
|
|
1440
|
+
},
|
|
1441
|
+
"persistWhen": {
|
|
1442
|
+
"type": "string"
|
|
1443
|
+
},
|
|
1444
|
+
"from": {
|
|
1445
|
+
"anyOf": [
|
|
1446
|
+
{
|
|
1447
|
+
"type": "string",
|
|
1448
|
+
"minLength": 1
|
|
1449
|
+
},
|
|
1450
|
+
{
|
|
1451
|
+
"type": "array",
|
|
1452
|
+
"items": {
|
|
1453
|
+
"type": "string",
|
|
1454
|
+
"minLength": 1
|
|
1455
|
+
},
|
|
1456
|
+
"minItems": 1,
|
|
1457
|
+
"uniqueItems": true
|
|
1458
|
+
}
|
|
1459
|
+
]
|
|
1460
|
+
}
|
|
1461
|
+
},
|
|
1462
|
+
"required": [
|
|
1463
|
+
"set",
|
|
1464
|
+
"persist",
|
|
1465
|
+
"persistWhen",
|
|
1466
|
+
"from"
|
|
1467
|
+
],
|
|
1468
|
+
"additionalProperties": false
|
|
1469
|
+
},
|
|
1470
|
+
{
|
|
1471
|
+
"type": "object",
|
|
1472
|
+
"properties": {
|
|
1473
|
+
"set": {
|
|
1474
|
+
"type": "string"
|
|
1475
|
+
},
|
|
1476
|
+
"persist": {
|
|
1477
|
+
"type": "string"
|
|
1478
|
+
},
|
|
1479
|
+
"persistWhen": {
|
|
1480
|
+
"type": "string"
|
|
1481
|
+
},
|
|
1482
|
+
"min": {
|
|
1483
|
+
"type": "integer"
|
|
1484
|
+
},
|
|
1485
|
+
"max": {
|
|
1486
|
+
"type": "integer"
|
|
1487
|
+
},
|
|
1488
|
+
"by": {
|
|
1489
|
+
"type": "integer"
|
|
1490
|
+
}
|
|
1491
|
+
},
|
|
1492
|
+
"required": [
|
|
1493
|
+
"set",
|
|
1494
|
+
"persist",
|
|
1495
|
+
"persistWhen",
|
|
1496
|
+
"min",
|
|
1497
|
+
"max",
|
|
1498
|
+
"by"
|
|
1499
|
+
],
|
|
1500
|
+
"additionalProperties": false
|
|
1501
|
+
},
|
|
1502
|
+
{
|
|
1503
|
+
"type": "object",
|
|
1504
|
+
"properties": {
|
|
1505
|
+
"set": {
|
|
1506
|
+
"type": "string"
|
|
1507
|
+
},
|
|
1508
|
+
"persist": {
|
|
1509
|
+
"type": "string"
|
|
1510
|
+
},
|
|
1511
|
+
"persistWhen": {
|
|
1512
|
+
"type": "string"
|
|
1513
|
+
},
|
|
1514
|
+
"cycle": {
|
|
1515
|
+
"type": "array",
|
|
1516
|
+
"items": {
|
|
1517
|
+
"type": "string",
|
|
1518
|
+
"minLength": 1
|
|
1519
|
+
},
|
|
1520
|
+
"minItems": 2,
|
|
1521
|
+
"uniqueItems": true
|
|
1522
|
+
}
|
|
1523
|
+
},
|
|
1524
|
+
"required": [
|
|
1525
|
+
"set",
|
|
1526
|
+
"persist",
|
|
1527
|
+
"persistWhen",
|
|
1528
|
+
"cycle"
|
|
1529
|
+
],
|
|
1530
|
+
"additionalProperties": false
|
|
1531
|
+
},
|
|
1408
1532
|
{
|
|
1409
1533
|
"type": "object",
|
|
1410
1534
|
"properties": {
|
package/src/click/wire.ts
CHANGED
|
@@ -57,10 +57,19 @@ export const VERB_LOAD_CONFIG = "load-config";
|
|
|
57
57
|
// (candybar-config-engine-71o.2). Args: `[sessionId, key, value]` — the
|
|
58
58
|
// sessionId is carried only for click.error surfacing, exactly like
|
|
59
59
|
// set-state; the write itself is daemon-global, not session-scoped.
|
|
60
|
+
// A durable write takes an OPTIONAL trailing segment: the SessionState key to
|
|
61
|
+
// RELEASE once the write has succeeded. A dual-destination control
|
|
62
|
+
// (candybar-settings-ui-aok.3) commits "make this the durable default AND stop
|
|
63
|
+
// overriding it in this session" — one intent, whose session half must not
|
|
64
|
+
// happen if the durable half failed. Carried as one more segment on the write
|
|
65
|
+
// itself rather than as a second effect beside it, because `dispatch` runs
|
|
66
|
+
// every effect in a click by design; a pair would let a rejected write still
|
|
67
|
+
// wipe the user's pick. Args: `[sessionId, key, value, releaseKey?]`.
|
|
60
68
|
export const VERB_SET_CONFIG = "set-config";
|
|
61
69
|
// [LAW:types-are-the-program] A RELATIVE nudge to a bounded config-overrides
|
|
62
70
|
// key (e.g. a padding stepper) — the config twin of step-state. Args:
|
|
63
|
-
// `[sessionId, key, by]
|
|
71
|
+
// `[sessionId, key, by, releaseKey?]` — the same optional release segment
|
|
72
|
+
// set-config takes, for the same reason.
|
|
64
73
|
export const VERB_STEP_CONFIG = "step-config";
|
|
65
74
|
// [LAW:one-source-of-truth] The gated undo for `persist`: clears one
|
|
66
75
|
// config-overrides key, restoring the user-file/bundled-default value on the
|
package/src/config/action.ts
CHANGED
|
@@ -185,7 +185,116 @@ export type ActionDecl =
|
|
|
185
185
|
| { readonly open: string }
|
|
186
186
|
| { readonly reset: string }
|
|
187
187
|
| { readonly undo: true }
|
|
188
|
-
| { readonly redo: true }
|
|
188
|
+
| { readonly redo: true }
|
|
189
|
+
| DualActionDecl;
|
|
190
|
+
|
|
191
|
+
// [LAW:one-source-of-truth] The key whose PRESENCE makes an action
|
|
192
|
+
// dual-destination, and whose VALUE names the SessionState key that chooses
|
|
193
|
+
// the destination at click time. Spelled once: the loader dispatches on it,
|
|
194
|
+
// the compiler reads it, and the settings menu's synthesis writes it.
|
|
195
|
+
export const PERSIST_WHEN = "persistWhen";
|
|
196
|
+
|
|
197
|
+
// [LAW:types-are-the-program] ONE setting, ONE control, TWO stores
|
|
198
|
+
// (candybar-settings-ui-aok.3). Before this arm, a setting with both a
|
|
199
|
+
// session and a durable half cost the author two declarations and the reader
|
|
200
|
+
// two controls — `{{ menu "applyTheme" }}` beside `📌{{ menu
|
|
201
|
+
// "applyThemeForever" }}` — a second representation of one setting that had
|
|
202
|
+
// to be reconciled at every glance.
|
|
203
|
+
//
|
|
204
|
+
// A dual decl carries BOTH destination keys (`set` = the SessionState key,
|
|
205
|
+
// `persist` = the config-overrides key — they differ where history made them
|
|
206
|
+
// differ, e.g. session "theme" over globals field "palette") and ONE value
|
|
207
|
+
// source shared by both. `persistWhen` names the session key whose boolean
|
|
208
|
+
// value SELECTS the destination; the value written is identical either way,
|
|
209
|
+
// so the destination is the only thing that varies, and it varies as DATA
|
|
210
|
+
// [LAW:dataflow-not-control-flow].
|
|
211
|
+
//
|
|
212
|
+
// [LAW:single-enforcer] This adds NO gate surface. `actionDestinations`
|
|
213
|
+
// below explodes one dual decl into exactly the two single-destination decls
|
|
214
|
+
// it is equivalent to, and both validator derivations (state-validators.ts,
|
|
215
|
+
// config-validators.ts) fold over that explosion — so the writable (key,
|
|
216
|
+
// spec) pairs stay statically enumerable from the declarations, derived by
|
|
217
|
+
// the same code that has always derived them.
|
|
218
|
+
//
|
|
219
|
+
// The `int` / `removeSegment` / `insertSegment*` sources are deliberately
|
|
220
|
+
// absent: `int` is a UI-only page cursor with no durable meaning, and the
|
|
221
|
+
// structural edits are persist-only by design (see the arms above), so
|
|
222
|
+
// neither has two destinations to choose between.
|
|
223
|
+
export type DualActionDecl =
|
|
224
|
+
| {
|
|
225
|
+
readonly set: string;
|
|
226
|
+
readonly persist: string;
|
|
227
|
+
readonly persistWhen: string;
|
|
228
|
+
readonly to: string;
|
|
229
|
+
}
|
|
230
|
+
| {
|
|
231
|
+
readonly set: string;
|
|
232
|
+
readonly persist: string;
|
|
233
|
+
readonly persistWhen: string;
|
|
234
|
+
readonly from: OptionDomain;
|
|
235
|
+
}
|
|
236
|
+
| {
|
|
237
|
+
readonly set: string;
|
|
238
|
+
readonly persist: string;
|
|
239
|
+
readonly persistWhen: string;
|
|
240
|
+
readonly cycle: readonly string[];
|
|
241
|
+
}
|
|
242
|
+
| {
|
|
243
|
+
readonly set: string;
|
|
244
|
+
readonly persist: string;
|
|
245
|
+
readonly persistWhen: string;
|
|
246
|
+
readonly min: number;
|
|
247
|
+
readonly max: number;
|
|
248
|
+
readonly by: number;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// [LAW:parse-dont-validate] The one discriminator for the dual arm, and the
|
|
252
|
+
// reason every `"set" in a` consumer stays correct: a dual decl carries both
|
|
253
|
+
// `set` and `persist`, so a consumer that must treat the two destinations
|
|
254
|
+
// separately asks THIS first (or folds through actionDestinations below), and
|
|
255
|
+
// a consumer that only asks "does this bind a session write" (actionBindsSet)
|
|
256
|
+
// keeps its existing answer with no change at all.
|
|
257
|
+
export function actionIsDual(a: ActionDecl): a is DualActionDecl {
|
|
258
|
+
return PERSIST_WHEN in a;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// [LAW:one-source-of-truth] THE explosion of an action into the
|
|
262
|
+
// single-destination declarations it writes through — `[a]` for every
|
|
263
|
+
// ordinary action, `[session, durable]` for a dual. Every consumer that
|
|
264
|
+
// reasons about DESTINATIONS (both validator derivations) flatMaps through
|
|
265
|
+
// this instead of learning the dual shape, so the gate a dual derives is by
|
|
266
|
+
// construction the union of the gates its two halves would have derived
|
|
267
|
+
// separately — there is no second derivation to keep in agreement.
|
|
268
|
+
export function actionDestinations(a: ActionDecl): readonly ActionDecl[] {
|
|
269
|
+
if (!actionIsDual(a)) return [a];
|
|
270
|
+
// [LAW:types-are-the-program] Written out per value source rather than
|
|
271
|
+
// spread-and-cast: the two halves are then ordinary, fully-typed `set` and
|
|
272
|
+
// `persist` members — the exact declarations an author would have written —
|
|
273
|
+
// and adding a value source to DualActionDecl fails to compile here until
|
|
274
|
+
// its explosion is stated.
|
|
275
|
+
if ("to" in a) {
|
|
276
|
+
return [
|
|
277
|
+
{ set: a.set, to: a.to },
|
|
278
|
+
{ persist: a.persist, to: a.to },
|
|
279
|
+
];
|
|
280
|
+
}
|
|
281
|
+
if ("from" in a) {
|
|
282
|
+
return [
|
|
283
|
+
{ set: a.set, from: a.from },
|
|
284
|
+
{ persist: a.persist, from: a.from },
|
|
285
|
+
];
|
|
286
|
+
}
|
|
287
|
+
if ("cycle" in a) {
|
|
288
|
+
return [
|
|
289
|
+
{ set: a.set, cycle: a.cycle },
|
|
290
|
+
{ persist: a.persist, cycle: a.cycle },
|
|
291
|
+
];
|
|
292
|
+
}
|
|
293
|
+
return [
|
|
294
|
+
{ set: a.set, min: a.min, max: a.max, by: a.by },
|
|
295
|
+
{ persist: a.persist, min: a.min, max: a.max, by: a.by },
|
|
296
|
+
];
|
|
297
|
+
}
|
|
189
298
|
|
|
190
299
|
// [LAW:dataflow-not-control-flow] Does this action write a SessionState key? A
|
|
191
300
|
// `set` action composes a set-state click URL whose first segment is session.id;
|