draken 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +108 -0
  2. package/dist/auth/middleware.d.ts +23 -0
  3. package/dist/auth/middleware.d.ts.map +1 -0
  4. package/dist/auth/middleware.js +117 -0
  5. package/dist/auth/middleware.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +70 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/db/queries.d.ts +16 -0
  11. package/dist/db/queries.d.ts.map +1 -0
  12. package/dist/db/queries.js +91 -0
  13. package/dist/db/queries.js.map +1 -0
  14. package/dist/db/schema.d.ts +4 -0
  15. package/dist/db/schema.d.ts.map +1 -0
  16. package/dist/db/schema.js +71 -0
  17. package/dist/db/schema.js.map +1 -0
  18. package/dist/docker/dockerfile.d.ts +5 -0
  19. package/dist/docker/dockerfile.d.ts.map +1 -0
  20. package/dist/docker/dockerfile.js +32 -0
  21. package/dist/docker/dockerfile.js.map +1 -0
  22. package/dist/docker/manager.d.ts +42 -0
  23. package/dist/docker/manager.d.ts.map +1 -0
  24. package/dist/docker/manager.js +311 -0
  25. package/dist/docker/manager.js.map +1 -0
  26. package/dist/git/status.d.ts +36 -0
  27. package/dist/git/status.d.ts.map +1 -0
  28. package/dist/git/status.js +213 -0
  29. package/dist/git/status.js.map +1 -0
  30. package/dist/routes/auth.d.ts +3 -0
  31. package/dist/routes/auth.d.ts.map +1 -0
  32. package/dist/routes/auth.js +49 -0
  33. package/dist/routes/auth.js.map +1 -0
  34. package/dist/routes/browse.d.ts +3 -0
  35. package/dist/routes/browse.d.ts.map +1 -0
  36. package/dist/routes/browse.js +49 -0
  37. package/dist/routes/browse.js.map +1 -0
  38. package/dist/routes/git.d.ts +3 -0
  39. package/dist/routes/git.d.ts.map +1 -0
  40. package/dist/routes/git.js +135 -0
  41. package/dist/routes/git.js.map +1 -0
  42. package/dist/routes/projects.d.ts +3 -0
  43. package/dist/routes/projects.d.ts.map +1 -0
  44. package/dist/routes/projects.js +149 -0
  45. package/dist/routes/projects.js.map +1 -0
  46. package/dist/routes/tasks.d.ts +3 -0
  47. package/dist/routes/tasks.d.ts.map +1 -0
  48. package/dist/routes/tasks.js +313 -0
  49. package/dist/routes/tasks.js.map +1 -0
  50. package/dist/server.d.ts +2 -0
  51. package/dist/server.d.ts.map +1 -0
  52. package/dist/server.js +60 -0
  53. package/dist/server.js.map +1 -0
  54. package/dist/types.d.ts +32 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +3 -0
  57. package/dist/types.js.map +1 -0
  58. package/draken.dockerfile.template +18 -0
  59. package/package.json +59 -0
  60. package/public/assets/index-B_sRrhlE.css +1 -0
  61. package/public/assets/index-DHRickdD.js +235 -0
  62. package/public/draken.svg +13 -0
  63. package/public/index.html +18 -0
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # Draken
2
+
3
+ ### What is this???
4
+
5
+ One more Agent orchestrator that I build for myself.
6
+
7
+ It might be buggy and it might be weird.
8
+
9
+ But it fit my needs.
10
+
11
+ ### WHY?
12
+
13
+ I often work on multiple projects simualtaniously and quite asynchrounously, and quite often I just want to submit a task for Claude in Private repo and return to it later.
14
+ I can use github integration with Claude, or Tmux sessions, but first one is lacking full machine access to run whatever it wants to achieve a task.
15
+ And tmux require ssh/machine access, so it doesn't really work when I commute or visiting at event.
16
+
17
+ The vision for Draken is that's asyncronous by nature and every interation with it is a single container run which completes and exits, the only artifact it produces is visible via `git diff`.
18
+ Context is preserved via sessions and threads in UI, so you can have few async sessions and interact with them.
19
+
20
+ ---
21
+
22
+ ## Install
23
+
24
+ ### Quick Start (npx)
25
+
26
+ ```bash
27
+ # Install prerequisites
28
+ npm install -g @anthropic-ai/claude-code
29
+ claude login # Authenticate with Anthropic
30
+
31
+ # Run Draken (local dev, no auth)
32
+ DRAKEN_NO_AUTH=true npx draken
33
+ ```
34
+
35
+ Open http://localhost:40333
36
+
37
+ ### VPS Deployment
38
+
39
+ ```bash
40
+ # 1. Install Node.js 18+ and Docker
41
+ curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
42
+ sudo apt-get install -y nodejs
43
+ curl -fsSL https://get.docker.com | sh
44
+ sudo usermod -aG docker $USER
45
+
46
+ # 2. Install and authenticate Claude CLI
47
+ npm install -g @anthropic-ai/claude-code
48
+ claude login
49
+
50
+ # 3. Set credentials and run
51
+ export DRAKEN_USERNAME=admin
52
+ export DRAKEN_PASSWORD=your-secure-password
53
+ export DRAKEN_JWT_SECRET=$(openssl rand -hex 32)
54
+
55
+ npx draken
56
+ ```
57
+
58
+ For HTTPS, put behind a reverse proxy:
59
+ ```bash
60
+ # Caddy (automatic HTTPS)
61
+ sudo caddy reverse-proxy --from draken.yourdomain.com --to localhost:40333
62
+ ```
63
+
64
+ ### From Source
65
+
66
+ ```bash
67
+ git clone https://github.com/mehanig/draken.git
68
+ cd draken
69
+
70
+ npm install && cd client && npm install && cd ..
71
+ npm run build && cd client && npm run build && cd ..
72
+
73
+ DRAKEN_NO_AUTH=true npm start
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Features
79
+
80
+ - **Multi-project** — Manage multiple codebases from one dashboard
81
+ - **Docker isolation** — Each task runs in its own container
82
+ - **Real-time logs** — Stream Claude's output via SSE
83
+ - **Session continuity** — Follow up on previous tasks
84
+ - **Git integration** — View status and diffs in the UI
85
+ - **Auth** — JWT-based for secure deployment
86
+
87
+ ## Configuration
88
+
89
+ | Variable | Required | Description |
90
+ |----------|----------|-------------|
91
+ | `DRAKEN_USERNAME` | For deployment | Web UI username |
92
+ | `DRAKEN_PASSWORD` | For deployment | Web UI password |
93
+ | `DRAKEN_JWT_SECRET` | For deployment | JWT signing secret (32+ chars) |
94
+ | `DRAKEN_NO_AUTH` | No | Set `true` to disable auth |
95
+ | `ANTHROPIC_API_KEY` | If no OAuth | Alternative to `claude login` |
96
+
97
+ ## Usage
98
+
99
+ 1. **Add a project** — Browse and select a folder
100
+ 2. **Generate Dockerfile** — One-time setup per project
101
+ 3. **Run a task** — Enter a prompt, Claude works in container
102
+ 4. **View logs** — Real-time output streaming
103
+ 5. **Follow up** — Continue the conversation
104
+ 6. **Check git diff** — Review changes before committing
105
+
106
+ ## License
107
+
108
+ MIT
@@ -0,0 +1,23 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ export interface AuthConfig {
3
+ username: string;
4
+ password: string;
5
+ jwtSecret: string;
6
+ tokenExpiry: string;
7
+ }
8
+ export interface JwtPayload {
9
+ username: string;
10
+ iat: number;
11
+ exp: number;
12
+ }
13
+ export interface AuthenticatedRequest extends Request {
14
+ user?: JwtPayload;
15
+ }
16
+ export declare function isNoAuthMode(): boolean;
17
+ export declare function getAuthConfig(): AuthConfig | null;
18
+ export declare function validateAuthConfig(): void;
19
+ export declare function isAuthEnabled(): boolean;
20
+ export declare function authMiddleware(req: AuthenticatedRequest, res: Response, next: NextFunction): void;
21
+ export declare function generateToken(username: string): string;
22
+ export declare function validateCredentials(username: string, password: string): boolean;
23
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,oBAAqB,SAAQ,OAAO;IACnD,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAGD,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAKD,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CA6BjD;AAGD,wBAAgB,kBAAkB,IAAI,IAAI,CASzC;AAGD,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAGD,wBAAgB,cAAc,CAAC,GAAG,EAAE,oBAAoB,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAqCjG;AAGD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAStD;AAGD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQ/E"}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isNoAuthMode = isNoAuthMode;
7
+ exports.getAuthConfig = getAuthConfig;
8
+ exports.validateAuthConfig = validateAuthConfig;
9
+ exports.isAuthEnabled = isAuthEnabled;
10
+ exports.authMiddleware = authMiddleware;
11
+ exports.generateToken = generateToken;
12
+ exports.validateCredentials = validateCredentials;
13
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
14
+ // Check if auth is explicitly disabled
15
+ function isNoAuthMode() {
16
+ return process.env.DRAKEN_NO_AUTH === 'true';
17
+ }
18
+ // Get auth configuration from environment variables
19
+ // Returns null only if NO_AUTH mode is enabled
20
+ // Throws error if auth is required but not properly configured
21
+ function getAuthConfig() {
22
+ // If NO_AUTH is explicitly set, disable authentication
23
+ if (isNoAuthMode()) {
24
+ return null;
25
+ }
26
+ const username = process.env.DRAKEN_USERNAME;
27
+ const password = process.env.DRAKEN_PASSWORD;
28
+ const jwtSecret = process.env.DRAKEN_JWT_SECRET;
29
+ // All three are required when auth is enabled
30
+ const missing = [];
31
+ if (!username)
32
+ missing.push('DRAKEN_USERNAME');
33
+ if (!password)
34
+ missing.push('DRAKEN_PASSWORD');
35
+ if (!jwtSecret)
36
+ missing.push('DRAKEN_JWT_SECRET');
37
+ if (missing.length > 0) {
38
+ throw new Error(`Authentication is required. Missing environment variables: ${missing.join(', ')}\n` +
39
+ `Set these variables or set DRAKEN_NO_AUTH=true to disable authentication.`);
40
+ }
41
+ return {
42
+ username: username,
43
+ password: password,
44
+ jwtSecret: jwtSecret,
45
+ tokenExpiry: process.env.DRAKEN_TOKEN_EXPIRY || '7d',
46
+ };
47
+ }
48
+ // Validate auth config on startup (call this early in server initialization)
49
+ function validateAuthConfig() {
50
+ if (isNoAuthMode()) {
51
+ console.log('Warning: Authentication is DISABLED (DRAKEN_NO_AUTH=true)');
52
+ return;
53
+ }
54
+ // This will throw if config is invalid
55
+ const config = getAuthConfig();
56
+ console.log(`Authentication enabled for user: ${config.username}`);
57
+ }
58
+ // Check if authentication is enabled
59
+ function isAuthEnabled() {
60
+ return !isNoAuthMode();
61
+ }
62
+ // Authentication middleware
63
+ function authMiddleware(req, res, next) {
64
+ // If NO_AUTH mode, allow all requests
65
+ if (isNoAuthMode()) {
66
+ return next();
67
+ }
68
+ const config = getAuthConfig();
69
+ // Get token from Authorization header or query param (for SSE endpoints)
70
+ const authHeader = req.headers.authorization;
71
+ const queryToken = req.query.token;
72
+ let token = null;
73
+ if (authHeader && authHeader.startsWith('Bearer ')) {
74
+ token = authHeader.substring(7); // Remove 'Bearer ' prefix
75
+ }
76
+ else if (queryToken) {
77
+ // Allow token via query param for SSE (EventSource doesn't support headers)
78
+ token = queryToken;
79
+ }
80
+ if (!token) {
81
+ res.status(401).json({ error: 'Authentication required', code: 'NO_TOKEN' });
82
+ return;
83
+ }
84
+ try {
85
+ const decoded = jsonwebtoken_1.default.verify(token, config.jwtSecret);
86
+ req.user = decoded;
87
+ next();
88
+ }
89
+ catch (err) {
90
+ if (err instanceof jsonwebtoken_1.default.TokenExpiredError) {
91
+ res.status(401).json({ error: 'Token expired', code: 'TOKEN_EXPIRED' });
92
+ }
93
+ else {
94
+ res.status(401).json({ error: 'Invalid token', code: 'INVALID_TOKEN' });
95
+ }
96
+ }
97
+ }
98
+ // Generate JWT token
99
+ function generateToken(username) {
100
+ const config = getAuthConfig();
101
+ if (!config) {
102
+ throw new Error('Auth not configured');
103
+ }
104
+ return jsonwebtoken_1.default.sign({ username }, config.jwtSecret, {
105
+ expiresIn: config.tokenExpiry,
106
+ });
107
+ }
108
+ // Validate credentials
109
+ function validateCredentials(username, password) {
110
+ const config = getAuthConfig();
111
+ if (!config) {
112
+ return false;
113
+ }
114
+ // Simple comparison - credentials are from env vars
115
+ return username === config.username && password === config.password;
116
+ }
117
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const path_1 = __importDefault(require("path"));
41
+ const fs_1 = __importDefault(require("fs"));
42
+ const os_1 = __importDefault(require("os"));
43
+ // Check for required environment variables
44
+ const noAuth = process.env.DRAKEN_NO_AUTH === 'true';
45
+ if (!noAuth) {
46
+ const required = ['DRAKEN_USERNAME', 'DRAKEN_PASSWORD', 'DRAKEN_JWT_SECRET'];
47
+ const missing = required.filter(key => !process.env[key]);
48
+ if (missing.length > 0) {
49
+ console.log('\n Draken - Claude Code Dashboard\n');
50
+ console.log(' Authentication is required. Set these environment variables:');
51
+ missing.forEach(key => console.log(` - ${key}`));
52
+ console.log('\n Or disable auth for local development:');
53
+ console.log(' DRAKEN_NO_AUTH=true npx draken\n');
54
+ process.exit(1);
55
+ }
56
+ }
57
+ // Check for Claude authentication
58
+ const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || path_1.default.join(os_1.default.homedir(), '.claude');
59
+ const hasOAuth = fs_1.default.existsSync(path_1.default.join(claudeConfigDir, '.credentials.json'));
60
+ const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
61
+ if (!hasOAuth && !hasApiKey) {
62
+ console.log('\n Draken - Claude Code Dashboard\n');
63
+ console.log(' Claude authentication required. Choose one:');
64
+ console.log(' 1. Run: claude login');
65
+ console.log(' 2. Set: ANTHROPIC_API_KEY=your-key\n');
66
+ process.exit(1);
67
+ }
68
+ // Import and start the server
69
+ Promise.resolve().then(() => __importStar(require('./server')));
70
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,gDAAwB;AACxB,4CAAoB;AACpB,4CAAoB;AAEpB,2CAA2C;AAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM,CAAC;AACrD,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,MAAM,QAAQ,GAAG,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAE1D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;QAC9E,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,kCAAkC;AAClC,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAC5F,MAAM,QAAQ,GAAG,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAChF,MAAM,SAAS,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;AAElD,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,8BAA8B;AAC9B,kDAAO,UAAU,IAAE"}
@@ -0,0 +1,16 @@
1
+ import { Project, Task } from '../types';
2
+ export declare function getAllProjects(): Project[];
3
+ export declare function getProjectById(id: number): Project | undefined;
4
+ export declare function createProject(name: string, path: string): Project;
5
+ export declare function deleteProject(id: number): boolean;
6
+ export declare function updateProjectDockerfileStatus(id: number, exists: boolean): void;
7
+ export declare function getTasksByProjectId(projectId: number): Task[];
8
+ export declare function getTaskById(id: number): Task | undefined;
9
+ export declare function createTask(projectId: number, prompt: string, parentTaskId?: number): Task;
10
+ export declare function updateTaskSessionId(id: number, sessionId: string): void;
11
+ export declare function getLatestTaskWithSession(projectId: number): Task | undefined;
12
+ export declare function updateTaskStatus(id: number, status: Task['status'], containerId?: string): void;
13
+ export declare function updateTaskCompleted(id: number, status: Task['status']): void;
14
+ export declare function appendTaskLogs(id: number, newLogs: string): void;
15
+ export declare function getRunningTasks(): Task[];
16
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/db/queries.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAGzC,wBAAgB,cAAc,IAAI,OAAO,EAAE,CAG1C;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAG9D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAIjE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAIjD;AAED,wBAAgB,6BAA6B,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAG/E;AAGD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,CAG7D;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAGxD;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAIzF;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAGvE;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAQ5E;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAO/F;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAG5E;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAKhE;AAED,wBAAgB,eAAe,IAAI,IAAI,EAAE,CAGxC"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAllProjects = getAllProjects;
4
+ exports.getProjectById = getProjectById;
5
+ exports.createProject = createProject;
6
+ exports.deleteProject = deleteProject;
7
+ exports.updateProjectDockerfileStatus = updateProjectDockerfileStatus;
8
+ exports.getTasksByProjectId = getTasksByProjectId;
9
+ exports.getTaskById = getTaskById;
10
+ exports.createTask = createTask;
11
+ exports.updateTaskSessionId = updateTaskSessionId;
12
+ exports.getLatestTaskWithSession = getLatestTaskWithSession;
13
+ exports.updateTaskStatus = updateTaskStatus;
14
+ exports.updateTaskCompleted = updateTaskCompleted;
15
+ exports.appendTaskLogs = appendTaskLogs;
16
+ exports.getRunningTasks = getRunningTasks;
17
+ const schema_1 = require("./schema");
18
+ // Project queries
19
+ function getAllProjects() {
20
+ const db = (0, schema_1.getDb)();
21
+ return db.prepare('SELECT * FROM projects ORDER BY created_at DESC').all();
22
+ }
23
+ function getProjectById(id) {
24
+ const db = (0, schema_1.getDb)();
25
+ return db.prepare('SELECT * FROM projects WHERE id = ?').get(id);
26
+ }
27
+ function createProject(name, path) {
28
+ const db = (0, schema_1.getDb)();
29
+ const result = db.prepare('INSERT INTO projects (name, path) VALUES (?, ?)').run(name, path);
30
+ return getProjectById(result.lastInsertRowid);
31
+ }
32
+ function deleteProject(id) {
33
+ const db = (0, schema_1.getDb)();
34
+ const result = db.prepare('DELETE FROM projects WHERE id = ?').run(id);
35
+ return result.changes > 0;
36
+ }
37
+ function updateProjectDockerfileStatus(id, exists) {
38
+ const db = (0, schema_1.getDb)();
39
+ db.prepare('UPDATE projects SET dockerfile_exists = ? WHERE id = ?').run(exists ? 1 : 0, id);
40
+ }
41
+ // Task queries
42
+ function getTasksByProjectId(projectId) {
43
+ const db = (0, schema_1.getDb)();
44
+ return db.prepare('SELECT * FROM tasks WHERE project_id = ? ORDER BY created_at DESC').all(projectId);
45
+ }
46
+ function getTaskById(id) {
47
+ const db = (0, schema_1.getDb)();
48
+ return db.prepare('SELECT * FROM tasks WHERE id = ?').get(id);
49
+ }
50
+ function createTask(projectId, prompt, parentTaskId) {
51
+ const db = (0, schema_1.getDb)();
52
+ const result = db.prepare('INSERT INTO tasks (project_id, prompt, status, parent_task_id) VALUES (?, ?, ?, ?)').run(projectId, prompt, 'pending', parentTaskId || null);
53
+ return getTaskById(result.lastInsertRowid);
54
+ }
55
+ function updateTaskSessionId(id, sessionId) {
56
+ const db = (0, schema_1.getDb)();
57
+ db.prepare('UPDATE tasks SET session_id = ? WHERE id = ?').run(sessionId, id);
58
+ }
59
+ function getLatestTaskWithSession(projectId) {
60
+ const db = (0, schema_1.getDb)();
61
+ return db.prepare(`
62
+ SELECT * FROM tasks
63
+ WHERE project_id = ? AND session_id IS NOT NULL
64
+ ORDER BY created_at DESC
65
+ LIMIT 1
66
+ `).get(projectId);
67
+ }
68
+ function updateTaskStatus(id, status, containerId) {
69
+ const db = (0, schema_1.getDb)();
70
+ if (containerId) {
71
+ db.prepare('UPDATE tasks SET status = ?, container_id = ? WHERE id = ?').run(status, containerId, id);
72
+ }
73
+ else {
74
+ db.prepare('UPDATE tasks SET status = ? WHERE id = ?').run(status, id);
75
+ }
76
+ }
77
+ function updateTaskCompleted(id, status) {
78
+ const db = (0, schema_1.getDb)();
79
+ db.prepare('UPDATE tasks SET status = ?, completed_at = CURRENT_TIMESTAMP WHERE id = ?').run(status, id);
80
+ }
81
+ function appendTaskLogs(id, newLogs) {
82
+ const db = (0, schema_1.getDb)();
83
+ const task = getTaskById(id);
84
+ const currentLogs = task?.logs || '';
85
+ db.prepare('UPDATE tasks SET logs = ? WHERE id = ?').run(currentLogs + newLogs, id);
86
+ }
87
+ function getRunningTasks() {
88
+ const db = (0, schema_1.getDb)();
89
+ return db.prepare("SELECT * FROM tasks WHERE status = 'running'").all();
90
+ }
91
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/db/queries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import Database from 'better-sqlite3';
2
+ export declare function getDb(): Database.Database;
3
+ export declare function closeDb(): void;
4
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAOtC,wBAAgB,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAczC;AA2CD,wBAAgB,OAAO,IAAI,IAAI,CAK9B"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getDb = getDb;
7
+ exports.closeDb = closeDb;
8
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const DB_PATH = path_1.default.join(__dirname, '../../data/draken.db');
11
+ let db = null;
12
+ function getDb() {
13
+ if (!db) {
14
+ // Ensure data directory exists
15
+ const fs = require('fs');
16
+ const dataDir = path_1.default.dirname(DB_PATH);
17
+ if (!fs.existsSync(dataDir)) {
18
+ fs.mkdirSync(dataDir, { recursive: true });
19
+ }
20
+ db = new better_sqlite3_1.default(DB_PATH);
21
+ db.pragma('journal_mode = WAL');
22
+ initSchema(db);
23
+ }
24
+ return db;
25
+ }
26
+ function initSchema(db) {
27
+ // Create tables
28
+ db.exec(`
29
+ CREATE TABLE IF NOT EXISTS projects (
30
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
31
+ name TEXT NOT NULL,
32
+ path TEXT NOT NULL UNIQUE,
33
+ dockerfile_exists INTEGER DEFAULT 0,
34
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
35
+ );
36
+
37
+ CREATE TABLE IF NOT EXISTS tasks (
38
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
39
+ project_id INTEGER NOT NULL,
40
+ prompt TEXT NOT NULL,
41
+ status TEXT DEFAULT 'pending',
42
+ container_id TEXT,
43
+ logs TEXT,
44
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
45
+ completed_at DATETIME,
46
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
47
+ );
48
+
49
+ CREATE INDEX IF NOT EXISTS idx_tasks_project_id ON tasks(project_id);
50
+ CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
51
+ `);
52
+ // Migration: Add session_id column if it doesn't exist
53
+ try {
54
+ db.exec(`ALTER TABLE tasks ADD COLUMN session_id TEXT`);
55
+ }
56
+ catch { /* Column already exists */ }
57
+ // Migration: Add parent_task_id column if it doesn't exist
58
+ try {
59
+ db.exec(`ALTER TABLE tasks ADD COLUMN parent_task_id INTEGER REFERENCES tasks(id) ON DELETE SET NULL`);
60
+ }
61
+ catch { /* Column already exists */ }
62
+ // Create index on session_id (after migration ensures column exists)
63
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_tasks_session_id ON tasks(session_id)`);
64
+ }
65
+ function closeDb() {
66
+ if (db) {
67
+ db.close();
68
+ db = null;
69
+ }
70
+ }
71
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":";;;;;AAOA,sBAcC;AA2CD,0BAKC;AArED,oEAAsC;AACtC,gDAAwB;AAExB,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;AAE7D,IAAI,EAAE,GAA6B,IAAI,CAAC;AAExC,SAAgB,KAAK;IACnB,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,+BAA+B;QAC/B,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,OAAO,GAAG,cAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QAED,EAAE,GAAG,IAAI,wBAAQ,CAAC,OAAO,CAAC,CAAC;QAC3B,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAChC,UAAU,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,UAAU,CAAC,EAAqB;IACvC,gBAAgB;IAChB,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;GAuBP,CAAC,CAAC;IAEH,uDAAuD;IACvD,IAAI,CAAC;QACH,EAAE,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC,CAAC,2BAA2B,CAAC,CAAC;IAEvC,2DAA2D;IAC3D,IAAI,CAAC;QACH,EAAE,CAAC,IAAI,CAAC,6FAA6F,CAAC,CAAC;IACzG,CAAC;IAAC,MAAM,CAAC,CAAC,2BAA2B,CAAC,CAAC;IAEvC,qEAAqE;IACrE,EAAE,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;AAClF,CAAC;AAED,SAAgB,OAAO;IACrB,IAAI,EAAE,EAAE,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,EAAE,GAAG,IAAI,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function getDockerfilePath(projectPath: string): string;
2
+ export declare function dockerfileExists(projectPath: string): boolean;
3
+ export declare function generateDockerfile(projectPath: string): void;
4
+ export declare function getDockerfileContent(projectPath: string): string | null;
5
+ //# sourceMappingURL=dockerfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dockerfile.d.ts","sourceRoot":"","sources":["../../src/docker/dockerfile.ts"],"names":[],"mappings":"AAMA,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAI5D;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMvE"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getDockerfilePath = getDockerfilePath;
7
+ exports.dockerfileExists = dockerfileExists;
8
+ exports.generateDockerfile = generateDockerfile;
9
+ exports.getDockerfileContent = getDockerfileContent;
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const TEMPLATE_PATH = path_1.default.join(__dirname, '../../draken.dockerfile.template');
13
+ const DOCKERFILE_NAME = 'Dockerfile.draken';
14
+ function getDockerfilePath(projectPath) {
15
+ return path_1.default.join(projectPath, DOCKERFILE_NAME);
16
+ }
17
+ function dockerfileExists(projectPath) {
18
+ return fs_1.default.existsSync(getDockerfilePath(projectPath));
19
+ }
20
+ function generateDockerfile(projectPath) {
21
+ const templateContent = fs_1.default.readFileSync(TEMPLATE_PATH, 'utf-8');
22
+ const dockerfilePath = getDockerfilePath(projectPath);
23
+ fs_1.default.writeFileSync(dockerfilePath, templateContent);
24
+ }
25
+ function getDockerfileContent(projectPath) {
26
+ const dockerfilePath = getDockerfilePath(projectPath);
27
+ if (fs_1.default.existsSync(dockerfilePath)) {
28
+ return fs_1.default.readFileSync(dockerfilePath, 'utf-8');
29
+ }
30
+ return null;
31
+ }
32
+ //# sourceMappingURL=dockerfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dockerfile.js","sourceRoot":"","sources":["../../src/docker/dockerfile.ts"],"names":[],"mappings":";;;;;AAMA,8CAEC;AAED,4CAEC;AAED,gDAIC;AAED,oDAMC;AA1BD,4CAAoB;AACpB,gDAAwB;AAExB,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kCAAkC,CAAC,CAAC;AAC/E,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAE5C,SAAgB,iBAAiB,CAAC,WAAmB;IACnD,OAAO,cAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;AACjD,CAAC;AAED,SAAgB,gBAAgB,CAAC,WAAmB;IAClD,OAAO,YAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,SAAgB,kBAAkB,CAAC,WAAmB;IACpD,MAAM,eAAe,GAAG,YAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAChE,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACtD,YAAE,CAAC,aAAa,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,oBAAoB,CAAC,WAAmB;IACtD,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACtD,IAAI,YAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAClC,OAAO,YAAE,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { EventEmitter } from 'events';
2
+ export interface ContainerLogEmitter extends EventEmitter {
3
+ on(event: 'log', listener: (data: string) => void): this;
4
+ on(event: 'end', listener: (exitCode: number) => void): this;
5
+ on(event: 'error', listener: (err: Error) => void): this;
6
+ on(event: 'session', listener: (sessionId: string) => void): this;
7
+ }
8
+ /**
9
+ * Get the Claude config directory path
10
+ * Uses CLAUDE_CONFIG_DIR if set, otherwise defaults to ~/.claude
11
+ */
12
+ export declare function getClaudeConfigDir(): string;
13
+ /**
14
+ * Check if OAuth credentials exist in the Claude config directory
15
+ */
16
+ export declare function hasOAuthCredentials(): boolean;
17
+ /**
18
+ * Get authentication configuration for Claude
19
+ * Returns either OAuth config (config dir to mount) or API key
20
+ */
21
+ export interface ClaudeAuthConfig {
22
+ type: 'oauth' | 'api_key';
23
+ configDir?: string;
24
+ apiKey?: string;
25
+ }
26
+ export declare function getClaudeAuthConfig(): ClaudeAuthConfig | null;
27
+ /**
28
+ * Validate Claude authentication on startup
29
+ * Throws if no auth method is available
30
+ */
31
+ export declare function validateClaudeAuth(): void;
32
+ export declare function buildProjectImage(projectPath: string, projectId: number): Promise<string>;
33
+ export declare function runTask(projectPath: string, projectId: number, prompt: string, taskId: number, resumeSessionId?: string): Promise<{
34
+ containerId: string;
35
+ logEmitter: ContainerLogEmitter;
36
+ }>;
37
+ export declare function sendInputToTask(taskId: number, input: string): boolean;
38
+ export declare function isTaskRunning(taskId: number): boolean;
39
+ export declare function stopContainer(containerId: string): Promise<void>;
40
+ export declare function getContainerStatus(containerId: string): Promise<string>;
41
+ export declare function imageExists(projectId: number): Promise<boolean>;
42
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/docker/manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAqCtC,MAAM,WAAW,mBAAoB,SAAQ,YAAY;IACvD,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACzD,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC7D,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IACzD,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;CACnE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAI7C;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,IAAI,CAoB7D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAoBzC;AAED,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkB/F;AAED,wBAAsB,OAAO,CAC3B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAsJnE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAOtE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBtE;AAED,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa7E;AAED,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQrE"}