@ghl-ai/aw 0.1.34-beta.24 → 0.1.34-beta.25

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 (2) hide show
  1. package/commands/pull.mjs +51 -13
  2. package/package.json +1 -1
package/commands/pull.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  // commands/pull.mjs — Pull content from registry
2
2
 
3
- import { mkdirSync, existsSync, readdirSync, copyFileSync } from 'node:fs';
4
- import { join } from 'node:path';
3
+ import { mkdirSync, existsSync, readdirSync, copyFileSync, unlinkSync, rmdirSync } from 'node:fs';
4
+ import { join, relative } from 'node:path';
5
5
  import { homedir } from 'node:os';
6
6
  import { execSync } from 'node:child_process';
7
7
  import * as config from '../config.mjs';
@@ -214,7 +214,7 @@ export async function pullCommand(args) {
214
214
  const contentSrc = join(tempDir, DOCS_SOURCE_DIR);
215
215
  if (existsSync(contentSrc)) {
216
216
  const docsDest = join(workspaceDir, 'platform', 'docs');
217
- copyMarkdownTree(contentSrc, docsDest);
217
+ syncMarkdownTree(contentSrc, docsDest);
218
218
  }
219
219
 
220
220
  // MCP registration (second-class — skip if not available)
@@ -335,7 +335,7 @@ export async function pullAsync(args) {
335
335
  const contentSrc = join(tempDir, DOCS_SOURCE_DIR);
336
336
  if (existsSync(contentSrc)) {
337
337
  const docsDest = join(workspaceDir, 'platform', 'docs');
338
- copyMarkdownTree(contentSrc, docsDest);
338
+ syncMarkdownTree(contentSrc, docsDest);
339
339
  }
340
340
 
341
341
  return { pattern, actions, conflictCount };
@@ -351,21 +351,59 @@ function listDirs(dir) {
351
351
  }
352
352
 
353
353
  /**
354
- * Recursively copy only .md files from src to dest, preserving directory structure.
355
- * Skips images and other non-markdown content.
354
+ * Collect all .md file paths (relative) in a directory tree.
356
355
  */
357
- function copyMarkdownTree(src, dest) {
358
- mkdirSync(dest, { recursive: true });
359
- for (const entry of readdirSync(src, { withFileTypes: true })) {
356
+ function collectMarkdownPaths(dir, base) {
357
+ const paths = new Set();
358
+ if (!existsSync(dir)) return paths;
359
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
360
360
  if (entry.name.startsWith('.')) continue;
361
- const srcPath = join(src, entry.name);
362
- const destPath = join(dest, entry.name);
361
+ const full = join(dir, entry.name);
363
362
  if (entry.isDirectory()) {
364
- copyMarkdownTree(srcPath, destPath);
363
+ for (const p of collectMarkdownPaths(full, base)) paths.add(p);
365
364
  } else if (entry.name.endsWith('.md')) {
366
- copyFileSync(srcPath, destPath);
365
+ paths.add(relative(base, full));
366
+ }
367
+ }
368
+ return paths;
369
+ }
370
+
371
+ /**
372
+ * Sync .md files from src to dest: copy new/changed, delete removed, prune empty dirs.
373
+ */
374
+ function syncMarkdownTree(src, dest) {
375
+ mkdirSync(dest, { recursive: true });
376
+
377
+ const remotePaths = collectMarkdownPaths(src, src);
378
+ const localPaths = collectMarkdownPaths(dest, dest);
379
+
380
+ // Copy new and updated files
381
+ for (const rel of remotePaths) {
382
+ const srcPath = join(src, rel);
383
+ const destPath = join(dest, rel);
384
+ mkdirSync(join(dest, rel, '..'), { recursive: true });
385
+ copyFileSync(srcPath, destPath);
386
+ }
387
+
388
+ // Delete local files not on remote
389
+ for (const rel of localPaths) {
390
+ if (!remotePaths.has(rel)) {
391
+ const destPath = join(dest, rel);
392
+ try { unlinkSync(destPath); } catch { /* best effort */ }
393
+ }
394
+ }
395
+
396
+ // Prune empty directories (bottom-up)
397
+ function pruneEmpty(dir) {
398
+ if (!existsSync(dir)) return;
399
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
400
+ if (entry.isDirectory()) pruneEmpty(join(dir, entry.name));
367
401
  }
402
+ try {
403
+ if (readdirSync(dir).length === 0 && dir !== dest) rmdirSync(dir);
404
+ } catch { /* best effort */ }
368
405
  }
406
+ pruneEmpty(dest);
369
407
  }
370
408
 
371
409
  function registerMcp(namespace) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghl-ai/aw",
3
- "version": "0.1.34-beta.24",
3
+ "version": "0.1.34-beta.25",
4
4
  "description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
5
5
  "type": "module",
6
6
  "bin": {