clawvault 1.10.3 → 1.11.1
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/README.md +0 -49
- package/bin/clawvault.js +6 -343
- package/dist/{chunk-RPMQZZPE.js → chunk-FPEH4FVM.js} +22 -9
- package/dist/{chunk-5VYRT2XZ.js → chunk-G3YZEFKU.js} +1 -1
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/observe.js +2 -2
- package/dist/commands/sleep.d.ts +0 -2
- package/dist/commands/sleep.js +5 -9
- package/dist/commands/status.js +3 -3
- package/dist/commands/wake.d.ts +2 -0
- package/dist/commands/wake.js +82 -12
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-BBPSJL6H.js +0 -375
- package/dist/commands/cloud.d.ts +0 -63
- package/dist/commands/cloud.js +0 -117
- package/dist/types-CilEQY9w.d.ts +0 -51
package/README.md
CHANGED
|
@@ -106,32 +106,6 @@ clawvault context "what decisions were made" --budget 2000
|
|
|
106
106
|
# → fits within token budget, 🔴 items first
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
## ClawVault Cloud
|
|
110
|
-
|
|
111
|
-
ClawVault Cloud extends local memory with org-linked decision traces. The local vault stays your source of truth, and cloud sync adds cross-agent visibility plus centralized audit trails.
|
|
112
|
-
|
|
113
|
-
- **Local-first writes** - `trace emit` always appends locally before sync attempts.
|
|
114
|
-
- **Queued and retryable sync** - traces are buffered and sent with `clawvault sync`.
|
|
115
|
-
- **Org-linked vault identity** - each vault can be linked once, then monitored with status checks.
|
|
116
|
-
- **Backwards-compatible sync command** - `clawvault sync <target>` still syncs vault files to a folder.
|
|
117
|
-
|
|
118
|
-
Quick setup:
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
# 1) Save your cloud API key
|
|
122
|
-
clawvault config --cloud-key cvk_xxx
|
|
123
|
-
|
|
124
|
-
# 2) Link this local vault to your org
|
|
125
|
-
clawvault org link --vault ~/memory
|
|
126
|
-
|
|
127
|
-
# 3) Verify cloud + org link state
|
|
128
|
-
clawvault org status
|
|
129
|
-
|
|
130
|
-
# 4) Emit trace events and sync queued traces
|
|
131
|
-
clawvault trace emit --summary "Approved 20% discount for ACME"
|
|
132
|
-
clawvault sync
|
|
133
|
-
```
|
|
134
|
-
|
|
135
109
|
## Search
|
|
136
110
|
|
|
137
111
|
Use `clawvault search` / `qmd` for vault search — it indexes the **entire vault** (decisions/, people/, lessons/, observations/, etc.).
|
|
@@ -217,29 +191,6 @@ clawvault recap --brief # Token-efficient recap
|
|
|
217
191
|
clawvault doctor
|
|
218
192
|
```
|
|
219
193
|
|
|
220
|
-
### Cloud Sync
|
|
221
|
-
|
|
222
|
-
```bash
|
|
223
|
-
# Configure cloud API access
|
|
224
|
-
clawvault config --cloud-key cvk_xxx
|
|
225
|
-
clawvault config --cloud-api-url https://api.clawvault.dev # optional override
|
|
226
|
-
|
|
227
|
-
# Link local vault to cloud org/vault ID
|
|
228
|
-
clawvault org link --vault ~/memory
|
|
229
|
-
clawvault org status
|
|
230
|
-
|
|
231
|
-
# Emit decision traces (summary-only or JSON payload)
|
|
232
|
-
clawvault trace emit --summary "Approved 20% discount for ACME"
|
|
233
|
-
clawvault trace emit --trace-file ./trace.json
|
|
234
|
-
|
|
235
|
-
# Sync queued cloud traces (no target argument)
|
|
236
|
-
clawvault sync
|
|
237
|
-
clawvault sync --all
|
|
238
|
-
clawvault sync --limit 25
|
|
239
|
-
|
|
240
|
-
# Existing file sync still works when target is provided
|
|
241
|
-
clawvault sync ./obsidian # existing file sync to target folder
|
|
242
|
-
```
|
|
243
194
|
|
|
244
195
|
## Agent Setup (AGENTS.md)
|
|
245
196
|
|
package/bin/clawvault.js
CHANGED
|
@@ -103,16 +103,6 @@ function printQmdMissing() {
|
|
|
103
103
|
console.log(chalk.dim(`Install: ${QMD_INSTALL_COMMAND}`));
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
function cloudSkipReasonText(reason) {
|
|
107
|
-
const map = {
|
|
108
|
-
'empty-queue': 'No pending traces to sync.',
|
|
109
|
-
'cloud-not-configured': 'Cloud not fully configured (need API key and linked vault).',
|
|
110
|
-
'sync-disabled': 'Cloud sync disabled for this trace emit.',
|
|
111
|
-
'sync-failed': 'Cloud sync failed; traces remain queued.'
|
|
112
|
-
};
|
|
113
|
-
return map[reason] || `Skipped: ${reason}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
106
|
function parseBooleanInput(value, defaultValue = true) {
|
|
117
107
|
const normalized = value.trim().toLowerCase();
|
|
118
108
|
if (!normalized) {
|
|
@@ -127,125 +117,6 @@ function parseBooleanInput(value, defaultValue = true) {
|
|
|
127
117
|
return null;
|
|
128
118
|
}
|
|
129
119
|
|
|
130
|
-
async function promptDecisionTrace(initialSummary) {
|
|
131
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
132
|
-
|
|
133
|
-
const ask = async (label, defaultValue = '') => {
|
|
134
|
-
const suffix = defaultValue ? ` [${defaultValue}]` : '';
|
|
135
|
-
const answer = await rl.question(`${label}${suffix}: `);
|
|
136
|
-
const trimmed = answer.trim();
|
|
137
|
-
return trimmed || defaultValue;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const askRequired = async (label, defaultValue = '') => {
|
|
141
|
-
while (true) {
|
|
142
|
-
const value = await ask(label, defaultValue);
|
|
143
|
-
if (value.trim()) {
|
|
144
|
-
return value.trim();
|
|
145
|
-
}
|
|
146
|
-
console.log(chalk.yellow(`${label} is required.`));
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const askBoolean = async (label, defaultValue = true) => {
|
|
151
|
-
while (true) {
|
|
152
|
-
const defaultText = defaultValue ? 'Y/n' : 'y/N';
|
|
153
|
-
const answer = await rl.question(`${label} (${defaultText}): `);
|
|
154
|
-
const parsed = parseBooleanInput(answer, defaultValue);
|
|
155
|
-
if (parsed !== null) {
|
|
156
|
-
return parsed;
|
|
157
|
-
}
|
|
158
|
-
console.log(chalk.yellow('Please answer yes or no.'));
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
const askOptionalObject = async (label) => {
|
|
163
|
-
while (true) {
|
|
164
|
-
const raw = await rl.question(`${label} (JSON object, leave blank for none): `);
|
|
165
|
-
const trimmed = raw.trim();
|
|
166
|
-
if (!trimmed) {
|
|
167
|
-
return undefined;
|
|
168
|
-
}
|
|
169
|
-
try {
|
|
170
|
-
const parsed = JSON.parse(trimmed);
|
|
171
|
-
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
172
|
-
console.log(chalk.yellow('Please enter a JSON object (e.g. {"key":"value"}).'));
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
return parsed;
|
|
176
|
-
} catch {
|
|
177
|
-
console.log(chalk.yellow('Invalid JSON. Try again.'));
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
const collectInputs = async () => {
|
|
183
|
-
const inputs = [];
|
|
184
|
-
let index = 1;
|
|
185
|
-
while (await askBoolean(`Add input #${index}?`, index === 1)) {
|
|
186
|
-
const source = await askRequired(' input.source');
|
|
187
|
-
const type = await askRequired(' input.type');
|
|
188
|
-
const id = await askRequired(' input.id');
|
|
189
|
-
const data = await askOptionalObject(' input.data');
|
|
190
|
-
inputs.push(data ? { source, type, id, data } : { source, type, id });
|
|
191
|
-
index += 1;
|
|
192
|
-
}
|
|
193
|
-
return inputs;
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
const collectPolicies = async () => {
|
|
197
|
-
const policies = [];
|
|
198
|
-
let index = 1;
|
|
199
|
-
while (await askBoolean(`Add policy #${index}?`, index === 1)) {
|
|
200
|
-
const id = await askRequired(' policy.id');
|
|
201
|
-
const name = await askRequired(' policy.name');
|
|
202
|
-
const version = await askRequired(' policy.version', '1.0');
|
|
203
|
-
const rule = await askRequired(' policy.rule');
|
|
204
|
-
const result = await askRequired(' policy.result');
|
|
205
|
-
policies.push({ id, name, version, rule, result });
|
|
206
|
-
index += 1;
|
|
207
|
-
}
|
|
208
|
-
return policies;
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
const collectExceptions = async () => {
|
|
212
|
-
const exceptions = [];
|
|
213
|
-
let index = 1;
|
|
214
|
-
while (await askBoolean(`Add exception #${index}?`, false)) {
|
|
215
|
-
const policyId = await askRequired(' exception.policyId');
|
|
216
|
-
const reason = await askRequired(' exception.reason');
|
|
217
|
-
const approvedBy = await ask(' exception.approvedBy');
|
|
218
|
-
exceptions.push(approvedBy ? { policyId, reason, approvedBy } : { policyId, reason });
|
|
219
|
-
index += 1;
|
|
220
|
-
}
|
|
221
|
-
return exceptions;
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
try {
|
|
225
|
-
console.log(chalk.cyan('\nTrace emit interactive mode\n'));
|
|
226
|
-
const summary = await askRequired('summary', initialSummary);
|
|
227
|
-
const inputs = await collectInputs();
|
|
228
|
-
const policies = await collectPolicies();
|
|
229
|
-
const exceptions = await collectExceptions();
|
|
230
|
-
|
|
231
|
-
console.log(chalk.cyan('\nOutcome\n'));
|
|
232
|
-
const action = await askRequired(' outcome.action');
|
|
233
|
-
const target = await askRequired(' outcome.target');
|
|
234
|
-
const success = await askBoolean(' outcome.success', true);
|
|
235
|
-
const data = await askOptionalObject(' outcome.data');
|
|
236
|
-
|
|
237
|
-
return {
|
|
238
|
-
summary,
|
|
239
|
-
inputs,
|
|
240
|
-
policies,
|
|
241
|
-
exceptions,
|
|
242
|
-
outcome: data ? { action, target, success, data } : { action, target, success }
|
|
243
|
-
};
|
|
244
|
-
} finally {
|
|
245
|
-
rl.close();
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
120
|
program
|
|
250
121
|
.name('clawvault')
|
|
251
122
|
.description('🐘 An elephant never forgets. Structured memory for AI agents.')
|
|
@@ -314,164 +185,6 @@ program
|
|
|
314
185
|
}
|
|
315
186
|
});
|
|
316
187
|
|
|
317
|
-
// === CONFIG ===
|
|
318
|
-
program
|
|
319
|
-
.command('config')
|
|
320
|
-
.description('Manage ClawVault cloud configuration')
|
|
321
|
-
.option('--cloud-key <key>', 'Set cloud API key')
|
|
322
|
-
.option('--cloud-api-url <url>', 'Set cloud API base URL')
|
|
323
|
-
.option('--json', 'Output as JSON')
|
|
324
|
-
.action(async (options) => {
|
|
325
|
-
try {
|
|
326
|
-
const { cloudConfigCommand } = await import('../dist/commands/cloud.js');
|
|
327
|
-
const status = await cloudConfigCommand({
|
|
328
|
-
cloudKey: options.cloudKey,
|
|
329
|
-
cloudApiUrl: options.cloudApiUrl
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
if (options.json) {
|
|
333
|
-
console.log(JSON.stringify(status, null, 2));
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
console.log(chalk.cyan('\n☁️ Cloud Config\n'));
|
|
338
|
-
console.log(chalk.dim(`API key: ${status.cloudApiKeyMasked}`));
|
|
339
|
-
console.log(chalk.dim(`Vault ID: ${status.cloudVaultId || '(not linked)'}`));
|
|
340
|
-
console.log(chalk.dim(`Org slug: ${status.cloudOrgSlug || '(not set)'}`));
|
|
341
|
-
console.log(chalk.dim(`Queue depth: ${status.queueDepth}`));
|
|
342
|
-
console.log(chalk.dim(`Configured: ${status.configured ? 'yes' : 'no'}`));
|
|
343
|
-
console.log();
|
|
344
|
-
} catch (err) {
|
|
345
|
-
console.error(chalk.red(`Error: ${err.message}`));
|
|
346
|
-
process.exit(1);
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
// === ORG ===
|
|
351
|
-
const org = program
|
|
352
|
-
.command('org')
|
|
353
|
-
.description('Manage cloud organization link');
|
|
354
|
-
|
|
355
|
-
org
|
|
356
|
-
.command('link')
|
|
357
|
-
.description('Link this vault to cloud org')
|
|
358
|
-
.option('-v, --vault <path>', 'Vault path')
|
|
359
|
-
.option('-a, --agent-id <id>', 'Agent ID (default: OPENCLAW_AGENT_ID or agent-local)')
|
|
360
|
-
.option('--org-slug <slug>', 'Org slug override')
|
|
361
|
-
.option('--json', 'Output as JSON')
|
|
362
|
-
.action(async (options) => {
|
|
363
|
-
try {
|
|
364
|
-
const vaultPath = resolveVaultPath(options.vault);
|
|
365
|
-
const { orgLinkCommand } = await import('../dist/commands/cloud.js');
|
|
366
|
-
const result = await orgLinkCommand({
|
|
367
|
-
vaultPath,
|
|
368
|
-
agentId: options.agentId,
|
|
369
|
-
orgSlug: options.orgSlug
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
if (options.json) {
|
|
373
|
-
console.log(JSON.stringify(result, null, 2));
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
console.log(chalk.green(`✓ Cloud vault linked: ${result.vaultId}`));
|
|
378
|
-
console.log(chalk.dim(` Vault: ${result.vaultName}`));
|
|
379
|
-
if (result.orgSlug) {
|
|
380
|
-
console.log(chalk.dim(` Org: ${result.orgSlug}`));
|
|
381
|
-
}
|
|
382
|
-
} catch (err) {
|
|
383
|
-
console.error(chalk.red(`Error: ${err.message}`));
|
|
384
|
-
process.exit(1);
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
org
|
|
389
|
-
.command('status')
|
|
390
|
-
.description('Show cloud org link status')
|
|
391
|
-
.option('--json', 'Output as JSON')
|
|
392
|
-
.action(async (options) => {
|
|
393
|
-
try {
|
|
394
|
-
const { orgStatusCommand } = await import('../dist/commands/cloud.js');
|
|
395
|
-
const status = await orgStatusCommand();
|
|
396
|
-
|
|
397
|
-
if (options.json) {
|
|
398
|
-
console.log(JSON.stringify(status, null, 2));
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
console.log(chalk.cyan('\n☁️ Org Status\n'));
|
|
403
|
-
console.log(chalk.dim(`Configured: ${status.configured ? 'yes' : 'no'}`));
|
|
404
|
-
console.log(chalk.dim(`API key set: ${status.apiKeySet ? 'yes' : 'no'}`));
|
|
405
|
-
console.log(chalk.dim(`Vault linked: ${status.vaultIdSet ? 'yes' : 'no'}`));
|
|
406
|
-
console.log(chalk.dim(`Org slug: ${status.orgSlug || '(not set)'}`));
|
|
407
|
-
console.log(chalk.dim(`Queue depth: ${status.queueDepth}`));
|
|
408
|
-
if (status.cloudApiUrl) {
|
|
409
|
-
console.log(chalk.dim(`API URL: ${status.cloudApiUrl}`));
|
|
410
|
-
}
|
|
411
|
-
console.log();
|
|
412
|
-
} catch (err) {
|
|
413
|
-
console.error(chalk.red(`Error: ${err.message}`));
|
|
414
|
-
process.exit(1);
|
|
415
|
-
}
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
// === TRACE ===
|
|
419
|
-
const trace = program
|
|
420
|
-
.command('trace')
|
|
421
|
-
.description('Manage decision traces');
|
|
422
|
-
|
|
423
|
-
trace
|
|
424
|
-
.command('emit')
|
|
425
|
-
.description('Emit decision trace (interactive, local + cloud queue)')
|
|
426
|
-
.option('--summary <text>', 'Decision summary')
|
|
427
|
-
.option('--trace-json <json>', 'Decision trace JSON payload')
|
|
428
|
-
.option('--trace-file <path>', 'Path to JSON trace payload')
|
|
429
|
-
.option('--stdin', 'Read JSON trace payload from stdin')
|
|
430
|
-
.option('--no-sync', 'Skip immediate cloud sync attempt')
|
|
431
|
-
.option('--json', 'Output as JSON')
|
|
432
|
-
.action(async (options) => {
|
|
433
|
-
try {
|
|
434
|
-
const { traceEmitCommand } = await import('../dist/commands/cloud.js');
|
|
435
|
-
const hasPayloadInput = Boolean(options.traceJson || options.traceFile || options.stdin);
|
|
436
|
-
|
|
437
|
-
let tracePayload;
|
|
438
|
-
if (!hasPayloadInput) {
|
|
439
|
-
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
440
|
-
throw new Error(
|
|
441
|
-
'Interactive trace emit requires a TTY. Use --trace-json, --trace-file, or --stdin for non-interactive mode.'
|
|
442
|
-
);
|
|
443
|
-
}
|
|
444
|
-
tracePayload = await promptDecisionTrace(options.summary);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
const result = await traceEmitCommand({
|
|
448
|
-
summary: options.summary,
|
|
449
|
-
traceJson: options.traceJson,
|
|
450
|
-
traceFile: options.traceFile,
|
|
451
|
-
stdin: options.stdin,
|
|
452
|
-
sync: options.sync,
|
|
453
|
-
trace: tracePayload
|
|
454
|
-
});
|
|
455
|
-
|
|
456
|
-
if (options.json) {
|
|
457
|
-
console.log(JSON.stringify(result, null, 2));
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
console.log(chalk.green(`✓ Trace emitted: ${result.trace.localTraceId}`));
|
|
462
|
-
console.log(chalk.dim(` Summary: ${result.trace.summary}`));
|
|
463
|
-
console.log(chalk.dim(` Queue depth: ${result.queueDepth}`));
|
|
464
|
-
if (result.sync.skippedReason) {
|
|
465
|
-
console.log(chalk.yellow(` Cloud sync: ${cloudSkipReasonText(result.sync.skippedReason)}`));
|
|
466
|
-
} else {
|
|
467
|
-
console.log(chalk.dim(` Cloud sync: sent ${result.sync.synced}, remaining ${result.sync.remaining}`));
|
|
468
|
-
}
|
|
469
|
-
} catch (err) {
|
|
470
|
-
console.error(chalk.red(`Error: ${err.message}`));
|
|
471
|
-
process.exit(1);
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
|
|
475
188
|
// === STORE ===
|
|
476
189
|
program
|
|
477
190
|
.command('store')
|
|
@@ -539,16 +252,6 @@ program
|
|
|
539
252
|
const collection = vault.getQmdCollection();
|
|
540
253
|
await runQmd(collection ? ['update', '-c', collection] : ['update']);
|
|
541
254
|
}
|
|
542
|
-
|
|
543
|
-
const { autoSyncHandoffCommand } = await import('../dist/commands/cloud.js');
|
|
544
|
-
const cloudSync = await autoSyncHandoffCommand();
|
|
545
|
-
if (!options.json) {
|
|
546
|
-
if (cloudSync.skippedReason) {
|
|
547
|
-
console.log(chalk.dim(` Cloud sync: ${cloudSkipReasonText(cloudSync.skippedReason)}`));
|
|
548
|
-
} else {
|
|
549
|
-
console.log(chalk.dim(` Cloud sync: sent ${cloudSync.synced}, remaining ${cloudSync.remaining}`));
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
255
|
} catch (err) {
|
|
553
256
|
console.error(chalk.red(`Error: ${err.message}`));
|
|
554
257
|
process.exit(1);
|
|
@@ -882,33 +585,15 @@ program
|
|
|
882
585
|
}
|
|
883
586
|
});
|
|
884
587
|
|
|
885
|
-
// === SYNC ===
|
|
588
|
+
// === SYNC (vault file sync only) ===
|
|
886
589
|
program
|
|
887
|
-
.command('sync
|
|
888
|
-
.description('Sync
|
|
590
|
+
.command('sync <target>')
|
|
591
|
+
.description('Sync vault files to target path')
|
|
889
592
|
.option('--delete', 'Delete orphan files in target')
|
|
890
593
|
.option('--dry-run', "Show what would be synced without syncing")
|
|
891
|
-
.option('--all', 'For cloud sync, send all queued traces')
|
|
892
|
-
.option('--limit <n>', 'For cloud sync, max traces to send')
|
|
893
594
|
.option('-v, --vault <path>', 'Vault path')
|
|
894
595
|
.action(async (target, options) => {
|
|
895
596
|
try {
|
|
896
|
-
if (!target) {
|
|
897
|
-
const { cloudSyncCommand } = await import('../dist/commands/cloud.js');
|
|
898
|
-
const cloudResult = await cloudSyncCommand({
|
|
899
|
-
all: options.all,
|
|
900
|
-
limit: options.limit ? parseInt(options.limit, 10) : undefined
|
|
901
|
-
});
|
|
902
|
-
|
|
903
|
-
if (cloudResult.skippedReason) {
|
|
904
|
-
console.log(chalk.yellow(cloudSkipReasonText(cloudResult.skippedReason)));
|
|
905
|
-
} else {
|
|
906
|
-
console.log(chalk.green(`✓ Synced ${cloudResult.synced} trace(s) to cloud`));
|
|
907
|
-
console.log(chalk.dim(` Remaining queued: ${cloudResult.remaining}`));
|
|
908
|
-
}
|
|
909
|
-
return;
|
|
910
|
-
}
|
|
911
|
-
|
|
912
597
|
const vault = await getVault(options.vault);
|
|
913
598
|
|
|
914
599
|
console.log(chalk.cyan(`\n🔄 Syncing to ${target}...\n`));
|
|
@@ -1128,13 +813,6 @@ program
|
|
|
1128
813
|
console.log(chalk.dim(' Git: commit skipped'));
|
|
1129
814
|
}
|
|
1130
815
|
}
|
|
1131
|
-
if (result.cloudSync) {
|
|
1132
|
-
if (result.cloudSync.skippedReason) {
|
|
1133
|
-
console.log(chalk.dim(` Cloud sync: ${cloudSkipReasonText(result.cloudSync.skippedReason)}`));
|
|
1134
|
-
} else {
|
|
1135
|
-
console.log(chalk.dim(` Cloud sync: sent ${result.cloudSync.synced}, remaining ${result.cloudSync.remaining}`));
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
816
|
if (result.observationRoutingSummary) {
|
|
1139
817
|
console.log(chalk.dim(` Observe: ${result.observationRoutingSummary}`));
|
|
1140
818
|
}
|
|
@@ -1177,7 +855,6 @@ program
|
|
|
1177
855
|
};
|
|
1178
856
|
|
|
1179
857
|
const doc = await vault.createHandoff(handoff);
|
|
1180
|
-
let cloudSync;
|
|
1181
858
|
|
|
1182
859
|
if (!options.json) {
|
|
1183
860
|
console.log(chalk.green(`✓ Handoff created: ${doc.id}`));
|
|
@@ -1190,15 +867,8 @@ program
|
|
|
1190
867
|
await runQmd(collection ? ['update', '-c', collection] : ['update']);
|
|
1191
868
|
}
|
|
1192
869
|
|
|
1193
|
-
const { autoSyncHandoffCommand } = await import('../dist/commands/cloud.js');
|
|
1194
|
-
cloudSync = await autoSyncHandoffCommand();
|
|
1195
|
-
|
|
1196
870
|
if (options.json) {
|
|
1197
|
-
console.log(JSON.stringify({ id: doc.id, path: doc.path, handoff
|
|
1198
|
-
} else if (cloudSync.skippedReason) {
|
|
1199
|
-
console.log(chalk.dim(` Cloud sync: ${cloudSkipReasonText(cloudSync.skippedReason)}`));
|
|
1200
|
-
} else {
|
|
1201
|
-
console.log(chalk.dim(` Cloud sync: sent ${cloudSync.synced}, remaining ${cloudSync.remaining}`));
|
|
871
|
+
console.log(JSON.stringify({ id: doc.id, path: doc.path, handoff }, null, 2));
|
|
1202
872
|
}
|
|
1203
873
|
} catch (err) {
|
|
1204
874
|
console.error(chalk.red(`Error: ${err.message}`));
|
|
@@ -1442,11 +1112,9 @@ program
|
|
|
1442
1112
|
blocked: options.blocked,
|
|
1443
1113
|
urgent: options.urgent
|
|
1444
1114
|
});
|
|
1445
|
-
const { autoSyncCheckpointCommand } = await import('../dist/commands/cloud.js');
|
|
1446
|
-
const cloudSync = await autoSyncCheckpointCommand();
|
|
1447
1115
|
|
|
1448
1116
|
if (options.json) {
|
|
1449
|
-
console.log(JSON.stringify(
|
|
1117
|
+
console.log(JSON.stringify(data, null, 2));
|
|
1450
1118
|
} else {
|
|
1451
1119
|
console.log(chalk.green('✓ Checkpoint saved'));
|
|
1452
1120
|
console.log(chalk.dim(` Timestamp: ${data.timestamp}`));
|
|
@@ -1454,11 +1122,6 @@ program
|
|
|
1454
1122
|
if (data.focus) console.log(chalk.dim(` Focus: ${data.focus}`));
|
|
1455
1123
|
if (data.blocked) console.log(chalk.dim(` Blocked: ${data.blocked}`));
|
|
1456
1124
|
if (data.urgent) console.log(chalk.dim(' Urgent: yes'));
|
|
1457
|
-
if (cloudSync.skippedReason) {
|
|
1458
|
-
console.log(chalk.dim(` Cloud sync: ${cloudSkipReasonText(cloudSync.skippedReason)}`));
|
|
1459
|
-
} else {
|
|
1460
|
-
console.log(chalk.dim(` Cloud sync: sent ${cloudSync.synced}, remaining ${cloudSync.remaining}`));
|
|
1461
|
-
}
|
|
1462
1125
|
}
|
|
1463
1126
|
} catch (err) {
|
|
1464
1127
|
console.error(chalk.red(`Error: ${err.message}`));
|
|
@@ -1621,4 +1284,4 @@ program
|
|
|
1621
1284
|
});
|
|
1622
1285
|
|
|
1623
1286
|
// Parse and run
|
|
1624
|
-
program.parse();
|
|
1287
|
+
program.parse();
|
|
@@ -34,6 +34,7 @@ var Compressor = class {
|
|
|
34
34
|
return this.mergeObservations(existingObservations, fallback);
|
|
35
35
|
}
|
|
36
36
|
resolveProvider() {
|
|
37
|
+
if (process.env.CLAWVAULT_NO_LLM) return null;
|
|
37
38
|
if (process.env.ANTHROPIC_API_KEY) {
|
|
38
39
|
return "anthropic";
|
|
39
40
|
}
|
|
@@ -47,21 +48,33 @@ var Compressor = class {
|
|
|
47
48
|
}
|
|
48
49
|
buildPrompt(messages, existingObservations) {
|
|
49
50
|
return [
|
|
50
|
-
"You are an observer that compresses raw AI session messages into durable observations.",
|
|
51
|
+
"You are an observer that compresses raw AI session messages into durable, human-meaningful observations.",
|
|
51
52
|
"",
|
|
52
53
|
"Rules:",
|
|
53
54
|
"- Output markdown only.",
|
|
54
55
|
"- Group observations by date heading: ## YYYY-MM-DD",
|
|
55
56
|
"- Each line must follow: <emoji> <HH:MM> <observation>",
|
|
56
57
|
"- Priority emojis: \u{1F534} critical, \u{1F7E1} notable, \u{1F7E2} info",
|
|
57
|
-
"- \u{1F534} for: decisions between alternatives,
|
|
58
|
-
"- \u{1F7E1} for: preferences, architecture discussions, trade-offs, milestones, people interactions, notable context
|
|
59
|
-
"- \u{1F7E2} for:
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"-
|
|
63
|
-
"
|
|
64
|
-
|
|
58
|
+
"- \u{1F534} for: decisions between alternatives, blockers, deadlines with explicit dates, breaking changes, commitments made to people",
|
|
59
|
+
"- \u{1F7E1} for: preferences, architecture discussions, trade-offs, milestones, people interactions, notable context",
|
|
60
|
+
"- \u{1F7E2} for: completed tasks, deployments, builds, general progress",
|
|
61
|
+
"",
|
|
62
|
+
"QUALITY FILTERS (important):",
|
|
63
|
+
"- DO NOT observe: CLI errors, command failures, tool output parsing issues, retry attempts, debug logs.",
|
|
64
|
+
" These are transient noise, not memories. Only observe errors if they represent a BLOCKER or an unresolved problem.",
|
|
65
|
+
'- DO NOT observe: "acknowledged the conversation", "said okay", routine confirmations.',
|
|
66
|
+
'- MERGE related events into single observations. If 5 images were generated, say "Generated 5 images for X" not 5 separate lines.',
|
|
67
|
+
'- MERGE retry sequences: "Tried X, failed, tried Y, succeeded" \u2192 "Resolved X using Y (after initial failure)"',
|
|
68
|
+
'- Prefer OUTCOMES over PROCESSES: "Deployed v1.2 to Railway" not "Started deploy... build finished... deploy succeeded"',
|
|
69
|
+
"",
|
|
70
|
+
"AGENT ATTRIBUTION:",
|
|
71
|
+
'- If the transcript shows multiple speakers/agents, prefix observations with who did it: "Pedro asked...", "Clawdious deployed...", "Zeca generated..."',
|
|
72
|
+
"- If only one agent is acting, attribution is optional.",
|
|
73
|
+
"",
|
|
74
|
+
"COMMITMENT FORMAT (when someone promises/agrees to something):",
|
|
75
|
+
'- Use: "\u{1F534} HH:MM [COMMITMENT] <who> committed to <what> by <when>" (include deadline if mentioned)',
|
|
76
|
+
"",
|
|
77
|
+
"Keep observations concise and factual. Aim for signal, not completeness.",
|
|
65
78
|
"",
|
|
66
79
|
"Existing observations (may be empty):",
|
|
67
80
|
existingObservations.trim() || "(none)",
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
formatAge
|
|
3
|
-
} from "../chunk-7ZRP733D.js";
|
|
4
1
|
import {
|
|
5
2
|
ClawVault,
|
|
6
3
|
findVault
|
|
@@ -12,6 +9,9 @@ import {
|
|
|
12
9
|
scanVaultLinks
|
|
13
10
|
} from "../chunk-4VQTUVH7.js";
|
|
14
11
|
import "../chunk-J7ZWCI2C.js";
|
|
12
|
+
import {
|
|
13
|
+
formatAge
|
|
14
|
+
} from "../chunk-7ZRP733D.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/doctor.ts
|
|
17
17
|
import * as fs from "fs";
|
package/dist/commands/observe.js
CHANGED
package/dist/commands/sleep.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { H as HandoffDocument, D as Document } from '../types-DMU3SuAV.js';
|
|
2
|
-
import { C as CloudSyncResult } from '../types-CilEQY9w.js';
|
|
3
2
|
|
|
4
3
|
type PromptFn = (question: string) => Promise<string>;
|
|
5
4
|
interface SleepOptions {
|
|
@@ -28,7 +27,6 @@ interface SleepResult {
|
|
|
28
27
|
handoff: HandoffDocument;
|
|
29
28
|
document: Document;
|
|
30
29
|
git?: GitCommitResult;
|
|
31
|
-
cloudSync?: CloudSyncResult;
|
|
32
30
|
observationRoutingSummary?: string;
|
|
33
31
|
}
|
|
34
32
|
declare function sleep(options: SleepOptions): Promise<SleepResult>;
|
package/dist/commands/sleep.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
clearDirtyFlag
|
|
3
|
-
} from "../chunk-MZZJLQNQ.js";
|
|
4
|
-
import {
|
|
5
|
-
autoSyncOnHandoff
|
|
6
|
-
} from "../chunk-BBPSJL6H.js";
|
|
7
1
|
import {
|
|
8
2
|
ClawVault
|
|
9
3
|
} from "../chunk-3HFB7EMU.js";
|
|
@@ -13,7 +7,10 @@ import {
|
|
|
13
7
|
import {
|
|
14
8
|
Observer,
|
|
15
9
|
parseSessionFile
|
|
16
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-FPEH4FVM.js";
|
|
11
|
+
import {
|
|
12
|
+
clearDirtyFlag
|
|
13
|
+
} from "../chunk-MZZJLQNQ.js";
|
|
17
14
|
|
|
18
15
|
// src/commands/sleep.ts
|
|
19
16
|
import * as fs from "fs";
|
|
@@ -173,7 +170,6 @@ async function sleep(options) {
|
|
|
173
170
|
cwd: options.cwd ?? process.cwd(),
|
|
174
171
|
interactive
|
|
175
172
|
});
|
|
176
|
-
const cloudSync = await autoSyncOnHandoff();
|
|
177
173
|
let observationRoutingSummary;
|
|
178
174
|
try {
|
|
179
175
|
const transcriptPath = resolveSessionTranscriptPath(options.sessionTranscript);
|
|
@@ -186,7 +182,7 @@ async function sleep(options) {
|
|
|
186
182
|
}
|
|
187
183
|
} catch {
|
|
188
184
|
}
|
|
189
|
-
return { handoff, document, git,
|
|
185
|
+
return { handoff, document, git, observationRoutingSummary };
|
|
190
186
|
}
|
|
191
187
|
export {
|
|
192
188
|
sleep
|
package/dist/commands/status.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
formatAge
|
|
3
|
-
} from "../chunk-7ZRP733D.js";
|
|
4
1
|
import {
|
|
5
2
|
ClawVault
|
|
6
3
|
} from "../chunk-3HFB7EMU.js";
|
|
@@ -12,6 +9,9 @@ import {
|
|
|
12
9
|
scanVaultLinks
|
|
13
10
|
} from "../chunk-4VQTUVH7.js";
|
|
14
11
|
import "../chunk-J7ZWCI2C.js";
|
|
12
|
+
import {
|
|
13
|
+
formatAge
|
|
14
|
+
} from "../chunk-7ZRP733D.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/status.ts
|
|
17
17
|
import * as fs from "fs";
|
package/dist/commands/wake.d.ts
CHANGED