tide-commander 1.165.1 → 1.167.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/CHANGELOG.md +24 -0
- package/dist/assets/{BossLogsModal-IqVqHwz-.js → BossLogsModal-CLmSG1H0.js} +1 -1
- package/dist/assets/BossSpawnModal-DZlB8KRy.js +1 -0
- package/dist/assets/ControlsModal-B1-STBnD.js +1 -0
- package/dist/assets/DockerLogsModal-CWnhsG_r.js +2 -0
- package/dist/assets/{EmbeddedEditor-BA9mX_Lg.js → EmbeddedEditor-5po-iz0Q.js} +1 -1
- package/dist/assets/{GmailOAuthSetup-7nj6aLot.js → GmailOAuthSetup-BB10r44e.js} +1 -1
- package/dist/assets/GoogleOAuthSetup-CW_Ib5kq.js +270 -0
- package/dist/assets/{IframeModal-DkkCx6nq.js → IframeModal-CPt5x5fr.js} +1 -1
- package/dist/assets/IntegrationsPanel-CO-5iHtn.js +2 -0
- package/dist/assets/{LogViewerModal-DKYB8dHo.js → LogViewerModal-DicJq6l-.js} +1 -1
- package/dist/assets/{MonitoringModal-DOKMIa5U.js → MonitoringModal-B3nwcYZn.js} +1 -1
- package/dist/assets/{PM2LogsModal-XlbT9uoY.js → PM2LogsModal-Viw6fBjN.js} +2 -2
- package/dist/assets/RestoreArchivedAreaModal-BVH9wxhk.js +1 -0
- package/dist/assets/Scene2DCanvas-D6TCimYq.js +1 -0
- package/dist/assets/SceneManager-BdJs75zx.js +104 -0
- package/dist/assets/{SkillsPanel-BKjpKM1N.js → SkillsPanel-D1WonIBN.js} +1 -1
- package/dist/assets/{SlackMultiInstanceSetup-C0k60ioO.js → SlackMultiInstanceSetup-DSTZ5Hry.js} +1 -1
- package/dist/assets/SpawnModal-DUpIkQ08.js +1 -0
- package/dist/assets/StatisticsModal-BoDgM_8E.js +1 -0
- package/dist/assets/SubordinateAssignmentModal-LysAkNGy.js +1 -0
- package/dist/assets/{TriggerManagerPanel-RWrID12k.js → TriggerManagerPanel-BHxmBRvy.js} +1 -1
- package/dist/assets/{WorkflowEditorPanel-Ccwm4H5t.js → WorkflowEditorPanel-BHayKmMV.js} +1 -1
- package/dist/assets/abnfDiagram-VRR7QNED-DBZ5EpAj.js +1 -0
- package/dist/assets/arc-UCe2q9lp.js +1 -0
- package/dist/assets/architectureDiagram-ZJ3FMSHR-D5zOdUA8.js +36 -0
- package/dist/assets/{area-logos-DnrrrkFh.js → area-logos-4nlUPBxf.js} +1 -1
- package/dist/assets/blockDiagram-677ZJIJ3-7S-qZlh0.js +132 -0
- package/dist/assets/c4Diagram-LMCZKHZV-CgLv5SCO.js +10 -0
- package/dist/assets/channel-C59jtig-.js +1 -0
- package/dist/assets/chunk-2Q5K7J3B-J08qsAGr.js +1 -0
- package/dist/assets/chunk-32BRIVSS-Xy5D5wu7.js +1 -0
- package/dist/assets/chunk-5VM5RSS4-DqhmRB6E.js +15 -0
- package/dist/assets/chunk-EX3LRPZG-QE89_WgA.js +231 -0
- package/dist/assets/chunk-JWPE2WC7-YSc_ua_g.js +1 -0
- package/dist/assets/chunk-MOJQB5TN-CcH7NM7I.js +88 -0
- package/dist/assets/chunk-RYQCIY6F-CndQTJJ1.js +1 -0
- package/dist/assets/chunk-V7JOEXUC-Dauixo5p.js +206 -0
- package/dist/assets/chunk-VR4S4FIN-BBU6oFw0.js +1 -0
- package/dist/assets/chunk-XXDRQBXY-DXMolb4D.js +1 -0
- package/dist/assets/classDiagram-OUVF2IWQ-DHvVmqF9.js +1 -0
- package/dist/assets/classDiagram-v2-EOCWNBFH-DHvVmqF9.js +1 -0
- package/dist/assets/cose-bilkent-JH36ORCC-Dd9IB924.js +1 -0
- package/dist/assets/cynefin-VYW2F7L2-BQxwdSSb.js +178 -0
- package/dist/assets/cynefinDiagram-TSTJHNR4-BLnxgd0m.js +62 -0
- package/dist/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
- package/dist/assets/dagre-VKFMJZFB-BZ7fXVWR.js +4 -0
- package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/assets/diagram-FQU43EPY-BFQ1xjHE.js +3 -0
- package/dist/assets/diagram-G47NLZAW-sXsGErM6.js +24 -0
- package/dist/assets/diagram-NH7WQ7WH-D6SPifDp.js +24 -0
- package/dist/assets/diagram-OA4YK3LP-Mu16f_2g.js +30 -0
- package/dist/assets/diagram-WEI45ONY-3BTJg43I.js +41 -0
- package/dist/assets/ebnfDiagram-CCIWWBDH-BGl2hs1X.js +1 -0
- package/dist/assets/erDiagram-Q63AITRT-D03B1rgc.js +85 -0
- package/dist/assets/flowDiagram-23GEKE2U-BCaZJGGE.js +156 -0
- package/dist/assets/ganttDiagram-NO4QXBWP-DrTSQR9G.js +292 -0
- package/dist/assets/gitGraphDiagram-IHSO6WYX-BvrZLcji.js +106 -0
- package/dist/assets/graph-C9eacEi8.js +1 -0
- package/dist/assets/index-B7l8Nsf8.js +1 -0
- package/dist/assets/index-BK7LL53p.js +1 -0
- package/dist/assets/index-CJ6x10Zs.js +2 -0
- package/dist/assets/index-D6btqUwj.js +2 -0
- package/dist/assets/{index-D-MKKw7S.js → index-DAXUzeVz.js} +6 -6
- package/dist/assets/{index-Cjgy2CnG.js → index-DcD9tVKJ.js} +3 -3
- package/dist/assets/{index-DZ7i37eV.js → index-Dzup44Dy.js} +6 -6
- package/dist/assets/index-JEgWBCoB.js +1 -0
- package/dist/assets/index-J_xWyk3Q.js +1 -0
- package/dist/assets/infoDiagram-FWYZ7A6U-Bw9k-wkS.js +2 -0
- package/dist/assets/init-Gi6I4Gst.js +1 -0
- package/dist/assets/ishikawaDiagram-FXEZZL3T-C2oVKtw0.js +70 -0
- package/dist/assets/journeyDiagram-5HDEW3XC-pRpwSEa5.js +139 -0
- package/dist/assets/kanban-definition-HUTT4EX6-CYq_poR1.js +89 -0
- package/dist/assets/katex-C5jXJg4s.js +257 -0
- package/dist/assets/layout-DEXfKzaS.js +1 -0
- package/dist/assets/linear-DLT2RlFJ.js +1 -0
- package/dist/assets/{main-DIf9R6Jx.js → main-06kmV-SQ.js} +125 -125
- package/dist/assets/main-BzGnAbiA.css +1 -0
- package/dist/assets/map-Czzmt4hB.js +1 -0
- package/dist/assets/mermaid.core-DmOBz9SE.js +314 -0
- package/dist/assets/mindmap-definition-LN4V7U3C-DzucjpI_.js +96 -0
- package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/assets/pegDiagram-2B236MQR-CIf_bLf4.js +1 -0
- package/dist/assets/pieDiagram-ENE6RG2P-Dh9HXeSf.js +39 -0
- package/dist/assets/quadrantDiagram-ABIIQ3AL-B5hZRZ5w.js +7 -0
- package/dist/assets/railroadDiagram-RFXS5EU6-B1oWAO1u.js +1 -0
- package/dist/assets/requirementDiagram-TGXJPOKE-Cg7bjm4O.js +84 -0
- package/dist/assets/sankeyDiagram-HTMAVEWB-TLCrcbtk.js +40 -0
- package/dist/assets/sequenceDiagram-DBY2YBRQ-BD3b_psw.js +162 -0
- package/dist/assets/sizeCapture-X5ZJPWSS-D26nx1uQ.js +1 -0
- package/dist/assets/stateDiagram-2N3HPSRC-CIwRQUnK.js +1 -0
- package/dist/assets/stateDiagram-v2-6OUMAXLB-C5qcZ4o1.js +1 -0
- package/dist/assets/swimlanes-5IMT3BWC-DYbes851.js +2 -0
- package/dist/assets/swimlanesDiagram-G3AALYLV-Ke-NRRIa.js +8 -0
- package/dist/assets/timeline-definition-FHXFAJF6-Fr9U6JU6.js +120 -0
- package/dist/assets/{vendor-three-Chj50gSY.js → vendor-three-3OKhI9bz.js} +1 -1
- package/dist/assets/vennDiagram-L72KCM5P-Cns-KLq7.js +34 -0
- package/dist/assets/wardleyDiagram-EHGQE667-DHA7rD9Z.js +78 -0
- package/dist/assets/{web-DDxnPoTK.js → web-B7c8sthS.js} +1 -1
- package/dist/assets/{web-DhZ0XCan.js → web-C05qFIA-.js} +1 -1
- package/dist/assets/{web-Dlc8Nyra.js → web-Dja1kfLs.js} +1 -1
- package/dist/assets/xychartDiagram-FW5EYKEG-DCnL05Wq.js +7 -0
- package/dist/build-info.json +1 -1
- package/dist/index.html +3 -3
- package/dist/src/packages/server/claude/runner/watchdog.js +27 -0
- package/dist/src/packages/server/codex/app-server/codex-app-server-runner.js +34 -4
- package/dist/src/packages/server/data/builtin-skills/index.js +2 -0
- package/dist/src/packages/server/data/builtin-skills/mermaid-diagrams.js +76 -0
- package/dist/src/packages/server/integrations/gmail/gmail-client.js +73 -5
- package/dist/src/packages/server/integrations/gmail/gmail-routes.js +9 -4
- package/dist/src/packages/server/integrations/google-auth/token-health.js +196 -0
- package/dist/src/packages/server/integrations/google-calendar/calendar-client.js +61 -6
- package/dist/src/packages/server/integrations/google-calendar/calendar-routes.js +9 -4
- package/dist/src/packages/server/integrations/google-drive/drive-client.js +61 -6
- package/dist/src/packages/server/integrations/google-drive/drive-routes.js +9 -4
- package/dist/src/packages/server/opencode/server/opencode-server-process.js +102 -7
- package/dist/src/packages/server/opencode/server/opencode-server-runner.js +13 -0
- package/dist/src/packages/server/services/agent-service.js +7 -0
- package/dist/src/packages/server/services/runtime-events.js +1 -0
- package/package.json +2 -1
- package/dist/assets/BossSpawnModal-Dj9ayWfR.js +0 -1
- package/dist/assets/ControlsModal-ki85jvDA.js +0 -1
- package/dist/assets/DockerLogsModal-CeIuKlvk.js +0 -2
- package/dist/assets/GoogleOAuthSetup-Bh-Cy-dE.js +0 -236
- package/dist/assets/IntegrationsPanel-DHjpWEFF.js +0 -2
- package/dist/assets/RestoreArchivedAreaModal-Du1f8Urv.js +0 -1
- package/dist/assets/Scene2DCanvas-BTnpyyK6.js +0 -1
- package/dist/assets/SceneManager-owoMSHKT.js +0 -104
- package/dist/assets/SpawnModal-Cww_6dcz.js +0 -1
- package/dist/assets/StatisticsModal-Dl5loLLI.js +0 -1
- package/dist/assets/SubordinateAssignmentModal-DefQL38f.js +0 -1
- package/dist/assets/index-B5iakYkB.js +0 -1
- package/dist/assets/index-CbJ-R04c.js +0 -2
- package/dist/assets/index-CcHBNDP_.js +0 -2
- package/dist/assets/index-DG7HgtQn.js +0 -1
- package/dist/assets/index-Fcs4x2Vj.js +0 -1
- package/dist/assets/index-g0yAcpoy.js +0 -1
- package/dist/assets/main-Dnp-3iMX.css +0 -1
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { google } from 'googleapis';
|
|
8
8
|
import { loadConfig, updateConfig } from './drive-config.js';
|
|
9
|
+
import { getTokenHealth, needsReauth, notifyTokenRotated, onTokenRotated, probeTokenHealth, reportGoogleApiError, reportGoogleApiSuccess, startTokenHealthMonitor, } from '../google-auth/token-health.js';
|
|
9
10
|
import { Readable } from 'stream';
|
|
10
11
|
// ─── State ───
|
|
11
12
|
let ctx = null;
|
|
@@ -22,6 +23,30 @@ const SCOPES = [
|
|
|
22
23
|
];
|
|
23
24
|
const REDIRECT_PATH = '/api/drive/auth/callback';
|
|
24
25
|
let oauth2Client = null;
|
|
26
|
+
/**
|
|
27
|
+
* Build an OAuth2 client whose every outbound call updates shared token health.
|
|
28
|
+
*
|
|
29
|
+
* Every Drive and Docs call made with `auth: oauth2Client` funnels through this one
|
|
30
|
+
* `request()` method, so wrapping it here means a revoked token is detected the moment
|
|
31
|
+
* an agent actually touches Drive — no waiting for the next background probe — without
|
|
32
|
+
* instrumenting each of the ~15 API call sites.
|
|
33
|
+
*/
|
|
34
|
+
function createOAuthClient(clientId, clientSecret, redirectUri) {
|
|
35
|
+
const client = new google.auth.OAuth2(clientId, clientSecret, redirectUri);
|
|
36
|
+
const originalRequest = client.request.bind(client);
|
|
37
|
+
client.request = (async (opts) => {
|
|
38
|
+
try {
|
|
39
|
+
const result = await originalRequest(opts);
|
|
40
|
+
reportGoogleApiSuccess();
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
reportGoogleApiError(err);
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return client;
|
|
49
|
+
}
|
|
25
50
|
function getRedirectUri() {
|
|
26
51
|
if (!ctx)
|
|
27
52
|
throw new Error('Google Drive not initialized');
|
|
@@ -44,10 +69,16 @@ export async function init(integrationCtx) {
|
|
|
44
69
|
ctx.log.info('Google Drive missing OAuth credentials, skipping init');
|
|
45
70
|
return;
|
|
46
71
|
}
|
|
47
|
-
oauth2Client =
|
|
72
|
+
oauth2Client = createOAuthClient(clientId, clientSecret, getRedirectUri());
|
|
48
73
|
oauth2Client.setCredentials({ refresh_token: refreshToken });
|
|
49
74
|
driveApi = google.drive({ version: 'v3', auth: oauth2Client });
|
|
50
75
|
docsApi = google.docs({ version: 'v1', auth: oauth2Client });
|
|
76
|
+
// Constructing the client above proves nothing — it just wraps the token string.
|
|
77
|
+
// Probe Google (and keep probing) so an expired token is reflected in getStatus().
|
|
78
|
+
startTokenHealthMonitor(ctx);
|
|
79
|
+
// Re-read the shared refresh token if the user re-consents via Gmail or Calendar,
|
|
80
|
+
// otherwise this client keeps using the token it was seeded with here.
|
|
81
|
+
onTokenRotated('google-drive', () => init(integrationCtx));
|
|
51
82
|
ctx.log.info('Google Drive initialized');
|
|
52
83
|
}
|
|
53
84
|
export async function shutdown() {
|
|
@@ -61,16 +92,36 @@ export function getStatus() {
|
|
|
61
92
|
const hasCredentials = !!(ctx?.secrets.get('GOOGLE_CLIENT_ID') &&
|
|
62
93
|
ctx?.secrets.get('GOOGLE_CLIENT_SECRET') &&
|
|
63
94
|
ctx?.secrets.get('GOOGLE_REFRESH_TOKEN'));
|
|
95
|
+
const health = getTokenHealth();
|
|
96
|
+
const reauth = hasCredentials && needsReauth(health);
|
|
97
|
+
// Having credentials on disk is necessary but not sufficient — a revoked refresh
|
|
98
|
+
// token is still three non-empty strings. Only report connected when Google's last
|
|
99
|
+
// verdict wasn't a rejection. An 'unreachable' probe (offline host) is deliberately
|
|
100
|
+
// NOT treated as a rejection: it would push users into a pointless re-consent flow.
|
|
101
|
+
const wired = config.enabled && hasCredentials && driveApi !== null;
|
|
102
|
+
let error;
|
|
103
|
+
if (!hasCredentials && config.enabled)
|
|
104
|
+
error = 'Missing OAuth credentials';
|
|
105
|
+
else if (reauth)
|
|
106
|
+
error = health.error;
|
|
64
107
|
return {
|
|
65
|
-
authenticated: Boolean(driveApi && hasCredentials),
|
|
66
|
-
connected:
|
|
67
|
-
lastChecked: Date.now(),
|
|
68
|
-
error
|
|
108
|
+
authenticated: Boolean(driveApi && hasCredentials) && !reauth,
|
|
109
|
+
connected: wired && !reauth,
|
|
110
|
+
lastChecked: health.checkedAt || Date.now(),
|
|
111
|
+
error,
|
|
112
|
+
needsReauth: reauth,
|
|
113
|
+
tokenState: hasCredentials ? health.state : undefined,
|
|
69
114
|
};
|
|
70
115
|
}
|
|
71
116
|
export function isConfigured() {
|
|
72
117
|
return driveApi !== null;
|
|
73
118
|
}
|
|
119
|
+
/** Force a live refresh_token exchange against Google and return the updated status. */
|
|
120
|
+
export async function probeToken() {
|
|
121
|
+
if (ctx)
|
|
122
|
+
await probeTokenHealth(ctx, { force: true });
|
|
123
|
+
return getStatus();
|
|
124
|
+
}
|
|
74
125
|
// ─── OAuth ───
|
|
75
126
|
export function getAuthUrl() {
|
|
76
127
|
if (!oauth2Client) {
|
|
@@ -79,7 +130,7 @@ export function getAuthUrl() {
|
|
|
79
130
|
if (!clientId || !clientSecret || !ctx) {
|
|
80
131
|
throw new Error('Google Drive OAuth not configured');
|
|
81
132
|
}
|
|
82
|
-
oauth2Client =
|
|
133
|
+
oauth2Client = createOAuthClient(clientId, clientSecret, getRedirectUri());
|
|
83
134
|
}
|
|
84
135
|
return oauth2Client.generateAuthUrl({
|
|
85
136
|
access_type: 'offline',
|
|
@@ -99,6 +150,10 @@ export async function handleAuthCallback(code) {
|
|
|
99
150
|
docsApi = google.docs({ version: 'v1', auth: oauth2Client });
|
|
100
151
|
// Auto-enable the integration after successful OAuth
|
|
101
152
|
updateConfig({ enabled: true });
|
|
153
|
+
// Fresh consent just produced this token. Clears the 'expired' verdict AND re-arms
|
|
154
|
+
// Gmail and Calendar, whose clients still hold the old refresh token — all three
|
|
155
|
+
// share this one secret, so one consent must repair all three.
|
|
156
|
+
await notifyTokenRotated();
|
|
102
157
|
ctx.log.info('Google Drive OAuth complete. Drive initialized.');
|
|
103
158
|
}
|
|
104
159
|
// ─── Files CRUD ───
|
|
@@ -283,10 +283,15 @@ router.get('/search', async (req, res) => {
|
|
|
283
283
|
}
|
|
284
284
|
});
|
|
285
285
|
// ─── Status & Auth ───
|
|
286
|
-
// GET /api/drive/status — Get Google Drive auth status
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
286
|
+
// GET /api/drive/status — Get Google Drive auth status.
|
|
287
|
+
// `?probe=1` forces a live refresh_token exchange against Google instead of reusing
|
|
288
|
+
// the cached verdict — the settings UI uses it to verify the token on open, so a
|
|
289
|
+
// revoked token can't keep rendering as "Connected".
|
|
290
|
+
router.get('/status', async (req, res) => {
|
|
291
|
+
if (req.query.probe === '1' || req.query.probe === 'true') {
|
|
292
|
+
await driveClient.probeToken();
|
|
293
|
+
}
|
|
294
|
+
res.json(driveClient.getStatus());
|
|
290
295
|
});
|
|
291
296
|
// GET /api/drive/auth/url — Get OAuth authorization URL
|
|
292
297
|
router.get('/auth/url', (_req, res) => {
|
|
@@ -162,17 +162,37 @@ export class OpencodeServerProcess {
|
|
|
162
162
|
}
|
|
163
163
|
// ---- HTTP helpers --------------------------------------------------------
|
|
164
164
|
async httpJson(method, path, body) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
165
|
+
// Retry ONCE on a transport failure, but ONLY for idempotent GETs. A POST
|
|
166
|
+
// (send message / create session) must NEVER auto-retry: a transport error
|
|
167
|
+
// does NOT prove the request was undelivered. Undici surfaces a stale
|
|
168
|
+
// keep-alive reset AND a `UND_ERR_HEADERS_TIMEOUT` (request delivered, daemon
|
|
169
|
+
// still working the turn) both as `TypeError: fetch failed` — indistinguishable
|
|
170
|
+
// here — so resending a POST can double-post the user's prompt (it did:
|
|
171
|
+
// agents saw the same message twice). GETs carry no such side effect.
|
|
172
|
+
let res;
|
|
173
|
+
try {
|
|
174
|
+
res = await this.doFetch(method, path, body);
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
if (method !== 'GET' || !isTransportError(err))
|
|
178
|
+
throw err;
|
|
179
|
+
log.warn(`GET ${path} transport error (${describeError(err)}); retrying once on a fresh connection`);
|
|
180
|
+
await sleep(100);
|
|
181
|
+
res = await this.doFetch(method, path, body);
|
|
182
|
+
}
|
|
170
183
|
if (!res.ok) {
|
|
171
184
|
throw new Error(`${method} ${path} → ${res.status} ${res.statusText}`);
|
|
172
185
|
}
|
|
173
186
|
const text = await res.text();
|
|
174
187
|
return text ? JSON.parse(text) : null;
|
|
175
188
|
}
|
|
189
|
+
doFetch(method, path, body) {
|
|
190
|
+
return fetch(`${this.baseUrl}${path}`, {
|
|
191
|
+
method,
|
|
192
|
+
headers: body !== undefined ? { 'Content-Type': 'application/json' } : undefined,
|
|
193
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
176
196
|
/** Create a session (optionally scoped to a working directory). */
|
|
177
197
|
async createSession(directory) {
|
|
178
198
|
const body = {};
|
|
@@ -184,12 +204,64 @@ export class OpencodeServerProcess {
|
|
|
184
204
|
throw new Error('opencode session create returned no id');
|
|
185
205
|
return id;
|
|
186
206
|
}
|
|
187
|
-
/**
|
|
207
|
+
/**
|
|
208
|
+
* Send a prompt to a session. opencode holds this POST open for the ENTIRE
|
|
209
|
+
* turn (it doesn't send response headers until the turn finishes) while the
|
|
210
|
+
* output streams over SSE. undici's 300s default headersTimeout would trip
|
|
211
|
+
* `UND_ERR_HEADERS_TIMEOUT` on any turn >5min and falsely error the agent —
|
|
212
|
+
* and that error MUST NOT be retried, because the prompt already landed, so a
|
|
213
|
+
* resend double-posts the user's message. So this one request uses a dedicated
|
|
214
|
+
* Node http request with NO timeout and a fresh (non-pooled) socket: it blocks
|
|
215
|
+
* harmlessly until turn end (SSE drives output + completion), rejects only on a
|
|
216
|
+
* genuine connection failure (surfaced once, never retried), and can't reuse a
|
|
217
|
+
* stale keep-alive socket. Everything else stays on the quick fetch path.
|
|
218
|
+
*/
|
|
188
219
|
sendPrompt(sessionId, text, model) {
|
|
189
220
|
const body = { parts: [{ type: 'text', text }] };
|
|
190
221
|
if (model)
|
|
191
222
|
body.model = model;
|
|
192
|
-
return this.
|
|
223
|
+
return this.postLongLived(`/session/${sessionId}/message`, body).then(() => undefined);
|
|
224
|
+
}
|
|
225
|
+
/** POST with no read timeout on a fresh socket — for the turn-length message send. */
|
|
226
|
+
postLongLived(path, body) {
|
|
227
|
+
return new Promise((resolve, reject) => {
|
|
228
|
+
if (this.port == null) {
|
|
229
|
+
reject(new Error('opencode server not connected (no port)'));
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const payload = JSON.stringify(body);
|
|
233
|
+
const req = http.request({
|
|
234
|
+
host: '127.0.0.1',
|
|
235
|
+
port: this.port,
|
|
236
|
+
path,
|
|
237
|
+
method: 'POST',
|
|
238
|
+
agent: false, // fresh socket every send — no keep-alive pool to go stale
|
|
239
|
+
headers: {
|
|
240
|
+
'Content-Type': 'application/json',
|
|
241
|
+
'Content-Length': Buffer.byteLength(payload),
|
|
242
|
+
},
|
|
243
|
+
}, (res) => {
|
|
244
|
+
let data = '';
|
|
245
|
+
res.setEncoding('utf8');
|
|
246
|
+
res.on('data', (c) => { data += c; });
|
|
247
|
+
res.on('aborted', () => reject(new Error(`POST ${path} → connection aborted before completion`)));
|
|
248
|
+
res.on('end', () => {
|
|
249
|
+
const status = res.statusCode ?? 0;
|
|
250
|
+
if (status < 200 || status >= 300) {
|
|
251
|
+
reject(new Error(`POST ${path} → ${status} ${res.statusMessage ?? ''}`.trim()));
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
resolve(data ? JSON.parse(data) : null);
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
req.on('error', reject);
|
|
263
|
+
req.end(payload);
|
|
264
|
+
});
|
|
193
265
|
}
|
|
194
266
|
async abort(sessionId) {
|
|
195
267
|
try {
|
|
@@ -283,3 +355,26 @@ function findFreePort() {
|
|
|
283
355
|
function sleep(ms) {
|
|
284
356
|
return new Promise((r) => setTimeout(r, ms));
|
|
285
357
|
}
|
|
358
|
+
/**
|
|
359
|
+
* True for a transport/connection failure (no HTTP response was received), as
|
|
360
|
+
* opposed to a rejected request. `fetch` throws a `TypeError` ("fetch failed")
|
|
361
|
+
* whose `cause` carries the undici socket error (ECONNRESET / UND_ERR_SOCKET /
|
|
362
|
+
* ECONNREFUSED) — the dead-keep-alive-socket case we retry.
|
|
363
|
+
*/
|
|
364
|
+
function isTransportError(err) {
|
|
365
|
+
if (!(err instanceof TypeError))
|
|
366
|
+
return false;
|
|
367
|
+
const cause = err.cause;
|
|
368
|
+
const code = cause?.code;
|
|
369
|
+
if (code && ['ECONNRESET', 'ECONNREFUSED', 'UND_ERR_SOCKET', 'EPIPE', 'ETIMEDOUT'].includes(code)) {
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
// Fall back to the message: undici surfaces the generic "fetch failed" here.
|
|
373
|
+
return /fetch failed/i.test(err.message);
|
|
374
|
+
}
|
|
375
|
+
function describeError(err) {
|
|
376
|
+
const cause = err?.cause;
|
|
377
|
+
const code = cause?.code;
|
|
378
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
379
|
+
return code ? `${msg} [${code}]` : msg;
|
|
380
|
+
}
|
|
@@ -273,6 +273,19 @@ export class OpencodeServerRunner {
|
|
|
273
273
|
const msg = err instanceof Error ? err.message : String(err);
|
|
274
274
|
log.error(`sendPrompt failed for ${agentId.slice(0, 8)}: ${msg}`);
|
|
275
275
|
this.callbacks.onError(agentId, `OpenCode prompt failed: ${msg}`);
|
|
276
|
+
// Reset the turn state so a failed send does NOT wedge the runner.
|
|
277
|
+
// Without this, turnState stays 'processing' forever — only a
|
|
278
|
+
// `step_complete` SSE event clears it, and that never comes for a turn
|
|
279
|
+
// that never started — so every later message is queued indefinitely and
|
|
280
|
+
// "never arrives" (the user-visible symptom). Guard it: only recover when
|
|
281
|
+
// THIS state is still the agent's current in-flight turn, so we don't
|
|
282
|
+
// double-drain into a concurrent turn (if a step_complete already advanced
|
|
283
|
+
// it) or act on a state a stop()/new turn already replaced. drainQueue
|
|
284
|
+
// re-queues safely when the daemon is unreachable, so this can't spin.
|
|
285
|
+
if (this.agents.get(agentId) === state && state.turnState === 'processing') {
|
|
286
|
+
state.turnState = 'waiting_for_input';
|
|
287
|
+
this.drainQueue(agentId, state);
|
|
288
|
+
}
|
|
276
289
|
}
|
|
277
290
|
}
|
|
278
291
|
drainQueue(agentId, state) {
|
|
@@ -491,6 +491,13 @@ export function updateAgent(id, updates, updateActivity = true) {
|
|
|
491
491
|
if (enteredIdleState && !('latestTodos' in normalizedUpdates)) {
|
|
492
492
|
normalizedUpdates.latestTodos = undefined;
|
|
493
493
|
}
|
|
494
|
+
// Drop the stored error message once the agent recovers from error to any
|
|
495
|
+
// other status (new command → working, recovery init, turn complete → idle),
|
|
496
|
+
// so the status-badge hover doesn't show a stale error after recovery.
|
|
497
|
+
const leftErrorState = agent.status === 'error' && nextStatus !== 'error';
|
|
498
|
+
if (leftErrorState && !('lastError' in normalizedUpdates)) {
|
|
499
|
+
normalizedUpdates.lastError = undefined;
|
|
500
|
+
}
|
|
494
501
|
// When an agent goes idle (process finished / run complete) clear any *transient*
|
|
495
502
|
// tracking status so the board doesn't show a phantom 'working'/'thinking' agent.
|
|
496
503
|
// Only 'working' (longer-running work) and 'thinking' (start-of-turn) are transient;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tide-commander",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.167.0",
|
|
4
4
|
"description": "Visual multi-agent orchestrator and manager for Claude Code with 3D/2D interface",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -87,6 +87,7 @@
|
|
|
87
87
|
"i18next": "^26.0.3",
|
|
88
88
|
"i18next-browser-languagedetector": "^8.2.1",
|
|
89
89
|
"i18next-http-backend": "^3.0.2",
|
|
90
|
+
"mermaid": "^11.16.0",
|
|
90
91
|
"mssql": "^12.4.0",
|
|
91
92
|
"multer": "^2.1.1",
|
|
92
93
|
"mysql2": "^3.16.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as Be,aC as Re,b6 as Oe,b5 as Te,r as t,_ as re,S as G,bj as O,k as Fe,s as S,ba as W,A as de,bk as C,j as s,a9 as y,bb as Pe,bd as ze,I as T,be as K,aT as A,aR as F,bh as H,$ as Ue}from"./main-DIf9R6Jx.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";function ue(u){const w=C.filter($=>!u.has(`Boss ${$}`));return w.length===0?`Boss ${C[Math.floor(Math.random()*C.length)]}-${Date.now()%1e3}`:`Boss ${w[Math.floor(Math.random()*w.length)]}`}function Ke({isOpen:u,onClose:w,onSpawnStart:$,onSpawnEnd:P,spawnPosition:me,spawnAreaId:g}){const{t:n}=Be(["terminal","common"]),J=Re(),c=Oe(),E=Te(),[m,p]=t.useState(""),[L,z]=t.useState(()=>re(G.LAST_CWD)),[d,I]=t.useState("boss"),[X,V]=t.useState(!1),[pe,_]=t.useState(!1),[Y,he]=t.useState(!0),[Q,we]=t.useState("bypass"),[o,D]=t.useState("claude"),[f,N]=t.useState({fullAuto:!0,sandbox:"workspace-write",approvalMode:"on-request",search:!1}),[Z,xe]=t.useState("claude-opus-4-8[1m]"),[ee,fe]=t.useState("gpt-5.6-luna"),[k,B]=t.useState(new Set),[se,U]=t.useState(new Set),[h,be]=t.useState(""),[v,je]=t.useState(""),[ae,ge]=t.useState(""),R=t.useRef(null),q=t.useRef(!1),ne=t.useRef(!1),b=t.useMemo(()=>E.filter(e=>e.enabled),[E]),le=t.useMemo(()=>{if(!v.trim())return b;const e=v.toLowerCase();return b.filter(a=>a.name.toLowerCase().includes(e)||a.description.toLowerCase().includes(e)||a.slug.toLowerCase().includes(e))},[b,v]),Ne=t.useMemo(()=>{var a;const e=c.find(l=>l.id===d);return(a=e==null?void 0:e.defaultSkillIds)!=null&&a.length?E.filter(l=>e.defaultSkillIds.includes(l.id)):[]},[c,d,E]),ve=["full-notifications","streaming-exec","task-label","report-task-to-boss","agent-tracking","agent-memory","send-message-to-agent"];t.useEffect(()=>{if(u&&!ne.current){if(b.length>0){const l=b.filter(i=>ve.includes(i.slug)).map(i=>i.id);l.length>0&&U(new Set(l))}if(re(G.DEFAULT_AGENT_CLASS)==="random"){const i=[...Object.keys(O).filter(j=>j!=="boss"),...c.map(j=>j.id)];i.length>0&&I(i[Math.floor(Math.random()*i.length)])}}ne.current=u},[u,b,c]);const Se=t.useCallback(e=>{U(a=>{const l=new Set(a);return l.has(e)?l.delete(e):l.add(e),l})},[]),r=t.useMemo(()=>c.find(e=>e.id===d),[c,d]),Ce=t.useMemo(()=>{if(r!=null&&r.model)return r.model},[r]),ke=t.useMemo(()=>{if(r!=null&&r.customModelPath)return Fe(`/api/custom-models/${r.id}`)},[r]),Me=r==null?void 0:r.modelScale,ye=t.useMemo(()=>r?"scout":d==="boss"?"architect":d,[d,r]);t.useEffect(()=>{if(!u||!g)return;const e=S.getState().areas.get(g);if(e!=null&&e.directories&&e.directories.length>0){z(e.directories[0]);return}const a=Array.from(S.getState().agents.values()).filter(x=>{var M;return((M=S.getAreaForAgent(x.id))==null?void 0:M.id)===g&&x.cwd});if(a.length===0)return;const l=new Map;for(const x of a)l.set(x.cwd,(l.get(x.cwd)||0)+1);let i="",j=0;for(const[x,M]of l)M>j&&(i=x,j=M);i&&z(i)},[u,g]);const te=t.useMemo(()=>Array.from(J.values()).filter(e=>!e.isBoss&&e.class!=="boss"&&!e.bossId),[J]),ie=t.useMemo(()=>{if(!h.trim())return c;const e=h.toLowerCase();return c.filter(a=>a.name.toLowerCase().includes(e)||a.description.toLowerCase().includes(e)||a.id.toLowerCase().includes(e))},[c,h]),ce=t.useMemo(()=>{if(!h.trim())return W;const e=h.toLowerCase();return W.filter(a=>{const l=de[a.id];return l?a.name.toLowerCase().includes(e)||a.id.toLowerCase().includes(e)||l.description.toLowerCase().includes(e):!1})},[h]),oe=t.useMemo(()=>{if(!h.trim())return!0;const e=h.toLowerCase(),a=O.boss;return"boss".includes(e)||a.description.toLowerCase().includes(e)},[h]);t.useEffect(()=>{if(u&&!q.current){q.current=!0;const e=new Set(Array.from(S.getState().agents.values()).map(l=>l.name)),a=c.find(l=>l.id===d);if(a){const l=C.filter(i=>!e.has(`${a.name} ${i}`));if(l.length===0){const i=C[Math.floor(Math.random()*C.length)];p(`${a.name} ${i}-${Date.now()%1e3}`)}else p(`${a.name} ${l[Math.floor(Math.random()*l.length)]}`)}else p(ue(e));B(new Set),R.current&&(R.current.focus(),R.current.select())}else u||(q.current=!1)},[u]),t.useEffect(()=>{if(!u)return;const e=c.find(a=>a.id===d);if(e)if(m.startsWith("Boss ")){const a=m.substring(5);p(`${e.name} ${a}`)}else{const a=c.find(l=>m.startsWith(l.name+" "));if(a){const l=m.substring(a.name.length+1);p(`${e.name} ${l}`)}else p(`${e.name} ${m}`)}else{const a=c.find(l=>m.startsWith(l.name+" "));if(a){const l=m.substring(a.name.length+1);p(`Boss ${l}`)}else m.startsWith("Boss ")||p(`Boss ${m}`)}},[d]);const Ae=()=>{if(_(!1),!L.trim()){_(!0);return}if(!m.trim()){const l=new Set(Array.from(S.getState().agents.values()).map(i=>i.name));p(ue(l));return}Ue(G.LAST_CWD,L),$(),window.__spawnModalAreaContext=g?{areaId:g}:null;const e=ae.trim()||void 0,a=Array.from(se);S.spawnBossAgent(m.trim(),d,L.trim(),me||void 0,Array.from(k),o==="claude"?Y:!1,Q,o,o==="codex"?f:void 0,o==="codex"?ee:void 0,o==="claude"?Z:void 0,e,a),p(""),B(new Set),U(new Set),P(),w()},$e=()=>{V(!1),p(""),B(new Set),P(),w()},Ee=()=>{V(!1),_(!0),P()};t.useEffect(()=>(window.__bossSpawnModalSuccess=$e,window.__bossSpawnModalError=Ee,()=>{delete window.__bossSpawnModalSuccess,delete window.__bossSpawnModalError}),[m]);const Le=e=>{e.target===e.currentTarget&&w()},Ie=e=>{e.key==="Escape"&&w()},_e=e=>{const a=new Set(k);a.has(e)?a.delete(e):a.add(e),B(a)};if(!u)return null;const De=O.boss;return s.jsx("div",{className:`modal-overlay ${u?"visible":""}`,onClick:Le,onKeyDown:Ie,children:s.jsxs("div",{className:"modal boss-spawn-modal",children:[s.jsxs("div",{className:"modal-header",children:[s.jsx(y,{classId:"boss",size:22,className:"boss-header-icon"}),n("terminal:spawn.deployBossTitle")]}),s.jsxs("div",{className:"modal-body spawn-modal-body",children:[s.jsxs("div",{className:"spawn-top-section",children:[s.jsx("div",{className:"spawn-preview-compact",children:s.jsx(Pe,{agentClass:ye,modelFile:Ce,customModelUrl:ke,modelScale:Me,width:100,height:120})}),s.jsxs("div",{className:"spawn-class-section",children:[s.jsx("div",{className:"spawn-class-label",children:n("terminal:spawn.bossClass")}),c.length+W.length+1>6&&s.jsx("input",{type:"text",className:"spawn-input class-search-input",placeholder:n("terminal:spawn.filterClasses"),value:h,onChange:e=>be(e.target.value)}),s.jsxs("div",{className:"class-selector-inline",children:[ie.map(e=>s.jsxs("button",{className:`class-chip ${d===e.id?"selected":""}`,onClick:()=>I(e.id),title:e.description,children:[s.jsx(y,{classId:e.id,size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:e.name})]},e.id)),oe&&s.jsxs("button",{className:`class-chip ${d==="boss"?"selected":""}`,onClick:()=>I("boss"),title:De.description,children:[s.jsx(y,{classId:"boss",size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:n("terminal:spawn.bossClassName")})]}),ce.map(e=>{const a=de[e.id];return a?s.jsxs("button",{className:`class-chip ${d===e.id?"selected":""}`,onClick:()=>I(e.id),title:a.description,children:[s.jsx(y,{classId:e.id,size:18,className:"class-chip-icon"}),s.jsx("span",{className:"class-chip-name",children:e.name})]},e.id):null}),h&&ie.length===0&&!oe&&ce.length===0&&s.jsx("div",{className:"class-search-empty",children:n("terminal:spawn.noClassesMatch",{query:h})})]})]})]}),s.jsxs("div",{className:"spawn-form-section",children:[s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.name")}),s.jsx("input",{ref:R,type:"text",className:"spawn-input",placeholder:n("terminal:spawn.bossNamePlaceholder"),value:m,onChange:e=>p(e.target.value)})]}),s.jsxs("div",{className:"spawn-field spawn-field-wide",children:[s.jsx("label",{className:"spawn-label",children:n("terminal:spawn.workingDir")}),s.jsx(ze,{value:L,onChange:e=>{z(e),_(!1)},placeholder:n("terminal:spawn.workingDirPlaceholder"),className:"spawn-input",hasError:pe,directoriesOnly:!0})]})]}),s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.runtime")}),s.jsxs("div",{className:"spawn-select-row",children:[s.jsxs("button",{className:`spawn-select-btn ${o==="claude"?"selected":""}`,onClick:()=>D("claude"),title:n("terminal:spawn.useClaudeCli"),children:[s.jsx("img",{src:"/assets/claude.ico",alt:"Claude",className:"spawn-provider-icon"}),s.jsx("span",{children:"Claude"})]}),s.jsxs("button",{className:`spawn-select-btn ${o==="codex"?"selected":""}`,onClick:()=>D("codex"),title:n("terminal:spawn.useCodexCli"),children:[s.jsx("img",{src:"/assets/codex.ico",alt:"Codex",className:"spawn-provider-icon"}),s.jsx("span",{children:"Codex"})]}),s.jsxs("button",{className:`spawn-select-btn spawn-select-btn--opencode ${o==="opencode"?"selected":""}`,onClick:()=>D("opencode"),title:"Use OpenCode CLI (multi-provider)",children:[s.jsx("span",{children:s.jsx(T,{name:"status-pending",size:14,weight:"fill",color:"#4ade80"})}),s.jsx("span",{children:"OpenCode"})]}),s.jsxs("button",{className:`spawn-select-btn spawn-select-btn--grok ${o==="grok"?"selected":""}`,onClick:()=>D("grok"),title:"Use Grok CLI (headless)",children:[s.jsx("img",{src:"/assets/grok.png",alt:"Grok",className:"spawn-provider-icon"}),s.jsx("span",{children:"Grok"})]})]})]}),s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.permissions")}),s.jsx("div",{className:"spawn-select-row",children:Object.keys(K).map(e=>s.jsxs("button",{className:`spawn-select-btn ${Q===e?"selected":""}`,onClick:()=>we(e),title:K[e].description,children:[s.jsx("span",{children:s.jsx(T,{name:e==="bypass"?"bolt":"lock",size:14})}),s.jsx("span",{children:K[e].label})]},e))})]})]}),s.jsxs("div",{className:"spawn-form-row",children:[s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.model")}),o==="claude"?s.jsx("div",{className:"spawn-select-row spawn-select-row--wrap",children:Object.keys(A).filter(e=>!A[e].deprecated).map(e=>s.jsxs("button",{className:`spawn-select-btn ${Z===e?"selected":""}`,onClick:()=>xe(e),title:A[e].description,children:[s.jsx("span",{children:A[e].icon}),s.jsx("span",{children:A[e].label})]},e))}):o==="codex"?s.jsx("div",{className:"spawn-select-row spawn-select-row--codex-models",children:Object.keys(F).map(e=>s.jsxs("button",{className:`spawn-select-btn ${ee===e?"selected":""}`,onClick:()=>fe(e),title:F[e].description,children:[s.jsx("span",{children:F[e].icon}),s.jsx("span",{children:F[e].label})]},e))}):o==="opencode"?s.jsx("input",{type:"text",className:"spawn-input",defaultValue:"minimax/MiniMax-M1-80k",placeholder:"provider/model (e.g., minimax/MiniMax-M1-80k)"}):o==="grok"?s.jsx("div",{className:"spawn-inline-hint",children:"grok-4.5"}):s.jsx("div",{className:"spawn-inline-hint",children:n("terminal:spawn.codex.configuration")})]}),s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("common:labels.browser")}),s.jsx("div",{className:"spawn-form-row spawn-options-row",children:s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:Y,onChange:e=>he(e.target.checked),disabled:o!=="claude"}),s.jsx("span",{children:n("terminal:spawn.chromeBrowser")})]})})]})]}),o==="codex"&&s.jsx("div",{className:"spawn-form-row",children:s.jsxs("div",{className:"spawn-field",children:[s.jsx("label",{className:"spawn-label",children:n("terminal:spawn.codex.config")}),s.jsxs("div",{className:"spawn-options-row",style:{display:"flex",flexDirection:"column",gap:8},children:[s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:f.fullAuto!==!1,onChange:e=>N(a=>({...a,fullAuto:e.target.checked}))}),s.jsx("span",{children:n("terminal:spawn.codex.useFullAuto")})]}),s.jsxs("label",{className:"spawn-checkbox",children:[s.jsx("input",{type:"checkbox",checked:!!f.search,onChange:e=>N(a=>({...a,search:e.target.checked}))}),s.jsx("span",{children:n("terminal:spawn.codex.enableSearch")})]}),f.fullAuto===!1&&s.jsxs(s.Fragment,{children:[s.jsxs("select",{className:"spawn-input",value:f.sandbox||"workspace-write",onChange:e=>N(a=>({...a,sandbox:e.target.value})),children:[s.jsx("option",{value:"read-only",children:n("terminal:spawn.codex.sandboxReadOnly")}),s.jsx("option",{value:"workspace-write",children:n("terminal:spawn.codex.sandboxWorkspaceWrite")}),s.jsx("option",{value:"danger-full-access",children:n("terminal:spawn.codex.sandboxDangerFullAccess")})]}),s.jsxs("select",{className:"spawn-input",value:f.approvalMode||"on-request",onChange:e=>N(a=>({...a,approvalMode:e.target.value})),children:[s.jsx("option",{value:"untrusted",children:n("terminal:spawn.codex.approvalsUntrusted")}),s.jsx("option",{value:"on-failure",children:n("terminal:spawn.codex.approvalsOnFailure")}),s.jsx("option",{value:"on-request",children:n("terminal:spawn.codex.approvalsOnRequest")}),s.jsx("option",{value:"never",children:n("terminal:spawn.codex.approvalsNever")})]})]}),s.jsx("input",{type:"text",className:"spawn-input",placeholder:n("terminal:spawn.codex.profileOptional"),value:f.profile||"",onChange:e=>N(a=>({...a,profile:e.target.value||void 0}))}),s.jsxs("select",{className:"spawn-input",value:f.reasoningEffort||"",onChange:e=>N(a=>({...a,reasoningEffort:e.target.value||void 0})),children:[s.jsx("option",{value:"",children:n("terminal:spawn.codex.reasoningEffortDefault")}),Object.keys(H).map(e=>s.jsxs("option",{value:e,children:[H[e].icon," ",n("terminal:spawn.codex.reasoningEffort"),": ",H[e].label]},e))]})]})]})}),b.length>0&&s.jsxs("div",{className:"spawn-skills-section",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.skills")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",n("common:labels.optional"),")"]})]}),b.length>6&&s.jsx("input",{type:"text",className:"spawn-input skill-search-input",placeholder:n("terminal:spawn.filterSkills"),value:v,onChange:e=>je(e.target.value)}),s.jsxs("div",{className:"spawn-skills-inline",children:[le.map(e=>{const a=se.has(e.id);return Ne.some(i=>i.id===e.id)?null:s.jsxs("button",{className:`spawn-skill-chip ${a?"selected":""}`,onClick:()=>Se(e.id),title:e.description,children:[a&&s.jsx("span",{className:"spawn-skill-check",children:s.jsx(T,{name:"check",size:12})}),s.jsx("span",{children:e.name}),e.builtin&&s.jsx("span",{className:"spawn-skill-builtin",children:"TC"})]},e.id)}),v&&le.length===0&&s.jsx("div",{className:"skill-search-empty",children:n("terminal:spawn.noSkillsMatch",{query:v})})]})]}),s.jsxs("div",{className:"spawn-custom-instructions-section",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.customInstructions")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",n("common:labels.optional"),")"]})]}),s.jsx("textarea",{className:"spawn-input spawn-textarea",placeholder:n("terminal:spawn.customInstructionsBossPlaceholder"),value:ae,onChange:e=>ge(e.target.value),rows:3})]}),s.jsxs("div",{className:"spawn-subordinates-section",children:[s.jsxs("label",{className:"spawn-label",children:[n("terminal:spawn.initialSubordinates")," ",s.jsxs("span",{className:"spawn-label-hint",children:["(",n("common:labels.optional"),")"]})]}),s.jsx("div",{className:"subordinates-selector-compact",children:te.length===0?s.jsx("div",{className:"subordinates-empty",children:n("terminal:spawn.noAvailableAgents")}):te.map(e=>{const a=k.has(e.id),l=O[e.class],i=c.find(x=>x.id===e.class),j=l||i||{color:"#888888"};return s.jsxs("button",{className:`subordinate-chip ${a?"selected":""}`,onClick:()=>_e(e.id),children:[a&&s.jsx("span",{className:"subordinate-check",children:s.jsx(T,{name:"check",size:12})}),s.jsx("span",{className:"subordinate-chip-icon",style:{color:j.color},children:s.jsx(y,{classId:e.class,size:16})}),s.jsx("span",{className:"subordinate-chip-name",children:e.name})]},e.id)})}),k.size>0&&s.jsxs("div",{className:"subordinates-count",children:[k.size," ",n("common:labels.selected").toLowerCase()]})]})]})]}),s.jsxs("div",{className:"modal-footer",children:[s.jsx("button",{className:"btn btn-secondary",onClick:w,children:n("common:buttons.cancel")}),s.jsx("button",{className:"btn btn-boss",onClick:Ae,disabled:X,children:n(X?"common:buttons.deploying":"common:buttons2.deployBoss")})]})]})})}export{Ke as BossSpawnModal};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as K,cZ as Q,aC as J,c_ as W,c$ as ee,r as u,aq as se,n as te,cO as D,d0 as z,d1 as ae,j as e,d2 as ne,C as re,s as g,d3 as R,d4 as V}from"./main-DIf9R6Jx.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";const G={global:"terminal:controls.contextGlobal",commander:"terminal:controls.contextCommander",toolbox:"terminal:controls.contextToolbox"},le={global:"terminal:controls.contextGlobalDesc",commander:"terminal:controls.contextCommanderDesc",toolbox:"terminal:controls.contextToolboxDesc"},U={camera:["camera-pan","camera-orbit","camera-rotate","camera-zoom","camera-tilt"],interaction:["primary-action","selection-box","context-menu","move-command"]},oe={camera:"terminal:controls.cameraControls",interaction:"terminal:controls.interaction"};function pe({isOpen:s,onClose:r}){const{t:a}=K(["terminal","common"]),l=Q(),o=J(),h=W(),N=ee(),[x,C]=u.useState("keyboard"),[b,v]=u.useState(""),[p,j]=u.useState("all"),[m,f]=u.useState(!1),[c,d]=u.useState(null),[k,w]=u.useState(null),Y=se.useRef(null),{handleMouseDown:Z,handleClick:_}=te(r);if(u.useEffect(()=>{if(!s||m)return;const t=n=>{n.key==="Escape"&&(n.preventDefault(),n.stopPropagation(),r())};return document.addEventListener("keydown",t,!0),()=>document.removeEventListener("keydown",t,!0)},[s,r,m]),u.useEffect(()=>{s||(v(""),f(!1),d(null))},[s]),u.useEffect(()=>{if(!s||!m)return;const t=n=>{if(n.key==="Escape"){n.preventDefault(),n.stopPropagation(),f(!1),d(null);return}if(["Control","Alt","Shift","Meta"].includes(n.key))return;n.preventDefault(),n.stopPropagation();let i=n.key;n.code.startsWith("Key")&&n.code.length===4?i=n.code.charAt(3).toLowerCase():n.code.startsWith("Digit")&&n.code.length===6?i=n.code.charAt(5):n.code==="Space"&&(i="Space"),d({key:i,modifiers:{ctrl:n.ctrlKey,alt:n.altKey,shift:n.shiftKey,meta:n.metaKey}})};return document.addEventListener("keydown",t,!0),()=>document.removeEventListener("keydown",t,!0)},[s,m]),!s)return null;const F=l.filter(t=>{const n=a(`terminal:controls.shortcuts.${t.id}.name`,{defaultValue:t.name}),i=a(`terminal:controls.shortcuts.${t.id}.description`,{defaultValue:t.description});if(m&&c){const A=S=>S===" "||S==="Space"?"Space":S.length===1?S.toLowerCase():S,B=A(t.key),L=A(c.key);if(!(L.length===1&&/^[a-zA-Z]$/.test(B)?`Key${B.toUpperCase()}`==`Key${L.toUpperCase()}`:B===L))return!1;const M=t.modifiers,T=c.modifiers;return(M.ctrl||!1)===(T.ctrl||!1)&&(M.alt||!1)===(T.alt||!1)&&(M.shift||!1)===(T.shift||!1)&&(M.meta||!1)===(T.meta||!1)}if(!b)return!0;const y=b.toLowerCase();return n.toLowerCase().includes(y)||i.toLowerCase().includes(y)||D(t).toLowerCase().includes(y)}),E=Array.from(o.values()).map(t=>t).filter(t=>t.shortcut&&t.shortcut.trim().length>0).filter(t=>{const n=z(t.shortcut).toLowerCase();if(m&&c){const y={key:c.key,code:c.key.length===1&&/^[a-zA-Z]$/.test(c.key)?`Key${c.key.toUpperCase()}`:c.key.length===1&&/^[0-9]$/.test(c.key)?`Digit${c.key}`:c.key==="Space"?"Space":c.key,ctrlKey:!!c.modifiers.ctrl,altKey:!!c.modifiers.alt,shiftKey:!!c.modifiers.shift,metaKey:!!c.modifiers.meta};return ae(y,t.shortcut)}if(!b)return!0;const i=b.toLowerCase();return t.name.toLowerCase().includes(i)||n.toLowerCase().includes(i)}),P=F.reduce((t,n)=>(t[n.context]||(t[n.context]=[]),t[n.context].push(n),t),{}),I=(t,n)=>{g.updateShortcut(t,n)},$=()=>{w(x)},X=()=>{k==="keyboard"?g.resetShortcuts():(k==="mouse"||k==="trackpad")&&g.resetMouseControls()},q=k==="keyboard"?"terminal:controls.confirmResetKeyboard":k==="mouse"?"terminal:controls.confirmResetMouse":"terminal:controls.confirmResetTrackpad",O=["global","commander","toolbox"],H=h.bindings.reduce((t,n)=>(U.camera.includes(n.action)?t.camera.push(n):U.interaction.includes(n.action)&&t.interaction.push(n),t),{camera:[],interaction:[]});return e.jsxs("div",{className:"shortcuts-modal-overlay",onMouseDown:Z,onClick:_,children:[e.jsxs("div",{className:"shortcuts-modal controls-modal",children:[e.jsxs("div",{className:"shortcuts-modal-header",children:[e.jsxs("div",{className:"shortcuts-modal-title",children:[e.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("circle",{cx:"12",cy:"12",r:"3"}),e.jsx("path",{d:"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"})]}),e.jsx("span",{children:a("terminal:controls.title")})]}),e.jsx("button",{className:"shortcuts-modal-close",onClick:r,children:"×"})]}),e.jsxs("div",{className:"controls-main-tabs",children:[e.jsxs("button",{className:`controls-main-tab ${x==="keyboard"?"active":""}`,onClick:()=>C("keyboard"),children:[e.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("rect",{x:"2",y:"4",width:"20",height:"16",rx:"2"}),e.jsx("path",{d:"M6 8h.01M10 8h.01M14 8h.01M18 8h.01M6 12h.01M18 12h.01M8 16h8"})]}),a("terminal:controls.keyboard")]}),e.jsxs("button",{className:`controls-main-tab ${x==="mouse"?"active":""}`,onClick:()=>C("mouse"),children:[e.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("rect",{x:"6",y:"3",width:"12",height:"18",rx:"6"}),e.jsx("line",{x1:"12",y1:"7",x2:"12",y2:"11"})]}),a("terminal:controls.mouse")]}),e.jsxs("button",{className:`controls-main-tab ${x==="trackpad"?"active":""}`,onClick:()=>C("trackpad"),children:[e.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("rect",{x:"2",y:"4",width:"20",height:"16",rx:"2"}),e.jsx("circle",{cx:"12",cy:"12",r:"3"})]}),a("terminal:controls.trackpad")]})]}),x==="keyboard"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"shortcuts-modal-toolbar",children:[m?e.jsxs("div",{className:"shortcuts-search find-by-shortcut-active",children:[e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("rect",{x:"2",y:"4",width:"20",height:"16",rx:"2"}),e.jsx("path",{d:"M6 8h.01M10 8h.01M14 8h.01M18 8h.01M6 12h.01M18 12h.01M8 16h8"})]}),c?e.jsxs("span",{className:"find-by-shortcut-display",children:[D({key:c.key,modifiers:c.modifiers}),e.jsx("button",{className:"shortcuts-search-clear",onClick:()=>d(null),children:"×"})]}):e.jsx("span",{className:"find-by-shortcut-prompt",children:a("terminal:controls.pressKeyCombination")})]}):e.jsxs("div",{className:"shortcuts-search",children:[e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("circle",{cx:"11",cy:"11",r:"8"}),e.jsx("path",{d:"M21 21l-4.35-4.35"})]}),e.jsx("input",{ref:Y,type:"text",placeholder:a("terminal:controls.searchShortcuts"),value:b,onChange:t=>v(t.target.value),autoFocus:!0}),b&&e.jsx("button",{className:"shortcuts-search-clear",onClick:()=>v(""),children:"×"})]}),e.jsx("button",{className:`shortcuts-find-by-key-btn ${m?"active":""}`,onClick:()=>{f(!m),d(null),v("")},title:a(m?"terminal:controls.switchToTextSearch":"terminal:controls.findByPressingKeys"),children:e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[e.jsx("rect",{x:"2",y:"4",width:"20",height:"16",rx:"2"}),e.jsx("path",{d:"M6 8h.01M10 8h.01M14 8h.01M18 8h.01M6 12h.01M18 12h.01M8 16h8"})]})}),e.jsx("button",{className:"shortcuts-reset-all-btn",onClick:$,children:a("common:buttons.reset")})]}),e.jsxs("div",{className:"shortcuts-context-tabs",children:[e.jsxs("button",{className:`shortcuts-context-tab ${p==="all"?"active":""}`,onClick:()=>j("all"),children:[a("common:labels.all"),e.jsx("span",{className:"shortcuts-context-tab-count",children:F.length})]}),O.map(t=>{var i;const n=((i=P[t])==null?void 0:i.length)||0;return e.jsxs("button",{className:`shortcuts-context-tab ${p===t?"active":""}`,onClick:()=>j(t),children:[a(G[t]),e.jsx("span",{className:"shortcuts-context-tab-count",children:n})]},t)})]}),e.jsxs("div",{className:"shortcuts-modal-content",children:[O.map(t=>{const n=P[t]||[];return n.length===0||p!=="all"&&p!==t?null:e.jsxs("div",{className:"shortcuts-context-group",children:[p==="all"&&e.jsxs("div",{className:"shortcuts-context-header",children:[e.jsx("span",{className:"shortcuts-context-label",children:a(G[t])}),e.jsx("span",{className:"shortcuts-context-description",children:a(le[t])})]}),e.jsx("div",{className:"shortcuts-grid",children:n.map(i=>e.jsxs("div",{className:"shortcut-item",children:[e.jsxs("div",{className:"shortcut-item-info",children:[e.jsx("span",{className:"shortcut-item-name",children:a(`terminal:controls.shortcuts.${i.id}.name`,{defaultValue:i.name})}),e.jsx("span",{className:"shortcut-item-description",children:a(`terminal:controls.shortcuts.${i.id}.description`,{defaultValue:i.description})})]}),e.jsx(ne,{shortcut:i,onUpdate:y=>I(i.id,y)})]},i.id))})]},t)}),F.length===0&&E.length===0&&e.jsx("div",{className:"shortcuts-empty",children:m?c?e.jsx("p",{children:a("terminal:controls.noShortcutBoundTo",{keys:D({key:c.key,modifiers:c.modifiers})})}):e.jsx("p",{children:a("terminal:controls.pressKeyCombinationToFind")}):e.jsx("p",{children:a("terminal:controls.noShortcutsFound",{query:b})})}),E.length>0&&(p==="all"||p==="global")&&e.jsxs("div",{className:"shortcuts-context-group",children:[p==="all"&&e.jsxs("div",{className:"shortcuts-context-header",children:[e.jsx("span",{className:"shortcuts-context-label",children:"Agent Terminal Shortcuts"}),e.jsx("span",{className:"shortcuts-context-description",children:"Per-agent global shortcuts that open the guake terminal"})]}),e.jsx("div",{className:"shortcuts-grid",children:E.map(t=>e.jsxs("div",{className:"shortcut-item",children:[e.jsxs("div",{className:"shortcut-item-info",children:[e.jsx("span",{className:"shortcut-item-name",children:t.name}),e.jsx("span",{className:"shortcut-item-description",children:"Open terminal for this agent"})]}),e.jsx("div",{className:"key-capture-container",children:e.jsx("button",{className:"key-capture-input disabled",disabled:!0,children:e.jsx("span",{className:"key-capture-value",children:z(t.shortcut)})})})]},t.id))})]})]})]}),x==="mouse"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"shortcuts-modal-toolbar",children:[e.jsx("span",{className:"mouse-controls-subtitle",children:a("terminal:controls.cameraAndInteraction")}),e.jsx("button",{className:"shortcuts-reset-all-btn",onClick:$,children:a("common:buttons.reset")})]}),e.jsxs("div",{className:"shortcuts-modal-content mouse-controls-content",children:[e.jsx("div",{className:"mouse-controls-bindings",children:Object.entries(H).map(([t,n])=>e.jsxs("div",{className:"shortcuts-context-group",children:[e.jsx("div",{className:"shortcuts-context-header",children:e.jsx("span",{className:"shortcuts-context-label",children:a(oe[t])})}),e.jsx("div",{className:"shortcuts-grid",children:n.map(i=>e.jsx(ce,{binding:i},i.id))})]},t))}),e.jsxs("div",{className:"shortcuts-context-group",children:[e.jsxs("div",{className:"shortcuts-context-header",children:[e.jsx("span",{className:"shortcuts-context-label",children:a("terminal:controls.sensitivity")}),e.jsx("span",{className:"shortcuts-context-description",children:a("terminal:controls.adjustCameraSpeed")})]}),e.jsx(ie,{sensitivity:h.sensitivity})]})]})]}),x==="trackpad"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"shortcuts-modal-toolbar",children:[e.jsx("span",{className:"mouse-controls-subtitle",children:a("terminal:controls.trackpadGestureSettings")}),e.jsx("button",{className:"shortcuts-reset-all-btn",onClick:$,children:a("common:buttons.reset")})]}),e.jsx("div",{className:"shortcuts-modal-content trackpad-controls-content",children:e.jsx(de,{config:N})})]}),e.jsx("div",{className:"shortcuts-modal-footer",children:e.jsx("span",{className:"shortcuts-modal-hint",children:a(x==="keyboard"?m?"terminal:controls.hintFindByShortcut":"terminal:controls.hintKeyboard":x==="mouse"?"terminal:controls.hintMouse":"terminal:controls.hintTrackpad")})})]}),e.jsx(re,{isOpen:k!==null,title:a("common:buttons.resetToDefaults"),message:a(q),confirmLabel:a("common:buttons.reset"),cancelLabel:a("common:buttons.cancel"),variant:"danger",onConfirm:X,onClose:()=>w(null)})]})}function ce({binding:s}){const{t:r}=K(["terminal"]),a=W(),[l,o]=u.useState(!1),[h,N]=u.useState(null);u.useEffect(()=>{if(!l)return;const j=d=>{d.preventDefault(),d.stopPropagation();const w={0:"left",1:"middle",2:"right",3:"back",4:"forward"}[d.button];w&&N({button:w,modifiers:{ctrl:d.ctrlKey,alt:d.altKey,shift:d.shiftKey,meta:d.metaKey}})},m=d=>{d.key==="Escape"&&(d.preventDefault(),d.stopPropagation(),o(!1),N(null))},f=()=>{h&&R(a.bindings,h,s.id).length===0&&g.updateMouseBinding(s.id,{button:h.button,modifiers:h.modifiers}),o(!1),N(null)},c=setTimeout(()=>{document.addEventListener("mousedown",j,!0),document.addEventListener("keydown",m,!0),document.addEventListener("click",f,!0)},100);return()=>{clearTimeout(c),document.removeEventListener("mousedown",j,!0),document.removeEventListener("keydown",m,!0),document.removeEventListener("click",f,!0)}},[l,h,s.id,a.bindings]);const x=h?R(a.bindings,h,s.id):[],C=r(`terminal:controls.mouseBindings.${s.id}.name`,{defaultValue:s.name}),b=r(`terminal:controls.mouseBindings.${s.id}.description`,{defaultValue:s.description}),v=j=>r(`terminal:controls.mouseButtons.${j}`,{defaultValue:j}),p=h?V({...s,...h},v):V(s,v);return e.jsxs("div",{className:`shortcut-item ${s.enabled?"":"disabled"}`,children:[e.jsxs("div",{className:"shortcut-item-info",children:[e.jsx("span",{className:"shortcut-item-name",children:C}),e.jsx("span",{className:"shortcut-item-description",children:b})]}),e.jsxs("div",{className:"key-capture-container",children:[e.jsx("button",{className:`key-capture-input ${l?"capturing":""} ${x.length>0?"conflict":""}`,onClick:()=>o(!0),children:l?h?e.jsx("span",{className:"key-capture-value",style:{color:"#f1fa8c"},children:p}):e.jsx("span",{style:{color:"#6272a4",fontStyle:"italic"},children:r("terminal:controls.clickToCapture")}):e.jsx("span",{className:"key-capture-value",children:p})}),x.length>0&&e.jsxs("span",{className:"key-capture-conflict",children:[r("terminal:controls.conflicts"),": ",x.map(j=>r(`terminal:controls.mouseBindings.${j.id}.name`,{defaultValue:j.name})).join(", ")]})]})]})}function ie({sensitivity:s}){const{t:r}=K(["terminal"]),a=u.useCallback((l,o)=>{g.updateCameraSensitivity({[l]:o})},[]);return e.jsxs("div",{className:"sensitivity-inline-settings",children:[e.jsxs("div",{className:"sensitivity-sliders",children:[e.jsxs("div",{className:"sensitivity-slider-row",children:[e.jsx("label",{children:r("terminal:controls.panSpeed")}),e.jsx("input",{type:"range",min:"0.1",max:"3",step:"0.1",value:s.panSpeed,onChange:l=>a("panSpeed",parseFloat(l.target.value))}),e.jsxs("span",{className:"sensitivity-slider-value",children:[s.panSpeed.toFixed(1),"x"]})]}),e.jsxs("div",{className:"sensitivity-slider-row",children:[e.jsx("label",{children:r("terminal:controls.orbitSpeed")}),e.jsx("input",{type:"range",min:"0.1",max:"3",step:"0.1",value:s.orbitSpeed,onChange:l=>a("orbitSpeed",parseFloat(l.target.value))}),e.jsxs("span",{className:"sensitivity-slider-value",children:[s.orbitSpeed.toFixed(1),"x"]})]}),e.jsxs("div",{className:"sensitivity-slider-row",children:[e.jsx("label",{children:r("terminal:controls.zoomSpeed")}),e.jsx("input",{type:"range",min:"0.1",max:"3",step:"0.1",value:s.zoomSpeed,onChange:l=>a("zoomSpeed",parseFloat(l.target.value))}),e.jsxs("span",{className:"sensitivity-slider-value",children:[s.zoomSpeed.toFixed(1),"x"]})]}),e.jsxs("div",{className:"sensitivity-slider-row",children:[e.jsx("label",{children:r("terminal:controls.smoothing")}),e.jsx("input",{type:"range",min:"0",max:"1",step:"0.1",value:s.smoothing,onChange:l=>a("smoothing",parseFloat(l.target.value))}),e.jsx("span",{className:"sensitivity-slider-value",children:s.smoothing.toFixed(1)})]})]}),e.jsxs("div",{className:"sensitivity-checkboxes-inline",children:[e.jsxs("label",{className:"sensitivity-checkbox-inline",children:[e.jsx("input",{type:"checkbox",checked:s.invertPanX,onChange:l=>a("invertPanX",l.target.checked)}),e.jsx("span",{children:r("terminal:controls.invertPanX")})]}),e.jsxs("label",{className:"sensitivity-checkbox-inline",children:[e.jsx("input",{type:"checkbox",checked:s.invertPanY,onChange:l=>a("invertPanY",l.target.checked)}),e.jsx("span",{children:r("terminal:controls.invertPanY")})]}),e.jsxs("label",{className:"sensitivity-checkbox-inline",children:[e.jsx("input",{type:"checkbox",checked:s.invertOrbitX,onChange:l=>a("invertOrbitX",l.target.checked)}),e.jsx("span",{children:r("terminal:controls.invertOrbitX")})]}),e.jsxs("label",{className:"sensitivity-checkbox-inline",children:[e.jsx("input",{type:"checkbox",checked:s.invertOrbitY,onChange:l=>a("invertOrbitY",l.target.checked)}),e.jsx("span",{children:r("terminal:controls.invertOrbitY")})]})]})]})}function de({config:s}){const{t:r}=K(["terminal"]),a=u.useCallback((o,h)=>{g.updateTrackpadConfig({[o]:h})},[]),l=u.useCallback((o,h)=>{g.updateTrackpadConfig({sensitivity:{[o]:h}})},[]);return e.jsxs("div",{className:"trackpad-settings",children:[e.jsxs("div",{className:"shortcuts-context-group",children:[e.jsxs("div",{className:"shortcuts-context-header",children:[e.jsx("span",{className:"shortcuts-context-label",children:r("terminal:controls.trackpadGestures")}),e.jsx("span",{className:"shortcuts-context-description",children:r("terminal:controls.enableTrackpadSupport")})]}),e.jsx("div",{className:"trackpad-toggle-row",children:e.jsxs("label",{className:"trackpad-toggle",children:[e.jsx("input",{type:"checkbox",checked:s.enabled,onChange:o=>a("enabled",o.target.checked)}),e.jsx("span",{className:"trackpad-toggle-label",children:r("terminal:controls.enableTrackpadGestures")})]})})]}),e.jsxs("div",{className:"shortcuts-context-group",children:[e.jsxs("div",{className:"shortcuts-context-header",children:[e.jsx("span",{className:"shortcuts-context-label",children:r("terminal:controls.gestureControls")}),e.jsx("span",{className:"shortcuts-context-description",children:r("terminal:controls.enableDisableGestures")})]}),e.jsxs("div",{className:"trackpad-gestures-grid",children:[e.jsxs("label",{className:`trackpad-gesture-item ${s.enabled?"":"disabled"}`,children:[e.jsx("input",{type:"checkbox",checked:s.pinchToZoom,onChange:o=>a("pinchToZoom",o.target.checked),disabled:!s.enabled}),e.jsxs("div",{className:"trackpad-gesture-info",children:[e.jsx("span",{className:"trackpad-gesture-name",children:r("terminal:controls.pinchToZoom")}),e.jsx("span",{className:"trackpad-gesture-desc",children:r("terminal:controls.pinchToZoomDesc")})]})]}),e.jsxs("label",{className:`trackpad-gesture-item ${s.enabled?"":"disabled"}`,children:[e.jsx("input",{type:"checkbox",checked:s.twoFingerPan,onChange:o=>a("twoFingerPan",o.target.checked),disabled:!s.enabled}),e.jsxs("div",{className:"trackpad-gesture-info",children:[e.jsx("span",{className:"trackpad-gesture-name",children:r("terminal:controls.twoFingerPan")}),e.jsx("span",{className:"trackpad-gesture-desc",children:r("terminal:controls.twoFingerPanDesc")})]})]}),e.jsxs("label",{className:`trackpad-gesture-item ${s.enabled?"":"disabled"}`,children:[e.jsx("input",{type:"checkbox",checked:s.shiftTwoFingerOrbit,onChange:o=>a("shiftTwoFingerOrbit",o.target.checked),disabled:!s.enabled}),e.jsxs("div",{className:"trackpad-gesture-info",children:[e.jsx("span",{className:"trackpad-gesture-name",children:r("terminal:controls.shiftTwoFingerOrbit")}),e.jsx("span",{className:"trackpad-gesture-desc",children:r("terminal:controls.shiftTwoFingerOrbitDesc")})]})]})]})]}),e.jsxs("div",{className:"shortcuts-context-group",children:[e.jsxs("div",{className:"shortcuts-context-header",children:[e.jsx("span",{className:"shortcuts-context-label",children:r("terminal:controls.sensitivity")}),e.jsx("span",{className:"shortcuts-context-description",children:r("terminal:controls.adjustGestureSensitivity")})]}),e.jsxs("div",{className:"trackpad-sensitivity-sliders",children:[e.jsxs("div",{className:`trackpad-slider-row ${!s.enabled||!s.pinchToZoom?"disabled":""}`,children:[e.jsx("label",{children:r("terminal:controls.zoom")}),e.jsx("input",{type:"range",min:"0.1",max:"3",step:"0.1",value:s.sensitivity.zoom,onChange:o=>l("zoom",parseFloat(o.target.value)),disabled:!s.enabled||!s.pinchToZoom}),e.jsxs("span",{className:"trackpad-slider-value",children:[s.sensitivity.zoom.toFixed(1),"x"]})]}),e.jsxs("div",{className:`trackpad-slider-row ${!s.enabled||!s.twoFingerPan?"disabled":""}`,children:[e.jsx("label",{children:r("terminal:controls.pan")}),e.jsx("input",{type:"range",min:"0.1",max:"3",step:"0.1",value:s.sensitivity.pan,onChange:o=>l("pan",parseFloat(o.target.value)),disabled:!s.enabled||!s.twoFingerPan}),e.jsxs("span",{className:"trackpad-slider-value",children:[s.sensitivity.pan.toFixed(1),"x"]})]}),e.jsxs("div",{className:`trackpad-slider-row ${!s.enabled||!s.shiftTwoFingerOrbit?"disabled":""}`,children:[e.jsx("label",{children:r("terminal:controls.orbit")}),e.jsx("input",{type:"range",min:"0.1",max:"3",step:"0.1",value:s.sensitivity.orbit,onChange:o=>l("orbit",parseFloat(o.target.value)),disabled:!s.enabled||!s.shiftTwoFingerOrbit}),e.jsxs("span",{className:"trackpad-slider-value",children:[s.sensitivity.orbit.toFixed(1),"x"]})]})]})]})]})}export{pe as ControlsModal};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{u as p,f as u,h as S,r as n,s as o,j as x}from"./main-DIf9R6Jx.js";import{L as k}from"./LogViewerModal-DKYB8dHo.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";function h({building:e,isOpen:t,onClose:i,onMinimize:m}){var a;const{t:c}=p(["terminal"]),g=u(),d=S(),r=g.get(e.id)||"",l=d.has(e.id);n.useEffect(()=>{var s;return t&&((s=e.docker)!=null&&s.enabled)&&o.startLogStreaming(e.id,200),()=>{e.id&&o.stopLogStreaming(e.id)}},[t,e.id,(a=e.docker)==null?void 0:a.enabled]);const L=n.useMemo(()=>r.split(`
|
|
2
|
-
`).map((s,f)=>({text:s,lineNumber:f+1})),[r]);return x.jsx(k,{isOpen:t,onClose:i,onMinimize:m,title:`${e.name} - ${c("terminal:logs.dockerLogs")}`,icon:"🐳",lines:L,isStreaming:l,onClear:()=>o.clearStreamingLogs(e.id)})}export{h as DockerLogsModal};
|