auden 0.1.0-alpha.2
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/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/auden-paths.d.ts +8 -0
- package/dist/auden-paths.d.ts.map +1 -0
- package/dist/auden-paths.js +10 -0
- package/dist/auden-paths.js.map +1 -0
- package/dist/bin.d.ts +11 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +13 -0
- package/dist/bin.js.map +1 -0
- package/dist/chunk.d.ts +3 -0
- package/dist/chunk.d.ts.map +1 -0
- package/dist/chunk.js +13 -0
- package/dist/chunk.js.map +1 -0
- package/dist/commands/doctor.d.ts +13 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +125 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/eval/index.d.ts +2 -0
- package/dist/commands/eval/index.d.ts.map +1 -0
- package/dist/commands/eval/index.js +2 -0
- package/dist/commands/eval/index.js.map +1 -0
- package/dist/commands/eval/run.d.ts +38 -0
- package/dist/commands/eval/run.d.ts.map +1 -0
- package/dist/commands/eval/run.js +179 -0
- package/dist/commands/eval/run.js.map +1 -0
- package/dist/commands/guides/active.d.ts +2 -0
- package/dist/commands/guides/active.d.ts.map +1 -0
- package/dist/commands/guides/active.js +38 -0
- package/dist/commands/guides/active.js.map +1 -0
- package/dist/commands/guides/index.d.ts +2 -0
- package/dist/commands/guides/index.d.ts.map +1 -0
- package/dist/commands/guides/index.js +13 -0
- package/dist/commands/guides/index.js.map +1 -0
- package/dist/commands/guides/project.d.ts +13 -0
- package/dist/commands/guides/project.d.ts.map +1 -0
- package/dist/commands/guides/project.js +71 -0
- package/dist/commands/guides/project.js.map +1 -0
- package/dist/commands/guides/search.d.ts +8 -0
- package/dist/commands/guides/search.d.ts.map +1 -0
- package/dist/commands/guides/search.js +46 -0
- package/dist/commands/guides/search.js.map +1 -0
- package/dist/commands/init.d.ts +43 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +436 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mcp.d.ts +23 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +55 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/pull.d.ts +38 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +127 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/rules/export.d.ts +140 -0
- package/dist/commands/rules/export.d.ts.map +1 -0
- package/dist/commands/rules/export.js +635 -0
- package/dist/commands/rules/export.js.map +1 -0
- package/dist/commands/rules/import.d.ts +33 -0
- package/dist/commands/rules/import.d.ts.map +1 -0
- package/dist/commands/rules/import.js +122 -0
- package/dist/commands/rules/import.js.map +1 -0
- package/dist/commands/rules/index.d.ts +2 -0
- package/dist/commands/rules/index.d.ts.map +1 -0
- package/dist/commands/rules/index.js +13 -0
- package/dist/commands/rules/index.js.map +1 -0
- package/dist/commands/rules/watch.d.ts +43 -0
- package/dist/commands/rules/watch.d.ts.map +1 -0
- package/dist/commands/rules/watch.js +125 -0
- package/dist/commands/rules/watch.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +61 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/suggest.d.ts +8 -0
- package/dist/commands/suggest.d.ts.map +1 -0
- package/dist/commands/suggest.js +43 -0
- package/dist/commands/suggest.js.map +1 -0
- package/dist/commands/sync.d.ts +23 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +193 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/verdict/index.d.ts +2 -0
- package/dist/commands/verdict/index.d.ts.map +1 -0
- package/dist/commands/verdict/index.js +11 -0
- package/dist/commands/verdict/index.js.map +1 -0
- package/dist/commands/verdict/record.d.ts +18 -0
- package/dist/commands/verdict/record.d.ts.map +1 -0
- package/dist/commands/verdict/record.js +60 -0
- package/dist/commands/verdict/record.js.map +1 -0
- package/dist/config.d.ts +96 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +246 -0
- package/dist/config.js.map +1 -0
- package/dist/context/pull.d.ts +40 -0
- package/dist/context/pull.d.ts.map +1 -0
- package/dist/context/pull.js +46 -0
- package/dist/context/pull.js.map +1 -0
- package/dist/dashboard-health.d.ts +20 -0
- package/dist/dashboard-health.d.ts.map +1 -0
- package/dist/dashboard-health.js +24 -0
- package/dist/dashboard-health.js.map +1 -0
- package/dist/eval-provider.d.ts +30 -0
- package/dist/eval-provider.d.ts.map +1 -0
- package/dist/eval-provider.js +359 -0
- package/dist/eval-provider.js.map +1 -0
- package/dist/eval-summary.d.ts +24 -0
- package/dist/eval-summary.d.ts.map +1 -0
- package/dist/eval-summary.js +30 -0
- package/dist/eval-summary.js.map +1 -0
- package/dist/feedback/extract.d.ts +6 -0
- package/dist/feedback/extract.d.ts.map +1 -0
- package/dist/feedback/extract.js +580 -0
- package/dist/feedback/extract.js.map +1 -0
- package/dist/http-retry.d.ts +23 -0
- package/dist/http-retry.d.ts.map +1 -0
- package/dist/http-retry.js +54 -0
- package/dist/http-retry.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +70 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +121 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/scope.d.ts +30 -0
- package/dist/mcp/scope.d.ts.map +1 -0
- package/dist/mcp/scope.js +64 -0
- package/dist/mcp/scope.js.map +1 -0
- package/dist/mcp/server.d.ts +57 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +427 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/write-items.d.ts +34 -0
- package/dist/mcp/write-items.d.ts.map +1 -0
- package/dist/mcp/write-items.js +59 -0
- package/dist/mcp/write-items.js.map +1 -0
- package/dist/rules/deletions-client.d.ts +16 -0
- package/dist/rules/deletions-client.d.ts.map +1 -0
- package/dist/rules/deletions-client.js +40 -0
- package/dist/rules/deletions-client.js.map +1 -0
- package/dist/rules/diff.d.ts +19 -0
- package/dist/rules/diff.d.ts.map +1 -0
- package/dist/rules/diff.js +36 -0
- package/dist/rules/diff.js.map +1 -0
- package/dist/rules/discover.d.ts +81 -0
- package/dist/rules/discover.d.ts.map +1 -0
- package/dist/rules/discover.js +307 -0
- package/dist/rules/discover.js.map +1 -0
- package/dist/rules/file-origin.d.ts +16 -0
- package/dist/rules/file-origin.d.ts.map +1 -0
- package/dist/rules/file-origin.js +31 -0
- package/dist/rules/file-origin.js.map +1 -0
- package/dist/rules/global-flag.d.ts +12 -0
- package/dist/rules/global-flag.d.ts.map +1 -0
- package/dist/rules/global-flag.js +15 -0
- package/dist/rules/global-flag.js.map +1 -0
- package/dist/rules/import-client.d.ts +37 -0
- package/dist/rules/import-client.d.ts.map +1 -0
- package/dist/rules/import-client.js +98 -0
- package/dist/rules/import-client.js.map +1 -0
- package/dist/rules/init-pull.d.ts +34 -0
- package/dist/rules/init-pull.d.ts.map +1 -0
- package/dist/rules/init-pull.js +43 -0
- package/dist/rules/init-pull.js.map +1 -0
- package/dist/rules/member-files-client.d.ts +17 -0
- package/dist/rules/member-files-client.d.ts.map +1 -0
- package/dist/rules/member-files-client.js +29 -0
- package/dist/rules/member-files-client.js.map +1 -0
- package/dist/rules/path-contains.d.ts +9 -0
- package/dist/rules/path-contains.d.ts.map +1 -0
- package/dist/rules/path-contains.js +17 -0
- package/dist/rules/path-contains.js.map +1 -0
- package/dist/rules/payload.d.ts +13 -0
- package/dist/rules/payload.d.ts.map +1 -0
- package/dist/rules/payload.js +35 -0
- package/dist/rules/payload.js.map +1 -0
- package/dist/rules/pull-bundle.d.ts +13 -0
- package/dist/rules/pull-bundle.d.ts.map +1 -0
- package/dist/rules/pull-bundle.js +32 -0
- package/dist/rules/pull-bundle.js.map +1 -0
- package/dist/rules/watch.d.ts +121 -0
- package/dist/rules/watch.d.ts.map +1 -0
- package/dist/rules/watch.js +457 -0
- package/dist/rules/watch.js.map +1 -0
- package/dist/skill-template.d.ts +19 -0
- package/dist/skill-template.d.ts.map +1 -0
- package/dist/skill-template.js +174 -0
- package/dist/skill-template.js.map +1 -0
- package/dist/sync-batches.d.ts +37 -0
- package/dist/sync-batches.d.ts.map +1 -0
- package/dist/sync-batches.js +67 -0
- package/dist/sync-batches.js.map +1 -0
- package/dist/sync-client.d.ts +22 -0
- package/dist/sync-client.d.ts.map +1 -0
- package/dist/sync-client.js +38 -0
- package/dist/sync-client.js.map +1 -0
- package/dist/sync-response.d.ts +23 -0
- package/dist/sync-response.d.ts.map +1 -0
- package/dist/sync-response.js +22 -0
- package/dist/sync-response.js.map +1 -0
- package/dist/token-verify.d.ts +14 -0
- package/dist/token-verify.d.ts.map +1 -0
- package/dist/token-verify.js +30 -0
- package/dist/token-verify.js.map +1 -0
- package/dist/usage/extract.d.ts +31 -0
- package/dist/usage/extract.d.ts.map +1 -0
- package/dist/usage/extract.js +200 -0
- package/dist/usage/extract.js.map +1 -0
- package/dist/usage/providers.d.ts +8 -0
- package/dist/usage/providers.d.ts.map +1 -0
- package/dist/usage/providers.js +23 -0
- package/dist/usage/providers.js.map +1 -0
- package/dist/verdict-queue.d.ts +50 -0
- package/dist/verdict-queue.d.ts.map +1 -0
- package/dist/verdict-queue.js +131 -0
- package/dist/verdict-queue.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { MAX_RULES_IMPORT_BATCH } from '@auden.to/protocol';
|
|
2
|
+
import * as v from 'valibot';
|
|
3
|
+
const NonNegativeIntSchema = v.pipe(v.number(), v.integer(), v.minValue(0));
|
|
4
|
+
// Present only when at least one payload in the batch carried a skill
|
|
5
|
+
// `members` array (older servers omit it entirely).
|
|
6
|
+
const MemberSyncSchema = v.object({
|
|
7
|
+
added: NonNegativeIntSchema,
|
|
8
|
+
updated: NonNegativeIntSchema,
|
|
9
|
+
removed: NonNegativeIntSchema,
|
|
10
|
+
unchanged: NonNegativeIntSchema,
|
|
11
|
+
});
|
|
12
|
+
const ImportSuccessSchema = v.object({
|
|
13
|
+
imported: NonNegativeIntSchema,
|
|
14
|
+
skipped: NonNegativeIntSchema,
|
|
15
|
+
members: v.optional(MemberSyncSchema),
|
|
16
|
+
});
|
|
17
|
+
function trimTrailingSlashes(url) {
|
|
18
|
+
return url.replace(/\/+$/, '');
|
|
19
|
+
}
|
|
20
|
+
// Flush a batch before its serialized body reaches this size. The server's
|
|
21
|
+
// request middleware caps /api/rules/import bodies at 64 MiB (sized for
|
|
22
|
+
// member-less payloads); skill payloads carry member files, so a
|
|
23
|
+
// count-only chunking of 100 large skills could exceed it. Half the cap
|
|
24
|
+
// leaves ample headroom for JSON envelope overhead.
|
|
25
|
+
const MAX_BATCH_BODY_BYTES = 32 * 1024 * 1024;
|
|
26
|
+
/**
|
|
27
|
+
* Split payloads into consecutive batches bounded by both count
|
|
28
|
+
* (`MAX_RULES_IMPORT_BATCH`) and approximate serialized size. A single
|
|
29
|
+
* payload larger than the byte budget still ships alone — the server's
|
|
30
|
+
* per-field caps are the authority on whether it is acceptable.
|
|
31
|
+
*/
|
|
32
|
+
export function chunkRulePayloads(rules) {
|
|
33
|
+
const batches = [];
|
|
34
|
+
let batch = [];
|
|
35
|
+
let batchBytes = 0;
|
|
36
|
+
for (const rule of rules) {
|
|
37
|
+
// Real UTF-8 bytes, not string length — multi-byte content (CJK, Cyrillic)
|
|
38
|
+
// serializes up to 3x larger than its UTF-16 code-unit count, and the
|
|
39
|
+
// server cap this budget protects is a Content-Length byte cap.
|
|
40
|
+
const ruleBytes = Buffer.byteLength(JSON.stringify(rule), 'utf8');
|
|
41
|
+
if (batch.length > 0 &&
|
|
42
|
+
(batch.length >= MAX_RULES_IMPORT_BATCH ||
|
|
43
|
+
batchBytes + ruleBytes > MAX_BATCH_BODY_BYTES)) {
|
|
44
|
+
batches.push(batch);
|
|
45
|
+
batch = [];
|
|
46
|
+
batchBytes = 0;
|
|
47
|
+
}
|
|
48
|
+
batch.push(rule);
|
|
49
|
+
batchBytes += ruleBytes;
|
|
50
|
+
}
|
|
51
|
+
if (batch.length > 0)
|
|
52
|
+
batches.push(batch);
|
|
53
|
+
return batches;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* POST `RawGuideFilePayload`s to the dashboard import endpoint, chunked to
|
|
57
|
+
* stay under the server's `MAX_RULES_IMPORT_BATCH` per-request cap and its
|
|
58
|
+
* request-body byte cap, and sum the parsed results. Throws on transport
|
|
59
|
+
* errors, non-2xx responses, or malformed bodies. Empty `rules` is rejected
|
|
60
|
+
* here so the CLI never sends a useless request.
|
|
61
|
+
*/
|
|
62
|
+
export async function importRules(options) {
|
|
63
|
+
if (options.rules.length === 0) {
|
|
64
|
+
throw new Error('importRules: rules array must not be empty');
|
|
65
|
+
}
|
|
66
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
67
|
+
const url = `${trimTrailingSlashes(options.dashboardUrl)}/api/rules/import`;
|
|
68
|
+
let imported = 0;
|
|
69
|
+
let skipped = 0;
|
|
70
|
+
let members;
|
|
71
|
+
for (const batch of chunkRulePayloads(options.rules)) {
|
|
72
|
+
const response = await fetchImpl(url, {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers: {
|
|
75
|
+
Authorization: `Bearer ${options.token}`,
|
|
76
|
+
'Content-Type': 'application/json',
|
|
77
|
+
},
|
|
78
|
+
body: JSON.stringify({ rules: batch }),
|
|
79
|
+
});
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
const text = await response.text().catch(() => '');
|
|
82
|
+
throw new Error(`Import failed with ${response.status}${text ? `: ${text}` : ''}`);
|
|
83
|
+
}
|
|
84
|
+
const json = (await response.json());
|
|
85
|
+
const result = v.parse(ImportSuccessSchema, json);
|
|
86
|
+
imported += result.imported;
|
|
87
|
+
skipped += result.skipped;
|
|
88
|
+
if (result.members) {
|
|
89
|
+
members = members ?? { added: 0, updated: 0, removed: 0, unchanged: 0 };
|
|
90
|
+
members.added += result.members.added;
|
|
91
|
+
members.updated += result.members.updated;
|
|
92
|
+
members.removed += result.members.removed;
|
|
93
|
+
members.unchanged += result.members.unchanged;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return members ? { imported, skipped, members } : { imported, skipped };
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=import-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-client.js","sourceRoot":"","sources":["../../src/rules/import-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ExportPrompts, ExportRulesWithPullResult } from '../commands/rules/export.js';
|
|
2
|
+
import type { GuideFileFormat } from '@auden.to/protocol';
|
|
3
|
+
export type PullGuidesIntoRepoOptions = {
|
|
4
|
+
cwd: string;
|
|
5
|
+
dashboardUrl: string;
|
|
6
|
+
token: string;
|
|
7
|
+
/** Formats to restore. Defaults to all supported formats so a fresh repo
|
|
8
|
+
* gets the user's full setup back in whatever format each guide came from. */
|
|
9
|
+
formats?: ReadonlyArray<GuideFileFormat>;
|
|
10
|
+
/** Override the cached bundle path (defaults to ~/.auden/guides.json). */
|
|
11
|
+
bundlePath?: string;
|
|
12
|
+
/** Skip every confirmation, overwrites included. */
|
|
13
|
+
yes?: boolean;
|
|
14
|
+
/** Custom prompts (tests / non-stdin callers). Defaults to: NEW files
|
|
15
|
+
* auto-confirmed (the caller already asked), OVERWRITE per-file with diff. */
|
|
16
|
+
prompts?: ExportPrompts;
|
|
17
|
+
/** Apply ANSI colors when rendering overwrite diffs. */
|
|
18
|
+
color?: boolean;
|
|
19
|
+
fetchFn?: typeof fetch;
|
|
20
|
+
onPull?: (count: number, target: string) => void;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Pull the user's active guide bundle from the dashboard and write it into a
|
|
24
|
+
* repo — the cross-machine / fresh-repo restore path `auden init` offers so a
|
|
25
|
+
* brand-new project starts with the user's accumulated setup rather than cold.
|
|
26
|
+
*
|
|
27
|
+
* Always pulls a fresh bundle (mode 'always'): init runs once at setup time, so
|
|
28
|
+
* the local cache may be stale or absent. The caller is expected to have already
|
|
29
|
+
* confirmed intent ("pull your guides into this repo?"), so brand-new files are
|
|
30
|
+
* written without a second bulk confirm; existing files still get a per-file
|
|
31
|
+
* diff confirmation so re-running init never silently clobbers local edits.
|
|
32
|
+
*/
|
|
33
|
+
export declare function pullGuidesIntoRepo(opts: PullGuidesIntoRepoOptions): Promise<ExportRulesWithPullResult>;
|
|
34
|
+
//# sourceMappingURL=init-pull.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-pull.d.ts","sourceRoot":"","sources":["../../src/rules/init-pull.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,aAAa,EAEb,yBAAyB,EAC1B,MAAM,6BAA6B,CAAA;AACpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEzD,MAAM,MAAM,yBAAyB,GAAG;IACtC,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb;mFAC+E;IAC/E,OAAO,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAA;IACxC,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oDAAoD;IACpD,GAAG,CAAC,EAAE,OAAO,CAAA;IACb;mFAC+E;IAC/E,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;IACtB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CACjD,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,yBAAyB,CAAC,CA4BpC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AUDEN_GUIDES_FILE } from '../auden-paths.js';
|
|
2
|
+
import { ALL_FORMATS, makeStdinPrompts, runRulesExportWithPull, } from '../commands/rules/export.js';
|
|
3
|
+
import { BUNDLED_SKILLS } from '../skill-template.js';
|
|
4
|
+
/**
|
|
5
|
+
* Pull the user's active guide bundle from the dashboard and write it into a
|
|
6
|
+
* repo — the cross-machine / fresh-repo restore path `auden init` offers so a
|
|
7
|
+
* brand-new project starts with the user's accumulated setup rather than cold.
|
|
8
|
+
*
|
|
9
|
+
* Always pulls a fresh bundle (mode 'always'): init runs once at setup time, so
|
|
10
|
+
* the local cache may be stale or absent. The caller is expected to have already
|
|
11
|
+
* confirmed intent ("pull your guides into this repo?"), so brand-new files are
|
|
12
|
+
* written without a second bulk confirm; existing files still get a per-file
|
|
13
|
+
* diff confirmation so re-running init never silently clobbers local edits.
|
|
14
|
+
*/
|
|
15
|
+
export async function pullGuidesIntoRepo(opts) {
|
|
16
|
+
const prompts = opts.prompts ?? {
|
|
17
|
+
...makeStdinPrompts(),
|
|
18
|
+
confirmNewFiles: async () => true,
|
|
19
|
+
};
|
|
20
|
+
const exportArgs = {
|
|
21
|
+
cwd: opts.cwd,
|
|
22
|
+
format: opts.formats ?? ALL_FORMATS,
|
|
23
|
+
bundlePath: opts.bundlePath ?? AUDEN_GUIDES_FILE,
|
|
24
|
+
yes: opts.yes ?? false,
|
|
25
|
+
write: true,
|
|
26
|
+
color: opts.color ?? false,
|
|
27
|
+
prompts,
|
|
28
|
+
// init's own skill step just wrote (or deliberately kept) these — a stale
|
|
29
|
+
// dashboard copy imported on some other machine must not offer to clobber
|
|
30
|
+
// the fresh install one step later.
|
|
31
|
+
excludePathPrefixes: BUNDLED_SKILLS.map((skill) => `.claude/skills/${skill.name}/`),
|
|
32
|
+
pull: {
|
|
33
|
+
mode: 'always',
|
|
34
|
+
dashboardUrl: opts.dashboardUrl,
|
|
35
|
+
token: opts.token,
|
|
36
|
+
...(opts.fetchFn ? { fetchFn: opts.fetchFn } : {}),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
if (opts.onPull)
|
|
40
|
+
exportArgs.onPull = opts.onPull;
|
|
41
|
+
return runRulesExportWithPull(exportArgs);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=init-pull.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-pull.js","sourceRoot":"","sources":["../../src/rules/init-pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AA6BrD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAA+B;IAE/B,MAAM,OAAO,GAAkB,IAAI,CAAC,OAAO,IAAI;QAC7C,GAAG,gBAAgB,EAAE;QACrB,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;KAClC,CAAA;IAED,MAAM,UAAU,GAA4B;QAC1C,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,MAAM,EAAE,IAAI,CAAC,OAAO,IAAI,WAAW;QACnC,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,iBAAiB;QAChD,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,KAAK;QACtB,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,KAAK;QAC1B,OAAO;QACP,0EAA0E;QAC1E,0EAA0E;QAC1E,oCAAoC;QACpC,mBAAmB,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,KAAK,CAAC,IAAI,GAAG,CAAC;QACnF,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD;KACF,CAAA;IACD,IAAI,IAAI,CAAC,MAAM;QAAE,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;IAEhD,OAAO,sBAAsB,CAAC,UAAU,CAAC,CAAA;AAC3C,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GuideMemberFile } from '@auden.to/protocol';
|
|
2
|
+
export type FetchGuideMemberFilesOptions = {
|
|
3
|
+
dashboardUrl: string;
|
|
4
|
+
token: string;
|
|
5
|
+
guideId: string;
|
|
6
|
+
/** Override fetch for tests. Defaults to globalThis.fetch. */
|
|
7
|
+
fetchImpl?: typeof fetch;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Fetch a skill guide's member files from the dashboard — the export
|
|
11
|
+
* round-trip's read side. Member bodies are deliberately not part of the
|
|
12
|
+
* cached guide bundle (the eval hot path pulls that every session), so this
|
|
13
|
+
* is a lazy per-guide call made only when exporting `skill-md` guides.
|
|
14
|
+
* Throws on transport errors, non-2xx responses, or malformed bodies.
|
|
15
|
+
*/
|
|
16
|
+
export declare function fetchGuideMemberFiles(options: FetchGuideMemberFilesOptions): Promise<GuideMemberFile[]>;
|
|
17
|
+
//# sourceMappingURL=member-files-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"member-files-client.d.ts","sourceRoot":"","sources":["../../src/rules/member-files-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEzD,MAAM,MAAM,4BAA4B,GAAG;IACzC,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,8DAA8D;IAC9D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB,CAAA;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,eAAe,EAAE,CAAC,CAsB5B"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { parseGuideMemberFilesResponse } from '@auden.to/protocol';
|
|
2
|
+
/**
|
|
3
|
+
* Fetch a skill guide's member files from the dashboard — the export
|
|
4
|
+
* round-trip's read side. Member bodies are deliberately not part of the
|
|
5
|
+
* cached guide bundle (the eval hot path pulls that every session), so this
|
|
6
|
+
* is a lazy per-guide call made only when exporting `skill-md` guides.
|
|
7
|
+
* Throws on transport errors, non-2xx responses, or malformed bodies.
|
|
8
|
+
*/
|
|
9
|
+
export async function fetchGuideMemberFiles(options) {
|
|
10
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
11
|
+
const base = options.dashboardUrl.replace(/\/+$/, '');
|
|
12
|
+
const url = `${base}/api/v1/guides/${encodeURIComponent(options.guideId)}/member-files`;
|
|
13
|
+
const response = await fetchImpl(url, {
|
|
14
|
+
headers: { Authorization: `Bearer ${options.token}` },
|
|
15
|
+
});
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
const detail = await response.text().catch(() => '');
|
|
18
|
+
throw new Error(`Member-file fetch failed with ${response.status}${detail ? `: ${detail}` : ''}`);
|
|
19
|
+
}
|
|
20
|
+
let payload;
|
|
21
|
+
try {
|
|
22
|
+
payload = await response.json();
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
throw new Error('Member-file response was not valid JSON.');
|
|
26
|
+
}
|
|
27
|
+
return parseGuideMemberFilesResponse(payload).memberFiles;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=member-files-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"member-files-client.js","sourceRoot":"","sources":["../../src/rules/member-files-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAA;AAYlE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAqC;IAErC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAA;IAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACrD,MAAM,GAAG,GAAG,GAAG,IAAI,kBAAkB,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAA;IAEvF,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;QACpC,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,CAAC,KAAK,EAAE,EAAE;KACtD,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;QACpD,MAAM,IAAI,KAAK,CACb,iCAAiC,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACjF,CAAA;IACH,CAAC;IAED,IAAI,OAAgB,CAAA;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IAC7D,CAAC;IACD,OAAO,6BAA6B,CAAC,OAAO,CAAC,CAAC,WAAW,CAAA;AAC3D,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return true if `child` is strictly contained within `parent` — i.e. equal or
|
|
3
|
+
* a descendant. Uses `path.relative` so `/repo` does not contain
|
|
4
|
+
* `/repo-malicious` (a prefix-match bug we hit on the first pass). An absolute
|
|
5
|
+
* result from `relative` means the two roots live on different Windows drives —
|
|
6
|
+
* definitely not contained.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isPathWithin(parent: string, child: string): boolean;
|
|
9
|
+
//# sourceMappingURL=path-contains.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-contains.d.ts","sourceRoot":"","sources":["../../src/rules/path-contains.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,WAKzD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { relative } from 'node:path';
|
|
2
|
+
/**
|
|
3
|
+
* Return true if `child` is strictly contained within `parent` — i.e. equal or
|
|
4
|
+
* a descendant. Uses `path.relative` so `/repo` does not contain
|
|
5
|
+
* `/repo-malicious` (a prefix-match bug we hit on the first pass). An absolute
|
|
6
|
+
* result from `relative` means the two roots live on different Windows drives —
|
|
7
|
+
* definitely not contained.
|
|
8
|
+
*/
|
|
9
|
+
export function isPathWithin(parent, child) {
|
|
10
|
+
const rel = relative(parent, child);
|
|
11
|
+
if (rel === '')
|
|
12
|
+
return true;
|
|
13
|
+
if (rel.startsWith('..'))
|
|
14
|
+
return false;
|
|
15
|
+
return !/^[a-zA-Z]:[/\\]/.test(rel) && !rel.startsWith('/');
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=path-contains.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-contains.js","sourceRoot":"","sources":["../../src/rules/path-contains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,KAAa;IACxD,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACnC,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,IAAI,CAAA;IAC3B,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAA;IACtC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;AAC7D,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type RawGuideFilePayload } from '@auden.to/protocol';
|
|
2
|
+
import type { DiscoveredGuideFile } from './discover.js';
|
|
3
|
+
/**
|
|
4
|
+
* Convert a discovered guide file into the canonical `RawGuideFilePayload`
|
|
5
|
+
* shape accepted by `POST /api/rules/import`. Throws if the resulting payload
|
|
6
|
+
* fails schema validation — a CLI bug, not a user error.
|
|
7
|
+
*
|
|
8
|
+
* Skill member files ride along only when discovery scanned the skill
|
|
9
|
+
* directory (`members` set, possibly `[]`); a payload without the field
|
|
10
|
+
* leaves the server's member rows untouched.
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildRulePayload(file: DiscoveredGuideFile): RawGuideFilePayload;
|
|
13
|
+
//# sourceMappingURL=payload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/rules/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAEvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAExD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,GAAG,mBAAmB,CAuB/E"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { parseRawGuideFilePayload } from '@auden.to/protocol';
|
|
2
|
+
/**
|
|
3
|
+
* Convert a discovered guide file into the canonical `RawGuideFilePayload`
|
|
4
|
+
* shape accepted by `POST /api/rules/import`. Throws if the resulting payload
|
|
5
|
+
* fails schema validation — a CLI bug, not a user error.
|
|
6
|
+
*
|
|
7
|
+
* Skill member files ride along only when discovery scanned the skill
|
|
8
|
+
* directory (`members` set, possibly `[]`); a payload without the field
|
|
9
|
+
* leaves the server's member rows untouched.
|
|
10
|
+
*/
|
|
11
|
+
export function buildRulePayload(file) {
|
|
12
|
+
return parseRawGuideFilePayload({
|
|
13
|
+
path: file.payloadPath,
|
|
14
|
+
format: file.format,
|
|
15
|
+
rawContent: file.rawContent,
|
|
16
|
+
lastModified: file.lastModified,
|
|
17
|
+
content_hash: file.contentHash,
|
|
18
|
+
...(file.members
|
|
19
|
+
? {
|
|
20
|
+
members: file.members.map((member) => ({
|
|
21
|
+
path: member.path,
|
|
22
|
+
rawContent: member.rawContent,
|
|
23
|
+
lastModified: member.lastModified,
|
|
24
|
+
content_hash: member.contentHash,
|
|
25
|
+
})),
|
|
26
|
+
// Skipped-but-present files ride along so the server preserves
|
|
27
|
+
// their rows instead of reading absence as removal.
|
|
28
|
+
...(file.membersSkippedPaths?.length
|
|
29
|
+
? { skippedMemberPaths: file.membersSkippedPaths }
|
|
30
|
+
: {}),
|
|
31
|
+
}
|
|
32
|
+
: {}),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=payload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../src/rules/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAA4B,MAAM,oBAAoB,CAAA;AAIvF;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAyB;IACxD,OAAO,wBAAwB,CAAC;QAC9B,IAAI,EAAE,IAAI,CAAC,WAAW;QACtB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,YAAY,EAAE,IAAI,CAAC,WAAW;QAC9B,GAAG,CAAC,IAAI,CAAC,OAAO;YACd,CAAC,CAAC;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;oBACrC,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,UAAU,EAAE,MAAM,CAAC,UAAU;oBAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;oBACjC,YAAY,EAAE,MAAM,CAAC,WAAW;iBACjC,CAAC,CAAC;gBACH,+DAA+D;gBAC/D,oDAAoD;gBACpD,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE,MAAM;oBAClC,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,CAAC,mBAAmB,EAAE;oBAClD,CAAC,CAAC,EAAE,CAAC;aACR;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { GuideBundleResponse } from '@auden.to/protocol';
|
|
2
|
+
export type PullGuideBundleOptions = {
|
|
3
|
+
dashboardUrl: string;
|
|
4
|
+
token: string;
|
|
5
|
+
bundlePath: string;
|
|
6
|
+
fetchFn?: typeof fetch;
|
|
7
|
+
};
|
|
8
|
+
export type PullGuideBundleResult = {
|
|
9
|
+
bundle: GuideBundleResponse;
|
|
10
|
+
bundlePath: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function pullGuideBundle(opts: PullGuideBundleOptions): Promise<PullGuideBundleResult>;
|
|
13
|
+
//# sourceMappingURL=pull-bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull-bundle.d.ts","sourceRoot":"","sources":["../../src/rules/pull-bundle.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAE7D,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,mBAAmB,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,qBAAqB,CAAC,CAiChC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { parseGuideBundleResponse } from '@auden.to/protocol';
|
|
4
|
+
export async function pullGuideBundle(opts) {
|
|
5
|
+
const fetchFn = opts.fetchFn ?? fetch;
|
|
6
|
+
const url = `${opts.dashboardUrl.replace(/\/+$/, '')}/api/v1/guides`;
|
|
7
|
+
const response = await fetchFn(url, {
|
|
8
|
+
headers: { Authorization: `Bearer ${opts.token}` },
|
|
9
|
+
});
|
|
10
|
+
if (!response.ok) {
|
|
11
|
+
const detail = await response.text().catch(() => '');
|
|
12
|
+
throw new Error(`Guide pull failed with ${response.status}${detail ? `: ${detail}` : ''}`);
|
|
13
|
+
}
|
|
14
|
+
let payload;
|
|
15
|
+
try {
|
|
16
|
+
payload = await response.json();
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
throw new Error('Guide bundle response was not valid JSON.');
|
|
20
|
+
}
|
|
21
|
+
let bundle;
|
|
22
|
+
try {
|
|
23
|
+
bundle = parseGuideBundleResponse(payload);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
throw new Error('Guide bundle response was malformed.');
|
|
27
|
+
}
|
|
28
|
+
await mkdir(dirname(opts.bundlePath), { recursive: true });
|
|
29
|
+
await writeFile(opts.bundlePath, JSON.stringify(bundle, null, 2) + '\n');
|
|
30
|
+
return { bundle, bundlePath: opts.bundlePath };
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=pull-bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull-bundle.js","sourceRoot":"","sources":["../../src/rules/pull-bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAgB7D,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,KAAK,CAAA;IACrC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,gBAAgB,CAAA;IAEpE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAClC,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,EAAE;KACnD,CAAC,CAAA;IAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;QACpD,MAAM,IAAI,KAAK,CACb,0BAA0B,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1E,CAAA;IACH,CAAC;IAED,IAAI,OAAgB,CAAA;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9D,CAAC;IAED,IAAI,MAA2B,CAAA;IAC/B,IAAI,CAAC;QACH,MAAM,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAA;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;IACzD,CAAC;IAED,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1D,MAAM,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IAExE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAA;AAChD,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { rescanSkill, type DiscoveredGuideFile } from './discover.js';
|
|
2
|
+
import type { RawGuideFileDeletion, RawGuideFilePayload } from '@auden.to/protocol';
|
|
3
|
+
export type WatchEventKind = 'change' | 'rename';
|
|
4
|
+
export type WatchEvent = {
|
|
5
|
+
kind: WatchEventKind;
|
|
6
|
+
/** Absolute path of the affected file. */
|
|
7
|
+
absolutePath: string;
|
|
8
|
+
/** Path relative to the discovery root that owns the watcher. */
|
|
9
|
+
payloadPath: string;
|
|
10
|
+
/** Display path shown to the user. */
|
|
11
|
+
displayPath: string;
|
|
12
|
+
};
|
|
13
|
+
export type WatchEventSource = {
|
|
14
|
+
/**
|
|
15
|
+
* Start emitting events. Returns a stop function used to tear watchers down.
|
|
16
|
+
* Implementations must call `onEvent` for every change/rename event seen on
|
|
17
|
+
* the project-level and (optional) global discovery roots.
|
|
18
|
+
*/
|
|
19
|
+
start(onEvent: (event: WatchEvent) => void): () => Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
export type WatchEngineOptions = {
|
|
22
|
+
cwd: string;
|
|
23
|
+
/** Pre-discovered files used to seed the in-memory state (hash + paths). */
|
|
24
|
+
initial: DiscoveredGuideFile[];
|
|
25
|
+
/**
|
|
26
|
+
* Roots whose descendant paths the engine will accept. Events outside these
|
|
27
|
+
* roots are dropped unless the path is already tracked from the initial
|
|
28
|
+
* scan. Defaults to `[cwd]`. The CLI passes `[cwd, ~/.claude]` when
|
|
29
|
+
* `--global` is enabled so newly-created global guide files are picked up.
|
|
30
|
+
*/
|
|
31
|
+
allowedRoots?: string[];
|
|
32
|
+
source: WatchEventSource;
|
|
33
|
+
/** Coalesce burst events for the same path within this window (ms). */
|
|
34
|
+
debounceMs: number;
|
|
35
|
+
/**
|
|
36
|
+
* Confirm a missing file is really gone before reporting a deletion. Editors
|
|
37
|
+
* often write atomically by deleting then recreating; the stability window
|
|
38
|
+
* suppresses that as a deletion and lets the follow-on change event fire.
|
|
39
|
+
*/
|
|
40
|
+
deleteStabilityMs: number;
|
|
41
|
+
/** Send a deletion batch to the dashboard. Required at runtime. */
|
|
42
|
+
sendDeletions?: (deletions: RawGuideFileDeletion[]) => Promise<void>;
|
|
43
|
+
/** Send a payload batch to the dashboard. Required at runtime. */
|
|
44
|
+
sendImports?: (payloads: RawGuideFilePayload[]) => Promise<void>;
|
|
45
|
+
/** Log line callback — defaults to console.log. */
|
|
46
|
+
log?: (line: string) => void;
|
|
47
|
+
/** Override file read for tests. */
|
|
48
|
+
readFileImpl?: (absolutePath: string) => Promise<{
|
|
49
|
+
rawContent: string;
|
|
50
|
+
lastModified: number;
|
|
51
|
+
} | null>;
|
|
52
|
+
/** Override the per-skill directory re-scan for tests. */
|
|
53
|
+
rescanSkillImpl?: typeof rescanSkill;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Stateful engine that turns raw fs events into batched import/delete calls.
|
|
57
|
+
* Exposed so tests can drive it deterministically.
|
|
58
|
+
*
|
|
59
|
+
* Per-path debouncing collapses editor save bursts. A deletion is only
|
|
60
|
+
* reported after `deleteStabilityMs` confirms the file is still gone — this
|
|
61
|
+
* lets atomic delete-then-create saves resolve as a change instead.
|
|
62
|
+
*/
|
|
63
|
+
export declare class RuleWatchEngine {
|
|
64
|
+
private readonly allowedRoots;
|
|
65
|
+
private readonly source;
|
|
66
|
+
private readonly debounceMs;
|
|
67
|
+
private readonly deleteStabilityMs;
|
|
68
|
+
private readonly sendImports;
|
|
69
|
+
private readonly sendDeletions;
|
|
70
|
+
private readonly log;
|
|
71
|
+
private readonly readFileImpl;
|
|
72
|
+
private readonly rescanSkillImpl;
|
|
73
|
+
private readonly known;
|
|
74
|
+
private readonly pending;
|
|
75
|
+
private readonly deletionTimers;
|
|
76
|
+
private readonly skillChains;
|
|
77
|
+
private stop;
|
|
78
|
+
private stopped;
|
|
79
|
+
constructor(options: WatchEngineOptions);
|
|
80
|
+
start(): void;
|
|
81
|
+
shutdown(): Promise<void>;
|
|
82
|
+
/** @internal — test helper to drive an event without going through the source. */
|
|
83
|
+
injectEvent(event: WatchEvent): void;
|
|
84
|
+
/** @internal — test helper to flush a pending debounce immediately. */
|
|
85
|
+
flush(absolutePath: string): Promise<void>;
|
|
86
|
+
private onEvent;
|
|
87
|
+
private process;
|
|
88
|
+
/**
|
|
89
|
+
* Find the tracked SKILL.md whose directory most tightly contains
|
|
90
|
+
* `absolutePath` — the skill a changed member file belongs to. Longest
|
|
91
|
+
* match wins so a nested skill owns its own subtree.
|
|
92
|
+
*/
|
|
93
|
+
private findOwningSkill;
|
|
94
|
+
/**
|
|
95
|
+
* Re-scan a skill's directory and re-send its SKILL.md payload with a fresh
|
|
96
|
+
* members array, serialized per owning skill. The server treats that array as
|
|
97
|
+
* the complete member set, so a member (or SKILL.md) add/edit/delete
|
|
98
|
+
* propagates by re-sending the whole skill. Chaining on `skillChains` keeps
|
|
99
|
+
* two near-simultaneous events for the same skill from POSTing concurrently —
|
|
100
|
+
* an earlier, staler snapshot must not land after a newer one and revert it.
|
|
101
|
+
*/
|
|
102
|
+
private resyncSkill;
|
|
103
|
+
private doResyncSkill;
|
|
104
|
+
private scheduleDeletion;
|
|
105
|
+
private fireDeletion;
|
|
106
|
+
}
|
|
107
|
+
type FsWatcher = {
|
|
108
|
+
close(): void;
|
|
109
|
+
};
|
|
110
|
+
export type CreateFsSourceOptions = {
|
|
111
|
+
cwd: string;
|
|
112
|
+
global: boolean;
|
|
113
|
+
homedir?: string;
|
|
114
|
+
/** Underlying watch primitive. Defaults to node:fs.watch. */
|
|
115
|
+
watchImpl?: (path: string, options: {
|
|
116
|
+
recursive?: boolean;
|
|
117
|
+
}, listener: (eventType: string, filename: string | null) => void) => FsWatcher;
|
|
118
|
+
};
|
|
119
|
+
export declare function createFsWatchSource(options: CreateFsSourceOptions): WatchEventSource;
|
|
120
|
+
export {};
|
|
121
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/rules/watch.ts"],"names":[],"mappings":"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"}
|