tide-commander 1.161.0 → 1.162.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 +14 -0
- package/dist/assets/{BossLogsModal-ByN3qs9-.js → BossLogsModal-DrYF13xp.js} +1 -1
- package/dist/assets/{BossSpawnModal-CNlqXvK9.js → BossSpawnModal-2ZgbW8Iy.js} +1 -1
- package/dist/assets/{ControlsModal-BxKH1QLw.js → ControlsModal-CRdNNTEo.js} +1 -1
- package/dist/assets/{DockerLogsModal-BPGru2EX.js → DockerLogsModal-BGPZP9_V.js} +1 -1
- package/dist/assets/{EmbeddedEditor-kSj9yTQI.js → EmbeddedEditor-B99bT-bl.js} +1 -1
- package/dist/assets/{GmailOAuthSetup-aaL2rsLN.js → GmailOAuthSetup-DmMCxdUW.js} +1 -1
- package/dist/assets/{GoogleOAuthSetup-Bc61FQ2H.js → GoogleOAuthSetup-BZqit-mW.js} +1 -1
- package/dist/assets/{IframeModal-DvM559FE.js → IframeModal-vMY7XxHP.js} +1 -1
- package/dist/assets/{IntegrationsPanel-4_733lDP.js → IntegrationsPanel-DVmqPRTs.js} +2 -2
- package/dist/assets/{LogViewerModal-BjC13hIK.js → LogViewerModal-rYC6IVPV.js} +1 -1
- package/dist/assets/{MonitoringModal-Xjkid3A5.js → MonitoringModal-C-QXpZkE.js} +1 -1
- package/dist/assets/{PM2LogsModal-DpbDESnu.js → PM2LogsModal-C3A_ohFv.js} +1 -1
- package/dist/assets/{RestoreArchivedAreaModal-B-9zHb3p.js → RestoreArchivedAreaModal-Dx94NzSz.js} +1 -1
- package/dist/assets/{Scene2DCanvas-DQdSAptp.js → Scene2DCanvas-BxOqJ0IB.js} +1 -1
- package/dist/assets/{SceneManager-Bn-9k6mM.js → SceneManager-CxcXfq_u.js} +1 -1
- package/dist/assets/{SkillsPanel-Bk3rbNQB.js → SkillsPanel-Fu5sfG7Q.js} +1 -1
- package/dist/assets/{SlackMultiInstanceSetup-CfhQ10Um.js → SlackMultiInstanceSetup-jnGMesoq.js} +1 -1
- package/dist/assets/{SpawnModal-DfT7bzNo.js → SpawnModal-CGYg4uTC.js} +1 -1
- package/dist/assets/{StatisticsModal-DFDFE58F.js → StatisticsModal-BOV6Juts.js} +1 -1
- package/dist/assets/{SubordinateAssignmentModal-hqH3o5Lp.js → SubordinateAssignmentModal-Bhgj9FvT.js} +1 -1
- package/dist/assets/{TriggerManagerPanel-svSECUjd.js → TriggerManagerPanel-Qkw4ajmL.js} +1 -1
- package/dist/assets/{WorkflowEditorPanel-CIqg8BLi.js → WorkflowEditorPanel-DTIBRGz4.js} +1 -1
- package/dist/assets/{area-logos-B0efSjrz.js → area-logos-uM2FM0I2.js} +1 -1
- package/dist/assets/{index-BeQoCc1W.js → index-3y5Ajiyr.js} +1 -1
- package/dist/assets/{index-hzbuivYC.js → index-5tz2e3op.js} +1 -1
- package/dist/assets/{index-CI4TPz4h.js → index-B03BKiDN.js} +1 -1
- package/dist/assets/{index-CPVGsE7g.js → index-BFJWNGpT.js} +3 -3
- package/dist/assets/{index-CmiQbHNF.js → index-BvD1v4JH.js} +1 -1
- package/dist/assets/{index-Db0U-21f.js → index-BvOgm4yp.js} +1 -1
- package/dist/assets/{index-B8R_gEnb.js → index-CpQeaxZ7.js} +2 -2
- package/dist/assets/index-CrBXvs1w.css +1 -0
- package/dist/assets/{index-F4gvAXEg.js → index-DzQxMm67.js} +1 -1
- package/dist/assets/index-cA0kPNUq.js +2 -0
- package/dist/assets/{main-BX-OUL7k.css → main-B-jhtDyZ.css} +1 -1
- package/dist/assets/main-rX2ghMIV.js +297 -0
- package/dist/assets/{web-D9FjjUJx.js → web-ClQyiX7L.js} +1 -1
- package/dist/assets/{web-AyXD75n2.js → web-NCIGsXXA.js} +1 -1
- package/dist/assets/{web-zhILDfYB.js → web-ml-7D2g7.js} +1 -1
- package/dist/build-info.json +1 -1
- package/dist/index.html +2 -2
- package/dist/locales/en/terminal.json +2 -0
- package/dist/src/packages/server/claude/backend.js +4 -0
- package/dist/src/packages/server/claude/session-loader.js +18 -0
- package/dist/src/packages/server/codex/generated-image.js +35 -0
- package/dist/src/packages/server/codex/json-event-parser.js +23 -0
- package/dist/src/packages/server/routes/agents.js +9 -6
- package/dist/src/packages/server/services/codex-usage-service.js +93 -0
- package/package.json +1 -1
- package/dist/assets/index-BIxFr4P2.css +0 -1
- package/dist/assets/index-CMI4WoS7.js +0 -2
- package/dist/assets/main-Bwg5cpUh.js +0 -297
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dh as a}from"./main-
|
|
1
|
+
import{dh as a}from"./main-rX2ghMIV.js";import{ImpactStyle as i,NotificationType as r}from"./index-CpQeaxZ7.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";class h extends a{constructor(){super(...arguments),this.selectionStarted=!1}async impact(t){const e=this.patternForImpact(t==null?void 0:t.style);this.vibrateWithPattern(e)}async notification(t){const e=this.patternForNotification(t==null?void 0:t.type);this.vibrateWithPattern(e)}async vibrate(t){const e=(t==null?void 0:t.duration)||300;this.vibrateWithPattern([e])}async selectionStart(){this.selectionStarted=!0}async selectionChanged(){this.selectionStarted&&this.vibrateWithPattern([70])}async selectionEnd(){this.selectionStarted=!1}patternForImpact(t=i.Heavy){return t===i.Medium?[43]:t===i.Light?[20]:[61]}patternForNotification(t=r.Success){return t===r.Warning?[30,40,30,50,60]:t===r.Error?[27,45,50]:[35,65,21]}vibrateWithPattern(t){if(navigator.vibrate)navigator.vibrate(t);else throw this.unavailable("Browser does not support the vibrate API")}}export{h as HapticsWeb};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dh as t}from"./main-
|
|
1
|
+
import{dh as t}from"./main-rX2ghMIV.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";class o extends t{constructor(){super(),this.handleVisibilityChange=()=>{const e={isActive:document.hidden!==!0};this.notifyListeners("appStateChange",e),document.hidden?this.notifyListeners("pause",null):this.notifyListeners("resume",null)},document.addEventListener("visibilitychange",this.handleVisibilityChange,!1)}exitApp(){throw this.unimplemented("Not implemented on web.")}async getInfo(){throw this.unimplemented("Not implemented on web.")}async getLaunchUrl(){return{url:""}}async getState(){return{isActive:document.hidden!==!0}}async minimizeApp(){throw this.unimplemented("Not implemented on web.")}async toggleBackButtonHandler(){throw this.unimplemented("Not implemented on web.")}async getAppLanguage(){return{value:navigator.language.split("-")[0].toLowerCase()}}}export{o as AppWeb};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dh as s}from"./main-
|
|
1
|
+
import{dh as s}from"./main-rX2ghMIV.js";import"./vendor-react--Eh9ivFN.js";import"./vendor-three-Chj50gSY.js";class l extends s{constructor(){super(...arguments),this.pending=[],this.deliveredNotifications=[],this.hasNotificationSupport=()=>{if(!("Notification"in window)||!Notification.requestPermission)return!1;if(Notification.permission!=="granted")try{new Notification("")}catch(i){if(i instanceof Error&&i.name==="TypeError")return!1}return!0}}async getDeliveredNotifications(){const i=[];for(const t of this.deliveredNotifications){const e={title:t.title,id:parseInt(t.tag),body:t.body};i.push(e)}return{notifications:i}}async removeDeliveredNotifications(i){for(const t of i.notifications){const e=this.deliveredNotifications.find(n=>n.tag===String(t.id));e==null||e.close(),this.deliveredNotifications=this.deliveredNotifications.filter(()=>!e)}}async removeAllDeliveredNotifications(){for(const i of this.deliveredNotifications)i.close();this.deliveredNotifications=[]}async createChannel(){throw this.unimplemented("Not implemented on web.")}async deleteChannel(){throw this.unimplemented("Not implemented on web.")}async listChannels(){throw this.unimplemented("Not implemented on web.")}async schedule(i){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");for(const t of i.notifications)this.sendNotification(t);return{notifications:i.notifications.map(t=>({id:t.id}))}}async getPending(){return{notifications:this.pending}}async registerActionTypes(){throw this.unimplemented("Not implemented on web.")}async cancel(i){this.pending=this.pending.filter(t=>!i.notifications.find(e=>e.id===t.id))}async areEnabled(){const{display:i}=await this.checkPermissions();return{value:i==="granted"}}async changeExactNotificationSetting(){throw this.unimplemented("Not implemented on web.")}async checkExactNotificationSetting(){throw this.unimplemented("Not implemented on web.")}async requestPermissions(){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");return{display:this.transformNotificationPermission(await Notification.requestPermission())}}async checkPermissions(){if(!this.hasNotificationSupport())throw this.unavailable("Notifications not supported in this browser.");return{display:this.transformNotificationPermission(Notification.permission)}}transformNotificationPermission(i){switch(i){case"granted":return"granted";case"denied":return"denied";default:return"prompt"}}sendPending(){var i;const t=[],e=new Date().getTime();for(const n of this.pending)!((i=n.schedule)===null||i===void 0)&&i.at&&n.schedule.at.getTime()<=e&&(this.buildNotification(n),t.push(n));this.pending=this.pending.filter(n=>!t.find(o=>o===n))}sendNotification(i){var t;if(!((t=i.schedule)===null||t===void 0)&&t.at){const e=i.schedule.at.getTime()-new Date().getTime();this.pending.push(i),setTimeout(()=>{this.sendPending()},e);return}this.buildNotification(i)}buildNotification(i){const t=new Notification(i.title,{body:i.body,tag:String(i.id)});return t.addEventListener("click",this.onClick.bind(this,i),!1),t.addEventListener("show",this.onShow.bind(this,i),!1),t.addEventListener("close",()=>{this.deliveredNotifications=this.deliveredNotifications.filter(()=>!this)},!1),this.deliveredNotifications.push(t),t}onClick(i){const t={actionId:"tap",notification:i};this.notifyListeners("localNotificationActionPerformed",t)}onShow(i){this.notifyListeners("localNotificationReceived",i)}}export{l as LocalNotificationsWeb};
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"1.
|
|
1
|
+
{"version":"1.162.0"}
|
package/dist/index.html
CHANGED
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
<link rel="icon" type="image/png" sizes="16x16" href="/assets/icons/favicon-16x16.png" />
|
|
23
23
|
<link rel="apple-touch-icon" sizes="180x180" href="/assets/icons/apple-touch-icon.png" />
|
|
24
24
|
<title>Tide Commander</title>
|
|
25
|
-
<script type="module" crossorigin src="/assets/main-
|
|
25
|
+
<script type="module" crossorigin src="/assets/main-rX2ghMIV.js"></script>
|
|
26
26
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react--Eh9ivFN.js">
|
|
27
27
|
<link rel="modulepreload" crossorigin href="/assets/vendor-three-Chj50gSY.js">
|
|
28
|
-
<link rel="stylesheet" crossorigin href="/assets/main-
|
|
28
|
+
<link rel="stylesheet" crossorigin href="/assets/main-B-jhtDyZ.css">
|
|
29
29
|
</head>
|
|
30
30
|
<body>
|
|
31
31
|
<div id="app"></div>
|
|
@@ -1270,6 +1270,7 @@
|
|
|
1270
1270
|
"usage": {
|
|
1271
1271
|
"title": "Claude Usage",
|
|
1272
1272
|
"titleGrok": "Grok Usage",
|
|
1273
|
+
"titleCodex": "Codex Usage",
|
|
1273
1274
|
"session": "Session",
|
|
1274
1275
|
"tokensUsed": "Tokens used",
|
|
1275
1276
|
"taskCount": "Tasks sent",
|
|
@@ -1288,6 +1289,7 @@
|
|
|
1288
1289
|
"currentWeekFable": "Current week (Fable)",
|
|
1289
1290
|
"currentWeekSonnet": "Current week (Sonnet only)",
|
|
1290
1291
|
"weeklyLimit": "Weekly limit",
|
|
1292
|
+
"dailyLimit": "Daily limit",
|
|
1291
1293
|
"monthlyLimit": "Monthly limit",
|
|
1292
1294
|
"periodLimit": "Plan period limit",
|
|
1293
1295
|
"onDemandLimit": "Pay-as-you-go limit",
|
|
@@ -348,6 +348,10 @@ export class ClaudeBackend {
|
|
|
348
348
|
toolName,
|
|
349
349
|
toolOutput: content,
|
|
350
350
|
toolUseId: block.tool_use_id, // Preserve for subagent correlation
|
|
351
|
+
// The matching tool_start uses the tool_use id as its live-output
|
|
352
|
+
// uuid. Reuse it for the result so clients can enrich that card in
|
|
353
|
+
// place instead of waiting for a session-history reconstruction.
|
|
354
|
+
uuid: block.tool_use_id,
|
|
351
355
|
};
|
|
352
356
|
// Extract subagent stats from Task/Agent tool completion metadata
|
|
353
357
|
if ((toolName === 'Task' || toolName === 'Agent') && event.tool_use_result) {
|
|
@@ -11,6 +11,7 @@ import * as os from 'os';
|
|
|
11
11
|
import * as readline from 'readline';
|
|
12
12
|
import Database from 'better-sqlite3';
|
|
13
13
|
import { createLogger } from '../utils/logger.js';
|
|
14
|
+
import { materializeCodexGeneratedImage } from '../codex/generated-image.js';
|
|
14
15
|
const log = createLogger('Session');
|
|
15
16
|
// Claude's project directory
|
|
16
17
|
const CLAUDE_DIR = path.join(os.homedir(), '.claude');
|
|
@@ -1141,6 +1142,23 @@ function parseCodexEntryMessages(entry, messages, toolUseIdToName, patchDiffsByC
|
|
|
1141
1142
|
}
|
|
1142
1143
|
return;
|
|
1143
1144
|
}
|
|
1145
|
+
if (payload.type === 'image_generation_begin') {
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
if (payload.type === 'image_generation_end') {
|
|
1149
|
+
const imagePath = materializeCodexGeneratedImage(payload.result);
|
|
1150
|
+
messages.push({
|
|
1151
|
+
type: 'assistant',
|
|
1152
|
+
content: imagePath
|
|
1153
|
+
? `[Image: ${imagePath}]`
|
|
1154
|
+
: '[codex-event] Image generation completed, but the PNG result was invalid.',
|
|
1155
|
+
timestamp: entry.timestamp,
|
|
1156
|
+
uuid: typeof payload.call_id === 'string'
|
|
1157
|
+
? payload.call_id
|
|
1158
|
+
: `${entry.timestamp}-assistant-generated-image`,
|
|
1159
|
+
});
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1144
1162
|
// agent_reasoning: Skip in history (consistent with Claude thinking behavior)
|
|
1145
1163
|
if (payload.type === 'agent_reasoning') {
|
|
1146
1164
|
return;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
const GENERATED_IMAGES_DIR = path.join(os.tmpdir(), 'tide-commander-uploads');
|
|
6
|
+
const MAX_GENERATED_IMAGE_BYTES = 50 * 1024 * 1024;
|
|
7
|
+
const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
8
|
+
/**
|
|
9
|
+
* Materialize Codex's image_generation_end base64 result in the directory
|
|
10
|
+
* already exposed by Tide Commander at /uploads.
|
|
11
|
+
*/
|
|
12
|
+
export function materializeCodexGeneratedImage(result) {
|
|
13
|
+
if (typeof result !== 'string')
|
|
14
|
+
return null;
|
|
15
|
+
const encoded = result.startsWith('data:image/png;base64,')
|
|
16
|
+
? result.slice('data:image/png;base64,'.length)
|
|
17
|
+
: result;
|
|
18
|
+
if (!encoded || encoded.length > Math.ceil(MAX_GENERATED_IMAGE_BYTES * 4 / 3) + 4)
|
|
19
|
+
return null;
|
|
20
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(encoded))
|
|
21
|
+
return null;
|
|
22
|
+
const image = Buffer.from(encoded, 'base64');
|
|
23
|
+
if (image.length === 0 ||
|
|
24
|
+
image.length > MAX_GENERATED_IMAGE_BYTES ||
|
|
25
|
+
image.length < PNG_SIGNATURE.length ||
|
|
26
|
+
!image.subarray(0, PNG_SIGNATURE.length).equals(PNG_SIGNATURE)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const digest = createHash('sha256').update(image).digest('hex').slice(0, 16);
|
|
30
|
+
const imagePath = path.join(GENERATED_IMAGES_DIR, `codex-generated-${digest}.png`);
|
|
31
|
+
fs.mkdirSync(GENERATED_IMAGES_DIR, { recursive: true });
|
|
32
|
+
if (!fs.existsSync(imagePath))
|
|
33
|
+
fs.writeFileSync(imagePath, image, { mode: 0o600 });
|
|
34
|
+
return imagePath;
|
|
35
|
+
}
|
|
@@ -2,6 +2,7 @@ import { execFileSync } from 'child_process';
|
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { createLogger } from '../utils/logger.js';
|
|
5
|
+
import { materializeCodexGeneratedImage } from './generated-image.js';
|
|
5
6
|
const log = createLogger('CodexParser');
|
|
6
7
|
let hasLoggedTurnAbortedLiveWarning = false;
|
|
7
8
|
const MAX_DIFF_FILE_BYTES = 256 * 1024;
|
|
@@ -260,6 +261,28 @@ export class CodexJsonEventParser {
|
|
|
260
261
|
if (payloadType === 'web_search_begin' || payloadType === 'web_search_end') {
|
|
261
262
|
return this.parseWebSearchEvent(payload, payloadType === 'web_search_end');
|
|
262
263
|
}
|
|
264
|
+
// Codex returns generated PNGs inline as base64. Persist the bytes in the
|
|
265
|
+
// existing uploads directory and let Guake's normal image-reference
|
|
266
|
+
// renderer show a clickable thumbnail instead of dumping the JSON/base64.
|
|
267
|
+
if (payloadType === 'image_generation_begin') {
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
if (payloadType === 'image_generation_end') {
|
|
271
|
+
const imagePath = materializeCodexGeneratedImage(payload.result);
|
|
272
|
+
if (!imagePath) {
|
|
273
|
+
return [{
|
|
274
|
+
type: 'text',
|
|
275
|
+
text: '[codex-event] Image generation completed, but the PNG result was invalid.',
|
|
276
|
+
isStreaming: false,
|
|
277
|
+
}];
|
|
278
|
+
}
|
|
279
|
+
return [{
|
|
280
|
+
type: 'text',
|
|
281
|
+
text: `[Image: ${imagePath}]`,
|
|
282
|
+
isStreaming: false,
|
|
283
|
+
uuid: asString(payload.call_id) || undefined,
|
|
284
|
+
}];
|
|
285
|
+
}
|
|
263
286
|
// agent_reasoning: Map to thinking event (stable uuid when item id present)
|
|
264
287
|
if (payloadType === 'agent_reasoning') {
|
|
265
288
|
const text = asString(payload.text);
|
|
@@ -23,6 +23,7 @@ import { markInstructionsDirtyForAll } from '../services/instruction-refresh.js'
|
|
|
23
23
|
import { startAgentTerminal, stopAgentTerminal } from '../services/agent-terminal-service.js';
|
|
24
24
|
import { buildClaudeUsageByAgentSummary, buildClaudeUsageByDaySummary, buildClaudeUsageSnapshot } from '../services/claude-usage-service.js';
|
|
25
25
|
import { buildGrokUsageSnapshot } from '../services/grok-usage-service.js';
|
|
26
|
+
import { buildCodexUsageSnapshot } from '../services/codex-usage-service.js';
|
|
26
27
|
import { getBackupStatus, setBackupEnabled } from '../services/backup-service.js';
|
|
27
28
|
const log = createLogger('Routes');
|
|
28
29
|
const router = Router();
|
|
@@ -949,7 +950,7 @@ router.delete('/:id', (req, res) => {
|
|
|
949
950
|
}
|
|
950
951
|
res.status(204).end();
|
|
951
952
|
});
|
|
952
|
-
// GET /api/agents/:id/usage -
|
|
953
|
+
// GET /api/agents/:id/usage - provider usage snapshot for a single agent
|
|
953
954
|
//
|
|
954
955
|
// Claude: local agent stats + Anthropic OAuth rate-limit gauges (CLI `/usage`).
|
|
955
956
|
// Grok: local agent stats + CLI chat-proxy billing/credit gauges (CLI `/usage`).
|
|
@@ -960,17 +961,19 @@ router.get('/:id/usage', async (req, res) => {
|
|
|
960
961
|
return;
|
|
961
962
|
}
|
|
962
963
|
const provider = agent.provider ?? 'claude';
|
|
963
|
-
if (provider !== 'claude' && provider !== 'grok') {
|
|
964
|
+
if (provider !== 'claude' && provider !== 'grok' && provider !== 'codex') {
|
|
964
965
|
res.status(400).json({
|
|
965
|
-
error: 'Usage data is only available for Claude and Grok agents',
|
|
966
|
+
error: 'Usage data is only available for Claude, Codex, and Grok agents',
|
|
966
967
|
provider,
|
|
967
968
|
});
|
|
968
969
|
return;
|
|
969
970
|
}
|
|
970
971
|
try {
|
|
971
|
-
const snapshot = provider === '
|
|
972
|
-
? await
|
|
973
|
-
:
|
|
972
|
+
const snapshot = provider === 'codex'
|
|
973
|
+
? await buildCodexUsageSnapshot(agent)
|
|
974
|
+
: provider === 'grok'
|
|
975
|
+
? await buildGrokUsageSnapshot(agent)
|
|
976
|
+
: await buildClaudeUsageSnapshot(agent);
|
|
974
977
|
res.json(snapshot);
|
|
975
978
|
}
|
|
976
979
|
catch (err) {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { getCodexBinaryPath } from './system-prompt-service.js';
|
|
3
|
+
export function classifyCodexRateLimits(raw) {
|
|
4
|
+
const result = { daily: null, weekly: null };
|
|
5
|
+
for (const value of [raw?.primary, raw?.secondary]) {
|
|
6
|
+
if (!value || typeof value.usedPercent !== 'number')
|
|
7
|
+
continue;
|
|
8
|
+
const mins = typeof value.windowDurationMins === 'number' ? value.windowDurationMins : null;
|
|
9
|
+
const resetsAtSeconds = typeof value.resetsAt === 'number' ? value.resetsAt : 0;
|
|
10
|
+
const window = {
|
|
11
|
+
utilization: Math.max(0, Math.min(100, value.usedPercent)),
|
|
12
|
+
resetsAt: resetsAtSeconds > 0 ? new Date(resetsAtSeconds * 1000).toISOString() : '',
|
|
13
|
+
windowDurationMins: mins,
|
|
14
|
+
};
|
|
15
|
+
// App-server identifies windows by duration rather than by name. Anything
|
|
16
|
+
// up to two days is the daily allowance; longer periods are weekly.
|
|
17
|
+
if (mins !== null && mins <= 2 * 24 * 60)
|
|
18
|
+
result.daily = window;
|
|
19
|
+
else
|
|
20
|
+
result.weekly = window;
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
function readNativeRateLimits() {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
const child = spawn(getCodexBinaryPath(), ['app-server'], { stdio: ['pipe', 'pipe', 'pipe'], env: process.env });
|
|
27
|
+
let stdout = '';
|
|
28
|
+
let stderr = '';
|
|
29
|
+
let settled = false;
|
|
30
|
+
const finish = (err, value) => {
|
|
31
|
+
if (settled)
|
|
32
|
+
return;
|
|
33
|
+
settled = true;
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
child.kill('SIGTERM');
|
|
36
|
+
if (err)
|
|
37
|
+
reject(err);
|
|
38
|
+
else
|
|
39
|
+
resolve(value ?? {});
|
|
40
|
+
};
|
|
41
|
+
const timer = setTimeout(() => finish(new Error('Codex usage request timed out')), 10_000);
|
|
42
|
+
child.on('error', (err) => finish(err));
|
|
43
|
+
child.stderr?.on('data', (chunk) => { stderr += chunk.toString(); });
|
|
44
|
+
child.stdout?.on('data', (chunk) => {
|
|
45
|
+
stdout += chunk.toString();
|
|
46
|
+
const lines = stdout.split('\n');
|
|
47
|
+
stdout = lines.pop() ?? '';
|
|
48
|
+
for (const line of lines) {
|
|
49
|
+
if (!line.trim())
|
|
50
|
+
continue;
|
|
51
|
+
try {
|
|
52
|
+
const message = JSON.parse(line);
|
|
53
|
+
if (message.id === 1 && message.result) {
|
|
54
|
+
child.stdin?.write(`${JSON.stringify({ method: 'initialized', params: {} })}\n`);
|
|
55
|
+
child.stdin?.write(`${JSON.stringify({ id: 2, method: 'account/rateLimits/read', params: {} })}\n`);
|
|
56
|
+
}
|
|
57
|
+
else if (message.id === 2) {
|
|
58
|
+
if (message.error)
|
|
59
|
+
finish(new Error(message.error.message || 'Codex rejected the usage request'));
|
|
60
|
+
else
|
|
61
|
+
finish(undefined, message.result?.rateLimits ?? {});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch { /* wait for the next complete JSON line */ }
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
child.on('close', (code) => {
|
|
68
|
+
if (!settled)
|
|
69
|
+
finish(new Error(stderr.trim() || `Codex app-server exited with code ${code}`));
|
|
70
|
+
});
|
|
71
|
+
child.stdin?.write(`${JSON.stringify({
|
|
72
|
+
id: 1,
|
|
73
|
+
method: 'initialize',
|
|
74
|
+
params: { clientInfo: { name: 'tide-commander', title: 'Tide Commander', version: '1.0.0' }, capabilities: { experimentalApi: true } },
|
|
75
|
+
})}\n`);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
let cache = null;
|
|
79
|
+
export async function buildCodexUsageSnapshot(_agent) {
|
|
80
|
+
if (cache && cache.expiresAt > Date.now())
|
|
81
|
+
return cache.snapshot;
|
|
82
|
+
let snapshot;
|
|
83
|
+
try {
|
|
84
|
+
const rateLimits = classifyCodexRateLimits(await readNativeRateLimits());
|
|
85
|
+
snapshot = { provider: 'codex', fetchedAt: Date.now(), rateLimits, rateLimitsError: null, cliHint: 'Run /status in Codex to see current usage limits.' };
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
89
|
+
snapshot = { provider: 'codex', fetchedAt: Date.now(), rateLimits: null, rateLimitsError: message, cliHint: 'Run /status in Codex to see current usage limits.' };
|
|
90
|
+
}
|
|
91
|
+
cache = { expiresAt: Date.now() + 60_000, snapshot };
|
|
92
|
+
return snapshot;
|
|
93
|
+
}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
: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-highlight-bg: var(--msg-user-bg);--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}.view-mode-toggle{display:flex;gap:2px;position:relative;background:#0009;border-radius:6px;padding:3px;border:1px solid #2a2a3a}.view-mode-toggle__indicator{position:absolute;top:3px;bottom:3px;background:#d4a05a2e;border-radius:4px;transition:left .2s cubic-bezier(.4,0,.2,1),width .2s cubic-bezier(.4,0,.2,1);pointer-events:none;z-index:0}.view-mode-toggle__btn{display:flex;align-items:center;gap:5px;padding:5px 10px;border:none;border-radius:4px;background:transparent;color:#8a8a98;font-size:11px;font-weight:600;font-family:JetBrains Mono,SF Mono,Fira Code,Consolas,monospace;cursor:pointer;transition:color .15s ease,background .15s ease;white-space:nowrap;position:relative;z-index:1}.view-mode-toggle__btn:hover:not(.view-mode-toggle__btn--active){background:#ffffff14;color:#d0d0d8}.view-mode-toggle__btn--active{color:#d4a05a}.view-mode-toggle__btn--active svg{stroke:#d4a05a}.view-mode-toggle__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0}.view-mode-toggle__label{line-height:1}.view-mode-toggle--floating{position:fixed;bottom:70px;left:60px;z-index:150;box-shadow:0 2px 8px #0000004d}@media(max-width:768px){.view-mode-toggle__btn{padding:10px 14px;min-height:44px;min-width:44px;font-size:12px;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.view-mode-toggle__btn:active{opacity:.7;transform:scale(.95)}.view-mode-toggle__icon svg{width:16px;height:16px}.view-mode-toggle__label{font-size:11px}}@media(max-width:480px){.view-mode-toggle--floating{padding:3px}.view-mode-toggle__btn{padding:8px 10px;min-height:44px}.view-mode-toggle__label{display:none}}.app.view-mode-flat .guake-terminal{display:none}.flat-view{--flat-middle-width: 1fr;--flat-inspector-width: 320px;display:grid;grid-template-columns:var(--flat-middle-width) 3px 1fr;height:100%;width:100%;background:#282a36;overflow:hidden;padding-left:64px;box-sizing:border-box;transition:grid-template-columns .25s ease}.flat-view--with-inspector{grid-template-columns:var(--flat-middle-width) 3px 1fr 3px var(--flat-inspector-width)}.flat-splitter{position:relative;cursor:col-resize;background:#ffffff0a;touch-action:none;-webkit-user-select:none;user-select:none;transition:background .15s ease;z-index:2}.flat-splitter:before{content:"";position:absolute;top:0;bottom:0;left:-5px;right:-5px}.flat-splitter:hover{background:#8be9fd73}body.flat-splitter-dragging{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}body.flat-splitter-dragging .flat-splitter{background:#8be9fd99}body.flat-splitter-dragging .flat-view{transition:none!important}.flat-middle{display:flex;flex-direction:column;background:#282a36;border-right:1px solid rgba(255,255,255,.06);overflow:hidden;min-width:280px}.flat-middle__header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;gap:12px}.flat-middle__title{font-size:14px;font-weight:600;color:#f8f8f2;margin:0}.flat-middle__actions{display:flex;gap:6px;flex-shrink:0}.flat-middle__content{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:8px}.flat-middle__content::-webkit-scrollbar{width:6px}.flat-middle__content::-webkit-scrollbar-track{background:transparent}.flat-middle__content::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:3px}.flat-middle__content::-webkit-scrollbar-thumb:hover{background:#fff3}.flat-cta-btn{padding:4px 10px;font-size:11px;font-weight:500;border:none;border-radius:4px;cursor:pointer;transition:all .15s ease;white-space:nowrap}.flat-cta-btn--agent{background:#50fa7b26;color:#50fa7b}.flat-cta-btn--agent:hover{background:#50fa7b40}.flat-cta-btn--boss{background:#ffd70026;color:gold}.flat-cta-btn--boss:hover{background:#ffd70040}.flat-cta-btn--building{background:#8be9fd26;color:#8be9fd}.flat-cta-btn--building:hover{background:#8be9fd40}.flat-cta-btn--area{background:#bd93f926;color:#bd93f9}.flat-cta-btn--area:hover{background:#bd93f940}.flat-middle .agent-overview-panel{position:relative;inset:auto;width:100%;height:100%;border-right:none;flex:1;min-height:0;z-index:auto}.flat-middle .agent-overview-panel .aop-row-controls .close-btn{display:none}.flat-middle__content:has(>.agent-overview-panel){padding:0;overflow:hidden}.flat-right{display:flex;flex-direction:column;background:#21222c;overflow:hidden}.flat-chat{display:flex;flex-direction:column;height:100%}.flat-chat--empty{align-items:center;justify-content:center}.flat-chat__placeholder{display:flex;flex-direction:column;align-items:center;gap:12px;color:#6272a4}.flat-chat__placeholder-icon{font-size:48px;opacity:.5}.flat-chat__placeholder-text{font-size:14px}.flat-map{display:flex;flex-direction:column;height:100%;padding:12px 16px;gap:10px;overflow-y:auto;position:relative}.flat-map::-webkit-scrollbar{width:6px}.flat-map::-webkit-scrollbar-track{background:transparent}.flat-map::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:3px}.flat-map::-webkit-scrollbar-thumb:hover{background:#fff3}.flat-map__header{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-shrink:0;padding-right:130px}.flat-map__title{font-size:13px;font-weight:600;color:#f8f8f2}.flat-map__hint{font-size:11px;color:#6272a4}.flat-map__stats{display:none}.flat-map__view-mode{position:absolute;top:10px;right:12px;z-index:5;background:color-mix(in srgb,#1e1f29 92%,transparent);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);border-radius:999px;box-shadow:0 2px 8px #0000004d}.flat-map__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px;align-content:start}.flat-map__empty{grid-column:1/-1;display:flex;align-items:center;justify-content:center;padding:40px;color:#6272a4;font-size:13px}.flat-map-area-card{display:flex;flex-direction:column;position:relative;isolation:isolate;background:color-mix(in srgb,var(--area-color, #6272a4) 12%,#363848);border:1px solid color-mix(in srgb,var(--area-color, #6272a4) 38%,transparent);border-radius:8px;overflow:hidden;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}.flat-map-area-card:hover{border-color:color-mix(in srgb,var(--area-color, #6272a4) 58%,transparent);box-shadow:0 2px 8px #00000040}.flat-map-area-card__header{display:flex;align-items:center;gap:6px;padding:6px 8px;background:transparent;border:none;cursor:pointer;width:100%;text-align:left;color:#f8f8f2;font-size:12px;font-weight:600;transition:background .15s ease}.flat-map-area-card__header:hover{background:#ffffff0a}.flat-map-area-card__color{width:8px;height:8px;border-radius:50%;flex-shrink:0}.flat-map-area-card__logo{position:absolute;right:8px;bottom:8px;width:88px;height:88px;max-width:55%;max-height:72%;object-fit:contain;opacity:.3;pointer-events:none;-webkit-user-select:none;user-select:none;z-index:-1;border-radius:4px}.flat-map-area-card__name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.flat-map-area-card__count{display:inline-flex;align-items:center;gap:3px;font-size:10px;font-weight:500;color:#6272a4;background:#ffffff0f;padding:1px 5px;border-radius:8px;flex-shrink:0}.flat-map-area-card__caret{font-size:10px;color:#6272a4;flex-shrink:0;width:12px;text-align:center}.flat-map-area-card__agents{display:flex;flex-wrap:wrap;gap:4px;padding:0 8px 8px}.flat-map-agent-chip{position:relative;display:inline-flex;align-items:center;gap:5px;padding:3px 7px 6px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px;cursor:pointer;color:#9a9caa;font-size:11px;text-align:left;transition:background .15s ease,color .15s ease,border-color .15s ease;white-space:nowrap;min-width:0;overflow:hidden}.flat-map-agent-chip:hover{background:#ffffff14;border-color:#ffffff1f;color:#f8f8f2}.flat-map-agent-chip.working{overflow:visible;isolation:isolate;background-color:#4a9eff1f;background-image:linear-gradient(100deg,transparent 30%,rgba(180,230,255,.45) 49%,rgba(139,220,240,.3) 51%,transparent 70%),linear-gradient(100deg,transparent 32%,rgba(139,233,253,.3) 50%,transparent 68%);background-size:220% 100%,260% 100%;background-repeat:no-repeat,no-repeat;background-position:150% 0,150% 0;border-color:#8be9fdb3;color:#f8f8f2;box-shadow:0 0 8px #4a9eff59,inset 0 0 0 1px #8be9fd00;transform-origin:center;will-change:transform,background-position,box-shadow,border-color;animation:flat-map-agent-working-shimmer .75s linear infinite,flat-map-agent-working-shimmer-2 1.15s linear infinite,flat-map-agent-working-pulse 1.1s ease-in-out infinite,flat-map-agent-working-beat .85s ease-in-out infinite,flat-map-agent-working-iris 3.2s linear infinite}.flat-map-agent-chip.working:before{content:"";position:absolute;top:-2px;right:-2px;bottom:-2px;left:-2px;border-radius:inherit;pointer-events:none;z-index:-1;background:conic-gradient(from 0deg,#8be9fd00,#8bc8fd8c,#a082e680,#dc82c873,#dcb48266,#8bc8fd8c,#8be9fd00);filter:blur(8px);transform-origin:center;will-change:transform,opacity;animation:flat-map-agent-working-spin 3.8s linear infinite,flat-map-agent-working-breath 2.6s ease-in-out infinite}.flat-map-agent-chip.working:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:inherit;pointer-events:none;z-index:1;background-image:radial-gradient(1px 1px at 18% 32%,rgba(255,255,255,.7) 0%,transparent 60%),radial-gradient(1px 1px at 72% 58%,rgba(200,240,255,.65) 0%,transparent 60%),radial-gradient(1.5px 1.5px at 42% 80%,rgba(220,200,255,.55) 0%,transparent 60%),radial-gradient(1px 1px at 88% 22%,rgba(255,255,255,.6) 0%,transparent 60%),radial-gradient(1px 1px at 12% 70%,rgba(210,190,255,.55) 0%,transparent 60%),radial-gradient(1px 1px at 58% 18%,rgba(255,255,255,.55) 0%,transparent 60%);mix-blend-mode:screen;opacity:.5;animation:flat-map-agent-working-twinkle 1.9s ease-in-out infinite}.flat-map-agent-chip.working .flat-map-agent-chip__dot{position:relative;z-index:2;box-shadow:0 0 6px #4a9effb3;animation:flat-map-agent-working-dot .65s ease-in-out infinite}.flat-map-agent-chip.working .flat-map-agent-chip__name,.flat-map-agent-chip.working .flat-map-agent-chip__provider-icon,.flat-map-agent-chip.working .flat-map-agent-chip__crown{position:relative;z-index:2}@keyframes flat-map-agent-working-shimmer{0%{background-position:150% 0,150% 0}to{background-position:-70% 0,150% 0}}@keyframes flat-map-agent-working-shimmer-2{0%{background-position:150% 0,150% 0}to{background-position:150% 0,-70% 0}}@keyframes flat-map-agent-working-pulse{0%,to{border-color:#4a9eff8c;box-shadow:0 0 6px #4a9eff59,inset 0 0 0 1px #8be9fd00}50%{border-color:#b4faff;box-shadow:0 0 18px #4a9effcc,0 0 30px #8be9fd59,inset 0 0 0 1px #b4faff8c}}@keyframes flat-map-agent-working-beat{0%,to{transform:scale(1)}35%{transform:scale(1.035)}55%{transform:scale(.99)}75%{transform:scale(1.015)}}@keyframes flat-map-agent-working-dot{0%,to{transform:scale(1);box-shadow:0 0 6px #4a9effb3}50%{transform:scale(1.7);box-shadow:0 0 12px #b4faff,0 0 22px #4a9effb3}}@keyframes flat-map-agent-working-iris{0%{border-color:#8be9fdb3}25%{border-color:#b482ffd9}50%{border-color:#ff78dccc}75%{border-color:#ffc878bf}to{border-color:#8be9fdb3}}@keyframes flat-map-agent-working-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes flat-map-agent-working-breath{0%,to{opacity:.3;filter:blur(7px)}40%{opacity:.7;filter:blur(11px)}70%{opacity:.45;filter:blur(8px)}}@keyframes flat-map-agent-working-twinkle{0%,to{opacity:.25;transform:translate(0) scale(.9)}25%{opacity:1;transform:translate(1px,-1px) scale(1.1)}50%{opacity:.55;transform:translate(-1px,1px) scale(.95)}75%{opacity:1;transform:translate(1px,1px) scale(1.15)}}@media(prefers-reduced-motion:reduce){.flat-map-agent-chip.working{animation:flat-map-agent-working-shimmer 5s linear infinite;background-image:linear-gradient(110deg,transparent 40%,rgba(139,233,253,.3) 50%,transparent 60%),linear-gradient(110deg,transparent 40%,rgba(139,233,253,0) 50%,transparent 60%);transform:none}.flat-map-agent-chip.working:before,.flat-map-agent-chip.working:after{animation:none;opacity:.3}.flat-map-agent-chip.working .flat-map-agent-chip__dot{animation:none}}.flat-map-agent-chip__name{min-width:0;overflow:hidden;text-overflow:ellipsis}.flat-map-agent-chip__dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.flat-map-agent-chip__provider-icon{width:12px;height:12px;object-fit:contain;flex-shrink:0;filter:drop-shadow(0 1px 2px rgba(0,0,0,.25))}.flat-map-agent-chip__crown{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.flat-map-agent-chip__context-bar{position:absolute;left:0;right:0;bottom:0;height:2px;background:#ffffff0f;pointer-events:none}.flat-map-agent-chip__context-bar-fill{display:block;height:100%;transition:width .2s ease,background-color .2s ease}.flat-map-area-card__buildings,.flat-map-area-card__folders{display:flex;flex-wrap:wrap;gap:4px;padding:6px 8px 8px;border-top:1px dashed rgba(255,255,255,.05);margin-top:2px}.flat-map-folder-chip{display:inline-flex;align-items:center;gap:5px;padding:3px 7px;background:#ffffff06;border:1px solid rgba(255,255,255,.06);border-radius:8px;cursor:pointer;color:#9a9caa;font-size:11px;font-family:JetBrains Mono,Fira Code,monospace;text-align:left;transition:background .15s ease,color .15s ease,border-color .15s ease;white-space:nowrap;min-width:0;max-width:100%;overflow:hidden}.flat-map-folder-chip:hover{background:#ffffff12;border-color:#ffffff2e;color:#f8f8f2}.flat-map-folder-chip__name{min-width:0;overflow:hidden;text-overflow:ellipsis}.flat-map-building-chip{display:inline-flex;align-items:center;gap:5px;padding:3px 7px;background:#ffffff06;border:1px dashed rgba(255,255,255,.08);border-left:2px solid var(--building-type-color, rgba(255, 255, 255, .08));border-radius:8px;cursor:pointer;color:#9a9caa;font-size:11px;text-align:left;transition:background .15s ease,color .15s ease,border-color .15s ease;white-space:nowrap;min-width:0;overflow:hidden}.flat-map-building-chip:hover{background:#ffffff12;border-color:#ffffff2e;border-left-color:var(--building-type-color, rgba(255, 255, 255, .18));color:#f8f8f2}.flat-map-building-chip__name{min-width:0;overflow:hidden;text-overflow:ellipsis}.flat-map-building-chip__dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.flat-map-building-chip--error{border-color:#ff4a4a66}.flat-map-building-chip--running{border-style:solid;border-color:#4aff9e40}.flat-terminal-wrapper{display:flex;flex-direction:column;height:100%;min-height:0;position:relative;background:#21222c;overflow:hidden;--guake-side-panel-width: 380px}.flat-terminal-wrapper--with-side-panel>*:not(.guake-git-panel):not(.guake-buildings-panel):not(.guake-workflow-panel):not(.agent-debug-panel){margin-right:var(--guake-side-panel-width);transition:margin-right .2s ease}.flat-terminal-wrapper__header{display:flex;flex-direction:row;align-items:center;gap:12px;padding:10px 12px 6px;border-bottom:1px solid rgba(255,255,255,.06);background:#1e1f29;flex-shrink:0;min-height:40px;overflow:visible}.flat-terminal-wrapper__header-main{display:flex;align-items:center;gap:10px;min-width:0;flex:1 1 auto;overflow:visible;padding:4px 6px;margin:0;background:transparent;border:1px solid transparent;border-radius:8px;color:inherit;font:inherit;text-align:left;cursor:pointer;transition:background .15s ease,border-color .15s ease}.flat-terminal-wrapper__header-main:hover{background:#ffffff0a;border-color:#ffffff0f}.flat-terminal-wrapper__header-main--active{background:#bd93f92e;border-color:#bd93f973}.flat-terminal-wrapper__header-main--active:hover{background:#bd93f942}.flat-terminal-wrapper__header-avatar{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;width:28px;height:28px;border-radius:8px;overflow:visible;transform-origin:center center;border:1.5px solid transparent;box-sizing:border-box}.flat-terminal-wrapper__header-avatar>*{display:block;width:100%;height:100%;object-fit:cover;border-radius:7px}.flat-terminal-wrapper__header-avatar.is-working{border-color:#8be9fd8c;animation:flat-header-avatar-sway 1.2s ease-in-out infinite!important}html.low-power .flat-terminal-wrapper__header-avatar.is-working{animation:none!important}.flat-terminal-wrapper__header-avatar.is-working{z-index:1;will-change:transform;transform-origin:center center}.flat-terminal-wrapper__header-meta{display:flex;align-items:center;justify-content:flex-end;gap:6px;flex:0 0 auto;flex-wrap:nowrap}.flat-terminal-wrapper__statusbar{display:flex;align-items:center;gap:10px;padding:6px 12px;flex-shrink:0;background:#1e1f29;border-top:1px solid rgba(255,255,255,.06);min-height:32px;box-sizing:border-box}.flat-terminal-wrapper__statusbar .flat-terminal-wrapper__cwd,.flat-terminal-wrapper__statusbar .flat-terminal-wrapper__context{background:transparent;border-color:#ffffff0a}.flat-terminal-wrapper__statusbar-spacer{flex:1 1 auto}.flat-terminal-wrapper__buildings{display:inline-flex;align-items:center;gap:4px;padding:2px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px}.flat-terminal-wrapper__building-btn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:22px;padding:0;color:#6272a4;background:transparent;border:none;border-radius:7px;cursor:pointer;transition:background .15s ease,color .15s ease}.flat-terminal-wrapper__building-btn:hover{color:#f8f8f2;background:#ffffff14}.flat-terminal-wrapper__building-btn--offline{color:#ffb86cbf}.flat-terminal-wrapper__building-btn--offline:hover{color:#ffb86c}.flat-terminal-wrapper__building-btn--active{color:#f8f8f2;background:#bd93f947;box-shadow:0 0 0 1px #bd93f973}.flat-terminal-wrapper__building-btn--active:hover{background:#bd93f95c}.flat-terminal-wrapper__building-btn--tests-working{color:#8be9fd;background:#8be9fd24;box-shadow:0 0 0 1px #8be9fd66;animation:flat-tests-glow 1.4s ease-in-out infinite}.flat-terminal-wrapper__building-btn--tests-working svg{animation:flat-tests-shake 1.1s ease-in-out infinite}.flat-terminal-wrapper__building-btn--tests-working:hover{color:#8be9fd;background:#8be9fd38}.flat-terminal-wrapper__detached{display:inline-flex;align-items:center;gap:6px;padding:3px 9px;font-size:11px;font-weight:500;color:#ffb86c;background:#ffb86c1f;border:1px solid rgba(255,184,108,.35);border-radius:10px;animation:blink 1.6s ease-in-out infinite}.flat-terminal-wrapper__area-dir{display:inline-flex;align-items:center;gap:5px;padding:3px 8px;font-size:11px;font-family:SF Mono,Menlo,Consolas,monospace;color:#9a9caa;background:#ffffff08;border:1px solid rgba(255,255,255,.05);border-radius:10px;cursor:pointer;max-width:240px;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:background .15s ease,color .15s ease,border-color .15s ease}.flat-terminal-wrapper__area-dir:hover{background:#ffffff14;color:#f8f8f2;border-color:#ffffff24}.flat-terminal-wrapper__area-dir-name{overflow:hidden;text-overflow:ellipsis}.flat-terminal-wrapper__area-dir-branch{display:inline-flex;align-items:center;gap:3px;color:#8be9fd;opacity:.85}.flat-terminal-wrapper__branch-ahead{display:inline-flex;align-items:center;color:#50fa7b}.flat-terminal-wrapper__branch-behind{display:inline-flex;align-items:center;color:#ffb86c}.flat-terminal-wrapper__area-fetch{display:inline-flex;align-items:center;padding:1px 3px;border-radius:4px;color:#6272a4;cursor:pointer;transition:background .15s ease,color .15s ease}.flat-terminal-wrapper__area-fetch:hover{background:#ffffff14;color:#f8f8f2}.flat-terminal-wrapper__area-fetch--fetching{animation:blink 1s ease-in-out infinite}.flat-terminal-wrapper__context-label{color:#6272a4;margin-right:2px}.flat-terminal-wrapper__context-free{color:#6272a4;font-size:10px}.flat-terminal-wrapper__actions{display:inline-flex;align-items:center;gap:4px;padding:2px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px}.flat-terminal-wrapper__action-btn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:24px;padding:0;font-size:12px;line-height:1;color:#6272a4;background:transparent;border:none;border-radius:7px;cursor:pointer;transition:background .15s ease,color .15s ease,box-shadow .15s ease}.flat-terminal-wrapper__action-btn:hover:not(:disabled){color:#f8f8f2;background:#ffffff0f}.flat-terminal-wrapper__action-btn:disabled{opacity:.35;cursor:not-allowed}.flat-terminal-wrapper__action-btn--active{color:#f8f8f2;background:#bd93f947;box-shadow:0 0 0 1px #bd93f973}.flat-terminal-wrapper__action-btn--active:hover{background:#bd93f95c}.flat-terminal-wrapper__action-btn--danger{color:#ff5555d9}.flat-terminal-wrapper__action-btn--danger:hover{color:#f55;background:#ff55551f}.flat-terminal-wrapper__action-btn--confirm{color:#f55;background:#ff55552e;box-shadow:0 0 0 1px #ff555580;animation:blink 1s ease-in-out infinite}.flat-terminal-wrapper__more{position:relative;display:inline-flex}.flat-terminal-wrapper__more-menu{position:absolute;top:calc(100% + 4px);right:0;min-width:220px;padding:4px;background:#363848;border:1px solid rgba(255,255,255,.08);border-radius:8px;box-shadow:0 8px 28px #00000073;z-index:100}.flat-terminal-wrapper__more-item{display:flex;align-items:center;gap:8px;width:100%;padding:6px 10px;font-size:12px;color:#f8f8f2;background:transparent;border:none;border-radius:6px;cursor:pointer;text-align:left;transition:background .15s ease,color .15s ease}.flat-terminal-wrapper__more-item:hover:not(:disabled){background:#ffffff0f}.flat-terminal-wrapper__more-item:disabled{opacity:.45;cursor:not-allowed}.flat-terminal-wrapper__more-item--danger{color:#ff5555e6}.flat-terminal-wrapper__more-item--danger:hover:not(:disabled){color:#f55;background:#ff55551f}.flat-terminal-wrapper__more-divider{height:1px;margin:4px 2px;background:#ffffff0f}.flat-terminal-wrapper__header-info{display:flex;flex-direction:row;align-items:center;gap:6px;min-width:0;flex:1 1 auto;overflow:hidden}.flat-terminal-wrapper__header-name{font-size:13px;font-weight:600;color:#f8f8f2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;flex:1 1 auto}.flat-terminal-wrapper__header-status{font-size:10px;text-transform:capitalize;flex-shrink:0}.flat-terminal-wrapper__header-task{font-size:11px;color:#6272a4;max-width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:2px 8px;border-radius:10px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);flex-shrink:1}.flat-terminal-wrapper__header-model{display:inline-flex;align-items:center;gap:6px;flex-shrink:0;min-width:0}.flat-terminal-wrapper__header-provider-icon{width:16px;height:16px;object-fit:contain;flex-shrink:0;filter:drop-shadow(0 1px 2px rgba(0,0,0,.25))}.flat-terminal-wrapper__header-model-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;font-size:10px;font-family:SF Mono,Menlo,Consolas,monospace;font-weight:600;color:#9a9caa;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:999px;white-space:nowrap;max-width:180px;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.flat-terminal-wrapper__header-model-name{color:#f8f8f2;text-transform:lowercase;overflow:hidden;text-overflow:ellipsis}.flat-terminal-wrapper__header-model-sep{opacity:.6}.flat-terminal-wrapper__header-model-effort{color:#bd93f9;text-transform:lowercase}.flat-terminal-wrapper__cwd{display:inline-flex;align-items:center;gap:6px;padding:4px 9px;font-size:11px;color:#9a9caa;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px;cursor:pointer;max-width:240px;transition:background .15s ease,border-color .15s ease,color .15s ease}.flat-terminal-wrapper__cwd:hover{background:#ffffff14;border-color:#ffffff24;color:#f8f8f2}.flat-terminal-wrapper__cwd-icon{font-size:12px;line-height:1}.flat-terminal-wrapper__cwd-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:SF Mono,Menlo,Consolas,monospace}.flat-terminal-wrapper__context{display:inline-flex;align-items:center;gap:6px;padding:4px 9px;font-size:11px;color:#9a9caa;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px;cursor:pointer;transition:background .15s ease,border-color .15s ease}.flat-terminal-wrapper__context:hover{background:#ffffff14;border-color:#ffffff24}.flat-terminal-wrapper__context-icon{font-size:12px;line-height:1}.flat-terminal-wrapper__context-bar{position:relative;width:56px;height:5px;border-radius:3px;background:#ffffff14;overflow:hidden}.flat-terminal-wrapper__context-bar-fill{position:absolute;left:0;top:0;height:100%;border-radius:3px;transition:width .2s ease,background-color .2s ease}.flat-terminal-wrapper__context-tokens{font-family:SF Mono,Menlo,Consolas,monospace;font-size:11px;font-weight:600;font-variant-numeric:tabular-nums}.flat-terminal-wrapper__context-warning{font-size:11px;opacity:.8}.flat-terminal-wrapper__view-mode{display:inline-flex;align-items:center;padding:2px;gap:2px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px}.flat-terminal-wrapper__view-mode-btn{display:inline-flex;align-items:center;gap:5px;padding:4px 9px;font-size:11px;font-weight:500;color:#6272a4;background:transparent;border:none;border-radius:8px;cursor:pointer;transition:background .15s ease,color .15s ease,box-shadow .15s ease}.flat-terminal-wrapper__view-mode-btn:hover{color:#f8f8f2;background:#ffffff0a}.flat-terminal-wrapper__view-mode-btn--active{color:#f8f8f2;background:#bd93f947;box-shadow:0 0 0 1px #bd93f980,0 1px 3px #00000040}.flat-terminal-wrapper__view-mode-btn--active:hover{background:#bd93f95c}.flat-terminal-wrapper__view-mode-icon{font-size:13px;line-height:1}.flat-terminal-wrapper__view-mode-label{line-height:1}.flat-terminal-wrapper__theme{display:inline-flex;align-items:center}.flat-terminal-wrapper__theme .theme-selector-trigger{padding:4px 9px;font-size:11px;border-radius:10px;background:#ffffff0a;border:1px solid rgba(255,255,255,.06)}.flat-terminal-wrapper__theme .theme-selector-trigger:hover{background:#ffffff14;border-color:#ffffff24}.flat-terminal-wrapper__inspector-toggle{display:inline-flex;align-items:center;gap:5px;padding:4px 9px;font-size:11px;font-weight:500;color:#9a9caa;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px;cursor:pointer;transition:background .15s ease,border-color .15s ease,color .15s ease,box-shadow .15s ease}.flat-terminal-wrapper__inspector-toggle:hover{color:#f8f8f2;background:#ffffff14;border-color:#ffffff24}.flat-terminal-wrapper__inspector-toggle--active{color:#f8f8f2;background:#bd93f938;border-color:#bd93f98c;box-shadow:0 0 0 1px #bd93f959,0 1px 3px #00000040}.flat-terminal-wrapper__inspector-toggle--active:hover{background:#bd93f952}.flat-terminal-wrapper__inspector-icon{display:inline-flex;align-items:center;justify-content:center;line-height:1}.flat-terminal-wrapper__inspector-label{line-height:1}.flat-terminal-wrapper__close{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;color:#6272a4;background:#ffffff0a;border:1px solid rgba(255,255,255,.06);border-radius:10px;cursor:pointer;transition:background .15s ease,color .15s ease,border-color .15s ease}.flat-terminal-wrapper__close:hover{color:#f55;background:#ff55551f;border-color:#f556}@media(max-width:1100px){.flat-terminal-wrapper__view-mode-label,.flat-terminal-wrapper__inspector-label{display:none}.flat-terminal-wrapper__cwd{max-width:160px}}.flat-terminal-wrapper .guake-output{flex:1 1 auto;min-height:0;overflow-y:auto;padding:14px 18px}.flat-terminal-wrapper .guake-output::-webkit-scrollbar{width:6px}.flat-terminal-wrapper .guake-output::-webkit-scrollbar-track{background:transparent}.flat-terminal-wrapper .guake-output::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:3px}.flat-terminal-wrapper .guake-input-container{position:relative;flex-shrink:0;border-top:1px solid rgba(255,255,255,.06);background:#1e1f29}.flat-terminal-wrapper .guake-search-bar,.flat-terminal-wrapper .atp-search-bar{position:sticky;top:0;z-index:10;background:#1e1f29}.flat-terminal-wrapper .guake-handle,.flat-terminal-wrapper .atp-resize-handle{display:none}.flat-terminal-wrapper .compacting-indicator{padding:12px;margin:8px}@keyframes blink{0%,to{opacity:1}50%{opacity:.3}}.flat-inspector{display:flex;flex-direction:column;min-width:0;min-height:0;height:100%;background:#1e1f29;border-left:1px solid rgba(255,255,255,.06);overflow:hidden;animation:flat-inspector-slide-in .22s ease}.flat-inspector__header{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.06);background:#21222c;flex-shrink:0}.flat-inspector__tabs{display:inline-flex;align-items:center;gap:4px;padding:2px;background:#00000040;border:1px solid rgba(255,255,255,.06);border-radius:6px}.flat-inspector__tab{padding:4px 10px;font-size:12px;font-weight:500;color:#6272a4;background:transparent;border:none;border-radius:4px;cursor:pointer;transition:background .15s ease,color .15s ease}.flat-inspector__tab:hover{color:#f8f8f2}.flat-inspector__tab--active{color:#f8f8f2;background:#ffffff14}.flat-inspector__close{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;font-size:13px;color:#6272a4;background:transparent;border:1px solid transparent;border-radius:6px;cursor:pointer;transition:background .15s ease,color .15s ease,border-color .15s ease}.flat-inspector__close:hover{color:#f8f8f2;background:#ffffff0f;border-color:#ffffff1a}.flat-inspector__body{flex:1 1 auto;min-height:0;min-width:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column}.flat-inspector__body .unit-panel{flex:1 1 auto;min-height:0;min-width:0;padding:10px}.flat-inspector__empty{display:flex;align-items:center;justify-content:center;flex:1;color:#6272a4;font-size:13px}@keyframes flat-inspector-slide-in{0%{opacity:0;transform:translate(12px)}to{opacity:1;transform:translate(0)}}.flat-mobile-sidebar-toggle,.flat-mobile-sidebar-backdrop{display:none}@media(max-width:1024px){.flat-view,.flat-view--with-inspector{grid-template-columns:1fr}.flat-splitter{display:none}.flat-right{grid-column:1/-1}.flat-right>.flat-terminal-wrapper,.flat-right>.flat-chat{flex:1 1 auto;min-height:0;height:auto}.flat-middle{position:fixed;top:0;left:0;bottom:0;width:min(380px,92vw);z-index:185;transform:translate(-110%);transition:transform .22s ease;border-right:1px solid rgba(255,255,255,.08);box-shadow:6px 0 32px #0009}.flat-view--mobile-sidebar-open .flat-middle{transform:translate(0)}.flat-mobile-sidebar-toggle{display:inline-flex;align-items:center;gap:8px;align-self:flex-start;margin:10px 12px 0;padding:8px 12px;font-size:12px;font-weight:500;color:#f8f8f2;background:#363848f2;border:1px solid rgba(255,255,255,.08);border-radius:10px;cursor:pointer;min-height:36px;flex-shrink:0;transition:background .15s ease,border-color .15s ease}.flat-mobile-sidebar-toggle:hover,.flat-mobile-sidebar-toggle:active{background:#bd93f947;border-color:#bd93f980}.flat-mobile-sidebar-toggle__label{line-height:1}.flat-mobile-sidebar-backdrop{display:block;position:fixed;top:0;right:0;bottom:0;left:0;z-index:184;background:#000000ad;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:flat-inspector-fade-in .18s ease}.flat-inspector{position:fixed;top:0;right:0;bottom:0;left:0;z-index:186;border-left:none;animation:none;transform:translate(100%);transition:transform .22s ease}.flat-inspector--open{transform:translate(0)}.flat-inspector--closing{transform:translate(100%)}.flat-inspector__tab{min-height:36px;padding:6px 14px}.flat-inspector__close{min-width:40px;min-height:40px;display:inline-flex;align-items:center;justify-content:center}}.flat-chat-actions-sheet-root{position:fixed;top:0;right:0;bottom:0;left:0;z-index:2050}.flat-chat-actions-sheet__backdrop{position:absolute;top:0;right:0;bottom:0;left:0;background:#00000073;animation:flat-sheet-fade .15s ease}.flat-chat-actions-sheet{position:absolute;left:0;right:0;bottom:var(--mobile-bottom-stack-height, 72px);display:flex;flex-direction:column;gap:10px;padding:8px 14px calc(14px + env(safe-area-inset-bottom,0px));background:#363848;border:1px solid rgba(255,255,255,.08);border-bottom:none;border-top-left-radius:18px;border-top-right-radius:18px;box-shadow:0 -12px 32px #00000080;animation:flat-sheet-slide-up .2s cubic-bezier(.22,1,.36,1)}.flat-chat-actions-sheet__grabber{width:40px;height:4px;margin:2px auto;border-radius:999px;background:#ffffff38}.flat-chat-actions-sheet__title-row{display:flex;align-items:center;justify-content:space-between;gap:8px}.flat-chat-actions-sheet__title{font-size:13px;font-weight:600;color:#f8f8f2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.flat-chat-actions-sheet__done{flex-shrink:0;font-size:13px;font-weight:500;color:#bd93f9;background:none;border:none;padding:6px 4px;cursor:pointer}.flat-chat-actions-sheet__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.flat-chat-actions-sheet__item{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;min-height:64px;padding:8px 4px;font-size:11px;color:#f8f8f2;background:#ffffff0d;border:1px solid rgba(255,255,255,.07);border-radius:12px;cursor:pointer}.flat-chat-actions-sheet__item span{text-align:center;line-height:1.2}.flat-chat-actions-sheet__item.is-active{background:#bd93f93d;border-color:#bd93f980}.flat-chat-actions-sheet__list{display:flex;flex-direction:column;gap:2px}.flat-chat-actions-sheet__row{display:flex;align-items:center;gap:12px;width:100%;min-height:48px;padding:10px 12px;font-size:14px;color:#f8f8f2;background:transparent;border:none;border-radius:10px;cursor:pointer;text-align:left}.flat-chat-actions-sheet__row:active{background:#ffffff0f}.flat-chat-actions-sheet__row:disabled{opacity:.4;cursor:not-allowed}.flat-chat-actions-sheet__row--danger{color:#ff5555e6}.flat-chat-actions-sheet__row.is-armed{color:#f55;background:#ff555529;box-shadow:inset 0 0 0 1px #ff555580}@keyframes flat-sheet-slide-up{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes flat-sheet-fade{0%{opacity:0}to{opacity:1}}@media(max-width:768px){.app.view-mode-flat .mobile-fab-toggle,.app.view-mode-flat .mobile-fab-menu,.app.view-mode-flat .voice-assistant-btn.mobile-voice-assistant{display:none!important}.app.view-mode-flat .flat-view{padding-left:0}.app.view-mode-flat .main-content{height:calc(100% - var(--mobile-bottom-stack-height, 72px))!important;max-height:calc(100% - var(--mobile-bottom-stack-height, 72px))!important;overflow:hidden}.app.view-mode-flat .flat-terminal-wrapper__header,.app.view-mode-flat .flat-inspector__header,.app.view-mode-flat .flat-middle__header,.app.view-mode-flat .flat-map__header{padding-top:calc(6px + env(safe-area-inset-top,0px))}.app.view-mode-flat .flat-terminal-wrapper__header{padding-top:calc(2px + env(safe-area-inset-top,0px))}.app.view-mode-flat .flat-inspector__body,.app.view-mode-flat .flat-middle__content{padding-bottom:var(--mobile-bottom-stack-height, 72px)}.flat-view{padding-left:56px}.flat-middle__header{flex-wrap:wrap;padding:6px 10px;gap:6px}.flat-middle__content{padding:8px}.flat-cta-btn{padding:8px 10px;font-size:11px;min-height:34px}.flat-chat--empty{align-items:stretch;justify-content:flex-start}.flat-map{width:100%;padding:0 10px 12px;gap:8px;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;touch-action:pan-y}.app.view-mode-flat .flat-map__header{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"title toggle" "stats stats";align-items:center;gap:3px 10px;position:sticky;top:0;z-index:8;margin:0 -10px;padding:calc(6px + env(safe-area-inset-top,0px)) 10px 8px;background:color-mix(in srgb,#282a36 94%,transparent);border-bottom:1px solid rgba(255,255,255,.05);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}.flat-map__title{grid-area:title;font-size:15px}.flat-map__hint{display:none}.flat-map__stats{grid-area:stats;display:flex;align-items:center;gap:8px;min-width:0;color:#6272a4;font-size:10px;font-family:SF Mono,Menlo,Consolas,monospace}.flat-map__stats-working{display:inline-flex;align-items:center;gap:4px;color:color-mix(in srgb,#4a9eff 78%,#9a9caa)}.flat-map__stats-dot{width:6px;height:6px;flex-shrink:0;border-radius:50%;background:#4a9eff;box-shadow:0 0 6px #4a9eff8c}.flat-map__view-mode{grid-area:toggle;position:relative;top:auto;right:auto;justify-self:end}.flat-map__view-mode .view-mode-toggle__btn{min-width:40px;min-height:40px;padding:6px 9px}.flat-map__grid{width:100%;grid-template-columns:repeat(2,minmax(0,1fr))!important;gap:8px}.flat-map-area-card{min-width:0;grid-row:auto!important;grid-column:auto!important;border-radius:12px}.flat-map-area-card__header{padding:7px 8px;gap:6px;min-height:48px}.flat-map-area-card__name{font-size:12px}.flat-map-area-card__count{font-size:9px;padding:2px 5px}.flat-map-area-card__logo{position:static;width:22px;height:22px;max-width:22px;max-height:22px;flex-shrink:0;opacity:.82;z-index:0;border-radius:5px}.flat-map-area-card__caret{flex-shrink:0;margin-left:auto;opacity:.7}.flat-map-area-card--collapsed .flat-map-area-card__agents,.flat-map-area-card--collapsed .flat-map-area-card__buildings,.flat-map-area-card--collapsed .flat-map-area-card__folders{display:none}.flat-map-area-card--expanded{grid-column:1/-1!important;border-color:color-mix(in srgb,var(--area-color, #6272a4) 72%,transparent);box-shadow:0 6px 18px #0000004d}.flat-map-area-card__agents{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;padding:2px 8px 8px}.flat-map-agent-chip{width:100%;padding:7px 10px 9px;font-size:12px;min-height:40px}.flat-map-area-card__folders,.flat-map-area-card__buildings{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px}.flat-map-folder-chip,.flat-map-building-chip{width:100%;min-height:36px}.flat-terminal-wrapper__header{flex-wrap:nowrap;padding:6px 10px 4px;gap:8px;min-height:40px;overflow:visible}.flat-terminal-wrapper__header-main{flex:1 1 auto;min-width:0;overflow:hidden;display:grid;grid-template-columns:auto minmax(0,1fr);grid-template-areas:"avatar info" "avatar model";align-items:center;column-gap:8px;row-gap:0;padding:2px 4px}.flat-terminal-wrapper__header-avatar{grid-area:avatar}.flat-terminal-wrapper__header-info{grid-area:info;min-width:0;align-self:end}.flat-terminal-wrapper__header-name{flex:1 1 auto;min-width:0}.flat-terminal-wrapper__header-status{font-size:9px;padding:1px 6px;border-radius:999px;background:#ffffff0f;max-width:72px;overflow:hidden;text-overflow:ellipsis}.flat-terminal-wrapper__header-model{grid-area:model;align-self:start;justify-self:start;min-width:0;max-width:100%;gap:4px}.flat-terminal-wrapper__header-provider-icon{width:11px;height:11px}.flat-terminal-wrapper__header-model-chip{padding:0;background:none;border:none;border-radius:0;font-size:9px;max-width:100%}.flat-terminal-wrapper__header-meta{flex:0 0 auto;justify-content:flex-end;flex-wrap:nowrap;gap:4px}.flat-terminal-wrapper__header-task{display:none}.flat-terminal-wrapper__header-avatar,.flat-terminal-wrapper__header-avatar>*{width:28px;height:28px}.flat-terminal-wrapper__action-btn,.flat-terminal-wrapper__building-btn{min-width:36px;min-height:36px}.flat-terminal-wrapper__statusbar{flex-wrap:wrap;padding:6px 10px;gap:6px;row-gap:6px}.flat-terminal-wrapper__action-btn,.flat-terminal-wrapper__building-btn,.flat-terminal-wrapper__close{width:28px;height:28px}.flat-terminal-wrapper__inspector-toggle{padding:4px 6px}.flat-terminal-wrapper__inspector-label,.flat-terminal-wrapper__actions{display:none}.flat-terminal-wrapper{--guake-side-panel-width: 100%;background:var(--bg-primary)}.flat-right{background:var(--bg-primary)}.flat-terminal-wrapper--with-side-panel>*:not(.guake-git-panel):not(.guake-buildings-panel):not(.guake-workflow-panel):not(.agent-debug-panel){margin-right:0}.flat-terminal-wrapper .guake-git-panel,.flat-terminal-wrapper .guake-buildings-panel,.flat-terminal-wrapper .guake-workflow-panel,.flat-terminal-wrapper .agent-debug-panel{width:100%}.flat-bottom-panel{height:180px}.flat-terminal-wrapper__view-mode,.flat-terminal-wrapper__close,.flat-terminal-wrapper__statusbar,.app.view-mode-flat .flat-mobile-sidebar-toggle,.app.view-mode-flat .flat-terminal-wrapper__inspector-toggle{display:none}}@media(max-width:480px){.flat-view{padding-left:52px}.flat-middle{width:100vw;max-width:100vw;box-shadow:none}.flat-middle__header{padding:8px 10px}.flat-middle__actions{gap:4px}.flat-cta-btn{padding:6px 8px;font-size:10px;min-height:32px}.flat-map-area-card__header{padding:8px 10px;font-size:13px}.flat-map-agent-chip{font-size:12px;padding:6px 8px 8px}.flat-terminal-wrapper__header-name{font-size:12px}.flat-terminal-wrapper__header-model-chip{max-width:100%}.flat-inspector__body{padding-bottom:env(safe-area-inset-bottom,0)}}@media(min-width:1400px){.flat-view{--flat-middle-width: minmax(280px, 400px);--flat-inspector-width: 360px}}@keyframes flat-inspector-fade-in{0%{opacity:0}to{opacity:1}}.flat-classic-terminal{flex:1 1 auto;min-height:0;display:flex;position:relative;overflow:hidden;background:#1a1a2e}.flat-classic-terminal .guake-bottom-terminal-embed{flex:1 1 auto;width:100%;height:100%;min-height:0}.flat-classic-terminal--message{align-items:center;justify-content:center;color:#6272a4;font-size:13px}.flat-bottom-panel{display:flex;flex-direction:column;flex-shrink:0;height:250px;min-height:0;background:#1e1f29;border-top:1px solid rgba(255,255,255,.08);overflow:hidden}.flat-bottom-panel__header{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:4px 10px;background:#21222c;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;min-height:28px}.flat-bottom-panel__title{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:500;color:#f8f8f2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.flat-bottom-panel__muted{color:#6272a4;font-weight:400;font-size:10px}.flat-bottom-panel__header-actions{display:inline-flex;align-items:center;gap:2px;flex-shrink:0}.flat-bottom-panel__close{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;padding:0;color:#6272a4;background:transparent;border:none;border-radius:6px;cursor:pointer;transition:background .15s ease,color .15s ease}.flat-bottom-panel__close:hover{color:#f8f8f2;background:#ffffff14}.flat-bottom-panel__body{flex:1 1 auto;min-height:0;display:flex;background:#282a36}.flat-bottom-panel__body>*{flex:1 1 auto;min-height:0}.flat-bottom-panel__placeholder{flex:1 1 auto;display:flex;align-items:center;justify-content:center;color:#6272a4;font-size:12px}@keyframes flat-tests-shake{0%,to{transform:rotate(0)}20%{transform:rotate(-14deg)}40%{transform:rotate(10deg)}60%{transform:rotate(-7deg)}80%{transform:rotate(4deg)}}@keyframes flat-tests-glow{0%,to{box-shadow:0 0 0 1px #8be9fd4d}50%{box-shadow:0 0 6px 1px #8be9fdb3}}@keyframes flat-header-avatar-sway{0%,to{transform:rotate(0)}25%{transform:rotate(-8deg)}75%{transform:rotate(8deg)}}
|