@newlandnpt/pep-cli 0.4.1 → 0.5.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 +17 -3
- package/dist/pep.cjs +40 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -137,9 +137,23 @@ pep skills add group/sub/project -p # move it into this project
|
|
|
137
137
|
`pep skills list` prints each repository with the directory it lives in, which is what `-p` matches
|
|
138
138
|
against.
|
|
139
139
|
|
|
140
|
-
Deleting a skill
|
|
141
|
-
|
|
142
|
-
|
|
140
|
+
### Deleting a skill
|
|
141
|
+
|
|
142
|
+
Delete a skill folder by hand and it **stays deleted**. `update` refreshes what is still on disk
|
|
143
|
+
and leaves the rest alone, naming them so the run is not silent:
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
group/sub/project: updated b
|
|
147
|
+
deleted locally, left alone: a
|
|
148
|
+
(`pep skills add group/sub/project` puts them back)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`add` is the command that installs, so that is what brings a deleted skill back. This split is
|
|
152
|
+
deliberate: `update` means "bring what I have up to date", not "refill everything the repository
|
|
153
|
+
offers".
|
|
154
|
+
|
|
155
|
+
Skills that are **new upstream** are still installed by `update` — the test is "was mine and is now
|
|
156
|
+
gone", not "is absent".
|
|
143
157
|
|
|
144
158
|
`pep auth token` writes only the access token to stdout, so agents can use it without parsing status
|
|
145
159
|
text. Refresh occurs automatically shortly before expiry and the rotated refresh token replaces the old
|
package/dist/pep.cjs
CHANGED
|
@@ -1195,14 +1195,17 @@ function hashSkill(files) {
|
|
|
1195
1195
|
}
|
|
1196
1196
|
return hash.digest("hex").slice(0, 32);
|
|
1197
1197
|
}
|
|
1198
|
-
|
|
1198
|
+
function pickSkipped(previous, skipped) {
|
|
1199
|
+
return Object.fromEntries(
|
|
1200
|
+
skipped.map((skill) => [skill, previous?.skills[skill] ?? ""])
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
async function missingSkills(directory, skills) {
|
|
1204
|
+
const gone = /* @__PURE__ */ new Set();
|
|
1199
1205
|
for (const skill of skills) {
|
|
1200
|
-
if (!await (0, import_promises4.stat)((0, import_node_path4.join)(directory, skill)).catch(() => null))
|
|
1201
|
-
if (linkedInto !== void 0 && !await (0, import_promises4.stat)((0, import_node_path4.join)(linkedInto, skill)).catch(() => null)) {
|
|
1202
|
-
return false;
|
|
1203
|
-
}
|
|
1206
|
+
if (!await (0, import_promises4.stat)((0, import_node_path4.join)(directory, skill)).catch(() => null)) gone.add(skill);
|
|
1204
1207
|
}
|
|
1205
|
-
return
|
|
1208
|
+
return gone;
|
|
1206
1209
|
}
|
|
1207
1210
|
async function updateSkills(dependencies) {
|
|
1208
1211
|
const doFetch = dependencies.fetch ?? globalThis.fetch;
|
|
@@ -1220,8 +1223,9 @@ async function updateSkills(dependencies) {
|
|
|
1220
1223
|
const state = await dependencies.stateStore.read();
|
|
1221
1224
|
const previous = state?.packages[name];
|
|
1222
1225
|
const sameTarget = previous?.directory === dependencies.directory && previous?.linkedInto === dependencies.linkInto;
|
|
1223
|
-
const
|
|
1224
|
-
|
|
1226
|
+
const gone = previous !== void 0 && sameTarget ? await missingSkills(previous.directory, Object.keys(previous.skills)) : /* @__PURE__ */ new Set();
|
|
1227
|
+
const nothingToRestore = !dependencies.restoreMissing || gone.size === 0;
|
|
1228
|
+
if (commit !== void 0 && commit === previous?.commit && sameTarget && nothingToRestore) {
|
|
1225
1229
|
await response.body?.cancel();
|
|
1226
1230
|
return { status: "unchanged", name, commit };
|
|
1227
1231
|
}
|
|
@@ -1233,7 +1237,9 @@ async function updateSkills(dependencies) {
|
|
|
1233
1237
|
if (group) group.push(file);
|
|
1234
1238
|
else bySkill.set(file.skill, [file]);
|
|
1235
1239
|
}
|
|
1236
|
-
const
|
|
1240
|
+
const inArchive = [...bySkill.keys()].sort();
|
|
1241
|
+
const skipped = dependencies.restoreMissing ? [] : inArchive.filter((skill) => gone.has(skill));
|
|
1242
|
+
const skills = inArchive.filter((skill) => !skipped.includes(skill));
|
|
1237
1243
|
const hashes = {};
|
|
1238
1244
|
const updated = [];
|
|
1239
1245
|
const unchanged = [];
|
|
@@ -1241,10 +1247,11 @@ async function updateSkills(dependencies) {
|
|
|
1241
1247
|
const hash = hashSkill(bySkill.get(skill));
|
|
1242
1248
|
hashes[skill] = hash;
|
|
1243
1249
|
const before = previous?.skills[skill];
|
|
1244
|
-
if (
|
|
1250
|
+
if (gone.has(skill)) updated.push(skill);
|
|
1251
|
+
else if (before !== void 0 && before !== "" && before === hash) unchanged.push(skill);
|
|
1245
1252
|
else updated.push(skill);
|
|
1246
1253
|
}
|
|
1247
|
-
const removed = Object.keys(previous?.skills ?? {}).filter((skill) => !
|
|
1254
|
+
const removed = Object.keys(previous?.skills ?? {}).filter((skill) => !inArchive.includes(skill));
|
|
1248
1255
|
if (previous !== void 0) {
|
|
1249
1256
|
const stale = sameTarget ? removed : Object.keys(previous.skills);
|
|
1250
1257
|
for (const skill of stale) {
|
|
@@ -1258,6 +1265,7 @@ async function updateSkills(dependencies) {
|
|
|
1258
1265
|
await (0, import_promises4.rm)((0, import_node_path4.join)(dependencies.directory, skill), { recursive: true, force: true });
|
|
1259
1266
|
}
|
|
1260
1267
|
for (const file of files) {
|
|
1268
|
+
if (skipped.includes(file.skill)) continue;
|
|
1261
1269
|
const target = (0, import_node_path4.join)(dependencies.directory, file.skill, ...file.path.split("/"));
|
|
1262
1270
|
await (0, import_promises4.mkdir)((0, import_node_path4.dirname)(target), { recursive: true });
|
|
1263
1271
|
await (0, import_promises4.writeFile)(target, file.data);
|
|
@@ -1282,7 +1290,9 @@ async function updateSkills(dependencies) {
|
|
|
1282
1290
|
...commit ? { commit } : {},
|
|
1283
1291
|
directory: dependencies.directory,
|
|
1284
1292
|
...dependencies.linkInto !== void 0 ? { linkedInto: dependencies.linkInto } : {},
|
|
1285
|
-
|
|
1293
|
+
// 跳过的那些**原样留着上次的哈希** —— 账上仍然认它是这个包的(将来 add 能补回来,
|
|
1294
|
+
// 上游删掉时也还清得动),只是这次没去碰它。
|
|
1295
|
+
skills: { ...pickSkipped(previous, skipped), ...hashes }
|
|
1286
1296
|
}
|
|
1287
1297
|
}
|
|
1288
1298
|
});
|
|
@@ -1292,8 +1302,9 @@ async function updateSkills(dependencies) {
|
|
|
1292
1302
|
updated,
|
|
1293
1303
|
unchanged,
|
|
1294
1304
|
skills,
|
|
1295
|
-
fileCount: files.length,
|
|
1305
|
+
fileCount: files.filter((one) => !skipped.includes(one.skill)).length,
|
|
1296
1306
|
removed,
|
|
1307
|
+
skipped,
|
|
1297
1308
|
directory: dependencies.directory,
|
|
1298
1309
|
...dependencies.linkInto !== void 0 ? { linkedInto: dependencies.linkInto } : {},
|
|
1299
1310
|
...copiedCount > 0 ? { copiedCount } : {},
|
|
@@ -1302,7 +1313,7 @@ async function updateSkills(dependencies) {
|
|
|
1302
1313
|
}
|
|
1303
1314
|
|
|
1304
1315
|
// src/cli.ts
|
|
1305
|
-
var VERSION = false ? "0.0.0-dev" : "0.
|
|
1316
|
+
var VERSION = false ? "0.0.0-dev" : "0.5.0";
|
|
1306
1317
|
function usage() {
|
|
1307
1318
|
return `PEP CLI ${VERSION}
|
|
1308
1319
|
|
|
@@ -1358,8 +1369,10 @@ it already lives and never moves anything. On update, -p and --dir instead NARRO
|
|
|
1358
1369
|
repositories installed there: \`pep skills update -p\` refreshes only this project's, and reports
|
|
1359
1370
|
nothing to do when the project has none. To move a repository, add it again with the new flag \u2014
|
|
1360
1371
|
add is where the location is decided, and the copy in the old location is then removed.
|
|
1361
|
-
|
|
1362
|
-
|
|
1372
|
+
Delete a skill folder by hand and update LEAVES IT DELETED \u2014 it refreshes what is still there and
|
|
1373
|
+
reports the ones it left alone. Run \`pep skills add <repo>\` to put them back; add is the command
|
|
1374
|
+
that installs. Either way update only touches skills it wrote itself; anything you put there by
|
|
1375
|
+
hand is left alone.
|
|
1363
1376
|
|
|
1364
1377
|
\`pep docs list\` prints the documents this account can read (path + description); feed a path
|
|
1365
1378
|
straight to \`pep docs get\` to print that document as markdown on stdout. The documentation
|
|
@@ -1386,6 +1399,10 @@ function reportUpdate(result) {
|
|
|
1386
1399
|
if (result.unchanged.length > 0) {
|
|
1387
1400
|
console.log(` unchanged: ${result.unchanged.join(" ")}`);
|
|
1388
1401
|
}
|
|
1402
|
+
if (result.skipped.length > 0) {
|
|
1403
|
+
console.log(` deleted locally, left alone: ${result.skipped.join(" ")}`);
|
|
1404
|
+
console.log(` (\`pep skills add ${result.name}\` puts them back)`);
|
|
1405
|
+
}
|
|
1389
1406
|
console.log(` ${result.fileCount} file(s) in ${result.directory}`);
|
|
1390
1407
|
if (result.linkedInto !== void 0) {
|
|
1391
1408
|
console.log(
|
|
@@ -1576,17 +1593,22 @@ ${usage()}`);
|
|
|
1576
1593
|
const stateStore = fileSkillsStateStore();
|
|
1577
1594
|
const state = await stateStore.read();
|
|
1578
1595
|
const installed = Object.keys(state?.packages ?? {}).sort();
|
|
1579
|
-
const run2 = async (source, target) => reportUpdate(
|
|
1596
|
+
const run2 = async (source, target, restoreMissing = false) => reportUpdate(
|
|
1580
1597
|
await updateSkills({
|
|
1581
1598
|
...remote,
|
|
1582
1599
|
source,
|
|
1583
1600
|
directory: target.directory,
|
|
1584
1601
|
...target.linkInto !== void 0 ? { linkInto: target.linkInto } : {},
|
|
1602
|
+
...restoreMissing ? { restoreMissing: true } : {},
|
|
1585
1603
|
stateStore
|
|
1586
1604
|
})
|
|
1587
1605
|
);
|
|
1588
1606
|
if (command === "add") {
|
|
1589
|
-
await run2(
|
|
1607
|
+
await run2(
|
|
1608
|
+
requested,
|
|
1609
|
+
targetForSource(chosenTarget, state?.packages[requested]),
|
|
1610
|
+
true
|
|
1611
|
+
);
|
|
1590
1612
|
return;
|
|
1591
1613
|
}
|
|
1592
1614
|
if (installed.length === 0) {
|