@senior-skills/core 1.0.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.
- package/dist/application/agent-selection.d.ts +42 -0
- package/dist/application/agent-selection.d.ts.map +1 -0
- package/dist/application/agent-selection.js +143 -0
- package/dist/application/agent-selection.js.map +1 -0
- package/dist/application/apply-skill-updates.d.ts +10 -0
- package/dist/application/apply-skill-updates.d.ts.map +1 -0
- package/dist/application/apply-skill-updates.js +75 -0
- package/dist/application/apply-skill-updates.js.map +1 -0
- package/dist/application/check-updates.d.ts +40 -0
- package/dist/application/check-updates.d.ts.map +1 -0
- package/dist/application/check-updates.js +130 -0
- package/dist/application/check-updates.js.map +1 -0
- package/dist/application/context.d.ts +28 -0
- package/dist/application/context.d.ts.map +1 -0
- package/dist/application/context.js +2 -0
- package/dist/application/context.js.map +1 -0
- package/dist/application/create-skill.d.ts +33 -0
- package/dist/application/create-skill.d.ts.map +1 -0
- package/dist/application/create-skill.js +58 -0
- package/dist/application/create-skill.js.map +1 -0
- package/dist/application/diagnose.d.ts +44 -0
- package/dist/application/diagnose.d.ts.map +1 -0
- package/dist/application/diagnose.js +228 -0
- package/dist/application/diagnose.js.map +1 -0
- package/dist/application/install-skills.d.ts +59 -0
- package/dist/application/install-skills.d.ts.map +1 -0
- package/dist/application/install-skills.js +191 -0
- package/dist/application/install-skills.js.map +1 -0
- package/dist/application/list-installed.d.ts +39 -0
- package/dist/application/list-installed.d.ts.map +1 -0
- package/dist/application/list-installed.js +68 -0
- package/dist/application/list-installed.js.map +1 -0
- package/dist/application/package-loader.d.ts +42 -0
- package/dist/application/package-loader.d.ts.map +1 -0
- package/dist/application/package-loader.js +320 -0
- package/dist/application/package-loader.js.map +1 -0
- package/dist/application/publish-skill.d.ts +41 -0
- package/dist/application/publish-skill.d.ts.map +1 -0
- package/dist/application/publish-skill.js +112 -0
- package/dist/application/publish-skill.js.map +1 -0
- package/dist/application/remove-skills.d.ts +34 -0
- package/dist/application/remove-skills.d.ts.map +1 -0
- package/dist/application/remove-skills.js +95 -0
- package/dist/application/remove-skills.js.map +1 -0
- package/dist/application/resolution-source.d.ts +25 -0
- package/dist/application/resolution-source.d.ts.map +1 -0
- package/dist/application/resolution-source.js +60 -0
- package/dist/application/resolution-source.js.map +1 -0
- package/dist/application/resolve-suggestions.d.ts +17 -0
- package/dist/application/resolve-suggestions.d.ts.map +1 -0
- package/dist/application/resolve-suggestions.js +77 -0
- package/dist/application/resolve-suggestions.js.map +1 -0
- package/dist/application/search-skills.d.ts +36 -0
- package/dist/application/search-skills.d.ts.map +1 -0
- package/dist/application/search-skills.js +78 -0
- package/dist/application/search-skills.js.map +1 -0
- package/dist/application/update-skills.d.ts +55 -0
- package/dist/application/update-skills.d.ts.map +1 -0
- package/dist/application/update-skills.js +115 -0
- package/dist/application/update-skills.js.map +1 -0
- package/dist/application/validate-package.d.ts +27 -0
- package/dist/application/validate-package.d.ts.map +1 -0
- package/dist/application/validate-package.js +165 -0
- package/dist/application/validate-package.js.map +1 -0
- package/dist/application/workspace.d.ts +22 -0
- package/dist/application/workspace.d.ts.map +1 -0
- package/dist/application/workspace.js +66 -0
- package/dist/application/workspace.js.map +1 -0
- package/dist/domain/agent.d.ts +89 -0
- package/dist/domain/agent.d.ts.map +1 -0
- package/dist/domain/agent.js +20 -0
- package/dist/domain/agent.js.map +1 -0
- package/dist/domain/errors.d.ts +91 -0
- package/dist/domain/errors.d.ts.map +1 -0
- package/dist/domain/errors.js +121 -0
- package/dist/domain/errors.js.map +1 -0
- package/dist/domain/integrity.d.ts +19 -0
- package/dist/domain/integrity.d.ts.map +1 -0
- package/dist/domain/integrity.js +0 -0
- package/dist/domain/integrity.js.map +1 -0
- package/dist/domain/js-literal.d.ts +22 -0
- package/dist/domain/js-literal.d.ts.map +1 -0
- package/dist/domain/js-literal.js +221 -0
- package/dist/domain/js-literal.js.map +1 -0
- package/dist/domain/lockfile.d.ts +36 -0
- package/dist/domain/lockfile.d.ts.map +1 -0
- package/dist/domain/lockfile.js +148 -0
- package/dist/domain/lockfile.js.map +1 -0
- package/dist/domain/manifest.d.ts +96 -0
- package/dist/domain/manifest.d.ts.map +1 -0
- package/dist/domain/manifest.js +448 -0
- package/dist/domain/manifest.js.map +1 -0
- package/dist/domain/path-safety.d.ts +19 -0
- package/dist/domain/path-safety.d.ts.map +1 -0
- package/dist/domain/path-safety.js +125 -0
- package/dist/domain/path-safety.js.map +1 -0
- package/dist/domain/posix-path.d.ts +28 -0
- package/dist/domain/posix-path.d.ts.map +1 -0
- package/dist/domain/posix-path.js +84 -0
- package/dist/domain/posix-path.js.map +1 -0
- package/dist/domain/receipt.d.ts +41 -0
- package/dist/domain/receipt.d.ts.map +1 -0
- package/dist/domain/receipt.js +93 -0
- package/dist/domain/receipt.js.map +1 -0
- package/dist/domain/registry-index.d.ts +41 -0
- package/dist/domain/registry-index.d.ts.map +1 -0
- package/dist/domain/registry-index.js +150 -0
- package/dist/domain/registry-index.js.map +1 -0
- package/dist/domain/resolver.d.ts +54 -0
- package/dist/domain/resolver.d.ts.map +1 -0
- package/dist/domain/resolver.js +238 -0
- package/dist/domain/resolver.js.map +1 -0
- package/dist/domain/skill-document.d.ts +16 -0
- package/dist/domain/skill-document.d.ts.map +1 -0
- package/dist/domain/skill-document.js +60 -0
- package/dist/domain/skill-document.js.map +1 -0
- package/dist/domain/skill-package.d.ts +43 -0
- package/dist/domain/skill-package.d.ts.map +1 -0
- package/dist/domain/skill-package.js +63 -0
- package/dist/domain/skill-package.js.map +1 -0
- package/dist/domain/skill-ref.d.ts +30 -0
- package/dist/domain/skill-ref.d.ts.map +1 -0
- package/dist/domain/skill-ref.js +119 -0
- package/dist/domain/skill-ref.js.map +1 -0
- package/dist/domain/validation.d.ts +30 -0
- package/dist/domain/validation.d.ts.map +1 -0
- package/dist/domain/validation.js +32 -0
- package/dist/domain/validation.js.map +1 -0
- package/dist/domain/version.d.ts +23 -0
- package/dist/domain/version.d.ts.map +1 -0
- package/dist/domain/version.js +81 -0
- package/dist/domain/version.js.map +1 -0
- package/dist/domain/workflow-document.d.ts +23 -0
- package/dist/domain/workflow-document.d.ts.map +1 -0
- package/dist/domain/workflow-document.js +56 -0
- package/dist/domain/workflow-document.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/ports/agent-adapter.d.ts +65 -0
- package/dist/ports/agent-adapter.d.ts.map +1 -0
- package/dist/ports/agent-adapter.js +28 -0
- package/dist/ports/agent-adapter.js.map +1 -0
- package/dist/ports/config-store.d.ts +27 -0
- package/dist/ports/config-store.d.ts.map +1 -0
- package/dist/ports/config-store.js +2 -0
- package/dist/ports/config-store.js.map +1 -0
- package/dist/ports/infrastructure.d.ts +123 -0
- package/dist/ports/infrastructure.d.ts.map +1 -0
- package/dist/ports/infrastructure.js +9 -0
- package/dist/ports/infrastructure.js.map +1 -0
- package/dist/ports/installation.d.ts +86 -0
- package/dist/ports/installation.d.ts.map +1 -0
- package/dist/ports/installation.js +2 -0
- package/dist/ports/installation.js.map +1 -0
- package/dist/ports/skill-registry.d.ts +74 -0
- package/dist/ports/skill-registry.d.ts.map +1 -0
- package/dist/ports/skill-registry.js +2 -0
- package/dist/ports/skill-registry.js.map +1 -0
- package/dist/ports/updates.d.ts +31 -0
- package/dist/ports/updates.d.ts.map +1 -0
- package/dist/ports/updates.js +4 -0
- package/dist/ports/updates.js.map +1 -0
- package/dist/testing/doubles.d.ts +127 -0
- package/dist/testing/doubles.d.ts.map +1 -0
- package/dist/testing/doubles.js +299 -0
- package/dist/testing/doubles.js.map +1 -0
- package/dist/testing/in-memory-file-system.d.ts +61 -0
- package/dist/testing/in-memory-file-system.d.ts.map +1 -0
- package/dist/testing/in-memory-file-system.js +297 -0
- package/dist/testing/in-memory-file-system.js.map +1 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +10 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { AgentSkillsError, ErrorCode } from "../domain/errors.js";
|
|
2
|
+
import { classifyChange } from "../domain/version.js";
|
|
3
|
+
import { selectAgents } from "./agent-selection.js";
|
|
4
|
+
import { InstallSkills } from "./install-skills.js";
|
|
5
|
+
/**
|
|
6
|
+
* Update: detect current → resolve newest compatible → install atomically → report the diff.
|
|
7
|
+
*
|
|
8
|
+
* Implemented on top of {@link InstallSkills} rather than beside it. The install pipeline
|
|
9
|
+
* already does fetch/verify/validate/atomic-commit correctly; duplicating it here would mean
|
|
10
|
+
* two places to keep safe.
|
|
11
|
+
*/
|
|
12
|
+
export class UpdateSkills {
|
|
13
|
+
ctx;
|
|
14
|
+
constructor(ctx) {
|
|
15
|
+
this.ctx = ctx;
|
|
16
|
+
}
|
|
17
|
+
async execute(options) {
|
|
18
|
+
if (options.withSuggests === true && options.names.length === 0) {
|
|
19
|
+
throw new AgentSkillsError(ErrorCode.USAGE, '--with-suggests requires explicit skill names for update', {
|
|
20
|
+
hints: ['senior-skills update <skill> --with-suggests'],
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const selection = await selectAgents(this.ctx, {
|
|
24
|
+
scope: options.scope,
|
|
25
|
+
...(options.agents === undefined ? {} : { agents: options.agents }),
|
|
26
|
+
...(options.projectRoot === undefined ? {} : { projectRoot: options.projectRoot }),
|
|
27
|
+
...(options.startDir === undefined ? {} : { startDir: options.startDir }),
|
|
28
|
+
});
|
|
29
|
+
const current = new Map();
|
|
30
|
+
for (const target of selection.targets) {
|
|
31
|
+
for (const skill of await this.ctx.installer.list(target)) {
|
|
32
|
+
if (skill.unmanaged)
|
|
33
|
+
continue;
|
|
34
|
+
const known = current.get(skill.name);
|
|
35
|
+
// When agents disagree, the oldest wins: updating brings every agent forward.
|
|
36
|
+
if (known === undefined || classifyChange(skill.version, known) !== 'downgrade') {
|
|
37
|
+
current.set(skill.name, skill.version);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const names = options.names.length > 0 ? options.names : [...current.keys()].sort();
|
|
42
|
+
if (names.length === 0) {
|
|
43
|
+
throw new AgentSkillsError(ErrorCode.NOT_INSTALLED, 'Nothing to update', {
|
|
44
|
+
details: [
|
|
45
|
+
'',
|
|
46
|
+
'No senior-skills-managed skills were found in:',
|
|
47
|
+
...selection.targets.map((target) => ` ${target.displayName} (${target.scope}): ${target.root}`),
|
|
48
|
+
],
|
|
49
|
+
hints: ['senior-skills install <skill> to install one'],
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
for (const name of names) {
|
|
53
|
+
if (current.has(name))
|
|
54
|
+
continue;
|
|
55
|
+
throw new AgentSkillsError(ErrorCode.NOT_INSTALLED, `"${name}" is not installed`, {
|
|
56
|
+
hints: [`senior-skills install ${name}`, 'senior-skills list'],
|
|
57
|
+
data: { name },
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
// `^current` keeps update within the major by default; `--major` opens it up.
|
|
61
|
+
const refs = names.map((name) => {
|
|
62
|
+
const version = current.get(name);
|
|
63
|
+
return options.major === true ? `${name}@latest` : `${name}@^${version}`;
|
|
64
|
+
});
|
|
65
|
+
const install = await new InstallSkills(this.ctx).execute({
|
|
66
|
+
refs,
|
|
67
|
+
scope: options.scope,
|
|
68
|
+
...(options.agents === undefined ? {} : { agents: options.agents }),
|
|
69
|
+
...(options.projectRoot === undefined ? {} : { projectRoot: options.projectRoot }),
|
|
70
|
+
...(options.startDir === undefined ? {} : { startDir: options.startDir }),
|
|
71
|
+
...(options.registry === undefined ? {} : { registry: options.registry }),
|
|
72
|
+
...(options.dryRun === undefined ? {} : { dryRun: options.dryRun }),
|
|
73
|
+
force: options.force === true,
|
|
74
|
+
...(options.withSuggests === true
|
|
75
|
+
? {
|
|
76
|
+
withSuggests: true,
|
|
77
|
+
suggestedVersionRanges: Object.fromEntries([...current].map(([name, version]) => [
|
|
78
|
+
name,
|
|
79
|
+
options.major === true ? 'latest' : `^${version}`,
|
|
80
|
+
])),
|
|
81
|
+
}
|
|
82
|
+
: {}),
|
|
83
|
+
});
|
|
84
|
+
const changes = [];
|
|
85
|
+
const additions = [];
|
|
86
|
+
const unchanged = [];
|
|
87
|
+
for (const skill of install.resolved) {
|
|
88
|
+
const from = current.get(skill.name);
|
|
89
|
+
const results = install.results.filter((result) => result.name === skill.name && (from === undefined || result.outcome === 'installed'));
|
|
90
|
+
if (from === undefined || results.length > 0) {
|
|
91
|
+
additions.push({
|
|
92
|
+
name: skill.name,
|
|
93
|
+
version: skill.version,
|
|
94
|
+
suggestedBy: skill.suggestedBy ?? [],
|
|
95
|
+
results,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (from === undefined) {
|
|
99
|
+
// Keep the existing changes representation for JSON consumers; additions carry
|
|
100
|
+
// the explicit new-package plan, including skipped destinations and provenance.
|
|
101
|
+
changes.push({ name: skill.name, from: skill.version, to: skill.version, bump: 'same' });
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const bump = classifyChange(from, skill.version);
|
|
105
|
+
if (bump === 'same') {
|
|
106
|
+
unchanged.push(skill.name);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
changes.push({ name: skill.name, from, to: skill.version, bump });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { changes, additions, unchanged, install };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=update-skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-skills.js","sourceRoot":"","sources":["../../src/application/update-skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SkillPackage } from '../domain/skill-package.ts';
|
|
2
|
+
import { type ValidationIssue, type ValidationReport } from '../domain/validation.ts';
|
|
3
|
+
import type { AgentAdapter } from '../ports/agent-adapter.ts';
|
|
4
|
+
import { type LoadPackageOptions } from './package-loader.ts';
|
|
5
|
+
import type { ApplicationContext } from './context.ts';
|
|
6
|
+
export interface ValidatePackageOptions extends LoadPackageOptions {
|
|
7
|
+
/** Directory name to compare against the manifest name, when validating from disk. */
|
|
8
|
+
readonly directoryName?: string;
|
|
9
|
+
/** Adapters whose agent-specific rules should also run. */
|
|
10
|
+
readonly adapters?: readonly AgentAdapter[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Validates an already-loaded package.
|
|
14
|
+
*
|
|
15
|
+
* Reports every problem it can find rather than throwing on the first: an author fixing a
|
|
16
|
+
* package wants the whole list, and `install` wants to distinguish "unusable" from
|
|
17
|
+
* "imperfect".
|
|
18
|
+
*/
|
|
19
|
+
export declare function validatePackage(pkg: SkillPackage, options?: ValidatePackageOptions): ValidationReport;
|
|
20
|
+
export declare function pathSafetyIssues(path: string): readonly ValidationIssue[];
|
|
21
|
+
export interface ValidateDirectoryResult extends ValidationReport {
|
|
22
|
+
readonly pkg: SkillPackage;
|
|
23
|
+
readonly directory: string;
|
|
24
|
+
}
|
|
25
|
+
/** Loads a package from disk and validates it. The `validate` command in one call. */
|
|
26
|
+
export declare function validateDirectory(ctx: ApplicationContext, directory: string, options?: ValidatePackageOptions): Promise<ValidateDirectoryResult>;
|
|
27
|
+
//# sourceMappingURL=validate-package.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-package.d.ts","sourceRoot":"","sources":["../../src/application/validate-package.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,WAAW,sBAAuB,SAAQ,kBAAkB;IAChE,sFAAsF;IACtF,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CAC7C;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,YAAY,EACjB,OAAO,GAAE,sBAA2B,GACnC,gBAAgB,CAkLlB;AAqBD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,eAAe,EAAE,CAazE;AAED,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC/D,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,sFAAsF;AACtF,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,kBAAkB,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,uBAAuB,CAAC,CAUlC"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { MANIFEST_FILENAME, entrypointFor } from "../domain/manifest.js";
|
|
2
|
+
import { inspectPath } from "../domain/path-safety.js";
|
|
3
|
+
import { normalize } from "../domain/posix-path.js";
|
|
4
|
+
import { documentDescription, documentName, documentVersion } from "../domain/skill-document.js";
|
|
5
|
+
import { IssueCollector, buildReport, } from "../domain/validation.js";
|
|
6
|
+
import { isSemanticVersion } from "../domain/version.js";
|
|
7
|
+
import { loadPackageFromDirectory } from "./package-loader.js";
|
|
8
|
+
/**
|
|
9
|
+
* Validates an already-loaded package.
|
|
10
|
+
*
|
|
11
|
+
* Reports every problem it can find rather than throwing on the first: an author fixing a
|
|
12
|
+
* package wants the whole list, and `install` wants to distinguish "unusable" from
|
|
13
|
+
* "imperfect".
|
|
14
|
+
*/
|
|
15
|
+
export function validatePackage(pkg, options = {}) {
|
|
16
|
+
const issues = new IssueCollector();
|
|
17
|
+
const { manifest, document } = pkg;
|
|
18
|
+
const entrypoint = entrypointFor(manifest.kind);
|
|
19
|
+
// A workflow declares its identity in `export const meta`, every other kind in YAML
|
|
20
|
+
// frontmatter. Only the wording differs; the rules are the same.
|
|
21
|
+
const holder = manifest.kind === 'workflow' ? 'meta' : 'frontmatter';
|
|
22
|
+
// --- Identity agreement -------------------------------------------------------------
|
|
23
|
+
const docName = documentName(document);
|
|
24
|
+
if (docName === undefined) {
|
|
25
|
+
issues.error('skill.name.missing', entrypoint, `${capitalise(holder)} is missing "name"`, `Add name: "${manifest.name}" to the ${entrypoint} ${holder}`);
|
|
26
|
+
}
|
|
27
|
+
else if (docName !== manifest.name) {
|
|
28
|
+
issues.error('skill.name.mismatch', entrypoint, `${capitalise(holder)} name "${docName}" does not match manifest name "${manifest.name}"`, 'Both files and the directory name must agree');
|
|
29
|
+
}
|
|
30
|
+
if (options.directoryName !== undefined && options.directoryName !== manifest.name) {
|
|
31
|
+
issues.error('package.directory.mismatch', options.directoryName, `Directory is named "${options.directoryName}" but the ${manifest.kind} is named "${manifest.name}"`, `Rename the directory to "${manifest.name}"`);
|
|
32
|
+
}
|
|
33
|
+
const docVersion = documentVersion(document);
|
|
34
|
+
if (docVersion !== undefined) {
|
|
35
|
+
if (!isSemanticVersion(docVersion)) {
|
|
36
|
+
issues.error('skill.version.invalid', entrypoint, `${capitalise(holder)} version "${docVersion}" is not valid semver`);
|
|
37
|
+
}
|
|
38
|
+
else if (docVersion !== manifest.version) {
|
|
39
|
+
issues.error('skill.version.mismatch', entrypoint, `${capitalise(holder)} version "${docVersion}" does not match manifest version "${manifest.version}"`, `Keep them in sync, or drop the version from the ${holder}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const docDescription = documentDescription(document);
|
|
43
|
+
if (docDescription === undefined || docDescription === '') {
|
|
44
|
+
issues.error('skill.description.missing', entrypoint, `${capitalise(holder)} is missing "description"`, manifest.kind === 'workflow'
|
|
45
|
+
? 'It is what search and info show for the workflow; it is required'
|
|
46
|
+
: 'Both Claude Code and Codex route on the description; it is required');
|
|
47
|
+
}
|
|
48
|
+
else if (collapse(docDescription) !== collapse(manifest.description)) {
|
|
49
|
+
// Adapters project the *manifest* description into the installed entrypoint, and the
|
|
50
|
+
// registry index carries only the manifest description. A divergent frontmatter one is
|
|
51
|
+
// therefore text no agent ever reads — including any trigger or boundary clause an
|
|
52
|
+
// author added there, which is how routing degrades silently.
|
|
53
|
+
//
|
|
54
|
+
// A warning and not an error: the package installs and works, so refusing it would be
|
|
55
|
+
// disproportionate. A registry that wants the stronger guarantee enforces it at index
|
|
56
|
+
// build time, where it can see its own packages — this repository does exactly that.
|
|
57
|
+
issues.warn('skill.description.mismatch', entrypoint, `${capitalise(holder)} description does not match the manifest description`, `Only the manifest description ships; make them identical, or edit ${MANIFEST_FILENAME} instead`);
|
|
58
|
+
}
|
|
59
|
+
// --- Body ---------------------------------------------------------------------------
|
|
60
|
+
if (document.body.trim().length < 40) {
|
|
61
|
+
issues.warn('skill.body.thin', entrypoint, manifest.kind === 'workflow'
|
|
62
|
+
? 'The script body is nearly empty'
|
|
63
|
+
: 'The Markdown body is nearly empty', manifest.kind === 'workflow'
|
|
64
|
+
? 'The body is the script the agent runs; meta alone does nothing'
|
|
65
|
+
: 'The body is what the agent loads once the package is selected');
|
|
66
|
+
}
|
|
67
|
+
// --- Declared files exist ------------------------------------------------------------
|
|
68
|
+
const present = new Set(pkg.files.map((file) => file.path));
|
|
69
|
+
for (const declared of manifest.files) {
|
|
70
|
+
const relative = normalize(declared.replace(/\/+$/, ''));
|
|
71
|
+
const isDirectory = declared.endsWith('/');
|
|
72
|
+
const satisfied = isDirectory
|
|
73
|
+
? [...present].some((path) => path === relative || path.startsWith(`${relative}/`))
|
|
74
|
+
: present.has(relative);
|
|
75
|
+
if (!satisfied) {
|
|
76
|
+
issues.warn('package.files.missing', MANIFEST_FILENAME, `"${declared}" is declared in files but is not present`, 'Remove it from files, or add the file');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!present.has(entrypoint)) {
|
|
80
|
+
issues.error('package.entrypoint.missing', entrypoint, `Package has no ${entrypoint}`);
|
|
81
|
+
}
|
|
82
|
+
if (!present.has(MANIFEST_FILENAME)) {
|
|
83
|
+
issues.error('package.manifest.missing', MANIFEST_FILENAME, `Package has no ${MANIFEST_FILENAME}`);
|
|
84
|
+
}
|
|
85
|
+
// --- Path safety for every shipped file ----------------------------------------------
|
|
86
|
+
for (const file of pkg.files) {
|
|
87
|
+
issues.absorb(pathSafetyIssues(file.path));
|
|
88
|
+
}
|
|
89
|
+
// --- agentOverrides are allowlisted by the adapter that consumes them ------------------
|
|
90
|
+
const adapters = options.adapters ?? [];
|
|
91
|
+
for (const [agentId, override] of Object.entries(manifest.agentOverrides)) {
|
|
92
|
+
const adapter = adapters.find((candidate) => candidate.id === agentId);
|
|
93
|
+
if (adapters.length > 0 && adapter === undefined) {
|
|
94
|
+
issues.warn('manifest.agentOverrides.unknownAgent', `agentOverrides.${agentId}`, `No adapter is registered for agent "${agentId}"`, 'The override will be ignored');
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (adapter === undefined)
|
|
98
|
+
continue;
|
|
99
|
+
for (const key of Object.keys(override)) {
|
|
100
|
+
if (adapter.overrideKeys.includes(key))
|
|
101
|
+
continue;
|
|
102
|
+
issues.error('manifest.agentOverrides.unknownKey', `agentOverrides.${agentId}.${key}`, `Agent "${agentId}" does not accept the override key "${key}"`, `Accepted keys: ${adapter.overrideKeys.join(', ') || '(none)'}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// --- Declared compatibility refers to agents we know ----------------------------------
|
|
106
|
+
if (adapters.length > 0) {
|
|
107
|
+
for (const compatibility of manifest.compatibility) {
|
|
108
|
+
if (adapters.some((adapter) => adapter.id === compatibility.id))
|
|
109
|
+
continue;
|
|
110
|
+
issues.warn('manifest.compatibility.unknownAgent', `compatibility.agents.${compatibility.id}`, `Unknown agent id "${compatibility.id}"`, `Known: ${adapters.map((adapter) => adapter.id).join(', ')}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// --- Agent-specific rules -------------------------------------------------------------
|
|
114
|
+
for (const adapter of adapters) {
|
|
115
|
+
if (manifest.compatibility.length > 0 &&
|
|
116
|
+
!manifest.compatibility.some((entry) => entry.id === adapter.id)) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
issues.absorb(adapter.validate(pkg));
|
|
120
|
+
}
|
|
121
|
+
return issues.report();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Reports path-safety violations as validation issues.
|
|
125
|
+
*
|
|
126
|
+
* The rules themselves live in `domain/path-safety.ts`, shared with the installer's
|
|
127
|
+
* extractor, so a package that `validate` accepts can never be one the extractor rejects.
|
|
128
|
+
*/
|
|
129
|
+
function capitalise(value) {
|
|
130
|
+
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Normalises whitespace before comparing two descriptions. A folded YAML scalar (`>`) and a
|
|
134
|
+
* quoted one carry the same text with different line breaks, and that difference is not a
|
|
135
|
+
* mismatch anybody needs to hear about.
|
|
136
|
+
*/
|
|
137
|
+
function collapse(value) {
|
|
138
|
+
return value.replace(/\s+/g, ' ').trim();
|
|
139
|
+
}
|
|
140
|
+
export function pathSafetyIssues(path) {
|
|
141
|
+
const violation = inspectPath(path);
|
|
142
|
+
if (violation === undefined)
|
|
143
|
+
return [];
|
|
144
|
+
return [
|
|
145
|
+
{
|
|
146
|
+
severity: 'error',
|
|
147
|
+
rule: `path.${violation.rule}`,
|
|
148
|
+
at: path,
|
|
149
|
+
message: violation.message,
|
|
150
|
+
hint: 'Rename the file so it is safe on every platform',
|
|
151
|
+
},
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
/** Loads a package from disk and validates it. The `validate` command in one call. */
|
|
155
|
+
export async function validateDirectory(ctx, directory, options = {}) {
|
|
156
|
+
const loaded = await loadPackageFromDirectory(ctx.fs, directory, options);
|
|
157
|
+
const report = validatePackage(loaded.pkg, {
|
|
158
|
+
...options,
|
|
159
|
+
directoryName: options.directoryName ?? ctx.fs.basename(loaded.directory),
|
|
160
|
+
adapters: options.adapters ?? ctx.agents.all(),
|
|
161
|
+
});
|
|
162
|
+
const combined = buildReport([...loaded.issues, ...report.issues]);
|
|
163
|
+
return { ...combined, pkg: loaded.pkg, directory: loaded.directory };
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=validate-package.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-package.js","sourceRoot":"","sources":["../../src/application/validate-package.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Lockfile } from '../domain/lockfile.ts';
|
|
2
|
+
import type { SemanticVersion } from '../domain/version.ts';
|
|
3
|
+
import type { FileSystem } from '../ports/infrastructure.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Walks up from `start` looking for a project marker.
|
|
6
|
+
*
|
|
7
|
+
* Returns `undefined` rather than defaulting to the cwd: silently treating an arbitrary
|
|
8
|
+
* directory as a project is how tools end up scattering `.claude/` folders around a filesystem.
|
|
9
|
+
*
|
|
10
|
+
* The home directory is never a project, and the walk stops there. `~/.claude` and `~/.codex`
|
|
11
|
+
* are an agent's *global* configuration; treating them as project markers would make every
|
|
12
|
+
* command run from anywhere under `$HOME` — a scratch directory, a temp folder — resolve
|
|
13
|
+
* "project scope" to the user's home and install into their global configuration by accident.
|
|
14
|
+
*/
|
|
15
|
+
export declare function findProjectRoot(fs: FileSystem, start: string, homeDir?: string): Promise<string | undefined>;
|
|
16
|
+
export declare function requireProjectRoot(fs: FileSystem, start: string, homeDir?: string): Promise<string>;
|
|
17
|
+
export declare function lockfilePath(fs: FileSystem, projectRoot: string): string;
|
|
18
|
+
export declare function readLockfile(fs: FileSystem, projectRoot: string): Promise<Lockfile>;
|
|
19
|
+
export declare function writeLockfile(fs: FileSystem, projectRoot: string, lock: Lockfile): Promise<void>;
|
|
20
|
+
/** Version pins from the lockfile, in the shape the resolver expects. */
|
|
21
|
+
export declare function pinsFrom(lock: Lockfile): Record<string, SemanticVersion>;
|
|
22
|
+
//# sourceMappingURL=workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/application/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAS7D;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAa7B;AAED,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAExE;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAIzF;AAED,wBAAsB,aAAa,CACjC,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,yEAAyE;AACzE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAIxE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { LOCKFILE_NAME, emptyLockfile, parseLockfile, stringifyLockfile, } from "../domain/lockfile.js";
|
|
2
|
+
import { AgentSkillsError, ErrorCode } from "../domain/errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* Markers that make a directory "a project". `.git` is the usual answer; the others let the
|
|
5
|
+
* tool work in a checkout that is not a git repository, or in a subdirectory of one that has
|
|
6
|
+
* its own agent configuration.
|
|
7
|
+
*/
|
|
8
|
+
const PROJECT_MARKERS = [LOCKFILE_NAME, '.git', '.claude', '.agents', '.codex'];
|
|
9
|
+
/**
|
|
10
|
+
* Walks up from `start` looking for a project marker.
|
|
11
|
+
*
|
|
12
|
+
* Returns `undefined` rather than defaulting to the cwd: silently treating an arbitrary
|
|
13
|
+
* directory as a project is how tools end up scattering `.claude/` folders around a filesystem.
|
|
14
|
+
*
|
|
15
|
+
* The home directory is never a project, and the walk stops there. `~/.claude` and `~/.codex`
|
|
16
|
+
* are an agent's *global* configuration; treating them as project markers would make every
|
|
17
|
+
* command run from anywhere under `$HOME` — a scratch directory, a temp folder — resolve
|
|
18
|
+
* "project scope" to the user's home and install into their global configuration by accident.
|
|
19
|
+
*/
|
|
20
|
+
export async function findProjectRoot(fs, start, homeDir) {
|
|
21
|
+
const home = homeDir === undefined ? undefined : fs.resolve(homeDir);
|
|
22
|
+
let current = fs.resolve(start);
|
|
23
|
+
for (;;) {
|
|
24
|
+
if (current === home)
|
|
25
|
+
return undefined;
|
|
26
|
+
for (const marker of PROJECT_MARKERS) {
|
|
27
|
+
if (await fs.exists(fs.join(current, marker)))
|
|
28
|
+
return current;
|
|
29
|
+
}
|
|
30
|
+
const parent = fs.dirname(current);
|
|
31
|
+
if (parent === current)
|
|
32
|
+
return undefined;
|
|
33
|
+
current = parent;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export async function requireProjectRoot(fs, start, homeDir) {
|
|
37
|
+
const root = await findProjectRoot(fs, start, homeDir);
|
|
38
|
+
if (root !== undefined)
|
|
39
|
+
return root;
|
|
40
|
+
throw new AgentSkillsError(ErrorCode.USAGE, 'Not inside a project', {
|
|
41
|
+
details: [`Looked for ${PROJECT_MARKERS.join(', ')} in ${start} and every parent directory.`],
|
|
42
|
+
hints: [
|
|
43
|
+
'Run the command from inside a project,',
|
|
44
|
+
'pass --project-root <path>,',
|
|
45
|
+
'or use --global to install into your user configuration',
|
|
46
|
+
],
|
|
47
|
+
data: { start },
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export function lockfilePath(fs, projectRoot) {
|
|
51
|
+
return fs.join(projectRoot, LOCKFILE_NAME);
|
|
52
|
+
}
|
|
53
|
+
export async function readLockfile(fs, projectRoot) {
|
|
54
|
+
const path = lockfilePath(fs, projectRoot);
|
|
55
|
+
if (!(await fs.exists(path)))
|
|
56
|
+
return emptyLockfile();
|
|
57
|
+
return parseLockfile(await fs.readTextFile(path), path);
|
|
58
|
+
}
|
|
59
|
+
export async function writeLockfile(fs, projectRoot, lock) {
|
|
60
|
+
await fs.writeFile(lockfilePath(fs, projectRoot), stringifyLockfile(lock));
|
|
61
|
+
}
|
|
62
|
+
/** Version pins from the lockfile, in the shape the resolver expects. */
|
|
63
|
+
export function pinsFrom(lock) {
|
|
64
|
+
return Object.fromEntries(Object.entries(lock.skills).map(([name, entry]) => [name, entry.version]));
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/application/workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { PackageKind } from './manifest.ts';
|
|
2
|
+
import type { SkillPackage } from './skill-package.ts';
|
|
3
|
+
/** Stable adapter identifier, e.g. `claude-code`, `codex`. Appears in receipts and lockfiles. */
|
|
4
|
+
export type AgentId = string;
|
|
5
|
+
/** `global` targets the user's home configuration; `project` targets a repository. */
|
|
6
|
+
export type InstallScope = 'global' | 'project';
|
|
7
|
+
export declare const INSTALL_SCOPES: readonly InstallScope[];
|
|
8
|
+
/** Everything an adapter may consult when computing a skill root. */
|
|
9
|
+
export interface LocationContext {
|
|
10
|
+
readonly homeDir: string;
|
|
11
|
+
readonly projectRoot?: string;
|
|
12
|
+
/** Raw environment, so an adapter can honour `$CODEX_HOME` or `$CLAUDE_CONFIG_DIR`. */
|
|
13
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
14
|
+
/** User override from config, e.g. `agents["codex"].globalRoot`. Wins over defaults. */
|
|
15
|
+
readonly overrideRoot?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* How one installed package appears inside an agent's root: a directory holding the
|
|
19
|
+
* package's files, or a single file named after the package. Claude Code skills are
|
|
20
|
+
* directories; its commands are `<name>.md` files.
|
|
21
|
+
*/
|
|
22
|
+
export type EntryShape = 'directory' | 'file';
|
|
23
|
+
/** Where and how one agent stores packages of one kind. */
|
|
24
|
+
export interface AgentLocation {
|
|
25
|
+
/** Absolute path of the directory holding every package of this kind. */
|
|
26
|
+
readonly root: string;
|
|
27
|
+
readonly shape: EntryShape;
|
|
28
|
+
/** Suffix appended to the package name for `file` shape, e.g. `.md`. Empty otherwise. */
|
|
29
|
+
readonly extension: string;
|
|
30
|
+
}
|
|
31
|
+
export type DetectionStrength = 'strong' | 'weak' | 'none';
|
|
32
|
+
export interface DetectionEvidence {
|
|
33
|
+
readonly strength: DetectionStrength;
|
|
34
|
+
/** Short machine-ish label, e.g. `config-dir`, `executable`, `project-dir`. */
|
|
35
|
+
readonly kind: string;
|
|
36
|
+
/** Human-readable location or explanation. */
|
|
37
|
+
readonly detail: string;
|
|
38
|
+
}
|
|
39
|
+
export interface AgentDetection {
|
|
40
|
+
readonly agentId: AgentId;
|
|
41
|
+
/** True when at least one piece of strong evidence was found. */
|
|
42
|
+
readonly installed: boolean;
|
|
43
|
+
readonly strength: DetectionStrength;
|
|
44
|
+
readonly evidence: readonly DetectionEvidence[];
|
|
45
|
+
/** Populated only when the agent reliably exposes a version. */
|
|
46
|
+
readonly version?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare function detectionFrom(agentId: AgentId, evidence: readonly DetectionEvidence[], version?: string): AgentDetection;
|
|
49
|
+
/**
|
|
50
|
+
* One file the adapter wants written into the installed skill directory.
|
|
51
|
+
* Either inline `content` (adapter-synthesised, e.g. Codex's `agents/openai.yaml`)
|
|
52
|
+
* or `copyFrom` (a path in the neutral package, copied verbatim).
|
|
53
|
+
*/
|
|
54
|
+
export type LayoutEntry = {
|
|
55
|
+
readonly path: string;
|
|
56
|
+
readonly content: Uint8Array;
|
|
57
|
+
readonly copyFrom?: undefined;
|
|
58
|
+
} | {
|
|
59
|
+
readonly path: string;
|
|
60
|
+
readonly copyFrom: string;
|
|
61
|
+
readonly content?: undefined;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* The projection of a neutral package onto one agent. Pure data: producing it must not
|
|
65
|
+
* touch the filesystem, which is what makes every adapter snapshot-testable.
|
|
66
|
+
*/
|
|
67
|
+
export interface AgentLayout {
|
|
68
|
+
/**
|
|
69
|
+
* Files to write. Paths are relative to the installed package directory; for a `file`
|
|
70
|
+
* shaped target there must be exactly one entry, and its path is unused because the
|
|
71
|
+
* installer names the file after the package.
|
|
72
|
+
*/
|
|
73
|
+
readonly entries: readonly LayoutEntry[];
|
|
74
|
+
/** Frontmatter the adapter wants in the installed entrypoint document. */
|
|
75
|
+
readonly frontmatter: Readonly<Record<string, unknown>>;
|
|
76
|
+
}
|
|
77
|
+
/** Convenience view used by `list`, `doctor` and the installer. */
|
|
78
|
+
export interface AgentTarget extends AgentLocation {
|
|
79
|
+
readonly agentId: AgentId;
|
|
80
|
+
readonly displayName: string;
|
|
81
|
+
readonly scope: InstallScope;
|
|
82
|
+
readonly kind: PackageKind;
|
|
83
|
+
}
|
|
84
|
+
/** Path of one installed package inside its root, for both entry shapes. */
|
|
85
|
+
export declare function entryNameFor(target: AgentLocation, name: string): string;
|
|
86
|
+
export interface AgentLayoutInput {
|
|
87
|
+
readonly pkg: SkillPackage;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/domain/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const INSTALL_SCOPES = ['global', 'project'];
|
|
2
|
+
export function detectionFrom(agentId, evidence, version) {
|
|
3
|
+
const strength = evidence.some((item) => item.strength === 'strong')
|
|
4
|
+
? 'strong'
|
|
5
|
+
: evidence.some((item) => item.strength === 'weak')
|
|
6
|
+
? 'weak'
|
|
7
|
+
: 'none';
|
|
8
|
+
return {
|
|
9
|
+
agentId,
|
|
10
|
+
installed: strength === 'strong',
|
|
11
|
+
strength,
|
|
12
|
+
evidence,
|
|
13
|
+
...(version === undefined ? {} : { version }),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Path of one installed package inside its root, for both entry shapes. */
|
|
17
|
+
export function entryNameFor(target, name) {
|
|
18
|
+
return `${name}${target.extension}`;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/domain/agent.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,cAAc,GAA4B,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAgD7E,MAAM,UAAU,aAAa,CAC3B,OAAgB,EAChB,QAAsC,EACtC,OAAgB;IAEhB,MAAM,QAAQ,GAAsB,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC;QACrF,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC;YACjD,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,MAAM,CAAC;IACb,OAAO;QACL,OAAO;QACP,SAAS,EAAE,QAAQ,KAAK,QAAQ;QAChC,QAAQ;QACR,QAAQ;QACR,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;KAC9C,CAAC;AACJ,CAAC;AAkCD,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAAC,MAAqB,EAAE,IAAY;IAC9D,OAAO,GAAG,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;AACtC,CAAC"}
|