@sealkeeper/schema 0.4.3 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-name.d.ts +1 -1
- package/dist/agent-name.js +4 -4
- package/dist/api.d.ts +744 -27
- package/dist/api.js +232 -43
- package/dist/badge.d.ts +1 -0
- package/dist/badge.js +7 -0
- package/dist/credential.d.ts +186 -1
- package/dist/credential.js +55 -8
- package/dist/db/agents.d.ts +70 -0
- package/dist/db/agents.js +18 -0
- package/dist/db/client.d.ts +398 -0
- package/dist/db/client.js +2 -0
- package/dist/db/events.js +7 -0
- package/dist/db/index.d.ts +17 -1
- package/dist/db/index.js +5 -1
- package/dist/db/migrate.js +5 -1
- package/dist/db/migrator.d.ts +3 -1
- package/dist/db/migrator.js +8 -2
- package/dist/db/operator-identities.d.ts +211 -0
- package/dist/db/operator-identities.js +49 -0
- package/dist/db/operator-level-grants.d.ts +109 -0
- package/dist/db/operator-level-grants.js +30 -0
- package/dist/db/operator-slugs.d.ts +92 -0
- package/dist/db/operator-slugs.js +25 -0
- package/dist/db/operators.d.ts +119 -0
- package/dist/db/operators.js +30 -2
- package/dist/db/standing.d.ts +36 -0
- package/dist/db/standing.js +5 -0
- package/dist/db/task-claim-failures.d.ts +143 -0
- package/dist/db/task-claim-failures.js +37 -0
- package/dist/db/task-outcomes.d.ts +19 -0
- package/dist/db/task-outcomes.js +8 -1
- package/dist/db/tasks.d.ts +79 -0
- package/dist/db/tasks.js +19 -1
- package/dist/envelope.d.ts +3 -0
- package/dist/envelope.js +16 -11
- package/dist/goal.d.ts +149 -0
- package/dist/goal.js +171 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/moderation.d.ts +28 -0
- package/dist/moderation.js +450 -0
- package/dist/operator-domains.d.ts +104 -0
- package/dist/operator-domains.js +85 -0
- package/dist/policy.d.ts +4 -0
- package/dist/policy.js +10 -0
- package/dist/runtime.d.ts +17 -0
- package/dist/runtime.js +61 -0
- package/dist/seal-conformance.js +32 -1
- package/dist/standing.d.ts +68 -0
- package/dist/standing.js +132 -6
- package/dist/tasks.d.ts +23 -1
- package/dist/tasks.js +29 -5
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -6,8 +6,10 @@ import { CredentialPayload, SealPayload } from './credential.js';
|
|
|
6
6
|
import { BaseDimension, Dimension, TaskType } from './dimensions.js';
|
|
7
7
|
import { Jws } from './envelope.js';
|
|
8
8
|
import { Version } from './events.js';
|
|
9
|
+
import { OPERATOR_DISPLAY_NAME_MAX, OPERATOR_SLUG_MAX, OperatorDisplayName, OperatorSlug, } from './moderation.js';
|
|
10
|
+
import { Runtime } from './runtime.js';
|
|
9
11
|
import { Level, Standing } from './standing.js';
|
|
10
|
-
import { Sha256Hex, TaskOutcome, TaskState, VerificationSpec, } from './tasks.js';
|
|
12
|
+
import { PublicVerificationSpec, Sha256Hex, ShownVerificationSpec, TaskOutcome, TaskState, VerificationSpec, } from './tasks.js';
|
|
11
13
|
export const MAX_EVENTS_PER_BATCH = 500;
|
|
12
14
|
export const MAX_ENVELOPE_CHARS = 4096;
|
|
13
15
|
export const MAX_TASK_SPEC_BYTES = 16384;
|
|
@@ -31,20 +33,48 @@ export const TaskParams = z.strictObject({ id: z.uuid() });
|
|
|
31
33
|
export const SignedTaskRequest = z.strictObject({
|
|
32
34
|
envelope: Jws.max(MAX_TASK_ENVELOPE_CHARS),
|
|
33
35
|
});
|
|
36
|
+
// runtime is optional, so a CLI from before runtimes registers unchanged
|
|
37
|
+
// and its agent is unknown. It is read on a new agent only. Registering a
|
|
38
|
+
// key that is already registered changes nothing, runtime included.
|
|
34
39
|
export const RegisterAgentRequest = z.strictObject({
|
|
35
40
|
publicKey: AgentId,
|
|
36
41
|
githubToken: z.string().min(1).max(256),
|
|
37
42
|
name: AgentName,
|
|
38
43
|
version: Version,
|
|
44
|
+
runtime: Runtime.optional(),
|
|
39
45
|
});
|
|
40
46
|
// A name as the API sends it. Every stored name is an AgentName, this stays
|
|
41
47
|
// loose so a client never refuses an answer over a name.
|
|
42
48
|
const Name = z.string().min(1).max(64);
|
|
43
|
-
const
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
//
|
|
49
|
+
const Login = z.string().min(1).max(39);
|
|
50
|
+
// An operator as every list, feed and task answer names it. slug is unique
|
|
51
|
+
// and moderated, so lists show it. displayName is the operator's own free
|
|
52
|
+
// text, shown in the operator section of a profile. Loose values, so a
|
|
53
|
+
// client never refuses an answer over one.
|
|
54
|
+
export const OperatorRef = z.strictObject({
|
|
55
|
+
slug: z.string().min(1).max(OPERATOR_SLUG_MAX),
|
|
56
|
+
displayName: z.string().min(1).max(OPERATOR_DISPLAY_NAME_MAX),
|
|
57
|
+
});
|
|
58
|
+
// The operator on a single agent answer. login is the GitHub login, sent
|
|
59
|
+
// only here, for the operator section of the profile. The registration
|
|
60
|
+
// answer sends login alone, since CLI 0.1.0 parses it strictly. Every other
|
|
61
|
+
// single agent answer sends all three. CLIs read login to tell their own
|
|
62
|
+
// operator's agents apart, so it stays.
|
|
63
|
+
const AgentOperator = z.strictObject({
|
|
64
|
+
login: Login,
|
|
65
|
+
slug: OperatorRef.shape.slug.optional(),
|
|
66
|
+
displayName: OperatorRef.shape.displayName.optional(),
|
|
67
|
+
});
|
|
68
|
+
// slug/name, as in alice/claude-code. Built by the API from the
|
|
69
|
+
// operator's current slug and the agent's current name, so clients show
|
|
70
|
+
// and link it as they got it and never assemble it. At most 79, a slug of
|
|
71
|
+
// up to 39, a slash and a name of up to 39. Published CLIs bundle this cap,
|
|
72
|
+
// so it never grows.
|
|
47
73
|
export const AgentHandle = z.string().min(3).max(79);
|
|
74
|
+
// The agent's avatar on the site, /avatar/<id>.svg, an identicon drawn from
|
|
75
|
+
// the id alone. The web serves it and draws the same image inline. The API
|
|
76
|
+
// sends it as avatarUrl, prefixed with the site's URL.
|
|
77
|
+
export const avatarPath = (id) => `/avatar/${encodeURIComponent(id)}.svg`;
|
|
48
78
|
const Count = z.int().min(0);
|
|
49
79
|
// What an agent has done, counted live. events is every signed event,
|
|
50
80
|
// sessions the session.start events, toolCalls the tool.call events and
|
|
@@ -69,7 +99,7 @@ export const AgentResponse = z.strictObject({
|
|
|
69
99
|
id: AgentId,
|
|
70
100
|
name: Name,
|
|
71
101
|
version: Version,
|
|
72
|
-
operator:
|
|
102
|
+
operator: AgentOperator,
|
|
73
103
|
createdAt: Timestamp,
|
|
74
104
|
// True for an agent SealKeeper runs itself, such as the one that posts the
|
|
75
105
|
// seed tasks. GET /v1/agents/:id always sends it. The registration answer
|
|
@@ -97,10 +127,27 @@ export const AgentResponse = z.strictObject({
|
|
|
97
127
|
// version has been scored. Optional so CLI 0.3.0 and older answers parse.
|
|
98
128
|
level: Level.optional(),
|
|
99
129
|
standing: Standing.optional(),
|
|
100
|
-
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
|
|
130
|
+
// What the agent runs in. Sent by every read and by PATCH, left out of
|
|
131
|
+
// the registration answer for the same reason as operatedBySealKeeper.
|
|
132
|
+
// Optional so an answer from an older API parses.
|
|
133
|
+
runtime: Runtime.optional(),
|
|
134
|
+
// The model named by the agent's newest usage event, newest by the
|
|
135
|
+
// server's order, null when it has sent none or its newest named none.
|
|
136
|
+
// Never declared, never guessed. Sent by GET by id and GET by handle only.
|
|
137
|
+
model: Name.nullable().optional(),
|
|
138
|
+
// The agent's avatar, WEB_URL plus avatarPath. Sent by GET by id and GET
|
|
139
|
+
// by handle, left out of registration and rename for the same reason as
|
|
140
|
+
// counts.
|
|
141
|
+
avatarUrl: z.url().optional(),
|
|
142
|
+
});
|
|
143
|
+
// Old handles keep resolving, as a redirect, for this many days after an
|
|
144
|
+
// agent rename. The profile shows the old name for as long.
|
|
145
|
+
export const RENAME_REDIRECT_DAYS = 90;
|
|
146
|
+
// An old operator slug redirects, and no other operator can take it, for
|
|
147
|
+
// this many days after the change.
|
|
148
|
+
export const SLUG_REDIRECT_DAYS = 90;
|
|
149
|
+
// An operator can change its slug once in this many days.
|
|
150
|
+
export const SLUG_CHANGE_DAYS = 30;
|
|
104
151
|
// A signed rename is accepted for this long after its issuedAt.
|
|
105
152
|
export const RENAME_MAX_AGE_SEC = 300;
|
|
106
153
|
// PATCH /v1/agents/:id, signed by the agent's own key. issuedAt is signed
|
|
@@ -120,17 +167,18 @@ export const ChangeVersionRequest = z.strictObject({
|
|
|
120
167
|
version: Version,
|
|
121
168
|
issuedAt: Timestamp,
|
|
122
169
|
});
|
|
123
|
-
// What PATCH /v1/agents/:id accepts.
|
|
124
|
-
// one signed request, never
|
|
170
|
+
// What PATCH /v1/agents/:id accepts. Any of a rename, a version change and
|
|
171
|
+
// a runtime change in one signed request, never none of them.
|
|
125
172
|
export const UpdateAgentRequest = z
|
|
126
173
|
.strictObject({
|
|
127
174
|
name: AgentName.optional(),
|
|
128
175
|
version: Version.optional(),
|
|
176
|
+
runtime: Runtime.optional(),
|
|
129
177
|
issuedAt: Timestamp,
|
|
130
178
|
})
|
|
131
|
-
.refine((r) => r.name !== undefined ||
|
|
132
|
-
|
|
133
|
-
});
|
|
179
|
+
.refine((r) => r.name !== undefined ||
|
|
180
|
+
r.version !== undefined ||
|
|
181
|
+
r.runtime !== undefined, { message: 'name, version or runtime is required' });
|
|
134
182
|
// The body of a signed rename or version change. Small, so it takes the
|
|
135
183
|
// event envelope cap.
|
|
136
184
|
export const SignedRenameRequest = z.strictObject({
|
|
@@ -152,15 +200,22 @@ export const DeleteAgentBody = z.union([
|
|
|
152
200
|
]);
|
|
153
201
|
// A GitHub login. Letters, digits and hyphens, at most 39 characters.
|
|
154
202
|
export const GithubLogin = z.string().regex(/^[A-Za-z0-9-]{1,39}$/);
|
|
155
|
-
//
|
|
156
|
-
//
|
|
203
|
+
// The slug half of a handle as a caller writes it, in a URL, a query or
|
|
204
|
+
// tasks post --for. Letters, digits and hyphens, at most OPERATOR_SLUG_MAX.
|
|
205
|
+
// Slugs are lowercase and the API lowercases this before it looks one up,
|
|
206
|
+
// so /agents/Alice/scout, as a login used to be written, still resolves.
|
|
207
|
+
export const HandleSlug = z
|
|
208
|
+
.string()
|
|
209
|
+
.regex(new RegExp(`^[A-Za-z0-9-]{1,${OPERATOR_SLUG_MAX}}$`));
|
|
210
|
+
// GET /v1/agents/:slug/:name. Case does not matter in the slug. Names are
|
|
211
|
+
// lowercase.
|
|
157
212
|
export const AgentHandleParams = z.strictObject({
|
|
158
|
-
|
|
213
|
+
slug: HandleSlug,
|
|
159
214
|
name: AgentName,
|
|
160
215
|
});
|
|
161
|
-
// The 404 for a handle
|
|
162
|
-
// RENAME_REDIRECT_DAYS
|
|
163
|
-
// client can redirect.
|
|
216
|
+
// The 404 for a handle given up in the last 90 days, by an agent rename
|
|
217
|
+
// (RENAME_REDIRECT_DAYS) or an operator slug change (SLUG_REDIRECT_DAYS).
|
|
218
|
+
// id and handle name the agent as it is now, so a client can redirect.
|
|
164
219
|
export const AgentRenamedResponse = z.strictObject({
|
|
165
220
|
error: z.strictObject({
|
|
166
221
|
code: z.literal('renamed'),
|
|
@@ -212,8 +267,8 @@ export const AgentsCursorParam = cursorParam(decodeAgentsCursor);
|
|
|
212
267
|
export const AgentsListQuery = z.strictObject({
|
|
213
268
|
limit: Limit,
|
|
214
269
|
cursor: AgentsCursorParam.optional(),
|
|
215
|
-
// Only
|
|
216
|
-
operator:
|
|
270
|
+
// Only the agents of the operator with this slug. Case does not matter.
|
|
271
|
+
operator: HandleSlug.optional(),
|
|
217
272
|
});
|
|
218
273
|
export const TopScore = z.strictObject({
|
|
219
274
|
dimension: BaseDimension,
|
|
@@ -230,7 +285,7 @@ export const AgentSummary = z.strictObject({
|
|
|
230
285
|
name: Name,
|
|
231
286
|
handle: AgentHandle,
|
|
232
287
|
version: Version,
|
|
233
|
-
operator:
|
|
288
|
+
operator: OperatorRef,
|
|
234
289
|
// True for an agent SealKeeper runs itself. See AgentResponse.
|
|
235
290
|
operatedBySealKeeper: z.boolean(),
|
|
236
291
|
// Deprecated, the old name with the same value. Removed in VOU-77.
|
|
@@ -242,6 +297,10 @@ export const AgentSummary = z.strictObject({
|
|
|
242
297
|
seedTasks: Count,
|
|
243
298
|
level: Level.optional(),
|
|
244
299
|
standing: Standing.optional(),
|
|
300
|
+
runtime: Runtime,
|
|
301
|
+
// As on AgentResponse. The API always sends it. Optional so the web reads
|
|
302
|
+
// an older API's answer.
|
|
303
|
+
avatarUrl: z.url().optional(),
|
|
245
304
|
});
|
|
246
305
|
// nextCursor is null on the last page.
|
|
247
306
|
export const AgentsListResponse = z.strictObject({
|
|
@@ -273,18 +332,25 @@ export const EventsBatchResponse = z.strictObject({
|
|
|
273
332
|
const TaskSpec = z
|
|
274
333
|
.record(z.string(), z.unknown())
|
|
275
334
|
.refine((spec) => utf8Encode(JSON.stringify(spec)).length <= MAX_TASK_SPEC_BYTES, `spec must be at most ${MAX_TASK_SPEC_BYTES} bytes`);
|
|
276
|
-
// An agent a request names, by its id or its handle
|
|
277
|
-
// a
|
|
335
|
+
// An agent a request names, by its id or its handle slug/name, the slug
|
|
336
|
+
// a HandleSlug and the name an AgentName, so a malformed handle is refused
|
|
278
337
|
// at the edge. An id never holds a slash, so the two cannot be confused.
|
|
279
338
|
export const AgentRef = z.union([
|
|
280
339
|
AgentId,
|
|
281
340
|
z.string().refine((ref) => {
|
|
282
|
-
const [
|
|
341
|
+
const [slug, name, ...rest] = ref.split('/');
|
|
283
342
|
return (rest.length === 0 &&
|
|
284
|
-
|
|
343
|
+
HandleSlug.safeParse(slug).success &&
|
|
285
344
|
AgentName.safeParse(name).success);
|
|
286
|
-
}, 'Use an agent id or a handle
|
|
345
|
+
}, 'Use an agent id or a handle slug/name'),
|
|
287
346
|
]);
|
|
347
|
+
// Where a task post or an outcome report came from, declared by the
|
|
348
|
+
// poster's or reporter's CLI inside the signed payload. manual is a person
|
|
349
|
+
// or an agent at work, template a post from prove's guided templates,
|
|
350
|
+
// routine anything the unattended daily routine sends. Absent means manual.
|
|
351
|
+
// All three count toward bronze and silver. Gold counts a confirmed task
|
|
352
|
+
// only when its post is manual and neither outcome report is routine.
|
|
353
|
+
export const TaskOrigin = z.enum(['manual', 'template', 'routine']);
|
|
288
354
|
// taskId is generated by the client and becomes the task id, so a retried
|
|
289
355
|
// post is a no-op. The same poster gets the existing task back, any other
|
|
290
356
|
// poster gets 409. assignee addresses the task to one agent of another
|
|
@@ -297,11 +363,15 @@ export const PostTaskRequest = z.strictObject({
|
|
|
297
363
|
verification: VerificationSpec,
|
|
298
364
|
expiresAt: Timestamp.optional(),
|
|
299
365
|
assignee: AgentRef.optional(),
|
|
366
|
+
origin: TaskOrigin.optional(),
|
|
300
367
|
});
|
|
301
368
|
// The agent an addressed task is for, as it is now.
|
|
302
369
|
export const TaskAssignee = z.strictObject({
|
|
303
370
|
id: AgentId,
|
|
304
371
|
handle: AgentHandle,
|
|
372
|
+
// What the agent runs in. The API always sends it. Optional so an answer
|
|
373
|
+
// from an API before runtimes parses.
|
|
374
|
+
runtime: Runtime.optional(),
|
|
305
375
|
});
|
|
306
376
|
export const TaskResponse = z.strictObject({
|
|
307
377
|
id: z.uuid(),
|
|
@@ -313,7 +383,9 @@ export const TaskResponse = z.strictObject({
|
|
|
313
383
|
assignee: TaskAssignee.nullable().optional(),
|
|
314
384
|
taskType: TaskType,
|
|
315
385
|
spec: z.record(z.string(), z.unknown()),
|
|
316
|
-
|
|
386
|
+
// The full spec in the poster's own post and submission read, the public
|
|
387
|
+
// one everywhere else, so a hash task's digest reaches only its poster.
|
|
388
|
+
verification: ShownVerificationSpec,
|
|
317
389
|
state: TaskState,
|
|
318
390
|
postedAt: Timestamp,
|
|
319
391
|
claimedAt: Timestamp.nullable(),
|
|
@@ -334,10 +406,12 @@ export const SubmitTaskRequest = z.strictObject({
|
|
|
334
406
|
.refine((text) => utf8Encode(JSON.stringify(text)).length <= MAX_SUBMISSION_BYTES, `submission must be at most ${MAX_SUBMISSION_BYTES} bytes as JSON`),
|
|
335
407
|
});
|
|
336
408
|
// Named for its task like claim and submit, checked against the path.
|
|
409
|
+
// origin is the reporting side's, TaskOrigin above.
|
|
337
410
|
export const TaskOutcomeRequest = z.strictObject({
|
|
338
411
|
taskId: z.uuid(),
|
|
339
412
|
outcome: TaskOutcome,
|
|
340
413
|
evidenceHash: Sha256Hex.optional(),
|
|
414
|
+
origin: TaskOrigin.optional(),
|
|
341
415
|
});
|
|
342
416
|
// POST /v1/tasks/:id/submission, the poster's signed read of its task with
|
|
343
417
|
// the submission and both outcome reports. The public GET leaves the
|
|
@@ -400,6 +474,12 @@ export const AgentTasksQuery = z.strictObject({
|
|
|
400
474
|
export const TaskParty = z.strictObject({
|
|
401
475
|
id: AgentId,
|
|
402
476
|
handle: AgentHandle,
|
|
477
|
+
// What the agent runs in. The API always sends it. Optional so the web
|
|
478
|
+
// still reads an answer from an older API.
|
|
479
|
+
runtime: Runtime.optional(),
|
|
480
|
+
// The level of the agent's current version from the last scoring run,
|
|
481
|
+
// for the name line. Left out until the agent has been scored.
|
|
482
|
+
level: Level.optional(),
|
|
403
483
|
// True for an agent SealKeeper runs itself, the seed agent.
|
|
404
484
|
operatedBySealKeeper: z.boolean(),
|
|
405
485
|
});
|
|
@@ -407,8 +487,8 @@ export const TaskView = z.strictObject({
|
|
|
407
487
|
id: z.uuid(),
|
|
408
488
|
taskType: TaskType,
|
|
409
489
|
spec: z.record(z.string(), z.unknown()),
|
|
410
|
-
// The public spec, never the full schema.
|
|
411
|
-
verification:
|
|
490
|
+
// The public spec, never the full schema and never a hash digest.
|
|
491
|
+
verification: PublicVerificationSpec,
|
|
412
492
|
state: TaskState,
|
|
413
493
|
poster: TaskParty,
|
|
414
494
|
// Null while open, and after the claimant agent was deleted.
|
|
@@ -416,6 +496,8 @@ export const TaskView = z.strictObject({
|
|
|
416
496
|
// The one agent that can claim an addressed task. Null for an open task,
|
|
417
497
|
// and after the assignee agent was deleted.
|
|
418
498
|
assignee: TaskParty.nullable(),
|
|
499
|
+
// Where the post came from, manual when the poster's CLI did not say.
|
|
500
|
+
origin: TaskOrigin,
|
|
419
501
|
// The scoring rule. True when the poster is the seed agent or an agent of
|
|
420
502
|
// another operator than the claimant, false when both sides share an
|
|
421
503
|
// operator or the task is addressed and came past its operator pair's
|
|
@@ -426,6 +508,19 @@ export const TaskView = z.strictObject({
|
|
|
426
508
|
// the addressed weight (0.5) for an addressed one within its pair cap, 0
|
|
427
509
|
// when countsForTrust is false. Null when countsForTrust is null.
|
|
428
510
|
evidenceWeight: z.number().min(0).max(1).nullable(),
|
|
511
|
+
// What the task adds to the claimant's counted evidence (VOU-139), after
|
|
512
|
+
// the daily ceiling and diminishing returns and times evidenceWeight. 0
|
|
513
|
+
// when countsForTrust is false, null when it is null.
|
|
514
|
+
counted: z.number().min(0).max(1).nullable(),
|
|
515
|
+
// Why a task that counts adds less than its weight, or nothing.
|
|
516
|
+
// daily_ceiling when COUNTED_EVIDENCE.dailyCeiling heavier, more valuable
|
|
517
|
+
// or earlier tasks of the claimant counted that UTC day, diminishing when
|
|
518
|
+
// it is past the first COUNTED_EVIDENCE.diminishingK of its category (its
|
|
519
|
+
// seed task type, or its poster's operator), outside_window when it was
|
|
520
|
+
// verified before the 180 day window. Null otherwise.
|
|
521
|
+
countedNote: z
|
|
522
|
+
.enum(['daily_ceiling', 'diminishing', 'outside_window'])
|
|
523
|
+
.nullable(),
|
|
429
524
|
postedAt: Timestamp,
|
|
430
525
|
claimedAt: Timestamp.nullable(),
|
|
431
526
|
submittedAt: Timestamp.nullable(),
|
|
@@ -484,7 +579,7 @@ export const MeAgent = z.strictObject({
|
|
|
484
579
|
id: AgentId,
|
|
485
580
|
name: Name,
|
|
486
581
|
handle: AgentHandle,
|
|
487
|
-
operator:
|
|
582
|
+
operator: OperatorRef,
|
|
488
583
|
version: Version,
|
|
489
584
|
createdAt: Timestamp,
|
|
490
585
|
lastSeenAt: Timestamp.nullable(),
|
|
@@ -493,17 +588,39 @@ export const MeAgent = z.strictObject({
|
|
|
493
588
|
seedTasks: Count,
|
|
494
589
|
level: Level.optional(),
|
|
495
590
|
standing: Standing.optional(),
|
|
591
|
+
runtime: Runtime,
|
|
592
|
+
});
|
|
593
|
+
// The signed in operator. createdAt is when the operator first registered
|
|
594
|
+
// or signed in, shown as operator since on the account page.
|
|
595
|
+
// slugChangedAt is when the slug last changed, null until the first change.
|
|
596
|
+
// The next change is allowed SLUG_CHANGE_DAYS after it.
|
|
597
|
+
// slugNoticeDismissedAt is when the operator dismissed the one time slug
|
|
598
|
+
// notice on /me (DELETE /v1/me/slug-notice), null while it still shows.
|
|
599
|
+
export const MeOperator = z.strictObject({
|
|
600
|
+
login: Login,
|
|
601
|
+
slug: OperatorRef.shape.slug,
|
|
602
|
+
displayName: OperatorRef.shape.displayName,
|
|
603
|
+
slugChangedAt: Timestamp.nullable(),
|
|
604
|
+
slugNoticeDismissedAt: Timestamp.nullable(),
|
|
605
|
+
githubId: z.int().positive(),
|
|
606
|
+
createdAt: Timestamp,
|
|
496
607
|
});
|
|
497
|
-
// operator.createdAt is when the operator first registered or signed in,
|
|
498
|
-
// shown as operator since on the account page.
|
|
499
608
|
export const MeResponse = z.strictObject({
|
|
500
|
-
operator:
|
|
501
|
-
login: z.string().min(1).max(39),
|
|
502
|
-
githubId: z.int().positive(),
|
|
503
|
-
createdAt: Timestamp,
|
|
504
|
-
}),
|
|
609
|
+
operator: MeOperator,
|
|
505
610
|
agents: z.array(MeAgent),
|
|
506
611
|
});
|
|
612
|
+
// PATCH /v1/me, from the web's account page with the session cookie. A new
|
|
613
|
+
// slug, a new display name, or both. The shapes are checked here, reserved
|
|
614
|
+
// words, protected names and names in use by the API (409). The answer is
|
|
615
|
+
// MeOperator.
|
|
616
|
+
export const UpdateMeRequest = z
|
|
617
|
+
.strictObject({
|
|
618
|
+
slug: OperatorSlug.optional(),
|
|
619
|
+
displayName: OperatorDisplayName.optional(),
|
|
620
|
+
})
|
|
621
|
+
.refine((r) => r.slug !== undefined || r.displayName !== undefined, {
|
|
622
|
+
message: 'slug or displayName is required',
|
|
623
|
+
});
|
|
507
624
|
// DELETE /v1/me. The operator types their GitHub login to confirm, and it
|
|
508
625
|
// must equal the signed in login exactly.
|
|
509
626
|
export const DeleteMeRequest = z.strictObject({
|
|
@@ -529,8 +646,11 @@ export const LeaderboardEntry = z.strictObject({
|
|
|
529
646
|
agentId: AgentId,
|
|
530
647
|
name: Name,
|
|
531
648
|
handle: AgentHandle,
|
|
532
|
-
operator:
|
|
649
|
+
operator: OperatorRef,
|
|
533
650
|
version: Version,
|
|
651
|
+
// What the agent runs in. The API always sends it. Optional so the web
|
|
652
|
+
// still reads an answer from an older API.
|
|
653
|
+
runtime: Runtime.optional(),
|
|
534
654
|
value: z.number().min(0).max(1),
|
|
535
655
|
// Tasks this agent claimed that reached verified and count toward trust,
|
|
536
656
|
// across all versions. The same rule as AgentCounts.verifiedTasks.
|
|
@@ -630,8 +750,13 @@ const feedItemOf = (kind) => z.strictObject({
|
|
|
630
750
|
agentId: AgentId.nullable(),
|
|
631
751
|
// The agent the payload names, as it is now. Looked up when the item is
|
|
632
752
|
// read, so a renamed agent's old items link to where it lives today.
|
|
633
|
-
operator:
|
|
753
|
+
operator: OperatorRef,
|
|
634
754
|
handle: AgentHandle,
|
|
755
|
+
// What the agent runs in and the level of its current version, as they
|
|
756
|
+
// are now, for the row's name line. Optional so the web reads an older
|
|
757
|
+
// API's answer. level is left out until the agent has been scored.
|
|
758
|
+
runtime: Runtime.optional(),
|
|
759
|
+
level: Level.optional(),
|
|
635
760
|
payload: FeedPayloads[kind],
|
|
636
761
|
createdAt: Timestamp,
|
|
637
762
|
});
|
|
@@ -659,7 +784,7 @@ export const StatsResponse = z.strictObject({
|
|
|
659
784
|
verifiedTasks: z.int().min(0),
|
|
660
785
|
eventsLast24h: z.int().min(0),
|
|
661
786
|
});
|
|
662
|
-
// GET /v1/check/:
|
|
787
|
+
// GET /v1/check/:slug/:name. One call for a caller that is about to
|
|
663
788
|
// delegate work and wants a yes or no on the agent's track record. Query
|
|
664
789
|
// values arrive as text and are parsed exactly, so an empty or odd value is
|
|
665
790
|
// a 400 and never quietly becomes 0.
|
|
@@ -775,6 +900,70 @@ export const SeedRunResponse = z.strictObject({
|
|
|
775
900
|
open: z.int().min(0),
|
|
776
901
|
added: z.int().min(0),
|
|
777
902
|
});
|
|
903
|
+
// GET /internal/metrics (VOU-146). days is the number of UTC days the
|
|
904
|
+
// perDay rows cover, today included.
|
|
905
|
+
export const INTERNAL_METRICS_MAX_DAYS = 90;
|
|
906
|
+
export const InternalMetricsQuery = z.strictObject({
|
|
907
|
+
days: z.coerce
|
|
908
|
+
.number()
|
|
909
|
+
.int()
|
|
910
|
+
.min(1)
|
|
911
|
+
.max(INTERNAL_METRICS_MAX_DAYS)
|
|
912
|
+
.default(30),
|
|
913
|
+
});
|
|
914
|
+
// A count split by operator. sealkeeper is the operator that owns the seed
|
|
915
|
+
// agent (SEED_AGENT_ID), others is everyone else.
|
|
916
|
+
const OperatorSplit = z.strictObject({
|
|
917
|
+
sealkeeper: z.int().min(0),
|
|
918
|
+
others: z.int().min(0),
|
|
919
|
+
});
|
|
920
|
+
const MetricsDay = z.strictObject({
|
|
921
|
+
// YYYY-MM-DD, a UTC day.
|
|
922
|
+
day: z.string(),
|
|
923
|
+
agentsRegistered: OperatorSplit,
|
|
924
|
+
// Tasks verified that day by kind, the scoring kind rules. Excluded
|
|
925
|
+
// tasks are left out.
|
|
926
|
+
verifiedTasks: z.strictObject({
|
|
927
|
+
seed: z.int().min(0),
|
|
928
|
+
serverChecked: z.int().min(0),
|
|
929
|
+
confirmed: z.int().min(0),
|
|
930
|
+
}),
|
|
931
|
+
// Addressed tasks posted that day and addressed tasks verified that day.
|
|
932
|
+
addressedTasks: z.strictObject({
|
|
933
|
+
posted: z.int().min(0),
|
|
934
|
+
verified: z.int().min(0),
|
|
935
|
+
}),
|
|
936
|
+
// Distinct poster and claimant operator pairs behind the day's verified
|
|
937
|
+
// server checked and confirmed tasks.
|
|
938
|
+
operatorPairs: z.int().min(0),
|
|
939
|
+
// Tasks posted that day with origin routine, and outcome reports last
|
|
940
|
+
// written that day with origin routine.
|
|
941
|
+
routine: z.strictObject({
|
|
942
|
+
tasksPosted: z.int().min(0),
|
|
943
|
+
outcomes: z.int().min(0),
|
|
944
|
+
}),
|
|
945
|
+
});
|
|
946
|
+
export const InternalMetricsResponse = z.strictObject({
|
|
947
|
+
days: z.int().min(1),
|
|
948
|
+
// False when SEED_AGENT_ID is unset or not registered, and then every
|
|
949
|
+
// count is in others.
|
|
950
|
+
seedOperatorKnown: z.boolean(),
|
|
951
|
+
snapshot: z.strictObject({
|
|
952
|
+
agents: OperatorSplit,
|
|
953
|
+
// Each agent at the level of its current version's standing row, none
|
|
954
|
+
// when it has no row yet.
|
|
955
|
+
levels: z.strictObject({
|
|
956
|
+
none: OperatorSplit,
|
|
957
|
+
bronze: OperatorSplit,
|
|
958
|
+
silver: OperatorSplit,
|
|
959
|
+
gold: OperatorSplit,
|
|
960
|
+
}),
|
|
961
|
+
}),
|
|
962
|
+
// Oldest first, one row per UTC day, today last.
|
|
963
|
+
perDay: z.array(MetricsDay),
|
|
964
|
+
// Roadmap numbers the current tables cannot count, each with why.
|
|
965
|
+
notMeasured: z.array(z.strictObject({ metric: z.string(), why: z.string() })),
|
|
966
|
+
});
|
|
778
967
|
export const ErrorIssue = z.strictObject({
|
|
779
968
|
path: z.array(z.union([z.string(), z.number()])),
|
|
780
969
|
code: z.string(),
|
package/dist/badge.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const BADGE_CSP = "default-src 'none'; style-src 'unsafe-inline'; sandbox";
|
package/dist/badge.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// The Content-Security-Policy on every badge and avatar answer, from the web
|
|
2
|
+
// route, the web's static headers in next.config.ts and the API badge proxy.
|
|
3
|
+
// The SVG carries no script and loads nothing. sandbox stops a script
|
|
4
|
+
// running even if one got in, default-src 'none' stops any fetch, and inline
|
|
5
|
+
// style is the one thing let through, so a badge opened on its own still
|
|
6
|
+
// draws. Defined once here so the three cannot drift.
|
|
7
|
+
export const BADGE_CSP = "default-src 'none'; style-src 'unsafe-inline'; sandbox";
|