@jonit-dev/night-watch-cli 1.0.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/LICENSE +21 -0
- package/README.md +509 -0
- package/bin/night-watch.mjs +2 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +35 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +376 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +15 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +135 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/logs.d.ts +15 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +104 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/review.d.ts +26 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +144 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/run.d.ts +26 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +161 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/status.d.ts +14 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +303 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/uninstall.d.ts +13 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +97 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/config.d.ts +23 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +213 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +33 -0
- package/dist/constants.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/crontab.d.ts +50 -0
- package/dist/utils/crontab.d.ts.map +1 -0
- package/dist/utils/crontab.js +116 -0
- package/dist/utils/crontab.js.map +1 -0
- package/dist/utils/shell.d.ts +13 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +44 -0
- package/dist/utils/shell.js.map +1 -0
- package/dist/utils/ui.d.ts +55 -0
- package/dist/utils/ui.d.ts.map +1 -0
- package/dist/utils/ui.js +121 -0
- package/dist/utils/ui.js.map +1 -0
- package/package.json +64 -0
- package/scripts/night-watch-cron.sh +148 -0
- package/scripts/night-watch-helpers.sh +155 -0
- package/scripts/night-watch-pr-reviewer-cron.sh +135 -0
- package/templates/night-watch-pr-reviewer.md +144 -0
- package/templates/night-watch.config.json +21 -0
- package/templates/night-watch.md +100 -0
- package/templates/prd-executor.md +235 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader for Night Watch CLI
|
|
3
|
+
* Loads config from: defaults -> config file -> environment variables
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import { DEFAULT_PRD_DIR, DEFAULT_MAX_RUNTIME, DEFAULT_REVIEWER_MAX_RUNTIME, DEFAULT_CRON_SCHEDULE, DEFAULT_REVIEWER_SCHEDULE, DEFAULT_BRANCH_PREFIX, DEFAULT_BRANCH_PATTERNS, DEFAULT_MIN_REVIEW_SCORE, DEFAULT_MAX_LOG_SIZE, DEFAULT_PROVIDER, DEFAULT_REVIEWER_ENABLED, VALID_PROVIDERS, CONFIG_FILE_NAME, } from "./constants.js";
|
|
8
|
+
/**
|
|
9
|
+
* Get the default configuration values
|
|
10
|
+
*/
|
|
11
|
+
export function getDefaultConfig() {
|
|
12
|
+
return {
|
|
13
|
+
// PRD execution
|
|
14
|
+
prdDir: DEFAULT_PRD_DIR,
|
|
15
|
+
maxRuntime: DEFAULT_MAX_RUNTIME,
|
|
16
|
+
reviewerMaxRuntime: DEFAULT_REVIEWER_MAX_RUNTIME,
|
|
17
|
+
branchPrefix: DEFAULT_BRANCH_PREFIX,
|
|
18
|
+
branchPatterns: [...DEFAULT_BRANCH_PATTERNS],
|
|
19
|
+
minReviewScore: DEFAULT_MIN_REVIEW_SCORE,
|
|
20
|
+
maxLogSize: DEFAULT_MAX_LOG_SIZE,
|
|
21
|
+
// Cron scheduling
|
|
22
|
+
cronSchedule: DEFAULT_CRON_SCHEDULE,
|
|
23
|
+
reviewerSchedule: DEFAULT_REVIEWER_SCHEDULE,
|
|
24
|
+
// Provider configuration
|
|
25
|
+
provider: DEFAULT_PROVIDER,
|
|
26
|
+
reviewerEnabled: DEFAULT_REVIEWER_ENABLED,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Load configuration from a JSON file
|
|
31
|
+
*/
|
|
32
|
+
function loadConfigFile(configPath) {
|
|
33
|
+
try {
|
|
34
|
+
if (!fs.existsSync(configPath)) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
38
|
+
const config = JSON.parse(content);
|
|
39
|
+
return config;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
// If file exists but can't be parsed, warn but don't fail
|
|
43
|
+
console.warn(`Warning: Could not parse config file at ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Parse a boolean string value
|
|
49
|
+
*/
|
|
50
|
+
function parseBoolean(value) {
|
|
51
|
+
const normalized = value.toLowerCase().trim();
|
|
52
|
+
if (normalized === "true" || normalized === "1") {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (normalized === "false" || normalized === "0") {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Validate and return a provider value
|
|
62
|
+
*/
|
|
63
|
+
function validateProvider(value) {
|
|
64
|
+
if (VALID_PROVIDERS.includes(value)) {
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Deep merge configuration objects
|
|
71
|
+
* Environment values take precedence over file values
|
|
72
|
+
*/
|
|
73
|
+
function mergeConfigs(base, fileConfig, envConfig) {
|
|
74
|
+
const merged = { ...base };
|
|
75
|
+
// Merge file config
|
|
76
|
+
if (fileConfig) {
|
|
77
|
+
if (fileConfig.prdDir !== undefined)
|
|
78
|
+
merged.prdDir = fileConfig.prdDir;
|
|
79
|
+
if (fileConfig.maxRuntime !== undefined)
|
|
80
|
+
merged.maxRuntime = fileConfig.maxRuntime;
|
|
81
|
+
if (fileConfig.reviewerMaxRuntime !== undefined)
|
|
82
|
+
merged.reviewerMaxRuntime = fileConfig.reviewerMaxRuntime;
|
|
83
|
+
if (fileConfig.branchPrefix !== undefined)
|
|
84
|
+
merged.branchPrefix = fileConfig.branchPrefix;
|
|
85
|
+
if (fileConfig.branchPatterns !== undefined)
|
|
86
|
+
merged.branchPatterns = [...fileConfig.branchPatterns];
|
|
87
|
+
if (fileConfig.minReviewScore !== undefined)
|
|
88
|
+
merged.minReviewScore = fileConfig.minReviewScore;
|
|
89
|
+
if (fileConfig.maxLogSize !== undefined)
|
|
90
|
+
merged.maxLogSize = fileConfig.maxLogSize;
|
|
91
|
+
if (fileConfig.cronSchedule !== undefined)
|
|
92
|
+
merged.cronSchedule = fileConfig.cronSchedule;
|
|
93
|
+
if (fileConfig.reviewerSchedule !== undefined)
|
|
94
|
+
merged.reviewerSchedule = fileConfig.reviewerSchedule;
|
|
95
|
+
if (fileConfig.provider !== undefined)
|
|
96
|
+
merged.provider = fileConfig.provider;
|
|
97
|
+
if (fileConfig.reviewerEnabled !== undefined)
|
|
98
|
+
merged.reviewerEnabled = fileConfig.reviewerEnabled;
|
|
99
|
+
}
|
|
100
|
+
// Merge env config (takes precedence)
|
|
101
|
+
if (envConfig.prdDir !== undefined)
|
|
102
|
+
merged.prdDir = envConfig.prdDir;
|
|
103
|
+
if (envConfig.maxRuntime !== undefined)
|
|
104
|
+
merged.maxRuntime = envConfig.maxRuntime;
|
|
105
|
+
if (envConfig.reviewerMaxRuntime !== undefined)
|
|
106
|
+
merged.reviewerMaxRuntime = envConfig.reviewerMaxRuntime;
|
|
107
|
+
if (envConfig.branchPrefix !== undefined)
|
|
108
|
+
merged.branchPrefix = envConfig.branchPrefix;
|
|
109
|
+
if (envConfig.branchPatterns !== undefined)
|
|
110
|
+
merged.branchPatterns = [...envConfig.branchPatterns];
|
|
111
|
+
if (envConfig.minReviewScore !== undefined)
|
|
112
|
+
merged.minReviewScore = envConfig.minReviewScore;
|
|
113
|
+
if (envConfig.maxLogSize !== undefined)
|
|
114
|
+
merged.maxLogSize = envConfig.maxLogSize;
|
|
115
|
+
if (envConfig.cronSchedule !== undefined)
|
|
116
|
+
merged.cronSchedule = envConfig.cronSchedule;
|
|
117
|
+
if (envConfig.reviewerSchedule !== undefined)
|
|
118
|
+
merged.reviewerSchedule = envConfig.reviewerSchedule;
|
|
119
|
+
if (envConfig.provider !== undefined)
|
|
120
|
+
merged.provider = envConfig.provider;
|
|
121
|
+
if (envConfig.reviewerEnabled !== undefined)
|
|
122
|
+
merged.reviewerEnabled = envConfig.reviewerEnabled;
|
|
123
|
+
return merged;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Load Night Watch configuration
|
|
127
|
+
* Priority: defaults < config file < environment variables
|
|
128
|
+
*
|
|
129
|
+
* @param projectDir - The project directory to load config from
|
|
130
|
+
* @returns Merged configuration object
|
|
131
|
+
*/
|
|
132
|
+
export function loadConfig(projectDir) {
|
|
133
|
+
// Start with defaults
|
|
134
|
+
const defaults = getDefaultConfig();
|
|
135
|
+
// Load config file
|
|
136
|
+
const configPath = path.join(projectDir, CONFIG_FILE_NAME);
|
|
137
|
+
const fileConfig = loadConfigFile(configPath);
|
|
138
|
+
// Load environment overrides
|
|
139
|
+
const envConfig = {};
|
|
140
|
+
// NW_* environment variables
|
|
141
|
+
if (process.env.NW_PRD_DIR) {
|
|
142
|
+
envConfig.prdDir = process.env.NW_PRD_DIR;
|
|
143
|
+
}
|
|
144
|
+
if (process.env.NW_MAX_RUNTIME) {
|
|
145
|
+
const runtime = parseInt(process.env.NW_MAX_RUNTIME, 10);
|
|
146
|
+
if (!isNaN(runtime)) {
|
|
147
|
+
envConfig.maxRuntime = runtime;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (process.env.NW_REVIEWER_MAX_RUNTIME) {
|
|
151
|
+
const runtime = parseInt(process.env.NW_REVIEWER_MAX_RUNTIME, 10);
|
|
152
|
+
if (!isNaN(runtime)) {
|
|
153
|
+
envConfig.reviewerMaxRuntime = runtime;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (process.env.NW_BRANCH_PREFIX) {
|
|
157
|
+
envConfig.branchPrefix = process.env.NW_BRANCH_PREFIX;
|
|
158
|
+
}
|
|
159
|
+
if (process.env.NW_BRANCH_PATTERNS) {
|
|
160
|
+
try {
|
|
161
|
+
envConfig.branchPatterns = JSON.parse(process.env.NW_BRANCH_PATTERNS);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// If not valid JSON, treat as comma-separated
|
|
165
|
+
envConfig.branchPatterns = process.env.NW_BRANCH_PATTERNS.split(",").map((s) => s.trim());
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (process.env.NW_MIN_REVIEW_SCORE) {
|
|
169
|
+
const score = parseInt(process.env.NW_MIN_REVIEW_SCORE, 10);
|
|
170
|
+
if (!isNaN(score)) {
|
|
171
|
+
envConfig.minReviewScore = score;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (process.env.NW_MAX_LOG_SIZE) {
|
|
175
|
+
const size = parseInt(process.env.NW_MAX_LOG_SIZE, 10);
|
|
176
|
+
if (!isNaN(size)) {
|
|
177
|
+
envConfig.maxLogSize = size;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (process.env.NW_CRON_SCHEDULE) {
|
|
181
|
+
envConfig.cronSchedule = process.env.NW_CRON_SCHEDULE;
|
|
182
|
+
}
|
|
183
|
+
if (process.env.NW_REVIEWER_SCHEDULE) {
|
|
184
|
+
envConfig.reviewerSchedule = process.env.NW_REVIEWER_SCHEDULE;
|
|
185
|
+
}
|
|
186
|
+
// NW_PROVIDER environment variable
|
|
187
|
+
if (process.env.NW_PROVIDER) {
|
|
188
|
+
const provider = validateProvider(process.env.NW_PROVIDER);
|
|
189
|
+
if (provider !== null) {
|
|
190
|
+
envConfig.provider = provider;
|
|
191
|
+
}
|
|
192
|
+
// If invalid, fallback to default (don't set envConfig.provider)
|
|
193
|
+
}
|
|
194
|
+
// NW_REVIEWER_ENABLED environment variable
|
|
195
|
+
if (process.env.NW_REVIEWER_ENABLED) {
|
|
196
|
+
const reviewerEnabled = parseBoolean(process.env.NW_REVIEWER_ENABLED);
|
|
197
|
+
if (reviewerEnabled !== null) {
|
|
198
|
+
envConfig.reviewerEnabled = reviewerEnabled;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Merge all configs
|
|
202
|
+
return mergeConfigs(defaults, fileConfig, envConfig);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get the path to a bundled script
|
|
206
|
+
* This returns the path to a script in the package's scripts/ directory
|
|
207
|
+
*/
|
|
208
|
+
export function getScriptPath(scriptName) {
|
|
209
|
+
// In development, scripts are in scripts/ relative to package root
|
|
210
|
+
// In production (after npm pack), they're still in scripts/
|
|
211
|
+
return path.join(path.dirname(new URL(import.meta.url).pathname), "..", "scripts", scriptName);
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default configuration values for Night Watch CLI
|
|
3
|
+
*/
|
|
4
|
+
import { Provider } from "./types.js";
|
|
5
|
+
export declare const DEFAULT_PRD_DIR = "docs/PRDs/night-watch";
|
|
6
|
+
export declare const DEFAULT_MAX_RUNTIME = 7200;
|
|
7
|
+
export declare const DEFAULT_REVIEWER_MAX_RUNTIME = 3600;
|
|
8
|
+
export declare const DEFAULT_CRON_SCHEDULE = "0 0-15 * * *";
|
|
9
|
+
export declare const DEFAULT_REVIEWER_SCHEDULE = "0 0,3,6,9,12,15 * * *";
|
|
10
|
+
export declare const DEFAULT_BRANCH_PREFIX = "night-watch";
|
|
11
|
+
export declare const DEFAULT_BRANCH_PATTERNS: string[];
|
|
12
|
+
export declare const DEFAULT_MIN_REVIEW_SCORE = 80;
|
|
13
|
+
export declare const DEFAULT_MAX_LOG_SIZE = 524288;
|
|
14
|
+
export declare const DEFAULT_PROVIDER: Provider;
|
|
15
|
+
export declare const DEFAULT_REVIEWER_ENABLED = true;
|
|
16
|
+
export declare const VALID_PROVIDERS: Provider[];
|
|
17
|
+
export declare const PROVIDER_COMMANDS: Record<Provider, string>;
|
|
18
|
+
export declare const CONFIG_FILE_NAME = "night-watch.config.json";
|
|
19
|
+
export declare const LOCK_FILE_PREFIX = "/tmp/night-watch-";
|
|
20
|
+
export declare const LOG_DIR = "logs";
|
|
21
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,eAAO,MAAM,eAAe,0BAA0B,CAAC;AAGvD,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAGjD,eAAO,MAAM,qBAAqB,iBAAiB,CAAC;AACpD,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AAGjE,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AACnD,eAAO,MAAM,uBAAuB,UAA4B,CAAC;AAGjE,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAG3C,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAG3C,eAAO,MAAM,gBAAgB,EAAE,QAAmB,CAAC;AACnD,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAG7C,eAAO,MAAM,eAAe,EAAE,QAAQ,EAAwB,CAAC;AAG/D,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAGtD,CAAC;AAGF,eAAO,MAAM,gBAAgB,4BAA4B,CAAC;AAC1D,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AACpD,eAAO,MAAM,OAAO,SAAS,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default configuration values for Night Watch CLI
|
|
3
|
+
*/
|
|
4
|
+
// PRD Configuration
|
|
5
|
+
export const DEFAULT_PRD_DIR = "docs/PRDs/night-watch";
|
|
6
|
+
// Runtime Configuration (in seconds)
|
|
7
|
+
export const DEFAULT_MAX_RUNTIME = 7200;
|
|
8
|
+
export const DEFAULT_REVIEWER_MAX_RUNTIME = 3600;
|
|
9
|
+
// Cron Schedule Configuration
|
|
10
|
+
export const DEFAULT_CRON_SCHEDULE = "0 0-15 * * *";
|
|
11
|
+
export const DEFAULT_REVIEWER_SCHEDULE = "0 0,3,6,9,12,15 * * *";
|
|
12
|
+
// Branch Configuration
|
|
13
|
+
export const DEFAULT_BRANCH_PREFIX = "night-watch";
|
|
14
|
+
export const DEFAULT_BRANCH_PATTERNS = ["feat/", "night-watch/"];
|
|
15
|
+
// Review Configuration
|
|
16
|
+
export const DEFAULT_MIN_REVIEW_SCORE = 80;
|
|
17
|
+
// Log Configuration
|
|
18
|
+
export const DEFAULT_MAX_LOG_SIZE = 524288; // 512 KB
|
|
19
|
+
// Provider Configuration
|
|
20
|
+
export const DEFAULT_PROVIDER = "claude";
|
|
21
|
+
export const DEFAULT_REVIEWER_ENABLED = true;
|
|
22
|
+
// Valid providers
|
|
23
|
+
export const VALID_PROVIDERS = ["claude", "codex"];
|
|
24
|
+
// Provider commands configuration
|
|
25
|
+
export const PROVIDER_COMMANDS = {
|
|
26
|
+
claude: "claude",
|
|
27
|
+
codex: "codex",
|
|
28
|
+
};
|
|
29
|
+
// File Names and Paths
|
|
30
|
+
export const CONFIG_FILE_NAME = "night-watch.config.json";
|
|
31
|
+
export const LOCK_FILE_PREFIX = "/tmp/night-watch-";
|
|
32
|
+
export const LOG_DIR = "logs";
|
|
33
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,oBAAoB;AACpB,MAAM,CAAC,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAEvD,qCAAqC;AACrC,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACxC,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAEjD,8BAA8B;AAC9B,MAAM,CAAC,MAAM,qBAAqB,GAAG,cAAc,CAAC;AACpD,MAAM,CAAC,MAAM,yBAAyB,GAAG,uBAAuB,CAAC;AAEjE,uBAAuB;AACvB,MAAM,CAAC,MAAM,qBAAqB,GAAG,aAAa,CAAC;AACnD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AAEjE,uBAAuB;AACvB,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C,oBAAoB;AACpB,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,CAAC,SAAS;AAErD,yBAAyB;AACzB,MAAM,CAAC,MAAM,gBAAgB,GAAa,QAAQ,CAAC;AACnD,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAE7C,kBAAkB;AAClB,MAAM,CAAC,MAAM,eAAe,GAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAE/D,kCAAkC;AAClC,MAAM,CAAC,MAAM,iBAAiB,GAA6B;IACzD,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;CACf,CAAC;AAEF,uBAAuB;AACvB,MAAM,CAAC,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAC1D,MAAM,CAAC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AACpD,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript interfaces for Night Watch CLI configuration
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Supported AI providers
|
|
6
|
+
*/
|
|
7
|
+
export type Provider = "claude" | "codex";
|
|
8
|
+
/**
|
|
9
|
+
* Complete Night Watch configuration
|
|
10
|
+
*/
|
|
11
|
+
export interface INightWatchConfig {
|
|
12
|
+
/** Directory containing PRD files (relative to project root) */
|
|
13
|
+
prdDir: string;
|
|
14
|
+
/** Maximum runtime in seconds for PRD execution */
|
|
15
|
+
maxRuntime: number;
|
|
16
|
+
/** Maximum runtime in seconds for PR reviewer */
|
|
17
|
+
reviewerMaxRuntime: number;
|
|
18
|
+
/** Prefix for night-watch branches */
|
|
19
|
+
branchPrefix: string;
|
|
20
|
+
/** Branch patterns to match for PR reviewer */
|
|
21
|
+
branchPatterns: string[];
|
|
22
|
+
/** Minimum review score (out of 100) to consider PR complete */
|
|
23
|
+
minReviewScore: number;
|
|
24
|
+
/** Maximum log file size in bytes before rotation */
|
|
25
|
+
maxLogSize: number;
|
|
26
|
+
/** Cron schedule for PRD execution */
|
|
27
|
+
cronSchedule: string;
|
|
28
|
+
/** Cron schedule for PR reviewer */
|
|
29
|
+
reviewerSchedule: string;
|
|
30
|
+
/** AI provider to use for execution */
|
|
31
|
+
provider: Provider;
|
|
32
|
+
/** Whether the reviewer is enabled */
|
|
33
|
+
reviewerEnabled: boolean;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAGhC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IAEf,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IAEnB,iDAAiD;IACjD,kBAAkB,EAAE,MAAM,CAAC;IAE3B,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IAErB,+CAA+C;IAC/C,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;IAEvB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IAInB,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IAErB,oCAAoC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IAIzB,uCAAuC;IACvC,QAAQ,EAAE,QAAQ,CAAC;IAEnB,sCAAsC;IACtC,eAAe,EAAE,OAAO,CAAC;CAC1B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crontab utility functions for Night Watch CLI
|
|
3
|
+
* Provides safe read/write operations for user crontab
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Marker prefix used to identify Night Watch entries
|
|
7
|
+
*/
|
|
8
|
+
export declare const CRONTAB_MARKER_PREFIX = "# night-watch-cli:";
|
|
9
|
+
/**
|
|
10
|
+
* Read current crontab entries
|
|
11
|
+
* Returns empty array if user has no crontab
|
|
12
|
+
*/
|
|
13
|
+
export declare function readCrontab(): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Write crontab entries
|
|
16
|
+
* @param lines - Array of crontab lines to write
|
|
17
|
+
* @throws Error if crontab write fails
|
|
18
|
+
*/
|
|
19
|
+
export declare function writeCrontab(lines: string[]): void;
|
|
20
|
+
/**
|
|
21
|
+
* Generate a marker comment for identifying entries
|
|
22
|
+
* @param projectName - Name of the project
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateMarker(projectName: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Add a crontab entry if it doesn't already exist
|
|
27
|
+
* @param entry - The crontab entry to add
|
|
28
|
+
* @param marker - The marker to use for deduplication
|
|
29
|
+
* @returns true if entry was added, false if it already existed
|
|
30
|
+
*/
|
|
31
|
+
export declare function addEntry(entry: string, marker: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Remove all crontab entries containing the marker
|
|
34
|
+
* @param marker - The marker to search for
|
|
35
|
+
* @returns Number of entries removed
|
|
36
|
+
*/
|
|
37
|
+
export declare function removeEntries(marker: string): number;
|
|
38
|
+
/**
|
|
39
|
+
* Check if an entry with the marker exists
|
|
40
|
+
* @param marker - The marker to search for
|
|
41
|
+
* @returns true if entry exists
|
|
42
|
+
*/
|
|
43
|
+
export declare function hasEntry(marker: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Get all entries containing the marker
|
|
46
|
+
* @param marker - The marker to search for
|
|
47
|
+
* @returns Array of matching entries
|
|
48
|
+
*/
|
|
49
|
+
export declare function getEntries(marker: string): string[];
|
|
50
|
+
//# sourceMappingURL=crontab.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crontab.d.ts","sourceRoot":"","sources":["../../src/utils/crontab.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAYtC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAyBlD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAiB/D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAUpD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGhD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAGnD"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crontab utility functions for Night Watch CLI
|
|
3
|
+
* Provides safe read/write operations for user crontab
|
|
4
|
+
*/
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
/**
|
|
7
|
+
* Marker prefix used to identify Night Watch entries
|
|
8
|
+
*/
|
|
9
|
+
export const CRONTAB_MARKER_PREFIX = "# night-watch-cli:";
|
|
10
|
+
/**
|
|
11
|
+
* Read current crontab entries
|
|
12
|
+
* Returns empty array if user has no crontab
|
|
13
|
+
*/
|
|
14
|
+
export function readCrontab() {
|
|
15
|
+
try {
|
|
16
|
+
const output = execSync("crontab -l 2>/dev/null", {
|
|
17
|
+
encoding: "utf-8",
|
|
18
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
19
|
+
});
|
|
20
|
+
return output.trim().split("\n").filter((line) => line.length > 0);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
// crontab -l returns error if no crontab exists
|
|
24
|
+
// This is expected and should return empty array
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Write crontab entries
|
|
30
|
+
* @param lines - Array of crontab lines to write
|
|
31
|
+
* @throws Error if crontab write fails
|
|
32
|
+
*/
|
|
33
|
+
export function writeCrontab(lines) {
|
|
34
|
+
const content = lines.join("\n");
|
|
35
|
+
// Create a backup first
|
|
36
|
+
try {
|
|
37
|
+
const currentCrontab = readCrontab();
|
|
38
|
+
if (currentCrontab.length > 0) {
|
|
39
|
+
execSync(`crontab -l > /tmp/night-watch-crontab-backup-$(date +%s).txt`, {
|
|
40
|
+
encoding: "utf-8",
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Ignore backup errors
|
|
46
|
+
}
|
|
47
|
+
// Write new crontab using echo and pipe
|
|
48
|
+
try {
|
|
49
|
+
execSync(`echo "${content.replace(/"/g, '\\"')}" | crontab -`, {
|
|
50
|
+
encoding: "utf-8",
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw new Error(`Failed to write crontab: ${error instanceof Error ? error.message : String(error)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Generate a marker comment for identifying entries
|
|
59
|
+
* @param projectName - Name of the project
|
|
60
|
+
*/
|
|
61
|
+
export function generateMarker(projectName) {
|
|
62
|
+
return `${CRONTAB_MARKER_PREFIX} ${projectName}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Add a crontab entry if it doesn't already exist
|
|
66
|
+
* @param entry - The crontab entry to add
|
|
67
|
+
* @param marker - The marker to use for deduplication
|
|
68
|
+
* @returns true if entry was added, false if it already existed
|
|
69
|
+
*/
|
|
70
|
+
export function addEntry(entry, marker) {
|
|
71
|
+
// Check if entry already exists
|
|
72
|
+
if (hasEntry(marker)) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const lines = readCrontab();
|
|
76
|
+
// Add the entry with marker comment on the same line
|
|
77
|
+
const entryWithMarker = entry.endsWith(marker)
|
|
78
|
+
? entry
|
|
79
|
+
: `${entry} ${marker}`;
|
|
80
|
+
lines.push(entryWithMarker);
|
|
81
|
+
writeCrontab(lines);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Remove all crontab entries containing the marker
|
|
86
|
+
* @param marker - The marker to search for
|
|
87
|
+
* @returns Number of entries removed
|
|
88
|
+
*/
|
|
89
|
+
export function removeEntries(marker) {
|
|
90
|
+
const lines = readCrontab();
|
|
91
|
+
const filtered = lines.filter((line) => !line.includes(marker));
|
|
92
|
+
const removedCount = lines.length - filtered.length;
|
|
93
|
+
if (removedCount > 0) {
|
|
94
|
+
writeCrontab(filtered);
|
|
95
|
+
}
|
|
96
|
+
return removedCount;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check if an entry with the marker exists
|
|
100
|
+
* @param marker - The marker to search for
|
|
101
|
+
* @returns true if entry exists
|
|
102
|
+
*/
|
|
103
|
+
export function hasEntry(marker) {
|
|
104
|
+
const lines = readCrontab();
|
|
105
|
+
return lines.some((line) => line.includes(marker));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get all entries containing the marker
|
|
109
|
+
* @param marker - The marker to search for
|
|
110
|
+
* @returns Array of matching entries
|
|
111
|
+
*/
|
|
112
|
+
export function getEntries(marker) {
|
|
113
|
+
const lines = readCrontab();
|
|
114
|
+
return lines.filter((line) => line.includes(marker));
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=crontab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crontab.js","sourceRoot":"","sources":["../../src/utils/crontab.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell execution utility for running bash scripts
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Execute a bash script with arguments and environment variables
|
|
6
|
+
*
|
|
7
|
+
* @param scriptPath - Absolute path to the bash script to execute
|
|
8
|
+
* @param args - Arguments to pass to the script
|
|
9
|
+
* @param env - Environment variables to set for the child process
|
|
10
|
+
* @returns Promise that resolves with the exit code (0 for success)
|
|
11
|
+
*/
|
|
12
|
+
export declare function executeScript(scriptPath: string, args?: string[], env?: Record<string, string>): Promise<number>;
|
|
13
|
+
//# sourceMappingURL=shell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,MAAM,EAAO,EACnB,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAC/B,OAAO,CAAC,MAAM,CAAC,CAmCjB"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell execution utility for running bash scripts
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from "child_process";
|
|
5
|
+
/**
|
|
6
|
+
* Execute a bash script with arguments and environment variables
|
|
7
|
+
*
|
|
8
|
+
* @param scriptPath - Absolute path to the bash script to execute
|
|
9
|
+
* @param args - Arguments to pass to the script
|
|
10
|
+
* @param env - Environment variables to set for the child process
|
|
11
|
+
* @returns Promise that resolves with the exit code (0 for success)
|
|
12
|
+
*/
|
|
13
|
+
export async function executeScript(scriptPath, args = [], env = {}) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
// Merge provided env with process.env, with provided env taking precedence
|
|
16
|
+
const childEnv = {
|
|
17
|
+
...process.env,
|
|
18
|
+
...env,
|
|
19
|
+
};
|
|
20
|
+
const child = spawn("bash", [scriptPath, ...args], {
|
|
21
|
+
env: childEnv,
|
|
22
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
23
|
+
});
|
|
24
|
+
// Stream stdout to console in real-time
|
|
25
|
+
child.stdout?.on("data", (data) => {
|
|
26
|
+
process.stdout.write(data);
|
|
27
|
+
});
|
|
28
|
+
// Stream stderr to console in real-time
|
|
29
|
+
child.stderr?.on("data", (data) => {
|
|
30
|
+
process.stderr.write(data);
|
|
31
|
+
});
|
|
32
|
+
// Handle process errors
|
|
33
|
+
child.on("error", (error) => {
|
|
34
|
+
console.error(`Failed to execute script: ${scriptPath}`);
|
|
35
|
+
console.error(error.message);
|
|
36
|
+
reject(error);
|
|
37
|
+
});
|
|
38
|
+
// Handle process completion
|
|
39
|
+
child.on("close", (code) => {
|
|
40
|
+
resolve(code ?? 1);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,UAAkB,EAClB,OAAiB,EAAE,EACnB,MAA8B,EAAE;IAEhC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,2EAA2E;QAC3E,MAAM,QAAQ,GAAsB;YAClC,GAAG,OAAO,CAAC,GAAG;YACd,GAAG,GAAG;SACP,CAAC;QAEF,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,EAAE;YACjD,GAAG,EAAE,QAAQ;YACb,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC;SACnC,CAAC,CAAC;QAEH,wCAAwC;QACxC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,wCAAwC;QACxC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,wBAAwB;QACxB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;YACjC,OAAO,CAAC,KAAK,CAAC,6BAA6B,UAAU,EAAE,CAAC,CAAC;YACzD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7B,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,4BAA4B;QAC5B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAmB,EAAE,EAAE;YACxC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI utilities for Night Watch CLI
|
|
3
|
+
* Provides colored output, spinners, and table formatting
|
|
4
|
+
*/
|
|
5
|
+
import { type Ora } from "ora";
|
|
6
|
+
import Table from "cli-table3";
|
|
7
|
+
/**
|
|
8
|
+
* Print a success message with green check prefix
|
|
9
|
+
*/
|
|
10
|
+
export declare function success(msg: string): void;
|
|
11
|
+
/**
|
|
12
|
+
* Print an error message with red cross prefix
|
|
13
|
+
*/
|
|
14
|
+
export declare function error(msg: string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Print a warning message with yellow warning prefix
|
|
17
|
+
*/
|
|
18
|
+
export declare function warn(msg: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Print an info message with cyan info prefix
|
|
21
|
+
*/
|
|
22
|
+
export declare function info(msg: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Print a bold section header with underline
|
|
25
|
+
*/
|
|
26
|
+
export declare function header(title: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Print dimmed text for secondary information
|
|
29
|
+
*/
|
|
30
|
+
export declare function dim(msg: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Format and print a key-value pair with consistent alignment
|
|
33
|
+
*/
|
|
34
|
+
export declare function label(key: string, value: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Create an ora spinner instance
|
|
37
|
+
*/
|
|
38
|
+
export declare function createSpinner(text: string): Ora;
|
|
39
|
+
/**
|
|
40
|
+
* Create a configured cli-table3 instance with sensible defaults
|
|
41
|
+
*/
|
|
42
|
+
export declare function createTable(options?: Table.TableConstructorOptions): Table.Table;
|
|
43
|
+
/**
|
|
44
|
+
* Format status indicator: green running or dim not running
|
|
45
|
+
*/
|
|
46
|
+
export declare function formatRunningStatus(running: boolean, pid: number | null): string;
|
|
47
|
+
/**
|
|
48
|
+
* Format installed status: green installed or yellow not installed
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatInstalledStatus(installed: boolean): string;
|
|
51
|
+
/**
|
|
52
|
+
* Print a step message with step number
|
|
53
|
+
*/
|
|
54
|
+
export declare function step(current: number, total: number, msg: string): void;
|
|
55
|
+
//# sourceMappingURL=ui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/utils/ui.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAY,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEzC;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEvC;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK1C;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAErC;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAGtD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAK/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,uBAAuB,GAAG,KAAK,CAAC,KAAK,CA4BhF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAQhF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAKhE;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtE"}
|