@xpufx/paseo-top 0.4.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/LICENSE +21 -0
- package/README.md +114 -0
- package/client/pill-labels.ts +480 -0
- package/client/pill.tsx +2461 -0
- package/client/resources-query.ts +68 -0
- package/client/settings-ui.tsx +50 -0
- package/client/surface.tsx +364 -0
- package/client/telemetry-copy.ts +105 -0
- package/client/telemetry.tsx +486 -0
- package/client/turn-counter.ts +151 -0
- package/client/turn-panel.tsx +182 -0
- package/client/vendor/paseo-plugin-helper/command-center.ts +43 -0
- package/client/vendor/paseo-plugin-helper/components/AboutSection.tsx +493 -0
- package/client/vendor/paseo-plugin-helper/components/AttentionBeacon.tsx +250 -0
- package/client/vendor/paseo-plugin-helper/components/Badge.tsx +156 -0
- package/client/vendor/paseo-plugin-helper/components/Button.tsx +178 -0
- package/client/vendor/paseo-plugin-helper/components/Card.tsx +225 -0
- package/client/vendor/paseo-plugin-helper/components/CodeBlock.tsx +196 -0
- package/client/vendor/paseo-plugin-helper/components/Collapsible.tsx +277 -0
- package/client/vendor/paseo-plugin-helper/components/CommandBox.tsx +172 -0
- package/client/vendor/paseo-plugin-helper/components/CopyButton.tsx +180 -0
- package/client/vendor/paseo-plugin-helper/components/DataTable.tsx +200 -0
- package/client/vendor/paseo-plugin-helper/components/EmptyState.tsx +97 -0
- package/client/vendor/paseo-plugin-helper/components/HighlightedText.tsx +70 -0
- package/client/vendor/paseo-plugin-helper/components/InlineButton.tsx +73 -0
- package/client/vendor/paseo-plugin-helper/components/KeyValue.tsx +446 -0
- package/client/vendor/paseo-plugin-helper/components/MetricGauge.tsx +247 -0
- package/client/vendor/paseo-plugin-helper/components/ProgressBar.tsx +117 -0
- package/client/vendor/paseo-plugin-helper/components/Responsive.tsx +53 -0
- package/client/vendor/paseo-plugin-helper/components/SearchInput.tsx +118 -0
- package/client/vendor/paseo-plugin-helper/components/SectionHeader.tsx +80 -0
- package/client/vendor/paseo-plugin-helper/components/Select.tsx +215 -0
- package/client/vendor/paseo-plugin-helper/components/StatusDot.tsx +80 -0
- package/client/vendor/paseo-plugin-helper/components/Tabs.tsx +319 -0
- package/client/vendor/paseo-plugin-helper/components/TextInput.tsx +150 -0
- package/client/vendor/paseo-plugin-helper/components/Toggle.tsx +163 -0
- package/client/vendor/paseo-plugin-helper/components/TruncatedText.tsx +157 -0
- package/client/vendor/paseo-plugin-helper/components/index.ts +25 -0
- package/client/vendor/paseo-plugin-helper/custom-pills.tsx +224 -0
- package/client/vendor/paseo-plugin-helper/forge-icon.tsx +79 -0
- package/client/vendor/paseo-plugin-helper/host.ts +277 -0
- package/client/vendor/paseo-plugin-helper/icon.tsx +39 -0
- package/client/vendor/paseo-plugin-helper/index.ts +28 -0
- package/client/vendor/paseo-plugin-helper/layout/ActionBar.tsx +49 -0
- package/client/vendor/paseo-plugin-helper/layout/FormRow.tsx +103 -0
- package/client/vendor/paseo-plugin-helper/layout/Grid.tsx +65 -0
- package/client/vendor/paseo-plugin-helper/layout/ModalBody.tsx +378 -0
- package/client/vendor/paseo-plugin-helper/layout/ModalContent.tsx +49 -0
- package/client/vendor/paseo-plugin-helper/layout/Row.tsx +39 -0
- package/client/vendor/paseo-plugin-helper/layout/Stack.tsx +39 -0
- package/client/vendor/paseo-plugin-helper/layout/index.ts +7 -0
- package/client/vendor/paseo-plugin-helper/panel.tsx +81 -0
- package/client/vendor/paseo-plugin-helper/pill.tsx +884 -0
- package/client/vendor/paseo-plugin-helper/query-refresh.ts +79 -0
- package/client/vendor/paseo-plugin-helper/query.ts +66 -0
- package/client/vendor/paseo-plugin-helper/settings-screen.tsx +372 -0
- package/client/vendor/paseo-plugin-helper/settings.ts +181 -0
- package/client/vendor/paseo-plugin-helper/shared-settings.ts +46 -0
- package/client/vendor/paseo-plugin-helper/snapshot.ts +68 -0
- package/client/vendor/paseo-plugin-helper/surface.tsx +80 -0
- package/client/vendor/paseo-plugin-helper/theme/color-utils.ts +118 -0
- package/client/vendor/paseo-plugin-helper/theme/flair.ts +76 -0
- package/client/vendor/paseo-plugin-helper/theme/host-variables.ts +121 -0
- package/client/vendor/paseo-plugin-helper/theme/index.ts +7 -0
- package/client/vendor/paseo-plugin-helper/theme/provider.tsx +214 -0
- package/client/vendor/paseo-plugin-helper/theme/responsive.ts +213 -0
- package/client/vendor/paseo-plugin-helper/theme/tokens.ts +161 -0
- package/client/vendor/paseo-plugin-helper/theme/useResponsive.ts +57 -0
- package/client/vendor/paseo-plugin-helper/utils/clipboard.ts +149 -0
- package/client/vendor/paseo-plugin-helper/utils/haptics.ts +34 -0
- package/examples/pills/battery.jsonc +23 -0
- package/examples/pills/disk-usage.jsonc +18 -0
- package/examples/pills/docker-containers.jsonc +22 -0
- package/examples/pills/git-dirty.jsonc +22 -0
- package/examples/pills/gpu-nvidia.jsonc +22 -0
- package/package.json +37 -0
- package/paseo-plugin.json +4 -0
- package/server/resources.ts +784 -0
- package/server/vendor/paseo-plugin-helper/agent.ts +85 -0
- package/server/vendor/paseo-plugin-helper/custom-pills.ts +344 -0
- package/server/vendor/paseo-plugin-helper/index.ts +18 -0
- package/server/vendor/paseo-plugin-helper/jsonc.ts +78 -0
- package/server/vendor/paseo-plugin-helper/logger.ts +210 -0
- package/server/vendor/paseo-plugin-helper/mcp-config.ts +367 -0
- package/server/vendor/paseo-plugin-helper/mcp-injection.ts +85 -0
- package/server/vendor/paseo-plugin-helper/network.ts +91 -0
- package/server/vendor/paseo-plugin-helper/plugins.ts +160 -0
- package/server/vendor/paseo-plugin-helper/process.ts +186 -0
- package/server/vendor/paseo-plugin-helper/redact.ts +86 -0
- package/server/vendor/paseo-plugin-helper/rpc-guard.ts +77 -0
- package/server/vendor/paseo-plugin-helper/settings.ts +97 -0
- package/server/vendor/paseo-plugin-helper/shared-settings.ts +243 -0
- package/server/vendor/paseo-plugin-helper/storage.ts +244 -0
- package/server/vendor/paseo-plugin-helper/system.ts +128 -0
- package/server/vendor/paseo-plugin-helper/task.ts +116 -0
- package/server/vendor/paseo-plugin-helper/version.ts +153 -0
- package/server/vendor/paseo-plugin-helper/workspace-beacon.ts +418 -0
- package/shared/resources.ts +686 -0
- package/shared/vendor/paseo-plugin-helper/README.md +11 -0
- package/shared/vendor/paseo-plugin-helper/async.ts +35 -0
- package/shared/vendor/paseo-plugin-helper/custom-pills.ts +169 -0
- package/shared/vendor/paseo-plugin-helper/forge.ts +110 -0
- package/shared/vendor/paseo-plugin-helper/formatters.ts +271 -0
- package/shared/vendor/paseo-plugin-helper/highlight.ts +184 -0
- package/shared/vendor/paseo-plugin-helper/index.ts +10 -0
- package/shared/vendor/paseo-plugin-helper/rpc.ts +72 -0
- package/shared/vendor/paseo-plugin-helper/settings.ts +138 -0
- package/shared/vendor/paseo-plugin-helper/suite-settings.ts +17 -0
- package/shared/vendor/paseo-plugin-helper/suppressed.ts +31 -0
- package/shared/vendor/paseo-plugin-helper/types.ts +36 -0
- package/shared/version.ts +2 -0
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineContract,
|
|
3
|
+
defineSettingsContract,
|
|
4
|
+
type RpcOutput,
|
|
5
|
+
type CustomPillState,
|
|
6
|
+
} from "paseo-plugin-helper/shared";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
export type { CustomPillState };
|
|
10
|
+
|
|
11
|
+
export const ResourceFieldSchema = z.enum(["cpu", "memory", "load", "uptime", "branch", "mcp"]);
|
|
12
|
+
export type ResourceField = z.infer<typeof ResourceFieldSchema>;
|
|
13
|
+
|
|
14
|
+
export const McpServerStatusSchema = z.object({
|
|
15
|
+
name: z.string(),
|
|
16
|
+
status: z.enum(["healthy", "degraded", "down", "unknown"]),
|
|
17
|
+
latencyMs: z.number(),
|
|
18
|
+
});
|
|
19
|
+
export type McpServerStatus = z.infer<typeof McpServerStatusSchema>;
|
|
20
|
+
|
|
21
|
+
export interface McpStatusSnapshot {
|
|
22
|
+
updatedAt: string;
|
|
23
|
+
total: number;
|
|
24
|
+
healthy: number;
|
|
25
|
+
degraded: number;
|
|
26
|
+
down: number;
|
|
27
|
+
servers: McpServerStatus[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const McpResourceStatusSchema = z.object({
|
|
31
|
+
updatedAt: z.string(),
|
|
32
|
+
total: z.number(),
|
|
33
|
+
healthy: z.number(),
|
|
34
|
+
degraded: z.number(),
|
|
35
|
+
down: z.number(),
|
|
36
|
+
isStale: z.boolean(),
|
|
37
|
+
servers: z.array(McpServerStatusSchema),
|
|
38
|
+
});
|
|
39
|
+
export type McpResourceStatus = z.infer<typeof McpResourceStatusSchema>;
|
|
40
|
+
|
|
41
|
+
export const CustomPillStateSchema = z.object({
|
|
42
|
+
id: z.string(),
|
|
43
|
+
sourceFile: z.string().optional(),
|
|
44
|
+
title: z.string(),
|
|
45
|
+
compactTitle: z.string().optional(),
|
|
46
|
+
icon: z.string().optional(),
|
|
47
|
+
compactIcon: z.string().optional(),
|
|
48
|
+
rawValue: z.string(),
|
|
49
|
+
displayValue: z.string(),
|
|
50
|
+
numericValue: z.number().optional(),
|
|
51
|
+
status: z.enum(["neutral", "success", "warning", "danger", "accent", "info"]),
|
|
52
|
+
lastUpdated: z.number(),
|
|
53
|
+
error: z.string().optional(),
|
|
54
|
+
modalTitle: z.string().optional(),
|
|
55
|
+
modalDescription: z.string().optional(),
|
|
56
|
+
modalOutput: z.string().optional(),
|
|
57
|
+
modalError: z.string().optional(),
|
|
58
|
+
modalLastUpdated: z.number().optional(),
|
|
59
|
+
});
|
|
60
|
+
export type CustomPillStateOutput = z.infer<typeof CustomPillStateSchema>;
|
|
61
|
+
|
|
62
|
+
export const getCustomPillsRpc = defineContract({
|
|
63
|
+
name: "top.custom-pills.get",
|
|
64
|
+
description: "Retrieve live states of all discovered custom metric pills",
|
|
65
|
+
input: z.object({}).default({}),
|
|
66
|
+
output: z.object({
|
|
67
|
+
pills: z.array(CustomPillStateSchema),
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
export const runCustomPillModalCommandRpc = defineContract({
|
|
72
|
+
name: "top.custom-pills.modal-command",
|
|
73
|
+
description: "Execute the on-demand drilldown command for a custom metric pill",
|
|
74
|
+
input: z.object({
|
|
75
|
+
pillId: z.string(),
|
|
76
|
+
}),
|
|
77
|
+
output: z.object({
|
|
78
|
+
output: z.string().optional(),
|
|
79
|
+
error: z.string().optional(),
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export const CustomPillDefinitionSchema = z.object({
|
|
84
|
+
id: z.string(),
|
|
85
|
+
title: z.string(),
|
|
86
|
+
sourceFile: z.string().optional(),
|
|
87
|
+
enabled: z.boolean().default(true),
|
|
88
|
+
});
|
|
89
|
+
export type CustomPillDefinition = z.infer<typeof CustomPillDefinitionSchema>;
|
|
90
|
+
|
|
91
|
+
export const listCustomPillsRpc = defineContract({
|
|
92
|
+
name: "top.custom-pills.list",
|
|
93
|
+
description: "List all discovered custom metric pill definitions",
|
|
94
|
+
input: z.object({}).default({}),
|
|
95
|
+
output: z.object({
|
|
96
|
+
pills: z.array(CustomPillDefinitionSchema),
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
export const liveUsageSchema = z.object({
|
|
101
|
+
inputTokens: z.number().optional(),
|
|
102
|
+
cachedInputTokens: z.number().optional(),
|
|
103
|
+
outputTokens: z.number().optional(),
|
|
104
|
+
totalCostUsd: z.number().optional(),
|
|
105
|
+
contextWindowMaxTokens: z.number().optional(),
|
|
106
|
+
contextWindowUsedTokens: z.number().optional(),
|
|
107
|
+
});
|
|
108
|
+
export type LiveUsage = z.infer<typeof liveUsageSchema>;
|
|
109
|
+
|
|
110
|
+
export const topTimelineTelemetrySchema = z.object({
|
|
111
|
+
turnId: z.string().nullable(),
|
|
112
|
+
agentId: z.string(),
|
|
113
|
+
outcomeKind: z.enum(["completed", "failed", "canceled"]),
|
|
114
|
+
outcomeError: z.string().optional(),
|
|
115
|
+
timestamp: z.string(),
|
|
116
|
+
durationMs: z.number().optional(),
|
|
117
|
+
cpuPercent: z.number(),
|
|
118
|
+
memUsedBytes: z.number(),
|
|
119
|
+
memTotalBytes: z.number(),
|
|
120
|
+
memPercent: z.number(),
|
|
121
|
+
loadAvg1m: z.number(),
|
|
122
|
+
mcpHealthy: z.number().optional(),
|
|
123
|
+
mcpTotal: z.number().optional(),
|
|
124
|
+
mcpInstalled: z.boolean().optional(),
|
|
125
|
+
mcpRunning: z.boolean().optional(),
|
|
126
|
+
branch: z.string().nullable().optional(),
|
|
127
|
+
worktree: z.string().nullable().optional(),
|
|
128
|
+
agentTitle: z.string().nullable().optional(),
|
|
129
|
+
agentModel: z.string().nullable().optional(),
|
|
130
|
+
agentProvider: z.string().nullable().optional(),
|
|
131
|
+
uptimeSeconds: z.number().optional(),
|
|
132
|
+
gitInsertions: z.number().optional(),
|
|
133
|
+
gitDeletions: z.number().optional(),
|
|
134
|
+
gitFilesChanged: z.number().optional(),
|
|
135
|
+
toolCalls: z.number().optional(),
|
|
136
|
+
toolErrors: z.number().optional(),
|
|
137
|
+
turnCount: z.number().optional(),
|
|
138
|
+
inputTokens: z.number().optional(),
|
|
139
|
+
outputTokens: z.number().optional(),
|
|
140
|
+
cachedTokens: z.number().optional(),
|
|
141
|
+
cachedInputTokens: z.number().optional(),
|
|
142
|
+
contextUsedTokens: z.number().optional(),
|
|
143
|
+
contextMaxTokens: z.number().optional(),
|
|
144
|
+
costUsd: z.number().optional(),
|
|
145
|
+
});
|
|
146
|
+
export type TopTimelineTelemetryData = z.infer<typeof topTimelineTelemetrySchema>;
|
|
147
|
+
|
|
148
|
+
export const TOP_TIMELINE_KIND = "top-turn-telemetry";
|
|
149
|
+
export const TOP_TIMELINE_VERSION = 1;
|
|
150
|
+
|
|
151
|
+
export const getSystemResourcesRpc = defineContract({
|
|
152
|
+
name: "system-resources.get",
|
|
153
|
+
description: "Retrieve real-time host system resource metrics (CPU, RAM, load, uptime)",
|
|
154
|
+
input: z
|
|
155
|
+
.object({
|
|
156
|
+
directory: z.string().optional(),
|
|
157
|
+
fields: z.array(ResourceFieldSchema).optional(),
|
|
158
|
+
})
|
|
159
|
+
.default({}),
|
|
160
|
+
output: z.object({
|
|
161
|
+
version: z.string(),
|
|
162
|
+
hostname: z.string().optional(),
|
|
163
|
+
platform: z.string().optional(),
|
|
164
|
+
arch: z.string().optional(),
|
|
165
|
+
cpuModel: z.string().optional(),
|
|
166
|
+
cpuCores: z.number().optional(),
|
|
167
|
+
cpuUsagePercent: z.number().optional(),
|
|
168
|
+
memoryUsedBytes: z.number().optional(),
|
|
169
|
+
memoryTotalBytes: z.number().optional(),
|
|
170
|
+
memoryUsedPercent: z.number().optional(),
|
|
171
|
+
loadAvg: z.array(z.number()).optional(),
|
|
172
|
+
uptimeSeconds: z.number().optional(),
|
|
173
|
+
branch: z.string().nullable().optional(),
|
|
174
|
+
mcp: McpResourceStatusSchema.nullable().optional(),
|
|
175
|
+
mcpInstalled: z.boolean().optional(),
|
|
176
|
+
mcpRunning: z.boolean().optional(),
|
|
177
|
+
customPills: z.array(CustomPillStateSchema).optional(),
|
|
178
|
+
lastTurn: topTimelineTelemetrySchema.nullable().optional(),
|
|
179
|
+
liveUsage: liveUsageSchema.nullable().optional(),
|
|
180
|
+
}),
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
export type SystemResources = RpcOutput<typeof getSystemResourcesRpc>;
|
|
184
|
+
|
|
185
|
+
export const PillModeSchema = z.enum(["cycle", "all", "multiple"]).default("cycle");
|
|
186
|
+
export type PillMode = z.infer<typeof PillModeSchema>;
|
|
187
|
+
|
|
188
|
+
export const SurfaceTargetSchema = z.enum(["pill", "timeline", "both", "none"]);
|
|
189
|
+
export type SurfaceTarget = z.infer<typeof SurfaceTargetSchema>;
|
|
190
|
+
|
|
191
|
+
export const MetricIdSchema = z.enum([
|
|
192
|
+
"cpu_ram",
|
|
193
|
+
"branch",
|
|
194
|
+
"worktree",
|
|
195
|
+
"agent_title",
|
|
196
|
+
"agent",
|
|
197
|
+
"agent_provider",
|
|
198
|
+
"agent_activity",
|
|
199
|
+
"agent_id",
|
|
200
|
+
"load",
|
|
201
|
+
"uptime",
|
|
202
|
+
"mcp",
|
|
203
|
+
"changes",
|
|
204
|
+
"tokens",
|
|
205
|
+
"tools",
|
|
206
|
+
"turns",
|
|
207
|
+
]);
|
|
208
|
+
export type MetricId = z.infer<typeof MetricIdSchema>;
|
|
209
|
+
|
|
210
|
+
export const METRIC_IDS: readonly MetricId[] = [
|
|
211
|
+
"cpu_ram",
|
|
212
|
+
"branch",
|
|
213
|
+
"worktree",
|
|
214
|
+
"agent_title",
|
|
215
|
+
"agent",
|
|
216
|
+
"agent_provider",
|
|
217
|
+
"agent_activity",
|
|
218
|
+
"agent_id",
|
|
219
|
+
"load",
|
|
220
|
+
"uptime",
|
|
221
|
+
"mcp",
|
|
222
|
+
"changes",
|
|
223
|
+
"tokens",
|
|
224
|
+
"tools",
|
|
225
|
+
"turns",
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
export const CORE_TIMELINE_METRICS: readonly MetricId[] = [
|
|
229
|
+
"cpu_ram",
|
|
230
|
+
"branch",
|
|
231
|
+
"load",
|
|
232
|
+
"mcp",
|
|
233
|
+
"agent_id",
|
|
234
|
+
"changes",
|
|
235
|
+
"tokens",
|
|
236
|
+
];
|
|
237
|
+
|
|
238
|
+
export const DEFAULT_METRIC_SURFACES: Record<MetricId, SurfaceTarget> = {
|
|
239
|
+
cpu_ram: "both",
|
|
240
|
+
branch: "both",
|
|
241
|
+
worktree: "pill",
|
|
242
|
+
agent_id: "both",
|
|
243
|
+
load: "both",
|
|
244
|
+
uptime: "none",
|
|
245
|
+
mcp: "both",
|
|
246
|
+
agent_title: "none",
|
|
247
|
+
agent: "none",
|
|
248
|
+
agent_provider: "none",
|
|
249
|
+
agent_activity: "none",
|
|
250
|
+
changes: "timeline",
|
|
251
|
+
tokens: "timeline",
|
|
252
|
+
tools: "timeline",
|
|
253
|
+
turns: "none",
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
export interface MetricDefinition {
|
|
257
|
+
id: MetricId;
|
|
258
|
+
title: string;
|
|
259
|
+
description: string;
|
|
260
|
+
icon: string;
|
|
261
|
+
shortLabel?: string;
|
|
262
|
+
core?: boolean;
|
|
263
|
+
pillOnly?: boolean;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export const METRIC_DEFINITIONS: MetricDefinition[] = [
|
|
267
|
+
{
|
|
268
|
+
id: "cpu_ram",
|
|
269
|
+
title: "CPU & RAM",
|
|
270
|
+
description: "Host CPU utilization and memory consumption",
|
|
271
|
+
icon: "Cpu",
|
|
272
|
+
core: true,
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
id: "branch",
|
|
276
|
+
title: "Git Branch",
|
|
277
|
+
description: "Active Git branch in agent workspace",
|
|
278
|
+
icon: "GitBranch",
|
|
279
|
+
core: true,
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
id: "load",
|
|
283
|
+
title: "System Load",
|
|
284
|
+
description: "1-minute host system load average",
|
|
285
|
+
icon: "Activity",
|
|
286
|
+
shortLabel: "load",
|
|
287
|
+
core: true,
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
id: "mcp",
|
|
291
|
+
title: "MCP Server Health",
|
|
292
|
+
description: "Connected MCP server count and status snapshots",
|
|
293
|
+
icon: "Server",
|
|
294
|
+
core: true,
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
id: "agent_id",
|
|
298
|
+
title: "Agent ID",
|
|
299
|
+
description: "Agent session short ID",
|
|
300
|
+
icon: "Hash",
|
|
301
|
+
core: true,
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
id: "worktree",
|
|
305
|
+
title: "Worktree Location",
|
|
306
|
+
description: "Workspace directory or worktree path",
|
|
307
|
+
icon: "Folder",
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
id: "agent",
|
|
311
|
+
title: "Agent Model",
|
|
312
|
+
description: "Active LLM model identifier",
|
|
313
|
+
icon: "Bot",
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
id: "agent_provider",
|
|
317
|
+
title: "Agent Provider",
|
|
318
|
+
description: "LLM provider name (e.g. anthropic, openai)",
|
|
319
|
+
icon: "Globe",
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
id: "agent_activity",
|
|
323
|
+
title: "Agent Activity",
|
|
324
|
+
description: "Live idle timer; timeline snapshots would freeze it",
|
|
325
|
+
icon: "Clock",
|
|
326
|
+
pillOnly: true,
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
id: "agent_title",
|
|
330
|
+
title: "Agent Title",
|
|
331
|
+
description: "Agent tab display title",
|
|
332
|
+
icon: "Tag",
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
id: "uptime",
|
|
336
|
+
title: "Host Uptime",
|
|
337
|
+
description: "System running duration since boot",
|
|
338
|
+
icon: "Power",
|
|
339
|
+
shortLabel: "up",
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
id: "changes",
|
|
343
|
+
title: "Git Changes",
|
|
344
|
+
description: "Per-turn git insertions, deletions, and files changed",
|
|
345
|
+
icon: "GitCommitHorizontal",
|
|
346
|
+
shortLabel: "Δ",
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
id: "tokens",
|
|
350
|
+
title: "Token Usage",
|
|
351
|
+
description: "Live cumulative plus per-turn input/output tokens and context use",
|
|
352
|
+
icon: "Coins",
|
|
353
|
+
shortLabel: "tok",
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
id: "tools",
|
|
357
|
+
title: "Tool Calls",
|
|
358
|
+
description: "Per-turn tool call and error counts",
|
|
359
|
+
icon: "Wrench",
|
|
360
|
+
shortLabel: "calls",
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
id: "turns",
|
|
364
|
+
title: "Turn Count",
|
|
365
|
+
description: "Lifetime completed turns for the active agent",
|
|
366
|
+
icon: "Repeat",
|
|
367
|
+
shortLabel: "turns",
|
|
368
|
+
},
|
|
369
|
+
];
|
|
370
|
+
|
|
371
|
+
export function isPillEnabled(target?: SurfaceTarget): boolean {
|
|
372
|
+
return target === "pill" || target === "both";
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function isTimelineEnabled(target?: SurfaceTarget): boolean {
|
|
376
|
+
return target === "timeline" || target === "both";
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Single presence-gated read point for the MCP metric surface. Every surface
|
|
381
|
+
* (pill, timeline) resolves through here so uninstalled means invisible
|
|
382
|
+
* everywhere with no per-call-site presence checks. Fail-closed: anything
|
|
383
|
+
* other than positively installed (including unknown) resolves to off.
|
|
384
|
+
*/
|
|
385
|
+
/**
|
|
386
|
+
* Surface visibility contract (single source of truth for pill and card):
|
|
387
|
+
* selected + live data -> value; selected + not-yet-observed -> placeholder;
|
|
388
|
+
* selected + known-dead source -> hidden on both surfaces; unselected -> hidden.
|
|
389
|
+
* A disabled dependency is known-dead, never placeholder material.
|
|
390
|
+
*/
|
|
391
|
+
/**
|
|
392
|
+
* Effective enabled state for one custom pill. Single decision point shared
|
|
393
|
+
* by the server filter, the settings matrix, and the composer sync.
|
|
394
|
+
*/
|
|
395
|
+
export function customPillEffectiveEnabled(
|
|
396
|
+
masterEnabled: boolean,
|
|
397
|
+
overrides: Record<string, boolean> | undefined,
|
|
398
|
+
pill: { id: string; enabled: boolean },
|
|
399
|
+
): boolean {
|
|
400
|
+
if (!masterEnabled) return false;
|
|
401
|
+
const override = overrides?.[pill.id];
|
|
402
|
+
return override === undefined ? pill.enabled : override;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
export function isSourceDead(
|
|
406
|
+
id: MetricId,
|
|
407
|
+
status: { mcpRunning?: boolean | null },
|
|
408
|
+
): boolean {
|
|
409
|
+
if (id === "mcp") return status?.mcpRunning === false;
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export function isMcpSurfaceEnabled(
|
|
414
|
+
settings: {
|
|
415
|
+
metricSurfaces?: Partial<Record<MetricId, SurfaceTarget>>;
|
|
416
|
+
showMcp?: boolean;
|
|
417
|
+
mcp?: boolean;
|
|
418
|
+
},
|
|
419
|
+
surface: "pill" | "timeline",
|
|
420
|
+
mcpInstalled?: boolean,
|
|
421
|
+
mcpRunning?: boolean | null,
|
|
422
|
+
): boolean {
|
|
423
|
+
if (mcpInstalled !== true) return false;
|
|
424
|
+
if (mcpRunning === false) return false;
|
|
425
|
+
if (surface === "pill") return legacyFlagView(settings).showMcp;
|
|
426
|
+
const s = settings.metricSurfaces;
|
|
427
|
+
if (!s) return true;
|
|
428
|
+
return isTimelineEnabled(s["mcp"]);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export function targetFromCheckboxes(pill: boolean, timeline: boolean): SurfaceTarget {
|
|
432
|
+
if (pill && timeline) return "both";
|
|
433
|
+
if (pill) return "pill";
|
|
434
|
+
if (timeline) return "timeline";
|
|
435
|
+
return "none";
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export function checkboxesFromTarget(target?: SurfaceTarget): { pill: boolean; timeline: boolean } {
|
|
439
|
+
const t = target ?? "none";
|
|
440
|
+
return {
|
|
441
|
+
pill: t === "pill" || t === "both",
|
|
442
|
+
timeline: t === "timeline" || t === "both",
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
export function isCoreTimelineMetric(metricId: MetricId): boolean {
|
|
447
|
+
return (CORE_TIMELINE_METRICS as readonly string[]).includes(metricId);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export const PROVIDER_DEPENDENT_METRICS: readonly MetricId[] = [
|
|
451
|
+
"tokens",
|
|
452
|
+
];
|
|
453
|
+
|
|
454
|
+
export function isProviderDependent(metricId: MetricId): boolean {
|
|
455
|
+
return (PROVIDER_DEPENDENT_METRICS as readonly string[]).includes(metricId);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Where each metric renders. The gap test asserts every non-pillOnly metric
|
|
460
|
+
* appears in at least one registry: offered-but-nowhere-visible is a bug.
|
|
461
|
+
* Keep these in sync with PillItemContent cases (pill), the multiple-mode
|
|
462
|
+
* desiredPills list (dedicated pills), and TopTimelineTelemetryCard rows
|
|
463
|
+
* (timeline) in client/.
|
|
464
|
+
*/
|
|
465
|
+
export const PILL_RENDERED_METRICS: readonly MetricId[] = [...METRIC_IDS];
|
|
466
|
+
|
|
467
|
+
export const MULTIPLE_MODE_RENDERED_METRICS: readonly MetricId[] = [...METRIC_IDS];
|
|
468
|
+
|
|
469
|
+
export const TIMELINE_RENDERED_METRICS: readonly MetricId[] = [
|
|
470
|
+
"cpu_ram",
|
|
471
|
+
"load",
|
|
472
|
+
"mcp",
|
|
473
|
+
"agent_id",
|
|
474
|
+
"agent_title",
|
|
475
|
+
"agent",
|
|
476
|
+
"agent_provider",
|
|
477
|
+
"branch",
|
|
478
|
+
"worktree",
|
|
479
|
+
"uptime",
|
|
480
|
+
"changes",
|
|
481
|
+
"tokens",
|
|
482
|
+
"tools",
|
|
483
|
+
"turns",
|
|
484
|
+
];
|
|
485
|
+
|
|
486
|
+
export interface LegacyFlagView {
|
|
487
|
+
showCpuRam: boolean;
|
|
488
|
+
showBranch: boolean;
|
|
489
|
+
showWorktree: boolean;
|
|
490
|
+
showAgentTitle: boolean;
|
|
491
|
+
showAgent: boolean;
|
|
492
|
+
showAgentProvider: boolean;
|
|
493
|
+
showAgentActivity: boolean;
|
|
494
|
+
showAgentId: boolean;
|
|
495
|
+
showLoad: boolean;
|
|
496
|
+
showUptime: boolean;
|
|
497
|
+
showMcp: boolean;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Projects per-metric surface selectors back onto the legacy boolean flags
|
|
502
|
+
* consumed by pill rendering. Selectors win when present; raw legacy flags
|
|
503
|
+
* apply only to settings objects that predate migration.
|
|
504
|
+
*/
|
|
505
|
+
export function legacyFlagView(settings: {
|
|
506
|
+
metricSurfaces?: Partial<Record<MetricId, SurfaceTarget>>;
|
|
507
|
+
showCpuRam?: boolean;
|
|
508
|
+
showBranch?: boolean;
|
|
509
|
+
showWorktree?: boolean;
|
|
510
|
+
showAgentTitle?: boolean;
|
|
511
|
+
showAgent?: boolean;
|
|
512
|
+
showAgentProvider?: boolean;
|
|
513
|
+
showAgentActivity?: boolean;
|
|
514
|
+
showAgentId?: boolean;
|
|
515
|
+
showLoad?: boolean;
|
|
516
|
+
showUptime?: boolean;
|
|
517
|
+
showMcp?: boolean;
|
|
518
|
+
mcp?: boolean;
|
|
519
|
+
}): LegacyFlagView {
|
|
520
|
+
const s = settings.metricSurfaces;
|
|
521
|
+
if (!s) {
|
|
522
|
+
return {
|
|
523
|
+
showCpuRam: settings.showCpuRam ?? true,
|
|
524
|
+
showBranch: settings.showBranch ?? true,
|
|
525
|
+
showWorktree: settings.showWorktree ?? true,
|
|
526
|
+
showAgentTitle: settings.showAgentTitle ?? false,
|
|
527
|
+
showAgent: settings.showAgent ?? false,
|
|
528
|
+
showAgentProvider: settings.showAgentProvider ?? false,
|
|
529
|
+
showAgentActivity: settings.showAgentActivity ?? false,
|
|
530
|
+
showAgentId: settings.showAgentId ?? true,
|
|
531
|
+
showLoad: settings.showLoad ?? false,
|
|
532
|
+
showUptime: settings.showUptime ?? false,
|
|
533
|
+
showMcp: settings.showMcp ?? settings.mcp ?? true,
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
const pill = (id: MetricId): boolean => isPillEnabled(s[id]);
|
|
537
|
+
return {
|
|
538
|
+
showCpuRam: pill("cpu_ram"),
|
|
539
|
+
showBranch: pill("branch"),
|
|
540
|
+
showWorktree: pill("worktree"),
|
|
541
|
+
showAgentTitle: pill("agent_title"),
|
|
542
|
+
showAgent: pill("agent"),
|
|
543
|
+
showAgentProvider: pill("agent_provider"),
|
|
544
|
+
showAgentActivity: pill("agent_activity"),
|
|
545
|
+
showAgentId: pill("agent_id"),
|
|
546
|
+
showLoad: pill("load"),
|
|
547
|
+
showUptime: pill("uptime"),
|
|
548
|
+
showMcp: pill("mcp"),
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Migrates legacy boolean toggles and single recordTurnTelemetry switch into the
|
|
554
|
+
* per-metric SurfaceTarget model: Record<MetricId, "pill" | "timeline" | "both" | "none">.
|
|
555
|
+
*/
|
|
556
|
+
export function migrateLegacyMetricSurfaces(raw: Record<string, unknown>): Record<MetricId, SurfaceTarget> {
|
|
557
|
+
if (raw.metricSurfaces && typeof raw.metricSurfaces === "object") {
|
|
558
|
+
const custom = raw.metricSurfaces as Partial<Record<MetricId, SurfaceTarget>>;
|
|
559
|
+
const resolved: Record<MetricId, SurfaceTarget> = { ...DEFAULT_METRIC_SURFACES };
|
|
560
|
+
for (const id of METRIC_IDS) {
|
|
561
|
+
if (custom[id] && SurfaceTargetSchema.safeParse(custom[id]).success) {
|
|
562
|
+
resolved[id] = custom[id]!;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return resolved;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const hasLegacyKey =
|
|
569
|
+
"recordTurnTelemetry" in raw ||
|
|
570
|
+
"showCpuRam" in raw ||
|
|
571
|
+
"showBranch" in raw ||
|
|
572
|
+
"showWorktree" in raw ||
|
|
573
|
+
"showAgentId" in raw ||
|
|
574
|
+
"showLoad" in raw ||
|
|
575
|
+
"showUptime" in raw ||
|
|
576
|
+
"showMcp" in raw ||
|
|
577
|
+
"mcp" in raw ||
|
|
578
|
+
"showAgentTitle" in raw ||
|
|
579
|
+
"showAgent" in raw ||
|
|
580
|
+
"showAgentProvider" in raw ||
|
|
581
|
+
"showAgentActivity" in raw;
|
|
582
|
+
|
|
583
|
+
if (!hasLegacyKey) {
|
|
584
|
+
return { ...DEFAULT_METRIC_SURFACES };
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const singleSwitch = raw.recordTurnTelemetry;
|
|
588
|
+
const singleSwitchOn = singleSwitch !== false;
|
|
589
|
+
|
|
590
|
+
const legacyPillMap: Record<MetricId, boolean> = {
|
|
591
|
+
cpu_ram: typeof raw.showCpuRam === "boolean" ? raw.showCpuRam : true,
|
|
592
|
+
branch: typeof raw.showBranch === "boolean" ? raw.showBranch : true,
|
|
593
|
+
worktree: typeof raw.showWorktree === "boolean" ? raw.showWorktree : true,
|
|
594
|
+
agent_id: typeof raw.showAgentId === "boolean" ? raw.showAgentId : true,
|
|
595
|
+
load: typeof raw.showLoad === "boolean" ? raw.showLoad : false,
|
|
596
|
+
uptime: typeof raw.showUptime === "boolean" ? raw.showUptime : false,
|
|
597
|
+
mcp: typeof raw.showMcp === "boolean" ? raw.showMcp : (typeof raw.mcp === "boolean" ? raw.mcp : true),
|
|
598
|
+
agent_title: typeof raw.showAgentTitle === "boolean" ? raw.showAgentTitle : false,
|
|
599
|
+
agent: typeof raw.showAgent === "boolean" ? raw.showAgent : false,
|
|
600
|
+
agent_provider: typeof raw.showAgentProvider === "boolean" ? raw.showAgentProvider : false,
|
|
601
|
+
agent_activity: typeof raw.showAgentActivity === "boolean" ? raw.showAgentActivity : false,
|
|
602
|
+
changes: false,
|
|
603
|
+
tokens: false,
|
|
604
|
+
tools: false,
|
|
605
|
+
turns: false,
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
const result: Record<MetricId, SurfaceTarget> = { ...DEFAULT_METRIC_SURFACES };
|
|
609
|
+
|
|
610
|
+
for (const id of METRIC_IDS) {
|
|
611
|
+
const pill = legacyPillMap[id];
|
|
612
|
+
// If single switch was on: on = both for core metrics
|
|
613
|
+
// If single switch was off: off = none for timeline
|
|
614
|
+
const timeline = singleSwitchOn && isCoreTimelineMetric(id);
|
|
615
|
+
result[id] = targetFromCheckboxes(pill, timeline);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
return result;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
export const TopSettingsSchema = z.preprocess(
|
|
622
|
+
(val) => {
|
|
623
|
+
if (val && typeof val === "object") {
|
|
624
|
+
const obj = { ...(val as Record<string, unknown>) };
|
|
625
|
+
if (!obj.metricSurfaces) {
|
|
626
|
+
obj.metricSurfaces = migrateLegacyMetricSurfaces(obj);
|
|
627
|
+
}
|
|
628
|
+
if (obj.timelineCadence === undefined && obj.recordTurnTelemetry === false) {
|
|
629
|
+
obj.timelineCadence = 0;
|
|
630
|
+
}
|
|
631
|
+
return obj;
|
|
632
|
+
}
|
|
633
|
+
return val;
|
|
634
|
+
},
|
|
635
|
+
z.object({
|
|
636
|
+
pillMode: PillModeSchema,
|
|
637
|
+
metricSurfaces: z.record(MetricIdSchema, SurfaceTargetSchema).default(DEFAULT_METRIC_SURFACES),
|
|
638
|
+
showCpuRam: z.boolean().optional(),
|
|
639
|
+
showBranch: z.boolean().optional(),
|
|
640
|
+
showWorktree: z.boolean().optional(),
|
|
641
|
+
showAgentTitle: z.boolean().optional(),
|
|
642
|
+
showAgent: z.boolean().optional(),
|
|
643
|
+
showAgentProvider: z.boolean().optional(),
|
|
644
|
+
showAgentActivity: z.boolean().optional(),
|
|
645
|
+
showAgentId: z.boolean().optional(),
|
|
646
|
+
showLoad: z.boolean().optional(),
|
|
647
|
+
showUptime: z.boolean().optional(),
|
|
648
|
+
showMcp: z.boolean().optional(),
|
|
649
|
+
mcp: z.boolean().optional(),
|
|
650
|
+
showComposerPill: z.boolean().default(true),
|
|
651
|
+
showCustomPills: z.boolean().default(true),
|
|
652
|
+
customPillEnabled: z.record(z.string(), z.boolean()).default({}),
|
|
653
|
+
provisionedMetrics: z.array(MetricIdSchema).default([]),
|
|
654
|
+
recordTurnTelemetry: z.boolean().optional(),
|
|
655
|
+
timelineCadence: z.number().min(0).max(10).default(1),
|
|
656
|
+
intervalSeconds: z.number().min(1).max(60).default(3),
|
|
657
|
+
defaultTab: z.enum(["system", "context", "settings", "about"]).default("system"),
|
|
658
|
+
})
|
|
659
|
+
);
|
|
660
|
+
|
|
661
|
+
export type TopSettings = z.infer<typeof TopSettingsSchema>;
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Timeline card cadence: 0 suppresses the card (legacy `never`),
|
|
665
|
+
* 1 appends every turn, N>1 appends every Nth turn.
|
|
666
|
+
*/
|
|
667
|
+
export function resolveTimelineCadence(settings: {
|
|
668
|
+
timelineCadence?: number;
|
|
669
|
+
recordTurnTelemetry?: boolean;
|
|
670
|
+
}): number {
|
|
671
|
+
if (settings.timelineCadence !== undefined) return settings.timelineCadence;
|
|
672
|
+
return settings.recordTurnTelemetry === false ? 0 : 1;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
export function shouldAppendTimelineForTurn(cadence: number, turnIndex: number): boolean {
|
|
676
|
+
if (!Number.isFinite(cadence) || cadence <= 0) return false;
|
|
677
|
+
if (cadence <= 1) return true;
|
|
678
|
+
return turnIndex % Math.floor(cadence) === 0;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
export const topSettingsContract = defineSettingsContract({
|
|
682
|
+
name: "top.settings",
|
|
683
|
+
schema: TopSettingsSchema,
|
|
684
|
+
description: "Paseo top composer pill and display settings",
|
|
685
|
+
});
|
|
686
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Vendored paseo-plugin-helper (Track B of issue #71)
|
|
2
|
+
|
|
3
|
+
Pinned helper version: 0.4.0-beta.12
|
|
4
|
+
|
|
5
|
+
Docs: https://github.com/xpufx/paseo/tree/main/packages/paseo-plugin-helper — npm: https://www.npmjs.com/package/paseo-plugin-helper
|
|
6
|
+
|
|
7
|
+
Zero host requirements (no npm, no registry, no build key): the daemon bundles
|
|
8
|
+
this source directly. Layout: `client/`, `server/`, `shared/` vendor splits
|
|
9
|
+
mapping helper `src/client`, `src/server`, `src/shared` (daemon accepts modules
|
|
10
|
+
only under those dirs). Updating: run `make vendor-sync` and bump the pinned
|
|
11
|
+
version above.
|