tide-commander 1.152.0 → 1.154.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 +20 -0
- package/dist/assets/{BossLogsModal-DZWUfQXs.js → BossLogsModal-Bo0pUCWU.js} +1 -1
- package/dist/assets/{BossSpawnModal-7IwzcqE7.js → BossSpawnModal-BOOHaqaD.js} +1 -1
- package/dist/assets/{ControlsModal-D8L1xD-H.js → ControlsModal-DItGV-CW.js} +1 -1
- package/dist/assets/{DockerLogsModal-_zLe5UFl.js → DockerLogsModal-DjAZ3GL7.js} +1 -1
- package/dist/assets/{EmbeddedEditor-gbiFXvt_.js → EmbeddedEditor-Cihkr8Xb.js} +1 -1
- package/dist/assets/{GmailOAuthSetup-CcXTV3NP.js → GmailOAuthSetup-G1XqiM44.js} +1 -1
- package/dist/assets/{GoogleOAuthSetup-wbETidgv.js → GoogleOAuthSetup-Ce6gojdm.js} +1 -1
- package/dist/assets/{IframeModal-a9E5UDBk.js → IframeModal-CSSZJzPv.js} +1 -1
- package/dist/assets/{IntegrationsPanel-BbGyluL0.js → IntegrationsPanel-EspPH09n.js} +2 -2
- package/dist/assets/LogViewerModal-Bn-HDysM.js +1 -0
- package/dist/assets/{MonitoringModal-DymqjenY.js → MonitoringModal-DuSLTKVR.js} +1 -1
- package/dist/assets/{PM2LogsModal-CEaCk-dt.js → PM2LogsModal-Bo2OtaQd.js} +1 -1
- package/dist/assets/{RestoreArchivedAreaModal-q_FFv7L6.js → RestoreArchivedAreaModal-BOx-V6tl.js} +1 -1
- package/dist/assets/{Scene2DCanvas-DOvVtiYO.js → Scene2DCanvas-BIUbi14G.js} +1 -1
- package/dist/assets/{SceneManager-D0NdrG8K.js → SceneManager-CIWrGc-K.js} +4 -4
- package/dist/assets/{SkillsPanel-DpqD60Hy.js → SkillsPanel-_KHtTDhC.js} +1 -1
- package/dist/assets/{SlackMultiInstanceSetup-BdoALd_g.js → SlackMultiInstanceSetup-DbQ3rUtd.js} +1 -1
- package/dist/assets/{SpawnModal-DFFFH2kc.js → SpawnModal-CYEoOMPW.js} +1 -1
- package/dist/assets/{StatisticsModal-Dv_rYZDt.js → StatisticsModal-BJ-coeis.js} +1 -1
- package/dist/assets/{SubordinateAssignmentModal-CRCCI686.js → SubordinateAssignmentModal-5Z3jvbM9.js} +1 -1
- package/dist/assets/SymbolsNerdFontMono-Regular-BM2yZ5nr.woff2 +0 -0
- package/dist/assets/{TriggerManagerPanel-DBN8IRa-.js → TriggerManagerPanel-DvC0xP9r.js} +1 -1
- package/dist/assets/{WorkflowEditorPanel-uQEvNTs2.js → WorkflowEditorPanel-6ym1_csr.js} +1 -1
- package/dist/assets/{area-logos-CuVxToGM.js → area-logos-mWPCtCnf.js} +1 -1
- package/dist/assets/{index-Dwll5Eyj.js → index-8VVbTmtb.js} +1 -1
- package/dist/assets/{index-BNzYPyBm.css → index-BPjQZacc.css} +1 -1
- package/dist/assets/index-C34l72MW.js +1 -0
- package/dist/assets/{index-DKnfLe7S.js → index-CS8OutmQ.js} +1 -1
- package/dist/assets/{index-ipuWrg1S.js → index-CT2vtbed.js} +3 -3
- package/dist/assets/{index-Blc4MwKs.js → index-CY_NzVPm.js} +1 -1
- package/dist/assets/index-CiKbhMfN.js +1 -0
- package/dist/assets/{index-HvyFhszc.js → index-CnESn83U.js} +2 -2
- package/dist/assets/{index-8Ghh3AQ-.js → index-DZiNmiyC.js} +1 -1
- package/dist/assets/{index-D4iie3Vd.js → index-DxyZ-rYT.js} +1 -1
- package/dist/assets/main-BHBs2E1L.css +1 -0
- package/dist/assets/main-D5j8Ul0m.js +289 -0
- package/dist/assets/{web-D0JSbYeo.js → web-BvAQVbIF.js} +1 -1
- package/dist/assets/{web-1pfPwxBS.js → web-Cd0-XOkz.js} +1 -1
- package/dist/assets/{web-DjgiLxvi.js → web-DMxl9AVF.js} +1 -1
- package/dist/build-info.json +1 -0
- package/dist/index.html +2 -2
- package/dist/locales/de/config.json +1 -0
- package/dist/locales/en/config.json +6 -1
- package/dist/locales/en/terminal.json +36 -0
- package/dist/locales/es/config.json +4 -1
- package/dist/locales/es/terminal.json +8 -0
- package/dist/locales/fr/config.json +1 -0
- package/dist/locales/hi/config.json +1 -0
- package/dist/locales/it/config.json +1 -0
- package/dist/locales/ja/config.json +1 -0
- package/dist/locales/pt/config.json +1 -0
- package/dist/locales/ru/config.json +1 -0
- package/dist/locales/zh-CN/config.json +1 -0
- package/dist/src/packages/server/codex/app-server/app-server-event-adapter.js +222 -0
- package/dist/src/packages/server/codex/app-server/app-server-process.js +304 -0
- package/dist/src/packages/server/codex/app-server/app-server-recovery-store.js +76 -0
- package/dist/src/packages/server/codex/app-server/codex-app-server-runner.js +453 -0
- package/dist/src/packages/server/routes/agents.js +29 -1
- package/dist/src/packages/server/routes/system.js +216 -1
- package/dist/src/packages/server/runtime/codex-runner-router.js +99 -0
- package/dist/src/packages/server/runtime/codex-runtime-provider.js +5 -3
- package/dist/src/packages/server/services/claude-credentials-service.js +536 -0
- package/dist/src/packages/server/services/claude-usage-service.js +35 -28
- package/dist/src/packages/server/services/provider-credentials-service.js +338 -0
- package/dist/src/packages/server/services/system-prompt-service.js +46 -0
- package/package.json +1 -1
- package/dist/assets/LogViewerModal-cnMAbNvY.js +0 -1
- package/dist/assets/index-BHM8V4i-.js +0 -1
- package/dist/assets/index-OkenGYC6.js +0 -1
- package/dist/assets/main-DpNJ8pqp.css +0 -1
- package/dist/assets/main-aIpEYDDR.js +0 -289
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Credentials Service (Grok + Codex)
|
|
3
|
+
*
|
|
4
|
+
* Same account-switcher model as claude-credentials-service, generalized for
|
|
5
|
+
* providers that keep a SINGLE active auth file plus named copies:
|
|
6
|
+
* - Grok: ~/.grok/auth.json + ~/.grok/auth.<name>.json
|
|
7
|
+
* - Codex: ~/.codex/auth.json + ~/.codex/auth.<name>.json
|
|
8
|
+
*
|
|
9
|
+
* Operators keep accounts as named profiles and promote one to active when the
|
|
10
|
+
* current account hits limits. Tokens are never returned to clients — only
|
|
11
|
+
* non-secret metadata (email, plan label, expiry) + a stable fingerprint.
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'fs';
|
|
14
|
+
import * as os from 'os';
|
|
15
|
+
import * as path from 'path';
|
|
16
|
+
import * as crypto from 'crypto';
|
|
17
|
+
import { createLogger } from '../utils/logger.js';
|
|
18
|
+
const log = createLogger('ProviderCredentials');
|
|
19
|
+
// --- JWT helper (metadata only; never logs or returns the token) -----------
|
|
20
|
+
function decodeJwtPayload(jwt) {
|
|
21
|
+
const parts = jwt.split('.');
|
|
22
|
+
if (parts.length < 2)
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
const pad = parts[1] + '='.repeat((4 - (parts[1].length % 4)) % 4);
|
|
26
|
+
const json = Buffer.from(pad.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf-8');
|
|
27
|
+
return JSON.parse(json);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function fingerprintToken(token) {
|
|
34
|
+
return crypto.createHash('sha256').update(token).digest('hex').slice(0, 12);
|
|
35
|
+
}
|
|
36
|
+
// --- Provider-specific parsers ---------------------------------------------
|
|
37
|
+
/** Grok ~/.grok/auth.json: dict keyed by "issuer::client_id" → { key, email, expires_at, ... }. */
|
|
38
|
+
function parseGrokCredentials(raw) {
|
|
39
|
+
try {
|
|
40
|
+
const data = JSON.parse(raw);
|
|
41
|
+
for (const entry of Object.values(data)) {
|
|
42
|
+
if (!entry || typeof entry !== 'object')
|
|
43
|
+
continue;
|
|
44
|
+
const token = typeof entry.key === 'string' ? entry.key : '';
|
|
45
|
+
if (!token)
|
|
46
|
+
continue;
|
|
47
|
+
const expiresRaw = entry.expires_at ?? entry.expiresAt;
|
|
48
|
+
let expiresAt = null;
|
|
49
|
+
if (typeof expiresRaw === 'number')
|
|
50
|
+
expiresAt = expiresRaw;
|
|
51
|
+
else if (typeof expiresRaw === 'string') {
|
|
52
|
+
const ms = Date.parse(expiresRaw);
|
|
53
|
+
expiresAt = Number.isFinite(ms) ? ms : null;
|
|
54
|
+
}
|
|
55
|
+
const email = typeof entry.email === 'string' ? entry.email : null;
|
|
56
|
+
const label = typeof entry.principal_type === 'string' ? entry.principal_type : null;
|
|
57
|
+
return { fingerprint: fingerprintToken(token), label, email, expiresAt, valid: true };
|
|
58
|
+
}
|
|
59
|
+
return { fingerprint: null, label: null, email: null, expiresAt: null, valid: false };
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return { fingerprint: null, label: null, email: null, expiresAt: null, valid: false };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Codex ~/.codex/auth.json: { tokens: { access_token, id_token, ... } }; plan/email live in the id_token JWT. */
|
|
66
|
+
function parseCodexCredentials(raw) {
|
|
67
|
+
try {
|
|
68
|
+
const data = JSON.parse(raw);
|
|
69
|
+
const tokens = data.tokens;
|
|
70
|
+
const accessToken = typeof tokens?.access_token === 'string' ? tokens.access_token : '';
|
|
71
|
+
const idToken = typeof tokens?.id_token === 'string' ? tokens.id_token : '';
|
|
72
|
+
// API-key-only auth (no ChatGPT login) is also valid.
|
|
73
|
+
const apiKey = typeof data.OPENAI_API_KEY === 'string' ? data.OPENAI_API_KEY : '';
|
|
74
|
+
const fpToken = accessToken || apiKey;
|
|
75
|
+
if (!fpToken)
|
|
76
|
+
return { fingerprint: null, label: null, email: null, expiresAt: null, valid: false };
|
|
77
|
+
let email = null;
|
|
78
|
+
let label = apiKey && !accessToken ? 'API key' : null;
|
|
79
|
+
let expiresAt = null;
|
|
80
|
+
const claims = idToken ? decodeJwtPayload(idToken) : null;
|
|
81
|
+
if (claims) {
|
|
82
|
+
if (typeof claims.email === 'string')
|
|
83
|
+
email = claims.email;
|
|
84
|
+
const auth = claims['https://api.openai.com/auth'];
|
|
85
|
+
if (auth && typeof auth.chatgpt_plan_type === 'string')
|
|
86
|
+
label = auth.chatgpt_plan_type;
|
|
87
|
+
}
|
|
88
|
+
// Access-token expiry (its own JWT exp) — the value the CLI refreshes on.
|
|
89
|
+
const accessClaims = accessToken ? decodeJwtPayload(accessToken) : null;
|
|
90
|
+
if (accessClaims && typeof accessClaims.exp === 'number')
|
|
91
|
+
expiresAt = accessClaims.exp * 1000;
|
|
92
|
+
return { fingerprint: fingerprintToken(fpToken), label, email, expiresAt, valid: true };
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return { fingerprint: null, label: null, email: null, expiresAt: null, valid: false };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// --- Provider registry (dir overridable for tests) -------------------------
|
|
99
|
+
let dirOverrides = {};
|
|
100
|
+
export function setProviderCredentialsDirForTests(overrides) {
|
|
101
|
+
dirOverrides = overrides;
|
|
102
|
+
}
|
|
103
|
+
function providerConfig(provider) {
|
|
104
|
+
if (provider === 'grok') {
|
|
105
|
+
return {
|
|
106
|
+
provider,
|
|
107
|
+
dir: dirOverrides.grok ?? path.join(os.homedir(), '.grok'),
|
|
108
|
+
activeFile: 'auth.json',
|
|
109
|
+
namedPrefix: 'auth.',
|
|
110
|
+
namedSuffix: '.json',
|
|
111
|
+
parse: parseGrokCredentials,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
provider,
|
|
116
|
+
dir: dirOverrides.codex ?? path.join(os.homedir(), '.codex'),
|
|
117
|
+
activeFile: 'auth.json',
|
|
118
|
+
namedPrefix: 'auth.',
|
|
119
|
+
namedSuffix: '.json',
|
|
120
|
+
parse: parseCodexCredentials,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$/;
|
|
124
|
+
export function isValidProviderProfileName(name) {
|
|
125
|
+
if (typeof name !== 'string' || !NAME_RE.test(name))
|
|
126
|
+
return false;
|
|
127
|
+
if (name === 'json' || name.includes('/') || name.includes('\\') || name.includes('..'))
|
|
128
|
+
return false;
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
function assertValidName(name) {
|
|
132
|
+
if (!isValidProviderProfileName(name)) {
|
|
133
|
+
throw new Error(`Invalid profile name "${name}". Use 1–64 chars: letters, digits, dot, underscore, hyphen; must start with alphanumeric.`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function activePath(cfg) {
|
|
137
|
+
return path.join(cfg.dir, cfg.activeFile);
|
|
138
|
+
}
|
|
139
|
+
function namedPath(cfg, name) {
|
|
140
|
+
return path.join(cfg.dir, `${cfg.namedPrefix}${name}${cfg.namedSuffix}`);
|
|
141
|
+
}
|
|
142
|
+
function parseFile(cfg, filePath) {
|
|
143
|
+
if (!fs.existsSync(filePath))
|
|
144
|
+
return null;
|
|
145
|
+
try {
|
|
146
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
147
|
+
const meta = cfg.parse(raw);
|
|
148
|
+
return { raw, ...meta };
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
log.warn(`Failed to parse ${cfg.provider} credentials at ${filePath}: ${err}`);
|
|
152
|
+
return { raw: '', fingerprint: null, label: null, email: null, expiresAt: null, valid: false };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function fileMtime(filePath) {
|
|
156
|
+
try {
|
|
157
|
+
return fs.statSync(filePath).mtimeMs;
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function toMeta(cfg, id, name, filePath, parsed, isActive, matchesNamed) {
|
|
164
|
+
return {
|
|
165
|
+
id,
|
|
166
|
+
name,
|
|
167
|
+
isActive,
|
|
168
|
+
path: filePath,
|
|
169
|
+
valid: parsed?.valid ?? false,
|
|
170
|
+
fingerprint: parsed?.fingerprint ?? null,
|
|
171
|
+
label: parsed?.label ?? null,
|
|
172
|
+
email: parsed?.email ?? null,
|
|
173
|
+
expiresAt: parsed?.expiresAt ?? null,
|
|
174
|
+
mtimeMs: fileMtime(filePath),
|
|
175
|
+
matchesNamed,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function listNamedProfileNames(cfg) {
|
|
179
|
+
if (!fs.existsSync(cfg.dir))
|
|
180
|
+
return [];
|
|
181
|
+
const names = [];
|
|
182
|
+
for (const entry of fs.readdirSync(cfg.dir)) {
|
|
183
|
+
if (entry === cfg.activeFile)
|
|
184
|
+
continue;
|
|
185
|
+
if (!entry.startsWith(cfg.namedPrefix) || !entry.endsWith(cfg.namedSuffix))
|
|
186
|
+
continue;
|
|
187
|
+
const name = entry.slice(cfg.namedPrefix.length, entry.length - cfg.namedSuffix.length);
|
|
188
|
+
if (!name || !isValidProviderProfileName(name))
|
|
189
|
+
continue;
|
|
190
|
+
names.push(name);
|
|
191
|
+
}
|
|
192
|
+
names.sort((a, b) => a.localeCompare(b));
|
|
193
|
+
return names;
|
|
194
|
+
}
|
|
195
|
+
/** List the active auth file plus every named profile. Never returns tokens. */
|
|
196
|
+
export function listProviderCredentialProfiles(provider) {
|
|
197
|
+
const cfg = providerConfig(provider);
|
|
198
|
+
const activeFile = activePath(cfg);
|
|
199
|
+
const activeParsed = parseFile(cfg, activeFile);
|
|
200
|
+
const namedNames = listNamedProfileNames(cfg);
|
|
201
|
+
const namedByFp = new Map();
|
|
202
|
+
for (const name of namedNames) {
|
|
203
|
+
const parsed = parseFile(cfg, namedPath(cfg, name));
|
|
204
|
+
if (parsed?.fingerprint)
|
|
205
|
+
namedByFp.set(parsed.fingerprint, name);
|
|
206
|
+
}
|
|
207
|
+
const activeMatchesNamed = activeParsed?.fingerprint ? (namedByFp.get(activeParsed.fingerprint) ?? null) : null;
|
|
208
|
+
const active = fs.existsSync(activeFile)
|
|
209
|
+
? toMeta(cfg, 'active', 'active', activeFile, activeParsed, true, activeMatchesNamed)
|
|
210
|
+
: null;
|
|
211
|
+
const profiles = namedNames.map((name) => {
|
|
212
|
+
const p = namedPath(cfg, name);
|
|
213
|
+
const parsed = parseFile(cfg, p);
|
|
214
|
+
const isActive = Boolean(activeParsed?.fingerprint) && parsed?.fingerprint === activeParsed?.fingerprint;
|
|
215
|
+
return toMeta(cfg, name, name, p, parsed, isActive, null);
|
|
216
|
+
});
|
|
217
|
+
return { provider, dir: cfg.dir, active, profiles };
|
|
218
|
+
}
|
|
219
|
+
function ensureDir(cfg) {
|
|
220
|
+
if (!fs.existsSync(cfg.dir))
|
|
221
|
+
fs.mkdirSync(cfg.dir, { recursive: true, mode: 0o700 });
|
|
222
|
+
}
|
|
223
|
+
/** Atomic write with restrictive permissions (credentials are secrets). */
|
|
224
|
+
function writeAtomic(cfg, filePath, content) {
|
|
225
|
+
ensureDir(cfg);
|
|
226
|
+
const tmp = path.join(cfg.dir, `.auth.tmp.${process.pid}.${Date.now()}`);
|
|
227
|
+
fs.writeFileSync(tmp, content, { encoding: 'utf-8', mode: 0o600 });
|
|
228
|
+
fs.renameSync(tmp, filePath);
|
|
229
|
+
try {
|
|
230
|
+
fs.chmodSync(filePath, 0o600);
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// best-effort
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Switch the active account to a named profile. Optionally stash the current
|
|
238
|
+
* active account under a name first (so an unsaved live login isn't lost).
|
|
239
|
+
*/
|
|
240
|
+
export function switchProviderCredentialProfile(provider, name, opts = {}) {
|
|
241
|
+
assertValidName(name);
|
|
242
|
+
const cfg = providerConfig(provider);
|
|
243
|
+
const activeFile = activePath(cfg);
|
|
244
|
+
const targetFile = namedPath(cfg, name);
|
|
245
|
+
if (!fs.existsSync(targetFile))
|
|
246
|
+
throw new Error(`Named profile "${name}" not found`);
|
|
247
|
+
const targetParsed = parseFile(cfg, targetFile);
|
|
248
|
+
if (!targetParsed?.valid || !targetParsed.raw)
|
|
249
|
+
throw new Error(`Profile "${name}" has no valid credentials`);
|
|
250
|
+
const listing = listProviderCredentialProfiles(provider);
|
|
251
|
+
const previousMatchesNamed = listing.active?.matchesNamed ?? null;
|
|
252
|
+
let stashedAs = null;
|
|
253
|
+
if (listing.active?.valid) {
|
|
254
|
+
const stash = opts.stashActiveAs?.trim();
|
|
255
|
+
if (!previousMatchesNamed && stash) {
|
|
256
|
+
assertValidName(stash);
|
|
257
|
+
if (stash === name)
|
|
258
|
+
throw new Error('stashActiveAs cannot be the same as the profile you are switching to');
|
|
259
|
+
const stashFile = namedPath(cfg, stash);
|
|
260
|
+
if (fs.existsSync(stashFile)) {
|
|
261
|
+
const existing = parseFile(cfg, stashFile);
|
|
262
|
+
if (existing?.fingerprint && existing.fingerprint !== listing.active.fingerprint) {
|
|
263
|
+
throw new Error(`Profile "${stash}" already exists with different credentials. Choose another name.`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const activeRaw = parseFile(cfg, activeFile)?.raw;
|
|
267
|
+
if (!activeRaw)
|
|
268
|
+
throw new Error('Failed to read active credentials for stash');
|
|
269
|
+
writeAtomic(cfg, stashFile, activeRaw);
|
|
270
|
+
stashedAs = stash;
|
|
271
|
+
log.log(`Stashed previous active ${provider} credentials as profile "${stash}"`);
|
|
272
|
+
}
|
|
273
|
+
else if (previousMatchesNamed) {
|
|
274
|
+
// Keep the matched named copy in sync with the (possibly refreshed) active file.
|
|
275
|
+
const matchedRaw = parseFile(cfg, activeFile)?.raw;
|
|
276
|
+
if (matchedRaw)
|
|
277
|
+
writeAtomic(cfg, namedPath(cfg, previousMatchesNamed), matchedRaw);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
writeAtomic(cfg, activeFile, targetParsed.raw);
|
|
281
|
+
log.log(`Switched active ${provider} credentials to profile "${name}"`);
|
|
282
|
+
const after = listProviderCredentialProfiles(provider);
|
|
283
|
+
if (!after.active)
|
|
284
|
+
throw new Error('Active credentials missing after switch');
|
|
285
|
+
return { ok: true, active: after.active, profiles: after.profiles, stashedAs, previousMatchesNamed };
|
|
286
|
+
}
|
|
287
|
+
/** Save (copy) the current active credentials as a named profile. */
|
|
288
|
+
export function saveActiveProviderCredentialProfile(provider, name, opts = {}) {
|
|
289
|
+
assertValidName(name);
|
|
290
|
+
const cfg = providerConfig(provider);
|
|
291
|
+
const activeParsed = parseFile(cfg, activePath(cfg));
|
|
292
|
+
if (!activeParsed?.valid || !activeParsed.raw)
|
|
293
|
+
throw new Error(`No valid active ${provider} credentials to save`);
|
|
294
|
+
const dest = namedPath(cfg, name);
|
|
295
|
+
if (fs.existsSync(dest) && !opts.force) {
|
|
296
|
+
const existing = parseFile(cfg, dest);
|
|
297
|
+
if (existing?.fingerprint && existing.fingerprint !== activeParsed.fingerprint) {
|
|
298
|
+
throw new Error(`Profile "${name}" already exists with different credentials. Pass force=true to overwrite.`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
writeAtomic(cfg, dest, activeParsed.raw);
|
|
302
|
+
log.log(`Saved active ${provider} credentials as profile "${name}"`);
|
|
303
|
+
return listProviderCredentialProfiles(provider);
|
|
304
|
+
}
|
|
305
|
+
/** Rename a named profile file. */
|
|
306
|
+
export function renameProviderCredentialProfile(provider, from, to) {
|
|
307
|
+
assertValidName(from);
|
|
308
|
+
assertValidName(to);
|
|
309
|
+
if (from === to)
|
|
310
|
+
return listProviderCredentialProfiles(provider);
|
|
311
|
+
const cfg = providerConfig(provider);
|
|
312
|
+
const src = namedPath(cfg, from);
|
|
313
|
+
const dest = namedPath(cfg, to);
|
|
314
|
+
if (!fs.existsSync(src))
|
|
315
|
+
throw new Error(`Named profile "${from}" not found`);
|
|
316
|
+
if (fs.existsSync(dest))
|
|
317
|
+
throw new Error(`Profile "${to}" already exists`);
|
|
318
|
+
fs.renameSync(src, dest);
|
|
319
|
+
try {
|
|
320
|
+
fs.chmodSync(dest, 0o600);
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
// ignore
|
|
324
|
+
}
|
|
325
|
+
log.log(`Renamed ${provider} credentials profile "${from}" → "${to}"`);
|
|
326
|
+
return listProviderCredentialProfiles(provider);
|
|
327
|
+
}
|
|
328
|
+
/** Delete a named profile. */
|
|
329
|
+
export function deleteProviderCredentialProfile(provider, name) {
|
|
330
|
+
assertValidName(name);
|
|
331
|
+
const cfg = providerConfig(provider);
|
|
332
|
+
const file = namedPath(cfg, name);
|
|
333
|
+
if (!fs.existsSync(file))
|
|
334
|
+
throw new Error(`Named profile "${name}" not found`);
|
|
335
|
+
fs.unlinkSync(file);
|
|
336
|
+
log.log(`Deleted ${provider} credentials profile "${name}"`);
|
|
337
|
+
return listProviderCredentialProfiles(provider);
|
|
338
|
+
}
|
|
@@ -293,3 +293,49 @@ export function setInteractiveModeEnabled(enabled) {
|
|
|
293
293
|
throw error;
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
|
+
// ============================================================================
|
|
297
|
+
// Codex App-Server Mode Setting
|
|
298
|
+
// ============================================================================
|
|
299
|
+
//
|
|
300
|
+
// Experimental: when enabled, Codex agents run through a persistent
|
|
301
|
+
// `codex app-server` JSON-RPC process instead of one `codex exec` process per
|
|
302
|
+
// turn. The app-server protocol streams word-by-word agent-message deltas
|
|
303
|
+
// (item/agentMessage/delta), which `codex exec --experimental-json` never
|
|
304
|
+
// emits, so this is the only way Codex replies can typewriter in the UI.
|
|
305
|
+
// Like interactive mode, the setting is read live at each launch — no server
|
|
306
|
+
// restart needed to switch.
|
|
307
|
+
const CODEX_APP_SERVER_MODE_FILE = path.join(DATA_DIR, 'codex-app-server-mode.json');
|
|
308
|
+
/**
|
|
309
|
+
* Check if experimental Codex app-server (streaming) mode is enabled.
|
|
310
|
+
*/
|
|
311
|
+
export function isCodexAppServerModeEnabled() {
|
|
312
|
+
ensureDataDir();
|
|
313
|
+
try {
|
|
314
|
+
if (fs.existsSync(CODEX_APP_SERVER_MODE_FILE)) {
|
|
315
|
+
const data = JSON.parse(fs.readFileSync(CODEX_APP_SERVER_MODE_FILE, 'utf-8'));
|
|
316
|
+
return data.enabled;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
log.error(` Failed to load codex app-server mode setting: ${error.message}`);
|
|
321
|
+
}
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Enable/disable experimental Codex app-server (streaming) mode.
|
|
326
|
+
*/
|
|
327
|
+
export function setCodexAppServerModeEnabled(enabled) {
|
|
328
|
+
ensureDataDir();
|
|
329
|
+
const data = {
|
|
330
|
+
enabled,
|
|
331
|
+
updatedAt: Date.now(),
|
|
332
|
+
};
|
|
333
|
+
try {
|
|
334
|
+
fs.writeFileSync(CODEX_APP_SERVER_MODE_FILE, JSON.stringify(data, null, 2), 'utf-8');
|
|
335
|
+
log.log(` Codex app-server mode setting updated: enabled=${enabled}`);
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
log.error(` Failed to save codex app-server mode setting: ${error.message}`);
|
|
339
|
+
throw error;
|
|
340
|
+
}
|
|
341
|
+
}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as me,r as l,n as ge,j as e,I as xe,o as fe}from"./main-aIpEYDDR.js";function je({isOpen:E,onClose:L,onMinimize:P,title:z,icon:U,lines:c,isStreaming:B,onClear:J,emptyMessage:F,streamingIndicatorLabel:X,headerInfo:Y,isLoading:V,extraToolbar:Z,extraFooter:O,modalClassName:ee}){const{t:a}=me(["terminal","common"]),[u,$]=l.useState(""),[h,w]=l.useState(!1),[f,S]=l.useState(!1),[M,I]=l.useState(""),[k,p]=l.useState(!0),[R,te]=l.useState(!0),[se,W]=l.useState(null),[r,le]=l.useState([]),[m,j]=l.useState(0),[v,ne]=l.useState(!1),[T,re]=l.useState(5),[Q,C]=l.useState(null),[y,ae]=l.useState(!0),o=l.useRef(null),D=l.useRef(null),A=l.useRef(null),H=l.useRef(!1),_=l.useRef(0),K=l.useMemo(()=>c.map(t=>t.text),[c]),b=l.useMemo(()=>{if(!u)return C(null),null;try{const t=v?u:u.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),s=new RegExp(t,"gi");return C(null),s}catch(t){return C(t.message),null}},[u,v]),N=l.useMemo(()=>{if(!b)return[];const t=[];for(let s=0;s<K.length;s++)b.test(K[s])&&t.push(s),b.lastIndex=0;return t},[K,b]);l.useEffect(()=>{le(N),m>=N.length&&j(Math.max(0,N.length-1))},[N]);const oe=l.useMemo(()=>{const t=c.map((i,x)=>({entry:i,originalIndex:x}));if(!u||!b||y)return t;if(N.length===0)return[];const s=new Set;for(const i of N){const x=Math.max(0,i-T),de=Math.min(c.length-1,i+T);for(let G=x;G<=de;G++)s.add(G)}const n=Array.from(s).sort((i,x)=>i-x),d=[];for(let i=0;i<n.length;i++){const x=n[i];i>0&&x-n[i-1]>1&&d.push({entry:{text:"",lineNumber:-1},originalIndex:-1,isSeparator:!0}),d.push({entry:c[x],originalIndex:x})}return d},[c,u,b,N,T,y]);l.useEffect(()=>{k&&o.current&&c.length>_.current&&(H.current=!0,requestAnimationFrame(()=>{o.current&&(o.current.scrollTop=o.current.scrollHeight),setTimeout(()=>{H.current=!1},50)})),_.current=c.length},[c.length,k]),l.useEffect(()=>{h&&D.current&&D.current.focus()},[h]),l.useEffect(()=>{f&&A.current&&A.current.focus()},[f]);const g=l.useCallback(t=>{if(!o.current)return;const n=t*18;o.current.scrollTop=n-100,W(t),setTimeout(()=>W(null),2e3)},[]);l.useEffect(()=>{if(!E)return;const t=s=>{if(s.key==="Escape"){s.preventDefault(),s.stopPropagation(),s.stopImmediatePropagation(),h?w(!1):f?S(!1):L();return}if(s.key==="/"&&!h&&!f&&(s.preventDefault(),w(!0)),s.key==="g"&&s.ctrlKey&&(s.preventDefault(),S(!0)),s.key==="End"&&s.ctrlKey&&o.current&&(o.current.scrollTop=o.current.scrollHeight),s.key==="Home"&&s.ctrlKey&&o.current&&(o.current.scrollTop=0),(s.key==="F3"||s.key==="Enter"&&h)&&r.length>0)if(s.preventDefault(),s.shiftKey){const n=(m-1+r.length)%r.length;j(n),g(r[n])}else{const n=(m+1)%r.length;j(n),g(r[n])}if(!h&&!f&&r.length>0){if(s.key==="n"&&!s.ctrlKey){s.preventDefault();const n=(m+1)%r.length;j(n),g(r[n])}else if(s.key==="N"){s.preventDefault();const n=(m-1+r.length)%r.length;j(n),g(r[n])}}!h&&!f&&o.current&&(s.key==="j"?(s.preventDefault(),o.current.scrollTop+=60,p(!1)):s.key==="k"?(s.preventDefault(),o.current.scrollTop-=60,p(!1)):s.key==="G"&&!s.ctrlKey?(s.preventDefault(),o.current.scrollTop=o.current.scrollHeight,p(!0)):s.key==="g"&&!s.ctrlKey&&(s.preventDefault(),o.current.scrollTop=0,p(!1)))};return window.addEventListener("keydown",t,{capture:!0}),()=>window.removeEventListener("keydown",t,{capture:!0})},[E,h,f,r,m,L,g]);const q=l.useCallback(()=>{const t=parseInt(M,10);!isNaN(t)&&t>0&&t<=c.length&&(g(t-1),p(!1)),S(!1),I("")},[M,c.length,g]),ce=l.useCallback(()=>{if(H.current||!o.current)return;const{scrollTop:t,scrollHeight:s,clientHeight:n}=o.current,d=s-t-n<50;!d&&k&&p(!1),d&&!k&&p(!0)},[k]),ie=l.useCallback(t=>{if(!u||!b)return t;const s=v?u:u.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");try{const n=new RegExp(`(${s})`,"gi");return t.replace(n,'<mark class="search-highlight">$1</mark>')}catch{return t}},[u,b,v]),{handleMouseDown:ue,handleClick:he}=ge(L);return E?e.jsx("div",{className:"pm2-logs-modal-overlay",onMouseDown:ue,onClick:he,children:e.jsxs("div",{className:`pm2-logs-modal ${ee||""}`,children:[e.jsxs("div",{className:"pm2-logs-modal-header",children:[e.jsxs("div",{className:"header-left",children:[e.jsx("span",{className:"modal-icon",children:U}),e.jsx("span",{className:"modal-title",children:z}),B&&e.jsxs("span",{className:"streaming-indicator",title:"Live streaming",children:[e.jsx("span",{className:"pulse"}),X||a("terminal:logs.live")]}),Y]}),e.jsxs("div",{className:"header-right",children:[e.jsx("span",{className:"line-count",children:a("terminal:logs.lines",{count:c.length})}),P&&e.jsx("button",{className:"modal-close",onClick:P,title:"Minimize — dock below the terminal input",children:e.jsx(xe,{name:"arrow-down",size:14})}),e.jsx("button",{className:"modal-close",onClick:L,title:a("terminal:logs.closeEsc"),children:"×"})]})]}),e.jsxs("div",{className:"pm2-logs-modal-toolbar",children:[e.jsxs("div",{className:"toolbar-left",children:[e.jsxs("button",{className:`toolbar-btn ${h?"active":""}`,onClick:()=>w(!h),title:a("terminal:logs.searchShortcut"),children:["🔍 ",a("terminal:logs.search")]}),e.jsxs("button",{className:"toolbar-btn",onClick:()=>S(!0),title:a("terminal:logs.goToLineShortcut"),children:["⏬ ",a("terminal:logs.goToLine")]}),Z,e.jsxs("button",{className:`toolbar-btn ${R?"active":""}`,onClick:()=>te(!R),title:a("terminal:logs.toggleWrap"),children:["↩ ",a("terminal:logs.wrap")]}),e.jsxs("button",{className:`toolbar-btn ${k?"active":""}`,onClick:()=>p(!k),title:a("terminal:logs.autoScrollToBottom"),children:["↓ ",a("terminal:logs.auto")]})]}),e.jsx("div",{className:"toolbar-right",children:e.jsxs("button",{className:"toolbar-btn danger",onClick:J,title:a("terminal:logs.clear"),children:["🗑 ",a("terminal:logs.clear")]})})]}),h&&e.jsxs("div",{className:"pm2-logs-search-bar",children:[e.jsx("input",{ref:D,type:"text",placeholder:a(v?"terminal:logs.regexPlaceholder":"terminal:logs.searchPlaceholder"),value:u,onChange:t=>{$(t.target.value),j(0)},onKeyDown:t=>{t.key==="Escape"&&(w(!1),$(""),C(null))}}),e.jsx("button",{className:`toolbar-btn small ${v?"active":""}`,onClick:()=>ne(!v),title:"Toggle regex mode",children:".*"}),e.jsx("button",{className:`toolbar-btn small ${y?"active":""}`,onClick:()=>ae(!y),title:y?"Show all lines (highlight matches)":"Show only context around matches",children:y?"All":"Ctx"}),e.jsxs("div",{className:`context-control ${y?"hidden":""}`,title:"Lines of context around matches",children:[e.jsx("label",{children:"±"}),e.jsx("input",{type:"number",min:"0",max:"100",value:T,onChange:t=>re(Math.max(0,parseInt(t.target.value)||0)),className:"context-input"})]}),e.jsx("button",{className:"toolbar-btn small",onClick:()=>{if(r.length===0)return;const t=(m-1+r.length)%r.length;j(t),g(r[t])},disabled:r.length===0,title:"Previous match (Shift+F3)",children:"▲"}),e.jsx("button",{className:"toolbar-btn small",onClick:()=>{if(r.length===0)return;const t=(m+1)%r.length;j(t),g(r[t])},disabled:r.length===0,title:"Next match (F3)",children:"▼"}),u&&e.jsx("span",{className:"match-count",children:Q?e.jsx("span",{className:"regex-error",title:Q,children:a("terminal:logs.invalidRegex")}):r.length>0?`${m+1}/${r.length}`:a("terminal:logs.noMatches")}),e.jsx("button",{className:"search-close",onClick:()=>{w(!1),$(""),C(null)},children:"×"})]}),f&&e.jsxs("div",{className:"pm2-logs-goto-line",children:[e.jsxs("label",{children:[a("terminal:logs.goToLineLabel"),":"]}),e.jsx("input",{ref:A,type:"number",min:"1",max:c.length,placeholder:`1-${c.length}`,value:M,onChange:t=>I(t.target.value),onKeyDown:t=>{t.key==="Enter"?q():t.key==="Escape"&&(S(!1),I(""))}}),e.jsx("button",{onClick:q,children:a("terminal:logs.go")}),e.jsx("button",{onClick:()=>S(!1),children:a("common:buttons.cancel")})]}),e.jsx("div",{ref:o,className:`pm2-logs-content ${R?"wrap":"nowrap"}`,onScroll:ce,children:c.length===0?e.jsx("div",{className:"logs-empty",children:V||B?e.jsxs("div",{className:"logs-loading",children:[e.jsx("span",{className:"logs-loading-spinner","aria-hidden":"true"}),e.jsx("span",{children:F||a(V?"terminal:logs.loadingLogs":"terminal:logs.waitingForLogs")})]}):e.jsx("span",{children:F||a("terminal:logs.noLogs")})}):e.jsx("div",{className:"logs-lines",children:oe.map((t,s)=>{if("isSeparator"in t&&t.isSeparator)return e.jsxs("div",{className:"log-separator",children:[e.jsx("span",{className:"separator-line"}),e.jsx("span",{className:"separator-label",children:"…"}),e.jsx("span",{className:"separator-line"})]},`sep-${s}`);const{entry:n,originalIndex:d}=t,i=u&&N.includes(d);return e.jsxs("div",{className:`log-line ${se===d?"highlighted":""} ${r[m]===d?"current-match":""} ${i?"match-line":""} ${n.isError?"error-line":""}`,children:[e.jsx("span",{className:"line-number",children:n.lineNumber}),n.sourceLabel&&e.jsxs("span",{className:"boss-log-source",style:{color:n.sourceColor},children:["[",n.sourceLabel,"]"]}),e.jsx("span",{className:"line-content",dangerouslySetInnerHTML:{__html:ie(fe(n.text))}})]},d)})})}),e.jsxs("div",{className:"pm2-logs-modal-footer",children:[e.jsxs("span",{className:"shortcut",children:[e.jsx("kbd",{children:"j"}),"/",e.jsx("kbd",{children:"k"})," Scroll"]}),e.jsxs("span",{className:"shortcut",children:[e.jsx("kbd",{children:"g"}),"/",e.jsx("kbd",{children:"G"})," Top/Bottom"]}),e.jsxs("span",{className:"shortcut",children:[e.jsx("kbd",{children:"/"})," Search"]}),e.jsxs("span",{className:"shortcut",children:[e.jsx("kbd",{children:"n"}),"/",e.jsx("kbd",{children:"N"})," Next/Prev match"]}),e.jsxs("span",{className:"shortcut",children:[e.jsx("kbd",{children:"Ctrl+G"})," Go to line"]}),e.jsxs("span",{className:"shortcut",children:[e.jsx("kbd",{children:"Esc"})," Close"]}),O]})]})}):null}export{je as L};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{i as At,k as yt,aC as Et,a5 as xt,m as Ct,cA as Mt,cB as Ft,aU as wt,r as d,$ as St,S as pe,cC as Bt,cD as fe,s as V,cE as vt,j as f,I as ne,cF as Ve,cG as It,a9 as _t,cH as Dt,cI as kt,cJ as Ee,aq as ve,_ as Rt,v as nt,u as Fe,cK as Je}from"./main-aIpEYDDR.js";import{cL as Ls,cM as $s,cN as js,cO as Ns,cP as Ps}from"./main-aIpEYDDR.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";function re(t){return Array.isArray?Array.isArray(t):ct(t)==="[object Array]"}function bt(t){if(typeof t=="string")return t;let e=t+"";return e=="0"&&1/t==-1/0?"-0":e}function Tt(t){return t==null?"":bt(t)}function Z(t){return typeof t=="string"}function rt(t){return typeof t=="number"}function Lt(t){return t===!0||t===!1||$t(t)&&ct(t)=="[object Boolean]"}function it(t){return typeof t=="object"}function $t(t){return it(t)&&t!==null}function G(t){return t!=null}function Ie(t){return!t.trim().length}function ct(t){return t==null?t===void 0?"[object Undefined]":"[object Null]":Object.prototype.toString.call(t)}const jt="Incorrect 'index' type",Nt=t=>`Invalid value for key ${t}`,Pt=t=>`Pattern length exceeds max of ${t}.`,Kt=t=>`Missing ${t} property in key`,Ot=t=>`Property 'weight' in key '${t}' must be a positive integer`,Xe=Object.prototype.hasOwnProperty;class zt{constructor(e){this._keys=[],this._keyMap={};let n=0;e.forEach(r=>{let i=ot(r);this._keys.push(i),this._keyMap[i.id]=i,n+=i.weight}),this._keys.forEach(r=>{r.weight/=n})}get(e){return this._keyMap[e]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}}function ot(t){let e=null,n=null,r=null,i=1,c=null;if(Z(t)||re(t))r=t,e=qe(t),n=_e(t);else{if(!Xe.call(t,"name"))throw new Error(Kt("name"));const o=t.name;if(r=o,Xe.call(t,"weight")&&(i=t.weight,i<=0))throw new Error(Ot(o));e=qe(o),n=_e(o),c=t.getFn}return{path:e,id:n,weight:i,src:r,getFn:c}}function qe(t){return re(t)?t:t.split(".")}function _e(t){return re(t)?t.join("."):t}function Gt(t,e){let n=[],r=!1;const i=(c,o,a)=>{if(G(c))if(!o[a])n.push(c);else{let u=o[a];const l=c[u];if(!G(l))return;if(a===o.length-1&&(Z(l)||rt(l)||Lt(l)))n.push(Tt(l));else if(re(l)){r=!0;for(let h=0,E=l.length;h<E;h+=1)i(l[h],o,a+1)}else o.length&&i(l,o,a+1)}};return i(t,Z(e)?e.split("."):e,0),r?n:n[0]}const Qt={includeMatches:!1,findAllMatches:!1,minMatchCharLength:1},Wt={isCaseSensitive:!1,ignoreDiacritics:!1,includeScore:!1,keys:[],shouldSort:!0,sortFn:(t,e)=>t.score===e.score?t.idx<e.idx?-1:1:t.score<e.score?-1:1},Ht={location:0,threshold:.6,distance:100},Ut={useExtendedSearch:!1,getFn:Gt,ignoreLocation:!1,ignoreFieldNorm:!1,fieldNormWeight:1};var y={...Wt,...Qt,...Ht,...Ut};const Yt=/[^ ]+/g;function Vt(t=1,e=3){const n=new Map,r=Math.pow(10,e);return{get(i){const c=i.match(Yt).length;if(n.has(c))return n.get(c);const o=1/Math.pow(c,.5*t),a=parseFloat(Math.round(o*r)/r);return n.set(c,a),a},clear(){n.clear()}}}class Le{constructor({getFn:e=y.getFn,fieldNormWeight:n=y.fieldNormWeight}={}){this.norm=Vt(n,3),this.getFn=e,this.isCreated=!1,this.setIndexRecords()}setSources(e=[]){this.docs=e}setIndexRecords(e=[]){this.records=e}setKeys(e=[]){this.keys=e,this._keysMap={},e.forEach((n,r)=>{this._keysMap[n.id]=r})}create(){this.isCreated||!this.docs.length||(this.isCreated=!0,Z(this.docs[0])?this.docs.forEach((e,n)=>{this._addString(e,n)}):this.docs.forEach((e,n)=>{this._addObject(e,n)}),this.norm.clear())}add(e){const n=this.size();Z(e)?this._addString(e,n):this._addObject(e,n)}removeAt(e){this.records.splice(e,1);for(let n=e,r=this.size();n<r;n+=1)this.records[n].i-=1}getValueForItemAtKeyId(e,n){return e[this._keysMap[n]]}size(){return this.records.length}_addString(e,n){if(!G(e)||Ie(e))return;let r={v:e,i:n,n:this.norm.get(e)};this.records.push(r)}_addObject(e,n){let r={i:n,$:{}};this.keys.forEach((i,c)=>{let o=i.getFn?i.getFn(e):this.getFn(e,i.path);if(G(o)){if(re(o)){let a=[];const u=[{nestedArrIndex:-1,value:o}];for(;u.length;){const{nestedArrIndex:l,value:h}=u.pop();if(G(h))if(Z(h)&&!Ie(h)){let E={v:h,i:l,n:this.norm.get(h)};a.push(E)}else re(h)&&h.forEach((E,x)=>{u.push({nestedArrIndex:x,value:E})})}r.$[c]=a}else if(Z(o)&&!Ie(o)){let a={v:o,n:this.norm.get(o)};r.$[c]=a}}}),this.records.push(r)}toJSON(){return{keys:this.keys,records:this.records}}}function at(t,e,{getFn:n=y.getFn,fieldNormWeight:r=y.fieldNormWeight}={}){const i=new Le({getFn:n,fieldNormWeight:r});return i.setKeys(t.map(ot)),i.setSources(e),i.create(),i}function Jt(t,{getFn:e=y.getFn,fieldNormWeight:n=y.fieldNormWeight}={}){const{keys:r,records:i}=t,c=new Le({getFn:e,fieldNormWeight:n});return c.setKeys(r),c.setIndexRecords(i),c}function xe(t,{errors:e=0,currentLocation:n=0,expectedLocation:r=0,distance:i=y.distance,ignoreLocation:c=y.ignoreLocation}={}){const o=e/t.length;if(c)return o;const a=Math.abs(r-n);return i?o+a/i:a?1:o}function Xt(t=[],e=y.minMatchCharLength){let n=[],r=-1,i=-1,c=0;for(let o=t.length;c<o;c+=1){let a=t[c];a&&r===-1?r=c:!a&&r!==-1&&(i=c-1,i-r+1>=e&&n.push([r,i]),r=-1)}return t[c-1]&&c-r>=e&&n.push([r,c-1]),n}const le=32;function qt(t,e,n,{location:r=y.location,distance:i=y.distance,threshold:c=y.threshold,findAllMatches:o=y.findAllMatches,minMatchCharLength:a=y.minMatchCharLength,includeMatches:u=y.includeMatches,ignoreLocation:l=y.ignoreLocation}={}){if(e.length>le)throw new Error(Pt(le));const h=e.length,E=t.length,x=Math.max(0,Math.min(r,E));let g=c,m=x;const S=a>1||u,w=S?Array(E):[];let T;for(;(T=t.indexOf(e,m))>-1;){let $=xe(e,{currentLocation:T,expectedLocation:x,distance:i,ignoreLocation:l});if(g=Math.min($,g),m=T+h,S){let N=0;for(;N<h;)w[T+N]=1,N+=1}}m=-1;let j=[],Q=1,W=h+E;const oe=1<<h-1;for(let $=0;$<h;$+=1){let N=0,D=W;for(;N<D;)xe(e,{errors:$,currentLocation:x+D,expectedLocation:x,distance:i,ignoreLocation:l})<=g?N=D:W=D,D=Math.floor((W-N)/2+N);W=D;let ae=Math.max(1,x-D+1),H=o?E:Math.min(x+D,E)+h,B=Array(H+2);B[H+1]=(1<<$)-1;for(let R=H;R>=ae;R-=1){let X=R-1,O=n[t.charAt(X)];if(S&&(w[X]=+!!O),B[R]=(B[R+1]<<1|1)&O,$&&(B[R]|=(j[R+1]|j[R])<<1|1|j[R+1]),B[R]&oe&&(Q=xe(e,{errors:$,currentLocation:X,expectedLocation:x,distance:i,ignoreLocation:l}),Q<=g)){if(g=Q,m=X,m<=x)break;ae=Math.max(1,2*x-m)}}if(xe(e,{errors:$+1,currentLocation:x,expectedLocation:x,distance:i,ignoreLocation:l})>g)break;j=B}const ie={isMatch:m>=0,score:Math.max(.001,Q)};if(S){const $=Xt(w,a);$.length?u&&(ie.indices=$):ie.isMatch=!1}return ie}function Zt(t){let e={};for(let n=0,r=t.length;n<r;n+=1){const i=t.charAt(n);e[i]=(e[i]||0)|1<<r-n-1}return e}const Ce=String.prototype.normalize?(t=>t.normalize("NFD").replace(/[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C04\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F]/g,"")):(t=>t);class ut{constructor(e,{location:n=y.location,threshold:r=y.threshold,distance:i=y.distance,includeMatches:c=y.includeMatches,findAllMatches:o=y.findAllMatches,minMatchCharLength:a=y.minMatchCharLength,isCaseSensitive:u=y.isCaseSensitive,ignoreDiacritics:l=y.ignoreDiacritics,ignoreLocation:h=y.ignoreLocation}={}){if(this.options={location:n,threshold:r,distance:i,includeMatches:c,findAllMatches:o,minMatchCharLength:a,isCaseSensitive:u,ignoreDiacritics:l,ignoreLocation:h},e=u?e:e.toLowerCase(),e=l?Ce(e):e,this.pattern=e,this.chunks=[],!this.pattern.length)return;const E=(g,m)=>{this.chunks.push({pattern:g,alphabet:Zt(g),startIndex:m})},x=this.pattern.length;if(x>le){let g=0;const m=x%le,S=x-m;for(;g<S;)E(this.pattern.substr(g,le),g),g+=le;if(m){const w=x-le;E(this.pattern.substr(w),w)}}else E(this.pattern,0)}searchIn(e){const{isCaseSensitive:n,ignoreDiacritics:r,includeMatches:i}=this.options;if(e=n?e:e.toLowerCase(),e=r?Ce(e):e,this.pattern===e){let S={isMatch:!0,score:0};return i&&(S.indices=[[0,e.length-1]]),S}const{location:c,distance:o,threshold:a,findAllMatches:u,minMatchCharLength:l,ignoreLocation:h}=this.options;let E=[],x=0,g=!1;this.chunks.forEach(({pattern:S,alphabet:w,startIndex:T})=>{const{isMatch:j,score:Q,indices:W}=qt(e,S,w,{location:c+T,distance:o,threshold:a,findAllMatches:u,minMatchCharLength:l,includeMatches:i,ignoreLocation:h});j&&(g=!0),x+=Q,j&&W&&(E=[...E,...W])});let m={isMatch:g,score:g?x/this.chunks.length:1};return g&&i&&(m.indices=E),m}}class ce{constructor(e){this.pattern=e}static isMultiMatch(e){return Ze(e,this.multiRegex)}static isSingleMatch(e){return Ze(e,this.singleRegex)}search(){}}function Ze(t,e){const n=t.match(e);return n?n[1]:null}class es extends ce{constructor(e){super(e)}static get type(){return"exact"}static get multiRegex(){return/^="(.*)"$/}static get singleRegex(){return/^=(.*)$/}search(e){const n=e===this.pattern;return{isMatch:n,score:n?0:1,indices:[0,this.pattern.length-1]}}}class ts extends ce{constructor(e){super(e)}static get type(){return"inverse-exact"}static get multiRegex(){return/^!"(.*)"$/}static get singleRegex(){return/^!(.*)$/}search(e){const r=e.indexOf(this.pattern)===-1;return{isMatch:r,score:r?0:1,indices:[0,e.length-1]}}}class ss extends ce{constructor(e){super(e)}static get type(){return"prefix-exact"}static get multiRegex(){return/^\^"(.*)"$/}static get singleRegex(){return/^\^(.*)$/}search(e){const n=e.startsWith(this.pattern);return{isMatch:n,score:n?0:1,indices:[0,this.pattern.length-1]}}}class ns extends ce{constructor(e){super(e)}static get type(){return"inverse-prefix-exact"}static get multiRegex(){return/^!\^"(.*)"$/}static get singleRegex(){return/^!\^(.*)$/}search(e){const n=!e.startsWith(this.pattern);return{isMatch:n,score:n?0:1,indices:[0,e.length-1]}}}class rs extends ce{constructor(e){super(e)}static get type(){return"suffix-exact"}static get multiRegex(){return/^"(.*)"\$$/}static get singleRegex(){return/^(.*)\$$/}search(e){const n=e.endsWith(this.pattern);return{isMatch:n,score:n?0:1,indices:[e.length-this.pattern.length,e.length-1]}}}class is extends ce{constructor(e){super(e)}static get type(){return"inverse-suffix-exact"}static get multiRegex(){return/^!"(.*)"\$$/}static get singleRegex(){return/^!(.*)\$$/}search(e){const n=!e.endsWith(this.pattern);return{isMatch:n,score:n?0:1,indices:[0,e.length-1]}}}class lt extends ce{constructor(e,{location:n=y.location,threshold:r=y.threshold,distance:i=y.distance,includeMatches:c=y.includeMatches,findAllMatches:o=y.findAllMatches,minMatchCharLength:a=y.minMatchCharLength,isCaseSensitive:u=y.isCaseSensitive,ignoreDiacritics:l=y.ignoreDiacritics,ignoreLocation:h=y.ignoreLocation}={}){super(e),this._bitapSearch=new ut(e,{location:n,threshold:r,distance:i,includeMatches:c,findAllMatches:o,minMatchCharLength:a,isCaseSensitive:u,ignoreDiacritics:l,ignoreLocation:h})}static get type(){return"fuzzy"}static get multiRegex(){return/^"(.*)"$/}static get singleRegex(){return/^(.*)$/}search(e){return this._bitapSearch.searchIn(e)}}class ht extends ce{constructor(e){super(e)}static get type(){return"include"}static get multiRegex(){return/^'"(.*)"$/}static get singleRegex(){return/^'(.*)$/}search(e){let n=0,r;const i=[],c=this.pattern.length;for(;(r=e.indexOf(this.pattern,n))>-1;)n=r+c,i.push([r,n-1]);const o=!!i.length;return{isMatch:o,score:o?0:1,indices:i}}}const De=[es,ht,ss,ns,is,rs,ts,lt],et=De.length,cs=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,os="|";function as(t,e={}){return t.split(os).map(n=>{let r=n.trim().split(cs).filter(c=>c&&!!c.trim()),i=[];for(let c=0,o=r.length;c<o;c+=1){const a=r[c];let u=!1,l=-1;for(;!u&&++l<et;){const h=De[l];let E=h.isMultiMatch(a);E&&(i.push(new h(E,e)),u=!0)}if(!u)for(l=-1;++l<et;){const h=De[l];let E=h.isSingleMatch(a);if(E){i.push(new h(E,e));break}}}return i})}const us=new Set([lt.type,ht.type]);class ls{constructor(e,{isCaseSensitive:n=y.isCaseSensitive,ignoreDiacritics:r=y.ignoreDiacritics,includeMatches:i=y.includeMatches,minMatchCharLength:c=y.minMatchCharLength,ignoreLocation:o=y.ignoreLocation,findAllMatches:a=y.findAllMatches,location:u=y.location,threshold:l=y.threshold,distance:h=y.distance}={}){this.query=null,this.options={isCaseSensitive:n,ignoreDiacritics:r,includeMatches:i,minMatchCharLength:c,findAllMatches:a,ignoreLocation:o,location:u,threshold:l,distance:h},e=n?e:e.toLowerCase(),e=r?Ce(e):e,this.pattern=e,this.query=as(this.pattern,this.options)}static condition(e,n){return n.useExtendedSearch}searchIn(e){const n=this.query;if(!n)return{isMatch:!1,score:1};const{includeMatches:r,isCaseSensitive:i,ignoreDiacritics:c}=this.options;e=i?e:e.toLowerCase(),e=c?Ce(e):e;let o=0,a=[],u=0;for(let l=0,h=n.length;l<h;l+=1){const E=n[l];a.length=0,o=0;for(let x=0,g=E.length;x<g;x+=1){const m=E[x],{isMatch:S,indices:w,score:T}=m.search(e);if(S){if(o+=1,u+=T,r){const j=m.constructor.type;us.has(j)?a=[...a,...w]:a.push(w)}}else{u=0,o=0,a.length=0;break}}if(o){let x={isMatch:!0,score:u/o};return r&&(x.indices=a),x}}return{isMatch:!1,score:1}}}const ke=[];function hs(...t){ke.push(...t)}function Re(t,e){for(let n=0,r=ke.length;n<r;n+=1){let i=ke[n];if(i.condition(t,e))return new i(t,e)}return new ut(t,e)}const Me={AND:"$and",OR:"$or"},be={PATH:"$path",PATTERN:"$val"},Te=t=>!!(t[Me.AND]||t[Me.OR]),ds=t=>!!t[be.PATH],fs=t=>!re(t)&&it(t)&&!Te(t),tt=t=>({[Me.AND]:Object.keys(t).map(e=>({[e]:t[e]}))});function dt(t,e,{auto:n=!0}={}){const r=i=>{let c=Object.keys(i);const o=ds(i);if(!o&&c.length>1&&!Te(i))return r(tt(i));if(fs(i)){const u=o?i[be.PATH]:c[0],l=o?i[be.PATTERN]:i[u];if(!Z(l))throw new Error(Nt(u));const h={keyId:_e(u),pattern:l};return n&&(h.searcher=Re(l,e)),h}let a={children:[],operator:c[0]};return c.forEach(u=>{const l=i[u];re(l)&&l.forEach(h=>{a.children.push(r(h))})}),a};return Te(t)||(t=tt(t)),r(t)}function gs(t,{ignoreFieldNorm:e=y.ignoreFieldNorm}){t.forEach(n=>{let r=1;n.matches.forEach(({key:i,norm:c,score:o})=>{const a=i?i.weight:null;r*=Math.pow(o===0&&a?Number.EPSILON:o,(a||1)*(e?1:c))}),n.score=r})}function ps(t,e){const n=t.matches;e.matches=[],G(n)&&n.forEach(r=>{if(!G(r.indices)||!r.indices.length)return;const{indices:i,value:c}=r;let o={indices:i,value:c};r.key&&(o.key=r.key.src),r.idx>-1&&(o.refIndex=r.idx),e.matches.push(o)})}function ms(t,e){e.score=t.score}function As(t,e,{includeMatches:n=y.includeMatches,includeScore:r=y.includeScore}={}){const i=[];return n&&i.push(ps),r&&i.push(ms),t.map(c=>{const{idx:o}=c,a={item:e[o],refIndex:o};return i.length&&i.forEach(u=>{u(c,a)}),a})}class q{constructor(e,n={},r){this.options={...y,...n},this.options.useExtendedSearch,this._keyStore=new zt(this.options.keys),this.setCollection(e,r)}setCollection(e,n){if(this._docs=e,n&&!(n instanceof Le))throw new Error(jt);this._myIndex=n||at(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(e){G(e)&&(this._docs.push(e),this._myIndex.add(e))}remove(e=()=>!1){const n=[];for(let r=0,i=this._docs.length;r<i;r+=1){const c=this._docs[r];e(c,r)&&(this.removeAt(r),r-=1,i-=1,n.push(c))}return n}removeAt(e){this._docs.splice(e,1),this._myIndex.removeAt(e)}getIndex(){return this._myIndex}search(e,{limit:n=-1}={}){const{includeMatches:r,includeScore:i,shouldSort:c,sortFn:o,ignoreFieldNorm:a}=this.options;let u=Z(e)?Z(this._docs[0])?this._searchStringList(e):this._searchObjectList(e):this._searchLogical(e);return gs(u,{ignoreFieldNorm:a}),c&&u.sort(o),rt(n)&&n>-1&&(u=u.slice(0,n)),As(u,this._docs,{includeMatches:r,includeScore:i})}_searchStringList(e){const n=Re(e,this.options),{records:r}=this._myIndex,i=[];return r.forEach(({v:c,i:o,n:a})=>{if(!G(c))return;const{isMatch:u,score:l,indices:h}=n.searchIn(c);u&&i.push({item:c,idx:o,matches:[{score:l,value:c,norm:a,indices:h}]})}),i}_searchLogical(e){const n=dt(e,this.options),r=(a,u,l)=>{if(!a.children){const{keyId:E,searcher:x}=a,g=this._findMatches({key:this._keyStore.get(E),value:this._myIndex.getValueForItemAtKeyId(u,E),searcher:x});return g&&g.length?[{idx:l,item:u,matches:g}]:[]}const h=[];for(let E=0,x=a.children.length;E<x;E+=1){const g=a.children[E],m=r(g,u,l);if(m.length)h.push(...m);else if(a.operator===Me.AND)return[]}return h},i=this._myIndex.records,c={},o=[];return i.forEach(({$:a,i:u})=>{if(G(a)){let l=r(n,a,u);l.length&&(c[u]||(c[u]={idx:u,item:a,matches:[]},o.push(c[u])),l.forEach(({matches:h})=>{c[u].matches.push(...h)}))}}),o}_searchObjectList(e){const n=Re(e,this.options),{keys:r,records:i}=this._myIndex,c=[];return i.forEach(({$:o,i:a})=>{if(!G(o))return;let u=[];r.forEach((l,h)=>{u.push(...this._findMatches({key:l,value:o[h],searcher:n}))}),u.length&&c.push({idx:a,item:o,matches:u})}),c}_findMatches({key:e,value:n,searcher:r}){if(!G(n))return[];let i=[];if(re(n))n.forEach(({v:c,i:o,n:a})=>{if(!G(c))return;const{isMatch:u,score:l,indices:h}=r.searchIn(c);u&&i.push({score:l,key:e,value:c,idx:o,norm:a,indices:h})});else{const{v:c,n:o}=n,{isMatch:a,score:u,indices:l}=r.searchIn(c);a&&i.push({score:u,key:e,value:c,norm:o,indices:l})}return i}}q.version="7.1.0";q.createIndex=at;q.parseIndex=Jt;q.config=y;q.parseQuery=dt;hs(ls);async function ys(t){const e=new URLSearchParams({q:t}),n=await At(yt(`/api/folders/search?${e.toString()}`));if(!n.ok){const i=await n.json().catch(()=>({}));throw new Error(i.error||`Failed to search folders: ${n.statusText}`)}const r=await n.json();return Array.isArray(r.folders)?r.folders:[]}const Es=["command","agent","building","area","folder","modified-file"],xs=2;function Cs(){const t=nt(pe.SPOTLIGHT_TAB,"all");return fe.includes(t)?t:"all"}function st(){return Rt(pe.SPOTLIGHT_QUERY,"")}function Ms(){const t=nt(pe.AOP_CONFIG,{});return t.sortMode==="name"||t.sortMode==="status"||t.sortMode==="recent"?t.sortMode:"recent"}function Fs({isOpen:t,onClose:e,onOpenSpawnModal:n,onOpenCommanderView:r,onOpenToolbox:i,onOpenFileExplorer:c,onOpenPM2LogsModal:o,onOpenBossLogsModal:a,onOpenDatabasePanel:u,onOpenMonitoringModal:l}){const h=Et(),E=xt(),x=Ct(),g=Mt(),m=Ft(),S=wt(),w=d.useRef(e);w.current=e;const T=d.useRef(n);T.current=n;const j=d.useRef(r);j.current=r;const Q=d.useRef(i);Q.current=i;const W=d.useRef(c);W.current=c;const oe=d.useRef(o);oe.current=o;const ie=d.useRef(a);ie.current=a;const $=d.useRef(u);$.current=u;const N=d.useRef(l);N.current=l;const[D,ae]=d.useState(st),[H,B]=d.useState(0),[M,R]=d.useState(Cs),[X,O]=d.useState([]),ft=d.useCallback(s=>{ae(s),St(pe.SPOTLIGHT_QUERY,s)},[]);d.useEffect(()=>{t&&(ae(st()),B(0))},[t]),d.useEffect(()=>{if(!t){O([]);return}const s=D.trim();if(s.length<xs){O([]);return}let p=!1;const C=setTimeout(()=>{ys(s).then(F=>{p||O(F)}).catch(()=>{p||O([])})},250);return()=>{p=!0,clearTimeout(C)}},[t,D]);const we=d.useCallback(s=>{R(s),Bt(pe.SPOTLIGHT_TAB,s)},[]),$e=d.useRef(M);$e.current=M;const gt=d.useCallback(s=>{const p=fe.indexOf($e.current),C=fe[(p+s+fe.length)%fe.length];we(C)},[we]);d.useEffect(()=>{B(0)},[M]);const Se=V.getShortcuts(),ge=d.useMemo(()=>t?vt():{},[t]),me=d.useMemo(()=>{if(!t)return[];const s=Se.find(C=>C.id==="spawn-agent"),p=Se.find(C=>C.id==="toggle-commander");return[{id:"cmd-spawn",type:"command",title:"Spawn New Agent",subtitle:s?Ve(s):"Alt+N",icon:f.jsx(ne,{name:"plus",size:16}),action:()=>{w.current(),T.current()}},{id:"cmd-commander",type:"command",title:"Commander View",subtitle:p!=null&&p.key?Ve(p):"Tab",icon:f.jsx(ne,{name:"dashboard",size:16}),action:()=>{w.current(),j.current()}},{id:"cmd-settings",type:"command",title:"Settings & Tools",subtitle:"Configure Tide Commander",icon:f.jsx(ne,{name:"gear",size:16}),action:()=>{w.current(),Q.current()}},{id:"cmd-monitoring",type:"command",title:"Monitoring & Logs",subtitle:"Triggers, workflows, events",icon:f.jsx(ne,{name:"chart-line",size:16}),action:()=>{var C;w.current(),(C=N.current)==null||C.call(N)}}]},[t,Se]),he=d.useMemo(()=>t?Array.from(h.values()).map(s=>{const p=(g||[]).filter(Y=>Y.agentId===s.id).map(Y=>Y.filePath),C=[...new Set(p)],F=C.map(Y=>Y.split("/").pop()||Y),v=[];s.lastAssignedTask&&v.push(s.lastAssignedTask);const L=`${s.class} • ${s.cwd}`;let k=`${s.name} ${s.class} ${s.status} ${s.cwd}`;s.taskLabel&&(k+=` ${s.taskLabel}`),F.length>0&&(k+=` ${F.join(" ")} ${C.join(" ")}`),v.length>0&&(k+=` ${v.join(" ")}`);const P=Date.now()-s.lastActivity;let U;return s.lastAssignedTask&&(s.lastAssignedTask.length>150?U=s.lastAssignedTask.slice(0,150)+"...":U=s.lastAssignedTask),{id:`agent-${s.id}`,type:"agent",title:s.name,subtitle:L,lastUserInput:U,timeAway:P,icon:f.jsx(_t,{agent:s,size:20}),_searchText:k,_modifiedFiles:C,_userQueries:v,_agentId:s.id,_lastActivity:s.lastActivity,_taskLabel:s.taskLabel,_status:s.status,action:()=>{w.current(),It(s.id),V.selectAgent(s.id),V.getState().viewMode!=="flat"&&V.requestTerminalExpand()}}}):[],[t,h,g]),Ae=d.useMemo(()=>t?Array.from(E.values()).map(s=>{var p;return{id:`area-${s.id}`,type:"area",title:s.name,subtitle:`${s.assignedAgentIds.length} agents • ${((p=s.directories)==null?void 0:p.length)||0} folders`,icon:f.jsx(ne,{name:"map",size:16}),action:()=>{w.current(),V.selectArea(s.id)}}}):[],[t,E]),je=d.useMemo(()=>{const s=new Map;for(const p of he)p._agentId&&s.set(p._agentId,p);return s},[he]),Ne=d.useMemo(()=>{const s=new Map;if(!t)return s;for(const p of h.values()){const C=V.getAreaForAgent(p.id);if(!C||C.archived)continue;const F=s.get(C.id);F?F.push(p):s.set(C.id,[p])}return s},[t,h,E]),Pe=d.useMemo(()=>{const s=new Map;for(const p of m)s.has(p.agentId)||s.set(p.agentId,p.timestamp);return s},[m]),Be=d.useMemo(()=>{if(!t)return[];const s=D.trim().toLowerCase(),p=Dt({sortMode:Ms(),agentsWithUnseenOutput:S,getLatestToolTimestamp:v=>Pe.get(v)}),C=Array.from(E.values()).filter(v=>!v.archived).filter(v=>s?v.name.toLowerCase().includes(s):!0).sort((v,L)=>v.name.localeCompare(L.name,void 0,{sensitivity:"base"})),F=[];for(const v of C){const k=(Ne.get(v.id)||[]).slice().sort(p).map(P=>je.get(P.id)).filter(P=>!!P);!s&&k.length===0||F.push({areaId:v.id,areaName:v.name,areaColor:v.color,agents:k})}return F},[t,D,E,Ne,je,S,Pe]),ye=d.useMemo(()=>t?Array.from(x.values()).filter(s=>s.type==="server"||s.type==="boss"||s.type==="database"||s.type==="tests").map(s=>{var P,U,Y,ue,ee;const p=s.status==="running"?"#4ade80":s.status==="stopped"?"#f87171":"#facc15",C=s.type==="boss"?"crown":s.type==="database"?"database":s.type==="tests"?"flask":"desktop",F=s.type==="boss"?"Boss":s.type==="database"?"Database":s.type==="tests"?"Tests":"Server";let v=`${F} • ${s.status}`;if(s.type==="database"&&((U=(P=s.database)==null?void 0:P.connections)!=null&&U.length)){const z=s.database.connections[0];v+=` • ${z.engine} @ ${z.host}`}else s.type==="tests"&&s.folderPath?v=`${F} • ${s.folderPath}`:s.cwd&&(v+=` • ${s.cwd}`);const L=((Y=s.pm2Status)==null?void 0:Y.ports)||[];let k=`${s.name} ${s.type} ${s.status} ${s.cwd||""} ${((ue=s.pm2)==null?void 0:ue.name)||""}`;if(s.type==="tests"&&(k+=` ${s.folderPath||""} tests junit maven`),L.length>0&&(k+=` ${L.join(" ")}`),s.type==="database"&&((ee=s.database)!=null&&ee.connections))for(const z of s.database.connections)k+=` ${z.name} ${z.engine} ${z.host} ${z.database||""} mysql postgresql sql`;return{id:`building-${s.id}`,type:"building",title:s.name,subtitle:v,_ports:L,icon:f.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4},children:[f.jsx(ne,{name:"status-pending",size:10,weight:"fill",color:p}),f.jsx(ne,{name:C,size:16})]}),_searchText:k,action:()=>{var z;w.current(),s.type==="boss"?ie.current(s.id):s.type==="database"?$.current(s.id):s.type==="tests"?V.openTestsBuilding(s.id):s.type==="http"?V.openHttpBuilding(s.id):(z=s.pm2)!=null&&z.enabled&&oe.current(s.id)}}}):[],[t,x]),Ke=d.useMemo(()=>{if(!t)return[];const s=g||[],p=new Set,C=[];for(const F of s){if(p.has(F.filePath))continue;p.add(F.filePath);const v=F.filePath.split("/").pop()||F.filePath,L=F.action==="created"?"Created":F.action==="modified"?"Modified":F.action==="deleted"?"Deleted":"Read";if(C.push({id:`modified-${F.filePath}-${F.timestamp}`,type:"modified-file",title:v,subtitle:`${L} by ${F.agentName} • ${F.filePath}`,matchedText:F.filePath,icon:F.action==="deleted"?f.jsx(ne,{name:"trash",size:16}):kt(F.filePath),action:()=>{w.current();const k=Array.from(V.getState().areas.values());for(const P of k)for(const U of P.directories||[])if(F.filePath.startsWith(U)){V.setFileViewerPath(F.filePath),W.current(P.id);return}V.selectAgent(F.agentId)}}),C.length>=50)break}return C},[t,g]),Oe=d.useMemo(()=>t?X.map(s=>{const p=s.isGitRepo&&s.gitBranch?`${s.path} • ${s.gitBranch}`:s.path;return{id:`folder-${s.path}`,type:"folder",title:s.name,subtitle:p,matchedText:s.path,icon:f.jsx(ne,{name:s.isGitRepo?"git-branch":"folder",size:16}),_searchText:`${s.name} ${s.path}`,_isGitRepo:s.isGitRepo,_gitBranch:s.gitBranch,action:()=>{w.current(),V.openFileExplorer(s.path)}}}):[],[t,X]),ze=d.useMemo(()=>new q(he,{keys:["title","subtitle","_searchText","lastUserInput"],threshold:.4,ignoreLocation:!0,includeScore:!0,includeMatches:!0}),[he]),Ge=d.useMemo(()=>new q(me,{keys:["title","subtitle"],threshold:.4,includeScore:!0,includeMatches:!0}),[me]),Qe=d.useMemo(()=>new q(Ae,{keys:["title","subtitle"],threshold:.4,includeScore:!0,includeMatches:!0}),[Ae]),We=d.useMemo(()=>new q(Ke,{keys:["title","subtitle","matchedText"],threshold:.4,ignoreLocation:!0,includeScore:!0,includeMatches:!0}),[Ke]),He=d.useMemo(()=>new q(ye,{keys:["title","subtitle","_searchText"],threshold:.4,ignoreLocation:!0,includeScore:!0,includeMatches:!0}),[ye]),de=d.useMemo(()=>{if(!D.trim()){const A=[];A.push(...ye);const I=[...he].sort((b,K)=>{const te=Ee(b._agentId,b._lastActivity,ge);return Ee(K._agentId,K._lastActivity,ge)-te});A.push(...I),A.push(...me.slice(0,2)),A.push(...Ae.slice(0,2));const _={};return Es.forEach((b,K)=>{_[b]=K}),A.sort((b,K)=>(_[b.type]??999)-(_[K.type]??999)),A}const s=D.trim().toLowerCase(),p=ze.search(D).slice(0,8),C=Ge.search(D).slice(0,3),F=Qe.search(D).slice(0,2),v=We.search(D).slice(0,3),L=Oe.slice(0,8),k=He.search(D).filter(A=>{const I=A.score??1;return`${A.item.title} ${A.item.subtitle||""} ${A.item._searchText||""}`.toLowerCase().includes(s)||I<=.2}).slice(0,4),P={agent:6,building:5,folder:4,command:3,area:2,"modified-file":1},U=A=>{if(!s)return 1;const I=A.title.toLowerCase();return I===s?6:I.startsWith(s)?5:I.split(/[^a-z0-9]+/i).includes(s)?4:I.includes(s)?3:`${A.subtitle||""} ${A._searchText||""} ${A.matchedText||""}`.toLowerCase().includes(s)?2:1},Y=(A,I)=>{const _=(1-Math.min(1,I??1))*4;return U(A)*100+(P[A.type]??0)*5+_},ue=new Map,ee=(A,I)=>{const _=ue.get(A.type),b={item:A,score:Y(A,I)};_?_.push(b):ue.set(A.type,[b])};for(const A of p){const I={...A.item};if(I._modifiedFiles&&I._modifiedFiles.length>0){const _=I._modifiedFiles.filter(b=>{var se;const K=((se=b.split("/").pop())==null?void 0:se.toLowerCase())||"",te=b.toLowerCase();return K.includes(s)||te.includes(s)});_.length>0&&(I.matchedFiles=_)}if(I._userQueries&&I._userQueries.length>0){const _=I._userQueries.find(b=>b.toLowerCase().includes(s));if(_)if(_.length>200){const K=_.toLowerCase().indexOf(s),te=Math.max(0,K-60),se=Math.min(_.length,K+s.length+100);I.matchedQuery=(te>0?"...":"")+_.slice(te,se)+(se<_.length?"...":"")}else I.matchedQuery=_}ee(I,A.score)}for(const A of k)ee(A.item,A.score);for(const A of C)ee(A.item,A.score);for(const A of F)ee(A.item,A.score);for(const A of v)ee(A.item,A.score);for(const A of L)ee(A,void 0);for(const[A,I]of ue)A==="agent"?I.sort((_,b)=>{const K=U(_.item),te=U(b.item);if(te!==K)return te-K;const se=Ee(_.item._agentId,_.item._lastActivity,ge),Ye=Ee(b.item._agentId,b.item._lastActivity,ge);return Ye!==se?Ye-se:b.score-_.score}):I.sort((_,b)=>b.score-_.score);const z=A=>A.reduce((I,_)=>Math.max(I,_.score),-1),Ue=[];return Array.from(ue.values()).sort((A,I)=>z(I)-z(A)).forEach(A=>{for(const I of A)Ue.push(I.item)}),Ue},[D,ze,Ge,Qe,We,He,me,he,Ae,ye,Oe,ge]),J=d.useMemo(()=>{switch(M){case"agents":return de.filter(s=>s.type==="agent");case"buildings":return de.filter(s=>s.type==="building");case"commands":return de.filter(s=>s.type==="command");case"folders":return de.filter(s=>s.type==="folder");case"areas":return Be.flatMap(s=>s.agents);case"all":default:return de}},[M,de,Be]);d.useEffect(()=>{H>=J.length&&B(Math.max(0,J.length-1))},[J.length,H]);const pt=d.useCallback(s=>{if(s.altKey&&!s.ctrlKey&&!s.metaKey&&(s.key==="p"||s.key==="n"||s.key==="P"||s.key==="N")){s.preventDefault(),s.stopPropagation(),s.nativeEvent.stopImmediatePropagation();const p=s.key.toLowerCase();B(p==="p"?C=>C>0?C-1:J.length-1:C=>C<J.length-1?C+1:0);return}switch(s.key){case"Escape":s.preventDefault(),w.current();break;case"ArrowUp":s.preventDefault(),B(p=>p>0?p-1:J.length-1);break;case"ArrowDown":s.preventDefault(),B(p=>p<J.length-1?p+1:0);break;case"Enter":s.preventDefault(),J[H]&&J[H].action();break}},[J,H]),mt=d.useCallback((s,p)=>{if(!p||!s)return s;const C=s.toLowerCase(),F=p.toLowerCase(),v=[];let L=0,k=C.indexOf(F),P=0;for(;k!==-1;)k>L&&v.push(s.slice(L,k)),v.push(ve.createElement("mark",{key:P++,className:"spotlight-highlight"},s.slice(k,k+p.length))),L=k+p.length,k=C.indexOf(F,L);return L<s.length&&v.push(s.slice(L)),v.length>0?ve.createElement(ve.Fragment,null,...v):s},[]);return{query:D,setQuery:ft,selectedIndex:H,setSelectedIndex:B,results:J,activeTab:M,setActiveTab:we,cycleTab:gt,areaSections:Be,handleKeyDown:pt,highlightMatch:mt}}const ws=d.forwardRef(function({query:e,onQueryChange:n,onKeyDown:r,onResetSelection:i},c){const{t:o}=Fe(["common"]);return f.jsxs("div",{className:"spotlight-input-wrapper",children:[f.jsx("span",{className:"spotlight-search-icon",children:"⌘"}),f.jsx("input",{ref:c,type:"text",className:"spotlight-input",placeholder:o("common:search.spotlightPlaceholder"),value:e,onChange:a=>{n(a.target.value),i()},onKeyDown:r,autoFocus:!0,spellCheck:!1}),f.jsxs("div",{className:"spotlight-input-hints",children:[f.jsx("span",{className:"spotlight-shortcut-hint",children:"↑↓"}),f.jsx("span",{className:"spotlight-shortcut-hint",children:"Enter"}),f.jsx("span",{className:"spotlight-shortcut-hint",children:"Esc"})]})]})}),Ss=d.memo(function({activeTab:e,onSelect:n}){const{t:r}=Fe(["terminal"]);return f.jsxs("div",{className:"spotlight-tabs",role:"tablist","aria-label":r("terminal:spotlight.tabsLabel"),children:[fe.map(i=>f.jsx("button",{type:"button",role:"tab","aria-selected":i===e,tabIndex:-1,className:`spotlight-tab${i===e?" active":""}`,onClick:()=>n(i),children:r(`terminal:spotlight.tabs.${i}`)},i)),f.jsx("span",{className:"spotlight-tabs-hint",children:f.jsx("kbd",{children:"Tab"})})]})}),Bs=d.forwardRef(function({results:e,selectedIndex:n,query:r,activeTab:i,areaSections:c,highlightMatch:o,onSelectIndex:a},u){const{t:l}=Fe(["terminal"]),h=d.useRef(!1);d.useEffect(()=>{h.current=!1},[e]),d.useEffect(()=>{const g=typeof u=="function"?null:u==null?void 0:u.current;if(!g)return;const m=()=>{h.current=!0};return g.addEventListener("mousemove",m),()=>{g.removeEventListener("mousemove",m)}},[u,e]);const E={command:l("terminal:spotlight.categories.commands"),agent:l("terminal:spotlight.categories.agents"),building:l("terminal:spotlight.categories.infrastructure"),area:l("terminal:spotlight.categories.areas"),folder:l("terminal:spotlight.categories.folders"),"modified-file":l("terminal:spotlight.categories.modifiedFiles")},x=d.useMemo(()=>{const g=[];let m=null,S=[];return e.forEach((w,T)=>{w.type!==m&&(m!==null&&S.length>0&&g.push([m,S]),m=w.type,S=[]),S.push({result:w,index:T})}),m!==null&&S.length>0&&g.push([m,S]),g},[e]);if(d.useEffect(()=>{if(!u||typeof u=="function")return;const g=u.current;if(!g)return;const m=g.querySelector(".spotlight-item.selected");m&&m.scrollIntoView({block:"nearest",behavior:"smooth"})},[n,u]),i==="areas"){if(c.length===0)return f.jsx("div",{className:"spotlight-results",ref:u,children:f.jsx("div",{className:"spotlight-empty",children:l("terminal:spotlight.noResults")})});let g=0;return f.jsx("div",{className:"spotlight-results",ref:u,children:c.map(m=>f.jsxs("div",{children:[f.jsxs("div",{className:"spotlight-category-header spotlight-area-section-header",children:[f.jsx("span",{className:"spotlight-area-dot",style:{background:m.areaColor},"aria-hidden":"true"}),f.jsx("span",{className:"spotlight-area-name",children:m.areaName}),f.jsx("span",{className:"spotlight-area-count",children:m.agents.length})]}),m.agents.length===0?f.jsx("div",{className:"spotlight-area-empty",children:l("terminal:spotlight.noAgentsInArea")}):m.agents.map(S=>{const w=g++;return f.jsx(Je,{result:S,isSelected:w===n,query:r,highlightMatch:o,onClick:()=>S.action(),onMouseEnter:()=>{h.current&&a(w)}},S.id)})]},m.areaId))})}return e.length===0?f.jsx("div",{className:"spotlight-results",ref:u,children:f.jsx("div",{className:"spotlight-empty",children:l("terminal:spotlight.noResults")})}):f.jsx("div",{className:"spotlight-results",ref:u,children:x.map(([g,m])=>f.jsxs("div",{children:[x.length>1&&f.jsx("div",{className:"spotlight-category-header",children:E[g]||g}),m.map(({result:S,index:w})=>f.jsx(Je,{result:S,isSelected:w===n,query:r,highlightMatch:o,onClick:()=>S.action(),onMouseEnter:()=>{h.current&&a(w)}},S.id))]},g))})}),vs=d.memo(function(){const{t:e}=Fe(["terminal"]);return f.jsxs("div",{className:"spotlight-footer",children:[f.jsxs("div",{className:"spotlight-footer-left",children:[f.jsxs("span",{className:"spotlight-footer-hint",children:[f.jsx("kbd",{children:"↑"}),f.jsx("kbd",{children:"↓"})," ",f.jsx("kbd",{children:"Alt+N"}),f.jsx("kbd",{children:"Alt+P"})," ",e("terminal:spotlight.navigate")]}),f.jsxs("span",{className:"spotlight-footer-hint",children:[f.jsx("kbd",{children:"Enter"})," ",e("terminal:spotlight.select")]}),f.jsxs("span",{className:"spotlight-footer-hint",children:[f.jsx("kbd",{children:"Tab"})," ",e("terminal:spotlight.switchTabs")]})]}),f.jsx("div",{className:"spotlight-footer-right",children:f.jsxs("span",{className:"spotlight-footer-hint",children:[f.jsx("kbd",{children:"Esc"})," ",e("common:buttons.close")]})})]})}),Is=768;function Rs({isOpen:t,onClose:e,onOpenSpawnModal:n,onOpenCommanderView:r,onOpenToolbox:i,onOpenFileExplorer:c,onOpenPM2LogsModal:o,onOpenBossLogsModal:a,onOpenDatabasePanel:u,onOpenMonitoringModal:l}){const h=d.useRef(null),E=d.useRef(null),x=d.useRef(null),g=d.useRef(0),{query:m,setQuery:S,selectedIndex:w,setSelectedIndex:T,results:j,activeTab:Q,setActiveTab:W,cycleTab:oe,areaSections:ie,handleKeyDown:$,highlightMatch:N}=Fs({isOpen:t,onClose:e,onOpenSpawnModal:n,onOpenCommanderView:r,onOpenToolbox:i,onOpenFileExplorer:c,onOpenPM2LogsModal:o,onOpenBossLogsModal:a,onOpenDatabasePanel:u,onOpenMonitoringModal:l});g.current=j.length;const D=d.useRef(oe);D.current=oe,d.useEffect(()=>{t&&setTimeout(()=>{var B,M;(B=h.current)==null||B.focus(),(M=h.current)==null||M.select()},50)},[t]),d.useEffect(()=>{if(!t)return;const B=window.visualViewport;if(!B||window.innerWidth>Is)return;const M=()=>{const R=E.current;R&&(R.style.height=`${B.height}px`,R.style.top=`${B.offsetTop}px`)};return M(),B.addEventListener("resize",M),B.addEventListener("scroll",M),()=>{B.removeEventListener("resize",M),B.removeEventListener("scroll",M);const R=E.current;R&&(R.style.height="",R.style.top="")}},[t]),d.useEffect(()=>{if(!t)return;const B=M=>{if(M.key==="Escape"){M.preventDefault(),M.stopPropagation(),M.stopImmediatePropagation(),e();return}if(M.key==="Tab"){M.preventDefault(),M.stopPropagation(),M.stopImmediatePropagation(),D.current(M.shiftKey?-1:1);return}if(M.altKey&&!M.ctrlKey&&!M.metaKey&&(M.key==="n"||M.key==="p"||M.key==="N"||M.key==="P")){M.preventDefault(),M.stopPropagation(),M.stopImmediatePropagation();const R=M.key.toLowerCase(),X=g.current;T(R==="p"?O=>O>0?O-1:X-1:O=>O<X-1?O+1:0);return}};return window.addEventListener("keydown",B,{capture:!0}),()=>{window.removeEventListener("keydown",B,{capture:!0})}},[t,e]);const ae=d.useCallback(B=>{B.target===B.currentTarget&&e()},[e]),H=d.useCallback(()=>{T(0)},[T]);return t?f.jsx("div",{ref:E,className:"spotlight-overlay",onClick:ae,children:f.jsxs("div",{className:"spotlight-modal",children:[f.jsx(ws,{ref:h,query:m,onQueryChange:S,onKeyDown:$,onResetSelection:H}),f.jsx(Ss,{activeTab:Q,onSelect:W}),f.jsx(Bs,{ref:x,results:j,selectedIndex:w,query:m,activeTab:Q,areaSections:ie,highlightMatch:N,onSelectIndex:T}),f.jsx(vs,{})]})}):null}export{Ls as FILE_ICON_NAMES,Rs as Spotlight,vs as SpotlightFooter,ws as SpotlightInput,Je as SpotlightItem,Bs as SpotlightResults,$s as formatDuration,js as formatRelativeTime,Ns as getAgentIcon,kt as getFileIconFromPath,Ps as getTypeLabel,Fs as useSpotlightSearch};
|