@dsh-electron/dsh-plugin-multi-root-workspace 0.1.13 → 0.1.15
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/CHANGELOG.en.md +36 -1
- package/CHANGELOG.md +36 -1
- package/README.en.md +27 -10
- package/README.md +27 -10
- package/cordis.patch.yml +5 -1
- package/detail/DETAIL.en.md +1 -0
- package/detail/DETAIL.md +1 -0
- package/detail/preview.svg +1 -0
- package/detail/preview.zh.svg +1 -0
- package/lib/{llm-message-fYORacvh.js → agent-instructions-BXuKhOzr.js} +1 -84
- package/lib/auto-review.js +2 -2
- package/lib/client.js +584 -73
- package/lib/client.js.map +1 -1
- package/lib/{command-B9855H7y.js → command-y5tfcAeC.js} +45 -12
- package/lib/command.js +1 -1
- package/lib/compat-CTJbpCxu.js +267 -0
- package/lib/compat.js +1 -1
- package/lib/{dialects-Dr4rDR-H.js → dialects-CdlG3RF9.js} +1 -1
- package/lib/{compat-Bg2HFVMX.js → dsh-version-DCwF7REk.js} +5 -265
- package/lib/{fs-CfzJq2wd.js → fs-Uws0ZpmV.js} +38 -0
- package/lib/fs.js +1 -1
- package/lib/index.js +11 -9
- package/lib/{instructions-KsUwUFE0.js → instructions-Ck9wp4J4.js} +695 -26
- package/lib/instructions.js +1 -1
- package/lib/llm-message-CepyzEBQ.js +84 -0
- package/lib/lsp.js +3 -3
- package/lib/{metadata-DgqSdVX_.js → metadata-99jgViHQ.js} +1 -1
- package/lib/{method-wrapper-CFY3p3j2.js → method-wrapper-D4oUCsEF.js} +22 -2
- package/lib/{native-win32-2waCRkPI.js → native-win32-C5oMtt7f.js} +2 -1
- package/lib/ops-compatibility.js +58 -0
- package/lib/ops-settings-UN2oOKEp.js +40 -0
- package/lib/ops-tools-k4JYaOrM.js +152 -0
- package/lib/process-fence.js +100 -24
- package/lib/{protocol-CJOvAvOS.js → protocol-CwDnFEyK.js} +54 -8
- package/lib/{registry-Bv431TfO.js → registry-DyDNDSJZ.js} +235 -79
- package/lib/{registry-lease-win32-DVTq9d4D.js → registry-lease-win32-r4puac9m.js} +2 -1
- package/lib/registry.js +2 -2
- package/lib/{review-context-NDpKeMCc.js → review-context-B-oHkU6a.js} +24 -7
- package/lib/review-context.js +1 -1
- package/lib/{roots-Ca_W1S9n.js → roots-CmaWxRVy.js} +112 -22
- package/lib/{sandbox-C-vCJCp3.js → sandbox-CZElTNPz.js} +1 -1
- package/lib/sandbox.js +1 -1
- package/lib/scope.js +72 -9
- package/lib/skills-utyuvmwr.js +104 -0
- package/lib/skills.js +4 -105
- package/lib/{tool-context-CpgIFcCB.js → tool-context-CCeY3mrK.js} +1 -1
- package/lib/types/authority/protocol.d.ts +5 -1
- package/lib/types/client/RootSwitcher.d.ts +2 -0
- package/lib/types/client/auto-review-settings.d.ts +18 -0
- package/lib/types/client/files-tree/FilesTree.d.ts +4 -1
- package/lib/types/client/files-tree/locales.d.ts +1 -1
- package/lib/types/client/locales.d.ts +40 -0
- package/lib/types/client/open-in-app/locales.d.ts +1 -1
- package/lib/types/client/ops-settings.d.ts +6 -0
- package/lib/types/client/skills-settings.d.ts +13 -0
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/command.d.ts +3 -3
- package/lib/types/compat/auto-review-client.d.ts +58 -0
- package/lib/types/compat/connection-rpc.d.ts +12 -0
- package/lib/types/compat/dsh-version.d.ts +1 -1
- package/lib/types/compat/files-tree.d.ts +36 -0
- package/lib/types/compat/fs-patch.d.ts +6 -0
- package/lib/types/compat/instruction-activity.d.ts +32 -1
- package/lib/types/compat/koffi.d.ts +2 -0
- package/lib/types/compat/ops-confirmation.d.ts +17 -0
- package/lib/types/compat/ops-settings.d.ts +11 -0
- package/lib/types/compat/ops-tools.d.ts +25 -0
- package/lib/types/compat/skills-client.d.ts +1 -0
- package/lib/types/compat/tool-context.d.ts +4 -0
- package/lib/types/compat.d.ts +2 -2
- package/lib/types/fs.d.ts +3 -1
- package/lib/types/instructions.d.ts +6 -1
- package/lib/types/ops-compatibility.d.ts +34 -0
- package/lib/types/registry.d.ts +67 -8
- package/lib/types/review-context.d.ts +2 -0
- package/lib/types/roots.d.ts +114 -20
- package/lib/types/scope.d.ts +28 -2
- package/lib/workspace-files.js +3 -3
- package/lib/{workspace-routing-YPxaQ4V3.js → workspace-routing-D_qwMUh-.js} +4 -4
- package/locale/en.json +7 -0
- package/locale/zh.json +7 -0
- package/package.json +93 -82
- package/src/auto-review/README.en.md +1 -1
- package/src/auto-review/README.md +1 -1
package/lib/skills.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { t as wrapMethod } from "./method-wrapper-
|
|
1
|
+
import { t as wrapMethod } from "./method-wrapper-D4oUCsEF.js";
|
|
2
2
|
import { c as withRegistryRead } from "./registry-operation-C2ZV3Jhw.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as skillsMetadataValid } from "./metadata-
|
|
3
|
+
import { t as createInstructionMessage } from "./llm-message-CepyzEBQ.js";
|
|
4
|
+
import { n as skillsMetadataValid } from "./metadata-99jgViHQ.js";
|
|
5
|
+
import { a as skillOrigin, i as skillAgent, n as filesystemSkillsApi, o as volatileField, r as observedSkillOrigin, t as configValue } from "./skills-utyuvmwr.js";
|
|
5
6
|
import { constants, statSync } from "node:fs";
|
|
6
7
|
import { createHash } from "node:crypto";
|
|
7
8
|
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
@@ -10,108 +11,6 @@ import { canonicalPath } from "@deepseek-ai/dsh-sandbox";
|
|
|
10
11
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
12
|
import { lstat, open, readdir, stat } from "node:fs/promises";
|
|
12
13
|
import z from "@deepseek-ai/schemastery";
|
|
13
|
-
//#region \0@oxc-project+runtime@0.149.0/helpers/esm/usingCtx.js
|
|
14
|
-
function _usingCtx() {
|
|
15
|
-
var r = "function" == typeof SuppressedError ? SuppressedError : function(r, e) {
|
|
16
|
-
var n = Error();
|
|
17
|
-
return n.name = "SuppressedError", n.error = r, n.suppressed = e, n;
|
|
18
|
-
}, e = {}, n = [];
|
|
19
|
-
function using(r, e) {
|
|
20
|
-
if (null != e) {
|
|
21
|
-
if (Object(e) !== e) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
|
|
22
|
-
if (r) var o = e[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
|
|
23
|
-
if (void 0 === o && (o = e[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r)) var t = o;
|
|
24
|
-
if ("function" != typeof o) throw new TypeError("Object is not disposable.");
|
|
25
|
-
t && (o = function o() {
|
|
26
|
-
try {
|
|
27
|
-
t.call(e);
|
|
28
|
-
} catch (r) {
|
|
29
|
-
return Promise.reject(r);
|
|
30
|
-
}
|
|
31
|
-
}), n.push({
|
|
32
|
-
v: e,
|
|
33
|
-
d: o,
|
|
34
|
-
a: r
|
|
35
|
-
});
|
|
36
|
-
} else r && n.push({
|
|
37
|
-
d: e,
|
|
38
|
-
a: r
|
|
39
|
-
});
|
|
40
|
-
return e;
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
e,
|
|
44
|
-
u: using.bind(null, !1),
|
|
45
|
-
a: using.bind(null, !0),
|
|
46
|
-
d: function d() {
|
|
47
|
-
var o, t = this.e, s = 0;
|
|
48
|
-
function next() {
|
|
49
|
-
for (; o = n.pop();) try {
|
|
50
|
-
if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
|
|
51
|
-
if (o.d) {
|
|
52
|
-
var r = o.d.call(o.v);
|
|
53
|
-
if (o.a) return s |= 2, Promise.resolve(r).then(next, err);
|
|
54
|
-
} else s |= 1;
|
|
55
|
-
} catch (r) {
|
|
56
|
-
return err(r);
|
|
57
|
-
}
|
|
58
|
-
if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
|
|
59
|
-
if (t !== e) throw t;
|
|
60
|
-
}
|
|
61
|
-
function err(n) {
|
|
62
|
-
return t = t !== e ? new r(n, t) : n, next();
|
|
63
|
-
}
|
|
64
|
-
return next();
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
//#endregion
|
|
69
|
-
//#region src/compat/skills.ts
|
|
70
|
-
/** Never infer authority from cwd, a preset key, or a lookalike Agent. */
|
|
71
|
-
function skillAgent(ctx, options) {
|
|
72
|
-
const scope = options.scope;
|
|
73
|
-
if (typeof scope !== "object" || scope === null || !("id" in scope) || typeof scope.id !== "string") return void 0;
|
|
74
|
-
const agent = ctx.get("agents")?.get(scope.id);
|
|
75
|
-
return agent === scope ? agent : void 0;
|
|
76
|
-
}
|
|
77
|
-
function skillOrigin(ctx, options) {
|
|
78
|
-
const cwd = skillAgent(ctx, options)?.session.header.cwd;
|
|
79
|
-
return typeof cwd === "string" && cwd !== "" ? canonicalPath(cwd) : void 0;
|
|
80
|
-
}
|
|
81
|
-
/** Absence is optional; a present but broken module must fail visibly. */
|
|
82
|
-
async function filesystemSkillsApi() {
|
|
83
|
-
if (!isPackageInstalled("@deepseek-ai/dsh-skill-filesystem")) return void 0;
|
|
84
|
-
const api = await import("@deepseek-ai/dsh-skill-filesystem");
|
|
85
|
-
if (typeof api.FileSystemSkillProvider !== "function") throw new Error("multi-root skills: FileSystemSkillProvider is unavailable");
|
|
86
|
-
return api;
|
|
87
|
-
}
|
|
88
|
-
function volatileField(schema) {
|
|
89
|
-
const method = schema.volatile;
|
|
90
|
-
return typeof method === "function" ? method.call(schema) : schema;
|
|
91
|
-
}
|
|
92
|
-
function configValue(value) {
|
|
93
|
-
if (typeof value === "object" && value !== null && Symbol.for("cosmokit.volatile.write") in value) {
|
|
94
|
-
const get = value.get;
|
|
95
|
-
if (typeof get === "function") return get.call(value);
|
|
96
|
-
}
|
|
97
|
-
return value;
|
|
98
|
-
}
|
|
99
|
-
/** Cold Browser Catalog supplies a Session header, never a fabricated Agent. */
|
|
100
|
-
async function observedSkillOrigin(ctx, sessionId) {
|
|
101
|
-
try {
|
|
102
|
-
var _usingCtx$1 = _usingCtx();
|
|
103
|
-
const query = ctx.get("sessionQuery");
|
|
104
|
-
if (query === void 0) throw new Error("multi-root skills: SessionQuery is unavailable");
|
|
105
|
-
const cwd = _usingCtx$1.u(await query.observeSession(sessionId)).header.cwd;
|
|
106
|
-
if (typeof cwd !== "string" || cwd === "") throw new Error("multi-root skills: Session has no origin");
|
|
107
|
-
return canonicalPath(cwd);
|
|
108
|
-
} catch (_) {
|
|
109
|
-
_usingCtx$1.e = _;
|
|
110
|
-
} finally {
|
|
111
|
-
_usingCtx$1.d();
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
//#endregion
|
|
115
14
|
//#region src/skills/reader.ts
|
|
116
15
|
/** Constrain the native parser before discovery can read a candidate's body. */
|
|
117
16
|
function containsPath(root, target) {
|
|
@@ -29,7 +29,11 @@ export declare const snapshotSchema: z.ZodObject<{
|
|
|
29
29
|
invalid: "invalid";
|
|
30
30
|
}>;
|
|
31
31
|
detail: z.ZodOptional<z.ZodString>;
|
|
32
|
-
invalidReason: z.ZodOptional<z.
|
|
32
|
+
invalidReason: z.ZodOptional<z.ZodEnum<{
|
|
33
|
+
"membership-conflict": "membership-conflict";
|
|
34
|
+
"protected-path": "protected-path";
|
|
35
|
+
"primary-overlap": "primary-overlap";
|
|
36
|
+
}>>;
|
|
33
37
|
}, z.core.$strict>>;
|
|
34
38
|
available: z.ZodBoolean;
|
|
35
39
|
}, z.core.$strict>;
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
* @module @dsh-electron/dsh-plugin-multi-root-workspace/client/RootSwitcher
|
|
43
43
|
*/
|
|
44
44
|
import { type ReactNode } from 'react';
|
|
45
|
+
import type { NativeTreeRenderer } from '../compat/files-tree.ts';
|
|
45
46
|
import { type FilesTreeSurface } from './files-tree/adapter.tsx';
|
|
46
47
|
import { type OpenInAppAdapter } from './open-in-app/adapter.tsx';
|
|
47
48
|
import { type WorkspaceFoldersActionProps } from './WorkspaceFoldersAction.tsx';
|
|
@@ -61,6 +62,7 @@ export interface RootSwitcherProps extends Omit<WorkspaceFoldersActionProps, 'co
|
|
|
61
62
|
* all, which is the same absence upstream's own tree produces.
|
|
62
63
|
*/
|
|
63
64
|
readonly filesTree?: FilesTreeSurface | undefined;
|
|
65
|
+
readonly nativeTree?: NativeTreeRenderer | undefined;
|
|
64
66
|
}
|
|
65
67
|
/** The Files-header switcher: root menu, dialog entry, and the portal tree. */
|
|
66
68
|
export declare function RootSwitcher(props: RootSwitcherProps): ReactNode;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AutoReviewForm } from '../compat/auto-review-client.ts';
|
|
2
|
+
import type { Translate } from './WorkspaceFoldersAction.tsx';
|
|
3
|
+
/**
|
|
4
|
+
* The optional Auto Review row of the plugin settings card.
|
|
5
|
+
*
|
|
6
|
+
* Its switch is the Loader row's own enablement — the same write the Plugin
|
|
7
|
+
* Manager's row switch performs — so the card can never disagree with the row
|
|
8
|
+
* list about whether the companion is on. Feedback is a transient `Toast`
|
|
9
|
+
* banner, never inline text: state-driven messages (a failed read, an entry
|
|
10
|
+
* diagnostic) fire on entry and clear when their source resolves, while write
|
|
11
|
+
* outcomes report once and fade. The row stays hidden entirely on hosts
|
|
12
|
+
* without the `pluginManager` namespace or when the composition does not list
|
|
13
|
+
* the optional entry.
|
|
14
|
+
*/
|
|
15
|
+
export declare function AutoReviewSettingsCard({ form, t }: {
|
|
16
|
+
form: AutoReviewForm;
|
|
17
|
+
t: Translate;
|
|
18
|
+
}): import("react").JSX.Element | null;
|
|
@@ -3,6 +3,7 @@ import type { RemoteFailure } from '@deepseek-ai/dsh-api-remotes/client';
|
|
|
3
3
|
import type { PropsLocale, PropsStore, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
|
|
4
4
|
import type { TabId } from '@deepseek-ai/dsh-client-ui-dockkit';
|
|
5
5
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
6
|
+
import { type NativeTreeRenderer } from '../../compat/files-tree.ts';
|
|
6
7
|
import type { WorkspaceDirectoryEntry } from '@deepseek-ai/dsh-api-workspace-files/types';
|
|
7
8
|
import type { FilesInjected } from './face.ts';
|
|
8
9
|
import type { createFilesStore } from './store.ts';
|
|
@@ -23,6 +24,8 @@ export type FilesTreeProps = PropsStore<ReturnType<typeof createFilesStore>> & P
|
|
|
23
24
|
readonly signal: AbortSignal;
|
|
24
25
|
/** Open one `dsh-resource://file` address (the adapter's sidebarRight route). */
|
|
25
26
|
readonly onOpen: (address: string) => void;
|
|
27
|
+
/** Optional host-controlled tree Factory, available on the newer Files page. */
|
|
28
|
+
readonly nativeTree?: NativeTreeRenderer | undefined;
|
|
26
29
|
};
|
|
27
30
|
/**
|
|
28
31
|
* Order one level's entries for display: directories first, then everything
|
|
@@ -44,4 +47,4 @@ export declare function failureLine(t: TranslateNS<'sidebarFiles'>, failure: Rem
|
|
|
44
47
|
* has opened under it — the upstream body's scroll, seed, and render logic
|
|
45
48
|
* verbatim, with the root arriving as a prop instead of `useSessions(cwd)`.
|
|
46
49
|
*/
|
|
47
|
-
export declare function FilesTree({ tabId, sessionId, root, signal, useStore, actions, start, toggle, onOpen, t, }: FilesTreeProps): ReactNode;
|
|
50
|
+
export declare function FilesTree({ tabId, sessionId, root, signal, useStore, actions, start, toggle, onOpen, t, nativeTree, }: FilesTreeProps): ReactNode;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Dictionary namespace owned by upstream's plugin (verbatim). */
|
|
2
2
|
export declare const NS = "sidebarFiles";
|
|
3
3
|
/** Key domain of the `sidebarFiles` namespace (verbatim union of upstream's zh keys). */
|
|
4
|
-
export type SidebarFilesKey = 'shortcut.noSession' | 'type.label' | 'guide.title' | 'guide.description' | 'loading' | 'empty' | 'truncated' | 'noWorkspace' | 'reload' | 'autoRefresh' | 'autoRefresh.enable' | 'autoRefresh.disable' | 'entry.other' | 'error.notFound' | 'error.outsideWorkspace' | 'error.notDirectory' | 'error.unavailable';
|
|
4
|
+
export type SidebarFilesKey = 'shortcut.noSession' | 'type.label' | 'guide.title' | 'guide.description' | 'loading' | 'empty' | 'truncated' | 'noWorkspace' | 'reload' | 'autoRefresh' | 'autoRefresh.enable' | 'autoRefresh.disable' | 'entry.other' | 'entry.noViewer' | 'navigator.show' | 'navigator.hide' | 'navigator.resize' | 'error.notFound' | 'error.outsideWorkspace' | 'error.notDirectory' | 'error.unavailable';
|
|
5
5
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
6
6
|
interface LocaleNamespaceMap {
|
|
7
7
|
/** File-tree type name, guide entry, row states, and failure lines. */
|
|
@@ -15,6 +15,22 @@ export declare const zh: {
|
|
|
15
15
|
'skills.globalEnable': string;
|
|
16
16
|
'skills.globalHint': string;
|
|
17
17
|
'skills.settingsFailed': string;
|
|
18
|
+
'autoReview.title': string;
|
|
19
|
+
'autoReview.experimental': string;
|
|
20
|
+
'autoReview.hint': string;
|
|
21
|
+
'autoReview.loadFailed': string;
|
|
22
|
+
'autoReview.restartRequired': string;
|
|
23
|
+
'autoReview.settingsFailed': string;
|
|
24
|
+
'ops.compatibilityEnable': string;
|
|
25
|
+
'ops.experimental': string;
|
|
26
|
+
'ops.compatibilityHint': string;
|
|
27
|
+
'ops.settingsFailed': string;
|
|
28
|
+
'ops.confirmTitle': string;
|
|
29
|
+
'ops.confirmDescription': string;
|
|
30
|
+
'ops.confirmAcknowledge': string;
|
|
31
|
+
'ops.confirmCancel': string;
|
|
32
|
+
'ops.confirmClose': string;
|
|
33
|
+
'ops.confirmEnable': string;
|
|
18
34
|
'skills.userOnly': string;
|
|
19
35
|
'panel.skills': string;
|
|
20
36
|
'panel.skillsEnabled': string;
|
|
@@ -59,6 +75,7 @@ export declare const zh: {
|
|
|
59
75
|
'panel.copied': string;
|
|
60
76
|
'panel.reveal': string;
|
|
61
77
|
'panel.reRegister': string;
|
|
78
|
+
'panel.redirectedHint': string;
|
|
62
79
|
'panel.moveUp': string;
|
|
63
80
|
'panel.moveDown': string;
|
|
64
81
|
'access.inherit': string;
|
|
@@ -95,6 +112,9 @@ export declare const zh: {
|
|
|
95
112
|
'error.copy-failed': string;
|
|
96
113
|
'error.session-not-found': string;
|
|
97
114
|
'error.unsupported-path': string;
|
|
115
|
+
'error.protected-path': string;
|
|
116
|
+
'error.protected-boundary-unknown': string;
|
|
117
|
+
'error.revive-target-changed': string;
|
|
98
118
|
'error.fallback': string;
|
|
99
119
|
};
|
|
100
120
|
/** The canonical key set. */
|
|
@@ -104,6 +124,22 @@ export declare const en: {
|
|
|
104
124
|
'skills.globalEnable': string;
|
|
105
125
|
'skills.globalHint': string;
|
|
106
126
|
'skills.settingsFailed': string;
|
|
127
|
+
'autoReview.title': string;
|
|
128
|
+
'autoReview.experimental': string;
|
|
129
|
+
'autoReview.hint': string;
|
|
130
|
+
'autoReview.loadFailed': string;
|
|
131
|
+
'autoReview.restartRequired': string;
|
|
132
|
+
'autoReview.settingsFailed': string;
|
|
133
|
+
'ops.compatibilityEnable': string;
|
|
134
|
+
'ops.experimental': string;
|
|
135
|
+
'ops.compatibilityHint': string;
|
|
136
|
+
'ops.settingsFailed': string;
|
|
137
|
+
'ops.confirmTitle': string;
|
|
138
|
+
'ops.confirmDescription': string;
|
|
139
|
+
'ops.confirmAcknowledge': string;
|
|
140
|
+
'ops.confirmCancel': string;
|
|
141
|
+
'ops.confirmClose': string;
|
|
142
|
+
'ops.confirmEnable': string;
|
|
107
143
|
'skills.userOnly': string;
|
|
108
144
|
'panel.skills': string;
|
|
109
145
|
'panel.skillsEnabled': string;
|
|
@@ -148,6 +184,7 @@ export declare const en: {
|
|
|
148
184
|
'panel.copied': string;
|
|
149
185
|
'panel.reveal': string;
|
|
150
186
|
'panel.reRegister': string;
|
|
187
|
+
'panel.redirectedHint': string;
|
|
151
188
|
'panel.moveUp': string;
|
|
152
189
|
'panel.moveDown': string;
|
|
153
190
|
'access.inherit': string;
|
|
@@ -184,6 +221,9 @@ export declare const en: {
|
|
|
184
221
|
'error.copy-failed': string;
|
|
185
222
|
'error.session-not-found': string;
|
|
186
223
|
'error.unsupported-path': string;
|
|
224
|
+
'error.protected-path': string;
|
|
225
|
+
'error.protected-boundary-unknown': string;
|
|
226
|
+
'error.revive-target-changed': string;
|
|
187
227
|
'error.fallback': string;
|
|
188
228
|
};
|
|
189
229
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Dictionary namespace owned by upstream's plugin (verbatim). */
|
|
2
2
|
export declare const NS = "open-in-app";
|
|
3
3
|
/** Key domain of the `open-in-app` namespace (verbatim union of upstream's zh keys). */
|
|
4
|
-
export type OpenInAppKey = 'open.title' | 'path.appDefault' | 'path.appsError' | 'shortcut.busy' | 'shortcut.unavailable' | 'open.tooltip' | 'path.open' | 'path.more' | 'path.reveal' | 'path.opened' | 'path.revealed' | 'path.openError' | 'path.revealError' | 'app.cursor' | 'app.vscode' | 'app.vscodeinsiders' | 'app.windsurf' | 'app.zed' | 'app.sublimetext' | 'app.xcode' | 'app.androidstudio' | 'app.intellij' | 'app.pycharm' | 'app.webstorm' | 'app.phpstorm' | 'app.goland' | 'app.rider' | 'app.rustrover' | 'app.fork' | 'app.sourcetree' | 'app.github' | 'app.tower' | 'app.gitkraken' | 'app.smartgit' | 'app.sublimemerge' | 'app.ghostty' | 'app.warp' | 'app.iterm' | 'app.kitty' | 'app.terminal' | 'app.windowsterminal' | 'app.gitbash' | 'app.gnometerminal' | 'app.konsole' | 'app.finder' | 'app.explorer' | 'app.filemanager';
|
|
4
|
+
export type OpenInAppKey = 'menu.openInSidebar' | 'menu.openInFloat' | 'menu.finder' | 'menu.reveal' | 'menu.defaultApp' | 'menu.external' | 'menu.copyLink' | 'menu.copyPath' | 'menu.copyDirectoryPath' | 'menu.copied' | 'menu.copyFailed' | 'open.title' | 'path.appDefault' | 'path.appsError' | 'shortcut.busy' | 'shortcut.unavailable' | 'open.tooltip' | 'path.open' | 'path.more' | 'path.reveal' | 'path.opened' | 'path.revealed' | 'path.openError' | 'path.revealError' | 'app.cursor' | 'app.vscode' | 'app.vscodeinsiders' | 'app.windsurf' | 'app.zed' | 'app.sublimetext' | 'app.xcode' | 'app.androidstudio' | 'app.intellij' | 'app.pycharm' | 'app.webstorm' | 'app.phpstorm' | 'app.goland' | 'app.rider' | 'app.rustrover' | 'app.fork' | 'app.sourcetree' | 'app.github' | 'app.tower' | 'app.gitkraken' | 'app.smartgit' | 'app.sublimemerge' | 'app.ghostty' | 'app.warp' | 'app.iterm' | 'app.kitty' | 'app.terminal' | 'app.windowsterminal' | 'app.gitbash' | 'app.gnometerminal' | 'app.konsole' | 'app.finder' | 'app.explorer' | 'app.filemanager';
|
|
5
5
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
6
6
|
interface LocaleNamespaceMap {
|
|
7
7
|
/** Session-header "open workspace in application" copy (upstream declaration). */
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SkillsForm } from '../compat/skills-client.ts';
|
|
2
|
+
import type { Translate } from './WorkspaceFoldersAction.tsx';
|
|
3
|
+
export declare function OpsCompatibilitySettingsCard({ form, t }: {
|
|
4
|
+
form: SkillsForm;
|
|
5
|
+
t: Translate;
|
|
6
|
+
}): import("react").JSX.Element | null;
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
2
|
import { type SkillsForm } from '../compat/skills-client.ts';
|
|
3
|
+
import { type AutoReviewForm } from '../compat/auto-review-client.ts';
|
|
3
4
|
import type { Translate } from './WorkspaceFoldersAction.tsx';
|
|
4
5
|
interface CardProps {
|
|
5
6
|
form: SkillsForm;
|
|
6
7
|
t: Translate;
|
|
7
8
|
}
|
|
8
9
|
export declare function SkillsSettingsCard({ form, t }: CardProps): import("react").JSX.Element;
|
|
10
|
+
/**
|
|
11
|
+
* The bundle's one `plugins.bundle.config` cell: every plugin-level switch the
|
|
12
|
+
* package offers, in display order. Each row owns its own form and write path —
|
|
13
|
+
* Skills and OPS through their settings namespaces, Auto Review through the Plugin
|
|
14
|
+
* Manager's Loader-row enablement — so one cell never serializes their state.
|
|
15
|
+
*/
|
|
16
|
+
export declare function BundleSettingsCard({ form, autoReviewForm, opsForm, t }: {
|
|
17
|
+
form?: SkillsForm | undefined;
|
|
18
|
+
autoReviewForm?: AutoReviewForm | undefined;
|
|
19
|
+
opsForm?: SkillsForm | undefined;
|
|
20
|
+
t: Translate;
|
|
21
|
+
}): import("react").JSX.Element;
|
|
9
22
|
export declare function installSkillsSettingsCard(ctx: Context, t: Translate): void;
|
|
10
23
|
export {};
|
|
@@ -11,4 +11,4 @@
|
|
|
11
11
|
* @module @dsh-electron/dsh-plugin-multi-root-workspace/client/styles
|
|
12
12
|
*/
|
|
13
13
|
/** The stylesheet text; every class is prefixed `mrfw-` to stay collision-free. */
|
|
14
|
-
export declare const STYLES = "\n/* Sidebar footer row, mirroring the host ui-settings-general trigger: the row\n * wrapper overhangs each side by 2px (width calc(100% + 4px) against the\n * shell's 12px inline padding) so the icon's ink line lands at 18px from the\n * column edge \u2014 exactly where the Settings gear below sits. */\n.mrfw-triggerRow {\n flex: none;\n display: flex;\n align-items: center;\n gap: 8px;\n width: calc(100% + 4px);\n margin: 4px -2px;\n}\n\n.mrfw-triggerRow.mrfw-railRow {\n width: 36px;\n margin: 8px 0 10px;\n}\n\n.mrfw-trigger {\n box-sizing: border-box;\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n width: auto;\n height: 42px;\n margin: 0;\n padding: 0 10px 0 8px;\n border: none;\n border-radius: 12px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 14px;\n line-height: 22px;\n text-align: left;\n cursor: pointer;\n overflow: hidden;\n transition: background-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-trigger:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.mrfw-triggerIcon {\n flex: none;\n display: inline-flex;\n}\n\n.mrfw-triggerLabel {\n overflow: hidden;\n white-space: nowrap;\n}\n\n.mrfw-triggerRail {\n flex: none;\n width: 36px;\n height: 36px;\n margin: 0;\n padding: 0;\n gap: 0;\n border-radius: 50%;\n justify-content: center;\n}\n\n/* Icon-only launcher inside the upstream Files tab header. Upstream's\n FilesBody renders .header as one flat flex row \u2014 PathLabel, then the\n reload button, then the files.actions slot occupants \u2014 and each of those\n children carries a stable data-files-* attribute on the flex item itself\n (data-files-root on the pane, data-files-path, data-files-reload).\n A registration order sorts only INSIDE the actions slot and can never\n overtake the reload button, so the launcher is moved with the flex order\n property instead: this wrapper is the slot's root element and therefore a\n direct flex item of .header, and order: -1 puts it ahead of every\n order-0 sibling while the :has() rule below keeps the path first. */\n.mrfw-fileLauncher {\n order: -1;\n flex: none;\n display: flex;\n align-items: center;\n}\n\n/* Pin the upstream path label ahead of the launcher \u2014 but only while this\n plugin is in the row: the :has() guard keeps a rule that names an\n upstream element inert whenever the launcher is absent. The\n :not([data-files-entry]) qualifier is load-bearing, not decorative:\n upstream puts data-files-path on EVERY tree row too (the row's own\n absolute path), so an unqualified selector would match the whole tree,\n not just the header's PathLabel. Both selectors depend on upstream's DOM\n shape, which is not part of the slot contract; if it changes, the rules\n simply stop matching and the launcher falls back to its in-slot position \u2014\n a silent degradation, never a broken header. */\n[data-files-root]:has(.mrfw-fileLauncher) [data-files-path]:not([data-files-entry]) {\n order: -2;\n}\n\n/* The root switcher is the launcher's grown-up form on runtimes whose\n files.actions owner carries absolutePath. It takes the path label's flex\n position and stretch: order: -1 ahead of every order-0 sibling, and a\n growing min-width:0 item so both the trigger label and the PathLabel\n inside it can ellipsize instead of pushing the header controls out. */\n.mrfw-rootSwitcher {\n order: -1;\n flex: 1 1 auto;\n min-width: 0;\n display: flex;\n align-items: center;\n /* Same 4px the upstream .header puts between its own flex items, so the\n takeover controls (reload, open-in-app fork) sit at the same offsets the\n hidden native ones did \u2014 no drift between primary and additional state. */\n gap: 4px;\n}\n\n/* While the switcher exists it hides the upstream path label \u2014 the\n :has() guard again keeps the upstream-naming rule inert unless this\n plugin is actually in the row. The switcher draws its own PathLabel of\n the selected root next to the trigger (className mrfw-switcherPath, no\n data-files-* attributes), so the header keeps a path in the same spot.\n :not([data-files-entry]) is what confines this rule to the header:\n every tree row carries data-files-path with its own path as the value,\n and only the PathLabel carries it bare. Without the qualifier this\n display:none would blank the entire native tree. */\n[data-files-root]:has(.mrfw-rootSwitcher) [data-files-path]:not([data-files-entry]) {\n display: none;\n}\n\n/* While the switcher names an additional root, the native tree body and its\n reload hide: the reload refreshes the very tree that is no longer\n visible, and the plugin's forked tree is portaled in as the body's sibling.\n The header still offers a reload \u2014 the switcher's own .mrfw-switcherReload\n calls the forked face's refresh. The native tree keeps watching in the\n background, so switching back to the primary root restores it instantly. */\n[data-files-root]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-files-body],\n[data-files-root]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-files-reload] {\n display: none;\n}\n\n/* While the switcher names an additional root, the native open-in-app split\n button hides too: its slot props carry the pane's primary root, so it\n would always open the primary root no matter what the switcher selected.\n The header gets the plugin's own fork of that same control instead (the\n open-in-app directory), wired to the selected root.\n\n The slot's render site is wrapped in the renderer's own anchor \u2014\n <div data-slot=\"sidebar.right.tab.files.actions\" style=\"display:contents\">\n \u2014 so the header's flex items inside it are the occupants themselves, and\n the native item is the ui-primitives Menu anchor span wrapping the marked\n .split. The first selector hides that occupant item through the data-slot\n anchor: hiding only the inner control would leave the empty anchor span\n as a zero-width flex item whose header gap pushes the fork 4px left of\n the native position. The wrapper itself can never be the target \u2014 its\n inline display:contents beats any stylesheet rule, and hiding it would\n take the switcher with it. The second selector is the fallback for an\n upstream that moves the attribute off the item. The fork survives both:\n the only data-open-target inside .mrfw-rootSwitcher is its own\n .mrfw-openSplit, which :not() excludes. */\n[data-files-root]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-slot=\"sidebar.right.tab.files.actions\"] > *:has([data-open-target=\"directory\"]:not(.mrfw-openSplit)),\n[data-files-root]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-open-target=\"directory\"]:not(.mrfw-openSplit) {\n display: none;\n}\n\n/* The trigger borrows the path label's look: quiet text with a folder\n glyph, the hover of the neighboring header buttons, and the overflow\n behavior PathLabel itself uses in a narrow header. It may shrink but\n never grows \u2014 the PathLabel after it owns the free header space. */\n.mrfw-rootSwitchBtn {\n flex: 0 1 auto;\n min-width: 0;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 28px;\n margin: 0;\n padding: 0 4px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: inherit;\n line-height: 20px;\n text-align: left;\n cursor: pointer;\n transition: background-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-rootSwitchBtn:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.mrfw-rootSwitchBtn .mrfw-triggerIcon {\n color: var(--dsw-alias-label-secondary);\n}\n\n.mrfw-rootSwitchLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mrfw-rootSwitchChevron {\n margin-left: auto;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* The selected root's full path sits between the trigger and the reload \u2014\n the very PathLabel upstream draws there, so it brings its own grow,\n left-clip and hover-title behavior; only the gutters are ours. The right\n margin plus the container gap reproduces upstream's .path margin-right\n 12px + header gap 4px; the left gutter comes from the same container gap. */\n.mrfw-switcherPath {\n margin: 0 12px 0 0;\n}\n\n/* The takeover's own reload, standing exactly where the hidden native one\n did: the upstream .tool recipe verbatim (28px hit area, 15px glyph,\n secondary voice, hover fills). It calls the forked face's refresh \u2014 an\n in-place re-list, not a remount. */\n.mrfw-switcherReload {\n flex: none;\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: var(--dsw-radius-sm);\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n line-height: 1;\n cursor: pointer;\n}\n\n.mrfw-switcherReload:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n/* \u2500\u2500 files-tree fork (verbatim rules, renamed classes) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Copied from upstream's FilesBody.module.css (ui-sidebar-files @\n 0.2.2-alpha.2) with local names mapped to mrfw-ft* so the rules cannot\n collide with host DOM \u2014 and so the fork's own body (which must NOT carry\n data-files-body) stays visible while the rules above hide the native one.\n The header-only rules (root/header/path/tool/status/statusLine/titleIcon)\n belong to the upstream shell this fork drops and are not mapped. Fork sync\n re-diffs the upstream file and re-applies the rename \u2014 see\n src/client/files-tree/FORK.md. */\n\n/* The pane's own .root already supplies the flex column, color, and font;\n the fork's body takes the same stretch item the hidden native body held,\n including the workspace list's 2px scrollbar offset and stable gutter. */\n.mrfw-ftBody {\n flex: 1 1 auto;\n min-height: 0;\n margin-right: 2px;\n padding: 8px 0 8px 8px;\n overflow: auto;\n scrollbar-gutter: stable;\n}\n\n.mrfw-ftBody::-webkit-scrollbar-track {\n margin: 2px;\n}\n\n.mrfw-ftLevel {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.mrfw-ftLevel .mrfw-ftLevel {\n padding-left: 18px;\n}\n\n.mrfw-ftItem {\n margin: 0;\n padding: 0;\n}\n\n/* Rows abut, so the hover fill is the whole row; the tree's air is this\n inset, not a gap between rows. */\n.mrfw-ftRow {\n display: flex;\n gap: 6px;\n align-items: center;\n width: 100%;\n min-width: 0;\n padding: 5px 10px;\n color: inherit;\n font: inherit;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: var(--dsw-radius-md);\n cursor: pointer;\n}\n\n@media (hover: hover) {\n .mrfw-ftRow:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n }\n}\n\n/* The folder glyph rides the tertiary ink, as the workspace tree's does. */\n.mrfw-ftIcon {\n flex: 0 0 auto;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* The type's coloured sheet at the folder glyph's 16px; its colour is its own. */\n.mrfw-ftFileIcon {\n flex: 0 0 auto;\n}\n\n.mrfw-ftName {\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n/* Neither a file nor a directory: shown so the directory is reported whole,\n greyed so nobody tries to open it. */\n.mrfw-ftOther {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n\n@media (hover: hover) {\n .mrfw-ftOther:hover {\n background: transparent;\n }\n}\n\n.mrfw-ftNote {\n margin: 0;\n padding: 3px 10px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n\n/* \u2500\u2500 open-in-app fork (verbatim rules, renamed classes) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Copied from upstream's OpenTargetButton.module.css\n (dsh-client-ui-open-in-app @ 0.2.1-alpha.2) with local names mapped to\n mrfw-open* so the rules cannot collide with host DOM. Fork sync re-diffs\n the upstream file and re-applies the rename \u2014 see\n src/client/open-in-app/FORK.md. */\n\n/* Sized to sit in the document header's 24px control row beside its round\n icon buttons: a hairline pill with a 12px label and a narrow chevron half. */\n.mrfw-openMenuAnchor {\n display: inline-flex;\n flex: none;\n align-self: center;\n}\n\n.mrfw-openSplit {\n display: inline-flex;\n align-items: stretch;\n box-sizing: border-box;\n height: 24px;\n overflow: hidden;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-sm);\n font-family: var(--dsw-font-family);\n}\n\n.mrfw-openMain,\n.mrfw-openChevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 0;\n background: none;\n color: var(--dsw-alias-label-primary);\n font-size: 11px;\n line-height: 16px;\n white-space: nowrap;\n cursor: pointer;\n}\n\n.mrfw-openMain {\n gap: 4px;\n padding: 3px 5px;\n}\n\n.mrfw-openChevron {\n padding: 3px 4px 3px 3px;\n border-left: 0.5px solid var(--dsw-alias-border-l4);\n color: var(--dsw-alias-label-secondary);\n}\n\n.mrfw-openMain:hover:not(:disabled),\n.mrfw-openMain:focus-visible,\n.mrfw-openChevron:hover:not(:disabled),\n.mrfw-openChevron:focus-visible {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n/* Pending disables clicks without a restyle; only hover feedback pauses. */\n.mrfw-openMain:disabled,\n.mrfw-openChevron:disabled {\n cursor: default;\n}\n\n.mrfw-openAppIcon {\n object-fit: contain;\n}\n\n/* The unavailable preview emphasizes the same actions with a labeled button. */\n.mrfw-openSplit[data-size='large'] {\n height: 36px;\n border-radius: var(--dsw-radius-md);\n border-color: var(--dsw-alias-border-l2);\n}\n\n.mrfw-openSplit[data-size='large'] .mrfw-openMain {\n gap: 6px;\n padding: 6px 14px;\n font-size: 14px;\n}\n\n.mrfw-openSplit[data-size='large'] .mrfw-openChevron {\n padding: 6px 10px;\n}\n\n.mrfw-openSkeleton { display: inline-block; flex: none; border-radius: var(--dsw-radius-xs); background: var(--dsw-alias-interactive-bg-hover); }\n\n.mrfw-overlay {\n position: fixed;\n inset: 0;\n z-index: 1000;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n}\n\n.mrfw-mask {\n position: absolute;\n inset: 0;\n background: var(--dsw-alias-bg-mask-1);\n backdrop-filter: var(--dsw-mask-blur);\n}\n\n.mrfw-dialog {\n position: relative;\n z-index: 1;\n display: flex;\n flex-direction: column;\n width: min(640px, 100%);\n max-height: 100%;\n overflow: hidden;\n border: none;\n border-radius: 24px;\n background: var(--dsw-alias-bg-layer-2);\n box-shadow: var(--dsw-elevation-prominent);\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n outline: none;\n}\n\n.mrfw-header {\n flex: none;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 22px 14px 12px 24px;\n}\n\n.mrfw-title {\n margin: 0;\n font-size: 16px;\n line-height: 24px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.mrfw-close {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 8px;\n background: transparent;\n cursor: pointer;\n color: var(--dsw-alias-label-secondary);\n transition: background-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-close:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.mrfw-body {\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow-y: auto;\n padding: 0 24px 24px;\n}\n\n.mrfw-alert {\n margin: 0 0 8px;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.mrfw-section {\n display: flex;\n flex-direction: column;\n}\n\n.mrfw-section + .mrfw-section {\n margin-top: 8px;\n}\n\n.mrfw-sectionTitleRow {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding: 8px 0 4px;\n}\n\n.mrfw-sectionTitle {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.mrfw-sectionNote {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.mrfw-row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n padding: 12px 0;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n.mrfw-rowBare {\n border-bottom: none;\n}\n\n/* A root entry's two lines: the display name on top, the absolute path under\n it in the tertiary voice (the workspace rows recipe of the host sidebar). */\n/* Match upstream General Settings' DeveloperToolsRow layout. */\n.mrfw-skillsSettings {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n padding: 16px 0;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n.mrfw-skillsSettingsText { min-width: 0; }\n.mrfw-skillsSettingsTitle { font-size: 14px; line-height: 20px; }\n.mrfw-skillsSettingsDescription {\n margin-top: 4px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 18px;\n}\n.mrfw-rootText {\n display: flex;\n flex: 1 1 240px;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n/* Keep status tags and permission glyphs visible beside the alias, wrapping\n onto another line when the dialog is narrow. */\n.mrfw-rootName {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n min-width: 0;\n font-size: 14px;\n line-height: 20px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.mrfw-rootNameText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mrfw-rootPath {\n font-family: var(--ds-font-family-code);\n font-size: 12px;\n line-height: 18px;\n word-break: break-all;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* The path doubles as the copy control: an unstyled button that keeps the\n text recipe and makes the whole string clickable \u2014 the whole region, not\n just the icon, copies on click. */\n.mrfw-pathCopy {\n display: block;\n width: 100%;\n padding: 0;\n border: 0;\n background: transparent;\n text-align: left;\n cursor: pointer;\n}\n\n/* The trailing icon stays in flow but invisible until the path is hovered\n or focused: appearing never re-wraps the text, and the icon inherits the\n path's own tertiary ink. */\n.mrfw-pathCopyIcon {\n display: inline-flex;\n margin-left: 4px;\n vertical-align: -2px;\n opacity: 0;\n transition: opacity var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-pathCopy:hover .mrfw-pathCopyIcon,\n.mrfw-pathCopy:focus-visible .mrfw-pathCopyIcon {\n opacity: 1;\n}\n\n.mrfw-note {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.mrfw-stateWarn {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.mrfw-btn {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 28px;\n padding: 0 10px;\n border: none;\n border-radius: 14px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n transition: background-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-btn[aria-busy='true'] {\n cursor: wait;\n}\n\n.mrfw-btn:disabled {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.mrfw-btnGhost:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.mrfw-btnGhost:active:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-active);\n}\n\n/* The solid destructive action of the capsule family: the upgrade confirm's\n red button. state-error-primary is the error ink upstream also uses as a\n fill (StateDot); the hover mixes in the host's primary label token to\n follow its theme and contrast choices. Neither color is a guessed token:\n an undefined var() would fall back\n to transparent and white-out the whole button. */\n.mrfw-btnDanger {\n background: var(--dsw-alias-state-error-primary);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.mrfw-btnDanger:hover:not(:disabled) {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 85%, var(--dsw-alias-label-primary));\n}\n\n.mrfw-btnOutline {\n border: 0.5px solid var(--dsw-alias-border-l3);\n background: transparent;\n}\n\n.mrfw-btnOutline:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.mrfw-btnPrimary {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.mrfw-btnPrimary:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n/* One icon-only action: a square of the capsule family, meaning in title.\n Declared after the .mrfw-btn family so its padding wins the cascade tie:\n the capsule's 0 10px padding would otherwise squeeze the icon glyph. */\n.mrfw-iconBtn {\n width: 28px;\n padding: 0;\n border-radius: 8px;\n}\n\n.mrfw-input {\n flex: 1 1 220px;\n min-width: 0;\n height: 32px;\n padding: 0 8px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 14px;\n line-height: 22px;\n outline: none;\n transition: border-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-input:focus {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.mrfw-input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n.mrfw-inputInline {\n flex: 1 1 auto;\n}\n\n.mrfw-accessSelect {\n flex: 0 0 auto;\n}\n\n/* The access dropdown's capsule trigger: the Menu anchor wrapper is the flex\n item, the button inside keeps the control row's 32px capsule recipe. */\n.mrfw-accessTrigger {\n padding: 0 12px;\n}\n\n.mrfw-cwdTag {\n flex: none;\n padding: 0 6px;\n border-radius: 4px;\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n line-height: 18px;\n}\n\n.mrfw-accessBadge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.mrfw-accessBadge {\n flex: none;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.mrfw-aliasEditor {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n flex-basis: 100%;\n}\n\n.mrfw-actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n margin-top: 16px;\n padding-top: 16px;\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n/* One control row, one height: the capsule buttons match the 32px input. */\n.mrfw-actions .mrfw-btn {\n height: 32px;\n border-radius: 16px;\n}\n\n.mrfw-actions .mrfw-iconBtn {\n width: 32px;\n}\n";
|
|
14
|
+
export declare const STYLES = "\n/* Sidebar footer row, mirroring the host ui-settings-general trigger: the row\n * wrapper overhangs each side by 2px (width calc(100% + 4px) against the\n * shell's 12px inline padding) so the icon's ink line lands at 18px from the\n * column edge \u2014 exactly where the Settings gear below sits. */\n.mrfw-triggerRow {\n flex: none;\n display: flex;\n align-items: center;\n gap: 8px;\n width: calc(100% + 4px);\n margin: 4px -2px;\n}\n\n.mrfw-triggerRow.mrfw-railRow {\n width: 36px;\n margin: 8px 0 10px;\n}\n\n.mrfw-trigger {\n box-sizing: border-box;\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n width: auto;\n height: 42px;\n margin: 0;\n padding: 0 10px 0 8px;\n border: none;\n border-radius: 12px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 14px;\n line-height: 22px;\n text-align: left;\n cursor: pointer;\n overflow: hidden;\n transition: background-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-trigger:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.mrfw-triggerIcon {\n flex: none;\n display: inline-flex;\n}\n\n.mrfw-triggerLabel {\n overflow: hidden;\n white-space: nowrap;\n}\n\n.mrfw-triggerRail {\n flex: none;\n width: 36px;\n height: 36px;\n margin: 0;\n padding: 0;\n gap: 0;\n border-radius: 50%;\n justify-content: center;\n}\n\n/* Icon-only launcher inside the upstream Files tab header. Upstream's\n FilesBody renders .header as one flat flex row \u2014 PathLabel, then the\n reload button, then the files.actions slot occupants \u2014 and each of those\n children carries a stable data-files-* attribute on the flex item itself\n (data-files-root on the pane, data-files-path, data-files-reload).\n A registration order sorts only INSIDE the actions slot and can never\n overtake the reload button, so the launcher is moved with the flex order\n property instead: this wrapper is the slot's root element and therefore a\n direct flex item of .header, and order: -1 puts it ahead of every\n order-0 sibling while the :has() rule below keeps the path first. */\n.mrfw-fileLauncher {\n order: -1;\n flex: none;\n display: flex;\n align-items: center;\n}\n\n/* Pin the upstream path label ahead of the launcher \u2014 but only while this\n plugin is in the row: the :has() guard keeps a rule that names an\n upstream element inert whenever the launcher is absent. The\n :not([data-files-entry]) qualifier is load-bearing, not decorative:\n upstream puts data-files-path on EVERY tree row too (the row's own\n absolute path), so an unqualified selector would match the whole tree,\n not just the header's PathLabel. Both selectors depend on upstream's DOM\n shape, which is not part of the slot contract; if it changes, the rules\n simply stop matching and the launcher falls back to its in-slot position \u2014\n a silent degradation, never a broken header. */\n[data-files-root]:has(.mrfw-fileLauncher) [data-files-path]:not([data-files-entry]) {\n order: -2;\n}\n\n/* The root switcher is the launcher's grown-up form on runtimes whose\n files.actions owner carries absolutePath. It takes the path label's flex\n position and stretch: order: -1 ahead of every order-0 sibling, and a\n growing min-width:0 item so both the trigger label and the PathLabel\n inside it can ellipsize instead of pushing the header controls out. */\n.mrfw-rootSwitcher {\n order: -1;\n flex: 1 1 auto;\n min-width: 0;\n display: flex;\n align-items: center;\n /* Same 4px the upstream .header puts between its own flex items, so the\n takeover controls (reload, open-in-app fork) sit at the same offsets the\n hidden native ones did \u2014 no drift between primary and additional state. */\n gap: 4px;\n}\n\n/* While the switcher exists it hides the upstream path label \u2014 the\n :has() guard again keeps the upstream-naming rule inert unless this\n plugin is actually in the row. The switcher draws its own PathLabel of\n the selected root next to the trigger (className mrfw-switcherPath, no\n data-files-* attributes), so the header keeps a path in the same spot.\n :not([data-files-entry]) is what confines this rule to the header:\n every tree row carries data-files-path with its own path as the value,\n and only the PathLabel carries it bare. Without the qualifier this\n display:none would blank the entire native tree. */\n[data-files-root]:has(.mrfw-rootSwitcher) [data-files-path]:not([data-files-entry]) {\n display: none;\n}\n\n/* While the switcher names an additional root, the native tree body and its\n reload hide: the reload refreshes the very tree that is no longer\n visible, and the plugin's forked tree is portaled in as the body's sibling.\n The header still offers a reload \u2014 the switcher's own .mrfw-switcherReload\n calls the forked face's refresh. The native tree keeps watching in the\n background, so switching back to the primary root restores it instantly. */\n[data-files-root]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-files-body],\n[data-files-root]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-files-reload] {\n display: none;\n}\n\n/* Newer Files pages place the navigator beside the header instead of\n wrapping both in data-files-root. Target the page without hiding the\n portaled replacement or any of its rows. */\n[data-files-page]:has(.mrfw-fileLauncher) [data-files-path]:not([data-files-entry]) { order: -2; }\n[data-files-page]:has(.mrfw-rootSwitcher) [data-files-path]:not([data-files-entry]) { display: none; }\n[data-files-page]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-files-content],\n[data-files-page]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-files-reload] { display: none; }\n[data-files-page]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-slot=\"sidebar.right.tab.files.actions\"] > *:has([data-open-target=\"directory\"]:not(.mrfw-openSplit)),\n[data-files-page]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-open-target=\"directory\"]:not(.mrfw-openSplit) { display: none; }\n\n/* While the switcher names an additional root, the native open-in-app split\n button hides too: its slot props carry the pane's primary root, so it\n would always open the primary root no matter what the switcher selected.\n The header gets the plugin's own fork of that same control instead (the\n open-in-app directory), wired to the selected root.\n\n The slot's render site is wrapped in the renderer's own anchor \u2014\n <div data-slot=\"sidebar.right.tab.files.actions\" style=\"display:contents\">\n \u2014 so the header's flex items inside it are the occupants themselves, and\n the native item is the ui-primitives Menu anchor span wrapping the marked\n .split. The first selector hides that occupant item through the data-slot\n anchor: hiding only the inner control would leave the empty anchor span\n as a zero-width flex item whose header gap pushes the fork 4px left of\n the native position. The wrapper itself can never be the target \u2014 its\n inline display:contents beats any stylesheet rule, and hiding it would\n take the switcher with it. The second selector is the fallback for an\n upstream that moves the attribute off the item. The fork survives both:\n the only data-open-target inside .mrfw-rootSwitcher is its own\n .mrfw-openSplit, which :not() excludes. */\n[data-files-root]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-slot=\"sidebar.right.tab.files.actions\"] > *:has([data-open-target=\"directory\"]:not(.mrfw-openSplit)),\n[data-files-root]:has(.mrfw-rootSwitcher[data-root-kind=\"additional\"]) [data-open-target=\"directory\"]:not(.mrfw-openSplit) {\n display: none;\n}\n\n/* The trigger borrows the path label's look: quiet text with a folder\n glyph, the hover of the neighboring header buttons, and the overflow\n behavior PathLabel itself uses in a narrow header. It may shrink but\n never grows \u2014 the PathLabel after it owns the free header space. */\n.mrfw-rootSwitchBtn {\n flex: 0 1 auto;\n min-width: 0;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 28px;\n margin: 0;\n padding: 0 4px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: inherit;\n line-height: 20px;\n text-align: left;\n cursor: pointer;\n transition: background-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-rootSwitchBtn:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.mrfw-rootSwitchBtn .mrfw-triggerIcon {\n color: var(--dsw-alias-label-secondary);\n}\n\n.mrfw-rootSwitchLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mrfw-rootSwitchChevron {\n margin-left: auto;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* The selected root's full path sits between the trigger and the reload \u2014\n the very PathLabel upstream draws there, so it brings its own grow,\n left-clip and hover-title behavior; only the gutters are ours. The right\n margin plus the container gap reproduces upstream's .path margin-right\n 12px + header gap 4px; the left gutter comes from the same container gap. */\n.mrfw-switcherPath {\n margin: 0 12px 0 0;\n}\n\n/* The takeover's own reload, standing exactly where the hidden native one\n did: the upstream .tool recipe verbatim (28px hit area, 15px glyph,\n secondary voice, hover fills). It calls the forked face's refresh \u2014 an\n in-place re-list, not a remount. */\n.mrfw-switcherReload {\n flex: none;\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: var(--dsw-radius-sm);\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n line-height: 1;\n cursor: pointer;\n}\n\n.mrfw-switcherReload:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n/* \u2500\u2500 files-tree fork (verbatim rules, renamed classes) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Copied from upstream's FilesBody.module.css (ui-sidebar-files @\n 0.2.2-alpha.2) with local names mapped to mrfw-ft* so the rules cannot\n collide with host DOM \u2014 and so the fork's own body (which must NOT carry\n data-files-body) stays visible while the rules above hide the native one.\n The header-only rules (root/header/path/tool/status/statusLine/titleIcon)\n belong to the upstream shell this fork drops and are not mapped. Fork sync\n re-diffs the upstream file and re-applies the rename \u2014 see\n src/client/files-tree/FORK.md. */\n\n/* The pane's own .root already supplies the flex column, color, and font;\n the fork's body takes the same stretch item the hidden native body held,\n including the workspace list's 2px scrollbar offset and stable gutter. */\n.mrfw-ftBody {\n flex: 1 1 auto;\n min-height: 0;\n margin-right: 2px;\n padding: 8px 0 8px 8px;\n overflow: auto;\n scrollbar-gutter: stable;\n}\n\n.mrfw-ftBody::-webkit-scrollbar-track {\n margin: 2px;\n}\n\n.mrfw-ftLevel {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.mrfw-ftLevel .mrfw-ftLevel {\n padding-left: 18px;\n}\n\n.mrfw-ftItem {\n margin: 0;\n padding: 0;\n}\n\n/* Rows abut, so the hover fill is the whole row; the tree's air is this\n inset, not a gap between rows. */\n.mrfw-ftRow {\n display: flex;\n gap: 6px;\n align-items: center;\n width: 100%;\n min-width: 0;\n padding: 5px 10px;\n color: inherit;\n font: inherit;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: var(--dsw-radius-md);\n cursor: pointer;\n}\n\n@media (hover: hover) {\n .mrfw-ftRow:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n }\n}\n\n/* The folder glyph rides the tertiary ink, as the workspace tree's does. */\n.mrfw-ftIcon {\n flex: 0 0 auto;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* The type's coloured sheet at the folder glyph's 16px; its colour is its own. */\n.mrfw-ftFileIcon {\n flex: 0 0 auto;\n}\n\n.mrfw-ftName {\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n/* Neither a file nor a directory: shown so the directory is reported whole,\n greyed so nobody tries to open it. */\n.mrfw-ftOther {\n color: var(--dsw-alias-label-tertiary);\n cursor: default;\n}\n\n@media (hover: hover) {\n .mrfw-ftOther:hover {\n background: transparent;\n }\n}\n\n.mrfw-ftNote {\n margin: 0;\n padding: 3px 10px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n}\n\n/* \u2500\u2500 open-in-app fork (verbatim rules, renamed classes) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Copied from upstream's OpenTargetButton.module.css\n (dsh-client-ui-open-in-app @ 0.2.1-alpha.2) with local names mapped to\n mrfw-open* so the rules cannot collide with host DOM. Fork sync re-diffs\n the upstream file and re-applies the rename \u2014 see\n src/client/open-in-app/FORK.md. */\n\n/* Sized to sit in the document header's 24px control row beside its round\n icon buttons: a hairline pill with a 12px label and a narrow chevron half. */\n.mrfw-openMenuAnchor {\n display: inline-flex;\n flex: none;\n align-self: center;\n}\n\n.mrfw-openSplit {\n display: inline-flex;\n align-items: stretch;\n box-sizing: border-box;\n height: 24px;\n overflow: hidden;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-sm);\n font-family: var(--dsw-font-family);\n}\n\n.mrfw-openMain,\n.mrfw-openChevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 0;\n background: none;\n color: var(--dsw-alias-label-primary);\n font-size: 11px;\n line-height: 16px;\n white-space: nowrap;\n cursor: pointer;\n}\n\n.mrfw-openMain {\n gap: 4px;\n padding: 3px 5px;\n}\n\n.mrfw-openChevron {\n padding: 3px 4px 3px 3px;\n border-left: 0.5px solid var(--dsw-alias-border-l4);\n color: var(--dsw-alias-label-secondary);\n}\n\n.mrfw-openMain:hover:not(:disabled),\n.mrfw-openMain:focus-visible,\n.mrfw-openChevron:hover:not(:disabled),\n.mrfw-openChevron:focus-visible {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n/* Pending disables clicks without a restyle; only hover feedback pauses. */\n.mrfw-openMain:disabled,\n.mrfw-openChevron:disabled {\n cursor: default;\n}\n\n.mrfw-openAppIcon {\n object-fit: contain;\n}\n\n/* The unavailable preview emphasizes the same actions with a labeled button. */\n.mrfw-openSplit[data-size='large'] {\n height: 36px;\n border-radius: var(--dsw-radius-md);\n border-color: var(--dsw-alias-border-l2);\n}\n\n.mrfw-openSplit[data-size='large'] .mrfw-openMain {\n gap: 6px;\n padding: 6px 14px;\n font-size: 14px;\n}\n\n.mrfw-openSplit[data-size='large'] .mrfw-openChevron {\n padding: 6px 10px;\n}\n\n.mrfw-openSkeleton { display: inline-block; flex: none; border-radius: var(--dsw-radius-xs); background: var(--dsw-alias-interactive-bg-hover); }\n\n.mrfw-overlay {\n position: fixed;\n inset: 0;\n z-index: 1000;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n}\n\n.mrfw-mask {\n position: absolute;\n inset: 0;\n background: var(--dsw-alias-bg-mask-1);\n backdrop-filter: var(--dsw-mask-blur);\n}\n\n.mrfw-dialog {\n position: relative;\n z-index: 1;\n display: flex;\n flex-direction: column;\n width: min(640px, 100%);\n max-height: 100%;\n overflow: hidden;\n border: none;\n border-radius: 24px;\n background: var(--dsw-alias-bg-layer-2);\n box-shadow: var(--dsw-elevation-prominent);\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n outline: none;\n}\n\n.mrfw-header {\n flex: none;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 22px 14px 12px 24px;\n}\n\n.mrfw-title {\n margin: 0;\n font-size: 16px;\n line-height: 24px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.mrfw-close {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 8px;\n background: transparent;\n cursor: pointer;\n color: var(--dsw-alias-label-secondary);\n transition: background-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-close:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.mrfw-body {\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow-y: auto;\n padding: 0 24px 24px;\n}\n\n.mrfw-alert {\n margin: 0 0 8px;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.mrfw-section {\n display: flex;\n flex-direction: column;\n}\n\n.mrfw-section + .mrfw-section {\n margin-top: 8px;\n}\n\n.mrfw-sectionTitleRow {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding: 8px 0 4px;\n}\n\n.mrfw-sectionTitle {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.mrfw-sectionNote {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.mrfw-row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n padding: 12px 0;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n.mrfw-rowBare {\n border-bottom: none;\n}\n\n/* A root entry's two lines: the display name on top, the absolute path under\n it in the tertiary voice (the workspace rows recipe of the host sidebar). */\n/* Match upstream General Settings' DeveloperToolsRow layout. */\n.mrfw-skillsSettings {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n padding: 16px 0;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n.mrfw-skillsSettingsText { min-width: 0; }\n.mrfw-settingsTitleRow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.mrfw-skillsSettingsTitle { font-size: 14px; line-height: 20px; }\n.mrfw-skillsSettingsDescription {\n margin-top: 4px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 18px;\n}\n.mrfw-rootText {\n display: flex;\n flex: 1 1 240px;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n/* Keep status tags and permission glyphs visible beside the alias, wrapping\n onto another line when the dialog is narrow. */\n.mrfw-rootName {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n min-width: 0;\n font-size: 14px;\n line-height: 20px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.mrfw-rootNameText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mrfw-rootPath {\n font-family: var(--ds-font-family-code);\n font-size: 12px;\n line-height: 18px;\n word-break: break-all;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* The path doubles as the copy control: an unstyled button that keeps the\n text recipe and makes the whole string clickable \u2014 the whole region, not\n just the icon, copies on click. */\n.mrfw-pathCopy {\n display: block;\n width: 100%;\n padding: 0;\n border: 0;\n background: transparent;\n text-align: left;\n cursor: pointer;\n}\n\n/* The trailing icon stays in flow but invisible until the path is hovered\n or focused: appearing never re-wraps the text, and the icon inherits the\n path's own tertiary ink. */\n.mrfw-pathCopyIcon {\n display: inline-flex;\n margin-left: 4px;\n vertical-align: -2px;\n opacity: 0;\n transition: opacity var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-pathCopy:hover .mrfw-pathCopyIcon,\n.mrfw-pathCopy:focus-visible .mrfw-pathCopyIcon {\n opacity: 1;\n}\n\n.mrfw-note {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.mrfw-stateWarn {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.mrfw-btn {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 28px;\n padding: 0 10px;\n border: none;\n border-radius: 14px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n transition: background-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-btn[aria-busy='true'] {\n cursor: wait;\n}\n\n.mrfw-btn:disabled {\n cursor: not-allowed;\n opacity: 0.4;\n}\n\n.mrfw-btnGhost:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.mrfw-btnGhost:active:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-active);\n}\n\n/* The solid destructive action of the capsule family: the upgrade confirm's\n red button. state-error-primary is the error ink upstream also uses as a\n fill (StateDot); the hover mixes in the host's primary label token to\n follow its theme and contrast choices. Neither color is a guessed token:\n an undefined var() would fall back\n to transparent and white-out the whole button. */\n.mrfw-btnDanger {\n background: var(--dsw-alias-state-error-primary);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.mrfw-btnDanger:hover:not(:disabled) {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 85%, var(--dsw-alias-label-primary));\n}\n\n.mrfw-btnOutline {\n border: 0.5px solid var(--dsw-alias-border-l3);\n background: transparent;\n}\n\n.mrfw-btnOutline:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.mrfw-btnPrimary {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.mrfw-btnPrimary:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n/* One icon-only action: a square of the capsule family, meaning in title.\n Declared after the .mrfw-btn family so its padding wins the cascade tie:\n the capsule's 0 10px padding would otherwise squeeze the icon glyph. */\n.mrfw-iconBtn {\n width: 28px;\n padding: 0;\n border-radius: 8px;\n}\n\n.mrfw-input {\n flex: 1 1 220px;\n min-width: 0;\n height: 32px;\n padding: 0 8px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 14px;\n line-height: 22px;\n outline: none;\n transition: border-color var(--ds-transition-duration-fast) var(--ds-ease-in-out);\n}\n\n.mrfw-input:focus {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.mrfw-input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n.mrfw-inputInline {\n flex: 1 1 auto;\n}\n\n.mrfw-accessSelect {\n flex: 0 0 auto;\n}\n\n/* The access dropdown's capsule trigger: the Menu anchor wrapper is the flex\n item, the button inside keeps the control row's 32px capsule recipe. */\n.mrfw-accessTrigger {\n padding: 0 12px;\n}\n\n.mrfw-cwdTag {\n flex: none;\n padding: 0 6px;\n border-radius: 4px;\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n line-height: 18px;\n}\n\n.mrfw-accessBadge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.mrfw-accessBadge {\n flex: none;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.mrfw-aliasEditor {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n flex-basis: 100%;\n}\n\n.mrfw-actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n margin-top: 16px;\n padding-top: 16px;\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n/* One control row, one height: the capsule buttons match the 32px input. */\n.mrfw-actions .mrfw-btn {\n height: 32px;\n border-radius: 16px;\n}\n\n.mrfw-actions .mrfw-iconBtn {\n width: 32px;\n}\n";
|
package/lib/types/command.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The user-facing surface: the `/workspace-folders` command
|
|
3
|
-
* RPC channel.
|
|
2
|
+
* The user-facing surface: the `/workspace-folders` command, its `/add-dirs`
|
|
3
|
+
* alias for adding a root, and the panel's RPC channel.
|
|
4
4
|
*
|
|
5
5
|
* They share one module because they are one thing — the operator-facing edge
|
|
6
6
|
* over `ctx.multiRootRegistry`. The command serves the text surfaces (the
|
|
@@ -81,7 +81,7 @@ export declare function apply(ctx: Context, config?: CommandConfig): void;
|
|
|
81
81
|
*
|
|
82
82
|
* @param ctx - the host context that may carry `sessions`.
|
|
83
83
|
* @param sessionId - the id the panel sent; already required by the wire schema.
|
|
84
|
-
* @returns the
|
|
84
|
+
* @returns the session's cwd spelling, verbatim — the Registry key.
|
|
85
85
|
* @throws {RootValidationError} `session-not-found` when the service is absent,
|
|
86
86
|
* the id does not name a live session, or that session has no cwd.
|
|
87
87
|
*/
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client seam for the optional Auto Review loader row.
|
|
3
|
+
*
|
|
4
|
+
* The row ships `disabled: true` in `cordis.patch.yml`; its only switch is the
|
|
5
|
+
* Loader entry's own enablement, which the Plugin Manager persists as a
|
|
6
|
+
* profile `{ id, disabled }` override through `pluginManager.setPluginEnabled`.
|
|
7
|
+
* This module binds that Remote namespace lazily — hosts without the Plugin
|
|
8
|
+
* Manager simply never attach, and the settings row stays hidden — and mirrors
|
|
9
|
+
* the Plugin Manager's own row semantics: the same entry id, the same
|
|
10
|
+
* `plugin-manager/changed` refresh, and the same `applied` /
|
|
11
|
+
* `restart-required` outcome split.
|
|
12
|
+
*
|
|
13
|
+
* Everything here is structural on purpose: the namespace is an optional
|
|
14
|
+
* service, so no module-level `inject` may name it, and the wire shapes are
|
|
15
|
+
* narrowed to the fields this card reads rather than imported from the
|
|
16
|
+
* generated Remote types.
|
|
17
|
+
*
|
|
18
|
+
* @module @dsh-electron/dsh-plugin-multi-root-workspace/compat/auto-review-client
|
|
19
|
+
*/
|
|
20
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
21
|
+
/** The module specifier `cordis.patch.yml` gives the optional row. */
|
|
22
|
+
export declare const AUTO_REVIEW_MODULE = "@dsh-electron/dsh-plugin-multi-root-workspace/auto-review";
|
|
23
|
+
/** The row's live state, narrowed to what the settings card renders. */
|
|
24
|
+
export interface AutoReviewRowView {
|
|
25
|
+
readonly entryId: string;
|
|
26
|
+
readonly enabled: boolean;
|
|
27
|
+
/** Whether `setPluginEnabled` may address this entry (no read-only reason). */
|
|
28
|
+
readonly writable: boolean;
|
|
29
|
+
/** Startup failure text while the entry's fiber is failed. */
|
|
30
|
+
readonly diagnostic?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface AutoReviewSnapshot {
|
|
33
|
+
/**
|
|
34
|
+
* `unavailable` — the `pluginManager` namespace never attached (old host or
|
|
35
|
+
* headless composition): the row renders nothing. `loading` — attached, the
|
|
36
|
+
* first `listPlugins` is in flight. `ready` — `row` is present exactly when
|
|
37
|
+
* the composition lists our module. `error` — the last read failed.
|
|
38
|
+
*/
|
|
39
|
+
readonly status: 'unavailable' | 'loading' | 'ready' | 'error';
|
|
40
|
+
readonly row?: AutoReviewRowView;
|
|
41
|
+
}
|
|
42
|
+
/** What one enable/disable write resolved to. */
|
|
43
|
+
export type AutoReviewWriteResult = 'applied' | 'restart-required' | 'failed';
|
|
44
|
+
/** The card's handle: a snapshot source plus the row's one write. */
|
|
45
|
+
export interface AutoReviewForm {
|
|
46
|
+
getSnapshot(): AutoReviewSnapshot;
|
|
47
|
+
subscribe(listener: () => void): () => void;
|
|
48
|
+
setEnabled(enabled: boolean): Promise<AutoReviewWriteResult>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create the card's Auto Review handle and attach it when the host's
|
|
52
|
+
* `pluginManager` namespace arrives. The returned form exists immediately with
|
|
53
|
+
* status `unavailable` and publishes on every attach/detach/read, so callers
|
|
54
|
+
* only need `subscribe` — no separate availability callback.
|
|
55
|
+
* @param ctx - the client root context.
|
|
56
|
+
* @returns the stable form the settings row renders.
|
|
57
|
+
*/
|
|
58
|
+
export declare function installAutoReviewSettings(ctx: Context): AutoReviewForm;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Bind Connection's public RPC getter to the fiber that owns the route. */
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { HostConnectionHandle, HostConnectionRpc } from '@deepseek-ai/dsh-client-connection';
|
|
4
|
+
/**
|
|
5
|
+
* Newer Cordis keeps a service getter's definition site when tracing it, so
|
|
6
|
+
* even reading Connection from the root can make its RPC getter capture the
|
|
7
|
+
* provider's context (which does not inject webServer). Invoke the public
|
|
8
|
+
* accessor with the actual consumer context instead. A data property is used
|
|
9
|
+
* unchanged for simpler Connection implementations. The service is not
|
|
10
|
+
* modified and the route remains owned by the injecting fiber.
|
|
11
|
+
*/
|
|
12
|
+
export declare function connectionRpcFor(ctx: Context, connection: HostConnectionHandle): HostConnectionRpc;
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* the upgrade smoke passed on that exact version — a green CI run on an
|
|
29
29
|
* unlisted release is evidence, not authorization (ADR-0009).
|
|
30
30
|
*/
|
|
31
|
-
export declare const SUPPORTED_DSH_RELEASES: readonly ["0.1.5-rc.2", "0.1.6-alpha.1", "0.1.6-alpha.2", "0.1.7-alpha.1", "0.1.7-alpha.2", "0.1.7-rc.1", "0.1.7-rc.2", "0.2.0-rc.1", "0.2.0-rc.2", "0.2.1-alpha.1", "0.2.1-alpha.2", "0.2.1-alpha.3", "0.2.1-alpha.4", "0.2.1-alpha.5", "0.2.1-rc.1", "0.2.1-rc.2", "0.2.1-rc.3", "0.2.1-rc.4", "0.2.1-rc.5", "0.2.2-alpha.2"];
|
|
31
|
+
export declare const SUPPORTED_DSH_RELEASES: readonly ["0.1.5-rc.2", "0.1.6-alpha.1", "0.1.6-alpha.2", "0.1.7-alpha.1", "0.1.7-alpha.2", "0.1.7-rc.1", "0.1.7-rc.2", "0.2.0-rc.1", "0.2.0-rc.2", "0.2.1-alpha.1", "0.2.1-alpha.2", "0.2.1-alpha.3", "0.2.1-alpha.4", "0.2.1-alpha.5", "0.2.1-rc.1", "0.2.1-rc.2", "0.2.1-rc.3", "0.2.1-rc.4", "0.2.1-rc.5", "0.2.2-alpha.2", "0.2.2-alpha.3", "0.2.2-rc.1"];
|
|
32
32
|
/** One release this plugin claims to support. */
|
|
33
33
|
export type SupportedDshRelease = typeof SUPPORTED_DSH_RELEASES[number];
|
|
34
34
|
/**
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Adapt the legacy listing store to the host's optional controlled tree Factory. */
|
|
2
|
+
export interface NativeTreeEntry {
|
|
3
|
+
readonly path: string;
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly meta: {
|
|
6
|
+
readonly kind: 'file' | 'directory' | 'other';
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
type Level<F> = {
|
|
10
|
+
readonly kind: 'loading';
|
|
11
|
+
} | {
|
|
12
|
+
readonly kind: 'failed';
|
|
13
|
+
readonly failure: F;
|
|
14
|
+
} | {
|
|
15
|
+
readonly kind: 'ready';
|
|
16
|
+
readonly level: {
|
|
17
|
+
readonly entries: readonly {
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly type: 'file' | 'directory' | 'other';
|
|
20
|
+
}[];
|
|
21
|
+
readonly truncated: boolean;
|
|
22
|
+
};
|
|
23
|
+
readonly failure?: F;
|
|
24
|
+
};
|
|
25
|
+
/** Render function supplied to a slot occupant by newer renderer builds. */
|
|
26
|
+
export type NativeTreeRenderer = (name: string, input: object, options: {
|
|
27
|
+
fallback: unknown;
|
|
28
|
+
}) => unknown;
|
|
29
|
+
export declare function nativeTreeRenderer(value: unknown): NativeTreeRenderer | undefined;
|
|
30
|
+
/** The factory consumes absolute, slash-separated keys and already-localized errors. */
|
|
31
|
+
export declare function nativeTreeInput<F>(state: {
|
|
32
|
+
readonly root: string;
|
|
33
|
+
readonly levels: Readonly<Record<string, Level<F>>>;
|
|
34
|
+
readonly expanded: readonly string[];
|
|
35
|
+
}, failureLine: (failure: F) => string, toggle: (parent: string, path: string) => void, open: (path: string) => void): object;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type AdditionalMutation = 'patchText' | 'deleteFile' | 'moveFile';
|
|
2
|
+
type Invoke = (args: unknown[]) => unknown;
|
|
3
|
+
type Fence<T> = (receiver: T, method: AdditionalMutation, args: unknown[], invoke: Invoke) => unknown;
|
|
4
|
+
/** Install only methods present on the actual backend, preserving the caller as `this`. */
|
|
5
|
+
export declare function installAdditionalMutations<T extends object>(prototype: T, fence: Fence<T>): void;
|
|
6
|
+
export {};
|