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.
- package/bin/clawvault.js +6 -0
- package/bin/register-core-commands.js +25 -2
- package/bin/register-tailscale-commands.js +106 -0
- package/bin/register-task-commands.js +18 -2
- package/bin/register-task-commands.test.js +24 -0
- package/dist/{chunk-SOTWYGH7.js → chunk-33GW63WK.js} +4 -35
- package/dist/chunk-4GBPTBFJ.js +628 -0
- package/dist/{chunk-GQVYQCY5.js → chunk-AHGUJG76.js} +3 -3
- package/dist/{chunk-GJEGPO7U.js → chunk-BI6SGGZP.js} +1 -1
- package/dist/chunk-CLE2HHNT.js +513 -0
- package/dist/{chunk-NGVAEFT2.js → chunk-DEFBIVQ3.js} +21 -0
- package/dist/{chunk-DPS7NYIU.js → chunk-DHJPXGC7.js} +2 -2
- package/dist/{chunk-2HM7ZI4X.js → chunk-FEFPBHH4.js} +287 -12
- package/dist/{chunk-K6XHCUFL.js → chunk-FHFUXL6G.js} +8 -1
- package/dist/{chunk-6BBTI7NV.js → chunk-GBIDDDSL.js} +2 -2
- package/dist/{chunk-VR5NE7PZ.js → chunk-HVTTYDCJ.js} +1 -1
- package/dist/chunk-IFTEGE4D.js +361 -0
- package/dist/{chunk-5WR6RRPX.js → chunk-JXY6T5R7.js} +2 -2
- package/dist/chunk-L3DJ36BZ.js +40 -0
- package/dist/{chunk-Z2XBWN7A.js → chunk-NAMFB7ZA.js} +2 -0
- package/dist/chunk-NZ4ZZNSR.js +373 -0
- package/dist/{chunk-OTQW3OMC.js → chunk-Q3WBH4P4.js} +97 -0
- package/dist/{chunk-MQUJNOHK.js → chunk-QALB2V3E.js} +1 -1
- package/dist/{chunk-PTSEIWXZ.js → chunk-SNEMCQP7.js} +13 -6
- package/dist/commands/archive.js +3 -3
- package/dist/commands/backlog.js +9 -2
- package/dist/commands/blocked.js +9 -2
- package/dist/commands/canvas.d.ts +11 -3
- package/dist/commands/canvas.js +1333 -25
- package/dist/commands/context.js +5 -4
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/migrate-observations.js +3 -3
- package/dist/commands/observe.d.ts +1 -0
- package/dist/commands/observe.js +5 -4
- package/dist/commands/rebuild.js +5 -4
- package/dist/commands/reflect.js +5 -5
- package/dist/commands/replay.js +7 -6
- package/dist/commands/setup.d.ts +10 -2
- package/dist/commands/setup.js +1 -1
- package/dist/commands/sleep.js +7 -6
- package/dist/commands/status.js +1 -1
- package/dist/commands/tailscale.d.ts +52 -0
- package/dist/commands/tailscale.js +25 -0
- package/dist/commands/task.js +1 -1
- package/dist/commands/wake.js +4 -4
- package/dist/index.d.ts +9 -0
- package/dist/index.js +79 -15
- package/dist/lib/tailscale.d.ts +225 -0
- package/dist/lib/tailscale.js +49 -0
- package/dist/lib/task-utils.d.ts +13 -1
- package/dist/lib/task-utils.js +3 -1
- package/dist/lib/webdav.d.ts +109 -0
- package/dist/lib/webdav.js +34 -0
- package/package.json +2 -2
- 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
|
+
};
|
package/dist/lib/task-utils.d.ts
CHANGED
|
@@ -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 };
|
package/dist/lib/task-utils.js
CHANGED
|
@@ -19,8 +19,9 @@ import {
|
|
|
19
19
|
readBacklogItem,
|
|
20
20
|
readTask,
|
|
21
21
|
slugify,
|
|
22
|
+
updateBacklogItem,
|
|
22
23
|
updateTask
|
|
23
|
-
} from "../chunk-
|
|
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
|
+
"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/
|
|
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",
|
package/dist/chunk-W463YRED.js
DELETED
|
@@ -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
|
-
};
|