@bitkyc08/agent-sync 0.1.7 → 0.1.9
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/README.md +1 -1
- package/dist/__tests__/symlink.test.d.ts +1 -0
- package/dist/__tests__/symlink.test.js +348 -0
- package/dist/__tests__/symlink.test.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/core/skill-sync.js +53 -6
- package/dist/core/skill-sync.js.map +1 -1
- package/dist/core/symlink.d.ts +5 -0
- package/dist/core/symlink.js +88 -4
- package/dist/core/symlink.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Comprehensive tests for symlink cycle detection and skill-sync safety.
|
|
3
|
+
*
|
|
4
|
+
* Covers:
|
|
5
|
+
* - wouldCreateCycle() — direct, indirect, ELOOP, deep chains
|
|
6
|
+
* - ensureSymlinkSafe() — cycle guard integration
|
|
7
|
+
* - syncSkills() — resolved path comparisons, real-world scenarios
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import { join, resolve } from 'node:path';
|
|
12
|
+
import os from 'node:os';
|
|
13
|
+
import { wouldCreateCycle, ensureSymlinkSafe, resolveSymlinkTarget, copyDirRecursive, } from '../core/symlink.js';
|
|
14
|
+
import { syncSkills, detectSkillSources, listSkills } from '../core/skill-sync.js';
|
|
15
|
+
// ─── Test helpers ─────────────────────────────────
|
|
16
|
+
function tmpDir() {
|
|
17
|
+
return fs.mkdtempSync(join(os.tmpdir(), 'agent-sync-test-'));
|
|
18
|
+
}
|
|
19
|
+
function touch(path, content = '') {
|
|
20
|
+
fs.mkdirSync(join(path, '..').replace(/\/\.\.$/, ''), { recursive: true });
|
|
21
|
+
const dir = resolve(path, '..');
|
|
22
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
23
|
+
fs.writeFileSync(path, content);
|
|
24
|
+
}
|
|
25
|
+
function makeSkillDir(base, name) {
|
|
26
|
+
const skillDir = join(base, name);
|
|
27
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
28
|
+
touch(join(skillDir, 'SKILL.md'), `---\nname: ${name}\n---\n# ${name}\n`);
|
|
29
|
+
}
|
|
30
|
+
function cleanDir(dir) {
|
|
31
|
+
try {
|
|
32
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
33
|
+
}
|
|
34
|
+
catch { /* ok */ }
|
|
35
|
+
}
|
|
36
|
+
// ─── wouldCreateCycle ─────────────────────────────
|
|
37
|
+
describe('wouldCreateCycle', () => {
|
|
38
|
+
let tmp;
|
|
39
|
+
beforeEach(() => { tmp = tmpDir(); });
|
|
40
|
+
afterEach(() => { cleanDir(tmp); });
|
|
41
|
+
it('returns false for non-existing target (new symlink)', () => {
|
|
42
|
+
const target = join(tmp, 'target-dir');
|
|
43
|
+
const linkPath = join(tmp, 'link');
|
|
44
|
+
fs.mkdirSync(target, { recursive: true });
|
|
45
|
+
expect(wouldCreateCycle(target, linkPath)).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
it('returns false for a valid non-circular symlink', () => {
|
|
48
|
+
const realDir = join(tmp, 'real');
|
|
49
|
+
const linkPath = join(tmp, 'link');
|
|
50
|
+
fs.mkdirSync(realDir, { recursive: true });
|
|
51
|
+
fs.symlinkSync(realDir, linkPath);
|
|
52
|
+
// Creating link2 → realDir should not be circular
|
|
53
|
+
const link2 = join(tmp, 'link2');
|
|
54
|
+
expect(wouldCreateCycle(realDir, link2)).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
it('detects direct cycle: A → B where B already → A', () => {
|
|
57
|
+
// Setup: B is a symlink → A
|
|
58
|
+
const a = join(tmp, 'a');
|
|
59
|
+
const b = join(tmp, 'b');
|
|
60
|
+
fs.mkdirSync(a, { recursive: true });
|
|
61
|
+
fs.symlinkSync(a, b);
|
|
62
|
+
// Creating A → B would create: A → B → A (cycle)
|
|
63
|
+
expect(wouldCreateCycle(b, a)).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
it('detects 3-node cycle: A → B → C → A', () => {
|
|
66
|
+
const a = join(tmp, 'a');
|
|
67
|
+
const b = join(tmp, 'b');
|
|
68
|
+
const c = join(tmp, 'c');
|
|
69
|
+
// Setup chain: b → c, c → a (a doesn't exist yet)
|
|
70
|
+
touch(join(a, 'dummy')); // a is a real dir
|
|
71
|
+
fs.symlinkSync(join(tmp, 'c'), b);
|
|
72
|
+
fs.symlinkSync(a, c);
|
|
73
|
+
// Creating a → b would complete the cycle: a → b → c → a
|
|
74
|
+
// But a is a real dir, so wouldCreateCycle checks if target (b) resolves back to linkPath (a)
|
|
75
|
+
// b → c → a, and a === linkPath → cycle!
|
|
76
|
+
expect(wouldCreateCycle(b, a)).toBe(true);
|
|
77
|
+
});
|
|
78
|
+
it('detects ELOOP on already-circular targets', () => {
|
|
79
|
+
const a = join(tmp, 'a');
|
|
80
|
+
const b = join(tmp, 'b');
|
|
81
|
+
// Create circular pair: a → b, b → a
|
|
82
|
+
fs.symlinkSync(b, a);
|
|
83
|
+
fs.symlinkSync(a, b);
|
|
84
|
+
// Any operation involving these should detect cycle
|
|
85
|
+
const c = join(tmp, 'c');
|
|
86
|
+
expect(wouldCreateCycle(a, c)).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
it('returns false when target is self (idempotent)', () => {
|
|
89
|
+
const realDir = join(tmp, 'real');
|
|
90
|
+
fs.mkdirSync(realDir, { recursive: true });
|
|
91
|
+
// linkPath doesn't exist → target points to a real dir → no cycle
|
|
92
|
+
const linkPath = join(tmp, 'link');
|
|
93
|
+
expect(wouldCreateCycle(realDir, linkPath)).toBe(false);
|
|
94
|
+
});
|
|
95
|
+
it('detects cycle when existing symlink would point back to itself', () => {
|
|
96
|
+
// Create a → b where b is a real dir, then check if b → a would cycle
|
|
97
|
+
// (since a → b, making b → a creates a → b → a)
|
|
98
|
+
const a = join(tmp, 'selfA');
|
|
99
|
+
const b = join(tmp, 'selfB');
|
|
100
|
+
fs.mkdirSync(b, { recursive: true });
|
|
101
|
+
fs.symlinkSync(b, a);
|
|
102
|
+
// b → a would cycle: a → b → a
|
|
103
|
+
expect(wouldCreateCycle(a, b)).toBe(true);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
// ─── ensureSymlinkSafe ────────────────────────────
|
|
107
|
+
describe('ensureSymlinkSafe', () => {
|
|
108
|
+
let tmp;
|
|
109
|
+
beforeEach(() => { tmp = tmpDir(); });
|
|
110
|
+
afterEach(() => { cleanDir(tmp); });
|
|
111
|
+
it('creates a new symlink for non-existing path', () => {
|
|
112
|
+
const target = join(tmp, 'target');
|
|
113
|
+
const linkPath = join(tmp, 'link');
|
|
114
|
+
fs.mkdirSync(target, { recursive: true });
|
|
115
|
+
const result = ensureSymlinkSafe(target, linkPath, { name: 'test' });
|
|
116
|
+
expect(result.status).toBe('ok');
|
|
117
|
+
expect(result.action).toBe('created');
|
|
118
|
+
expect(fs.readlinkSync(linkPath)).toBe(target);
|
|
119
|
+
});
|
|
120
|
+
it('skips when symlink already points to correct target', () => {
|
|
121
|
+
const target = join(tmp, 'target');
|
|
122
|
+
const linkPath = join(tmp, 'link');
|
|
123
|
+
fs.mkdirSync(target, { recursive: true });
|
|
124
|
+
fs.symlinkSync(target, linkPath);
|
|
125
|
+
const result = ensureSymlinkSafe(target, linkPath, { name: 'test' });
|
|
126
|
+
expect(result.status).toBe('skip');
|
|
127
|
+
expect(result.action).toBe('already_correct');
|
|
128
|
+
});
|
|
129
|
+
it('replaces symlink with different target', () => {
|
|
130
|
+
const target1 = join(tmp, 'target1');
|
|
131
|
+
const target2 = join(tmp, 'target2');
|
|
132
|
+
const linkPath = join(tmp, 'link');
|
|
133
|
+
fs.mkdirSync(target1, { recursive: true });
|
|
134
|
+
fs.mkdirSync(target2, { recursive: true });
|
|
135
|
+
fs.symlinkSync(target1, linkPath);
|
|
136
|
+
const result = ensureSymlinkSafe(target2, linkPath, { name: 'test' });
|
|
137
|
+
expect(result.status).toBe('ok');
|
|
138
|
+
expect(result.action).toBe('replace_symlink');
|
|
139
|
+
expect(fs.readlinkSync(linkPath)).toBe(target2);
|
|
140
|
+
});
|
|
141
|
+
it('BLOCKS circular symlink creation (cycle_detected)', () => {
|
|
142
|
+
const a = join(tmp, 'a');
|
|
143
|
+
const b = join(tmp, 'b');
|
|
144
|
+
fs.mkdirSync(a, { recursive: true });
|
|
145
|
+
fs.symlinkSync(a, b);
|
|
146
|
+
// Trying to create a → b would form cycle a → b → a
|
|
147
|
+
const result = ensureSymlinkSafe(b, a, { name: 'test' });
|
|
148
|
+
expect(result.status).toBe('error');
|
|
149
|
+
expect(result.action).toBe('cycle_detected');
|
|
150
|
+
// a should NOT be a symlink — it should remain a real directory
|
|
151
|
+
expect(fs.lstatSync(a).isDirectory()).toBe(true);
|
|
152
|
+
});
|
|
153
|
+
it('backs up real directory and creates symlink', () => {
|
|
154
|
+
const target = join(tmp, 'target');
|
|
155
|
+
const linkPath = join(tmp, 'existing-dir');
|
|
156
|
+
fs.mkdirSync(target, { recursive: true });
|
|
157
|
+
fs.mkdirSync(linkPath, { recursive: true });
|
|
158
|
+
touch(join(linkPath, 'file.txt'), 'original');
|
|
159
|
+
const result = ensureSymlinkSafe(target, linkPath, {
|
|
160
|
+
name: 'test', onConflict: 'backup',
|
|
161
|
+
});
|
|
162
|
+
expect(result.status).toBe('ok');
|
|
163
|
+
expect(result.action).toBe('backup_and_link');
|
|
164
|
+
expect(fs.lstatSync(linkPath).isSymbolicLink()).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
it('skips conflict when onConflict=skip', () => {
|
|
167
|
+
const target = join(tmp, 'target');
|
|
168
|
+
const linkPath = join(tmp, 'existing-dir');
|
|
169
|
+
fs.mkdirSync(target, { recursive: true });
|
|
170
|
+
fs.mkdirSync(linkPath, { recursive: true });
|
|
171
|
+
const result = ensureSymlinkSafe(target, linkPath, {
|
|
172
|
+
name: 'test', onConflict: 'skip',
|
|
173
|
+
});
|
|
174
|
+
expect(result.status).toBe('skip');
|
|
175
|
+
expect(result.action).toBe('skip_conflict');
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
// ─── resolveSymlinkTarget ─────────────────────────
|
|
179
|
+
describe('resolveSymlinkTarget', () => {
|
|
180
|
+
it('returns absolute target as-is', () => {
|
|
181
|
+
expect(resolveSymlinkTarget('/foo/link', '/bar/target')).toBe('/bar/target');
|
|
182
|
+
});
|
|
183
|
+
it('resolves relative target from link directory', () => {
|
|
184
|
+
const result = resolveSymlinkTarget('/foo/bar/link', '../baz');
|
|
185
|
+
expect(result).toBe(resolve('/foo/bar', '../baz'));
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
// ─── syncSkills ───────────────────────────────────
|
|
189
|
+
describe('syncSkills', () => {
|
|
190
|
+
let tmp;
|
|
191
|
+
beforeEach(() => { tmp = tmpDir(); });
|
|
192
|
+
afterEach(() => { cleanDir(tmp); });
|
|
193
|
+
it('creates symlinks from .agents/skills source to .agent and .claude', () => {
|
|
194
|
+
const source = join(tmp, '.agents', 'skills');
|
|
195
|
+
makeSkillDir(source, 'test-skill');
|
|
196
|
+
const result = syncSkills(tmp, source);
|
|
197
|
+
expect(result.source).toBe(source);
|
|
198
|
+
// .agents/skills is source → skipped
|
|
199
|
+
const agentsLink = result.links.find(l => l.name === 'agents_skills');
|
|
200
|
+
expect(agentsLink?.status).toBe('skip');
|
|
201
|
+
expect(agentsLink?.action).toBe('is_source');
|
|
202
|
+
// .agent/skills should be created
|
|
203
|
+
const agentLink = result.links.find(l => l.name === 'agent_skills');
|
|
204
|
+
expect(agentLink?.status).toBe('ok');
|
|
205
|
+
// .claude/skills should be created
|
|
206
|
+
const claudeLink = result.links.find(l => l.name === 'claude_skills');
|
|
207
|
+
expect(claudeLink?.status).toBe('ok');
|
|
208
|
+
});
|
|
209
|
+
it('detects same resolved path and skips (symlink-to-source)', () => {
|
|
210
|
+
// .agents/skills is real dir, .agent/skills → .agents/skills
|
|
211
|
+
const source = join(tmp, '.agents', 'skills');
|
|
212
|
+
makeSkillDir(source, 'my-skill');
|
|
213
|
+
const agentSkills = join(tmp, '.agent', 'skills');
|
|
214
|
+
fs.mkdirSync(join(tmp, '.agent'), { recursive: true });
|
|
215
|
+
fs.symlinkSync(source, agentSkills);
|
|
216
|
+
const result = syncSkills(tmp, source);
|
|
217
|
+
// .agent/skills resolves to .agents/skills (same as source) → skip
|
|
218
|
+
const agentLink = result.links.find(l => l.name === 'agent_skills');
|
|
219
|
+
expect(agentLink?.status).toBe('skip');
|
|
220
|
+
expect(agentLink?.action).toBe('is_source');
|
|
221
|
+
});
|
|
222
|
+
it('PREVENTS circular symlink in the incident scenario', () => {
|
|
223
|
+
// Reproduce the exact scenario that caused the incident:
|
|
224
|
+
// 1. .agents/skills = real dir (29 skills)
|
|
225
|
+
// 2. .agent/skills = symlink → ../.agents/skills (set up long ago)
|
|
226
|
+
// 3. User selects .agents/skills as source
|
|
227
|
+
// Expected: NO circular symlink created
|
|
228
|
+
const source = join(tmp, '.agents', 'skills');
|
|
229
|
+
makeSkillDir(source, 'api-proxy');
|
|
230
|
+
makeSkillDir(source, 'browser');
|
|
231
|
+
makeSkillDir(source, 'ccs');
|
|
232
|
+
// Pre-existing reverse symlink
|
|
233
|
+
const agentSkills = join(tmp, '.agent', 'skills');
|
|
234
|
+
fs.mkdirSync(join(tmp, '.agent'), { recursive: true });
|
|
235
|
+
fs.symlinkSync(join('..', '.agents', 'skills'), agentSkills);
|
|
236
|
+
const result = syncSkills(tmp, source);
|
|
237
|
+
// .agents/skills is source → skip
|
|
238
|
+
const agentsResult = result.links.find(l => l.name === 'agents_skills');
|
|
239
|
+
expect(agentsResult?.status).toBe('skip');
|
|
240
|
+
// .agent/skills already points to source → skip (resolved paths match)
|
|
241
|
+
const agentResult = result.links.find(l => l.name === 'agent_skills');
|
|
242
|
+
expect(agentResult?.status).toBe('skip');
|
|
243
|
+
expect(agentResult?.action).toBe('is_source');
|
|
244
|
+
// .agents/skills should STILL be a real directory, NOT a symlink
|
|
245
|
+
expect(fs.lstatSync(source).isDirectory()).toBe(true);
|
|
246
|
+
expect(fs.lstatSync(source).isSymbolicLink()).toBe(false);
|
|
247
|
+
// Skills should still be accessible
|
|
248
|
+
const skills = listSkills(source);
|
|
249
|
+
expect(skills).toContain('api-proxy');
|
|
250
|
+
expect(skills).toContain('browser');
|
|
251
|
+
expect(skills).toContain('ccs');
|
|
252
|
+
});
|
|
253
|
+
it('blocks ensureSymlinkSafe from creating cycle in edge case', () => {
|
|
254
|
+
// Edge case: .agent/skills is source, .agents/skills = symlink → .agent/skills
|
|
255
|
+
// Then syncSkills tries .agents/skills → canonical (.agent/skills)
|
|
256
|
+
// This should be caught by cycle detection
|
|
257
|
+
const source = join(tmp, '.agent', 'skills');
|
|
258
|
+
makeSkillDir(source, 'test-skill');
|
|
259
|
+
// .agents/skills already points to .agent/skills
|
|
260
|
+
fs.mkdirSync(join(tmp, '.agents'), { recursive: true });
|
|
261
|
+
fs.symlinkSync(source, join(tmp, '.agents', 'skills'));
|
|
262
|
+
const result = syncSkills(tmp, source);
|
|
263
|
+
// No link should have created a cycle
|
|
264
|
+
for (const link of result.links) {
|
|
265
|
+
if (link.status === 'error') {
|
|
266
|
+
expect(link.action).toBe('cycle_detected');
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// Source should still be intact
|
|
270
|
+
expect(fs.lstatSync(source).isDirectory()).toBe(true);
|
|
271
|
+
const skills = listSkills(source);
|
|
272
|
+
expect(skills).toContain('test-skill');
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
// ─── detectSkillSources ──────────────────────────
|
|
276
|
+
describe('detectSkillSources', () => {
|
|
277
|
+
let tmp;
|
|
278
|
+
beforeEach(() => { tmp = tmpDir(); });
|
|
279
|
+
afterEach(() => { cleanDir(tmp); });
|
|
280
|
+
it('detects skills in .agents/skills', () => {
|
|
281
|
+
const skillDir = join(tmp, '.agents', 'skills');
|
|
282
|
+
makeSkillDir(skillDir, 'test-skill');
|
|
283
|
+
const candidates = detectSkillSources(tmp);
|
|
284
|
+
expect(candidates.length).toBeGreaterThanOrEqual(1);
|
|
285
|
+
const match = candidates.find(c => c.label.includes('.agents'));
|
|
286
|
+
expect(match).toBeDefined();
|
|
287
|
+
expect(match.count).toBe(1);
|
|
288
|
+
});
|
|
289
|
+
it('deduplicates symlinked directories', () => {
|
|
290
|
+
const real = join(tmp, '.agents', 'skills');
|
|
291
|
+
makeSkillDir(real, 'test-skill');
|
|
292
|
+
// .agent/skills → .agents/skills
|
|
293
|
+
fs.mkdirSync(join(tmp, '.agent'), { recursive: true });
|
|
294
|
+
fs.symlinkSync(real, join(tmp, '.agent', 'skills'));
|
|
295
|
+
const candidates = detectSkillSources(tmp);
|
|
296
|
+
// Should only detect once, not twice
|
|
297
|
+
expect(candidates.length).toBe(1);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
// ─── listSkills ───────────────────────────────────
|
|
301
|
+
describe('listSkills', () => {
|
|
302
|
+
let tmp;
|
|
303
|
+
beforeEach(() => { tmp = tmpDir(); });
|
|
304
|
+
afterEach(() => { cleanDir(tmp); });
|
|
305
|
+
it('lists skill directories', () => {
|
|
306
|
+
makeSkillDir(tmp, 'alpha');
|
|
307
|
+
makeSkillDir(tmp, 'beta');
|
|
308
|
+
touch(join(tmp, 'not-a-skill.txt'), 'file');
|
|
309
|
+
const skills = listSkills(tmp);
|
|
310
|
+
expect(skills).toEqual(['alpha', 'beta']);
|
|
311
|
+
});
|
|
312
|
+
it('returns empty for non-existent directory', () => {
|
|
313
|
+
expect(listSkills('/nonexistent-12345')).toEqual([]);
|
|
314
|
+
});
|
|
315
|
+
it('ignores dotfiles and registry.json', () => {
|
|
316
|
+
makeSkillDir(tmp, 'real-skill');
|
|
317
|
+
fs.mkdirSync(join(tmp, '.hidden'), { recursive: true });
|
|
318
|
+
touch(join(tmp, 'registry.json'), '{}');
|
|
319
|
+
const skills = listSkills(tmp);
|
|
320
|
+
expect(skills).toEqual(['real-skill']);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
// ─── copyDirRecursive ─────────────────────────────
|
|
324
|
+
describe('copyDirRecursive', () => {
|
|
325
|
+
let tmp;
|
|
326
|
+
beforeEach(() => { tmp = tmpDir(); });
|
|
327
|
+
afterEach(() => { cleanDir(tmp); });
|
|
328
|
+
it('copies directory structure and files', () => {
|
|
329
|
+
const src = join(tmp, 'src');
|
|
330
|
+
const dst = join(tmp, 'dst');
|
|
331
|
+
makeSkillDir(src, 'skill-a');
|
|
332
|
+
touch(join(src, 'README.md'), '# Hello');
|
|
333
|
+
copyDirRecursive(src, dst);
|
|
334
|
+
expect(fs.existsSync(join(dst, 'skill-a', 'SKILL.md'))).toBe(true);
|
|
335
|
+
expect(fs.readFileSync(join(dst, 'README.md'), 'utf8')).toBe('# Hello');
|
|
336
|
+
});
|
|
337
|
+
it('skips broken symlinks without throwing', () => {
|
|
338
|
+
const src = join(tmp, 'src');
|
|
339
|
+
const dst = join(tmp, 'dst');
|
|
340
|
+
fs.mkdirSync(src, { recursive: true });
|
|
341
|
+
touch(join(src, 'file.txt'), 'ok');
|
|
342
|
+
fs.symlinkSync('/nonexistent-path-12345', join(src, 'broken-link'));
|
|
343
|
+
// Should not throw
|
|
344
|
+
expect(() => copyDirRecursive(src, dst)).not.toThrow();
|
|
345
|
+
expect(fs.readFileSync(join(dst, 'file.txt'), 'utf8')).toBe('ok');
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
//# sourceMappingURL=symlink.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symlink.test.js","sourceRoot":"","sources":["../../src/__tests__/symlink.test.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -18,7 +18,7 @@ import { ensureHome, MCP_PATH, AGENT_SYNC_HOME } from './core/config.js';
|
|
|
18
18
|
import { detectPromptFiles, generateAgentsMd } from './core/agents-md.js';
|
|
19
19
|
import { detectSkillSources, syncSkills, listSkills } from './core/skill-sync.js';
|
|
20
20
|
import { detectMcpConfigs, loadMcpConfig, saveMcpConfig, syncToAll, importFromClaude } from './core/mcp-sync.js';
|
|
21
|
-
const VERSION = '0.1.
|
|
21
|
+
const VERSION = '0.1.9';
|
|
22
22
|
const cwd = process.cwd();
|
|
23
23
|
// ─── Subcommand routing ───────────────────────────
|
|
24
24
|
async function main() {
|
package/dist/core/skill-sync.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* {cwd}/.claude/skills/ → .agent/skills (symlink)
|
|
9
9
|
*/
|
|
10
10
|
import fs from 'node:fs';
|
|
11
|
-
import { join } from 'node:path';
|
|
11
|
+
import { join, resolve } from 'node:path';
|
|
12
12
|
import { ensureSymlinkSafe, createBackupContext } from './symlink.js';
|
|
13
13
|
export function detectSkillSources(cwd) {
|
|
14
14
|
const candidates = [];
|
|
@@ -50,27 +50,74 @@ export function detectSkillSources(cwd) {
|
|
|
50
50
|
}
|
|
51
51
|
return candidates;
|
|
52
52
|
}
|
|
53
|
+
// ─── Resolve paths safely (ELOOP-aware) ──────────
|
|
54
|
+
function safeRealPath(p) {
|
|
55
|
+
try {
|
|
56
|
+
return fs.realpathSync(p);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// ELOOP (circular) or ENOENT (missing) — fall back to string resolution
|
|
60
|
+
return resolve(p);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Returns true if `p` (possibly a symlink) resolves to the SAME real directory
|
|
65
|
+
* as `realSource`. Uses lstat to avoid ELOOP when p itself is a circular link.
|
|
66
|
+
*/
|
|
67
|
+
function isSameRealDir(p, realSource) {
|
|
68
|
+
const stat = fs.lstatSync(p, { throwIfNoEntry: false });
|
|
69
|
+
if (!stat)
|
|
70
|
+
return false;
|
|
71
|
+
if (!stat.isSymbolicLink()) {
|
|
72
|
+
// Real entry — compare inodes instead of paths to handle hardlinks/bind-mounts
|
|
73
|
+
try {
|
|
74
|
+
const statReal = fs.statSync(realSource);
|
|
75
|
+
return stat.ino === statReal.ino && stat.dev === statReal.dev;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// It's a symlink — follow it safely
|
|
82
|
+
try {
|
|
83
|
+
const resolved = fs.realpathSync(p);
|
|
84
|
+
return resolved === realSource;
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
// ELOOP means it's already circular — definitely NOT the same real dir
|
|
88
|
+
if (e.code === 'ELOOP')
|
|
89
|
+
return false;
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
53
93
|
export function syncSkills(cwd, sourcePath) {
|
|
54
94
|
const backupContext = createBackupContext();
|
|
55
95
|
const links = [];
|
|
96
|
+
// Resolve source to real path.
|
|
97
|
+
// NOTE: safeRealPath falls back to resolve() on ELOOP, so we must NOT rely
|
|
98
|
+
// solely on string comparison for is_source detection — use isSameRealDir.
|
|
99
|
+
const resolvedSource = safeRealPath(sourcePath);
|
|
56
100
|
// Target paths within the project
|
|
57
101
|
const targets = [
|
|
58
102
|
['agent_skills', join(cwd, '.agent', 'skills')],
|
|
59
103
|
['agents_skills', join(cwd, '.agents', 'skills')],
|
|
60
104
|
['claude_skills', join(cwd, '.claude', 'skills')],
|
|
61
105
|
];
|
|
62
|
-
// Determine canonical location (
|
|
106
|
+
// Determine canonical location (.agent/skills is the stable reference)
|
|
63
107
|
const canonicalPath = join(cwd, '.agent', 'skills');
|
|
108
|
+
const resolvedCanonical = safeRealPath(canonicalPath);
|
|
64
109
|
for (const [name, targetPath] of targets) {
|
|
65
|
-
|
|
66
|
-
|
|
110
|
+
// Use isSameRealDir to detect source even through ELOOP or inode equality
|
|
111
|
+
if (isSameRealDir(targetPath, resolvedSource)) {
|
|
112
|
+
// Target IS the real source directory — never overwrite it
|
|
67
113
|
links.push({
|
|
68
114
|
status: 'skip', action: 'is_source', name, linkPath: targetPath, target: sourcePath,
|
|
69
115
|
});
|
|
70
116
|
continue;
|
|
71
117
|
}
|
|
72
|
-
|
|
73
|
-
|
|
118
|
+
const resolvedTarget = safeRealPath(targetPath);
|
|
119
|
+
if (resolvedTarget === resolvedCanonical && resolvedSource !== resolvedCanonical) {
|
|
120
|
+
// .agent/skills-style path: symlink → source
|
|
74
121
|
links.push(ensureSymlinkSafe(sourcePath, targetPath, {
|
|
75
122
|
onConflict: 'backup', backupContext, name,
|
|
76
123
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-sync.js","sourceRoot":"","sources":["../../src/core/skill-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"skill-sync.js","sourceRoot":"","sources":["../../src/core/skill-sync.ts"],"names":[],"mappings":"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"}
|
package/dist/core/symlink.d.ts
CHANGED
|
@@ -4,6 +4,11 @@ interface BackupContext {
|
|
|
4
4
|
}
|
|
5
5
|
export declare function createBackupContext(): BackupContext;
|
|
6
6
|
export declare function resolveSymlinkTarget(linkPath: string, rawTarget: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Detect if creating a symlink linkPath → target would form a cycle.
|
|
9
|
+
* Handles ELOOP (already-circular) targets and deep chains.
|
|
10
|
+
*/
|
|
11
|
+
export declare function wouldCreateCycle(target: string, linkPath: string): boolean;
|
|
7
12
|
export interface SymlinkResult {
|
|
8
13
|
status: 'ok' | 'skip' | 'error';
|
|
9
14
|
action: string;
|
package/dist/core/symlink.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Extracted from cli-jaw lib/mcp-sync.ts
|
|
4
4
|
*/
|
|
5
5
|
import fs from 'node:fs';
|
|
6
|
-
import { join, dirname, resolve } from 'node:path';
|
|
6
|
+
import { join, dirname, resolve, basename } from 'node:path';
|
|
7
7
|
import { AGENT_SYNC_HOME } from './config.js';
|
|
8
8
|
export function createBackupContext() {
|
|
9
9
|
const root = join(AGENT_SYNC_HOME, 'backups', new Date().toISOString().slice(0, 10));
|
|
@@ -14,12 +14,72 @@ export function resolveSymlinkTarget(linkPath, rawTarget) {
|
|
|
14
14
|
return rawTarget;
|
|
15
15
|
return resolve(dirname(linkPath), rawTarget);
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Detect if creating a symlink linkPath → target would form a cycle.
|
|
19
|
+
* Handles ELOOP (already-circular) targets and deep chains.
|
|
20
|
+
*/
|
|
21
|
+
export function wouldCreateCycle(target, linkPath) {
|
|
22
|
+
try {
|
|
23
|
+
// Resolve target — ELOOP means it's already part of a circular chain
|
|
24
|
+
let realTarget;
|
|
25
|
+
try {
|
|
26
|
+
realTarget = fs.realpathSync(target);
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
if (e.code === 'ELOOP')
|
|
30
|
+
return true;
|
|
31
|
+
// ENOENT or other — target doesn't exist yet, resolve as string
|
|
32
|
+
realTarget = resolve(target);
|
|
33
|
+
}
|
|
34
|
+
// Resolve linkPath's parent (linkPath itself may not exist yet)
|
|
35
|
+
let realLinkParent;
|
|
36
|
+
try {
|
|
37
|
+
realLinkParent = fs.realpathSync(dirname(linkPath));
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
realLinkParent = resolve(dirname(linkPath));
|
|
41
|
+
}
|
|
42
|
+
const resolvedLinkPath = join(realLinkParent, basename(linkPath));
|
|
43
|
+
// Direct cycle: target resolves to linkPath itself
|
|
44
|
+
if (realTarget === resolvedLinkPath)
|
|
45
|
+
return true;
|
|
46
|
+
// Walk the symlink chain from target, check if any hop leads back to linkPath
|
|
47
|
+
let current = target;
|
|
48
|
+
const visited = new Set();
|
|
49
|
+
const MAX_DEPTH = 40; // SYMLOOP_MAX on most systems
|
|
50
|
+
let depth = 0;
|
|
51
|
+
while (depth++ < MAX_DEPTH) {
|
|
52
|
+
const stat = fs.lstatSync(current, { throwIfNoEntry: false });
|
|
53
|
+
if (!stat || !stat.isSymbolicLink())
|
|
54
|
+
break;
|
|
55
|
+
current = resolveSymlinkTarget(current, fs.readlinkSync(current));
|
|
56
|
+
if (visited.has(current))
|
|
57
|
+
return true;
|
|
58
|
+
if (current === resolvedLinkPath)
|
|
59
|
+
return true;
|
|
60
|
+
visited.add(current);
|
|
61
|
+
}
|
|
62
|
+
if (depth >= MAX_DEPTH)
|
|
63
|
+
return true; // too deep = likely cycle
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false; // genuinely unknown, proceed cautiously
|
|
68
|
+
}
|
|
69
|
+
}
|
|
17
70
|
export function ensureSymlinkSafe(target, linkPath, opts = {}) {
|
|
18
71
|
const onConflict = opts.onConflict ?? 'backup';
|
|
19
72
|
const name = opts.name ?? 'link';
|
|
20
73
|
const context = opts.backupContext ?? createBackupContext();
|
|
21
74
|
try {
|
|
22
75
|
fs.mkdirSync(dirname(linkPath), { recursive: true });
|
|
76
|
+
// Cycle guard — covers ALL creation paths below
|
|
77
|
+
if (wouldCreateCycle(target, linkPath)) {
|
|
78
|
+
return {
|
|
79
|
+
status: 'error', action: 'cycle_detected', name, linkPath, target,
|
|
80
|
+
error: `Circular symlink: ${linkPath} → ${target} would create a loop`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
23
83
|
const stat = fs.lstatSync(linkPath, { throwIfNoEntry: false });
|
|
24
84
|
if (stat) {
|
|
25
85
|
if (stat.isSymbolicLink()) {
|
|
@@ -30,7 +90,7 @@ export function ensureSymlinkSafe(target, linkPath, opts = {}) {
|
|
|
30
90
|
}
|
|
31
91
|
// Different target — update
|
|
32
92
|
fs.unlinkSync(linkPath);
|
|
33
|
-
|
|
93
|
+
createLinkWithFallback(target, linkPath);
|
|
34
94
|
return { status: 'ok', action: 'replace_symlink', name, linkPath, target };
|
|
35
95
|
}
|
|
36
96
|
// Real directory or file — conflict
|
|
@@ -39,17 +99,41 @@ export function ensureSymlinkSafe(target, linkPath, opts = {}) {
|
|
|
39
99
|
}
|
|
40
100
|
// Backup and replace
|
|
41
101
|
movePathToBackup(linkPath, context);
|
|
42
|
-
|
|
102
|
+
createLinkWithFallback(target, linkPath);
|
|
43
103
|
return { status: 'ok', action: 'backup_and_link', name, linkPath, target };
|
|
44
104
|
}
|
|
45
105
|
// Nothing exists — create
|
|
46
|
-
|
|
106
|
+
createLinkWithFallback(target, linkPath);
|
|
47
107
|
return { status: 'ok', action: 'created', name, linkPath, target };
|
|
48
108
|
}
|
|
49
109
|
catch (e) {
|
|
50
110
|
return { status: 'error', action: 'error', name, linkPath, target, error: e.message };
|
|
51
111
|
}
|
|
52
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Try symlink → junction (Windows) → directory copy fallback.
|
|
115
|
+
* WSL/macOS/Linux: symlink always works.
|
|
116
|
+
* Native Windows: symlink needs Developer Mode; junction works without it;
|
|
117
|
+
* copy is the last resort.
|
|
118
|
+
*/
|
|
119
|
+
function createLinkWithFallback(target, linkPath) {
|
|
120
|
+
// 1. Try regular symlink
|
|
121
|
+
try {
|
|
122
|
+
fs.symlinkSync(target, linkPath);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
catch { /* continue to fallback */ }
|
|
126
|
+
// 2. Try junction (Windows only, no admin required)
|
|
127
|
+
if (process.platform === 'win32') {
|
|
128
|
+
try {
|
|
129
|
+
fs.symlinkSync(target, linkPath, 'junction');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
catch { /* continue to fallback */ }
|
|
133
|
+
}
|
|
134
|
+
// 3. Fall back to directory copy
|
|
135
|
+
copyDirRecursive(target, linkPath);
|
|
136
|
+
}
|
|
53
137
|
function movePathToBackup(pathToMove, context) {
|
|
54
138
|
fs.mkdirSync(context.root, { recursive: true });
|
|
55
139
|
const base = pathToMove.replace(/\//g, '__').replace(/^__/, '');
|
package/dist/core/symlink.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symlink.js","sourceRoot":"","sources":["../../src/core/symlink.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"symlink.js","sourceRoot":"","sources":["../../src/core/symlink.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAO9C,MAAM,UAAU,mBAAmB;IAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACrF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,SAAiB;IACpE,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAChD,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;AACjD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,QAAgB;IAC7D,IAAI,CAAC;QACD,qEAAqE;QACrE,IAAI,UAAkB,CAAC;QACvB,IAAI,CAAC;YACD,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YAClB,IAAK,CAA2B,CAAC,IAAI,KAAK,OAAO;gBAAE,OAAO,IAAI,CAAC;YAC/D,gEAAgE;YAChE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,gEAAgE;QAChE,IAAI,cAAsB,CAAC;QAC3B,IAAI,CAAC;YACD,cAAc,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACL,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QAChD,CAAC;QACD,MAAM,gBAAgB,GAAG,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAElE,mDAAmD;QACnD,IAAI,UAAU,KAAK,gBAAgB;YAAE,OAAO,IAAI,CAAC;QAEjD,8EAA8E;QAC9E,IAAI,OAAO,GAAG,MAAM,CAAC;QACrB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC,8BAA8B;QACpD,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,OAAO,KAAK,EAAE,GAAG,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,KAAK,EAAS,CAAC,CAAC;YACrE,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;gBAAE,MAAM;YAC3C,OAAO,GAAG,oBAAoB,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;YAClE,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,OAAO,IAAI,CAAC;YACtC,IAAI,OAAO,KAAK,gBAAgB;gBAAE,OAAO,IAAI,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,KAAK,IAAI,SAAS;YAAE,OAAO,IAAI,CAAC,CAAC,0BAA0B;QAC/D,OAAO,KAAK,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC,CAAC,wCAAwC;IAC1D,CAAC;AACL,CAAC;AAWD,MAAM,UAAU,iBAAiB,CAC7B,MAAc,EACd,QAAgB,EAChB,OAA8E,EAAE;IAEhF,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,QAAQ,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,IAAI,mBAAmB,EAAE,CAAC;IAE5D,IAAI,CAAC;QACD,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAErD,gDAAgD;QAChD,IAAI,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;YACrC,OAAO;gBACH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM;gBACjE,KAAK,EAAE,qBAAqB,QAAQ,MAAM,MAAM,sBAAsB;aACzE,CAAC;QACN,CAAC;QAED,MAAM,IAAI,GAAG,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,KAAK,EAAS,CAAC,CAAC;QAEtE,IAAI,IAAI,EAAE,CAAC;YACP,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;gBACxB,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAC5C,MAAM,aAAa,GAAG,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;gBAChE,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;oBAC3B,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;gBACjF,CAAC;gBACD,4BAA4B;gBAC5B,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACxB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;gBACzC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YAC/E,CAAC;YAED,oCAAoC;YACpC,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;gBACxB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YAC/E,CAAC;YAED,qBAAqB;YACrB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACpC,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACzC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC/E,CAAC;QAED,0BAA0B;QAC1B,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACzC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACvE,CAAC;IAAC,OAAO,CAAU,EAAE,CAAC;QAClB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC;IACrG,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,SAAS,sBAAsB,CAAC,MAAc,EAAE,QAAgB;IAC5D,yBAAyB;IACzB,IAAI,CAAC;QACD,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACjC,OAAO;IACX,CAAC;IAAC,MAAM,CAAC,CAAC,0BAA0B,CAAC,CAAC;IAEtC,oDAAoD;IACpD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC/B,IAAI,CAAC;YACD,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;YAC7C,OAAO;QACX,CAAC;QAAC,MAAM,CAAC,CAAC,0BAA0B,CAAC,CAAC;IAC1C,CAAC;IAED,iCAAiC;IACjC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB,EAAE,OAAsB;IAChE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC9D,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,GAAW;IACrD,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACtC,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;gBACzB,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACJ,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACtC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,4CAA4C;QAChD,CAAC;IACL,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED