@jonit-dev/night-watch-cli 1.7.87 → 1.7.89
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/dist/cli.js +278 -37
- package/dist/commands/dashboard/tab-config.d.ts.map +1 -1
- package/dist/commands/dashboard/tab-config.js +12 -15
- package/dist/commands/dashboard/tab-config.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +3 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +42 -1
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/shared/env-builder.d.ts +11 -1
- package/dist/commands/shared/env-builder.d.ts.map +1 -1
- package/dist/commands/shared/env-builder.js +40 -8
- package/dist/commands/shared/env-builder.js.map +1 -1
- package/dist/scripts/night-watch-audit-cron.sh +9 -33
- package/dist/scripts/night-watch-cron.sh +110 -60
- package/dist/scripts/night-watch-helpers.sh +76 -12
- package/dist/scripts/night-watch-pr-reviewer-cron.sh +9 -32
- package/dist/scripts/night-watch-qa-cron.sh +23 -58
- package/dist/web/assets/index-BsC7RT48.css +1 -0
- package/dist/web/assets/index-C7lMNxRE.js +370 -0
- package/dist/web/assets/index-Sv2B60J4.js +370 -0
- package/dist/web/assets/index-mz1VIYsP.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -31,7 +31,7 @@ function resolveProviderBucketKey(provider, providerEnv) {
|
|
|
31
31
|
return `claude-proxy:${baseUrl}`;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
var DEFAULT_DEFAULT_BRANCH, DEFAULT_PRD_DIR, DEFAULT_MAX_RUNTIME, DEFAULT_REVIEWER_MAX_RUNTIME, DEFAULT_CRON_SCHEDULE, DEFAULT_REVIEWER_SCHEDULE, DEFAULT_CRON_SCHEDULE_OFFSET, DEFAULT_MAX_RETRIES, DEFAULT_REVIEWER_MAX_RETRIES, DEFAULT_REVIEWER_RETRY_DELAY, DEFAULT_BRANCH_PREFIX, DEFAULT_BRANCH_PATTERNS, DEFAULT_MIN_REVIEW_SCORE, DEFAULT_MAX_LOG_SIZE, DEFAULT_PROVIDER, DEFAULT_EXECUTOR_ENABLED, DEFAULT_REVIEWER_ENABLED, DEFAULT_PROVIDER_ENV, DEFAULT_FALLBACK_ON_RATE_LIMIT, DEFAULT_CLAUDE_MODEL, DEFAULT_PRIMARY_FALLBACK_MODEL, DEFAULT_SECONDARY_FALLBACK_MODEL, VALID_CLAUDE_MODELS, CLAUDE_MODEL_IDS, DEFAULT_NOTIFICATIONS, DEFAULT_PRD_PRIORITY, DEFAULT_SLICER_SCHEDULE, DEFAULT_SLICER_MAX_RUNTIME, DEFAULT_ROADMAP_SCANNER, DEFAULT_TEMPLATES_DIR, DEFAULT_BOARD_PROVIDER, DEFAULT_LOCAL_BOARD_INFO, DEFAULT_AUTO_MERGE, DEFAULT_AUTO_MERGE_METHOD, VALID_MERGE_METHODS, DEFAULT_QA_ENABLED, DEFAULT_QA_SCHEDULE, DEFAULT_QA_MAX_RUNTIME, DEFAULT_QA_ARTIFACTS, DEFAULT_QA_SKIP_LABEL, DEFAULT_QA_AUTO_INSTALL_PLAYWRIGHT, DEFAULT_QA, QA_LOG_NAME, DEFAULT_AUDIT_ENABLED, DEFAULT_AUDIT_SCHEDULE, DEFAULT_AUDIT_MAX_RUNTIME, DEFAULT_AUDIT, AUDIT_LOG_NAME, PLANNER_LOG_NAME, VALID_PROVIDERS, VALID_JOB_TYPES, DEFAULT_JOB_PROVIDERS, PROVIDER_COMMANDS, CONFIG_FILE_NAME, LOCK_FILE_PREFIX, LOG_DIR, CLAIM_FILE_EXTENSION, EXECUTOR_LOG_NAME, REVIEWER_LOG_NAME, EXECUTOR_LOG_FILE, REVIEWER_LOG_FILE, LOG_FILE_NAMES, GLOBAL_CONFIG_DIR, REGISTRY_FILE_NAME, HISTORY_FILE_NAME, PRD_STATES_FILE_NAME, STATE_DB_FILE_NAME, MAX_HISTORY_RECORDS_PER_PRD, DEFAULT_QUEUE_ENABLED, DEFAULT_QUEUE_MODE, DEFAULT_QUEUE_MAX_CONCURRENCY, DEFAULT_QUEUE_MAX_WAIT_TIME, DEFAULT_QUEUE_PRIORITY, DEFAULT_QUEUE, DEFAULT_SCHEDULING_PRIORITY, QUEUE_LOCK_FILE_NAME;
|
|
34
|
+
var DEFAULT_DEFAULT_BRANCH, DEFAULT_PRD_DIR, DEFAULT_MAX_RUNTIME, DEFAULT_REVIEWER_MAX_RUNTIME, DEFAULT_CRON_SCHEDULE, DEFAULT_REVIEWER_SCHEDULE, DEFAULT_CRON_SCHEDULE_OFFSET, DEFAULT_MAX_RETRIES, DEFAULT_REVIEWER_MAX_RETRIES, DEFAULT_REVIEWER_RETRY_DELAY, DEFAULT_BRANCH_PREFIX, DEFAULT_BRANCH_PATTERNS, DEFAULT_MIN_REVIEW_SCORE, DEFAULT_MAX_LOG_SIZE, DEFAULT_PROVIDER, DEFAULT_EXECUTOR_ENABLED, DEFAULT_REVIEWER_ENABLED, DEFAULT_PROVIDER_ENV, DEFAULT_FALLBACK_ON_RATE_LIMIT, DEFAULT_CLAUDE_MODEL, DEFAULT_PRIMARY_FALLBACK_MODEL, DEFAULT_SECONDARY_FALLBACK_MODEL, VALID_CLAUDE_MODELS, CLAUDE_MODEL_IDS, DEFAULT_NOTIFICATIONS, DEFAULT_PRD_PRIORITY, DEFAULT_SLICER_SCHEDULE, DEFAULT_SLICER_MAX_RUNTIME, DEFAULT_ROADMAP_SCANNER, DEFAULT_TEMPLATES_DIR, DEFAULT_BOARD_PROVIDER, DEFAULT_LOCAL_BOARD_INFO, DEFAULT_AUTO_MERGE, DEFAULT_AUTO_MERGE_METHOD, VALID_MERGE_METHODS, DEFAULT_QA_ENABLED, DEFAULT_QA_SCHEDULE, DEFAULT_QA_MAX_RUNTIME, DEFAULT_QA_ARTIFACTS, DEFAULT_QA_SKIP_LABEL, DEFAULT_QA_AUTO_INSTALL_PLAYWRIGHT, DEFAULT_QA, QA_LOG_NAME, DEFAULT_AUDIT_ENABLED, DEFAULT_AUDIT_SCHEDULE, DEFAULT_AUDIT_MAX_RUNTIME, DEFAULT_AUDIT, AUDIT_LOG_NAME, PLANNER_LOG_NAME, VALID_PROVIDERS, VALID_JOB_TYPES, DEFAULT_JOB_PROVIDERS, BUILT_IN_PRESETS, BUILT_IN_PRESET_IDS, PROVIDER_COMMANDS, CONFIG_FILE_NAME, LOCK_FILE_PREFIX, LOG_DIR, CLAIM_FILE_EXTENSION, EXECUTOR_LOG_NAME, REVIEWER_LOG_NAME, EXECUTOR_LOG_FILE, REVIEWER_LOG_FILE, LOG_FILE_NAMES, GLOBAL_CONFIG_DIR, REGISTRY_FILE_NAME, HISTORY_FILE_NAME, PRD_STATES_FILE_NAME, STATE_DB_FILE_NAME, MAX_HISTORY_RECORDS_PER_PRD, DEFAULT_QUEUE_ENABLED, DEFAULT_QUEUE_MODE, DEFAULT_QUEUE_MAX_CONCURRENCY, DEFAULT_QUEUE_MAX_WAIT_TIME, DEFAULT_QUEUE_PRIORITY, DEFAULT_QUEUE, DEFAULT_SCHEDULING_PRIORITY, QUEUE_LOCK_FILE_NAME;
|
|
35
35
|
var init_constants = __esm({
|
|
36
36
|
"../core/dist/constants.js"() {
|
|
37
37
|
"use strict";
|
|
@@ -113,9 +113,69 @@ var init_constants = __esm({
|
|
|
113
113
|
VALID_PROVIDERS = ["claude", "codex"];
|
|
114
114
|
VALID_JOB_TYPES = ["executor", "reviewer", "qa", "audit", "slicer"];
|
|
115
115
|
DEFAULT_JOB_PROVIDERS = {};
|
|
116
|
+
BUILT_IN_PRESETS = {
|
|
117
|
+
claude: {
|
|
118
|
+
name: "Claude",
|
|
119
|
+
command: "claude",
|
|
120
|
+
promptFlag: "-p",
|
|
121
|
+
autoApproveFlag: "--dangerously-skip-permissions"
|
|
122
|
+
},
|
|
123
|
+
"claude-sonnet-4-6": {
|
|
124
|
+
name: "Claude Sonnet 4.6",
|
|
125
|
+
command: "claude",
|
|
126
|
+
promptFlag: "-p",
|
|
127
|
+
autoApproveFlag: "--dangerously-skip-permissions",
|
|
128
|
+
modelFlag: "--model",
|
|
129
|
+
model: "claude-sonnet-4-6"
|
|
130
|
+
},
|
|
131
|
+
"claude-opus-4-6": {
|
|
132
|
+
name: "Claude Opus 4.6",
|
|
133
|
+
command: "claude",
|
|
134
|
+
promptFlag: "-p",
|
|
135
|
+
autoApproveFlag: "--dangerously-skip-permissions",
|
|
136
|
+
modelFlag: "--model",
|
|
137
|
+
model: "claude-opus-4-6"
|
|
138
|
+
},
|
|
139
|
+
codex: {
|
|
140
|
+
name: "Codex",
|
|
141
|
+
command: "codex",
|
|
142
|
+
subcommand: "exec",
|
|
143
|
+
autoApproveFlag: "--yolo",
|
|
144
|
+
workdirFlag: "-C"
|
|
145
|
+
},
|
|
146
|
+
"glm-47": {
|
|
147
|
+
name: "GLM-4.7",
|
|
148
|
+
command: "claude",
|
|
149
|
+
promptFlag: "-p",
|
|
150
|
+
autoApproveFlag: "--dangerously-skip-permissions",
|
|
151
|
+
modelFlag: "--model",
|
|
152
|
+
model: "glm-4.7",
|
|
153
|
+
envVars: {
|
|
154
|
+
ANTHROPIC_BASE_URL: "https://api.z.ai/api/anthropic",
|
|
155
|
+
API_TIMEOUT_MS: "3000000",
|
|
156
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-4.7",
|
|
157
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: "glm-4.7"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"glm-5": {
|
|
161
|
+
name: "GLM-5",
|
|
162
|
+
command: "claude",
|
|
163
|
+
promptFlag: "-p",
|
|
164
|
+
autoApproveFlag: "--dangerously-skip-permissions",
|
|
165
|
+
modelFlag: "--model",
|
|
166
|
+
model: "glm-5",
|
|
167
|
+
envVars: {
|
|
168
|
+
ANTHROPIC_BASE_URL: "https://api.z.ai/api/anthropic",
|
|
169
|
+
API_TIMEOUT_MS: "3000000",
|
|
170
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-5",
|
|
171
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: "glm-5"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
BUILT_IN_PRESET_IDS = Object.keys(BUILT_IN_PRESETS);
|
|
116
176
|
PROVIDER_COMMANDS = {
|
|
117
|
-
claude:
|
|
118
|
-
codex:
|
|
177
|
+
claude: BUILT_IN_PRESETS.claude.command,
|
|
178
|
+
codex: BUILT_IN_PRESETS.codex.command
|
|
119
179
|
};
|
|
120
180
|
CONFIG_FILE_NAME = "night-watch.config.json";
|
|
121
181
|
LOCK_FILE_PREFIX = "/tmp/night-watch-";
|
|
@@ -164,8 +224,9 @@ var init_constants = __esm({
|
|
|
164
224
|
|
|
165
225
|
// ../core/dist/config-normalize.js
|
|
166
226
|
function validateProvider(value) {
|
|
167
|
-
|
|
168
|
-
|
|
227
|
+
const trimmed = value.trim();
|
|
228
|
+
if (trimmed.length > 0) {
|
|
229
|
+
return trimmed;
|
|
169
230
|
}
|
|
170
231
|
return null;
|
|
171
232
|
}
|
|
@@ -221,6 +282,45 @@ function normalizeConfig(rawConfig) {
|
|
|
221
282
|
normalized.providerEnv = env;
|
|
222
283
|
}
|
|
223
284
|
}
|
|
285
|
+
const rawProviderPresets = readObject(rawConfig.providerPresets);
|
|
286
|
+
if (rawProviderPresets) {
|
|
287
|
+
const presets = {};
|
|
288
|
+
for (const [presetId, presetVal] of Object.entries(rawProviderPresets)) {
|
|
289
|
+
const rawPreset = readObject(presetVal);
|
|
290
|
+
if (rawPreset) {
|
|
291
|
+
const name = readString(rawPreset.name);
|
|
292
|
+
const command = readString(rawPreset.command);
|
|
293
|
+
if (name && command) {
|
|
294
|
+
const preset = {
|
|
295
|
+
name,
|
|
296
|
+
command,
|
|
297
|
+
subcommand: readString(rawPreset.subcommand),
|
|
298
|
+
promptFlag: readString(rawPreset.promptFlag),
|
|
299
|
+
autoApproveFlag: readString(rawPreset.autoApproveFlag),
|
|
300
|
+
workdirFlag: readString(rawPreset.workdirFlag),
|
|
301
|
+
modelFlag: readString(rawPreset.modelFlag),
|
|
302
|
+
model: readString(rawPreset.model)
|
|
303
|
+
};
|
|
304
|
+
const rawEnvVars = readObject(rawPreset.envVars);
|
|
305
|
+
if (rawEnvVars) {
|
|
306
|
+
const envVars = {};
|
|
307
|
+
for (const [envKey, envVal] of Object.entries(rawEnvVars)) {
|
|
308
|
+
if (typeof envVal === "string") {
|
|
309
|
+
envVars[envKey] = envVal;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (Object.keys(envVars).length > 0) {
|
|
313
|
+
preset.envVars = envVars;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
presets[presetId] = preset;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (Object.keys(presets).length > 0) {
|
|
321
|
+
normalized.providerPresets = presets;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
224
324
|
const rawNotifications = readObject(rawConfig.notifications);
|
|
225
325
|
if (rawNotifications) {
|
|
226
326
|
const rawWebhooks = Array.isArray(rawNotifications.webhooks) ? rawNotifications.webhooks : [];
|
|
@@ -285,6 +385,8 @@ function normalizeConfig(rawConfig) {
|
|
|
285
385
|
if (secondaryFallbackModelRaw && VALID_CLAUDE_MODELS.includes(secondaryFallbackModelRaw)) {
|
|
286
386
|
normalized.secondaryFallbackModel = secondaryFallbackModelRaw;
|
|
287
387
|
}
|
|
388
|
+
normalized.primaryFallbackPreset = readString(rawConfig.primaryFallbackPreset);
|
|
389
|
+
normalized.secondaryFallbackPreset = readString(rawConfig.secondaryFallbackPreset);
|
|
288
390
|
normalized.autoMerge = readBoolean(rawConfig.autoMerge);
|
|
289
391
|
const mergeMethod = readString(rawConfig.autoMergeMethod);
|
|
290
392
|
if (mergeMethod && VALID_MERGE_METHODS.includes(mergeMethod)) {
|
|
@@ -319,8 +421,8 @@ function normalizeConfig(rawConfig) {
|
|
|
319
421
|
const jobProviders = {};
|
|
320
422
|
for (const jobType of VALID_JOB_TYPES) {
|
|
321
423
|
const providerValue = readString(rawJobProviders[jobType]);
|
|
322
|
-
if (providerValue &&
|
|
323
|
-
jobProviders[jobType] = providerValue;
|
|
424
|
+
if (providerValue && providerValue.trim().length > 0) {
|
|
425
|
+
jobProviders[jobType] = providerValue.trim();
|
|
324
426
|
}
|
|
325
427
|
}
|
|
326
428
|
if (Object.keys(jobProviders).length > 0) {
|
|
@@ -779,6 +881,15 @@ function resolveJobProvider(config, jobType) {
|
|
|
779
881
|
return config.jobProviders[jobType];
|
|
780
882
|
return config.provider;
|
|
781
883
|
}
|
|
884
|
+
function resolvePreset(config, presetId) {
|
|
885
|
+
if (config.providerPresets?.[presetId]) {
|
|
886
|
+
return config.providerPresets[presetId];
|
|
887
|
+
}
|
|
888
|
+
if (BUILT_IN_PRESETS[presetId]) {
|
|
889
|
+
return BUILT_IN_PRESETS[presetId];
|
|
890
|
+
}
|
|
891
|
+
throw new Error(`Unknown provider preset: "${presetId}"`);
|
|
892
|
+
}
|
|
782
893
|
function getScriptPath(scriptName) {
|
|
783
894
|
const configFilePath = fileURLToPath(import.meta.url);
|
|
784
895
|
const baseDir = path.dirname(configFilePath);
|
|
@@ -3976,7 +4087,7 @@ var init_config_writer = __esm({
|
|
|
3976
4087
|
"../core/dist/utils/config-writer.js"() {
|
|
3977
4088
|
"use strict";
|
|
3978
4089
|
init_constants();
|
|
3979
|
-
PARTIAL_MERGE_KEYS = /* @__PURE__ */ new Set(["notifications", "qa", "audit", "roadmapScanner", "queue"]);
|
|
4090
|
+
PARTIAL_MERGE_KEYS = /* @__PURE__ */ new Set(["notifications", "qa", "audit", "roadmapScanner", "queue", "providerPresets", "jobProviders"]);
|
|
3980
4091
|
}
|
|
3981
4092
|
});
|
|
3982
4093
|
|
|
@@ -6741,6 +6852,8 @@ var dist_exports = {};
|
|
|
6741
6852
|
__export(dist_exports, {
|
|
6742
6853
|
AUDIT_LOG_NAME: () => AUDIT_LOG_NAME,
|
|
6743
6854
|
BOARD_COLUMNS: () => BOARD_COLUMNS,
|
|
6855
|
+
BUILT_IN_PRESETS: () => BUILT_IN_PRESETS,
|
|
6856
|
+
BUILT_IN_PRESET_IDS: () => BUILT_IN_PRESET_IDS,
|
|
6744
6857
|
CATEGORY_LABELS: () => CATEGORY_LABELS,
|
|
6745
6858
|
CATEGORY_LABEL_INFO: () => CATEGORY_LABEL_INFO,
|
|
6746
6859
|
CLAIM_FILE_EXTENSION: () => CLAIM_FILE_EXTENSION,
|
|
@@ -6985,6 +7098,7 @@ __export(dist_exports, {
|
|
|
6985
7098
|
renderSlicerPrompt: () => renderSlicerPrompt,
|
|
6986
7099
|
resetRepositories: () => resetRepositories,
|
|
6987
7100
|
resolveJobProvider: () => resolveJobProvider,
|
|
7101
|
+
resolvePreset: () => resolvePreset,
|
|
6988
7102
|
resolveProviderBucketKey: () => resolveProviderBucketKey,
|
|
6989
7103
|
resolveWorktreeBaseRef: () => resolveWorktreeBaseRef,
|
|
6990
7104
|
reviewerLockPath: () => reviewerLockPath,
|
|
@@ -7385,9 +7499,9 @@ function initCommand(program2) {
|
|
|
7385
7499
|
step(3, totalSteps, "Detecting AI providers...");
|
|
7386
7500
|
let selectedProvider;
|
|
7387
7501
|
if (options.provider) {
|
|
7388
|
-
if (!
|
|
7502
|
+
if (!BUILT_IN_PRESET_IDS.includes(options.provider)) {
|
|
7389
7503
|
error(`Invalid provider "${options.provider}".`);
|
|
7390
|
-
console.log(`Valid providers: ${
|
|
7504
|
+
console.log(`Valid providers: ${BUILT_IN_PRESET_IDS.join(", ")}`);
|
|
7391
7505
|
process.exit(1);
|
|
7392
7506
|
}
|
|
7393
7507
|
selectedProvider = options.provider;
|
|
@@ -7615,23 +7729,34 @@ init_dist();
|
|
|
7615
7729
|
|
|
7616
7730
|
// src/commands/shared/env-builder.ts
|
|
7617
7731
|
init_dist();
|
|
7618
|
-
function deriveProviderLabel(config,
|
|
7732
|
+
function deriveProviderLabel(config, preset) {
|
|
7733
|
+
if (preset.name) return preset.name;
|
|
7619
7734
|
if (config.providerLabel) return config.providerLabel;
|
|
7620
|
-
|
|
7621
|
-
if (provider === "codex") return "Codex";
|
|
7735
|
+
if (preset.command === "codex") return "Codex";
|
|
7622
7736
|
if (config.providerEnv?.ANTHROPIC_BASE_URL) return "Claude (proxy)";
|
|
7623
7737
|
return "Claude";
|
|
7624
7738
|
}
|
|
7625
7739
|
function buildBaseEnvVars(config, jobType, isDryRun) {
|
|
7626
7740
|
const env = {};
|
|
7627
|
-
|
|
7628
|
-
|
|
7741
|
+
const presetId = resolveJobProvider(config, jobType);
|
|
7742
|
+
const preset = resolvePreset(config, presetId);
|
|
7743
|
+
env.NW_PROVIDER_CMD = preset.command;
|
|
7744
|
+
env.NW_PROVIDER_SUBCOMMAND = preset.subcommand ?? "";
|
|
7745
|
+
env.NW_PROVIDER_PROMPT_FLAG = preset.promptFlag ?? "";
|
|
7746
|
+
env.NW_PROVIDER_APPROVE_FLAG = preset.autoApproveFlag ?? "";
|
|
7747
|
+
env.NW_PROVIDER_WORKDIR_FLAG = preset.workdirFlag ?? "";
|
|
7748
|
+
env.NW_PROVIDER_MODEL_FLAG = preset.modelFlag ?? "";
|
|
7749
|
+
env.NW_PROVIDER_MODEL = preset.model ?? "";
|
|
7750
|
+
env.NW_PROVIDER_LABEL = deriveProviderLabel(config, preset);
|
|
7629
7751
|
if (config.defaultBranch) {
|
|
7630
7752
|
env.NW_DEFAULT_BRANCH = config.defaultBranch;
|
|
7631
7753
|
}
|
|
7632
7754
|
if (config.providerEnv) {
|
|
7633
7755
|
Object.assign(env, config.providerEnv);
|
|
7634
7756
|
}
|
|
7757
|
+
if (preset.envVars) {
|
|
7758
|
+
Object.assign(env, preset.envVars);
|
|
7759
|
+
}
|
|
7635
7760
|
const queueConfig = config.queue ?? DEFAULT_QUEUE;
|
|
7636
7761
|
env.NW_QUEUE_ENABLED = queueConfig.enabled ? "1" : "0";
|
|
7637
7762
|
env.NW_QUEUE_MAX_CONCURRENCY = String(queueConfig.maxConcurrency);
|
|
@@ -7852,6 +7977,34 @@ function buildEnvVars(config, options) {
|
|
|
7852
7977
|
env.NW_CLAUDE_PRIMARY_MODEL_ID = CLAUDE_MODEL_IDS[primaryFallbackModel];
|
|
7853
7978
|
env.NW_CLAUDE_SECONDARY_MODEL_ID = CLAUDE_MODEL_IDS[secondaryFallbackModel];
|
|
7854
7979
|
env.NW_CLAUDE_MODEL_ID = env.NW_CLAUDE_PRIMARY_MODEL_ID;
|
|
7980
|
+
if (config.primaryFallbackPreset) {
|
|
7981
|
+
try {
|
|
7982
|
+
const fallbackPreset = resolvePreset(config, config.primaryFallbackPreset);
|
|
7983
|
+
env.NW_FALLBACK_PRIMARY_PRESET_CMD = fallbackPreset.command;
|
|
7984
|
+
if (fallbackPreset.promptFlag) env.NW_FALLBACK_PRIMARY_PRESET_PROMPT_FLAG = fallbackPreset.promptFlag;
|
|
7985
|
+
if (fallbackPreset.autoApproveFlag) env.NW_FALLBACK_PRIMARY_PRESET_AUTO_APPROVE_FLAG = fallbackPreset.autoApproveFlag;
|
|
7986
|
+
if (fallbackPreset.modelFlag) env.NW_FALLBACK_PRIMARY_PRESET_MODEL_FLAG = fallbackPreset.modelFlag;
|
|
7987
|
+
if (fallbackPreset.model) env.NW_FALLBACK_PRIMARY_PRESET_MODEL = fallbackPreset.model;
|
|
7988
|
+
if (fallbackPreset.envVars && Object.keys(fallbackPreset.envVars).length > 0) {
|
|
7989
|
+
env.NW_FALLBACK_PRIMARY_PRESET_ENV = JSON.stringify(fallbackPreset.envVars);
|
|
7990
|
+
}
|
|
7991
|
+
} catch {
|
|
7992
|
+
}
|
|
7993
|
+
}
|
|
7994
|
+
if (config.secondaryFallbackPreset) {
|
|
7995
|
+
try {
|
|
7996
|
+
const fallbackPreset = resolvePreset(config, config.secondaryFallbackPreset);
|
|
7997
|
+
env.NW_FALLBACK_SECONDARY_PRESET_CMD = fallbackPreset.command;
|
|
7998
|
+
if (fallbackPreset.promptFlag) env.NW_FALLBACK_SECONDARY_PRESET_PROMPT_FLAG = fallbackPreset.promptFlag;
|
|
7999
|
+
if (fallbackPreset.autoApproveFlag) env.NW_FALLBACK_SECONDARY_PRESET_AUTO_APPROVE_FLAG = fallbackPreset.autoApproveFlag;
|
|
8000
|
+
if (fallbackPreset.modelFlag) env.NW_FALLBACK_SECONDARY_PRESET_MODEL_FLAG = fallbackPreset.modelFlag;
|
|
8001
|
+
if (fallbackPreset.model) env.NW_FALLBACK_SECONDARY_PRESET_MODEL = fallbackPreset.model;
|
|
8002
|
+
if (fallbackPreset.envVars && Object.keys(fallbackPreset.envVars).length > 0) {
|
|
8003
|
+
env.NW_FALLBACK_SECONDARY_PRESET_ENV = JSON.stringify(fallbackPreset.envVars);
|
|
8004
|
+
}
|
|
8005
|
+
} catch {
|
|
8006
|
+
}
|
|
8007
|
+
}
|
|
7855
8008
|
const fallbackTelegramWebhooks = getRateLimitFallbackTelegramWebhooks(config);
|
|
7856
8009
|
if (fallbackTelegramWebhooks.length > 0) {
|
|
7857
8010
|
env.NW_TELEGRAM_RATE_LIMIT_WEBHOOKS = JSON.stringify(fallbackTelegramWebhooks);
|
|
@@ -9899,14 +10052,8 @@ var NOTIFICATION_EVENTS = [
|
|
|
9899
10052
|
"rate_limit_fallback",
|
|
9900
10053
|
"qa_completed"
|
|
9901
10054
|
];
|
|
9902
|
-
var GLM5_DEFAULTS = {
|
|
9903
|
-
ANTHROPIC_BASE_URL: "https://api.z.ai/api/anthropic",
|
|
9904
|
-
API_TIMEOUT_MS: "3000000",
|
|
9905
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-5",
|
|
9906
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL: "glm-5"
|
|
9907
|
-
};
|
|
9908
10055
|
var CONFIG_FIELDS = [
|
|
9909
|
-
{ key: "provider", label: "Provider", type: "enum", options: [...
|
|
10056
|
+
{ key: "provider", label: "Provider", type: "enum", options: [...BUILT_IN_PRESET_IDS] },
|
|
9910
10057
|
{ key: "reviewerEnabled", label: "Reviewer Enabled", type: "boolean" },
|
|
9911
10058
|
{ key: "defaultBranch", label: "Default Branch", type: "string" },
|
|
9912
10059
|
{ key: "prdDir", label: "PRD Directory", type: "string" },
|
|
@@ -10437,10 +10584,16 @@ function createConfigTab() {
|
|
|
10437
10584
|
ctx.screen.render();
|
|
10438
10585
|
return;
|
|
10439
10586
|
}
|
|
10440
|
-
pendingChanges.
|
|
10441
|
-
|
|
10442
|
-
|
|
10443
|
-
|
|
10587
|
+
pendingChanges.provider = "glm-5";
|
|
10588
|
+
pendingChanges.providerPresets = {
|
|
10589
|
+
"glm-5": {
|
|
10590
|
+
...BUILT_IN_PRESETS["glm-5"],
|
|
10591
|
+
envVars: {
|
|
10592
|
+
...BUILT_IN_PRESETS["glm-5"].envVars,
|
|
10593
|
+
ANTHROPIC_API_KEY: apiKey,
|
|
10594
|
+
ANTHROPIC_AUTH_TOKEN: apiKey
|
|
10595
|
+
}
|
|
10596
|
+
}
|
|
10444
10597
|
};
|
|
10445
10598
|
ctx.showMessage("GLM-5 configured. Press s to save.", "success");
|
|
10446
10599
|
if (currentConfig) refreshList(currentConfig);
|
|
@@ -12437,14 +12590,13 @@ function validateCronField(fieldName, value) {
|
|
|
12437
12590
|
}
|
|
12438
12591
|
return null;
|
|
12439
12592
|
}
|
|
12440
|
-
function validateConfigChanges(changes) {
|
|
12593
|
+
function validateConfigChanges(changes, currentConfig) {
|
|
12441
12594
|
if (typeof changes !== "object" || changes === null) {
|
|
12442
12595
|
return "Invalid request body";
|
|
12443
12596
|
}
|
|
12444
12597
|
if (changes.provider !== void 0) {
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
return `Invalid provider. Must be one of: ${validProviders.join(", ")}`;
|
|
12598
|
+
if (typeof changes.provider !== "string" || changes.provider.trim().length === 0) {
|
|
12599
|
+
return "provider must be a non-empty string (preset ID)";
|
|
12448
12600
|
}
|
|
12449
12601
|
}
|
|
12450
12602
|
if (changes.providerLabel !== void 0 && typeof changes.providerLabel !== "string") {
|
|
@@ -12571,8 +12723,41 @@ function validateConfigChanges(changes) {
|
|
|
12571
12723
|
if (!VALID_JOB_TYPES.includes(jobType)) {
|
|
12572
12724
|
return `Invalid job type in jobProviders: ${jobType}. Must be one of: ${VALID_JOB_TYPES.join(", ")}`;
|
|
12573
12725
|
}
|
|
12574
|
-
if (provider !== null && provider !== void 0 &&
|
|
12575
|
-
return `Invalid provider in jobProviders.${jobType}: ${provider}. Must be
|
|
12726
|
+
if (provider !== null && provider !== void 0 && (typeof provider !== "string" || provider.trim().length === 0)) {
|
|
12727
|
+
return `Invalid provider in jobProviders.${jobType}: ${provider}. Must be a non-empty string (preset ID)`;
|
|
12728
|
+
}
|
|
12729
|
+
}
|
|
12730
|
+
}
|
|
12731
|
+
if (changes.providerPresets !== void 0) {
|
|
12732
|
+
if (typeof changes.providerPresets !== "object" || changes.providerPresets === null) {
|
|
12733
|
+
return "providerPresets must be an object";
|
|
12734
|
+
}
|
|
12735
|
+
for (const [presetId, presetVal] of Object.entries(changes.providerPresets)) {
|
|
12736
|
+
if (typeof presetId !== "string" || presetId.trim().length === 0) {
|
|
12737
|
+
return "providerPresets keys must be non-empty strings";
|
|
12738
|
+
}
|
|
12739
|
+
if (presetVal === null || presetVal === void 0) {
|
|
12740
|
+
continue;
|
|
12741
|
+
}
|
|
12742
|
+
if (typeof presetVal !== "object") {
|
|
12743
|
+
return `providerPresets.${presetId} must be an object`;
|
|
12744
|
+
}
|
|
12745
|
+
const preset = presetVal;
|
|
12746
|
+
if (typeof preset.name !== "string" || preset.name.trim().length === 0) {
|
|
12747
|
+
return `providerPresets.${presetId}.name must be a non-empty string`;
|
|
12748
|
+
}
|
|
12749
|
+
if (typeof preset.command !== "string" || preset.command.trim().length === 0) {
|
|
12750
|
+
return `providerPresets.${presetId}.command must be a non-empty string`;
|
|
12751
|
+
}
|
|
12752
|
+
if (preset.envVars !== void 0) {
|
|
12753
|
+
if (typeof preset.envVars !== "object" || preset.envVars === null) {
|
|
12754
|
+
return `providerPresets.${presetId}.envVars must be an object`;
|
|
12755
|
+
}
|
|
12756
|
+
for (const [envKey, envVal] of Object.entries(preset.envVars)) {
|
|
12757
|
+
if (typeof envVal !== "string") {
|
|
12758
|
+
return `providerPresets.${presetId}.envVars.${envKey} must be a string`;
|
|
12759
|
+
}
|
|
12760
|
+
}
|
|
12576
12761
|
}
|
|
12577
12762
|
}
|
|
12578
12763
|
}
|
|
@@ -12591,6 +12776,16 @@ function validateConfigChanges(changes) {
|
|
|
12591
12776
|
if (changes.fallbackOnRateLimit !== void 0 && typeof changes.fallbackOnRateLimit !== "boolean") {
|
|
12592
12777
|
return "fallbackOnRateLimit must be a boolean";
|
|
12593
12778
|
}
|
|
12779
|
+
if (changes.primaryFallbackPreset !== void 0 && changes.primaryFallbackPreset !== null) {
|
|
12780
|
+
if (typeof changes.primaryFallbackPreset !== "string" || changes.primaryFallbackPreset.trim().length === 0) {
|
|
12781
|
+
return "primaryFallbackPreset must be a non-empty string (preset ID)";
|
|
12782
|
+
}
|
|
12783
|
+
}
|
|
12784
|
+
if (changes.secondaryFallbackPreset !== void 0 && changes.secondaryFallbackPreset !== null) {
|
|
12785
|
+
if (typeof changes.secondaryFallbackPreset !== "string" || changes.secondaryFallbackPreset.trim().length === 0) {
|
|
12786
|
+
return "secondaryFallbackPreset must be a non-empty string (preset ID)";
|
|
12787
|
+
}
|
|
12788
|
+
}
|
|
12594
12789
|
if (changes.claudeModel !== void 0 && !VALID_CLAUDE_MODELS.includes(changes.claudeModel)) {
|
|
12595
12790
|
return `Invalid claudeModel. Must be one of: ${VALID_CLAUDE_MODELS.join(", ")}`;
|
|
12596
12791
|
}
|
|
@@ -12695,6 +12890,47 @@ function validateConfigChanges(changes) {
|
|
|
12695
12890
|
return "boardProvider.enabled must be a boolean";
|
|
12696
12891
|
}
|
|
12697
12892
|
}
|
|
12893
|
+
if (changes.providerPresets !== void 0 && currentConfig) {
|
|
12894
|
+
const currentPresetIds = new Set(Object.keys(currentConfig.providerPresets || {}));
|
|
12895
|
+
const newPresetIds = /* @__PURE__ */ new Set();
|
|
12896
|
+
for (const [presetId, presetVal] of Object.entries(changes.providerPresets)) {
|
|
12897
|
+
if (presetVal !== null && presetVal !== void 0) {
|
|
12898
|
+
newPresetIds.add(presetId);
|
|
12899
|
+
}
|
|
12900
|
+
}
|
|
12901
|
+
for (const presetId of currentPresetIds) {
|
|
12902
|
+
if (!(presetId in changes.providerPresets)) {
|
|
12903
|
+
newPresetIds.add(presetId);
|
|
12904
|
+
}
|
|
12905
|
+
}
|
|
12906
|
+
const deletedPresetIds = [...currentPresetIds].filter((id) => !newPresetIds.has(id));
|
|
12907
|
+
if (deletedPresetIds.length > 0) {
|
|
12908
|
+
const presetReferences = [];
|
|
12909
|
+
for (const deletedId of deletedPresetIds) {
|
|
12910
|
+
const references = [];
|
|
12911
|
+
const effectiveProvider = changes.provider ?? currentConfig.provider;
|
|
12912
|
+
if (effectiveProvider === deletedId) {
|
|
12913
|
+
references.push("provider (global)");
|
|
12914
|
+
}
|
|
12915
|
+
const effectiveJobProviders = {
|
|
12916
|
+
...currentConfig.jobProviders,
|
|
12917
|
+
...changes.jobProviders || {}
|
|
12918
|
+
};
|
|
12919
|
+
for (const [jobType, provider] of Object.entries(effectiveJobProviders)) {
|
|
12920
|
+
if (provider === deletedId) {
|
|
12921
|
+
references.push(`jobProviders.${jobType}`);
|
|
12922
|
+
}
|
|
12923
|
+
}
|
|
12924
|
+
if (references.length > 0) {
|
|
12925
|
+
presetReferences.push({ presetId: deletedId, references });
|
|
12926
|
+
}
|
|
12927
|
+
}
|
|
12928
|
+
if (presetReferences.length > 0) {
|
|
12929
|
+
const details = presetReferences.map(({ presetId, references }) => `"${presetId}" is used by: ${references.join(", ")}`).join("; ");
|
|
12930
|
+
return `Cannot delete preset(s) that are still in use. ${details}`;
|
|
12931
|
+
}
|
|
12932
|
+
}
|
|
12933
|
+
}
|
|
12698
12934
|
return null;
|
|
12699
12935
|
}
|
|
12700
12936
|
function createConfigRoutes(deps) {
|
|
@@ -12702,6 +12938,7 @@ function createConfigRoutes(deps) {
|
|
|
12702
12938
|
const router = Router3();
|
|
12703
12939
|
router.get("/", (_req, res) => {
|
|
12704
12940
|
try {
|
|
12941
|
+
reloadConfig();
|
|
12705
12942
|
res.json(getConfig());
|
|
12706
12943
|
} catch (error2) {
|
|
12707
12944
|
res.status(500).json({ error: error2 instanceof Error ? error2.message : String(error2) });
|
|
@@ -12710,7 +12947,7 @@ function createConfigRoutes(deps) {
|
|
|
12710
12947
|
router.put("/", (req, res) => {
|
|
12711
12948
|
try {
|
|
12712
12949
|
const changes = req.body;
|
|
12713
|
-
const validationError = validateConfigChanges(changes);
|
|
12950
|
+
const validationError = validateConfigChanges(changes, getConfig());
|
|
12714
12951
|
if (validationError) {
|
|
12715
12952
|
res.status(400).json({ error: validationError });
|
|
12716
12953
|
return;
|
|
@@ -12741,7 +12978,7 @@ function createProjectConfigRoutes() {
|
|
|
12741
12978
|
const projectDir = req.projectDir;
|
|
12742
12979
|
try {
|
|
12743
12980
|
const changes = req.body;
|
|
12744
|
-
const validationError = validateConfigChanges(changes);
|
|
12981
|
+
const validationError = validateConfigChanges(changes, req.projectConfig);
|
|
12745
12982
|
if (validationError) {
|
|
12746
12983
|
res.status(400).json({ error: validationError });
|
|
12747
12984
|
return;
|
|
@@ -12777,17 +13014,21 @@ function runDoctorChecks(projectDir, config) {
|
|
|
12777
13014
|
checks.push({ name: "git", status: "fail", detail: "Not a git repository" });
|
|
12778
13015
|
}
|
|
12779
13016
|
try {
|
|
12780
|
-
|
|
13017
|
+
const preset = resolvePreset(config, config.provider);
|
|
13018
|
+
const command = preset?.command ?? config.provider;
|
|
13019
|
+
execSync6(`which ${command}`, { stdio: "pipe" });
|
|
12781
13020
|
checks.push({
|
|
12782
13021
|
name: "provider",
|
|
12783
13022
|
status: "pass",
|
|
12784
|
-
detail: `Provider CLI found: ${config.provider}`
|
|
13023
|
+
detail: `Provider CLI found: ${command} (preset: ${config.provider})`
|
|
12785
13024
|
});
|
|
12786
13025
|
} catch {
|
|
13026
|
+
const preset = resolvePreset(config, config.provider);
|
|
13027
|
+
const command = preset?.command ?? config.provider;
|
|
12787
13028
|
checks.push({
|
|
12788
13029
|
name: "provider",
|
|
12789
13030
|
status: "fail",
|
|
12790
|
-
detail: `Provider CLI not found: ${config.provider}`
|
|
13031
|
+
detail: `Provider CLI not found: ${command} (preset: ${config.provider})`
|
|
12791
13032
|
});
|
|
12792
13033
|
}
|
|
12793
13034
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tab-config.d.ts","sourceRoot":"","sources":["../../../src/commands/dashboard/tab-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"tab-config.d.ts","sourceRoot":"","sources":["../../../src/commands/dashboard/tab-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAGL,iBAAiB,EAKlB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,IAAI,EAAe,MAAM,YAAY,CAAC;AAE/C,KAAK,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;AAEjG,UAAU,YAAY;IACpB,GAAG,EAAE,MAAM,iBAAiB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAC7C;AAiDD,eAAO,MAAM,aAAa,EAAE,YAAY,EA+CvC,CAAC;AA0BF;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAyzBtC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Allows viewing and editing all configuration fields
|
|
4
4
|
*/
|
|
5
5
|
import blessed from 'blessed';
|
|
6
|
-
import {
|
|
6
|
+
import { BUILT_IN_PRESETS, BUILT_IN_PRESET_IDS, saveConfig, } from '@night-watch/core';
|
|
7
7
|
import { performUninstall } from '../uninstall.js';
|
|
8
8
|
import { performInstall } from '../install.js';
|
|
9
9
|
const SENSITIVE_PATTERNS = /TOKEN|KEY|SECRET|PASSWORD/i;
|
|
@@ -43,17 +43,8 @@ const NOTIFICATION_EVENTS = [
|
|
|
43
43
|
'rate_limit_fallback',
|
|
44
44
|
'qa_completed',
|
|
45
45
|
];
|
|
46
|
-
/**
|
|
47
|
-
* GLM-5 default provider environment configuration
|
|
48
|
-
*/
|
|
49
|
-
const GLM5_DEFAULTS = {
|
|
50
|
-
ANTHROPIC_BASE_URL: 'https://api.z.ai/api/anthropic',
|
|
51
|
-
API_TIMEOUT_MS: '3000000',
|
|
52
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL: 'glm-5',
|
|
53
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL: 'glm-5',
|
|
54
|
-
};
|
|
55
46
|
export const CONFIG_FIELDS = [
|
|
56
|
-
{ key: 'provider', label: 'Provider', type: 'enum', options: [...
|
|
47
|
+
{ key: 'provider', label: 'Provider', type: 'enum', options: [...BUILT_IN_PRESET_IDS] },
|
|
57
48
|
{ key: 'reviewerEnabled', label: 'Reviewer Enabled', type: 'boolean' },
|
|
58
49
|
{ key: 'defaultBranch', label: 'Default Branch', type: 'string' },
|
|
59
50
|
{ key: 'prdDir', label: 'PRD Directory', type: 'string' },
|
|
@@ -612,10 +603,16 @@ export function createConfigTab() {
|
|
|
612
603
|
ctx.screen.render();
|
|
613
604
|
return;
|
|
614
605
|
}
|
|
615
|
-
pendingChanges.
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
606
|
+
pendingChanges.provider = 'glm-5';
|
|
607
|
+
pendingChanges.providerPresets = {
|
|
608
|
+
'glm-5': {
|
|
609
|
+
...BUILT_IN_PRESETS['glm-5'],
|
|
610
|
+
envVars: {
|
|
611
|
+
...BUILT_IN_PRESETS['glm-5'].envVars,
|
|
612
|
+
ANTHROPIC_API_KEY: apiKey,
|
|
613
|
+
ANTHROPIC_AUTH_TOKEN: apiKey,
|
|
614
|
+
},
|
|
615
|
+
},
|
|
619
616
|
};
|
|
620
617
|
ctx.showMessage('GLM-5 configured. Press s to save.', 'success');
|
|
621
618
|
if (currentConfig)
|