@cogitator-ai/deploy 0.1.9 → 0.2.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 +84 -47
- package/dist/analyzer.d.ts +17 -3
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +118 -34
- package/dist/analyzer.js.map +1 -1
- package/dist/deployer.d.ts +12 -4
- package/dist/deployer.d.ts.map +1 -1
- package/dist/deployer.js +26 -13
- package/dist/deployer.js.map +1 -1
- package/dist/generator.d.ts +7 -0
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +6 -7
- package/dist/generator.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/providers/artifacts.d.ts +9 -0
- package/dist/providers/artifacts.d.ts.map +1 -0
- package/dist/providers/artifacts.js +32 -0
- package/dist/providers/artifacts.js.map +1 -0
- package/dist/providers/docker.d.ts +5 -4
- package/dist/providers/docker.d.ts.map +1 -1
- package/dist/providers/docker.js +82 -48
- package/dist/providers/docker.js.map +1 -1
- package/dist/providers/fly.d.ts +9 -2
- package/dist/providers/fly.d.ts.map +1 -1
- package/dist/providers/fly.js +120 -59
- package/dist/providers/fly.js.map +1 -1
- package/dist/templates/docker-compose.d.ts +3 -0
- package/dist/templates/docker-compose.d.ts.map +1 -1
- package/dist/templates/docker-compose.js +38 -10
- package/dist/templates/docker-compose.js.map +1 -1
- package/dist/templates/dockerfile.d.ts +8 -3
- package/dist/templates/dockerfile.d.ts.map +1 -1
- package/dist/templates/dockerfile.js +59 -17
- package/dist/templates/dockerfile.js.map +1 -1
- package/dist/templates/fly-toml.d.ts +1 -0
- package/dist/templates/fly-toml.d.ts.map +1 -1
- package/dist/templates/fly-toml.js +21 -12
- package/dist/templates/fly-toml.js.map +1 -1
- package/dist/utils/env.d.ts +7 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +21 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/exec.d.ts +15 -3
- package/dist/utils/exec.d.ts.map +1 -1
- package/dist/utils/exec.js +50 -14
- package/dist/utils/exec.js.map +1 -1
- package/dist/utils/registry-auth.d.ts +7 -0
- package/dist/utils/registry-auth.d.ts.map +1 -0
- package/dist/utils/registry-auth.js +71 -0
- package/dist/utils/registry-auth.js.map +1 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @cogitator-ai/deploy
|
|
2
2
|
|
|
3
|
-
One-command deployment engine for Cogitator agents.
|
|
3
|
+
One-command deployment engine for Cogitator agents. Analyzes your project, generates a Dockerfile and target-specific artifacts, runs preflight checks and deploys to Docker or Fly.io.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -13,19 +13,10 @@ pnpm add @cogitator-ai/deploy
|
|
|
13
13
|
### Via CLI
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
#
|
|
17
|
-
cogitator deploy
|
|
18
|
-
|
|
19
|
-
# Deploy to Fly.io
|
|
20
|
-
cogitator deploy --target fly
|
|
21
|
-
|
|
22
|
-
# Dry run — see what would happen
|
|
23
|
-
cogitator deploy --dry-run
|
|
24
|
-
|
|
25
|
-
# Check status
|
|
16
|
+
cogitator deploy --dry-run # analyze + preflight, change nothing
|
|
17
|
+
cogitator deploy # Docker: build image, start the compose stack
|
|
18
|
+
cogitator deploy --target fly # Fly.io
|
|
26
19
|
cogitator deploy status
|
|
27
|
-
|
|
28
|
-
# Tear down
|
|
29
20
|
cogitator deploy destroy
|
|
30
21
|
```
|
|
31
22
|
|
|
@@ -36,72 +27,119 @@ import { Deployer } from '@cogitator-ai/deploy';
|
|
|
36
27
|
|
|
37
28
|
const deployer = new Deployer();
|
|
38
29
|
|
|
39
|
-
// Plan deployment (preflight checks, no execution)
|
|
40
30
|
const plan = await deployer.plan({
|
|
41
31
|
projectDir: process.cwd(),
|
|
42
32
|
target: 'docker',
|
|
43
33
|
noPush: true,
|
|
44
34
|
});
|
|
45
35
|
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
target: 'fly',
|
|
50
|
-
});
|
|
36
|
+
console.log(plan.config); // resolved DeployConfig (image, port, services, secrets, ...)
|
|
37
|
+
console.log(plan.warnings); // e.g. missing start script, local Ollama on a cloud target
|
|
38
|
+
console.log(plan.preflight.passed, plan.preflight.checks);
|
|
51
39
|
|
|
40
|
+
const result = await deployer.deploy({ projectDir: process.cwd(), target: 'fly' });
|
|
41
|
+
if (!result.success) throw new Error(result.error);
|
|
52
42
|
console.log(result.url); // https://my-app.fly.dev
|
|
53
43
|
```
|
|
54
44
|
|
|
45
|
+
| Method | Description |
|
|
46
|
+
| ------------------------------------- | -------------------------------------------------------------------------------------------- |
|
|
47
|
+
| `plan(options)` | Analyze + preflight. Returns `config`, `preflight`, `warnings`, `analysis`, `provider` |
|
|
48
|
+
| `deploy(options)` | `plan`, generate artifacts, deploy. Returns `DeployResult` (`dryRun` stops before deploying) |
|
|
49
|
+
| `status(target, config, projectDir)` | `DeployStatus` (`running`, `url`, `instances`) |
|
|
50
|
+
| `destroy(target, config, projectDir)` | Tears down the deployment; throws when it fails |
|
|
51
|
+
| `availableTargets()` | Names of registered providers (`['docker', 'fly']` by default) |
|
|
52
|
+
| `registerProvider(provider)` | Add a custom `DeployProvider` |
|
|
53
|
+
|
|
55
54
|
## Configuration
|
|
56
55
|
|
|
57
|
-
Add a `deploy` section to `cogitator.yml
|
|
56
|
+
Add a `deploy` section to `cogitator.yml` (or pass `configOverrides`):
|
|
58
57
|
|
|
59
58
|
```yaml
|
|
60
59
|
deploy:
|
|
61
|
-
target: fly
|
|
60
|
+
target: fly # docker | fly
|
|
62
61
|
port: 3000
|
|
62
|
+
image: my-agent # Docker image / Fly app name (default: package.json name)
|
|
63
63
|
region: iad
|
|
64
|
-
instances: 2
|
|
65
|
-
registry: ghcr.io/myorg
|
|
64
|
+
instances: 2 # Fly.io only
|
|
65
|
+
registry: ghcr.io/myorg
|
|
66
66
|
services:
|
|
67
67
|
redis: true
|
|
68
68
|
postgres: true
|
|
69
|
+
env:
|
|
70
|
+
LOG_LEVEL: info
|
|
69
71
|
secrets:
|
|
70
72
|
- OPENAI_API_KEY
|
|
71
|
-
|
|
73
|
+
health:
|
|
74
|
+
path: /health
|
|
75
|
+
interval: 30s
|
|
76
|
+
timeout: 5s
|
|
77
|
+
resources:
|
|
78
|
+
memory: 512mb
|
|
79
|
+
cpu: 1
|
|
72
80
|
```
|
|
73
81
|
|
|
82
|
+
Secrets are read from the current environment or the project's `.env` file. They are checked during preflight, passed through to the Docker Compose stack, and imported into Fly.io with `fly secrets import --stage`.
|
|
83
|
+
|
|
74
84
|
## Auto-Detection
|
|
75
85
|
|
|
76
|
-
|
|
86
|
+
| What | Source | Example |
|
|
87
|
+
| ---------------- | ---------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
88
|
+
| Server adapter | `package.json` dependencies | `@cogitator-ai/express` → Express |
|
|
89
|
+
| Image / app name | `package.json` `name` | `@acme/My Agent` → `my-agent` |
|
|
90
|
+
| Package manager | Lockfile | `pnpm-lock.yaml` → `pnpm install --frozen-lockfile`, `package-lock.json` → `npm ci` |
|
|
91
|
+
| Start command | `scripts.start`, then `main` | `node dist/index.js` → `CMD ["node","dist/index.js"]`, otherwise `npm start` |
|
|
92
|
+
| Build step | `tsconfig.json` + `scripts.build` | Multi-stage build running `<pm> run build` |
|
|
93
|
+
| Services | `cogitator.yml` / `.yaml` memory adapter | `adapter: postgres` → PostgreSQL service |
|
|
94
|
+
| Required secrets | `llm.defaultModel` (+ `defaultProvider`) | `openai/gpt-4o` → `OPENAI_API_KEY`; Bedrock → both AWS keys |
|
|
95
|
+
| Ollama Cloud | Model tag `:cloud` / `-cloud` | `gpt-oss:120b-cloud` → `OLLAMA_API_KEY` |
|
|
77
96
|
|
|
78
|
-
|
|
79
|
-
| ---------------- | ----------------------------- | ---------------------------------- |
|
|
80
|
-
| Server adapter | `package.json` dependencies | `@cogitator-ai/express` → Express |
|
|
81
|
-
| Services | `cogitator.yml` memory config | `adapter: redis` → Redis service |
|
|
82
|
-
| Required secrets | LLM provider configs | `openai` → `OPENAI_API_KEY` |
|
|
83
|
-
| Ollama Cloud | Model suffix or API key | `:cloud` suffix → `OLLAMA_API_KEY` |
|
|
97
|
+
Problems found during analysis (invalid config, unparsable `package.json`, missing start script, local Ollama models on cloud targets) are returned as `plan.warnings` instead of being ignored.
|
|
84
98
|
|
|
85
99
|
## Deploy Targets
|
|
86
100
|
|
|
87
101
|
### Docker
|
|
88
102
|
|
|
89
|
-
|
|
103
|
+
Artifacts are written to `.cogitator/`: `Dockerfile`, `Dockerfile.dockerignore` and `docker-compose.prod.yml`. A root `.dockerignore` is created when the project has none, so `.env` and `node_modules` never enter the image.
|
|
90
104
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
```
|
|
105
|
+
`deploy` builds and tags the image (`<registry>/<image>:latest`), pushes it when a registry is configured, then runs `docker compose up -d` for the app plus the Redis/PostgreSQL services it needs (health-gated, data in named volumes). `status` reports whether the `app` service is running; `destroy` runs `docker compose down` and keeps volumes.
|
|
106
|
+
|
|
107
|
+
Preflight checks: Docker installed, daemon running, Compose v2 available, registry credentials (read from the Docker config, credential helpers and stores), secrets.
|
|
95
108
|
|
|
96
109
|
### Fly.io
|
|
97
110
|
|
|
98
|
-
Generates `fly.toml` and
|
|
111
|
+
Generates `.cogitator/fly.toml` (your own `fly.toml` is never overwritten) with `[env]`, HTTP checks from `health`, VM size from `resources`, and `min_machines_running` from `instances`. `deploy` creates the app when needed, stages secrets, runs `fly deploy --config .cogitator/fly.toml --dockerfile .cogitator/Dockerfile`, and scales to `instances`. Works with either `flyctl` or `fly` on `PATH`.
|
|
99
112
|
|
|
100
|
-
|
|
101
|
-
|
|
113
|
+
## Custom Providers
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { Deployer, type DeployProvider } from '@cogitator-ai/deploy';
|
|
117
|
+
|
|
118
|
+
class KubernetesProvider implements DeployProvider {
|
|
119
|
+
readonly name = 'kubernetes';
|
|
120
|
+
async preflight(config, projectDir) {
|
|
121
|
+
/* ... */
|
|
122
|
+
}
|
|
123
|
+
async generate(config, projectDir) {
|
|
124
|
+
/* ... */
|
|
125
|
+
}
|
|
126
|
+
async deploy(config, artifacts, projectDir) {
|
|
127
|
+
/* ... */
|
|
128
|
+
}
|
|
129
|
+
async status(config, projectDir) {
|
|
130
|
+
/* ... */
|
|
131
|
+
}
|
|
132
|
+
async destroy(config, projectDir) {
|
|
133
|
+
/* ... */
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const deployer = new Deployer();
|
|
138
|
+
deployer.registerProvider(new KubernetesProvider());
|
|
139
|
+
await deployer.deploy({ projectDir: process.cwd(), target: 'kubernetes' });
|
|
102
140
|
```
|
|
103
141
|
|
|
104
|
-
|
|
142
|
+
All external commands are executed without a shell, so paths with spaces and user-supplied values are passed verbatim.
|
|
105
143
|
|
|
106
144
|
## Architecture
|
|
107
145
|
|
|
@@ -110,12 +148,11 @@ ProjectAnalyzer → ArtifactGenerator → DeployProvider → Result
|
|
|
110
148
|
(detect config) (Dockerfile, etc.) (docker/fly) (url, status)
|
|
111
149
|
```
|
|
112
150
|
|
|
113
|
-
- **ProjectAnalyzer** — reads `package.json` and `cogitator.yml` to detect server, services, secrets
|
|
114
|
-
- **ArtifactGenerator** — generates Dockerfile, docker-compose, fly.toml from templates
|
|
115
|
-
- **DeployProvider** — executes preflight checks, builds, deploys (Docker or Fly.io)
|
|
116
|
-
- **Deployer** — orchestrator that ties it all together
|
|
117
|
-
|
|
118
151
|
## See Also
|
|
119
152
|
|
|
120
|
-
- [Deployment Guide](../../docs/DEPLOY.md) —
|
|
121
|
-
- [CLI Reference](../cli/README.md)
|
|
153
|
+
- [Deployment Guide](../../docs/DEPLOY.md) — CI/CD examples
|
|
154
|
+
- [CLI Reference](../cli/README.md#cogitator-deploy)
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT
|
package/dist/analyzer.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { DeployConfig, DeployServer, DeployServicesConfig, DeployTarget } from '@cogitator-ai/types';
|
|
2
|
+
export type PackageManager = 'pnpm' | 'npm' | 'yarn';
|
|
2
3
|
interface PackageJson {
|
|
4
|
+
name?: string;
|
|
5
|
+
main?: string;
|
|
6
|
+
scripts?: Record<string, string>;
|
|
3
7
|
dependencies?: Record<string, string>;
|
|
4
8
|
devDependencies?: Record<string, string>;
|
|
5
9
|
}
|
|
@@ -9,6 +13,10 @@ export interface AnalyzerResult {
|
|
|
9
13
|
secrets: string[];
|
|
10
14
|
warnings: string[];
|
|
11
15
|
hasTypeScript: boolean;
|
|
16
|
+
packageManager: PackageManager;
|
|
17
|
+
hasLockfile: boolean;
|
|
18
|
+
hasBuildScript: boolean;
|
|
19
|
+
startCommand: string[];
|
|
12
20
|
deployConfig: DeployConfig;
|
|
13
21
|
}
|
|
14
22
|
export declare class ProjectAnalyzer {
|
|
@@ -18,10 +26,16 @@ export declare class ProjectAnalyzer {
|
|
|
18
26
|
adapter?: string | null;
|
|
19
27
|
};
|
|
20
28
|
}): DeployServicesConfig;
|
|
21
|
-
detectSecrets(model: string): string[];
|
|
29
|
+
detectSecrets(model: string, defaultProvider?: string): string[];
|
|
22
30
|
isOllamaCloud(model: string): boolean;
|
|
23
|
-
getDeployWarnings(model: string, target: DeployTarget): string[];
|
|
24
|
-
|
|
31
|
+
getDeployWarnings(model: string, target: DeployTarget, defaultProvider?: string): string[];
|
|
32
|
+
detectPackageManager(projectDir: string): {
|
|
33
|
+
packageManager: PackageManager;
|
|
34
|
+
hasLockfile: boolean;
|
|
35
|
+
};
|
|
36
|
+
detectStartCommand(pkg: PackageJson, hasTypeScript: boolean): string[];
|
|
37
|
+
private loadProjectConfig;
|
|
38
|
+
analyze(projectDir: string, configOverrides?: Partial<DeployConfig>): AnalyzerResult;
|
|
25
39
|
}
|
|
26
40
|
export {};
|
|
27
41
|
//# sourceMappingURL=analyzer.d.ts.map
|
package/dist/analyzer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACb,MAAM,qBAAqB,CAAC;AA4B7B,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAErD,UAAU,WAAW;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,YAAY,CAAC;CAC5B;AA0CD,qBAAa,eAAe;IAC1B,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,YAAY,GAAG,SAAS;IAQxD,cAAc,CAAC,MAAM,EAAE;QAAE,MAAM,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,CAAA;KAAE,GAAG,oBAAoB;IAQtF,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAOhE,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAKrC,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAe1F,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG;QACxC,cAAc,EAAE,cAAc,CAAC;QAC/B,WAAW,EAAE,OAAO,CAAC;KACtB;IAaD,kBAAkB,CAAC,GAAG,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,GAAG,MAAM,EAAE;IAUtE,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,cAAc;CA2DrF"}
|
package/dist/analyzer.js
CHANGED
|
@@ -1,20 +1,60 @@
|
|
|
1
1
|
import { loadConfig } from '@cogitator-ai/config';
|
|
2
2
|
import { readFileSync, existsSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
+
import { sanitizeName } from './utils/env.js';
|
|
4
5
|
const SERVER_PACKAGES = {
|
|
5
6
|
'@cogitator-ai/express': 'express',
|
|
6
7
|
'@cogitator-ai/fastify': 'fastify',
|
|
7
8
|
'@cogitator-ai/hono': 'hono',
|
|
8
9
|
'@cogitator-ai/koa': 'koa',
|
|
9
10
|
};
|
|
10
|
-
const
|
|
11
|
-
openai: 'OPENAI_API_KEY',
|
|
12
|
-
anthropic: 'ANTHROPIC_API_KEY',
|
|
13
|
-
google: 'GOOGLE_API_KEY',
|
|
14
|
-
azure: 'AZURE_OPENAI_API_KEY',
|
|
15
|
-
bedrock: 'AWS_ACCESS_KEY_ID',
|
|
16
|
-
|
|
11
|
+
const PROVIDER_SECRETS = {
|
|
12
|
+
openai: ['OPENAI_API_KEY'],
|
|
13
|
+
anthropic: ['ANTHROPIC_API_KEY'],
|
|
14
|
+
google: ['GOOGLE_API_KEY'],
|
|
15
|
+
azure: ['AZURE_OPENAI_API_KEY'],
|
|
16
|
+
bedrock: ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY'],
|
|
17
|
+
mistral: ['MISTRAL_API_KEY'],
|
|
18
|
+
groq: ['GROQ_API_KEY'],
|
|
19
|
+
together: ['TOGETHER_API_KEY'],
|
|
20
|
+
deepseek: ['DEEPSEEK_API_KEY'],
|
|
21
|
+
ollama: ['OLLAMA_API_KEY'],
|
|
17
22
|
};
|
|
23
|
+
const CONFIG_FILES = ['cogitator.yml', 'cogitator.yaml'];
|
|
24
|
+
function isStringRecord(value) {
|
|
25
|
+
return (typeof value === 'object' &&
|
|
26
|
+
value !== null &&
|
|
27
|
+
!Array.isArray(value) &&
|
|
28
|
+
Object.values(value).every((v) => typeof v === 'string'));
|
|
29
|
+
}
|
|
30
|
+
function readPackageJson(projectDir, warnings) {
|
|
31
|
+
const pkgPath = join(projectDir, 'package.json');
|
|
32
|
+
if (!existsSync(pkgPath))
|
|
33
|
+
return {};
|
|
34
|
+
let raw;
|
|
35
|
+
try {
|
|
36
|
+
raw = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
warnings.push(`Could not parse package.json: ${error instanceof Error ? error.message : String(error)}`);
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
if (typeof raw !== 'object' || raw === null)
|
|
43
|
+
return {};
|
|
44
|
+
const get = (key) => Reflect.get(raw, key);
|
|
45
|
+
const name = get('name');
|
|
46
|
+
const main = get('main');
|
|
47
|
+
const scripts = get('scripts');
|
|
48
|
+
const dependencies = get('dependencies');
|
|
49
|
+
const devDependencies = get('devDependencies');
|
|
50
|
+
return {
|
|
51
|
+
name: typeof name === 'string' ? name : undefined,
|
|
52
|
+
main: typeof main === 'string' ? main : undefined,
|
|
53
|
+
scripts: isStringRecord(scripts) ? scripts : undefined,
|
|
54
|
+
dependencies: isStringRecord(dependencies) ? dependencies : undefined,
|
|
55
|
+
devDependencies: isStringRecord(devDependencies) ? devDependencies : undefined,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
18
58
|
export class ProjectAnalyzer {
|
|
19
59
|
detectServer(pkg) {
|
|
20
60
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
@@ -31,26 +71,21 @@ export class ProjectAnalyzer {
|
|
|
31
71
|
postgres: adapter === 'postgres',
|
|
32
72
|
};
|
|
33
73
|
}
|
|
34
|
-
detectSecrets(model) {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
else if (provider !== 'ollama') {
|
|
42
|
-
secrets.push(MODEL_SECRET_MAP[provider]);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return secrets;
|
|
74
|
+
detectSecrets(model, defaultProvider) {
|
|
75
|
+
const provider = model.includes('/') ? model.split('/')[0] : defaultProvider;
|
|
76
|
+
if (!provider || !(provider in PROVIDER_SECRETS))
|
|
77
|
+
return [];
|
|
78
|
+
if (provider === 'ollama' && !this.isOllamaCloud(model))
|
|
79
|
+
return [];
|
|
80
|
+
return [...PROVIDER_SECRETS[provider]];
|
|
46
81
|
}
|
|
47
82
|
isOllamaCloud(model) {
|
|
48
|
-
const modelName = model.includes('/') ? model.
|
|
49
|
-
return
|
|
83
|
+
const modelName = model.includes('/') ? model.slice(model.indexOf('/') + 1) : model;
|
|
84
|
+
return /(?::|-)cloud$/.test(modelName);
|
|
50
85
|
}
|
|
51
|
-
getDeployWarnings(model, target) {
|
|
86
|
+
getDeployWarnings(model, target, defaultProvider) {
|
|
52
87
|
const warnings = [];
|
|
53
|
-
const provider = model.split('/')[0];
|
|
88
|
+
const provider = model.includes('/') ? model.split('/')[0] : defaultProvider;
|
|
54
89
|
if (provider === 'ollama' && !this.isOllamaCloud(model) && target !== 'docker') {
|
|
55
90
|
warnings.push(`Model "${model}" requires local Ollama server. Cloud targets don't include Ollama. ` +
|
|
56
91
|
'Use a cloud model (e.g. qwen3.5:cloud with OLLAMA_API_KEY), switch to a cloud LLM provider, ' +
|
|
@@ -58,34 +93,83 @@ export class ProjectAnalyzer {
|
|
|
58
93
|
}
|
|
59
94
|
return warnings;
|
|
60
95
|
}
|
|
96
|
+
detectPackageManager(projectDir) {
|
|
97
|
+
if (existsSync(join(projectDir, 'pnpm-lock.yaml'))) {
|
|
98
|
+
return { packageManager: 'pnpm', hasLockfile: true };
|
|
99
|
+
}
|
|
100
|
+
if (existsSync(join(projectDir, 'yarn.lock'))) {
|
|
101
|
+
return { packageManager: 'yarn', hasLockfile: true };
|
|
102
|
+
}
|
|
103
|
+
if (existsSync(join(projectDir, 'package-lock.json'))) {
|
|
104
|
+
return { packageManager: 'npm', hasLockfile: true };
|
|
105
|
+
}
|
|
106
|
+
return { packageManager: 'npm', hasLockfile: false };
|
|
107
|
+
}
|
|
108
|
+
detectStartCommand(pkg, hasTypeScript) {
|
|
109
|
+
const start = pkg.scripts?.start?.trim();
|
|
110
|
+
if (start) {
|
|
111
|
+
const nodeScript = /^node\s+([^\s&|;<>$`"']+)$/.exec(start);
|
|
112
|
+
return nodeScript ? ['node', nodeScript[1]] : ['npm', 'start'];
|
|
113
|
+
}
|
|
114
|
+
if (pkg.main)
|
|
115
|
+
return ['node', pkg.main];
|
|
116
|
+
return ['node', hasTypeScript ? 'dist/server.js' : 'src/server.js'];
|
|
117
|
+
}
|
|
118
|
+
loadProjectConfig(projectDir, warnings) {
|
|
119
|
+
const configPath = CONFIG_FILES.map((name) => join(projectDir, name)).find((p) => existsSync(p));
|
|
120
|
+
if (!configPath)
|
|
121
|
+
return undefined;
|
|
122
|
+
try {
|
|
123
|
+
return loadConfig({ configPath, skipEnv: true });
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
warnings.push(`Ignoring invalid ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
61
130
|
analyze(projectDir, configOverrides) {
|
|
62
|
-
const
|
|
63
|
-
const pkg =
|
|
131
|
+
const warnings = [];
|
|
132
|
+
const pkg = readPackageJson(projectDir, warnings);
|
|
64
133
|
const server = configOverrides?.server ?? this.detectServer(pkg);
|
|
65
134
|
const hasTypeScript = existsSync(join(projectDir, 'tsconfig.json'));
|
|
66
135
|
const target = configOverrides?.target ?? 'docker';
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
});
|
|
136
|
+
const { packageManager, hasLockfile } = this.detectPackageManager(projectDir);
|
|
137
|
+
const startCommand = this.detectStartCommand(pkg, hasTypeScript);
|
|
138
|
+
const hasBuildScript = typeof pkg.scripts?.build === 'string';
|
|
139
|
+
if (!pkg.scripts?.start && !pkg.main) {
|
|
140
|
+
warnings.push(`No "start" script or "main" in package.json — the container will run "${startCommand.join(' ')}"`);
|
|
73
141
|
}
|
|
74
|
-
|
|
142
|
+
if (hasTypeScript && !hasBuildScript) {
|
|
143
|
+
warnings.push('tsconfig.json found but package.json has no "build" script — skipping build step');
|
|
144
|
+
}
|
|
145
|
+
const fullConfig = this.loadProjectConfig(projectDir, warnings);
|
|
75
146
|
const model = fullConfig?.llm?.defaultModel ?? '';
|
|
147
|
+
const defaultProvider = fullConfig?.llm?.defaultProvider;
|
|
76
148
|
const services = configOverrides?.services ??
|
|
77
149
|
(fullConfig ? this.detectServices(fullConfig) : { redis: false, postgres: false });
|
|
78
|
-
const secrets = configOverrides?.secrets ?? (model ? this.detectSecrets(model) : []);
|
|
79
|
-
|
|
150
|
+
const secrets = configOverrides?.secrets ?? (model ? this.detectSecrets(model, defaultProvider) : []);
|
|
151
|
+
if (model)
|
|
152
|
+
warnings.push(...this.getDeployWarnings(model, target, defaultProvider));
|
|
153
|
+
if (target === 'docker' && (configOverrides?.instances ?? 1) > 1) {
|
|
154
|
+
warnings.push('instances > 1 is not supported for the docker target; running one container');
|
|
155
|
+
}
|
|
156
|
+
const image = configOverrides?.image ?? sanitizeName(pkg.name ?? '');
|
|
80
157
|
return {
|
|
81
158
|
server,
|
|
82
159
|
services,
|
|
83
160
|
secrets,
|
|
84
161
|
warnings,
|
|
85
162
|
hasTypeScript,
|
|
163
|
+
packageManager,
|
|
164
|
+
hasLockfile,
|
|
165
|
+
hasBuildScript,
|
|
166
|
+
startCommand,
|
|
86
167
|
deployConfig: {
|
|
87
168
|
...configOverrides,
|
|
88
169
|
server,
|
|
170
|
+
image,
|
|
171
|
+
services,
|
|
172
|
+
secrets,
|
|
89
173
|
port: configOverrides?.port ?? 3000,
|
|
90
174
|
},
|
|
91
175
|
};
|
package/dist/analyzer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
|
package/dist/deployer.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { DeployConfig, DeployResult, DeployStatus, DeployTarget, PreflightResult } from '@cogitator-ai/types';
|
|
2
2
|
import type { DeployProvider } from './providers/base.js';
|
|
3
|
+
import { type AnalyzerResult } from './analyzer.js';
|
|
4
|
+
/** A built-in target, or the name of a provider registered via `registerProvider`. */
|
|
5
|
+
export type DeployTargetName = DeployTarget | (string & {});
|
|
3
6
|
export interface DeployOptions {
|
|
4
7
|
projectDir: string;
|
|
5
|
-
target:
|
|
8
|
+
target: DeployTargetName;
|
|
6
9
|
dryRun?: boolean;
|
|
7
10
|
noPush?: boolean;
|
|
8
11
|
configOverrides?: Partial<DeployConfig>;
|
|
@@ -11,6 +14,8 @@ export interface DeployPlan {
|
|
|
11
14
|
config: DeployConfig;
|
|
12
15
|
preflight: PreflightResult;
|
|
13
16
|
provider: DeployProvider;
|
|
17
|
+
warnings: string[];
|
|
18
|
+
analysis: AnalyzerResult;
|
|
14
19
|
}
|
|
15
20
|
export declare class Deployer {
|
|
16
21
|
private providers;
|
|
@@ -18,10 +23,13 @@ export declare class Deployer {
|
|
|
18
23
|
private generator;
|
|
19
24
|
constructor();
|
|
20
25
|
registerProvider(provider: DeployProvider): void;
|
|
21
|
-
|
|
26
|
+
/** Targets that have a registered provider. */
|
|
27
|
+
availableTargets(): string[];
|
|
28
|
+
getProvider(target: DeployTargetName): DeployProvider;
|
|
29
|
+
private resolveConfig;
|
|
22
30
|
plan(options: DeployOptions): Promise<DeployPlan>;
|
|
23
31
|
deploy(options: DeployOptions): Promise<DeployResult>;
|
|
24
|
-
status(target:
|
|
25
|
-
destroy(target:
|
|
32
|
+
status(target: DeployTargetName, config: DeployConfig, projectDir: string): Promise<DeployStatus>;
|
|
33
|
+
destroy(target: DeployTargetName, config: DeployConfig, projectDir: string): Promise<void>;
|
|
26
34
|
}
|
|
27
35
|
//# sourceMappingURL=deployer.d.ts.map
|
package/dist/deployer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deployer.d.ts","sourceRoot":"","sources":["../src/deployer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"deployer.d.ts","sourceRoot":"","sources":["../src/deployer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAGrE,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAQ5D,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,SAAS,CAA2B;;IAO5C,gBAAgB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAIhD,+CAA+C;IAC/C,gBAAgB,IAAI,MAAM,EAAE;IAI5B,WAAW,CAAC,MAAM,EAAE,gBAAgB,GAAG,cAAc;IAUrD,OAAO,CAAC,aAAa;IAUf,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC;IAiBjD,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IA0BrD,MAAM,CACV,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,CAAC;IAMlB,OAAO,CAAC,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAKjG"}
|
package/dist/deployer.js
CHANGED
|
@@ -2,6 +2,10 @@ import { DockerProvider } from './providers/docker.js';
|
|
|
2
2
|
import { FlyProvider } from './providers/fly.js';
|
|
3
3
|
import { ProjectAnalyzer } from './analyzer.js';
|
|
4
4
|
import { ArtifactGenerator } from './generator.js';
|
|
5
|
+
const BUILTIN_TARGETS = ['docker', 'fly'];
|
|
6
|
+
function isBuiltinTarget(target) {
|
|
7
|
+
return BUILTIN_TARGETS.some((t) => t === target);
|
|
8
|
+
}
|
|
5
9
|
export class Deployer {
|
|
6
10
|
providers = new Map();
|
|
7
11
|
analyzer = new ProjectAnalyzer();
|
|
@@ -13,29 +17,33 @@ export class Deployer {
|
|
|
13
17
|
registerProvider(provider) {
|
|
14
18
|
this.providers.set(provider.name, provider);
|
|
15
19
|
}
|
|
20
|
+
/** Targets that have a registered provider. */
|
|
21
|
+
availableTargets() {
|
|
22
|
+
return [...this.providers.keys()];
|
|
23
|
+
}
|
|
16
24
|
getProvider(target) {
|
|
17
25
|
const provider = this.providers.get(target);
|
|
18
26
|
if (!provider) {
|
|
19
|
-
throw new Error(`Unknown deploy target: "${target}". Available: ${
|
|
27
|
+
throw new Error(`Unknown deploy target: "${target}". Available: ${this.availableTargets().join(', ')}`);
|
|
20
28
|
}
|
|
21
29
|
return provider;
|
|
22
30
|
}
|
|
31
|
+
resolveConfig(projectDir, target, overrides) {
|
|
32
|
+
const builtin = isBuiltinTarget(target) ? { target } : {};
|
|
33
|
+
const analysis = this.analyzer.analyze(projectDir, { ...overrides, ...builtin });
|
|
34
|
+
return { config: { ...analysis.deployConfig, ...builtin }, analysis };
|
|
35
|
+
}
|
|
23
36
|
async plan(options) {
|
|
24
|
-
const
|
|
25
|
-
const config =
|
|
26
|
-
...analysis.deployConfig,
|
|
27
|
-
...options.configOverrides,
|
|
28
|
-
target: options.target,
|
|
29
|
-
};
|
|
37
|
+
const provider = this.getProvider(options.target);
|
|
38
|
+
const { config, analysis } = this.resolveConfig(options.projectDir, options.target, options.configOverrides);
|
|
30
39
|
if (options.noPush) {
|
|
31
40
|
delete config.registry;
|
|
32
41
|
}
|
|
33
|
-
const provider = this.getProvider(options.target);
|
|
34
42
|
const preflight = await provider.preflight(config, options.projectDir);
|
|
35
|
-
return { config, preflight, provider };
|
|
43
|
+
return { config, preflight, provider, warnings: analysis.warnings, analysis };
|
|
36
44
|
}
|
|
37
45
|
async deploy(options) {
|
|
38
|
-
const { config, preflight, provider } = await this.plan(options);
|
|
46
|
+
const { config, preflight, provider, analysis } = await this.plan(options);
|
|
39
47
|
if (!preflight.passed) {
|
|
40
48
|
const failures = preflight.checks.filter((c) => !c.passed);
|
|
41
49
|
return {
|
|
@@ -43,9 +51,12 @@ export class Deployer {
|
|
|
43
51
|
error: `Preflight failed:\n${failures.map((f) => ` - ${f.message}${f.fix ? ` (${f.fix})` : ''}`).join('\n')}`,
|
|
44
52
|
};
|
|
45
53
|
}
|
|
46
|
-
const analysis = this.analyzer.analyze(options.projectDir);
|
|
47
54
|
const artifacts = this.generator.generate(config, {
|
|
48
55
|
hasTypeScript: analysis.hasTypeScript,
|
|
56
|
+
packageManager: analysis.packageManager,
|
|
57
|
+
hasLockfile: analysis.hasLockfile,
|
|
58
|
+
hasBuildScript: analysis.hasBuildScript,
|
|
59
|
+
startCommand: analysis.startCommand,
|
|
49
60
|
});
|
|
50
61
|
if (options.dryRun) {
|
|
51
62
|
return { success: true, url: '(dry run)' };
|
|
@@ -54,11 +65,13 @@ export class Deployer {
|
|
|
54
65
|
}
|
|
55
66
|
async status(target, config, projectDir) {
|
|
56
67
|
const provider = this.getProvider(target);
|
|
57
|
-
|
|
68
|
+
const resolved = this.resolveConfig(projectDir, target, config).config;
|
|
69
|
+
return provider.status(resolved, projectDir);
|
|
58
70
|
}
|
|
59
71
|
async destroy(target, config, projectDir) {
|
|
60
72
|
const provider = this.getProvider(target);
|
|
61
|
-
|
|
73
|
+
const resolved = this.resolveConfig(projectDir, target, config).config;
|
|
74
|
+
return provider.destroy(resolved, projectDir);
|
|
62
75
|
}
|
|
63
76
|
}
|
|
64
77
|
//# sourceMappingURL=deployer.js.map
|
package/dist/deployer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deployer.js","sourceRoot":"","sources":["../src/deployer.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"deployer.js","sourceRoot":"","sources":["../src/deployer.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAuB,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKnD,MAAM,eAAe,GAA4B,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AAEnE,SAAS,eAAe,CAAC,MAAc;IACrC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC;AACnD,CAAC;AAkBD,MAAM,OAAO,QAAQ;IACX,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC9C,QAAQ,GAAG,IAAI,eAAe,EAAE,CAAC;IACjC,SAAS,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAE5C;QACE,IAAI,CAAC,gBAAgB,CAAC,IAAI,cAAc,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,gBAAgB,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,gBAAgB,CAAC,QAAwB;QACvC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,+CAA+C;IAC/C,gBAAgB;QACd,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,WAAW,CAAC,MAAwB;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CACb,2BAA2B,MAAM,iBAAiB,IAAI,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACvF,CAAC;QACJ,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEO,aAAa,CACnB,UAAkB,EAClB,MAAwB,EACxB,SAA4C;QAE5C,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,GAAG,SAAS,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;QACjF,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,YAAY,EAAE,GAAG,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAsB;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,aAAa,CAC7C,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,eAAe,CACxB,CAAC;QAEF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QAEvE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAChF,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAsB;QACjC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE3E,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YACtB,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC3D,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,sBAAsB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aAC/G,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE;YAChD,aAAa,EAAE,QAAQ,CAAC,aAAa;YACrC,cAAc,EAAE,QAAQ,CAAC,cAAc;YACvC,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,cAAc,EAAE,QAAQ,CAAC,cAAc;YACvC,YAAY,EAAE,QAAQ,CAAC,YAAY;SACpC,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;QAC7C,CAAC;QAED,OAAO,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,MAAM,CACV,MAAwB,EACxB,MAAoB,EACpB,UAAkB;QAElB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC;QACvE,OAAO,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAwB,EAAE,MAAoB,EAAE,UAAkB;QAC9E,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC;QACvE,OAAO,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAChD,CAAC;CACF"}
|