dsh-capability-panel 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +3 -3
- package/README.i18n.yaml +4 -4
- package/README.ja.md +3 -3
- package/README.ko.md +3 -3
- package/README.md +3 -3
- package/icon.svg +19 -0
- package/lib/client.js +2206 -2003
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +35 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +82 -3
- package/lib/index.js.map +1 -1
- package/package.json +15 -9
package/lib/index.d.ts
CHANGED
|
@@ -166,6 +166,32 @@ interface AgentCreatedPayload {
|
|
|
166
166
|
};
|
|
167
167
|
};
|
|
168
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* The Host's Session controller, as far as this plugin uses it: the two
|
|
171
|
+
* members that open one path on the user's own desktop. Structural like every
|
|
172
|
+
* other service here, so nothing static is imported from
|
|
173
|
+
* `@deepseek-ai/dsh-api-session-controller` — and it spans this plugin's whole
|
|
174
|
+
* supported range, because both members exist in every generation from
|
|
175
|
+
* 0.1.2-rc.1 through 0.2.x. The richer members (`workspaceDesktop`,
|
|
176
|
+
* `workspacePathApplications`) only appear from 0.1.7-rc.2, so they stay unused
|
|
177
|
+
* rather than optional-by-extra-probing.
|
|
178
|
+
*/
|
|
179
|
+
interface SessionControllerLike {
|
|
180
|
+
/**
|
|
181
|
+
* Whether this deployment can hand one path to a native desktop. `false` is
|
|
182
|
+
* an answer rather than a failure: either the deployment turned native
|
|
183
|
+
* opening off, or the platform announces no desktop at all.
|
|
184
|
+
*/
|
|
185
|
+
canOpenWorkspacePath(): boolean;
|
|
186
|
+
/**
|
|
187
|
+
* Verify the path through the composed filesystem, then open it natively.
|
|
188
|
+
* Rejects with the Host's own error when no verified mapping exists, which is
|
|
189
|
+
* how a sandboxed deployment refuses a path outside its roots.
|
|
190
|
+
*/
|
|
191
|
+
openWorkspacePath(request: {
|
|
192
|
+
readonly path: string;
|
|
193
|
+
}, signal: AbortSignal): Promise<unknown>;
|
|
194
|
+
}
|
|
169
195
|
interface HostServices {
|
|
170
196
|
/**
|
|
171
197
|
* This plugin's own cordis fiber, read for the profile entry id that 0.1.7
|
|
@@ -201,6 +227,7 @@ interface HostServices {
|
|
|
201
227
|
get(name: 'agents', strict?: boolean): AgentsService | undefined;
|
|
202
228
|
get(name: 'agentPresets', strict?: boolean): AgentPresetsService | undefined;
|
|
203
229
|
get(name: 'settings', strict?: boolean): SettingsService | undefined;
|
|
230
|
+
get(name: 'sessionController', strict?: boolean): SessionControllerLike | undefined;
|
|
204
231
|
get(name: 'skills', strict?: boolean): SkillsService | undefined;
|
|
205
232
|
get(name: 'tools', strict?: boolean): ToolsService | undefined;
|
|
206
233
|
on(event: 'agent/created',
|
|
@@ -285,6 +312,12 @@ interface SkillSummary {
|
|
|
285
312
|
readonly modelInvocable?: unknown;
|
|
286
313
|
};
|
|
287
314
|
readonly resourceBase?: unknown;
|
|
315
|
+
/**
|
|
316
|
+
* The absolute instruction file path, when the provider supplies one —
|
|
317
|
+
* `SKILL.md` for a directory bundle, the file itself for a flat Markdown
|
|
318
|
+
* skill, absent for a virtual skill registered in memory.
|
|
319
|
+
*/
|
|
320
|
+
readonly path?: unknown;
|
|
288
321
|
}
|
|
289
322
|
interface SkillDefinitionLike {
|
|
290
323
|
readonly name?: unknown;
|
|
@@ -293,6 +326,8 @@ interface SkillDefinitionLike {
|
|
|
293
326
|
readonly source?: unknown;
|
|
294
327
|
readonly provider?: unknown;
|
|
295
328
|
readonly resourceBase?: unknown;
|
|
329
|
+
/** The provider's instruction-file path, inherited by the panel's shadow. */
|
|
330
|
+
readonly path?: unknown;
|
|
296
331
|
}
|
|
297
332
|
interface IncomingLike$1 extends IncomingLike {
|
|
298
333
|
on?(event: 'data', listener: (chunk: unknown) => void): void;
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/loopback.ts","../src/host/types.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;AACiB,UAAA,YAAA,CAAY;;;oBAGT;ECkBH;AAQjB;;;EAQY,SAAA,MAAA,CAAA,EAAA;IAAO,SAAA,aAAA,CAAA,EAAA,MAAA;EAkBF,CAAA;AAMjB;;;;AAAA;AAoBA;AAKA;;;;;AAa8B,UA9Eb,eAAA,CA8Ea;EAAO,SAAA,QAAA,CAAA,EAAA,OAAA;EA8BpB;EAWA,SAAA,OAAA,CAAA,EAAA;IAgBA,SAAA,EAAA,CAAA,EAAe,OAAA;IAMkF,SAAA,IAAA,CAAA,EAAA,OAAA;IAAlB,SAAA,MAAA,CAAA,EAAA,OAAA;EAKnC,CAAA;EAEc,QAAA,EAAA,EAhJ7D,OAgJ6D,CAAA,IAAA,CAAA;EAED,OAAA,EAAA,EAjJ7D,OAiJ6D,CAAA,IAAA,CAAA;;AAEqB,UAhJ9E,UAAA,CAgJ8E;EAW9E,OAAA,EAAA,EA1JJ,QA0JiB,CA1JR,eA0JQ,CAAA;EACsC;;;;;AAIpE;EAMiB,KAAA,GAAA,EA9JL,OA8JK,CAAA,OAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/loopback.ts","../src/host/types.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;AACiB,UAAA,YAAA,CAAY;;;oBAGT;ECkBH;AAQjB;;;EAQY,SAAA,MAAA,CAAA,EAAA;IAAO,SAAA,aAAA,CAAA,EAAA,MAAA;EAkBF,CAAA;AAMjB;;;;AAAA;AAoBA;AAKA;;;;;AAa8B,UA9Eb,eAAA,CA8Ea;EAAO,SAAA,QAAA,CAAA,EAAA,OAAA;EA8BpB;EAWA,SAAA,OAAA,CAAA,EAAA;IAgBA,SAAA,EAAA,CAAA,EAAe,OAAA;IAMkF,SAAA,IAAA,CAAA,EAAA,OAAA;IAAlB,SAAA,MAAA,CAAA,EAAA,OAAA;EAKnC,CAAA;EAEc,QAAA,EAAA,EAhJ7D,OAgJ6D,CAAA,IAAA,CAAA;EAED,OAAA,EAAA,EAjJ7D,OAiJ6D,CAAA,IAAA,CAAA;;AAEqB,UAhJ9E,UAAA,CAgJ8E;EAW9E,OAAA,EAAA,EA1JJ,QA0JiB,CA1JR,eA0JQ,CAAA;EACsC;;;;;AAIpE;EAMiB,KAAA,GAAA,EA9JL,OA8JK,CAAA,OAAmB,CAAA;AAiBpC;AAmE2B,UAhOV,aAAA,CAgOU;EAcT,GAAA,CAAA,SAAA,EAAA,MAAA,CAAA,EA7OQ,SA6OR,GAAA,SAAA;EACT;EAAO,IAAA,EAAA,EA5ON,SA4OM,EAAA;AAqBhB;AAIiB,UAlQA,eAAA,CAkQS;EAiBT,SAAA,EAAA,EAAA,MAAY;EAeZ;AAWjB;AAMA;;;;ECvVa;EAGG,SAAK,IAAA,CAAA,EAAA,MAAM;EA6Bd,SAAsB,IAAA,CAAA,EAAA,MAAA;;;;;;;;;UDwBlB,cAAA;;2BAEU;;UAGV,mBAAA;UACP,QAAQ;;;;;;gCAMc;;;;;;8BAMF,QAAQ;;;UA8BrB;SACR;;;;;;4BAMmB;;;UAIX,kBAAA;;;;;;;;;;;;;;;UAgBA,eAAA;;;;;;;;MAM+E,kBAAkB;;;;;;;eAKrD;;2EAEc;;0EAED;;wFAEc;;UAWvE,aAAA;;;;MACkC,iBAAiB;;;;MACJ,QAAQ;;UAGvD,YAAA;4BACW;;;;;;;;;;;;UAKX,mBAAA;kBACC;;;0BAEsB;;;;;;;;;;;;;;UAcvB,qBAAA;;;;;;;;;;;;;;aAY+C,cAAc;;UAG7D,YAAA;;;;;;;;;;;;;;;;;;;qBAeI,qBAAmB,uBAAuB;;;;;;;;;;;;yCAYtB;yCACA;+CACM;2CACJ;oDACS;yCACX;wCACD;;;;;;;;sBAShB,+BAA+B;;iGAKS;;mDAKrC;;;;;;;;;;;;;;;;;;;;;;;;iBAcT;;;;SACT;;;;;;;UAqBQ,mBAAA;;;;;UAIA,SAAA;;;;;;;;;;;;;;;;;;;;;;UAiBA,YAAA;;;;;;;;;;;;;;;;UAeA,mBAAA;;;;;;;;;;UAWA,cAAA,SAAqB;;;;;UAMrB,kBAAA;qCACoB;;;;;ADjXrC;;;;ACqBA;AAQA;;;;;AA0BA;AAMA;AAoBA;AAKA;;AACU,cC9DG,MD8DH,EC9DS,WD8DT,CAAA,GAAA,EAAA,GAAA,EAAA,OAAA,CAAA;;AAY4B,iBCvEtB,KAAA,CDuEsB,GAAA,ECvEX,YDuEW,CAAA,EAAA,IAAA;AAAR,cC1CjB,MD0CiB,EAAA,MAAA,EAAA"}
|
package/lib/index.js
CHANGED
|
@@ -252,7 +252,7 @@ function decideStates(available, loads, shadowedSeqs, disabledSkills = /* @__PUR
|
|
|
252
252
|
if (bucket === void 0) byName.set(record.skillName, [record]);
|
|
253
253
|
else bucket.push(record);
|
|
254
254
|
}
|
|
255
|
-
return available.map(({ name, description, masked, source, provider, path, group }) => {
|
|
255
|
+
return available.map(({ name, description, masked, source, provider, path, fileAddress, group }) => {
|
|
256
256
|
const records = byName.get(name) ?? [];
|
|
257
257
|
let state = "unloaded";
|
|
258
258
|
if (records.length > 0) {
|
|
@@ -269,6 +269,7 @@ function decideStates(available, loads, shadowedSeqs, disabledSkills = /* @__PUR
|
|
|
269
269
|
source,
|
|
270
270
|
provider,
|
|
271
271
|
...path === void 0 ? {} : { path },
|
|
272
|
+
...fileAddress === void 0 ? {} : { fileAddress },
|
|
272
273
|
...group === void 0 ? {} : { group }
|
|
273
274
|
};
|
|
274
275
|
});
|
|
@@ -449,6 +450,7 @@ function createCapabilityController(ctx, appendStats, blockedCounts) {
|
|
|
449
450
|
source: typeof original.source === "string" ? original.source : "custom",
|
|
450
451
|
provider: typeof original.provider === "string" ? original.provider : "capability-panel",
|
|
451
452
|
...original.resourceBase === void 0 ? {} : { resourceBase: original.resourceBase },
|
|
453
|
+
...typeof original.path === "string" ? { path: original.path } : {},
|
|
452
454
|
invocation: {
|
|
453
455
|
modelInvocable: false,
|
|
454
456
|
userInvocable: true
|
|
@@ -594,6 +596,7 @@ function createCapabilityController(ctx, appendStats, blockedCounts) {
|
|
|
594
596
|
source: typeof original.source === "string" ? original.source : "custom",
|
|
595
597
|
provider: typeof original.provider === "string" ? original.provider : "capability-panel",
|
|
596
598
|
...original.resourceBase === void 0 ? {} : { resourceBase: original.resourceBase },
|
|
599
|
+
...typeof original.path === "string" ? { path: original.path } : {},
|
|
597
600
|
invocation: {
|
|
598
601
|
modelInvocable: false,
|
|
599
602
|
userInvocable: true
|
|
@@ -7815,6 +7818,44 @@ async function restartMcpServer(ctx, server) {
|
|
|
7815
7818
|
await entry.refresh();
|
|
7816
7819
|
}
|
|
7817
7820
|
|
|
7821
|
+
//#endregion
|
|
7822
|
+
//#region src/host/skill-preview.ts
|
|
7823
|
+
/** The single member used from `@deepseek-ai/dsh-util-workspace-path`. */
|
|
7824
|
+
function pickFileAddressFor(module) {
|
|
7825
|
+
const candidate = module.fileAddressFor;
|
|
7826
|
+
return typeof candidate === "function" ? candidate : void 0;
|
|
7827
|
+
}
|
|
7828
|
+
let probed = false;
|
|
7829
|
+
let builder;
|
|
7830
|
+
/**
|
|
7831
|
+
* Resolve the Host's address helper once, or `undefined` when this deployment
|
|
7832
|
+
* has no such export. The probe result is remembered either way: a missing
|
|
7833
|
+
* package cannot appear later in one process's life.
|
|
7834
|
+
* @returns the helper, when the running Host ships it.
|
|
7835
|
+
*/
|
|
7836
|
+
async function loadFileAddressFor() {
|
|
7837
|
+
if (!probed) {
|
|
7838
|
+
probed = true;
|
|
7839
|
+
try {
|
|
7840
|
+
builder = pickFileAddressFor(await import("@deepseek-ai/dsh-util-workspace-path"));
|
|
7841
|
+
} catch {
|
|
7842
|
+
builder = void 0;
|
|
7843
|
+
}
|
|
7844
|
+
}
|
|
7845
|
+
return builder;
|
|
7846
|
+
}
|
|
7847
|
+
/**
|
|
7848
|
+
* The address that opens `file` in the Host's right-sidebar preview.
|
|
7849
|
+
* @param forFile - the resolved helper; `undefined` means this Host cannot.
|
|
7850
|
+
* @param sessionId - the Session whose workspace resolves the path.
|
|
7851
|
+
* @param cwd - that Session's workspace root, when the Host reported one.
|
|
7852
|
+
* @param file - the skill's absolute instruction file path.
|
|
7853
|
+
* @returns the address, or `undefined` when the preview is unavailable.
|
|
7854
|
+
*/
|
|
7855
|
+
function previewAddressFor(forFile, sessionId, cwd, file) {
|
|
7856
|
+
return forFile === void 0 ? void 0 : forFile(sessionId, cwd, file);
|
|
7857
|
+
}
|
|
7858
|
+
|
|
7818
7859
|
//#endregion
|
|
7819
7860
|
//#region src/host/catalog.ts
|
|
7820
7861
|
/** Coerce a skill summary field to a string, falling back when the runtime shape is wrong. */
|
|
@@ -7875,6 +7916,7 @@ async function readAvailable(services, sessionId, degraded, presetDirs = []) {
|
|
|
7875
7916
|
...cwd === void 0 ? {} : { cwd },
|
|
7876
7917
|
scope: agent
|
|
7877
7918
|
});
|
|
7919
|
+
const forFile = await loadFileAddressFor();
|
|
7878
7920
|
const out = [];
|
|
7879
7921
|
const seen = /* @__PURE__ */ new Map();
|
|
7880
7922
|
const groupFor = (source, rawRoot) => {
|
|
@@ -7892,6 +7934,8 @@ async function readAvailable(services, sessionId, degraded, presetDirs = []) {
|
|
|
7892
7934
|
const rawRoot = rawPath === "" ? "" : parentDir(rawPath);
|
|
7893
7935
|
const path = rawRoot === "" ? "" : displayPath(rawRoot, cwd);
|
|
7894
7936
|
const group = groupFor(source, rawRoot);
|
|
7937
|
+
const file = coerceString(item.path, "");
|
|
7938
|
+
const fileAddress = file === "" ? void 0 : previewAddressFor(forFile, sessionId, cwd, file);
|
|
7895
7939
|
const existing = seen.get(item.name);
|
|
7896
7940
|
if (existing !== void 0) {
|
|
7897
7941
|
if (masked) existing.masked = true;
|
|
@@ -7899,6 +7943,7 @@ async function readAvailable(services, sessionId, degraded, presetDirs = []) {
|
|
|
7899
7943
|
existing.source = source;
|
|
7900
7944
|
existing.provider = provider;
|
|
7901
7945
|
if (path !== "") existing.path = path;
|
|
7946
|
+
if (fileAddress !== void 0) existing.fileAddress = fileAddress;
|
|
7902
7947
|
if (group !== void 0) existing.group = group;
|
|
7903
7948
|
}
|
|
7904
7949
|
continue;
|
|
@@ -7911,6 +7956,7 @@ async function readAvailable(services, sessionId, degraded, presetDirs = []) {
|
|
|
7911
7956
|
source,
|
|
7912
7957
|
provider,
|
|
7913
7958
|
...path === "" ? {} : { path },
|
|
7959
|
+
...fileAddress === void 0 ? {} : { fileAddress },
|
|
7914
7960
|
...group === void 0 ? {} : { group }
|
|
7915
7961
|
};
|
|
7916
7962
|
seen.set(item.name, row);
|
|
@@ -8439,13 +8485,43 @@ function isLoopback(req) {
|
|
|
8439
8485
|
*/
|
|
8440
8486
|
function openFolder(path) {
|
|
8441
8487
|
return new Promise((resolve, reject) => {
|
|
8442
|
-
exec(`${process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open"} "${path}"`, (error) => {
|
|
8488
|
+
exec(`${process.platform === "darwin" ? "open" : process.platform === "win32" ? "start \"\"" : "xdg-open"} "${path}"`, (error) => {
|
|
8443
8489
|
if (error) reject(/* @__PURE__ */ new Error(`failed to open folder: ${error.message}`));
|
|
8444
8490
|
else resolve();
|
|
8445
8491
|
});
|
|
8446
8492
|
});
|
|
8447
8493
|
}
|
|
8448
8494
|
|
|
8495
|
+
//#endregion
|
|
8496
|
+
//#region src/host/open-source-folder.ts
|
|
8497
|
+
/**
|
|
8498
|
+
* Whether the resolved service really carries both members this route calls.
|
|
8499
|
+
* Probed rather than assumed, exactly like the other optional services: the
|
|
8500
|
+
* service name is stable across generations, but a composition is free to
|
|
8501
|
+
* mount a partial implementation.
|
|
8502
|
+
*/
|
|
8503
|
+
function isUsableOpener(opener) {
|
|
8504
|
+
return opener !== void 0 && typeof opener.canOpenWorkspacePath === "function" && typeof opener.openWorkspacePath === "function";
|
|
8505
|
+
}
|
|
8506
|
+
/**
|
|
8507
|
+
* Open `path` through the Host when it can, else through `fallback`.
|
|
8508
|
+
* @param opener - the Session controller, when the composition mounts one.
|
|
8509
|
+
* @param path - absolute folder path already resolved from the source key.
|
|
8510
|
+
* @param fallback - this plugin's own opener, used where the Host cannot.
|
|
8511
|
+
* @returns which opener ran.
|
|
8512
|
+
*/
|
|
8513
|
+
async function openSourceFolder(opener, path, fallback) {
|
|
8514
|
+
if (isUsableOpener(opener)) {
|
|
8515
|
+
if (!opener.canOpenWorkspacePath()) return "unsupported";
|
|
8516
|
+
try {
|
|
8517
|
+
await opener.openWorkspacePath({ path }, new AbortController().signal);
|
|
8518
|
+
return "host";
|
|
8519
|
+
} catch {}
|
|
8520
|
+
}
|
|
8521
|
+
await fallback(path);
|
|
8522
|
+
return "local";
|
|
8523
|
+
}
|
|
8524
|
+
|
|
8449
8525
|
//#endregion
|
|
8450
8526
|
//#region src/host/route.ts
|
|
8451
8527
|
const ROUTE = "/api/capability-panel";
|
|
@@ -8675,7 +8751,10 @@ function createRouteHandler(services, capabilities, stats, blockedCounts, preset
|
|
|
8675
8751
|
return;
|
|
8676
8752
|
}
|
|
8677
8753
|
try {
|
|
8678
|
-
await
|
|
8754
|
+
if (await openSourceFolder(services.get("sessionController", false), folderPath, openFolder) === "unsupported") {
|
|
8755
|
+
json(res, 500, { error: "this deployment cannot open folders on a desktop" });
|
|
8756
|
+
return;
|
|
8757
|
+
}
|
|
8679
8758
|
json(res, 200, { ok: true });
|
|
8680
8759
|
} catch (error) {
|
|
8681
8760
|
json(res, 500, { error: `failed to open folder: ${errorMessage(error)}` });
|