devchain-cli 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/cli.js +199 -42
- package/dist/drizzle/0018_whole_zodiak.sql +43 -0
- package/dist/drizzle/0019_flat_avengers.sql +3 -0
- package/dist/drizzle/0020_statuses_mcp_hidden.sql +1 -0
- package/dist/drizzle/meta/0018_snapshot.json +2920 -0
- package/dist/drizzle/meta/0019_snapshot.json +2943 -0
- package/dist/drizzle/meta/0020_snapshot.json +2951 -0
- package/dist/drizzle/meta/_journal.json +21 -0
- package/dist/server/app.module.js +11 -1
- package/dist/server/app.module.js.map +1 -1
- package/dist/server/common/config/env.config.d.ts +1 -0
- package/dist/server/common/config/env.config.js +4 -0
- package/dist/server/common/config/env.config.js.map +1 -1
- package/dist/server/common/filters/http-exception.filter.js +24 -1
- package/dist/server/common/filters/http-exception.filter.js.map +1 -1
- package/dist/server/common/logging/logger.js +4 -3
- package/dist/server/common/logging/logger.js.map +1 -1
- package/dist/server/main.js +0 -3
- package/dist/server/main.js.map +1 -1
- package/dist/server/modules/agents/agents.module.js +2 -1
- package/dist/server/modules/agents/agents.module.js.map +1 -1
- package/dist/server/modules/agents/controllers/agents.controller.d.ts +17 -2
- package/dist/server/modules/agents/controllers/agents.controller.js +84 -3
- package/dist/server/modules/agents/controllers/agents.controller.js.map +1 -1
- package/dist/server/modules/chat/dtos/chat.dto.d.ts +18 -18
- package/dist/server/modules/chat/services/invite-template.util.js +1 -1
- package/dist/server/modules/chat/services/invite-template.util.js.map +1 -1
- package/dist/server/modules/core/controllers/health.controller.d.ts +1 -0
- package/dist/server/modules/core/controllers/health.controller.js +23 -0
- package/dist/server/modules/core/controllers/health.controller.js.map +1 -1
- package/dist/server/modules/events/catalog/index.d.ts +40 -0
- package/dist/server/modules/events/catalog/index.js +2 -0
- package/dist/server/modules/events/catalog/index.js.map +1 -1
- package/dist/server/modules/events/catalog/terminal.watcher.triggered.d.ts +45 -0
- package/dist/server/modules/events/catalog/terminal.watcher.triggered.js +22 -0
- package/dist/server/modules/events/catalog/terminal.watcher.triggered.js.map +1 -0
- package/dist/server/modules/events/subscribers/chat-message-delivery.subscriber.d.ts +1 -0
- package/dist/server/modules/events/subscribers/chat-message-delivery.subscriber.js +30 -12
- package/dist/server/modules/events/subscribers/chat-message-delivery.subscriber.js.map +1 -1
- package/dist/server/modules/mcp/constants.js +5 -1
- package/dist/server/modules/mcp/constants.js.map +1 -1
- package/dist/server/modules/mcp/controllers/mcp-http.controller.js +78 -77
- package/dist/server/modules/mcp/controllers/mcp-http.controller.js.map +1 -1
- package/dist/server/modules/mcp/controllers/mcp-sdk.controller.js +78 -77
- package/dist/server/modules/mcp/controllers/mcp-sdk.controller.js.map +1 -1
- package/dist/server/modules/mcp/dtos/mcp.dto.d.ts +125 -97
- package/dist/server/modules/mcp/dtos/mcp.dto.js +23 -26
- package/dist/server/modules/mcp/dtos/mcp.dto.js.map +1 -1
- package/dist/server/modules/mcp/services/instructions-resolver.d.ts +3 -0
- package/dist/server/modules/mcp/services/instructions-resolver.js +83 -2
- package/dist/server/modules/mcp/services/instructions-resolver.js.map +1 -1
- package/dist/server/modules/mcp/services/mcp.service.d.ts +3 -2
- package/dist/server/modules/mcp/services/mcp.service.js +549 -263
- package/dist/server/modules/mcp/services/mcp.service.js.map +1 -1
- package/dist/server/modules/projects/controllers/projects.controller.d.ts +42 -0
- package/dist/server/modules/projects/controllers/projects.controller.js +11 -0
- package/dist/server/modules/projects/controllers/projects.controller.js.map +1 -1
- package/dist/server/modules/projects/projects.module.js +2 -1
- package/dist/server/modules/projects/projects.module.js.map +1 -1
- package/dist/server/modules/projects/services/projects.service.d.ts +47 -1
- package/dist/server/modules/projects/services/projects.service.js +278 -22
- package/dist/server/modules/projects/services/projects.service.js.map +1 -1
- package/dist/server/modules/prompts/controllers/prompts.controller.d.ts +1 -1
- package/dist/server/modules/prompts/controllers/prompts.controller.js +26 -4
- package/dist/server/modules/prompts/controllers/prompts.controller.js.map +1 -1
- package/dist/server/modules/sessions/utils/template-renderer.js +1 -0
- package/dist/server/modules/sessions/utils/template-renderer.js.map +1 -1
- package/dist/server/modules/statuses/controllers/statuses.controller.js +2 -0
- package/dist/server/modules/statuses/controllers/statuses.controller.js.map +1 -1
- package/dist/server/modules/storage/db/schema.d.ts +613 -0
- package/dist/server/modules/storage/db/schema.js +50 -1
- package/dist/server/modules/storage/db/schema.js.map +1 -1
- package/dist/server/modules/storage/interfaces/storage.interface.d.ts +40 -2
- package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
- package/dist/server/modules/storage/local/local-storage.service.d.ts +18 -3
- package/dist/server/modules/storage/local/local-storage.service.js +407 -11
- package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
- package/dist/server/modules/storage/models/domain.models.d.ts +59 -1
- package/dist/server/modules/subscribers/actions/action.interface.d.ts +67 -0
- package/dist/server/modules/subscribers/actions/action.interface.js +3 -0
- package/dist/server/modules/subscribers/actions/action.interface.js.map +1 -0
- package/dist/server/modules/subscribers/actions/actions.registry.d.ts +7 -0
- package/dist/server/modules/subscribers/actions/actions.registry.js +37 -0
- package/dist/server/modules/subscribers/actions/actions.registry.js.map +1 -0
- package/dist/server/modules/subscribers/actions/restart-agent.action.d.ts +8 -0
- package/dist/server/modules/subscribers/actions/restart-agent.action.js +119 -0
- package/dist/server/modules/subscribers/actions/restart-agent.action.js.map +1 -0
- package/dist/server/modules/subscribers/actions/send-message.action.d.ts +2 -0
- package/dist/server/modules/subscribers/actions/send-message.action.js +83 -0
- package/dist/server/modules/subscribers/actions/send-message.action.js.map +1 -0
- package/dist/server/modules/subscribers/controllers/actions.controller.d.ts +6 -0
- package/dist/server/modules/subscribers/controllers/actions.controller.js +51 -0
- package/dist/server/modules/subscribers/controllers/actions.controller.js.map +1 -0
- package/dist/server/modules/subscribers/controllers/subscribers.controller.d.ts +17 -0
- package/dist/server/modules/subscribers/controllers/subscribers.controller.js +178 -0
- package/dist/server/modules/subscribers/controllers/subscribers.controller.js.map +1 -0
- package/dist/server/modules/subscribers/dtos/subscriber.dto.d.ts +251 -0
- package/dist/server/modules/subscribers/dtos/subscriber.dto.js +68 -0
- package/dist/server/modules/subscribers/dtos/subscriber.dto.js.map +1 -0
- package/dist/server/modules/subscribers/events/event-fields-catalog.d.ts +19 -0
- package/dist/server/modules/subscribers/events/event-fields-catalog.js +98 -0
- package/dist/server/modules/subscribers/events/event-fields-catalog.js.map +1 -0
- package/dist/server/modules/subscribers/services/automation-scheduler.service.d.ts +49 -0
- package/dist/server/modules/subscribers/services/automation-scheduler.service.js +300 -0
- package/dist/server/modules/subscribers/services/automation-scheduler.service.js.map +1 -0
- package/dist/server/modules/subscribers/services/subscriber-executor.service.d.ts +77 -0
- package/dist/server/modules/subscribers/services/subscriber-executor.service.js +576 -0
- package/dist/server/modules/subscribers/services/subscriber-executor.service.js.map +1 -0
- package/dist/server/modules/subscribers/services/subscribers.service.d.ts +14 -0
- package/dist/server/modules/subscribers/services/subscribers.service.js +70 -0
- package/dist/server/modules/subscribers/services/subscribers.service.js.map +1 -0
- package/dist/server/modules/subscribers/subscribers.module.d.ts +2 -0
- package/dist/server/modules/subscribers/subscribers.module.js +36 -0
- package/dist/server/modules/subscribers/subscribers.module.js.map +1 -0
- package/dist/server/modules/terminal/services/tmux.service.js +9 -6
- package/dist/server/modules/terminal/services/tmux.service.js.map +1 -1
- package/dist/server/modules/watchers/controllers/watchers.controller.d.ts +16 -0
- package/dist/server/modules/watchers/controllers/watchers.controller.js +180 -0
- package/dist/server/modules/watchers/controllers/watchers.controller.js.map +1 -0
- package/dist/server/modules/watchers/dtos/watcher.dto.d.ts +206 -0
- package/dist/server/modules/watchers/dtos/watcher.dto.js +54 -0
- package/dist/server/modules/watchers/dtos/watcher.dto.js.map +1 -0
- package/dist/server/modules/watchers/services/watcher-runner.service.d.ts +68 -0
- package/dist/server/modules/watchers/services/watcher-runner.service.js +477 -0
- package/dist/server/modules/watchers/services/watcher-runner.service.js.map +1 -0
- package/dist/server/modules/watchers/services/watchers.service.d.ts +29 -0
- package/dist/server/modules/watchers/services/watchers.service.js +98 -0
- package/dist/server/modules/watchers/services/watchers.service.js.map +1 -0
- package/dist/server/modules/watchers/watchers.module.d.ts +2 -0
- package/dist/server/modules/watchers/watchers.module.js +34 -0
- package/dist/server/modules/watchers/watchers.module.js.map +1 -0
- package/dist/server/templates/claude-codex-advanced.json +377 -0
- package/dist/server/templates/claude-opus.json +29 -25
- package/dist/server/templates/simple-codex.json +29 -25
- package/dist/server/test-setup-node.d.ts +1 -0
- package/dist/server/test-setup-node.js +8 -0
- package/dist/server/test-setup-node.js.map +1 -0
- package/dist/server/test-setup.js +2 -0
- package/dist/server/test-setup.js.map +1 -1
- package/dist/server/tsconfig.tsbuildinfo +1 -1
- package/dist/server/ui/assets/index-C9GXCjnF.js +700 -0
- package/dist/server/ui/assets/index-o0FbZg-1.css +32 -0
- package/dist/server/ui/index.html +2 -2
- package/dist/templates/claude-codex-advanced.json +377 -0
- package/dist/templates/claude-opus.json +29 -25
- package/dist/templates/simple-codex.json +29 -25
- package/package.json +58 -27
- package/dist/server/templates/codex-claude.json +0 -178
- package/dist/server/ui/assets/index-5Xb7jFMJ.js +0 -641
- package/dist/server/ui/assets/index-CbYIbCQV.css +0 -32
- package/dist/templates/codex-claude.json +0 -178
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
AI driven development platform
|
|
4
4
|
|
|
5
|
+
**[Homepage](https://devchain.twitechlab.com/)** · **[GitHub](https://github.com/twitech-lab/devchain)**
|
|
6
|
+
|
|
5
7
|
Devchain coordinates AI coding agents (Claude, Codex) through a visual workflow interface with tmux-backed terminal sessions.
|
|
6
8
|
|
|
7
9
|
## Features
|
package/dist/cli.js
CHANGED
|
@@ -52,6 +52,113 @@ async function fetchWithTimeout(url, options = {}, timeoutMs = 2000) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
function isNewerVersion(latest, current) {
|
|
56
|
+
const l = latest.split('.').map(Number);
|
|
57
|
+
const c = current.split('.').map(Number);
|
|
58
|
+
for (let i = 0; i < 3; i++) {
|
|
59
|
+
if ((l[i] || 0) > (c[i] || 0)) return true;
|
|
60
|
+
if ((l[i] || 0) < (c[i] || 0)) return false;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function getChangelogBetweenVersions(changelog, fromVersion, toVersion) {
|
|
66
|
+
if (!changelog || typeof changelog !== 'object') return [];
|
|
67
|
+
|
|
68
|
+
const changes = [];
|
|
69
|
+
const versions = Object.keys(changelog).sort((a, b) => {
|
|
70
|
+
// Sort versions descending
|
|
71
|
+
const aParts = a.split('.').map(Number);
|
|
72
|
+
const bParts = b.split('.').map(Number);
|
|
73
|
+
for (let i = 0; i < 3; i++) {
|
|
74
|
+
if ((bParts[i] || 0) !== (aParts[i] || 0)) {
|
|
75
|
+
return (bParts[i] || 0) - (aParts[i] || 0);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return 0;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
for (const version of versions) {
|
|
82
|
+
if (isNewerVersion(version, fromVersion) && !isNewerVersion(version, toVersion)) {
|
|
83
|
+
// Include this version's changes
|
|
84
|
+
if (Array.isArray(changelog[version])) {
|
|
85
|
+
changes.push({ version, items: changelog[version] });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Also include the target version itself
|
|
89
|
+
if (version === toVersion && Array.isArray(changelog[version])) {
|
|
90
|
+
if (!changes.find(c => c.version === version)) {
|
|
91
|
+
changes.unshift({ version, items: changelog[version] });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return changes;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function checkForUpdates(cli, askYesNoFn) {
|
|
100
|
+
try {
|
|
101
|
+
const pkg = require('../package.json');
|
|
102
|
+
const currentVersion = pkg.version;
|
|
103
|
+
const packageName = pkg.name;
|
|
104
|
+
|
|
105
|
+
// Fetch latest package info from npm registry (with short timeout)
|
|
106
|
+
const res = await fetchWithTimeout(`https://registry.npmjs.org/${packageName}/latest`, {}, 3000);
|
|
107
|
+
if (!res.ok) return;
|
|
108
|
+
|
|
109
|
+
const data = await res.json();
|
|
110
|
+
const latestVersion = data.version;
|
|
111
|
+
|
|
112
|
+
if (latestVersion !== currentVersion && isNewerVersion(latestVersion, currentVersion)) {
|
|
113
|
+
cli.blank();
|
|
114
|
+
cli.warn(`A new version of devchain is available: ${currentVersion} → ${latestVersion}`);
|
|
115
|
+
|
|
116
|
+
// Show changelog if available
|
|
117
|
+
const changelog = data.changelog;
|
|
118
|
+
const changes = getChangelogBetweenVersions(changelog, currentVersion, latestVersion);
|
|
119
|
+
if (changes.length > 0) {
|
|
120
|
+
cli.blank();
|
|
121
|
+
cli.info("What's new:");
|
|
122
|
+
for (const { version, items } of changes) {
|
|
123
|
+
for (const item of items) {
|
|
124
|
+
console.log(` • ${item}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
cli.blank();
|
|
129
|
+
|
|
130
|
+
const shouldUpdate = await askYesNoFn('Would you like to update now?', true);
|
|
131
|
+
|
|
132
|
+
if (shouldUpdate) {
|
|
133
|
+
cli.info('Updating devchain...');
|
|
134
|
+
try {
|
|
135
|
+
// Try without sudo first (works for nvm/fnm/Windows)
|
|
136
|
+
execSync(`npm update -g ${packageName}`, { stdio: 'inherit' });
|
|
137
|
+
cli.success('Update complete! Please restart devchain.');
|
|
138
|
+
process.exit(0);
|
|
139
|
+
} catch (e) {
|
|
140
|
+
// On Linux/Mac, might need sudo for system npm
|
|
141
|
+
if (platform() !== 'win32') {
|
|
142
|
+
cli.info('Retrying with sudo...');
|
|
143
|
+
try {
|
|
144
|
+
execSync(`sudo npm update -g ${packageName}`, { stdio: 'inherit' });
|
|
145
|
+
cli.success('Update complete! Please restart devchain.');
|
|
146
|
+
process.exit(0);
|
|
147
|
+
} catch (e2) {
|
|
148
|
+
cli.error('Update failed. You can manually run: sudo npm update -g ' + packageName);
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
cli.error('Update failed. You can manually run: npm update -g ' + packageName);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
cli.blank();
|
|
156
|
+
}
|
|
157
|
+
} catch (e) {
|
|
158
|
+
// Silently ignore - don't block startup for update check failures
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
55
162
|
function isBinaryInstalled(cmd) {
|
|
56
163
|
try {
|
|
57
164
|
const out = execSync(`which ${cmd}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })
|
|
@@ -218,15 +325,32 @@ async function validateMcpForProviders(baseUrl, cli, opts, log, projectPath) {
|
|
|
218
325
|
}
|
|
219
326
|
}
|
|
220
327
|
|
|
221
|
-
function askYesNo(question) {
|
|
328
|
+
function askYesNo(question, defaultYes = false) {
|
|
222
329
|
return new Promise((resolve) => {
|
|
223
330
|
const rl = readline.createInterface({
|
|
224
331
|
input: process.stdin,
|
|
225
332
|
output: process.stdout,
|
|
226
333
|
});
|
|
227
|
-
|
|
334
|
+
const prompt = defaultYes ? `${question} [Y/n] ` : `${question} [y/N] `;
|
|
335
|
+
let answered = false;
|
|
336
|
+
|
|
337
|
+
// Handle Ctrl+D (EOF) - user wants to cancel/exit
|
|
338
|
+
rl.on('close', () => {
|
|
339
|
+
if (!answered) {
|
|
340
|
+
console.log(); // Print newline since Ctrl+D doesn't
|
|
341
|
+
process.exit(0);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
rl.question(prompt, (answer) => {
|
|
346
|
+
answered = true;
|
|
228
347
|
rl.close();
|
|
229
|
-
|
|
348
|
+
const trimmed = answer.trim().toLowerCase();
|
|
349
|
+
if (trimmed === '') {
|
|
350
|
+
resolve(defaultYes);
|
|
351
|
+
} else {
|
|
352
|
+
resolve(trimmed === 'y' || trimmed === 'yes');
|
|
353
|
+
}
|
|
230
354
|
});
|
|
231
355
|
});
|
|
232
356
|
}
|
|
@@ -258,7 +382,8 @@ async function ensureClaudeBypassPermissions(cli) {
|
|
|
258
382
|
cli.info('Claude requires permission approval for each command by default.');
|
|
259
383
|
cli.info('Enabling bypass mode allows devchain to auto-approve commands.');
|
|
260
384
|
|
|
261
|
-
const confirmed = await askYesNo('Enable bypass permissions mode for Claude?');
|
|
385
|
+
const confirmed = await askYesNo('Enable bypass permissions mode for Claude?', true);
|
|
386
|
+
cli.blank();
|
|
262
387
|
|
|
263
388
|
if (confirmed) {
|
|
264
389
|
config.bypassPermissionsModeAccepted = true;
|
|
@@ -444,45 +569,34 @@ async function main(argv) {
|
|
|
444
569
|
startCommand.help();
|
|
445
570
|
return;
|
|
446
571
|
}
|
|
572
|
+
|
|
573
|
+
// Check if already running (skip for detached child - parent already checked)
|
|
574
|
+
if (!opts.internalDetachedChild) {
|
|
575
|
+
const existingPid = readPidFile();
|
|
576
|
+
if (existingPid && isProcessRunning(existingPid.pid)) {
|
|
577
|
+
console.error(`Devchain is already running (PID ${existingPid.pid}, port ${existingPid.port})`);
|
|
578
|
+
console.error(`Access it at: http://127.0.0.1:${existingPid.port}`);
|
|
579
|
+
console.error('Use "devchain stop" to stop it first.');
|
|
580
|
+
process.exit(1);
|
|
581
|
+
}
|
|
582
|
+
// Clean up stale PID file if process is not running
|
|
583
|
+
if (existingPid && !isProcessRunning(existingPid.pid)) {
|
|
584
|
+
removePidFile();
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
447
588
|
// Normalize defaults for negatable options (Commander may leave undefined)
|
|
448
589
|
if (typeof opts.open === 'undefined') {
|
|
449
590
|
opts.open = true;
|
|
450
591
|
}
|
|
451
592
|
// Detached mode by default, unless foreground is explicitly requested
|
|
452
593
|
// Don't detach again if we're already the detached child process
|
|
453
|
-
const
|
|
454
|
-
|
|
455
|
-
// If detached mode, respawn as a background process
|
|
456
|
-
if (shouldDetach) {
|
|
457
|
-
const args = process.argv.slice(2).filter(arg => arg !== '-d' && arg !== '--detach');
|
|
458
|
-
// Add internal flag to prevent infinite respawning
|
|
459
|
-
args.push('--internal-detached-child');
|
|
460
|
-
|
|
461
|
-
// Create log file for detached process output
|
|
462
|
-
const devchainDir = join(homedir(), '.devchain');
|
|
463
|
-
if (!existsSync(devchainDir)) {
|
|
464
|
-
mkdirSync(devchainDir, { recursive: true });
|
|
465
|
-
}
|
|
466
|
-
const logFile = join(devchainDir, 'devchain.log');
|
|
467
|
-
const out = openSync(logFile, 'a');
|
|
468
|
-
const err = openSync(logFile, 'a');
|
|
469
|
-
|
|
470
|
-
const child = spawn(process.execPath, [__filename, ...args], {
|
|
471
|
-
detached: true,
|
|
472
|
-
stdio: ['ignore', out, err],
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
child.unref();
|
|
476
|
-
|
|
477
|
-
console.log(`Devchain is starting in background (PID ${child.pid})...`);
|
|
478
|
-
console.log(`Log file: ${logFile}`);
|
|
479
|
-
console.log('Use "devchain stop" to stop it.');
|
|
480
|
-
process.exit(0);
|
|
481
|
-
}
|
|
594
|
+
const isDetachedChild = opts.internalDetachedChild;
|
|
595
|
+
const shouldDetach = opts.foreground !== true && !isDetachedChild;
|
|
482
596
|
|
|
483
597
|
// Initialize interactive CLI (user-friendly output unless in foreground mode)
|
|
484
598
|
const cli = new InteractiveCLI({
|
|
485
|
-
interactive: !opts.foreground,
|
|
599
|
+
interactive: !opts.foreground && !isDetachedChild,
|
|
486
600
|
colors: true,
|
|
487
601
|
spinners: true
|
|
488
602
|
});
|
|
@@ -492,6 +606,11 @@ async function main(argv) {
|
|
|
492
606
|
console.log(JSON.stringify(entry));
|
|
493
607
|
};
|
|
494
608
|
|
|
609
|
+
// Check for updates (parent process only, skip in dev mode)
|
|
610
|
+
if (!isDetachedChild && !opts.dev) {
|
|
611
|
+
await checkForUpdates(cli, askYesNo);
|
|
612
|
+
}
|
|
613
|
+
|
|
495
614
|
// Show startup banner (interactive mode only)
|
|
496
615
|
if (!opts.foreground) {
|
|
497
616
|
cli.blank();
|
|
@@ -612,9 +731,53 @@ async function main(argv) {
|
|
|
612
731
|
}
|
|
613
732
|
}
|
|
614
733
|
|
|
734
|
+
// Prompt for Claude bypass permissions (parent only - requires stdin)
|
|
735
|
+
// This runs BEFORE detach since it needs user interaction
|
|
736
|
+
if (!isDetachedChild && opts.__providersDetected && opts.__providersDetected.has('claude')) {
|
|
737
|
+
await ensureClaudeBypassPermissions(cli);
|
|
738
|
+
}
|
|
739
|
+
|
|
615
740
|
const preferPort = opts.port ? Number(opts.port) : 3000;
|
|
616
741
|
const port = await getPort({ port: preferPort });
|
|
617
742
|
|
|
743
|
+
// === DETACH POINT ===
|
|
744
|
+
// All interactive prompts are done. Now spawn the detached child if needed.
|
|
745
|
+
if (shouldDetach) {
|
|
746
|
+
// Build child args, passing the selected port
|
|
747
|
+
const childArgs = process.argv.slice(2)
|
|
748
|
+
.filter(arg => arg !== '-d' && arg !== '--detach')
|
|
749
|
+
.filter((arg, i, arr) => {
|
|
750
|
+
// Remove existing --port and its value
|
|
751
|
+
if (arg === '--port' || arg === '-p') return false;
|
|
752
|
+
if (i > 0 && (arr[i - 1] === '--port' || arr[i - 1] === '-p')) return false;
|
|
753
|
+
return true;
|
|
754
|
+
});
|
|
755
|
+
childArgs.push('--internal-detached-child');
|
|
756
|
+
childArgs.push('--port', String(port));
|
|
757
|
+
|
|
758
|
+
// Create log file for detached process output
|
|
759
|
+
const devchainDir = join(homedir(), '.devchain');
|
|
760
|
+
if (!existsSync(devchainDir)) {
|
|
761
|
+
mkdirSync(devchainDir, { recursive: true });
|
|
762
|
+
}
|
|
763
|
+
const logFile = join(devchainDir, 'devchain.log');
|
|
764
|
+
const out = openSync(logFile, 'a');
|
|
765
|
+
const err = openSync(logFile, 'a');
|
|
766
|
+
|
|
767
|
+
const child = spawn(process.execPath, [__filename, ...childArgs], {
|
|
768
|
+
detached: true,
|
|
769
|
+
stdio: ['ignore', out, err],
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
child.unref();
|
|
773
|
+
|
|
774
|
+
cli.blank();
|
|
775
|
+
cli.success(`Devchain starting in background (PID ${child.pid})`);
|
|
776
|
+
cli.info(`Log file: ${logFile}`);
|
|
777
|
+
cli.info('Use "devchain stop" to stop it.');
|
|
778
|
+
process.exit(0);
|
|
779
|
+
}
|
|
780
|
+
|
|
618
781
|
// Apply env before requiring the server
|
|
619
782
|
process.env.PORT = String(port);
|
|
620
783
|
process.env.HOST = process.env.HOST || '127.0.0.1';
|
|
@@ -697,10 +860,7 @@ async function main(argv) {
|
|
|
697
860
|
// Validate MCP for all providers
|
|
698
861
|
await validateMcpForProviders(baseUrl, cli, opts, log, startupPath);
|
|
699
862
|
|
|
700
|
-
//
|
|
701
|
-
if (opts.__providersDetected && opts.__providersDetected.has('claude')) {
|
|
702
|
-
await ensureClaudeBypassPermissions(cli);
|
|
703
|
-
}
|
|
863
|
+
// Note: Claude bypass prompt already handled before server start
|
|
704
864
|
|
|
705
865
|
cli.blank();
|
|
706
866
|
cli.info('Starting UI (dev mode)...');
|
|
@@ -798,10 +958,7 @@ async function main(argv) {
|
|
|
798
958
|
// Validate MCP for all providers (with project context)
|
|
799
959
|
await validateMcpForProviders(baseUrl, cli, opts, log, startupPath);
|
|
800
960
|
|
|
801
|
-
//
|
|
802
|
-
if (opts.__providersDetected && opts.__providersDetected.has('claude')) {
|
|
803
|
-
await ensureClaudeBypassPermissions(cli);
|
|
804
|
-
}
|
|
961
|
+
// Note: Claude bypass prompt already handled before server start (in parent process for detach mode)
|
|
805
962
|
|
|
806
963
|
// Determine URL to open based on project path
|
|
807
964
|
let urlToOpen = baseUrl;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
CREATE TABLE `automation_subscribers` (
|
|
2
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
3
|
+
`project_id` text NOT NULL,
|
|
4
|
+
`name` text NOT NULL,
|
|
5
|
+
`description` text,
|
|
6
|
+
`enabled` integer DEFAULT true NOT NULL,
|
|
7
|
+
`event_name` text NOT NULL,
|
|
8
|
+
`event_filter` text,
|
|
9
|
+
`action_type` text NOT NULL,
|
|
10
|
+
`action_inputs` text NOT NULL,
|
|
11
|
+
`delay_ms` integer DEFAULT 0 NOT NULL,
|
|
12
|
+
`cooldown_ms` integer DEFAULT 5000 NOT NULL,
|
|
13
|
+
`retry_on_error` integer DEFAULT false NOT NULL,
|
|
14
|
+
`created_at` text NOT NULL,
|
|
15
|
+
`updated_at` text NOT NULL,
|
|
16
|
+
FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`) ON UPDATE no action ON DELETE cascade
|
|
17
|
+
);
|
|
18
|
+
--> statement-breakpoint
|
|
19
|
+
CREATE INDEX `automation_subscribers_project_id_idx` ON `automation_subscribers` (`project_id`);--> statement-breakpoint
|
|
20
|
+
CREATE INDEX `automation_subscribers_event_name_idx` ON `automation_subscribers` (`event_name`);--> statement-breakpoint
|
|
21
|
+
CREATE INDEX `automation_subscribers_enabled_idx` ON `automation_subscribers` (`enabled`);--> statement-breakpoint
|
|
22
|
+
CREATE TABLE `terminal_watchers` (
|
|
23
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
24
|
+
`project_id` text NOT NULL,
|
|
25
|
+
`name` text NOT NULL,
|
|
26
|
+
`description` text,
|
|
27
|
+
`enabled` integer DEFAULT true NOT NULL,
|
|
28
|
+
`scope` text DEFAULT 'all' NOT NULL,
|
|
29
|
+
`scope_filter_id` text,
|
|
30
|
+
`poll_interval_ms` integer DEFAULT 5000 NOT NULL,
|
|
31
|
+
`viewport_lines` integer DEFAULT 50 NOT NULL,
|
|
32
|
+
`condition` text NOT NULL,
|
|
33
|
+
`cooldown_ms` integer DEFAULT 60000 NOT NULL,
|
|
34
|
+
`cooldown_mode` text DEFAULT 'time' NOT NULL,
|
|
35
|
+
`event_name` text NOT NULL,
|
|
36
|
+
`created_at` text NOT NULL,
|
|
37
|
+
`updated_at` text NOT NULL,
|
|
38
|
+
FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`) ON UPDATE no action ON DELETE cascade
|
|
39
|
+
);
|
|
40
|
+
--> statement-breakpoint
|
|
41
|
+
CREATE INDEX `terminal_watchers_project_id_idx` ON `terminal_watchers` (`project_id`);--> statement-breakpoint
|
|
42
|
+
CREATE INDEX `terminal_watchers_enabled_idx` ON `terminal_watchers` (`enabled`);--> statement-breakpoint
|
|
43
|
+
CREATE UNIQUE INDEX `terminal_watchers_event_name_unique` ON `terminal_watchers` (`project_id`,`event_name`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE `statuses` ADD `mcp_hidden` integer DEFAULT 0 NOT NULL;
|