@ai-dossier/cli 0.8.3 → 0.8.5
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 +130 -36
- package/dist/cache-resolver.d.ts +91 -0
- package/dist/cache-resolver.d.ts.map +1 -0
- package/dist/cache-resolver.js +331 -0
- package/dist/cache-resolver.js.map +1 -0
- package/dist/commands/cache.d.ts.map +1 -1
- package/dist/commands/cache.js +66 -0
- package/dist/commands/cache.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +37 -28
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/install-skill.d.ts.map +1 -1
- package/dist/commands/install-skill.js +21 -48
- package/dist/commands/install-skill.js.map +1 -1
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +5 -8
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +74 -119
- package/dist/commands/run.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/run-log.d.ts +15 -0
- package/dist/run-log.d.ts.map +1 -1
- package/dist/run-log.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/@ai-dossier/cli)
|
|
5
5
|
[](https://github.com/imboard-ai/ai-dossier/blob/main/LICENSE)
|
|
6
6
|
|
|
7
|
-
**
|
|
7
|
+
**Install, verify, and publish dossiers — portable, signed, versioned skills — for any LLM tool.**
|
|
8
|
+
|
|
9
|
+
A dossier is a skill with trust built in. This CLI is how you author them, verify their signatures, publish them to a registry, and install them as Claude Code skills (`install-skill` / `skill-export`).
|
|
8
10
|
|
|
9
11
|
## The Problem This Solves
|
|
10
12
|
|
|
11
|
-
**
|
|
13
|
+
A plain skill is unsigned, unversioned, and locked to one tool — and **LLMs cannot be relied upon to enforce security checks automatically.**
|
|
12
14
|
|
|
13
15
|
Even with MCP server installed and protocol documentation:
|
|
14
16
|
- ❌ LLMs may skip verification
|
|
@@ -225,7 +227,7 @@ ai-dossier pull org/dossier-a org/dossier-b
|
|
|
225
227
|
ai-dossier pull org/my-dossier --force
|
|
226
228
|
```
|
|
227
229
|
|
|
228
|
-
Pulled dossiers are cached locally with checksum verification. Subsequent `pull` calls skip the download if the version is already cached (use `--force` to override).
|
|
230
|
+
Pulled dossiers are cached locally with checksum verification. Subsequent `pull` calls skip the download if the version is already cached (use `--force` to override). See [Cache and Version Resolution](#cache-and-version-resolution) for how versionless names are resolved and how to control freshness.
|
|
229
231
|
|
|
230
232
|
### Export
|
|
231
233
|
|
|
@@ -244,6 +246,112 @@ ai-dossier export org/my-dossier --stdout
|
|
|
244
246
|
|
|
245
247
|
---
|
|
246
248
|
|
|
249
|
+
## Skills
|
|
250
|
+
|
|
251
|
+
A dossier is a skill with trust, versioning, and registry distribution added. These commands bridge the registry and Claude Code skills (`~/.claude/skills/`).
|
|
252
|
+
|
|
253
|
+
A **trigger skill** is a thin `SKILL.md` that fires on a phrase and invokes a versioned, signed dossier via `ai-dossier run <registry-path>`. You author and trigger it like any skill, but it gains signing, version pinning, and registry distribution.
|
|
254
|
+
|
|
255
|
+
### `install-skill` — registry dossier → Claude Code skill
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# Install a published skill into ~/.claude/skills/
|
|
259
|
+
ai-dossier install-skill org/skills/my-skill
|
|
260
|
+
|
|
261
|
+
# List installed skills / force a fresh re-pull / remove one
|
|
262
|
+
ai-dossier install-skill --list
|
|
263
|
+
ai-dossier install-skill org/skills/my-skill --fresh --force
|
|
264
|
+
ai-dossier install-skill --remove my-skill
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Restart Claude Code (or start a new session) to pick up a newly installed skill. At run time the skill calls `ai-dossier run <registry-path>`, which fetches and verifies the dossier on demand — so you don't need to install the dossier separately.
|
|
268
|
+
|
|
269
|
+
### `skill-export` — local skill → registry dossier
|
|
270
|
+
|
|
271
|
+
Publish a locally installed skill to the registry as a versioned, signed dossier so others can `install-skill` it:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
# Publish ~/.claude/skills/my-skill to the registry (minor version bump)
|
|
275
|
+
ai-dossier skill-export my-skill --namespace org/skills
|
|
276
|
+
|
|
277
|
+
# Pin an explicit version, add a changelog, verify the roundtrip
|
|
278
|
+
ai-dossier skill-export my-skill --version 2.0.0 --changelog "Add range support" --verify
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
| Option | Effect |
|
|
282
|
+
|--------|--------|
|
|
283
|
+
| `--namespace <ns>` | Registry namespace (default: first org or username) |
|
|
284
|
+
| `--version <v>` / `--major` / `--no-bump` | Control the published version |
|
|
285
|
+
| `--changelog <msg>` | Changelog message for the release |
|
|
286
|
+
| `--verify` | Re-install after publish to confirm the roundtrip |
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Cache and Version Resolution
|
|
291
|
+
|
|
292
|
+
The CLI maintains a local cache at `~/.dossier/cache/`:
|
|
293
|
+
|
|
294
|
+
- **Content cache** — `~/.dossier/cache/<name>/<version>.ds.md` (the dossier bytes, content-addressable by version).
|
|
295
|
+
- **Resolution cache** — `~/.dossier/cache/.resolution/<name>.json` (which version a versionless name resolves to, with TTL).
|
|
296
|
+
|
|
297
|
+
### How versionless names resolve
|
|
298
|
+
|
|
299
|
+
Pinned references (`org/my-dossier@1.2.3`) are content-addressable and never expire — they bypass the resolver entirely.
|
|
300
|
+
|
|
301
|
+
Versionless references (`org/my-dossier`) are resolved through a **TTL'd resolution cache**:
|
|
302
|
+
|
|
303
|
+
1. If a recent resolution exists (within TTL) → reuse it (no registry call).
|
|
304
|
+
2. Otherwise → call the registry, write the resolved version to the resolution cache, return it.
|
|
305
|
+
3. If the registry is unreachable → fall back to the highest-semver cached version and print a loud stderr warning. If nothing is cached, fail with a clear error.
|
|
306
|
+
|
|
307
|
+
This applies to `ai-dossier run`, `ai-dossier create`, and `ai-dossier install-skill`.
|
|
308
|
+
|
|
309
|
+
### Controlling freshness
|
|
310
|
+
|
|
311
|
+
| Flag | Effect |
|
|
312
|
+
|------|--------|
|
|
313
|
+
| (none) | Use cached resolution if newer than `cache.resolutionTtlSeconds` (default 300s). |
|
|
314
|
+
| `--max-age <seconds>` | Override TTL for this call. `0` forces a registry check. |
|
|
315
|
+
| `--fresh` | Skip the resolution cache and the content cache; fetch fresh from the registry. |
|
|
316
|
+
| `--pull` (`run` only) | Refresh the content cache (re-download) but still resolve via the resolver. |
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
# Default: use cached resolution if within 300s
|
|
320
|
+
ai-dossier run org/my-dossier
|
|
321
|
+
|
|
322
|
+
# Force a registry re-check
|
|
323
|
+
ai-dossier run org/my-dossier --max-age 0
|
|
324
|
+
|
|
325
|
+
# Skip the entire cache for this call
|
|
326
|
+
ai-dossier run org/my-dossier --fresh
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Configure the default TTL:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
dossier config cache.resolutionTtlSeconds 600
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### `cache` subcommand
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
# Show all cached dossiers (content cache)
|
|
339
|
+
ai-dossier cache list
|
|
340
|
+
ai-dossier cache list --size --json
|
|
341
|
+
|
|
342
|
+
# Show cached versionless → version resolutions (with timestamps)
|
|
343
|
+
ai-dossier cache resolutions
|
|
344
|
+
ai-dossier cache resolutions --json
|
|
345
|
+
|
|
346
|
+
# Remove cached entries
|
|
347
|
+
ai-dossier cache clean <name> # all versions of a dossier
|
|
348
|
+
ai-dossier cache clean <name> --ver 1.2.0 # specific version
|
|
349
|
+
ai-dossier cache clean --older-than 30 # entries older than N days
|
|
350
|
+
ai-dossier cache clean --all # everything (prompts; use -y to skip)
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
247
355
|
## Multi-Registry Resolution
|
|
248
356
|
|
|
249
357
|
The CLI queries all configured registries in parallel when resolving dossiers (e.g., `dossier get`, `dossier run`, `dossier pull`). This uses `Promise.allSettled()` so a single registry failure does not block results from other registries.
|
|
@@ -641,34 +749,20 @@ Exit 0 (safe) or 1 (unsafe)
|
|
|
641
749
|
|
|
642
750
|
---
|
|
643
751
|
|
|
644
|
-
## Limitations
|
|
645
|
-
|
|
646
|
-
### Current Limitations
|
|
647
|
-
|
|
648
|
-
1. **Signature Verification**: Basic implementation
|
|
649
|
-
- Detects test signatures (invalid/fake)
|
|
650
|
-
- Full minisign verification requires external tool
|
|
651
|
-
- Future: Native minisign support
|
|
652
|
-
|
|
653
|
-
2. **Trusted Keys**: Not yet implemented
|
|
654
|
-
- Future: Check against ~/.dossier/trusted-keys.txt
|
|
655
|
-
- Future: Key management commands
|
|
752
|
+
## Capabilities & Limitations
|
|
656
753
|
|
|
657
|
-
|
|
658
|
-
- Currently just verifies
|
|
659
|
-
- Future: Execute if verification passes
|
|
754
|
+
### What's implemented
|
|
660
755
|
|
|
661
|
-
|
|
756
|
+
- ✅ **Checksum verification** (SHA256) — catches any tampering with the dossier body
|
|
757
|
+
- ✅ **Signature verification** — Ed25519 (Minisign-compatible) and AWS KMS; signatures are validated, not just detected
|
|
758
|
+
- ✅ **Trusted keys** — verified against `~/.dossier/trusted-keys.txt`; manage with `ai-dossier keys`
|
|
759
|
+
- ✅ **Risk assessment** — declared risk level + destructive-operation analysis gate execution
|
|
760
|
+
- ✅ **Execution** — `ai-dossier run` verifies, then executes if checks pass
|
|
662
761
|
|
|
663
|
-
|
|
664
|
-
**Focus**: Get checksum verification working reliably
|
|
665
|
-
**Future**: Full signature verification, trust management, execution
|
|
762
|
+
### Current limitations
|
|
666
763
|
|
|
667
|
-
|
|
668
|
-
-
|
|
669
|
-
- ✅ Signature presence detection works
|
|
670
|
-
- ✅ Exit codes enable integration
|
|
671
|
-
- ✅ Enforces security before LLM involvement
|
|
764
|
+
- Verification is a single integrity stage (checksum + signature) plus risk assessment — there is no multi-stage sandbox; the executing agent enforces runtime permissions.
|
|
765
|
+
- Trust is local: you decide which keys to trust. A valid signature from an untrusted key is reported as such, not auto-trusted.
|
|
672
766
|
|
|
673
767
|
---
|
|
674
768
|
|
|
@@ -682,7 +776,7 @@ Exit 0 (safe) or 1 (unsafe)
|
|
|
682
776
|
|
|
683
777
|
### v0.2.0
|
|
684
778
|
- ✅ Multi-command CLI structure (`ai-dossier <command>`)
|
|
685
|
-
- ✅ `dossier run` command with
|
|
779
|
+
- ✅ `ai-dossier run` command with integrity verification (checksum + signature)
|
|
686
780
|
- ✅ LLM auto-detection and execution integration
|
|
687
781
|
|
|
688
782
|
### v0.3.0
|
|
@@ -715,18 +809,18 @@ Exit 0 (safe) or 1 (unsafe)
|
|
|
715
809
|
- ✅ Coverage thresholds enforcement
|
|
716
810
|
- ✅ Documentation consistency fixes
|
|
717
811
|
|
|
718
|
-
### v0.8.
|
|
812
|
+
### v0.8.x (Current)
|
|
719
813
|
- ✅ Zod validation on MCP prompt handlers
|
|
720
814
|
- ✅ Complete doc link audit and fix (30+ broken links)
|
|
721
|
-
- ✅
|
|
722
|
-
- ✅
|
|
723
|
-
- ✅
|
|
815
|
+
- ✅ Ed25519 + AWS KMS signature verification with trusted-keys
|
|
816
|
+
- ✅ `install-skill` / `skill-export` (Claude Code skill bridge)
|
|
817
|
+
- ✅ Execution tracing with verified checksum + signer metadata
|
|
818
|
+
- ✅ TTL-based version resolution for the content cache
|
|
724
819
|
|
|
725
820
|
### v1.0.0 (Stable)
|
|
726
|
-
- ⏳
|
|
727
|
-
- ⏳
|
|
728
|
-
- ⏳
|
|
729
|
-
- ⏳ Comprehensive documentation
|
|
821
|
+
- ⏳ Stable, frozen CLI surface and exit-code contract
|
|
822
|
+
- ⏳ Deeper integration with major LLM tools
|
|
823
|
+
- ⏳ Expanded registry/discovery features
|
|
730
824
|
|
|
731
825
|
---
|
|
732
826
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Versionless dossier name → resolved version mapping with TTL.
|
|
3
|
+
*
|
|
4
|
+
* Pinned versions (name@1.2.3) are content-addressable and never go stale.
|
|
5
|
+
* Versionless names (name) are the only thing that ages, so the TTL belongs
|
|
6
|
+
* on resolution, not on cached content bytes.
|
|
7
|
+
*
|
|
8
|
+
* Resolution cache lives at ~/.dossier/cache/.resolution/<name>.json, one
|
|
9
|
+
* tiny file per dossier with { resolved_version, resolved_at, source_registry }.
|
|
10
|
+
*
|
|
11
|
+
* On registry failure, falls back to the highest-semver version already in
|
|
12
|
+
* ~/.dossier/cache/<name>/ and prints a loud stderr warning so the staleness
|
|
13
|
+
* is never silent.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DEFAULT_RESOLUTION_TTL_SECONDS = 300;
|
|
16
|
+
export declare const CACHE_DIR: string;
|
|
17
|
+
export declare const RESOLUTION_DIR: string;
|
|
18
|
+
export interface ResolutionRecord {
|
|
19
|
+
resolved_version: string;
|
|
20
|
+
resolved_at: string;
|
|
21
|
+
source_registry?: string;
|
|
22
|
+
}
|
|
23
|
+
export type ResolutionSource = 'cache' | 'registry' | 'stale-cache';
|
|
24
|
+
export interface ResolvedVersion {
|
|
25
|
+
version: string;
|
|
26
|
+
source: ResolutionSource;
|
|
27
|
+
registry?: string;
|
|
28
|
+
/** Present only when source === 'stale-cache' — explains why we did not reach the registry. */
|
|
29
|
+
warning?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ResolveOptions {
|
|
32
|
+
/** Skip the resolution cache and force a registry call. */
|
|
33
|
+
fresh?: boolean;
|
|
34
|
+
/** Override the TTL for this call. 0 forces a registry call. */
|
|
35
|
+
maxAgeSeconds?: number;
|
|
36
|
+
}
|
|
37
|
+
/** Highest-semver version currently cached on disk for this name, or null. */
|
|
38
|
+
export declare function highestCachedSemver(dossierName: string): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a versionless dossier name to a concrete version.
|
|
41
|
+
*
|
|
42
|
+
* Flow:
|
|
43
|
+
* 1. If !fresh and a resolution file exists and is within TTL → return cached resolution.
|
|
44
|
+
* 2. Otherwise call the registry. On success → write resolution file → return.
|
|
45
|
+
* 3. On registry failure → fall back to highest-semver cached version with a
|
|
46
|
+
* loud stderr warning. If nothing is cached, rethrow.
|
|
47
|
+
*
|
|
48
|
+
* Callers should pass an already-stripped name (without @version suffix). For
|
|
49
|
+
* pinned versions, skip this resolver entirely.
|
|
50
|
+
*/
|
|
51
|
+
export declare function resolveCachedVersion(dossierName: string, opts?: ResolveOptions): Promise<ResolvedVersion>;
|
|
52
|
+
/** Exposed for the `cache resolutions` subcommand. */
|
|
53
|
+
export declare function listResolutions(): Array<{
|
|
54
|
+
name: string;
|
|
55
|
+
record: ResolutionRecord;
|
|
56
|
+
}>;
|
|
57
|
+
/** Exposed for tests and the `cache clean` flow — remove all resolution files. */
|
|
58
|
+
export declare function clearResolutions(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Path to a cached dossier's content file (without checking existence).
|
|
61
|
+
* Centralises the `<cache>/<name>/<version>.ds.md` layout used by
|
|
62
|
+
* run/create/install-skill/pull so layout changes happen in one place.
|
|
63
|
+
*/
|
|
64
|
+
export declare function cachedContentPath(dossierName: string, version: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Return cached dossier content as a string, or null if not cached.
|
|
67
|
+
* Single source of truth for the `existsSync(contentFile) ? read : miss`
|
|
68
|
+
* block that previously lived in run.ts, create.ts, and install-skill.ts.
|
|
69
|
+
*/
|
|
70
|
+
export declare function readCachedContent(dossierName: string, version: string): string | null;
|
|
71
|
+
/**
|
|
72
|
+
* Write a dossier's content + .meta.json to the cache.
|
|
73
|
+
*
|
|
74
|
+
* The .meta.json shape (`cached_at` + `version` + `source_registry`) is the
|
|
75
|
+
* one read by `cache list` / `cache clean` and was previously duplicated
|
|
76
|
+
* verbatim in run.ts, create.ts, install-skill.ts, and pull.ts.
|
|
77
|
+
*
|
|
78
|
+
* Best-effort by default (errors swallowed, matching create.ts/install-skill.ts).
|
|
79
|
+
* Pass `throwOnError: true` for callers that want to surface write failures
|
|
80
|
+
* (pull.ts wants this — a failed download cache write is a hard failure).
|
|
81
|
+
*/
|
|
82
|
+
export declare function writeCachedContent(dossierName: string, version: string, content: string, sourceRegistry: string | undefined, opts?: {
|
|
83
|
+
throwOnError?: boolean;
|
|
84
|
+
}): void;
|
|
85
|
+
/**
|
|
86
|
+
* Parse a `--max-age <seconds>` CLI option into a number, or return undefined
|
|
87
|
+
* when unset. Throws when the value is provided but not a valid number.
|
|
88
|
+
* Used by run/create/install-skill which all expose the same flag.
|
|
89
|
+
*/
|
|
90
|
+
export declare function parseMaxAgeOption(raw: string | undefined): number | undefined;
|
|
91
|
+
//# sourceMappingURL=cache-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-resolver.d.ts","sourceRoot":"","sources":["../src/cache-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,SAAS,QAA+C,CAAC;AACtE,eAAO,MAAM,cAAc,QAAsC,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,UAAU,GAAG,aAAa,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAwED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CActE;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,eAAe,CAAC,CAwF1B;AAED,sDAAsD;AACtD,wBAAgB,eAAe,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC,CA2BnF;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQrF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,IAAI,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACpC,IAAI,CAsBN;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAO7E"}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Versionless dossier name → resolved version mapping with TTL.
|
|
4
|
+
*
|
|
5
|
+
* Pinned versions (name@1.2.3) are content-addressable and never go stale.
|
|
6
|
+
* Versionless names (name) are the only thing that ages, so the TTL belongs
|
|
7
|
+
* on resolution, not on cached content bytes.
|
|
8
|
+
*
|
|
9
|
+
* Resolution cache lives at ~/.dossier/cache/.resolution/<name>.json, one
|
|
10
|
+
* tiny file per dossier with { resolved_version, resolved_at, source_registry }.
|
|
11
|
+
*
|
|
12
|
+
* On registry failure, falls back to the highest-semver version already in
|
|
13
|
+
* ~/.dossier/cache/<name>/ and prints a loud stderr warning so the staleness
|
|
14
|
+
* is never silent.
|
|
15
|
+
*/
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.RESOLUTION_DIR = exports.CACHE_DIR = exports.DEFAULT_RESOLUTION_TTL_SECONDS = void 0;
|
|
21
|
+
exports.highestCachedSemver = highestCachedSemver;
|
|
22
|
+
exports.resolveCachedVersion = resolveCachedVersion;
|
|
23
|
+
exports.listResolutions = listResolutions;
|
|
24
|
+
exports.clearResolutions = clearResolutions;
|
|
25
|
+
exports.cachedContentPath = cachedContentPath;
|
|
26
|
+
exports.readCachedContent = readCachedContent;
|
|
27
|
+
exports.writeCachedContent = writeCachedContent;
|
|
28
|
+
exports.parseMaxAgeOption = parseMaxAgeOption;
|
|
29
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
30
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
31
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
32
|
+
const config_1 = require("./config");
|
|
33
|
+
const helpers_1 = require("./helpers");
|
|
34
|
+
const multi_registry_1 = require("./multi-registry");
|
|
35
|
+
exports.DEFAULT_RESOLUTION_TTL_SECONDS = 300;
|
|
36
|
+
exports.CACHE_DIR = node_path_1.default.join(node_os_1.default.homedir(), '.dossier', 'cache');
|
|
37
|
+
exports.RESOLUTION_DIR = node_path_1.default.join(exports.CACHE_DIR, '.resolution');
|
|
38
|
+
function resolutionFilePath(dossierName) {
|
|
39
|
+
const safeDir = (0, helpers_1.safeDossierPath)(exports.RESOLUTION_DIR, dossierName);
|
|
40
|
+
return `${safeDir}.json`;
|
|
41
|
+
}
|
|
42
|
+
function readResolution(dossierName) {
|
|
43
|
+
const file = resolutionFilePath(dossierName);
|
|
44
|
+
try {
|
|
45
|
+
if (!node_fs_1.default.existsSync(file))
|
|
46
|
+
return null;
|
|
47
|
+
const raw = node_fs_1.default.readFileSync(file, 'utf8');
|
|
48
|
+
const parsed = JSON.parse(raw);
|
|
49
|
+
if (!parsed.resolved_version || !parsed.resolved_at) {
|
|
50
|
+
if (process.env.DOSSIER_DEBUG) {
|
|
51
|
+
process.stderr.write(`[cache-resolver] resolution file ${file} missing required fields; ignoring\n`);
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
return parsed;
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
// Corrupted resolution file — warn (always) and fall through to re-resolve.
|
|
59
|
+
// Silent fallback would hide a real corruption issue from operators.
|
|
60
|
+
process.stderr.write(`⚠️ Resolution cache file unreadable (${file}): ${err.message}. Re-resolving from registry.\n`);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function writeResolution(dossierName, record) {
|
|
65
|
+
const file = resolutionFilePath(dossierName);
|
|
66
|
+
const targetDir = node_path_1.default.dirname(file);
|
|
67
|
+
// Node's mkdir({recursive:true,mode}) only applies `mode` to the leaf directory it creates.
|
|
68
|
+
// For org-scoped names (org/sub/name) we must chmod each intermediate dir under
|
|
69
|
+
// RESOLUTION_DIR to 0o700 so resolution metadata never becomes world-readable.
|
|
70
|
+
node_fs_1.default.mkdirSync(targetDir, { recursive: true, mode: 0o700 });
|
|
71
|
+
let cursor = targetDir;
|
|
72
|
+
while (cursor.startsWith(exports.RESOLUTION_DIR) && cursor !== node_path_1.default.dirname(exports.RESOLUTION_DIR)) {
|
|
73
|
+
try {
|
|
74
|
+
node_fs_1.default.chmodSync(cursor, 0o700);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// best-effort; if chmod fails (e.g. not owner) we still proceed
|
|
78
|
+
}
|
|
79
|
+
if (cursor === exports.RESOLUTION_DIR)
|
|
80
|
+
break;
|
|
81
|
+
cursor = node_path_1.default.dirname(cursor);
|
|
82
|
+
}
|
|
83
|
+
// Defend against symlink swap: if a non-regular file (symlink, fifo, etc.) sits at
|
|
84
|
+
// the target path, refuse to write through it. lstat does not follow symlinks.
|
|
85
|
+
try {
|
|
86
|
+
const st = node_fs_1.default.lstatSync(file);
|
|
87
|
+
if (!st.isFile()) {
|
|
88
|
+
node_fs_1.default.unlinkSync(file);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// ENOENT — fine, fresh write
|
|
93
|
+
}
|
|
94
|
+
node_fs_1.default.writeFileSync(file, JSON.stringify(record, null, 2), { encoding: 'utf8', mode: 0o600 });
|
|
95
|
+
}
|
|
96
|
+
function compareSemver(a, b) {
|
|
97
|
+
const pa = a.split('.').map(Number);
|
|
98
|
+
const pb = b.split('.').map(Number);
|
|
99
|
+
for (let i = 0; i < 3; i++) {
|
|
100
|
+
const diff = (pa[i] || 0) - (pb[i] || 0);
|
|
101
|
+
if (diff !== 0)
|
|
102
|
+
return diff;
|
|
103
|
+
}
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
/** Highest-semver version currently cached on disk for this name, or null. */
|
|
107
|
+
function highestCachedSemver(dossierName) {
|
|
108
|
+
try {
|
|
109
|
+
const dir = (0, helpers_1.safeDossierPath)(exports.CACHE_DIR, dossierName);
|
|
110
|
+
if (!node_fs_1.default.existsSync(dir))
|
|
111
|
+
return null;
|
|
112
|
+
const versions = node_fs_1.default
|
|
113
|
+
.readdirSync(dir)
|
|
114
|
+
.filter((f) => f.endsWith('.meta.json'))
|
|
115
|
+
.map((f) => f.replace('.meta.json', ''))
|
|
116
|
+
.filter((v) => node_fs_1.default.existsSync(node_path_1.default.join(dir, `${v}.ds.md`)))
|
|
117
|
+
.sort(compareSemver);
|
|
118
|
+
return versions.length > 0 ? versions[versions.length - 1] : null;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function getConfiguredTtlSeconds() {
|
|
125
|
+
const raw = (0, config_1.getConfig)('cache.resolutionTtlSeconds');
|
|
126
|
+
if (typeof raw === 'number' && Number.isFinite(raw) && raw >= 0)
|
|
127
|
+
return raw;
|
|
128
|
+
return exports.DEFAULT_RESOLUTION_TTL_SECONDS;
|
|
129
|
+
}
|
|
130
|
+
function formatAge(ageMs) {
|
|
131
|
+
const seconds = Math.round(ageMs / 1000);
|
|
132
|
+
if (seconds < 60)
|
|
133
|
+
return `${seconds}s ago`;
|
|
134
|
+
const minutes = Math.round(seconds / 60);
|
|
135
|
+
if (minutes < 60)
|
|
136
|
+
return `${minutes}m ago`;
|
|
137
|
+
const hours = Math.round(minutes / 60);
|
|
138
|
+
if (hours < 24)
|
|
139
|
+
return `${hours}h ago`;
|
|
140
|
+
const days = Math.round(hours / 24);
|
|
141
|
+
return `${days}d ago`;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Resolve a versionless dossier name to a concrete version.
|
|
145
|
+
*
|
|
146
|
+
* Flow:
|
|
147
|
+
* 1. If !fresh and a resolution file exists and is within TTL → return cached resolution.
|
|
148
|
+
* 2. Otherwise call the registry. On success → write resolution file → return.
|
|
149
|
+
* 3. On registry failure → fall back to highest-semver cached version with a
|
|
150
|
+
* loud stderr warning. If nothing is cached, rethrow.
|
|
151
|
+
*
|
|
152
|
+
* Callers should pass an already-stripped name (without @version suffix). For
|
|
153
|
+
* pinned versions, skip this resolver entirely.
|
|
154
|
+
*/
|
|
155
|
+
async function resolveCachedVersion(dossierName, opts = {}) {
|
|
156
|
+
const ttl = opts.maxAgeSeconds ?? getConfiguredTtlSeconds();
|
|
157
|
+
if (!opts.fresh && ttl > 0) {
|
|
158
|
+
const cached = readResolution(dossierName);
|
|
159
|
+
if (cached) {
|
|
160
|
+
const ageMs = Date.now() - new Date(cached.resolved_at).getTime();
|
|
161
|
+
if (ageMs >= 0 && ageMs < ttl * 1000) {
|
|
162
|
+
if (process.env.DOSSIER_DEBUG) {
|
|
163
|
+
process.stderr.write(`[cache-resolver] '${dossierName}' served from resolution cache: ` +
|
|
164
|
+
`version=${cached.resolved_version}, age=${formatAge(ageMs)}, ttl=${ttl}s, registry=${cached.source_registry ?? 'unknown'}\n`);
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
version: cached.resolved_version,
|
|
168
|
+
source: 'cache',
|
|
169
|
+
registry: cached.source_registry,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (process.env.DOSSIER_DEBUG) {
|
|
173
|
+
process.stderr.write(`[cache-resolver] '${dossierName}' resolution cache expired (age=${formatAge(ageMs)}, ttl=${ttl}s); re-resolving\n`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else if (process.env.DOSSIER_DEBUG) {
|
|
177
|
+
process.stderr.write(`[cache-resolver] '${dossierName}' has no resolution cache; calling registry\n`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else if (process.env.DOSSIER_DEBUG) {
|
|
181
|
+
process.stderr.write(`[cache-resolver] '${dossierName}' bypassing resolution cache (fresh=${opts.fresh ?? false}, ttl=${ttl}s)\n`);
|
|
182
|
+
}
|
|
183
|
+
let registryError = null;
|
|
184
|
+
try {
|
|
185
|
+
const { result, errors } = await (0, multi_registry_1.multiRegistryGetDossier)(dossierName);
|
|
186
|
+
if (result?.version) {
|
|
187
|
+
writeResolution(dossierName, {
|
|
188
|
+
resolved_version: result.version,
|
|
189
|
+
resolved_at: new Date().toISOString(),
|
|
190
|
+
source_registry: result._registry,
|
|
191
|
+
});
|
|
192
|
+
if (process.env.DOSSIER_DEBUG) {
|
|
193
|
+
process.stderr.write(`[cache-resolver] '${dossierName}' resolved from registry '${result._registry}' to version ${result.version}\n`);
|
|
194
|
+
}
|
|
195
|
+
return { version: result.version, source: 'registry', registry: result._registry };
|
|
196
|
+
}
|
|
197
|
+
const message = errors.length > 0 ? errors.map((e) => e.error).join('; ') : 'no result';
|
|
198
|
+
registryError = new Error(message);
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
registryError = err;
|
|
202
|
+
}
|
|
203
|
+
// Registry unreachable — try stale fallback.
|
|
204
|
+
const fallback = highestCachedSemver(dossierName);
|
|
205
|
+
const lastKnown = readResolution(dossierName);
|
|
206
|
+
if (fallback) {
|
|
207
|
+
const ageHint = lastKnown
|
|
208
|
+
? ` (last successful check: ${formatAge(Date.now() - new Date(lastKnown.resolved_at).getTime())})`
|
|
209
|
+
: ' (no record of last successful check)';
|
|
210
|
+
const warning = `Registry unreachable — falling back to cached ${dossierName}@${fallback}${ageHint}.\n` +
|
|
211
|
+
` Cause: ${registryError?.message ?? 'unknown'}\n` +
|
|
212
|
+
` This may be stale. To force a fresh check once registry is reachable, re-run with --fresh ` +
|
|
213
|
+
`(or --max-age 0).`;
|
|
214
|
+
process.stderr.write(`⚠️ ${warning}\n`);
|
|
215
|
+
return {
|
|
216
|
+
version: fallback,
|
|
217
|
+
source: 'stale-cache',
|
|
218
|
+
registry: lastKnown?.source_registry,
|
|
219
|
+
warning,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
throw new Error(`Failed to resolve ${dossierName}: registry unreachable and no cached version available.\n` +
|
|
223
|
+
` Underlying error: ${registryError?.message ?? 'unknown'}\n` +
|
|
224
|
+
` Try:\n` +
|
|
225
|
+
` 1. Check network connectivity\n` +
|
|
226
|
+
` 2. Verify registry is configured: dossier config --list-registries\n` +
|
|
227
|
+
` 3. Pin a known-good version: dossier run ${dossierName}@<version>\n` +
|
|
228
|
+
` 4. Re-run with --fresh once the registry is reachable.`);
|
|
229
|
+
}
|
|
230
|
+
/** Exposed for the `cache resolutions` subcommand. */
|
|
231
|
+
function listResolutions() {
|
|
232
|
+
if (!node_fs_1.default.existsSync(exports.RESOLUTION_DIR))
|
|
233
|
+
return [];
|
|
234
|
+
const entries = [];
|
|
235
|
+
function walk(dir, prefix) {
|
|
236
|
+
for (const entry of node_fs_1.default.readdirSync(dir, { withFileTypes: true })) {
|
|
237
|
+
const full = node_path_1.default.join(dir, entry.name);
|
|
238
|
+
if (entry.isDirectory()) {
|
|
239
|
+
walk(full, prefix ? `${prefix}/${entry.name}` : entry.name);
|
|
240
|
+
}
|
|
241
|
+
else if (entry.name.endsWith('.json')) {
|
|
242
|
+
try {
|
|
243
|
+
const record = JSON.parse(node_fs_1.default.readFileSync(full, 'utf8'));
|
|
244
|
+
if (record.resolved_version && record.resolved_at) {
|
|
245
|
+
const name = entry.name.replace(/\.json$/, '');
|
|
246
|
+
entries.push({ name: prefix ? `${prefix}/${name}` : name, record });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
// skip invalid entries
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
walk(exports.RESOLUTION_DIR, '');
|
|
256
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
257
|
+
return entries;
|
|
258
|
+
}
|
|
259
|
+
/** Exposed for tests and the `cache clean` flow — remove all resolution files. */
|
|
260
|
+
function clearResolutions() {
|
|
261
|
+
if (node_fs_1.default.existsSync(exports.RESOLUTION_DIR)) {
|
|
262
|
+
node_fs_1.default.rmSync(exports.RESOLUTION_DIR, { recursive: true, force: true });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Path to a cached dossier's content file (without checking existence).
|
|
267
|
+
* Centralises the `<cache>/<name>/<version>.ds.md` layout used by
|
|
268
|
+
* run/create/install-skill/pull so layout changes happen in one place.
|
|
269
|
+
*/
|
|
270
|
+
function cachedContentPath(dossierName, version) {
|
|
271
|
+
return node_path_1.default.join((0, helpers_1.safeDossierPath)(exports.CACHE_DIR, dossierName), `${version}.ds.md`);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Return cached dossier content as a string, or null if not cached.
|
|
275
|
+
* Single source of truth for the `existsSync(contentFile) ? read : miss`
|
|
276
|
+
* block that previously lived in run.ts, create.ts, and install-skill.ts.
|
|
277
|
+
*/
|
|
278
|
+
function readCachedContent(dossierName, version) {
|
|
279
|
+
const file = cachedContentPath(dossierName, version);
|
|
280
|
+
if (!node_fs_1.default.existsSync(file))
|
|
281
|
+
return null;
|
|
282
|
+
try {
|
|
283
|
+
return node_fs_1.default.readFileSync(file, 'utf8');
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Write a dossier's content + .meta.json to the cache.
|
|
291
|
+
*
|
|
292
|
+
* The .meta.json shape (`cached_at` + `version` + `source_registry`) is the
|
|
293
|
+
* one read by `cache list` / `cache clean` and was previously duplicated
|
|
294
|
+
* verbatim in run.ts, create.ts, install-skill.ts, and pull.ts.
|
|
295
|
+
*
|
|
296
|
+
* Best-effort by default (errors swallowed, matching create.ts/install-skill.ts).
|
|
297
|
+
* Pass `throwOnError: true` for callers that want to surface write failures
|
|
298
|
+
* (pull.ts wants this — a failed download cache write is a hard failure).
|
|
299
|
+
*/
|
|
300
|
+
function writeCachedContent(dossierName, version, content, sourceRegistry, opts = {}) {
|
|
301
|
+
const dir = (0, helpers_1.safeDossierPath)(exports.CACHE_DIR, dossierName);
|
|
302
|
+
try {
|
|
303
|
+
node_fs_1.default.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
304
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(dir, `${version}.ds.md`), content, 'utf8');
|
|
305
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(dir, `${version}.meta.json`), JSON.stringify({
|
|
306
|
+
cached_at: new Date().toISOString(),
|
|
307
|
+
version,
|
|
308
|
+
source_registry: sourceRegistry,
|
|
309
|
+
}, null, 2), 'utf8');
|
|
310
|
+
}
|
|
311
|
+
catch (err) {
|
|
312
|
+
if (opts.throwOnError)
|
|
313
|
+
throw err;
|
|
314
|
+
// best-effort: swallow (matches prior create.ts / install-skill.ts behaviour)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Parse a `--max-age <seconds>` CLI option into a number, or return undefined
|
|
319
|
+
* when unset. Throws when the value is provided but not a valid number.
|
|
320
|
+
* Used by run/create/install-skill which all expose the same flag.
|
|
321
|
+
*/
|
|
322
|
+
function parseMaxAgeOption(raw) {
|
|
323
|
+
if (raw === undefined)
|
|
324
|
+
return undefined;
|
|
325
|
+
const n = Number(raw);
|
|
326
|
+
if (Number.isNaN(n)) {
|
|
327
|
+
throw new Error(`--max-age must be a number (got "${raw}")`);
|
|
328
|
+
}
|
|
329
|
+
return n;
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=cache-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-resolver.js","sourceRoot":"","sources":["../src/cache-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/commands/cache.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/commands/cache.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgU3D"}
|