@dawn0608/dsh-skill-manager 0.1.7 → 0.2.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.md +5 -29
- package/README.zh.md +5 -29
- package/lib/client.js +3 -9
- package/lib/client.js.map +2 -2
- package/lib/index.js +44 -220
- package/lib/index.js.map +4 -4
- package/package.json +3 -6
- package/lib/install-sync.js +0 -7681
- package/lib/install-sync.js.map +0 -7
- package/lib/sync-daemon.js +0 -7841
- package/lib/sync-daemon.js.map +0 -7
package/lib/index.js
CHANGED
|
@@ -7413,10 +7413,10 @@ var require_dist = __commonJS({
|
|
|
7413
7413
|
|
|
7414
7414
|
// src/index.js
|
|
7415
7415
|
import { homedir } from "node:os";
|
|
7416
|
-
import { join as
|
|
7416
|
+
import { join as join4, resolve as resolve2 } from "node:path";
|
|
7417
7417
|
|
|
7418
7418
|
// src/host.js
|
|
7419
|
-
import { isAbsolute as isAbsolute2, join as
|
|
7419
|
+
import { isAbsolute as isAbsolute2, join as join3, normalize } from "node:path";
|
|
7420
7420
|
|
|
7421
7421
|
// src/host-bundle.js
|
|
7422
7422
|
var import_yaml = __toESM(require_dist(), 1);
|
|
@@ -7586,7 +7586,7 @@ import {
|
|
|
7586
7586
|
unlinkSync,
|
|
7587
7587
|
writeFileSync
|
|
7588
7588
|
} from "node:fs";
|
|
7589
|
-
import { dirname, join as join2 } from "node:path";
|
|
7589
|
+
import { dirname, join as join2, resolve, toNamespacedPath } from "node:path";
|
|
7590
7590
|
import { randomUUID } from "node:crypto";
|
|
7591
7591
|
function stat(path) {
|
|
7592
7592
|
try {
|
|
@@ -7599,6 +7599,13 @@ function stat(path) {
|
|
|
7599
7599
|
function identity(stats) {
|
|
7600
7600
|
return `${stats.dev}:${stats.ino}:${stats.birthtimeNs}`;
|
|
7601
7601
|
}
|
|
7602
|
+
function linkTargets(path, expected) {
|
|
7603
|
+
const target = resolve(dirname(path), readlinkSync(path));
|
|
7604
|
+
return process.platform === "win32" ? toNamespacedPath(target).toLowerCase() === toNamespacedPath(resolve(expected)).toLowerCase() : target === resolve(expected);
|
|
7605
|
+
}
|
|
7606
|
+
function directoryLink(target, path) {
|
|
7607
|
+
symlinkSync(resolve(target), path, process.platform === "win32" ? "junction" : "dir");
|
|
7608
|
+
}
|
|
7602
7609
|
function safeDirectory(path, create) {
|
|
7603
7610
|
let stats = stat(path);
|
|
7604
7611
|
if (!stats && create) {
|
|
@@ -7685,19 +7692,30 @@ function createSkillStore(home) {
|
|
|
7685
7692
|
function takeLock() {
|
|
7686
7693
|
for (let generation = 0; ; generation += 1) {
|
|
7687
7694
|
const path = join2(manager, `.write-lock-${generation}`);
|
|
7695
|
+
const temp = join2(manager, `.lock-${randomUUID()}`);
|
|
7696
|
+
writeFileSync(temp, JSON.stringify({ pid: process.pid, nonce: randomUUID() }), { flag: "wx", mode: 384 });
|
|
7697
|
+
const token = identity(stat(temp));
|
|
7688
7698
|
try {
|
|
7689
|
-
|
|
7690
|
-
|
|
7699
|
+
linkSync(temp, path);
|
|
7700
|
+
if (!sameEntry(path, token)) throw new ManagerError("conflict");
|
|
7691
7701
|
return () => unlinkOwned(path, token);
|
|
7692
7702
|
} catch (error) {
|
|
7693
7703
|
if (error.code !== "EEXIST") throw error;
|
|
7704
|
+
} finally {
|
|
7705
|
+
unlinkSync(temp);
|
|
7694
7706
|
}
|
|
7695
7707
|
const stats = stat(path);
|
|
7696
|
-
if (!stats) throw new ManagerError("conflict");
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7708
|
+
if (!stats?.isFile()) throw new ManagerError("conflict");
|
|
7709
|
+
let owner;
|
|
7710
|
+
try {
|
|
7711
|
+
owner = JSON.parse(readRegularFile(path, 1024, identity(stats)));
|
|
7712
|
+
} catch {
|
|
7713
|
+
throw new ManagerError("conflict");
|
|
7714
|
+
}
|
|
7715
|
+
const pid = owner?.pid;
|
|
7716
|
+
if (!Number.isSafeInteger(pid) || pid < 1 || pid > 2147483647 || !MANAGED_ID.test(owner?.nonce ?? "")) {
|
|
7717
|
+
throw new ManagerError("conflict");
|
|
7718
|
+
}
|
|
7701
7719
|
try {
|
|
7702
7720
|
process.kill(pid, 0);
|
|
7703
7721
|
} catch (error) {
|
|
@@ -7713,6 +7731,9 @@ function createSkillStore(home) {
|
|
|
7713
7731
|
try {
|
|
7714
7732
|
if (!roots()) throw new ManagerError("conflict");
|
|
7715
7733
|
return operation();
|
|
7734
|
+
} catch (error) {
|
|
7735
|
+
if (["EBUSY", "EACCES", "EPERM"].includes(error.code)) throw new ManagerError("conflict");
|
|
7736
|
+
throw error;
|
|
7716
7737
|
} finally {
|
|
7717
7738
|
release();
|
|
7718
7739
|
}
|
|
@@ -7732,13 +7753,13 @@ function createSkillStore(home) {
|
|
|
7732
7753
|
if (!activation) return false;
|
|
7733
7754
|
if (!stats?.isSymbolicLink() || activation.link !== null && identity(stats) !== activation.link) return false;
|
|
7734
7755
|
const anchor = anchorPath(activation);
|
|
7735
|
-
return
|
|
7756
|
+
return linkTargets(paths.active, anchor) && stat(anchor)?.isSymbolicLink() === true && linkTargets(anchor, paths.bundle);
|
|
7736
7757
|
}
|
|
7737
7758
|
function discardAnchor(paths, activation) {
|
|
7738
7759
|
if (!activation) return;
|
|
7739
7760
|
const anchor = anchorPath(activation);
|
|
7740
7761
|
const stats = stat(anchor);
|
|
7741
|
-
if (stats?.isSymbolicLink() &&
|
|
7762
|
+
if (stats?.isSymbolicLink() && linkTargets(anchor, paths.bundle)) unlinkOwned(anchor, identity(stats));
|
|
7742
7763
|
}
|
|
7743
7764
|
function lookup(name, id) {
|
|
7744
7765
|
const paths = pathsFor(name);
|
|
@@ -7804,7 +7825,7 @@ function createSkillStore(home) {
|
|
|
7804
7825
|
assertFree(skills, [name, `${name}.md`]);
|
|
7805
7826
|
const activation = { anchor: randomUUID(), link: null };
|
|
7806
7827
|
const anchor = anchorPath(activation);
|
|
7807
|
-
|
|
7828
|
+
directoryLink(paths.bundle, anchor);
|
|
7808
7829
|
let prepared;
|
|
7809
7830
|
try {
|
|
7810
7831
|
prepared = writeRecord(paths.record, { ...record.data, activation }, record.token);
|
|
@@ -7814,7 +7835,7 @@ function createSkillStore(home) {
|
|
|
7814
7835
|
}
|
|
7815
7836
|
discardAnchor(paths, record.data.activation);
|
|
7816
7837
|
try {
|
|
7817
|
-
|
|
7838
|
+
directoryLink(anchor, paths.active);
|
|
7818
7839
|
} catch (error) {
|
|
7819
7840
|
if (error.code === "EEXIST") throw new ManagerError("conflict");
|
|
7820
7841
|
throw error;
|
|
@@ -7929,181 +7950,6 @@ function createSkillStore(home) {
|
|
|
7929
7950
|
return { install, list, read, remove, setEnabled };
|
|
7930
7951
|
}
|
|
7931
7952
|
|
|
7932
|
-
// src/shared-policy.js
|
|
7933
|
-
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
7934
|
-
import { mkdir, readlink, rename, symlink, unlink, writeFile, lstat as lstat3 } from "node:fs/promises";
|
|
7935
|
-
import { dirname as dirname3, join as join4 } from "node:path";
|
|
7936
|
-
|
|
7937
|
-
// src/shared-sync.js
|
|
7938
|
-
import { constants as constants3, watchFile, unwatchFile } from "node:fs";
|
|
7939
|
-
import { lstat as lstat2, open as open2, readdir, realpath as realpath2 } from "node:fs/promises";
|
|
7940
|
-
import { dirname as dirname2, join as join3, resolve } from "node:path";
|
|
7941
|
-
var syncDirectory = (home) => join3(home, "skill-manager", "shared-sync");
|
|
7942
|
-
var syncStateFile = (home) => join3(syncDirectory(home), "state.json");
|
|
7943
|
-
var MAX_STATE_BYTES = 2 * 1024 * 1024;
|
|
7944
|
-
var disabled = { modelInvocable: false, userInvocable: false };
|
|
7945
|
-
async function regularFile(path, limit) {
|
|
7946
|
-
var _stack = [];
|
|
7947
|
-
try {
|
|
7948
|
-
const before = await lstat2(path);
|
|
7949
|
-
if (!before.isFile() || before.size > limit) throw new ManagerError("invalid");
|
|
7950
|
-
const file = __using(_stack, await open2(path, constants3.O_RDONLY | (constants3.O_NOFOLLOW ?? 0) | (constants3.O_NONBLOCK ?? 0)), true);
|
|
7951
|
-
const stat2 = await file.stat();
|
|
7952
|
-
if (!stat2.isFile() || stat2.dev !== before.dev || stat2.ino !== before.ino || stat2.size > limit) {
|
|
7953
|
-
throw new ManagerError("conflict");
|
|
7954
|
-
}
|
|
7955
|
-
const bytes = Buffer.alloc(stat2.size + 1);
|
|
7956
|
-
const { bytesRead } = await file.read(bytes);
|
|
7957
|
-
if (bytesRead !== stat2.size) throw new ManagerError("conflict");
|
|
7958
|
-
return bytes.subarray(0, bytesRead);
|
|
7959
|
-
} catch (_) {
|
|
7960
|
-
var _error = _, _hasError = true;
|
|
7961
|
-
} finally {
|
|
7962
|
-
var _promise = __callDispose(_stack, _error, _hasError);
|
|
7963
|
-
_promise && await _promise;
|
|
7964
|
-
}
|
|
7965
|
-
}
|
|
7966
|
-
async function sharedSkills(agentsHome) {
|
|
7967
|
-
if (!agentsHome) return /* @__PURE__ */ new Map();
|
|
7968
|
-
const root = await realpath2(join3(agentsHome, "skills")).catch((error) => {
|
|
7969
|
-
if (error.code !== "ENOENT") throw error;
|
|
7970
|
-
});
|
|
7971
|
-
const skills = /* @__PURE__ */ new Map();
|
|
7972
|
-
if (!root) return skills;
|
|
7973
|
-
for (const entry of await readdir(root, { withFileTypes: true })) {
|
|
7974
|
-
if (!entry.isDirectory() || !isManagedName(entry.name) || entry.name === "synced" || entry.name === "anthropic-skills") continue;
|
|
7975
|
-
const path = join3(root, entry.name, "SKILL.md");
|
|
7976
|
-
try {
|
|
7977
|
-
if (await realpath2(path) !== path) continue;
|
|
7978
|
-
const parsed = parseSkillFile(await regularFile(path, MAX_BUNDLE_BYTES));
|
|
7979
|
-
if (parsed.name === entry.name) skills.set(path, { path, name: parsed.name, description: parsed.description });
|
|
7980
|
-
} catch (error) {
|
|
7981
|
-
}
|
|
7982
|
-
}
|
|
7983
|
-
return skills;
|
|
7984
|
-
}
|
|
7985
|
-
async function readSyncState(home) {
|
|
7986
|
-
try {
|
|
7987
|
-
const value = JSON.parse(await regularFile(syncStateFile(home), MAX_STATE_BYTES));
|
|
7988
|
-
if (![1, 2].includes(value.version) || !isRecord(value.entries)) throw new ManagerError("unavailable");
|
|
7989
|
-
return value;
|
|
7990
|
-
} catch (error) {
|
|
7991
|
-
if (error.code === "ENOENT") return null;
|
|
7992
|
-
throw new ManagerError("unavailable");
|
|
7993
|
-
}
|
|
7994
|
-
}
|
|
7995
|
-
function sharedPolicyEnabled(entry) {
|
|
7996
|
-
if (!entry) return void 0;
|
|
7997
|
-
if (typeof entry.policyEnabled === "boolean") return entry.policyEnabled;
|
|
7998
|
-
if (entry.pending && (entry.codex === false || entry.claude === "off")) return false;
|
|
7999
|
-
return entry.enabled;
|
|
8000
|
-
}
|
|
8001
|
-
function registerSharedPolicy(skills, home, agentsHome) {
|
|
8002
|
-
if (typeof skills.registerProvider !== "function") return () => {
|
|
8003
|
-
};
|
|
8004
|
-
let invalidate;
|
|
8005
|
-
const dispose = skills.registerProvider((control) => {
|
|
8006
|
-
invalidate = control.invalidate;
|
|
8007
|
-
return {
|
|
8008
|
-
name: "skill-manager-shared-policy",
|
|
8009
|
-
async list() {
|
|
8010
|
-
const state = await readSharedPolicy(home);
|
|
8011
|
-
if (!Object.values(state.entries).some((enabled) => enabled === false)) return [];
|
|
8012
|
-
return [...(await sharedSkills(agentsHome)).values()].filter((skill) => state.entries[skill.path] === false).map((skill) => ({
|
|
8013
|
-
...skill,
|
|
8014
|
-
provider: "skill-manager-shared-policy",
|
|
8015
|
-
source: "user-agents",
|
|
8016
|
-
// Immediately ahead of the default user-agents provider. Project and user-dsh win.
|
|
8017
|
-
rank: 499,
|
|
8018
|
-
invocation: disabled,
|
|
8019
|
-
locator: skill.path,
|
|
8020
|
-
resourceBase: { kind: "directory", path: dirname2(skill.path) }
|
|
8021
|
-
}));
|
|
8022
|
-
},
|
|
8023
|
-
async get(candidate) {
|
|
8024
|
-
try {
|
|
8025
|
-
if (await realpath2(candidate.path) !== candidate.path) return void 0;
|
|
8026
|
-
const { name, description, body } = parseSkillFile(await regularFile(candidate.path, MAX_BUNDLE_BYTES));
|
|
8027
|
-
return { ...candidate, name, description, content: body };
|
|
8028
|
-
} catch (error) {
|
|
8029
|
-
if (error.code === "ENOENT" || error.code === "invalid") return void 0;
|
|
8030
|
-
throw error;
|
|
8031
|
-
}
|
|
8032
|
-
}
|
|
8033
|
-
};
|
|
8034
|
-
});
|
|
8035
|
-
const path = policyFile(home);
|
|
8036
|
-
watchFile(path, { persistent: false, interval: 500 }, invalidate);
|
|
8037
|
-
return () => {
|
|
8038
|
-
unwatchFile(path, invalidate);
|
|
8039
|
-
dispose();
|
|
8040
|
-
};
|
|
8041
|
-
}
|
|
8042
|
-
|
|
8043
|
-
// src/shared-policy.js
|
|
8044
|
-
var policyFile = (home) => join4(home, "skill-manager", "shared-policy.json");
|
|
8045
|
-
var missing = (error) => {
|
|
8046
|
-
if (error.code !== "ENOENT") throw error;
|
|
8047
|
-
return null;
|
|
8048
|
-
};
|
|
8049
|
-
async function readSharedPolicy(home) {
|
|
8050
|
-
const bytes = await regularFile(policyFile(home), 2 * 1024 * 1024).catch(missing);
|
|
8051
|
-
if (bytes) {
|
|
8052
|
-
const state = JSON.parse(bytes);
|
|
8053
|
-
if (state.version !== 1 || !isRecord(state.entries) || Object.values(state.entries).some((x) => typeof x !== "boolean")) {
|
|
8054
|
-
throw new ManagerError("unavailable");
|
|
8055
|
-
}
|
|
8056
|
-
return state;
|
|
8057
|
-
}
|
|
8058
|
-
const previous = await readSyncState(home);
|
|
8059
|
-
return { version: 1, entries: Object.fromEntries(Object.entries(previous?.entries ?? {}).map(([path, entry]) => [path, sharedPolicyEnabled(entry)]).filter(([, enabled]) => typeof enabled === "boolean")) };
|
|
8060
|
-
}
|
|
8061
|
-
async function locked(home, operation) {
|
|
8062
|
-
const path = policyFile(home);
|
|
8063
|
-
await mkdir(dirname3(path), { recursive: true, mode: 448 });
|
|
8064
|
-
for (let generation = 0; generation < 1e3; generation++) {
|
|
8065
|
-
const lock = path + ".lock-" + generation;
|
|
8066
|
-
const owner = `${process.pid}-${randomUUID2()}`;
|
|
8067
|
-
try {
|
|
8068
|
-
await symlink(owner, lock);
|
|
8069
|
-
} catch (error) {
|
|
8070
|
-
if (error.code !== "EEXIST") throw error;
|
|
8071
|
-
const target = await readlink(lock).catch(() => null);
|
|
8072
|
-
const pid = Number(/^([1-9][0-9]*)-/.exec(target)?.[1]);
|
|
8073
|
-
if (!Number.isSafeInteger(pid) || pid > 2147483647) throw new ManagerError("conflict");
|
|
8074
|
-
try {
|
|
8075
|
-
process.kill(pid, 0);
|
|
8076
|
-
} catch (failure) {
|
|
8077
|
-
if (failure.code === "ESRCH") continue;
|
|
8078
|
-
}
|
|
8079
|
-
throw new ManagerError("conflict");
|
|
8080
|
-
}
|
|
8081
|
-
try {
|
|
8082
|
-
return await operation(path);
|
|
8083
|
-
} finally {
|
|
8084
|
-
if (await readlink(lock).catch(() => null) === owner) await unlink(lock);
|
|
8085
|
-
}
|
|
8086
|
-
}
|
|
8087
|
-
throw new ManagerError("conflict");
|
|
8088
|
-
}
|
|
8089
|
-
async function save(path, state) {
|
|
8090
|
-
const temp = path + "." + randomUUID2();
|
|
8091
|
-
try {
|
|
8092
|
-
await writeFile(temp, JSON.stringify(state) + "\n", { flag: "wx", mode: 384 });
|
|
8093
|
-
await rename(temp, path);
|
|
8094
|
-
} finally {
|
|
8095
|
-
await unlink(temp).catch(missing);
|
|
8096
|
-
}
|
|
8097
|
-
}
|
|
8098
|
-
async function setSharedEnabled(home, skillPath, enabled) {
|
|
8099
|
-
if (typeof enabled !== "boolean") throw new ManagerError("invalid");
|
|
8100
|
-
return locked(home, async (path) => {
|
|
8101
|
-
const state = await readSharedPolicy(home);
|
|
8102
|
-
state.entries[skillPath] = enabled;
|
|
8103
|
-
await save(path, state);
|
|
8104
|
-
});
|
|
8105
|
-
}
|
|
8106
|
-
|
|
8107
7953
|
// src/host.js
|
|
8108
7954
|
var ROUTE = "/api/skill-manager";
|
|
8109
7955
|
var MAX_REQUEST_BYTES = 12 * 1024 * 1024;
|
|
@@ -8144,7 +7990,7 @@ function parseId(id) {
|
|
|
8144
7990
|
function skillProvenance(skill, provenance) {
|
|
8145
7991
|
return skill.source === "bundled" ? { origin: "builtin" } : provenance(skill);
|
|
8146
7992
|
}
|
|
8147
|
-
function catalogRow(skill, provenance
|
|
7993
|
+
function catalogRow(skill, provenance) {
|
|
8148
7994
|
const origin = skillProvenance(skill, provenance)?.origin;
|
|
8149
7995
|
return {
|
|
8150
7996
|
id: `catalog:${skill.name}`,
|
|
@@ -8152,7 +7998,7 @@ function catalogRow(skill, provenance, shared, available) {
|
|
|
8152
7998
|
description: skill.description,
|
|
8153
7999
|
group: SOURCES.get(skill.source) ?? "local",
|
|
8154
8000
|
source: SOURCES.has(skill.source) ? skill.source : "other",
|
|
8155
|
-
enabled:
|
|
8001
|
+
enabled: null,
|
|
8156
8002
|
shadowed: false,
|
|
8157
8003
|
...origin && { origin }
|
|
8158
8004
|
};
|
|
@@ -8161,7 +8007,7 @@ function matchesManaged(skill, managed) {
|
|
|
8161
8007
|
if (!skill || skill.source !== "user-dsh" || typeof skill.path !== "string") return false;
|
|
8162
8008
|
if (!managed.enabled && !managed.activeMissing) return false;
|
|
8163
8009
|
const path = normalize(skill.path);
|
|
8164
|
-
return path === managed.resolvedFile || path ===
|
|
8010
|
+
return path === managed.resolvedFile || path === join3(managed.bundle, "SKILL.md") || path === join3(managed.active, "SKILL.md");
|
|
8165
8011
|
}
|
|
8166
8012
|
function createSkillManager({ home, agentsHome, skills, workspaceRegistry, agentPresets }) {
|
|
8167
8013
|
const store = createSkillStore(home);
|
|
@@ -8195,12 +8041,9 @@ function createSkillManager({ home, agentsHome, skills, workspaceRegistry, agent
|
|
|
8195
8041
|
}
|
|
8196
8042
|
async function list(options) {
|
|
8197
8043
|
const workspaces = workspaceRegistry.list().map(({ id, title }) => ({ id, title }));
|
|
8198
|
-
const [catalog, provenance
|
|
8044
|
+
const [catalog, provenance] = await Promise.all([
|
|
8199
8045
|
snapshot(options),
|
|
8200
|
-
readProvenance(agentsHome)
|
|
8201
|
-
readSyncState(home).catch(() => ({ error: "unavailable" })),
|
|
8202
|
-
readSharedPolicy(home),
|
|
8203
|
-
sharedSkills(agentsHome)
|
|
8046
|
+
readProvenance(agentsHome)
|
|
8204
8047
|
]);
|
|
8205
8048
|
const managed = store.list();
|
|
8206
8049
|
const byName = new Map(catalog.skills.map((skill) => [skill.name, skill]));
|
|
@@ -8219,17 +8062,12 @@ function createSkillManager({ home, agentsHome, skills, workspaceRegistry, agent
|
|
|
8219
8062
|
shadowed: skill.enabled && Boolean(match) && !ownWinner
|
|
8220
8063
|
});
|
|
8221
8064
|
}
|
|
8222
|
-
rows.push(...[...byName.values()].map((skill) => catalogRow(skill, provenance
|
|
8065
|
+
rows.push(...[...byName.values()].map((skill) => catalogRow(skill, provenance)));
|
|
8223
8066
|
rows.sort((left, right) => left.name.localeCompare(right.name) || Number(right.group === "imported") - Number(left.group === "imported"));
|
|
8224
|
-
const syncError = sync?.error ?? Object.values(sync?.entries ?? {}).find((entry) => entry.error)?.error;
|
|
8225
|
-
const stopped = sync && !sync.error && (!Number.isFinite(Date.parse(sync.health?.lastAttemptAt)) || Date.now() - Date.parse(sync.health.lastAttemptAt) > 15e3);
|
|
8226
|
-
const healthError = stopped ? "sharedStopped" : sync?.health?.status === "unavailable" ? "sharedUnavailable" : null;
|
|
8227
8067
|
return {
|
|
8228
|
-
...sync?.health && { syncHealth: sync.health },
|
|
8229
8068
|
skills: rows,
|
|
8230
8069
|
workspaces,
|
|
8231
|
-
complete: catalog.complete && managed.complete
|
|
8232
|
-
...(healthError || syncError) && { syncError: healthError ?? (syncError === "conflict" ? "sharedConflict" : "sharedUnavailable") }
|
|
8070
|
+
complete: catalog.complete && managed.complete
|
|
8233
8071
|
};
|
|
8234
8072
|
}
|
|
8235
8073
|
async function detail(id, options) {
|
|
@@ -8276,17 +8114,6 @@ function createSkillManager({ home, agentsHome, skills, workspaceRegistry, agent
|
|
|
8276
8114
|
case "setEnabled":
|
|
8277
8115
|
case "remove": {
|
|
8278
8116
|
const { kind, name, installId } = parseId(payload.id);
|
|
8279
|
-
if (kind === "catalog" && action === "setEnabled") {
|
|
8280
|
-
if (typeof payload.enabled !== "boolean") throw new ManagerError("invalid");
|
|
8281
|
-
return scoped(options, async (scopedOptions) => {
|
|
8282
|
-
const skill = await load(name, scopedOptions);
|
|
8283
|
-
const shared = await sharedSkills(agentsHome);
|
|
8284
|
-
if (skill?.source !== "user-agents" || !shared.has(skill.path)) throw new ManagerError("forbidden");
|
|
8285
|
-
signal?.throwIfAborted();
|
|
8286
|
-
await setSharedEnabled(home, skill.path, payload.enabled);
|
|
8287
|
-
return null;
|
|
8288
|
-
});
|
|
8289
|
-
}
|
|
8290
8117
|
if (kind !== "managed") throw new ManagerError("forbidden");
|
|
8291
8118
|
signal?.throwIfAborted();
|
|
8292
8119
|
if (action === "setEnabled") {
|
|
@@ -8364,8 +8191,8 @@ function createFetchHandler(manager) {
|
|
|
8364
8191
|
var inject = ["agentPresets", "connection", "skills", "workspaceRegistry"];
|
|
8365
8192
|
function resolveHome(configured, fallback) {
|
|
8366
8193
|
return configured?.trim() ? resolve2(
|
|
8367
|
-
configured === "~" ? homedir() : /^~[/\\]/.test(configured) ?
|
|
8368
|
-
) :
|
|
8194
|
+
configured === "~" ? homedir() : /^~[/\\]/.test(configured) ? join4(homedir(), configured.slice(2)) : configured
|
|
8195
|
+
) : join4(homedir(), fallback);
|
|
8369
8196
|
}
|
|
8370
8197
|
function apply(ctx) {
|
|
8371
8198
|
const home = resolveHome(process.env.DSH_HOME, ".dsh");
|
|
@@ -8377,9 +8204,6 @@ function apply(ctx) {
|
|
|
8377
8204
|
workspaceRegistry: ctx.workspaceRegistry,
|
|
8378
8205
|
agentPresets: ctx.agentPresets
|
|
8379
8206
|
});
|
|
8380
|
-
if (typeof ctx.skills.registerProvider === "function") {
|
|
8381
|
-
ctx.effect(() => registerSharedPolicy(ctx.skills, home, agentsHome), "skill-manager: shared invocation policy");
|
|
8382
|
-
}
|
|
8383
8207
|
ctx.effect(() => ctx.connection.fetch.register({
|
|
8384
8208
|
path: ROUTE,
|
|
8385
8209
|
methods: ["POST"],
|