paseo-bm-plugin 0.0.0-placeholder.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 +53 -0
- package/client/agent-tree.ts +308 -0
- package/client/answer-state.ts +62 -0
- package/client/bead-chips.tsx +147 -0
- package/client/beads-header-button.ts +108 -0
- package/client/beads-model.ts +581 -0
- package/client/beads-screen.tsx +516 -0
- package/client/beads-tab.tsx +58 -0
- package/client/chat-card.tsx +636 -0
- package/client/chat-cards.ts +1038 -0
- package/client/dashboard-actions.tsx +255 -0
- package/client/dashboard-model.ts +947 -0
- package/client/dashboard-view.ts +215 -0
- package/client/dashboard.tsx +318 -0
- package/client/launch-manager.ts +323 -0
- package/client/launcher.tsx +516 -0
- package/client/markdown-view.tsx +112 -0
- package/client/markdown.ts +145 -0
- package/client/settings.tsx +104 -0
- package/client/setup-model.ts +552 -0
- package/client/setup-screen.tsx +913 -0
- package/client/slot.ts +47 -0
- package/client/tree.tsx +204 -0
- package/client/ui.tsx +262 -0
- package/client/waiting-pills-model.ts +156 -0
- package/client/waiting-pills.tsx +201 -0
- package/index.client.tsx +232 -0
- package/index.server.ts +168 -0
- package/package.json +35 -0
- package/paseo-plugin.json +6 -0
- package/roles/manager.md +181 -0
- package/roles/reviewer.md +160 -0
- package/roles/worker.md +407 -0
- package/server/agent-labels.ts +194 -0
- package/server/agent-role.ts +102 -0
- package/server/answer-marks.ts +120 -0
- package/server/bead-actions.ts +88 -0
- package/server/bead-work.ts +80 -0
- package/server/beads-store.ts +342 -0
- package/server/bm-report.ts +433 -0
- package/server/chat-peers.ts +65 -0
- package/server/chat-rpc.ts +122 -0
- package/server/chat-waiting.ts +182 -0
- package/server/collector.ts +629 -0
- package/server/config-writer.ts +222 -0
- package/server/cost.ts +88 -0
- package/server/dashboard-rpc.ts +662 -0
- package/server/fallback-detect.ts +183 -0
- package/server/fallback-handover.ts +365 -0
- package/server/fallback-manager.ts +170 -0
- package/server/fallback-reviewer.ts +198 -0
- package/server/fallback-rpc.ts +306 -0
- package/server/fallback-settings.ts +322 -0
- package/server/fallback-state.ts +518 -0
- package/server/fallback-switch.ts +191 -0
- package/server/fallback-wait.ts +188 -0
- package/server/format-check.ts +352 -0
- package/server/install-home.ts +187 -0
- package/server/live-timeline.ts +129 -0
- package/server/manager-instructions.ts +9 -0
- package/server/manager.ts +647 -0
- package/server/model-costs.ts +238 -0
- package/server/notice-queue.ts +315 -0
- package/server/notices.ts +81 -0
- package/server/paseo-cli.ts +115 -0
- package/server/provider-id.ts +12 -0
- package/server/review-budget.ts +208 -0
- package/server/reviewer-instructions.ts +9 -0
- package/server/role-choices.ts +161 -0
- package/server/role-extras.ts +270 -0
- package/server/role-hook.ts +347 -0
- package/server/role-mode.ts +397 -0
- package/server/role-settings-rpc.ts +325 -0
- package/server/roles.ts +96 -0
- package/server/settings-notices.ts +112 -0
- package/server/setup-rpc.ts +70 -0
- package/server/setup-skills.ts +121 -0
- package/server/setup-tools.ts +162 -0
- package/server/shell.ts +68 -0
- package/server/stop-propagation.ts +365 -0
- package/server/tools-check.ts +118 -0
- package/server/trace-store.ts +1137 -0
- package/server/traces.ts +1356 -0
- package/server/worker-instructions.ts +9 -0
- package/server/workflow-steps.ts +422 -0
- package/shared/bead-ids.ts +25 -0
- package/shared/bm-fallback.ts +91 -0
- package/shared/bm-format.ts +424 -0
- package/shared/bm-questions.ts +213 -0
- package/shared/bm-report.ts +433 -0
- package/shared/contracts.ts +1371 -0
- package/shared/fallback-patterns.ts +201 -0
- package/shared/fallback.ts +46 -0
- package/shared/new-request.ts +20 -0
- package/shared/order.ts +22 -0
- package/shared/prices.ts +65 -0
- package/shared/settings.ts +57 -0
- package/shared/sole-worker.ts +20 -0
- package/shared/version.ts +6 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,1371 @@
|
|
|
1
|
+
import { defineRpc } from "@getpaseo/plugin";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { modelPriceSchema } from "./prices";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* RPC contracts for the paseo-bm plugin.
|
|
7
|
+
*
|
|
8
|
+
* Source of truth: docs/design/paseo-bm.md §5 ("Hợp đồng RPC của plugin").
|
|
9
|
+
* This module is `shared/`, so it must stay free of Node and React Native
|
|
10
|
+
* runtime imports: Zod schemas and plain values only.
|
|
11
|
+
*
|
|
12
|
+
* WP-108 delivers the contracts. Handler behaviour lives in `server/` (WP-112)
|
|
13
|
+
* and the surfaces that call them live in `client/` (WP-113).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** Value of the `bm.role` agent label that paseo-bm sets when it creates an agent. */
|
|
17
|
+
export const bmRoleSchema = z.enum(["manager", "worker", "reviewer"]);
|
|
18
|
+
|
|
19
|
+
/** Identifier of a Paseo workspace, as returned by the Paseo SDK. */
|
|
20
|
+
export const workspaceIdSchema = z.string().min(1);
|
|
21
|
+
|
|
22
|
+
/** Identifier of a Paseo agent, as returned by the Paseo SDK. */
|
|
23
|
+
export const agentIdSchema = z.string().min(1);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `manager.ensure` — find the live Manager of a workspace by its `bm.role=manager`
|
|
27
|
+
* label, or create one from the `bm-manager` profile with the instructions in
|
|
28
|
+
* `roles/manager.md`. `created` reports which of the two happened.
|
|
29
|
+
*
|
|
30
|
+
* `otherManagerIds` lists the other live Managers of the same workspace (newest
|
|
31
|
+
* first) when more than one exists; `agentId` is then the newest. They are
|
|
32
|
+
* reported, never deleted or archived (design §9.3). NOTE: this field is not in
|
|
33
|
+
* the design §5 table yet — see the WP-112 report; it is the only channel for
|
|
34
|
+
* the "báo trong panel" requirement.
|
|
35
|
+
*
|
|
36
|
+
* Failures are thrown as errors whose message starts with a registry code
|
|
37
|
+
* (`E_PROVIDER_UNAVAILABLE`).
|
|
38
|
+
*/
|
|
39
|
+
export const managerEnsureRpc = defineRpc({
|
|
40
|
+
name: "manager.ensure",
|
|
41
|
+
input: z.object({
|
|
42
|
+
workspaceId: workspaceIdSchema,
|
|
43
|
+
}),
|
|
44
|
+
output: z.object({
|
|
45
|
+
agentId: agentIdSchema,
|
|
46
|
+
created: z.boolean(),
|
|
47
|
+
otherManagerIds: z.array(agentIdSchema),
|
|
48
|
+
/**
|
|
49
|
+
* Why an existing Manager was not switched to its no-prompt mode, or `null`
|
|
50
|
+
* (delta 20260918 §4.1). Added field: a client that does not know it drops it.
|
|
51
|
+
*/
|
|
52
|
+
modeNotice: z.string().nullable(),
|
|
53
|
+
/**
|
|
54
|
+
* Set when the Manager just created has no Paseo tools (delta 20260921
|
|
55
|
+
* §4.2.4). Optional so an older server's answer still parses; the server
|
|
56
|
+
* always sends it.
|
|
57
|
+
*/
|
|
58
|
+
toolsNotice: z.string().nullable().optional(),
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Role shown for a listed agent: one of the three roles, or `unknown` when the
|
|
64
|
+
* `bm.role` label is missing or holds another value (design §5, "không rõ vai trò").
|
|
65
|
+
*/
|
|
66
|
+
export const agentRoleSchema = z.enum(["manager", "worker", "reviewer", "unknown"]);
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* One node of the agent tree the workspace panel draws.
|
|
70
|
+
*
|
|
71
|
+
* `role` is `unknown` when the agent carries no readable `bm.role` label; the
|
|
72
|
+
* panel renders that instead of dropping the agent (design §5).
|
|
73
|
+
* `title` mirrors the SDK snapshot, which may be `null` (untitled agent).
|
|
74
|
+
* `parentId` is the `paseo.parent-agent-id` label when that parent is itself in
|
|
75
|
+
* the list, otherwise `null` — so an orphaned Worker (its Manager deleted or
|
|
76
|
+
* archived) is a root of the tree (design §8).
|
|
77
|
+
*/
|
|
78
|
+
export const agentNodeSchema = z.object({
|
|
79
|
+
id: agentIdSchema,
|
|
80
|
+
role: agentRoleSchema,
|
|
81
|
+
title: z.string().nullable(),
|
|
82
|
+
status: z.string(),
|
|
83
|
+
parentId: agentIdSchema.nullable(),
|
|
84
|
+
updatedAt: z.string(),
|
|
85
|
+
/**
|
|
86
|
+
* False when the agent has no valid `bm.role` label: its role came from its
|
|
87
|
+
* provider, or it is an unlabelled descendant (delta 20260918g §4.4).
|
|
88
|
+
* Defaults to true for older servers.
|
|
89
|
+
*/
|
|
90
|
+
labelled: z.boolean().default(true),
|
|
91
|
+
/**
|
|
92
|
+
* The agent that replaced this one after a fallback switch: its `bm.replacedBy`
|
|
93
|
+
* label, else the replacement of a `switched` incident (delta 20260921
|
|
94
|
+
* §4.4.8). Defaults to null for older servers.
|
|
95
|
+
*/
|
|
96
|
+
replacedBy: z.string().nullable().default(null),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* `agents.list` — the agents of one workspace, flat. The caller builds the tree
|
|
101
|
+
* from `role` and `parentId`.
|
|
102
|
+
*/
|
|
103
|
+
export const agentsListRpc = defineRpc({
|
|
104
|
+
name: "agents.list",
|
|
105
|
+
input: z.object({
|
|
106
|
+
workspaceId: workspaceIdSchema,
|
|
107
|
+
}),
|
|
108
|
+
output: z.object({
|
|
109
|
+
agents: z.array(agentNodeSchema),
|
|
110
|
+
}),
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* One row of the effective role configuration the panel shows (REQ-032d).
|
|
115
|
+
*
|
|
116
|
+
* Read from the Paseo configuration in effect (errata bm-dnc): `provider` is the
|
|
117
|
+
* base provider the role's derived provider extends, `model` comes from the
|
|
118
|
+
* role's agent profile, `paseoTools` is whether the derived provider currently
|
|
119
|
+
* has the Paseo agent tools enabled, and `instructionsPath` is the name of the
|
|
120
|
+
* role's instructions inside the payload (e.g. `roles/manager.md`), not an
|
|
121
|
+
* on-disk path.
|
|
122
|
+
*/
|
|
123
|
+
export const roleDescriptorSchema = z.object({
|
|
124
|
+
role: bmRoleSchema,
|
|
125
|
+
provider: z.string(),
|
|
126
|
+
model: z.string(),
|
|
127
|
+
paseoTools: z.boolean(),
|
|
128
|
+
instructionsPath: z.string(),
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* `roles.describe` — the role configuration in effect right now. Takes no input.
|
|
133
|
+
*/
|
|
134
|
+
export const rolesDescribeRpc = defineRpc({
|
|
135
|
+
name: "roles.describe",
|
|
136
|
+
input: z.object({}),
|
|
137
|
+
output: z.object({
|
|
138
|
+
roles: z.array(roleDescriptorSchema),
|
|
139
|
+
}),
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
export type BmRole = z.infer<typeof bmRoleSchema>;
|
|
143
|
+
/** Input shape: `labelled` may be absent (meaning labelled), as from a server older than delta 20260918g. */
|
|
144
|
+
export type AgentNode = z.input<typeof agentNodeSchema>;
|
|
145
|
+
export type RoleDescriptor = z.infer<typeof roleDescriptorSchema>;
|
|
146
|
+
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
// Dashboard (Phase 2a) — WP-201.
|
|
149
|
+
//
|
|
150
|
+
// Source of truth: docs/design/paseo-bm-dashboard.md §§3.2–3.3 (persisted
|
|
151
|
+
// record), §4 (data model) and §5 (RPC + error codes). Field names are part of
|
|
152
|
+
// a *persisted* format: renaming one later costs a schema migration, so they
|
|
153
|
+
// follow the design literally.
|
|
154
|
+
//
|
|
155
|
+
// Everything below is read-only from the caller's point of view except
|
|
156
|
+
// `traces.delete` and `traces.reassign`, which only ever touch paseo-bm's own
|
|
157
|
+
// trace store (REQ-047).
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* How sure the server is about a derived conclusion. Rendered to the user, never
|
|
162
|
+
* hidden: `inferred` and `unknown` are the honest answers the Dashboard is
|
|
163
|
+
* required to show instead of a plausible guess (REQ-041d, REQ-044c, REQ-045).
|
|
164
|
+
*/
|
|
165
|
+
export const confidenceSchema = z.enum(["exact", "inferred", "unknown"]);
|
|
166
|
+
|
|
167
|
+
/** One traceable piece of evidence behind a derived conclusion (design §4.1). */
|
|
168
|
+
export const evidenceSchema = z.object({
|
|
169
|
+
/** `skill`: the agent loaded an agent skill; `detail` is the skill name. */
|
|
170
|
+
kind: z.enum(["report", "shell", "file", "agent", "timeline", "skill"]),
|
|
171
|
+
detail: z.string(),
|
|
172
|
+
agentId: agentIdSchema.nullable(),
|
|
173
|
+
at: z.string().nullable(),
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Token and cost roll-up (REQ-052). `costBasis` is what keeps the number
|
|
178
|
+
* honest: `provider` is the figure the tool itself reported, `estimated` comes
|
|
179
|
+
* from the dated price table bundled with the release, and `unavailable` means
|
|
180
|
+
* the model is not in that table — then `costUsd` is null and only tokens show.
|
|
181
|
+
*/
|
|
182
|
+
export const usageSchema = z.object({
|
|
183
|
+
inputTokens: z.number().int().nonnegative(),
|
|
184
|
+
cachedInputTokens: z.number().int().nonnegative(),
|
|
185
|
+
outputTokens: z.number().int().nonnegative(),
|
|
186
|
+
costUsd: z.number().nonnegative().nullable(),
|
|
187
|
+
costBasis: z.enum(["provider", "estimated", "unavailable"]),
|
|
188
|
+
model: z.string().nullable(),
|
|
189
|
+
pricesUpdatedAt: z.string().nullable(),
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
/** Lifecycle of one request, derived in the fixed order of design §7.3. */
|
|
193
|
+
export const traceStateSchema = z.enum([
|
|
194
|
+
"running",
|
|
195
|
+
"waiting_user",
|
|
196
|
+
"completed",
|
|
197
|
+
"stopped",
|
|
198
|
+
"failed",
|
|
199
|
+
"unknown",
|
|
200
|
+
]);
|
|
201
|
+
|
|
202
|
+
/** Request size the Worker classified itself into (REQ-036, REQ-045e). */
|
|
203
|
+
export const tierSchema = z.enum(["Small", "Medium", "Large"]);
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Whether the workspace a trace belongs to still exists in Paseo (design §3.7).
|
|
207
|
+
* `unknown` is used when `workspaces.list()` failed — one failed call must never
|
|
208
|
+
* be turned into the conclusion "this workspace is gone" (REQ-057a).
|
|
209
|
+
*/
|
|
210
|
+
export const workspaceStateSchema = z.enum(["live", "archived", "orphaned", "unknown"]);
|
|
211
|
+
|
|
212
|
+
/** A bead count plus how sure it is (REQ-044b, REQ-044c). */
|
|
213
|
+
export const beadCountSchema = z.object({
|
|
214
|
+
count: z.number().int().nonnegative(),
|
|
215
|
+
confidence: confidenceSchema,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
/** Self-reported guardrail counters, verbatim from a `BM-REPORT` (REQ-042c). */
|
|
219
|
+
export const guardrailReportSchema = z.object({
|
|
220
|
+
batchId: z.string().nullable(),
|
|
221
|
+
batchReviews: z.number().int().nonnegative().nullable(),
|
|
222
|
+
batchMax: z.number().int().nonnegative().nullable(),
|
|
223
|
+
polish: z.number().int().nonnegative().nullable(),
|
|
224
|
+
polishMax: z.number().int().nonnegative().nullable(),
|
|
225
|
+
total: z.number().int().nonnegative().nullable(),
|
|
226
|
+
budget: z.number().int().nonnegative().nullable(),
|
|
227
|
+
userAllowedExtra: z.number().int().nonnegative().nullable(),
|
|
228
|
+
raw: z.string(),
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
/** One row of the trace list (design §4.2). */
|
|
232
|
+
export const traceSummarySchema = z.object({
|
|
233
|
+
traceId: z.string().min(1),
|
|
234
|
+
requestId: z.string().nullable(),
|
|
235
|
+
requestedAt: z.string(),
|
|
236
|
+
/** Null when no user turn was captured, so the screen says so rather than showing "". */
|
|
237
|
+
excerpt: z.string().nullable(),
|
|
238
|
+
/**
|
|
239
|
+
* Which turn of the request this row is, when the user asked more than once
|
|
240
|
+
* (delta 20260917e §4.3). `null` for a request that was never followed up, so
|
|
241
|
+
* those rows look exactly as they always did — no `lượt 1` noise.
|
|
242
|
+
*
|
|
243
|
+
* Rows of one request share a `traceId` on purpose: opening any of them leads
|
|
244
|
+
* to the same request. The list key is the pair.
|
|
245
|
+
*/
|
|
246
|
+
turn: z.object({ index: z.number().int().positive(), total: z.number().int().positive() }).nullable(),
|
|
247
|
+
state: traceStateSchema,
|
|
248
|
+
workerIds: z.array(agentIdSchema),
|
|
249
|
+
reviewerIds: z.array(agentIdSchema),
|
|
250
|
+
reviewCalls: z.number().int().nonnegative().nullable(),
|
|
251
|
+
guardrailReported: guardrailReportSchema.nullable(),
|
|
252
|
+
durationMs: z.number().int().nonnegative().nullable(),
|
|
253
|
+
usage: usageSchema,
|
|
254
|
+
/** Messages sent and received by the request's agents, for the overview. */
|
|
255
|
+
messageCount: z.number().int().nonnegative(),
|
|
256
|
+
/** Messages the user typed directly to one of the request's agents. */
|
|
257
|
+
userMessageCount: z.number().int().nonnegative(),
|
|
258
|
+
/** Tokens and cost per Worker of this request, for the "heaviest Workers" chart. */
|
|
259
|
+
workerUsage: z.array(z.object({ agentId: agentIdSchema, title: z.string().nullable(), usage: usageSchema })),
|
|
260
|
+
/**
|
|
261
|
+
* Tokens and cost per (role, model the agents ran), for the overview's
|
|
262
|
+
* "model × role" chart (delta 20260918 §4.3, REQ-058e). Always sent by this
|
|
263
|
+
* server; optional so an older payload still parses.
|
|
264
|
+
*/
|
|
265
|
+
usageByModelRole: z
|
|
266
|
+
.array(z.object({ role: agentRoleSchema, model: z.string().nullable(), usage: usageSchema }))
|
|
267
|
+
.optional(),
|
|
268
|
+
beadCounts: z.object({
|
|
269
|
+
created: beadCountSchema,
|
|
270
|
+
updated: beadCountSchema,
|
|
271
|
+
closed: beadCountSchema,
|
|
272
|
+
ready: beadCountSchema,
|
|
273
|
+
}),
|
|
274
|
+
tier: tierSchema.nullable(),
|
|
275
|
+
linking: confidenceSchema,
|
|
276
|
+
agentsMissing: z.array(agentIdSchema),
|
|
277
|
+
workspaceState: workspaceStateSchema,
|
|
278
|
+
reassignedFrom: workspaceIdSchema.nullable(),
|
|
279
|
+
notices: z.array(z.string()),
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
/** Milestone of a `BM-REPORT` block (roles/worker.md, Reporting). */
|
|
283
|
+
export const reportPhaseSchema = z.enum([
|
|
284
|
+
"received",
|
|
285
|
+
"documents-done",
|
|
286
|
+
"beads-done",
|
|
287
|
+
"bead-implemented",
|
|
288
|
+
"blocked",
|
|
289
|
+
"finished",
|
|
290
|
+
]);
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* One parsed `BM-REPORT`. Every field is nullable on purpose: the parser is
|
|
294
|
+
* required to be tolerant, and a field it could not read becomes "không rõ"
|
|
295
|
+
* rather than breaking the trace (REQ-050a).
|
|
296
|
+
*/
|
|
297
|
+
export const parsedReportSchema = z.object({
|
|
298
|
+
agentId: agentIdSchema,
|
|
299
|
+
at: z.string(),
|
|
300
|
+
requestId: z.string().nullable(),
|
|
301
|
+
phase: reportPhaseSchema.nullable(),
|
|
302
|
+
tier: tierSchema.nullable(),
|
|
303
|
+
filesChanged: z.array(z.string()),
|
|
304
|
+
beadsCreated: z.array(z.string()),
|
|
305
|
+
beadsUpdated: z.array(z.string()),
|
|
306
|
+
beadsClosed: z.array(z.string()),
|
|
307
|
+
beadsReady: z.array(z.string()),
|
|
308
|
+
reviewFindingsOpen: z.string().nullable(),
|
|
309
|
+
buildAndTests: z.string().nullable(),
|
|
310
|
+
/** Skills the Worker loaded for the request (delta 20260917 §4.9); defaulted for older records. */
|
|
311
|
+
skillsUsed: z.array(z.string()).default([]),
|
|
312
|
+
blockers: z.string().nullable(),
|
|
313
|
+
guardrail: guardrailReportSchema.nullable(),
|
|
314
|
+
unparsedFields: z.array(z.string()),
|
|
315
|
+
/**
|
|
316
|
+
* Bead-id list fields the parser could not fully read (delta 20260917 §5.1):
|
|
317
|
+
* their ids are a lower bound. Defaulted so records written before the field
|
|
318
|
+
* existed still pass `traceRecordSchema` (the store drops undeclared keys).
|
|
319
|
+
*/
|
|
320
|
+
incompleteFields: z.array(z.string()).default([]),
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
/** One parsed `BM-REVIEW` from a Reviewer (roles/reviewer.md). */
|
|
324
|
+
export const parsedReviewSchema = z.object({
|
|
325
|
+
agentId: agentIdSchema,
|
|
326
|
+
at: z.string(),
|
|
327
|
+
batchId: z.string().nullable(),
|
|
328
|
+
verdict: z.string().nullable(),
|
|
329
|
+
blockingCount: z.number().int().nonnegative().nullable(),
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
/** A message the Dashboard shows as "sent" or "received" (REQ-043a, REQ-043b). */
|
|
333
|
+
export const traceMessageSchema = z.object({
|
|
334
|
+
agentId: agentIdSchema.nullable(),
|
|
335
|
+
at: z.string(),
|
|
336
|
+
text: z.string(),
|
|
337
|
+
truncated: z.boolean(),
|
|
338
|
+
/**
|
|
339
|
+
* Who wrote an inbound message: `user` when Paseo's app sent it (the
|
|
340
|
+
* timeline item carries `clientMessageId`), `agent` when another agent sent
|
|
341
|
+
* it with `send_agent_prompt`. Absent on records written before this field
|
|
342
|
+
* existed — never read that as "user".
|
|
343
|
+
*/
|
|
344
|
+
origin: z.enum(["user", "agent"]).optional(),
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
/** Timing of one agent inside a trace (design §7.1). */
|
|
348
|
+
export const agentTimingSchema = z.object({
|
|
349
|
+
agentId: agentIdSchema,
|
|
350
|
+
role: agentRoleSchema,
|
|
351
|
+
startedAt: z.string().nullable(),
|
|
352
|
+
lastActivityAt: z.string().nullable(),
|
|
353
|
+
ms: z.number().int().nonnegative().nullable(),
|
|
354
|
+
state: traceStateSchema,
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
/** Timing of one Manager turn (design §7.1). */
|
|
358
|
+
export const turnTimingSchema = z.object({
|
|
359
|
+
turnId: z.string().nullable(),
|
|
360
|
+
startedAt: z.string().nullable(),
|
|
361
|
+
endedAt: z.string().nullable(),
|
|
362
|
+
ms: z.number().int().nonnegative().nullable(),
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* The twelve fixed feature-workflow steps the Dashboard reports on (REQ-045a;
|
|
367
|
+
* `review_plan` added by delta 20260917-workflow-skills §5.5).
|
|
368
|
+
*/
|
|
369
|
+
export const workflowStepSchema = z.enum([
|
|
370
|
+
"classify_tier",
|
|
371
|
+
"prd",
|
|
372
|
+
"design",
|
|
373
|
+
"adr",
|
|
374
|
+
"plan",
|
|
375
|
+
"review_plan",
|
|
376
|
+
"convert_to_beads",
|
|
377
|
+
"polish_beads",
|
|
378
|
+
"implement",
|
|
379
|
+
"review_batches",
|
|
380
|
+
"build_and_tests",
|
|
381
|
+
"close_with_evidence",
|
|
382
|
+
]);
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* One row of the workflow table. `skipped` is only legal when the Worker stated
|
|
386
|
+
* a tier that REQ-036 allows to skip that step; everything else is `unknown`
|
|
387
|
+
* (REQ-045d) — the rule that keeps the table from accusing a good run.
|
|
388
|
+
*/
|
|
389
|
+
export const workflowStepResultSchema = z.object({
|
|
390
|
+
step: workflowStepSchema,
|
|
391
|
+
status: z.enum(["done", "skipped", "unknown"]),
|
|
392
|
+
confidence: confidenceSchema,
|
|
393
|
+
evidence: z.array(evidenceSchema),
|
|
394
|
+
note: z.string().nullable(),
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
/** A bead the trace touched, with its current state read from the store (REQ-044). */
|
|
398
|
+
export const traceBeadSchema = z.object({
|
|
399
|
+
id: z.string().min(1),
|
|
400
|
+
title: z.string().nullable(),
|
|
401
|
+
statusNow: z.string().nullable(),
|
|
402
|
+
action: z.enum(["created", "updated", "closed", "ready"]),
|
|
403
|
+
confidence: confidenceSchema,
|
|
404
|
+
evidence: z.array(evidenceSchema),
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* A provider-internal sub-agent seen only as a tool-call trace. Paseo 0.8 gives
|
|
409
|
+
* plugins no way to list them (`listProviderSubagents` is `DaemonClient`-only),
|
|
410
|
+
* so these are counted as traces, and labelled as such (REQ-042e).
|
|
411
|
+
*/
|
|
412
|
+
export const subAgentTraceSchema = z.object({
|
|
413
|
+
agentId: agentIdSchema,
|
|
414
|
+
subAgentType: z.string().nullable(),
|
|
415
|
+
description: z.string().nullable(),
|
|
416
|
+
count: z.number().int().nonnegative(),
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
/** Full detail of one trace (design §4.3). */
|
|
420
|
+
/**
|
|
421
|
+
* One combination of model, thinking option and mode an agent ran on, and in
|
|
422
|
+
* how many turns (delta 20260918 §4.3, REQ-058 a–c). `recorded: false` means the
|
|
423
|
+
* turn predates the collector recording it (or its snapshot could not be read):
|
|
424
|
+
* the model then comes from `usage` and thinking/mode are unknown — which is not
|
|
425
|
+
* the same as `recorded: true` with `thinkingOptionId: null`, the provider's default.
|
|
426
|
+
*/
|
|
427
|
+
export const runtimeRowSchema = z.object({
|
|
428
|
+
model: z.string().nullable(),
|
|
429
|
+
thinkingOptionId: z.string().nullable(),
|
|
430
|
+
modeId: z.string().nullable(),
|
|
431
|
+
recorded: z.boolean(),
|
|
432
|
+
turns: z.number().int().positive(),
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
export const traceDetailSchema = traceSummarySchema.extend({
|
|
436
|
+
sent: z.object({
|
|
437
|
+
userRequest: traceMessageSchema.nullable(),
|
|
438
|
+
workerInitialPrompts: z.array(traceMessageSchema),
|
|
439
|
+
reviewRequests: z.array(traceMessageSchema.extend({ batchId: z.string().nullable() })),
|
|
440
|
+
}),
|
|
441
|
+
received: z.object({
|
|
442
|
+
reports: z.array(parsedReportSchema),
|
|
443
|
+
reviews: z.array(parsedReviewSchema),
|
|
444
|
+
managerReplies: z.array(traceMessageSchema),
|
|
445
|
+
}),
|
|
446
|
+
timing: z.object({
|
|
447
|
+
totalMs: z.number().int().nonnegative().nullable(),
|
|
448
|
+
managerTurns: z.array(turnTimingSchema),
|
|
449
|
+
workers: z.array(agentTimingSchema),
|
|
450
|
+
reviewers: z.array(agentTimingSchema),
|
|
451
|
+
basis: z.string(),
|
|
452
|
+
}),
|
|
453
|
+
usageByAgent: z.array(
|
|
454
|
+
z.object({
|
|
455
|
+
agentId: agentIdSchema,
|
|
456
|
+
role: agentRoleSchema,
|
|
457
|
+
usage: usageSchema,
|
|
458
|
+
/** What this agent ran on, one row per distinct combination (delta 20260918 §4.3). */
|
|
459
|
+
runtime: z.array(runtimeRowSchema).optional(),
|
|
460
|
+
}),
|
|
461
|
+
),
|
|
462
|
+
/** Tokens and cost per model the agents actually ran (delta 20260918 §4.3, REQ-058d). */
|
|
463
|
+
usageByModel: z.array(z.object({ model: z.string().nullable(), usage: usageSchema })).optional(),
|
|
464
|
+
beads: z.array(traceBeadSchema),
|
|
465
|
+
workflowSteps: z.array(workflowStepResultSchema),
|
|
466
|
+
subAgentTraces: z.array(subAgentTraceSchema),
|
|
467
|
+
/** Messages the user typed directly to an agent of this request, oldest first. */
|
|
468
|
+
userMessages: z.array(traceMessageSchema),
|
|
469
|
+
/** Skills each agent loaded, oldest first. */
|
|
470
|
+
skills: z.array(z.object({ agentId: agentIdSchema, skill: z.string(), at: z.string().nullable() })),
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Bead statistics of one workspace (REQ-046). `present: false` means the
|
|
475
|
+
* workspace has no `.beads/issues.jsonl` — an empty state, not an error.
|
|
476
|
+
*/
|
|
477
|
+
export const beadStatsSchema = z.object({
|
|
478
|
+
total: z.number().int().nonnegative(),
|
|
479
|
+
open: z.number().int().nonnegative(),
|
|
480
|
+
inProgress: z.number().int().nonnegative(),
|
|
481
|
+
blocked: z.number().int().nonnegative(),
|
|
482
|
+
closed: z.number().int().nonnegative(),
|
|
483
|
+
ready: z.number().int().nonnegative(),
|
|
484
|
+
readAt: z.string(),
|
|
485
|
+
source: z.string(),
|
|
486
|
+
skippedLines: z.number().int().nonnegative(),
|
|
487
|
+
present: z.boolean(),
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
/** Size of the trace store, measured with `stat` and never by reading content. */
|
|
491
|
+
export const storeSizeSchema = z.object({
|
|
492
|
+
bytes: z.number().int().nonnegative(),
|
|
493
|
+
workspaceBytes: z.number().int().nonnegative(),
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
// ---------------------------------------------------------------------------
|
|
497
|
+
// Persisted format, schema version 1 (design §3.2, §3.3).
|
|
498
|
+
//
|
|
499
|
+
// These shapes live on disk under `<install home>/traces/`. A reader that meets
|
|
500
|
+
// a higher `schemaVersion` reads what it understands and refuses to write
|
|
501
|
+
// (`E_TRACE_STORE_SCHEMA_TOO_NEW`), so a new record must only ever *add*
|
|
502
|
+
// optional fields.
|
|
503
|
+
// ---------------------------------------------------------------------------
|
|
504
|
+
|
|
505
|
+
/** Current version of the persisted trace record and store metadata. */
|
|
506
|
+
export const TRACE_STORE_SCHEMA_VERSION = 1;
|
|
507
|
+
|
|
508
|
+
/** `<install home>/traces/meta.json`. */
|
|
509
|
+
export const traceStoreMetaSchema = z.object({
|
|
510
|
+
schemaVersion: z.number().int().positive(),
|
|
511
|
+
createdAt: z.string(),
|
|
512
|
+
updatedAt: z.string(),
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
/** `<install home>/traces/<workspaceId>/meta.json` — lets an orphaned workspace still be recognisable (REQ-057a). */
|
|
516
|
+
export const traceWorkspaceMetaSchema = z.object({
|
|
517
|
+
lastKnownName: z.string().nullable(),
|
|
518
|
+
lastKnownDirectory: z.string().nullable(),
|
|
519
|
+
lastSeenAt: z.string(),
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* What the agent actually ran on during one turn (delta 20260918 §4.2): the
|
|
524
|
+
* running values the provider reports (`runtimeInfo`) first, the snapshot's
|
|
525
|
+
* configuration only as a fallback. `thinkingOptionId: null` means the
|
|
526
|
+
* provider's default.
|
|
527
|
+
*
|
|
528
|
+
* `provider` was added by delta 20260921 §4.2.7 (F7) so a model missing from
|
|
529
|
+
* the bundled price table can be priced from its provider's model list. It is
|
|
530
|
+
* optional for the same reason `runtime` is: records written before it, and
|
|
531
|
+
* readers built before it, keep working — `v` stays 1, nothing migrates. `null`
|
|
532
|
+
* when the snapshot names no provider.
|
|
533
|
+
*/
|
|
534
|
+
export const traceRuntimeSchema = z.object({
|
|
535
|
+
model: z.string().nullable(),
|
|
536
|
+
thinkingOptionId: z.string().nullable(),
|
|
537
|
+
modeId: z.string().nullable(),
|
|
538
|
+
provider: z.string().nullable().optional(),
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
/** One line of `events-<YYYYMM>.jsonl`: everything one agent turn produced. */
|
|
542
|
+
export const traceRecordSchema = z.object({
|
|
543
|
+
v: z.number().int().positive(),
|
|
544
|
+
kind: z.literal("turn"),
|
|
545
|
+
at: z.string(),
|
|
546
|
+
workspaceId: workspaceIdSchema,
|
|
547
|
+
agentId: agentIdSchema,
|
|
548
|
+
role: agentRoleSchema,
|
|
549
|
+
turnId: z.string().nullable(),
|
|
550
|
+
requestId: z.string().nullable(),
|
|
551
|
+
parentAgentId: agentIdSchema.nullable(),
|
|
552
|
+
agentCreatedAt: z.string().nullable(),
|
|
553
|
+
startedAt: z.string().nullable(),
|
|
554
|
+
endedAt: z.string(),
|
|
555
|
+
outcome: z.enum(["completed", "failed", "canceled"]),
|
|
556
|
+
sent: z.array(traceMessageSchema),
|
|
557
|
+
received: z.array(traceMessageSchema),
|
|
558
|
+
reports: z.array(parsedReportSchema),
|
|
559
|
+
reviews: z.array(parsedReviewSchema),
|
|
560
|
+
evidence: z.array(evidenceSchema),
|
|
561
|
+
usage: usageSchema.nullable(),
|
|
562
|
+
/**
|
|
563
|
+
* Added by delta 20260918 — optional, so records written before it (and
|
|
564
|
+
* readers built before it) keep working: `v` stays 1, nothing migrates. `null`
|
|
565
|
+
* when the snapshot could not be read for this turn.
|
|
566
|
+
*/
|
|
567
|
+
runtime: traceRuntimeSchema.nullable().optional(),
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
// ---------------------------------------------------------------------------
|
|
571
|
+
// Error codes.
|
|
572
|
+
//
|
|
573
|
+
// Registered in the single product-wide registry (design gốc §4.4, delta
|
|
574
|
+
// `design-delta-20260916-trace-store`). They travel over the plugin RPC channel
|
|
575
|
+
// so they have no CLI exit code.
|
|
576
|
+
// ---------------------------------------------------------------------------
|
|
577
|
+
|
|
578
|
+
export const DASHBOARD_ERROR_CODES = [
|
|
579
|
+
"E_TIMELINE_UNAVAILABLE",
|
|
580
|
+
"E_BEADS_STORE_UNREADABLE",
|
|
581
|
+
"E_TRACE_NOT_FOUND",
|
|
582
|
+
"E_TRACE_STORE_UNWRITABLE",
|
|
583
|
+
"E_TRACE_STORE_SCHEMA_TOO_NEW",
|
|
584
|
+
"E_TRACE_REASSIGN_INVALID",
|
|
585
|
+
"E_BEAD_NOT_FOUND",
|
|
586
|
+
"E_ROLE_EXTRA_INVALID",
|
|
587
|
+
"E_TOOL_PRESENT",
|
|
588
|
+
"E_TOOL_INSTALL_FAILED",
|
|
589
|
+
// Delta 20260921 §4.3.3–§4.3.4 (ADR-008): the plugin's own writes of the role settings.
|
|
590
|
+
"E_ROLE_SETTINGS_INVALID",
|
|
591
|
+
"E_ROLE_SETTINGS_CONFLICT",
|
|
592
|
+
"E_ROLE_SETTINGS_WRITE_FAILED",
|
|
593
|
+
// Delta 20260921 §4.4.6: the fallback card's actions.
|
|
594
|
+
"E_FALLBACK_NOT_FOUND",
|
|
595
|
+
"E_FALLBACK_NOT_PENDING",
|
|
596
|
+
"E_FALLBACK_NO_CANDIDATE",
|
|
597
|
+
"E_FALLBACK_NO_RESET",
|
|
598
|
+
"E_FALLBACK_CREATE_FAILED",
|
|
599
|
+
] as const;
|
|
600
|
+
|
|
601
|
+
export type DashboardErrorCode = (typeof DASHBOARD_ERROR_CODES)[number];
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Coded failure of a Dashboard RPC. The message starts with the code so it
|
|
605
|
+
* survives transports that only forward `message`, exactly like
|
|
606
|
+
* `ManagerEnsureError` does for `manager.ensure`.
|
|
607
|
+
*/
|
|
608
|
+
export class DashboardError extends Error {
|
|
609
|
+
readonly code: DashboardErrorCode;
|
|
610
|
+
|
|
611
|
+
constructor(code: DashboardErrorCode, detail: string, options?: { cause?: unknown }) {
|
|
612
|
+
super(`${code}: ${detail}`, options);
|
|
613
|
+
this.name = "DashboardError";
|
|
614
|
+
this.code = code;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// ---------------------------------------------------------------------------
|
|
619
|
+
// RPC contracts (design §5). All five are new; the three Phase 1 contracts
|
|
620
|
+
// above are unchanged.
|
|
621
|
+
// ---------------------------------------------------------------------------
|
|
622
|
+
|
|
623
|
+
/** Largest page `traces.list` will return, and its default (REQ-049a, Q-034). */
|
|
624
|
+
export const TRACE_LIST_LIMIT = 50;
|
|
625
|
+
|
|
626
|
+
/** `traces.list` — one page of trace rows for a workspace, newest first. */
|
|
627
|
+
export const tracesListRpc = defineRpc({
|
|
628
|
+
name: "traces.list",
|
|
629
|
+
input: z.object({
|
|
630
|
+
workspaceId: workspaceIdSchema,
|
|
631
|
+
limit: z.number().int().positive().max(TRACE_LIST_LIMIT).optional(),
|
|
632
|
+
cursor: z.string().min(1).optional(),
|
|
633
|
+
}),
|
|
634
|
+
output: z.object({
|
|
635
|
+
traces: z.array(traceSummarySchema),
|
|
636
|
+
nextCursor: z.string().nullable(),
|
|
637
|
+
truncated: z.boolean(),
|
|
638
|
+
store: storeSizeSchema,
|
|
639
|
+
notices: z.array(z.string()),
|
|
640
|
+
}),
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
/** `traces.get` — full detail of one trace; unknown id fails `E_TRACE_NOT_FOUND`. */
|
|
644
|
+
export const tracesGetRpc = defineRpc({
|
|
645
|
+
name: "traces.get",
|
|
646
|
+
input: z.object({
|
|
647
|
+
workspaceId: workspaceIdSchema,
|
|
648
|
+
traceId: z.string().min(1),
|
|
649
|
+
}),
|
|
650
|
+
output: z.object({
|
|
651
|
+
trace: traceDetailSchema,
|
|
652
|
+
}),
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Scope of a deletion. Exactly one of the three shapes (REQ-054a); the union is
|
|
657
|
+
* what stops a caller from half-specifying a destructive operation.
|
|
658
|
+
*/
|
|
659
|
+
export const traceDeleteScopeSchema = z.union([
|
|
660
|
+
z.object({ traceId: z.string().min(1) }),
|
|
661
|
+
z.object({ before: z.string().min(1) }),
|
|
662
|
+
z.object({ allOfWorkspace: z.literal(true) }),
|
|
663
|
+
]);
|
|
664
|
+
|
|
665
|
+
/** `traces.delete` — `dryRun: true` only counts, so the UI can confirm first. */
|
|
666
|
+
export const tracesDeleteRpc = defineRpc({
|
|
667
|
+
name: "traces.delete",
|
|
668
|
+
input: z.object({
|
|
669
|
+
workspaceId: workspaceIdSchema,
|
|
670
|
+
scope: traceDeleteScopeSchema,
|
|
671
|
+
dryRun: z.boolean().optional(),
|
|
672
|
+
}),
|
|
673
|
+
output: z.object({
|
|
674
|
+
deleted: z.object({
|
|
675
|
+
traces: z.number().int().nonnegative(),
|
|
676
|
+
bytes: z.number().int().nonnegative(),
|
|
677
|
+
/** Requests in scope that still have a running agent (REQ-054e). */
|
|
678
|
+
running: z.number().int().nonnegative(),
|
|
679
|
+
}),
|
|
680
|
+
store: storeSizeSchema,
|
|
681
|
+
}),
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* `traces.reassign` — move the traces of a workspace that is gone onto one that
|
|
686
|
+
* exists (REQ-057d). Never automatic: only a user action reaches this RPC.
|
|
687
|
+
*/
|
|
688
|
+
export const tracesReassignRpc = defineRpc({
|
|
689
|
+
name: "traces.reassign",
|
|
690
|
+
input: z.object({
|
|
691
|
+
fromWorkspaceId: workspaceIdSchema,
|
|
692
|
+
toWorkspaceId: workspaceIdSchema,
|
|
693
|
+
dryRun: z.boolean().optional(),
|
|
694
|
+
}),
|
|
695
|
+
output: z.object({
|
|
696
|
+
moved: z.object({
|
|
697
|
+
traces: z.number().int().nonnegative(),
|
|
698
|
+
bytes: z.number().int().nonnegative(),
|
|
699
|
+
}),
|
|
700
|
+
store: storeSizeSchema,
|
|
701
|
+
}),
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
/** `beads.stats` — counts of the workspace's bead store; missing file is not an error. */
|
|
705
|
+
export const beadsStatsRpc = defineRpc({
|
|
706
|
+
name: "beads.stats",
|
|
707
|
+
input: z.object({
|
|
708
|
+
workspaceId: workspaceIdSchema,
|
|
709
|
+
}),
|
|
710
|
+
output: z.object({
|
|
711
|
+
stats: beadStatsSchema,
|
|
712
|
+
}),
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
/** One bead in the Beads screen list (delta 20260916-beads-screen). */
|
|
716
|
+
/**
|
|
717
|
+
* `workspaces.overview` — per listed workspace: its bead counts (null when the
|
|
718
|
+
* workspace has no readable bead store) and how many Workers are running now.
|
|
719
|
+
* One call for the whole Beads Manager screen.
|
|
720
|
+
*/
|
|
721
|
+
export const workspacesOverviewRpc = defineRpc({
|
|
722
|
+
name: "workspaces.overview",
|
|
723
|
+
input: z.object({}),
|
|
724
|
+
output: z.object({
|
|
725
|
+
workspaces: z.array(
|
|
726
|
+
z.object({
|
|
727
|
+
workspaceId: workspaceIdSchema,
|
|
728
|
+
beads: z
|
|
729
|
+
.object({
|
|
730
|
+
total: z.number().int().nonnegative(),
|
|
731
|
+
inProgress: z.number().int().nonnegative(),
|
|
732
|
+
blocked: z.number().int().nonnegative(),
|
|
733
|
+
ready: z.number().int().nonnegative(),
|
|
734
|
+
})
|
|
735
|
+
.nullable(),
|
|
736
|
+
/** Kept for readers that predate `runningAgents`; equals `runningAgents.worker`. */
|
|
737
|
+
runningWorkers: z.number().int().nonnegative(),
|
|
738
|
+
/** Running agents of this workspace, per role (delta 20260917e §4.2). */
|
|
739
|
+
runningAgents: z.object({
|
|
740
|
+
manager: z.number().int().nonnegative(),
|
|
741
|
+
worker: z.number().int().nonnegative(),
|
|
742
|
+
reviewer: z.number().int().nonnegative(),
|
|
743
|
+
}),
|
|
744
|
+
}),
|
|
745
|
+
),
|
|
746
|
+
}),
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
export type WorkspaceOverview = z.infer<typeof workspacesOverviewRpc.output>["workspaces"][number];
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* `agents.stop-all` — asks every running Worker and Reviewer of one workspace to
|
|
753
|
+
* stop (delta 20260917e §4.4). It ASKS: Paseo gives plugins no agent cancel, so
|
|
754
|
+
* the counts below are notices delivered, not turns killed.
|
|
755
|
+
*/
|
|
756
|
+
export const agentsStopAllRpc = defineRpc({
|
|
757
|
+
name: "agents.stop-all",
|
|
758
|
+
input: z.object({ workspaceId: workspaceIdSchema }),
|
|
759
|
+
output: z.object({
|
|
760
|
+
workers: z.number().int().nonnegative(),
|
|
761
|
+
reviewers: z.number().int().nonnegative(),
|
|
762
|
+
skipped: z.number().int().nonnegative(),
|
|
763
|
+
}),
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
const answerMarksOutput = z.object({
|
|
767
|
+
/** Card keys (`answeredKey`) the user marked as answered, oldest first. */
|
|
768
|
+
keys: z.array(z.string()),
|
|
769
|
+
notices: z.array(z.string()),
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
/** `answers.marks` — the cards the user marked as answered (delta 20260918d §4.9). */
|
|
773
|
+
export const answersMarksRpc = defineRpc({
|
|
774
|
+
name: "answers.marks",
|
|
775
|
+
input: z.object({}),
|
|
776
|
+
output: answerMarksOutput,
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
/** `answers.mark` — marks one card as answered, or removes the mark (delta 20260918d §4.9). */
|
|
780
|
+
export const answersMarkRpc = defineRpc({
|
|
781
|
+
name: "answers.mark",
|
|
782
|
+
input: z.object({ key: z.string().min(1).max(400), marked: z.boolean() }),
|
|
783
|
+
output: answerMarksOutput,
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
// ---------------------------------------------------------------------------
|
|
787
|
+
// Setup screen (delta 20260916-setup-screen).
|
|
788
|
+
// ---------------------------------------------------------------------------
|
|
789
|
+
|
|
790
|
+
export const setupRoleSchema = z.enum(["manager", "worker", "reviewer"]);
|
|
791
|
+
const skillStateSchema = z.enum(["ok", "missing", "broken"]);
|
|
792
|
+
|
|
793
|
+
/** One Paseo-tools check (`plugin/server/tools-check.ts`). */
|
|
794
|
+
export const toolsSeenSchema = z.object({
|
|
795
|
+
state: z.enum(["ok", "missing", "unknown"]),
|
|
796
|
+
agentId: z.string(),
|
|
797
|
+
provider: z.string(),
|
|
798
|
+
at: z.string(),
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
export const setupStatusSchema = z.object({
|
|
802
|
+
tools: z.array(
|
|
803
|
+
z.object({
|
|
804
|
+
id: z.enum(["br", "bv", "bd"]),
|
|
805
|
+
name: z.string(),
|
|
806
|
+
purpose: z.string(),
|
|
807
|
+
required: z.boolean(),
|
|
808
|
+
path: z.string().nullable(),
|
|
809
|
+
version: z.string().nullable(),
|
|
810
|
+
latestKnown: z.string().nullable(),
|
|
811
|
+
installCommand: z.string().nullable(),
|
|
812
|
+
updateCommand: z.string().nullable(),
|
|
813
|
+
homepage: z.string(),
|
|
814
|
+
}),
|
|
815
|
+
),
|
|
816
|
+
latestCheckedOn: z.string(),
|
|
817
|
+
/**
|
|
818
|
+
* `pi` and `opencode` (delta 20260921 §4.2.6) are optional so a payload
|
|
819
|
+
* from before them still parses; a client shows those columns only when
|
|
820
|
+
* they are present.
|
|
821
|
+
*/
|
|
822
|
+
skills: z.object({
|
|
823
|
+
checkedAt: z.string(),
|
|
824
|
+
dirs: z.object({
|
|
825
|
+
shared: z.string(),
|
|
826
|
+
claude: z.string(),
|
|
827
|
+
codex: z.string(),
|
|
828
|
+
pi: z.string().optional(),
|
|
829
|
+
opencode: z.string().optional(),
|
|
830
|
+
}),
|
|
831
|
+
skills: z.array(
|
|
832
|
+
z.object({
|
|
833
|
+
name: z.string(),
|
|
834
|
+
required: z.boolean(),
|
|
835
|
+
claude: skillStateSchema,
|
|
836
|
+
codex: skillStateSchema,
|
|
837
|
+
pi: skillStateSchema.optional(),
|
|
838
|
+
opencode: skillStateSchema.optional(),
|
|
839
|
+
problem: z.string().nullable(),
|
|
840
|
+
}),
|
|
841
|
+
),
|
|
842
|
+
missingRequired: z.object({
|
|
843
|
+
claude: z.number().int(),
|
|
844
|
+
codex: z.number().int(),
|
|
845
|
+
pi: z.number().int().optional(),
|
|
846
|
+
opencode: z.number().int().optional(),
|
|
847
|
+
}),
|
|
848
|
+
installCommand: z.string(),
|
|
849
|
+
}),
|
|
850
|
+
/** Characters of additional instructions per role; 0 when none. */
|
|
851
|
+
extras: z.object({ manager: z.number().int(), worker: z.number().int(), reviewer: z.number().int() }),
|
|
852
|
+
/**
|
|
853
|
+
* The last Paseo-tools check of a new Manager and of a new Worker in this
|
|
854
|
+
* plugin run, `null` when none ran (delta 20260921 §4.2.4). Optional: an
|
|
855
|
+
* older server does not send it.
|
|
856
|
+
*/
|
|
857
|
+
paseoTools: z
|
|
858
|
+
.object({ manager: toolsSeenSchema.nullable(), worker: toolsSeenSchema.nullable() })
|
|
859
|
+
.optional(),
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
export type SetupStatus = z.infer<typeof setupStatusSchema>;
|
|
863
|
+
|
|
864
|
+
/** `setup.status` — tools, skills and extras at a glance. Read-only; runs `--version` only. */
|
|
865
|
+
export const setupStatusRpc = defineRpc({ name: "setup.status", input: z.object({}), output: setupStatusSchema });
|
|
866
|
+
|
|
867
|
+
/** `setup.install-tool` — runs the documented installer for a missing `br` or `bv`, after the user confirmed. */
|
|
868
|
+
export const setupInstallToolRpc = defineRpc({
|
|
869
|
+
name: "setup.install-tool",
|
|
870
|
+
/** `confirmed` must be `true`: the Setup screen sends it only after the user confirmed the exact command. */
|
|
871
|
+
input: z.object({ tool: z.enum(["br", "bv"]), confirmed: z.literal(true) }),
|
|
872
|
+
output: z.object({ command: z.string(), code: z.number().int(), tail: z.array(z.string()) }),
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
/** `roles.instructions` — a role's base instructions, the user's additions and the result. */
|
|
876
|
+
export const rolesInstructionsRpc = defineRpc({
|
|
877
|
+
name: "roles.instructions",
|
|
878
|
+
input: z.object({ role: setupRoleSchema }),
|
|
879
|
+
output: z.object({ base: z.string(), extra: z.string(), full: z.string(), path: z.string().nullable(), maxChars: z.number().int() }),
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
/** `roles.save-extra` — replaces one role's additional instructions. Applies to agents created afterwards. */
|
|
883
|
+
export const rolesSaveExtraRpc = defineRpc({
|
|
884
|
+
name: "roles.save-extra",
|
|
885
|
+
input: z.object({ role: setupRoleSchema, text: z.string() }),
|
|
886
|
+
output: z.object({ extra: z.string(), full: z.string() }),
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
// ---------------------------------------------------------------------------
|
|
890
|
+
// Roles & models (delta 20260921 §4.3.2, REQ-064 a/b). Read-only; saving is
|
|
891
|
+
// `roles.save-settings` (§4.3.4). `roles.describe` stays for older clients.
|
|
892
|
+
// ---------------------------------------------------------------------------
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* How a provider lets paseo-bm choose a role's start mode (delta 20260921
|
|
896
|
+
* §4.2.1): `tiered` (modes carry a `colorTier`: Claude, Codex), `untiered`
|
|
897
|
+
* (modes without one: OpenCode), `none` (no modes, no error: Pi), `unknown`
|
|
898
|
+
* (the modes could not be read).
|
|
899
|
+
*/
|
|
900
|
+
export const providerCapabilitySchema = z.enum(["tiered", "untiered", "none", "unknown"]);
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* One role as Paseo's configuration has it right now: `baseProvider` and
|
|
904
|
+
* `label` from the derived provider `bm-<role>` (`extends`, `label`); `model`,
|
|
905
|
+
* `thinkingOptionId`, `modeId` and `featureValues` from the agent profile
|
|
906
|
+
* `bm-<role>`. A field the configuration does not set is `null`
|
|
907
|
+
* (`featureValues`: `{}`); `capability` is that of `baseProvider`.
|
|
908
|
+
*/
|
|
909
|
+
export const roleSettingSchema = z.object({
|
|
910
|
+
role: bmRoleSchema,
|
|
911
|
+
providerId: z.enum(["bm-manager", "bm-worker", "bm-reviewer"]),
|
|
912
|
+
baseProvider: z.string().nullable(),
|
|
913
|
+
label: z.string().nullable(),
|
|
914
|
+
model: z.string().nullable(),
|
|
915
|
+
thinkingOptionId: z.string().nullable(),
|
|
916
|
+
modeId: z.string().nullable(),
|
|
917
|
+
featureValues: z.record(z.string(), z.unknown()),
|
|
918
|
+
capability: providerCapabilitySchema,
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
* One entry of a role's fallback chain as the user saves it (delta 20260921
|
|
923
|
+
* §4.4.2–§4.4.3): a BASE provider (never a `bm-*` alias), one of its models,
|
|
924
|
+
* and optional thinking and mode (`null` = not set).
|
|
925
|
+
*/
|
|
926
|
+
export const fallbackEntryInputSchema = z.object({
|
|
927
|
+
baseProvider: z.string().min(1).max(200),
|
|
928
|
+
model: z.string().min(1).max(200),
|
|
929
|
+
thinkingOptionId: z.string().min(1).max(200).nullable(),
|
|
930
|
+
modeId: z.string().min(1).max(200).nullable(),
|
|
931
|
+
});
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* A role's fallback chain as Roles & models shows it: the policy (`ask`
|
|
935
|
+
* shows a card when the role hits a plan limit, `off` does nothing; `auto`
|
|
936
|
+
* only from phase 2a-18), the entries in order with the alias each runs on
|
|
937
|
+
* (`bm-<role>-fallback-<position>`), the capability and listed price of each
|
|
938
|
+
* entry's provider and model, and whether detection patterns come from the
|
|
939
|
+
* user's `role-fallback.json`.
|
|
940
|
+
*/
|
|
941
|
+
export const fallbackSettingsSchema = z.object({
|
|
942
|
+
role: bmRoleSchema,
|
|
943
|
+
policy: z.enum(["ask", "off", "auto"]),
|
|
944
|
+
entries: z.array(
|
|
945
|
+
fallbackEntryInputSchema.extend({
|
|
946
|
+
position: z.number().int().min(1).max(3),
|
|
947
|
+
alias: z.string(),
|
|
948
|
+
capability: providerCapabilitySchema,
|
|
949
|
+
cost: modelPriceSchema.nullable(),
|
|
950
|
+
}),
|
|
951
|
+
),
|
|
952
|
+
patternsFromFile: z.boolean(),
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* `roles.settings` — the three roles, always in the order manager, worker,
|
|
957
|
+
* reviewer. `revision` is what `roles.save-settings` must send back: sha256 of
|
|
958
|
+
* the canonical JSON of every `bm-*` provider and the whole profile array
|
|
959
|
+
* (§4.3.2). `fallback` holds the chain of each role whose chain is offered
|
|
960
|
+
* (`FALLBACK_ROLES`, §4.4.3); `null` when none is.
|
|
961
|
+
* `warnings` are English sentences for the user, e.g. the shared-plan warning
|
|
962
|
+
* when the Manager and the Worker extend the same base provider.
|
|
963
|
+
*/
|
|
964
|
+
export const rolesSettingsRpc = defineRpc({
|
|
965
|
+
name: "roles.settings",
|
|
966
|
+
input: z.object({}),
|
|
967
|
+
output: z.object({
|
|
968
|
+
revision: z.string(),
|
|
969
|
+
roles: z.array(roleSettingSchema),
|
|
970
|
+
fallback: z
|
|
971
|
+
.object({
|
|
972
|
+
manager: fallbackSettingsSchema.optional(),
|
|
973
|
+
worker: fallbackSettingsSchema.optional(),
|
|
974
|
+
reviewer: fallbackSettingsSchema.optional(),
|
|
975
|
+
})
|
|
976
|
+
.nullable(),
|
|
977
|
+
warnings: z.array(z.string()),
|
|
978
|
+
/** The base providers Paseo reports as available (never a `bm-*` alias), for the Edit form's Provider picker. */
|
|
979
|
+
providers: z.array(z.string()),
|
|
980
|
+
}),
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
/** A model a role can run, as `providers.listModels` lists it; `cost` from its `metadata.cost` (§4.2.7). */
|
|
984
|
+
export const roleModelOptionSchema = z.object({
|
|
985
|
+
id: z.string(),
|
|
986
|
+
label: z.string(),
|
|
987
|
+
thinkingOptions: z.array(z.object({ id: z.string(), label: z.string() })),
|
|
988
|
+
defaultThinkingOptionId: z.string().nullable(),
|
|
989
|
+
cost: modelPriceSchema.nullable(),
|
|
990
|
+
});
|
|
991
|
+
|
|
992
|
+
/** A mode as `providers.listModes` lists it; `colorTier` is `null` when the provider gives none. */
|
|
993
|
+
export const roleModeOptionSchema = z.object({
|
|
994
|
+
id: z.string(),
|
|
995
|
+
label: z.string(),
|
|
996
|
+
colorTier: z.string().nullable(),
|
|
997
|
+
});
|
|
998
|
+
|
|
999
|
+
/**
|
|
1000
|
+
* `roles.options` — what the Edit form of Roles & models may offer for one
|
|
1001
|
+
* BASE provider (never a `bm-*` alias: refused with `E_ROLE_SETTINGS_INVALID`).
|
|
1002
|
+
* Only values Paseo lists; a list Paseo cannot give is empty. `autoAccept` is
|
|
1003
|
+
* true when an `untiered` provider offers the `auto_accept` toggle.
|
|
1004
|
+
*/
|
|
1005
|
+
export const rolesOptionsRpc = defineRpc({
|
|
1006
|
+
name: "roles.options",
|
|
1007
|
+
input: z.object({ provider: z.string().min(1) }),
|
|
1008
|
+
output: z.object({
|
|
1009
|
+
provider: z.string(),
|
|
1010
|
+
capability: providerCapabilitySchema,
|
|
1011
|
+
models: z.array(roleModelOptionSchema),
|
|
1012
|
+
modes: z.array(roleModeOptionSchema),
|
|
1013
|
+
autoAccept: z.boolean(),
|
|
1014
|
+
}),
|
|
1015
|
+
});
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* `roles.save-settings` — writes one role's base provider, model, thinking and
|
|
1019
|
+
* mode into Paseo's config (delta 20260921 §4.3.2–§4.3.4, ADR-008). `null`
|
|
1020
|
+
* thinking / mode means "not set" (the key is removed). `notified` counts the
|
|
1021
|
+
* live agents told a changed child mode (BM-SETTINGS, §4.3.5).
|
|
1022
|
+
*/
|
|
1023
|
+
export const rolesSaveSettingsRpc = defineRpc({
|
|
1024
|
+
name: "roles.save-settings",
|
|
1025
|
+
input: z.object({
|
|
1026
|
+
revision: z.string().min(1),
|
|
1027
|
+
role: bmRoleSchema,
|
|
1028
|
+
baseProvider: z.string().min(1).max(200),
|
|
1029
|
+
model: z.string().min(1).max(200),
|
|
1030
|
+
thinkingOptionId: z.string().min(1).max(200).nullable(),
|
|
1031
|
+
modeId: z.string().min(1).max(200).nullable(),
|
|
1032
|
+
}),
|
|
1033
|
+
output: z.object({
|
|
1034
|
+
revision: z.string(),
|
|
1035
|
+
role: roleSettingSchema,
|
|
1036
|
+
warnings: z.array(z.string()),
|
|
1037
|
+
notified: z.number().int(),
|
|
1038
|
+
}),
|
|
1039
|
+
});
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* `roles.save-fallback` — saves one role's policy and 0–3 fallback entries
|
|
1043
|
+
* (delta 20260921 §4.4.3, §4.6): the aliases through the config writer (so
|
|
1044
|
+
* `revision` guards them like `roles.save-settings`), then `role-fallback.json`.
|
|
1045
|
+
*/
|
|
1046
|
+
export const rolesSaveFallbackRpc = defineRpc({
|
|
1047
|
+
name: "roles.save-fallback",
|
|
1048
|
+
input: z.object({
|
|
1049
|
+
revision: z.string().min(1),
|
|
1050
|
+
role: bmRoleSchema,
|
|
1051
|
+
/** `auto` (REQ-067, phase 2a-18): the plugin decides at once, by the same rules as the card's buttons. */
|
|
1052
|
+
policy: z.enum(["ask", "off", "auto"]),
|
|
1053
|
+
entries: z.array(fallbackEntryInputSchema).max(3),
|
|
1054
|
+
}),
|
|
1055
|
+
output: z.object({
|
|
1056
|
+
revision: z.string(),
|
|
1057
|
+
fallback: fallbackSettingsSchema,
|
|
1058
|
+
warnings: z.array(z.string()),
|
|
1059
|
+
}),
|
|
1060
|
+
});
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* One recorded fallback incident (delta 20260921 §4.4.2, §4.4.5, REQ-065 j):
|
|
1064
|
+
* an agent whose turn ended on a provider-plan failure, what was learnt about
|
|
1065
|
+
* it (class, verbatim message cut to 500 characters, reset time), the next
|
|
1066
|
+
* candidate of its role's chain, and what became of it. Stored in
|
|
1067
|
+
* `<install home>/role-fallback-state.json`.
|
|
1068
|
+
*/
|
|
1069
|
+
export const fallbackIncidentSchema = z.object({
|
|
1070
|
+
id: z.string().regex(/^fb-[0-9a-f]{12}$/),
|
|
1071
|
+
role: bmRoleSchema,
|
|
1072
|
+
workspaceId: z.string(),
|
|
1073
|
+
/** `null` for a Manager, which serves a workspace, not a request. */
|
|
1074
|
+
requestId: z.string().nullable(),
|
|
1075
|
+
agentId: z.string(),
|
|
1076
|
+
agentProvider: z.string(),
|
|
1077
|
+
agentModel: z.string().nullable(),
|
|
1078
|
+
/** The Worker of a Reviewer; the Manager of a Worker; `null` for a Manager. */
|
|
1079
|
+
parentId: z.string().nullable(),
|
|
1080
|
+
/** The chat whose card shows the incident. */
|
|
1081
|
+
managerId: z.string().nullable(),
|
|
1082
|
+
class: z.enum(["L1", "L2", "L4", "L5"]),
|
|
1083
|
+
/** N1 (`failed`) or N2 (`completed`). */
|
|
1084
|
+
signal: z.enum(["failed", "completed"]),
|
|
1085
|
+
message: z.string().max(500),
|
|
1086
|
+
perModelWindow: z.boolean(),
|
|
1087
|
+
resetsAt: z.string().nullable(),
|
|
1088
|
+
candidate: fallbackEntryInputSchema
|
|
1089
|
+
.extend({ position: z.number().int().min(1).max(3), alias: z.string() })
|
|
1090
|
+
.nullable(),
|
|
1091
|
+
status: z.enum(["pending", "switched", "waiting", "resumed", "dismissed", "exhausted", "expired", "failed"]),
|
|
1092
|
+
detectedAt: z.string(),
|
|
1093
|
+
decidedAt: z.string().nullable(),
|
|
1094
|
+
waitUntil: z.string().nullable(),
|
|
1095
|
+
replacementId: z.string().nullable(),
|
|
1096
|
+
error: z.string().nullable(),
|
|
1097
|
+
});
|
|
1098
|
+
|
|
1099
|
+
/**
|
|
1100
|
+
* `fallback.incidents` — the recorded incidents (§4.4.6), oldest first,
|
|
1101
|
+
* filtered by workspace and/or ids when given. The fallback card and the
|
|
1102
|
+
* waiting pill read their state here, never from the notice text, so an old
|
|
1103
|
+
* notice never shows a button that no longer applies.
|
|
1104
|
+
*/
|
|
1105
|
+
export const fallbackIncidentsRpc = defineRpc({
|
|
1106
|
+
name: "fallback.incidents",
|
|
1107
|
+
input: z.object({ workspaceId: z.string().min(1).optional(), ids: z.array(z.string().min(1)).max(200).optional() }),
|
|
1108
|
+
output: z.object({ incidents: z.array(fallbackIncidentSchema) }),
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* `fallback.act` — the user's choice on the card for a `pending` incident:
|
|
1113
|
+
* switch to the candidate (§4.4.7, §4.5.1), wait for the reset (§4.4.9), or
|
|
1114
|
+
* handle it themselves (`dismiss`, §4.4.10). `resend` sends a switched
|
|
1115
|
+
* Reviewer's instructions to its Worker again when the notice queue lost them
|
|
1116
|
+
* (§7, "Resend to Worker"). Returns the incident as it is afterwards.
|
|
1117
|
+
*/
|
|
1118
|
+
export const fallbackActRpc = defineRpc({
|
|
1119
|
+
name: "fallback.act",
|
|
1120
|
+
input: z.object({ incidentId: z.string().min(1), action: z.enum(["switch", "wait", "dismiss", "resend"]) }),
|
|
1121
|
+
output: z.object({ incident: fallbackIncidentSchema }),
|
|
1122
|
+
});
|
|
1123
|
+
|
|
1124
|
+
/**
|
|
1125
|
+
* Furthest ahead a `resetsAt` may lie for the card to offer "Wait until …"
|
|
1126
|
+
* and for `fallback.act` `wait` to accept it: 7 days (§4.4.6, §4.4.9).
|
|
1127
|
+
*/
|
|
1128
|
+
export const FALLBACK_MAX_WAIT_MS = 7 * 24 * 60 * 60 * 1000;
|
|
1129
|
+
|
|
1130
|
+
export type ProviderCapabilityClass = z.infer<typeof providerCapabilitySchema>;
|
|
1131
|
+
export type FallbackActInput = z.infer<typeof fallbackActRpc.input>;
|
|
1132
|
+
export type FallbackIncident = z.infer<typeof fallbackIncidentSchema>;
|
|
1133
|
+
export type FallbackEntryInput = z.infer<typeof fallbackEntryInputSchema>;
|
|
1134
|
+
export type FallbackSettings = z.infer<typeof fallbackSettingsSchema>;
|
|
1135
|
+
export type RolesSaveFallbackInput = z.infer<typeof rolesSaveFallbackRpc.input>;
|
|
1136
|
+
export type RolesSaveSettingsInput = z.infer<typeof rolesSaveSettingsRpc.input>;
|
|
1137
|
+
export type RoleSetting = z.infer<typeof roleSettingSchema>;
|
|
1138
|
+
export type RolesSettings = z.infer<typeof rolesSettingsRpc.output>;
|
|
1139
|
+
export type RoleModelOption = z.infer<typeof roleModelOptionSchema>;
|
|
1140
|
+
export type RoleModeOption = z.infer<typeof roleModeOptionSchema>;
|
|
1141
|
+
export type RolesOptions = z.infer<typeof rolesOptionsRpc.output>;
|
|
1142
|
+
|
|
1143
|
+
/** One paseo-bm agent as a chat card needs it. */
|
|
1144
|
+
export const chatPeerSchema = z.object({
|
|
1145
|
+
id: agentIdSchema,
|
|
1146
|
+
role: agentRoleSchema,
|
|
1147
|
+
title: z.string().nullable(),
|
|
1148
|
+
status: z.string(),
|
|
1149
|
+
parentId: z.string().nullable(),
|
|
1150
|
+
/** `bm.requestId` / `bm.batchId` labels. */
|
|
1151
|
+
requestId: z.string().nullable(),
|
|
1152
|
+
batchId: z.string().nullable(),
|
|
1153
|
+
/**
|
|
1154
|
+
* False when the agent has no `bm.role` label and was recognised by its
|
|
1155
|
+
* provider only (delta 20260918g §4.4). Defaults to true for older servers.
|
|
1156
|
+
*/
|
|
1157
|
+
labelled: z.boolean().default(true),
|
|
1158
|
+
/** Archived in Paseo: never a recipient, since a message would bring it back (delta 20260918f F12). */
|
|
1159
|
+
archived: z.boolean(),
|
|
1160
|
+
/**
|
|
1161
|
+
* A fallback agent took over from this one (`bm.replacedBy`, or the agent of
|
|
1162
|
+
* a `switched` incident, delta 20260921 §4.4.8): never the request's Worker
|
|
1163
|
+
* again. Defaults to false for older servers.
|
|
1164
|
+
*/
|
|
1165
|
+
replaced: z.boolean().default(false),
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1168
|
+
/** One Worker waiting for the user's answer in a Manager's chat (delta 20260918d §4.8). */
|
|
1169
|
+
export const waitingWorkerSchema = z.object({
|
|
1170
|
+
managerId: agentIdSchema,
|
|
1171
|
+
workspaceId: workspaceIdSchema,
|
|
1172
|
+
workerId: agentIdSchema,
|
|
1173
|
+
workerTitle: z.string().nullable(),
|
|
1174
|
+
requestId: z.string(),
|
|
1175
|
+
/** The report message as the Manager received it: the client builds the same card from it. */
|
|
1176
|
+
text: z.string(),
|
|
1177
|
+
at: z.string().nullable(),
|
|
1178
|
+
});
|
|
1179
|
+
|
|
1180
|
+
export type WaitingWorker = z.infer<typeof waitingWorkerSchema>;
|
|
1181
|
+
|
|
1182
|
+
/**
|
|
1183
|
+
* One `pending` fallback incident waiting for the user's decision in a live
|
|
1184
|
+
* Manager's chat (delta 20260921 §4.4.6): `managerId` is the incident's, and
|
|
1185
|
+
* `workspaceId` that Manager's, where its pill goes.
|
|
1186
|
+
*/
|
|
1187
|
+
export const waitingFallbackSchema = z.object({
|
|
1188
|
+
managerId: agentIdSchema,
|
|
1189
|
+
workspaceId: workspaceIdSchema,
|
|
1190
|
+
incident: fallbackIncidentSchema,
|
|
1191
|
+
});
|
|
1192
|
+
|
|
1193
|
+
export type WaitingFallback = z.infer<typeof waitingFallbackSchema>;
|
|
1194
|
+
|
|
1195
|
+
/**
|
|
1196
|
+
* `chat.waiting` — for every paseo-bm Manager, the idle Workers whose latest
|
|
1197
|
+
* report to it is `blocked` with a `BM-QUESTIONS` block (delta 20260918d §4.8,
|
|
1198
|
+
* REQ-059 j), and the `pending` fallback incidents whose card is in its chat
|
|
1199
|
+
* (delta 20260921 §4.4.6), read from the incidents file, not the timeline, so
|
|
1200
|
+
* they show even when the Manager's own turn failed. `fallback` defaults to
|
|
1201
|
+
* empty for a server built before it. Read-only.
|
|
1202
|
+
*/
|
|
1203
|
+
export const chatWaitingRpc = defineRpc({
|
|
1204
|
+
name: "chat.waiting",
|
|
1205
|
+
input: z.object({}),
|
|
1206
|
+
output: z.object({ waiting: z.array(waitingWorkerSchema), fallback: z.array(waitingFallbackSchema).default([]) }),
|
|
1207
|
+
});
|
|
1208
|
+
|
|
1209
|
+
/**
|
|
1210
|
+
* `chat.peers` — the paseo-bm agent that owns a chat and the other paseo-bm
|
|
1211
|
+
* agents of its workspace (delta 20260916-chat-cards §4.3). Read-only.
|
|
1212
|
+
*/
|
|
1213
|
+
export const chatPeersRpc = defineRpc({
|
|
1214
|
+
name: "chat.peers",
|
|
1215
|
+
input: z.object({ agentId: agentIdSchema }),
|
|
1216
|
+
output: z.object({
|
|
1217
|
+
owner: chatPeerSchema.nullable(),
|
|
1218
|
+
peers: z.array(chatPeerSchema),
|
|
1219
|
+
/** The owner's workspace; null for an agent that is not paseo-bm's. */
|
|
1220
|
+
workspaceId: z.string().nullable(),
|
|
1221
|
+
}),
|
|
1222
|
+
});
|
|
1223
|
+
|
|
1224
|
+
|
|
1225
|
+
/** A Worker and the moment it did something to a bead. */
|
|
1226
|
+
export const beadWorkMarkSchema = z.object({
|
|
1227
|
+
agentId: z.string().min(1),
|
|
1228
|
+
at: z.string(),
|
|
1229
|
+
/** The agent's title in Paseo; null when Paseo no longer lists the agent. */
|
|
1230
|
+
title: z.string().nullable(),
|
|
1231
|
+
/** The agent's status now (`running`, `idle`, …); null when it is gone. */
|
|
1232
|
+
status: z.string().nullable(),
|
|
1233
|
+
});
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
* Who is working on an `in_progress` bead, from the trace store. `started` is
|
|
1237
|
+
* the Worker command that moved the bead to `in_progress`; `last` is the latest
|
|
1238
|
+
* Worker command or report that named the bead. Either can be unknown.
|
|
1239
|
+
*/
|
|
1240
|
+
export const beadWorkSchema = z.object({
|
|
1241
|
+
started: beadWorkMarkSchema.nullable(),
|
|
1242
|
+
last: beadWorkMarkSchema.nullable(),
|
|
1243
|
+
});
|
|
1244
|
+
|
|
1245
|
+
export const beadRowSchema = z.object({
|
|
1246
|
+
id: z.string().min(1),
|
|
1247
|
+
title: z.string().nullable(),
|
|
1248
|
+
status: z.string(),
|
|
1249
|
+
issueType: z.string(),
|
|
1250
|
+
/** 0 (highest) to 4; null when the store has none. */
|
|
1251
|
+
priority: z.number().int().nullable(),
|
|
1252
|
+
labels: z.array(z.string()),
|
|
1253
|
+
createdAt: z.string().nullable(),
|
|
1254
|
+
updatedAt: z.string().nullable(),
|
|
1255
|
+
closedAt: z.string().nullable(),
|
|
1256
|
+
/** Derived like `br ready`: open, every blocker closed, not an epic. */
|
|
1257
|
+
ready: z.boolean(),
|
|
1258
|
+
parentId: z.string().nullable(),
|
|
1259
|
+
/** Only for `in_progress` beads; null when nothing was recorded. */
|
|
1260
|
+
work: beadWorkSchema.nullable(),
|
|
1261
|
+
});
|
|
1262
|
+
|
|
1263
|
+
export const beadDetailSchema = beadRowSchema.extend({
|
|
1264
|
+
description: z.string().nullable(),
|
|
1265
|
+
closeReason: z.string().nullable(),
|
|
1266
|
+
blockedBy: z.array(z.string()),
|
|
1267
|
+
children: z.array(z.string()),
|
|
1268
|
+
});
|
|
1269
|
+
|
|
1270
|
+
/** `beads.list` — every bead of a workspace, read from `.beads/issues.jsonl`. */
|
|
1271
|
+
export const beadsListRpc = defineRpc({
|
|
1272
|
+
name: "beads.list",
|
|
1273
|
+
input: z.object({ workspaceId: workspaceIdSchema }),
|
|
1274
|
+
output: z.object({ beads: z.array(beadRowSchema), stats: beadStatsSchema }),
|
|
1275
|
+
});
|
|
1276
|
+
|
|
1277
|
+
/** `beads.get` — one bead in full; an unknown id fails `E_BEAD_NOT_FOUND`. */
|
|
1278
|
+
export const beadsGetRpc = defineRpc({
|
|
1279
|
+
name: "beads.get",
|
|
1280
|
+
input: z.object({ workspaceId: workspaceIdSchema, id: z.string().min(1) }),
|
|
1281
|
+
output: z.object({ bead: beadDetailSchema }),
|
|
1282
|
+
});
|
|
1283
|
+
|
|
1284
|
+
export const beadActionSchema = z.enum(["implement", "delete", "close"]);
|
|
1285
|
+
|
|
1286
|
+
/**
|
|
1287
|
+
* `beads.action` — hands a bead to the workspace's Manager, which delegates it
|
|
1288
|
+
* to a Worker. The plugin itself never writes the bead store.
|
|
1289
|
+
*/
|
|
1290
|
+
export const beadsActionRpc = defineRpc({
|
|
1291
|
+
name: "beads.action",
|
|
1292
|
+
input: z.object({ workspaceId: workspaceIdSchema, id: z.string().min(1), action: beadActionSchema }),
|
|
1293
|
+
output: z.object({ managerId: z.string(), created: z.boolean() }),
|
|
1294
|
+
});
|
|
1295
|
+
|
|
1296
|
+
/**
|
|
1297
|
+
* `traces.workspaces` — every workspace that has trace history, with what
|
|
1298
|
+
* Paseo says about it now. This is how a closed workspace's history stays
|
|
1299
|
+
* reachable: the launcher only lists workspaces Paseo still has.
|
|
1300
|
+
*/
|
|
1301
|
+
export const tracesWorkspacesRpc = defineRpc({
|
|
1302
|
+
name: "traces.workspaces",
|
|
1303
|
+
input: z.object({}),
|
|
1304
|
+
output: z.object({
|
|
1305
|
+
workspaces: z.array(
|
|
1306
|
+
z.object({
|
|
1307
|
+
workspaceId: workspaceIdSchema,
|
|
1308
|
+
state: workspaceStateSchema,
|
|
1309
|
+
lastKnownName: z.string().nullable(),
|
|
1310
|
+
lastKnownDirectory: z.string().nullable(),
|
|
1311
|
+
lastSeenAt: z.string().nullable(),
|
|
1312
|
+
bytes: z.number().int().nonnegative(),
|
|
1313
|
+
}),
|
|
1314
|
+
),
|
|
1315
|
+
}),
|
|
1316
|
+
});
|
|
1317
|
+
|
|
1318
|
+
export type BeadRow = z.infer<typeof beadRowSchema>;
|
|
1319
|
+
/** Input shape: `labelled` may be absent (meaning labelled), as from a server older than delta 20260918g. */
|
|
1320
|
+
export type ChatPeer = z.input<typeof chatPeerSchema>;
|
|
1321
|
+
export type BeadWork = z.infer<typeof beadWorkSchema>;
|
|
1322
|
+
export type BeadDetail = z.infer<typeof beadDetailSchema>;
|
|
1323
|
+
export type BeadAction = z.infer<typeof beadActionSchema>;
|
|
1324
|
+
|
|
1325
|
+
export type Confidence = z.infer<typeof confidenceSchema>;
|
|
1326
|
+
export type Evidence = z.infer<typeof evidenceSchema>;
|
|
1327
|
+
export type Usage = z.infer<typeof usageSchema>;
|
|
1328
|
+
export type TraceState = z.infer<typeof traceStateSchema>;
|
|
1329
|
+
export type Tier = z.infer<typeof tierSchema>;
|
|
1330
|
+
export type WorkspaceState = z.infer<typeof workspaceStateSchema>;
|
|
1331
|
+
export type GuardrailReport = z.infer<typeof guardrailReportSchema>;
|
|
1332
|
+
export type TraceSummary = z.infer<typeof traceSummarySchema>;
|
|
1333
|
+
export type TraceDetail = z.infer<typeof traceDetailSchema>;
|
|
1334
|
+
export type TraceMessage = z.infer<typeof traceMessageSchema>;
|
|
1335
|
+
export type AgentTiming = z.infer<typeof agentTimingSchema>;
|
|
1336
|
+
export type TurnTiming = z.infer<typeof turnTimingSchema>;
|
|
1337
|
+
export type ParsedReport = z.infer<typeof parsedReportSchema>;
|
|
1338
|
+
export type ParsedReview = z.infer<typeof parsedReviewSchema>;
|
|
1339
|
+
export type ReportPhase = z.infer<typeof reportPhaseSchema>;
|
|
1340
|
+
export type WorkflowStep = z.infer<typeof workflowStepSchema>;
|
|
1341
|
+
export type WorkflowStepResult = z.infer<typeof workflowStepResultSchema>;
|
|
1342
|
+
export type TraceBead = z.infer<typeof traceBeadSchema>;
|
|
1343
|
+
export type SubAgentTrace = z.infer<typeof subAgentTraceSchema>;
|
|
1344
|
+
export type BeadStats = z.infer<typeof beadStatsSchema>;
|
|
1345
|
+
export type StoreSize = z.infer<typeof storeSizeSchema>;
|
|
1346
|
+
export type TraceRecord = z.infer<typeof traceRecordSchema>;
|
|
1347
|
+
export type TraceRuntime = z.infer<typeof traceRuntimeSchema>;
|
|
1348
|
+
export type RuntimeRow = z.infer<typeof runtimeRowSchema>;
|
|
1349
|
+
export type TraceStoreMeta = z.infer<typeof traceStoreMetaSchema>;
|
|
1350
|
+
export type TraceWorkspaceMeta = z.infer<typeof traceWorkspaceMetaSchema>;
|
|
1351
|
+
export type TraceDeleteScope = z.infer<typeof traceDeleteScopeSchema>;
|
|
1352
|
+
|
|
1353
|
+
/** `beads.lookup` — the beads among `ids` that the workspace's bead store has. Read-only. */
|
|
1354
|
+
export const beadsLookupRpc = defineRpc({
|
|
1355
|
+
name: "beads.lookup",
|
|
1356
|
+
input: z.object({ workspaceId: workspaceIdSchema, ids: z.array(z.string().min(1)).max(100) }),
|
|
1357
|
+
output: z.object({ beads: z.array(beadRowSchema) }),
|
|
1358
|
+
});
|
|
1359
|
+
|
|
1360
|
+
/**
|
|
1361
|
+
* `chat.beads` — beads named in an agent's recent chat (messages and shell
|
|
1362
|
+
* commands), newest mention first. Read-only.
|
|
1363
|
+
*/
|
|
1364
|
+
export const chatBeadsRpc = defineRpc({
|
|
1365
|
+
name: "chat.beads",
|
|
1366
|
+
input: z.object({ workspaceId: workspaceIdSchema, agentId: agentIdSchema }),
|
|
1367
|
+
output: z.object({
|
|
1368
|
+
beads: z.array(z.object({ bead: beadRowSchema, mentions: z.number().int(), lastMentionedAt: z.string().nullable() })),
|
|
1369
|
+
scannedItems: z.number().int(),
|
|
1370
|
+
}),
|
|
1371
|
+
});
|