squads 0.1.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/commands/add.d.ts +3 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +98 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/check.d.ts +3 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +127 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/find.d.ts +3 -0
- package/dist/commands/find.d.ts.map +1 -0
- package/dist/commands/find.js +84 -0
- package/dist/commands/find.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +281 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +49 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +129 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/publish.d.ts +3 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +118 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/remove.d.ts +3 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +67 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/update.d.ts +3 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +58 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts +3 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +116 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agents.d.ts +26 -0
- package/dist/lib/agents.d.ts.map +1 -0
- package/dist/lib/agents.js +87 -0
- package/dist/lib/agents.js.map +1 -0
- package/dist/lib/config.d.ts +9 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +44 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/installer.d.ts +29 -0
- package/dist/lib/installer.d.ts.map +1 -0
- package/dist/lib/installer.js +124 -0
- package/dist/lib/installer.js.map +1 -0
- package/dist/lib/lock-file.d.ts +11 -0
- package/dist/lib/lock-file.d.ts.map +1 -0
- package/dist/lib/lock-file.js +72 -0
- package/dist/lib/lock-file.js.map +1 -0
- package/dist/lib/sources/github.d.ts +26 -0
- package/dist/lib/sources/github.d.ts.map +1 -0
- package/dist/lib/sources/github.js +182 -0
- package/dist/lib/sources/github.js.map +1 -0
- package/dist/lib/sources/local.d.ts +15 -0
- package/dist/lib/sources/local.d.ts.map +1 -0
- package/dist/lib/sources/local.js +52 -0
- package/dist/lib/sources/local.js.map +1 -0
- package/dist/lib/sources/registry.d.ts +21 -0
- package/dist/lib/sources/registry.d.ts.map +1 -0
- package/dist/lib/sources/registry.js +63 -0
- package/dist/lib/sources/registry.js.map +1 -0
- package/dist/lib/telemetry.d.ts +6 -0
- package/dist/lib/telemetry.d.ts.map +1 -0
- package/dist/lib/telemetry.js +68 -0
- package/dist/lib/telemetry.js.map +1 -0
- package/dist/lib/validator.d.ts +29 -0
- package/dist/lib/validator.d.ts.map +1 -0
- package/dist/lib/validator.js +107 -0
- package/dist/lib/validator.js.map +1 -0
- package/dist/types.d.ts +86 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +47 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { createAddCommand } from "./commands/add.js";
|
|
5
|
+
import { createFindCommand } from "./commands/find.js";
|
|
6
|
+
import { createListCommand } from "./commands/list.js";
|
|
7
|
+
import { createCheckCommand } from "./commands/check.js";
|
|
8
|
+
import { createUpdateCommand } from "./commands/update.js";
|
|
9
|
+
import { createRemoveCommand } from "./commands/remove.js";
|
|
10
|
+
import { createInitCommand } from "./commands/init.js";
|
|
11
|
+
import { createPublishCommand } from "./commands/publish.js";
|
|
12
|
+
import { createValidateCommand } from "./commands/validate.js";
|
|
13
|
+
import { createLoginCommand } from "./commands/login.js";
|
|
14
|
+
const program = new Command();
|
|
15
|
+
program
|
|
16
|
+
.name("squads")
|
|
17
|
+
.description("CLI for squads.sh — Install and manage AIOS squads")
|
|
18
|
+
.version("0.1.0")
|
|
19
|
+
.addHelpText("after", `
|
|
20
|
+
${chalk.bold("Examples:")}
|
|
21
|
+
${chalk.dim("$")} squads add owner/repo Install a squad from GitHub
|
|
22
|
+
${chalk.dim("$")} squads add ./my-squad Install from local directory
|
|
23
|
+
${chalk.dim("$")} squads add design-system Install from squads.sh registry
|
|
24
|
+
${chalk.dim("$")} squads find code-review Search for squads
|
|
25
|
+
${chalk.dim("$")} squads list List installed squads
|
|
26
|
+
${chalk.dim("$")} squads init my-squad Create a new squad project
|
|
27
|
+
${chalk.dim("$")} squads validate Validate a squad deeply
|
|
28
|
+
${chalk.dim("$")} squads publish Publish to squads.sh
|
|
29
|
+
|
|
30
|
+
${chalk.dim("Documentation: https://squads.sh/docs")}
|
|
31
|
+
`);
|
|
32
|
+
// Register all subcommands
|
|
33
|
+
program.addCommand(createAddCommand());
|
|
34
|
+
program.addCommand(createFindCommand());
|
|
35
|
+
program.addCommand(createListCommand());
|
|
36
|
+
program.addCommand(createCheckCommand());
|
|
37
|
+
program.addCommand(createUpdateCommand());
|
|
38
|
+
program.addCommand(createRemoveCommand());
|
|
39
|
+
program.addCommand(createInitCommand());
|
|
40
|
+
program.addCommand(createPublishCommand());
|
|
41
|
+
program.addCommand(createValidateCommand());
|
|
42
|
+
program.addCommand(createLoginCommand());
|
|
43
|
+
// Parse arguments and run
|
|
44
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
45
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
46
|
+
process.exit(1);
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,oDAAoD,CAAC;KACjE,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CACV,OAAO,EACP;EACF,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC;IACrB,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IACd,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IACd,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IACd,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IACd,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IACd,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IACd,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;IACd,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;;EAEhB,KAAK,CAAC,GAAG,CAAC,uCAAuC,CAAC;CACnD,CACE,CAAC;AAEJ,2BAA2B;AAC3B,OAAO,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;AACvC,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,oBAAoB,EAAE,CAAC,CAAC;AAC3C,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AAEzC,0BAA0B;AAC1B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;IACpD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SquadManifest } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Get the IDE-specific agents installation path for a squad.
|
|
4
|
+
* For Claude Code: .claude/squads/{squad-name}/agents/
|
|
5
|
+
*/
|
|
6
|
+
export declare function getAgentsInstallPath(projectDir: string, squadName: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Get the slash commands path for a squad based on its prefix.
|
|
9
|
+
* For Claude Code: .claude/commands/{prefix}/agents/
|
|
10
|
+
*/
|
|
11
|
+
export declare function getCommandsPath(projectDir: string, prefix: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Copy agent files to IDE-specific paths.
|
|
14
|
+
* - Always copies to .claude/squads/{name}/agents/
|
|
15
|
+
* - If slashPrefix is defined, also copies to .claude/commands/{prefix}/agents/
|
|
16
|
+
*/
|
|
17
|
+
export declare function installAgentFiles(squadDir: string, projectDir: string, manifest: SquadManifest, specificAgent?: string): Promise<string[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Remove agent files from IDE-specific paths.
|
|
20
|
+
*/
|
|
21
|
+
export declare function removeAgentFiles(projectDir: string, squadName: string, prefix?: string): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Read the slashPrefix from a squad.yaml file.
|
|
24
|
+
*/
|
|
25
|
+
export declare function readSlashPrefix(squadDir: string): Promise<string | undefined>;
|
|
26
|
+
//# sourceMappingURL=agents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/lib/agents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,aAAa,EACvB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CAiDnB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQ7B"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { readFile, writeFile, readdir, mkdir, rm } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Get the IDE-specific agents installation path for a squad.
|
|
5
|
+
* For Claude Code: .claude/squads/{squad-name}/agents/
|
|
6
|
+
*/
|
|
7
|
+
export function getAgentsInstallPath(projectDir, squadName) {
|
|
8
|
+
return join(projectDir, ".claude", "squads", squadName, "agents");
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get the slash commands path for a squad based on its prefix.
|
|
12
|
+
* For Claude Code: .claude/commands/{prefix}/agents/
|
|
13
|
+
*/
|
|
14
|
+
export function getCommandsPath(projectDir, prefix) {
|
|
15
|
+
return join(projectDir, ".claude", "commands", prefix, "agents");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Copy agent files to IDE-specific paths.
|
|
19
|
+
* - Always copies to .claude/squads/{name}/agents/
|
|
20
|
+
* - If slashPrefix is defined, also copies to .claude/commands/{prefix}/agents/
|
|
21
|
+
*/
|
|
22
|
+
export async function installAgentFiles(squadDir, projectDir, manifest, specificAgent) {
|
|
23
|
+
const agentsSourceDir = join(squadDir, "agents");
|
|
24
|
+
const installedAgents = [];
|
|
25
|
+
let agentFiles;
|
|
26
|
+
try {
|
|
27
|
+
const allFiles = await readdir(agentsSourceDir);
|
|
28
|
+
agentFiles = allFiles.filter((f) => f.endsWith(".md"));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
if (specificAgent) {
|
|
34
|
+
const target = specificAgent.endsWith(".md")
|
|
35
|
+
? specificAgent
|
|
36
|
+
: `${specificAgent}.md`;
|
|
37
|
+
agentFiles = agentFiles.filter((f) => f === target);
|
|
38
|
+
if (agentFiles.length === 0) {
|
|
39
|
+
throw new Error(`Agent "${specificAgent}" not found in squad "${manifest.name}"`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Install to .claude/squads/{name}/agents/
|
|
43
|
+
const squadsAgentPath = getAgentsInstallPath(projectDir, manifest.name);
|
|
44
|
+
await mkdir(squadsAgentPath, { recursive: true });
|
|
45
|
+
for (const file of agentFiles) {
|
|
46
|
+
const content = await readFile(join(agentsSourceDir, file), "utf-8");
|
|
47
|
+
await writeFile(join(squadsAgentPath, file), content, "utf-8");
|
|
48
|
+
installedAgents.push(file.replace(/\.md$/, ""));
|
|
49
|
+
}
|
|
50
|
+
// If slashPrefix is defined, also copy to .claude/commands/{prefix}/agents/
|
|
51
|
+
if (manifest.slashPrefix) {
|
|
52
|
+
const commandsAgentPath = getCommandsPath(projectDir, manifest.slashPrefix);
|
|
53
|
+
await mkdir(commandsAgentPath, { recursive: true });
|
|
54
|
+
for (const file of agentFiles) {
|
|
55
|
+
const content = await readFile(join(agentsSourceDir, file), "utf-8");
|
|
56
|
+
await writeFile(join(commandsAgentPath, file), content, "utf-8");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return installedAgents;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Remove agent files from IDE-specific paths.
|
|
63
|
+
*/
|
|
64
|
+
export async function removeAgentFiles(projectDir, squadName, prefix) {
|
|
65
|
+
// Remove .claude/squads/{name}/
|
|
66
|
+
const squadsPath = join(projectDir, ".claude", "squads", squadName);
|
|
67
|
+
await rm(squadsPath, { recursive: true, force: true });
|
|
68
|
+
// Remove .claude/commands/{prefix}/ if prefix was set
|
|
69
|
+
if (prefix) {
|
|
70
|
+
const commandsPath = join(projectDir, ".claude", "commands", prefix, "agents");
|
|
71
|
+
await rm(commandsPath, { recursive: true, force: true });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Read the slashPrefix from a squad.yaml file.
|
|
76
|
+
*/
|
|
77
|
+
export async function readSlashPrefix(squadDir) {
|
|
78
|
+
try {
|
|
79
|
+
const content = await readFile(join(squadDir, "squad.yaml"), "utf-8");
|
|
80
|
+
const match = content.match(/^slashPrefix:\s*["']?([^"'\n]+)["']?\s*$/m);
|
|
81
|
+
return match?.[1]?.trim();
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/lib/agents.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CLIConfig } from "../types.js";
|
|
2
|
+
export declare function ensureConfigDir(): Promise<void>;
|
|
3
|
+
export declare function readConfig(): Promise<CLIConfig>;
|
|
4
|
+
export declare function writeConfig(config: CLIConfig): Promise<void>;
|
|
5
|
+
export declare function updateConfig(updates: Partial<CLIConfig>): Promise<CLIConfig>;
|
|
6
|
+
export declare function getAuthToken(): Promise<string | undefined>;
|
|
7
|
+
export declare function getRegistryUrl(): Promise<string>;
|
|
8
|
+
export declare function getGlobalSquadsDir(): string;
|
|
9
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAU7C,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CAQrD;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlE;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAC1B,OAAO,CAAC,SAAS,CAAC,CAKpB;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAGhE;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAGtD;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
const CONFIG_DIR = join(homedir(), ".squads");
|
|
5
|
+
const CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
6
|
+
const DEFAULT_CONFIG = {
|
|
7
|
+
registry: "https://squads.sh",
|
|
8
|
+
telemetryOptOut: false,
|
|
9
|
+
};
|
|
10
|
+
export async function ensureConfigDir() {
|
|
11
|
+
await mkdir(CONFIG_DIR, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
export async function readConfig() {
|
|
14
|
+
try {
|
|
15
|
+
const raw = await readFile(CONFIG_FILE, "utf-8");
|
|
16
|
+
const parsed = JSON.parse(raw);
|
|
17
|
+
return { ...DEFAULT_CONFIG, ...parsed };
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return { ...DEFAULT_CONFIG };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export async function writeConfig(config) {
|
|
24
|
+
await ensureConfigDir();
|
|
25
|
+
await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
26
|
+
}
|
|
27
|
+
export async function updateConfig(updates) {
|
|
28
|
+
const current = await readConfig();
|
|
29
|
+
const updated = { ...current, ...updates };
|
|
30
|
+
await writeConfig(updated);
|
|
31
|
+
return updated;
|
|
32
|
+
}
|
|
33
|
+
export async function getAuthToken() {
|
|
34
|
+
const config = await readConfig();
|
|
35
|
+
return config.authToken;
|
|
36
|
+
}
|
|
37
|
+
export async function getRegistryUrl() {
|
|
38
|
+
const config = await readConfig();
|
|
39
|
+
return config.registry;
|
|
40
|
+
}
|
|
41
|
+
export function getGlobalSquadsDir() {
|
|
42
|
+
return join(CONFIG_DIR, "global");
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEpD,MAAM,cAAc,GAAc;IAChC,QAAQ,EAAE,mBAAmB;IAC7B,eAAe,EAAE,KAAK;CACvB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;QACrD,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAiB;IACjD,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAA2B;IAE3B,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;IAC3C,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,OAAO,MAAM,CAAC,SAAS,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,OAAO,MAAM,CAAC,QAAQ,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { SquadSource } from "../types.js";
|
|
2
|
+
export interface InstallOptions {
|
|
3
|
+
source: SquadSource;
|
|
4
|
+
projectDir: string;
|
|
5
|
+
specificAgent?: string;
|
|
6
|
+
global?: boolean;
|
|
7
|
+
skipConfirmation?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface InstallResult {
|
|
10
|
+
squadName: string;
|
|
11
|
+
version: string;
|
|
12
|
+
agents: string[];
|
|
13
|
+
squadDir: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Orchestrate the full installation of a squad:
|
|
17
|
+
* 1. Resolve source
|
|
18
|
+
* 2. Download/copy files to squads/{name}/
|
|
19
|
+
* 3. Validate
|
|
20
|
+
* 4. Install agent files to IDE paths
|
|
21
|
+
* 5. Update lock file
|
|
22
|
+
* 6. Fire telemetry
|
|
23
|
+
*/
|
|
24
|
+
export declare function installSquad(options: InstallOptions): Promise<InstallResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Re-install a squad from its lock entry source.
|
|
27
|
+
*/
|
|
28
|
+
export declare function reinstallSquad(projectDir: string, squadName: string, sourceString: string): Promise<InstallResult>;
|
|
29
|
+
//# sourceMappingURL=installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/lib/installer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,aAAa,CAAC;AAc1D,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AASD;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA2FxB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,CAMxB"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { mkdir, rm, cp } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { validateSquadDirectory, listAgentFiles } from "./validator.js";
|
|
4
|
+
import { installAgentFiles } from "./agents.js";
|
|
5
|
+
import { addLockEntry, generateSquadHash } from "./lock-file.js";
|
|
6
|
+
import { trackInstall } from "./telemetry.js";
|
|
7
|
+
import { downloadSquad, formatGitHubSource, parseGitHubSource, } from "./sources/github.js";
|
|
8
|
+
import { copyLocalSquad } from "./sources/local.js";
|
|
9
|
+
import { downloadRegistrySquad } from "./sources/registry.js";
|
|
10
|
+
import { getGlobalSquadsDir } from "./config.js";
|
|
11
|
+
/**
|
|
12
|
+
* Determine the effective project directory for installation.
|
|
13
|
+
*/
|
|
14
|
+
function getEffectiveProjectDir(projectDir, global) {
|
|
15
|
+
return global ? getGlobalSquadsDir() : projectDir;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Orchestrate the full installation of a squad:
|
|
19
|
+
* 1. Resolve source
|
|
20
|
+
* 2. Download/copy files to squads/{name}/
|
|
21
|
+
* 3. Validate
|
|
22
|
+
* 4. Install agent files to IDE paths
|
|
23
|
+
* 5. Update lock file
|
|
24
|
+
* 6. Fire telemetry
|
|
25
|
+
*/
|
|
26
|
+
export async function installSquad(options) {
|
|
27
|
+
const { source, specificAgent, global } = options;
|
|
28
|
+
const effectiveDir = getEffectiveProjectDir(options.projectDir, global);
|
|
29
|
+
// Step 1: Download or copy to a temporary staging area,
|
|
30
|
+
// then we validate and move to final location.
|
|
31
|
+
const stagingDir = join(effectiveDir, ".squads-staging");
|
|
32
|
+
await mkdir(stagingDir, { recursive: true });
|
|
33
|
+
let sourceLabel;
|
|
34
|
+
try {
|
|
35
|
+
switch (source.type) {
|
|
36
|
+
case "github": {
|
|
37
|
+
await downloadSquad(source, stagingDir);
|
|
38
|
+
sourceLabel = formatGitHubSource(source);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case "local": {
|
|
42
|
+
await copyLocalSquad(source, stagingDir);
|
|
43
|
+
sourceLabel = source.path || "local";
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
case "registry": {
|
|
47
|
+
const slug = source.squad || source.repo || "unknown";
|
|
48
|
+
const result = await downloadRegistrySquad(slug, stagingDir);
|
|
49
|
+
source.owner = result.source.owner;
|
|
50
|
+
source.repo = result.source.repo;
|
|
51
|
+
sourceLabel = `registry:${slug}`;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
default:
|
|
55
|
+
throw new Error(`Unknown source type: ${source.type}`);
|
|
56
|
+
}
|
|
57
|
+
// Step 2: Validate the downloaded squad
|
|
58
|
+
const validation = await validateSquadDirectory(stagingDir);
|
|
59
|
+
if (!validation.valid) {
|
|
60
|
+
throw new Error(`Invalid squad:\n - ${validation.errors.join("\n - ")}`);
|
|
61
|
+
}
|
|
62
|
+
const manifest = validation.manifest;
|
|
63
|
+
const squadName = manifest.name;
|
|
64
|
+
// Step 3: Move from staging to final location
|
|
65
|
+
const finalSquadDir = join(effectiveDir, "squads", squadName);
|
|
66
|
+
await rm(finalSquadDir, { recursive: true, force: true });
|
|
67
|
+
await mkdir(join(effectiveDir, "squads"), { recursive: true });
|
|
68
|
+
// Copy from staging to final location (cp is reliable cross-device)
|
|
69
|
+
await cp(stagingDir, finalSquadDir, { recursive: true });
|
|
70
|
+
// Step 4: Install agent files to IDE-specific paths
|
|
71
|
+
const agents = await installAgentFiles(finalSquadDir, effectiveDir, manifest, specificAgent);
|
|
72
|
+
// Step 5: Generate hash and update lock file
|
|
73
|
+
const hash = await generateSquadHash(finalSquadDir);
|
|
74
|
+
const agentFiles = await listAgentFiles(finalSquadDir);
|
|
75
|
+
const lockEntry = {
|
|
76
|
+
source: sourceLabel,
|
|
77
|
+
squad: squadName,
|
|
78
|
+
version: manifest.version,
|
|
79
|
+
hash,
|
|
80
|
+
installedAt: new Date().toISOString(),
|
|
81
|
+
agents: agentFiles.map((f) => f.replace(/\.md$/, "")),
|
|
82
|
+
};
|
|
83
|
+
await addLockEntry(effectiveDir, squadName, lockEntry);
|
|
84
|
+
// Step 6: Fire telemetry (non-blocking)
|
|
85
|
+
trackInstall(squadName, source.type, !!global);
|
|
86
|
+
return {
|
|
87
|
+
squadName,
|
|
88
|
+
version: manifest.version,
|
|
89
|
+
agents,
|
|
90
|
+
squadDir: finalSquadDir,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
// Clean up staging directory
|
|
95
|
+
await rm(stagingDir, { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Re-install a squad from its lock entry source.
|
|
100
|
+
*/
|
|
101
|
+
export async function reinstallSquad(projectDir, squadName, sourceString) {
|
|
102
|
+
const source = parseSourceString(sourceString);
|
|
103
|
+
return installSquad({
|
|
104
|
+
source,
|
|
105
|
+
projectDir,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Parse a stored source string back into a SquadSource.
|
|
110
|
+
*/
|
|
111
|
+
function parseSourceString(sourceStr) {
|
|
112
|
+
if (sourceStr.startsWith("registry:")) {
|
|
113
|
+
return {
|
|
114
|
+
type: "registry",
|
|
115
|
+
squad: sourceStr.slice("registry:".length),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (sourceStr.startsWith("/") || sourceStr.startsWith("./")) {
|
|
119
|
+
return { type: "local", path: sourceStr };
|
|
120
|
+
}
|
|
121
|
+
// Assume GitHub
|
|
122
|
+
return parseGitHubSource(sourceStr);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/lib/installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LockFile, LockEntry } from "../types.js";
|
|
2
|
+
export declare function readLockFile(projectDir: string): Promise<LockFile>;
|
|
3
|
+
export declare function writeLockFile(projectDir: string, lockFile: LockFile): Promise<void>;
|
|
4
|
+
export declare function addLockEntry(projectDir: string, name: string, entry: LockEntry): Promise<void>;
|
|
5
|
+
export declare function removeLockEntry(projectDir: string, name: string): Promise<void>;
|
|
6
|
+
export declare function getLockEntry(projectDir: string, name: string): Promise<LockEntry | undefined>;
|
|
7
|
+
/**
|
|
8
|
+
* Generate a hash of a squad directory contents for integrity checking.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateSquadHash(squadDir: string): Promise<string>;
|
|
11
|
+
//# sourceMappingURL=lock-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock-file.d.ts","sourceRoot":"","sources":["../../src/lib/lock-file.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAQvD,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAYxE;AAED,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAGhC;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAIjB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { readdir, stat } from "node:fs/promises";
|
|
5
|
+
const LOCK_FILE_NAME = ".squad-lock.json";
|
|
6
|
+
function getLockFilePath(projectDir) {
|
|
7
|
+
return join(projectDir, LOCK_FILE_NAME);
|
|
8
|
+
}
|
|
9
|
+
export async function readLockFile(projectDir) {
|
|
10
|
+
const lockPath = getLockFilePath(projectDir);
|
|
11
|
+
try {
|
|
12
|
+
const raw = await readFile(lockPath, "utf-8");
|
|
13
|
+
const parsed = JSON.parse(raw);
|
|
14
|
+
if (parsed.version !== 1) {
|
|
15
|
+
throw new Error(`Unsupported lock file version: ${parsed.version}`);
|
|
16
|
+
}
|
|
17
|
+
return parsed;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return { version: 1, squads: {} };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export async function writeLockFile(projectDir, lockFile) {
|
|
24
|
+
const lockPath = getLockFilePath(projectDir);
|
|
25
|
+
await writeFile(lockPath, JSON.stringify(lockFile, null, 2) + "\n", "utf-8");
|
|
26
|
+
}
|
|
27
|
+
export async function addLockEntry(projectDir, name, entry) {
|
|
28
|
+
const lockFile = await readLockFile(projectDir);
|
|
29
|
+
lockFile.squads[name] = entry;
|
|
30
|
+
await writeLockFile(projectDir, lockFile);
|
|
31
|
+
}
|
|
32
|
+
export async function removeLockEntry(projectDir, name) {
|
|
33
|
+
const lockFile = await readLockFile(projectDir);
|
|
34
|
+
delete lockFile.squads[name];
|
|
35
|
+
await writeLockFile(projectDir, lockFile);
|
|
36
|
+
}
|
|
37
|
+
export async function getLockEntry(projectDir, name) {
|
|
38
|
+
const lockFile = await readLockFile(projectDir);
|
|
39
|
+
return lockFile.squads[name];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Generate a hash of a squad directory contents for integrity checking.
|
|
43
|
+
*/
|
|
44
|
+
export async function generateSquadHash(squadDir) {
|
|
45
|
+
const hash = createHash("sha256");
|
|
46
|
+
await hashDirectory(squadDir, hash);
|
|
47
|
+
return hash.digest("hex").slice(0, 16);
|
|
48
|
+
}
|
|
49
|
+
async function hashDirectory(dirPath, hash) {
|
|
50
|
+
let entries;
|
|
51
|
+
try {
|
|
52
|
+
entries = await readdir(dirPath);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
entries.sort();
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
const fullPath = join(dirPath, entry);
|
|
60
|
+
const entryStat = await stat(fullPath);
|
|
61
|
+
if (entryStat.isDirectory()) {
|
|
62
|
+
hash.update(`dir:${entry}\n`);
|
|
63
|
+
await hashDirectory(fullPath, hash);
|
|
64
|
+
}
|
|
65
|
+
else if (entryStat.isFile()) {
|
|
66
|
+
const content = await readFile(fullPath);
|
|
67
|
+
hash.update(`file:${entry}:${content.length}\n`);
|
|
68
|
+
hash.update(content);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=lock-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock-file.js","sourceRoot":"","sources":["../../src/lib/lock-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SquadSource, GitHubTreeEntry } from "../../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parse a GitHub source string into a SquadSource object.
|
|
4
|
+
*
|
|
5
|
+
* Supported formats:
|
|
6
|
+
* owner/repo
|
|
7
|
+
* owner/repo/squad-name
|
|
8
|
+
* owner/repo#branch
|
|
9
|
+
* owner/repo/squad-name#branch
|
|
10
|
+
* https://github.com/owner/repo
|
|
11
|
+
* https://github.com/owner/repo/tree/branch/path
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseGitHubSource(input: string): SquadSource;
|
|
14
|
+
/**
|
|
15
|
+
* Find squad directories in a repository tree.
|
|
16
|
+
* A squad is identified by the presence of squad.yaml.
|
|
17
|
+
*/
|
|
18
|
+
export declare function findSquadsInTree(tree: GitHubTreeEntry[]): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Download a squad from GitHub to a local directory.
|
|
21
|
+
*/
|
|
22
|
+
export declare function downloadSquad(source: SquadSource, targetDir: string): Promise<{
|
|
23
|
+
sha: string;
|
|
24
|
+
}>;
|
|
25
|
+
export declare function formatGitHubSource(source: SquadSource): string;
|
|
26
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../../src/lib/sources/github.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAsB,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAIvF;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAwC5D;AAsED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAclE;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CA6E1B;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAS9D"}
|