@noclaf/cli 0.4.13 → 0.4.15
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/auth.js +2 -1
- package/dist/auth.js.map +1 -1
- package/dist/brand.js +82 -0
- package/dist/brand.js.map +1 -0
- package/dist/cli/commands/auth.js +91 -58
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/init/auth-step.js +48 -0
- package/dist/cli/commands/init/auth-step.js.map +1 -0
- package/dist/cli/commands/init/clients-step.js +76 -0
- package/dist/cli/commands/init/clients-step.js.map +1 -0
- package/dist/cli/commands/init/context-step.js +66 -0
- package/dist/cli/commands/init/context-step.js.map +1 -0
- package/dist/cli/commands/init/index.js +67 -0
- package/dist/cli/commands/init/index.js.map +1 -0
- package/dist/cli/commands/init/project-step.js +105 -0
- package/dist/cli/commands/init/project-step.js.map +1 -0
- package/dist/cli/commands/init/provision-step.js +76 -0
- package/dist/cli/commands/init/provision-step.js.map +1 -0
- package/dist/cli/commands/validate-plan.js +42 -0
- package/dist/cli/commands/validate-plan.js.map +1 -0
- package/dist/cli/flows/clients.js +27 -17
- package/dist/cli/flows/clients.js.map +1 -1
- package/dist/cli.js +7 -5
- package/dist/cli.js.map +1 -1
- package/dist/config.js +19 -11
- package/dist/config.js.map +1 -1
- package/dist/constants.js +7 -8
- package/dist/constants.js.map +1 -1
- package/dist/lib/autopull.js +13 -0
- package/dist/lib/autopull.js.map +1 -0
- package/dist/lib/client-configs.js +37 -25
- package/dist/lib/client-configs.js.map +1 -1
- package/dist/lib/cowork-extension.js +42 -30
- package/dist/lib/cowork-extension.js.map +1 -1
- package/dist/lib/dependencies.js +83 -247
- package/dist/lib/dependencies.js.map +1 -1
- package/dist/lib/dependency-install.js +163 -0
- package/dist/lib/dependency-install.js.map +1 -0
- package/dist/lib/exec-delegate.js +2 -2
- package/dist/lib/exec-delegate.js.map +1 -1
- package/dist/lib/exec-engines.js +7 -6
- package/dist/lib/exec-engines.js.map +1 -1
- package/dist/lib/provision-apply.js +214 -0
- package/dist/lib/provision-apply.js.map +1 -0
- package/dist/lib/provision-collect.js +47 -0
- package/dist/lib/provision-collect.js.map +1 -0
- package/dist/lib/provision.js +8 -253
- package/dist/lib/provision.js.map +1 -1
- package/dist/lib/require-config.js +3 -2
- package/dist/lib/require-config.js.map +1 -1
- package/dist/lib/skills-cache.js +9 -8
- package/dist/lib/skills-cache.js.map +1 -1
- package/dist/lib/skills.js +30 -16
- package/dist/lib/skills.js.map +1 -1
- package/dist/lib/telemetry.js +2 -1
- package/dist/lib/telemetry.js.map +1 -1
- package/dist/lib/validate-plan-delegate.js +105 -0
- package/dist/lib/validate-plan-delegate.js.map +1 -0
- package/dist/lib/version-check.js +3 -2
- package/dist/lib/version-check.js.map +1 -1
- package/dist/mcp-server.js +107 -79
- package/dist/mcp-server.js.map +1 -1
- package/dist/tools/comment-task.js +32 -32
- package/dist/tools/comment-task.js.map +1 -1
- package/dist/tools/create-task.js +92 -101
- package/dist/tools/create-task.js.map +1 -1
- package/dist/tools/delegate-exec.js +4 -3
- package/dist/tools/delegate-exec.js.map +1 -1
- package/dist/tools/end-allocation.js +19 -32
- package/dist/tools/end-allocation.js.map +1 -1
- package/dist/tools/end-task-allocation.js +17 -26
- package/dist/tools/end-task-allocation.js.map +1 -1
- package/dist/tools/exec-status.js +4 -3
- package/dist/tools/exec-status.js.map +1 -1
- package/dist/tools/get-active-allocation.js +53 -60
- package/dist/tools/get-active-allocation.js.map +1 -1
- package/dist/tools/get-context.js +4 -3
- package/dist/tools/get-context.js.map +1 -1
- package/dist/tools/get-task.js +144 -142
- package/dist/tools/get-task.js.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/list-my-allocations.js +35 -43
- package/dist/tools/list-my-allocations.js.map +1 -1
- package/dist/tools/list-projects.js +3 -2
- package/dist/tools/list-projects.js.map +1 -1
- package/dist/tools/list-tasks.js +117 -124
- package/dist/tools/list-tasks.js.map +1 -1
- package/dist/tools/move-task.js +37 -39
- package/dist/tools/move-task.js.map +1 -1
- package/dist/tools/plan.js +3 -2
- package/dist/tools/plan.js.map +1 -1
- package/dist/tools/record-delivery.js +4 -3
- package/dist/tools/record-delivery.js.map +1 -1
- package/dist/tools/set-project.js +9 -4
- package/dist/tools/set-project.js.map +1 -1
- package/dist/tools/start-allocation.js +16 -26
- package/dist/tools/start-allocation.js.map +1 -1
- package/dist/tools/start-task-allocation.js +72 -92
- package/dist/tools/start-task-allocation.js.map +1 -1
- package/dist/tools/update-task.js +149 -168
- package/dist/tools/update-task.js.map +1 -1
- package/dist/tools/validate-plan.js +58 -0
- package/dist/tools/validate-plan.js.map +1 -0
- package/package.json +1 -1
- package/dist/cli/commands/init.js +0 -336
- package/dist/cli/commands/init.js.map +0 -1
- package/dist/logo.js +0 -17
- package/dist/logo.js.map +0 -1
package/dist/lib/exec-engines.js
CHANGED
|
@@ -2,6 +2,7 @@ import { existsSync } from 'node:fs';
|
|
|
2
2
|
import { spawnSync } from 'node:child_process';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
+
import { envName } from '../brand.js';
|
|
5
6
|
/**
|
|
6
7
|
* Registro central dos engines da delegação headless. É o **único** lugar que conhece
|
|
7
8
|
* nome de binário, candidatos de PATH e flags. Adicionar engine = adicionar uma entrada.
|
|
@@ -23,18 +24,18 @@ const SPECS = {
|
|
|
23
24
|
codex: {
|
|
24
25
|
bin: 'codex',
|
|
25
26
|
candidates: knownPaths('codex'),
|
|
26
|
-
binEnv: '
|
|
27
|
-
argsEnv: '
|
|
27
|
+
binEnv: envName('CODEX_BIN'),
|
|
28
|
+
argsEnv: envName('CODEX_ARGS'),
|
|
28
29
|
args: (prompt) => ['exec', '--full-auto', prompt],
|
|
29
|
-
missing:
|
|
30
|
+
missing: `codex não encontrado — instale/logue (\`codex login\`) ou defina ${envName('CODEX_BIN')}`,
|
|
30
31
|
},
|
|
31
32
|
claude: {
|
|
32
33
|
bin: 'claude',
|
|
33
34
|
candidates: knownPaths('claude', join(homedir(), '.claude', 'local', 'claude')),
|
|
34
|
-
binEnv: '
|
|
35
|
-
argsEnv: '
|
|
35
|
+
binEnv: envName('CLAUDE_BIN'),
|
|
36
|
+
argsEnv: envName('CLAUDE_ARGS'),
|
|
36
37
|
args: (prompt) => ['-p', prompt, '--permission-mode', 'acceptEdits'],
|
|
37
|
-
missing:
|
|
38
|
+
missing: `claude não encontrado — instale/logue (\`claude login\`) ou defina ${envName('CLAUDE_BIN')}`,
|
|
38
39
|
},
|
|
39
40
|
};
|
|
40
41
|
export function isEngine(value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec-engines.js","sourceRoot":"","sources":["../../src/lib/exec-engines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"exec-engines.js","sourceRoot":"","sources":["../../src/lib/exec-engines.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, lstatSync, readlinkSync } from "node:fs";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { VERSION } from "../version.js";
|
|
6
|
+
import { brand } from "../brand.js";
|
|
7
|
+
/**
|
|
8
|
+
* Motor do provisionamento: hash/manifesto (`.noclaf-provision.json`), escrita
|
|
9
|
+
* idempotente e poda do que o noclaf gravou. `provision.ts` monta a lista e chama
|
|
10
|
+
* `applyProvision`; `uninstallProvision` desfaz pelo mesmo manifesto.
|
|
11
|
+
*/
|
|
12
|
+
export const MANIFEST_NAME = ".noclaf-provision.json";
|
|
13
|
+
export function defaultTargetDir() {
|
|
14
|
+
return join(homedir(), ".claude");
|
|
15
|
+
}
|
|
16
|
+
function sha256(buf) {
|
|
17
|
+
return createHash("sha256").update(buf).digest("hex");
|
|
18
|
+
}
|
|
19
|
+
function readManifest(path) {
|
|
20
|
+
if (!existsSync(path))
|
|
21
|
+
return null;
|
|
22
|
+
try {
|
|
23
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
24
|
+
if (parsed && typeof parsed === "object" && parsed.files)
|
|
25
|
+
return parsed;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// manifesto corrompido → trata como ausente e reconstrói
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Se um componente de `dir` é symlink com alvo inexistente (dotfiles gerenciando
|
|
34
|
+
* `~/.claude`), materializa o alvo em vez de deixar o `mkdir -p` estourar ENOENT.
|
|
35
|
+
* Retorna `true` se materializou algo. Escrever depois grava através do link.
|
|
36
|
+
*/
|
|
37
|
+
function materializeDanglingLink(dir) {
|
|
38
|
+
let cursor = dir;
|
|
39
|
+
for (;;) {
|
|
40
|
+
let info;
|
|
41
|
+
try {
|
|
42
|
+
info = lstatSync(cursor);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// cursor não existe (parent pendurado) → sobe um nível.
|
|
46
|
+
const parent = dirname(cursor);
|
|
47
|
+
if (parent === cursor)
|
|
48
|
+
return false;
|
|
49
|
+
cursor = parent;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (info.isSymbolicLink()) {
|
|
53
|
+
const target = resolve(dirname(cursor), readlinkSync(cursor));
|
|
54
|
+
if (existsSync(target))
|
|
55
|
+
return false; // link ok — o ENOENT veio de outro lugar
|
|
56
|
+
mkdirSync(target, { recursive: true });
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return false; // cursor existe e é real → não há link pendurado acima
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** `mkdir -p` tolerante a symlinks pendurados de dotfiles (ver acima). */
|
|
63
|
+
export function ensureDir(dir) {
|
|
64
|
+
for (let attempt = 0; attempt < 40; attempt++) {
|
|
65
|
+
try {
|
|
66
|
+
mkdirSync(dir, { recursive: true });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
if (err.code !== "ENOENT")
|
|
71
|
+
throw err;
|
|
72
|
+
if (!materializeDanglingLink(dir))
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
mkdirSync(dir, { recursive: true });
|
|
77
|
+
}
|
|
78
|
+
function writeFile(targetAbs, content) {
|
|
79
|
+
ensureDir(dirname(targetAbs));
|
|
80
|
+
writeFileSync(targetAbs, content);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Núcleo do provisionamento: aplica `docs` no destino, idempotente e não-destrutivo
|
|
84
|
+
* via manifesto. Retorna o plano por arquivo.
|
|
85
|
+
*/
|
|
86
|
+
export function applyProvision(docs, options = {}) {
|
|
87
|
+
const dryRun = options.dryRun ?? false;
|
|
88
|
+
const force = options.force ?? false;
|
|
89
|
+
const prune = options.prune ?? true;
|
|
90
|
+
const targetDir = options.targetDir ?? defaultTargetDir();
|
|
91
|
+
const manifestPath = join(targetDir, MANIFEST_NAME);
|
|
92
|
+
const oldFiles = readManifest(manifestPath)?.files ?? {};
|
|
93
|
+
const files = docs.map((d) => ({
|
|
94
|
+
relPath: d.relPath,
|
|
95
|
+
content: d.content,
|
|
96
|
+
hash: sha256(d.content),
|
|
97
|
+
}));
|
|
98
|
+
const incomingSet = new Set(files.map((f) => f.relPath));
|
|
99
|
+
const results = [];
|
|
100
|
+
const newFiles = {};
|
|
101
|
+
for (const f of files) {
|
|
102
|
+
const targetAbs = join(targetDir, f.relPath);
|
|
103
|
+
// Um arquivo problemático (ex.: symlink de dotfiles quebrado) vira um resultado
|
|
104
|
+
// `write-error` e a sincronização segue — nunca aborta o resto por causa de um.
|
|
105
|
+
try {
|
|
106
|
+
if (!existsSync(targetAbs)) {
|
|
107
|
+
if (!dryRun)
|
|
108
|
+
writeFile(targetAbs, f.content);
|
|
109
|
+
results.push({ relPath: f.relPath, action: "create" });
|
|
110
|
+
newFiles[f.relPath] = f.hash;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const existingHash = sha256(readFileSync(targetAbs));
|
|
114
|
+
if (existingHash === f.hash) {
|
|
115
|
+
results.push({ relPath: f.relPath, action: "unchanged" });
|
|
116
|
+
newFiles[f.relPath] = f.hash;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
// Divergente. Só atualizamos se o arquivo era nosso e o worker não mexeu,
|
|
120
|
+
// ou se ele pediu --force.
|
|
121
|
+
const wasOursUntouched = oldFiles[f.relPath] === existingHash;
|
|
122
|
+
if (wasOursUntouched || force) {
|
|
123
|
+
if (!dryRun)
|
|
124
|
+
writeFile(targetAbs, f.content);
|
|
125
|
+
results.push({
|
|
126
|
+
relPath: f.relPath,
|
|
127
|
+
action: "update",
|
|
128
|
+
detail: wasOursUntouched
|
|
129
|
+
? undefined
|
|
130
|
+
: "forçado sobre arquivo divergente",
|
|
131
|
+
});
|
|
132
|
+
newFiles[f.relPath] = f.hash;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
results.push({
|
|
136
|
+
relPath: f.relPath,
|
|
137
|
+
action: "skip-conflict",
|
|
138
|
+
detail: oldFiles[f.relPath] !== undefined
|
|
139
|
+
? "editado localmente"
|
|
140
|
+
: "arquivo de terceiros",
|
|
141
|
+
});
|
|
142
|
+
// Não reivindica propriedade: fica de fora do novo manifesto.
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
results.push({
|
|
147
|
+
relPath: f.relPath,
|
|
148
|
+
action: "write-error",
|
|
149
|
+
detail: err.message,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Prune: o que era nosso mas não veio nesta fonte.
|
|
154
|
+
if (prune) {
|
|
155
|
+
for (const [relPath, oldHash] of Object.entries(oldFiles)) {
|
|
156
|
+
if (incomingSet.has(relPath))
|
|
157
|
+
continue;
|
|
158
|
+
const targetAbs = join(targetDir, relPath);
|
|
159
|
+
if (!existsSync(targetAbs))
|
|
160
|
+
continue;
|
|
161
|
+
const existingHash = sha256(readFileSync(targetAbs));
|
|
162
|
+
if (existingHash === oldHash) {
|
|
163
|
+
if (!dryRun)
|
|
164
|
+
rmSync(targetAbs);
|
|
165
|
+
results.push({ relPath, action: "prune" });
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
results.push({
|
|
169
|
+
relPath,
|
|
170
|
+
action: "prune-kept",
|
|
171
|
+
detail: "modificado localmente — mantido",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (!dryRun) {
|
|
177
|
+
const manifest = {
|
|
178
|
+
version: VERSION,
|
|
179
|
+
generator: brand.packageName,
|
|
180
|
+
files: newFiles,
|
|
181
|
+
};
|
|
182
|
+
mkdirSync(targetDir, { recursive: true });
|
|
183
|
+
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
184
|
+
}
|
|
185
|
+
return { targetDir, version: VERSION, dryRun, files: results };
|
|
186
|
+
}
|
|
187
|
+
/** Remove só o que o noclaf instalou (conforme o manifesto), preservando edições locais. */
|
|
188
|
+
export function uninstallProvision(options = {}) {
|
|
189
|
+
const dryRun = options.dryRun ?? false;
|
|
190
|
+
const targetDir = options.targetDir ?? defaultTargetDir();
|
|
191
|
+
const manifestPath = join(targetDir, MANIFEST_NAME);
|
|
192
|
+
const manifest = readManifest(manifestPath);
|
|
193
|
+
const removed = [];
|
|
194
|
+
const kept = [];
|
|
195
|
+
if (manifest) {
|
|
196
|
+
for (const [relPath, hash] of Object.entries(manifest.files)) {
|
|
197
|
+
const targetAbs = join(targetDir, relPath);
|
|
198
|
+
if (!existsSync(targetAbs))
|
|
199
|
+
continue;
|
|
200
|
+
if (sha256(readFileSync(targetAbs)) === hash) {
|
|
201
|
+
if (!dryRun)
|
|
202
|
+
rmSync(targetAbs);
|
|
203
|
+
removed.push(relPath);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
kept.push(relPath);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (!dryRun && existsSync(manifestPath))
|
|
210
|
+
rmSync(manifestPath);
|
|
211
|
+
}
|
|
212
|
+
return { targetDir, removed, kept, dryRun };
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=provision-apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision-apply.js","sourceRoot":"","sources":["../../src/lib/provision-apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join, relative, sep } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Coleta os arquivos sincronizáveis do pacote `@noclaf/skills` (commands/skills/
|
|
5
|
+
* agents) como uma lista em memória — a fonte que `provision()` filtra/achata
|
|
6
|
+
* (via `sections.ts`) e passa pro motor de aplicação (`provision-apply.ts`).
|
|
7
|
+
*/
|
|
8
|
+
/** Subpastas do pacote `@noclaf/skills` espelhadas em `~/.claude`. */
|
|
9
|
+
const SYNCED_SUBDIRS = ["commands", "skills", "agents"];
|
|
10
|
+
/** Basenames que nunca são copiados pro destino (READMEs são só do repo). */
|
|
11
|
+
const IGNORED_BASENAMES = new Set([".gitkeep", ".DS_Store", "README.md"]);
|
|
12
|
+
/** Lista arquivos sob `dir` recursivamente, paths relativos a `dir` em estilo POSIX. */
|
|
13
|
+
function listFilesRecursive(dir) {
|
|
14
|
+
const out = [];
|
|
15
|
+
const walk = (abs) => {
|
|
16
|
+
for (const entry of readdirSync(abs, { withFileTypes: true })) {
|
|
17
|
+
if (entry.name === ".DS_Store")
|
|
18
|
+
continue;
|
|
19
|
+
const childAbs = join(abs, entry.name);
|
|
20
|
+
if (entry.isDirectory())
|
|
21
|
+
walk(childAbs);
|
|
22
|
+
else if (entry.isFile())
|
|
23
|
+
out.push(relative(dir, childAbs).split(sep).join("/"));
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
walk(dir);
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
/** Coleta os arquivos sincronizáveis do pacote (só as subpastas conhecidas). */
|
|
30
|
+
export function collectSkillFiles(dir) {
|
|
31
|
+
const files = [];
|
|
32
|
+
for (const sub of SYNCED_SUBDIRS) {
|
|
33
|
+
const subDir = join(dir, sub);
|
|
34
|
+
if (!existsSync(subDir))
|
|
35
|
+
continue;
|
|
36
|
+
for (const rel of listFilesRecursive(subDir)) {
|
|
37
|
+
const base = rel.split("/").pop() ?? rel;
|
|
38
|
+
if (IGNORED_BASENAMES.has(base))
|
|
39
|
+
continue;
|
|
40
|
+
const abs = join(subDir, rel);
|
|
41
|
+
const content = readFileSync(abs);
|
|
42
|
+
files.push({ relPath: `${sub}/${rel}`, content });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return files;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=provision-collect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision-collect.js","sourceRoot":"","sources":["../../src/lib/provision-collect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhD;;;;GAIG;AAEH,sEAAsE;AACtE,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAEjE,6EAA6E;AAC7E,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;AAO1E,wFAAwF;AACxF,SAAS,kBAAkB,CAAC,GAAW;IACrC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,CAAC,GAAW,EAAQ,EAAE;QACjC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAC9D,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gBAAE,SAAS;YACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACvC,IAAI,KAAK,CAAC,WAAW,EAAE;gBAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;iBACnC,IAAI,KAAK,CAAC,MAAM,EAAE;gBACrB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,GAAG,CAAC;AACb,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,SAAS;QAClC,KAAK,MAAM,GAAG,IAAI,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC;YACzC,IAAI,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC9B,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/lib/provision.js
CHANGED
|
@@ -1,233 +1,14 @@
|
|
|
1
|
-
import { existsSync
|
|
2
|
-
import { createHash } from "node:crypto";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
5
|
-
import { VERSION } from "../version.js";
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
6
2
|
import { claudeTarget } from "./targets.js";
|
|
7
3
|
import { filterDocsForSurface, skillsDir } from "./skills.js";
|
|
8
|
-
import { filterForSelection, flattenSelection
|
|
4
|
+
import { filterForSelection, flattenSelection } from "./sections.js";
|
|
5
|
+
import { collectSkillFiles } from "./provision-collect.js";
|
|
6
|
+
import { applyProvision } from "./provision-apply.js";
|
|
9
7
|
/**
|
|
10
|
-
* Provisiona
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* atualiza os arquivos dele, nunca sobrescreve os do worker (a menos que `force`).
|
|
8
|
+
* Provisiona skills/commands/agents do noclaf (o MCP não grava em `~/.claude`; a CLI
|
|
9
|
+
* `sync`/`init` chama `provision()`). Idempotente via manifesto. Coleta em
|
|
10
|
+
* `provision-collect.ts`, motor em `provision-apply.ts` — ambos reexportados daqui.
|
|
14
11
|
*/
|
|
15
|
-
/** Subpastas do pacote `@noclaf/skills` espelhadas em `~/.claude`. */
|
|
16
|
-
const SYNCED_SUBDIRS = ["commands", "skills", "agents"];
|
|
17
|
-
/** Basenames que nunca são copiados pro destino (READMEs são só do repo). */
|
|
18
|
-
const IGNORED_BASENAMES = new Set([".gitkeep", ".DS_Store", "README.md"]);
|
|
19
|
-
export const MANIFEST_NAME = ".noclaf-provision.json";
|
|
20
|
-
function defaultTargetDir() {
|
|
21
|
-
return join(homedir(), ".claude");
|
|
22
|
-
}
|
|
23
|
-
function sha256(buf) {
|
|
24
|
-
return createHash("sha256").update(buf).digest("hex");
|
|
25
|
-
}
|
|
26
|
-
/** Lista arquivos sob `dir` recursivamente, paths relativos a `dir` em estilo POSIX. */
|
|
27
|
-
function listFilesRecursive(dir) {
|
|
28
|
-
const out = [];
|
|
29
|
-
const walk = (abs) => {
|
|
30
|
-
for (const entry of readdirSync(abs, { withFileTypes: true })) {
|
|
31
|
-
if (entry.name === ".DS_Store")
|
|
32
|
-
continue;
|
|
33
|
-
const childAbs = join(abs, entry.name);
|
|
34
|
-
if (entry.isDirectory())
|
|
35
|
-
walk(childAbs);
|
|
36
|
-
else if (entry.isFile())
|
|
37
|
-
out.push(relative(dir, childAbs).split(sep).join("/"));
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
walk(dir);
|
|
41
|
-
return out;
|
|
42
|
-
}
|
|
43
|
-
function readManifest(path) {
|
|
44
|
-
if (!existsSync(path))
|
|
45
|
-
return null;
|
|
46
|
-
try {
|
|
47
|
-
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
48
|
-
if (parsed && typeof parsed === "object" && parsed.files)
|
|
49
|
-
return parsed;
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
// manifesto corrompido → trata como ausente e reconstrói
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
/** Coleta os arquivos sincronizáveis do pacote (só as subpastas conhecidas). */
|
|
57
|
-
function collectSkillFiles(dir) {
|
|
58
|
-
const files = [];
|
|
59
|
-
for (const sub of SYNCED_SUBDIRS) {
|
|
60
|
-
const subDir = join(dir, sub);
|
|
61
|
-
if (!existsSync(subDir))
|
|
62
|
-
continue;
|
|
63
|
-
for (const rel of listFilesRecursive(subDir)) {
|
|
64
|
-
const base = rel.split("/").pop() ?? rel;
|
|
65
|
-
if (IGNORED_BASENAMES.has(base))
|
|
66
|
-
continue;
|
|
67
|
-
const abs = join(subDir, rel);
|
|
68
|
-
const content = readFileSync(abs);
|
|
69
|
-
files.push({ relPath: `${sub}/${rel}`, content, hash: sha256(content) });
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return files;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Se algum componente de `dir` é um symlink cujo alvo não existe (comum quando o
|
|
76
|
-
* usuário gerencia `~/.claude` via dotfiles com links), materializa o alvo do link
|
|
77
|
-
* em vez de deixar o `mkdir -p` estourar ENOENT. Retorna `true` se materializou
|
|
78
|
-
* algo (aí vale retentar o mkdir). Escrever depois grava *através* do symlink, no
|
|
79
|
-
* destino dos dotfiles — que é a intenção do link.
|
|
80
|
-
*/
|
|
81
|
-
function materializeDanglingLink(dir) {
|
|
82
|
-
let cursor = dir;
|
|
83
|
-
for (;;) {
|
|
84
|
-
let info;
|
|
85
|
-
try {
|
|
86
|
-
info = lstatSync(cursor);
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
// cursor não existe (parent pendurado) → sobe um nível.
|
|
90
|
-
const parent = dirname(cursor);
|
|
91
|
-
if (parent === cursor)
|
|
92
|
-
return false;
|
|
93
|
-
cursor = parent;
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
if (info.isSymbolicLink()) {
|
|
97
|
-
const target = resolve(dirname(cursor), readlinkSync(cursor));
|
|
98
|
-
if (existsSync(target))
|
|
99
|
-
return false; // link ok — o ENOENT veio de outro lugar
|
|
100
|
-
mkdirSync(target, { recursive: true });
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
return false; // cursor existe e é real → não há link pendurado acima
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
/** `mkdir -p` tolerante a symlinks pendurados de dotfiles (ver acima). */
|
|
107
|
-
export function ensureDir(dir) {
|
|
108
|
-
for (let attempt = 0; attempt < 40; attempt++) {
|
|
109
|
-
try {
|
|
110
|
-
mkdirSync(dir, { recursive: true });
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
catch (err) {
|
|
114
|
-
if (err.code !== "ENOENT")
|
|
115
|
-
throw err;
|
|
116
|
-
if (!materializeDanglingLink(dir))
|
|
117
|
-
throw err;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
mkdirSync(dir, { recursive: true });
|
|
121
|
-
}
|
|
122
|
-
function writeFile(targetAbs, content) {
|
|
123
|
-
ensureDir(dirname(targetAbs));
|
|
124
|
-
writeFileSync(targetAbs, content);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Núcleo do provisionamento: aplica `docs` no destino, idempotente e não-destrutivo
|
|
128
|
-
* via manifesto. Retorna o plano por arquivo.
|
|
129
|
-
*/
|
|
130
|
-
export function applyProvision(docs, options = {}) {
|
|
131
|
-
const dryRun = options.dryRun ?? false;
|
|
132
|
-
const force = options.force ?? false;
|
|
133
|
-
const prune = options.prune ?? true;
|
|
134
|
-
const targetDir = options.targetDir ?? defaultTargetDir();
|
|
135
|
-
const manifestPath = join(targetDir, MANIFEST_NAME);
|
|
136
|
-
const oldFiles = readManifest(manifestPath)?.files ?? {};
|
|
137
|
-
const files = docs.map((d) => ({
|
|
138
|
-
relPath: d.relPath,
|
|
139
|
-
content: d.content,
|
|
140
|
-
hash: sha256(d.content),
|
|
141
|
-
}));
|
|
142
|
-
const incomingSet = new Set(files.map((f) => f.relPath));
|
|
143
|
-
const results = [];
|
|
144
|
-
const newFiles = {};
|
|
145
|
-
for (const f of files) {
|
|
146
|
-
const targetAbs = join(targetDir, f.relPath);
|
|
147
|
-
// Um arquivo problemático (ex.: symlink de dotfiles quebrado) vira um resultado
|
|
148
|
-
// `write-error` e a sincronização segue — nunca aborta o resto por causa de um.
|
|
149
|
-
try {
|
|
150
|
-
if (!existsSync(targetAbs)) {
|
|
151
|
-
if (!dryRun)
|
|
152
|
-
writeFile(targetAbs, f.content);
|
|
153
|
-
results.push({ relPath: f.relPath, action: "create" });
|
|
154
|
-
newFiles[f.relPath] = f.hash;
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
const existingHash = sha256(readFileSync(targetAbs));
|
|
158
|
-
if (existingHash === f.hash) {
|
|
159
|
-
results.push({ relPath: f.relPath, action: "unchanged" });
|
|
160
|
-
newFiles[f.relPath] = f.hash;
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
// Divergente. Só atualizamos se o arquivo era nosso e o worker não mexeu,
|
|
164
|
-
// ou se ele pediu --force.
|
|
165
|
-
const wasOursUntouched = oldFiles[f.relPath] === existingHash;
|
|
166
|
-
if (wasOursUntouched || force) {
|
|
167
|
-
if (!dryRun)
|
|
168
|
-
writeFile(targetAbs, f.content);
|
|
169
|
-
results.push({
|
|
170
|
-
relPath: f.relPath,
|
|
171
|
-
action: "update",
|
|
172
|
-
detail: wasOursUntouched
|
|
173
|
-
? undefined
|
|
174
|
-
: "forçado sobre arquivo divergente",
|
|
175
|
-
});
|
|
176
|
-
newFiles[f.relPath] = f.hash;
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
results.push({
|
|
180
|
-
relPath: f.relPath,
|
|
181
|
-
action: "skip-conflict",
|
|
182
|
-
detail: oldFiles[f.relPath] !== undefined
|
|
183
|
-
? "editado localmente"
|
|
184
|
-
: "arquivo de terceiros",
|
|
185
|
-
});
|
|
186
|
-
// Não reivindica propriedade: fica de fora do novo manifesto.
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
catch (err) {
|
|
190
|
-
results.push({
|
|
191
|
-
relPath: f.relPath,
|
|
192
|
-
action: "write-error",
|
|
193
|
-
detail: err.message,
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
// Prune: o que era nosso mas não veio nesta fonte.
|
|
198
|
-
if (prune) {
|
|
199
|
-
for (const [relPath, oldHash] of Object.entries(oldFiles)) {
|
|
200
|
-
if (incomingSet.has(relPath))
|
|
201
|
-
continue;
|
|
202
|
-
const targetAbs = join(targetDir, relPath);
|
|
203
|
-
if (!existsSync(targetAbs))
|
|
204
|
-
continue;
|
|
205
|
-
const existingHash = sha256(readFileSync(targetAbs));
|
|
206
|
-
if (existingHash === oldHash) {
|
|
207
|
-
if (!dryRun)
|
|
208
|
-
rmSync(targetAbs);
|
|
209
|
-
results.push({ relPath, action: "prune" });
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
results.push({
|
|
213
|
-
relPath,
|
|
214
|
-
action: "prune-kept",
|
|
215
|
-
detail: "modificado localmente — mantido",
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
if (!dryRun) {
|
|
221
|
-
const manifest = {
|
|
222
|
-
version: VERSION,
|
|
223
|
-
generator: "@noclaf/cli",
|
|
224
|
-
files: newFiles,
|
|
225
|
-
};
|
|
226
|
-
mkdirSync(targetDir, { recursive: true });
|
|
227
|
-
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
228
|
-
}
|
|
229
|
-
return { targetDir, version: VERSION, dryRun, files: results };
|
|
230
|
-
}
|
|
231
12
|
/**
|
|
232
13
|
* Copia/atualiza o conteúdo do pacote `@noclaf/skills` no destino.
|
|
233
14
|
* (`noclaf sync` / `noclaf init`.)
|
|
@@ -251,31 +32,5 @@ export function provision(options = {}) {
|
|
|
251
32
|
targetDir: options.targetDir ?? target.targetDir(),
|
|
252
33
|
});
|
|
253
34
|
}
|
|
254
|
-
|
|
255
|
-
export function uninstallProvision(options = {}) {
|
|
256
|
-
const dryRun = options.dryRun ?? false;
|
|
257
|
-
const targetDir = options.targetDir ?? defaultTargetDir();
|
|
258
|
-
const manifestPath = join(targetDir, MANIFEST_NAME);
|
|
259
|
-
const manifest = readManifest(manifestPath);
|
|
260
|
-
const removed = [];
|
|
261
|
-
const kept = [];
|
|
262
|
-
if (manifest) {
|
|
263
|
-
for (const [relPath, hash] of Object.entries(manifest.files)) {
|
|
264
|
-
const targetAbs = join(targetDir, relPath);
|
|
265
|
-
if (!existsSync(targetAbs))
|
|
266
|
-
continue;
|
|
267
|
-
if (sha256(readFileSync(targetAbs)) === hash) {
|
|
268
|
-
if (!dryRun)
|
|
269
|
-
rmSync(targetAbs);
|
|
270
|
-
removed.push(relPath);
|
|
271
|
-
}
|
|
272
|
-
else {
|
|
273
|
-
kept.push(relPath);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
if (!dryRun && existsSync(manifestPath))
|
|
277
|
-
rmSync(manifestPath);
|
|
278
|
-
}
|
|
279
|
-
return { targetDir, removed, kept, dryRun };
|
|
280
|
-
}
|
|
35
|
+
export { MANIFEST_NAME, applyProvision, ensureDir, uninstallProvision, } from "./provision-apply.js";
|
|
281
36
|
//# sourceMappingURL=provision.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provision.js","sourceRoot":"","sources":["../../src/lib/provision.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"provision.js","sourceRoot":"","sources":["../../src/lib/provision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,YAAY,EAAwB,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAkB,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAA+C,MAAM,sBAAsB,CAAC;AAEnG;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,UAAU,SAAS,CACvB,UAAkF,EAAE;IAEpF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,YAAY,CAAC;IAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,IAAI,SAAS,EAAE,CAAC;IAC7C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,sCAAsC,GAAG,oCAAoC,CAC9E,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjD,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,OAAO,EAAE,CAAC,CAAC,OAAO;KACnB,CAAC,CAAC,CAAC;IACJ,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,cAAc,CAAC,IAAI,EAAE;QAC1B,GAAG,OAAO;QACV,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,EAAE;KACnD,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EACL,aAAa,EACb,cAAc,EACd,SAAS,EACT,kBAAkB,GAOnB,MAAM,sBAAsB,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { UUID_REGEX } from '../config.js';
|
|
2
2
|
import { errorResult } from './tool-result.js';
|
|
3
3
|
import { loadActiveProjectId } from './active-project.js';
|
|
4
|
+
import { brand } from '../brand.js';
|
|
4
5
|
/**
|
|
5
6
|
* Resolve o projeto efetivo de uma chamada, na ordem:
|
|
6
7
|
* 1. project_id explícito passado na tool (override por chamada)
|
|
@@ -13,8 +14,8 @@ import { loadActiveProjectId } from './active-project.js';
|
|
|
13
14
|
export function resolveProjectConfig(ctx, explicitProjectId) {
|
|
14
15
|
const projectId = explicitProjectId ?? loadActiveProjectId() ?? ctx.config?.project_id;
|
|
15
16
|
if (!projectId) {
|
|
16
|
-
return errorResult(
|
|
17
|
-
|
|
17
|
+
return errorResult(`Nenhum projeto selecionado. Use \`${brand.toolPrefix}list_projects\` para ver os seus e ` +
|
|
18
|
+
`\`${brand.toolPrefix}set_project\` para escolher um (ou passe \`project_id\` direto na chamada).`);
|
|
18
19
|
}
|
|
19
20
|
if (!UUID_REGEX.test(projectId)) {
|
|
20
21
|
return errorResult(`project_id inválido (UUID esperado): ${projectId}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"require-config.js","sourceRoot":"","sources":["../../src/lib/require-config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAsB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"require-config.js","sourceRoot":"","sources":["../../src/lib/require-config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAsB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,GAAgB,EAChB,iBAA0B;IAE1B,MAAM,SAAS,GAAG,iBAAiB,IAAI,mBAAmB,EAAE,IAAI,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC;IAEvF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,WAAW,CAChB,qCAAqC,KAAK,CAAC,UAAU,qCAAqC;YACxF,KAAK,KAAK,CAAC,UAAU,6EAA6E,CACrG,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,OAAO,WAAW,CAAC,wCAAwC,SAAS,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,MAAM,GAAkB,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;IACxD,IAAI,SAAS,KAAK,GAAG,CAAC,MAAM,EAAE,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC;QACtE,MAAM,CAAC,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC;IAClD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,SAAS,IAAI,KAAK,CAAC;AAC3E,CAAC"}
|