dsh-rewind-plugin 0.12.2 → 0.13.0-alpha.2
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/CONTRIBUTING.md +1 -1
- package/README.en.md +0 -3
- package/README.md +0 -3
- package/SECURITY.md +1 -1
- package/docs/README.md +1 -1
- package/docs/architecture.md +3 -3
- package/docs/compat/audit.md +30 -17
- package/docs/compat/diagnostics.md +1 -0
- package/docs/compat/diagnostics.zh.md +1 -0
- package/docs/contract/client-contract.md +1 -1
- package/docs/contract/client-contract.zh.md +1 -1
- package/docs/format.md +2 -2
- package/docs/harness-reference.md +6 -3
- package/docs/release/release.md +9 -9
- package/docs/release/release.zh.md +10 -10
- package/docs/rewind-fix.md +1 -1
- package/docs/rewind-fix.zh.md +1 -1
- package/lib/client.js +315 -346
- package/lib/index.js +56 -25
- package/lib/types/client/build-info.d.ts +6 -0
- package/lib/types/client/candidates.d.ts +0 -2
- package/lib/types/client/hidden.d.ts +6 -7
- package/lib/types/client/locales.d.ts +6 -14
- package/lib/types/client/pending.d.ts +57 -15
- package/lib/types/client/popover.d.ts +1 -1
- package/lib/types/client/portals.d.ts +37 -27
- package/lib/types/client/settings-card.d.ts +177 -48
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/locales.d.ts +1 -1
- package/lib/types/rewind.d.ts +1 -1
- package/lib/types/session-cwd.d.ts +8 -10
- package/lib/types/snapshot-cleanup.d.ts +6 -4
- package/lib/types/snapshot.d.ts +4 -11
- package/package.json +54 -46
|
@@ -1,76 +1,205 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* dsh-rewind
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* dsh-rewind's configuration form for the Snapshot cleanup policy, rendered on
|
|
3
|
+
* this bundle's page under the sidebar's Plugins page (`plugins.bundle.config`,
|
|
4
|
+
* keyed by the bundle package name — 0.1.6-alpha.2 deleted the per-namespace
|
|
5
|
+
* `settings.plugin.item` slot).
|
|
5
6
|
*
|
|
6
|
-
* The
|
|
7
|
-
* `
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* The harness forms (`PluginConfigForm`, `CardForm`, `ValueField`) are
|
|
8
|
+
* package-internal — `ui-settings-plugins` ships `lib/**` only — so their
|
|
9
|
+
* behaviour and numbers are re-implemented here rather than imported; each rule
|
|
10
|
+
* below names the official function it mirrors. The switch follows
|
|
11
|
+
* `SubagentModelSelectionFields` (the official ships no boolean-with-reset
|
|
12
|
+
* control, so its entry point is the plain staged toggle) and the number
|
|
13
|
+
* follows `ValueField`.
|
|
12
14
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Two deliberate divergences, both where the official provides the entry point
|
|
16
|
+
* but no card uses it: the optional `help` disclosure is unused (it needs a
|
|
17
|
+
* second, help-only copy), and `placeholder` shows the host default (an empty
|
|
18
|
+
* draft means "use the default", and nothing else would say what that is).
|
|
19
|
+
*
|
|
20
|
+
* The transport is the structural {@link CleanupCardApi} supplied by
|
|
21
|
+
* `src/client/index.ts`: no client-settings type import, no `mutate`.
|
|
18
22
|
*
|
|
19
23
|
* @module dsh-rewind/client/settings-card
|
|
20
24
|
*/
|
|
21
25
|
/**
|
|
22
|
-
* The dsh-settings namespace
|
|
23
|
-
*
|
|
24
|
-
* imports; a cross-config test pins it equal to the host's constant. The
|
|
25
|
-
* settings grammar forbids dots, so this is hyphenated.
|
|
26
|
+
* The dsh-settings namespace, duplicated from the host module (the client build
|
|
27
|
+
* must stay free of host/node imports); both sides pin the literal.
|
|
26
28
|
*/
|
|
27
29
|
export declare const CLEANUP_SETTINGS_NAMESPACE = "dsh-rewind-snapshot-cleanup";
|
|
28
|
-
/** The
|
|
30
|
+
/** The default max age; an empty draft means "use this". */
|
|
29
31
|
export declare const DEFAULT_MAX_AGE_DAYS = 30;
|
|
30
32
|
/** The two editable knobs, exactly as the host policy exposes them. */
|
|
31
33
|
export interface CleanupPolicy {
|
|
32
34
|
readonly enabled: boolean;
|
|
33
35
|
readonly maxAgeDays: number;
|
|
34
36
|
}
|
|
35
|
-
/**
|
|
36
|
-
export
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
/** One editable field, named exactly as the host's settings section names it. */
|
|
38
|
+
export type CleanupField = 'enabled' | 'maxAgeDays';
|
|
39
|
+
/** The value type one field writes. */
|
|
40
|
+
export type CleanupValue = boolean | number;
|
|
41
|
+
/** One staged edit: the text the control renders, and whether saving clears the field. */
|
|
42
|
+
export interface StagedEdit {
|
|
43
|
+
/** Draft text the control renders. */
|
|
44
|
+
readonly text: string;
|
|
45
|
+
/** True when this edit clears the field whatever text it shows. */
|
|
46
|
+
readonly clear: boolean;
|
|
47
|
+
}
|
|
48
|
+
/** The staged edits, keyed by field (iteration order is staging order). */
|
|
49
|
+
export type StagedEdits = ReadonlyMap<CleanupField, StagedEdit>;
|
|
50
|
+
/**
|
|
51
|
+
* One entry in the save plan (the official `PlannedWrite`): `invalid` carries no
|
|
52
|
+
* write, which keeps the form dirty and makes the save refuse.
|
|
53
|
+
*/
|
|
54
|
+
export type PlannedWrite = {
|
|
55
|
+
readonly field: CleanupField;
|
|
56
|
+
readonly kind: 'set';
|
|
57
|
+
readonly value: CleanupValue;
|
|
58
|
+
} | {
|
|
59
|
+
readonly field: CleanupField;
|
|
60
|
+
readonly kind: 'clear';
|
|
61
|
+
} | {
|
|
62
|
+
readonly field: CleanupField;
|
|
63
|
+
readonly kind: 'invalid';
|
|
64
|
+
};
|
|
65
|
+
/** The reads one field's staging needs (the official scope reads). */
|
|
66
|
+
export interface CleanupFieldReads {
|
|
67
|
+
/** The resolved (effective) value of the field, if the section carries one. */
|
|
68
|
+
readonly value: CleanupValue | undefined;
|
|
69
|
+
/** Whether the USER layer carries the field (presence, never value equality). */
|
|
70
|
+
readonly stored: boolean;
|
|
39
71
|
}
|
|
40
|
-
/** The structural api the card reads/
|
|
72
|
+
/** The structural api the card reads/writes through (supplied by the client). */
|
|
41
73
|
export interface CleanupCardApi {
|
|
42
|
-
/**
|
|
43
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Whether the namespace is served to this client. The official shell reads
|
|
76
|
+
* `status === 'ready'`, so a still-loading namespace is NOT available.
|
|
77
|
+
*/
|
|
78
|
+
available(): boolean;
|
|
44
79
|
/** Whether the settings source accepts writes (false = read-only card). */
|
|
45
80
|
writable(): boolean;
|
|
46
|
-
/**
|
|
47
|
-
|
|
81
|
+
/** The resolved (effective) value of one field. */
|
|
82
|
+
read(field: CleanupField): CleanupValue | undefined;
|
|
83
|
+
/** The COMPOSITION value of one field, which a reset reverts to. */
|
|
84
|
+
base(field: CleanupField): CleanupValue | undefined;
|
|
85
|
+
/** Whether the user layer carries one field. */
|
|
86
|
+
stored(field: CleanupField): boolean;
|
|
87
|
+
/** Write one field; resolves to whether the Host holds the value afterwards. */
|
|
88
|
+
set(field: CleanupField, value: CleanupValue): Promise<boolean>;
|
|
89
|
+
/** Clear one field; resolves to whether the user layer no longer carries it. */
|
|
90
|
+
unset(field: CleanupField): Promise<boolean>;
|
|
48
91
|
/** Optional change subscription (returns the disposer). */
|
|
49
92
|
subscribe(cb: () => void): () => void;
|
|
50
93
|
}
|
|
51
94
|
/** Translate one client dictionary key (the card's `t`). */
|
|
52
95
|
export type CardTranslate = (key: string, params?: Record<string, string | number>) => string;
|
|
53
|
-
/**
|
|
54
|
-
export
|
|
55
|
-
|
|
56
|
-
|
|
96
|
+
/** The write a max-age draft stages. */
|
|
97
|
+
export type MaxAgeWrite = {
|
|
98
|
+
readonly kind: 'clear';
|
|
99
|
+
} | {
|
|
100
|
+
readonly kind: 'set';
|
|
101
|
+
readonly value: number;
|
|
102
|
+
};
|
|
103
|
+
/** The parsed form of one field's draft. */
|
|
104
|
+
export type FieldWrite = {
|
|
105
|
+
readonly kind: 'clear';
|
|
106
|
+
} | {
|
|
107
|
+
readonly kind: 'set';
|
|
108
|
+
readonly value: CleanupValue;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* The write a max-age draft stages, or undefined when the draft is not a value
|
|
112
|
+
* this field accepts (an invalid draft blocks the save rather than dropping the
|
|
113
|
+
* edit). An EMPTY draft clears, matching the official `numberField` spec.
|
|
114
|
+
* @param text - the control's draft text.
|
|
115
|
+
* @returns the staged write, or undefined when the draft is invalid.
|
|
116
|
+
*/
|
|
117
|
+
export declare function parseMaxAge(text: string): MaxAgeWrite | undefined;
|
|
118
|
+
/** Render a stored value as the max-age control's draft text (the official `numberField.format`). */
|
|
119
|
+
export declare function formatMaxAge(value: unknown): string;
|
|
120
|
+
/** Render a stored value as the switch's draft text. */
|
|
121
|
+
export declare function formatEnabled(value: unknown): string;
|
|
122
|
+
/**
|
|
123
|
+
* The write a boolean draft stages: the official switch is two-state, so every
|
|
124
|
+
* staged edit is a set and never a clear.
|
|
125
|
+
* @param text - the staged toggle text (`'true'` / `'false'`).
|
|
126
|
+
* @returns the staged write.
|
|
127
|
+
*/
|
|
128
|
+
export declare function parseEnabled(text: string): {
|
|
129
|
+
kind: 'set';
|
|
130
|
+
value: boolean;
|
|
131
|
+
};
|
|
132
|
+
/** Format one field's value as draft text. */
|
|
133
|
+
export declare function formatOf(field: CleanupField, value: unknown): string;
|
|
134
|
+
/** Parse one field's draft through its own spec. */
|
|
135
|
+
export declare function parseOf(field: CleanupField, text: string): FieldWrite | undefined;
|
|
136
|
+
/**
|
|
137
|
+
* The text one field's control renders: the staged draft when one stands,
|
|
138
|
+
* otherwise the effective value.
|
|
139
|
+
* @param field - field to render.
|
|
140
|
+
* @param staged - the current staged edits.
|
|
141
|
+
* @param reads - the field's effective value.
|
|
142
|
+
* @returns the control text.
|
|
143
|
+
*/
|
|
144
|
+
export declare function textOf(field: CleanupField, staged: StagedEdits, reads: CleanupFieldReads): string;
|
|
145
|
+
/**
|
|
146
|
+
* Whether saving would leave a user-layer entry for one field (the official
|
|
147
|
+
* `field().overridden`): a staged set answers true, a staged clear false, and
|
|
148
|
+
* with nothing staged the user layer's presence decides.
|
|
149
|
+
* @param field - field to judge.
|
|
150
|
+
* @param staged - the current staged edits.
|
|
151
|
+
* @param reads - the field's effective value and user-layer presence.
|
|
152
|
+
* @returns whether the badge is shown.
|
|
153
|
+
*/
|
|
154
|
+
export declare function overriddenOf(field: CleanupField, staged: StagedEdits, reads: CleanupFieldReads): boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Whether one field's draft is invalid, which blocks the save (the official
|
|
157
|
+
* `field().invalid`). A staged clear is never invalid.
|
|
158
|
+
* @param field - field to judge.
|
|
159
|
+
* @param staged - the current staged edits.
|
|
160
|
+
* @returns whether the draft cannot be saved.
|
|
161
|
+
*/
|
|
162
|
+
export declare function invalidOf(field: CleanupField, staged: StagedEdits): boolean;
|
|
163
|
+
/**
|
|
164
|
+
* Every entry a save would act on, in staging order (the official `plan()`).
|
|
165
|
+
* Two drafts plan nothing — one equal to the field's effective value, and a
|
|
166
|
+
* clear of a field the user layer never carried; an invalid draft plans an
|
|
167
|
+
* entry with no write, so the form stays dirty AND the save refuses.
|
|
168
|
+
* @param staged - the current staged edits.
|
|
169
|
+
* @param reads - per-field effective value and user-layer presence.
|
|
170
|
+
* @returns the planned entries.
|
|
171
|
+
*/
|
|
172
|
+
export declare function planOf(staged: StagedEdits, reads: (field: CleanupField) => CleanupFieldReads): readonly PlannedWrite[];
|
|
173
|
+
/** The form state the footer reads (the official `CardShell` subset this card uses). */
|
|
174
|
+
export interface CardShellState {
|
|
175
|
+
/** Whether the form holds edits a save would act on (an invalid entry counts). */
|
|
176
|
+
readonly dirty: boolean;
|
|
177
|
+
/** Whether any planned entry carries no write, which blocks the save. */
|
|
178
|
+
readonly invalid: boolean;
|
|
179
|
+
readonly saving: boolean;
|
|
180
|
+
readonly failed: boolean;
|
|
181
|
+
}
|
|
57
182
|
/**
|
|
58
|
-
* The
|
|
59
|
-
*
|
|
60
|
-
*
|
|
183
|
+
* The card-level state (the official `CardShell`): both `dirty` and `invalid`
|
|
184
|
+
* come from the plan, so the button and the drafts cannot disagree.
|
|
185
|
+
* @param plan - the entries a save would act on.
|
|
186
|
+
* @param flags - the crossing-the-wire and failure flags.
|
|
187
|
+
* @returns the footer's state.
|
|
61
188
|
*/
|
|
62
|
-
export declare function
|
|
63
|
-
|
|
64
|
-
|
|
189
|
+
export declare function shellOf(plan: readonly PlannedWrite[], flags: {
|
|
190
|
+
readonly saving: boolean;
|
|
191
|
+
readonly failed: boolean;
|
|
192
|
+
}): CardShellState;
|
|
65
193
|
/**
|
|
66
|
-
* The
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* @param api - the read/write transport.
|
|
70
|
-
* @param t - the client dictionary translator.
|
|
71
|
-
* @returns the
|
|
194
|
+
* The bundle's configuration form; `summary` renders nothing (the page only
|
|
195
|
+
* asks a bundle configuration for its `page` form).
|
|
196
|
+
* @param props.view - the view the Plugins page asks for.
|
|
197
|
+
* @param props.api - the read/write transport.
|
|
198
|
+
* @param props.t - the client dictionary translator.
|
|
199
|
+
* @returns the form element, or null for the summary view.
|
|
72
200
|
*/
|
|
73
|
-
export declare function SettingsCleanupCard({ api, t }: {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
201
|
+
export declare function SettingsCleanupCard({ view, api, t }: {
|
|
202
|
+
readonly view?: 'summary' | 'page';
|
|
203
|
+
readonly api: CleanupCardApi;
|
|
204
|
+
readonly t: CardTranslate;
|
|
205
|
+
}): import("react").JSX.Element | null;
|
|
@@ -23,4 +23,4 @@ export declare const CLASS: {
|
|
|
23
23
|
/** The ↶ glyph, drawn inline so the bundle stays dependency-free. */
|
|
24
24
|
export declare const REWIND_ICON_SVG: string;
|
|
25
25
|
/** One injected stylesheet (scoped under `.dsh-rewind-*`). */
|
|
26
|
-
export declare const STYLE = "\n.dsh-rewind-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 6px;\n border: none;\n border-radius: 28px;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n.dsh-rewind-btn:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.dsh-rewind-popover {\n position: fixed;\n z-index: 1000;\n width: 288px;\n padding: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3));\n box-shadow: var(--dsw-shadow-lv3);\n font-size: 14px;\n line-height: 20px;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-popover-title {\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n.dsh-rewind-popover-target {\n margin: 4px 0 10px;\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-all;\n}\n.dsh-rewind-popover-option {\n display: flex;\n flex-direction: column;\n gap: 2px;\n width: 100%;\n margin: 0 0 6px;\n padding: 8px 10px;\n border: 1px solid transparent;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n.dsh-rewind-popover-option:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-rewind-popover-option:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.dsh-rewind-popover-option-label {\n font-weight: 500;\n}\n.dsh-rewind-popover-option-hint {\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-popover-impact {\n margin: 4px 0 10px;\n padding: 8px 10px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n white-space: pre-wrap;\n max-height: 160px;\n overflow: auto;\n}\n.dsh-rewind-popover-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n.dsh-rewind-popover-primary,\n.dsh-rewind-popover-ghost {\n padding: 5px 12px;\n border: none;\n border-radius: 8px;\n font: inherit;\n font-size: 13px;\n line-height: 18px;\n cursor: pointer;\n}\n.dsh-rewind-popover-primary {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n.dsh-rewind-popover-primary:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n.dsh-rewind-popover-primary:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.dsh-rewind-popover-ghost {\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-rewind-popover-ghost:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.dsh-rewind-guard-hint {\n position: fixed;\n z-index: 1000;\n max-width: min(440px, calc(100vw - 24px));\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3));\n box-shadow: var(--dsw-shadow-lv3);\n font-size: 13px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n pointer-events: none;\n}\n\n/* ---- Snapshot-cleanup settings card (mirrors the harness PluginCard look) ---- */\n/* Standardized on the 0.1.2 harness card look (border-radius 16px + 0.5px\n border-l4, 0.5px internal separators). */\n.dsh-rewind-cleanup-card {\n list-style: none;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 16px;\n background: var(--dsw-alias-bg-layer-3);\n transition: border-color .16s, background .16s;\n}\n.dsh-rewind-cleanup-card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-rewind-cleanup-card-open {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-rewind-cleanup-header {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 12px;\n}\n.dsh-rewind-cleanup-header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n.dsh-rewind-cleanup-head-text {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.dsh-rewind-cleanup-name {\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-desc {\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-cleanup-chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n transition: transform .16s;\n}\n.dsh-rewind-cleanup-chevron-open {\n transform: rotate(180deg);\n}\n.dsh-rewind-cleanup-pending {\n flex: none;\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-rewind-cleanup-body {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n margin: 0 16px;\n padding: 0 0 8px;\n}\n.dsh-rewind-cleanup-readonly {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-cleanup-permission {\n display: grid;\n gap: 6px;\n padding: 12px 0;\n}\n.dsh-rewind-cleanup-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 0;\n}\n.dsh-rewind-cleanup-field + .dsh-rewind-cleanup-field {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n/* Auto-cleanup (permission) block and the max-age field are consecutive control\n * sections of the open card \u2014 give them the same 0.5px divider the harness gives\n * every pair of config fields (fields.module.css field + field). */\n.dsh-rewind-cleanup-permission + .dsh-rewind-cleanup-field {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n.dsh-rewind-cleanup-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-rewind-cleanup-label {\n flex: 1;\n min-width: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-hint {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-cleanup-error {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-error);\n}\n/* Switch row: label left, role=switch button right, hint below (Subagent module).\n * The track mirrors the harness ui-primitives Switch (0.1.3-alpha.2 line): the\n * on/off appearance keys off aria-checked rather than a parallel class, so the\n * visual state cannot disagree with the state assistive technology reads, and\n * corner-shape: round opts the capsule track out of the global superellipse\n * (which would square the capsule ends off against the round thumb inside). */\n.dsh-rewind-cleanup-toggle-row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-toggle-label {\n flex: 1;\n min-width: 0;\n}\n.dsh-rewind-cleanup-switch {\n box-sizing: border-box;\n position: relative;\n flex: 0 0 auto;\n width: 36px;\n height: 20px;\n padding: 2px;\n border: 0;\n border-radius: 10px;\n corner-shape: round;\n background: var(--dsw-alias-border-l3);\n cursor: pointer;\n}\n.dsh-rewind-cleanup-switch[aria-checked='true'] {\n background: var(--dsw-alias-brand-primary);\n}\n.dsh-rewind-cleanup-switch:disabled {\n cursor: default;\n opacity: 0.5;\n}\n.dsh-rewind-cleanup-switch:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n.dsh-rewind-cleanup-thumb {\n display: block;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n corner-shape: round;\n background: var(--dsw-alias-label-primary-foreground);\n transition: transform 120ms ease;\n}\n.dsh-rewind-cleanup-switch[aria-checked='true'] .dsh-rewind-cleanup-thumb {\n transform: translateX(16px);\n}\n.dsh-rewind-cleanup-input {\n box-sizing: border-box;\n height: 34px;\n padding: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-input:focus-visible {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n.dsh-rewind-cleanup-input:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n.dsh-rewind-cleanup-input-invalid {\n border-color: var(--dsw-alias-label-error);\n}\n.dsh-rewind-cleanup-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n padding: 12px 0 4px;\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n.dsh-rewind-cleanup-failed {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-error);\n}\n.dsh-rewind-cleanup-discard,\n.dsh-rewind-cleanup-save {\n appearance: none;\n border: 1px solid transparent;\n border-radius: 8px;\n padding: 5px 14px;\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n cursor: pointer;\n}\n.dsh-rewind-cleanup-discard {\n border-color: var(--dsw-alias-border-l2);\n background: none;\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-rewind-cleanup-discard:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-dimmed);\n}\n.dsh-rewind-cleanup-save {\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n.dsh-rewind-cleanup-discard:disabled,\n.dsh-rewind-cleanup-save:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.dsh-rewind-cleanup-discard:focus-visible,\n.dsh-rewind-cleanup-save:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n";
|
|
26
|
+
export declare const STYLE = "\n.dsh-rewind-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 6px;\n border: none;\n border-radius: 28px;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n.dsh-rewind-btn:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.dsh-rewind-popover {\n position: fixed;\n z-index: 1000;\n width: 288px;\n padding: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3));\n box-shadow: var(--dsw-shadow-lv3);\n font-size: 14px;\n line-height: 20px;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-popover-title {\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n.dsh-rewind-popover-target {\n margin: 4px 0 10px;\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary);\n word-break: break-all;\n}\n.dsh-rewind-popover-option {\n display: flex;\n flex-direction: column;\n gap: 2px;\n width: 100%;\n margin: 0 0 6px;\n padding: 8px 10px;\n border: 1px solid transparent;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n.dsh-rewind-popover-option:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n/* Arrow navigation moves real focus, so the focused row carries the pointer's\n fill and the browser ring is suppressed: in dark mode the UA two-tone ring\n draws its dark half against the filled row and reads as a residue edge (the\n harness Menu suppresses it the same way). */\n.dsh-rewind-popover-option:focus-visible:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n outline: none;\n}\n.dsh-rewind-popover-option:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.dsh-rewind-popover-option-label {\n font-weight: 500;\n}\n.dsh-rewind-popover-option-hint {\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-popover-impact {\n margin: 4px 0 10px;\n padding: 8px 10px;\n border-radius: 8px;\n background: var(--dsw-alias-interactive-bg-hover);\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n white-space: pre-wrap;\n max-height: 160px;\n overflow: auto;\n}\n.dsh-rewind-popover-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n.dsh-rewind-popover-primary,\n.dsh-rewind-popover-ghost {\n padding: 5px 12px;\n border: none;\n border-radius: 8px;\n font: inherit;\n font-size: 13px;\n line-height: 18px;\n cursor: pointer;\n}\n.dsh-rewind-popover-primary {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n.dsh-rewind-popover-primary:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n.dsh-rewind-popover-primary:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.dsh-rewind-popover-ghost {\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n}\n.dsh-rewind-popover-ghost:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.dsh-rewind-guard-hint {\n position: fixed;\n z-index: 1000;\n max-width: min(440px, calc(100vw - 24px));\n padding: 8px 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-specific-menu, var(--dsw-alias-bg-layer-3));\n box-shadow: var(--dsw-shadow-lv3);\n font-size: 13px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n pointer-events: none;\n}\n\n/* ---- Snapshot-cleanup configuration form (mirrors the harness plugin form) ---- */\n/* The Plugins page draws the bundle's title, icon, crumb, and description; this\n is the form body only. Every value mirrors ui-settings-plugins'\n PluginConfigForm.module.css / fields.module.css /\n SubagentModelSelectionFields.module.css: those components are package-internal\n (the package ships lib/** only) and cannot be imported across packages, so the\n numbers are copied rather than the components. */\n.dsh-rewind-cleanup-form {\n display: flex;\n flex-direction: column;\n}\n.dsh-rewind-cleanup-readonly,\n.dsh-rewind-cleanup-unavailable {\n margin: 0 0 12px;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n/* Auto-cleanup permission block: the label + Switch row, then the hint. */\n.dsh-rewind-cleanup-permission {\n display: grid;\n gap: 6px;\n padding: 12px 0;\n}\n.dsh-rewind-cleanup-toggle-row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-toggle-label {\n flex: 1;\n min-width: 0;\n}\n.dsh-rewind-cleanup-field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px 0;\n}\n.dsh-rewind-cleanup-field + .dsh-rewind-cleanup-field {\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n.dsh-rewind-cleanup-head {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-rewind-cleanup-label-group {\n display: flex;\n align-items: center;\n gap: 4px;\n flex: 1;\n min-width: 0;\n}\n.dsh-rewind-cleanup-label {\n flex: 1;\n min-width: 0;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-label-group > .dsh-rewind-cleanup-label {\n flex: 0 1 auto;\n}\n.dsh-rewind-cleanup-badges {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-rewind-cleanup-reset {\n border: none;\n background: none;\n padding: 0;\n font: inherit;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n.dsh-rewind-cleanup-reset:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-reset:disabled {\n cursor: default;\n}\n.dsh-rewind-cleanup-hint {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n.dsh-rewind-cleanup-error {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-state-error-primary);\n}\n.dsh-rewind-cleanup-input {\n height: 34px;\n padding: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsh-rewind-cleanup-input:focus-visible {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n.dsh-rewind-cleanup-input:disabled {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n.dsh-rewind-cleanup-input[aria-invalid='true'] {\n border-color: var(--dsw-alias-state-error-primary);\n}\n.dsh-rewind-cleanup-footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding-top: 16px;\n}\n.dsh-rewind-cleanup-failed {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-error);\n}\n.dsh-rewind-cleanup-save {\n appearance: none;\n border: 1px solid transparent;\n border-radius: 8px;\n padding: 5px 14px;\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n cursor: pointer;\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n.dsh-rewind-cleanup-save:disabled {\n opacity: 0.4;\n cursor: default;\n}\n.dsh-rewind-cleanup-save:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n";
|
package/lib/types/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* (and the rendered transcript) is untouched — only the model-visible surface
|
|
10
10
|
* is cut, so the next request derives its context from the target onward.
|
|
11
11
|
* The marker is a `user/message` carrying the shadowed-seq citations
|
|
12
|
-
* (`sourceEventSeqs`):
|
|
12
|
+
* (`sourceEventSeqs`): v3 reserves surface `replace` to a node that cites
|
|
13
13
|
* every shadowed seq, and `assistant/message` can no longer carry those — so
|
|
14
14
|
* the replacement node is a `user/message`, exactly as /compact's checkpoint
|
|
15
15
|
* is. It derives to itself (a present user turn), so the marker stays as the
|
package/lib/types/locales.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* host prose.
|
|
17
17
|
*
|
|
18
18
|
* DSH localizes only its OWN command descriptions via the client locale — a
|
|
19
|
-
* closed `
|
|
19
|
+
* closed `HOST_FACES` allowlist; third-party plugin descriptions are
|
|
20
20
|
* not in that channel (see docs/compat/audit.md, RU-I18N), so this plugin's host
|
|
21
21
|
* command copy stays in the host's tongue (English by default).
|
|
22
22
|
*
|
package/lib/types/rewind.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* user/message (marker content) → { surfaceOp {replace, startSeq, endSeq} }
|
|
16
16
|
*
|
|
17
|
-
*
|
|
17
|
+
* v3 reserves surface `replace` to a node that cites every shadowed seq via
|
|
18
18
|
* `sourceEventSeqs`, and `assistant/message` can no longer carry
|
|
19
19
|
* `sourceEventSeqs` (it now embeds its provider stream instead) — so the
|
|
20
20
|
* replacement node must be a `user/message`, exactly as /compact's checkpoint
|
|
@@ -4,26 +4,24 @@
|
|
|
4
4
|
* resolve against the calling agent's session workspace
|
|
5
5
|
* (`exec.agent.session.header.cwd`), not the server's launch dir.
|
|
6
6
|
*
|
|
7
|
-
* Pure functions: the
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* tool boundary behavior.
|
|
7
|
+
* Pure functions: the session cwd is returned verbatim. The fs tools no longer
|
|
8
|
+
* canonicalize a parent-traversing cwd (alpha line), so neither does the
|
|
9
|
+
* plugin — snapshot tracking must resolve to the same base the tool wrote to.
|
|
11
10
|
*
|
|
12
11
|
* @module dsh-rewind/session-cwd
|
|
13
12
|
*/
|
|
14
13
|
import type { ToolExecution } from '@deepseek-ai/dsh-tools';
|
|
15
14
|
/**
|
|
16
|
-
* The session workspace cwd to resolve
|
|
15
|
+
* The session workspace cwd to resolve a requested path against, or undefined
|
|
17
16
|
* when no session cwd applies (the filesystem backend then uses its own
|
|
18
17
|
* default base).
|
|
19
18
|
* @param cwd - the session's `header.cwd`, if any.
|
|
20
|
-
* @
|
|
21
|
-
* @returns the cwd, canonicalized when traversal could expose a symlink.
|
|
19
|
+
* @returns the cwd unchanged.
|
|
22
20
|
*/
|
|
23
|
-
export declare function sessionCwd(cwd: string | undefined
|
|
21
|
+
export declare function sessionCwd(cwd: string | undefined): string | undefined;
|
|
24
22
|
/**
|
|
25
23
|
* Session cwd for one tool execution (same rule as the fs tools).
|
|
26
24
|
* @param exec - the tool-execution context; only its optional `agent` is read.
|
|
27
|
-
* @
|
|
25
|
+
* @returns the calling agent's session cwd, or undefined for a non-agent caller.
|
|
28
26
|
*/
|
|
29
|
-
export declare function execSessionCwd(exec: ToolExecution
|
|
27
|
+
export declare function execSessionCwd(exec: ToolExecution): string | undefined;
|
|
@@ -47,7 +47,7 @@ export declare const CleanupConfigSchema: z<CleanupConfig>;
|
|
|
47
47
|
* Structural face of the settings scope the host needs for the policy: a
|
|
48
48
|
* resolved read and a validated write. Kept local (never imports the settings
|
|
49
49
|
* contract) so the host bundle does not type-couple on the client settings
|
|
50
|
-
* API (
|
|
50
|
+
* API (`mutate` is unused here), and the seam the host passes
|
|
51
51
|
* in isolates the drift to this module.
|
|
52
52
|
*/
|
|
53
53
|
export interface CleanupSettingsScope {
|
|
@@ -107,6 +107,9 @@ export interface AutoCleanupPruner {
|
|
|
107
107
|
* a corrupt config fail-closes (no deletion) and logs, a prune failure logs.
|
|
108
108
|
*
|
|
109
109
|
* `sessionId` is the active session directory that must never be pruned.
|
|
110
|
+
* `signal` is the caller's mount lifecycle: an abort before the prune or before
|
|
111
|
+
* the re-anchor stops the sweep (a live plugin unload must not keep deleting
|
|
112
|
+
* under a disposed owner).
|
|
110
113
|
*/
|
|
111
114
|
export declare function runAutoCleanupCheck(deps: {
|
|
112
115
|
pruner: AutoCleanupPruner;
|
|
@@ -119,6 +122,8 @@ export declare function runAutoCleanupCheck(deps: {
|
|
|
119
122
|
}>;
|
|
120
123
|
statePath: string;
|
|
121
124
|
log: (msg: string) => void;
|
|
125
|
+
/** Optional mount lifecycle signal; absent means "never cancelled". */
|
|
126
|
+
signal?: AbortSignal;
|
|
122
127
|
}, sessionId: string | undefined): Promise<void>;
|
|
123
128
|
/**
|
|
124
129
|
* Validate one parsed JSON value into a {@link CleanupConfig}. Tolerates
|
|
@@ -132,9 +137,6 @@ export declare function parseCleanupConfig(raw: unknown): {
|
|
|
132
137
|
ok: false;
|
|
133
138
|
error: string;
|
|
134
139
|
};
|
|
135
|
-
/**
|
|
136
|
-
* The `/snapshot-auto-cleanup` sub-command the parser can resolve to.
|
|
137
|
-
*/ export type CleanupCommandAction = 'status' | 'on' | 'off' | 'max-age' | 'run';
|
|
138
140
|
/** A parsed `/snapshot-auto-cleanup` command (excludes the error branch). */
|
|
139
141
|
export type CleanupCommand = {
|
|
140
142
|
action: 'status' | 'on' | 'off';
|
package/lib/types/snapshot.d.ts
CHANGED
|
@@ -65,13 +65,6 @@
|
|
|
65
65
|
*
|
|
66
66
|
* @module dsh-rewind/snapshot
|
|
67
67
|
*/
|
|
68
|
-
/**
|
|
69
|
-
* Default store root: `<harness home>/rewind-snapshots`. Resolved through
|
|
70
|
-
* {@link resolveDshHome} so the plugin follows `$DSH_HOME` (or a configured
|
|
71
|
-
* harness home) rather than hardcoding `~/.dsh` — matching the other
|
|
72
|
-
* first-party DSH packages. See `SECURITY.md` "Sensitive files".
|
|
73
|
-
*/
|
|
74
|
-
export declare const DEFAULT_SNAPSHOT_ROOT: string;
|
|
75
68
|
/** Environment variable overriding the store root (tests, exotic homes). */
|
|
76
69
|
export declare const SNAPSHOT_ROOT_ENV = "DSH_REWIND_SNAPSHOT_DIR";
|
|
77
70
|
/** Number of newest anchor groups (user messages) kept per session. */
|
|
@@ -481,7 +474,7 @@ export declare class SnapshotStore {
|
|
|
481
474
|
/**
|
|
482
475
|
* Session-format version snapshots are anchored under, stamped into each
|
|
483
476
|
* session's `format` marker when an entry is recorded. `null` until the host
|
|
484
|
-
* sets it (from `agent/
|
|
477
|
+
* sets it (from `agent/created`), so a session that never records is
|
|
485
478
|
* never materialized and a marker is only written where snapshots exist.
|
|
486
479
|
*/
|
|
487
480
|
private formatVersion;
|
|
@@ -837,7 +830,7 @@ export declare class SnapshotStore {
|
|
|
837
830
|
* record that cannot be classified is never destroyed.
|
|
838
831
|
*/
|
|
839
832
|
private pruneTerminalJournals;
|
|
840
|
-
/** True when a path exists on disk
|
|
833
|
+
/** True when a path exists on disk. */
|
|
841
834
|
exists(path: string): Promise<boolean>;
|
|
842
835
|
/**
|
|
843
836
|
* Cross-session retention sweep: remove WHOLE session directories whose
|
|
@@ -941,7 +934,7 @@ export declare class SnapshotStore {
|
|
|
941
934
|
markFormatVersion(sessionId: string, sessionVersion: number): Promise<void>;
|
|
942
935
|
/**
|
|
943
936
|
* Set the session-format version the store stamps onto every snapshot it
|
|
944
|
-
* records. The host sets this once per process from `agent/
|
|
937
|
+
* records. The host sets this once per process from `agent/created`
|
|
945
938
|
* (`agent.session.header.version`), so a marker is only materialized for a
|
|
946
939
|
* session that actually records a snapshot.
|
|
947
940
|
*/
|
|
@@ -972,7 +965,7 @@ export declare class SnapshotStore {
|
|
|
972
965
|
* Session-format-version guard: clear a session's snapshot dir when the
|
|
973
966
|
* format its snapshots were anchored under differs from the current session
|
|
974
967
|
* format, so seq-anchored references can never survive a format migration
|
|
975
|
-
* mis-mapped. Runs at `agent/
|
|
968
|
+
* mis-mapped. Runs at `agent/created` — after DSH has migrated/loaded
|
|
976
969
|
* the session, so `sessionVersion` is the post-migration value.
|
|
977
970
|
*
|
|
978
971
|
* Conservative rule (per the "delete stale snapshots" policy): a session
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-rewind-plugin",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.13.0-alpha.2",
|
|
4
|
+
"description": "In-window conversation rewind with workspace file restore · 同窗口内对话回退并可还原工作区文件",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
7
7
|
"dsh",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"patch": "./cordis.patch.yml"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
|
-
"dsh": ">=0.1.
|
|
53
|
+
"dsh": ">=0.1.6-alpha.2"
|
|
54
54
|
},
|
|
55
55
|
"client": {
|
|
56
56
|
"inject": [
|
|
@@ -76,18 +76,19 @@
|
|
|
76
76
|
"peerDependencies": {
|
|
77
77
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
78
78
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
79
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.
|
|
80
|
-
"@deepseek-ai/dsh-client-ui-commands": "^0.1.
|
|
81
|
-
"@deepseek-ai/dsh-client-ui-
|
|
82
|
-
"@deepseek-ai/dsh-client-ui-
|
|
83
|
-
"@deepseek-ai/dsh-
|
|
84
|
-
"@deepseek-ai/dsh-
|
|
85
|
-
"@deepseek-ai/dsh-
|
|
86
|
-
"@deepseek-ai/dsh-
|
|
87
|
-
"@deepseek-ai/dsh-
|
|
88
|
-
"@deepseek-ai/dsh-
|
|
89
|
-
"@deepseek-ai/dsh-
|
|
90
|
-
"@deepseek-ai/dsh-
|
|
79
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.6-alpha.2",
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-commands": "^0.1.6-alpha.2",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.6-alpha.2",
|
|
82
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.6-alpha.2",
|
|
83
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.2",
|
|
84
|
+
"@deepseek-ai/dsh-commands": "^0.1.6-alpha.2",
|
|
85
|
+
"@deepseek-ai/dsh-fs": "^0.1.6-alpha.2",
|
|
86
|
+
"@deepseek-ai/dsh-home-paths": "^0.1.6-alpha.2",
|
|
87
|
+
"@deepseek-ai/dsh-llm": "^0.1.6-alpha.2",
|
|
88
|
+
"@deepseek-ai/dsh-sandbox": "^0.1.6-alpha.2",
|
|
89
|
+
"@deepseek-ai/dsh-session": "^0.1.6-alpha.2",
|
|
90
|
+
"@deepseek-ai/dsh-settings": "^0.1.6-alpha.2",
|
|
91
|
+
"@deepseek-ai/dsh-tools": "^0.1.6-alpha.2"
|
|
91
92
|
},
|
|
92
93
|
"peerDependenciesMeta": {
|
|
93
94
|
"@deepseek-ai/cordis": {
|
|
@@ -102,6 +103,9 @@
|
|
|
102
103
|
"@deepseek-ai/dsh-client-ui-commands": {
|
|
103
104
|
"optional": true
|
|
104
105
|
},
|
|
106
|
+
"@deepseek-ai/dsh-client-ui-primitives": {
|
|
107
|
+
"optional": true
|
|
108
|
+
},
|
|
105
109
|
"@deepseek-ai/dsh-client-ui-settings": {
|
|
106
110
|
"optional": true
|
|
107
111
|
},
|
|
@@ -136,37 +140,41 @@
|
|
|
136
140
|
"devDependencies": {
|
|
137
141
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
138
142
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
139
|
-
"@deepseek-ai/dsh-agent": "^0.1.
|
|
140
|
-
"@deepseek-ai/dsh-attachment": "^0.1.
|
|
141
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.
|
|
142
|
-
"@deepseek-ai/dsh-client-connection": "^0.1.
|
|
143
|
-
"@deepseek-ai/dsh-client-store": "^0.1.
|
|
144
|
-
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.
|
|
145
|
-
"@deepseek-ai/dsh-
|
|
146
|
-
"@deepseek-ai/dsh-client-ui-
|
|
147
|
-
"@deepseek-ai/dsh-
|
|
148
|
-
"@deepseek-ai/dsh-
|
|
149
|
-
"@deepseek-ai/dsh-
|
|
150
|
-
"@deepseek-ai/dsh-
|
|
151
|
-
"@deepseek-ai/dsh-
|
|
152
|
-
"@deepseek-ai/dsh-
|
|
153
|
-
"@deepseek-ai/dsh-
|
|
154
|
-
"@deepseek-ai/dsh-
|
|
155
|
-
"@deepseek-ai/dsh-
|
|
156
|
-
"@deepseek-ai/dsh-
|
|
157
|
-
"@deepseek-ai/dsh-
|
|
158
|
-
"@deepseek-ai/dsh-
|
|
159
|
-
"@deepseek-ai/dsh-
|
|
160
|
-
"@deepseek-ai/dsh-
|
|
161
|
-
"@deepseek-ai/dsh-
|
|
162
|
-
"@deepseek-ai/dsh-
|
|
163
|
-
"@deepseek-ai/dsh-
|
|
164
|
-
"@deepseek-ai/dsh-
|
|
165
|
-
"@deepseek-ai/dsh-
|
|
166
|
-
"@deepseek-ai/dsh-
|
|
167
|
-
"@deepseek-ai/dsh-
|
|
168
|
-
"@deepseek-ai/dsh-
|
|
169
|
-
"@deepseek-ai/dsh-
|
|
143
|
+
"@deepseek-ai/dsh-agent": "^0.1.6-alpha.2",
|
|
144
|
+
"@deepseek-ai/dsh-attachment": "^0.1.6-alpha.2",
|
|
145
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.6-alpha.2",
|
|
146
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.6-alpha.2",
|
|
147
|
+
"@deepseek-ai/dsh-client-store": "^0.1.6-alpha.2",
|
|
148
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.6-alpha.2",
|
|
149
|
+
"@deepseek-ai/dsh-client-ui-plugin-manager": "^0.1.6-alpha.2",
|
|
150
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.6-alpha.2",
|
|
151
|
+
"@deepseek-ai/dsh-client-ui-session": "^0.1.6-alpha.2",
|
|
152
|
+
"@deepseek-ai/dsh-api-session-controller": "^0.1.6-alpha.2",
|
|
153
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.6-alpha.2",
|
|
154
|
+
"@deepseek-ai/dsh-scope": "^0.1.6-alpha.2",
|
|
155
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.6-alpha.2",
|
|
156
|
+
"@deepseek-ai/dsh-user-questions": "^0.1.6-alpha.2",
|
|
157
|
+
"@deepseek-ai/dsh-client-ui-commands": "^0.1.6-alpha.2",
|
|
158
|
+
"@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.6-alpha.2",
|
|
159
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.2",
|
|
160
|
+
"@deepseek-ai/dsh-command-compact": "^0.1.6-alpha.2",
|
|
161
|
+
"@deepseek-ai/dsh-commands": "^0.1.6-alpha.2",
|
|
162
|
+
"@deepseek-ai/dsh-compaction": "^0.1.6-alpha.2",
|
|
163
|
+
"@deepseek-ai/dsh-compaction-basic": "^0.1.6-alpha.2",
|
|
164
|
+
"@deepseek-ai/dsh-compaction-image-offload": "^0.1.6-alpha.2",
|
|
165
|
+
"@deepseek-ai/dsh-fs": "^0.1.6-alpha.2",
|
|
166
|
+
"@deepseek-ai/dsh-goal": "^0.1.6-alpha.2",
|
|
167
|
+
"@deepseek-ai/dsh-home-paths": "^0.1.6-alpha.2",
|
|
168
|
+
"@deepseek-ai/dsh-llm": "^0.1.6-alpha.2",
|
|
169
|
+
"@deepseek-ai/dsh-plan-mode": "^0.1.6-alpha.2",
|
|
170
|
+
"@deepseek-ai/dsh-sandbox": "^0.1.6-alpha.2",
|
|
171
|
+
"@deepseek-ai/dsh-session": "^0.1.6-alpha.2",
|
|
172
|
+
"@deepseek-ai/dsh-session-projection": "^0.1.6-alpha.2",
|
|
173
|
+
"@deepseek-ai/dsh-session-stats": "^0.1.6-alpha.2",
|
|
174
|
+
"@deepseek-ai/dsh-session-title": "^0.1.6-alpha.2",
|
|
175
|
+
"@deepseek-ai/dsh-settings": "^0.1.6-alpha.2",
|
|
176
|
+
"@deepseek-ai/dsh-token-meter": "^0.1.6-alpha.2",
|
|
177
|
+
"@deepseek-ai/dsh-tools": "^0.1.6-alpha.2",
|
|
170
178
|
"@types/node": "^24.0.0",
|
|
171
179
|
"@types/react": "^18.3.31",
|
|
172
180
|
"@types/react-dom": "^18.3.7",
|