tide-commander 1.97.0 → 1.99.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/dist/assets/{BossLogsModal-CT25hD17.js → BossLogsModal-CDel834o.js} +1 -1
- package/dist/assets/{BossSpawnModal-9rS7AFkZ.js → BossSpawnModal-BB9wL5VV.js} +1 -1
- package/dist/assets/{ControlsModal-D-mymoM7.js → ControlsModal-D5RE5MvT.js} +1 -1
- package/dist/assets/{DockerLogsModal-Ae-ZCeeP.js → DockerLogsModal-B27P1JpZ.js} +1 -1
- package/dist/assets/{EmbeddedEditor-DLOOpM0K.js → EmbeddedEditor-DP1jqsT_.js} +1 -1
- package/dist/assets/{GmailOAuthSetup-C9NLhWLo.js → GmailOAuthSetup-DvuL5G8Q.js} +1 -1
- package/dist/assets/{GoogleOAuthSetup-1kzgrPV6.js → GoogleOAuthSetup-CG6bSCjv.js} +1 -1
- package/dist/assets/{IframeModal-DKS0IFsr.js → IframeModal-ClnUGmJV.js} +1 -1
- package/dist/assets/{IntegrationsPanel-CBvKOeud.js → IntegrationsPanel-0vdfxZRq.js} +2 -2
- package/dist/assets/{LogViewerModal-Dlt8JfVg.js → LogViewerModal-DLQlrZ4O.js} +1 -1
- package/dist/assets/{MonitoringModal-BM1IEZv6.js → MonitoringModal-DiC9TNCy.js} +1 -1
- package/dist/assets/{PM2LogsModal-B1-HUHWZ.js → PM2LogsModal-BgPrnaP5.js} +1 -1
- package/dist/assets/{RestoreArchivedAreaModal-DXmYo7fp.js → RestoreArchivedAreaModal-CIN1OrOW.js} +1 -1
- package/dist/assets/{Scene2DCanvas-CuUxSaPb.js → Scene2DCanvas-Bap6brvv.js} +1 -1
- package/dist/assets/{SceneManager-UD3IHY20.js → SceneManager-CidCW0PR.js} +1 -1
- package/dist/assets/{SkillsPanel-DjRBVrO2.js → SkillsPanel-DHQTPaP2.js} +1 -1
- package/dist/assets/{SlackMultiInstanceSetup-Csp81Dqn.js → SlackMultiInstanceSetup-CQK4D89W.js} +1 -1
- package/dist/assets/{SpawnModal-dg0mH3d9.js → SpawnModal-Cx_k3HHC.js} +1 -1
- package/dist/assets/{SubordinateAssignmentModal-CeBPRNNX.js → SubordinateAssignmentModal-C1DOv51H.js} +1 -1
- package/dist/assets/TriggerManagerPanel-jP5RBK2L.js +9 -0
- package/dist/assets/{WorkflowEditorPanel-IIsptZgp.js → WorkflowEditorPanel-Dh6mZ8M4.js} +1 -1
- package/dist/assets/{index-h-IcmGfB.js → index-B-ttQFx4.js} +2 -2
- package/dist/assets/index-BXnThzaG.js +11 -0
- package/dist/assets/index-CK8NcQSU.css +1 -0
- package/dist/assets/{index-CNDUxsGy.js → index-CYwFXTQZ.js} +1 -1
- package/dist/assets/{index-sDgBtEgH.js → index-Cwlm-Pqi.js} +3 -3
- package/dist/assets/index-D96LXKm4.js +1 -0
- package/dist/assets/{index-BGh9tRSy.js → index-DP5sMNS9.js} +1 -1
- package/dist/assets/{index-CsyPNc8u.js → index-DfEbuBH8.js} +1 -1
- package/dist/assets/{index-DEI-vrXk.js → index-DsKaX6TJ.js} +1 -1
- package/dist/assets/{index-CIqkVLo1.js → index-enJvXAbe.js} +1 -1
- package/dist/assets/main-B7wf_xU_.js +214 -0
- package/dist/assets/main-DLzFxLC1.css +1 -0
- package/dist/assets/{web-BmPSJLwQ.js → web-BHmmnvF7.js} +1 -1
- package/dist/assets/{web-Dggt4D4N.js → web-IGuhG0xr.js} +1 -1
- package/dist/assets/{web-BgPjNMBK.js → web-SOehUGgT.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/locales/en/config.json +60 -1
- package/dist/locales/en/terminal.json +10 -0
- package/dist/src/packages/server/claude/backend.js +42 -0
- package/dist/src/packages/server/claude/permission-prompt-server.mjs +188 -0
- package/dist/src/packages/server/claude/runner/process-lifecycle.js +3 -0
- package/dist/src/packages/server/claude/runner/stdout-pipeline.js +8 -0
- package/dist/src/packages/server/claude/runner/tmux-helper.js +14 -0
- package/dist/src/packages/server/data/event-queries.js +143 -1
- package/dist/src/packages/server/data/migrations/007_whatsapp_messages.sql +48 -0
- package/dist/src/packages/server/index.js +1 -0
- package/dist/src/packages/server/integrations/gmail/gmail-client.js +139 -24
- package/dist/src/packages/server/integrations/gmail/gmail-routes.js +162 -0
- package/dist/src/packages/server/integrations/whatsapp/whatsapp-routes.js +81 -0
- package/dist/src/packages/server/integrations/whatsapp/whatsapp-trigger-handler.js +29 -0
- package/dist/src/packages/server/routes/agent-prompt.js +57 -0
- package/dist/src/packages/server/routes/index.js +8 -1
- package/dist/src/packages/server/routes/skills.js +193 -0
- package/dist/src/packages/server/routes/system.js +156 -0
- package/dist/src/packages/server/routes/trigger-routes.js +74 -17
- package/dist/src/packages/server/routes/webhook-signatures.js +20 -7
- package/dist/src/packages/server/services/agent-prompt-service.js +100 -0
- package/dist/src/packages/server/services/index.js +1 -0
- package/dist/src/packages/server/services/self-update-service.js +191 -0
- package/dist/src/packages/server/websocket/handler.js +2 -1
- package/dist/src/packages/server/websocket/listeners/agent-prompt-listeners.js +13 -0
- package/dist/src/packages/server/websocket/listeners/index.js +2 -0
- package/dist/src/packages/shared/whatsapp-types.js +1 -0
- package/package.json +2 -2
- package/dist/assets/TriggerManagerPanel-D1QPpFhP.js +0 -9
- package/dist/assets/index-BdGz_GAe.css +0 -1
- package/dist/assets/index-CR9w26tq.js +0 -1
- package/dist/assets/index-vJkimYqD.js +0 -1
- package/dist/assets/main-BV_IuaBg.css +0 -1
- package/dist/assets/main-klWBzHh0.js +0 -214
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-Update Service
|
|
3
|
+
*
|
|
4
|
+
* Detects how Tide Commander was installed (global npm/pnpm/yarn/bun vs dev mode)
|
|
5
|
+
* and runs `npm install -g tide-commander@latest` when invoked from the UI.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { spawn } from 'child_process';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { createLogger } from '../utils/logger.js';
|
|
12
|
+
const log = createLogger('SelfUpdate');
|
|
13
|
+
function readPackageJson(dir) {
|
|
14
|
+
try {
|
|
15
|
+
const raw = fs.readFileSync(path.join(dir, 'package.json'), 'utf8');
|
|
16
|
+
return JSON.parse(raw);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function detectPackageManager(installRoot) {
|
|
23
|
+
const lower = installRoot.toLowerCase();
|
|
24
|
+
// Bun: ~/.bun/install/global/node_modules/tide-commander/
|
|
25
|
+
if (lower.includes(`${path.sep}.bun${path.sep}install${path.sep}global${path.sep}`) || lower.includes(`${path.sep}.bun${path.sep}`)) {
|
|
26
|
+
return { pm: 'bun', suggested: 'bun add -g tide-commander@latest' };
|
|
27
|
+
}
|
|
28
|
+
// Pnpm:
|
|
29
|
+
// ~/.local/share/pnpm/global/<N>/node_modules/tide-commander/
|
|
30
|
+
// ~/Library/pnpm/global/...
|
|
31
|
+
// ~/.pnpm/global/...
|
|
32
|
+
if (lower.includes(`${path.sep}pnpm${path.sep}global${path.sep}`) || lower.includes(`${path.sep}.pnpm${path.sep}`)) {
|
|
33
|
+
return { pm: 'pnpm', suggested: 'pnpm add -g tide-commander@latest' };
|
|
34
|
+
}
|
|
35
|
+
// Yarn:
|
|
36
|
+
// ~/.config/yarn/global/node_modules/tide-commander/
|
|
37
|
+
// ~/.yarn/global/...
|
|
38
|
+
if (lower.includes(`${path.sep}yarn${path.sep}global${path.sep}`) || lower.includes(`${path.sep}.yarn${path.sep}`)) {
|
|
39
|
+
return { pm: 'yarn', suggested: 'yarn global add tide-commander@latest' };
|
|
40
|
+
}
|
|
41
|
+
// npm — global prefix typically ends in /lib/node_modules/tide-commander
|
|
42
|
+
// Works for system npm, nvm, asdf, volta, fnm, npm config prefix overrides.
|
|
43
|
+
if (lower.includes(`${path.sep}lib${path.sep}node_modules${path.sep}`)) {
|
|
44
|
+
return { pm: 'npm', suggested: 'npm install -g tide-commander@latest' };
|
|
45
|
+
}
|
|
46
|
+
// Some Windows / non-standard prefixes don't have /lib — fall back to npm
|
|
47
|
+
return { pm: 'npm', suggested: 'npm install -g tide-commander@latest' };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Locate the tide-commander package root on disk (the dir whose package.json
|
|
51
|
+
* has name === "tide-commander"). Returns null if it can't be determined.
|
|
52
|
+
*/
|
|
53
|
+
export function locateInstallRoot() {
|
|
54
|
+
try {
|
|
55
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
56
|
+
// Walk up looking for the nearest package.json named "tide-commander"
|
|
57
|
+
let current = here;
|
|
58
|
+
while (current !== path.dirname(current)) {
|
|
59
|
+
const pkgPath = path.join(current, 'package.json');
|
|
60
|
+
if (fs.existsSync(pkgPath)) {
|
|
61
|
+
const pkg = readPackageJson(current);
|
|
62
|
+
if (pkg?.name === 'tide-commander') {
|
|
63
|
+
return current;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
current = path.dirname(current);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
log.error(`Failed to locate install root: ${err.message}`);
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Returns true when the install root looks like a global npm-style install
|
|
76
|
+
* (lives under a node_modules directory) AND is not the dev/repo checkout
|
|
77
|
+
* (no .git/ at the package root).
|
|
78
|
+
*/
|
|
79
|
+
function isGlobalInstallPath(installRoot) {
|
|
80
|
+
const parent = path.dirname(installRoot);
|
|
81
|
+
const insideNodeModules = path.basename(parent) === 'node_modules';
|
|
82
|
+
const hasGitDir = fs.existsSync(path.join(installRoot, '.git'));
|
|
83
|
+
if (hasGitDir) {
|
|
84
|
+
return { isGlobal: false, reason: 'Install root contains .git/ — running from a repo checkout (dev mode).' };
|
|
85
|
+
}
|
|
86
|
+
if (!insideNodeModules) {
|
|
87
|
+
return { isGlobal: false, reason: 'Install root is not inside a node_modules directory — running from source.' };
|
|
88
|
+
}
|
|
89
|
+
return { isGlobal: true, reason: 'Install root lives under node_modules — looks like a global install.' };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build the full install info snapshot used by the UI.
|
|
93
|
+
*/
|
|
94
|
+
export function getInstallInfo() {
|
|
95
|
+
const installRoot = locateInstallRoot();
|
|
96
|
+
if (!installRoot) {
|
|
97
|
+
return {
|
|
98
|
+
isGlobalInstall: false,
|
|
99
|
+
packageManager: 'unknown',
|
|
100
|
+
installRoot: null,
|
|
101
|
+
currentVersion: 'unknown',
|
|
102
|
+
suggestedManualCommand: null,
|
|
103
|
+
reason: 'Could not locate tide-commander package root on disk.',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const pkg = readPackageJson(installRoot);
|
|
107
|
+
const currentVersion = pkg?.version ?? 'unknown';
|
|
108
|
+
const { isGlobal, reason } = isGlobalInstallPath(installRoot);
|
|
109
|
+
if (!isGlobal) {
|
|
110
|
+
return {
|
|
111
|
+
isGlobalInstall: false,
|
|
112
|
+
packageManager: 'unknown',
|
|
113
|
+
installRoot,
|
|
114
|
+
currentVersion,
|
|
115
|
+
suggestedManualCommand: null,
|
|
116
|
+
reason,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const { pm, suggested } = detectPackageManager(installRoot);
|
|
120
|
+
return {
|
|
121
|
+
isGlobalInstall: true,
|
|
122
|
+
packageManager: pm,
|
|
123
|
+
installRoot,
|
|
124
|
+
currentVersion,
|
|
125
|
+
suggestedManualCommand: suggested,
|
|
126
|
+
reason,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Whether the current install can be auto-updated by this server.
|
|
131
|
+
* Right now only npm-style globals are supported.
|
|
132
|
+
*/
|
|
133
|
+
export function isAutoUpdateSupported(info = getInstallInfo()) {
|
|
134
|
+
return info.isGlobalInstall && info.packageManager === 'npm';
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Run `npm install -g tide-commander@latest`. Streams stdout/stderr via callbacks.
|
|
138
|
+
* Never throws; always resolves with the captured output and exit code.
|
|
139
|
+
*/
|
|
140
|
+
export function runNpmGlobalUpdate(callbacks = {}) {
|
|
141
|
+
return new Promise((resolve) => {
|
|
142
|
+
const args = ['install', '-g', 'tide-commander@latest'];
|
|
143
|
+
// Disable npm fund/audit output noise to keep the log readable
|
|
144
|
+
const env = {
|
|
145
|
+
...process.env,
|
|
146
|
+
npm_config_fund: 'false',
|
|
147
|
+
npm_config_audit: 'false',
|
|
148
|
+
npm_config_progress: 'false',
|
|
149
|
+
};
|
|
150
|
+
log.log(`Running: npm ${args.join(' ')}`);
|
|
151
|
+
const child = spawn('npm', args, {
|
|
152
|
+
env,
|
|
153
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
154
|
+
});
|
|
155
|
+
let stdout = '';
|
|
156
|
+
let stderr = '';
|
|
157
|
+
child.stdout?.on('data', (buf) => {
|
|
158
|
+
const text = buf.toString('utf8');
|
|
159
|
+
stdout += text;
|
|
160
|
+
callbacks.onStdout?.(text);
|
|
161
|
+
});
|
|
162
|
+
child.stderr?.on('data', (buf) => {
|
|
163
|
+
const text = buf.toString('utf8');
|
|
164
|
+
stderr += text;
|
|
165
|
+
callbacks.onStderr?.(text);
|
|
166
|
+
});
|
|
167
|
+
child.on('error', (err) => {
|
|
168
|
+
const message = `Failed to spawn npm: ${err.message}\n`;
|
|
169
|
+
stderr += message;
|
|
170
|
+
callbacks.onStderr?.(message);
|
|
171
|
+
resolve({
|
|
172
|
+
exitCode: -1,
|
|
173
|
+
signal: null,
|
|
174
|
+
stdout,
|
|
175
|
+
stderr,
|
|
176
|
+
permissionDenied: /eacces|eperm|permission/i.test(message),
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
child.on('close', (code, signal) => {
|
|
180
|
+
const combined = `${stdout}\n${stderr}`;
|
|
181
|
+
const permissionDenied = /EACCES|EPERM|permission denied/i.test(combined);
|
|
182
|
+
resolve({
|
|
183
|
+
exitCode: code,
|
|
184
|
+
signal,
|
|
185
|
+
stdout,
|
|
186
|
+
stderr,
|
|
187
|
+
permissionDenied,
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
}
|
|
@@ -6,7 +6,7 @@ import { WebSocketServer, WebSocket } from 'ws';
|
|
|
6
6
|
import { agentService, bossMessageService, customClassService, permissionService, runtimeService, skillService, triggerService, workflowService, } from '../services/index.js';
|
|
7
7
|
import { loadAreas, loadBuildings } from '../data/index.js';
|
|
8
8
|
import { logger } from '../utils/index.js';
|
|
9
|
-
import { setNotificationBroadcast, setExecBroadcast, setFocusAgentBroadcast, setAgentsBroadcast, setTriggerBroadcast, setBuildingsBroadcast } from '../routes/index.js';
|
|
9
|
+
import { setNotificationBroadcast, setExecBroadcast, setFocusAgentBroadcast, setAgentsBroadcast, setTriggerBroadcast, setBuildingsBroadcast, setSkillsBroadcast } from '../routes/index.js';
|
|
10
10
|
import { validateWebSocketAuth, isAuthEnabled } from '../auth/index.js';
|
|
11
11
|
import { incrementWsSent, incrementWsReceived, setWsClientsCount } from '../routes/perf.js';
|
|
12
12
|
import { handleSpawnAgent, handleKillAgent, handleStopAgent, handleClearContext, handleRestoreSession, handleRequestSessionHistory, handleCollapseContext, handleRequestContextStats, handleMoveAgent, handleRemoveAgent, handleRenameAgent, handleUpdateAgentProperties, handleCreateDirectory, handleReattachAgent, } from './handlers/agent-handler.js';
|
|
@@ -302,6 +302,7 @@ export function init(server) {
|
|
|
302
302
|
setAgentsBroadcast(broadcast);
|
|
303
303
|
setTriggerBroadcast(broadcast);
|
|
304
304
|
setBuildingsBroadcast(broadcast);
|
|
305
|
+
setSkillsBroadcast(broadcast);
|
|
305
306
|
log.log('Handler initialized');
|
|
306
307
|
return wss;
|
|
307
308
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { agentPromptService } from '../../services/index.js';
|
|
2
|
+
import { logger } from '../../utils/index.js';
|
|
3
|
+
const log = logger.ws;
|
|
4
|
+
export function setupAgentPromptListeners(ctx) {
|
|
5
|
+
agentPromptService.subscribe((prompt) => {
|
|
6
|
+
log.log(` Broadcasting agent_prompt_request: ${prompt.id} tool=${prompt.tool} agent=${prompt.agentId}`);
|
|
7
|
+
ctx.broadcast({ type: 'agent_prompt_request', payload: prompt });
|
|
8
|
+
});
|
|
9
|
+
agentPromptService.subscribeResolved((requestId, approved) => {
|
|
10
|
+
log.log(` Broadcasting agent_prompt_resolved: ${requestId} approved=${approved}`);
|
|
11
|
+
ctx.broadcast({ type: 'agent_prompt_resolved', payload: { requestId, approved } });
|
|
12
|
+
});
|
|
13
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { agentService } from '../../services/index.js';
|
|
2
2
|
import { setupBossListeners } from './boss-listeners.js';
|
|
3
3
|
import { setupPermissionListeners } from './permission-listeners.js';
|
|
4
|
+
import { setupAgentPromptListeners } from './agent-prompt-listeners.js';
|
|
4
5
|
import { setupRuntimeListeners } from './runtime-listeners.js';
|
|
5
6
|
import { setupSkillListeners } from './skill-listeners.js';
|
|
6
7
|
export function setupServiceListeners(ctx) {
|
|
@@ -25,6 +26,7 @@ export function setupServiceListeners(ctx) {
|
|
|
25
26
|
});
|
|
26
27
|
setupRuntimeListeners(ctx);
|
|
27
28
|
setupPermissionListeners(ctx);
|
|
29
|
+
setupAgentPromptListeners(ctx);
|
|
28
30
|
setupBossListeners(ctx);
|
|
29
31
|
setupSkillListeners(ctx);
|
|
30
32
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tide-commander",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.99.0",
|
|
4
4
|
"description": "Visual multi-agent orchestrator and manager for Claude Code with 3D/2D interface",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"docs:preview": "npm --prefix src/packages/landing run preview",
|
|
26
26
|
"docs:install": "npm --prefix src/packages/landing install",
|
|
27
27
|
"build": "npm run build:types && vite build && npm run build:server",
|
|
28
|
-
"build:server": "tsc -p tsconfig.server.json && cp -r src/packages/server/data/migrations dist/src/packages/server/data/",
|
|
28
|
+
"build:server": "tsc -p tsconfig.server.json && cp -r src/packages/server/data/migrations dist/src/packages/server/data/ && cp src/packages/server/claude/permission-prompt-server.mjs dist/src/packages/server/claude/",
|
|
29
29
|
"preview": "vite preview",
|
|
30
30
|
"setup": "tsx src/packages/server/setup.ts",
|
|
31
31
|
"lint": "eslint src/",
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import{ah as je,r as i,aJ as f,l as g,j as e}from"./main-klWBzHh0.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";const ve=[{value:"webhook",label:"Webhook"},{value:"bitbucket",label:"Bitbucket"},{value:"cron",label:"Cron"},{value:"slack",label:"Slack"},{value:"email",label:"Email"},{value:"jira",label:"Jira"},{value:"whatsapp",label:"WhatsApp"}],ke=[{value:"pullrequest:created",label:"PR created"},{value:"pullrequest:updated",label:"PR updated"},{value:"pullrequest:approved",label:"PR approved"},{value:"pullrequest:unapproved",label:"PR unapproved"},{value:"pullrequest:fulfilled",label:"PR merged"},{value:"pullrequest:rejected",label:"PR declined"},{value:"pullrequest:comment_created",label:"PR comment created"}],Ce=[{value:"structural",label:"Structural",desc:"Field-based matching (fast, free)"},{value:"llm",label:"LLM",desc:"Semantic matching via LLM (flexible, costs tokens)"},{value:"hybrid",label:"Hybrid",desc:"Structural pre-filter + LLM (recommended)"}],Te=[{value:"structural",label:"Structural"},{value:"llm",label:"LLM"}];function Se(v){if(!v)return"";const y=new Date(v);if(Number.isNaN(y.getTime()))return"";const b=w=>String(w).padStart(2,"0");return`${y.getFullYear()}-${b(y.getMonth()+1)}-${b(y.getDate())}T${b(y.getHours())}:${b(y.getMinutes())}`}const O=()=>({name:"",description:"",type:"webhook",agentId:"",promptTemplate:"",enabled:!0,matchMode:"structural",extractionMode:"structural",config:{method:"POST"}});function Ee({isOpen:v,onClose:y}){var q,V,G,X,Y,K,Q,Z,ee,te,le,se,ae,ne,ie,re;const b=je(),[w,oe]=i.useState([]),[C,M]=i.useState("list"),[n,j]=i.useState(O()),[x,E]=i.useState(!1),[A,L]=i.useState(!1),[z,u]=i.useState(null),[P,ce]=i.useState([]),[T,de]=i.useState(null),[B,pe]=i.useState(`{
|
|
2
|
-
|
|
3
|
-
}`),[o,S]=i.useState(null),[I,D]=i.useState(!1),[N,H]=i.useState([]),m=i.useCallback(async()=>{try{const l=await f(g("/api/triggers"));if(l.ok){const s=await l.json();oe(s)}}catch(l){console.error("Failed to load triggers:",l)}},[]),R=i.useCallback(async l=>{try{const s=await f(g(`/api/triggers/${l}/events?limit=20`));if(s.ok){const a=await s.json();ce(a)}}catch(s){console.error("Failed to load trigger history:",s)}},[]);i.useEffect(()=>{v&&m()},[v,m]),i.useEffect(()=>{T&&R(T)},[T,R]);const xe=i.useCallback(async()=>{L(!0),u(null);try{const l=x?g(`/api/triggers/${n.id}`):g("/api/triggers"),h=await f(l,{method:x?"PATCH":"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(!h.ok){const r=await h.json();throw new Error(r.error||"Failed to save trigger")}await m(),M("list"),j(O()),E(!1)}catch(l){u(l instanceof Error?l.message:"Save failed")}finally{L(!1)}},[n,x,m]),ue=i.useCallback(async l=>{try{await f(g(`/api/triggers/${l}`),{method:"DELETE"}),await m()}catch(s){console.error("Failed to delete trigger:",s)}},[m]),he=i.useCallback(async l=>{try{await f(g(`/api/triggers/${l.id}`),{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({enabled:!l.enabled})}),await m()}catch(s){console.error("Failed to toggle trigger:",s)}},[m]),ye=i.useCallback(async l=>{try{await f(g(`/api/triggers/${l}/fire`),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({variables:{}})}),T===l&&await R(l)}catch(s){console.error("Failed to test fire trigger:",s)}},[T,R]),ge=i.useCallback(async()=>{if(n.id){D(!0),S(null);try{let l;try{l=JSON.parse(B)}catch{S({structuralMatch:void 0,extractedVariables:{},wouldFire:!1}),u("Invalid JSON payload");return}const s=await f(g(`/api/triggers/${n.id}/test-match`),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({payload:l})});if(s.ok){const a=await s.json();S(a),u(null)}else{const a=await s.json();u(a.error||"Test match failed")}}catch(l){u(l instanceof Error?l.message:"Test match failed")}finally{D(!1)}}},[n.id,B]),be=i.useCallback(async l=>{var s;try{const a=await f(g("/api/triggers/validate-cron"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({expression:l,timezone:((s=n.config)==null?void 0:s.timezone)||"UTC"})});if(a.ok){const h=await a.json();H(h.valid?h.nextFires:[])}}catch{H([])}},[n]),U=i.useCallback(l=>{l?(j({...l}),E(!0)):(j(O()),E(!1)),S(null),u(null),M("edit")},[]),c=i.useCallback((l,s)=>{j(a=>({...a,[l]:s}))},[]),d=i.useCallback((l,s)=>{j(a=>({...a,config:{...a.config,[l]:s}}))},[]),F=i.useCallback((l,s)=>{j(a=>({...a,llmMatch:{...a.llmMatch||{prompt:""},[l]:s}}))},[]),W=i.useCallback((l,s)=>{j(a=>({...a,llmExtract:{...a.llmExtract||{prompt:"",variables:[]},[l]:s}}))},[]),me=i.useMemo(()=>Array.from(b.values()).map(l=>({id:l.id,name:l.name,class:l.class})),[b]),[_,$]=i.useState(null),J=i.useCallback((l,s)=>{l&&navigator.clipboard.writeText(l).then(()=>{$(s),setTimeout(()=>$(a=>a===s?null:a),1500)},()=>u("Failed to copy to clipboard"))},[]);return v?e.jsx("div",{style:t.overlay,onClick:y,children:e.jsxs("div",{style:t.panel,onClick:l=>l.stopPropagation(),children:[e.jsxs("div",{style:t.header,children:[e.jsx("h2",{style:t.title,children:C==="list"?"Triggers":x?"Edit Trigger":"New Trigger"}),e.jsxs("div",{style:t.headerActions,children:[C==="list"&&e.jsx("button",{style:t.addBtn,onClick:()=>U(),children:"+ New Trigger"}),C==="edit"&&e.jsx("button",{style:t.backBtn,onClick:()=>{M("list"),S(null),u(null)},children:"Back"}),e.jsx("button",{style:t.closeBtn,onClick:y,children:"X"})]})]}),z&&e.jsx("div",{style:t.error,children:z}),C==="list"&&e.jsx("div",{style:t.content,children:w.length===0?e.jsx("div",{style:t.empty,children:"No triggers configured. Create one to get started."}):w.map(l=>{var s;return e.jsxs("div",{style:{...t.triggerCard,borderLeftColor:l.status==="error"?"#e74c3c":l.enabled?"#2ecc71":"#95a5a6"},onClick:()=>{de(l.id),U(l)},children:[e.jsxs("div",{style:t.cardHeader,children:[e.jsxs("div",{style:t.cardTitle,children:[e.jsx("span",{style:t.typeTag,children:l.type}),e.jsx("span",{children:l.name}),l.type==="cron"&&(()=>{const a=l.config||{};return a.runOnce?a.completedAt?e.jsx("span",{style:{...t.matchTag,color:"#a6e3a1"},children:"Once · completed"}):a.missedAt?e.jsx("span",{style:{...t.matchTag,color:"#f38ba8"},children:"Once · missed"}):e.jsx("span",{style:{...t.matchTag,color:"#f9e2af"},children:"Once · pending"}):e.jsx("span",{style:t.matchTag,children:"Recurring"})})(),l.matchMode!=="structural"&&e.jsx("span",{style:t.matchTag,children:l.matchMode})]}),e.jsxs("div",{style:t.cardActions,children:[e.jsx("button",{style:t.smallBtn,onClick:a=>{a.stopPropagation(),he(l)},children:l.enabled?"Disable":"Enable"}),e.jsx("button",{style:t.smallBtn,onClick:a=>{a.stopPropagation(),ye(l.id)},children:"Test Fire"}),e.jsx("button",{style:{...t.smallBtn,color:"#e74c3c"},onClick:a=>{a.stopPropagation(),ue(l.id)},children:"Delete"})]})]}),e.jsxs("div",{style:t.cardMeta,children:[e.jsxs("span",{children:["Agent: ",((s=b.get(l.agentId))==null?void 0:s.name)||l.agentId]}),e.jsxs("span",{children:["Fires: ",l.fireCount]}),l.lastFiredAt&&e.jsxs("span",{children:["Last: ",new Date(l.lastFiredAt).toLocaleString()]}),l.status==="error"&&l.lastError&&e.jsxs("span",{style:{color:"#e74c3c"},children:["Error: ",l.lastError]})]})]},l.id)})}),C==="edit"&&e.jsx("div",{style:t.content,children:e.jsxs("div",{style:t.form,children:[e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Name"}),e.jsx("input",{style:t.input,value:n.name||"",onChange:l=>c("name",l.target.value),placeholder:"My Trigger"})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Description"}),e.jsx("input",{style:t.input,value:n.description||"",onChange:l=>c("description",l.target.value),placeholder:"Optional description"})]}),e.jsxs("div",{style:t.row,children:[e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Type"}),e.jsx("select",{style:t.select,value:n.type||"webhook",onChange:l=>{const s=l.target.value;c("type",s),s==="webhook"?c("config",{method:"POST"}):s==="cron"?c("config",{expression:"0 9 * * MON-FRI",timezone:"UTC"}):s==="bitbucket"?c("config",{workspace:"",repoSlug:"",events:["pullrequest:created","pullrequest:updated"]}):c("config",{}),(n.promptTemplate??"").trim()||(s==="slack"?c("promptTemplate",`Slack message from {{slack.user}} in {{slack.channelName}}:
|
|
4
|
-
{{slack.message}}
|
|
5
|
-
|
|
6
|
-
{{slack.attachmentsBlock}}`):s==="whatsapp"&&c("promptTemplate",`WhatsApp message from {{whatsapp.fromName}} ({{whatsapp.from}}):
|
|
7
|
-
{{whatsapp.body}}
|
|
8
|
-
|
|
9
|
-
{{whatsapp.attachmentsBlock}}`))},children:ve.map(l=>e.jsx("option",{value:l.value,children:l.label},l.value))})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Agent"}),e.jsxs("select",{style:t.select,value:n.agentId||"",onChange:l=>c("agentId",l.target.value),children:[e.jsx("option",{value:"",children:"Select agent..."}),me.map(l=>e.jsxs("option",{value:l.id,children:[l.name," (",l.class,")"]},l.id))]})]})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Prompt Template"}),e.jsx("textarea",{style:t.textarea,value:n.promptTemplate||"",onChange:l=>c("promptTemplate",l.target.value),placeholder:"Message sent to agent. Use {{variable}} for interpolation.",rows:4})]}),n.type==="webhook"&&e.jsxs("div",{style:t.section,children:[e.jsx("h4",{style:t.sectionTitle,children:"Webhook Config"}),e.jsxs("div",{style:t.row,children:[e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Method"}),e.jsxs("select",{style:t.select,value:((q=n.config)==null?void 0:q.method)||"POST",onChange:l=>d("method",l.target.value),children:[e.jsx("option",{value:"POST",children:"POST"}),e.jsx("option",{value:"PUT",children:"PUT"})]})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Secret (HMAC)"}),e.jsx("input",{style:t.input,type:"password",value:((V=n.config)==null?void 0:V.secret)||"",onChange:l=>d("secret",l.target.value||void 0),placeholder:"Optional HMAC secret"})]})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Extract Fields (comma-separated JSON paths)"}),e.jsx("input",{style:t.input,value:((X=(G=n.config)==null?void 0:G.extractFields)==null?void 0:X.join(", "))||"",onChange:l=>d("extractFields",l.target.value.split(",").map(s=>s.trim()).filter(Boolean)),placeholder:"body.release_name, body.version"})]}),x&&n.id&&e.jsxs("div",{style:t.webhookUrl,children:[e.jsx("label",{style:t.label,children:"Webhook URL"}),e.jsx("code",{style:t.code,children:`${window.location.origin}/api/triggers/webhook/${n.id}`})]})]}),n.type==="bitbucket"&&(()=>{const l=n.config||{},s=Array.isArray(l.events)?l.events:[],a=x&&n.id?`${window.location.origin}/api/triggers/webhook/${n.id}`:"",h=r=>{const p=s.includes(r)?s.filter(k=>k!==r):[...s,r];d("events",p)};return e.jsxs("div",{style:t.section,children:[e.jsx("h4",{style:t.sectionTitle,children:"Bitbucket Config"}),e.jsxs("div",{style:t.row,children:[e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Workspace"}),e.jsx("input",{style:t.input,value:l.workspace||"",onChange:r=>d("workspace",r.target.value),placeholder:"tide"})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Repository slug"}),e.jsx("input",{style:t.input,value:l.repoSlug||"",onChange:r=>d("repoSlug",r.target.value),placeholder:"wind"})]})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Events"}),e.jsx("div",{style:t.checkboxGrid,children:ke.map(r=>{const p=s.includes(r.value);return e.jsxs("label",{style:t.checkboxLabel,children:[e.jsx("input",{type:"checkbox",checked:p,onChange:()=>h(r.value)}),e.jsx("span",{children:r.label}),e.jsx("code",{style:t.checkboxCode,children:r.value})]},r.value)})})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"HMAC secret"}),e.jsxs("div",{style:t.inlineRow,children:[e.jsx("input",{style:{...t.input,flex:1},type:"password",value:l.secret||"",onChange:r=>d("secret",r.target.value||void 0),placeholder:"Shared secret used to validate Bitbucket signature"}),e.jsx("button",{type:"button",style:t.smallBtn,onClick:()=>J(l.secret||"","bitbucket-secret"),disabled:!l.secret,children:_==="bitbucket-secret"?"Copied!":"Copy"})]}),e.jsx("span",{style:t.llmMeta,children:"Paste the same secret into Bitbucket's webhook configuration."})]}),a&&e.jsxs("div",{style:t.webhookUrl,children:[e.jsx("label",{style:t.label,children:"Webhook URL"}),e.jsxs("div",{style:t.inlineRow,children:[e.jsx("code",{style:{...t.code,flex:1},children:a}),e.jsx("button",{type:"button",style:t.smallBtn,onClick:()=>J(a,"bitbucket-url"),children:_==="bitbucket-url"?"Copied!":"Copy"})]}),e.jsx("span",{style:t.llmMeta,children:"In Bitbucket: Repository settings → Webhooks → Add webhook, then paste this URL and the secret above."})]}),!a&&e.jsx("span",{style:t.llmMeta,children:"Save the trigger to reveal its webhook URL."})]})})(),n.type==="cron"&&(()=>{const l=n.config||{},s=!!l.runOnce,a=l.completedAt,h=l.missedAt,r=!!a;return e.jsxs("div",{style:t.section,children:[e.jsx("h4",{style:t.sectionTitle,children:"Cron Config"}),e.jsxs("div",{style:t.modeSelector,children:[e.jsxs("button",{type:"button",style:{...t.modeBtn,...s?{}:t.modeBtnActive},onClick:()=>d("runOnce",!1),disabled:r,children:[e.jsx("strong",{children:"Repeats"}),e.jsx("span",{style:t.modeDesc,children:"Fires on a cron schedule"})]}),e.jsxs("button",{type:"button",style:{...t.modeBtn,...s?t.modeBtnActive:{}},onClick:()=>d("runOnce",!0),disabled:r,children:[e.jsx("strong",{children:"Run once"}),e.jsx("span",{style:t.modeDesc,children:"Fires exactly once at a specific time"})]})]}),r&&e.jsxs("div",{style:{...t.testResult,borderLeft:"3px solid #a6e3a1"},children:[e.jsx("strong",{style:{color:"#a6e3a1"},children:"Completed"}),e.jsxs("span",{style:t.llmMeta,children:["Fired at ",new Date(a).toLocaleString()]})]}),!r&&h&&e.jsxs("div",{style:{...t.testResult,borderLeft:"3px solid #f38ba8"},children:[e.jsx("strong",{style:{color:"#f38ba8"},children:"Missed"}),e.jsxs("span",{style:t.llmMeta,children:["Marked missed at ",new Date(h).toLocaleString()," (server was down at runAt)"]})]}),s?e.jsx("div",{style:t.row,children:e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Run at"}),e.jsx("input",{style:t.input,type:"datetime-local",value:Se(l.runAt),onChange:p=>{const k=p.target.value;if(!k){d("runAt",void 0);return}const fe=new Date(k).toISOString();d("runAt",fe)},disabled:r}),e.jsx("span",{style:t.llmMeta,children:"Interpreted in your browser's local timezone"})]})}):e.jsxs("div",{style:t.row,children:[e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Expression"}),e.jsx("input",{style:t.input,value:l.expression||"",onChange:p=>{d("expression",p.target.value),p.target.value&&be(p.target.value)},placeholder:"0 9 * * MON-FRI"})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Timezone"}),e.jsx("input",{style:t.input,value:l.timezone||"UTC",onChange:p=>d("timezone",p.target.value),placeholder:"America/Mexico_City"})]})]}),!s&&N.length>0&&e.jsxs("div",{style:t.nextFires,children:[e.jsx("label",{style:t.label,children:"Next fires:"}),N.map((p,k)=>e.jsx("div",{style:t.nextFireItem,children:new Date(p).toLocaleString()},k))]})]})})(),e.jsxs("div",{style:t.section,children:[e.jsx("h4",{style:t.sectionTitle,children:"Match Mode"}),e.jsx("div",{style:t.modeSelector,children:Ce.map(l=>e.jsxs("button",{style:{...t.modeBtn,...n.matchMode===l.value?t.modeBtnActive:{}},onClick:()=>c("matchMode",l.value),children:[e.jsx("strong",{children:l.label}),e.jsx("span",{style:t.modeDesc,children:l.desc})]},l.value))}),(n.matchMode==="llm"||n.matchMode==="hybrid")&&e.jsxs("div",{style:t.llmConfig,children:[e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"LLM Match Prompt"}),e.jsx("textarea",{style:t.textarea,value:((Y=n.llmMatch)==null?void 0:Y.prompt)||"",onChange:l=>F("prompt",l.target.value),placeholder:"Does this message request a release deployment?",rows:3})]}),e.jsxs("div",{style:t.row,children:[e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Model"}),e.jsxs("select",{style:t.select,value:((K=n.llmMatch)==null?void 0:K.model)||"haiku",onChange:l=>F("model",l.target.value),children:[e.jsx("option",{value:"haiku",children:"Haiku (fast, cheap)"}),e.jsx("option",{value:"sonnet",children:"Sonnet (balanced)"}),e.jsx("option",{value:"opus",children:"Opus (powerful)"})]})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Min Confidence"}),e.jsx("input",{style:t.input,type:"number",min:"0",max:"1",step:"0.1",value:((Q=n.llmMatch)==null?void 0:Q.minConfidence)??0,onChange:l=>F("minConfidence",parseFloat(l.target.value))})]})]})]})]}),e.jsxs("div",{style:t.section,children:[e.jsx("h4",{style:t.sectionTitle,children:"Extraction Mode"}),e.jsx("div",{style:t.row,children:Te.map(l=>e.jsx("button",{style:{...t.modeBtn,...n.extractionMode===l.value?t.modeBtnActive:{}},onClick:()=>c("extractionMode",l.value),children:l.label},l.value))}),n.extractionMode==="llm"&&e.jsxs("div",{style:t.llmConfig,children:[e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Extraction Instructions"}),e.jsx("textarea",{style:t.textarea,value:((Z=n.llmExtract)==null?void 0:Z.prompt)||"",onChange:l=>W("prompt",l.target.value),placeholder:"Extract: release version, affected systems, urgency",rows:3})]}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Variable Names (comma-separated)"}),e.jsx("input",{style:t.input,value:((te=(ee=n.llmExtract)==null?void 0:ee.variables)==null?void 0:te.join(", "))||"",onChange:l=>W("variables",l.target.value.split(",").map(s=>s.trim()).filter(Boolean)),placeholder:"release_name, affected_systems, urgency"})]})]})]}),x&&e.jsxs("div",{style:t.section,children:[e.jsx("h4",{style:t.sectionTitle,children:"Test Match"}),e.jsxs("div",{style:t.field,children:[e.jsx("label",{style:t.label,children:"Sample Event Payload (JSON)"}),e.jsx("textarea",{style:t.textarea,value:B,onChange:l=>pe(l.target.value),rows:4})]}),e.jsx("button",{style:t.testBtn,onClick:ge,disabled:I,children:I?"Testing...":"Test Match"}),o&&e.jsxs("div",{style:t.testResult,children:[e.jsx("div",{style:{...t.testResultHeader,color:o.wouldFire?"#2ecc71":"#e74c3c"},children:o.wouldFire?"WOULD FIRE":"WOULD NOT FIRE"}),o.structuralMatch!==void 0&&e.jsxs("div",{children:["Structural: ",o.structuralMatch?"Match":"No match"]}),o.llmMatch&&e.jsxs("div",{style:t.llmResult,children:[e.jsxs("div",{children:["LLM: ",o.llmMatch.match?"Match":"No match"]}),e.jsxs("div",{children:["Confidence: ",(o.llmMatch.confidence*100).toFixed(0),"%"]}),e.jsxs("div",{children:["Reason: ",o.llmMatch.reason]}),e.jsxs("div",{style:t.llmMeta,children:["Model: ",o.llmMatch.model," | Tokens: ",o.llmMatch.tokensUsed," | Latency: ",o.llmMatch.durationMs,"ms"]})]}),Object.keys(o.extractedVariables).length>0&&e.jsxs("div",{children:[e.jsx("div",{style:t.label,children:"Extracted Variables:"}),Object.entries(o.extractedVariables).map(([l,s])=>e.jsxs("div",{style:t.varRow,children:[e.jsx("code",{children:l}),": ",s]},l))]})]})]}),x&&P.length>0&&e.jsxs("div",{style:t.section,children:[e.jsx("h4",{style:t.sectionTitle,children:"Recent Fires"}),e.jsx("div",{style:t.historyList,children:P.map((l,s)=>{const a=l.llm_match_result?JSON.parse(l.llm_match_result):null;return e.jsxs("div",{style:t.historyItem,children:[e.jsxs("div",{style:t.historyHeader,children:[e.jsx("span",{style:{color:l.status==="delivered"?"#2ecc71":l.status==="failed"?"#e74c3c":"#f39c12"},children:l.status}),e.jsx("span",{children:new Date(l.fired_at).toLocaleString()}),l.duration_ms&&e.jsxs("span",{children:[l.duration_ms,"ms"]})]}),l.error&&e.jsx("div",{style:{color:"#e74c3c",fontSize:"12px"},children:l.error}),a&&e.jsxs("div",{style:t.llmMeta,children:["LLM: ",a.match?"match":"no match"," (",(a.confidence*100).toFixed(0),"%) - ",a.reason]})]},l.id||s)})})]}),e.jsxs("div",{style:t.actions,children:[e.jsx("button",{style:t.cancelBtn,onClick:()=>{M("list"),u(null)},children:"Cancel"}),e.jsx("button",{style:t.saveBtn,onClick:xe,disabled:A||!n.name||!n.agentId||n.type==="cron"&&!!((le=n.config)!=null&&le.runOnce)&&!((se=n.config)!=null&&se.runAt)||n.type==="bitbucket"&&(!((ae=n.config)!=null&&ae.workspace)||!((ne=n.config)!=null&&ne.repoSlug)||!((re=(ie=n.config)==null?void 0:ie.events)!=null&&re.length)),children:A?"Saving...":x?"Update":"Create"})]})]})})]})}):null}const t={overlay:{position:"fixed",top:0,left:0,right:0,bottom:0,background:"rgba(0,0,0,0.6)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:1e3},panel:{background:"#1e1e2e",borderRadius:"12px",width:"680px",maxHeight:"85vh",display:"flex",flexDirection:"column",color:"#cdd6f4",boxShadow:"0 8px 32px rgba(0,0,0,0.4)"},header:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"16px 20px",borderBottom:"1px solid #313244"},title:{margin:0,fontSize:"18px",fontWeight:600},headerActions:{display:"flex",gap:"8px"},content:{overflow:"auto",padding:"16px 20px",flex:1},empty:{textAlign:"center",padding:"40px",color:"#6c7086"},error:{background:"#45252a",color:"#f38ba8",padding:"8px 20px",fontSize:"13px"},triggerCard:{background:"#181825",borderRadius:"8px",padding:"12px 16px",marginBottom:"8px",borderLeft:"3px solid",cursor:"pointer",transition:"background 0.15s"},cardHeader:{display:"flex",justifyContent:"space-between",alignItems:"center"},cardTitle:{display:"flex",alignItems:"center",gap:"8px",fontWeight:500},typeTag:{background:"#313244",padding:"2px 6px",borderRadius:"4px",fontSize:"11px",textTransform:"uppercase"},matchTag:{background:"#45475a",padding:"2px 6px",borderRadius:"4px",fontSize:"10px",color:"#a6e3a1"},cardActions:{display:"flex",gap:"6px"},cardMeta:{display:"flex",gap:"16px",marginTop:"8px",fontSize:"12px",color:"#6c7086"},form:{display:"flex",flexDirection:"column",gap:"12px"},field:{display:"flex",flexDirection:"column",gap:"4px",flex:1},row:{display:"flex",gap:"12px"},label:{fontSize:"12px",color:"#a6adc8",fontWeight:500},input:{background:"#313244",border:"1px solid #45475a",borderRadius:"6px",padding:"8px 10px",color:"#cdd6f4",fontSize:"13px",outline:"none"},select:{background:"#313244",border:"1px solid #45475a",borderRadius:"6px",padding:"8px 10px",color:"#cdd6f4",fontSize:"13px",outline:"none"},textarea:{background:"#313244",border:"1px solid #45475a",borderRadius:"6px",padding:"8px 10px",color:"#cdd6f4",fontSize:"13px",outline:"none",fontFamily:"monospace",resize:"vertical"},section:{borderTop:"1px solid #313244",paddingTop:"12px"},sectionTitle:{margin:"0 0 8px",fontSize:"14px",fontWeight:600,color:"#a6adc8"},modeSelector:{display:"flex",gap:"8px",marginBottom:"8px"},modeBtn:{flex:1,background:"#313244",border:"1px solid #45475a",borderRadius:"6px",padding:"8px",color:"#cdd6f4",cursor:"pointer",textAlign:"left",display:"flex",flexDirection:"column",gap:"2px",fontSize:"12px"},modeBtnActive:{borderColor:"#89b4fa",background:"#1e3a5f"},modeDesc:{fontSize:"10px",color:"#6c7086"},llmConfig:{background:"#181825",borderRadius:"6px",padding:"12px",display:"flex",flexDirection:"column",gap:"8px"},webhookUrl:{marginTop:"8px"},inlineRow:{display:"flex",gap:"6px",alignItems:"center"},checkboxGrid:{display:"grid",gridTemplateColumns:"repeat(2, 1fr)",gap:"6px 12px"},checkboxLabel:{display:"flex",alignItems:"center",gap:"6px",fontSize:"12px",color:"#cdd6f4",cursor:"pointer"},checkboxCode:{fontSize:"10px",color:"#6c7086",background:"transparent",padding:0},code:{background:"#313244",padding:"6px 10px",borderRadius:"4px",fontSize:"12px",display:"block",wordBreak:"break-all",color:"#89b4fa"},nextFires:{marginTop:"8px"},nextFireItem:{fontSize:"12px",color:"#a6e3a1",padding:"2px 0"},testBtn:{background:"#89b4fa",border:"none",borderRadius:"6px",padding:"8px 16px",color:"#1e1e2e",fontWeight:600,cursor:"pointer",fontSize:"13px"},testResult:{background:"#181825",borderRadius:"6px",padding:"12px",marginTop:"8px",fontSize:"13px",display:"flex",flexDirection:"column",gap:"6px"},testResultHeader:{fontWeight:700,fontSize:"14px"},llmResult:{display:"flex",flexDirection:"column",gap:"2px"},llmMeta:{fontSize:"11px",color:"#6c7086",marginTop:"2px"},varRow:{fontSize:"12px",padding:"2px 0"},historyList:{display:"flex",flexDirection:"column",gap:"6px",maxHeight:"200px",overflow:"auto"},historyItem:{background:"#181825",borderRadius:"4px",padding:"8px 10px",fontSize:"12px"},historyHeader:{display:"flex",justifyContent:"space-between",alignItems:"center"},actions:{display:"flex",justifyContent:"flex-end",gap:"8px",marginTop:"16px",paddingTop:"12px",borderTop:"1px solid #313244"},addBtn:{background:"#89b4fa",border:"none",borderRadius:"6px",padding:"6px 14px",color:"#1e1e2e",fontWeight:600,cursor:"pointer",fontSize:"13px"},backBtn:{background:"transparent",border:"1px solid #45475a",borderRadius:"6px",padding:"6px 14px",color:"#cdd6f4",cursor:"pointer",fontSize:"13px"},closeBtn:{background:"transparent",border:"none",color:"#6c7086",cursor:"pointer",fontSize:"16px",padding:"4px 8px"},smallBtn:{background:"transparent",border:"1px solid #45475a",borderRadius:"4px",padding:"3px 8px",color:"#cdd6f4",cursor:"pointer",fontSize:"11px"},saveBtn:{background:"#a6e3a1",border:"none",borderRadius:"6px",padding:"8px 20px",color:"#1e1e2e",fontWeight:600,cursor:"pointer",fontSize:"13px"},cancelBtn:{background:"transparent",border:"1px solid #45475a",borderRadius:"6px",padding:"8px 20px",color:"#cdd6f4",cursor:"pointer",fontSize:"13px"}};export{Ee as TriggerManagerPanel,Ee as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.system-prompt-modal{width:720px;max-width:95vw;max-height:85vh;display:flex;flex-direction:column;padding:0;background:#14141e;border:1px solid #2a2a3a;border-radius:12px;overflow:hidden}.system-prompt-modal .modal-header{padding:14px 20px;margin-bottom:0;border-bottom:1px solid #2a2a3a;font-size:16px;font-weight:600;display:flex;justify-content:space-between;align-items:center;gap:12px}.system-prompt-modal .modal-header h2{margin:0;font-size:16px}.system-prompt-modal .modal-footer{padding:12px 20px;border-top:1px solid #2a2a3a;display:flex;justify-content:space-between;align-items:center;gap:12px}.modal-close{background:transparent;border:none;color:#8a8a98;font-size:24px;line-height:1;cursor:pointer;padding:4px 8px;border-radius:4px;transition:all .15s;flex-shrink:0}.modal-close:hover{background:#d45a5a26;color:#d45a5a}.modal-body{flex:1;overflow-y:auto;padding:20px;min-height:0;display:flex;flex-direction:column;gap:12px}.modal-description{margin:0;font-size:12px;color:#8a8a98;line-height:1.5}.loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:48px 24px}.loading-state .spinner{width:32px;height:32px;border:3px solid rgba(42,42,58,.5);border-top-color:#5a8fd4;border-radius:50%;animation:spin .8s linear infinite}.loading-state p{color:#8a8a98;margin:0;font-size:13px}@keyframes spin{to{transform:rotate(360deg)}}.alert{padding:10px 12px;border-radius:4px;display:flex;gap:8px;align-items:flex-start;font-size:12px;line-height:1.4}.alert .alert-icon{flex-shrink:0;font-size:14px}.alert.alert-error{background:#d45a5a1a;border:1px solid rgba(212,90,90,.25);color:#d45a5a}.alert.alert-success{background:#5cb88a1a;border:1px solid rgba(92,184,138,.25);color:#5cb88a}.editor-wrapper{display:flex;flex-direction:column;gap:6px;flex:1}.editor-header{display:flex;justify-content:space-between;align-items:center;gap:8px}.editor-label{font-size:11px;font-weight:600;color:#8a8a98;text-transform:uppercase;letter-spacing:.3px}.char-count{font-size:10px;color:#606070;flex-shrink:0}.prompt-editor{padding:10px 12px;border:1px solid #2a2a3a;border-radius:4px;background:#1c1c28;color:#d0d0d8;font-family:JetBrains Mono,SF Mono,Fira Code,Consolas,monospace;font-size:12px;line-height:1.6;resize:vertical;min-height:14rem;flex:1;max-height:28rem;outline:none;transition:all .15s}.prompt-editor:focus{border-color:#5a8fd4;background:#1c1c28cc}.prompt-editor::placeholder{color:#606070;white-space:pre-line}.editor-hint{font-size:10px;color:#606070;font-style:italic;padding:0 2px}.footer-buttons-left{display:flex;gap:6px}.footer-buttons-right{display:flex;gap:6px;margin-left:auto}.btn{padding:8px 14px;border:1px solid #2a2a3a;border-radius:4px;font-size:12px;font-weight:500;cursor:pointer;transition:all .15s;white-space:nowrap;background:#1c1c28;color:#d0d0d8}.whatsapp-config-modal{width:900px;max-width:95vw;max-height:85vh;display:flex;flex-direction:column;padding:0;background:#14141e;border:1px solid #2a2a3a;border-radius:12px;overflow:hidden}.whatsapp-config-modal .modal-header{padding:14px 20px;margin-bottom:0;border-bottom:1px solid #2a2a3a;font-size:16px;font-weight:600;display:flex;justify-content:space-between;align-items:center;gap:12px}.whatsapp-config-modal .modal-header h2{margin:0;font-size:16px}.whatsapp-config-modal .modal-footer{padding:12px 20px;border-top:1px solid #2a2a3a;display:flex;justify-content:space-between;align-items:center;gap:12px}.whatsapp-config-modal .modal-body{flex:1;overflow-y:auto;padding:20px;min-height:0;display:flex;flex-direction:column;gap:16px}.whatsapp-config-modal .modal-description{margin:0;font-size:12px;color:#8a8a98;line-height:1.5}.whatsapp-config-modal .loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:48px 24px}.whatsapp-config-modal .loading-state .spinner{width:32px;height:32px;border:3px solid rgba(42,42,58,.5);border-top-color:#5a8fd4;border-radius:50%;animation:wa-spin .8s linear infinite}.whatsapp-config-modal .loading-state p{color:#8a8a98;margin:0;font-size:13px}.whatsapp-config-modal .alert{padding:10px 12px;border-radius:4px;display:flex;gap:8px;align-items:flex-start;font-size:12px;line-height:1.4}.whatsapp-config-modal .alert .alert-icon{flex-shrink:0;font-size:14px}.whatsapp-config-modal .alert.alert-error{background:#d45a5a1a;border:1px solid rgba(212,90,90,.25);color:#d45a5a}.whatsapp-config-modal .alert.alert-success{background:#5cb88a1a;border:1px solid rgba(92,184,138,.25);color:#5cb88a}.whatsapp-config-modal .footer-buttons-left{display:flex;gap:6px}.whatsapp-config-modal .footer-buttons-right{display:flex;gap:6px;margin-left:auto}@keyframes wa-spin{to{transform:rotate(360deg)}}.wa-section{display:flex;flex-direction:column;gap:10px;padding:14px 14px 16px;border:1px solid #2a2a3a;border-radius:8px;background:#1c1c2873}.wa-section-title{margin:0 0 4px;font-size:12px;font-weight:600;color:#8a8a98;text-transform:uppercase;letter-spacing:.5px}.wa-field{display:flex;flex-direction:column;gap:4px}.wa-field.wa-field-row{flex-direction:row;align-items:center;justify-content:space-between}.wa-field.wa-field-inline{flex-direction:row;align-items:center;gap:8px;flex-wrap:wrap}.wa-field.wa-field-inline .wa-input{flex:1 1 220px;min-width:160px}.wa-field.wa-field-end{justify-content:flex-end}.wa-label{font-size:11px;font-weight:600;color:#8a8a98;text-transform:uppercase;letter-spacing:.3px}.wa-hint{font-size:10px;color:#606070;font-style:italic}.wa-input,.wa-textarea{padding:8px 10px;border:1px solid #2a2a3a;border-radius:4px;background:#1c1c28;color:#d0d0d8;font-family:JetBrains Mono,SF Mono,Fira Code,Consolas,monospace;font-size:12px;line-height:1.5;outline:none;transition:all .15s;width:100%;box-sizing:border-box}.wa-input:focus,.wa-textarea:focus{border-color:#5a8fd4;background:#1c1c28cc}.wa-input::placeholder,.wa-textarea::placeholder{color:#606070}.wa-textarea{resize:vertical;min-height:6rem;max-height:14rem}.wa-toggle{position:relative;display:inline-flex;align-items:center;cursor:pointer;flex-shrink:0}.wa-toggle input{position:absolute;opacity:0;pointer-events:none}.wa-toggle .wa-toggle-track{width:32px;height:18px;background:#1c1c28;border:1px solid #2a2a3a;border-radius:9px;transition:background .15s,border-color .15s;position:relative;display:inline-block}.wa-toggle .wa-toggle-thumb{position:absolute;top:1px;left:1px;width:14px;height:14px;background:#8a8a98;border-radius:50%;transition:transform .15s,background .15s}.wa-toggle input:checked+.wa-toggle-track{background:#5a8fd459;border-color:#5a8fd4}.wa-toggle input:checked+.wa-toggle-track .wa-toggle-thumb{transform:translate(14px);background:#5a8fd4}.wa-key-status{display:flex;align-items:center;gap:8px}.wa-status{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:4px;font-size:11px;font-weight:500}.wa-status.wa-status-ok{background:#5cb88a1f;color:#5cb88a;border:1px solid rgba(92,184,138,.3)}.wa-status.wa-status-warn{background:#d4a05a1f;color:#d4a05a;border:1px solid rgba(212,160,90,.3)}.wa-sessions-list{display:flex;flex-direction:column;gap:6px}.wa-empty{font-size:12px;color:#606070;font-style:italic;padding:8px 0}.wa-session-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 10px;border:1px solid #2a2a3a;border-radius:4px;background:#1c1c28}.wa-session-info{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}.wa-session-id{font-family:JetBrains Mono,SF Mono,Fira Code,Consolas,monospace;font-size:12px;color:#d0d0d8;font-weight:500}.wa-session-status{font-size:11px;padding:2px 6px;border-radius:4px;background:#60607026;color:#8a8a98;text-transform:uppercase;letter-spacing:.3px}.wa-session-status.status-connected,.wa-session-status.status-paired,.wa-session-status.status-open,.wa-session-status.status-ready{background:#5cb88a26;color:#5cb88a}.wa-session-status.status-pairing,.wa-session-status.status-connecting,.wa-session-status.status-qr{background:#5a8fd426;color:#5a8fd4}.wa-session-status.status-error,.wa-session-status.status-disconnected,.wa-session-status.status-failed{background:#d45a5a26;color:#d45a5a}.wa-session-paired{font-size:11px;color:#606070}.wa-qr-panel{margin-top:8px;padding:12px;border:1px dashed #2a2a3a;border-radius:6px;background:#0d0d1480;display:flex;flex-direction:column;gap:10px}.wa-qr-header{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:12px;color:#8a8a98}.wa-qr-image{display:flex;justify-content:center;padding:12px;background:#fff;border-radius:4px}.wa-qr-image img{width:240px;height:240px;image-rendering:pixelated}.wa-qr-loading{display:flex;flex-direction:column;align-items:center;gap:8px;padding:24px}.wa-qr-loading .spinner{width:24px;height:24px;border:3px solid rgba(42,42,58,.5);border-top-color:#5a8fd4;border-radius:50%;animation:wa-spin .8s linear infinite}.wa-qr-loading p{margin:0;font-size:12px;color:#8a8a98}.wa-pairing-message{font-size:12px;color:#8a8a98;font-style:italic}.btn{padding:8px 14px;border:1px solid #2a2a3a;border-radius:4px;font-size:12px;font-weight:500;cursor:pointer;transition:all .15s;white-space:nowrap;background:#1c1c28;color:#d0d0d8;display:inline-flex;align-items:center;gap:6px}.btn:disabled{opacity:.5;cursor:not-allowed}.btn:active:not(:disabled){transform:scale(.98)}.btn:hover:not(:disabled){border-color:#8a8a98;background:#1c1c28cc}.btn.btn-sm{padding:5px 10px;font-size:11px}.btn.btn-primary{background:#5a8fd4;color:#fff;border-color:#5a8fd4}.btn.btn-primary:hover:not(:disabled){background:#5a8fd4e6;box-shadow:0 0 0 2px #5a8fd433}.btn.btn-secondary{background:#1c1c28;color:#d0d0d8;border-color:#2a2a3a}.btn.btn-secondary:hover:not(:disabled){border-color:#8a8a98;background:#1c1c28cc}.btn.btn-danger{background:#d45a5a26;color:#d45a5a;border-color:#d45a5a4d}.btn.btn-danger:hover:not(:disabled){background:#d45a5a40;border-color:#d45a5a80}:root{--bg-primary: #0d0d14;--bg-secondary: #14141e;--bg-tertiary: #1c1c28;--border-color: #2a2a3a;--text-primary: #d0d0d8;--text-secondary: #8a8a98;--text-muted: #606070;--accent-blue: #5a8fd4;--accent-green: #5cb88a;--accent-orange: #d4a05a;--accent-red: #d45a5a;--accent-purple: #8a6fbf;--accent-cyan: #5ab8c8;--accent-claude: #a06848;--accent-claude-light: #c8896a;--accent-pink: #5a8fd4;--accent-yellow: #d0d0d8;--font-size-base: 14px;--line-height-base: 1.5;--msg-user-bg: color-mix(in srgb, #5ab8c8 8%, transparent);--msg-user-border: #5ab8c8;--msg-user-text: #d0d0d8;--msg-assistant-bg: color-mix(in srgb, #5cb88a 8%, transparent);--msg-assistant-border: #5cb88a;--msg-assistant-text: #d0d0d8;--tool-use-bg: color-mix(in srgb, #d4a05a 8%, transparent);--tool-use-border: #d4a05a;--tool-use-text: #d4a05a;--tool-use-name: #d4a05a;--tool-result-bg: color-mix(in srgb, #8a6fbf 6%, transparent);--tool-result-border: #8a6fbf;--tool-result-text: #5cb88a;--context-bar-bg: #1c1c28;--context-bar-fill: #8a6fbf;--output-line-bg: transparent;--task-label-color: #5ab8c8}.whatsapp-notifications-modal{width:720px;max-width:95vw;max-height:85vh;display:flex;flex-direction:column;padding:0;background:#14141e;border:1px solid #2a2a3a;border-radius:12px;overflow:hidden}.whatsapp-notifications-modal .modal-header{padding:14px 20px;border-bottom:1px solid #2a2a3a;font-size:16px;font-weight:600;display:flex;justify-content:space-between;align-items:center;gap:12px}.whatsapp-notifications-modal .modal-header h2{margin:0;font-size:16px}.whatsapp-notifications-modal .modal-footer{padding:12px 20px;border-top:1px solid #2a2a3a;display:flex;justify-content:space-between;align-items:center;gap:12px}.whatsapp-notifications-modal .modal-footer .footer-buttons-right{display:flex;gap:8px}.whatsapp-notifications-modal .modal-body{flex:1;overflow-y:auto;padding:20px;min-height:0;display:flex;flex-direction:column;gap:16px}.whatsapp-notifications-modal .modal-description{margin:0;font-size:12px;color:#8a8a98;line-height:1.5}.whatsapp-notifications-modal .loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:48px 24px}.whatsapp-notifications-modal .loading-state .spinner{width:32px;height:32px;border:3px solid rgba(42,42,58,.5);border-top-color:#5a8fd4;border-radius:50%;animation:wan-spin .8s linear infinite}.whatsapp-notifications-modal .loading-state p{color:#8a8a98;margin:0;font-size:13px}.whatsapp-notifications-modal .alert{display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:6px;font-size:12px}.whatsapp-notifications-modal .alert.alert-error{background:#dc26261a;color:#f87171;border:1px solid rgba(220,38,38,.3)}.whatsapp-notifications-modal .alert.alert-success{background:#22c55e1a;color:#4ade80;border:1px solid rgba(34,197,94,.3)}.whatsapp-notifications-modal .wan-section{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid #2a2a3a;border-radius:8px;background:#0d0d14}.whatsapp-notifications-modal .wan-section-title{margin:0;font-size:13px;font-weight:600;color:#d0d0d8}.whatsapp-notifications-modal .wan-section-hint{margin:0;font-size:11px;color:#8a8a98;line-height:1.4}.whatsapp-notifications-modal .wan-field{display:flex;flex-direction:column;gap:4px}.whatsapp-notifications-modal .wan-label{font-size:12px;font-weight:500;color:#8a8a98}.whatsapp-notifications-modal .wan-input{padding:8px 10px;background:#14141e;color:#d0d0d8;border:1px solid #2a2a3a;border-radius:6px;font-size:13px}.whatsapp-notifications-modal .wan-input:focus{outline:none;border-color:#5a8fd4}.whatsapp-notifications-modal .wan-hint{font-size:11px;color:#8a8a98}.whatsapp-notifications-modal .wan-toggle-row{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:8px 0;border-bottom:1px solid rgba(42,42,58,.5)}.whatsapp-notifications-modal .wan-toggle-row:last-child{border-bottom:none}.whatsapp-notifications-modal .wan-toggle-info{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.whatsapp-notifications-modal .wan-toggle-title{font-size:13px;color:#d0d0d8;font-weight:500}.whatsapp-notifications-modal .wan-toggle-help{font-size:11px;color:#8a8a98;line-height:1.4}.whatsapp-notifications-modal .wan-toggle{position:relative;display:inline-block;width:36px;height:20px;flex-shrink:0;cursor:pointer}.whatsapp-notifications-modal .wan-toggle input{opacity:0;width:0;height:0}.whatsapp-notifications-modal .wan-toggle input:checked+.wan-toggle-track{background:#5a8fd4}.whatsapp-notifications-modal .wan-toggle input:checked+.wan-toggle-track .wan-toggle-thumb{transform:translate(16px)}.whatsapp-notifications-modal .wan-toggle-track{position:absolute;top:0;right:0;bottom:0;left:0;background:#2a2a3a99;border-radius:999px;transition:background .15s ease}.whatsapp-notifications-modal .wan-toggle-thumb{position:absolute;top:2px;left:2px;width:16px;height:16px;background:#fff;border-radius:50%;transition:transform .15s ease}@media(max-width:600px){.whatsapp-notifications-modal{width:100%;max-width:100vw}.whatsapp-notifications-modal .modal-footer{flex-direction:column;align-items:stretch}.whatsapp-notifications-modal .modal-footer .footer-buttons-left,.whatsapp-notifications-modal .modal-footer .footer-buttons-right{width:100%;justify-content:stretch}.whatsapp-notifications-modal .modal-footer .footer-buttons-left .btn,.whatsapp-notifications-modal .modal-footer .footer-buttons-right .btn{flex:1}}@keyframes wan-spin{to{transform:rotate(360deg)}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as J,a as Z,r,s as u,j as e,D as le,I as H,C as ce,b as ie,c as de,d as oe,g as me,e as ue,Q as be,R as he}from"./main-klWBzHh0.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";const _e=({building:a,connections:x,activeConnectionId:l,activeDatabase:c,collapsed:j,onToggleCollapse:p,onConnectionChange:Q,onDatabaseChange:N,onInsertTable:A,onSelectTableQuery:P})=>{const{t:o}=J(["terminal"]),q=Z(a.id),[M,R]=r.useState(new Set),[w,n]=r.useState(""),[d,T]=r.useState(""),[E,k]=r.useState(!1),[U,F]=r.useState(null),z=r.useRef(null),S=r.useRef(null),O=r.useRef(null),y=l?q.databases.get(l)??[]:[],I=l&&c?`${l}:${c}`:"",f=I?q.tables.get(I)??[]:[],_=l?q.connectionStatus.get(l):void 0,D=r.useMemo(()=>{if(!w.trim())return y;const t=w.toLowerCase();return y.filter(m=>m.toLowerCase().includes(t))},[y,w]),h=r.useMemo(()=>{if(!d.trim())return f;const t=d.toLowerCase();return f.filter(m=>m.name.toLowerCase().includes(t))},[f,d]);r.useEffect(()=>{const t=m=>{S.current&&!S.current.contains(m.target)&&k(!1)};return E&&document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[E]),r.useEffect(()=>{l&&!_&&u.testDatabaseConnection(a.id,l)},[a.id,l,_]),r.useEffect(()=>{l&&(_!=null&&_.connected)&&y.length===0&&u.listDatabases(a.id,l)},[a.id,l,_==null?void 0:_.connected,y.length]),r.useEffect(()=>{l&&c&&f.length===0&&u.listTables(a.id,l,c)},[a.id,l,c,f.length]),r.useEffect(()=>{F(null),T("")},[l,c]);const v=r.useCallback(t=>{R(m=>{const g=new Set(m);if(g.has(t))g.delete(t);else if(g.add(t),l&&c){const C=`${l}:${c}:${t}`;q.tableSchemas.has(C)||u.getTableSchema(a.id,l,c,t)}return g})},[a.id,l,c,q.tableSchemas]),K=t=>{if(!l||!c)return null;const m=`${l}:${c}:${t}`;return q.tableSchemas.get(m)};return j?e.jsx("div",{className:"database-sidebar database-sidebar--collapsed",children:e.jsx("button",{className:"database-sidebar__toggle",onClick:p,title:o("terminal:database.expandSidebar"),children:"»"})}):e.jsxs("div",{className:"database-sidebar",children:[e.jsxs("div",{className:"database-sidebar__header",children:[e.jsx("span",{children:o("terminal:database.explorer")}),e.jsx("button",{className:"database-sidebar__toggle",onClick:p,title:o("terminal:database.collapseSidebar"),children:"«"})]}),e.jsxs("div",{className:"database-sidebar__section",children:[e.jsx("div",{className:"database-sidebar__section-title",children:o("terminal:database.connection")}),e.jsx("select",{className:"database-sidebar__select",value:l||"",onChange:t=>Q(t.target.value),children:x.length===0?e.jsx("option",{value:"",children:o("terminal:database.noConnections")}):x.map(t=>{var m;return e.jsxs("option",{value:t.id,children:[((m=le[t.engine])==null?void 0:m.icon)??"🗄️"," ",t.name]},t.id)})}),_&&e.jsx("div",{className:`database-sidebar__status ${_.connected?"database-sidebar__status--connected":"database-sidebar__status--error"}`,children:_.connected?e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"database-sidebar__status-icon",children:"✓"}),o("terminal:database.connected"),_.serverVersion&&e.jsxs("span",{className:"database-sidebar__version",children:["(",_.serverVersion,")"]})]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"database-sidebar__status-icon",children:"✗"}),_.error||o("terminal:database.disconnected")]})})]}),y.length>0&&e.jsxs("div",{className:"database-sidebar__section",children:[e.jsx("div",{className:"database-sidebar__section-title",children:o("terminal:database.databaseTitle")}),e.jsxs("div",{className:"database-sidebar__searchable-select",ref:S,children:[e.jsx("input",{ref:z,className:"database-sidebar__search-input",type:"text",value:E?w:c||"",placeholder:o("terminal:database.selectDatabase"),onChange:t=>{n(t.target.value),E||k(!0)},onFocus:()=>{k(!0),n("")},onKeyDown:t=>{var m,g;t.key==="Escape"?(k(!1),n(""),(m=z.current)==null||m.blur()):t.key==="Enter"&&D.length===1&&(N(D[0]),k(!1),n(""),(g=z.current)==null||g.blur())}}),E&&e.jsx("div",{className:"database-sidebar__dropdown",children:D.length===0?e.jsx("div",{className:"database-sidebar__dropdown-empty",children:"No matches"}):D.map(t=>e.jsx("div",{className:`database-sidebar__dropdown-item ${t===c?"database-sidebar__dropdown-item--active":""}`,onMouseDown:m=>{m.preventDefault(),N(t),k(!1),n("")},children:t},t))})]})]}),f.length>0&&e.jsxs("div",{className:"database-sidebar__section database-sidebar__section--tables",children:[e.jsx("div",{className:"database-sidebar__section-title",children:d.trim()?o("terminal:database.tablesCount",{count:h.length})+` / ${f.length}`:o("terminal:database.tablesCount",{count:f.length})}),e.jsxs("div",{className:"database-sidebar__table-filter",children:[e.jsx("input",{ref:O,className:"database-sidebar__table-filter-input",type:"text",value:d,placeholder:o("terminal:database.filterTables"),onChange:t=>T(t.target.value),onKeyDown:t=>{var m;t.key==="Escape"&&(d?T(""):(m=O.current)==null||m.blur(),t.stopPropagation())}}),d&&e.jsx("button",{className:"database-sidebar__table-filter-clear",onClick:()=>{var t;T(""),(t=O.current)==null||t.focus()},title:"Clear filter",children:"×"})]}),e.jsxs("div",{className:"database-sidebar__tables",children:[d.trim()&&h.length===0&&e.jsx("div",{className:"database-sidebar__tables-empty",children:o("terminal:database.noTablesMatch")}),h.map(t=>{const m=M.has(t.name),g=m?K(t.name):null;return e.jsxs("div",{className:"database-sidebar__table",children:[e.jsxs("div",{className:"database-sidebar__table-header",children:[e.jsx("button",{className:"database-sidebar__table-expand",onClick:()=>v(t.name),title:m?"Collapse table schema":"Expand table schema",children:e.jsx(H,{name:m?"caret-down":"caret-right",size:10})}),e.jsx("span",{className:"database-sidebar__table-icon",children:e.jsx(H,{name:t.type==="view"?"eye":"clipboard",size:12})}),e.jsx("span",{className:`database-sidebar__table-name ${U===t.name?"database-sidebar__table-name--selected":""}`,onClick:()=>F(t.name),onDoubleClick:()=>{F(t.name),P(t.name)},children:t.name}),e.jsx("button",{className:"database-sidebar__table-insert",onClick:C=>{C.stopPropagation(),A(t.name)},title:o("terminal:database.insertTableName"),children:"+"})]}),m&&g&&e.jsx("div",{className:"database-sidebar__table-columns",children:g.columns.map(C=>e.jsxs("div",{className:"database-sidebar__column",onClick:()=>A(C.name),title:`${C.type}${C.nullable?" NULL":" NOT NULL"}${C.primaryKey?" PK":""}`,children:[e.jsx("span",{className:"database-sidebar__column-icon",children:C.primaryKey?e.jsx(H,{name:"key",size:11}):null}),e.jsx("span",{className:"database-sidebar__column-name",children:C.name}),e.jsx("span",{className:"database-sidebar__column-type",children:C.type})]},C.name))})]},t.name)})]})]})]})},xe=({buildingId:a,history:x,onLoadQuery:l})=>{const{t:c}=J(["terminal","common"]),[j,p]=r.useState(""),[Q,N]=r.useState(!1),[A,P]=r.useState(!1),o=r.useMemo(()=>{let n=x;if(Q&&(n=n.filter(d=>d.favorite)),j.trim()){const d=j.toLowerCase();n=n.filter(T=>T.query.toLowerCase().includes(d)||T.database.toLowerCase().includes(d))}return n},[x,Q,j]),q=n=>{const d=new Date(n),E=new Date().getTime()-d.getTime();return E<1440*60*1e3?d.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):E<10080*60*1e3?d.toLocaleDateString([],{weekday:"short"})+" "+d.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}):d.toLocaleDateString([],{month:"short",day:"numeric"})},M=r.useCallback((n,d)=>{d.stopPropagation(),u.toggleQueryFavorite(a,n)},[a]),R=r.useCallback((n,d)=>{d.stopPropagation(),u.deleteQueryFromHistory(a,n)},[a]),w=r.useCallback(()=>{P(!0)},[]);return x.length===0?e.jsxs("div",{className:"query-history query-history--empty",children:[e.jsx("p",{children:c("terminal:database.noHistory")}),e.jsx("p",{children:c("terminal:database.queriesAppearHere")})]}):e.jsxs("div",{className:"query-history",children:[e.jsxs("div",{className:"query-history__toolbar",children:[e.jsx("input",{type:"text",className:"query-history__search",placeholder:c("terminal:database.searchQueries"),value:j,onChange:n=>p(n.target.value)}),e.jsxs("label",{className:"query-history__filter",children:[e.jsx("input",{type:"checkbox",checked:Q,onChange:n=>N(n.target.checked)}),c("terminal:database.favoritesOnly")]}),e.jsx("button",{className:"query-history__clear",onClick:w,title:c("terminal:database.clearAll"),children:c("terminal:database.clearAll")})]}),e.jsxs("div",{className:"query-history__list",children:[o.map(n=>e.jsxs("div",{className:`query-history__item ${n.status==="error"?"query-history__item--error":""}`,onClick:()=>l(n.query),children:[e.jsxs("div",{className:"query-history__item-header",children:[e.jsx("span",{className:`query-history__status ${n.status==="success"?"query-history__status--success":"query-history__status--error"}`,children:e.jsx(H,{name:n.status==="success"?"check":"cross",size:12})}),e.jsx("span",{className:"query-history__database",children:n.database}),e.jsx("span",{className:"query-history__date",children:q(n.executedAt)}),e.jsxs("span",{className:"query-history__duration",children:[n.duration,"ms"]}),n.rowCount!==void 0&&e.jsx("span",{className:"query-history__row-count",children:c("terminal:database.rowCount",{count:n.rowCount})})]}),e.jsx("div",{className:"query-history__query",children:e.jsx("code",{children:n.query.length>200?n.query.substring(0,200)+"...":n.query})}),n.error&&e.jsx("div",{className:"query-history__error",children:n.error}),e.jsxs("div",{className:"query-history__actions",children:[e.jsx("button",{className:`query-history__favorite ${n.favorite?"query-history__favorite--active":""}`,onClick:d=>M(n.id,d),title:n.favorite?c("terminal:database.removeFromFavorites"):c("terminal:database.addToFavorites"),children:e.jsx(H,{name:"star",size:12,weight:n.favorite?"fill":"regular",color:n.favorite?"#facc15":void 0})}),e.jsx("button",{className:"query-history__delete",onClick:d=>R(n.id,d),title:c("terminal:database.deleteFromHistory"),children:e.jsx(H,{name:"trash",size:12})})]})]},n.id)),o.length===0&&e.jsx("div",{className:"query-history__no-results",children:c("terminal:database.noQueriesMatch")})]}),e.jsx(ce,{isOpen:A,title:c("terminal:database.clearAll"),message:c("terminal:database.confirmClearHistory"),confirmLabel:c("terminal:database.clearAll"),cancelLabel:c("common:buttons.cancel"),variant:"danger",onConfirm:()=>u.clearQueryHistory(a),onClose:()=>P(!1)})]})},pe=({tabs:a,activeTabId:x,onTabClick:l,onTabClose:c})=>{const{t:j}=J(["terminal"]);return e.jsx("div",{className:"database-tabs",children:a.map(p=>e.jsxs("div",{className:`database-tabs__tab ${x===p.id?"database-tabs__tab--active":""}`,children:[e.jsxs("button",{className:"database-tabs__tab-label",onClick:()=>l(p),title:`${p.connectionName} / ${p.database}`,children:[p.database,e.jsx("span",{className:"database-tabs__tab-connection",children:p.connectionName})]}),e.jsx("button",{className:"database-tabs__tab-close",onClick:()=>c(p.id),title:j("terminal:database.closeTab"),"aria-label":`Close ${p.database} tab`,children:"×"})]},p.id))})},ee=a=>`db-panel-${a}`;function fe(a){try{const x=localStorage.getItem(ee(a));return x?JSON.parse(x):{}}catch{return{}}}function je(a,x){try{localStorage.setItem(ee(a),JSON.stringify(x))}catch{}}const Ce=({building:a,onClose:x})=>{var B,Y,W,X;const{t:l}=J(["terminal","common"]),c=Z(a.id),j=ie(a.id),p=de(a.id),Q=oe(a.id),N=r.useRef(fe(a.id)),A=r.useRef(null),P=r.useRef(0),o=((B=a.database)==null?void 0:B.connections)??[],q=(s,i)=>`${s}:${i}`,M=s=>s?(N.current.queries??{})[s]??"":N.current.generalQuery??"",[R,w]=r.useState("results"),[n,d]=r.useState(0),[T,E]=r.useState(!1),[k,U]=r.useState(!1),[F,z]=r.useState(()=>(N.current.openTabs??[]).map(i=>{var b;return{id:`${i.connectionId}:${i.database}`,connectionId:i.connectionId,connectionName:((b=o.find(L=>L.id===i.connectionId))==null?void 0:b.name)??i.connectionId,database:i.database}})),[S,O]=r.useState(N.current.activeTabId??null),[y,I]=r.useState(()=>{const s=N.current.queries??{};return N.current.generalQuery,s}),[f,_]=r.useState(M(S)),D=r.useCallback(s=>{_(i=>{const b=typeof s=="function"?s(i):s;return I(L=>{const $={...L};return S&&($[S]=b),$}),b})},[S]),h=c.activeConnectionId??N.current.connectionId??((Y=a.database)==null?void 0:Y.activeConnectionId)??((W=o[0])==null?void 0:W.id),v=c.activeDatabase??N.current.database??((X=a.database)==null?void 0:X.activeDatabase),K=o.find(s=>s.id===h),t=r.useCallback((s,i)=>{var $;const b=q(s,i),L=(($=o.find(G=>G.id===s))==null?void 0:$.name)??s;z(G=>{if(G.some(re=>re.id===b))return G;const ne={id:b,connectionId:s,connectionName:L,database:i};return[...G,ne]}),O(b),_(y[b]??""),u.setActiveConnection(a.id,s),u.setActiveDatabase(a.id,i)},[a.id,o,y]),m=r.useCallback(s=>{z(i=>i.filter(b=>b.id!==s)),S===s&&z(i=>{if(i.length>0){const b=i[0];O(b.id),_(y[b.id]??""),u.setActiveConnection(a.id,b.connectionId),u.setActiveDatabase(a.id,b.database)}else O(null),_("");return i})},[S,a.id,y]),g=r.useCallback(s=>{O(s.id),_(y[s.id]??""),u.setActiveConnection(a.id,s.connectionId),u.setActiveDatabase(a.id,s.database)},[a.id,y]);r.useEffect(()=>{if(!k&&o.length>0){const s=N.current;s.connectionId&&o.some(i=>i.id===s.connectionId)&&(u.setActiveConnection(a.id,s.connectionId),u.listDatabases(a.id,s.connectionId),s.database&&(u.setActiveDatabase(a.id,s.database),u.listTables(a.id,s.connectionId,s.database))),U(!0)}},[a.id,o,k]),r.useEffect(()=>{u.requestQueryHistory(a.id)},[a.id]),r.useEffect(()=>{const s=i=>{i.key==="Escape"&&(i.preventDefault(),i.stopPropagation(),x())};return window.addEventListener("keydown",s),()=>window.removeEventListener("keydown",s)},[x]),r.useEffect(()=>{k&&h&&je(a.id,{connectionId:h,database:v,lastQuery:f,queries:y,generalQuery:"",openTabs:F.map(s=>({connectionId:s.connectionId,database:s.database})),activeTabId:S??void 0})},[a.id,h,v,f,k,F,S,y]);const C=r.useCallback(s=>{var i;if(!(!h||!v||!f.trim()||Q))if(s==="cursor"){const b=(i=A.current)==null?void 0:i.querySelector(".query-editor__textarea"),L=(b==null?void 0:b.selectionStart)??P.current,$=me(f,L);$&&u.executeQuery(a.id,h,v,$)}else{const b=ue(f);b.length<=1?u.executeQuery(a.id,h,v,f.trim()):b.forEach((L,$)=>{setTimeout(()=>{u.executeQuery(a.id,h,v,L.sql)},$*150)})}},[a.id,h,v,f,Q]),ae=r.useCallback(s=>{D(s),w("results")},[]),se=r.useCallback(s=>{u.setActiveConnection(a.id,s),u.listDatabases(a.id,s)},[a.id]),te=r.useCallback(s=>{h&&(t(h,s),u.listTables(a.id,h,s))},[a.id,h,t]),V=j[n];return o.length===0?e.jsxs("div",{className:"database-panel",ref:A,children:[e.jsxs("div",{className:"database-panel__header",children:[e.jsxs("div",{className:"database-panel__title",children:[e.jsx("span",{className:"database-panel__icon",children:e.jsx(H,{name:"database",size:16})}),e.jsx("span",{className:"database-panel__name",children:a.name})]}),e.jsx("button",{className:"database-panel__close",onClick:x,children:"×"})]}),e.jsx("div",{className:"database-panel__body",children:e.jsxs("div",{className:"database-panel__no-connections",children:[e.jsx("div",{className:"database-panel__no-connections-icon",children:e.jsx(H,{name:"plug",size:32})}),e.jsx("h3",{children:l("terminal:database.noConnections")}),e.jsx("p",{children:l("terminal:database.noConnectionsDesc")}),e.jsx("p",{children:l("terminal:database.toGetStarted")}),e.jsxs("ol",{children:[e.jsx("li",{children:l("terminal:database.step1Close")}),e.jsx("li",{children:l("terminal:database.step2Settings")}),e.jsx("li",{children:l("terminal:database.step3AddConnection")}),e.jsx("li",{children:l("terminal:database.step4Reopen")})]})]})})]}):e.jsxs("div",{className:"database-panel",ref:A,children:[e.jsxs("div",{className:"database-panel__header",children:[e.jsxs("div",{className:"database-panel__title",children:[e.jsx("span",{className:"database-panel__icon",children:(K==null?void 0:K.engine)==="mysql"?"🐬":"🐘"}),e.jsx("span",{className:"database-panel__name",children:a.name}),K&&e.jsxs("span",{className:"database-panel__connection-info",children:[K.name," / ",v||l("terminal:database.noDatabaseSelected")]})]}),e.jsx("button",{className:"database-panel__close",onClick:x,children:"×"})]}),e.jsxs("div",{className:"database-panel__body",children:[e.jsx(_e,{building:a,connections:o,activeConnectionId:h,activeDatabase:v,collapsed:T,onToggleCollapse:()=>E(!T),onConnectionChange:se,onDatabaseChange:te,onInsertTable:s=>D(i=>i+` ${s}`),onSelectTableQuery:s=>{const i=`SELECT * FROM ${s}`;D(i),h&&v&&u.executeQuery(a.id,h,v,i)}}),e.jsxs("div",{className:"database-panel__main",children:[F.length>0&&e.jsx(pe,{tabs:F,activeTabId:S,onTabClick:g,onTabClose:m}),e.jsx(be,{query:f,onChange:D,onExecute:C,isExecuting:Q,disabled:!h||!v}),e.jsxs("div",{className:"database-panel__tabs",children:[e.jsxs("button",{className:`database-panel__tab ${R==="results"?"database-panel__tab--active":""}`,onClick:()=>w("results"),children:[l("terminal:database.results"),j.length>0&&e.jsx("span",{className:"database-panel__tab-badge",children:j.length})]}),e.jsxs("button",{className:`database-panel__tab ${R==="history"?"database-panel__tab--active":""}`,onClick:()=>w("history"),children:[l("terminal:database.history"),p.length>0&&e.jsx("span",{className:"database-panel__tab-badge",children:p.length})]}),R==="results"&&j.length>1&&e.jsxs("div",{className:"database-panel__result-nav",children:[e.jsxs("button",{disabled:n>=j.length-1,onClick:()=>d(s=>s+1),children:["← ",l("terminal:database.older")]}),e.jsxs("span",{children:[n+1," / ",j.length]}),e.jsxs("button",{disabled:n<=0,onClick:()=>d(s=>s-1),children:[l("terminal:database.newer")," →"]})]})]}),e.jsx("div",{className:"database-panel__tab-content",children:R==="results"?V?e.jsx(he,{result:V,buildingId:a.id,building:a}):e.jsxs("div",{className:"database-panel__empty",children:[e.jsx("p",{children:l("terminal:database.noResultsYet")}),e.jsx("p",{children:l("terminal:database.selectDbAndRun")})]}):e.jsx(xe,{buildingId:a.id,history:p,onLoadQuery:ae})})]})]})]})};export{Ce as DatabasePanel,_e as DatabaseSidebar,pe as DatabaseTabs,be as QueryEditor,xe as QueryHistoryPanel,he as ResultsTable};
|