@arshdelight/practi 0.9.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.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -0
  3. package/dist/client.js +84 -0
  4. package/dist/client.js.map +1 -0
  5. package/dist/cmd/blob.js +97 -0
  6. package/dist/cmd/blob.js.map +1 -0
  7. package/dist/cmd/clone.js +76 -0
  8. package/dist/cmd/clone.js.map +1 -0
  9. package/dist/cmd/comment.js +210 -0
  10. package/dist/cmd/comment.js.map +1 -0
  11. package/dist/cmd/config.js +30 -0
  12. package/dist/cmd/config.js.map +1 -0
  13. package/dist/cmd/edit.js +122 -0
  14. package/dist/cmd/edit.js.map +1 -0
  15. package/dist/cmd/init.js +11 -0
  16. package/dist/cmd/init.js.map +1 -0
  17. package/dist/cmd/lifecycle.js +69 -0
  18. package/dist/cmd/lifecycle.js.map +1 -0
  19. package/dist/cmd/login.js +125 -0
  20. package/dist/cmd/login.js.map +1 -0
  21. package/dist/cmd/ls.js +59 -0
  22. package/dist/cmd/ls.js.map +1 -0
  23. package/dist/cmd/new.js +57 -0
  24. package/dist/cmd/new.js.map +1 -0
  25. package/dist/cmd/pull.js +94 -0
  26. package/dist/cmd/pull.js.map +1 -0
  27. package/dist/cmd/push.js +84 -0
  28. package/dist/cmd/push.js.map +1 -0
  29. package/dist/cmd/remote.js +48 -0
  30. package/dist/cmd/remote.js.map +1 -0
  31. package/dist/cmd/search.js +137 -0
  32. package/dist/cmd/search.js.map +1 -0
  33. package/dist/cmd/show.js +61 -0
  34. package/dist/cmd/show.js.map +1 -0
  35. package/dist/cmd/skill.js +198 -0
  36. package/dist/cmd/skill.js.map +1 -0
  37. package/dist/cmd/spec.js +10 -0
  38. package/dist/cmd/spec.js.map +1 -0
  39. package/dist/cmd/update.js +60 -0
  40. package/dist/cmd/update.js.map +1 -0
  41. package/dist/credentials.js +65 -0
  42. package/dist/credentials.js.map +1 -0
  43. package/dist/index.js +412 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/oauth.js +244 -0
  46. package/dist/oauth.js.map +1 -0
  47. package/dist/render.js +25 -0
  48. package/dist/render.js.map +1 -0
  49. package/dist/state.js +74 -0
  50. package/dist/state.js.map +1 -0
  51. package/dist/version.js +12 -0
  52. package/dist/version.js.map +1 -0
  53. package/dist/web.js +243 -0
  54. package/dist/web.js.map +1 -0
  55. package/dist/workspace.js +38 -0
  56. package/dist/workspace.js.map +1 -0
  57. package/package.json +48 -0
  58. package/skills/use-practi/SKILL.md +186 -0
@@ -0,0 +1,84 @@
1
+ import { exportSubtree, resolveNodeRef } from '@arshdelight/pop-sdk';
2
+ import { defaultDataDir, loadState } from '../state.js';
3
+ import { openWorkspace } from '../workspace.js';
4
+ import { authedFetch, fetchMine } from '../client.js';
5
+ /**
6
+ * practi push [hash]:把本地认领增量推送到 practihub(git push 的对象协商语义)。
7
+ * - 先分页取 hub 上「我的」认领表(mine),diff 出本地认领而 hub 我还没认领的,
8
+ * 只传这些(带 hash 只推该 direct;不带推全部 direct)——不再全量 POST。
9
+ * - 走 POST /api/v1/pop(内容寻址幂等):hub 没有就存,有则 idempotent 不重复写,
10
+ * 且每次上传都获得 DIRECT 认领。默认存为 PRIVATE;公开仍需 submit 审核。
11
+ */
12
+ export async function runPush(opts) {
13
+ const dataDir = opts.dataDir ?? defaultDataDir();
14
+ const state = loadState(dataDir);
15
+ if (!state.remote) {
16
+ console.error('error: no remote configured — run `practi remote set <url>` first');
17
+ return 1;
18
+ }
19
+ const ws = openWorkspace(dataDir);
20
+ const targets = opts.positional[0] ? [opts.positional[0]] : state.direct;
21
+ if (targets.length === 0) {
22
+ console.error('error: no direct pops to push (none registered)');
23
+ return 1;
24
+ }
25
+ // 认领表 diff 的基准:hub 上我已认领的 hash 集合
26
+ let mineHashes;
27
+ try {
28
+ const mine = await fetchMine(dataDir, state.remote.url);
29
+ mineHashes = new Set(mine.map((r) => r.root_hash));
30
+ }
31
+ catch (e) {
32
+ console.error(`error: ${e.message}`);
33
+ return 1;
34
+ }
35
+ // 解析目标为完整 hash,只保留本地认领而 hub 我还没认领的(增量)
36
+ const toPush = [];
37
+ let failed = 0;
38
+ for (const ref of targets) {
39
+ let resolved;
40
+ try {
41
+ resolved = resolveNodeRef(ws, ref);
42
+ }
43
+ catch (e) {
44
+ console.error(`push failed: ${ref} — ${e.message}`);
45
+ failed++;
46
+ continue;
47
+ }
48
+ if (!mineHashes.has(resolved))
49
+ toPush.push(resolved);
50
+ }
51
+ if (toPush.length === 0) {
52
+ console.log('up to date — no new direct pops to push');
53
+ return failed ? 1 : 0;
54
+ }
55
+ for (const ref of toPush) {
56
+ try {
57
+ const node = ws.nodes.get(ref);
58
+ if (!node)
59
+ throw new Error(`node not found: ${ref}`);
60
+ const doc = exportSubtree(node, ws.nodes);
61
+ const res = await authedFetch(dataDir, state.remote.url, '/api/v1/pop', {
62
+ method: 'POST',
63
+ headers: { 'content-type': 'application/json' },
64
+ body: JSON.stringify(doc),
65
+ });
66
+ const body = (await res.json().catch(() => ({})));
67
+ if (!res.ok) {
68
+ const detail = typeof body.message === 'string' ? body.message : typeof body.error === 'string' ? body.error : `HTTP ${res.status}`;
69
+ console.error(`push failed: ${ref} — ${detail}`);
70
+ failed++;
71
+ continue;
72
+ }
73
+ const name = doc.name ?? '';
74
+ const status = String(body.status ?? 'PRIVATE');
75
+ console.log(`pushed: ${ref} (${body.idempotent ? 'already existed' : 'stored'}, ${status}) ${name}`);
76
+ }
77
+ catch (e) {
78
+ console.error(`push failed: ${ref} — ${e.message}`);
79
+ failed++;
80
+ }
81
+ }
82
+ return failed ? 1 : 0;
83
+ }
84
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/cmd/push.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { defaultDataDir, loadState, saveState } from '../state.js';
2
+ import { loadCredentials, deleteCredentials } from '../credentials.js';
3
+ import { cliResource, revokeToken } from '../oauth.js';
4
+ export async function runRemote(opts) {
5
+ const dataDir = opts.dataDir ?? defaultDataDir();
6
+ const state = loadState(dataDir);
7
+ const action = opts.positional[0] ?? 'show';
8
+ switch (action) {
9
+ case 'set': {
10
+ const url = opts.positional[1];
11
+ if (!url) {
12
+ console.error('usage: practi remote set <url> e.g. practi remote set https://practihub.com');
13
+ return 1;
14
+ }
15
+ if (!/^https?:\/\/\S+$/i.test(url)) {
16
+ console.error(`error: "${url}" is not an http(s) URL`);
17
+ return 1;
18
+ }
19
+ state.remote = { url: url.replace(/\/+$/, '') };
20
+ saveState(dataDir, state);
21
+ console.log(`remote set: ${state.remote.url}`);
22
+ // 换 hub 时,旧 hub 签发的凭据对新 remote 无用:revoke(best-effort,打给旧 hub)并清除
23
+ const creds = loadCredentials(dataDir);
24
+ if (creds && creds.resource && creds.resource !== cliResource(state.remote.url)) {
25
+ const oldOrigin = creds.resource.replace(/\/cli$/, '');
26
+ if (oldOrigin)
27
+ await revokeToken(oldOrigin, creds.client_id, creds.refresh_token, 'refresh_token');
28
+ deleteCredentials(dataDir);
29
+ console.log(`note: cleared credentials issued by ${oldOrigin} — run \`practi login\` against ${state.remote.url}`);
30
+ }
31
+ return 0;
32
+ }
33
+ case 'remove': {
34
+ delete state.remote;
35
+ saveState(dataDir, state);
36
+ console.log('remote removed');
37
+ return 0;
38
+ }
39
+ case 'show': {
40
+ console.log(state.remote ? state.remote.url : '(not set)');
41
+ return 0;
42
+ }
43
+ default:
44
+ console.error(`usage: practi remote set <url> | show | remove`);
45
+ return 1;
46
+ }
47
+ }
48
+ //# sourceMappingURL=remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../src/cmd/remote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAOvD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAgB;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,cAAc,EAAE,CAAC;IACjD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;IAE5C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,OAAO,CAAC,KAAK,CAAC,+EAA+E,CAAC,CAAC;gBAC/F,OAAO,CAAC,CAAC;YACX,CAAC;YACD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnC,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,yBAAyB,CAAC,CAAC;gBACvD,OAAO,CAAC,CAAC;YACX,CAAC;YACD,KAAK,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;YAChD,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;YAC/C,iEAAiE;YACjE,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YACvC,IAAI,KAAK,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChF,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACvD,IAAI,SAAS;oBAAE,MAAM,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;gBACnG,iBAAiB,CAAC,OAAO,CAAC,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,uCAAuC,SAAS,mCAAmC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;YACrH,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,OAAO,KAAK,CAAC,MAAM,CAAC;YACpB,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC9B,OAAO,CAAC,CAAC;QACX,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;YAC3D,OAAO,CAAC,CAAC;QACX,CAAC;QACD;YACE,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;YAChE,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,137 @@
1
+ import { defaultDataDir, loadState } from '../state.js';
2
+ import { openWorkspace } from '../workspace.js';
3
+ import { authedFetch } from '../client.js';
4
+ import { shortHash } from '../render.js';
5
+ /**
6
+ * practi search <query...>:在 remote 上检索 POP(GET /api/v1/pop/search)。
7
+ * - 标题与内容都参与匹配,标题命中优先(服务端排序)。
8
+ * - --scope public=公开库(默认,仅 PUBLISHED);me=自己 direct 认领(全状态);all=并集。
9
+ * - 空 q(`practi search`)返回最近文档,可当浏览用。
10
+ */
11
+ export async function runSearch(opts) {
12
+ const dataDir = opts.dataDir ?? defaultDataDir();
13
+ const q = opts.positional.join(' ').trim();
14
+ if (opts.local)
15
+ return runLocalSearch(opts, dataDir, q);
16
+ const state = loadState(dataDir);
17
+ if (!state.remote) {
18
+ console.error('error: no remote configured — run `practi remote set <url>` first');
19
+ return 1;
20
+ }
21
+ if (!['public', 'me', 'all'].includes(opts.scope)) {
22
+ console.error("error: invalid scope — expected public | me | all");
23
+ return 1;
24
+ }
25
+ const params = new URLSearchParams({ q, scope: opts.scope, limit: String(opts.limit) });
26
+ const res = await authedFetch(dataDir, state.remote.url, `/api/v1/pop/search?${params.toString()}`);
27
+ const body = (await res.json().catch(() => ({})));
28
+ if (!res.ok) {
29
+ const detail = typeof body.message === 'string' ? body.message : typeof body.error === 'string' ? body.error : `HTTP ${res.status}`;
30
+ console.error(`search failed: ${detail}`);
31
+ return 1;
32
+ }
33
+ const results = body.results ?? [];
34
+ if (opts.json) {
35
+ console.log(JSON.stringify(body, null, 2));
36
+ return 0;
37
+ }
38
+ if (results.length === 0) {
39
+ console.log(q ? `no results for "${q}" (scope: ${opts.scope})` : `no documents yet (scope: ${opts.scope})`);
40
+ return 0;
41
+ }
42
+ for (const r of results) {
43
+ const desc = r.description ? ` — ${r.description}` : '';
44
+ const author = r.authorName ? ` @${r.authorName}` : '';
45
+ console.log(` ${shortHash(r.root_hash)} [${r.status}] ${r.name}${desc}${author}`);
46
+ console.log(` ${r.root_hash}`);
47
+ }
48
+ console.log(`\n${results.length} shown (total ${body.total ?? results.length}, scope: ${opts.scope}) — fetch one with \`practi pull <hash>\``);
49
+ return 0;
50
+ }
51
+ /**
52
+ * --local:本地工作区检索,不碰 remote。
53
+ * - 遍历全部已存节点(含 indirect),对 name/description/content 做大小写不敏感子串匹配;
54
+ * 纯 hex 查询词(≥4 位)额外按哈希前缀匹配。
55
+ * - 输出按 direct 树的深度优先步骤顺序排列,共享子树只出现一次并标注全部所属根。
56
+ * - 空查询 = 浏览 direct 根(带各树节点数);--limit 同样生效。
57
+ */
58
+ function runLocalSearch(opts, dataDir, q) {
59
+ const ws = openWorkspace(dataDir);
60
+ const state = loadState(dataDir);
61
+ const direct = state.direct.filter((h) => ws.nodes.has(h));
62
+ const directSet = new Set(direct);
63
+ // 包含关系:节点 → 所属 direct 根(共享子树可属多个根);根 → 树内节点数
64
+ const owner = new Map();
65
+ const size = new Map();
66
+ for (const root of direct) {
67
+ const seen = new Set();
68
+ const stack = [root];
69
+ while (stack.length > 0) {
70
+ const h = stack.pop();
71
+ if (seen.has(h))
72
+ continue;
73
+ seen.add(h);
74
+ const list = owner.get(h) ?? [];
75
+ if (!list.includes(root))
76
+ list.push(root);
77
+ owner.set(h, list);
78
+ const n = ws.nodes.get(h);
79
+ if (n?.type === 'practice')
80
+ for (const c of n.children)
81
+ stack.push(c.hash);
82
+ }
83
+ size.set(root, seen.size);
84
+ }
85
+ const needle = q.toLowerCase();
86
+ const hits = [];
87
+ const emitted = new Set();
88
+ const visit = (h) => {
89
+ if (emitted.has(h))
90
+ return;
91
+ emitted.add(h);
92
+ const n = ws.nodes.get(h);
93
+ if (!n)
94
+ return;
95
+ const text = `${n.name}\n${n.description ?? ''}\n${n.content ?? ''}`.toLowerCase();
96
+ const hashHit = /^[0-9a-f]{4,64}$/.test(needle) && h.startsWith(`sha256:${needle}`);
97
+ const matched = !needle || text.includes(needle) || hashHit;
98
+ if (matched && (needle !== '' || directSet.has(h))) {
99
+ hits.push({
100
+ hash: h,
101
+ type: n.type,
102
+ ...(n.type === 'practice' ? { op: n.op } : {}),
103
+ name: n.name,
104
+ direct: directSet.has(h),
105
+ roots: (owner.get(h) ?? []).filter((r) => r !== h).map((r) => ({ hash: r, name: ws.nodes.get(r)?.name ?? r })),
106
+ ...(size.has(h) ? { size: size.get(h) } : {}),
107
+ });
108
+ }
109
+ if (n.type === 'practice')
110
+ for (const c of n.children)
111
+ visit(c.hash);
112
+ };
113
+ for (const root of direct)
114
+ visit(root);
115
+ const total = hits.length;
116
+ const shown = hits.slice(0, opts.limit);
117
+ if (opts.json) {
118
+ console.log(JSON.stringify({ query: q, local: true, results: shown, total }, null, 2));
119
+ return 0;
120
+ }
121
+ if (total === 0) {
122
+ console.log(needle ? `no local matches for "${q}"` : '(no direct pops in this workspace)');
123
+ return 0;
124
+ }
125
+ for (const hit of shown) {
126
+ const tag = hit.type === 'practice' ? `[practice·${hit.op}]` : '[action]';
127
+ const where = hit.direct
128
+ ? `direct root, ${hit.size} nodes`
129
+ : hit.roots.map((r) => `in ${shortHash(r.hash)} (${r.name})`).join('; ');
130
+ console.log(` ${shortHash(hit.hash)} ${tag} ${hit.name}`);
131
+ console.log(` ${where}`);
132
+ }
133
+ const label = needle ? `${shown.length} matched` : `${shown.length} direct POP(s), ${ws.nodes.size} nodes`;
134
+ console.log(`\n${label} (local workspace) — inspect with \`practi show <hash>\``);
135
+ return 0;
136
+ }
137
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/cmd/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import { aggregateView, exportSubtree, resolveNodeRef } from '@arshdelight/pop-sdk';
2
+ import { defaultDataDir } from '../state.js';
3
+ import { openWorkspace } from '../workspace.js';
4
+ import { renderSteps, viewHeader } from '../render.js';
5
+ /** Inspect one node: aggregate view (default), --json for the StandardView, --doc for the document form */
6
+ export function runShow(opts) {
7
+ const dataDir = opts.dataDir ?? defaultDataDir();
8
+ const ws = openWorkspace(dataDir);
9
+ const hash = resolveNodeRef(ws, opts.hash);
10
+ const node = ws.nodes.get(hash);
11
+ if (opts.doc) {
12
+ console.log(JSON.stringify(exportSubtree(node, ws.nodes), null, 2));
13
+ return 0;
14
+ }
15
+ const view = aggregateView(hash, ws.nodes);
16
+ if (opts.json) {
17
+ console.log(JSON.stringify(view, null, 2));
18
+ return 0;
19
+ }
20
+ console.log(viewHeader(view));
21
+ if (view.description !== undefined)
22
+ console.log(`\ndescription: ${view.description}`);
23
+ if (view.content !== undefined && view.content.trim() !== '')
24
+ console.log(`\n${view.content}`);
25
+ if (view.steps.length > 0) {
26
+ console.log('\nsteps:');
27
+ for (const line of renderSteps(view.steps, ws.nodes))
28
+ console.log(` ${line}`);
29
+ }
30
+ if (view.flow.length > 0) {
31
+ console.log('\nflow:');
32
+ for (const e of view.flow) {
33
+ console.log(` ${e.name} ${short(e.fromHash)} (${e.fromName}) → ${short(e.toHash)} (${e.toName})`);
34
+ }
35
+ }
36
+ if (view.inputs.length > 0) {
37
+ console.log('\ndeclared inputs (needs):');
38
+ for (const d of view.inputs)
39
+ console.log(` ${d.name}${d.spec ? ` — ${d.spec}` : ''} [${short(d.refHash)}]`);
40
+ }
41
+ if (view.outputs.length > 0) {
42
+ console.log('\ndeclared outputs (produces):');
43
+ for (const d of view.outputs)
44
+ console.log(` ${d.name}${d.spec ? ` — ${d.spec}` : ''} [${short(d.refHash)}]`);
45
+ }
46
+ if (view.attachments.length > 0) {
47
+ console.log('\nattachments:');
48
+ for (const a of view.attachments)
49
+ console.log(` ${a.name} ${a.mime ?? ''} ${a.size ?? ''}b ${short(a.hash)}`);
50
+ }
51
+ if (view.revisions !== undefined && view.revisions.length > 0) {
52
+ console.log('\nrevisions:');
53
+ for (const r of view.revisions)
54
+ console.log(` ${r.when} ${r.what}${r.from ? ` (from ${short(r.from)})` : ''}`);
55
+ }
56
+ return 0;
57
+ }
58
+ function short(hash) {
59
+ return hash.slice('sha256:'.length, 'sha256:'.length + 12);
60
+ }
61
+ //# sourceMappingURL=show.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/cmd/show.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,198 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { exportSkill, importSkill, PracticeError, resolveNodeRef } from '@arshdelight/pop-sdk';
6
+ import { defaultDataDir, loadState, saveState } from '../state.js';
7
+ import { openWorkspace } from '../workspace.js';
8
+ /**
9
+ * practi skill 子命令:
10
+ * - install|update|uninstall:管理随 CLI 打包的 use-practi agent skill。
11
+ * 源:包内 skills/use-practi(package.json files 已含)。仓库根 skills/use-practi
12
+ * 是标准(npx skills 从仓库安装),CI 锁两份逐字节一致。
13
+ * 该 skill 是手写维护的(SKILL.md 即源,无 pop.doc.json sidecar,不从 POP 导出)。
14
+ * 目标:默认 ~/.agents/skills(跨 agent 约定目录,与 npx skills 的落点相同),
15
+ * --dir <skills-dir> 覆盖;安装形态 <skills-dir>/use-practi/SKILL.md。
16
+ * install 幂等同步(含清理源里已不存在的陈旧文件),并顺带移除改名前安装的
17
+ * 旧 use-pop 目录(CLI 自管产物);update 要求已安装;uninstall 删整个目录。
18
+ * - import|export:skill ⇄ POP 转换(spec §1/§8)。
19
+ * export 把 workspace 里的 POP 投影成可安装的技能目录(SKILL.md + 附件 +
20
+ * pop.doc.json sidecar);import 是它的逆运算——sidecar 精确回放(附件文件
21
+ * 重新入库并验哈希),无 sidecar 的外来技能目录被拒绝(E_NO_SIDECAR):
22
+ * 外来 skill 靠重新撰写进入 POP,不做机械压平。
23
+ */
24
+ const SKILL_NAME = 'use-practi';
25
+ const LEGACY_SKILL_NAME = 'use-pop';
26
+ function sourceDir() {
27
+ // dist/cmd/skill.js → 包根 → skills/use-practi(源码运行与 npm 安装布局同构)
28
+ return fileURLToPath(new URL('../../skills/use-practi', import.meta.url));
29
+ }
30
+ function listFiles(dir, base = dir, out = []) {
31
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
32
+ const full = path.join(dir, e.name);
33
+ if (e.isDirectory())
34
+ listFiles(full, base, out);
35
+ else if (e.isFile())
36
+ out.push(path.relative(base, full).split(path.sep).join('/'));
37
+ }
38
+ return out;
39
+ }
40
+ function sameBytes(a, b) {
41
+ const fa = fs.readFileSync(a);
42
+ const fb = fs.readFileSync(b);
43
+ return fa.length === fb.length && fa.equals(fb);
44
+ }
45
+ const kb = (n) => (n < 1024 ? `${n} B` : `${(n / 1024).toFixed(1)} KB`);
46
+ /** 把包内 skill 目录同步到 target:写入缺失/有差异的文件,清理源里已不存在的陈旧文件 */
47
+ function syncTo(src, target) {
48
+ const files = listFiles(src);
49
+ const want = new Set(files);
50
+ let written = 0;
51
+ let unchanged = 0;
52
+ for (const rel of files) {
53
+ const from = path.join(src, rel);
54
+ const to = path.join(target, rel);
55
+ if (fs.existsSync(to) && sameBytes(from, to)) {
56
+ unchanged++;
57
+ continue;
58
+ }
59
+ fs.mkdirSync(path.dirname(to), { recursive: true });
60
+ fs.copyFileSync(from, to);
61
+ console.log(` ${rel} written (${kb(fs.statSync(from).size)})`);
62
+ written++;
63
+ }
64
+ let pruned = 0;
65
+ if (fs.existsSync(target)) {
66
+ for (const rel of listFiles(target)) {
67
+ if (!want.has(rel)) {
68
+ fs.rmSync(path.join(target, rel));
69
+ console.log(` ${rel} pruned (no longer in the package)`);
70
+ pruned++;
71
+ }
72
+ }
73
+ }
74
+ return { written, unchanged, pruned };
75
+ }
76
+ export function runSkill(opts) {
77
+ if (opts.action === 'import')
78
+ return runSkillImport(opts);
79
+ if (opts.action === 'export')
80
+ return runSkillExport(opts);
81
+ const skillsDir = opts.dir ? path.resolve(opts.dir) : path.join(os.homedir(), '.agents', 'skills');
82
+ const target = path.join(skillsDir, SKILL_NAME);
83
+ if (opts.action === 'uninstall') {
84
+ if (!fs.existsSync(target)) {
85
+ console.error(`error: nothing to remove — ${target} does not exist`);
86
+ return 1;
87
+ }
88
+ if (!fs.existsSync(path.join(target, 'SKILL.md'))) {
89
+ console.error(`error: ${target} exists but has no SKILL.md — does not look like the ${SKILL_NAME} skill; remove it manually`);
90
+ return 1;
91
+ }
92
+ fs.rmSync(target, { recursive: true });
93
+ console.log(`removed: ${SKILL_NAME} → ${target}`);
94
+ return 0;
95
+ }
96
+ const src = sourceDir();
97
+ if (!fs.existsSync(src)) {
98
+ console.error(`error: bundled skill not found at ${src} — the cli package is broken; reinstall it (npm install -g @arshdelight/practi)`);
99
+ return 1;
100
+ }
101
+ if (opts.action === 'update' && !fs.existsSync(target)) {
102
+ console.error(`error: ${SKILL_NAME} is not installed in ${skillsDir} — run \`practi skill install\` first`);
103
+ return 1;
104
+ }
105
+ const existed = fs.existsSync(target);
106
+ const { written, unchanged, pruned } = syncTo(src, target);
107
+ if (written === 0 && pruned === 0) {
108
+ console.log(`up to date: ${SKILL_NAME} → ${target} (${unchanged} file(s), nothing changed)`);
109
+ }
110
+ else {
111
+ const verb = existed ? 'updated' : 'installed';
112
+ console.log(`${verb}: ${SKILL_NAME} → ${target} (${written} written, ${unchanged} unchanged${pruned > 0 ? `, ${pruned} pruned` : ''})`);
113
+ }
114
+ // 改名迁移:旧 CLI 装的 use-pop 是本 CLI 自管产物,装新版时顺带移除,避免两份并存
115
+ const legacyTarget = path.join(skillsDir, LEGACY_SKILL_NAME);
116
+ if (fs.existsSync(path.join(legacyTarget, 'SKILL.md'))) {
117
+ fs.rmSync(legacyTarget, { recursive: true });
118
+ console.log(`removed: ${LEGACY_SKILL_NAME} → ${legacyTarget} (replaced by ${SKILL_NAME})`);
119
+ }
120
+ return 0;
121
+ }
122
+ /** 技能目录名兜底:非 ASCII 名(如中文)slug 后为空 → 用 hash 前缀 */
123
+ function slugOrHash(name, hash) {
124
+ const slug = name
125
+ .toLowerCase()
126
+ .replace(/[^a-z0-9-]+/g, '-')
127
+ .replace(/^-+|-+$/g, '')
128
+ .replace(/-{2,}/g, '-');
129
+ return slug !== '' ? slug : hash.slice('sha256:'.length, 'sha256:'.length + 12);
130
+ }
131
+ /** practi skill import <dir>:回放 `practi skill export` 导出的目录(sidecar 精确复放,附件重新入库)+ 注册 direct */
132
+ function runSkillImport(opts) {
133
+ if (!opts.positional) {
134
+ console.error('usage: practi skill import <skill-dir> [--data-dir <dir>]');
135
+ return 1;
136
+ }
137
+ const dataDir = opts.dataDir ? path.resolve(opts.dataDir) : defaultDataDir();
138
+ const skillDir = path.resolve(opts.positional);
139
+ const ws = openWorkspace(dataDir);
140
+ const warns = [];
141
+ let res;
142
+ try {
143
+ res = importSkill(ws, skillDir, { warn: (m) => warns.push(m) });
144
+ }
145
+ catch (e) {
146
+ const detail = e instanceof Error ? e.message : String(e);
147
+ console.error(`import failed: ${skillDir} — ${detail}`);
148
+ if (e instanceof PracticeError && e.hint)
149
+ console.error(` hint: ${e.hint}`);
150
+ return 1;
151
+ }
152
+ const state = loadState(dataDir);
153
+ if (!state.direct.includes(res.root)) {
154
+ state.direct.push(res.root);
155
+ saveState(dataDir, state);
156
+ }
157
+ console.log(`imported: ${res.root} (${res.count} node(s)) [direct]`);
158
+ console.log(` source: ${res.sidecarUsed ? 'pop.doc.json sidecar replay (byte-identical hash)' : 'edited SKILL.md body (sidecar out of sync — new hash)'}`);
159
+ for (const w of warns)
160
+ console.log(` warning: ${w}`);
161
+ return 0;
162
+ }
163
+ /** practi skill export <ref> [--dir <out>]:POP → 技能目录(SKILL.md 投影 + 附件 + sidecar) */
164
+ function runSkillExport(opts) {
165
+ if (!opts.positional) {
166
+ console.error('usage: practi skill export <ref> [--dir <out-dir>] [--data-dir <dir>]');
167
+ return 1;
168
+ }
169
+ const dataDir = opts.dataDir ? path.resolve(opts.dataDir) : defaultDataDir();
170
+ const ws = openWorkspace(dataDir);
171
+ let rootHash;
172
+ try {
173
+ rootHash = resolveNodeRef(ws, opts.positional);
174
+ }
175
+ catch (e) {
176
+ const detail = e instanceof Error ? e.message : String(e);
177
+ console.error(`export failed: ${opts.positional} — ${detail}`);
178
+ return 1;
179
+ }
180
+ const name = ws.nodes.get(rootHash)?.name ?? rootHash;
181
+ const outDir = opts.dir ? path.resolve(opts.dir) : path.resolve(process.cwd(), slugOrHash(name, rootHash));
182
+ let res;
183
+ try {
184
+ res = exportSkill(ws, opts.positional, outDir);
185
+ }
186
+ catch (e) {
187
+ const detail = e instanceof Error ? e.message : String(e);
188
+ console.error(`export failed: ${rootHash} — ${detail}`);
189
+ return 1;
190
+ }
191
+ console.log(`exported: ${res.rootHash} → ${outDir}`);
192
+ console.log(` SKILL.md (projection of the document)`);
193
+ for (const f of res.files)
194
+ console.log(` ${f}`);
195
+ console.log(` pop.doc.json (sidecar — re-import replays this exact document, lossless round-trip)`);
196
+ return 0;
197
+ }
198
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/cmd/skill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { readSpec } from '@arshdelight/pop-sdk';
2
+ /**
3
+ * practi spec:打印本 CLI 所实现协议的 pop-spec.md(SDK 包内分发,readSpec 直读)。
4
+ * 无网络依赖;重定向即导出:practi spec > spec.md。
5
+ */
6
+ export function runSpec(_opts) {
7
+ console.log(readSpec());
8
+ return 0;
9
+ }
10
+ //# sourceMappingURL=spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/cmd/spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAMhD;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,KAAe;IACrC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxB,OAAO,CAAC,CAAC;AACX,CAAC"}