dsh-claude-desktop-theme 0.4.3 → 0.4.5
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 +95 -140
- package/lib/client.js +9036 -812
- package/lib/index.js +56 -19
- package/lib/types/client/compat/browser-header.d.ts +1 -2
- package/lib/types/client/compat/frame.d.ts +29 -0
- package/lib/types/client/compat/hero-greeting.d.ts +6 -0
- package/lib/types/client/compat/host-dom.d.ts +8 -0
- package/lib/types/client/compat/mutation-scope.d.ts +43 -0
- package/lib/types/client/compat/pane-chrome.d.ts +2 -0
- package/lib/types/client/compat/permission-confirmation.d.ts +5 -0
- package/lib/types/client/compat/permission-menu.d.ts +4 -1
- package/lib/types/client/compat/pet-anchor.d.ts +5 -1
- package/lib/types/client/compat/sidebar-search.d.ts +18 -0
- package/lib/types/client/compat/view-switch.d.ts +1 -1
- package/lib/types/client/contracts/ports.d.ts +2 -0
- package/lib/types/client/features/composer-pet/BlankPet.d.ts +4 -1
- package/lib/types/client/features/composer-pet/ClaudePet.d.ts +7 -0
- package/lib/types/client/features/composer-pet/claude-frames.d.ts +12 -0
- package/lib/types/client/features/composer-pet/claude-motion.d.ts +3 -0
- package/lib/types/client/features/conversation/header-actions/HeaderActionButton.d.ts +2 -2
- package/lib/types/client/features/conversation/header-actions/entries.d.ts +11 -15
- package/lib/types/client/features/conversation/view-switch-icons.d.ts +2 -2
- package/lib/types/client/features/model-controls/EffortPanel.d.ts +2 -1
- package/lib/types/client/features/model-controls/ModelControls.d.ts +11 -1
- package/lib/types/client/features/model-controls/model-icon-data.d.ts +31 -0
- package/lib/types/client/features/model-controls/model-icon-match.d.ts +20 -0
- package/lib/types/client/features/model-controls/model-icons.d.ts +13 -0
- package/lib/types/client/features/model-controls/popup.d.ts +20 -0
- package/lib/types/client/features/model-controls/selection.d.ts +2 -0
- package/lib/types/client/features/new-session/ripples.d.ts +2 -2
- package/lib/types/client/features/settings/ChoiceMenu.d.ts +15 -0
- package/lib/types/client/features/settings/fields.d.ts +18 -0
- package/lib/types/client/features/settings/locales.d.ts +16 -1
- package/lib/types/client/features/statistics/source.d.ts +2 -1
- package/lib/types/host/index.d.ts +30 -0
- package/lib/types/shared/config.d.ts +11 -2
- package/package.json +2 -1
package/lib/index.js
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
|
|
4
4
|
// src/shared/config.ts
|
|
5
|
+
var DEFAULT_PERSONALIZATION = Object.freeze({
|
|
6
|
+
petStyle: "whale",
|
|
7
|
+
greetingStyle: "explore",
|
|
8
|
+
greetingName: ""
|
|
9
|
+
});
|
|
5
10
|
var DEFAULT_FEATURES = Object.freeze({
|
|
6
11
|
shell: true,
|
|
7
12
|
sidebar: true,
|
|
@@ -11,7 +16,8 @@ var DEFAULT_FEATURES = Object.freeze({
|
|
|
11
16
|
statistics: false,
|
|
12
17
|
"composer-pet": true,
|
|
13
18
|
"composer-stats": false,
|
|
14
|
-
"context-panel": true
|
|
19
|
+
"context-panel": true,
|
|
20
|
+
"hero-ripples": true
|
|
15
21
|
});
|
|
16
22
|
var DEFAULT_APPEARANCE = Object.freeze({
|
|
17
23
|
canvas: "",
|
|
@@ -26,7 +32,9 @@ var DEFAULT_VIEW = Object.freeze({
|
|
|
26
32
|
showEmptyGroups: false,
|
|
27
33
|
groupByStatus: true,
|
|
28
34
|
showHeaderSubagents: false,
|
|
29
|
-
showHeaderTeam: false
|
|
35
|
+
showHeaderTeam: false,
|
|
36
|
+
showSidebarBrand: false,
|
|
37
|
+
showModelIcons: true
|
|
30
38
|
});
|
|
31
39
|
var FONT_NAME_MAX_LENGTH = 64;
|
|
32
40
|
|
|
@@ -431,12 +439,14 @@ var UsageAggregator = class {
|
|
|
431
439
|
ctx;
|
|
432
440
|
warn;
|
|
433
441
|
values = /* @__PURE__ */ new Map();
|
|
434
|
-
queued =
|
|
442
|
+
queued = /* @__PURE__ */ new Map();
|
|
435
443
|
folding = /* @__PURE__ */ new Set();
|
|
436
444
|
failures = /* @__PURE__ */ new Map();
|
|
437
445
|
running = 0;
|
|
438
446
|
refreshRun = null;
|
|
439
447
|
snapshot = null;
|
|
448
|
+
dirty = true;
|
|
449
|
+
listed = /* @__PURE__ */ new Set();
|
|
440
450
|
disposed = false;
|
|
441
451
|
constructor(ctx, warn) {
|
|
442
452
|
this.ctx = ctx;
|
|
@@ -444,7 +454,15 @@ var UsageAggregator = class {
|
|
|
444
454
|
}
|
|
445
455
|
/** The most recent snapshot; an empty one before the first refresh. */
|
|
446
456
|
get current() {
|
|
447
|
-
|
|
457
|
+
if (this.snapshot === null || this.dirty) {
|
|
458
|
+
this.snapshot = aggregateUsage(this.values.values(), {
|
|
459
|
+
now: Date.now(),
|
|
460
|
+
pending: this.queued.size + this.running,
|
|
461
|
+
missed: this.failures.size
|
|
462
|
+
});
|
|
463
|
+
this.dirty = false;
|
|
464
|
+
}
|
|
465
|
+
return this.snapshot;
|
|
448
466
|
}
|
|
449
467
|
/**
|
|
450
468
|
* Bring the snapshot up to date.
|
|
@@ -456,6 +474,7 @@ var UsageAggregator = class {
|
|
|
456
474
|
* @returns the snapshot as of this pass.
|
|
457
475
|
*/
|
|
458
476
|
refresh() {
|
|
477
|
+
if (this.disposed) return Promise.resolve(this.current);
|
|
459
478
|
const running = this.refreshRun;
|
|
460
479
|
if (running !== null) return running;
|
|
461
480
|
const run = this.pass().finally(() => {
|
|
@@ -467,24 +486,34 @@ var UsageAggregator = class {
|
|
|
467
486
|
/** Stop folding; in-flight reads settle but no longer publish. */
|
|
468
487
|
dispose() {
|
|
469
488
|
this.disposed = true;
|
|
470
|
-
this.queued.
|
|
489
|
+
this.queued.clear();
|
|
490
|
+
this.values.clear();
|
|
491
|
+
this.failures.clear();
|
|
492
|
+
this.listed.clear();
|
|
493
|
+
this.snapshot = null;
|
|
471
494
|
}
|
|
472
495
|
async pass() {
|
|
473
496
|
try {
|
|
474
497
|
const candidates = await this.list();
|
|
498
|
+
if (this.disposed) return this.current;
|
|
475
499
|
const listed = new Set(candidates.map((candidate) => candidate.header.id));
|
|
500
|
+
this.listed = listed;
|
|
476
501
|
for (const id of [...this.values.keys()]) if (!listed.has(id)) this.values.delete(id);
|
|
477
502
|
for (const id of [...this.failures.keys()]) if (!listed.has(id)) this.failures.delete(id);
|
|
503
|
+
for (const id of this.queued.keys()) if (!listed.has(id)) this.queued.delete(id);
|
|
478
504
|
for (const candidate of candidates) {
|
|
479
505
|
if (this.disposed) break;
|
|
480
506
|
const value = this.readSafely(candidate);
|
|
481
507
|
if (value === void 0) this.enqueue(candidate);
|
|
482
|
-
else
|
|
508
|
+
else {
|
|
509
|
+
this.queued.delete(candidate.header.id);
|
|
510
|
+
this.values.set(candidate.header.id, value);
|
|
511
|
+
}
|
|
483
512
|
}
|
|
484
513
|
} catch (error) {
|
|
485
514
|
this.warn("session listing failed; the card keeps the last snapshot", error);
|
|
486
515
|
}
|
|
487
|
-
this.
|
|
516
|
+
this.invalidate();
|
|
488
517
|
return this.current;
|
|
489
518
|
}
|
|
490
519
|
/** Every stored session the card counts, newest first. */
|
|
@@ -530,24 +559,25 @@ var UsageAggregator = class {
|
|
|
530
559
|
/** Queue one cold fold unless it is already queued, running, or cooling down. */
|
|
531
560
|
enqueue(candidate) {
|
|
532
561
|
const id = candidate.header.id;
|
|
533
|
-
if (this.folding.has(id) || this.queued.
|
|
562
|
+
if (this.disposed || this.folding.has(id) || this.queued.has(id)) return;
|
|
534
563
|
const failedAt = this.failures.get(id);
|
|
535
564
|
if (failedAt !== void 0 && Date.now() - failedAt < RETRY_COOLDOWN_MS) return;
|
|
536
|
-
this.queued.
|
|
565
|
+
this.queued.set(id, candidate);
|
|
537
566
|
this.pump();
|
|
538
567
|
}
|
|
539
568
|
/** Keep at most {@link FOLD_CONCURRENCY} folds in flight. */
|
|
540
569
|
pump() {
|
|
541
570
|
while (!this.disposed && this.running < FOLD_CONCURRENCY) {
|
|
542
|
-
const candidate = this.queued.
|
|
571
|
+
const candidate = this.queued.values().next().value;
|
|
543
572
|
if (candidate === void 0) return;
|
|
544
573
|
const id = candidate.header.id;
|
|
574
|
+
this.queued.delete(id);
|
|
545
575
|
this.folding.add(id);
|
|
546
576
|
this.running += 1;
|
|
547
577
|
void this.fold(candidate).finally(() => {
|
|
548
578
|
this.folding.delete(id);
|
|
549
579
|
this.running -= 1;
|
|
550
|
-
this.
|
|
580
|
+
this.invalidate();
|
|
551
581
|
this.pump();
|
|
552
582
|
});
|
|
553
583
|
}
|
|
@@ -560,7 +590,9 @@ var UsageAggregator = class {
|
|
|
560
590
|
let handle;
|
|
561
591
|
try {
|
|
562
592
|
handle = await persistence.open(candidate.header.id, "read");
|
|
593
|
+
if (this.disposed || !this.listed.has(candidate.header.id)) return;
|
|
563
594
|
const { events } = await handle.read(0);
|
|
595
|
+
if (this.disposed || !this.listed.has(candidate.header.id)) return;
|
|
564
596
|
const block = cache.coldSnapshot(handle.header, handle.inheritedEventCount, events);
|
|
565
597
|
const value = block.values[USAGE_KEY];
|
|
566
598
|
if (this.disposed) return;
|
|
@@ -571,6 +603,7 @@ var UsageAggregator = class {
|
|
|
571
603
|
this.values.set(candidate.header.id, value);
|
|
572
604
|
this.failures.delete(candidate.header.id);
|
|
573
605
|
} catch (error) {
|
|
606
|
+
if (this.disposed || !this.listed.has(candidate.header.id)) return;
|
|
574
607
|
this.failures.set(candidate.header.id, Date.now());
|
|
575
608
|
this.warn(`fold failed for session ${candidate.header.id}`, error);
|
|
576
609
|
} finally {
|
|
@@ -582,14 +615,10 @@ var UsageAggregator = class {
|
|
|
582
615
|
}
|
|
583
616
|
}
|
|
584
617
|
}
|
|
585
|
-
/**
|
|
586
|
-
|
|
618
|
+
/** Fold completions invalidate totals; only a route read pays for aggregation. */
|
|
619
|
+
invalidate() {
|
|
587
620
|
if (this.disposed) return;
|
|
588
|
-
this.
|
|
589
|
-
now: Date.now(),
|
|
590
|
-
pending: this.queued.length + this.running,
|
|
591
|
-
missed: this.failures.size
|
|
592
|
-
});
|
|
621
|
+
this.dirty = true;
|
|
593
622
|
}
|
|
594
623
|
};
|
|
595
624
|
function mountStatistics(ctx, isEnabled) {
|
|
@@ -995,7 +1024,8 @@ var Config = z.object({
|
|
|
995
1024
|
statistics: z.boolean().default(DEFAULT_FEATURES.statistics),
|
|
996
1025
|
"composer-pet": z.boolean().default(DEFAULT_FEATURES["composer-pet"]),
|
|
997
1026
|
"composer-stats": z.boolean().default(DEFAULT_FEATURES["composer-stats"]),
|
|
998
|
-
"context-panel": z.boolean().default(DEFAULT_FEATURES["context-panel"])
|
|
1027
|
+
"context-panel": z.boolean().default(DEFAULT_FEATURES["context-panel"]),
|
|
1028
|
+
"hero-ripples": z.boolean().default(DEFAULT_FEATURES["hero-ripples"])
|
|
999
1029
|
}).default({ ...DEFAULT_FEATURES }).description("\u6309\u6A21\u5757\u542F\u7528").volatile(),
|
|
1000
1030
|
/* One volatile node per section, exactly like `features`: Cordis rejects a
|
|
1001
1031
|
volatile field nested inside another volatile field ("volatile fields
|
|
@@ -1010,7 +1040,14 @@ var Config = z.object({
|
|
|
1010
1040
|
uiCjk: z.string().default(DEFAULT_FONTS.uiCjk).description("\u754C\u9762\u4E2D\u6587\u5B57\u4F53\u540D\uFF08\u7559\u7A7A\u7528\u7CFB\u7EDF\u6808\uFF09").pattern(FONT_NAME),
|
|
1011
1041
|
code: z.string().default(DEFAULT_FONTS.code).description("\u4EE3\u7801\u4E0E\u7B49\u5BBD\u5B57\u4F53\u540D\uFF08\u7559\u7A7A\u7528\u7CFB\u7EDF\u6808\uFF09").pattern(FONT_NAME)
|
|
1012
1042
|
}).default({ ...DEFAULT_FONTS }).description("\u5B57\u4F53").volatile(),
|
|
1043
|
+
personalization: z.object({
|
|
1044
|
+
petStyle: z.union(["whale", "claude"]).default(DEFAULT_PERSONALIZATION.petStyle).description("\u8F93\u5165\u6846\u5BA0\u7269\u6837\u5F0F"),
|
|
1045
|
+
greetingStyle: z.union(["explore", "claude"]).default(DEFAULT_PERSONALIZATION.greetingStyle).description("\u9996\u9875\u95EE\u5019\u8BED\u4E0E\u56FE\u6807\u6837\u5F0F"),
|
|
1046
|
+
greetingName: z.string().default("").pattern(/^.{0,64}$/u).description("\u95EE\u5019\u8BED\u4E2D\u7684\u79F0\u547C\uFF08\u53EF\u7559\u7A7A\uFF09")
|
|
1047
|
+
}).default({ ...DEFAULT_PERSONALIZATION }).description("\u4E2A\u6027\u5316").volatile(),
|
|
1013
1048
|
view: z.object({
|
|
1049
|
+
showModelIcons: z.boolean().default(DEFAULT_VIEW.showModelIcons).description("\u663E\u793A\u6A21\u578B\u9009\u5355\u4E2D\u7684\u524D\u7F6E\u56FE\u6807\uFF08\u9ED8\u8BA4\u5F00\u542F\uFF09"),
|
|
1050
|
+
showSidebarBrand: z.boolean().default(DEFAULT_VIEW.showSidebarBrand).description("\u663E\u793A\u4FA7\u680F DeepSeek Harness \u54C1\u724C\u6761\u76EE\uFF08\u9ED8\u8BA4\u5173\u95ED\uFF09"),
|
|
1014
1051
|
showHeaderSubagents: z.boolean().default(DEFAULT_VIEW.showHeaderSubagents).description("\u663E\u793A\u9876\u680F\u5B50\u4EE3\u7406\u5165\u53E3\uFF08\u4EC5\u63A7\u5236\u5165\u53E3\u663E\u793A\uFF09"),
|
|
1015
1052
|
showHeaderTeam: z.boolean().default(DEFAULT_VIEW.showHeaderTeam).description("\u663E\u793A\u9876\u680F\u56E2\u961F\u5165\u53E3\uFF08\u4EC5\u63A7\u5236\u5165\u53E3\u663E\u793A\uFF09"),
|
|
1016
1053
|
groupByStatus: z.boolean().default(DEFAULT_VIEW.groupByStatus).description("\u6309\u4F1A\u8BDD\u72B6\u6001\u5206\u7EC4\uFF08\u4FDD\u7559\u539F\u751F\u9879\u76EE\u89C6\u56FE\u9009\u9879\uFF09"),
|
|
@@ -2,10 +2,9 @@ import type { Disposer } from '../contracts/ports.ts';
|
|
|
2
2
|
/**
|
|
3
3
|
* The name the browsing region's own title line draws.
|
|
4
4
|
* @param text - the host's word, exactly as it rendered it.
|
|
5
|
-
* @param noHistory - whether the plugin's no-history prompt is on screen.
|
|
6
5
|
* @returns the reference's name, or null to leave the host's own word.
|
|
7
6
|
*/
|
|
8
|
-
export declare function browserHeaderWord(text: string
|
|
7
|
+
export declare function browserHeaderWord(text: string): string | null;
|
|
9
8
|
/**
|
|
10
9
|
* Name the browsing region's separate toolbar.
|
|
11
10
|
*
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coalesce DOM work into one paint frame.
|
|
3
|
+
*
|
|
4
|
+
* A mutation observer delivers one batch per microtask, and several documents
|
|
5
|
+
* (a panel drag, a streaming transcript, a slider writing its own inline
|
|
6
|
+
* style) can produce many batches between two paints. Doing a full geometry
|
|
7
|
+
* pass per batch multiplies the layout reads by the batch count; doing it once
|
|
8
|
+
* per frame is what the screen can actually use.
|
|
9
|
+
*
|
|
10
|
+
* The fallbacks are deliberate: an occluded Electron window throttles animation
|
|
11
|
+
* frames, and a frame without `requestAnimationFrame` at all (some test hosts)
|
|
12
|
+
* must still settle. In both cases the work runs on a timeout instead, so the
|
|
13
|
+
* published values are never left stale.
|
|
14
|
+
*/
|
|
15
|
+
/** One coalescing scheduler; `schedule` runs `task` once before the next paint. */
|
|
16
|
+
export interface FrameScheduler {
|
|
17
|
+
/** Queue the task; repeated calls before it runs collapse into one. */
|
|
18
|
+
schedule(): void;
|
|
19
|
+
/** Drop a queued task without running it. */
|
|
20
|
+
cancel(): void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Build a scheduler over one task.
|
|
24
|
+
*
|
|
25
|
+
* @param task - the read/write pass to run at most once per frame.
|
|
26
|
+
* @param win - the window supplying animation frames; defaults to the global.
|
|
27
|
+
* @returns the scheduler; its task never runs after `cancel`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function frameScheduler(task: () => void, win?: Window | null): FrameScheduler;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PersonalizationConfig } from '../../shared/config.ts';
|
|
2
|
+
import type { Disposer } from '../contracts/ports.ts';
|
|
3
|
+
/** The greeting follows the interface language and never includes an account name. */
|
|
4
|
+
export declare function claudeGreeting(language?: string): string;
|
|
5
|
+
/** Add a reversible presentation beside the native heading without taking its React nodes. */
|
|
6
|
+
export declare function mountHeroGreeting(document: Document, config: PersonalizationConfig): Disposer;
|
|
@@ -42,6 +42,8 @@
|
|
|
42
42
|
* - `packages/client/ui-settings/src/client/SettingsRoot.module.css` (`Dws9Sa_`)
|
|
43
43
|
* - `packages/client/ui-settings-account/src/client/AccountMenu.module.css` (`ZogL4G_`)
|
|
44
44
|
* - `packages/client/ui-primitives/lib/Menu.module.css` (`_4ub78_`, `_ri079_`)
|
|
45
|
+
* - `packages/client/ui-primitives/lib/Modal.module.css` (`_o6lrb_`) and
|
|
46
|
+
* `RiskConfirmation.module.css` (`_cjd8z_`), shared static frontend styles
|
|
45
47
|
* - `packages/client/ui-primitives/lib/Menu.js` (`MenuItemButton`: the icon seat
|
|
46
48
|
* `account-menu.css` scales; its `[role="menuitem"] > span` structure)
|
|
47
49
|
* - `packages/client/ui-chat/src/client/chat/AssistantMarkdown.module.css` (`gKv1-q_`)
|
|
@@ -127,6 +129,7 @@ export declare const HOST: Readonly<{
|
|
|
127
129
|
readonly filesBody: '[data-files-body]';
|
|
128
130
|
readonly filesEntry: '[data-files-entry]';
|
|
129
131
|
readonly sidebarRoot: '._3WPZCG_root';
|
|
132
|
+
readonly sidebarCollapsed: '._3WPZCG_collapsed';
|
|
130
133
|
readonly sidebarLogoRow: '._3WPZCG_logoRow';
|
|
131
134
|
readonly sidebarBrand: '._3WPZCG_brand';
|
|
132
135
|
readonly sidebarBrandName: '._3WPZCG_brandName';
|
|
@@ -326,6 +329,11 @@ export declare const HOST: Readonly<{
|
|
|
326
329
|
children, so the statistics card is appended here and positioned against
|
|
327
330
|
the greeting. */
|
|
328
331
|
readonly heroComposerStack: '.ST7X_W_composerStack';
|
|
332
|
+
/** Shared frontend RiskConfirmation DOM, identical in both desktop builds. */
|
|
333
|
+
readonly riskConfirmation: '._confirmation_cjd8z_1[role="dialog"]';
|
|
334
|
+
readonly riskAcknowledgement: '._acknowledgement_cjd8z_38';
|
|
335
|
+
readonly riskConfirmAction: '._confirmAction_cjd8z_71';
|
|
336
|
+
readonly riskCancelAction: '._modalAction_cjd8z_67';
|
|
329
337
|
/** Every menu surface the `Menu` primitive renders, portal or in place. */
|
|
330
338
|
readonly menu: '[role="menu"]';
|
|
331
339
|
readonly menuItem: '[role="menuitem"]';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a mutation batch can concern one region of the page.
|
|
3
|
+
*
|
|
4
|
+
* Several modules here observe the whole body because the host can move or
|
|
5
|
+
* rebuild their anchor at any time, then pay a geometry pass on every batch.
|
|
6
|
+
* Most batches, though, come from somewhere else — a drag in the right pane, a
|
|
7
|
+
* streaming transcript on another page, another plugin writing its own markup.
|
|
8
|
+
* This predicate lets a module skip those batches without narrowing what it
|
|
9
|
+
* observes, so an anchor that is replaced still reaches it.
|
|
10
|
+
*
|
|
11
|
+
* The answer is deliberately conservative: a region that is missing, detached
|
|
12
|
+
* or cannot answer `contains` makes every batch relevant, so a module that
|
|
13
|
+
* cannot yet measure is never starved of the mutation that would let it.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Whether any record in a batch can move something inside `region`.
|
|
17
|
+
*
|
|
18
|
+
* `region` is the element the module measures — the composer, the scroller,
|
|
19
|
+
* the conversation root. A change inside it, on it, or on any of its ancestors
|
|
20
|
+
* counts, because those are the writes that can change its box. A `null`
|
|
21
|
+
* region, or one the host has already detached, makes the batch relevant:
|
|
22
|
+
* that is exactly the state in which the module has to look again.
|
|
23
|
+
*
|
|
24
|
+
* @param records - the observer's batch.
|
|
25
|
+
* @param region - the element being measured, or null while it is unknown.
|
|
26
|
+
* @returns true when the batch is worth a pass.
|
|
27
|
+
*/
|
|
28
|
+
export declare function recordsTouch(records: readonly MutationRecord[], region: Element | null): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Whether a batch inserted a subtree the selector names.
|
|
31
|
+
*
|
|
32
|
+
* For modules that watch the whole body only because their anchor can be
|
|
33
|
+
* replaced: an insertion that matches the selector is the one structural event
|
|
34
|
+
* worth a pass, and it costs one `matches`/`querySelector` per inserted element
|
|
35
|
+
* rather than a scan of the document. The predicate is also conservative: a
|
|
36
|
+
* node from another realm, or one without the selector helpers, counts as a
|
|
37
|
+
* match.
|
|
38
|
+
*
|
|
39
|
+
* @param records - the observer's batch.
|
|
40
|
+
* @param selector - the marker whose arrival matters.
|
|
41
|
+
* @returns true when an inserted element is, or contains, a match.
|
|
42
|
+
*/
|
|
43
|
+
export declare function recordsIntroduce(records: readonly MutationRecord[], selector: string): boolean;
|
|
@@ -7,6 +7,7 @@ export interface PaneChromeOptions {
|
|
|
7
7
|
readonly onNew: () => void;
|
|
8
8
|
readonly onSelect: (id: string) => void;
|
|
9
9
|
readonly onClose: (id: string) => void;
|
|
10
|
+
readonly onCloseGroup?: () => void;
|
|
10
11
|
readonly closeTabs: readonly string[];
|
|
11
12
|
readonly terminals: readonly {
|
|
12
13
|
id: string;
|
|
@@ -16,6 +17,7 @@ export interface PaneChromeOptions {
|
|
|
16
17
|
readonly files: readonly {
|
|
17
18
|
id: string;
|
|
18
19
|
title: string;
|
|
20
|
+
path: string;
|
|
19
21
|
selected: boolean;
|
|
20
22
|
}[];
|
|
21
23
|
readonly panel: HTMLElement;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Disposer } from '../contracts/ports.ts';
|
|
2
|
+
/** Remove the redundant acknowledgement step from permission confirmations.
|
|
3
|
+
* The native handler still updates React; only the user can press Enable.
|
|
4
|
+
* Other RiskConfirmation callers retain their acknowledgement controls. */
|
|
5
|
+
export declare function mountPermissionConfirmation(document: Document, report: (error: unknown) => void): Disposer;
|
|
@@ -36,6 +36,9 @@ export interface PermissionCopy {
|
|
|
36
36
|
* @returns Chinese copy for a Chinese document, English otherwise.
|
|
37
37
|
*/
|
|
38
38
|
export declare function permissionCopy(document: Document): PermissionCopy;
|
|
39
|
+
/** Short summaries of DSH's four built-in Agent presets. */
|
|
40
|
+
export declare function agentPresetCopy(document: Document): PermissionCopy;
|
|
41
|
+
export declare function mountAgentPresetMenu(document: Document, report: (error: unknown) => void): Disposer;
|
|
39
42
|
/**
|
|
40
43
|
* The permission picker's card, drawn the way the reference draws it.
|
|
41
44
|
*
|
|
@@ -54,7 +57,7 @@ export declare function permissionCopy(document: Document): PermissionCopy;
|
|
|
54
57
|
* `permissionCopy` above. It is kept in one table per document language, so a
|
|
55
58
|
* wording change is one edit in one place.
|
|
56
59
|
*
|
|
57
|
-
* Three facts decide how the rows are reached, and each is worth stating:
|
|
60
|
+
* Three facts decide how the permission rows are reached, and each is worth stating:
|
|
58
61
|
*
|
|
59
62
|
* - **A row is recognised by its name.** `Menu` rows carry no identity of their
|
|
60
63
|
* own — no id, no data attribute, and the preset's own glyph is a thing this
|
|
@@ -27,4 +27,8 @@ export declare const PET_INSET = 12;
|
|
|
27
27
|
* selects new sessions; hidden, missing or unlaid-out cards publish null.
|
|
28
28
|
* @returns position source whose dispose releases all listeners and observers.
|
|
29
29
|
*/
|
|
30
|
-
export declare function createPetAnchor(document: Document, report: (error: unknown) => void
|
|
30
|
+
export declare function createPetAnchor(document: Document, report: (error: unknown) => void, box?: {
|
|
31
|
+
readonly width: number;
|
|
32
|
+
readonly height: number;
|
|
33
|
+
readonly inset?: number;
|
|
34
|
+
}): PetAnchorSource;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Disposer } from '../contracts/ports.ts';
|
|
2
|
+
/** Marks the sidebar column whose field is currently parked above New Session. */
|
|
3
|
+
export declare const SIDEBAR_SEARCH_PLACED_ATTRIBUTE = "data-ccd-sidebar-search-placed";
|
|
4
|
+
/**
|
|
5
|
+
* Park the browsing region's search field above New Session.
|
|
6
|
+
*
|
|
7
|
+
* The field belongs to `ui-workspace`'s `WorkspaceBrowser`, and React removes
|
|
8
|
+
* it from the section header whenever the sidebar collapses to its rail.
|
|
9
|
+
* Moving the React-owned node would make that removal target the wrong parent,
|
|
10
|
+
* so the node stays where React put it and is positioned over the gap that New
|
|
11
|
+
* Session opens above itself. That gap sits after the brand row when the brand
|
|
12
|
+
* is visible and directly below the window strip when it is not.
|
|
13
|
+
*
|
|
14
|
+
* The section header keeps its own row. With the search slot out of flow, its
|
|
15
|
+
* label takes the leading edge and the native View options trigger stays on the
|
|
16
|
+
* trailing edge.
|
|
17
|
+
*/
|
|
18
|
+
export declare function mountSidebarSearch(document: Document, report: (error: unknown) => void): Disposer;
|
|
@@ -21,7 +21,7 @@ export declare const VIEW_GLYPH_ATTRIBUTE = "data-ccd-view-glyph";
|
|
|
21
21
|
/**
|
|
22
22
|
* The parked pill's inset from the sidebar column's right edge, in px. Measured
|
|
23
23
|
* at @2x on the reference: the column's divider sits 16 device px right of the
|
|
24
|
-
* pill's right edge (
|
|
24
|
+
* pill's right edge (DESIGN.md §6.5).
|
|
25
25
|
*/
|
|
26
26
|
export declare const VIEW_DOCK_INSET = 8;
|
|
27
27
|
/** Bundled artwork, one per shipped View; see features/conversation/view-switch-icons.ts. */
|
|
@@ -82,6 +82,8 @@ export interface SidebarRightPort {
|
|
|
82
82
|
}): void;
|
|
83
83
|
/** Focus a tab and the pane holding it; a missing tab is left alone. */
|
|
84
84
|
focus(tabId: string): void;
|
|
85
|
+
/** Close a tab in the on-screen Session through the host's cleanup path. */
|
|
86
|
+
close?(tabId: string): void;
|
|
85
87
|
/**
|
|
86
88
|
* Open tab metadata across adopted Sessions — and, in the shipped face, the
|
|
87
89
|
* snapshot store behind it: the plugin's pane layer re-reads the layout
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
import type { PersonalizationConfig } from '../../../shared/config.ts';
|
|
2
3
|
import type { PetAnchor } from '../../compat/pet-anchor.ts';
|
|
3
4
|
/** Business face the frame overlay injects: the measured new-session corner. */
|
|
4
5
|
export interface BlankPetFace {
|
|
6
|
+
/** Visual variant chosen in settings. */
|
|
7
|
+
readonly petStyle: PersonalizationConfig['petStyle'];
|
|
5
8
|
/** Selector hook over the compat layer's measurement. */
|
|
6
9
|
readonly useAnchor: () => PetAnchor | null;
|
|
7
10
|
}
|
|
@@ -14,4 +17,4 @@ export type BlankPetProps = PropsRuntime<'shell.overlay'> & BlankPetFace;
|
|
|
14
17
|
* @param props - injected measurement.
|
|
15
18
|
* @returns the positioned whale, or null.
|
|
16
19
|
*/
|
|
17
|
-
export declare function BlankPet({ useAnchor }: BlankPetProps): import("react/jsx-runtime").JSX.Element | null;
|
|
20
|
+
export declare function BlankPet({ useAnchor, petStyle }: BlankPetProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Reference pixel companion: take out a laptop, type, then return to standing. */
|
|
2
|
+
export declare function ClaudePet(): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
/** One shared drawing path for idle and recorded poses, also used by previews. */
|
|
4
|
+
export declare function ClaudeArt({ elapsed, reducedMotion }: {
|
|
5
|
+
readonly elapsed?: number | null;
|
|
6
|
+
readonly reducedMotion?: boolean;
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Geometric reconstruction of the original click sequence, sampled at 20fps.
|
|
2
|
+
* Recording antialiasing/compression fringes are not artwork: there is no outline
|
|
3
|
+
* layer. All feet have a constant 3px width; their roots follow the belly while
|
|
4
|
+
* their toes share a ground line. Only the projected feet have a deliberate bend.
|
|
5
|
+
*/
|
|
6
|
+
export type ClaudeFrame = readonly [body: string, shade: string, eyes: string, laptop: string];
|
|
7
|
+
export declare const CLAUDE_GROUND_Y = 23.5;
|
|
8
|
+
export declare const CLAUDE_IDLE: ClaudeFrame;
|
|
9
|
+
/** Pose order and hold times follow the recording; identical clean silhouettes
|
|
10
|
+
* are reused so compression noise cannot animate otherwise stationary edges. */
|
|
11
|
+
export declare const CLAUDE_FRAMES: readonly ClaudeFrame[];
|
|
12
|
+
export declare const CLAUDE_TRACK: readonly number[];
|
|
@@ -11,8 +11,8 @@ export interface HeaderActionProps {
|
|
|
11
11
|
/**
|
|
12
12
|
* One view button for the conversation header.
|
|
13
13
|
*
|
|
14
|
-
* All three sit in the utilities group beside the native actions,
|
|
15
|
-
* project folder; the corner seat past them holds nothing (the panel's shipped
|
|
14
|
+
* All three sit in the utilities group beside the native actions, in terminal,
|
|
15
|
+
* browser, project folder order; the corner seat past them holds nothing (the panel's shipped
|
|
16
16
|
* expand control is retired there and its action moves into the Session menu).
|
|
17
17
|
* All three are the same control: the box size, hover surface and spacing
|
|
18
18
|
* belong to the seat's own stylesheet
|
|
@@ -18,28 +18,24 @@ export declare const FILES_KIND = "files";
|
|
|
18
18
|
/**
|
|
19
19
|
* List orders inside `conversation.session.header.utilities`.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* scheduled-tasks entry (-5), not only below this plugin's own views: the
|
|
24
|
-
* reference draws the folder as the cluster's first control, whatever a Session
|
|
25
|
-
* happens to carry. The two views then land directly before the native session
|
|
26
|
-
* menu at 0 and keep it as the cluster's closing entry.
|
|
21
|
+
* Terminal, browser and project folder sit directly before the native session
|
|
22
|
+
* menu at 0, in that order.
|
|
27
23
|
*/
|
|
28
|
-
export declare const
|
|
29
|
-
export declare const
|
|
30
|
-
export declare const
|
|
24
|
+
export declare const TERMINAL_ORDER = -3;
|
|
25
|
+
export declare const BROWSER_ORDER = -2;
|
|
26
|
+
export declare const FOLDER_ORDER = -1;
|
|
31
27
|
/** The views this plugin exposes in the utilities group, in cluster order. */
|
|
32
28
|
export declare const VIEWS: readonly [{
|
|
33
|
-
readonly id: 'ccd-folder';
|
|
34
|
-
readonly kind: "files";
|
|
35
|
-
readonly order: -11;
|
|
36
|
-
}, {
|
|
37
29
|
readonly id: 'ccd-terminal';
|
|
38
30
|
readonly kind: 'terminal';
|
|
39
|
-
readonly order: -
|
|
31
|
+
readonly order: -3;
|
|
40
32
|
}, {
|
|
41
33
|
readonly id: 'ccd-browser';
|
|
42
34
|
readonly kind: 'browser';
|
|
35
|
+
readonly order: -2;
|
|
36
|
+
}, {
|
|
37
|
+
readonly id: 'ccd-folder';
|
|
38
|
+
readonly kind: "files";
|
|
43
39
|
readonly order: -1;
|
|
44
40
|
}];
|
|
45
41
|
/**
|
|
@@ -64,7 +60,7 @@ export type OpenViewKind = (kind: string, sessionId: string) => void;
|
|
|
64
60
|
export declare function utilitiesEntry(view: (typeof VIEWS)[number], labels: Record<(typeof VIEWS)[number]['kind'] | typeof FILES_KIND, string>, open: OpenViewKind): {
|
|
65
61
|
name: "conversation.session.header.utilities";
|
|
66
62
|
id: "ccd-browser" | "ccd-folder" | "ccd-terminal";
|
|
67
|
-
order: -
|
|
63
|
+
order: -3 | -2 | -1;
|
|
68
64
|
inject: (sessionId: string) => HeaderActionProps;
|
|
69
65
|
};
|
|
70
66
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The two View switcher glyphs, bundled as trusted static markup.
|
|
3
3
|
*
|
|
4
|
-
* Drawn to the reference's own segments (
|
|
5
|
-
*
|
|
4
|
+
* Drawn to the reference's own segments (DESIGN.md §6.5, @2x): a pair of
|
|
5
|
+
* speech bubbles for the chat View and the `</>` pair for the
|
|
6
6
|
* trajectory View, both on the CCD 16 grid — 1–1.2px stroke (each glyph's own
|
|
7
7
|
* weight read off the reference), round caps and joins, `currentColor` ink,
|
|
8
8
|
* ink box ≈ 12.5 × 11px inside the 16px artwork.
|
|
@@ -4,6 +4,7 @@ export interface EffortPanelProps {
|
|
|
4
4
|
readonly anchor: RefObject<HTMLButtonElement>;
|
|
5
5
|
readonly choices: readonly EffortChoice[];
|
|
6
6
|
readonly selected: number;
|
|
7
|
+
readonly defaultIndex: number;
|
|
7
8
|
readonly disabled: boolean;
|
|
8
9
|
readonly busy: boolean;
|
|
9
10
|
readonly error: string | null;
|
|
@@ -11,4 +12,4 @@ export interface EffortPanelProps {
|
|
|
11
12
|
readonly onClose: () => void;
|
|
12
13
|
}
|
|
13
14
|
/** Presentation-only slider: continuous local preview, one supported choice on release. */
|
|
14
|
-
export declare function EffortPanel({ anchor, choices, selected, disabled, busy, error, onCommit, onClose }: EffortPanelProps): import("react/jsx-runtime").JSX.Element | null;
|
|
15
|
+
export declare function EffortPanel({ anchor, choices, selected, defaultIndex, disabled, busy, error, onCommit, onClose }: EffortPanelProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -3,9 +3,19 @@ import type { ModelDirectoryState } from '@deepseek-ai/dsh-client-ui-model-selec
|
|
|
3
3
|
import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
|
|
4
4
|
import type { ModelSelection } from '@deepseek-ai/dsh-api-session-controller/types';
|
|
5
5
|
export type ModelControlsProps = Omit<ModelSelectInjected, 'directory'> & PropsLocale<'model'> & {
|
|
6
|
+
readonly showModelIcons: boolean;
|
|
6
7
|
readonly locked: boolean;
|
|
7
8
|
readonly useDirectory: () => ModelDirectoryState;
|
|
8
9
|
readonly selectEffort: (route: ModelSelection, effort: string | undefined) => void;
|
|
9
10
|
};
|
|
10
11
|
/** SDK-derived values/hooks and callbacks only; DSH retains all business state. */
|
|
11
|
-
export declare function ModelControls({ locked, available, useDirectory, load, select, selectEffort, t }: ModelControlsProps): import("react/jsx-runtime").JSX.Element | null;
|
|
12
|
+
export declare function ModelControls({ showModelIcons, locked, available, useDirectory, load, select, selectEffort, t }: ModelControlsProps): import("react/jsx-runtime").JSX.Element | null;
|
|
13
|
+
export declare function ModelPanel({ showModelIcons, anchor, state, disabled, load, t, onClose, onSelect }: PropsLocale<'model'> & {
|
|
14
|
+
readonly showModelIcons: boolean;
|
|
15
|
+
readonly anchor: React.RefObject<HTMLButtonElement>;
|
|
16
|
+
readonly state: ModelDirectoryState;
|
|
17
|
+
readonly disabled: boolean;
|
|
18
|
+
readonly load: () => void;
|
|
19
|
+
readonly onClose: () => void;
|
|
20
|
+
readonly onSelect: (selection: ModelSelection) => void;
|
|
21
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface ModelIconShape {
|
|
2
|
+
readonly kind: 'path' | 'circle' | 'ellipse' | 'rect';
|
|
3
|
+
readonly d?: string;
|
|
4
|
+
readonly cx?: string;
|
|
5
|
+
readonly cy?: string;
|
|
6
|
+
readonly r?: string;
|
|
7
|
+
readonly rx?: string;
|
|
8
|
+
readonly ry?: string;
|
|
9
|
+
readonly x?: string;
|
|
10
|
+
readonly y?: string;
|
|
11
|
+
readonly width?: string;
|
|
12
|
+
readonly height?: string;
|
|
13
|
+
readonly fillOpacity?: string;
|
|
14
|
+
readonly fillRule?: string;
|
|
15
|
+
readonly clipRule?: string;
|
|
16
|
+
readonly opacity?: string;
|
|
17
|
+
readonly transform?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ModelIconMark {
|
|
20
|
+
readonly title: string;
|
|
21
|
+
readonly viewBox: string;
|
|
22
|
+
readonly shapes: readonly ModelIconShape[];
|
|
23
|
+
readonly color?: ModelIconColor;
|
|
24
|
+
}
|
|
25
|
+
export interface ModelIconColor {
|
|
26
|
+
readonly viewBox: string;
|
|
27
|
+
readonly fill?: string;
|
|
28
|
+
readonly fillRule?: string;
|
|
29
|
+
readonly markup: string;
|
|
30
|
+
}
|
|
31
|
+
export declare const MODEL_ICONS: Readonly<Record<string, ModelIconMark>>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ModelIconMark } from './model-icon-data.ts';
|
|
2
|
+
export interface ModelIconTarget {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly name: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ModelIconMatch {
|
|
7
|
+
readonly slug: string;
|
|
8
|
+
readonly mark: ModelIconMark;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve one row's mark, preferring the model over its routing group.
|
|
12
|
+
*
|
|
13
|
+
* The provider is a fallback because a group such as `Magpie` can carry
|
|
14
|
+
* several brands; matching the group first made every row in it share one
|
|
15
|
+
* initial. The model row is the closest statement of which family a route
|
|
16
|
+
* actually serves.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveModelIcon(provider: ModelIconTarget, model: ModelIconTarget): ModelIconMatch | null;
|
|
19
|
+
/** The fallback seat: the model's own initial, not its routing group's. */
|
|
20
|
+
export declare function modelIconInitial(provider: ModelIconTarget, model: ModelIconTarget): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface ModelIconTarget {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly name: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* One row's leading glyph: the model family's mark when the index knows it,
|
|
7
|
+
* otherwise the model's initial. The seat is always drawn so rows align.
|
|
8
|
+
*/
|
|
9
|
+
export declare function ModelIcon({ provider, model }: {
|
|
10
|
+
readonly provider: ModelIconTarget;
|
|
11
|
+
readonly model: ModelIconTarget;
|
|
12
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|