@mrpatronz/nexusflow 1.7.0 → 1.9.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/README.md +57 -23
- package/dist/agent/AntigravityCliAdapter.d.ts +7 -0
- package/dist/agent/AntigravityCliAdapter.d.ts.map +1 -0
- package/dist/agent/AntigravityCliAdapter.js +13 -0
- package/dist/agent/AntigravityCliAdapter.js.map +1 -0
- package/dist/agent/ClaudeCliAdapter.d.ts +16 -0
- package/dist/agent/ClaudeCliAdapter.d.ts.map +1 -0
- package/dist/agent/ClaudeCliAdapter.js +34 -0
- package/dist/agent/ClaudeCliAdapter.js.map +1 -0
- package/dist/agent/CliAdapterBase.d.ts +48 -0
- package/dist/agent/CliAdapterBase.d.ts.map +1 -0
- package/dist/agent/CliAdapterBase.js +120 -0
- package/dist/agent/CliAdapterBase.js.map +1 -0
- package/dist/agent/NativeAgent.d.ts +13 -0
- package/dist/agent/NativeAgent.d.ts.map +1 -0
- package/dist/agent/NativeAgent.js +97 -0
- package/dist/agent/NativeAgent.js.map +1 -0
- package/dist/agent/NativeAgentBase.d.ts +27 -0
- package/dist/agent/NativeAgentBase.d.ts.map +1 -0
- package/dist/agent/NativeAgentBase.js +58 -0
- package/dist/agent/NativeAgentBase.js.map +1 -0
- package/dist/agent/NativeClaudeAgent.d.ts +13 -0
- package/dist/agent/NativeClaudeAgent.d.ts.map +1 -0
- package/dist/agent/NativeClaudeAgent.js +115 -0
- package/dist/agent/NativeClaudeAgent.js.map +1 -0
- package/dist/agent/NativeGoogleAgent.d.ts +13 -0
- package/dist/agent/NativeGoogleAgent.d.ts.map +1 -0
- package/dist/agent/NativeGoogleAgent.js +90 -0
- package/dist/agent/NativeGoogleAgent.js.map +1 -0
- package/dist/agent/ProviderRegistry.d.ts +31 -0
- package/dist/agent/ProviderRegistry.d.ts.map +1 -0
- package/dist/agent/ProviderRegistry.js +20 -0
- package/dist/agent/ProviderRegistry.js.map +1 -0
- package/dist/agent/ProviderRegistry.test.d.ts +2 -0
- package/dist/agent/ProviderRegistry.test.d.ts.map +1 -0
- package/dist/agent/ProviderRegistry.test.js +57 -0
- package/dist/agent/ProviderRegistry.test.js.map +1 -0
- package/dist/agent/adapters.d.ts +3 -0
- package/dist/agent/adapters.d.ts.map +1 -0
- package/dist/agent/adapters.js +48 -0
- package/dist/agent/adapters.js.map +1 -0
- package/dist/agent/nativeAgent.test.d.ts +2 -0
- package/dist/agent/nativeAgent.test.d.ts.map +1 -0
- package/dist/agent/nativeAgent.test.js +35 -0
- package/dist/agent/nativeAgent.test.js.map +1 -0
- package/dist/agent/nativeTools.d.ts +26 -0
- package/dist/agent/nativeTools.d.ts.map +1 -0
- package/dist/agent/nativeTools.js +62 -0
- package/dist/agent/nativeTools.js.map +1 -0
- package/dist/agent/nativeTools.test.d.ts +2 -0
- package/dist/agent/nativeTools.test.d.ts.map +1 -0
- package/dist/agent/nativeTools.test.js +67 -0
- package/dist/agent/nativeTools.test.js.map +1 -0
- package/dist/agent/session.d.ts +25 -0
- package/dist/agent/session.d.ts.map +1 -0
- package/dist/agent/session.js +31 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/agent/session.test.d.ts +2 -0
- package/dist/agent/session.test.d.ts.map +1 -0
- package/dist/agent/session.test.js +44 -0
- package/dist/agent/session.test.js.map +1 -0
- package/dist/commands/create.d.ts +8 -7
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +134 -65
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/desktop.d.ts +4 -5
- package/dist/commands/desktop.d.ts.map +1 -1
- package/dist/commands/desktop.js +35 -89
- package/dist/commands/desktop.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +0 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -72
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +2 -1
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/project.d.ts +30 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +125 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/refresh.js +1 -1
- package/dist/commands/refresh.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +18 -2
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/stop.d.ts +1 -1
- package/dist/commands/stop.d.ts.map +1 -1
- package/dist/commands/stop.js +19 -2
- package/dist/commands/stop.js.map +1 -1
- package/dist/commands/tui.js +0 -1
- package/dist/commands/tui.js.map +1 -1
- package/dist/commands/ui.d.ts +7 -3
- package/dist/commands/ui.d.ts.map +1 -1
- package/dist/commands/ui.js +12 -6
- package/dist/commands/ui.js.map +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +0 -9
- package/dist/core/config.js.map +1 -1
- package/dist/core/config.test.js +0 -9
- package/dist/core/config.test.js.map +1 -1
- package/dist/core/doctor.d.ts +1 -3
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +18 -69
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/finish.d.ts.map +1 -1
- package/dist/core/finish.js +5 -0
- package/dist/core/finish.js.map +1 -1
- package/dist/core/graph.d.ts.map +1 -1
- package/dist/core/graph.js +2 -1
- package/dist/core/graph.js.map +1 -1
- package/dist/core/projects.d.ts +58 -0
- package/dist/core/projects.d.ts.map +1 -0
- package/dist/core/projects.js +190 -0
- package/dist/core/projects.js.map +1 -0
- package/dist/core/projects.test.d.ts +2 -0
- package/dist/core/projects.test.d.ts.map +1 -0
- package/dist/core/projects.test.js +165 -0
- package/dist/core/projects.test.js.map +1 -0
- package/dist/core/sync.d.ts.map +1 -1
- package/dist/core/sync.js +21 -0
- package/dist/core/sync.js.map +1 -1
- package/dist/core/sync.test.js +15 -0
- package/dist/core/sync.test.js.map +1 -1
- package/dist/core/workspace.create.test.js +68 -1
- package/dist/core/workspace.create.test.js.map +1 -1
- package/dist/core/workspace.d.ts +4 -3
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +138 -64
- package/dist/core/workspace.js.map +1 -1
- package/dist/desktop-server.d.ts +13 -0
- package/dist/desktop-server.d.ts.map +1 -0
- package/dist/desktop-server.js +23 -0
- package/dist/desktop-server.js.map +1 -0
- package/dist/generators/antigravity.js +1 -1
- package/dist/generators/antigravity.js.map +1 -1
- package/dist/generators/base.d.ts +1 -8
- package/dist/generators/base.d.ts.map +1 -1
- package/dist/generators/base.js +107 -58
- package/dist/generators/base.js.map +1 -1
- package/dist/generators/base.test.d.ts +2 -0
- package/dist/generators/base.test.d.ts.map +1 -0
- package/dist/generators/base.test.js +80 -0
- package/dist/generators/base.test.js.map +1 -0
- package/dist/generators/claude.js +1 -1
- package/dist/generators/claude.js.map +1 -1
- package/dist/generators/codex.js +1 -1
- package/dist/generators/codex.js.map +1 -1
- package/dist/generators/copilot.js +1 -1
- package/dist/generators/copilot.js.map +1 -1
- package/dist/generators/cursor.js +1 -1
- package/dist/generators/cursor.js.map +1 -1
- package/dist/generators/diff-context.d.ts.map +1 -1
- package/dist/generators/diff-context.js +3 -1
- package/dist/generators/diff-context.js.map +1 -1
- package/dist/generators/index.js +1 -1
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/map-generator.d.ts.map +1 -1
- package/dist/generators/map-generator.js +3 -1
- package/dist/generators/map-generator.js.map +1 -1
- package/dist/gui/assets/DashboardPage-C3NH97y2.js +1 -0
- package/dist/gui/assets/GettingStartedPage-og-Kv7Sm.js +1 -0
- package/dist/gui/assets/ProjectsPage-COqqadEr.js +1 -0
- package/dist/gui/assets/ScaffoldRepoInline-DRipQsos.js +1 -0
- package/dist/gui/assets/Separator-Chx6O62Y.js +1 -0
- package/dist/gui/assets/SettingsPage-CpU3V9oU.js +1 -0
- package/dist/gui/assets/StartWorkPage-DIND0hJy.js +1 -0
- package/dist/gui/assets/StrategiesPage-6LWOnKdk.js +3 -0
- package/dist/gui/assets/WorkspacesPage-BUqgOhuy.js +6 -0
- package/dist/gui/assets/badge-BnkhqVEF.js +1 -0
- package/dist/gui/assets/button-cPldH5S4.js +1 -0
- package/dist/gui/assets/card-82INhRRE.js +1 -0
- package/dist/gui/assets/circle-plus-C0PNc7h4.js +1 -0
- package/dist/gui/assets/cpu-CPUNnHRM.js +1 -0
- package/dist/gui/assets/empty-DWyDwDYB.js +1 -0
- package/dist/gui/assets/external-link-BtYhMxno.js +1 -0
- package/dist/gui/assets/git-branch-Dw55pQWa.js +1 -0
- package/dist/gui/assets/index-CsA2SueF.css +2 -0
- package/dist/gui/assets/index-CyYbQwRf.js +52 -0
- package/dist/gui/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/gui/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/gui/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/gui/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/gui/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/gui/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/gui/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-100-normal-DlYB2XW3.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-100-normal-DzH8uRxw.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-200-normal-CHn02WOn.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-200-normal-DvzYDkvL.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-300-normal-BYcAiAh2.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-300-normal-DuMDZskh.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-600-normal-BfsvjouI.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-800-normal-D2mQHRMK.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-800-normal-Dj9qwObk.woff +0 -0
- package/dist/gui/assets/label-JFgMNsTn.js +1 -0
- package/dist/gui/assets/search-ChVovkOL.js +1 -0
- package/dist/gui/assets/skeleton-CCPbfn1L.js +1 -0
- package/dist/gui/assets/spinner-DXt6mnJk.js +1 -0
- package/dist/gui/assets/textarea-BLU5HXmZ.js +1 -0
- package/dist/gui/assets/trash-2-Da8F2gKd.js +1 -0
- package/dist/gui/assets/useAriaLabelledBy-CjNlctb9.js +1 -0
- package/dist/gui/assets/useCompositeListItem-DWGFLKqA.js +1 -0
- package/dist/gui/index.html +16 -6
- package/dist/index.js +56 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +4 -63
- package/dist/mcp/tools.js.map +1 -1
- package/dist/orchestration/detect.d.ts.map +1 -1
- package/dist/orchestration/detect.js +72 -26
- package/dist/orchestration/detect.js.map +1 -1
- package/dist/orchestration/index.d.ts +3 -1
- package/dist/orchestration/index.d.ts.map +1 -1
- package/dist/orchestration/index.js +3 -1
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/log-tail.d.ts +27 -0
- package/dist/orchestration/log-tail.d.ts.map +1 -0
- package/dist/orchestration/log-tail.js +93 -0
- package/dist/orchestration/log-tail.js.map +1 -0
- package/dist/orchestration/log-tail.test.d.ts +2 -0
- package/dist/orchestration/log-tail.test.d.ts.map +1 -0
- package/dist/orchestration/log-tail.test.js +72 -0
- package/dist/orchestration/log-tail.test.js.map +1 -0
- package/dist/orchestration/orchestrator.d.ts +26 -0
- package/dist/orchestration/orchestrator.d.ts.map +1 -0
- package/dist/orchestration/orchestrator.js +102 -0
- package/dist/orchestration/orchestrator.js.map +1 -0
- package/dist/orchestration/orchestrator.test.d.ts +2 -0
- package/dist/orchestration/orchestrator.test.d.ts.map +1 -0
- package/dist/orchestration/orchestrator.test.js +85 -0
- package/dist/orchestration/orchestrator.test.js.map +1 -0
- package/dist/orchestration/runner.d.ts +62 -3
- package/dist/orchestration/runner.d.ts.map +1 -1
- package/dist/orchestration/runner.js +198 -103
- package/dist/orchestration/runner.js.map +1 -1
- package/dist/orchestration/runner.test.js +125 -1
- package/dist/orchestration/runner.test.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +395 -126
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +111 -123
- package/dist/server.test.js.map +1 -1
- package/dist/types.d.ts +79 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/feature.d.ts +42 -0
- package/dist/utils/feature.d.ts.map +1 -0
- package/dist/utils/feature.js +52 -0
- package/dist/utils/feature.js.map +1 -0
- package/dist/utils/multi-git.d.ts.map +1 -1
- package/dist/utils/multi-git.js +30 -7
- package/dist/utils/multi-git.js.map +1 -1
- package/dist/utils/session-finder.d.ts +21 -1
- package/dist/utils/session-finder.d.ts.map +1 -1
- package/dist/utils/session-finder.js +220 -143
- package/dist/utils/session-finder.js.map +1 -1
- package/dist/utils/session-finder.test.d.ts +2 -0
- package/dist/utils/session-finder.test.d.ts.map +1 -0
- package/dist/utils/session-finder.test.js +65 -0
- package/dist/utils/session-finder.test.js.map +1 -0
- package/dist/utils/slug.d.ts +12 -0
- package/dist/utils/slug.d.ts.map +1 -0
- package/dist/utils/slug.js +18 -0
- package/dist/utils/slug.js.map +1 -0
- package/dist/utils/test-command.d.ts +12 -0
- package/dist/utils/test-command.d.ts.map +1 -0
- package/dist/utils/test-command.js +22 -0
- package/dist/utils/test-command.js.map +1 -0
- package/dist/utils/update-check.d.ts +8 -0
- package/dist/utils/update-check.d.ts.map +1 -1
- package/dist/utils/update-check.js +13 -7
- package/dist/utils/update-check.js.map +1 -1
- package/dist/utils/update-check.test.d.ts +2 -0
- package/dist/utils/update-check.test.d.ts.map +1 -0
- package/dist/utils/update-check.test.js +25 -0
- package/dist/utils/update-check.test.js.map +1 -0
- package/dist/utils/workflow-advisor.d.ts +2 -2
- package/dist/utils/workflow-advisor.d.ts.map +1 -1
- package/dist/utils/workflow-advisor.js +50 -92
- package/dist/utils/workflow-advisor.js.map +1 -1
- package/dist/utils/workflows.d.ts.map +1 -1
- package/dist/utils/workflows.js +2 -4
- package/dist/utils/workflows.js.map +1 -1
- package/package.json +10 -1
- package/dist/gui/assets/index-CB-Ekvrs.css +0 -1
- package/dist/gui/assets/index-CixLsYSa.js +0 -26
- package/dist/utils/local-ai.d.ts +0 -27
- package/dist/utils/local-ai.d.ts.map +0 -1
- package/dist/utils/local-ai.js +0 -100
- package/dist/utils/local-ai.js.map +0 -1
- package/dist/utils/local-ai.test.d.ts +0 -2
- package/dist/utils/local-ai.test.d.ts.map +0 -1
- package/dist/utils/local-ai.test.js +0 -108
- package/dist/utils/local-ai.test.js.map +0 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import { tailLogFile } from './log-tail.js';
|
|
6
|
+
/** Collects emitted chunks until `predicate` is satisfied or a timeout hits. */
|
|
7
|
+
function collectUntil(file, startOffset, predicate, timeoutMs = 2000) {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
const chunks = [];
|
|
10
|
+
const handle = tailLogFile(file, (chunk) => {
|
|
11
|
+
chunks.push(chunk);
|
|
12
|
+
if (predicate(chunks.join('')))
|
|
13
|
+
resolve({ chunks, stop: handle.stop });
|
|
14
|
+
}, { intervalMs: 15, startOffset });
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
handle.stop();
|
|
17
|
+
reject(new Error(`timeout; got: ${JSON.stringify(chunks)}`));
|
|
18
|
+
}, timeoutMs);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
describe('tailLogFile', () => {
|
|
22
|
+
let dir;
|
|
23
|
+
let file;
|
|
24
|
+
beforeEach(async () => {
|
|
25
|
+
dir = await fs.mkdtemp(path.join(os.tmpdir(), 'nexusflow-tail-'));
|
|
26
|
+
file = path.join(dir, 'svc.log');
|
|
27
|
+
await fs.writeFile(file, 'existing\n', 'utf-8');
|
|
28
|
+
});
|
|
29
|
+
afterEach(async () => {
|
|
30
|
+
await fs.rm(dir, { recursive: true, force: true }).catch(() => { });
|
|
31
|
+
});
|
|
32
|
+
it('emits only bytes appended after the start offset', async () => {
|
|
33
|
+
const size = (await fs.stat(file)).size;
|
|
34
|
+
const wait = collectUntil(file, size, (j) => j.includes('new line'));
|
|
35
|
+
await fs.appendFile(file, 'new line\n', 'utf-8');
|
|
36
|
+
const { chunks, stop } = await wait;
|
|
37
|
+
stop();
|
|
38
|
+
expect(chunks.join('')).toContain('new line');
|
|
39
|
+
expect(chunks.join('')).not.toContain('existing');
|
|
40
|
+
});
|
|
41
|
+
it('resets and streams from the top after truncation', async () => {
|
|
42
|
+
const size = (await fs.stat(file)).size; // 'existing\n' → 9 bytes
|
|
43
|
+
const wait = collectUntil(file, size, (j) => j.includes('fresh'));
|
|
44
|
+
// Rewrite to content SHORTER than the current offset (as PM2 does on
|
|
45
|
+
// rotation) so size < offset triggers the reset-to-top path.
|
|
46
|
+
await fs.writeFile(file, 'fresh\n', 'utf-8');
|
|
47
|
+
const { chunks, stop } = await wait;
|
|
48
|
+
stop();
|
|
49
|
+
expect(chunks.join('')).toContain('fresh');
|
|
50
|
+
});
|
|
51
|
+
it('decodes a multi-byte character split across two appends', async () => {
|
|
52
|
+
const size = (await fs.stat(file)).size;
|
|
53
|
+
const euro = Buffer.from('€', 'utf-8'); // 3 bytes: e2 82 ac
|
|
54
|
+
const wait = collectUntil(file, size, (j) => j.includes('€'));
|
|
55
|
+
await fs.appendFile(file, euro.subarray(0, 1)); // first byte only
|
|
56
|
+
await new Promise((r) => setTimeout(r, 40));
|
|
57
|
+
await fs.appendFile(file, euro.subarray(1)); // remaining bytes
|
|
58
|
+
const { chunks, stop } = await wait;
|
|
59
|
+
stop();
|
|
60
|
+
expect(chunks.join('')).toContain('€');
|
|
61
|
+
});
|
|
62
|
+
it('stop() ends polling (no chunks after stop)', async () => {
|
|
63
|
+
const size = (await fs.stat(file)).size;
|
|
64
|
+
const seen = [];
|
|
65
|
+
const handle = tailLogFile(file, (c) => seen.push(c), { intervalMs: 15, startOffset: size });
|
|
66
|
+
handle.stop();
|
|
67
|
+
await fs.appendFile(file, 'ignored\n', 'utf-8');
|
|
68
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
69
|
+
expect(seen.join('')).not.toContain('ignored');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=log-tail.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-tail.test.js","sourceRoot":"","sources":["../../src/orchestration/log-tail.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module orchestration/orchestrator
|
|
3
|
+
* Executes detected orchestration tools (docker-compose, Aspire, Tilt,
|
|
4
|
+
* Procfile, Makefile). Only the structured `run`/`stopRun` invocations from
|
|
5
|
+
* detection are ever executed — never display strings, never client input.
|
|
6
|
+
*/
|
|
7
|
+
import type { OrchestrationDetection, RunningOrchestrator } from '../types.js';
|
|
8
|
+
/** PM2 app name for a pm2-mode orchestrator: `nexusflow-<ws>-orch-<slug>`. */
|
|
9
|
+
export declare function orchestratorPm2Name(workspacePath: string, detection: OrchestrationDetection): string;
|
|
10
|
+
/** Log source name for a pm2-mode orchestrator (tailable like a service). */
|
|
11
|
+
export declare function orchestratorLogName(detection: OrchestrationDetection): string;
|
|
12
|
+
/**
|
|
13
|
+
* Starts a detected orchestration tool.
|
|
14
|
+
* - `oneshot` (docker compose): awaits `run` — the command detaches by itself.
|
|
15
|
+
* - `pm2`: wraps `run` in a PM2 app whose log streams like a service log.
|
|
16
|
+
* Records the orchestrator in the running state. Throws with the tool's
|
|
17
|
+
* stderr on failure.
|
|
18
|
+
*/
|
|
19
|
+
export declare function startOrchestrator(detection: OrchestrationDetection, workspacePath: string, logDir: string): Promise<RunningOrchestrator>;
|
|
20
|
+
/**
|
|
21
|
+
* Stops a detected orchestration tool: runs `stopRun` when the tool has one
|
|
22
|
+
* (compose `down`, tilt `down`), deletes the PM2 app for pm2-mode tools, and
|
|
23
|
+
* removes the entry from the running state.
|
|
24
|
+
*/
|
|
25
|
+
export declare function stopOrchestrator(detection: OrchestrationDetection, workspacePath: string): Promise<void>;
|
|
26
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestration/orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAiB/E,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,sBAAsB,GAAG,MAAM,CAEpG;AAED,6EAA6E;AAC7E,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,sBAAsB,GAAG,MAAM,CAE7E;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,sBAAsB,EACjC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,mBAAmB,CAAC,CAsC9B;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,sBAAsB,EACjC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAsBf"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module orchestration/orchestrator
|
|
3
|
+
* Executes detected orchestration tools (docker-compose, Aspire, Tilt,
|
|
4
|
+
* Procfile, Makefile). Only the structured `run`/`stopRun` invocations from
|
|
5
|
+
* detection are ever executed — never display strings, never client input.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs/promises';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import { execa } from 'execa';
|
|
10
|
+
import { getPm2List, mutateRunningState, pm2Start, serviceLogFile } from './runner.js';
|
|
11
|
+
/**
|
|
12
|
+
* Slugifies a detection id into a PM2/filesystem-safe token. Keyed on the id
|
|
13
|
+
* (`<tool>:<relative config path>`), NOT the tool alone, so two same-tool
|
|
14
|
+
* detections in different sub-repos (e.g. a Makefile in each) get distinct PM2
|
|
15
|
+
* apps and log files instead of colliding onto one — where starting the second
|
|
16
|
+
* would `pm2 delete` the first and both would stream into a shared log.
|
|
17
|
+
*/
|
|
18
|
+
function orchSlug(detection) {
|
|
19
|
+
return detection.id
|
|
20
|
+
.replace(/[^a-zA-Z0-9]+/g, '-')
|
|
21
|
+
.replace(/^-+|-+$/g, '')
|
|
22
|
+
.toLowerCase();
|
|
23
|
+
}
|
|
24
|
+
/** PM2 app name for a pm2-mode orchestrator: `nexusflow-<ws>-orch-<slug>`. */
|
|
25
|
+
export function orchestratorPm2Name(workspacePath, detection) {
|
|
26
|
+
return `nexusflow-${path.basename(workspacePath)}-orch-${orchSlug(detection)}`;
|
|
27
|
+
}
|
|
28
|
+
/** Log source name for a pm2-mode orchestrator (tailable like a service). */
|
|
29
|
+
export function orchestratorLogName(detection) {
|
|
30
|
+
return `orch-${orchSlug(detection)}`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Starts a detected orchestration tool.
|
|
34
|
+
* - `oneshot` (docker compose): awaits `run` — the command detaches by itself.
|
|
35
|
+
* - `pm2`: wraps `run` in a PM2 app whose log streams like a service log.
|
|
36
|
+
* Records the orchestrator in the running state. Throws with the tool's
|
|
37
|
+
* stderr on failure.
|
|
38
|
+
*/
|
|
39
|
+
export async function startOrchestrator(detection, workspacePath, logDir) {
|
|
40
|
+
const running = {
|
|
41
|
+
id: detection.id,
|
|
42
|
+
tool: detection.tool,
|
|
43
|
+
configPath: detection.configPath,
|
|
44
|
+
mode: detection.mode,
|
|
45
|
+
startedAt: new Date().toISOString(),
|
|
46
|
+
};
|
|
47
|
+
if (detection.mode === 'oneshot') {
|
|
48
|
+
await execa(detection.run.command, detection.run.args, {
|
|
49
|
+
cwd: detection.run.cwd,
|
|
50
|
+
shell: false,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const pm2Name = orchestratorPm2Name(workspacePath, detection);
|
|
55
|
+
const logName = orchestratorLogName(detection);
|
|
56
|
+
const logFile = serviceLogFile(logDir, logName);
|
|
57
|
+
await fs.mkdir(path.dirname(logFile), { recursive: true });
|
|
58
|
+
// Same launch shape as service starts, so the log is tailable by the shared
|
|
59
|
+
// SSE endpoint and the app shows up under the workspace prefix.
|
|
60
|
+
await pm2Start({
|
|
61
|
+
name: pm2Name,
|
|
62
|
+
command: detection.run.command,
|
|
63
|
+
args: detection.run.args,
|
|
64
|
+
cwd: detection.run.cwd,
|
|
65
|
+
logFile,
|
|
66
|
+
});
|
|
67
|
+
running.pm2Name = pm2Name;
|
|
68
|
+
running.logName = logName;
|
|
69
|
+
}
|
|
70
|
+
await mutateRunningState(workspacePath, (state) => ({
|
|
71
|
+
...state,
|
|
72
|
+
orchestrators: [...(state.orchestrators ?? []).filter((o) => o.id !== detection.id), running],
|
|
73
|
+
}));
|
|
74
|
+
return running;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Stops a detected orchestration tool: runs `stopRun` when the tool has one
|
|
78
|
+
* (compose `down`, tilt `down`), deletes the PM2 app for pm2-mode tools, and
|
|
79
|
+
* removes the entry from the running state.
|
|
80
|
+
*/
|
|
81
|
+
export async function stopOrchestrator(detection, workspacePath) {
|
|
82
|
+
if (detection.mode === 'pm2') {
|
|
83
|
+
const pm2Name = orchestratorPm2Name(workspacePath, detection);
|
|
84
|
+
const pm2List = await getPm2List();
|
|
85
|
+
if (pm2List.some((app) => app.name === pm2Name)) {
|
|
86
|
+
await execa('npx', ['pm2', 'delete', pm2Name], { reject: false });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (detection.stopRun) {
|
|
90
|
+
// Best-effort: compose down / tilt down may fail if nothing is up.
|
|
91
|
+
await execa(detection.stopRun.command, detection.stopRun.args, {
|
|
92
|
+
cwd: detection.stopRun.cwd,
|
|
93
|
+
shell: false,
|
|
94
|
+
reject: false,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
await mutateRunningState(workspacePath, (state) => ({
|
|
98
|
+
...state,
|
|
99
|
+
orchestrators: (state.orchestrators ?? []).filter((o) => o.id !== detection.id),
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/orchestration/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.test.d.ts","sourceRoot":"","sources":["../../src/orchestration/orchestrator.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import { execa } from 'execa';
|
|
4
|
+
import { startOrchestrator, stopOrchestrator, orchestratorPm2Name } from './orchestrator.js';
|
|
5
|
+
vi.mock('node:fs/promises');
|
|
6
|
+
vi.mock('execa');
|
|
7
|
+
const WS = '/ws/feature-a';
|
|
8
|
+
function compose() {
|
|
9
|
+
return {
|
|
10
|
+
id: 'docker-compose:docker-compose.yml',
|
|
11
|
+
tool: 'docker-compose',
|
|
12
|
+
configPath: '/ws/feature-a/docker-compose.yml',
|
|
13
|
+
startCommand: 'docker compose ... up -d',
|
|
14
|
+
stopCommand: 'docker compose ... down',
|
|
15
|
+
run: { command: 'docker', args: ['compose', '-f', '/ws/feature-a/docker-compose.yml', 'up', '-d'], cwd: '/ws/feature-a' },
|
|
16
|
+
stopRun: { command: 'docker', args: ['compose', '-f', '/ws/feature-a/docker-compose.yml', 'down'], cwd: '/ws/feature-a' },
|
|
17
|
+
mode: 'oneshot',
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function tilt() {
|
|
21
|
+
return {
|
|
22
|
+
id: 'tilt:Tiltfile',
|
|
23
|
+
tool: 'tilt',
|
|
24
|
+
configPath: '/ws/feature-a/Tiltfile',
|
|
25
|
+
startCommand: 'tilt up',
|
|
26
|
+
stopCommand: 'Stopped via NexusFlow',
|
|
27
|
+
run: { command: 'tilt', args: ['up', '--file', '/ws/feature-a/Tiltfile'], cwd: '/ws/feature-a' },
|
|
28
|
+
stopRun: { command: 'tilt', args: ['down', '--file', '/ws/feature-a/Tiltfile'], cwd: '/ws/feature-a' },
|
|
29
|
+
mode: 'pm2',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
describe('orchestrator runner', () => {
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
vi.clearAllMocks();
|
|
35
|
+
vi.mocked(fs.mkdir).mockResolvedValue(undefined);
|
|
36
|
+
vi.mocked(fs.readFile).mockRejectedValue(new Error('ENOENT'));
|
|
37
|
+
vi.mocked(fs.writeFile).mockResolvedValue(undefined);
|
|
38
|
+
vi.mocked(fs.unlink).mockResolvedValue(undefined);
|
|
39
|
+
});
|
|
40
|
+
it('starts a one-shot compose tool by executing the structured run (no shell) and records state', async () => {
|
|
41
|
+
vi.mocked(execa).mockResolvedValue({ stdout: '' });
|
|
42
|
+
const running = await startOrchestrator(compose(), WS, '/logs');
|
|
43
|
+
expect(running.mode).toBe('oneshot');
|
|
44
|
+
expect(running.pm2Name).toBeUndefined();
|
|
45
|
+
expect(vi.mocked(execa).mock.calls[0]).toEqual([
|
|
46
|
+
'docker',
|
|
47
|
+
['compose', '-f', '/ws/feature-a/docker-compose.yml', 'up', '-d'],
|
|
48
|
+
{ cwd: '/ws/feature-a', shell: false },
|
|
49
|
+
]);
|
|
50
|
+
const written = JSON.parse(vi.mocked(fs.writeFile).mock.calls.at(-1)?.[1]);
|
|
51
|
+
expect(written.orchestrators[0].id).toBe('docker-compose:docker-compose.yml');
|
|
52
|
+
});
|
|
53
|
+
it('wraps a pm2-mode tool under a PM2 app named orch-<id-slug>', async () => {
|
|
54
|
+
vi.mocked(execa).mockResolvedValue({ stdout: '' });
|
|
55
|
+
const detection = tilt();
|
|
56
|
+
const running = await startOrchestrator(detection, WS, '/logs');
|
|
57
|
+
// Name/log are keyed on the detection id (not the tool) so same-tool tools
|
|
58
|
+
// in different sub-repos never collide.
|
|
59
|
+
expect(running.pm2Name).toBe(orchestratorPm2Name(WS, detection));
|
|
60
|
+
expect(running.pm2Name).toBe('nexusflow-feature-a-orch-tilt-tiltfile');
|
|
61
|
+
expect(running.logName).toBe('orch-tilt-tiltfile');
|
|
62
|
+
// pm2 delete (idempotent) then pm2 start with the orch app name.
|
|
63
|
+
const startCall = vi.mocked(execa).mock.calls.find((c) => c[1]?.includes('start'));
|
|
64
|
+
expect(startCall?.[1]).toContain(orchestratorPm2Name(WS, detection));
|
|
65
|
+
});
|
|
66
|
+
it('stops a one-shot tool by running stopRun and clearing state', async () => {
|
|
67
|
+
// State currently has the compose orchestrator recorded.
|
|
68
|
+
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({
|
|
69
|
+
workspacePath: WS,
|
|
70
|
+
services: [],
|
|
71
|
+
orchestrators: [{ id: 'docker-compose:docker-compose.yml', tool: 'docker-compose', configPath: 'x', mode: 'oneshot', startedAt: 'x' }],
|
|
72
|
+
updatedAt: 'x',
|
|
73
|
+
}));
|
|
74
|
+
vi.mocked(execa).mockResolvedValue({ stdout: '' });
|
|
75
|
+
await stopOrchestrator(compose(), WS);
|
|
76
|
+
expect(vi.mocked(execa).mock.calls[0]).toEqual([
|
|
77
|
+
'docker',
|
|
78
|
+
['compose', '-f', '/ws/feature-a/docker-compose.yml', 'down'],
|
|
79
|
+
{ cwd: '/ws/feature-a', shell: false, reject: false },
|
|
80
|
+
]);
|
|
81
|
+
// No services and no orchestrators left → state file removed.
|
|
82
|
+
expect(fs.unlink).toHaveBeenCalled();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
//# sourceMappingURL=orchestrator.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.test.js","sourceRoot":"","sources":["../../src/orchestration/orchestrator.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,28 @@
|
|
|
3
3
|
* Manages the lifecycle of services — start, stop, status, and log streaming.
|
|
4
4
|
* Uses PM2 for process management.
|
|
5
5
|
*/
|
|
6
|
-
import type { ServiceConfig, RunningState } from '../types.js';
|
|
6
|
+
import type { ServiceConfig, RunningService, RunningState } from '../types.js';
|
|
7
|
+
/** PM2 app name for a workspace service: `nexusflow-<workspaceId>-<name>`. */
|
|
8
|
+
export declare function pm2AppName(workspacePath: string, serviceName: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Log file for a service. Service names may contain '/' (nested packages,
|
|
11
|
+
* e.g. `repo/sub`), which maps to a nested path under the log dir.
|
|
12
|
+
*/
|
|
13
|
+
export declare function serviceLogFile(logDir: string, serviceName: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Launches a command under PM2 using the shared NexusFlow launch shape: delete
|
|
16
|
+
* any same-named app first (idempotent restart), then start it with stdout and
|
|
17
|
+
* stderr wired to a single log file and no interpreter (run the binary
|
|
18
|
+
* directly). Shared by service and orchestrator starts so their logging and
|
|
19
|
+
* restart behavior can never drift apart.
|
|
20
|
+
*/
|
|
21
|
+
export declare function pm2Start(opts: {
|
|
22
|
+
name: string;
|
|
23
|
+
command: string;
|
|
24
|
+
args: string[];
|
|
25
|
+
cwd: string;
|
|
26
|
+
logFile: string;
|
|
27
|
+
}): Promise<void>;
|
|
7
28
|
/**
|
|
8
29
|
* Parses `pm2 jlist` output defensively. npx/pm2 can emit preamble lines before
|
|
9
30
|
* the JSON array, which would make a bare JSON.parse throw and silently drop us
|
|
@@ -17,12 +38,49 @@ export declare function parsePm2Json(stdout: string): any[];
|
|
|
17
38
|
*/
|
|
18
39
|
export declare function getPm2List(): Promise<any[]>;
|
|
19
40
|
/**
|
|
20
|
-
*
|
|
41
|
+
* Reads the raw on-disk running state without reconciling it against PM2.
|
|
42
|
+
* Callers that need the full recorded set — e.g. the stop path, which must
|
|
43
|
+
* still tear down a crashed orchestrator that {@link loadRunningState} hides —
|
|
44
|
+
* use this instead of the reconciled view.
|
|
45
|
+
*
|
|
46
|
+
* @param workspacePath - Workspace root path.
|
|
47
|
+
*/
|
|
48
|
+
export declare function readRawRunningState(workspacePath: string): Promise<RunningState | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Loads the running state from disk, syncing active status with PM2. Services
|
|
51
|
+
* and pm2-mode orchestrators are verified against the live PM2 process list and
|
|
52
|
+
* dropped when no longer online (crashed or stopped outside NexusFlow), so the
|
|
53
|
+
* Services tab and dashboard count never show a phantom-running process.
|
|
54
|
+
* One-shot tools (docker compose up -d) have no PM2 app or PID to verify; they
|
|
55
|
+
* are passed through and cleared on explicit stop.
|
|
21
56
|
*
|
|
22
57
|
* @param workspacePath - Workspace root path.
|
|
23
58
|
* @param pm2List - Optional pre-fetched `pm2 jlist` output (see {@link getPm2List}).
|
|
24
59
|
*/
|
|
25
60
|
export declare function loadRunningState(workspacePath: string, pm2List?: any[]): Promise<RunningState | null>;
|
|
61
|
+
/**
|
|
62
|
+
* Applies a read-modify-write mutation to the raw on-disk running state,
|
|
63
|
+
* serialized per workspace. The mutator receives the current state (a fresh
|
|
64
|
+
* empty one when no file exists) and returns the state to persist; when both
|
|
65
|
+
* services and orchestrators end up empty, the file is removed instead.
|
|
66
|
+
*/
|
|
67
|
+
export declare function mutateRunningState(workspacePath: string, mutator: (state: RunningState) => RunningState): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Starts ONE service under PM2 (deleting any same-named app first), resolves
|
|
70
|
+
* its PID, and upserts it into the running state. Returns the running entry,
|
|
71
|
+
* or null when the start failed or the PID could not be resolved.
|
|
72
|
+
*/
|
|
73
|
+
export declare function startService(service: ServiceConfig, workspacePath: string, logDir: string): Promise<RunningService | null>;
|
|
74
|
+
/**
|
|
75
|
+
* Stops ONE service: deletes its PM2 app and removes it from the running
|
|
76
|
+
* state. Returns whether a PM2 app or state entry existed for it.
|
|
77
|
+
*/
|
|
78
|
+
export declare function stopService(workspacePath: string, serviceName: string): Promise<boolean>;
|
|
79
|
+
/**
|
|
80
|
+
* Restarts ONE service. PM2 starts pre-delete the app, so this is startService
|
|
81
|
+
* — kept as a named export for endpoint and UI clarity.
|
|
82
|
+
*/
|
|
83
|
+
export declare function restartService(service: ServiceConfig, workspacePath: string, logDir: string): Promise<RunningService | null>;
|
|
26
84
|
/**
|
|
27
85
|
* Starts all services in the given list using PM2.
|
|
28
86
|
*
|
|
@@ -32,7 +90,8 @@ export declare function loadRunningState(workspacePath: string, pm2List?: any[])
|
|
|
32
90
|
*/
|
|
33
91
|
export declare function startServices(services: ServiceConfig[], workspacePath: string, logDir: string): Promise<void>;
|
|
34
92
|
/**
|
|
35
|
-
* Stops all services for a workspace under PM2.
|
|
93
|
+
* Stops all services for a workspace under PM2. Orchestrator entries in the
|
|
94
|
+
* running state are preserved — they are stopped separately.
|
|
36
95
|
*
|
|
37
96
|
* @param workspacePath - Workspace root path.
|
|
38
97
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/orchestration/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/orchestration/runner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAY/E,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBhB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,CAYlD;AAED;;;;GAIG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAOjD;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAM7F;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAoC3G;AAOD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,YAAY,GAC7C,OAAO,CAAC,IAAI,CAAC,CAsBf;AAID;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,aAAa,EACtB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAgDhC;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB9F;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,aAAa,EACtB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAEhC;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,aAAa,EAAE,EACzB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAKf;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCvE;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B3E;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAC5B,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CAkCf"}
|