greprag 5.50.0 → 5.52.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.
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ /** Skill-mirror client — the Tier-3 mirror's upload half
3
+ * (docs/load-system.md §Tier 3). Runs inside the Stop hook: a skill-load turn
4
+ * triggers `maybeMirrorSkill`, which content-hashes the skill's markdown and
5
+ * uploads ONLY on change. Follower semantics — files canonical, the mirror
6
+ * shadows "last used state." Best-effort end to end: a mirror failure never
7
+ * touches the turn.
8
+ *
9
+ * Local freshness state (`~/.greprag/state/skill-mirror.json`) remembers the
10
+ * last-mirrored hash per skill so an unchanged skill costs one hash pass and
11
+ * ZERO network. Markdown only, v1 — SKILL.md + docs/**\/*.md; script-bearing
12
+ * assets stay file-bound (see the spec's named gaps). */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.collectSkillFiles = collectSkillFiles;
48
+ exports.computeMirrorHash = computeMirrorHash;
49
+ exports.readMirrorState = readMirrorState;
50
+ exports.writeMirrorState = writeMirrorState;
51
+ exports.maybeMirrorSkill = maybeMirrorSkill;
52
+ const fs = __importStar(require("fs"));
53
+ const path = __importStar(require("path"));
54
+ const crypto = __importStar(require("crypto"));
55
+ const skill_landing_1 = require("./skill-landing");
56
+ /** Mirrors the server's caps (SKILL_MIRROR_* in @greprag/core — the CLI is
57
+ * core-free, so the numbers are restated; the server re-validates anyway). */
58
+ const MAX_FILES = 20;
59
+ const MAX_FILE_CHARS = 100_000;
60
+ /** Collect the skill's markdown: SKILL.md (required) + docs/**\/*.md, capped.
61
+ * Returns null when the dir has no SKILL.md. Never throws. */
62
+ function collectSkillFiles(skillDir) {
63
+ try {
64
+ const files = [];
65
+ const skillMd = path.join(skillDir, 'SKILL.md');
66
+ let main;
67
+ try {
68
+ main = fs.readFileSync(skillMd, 'utf-8');
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ if (main.length > MAX_FILE_CHARS)
74
+ return null; // a >100KB SKILL.md is not a mirror candidate
75
+ files.push({ path: 'SKILL.md', content: main });
76
+ const docsDir = path.join(skillDir, 'docs');
77
+ const walk = (dir, rel) => {
78
+ let entries;
79
+ try {
80
+ entries = fs.readdirSync(dir, { withFileTypes: true });
81
+ }
82
+ catch {
83
+ return;
84
+ }
85
+ for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
86
+ if (files.length >= MAX_FILES)
87
+ return;
88
+ const abs = path.join(dir, e.name);
89
+ const relPath = `${rel}/${e.name}`;
90
+ if (e.isDirectory()) {
91
+ walk(abs, relPath);
92
+ continue;
93
+ }
94
+ if (!e.name.toLowerCase().endsWith('.md'))
95
+ continue;
96
+ try {
97
+ const content = fs.readFileSync(abs, 'utf-8');
98
+ if (content.length <= MAX_FILE_CHARS)
99
+ files.push({ path: relPath, content });
100
+ }
101
+ catch { /* unreadable — skip */ }
102
+ }
103
+ };
104
+ walk(docsDir, 'docs');
105
+ return files;
106
+ }
107
+ catch {
108
+ return null;
109
+ }
110
+ }
111
+ /** Deterministic content hash over path+content pairs. PURE — unit-tested. */
112
+ function computeMirrorHash(files) {
113
+ const h = crypto.createHash('sha256');
114
+ for (const f of [...files].sort((a, b) => a.path.localeCompare(b.path))) {
115
+ h.update(f.path).update('\0').update(f.content).update('\0');
116
+ }
117
+ return h.digest('hex');
118
+ }
119
+ function statePath() {
120
+ const home = process.env.HOME || process.env.USERPROFILE || '';
121
+ return path.join(home, '.greprag', 'state', 'skill-mirror.json');
122
+ }
123
+ function readMirrorState() {
124
+ try {
125
+ const parsed = JSON.parse(fs.readFileSync(statePath(), 'utf-8'));
126
+ if (parsed && typeof parsed.skills === 'object' && parsed.skills) {
127
+ return { skills: parsed.skills };
128
+ }
129
+ }
130
+ catch { /* missing/unreadable → empty */ }
131
+ return { skills: {} };
132
+ }
133
+ function writeMirrorState(state) {
134
+ try {
135
+ const file = statePath();
136
+ fs.mkdirSync(path.dirname(file), { recursive: true });
137
+ fs.writeFileSync(file, JSON.stringify(state, null, 2) + '\n');
138
+ }
139
+ catch { /* best-effort — worst case is one redundant upload next use */ }
140
+ }
141
+ /** Mirror one skill if its content changed since the last mirror. Never throws. */
142
+ async function maybeMirrorSkill(params) {
143
+ try {
144
+ if (!/^[A-Za-z0-9._-]{1,64}$/.test(params.skill))
145
+ return 'skipped';
146
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '';
147
+ const dir = (0, skill_landing_1.resolveSkillDir)(params.skill, params.cwd, homeDir);
148
+ if (!dir)
149
+ return 'skipped';
150
+ const files = collectSkillFiles(dir);
151
+ if (!files)
152
+ return 'skipped';
153
+ const hash = computeMirrorHash(files);
154
+ const state = readMirrorState();
155
+ if (state.skills[params.skill]?.hash === hash)
156
+ return 'fresh';
157
+ const res = await fetch(`${params.apiUrl}/v1/skillmirror/${encodeURIComponent(params.skill)}`, {
158
+ method: 'POST',
159
+ headers: { 'Authorization': `Bearer ${params.apiKey}`, 'Content-Type': 'application/json' },
160
+ body: JSON.stringify({ files, contentHash: hash }),
161
+ });
162
+ if (!res.ok)
163
+ return 'skipped';
164
+ state.skills[params.skill] = { hash, mirroredAt: new Date().toISOString() };
165
+ writeMirrorState(state);
166
+ return 'mirrored';
167
+ }
168
+ catch {
169
+ return 'skipped';
170
+ }
171
+ }
172
+ //# sourceMappingURL=skill-mirror-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-mirror-client.js","sourceRoot":"","sources":["../src/skill-mirror-client.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "greprag",
3
- "version": "5.50.0",
3
+ "version": "5.52.0",
4
4
  "description": "GrepRAG — agent memory for Claude Code, Codex, and OpenCode.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {