@newlandnpt/pep-cli 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pep.cjs +79 -20
- package/package.json +1 -1
package/dist/pep.cjs
CHANGED
|
@@ -21,8 +21,8 @@ function issuerForEnvironment(environment) {
|
|
|
21
21
|
}
|
|
22
22
|
var BUILD_ENVIRONMENT = false ? "development" : "production";
|
|
23
23
|
var DEFAULT_ISSUER = issuerForEnvironment(BUILD_ENVIRONMENT);
|
|
24
|
-
function configuredIssuer(explicitIssuer
|
|
25
|
-
return explicitIssuer ??
|
|
24
|
+
function configuredIssuer(explicitIssuer) {
|
|
25
|
+
return explicitIssuer ?? DEFAULT_ISSUER;
|
|
26
26
|
}
|
|
27
27
|
function configDirectory() {
|
|
28
28
|
if (process.platform === "win32") return (0, import_node_path.join)((0, import_node_os.homedir)(), "AppData", "Roaming", "PEP");
|
|
@@ -38,6 +38,9 @@ function skillsStatePath() {
|
|
|
38
38
|
return (0, import_node_path.join)(configDirectory(), "skills.json");
|
|
39
39
|
}
|
|
40
40
|
function defaultSkillsDirectory() {
|
|
41
|
+
return (0, import_node_path.join)((0, import_node_os.homedir)(), ".agents", "skills");
|
|
42
|
+
}
|
|
43
|
+
function claudeSkillsDirectory() {
|
|
41
44
|
return (0, import_node_path.join)((0, import_node_os.homedir)(), ".claude", "skills");
|
|
42
45
|
}
|
|
43
46
|
function isCliConfig(value) {
|
|
@@ -73,7 +76,8 @@ function fileConfigStore(path = configPath()) {
|
|
|
73
76
|
function isSkillsState(value) {
|
|
74
77
|
if (typeof value !== "object" || value === null) return false;
|
|
75
78
|
const candidate = value;
|
|
76
|
-
return candidate.version === 1 && typeof candidate.directory === "string" && Array.isArray(candidate.skills) && candidate.skills.every((one) => typeof one === "string") && (candidate.commit === void 0 || typeof candidate.commit === "string")
|
|
79
|
+
return candidate.version === 1 && typeof candidate.directory === "string" && Array.isArray(candidate.skills) && candidate.skills.every((one) => typeof one === "string") && (candidate.commit === void 0 || typeof candidate.commit === "string") && // 可选:0.1.1 及更早写下的 skills.json 没有这个键,读它们不该报「状态损坏」。
|
|
80
|
+
(candidate.linkedInto === void 0 || typeof candidate.linkedInto === "string");
|
|
77
81
|
}
|
|
78
82
|
function fileSkillsStateStore(path = skillsStatePath()) {
|
|
79
83
|
return {
|
|
@@ -763,6 +767,7 @@ async function fetchDocContent(dependencies, path) {
|
|
|
763
767
|
|
|
764
768
|
// src/skills-service.ts
|
|
765
769
|
var import_promises3 = require("node:fs/promises");
|
|
770
|
+
var import_node_os2 = require("node:os");
|
|
766
771
|
var import_node_path3 = require("node:path");
|
|
767
772
|
var import_node_zlib = require("node:zlib");
|
|
768
773
|
|
|
@@ -852,11 +857,11 @@ function planSkillFiles(entries) {
|
|
|
852
857
|
);
|
|
853
858
|
}
|
|
854
859
|
const withoutRoot = segments.slice(1);
|
|
855
|
-
const
|
|
856
|
-
if (
|
|
860
|
+
const relative2 = withoutRoot[0] === SKILLS_SEGMENT ? withoutRoot.slice(1) : withoutRoot;
|
|
861
|
+
if (relative2.length < 2) continue;
|
|
857
862
|
files.push({
|
|
858
|
-
skill:
|
|
859
|
-
path:
|
|
863
|
+
skill: relative2[0],
|
|
864
|
+
path: relative2.slice(1).join("/"),
|
|
860
865
|
data: entry.data
|
|
861
866
|
});
|
|
862
867
|
}
|
|
@@ -876,6 +881,22 @@ function describeFailure2(status) {
|
|
|
876
881
|
}
|
|
877
882
|
return `PEP answered ${status}.`;
|
|
878
883
|
}
|
|
884
|
+
async function linkSkill(canonicalSkillDir, linkPath) {
|
|
885
|
+
await (0, import_promises3.rm)(linkPath, { recursive: true, force: true });
|
|
886
|
+
await (0, import_promises3.mkdir)((0, import_node_path3.dirname)(linkPath), { recursive: true });
|
|
887
|
+
try {
|
|
888
|
+
const junction = (0, import_node_os2.platform)() === "win32";
|
|
889
|
+
await (0, import_promises3.symlink)(
|
|
890
|
+
junction ? canonicalSkillDir : (0, import_node_path3.relative)((0, import_node_path3.dirname)(linkPath), canonicalSkillDir),
|
|
891
|
+
linkPath,
|
|
892
|
+
junction ? "junction" : void 0
|
|
893
|
+
);
|
|
894
|
+
return "linked";
|
|
895
|
+
} catch {
|
|
896
|
+
await (0, import_promises3.cp)(canonicalSkillDir, linkPath, { recursive: true });
|
|
897
|
+
return "copied";
|
|
898
|
+
}
|
|
899
|
+
}
|
|
879
900
|
async function syncSkills(dependencies) {
|
|
880
901
|
const doFetch = dependencies.fetch ?? globalThis.fetch;
|
|
881
902
|
const response = await doFetch(`${dependencies.issuer}${ARCHIVE_PATH}`, {
|
|
@@ -909,6 +930,16 @@ async function syncSkills(dependencies) {
|
|
|
909
930
|
await (0, import_promises3.mkdir)((0, import_node_path3.dirname)(target), { recursive: true });
|
|
910
931
|
await (0, import_promises3.writeFile)(target, file.data);
|
|
911
932
|
}
|
|
933
|
+
let copiedCount = 0;
|
|
934
|
+
if (dependencies.linkInto !== void 0) {
|
|
935
|
+
for (const skill of skills) {
|
|
936
|
+
const how = await linkSkill(
|
|
937
|
+
(0, import_node_path3.join)(dependencies.directory, skill),
|
|
938
|
+
(0, import_node_path3.join)(dependencies.linkInto, skill)
|
|
939
|
+
);
|
|
940
|
+
if (how === "copied") copiedCount += 1;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
912
943
|
const removed = (previous?.skills ?? []).filter(
|
|
913
944
|
(skill) => !skills.includes(skill)
|
|
914
945
|
);
|
|
@@ -917,11 +948,15 @@ async function syncSkills(dependencies) {
|
|
|
917
948
|
recursive: true,
|
|
918
949
|
force: true
|
|
919
950
|
});
|
|
951
|
+
if (previous?.linkedInto !== void 0) {
|
|
952
|
+
await (0, import_promises3.rm)((0, import_node_path3.join)(previous.linkedInto, skill), { recursive: true, force: true });
|
|
953
|
+
}
|
|
920
954
|
}
|
|
921
955
|
const state = {
|
|
922
956
|
version: 1,
|
|
923
957
|
skills,
|
|
924
958
|
directory: dependencies.directory,
|
|
959
|
+
...dependencies.linkInto !== void 0 ? { linkedInto: dependencies.linkInto } : {},
|
|
925
960
|
...commit ? { commit } : {}
|
|
926
961
|
};
|
|
927
962
|
await dependencies.stateStore.write(state);
|
|
@@ -931,12 +966,14 @@ async function syncSkills(dependencies) {
|
|
|
931
966
|
fileCount: files.length,
|
|
932
967
|
removed,
|
|
933
968
|
directory: dependencies.directory,
|
|
969
|
+
...dependencies.linkInto !== void 0 ? { linkedInto: dependencies.linkInto } : {},
|
|
970
|
+
...copiedCount > 0 ? { copiedCount } : {},
|
|
934
971
|
...commit ? { commit } : {}
|
|
935
972
|
};
|
|
936
973
|
}
|
|
937
974
|
|
|
938
975
|
// src/cli.ts
|
|
939
|
-
var VERSION = "0.1.
|
|
976
|
+
var VERSION = "0.1.2";
|
|
940
977
|
function usage() {
|
|
941
978
|
return `PEP CLI ${VERSION}
|
|
942
979
|
|
|
@@ -949,15 +986,22 @@ Usage:
|
|
|
949
986
|
pep docs list [--docs-url <url>]
|
|
950
987
|
pep docs get <path> [--docs-url <url>]
|
|
951
988
|
|
|
952
|
-
The issuer is built into this executable.
|
|
989
|
+
The issuer is built into this executable. --issuer overrides it for that one command and is
|
|
990
|
+
NOT remembered \u2014 pass it every time you log in against a non-default deployment.
|
|
953
991
|
--resource names which resource server the token is for (RFC 8707); repeat it for more than
|
|
954
992
|
one. It defaults to the docs platform \u2014 a token minted without it is rejected by every
|
|
955
993
|
resource server, and their answer looks exactly like "this token does not exist".
|
|
956
994
|
Use \`pep auth token\` when another agent needs a fresh bearer token.
|
|
957
995
|
|
|
958
|
-
\`pep skills sync\` fetches the latest skills from PEP and writes them
|
|
959
|
-
|
|
960
|
-
|
|
996
|
+
\`pep skills sync\` fetches the latest skills from PEP and writes them to the shared agent
|
|
997
|
+
directory (${defaultSkillsDirectory()}), which Codex, Cursor, Amp and ~20 other agents read
|
|
998
|
+
directly. Claude Code keeps its own directory, so each skill is also linked into
|
|
999
|
+
${claudeSkillsDirectory()} \u2014 one copy on disk, updated in one place. Where links are not
|
|
1000
|
+
available the skill is copied instead and the run says so.
|
|
1001
|
+
|
|
1002
|
+
--dir <path> writes to that path ONLY and skips the linking, for an agent that reads neither
|
|
1003
|
+
directory. Either way sync only touches skills it wrote itself; anything you put there by
|
|
1004
|
+
hand is left alone.
|
|
961
1005
|
|
|
962
1006
|
\`pep docs list\` prints the documents this account can read (path + description); feed a path
|
|
963
1007
|
straight to \`pep docs get\` to print that document as markdown on stdout. The documentation
|
|
@@ -982,15 +1026,21 @@ function option(args, name) {
|
|
|
982
1026
|
args.splice(index, 2);
|
|
983
1027
|
return value;
|
|
984
1028
|
}
|
|
985
|
-
async function loginConfig(args) {
|
|
986
|
-
const
|
|
987
|
-
const
|
|
988
|
-
const issuer = configuredIssuer(option(args, "--issuer"), saved?.issuer);
|
|
989
|
-
const clientId = option(args, "--client-id") ?? saved?.clientId ?? DEFAULT_CLIENT_ID;
|
|
1029
|
+
async function loginConfig(args, store = fileConfigStore()) {
|
|
1030
|
+
const issuer = configuredIssuer(option(args, "--issuer"));
|
|
1031
|
+
const clientId = option(args, "--client-id") ?? DEFAULT_CLIENT_ID;
|
|
990
1032
|
const explicit = repeatedOption(args, "--resource");
|
|
991
|
-
const resources = explicit.length > 0 ? explicit :
|
|
1033
|
+
const resources = explicit.length > 0 ? explicit : [...DEFAULT_RESOURCES];
|
|
992
1034
|
if (args.length > 0) throw new Error(`Unknown option: ${args[0]}`);
|
|
993
|
-
|
|
1035
|
+
const saved = await store.read();
|
|
1036
|
+
return {
|
|
1037
|
+
version: 1,
|
|
1038
|
+
issuer,
|
|
1039
|
+
clientId,
|
|
1040
|
+
redirectUri: DEFAULT_REDIRECT_URI,
|
|
1041
|
+
resources,
|
|
1042
|
+
...saved?.docsUrl !== void 0 ? { docsUrl: saved.docsUrl } : {}
|
|
1043
|
+
};
|
|
994
1044
|
}
|
|
995
1045
|
async function main() {
|
|
996
1046
|
const args = process.argv.slice(2);
|
|
@@ -1049,13 +1099,15 @@ ${usage()}`);
|
|
|
1049
1099
|
if (command !== "sync") throw new Error(`Unknown skills command.
|
|
1050
1100
|
|
|
1051
1101
|
${usage()}`);
|
|
1052
|
-
const
|
|
1102
|
+
const explicitDirectory = option(args, "--dir");
|
|
1103
|
+
const directory = explicitDirectory ?? defaultSkillsDirectory();
|
|
1053
1104
|
if (args.length > 0) throw new Error(`Unknown option: ${args[0]}`);
|
|
1054
1105
|
const authorization = await auth.currentAuthorization();
|
|
1055
1106
|
const result = await syncSkills({
|
|
1056
1107
|
issuer: authorization.issuer,
|
|
1057
1108
|
accessToken: authorization.accessToken,
|
|
1058
1109
|
directory,
|
|
1110
|
+
...explicitDirectory === void 0 ? { linkInto: claudeSkillsDirectory() } : {},
|
|
1059
1111
|
stateStore: fileSkillsStateStore()
|
|
1060
1112
|
});
|
|
1061
1113
|
if (result.status === "unchanged") {
|
|
@@ -1065,6 +1117,11 @@ ${usage()}`);
|
|
|
1065
1117
|
console.log(
|
|
1066
1118
|
`Wrote ${result.fileCount} file(s) across ${result.skills.length} skill(s) to ${result.directory}`
|
|
1067
1119
|
);
|
|
1120
|
+
if (result.linkedInto !== void 0) {
|
|
1121
|
+
console.log(
|
|
1122
|
+
result.copiedCount === void 0 ? `Linked into ${result.linkedInto} for Claude Code` : `Linked into ${result.linkedInto} for Claude Code (${result.copiedCount} copied instead \u2014 links unavailable here)`
|
|
1123
|
+
);
|
|
1124
|
+
}
|
|
1068
1125
|
if (result.commit) console.log(`Commit: ${result.commit}`);
|
|
1069
1126
|
if (result.removed.length > 0)
|
|
1070
1127
|
console.log(`Removed (gone upstream): ${result.removed.join(" ")}`);
|
|
@@ -1113,6 +1170,8 @@ ${url}`)
|
|
|
1113
1170
|
|
|
1114
1171
|
${usage()}`);
|
|
1115
1172
|
}
|
|
1173
|
+
|
|
1174
|
+
// src/main.ts
|
|
1116
1175
|
main().catch((error) => {
|
|
1117
1176
|
console.error(`pep: ${error.message}`);
|
|
1118
1177
|
process.exitCode = 1;
|