@runfusion/fusion 0.42.0 → 0.43.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +2454 -1618
- package/dist/client/.vite/manifest.json +74 -74
- package/dist/client/assets/AgentDetailView-BGN03dyz.css +1 -0
- package/dist/client/assets/{AgentDetailView-C5Lb3fd3.js → AgentDetailView-DKMz3r04.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-DtRcvE6M.js → AgentPermissionPolicyEditor-BiY1a4KR.js} +2 -2
- package/dist/client/assets/{AgentsView-BVW-NOYD.js → AgentsView-Co-k4vjh.js} +3 -3
- package/dist/client/assets/ChatView-BkAG99bj.js +6 -0
- package/dist/client/assets/{DevServerView-DLsFSP4s.js → DevServerView-C6DC0URX.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-_QawX-uL.js → DirectoryPicker-CkcGjyv0.js} +1 -1
- package/dist/client/assets/{DocumentsView-DierUJsj.js → DocumentsView-OCK1Vsw_.js} +1 -1
- package/dist/client/assets/{EvalsView-B83lYKQl.js → EvalsView-CUfyj5GW.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-CTctYTPU.js → ExperimentalAgentOnboardingModal-Dau9RTU_.js} +1 -1
- package/dist/client/assets/{GoalsView-CKn8i0i0.js → GoalsView-CNLTn0rX.js} +1 -1
- package/dist/client/assets/{InsightsView-EpRHCD8G.js → InsightsView-BQPxHxKI.js} +1 -1
- package/dist/client/assets/{MemoryView-Df_ocTc5.js → MemoryView-D3xQIFjj.js} +1 -1
- package/dist/client/assets/{NodesView-DF7xJ_3z.js → NodesView-CSMvGwDU.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-BOooOEDx.js → PiExtensionsManager-BtqXF3fl.js} +1 -1
- package/dist/client/assets/{PluginManager-CHrDAzK6.js → PluginManager-CSSDb3VO.js} +1 -1
- package/dist/client/assets/{PullRequestView-CJU21OZ6.js → PullRequestView-Bjyfffdu.js} +1 -1
- package/dist/client/assets/{ReliabilityView-uHkW1Qeu.js → ReliabilityView-QKMUDebT.js} +1 -1
- package/dist/client/assets/{ResearchView-oZ2-vbjL.js → ResearchView-CRU_NPho.js} +1 -1
- package/dist/client/assets/{SecretsView-BpkqSV_E.js → SecretsView-Bs8ySyC5.js} +1 -1
- package/dist/client/assets/SecretsView-Djo1rahi.css +1 -0
- package/dist/client/assets/{SessionTerminal-D9IW4cDj.js → SessionTerminal-Dk1NgmN2.js} +1 -1
- package/dist/client/assets/SettingsModal-DpAxDq6M.css +1 -0
- package/dist/client/assets/{SettingsModal-C8gsAazm.js → SettingsModal-JCaNvdAb.js} +6 -6
- package/dist/client/assets/{SettingsModal-BmB5l2bA.js → SettingsModal-Nw5cTKAK.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-BYLEU_7o.js → SetupWizardModal-CE79myEy.js} +1 -1
- package/dist/client/assets/{SkillsView-8GgQ8Z_Z.js → SkillsView-Dc8YskAX.js} +1 -1
- package/dist/client/assets/{StashRecoveryView-CT1t1Uf2.js → StashRecoveryView-CqKOFiXT.js} +1 -1
- package/dist/client/assets/{TodoView-BUj6ITAb.js → TodoView-BqIRwcZw.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-CN7GPmvV.js → WorkflowNodeEditor-2jDuk2FR.js} +1 -1
- package/dist/client/assets/WorkflowNodeEditor-BokhW3de.css +1 -0
- package/dist/client/assets/{app-DCot4oXA.js → app-CUu1sm3x.js} +2 -2
- package/dist/client/assets/{dashboard-view-CrYwb0oQ.js → dashboard-view-BhbN8LPh.js} +1 -1
- package/dist/client/assets/{folder-open-CREXTATY.js → folder-open-Bw1mxVfa.js} +1 -1
- package/dist/client/assets/index-CpTBp1RG.js +793 -0
- package/dist/client/assets/index-DqhCiU35.css +1 -0
- package/dist/client/assets/{upload-BvLUlwaH.js → upload-BCmd-1I0.js} +1 -1
- package/dist/client/assets/{users-CjhbU-sF.js → users-DO_t3V1p.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +1892 -1107
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugin-sdk/index.d.ts +6260 -86
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +177 -18
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -9
- package/dist/automation-store-EKXXEE2S.js +0 -10
- package/dist/automation-store-PLNG3X72.js +0 -10
- package/dist/automation-store-RDDYZFUJ.js +0 -10
- package/dist/chunk-2JI3F6MG.js +0 -948
- package/dist/chunk-4L6CLWJC.js +0 -8345
- package/dist/chunk-4VNS5WPM.js +0 -42
- package/dist/chunk-5RGECGQL.js +0 -1139
- package/dist/chunk-6JDLN7IL.js +0 -409
- package/dist/chunk-AICJATVW.js +0 -948
- package/dist/chunk-AWKNRUOR.js +0 -1148
- package/dist/chunk-BHM3UYWS.js +0 -4651
- package/dist/chunk-BMUXDSBF.js +0 -4647
- package/dist/chunk-GETECT6V.js +0 -353
- package/dist/chunk-GUV4QQT3.js +0 -1143
- package/dist/chunk-JKQO7YYZ.js +0 -8369
- package/dist/chunk-LYZVU6UV.js +0 -409
- package/dist/chunk-MAN4WYHO.js +0 -353
- package/dist/chunk-MCUG2Z7M.js +0 -4651
- package/dist/chunk-PSDYB45U.js +0 -948
- package/dist/chunk-RR2HM46R.js +0 -8345
- package/dist/chunk-RXMQ5OMY.js +0 -9226
- package/dist/chunk-S2EVJUY3.js +0 -353
- package/dist/chunk-UXR5XZFZ.js +0 -409
- package/dist/client/assets/AgentDetailView-DiWELtb1.css +0 -1
- package/dist/client/assets/ChatView-Dy-oIkrK.js +0 -6
- package/dist/client/assets/SecretsView-D5bHZ-wM.css +0 -1
- package/dist/client/assets/SettingsModal-bJvc9aHl.css +0 -1
- package/dist/client/assets/WorkflowNodeEditor-aPj8cv81.css +0 -1
- package/dist/client/assets/index-2kYpdJrx.js +0 -793
- package/dist/client/assets/index-CJUfvGdC.css +0 -1
- package/dist/extract-zip-WL55Z3AU.js +0 -2497
- package/dist/index.min-CHQ3ABYJ.js +0 -2926
- package/dist/memory-dreams-7USISKVE.js +0 -32
- package/dist/memory-dreams-PBPISUDD.js +0 -32
- package/dist/memory-dreams-XNO2B2QF.js +0 -32
- package/dist/migration-EH2YOCYQ.js +0 -15
- package/dist/migration-PLGTTKL5.js +0 -15
- package/dist/migration-WZEZK22R.js +0 -15
- package/dist/routine-store-GIJ6MXWY.js +0 -10
- package/dist/routine-store-HTVC2PUQ.js +0 -10
- package/dist/routine-store-KGHZBPDF.js +0 -10
package/dist/chunk-UXR5XZFZ.js
DELETED
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
assertProjectRootDir,
|
|
3
|
-
require_dist
|
|
4
|
-
} from "./chunk-RXMQ5OMY.js";
|
|
5
|
-
import {
|
|
6
|
-
Database,
|
|
7
|
-
fromJson
|
|
8
|
-
} from "./chunk-BMUXDSBF.js";
|
|
9
|
-
import {
|
|
10
|
-
__toESM
|
|
11
|
-
} from "./chunk-4VNS5WPM.js";
|
|
12
|
-
|
|
13
|
-
// ../core/dist/routine-store.js
|
|
14
|
-
var import_cron_parser = __toESM(require_dist(), 1);
|
|
15
|
-
import { EventEmitter } from "events";
|
|
16
|
-
import { randomUUID } from "crypto";
|
|
17
|
-
|
|
18
|
-
// ../core/dist/routine.js
|
|
19
|
-
function isCronTrigger(trigger) {
|
|
20
|
-
return trigger.type === "cron";
|
|
21
|
-
}
|
|
22
|
-
var MAX_ROUTINE_RUN_HISTORY = 50;
|
|
23
|
-
|
|
24
|
-
// ../core/dist/routine-store.js
|
|
25
|
-
var CRON_TIMEZONE = "UTC";
|
|
26
|
-
var RoutineStore = class _RoutineStore extends EventEmitter {
|
|
27
|
-
rootDir;
|
|
28
|
-
/** SQLite database instance (lazy init). */
|
|
29
|
-
_db = null;
|
|
30
|
-
/** Per-routine promise chain for serializing writes. */
|
|
31
|
-
routineLocks = /* @__PURE__ */ new Map();
|
|
32
|
-
inMemoryDb;
|
|
33
|
-
constructor(rootDir, options) {
|
|
34
|
-
super();
|
|
35
|
-
this.rootDir = rootDir;
|
|
36
|
-
assertProjectRootDir(rootDir, "RoutineStore");
|
|
37
|
-
this.inMemoryDb = options?.inMemoryDb === true;
|
|
38
|
-
}
|
|
39
|
-
// ── Database Access ────────────────────────────────────────────────
|
|
40
|
-
/**
|
|
41
|
-
* Get the SQLite database, initializing it on first access.
|
|
42
|
-
*/
|
|
43
|
-
get db() {
|
|
44
|
-
if (!this._db) {
|
|
45
|
-
const fusionDir = `${this.rootDir}/.fusion`;
|
|
46
|
-
this._db = new Database(fusionDir, { inMemory: this.inMemoryDb });
|
|
47
|
-
this._db.init();
|
|
48
|
-
}
|
|
49
|
-
return this._db;
|
|
50
|
-
}
|
|
51
|
-
/** Initialize the store (no-op, DB is lazily initialized). */
|
|
52
|
-
async init() {
|
|
53
|
-
const _ = this.db;
|
|
54
|
-
}
|
|
55
|
-
// ── Row Conversion ─────────────────────────────────────────────────
|
|
56
|
-
rowToRoutine(row) {
|
|
57
|
-
const triggerConfig = fromJson(row.triggerConfig);
|
|
58
|
-
let trigger;
|
|
59
|
-
switch (row.triggerType) {
|
|
60
|
-
case "cron":
|
|
61
|
-
trigger = {
|
|
62
|
-
type: "cron",
|
|
63
|
-
cronExpression: triggerConfig?.cronExpression ?? "0 * * * *",
|
|
64
|
-
timezone: triggerConfig?.timezone
|
|
65
|
-
};
|
|
66
|
-
break;
|
|
67
|
-
case "webhook":
|
|
68
|
-
trigger = {
|
|
69
|
-
type: "webhook",
|
|
70
|
-
webhookPath: triggerConfig?.webhookPath ?? "",
|
|
71
|
-
secret: triggerConfig?.secret
|
|
72
|
-
};
|
|
73
|
-
break;
|
|
74
|
-
case "api":
|
|
75
|
-
trigger = {
|
|
76
|
-
type: "api",
|
|
77
|
-
endpoint: triggerConfig?.endpoint ?? ""
|
|
78
|
-
};
|
|
79
|
-
break;
|
|
80
|
-
case "manual":
|
|
81
|
-
default:
|
|
82
|
-
trigger = { type: "manual" };
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
return {
|
|
86
|
-
id: row.id,
|
|
87
|
-
agentId: row.agentId || "",
|
|
88
|
-
name: row.name,
|
|
89
|
-
description: row.description || void 0,
|
|
90
|
-
trigger,
|
|
91
|
-
command: row.command || void 0,
|
|
92
|
-
steps: fromJson(row.steps),
|
|
93
|
-
timeoutMs: row.timeoutMs ?? void 0,
|
|
94
|
-
catchUpPolicy: row.catchUpPolicy || "run_one",
|
|
95
|
-
executionPolicy: row.executionPolicy || "queue",
|
|
96
|
-
enabled: row.enabled === 1,
|
|
97
|
-
lastRunAt: row.lastRunAt || void 0,
|
|
98
|
-
lastRunResult: fromJson(row.lastRunResult),
|
|
99
|
-
nextRunAt: row.nextRunAt || void 0,
|
|
100
|
-
runCount: row.runCount || 0,
|
|
101
|
-
runHistory: fromJson(row.runHistory) || [],
|
|
102
|
-
catchUpLimit: row.catchUpLimit ?? 5,
|
|
103
|
-
cronExpression: isCronTrigger(trigger) ? trigger.cronExpression : void 0,
|
|
104
|
-
scope: row.scope || "project",
|
|
105
|
-
createdAt: row.createdAt,
|
|
106
|
-
updatedAt: row.updatedAt
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
upsertRoutine(routine) {
|
|
110
|
-
const trigger = routine.trigger;
|
|
111
|
-
let triggerConfig = {};
|
|
112
|
-
if (isCronTrigger(trigger)) {
|
|
113
|
-
triggerConfig = {
|
|
114
|
-
cronExpression: trigger.cronExpression,
|
|
115
|
-
timezone: trigger.timezone
|
|
116
|
-
};
|
|
117
|
-
} else if (trigger.type === "webhook") {
|
|
118
|
-
triggerConfig = {
|
|
119
|
-
webhookPath: trigger.webhookPath,
|
|
120
|
-
secret: trigger.secret
|
|
121
|
-
};
|
|
122
|
-
} else if (trigger.type === "api") {
|
|
123
|
-
triggerConfig = {
|
|
124
|
-
endpoint: trigger.endpoint
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
this.db.prepare(`
|
|
128
|
-
INSERT OR REPLACE INTO routines (
|
|
129
|
-
id, agentId, name, description, triggerType, triggerConfig,
|
|
130
|
-
command, steps, timeoutMs,
|
|
131
|
-
catchUpPolicy, executionPolicy, catchUpLimit, enabled,
|
|
132
|
-
lastRunAt, lastRunResult, nextRunAt,
|
|
133
|
-
runCount, runHistory, scope, createdAt, updatedAt
|
|
134
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
135
|
-
`).run(routine.id, routine.agentId, routine.name, routine.description ?? null, trigger.type, JSON.stringify(triggerConfig), routine.command ?? null, routine.steps ? JSON.stringify(routine.steps) : null, routine.timeoutMs ?? null, routine.catchUpPolicy, routine.executionPolicy, routine.catchUpLimit ?? 5, routine.enabled ? 1 : 0, routine.lastRunAt ?? null, routine.lastRunResult ? JSON.stringify(routine.lastRunResult) : null, routine.nextRunAt ?? null, routine.runCount || 0, JSON.stringify(routine.runHistory || []), routine.scope ?? "project", routine.createdAt, routine.updatedAt);
|
|
136
|
-
this.db.bumpLastModified();
|
|
137
|
-
}
|
|
138
|
-
// ── Locking ───────────────────────────────────────────────────────
|
|
139
|
-
/**
|
|
140
|
-
* Serialize all mutations to a given routine by chaining promises.
|
|
141
|
-
* Concurrent callers for the same ID will queue behind each other.
|
|
142
|
-
*/
|
|
143
|
-
withRoutineLock(id, fn) {
|
|
144
|
-
const prev = this.routineLocks.get(id) ?? Promise.resolve();
|
|
145
|
-
let resolve;
|
|
146
|
-
const next = new Promise((r) => {
|
|
147
|
-
resolve = r;
|
|
148
|
-
});
|
|
149
|
-
this.routineLocks.set(id, next);
|
|
150
|
-
return prev.then(async () => {
|
|
151
|
-
try {
|
|
152
|
-
return await fn();
|
|
153
|
-
} finally {
|
|
154
|
-
if (this.routineLocks.get(id) === next) {
|
|
155
|
-
this.routineLocks.delete(id);
|
|
156
|
-
}
|
|
157
|
-
resolve();
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
// ── Cron Utilities ────────────────────────────────────────────────
|
|
162
|
-
/**
|
|
163
|
-
* Compute the next run time from a cron expression.
|
|
164
|
-
* @param cronExpression - A valid cron expression (5 fields).
|
|
165
|
-
* @param fromDate - The date to compute from. Defaults to now.
|
|
166
|
-
* @returns ISO-8601 timestamp of the next run.
|
|
167
|
-
*/
|
|
168
|
-
computeNextRun(cronExpression, fromDate) {
|
|
169
|
-
const interval = import_cron_parser.CronExpressionParser.parse(cronExpression, {
|
|
170
|
-
currentDate: fromDate ?? /* @__PURE__ */ new Date(),
|
|
171
|
-
tz: CRON_TIMEZONE
|
|
172
|
-
});
|
|
173
|
-
const next = interval.next();
|
|
174
|
-
return new Date(next.getTime()).toISOString();
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Validate a cron expression. Returns true if valid.
|
|
178
|
-
*/
|
|
179
|
-
static isValidCron(cronExpression) {
|
|
180
|
-
try {
|
|
181
|
-
import_cron_parser.CronExpressionParser.parse(cronExpression);
|
|
182
|
-
return true;
|
|
183
|
-
} catch {
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
// ── CRUD ──────────────────────────────────────────────────────────
|
|
188
|
-
/**
|
|
189
|
-
* Create a new routine.
|
|
190
|
-
*/
|
|
191
|
-
async createRoutine(input) {
|
|
192
|
-
if (!input.name?.trim()) {
|
|
193
|
-
throw new Error("Name is required and cannot be empty");
|
|
194
|
-
}
|
|
195
|
-
if (isCronTrigger(input.trigger)) {
|
|
196
|
-
if (!_RoutineStore.isValidCron(input.trigger.cronExpression)) {
|
|
197
|
-
throw new Error(`Invalid cron expression: "${input.trigger.cronExpression}"`);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
const id = randomUUID();
|
|
201
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
202
|
-
const enabled = input.enabled !== void 0 ? input.enabled : true;
|
|
203
|
-
const routine = {
|
|
204
|
-
id,
|
|
205
|
-
agentId: input.agentId,
|
|
206
|
-
name: input.name.trim(),
|
|
207
|
-
description: input.description?.trim() || void 0,
|
|
208
|
-
trigger: input.trigger,
|
|
209
|
-
command: input.command?.trim() || void 0,
|
|
210
|
-
steps: input.steps && input.steps.length > 0 ? input.steps : void 0,
|
|
211
|
-
timeoutMs: input.timeoutMs,
|
|
212
|
-
catchUpPolicy: input.catchUpPolicy ?? "run_one",
|
|
213
|
-
executionPolicy: input.executionPolicy ?? "queue",
|
|
214
|
-
enabled,
|
|
215
|
-
runCount: 0,
|
|
216
|
-
runHistory: [],
|
|
217
|
-
scope: input.scope ?? "project",
|
|
218
|
-
createdAt: now,
|
|
219
|
-
updatedAt: now
|
|
220
|
-
};
|
|
221
|
-
if (enabled && isCronTrigger(routine.trigger)) {
|
|
222
|
-
routine.nextRunAt = this.computeNextRun(routine.trigger.cronExpression);
|
|
223
|
-
}
|
|
224
|
-
this.upsertRoutine(routine);
|
|
225
|
-
this.emit("routine:created", routine);
|
|
226
|
-
return routine;
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Get a routine by ID.
|
|
230
|
-
*/
|
|
231
|
-
async getRoutine(id) {
|
|
232
|
-
const row = this.db.prepare("SELECT * FROM routines WHERE id = ?").get(id);
|
|
233
|
-
if (!row) {
|
|
234
|
-
throw Object.assign(new Error(`Routine '${id}' not found`), { code: "ENOENT" });
|
|
235
|
-
}
|
|
236
|
-
return this.rowToRoutine(row);
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* List all routines.
|
|
240
|
-
*/
|
|
241
|
-
async listRoutines() {
|
|
242
|
-
const rows = this.db.prepare("SELECT * FROM routines ORDER BY createdAt ASC").all();
|
|
243
|
-
return rows.map((row) => this.rowToRoutine(row));
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Update an existing routine.
|
|
247
|
-
*/
|
|
248
|
-
async updateRoutine(id, updates) {
|
|
249
|
-
return this.withRoutineLock(id, async () => {
|
|
250
|
-
const routine = await this.getRoutine(id);
|
|
251
|
-
if (updates.name !== void 0) {
|
|
252
|
-
if (!updates.name.trim())
|
|
253
|
-
throw new Error("Name cannot be empty");
|
|
254
|
-
routine.name = updates.name.trim();
|
|
255
|
-
}
|
|
256
|
-
if (updates.description !== void 0) {
|
|
257
|
-
routine.description = updates.description?.trim() || void 0;
|
|
258
|
-
}
|
|
259
|
-
if (updates.trigger !== void 0) {
|
|
260
|
-
if (isCronTrigger(updates.trigger)) {
|
|
261
|
-
if (!_RoutineStore.isValidCron(updates.trigger.cronExpression)) {
|
|
262
|
-
throw new Error(`Invalid cron expression: "${updates.trigger.cronExpression}"`);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
routine.trigger = updates.trigger;
|
|
266
|
-
}
|
|
267
|
-
if (updates.command !== void 0) {
|
|
268
|
-
routine.command = updates.command?.trim() || void 0;
|
|
269
|
-
}
|
|
270
|
-
if (updates.steps !== void 0) {
|
|
271
|
-
routine.steps = updates.steps.length > 0 ? updates.steps : void 0;
|
|
272
|
-
}
|
|
273
|
-
if (updates.timeoutMs !== void 0) {
|
|
274
|
-
routine.timeoutMs = updates.timeoutMs;
|
|
275
|
-
}
|
|
276
|
-
if (updates.catchUpPolicy !== void 0) {
|
|
277
|
-
routine.catchUpPolicy = updates.catchUpPolicy;
|
|
278
|
-
}
|
|
279
|
-
if (updates.executionPolicy !== void 0) {
|
|
280
|
-
routine.executionPolicy = updates.executionPolicy;
|
|
281
|
-
}
|
|
282
|
-
if (updates.enabled !== void 0) {
|
|
283
|
-
routine.enabled = updates.enabled;
|
|
284
|
-
}
|
|
285
|
-
if (routine.enabled && isCronTrigger(routine.trigger)) {
|
|
286
|
-
routine.nextRunAt = this.computeNextRun(routine.trigger.cronExpression);
|
|
287
|
-
} else if (!routine.enabled || !isCronTrigger(routine.trigger)) {
|
|
288
|
-
routine.nextRunAt = void 0;
|
|
289
|
-
}
|
|
290
|
-
routine.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
291
|
-
this.upsertRoutine(routine);
|
|
292
|
-
this.emit("routine:updated", routine);
|
|
293
|
-
return routine;
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Delete a routine.
|
|
298
|
-
*/
|
|
299
|
-
async deleteRoutine(id) {
|
|
300
|
-
return this.withRoutineLock(id, async () => {
|
|
301
|
-
const routine = await this.getRoutine(id);
|
|
302
|
-
this.db.prepare("DELETE FROM routines WHERE id = ?").run(id);
|
|
303
|
-
this.db.bumpLastModified();
|
|
304
|
-
this.emit("routine:deleted", routine);
|
|
305
|
-
return routine;
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
// ── Run Tracking ─────────────────────────────────────────────────
|
|
309
|
-
/**
|
|
310
|
-
* Record a run result for a routine. Updates lastRunAt, lastRunResult,
|
|
311
|
-
* nextRunAt, runCount, and appends to runHistory.
|
|
312
|
-
*/
|
|
313
|
-
async recordRun(id, result) {
|
|
314
|
-
return this.withRoutineLock(id, async () => {
|
|
315
|
-
const routine = await this.getRoutine(id);
|
|
316
|
-
routine.lastRunAt = result.startedAt;
|
|
317
|
-
routine.lastRunResult = result;
|
|
318
|
-
routine.runCount += 1;
|
|
319
|
-
routine.runHistory.unshift(result);
|
|
320
|
-
if (routine.runHistory.length > MAX_ROUTINE_RUN_HISTORY) {
|
|
321
|
-
routine.runHistory = routine.runHistory.slice(0, MAX_ROUTINE_RUN_HISTORY);
|
|
322
|
-
}
|
|
323
|
-
if (routine.enabled && isCronTrigger(routine.trigger)) {
|
|
324
|
-
routine.nextRunAt = this.computeNextRun(routine.trigger.cronExpression);
|
|
325
|
-
}
|
|
326
|
-
routine.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
327
|
-
this.upsertRoutine(routine);
|
|
328
|
-
this.emit("routine:run", { routine, result });
|
|
329
|
-
return routine;
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Mark a routine execution as started (pre-run bookkeeping).
|
|
334
|
-
*/
|
|
335
|
-
async startRoutineExecution(id, meta) {
|
|
336
|
-
await this.withRoutineLock(id, async () => {
|
|
337
|
-
const routine = await this.getRoutine(id);
|
|
338
|
-
routine.lastRunAt = meta.triggeredAt;
|
|
339
|
-
routine.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
340
|
-
this.upsertRoutine(routine);
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Record the completion (success or failure) of a routine execution.
|
|
345
|
-
*/
|
|
346
|
-
async completeRoutineExecution(id, meta) {
|
|
347
|
-
await this.withRoutineLock(id, async () => {
|
|
348
|
-
const routine = await this.getRoutine(id);
|
|
349
|
-
const result = {
|
|
350
|
-
routineId: id,
|
|
351
|
-
success: meta.success,
|
|
352
|
-
output: meta.output ?? (meta.success ? JSON.stringify(meta.resultJson ?? {}) : ""),
|
|
353
|
-
error: meta.error,
|
|
354
|
-
startedAt: routine.lastRunAt ?? meta.completedAt,
|
|
355
|
-
completedAt: meta.completedAt,
|
|
356
|
-
triggerType: meta.triggerType,
|
|
357
|
-
stepResults: meta.stepResults
|
|
358
|
-
};
|
|
359
|
-
routine.lastRunAt = result.startedAt;
|
|
360
|
-
routine.lastRunResult = result;
|
|
361
|
-
routine.runCount += 1;
|
|
362
|
-
routine.runHistory.unshift(result);
|
|
363
|
-
if (routine.runHistory.length > MAX_ROUTINE_RUN_HISTORY) {
|
|
364
|
-
routine.runHistory = routine.runHistory.slice(0, MAX_ROUTINE_RUN_HISTORY);
|
|
365
|
-
}
|
|
366
|
-
if (routine.enabled && isCronTrigger(routine.trigger)) {
|
|
367
|
-
routine.nextRunAt = this.computeNextRun(routine.trigger.cronExpression);
|
|
368
|
-
}
|
|
369
|
-
routine.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
370
|
-
this.upsertRoutine(routine);
|
|
371
|
-
this.emit("routine:run", { routine, result });
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* Cancel a routine execution (no result recorded, just reset state).
|
|
376
|
-
*/
|
|
377
|
-
async cancelRoutineExecution(id) {
|
|
378
|
-
await this.withRoutineLock(id, async () => {
|
|
379
|
-
const routine = await this.getRoutine(id);
|
|
380
|
-
if (routine.enabled && isCronTrigger(routine.trigger)) {
|
|
381
|
-
routine.nextRunAt = this.computeNextRun(routine.trigger.cronExpression);
|
|
382
|
-
}
|
|
383
|
-
routine.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
384
|
-
this.upsertRoutine(routine);
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* Get all routines that are due to run (nextRunAt <= now and enabled).
|
|
389
|
-
* Filters by scope: "global" or "project".
|
|
390
|
-
*/
|
|
391
|
-
async getDueRoutines(scope) {
|
|
392
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
393
|
-
const rows = this.db.prepare("SELECT * FROM routines WHERE enabled = 1 AND nextRunAt IS NOT NULL AND nextRunAt <= ? AND scope = ?").all(now, scope);
|
|
394
|
-
return rows.map((row) => this.rowToRoutine(row));
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* Get all routines that are due to run (nextRunAt <= now and enabled) for both scopes.
|
|
398
|
-
* Returns routines from both "global" and "project" scopes.
|
|
399
|
-
*/
|
|
400
|
-
async getDueRoutinesAllScopes() {
|
|
401
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
402
|
-
const rows = this.db.prepare("SELECT * FROM routines WHERE enabled = 1 AND nextRunAt IS NOT NULL AND nextRunAt <= ?").all(now);
|
|
403
|
-
return rows.map((row) => this.rowToRoutine(row));
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
export {
|
|
408
|
-
RoutineStore
|
|
409
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.agent-detail-overlay{position:fixed;inset:0;background:color-mix(in srgb,var(--bg) 60%,transparent);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:100;padding:var(--space-lg)}.agent-detail-modal{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);width:100%;min-width:calc(var(--space-xl) * 20);max-width:calc(100vw - var(--space-2xl) - var(--space-xs) * 2);min-height:calc(var(--space-xl) * 13 + var(--space-sm));max-height:calc(100dvh - var(--space-2xl) - var(--space-xs) * 2);display:flex;flex-direction:column;overflow:hidden;resize:both;box-shadow:var(--shadow-lg)}.agent-detail-modal:not([style*=width]){width:min(calc(var(--space-xl) * 37 + var(--space-md)),calc(100vw - var(--space-2xl) - var(--space-xs) * 2))}.agent-detail-modal:not([style*=height]){height:min(85vh,calc(100dvh - var(--space-2xl) - var(--space-xs) * 2))}.agent-detail-inline-shell{width:100%;height:100%;min-height:0;display:flex;flex-direction:column;overflow:hidden}.agent-detail-inline{width:100%;height:100%;min-height:0;display:flex;flex-direction:column;overflow:hidden;background:var(--surface);border:1px solid var(--border)}.agent-detail-inline-loading{width:100%;height:100%;min-height:0;display:flex;align-items:center;justify-content:center;overflow:hidden}.agent-detail-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-md);padding:calc(var(--space-xl) * 2 + var(--space-md));color:var(--text-muted)}.agent-detail-header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-md);padding:var(--space-md) calc(var(--space-lg) + var(--space-xs));border-bottom:1px solid var(--border);background:var(--bg-secondary);flex-shrink:0}.agent-detail-identity{display:flex;align-items:center;gap:var(--space-md);flex-shrink:0;min-width:0}.agent-detail-inline-back{display:inline-flex;align-items:center;gap:var(--space-xs);min-height:calc(var(--space-lg) + var(--space-md) + var(--space-xs));padding:calc(var(--space-sm) - var(--space-xs) * .5) calc(var(--space-sm) + var(--space-xs) * .5);flex-shrink:0}.agent-detail-icon{width:calc(var(--space-lg) * 2 + var(--space-xs));height:calc(var(--space-lg) * 2 + var(--space-xs));display:flex;align-items:center;justify-content:center;color:var(--text);flex-shrink:0}.agent-detail-info{min-width:0}.agent-detail-info h2{font-size:calc(var(--space-md) + var(--space-xs));font-weight:600;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.agent-detail-badges{display:flex;gap:var(--space-xs);margin-top:calc(var(--space-xs) * .5)}.agent-detail-header-actions{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-sm);flex:1 1 auto;min-width:0}.agent-detail-controls{display:flex;align-items:center;gap:calc(var(--space-xs) + var(--space-sm) * .25);flex-shrink:0}.btn--compact{padding:calc(var(--space-xs) + var(--space-xs) * .25) calc(var(--space-sm) + var(--space-xs) * .5);font-size:var(--space-md);gap:var(--space-xs)}.agent-detail-utility-actions{display:flex;align-items:center;gap:var(--space-xs);flex-shrink:0}.agent-detail-bulk-menu{position:relative}.agent-detail-bulk-menu-popover{position:absolute;right:0;top:calc(100% + var(--space-xs));min-width:calc(var(--space-xl) * 9);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);z-index:2;padding:var(--space-xs);display:flex;flex-direction:column;gap:var(--space-xs)}.agent-detail-bulk-menu-item{width:100%;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--text);text-align:left;padding:var(--space-sm);display:flex;flex-direction:column;gap:calc(var(--space-xs) * .5);cursor:pointer}.agent-detail-bulk-menu-item:hover:not(:disabled),.agent-detail-bulk-menu-item:focus-visible{outline:none;background:var(--card-hover)}.agent-detail-bulk-menu-item:disabled{color:var(--text-muted);cursor:not-allowed}.agent-detail-bulk-menu-item-hint{font-size:calc(var(--space-sm) + var(--space-xs) * .5);color:var(--text-muted)}.agent-detail-import-btn{min-height:calc(var(--space-lg) + var(--space-md) + var(--space-xs))}.agent-detail-title{display:flex;align-items:center;gap:var(--space-lg)}.agent-detail-actions{display:flex;align-items:center;gap:var(--space-sm)}.agent-detail-tabs{display:flex;gap:var(--space-xs);padding:0 calc(var(--space-lg) + var(--space-xs));border-bottom:1px solid var(--border);background:var(--bg-secondary);flex-shrink:0;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}.agent-detail-tabs::-webkit-scrollbar{display:none}.agent-detail-tab{display:flex;align-items:center;gap:var(--space-xs);padding:calc(var(--space-sm) + var(--space-xs) * .5) var(--space-md);background:none;border:none;border-bottom:calc(var(--space-xs) * .5) solid transparent;color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs) + var(--space-xs) * .25);cursor:pointer;transition:all var(--transition-fast);white-space:nowrap}.agent-detail-tab:hover{color:var(--text);background:var(--card-hover)}.agent-detail-tab.active{color:var(--todo);border-bottom-color:var(--todo)}.agent-detail-tab:focus-visible{outline:none;box-shadow:var(--focus-ring-strong);background:color-mix(in srgb,var(--todo) 12%,transparent);color:var(--text);border-radius:var(--radius-sm)}.agent-detail-content{flex:1;min-height:0;overflow-y:auto;padding:var(--space-xl)}.agent-detail-footer{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-md) var(--space-xl);border-top:1px solid var(--border);background:var(--bg-secondary);font-size:var(--space-md);color:var(--text-muted);flex-shrink:0}.agent-detail-id{font-family:var(--font-mono);cursor:pointer}.agent-detail-id:hover{color:var(--text)}.dashboard-tab{display:flex;flex-direction:column;gap:var(--space-xl)}.dashboard-summary-layout{padding-bottom:var(--space-md)}.dashboard-summary-health-reason{margin-left:var(--space-xs);font-size:calc(var(--space-sm) + var(--space-xs))}.dashboard-summary-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-md)}.budget-warning-banner{display:flex;gap:var(--space-sm);align-items:flex-start;border:1px solid var(--color-warning);background:color-mix(in srgb,var(--color-warning) 12%,transparent);border-radius:var(--radius-md);padding:var(--space-md)}.dashboard-summary-hero__heading{display:flex;align-items:center;gap:var(--space-sm)}.dashboard-summary-hero__heading h3{margin:0;font-size:calc(var(--space-lg) + var(--space-xs) * .5);font-weight:600}.dashboard-summary-hero__meta{display:flex;flex-wrap:wrap;gap:var(--space-md);color:var(--text-muted)}.agent-detail-approval-badge{display:inline-flex;align-items:center;gap:var(--space-xs);color:var(--color-warning)}.dashboard-summary-skills{display:inline-flex;align-items:center;gap:var(--space-sm)}.dashboard-summary-skill-badges{display:inline-flex;flex-wrap:wrap;gap:var(--space-xs)}.dashboard-summary-skill-badge{max-width:calc(var(--space-xl) * 8);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dashboard-summary-skill-badge-btn{cursor:pointer}.dashboard-summary-skill-badge-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.dashboard-summary-skill-badge--selected{border-color:var(--todo);background:color-mix(in srgb,var(--todo) 20%,transparent)}.dashboard-summary-skill-detail{margin-top:var(--space-sm);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface);padding:var(--space-md);display:flex;flex-direction:column;gap:var(--space-sm)}.dashboard-summary-skill-detail-header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}.dashboard-summary-skill-detail-title{font-weight:600;color:var(--text)}.dashboard-summary-skill-detail-loading,.dashboard-summary-skill-detail-empty{display:inline-flex;align-items:center;gap:var(--space-xs);color:var(--text-muted)}.dashboard-summary-skill-detail-error{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-xs);color:var(--color-error)}.dashboard-summary-skill-detail-content{margin:0;padding:var(--space-sm);border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--card);color:var(--text);white-space:pre-wrap;word-break:break-word;max-height:calc(var(--space-2xl) * 6);overflow:auto}.dashboard-summary-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(calc(var(--space-xl) * 6 + var(--space-sm)),1fr));gap:var(--space-md)}.dashboard-summary-grid p{margin:0}.dashboard-summary-label{font-size:calc(var(--space-sm) + var(--space-xs) * .5);color:var(--text-muted)}.dashboard-summary-health-row{display:inline-flex;align-items:center;gap:var(--space-xs)}.dashboard-summary-health-reason{margin-left:var(--space-xs);font-size:var(--space-md)}.runs-list{display:flex;flex-direction:column;gap:var(--space-sm)}.run-item{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:var(--space-sm)}.dashboard-section{background:var(--bg-secondary);border-radius:var(--radius-md);padding:calc(var(--space-lg) + var(--space-xs))}.dashboard-section h3{font-size:calc(var(--space-md) + var(--space-xs) * .5);font-weight:600;margin:0 0 var(--space-lg) 0;color:var(--text-muted);text-transform:uppercase;letter-spacing:calc(var(--space-xs) * .125)}.info-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(calc(var(--space-xl) * 7 + var(--space-sm)),1fr));gap:var(--space-lg)}.info-item{display:flex;flex-direction:column;gap:var(--space-xs)}.info-label{font-size:var(--space-md);color:var(--text-muted)}.info-value{font-size:calc(var(--space-md) + var(--space-xs) * .5);font-weight:500}.inline-badge{display:inline-block;padding:calc(var(--space-xs) * .5) var(--space-sm);border-radius:var(--radius-sm);font-size:var(--space-md);text-transform:capitalize}.stats-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-lg)}.stat-card{background:var(--surface);border-radius:var(--radius-md);padding:var(--space-lg);text-align:center}.stat-value{font-size:calc(var(--space-lg) + var(--space-xs) * .5);font-weight:700;color:var(--todo)}.stat-label{font-size:calc(var(--space-sm) + var(--space-xs) * .5);color:var(--text-muted);margin-top:var(--space-xs)}.current-task{display:flex;align-items:center;gap:var(--space-md)}.task-badge{font-family:var(--font-mono);background:var(--surface);padding:var(--space-sm) var(--space-md);border-radius:var(--radius-sm);font-size:calc(var(--space-md) + var(--space-xs) * .25)}.metadata-json{background:var(--surface);padding:var(--space-md);border-radius:var(--radius-sm);font-size:var(--space-md);overflow-x:auto;margin:0}.logs-tab{display:flex;flex-direction:column;height:100%}.logs-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--space-md);margin-bottom:var(--space-md);border-bottom:1px solid var(--border)}.logs-count{font-size:var(--space-md);color:var(--text-muted)}.streaming-indicator{display:flex;align-items:center;gap:calc(var(--space-xs) + var(--space-sm) * .25);font-size:var(--space-md);color:var(--color-success)}.streaming-dot{width:var(--space-sm);height:var(--space-sm);background:var(--color-success);border-radius:50%;animation:pulse 1.5s infinite}.logs-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:calc(var(--space-2xl) + var(--space-lg));color:var(--text-muted);text-align:center}.logs-empty p{margin:var(--space-sm) 0 0 0}.agent-mail-tab{display:flex;flex-direction:column;gap:var(--space-md)}.agent-mail-tab-header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}.agent-mail-tab-header h3{margin:0;font-size:calc(var(--space-md) + var(--space-xs) * .5)}.agent-mail-tab-error{display:flex;align-items:center;gap:var(--space-xs);color:var(--color-error)}.agent-detail-loading--inline{flex-direction:row;justify-content:flex-start;padding:var(--space-md) 0}.agent-mail-tab .agent-mail-tab-message{width:100%;border:0;background:transparent;text-align:left;color:inherit;cursor:pointer}.agent-mail-tab .agent-mail-tab-message:hover{background:var(--card-hover)}.agent-mail-tab .agent-mail-tab-message:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.agent-mail-tab .agent-mail-tab-message--selected{background:color-mix(in srgb,var(--todo) 12%,transparent)}.agent-mail-tab .agent-mail-tab-detail{display:flex;flex-direction:column;gap:var(--space-md);padding:var(--space-lg);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface)}.agent-mail-tab .agent-mail-tab-back{align-self:flex-start}.agent-mail-tab .agent-mail-tab-detail-meta{display:flex;flex-direction:column;gap:var(--space-sm)}.agent-mail-tab .agent-mail-tab-detail-row{display:flex;flex-wrap:wrap;gap:var(--space-md)}.agent-mail-tab .agent-mail-tab-detail-label{color:var(--text-muted);min-width:calc(var(--space-2xl) * 2)}.agent-mail-tab .agent-mail-tab-reply-context{color:var(--text-muted)}.agent-mail-tab .agent-mail-tab-detail-body{white-space:pre-wrap;word-break:break-word}.runs-tab{display:flex;flex-direction:column;gap:var(--space-md)}.runs-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:calc(var(--space-2xl) + var(--space-lg));color:var(--text-muted);text-align:center}.runs-empty p{margin:var(--space-sm) 0 0 0}.run-card{background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-lg)}.run-card--active{border-color:var(--in-progress);background:color-mix(in srgb,var(--in-progress) 5%,transparent)}.run-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-sm)}.run-live-indicator{display:flex;align-items:center;gap:calc(var(--space-xs) + var(--space-sm) * .25);font-weight:600;color:var(--in-progress)}.live-dot{width:var(--space-sm);height:var(--space-sm);background:var(--in-progress);border-radius:50%;animation:pulse 1.5s infinite}.run-id{font-family:var(--font-mono);font-size:calc(var(--space-md) + var(--space-xs) * .25);color:var(--text-muted)}.run-status{display:flex;align-items:center;gap:calc(var(--space-xs) + var(--space-sm) * .25);font-size:calc(var(--space-md) + var(--space-xs) * .25);text-transform:capitalize}.run-status.active{color:var(--in-progress)}.run-status.completed{color:var(--color-success)}.run-status.failed{color:var(--color-error)}.run-status.terminated{color:var(--text-muted)}.run-details{display:flex;gap:var(--space-sm);font-size:var(--space-md);color:var(--text-muted)}.run-logs-container{padding:var(--space-md);background:var(--bg-secondary);border-top:1px solid var(--border);border-bottom:1px solid var(--border)}.run-details-loading-state{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) 0}.run-output-sections{margin-bottom:var(--space-md)}.run-output-section{margin-bottom:var(--space-sm)}.run-output-label{margin-bottom:var(--space-xs);color:var(--text-muted);font-size:calc(var(--space-sm) + var(--space-xs));font-weight:600;letter-spacing:calc(var(--space-xs) * .1);text-transform:uppercase}.run-output-label--error{color:var(--color-error)}.run-output-panel{margin:0;max-height:calc(var(--space-2xl) * 6.25);overflow:auto;border-radius:var(--radius-sm);padding:var(--space-sm) var(--space-md);background:var(--surface);border:1px solid var(--border);white-space:pre-wrap;word-break:break-word;font-size:calc(var(--space-sm) + var(--space-xs));line-height:1.5}.run-output-panel--error{color:var(--color-error);border-color:color-mix(in srgb,var(--color-error) 35%,var(--border));background:color-mix(in srgb,var(--color-error) 10%,transparent)}.run-context-grid{display:flex;flex-wrap:wrap;gap:var(--space-xs) var(--space-md);font-size:calc(var(--space-sm) + var(--space-xs))}.run-context-item{line-height:1.5}.run-output-empty{padding:var(--space-sm) 0;font-style:italic;font-size:calc(var(--space-sm) + var(--space-xs))}.prompt-size-summary{display:flex;align-items:center;gap:var(--space-sm)}.prompt-size-sparkline{width:calc(var(--space-2xl) * 2);height:calc(var(--space-xl) + var(--space-md));border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface)}.prompt-size-sparkline-grid{fill:none;stroke:var(--text-muted);stroke-width:1}.prompt-size-sparkline-line{fill:none;stroke:var(--accent);stroke-width:2}.prompt-size-values{font-family:var(--font-mono);font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.run-agent-logs-section{margin-top:var(--space-xs);padding-top:var(--space-sm);border-top:1px solid var(--border)}.agent-tasks-list{display:flex;flex-direction:column;gap:var(--space-sm)}.agent-task-item{display:flex;flex-direction:column;gap:calc(var(--space-xs) + var(--space-sm) * .25);padding:var(--space-md) calc(var(--space-md) + var(--space-xs) * .5);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-secondary);text-decoration:none;transition:background var(--transition-fast),border-color var(--transition-fast)}.agent-task-item:hover{background:var(--card-hover);border-color:var(--text-dim)}.agent-task-row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm)}.agent-task-id{font-family:var(--font-mono);font-size:var(--space-md);font-weight:600;color:var(--todo)}.agent-task-title{font-size:calc(var(--space-md) + var(--space-xs) * .5);font-weight:500;color:var(--text);line-height:1.4}.agent-task-status{font-size:var(--space-md);color:var(--text-muted)}.agent-task-column{display:inline-flex;align-items:center;padding:calc(var(--space-xs) * .5) var(--space-sm);border-radius:var(--radius-pill);font-size:calc(var(--space-sm) + var(--space-xs) * .5);font-weight:700;text-transform:uppercase;letter-spacing:calc(var(--space-xs) * .1)}.agent-task-column.column-triage{color:var(--triage);background:color-mix(in srgb,var(--triage) 18%,transparent)}.agent-task-column.column-todo{color:var(--todo);background:color-mix(in srgb,var(--todo) 18%,transparent)}.agent-task-column.column-in-progress{color:var(--in-progress);background:color-mix(in srgb,var(--in-progress) 18%,transparent)}.agent-task-column.column-in-review{color:var(--in-review);background:color-mix(in srgb,var(--in-review) 18%,transparent)}.agent-task-column.column-done{color:var(--done);background:color-mix(in srgb,var(--done) 18%,transparent)}.agent-task-column.column-archived{color:var(--text-muted);background:color-mix(in srgb,var(--text-muted) 18%,transparent)}.agent-tasks-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-sm);padding:calc(var(--space-2xl) + var(--space-lg));color:var(--text-muted);text-align:center}.agent-tasks-empty p{margin:0}.config-tab{display:flex;flex-direction:column;gap:var(--space-xl)}.config-section{background:var(--bg-secondary);border-radius:var(--radius-md);padding:calc(var(--space-md) + var(--space-sm))}.config-section h3{font-size:calc(var(--space-md) + var(--space-xs));font-weight:600;margin:0 0 var(--space-sm) 0}.config-section--danger{border:1px solid color-mix(in srgb,var(--color-error) 40%,transparent)}.config-danger-note{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted)}.agent-content-toolbar{display:flex;align-items:center;gap:var(--space-md);padding:var(--space-sm) var(--space-lg);border-bottom:1px solid var(--border);background:var(--surface);flex-shrink:0}.agent-content-mode-toggle{display:flex;align-items:center;gap:var(--space-xs)}.agent-content-mode-toggle .btn{display:inline-flex;align-items:center;gap:calc(var(--space-xs) + var(--space-sm) * .25)}.agent-content-preview{overflow-y:auto;padding:var(--space-lg);min-height:150px}.agent-content-placeholder{color:var(--text-muted);text-align:center;padding:var(--space-xl);min-height:150px;display:flex;align-items:center;justify-content:center}.config-description{font-size:calc(var(--space-md) + var(--space-xs) * .5);color:var(--text-muted);margin:0 0 calc(var(--space-md) + var(--space-sm)) 0}.config-actions-row{display:flex;align-items:center;gap:var(--space-sm);margin-bottom:var(--space-md)}.config-fields{display:flex;flex-direction:column;gap:var(--space-lg)}.config-field{display:flex;flex-direction:column;gap:calc(var(--space-xs) + var(--space-sm) * .25)}.config-field label{font-size:calc(var(--space-md) + var(--space-xs) * .25);font-weight:500}.agent-avatar-editor{display:flex;align-items:center;gap:var(--space-md)}.agent-avatar-editor-preview{background:var(--card)}.agent-avatar-editor-actions{display:flex;align-items:center;gap:var(--space-sm);flex-wrap:wrap}.config-runtime-tabs{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-sm);margin-bottom:var(--space-md)}.config-runtime-tab{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--card);color:var(--text-muted);padding:var(--space-sm) var(--space-md);font-size:calc(var(--space-sm) + var(--space-xs));font-weight:600;cursor:pointer;transition:border-color var(--transition-fast),background var(--transition-fast),color var(--transition-fast),box-shadow var(--transition-fast)}.config-runtime-tab:hover{border-color:var(--todo);color:var(--text);background:var(--card-hover)}.config-runtime-tab:focus-visible{outline:none;border-color:var(--todo);box-shadow:var(--focus-ring-strong)}.config-runtime-tab.active{border-color:var(--todo);color:var(--text);background:color-mix(in srgb,var(--todo) 12%,transparent)}.config-hint{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted);font-style:italic}.config-error{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--color-error)}.input--error{border-color:var(--color-error)!important}.config-actions{display:flex;align-items:center;gap:var(--space-md);margin-top:calc(var(--space-md) + var(--space-sm));padding-top:var(--space-lg);border-top:1px solid var(--border)}.config-saved-indicator{display:flex;align-items:center;gap:calc(var(--space-sm) - var(--space-xs) * .5);font-size:calc(var(--space-md) + var(--space-xs) * .25);color:var(--color-success)}.config-saved-indicator--error{color:var(--color-error)}.heartbeat-procedure-actions{margin-top:var(--space-sm)}.heartbeat-procedure-viewer{margin-top:var(--space-lg)}.heartbeat-procedure-status{display:inline-flex;align-items:center;gap:var(--space-xs);margin-left:auto}.heartbeat-procedure-status--warning{color:var(--color-warning)}.rating-summary-card{background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--radius-md);padding:calc(var(--space-md) + var(--space-sm));display:flex;flex-direction:column;gap:var(--space-md)}.rating-score-display{display:flex;align-items:center;gap:var(--space-md)}.rating-average{font-size:var(--space-2xl);font-weight:700;line-height:1}.rating-stats{display:flex;align-items:center;gap:var(--space-md)}.rating-count{font-size:calc(var(--space-md) + var(--space-xs) * .5);color:var(--text-muted)}.rating-trend-badge{font-size:var(--space-md);padding:var(--space-xs) calc(var(--space-md) - var(--space-xs) * .5);border-radius:var(--radius-lg);font-weight:500}.trend-improving{background:color-mix(in srgb,var(--color-success) 15%,transparent);color:var(--color-success)}.trend-declining{background:color-mix(in srgb,var(--color-error) 15%,transparent);color:var(--color-error)}.trend-stable{background:color-mix(in srgb,var(--color-warning) 15%,transparent);color:var(--color-warning)}.trend-insufficient{background:var(--bg-tertiary);color:var(--text-muted)}.category-breakdown{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-lg)}.category-breakdown h4{margin:0 0 var(--space-md) 0;font-size:calc(var(--space-md) + var(--space-xs) * .25);font-weight:600}.category-breakdown .category-item{display:flex;justify-content:space-between;align-items:center;padding:var(--space-sm) 0;border-bottom:1px solid var(--border)}.category-breakdown .category-item:last-child{border-bottom:none}.category-name{text-transform:capitalize;font-size:calc(var(--space-md) + var(--space-xs) * .25)}.category-score{font-weight:600;font-size:calc(var(--space-md) + var(--space-xs) * .25)}.add-rating-form{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-md)}.add-rating-form h4{margin:0;font-size:calc(var(--space-md) + var(--space-xs) * .25);font-weight:600}.star-selector{display:flex;gap:var(--space-xs)}.star-btn{background:none;border:none;padding:var(--space-xs);cursor:pointer;border-radius:var(--radius-sm);color:var(--text-muted);transition:background-color var(--transition-fast),color var(--transition-fast)}.star-btn:hover{background:var(--card-hover)}.star-btn:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.rating-stars{display:inline-flex;gap:var(--space-xs)}.rating-stars .star-filled{color:var(--color-warning)}.rating-stars .star-empty{color:var(--text-muted)}.add-rating-form .add-rating-category-select,.add-rating-form .add-rating-comment-input{width:100%}.add-rating-form .add-rating-comment-input{resize:vertical;min-height:calc(var(--space-xl) + var(--space-2xl))}.rating-history{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-lg);max-height:calc(var(--space-xl) * 12 + var(--space-md));overflow-y:auto}.rating-history h4{margin:0 0 var(--space-md) 0;font-size:calc(var(--space-md) + var(--space-xs) * .25);font-weight:600}.rating-history .no-ratings{color:var(--text-muted);font-size:calc(var(--space-md) + var(--space-xs) * .25);text-align:center;padding:var(--space-lg)}.rating-history-item{padding:var(--space-md) 0;border-bottom:1px solid var(--border)}.rating-history-item:last-child{border-bottom:none}.rating-item-header{display:flex;align-items:center;gap:var(--space-sm);flex-wrap:wrap}.rating-category-badge{font-size:calc(var(--space-sm) + var(--space-xs) * .5);padding:calc(var(--space-xs) * .5) var(--space-sm);background:var(--card-hover);border-radius:var(--radius-pill);text-transform:capitalize}.rating-time{font-size:calc(var(--space-sm) + var(--space-xs) * .5);color:var(--text-muted);margin-left:auto}.rating-delete-btn{background:none;border:none;padding:var(--space-xs);cursor:pointer;color:var(--text-muted);border-radius:var(--radius-sm);transition:color var(--transition-fast),background-color var(--transition-fast)}.rating-delete-btn:hover{color:var(--color-error);background:color-mix(in srgb,var(--color-error) 10%,transparent)}.rating-comment{margin:var(--space-sm) 0 0 0;font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted);line-height:1.4}.runs-loading-row{display:flex;align-items:center;justify-content:center;gap:var(--space-sm);padding:var(--space-xl)}.runs-toolbar{padding:var(--space-sm) var(--space-lg);border-bottom:1px solid var(--border)}.runs-toolbar--between{display:flex;justify-content:space-between;align-items:center}.runs-toolbar-meta{font-size:calc(var(--space-sm) + var(--space-xs));color:var(--text-muted)}.run-card--clickable{cursor:pointer}.run-card--clickable:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.run-header-group{display:flex;align-items:center;gap:var(--space-sm)}.run-badge--compact{font-size:calc(var(--space-sm) + var(--space-xs) * .5);padding:calc(var(--space-xs) * .25) calc(var(--space-sm) * .75)}.run-output-summary{cursor:pointer;user-select:none}.run-live-indicator--with-margin{margin-left:var(--space-sm)}.detail-section-body--loading{display:flex;align-items:center;gap:var(--space-sm)}.agent-empty--padded{padding:var(--space-xl)}.logs-fallback-label{font-size:calc(var(--space-sm) + var(--space-xs))}.config-textarea-mono{font-family:var(--font-mono);font-size:calc(var(--space-md) + var(--space-xs) * .25);resize:vertical}.config-textarea-top-spacing{margin-top:var(--space-sm)}.config-hint--block-spacing{margin-bottom:var(--space-md)}.config-hint--block{display:block;margin-bottom:var(--space-sm)}.config-hint--top-spacing{margin-top:var(--space-sm)}.config-hint--inline-loader{display:inline-flex;gap:var(--space-xs);margin-top:var(--space-sm)}.config-inline-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--space-sm)}.config-hint--inline-tight{display:flex;align-items:center;gap:var(--space-xs)}.config-hint--warning{color:var(--color-warning)}.agent-heartbeat-auto-claim-card{background:color-mix(in srgb,var(--surface) 60%,transparent);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md)}.agent-heartbeat-preset-row{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-md);margin-bottom:var(--space-sm)}.agent-heartbeat-preset-label{display:block;color:var(--text);font-size:calc(var(--space-sm) + var(--space-xs));font-weight:600;margin-bottom:calc(var(--space-xs) * .5)}.agent-heartbeat-preset-btn{min-height:calc(var(--space-xl) + var(--space-md));flex-shrink:0}@media(max-width:768px){.agent-heartbeat-preset-row{flex-direction:column;align-items:stretch}.agent-heartbeat-preset-btn{width:100%;min-height:calc(var(--space-xl) + var(--space-md))}.config-runtime-tabs{grid-template-columns:1fr}.agent-detail-overlay{padding:0;align-items:stretch}.agent-detail-modal{min-width:0!important;min-height:0!important;width:100vw!important;height:100dvh!important;max-width:100vw!important;max-height:100dvh;margin:0;border-radius:0;border:none;resize:none}.agent-detail-header{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;column-gap:var(--space-xs);row-gap:0;padding:var(--space-sm) var(--space-md);padding-top:max(var(--space-sm),env(safe-area-inset-top,0))}.agent-detail-identity{grid-column:1;grid-row:1;flex:1 1 auto;min-width:0;gap:var(--space-sm)}.agent-detail-icon{width:calc(var(--space-lg) * 2);height:calc(var(--space-lg) * 2);flex-shrink:0}.agent-detail-icon svg{width:calc(var(--space-sm) + var(--space-xs) * 2);height:calc(var(--space-sm) + var(--space-xs) * 2)}.agent-detail-info h2{font-size:calc(var(--space-md) + var(--space-xs) * .75);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.agent-detail-badges{flex-wrap:wrap}.agent-detail-header-actions{grid-column:2;grid-row:1;flex:0 0 auto;justify-content:flex-end;gap:calc(var(--space-xs) * .5)}.agent-detail-controls{flex:0 0 auto;gap:calc(var(--space-xs) * .5)}.agent-detail-controls .btn--compact{padding:calc(var(--space-sm) - var(--space-xs) * .5) calc(var(--space-md) - var(--space-xs) * .5);font-size:var(--space-md);min-height:calc(var(--space-lg) + var(--space-md) + var(--space-xs))}.agent-detail-controls .agent-detail-mobile-icon-control{min-width:calc(var(--space-lg) + var(--space-md) + var(--space-xs));padding-left:calc(var(--space-sm) - var(--space-xs) * .5);padding-right:calc(var(--space-sm) - var(--space-xs) * .5)}.agent-detail-controls .agent-detail-mobile-icon-control .agent-detail-control-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.agent-detail-controls .btn--compact svg{width:calc(var(--space-md) + var(--space-xs) * .5);height:calc(var(--space-md) + var(--space-xs) * .5)}.agent-detail-utility-actions{flex-shrink:0;margin-left:0}.agent-detail-bulk-menu-popover{right:0}.agent-detail-utility-actions .btn-icon{min-height:calc(var(--space-lg) + var(--space-md) + var(--space-xs));min-width:calc(var(--space-lg) + var(--space-md) + var(--space-xs))}.agent-detail-import-btn{min-width:calc(var(--space-xl) * 3 + var(--space-xs))}.agent-detail-title{flex:1 1 auto;min-width:0;gap:var(--space-md)}.agent-detail-actions{flex:1 1 100%;flex-wrap:wrap;gap:calc(var(--space-xs) + var(--space-sm) * .25)}.agent-detail-actions .btn{padding:calc(var(--space-sm) - var(--space-xs) * .5) calc(var(--space-md) - var(--space-xs) * .5);font-size:calc(var(--space-md) + var(--space-xs) * .25);min-height:calc(var(--space-lg) + var(--space-md) + var(--space-xs))}.agent-detail-actions .btn svg{width:calc(var(--space-sm) + var(--space-xs) * 1.5);height:calc(var(--space-sm) + var(--space-xs) * 1.5)}.agent-detail-actions .btn-icon{min-height:calc(var(--space-lg) + var(--space-md) + var(--space-xs));min-width:calc(var(--space-lg) + var(--space-md) + var(--space-xs))}.agent-detail-tabs{padding:0;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}.agent-detail-tabs::-webkit-scrollbar{display:none}.agent-detail-tab{padding:var(--space-md) calc(var(--space-md) + var(--space-xs) * .5);font-size:calc(var(--space-md) + var(--space-xs) * .25);white-space:nowrap;min-height:calc(var(--space-lg) + var(--space-md) + var(--space-xs))}.agent-detail-content{padding:var(--space-lg);-webkit-overflow-scrolling:touch;overscroll-behavior:contain}.agent-detail-footer{flex-wrap:wrap;gap:var(--space-sm);padding:var(--space-sm) var(--space-lg);padding-bottom:max(var(--space-sm),env(safe-area-inset-bottom,0));font-size:calc(var(--space-sm) + var(--space-xs) * .75)}.agent-detail-id{max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dashboard-tab{gap:var(--space-lg)}.dashboard-summary-skills,.dashboard-summary-skill-detail-header{flex-direction:column;align-items:flex-start}.dashboard-section{padding:var(--space-lg)}.info-grid{grid-template-columns:repeat(2,1fr);gap:var(--space-md)}.stats-grid{grid-template-columns:repeat(3,1fr);gap:var(--space-md)}.stat-value{font-size:calc(var(--space-lg) + var(--space-xs) * .5)}.logs-empty{padding:var(--space-2xl) var(--space-lg)}.agent-mail-tab-header{flex-direction:column;align-items:flex-start}.agent-mail-tab .mailbox-agent-subtabs{width:100%}.agent-mail-tab .mailbox-agent-subtab{flex:1}.agent-mail-tab .agent-mail-tab-detail{width:100%;padding:var(--space-md)}.agent-mail-tab .agent-mail-tab-back{min-height:calc(var(--space-lg) * 2 + var(--space-xs))}.run-card{padding:var(--space-md)}.run-header{flex-wrap:wrap;gap:calc(var(--space-xs) + var(--space-sm) * .25)}.run-details{flex-wrap:wrap}.run-logs-container{padding:var(--space-sm)}.run-output-panel{max-height:calc(var(--space-2xl) * 5)}.run-context-grid{flex-direction:column;gap:var(--space-xs)}.run-details .text-muted{min-width:0;overflow-wrap:anywhere}.config-tab{gap:var(--space-lg)}.config-section{padding:var(--space-lg)}.config-section .input,.config-section .select,.config-section textarea{font-size:calc(var(--space-md) + var(--space-xs));min-height:calc(var(--space-lg) + var(--space-md) + var(--space-xs))}.config-actions{flex-direction:column;align-items:stretch;gap:var(--space-sm)}.config-actions .btn{width:100%;justify-content:center}.heartbeat-procedure-status{margin-left:0}}@media(max-width:480px){.info-grid,.stats-grid{grid-template-columns:1fr}.agent-detail-actions{flex-direction:column;width:100%}.agent-detail-actions .btn{width:100%;justify-content:center}.agent-detail-actions .btn-icon{align-self:flex-end}.agent-detail-footer .divider,.agent-detail-footer .text-muted,.agent-detail-footer .link{display:none}}@media(max-width:768px){.agent-avatar-editor{flex-direction:column;align-items:flex-start}.agent-avatar-editor-actions{width:100%}.agent-avatar-editor-actions .btn{min-height:calc(var(--space-lg) * 2 + var(--space-xs))}.agent-dialog-overlay{padding:0;align-items:stretch}.agent-dialog{width:100vw!important;height:100dvh;max-width:100%!important;max-height:100dvh;border-radius:0;border:none}.agent-dialog-header{padding:max(var(--space-md),env(safe-area-inset-top,0px)) var(--space-lg) var(--space-md) var(--space-lg);flex-shrink:0}.agent-dialog-body{padding:var(--space-lg);-webkit-overflow-scrolling:touch}.agent-dialog-footer{padding:var(--space-md) var(--space-lg);padding-bottom:max(var(--space-md),env(safe-area-inset-bottom,0px));flex-wrap:wrap;gap:var(--space-sm)}.agent-dialog-field .input,.agent-dialog-field .select,.agent-dialog-field textarea{font-size:calc(var(--space-md) + var(--space-xs));min-height:calc(var(--space-lg) * 2 + var(--space-xs))}.agent-dialog-summary-row{flex-direction:column;gap:calc(var(--space-xs) * .5)}.agent-dialog-summary-row>span:first-child,.agent-dialog-summary-row-label{width:auto}.agent-dialog-steps{padding:var(--space-sm) var(--space-lg)}.agent-dialog-step{flex:1;width:auto;height:calc(var(--space-xs) - var(--space-xs) * .25)}.agent-dialog-tabs{grid-template-columns:1fr;gap:calc(var(--space-sm) - var(--space-xs) * .5);margin-bottom:var(--space-md)}.agent-dialog-tab{min-height:calc(var(--space-lg) * 2 + var(--space-xs));text-align:left}.agent-import-file-upload{flex-direction:column;align-items:stretch;gap:var(--space-sm)}.agent-import-textarea{font-size:calc(var(--space-md) + var(--space-xs));min-height:calc(var(--space-xl) * 4 + var(--space-xs))}.agent-import-agent-list{max-height:calc(100dvh - (var(--space-xl) * 10 + var(--space-lg)))}.agent-import-result-stats{flex-direction:column;gap:var(--space-sm);align-items:center}.agent-import-browse-list{max-height:calc(100dvh - (var(--space-xl) * 10 + var(--space-lg)))}.agent-import-skill-list{max-height:calc(100dvh - (var(--space-xl) * 15 + var(--space-md)))}}@media(max-width:480px){.agent-dialog-body{padding:var(--space-md)}.agent-dialog-footer{flex-direction:column}.agent-dialog-footer .btn{width:100%;justify-content:center}}.agent-permission-inherit-banner{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm);padding:var(--space-sm);border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface);margin-bottom:var(--space-sm)}.reflections-tab{padding:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-lg)}.reflections-header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-md)}.reflections-header h3{display:flex;align-items:center;gap:var(--space-sm);font-size:1rem;font-weight:600;color:var(--text)}.reflections-stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:var(--space-md)}.reflections-stat-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md);text-align:center}.reflections-stat-card .stat-value{display:flex;align-items:center;justify-content:center;gap:var(--space-sm);font-size:1.5rem;font-weight:700;color:var(--text);margin-bottom:var(--space-xs)}.reflections-stat-card .stat-label{font-size:.75rem;color:var(--text-muted);text-transform:uppercase;letter-spacing:.05em}.reflections-no-data{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-sm);padding:var(--space-xl);color:var(--text-muted);text-align:center}.reflections-list{display:flex;flex-direction:column;gap:var(--space-md)}.reflections-loading-indicator{display:flex;align-items:center;justify-content:center;gap:var(--space-sm);padding:var(--space-lg)}.reflections-ratings-section{display:flex;flex-direction:column;gap:var(--space-md)}.reflections-ratings-section>h4,.reflections-list h4{font-size:.875rem;font-weight:600;color:var(--text);margin-bottom:var(--space-xs)}.reflection-cards{display:flex;flex-direction:column;gap:var(--space-sm)}.reflection-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-md);cursor:pointer;transition:border-color .15s,background-color .15s}.reflection-card:hover{border-color:var(--border-active);background:var(--card-hover)}.reflection-card:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.reflection-card--expanded{border-color:var(--color-primary)}.reflection-card-header{display:flex;align-items:center;gap:var(--space-sm);margin-bottom:var(--space-sm)}.reflection-trigger-badge{font-size:.7rem;font-weight:600;padding:2px 6px;border-radius:var(--radius-sm);text-transform:uppercase;letter-spacing:.05em}.reflection-trigger-periodic{background:color-mix(in srgb,var(--color-info) 15%,transparent);color:var(--color-info)}.reflection-trigger-post-task{background:color-mix(in srgb,var(--color-success) 15%,transparent);color:var(--color-success)}.reflection-trigger-manual{background:color-mix(in srgb,var(--color-primary) 15%,transparent);color:var(--color-primary)}.reflection-trigger-user-requested{background:color-mix(in srgb,var(--color-warning) 15%,transparent);color:var(--color-warning)}.reflection-timestamp{font-size:.75rem;color:var(--text-muted);flex:1}.reflection-chevron{color:var(--text-muted)}.reflection-summary{font-size:.875rem;color:var(--text);line-height:1.5}.reflection-details{margin-top:var(--space-md);padding-top:var(--space-md);border-top:1px solid var(--border);display:flex;flex-direction:column;gap:var(--space-md)}.reflection-insights h5,.reflection-suggestions h5{display:flex;align-items:center;gap:var(--space-xs);font-size:.8rem;font-weight:600;color:var(--text);margin-bottom:var(--space-xs)}.reflection-insights ul,.reflection-suggestions ul{list-style:none;display:flex;flex-direction:column;gap:var(--space-xs)}.reflection-insights li,.reflection-suggestions li{font-size:.8rem;color:var(--text-muted);padding-left:var(--space-md);position:relative}.reflection-insights li:before{content:"•";position:absolute;left:4px;color:var(--color-success)}.reflection-suggestions li:before{content:"→";position:absolute;left:0;color:var(--color-primary)}.reflection-metrics{background:var(--bg);border-radius:var(--radius-sm);padding:var(--space-sm)}.reflection-metrics h5{font-size:.75rem;font-weight:600;color:var(--text-muted);margin-bottom:var(--space-xs)}.metrics-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:var(--space-sm)}.metric{display:flex;flex-direction:column;gap:2px}.metric-label{font-size:.7rem;color:var(--text-muted)}.metric-value{font-size:.875rem;font-weight:600;color:var(--text)}.reflection-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-sm);padding:var(--space-2xl);color:var(--text-muted);text-align:center}.reflection-empty p{font-size:.875rem}@media(max-width:768px){.reflections-header{flex-wrap:wrap;align-items:flex-start}.reflections-header .btn{width:100%;justify-content:center}}.budget-progress-container{margin-top:var(--space-xs)}.budget-progress-bar{width:100%;height:var(--space-sm);background:var(--surface);border-radius:var(--radius-sm);overflow:hidden;margin-top:var(--space-xs)}.budget-progress-bar__fill{height:100%;border-radius:var(--radius-sm);transition:width var(--transition-slow),background-color var(--transition-slow)}.budget-progress-bar__fill--green{background:var(--color-success)}.budget-progress-bar__fill--amber{background:var(--color-warning)}.budget-progress-bar__fill--red{background:var(--color-error)}.budget-progress-label{font-size:.75rem;color:var(--text-muted);margin-top:var(--space-xs);display:block}.budget-badge{display:inline-flex;align-items:center;gap:var(--space-xs);padding:calc(var(--space-xs) / 2) var(--space-sm);border-radius:var(--radius-pill);font-size:.75rem;font-weight:500}.budget-warning-banner{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);border-radius:var(--radius-sm);background:var(--state-error-bg, color-mix(in srgb, var(--color-error) 15%, transparent));color:var(--state-error-text);border:1px solid var(--state-error-border);font-size:.875rem;margin-bottom:var(--space-md)}.btn-reset-budget{margin-top:var(--space-sm)}
|