@anchrd/colab-sdk 0.0.0-stage → 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/README.md +65 -2
- package/dist/actions/actions.d.ts +810 -0
- package/dist/actions/actions.js +177 -0
- package/dist/admin-mode.d.ts +2 -0
- package/dist/admin-mode.js +5 -0
- package/dist/apps/apps.d.ts +108 -0
- package/dist/apps/apps.js +73 -0
- package/dist/archive/archive.d.ts +25 -0
- package/dist/archive/archive.js +27 -0
- package/dist/auth/auth.d.ts +27 -0
- package/dist/auth/auth.js +22 -0
- package/dist/authorization/authorization.d.ts +36 -0
- package/dist/authorization/authorization.js +23 -0
- package/dist/boards/boards.d.ts +612 -0
- package/dist/boards/boards.js +289 -0
- package/dist/columns/columns.d.ts +28 -0
- package/dist/columns/columns.js +28 -0
- package/dist/connections/connections.d.ts +149 -0
- package/dist/connections/connections.js +74 -0
- package/dist/connectors/connectors.d.ts +148 -0
- package/dist/connectors/connectors.js +83 -0
- package/dist/dashboards/dashboards.d.ts +221 -0
- package/dist/dashboards/dashboards.js +520 -0
- package/dist/directory/directory.d.ts +20 -0
- package/dist/directory/directory.js +18 -0
- package/dist/documents/documents.d.ts +61 -0
- package/dist/documents/documents.js +58 -0
- package/dist/error/error.d.ts +34 -0
- package/dist/error/error.js +30 -0
- package/dist/events/events.d.ts +104 -0
- package/dist/events/events.js +69 -0
- package/dist/files/files.d.ts +60 -0
- package/dist/files/files.js +139 -0
- package/dist/functions/functions.d.ts +26 -0
- package/dist/functions/functions.js +28 -0
- package/dist/grammar/grammar.d.ts +62 -0
- package/dist/grammar/grammar.js +197 -0
- package/dist/grants/grants.d.ts +93 -0
- package/dist/grants/grants.js +66 -0
- package/dist/ids/ids.d.ts +5 -0
- package/dist/ids/ids.js +12 -0
- package/dist/instructions/instructions.d.ts +19 -0
- package/dist/instructions/instructions.js +35 -0
- package/dist/interfaces/interfaces.d.ts +41 -0
- package/dist/interfaces/interfaces.js +52 -0
- package/dist/invitations/invitations.d.ts +98 -0
- package/dist/invitations/invitations.js +58 -0
- package/dist/links/links.d.ts +76 -0
- package/dist/links/links.js +73 -0
- package/dist/list-input.d.ts +3 -0
- package/dist/list-input.js +11 -0
- package/dist/machines/machines.d.ts +69 -0
- package/dist/machines/machines.js +39 -0
- package/dist/messages/messages.d.ts +117 -0
- package/dist/messages/messages.js +77 -0
- package/dist/nodes/nodes.d.ts +673 -0
- package/dist/nodes/nodes.js +354 -0
- package/dist/operators/operators.d.ts +898 -0
- package/dist/operators/operators.js +398 -0
- package/dist/pages/pages.d.ts +89 -0
- package/dist/pages/pages.js +62 -0
- package/dist/primitives/primitives.d.ts +5 -0
- package/dist/primitives/primitives.js +19 -0
- package/dist/profile/profile.d.ts +37 -0
- package/dist/profile/profile.js +43 -0
- package/dist/roles/roles.d.ts +135 -0
- package/dist/roles/roles.js +87 -0
- package/dist/runs/runs.d.ts +244 -0
- package/dist/runs/runs.js +137 -0
- package/dist/runtime-config.d.ts +12 -0
- package/dist/runtime-config.js +18 -0
- package/dist/sdk.d.ts +45 -0
- package/dist/sdk.js +48 -0
- package/dist/secrets/secrets.d.ts +65 -0
- package/dist/secrets/secrets.js +57 -0
- package/dist/service-client/service-client.d.ts +35 -0
- package/dist/service-client/service-client.js +90 -0
- package/dist/services/services.d.ts +122 -0
- package/dist/services/services.js +89 -0
- package/dist/sso/sso.d.ts +70 -0
- package/dist/sso/sso.js +54 -0
- package/dist/tables/tables.d.ts +133 -0
- package/dist/tables/tables.js +131 -0
- package/dist/tool.d.ts +31 -0
- package/dist/tool.js +4 -0
- package/dist/user-settings/user-settings.d.ts +44 -0
- package/dist/user-settings/user-settings.js +44 -0
- package/dist/users/users.d.ts +254 -0
- package/dist/users/users.js +125 -0
- package/dist/validation/validation.d.ts +106 -0
- package/dist/validation/validation.js +41 -0
- package/dist/versions/versions.d.ts +100 -0
- package/dist/versions/versions.js +70 -0
- package/package.json +27 -4
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Schedule } from "../dashboards/dashboards.js";
|
|
3
|
+
import { idSchema } from "../ids/ids.js";
|
|
4
|
+
import { Limit } from "../list-input.js";
|
|
5
|
+
import { MachineId } from "../machines/machines.js";
|
|
6
|
+
import { RoleId } from "../roles/roles.js";
|
|
7
|
+
import { OperatorProvider, UserId } from "../users/users.js";
|
|
8
|
+
// The package `operator` (#336, Einstellungen › Operator): the credentials at a provider ("Zugang",
|
|
9
|
+
// `operator_credential_*`) and the Operators themselves (`operator_machine_*`). An Operator is a machine
|
|
10
|
+
// of kind `operator` in `access` (E80, E85); its `machineId` is that user's id, and this package
|
|
11
|
+
// keeps only what a run needs: provider, credential, model, subagents, trigger and limits.
|
|
12
|
+
//
|
|
13
|
+
// ⚠️ A credential's value goes in and never comes out: no answer carries it, and no field of an answer
|
|
14
|
+
// is called `key`, `secret`, `token` or `password` (`/mcp` would strike it, `redactSecrets`). The
|
|
15
|
+
// value's field in the inputs is `value`, the kinds are `subscription` and `apikey`.
|
|
16
|
+
// The catalog (Einstellungen › Operator › Katalog). `models` are the names the provider's CLI takes
|
|
17
|
+
// without a UI: Claude Code's aliases for "the newest of this line", Gemini CLI's aliases `pro`,
|
|
18
|
+
// `flash` and `flash-lite` the same; Codex has no aliases, so its names are the models
|
|
19
|
+
// `codex debug models` of Codex 0.162.1 lists as current (#455). `subagents`: only Claude Code has
|
|
20
|
+
// them (#455); the UI hides the setting for the others. `costs`: only Claude Code reports a dollar
|
|
21
|
+
// amount; Codex and Gemini report tokens, and their runs carry no `costUsd` (Jack, #455), unless
|
|
22
|
+
// they run through the Cloudflare AI Gateway, whose logs carry the amount (#470). `gateway` is in
|
|
23
|
+
// every provider's kinds: one gateway credential serves the Operators of all three (#470). Only Claude
|
|
24
|
+
// keeps the sign-in of a subscription (#459). `beta`: Codex and Gemini carry the mark wherever the UI
|
|
25
|
+
// names them, with the note that Claude is the tried way (#459).
|
|
26
|
+
//
|
|
27
|
+
// `gateway`: the models an Operator on a gateway credential may take, and its default there (#483).
|
|
28
|
+
// ⚠️ The gateway pays only for the models it knows; any other request goes on to the provider without
|
|
29
|
+
// a key and is refused. Nothing is replaced on the way: a model not in this list cannot be chosen
|
|
30
|
+
// with a gateway credential, and with the customer's own key or subscription the full `models` stay.
|
|
31
|
+
// Measured 2026-10-15 with one smallest request per model through a gateway with Unified Billing
|
|
32
|
+
// (paths and header as in developers.cloudflare.com/ai-gateway/usage/providers/{anthropic,openai,
|
|
33
|
+
// google-ai-studio}/; the gateway's docs name no list of models, /features/unified-billing/):
|
|
34
|
+
// - Claude Code 2.1.299: `opus` (`claude-opus-5-5`) and `sonnet` (`claude-sonnet-5-5`) answer 200;
|
|
35
|
+
// `haiku` (`claude-haiku-5-5`) 401 from Anthropic. `claude-haiku-4-5` answers, but Claude Code then
|
|
36
|
+
// finds none of its MCP tools (run `…ZX0N8A` of #470), so it is no choice.
|
|
37
|
+
// - Codex: `gpt-6.1-sol` and `gpt-6-luna` 200, `gpt-6-astra` 401 from OpenAI.
|
|
38
|
+
// - Gemini CLI 0.63.0: its aliases are the 3.5 line, 403 from Google; `gemini-2.5-pro`, `-flash`
|
|
39
|
+
// and `-flash-lite` 200 and ran as Operators (#470), so the gateway offers those by name. Also 200
|
|
40
|
+
// that day, not offered without a run: `gemini-3.8-flash`, `gemini-3.1-flash-lite`,
|
|
41
|
+
// `gemini-3.1-pro-preview`.
|
|
42
|
+
// Add a model here once the gateway pays for it, after one smallest request and one run.
|
|
43
|
+
export const operatorProviders = [
|
|
44
|
+
{
|
|
45
|
+
provider: "claude",
|
|
46
|
+
name: "Claude",
|
|
47
|
+
vendor: "Anthropic",
|
|
48
|
+
selectable: true,
|
|
49
|
+
kinds: ["subscription", "apikey", "gateway"],
|
|
50
|
+
beta: false,
|
|
51
|
+
models: ["opus", "sonnet", "haiku"],
|
|
52
|
+
defaultModel: "sonnet",
|
|
53
|
+
gateway: { models: ["opus", "sonnet"], defaultModel: "sonnet" },
|
|
54
|
+
subagents: true,
|
|
55
|
+
costs: true,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
provider: "codex",
|
|
59
|
+
name: "Codex",
|
|
60
|
+
vendor: "OpenAI",
|
|
61
|
+
selectable: true,
|
|
62
|
+
// No ChatGPT sign-in (#459): chatgpt.com refuses every request that carries `CF-Worker`,
|
|
63
|
+
// which Cloudflare sets on each request of a Worker; GPT runs with an API key or the gateway.
|
|
64
|
+
kinds: ["apikey", "gateway"],
|
|
65
|
+
beta: true,
|
|
66
|
+
models: ["gpt-6-astra", "gpt-6.1-sol", "gpt-6-luna"],
|
|
67
|
+
defaultModel: "gpt-6.1-sol",
|
|
68
|
+
gateway: { models: ["gpt-6.1-sol", "gpt-6-luna"], defaultModel: "gpt-6.1-sol" },
|
|
69
|
+
subagents: false,
|
|
70
|
+
costs: false,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
provider: "gemini",
|
|
74
|
+
name: "Gemini",
|
|
75
|
+
vendor: "Google",
|
|
76
|
+
selectable: true,
|
|
77
|
+
// No Google sign-in (#459): Code Assist then asks for a Google Cloud project of the account,
|
|
78
|
+
// and for free accounts the Gemini CLI gave way to Antigravity (#507, from #502).
|
|
79
|
+
kinds: ["apikey", "gateway"],
|
|
80
|
+
beta: true,
|
|
81
|
+
models: ["pro", "flash", "flash-lite"],
|
|
82
|
+
defaultModel: "flash",
|
|
83
|
+
gateway: {
|
|
84
|
+
models: ["gemini-2.5-pro", "gemini-2.5-flash", "gemini-2.5-flash-lite"],
|
|
85
|
+
defaultModel: "gemini-2.5-flash",
|
|
86
|
+
},
|
|
87
|
+
subagents: false,
|
|
88
|
+
costs: false,
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
// The models an Operator of this provider may take with a credential of this kind, and the default
|
|
92
|
+
// among them (#483): the gateway's own list, else the provider's.
|
|
93
|
+
export function modelsOf(entry, kind) {
|
|
94
|
+
return kind === "gateway" ? entry.gateway : entry;
|
|
95
|
+
}
|
|
96
|
+
// `subscription`: the sign-in of a subscription, the token of `claude setup-token`; none for Codex
|
|
97
|
+
// and Gemini since #459, a stored one reads as invalid. `apikey`: an API key (Claude Console,
|
|
98
|
+
// OpenAI, Gemini API). The same words for every provider, so the Claude credentials stored before #455 keep their kind. Always the
|
|
99
|
+
// customer's own (Spike #335, E86). `gateway`: a token of the customer's Cloudflare AI Gateway with
|
|
100
|
+
// its account and gateway (#470); the runs of Claude, Codex and Gemini go through it, paid by the
|
|
101
|
+
// credits of the Cloudflare account (Unified Billing) or the keys stored in the gateway (BYOK). One
|
|
102
|
+
// such credential belongs to no provider and serves the Operators of all three.
|
|
103
|
+
export const CredentialKind = z.enum(["subscription", "apikey", "gateway"]);
|
|
104
|
+
// `valid` until the provider refuses it; `invalid` pauses every Operator that uses it (E81) until it
|
|
105
|
+
// is replaced.
|
|
106
|
+
export const CredentialState = z.enum(["valid", "invalid"]);
|
|
107
|
+
// Every provider's models in one list; which belong to which provider says the catalog, and the
|
|
108
|
+
// package refuses a model of another provider.
|
|
109
|
+
export const OperatorModel = z.enum([
|
|
110
|
+
"opus",
|
|
111
|
+
"sonnet",
|
|
112
|
+
"haiku",
|
|
113
|
+
"gpt-6-astra",
|
|
114
|
+
"gpt-6.1-sol",
|
|
115
|
+
"gpt-6-luna",
|
|
116
|
+
"pro",
|
|
117
|
+
"flash",
|
|
118
|
+
"flash-lite",
|
|
119
|
+
"gemini-2.5-pro",
|
|
120
|
+
"gemini-2.5-flash",
|
|
121
|
+
"gemini-2.5-flash-lite",
|
|
122
|
+
]);
|
|
123
|
+
export const CredentialId = idSchema("credential");
|
|
124
|
+
const CredentialName = z.string().trim().min(1).max(64);
|
|
125
|
+
// The value as pasted. Its shape per provider and kind is checked by the package, whose message never
|
|
126
|
+
// quotes it. A sign-in file of Codex is a few kilobytes (#455).
|
|
127
|
+
const CredentialValue = z.string().trim().min(16).max(20_000);
|
|
128
|
+
// Where a gateway credential's token goes (#470): the Cloudflare account and the gateway in it, as
|
|
129
|
+
// the dashboard names them. Not secret, but checked strictly: both become parts of a URL.
|
|
130
|
+
export const GatewayTarget = z.strictObject({
|
|
131
|
+
accountId: z
|
|
132
|
+
.string()
|
|
133
|
+
.trim()
|
|
134
|
+
.regex(/^[0-9a-f]{32}$/i, "A Cloudflare account id is 32 hexadecimal characters."),
|
|
135
|
+
gatewayId: z
|
|
136
|
+
.string()
|
|
137
|
+
.trim()
|
|
138
|
+
.regex(/^[A-Za-z0-9_-]{1,64}$/, "A gateway id holds letters, digits, - and _ only."),
|
|
139
|
+
});
|
|
140
|
+
export const CredentialListInput = z.strictObject({
|
|
141
|
+
cursor: CredentialId.optional(),
|
|
142
|
+
limit: Limit.optional(),
|
|
143
|
+
});
|
|
144
|
+
export const CredentialGetInput = z.strictObject({ credentialId: CredentialId });
|
|
145
|
+
// A gateway credential names no provider and takes `gateway` beside its token in `value` (#470);
|
|
146
|
+
// every other kind names its provider and takes no `gateway`.
|
|
147
|
+
export const CredentialCreateInput = z
|
|
148
|
+
.strictObject({
|
|
149
|
+
provider: OperatorProvider.optional(),
|
|
150
|
+
kind: CredentialKind,
|
|
151
|
+
name: CredentialName,
|
|
152
|
+
value: CredentialValue,
|
|
153
|
+
gateway: GatewayTarget.optional(),
|
|
154
|
+
})
|
|
155
|
+
.refine((input) => input.kind === "gateway"
|
|
156
|
+
? input.provider === undefined && input.gateway !== undefined
|
|
157
|
+
: input.provider !== undefined && input.gateway === undefined, {
|
|
158
|
+
message: "A gateway credential takes gateway and no provider; every other kind takes provider and no gateway.",
|
|
159
|
+
});
|
|
160
|
+
// "Token ersetzen": a new value, a new name, or both. A new value is tested at once. A gateway
|
|
161
|
+
// credential takes a new value only together with its `gateway` (#470).
|
|
162
|
+
export const CredentialUpdateInput = z
|
|
163
|
+
.strictObject({
|
|
164
|
+
credentialId: CredentialId,
|
|
165
|
+
name: CredentialName.optional(),
|
|
166
|
+
value: CredentialValue.optional(),
|
|
167
|
+
gateway: GatewayTarget.optional(),
|
|
168
|
+
})
|
|
169
|
+
.refine((input) => input.name !== undefined || input.value !== undefined, {
|
|
170
|
+
message: "Name a field to change: name or value.",
|
|
171
|
+
})
|
|
172
|
+
.refine((input) => input.gateway === undefined || input.value !== undefined, {
|
|
173
|
+
message: "A new gateway goes together with a new value.",
|
|
174
|
+
});
|
|
175
|
+
export const CredentialTestInput = z.strictObject({ credentialId: CredentialId });
|
|
176
|
+
// "Trennen": the value is deleted at once and without archive. Refused while an Operator uses it.
|
|
177
|
+
export const CredentialRevokeInput = z.strictObject({ credentialId: CredentialId });
|
|
178
|
+
export const Credential = z.strictObject({
|
|
179
|
+
credentialId: CredentialId,
|
|
180
|
+
// Null for a gateway credential, which serves the Operators of every provider (#470).
|
|
181
|
+
provider: OperatorProvider.nullable(),
|
|
182
|
+
kind: CredentialKind,
|
|
183
|
+
name: z.string(),
|
|
184
|
+
state: CredentialState,
|
|
185
|
+
// The last test, whatever its result; null before the first.
|
|
186
|
+
checkedAt: z.iso.datetime().nullable(),
|
|
187
|
+
// When the value was set; never the value.
|
|
188
|
+
setAt: z.iso.datetime(),
|
|
189
|
+
// The Operators that use it, archived ones left out: "Genutzt von n Operatoren", and while it is
|
|
190
|
+
// invalid, the ones that pause because of it.
|
|
191
|
+
machineIds: z.array(MachineId),
|
|
192
|
+
createdAt: z.iso.datetime(),
|
|
193
|
+
createdBy: UserId.nullable(),
|
|
194
|
+
updatedAt: z.iso.datetime(),
|
|
195
|
+
});
|
|
196
|
+
export const CredentialList = z.strictObject({
|
|
197
|
+
items: z.array(Credential),
|
|
198
|
+
nextCursor: CredentialId.nullable(),
|
|
199
|
+
});
|
|
200
|
+
// The smallest call at the provider with the stored value. An error names the outcome, never a value.
|
|
201
|
+
export const CredentialTestResult = z.discriminatedUnion("ok", [
|
|
202
|
+
z.strictObject({ ok: z.literal(true) }),
|
|
203
|
+
z.strictObject({ ok: z.literal(false), error: z.string() }),
|
|
204
|
+
]);
|
|
205
|
+
export const CredentialTested = z.strictObject({
|
|
206
|
+
credential: Credential,
|
|
207
|
+
test: CredentialTestResult,
|
|
208
|
+
});
|
|
209
|
+
// Subagents (#335): allowed or not, and at most `max` at the same time. Claude Code knows no limit
|
|
210
|
+
// per run, only at the same time (Jack's decision at #336).
|
|
211
|
+
export const Subagents = z.strictObject({
|
|
212
|
+
allowed: z.boolean(),
|
|
213
|
+
max: z.int().min(1).max(10),
|
|
214
|
+
});
|
|
215
|
+
// When an Operator wakes (Springt an): once something changed, after `quietMinutes` without a further
|
|
216
|
+
// change; or at fixed times, with the schedule of processes and dashboards.
|
|
217
|
+
export const Trigger = z.discriminatedUnion("on", [
|
|
218
|
+
z.strictObject({ on: z.literal("change"), quietMinutes: z.int().min(0).max(1440) }),
|
|
219
|
+
z.strictObject({ on: z.literal("schedule"), schedule: Schedule }),
|
|
220
|
+
]);
|
|
221
|
+
// The limits of E81: the longest run in minutes and the most runs a day.
|
|
222
|
+
export const OperatorLimits = z.strictObject({
|
|
223
|
+
maxRunMinutes: z.int().min(1).max(240),
|
|
224
|
+
maxRunsPerDay: z.int().min(1).max(1000),
|
|
225
|
+
});
|
|
226
|
+
export const operatorDefaults = {
|
|
227
|
+
model: "sonnet",
|
|
228
|
+
subagents: { allowed: false, max: 3 },
|
|
229
|
+
trigger: { on: "change", quietMinutes: 5 },
|
|
230
|
+
limits: { maxRunMinutes: 30, maxRunsPerDay: 50 },
|
|
231
|
+
};
|
|
232
|
+
// `no_role`: it has no role and starts no run (E84). `paused`: see `pausedReason`. `ready`: it may run.
|
|
233
|
+
// "läuft" is `running` beside the state (#337).
|
|
234
|
+
export const OperatorState = z.enum(["no_role", "ready", "paused"]);
|
|
235
|
+
// `manual` by hand, `limit` the daily limit, `failures` three failed runs in a row (#337 sets those
|
|
236
|
+
// two), `credential` its credential is invalid or gone.
|
|
237
|
+
export const PauseReason = z.enum(["manual", "limit", "failures", "credential"]);
|
|
238
|
+
export const MachineListInput = z.strictObject({
|
|
239
|
+
cursor: MachineId.optional(),
|
|
240
|
+
limit: Limit.optional(),
|
|
241
|
+
});
|
|
242
|
+
export const MachineGetInput = z.strictObject({ machineId: MachineId });
|
|
243
|
+
// The name and roles go to the machine in `access`; without `roleIds` it has none (E84).
|
|
244
|
+
export const OperatorMachineCreateInput = z.strictObject({
|
|
245
|
+
name: z.string().trim().min(1).max(64),
|
|
246
|
+
roleIds: z.array(RoleId).max(50).optional(),
|
|
247
|
+
provider: OperatorProvider,
|
|
248
|
+
credentialId: CredentialId,
|
|
249
|
+
model: OperatorModel.optional(),
|
|
250
|
+
subagents: Subagents.optional(),
|
|
251
|
+
trigger: Trigger.optional(),
|
|
252
|
+
limits: OperatorLimits.partial().optional(),
|
|
253
|
+
});
|
|
254
|
+
// Every field optional; `responsibleId` hands the machine to another person in `access` (E76).
|
|
255
|
+
export const OperatorMachineUpdateInput = z
|
|
256
|
+
.strictObject({
|
|
257
|
+
machineId: MachineId,
|
|
258
|
+
credentialId: CredentialId.optional(),
|
|
259
|
+
model: OperatorModel.optional(),
|
|
260
|
+
subagents: Subagents.optional(),
|
|
261
|
+
trigger: Trigger.optional(),
|
|
262
|
+
limits: OperatorLimits.partial().optional(),
|
|
263
|
+
responsibleId: UserId.optional(),
|
|
264
|
+
})
|
|
265
|
+
.refine((input) => Object.keys(input).some((field) => field !== "machineId"), {
|
|
266
|
+
message: "Name a field to change.",
|
|
267
|
+
});
|
|
268
|
+
// Pause and resume by hand. Resuming lifts a pause for the daily limit or failures too.
|
|
269
|
+
export const MachineDisableInput = z.strictObject({ machineId: MachineId });
|
|
270
|
+
export const MachineEnableInput = z.strictObject({ machineId: MachineId });
|
|
271
|
+
// Deleting an Operator archives its machine in `access`; nothing is deleted.
|
|
272
|
+
export const OperatorMachineArchiveInput = z.strictObject({ machineId: MachineId });
|
|
273
|
+
export const Operator = z.strictObject({
|
|
274
|
+
machineId: MachineId,
|
|
275
|
+
// The machine's name in `access`, read now.
|
|
276
|
+
name: z.string(),
|
|
277
|
+
provider: OperatorProvider,
|
|
278
|
+
credentialId: CredentialId.nullable(),
|
|
279
|
+
model: OperatorModel,
|
|
280
|
+
subagents: Subagents,
|
|
281
|
+
trigger: Trigger,
|
|
282
|
+
limits: OperatorLimits,
|
|
283
|
+
state: OperatorState,
|
|
284
|
+
pausedReason: PauseReason.nullable(),
|
|
285
|
+
pausedAt: z.iso.datetime().nullable(),
|
|
286
|
+
// "läuft" (#337): the run in progress, beside the state, so a paused Operator can still finish
|
|
287
|
+
// the run it started; null while none runs.
|
|
288
|
+
running: z.strictObject({ runId: idSchema("run"), startedAt: z.iso.datetime() }).nullable(),
|
|
289
|
+
archivedAt: z.iso.datetime().nullable(),
|
|
290
|
+
createdAt: z.iso.datetime(),
|
|
291
|
+
createdBy: UserId.nullable(),
|
|
292
|
+
updatedAt: z.iso.datetime(),
|
|
293
|
+
});
|
|
294
|
+
export const OperatorList = z.strictObject({
|
|
295
|
+
items: z.array(Operator),
|
|
296
|
+
nextCursor: MachineId.nullable(),
|
|
297
|
+
});
|
|
298
|
+
// ---------------------------------------------------------------------------------------------
|
|
299
|
+
// The runs of an Operator (#337, Einstellungen › Operator › Protokoll und Nutzung, E75, E81, E82).
|
|
300
|
+
// A run's id is `run_…` like a run of `intelligence`: both are the resource `run`, in two databases.
|
|
301
|
+
export const OperatorRunId = idSchema("run").describe("The Operator run's id, `run_…`, as operator_run_list returned it.");
|
|
302
|
+
// `running` until the runner reports; then `completed` or `failed` with its reason (E82).
|
|
303
|
+
export const OperatorRunStatus = z.enum(["running", "completed", "failed"]);
|
|
304
|
+
// Why a run failed (E82): the container did not start (`container`), the provider refused or was
|
|
305
|
+
// overloaded (`provider`), the longest run was reached (`timeout`), Claude Code crashed or ended with
|
|
306
|
+
// an error (`crash`), it ended without its closing message (`noresult`), the package itself broke
|
|
307
|
+
// (`error`), or the provider refused the credential (`credential`: it is marked invalid and its
|
|
308
|
+
// Operators pause; no failure in a row is counted and no run follows).
|
|
309
|
+
export const OperatorRunReason = z.enum([
|
|
310
|
+
"container",
|
|
311
|
+
"provider",
|
|
312
|
+
"timeout",
|
|
313
|
+
"crash",
|
|
314
|
+
"noresult",
|
|
315
|
+
"error",
|
|
316
|
+
"credential",
|
|
317
|
+
]);
|
|
318
|
+
// What woke it: a change after the quiet minutes, a fixed time, or the retry after a failure.
|
|
319
|
+
export const OperatorRunTrigger = z.enum(["change", "schedule", "retry"]);
|
|
320
|
+
export const OperatorRunTokens = z.strictObject({
|
|
321
|
+
input: z.int().min(0),
|
|
322
|
+
output: z.int().min(0),
|
|
323
|
+
cacheRead: z.int().min(0),
|
|
324
|
+
cacheWrite: z.int().min(0),
|
|
325
|
+
});
|
|
326
|
+
// The processes and connectors a run touched, as the runner names them (#338).
|
|
327
|
+
export const OperatorRunTouched = z.strictObject({
|
|
328
|
+
processes: z.array(z.string().max(200)).max(200),
|
|
329
|
+
connectors: z.array(z.string().max(200)).max(200),
|
|
330
|
+
});
|
|
331
|
+
// Who ran, named by the backend (#448): the machine's name in `access`, archived ones included, and
|
|
332
|
+
// when the Operator was deleted (archived), so a run of a deleted Operator still says whose it was.
|
|
333
|
+
const RunMachine = {
|
|
334
|
+
machineId: MachineId,
|
|
335
|
+
machineName: z.string(),
|
|
336
|
+
machineArchivedAt: z.iso.datetime().nullable(),
|
|
337
|
+
};
|
|
338
|
+
export const OperatorRun = z.strictObject({
|
|
339
|
+
runId: OperatorRunId,
|
|
340
|
+
...RunMachine,
|
|
341
|
+
trigger: OperatorRunTrigger,
|
|
342
|
+
status: OperatorRunStatus,
|
|
343
|
+
reason: OperatorRunReason.nullable(),
|
|
344
|
+
// What the runner said about a failure, never a credential's value.
|
|
345
|
+
detail: z.string().nullable(),
|
|
346
|
+
// The summary the Operator wrote at the end itself.
|
|
347
|
+
summary: z.string().nullable(),
|
|
348
|
+
touched: OperatorRunTouched,
|
|
349
|
+
// The credential's kind decides how the cost reads: `apikey` is cost, `subscription` the API
|
|
350
|
+
// equivalent (E81).
|
|
351
|
+
credentialKind: CredentialKind.nullable(),
|
|
352
|
+
// Claude's own amount; Codex and Gemini report tokens and no amount, so their runs carry null
|
|
353
|
+
// (#455). Through the Cloudflare AI Gateway the amount of its logs, for every provider (#470).
|
|
354
|
+
costUsd: z.number().nullable(),
|
|
355
|
+
tokens: OperatorRunTokens.nullable(),
|
|
356
|
+
startedAt: z.iso.datetime(),
|
|
357
|
+
endedAt: z.iso.datetime().nullable(),
|
|
358
|
+
durationMs: z.int().nullable(),
|
|
359
|
+
});
|
|
360
|
+
const RunMoment = z.iso.datetime({ offset: true });
|
|
361
|
+
export const OperatorRunListInput = z.strictObject({
|
|
362
|
+
machineId: MachineId.optional().describe("Only this Operator's runs, `user_…`. An Operator without admin rights reads its own runs only, whatever it names here."),
|
|
363
|
+
provider: OperatorProvider.optional().describe("Only the runs of this provider's Operators: claude, codex or gemini."),
|
|
364
|
+
status: OperatorRunStatus.optional().describe("Only runs in this status."),
|
|
365
|
+
from: RunMoment.optional().describe("Runs started at or after this moment, ISO."),
|
|
366
|
+
to: RunMoment.optional().describe("Runs started before this moment, ISO."),
|
|
367
|
+
search: z
|
|
368
|
+
.string()
|
|
369
|
+
.trim()
|
|
370
|
+
.min(1)
|
|
371
|
+
.max(200)
|
|
372
|
+
.optional()
|
|
373
|
+
.describe("Words in a run's summary or failure, case-insensitive."),
|
|
374
|
+
cursor: OperatorRunId.optional().describe("The nextCursor of the previous page, for the runs after it; newest first."),
|
|
375
|
+
limit: Limit.optional().describe("Runs per page, 1 to 100. Leaving it out gives 50."),
|
|
376
|
+
});
|
|
377
|
+
export const OperatorRunGetInput = z.strictObject({ runId: OperatorRunId });
|
|
378
|
+
const UsageSums = {
|
|
379
|
+
runs: z.int(),
|
|
380
|
+
costUsd: z.number(),
|
|
381
|
+
tokens: OperatorRunTokens,
|
|
382
|
+
};
|
|
383
|
+
// The use over every run the filter takes, not only the page (Nutzung): in total, per Operator, per
|
|
384
|
+
// day (UTC), per credential kind, so cost and API equivalent stand apart, and per provider, so the
|
|
385
|
+
// tokens of Codex and Gemini, which report no amount, stand apart from Claude's (#455). `costUsd`
|
|
386
|
+
// sums the runs that carry an amount: Claude's, and every run through the AI Gateway (#470).
|
|
387
|
+
export const OperatorRunUsage = z.strictObject({
|
|
388
|
+
...UsageSums,
|
|
389
|
+
byMachine: z.array(z.strictObject({ ...RunMachine, ...UsageSums })),
|
|
390
|
+
byDay: z.array(z.strictObject({ day: z.iso.date(), ...UsageSums })),
|
|
391
|
+
byKind: z.array(z.strictObject({ kind: CredentialKind, ...UsageSums })),
|
|
392
|
+
byProvider: z.array(z.strictObject({ provider: OperatorProvider, ...UsageSums })),
|
|
393
|
+
});
|
|
394
|
+
export const OperatorRunList = z.strictObject({
|
|
395
|
+
items: z.array(OperatorRun),
|
|
396
|
+
nextCursor: OperatorRunId.nullable(),
|
|
397
|
+
usage: OperatorRunUsage,
|
|
398
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const PageId: z.ZodString;
|
|
3
|
+
export type PageId = z.infer<typeof PageId>;
|
|
4
|
+
export declare const PageHead: z.ZodObject<{
|
|
5
|
+
title: z.ZodString;
|
|
6
|
+
group: z.ZodString;
|
|
7
|
+
parent: z.ZodNullable<z.ZodString>;
|
|
8
|
+
order: z.ZodNumber;
|
|
9
|
+
summary: z.ZodString;
|
|
10
|
+
}, z.core.$strict>;
|
|
11
|
+
export type PageHead = z.infer<typeof PageHead>;
|
|
12
|
+
export declare const PageListInput: z.ZodObject<{
|
|
13
|
+
locale: z.ZodOptional<z.ZodEnum<{
|
|
14
|
+
en: "en";
|
|
15
|
+
de: "de";
|
|
16
|
+
}>>;
|
|
17
|
+
query: z.ZodOptional<z.ZodString>;
|
|
18
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
19
|
+
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
20
|
+
}, z.core.$strict>;
|
|
21
|
+
export type PageListInput = z.infer<typeof PageListInput>;
|
|
22
|
+
export declare const PageGetInput: z.ZodObject<{
|
|
23
|
+
pageId: z.ZodString;
|
|
24
|
+
locale: z.ZodOptional<z.ZodEnum<{
|
|
25
|
+
en: "en";
|
|
26
|
+
de: "de";
|
|
27
|
+
}>>;
|
|
28
|
+
}, z.core.$strict>;
|
|
29
|
+
export type PageGetInput = z.infer<typeof PageGetInput>;
|
|
30
|
+
export declare const PageSummary: z.ZodObject<{
|
|
31
|
+
title: z.ZodString;
|
|
32
|
+
group: z.ZodString;
|
|
33
|
+
parent: z.ZodNullable<z.ZodString>;
|
|
34
|
+
order: z.ZodNumber;
|
|
35
|
+
summary: z.ZodString;
|
|
36
|
+
pageId: z.ZodString;
|
|
37
|
+
locale: z.ZodEnum<{
|
|
38
|
+
en: "en";
|
|
39
|
+
de: "de";
|
|
40
|
+
}>;
|
|
41
|
+
match: z.ZodOptional<z.ZodString>;
|
|
42
|
+
}, z.core.$strict>;
|
|
43
|
+
export type PageSummary = z.infer<typeof PageSummary>;
|
|
44
|
+
export declare const PageList: z.ZodObject<{
|
|
45
|
+
items: z.ZodArray<z.ZodObject<{
|
|
46
|
+
title: z.ZodString;
|
|
47
|
+
group: z.ZodString;
|
|
48
|
+
parent: z.ZodNullable<z.ZodString>;
|
|
49
|
+
order: z.ZodNumber;
|
|
50
|
+
summary: z.ZodString;
|
|
51
|
+
pageId: z.ZodString;
|
|
52
|
+
locale: z.ZodEnum<{
|
|
53
|
+
en: "en";
|
|
54
|
+
de: "de";
|
|
55
|
+
}>;
|
|
56
|
+
match: z.ZodOptional<z.ZodString>;
|
|
57
|
+
}, z.core.$strict>>;
|
|
58
|
+
nextCursor: z.ZodNullable<z.ZodString>;
|
|
59
|
+
}, z.core.$strict>;
|
|
60
|
+
export type PageList = z.infer<typeof PageList>;
|
|
61
|
+
export declare const PageHeading: z.ZodObject<{
|
|
62
|
+
depth: z.ZodNumber;
|
|
63
|
+
text: z.ZodString;
|
|
64
|
+
slug: z.ZodString;
|
|
65
|
+
}, z.core.$strict>;
|
|
66
|
+
export type PageHeading = z.infer<typeof PageHeading>;
|
|
67
|
+
export declare const PageDetail: z.ZodObject<{
|
|
68
|
+
title: z.ZodString;
|
|
69
|
+
group: z.ZodString;
|
|
70
|
+
parent: z.ZodNullable<z.ZodString>;
|
|
71
|
+
order: z.ZodNumber;
|
|
72
|
+
summary: z.ZodString;
|
|
73
|
+
pageId: z.ZodString;
|
|
74
|
+
locale: z.ZodEnum<{
|
|
75
|
+
en: "en";
|
|
76
|
+
de: "de";
|
|
77
|
+
}>;
|
|
78
|
+
markdown: z.ZodString;
|
|
79
|
+
headings: z.ZodArray<z.ZodObject<{
|
|
80
|
+
depth: z.ZodNumber;
|
|
81
|
+
text: z.ZodString;
|
|
82
|
+
slug: z.ZodString;
|
|
83
|
+
}, z.core.$strict>>;
|
|
84
|
+
breadcrumbs: z.ZodArray<z.ZodObject<{
|
|
85
|
+
pageId: z.ZodString;
|
|
86
|
+
title: z.ZodString;
|
|
87
|
+
}, z.core.$strict>>;
|
|
88
|
+
}, z.core.$strict>;
|
|
89
|
+
export type PageDetail = z.infer<typeof PageDetail>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Limit } from "../list-input.js";
|
|
3
|
+
import { Locale } from "../profile/profile.js";
|
|
4
|
+
// The pages of the documentation (Seiten › Documentation, E23, #51): Markdown files per language in
|
|
5
|
+
// the package `documentation`, read by the docs overlay and by the AI through the
|
|
6
|
+
// `documentation_page_*` tools.
|
|
7
|
+
// ⚠️ Not a prefixed ULID like every other id: a page is a file in the package, and its id is the
|
|
8
|
+
// file's name (`connect-ai`), stable across languages and releases (#51).
|
|
9
|
+
export const PageId = z
|
|
10
|
+
.string()
|
|
11
|
+
.regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, "A page id is the file name in kebab-case, such as connect-ai");
|
|
12
|
+
// The YAML head every page file starts with. Strict: a key nobody reads is a typo.
|
|
13
|
+
export const PageHead = z.strictObject({
|
|
14
|
+
title: z.string().trim().min(1),
|
|
15
|
+
// The heading in the overlay's side bar, in the page's language ("Getting started", "Einstieg").
|
|
16
|
+
group: z.string().trim().min(1),
|
|
17
|
+
// The page this one sits under, or null at the top of its group.
|
|
18
|
+
parent: PageId.nullable(),
|
|
19
|
+
// The position among the pages with the same parent.
|
|
20
|
+
order: z.number().int().min(0),
|
|
21
|
+
// The grey lead under the title.
|
|
22
|
+
summary: z.string().trim().min(1),
|
|
23
|
+
});
|
|
24
|
+
export const PageListInput = z.strictObject({
|
|
25
|
+
// Without it, the caller's own language.
|
|
26
|
+
locale: Locale.optional(),
|
|
27
|
+
// Searches title, summary and text, ignoring case.
|
|
28
|
+
query: z.string().trim().min(1).max(200).optional(),
|
|
29
|
+
cursor: PageId.optional(),
|
|
30
|
+
limit: Limit.optional(),
|
|
31
|
+
});
|
|
32
|
+
export const PageGetInput = z.strictObject({
|
|
33
|
+
pageId: PageId,
|
|
34
|
+
locale: Locale.optional(),
|
|
35
|
+
});
|
|
36
|
+
// One page in the list. `locale` is the language delivered: English stands in for a missing
|
|
37
|
+
// translation (E22).
|
|
38
|
+
export const PageSummary = PageHead.extend({
|
|
39
|
+
pageId: PageId,
|
|
40
|
+
locale: Locale,
|
|
41
|
+
// Only with `query`: the passage that matched.
|
|
42
|
+
match: z.string().optional(),
|
|
43
|
+
});
|
|
44
|
+
export const PageList = z.strictObject({
|
|
45
|
+
items: z.array(PageSummary),
|
|
46
|
+
nextCursor: PageId.nullable(),
|
|
47
|
+
});
|
|
48
|
+
export const PageHeading = z.strictObject({
|
|
49
|
+
depth: z.number().int().min(2).max(6),
|
|
50
|
+
text: z.string(),
|
|
51
|
+
// GitHub's anchor for the heading, for "Auf dieser Seite".
|
|
52
|
+
slug: z.string(),
|
|
53
|
+
});
|
|
54
|
+
export const PageDetail = PageHead.extend({
|
|
55
|
+
pageId: PageId,
|
|
56
|
+
locale: Locale,
|
|
57
|
+
// The page without its YAML head.
|
|
58
|
+
markdown: z.string(),
|
|
59
|
+
headings: z.array(PageHeading),
|
|
60
|
+
// From the top of the tree down to this page itself; the group comes first in the UI, from `group`.
|
|
61
|
+
breadcrumbs: z.array(z.strictObject({ pageId: PageId, title: z.string() })),
|
|
62
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// Primitives every writer of every package takes the same way, each described ONCE (trap C006): a
|
|
3
|
+
// word used everywhere gets one schema with one sentence, so HTTP, MCP and the types say the same.
|
|
4
|
+
// Taken from anchrd/intel `src/contract/contract.ts` (f4eccd16). The description says what the caller
|
|
5
|
+
// has to DO, because that is the part a model gets wrong: it invents a fresh key on the retry and
|
|
6
|
+
// creates the thing twice.
|
|
7
|
+
export const IdempotencyKey = z
|
|
8
|
+
.string()
|
|
9
|
+
.min(8)
|
|
10
|
+
.max(200)
|
|
11
|
+
.describe("A caller-chosen key that makes this call safe to retry: repeating the same key returns the first result instead of doing the work twice. Reuse the SAME key when retrying one attempt, and a new one for a genuinely new call.");
|
|
12
|
+
// The revision a save is based on (E70): every save counts it up by one, and a save that names
|
|
13
|
+
// another than the stored one is `conflict` and writes nothing. Not the version number of a
|
|
14
|
+
// document and not `updatedAt`: a move or a grant touches the row too (trap P117).
|
|
15
|
+
export const Rev = z
|
|
16
|
+
.number()
|
|
17
|
+
.int()
|
|
18
|
+
.min(1)
|
|
19
|
+
.describe("The revision of the node this change is based on, as the last read returned it. If someone saved in between, the call answers conflict and changes nothing: read the node again and decide.");
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const locales: readonly ["en", "de"];
|
|
3
|
+
export declare const Locale: z.ZodEnum<{
|
|
4
|
+
en: "en";
|
|
5
|
+
de: "de";
|
|
6
|
+
}>;
|
|
7
|
+
export type Locale = z.infer<typeof Locale>;
|
|
8
|
+
export declare const themes: readonly ["light", "dark", "system"];
|
|
9
|
+
export declare const Theme: z.ZodEnum<{
|
|
10
|
+
light: "light";
|
|
11
|
+
dark: "dark";
|
|
12
|
+
system: "system";
|
|
13
|
+
}>;
|
|
14
|
+
export type Theme = z.infer<typeof Theme>;
|
|
15
|
+
export declare const TimeZone: z.ZodString;
|
|
16
|
+
export type TimeZone = z.infer<typeof TimeZone>;
|
|
17
|
+
export declare const Name: z.ZodString;
|
|
18
|
+
export declare const ProfileUpdateInput: z.ZodObject<{
|
|
19
|
+
name: z.ZodOptional<z.ZodString>;
|
|
20
|
+
locale: z.ZodOptional<z.ZodEnum<{
|
|
21
|
+
en: "en";
|
|
22
|
+
de: "de";
|
|
23
|
+
}>>;
|
|
24
|
+
timezone: z.ZodOptional<z.ZodString>;
|
|
25
|
+
theme: z.ZodOptional<z.ZodEnum<{
|
|
26
|
+
light: "light";
|
|
27
|
+
dark: "dark";
|
|
28
|
+
system: "system";
|
|
29
|
+
}>>;
|
|
30
|
+
}, z.core.$strict>;
|
|
31
|
+
export type ProfileUpdateInput = z.infer<typeof ProfileUpdateInput>;
|
|
32
|
+
export declare const profileImageTypes: readonly ["image/png", "image/jpeg", "image/webp"];
|
|
33
|
+
export declare const profileImageMaxBytes = 5000000;
|
|
34
|
+
export declare const ProfileImageResponse: z.ZodObject<{
|
|
35
|
+
image: z.ZodNullable<z.ZodString>;
|
|
36
|
+
}, z.core.$strict>;
|
|
37
|
+
export type ProfileImageResponse = z.infer<typeof ProfileImageResponse>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// The own profile (Einstellungen › Profil, Darstellung): what a person writes about themselves
|
|
3
|
+
// through `/auth/update-user` and `/auth/profile-image`. The email is not here: it comes from the
|
|
4
|
+
// sign-in and is read only.
|
|
5
|
+
// The languages Colab speaks (E22). English is the default.
|
|
6
|
+
export const locales = ["en", "de"];
|
|
7
|
+
export const Locale = z.enum(locales);
|
|
8
|
+
// Einstellungen › Darstellung.
|
|
9
|
+
export const themes = ["light", "dark", "system"];
|
|
10
|
+
export const Theme = z.enum(themes);
|
|
11
|
+
// An IANA zone `Intl` knows, such as `Europe/Berlin`. A zone it does not know would make every date
|
|
12
|
+
// in a mail or the UI throw, so it is refused at the door instead.
|
|
13
|
+
export const TimeZone = z
|
|
14
|
+
.string()
|
|
15
|
+
.min(1)
|
|
16
|
+
.max(64)
|
|
17
|
+
.refine((zone) => {
|
|
18
|
+
try {
|
|
19
|
+
new Intl.DateTimeFormat("en", { timeZone: zone });
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}, "Unknown time zone");
|
|
26
|
+
export const Name = z.string().trim().min(1).max(200);
|
|
27
|
+
// The body of `POST /auth/update-user`. Strict: `email` and `image` are refused there, the email
|
|
28
|
+
// because it identifies the account, the picture because it only comes through its own door.
|
|
29
|
+
export const ProfileUpdateInput = z.strictObject({
|
|
30
|
+
name: Name.optional(),
|
|
31
|
+
locale: Locale.optional(),
|
|
32
|
+
timezone: TimeZone.optional(),
|
|
33
|
+
theme: Theme.optional(),
|
|
34
|
+
});
|
|
35
|
+
// The picture's upload door takes the file itself as body, never base64 in JSON. The allowlist is
|
|
36
|
+
// not a filter of the dangerous types: `image/svg+xml` can carry script and stays off it.
|
|
37
|
+
// Taken from anchrd/gate `packages/sdk/src/contract/contract.ts` (9d8ece3).
|
|
38
|
+
export const profileImageTypes = ["image/png", "image/jpeg", "image/webp"];
|
|
39
|
+
// A portrait drawn at 40 pixels needs a thousandth of this; the limit catches the untouched photo
|
|
40
|
+
// straight from the phone. One figure for the UI before the upload and for the door that refuses.
|
|
41
|
+
export const profileImageMaxBytes = 5_000_000;
|
|
42
|
+
// The answer of upload and removal: the address the profile carries in `image`, or `null`.
|
|
43
|
+
export const ProfileImageResponse = z.strictObject({ image: z.string().nullable() });
|