@cluesmith/codev 3.3.4 → 3.3.6
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/dashboard-dist/assets/index-BjcqV9Vv.css +32 -0
- package/dashboard-dist/assets/index-b7GnZV2i.js +220 -0
- package/dashboard-dist/assets/index-b7GnZV2i.js.map +1 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +50 -17
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/architect.d.ts.map +1 -1
- package/dist/agent-farm/commands/architect.js +5 -1
- package/dist/agent-farm/commands/architect.js.map +1 -1
- package/dist/agent-farm/commands/attach.d.ts +1 -1
- package/dist/agent-farm/commands/attach.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.d.ts +1 -1
- package/dist/agent-farm/commands/cleanup.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.js +2 -1
- package/dist/agent-farm/commands/cleanup.js.map +1 -1
- package/dist/agent-farm/commands/decisions.d.ts +25 -0
- package/dist/agent-farm/commands/decisions.d.ts.map +1 -0
- package/dist/agent-farm/commands/decisions.js +54 -0
- package/dist/agent-farm/commands/decisions.js.map +1 -0
- package/dist/agent-farm/commands/ide.d.ts +32 -3
- package/dist/agent-farm/commands/ide.d.ts.map +1 -1
- package/dist/agent-farm/commands/ide.js +180 -19
- package/dist/agent-farm/commands/ide.js.map +1 -1
- package/dist/agent-farm/commands/reset/context.d.ts +4 -2
- package/dist/agent-farm/commands/reset/context.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/context.js +12 -4
- package/dist/agent-farm/commands/reset/context.js.map +1 -1
- package/dist/agent-farm/commands/send.d.ts +3 -2
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +35 -21
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts +7 -0
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +63 -20
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts +17 -0
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +41 -19
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/lib/builder-lookup.d.ts +3 -2
- package/dist/agent-farm/lib/builder-lookup.d.ts.map +1 -1
- package/dist/agent-farm/lib/builder-lookup.js +24 -9
- package/dist/agent-farm/lib/builder-lookup.js.map +1 -1
- package/dist/agent-farm/lib/ide-extensions.d.ts +82 -0
- package/dist/agent-farm/lib/ide-extensions.d.ts.map +1 -0
- package/dist/agent-farm/lib/ide-extensions.js +179 -0
- package/dist/agent-farm/lib/ide-extensions.js.map +1 -0
- package/dist/agent-farm/lib/ide-record.d.ts +6 -1
- package/dist/agent-farm/lib/ide-record.d.ts.map +1 -1
- package/dist/agent-farm/lib/ide-record.js +8 -1
- package/dist/agent-farm/lib/ide-record.js.map +1 -1
- package/dist/agent-farm/lib/ide-version.d.ts +97 -0
- package/dist/agent-farm/lib/ide-version.d.ts.map +1 -0
- package/dist/agent-farm/lib/ide-version.js +224 -0
- package/dist/agent-farm/lib/ide-version.js.map +1 -0
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +7 -3
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/agent-state/broadcast.d.ts +19 -0
- package/dist/agent-farm/servers/agent-state/broadcast.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/broadcast.js +30 -0
- package/dist/agent-farm/servers/agent-state/broadcast.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/identity.d.ts +50 -0
- package/dist/agent-farm/servers/agent-state/identity.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/identity.js +120 -0
- package/dist/agent-farm/servers/agent-state/identity.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/liveness.d.ts +107 -0
- package/dist/agent-farm/servers/agent-state/liveness.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/liveness.js +224 -0
- package/dist/agent-farm/servers/agent-state/liveness.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/route.d.ts +38 -0
- package/dist/agent-farm/servers/agent-state/route.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/route.js +170 -0
- package/dist/agent-farm/servers/agent-state/route.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/serve.d.ts +31 -0
- package/dist/agent-farm/servers/agent-state/serve.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/serve.js +49 -0
- package/dist/agent-farm/servers/agent-state/serve.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/store.d.ts +76 -0
- package/dist/agent-farm/servers/agent-state/store.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/store.js +157 -0
- package/dist/agent-farm/servers/agent-state/store.js.map +1 -0
- package/dist/agent-farm/servers/decisions/file.d.ts +50 -0
- package/dist/agent-farm/servers/decisions/file.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/file.js +146 -0
- package/dist/agent-farm/servers/decisions/file.js.map +1 -0
- package/dist/agent-farm/servers/decisions/grammar.d.ts +36 -0
- package/dist/agent-farm/servers/decisions/grammar.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/grammar.js +109 -0
- package/dist/agent-farm/servers/decisions/grammar.js.map +1 -0
- package/dist/agent-farm/servers/decisions/notice.d.ts +11 -0
- package/dist/agent-farm/servers/decisions/notice.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/notice.js +18 -0
- package/dist/agent-farm/servers/decisions/notice.js.map +1 -0
- package/dist/agent-farm/servers/decisions/parse.d.ts +36 -0
- package/dist/agent-farm/servers/decisions/parse.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/parse.js +338 -0
- package/dist/agent-farm/servers/decisions/parse.js.map +1 -0
- package/dist/agent-farm/servers/decisions/routes.d.ts +17 -0
- package/dist/agent-farm/servers/decisions/routes.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/routes.js +160 -0
- package/dist/agent-farm/servers/decisions/routes.js.map +1 -0
- package/dist/agent-farm/servers/decisions/splice.d.ts +26 -0
- package/dist/agent-farm/servers/decisions/splice.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/splice.js +120 -0
- package/dist/agent-farm/servers/decisions/splice.js.map +1 -0
- package/dist/agent-farm/servers/decisions/stamp.d.ts +8 -0
- package/dist/agent-farm/servers/decisions/stamp.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/stamp.js +195 -0
- package/dist/agent-farm/servers/decisions/stamp.js.map +1 -0
- package/dist/agent-farm/servers/decisions/template.d.ts +2 -0
- package/dist/agent-farm/servers/decisions/template.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/template.js +15 -0
- package/dist/agent-farm/servers/decisions/template.js.map +1 -0
- package/dist/agent-farm/servers/ide-server.d.ts +28 -8
- package/dist/agent-farm/servers/ide-server.d.ts.map +1 -1
- package/dist/agent-farm/servers/ide-server.js +147 -50
- package/dist/agent-farm/servers/ide-server.js.map +1 -1
- package/dist/agent-farm/servers/overview.d.ts +31 -4
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +235 -55
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts +14 -1
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +51 -9
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +113 -14
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +35 -1
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +25 -0
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +128 -4
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.js +18 -5
- package/dist/agent-farm/servers/tower-utils.js.map +1 -1
- package/dist/agent-farm/utils/builder-worktree-identity.d.ts +39 -0
- package/dist/agent-farm/utils/builder-worktree-identity.d.ts.map +1 -0
- package/dist/agent-farm/utils/builder-worktree-identity.js +42 -0
- package/dist/agent-farm/utils/builder-worktree-identity.js.map +1 -0
- package/dist/agent-farm/utils/harness.d.ts +71 -0
- package/dist/agent-farm/utils/harness.d.ts.map +1 -1
- package/dist/agent-farm/utils/harness.js +153 -0
- package/dist/agent-farm/utils/harness.js.map +1 -1
- package/dist/agent-farm/utils/lifecycle-reporter.d.ts +79 -0
- package/dist/agent-farm/utils/lifecycle-reporter.d.ts.map +1 -0
- package/dist/agent-farm/utils/lifecycle-reporter.js +347 -0
- package/dist/agent-farm/utils/lifecycle-reporter.js.map +1 -0
- package/dist/agent-farm/utils/message-format.d.ts +8 -0
- package/dist/agent-farm/utils/message-format.d.ts.map +1 -1
- package/dist/agent-farm/utils/message-format.js +16 -0
- package/dist/agent-farm/utils/message-format.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +17 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt.d.ts +16 -2
- package/dist/commands/adopt.d.ts.map +1 -1
- package/dist/commands/adopt.js +67 -23
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/bootstrap-docs.d.ts +132 -0
- package/dist/commands/bootstrap-docs.d.ts.map +1 -0
- package/dist/commands/bootstrap-docs.js +725 -0
- package/dist/commands/bootstrap-docs.js.map +1 -0
- package/dist/commands/consult/index.d.ts +20 -1
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +70 -3
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/consult/tree-tripwire.d.ts +2 -75
- package/dist/commands/consult/tree-tripwire.d.ts.map +1 -1
- package/dist/commands/consult/tree-tripwire.js +7 -184
- package/dist/commands/consult/tree-tripwire.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +36 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/porch/checks.d.ts +7 -1
- package/dist/commands/porch/checks.d.ts.map +1 -1
- package/dist/commands/porch/checks.js +77 -14
- package/dist/commands/porch/checks.js.map +1 -1
- package/dist/commands/porch/index.d.ts +38 -1
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +79 -43
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/protocol.d.ts +4 -3
- package/dist/commands/porch/protocol.d.ts.map +1 -1
- package/dist/commands/porch/protocol.js +32 -5
- package/dist/commands/porch/protocol.js.map +1 -1
- package/dist/commands/porch/state.d.ts +0 -4
- package/dist/commands/porch/state.d.ts.map +1 -1
- package/dist/commands/porch/state.js +23 -10
- package/dist/commands/porch/state.js.map +1 -1
- package/dist/commands/porch/types.d.ts +2 -0
- package/dist/commands/porch/types.d.ts.map +1 -1
- package/dist/commands/update.d.ts +5 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +73 -18
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/agent-env.d.ts +31 -1
- package/dist/lib/agent-env.d.ts.map +1 -1
- package/dist/lib/agent-env.js +38 -1
- package/dist/lib/agent-env.js.map +1 -1
- package/dist/lib/agent-process.d.ts +23 -0
- package/dist/lib/agent-process.d.ts.map +1 -0
- package/dist/lib/agent-process.js +24 -0
- package/dist/lib/agent-process.js.map +1 -0
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/forge-contracts.d.ts +9 -3
- package/dist/lib/forge-contracts.d.ts.map +1 -1
- package/dist/lib/forge-contracts.js.map +1 -1
- package/dist/lib/forge.d.ts +8 -5
- package/dist/lib/forge.d.ts.map +1 -1
- package/dist/lib/forge.js +57 -1
- package/dist/lib/forge.js.map +1 -1
- package/dist/lib/github.d.ts.map +1 -1
- package/dist/lib/github.js +38 -0
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/governance-bootstrap.d.ts +155 -0
- package/dist/lib/governance-bootstrap.d.ts.map +1 -0
- package/dist/lib/governance-bootstrap.js +469 -0
- package/dist/lib/governance-bootstrap.js.map +1 -0
- package/dist/lib/issue-id.d.ts +34 -0
- package/dist/lib/issue-id.d.ts.map +1 -0
- package/dist/lib/issue-id.js +61 -0
- package/dist/lib/issue-id.js.map +1 -0
- package/dist/lib/scaffold.d.ts +4 -0
- package/dist/lib/scaffold.d.ts.map +1 -1
- package/dist/lib/scaffold.js +29 -5
- package/dist/lib/scaffold.js.map +1 -1
- package/dist/lib/shipped-skill-hashes.d.ts +10 -0
- package/dist/lib/shipped-skill-hashes.d.ts.map +1 -0
- package/dist/lib/shipped-skill-hashes.js +197 -0
- package/dist/lib/shipped-skill-hashes.js.map +1 -0
- package/dist/lib/skill-refresh.d.ts +90 -0
- package/dist/lib/skill-refresh.d.ts.map +1 -0
- package/dist/lib/skill-refresh.js +267 -0
- package/dist/lib/skill-refresh.js.map +1 -0
- package/dist/lib/tree-snapshot.d.ts +172 -0
- package/dist/lib/tree-snapshot.d.ts.map +1 -0
- package/dist/lib/tree-snapshot.js +393 -0
- package/dist/lib/tree-snapshot.js.map +1 -0
- package/dist/terminal/pty-session.d.ts +5 -0
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +7 -0
- package/dist/terminal/pty-session.js.map +1 -1
- package/ide-extension/codev-vscode.vsix +0 -0
- package/ide-extension/manifest.json +7 -0
- package/package.json +8 -6
- package/scripts/forge/jira/_lib.sh +113 -0
- package/scripts/forge/jira/auth-status.sh +29 -0
- package/scripts/forge/jira/issue-comment.sh +23 -0
- package/scripts/forge/jira/issue-list.sh +32 -0
- package/scripts/forge/jira/issue-search.sh +40 -0
- package/scripts/forge/jira/issue-view.sh +41 -0
- package/scripts/forge/jira/recently-closed.sh +81 -0
- package/scripts/forge/jira/user-identity.sh +18 -0
- package/skeleton/.claude/skills/afx/SKILL.md +51 -0
- package/skeleton/.claude/skills/arch-init/SKILL.md +56 -9
- package/skeleton/.claude/skills/arch-save/SKILL.md +100 -9
- package/skeleton/.claude/skills/codev/SKILL.md +18 -2
- package/skeleton/.claude/skills/consult/SKILL.md +9 -0
- package/skeleton/.claude/skills/porch/SKILL.md +18 -0
- package/skeleton/.claude/skills/update-arch-docs/SKILL.md +28 -2
- package/skeleton/.codex/skills/afx/SKILL.md +51 -0
- package/skeleton/.codex/skills/arch-init/SKILL.md +56 -9
- package/skeleton/.codex/skills/arch-save/SKILL.md +100 -9
- package/skeleton/.codex/skills/codev/SKILL.md +18 -2
- package/skeleton/.codex/skills/consult/SKILL.md +9 -0
- package/skeleton/.codex/skills/porch/SKILL.md +18 -0
- package/skeleton/.codex/skills/update-arch-docs/SKILL.md +28 -2
- package/skeleton/protocol-schema.json +6 -0
- package/skeleton/protocols/maintain/protocol.md +5 -0
- package/skeleton/protocols/pir/prompts/review.md +0 -1
- package/skeleton/protocols/protocol-schema.json +6 -0
- package/skeleton/resources/commands/agent-farm.md +156 -0
- package/skeleton/resources/commands/codev.md +47 -0
- package/skeleton/resources/commands/consult.md +9 -2
- package/skeleton/resources/commands/overview.md +1 -0
- package/skeleton/resources/decision-protocol.md +215 -0
- package/skeleton/resources/workflow-reference.md +12 -0
- package/skeleton/roles/architect.md +6 -0
- package/skeleton/templates/bootstrap-docs-prompt.md +16 -0
- package/skeleton/templates/bootstrap-docs-review-prompt.md +19 -0
- package/skeleton/templates/cheatsheet.md +2 -1
- package/dashboard-dist/assets/index-DZf6pNPE.js +0 -199
- package/dashboard-dist/assets/index-DZf6pNPE.js.map +0 -1
- package/dashboard-dist/assets/index-DnYLy5C_.css +0 -32
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refresh shipped provider skills on `codev update` (issue #1811).
|
|
3
|
+
*
|
|
4
|
+
* A skill directory is unedited when its content matches a version Codev has shipped
|
|
5
|
+
* (SHIPPED_SKILL_HASHES, generated from git history). Unedited skills are replaced with
|
|
6
|
+
* the package's version; an edited one gets a `.codev-new` copy of each differing file
|
|
7
|
+
* for update's merge session, the same treatment CLAUDE.md and AGENTS.md get.
|
|
8
|
+
*/
|
|
9
|
+
import * as crypto from 'node:crypto';
|
|
10
|
+
import * as fs from 'node:fs';
|
|
11
|
+
import * as path from 'node:path';
|
|
12
|
+
import { SHIPPED_SKILL_HASHES } from './shipped-skill-hashes.js';
|
|
13
|
+
import { SKILL_PROVIDERS } from './scaffold.js';
|
|
14
|
+
/** Suffix of the new version written beside an edited skill file. */
|
|
15
|
+
export const CODEV_NEW_SUFFIX = '.codev-new';
|
|
16
|
+
/**
|
|
17
|
+
* Files that never count as skill content: a pending `.codev-new` copy, and Finder's
|
|
18
|
+
* `.DS_Store`, which would otherwise mark every skill a macOS user opened as edited.
|
|
19
|
+
*/
|
|
20
|
+
function isIgnoredSkillFile(name) {
|
|
21
|
+
return name.endsWith(CODEV_NEW_SUFFIX) || name === '.DS_Store';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The content hash of one skill directory: its files in path order, each as path and
|
|
25
|
+
* content, with line endings normalised so a CRLF checkout of a shipped skill still matches.
|
|
26
|
+
*/
|
|
27
|
+
export function hashSkillFiles(files) {
|
|
28
|
+
const hash = crypto.createHash('sha256');
|
|
29
|
+
const sorted = [...files].sort((a, b) => {
|
|
30
|
+
if (a.path < b.path)
|
|
31
|
+
return -1;
|
|
32
|
+
if (a.path > b.path)
|
|
33
|
+
return 1;
|
|
34
|
+
return 0;
|
|
35
|
+
});
|
|
36
|
+
for (const file of sorted) {
|
|
37
|
+
hash.update(file.path);
|
|
38
|
+
hash.update('\0');
|
|
39
|
+
hash.update(file.content.replace(/\r\n/g, '\n'));
|
|
40
|
+
hash.update('\0');
|
|
41
|
+
}
|
|
42
|
+
return hash.digest('hex');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The files of a skill directory, or null when the path is not a real directory (missing,
|
|
46
|
+
* a symlink, or a file). Symlinked entries inside it are read as content, never followed.
|
|
47
|
+
*/
|
|
48
|
+
export function readSkillFiles(dir) {
|
|
49
|
+
let stat;
|
|
50
|
+
try {
|
|
51
|
+
stat = fs.lstatSync(dir);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
if (!stat.isDirectory())
|
|
57
|
+
return null;
|
|
58
|
+
const files = [];
|
|
59
|
+
// An unreadable directory or file reads as null, which classifies as not-regular: the
|
|
60
|
+
// skill is reported and left alone rather than ending the whole update.
|
|
61
|
+
const walk = (current, prefix) => {
|
|
62
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
63
|
+
if (isIgnoredSkillFile(entry.name))
|
|
64
|
+
continue;
|
|
65
|
+
const full = path.join(current, entry.name);
|
|
66
|
+
const rel = prefix + entry.name;
|
|
67
|
+
if (entry.isDirectory()) {
|
|
68
|
+
walk(full, `${rel}/`);
|
|
69
|
+
}
|
|
70
|
+
else if (entry.isSymbolicLink()) {
|
|
71
|
+
files.push({ path: rel, content: `<link:${fs.readlinkSync(full)}>`, link: true });
|
|
72
|
+
}
|
|
73
|
+
else if (entry.isFile()) {
|
|
74
|
+
files.push({ path: rel, content: fs.readFileSync(full, 'utf-8') });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
try {
|
|
79
|
+
walk(dir, '');
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
return files;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Whether a skill directory holds a pending `.codev-new` that is not a regular file. A
|
|
88
|
+
* symlinked pending path would carry the next `.codev-new` write outside the project.
|
|
89
|
+
*/
|
|
90
|
+
function hasIrregularPending(dir) {
|
|
91
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
92
|
+
const full = path.join(dir, entry.name);
|
|
93
|
+
if (entry.name.endsWith(CODEV_NEW_SUFFIX) && !entry.isFile())
|
|
94
|
+
return true;
|
|
95
|
+
if (entry.isDirectory() && hasIrregularPending(full))
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Whether `dir` is a real directory holding no skill files: nothing at all, or only
|
|
102
|
+
* `.DS_Store` / `.codev-new` leftovers. Such a folder is what discarding the untracked files
|
|
103
|
+
* of an earlier install leaves behind, and it is treated as a missing skill, never a skill.
|
|
104
|
+
*/
|
|
105
|
+
export function isEmptySkillDir(dir) {
|
|
106
|
+
const files = readSkillFiles(dir);
|
|
107
|
+
return files !== null && files.length === 0;
|
|
108
|
+
}
|
|
109
|
+
export function hashSkillDir(dir) {
|
|
110
|
+
const files = readSkillFiles(dir);
|
|
111
|
+
if (files === null)
|
|
112
|
+
return null;
|
|
113
|
+
return hashSkillFiles(files);
|
|
114
|
+
}
|
|
115
|
+
/** Project-relative directory of one provider's copy of a skill, e.g. `.claude/skills/afx`. */
|
|
116
|
+
export function skillRelDir(provider, name) {
|
|
117
|
+
return `.${provider}/skills/${name}`;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Where a project's copy of a skill stands against the package's version. `key` is the
|
|
121
|
+
* skill's project-relative directory (`skillRelDir`), which keys the shipped history.
|
|
122
|
+
*/
|
|
123
|
+
export function classifySkill(projectSkillDir, packageSkillDir, key, history = SHIPPED_SKILL_HASHES) {
|
|
124
|
+
if (!fs.existsSync(projectSkillDir) && !isSymlink(projectSkillDir))
|
|
125
|
+
return 'missing';
|
|
126
|
+
const files = readSkillFiles(projectSkillDir);
|
|
127
|
+
if (files === null || files.some(file => file.link) || hasIrregularPending(projectSkillDir))
|
|
128
|
+
return 'not-regular';
|
|
129
|
+
if (files.length === 0)
|
|
130
|
+
return 'missing';
|
|
131
|
+
const projectHash = hashSkillFiles(files);
|
|
132
|
+
if (projectHash === hashSkillDir(packageSkillDir))
|
|
133
|
+
return 'current';
|
|
134
|
+
if ((history[key] ?? []).includes(projectHash))
|
|
135
|
+
return 'shipped';
|
|
136
|
+
return 'edited';
|
|
137
|
+
}
|
|
138
|
+
function isSymlink(p) {
|
|
139
|
+
try {
|
|
140
|
+
return fs.lstatSync(p).isSymbolicLink();
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function replaceSkillDir(projectSkillDir, packageSkillDir) {
|
|
147
|
+
// Remove only the files the skill is made of; a .DS_Store is the user's.
|
|
148
|
+
for (const file of readSkillFiles(projectSkillDir) ?? []) {
|
|
149
|
+
fs.rmSync(path.join(projectSkillDir, file.path), { force: true });
|
|
150
|
+
}
|
|
151
|
+
fs.cpSync(packageSkillDir, projectSkillDir, { recursive: true, force: true });
|
|
152
|
+
}
|
|
153
|
+
/** Write the package's files over the project's copy, leaving any other file in place. */
|
|
154
|
+
function overwritePackagedFiles(projectSkillDir, packageSkillDir) {
|
|
155
|
+
fs.cpSync(packageSkillDir, projectSkillDir, { recursive: true, force: true });
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Delete a pending `.codev-new` that holds exactly the package's version of its file: the
|
|
159
|
+
* skill now has that version, so the copy is resolved. A copy with other content is kept.
|
|
160
|
+
*/
|
|
161
|
+
function removeResolvedCodevNew(projectSkillDir, file) {
|
|
162
|
+
const pending = path.join(projectSkillDir, file.path + CODEV_NEW_SUFFIX);
|
|
163
|
+
try {
|
|
164
|
+
if (fs.lstatSync(pending).isFile() && fs.readFileSync(pending, 'utf-8') === file.content)
|
|
165
|
+
fs.rmSync(pending);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
// No pending copy.
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function removeAllResolvedCodevNew(projectSkillDir, packageSkillDir) {
|
|
172
|
+
for (const file of readSkillFiles(packageSkillDir) ?? [])
|
|
173
|
+
removeResolvedCodevNew(projectSkillDir, file);
|
|
174
|
+
}
|
|
175
|
+
/** True when something other than a real directory sits at `p` (a symlink, a file). */
|
|
176
|
+
function existsButNotDirectory(p) {
|
|
177
|
+
try {
|
|
178
|
+
const stat = fs.lstatSync(p);
|
|
179
|
+
return !stat.isDirectory();
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Bring every shipped skill up to date: add missing ones, replace unedited ones, and write
|
|
187
|
+
* `<file>.codev-new` beside each file of an edited skill that differs from the package. A
|
|
188
|
+
* file the package adds to an edited skill arrives as `.codev-new` too: whether it belongs
|
|
189
|
+
* in the user's version of the skill is the merge's call. With `dryRun`, the same result
|
|
190
|
+
* is reported and nothing is written.
|
|
191
|
+
*/
|
|
192
|
+
export function refreshSkills(targetDir, skeletonDir, options = {}) {
|
|
193
|
+
const result = { added: [], updated: [], conflicts: [], notRegular: [] };
|
|
194
|
+
const write = !options.dryRun;
|
|
195
|
+
for (const provider of SKILL_PROVIDERS) {
|
|
196
|
+
const relativeSkillsDir = `.${provider}/skills`;
|
|
197
|
+
const skillsDir = path.join(targetDir, relativeSkillsDir);
|
|
198
|
+
const srcDir = path.join(skeletonDir, relativeSkillsDir);
|
|
199
|
+
// A symlinked `.claude` / `.codex` or skills root may be shared beyond this project;
|
|
200
|
+
// nothing is written through either.
|
|
201
|
+
const linkedRoot = [`.${provider}`, relativeSkillsDir].find(rel => existsButNotDirectory(path.join(targetDir, rel)));
|
|
202
|
+
if (linkedRoot) {
|
|
203
|
+
result.notRegular.push(`${linkedRoot}/`);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (write && !fs.existsSync(skillsDir))
|
|
207
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
208
|
+
// Older/corrupt skeletons may not provide every configured provider.
|
|
209
|
+
if (!fs.existsSync(srcDir))
|
|
210
|
+
continue;
|
|
211
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
212
|
+
if (!entry.isDirectory())
|
|
213
|
+
continue;
|
|
214
|
+
const key = skillRelDir(provider, entry.name);
|
|
215
|
+
const packageSkillDir = path.join(srcDir, entry.name);
|
|
216
|
+
const projectSkillDir = path.join(skillsDir, entry.name);
|
|
217
|
+
const state = classifySkill(projectSkillDir, packageSkillDir, key, options.history);
|
|
218
|
+
if (state === 'missing') {
|
|
219
|
+
if (write)
|
|
220
|
+
fs.cpSync(packageSkillDir, projectSkillDir, { recursive: true });
|
|
221
|
+
result.added.push(`${key}/`);
|
|
222
|
+
}
|
|
223
|
+
else if (state === 'current') {
|
|
224
|
+
if (write)
|
|
225
|
+
removeAllResolvedCodevNew(projectSkillDir, packageSkillDir);
|
|
226
|
+
}
|
|
227
|
+
else if (state === 'shipped') {
|
|
228
|
+
// Every file matched a shipped version, so none of them is the user's to keep.
|
|
229
|
+
if (write) {
|
|
230
|
+
replaceSkillDir(projectSkillDir, packageSkillDir);
|
|
231
|
+
removeAllResolvedCodevNew(projectSkillDir, packageSkillDir);
|
|
232
|
+
}
|
|
233
|
+
result.updated.push(`${key}/`);
|
|
234
|
+
}
|
|
235
|
+
else if (state === 'not-regular') {
|
|
236
|
+
result.notRegular.push(`${key}/`);
|
|
237
|
+
}
|
|
238
|
+
else if (state === 'edited' && options.force) {
|
|
239
|
+
if (write) {
|
|
240
|
+
overwritePackagedFiles(projectSkillDir, packageSkillDir);
|
|
241
|
+
removeAllResolvedCodevNew(projectSkillDir, packageSkillDir);
|
|
242
|
+
}
|
|
243
|
+
result.updated.push(`${key}/`);
|
|
244
|
+
}
|
|
245
|
+
else if (state === 'edited') {
|
|
246
|
+
const projectFiles = new Map((readSkillFiles(projectSkillDir) ?? []).map(file => [file.path, file.content]));
|
|
247
|
+
for (const file of readSkillFiles(packageSkillDir) ?? []) {
|
|
248
|
+
if (projectFiles.get(file.path) === file.content) {
|
|
249
|
+
if (write)
|
|
250
|
+
removeResolvedCodevNew(projectSkillDir, file);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (write) {
|
|
254
|
+
const target = path.join(projectSkillDir, file.path);
|
|
255
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
256
|
+
// `wx` after removing a regular pending copy: never follow a path swapped in since.
|
|
257
|
+
fs.rmSync(target + CODEV_NEW_SUFFIX, { force: true });
|
|
258
|
+
fs.writeFileSync(target + CODEV_NEW_SUFFIX, file.content, { flag: 'wx' });
|
|
259
|
+
}
|
|
260
|
+
result.conflicts.push(`${key}/${file.path}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=skill-refresh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-refresh.js","sourceRoot":"","sources":["../../src/lib/skill-refresh.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Before/after snapshots of a working tree, for commands that hand the tree to an agent
|
|
3
|
+
* they cannot sandbox and must report afterwards what moved.
|
|
4
|
+
*
|
|
5
|
+
* Two consumers: the consult tripwire (#1649), which watches a review lane that should
|
|
6
|
+
* write nothing, and `codev bootstrap-docs` (Spec 1797), which watches a drafting agent
|
|
7
|
+
* that may write only the governance files it was given. Each owns its own exemptions;
|
|
8
|
+
* this module only takes the snapshots and diffs them through a caller-supplied predicate.
|
|
9
|
+
*
|
|
10
|
+
* ## Why not just diff `git status --porcelain` output
|
|
11
|
+
*
|
|
12
|
+
* Because the interesting case is a tree that was *already dirty*. A builder mid-phase has
|
|
13
|
+
* uncommitted work; porcelain reports ` M src/foo.ts` before and after, identical strings,
|
|
14
|
+
* while the file's contents changed underneath. So the git snapshot pairs each path
|
|
15
|
+
* porcelain reports with a hash of its contents on disk.
|
|
16
|
+
*
|
|
17
|
+
* ## What it cannot see
|
|
18
|
+
*
|
|
19
|
+
* In a git work tree: files git ignores, edits inside a submodule (`git status` reports the
|
|
20
|
+
* submodule as one entry), and an edit restored byte-for-byte before the second snapshot.
|
|
21
|
+
* Outside git: paths the root `.gitignore` ignores (read with a simplified compiler that can
|
|
22
|
+
* ignore more than git would), `.git/` and `node_modules/` (so a `git init` and commit made
|
|
23
|
+
* during the session leave no trace), and anything past the walk's file bound, which the
|
|
24
|
+
* snapshot reports as `truncated`.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Where the repository itself is pointing.
|
|
28
|
+
*
|
|
29
|
+
* The working tree is only half the state an agent can move. `git commit` takes a dirty
|
|
30
|
+
* tree clean, and `git checkout` between two refs with identical content changes nothing a
|
|
31
|
+
* file comparison can see.
|
|
32
|
+
*
|
|
33
|
+
* Either field is `null` when git cannot answer — most usefully in a repository with no
|
|
34
|
+
* commits yet, where `rev-parse HEAD` fails and the tree is still worth watching.
|
|
35
|
+
*/
|
|
36
|
+
export interface RepositoryIdentity {
|
|
37
|
+
/** HEAD's object id. */
|
|
38
|
+
head: string | null;
|
|
39
|
+
/** Branch name, or `HEAD` when detached. */
|
|
40
|
+
branch: string | null;
|
|
41
|
+
/**
|
|
42
|
+
* True when HEAD names a branch with no commits yet (an unborn branch), so a `null` head
|
|
43
|
+
* means "no commits" rather than "could not tell" and a first commit is a real move.
|
|
44
|
+
*/
|
|
45
|
+
unborn?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A point-in-time view of every path that can be compared, plus where the repository was
|
|
49
|
+
* pointing when it was taken.
|
|
50
|
+
*
|
|
51
|
+
* `available: false` means no snapshot could be taken (for `snapshotTree`, most often a
|
|
52
|
+
* workspace that is not a git repository). Callers say so rather than pretending the tree
|
|
53
|
+
* was clean.
|
|
54
|
+
*/
|
|
55
|
+
export interface TreeSnapshot {
|
|
56
|
+
available: boolean;
|
|
57
|
+
/** Reason the snapshot is unavailable; only set when `available` is false. */
|
|
58
|
+
reason?: string;
|
|
59
|
+
/** Repo-relative path → `"<status code>:<content hash>"` (git) or the content hash (walk). */
|
|
60
|
+
entries: Map<string, string>;
|
|
61
|
+
/** HEAD and branch at the moment of the snapshot. */
|
|
62
|
+
identity: RepositoryIdentity;
|
|
63
|
+
/** Set by the filesystem walk when it stopped at its file bound; entries are then partial. */
|
|
64
|
+
truncated?: boolean;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Read HEAD and the branch name in one `git rev-parse`.
|
|
68
|
+
*
|
|
69
|
+
* Failure is not fatal to the snapshot. A freshly `git init`ed repository has no HEAD to
|
|
70
|
+
* resolve, and the file-level half works there perfectly well.
|
|
71
|
+
*/
|
|
72
|
+
export declare function readIdentity(workspaceRoot: string): RepositoryIdentity;
|
|
73
|
+
/**
|
|
74
|
+
* Paths `consult` writes itself on every run, and which therefore are not
|
|
75
|
+
* evidence of anything.
|
|
76
|
+
*
|
|
77
|
+
* `.consult/history.log` is appended by `logQuery()` after the lane returns, so
|
|
78
|
+
* it lands inside the window a consult or bootstrap tripwire measures. In this repo `.consult/` is
|
|
79
|
+
* gitignored and never surfaces — which is exactly why it was not obvious. A
|
|
80
|
+
* live run against a scratch repo without that entry reported the log file as a
|
|
81
|
+
* mutation on the very first try. An adopter's `.gitignore` is not something to
|
|
82
|
+
* depend on for correctness here.
|
|
83
|
+
*/
|
|
84
|
+
export declare const CONSULT_OWNED_PREFIXES: string[];
|
|
85
|
+
/**
|
|
86
|
+
* Hash a working-tree file, or mark it absent.
|
|
87
|
+
*
|
|
88
|
+
* Absent is a real state, not an error: a path can appear in porcelain output as a staged
|
|
89
|
+
* deletion, and an agent that *deletes* a file is precisely what is being watched for.
|
|
90
|
+
*/
|
|
91
|
+
export declare function hashPath(absolute: string): string;
|
|
92
|
+
/**
|
|
93
|
+
* Snapshot the git working tree of `workspaceRoot`.
|
|
94
|
+
*
|
|
95
|
+
* `-z` (NUL-separated) rather than plain `--porcelain` because git C-quotes paths containing
|
|
96
|
+
* spaces or non-ASCII in the human-readable form, and a quoted path cannot be handed back to
|
|
97
|
+
* `fs.readFileSync`. `--untracked-files=all` so a newly created file is listed individually
|
|
98
|
+
* instead of being collapsed into a single `?? dir/` entry.
|
|
99
|
+
*
|
|
100
|
+
* Records HEAD and the branch alongside the paths, so an agent that commits or switches refs
|
|
101
|
+
* is caught even when no file ends up looking different.
|
|
102
|
+
*/
|
|
103
|
+
export declare function snapshotTree(workspaceRoot: string): TreeSnapshot;
|
|
104
|
+
/** One root `.gitignore` rule, compiled. Negations are not supported (see readRootIgnore). */
|
|
105
|
+
export interface IgnoreRule {
|
|
106
|
+
regex: RegExp;
|
|
107
|
+
directoryOnly: boolean;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Compile the root `.gitignore` for walks outside git (the non-empty-repo rule and the
|
|
111
|
+
* filesystem snapshot). Only the common subset is honoured (names, `*`/`?`/`**` globs,
|
|
112
|
+
* anchored and directory-only patterns); `!` negations are skipped, and a `**` between
|
|
113
|
+
* two path segments can match more than git would, so a walk may ignore more than git,
|
|
114
|
+
* never less.
|
|
115
|
+
*/
|
|
116
|
+
export declare function readRootIgnore(root: string): IgnoreRule[];
|
|
117
|
+
export declare function isIgnored(rel: string, isDirectory: boolean, rules: IgnoreRule[]): boolean;
|
|
118
|
+
/** Directories the filesystem walk never enters. */
|
|
119
|
+
export declare const FILESYSTEM_WALK_SKIPPED: string[];
|
|
120
|
+
/** How many files the filesystem walk hashes before it gives up and reports `truncated`. */
|
|
121
|
+
export declare const FILESYSTEM_WALK_LIMIT = 50000;
|
|
122
|
+
/**
|
|
123
|
+
* Snapshot a directory that is not a git work tree: every file's content hash, keyed by its
|
|
124
|
+
* root-relative path with forward slashes.
|
|
125
|
+
*
|
|
126
|
+
* The same scope as the git snapshot: paths the root `.gitignore` ignores are not watched
|
|
127
|
+
* (they never reach a commit), and `.git/` and `node_modules/` are always skipped. Past
|
|
128
|
+
* `limit` files the walk stops and marks the snapshot `truncated`, so a caller can say its
|
|
129
|
+
* detection was partial instead of hashing an unbounded tree.
|
|
130
|
+
*/
|
|
131
|
+
export declare function snapshotFilesystem(root: string, limit?: number): TreeSnapshot;
|
|
132
|
+
/**
|
|
133
|
+
* A fingerprint of the git index: SHA-256 of `git ls-files --stage -z`, or null when git
|
|
134
|
+
* cannot answer.
|
|
135
|
+
*
|
|
136
|
+
* Porcelain status codes plus working-tree hashes cannot see a re-stage of an already
|
|
137
|
+
* staged path (`AM` before and after, working file unchanged), so the index needs its own
|
|
138
|
+
* witness. The staged blob ids are in this listing; their contents are not needed.
|
|
139
|
+
*/
|
|
140
|
+
export declare function readIndexFingerprint(workspaceRoot: string): string | null;
|
|
141
|
+
/**
|
|
142
|
+
* Paths that differ between two snapshots, sorted, skipping those `isExempt` claims.
|
|
143
|
+
*
|
|
144
|
+
* Returns nothing when either snapshot is unavailable: the caller reports that separately,
|
|
145
|
+
* because "could not look" is not "nothing changed".
|
|
146
|
+
*/
|
|
147
|
+
export declare function diffSnapshotEntries(before: TreeSnapshot, after: TreeSnapshot, isExempt?: (rel: string) => boolean): string[];
|
|
148
|
+
/** One field of the repository's identity that moved between two snapshots. */
|
|
149
|
+
export interface IdentityChange {
|
|
150
|
+
field: 'HEAD' | 'branch';
|
|
151
|
+
before: string;
|
|
152
|
+
after: string;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Repository identity fields that differ between two snapshots.
|
|
156
|
+
*
|
|
157
|
+
* A field that was unreadable at either end is skipped rather than reported as a change:
|
|
158
|
+
* "we could not tell" and "it moved" are different claims, and only one of them is evidence.
|
|
159
|
+
* An unborn branch's missing HEAD is not unreadable; it is compared as `(no commits)`.
|
|
160
|
+
*/
|
|
161
|
+
export declare function diffRepositoryIdentity(before: TreeSnapshot, after: TreeSnapshot): IdentityChange[];
|
|
162
|
+
/**
|
|
163
|
+
* Render a string safe to print to a terminal.
|
|
164
|
+
*
|
|
165
|
+
* Path names are bytes, and almost anything that is not `/` or NUL is legal in one —
|
|
166
|
+
* including newlines and ESC. Printing such a name raw lets it forge the rest of a report:
|
|
167
|
+
* a file called `\n - harmless.ts` adds a line to the list, and one containing a CSI
|
|
168
|
+
* sequence can repaint or erase what is above it. C0, DEL and C1 are escaped; ordinary
|
|
169
|
+
* Unicode is left alone.
|
|
170
|
+
*/
|
|
171
|
+
export declare function escapeControlChars(value: string): string;
|
|
172
|
+
//# sourceMappingURL=tree-snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-snapshot.d.ts","sourceRoot":"","sources":["../../src/lib/tree-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAOH;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,qDAAqD;IACrD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,8FAA8F;IAC9F,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAWD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,kBAAkB,CAatE;AAmCD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,UAAgB,CAAC;AAEpD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUjD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY,CA8DhE;AAMD,8FAA8F;AAC9F,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;CACxB;AAqBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,CAgBzD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,OAAO,CAEzF;AAED,oDAAoD;AACpD,eAAO,MAAM,uBAAuB,UAA2B,CAAC;AAEhE,4FAA4F;AAC5F,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAE5C;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAA8B,GAAG,YAAY,CA+BpG;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAazE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,YAAY,EACnB,QAAQ,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAqB,GAC/C,MAAM,EAAE,CAaV;AAKD,+EAA+E;AAC/E,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,cAAc,EAAE,CAqBlG;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUxD"}
|