clawvault 2.3.0 → 2.4.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 (55) hide show
  1. package/bin/clawvault.js +6 -0
  2. package/bin/register-core-commands.js +25 -2
  3. package/bin/register-tailscale-commands.js +106 -0
  4. package/bin/register-task-commands.js +18 -2
  5. package/bin/register-task-commands.test.js +24 -0
  6. package/dist/{chunk-SOTWYGH7.js → chunk-33GW63WK.js} +4 -35
  7. package/dist/chunk-4GBPTBFJ.js +628 -0
  8. package/dist/{chunk-GQVYQCY5.js → chunk-AHGUJG76.js} +3 -3
  9. package/dist/{chunk-GJEGPO7U.js → chunk-BI6SGGZP.js} +1 -1
  10. package/dist/chunk-CLE2HHNT.js +513 -0
  11. package/dist/{chunk-NGVAEFT2.js → chunk-DEFBIVQ3.js} +21 -0
  12. package/dist/{chunk-DPS7NYIU.js → chunk-DHJPXGC7.js} +2 -2
  13. package/dist/{chunk-2HM7ZI4X.js → chunk-FEFPBHH4.js} +287 -12
  14. package/dist/{chunk-K6XHCUFL.js → chunk-FHFUXL6G.js} +8 -1
  15. package/dist/{chunk-6BBTI7NV.js → chunk-GBIDDDSL.js} +2 -2
  16. package/dist/{chunk-VR5NE7PZ.js → chunk-HVTTYDCJ.js} +1 -1
  17. package/dist/chunk-IFTEGE4D.js +361 -0
  18. package/dist/{chunk-5WR6RRPX.js → chunk-JXY6T5R7.js} +2 -2
  19. package/dist/chunk-L3DJ36BZ.js +40 -0
  20. package/dist/{chunk-Z2XBWN7A.js → chunk-NAMFB7ZA.js} +2 -0
  21. package/dist/chunk-NZ4ZZNSR.js +373 -0
  22. package/dist/{chunk-OTQW3OMC.js → chunk-Q3WBH4P4.js} +97 -0
  23. package/dist/{chunk-MQUJNOHK.js → chunk-QALB2V3E.js} +1 -1
  24. package/dist/{chunk-PTSEIWXZ.js → chunk-SNEMCQP7.js} +13 -6
  25. package/dist/commands/archive.js +3 -3
  26. package/dist/commands/backlog.js +9 -2
  27. package/dist/commands/blocked.js +9 -2
  28. package/dist/commands/canvas.d.ts +11 -3
  29. package/dist/commands/canvas.js +1333 -25
  30. package/dist/commands/context.js +5 -4
  31. package/dist/commands/doctor.js +1 -1
  32. package/dist/commands/migrate-observations.js +3 -3
  33. package/dist/commands/observe.d.ts +1 -0
  34. package/dist/commands/observe.js +5 -4
  35. package/dist/commands/rebuild.js +5 -4
  36. package/dist/commands/reflect.js +5 -5
  37. package/dist/commands/replay.js +7 -6
  38. package/dist/commands/setup.d.ts +10 -2
  39. package/dist/commands/setup.js +1 -1
  40. package/dist/commands/sleep.js +7 -6
  41. package/dist/commands/status.js +1 -1
  42. package/dist/commands/tailscale.d.ts +52 -0
  43. package/dist/commands/tailscale.js +25 -0
  44. package/dist/commands/task.js +1 -1
  45. package/dist/commands/wake.js +4 -4
  46. package/dist/index.d.ts +9 -0
  47. package/dist/index.js +79 -15
  48. package/dist/lib/tailscale.d.ts +225 -0
  49. package/dist/lib/tailscale.js +49 -0
  50. package/dist/lib/task-utils.d.ts +13 -1
  51. package/dist/lib/task-utils.js +3 -1
  52. package/dist/lib/webdav.d.ts +109 -0
  53. package/dist/lib/webdav.js +34 -0
  54. package/package.json +2 -2
  55. package/dist/chunk-W463YRED.js +0 -97
@@ -0,0 +1,225 @@
1
+ import { ChildProcess } from 'child_process';
2
+ import * as http from 'http';
3
+
4
+ /**
5
+ * Tailscale Integration for ClawVault
6
+ *
7
+ * Provides native Tailscale networking capabilities for vault synchronization
8
+ * across devices on a Tailscale network (tailnet).
9
+ *
10
+ * Features:
11
+ * - Tailscale status detection and peer discovery
12
+ * - MagicDNS hostname resolution
13
+ * - Secure peer-to-peer vault sync
14
+ * - Tailscale Funnel/Serve integration for vault sharing
15
+ */
16
+
17
+ interface TailscaleStatus {
18
+ /** Whether Tailscale is installed */
19
+ installed: boolean;
20
+ /** Whether Tailscale daemon is running */
21
+ running: boolean;
22
+ /** Whether connected to tailnet */
23
+ connected: boolean;
24
+ /** Current device's Tailscale IP */
25
+ selfIP?: string;
26
+ /** Current device's MagicDNS hostname */
27
+ selfHostname?: string;
28
+ /** Current device's full domain name */
29
+ selfDNSName?: string;
30
+ /** Tailnet name */
31
+ tailnetName?: string;
32
+ /** Backend state (Running, Stopped, etc.) */
33
+ backendState?: string;
34
+ /** List of peers on the tailnet */
35
+ peers: TailscalePeer[];
36
+ /** Error message if any */
37
+ error?: string;
38
+ }
39
+ interface TailscalePeer {
40
+ /** Peer's hostname */
41
+ hostname: string;
42
+ /** Peer's MagicDNS name */
43
+ dnsName: string;
44
+ /** Peer's Tailscale IP addresses */
45
+ tailscaleIPs: string[];
46
+ /** Whether peer is currently online */
47
+ online: boolean;
48
+ /** Operating system */
49
+ os?: string;
50
+ /** Whether this peer is the exit node */
51
+ exitNode?: boolean;
52
+ /** Whether this peer is a tagged device */
53
+ tags?: string[];
54
+ /** Last seen timestamp */
55
+ lastSeen?: string;
56
+ /** Whether peer is running ClawVault serve */
57
+ clawvaultServing?: boolean;
58
+ /** ClawVault serve port if detected */
59
+ clawvaultPort?: number;
60
+ }
61
+ interface TailscaleServeConfig {
62
+ /** Port to serve on (default: 8384) */
63
+ port?: number;
64
+ /** Whether to use HTTPS (via Tailscale) */
65
+ https?: boolean;
66
+ /** Whether to expose via Tailscale Funnel (public internet) */
67
+ funnel?: boolean;
68
+ /** Path prefix for the serve endpoint */
69
+ pathPrefix?: string;
70
+ /** Optional WebDAV Basic Auth credentials */
71
+ webdavAuth?: {
72
+ username: string;
73
+ password: string;
74
+ };
75
+ }
76
+ interface TailscaleSyncOptions {
77
+ /** Target peer hostname or IP */
78
+ peer: string;
79
+ /** Port on the peer (default: 8384) */
80
+ port?: number;
81
+ /** Direction: push, pull, or bidirectional */
82
+ direction?: 'push' | 'pull' | 'bidirectional';
83
+ /** Dry run - don't actually sync */
84
+ dryRun?: boolean;
85
+ /** Delete files on target that don't exist on source */
86
+ deleteOrphans?: boolean;
87
+ /** Categories to sync (default: all) */
88
+ categories?: string[];
89
+ /** Use HTTPS for connection */
90
+ https?: boolean;
91
+ }
92
+ interface TailscaleSyncResult {
93
+ /** Files pushed to peer */
94
+ pushed: string[];
95
+ /** Files pulled from peer */
96
+ pulled: string[];
97
+ /** Files deleted */
98
+ deleted: string[];
99
+ /** Files unchanged */
100
+ unchanged: string[];
101
+ /** Errors encountered */
102
+ errors: string[];
103
+ /** Sync statistics */
104
+ stats: {
105
+ bytesTransferred: number;
106
+ filesProcessed: number;
107
+ duration: number;
108
+ };
109
+ }
110
+ interface VaultManifest {
111
+ /** Vault name */
112
+ name: string;
113
+ /** Vault version */
114
+ version: string;
115
+ /** Last updated timestamp */
116
+ lastUpdated: string;
117
+ /** File manifest with checksums */
118
+ files: VaultFileEntry[];
119
+ }
120
+ interface VaultFileEntry {
121
+ /** Relative path */
122
+ path: string;
123
+ /** File size in bytes */
124
+ size: number;
125
+ /** Last modified timestamp */
126
+ modified: string;
127
+ /** SHA-256 checksum */
128
+ checksum: string;
129
+ /** Category */
130
+ category: string;
131
+ }
132
+ declare const DEFAULT_SERVE_PORT = 8384;
133
+ declare const CLAWVAULT_SERVE_PATH = "/.clawvault";
134
+ declare const MANIFEST_ENDPOINT = "/.clawvault/manifest";
135
+ declare const SYNC_ENDPOINT = "/.clawvault/sync";
136
+ declare const FILE_ENDPOINT = "/.clawvault/files";
137
+ /**
138
+ * Check if Tailscale CLI is installed
139
+ */
140
+ declare function hasTailscale(): boolean;
141
+ /**
142
+ * Get Tailscale version
143
+ */
144
+ declare function getTailscaleVersion(): string | null;
145
+ /**
146
+ * Get comprehensive Tailscale status
147
+ */
148
+ declare function getTailscaleStatus(): TailscaleStatus;
149
+ /**
150
+ * Find a peer by hostname (partial match supported)
151
+ */
152
+ declare function findPeer(hostname: string): TailscalePeer | null;
153
+ /**
154
+ * Get online peers only
155
+ */
156
+ declare function getOnlinePeers(): TailscalePeer[];
157
+ /**
158
+ * Resolve a peer hostname to its Tailscale IP
159
+ */
160
+ declare function resolvePeerIP(hostname: string): string | null;
161
+ /**
162
+ * Generate vault manifest for synchronization
163
+ */
164
+ declare function generateVaultManifest(vaultPath: string): VaultManifest;
165
+ /**
166
+ * Compare two manifests and return differences
167
+ */
168
+ declare function compareManifests(local: VaultManifest, remote: VaultManifest): {
169
+ toPush: VaultFileEntry[];
170
+ toPull: VaultFileEntry[];
171
+ conflicts: Array<{
172
+ path: string;
173
+ local: VaultFileEntry;
174
+ remote: VaultFileEntry;
175
+ }>;
176
+ unchanged: string[];
177
+ };
178
+ interface ServeInstance {
179
+ server: http.Server;
180
+ port: number;
181
+ stop: () => Promise<void>;
182
+ }
183
+ /**
184
+ * Start serving a vault over HTTP for Tailscale sync
185
+ * Includes WebDAV support at /webdav/ for Obsidian mobile sync
186
+ */
187
+ declare function serveVault(vaultPath: string, options?: TailscaleServeConfig): ServeInstance;
188
+ /**
189
+ * Fetch remote vault manifest
190
+ */
191
+ declare function fetchRemoteManifest(host: string, port?: number, useHttps?: boolean): Promise<VaultManifest>;
192
+ /**
193
+ * Fetch a file from remote vault
194
+ */
195
+ declare function fetchRemoteFile(host: string, filePath: string, port?: number, useHttps?: boolean): Promise<string>;
196
+ /**
197
+ * Push a file to remote vault
198
+ */
199
+ declare function pushFileToRemote(host: string, filePath: string, content: string, port?: number, useHttps?: boolean): Promise<void>;
200
+ /**
201
+ * Sync vault with a remote peer
202
+ */
203
+ declare function syncWithPeer(vaultPath: string, options: TailscaleSyncOptions): Promise<TailscaleSyncResult>;
204
+ /**
205
+ * Configure Tailscale serve for the vault
206
+ * This uses `tailscale serve` to expose the vault server via Tailscale's HTTPS
207
+ */
208
+ declare function configureTailscaleServe(localPort: number, options?: {
209
+ funnel?: boolean;
210
+ background?: boolean;
211
+ }): ChildProcess | null;
212
+ /**
213
+ * Stop Tailscale serve
214
+ */
215
+ declare function stopTailscaleServe(): boolean;
216
+ /**
217
+ * Check if a peer is serving ClawVault
218
+ */
219
+ declare function checkPeerClawVault(host: string, port?: number): Promise<boolean>;
220
+ /**
221
+ * Discover ClawVault peers on the tailnet
222
+ */
223
+ declare function discoverClawVaultPeers(port?: number): Promise<TailscalePeer[]>;
224
+
225
+ export { CLAWVAULT_SERVE_PATH, DEFAULT_SERVE_PORT, FILE_ENDPOINT, MANIFEST_ENDPOINT, SYNC_ENDPOINT, type ServeInstance, type TailscalePeer, type TailscaleServeConfig, type TailscaleStatus, type TailscaleSyncOptions, type TailscaleSyncResult, type VaultFileEntry, type VaultManifest, checkPeerClawVault, compareManifests, configureTailscaleServe, discoverClawVaultPeers, fetchRemoteFile, fetchRemoteManifest, findPeer, generateVaultManifest, getOnlinePeers, getTailscaleStatus, getTailscaleVersion, hasTailscale, pushFileToRemote, resolvePeerIP, serveVault, stopTailscaleServe, syncWithPeer };
@@ -0,0 +1,49 @@
1
+ import {
2
+ CLAWVAULT_SERVE_PATH,
3
+ DEFAULT_SERVE_PORT,
4
+ FILE_ENDPOINT,
5
+ MANIFEST_ENDPOINT,
6
+ SYNC_ENDPOINT,
7
+ checkPeerClawVault,
8
+ compareManifests,
9
+ configureTailscaleServe,
10
+ discoverClawVaultPeers,
11
+ fetchRemoteFile,
12
+ fetchRemoteManifest,
13
+ findPeer,
14
+ generateVaultManifest,
15
+ getOnlinePeers,
16
+ getTailscaleStatus,
17
+ getTailscaleVersion,
18
+ hasTailscale,
19
+ pushFileToRemote,
20
+ resolvePeerIP,
21
+ serveVault,
22
+ stopTailscaleServe,
23
+ syncWithPeer
24
+ } from "../chunk-4GBPTBFJ.js";
25
+ import "../chunk-CLE2HHNT.js";
26
+ export {
27
+ CLAWVAULT_SERVE_PATH,
28
+ DEFAULT_SERVE_PORT,
29
+ FILE_ENDPOINT,
30
+ MANIFEST_ENDPOINT,
31
+ SYNC_ENDPOINT,
32
+ checkPeerClawVault,
33
+ compareManifests,
34
+ configureTailscaleServe,
35
+ discoverClawVaultPeers,
36
+ fetchRemoteFile,
37
+ fetchRemoteManifest,
38
+ findPeer,
39
+ generateVaultManifest,
40
+ getOnlinePeers,
41
+ getTailscaleStatus,
42
+ getTailscaleVersion,
43
+ hasTailscale,
44
+ pushFileToRemote,
45
+ resolvePeerIP,
46
+ serveVault,
47
+ stopTailscaleServe,
48
+ syncWithPeer
49
+ };
@@ -6,6 +6,7 @@ type TaskStatus = 'open' | 'in-progress' | 'blocked' | 'done';
6
6
  type TaskPriority = 'critical' | 'high' | 'medium' | 'low';
7
7
  interface TaskFrontmatter {
8
8
  status: TaskStatus;
9
+ source?: string;
9
10
  owner?: string;
10
11
  project?: string;
11
12
  priority?: TaskPriority;
@@ -27,6 +28,7 @@ interface BacklogFrontmatter {
27
28
  source?: string;
28
29
  project?: string;
29
30
  created: string;
31
+ lastSeen?: string;
30
32
  tags?: string[];
31
33
  }
32
34
  interface BacklogItem {
@@ -95,6 +97,7 @@ declare function listBacklogItems(vaultPath: string, filters?: BacklogFilterOpti
95
97
  * Create a new task
96
98
  */
97
99
  declare function createTask(vaultPath: string, title: string, options?: {
100
+ source?: string;
98
101
  owner?: string;
99
102
  project?: string;
100
103
  priority?: TaskPriority;
@@ -127,6 +130,15 @@ declare function createBacklogItem(vaultPath: string, title: string, options?: {
127
130
  content?: string;
128
131
  tags?: string[];
129
132
  }): BacklogItem;
133
+ /**
134
+ * Update an existing backlog item frontmatter.
135
+ */
136
+ declare function updateBacklogItem(vaultPath: string, slug: string, updates: {
137
+ source?: string;
138
+ project?: string;
139
+ tags?: string[];
140
+ lastSeen?: string;
141
+ }): BacklogItem;
130
142
  /**
131
143
  * Promote a backlog item to a task
132
144
  */
@@ -156,4 +168,4 @@ declare function getStatusIcon(status: TaskStatus): string;
156
168
  */
157
169
  declare function getStatusDisplay(status: TaskStatus): string;
158
170
 
159
- export { type BacklogFilterOptions, type BacklogFrontmatter, type BacklogItem, type Task, type TaskFilterOptions, type TaskFrontmatter, type TaskPriority, type TaskStatus, completeTask, createBacklogItem, createTask, ensureBacklogDir, ensureTasksDir, getActiveTasks, getBacklogDir, getBacklogPath, getBlockedTasks, getRecentlyCompletedTasks, getStatusDisplay, getStatusIcon, getTaskPath, getTasksDir, listBacklogItems, listTasks, promoteBacklogItem, readBacklogItem, readTask, slugify, updateTask };
171
+ export { type BacklogFilterOptions, type BacklogFrontmatter, type BacklogItem, type Task, type TaskFilterOptions, type TaskFrontmatter, type TaskPriority, type TaskStatus, completeTask, createBacklogItem, createTask, ensureBacklogDir, ensureTasksDir, getActiveTasks, getBacklogDir, getBacklogPath, getBlockedTasks, getRecentlyCompletedTasks, getStatusDisplay, getStatusIcon, getTaskPath, getTasksDir, listBacklogItems, listTasks, promoteBacklogItem, readBacklogItem, readTask, slugify, updateBacklogItem, updateTask };
@@ -19,8 +19,9 @@ import {
19
19
  readBacklogItem,
20
20
  readTask,
21
21
  slugify,
22
+ updateBacklogItem,
22
23
  updateTask
23
- } from "../chunk-NGVAEFT2.js";
24
+ } from "../chunk-DEFBIVQ3.js";
24
25
  export {
25
26
  completeTask,
26
27
  createBacklogItem,
@@ -42,5 +43,6 @@ export {
42
43
  readBacklogItem,
43
44
  readTask,
44
45
  slugify,
46
+ updateBacklogItem,
45
47
  updateTask
46
48
  };
@@ -0,0 +1,109 @@
1
+ import * as fs from 'fs';
2
+ import { IncomingMessage, ServerResponse } from 'http';
3
+
4
+ /**
5
+ * WebDAV Handler for ClawVault
6
+ *
7
+ * Implements WebDAV protocol support for Obsidian mobile sync via Remotely Save plugin.
8
+ * Uses only Node built-in modules (http, fs, path) - zero external dependencies.
9
+ *
10
+ * Supported methods:
11
+ * - GET: Serve file contents
12
+ * - PUT: Write/create file (creates parent dirs if needed)
13
+ * - DELETE: Delete file or directory
14
+ * - MKCOL: Create directory
15
+ * - PROPFIND: List directory contents or file properties (XML response)
16
+ * - OPTIONS: Return allowed methods + DAV header
17
+ * - HEAD: File metadata without body
18
+ * - MOVE: Rename/move file (uses Destination header)
19
+ * - COPY: Copy file
20
+ */
21
+
22
+ interface WebDAVConfig {
23
+ /** Root path for WebDAV files (vault path) */
24
+ rootPath: string;
25
+ /** URL prefix for WebDAV routes (default: /webdav) */
26
+ prefix?: string;
27
+ /** Optional Basic Auth credentials */
28
+ auth?: {
29
+ username: string;
30
+ password: string;
31
+ };
32
+ }
33
+ interface WebDAVRequest {
34
+ method: string;
35
+ path: string;
36
+ headers: Record<string, string | string[] | undefined>;
37
+ body?: string;
38
+ }
39
+ interface WebDAVResponse {
40
+ status: number;
41
+ headers: Record<string, string>;
42
+ body?: string;
43
+ }
44
+ declare const WEBDAV_PREFIX = "/webdav";
45
+ /**
46
+ * Check if a path is safe (no traversal attacks, not blocked)
47
+ */
48
+ declare function isPathSafe(requestPath: string, rootPath: string): boolean;
49
+ /**
50
+ * Resolve a WebDAV path to filesystem path
51
+ */
52
+ declare function resolveWebDAVPath(requestPath: string, rootPath: string): string | null;
53
+ /**
54
+ * Check Basic Auth credentials
55
+ */
56
+ declare function checkAuth(req: IncomingMessage, auth?: {
57
+ username: string;
58
+ password: string;
59
+ }): boolean;
60
+ /**
61
+ * Generate full PROPFIND response XML
62
+ */
63
+ declare function generatePropfindResponse(entries: Array<{
64
+ href: string;
65
+ stats: fs.Stats | null;
66
+ isCollection: boolean;
67
+ }>): string;
68
+ /**
69
+ * Handle OPTIONS request
70
+ */
71
+ declare function handleOptions(res: ServerResponse, prefix: string): void;
72
+ /**
73
+ * Handle HEAD request
74
+ */
75
+ declare function handleHead(res: ServerResponse, filePath: string): void;
76
+ /**
77
+ * Handle GET request
78
+ */
79
+ declare function handleGet(res: ServerResponse, filePath: string): void;
80
+ /**
81
+ * Handle PUT request
82
+ */
83
+ declare function handlePut(res: ServerResponse, filePath: string, body: Buffer): void;
84
+ /**
85
+ * Handle DELETE request
86
+ */
87
+ declare function handleDelete(res: ServerResponse, filePath: string): void;
88
+ /**
89
+ * Handle MKCOL request (create directory)
90
+ */
91
+ declare function handleMkcol(res: ServerResponse, filePath: string): void;
92
+ /**
93
+ * Handle PROPFIND request
94
+ */
95
+ declare function handlePropfind(res: ServerResponse, filePath: string, webdavPath: string, prefix: string, depth: string): void;
96
+ /**
97
+ * Handle MOVE request
98
+ */
99
+ declare function handleMove(res: ServerResponse, sourcePath: string, destinationPath: string | null, overwrite: boolean): void;
100
+ /**
101
+ * Handle COPY request
102
+ */
103
+ declare function handleCopy(res: ServerResponse, sourcePath: string, destinationPath: string | null, overwrite: boolean): void;
104
+ /**
105
+ * Create WebDAV request handler
106
+ */
107
+ declare function createWebDAVHandler(config: WebDAVConfig): (req: IncomingMessage, res: ServerResponse) => Promise<boolean>;
108
+
109
+ export { WEBDAV_PREFIX, type WebDAVConfig, type WebDAVRequest, type WebDAVResponse, checkAuth, createWebDAVHandler, generatePropfindResponse, handleCopy, handleDelete, handleGet, handleHead, handleMkcol, handleMove, handleOptions, handlePropfind, handlePut, isPathSafe, resolveWebDAVPath };
@@ -0,0 +1,34 @@
1
+ import {
2
+ WEBDAV_PREFIX,
3
+ checkAuth,
4
+ createWebDAVHandler,
5
+ generatePropfindResponse,
6
+ handleCopy,
7
+ handleDelete,
8
+ handleGet,
9
+ handleHead,
10
+ handleMkcol,
11
+ handleMove,
12
+ handleOptions,
13
+ handlePropfind,
14
+ handlePut,
15
+ isPathSafe,
16
+ resolveWebDAVPath
17
+ } from "../chunk-CLE2HHNT.js";
18
+ export {
19
+ WEBDAV_PREFIX,
20
+ checkAuth,
21
+ createWebDAVHandler,
22
+ generatePropfindResponse,
23
+ handleCopy,
24
+ handleDelete,
25
+ handleGet,
26
+ handleHead,
27
+ handleMkcol,
28
+ handleMove,
29
+ handleOptions,
30
+ handlePropfind,
31
+ handlePut,
32
+ isPathSafe,
33
+ resolveWebDAVPath
34
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawvault",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "ClawVault™ - 🐘 An elephant never forgets. Structured memory for OpenClaw agents. Context death resilience, Obsidian-compatible markdown, local semantic search.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -29,7 +29,7 @@
29
29
  ]
30
30
  },
31
31
  "scripts": {
32
- "build": "tsup src/index.ts src/commands/entities.ts src/commands/link.ts src/commands/checkpoint.ts src/commands/recover.ts src/commands/status.ts src/commands/template.ts src/commands/setup.ts src/commands/context.ts src/commands/observe.ts src/commands/reflect.ts src/commands/archive.ts src/commands/rebuild.ts src/commands/replay.ts src/commands/migrate-observations.ts src/commands/sync-bd.ts src/commands/session-recap.ts src/commands/wake.ts src/commands/sleep.ts src/commands/doctor.ts src/commands/compat.ts src/commands/graph.ts src/commands/shell-init.ts src/commands/repair-session.ts src/commands/task.ts src/commands/backlog.ts src/commands/blocked.ts src/commands/canvas.ts src/lib/entity-index.ts src/lib/auto-linker.ts src/lib/config.ts src/lib/template-engine.ts src/lib/session-utils.ts src/lib/session-repair.ts src/lib/task-utils.ts src/lib/canvas-layout.ts --format esm --dts --clean",
32
+ "build": "tsup src/commands/archive.ts src/commands/backlog.ts src/commands/blocked.ts src/commands/canvas.ts src/commands/checkpoint.ts src/commands/compat.ts src/commands/context.ts src/commands/doctor.ts src/commands/entities.ts src/commands/graph.ts src/commands/link.ts src/commands/migrate-observations.ts src/commands/observe.ts src/commands/rebuild.ts src/commands/recover.ts src/commands/reflect.ts src/commands/repair-session.ts src/commands/replay.ts src/commands/session-recap.ts src/commands/setup.ts src/commands/shell-init.ts src/commands/sleep.ts src/commands/status.ts src/commands/sync-bd.ts src/commands/tailscale.ts src/commands/task.ts src/commands/template.ts src/commands/wake.ts src/index.ts src/lib/auto-linker.ts src/lib/canvas-layout.ts src/lib/config.ts src/lib/entity-index.ts src/lib/session-repair.ts src/lib/session-utils.ts src/lib/tailscale.ts src/lib/task-utils.ts src/lib/template-engine.ts src/lib/webdav.ts --format esm --dts --clean",
33
33
  "dev": "tsup src/index.ts src/commands/*.ts src/lib/*.ts --format esm --dts --watch",
34
34
  "lint": "eslint src",
35
35
  "typecheck": "tsc --noEmit",
@@ -1,97 +0,0 @@
1
- import {
2
- DEFAULT_CATEGORIES,
3
- hasQmd
4
- } from "./chunk-FDJIZKCW.js";
5
-
6
- // src/commands/setup.ts
7
- import * as fs from "fs";
8
- import * as os from "os";
9
- import * as path from "path";
10
- import { execFileSync } from "child_process";
11
- var CONFIG_FILE = ".clawvault.json";
12
- function resolveVaultTarget() {
13
- const envPath = process.env.CLAWVAULT_PATH?.trim();
14
- const home = os.homedir();
15
- if (envPath) {
16
- const vaultPath = path.resolve(envPath);
17
- return { vaultPath, source: "CLAWVAULT_PATH", existed: fs.existsSync(vaultPath) };
18
- }
19
- const candidates = [
20
- { vaultPath: path.join(home, ".openclaw", "workspace", "memory"), source: "OpenClaw default" },
21
- { vaultPath: path.resolve(process.cwd(), "memory"), source: "./memory" },
22
- { vaultPath: path.join(home, "memory"), source: "~/memory" }
23
- ];
24
- for (const candidate of candidates) {
25
- if (fs.existsSync(candidate.vaultPath)) {
26
- return { ...candidate, existed: true };
27
- }
28
- }
29
- const fallback = candidates[0];
30
- return { ...fallback, existed: false };
31
- }
32
- function ensureVaultStructure(vaultPath) {
33
- fs.mkdirSync(vaultPath, { recursive: true });
34
- for (const category of DEFAULT_CATEGORIES) {
35
- fs.mkdirSync(path.join(vaultPath, category), { recursive: true });
36
- }
37
- const configPath = path.join(vaultPath, CONFIG_FILE);
38
- if (fs.existsSync(configPath)) return false;
39
- const now = (/* @__PURE__ */ new Date()).toISOString();
40
- const name = path.basename(vaultPath);
41
- const meta = {
42
- name,
43
- version: "1.0.0",
44
- created: now,
45
- lastUpdated: now,
46
- categories: DEFAULT_CATEGORIES,
47
- documentCount: 0,
48
- qmdCollection: name,
49
- qmdRoot: vaultPath
50
- };
51
- fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));
52
- return true;
53
- }
54
- function getQmdConfig(vaultPath) {
55
- const configPath = path.join(vaultPath, CONFIG_FILE);
56
- if (fs.existsSync(configPath)) {
57
- try {
58
- const meta = JSON.parse(fs.readFileSync(configPath, "utf-8"));
59
- return {
60
- collection: meta.qmdCollection || meta.name || path.basename(vaultPath),
61
- root: meta.qmdRoot || vaultPath
62
- };
63
- } catch {
64
- return { collection: path.basename(vaultPath), root: vaultPath };
65
- }
66
- }
67
- return { collection: path.basename(vaultPath), root: vaultPath };
68
- }
69
- async function setupCommand() {
70
- const target = resolveVaultTarget();
71
- if (target.existed && !fs.statSync(target.vaultPath).isDirectory()) {
72
- throw new Error(`Vault path is not a directory: ${target.vaultPath}`);
73
- }
74
- if (!target.existed) fs.mkdirSync(target.vaultPath, { recursive: true });
75
- console.log(`${target.existed ? "Found" : "Created"} vault path (${target.source}): ${target.vaultPath}`);
76
- const initialized = ensureVaultStructure(target.vaultPath);
77
- console.log(initialized ? "Initialized vault structure." : "Vault structure already present.");
78
- console.log("\nTip: add this to your shell config:");
79
- console.log(` export CLAWVAULT_PATH="${target.vaultPath}"`);
80
- if (hasQmd()) {
81
- const { collection, root } = getQmdConfig(target.vaultPath);
82
- try {
83
- execFileSync("qmd", ["collection", "add", root, "--name", collection, "--mask", "**/*.md"], {
84
- stdio: "ignore"
85
- });
86
- console.log(`qmd collection ready: ${collection}`);
87
- } catch {
88
- console.log("qmd collection already exists or could not be created.");
89
- }
90
- } else {
91
- console.log("qmd not found; skipping collection setup.");
92
- }
93
- }
94
-
95
- export {
96
- setupCommand
97
- };