@omercnet/paseo-gas-city 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/bun.lock +1217 -0
- package/client/city-operations.tsx +1505 -0
- package/client/contribute.tsx +96 -0
- package/client/dispatch-intent.ts +53 -0
- package/client/factory-panel.tsx +373 -0
- package/client/gas-city-surface.tsx +343 -0
- package/client/settings-screen.tsx +286 -0
- package/client/view-model.ts +318 -0
- package/docs/images/paseo-gas-city-compact-overview.webp +0 -0
- package/docs/images/paseo-gas-city-dispatch-confirmation.webp +0 -0
- package/docs/images/paseo-gas-city-wide-events.webp +0 -0
- package/docs/images/paseo-gas-city-wide-overview.webp +0 -0
- package/icon.svg +5 -0
- package/index.client.tsx +1 -0
- package/index.server.ts +42 -0
- package/package.json +73 -0
- package/paseo-plugin.json +4 -0
- package/server/gas-city-client.ts +668 -0
- package/server/handlers.ts +790 -0
- package/server/workspace-mapping.ts +170 -0
- package/shared/index.ts +4 -0
- package/shared/limits.ts +28 -0
- package/shared/rpc.ts +99 -0
- package/shared/schemas.ts +430 -0
- package/shared/settings.ts +89 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { GAS_CITY_LIMITS } from "./limits";
|
|
3
|
+
|
|
4
|
+
const boundedString = (maximum: number) => z.string().max(maximum);
|
|
5
|
+
const boundedNullableString = (maximum: number) => boundedString(maximum).nullable();
|
|
6
|
+
const countSchema = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
7
|
+
|
|
8
|
+
export const identifierSchema = boundedString(GAS_CITY_LIMITS.identifier).min(1);
|
|
9
|
+
export const nameSchema = boundedString(GAS_CITY_LIMITS.name).min(1);
|
|
10
|
+
export const pathSchema = boundedString(GAS_CITY_LIMITS.path).min(1);
|
|
11
|
+
export const titleSchema = boundedString(GAS_CITY_LIMITS.title).min(1);
|
|
12
|
+
export const statusSchema = boundedString(GAS_CITY_LIMITS.status).min(1);
|
|
13
|
+
export const timestampSchema = boundedString(GAS_CITY_LIMITS.timestamp).datetime({ offset: true });
|
|
14
|
+
export const endpointUrlSchema = boundedString(GAS_CITY_LIMITS.endpointUrl)
|
|
15
|
+
.url()
|
|
16
|
+
.superRefine((value, context) => {
|
|
17
|
+
const endpoint = new URL(value);
|
|
18
|
+
if (endpoint.protocol !== "http:" && endpoint.protocol !== "https:") {
|
|
19
|
+
context.addIssue({ code: "custom", message: "Gas City endpoint must use HTTP or HTTPS" });
|
|
20
|
+
}
|
|
21
|
+
if (endpoint.username || endpoint.password) {
|
|
22
|
+
context.addIssue({ code: "custom", message: "Gas City endpoint cannot contain credentials" });
|
|
23
|
+
}
|
|
24
|
+
if (endpoint.search) {
|
|
25
|
+
context.addIssue({ code: "custom", message: "Gas City endpoint cannot contain a query" });
|
|
26
|
+
}
|
|
27
|
+
if (endpoint.hash) {
|
|
28
|
+
context.addIssue({ code: "custom", message: "Gas City endpoint cannot contain a fragment" });
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export const MetadataValueSchema = z.union([
|
|
33
|
+
boundedString(GAS_CITY_LIMITS.metadataValue),
|
|
34
|
+
z.number().finite(),
|
|
35
|
+
z.boolean(),
|
|
36
|
+
z.null(),
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
export const BoundedMetadataSchema = z
|
|
40
|
+
.record(boundedString(GAS_CITY_LIMITS.metadataKey).min(1), MetadataValueSchema)
|
|
41
|
+
.refine((value) => Object.keys(value).length <= GAS_CITY_LIMITS.metadataEntries, {
|
|
42
|
+
message: `Metadata cannot contain more than ${GAS_CITY_LIMITS.metadataEntries} entries`,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const GasCityDiagnosticSchema = z
|
|
46
|
+
.object({
|
|
47
|
+
code: statusSchema,
|
|
48
|
+
message: boundedString(GAS_CITY_LIMITS.errorMessage),
|
|
49
|
+
retryable: z.boolean(),
|
|
50
|
+
})
|
|
51
|
+
.strict();
|
|
52
|
+
|
|
53
|
+
export const SupervisorSummarySchema = z
|
|
54
|
+
.object({
|
|
55
|
+
endpointUrl: endpointUrlSchema,
|
|
56
|
+
version: boundedNullableString(GAS_CITY_LIMITS.status),
|
|
57
|
+
buildId: boundedNullableString(GAS_CITY_LIMITS.identifier),
|
|
58
|
+
uptimeSeconds: countSchema.nullable(),
|
|
59
|
+
cityCount: countSchema,
|
|
60
|
+
runningCityCount: countSchema,
|
|
61
|
+
})
|
|
62
|
+
.strict();
|
|
63
|
+
|
|
64
|
+
export const CitySummarySchema = z
|
|
65
|
+
.object({
|
|
66
|
+
name: nameSchema,
|
|
67
|
+
path: pathSchema,
|
|
68
|
+
running: z.boolean(),
|
|
69
|
+
status: boundedNullableString(GAS_CITY_LIMITS.status),
|
|
70
|
+
error: boundedNullableString(GAS_CITY_LIMITS.errorMessage),
|
|
71
|
+
completedPhases: z.array(statusSchema).max(GAS_CITY_LIMITS.diagnostics),
|
|
72
|
+
})
|
|
73
|
+
.strict();
|
|
74
|
+
|
|
75
|
+
export const SupervisorDiscoverySchema = z
|
|
76
|
+
.object({
|
|
77
|
+
state: z.enum(["available", "unreachable", "invalid-response", "not-configured"]),
|
|
78
|
+
supervisor: SupervisorSummarySchema.nullable(),
|
|
79
|
+
cities: z.array(CitySummarySchema).max(GAS_CITY_LIMITS.cities),
|
|
80
|
+
diagnostics: z.array(GasCityDiagnosticSchema).max(GAS_CITY_LIMITS.diagnostics),
|
|
81
|
+
refreshedAt: timestampSchema,
|
|
82
|
+
})
|
|
83
|
+
.strict();
|
|
84
|
+
export const RigGitStatusSchema = z
|
|
85
|
+
.object({
|
|
86
|
+
branch: nameSchema,
|
|
87
|
+
clean: z.boolean(),
|
|
88
|
+
changedFiles: countSchema,
|
|
89
|
+
ahead: countSchema,
|
|
90
|
+
behind: countSchema,
|
|
91
|
+
})
|
|
92
|
+
.strict();
|
|
93
|
+
|
|
94
|
+
export const RigSummarySchema = z
|
|
95
|
+
.object({
|
|
96
|
+
name: nameSchema,
|
|
97
|
+
path: pathSchema,
|
|
98
|
+
prefix: boundedNullableString(GAS_CITY_LIMITS.identifier),
|
|
99
|
+
suspended: z.boolean(),
|
|
100
|
+
agentCount: countSchema,
|
|
101
|
+
runningAgentCount: countSchema,
|
|
102
|
+
defaultBranch: boundedNullableString(GAS_CITY_LIMITS.name),
|
|
103
|
+
lastActivityAt: timestampSchema.nullable(),
|
|
104
|
+
git: RigGitStatusSchema.nullable(),
|
|
105
|
+
})
|
|
106
|
+
.strict();
|
|
107
|
+
|
|
108
|
+
export const MappingCandidateSchema = z
|
|
109
|
+
.object({
|
|
110
|
+
cityName: nameSchema,
|
|
111
|
+
rigName: nameSchema,
|
|
112
|
+
rigPath: pathSchema,
|
|
113
|
+
})
|
|
114
|
+
.strict();
|
|
115
|
+
|
|
116
|
+
export const WorkspaceRigMappingSchema = z
|
|
117
|
+
.object({
|
|
118
|
+
state: z.enum(["mapped", "unmapped", "ambiguous", "unavailable"]),
|
|
119
|
+
workspaceId: identifierSchema,
|
|
120
|
+
workspacePath: pathSchema.nullable(),
|
|
121
|
+
cityName: nameSchema.nullable(),
|
|
122
|
+
rigName: nameSchema.nullable(),
|
|
123
|
+
rigPath: pathSchema.nullable(),
|
|
124
|
+
source: z.enum(["explicit", "longest-ancestor"]).nullable(),
|
|
125
|
+
candidates: z.array(MappingCandidateSchema).max(GAS_CITY_LIMITS.mappingCandidates),
|
|
126
|
+
diagnostics: z.array(GasCityDiagnosticSchema).max(GAS_CITY_LIMITS.diagnostics),
|
|
127
|
+
})
|
|
128
|
+
.strict();
|
|
129
|
+
|
|
130
|
+
export const AgentCountsSchema = z
|
|
131
|
+
.object({
|
|
132
|
+
total: countSchema,
|
|
133
|
+
running: countSchema,
|
|
134
|
+
suspended: countSchema,
|
|
135
|
+
quarantined: countSchema,
|
|
136
|
+
})
|
|
137
|
+
.strict();
|
|
138
|
+
|
|
139
|
+
export const SessionCountsSchema = z
|
|
140
|
+
.object({
|
|
141
|
+
active: countSchema,
|
|
142
|
+
suspended: countSchema,
|
|
143
|
+
})
|
|
144
|
+
.strict();
|
|
145
|
+
|
|
146
|
+
export const WorkCountsSchema = z
|
|
147
|
+
.object({
|
|
148
|
+
open: countSchema,
|
|
149
|
+
ready: countSchema,
|
|
150
|
+
inProgress: countSchema,
|
|
151
|
+
})
|
|
152
|
+
.strict();
|
|
153
|
+
|
|
154
|
+
export const CityRigSnapshotSchema = z
|
|
155
|
+
.object({
|
|
156
|
+
city: CitySummarySchema.extend({
|
|
157
|
+
suspended: z.boolean(),
|
|
158
|
+
uptimeSeconds: countSchema.nullable(),
|
|
159
|
+
agents: AgentCountsSchema,
|
|
160
|
+
sessions: SessionCountsSchema,
|
|
161
|
+
work: WorkCountsSchema,
|
|
162
|
+
totalsScope: z.literal("city"),
|
|
163
|
+
}).strict(),
|
|
164
|
+
rig: RigSummarySchema.nullable(),
|
|
165
|
+
rigs: z.array(RigSummarySchema).max(GAS_CITY_LIMITS.rigs),
|
|
166
|
+
partial: z.boolean(),
|
|
167
|
+
diagnostics: z.array(GasCityDiagnosticSchema).max(GAS_CITY_LIMITS.diagnostics),
|
|
168
|
+
refreshedAt: timestampSchema,
|
|
169
|
+
})
|
|
170
|
+
.strict();
|
|
171
|
+
|
|
172
|
+
export const GasCitySessionSchema = z
|
|
173
|
+
.object({
|
|
174
|
+
id: identifierSchema,
|
|
175
|
+
cityName: nameSchema,
|
|
176
|
+
rigName: nameSchema.nullable(),
|
|
177
|
+
template: nameSchema,
|
|
178
|
+
state: statusSchema,
|
|
179
|
+
title: titleSchema,
|
|
180
|
+
provider: nameSchema,
|
|
181
|
+
sessionName: nameSchema,
|
|
182
|
+
createdAt: timestampSchema,
|
|
183
|
+
lastActiveAt: timestampSchema.nullable(),
|
|
184
|
+
attached: z.boolean(),
|
|
185
|
+
running: z.boolean(),
|
|
186
|
+
configuredNamedSession: z.boolean(),
|
|
187
|
+
activity: boundedNullableString(GAS_CITY_LIMITS.status),
|
|
188
|
+
activeBeadId: identifierSchema.nullable(),
|
|
189
|
+
model: boundedNullableString(GAS_CITY_LIMITS.name),
|
|
190
|
+
kind: boundedNullableString(GAS_CITY_LIMITS.status),
|
|
191
|
+
submissionKinds: z.array(statusSchema).max(GAS_CITY_LIMITS.diagnostics),
|
|
192
|
+
})
|
|
193
|
+
.strict();
|
|
194
|
+
|
|
195
|
+
export const SessionListSchema = z
|
|
196
|
+
.object({
|
|
197
|
+
scope: z.enum(["city", "rig"]),
|
|
198
|
+
items: z.array(GasCitySessionSchema).max(GAS_CITY_LIMITS.sessions),
|
|
199
|
+
truncated: z.boolean(),
|
|
200
|
+
refreshedAt: timestampSchema,
|
|
201
|
+
})
|
|
202
|
+
.strict();
|
|
203
|
+
|
|
204
|
+
export const GasCityConvoySchema = z
|
|
205
|
+
.object({
|
|
206
|
+
id: identifierSchema,
|
|
207
|
+
cityName: nameSchema,
|
|
208
|
+
rigName: nameSchema.nullable(),
|
|
209
|
+
title: titleSchema,
|
|
210
|
+
status: statusSchema,
|
|
211
|
+
priority: z.number().int().min(0).max(4).nullable(),
|
|
212
|
+
assignee: boundedNullableString(GAS_CITY_LIMITS.name),
|
|
213
|
+
createdAt: timestampSchema,
|
|
214
|
+
updatedAt: timestampSchema.nullable(),
|
|
215
|
+
totalWork: countSchema.nullable(),
|
|
216
|
+
closedWork: countSchema.nullable(),
|
|
217
|
+
blocked: z.boolean(),
|
|
218
|
+
})
|
|
219
|
+
.strict()
|
|
220
|
+
.refine(
|
|
221
|
+
(convoy) =>
|
|
222
|
+
convoy.totalWork === null ||
|
|
223
|
+
convoy.closedWork === null ||
|
|
224
|
+
convoy.closedWork <= convoy.totalWork,
|
|
225
|
+
{ message: "Closed convoy work cannot exceed total work" },
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
export const ConvoyListSchema = z
|
|
229
|
+
.object({
|
|
230
|
+
scope: z.enum(["city", "rig-and-unattributed"]),
|
|
231
|
+
items: z.array(GasCityConvoySchema).max(GAS_CITY_LIMITS.convoys),
|
|
232
|
+
truncated: z.boolean(),
|
|
233
|
+
refreshedAt: timestampSchema,
|
|
234
|
+
})
|
|
235
|
+
.strict();
|
|
236
|
+
export const GasCityWorkItemSchema = z
|
|
237
|
+
.object({
|
|
238
|
+
id: identifierSchema,
|
|
239
|
+
cityName: nameSchema,
|
|
240
|
+
rigName: nameSchema.nullable(),
|
|
241
|
+
title: titleSchema,
|
|
242
|
+
status: statusSchema,
|
|
243
|
+
type: statusSchema,
|
|
244
|
+
priority: z.number().int().min(0).max(4).nullable(),
|
|
245
|
+
assignee: boundedNullableString(GAS_CITY_LIMITS.name),
|
|
246
|
+
createdAt: timestampSchema,
|
|
247
|
+
updatedAt: timestampSchema.nullable(),
|
|
248
|
+
blocked: z.boolean().nullable(),
|
|
249
|
+
})
|
|
250
|
+
.strict();
|
|
251
|
+
|
|
252
|
+
export const WorkListSchema = z
|
|
253
|
+
.object({
|
|
254
|
+
scope: z.enum(["city", "rig"]),
|
|
255
|
+
items: z.array(GasCityWorkItemSchema).max(GAS_CITY_LIMITS.workItems),
|
|
256
|
+
truncated: z.boolean(),
|
|
257
|
+
partial: z.boolean(),
|
|
258
|
+
refreshedAt: timestampSchema,
|
|
259
|
+
})
|
|
260
|
+
.strict();
|
|
261
|
+
|
|
262
|
+
export const GasCityEventSchema = z
|
|
263
|
+
.object({
|
|
264
|
+
cityName: nameSchema.nullable(),
|
|
265
|
+
sequence: countSchema,
|
|
266
|
+
type: boundedString(GAS_CITY_LIMITS.eventType).min(1),
|
|
267
|
+
actor: boundedNullableString(GAS_CITY_LIMITS.name),
|
|
268
|
+
subject: boundedNullableString(GAS_CITY_LIMITS.identifier),
|
|
269
|
+
message: boundedNullableString(GAS_CITY_LIMITS.message),
|
|
270
|
+
timestamp: timestampSchema,
|
|
271
|
+
metadata: BoundedMetadataSchema,
|
|
272
|
+
})
|
|
273
|
+
.strict();
|
|
274
|
+
|
|
275
|
+
export const EventListSchema = z
|
|
276
|
+
.object({
|
|
277
|
+
scope: z.enum(["supervisor-head", "city"]),
|
|
278
|
+
items: z.array(GasCityEventSchema).max(GAS_CITY_LIMITS.events),
|
|
279
|
+
cursor: boundedNullableString(GAS_CITY_LIMITS.cursor),
|
|
280
|
+
truncated: z.boolean(),
|
|
281
|
+
refreshedAt: timestampSchema,
|
|
282
|
+
})
|
|
283
|
+
.strict();
|
|
284
|
+
|
|
285
|
+
export const AttentionItemSchema = z
|
|
286
|
+
.object({
|
|
287
|
+
id: identifierSchema,
|
|
288
|
+
cityName: nameSchema,
|
|
289
|
+
rigName: nameSchema.nullable(),
|
|
290
|
+
kind: z.enum(["city", "rig", "session", "convoy", "work"]),
|
|
291
|
+
severity: z.enum(["info", "warning", "critical"]),
|
|
292
|
+
code: statusSchema,
|
|
293
|
+
title: titleSchema,
|
|
294
|
+
message: boundedString(GAS_CITY_LIMITS.message),
|
|
295
|
+
requestId: identifierSchema.nullable(),
|
|
296
|
+
resourceId: identifierSchema.nullable(),
|
|
297
|
+
observedAt: timestampSchema,
|
|
298
|
+
})
|
|
299
|
+
.strict();
|
|
300
|
+
|
|
301
|
+
export const AttentionListSchema = z
|
|
302
|
+
.object({
|
|
303
|
+
scope: z.enum(["city", "city-and-rig"]),
|
|
304
|
+
items: z.array(AttentionItemSchema).max(GAS_CITY_LIMITS.attentionItems),
|
|
305
|
+
truncated: z.boolean(),
|
|
306
|
+
refreshedAt: timestampSchema,
|
|
307
|
+
})
|
|
308
|
+
.strict();
|
|
309
|
+
|
|
310
|
+
export const DispatchTargetSchema = z
|
|
311
|
+
.object({
|
|
312
|
+
cityName: nameSchema,
|
|
313
|
+
rigName: nameSchema.nullable(),
|
|
314
|
+
agent: nameSchema,
|
|
315
|
+
})
|
|
316
|
+
.strict();
|
|
317
|
+
|
|
318
|
+
const confirmedMutation = {
|
|
319
|
+
confirmed: z.literal(true),
|
|
320
|
+
target: DispatchTargetSchema,
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
export const DispatchRequestSchema = z.discriminatedUnion("kind", [
|
|
324
|
+
z
|
|
325
|
+
.object({
|
|
326
|
+
...confirmedMutation,
|
|
327
|
+
kind: z.literal("bead"),
|
|
328
|
+
beadId: identifierSchema,
|
|
329
|
+
reassign: z.boolean(),
|
|
330
|
+
owned: z.boolean(),
|
|
331
|
+
force: z.boolean(),
|
|
332
|
+
noFormula: z.boolean(),
|
|
333
|
+
noConvoy: z.boolean(),
|
|
334
|
+
merge: z.enum(["direct", "mr", "local"]),
|
|
335
|
+
})
|
|
336
|
+
.strict(),
|
|
337
|
+
z
|
|
338
|
+
.object({
|
|
339
|
+
...confirmedMutation,
|
|
340
|
+
kind: z.literal("formula"),
|
|
341
|
+
formula: nameSchema,
|
|
342
|
+
title: titleSchema,
|
|
343
|
+
attachedBeadId: identifierSchema.nullable(),
|
|
344
|
+
variables: BoundedMetadataSchema,
|
|
345
|
+
force: z.boolean(),
|
|
346
|
+
merge: z.enum(["direct", "mr", "local"]),
|
|
347
|
+
})
|
|
348
|
+
.strict(),
|
|
349
|
+
]);
|
|
350
|
+
|
|
351
|
+
export const DispatchResultSchema = z
|
|
352
|
+
.object({
|
|
353
|
+
status: statusSchema,
|
|
354
|
+
target: nameSchema,
|
|
355
|
+
beadId: identifierSchema.nullable(),
|
|
356
|
+
formula: nameSchema.nullable(),
|
|
357
|
+
workflowId: identifierSchema.nullable(),
|
|
358
|
+
rootBeadId: identifierSchema.nullable(),
|
|
359
|
+
dashboardUrl: boundedNullableString(GAS_CITY_LIMITS.path),
|
|
360
|
+
warnings: z.array(boundedString(GAS_CITY_LIMITS.message)).max(GAS_CITY_LIMITS.warnings),
|
|
361
|
+
})
|
|
362
|
+
.strict();
|
|
363
|
+
|
|
364
|
+
const sessionMutationBase = {
|
|
365
|
+
cityName: nameSchema,
|
|
366
|
+
sessionId: identifierSchema,
|
|
367
|
+
confirmed: z.literal(true),
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
export const SessionActionRequestSchema = z.discriminatedUnion("action", [
|
|
371
|
+
z
|
|
372
|
+
.object({
|
|
373
|
+
...sessionMutationBase,
|
|
374
|
+
action: z.enum(["wake", "stop", "suspend", "close", "kill"]),
|
|
375
|
+
})
|
|
376
|
+
.strict(),
|
|
377
|
+
z
|
|
378
|
+
.object({
|
|
379
|
+
...sessionMutationBase,
|
|
380
|
+
action: z.literal("message"),
|
|
381
|
+
message: boundedString(GAS_CITY_LIMITS.prompt).min(1),
|
|
382
|
+
})
|
|
383
|
+
.strict(),
|
|
384
|
+
z
|
|
385
|
+
.object({
|
|
386
|
+
...sessionMutationBase,
|
|
387
|
+
action: z.literal("submit"),
|
|
388
|
+
message: boundedString(GAS_CITY_LIMITS.prompt).min(1),
|
|
389
|
+
intent: z.enum(["default", "follow_up", "interrupt_now"]),
|
|
390
|
+
})
|
|
391
|
+
.strict(),
|
|
392
|
+
z
|
|
393
|
+
.object({
|
|
394
|
+
...sessionMutationBase,
|
|
395
|
+
action: z.literal("respond"),
|
|
396
|
+
requestId: identifierSchema,
|
|
397
|
+
response: z.enum(["allow", "deny", "answer"]),
|
|
398
|
+
text: boundedNullableString(GAS_CITY_LIMITS.prompt),
|
|
399
|
+
metadata: BoundedMetadataSchema,
|
|
400
|
+
})
|
|
401
|
+
.strict(),
|
|
402
|
+
]);
|
|
403
|
+
|
|
404
|
+
export const SessionActionResultSchema = z
|
|
405
|
+
.object({
|
|
406
|
+
status: statusSchema,
|
|
407
|
+
sessionId: identifierSchema,
|
|
408
|
+
requestId: identifierSchema.nullable(),
|
|
409
|
+
eventCursor: boundedNullableString(GAS_CITY_LIMITS.cursor),
|
|
410
|
+
})
|
|
411
|
+
.strict();
|
|
412
|
+
|
|
413
|
+
export type GasCityDiagnostic = z.infer<typeof GasCityDiagnosticSchema>;
|
|
414
|
+
export type SupervisorDiscovery = z.infer<typeof SupervisorDiscoverySchema>;
|
|
415
|
+
export type WorkspaceRigMapping = z.infer<typeof WorkspaceRigMappingSchema>;
|
|
416
|
+
export type CityRigSnapshot = z.infer<typeof CityRigSnapshotSchema>;
|
|
417
|
+
export type GasCitySession = z.infer<typeof GasCitySessionSchema>;
|
|
418
|
+
export type SessionList = z.infer<typeof SessionListSchema>;
|
|
419
|
+
export type GasCityConvoy = z.infer<typeof GasCityConvoySchema>;
|
|
420
|
+
export type ConvoyList = z.infer<typeof ConvoyListSchema>;
|
|
421
|
+
export type GasCityWorkItem = z.infer<typeof GasCityWorkItemSchema>;
|
|
422
|
+
export type WorkList = z.infer<typeof WorkListSchema>;
|
|
423
|
+
export type GasCityEvent = z.infer<typeof GasCityEventSchema>;
|
|
424
|
+
export type EventList = z.infer<typeof EventListSchema>;
|
|
425
|
+
export type AttentionItem = z.infer<typeof AttentionItemSchema>;
|
|
426
|
+
export type AttentionList = z.infer<typeof AttentionListSchema>;
|
|
427
|
+
export type DispatchRequest = z.infer<typeof DispatchRequestSchema>;
|
|
428
|
+
export type DispatchResult = z.infer<typeof DispatchResultSchema>;
|
|
429
|
+
export type SessionActionRequest = z.infer<typeof SessionActionRequestSchema>;
|
|
430
|
+
export type SessionActionResult = z.infer<typeof SessionActionResultSchema>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { defineSettings } from "@getpaseo/plugin";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { GAS_CITY_LIMITS } from "./limits";
|
|
4
|
+
import { endpointUrlSchema, identifierSchema, nameSchema } from "./schemas";
|
|
5
|
+
|
|
6
|
+
export const DEFAULT_GAS_CITY_SETTINGS = {
|
|
7
|
+
endpointUrl: "http://127.0.0.1:8372",
|
|
8
|
+
allowRemoteEndpoint: false,
|
|
9
|
+
mutationsEnabled: false,
|
|
10
|
+
refreshIntervalMs: 10_000,
|
|
11
|
+
eventLimit: 100,
|
|
12
|
+
workspaceMappings: [],
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
export const WorkspaceMappingOverrideSchema = z
|
|
16
|
+
.object({
|
|
17
|
+
workspaceId: identifierSchema,
|
|
18
|
+
cityName: nameSchema,
|
|
19
|
+
rigName: nameSchema,
|
|
20
|
+
})
|
|
21
|
+
.strict();
|
|
22
|
+
|
|
23
|
+
const settingsShape = {
|
|
24
|
+
endpointUrl: endpointUrlSchema.default(DEFAULT_GAS_CITY_SETTINGS.endpointUrl),
|
|
25
|
+
allowRemoteEndpoint: z.boolean().default(DEFAULT_GAS_CITY_SETTINGS.allowRemoteEndpoint),
|
|
26
|
+
mutationsEnabled: z.boolean().default(DEFAULT_GAS_CITY_SETTINGS.mutationsEnabled),
|
|
27
|
+
refreshIntervalMs: z
|
|
28
|
+
.number()
|
|
29
|
+
.int()
|
|
30
|
+
.min(2_000)
|
|
31
|
+
.max(60_000)
|
|
32
|
+
.default(DEFAULT_GAS_CITY_SETTINGS.refreshIntervalMs),
|
|
33
|
+
eventLimit: z
|
|
34
|
+
.number()
|
|
35
|
+
.int()
|
|
36
|
+
.min(1)
|
|
37
|
+
.max(GAS_CITY_LIMITS.events)
|
|
38
|
+
.default(DEFAULT_GAS_CITY_SETTINGS.eventLimit),
|
|
39
|
+
workspaceMappings: z.array(WorkspaceMappingOverrideSchema).max(GAS_CITY_LIMITS.rigs).default([]),
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function rejectDuplicateWorkspaceMappings(
|
|
43
|
+
settings: { workspaceMappings: readonly WorkspaceMappingOverride[] },
|
|
44
|
+
context: z.RefinementCtx,
|
|
45
|
+
) {
|
|
46
|
+
const workspaceIds = new Set<string>();
|
|
47
|
+
for (const mapping of settings.workspaceMappings) {
|
|
48
|
+
if (workspaceIds.has(mapping.workspaceId)) {
|
|
49
|
+
context.addIssue({
|
|
50
|
+
code: "custom",
|
|
51
|
+
path: ["workspaceMappings"],
|
|
52
|
+
message: `Duplicate workspace mapping for ${mapping.workspaceId}`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
workspaceIds.add(mapping.workspaceId);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const GasCitySettingsBaseSchema = z.object(settingsShape).strict();
|
|
60
|
+
|
|
61
|
+
export const GasCitySettingsSchema = GasCitySettingsBaseSchema.superRefine(
|
|
62
|
+
rejectDuplicateWorkspaceMappings,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
export const GasCityRpcSettingsSchema = GasCitySettingsBaseSchema.omit({
|
|
66
|
+
refreshIntervalMs: true,
|
|
67
|
+
}).superRefine(rejectDuplicateWorkspaceMappings);
|
|
68
|
+
|
|
69
|
+
export type GasCityRpcSettings = z.infer<typeof GasCityRpcSettingsSchema>;
|
|
70
|
+
|
|
71
|
+
export function toGasCityRpcSettings(settings: GasCitySettings): GasCityRpcSettings {
|
|
72
|
+
return GasCityRpcSettingsSchema.parse({
|
|
73
|
+
endpointUrl: settings.endpointUrl,
|
|
74
|
+
allowRemoteEndpoint: settings.allowRemoteEndpoint,
|
|
75
|
+
mutationsEnabled: settings.mutationsEnabled,
|
|
76
|
+
eventLimit: settings.eventLimit,
|
|
77
|
+
workspaceMappings: settings.workspaceMappings,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type GasCitySettings = z.infer<typeof GasCitySettingsSchema>;
|
|
82
|
+
export type WorkspaceMappingOverride = z.infer<typeof WorkspaceMappingOverrideSchema>;
|
|
83
|
+
|
|
84
|
+
export const gasCitySettings = defineSettings({
|
|
85
|
+
id: "gas-city",
|
|
86
|
+
scope: "host",
|
|
87
|
+
version: 1,
|
|
88
|
+
schema: GasCitySettingsSchema,
|
|
89
|
+
});
|