@ai-dossier/cli 0.83.2 → 0.85.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +31 -6
  2. package/dist/commands/get.d.ts.map +1 -1
  3. package/dist/commands/get.js +1 -0
  4. package/dist/commands/get.js.map +1 -1
  5. package/dist/commands/info.d.ts.map +1 -1
  6. package/dist/commands/info.js +4 -0
  7. package/dist/commands/info.js.map +1 -1
  8. package/dist/commands/publish.d.ts.map +1 -1
  9. package/dist/commands/publish.js +4 -0
  10. package/dist/commands/publish.js.map +1 -1
  11. package/dist/commands/sched.d.ts.map +1 -1
  12. package/dist/commands/sched.js +8 -1
  13. package/dist/commands/sched.js.map +1 -1
  14. package/dist/commands/usage.d.ts +22 -1
  15. package/dist/commands/usage.d.ts.map +1 -1
  16. package/dist/commands/usage.js +202 -17
  17. package/dist/commands/usage.js.map +1 -1
  18. package/dist/helpers.d.ts +7 -0
  19. package/dist/helpers.d.ts.map +1 -1
  20. package/dist/helpers.js +13 -0
  21. package/dist/helpers.js.map +1 -1
  22. package/dist/registry-client.d.ts +6 -0
  23. package/dist/registry-client.d.ts.map +1 -1
  24. package/dist/registry-client.js.map +1 -1
  25. package/dist/sched-run-stats.d.ts +4 -0
  26. package/dist/sched-run-stats.d.ts.map +1 -1
  27. package/dist/sched-run-stats.js +1 -1
  28. package/dist/sched-run-stats.js.map +1 -1
  29. package/dist/usage/batch-prep.d.ts +50 -11
  30. package/dist/usage/batch-prep.d.ts.map +1 -1
  31. package/dist/usage/batch-prep.js +158 -22
  32. package/dist/usage/batch-prep.js.map +1 -1
  33. package/dist/usage/ledger.js +1 -1
  34. package/dist/usage/ledger.js.map +1 -1
  35. package/dist/usage/store.d.ts +110 -0
  36. package/dist/usage/store.d.ts.map +1 -0
  37. package/dist/usage/store.js +445 -0
  38. package/dist/usage/store.js.map +1 -0
  39. package/dist/usage/sync.d.ts +67 -0
  40. package/dist/usage/sync.d.ts.map +1 -0
  41. package/dist/usage/sync.js +223 -0
  42. package/dist/usage/sync.js.map +1 -0
  43. package/dist/usage/types.d.ts +6 -0
  44. package/dist/usage/types.d.ts.map +1 -1
  45. package/package.json +1 -1
@@ -0,0 +1,67 @@
1
+ /**
2
+ * `ai-dossier usage sync` (#782): refresh this host's persisted ledger, then
3
+ * exchange bundles with other hosts over ssh.
4
+ *
5
+ * Transport = the ssh the fleet already relies on (wls is the only host that can
6
+ * reach the others — see scripts/refresh-fleet.sh), streaming the bundle over
7
+ * stdin/stdout: no new secrets, no shared drop, no service. `sync --hosts a,b`
8
+ * is bidirectional so ONE run from wls leaves every host with every host's rows:
9
+ * pull (`ssh a usage export --all`) → merge locally → push (`ssh a usage import -`).
10
+ * The same bundles move by hand with `usage export` / `usage import <file>`.
11
+ */
12
+ import { type CollectOptions, type LedgerPaths } from './ledger';
13
+ import { type ImportResult } from './store';
14
+ /** First-ever sync looks this far back; later ones resume from the ledger's newest row. */
15
+ export declare const DEFAULT_INITIAL_SYNC_MS: number;
16
+ /** Re-collect this far before the cursor: recent rows' attribution (dispatch/prep) can be refined after the fact. */
17
+ export declare const CURSOR_OVERLAP_MS = 86400000;
18
+ export interface RefreshDeps {
19
+ dir?: string;
20
+ paths?: LedgerPaths;
21
+ host?: string;
22
+ nowMs?: number;
23
+ openOpenCode?: CollectOptions['openOpenCode'];
24
+ }
25
+ export interface RefreshResult {
26
+ host: string;
27
+ since: string;
28
+ collected: number;
29
+ added: number;
30
+ updated: number;
31
+ total: number;
32
+ }
33
+ /** Collect this host's stores since the cursor (or `sinceMs`) and upsert them into its ledger file. */
34
+ export declare function refreshLocal(deps?: RefreshDeps, sinceMs?: number): RefreshResult;
35
+ /**
36
+ * Same resolution as refresh-fleet.sh's REMOTE_PRELUDE: a non-login ssh shell has
37
+ * no nvm on PATH, and a repo-local `node_modules/.bin/ai-dossier` can shadow the
38
+ * global install — so source nvm and prefer the global binary explicitly.
39
+ */
40
+ export declare const REMOTE_PRELUDE: string;
41
+ export interface SshResult {
42
+ status: number | null;
43
+ stdout: string;
44
+ stderr: string;
45
+ }
46
+ export type SshRunner = (host: string, script: string, input?: string) => SshResult;
47
+ export declare const defaultSsh: SshRunner;
48
+ export interface RemoteSyncResult {
49
+ host: string;
50
+ ok: boolean;
51
+ error?: string;
52
+ pulled?: ImportResult;
53
+ pushed_rows?: number;
54
+ push?: ImportResult | null;
55
+ }
56
+ export interface SyncOptions {
57
+ hosts: readonly string[];
58
+ /** Override the incremental cursor: exchange rows at or after this time. */
59
+ sinceMs?: number;
60
+ push?: boolean;
61
+ pull?: boolean;
62
+ }
63
+ /** Exchange bundles with each remote. Per-host failures are reported, never thrown. */
64
+ export declare function syncWithRemotes(opts: SyncOptions, deps?: RefreshDeps & {
65
+ ssh?: SshRunner;
66
+ }): RemoteSyncResult[];
67
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/usage/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAE,KAAK,cAAc,EAAqC,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACpG,OAAO,EAEL,KAAK,YAAY,EAQlB,MAAM,SAAS,CAAC;AAMjB,2FAA2F;AAC3F,eAAO,MAAM,uBAAuB,QAAW,CAAC;AAChD,qHAAqH;AACrH,eAAO,MAAM,iBAAiB,WAAM,CAAC;AAErC,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,uGAAuG;AACvG,wBAAgB,YAAY,CAAC,IAAI,GAAE,WAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAuBpF;AAMD;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAKhB,CAAC;AAEZ,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,SAAS,CAAC;AAKpF,eAAO,MAAM,UAAU,EAAE,SAOxB,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5B;AA4BD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,uFAAuF;AACvF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,WAAW,EACjB,IAAI,GAAE,WAAW,GAAG;IAAE,GAAG,CAAC,EAAE,SAAS,CAAA;CAAO,GAC3C,gBAAgB,EAAE,CAwFpB"}
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ /**
3
+ * `ai-dossier usage sync` (#782): refresh this host's persisted ledger, then
4
+ * exchange bundles with other hosts over ssh.
5
+ *
6
+ * Transport = the ssh the fleet already relies on (wls is the only host that can
7
+ * reach the others — see scripts/refresh-fleet.sh), streaming the bundle over
8
+ * stdin/stdout: no new secrets, no shared drop, no service. `sync --hosts a,b`
9
+ * is bidirectional so ONE run from wls leaves every host with every host's rows:
10
+ * pull (`ssh a usage export --all`) → merge locally → push (`ssh a usage import -`).
11
+ * The same bundles move by hand with `usage export` / `usage import <file>`.
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.defaultSsh = exports.REMOTE_PRELUDE = exports.CURSOR_OVERLAP_MS = exports.DEFAULT_INITIAL_SYNC_MS = void 0;
48
+ exports.refreshLocal = refreshLocal;
49
+ exports.syncWithRemotes = syncWithRemotes;
50
+ const node_child_process_1 = require("node:child_process");
51
+ const fs = __importStar(require("node:fs"));
52
+ const path = __importStar(require("node:path"));
53
+ const ledger_1 = require("./ledger");
54
+ const store_1 = require("./store");
55
+ const DAY = 86_400_000;
56
+ // Limit: `sync` re-collects only CURSOR_OVERLAP_MS before its cursor, so an attribution change
57
+ // (dispatch/prep join) to a row older than that is not re-persisted or re-sent; run
58
+ // `usage sync --since <older>` to force a wider refresh.
59
+ /** First-ever sync looks this far back; later ones resume from the ledger's newest row. */
60
+ exports.DEFAULT_INITIAL_SYNC_MS = 30 * DAY;
61
+ /** Re-collect this far before the cursor: recent rows' attribution (dispatch/prep) can be refined after the fact. */
62
+ exports.CURSOR_OVERLAP_MS = DAY;
63
+ /** Collect this host's stores since the cursor (or `sinceMs`) and upsert them into its ledger file. */
64
+ function refreshLocal(deps = {}, sinceMs) {
65
+ const dir = deps.dir ?? (0, store_1.usageStoreDir)();
66
+ const host = deps.host ?? (0, store_1.localHostId)();
67
+ const nowMs = deps.nowMs ?? Date.now();
68
+ const cursor = (0, store_1.newestTs)(dir, host);
69
+ const since = sinceMs ?? (cursor !== null ? cursor - exports.CURSOR_OVERLAP_MS : nowMs - exports.DEFAULT_INITIAL_SYNC_MS);
70
+ const ledger = (0, ledger_1.collectLedger)({
71
+ sinceMs: since,
72
+ untilMs: nowMs,
73
+ paths: deps.paths ?? (0, ledger_1.defaultLedgerPaths)(),
74
+ host,
75
+ openOpenCode: deps.openOpenCode,
76
+ });
77
+ const stats = (0, store_1.persistLocal)(dir, host, ledger.rows, ledger.limits);
78
+ return {
79
+ host,
80
+ since: new Date(since).toISOString(),
81
+ collected: ledger.rows.length,
82
+ added: stats.added,
83
+ updated: stats.updated,
84
+ total: stats.total,
85
+ };
86
+ }
87
+ // ---------------------------------------------------------------------------
88
+ // ssh transport
89
+ // ---------------------------------------------------------------------------
90
+ /**
91
+ * Same resolution as refresh-fleet.sh's REMOTE_PRELUDE: a non-login ssh shell has
92
+ * no nvm on PATH, and a repo-local `node_modules/.bin/ai-dossier` can shadow the
93
+ * global install — so source nvm and prefer the global binary explicitly.
94
+ */
95
+ exports.REMOTE_PRELUDE = [
96
+ 'export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" >/dev/null 2>&1;',
97
+ 'AD="$(npm root -g 2>/dev/null)/@ai-dossier/cli/bin/ai-dossier";',
98
+ '[ -x "$AD" ] || AD="$(command -v ai-dossier || true)";',
99
+ '[ -n "$AD" ] || { echo "no ai-dossier binary found" >&2; exit 90; };',
100
+ ].join(' ');
101
+ /** A remote that hangs mid-transfer must not wedge a fleet sync (ConnectTimeout only covers connecting). */
102
+ const SSH_TIMEOUT_MS = 10 * 60 * 1000;
103
+ const defaultSsh = (host, script, input) => {
104
+ const r = (0, node_child_process_1.spawnSync)('ssh', ['-o', 'BatchMode=yes', '-o', 'ConnectTimeout=10', host, `${exports.REMOTE_PRELUDE}\n${script}`], { input, encoding: 'utf-8', maxBuffer: 1024 * 1024 * 1024, timeout: SSH_TIMEOUT_MS });
105
+ return { status: r.status, stdout: r.stdout ?? '', stderr: r.stderr ?? r.error?.message ?? '' };
106
+ };
107
+ exports.defaultSsh = defaultSsh;
108
+ function readState(dir) {
109
+ try {
110
+ const s = JSON.parse(fs.readFileSync(path.join(dir, 'sync-state.json'), 'utf-8'));
111
+ if (!s || typeof s.remotes !== 'object' || !s.remotes)
112
+ return { remotes: {} };
113
+ // Legacy/garbled entries reset to a full initial window rather than being trusted.
114
+ for (const [h, v] of Object.entries(s.remotes))
115
+ if (!v || typeof v !== 'object')
116
+ delete s.remotes[h];
117
+ return s;
118
+ }
119
+ catch {
120
+ return { remotes: {} };
121
+ }
122
+ }
123
+ function writeState(dir, state) {
124
+ fs.mkdirSync(dir, { recursive: true });
125
+ const file = path.join(dir, 'sync-state.json');
126
+ const tmp = `${file}.${process.pid}.tmp`;
127
+ fs.writeFileSync(tmp, `${JSON.stringify(state, null, 2)}\n`);
128
+ fs.renameSync(tmp, file);
129
+ }
130
+ /** Exchange bundles with each remote. Per-host failures are reported, never thrown. */
131
+ function syncWithRemotes(opts, deps = {}) {
132
+ const dir = deps.dir ?? (0, store_1.usageStoreDir)();
133
+ const local = deps.host ?? (0, store_1.localHostId)();
134
+ const nowMs = deps.nowMs ?? Date.now();
135
+ const ssh = deps.ssh ?? exports.defaultSsh;
136
+ const state = readState(dir);
137
+ const results = new Map();
138
+ const initial = nowMs - exports.DEFAULT_INITIAL_SYNC_MS;
139
+ const cursorOf = (host, dir_) => {
140
+ if (opts.sinceMs !== undefined)
141
+ return opts.sinceMs;
142
+ const iso = state.remotes[host]?.[dir_];
143
+ const t = iso ? Date.parse(iso) : Number.NaN;
144
+ return Number.isNaN(t) ? initial : t - exports.CURSOR_OVERLAP_MS;
145
+ };
146
+ const tail = (t) => t.trim().split('\n').slice(-2).join(' | ');
147
+ const valid = [];
148
+ for (const host of opts.hosts) {
149
+ if ((0, store_1.isValidHostId)(host))
150
+ valid.push(host);
151
+ else
152
+ results.set(host, { host, ok: false, error: 'invalid host name' });
153
+ }
154
+ // Pass 1 — pull from EVERY host first, so pass 2 pushes each host what all the others hold.
155
+ const pulledSince = [];
156
+ const pullOk = new Set();
157
+ for (const host of valid) {
158
+ const res = { host, ok: true };
159
+ results.set(host, res);
160
+ if (opts.pull === false)
161
+ continue;
162
+ const since = cursorOf(host, 'pull');
163
+ const out = ssh(host, `"$AD" usage export --all --since '${new Date(since).toISOString()}'`);
164
+ if (out.status !== 0) {
165
+ Object.assign(res, {
166
+ ok: false,
167
+ error: `pull failed (exit ${out.status}): ${tail(out.stderr)}`,
168
+ });
169
+ continue;
170
+ }
171
+ try {
172
+ res.pulled = (0, store_1.importBundle)(dir, out.stdout, local);
173
+ pulledSince.push(since);
174
+ pullOk.add(host);
175
+ }
176
+ catch (err) {
177
+ Object.assign(res, { ok: false, error: `pull import failed: ${err.message}` });
178
+ }
179
+ }
180
+ // Pass 2 — push everything except the target's own rows. Rows pulled this run may be OLDER
181
+ // than the target's push cursor (a host that was down, or a first pull), so reach back to the
182
+ // earliest pull window as well — otherwise those rows would never reach the other hosts.
183
+ const pushOk = new Set();
184
+ for (const host of valid) {
185
+ const res = results.get(host);
186
+ if (!res.ok || opts.push === false)
187
+ continue;
188
+ const since = Math.min(cursorOf(host, 'push'), ...pulledSince);
189
+ const bundle = (0, store_1.buildBundle)(dir, local,
190
+ // The alias and the host's self-reported id can differ (ssh config vs os.hostname()).
191
+ (0, store_1.listHosts)(dir).filter((h) => h !== host && h !== results.get(host)?.pulled?.from), since);
192
+ res.pushed_rows = bundle.rows;
193
+ const out = ssh(host, '"$AD" usage import - --json', bundle.text);
194
+ if (out.status !== 0) {
195
+ Object.assign(res, {
196
+ ok: false,
197
+ error: `push failed (exit ${out.status}): ${tail(out.stderr)}`,
198
+ });
199
+ continue;
200
+ }
201
+ pushOk.add(host);
202
+ try {
203
+ res.push = JSON.parse(out.stdout.trim().split('\n').pop() ?? 'null');
204
+ }
205
+ catch {
206
+ res.push = null;
207
+ }
208
+ }
209
+ // Advance only the direction that actually ran and succeeded.
210
+ const stamp = new Date(nowMs).toISOString();
211
+ for (const host of valid) {
212
+ const entry = state.remotes[host] ?? {};
213
+ if (pullOk.has(host))
214
+ entry.pull = stamp;
215
+ if (pushOk.has(host))
216
+ entry.push = stamp;
217
+ if (entry.pull || entry.push)
218
+ state.remotes[host] = entry;
219
+ }
220
+ writeState(dir, state);
221
+ return opts.hosts.map((h) => results.get(h));
222
+ }
223
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/usage/sync.ts"],"names":[],"mappings":"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"}
@@ -44,7 +44,13 @@ export interface UsageRow {
44
44
  unit: string | null;
45
45
  /** `prep` when the row is batch-prep spend attributed to `batch` by enqueue-time session capture (#796). */
46
46
  role?: 'prep';
47
+ /** For `role: 'prep'`: how the attributing window's start was found (#899). */
48
+ prep_basis?: PrepBasis;
49
+ /** For `role: 'prep'`: how many sibling batches (one enqueue) this row's window was split across, when > 1. */
50
+ prep_split?: number;
47
51
  }
52
+ /** `marker` = the session's first batch-issues-preparation run; `prev-enqueue` / `lookback-cap` = upper bounds. */
53
+ export type PrepBasis = 'marker' | 'prev-enqueue' | 'lookback-cap';
48
54
  /** A provider limit / rate-limit wall observed in a source store. */
49
55
  export interface LimitEvent {
50
56
  ts: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/usage/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,UAAU,CAAC;AAErD,oHAAoH;AACpH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE3D,MAAM,WAAW,QAAQ;IACvB,iGAAiG;IACjG,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,4GAA4G;IAC5G,QAAQ,EAAE,MAAM,CAAC;IACjB,2FAA2F;IAC3F,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,sGAAsG;IACtG,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;IACnB,oHAAoH;IACpH,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,wGAAwG;IACxG,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,wFAAwF;IACxF,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,4GAA4G;IAC5G,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qEAAqE;AACrE,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC;IAChC,uFAAuF;IACvF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,0DAA0D;IAC1D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,mHAAmH;IACnH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,6GAA6G;AAC7G,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,IAAI,GAAG,aAAa,GAAG,OAAO,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,+CAA+C;AAC/C,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,qGAAqG;IACrG,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/usage/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,UAAU,CAAC;AAErD,oHAAoH;AACpH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE3D,MAAM,WAAW,QAAQ;IACvB,iGAAiG;IACjG,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,4GAA4G;IAC5G,QAAQ,EAAE,MAAM,CAAC;IACjB,2FAA2F;IAC3F,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,sGAAsG;IACtG,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;IACnB,oHAAoH;IACpH,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,wGAAwG;IACxG,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,wFAAwF;IACxF,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,4GAA4G;IAC5G,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,+GAA+G;IAC/G,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,mHAAmH;AACnH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,cAAc,GAAG,cAAc,CAAC;AAEnE,qEAAqE;AACrE,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC;IAChC,uFAAuF;IACvF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,0DAA0D;IAC1D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,mHAAmH;IACnH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,6GAA6G;AAC7G,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,IAAI,GAAG,aAAa,GAAG,OAAO,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,+CAA+C;AAC/C,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,qGAAqG;IACrG,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-dossier/cli",
3
- "version": "0.83.2",
3
+ "version": "0.85.0",
4
4
  "description": "Create, verify, sign, publish, and run dossiers — portable, signed, versioned skills for any LLM tool. The dossier ⇄ Claude Code skill bridge (install-skill / skill-export).",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {