deckide 3.5.38 → 3.5.39
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/server.js +8 -0
- package/dist/utils/agent-browser.js +47 -0
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -51,6 +51,14 @@ export async function createServer() {
|
|
|
51
51
|
const decks = new Map();
|
|
52
52
|
const terminals = new Map();
|
|
53
53
|
const browserService = new AgentBrowserService();
|
|
54
|
+
// 共有ブラウザを起動時から常駐させ、BrowserPane を開いていなくても
|
|
55
|
+
// Codex/Claude の chrome MCP(--browserUrl 127.0.0.1:9222)が常に使えるようにする。
|
|
56
|
+
// 失敗してもサーバ起動は継続(Chrome 未導入の環境などを考慮)。AGENT_BROWSER_AUTOSTART=false で無効化可。
|
|
57
|
+
if (process.env.AGENT_BROWSER_AUTOSTART !== 'false') {
|
|
58
|
+
void browserService.start().catch((err) => {
|
|
59
|
+
console.error('[browser] 共有ブラウザの自動起動に失敗:', err instanceof Error ? err.message : err);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
54
62
|
loadPersistedState(db, workspaces, workspacePathIndex, decks);
|
|
55
63
|
// Create Hono app
|
|
56
64
|
const app = new Hono();
|
|
@@ -280,6 +280,13 @@ export class AgentBrowserService {
|
|
|
280
280
|
launching = null;
|
|
281
281
|
port = null;
|
|
282
282
|
executablePath = null;
|
|
283
|
+
// 共有ブラウザを常駐させるための状態。keepAlive が true の間はクラッシュ時に
|
|
284
|
+
// 自動再起動し、9222 を常時稼働させる(BrowserPane を開いていなくても
|
|
285
|
+
// chrome MCP が使えるようにするため)。明示的な stop() で false にする。
|
|
286
|
+
keepAlive = false;
|
|
287
|
+
restartTimer = null;
|
|
288
|
+
restartAttempts = 0;
|
|
289
|
+
lastStartTime = 0;
|
|
283
290
|
// Browser-level CDP connection used only to discover tabs (page targets) and
|
|
284
291
|
// drive their lifecycle (create/close/activate). One per running Chrome.
|
|
285
292
|
browserCdp = null;
|
|
@@ -333,6 +340,8 @@ export class AgentBrowserService {
|
|
|
333
340
|
};
|
|
334
341
|
}
|
|
335
342
|
async start() {
|
|
343
|
+
// 一度起動を要求されたら常駐させる(クラッシュ時は自動再起動)。
|
|
344
|
+
this.keepAlive = true;
|
|
336
345
|
if (this.isRunning()) {
|
|
337
346
|
await this.ensureSession();
|
|
338
347
|
if (this.clients.size > 0) {
|
|
@@ -350,6 +359,7 @@ export class AgentBrowserService {
|
|
|
350
359
|
this.launching = this.launch();
|
|
351
360
|
try {
|
|
352
361
|
await this.launching;
|
|
362
|
+
this.lastStartTime = Date.now();
|
|
353
363
|
}
|
|
354
364
|
catch (error) {
|
|
355
365
|
this.lastError = error instanceof Error ? error.message : String(error);
|
|
@@ -364,6 +374,12 @@ export class AgentBrowserService {
|
|
|
364
374
|
}
|
|
365
375
|
}
|
|
366
376
|
async stop() {
|
|
377
|
+
// 明示的な停止 → 自動再起動を無効化。
|
|
378
|
+
this.keepAlive = false;
|
|
379
|
+
if (this.restartTimer) {
|
|
380
|
+
clearTimeout(this.restartTimer);
|
|
381
|
+
this.restartTimer = null;
|
|
382
|
+
}
|
|
367
383
|
this.disconnectActiveCdp();
|
|
368
384
|
this.closeBrowserCdp();
|
|
369
385
|
const proc = this.chromeProcess;
|
|
@@ -438,6 +454,33 @@ export class AgentBrowserService {
|
|
|
438
454
|
await this.refreshActivePageInfo();
|
|
439
455
|
await this.broadcastStatus();
|
|
440
456
|
}
|
|
457
|
+
// クラッシュ後に共有ブラウザを自動再起動する(9222 常時稼働の維持)。
|
|
458
|
+
// 直近の起動が短命なら連続再起動を抑制し、5 回連続で短命なら諦める。
|
|
459
|
+
scheduleAutoRestart() {
|
|
460
|
+
if (this.restartTimer || !this.keepAlive) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
// 30 秒以上動いていたら安定とみなしてカウンタをリセット。
|
|
464
|
+
if (Date.now() - this.lastStartTime > 30_000) {
|
|
465
|
+
this.restartAttempts = 0;
|
|
466
|
+
}
|
|
467
|
+
if (this.restartAttempts >= 5) {
|
|
468
|
+
console.error('[agent-browser] 自動再起動を中止(短時間に連続クラッシュ)');
|
|
469
|
+
this.keepAlive = false;
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
this.restartAttempts++;
|
|
473
|
+
const delay = Math.min(1000 * this.restartAttempts, 10_000);
|
|
474
|
+
this.restartTimer = setTimeout(() => {
|
|
475
|
+
this.restartTimer = null;
|
|
476
|
+
if (!this.keepAlive)
|
|
477
|
+
return;
|
|
478
|
+
this.start().catch((e) => {
|
|
479
|
+
console.error('[agent-browser] 自動再起動に失敗:', e instanceof Error ? e.message : e);
|
|
480
|
+
});
|
|
481
|
+
}, delay);
|
|
482
|
+
this.restartTimer.unref?.();
|
|
483
|
+
}
|
|
441
484
|
// 履歴を delta だけ移動(-1=戻る, +1=進む)。端なら何もしない。
|
|
442
485
|
async goHistory(delta) {
|
|
443
486
|
await this.start();
|
|
@@ -541,6 +584,10 @@ export class AgentBrowserService {
|
|
|
541
584
|
this.closeLogStream();
|
|
542
585
|
this.lastError = code === 0 ? undefined : `Browser exited (${signal ?? code ?? 'unknown'})`;
|
|
543
586
|
void this.broadcastStatus();
|
|
587
|
+
// 明示停止でなく落ちた(クラッシュ)なら、常駐維持のため自動再起動。
|
|
588
|
+
if (this.keepAlive) {
|
|
589
|
+
this.scheduleAutoRestart();
|
|
590
|
+
}
|
|
544
591
|
}
|
|
545
592
|
});
|
|
546
593
|
child.once('error', (error) => {
|