@scitrera/memorylayer-sdk 0.0.5 → 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/dist/skills.js ADDED
@@ -0,0 +1,465 @@
1
+ import { MemoryLayerError } from "./errors.js";
2
+ /**
3
+ * UTF-8 encode a string and base64 it for the skill-file upsert endpoint.
4
+ * Uses Node's Buffer when present (the SDK's skill helpers are Node-oriented:
5
+ * parseSkillFolder/materialize use fs), falling back to btoa in the browser.
6
+ */
7
+ function _toBase64(content) {
8
+ const g = globalThis;
9
+ if (g.Buffer) {
10
+ return g.Buffer.from(content, "utf-8").toString("base64");
11
+ }
12
+ if (g.btoa && g.TextEncoder) {
13
+ const bytes = new g.TextEncoder().encode(content);
14
+ let binary = "";
15
+ for (const b of bytes)
16
+ binary += String.fromCharCode(b);
17
+ return g.btoa(binary);
18
+ }
19
+ throw new MemoryLayerError("No base64 encoder available (need Node Buffer or browser btoa/TextEncoder)");
20
+ }
21
+ // ------------------------------------------------------------------ //
22
+ // SkillsNamespace — attached as client.skills
23
+ // ------------------------------------------------------------------ //
24
+ export class SkillsNamespace {
25
+ _client;
26
+ _authority;
27
+ _workspaceId;
28
+ constructor(client, authority, workspaceId) {
29
+ this._client = client;
30
+ this._authority = authority;
31
+ this._workspaceId = workspaceId;
32
+ }
33
+ /** Return a scoped proxy that injects OBO headers and workspace on every call. */
34
+ withAuthority(authority, workspaceId) {
35
+ return new SkillsNamespace(this._client, authority, workspaceId ?? this._workspaceId);
36
+ }
37
+ _req(method, path, body, authority, responseMode = "json") {
38
+ return this._client._skillsRequest(method, path, body, authority ?? this._authority, responseMode);
39
+ }
40
+ async list(options = {}) {
41
+ const params = new URLSearchParams();
42
+ const wsId = options.workspaceId ?? this._workspaceId;
43
+ if (wsId)
44
+ params.set("workspace_id", wsId);
45
+ if (options.scope)
46
+ params.set("scope", options.scope);
47
+ if (options.name)
48
+ params.set("name", options.name);
49
+ if (options.enabled !== undefined)
50
+ params.set("enabled", String(options.enabled));
51
+ if (options.includeShadowed)
52
+ params.set("include_shadowed", "true");
53
+ if (options.tags?.length)
54
+ params.set("tags", options.tags.join(","));
55
+ const query = params.toString();
56
+ const response = await this._req("GET", `/v1/skills${query ? `?${query}` : ""}`, undefined, options.authority);
57
+ return response.skills;
58
+ }
59
+ async get(skillId) {
60
+ const response = await this._req("GET", `/v1/skills/${skillId}`);
61
+ return response.skill;
62
+ }
63
+ /**
64
+ * Render the full `SKILL.md` for a skill.
65
+ *
66
+ * The server returns raw markdown (`Content-Type: text/markdown`), not JSON,
67
+ * so this reads the body as text rather than parsing it.
68
+ */
69
+ async getManifest(skillId) {
70
+ return this._req("GET", `/v1/skills/${skillId}/manifest`, undefined, undefined, "text");
71
+ }
72
+ async listFiles(skillId) {
73
+ const response = await this._req("GET", `/v1/skills/${skillId}/files`);
74
+ return response.files;
75
+ }
76
+ /**
77
+ * Fetch only the raw content of a skill file (no metadata lookup).
78
+ *
79
+ * Used internally by `materialize()` to avoid the extra `listFiles()` call
80
+ * that `getFile()` performs. The caller already has the full `SkillFile`
81
+ * metadata from the single `listFiles()` done by `materialize()`, so we only
82
+ * need the raw bytes here.
83
+ */
84
+ async _fetchFileContent(skillId, filePath) {
85
+ const encoded = filePath
86
+ .split("/")
87
+ .map((seg) => encodeURIComponent(seg))
88
+ .join("/");
89
+ return this._req("GET", `/v1/skills/${skillId}/files/${encoded}`, undefined, undefined, "text");
90
+ }
91
+ /**
92
+ * Fetch a single skill file with its content populated.
93
+ *
94
+ * `GET /v1/skills/{id}/files/{path}` streams the raw file bytes (e.g.
95
+ * `text/x-python`), NOT a JSON envelope — so we read the body as text and
96
+ * merge it onto the file's metadata from `listFiles()`. The metadata lookup
97
+ * is best-effort: if the path isn't in the listing we still return the
98
+ * fetched content with the path filled in.
99
+ */
100
+ async getFile(skillId, filePath) {
101
+ const encoded = filePath
102
+ .split("/")
103
+ .map((seg) => encodeURIComponent(seg))
104
+ .join("/");
105
+ const [content, files] = await Promise.all([
106
+ this._req("GET", `/v1/skills/${skillId}/files/${encoded}`, undefined, undefined, "text"),
107
+ this.listFiles(skillId),
108
+ ]);
109
+ const info = files.find((f) => f.path === filePath);
110
+ return {
111
+ ...(info ?? { path: filePath }),
112
+ skill_id: skillId,
113
+ path: filePath,
114
+ content,
115
+ };
116
+ }
117
+ /**
118
+ * Delete a single file from a skill bundle.
119
+ *
120
+ * Calls `DELETE /v1/skills/{id}/files/{path}` (per-segment encodeURIComponent
121
+ * so embedded `/` separators are preserved, matching `getFile`). The server
122
+ * responds 204 with an empty body and is idempotent — deleting an
123
+ * already-absent path still succeeds — so the request helper's 204 handling
124
+ * means no JSON parsing happens here.
125
+ */
126
+ async deleteFile(skillId, filePath) {
127
+ const encoded = filePath
128
+ .split("/")
129
+ .map((seg) => encodeURIComponent(seg))
130
+ .join("/");
131
+ const wsQuery = this._workspaceId
132
+ ? `?workspace_id=${encodeURIComponent(this._workspaceId)}`
133
+ : "";
134
+ await this._req("DELETE", `/v1/skills/${skillId}/files/${encoded}${wsQuery}`);
135
+ }
136
+ /**
137
+ * Create or update a skill AND persist its bundle files.
138
+ *
139
+ * The server's create/update inputs (`POST /v1/skills`, `PUT /v1/skills/{id}`)
140
+ * carry NO `files` field — files are persisted out-of-band via
141
+ * `PUT /v1/skills/{id}/files/{path}` with base64 `content_b64`. A previous
142
+ * version sent `manifest.files` on the create body, where the server silently
143
+ * ignored it, so a skill saved with files lost them. This method now:
144
+ *
145
+ * 1. Detects create-vs-update by resolving the skill by name (the unique key
146
+ * within a scope). Found → UPDATE (`PUT /v1/skills/{id}`); else CREATE
147
+ * (`POST /v1/skills`). Neither create nor update bodies include `files`.
148
+ * 2. Upserts every manifest file via the dedicated file endpoint.
149
+ * 3. On UPDATE, performs a TRUE file reconcile: it lists the skill's current
150
+ * server files and DELETEs (`DELETE /v1/skills/{id}/files/{path}`) any whose
151
+ * path is no longer in the manifest, so the saved skill's bundle is an exact
152
+ * mirror of the manifest. (CREATE has no pre-existing files to prune.)
153
+ * 4. If the skill create/update succeeds but ANY file PUT fails, this RAISES a
154
+ * clear error rather than resolving — never silently dropping files. File
155
+ * PUTs are idempotent upserts, so the failed save is safe to retry.
156
+ *
157
+ * Returns the fully-persisted skill (re-fetched for fresh manifest/bundle
158
+ * hashes). The public signature and return type are unchanged.
159
+ */
160
+ async save(manifest) {
161
+ const files = manifest.files ?? [];
162
+ // Detect an existing skill by name (unique within scope). resolve() honors
163
+ // precedence/shadowing, matching how the rest of the SDK identifies skills.
164
+ let existing = null;
165
+ try {
166
+ existing = await this.resolve({
167
+ name: manifest.name,
168
+ authority: this._authority,
169
+ });
170
+ }
171
+ catch {
172
+ // resolve failures (e.g. 404-style empties) are treated as "not found";
173
+ // a hard create attempt below surfaces any real error.
174
+ existing = null;
175
+ }
176
+ let skillId;
177
+ if (existing) {
178
+ // ── UPDATE path: PUT manifest fields (no files), then reconcile files ──
179
+ const updateBody = {
180
+ description: manifest.description,
181
+ body: manifest.body,
182
+ metadata: manifest.metadata ?? {},
183
+ };
184
+ if (manifest.version !== undefined)
185
+ updateBody.version = manifest.version;
186
+ if (manifest.license !== undefined)
187
+ updateBody.license = manifest.license;
188
+ if (manifest.compatibility !== undefined)
189
+ updateBody.compatibility = manifest.compatibility;
190
+ if (manifest.allowed_tools !== undefined)
191
+ updateBody.allowed_tools = manifest.allowed_tools;
192
+ if (manifest.source_mode !== undefined)
193
+ updateBody.source_mode = manifest.source_mode;
194
+ const wsQuery = this._workspaceId
195
+ ? `?workspace_id=${encodeURIComponent(this._workspaceId)}`
196
+ : "";
197
+ await this._req("PUT", `/v1/skills/${existing.id}${wsQuery}`, updateBody);
198
+ skillId = existing.id;
199
+ // Reconcile deletions: list the skill's current server files and DELETE
200
+ // any whose path is no longer in the manifest, so the saved bundle is an
201
+ // exact mirror of the manifest. A delete failure must surface (don't
202
+ // silently diverge), so this is NOT wrapped in a swallow-all catch.
203
+ const serverFiles = await this.listFiles(skillId);
204
+ const manifestPaths = new Set(files.map((f) => f.path));
205
+ const stale = serverFiles
206
+ .map((f) => f.path)
207
+ .filter((p) => !manifestPaths.has(p));
208
+ for (const path of stale) {
209
+ await this.deleteFile(skillId, path);
210
+ }
211
+ }
212
+ else {
213
+ // ── CREATE path: POST manifest MINUS files, capture new id ──
214
+ const createBody = {
215
+ name: manifest.name,
216
+ description: manifest.description,
217
+ version: manifest.version ?? "0.1.0",
218
+ body: manifest.body,
219
+ metadata: manifest.metadata ?? {},
220
+ source_mode: manifest.source_mode ?? "server",
221
+ };
222
+ if (manifest.license !== undefined)
223
+ createBody.license = manifest.license;
224
+ if (manifest.compatibility !== undefined)
225
+ createBody.compatibility = manifest.compatibility;
226
+ if (manifest.allowed_tools !== undefined)
227
+ createBody.allowed_tools = manifest.allowed_tools;
228
+ if (this._workspaceId)
229
+ createBody.workspace_id = this._workspaceId;
230
+ const created = await this._req("POST", "/v1/skills", createBody);
231
+ skillId = created.skill.id;
232
+ }
233
+ // ── Persist each manifest file via the dedicated upsert endpoint ──
234
+ // A failure here, AFTER the skill create/update succeeded, must RAISE (never
235
+ // resolve) so files are never silently dropped. PUTs are idempotent upserts,
236
+ // so a failed save is retry-safe; we do NOT auto-delete the skill.
237
+ const wsQuery = this._workspaceId
238
+ ? `?workspace_id=${encodeURIComponent(this._workspaceId)}`
239
+ : "";
240
+ for (const file of files) {
241
+ const encoded = file.path
242
+ .split("/")
243
+ .map((seg) => encodeURIComponent(seg))
244
+ .join("/");
245
+ try {
246
+ await this._req("PUT", `/v1/skills/${skillId}/files/${encoded}${wsQuery}`, { content_b64: _toBase64(file.content) });
247
+ }
248
+ catch (err) {
249
+ throw new MemoryLayerError(`skill ${skillId} (${manifest.name}) saved but file ${file.path} ` +
250
+ `failed to persist: ${err instanceof Error ? err.message : String(err)}. ` +
251
+ `File upserts are idempotent — retry save() to complete persistence.`);
252
+ }
253
+ }
254
+ // Re-fetch so callers get fresh manifest/bundle hashes reflecting files.
255
+ return this.get(skillId);
256
+ }
257
+ async delete(skillId) {
258
+ await this._req("DELETE", `/v1/skills/${skillId}`);
259
+ }
260
+ async resolve(options = {}) {
261
+ const body = {};
262
+ if (options.name)
263
+ body.name = options.name;
264
+ if (options.query)
265
+ body.query = options.query;
266
+ if (options.scopeHint)
267
+ body.scope_hint = options.scopeHint;
268
+ const response = await this._req("POST", "/v1/skills/resolve", body, options.authority);
269
+ return response.skill;
270
+ }
271
+ async pull(skillId) {
272
+ const [skill, files] = await Promise.all([
273
+ this.get(skillId),
274
+ this.listFiles(skillId),
275
+ ]);
276
+ return { skill, files };
277
+ }
278
+ async push(manifest) {
279
+ return this.save(manifest);
280
+ }
281
+ /**
282
+ * Write every matching skill's `SKILL.md` + files into `targetDir`.
283
+ *
284
+ * The set of skills written is whatever the internal `list(...)` returns for
285
+ * the given `workspaceId`/`scope`. By default `enabled` is left unset, so
286
+ * both enabled and disabled server-visible skills are materialized (backwards
287
+ * compatible). Pass `enabled: true` to restrict the on-disk cache to the
288
+ * enabled subset (e.g. the OpenClaw skills-sync hook does this so disabled
289
+ * skills are never written into the agent's watched skills dir).
290
+ *
291
+ * By default materialize is purely additive: it writes/overwrites the desired
292
+ * skills but never removes anything already on disk. Pass `reconcile: true` to
293
+ * turn the sync into a true reconcile — after successfully listing AND writing
294
+ * the desired skills, any top-level entry in `targetDir` whose name is NOT in
295
+ * the desired skill-name set is removed. This is how a skill that was disabled,
296
+ * deleted, or renamed in MemoryLayer gets its stale on-disk copy pruned.
297
+ *
298
+ * CONTRACT (reconcile only): `targetDir` MUST be an exclusively
299
+ * MemoryLayer-managed directory (e.g. the OpenClaw plugin's dedicated
300
+ * `extraDir`). Reconcile will delete subdirectories it did not write. As a
301
+ * defensive guard it only removes a directory that *looks* like a materialized
302
+ * skill (i.e. contains a `SKILL.md`); unrelated files and non-skill directories
303
+ * are left untouched. Pruning runs ONLY after the list+materialize succeeded,
304
+ * so a transient server/list failure can never wipe the directory.
305
+ */
306
+ async materialize(targetDir, options = {}) {
307
+ if (typeof process === "undefined" || !process.versions?.node) {
308
+ throw new MemoryLayerError("Skill folder operations require Node.js");
309
+ }
310
+ const fs = await import("fs/promises");
311
+ const path = await import("path");
312
+ // If list() throws, this rejects before any prune — a transient server
313
+ // outage can never trigger a wipe of targetDir.
314
+ const skills = await this.list({
315
+ workspaceId: options.workspaceId ?? this._workspaceId,
316
+ scope: options.scope,
317
+ enabled: options.enabled,
318
+ });
319
+ // Desired set: the exact directory names materialize writes below.
320
+ const desiredNames = new Set(skills.map((skill) => skill.name));
321
+ for (const skill of skills) {
322
+ const skillDir = path.join(targetDir, skill.name);
323
+ await fs.mkdir(skillDir, { recursive: true });
324
+ // SKILL.md comes back as raw markdown text (not JSON) from getManifest.
325
+ const manifest = await this.getManifest(skill.id);
326
+ await fs.writeFile(path.join(skillDir, "SKILL.md"), manifest, "utf8");
327
+ // listFiles() returns metadata for all files in one call. We then fetch
328
+ // each file's raw bytes via _fetchFileContent() — which does a single
329
+ // content GET with no extra listFiles() — instead of calling getFile(),
330
+ // which would re-issue listFiles() per file. Net: 1 listFiles + N content
331
+ // GETs rather than 1 + N listFiles calls.
332
+ const files = await this.listFiles(skill.id);
333
+ for (const f of files) {
334
+ const filePath = path.join(skillDir, f.path);
335
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
336
+ const content = await this._fetchFileContent(skill.id, f.path);
337
+ await fs.writeFile(filePath, content, "utf8");
338
+ }
339
+ }
340
+ // Reconcile/prune: only after list+materialize succeeded above.
341
+ if (options.reconcile) {
342
+ let entries;
343
+ try {
344
+ entries = await fs.readdir(targetDir, { withFileTypes: true });
345
+ }
346
+ catch {
347
+ // targetDir doesn't exist (no skills were written, e.g. empty set);
348
+ // nothing to prune.
349
+ return;
350
+ }
351
+ for (const entry of entries) {
352
+ if (!entry.isDirectory())
353
+ continue; // never touch loose files
354
+ if (desiredNames.has(entry.name))
355
+ continue; // still wanted
356
+ const dir = path.join(targetDir, entry.name);
357
+ // Defensive: only remove dirs that look like a materialized skill.
358
+ try {
359
+ await fs.access(path.join(dir, "SKILL.md"));
360
+ }
361
+ catch {
362
+ continue; // no SKILL.md → not ours, leave it alone
363
+ }
364
+ await fs.rm(dir, { recursive: true, force: true });
365
+ }
366
+ }
367
+ }
368
+ }
369
+ // ------------------------------------------------------------------ //
370
+ // parseSkillFolder — Node.js helper
371
+ // ------------------------------------------------------------------ //
372
+ /**
373
+ * Parse a skill folder from the filesystem.
374
+ * Reads SKILL.md (frontmatter + body) and walks scripts/, references/, assets/.
375
+ * Requires Node.js (uses fs/promises). Not available in browser environments.
376
+ */
377
+ export async function parseSkillFolder(dir) {
378
+ if (typeof process === "undefined" || !process.versions?.node) {
379
+ throw new MemoryLayerError("Skill folder operations require Node.js");
380
+ }
381
+ const fs = await import("fs/promises");
382
+ const path = await import("path");
383
+ const manifestPath = path.join(dir, "SKILL.md");
384
+ const raw = await fs.readFile(manifestPath, "utf8");
385
+ const { frontmatter, body } = _parseMarkdownFrontmatter(raw);
386
+ const manifest = {
387
+ name: String(frontmatter.name ?? ""),
388
+ description: String(frontmatter.description ?? ""),
389
+ version: frontmatter.version ? String(frontmatter.version) : "0.1.0",
390
+ body,
391
+ };
392
+ if (frontmatter.license)
393
+ manifest.license = String(frontmatter.license);
394
+ if (frontmatter.compatibility)
395
+ manifest.compatibility = String(frontmatter.compatibility);
396
+ if (frontmatter.allowed_tools)
397
+ manifest.allowed_tools = String(frontmatter.allowed_tools);
398
+ const extraKeys = new Set([
399
+ "name",
400
+ "description",
401
+ "version",
402
+ "license",
403
+ "compatibility",
404
+ "allowed_tools",
405
+ ]);
406
+ const metadata = {};
407
+ for (const [k, v] of Object.entries(frontmatter)) {
408
+ if (!extraKeys.has(k))
409
+ metadata[k] = v;
410
+ }
411
+ manifest.metadata = metadata;
412
+ const files = [];
413
+ const knownDirs = ["scripts", "references", "assets"];
414
+ for (const subdir of knownDirs) {
415
+ const subdirPath = path.join(dir, subdir);
416
+ let entries;
417
+ try {
418
+ entries = await fs.readdir(subdirPath, { withFileTypes: true });
419
+ }
420
+ catch {
421
+ continue;
422
+ }
423
+ for (const entry of entries) {
424
+ if (!entry.isFile())
425
+ continue;
426
+ const filePath = path.join(subdirPath, entry.name);
427
+ const content = await fs.readFile(filePath, "utf8");
428
+ files.push({ path: `${subdir}/${entry.name}`, content });
429
+ }
430
+ }
431
+ return { manifest: { ...manifest, files }, files };
432
+ }
433
+ /** Minimal YAML-ish frontmatter parser — handles string/number/bool values only. */
434
+ function _parseMarkdownFrontmatter(raw) {
435
+ const trimmed = raw.trimStart();
436
+ if (!trimmed.startsWith("---")) {
437
+ return { frontmatter: {}, body: raw };
438
+ }
439
+ const end = trimmed.indexOf("\n---", 3);
440
+ if (end === -1) {
441
+ return { frontmatter: {}, body: raw };
442
+ }
443
+ const yamlBlock = trimmed.slice(4, end);
444
+ const body = trimmed.slice(end + 4).trimStart();
445
+ const frontmatter = {};
446
+ for (const line of yamlBlock.split("\n")) {
447
+ const colonIdx = line.indexOf(":");
448
+ if (colonIdx === -1)
449
+ continue;
450
+ const key = line.slice(0, colonIdx).trim();
451
+ const val = line.slice(colonIdx + 1).trim();
452
+ if (!key)
453
+ continue;
454
+ if (val === "true")
455
+ frontmatter[key] = true;
456
+ else if (val === "false")
457
+ frontmatter[key] = false;
458
+ else if (val !== "" && !isNaN(Number(val)))
459
+ frontmatter[key] = Number(val);
460
+ else
461
+ frontmatter[key] = val.replace(/^["']|["']$/g, "");
462
+ }
463
+ return { frontmatter, body };
464
+ }
465
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"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"}