@intentic/sandbox-contract 1.225.0 → 1.226.1
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-catalog.d.ts +2 -0
- package/dist/agent-catalog.d.ts.map +1 -1
- package/dist/agent-catalog.js +16 -0
- package/dist/agent-catalog.js.map +1 -1
- package/dist/contracts/activity.contract.d.ts.map +1 -1
- package/dist/contracts/activity.contract.js +17 -2
- package/dist/contracts/activity.contract.js.map +1 -1
- package/dist/contracts/agent.contract.d.ts.map +1 -1
- package/dist/contracts/agent.contract.js +71 -8
- package/dist/contracts/agent.contract.js.map +1 -1
- package/dist/contracts/agents.contract.d.ts +1 -0
- package/dist/contracts/agents.contract.d.ts.map +1 -1
- package/dist/contracts/agents.contract.js +164 -19
- package/dist/contracts/agents.contract.js.map +1 -1
- package/dist/contracts/automations.contract.d.ts.map +1 -1
- package/dist/contracts/automations.contract.js +78 -9
- package/dist/contracts/automations.contract.js.map +1 -1
- package/dist/contracts/capabilities.contract.d.ts.map +1 -1
- package/dist/contracts/capabilities.contract.js +98 -11
- package/dist/contracts/capabilities.contract.js.map +1 -1
- package/dist/contracts/chores.contract.d.ts.map +1 -1
- package/dist/contracts/chores.contract.js +26 -3
- package/dist/contracts/chores.contract.js.map +1 -1
- package/dist/contracts/ci.contract.d.ts.map +1 -1
- package/dist/contracts/ci.contract.js +52 -6
- package/dist/contracts/ci.contract.js.map +1 -1
- package/dist/contracts/claude.contract.d.ts.map +1 -1
- package/dist/contracts/claude.contract.js +44 -5
- package/dist/contracts/claude.contract.js.map +1 -1
- package/dist/contracts/drafts.contract.d.ts.map +1 -1
- package/dist/contracts/drafts.contract.js +26 -3
- package/dist/contracts/drafts.contract.js.map +1 -1
- package/dist/contracts/endpoints.contract.d.ts.map +1 -1
- package/dist/contracts/endpoints.contract.js +17 -2
- package/dist/contracts/endpoints.contract.js.map +1 -1
- package/dist/contracts/exit.contract.d.ts.map +1 -1
- package/dist/contracts/exit.contract.js +62 -7
- package/dist/contracts/exit.contract.js.map +1 -1
- package/dist/contracts/extensions.contract.d.ts.map +1 -1
- package/dist/contracts/extensions.contract.js +124 -15
- package/dist/contracts/extensions.contract.js.map +1 -1
- package/dist/contracts/git.contract.d.ts.map +1 -1
- package/dist/contracts/git.contract.js +384 -43
- package/dist/contracts/git.contract.js.map +1 -1
- package/dist/contracts/grok.contract.d.ts.map +1 -1
- package/dist/contracts/grok.contract.js +25 -3
- package/dist/contracts/grok.contract.js.map +1 -1
- package/dist/contracts/history.contract.d.ts.map +1 -1
- package/dist/contracts/history.contract.js +35 -4
- package/dist/contracts/history.contract.js.map +1 -1
- package/dist/contracts/intentic.contract.d.ts.map +1 -1
- package/dist/contracts/intentic.contract.js +25 -3
- package/dist/contracts/intentic.contract.js.map +1 -1
- package/dist/contracts/inventory.contract.d.ts.map +1 -1
- package/dist/contracts/inventory.contract.js +26 -3
- package/dist/contracts/inventory.contract.js.map +1 -1
- package/dist/contracts/logs.contract.d.ts.map +1 -1
- package/dist/contracts/logs.contract.js +17 -2
- package/dist/contracts/logs.contract.js.map +1 -1
- package/dist/contracts/loops.contract.d.ts.map +1 -1
- package/dist/contracts/loops.contract.js +52 -6
- package/dist/contracts/loops.contract.js.map +1 -1
- package/dist/contracts/panels.contract.d.ts.map +1 -1
- package/dist/contracts/panels.contract.js +26 -3
- package/dist/contracts/panels.contract.js.map +1 -1
- package/dist/contracts/personas.contract.d.ts.map +1 -1
- package/dist/contracts/personas.contract.js +71 -8
- package/dist/contracts/personas.contract.js.map +1 -1
- package/dist/contracts/ports.contract.d.ts.map +1 -1
- package/dist/contracts/ports.contract.js +26 -3
- package/dist/contracts/ports.contract.js.map +1 -1
- package/dist/contracts/prepush.contract.d.ts.map +1 -1
- package/dist/contracts/prepush.contract.js +24 -3
- package/dist/contracts/prepush.contract.js.map +1 -1
- package/dist/contracts/providers.contract.d.ts.map +1 -1
- package/dist/contracts/providers.contract.js +9 -1
- package/dist/contracts/providers.contract.js.map +1 -1
- package/dist/contracts/public.contract.d.ts.map +1 -1
- package/dist/contracts/public.contract.js +26 -3
- package/dist/contracts/public.contract.js.map +1 -1
- package/dist/contracts/push.contract.d.ts.map +1 -1
- package/dist/contracts/push.contract.js +35 -4
- package/dist/contracts/push.contract.js.map +1 -1
- package/dist/contracts/secrets.contract.d.ts.map +1 -1
- package/dist/contracts/secrets.contract.js +43 -5
- package/dist/contracts/secrets.contract.js.map +1 -1
- package/dist/contracts/sessions.contract.d.ts.map +1 -1
- package/dist/contracts/sessions.contract.js +15 -2
- package/dist/contracts/sessions.contract.js.map +1 -1
- package/dist/contracts/settings.contract.d.ts.map +1 -1
- package/dist/contracts/settings.contract.js +43 -5
- package/dist/contracts/settings.contract.js.map +1 -1
- package/dist/contracts/share.contract.d.ts.map +1 -1
- package/dist/contracts/share.contract.js +35 -4
- package/dist/contracts/share.contract.js.map +1 -1
- package/dist/contracts/skills.contract.d.ts.map +1 -1
- package/dist/contracts/skills.contract.js +35 -4
- package/dist/contracts/skills.contract.js.map +1 -1
- package/dist/contracts/system.contract.d.ts.map +1 -1
- package/dist/contracts/system.contract.js +107 -14
- package/dist/contracts/system.contract.js.map +1 -1
- package/dist/contracts/translator.contract.d.ts.map +1 -1
- package/dist/contracts/translator.contract.js +29 -4
- package/dist/contracts/translator.contract.js.map +1 -1
- package/dist/contracts/usage.contract.d.ts.map +1 -1
- package/dist/contracts/usage.contract.js +9 -1
- package/dist/contracts/usage.contract.js.map +1 -1
- package/dist/contracts/vpn.contract.d.ts.map +1 -1
- package/dist/contracts/vpn.contract.js +32 -4
- package/dist/contracts/vpn.contract.js.map +1 -1
- package/dist/contracts/workflows.contract.d.ts.map +1 -1
- package/dist/contracts/workflows.contract.js +70 -8
- package/dist/contracts/workflows.contract.js.map +1 -1
- package/dist/contracts/workspace.contract.d.ts.map +1 -1
- package/dist/contracts/workspace.contract.js +216 -25
- package/dist/contracts/workspace.contract.js.map +1 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +179 -88
- package/dist/events.js.map +1 -1
- package/dist/history-state.d.ts.map +1 -1
- package/dist/history-state.js +1 -0
- package/dist/history-state.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/schemas.d.ts +1 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +2856 -1276
- package/dist/schemas.js.map +1 -1
- package/package.json +4 -4
- package/src/agent-catalog.test.ts +48 -3
- package/src/agent-catalog.ts +88 -0
- package/src/capability-ledger.test.ts +21 -2
- package/src/contracts/activity.contract.ts +18 -2
- package/src/contracts/agent.contract.ts +78 -8
- package/src/contracts/agents.contract.ts +180 -19
- package/src/contracts/automations.contract.ts +80 -9
- package/src/contracts/capabilities.contract.ts +106 -11
- package/src/contracts/chores.contract.ts +29 -3
- package/src/contracts/ci.contract.ts +55 -6
- package/src/contracts/claude.contract.ts +47 -5
- package/src/contracts/drafts.contract.ts +26 -3
- package/src/contracts/endpoints.contract.ts +19 -2
- package/src/contracts/exit.contract.ts +69 -7
- package/src/contracts/extensions.contract.ts +134 -15
- package/src/contracts/git.contract.ts +421 -43
- package/src/contracts/grok.contract.ts +26 -3
- package/src/contracts/history.contract.ts +37 -4
- package/src/contracts/intentic.contract.ts +28 -3
- package/src/contracts/inventory.contract.ts +27 -3
- package/src/contracts/logs.contract.ts +18 -2
- package/src/contracts/loops.contract.ts +58 -6
- package/src/contracts/panels.contract.ts +26 -3
- package/src/contracts/personas.contract.ts +77 -8
- package/src/contracts/ports.contract.ts +27 -3
- package/src/contracts/prepush.contract.ts +26 -3
- package/src/contracts/providers.contract.ts +10 -1
- package/src/contracts/public.contract.ts +29 -3
- package/src/contracts/push.contract.ts +37 -4
- package/src/contracts/secrets.contract.ts +46 -5
- package/src/contracts/sessions.contract.ts +16 -2
- package/src/contracts/settings.contract.ts +46 -5
- package/src/contracts/share.contract.ts +37 -4
- package/src/contracts/skills.contract.ts +39 -4
- package/src/contracts/system.contract.ts +119 -14
- package/src/contracts/translator.contract.ts +32 -4
- package/src/contracts/usage.contract.ts +10 -1
- package/src/contracts/vpn.contract.ts +35 -4
- package/src/contracts/workflows.contract.ts +77 -8
- package/src/contracts/workspace.contract.ts +231 -25
- package/src/events.ts +207 -88
- package/src/history-state.ts +6 -0
- package/src/schemas.ts +3506 -1260
package/dist/schemas.js
CHANGED
|
@@ -3,22 +3,39 @@ import { ExtensionManifestSchema } from "@intentic/extension-manifest";
|
|
|
3
3
|
import { RegistryEntrySchema } from "@intentic/registry";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { OutputFieldsSchema } from "./output-fields.js";
|
|
6
|
-
export const OkSchema = z.object({
|
|
6
|
+
export const OkSchema = z.object({
|
|
7
|
+
ok: z
|
|
8
|
+
.literal(true)
|
|
9
|
+
.describe("Always true. A route that answers this either did the thing or refused with a status; there is no third outcome to report."),
|
|
10
|
+
});
|
|
7
11
|
export const MemberRoleSchema = z.enum(["viewer", "collaborator", "maintainer", "owner"]);
|
|
8
12
|
export const GrantedRoleSchema = z.enum(["viewer", "collaborator", "maintainer"]);
|
|
9
13
|
const MEMBER_ROLE_RANK = { viewer: 0, collaborator: 1, maintainer: 2, owner: 3 };
|
|
10
14
|
export const roleAtLeast = (role, floor) => MEMBER_ROLE_RANK[role] >= MEMBER_ROLE_RANK[floor];
|
|
11
|
-
export const RepoParamSchema = z.object({
|
|
15
|
+
export const RepoParamSchema = z.object({
|
|
16
|
+
repo: z
|
|
17
|
+
.string()
|
|
18
|
+
.describe('Which repository. "root" is the workspace itself; anything else is a repository\'s folder relative to the workspace root, URL-encoded.'),
|
|
19
|
+
});
|
|
12
20
|
export const NATIVE_PROVIDERS = ["claude", "codex", "grok", "kimi", "gemini"];
|
|
13
21
|
export const AgentProviderSchema = z.string().min(1);
|
|
14
22
|
export const NativeProviderParamSchema = z.object({ provider: z.enum(NATIVE_PROVIDERS) });
|
|
15
23
|
export const AgentHarnessSchema = z.enum(["native", "claude-code"]);
|
|
16
24
|
export const RepoBaseSchema = z.object({ repo: z.string(), base: z.string().min(1) });
|
|
17
25
|
export const EditorContextSchema = z.object({
|
|
18
|
-
file: z.string().min(1),
|
|
19
|
-
startLine: z
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
file: z.string().min(1).describe("The file open in the editor, as a workspace path."),
|
|
27
|
+
startLine: z
|
|
28
|
+
.number()
|
|
29
|
+
.int()
|
|
30
|
+
.min(1)
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("First line of the selection, counting from one. Leave both out when the whole file is the context."),
|
|
33
|
+
endLine: z.number().int().min(1).optional().describe("Last line of the selection, counting from one."),
|
|
34
|
+
selection: z
|
|
35
|
+
.string()
|
|
36
|
+
.max(20_000)
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("The selected text itself. Cut it down before sending if it is long: this is context, not an upload."),
|
|
22
39
|
});
|
|
23
40
|
export const ConversationIdSchema = z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/);
|
|
24
41
|
const entryId = z
|
|
@@ -57,35 +74,70 @@ export const ForkedFromSchema = z.object({
|
|
|
57
74
|
});
|
|
58
75
|
export const AgentTurnSchema = z
|
|
59
76
|
.object({
|
|
60
|
-
prompt: z.string(),
|
|
61
|
-
title: z
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
prompt: z.string().describe("What to say to the agent. May be empty if you are only attaching files."),
|
|
78
|
+
title: z
|
|
79
|
+
.string()
|
|
80
|
+
.max(80)
|
|
81
|
+
.optional()
|
|
82
|
+
.describe("A title for a conversation this turn is opening. Ignored for a conversation that already has one."),
|
|
83
|
+
attachments: z
|
|
84
|
+
.array(z.string().min(1))
|
|
85
|
+
.max(20)
|
|
86
|
+
.optional()
|
|
87
|
+
.describe("Files to hand the agent along with the prompt, as workspace paths. Upload them first."),
|
|
88
|
+
agent: AgentProviderSchema.optional().describe("Which model provider serves this turn. Leave it out for Claude."),
|
|
89
|
+
harness: AgentHarnessSchema.optional().describe("Which agentic loop runs the turn. Leave it out to use each provider's own."),
|
|
90
|
+
account: z.string().optional().describe("Which of that provider's connected accounts pays for the turn. Leave it out for the first one."),
|
|
91
|
+
actsAs: entryId.optional().describe("Which persona the turn speaks as out in the world. Not the same as which account pays for it."),
|
|
92
|
+
sessionId: z.string().optional().describe("Resume this provider session instead of starting a fresh one."),
|
|
93
|
+
conversationId: ConversationIdSchema.optional().describe("The conversation this turn belongs to. You choose it, it survives model switches, and it is how you address the conversation later. Naming one that does not exist opens it."),
|
|
94
|
+
isolated: z
|
|
95
|
+
.boolean()
|
|
96
|
+
.optional()
|
|
97
|
+
.describe("Work in this conversation's own private copy of the repos rather than the shared tree, so several agents can work at once. Needs a conversation id."),
|
|
98
|
+
worktreeBase: z
|
|
99
|
+
.array(RepoBaseSchema)
|
|
100
|
+
.min(1)
|
|
101
|
+
.max(50)
|
|
102
|
+
.optional()
|
|
103
|
+
.describe("Pin a new private copy to these exact commits instead of today's workspace. Used when several agents must start from identical files."),
|
|
104
|
+
autoLand: z
|
|
105
|
+
.boolean()
|
|
106
|
+
.optional()
|
|
107
|
+
.describe("Whether this turn's work merges into the workspace when it finishes. Overrides the conversation's own setting for this turn only."),
|
|
108
|
+
origin: AgentOriginSchema.optional().describe("Set by the sandbox alone: this turn opened a conversation on behalf of a message from outside rather than a person."),
|
|
73
109
|
forkOf: z
|
|
74
110
|
.object({
|
|
75
|
-
conversationId: ConversationIdSchema,
|
|
76
|
-
keep: z.number().int().nonnegative(),
|
|
77
|
-
files: z
|
|
111
|
+
conversationId: ConversationIdSchema.describe("The conversation this one was cut from."),
|
|
112
|
+
keep: z.number().int().nonnegative().describe("How many of that conversation's messages to copy in before this turn runs."),
|
|
113
|
+
files: z
|
|
114
|
+
.enum(["then", "now"])
|
|
115
|
+
.describe('Which files the fork opens on: "now" is the workspace as it stands, "then" is the files as they were at the cut, which needs a private copy.'),
|
|
78
116
|
})
|
|
79
|
-
.optional()
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
117
|
+
.optional()
|
|
118
|
+
.describe("Where this conversation was cut from, on its first turn only. Only the client knows this, so only the client can say it."),
|
|
119
|
+
model: z.string().optional().describe("Which model to use. Leave it out for the provider's default."),
|
|
120
|
+
unattended: z
|
|
121
|
+
.boolean()
|
|
122
|
+
.optional()
|
|
123
|
+
.describe("Nobody chose a model for this turn because a screen started it rather than a person. The sandbox then fills in the model its owner picked for unwatched work."),
|
|
124
|
+
outsideWake: z
|
|
125
|
+
.string()
|
|
126
|
+
.min(1)
|
|
127
|
+
.optional()
|
|
128
|
+
.describe("Content from outside caused this turn, and what to call the source. It is what makes the sandbox treat the turn as carrying somebody else's words."),
|
|
129
|
+
permissionMode: PermissionModeSchema.optional().describe("How tool calls are gated: ask each time, accept file edits, propose a plan first, or run everything. The agent can move itself between these mid-turn."),
|
|
130
|
+
allowedTools: z
|
|
131
|
+
.array(z.string().min(1))
|
|
132
|
+
.optional()
|
|
133
|
+
.describe("Narrow the turn to these tools. Leave it out for everything the runtime has. For a turn driven by an outside message this list is the real boundary, because prompt wording is only advice."),
|
|
134
|
+
effort: z.string().optional().describe("How hard the model should think, where the provider offers a choice."),
|
|
135
|
+
thinking: z.boolean().optional().describe("Whether to show the model's reasoning as it works."),
|
|
136
|
+
fast: z
|
|
137
|
+
.boolean()
|
|
138
|
+
.optional()
|
|
139
|
+
.describe("Ask for the same work at a higher rate for a higher price. A request rather than a promise: the answer says what actually happened."),
|
|
140
|
+
editorContext: EditorContextSchema.optional().describe('What the user has open in their editor, folded into the prompt so that pointing words like "this" resolve.'),
|
|
89
141
|
})
|
|
90
142
|
.refine((turn) => turn.prompt.trim().length > 0 || (turn.attachments?.length ?? 0) > 0, {
|
|
91
143
|
message: "prompt or attachments required",
|
|
@@ -105,86 +157,189 @@ export const AgentTurnSchema = z
|
|
|
105
157
|
.refine((turn) => turn.forkOf?.files !== "then" || turn.isolated === true, {
|
|
106
158
|
message: 'forkOf.files "then" requires isolated',
|
|
107
159
|
});
|
|
108
|
-
export const AgentRunPickSchema = z
|
|
109
|
-
|
|
160
|
+
export const AgentRunPickSchema = z
|
|
161
|
+
.object({
|
|
162
|
+
agent: z.string().min(1).describe("Which provider."),
|
|
163
|
+
model: z
|
|
164
|
+
.string()
|
|
165
|
+
.min(1)
|
|
166
|
+
.describe("Which of its models. Both or neither, because a model name only means anything to the provider that serves it."),
|
|
167
|
+
})
|
|
168
|
+
.optional();
|
|
169
|
+
export const StartedTurnSchema = z.object({
|
|
170
|
+
run: z.string().describe("The id of the run that just started. Hand it back when you attach, so the stream resumes rather than replaying."),
|
|
171
|
+
});
|
|
110
172
|
export const AttachTurnSchema = z.object({
|
|
111
|
-
conversationId: ConversationIdSchema,
|
|
112
|
-
run: z
|
|
113
|
-
|
|
173
|
+
conversationId: ConversationIdSchema.describe("Which conversation to watch."),
|
|
174
|
+
run: z
|
|
175
|
+
.string()
|
|
176
|
+
.optional()
|
|
177
|
+
.describe("The run you were watching. If a newer turn has started since, the stream replays that one from its beginning instead."),
|
|
178
|
+
after: z
|
|
179
|
+
.number()
|
|
180
|
+
.int()
|
|
181
|
+
.min(0)
|
|
182
|
+
.optional()
|
|
183
|
+
.describe("The last frame you already have. Everything after it replays, then the stream goes live. Leave it out to start from the beginning."),
|
|
114
184
|
});
|
|
115
185
|
export const LoopContextSchema = z.enum(["fresh", "continue"]);
|
|
116
186
|
export const LoopOutputSchema = z.discriminatedUnion("kind", [
|
|
117
|
-
z.object({
|
|
118
|
-
|
|
119
|
-
|
|
187
|
+
z.object({
|
|
188
|
+
kind: z
|
|
189
|
+
.literal("none")
|
|
190
|
+
.describe("It produces nothing but its work. The classic make the suite pass: what it leaves behind is a passing suite, and asking it to also file a report is asking it to spend a round on paperwork."),
|
|
191
|
+
}),
|
|
192
|
+
z.object({
|
|
193
|
+
kind: z
|
|
194
|
+
.literal("claim")
|
|
195
|
+
.describe("Each round says whether it is done and why. Structured prose: done is a value read rather than a sentence interpreted. Self-assessment, so advisory by construction; it exists because plenty of goals have no command that could check them."),
|
|
196
|
+
}),
|
|
197
|
+
z.object({
|
|
198
|
+
kind: z
|
|
199
|
+
.literal("json")
|
|
200
|
+
.describe("Each round writes a real answer in a shape you declared. This is the one that makes a step's output usable as the next step's input: a paragraph mentioning three files cannot be fed to anything, a list of three files can."),
|
|
201
|
+
fields: OutputFieldsSchema.describe("The shape that answer has to match."),
|
|
202
|
+
}),
|
|
120
203
|
]);
|
|
121
204
|
export const LoopCheckSchema = z.discriminatedUnion("kind", [
|
|
122
|
-
z.object({
|
|
123
|
-
|
|
205
|
+
z.object({
|
|
206
|
+
kind: z
|
|
207
|
+
.literal("command")
|
|
208
|
+
.describe("Run something and see if it passes. Deterministic, free, and the only signal here whose answer does not come from a model. A passing test suite beats any amount of self-report."),
|
|
209
|
+
command: z.string().min(1).describe("The command to run in the conversation's own tree. Exiting cleanly means satisfied."),
|
|
210
|
+
}),
|
|
211
|
+
z.object({
|
|
212
|
+
kind: z
|
|
213
|
+
.literal("judge")
|
|
214
|
+
.describe("Put the question to a separate model with no tools, which reads the round's own report and rules on it, having done none of the work and nothing invested in its being finished."),
|
|
215
|
+
rubric: z.string().min(1).describe("What that judge is asked."),
|
|
216
|
+
model: z.string().optional().describe("Which model judges. Leave it out for the cheap one the other small jobs use."),
|
|
217
|
+
}),
|
|
124
218
|
]);
|
|
125
219
|
export const LoopDocumentSchema = z.object({
|
|
126
|
-
done: z.boolean(),
|
|
127
|
-
reason: z.string(),
|
|
128
|
-
evidence: z
|
|
129
|
-
|
|
220
|
+
done: z.boolean().describe("Whether the goal is met. Reading this is the whole point of the file."),
|
|
221
|
+
reason: z.string().describe("Why, in one line. The most-read sentence in the feature: the next round reads it first and the history shows it."),
|
|
222
|
+
evidence: z
|
|
223
|
+
.string()
|
|
224
|
+
.optional()
|
|
225
|
+
.describe("What was checked to know that. Optional, so a round with nothing to point at says so by leaving it out rather than by inventing a sentence."),
|
|
226
|
+
data: z
|
|
227
|
+
.record(z.string(), z.unknown())
|
|
228
|
+
.optional()
|
|
229
|
+
.describe("The declared answer, for a loop that asked for one, checked against the shape it declared."),
|
|
130
230
|
});
|
|
131
231
|
const LOOP_ITERATIONS_MAX = 50;
|
|
132
232
|
export const LoopSchema = z.object({
|
|
133
|
-
conversationId: ConversationIdSchema,
|
|
134
|
-
goal: z
|
|
135
|
-
|
|
136
|
-
|
|
233
|
+
conversationId: ConversationIdSchema.describe("The conversation to loop. It need not exist yet: naming a fresh one opens it, which is what lets run this until it passes be the first thing you ever say."),
|
|
234
|
+
goal: z
|
|
235
|
+
.string()
|
|
236
|
+
.min(1)
|
|
237
|
+
.describe("What done means, in your words. It goes into every round's instructions and into the judge's question, so the model is told the bar rather than left to infer it."),
|
|
238
|
+
prompt: z
|
|
239
|
+
.string()
|
|
240
|
+
.min(1)
|
|
241
|
+
.describe("What each round is asked to do. The suite passes is the goal; run the tests, take the top failure, fix it is the instruction."),
|
|
242
|
+
context: LoopContextSchema.describe("How each round meets the last. Starting fresh makes the files the memory rather than the conversation, so the twentieth round reads the tree as clearly as the first, and costs a re-read each time. Carrying on is cheaper and keeps the reasoning, which suits a short polish-this loop and degrades on long ones: a session that has spent eleven rounds arguing for its own approach is the worst available judge of whether that approach is finished."),
|
|
137
243
|
output: LoopOutputSchema,
|
|
138
|
-
checks: z
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
244
|
+
checks: z
|
|
245
|
+
.array(LoopCheckSchema)
|
|
246
|
+
.describe("What else has to be true, all of them together. A list because the suite passes and the report is written is a real bar, and running it as two loops would do the work twice."),
|
|
247
|
+
maxIterations: z
|
|
248
|
+
.number()
|
|
249
|
+
.int()
|
|
250
|
+
.min(1)
|
|
251
|
+
.max(LOOP_ITERATIONS_MAX)
|
|
252
|
+
.describe("How many rounds before it gives up. A loop that has not got there in fifty is not one round short of it."),
|
|
253
|
+
maxSpendUsd: z
|
|
254
|
+
.number()
|
|
255
|
+
.positive()
|
|
256
|
+
.optional()
|
|
257
|
+
.describe("A ceiling on what the whole loop may spend, in dollars. Optional for a short loop somebody is watching, and strongly wanted otherwise: this is the first thing here that can keep spending with nobody pressing anything between rounds."),
|
|
258
|
+
stallLimit: z
|
|
259
|
+
.number()
|
|
260
|
+
.int()
|
|
261
|
+
.min(1)
|
|
262
|
+
.describe("Stop after this many rounds in a row that changed nothing on disk. The guard that matters most: a loop's failure is not runaway success, it is an agent re-reading the same three files, restating the same plan and declaring more work remains, eleven times. Every one of those rounds succeeds, so only the tree not moving catches it."),
|
|
263
|
+
isolated: z
|
|
264
|
+
.boolean()
|
|
265
|
+
.describe("Whether it works in the conversation's own private copy or in the shared tree. It also decides where a check runs: testing the shared tree would be testing code this loop has not merged yet."),
|
|
266
|
+
agent: AgentProviderSchema.optional().describe("Which provider the rounds run on. Absent falls back to the conversation's own last choice."),
|
|
267
|
+
harness: AgentHarnessSchema.optional().describe("Which agentic loop they run on."),
|
|
268
|
+
account: z.string().optional().describe("Which account pays."),
|
|
269
|
+
model: z.string().optional().describe("Which model."),
|
|
270
|
+
actsAs: entryId
|
|
271
|
+
.optional()
|
|
272
|
+
.describe("Which persona the rounds act as. It matters here: every round is unwatched, and an unwatched turn naming no persona reaches no signed-in account at all, so pinning one is how a loop gets hands."),
|
|
273
|
+
worktreeBase: z
|
|
274
|
+
.array(RepoBaseSchema)
|
|
275
|
+
.min(1)
|
|
276
|
+
.max(50)
|
|
277
|
+
.optional()
|
|
278
|
+
.describe("Pin the private copy to these exact commits, so a restart cannot quietly change what the loop is working on."),
|
|
279
|
+
autoLand: z.boolean().optional().describe("Whether the work merges as it goes."),
|
|
150
280
|
});
|
|
151
281
|
export const loopCanConverge = (loop) => loop.output.kind !== "none" || loop.checks.length > 0;
|
|
152
282
|
export const LOOP_DIR = `${STATE_DIR}/records/artifacts/loops`;
|
|
153
283
|
export const LoopIterationSchema = z.object({
|
|
154
|
-
n: z.number().int().min(1),
|
|
155
|
-
at: z.number(),
|
|
156
|
-
outcome: z
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
284
|
+
n: z.number().int().min(1).describe("Which round this was."),
|
|
285
|
+
at: z.number().describe("When it ran, in milliseconds."),
|
|
286
|
+
outcome: z
|
|
287
|
+
.enum(["continue", "done", "error"])
|
|
288
|
+
.describe("How the round ended, which is not the same question as how the loop did. A round that errored does not end the loop by itself: a failing turn is often exactly what the next round is meant to fix."),
|
|
289
|
+
detail: z
|
|
290
|
+
.string()
|
|
291
|
+
.optional()
|
|
292
|
+
.describe("What the check said, in its own words. What a run history is actually read for: why it kept going, and why it stopped."),
|
|
293
|
+
costUsd: z.number().optional().describe("What the round cost, in dollars."),
|
|
294
|
+
changed: z.boolean().describe("Whether anything on disk moved. Three unchanged rounds in a row is the shape of a loop that is not working."),
|
|
295
|
+
sessionId: z.string().optional().describe("The session it ran on, and the way from a history row to a readable record."),
|
|
161
296
|
});
|
|
162
297
|
export const LoopStateSchema = z.enum(["running", "done", "exhausted", "stalled", "overspent", "stopped", "error"]);
|
|
163
298
|
export const LoopRecordSchema = LoopSchema.extend({
|
|
164
|
-
state: LoopStateSchema,
|
|
165
|
-
startedAt: z.number(),
|
|
166
|
-
endedAt: z.number().optional(),
|
|
167
|
-
resumed: z
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
299
|
+
state: LoopStateSchema.describe("How it ended, and each of these is a different thing to be told. Out of rounds says give it more room; stalled says it is not making progress and more room will not help. Overspent, stopped by a person, and the loop itself failing are all their own answers."),
|
|
300
|
+
startedAt: z.number().describe("When it began, in milliseconds."),
|
|
301
|
+
endedAt: z.number().optional().describe("When it ended, in milliseconds."),
|
|
302
|
+
resumed: z
|
|
303
|
+
.number()
|
|
304
|
+
.int()
|
|
305
|
+
.min(0)
|
|
306
|
+
.describe("How many times the sandbox restarted under it and picked it back up. Counted rather than flagged, so a loop whose round reliably kills the sandbox is not resurrected on every boot for ever."),
|
|
307
|
+
detail: z.string().optional().describe("Why it ended, for the endings whose reason is not in their name."),
|
|
308
|
+
iterations: z
|
|
309
|
+
.array(LoopIterationSchema)
|
|
310
|
+
.describe("Every round, in order. Why it stopped at the fourth is the question a loop gets read for, and this is the answer."),
|
|
311
|
+
});
|
|
312
|
+
export const LoopsListSchema = z.object({
|
|
313
|
+
loops: z.array(LoopRecordSchema).describe("Every loop this workspace has run, newest first, kept after they end."),
|
|
314
|
+
});
|
|
315
|
+
export const LoopIdParamSchema = z.object({ conversationId: ConversationIdSchema.describe("Which conversation's loop.") });
|
|
173
316
|
export const LoopDesignSchema = z.object({
|
|
174
|
-
id: entryId,
|
|
175
|
-
name: z.string().min(1).max(60),
|
|
176
|
-
description: z.string().max(280).optional(),
|
|
177
|
-
prompt: z
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
317
|
+
id: entryId.describe("The design's id."),
|
|
318
|
+
name: z.string().min(1).max(60).describe("What to call it. Short, because it has to be readable on a small badge."),
|
|
319
|
+
description: z.string().max(280).optional().describe("What it is for, in one line. Optional, because a well-named loop has already said it."),
|
|
320
|
+
prompt: z
|
|
321
|
+
.string()
|
|
322
|
+
.optional()
|
|
323
|
+
.describe("What each round is asked to do, when that is worth saying separately from the goal. Absent means each round works towards the goal however it sees fit."),
|
|
324
|
+
context: LoopContextSchema.describe("How each round meets the last: starting clean, or carrying on."),
|
|
325
|
+
output: LoopOutputSchema.describe("What it has to produce."),
|
|
326
|
+
checks: z.array(LoopCheckSchema).describe("What else has to be true."),
|
|
327
|
+
maxIterations: z.number().int().min(1).max(LOOP_ITERATIONS_MAX).describe("How many rounds before it gives up."),
|
|
328
|
+
maxSpendUsd: z.number().positive().optional().describe("A ceiling on what it may spend, in dollars."),
|
|
329
|
+
stallLimit: z.number().int().min(1).describe("Stop after this many rounds in a row that changed nothing."),
|
|
330
|
+
});
|
|
331
|
+
export const LoopDesignsListSchema = z.object({
|
|
332
|
+
designs: z
|
|
333
|
+
.array(LoopDesignSchema)
|
|
334
|
+
.describe("Saved loops: the machinery with the goal left out, so one design can be pointed at a different job every time."),
|
|
335
|
+
});
|
|
336
|
+
export const LoopDesignSaveSchema = z.object({
|
|
337
|
+
design: LoopDesignSchema.describe("The design to write."),
|
|
338
|
+
create: z
|
|
339
|
+
.boolean()
|
|
340
|
+
.describe("Whether you mean to make a new one or replace an existing one, so an id that happens to collide cannot silently overwrite the one you had."),
|
|
341
|
+
});
|
|
342
|
+
export const LoopDesignIdParamSchema = z.object({ id: entryId.describe("Which saved loop.") });
|
|
188
343
|
export const loopFromDesign = (design, aim) => ({
|
|
189
344
|
conversationId: aim.conversationId,
|
|
190
345
|
goal: aim.goal,
|
|
@@ -223,125 +378,274 @@ export const AgentStatusSchema = z.enum([
|
|
|
223
378
|
"interrupted",
|
|
224
379
|
]);
|
|
225
380
|
export const AgentActivitySchema = z.object({
|
|
226
|
-
tool: z.string().optional(),
|
|
227
|
-
target: z.string().optional(),
|
|
228
|
-
todo: z.string().optional(),
|
|
381
|
+
tool: z.string().optional().describe("The last tool it reached for."),
|
|
382
|
+
target: z.string().optional().describe("What it reached for that tool with: a file, a command, a URL."),
|
|
383
|
+
todo: z.string().optional().describe("The item on its own list that it is working through."),
|
|
229
384
|
});
|
|
230
385
|
export const AgentAttentionSchema = z.object({
|
|
231
|
-
plan: z.boolean(),
|
|
232
|
-
question: z.boolean(),
|
|
233
|
-
permission: z.boolean(),
|
|
234
|
-
service: z
|
|
235
|
-
|
|
236
|
-
|
|
386
|
+
plan: z.boolean().describe("It has proposed a plan and is waiting for a yes."),
|
|
387
|
+
question: z.boolean().describe("It has asked you something."),
|
|
388
|
+
permission: z.boolean().describe("It wants to use a tool it needs permission for."),
|
|
389
|
+
service: z
|
|
390
|
+
.boolean()
|
|
391
|
+
.describe("It wants to spend money on a paid service and is waiting for approval. The one pause where waiting costs it the whole call."),
|
|
392
|
+
capability: z.boolean().describe("It needs something connected that is not connected yet."),
|
|
393
|
+
conflict: z.boolean().describe("Its work cannot be merged without somebody resolving a clash."),
|
|
237
394
|
});
|
|
238
395
|
export const LandedMessageSchema = z.object({
|
|
239
|
-
subject: z
|
|
240
|
-
|
|
241
|
-
|
|
396
|
+
subject: z
|
|
397
|
+
.string()
|
|
398
|
+
.describe("One line saying what the merged work did, read off the code rather than off the opening request. A conversation that asks for an audit and then spends four turns fixing what it found needs a subject about the fixes."),
|
|
399
|
+
note: z
|
|
400
|
+
.string()
|
|
401
|
+
.optional()
|
|
402
|
+
.describe("The same change said to somebody who uses the product, for a repository that keeps a changelog. Usually absent, because most changes are not ones a user would notice."),
|
|
403
|
+
breaking: z
|
|
404
|
+
.string()
|
|
405
|
+
.optional()
|
|
406
|
+
.describe("What this change takes away, for anything already relying on it. Nearly always absent: it is for removals, not for additions."),
|
|
242
407
|
});
|
|
243
408
|
export const LandedMessageStepSchema = z.object({
|
|
244
|
-
provider: z.string().min(1),
|
|
245
|
-
model: z.string().min(1),
|
|
246
|
-
status: z
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
409
|
+
provider: z.string().min(1).describe("Which provider was asked."),
|
|
410
|
+
model: z.string().min(1).describe("Which of its models."),
|
|
411
|
+
status: z
|
|
412
|
+
.enum(["asking", "answered", "refused", "skipped"])
|
|
413
|
+
.describe("How this one went. Skipped means it was not asked at all, because it refused a few minutes ago and the walk stepped over it."),
|
|
414
|
+
at: z.number().optional().describe("When it started being asked, in milliseconds. Absent for one that was skipped, which cost no time."),
|
|
415
|
+
ms: z.number().optional().describe("How long it took. Absent while it is still being asked."),
|
|
416
|
+
reason: z.string().optional().describe("Why it refused, in its own words."),
|
|
250
417
|
});
|
|
251
418
|
export const LandedMessageDraftSchema = z.object({
|
|
252
|
-
startedAt: z.number(),
|
|
253
|
-
steps: z
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
419
|
+
startedAt: z.number().describe("When the drafting began, in milliseconds."),
|
|
420
|
+
steps: z
|
|
421
|
+
.array(LandedMessageStepSchema)
|
|
422
|
+
.describe("Each model that was asked, in the order they were spent, so the list is the timeline. Empty with no outcome means the diff is still being read."),
|
|
423
|
+
outcome: z.enum(["written", "failed"]).optional().describe("How it ended. Absent means it is still going."),
|
|
424
|
+
reason: z
|
|
425
|
+
.string()
|
|
426
|
+
.optional()
|
|
427
|
+
.describe("The one-line account of a failure, for a screen with one line to spend. The steps carry each model's own words."),
|
|
428
|
+
finishedAt: z.number().optional().describe("When it ended, in milliseconds."),
|
|
257
429
|
});
|
|
258
430
|
export const AgentSummarySchema = z.object({
|
|
259
|
-
id: z.string(),
|
|
260
|
-
sessionId: z.string().optional(),
|
|
261
|
-
title: z.string().optional(),
|
|
262
|
-
status: AgentStatusSchema,
|
|
263
|
-
failure: z
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
431
|
+
id: z.string().describe("The conversation id, which is how every other call addresses it."),
|
|
432
|
+
sessionId: z.string().optional().describe("The provider session behind the last turn. It is retired whenever the model or account changes."),
|
|
433
|
+
title: z.string().optional().describe("What to call it: the first prompt cut to one line, unless somebody renamed it."),
|
|
434
|
+
status: AgentStatusSchema.describe("What it is doing. Stopping and stopped are the two halves of somebody pressing stop, because a cancel is not instant; resuming means the sandbox is already putting right whatever killed the turn."),
|
|
435
|
+
failure: z
|
|
436
|
+
.string()
|
|
437
|
+
.optional()
|
|
438
|
+
.describe("Why the last turn failed, in the words it died on. Absent unless it did, and cleared the moment it runs again. Carried here because the word error on its own is not an answer, least of all for a run nobody was watching."),
|
|
439
|
+
provider: AgentProviderSchema.describe("Which model provider it runs on."),
|
|
440
|
+
harness: AgentHarnessSchema.describe("Which agentic loop it runs on."),
|
|
441
|
+
model: z
|
|
442
|
+
.string()
|
|
443
|
+
.optional()
|
|
444
|
+
.describe("What its last turn ran with. Kept per conversation so opening it restores the choices made in it, rather than whatever some other tab last picked."),
|
|
445
|
+
effort: z.string().optional().describe("How hard that turn was told to think."),
|
|
446
|
+
thinking: z.boolean().optional().describe("Whether that turn showed its reasoning."),
|
|
447
|
+
fast: z.boolean().optional().describe("Whether that turn asked for higher speed. What was asked for, not what was served."),
|
|
448
|
+
account: z.string().optional().describe("Which connected account paid for it."),
|
|
449
|
+
branch: z.string().optional().describe("The branch its private copy works on. Absent for a conversation that works directly in the shared tree."),
|
|
450
|
+
autoLand: z
|
|
451
|
+
.boolean()
|
|
452
|
+
.optional()
|
|
453
|
+
.describe("This conversation's own answer to whether its work merges automatically. Absent means it follows the sandbox-wide setting, which is the common case."),
|
|
273
454
|
resumeAfterOutage: z.boolean().optional(),
|
|
274
|
-
landRequested: z
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
455
|
+
landRequested: z
|
|
456
|
+
.object({
|
|
457
|
+
email: z.string().describe("Who asked."),
|
|
458
|
+
name: z.string().optional().describe("Their display name."),
|
|
459
|
+
at: z.number().describe("When they asked, in milliseconds."),
|
|
460
|
+
})
|
|
461
|
+
.optional()
|
|
462
|
+
.describe("A collaborator has asked a maintainer to merge this work. Cleared by whichever merge or discard answers it. Absent means nobody is waiting."),
|
|
463
|
+
origin: AgentOriginSchema.optional().describe("Where the conversation came from when nobody typed it: a chat mention, a visitor's message, a webhook. Absent means a person started it."),
|
|
464
|
+
forkedFrom: ForkedFromSchema.optional().describe("The conversation this one was cut from. Recorded once and never cleared: it is the relationship, not a pending state."),
|
|
465
|
+
base: z.string().optional().describe("The commit its private copy started from, shortened."),
|
|
466
|
+
costUsd: z.number().optional().describe("What it has cost so far, in dollars. A helper agent's spend is its own and is not folded in here."),
|
|
467
|
+
inputTokens: z.number().optional().describe("Tokens sent."),
|
|
468
|
+
outputTokens: z.number().optional().describe("Tokens received."),
|
|
469
|
+
contextTokens: z.number().optional().describe("How much of the window the conversation currently fills."),
|
|
470
|
+
contextWindow: z.number().optional().describe("How large that window is."),
|
|
471
|
+
activity: AgentActivitySchema.optional().describe("What it is doing at this moment."),
|
|
472
|
+
landedMessageDraft: LandedMessageDraftSchema.optional().describe("The whole story of this merge's commit message being written: which models were asked, how long each took, what refused and in what words. Forgotten on restart, which is right, because a restart also killed the drafting it describes."),
|
|
473
|
+
landedMessage: LandedMessageSchema.optional().describe("What this conversation's merged work is called, once the drafting above has finished. It arrives on the same push that ends the draft, so the promise and the answer travel together."),
|
|
474
|
+
startedAt: z.number().optional().describe("When the running turn started, in milliseconds. Absent when none is running."),
|
|
475
|
+
updatedAt: z.number().describe("When it last did something, in milliseconds. Reading it does not count."),
|
|
476
|
+
seenAt: z
|
|
477
|
+
.number()
|
|
478
|
+
.optional()
|
|
479
|
+
.describe("When somebody last opened it, in milliseconds. Newer activity than this is what makes it unread. Kept by the sandbox rather than by a browser, so clearing site data or picking up a phone does not resurrect every badge."),
|
|
480
|
+
attention: AgentAttentionSchema.describe("Which kinds of waiting-for-you it is doing."),
|
|
481
|
+
turns: z.number().optional().describe("Turns it has finished."),
|
|
482
|
+
toolUses: z.number().optional().describe("Tools it has used, over its whole life."),
|
|
483
|
+
subagents: z
|
|
484
|
+
.object({
|
|
485
|
+
running: z.number().describe("Helpers working right now."),
|
|
486
|
+
total: z.number().describe("Helpers it has started over its whole life."),
|
|
487
|
+
})
|
|
488
|
+
.optional()
|
|
489
|
+
.describe("Helper agents this one delegated to. Absent means it never has, which is most conversations. Their spend is their own and is not folded into this conversation's cost."),
|
|
490
|
+
diff: z
|
|
491
|
+
.object({
|
|
492
|
+
files: z.number().describe("Files touched."),
|
|
493
|
+
insertions: z.number().describe("Lines added."),
|
|
494
|
+
deletions: z.number().describe("Lines removed."),
|
|
495
|
+
})
|
|
496
|
+
.optional()
|
|
497
|
+
.describe("Everything it has written, measured from where it started. Independent of how much has been merged."),
|
|
498
|
+
landedPresence: z
|
|
499
|
+
.object({
|
|
500
|
+
landed: z.number().describe("Paths this conversation merged in."),
|
|
501
|
+
present: z.number().describe("How many of them are still there, either pending or committed."),
|
|
502
|
+
})
|
|
503
|
+
.optional()
|
|
504
|
+
.describe("Present only when some of what it merged has since been thrown away. Absent is the steady state: its presence is the signal, so an ordinary card spends no line on it."),
|
|
295
505
|
loop: z
|
|
296
|
-
.object({
|
|
297
|
-
.
|
|
506
|
+
.object({
|
|
507
|
+
state: LoopStateSchema.describe("How the loop is going."),
|
|
508
|
+
iteration: z.number().int().min(0).describe("Which round it is on."),
|
|
509
|
+
maxIterations: z.number().int().min(1).describe("How many rounds it will attempt before giving up."),
|
|
510
|
+
goal: z.string().describe("What it is looping towards."),
|
|
511
|
+
})
|
|
512
|
+
.optional()
|
|
513
|
+
.describe("The loop driving this conversation, if one is. Absent for an ordinary conversation, which is nearly all of them."),
|
|
298
514
|
workflow: z
|
|
299
515
|
.object({
|
|
300
|
-
runId: z.string(),
|
|
301
|
-
name: z.string(),
|
|
302
|
-
step: z.string(),
|
|
303
|
-
index: z.number().int().min(1),
|
|
304
|
-
total: z.number().int().min(1),
|
|
516
|
+
runId: z.string().describe("The run this belongs to, which is how a board groups its steps together."),
|
|
517
|
+
name: z.string().describe("The workflow's name."),
|
|
518
|
+
step: z.string().describe("Which step this conversation is on now. It moves when steps are chained."),
|
|
519
|
+
index: z.number().int().min(1).describe("This step's place in the workflow, counting from one."),
|
|
520
|
+
total: z.number().int().min(1).describe("How many steps the workflow has."),
|
|
305
521
|
})
|
|
306
|
-
.optional()
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
export const
|
|
314
|
-
export const
|
|
522
|
+
.optional()
|
|
523
|
+
.describe("The workflow run this conversation is a step of. Without it, a four-step run reads as four unrelated conversations that happen to have started together."),
|
|
524
|
+
archivedAt: z
|
|
525
|
+
.number()
|
|
526
|
+
.optional()
|
|
527
|
+
.describe("When it was put away, in milliseconds. Nothing was lost: its branch, its record and every counter stayed, and bringing it back gives it a fresh working copy. Absent means it is live on the board."),
|
|
528
|
+
});
|
|
529
|
+
export const AgentIdSchema = z.object({ id: z.string().min(1).describe("Which conversation.") });
|
|
530
|
+
export const AgentArchiveSchema = z.object({
|
|
531
|
+
ids: z
|
|
532
|
+
.array(z.string().min(1))
|
|
533
|
+
.max(500)
|
|
534
|
+
.optional()
|
|
535
|
+
.describe("Which conversations to put away. Leave it out for every finished one that can be archived right now."),
|
|
536
|
+
});
|
|
537
|
+
export const AgentIdsSchema = z.object({ ids: z.array(z.string().min(1)).min(1).max(500).describe("Which conversations.") });
|
|
538
|
+
export const AgentsMovedSchema = z.object({
|
|
539
|
+
moved: z
|
|
540
|
+
.array(AgentSummarySchema)
|
|
541
|
+
.describe("What actually moved, whole, rather than the fleet afterwards. Two archives finishing at once would each carry a snapshot from a different instant, and swapping one in wholesale would let the slower answer resurrect what the faster one just filed away."),
|
|
542
|
+
rev: z
|
|
543
|
+
.number()
|
|
544
|
+
.describe("The version of the fleet that includes this move, so a caller can hold its own optimistic change until it sees a list at least that new."),
|
|
545
|
+
});
|
|
546
|
+
export const AgentsRemovedSchema = z.object({
|
|
547
|
+
removed: z
|
|
548
|
+
.array(z.string())
|
|
549
|
+
.describe("Which conversations were deleted, as ids. Ids rather than whole cards, because these no longer exist anywhere: there is nothing left to show and nothing to put back."),
|
|
550
|
+
});
|
|
551
|
+
export const AgentSearchQuerySchema = z.object({
|
|
552
|
+
query: z
|
|
553
|
+
.string()
|
|
554
|
+
.trim()
|
|
555
|
+
.min(2)
|
|
556
|
+
.describe("What to look for. Searched against what was said, both sides of the conversation, and nothing else: not the thinking, not the tool output, which between them name nearly every identifier in the workspace and would return most of the board."),
|
|
557
|
+
caseSensitive: z.stringbool().optional().describe("Whether capitals matter."),
|
|
558
|
+
});
|
|
315
559
|
export const SpeakerSchema = z.enum(["user", "agent"]);
|
|
316
|
-
export const MatchSnippetSchema = z.object({
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
export const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
560
|
+
export const MatchSnippetSchema = z.object({
|
|
561
|
+
text: z.string().describe("The matching line, with a little either side of it."),
|
|
562
|
+
speaker: SpeakerSchema.describe("Who said it. Carried with the words rather than beside them, because a line of the agent's prose under a card reads as something you typed until the row says otherwise."),
|
|
563
|
+
});
|
|
564
|
+
export const AgentMatchSchema = z.object({
|
|
565
|
+
id: z.string().describe("Which conversation matched."),
|
|
566
|
+
snippet: MatchSnippetSchema.optional().describe("Why, in its own words. Absent when the title was the match, which the card already shows: repeating it underneath is noise where evidence was wanted."),
|
|
567
|
+
});
|
|
568
|
+
export const AgentSearchResultSchema = z.object({
|
|
569
|
+
matches: z.array(AgentMatchSchema).describe("What matched, from the live fleet and the archive together."),
|
|
570
|
+
scanned: z
|
|
571
|
+
.number()
|
|
572
|
+
.describe("How many conversations were actually read, so a screen can say when a search saw less than everything rather than implying it saw all of it."),
|
|
573
|
+
indexing: z
|
|
574
|
+
.boolean()
|
|
575
|
+
.describe("Whether what was said is still being read in the background. True means this answer can still grow, so a screen must say it is incomplete rather than presenting it as the whole list."),
|
|
576
|
+
});
|
|
577
|
+
export const AgentRenameSchema = z.object({
|
|
578
|
+
id: z.string().min(1).describe("Which conversation."),
|
|
579
|
+
title: z.string().trim().min(1).max(80).describe("What to call it from now on."),
|
|
580
|
+
});
|
|
581
|
+
export const AgentPlaceSchema = z.object({
|
|
582
|
+
id: z.string().min(1).describe("Which conversation."),
|
|
583
|
+
text: z
|
|
584
|
+
.string()
|
|
585
|
+
.trim()
|
|
586
|
+
.min(1)
|
|
587
|
+
.max(8_000)
|
|
588
|
+
.describe("The words to put in the agent's mouth. Bounded just above what the next turn can carry whole, because a line too long to be handed over intact would reach the agent truncated and quietly break the very thing this is for."),
|
|
589
|
+
});
|
|
590
|
+
export const AgentAutoLandSchema = z.object({
|
|
591
|
+
id: z.string().min(1).describe("Which conversation."),
|
|
592
|
+
autoLand: z
|
|
593
|
+
.boolean()
|
|
594
|
+
.nullable()
|
|
595
|
+
.describe("Whether its work merges automatically when a turn finishes. Null clears the override and goes back to following the sandbox-wide setting, so a conversation does not sit holding a frozen copy of a default it has quietly stopped following."),
|
|
596
|
+
});
|
|
597
|
+
export const AgentResumeAfterOutageSchema = z.object({
|
|
598
|
+
id: z.string().min(1).describe("Which conversation."),
|
|
599
|
+
resumeAfterOutage: z
|
|
600
|
+
.boolean()
|
|
601
|
+
.nullable()
|
|
602
|
+
.describe("Whether it retries by itself when the model provider was what failed. Null clears the override back to the sandbox-wide setting."),
|
|
603
|
+
});
|
|
604
|
+
export const AgentFileDiffQuerySchema = z.object({
|
|
605
|
+
id: z.string().min(1).describe("Which conversation."),
|
|
606
|
+
repo: z.string().min(1).describe("Which repository."),
|
|
607
|
+
path: z.string().min(1).describe("Which file, relative to that repository."),
|
|
608
|
+
});
|
|
324
609
|
export const LandConflictReasonSchema = z.enum(["workspace", "diverged", "binary"]);
|
|
325
|
-
export const LandConflictPathSchema = z.object({
|
|
610
|
+
export const LandConflictPathSchema = z.object({
|
|
611
|
+
path: z.string().describe("Which file."),
|
|
612
|
+
reason: LandConflictReasonSchema.describe("Why it would not merge, and the three have nothing in common but the symptom. Your own uncommitted edits on that path, where yours is the copy at risk. The shared tree having moved under the conversation since it started, where nothing of yours is at risk. Or a file git cannot merge at all, where no automatic answer exists."),
|
|
613
|
+
});
|
|
326
614
|
export const LandConflictSchema = z.object({
|
|
327
|
-
repo: z.string(),
|
|
328
|
-
paths: z
|
|
329
|
-
|
|
330
|
-
|
|
615
|
+
repo: z.string().describe("Which repository."),
|
|
616
|
+
paths: z
|
|
617
|
+
.array(LandConflictPathSchema)
|
|
618
|
+
.describe("The files that genuinely would not apply. Not the whole change: reporting everything whenever the cause could not be pinned down turned four real conflicts into a wall of fourteen."),
|
|
619
|
+
clean: z
|
|
620
|
+
.number()
|
|
621
|
+
.describe("How many files would apply regardless, so a screen can say how much is being held back by how little and offer to take it. Zero alongside an empty list means the repository could not be reached at all."),
|
|
622
|
+
mainBranch: z
|
|
623
|
+
.string()
|
|
624
|
+
.optional()
|
|
625
|
+
.describe("The branch your own checkout is on, which is what the conversation has to rebase onto. Carried because only the sandbox can see it. Absent where there is no name to give."),
|
|
331
626
|
});
|
|
332
627
|
export const LandResultSchema = z.object({
|
|
333
|
-
landed: z.boolean(),
|
|
334
|
-
conflicts: z.array(LandConflictSchema).optional(),
|
|
335
|
-
resolving: z
|
|
336
|
-
|
|
628
|
+
landed: z.boolean().describe("Whether anything was applied."),
|
|
629
|
+
conflicts: z.array(LandConflictSchema).optional().describe("What stopped it, per repository."),
|
|
630
|
+
resolving: z
|
|
631
|
+
.array(z.object({
|
|
632
|
+
repo: z.string().describe("Which repository."),
|
|
633
|
+
paths: z.array(z.string()).describe("Which files now hold conflict markers to sort out by hand."),
|
|
634
|
+
}))
|
|
635
|
+
.optional()
|
|
636
|
+
.describe("Files left half-merged, when you asked for the mode that lands what it can and leaves the rest marked up."),
|
|
637
|
+
held: z
|
|
638
|
+
.boolean()
|
|
639
|
+
.optional()
|
|
640
|
+
.describe("Nothing was applied and nothing failed: there is work waiting on the branch for a deliberate merge. Not merged on its own cannot say that, because on its own it means refused."),
|
|
337
641
|
});
|
|
338
642
|
export const LandModeSchema = z.enum(["check", "merge", "measure"]);
|
|
339
643
|
export const AgentSpanSchema = z.enum(["cumulative", "outstanding"]);
|
|
340
644
|
export const AgentLandSchema = z.object({
|
|
341
|
-
id: z.string().min(1),
|
|
342
|
-
mode: LandModeSchema.optional(),
|
|
343
|
-
span: AgentSpanSchema.optional(),
|
|
344
|
-
force: z.boolean().optional(),
|
|
645
|
+
id: z.string().min(1).describe("Which conversation's work to merge."),
|
|
646
|
+
mode: LandModeSchema.optional().describe("How to apply it. The default applies all of it or none, so a refusal leaves the workspace exactly as it was. The other lands every clean file and leaves the rest with conflict markers to resolve by hand."),
|
|
647
|
+
span: AgentSpanSchema.optional().describe("How much of the work to take. Leave it out for everything not yet merged."),
|
|
648
|
+
force: z.boolean().optional().describe("Go ahead despite a check that would otherwise refuse."),
|
|
345
649
|
});
|
|
346
650
|
export const KeyedProviderSchema = z.enum(["codex", "grok", "kimi", "gemini"]);
|
|
347
651
|
export const UsageWindowSchema = z.object({
|
|
@@ -355,12 +659,18 @@ export const AccountUsageSchema = z.object({
|
|
|
355
659
|
measuredAt: z.number(),
|
|
356
660
|
});
|
|
357
661
|
export const ProviderRefusalSchema = z.object({
|
|
358
|
-
at: z.number(),
|
|
359
|
-
kind: z
|
|
360
|
-
|
|
361
|
-
|
|
662
|
+
at: z.number().describe("When it refused, in milliseconds."),
|
|
663
|
+
kind: z
|
|
664
|
+
.enum(["limit", "auth", "entitlement"])
|
|
665
|
+
.describe("Three different noes, kept apart because what fixes each is different. A spent allowance is answered by waiting; a refused credential by signing in again; and an entitlement refusal, where somebody has switched this off for your seat, by neither of those. That last one authenticates fine and reports healthy limits the whole time it refuses everything."),
|
|
666
|
+
message: z.string().describe("The provider's own words, verbatim. The only part that says which limit or which credential."),
|
|
667
|
+
account: z.string().optional().describe("Which account was serving, where that is known."),
|
|
668
|
+
});
|
|
669
|
+
export const ProviderRefusalsSchema = z.object({
|
|
670
|
+
refusals: z
|
|
671
|
+
.record(z.string(), ProviderRefusalSchema)
|
|
672
|
+
.describe("The most recent refusal per provider. Read alongside an account's usage: that says how full it was when last checked, this says whether it has since started saying no."),
|
|
362
673
|
});
|
|
363
|
-
export const ProviderRefusalsSchema = z.object({ refusals: z.record(z.string(), ProviderRefusalSchema) });
|
|
364
674
|
export const TranslatorAccountSchema = z.object({
|
|
365
675
|
name: z.string(),
|
|
366
676
|
label: z.string(),
|
|
@@ -374,62 +684,90 @@ export const TranslatorAccountsSchema = z.object({
|
|
|
374
684
|
});
|
|
375
685
|
export const AgentReplySchema = z.discriminatedUnion("kind", [
|
|
376
686
|
z.object({
|
|
377
|
-
kind: z.literal("plan"),
|
|
378
|
-
requestId: z.string().min(1),
|
|
379
|
-
approve: z
|
|
380
|
-
|
|
687
|
+
kind: z.literal("plan").describe("Answering a plan the agent proposed."),
|
|
688
|
+
requestId: z.string().min(1).describe("Which card you are answering, from the frame that raised it."),
|
|
689
|
+
approve: z
|
|
690
|
+
.boolean()
|
|
691
|
+
.describe("Whether to go ahead. Approving means the plan then runs without asking again per tool, because being asked whether a plan you just approved may run its first command is not a question worth having."),
|
|
692
|
+
feedback: z.string().optional().describe("Why not, which goes back to the model as the reason."),
|
|
381
693
|
}),
|
|
382
694
|
z.object({
|
|
383
|
-
kind: z.literal("question"),
|
|
384
|
-
requestId: z.string().min(1),
|
|
385
|
-
answers: z
|
|
386
|
-
|
|
695
|
+
kind: z.literal("question").describe("Answering a question the agent asked."),
|
|
696
|
+
requestId: z.string().min(1).describe("Which card you are answering."),
|
|
697
|
+
answers: z
|
|
698
|
+
.record(z.string(), z.array(z.string()))
|
|
699
|
+
.optional()
|
|
700
|
+
.describe("What you chose, keyed by the question, with the chosen labels or your own words."),
|
|
701
|
+
cancelled: z
|
|
702
|
+
.boolean()
|
|
703
|
+
.optional()
|
|
704
|
+
.describe("Dismissing it instead, which tells the agent to carry on using sensible defaults rather than leaving it waiting."),
|
|
387
705
|
}),
|
|
388
706
|
z.object({
|
|
389
|
-
kind: z.literal("permission"),
|
|
390
|
-
requestId: z.string().min(1),
|
|
391
|
-
decision: z
|
|
392
|
-
|
|
707
|
+
kind: z.literal("permission").describe("Answering a request to use a tool."),
|
|
708
|
+
requestId: z.string().min(1).describe("Which card you are answering."),
|
|
709
|
+
decision: z
|
|
710
|
+
.enum(["once", "always", "deny"])
|
|
711
|
+
.describe("Once allows this call alone; always allows that whole tool for the rest of the conversation; no blocks it."),
|
|
712
|
+
feedback: z.string().optional().describe("Why not, which goes back to the model as the reason."),
|
|
393
713
|
}),
|
|
394
714
|
z.object({
|
|
395
|
-
kind: z
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
715
|
+
kind: z
|
|
716
|
+
.literal("browser_help")
|
|
717
|
+
.describe("Answering a request for help in the agent's browser: a captcha, a password it does not hold, a check on your phone."),
|
|
718
|
+
requestId: z.string().min(1).describe("Which card you are answering."),
|
|
719
|
+
helped: z
|
|
720
|
+
.boolean()
|
|
721
|
+
.describe("Whether you cleared it. Yes means the turn carries on from the page as you left it; no tells the agent so, and it moves on rather than waiting for ever."),
|
|
722
|
+
note: z.string().optional().describe("Anything the agent should know, which goes back to it either way."),
|
|
399
723
|
}),
|
|
400
724
|
z.object({
|
|
401
|
-
kind: z
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
725
|
+
kind: z
|
|
726
|
+
.literal("terminal_help")
|
|
727
|
+
.describe("Answering a request for help at a terminal: a code to type, a confirmation only a person can give."),
|
|
728
|
+
requestId: z.string().min(1).describe("Which card you are answering."),
|
|
729
|
+
helped: z
|
|
730
|
+
.boolean()
|
|
731
|
+
.describe("Whether you did it. Yes also hands the agent what the terminal now says, because a person answering a prompt is exactly the moment the agent cannot see."),
|
|
732
|
+
note: z.string().optional().describe("Anything the agent should know, which goes back to it either way."),
|
|
405
733
|
}),
|
|
406
734
|
z.object({
|
|
407
|
-
kind: z.literal("service_offer"),
|
|
408
|
-
requestId: z.string().min(1),
|
|
409
|
-
approve: z
|
|
735
|
+
kind: z.literal("service_offer").describe("Answering a request to spend on a paid service."),
|
|
736
|
+
requestId: z.string().min(1).describe("Which card you are answering."),
|
|
737
|
+
approve: z
|
|
738
|
+
.boolean()
|
|
739
|
+
.describe("Yes releases exactly one run. Anything else charges nothing. This click is the only way the spend can happen."),
|
|
410
740
|
}),
|
|
411
741
|
z.object({
|
|
412
|
-
kind: z.literal("capability_offer"),
|
|
413
|
-
requestId: z.string().min(1),
|
|
414
|
-
connect: z
|
|
742
|
+
kind: z.literal("capability_offer").describe("Answering a request to connect something the agent needs."),
|
|
743
|
+
requestId: z.string().min(1).describe("Which card you are answering."),
|
|
744
|
+
connect: z
|
|
745
|
+
.boolean()
|
|
746
|
+
.describe("Yes keeps the agent waiting while you set it up, and it carries on the moment the connection comes alive. No tells it to continue without. The reply itself connects nothing: setting it up is still your own doing."),
|
|
415
747
|
}),
|
|
416
748
|
z.object({
|
|
417
|
-
kind: z.literal("payment_offer"),
|
|
418
|
-
requestId: z.string().min(1),
|
|
419
|
-
approve: z
|
|
749
|
+
kind: z.literal("payment_offer").describe("Answering a request to pay for something."),
|
|
750
|
+
requestId: z.string().min(1).describe("Which card you are answering."),
|
|
751
|
+
approve: z
|
|
752
|
+
.boolean()
|
|
753
|
+
.describe("Yes releases exactly one payment. Anything else spends nothing. This click is the only way the money can move."),
|
|
420
754
|
}),
|
|
421
755
|
]);
|
|
422
756
|
export const SteerSchema = z
|
|
423
757
|
.object({
|
|
424
|
-
conversationId: z.string().min(1),
|
|
425
|
-
text: z.string().max(20_000),
|
|
426
|
-
attachments: z
|
|
427
|
-
|
|
758
|
+
conversationId: z.string().min(1).describe("Which running conversation to interrupt."),
|
|
759
|
+
text: z.string().max(20_000).describe("What to say to it. It arrives mid-turn without stopping the turn."),
|
|
760
|
+
attachments: z
|
|
761
|
+
.array(z.string().min(1))
|
|
762
|
+
.max(20)
|
|
763
|
+
.optional()
|
|
764
|
+
.describe("Files to send with it, as workspace paths. A screenshot dropped in mid-turn with no words is a legitimate thing to send."),
|
|
765
|
+
editorContext: EditorContextSchema.optional().describe("What you have open, folded in so that pointing words resolve."),
|
|
428
766
|
})
|
|
429
767
|
.refine((steer) => steer.text.trim().length > 0 || (steer.attachments?.length ?? 0) > 0, {
|
|
430
768
|
message: "text or attachments required",
|
|
431
769
|
});
|
|
432
|
-
export const StopTurnSchema = z.object({ conversationId: z.string().min(1) });
|
|
770
|
+
export const StopTurnSchema = z.object({ conversationId: z.string().min(1).describe("Which conversation's running turn to cancel.") });
|
|
433
771
|
export const RateLimitInfoSchema = z.object({
|
|
434
772
|
status: z.enum(["allowed", "allowed_warning", "rejected"]),
|
|
435
773
|
resetsAt: z.number().optional(),
|
|
@@ -438,56 +776,91 @@ export const RateLimitInfoSchema = z.object({
|
|
|
438
776
|
});
|
|
439
777
|
export const FastModeStateSchema = z.enum(["off", "cooldown", "on"]);
|
|
440
778
|
export const OauthAccountSchema = z.object({
|
|
441
|
-
id: z.string(),
|
|
442
|
-
label: z.string(),
|
|
443
|
-
email: z
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
779
|
+
id: z.string().describe("The account's id, which is what a turn names to spend on it and what disconnecting takes."),
|
|
780
|
+
label: z.string().describe("What it is called here, which somebody can change."),
|
|
781
|
+
email: z
|
|
782
|
+
.string()
|
|
783
|
+
.optional()
|
|
784
|
+
.describe("Who it signs in as, in the provider's own words. Kept beside the label rather than folded into it, so a renamed account can still say whose it is. Absent when the provider says nothing, which is exactly when renaming is the only answer."),
|
|
785
|
+
organization: z.string().optional().describe("Which organisation it belongs to, where the provider says."),
|
|
786
|
+
scope: z.string().optional().describe("What the credential is permitted to do, in the provider's terms."),
|
|
787
|
+
connectedAt: z.number().describe("When it was connected, in milliseconds."),
|
|
788
|
+
needsReauth: z
|
|
789
|
+
.boolean()
|
|
790
|
+
.optional()
|
|
791
|
+
.describe("Its stored credential can no longer be renewed and somebody has to sign in again. Absent means healthy, or not checked yet."),
|
|
792
|
+
detail: z.string().optional().describe("Why, in words a person can act on."),
|
|
793
|
+
usage: AccountUsageSchema.optional().describe("How full its plan limits were when last measured, so a picker can show what is left before committing work to it. Absent until a reading exists, which reads as unknown rather than as nothing left."),
|
|
794
|
+
});
|
|
795
|
+
export const OauthAccountListSchema = z.object({
|
|
796
|
+
accounts: z
|
|
797
|
+
.array(OauthAccountSchema)
|
|
798
|
+
.describe("The connected accounts. Tokens never travel in this shape: being in this list is what connected means."),
|
|
799
|
+
});
|
|
800
|
+
export const AccountListQuerySchema = z.object({
|
|
801
|
+
force: z
|
|
802
|
+
.stringbool()
|
|
803
|
+
.default(false)
|
|
804
|
+
.describe("Measure the plan limits again before answering, rather than serving a recent reading. Slower, and the right thing when somebody has just changed a plan and is asking whether what they can see is still true."),
|
|
805
|
+
});
|
|
806
|
+
export const AccountIdSchema = z.object({ id: z.string().min(1).describe("Which account.") });
|
|
807
|
+
export const AccountRenameSchema = z.object({
|
|
808
|
+
id: z.string().min(1).describe("Which account."),
|
|
809
|
+
label: z.string().max(80).describe("The new name. Blank restores the one derived from the sign-in, rather than leaving a nameless row."),
|
|
450
810
|
});
|
|
451
|
-
export const OauthAccountListSchema = z.object({ accounts: z.array(OauthAccountSchema) });
|
|
452
|
-
export const AccountListQuerySchema = z.object({ force: z.stringbool().default(false) });
|
|
453
|
-
export const AccountIdSchema = z.object({ id: z.string().min(1) });
|
|
454
|
-
export const AccountRenameSchema = z.object({ id: z.string().min(1), label: z.string().max(80) });
|
|
455
811
|
export const OauthExchangeSchema = z.object({
|
|
456
|
-
code: z.string().min(1),
|
|
457
|
-
verifier: z.string().min(1),
|
|
458
|
-
state: z.string().min(1),
|
|
459
|
-
label: z.string().optional(),
|
|
812
|
+
code: z.string().min(1).describe("The code the sign-in handed back."),
|
|
813
|
+
verifier: z.string().min(1).describe("The proof from the start of the handshake, which is what stops somebody else's code being redeemed here."),
|
|
814
|
+
state: z.string().min(1).describe("The handshake this belongs to. A mismatch is refused."),
|
|
815
|
+
label: z.string().optional().describe("What to call the account. Blank derives one from the sign-in."),
|
|
816
|
+
});
|
|
817
|
+
export const AuthorizeChallengeSchema = z.object({
|
|
818
|
+
authorizeUrl: z.string().describe("Where to send somebody to sign in."),
|
|
819
|
+
verifier: z.string().describe("Keep this and send it back when finishing. It is what proves the code that comes back belongs to this handshake."),
|
|
820
|
+
state: z.string().describe("The handshake's own id, sent back with it."),
|
|
821
|
+
});
|
|
822
|
+
export const DeviceStartSchema = z.object({
|
|
823
|
+
url: z.string().describe("The page to open, which already has the code in it."),
|
|
824
|
+
code: z
|
|
825
|
+
.string()
|
|
826
|
+
.describe("The one-time code, shown as well so the page and the card say the same thing. Nothing is pasted back: the sandbox waits for the sign-in to complete on its own."),
|
|
460
827
|
});
|
|
461
|
-
export const AuthorizeChallengeSchema = z.object({ authorizeUrl: z.string(), verifier: z.string(), state: z.string() });
|
|
462
|
-
export const DeviceStartSchema = z.object({ url: z.string(), code: z.string() });
|
|
463
828
|
export const TranslatorStartSchema = z.object({
|
|
464
|
-
url: z.string(),
|
|
465
|
-
code: z.string(),
|
|
466
|
-
state: z.string(),
|
|
467
|
-
flow: z
|
|
829
|
+
url: z.string().describe("The page to open."),
|
|
830
|
+
code: z.string().describe("The one-time code, where the provider uses one."),
|
|
831
|
+
state: z.string().describe("The handshake's id, which the finishing call sends back."),
|
|
832
|
+
flow: z
|
|
833
|
+
.enum(["device", "redirect"])
|
|
834
|
+
.describe("Which shape this is. A device sign-in finishes by itself and you poll the account list; a redirect needs the address it landed on handed back. Said outright rather than guessed at from whether a code happens to exist."),
|
|
468
835
|
});
|
|
469
836
|
export const TranslatorCompleteSchema = z.object({
|
|
470
|
-
provider: KeyedProviderSchema,
|
|
471
|
-
redirectUrl: z.string().min(1),
|
|
472
|
-
state: z.string().min(1),
|
|
837
|
+
provider: KeyedProviderSchema.describe("Which provider."),
|
|
838
|
+
redirectUrl: z.string().min(1).describe("The address the browser was sent to, whole. The grant is inside it."),
|
|
839
|
+
state: z.string().min(1).describe("The handshake this belongs to. A mismatch is refused."),
|
|
473
840
|
});
|
|
474
841
|
export const ModelBadgeSchema = z.enum(["reasoning", "fast"]);
|
|
475
842
|
export const ModelSchema = z.object({
|
|
476
|
-
id: z.string(),
|
|
477
|
-
label: z.string(),
|
|
478
|
-
efforts: z.array(z.string()).optional(),
|
|
479
|
-
description: z
|
|
480
|
-
|
|
843
|
+
id: z.string().describe("What to name when asking for this model."),
|
|
844
|
+
label: z.string().describe("What to call it on screen."),
|
|
845
|
+
efforts: z.array(z.string()).optional().describe("The thinking levels it accepts, where the provider says. Empty means use your own defaults."),
|
|
846
|
+
description: z
|
|
847
|
+
.string()
|
|
848
|
+
.optional()
|
|
849
|
+
.describe("What it is good for, in the provider's own words. Absent where the provider publishes only ids, which is the honest answer rather than something to paper over with a hand-written table."),
|
|
850
|
+
badges: z.array(ModelBadgeSchema).optional().describe("What it is known for, where the provider says so."),
|
|
851
|
+
});
|
|
852
|
+
export const ModelsSchema = z.object({
|
|
853
|
+
models: z.array(ModelSchema).describe("What this provider serves, in its own preference order, which is not rearranged here. Never empty."),
|
|
854
|
+
default: z.string().describe("Which one a fresh conversation starts on. Always present."),
|
|
481
855
|
});
|
|
482
|
-
export const
|
|
483
|
-
export const SessionIdParamSchema = z.object({ id: z.string() });
|
|
856
|
+
export const SessionIdParamSchema = z.object({ id: z.string().describe("Which past conversation.") });
|
|
484
857
|
export const SessionSummarySchema = z.object({
|
|
485
|
-
id: z.string(),
|
|
486
|
-
title: z.string(),
|
|
487
|
-
updatedAt: z.number(),
|
|
488
|
-
snippet: MatchSnippetSchema.optional(),
|
|
858
|
+
id: z.string().describe("Its id."),
|
|
859
|
+
title: z.string().describe("What it is called."),
|
|
860
|
+
updatedAt: z.number().describe("When it last moved, in milliseconds."),
|
|
861
|
+
snippet: MatchSnippetSchema.optional().describe("Why a search matched: the line it hit, with a little around it, and who said it. Absent on an unfiltered list, and on a match the title already shows, where repeating it would be noise rather than evidence."),
|
|
489
862
|
});
|
|
490
|
-
export const SessionsListSchema = z.object({ sessions: z.array(SessionSummarySchema) });
|
|
863
|
+
export const SessionsListSchema = z.object({ sessions: z.array(SessionSummarySchema).describe("Past conversations, newest first.") });
|
|
491
864
|
export const SystemPromptModeSchema = z.enum(["intentic", "claude", "custom"]);
|
|
492
865
|
export const BuiltinPromptSchema = z.object({ base: z.enum(["intentic", "claude"]) });
|
|
493
866
|
export const RuleMomentSchema = z.enum([
|
|
@@ -533,59 +906,158 @@ export const RuleFiringsSchema = z.record(z.string(), z.number());
|
|
|
533
906
|
export const SkillOriginSchema = z.enum(["builtin", "own", "capability", "extension", "plugin", "persona", "dropped"]);
|
|
534
907
|
export const SkillNameSchema = z.string().regex(/^[a-z0-9][a-z0-9-]*$/, "a skill name is lowercase letters, digits and dashes");
|
|
535
908
|
export const SkillSummarySchema = z.object({
|
|
536
|
-
id: z
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
909
|
+
id: z
|
|
910
|
+
.string()
|
|
911
|
+
.describe("Its handle, which reading and deleting take. A skill of your own is simply its name; one belonging to something else is qualified, because two packages may each ship a review."),
|
|
912
|
+
name: z.string().describe("Its name."),
|
|
913
|
+
description: z
|
|
914
|
+
.string()
|
|
915
|
+
.describe("What it is for, which is the line the agent reads to decide whether to reach for it. Empty when the skill declares none, which is worth showing as the blank it is: a skill with no description is rarely picked."),
|
|
916
|
+
origin: SkillOriginSchema.describe("Where it came from."),
|
|
917
|
+
owner: z.string().optional().describe("Who ships it, as the row would name them."),
|
|
918
|
+
enabled: z.boolean().describe("Whether the agent can reach it."),
|
|
919
|
+
switchable: z
|
|
920
|
+
.boolean()
|
|
921
|
+
.describe("Whether this surface can switch it. Everything else is on because its extension or its plugin is, and a switch here that silently did nothing would be worse than none, so the row names its owner instead."),
|
|
922
|
+
editable: z
|
|
923
|
+
.boolean()
|
|
924
|
+
.describe("Whether it can be rewritten here. Your own only: editing somebody else's in place would be undone the next time the thing that ships it catches up."),
|
|
544
925
|
removable: z.boolean(),
|
|
545
926
|
});
|
|
546
927
|
export const SkillsListSchema = z.array(SkillSummarySchema);
|
|
547
928
|
export const SkillBodySchema = z.object({
|
|
548
|
-
id: z.string(),
|
|
549
|
-
name: z.string(),
|
|
550
|
-
body: z.string(),
|
|
929
|
+
id: z.string().describe("The skill's id, which can carry the owner it came from."),
|
|
930
|
+
name: z.string().describe("Its name."),
|
|
931
|
+
body: z.string().describe("The instructions themselves, as written."),
|
|
932
|
+
});
|
|
933
|
+
export const SkillIdSchema = z.object({
|
|
934
|
+
id: z
|
|
935
|
+
.string()
|
|
936
|
+
.min(1)
|
|
937
|
+
.describe("Which skill. It travels in the query rather than the address, because an id can name the owner it came from and that will not fit in a path."),
|
|
551
938
|
});
|
|
552
|
-
export const SkillIdSchema = z.object({ id: z.string().min(1) });
|
|
553
939
|
export const SkillDraftSchema = z.object({
|
|
554
|
-
name: SkillNameSchema,
|
|
555
|
-
description: z.string().min(1).max(1024),
|
|
556
|
-
body: z.string().min(1),
|
|
940
|
+
name: SkillNameSchema.describe("What to call it. Saving over an existing name rewrites it, which is also how one is renamed."),
|
|
941
|
+
description: z.string().min(1).max(1024).describe("What it is for, which is what the agent reads to decide whether to reach for it."),
|
|
942
|
+
body: z.string().min(1).describe("The skill itself."),
|
|
943
|
+
});
|
|
944
|
+
export const SkillRemoveSchema = z.object({
|
|
945
|
+
name: SkillNameSchema.describe("Which skill to delete. The text and the enabled list are both updated, so nothing is left half done."),
|
|
557
946
|
});
|
|
558
|
-
export const SkillRemoveSchema = z.object({ name: SkillNameSchema });
|
|
559
947
|
export const SandboxSettingsSchema = z.object({
|
|
560
|
-
stableSystemPrompt: z
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
948
|
+
stableSystemPrompt: z
|
|
949
|
+
.boolean()
|
|
950
|
+
.default(false)
|
|
951
|
+
.describe("Keep the instructions identical between turns so the provider can cache them, moving anything that varies into the message instead. Cheaper, at the cost of some flexibility."),
|
|
952
|
+
skills: z.array(z.string()).default(["lsp"]).describe("Which skills are switched on."),
|
|
953
|
+
hashlineEdits: z
|
|
954
|
+
.boolean()
|
|
955
|
+
.default(false)
|
|
956
|
+
.describe("Have the agent edit files by line number rather than by quoting the text it wants replaced. Cheaper on large files, and less forgiving of a stale read."),
|
|
957
|
+
terseOutput: z.boolean().default(false).describe("Ask the agent to say less. It changes how much it narrates, not how much it does."),
|
|
958
|
+
terseHoldout: z
|
|
959
|
+
.number()
|
|
960
|
+
.min(0)
|
|
961
|
+
.max(1)
|
|
962
|
+
.default(0)
|
|
963
|
+
.describe("What share of turns to run without that instruction, so the two can be compared honestly. It has to be measured this way, because a turn cannot be re-run to see what it would have said. Zero means no measurement, which is the default, since the comparison costs the very tokens it is measuring."),
|
|
964
|
+
systemPromptMode: SystemPromptModeSchema.default("intentic").describe("Which instructions the agent starts from: intentic's own, the ones the installed Claude Code carries, or your own. The first two both get this product's own guidance added on top; your own gets nothing added, which is the point of it."),
|
|
965
|
+
systemPrompt: z
|
|
966
|
+
.string()
|
|
967
|
+
.max(20000)
|
|
968
|
+
.default("")
|
|
969
|
+
.describe("Your own instructions, used only when the mode above says custom. Then it is the whole of them: both built-in bases go, and so does everything this product would otherwise add, including the guidance the chat's own cards are driven by. That is the price of total control."),
|
|
970
|
+
iqSearch: z
|
|
971
|
+
.boolean()
|
|
972
|
+
.default(false)
|
|
973
|
+
.describe("Teach the agent how to use this workspace's own search tool, rather than leaving it to grep around."),
|
|
974
|
+
iqSearchHoldout: z
|
|
975
|
+
.number()
|
|
976
|
+
.min(0)
|
|
977
|
+
.max(1)
|
|
978
|
+
.default(0)
|
|
979
|
+
.describe("What share of conversations to run without that teaching, so the two can be compared. Whole conversations rather than individual turns, because once the teaching is in a session, withholding it from the next request does not make the model forget it."),
|
|
980
|
+
workspaceMap: z
|
|
981
|
+
.boolean()
|
|
982
|
+
.default(false)
|
|
983
|
+
.describe("Open every conversation with a map of the project it starts in: what is in it, what each part is for, and where the agent is standing. Worked out fresh each time rather than written down anywhere, because a written layout is wrong within a fortnight. Off by default, since it spends tokens on the first message of every conversation."),
|
|
984
|
+
outputCleaners: z
|
|
985
|
+
.string()
|
|
986
|
+
.default("off")
|
|
987
|
+
.describe("Which command outputs to trim before the agent reads them, cutting the noise a build tool prints without cutting what it said."),
|
|
988
|
+
outputHoldout: z
|
|
989
|
+
.number()
|
|
990
|
+
.min(0)
|
|
991
|
+
.max(1)
|
|
992
|
+
.default(0)
|
|
993
|
+
.describe("What share of commands to leave untrimmed, so the saving can be measured against a real comparison rather than estimated."),
|
|
994
|
+
quickModel: z
|
|
995
|
+
.array(z.string())
|
|
996
|
+
.max(10)
|
|
997
|
+
.default([])
|
|
998
|
+
.describe("Which models do the small automatic jobs that are not a conversation, such as writing a commit message. A list rather than one pick, tried in order, because the interesting failure is a model that is connected and simply will not answer today. Empty means work it out from whatever is connected, which improves by itself as accounts are added."),
|
|
999
|
+
changelogRepos: z
|
|
1000
|
+
.array(z.string())
|
|
1001
|
+
.max(50)
|
|
1002
|
+
.default([])
|
|
1003
|
+
.describe("Which repositories keep a changelog, and so get a user-facing note written alongside each merge. A list rather than a switch, and empty by default, because the commit writer's standing rule is to copy the house style rather than impose one, and a repository that has never written such a note gives it nothing to copy."),
|
|
1004
|
+
agentRunModels: z
|
|
1005
|
+
.array(z.string())
|
|
1006
|
+
.max(10)
|
|
1007
|
+
.default([])
|
|
1008
|
+
.describe("Which models run the work a screen starts rather than a person: fixing a red pipeline, a maintenance chore, an acceptance run. Tried in order, so one spent account does not take every such run down. Empty falls back to whatever the chat would have used, which is the honest floor because it is the model you already chose to work with."),
|
|
1009
|
+
agentRunEffort: z.string().default("").describe("How hard those runs should think."),
|
|
1010
|
+
autoTier: z
|
|
1011
|
+
.enum(["off", "shadow", "on"])
|
|
1012
|
+
.default("shadow")
|
|
1013
|
+
.describe("Whether an easy-looking turn may run on a cheaper model from the same provider. Three states rather than a switch, because the middle one is the only honest road to the third: it scores every turn and routes nothing, so the guess can become a measurement before it changes anything. It can only ever route down, so the worst case is one turn's quality rather than a bill nobody asked for."),
|
|
1014
|
+
autoFastModels: z
|
|
1015
|
+
.array(z.string())
|
|
1016
|
+
.max(10)
|
|
1017
|
+
.default([])
|
|
1018
|
+
.describe("Which cheaper model a downgraded turn lands on. A list so a sandbox spanning providers can name a rung on each, but not a fallback ladder: an entry naming a different provider than the turn is on is skipped rather than tried, because switching provider retires the conversation and starting over to save a fraction of a penny is not a saving. Empty picks the cheapest the turn's own provider publishes."),
|
|
1019
|
+
agentRetentionDays: z
|
|
1020
|
+
.number()
|
|
1021
|
+
.min(0)
|
|
1022
|
+
.max(365)
|
|
1023
|
+
.default(3)
|
|
1024
|
+
.describe("How many days a finished conversation stays on the board before being put away. Zero means never. The one setting here that defaults on, because each card left behind is a real working copy on disk, not just a row."),
|
|
1025
|
+
resumeAfterOutage: z
|
|
1026
|
+
.boolean()
|
|
1027
|
+
.default(false)
|
|
1028
|
+
.describe("Whether a turn killed by the model provider failing is re-run automatically, backing off between attempts. The sandbox-wide default; any one conversation can say otherwise. Off to begin with, because a retry spends your allowance on a turn you sent once and only you can say whether it was worth paying for twice. Worth turning on for a sandbox whose work mostly happens with nobody in the room."),
|
|
1029
|
+
autoResumeOnRestart: z
|
|
1030
|
+
.boolean()
|
|
1031
|
+
.default(false)
|
|
1032
|
+
.describe("Whether a turn killed by the sandbox restarting is re-run once it comes back. Off to begin with, for the same reason: it would spend your allowance on work you are not watching and edit files while you are still waiting for the sandbox to return. Either way the interruption is recorded rather than silently lost."),
|
|
1033
|
+
rules: z
|
|
1034
|
+
.array(RuleSchema)
|
|
1035
|
+
.max(50)
|
|
1036
|
+
.default([])
|
|
1037
|
+
.describe("Standing instructions you give the sandbox about its own work: ask for proof before a turn ends, run something before a push, hold or release finished work. Empty is the default and is exactly the behaviour of a fresh sandbox, because each of those defaults is what no rule matched means at its own moment."),
|
|
1038
|
+
automationFailureLimit: z
|
|
1039
|
+
.number()
|
|
1040
|
+
.min(0)
|
|
1041
|
+
.max(20)
|
|
1042
|
+
.default(0)
|
|
1043
|
+
.describe("How many failures in a row before an automation switches itself off. Zero means never, which is the default, because the failure is not always the automation's fault and a job disabled at three in the morning is one nobody re-enables. Only real errors count: a guard deciding there was nothing to do, or the sandbox dying mid-run, say nothing about the automation."),
|
|
1044
|
+
admission: AdmissionPolicySchema.prefault({}).describe("Whether work started from outside may run, per kind of trigger: let it, hold it for approval, or refuse it. Composes with each automation's own setting, and the stricter of the two wins, so holding every visitor's message needs no edit to each automation."),
|
|
1045
|
+
actionRules: z
|
|
1046
|
+
.record(z.string(), AdmissionRuleSchema)
|
|
1047
|
+
.default({})
|
|
1048
|
+
.describe("What an agent may do out in the world, per kind of action: go ahead, ask first, or never."),
|
|
1049
|
+
commandRules: z
|
|
1050
|
+
.partialRecord(CommandClassSchema, AdmissionRuleSchema)
|
|
1051
|
+
.default({})
|
|
1052
|
+
.describe("What an agent may run inside the sandbox, for the five kinds of command that are hard to take back: rewriting git history, deleting recursively, reading credential files, publishing a package, reaching out to the network. Everything else is recoverable in a container that is itself disposable, and gating it would be friction bought with nothing."),
|
|
1053
|
+
subagentsAtOnce: z.number().min(1).max(200).default(20).describe("How many helper agents may work at the same time."),
|
|
1054
|
+
subagentsPerTurn: z.number().min(1).max(2000).default(200).describe("How many a single turn may start in total."),
|
|
1055
|
+
subagentDepth: z
|
|
1056
|
+
.number()
|
|
1057
|
+
.min(1)
|
|
1058
|
+
.max(10)
|
|
1059
|
+
.default(3)
|
|
1060
|
+
.describe("How many levels deep the delegation may go, since a helper can start helpers of its own."),
|
|
589
1061
|
});
|
|
590
1062
|
export const BuiltinPromptTextSchema = z.object({ text: z.string(), version: z.string() });
|
|
591
1063
|
export const SavingsStageSchema = z.object({ id: z.string(), commands: z.number(), savedTokens: z.number() });
|
|
@@ -622,314 +1094,603 @@ export const SavingsReportSchema = z.object({
|
|
|
622
1094
|
});
|
|
623
1095
|
export const IntenticRunSchema = z.object({ args: z.array(z.string()) });
|
|
624
1096
|
export const CommitSchema = RepoParamSchema.extend({
|
|
625
|
-
message: z.string().min(1),
|
|
626
|
-
all: z
|
|
627
|
-
|
|
1097
|
+
message: z.string().min(1).describe("The commit message."),
|
|
1098
|
+
all: z
|
|
1099
|
+
.boolean()
|
|
1100
|
+
.optional()
|
|
1101
|
+
.describe("Stage every change in the repository first, then commit. An alternative to naming paths, not a companion to it."),
|
|
1102
|
+
paths: z
|
|
1103
|
+
.array(z.string().min(1))
|
|
1104
|
+
.max(500)
|
|
1105
|
+
.optional()
|
|
1106
|
+
.describe("Stage exactly these paths, then commit everything staged. Leave this and `all` out to commit whatever is already staged."),
|
|
628
1107
|
});
|
|
629
1108
|
export const DiscardSchema = RepoParamSchema.extend({
|
|
630
|
-
paths: z
|
|
1109
|
+
paths: z
|
|
1110
|
+
.array(z.string().min(1))
|
|
1111
|
+
.max(500)
|
|
1112
|
+
.optional()
|
|
1113
|
+
.describe("Which paths to throw away. Leave it out to discard every uncommitted change in the repository."),
|
|
1114
|
+
});
|
|
1115
|
+
export const GitStageSchema = RepoParamSchema.extend({
|
|
1116
|
+
paths: z.array(z.string().min(1)).max(500).describe("The paths to move. Nothing on disk changes, so this is always safe and always reversible."),
|
|
1117
|
+
});
|
|
1118
|
+
export const PushSchema = RepoParamSchema.extend({
|
|
1119
|
+
branch: z
|
|
1120
|
+
.string()
|
|
1121
|
+
.min(1)
|
|
1122
|
+
.optional()
|
|
1123
|
+
.describe("Which branch to push. Leave it out for the checked-out one. A branch with no upstream yet gets one set on this push."),
|
|
1124
|
+
});
|
|
1125
|
+
export const GitFileQuerySchema = RepoParamSchema.extend({ path: z.string().min(1).describe("The file to read, relative to the repository root.") });
|
|
1126
|
+
export const GitFileWriteSchema = RepoParamSchema.extend({
|
|
1127
|
+
path: z.string().min(1).describe("Where to write, relative to the repository root. Missing folders are created."),
|
|
1128
|
+
content: z.string().describe("The file's whole new contents."),
|
|
631
1129
|
});
|
|
632
|
-
export const GitStageSchema = RepoParamSchema.extend({ paths: z.array(z.string().min(1)).max(500) });
|
|
633
|
-
export const PushSchema = RepoParamSchema.extend({ branch: z.string().min(1).optional() });
|
|
634
|
-
export const GitFileQuerySchema = RepoParamSchema.extend({ path: z.string().min(1) });
|
|
635
|
-
export const GitFileWriteSchema = RepoParamSchema.extend({ path: z.string().min(1), content: z.string() });
|
|
636
1130
|
export const GitDiffSideSchema = z.enum(["staged", "unstaged", "conflicted"]);
|
|
637
|
-
export const GitFileDiffQuerySchema = RepoParamSchema.extend({
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
export const
|
|
1131
|
+
export const GitFileDiffQuerySchema = RepoParamSchema.extend({
|
|
1132
|
+
path: z.string().min(1).describe("The file, relative to the repository root."),
|
|
1133
|
+
side: GitDiffSideSchema.describe("Which comparison you want. A file that is staged and then edited again has genuinely different answers for each, which is why this is required rather than assumed."),
|
|
1134
|
+
});
|
|
1135
|
+
export const GitStatusSchema = z.object({
|
|
1136
|
+
branch: z.string().describe("The checked-out branch."),
|
|
1137
|
+
dirty: z.boolean().describe("Whether anything is uncommitted."),
|
|
1138
|
+
files: z.array(z.string()).describe("Every path with something pending, staged or not."),
|
|
1139
|
+
});
|
|
1140
|
+
export const GitFilesSchema = z.object({
|
|
1141
|
+
files: z.array(z.string()).describe("Every path git tracks, relative to the repository root. Ignored and untracked files are not here."),
|
|
1142
|
+
});
|
|
1143
|
+
export const GitFileSchema = z.object({
|
|
1144
|
+
path: z.string().describe("The path, as asked for."),
|
|
1145
|
+
content: z.string().describe("The file's contents as they stand on disk."),
|
|
1146
|
+
});
|
|
1147
|
+
export const RepoPathsSchema = z.object({
|
|
1148
|
+
repo: z.string().min(1).describe("Which repository."),
|
|
1149
|
+
paths: z.array(z.string().min(1)).max(500).optional().describe("Which of its paths. Leave it out for the whole repository."),
|
|
1150
|
+
});
|
|
642
1151
|
export const GitChangeSchema = z.object({
|
|
643
|
-
path: z.string(),
|
|
644
|
-
status: z
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
1152
|
+
path: z.string().describe("The path, relative to the repository root. For a rename this is the new one."),
|
|
1153
|
+
status: z
|
|
1154
|
+
.enum(["added", "modified", "deleted", "renamed", "type-changed", "conflicted"])
|
|
1155
|
+
.describe("What happened to it. Conflicted is not a kind of edit: nothing can be committed anywhere in the repository while one exists."),
|
|
1156
|
+
from: z.string().optional().describe("Where a renamed file came from."),
|
|
1157
|
+
additions: z
|
|
1158
|
+
.number()
|
|
1159
|
+
.optional()
|
|
1160
|
+
.describe("Lines added. Absent for a binary file, and for an untracked one, which has nothing to compare against."),
|
|
1161
|
+
deletions: z.number().optional().describe("Lines removed. Absent for the same reasons additions is."),
|
|
648
1162
|
});
|
|
649
1163
|
export const GitRemoteStateSchema = z.object({
|
|
650
|
-
remote: z
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
1164
|
+
remote: z
|
|
1165
|
+
.string()
|
|
1166
|
+
.optional()
|
|
1167
|
+
.describe("The remote this branch pushes to. Absent means none is configured. In a fork with two remotes, pushing to the wrong one succeeds and leaves the count stuck, which is why this says which."),
|
|
1168
|
+
branch: z.string().optional().describe("The checked-out branch. Absent when the repository is on a bare commit, or has no commits yet."),
|
|
1169
|
+
upstream: z.string().optional().describe("The branch on the remote this one follows. Absent means the next push will publish it."),
|
|
1170
|
+
ahead: z.number().describe("Commits you have that the remote does not."),
|
|
1171
|
+
behind: z.number().describe("Commits the remote has that you do not, as of the last fetch. Fetch before trusting it."),
|
|
655
1172
|
});
|
|
656
1173
|
const RefNameSchema = z
|
|
657
1174
|
.string()
|
|
658
1175
|
.regex(/^[A-Za-z0-9][A-Za-z0-9._/-]*$/)
|
|
659
1176
|
.max(200);
|
|
660
1177
|
export const GitBranchSchema = z.object({
|
|
661
|
-
name: z.string(),
|
|
662
|
-
current: z.boolean(),
|
|
663
|
-
upstream: z.string().optional(),
|
|
664
|
-
ahead: z.number(),
|
|
665
|
-
behind: z.number(),
|
|
666
|
-
gone: z
|
|
667
|
-
|
|
1178
|
+
name: z.string().describe("The branch name."),
|
|
1179
|
+
current: z.boolean().describe("Whether this is the one checked out."),
|
|
1180
|
+
upstream: z.string().optional().describe("The branch on the remote it follows, if any."),
|
|
1181
|
+
ahead: z.number().describe("Commits this branch has that its remote counterpart does not."),
|
|
1182
|
+
behind: z.number().describe("Commits its remote counterpart has that it does not."),
|
|
1183
|
+
gone: z
|
|
1184
|
+
.boolean()
|
|
1185
|
+
.optional()
|
|
1186
|
+
.describe("The branch it followed no longer exists on the remote, usually because a merged pull request deleted it. The signal that this one is safe to delete."),
|
|
1187
|
+
at: z.number().describe("When its tip was committed, in milliseconds. Lists are newest first."),
|
|
1188
|
+
});
|
|
1189
|
+
export const GitRemoteBranchSchema = z.object({
|
|
1190
|
+
name: z.string().describe("The full name, such as origin/main."),
|
|
1191
|
+
remote: z.string().describe("Just the remote part, so a picker can group by it without re-parsing."),
|
|
1192
|
+
branch: z.string().describe("Just the branch part."),
|
|
1193
|
+
at: z.number().describe("When its tip was committed, in milliseconds, as this repository last saw it."),
|
|
1194
|
+
});
|
|
1195
|
+
export const GitBranchesSchema = z.object({
|
|
1196
|
+
branches: z.array(GitBranchSchema).describe("Branches in this repository."),
|
|
1197
|
+
remotes: z
|
|
1198
|
+
.array(GitRemoteBranchSchema)
|
|
1199
|
+
.describe("Branches on its remotes, as last seen. Sent together with the locals so a switcher never draws a half-filled list."),
|
|
668
1200
|
});
|
|
669
|
-
export const GitRemoteBranchSchema = z.object({ name: z.string(), remote: z.string(), branch: z.string(), at: z.number() });
|
|
670
|
-
export const GitBranchesSchema = z.object({ branches: z.array(GitBranchSchema), remotes: z.array(GitRemoteBranchSchema) });
|
|
671
1201
|
export const GitBranchCreateAtSchema = RepoParamSchema.extend({
|
|
672
|
-
name: RefNameSchema,
|
|
673
|
-
start: z.string().min(1).optional(),
|
|
674
|
-
checkout: z.boolean().optional(),
|
|
1202
|
+
name: RefNameSchema.describe("The new branch's name."),
|
|
1203
|
+
start: z.string().min(1).optional().describe("Where to start it: a commit or another branch. Leave it out to start from where you are."),
|
|
1204
|
+
checkout: z.boolean().optional().describe("Switch to it as well as creating it."),
|
|
1205
|
+
});
|
|
1206
|
+
export const GitBranchDeleteSchema = RepoParamSchema.extend({
|
|
1207
|
+
name: RefNameSchema.describe("The branch to delete."),
|
|
1208
|
+
force: z
|
|
1209
|
+
.boolean()
|
|
1210
|
+
.optional()
|
|
1211
|
+
.describe("Delete it even though it holds work that was never merged. The deliberate retry after the first attempt refuses."),
|
|
675
1212
|
});
|
|
676
|
-
export const GitBranchDeleteSchema = RepoParamSchema.extend({ name: RefNameSchema, force: z.boolean().optional() });
|
|
677
1213
|
export const GitOperationSchema = z.enum(["merge", "rebase", "cherry-pick", "revert"]);
|
|
678
|
-
export const GitOperationStateSchema = z.object({
|
|
1214
|
+
export const GitOperationStateSchema = z.object({
|
|
1215
|
+
repo: z.string().describe("The repository asked about."),
|
|
1216
|
+
operation: GitOperationSchema.optional().describe("Which operation the working tree is stuck inside. Absent means it is not stuck at all, which is almost always. While one is present git refuses nearly everything else, and abandoning it is the only way out."),
|
|
1217
|
+
});
|
|
679
1218
|
export const RepoChangesSchema = z.object({
|
|
680
1219
|
repo: z.string(),
|
|
681
|
-
branch: z.string().optional(),
|
|
682
|
-
conflicted: z
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
1220
|
+
branch: z.string().optional().describe("The checked-out branch. Absent in a repository that has no commits yet."),
|
|
1221
|
+
conflicted: z
|
|
1222
|
+
.array(GitChangeSchema)
|
|
1223
|
+
.describe("Paths a merge or rebase could not finish. First, because nothing anywhere in this repository can be committed until they are resolved. Held apart from the two lists below, because staged or not is not a question one of these has an answer to."),
|
|
1224
|
+
operation: GitOperationSchema.optional().describe("What halted, when something did. This is the sentence that explains the conflicts above and names the way out of them."),
|
|
1225
|
+
staged: z.array(GitChangeSchema).describe("What a plain commit would record right now."),
|
|
1226
|
+
unstaged: z
|
|
1227
|
+
.array(GitChangeSchema)
|
|
1228
|
+
.describe("Edits on disk that are not staged, plus untracked files. A path can be in both lists at once with different line counts, which is why they are separate."),
|
|
1229
|
+
truncated: z
|
|
1230
|
+
.number()
|
|
1231
|
+
.optional()
|
|
1232
|
+
.describe("How many changes were cut from the two lists above. A freshly cloned monorepo or a mass delete runs to six figures, which no screen can draw, so past a budget the lists arrive short and this says by how much. Absent means they are complete."),
|
|
1233
|
+
remote: GitRemoteStateSchema.optional().describe("Where this repository stands against its remote."),
|
|
1234
|
+
origins: z
|
|
1235
|
+
.record(z.string(), z.array(z.string()))
|
|
1236
|
+
.optional()
|
|
1237
|
+
.describe("Which conversation put each path here, newest first, keyed by path. Only work that went through a merge can appear: edits made in the shared tree, in a terminal, or by a person are simply absent rather than guessed at."),
|
|
1238
|
+
error: z
|
|
1239
|
+
.string()
|
|
1240
|
+
.optional()
|
|
1241
|
+
.describe("Why the repository could not be read at all, in git's own words. A repository left broken by a failed import arrives with empty lists and this set, rather than vanishing from the answer with nothing to act on."),
|
|
690
1242
|
});
|
|
691
1243
|
export const OriginAgentSchema = z.object({
|
|
692
|
-
title: z.string().optional(),
|
|
693
|
-
provider: AgentProviderSchema,
|
|
694
|
-
landedMessage: LandedMessageSchema.optional(),
|
|
1244
|
+
title: z.string().optional().describe("The conversation's title. Absent for one that never got as far as having a title."),
|
|
1245
|
+
provider: AgentProviderSchema.describe("Which model provider it ran on."),
|
|
1246
|
+
landedMessage: LandedMessageSchema.optional().describe("What the merged work did, drafted by the conversation itself. Carried here as well as on its card, because merged lines outlive the card: archiving a finished conversation does not uncommit its work."),
|
|
695
1247
|
});
|
|
696
1248
|
export const GitChangesSchema = z.object({
|
|
697
|
-
repos: z
|
|
698
|
-
|
|
699
|
-
|
|
1249
|
+
repos: z
|
|
1250
|
+
.array(RepoChangesSchema)
|
|
1251
|
+
.describe("One entry per repository that has something pending, is out of step with its remote, or could not be read. A clean repository is simply absent."),
|
|
1252
|
+
originAgents: z
|
|
1253
|
+
.record(z.string(), OriginAgentSchema)
|
|
1254
|
+
.optional()
|
|
1255
|
+
.describe("Who each conversation named above is, keyed by id, so a caller need not look them up. Absent when nothing in the review can be attributed."),
|
|
1256
|
+
committing: z
|
|
1257
|
+
.array(z.string())
|
|
1258
|
+
.optional()
|
|
1259
|
+
.describe("Repositories with a commit running right now. The sandbox's answer rather than any one tab's, so a reload, a second window and another device all know. Absent means nothing is committing."),
|
|
700
1260
|
});
|
|
701
1261
|
export const CommitResultSchema = z.object({
|
|
702
|
-
committed: z.boolean(),
|
|
703
|
-
changes: RepoChangesSchema.optional(),
|
|
704
|
-
originAgents: z
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
export const
|
|
1262
|
+
committed: z.boolean().describe("Whether a commit was actually recorded."),
|
|
1263
|
+
changes: RepoChangesSchema.optional().describe("What this repository looks like now, read in the same breath as the commit so a caller can redraw from here instead of asking for a fresh scan. Absent means there is nothing left to show."),
|
|
1264
|
+
originAgents: z
|
|
1265
|
+
.record(z.string(), OriginAgentSchema)
|
|
1266
|
+
.optional()
|
|
1267
|
+
.describe("Who the conversations named in those changes are. Merge it over what you already hold rather than replacing: other repositories still name their own."),
|
|
1268
|
+
});
|
|
1269
|
+
export const WorkspaceModuleSchema = z.object({
|
|
1270
|
+
dir: z.string().describe("Where the package lives, relative to its repository. Empty when the repository is itself one package."),
|
|
1271
|
+
name: z.string().describe("The name the package declares for itself."),
|
|
1272
|
+
});
|
|
1273
|
+
export const RepoModulesSchema = z.object({
|
|
1274
|
+
repo: z.string().describe("Which repository."),
|
|
1275
|
+
modules: z.array(WorkspaceModuleSchema).describe("Its packages."),
|
|
1276
|
+
});
|
|
1277
|
+
export const WorkspaceModulesSchema = z.object({ repos: z.array(RepoModulesSchema).describe("Every repository with the packages inside it.") });
|
|
1278
|
+
export const AgentChangeSchema = GitChangeSchema.extend({
|
|
1279
|
+
landed: z
|
|
1280
|
+
.boolean()
|
|
1281
|
+
.describe("Whether this change is already in the shared tree. The list is everything the conversation wrote, not just what is left over, because a clean turn merges in milliseconds and a list of leftovers would show an empty panel for work nobody had looked at yet."),
|
|
1282
|
+
});
|
|
710
1283
|
export const AgentRepoChangesSchema = z.object({
|
|
711
|
-
repo: z.string(),
|
|
712
|
-
branch: z.string().optional(),
|
|
713
|
-
changes: z.array(AgentChangeSchema),
|
|
714
|
-
modules: z
|
|
1284
|
+
repo: z.string().describe("Which repository."),
|
|
1285
|
+
branch: z.string().optional().describe("The branch this conversation's work sits on."),
|
|
1286
|
+
changes: z.array(AgentChangeSchema).describe("What it changed there."),
|
|
1287
|
+
modules: z
|
|
1288
|
+
.array(WorkspaceModuleSchema)
|
|
1289
|
+
.describe("The packages of the tree these changes came from, so a review can group by package. Carried with the changes rather than looked up separately, because a package the conversation has just created exists only in its own copy and the shared tree has never heard of it."),
|
|
1290
|
+
});
|
|
1291
|
+
export const AgentChangesSchema = z.object({
|
|
1292
|
+
repos: z.array(AgentRepoChangesSchema).describe("One entry per repository the conversation touched."),
|
|
1293
|
+
conflicts: z
|
|
1294
|
+
.array(LandConflictSchema)
|
|
1295
|
+
.optional()
|
|
1296
|
+
.describe("Why the last merge refused, when one did. Carried here as well as in the merge's own answer, because a conflict is found the moment a turn ends and dealt with hours later on this surface, which would otherwise open with nothing to explain what it promised to resolve."),
|
|
715
1297
|
});
|
|
716
|
-
export const AgentChangesSchema = z.object({ repos: z.array(AgentRepoChangesSchema), conflicts: z.array(LandConflictSchema).optional() });
|
|
717
1298
|
const ShaSchema = z.string().regex(/^[0-9a-f]{4,64}$/);
|
|
718
1299
|
export const GitCommitSchema = z.object({
|
|
719
|
-
sha: z.string(),
|
|
720
|
-
short: z.string(),
|
|
721
|
-
parents: z
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
1300
|
+
sha: z.string().describe("The commit, in full."),
|
|
1301
|
+
short: z.string().describe("The abbreviated form, for showing."),
|
|
1302
|
+
parents: z
|
|
1303
|
+
.array(z.string())
|
|
1304
|
+
.describe("What it came from. None means the first commit, one is ordinary, two or more is a merge, which is what a graph draws its lanes from."),
|
|
1305
|
+
subject: z.string().describe("Its first line."),
|
|
1306
|
+
body: z.string().describe("Everything after that."),
|
|
1307
|
+
author: z.string().describe("Who wrote it."),
|
|
1308
|
+
email: z.string().describe("Their address."),
|
|
1309
|
+
at: z.number().describe("When they wrote it, in milliseconds."),
|
|
1310
|
+
refs: z.array(z.string()).describe("Branches and tags sitting on it."),
|
|
1311
|
+
head: z.boolean().describe("Whether this is where the repository currently stands."),
|
|
729
1312
|
});
|
|
730
1313
|
export const GitLogSchema = z.object({
|
|
731
|
-
repo: z.string(),
|
|
732
|
-
branch: z.string().optional(),
|
|
733
|
-
commits: z.array(GitCommitSchema),
|
|
734
|
-
hasMore: z
|
|
1314
|
+
repo: z.string().describe("Which repository."),
|
|
1315
|
+
branch: z.string().optional().describe("Which branch these are from."),
|
|
1316
|
+
commits: z.array(GitCommitSchema).describe("The commits, newest first."),
|
|
1317
|
+
hasMore: z
|
|
1318
|
+
.boolean()
|
|
1319
|
+
.describe("There are older ones behind this page. It is also what stops the last row being drawn as the beginning of history, which is how a truncated log used to claim it started where the page happened to stop."),
|
|
735
1320
|
});
|
|
736
1321
|
export const GitLogQuerySchema = RepoParamSchema.extend({
|
|
737
|
-
limit: z.coerce.number().int().positive().max(2000).optional(),
|
|
738
|
-
skip: z.coerce
|
|
1322
|
+
limit: z.coerce.number().int().positive().max(2000).optional().describe("How many commits to return."),
|
|
1323
|
+
skip: z.coerce
|
|
1324
|
+
.number()
|
|
1325
|
+
.int()
|
|
1326
|
+
.nonnegative()
|
|
1327
|
+
.max(1_000_000)
|
|
1328
|
+
.optional()
|
|
1329
|
+
.describe("How many newer commits to step over, which is how you page further back. Paged rather than read whole, because a large repository's history is tens of thousands of rows."),
|
|
1330
|
+
});
|
|
1331
|
+
export const GitReposSchema = z.object({
|
|
1332
|
+
repos: z.array(z.string()).describe('Every repository\'s id. The workspace itself is always present as "root".'),
|
|
1333
|
+
});
|
|
1334
|
+
export const GitRemoteRepoSchema = z.object({
|
|
1335
|
+
repo: z.string().describe("The workspace repository."),
|
|
1336
|
+
host: z.string().describe("Which forge its remote points at."),
|
|
1337
|
+
project: z.string().describe("Which project there, as owner and name."),
|
|
1338
|
+
});
|
|
1339
|
+
export const GitRemoteReposSchema = z.object({
|
|
1340
|
+
repos: z.array(GitRemoteRepoSchema).describe("Each repository matched to the project its remote points at."),
|
|
1341
|
+
});
|
|
1342
|
+
export const GitPublishFileSchema = RepoParamSchema.extend({
|
|
1343
|
+
path: z.string().min(1).describe("Which file, relative to the repository."),
|
|
1344
|
+
content: z.string().describe("Its whole new contents."),
|
|
1345
|
+
message: z.string().min(1).describe("The commit message."),
|
|
739
1346
|
});
|
|
740
|
-
export const GitReposSchema = z.object({ repos: z.array(z.string()) });
|
|
741
|
-
export const GitRemoteRepoSchema = z.object({ repo: z.string(), host: z.string(), project: z.string() });
|
|
742
|
-
export const GitRemoteReposSchema = z.object({ repos: z.array(GitRemoteRepoSchema) });
|
|
743
|
-
export const GitPublishFileSchema = RepoParamSchema.extend({ path: z.string().min(1), content: z.string(), message: z.string().min(1) });
|
|
744
1347
|
export const GitPublishFileResultSchema = z.object({
|
|
745
|
-
ok: z.boolean(),
|
|
746
|
-
wrote: z.boolean(),
|
|
747
|
-
committed: z.boolean(),
|
|
748
|
-
pushed: z.boolean(),
|
|
749
|
-
branch: z.string().optional(),
|
|
750
|
-
defaultBranch: z.string().optional(),
|
|
751
|
-
reason: z
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
export const
|
|
757
|
-
export const
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
export const
|
|
763
|
-
|
|
1348
|
+
ok: z.boolean().describe("Whether the whole thing went through."),
|
|
1349
|
+
wrote: z.boolean().describe("The file was written."),
|
|
1350
|
+
committed: z.boolean().describe("The commit was recorded."),
|
|
1351
|
+
pushed: z.boolean().describe("It reached the remote."),
|
|
1352
|
+
branch: z.string().optional().describe("Which branch it happened on."),
|
|
1353
|
+
defaultBranch: z.string().optional().describe("Which branch the repository considers its main one, so a caller can see it was on a side branch."),
|
|
1354
|
+
reason: z
|
|
1355
|
+
.string()
|
|
1356
|
+
.optional()
|
|
1357
|
+
.describe("Why it stopped where it did. Being on a side branch, having no remote and having no credentials are all reported here rather than raised."),
|
|
1358
|
+
});
|
|
1359
|
+
export const GitCommitDiffQuerySchema = RepoParamSchema.extend({ sha: ShaSchema.describe("Which commit.") });
|
|
1360
|
+
export const GitCommitDiffSchema = z.object({
|
|
1361
|
+
files: z
|
|
1362
|
+
.array(GitChangeSchema)
|
|
1363
|
+
.describe("Which files it touched, with counts but not contents. Fetch any one file's contents separately, so a commit with a thousand files stays one cheap answer."),
|
|
1364
|
+
});
|
|
1365
|
+
export const GitCommitFileDiffQuerySchema = RepoParamSchema.extend({
|
|
1366
|
+
sha: ShaSchema.describe("Which commit."),
|
|
1367
|
+
path: z.string().min(1).describe("Which file in it."),
|
|
1368
|
+
});
|
|
1369
|
+
export const GitBranchCreateSchema = RepoParamSchema.extend({
|
|
1370
|
+
sha: ShaSchema.describe("Which commit to start it at."),
|
|
1371
|
+
name: RefNameSchema.describe("The new branch's name."),
|
|
1372
|
+
});
|
|
1373
|
+
export const GitTagCreateSchema = RepoParamSchema.extend({
|
|
1374
|
+
sha: ShaSchema.describe("Which commit to tag."),
|
|
1375
|
+
name: RefNameSchema.describe("The tag's name."),
|
|
1376
|
+
});
|
|
1377
|
+
export const GitCheckoutSchema = RepoParamSchema.extend({ ref: RefNameSchema.describe("Where to switch to: a branch, a tag, or a commit.") });
|
|
1378
|
+
export const GitTagDeleteSchema = RepoParamSchema.extend({
|
|
1379
|
+
name: RefNameSchema.describe("Which tag."),
|
|
1380
|
+
remote: RefNameSchema.optional().describe("Also delete it there. Leave it out to remove it locally only."),
|
|
1381
|
+
});
|
|
1382
|
+
export const GitTagPushSchema = RepoParamSchema.extend({
|
|
1383
|
+
name: RefNameSchema.describe("Which tag."),
|
|
1384
|
+
remote: RefNameSchema.describe("Which remote to send it to."),
|
|
1385
|
+
});
|
|
1386
|
+
export const GitResetSchema = RepoParamSchema.extend({
|
|
1387
|
+
sha: ShaSchema.describe("Which commit to move the branch to."),
|
|
1388
|
+
mode: z
|
|
1389
|
+
.enum(["soft", "mixed", "hard"])
|
|
1390
|
+
.describe("How much to take with it: move the branch alone, also unstage, or also throw away what is on disk. The last one takes a checkpoint first."),
|
|
1391
|
+
});
|
|
1392
|
+
export const GitCommitActionSchema = RepoParamSchema.extend({ sha: ShaSchema.describe("Which commit to act on.") });
|
|
1393
|
+
export const GitActionResultSchema = z.object({
|
|
1394
|
+
ok: z.boolean().describe("Whether it worked."),
|
|
1395
|
+
reason: z
|
|
1396
|
+
.string()
|
|
1397
|
+
.optional()
|
|
1398
|
+
.describe("Why not, in git's own words. A conflict, a missing remote and missing credentials are all reported here rather than raised, because they are things a screen has to render rather than breakages."),
|
|
1399
|
+
});
|
|
764
1400
|
export const StashEntrySchema = z.object({
|
|
765
|
-
ref: z.string(),
|
|
766
|
-
sha: z.string(),
|
|
767
|
-
short: z.string(),
|
|
768
|
-
subject: z.string(),
|
|
769
|
-
branch: z.string().optional(),
|
|
770
|
-
at: z.number(),
|
|
771
|
-
parents: z.array(z.string()),
|
|
1401
|
+
ref: z.string().describe("How to address it, which applying and dropping take."),
|
|
1402
|
+
sha: z.string().describe("The commit behind it, because a stash entry is a commit."),
|
|
1403
|
+
short: z.string().describe("The abbreviated form, for showing."),
|
|
1404
|
+
subject: z.string().describe("What it was set aside as, with git's own scaffolding stripped off."),
|
|
1405
|
+
branch: z.string().optional().describe("Which branch it was set aside from."),
|
|
1406
|
+
at: z.number().describe("When, in milliseconds."),
|
|
1407
|
+
parents: z.array(z.string()).describe("What it sits on, so a graph can draw it like any other commit."),
|
|
1408
|
+
});
|
|
1409
|
+
export const StashListSchema = z.object({
|
|
1410
|
+
repo: z.string().describe("Which repository."),
|
|
1411
|
+
stashes: z.array(StashEntrySchema).describe("What is set aside, newest first."),
|
|
772
1412
|
});
|
|
773
|
-
export const StashListSchema = z.object({ repo: z.string(), stashes: z.array(StashEntrySchema) });
|
|
774
1413
|
const StashRefSchema = z.string().regex(/^stash@\{\d{1,4}\}$/);
|
|
775
|
-
export const StashPushSchema = RepoParamSchema.extend({
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
1414
|
+
export const StashPushSchema = RepoParamSchema.extend({
|
|
1415
|
+
message: z.string().max(500).optional().describe("What to call it, so you know what it was later."),
|
|
1416
|
+
includeUntracked: z.boolean().optional().describe("Also set aside files git is not yet tracking, which are otherwise left where they are."),
|
|
1417
|
+
});
|
|
1418
|
+
export const StashApplySchema = RepoParamSchema.extend({
|
|
1419
|
+
ref: StashRefSchema.describe("Which entry."),
|
|
1420
|
+
pop: z.boolean().optional().describe("Remove it from the stash once it has been applied cleanly."),
|
|
1421
|
+
});
|
|
1422
|
+
export const StashRefParamSchema = RepoParamSchema.extend({ ref: StashRefSchema.describe("Which entry.") });
|
|
1423
|
+
export const StashDiffQuerySchema = RepoParamSchema.extend({ ref: StashRefSchema.describe("Which entry.") });
|
|
779
1424
|
export const UndoKindSchema = z.enum(["commit", "amend", "merge", "rebase", "cherry-pick", "revert", "reset", "pull", "other"]);
|
|
780
1425
|
export const UndoableActionSchema = z.object({
|
|
781
|
-
kind: UndoKindSchema,
|
|
782
|
-
description: z.string(),
|
|
783
|
-
branch: z.string(),
|
|
784
|
-
sha: z.string(),
|
|
785
|
-
previousSha: z
|
|
786
|
-
|
|
1426
|
+
kind: UndoKindSchema.describe("What the last action was."),
|
|
1427
|
+
description: z.string().describe("What undoing it would do, in words."),
|
|
1428
|
+
branch: z.string().describe("Which branch would move."),
|
|
1429
|
+
sha: z.string().describe("Where it stands now."),
|
|
1430
|
+
previousSha: z
|
|
1431
|
+
.string()
|
|
1432
|
+
.describe("Where it would go back to. Send this with the undo as proof you looked, so one prepared against a view that has since moved is refused rather than landing somewhere unexamined."),
|
|
1433
|
+
changesWorkingTree: z
|
|
1434
|
+
.boolean()
|
|
1435
|
+
.describe("Undoing would rewrite files as well as moving the branch, so anything offering it should warn about losing work."),
|
|
1436
|
+
});
|
|
1437
|
+
export const GitUndoStateSchema = z.object({
|
|
1438
|
+
repo: z.string().describe("Which repository."),
|
|
1439
|
+
action: UndoableActionSchema.optional().describe("What undoing would reverse. Absent means there is nothing to go back from."),
|
|
1440
|
+
});
|
|
1441
|
+
export const GitUndoSchema = RepoParamSchema.extend({
|
|
1442
|
+
previousSha: ShaSchema.describe("Where to go back to, from the matching read. It is also proof you looked: one prepared against a stale view is refused."),
|
|
1443
|
+
discardChanges: z.boolean().optional().describe("Also rewrite the files, rather than only moving the branch."),
|
|
787
1444
|
});
|
|
788
|
-
export const GitUndoStateSchema = z.object({ repo: z.string(), action: UndoableActionSchema.optional() });
|
|
789
|
-
export const GitUndoSchema = RepoParamSchema.extend({ previousSha: ShaSchema, discardChanges: z.boolean().optional() });
|
|
790
1445
|
export const SnapshotTriggerSchema = z.enum(["turn", "interval", "pre-restore", "restore", "user"]);
|
|
791
1446
|
export const SnapshotSchema = z.object({
|
|
792
|
-
id: z.string(),
|
|
793
|
-
at: z.number(),
|
|
794
|
-
trigger: SnapshotTriggerSchema,
|
|
795
|
-
label: z.string().optional(),
|
|
1447
|
+
id: z.string().describe("The saved point's id, which is what restoring and diffing take."),
|
|
1448
|
+
at: z.number().describe("When it was taken, in milliseconds."),
|
|
1449
|
+
trigger: SnapshotTriggerSchema.describe("What caused it. The automatic between-turn captures are a safety net and are not listed; they dissolve into the next visible point's differences."),
|
|
1450
|
+
label: z.string().optional().describe("What to call it. For one taken before a turn, that turn's prompt."),
|
|
796
1451
|
});
|
|
797
|
-
export const SnapshotsListSchema = z.object({ snapshots: z.array(SnapshotSchema) });
|
|
1452
|
+
export const SnapshotsListSchema = z.object({ snapshots: z.array(SnapshotSchema).describe("Every point you can go back to, newest first.") });
|
|
798
1453
|
export const RewindTurnSchema = z.object({
|
|
799
|
-
conversationId: z.string().min(1),
|
|
800
|
-
index: z
|
|
1454
|
+
conversationId: z.string().min(1).describe("Which conversation to rewind."),
|
|
1455
|
+
index: z
|
|
1456
|
+
.number()
|
|
1457
|
+
.int()
|
|
1458
|
+
.nonnegative()
|
|
1459
|
+
.describe("Which message to go back to, counting from the start. It is also how many messages survive: rewinding to the first keeps none of them and puts the files back to before it ran."),
|
|
801
1460
|
});
|
|
802
1461
|
export const RewindResultSchema = z.object({
|
|
803
|
-
snapshot: z
|
|
804
|
-
|
|
1462
|
+
snapshot: z
|
|
1463
|
+
.string()
|
|
1464
|
+
.optional()
|
|
1465
|
+
.describe("The saved point the files were put back to. Absent for a conversation working in its own copy, whose rewind moved a branch rather than the shared timeline."),
|
|
1466
|
+
dropped: z.number().int().nonnegative().describe("How many messages were removed."),
|
|
805
1467
|
});
|
|
806
|
-
export const SnapshotIdSchema = z.object({ id: z.string().min(1) });
|
|
1468
|
+
export const SnapshotIdSchema = z.object({ id: z.string().min(1).describe("Which saved point.") });
|
|
807
1469
|
export const SnapshotChangeSchema = z.object({
|
|
808
|
-
scope: z.string(),
|
|
809
|
-
path: z.string(),
|
|
810
|
-
status: z.enum(["added", "modified", "deleted", "type-changed"]),
|
|
1470
|
+
scope: z.string().describe("Which part of the workspace the path belongs to: the workspace root, or one of the repositories inside it."),
|
|
1471
|
+
path: z.string().describe("The path, relative to that scope."),
|
|
1472
|
+
status: z.enum(["added", "modified", "deleted", "type-changed"]).describe("What happened to it."),
|
|
1473
|
+
});
|
|
1474
|
+
export const SnapshotDiffSchema = z.object({
|
|
1475
|
+
changes: z.array(SnapshotChangeSchema).describe("Everything that differs between this saved point and the one before it."),
|
|
811
1476
|
});
|
|
812
|
-
export const SnapshotDiffSchema = z.object({ changes: z.array(SnapshotChangeSchema) });
|
|
813
1477
|
export const SnapshotFileDiffQuerySchema = z.object({
|
|
814
|
-
id: z.string().min(1),
|
|
815
|
-
scope: z.string().min(1),
|
|
816
|
-
path: z.string().min(1),
|
|
1478
|
+
id: z.string().min(1).describe("Which saved point."),
|
|
1479
|
+
scope: z.string().min(1).describe("Which part of the workspace the path belongs to."),
|
|
1480
|
+
path: z.string().min(1).describe("The file, relative to that scope."),
|
|
817
1481
|
});
|
|
818
1482
|
export const FileDiffSchema = z.object({
|
|
819
|
-
before: z.string().optional(),
|
|
820
|
-
after: z.string().optional(),
|
|
821
|
-
binary: z.boolean().optional(),
|
|
822
|
-
truncated: z.boolean().optional(),
|
|
1483
|
+
before: z.string().optional().describe("The whole file as it was. Absent when it did not exist yet."),
|
|
1484
|
+
after: z.string().optional().describe("The whole file as it is now. Absent when it was deleted."),
|
|
1485
|
+
binary: z.boolean().optional().describe("The file is not text, so neither side is sent."),
|
|
1486
|
+
truncated: z.boolean().optional().describe("The file was too large to send whole, so what you have is the start of it."),
|
|
1487
|
+
});
|
|
1488
|
+
export const WorkspaceScopeSchema = z.object({
|
|
1489
|
+
agent: ConversationIdSchema.optional().describe("Read a conversation's own private copy of the workspace rather than the shared tree. Leave it out for the shared tree. A conversation that is not working privately resolves back to the shared tree rather than failing, so a link need not know which mode it runs in."),
|
|
823
1490
|
});
|
|
824
|
-
export const WorkspaceScopeSchema = z.object({ agent: ConversationIdSchema.optional() });
|
|
825
1491
|
export const WorkspaceLinkSchema = z.object({
|
|
826
|
-
to: z
|
|
827
|
-
|
|
1492
|
+
to: z
|
|
1493
|
+
.string()
|
|
1494
|
+
.describe("What the link says, verbatim, rather than where it ends up. That is what the person who made it wrote, and what they would edit."),
|
|
1495
|
+
state: z
|
|
1496
|
+
.enum(["broken", "outside"])
|
|
1497
|
+
.optional()
|
|
1498
|
+
.describe("Absent for an ordinary link. Broken means there is nothing at the other end, and it is listed anyway because a dangling link is worth seeing. Outside means it leads out of the workspace, so it is shown and refused."),
|
|
828
1499
|
});
|
|
829
1500
|
export const WorkspaceTreeEntrySchema = z.object({
|
|
830
|
-
name: z.string(),
|
|
831
|
-
path: z.string(),
|
|
832
|
-
type: z.enum(["file", "dir"]),
|
|
833
|
-
size: z.number().optional(),
|
|
834
|
-
ignored: z
|
|
835
|
-
|
|
1501
|
+
name: z.string().describe("Just this entry's own name."),
|
|
1502
|
+
path: z.string().describe("Its full path from the workspace root, which feeds straight back into the file routes."),
|
|
1503
|
+
type: z.enum(["file", "dir"]).describe("What it is. For a link, what it points at, so a link to a folder opens like a folder."),
|
|
1504
|
+
size: z.number().optional().describe("Size in bytes, for a file."),
|
|
1505
|
+
ignored: z
|
|
1506
|
+
.boolean()
|
|
1507
|
+
.optional()
|
|
1508
|
+
.describe("Tooling ignores it: installed packages, git internals, anything the ignore rules exclude. Usually drawn greyed out."),
|
|
1509
|
+
link: WorkspaceLinkSchema.optional().describe("Present when this entry is a link."),
|
|
836
1510
|
get children() {
|
|
837
|
-
return z
|
|
1511
|
+
return z
|
|
1512
|
+
.array(WorkspaceTreeEntrySchema)
|
|
1513
|
+
.optional()
|
|
1514
|
+
.describe("What is inside a folder. Absent means it was not opened, either because it is ignored or because the walk ran out of budget above it, so ask for it separately. An empty list means it really is empty.");
|
|
838
1515
|
},
|
|
839
1516
|
});
|
|
840
1517
|
export const WorkspaceTreeSchema = z.object({
|
|
841
|
-
root: z.string(),
|
|
842
|
-
tree: z.array(WorkspaceTreeEntrySchema),
|
|
843
|
-
hidden: z.number(),
|
|
1518
|
+
root: z.string().describe("The path everything below is relative to."),
|
|
1519
|
+
tree: z.array(WorkspaceTreeEntrySchema).describe("The workspace, one entry per file and folder."),
|
|
1520
|
+
hidden: z.number().describe("How many entries at the top level were cut for size. Zero means the listing is complete."),
|
|
1521
|
+
});
|
|
1522
|
+
export const WorkspaceChildrenQuerySchema = WorkspaceScopeSchema.extend({
|
|
1523
|
+
path: z.string().min(1).describe("The folder to open, as a workspace path."),
|
|
844
1524
|
});
|
|
845
|
-
export const WorkspaceChildrenQuerySchema = WorkspaceScopeSchema.extend({ path: z.string().min(1) });
|
|
846
1525
|
export const WorkspaceChildrenSchema = z.object({
|
|
847
|
-
entries: z
|
|
848
|
-
|
|
1526
|
+
entries: z
|
|
1527
|
+
.array(WorkspaceTreeEntrySchema)
|
|
1528
|
+
.describe("What is directly inside it. Folders in here carry no contents of their own, so they open the same way."),
|
|
1529
|
+
hidden: z.number().describe("How many entries were cut for size. Zero means the listing is complete."),
|
|
1530
|
+
});
|
|
1531
|
+
export const WorkspaceFileQuerySchema = z.object({ path: z.string().min(1).describe("The file or folder, as a workspace path.") });
|
|
1532
|
+
export const WorkspaceMediaTicketQuerySchema = WorkspaceScopeSchema.extend({
|
|
1533
|
+
path: z.string().min(1).describe("The media file the ticket should cover."),
|
|
1534
|
+
});
|
|
1535
|
+
export const WorkspaceMediaTicketSchema = z.object({
|
|
1536
|
+
ticket: z.string().describe("Hand this to the streaming route in the query string. It buys exactly the one file it was minted for."),
|
|
1537
|
+
expiresAt: z.number().describe("When it stops working, in milliseconds, so a player can tell a dead ticket from a dead file."),
|
|
849
1538
|
});
|
|
850
|
-
export const WorkspaceFileQuerySchema = z.object({ path: z.string().min(1) });
|
|
851
|
-
export const WorkspaceMediaTicketQuerySchema = WorkspaceScopeSchema.extend({ path: z.string().min(1) });
|
|
852
|
-
export const WorkspaceMediaTicketSchema = z.object({ ticket: z.string(), expiresAt: z.number() });
|
|
853
1539
|
export const WorkspaceFileReadQuerySchema = WorkspaceScopeSchema.extend({
|
|
854
|
-
path: z.string().min(1),
|
|
855
|
-
offset: z.coerce
|
|
856
|
-
|
|
1540
|
+
path: z.string().min(1).describe("The file to read, as a workspace path."),
|
|
1541
|
+
offset: z.coerce
|
|
1542
|
+
.number()
|
|
1543
|
+
.int()
|
|
1544
|
+
.optional()
|
|
1545
|
+
.describe("Which byte to start at. A negative number reads that many bytes from the end, which is how you follow a growing log without knowing its size first."),
|
|
1546
|
+
limit: z.coerce
|
|
1547
|
+
.number()
|
|
1548
|
+
.int()
|
|
1549
|
+
.min(1)
|
|
1550
|
+
.optional()
|
|
1551
|
+
.describe("How many bytes to read. Capped by the sandbox, so leaving it out or asking for too much gives you the cap rather than the whole file."),
|
|
857
1552
|
});
|
|
858
1553
|
export const WorkspaceFilePresentSchema = z.object({
|
|
859
|
-
present: z.literal(true),
|
|
860
|
-
path: z.string(),
|
|
861
|
-
content: z.string(),
|
|
862
|
-
size: z.number(),
|
|
863
|
-
offset: z.number(),
|
|
864
|
-
bytes: z.number(),
|
|
865
|
-
shared: z
|
|
1554
|
+
present: z.literal(true).describe("There is something at that path."),
|
|
1555
|
+
path: z.string().describe("The path, as asked for."),
|
|
1556
|
+
content: z.string().describe("The bytes of the window you asked for, as text."),
|
|
1557
|
+
size: z.number().describe("How large the whole file is. Compare it with the window below to know whether there is more."),
|
|
1558
|
+
offset: z.number().describe("Which byte the window starts at."),
|
|
1559
|
+
bytes: z.number().describe("How many bytes the window holds."),
|
|
1560
|
+
shared: z
|
|
1561
|
+
.boolean()
|
|
1562
|
+
.describe("Which tree answered. True when no conversation was named, and also when one was but its own copy has no such file, which is the case a reader has to be told about rather than left to assume."),
|
|
1563
|
+
});
|
|
1564
|
+
export const WorkspaceFileAbsentSchema = z.object({
|
|
1565
|
+
present: z
|
|
1566
|
+
.literal(false)
|
|
1567
|
+
.describe("Nothing there. An answer, not a failure: reading a file that may not exist yet is the ordinary case for half the reads in this product."),
|
|
1568
|
+
path: z.string().describe("The path, as asked for."),
|
|
866
1569
|
});
|
|
867
|
-
export const WorkspaceFileAbsentSchema = z.object({ present: z.literal(false), path: z.string() });
|
|
868
1570
|
export const WorkspaceFileSchema = z.discriminatedUnion("present", [WorkspaceFilePresentSchema, WorkspaceFileAbsentSchema]);
|
|
869
|
-
export const WorkspaceResolveQuerySchema = WorkspaceScopeSchema.extend({
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1571
|
+
export const WorkspaceResolveQuerySchema = WorkspaceScopeSchema.extend({
|
|
1572
|
+
path: z
|
|
1573
|
+
.string()
|
|
1574
|
+
.min(1)
|
|
1575
|
+
.max(512)
|
|
1576
|
+
.describe("The reference as somebody wrote it. Often only the tail of the real path, which is why this is matched against the tree rather than read as-is."),
|
|
1577
|
+
});
|
|
1578
|
+
export const WorkspaceResolveSchema = z.object({
|
|
1579
|
+
path: z.string().optional().describe("The real path it means. Absent when nothing in the workspace ends that way."),
|
|
1580
|
+
});
|
|
1581
|
+
export const WorkspaceDirSchema = z.object({ path: z.string().min(1).describe("The folder to create. Missing folders above it are created too.") });
|
|
1582
|
+
export const WorkspaceMoveSchema = z.object({
|
|
1583
|
+
from: z.string().min(1).describe("What to move or copy, as a workspace path."),
|
|
1584
|
+
to: z.string().min(1).describe("Where it should end up. Changing only the last part is how you rename something."),
|
|
1585
|
+
});
|
|
873
1586
|
export const WorkspaceBucketSchema = z.enum(["repositories", "documents", "media", "archives", "other"]);
|
|
874
1587
|
export const WorkspaceClassificationSchema = z.object({
|
|
875
|
-
classifications: z
|
|
1588
|
+
classifications: z
|
|
1589
|
+
.array(z.object({
|
|
1590
|
+
path: z.string().describe("What was looked at."),
|
|
1591
|
+
bucket: WorkspaceBucketSchema.describe("Which bucket it was sorted into."),
|
|
1592
|
+
reason: z.string().describe("The signal that decided it, so the proposal can be argued with rather than trusted."),
|
|
1593
|
+
}))
|
|
1594
|
+
.describe("One entry per repository folder and loose file at the top of the workspace. A read-only proposal: nothing moves until you apply it."),
|
|
876
1595
|
});
|
|
877
1596
|
export const WorkspaceSearchQuerySchema = z.object({
|
|
878
|
-
query: z.string().min(2).max(512),
|
|
879
|
-
mode: z
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
1597
|
+
query: z.string().min(2).max(512).describe("What to look for. Plain words, a pattern, a symbol name, or a question."),
|
|
1598
|
+
mode: z
|
|
1599
|
+
.enum(["q", "find", "files", "def", "refs", "sym", "ast"])
|
|
1600
|
+
.optional()
|
|
1601
|
+
.describe("Narrow the search to one kind: plain text, filenames, definitions, references, symbols, or code structure. Leave it out to blend them, which also answers a question asked in words."),
|
|
1602
|
+
includeIgnored: z.stringbool().optional().describe("Search inside installed packages and other ignored folders too."),
|
|
1603
|
+
literal: z.stringbool().optional().describe("Treat the query as fixed text rather than a pattern."),
|
|
1604
|
+
word: z.stringbool().optional().describe("Match whole words only."),
|
|
1605
|
+
caseSensitive: z.stringbool().optional().describe("Whether capitals matter. Off means they do not, rather than being guessed at from the query."),
|
|
1606
|
+
include: z
|
|
1607
|
+
.string()
|
|
1608
|
+
.max(512)
|
|
1609
|
+
.optional()
|
|
1610
|
+
.describe("Which files to ask, in the same grammar an editor's files-to-include box takes: comma-separated patterns, matched at any depth unless anchored, a leading exclamation mark excluding instead."),
|
|
1611
|
+
limit: z.coerce.number().int().positive().optional().describe("How many results to return."),
|
|
1612
|
+
after: z.string().optional().describe("Resume from the cursor a previous answer handed back."),
|
|
887
1613
|
});
|
|
888
1614
|
export const WorkspaceSearchTagSchema = z.object({
|
|
889
|
-
kind: z
|
|
890
|
-
|
|
1615
|
+
kind: z
|
|
1616
|
+
.enum(["def", "text", "sem", "bm25", "rerank", "path", "import", "call", "type", "write", "fuzzy", "heuristic"])
|
|
1617
|
+
.describe("Why this line matched: the literal text, its meaning, the path, a definition, a call, and so on. Several kinds can agree on one line."),
|
|
1618
|
+
score: z.number().optional().describe("How strongly that reason applied."),
|
|
1619
|
+
});
|
|
1620
|
+
export const WorkspaceSearchSpanSchema = z.object({
|
|
1621
|
+
start: z.number().describe("First character of the match within the line."),
|
|
1622
|
+
end: z.number().describe("One past the last."),
|
|
891
1623
|
});
|
|
892
|
-
export const WorkspaceSearchSpanSchema = z.object({ start: z.number(), end: z.number() });
|
|
893
1624
|
export const WorkspaceSearchHitSchema = z.object({
|
|
894
|
-
line: z.number(),
|
|
895
|
-
text: z.string(),
|
|
896
|
-
spans: z
|
|
897
|
-
|
|
898
|
-
|
|
1625
|
+
line: z.number().describe("Which line, counting from one."),
|
|
1626
|
+
text: z.string().describe("The line itself."),
|
|
1627
|
+
spans: z
|
|
1628
|
+
.array(WorkspaceSearchSpanSchema)
|
|
1629
|
+
.describe("Where in the line the matches are, so you can highlight without searching again. Empty when the whole line is the match rather than part of it."),
|
|
1630
|
+
tags: z.array(WorkspaceSearchTagSchema).describe("Why it matched."),
|
|
1631
|
+
context: z
|
|
1632
|
+
.string()
|
|
1633
|
+
.optional()
|
|
1634
|
+
.describe("What it sits inside: the function, the class, the heading. Often enough that you need not open the file."),
|
|
899
1635
|
});
|
|
900
1636
|
export const WorkspaceSearchGroupSchema = z.object({
|
|
901
|
-
path: z.string(),
|
|
902
|
-
score: z.number(),
|
|
903
|
-
hits: z.array(WorkspaceSearchHitSchema),
|
|
904
|
-
capped: z
|
|
1637
|
+
path: z.string().describe("The file."),
|
|
1638
|
+
score: z.number().describe("How well it matched. Groups arrive best first, never in path order."),
|
|
1639
|
+
hits: z.array(WorkspaceSearchHitSchema).describe("The matching lines in it."),
|
|
1640
|
+
capped: z
|
|
1641
|
+
.boolean()
|
|
1642
|
+
.optional()
|
|
1643
|
+
.describe("This file had more matches than are kept per file, so the count is a floor. Say fifty-plus rather than fifty."),
|
|
905
1644
|
});
|
|
906
1645
|
export const WorkspaceSearchFreshnessSchema = z.object({
|
|
907
|
-
state: z.enum(["fresh", "building", "stale"]),
|
|
908
|
-
ageMs: z.number().optional(),
|
|
909
|
-
progress: z.number().optional(),
|
|
910
|
-
behind: z
|
|
1646
|
+
state: z.enum(["fresh", "building", "stale"]).describe("Whether the index matches what is on disk, is still filling, or has fallen behind."),
|
|
1647
|
+
ageMs: z.number().optional().describe("How long since it last matched the disk, in milliseconds."),
|
|
1648
|
+
progress: z.number().optional().describe("How far through building it is, from zero to one."),
|
|
1649
|
+
behind: z
|
|
1650
|
+
.number()
|
|
1651
|
+
.optional()
|
|
1652
|
+
.describe("How many files it has not caught up with. Worth showing, because the word stale on its own reads as a warning about the answer, which it almost never is."),
|
|
911
1653
|
});
|
|
912
1654
|
export const WorkspaceSearchResultSchema = z.object({
|
|
913
|
-
mode: z.string(),
|
|
914
|
-
total: z.number(),
|
|
915
|
-
files: z.number(),
|
|
916
|
-
shown: z.number(),
|
|
917
|
-
groups: z.array(WorkspaceSearchGroupSchema),
|
|
918
|
-
freshness: WorkspaceSearchFreshnessSchema,
|
|
919
|
-
truncated: z.boolean(),
|
|
920
|
-
partial: z
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1655
|
+
mode: z.string().describe("Which kind of search actually ran, which matters when you let it choose."),
|
|
1656
|
+
total: z.number().describe("Matching lines across the whole workspace, not just this page."),
|
|
1657
|
+
files: z.number().describe("Files the query matched in total."),
|
|
1658
|
+
shown: z.number().describe("How many of those lines are on this page."),
|
|
1659
|
+
groups: z.array(WorkspaceSearchGroupSchema).describe("The results, grouped by file, best first."),
|
|
1660
|
+
freshness: WorkspaceSearchFreshnessSchema.describe("Whether the index behind the answer is up to date."),
|
|
1661
|
+
truncated: z.boolean().describe("This page is not all of it. Use the cursor."),
|
|
1662
|
+
partial: z
|
|
1663
|
+
.boolean()
|
|
1664
|
+
.optional()
|
|
1665
|
+
.describe("At least one file had more matches than are kept per file, so the total is a floor. Different from the page being truncated: a complete page can still count partially."),
|
|
1666
|
+
cursor: z.string().optional().describe("Pass this back as `after` to get the next page."),
|
|
1667
|
+
hint: z.string().optional().describe("A suggestion for getting a better answer out of this query."),
|
|
1668
|
+
note: z
|
|
1669
|
+
.string()
|
|
1670
|
+
.optional()
|
|
1671
|
+
.describe("What the engine did that you did not ask for: a pattern rerun as plain text because it was not valid, escapes rewritten, a language filter that matched nothing."),
|
|
1672
|
+
related: z.array(z.string()).optional().describe("Places next door to the best results: where each is defined, and whatever calls it most."),
|
|
1673
|
+
candidates: z
|
|
1674
|
+
.array(z.string())
|
|
1675
|
+
.optional()
|
|
1676
|
+
.describe("Ranked places that scored but did not make the page, best first. The answer often sits at rank five to thirteen, so this saves paging through to find out."),
|
|
1677
|
+
features: z.array(z.string()).optional().describe("Which stages of the search were switched off for this run. Absent means all of them ran."),
|
|
927
1678
|
});
|
|
928
1679
|
export const HEALTH_LIMIT = 20;
|
|
929
1680
|
export const WorkspaceHealthQuerySchema = z.object({
|
|
930
|
-
repo: z.string().min(1),
|
|
931
|
-
since: z
|
|
932
|
-
|
|
1681
|
+
repo: z.string().min(1).describe("Which repository, using the same ids the git routes take."),
|
|
1682
|
+
since: z
|
|
1683
|
+
.string()
|
|
1684
|
+
.max(16)
|
|
1685
|
+
.optional()
|
|
1686
|
+
.describe("How far back to count changes, written as a span such as 2d, 12h, 1w or 3m. Leave it out for all of history."),
|
|
1687
|
+
limit: z.coerce
|
|
1688
|
+
.number()
|
|
1689
|
+
.int()
|
|
1690
|
+
.positive()
|
|
1691
|
+
.max(200)
|
|
1692
|
+
.optional()
|
|
1693
|
+
.describe("How many files and modules to rank. A leaderboard rather than an inventory: past a screenful the ranking stops being the point."),
|
|
933
1694
|
});
|
|
934
1695
|
export const WorkspaceHotspotSchema = z.object({
|
|
935
1696
|
path: z.string(),
|
|
@@ -942,78 +1703,127 @@ export const WorkspaceHotspotSchema = z.object({
|
|
|
942
1703
|
});
|
|
943
1704
|
export const WorkspaceKeyModuleSchema = z.object({ path: z.string(), exports: z.number() });
|
|
944
1705
|
export const WorkspaceHealthSchema = z.object({
|
|
945
|
-
repo: z.string(),
|
|
946
|
-
totals: z
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1706
|
+
repo: z.string().describe("Which repository this describes."),
|
|
1707
|
+
totals: z
|
|
1708
|
+
.object({
|
|
1709
|
+
files: z.number().describe("Files counted."),
|
|
1710
|
+
symbols: z.number().describe("Named things they export."),
|
|
1711
|
+
complexity: z.number().describe("Branch points across all of them added up."),
|
|
1712
|
+
hotspots: z.number().describe("How many files qualify as hotspots at all. The list below is capped; this is not."),
|
|
1713
|
+
})
|
|
1714
|
+
.describe("Counts anybody could recount in the files themselves. Deliberately no single maintainability grade: those cannot be checked and are not comparable between projects."),
|
|
1715
|
+
hotspots: z.array(WorkspaceHotspotSchema).describe("Files that change often and are complicated at the same time, worst first."),
|
|
1716
|
+
modules: z.array(WorkspaceKeyModuleSchema).describe("The parts of the codebase the rest of it leans on most."),
|
|
1717
|
+
freshness: WorkspaceSearchFreshnessSchema.describe("Whether the index these numbers were read from is up to date."),
|
|
955
1718
|
});
|
|
956
1719
|
export const ProjectSetupSchema = z.object({
|
|
957
|
-
dir: z.string(),
|
|
958
|
-
ecosystem: z.enum(["node", "python"]),
|
|
959
|
-
manager: z.string(),
|
|
960
|
-
command: z.string(),
|
|
961
|
-
evidence: z.string(),
|
|
962
|
-
state: z
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
export const
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
export const
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
1720
|
+
dir: z.string().describe("Where the project is, relative to the workspace root. Empty means the root itself."),
|
|
1721
|
+
ecosystem: z.enum(["node", "python"]).describe("Which language's tooling it uses."),
|
|
1722
|
+
manager: z.string().describe("The tool that would do the installing."),
|
|
1723
|
+
command: z.string().describe("The exact command that would run."),
|
|
1724
|
+
evidence: z.string().describe("The file that decided all of the above, so the answer can be checked rather than trusted."),
|
|
1725
|
+
state: z
|
|
1726
|
+
.enum(["ready", "installing", "needs-setup", "unsupported", "stale"])
|
|
1727
|
+
.describe("Ready means its dependencies are really there. Stale means it was installed once and has since outgrown that, which is what an agent leaves behind when it adds a dependency without installing it. Unsupported means this sandbox has no such tool."),
|
|
1728
|
+
missing: z.number().optional().describe("How many declared dependencies cannot be found on disk. What separates never-installed from outgrown."),
|
|
1729
|
+
});
|
|
1730
|
+
export const WorkspaceSetupSchema = z.object({
|
|
1731
|
+
projects: z.array(ProjectSetupSchema).describe("Every project the sandbox found, and whether each is usable."),
|
|
1732
|
+
});
|
|
1733
|
+
export const WorkspaceInstallSchema = z.object({
|
|
1734
|
+
dirs: z
|
|
1735
|
+
.array(z.string().max(500))
|
|
1736
|
+
.min(1)
|
|
1737
|
+
.max(50)
|
|
1738
|
+
.describe("Which projects to install, by folder. Ones already ready, already installing, or with no tool to install them are skipped rather than refused."),
|
|
1739
|
+
});
|
|
1740
|
+
export const WorkspaceInstallResultSchema = z.object({
|
|
1741
|
+
queued: z.array(z.string()).describe("Which of them actually started, which is not necessarily what you asked for."),
|
|
978
1742
|
});
|
|
979
|
-
export const
|
|
1743
|
+
export const ReposListSchema = z.object({
|
|
1744
|
+
repos: z
|
|
1745
|
+
.array(z.string())
|
|
1746
|
+
.describe('Every repository\'s id, sorted. An id is its folder relative to the workspace root, and "root" is the workspace itself.'),
|
|
1747
|
+
});
|
|
1748
|
+
export const CloneRepoSchema = z.object({
|
|
1749
|
+
name: z.string().min(1).describe("What to call it in the workspace."),
|
|
1750
|
+
cloneUrl: z.string().min(1).describe("Where to clone it from."),
|
|
1751
|
+
branch: z.string().optional().describe("Which branch to check out. Leave it out for the repository's default."),
|
|
1752
|
+
});
|
|
1753
|
+
export const CloneResultSchema = z.object({
|
|
1754
|
+
name: z.string().describe("What it ended up called."),
|
|
1755
|
+
path: z.string().describe("Where it landed."),
|
|
1756
|
+
});
|
|
1757
|
+
export const RepoSyncSchema = z.object({
|
|
1758
|
+
repo: z.string().describe("Which repository."),
|
|
1759
|
+
status: z
|
|
1760
|
+
.enum(["updated", "current", "dirty", "diverged", "no-remote", "skipped", "error"])
|
|
1761
|
+
.describe("What happened to it. Dirty and diverged are why a repository was left alone: it had uncommitted work, or it had moved in a way that cannot be fast-forwarded."),
|
|
1762
|
+
behind: z.number().optional().describe("How many commits it was behind."),
|
|
1763
|
+
ahead: z.number().optional().describe("How many commits it was ahead."),
|
|
1764
|
+
head: z.string().optional().describe("The commit it ended up on."),
|
|
1765
|
+
message: z.string().optional().describe("What went wrong, when something did."),
|
|
1766
|
+
});
|
|
1767
|
+
export const WorkspaceSyncSchema = z.object({ repos: z.array(RepoSyncSchema).describe("One entry per repository, saying what happened to it.") });
|
|
980
1768
|
export const AppInstanceInputSchema = z.object({
|
|
981
|
-
template: z.string().min(1),
|
|
1769
|
+
template: z.string().min(1).describe("Which kind of app to scaffold, by its key in the template list."),
|
|
982
1770
|
name: z
|
|
983
1771
|
.string()
|
|
984
1772
|
.min(1)
|
|
985
|
-
.regex(/^[a-z][a-z0-9-]*$/)
|
|
1773
|
+
.regex(/^[a-z][a-z0-9-]*$/)
|
|
1774
|
+
.describe("What to call this one."),
|
|
986
1775
|
});
|
|
987
1776
|
export const AddAppsSchema = z.object({
|
|
988
|
-
repo: z.string(),
|
|
989
|
-
apps: z.array(AppInstanceInputSchema).min(1),
|
|
1777
|
+
repo: z.string().describe("Which repository to scaffold into."),
|
|
1778
|
+
apps: z.array(AppInstanceInputSchema).min(1).describe("The apps to add."),
|
|
990
1779
|
});
|
|
991
1780
|
export const RunTestsSchema = z.object({
|
|
992
|
-
repo: z.string(),
|
|
993
|
-
session: z.string(),
|
|
994
|
-
dirs: z.array(z.string()).min(1),
|
|
1781
|
+
repo: z.string().describe("Which repository."),
|
|
1782
|
+
session: z.string().describe("What to call the terminal this runs in, so you can find it again."),
|
|
1783
|
+
dirs: z.array(z.string()).min(1).describe("Which projects to test, as folders relative to the repository. Empty targets the repository root."),
|
|
1784
|
+
});
|
|
1785
|
+
export const TemplateSummarySchema = z.object({
|
|
1786
|
+
key: z.string().describe("The id to name when scaffolding one."),
|
|
1787
|
+
label: z.string().describe("What to call it on screen."),
|
|
1788
|
+
description: z.string().describe("What you get."),
|
|
1789
|
+
});
|
|
1790
|
+
export const TemplatesListSchema = z.object({
|
|
1791
|
+
templates: z.array(TemplateSummarySchema).describe("The kinds of app the configured source repository knows how to scaffold."),
|
|
995
1792
|
});
|
|
996
|
-
export const TemplateSummarySchema = z.object({ key: z.string(), label: z.string(), description: z.string() });
|
|
997
|
-
export const TemplatesListSchema = z.object({ templates: z.array(TemplateSummarySchema) });
|
|
998
1793
|
export const RepoAppSchema = z.object({
|
|
999
|
-
app: z.string(),
|
|
1000
|
-
kind: z
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1794
|
+
app: z.string().describe("The app's name, which is also its folder."),
|
|
1795
|
+
kind: z
|
|
1796
|
+
.string()
|
|
1797
|
+
.optional()
|
|
1798
|
+
.describe("What sort of app it is: the template it came from, or the framework worked out from its dependencies. Absent when it was found purely by having a dev script."),
|
|
1799
|
+
previewUrl: z.string().optional().describe("Where to open it. Absent when this sandbox has no outside address."),
|
|
1800
|
+
running: z.boolean().describe("Whether its dev server is up."),
|
|
1801
|
+
healthy: z.boolean().describe("Whether it is actually answering."),
|
|
1802
|
+
});
|
|
1803
|
+
export const AppsListSchema = z.object({ apps: z.array(RepoAppSchema).describe("The apps in this repository.") });
|
|
1804
|
+
export const WorkspacePackageSchema = z.object({
|
|
1805
|
+
name: z.string().describe("The name the package declares."),
|
|
1806
|
+
dir: z.string().describe("Where it lives, relative to the repository."),
|
|
1807
|
+
group: z.string().describe("The top-level folder it sits under, which is what a diagram colours by."),
|
|
1004
1808
|
});
|
|
1005
|
-
export const AppsListSchema = z.object({ apps: z.array(RepoAppSchema) });
|
|
1006
|
-
export const WorkspacePackageSchema = z.object({ name: z.string(), dir: z.string(), group: z.string() });
|
|
1007
1809
|
export const WorkspaceDepTypeSchema = z.enum(["prod", "dev", "peer"]);
|
|
1008
|
-
export const WorkspaceDepEdgeSchema = z.object({
|
|
1009
|
-
|
|
1010
|
-
|
|
1810
|
+
export const WorkspaceDepEdgeSchema = z.object({
|
|
1811
|
+
from: z.string().describe("The package that depends."),
|
|
1812
|
+
to: z.string().describe("The package it depends on."),
|
|
1813
|
+
type: WorkspaceDepTypeSchema.describe("Which kind of dependency declared it."),
|
|
1814
|
+
});
|
|
1815
|
+
export const WorkspaceGraphSchema = z.object({
|
|
1816
|
+
packages: z.array(WorkspacePackageSchema).describe("Every package in the repository."),
|
|
1817
|
+
edges: z.array(WorkspaceDepEdgeSchema).describe("Which of them use which. Pure data: how to lay it out is yours to decide."),
|
|
1818
|
+
});
|
|
1819
|
+
export const RepoAppsParamSchema = z.object({ repo: z.string().describe("Which repository.") });
|
|
1011
1820
|
export const AppParamSchema = z.object({
|
|
1012
|
-
repo: z.string(),
|
|
1821
|
+
repo: z.string().describe("Which repository."),
|
|
1013
1822
|
app: z
|
|
1014
1823
|
.string()
|
|
1015
1824
|
.min(1)
|
|
1016
|
-
.regex(/^[a-z][a-z0-9-]*$/)
|
|
1825
|
+
.regex(/^[a-z][a-z0-9-]*$/)
|
|
1826
|
+
.describe("Which app inside it."),
|
|
1017
1827
|
});
|
|
1018
1828
|
export const InventoryProviderSchema = z.enum(["host", "cloudflare", "github", "gitlab", "stripe"]);
|
|
1019
1829
|
export const ServiceKindSchema = z.enum(["signoz", "outline", "paperless", "openproject", "invoiceninja", "infisical"]);
|
|
@@ -1024,25 +1834,25 @@ const inventoryName = z
|
|
|
1024
1834
|
.max(60)
|
|
1025
1835
|
.regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/);
|
|
1026
1836
|
export const BackendEntrySchema = z.object({
|
|
1027
|
-
kind: z.literal("backend"),
|
|
1028
|
-
provider: InventoryProviderSchema,
|
|
1029
|
-
name: z.string(),
|
|
1030
|
-
values: InventoryValuesSchema,
|
|
1837
|
+
kind: z.literal("backend").describe("Something you already have: a machine, an account with a hosting provider."),
|
|
1838
|
+
provider: InventoryProviderSchema.describe("Which provider it is with."),
|
|
1839
|
+
name: z.string().describe("What to call it, which is also how everything else refers to it."),
|
|
1840
|
+
values: InventoryValuesSchema.describe("Its settings. Anything secret is stored separately and referred to here, never written in."),
|
|
1031
1841
|
});
|
|
1032
1842
|
export const ServiceEntrySchema = z.object({
|
|
1033
|
-
kind: z.literal("service"),
|
|
1034
|
-
service: ServiceKindSchema,
|
|
1035
|
-
name: z.string(),
|
|
1036
|
-
values: InventoryValuesSchema,
|
|
1037
|
-
on: z.string(),
|
|
1038
|
-
expose: z.string(),
|
|
1843
|
+
kind: z.literal("service").describe("Something you want provisioned."),
|
|
1844
|
+
service: ServiceKindSchema.describe("Which service."),
|
|
1845
|
+
name: z.string().describe("What to call it."),
|
|
1846
|
+
values: InventoryValuesSchema.describe("Its settings."),
|
|
1847
|
+
on: z.string().describe("Which of your machines to put it on."),
|
|
1848
|
+
expose: z.string().describe("How it should be reachable."),
|
|
1039
1849
|
});
|
|
1040
1850
|
export const AppEntrySchema = z.object({
|
|
1041
|
-
kind: z.literal("app"),
|
|
1042
|
-
name: z.string(),
|
|
1043
|
-
values: InventoryValuesSchema,
|
|
1044
|
-
on: z.string(),
|
|
1045
|
-
expose: z.string(),
|
|
1851
|
+
kind: z.literal("app").describe("An app of your own, built from source and deployed."),
|
|
1852
|
+
name: z.string().describe("What to call it."),
|
|
1853
|
+
values: InventoryValuesSchema.describe("Its settings, including the address it should answer on."),
|
|
1854
|
+
on: z.string().describe("Which of your machines to put it on."),
|
|
1855
|
+
expose: z.string().describe("How it should be reachable."),
|
|
1046
1856
|
});
|
|
1047
1857
|
export const InventoryEntrySchema = z.discriminatedUnion("kind", [BackendEntrySchema, ServiceEntrySchema, AppEntrySchema]);
|
|
1048
1858
|
export const AddInventoryInputSchema = z.discriminatedUnion("kind", [
|
|
@@ -1050,8 +1860,10 @@ export const AddInventoryInputSchema = z.discriminatedUnion("kind", [
|
|
|
1050
1860
|
ServiceEntrySchema.extend({ name: inventoryName }),
|
|
1051
1861
|
AppEntrySchema.extend({ name: inventoryName }),
|
|
1052
1862
|
]);
|
|
1053
|
-
export const InventoryNameParamSchema = z.object({ name: z.string() });
|
|
1054
|
-
export const InventoryListSchema = z.object({
|
|
1863
|
+
export const InventoryNameParamSchema = z.object({ name: z.string().describe("Which entry, by name.") });
|
|
1864
|
+
export const InventoryListSchema = z.object({
|
|
1865
|
+
entries: z.array(InventoryEntrySchema).describe("Everything declared: what you have, and what you want provisioned."),
|
|
1866
|
+
});
|
|
1055
1867
|
export const EnrollHostInputSchema = z.object({
|
|
1056
1868
|
name: inventoryName,
|
|
1057
1869
|
user: z.string().min(1),
|
|
@@ -1084,51 +1896,74 @@ export const CapabilityKindSchema = z.enum([
|
|
|
1084
1896
|
"wallet",
|
|
1085
1897
|
]);
|
|
1086
1898
|
export const CapabilityStateSchema = z.enum(["active", "pending", "error", "inactive"]);
|
|
1087
|
-
export const McpConfigSchema = z.object({
|
|
1899
|
+
export const McpConfigSchema = z.object({
|
|
1900
|
+
url: z.url().describe("Where the tool server answers."),
|
|
1901
|
+
token: z.string().optional().describe("The credential it needs, if any. Stored, never echoed back."),
|
|
1902
|
+
});
|
|
1088
1903
|
export const ServiceConfigSchema = z.object({
|
|
1089
|
-
service: ServiceKindSchema,
|
|
1090
|
-
domain: z.string().min(1),
|
|
1091
|
-
on: z.string().min(1),
|
|
1092
|
-
expose: z.string().min(1),
|
|
1904
|
+
service: ServiceKindSchema.describe("Which service to provision."),
|
|
1905
|
+
domain: z.string().min(1).describe("The address it should answer on."),
|
|
1906
|
+
on: z.string().min(1).describe("Which machine to put it on."),
|
|
1907
|
+
expose: z.string().min(1).describe("How it should be reachable."),
|
|
1908
|
+
});
|
|
1909
|
+
export const IntegrationConfigSchema = z.object({
|
|
1910
|
+
provider: z.literal("stripe").describe("Which outside service's credential to make available to deployed apps."),
|
|
1093
1911
|
});
|
|
1094
|
-
export const
|
|
1095
|
-
|
|
1912
|
+
export const CliConfigSchema = z
|
|
1913
|
+
.object({
|
|
1914
|
+
provider: z
|
|
1915
|
+
.string()
|
|
1916
|
+
.min(1)
|
|
1917
|
+
.describe("Which tool to give the agent. The rest of the fields are whatever that tool's own card declares it needs, and are checked against it when you connect."),
|
|
1918
|
+
})
|
|
1919
|
+
.catchall(z.string());
|
|
1096
1920
|
export const PluginConfigSchema = z.object({
|
|
1097
|
-
url: z.url(),
|
|
1098
|
-
ref: z.string().min(1).optional(),
|
|
1921
|
+
url: z.url().describe("The repository to take the plugin from."),
|
|
1922
|
+
ref: z.string().min(1).optional().describe("A branch, tag or commit to pin to. Leave it out to follow the default branch."),
|
|
1099
1923
|
path: z
|
|
1100
1924
|
.string()
|
|
1101
1925
|
.min(1)
|
|
1102
1926
|
.refine((value) => !value.split("/").includes(".."), { message: "path must stay inside the checkout" })
|
|
1103
|
-
.optional()
|
|
1104
|
-
|
|
1927
|
+
.optional()
|
|
1928
|
+
.describe("Where inside the repository the plugin lives, for one that sits in a larger checkout."),
|
|
1929
|
+
token: z.string().min(1).optional().describe("A credential for a private repository. Stored, never echoed back."),
|
|
1105
1930
|
});
|
|
1106
1931
|
export const ExtensionConfigSchema = z.object({
|
|
1107
|
-
url: z.url(),
|
|
1108
|
-
ref: z
|
|
1932
|
+
url: z.url().describe("The repository to take the extension from."),
|
|
1933
|
+
ref: z
|
|
1934
|
+
.string()
|
|
1935
|
+
.regex(/^[0-9a-f]{40}$/, "ref must be a full 40-character commit sha")
|
|
1936
|
+
.describe("The exact commit to install, in full. Required rather than optional because extension code runs with your browser's trust: the owner approves precisely the code that runs, and an update is a deliberate re-install at a new commit."),
|
|
1109
1937
|
path: z
|
|
1110
1938
|
.string()
|
|
1111
1939
|
.min(1)
|
|
1112
1940
|
.refine((value) => !value.split("/").includes(".."), { message: "path must stay inside the checkout" })
|
|
1113
|
-
.optional()
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1941
|
+
.optional()
|
|
1942
|
+
.describe("Where inside the repository the extension lives, for one that sits in a larger checkout."),
|
|
1943
|
+
token: z.string().min(1).optional().describe("A credential for a private repository. Stored, never echoed back."),
|
|
1944
|
+
tier: z
|
|
1945
|
+
.enum(["free", "premium"])
|
|
1946
|
+
.optional()
|
|
1947
|
+
.describe("Whether installing this donates credits to its publisher. Absent means free, which donates nothing and asks for nothing. Taken from the listing rather than checked against it, which is the honesty an open-source posture accepts."),
|
|
1948
|
+
registry: z
|
|
1949
|
+
.url()
|
|
1950
|
+
.optional()
|
|
1951
|
+
.describe("Which registry this install came from, which is what update checks and security advisories are read against. Absent falls back to the official one."),
|
|
1117
1952
|
});
|
|
1118
1953
|
export const SshConfigSchema = z.discriminatedUnion("auth", [
|
|
1119
1954
|
z.object({
|
|
1120
|
-
auth: z.literal("key"),
|
|
1121
|
-
host: z.string().min(1),
|
|
1122
|
-
port: z.coerce.number().default(22),
|
|
1123
|
-
user: z.string().min(1),
|
|
1124
|
-
privateKey: z.string().min(1),
|
|
1955
|
+
auth: z.literal("key").describe("Sign in with a key."),
|
|
1956
|
+
host: z.string().min(1).describe("The machine's address."),
|
|
1957
|
+
port: z.coerce.number().default(22).describe("Which port it listens on."),
|
|
1958
|
+
user: z.string().min(1).describe("Which user to connect as."),
|
|
1959
|
+
privateKey: z.string().min(1).describe("The private key, whole. Stored with tight permissions and never echoed back."),
|
|
1125
1960
|
}),
|
|
1126
1961
|
z.object({
|
|
1127
|
-
auth: z.literal("password"),
|
|
1128
|
-
host: z.string().min(1),
|
|
1129
|
-
port: z.coerce.number().default(22),
|
|
1130
|
-
user: z.string().min(1),
|
|
1131
|
-
password: z.string().min(1),
|
|
1962
|
+
auth: z.literal("password").describe("Sign in with a password."),
|
|
1963
|
+
host: z.string().min(1).describe("The machine's address."),
|
|
1964
|
+
port: z.coerce.number().default(22).describe("Which port it listens on."),
|
|
1965
|
+
user: z.string().min(1).describe("Which user to connect as."),
|
|
1966
|
+
password: z.string().min(1).describe("The password. Stored, never echoed back."),
|
|
1132
1967
|
}),
|
|
1133
1968
|
]);
|
|
1134
1969
|
export const VpnProviderSchema = z.enum(["wireguard", "fortinet", "ipsec"]);
|
|
@@ -1286,10 +2121,19 @@ export const CapabilitySchema = z.discriminatedUnion("kind", [
|
|
|
1286
2121
|
z.object({ id: entryId, kind: z.literal("wallet"), config: WalletConfigSchema }),
|
|
1287
2122
|
]);
|
|
1288
2123
|
export const PersonaPowersSchema = z.object({
|
|
1289
|
-
files: z
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
2124
|
+
files: z
|
|
2125
|
+
.enum(["none", "read", "write"])
|
|
2126
|
+
.default("write")
|
|
2127
|
+
.describe("What it may do with files: nothing, look and search, or also create and change."),
|
|
2128
|
+
shell: z
|
|
2129
|
+
.boolean()
|
|
2130
|
+
.default(true)
|
|
2131
|
+
.describe("Whether it may run commands, and with them the terminals, the test runs and every tool on the image. The switch the strength of the others depends on."),
|
|
2132
|
+
code: z
|
|
2133
|
+
.boolean()
|
|
2134
|
+
.default(true)
|
|
2135
|
+
.describe("Whether it may write and run a script rather than a command line. Its fence is real where the shell's is not: reads and writes follow the files answer, and it can start no other program unless commands are allowed too. The one stated gap is that the fence cannot cut the network."),
|
|
2136
|
+
web: z.boolean().default(true).describe("Whether it may fetch a page or run a search."),
|
|
1293
2137
|
browser: z.boolean().default(true),
|
|
1294
2138
|
delegate: z.boolean().default(true),
|
|
1295
2139
|
sandbox: z.boolean().default(true),
|
|
@@ -1298,16 +2142,23 @@ export const PersonaPowersSchema = z.object({
|
|
|
1298
2142
|
mcp: z.array(entryId).max(50).optional(),
|
|
1299
2143
|
});
|
|
1300
2144
|
export const PersonaWorkspaceSchema = z.object({
|
|
1301
|
-
startIn: z.string().max(200).optional(),
|
|
1302
|
-
folders: z.array(z.string().min(1)).max(50).optional(),
|
|
2145
|
+
startIn: z.string().max(200).optional().describe("Which folder a conversation opens in."),
|
|
2146
|
+
folders: z.array(z.string().min(1)).max(50).optional().describe("Which folders it may touch at all. Absent means the whole workspace."),
|
|
1303
2147
|
});
|
|
1304
2148
|
export const PersonaSchema = z.object({
|
|
1305
|
-
id: entryId,
|
|
1306
|
-
label: z.string().max(60).optional(),
|
|
1307
|
-
capabilities: z
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
2149
|
+
id: entryId.describe("The persona's id."),
|
|
2150
|
+
label: z.string().max(60).optional().describe("What to call it on screen. Absent falls back to the id, which somebody chose anyway."),
|
|
2151
|
+
capabilities: z
|
|
2152
|
+
.array(entryId)
|
|
2153
|
+
.max(50)
|
|
2154
|
+
.describe("Which connected accounts are its hands. Named individually rather than by site, because two accounts on one site is the whole problem this solves. Naming one that is not connected yet is not an error: it is a card describing an account this sandbox has still to sign into."),
|
|
2155
|
+
repos: z
|
|
2156
|
+
.array(z.string().min(1))
|
|
2157
|
+
.max(50)
|
|
2158
|
+
.optional()
|
|
2159
|
+
.describe("Which repositories prefer this persona, so a conversation opened on one starts with the right choice already made. A preference rather than a fence."),
|
|
2160
|
+
powers: PersonaPowersSchema.optional().describe("What a conversation wearing it may do. Absent means the full toolbox, so a card written before this existed behaves exactly as it did."),
|
|
2161
|
+
workspace: PersonaWorkspaceSchema.optional().describe("Where it works. Absent means the whole workspace."),
|
|
1311
2162
|
systemPromptMode: SystemPromptModeSchema.optional(),
|
|
1312
2163
|
});
|
|
1313
2164
|
export const FRONT_DESK_PERSONA = "front-desk";
|
|
@@ -1336,49 +2187,82 @@ export const personaBounds = (persona) => {
|
|
|
1336
2187
|
].filter(Boolean).length;
|
|
1337
2188
|
return limits === 0 ? "Full powers" : `${limits} limit${limits === 1 ? "" : "s"}`;
|
|
1338
2189
|
};
|
|
1339
|
-
export const PersonaIdParamSchema = z.object({ id: entryId });
|
|
2190
|
+
export const PersonaIdParamSchema = z.object({ id: entryId.describe("Which persona.") });
|
|
1340
2191
|
export const PersonasListSchema = z.object({
|
|
1341
|
-
personas: z.array(PersonaSchema),
|
|
1342
|
-
connected: z
|
|
2192
|
+
personas: z.array(PersonaSchema).describe("The characters an agent can wear."),
|
|
2193
|
+
connected: z
|
|
2194
|
+
.array(z.string())
|
|
2195
|
+
.describe("Which accounts are actually connected right now, so a persona naming one that has since been disconnected can be shown as broken rather than as working."),
|
|
1343
2196
|
});
|
|
1344
2197
|
export const PersonaKitSchema = z.object({
|
|
1345
|
-
prompt: z
|
|
1346
|
-
|
|
2198
|
+
prompt: z
|
|
2199
|
+
.string()
|
|
2200
|
+
.describe("What this persona is told, on top of everything else. Empty means it simply follows the sandbox's own instructions."),
|
|
2201
|
+
skills: z
|
|
2202
|
+
.array(z.object({
|
|
2203
|
+
name: z.string().describe("The skill's name."),
|
|
2204
|
+
description: z.string().describe("What it is for."),
|
|
2205
|
+
}))
|
|
2206
|
+
.describe("Skills only this persona's conversations can reach. A different question from what the agent knows generally, with a different answer."),
|
|
2207
|
+
});
|
|
2208
|
+
export const PersonaPromptSchema = PersonaIdParamSchema.extend({
|
|
2209
|
+
prompt: z
|
|
2210
|
+
.string()
|
|
2211
|
+
.max(20000)
|
|
2212
|
+
.describe("What to tell this persona. Sending an empty one removes it entirely rather than storing a blank, so the persona falls back to the sandbox's own instructions."),
|
|
1347
2213
|
});
|
|
1348
|
-
export const PersonaPromptSchema = PersonaIdParamSchema.extend({ prompt: z.string().max(20000) });
|
|
1349
2214
|
export const PersonaSkillSchema = PersonaIdParamSchema.extend(SkillDraftSchema.shape);
|
|
1350
|
-
export const PersonaSkillNameSchema = PersonaIdParamSchema.extend({ name: SkillNameSchema });
|
|
1351
|
-
export const PersonaSkillBodySchema = z.object({
|
|
2215
|
+
export const PersonaSkillNameSchema = PersonaIdParamSchema.extend({ name: SkillNameSchema.describe("Which skill.") });
|
|
2216
|
+
export const PersonaSkillBodySchema = z.object({
|
|
2217
|
+
name: z.string().describe("The skill's name."),
|
|
2218
|
+
description: z.string().describe("What it is for."),
|
|
2219
|
+
body: z.string().describe("The skill itself, in full."),
|
|
2220
|
+
});
|
|
1352
2221
|
export const CapabilityStatusSchema = z.object({
|
|
1353
|
-
state: CapabilityStateSchema,
|
|
1354
|
-
detail: z.string().optional(),
|
|
1355
|
-
code: z.string().optional(),
|
|
2222
|
+
state: CapabilityStateSchema.describe("Whether it is live, still coming up, broken, or switched off."),
|
|
2223
|
+
detail: z.string().optional().describe("What is wrong, in words a person can act on."),
|
|
2224
|
+
code: z.string().optional().describe("A short marker for that reason, for anything deciding what to do about it."),
|
|
1356
2225
|
});
|
|
1357
2226
|
export const CapabilitySummarySchema = z.object({
|
|
1358
|
-
id: z.string(),
|
|
1359
|
-
kind: CapabilityKindSchema,
|
|
1360
|
-
status: CapabilityStatusSchema,
|
|
1361
|
-
config: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])),
|
|
1362
|
-
secrets: z
|
|
2227
|
+
id: z.string().describe("The connection's id."),
|
|
2228
|
+
kind: CapabilityKindSchema.describe("What sort of thing it is."),
|
|
2229
|
+
status: CapabilityStatusSchema.describe("Whether it is working."),
|
|
2230
|
+
config: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).describe("Its settings, minus anything secret."),
|
|
2231
|
+
secrets: z
|
|
2232
|
+
.array(z.string())
|
|
2233
|
+
.default([])
|
|
2234
|
+
.describe("Which credentials it holds, by name. The values are on one route only, and it is not this one."),
|
|
1363
2235
|
});
|
|
1364
2236
|
export const CapabilityRecommendationSchema = z.object({
|
|
1365
|
-
card: z.string(),
|
|
1366
|
-
evidence: z
|
|
1367
|
-
|
|
1368
|
-
|
|
2237
|
+
card: z.string().describe("Which connection is being suggested."),
|
|
2238
|
+
evidence: z
|
|
2239
|
+
.string()
|
|
2240
|
+
.describe("What was seen that prompted it: a file, a remote, printed verbatim so the claim can be checked rather than believed."),
|
|
2241
|
+
reason: z.string().describe("The same claim in words, without repeating the evidence into it."),
|
|
2242
|
+
prefill: z
|
|
2243
|
+
.record(z.string(), z.string())
|
|
2244
|
+
.describe("Settings the scan could read, to fill the form so you supply only the credential. Never a secret, even when one is sitting in a checked-in file: the suggestion points at such a file, it does not absorb what is in it."),
|
|
1369
2245
|
});
|
|
1370
2246
|
export const CapabilitiesListSchema = z.object({
|
|
1371
|
-
capabilities: z.array(CapabilitySummarySchema),
|
|
1372
|
-
recommendations: z
|
|
2247
|
+
capabilities: z.array(CapabilitySummarySchema).describe("What this sandbox is connected to."),
|
|
2248
|
+
recommendations: z
|
|
2249
|
+
.array(CapabilityRecommendationSchema)
|
|
2250
|
+
.default([])
|
|
2251
|
+
.describe("Things worth connecting, worked out from what is actually in the workspace rather than from anything you configured. Re-derived on every read, so one whose evidence has moved simply stops being suggested."),
|
|
1373
2252
|
});
|
|
1374
|
-
export const CapabilityIdParamSchema = z.object({ id: z.string() });
|
|
2253
|
+
export const CapabilityIdParamSchema = z.object({ id: z.string().describe("Which connection.") });
|
|
1375
2254
|
export const CapabilityConnectionSchema = z.object({
|
|
1376
|
-
id: z.string(),
|
|
1377
|
-
kind: z.string(),
|
|
1378
|
-
config: z
|
|
2255
|
+
id: z.string().describe("The connection's id."),
|
|
2256
|
+
kind: z.string().describe("What sort of thing it is."),
|
|
2257
|
+
config: z
|
|
2258
|
+
.record(z.string(), z.string())
|
|
2259
|
+
.describe("Its settings exactly as stored, credentials included. The field names are its own kind's, which the caller already knows."),
|
|
2260
|
+
});
|
|
2261
|
+
export const CapabilityCardParamSchema = z.object({ card: z.string().describe("Which suggestion to stop making.") });
|
|
2262
|
+
export const CapabilitySecretInputSchema = z.object({
|
|
2263
|
+
id: z.string().describe("Which connection."),
|
|
2264
|
+
value: z.string().min(1).describe("The new credential. Its other settings are left alone."),
|
|
1379
2265
|
});
|
|
1380
|
-
export const CapabilityCardParamSchema = z.object({ card: z.string() });
|
|
1381
|
-
export const CapabilitySecretInputSchema = z.object({ id: z.string(), value: z.string().min(1) });
|
|
1382
2266
|
export const CapabilityRenameSchema = z.object({
|
|
1383
2267
|
id: z.string(),
|
|
1384
2268
|
to: z
|
|
@@ -1387,8 +2271,13 @@ export const CapabilityRenameSchema = z.object({
|
|
|
1387
2271
|
.max(60)
|
|
1388
2272
|
.regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/),
|
|
1389
2273
|
});
|
|
1390
|
-
export const CapabilityLoginSchema = z.object({ session: z.string() });
|
|
1391
|
-
export const CapabilityOtpSchema = z.object({
|
|
2274
|
+
export const CapabilityLoginSchema = z.object({ session: z.string().describe("The terminal the sign-in is happening in. Attach to it to type.") });
|
|
2275
|
+
export const CapabilityOtpSchema = z.object({
|
|
2276
|
+
code: z.string().describe("The code."),
|
|
2277
|
+
secondsRemaining: z
|
|
2278
|
+
.number()
|
|
2279
|
+
.describe("How long it lasts. Its expiring is what makes handing one to an agent safe, since the seed behind it is never revealed."),
|
|
2280
|
+
});
|
|
1392
2281
|
export const HostFactsSchema = z.object({
|
|
1393
2282
|
os: z.string(),
|
|
1394
2283
|
arch: z.string(),
|
|
@@ -1413,37 +2302,66 @@ export const VpnStateSchema = z.enum([
|
|
|
1413
2302
|
"failed",
|
|
1414
2303
|
]);
|
|
1415
2304
|
export const VpnLinkSchema = z.object({
|
|
1416
|
-
id: z.string(),
|
|
1417
|
-
provider: VpnProviderSchema,
|
|
1418
|
-
state: VpnStateSchema,
|
|
1419
|
-
gateway: z.string().optional(),
|
|
1420
|
-
interface: z.string().optional(),
|
|
1421
|
-
address: z
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
2305
|
+
id: z.string().describe("Which tunnel."),
|
|
2306
|
+
provider: VpnProviderSchema.describe("What kind of tunnel it is."),
|
|
2307
|
+
state: VpnStateSchema.describe("Whether it is up, dialling, resting, failed, or not installable yet because its client needs a rebuild to arrive."),
|
|
2308
|
+
gateway: z.string().optional().describe("What it dials. For display only, and never a credential."),
|
|
2309
|
+
interface: z.string().optional().describe("The network interface carrying it, once one exists."),
|
|
2310
|
+
address: z
|
|
2311
|
+
.string()
|
|
2312
|
+
.optional()
|
|
2313
|
+
.describe("The address the far end gave this sandbox, which is the single most useful answer to whether you are on the VPN."),
|
|
2314
|
+
routes: z
|
|
2315
|
+
.array(z.string())
|
|
2316
|
+
.default([])
|
|
2317
|
+
.describe("What goes through it. Everything, when the range covers the whole internet. Empty until it is up."),
|
|
2318
|
+
dns: z.array(z.string()).default([]).describe("Name servers it pushed, when it pushed any."),
|
|
2319
|
+
since: z.number().optional().describe("When it came up, in milliseconds. Absent unless it is."),
|
|
2320
|
+
autoConnect: z.boolean().describe("Whether it dials itself when the sandbox starts."),
|
|
2321
|
+
detail: z.string().optional().describe("Why it failed, or a note about a healthy one. Never a credential."),
|
|
2322
|
+
});
|
|
2323
|
+
export const VpnListSchema = z.object({
|
|
2324
|
+
links: z
|
|
2325
|
+
.array(VpnLinkSchema)
|
|
2326
|
+
.describe("Every configured tunnel with its live state, read back from the operating system each time rather than remembered."),
|
|
2327
|
+
});
|
|
2328
|
+
export const VpnConnectInputSchema = z.object({
|
|
2329
|
+
id: z.string().describe("Which tunnel to dial."),
|
|
2330
|
+
otp: z
|
|
2331
|
+
.string()
|
|
2332
|
+
.min(1)
|
|
2333
|
+
.optional()
|
|
2334
|
+
.describe("A one-time code, where the gateway wants one. Supplied per dial and never stored; without it such a gateway refuses and says so."),
|
|
2335
|
+
});
|
|
2336
|
+
export const VpnIdParamSchema = z.object({ id: z.string().describe("Which tunnel.") });
|
|
2337
|
+
export const ForticlientImportInputSchema = z.object({
|
|
2338
|
+
xml: z.string().min(1).describe("The exported configuration file, whole. Nothing is stored: it is read and thrown away."),
|
|
1427
2339
|
});
|
|
1428
|
-
export const VpnListSchema = z.object({ links: z.array(VpnLinkSchema) });
|
|
1429
|
-
export const VpnConnectInputSchema = z.object({ id: z.string(), otp: z.string().min(1).optional() });
|
|
1430
|
-
export const VpnIdParamSchema = z.object({ id: z.string() });
|
|
1431
|
-
export const ForticlientImportInputSchema = z.object({ xml: z.string().min(1) });
|
|
1432
2340
|
export const ForticlientConnectionSchema = z.object({
|
|
1433
|
-
id: z.string(),
|
|
1434
|
-
label: z.string(),
|
|
1435
|
-
provider: VpnProviderSchema,
|
|
1436
|
-
server: z.string(),
|
|
1437
|
-
port: z.number(),
|
|
1438
|
-
username: z
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
2341
|
+
id: z.string().describe("The id it would be added under."),
|
|
2342
|
+
label: z.string().describe("Its name as the file has it, so somebody recognises the connection they are picking."),
|
|
2343
|
+
provider: VpnProviderSchema.describe("What kind of tunnel it is."),
|
|
2344
|
+
server: z.string().describe("Where it dials."),
|
|
2345
|
+
port: z.number().describe("On which port."),
|
|
2346
|
+
username: z
|
|
2347
|
+
.string()
|
|
2348
|
+
.optional()
|
|
2349
|
+
.describe("The username, but only when the file stored it in the clear. An encrypted one is dropped rather than guessed at."),
|
|
2350
|
+
description: z.string().optional().describe("Whatever the file said about it."),
|
|
2351
|
+
localId: z.string().optional().describe("An identity some tunnel types need, when the file stored it readably."),
|
|
2352
|
+
aggressive: z.boolean().optional().describe("Which negotiation mode it used."),
|
|
2353
|
+
pfs: z.boolean().optional().describe("Whether it asked for forward secrecy."),
|
|
2354
|
+
dhGroup: z
|
|
2355
|
+
.string()
|
|
2356
|
+
.optional()
|
|
2357
|
+
.describe("Which key-exchange group it used. Together with the setting above, this is what decides whether the connection can complete at all."),
|
|
2358
|
+
needs: z
|
|
2359
|
+
.array(z.string())
|
|
2360
|
+
.describe("What you still have to type in before it can dial. Always at least the password, because the export wraps credentials in encryption that cannot be undone here."),
|
|
2361
|
+
});
|
|
2362
|
+
export const ForticlientImportSchema = z.object({
|
|
2363
|
+
connections: z.array(ForticlientConnectionSchema).describe("The connections found in the file, ready to be added one at a time."),
|
|
2364
|
+
});
|
|
1447
2365
|
export const ExitStateSchema = z.enum([
|
|
1448
2366
|
"up",
|
|
1449
2367
|
"starting",
|
|
@@ -1452,35 +2370,50 @@ export const ExitStateSchema = z.enum([
|
|
|
1452
2370
|
"failed",
|
|
1453
2371
|
]);
|
|
1454
2372
|
export const ExitObservationSchema = z.object({
|
|
1455
|
-
ip: z.string(),
|
|
1456
|
-
country: z
|
|
1457
|
-
|
|
2373
|
+
ip: z.string().describe("The address the world sees, looked up through the exit's own proxy rather than assumed."),
|
|
2374
|
+
country: z
|
|
2375
|
+
.string()
|
|
2376
|
+
.optional()
|
|
2377
|
+
.describe("Which country that address is in. Absent when the lookup gave an address and no country, in which case a switch is judged on the address having changed instead."),
|
|
2378
|
+
countryName: z.string().optional().describe("That country's name, spelled out."),
|
|
1458
2379
|
});
|
|
1459
2380
|
export const ExitPointSchema = z.object({
|
|
1460
|
-
country: z.string(),
|
|
1461
|
-
countryName: z.string(),
|
|
1462
|
-
servers: z.number(),
|
|
1463
|
-
share: z
|
|
2381
|
+
country: z.string().describe("The country's code."),
|
|
2382
|
+
countryName: z.string().describe("Its name, spelled out."),
|
|
2383
|
+
servers: z.number().describe("How many servers this provider has there."),
|
|
2384
|
+
share: z
|
|
2385
|
+
.number()
|
|
2386
|
+
.optional()
|
|
2387
|
+
.describe("How much of the provider's actual capacity is there, from zero to one. This is what a list should be sorted by: a third of the countries on offer are one overloaded machine behind a flag, and a count of servers would rank them first."),
|
|
1464
2388
|
});
|
|
1465
2389
|
export const ExitCountriesSchema = z.object({
|
|
1466
|
-
countries: z.array(ExitPointSchema),
|
|
1467
|
-
live: z
|
|
2390
|
+
countries: z.array(ExitPointSchema).describe("Where this exit can put you, best-supplied first."),
|
|
2391
|
+
live: z
|
|
2392
|
+
.boolean()
|
|
2393
|
+
.describe("Whether the provider answered, or this came from a built-in list. Said out loud rather than presenting an old list as current."),
|
|
1468
2394
|
});
|
|
1469
2395
|
export const ExitLinkSchema = z.object({
|
|
1470
|
-
id: z.string(),
|
|
1471
|
-
provider: ExitProviderSchema,
|
|
1472
|
-
state: ExitStateSchema,
|
|
1473
|
-
proxy: z
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
2396
|
+
id: z.string().describe("Which exit."),
|
|
2397
|
+
provider: ExitProviderSchema.describe("What it runs on."),
|
|
2398
|
+
state: ExitStateSchema.describe("Whether it is carrying traffic, coming up, resting, failed, or not installable yet because its client needs a rebuild to arrive."),
|
|
2399
|
+
proxy: z
|
|
2400
|
+
.string()
|
|
2401
|
+
.describe("Where to point traffic that should go through it. Fixed per exit and unchanged by a country switch, which is what lets a long job move country halfway through without reconfiguring anything."),
|
|
2402
|
+
country: z.string().optional().describe("Where it was asked to come out. Absent means the provider chose."),
|
|
2403
|
+
observedCountry: z
|
|
2404
|
+
.string()
|
|
2405
|
+
.optional()
|
|
2406
|
+
.describe("Where it actually comes out, as last checked. Kept separate from what was asked for, because those two disagreeing is the most useful fault signal this whole feature has."),
|
|
2407
|
+
ip: z.string().optional().describe("The address behind that observation."),
|
|
2408
|
+
checkedAt: z.number().optional().describe("When that was checked, in milliseconds, so an old reading can be shown as old."),
|
|
2409
|
+
interface: z.string().optional().describe("The network interface, for the kinds that have one."),
|
|
2410
|
+
since: z.number().optional().describe("When it came up, in milliseconds."),
|
|
2411
|
+
autoStart: z.boolean().describe("Whether it starts itself when the sandbox does."),
|
|
2412
|
+
detail: z.string().optional().describe("Why it failed, or a note about a healthy one."),
|
|
2413
|
+
});
|
|
2414
|
+
export const ExitListSchema = z.object({
|
|
2415
|
+
links: z.array(ExitLinkSchema).describe("Every configured exit, with where it was asked to come out and where it actually does."),
|
|
1482
2416
|
});
|
|
1483
|
-
export const ExitListSchema = z.object({ links: z.array(ExitLinkSchema) });
|
|
1484
2417
|
export const TOR_EXIT_COUNTRIES = [
|
|
1485
2418
|
{ country: "NL", countryName: "Netherlands", servers: 607, share: 0.304 },
|
|
1486
2419
|
{ country: "DE", countryName: "Germany", servers: 415, share: 0.242 },
|
|
@@ -1514,10 +2447,25 @@ export const VPNGATE_EXIT_COUNTRIES = [
|
|
|
1514
2447
|
{ country: "CN", countryName: "China", servers: 1, share: 0.01 },
|
|
1515
2448
|
{ country: "BY", countryName: "Belarus", servers: 1, share: 0.01 },
|
|
1516
2449
|
];
|
|
1517
|
-
export const ExitIdParamSchema = z.object({ id: z.string() });
|
|
1518
|
-
export const ExitUseInputSchema = z.object({
|
|
1519
|
-
|
|
1520
|
-
|
|
2450
|
+
export const ExitIdParamSchema = z.object({ id: z.string().describe("Which exit.") });
|
|
2451
|
+
export const ExitUseInputSchema = z.object({
|
|
2452
|
+
id: z.string().describe("Which exit."),
|
|
2453
|
+
country: CountryCodeSchema.optional().describe("Where to come out. Leaving it out means letting the provider choose, so clearing a country is something you can actually say rather than only setting one."),
|
|
2454
|
+
});
|
|
2455
|
+
export const MarketplaceRequestSchema = z.object({
|
|
2456
|
+
url: z.url().describe("The registry to read."),
|
|
2457
|
+
token: z
|
|
2458
|
+
.string()
|
|
2459
|
+
.min(1)
|
|
2460
|
+
.optional()
|
|
2461
|
+
.describe("A credential for a private one. Sent as a body rather than in the address, so it never lands in a log."),
|
|
2462
|
+
});
|
|
2463
|
+
export const MarketplaceSchema = z.object({
|
|
2464
|
+
name: z.string().describe("What the registry calls itself."),
|
|
2465
|
+
plugins: z
|
|
2466
|
+
.array(RegistryEntrySchema)
|
|
2467
|
+
.describe("What it lists, each with the curated decision, the resolved pointer and what a scan found upstream."),
|
|
2468
|
+
});
|
|
1521
2469
|
const extensionId = z
|
|
1522
2470
|
.string()
|
|
1523
2471
|
.min(1)
|
|
@@ -1528,100 +2476,189 @@ export const ExtensionUpdatePolicySchema = z.object({
|
|
|
1528
2476
|
advisories: z.enum(["auto-disable", "notify"]),
|
|
1529
2477
|
});
|
|
1530
2478
|
export const ExtensionUpdateSchema = z.object({
|
|
1531
|
-
ref: z.string(),
|
|
1532
|
-
version: z.string().optional(),
|
|
1533
|
-
url: z.string(),
|
|
1534
|
-
path: z.string().optional(),
|
|
1535
|
-
trust: z.enum(["verified", "listed"]),
|
|
1536
|
-
securityFix: z
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
2479
|
+
ref: z.string().describe("The commit being offered."),
|
|
2480
|
+
version: z.string().optional().describe("What it calls itself."),
|
|
2481
|
+
url: z.string().describe("Where it comes from."),
|
|
2482
|
+
path: z.string().optional().describe("Where inside that repository it lives."),
|
|
2483
|
+
trust: z.enum(["verified", "listed"]).describe("Whether anybody vouched for it, or it is merely listed."),
|
|
2484
|
+
securityFix: z
|
|
2485
|
+
.boolean()
|
|
2486
|
+
.optional()
|
|
2487
|
+
.describe("This release fixes a security problem in earlier ones, so here the old version is the dangerous one."),
|
|
2488
|
+
registry: z.string().describe("Which registry said so."),
|
|
2489
|
+
at: z.string().describe("When it was published."),
|
|
2490
|
+
needsReview: z
|
|
2491
|
+
.string()
|
|
2492
|
+
.optional()
|
|
2493
|
+
.describe("Why this one was not taken automatically and is asking for a person instead: it wants more than it used to, or nobody has vouched for it."),
|
|
2494
|
+
review: z
|
|
2495
|
+
.object({
|
|
2496
|
+
conversationId: z.string().describe("Where to read what it found."),
|
|
2497
|
+
at: z.string().describe("When it looked."),
|
|
2498
|
+
})
|
|
2499
|
+
.optional()
|
|
2500
|
+
.describe("An agent has already read the difference between what is installed and this, so the card can link to what it found rather than offer to start looking."),
|
|
1541
2501
|
});
|
|
1542
2502
|
export const ExtensionAdvisorySchema = z.object({
|
|
1543
|
-
reason: z
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
2503
|
+
reason: z
|
|
2504
|
+
.string()
|
|
2505
|
+
.describe("Why the registry pulled the listing, in its own words. Delisting protects people browsing; this record is for the person already running it."),
|
|
2506
|
+
registry: z.string().describe("Which registry said so."),
|
|
2507
|
+
at: z.string().describe("When."),
|
|
2508
|
+
autoDisabled: z.boolean().describe("Whether the sandbox has already switched it off."),
|
|
1547
2509
|
});
|
|
1548
2510
|
export const ExtensionHealthSchema = z.object({
|
|
1549
|
-
state: z
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
2511
|
+
state: z
|
|
2512
|
+
.enum(["watching", "healthy", "unhealthy"])
|
|
2513
|
+
.describe("How it has behaved since the last update. Checks catch broken, not wrong, so for a while after a swap it is simply watched."),
|
|
2514
|
+
detail: z.string().optional().describe("What is going wrong, when something is."),
|
|
2515
|
+
fromRef: z.string().optional().describe("Which version it was updated from, which is what going back would return to."),
|
|
2516
|
+
at: z.string().describe("When the watching started."),
|
|
2517
|
+
autoReverted: z
|
|
2518
|
+
.boolean()
|
|
2519
|
+
.optional()
|
|
2520
|
+
.describe("The update was already rolled back without anybody asking. The record stays rather than pretending the attempt never happened."),
|
|
2521
|
+
});
|
|
2522
|
+
export const PowersDiffSchema = z.object({
|
|
2523
|
+
added: z.array(z.string()).describe("What the new version asks for that the running one does not. The whole point of the comparison."),
|
|
2524
|
+
removed: z.array(z.string()).describe("What it no longer asks for."),
|
|
2525
|
+
unchanged: z.array(z.string()).describe("What stays the same."),
|
|
1554
2526
|
});
|
|
1555
|
-
export const PowersDiffSchema = z.object({ added: z.array(z.string()), removed: z.array(z.string()), unchanged: z.array(z.string()) });
|
|
1556
2527
|
export const ExtensionUpdateActionSchema = z.object({
|
|
1557
|
-
id: extensionId,
|
|
2528
|
+
id: extensionId.describe("Which extension."),
|
|
1558
2529
|
ref: z
|
|
1559
2530
|
.string()
|
|
1560
2531
|
.regex(/^[0-9a-f]{40}$/)
|
|
1561
|
-
.optional()
|
|
2532
|
+
.optional()
|
|
2533
|
+
.describe("Which commit, in full. Leave it out for whatever the last check found, which is what most callers mean."),
|
|
1562
2534
|
});
|
|
1563
2535
|
export const ExtensionUpdatePreviewSchema = z.object({
|
|
1564
|
-
ref: z.string(),
|
|
1565
|
-
version: z.string(),
|
|
1566
|
-
installedVersion: z.string(),
|
|
1567
|
-
engines: z.string(),
|
|
1568
|
-
compatible: z.boolean(),
|
|
1569
|
-
powers: PowersDiffSchema,
|
|
1570
|
-
});
|
|
1571
|
-
export const ExtensionUpdateAppliedSchema = z.object({
|
|
2536
|
+
ref: z.string().describe("The commit this would install."),
|
|
2537
|
+
version: z.string().describe("What that version calls itself."),
|
|
2538
|
+
installedVersion: z.string().describe("What is running now."),
|
|
2539
|
+
engines: z.string().describe("Which sandbox versions the new one says it needs."),
|
|
2540
|
+
compatible: z.boolean().describe("Whether this sandbox is one of them."),
|
|
2541
|
+
powers: PowersDiffSchema.describe("Exactly what the new code asks for that the running one does not. This is what approving an update is approving."),
|
|
2542
|
+
});
|
|
2543
|
+
export const ExtensionUpdateAppliedSchema = z.object({
|
|
2544
|
+
ok: z.literal(true).describe("It went through."),
|
|
2545
|
+
ref: z.string().describe("Which commit is now running."),
|
|
2546
|
+
rebuildNeeded: z
|
|
2547
|
+
.boolean()
|
|
2548
|
+
.optional()
|
|
2549
|
+
.describe("The new version changes what the sandbox image contains, so a one-time rebuild is still pending and the update is not wholly landed yet."),
|
|
2550
|
+
});
|
|
1572
2551
|
export const ExtensionUpdatePolicyInputSchema = z.object({
|
|
1573
|
-
id: extensionId,
|
|
1574
|
-
updates: z
|
|
1575
|
-
|
|
2552
|
+
id: extensionId.describe("Which extension."),
|
|
2553
|
+
updates: z
|
|
2554
|
+
.enum(["notify", "agent", "auto"])
|
|
2555
|
+
.optional()
|
|
2556
|
+
.describe("What to do about a newer version: tell you, have an agent read the difference first, or just take it."),
|
|
2557
|
+
advisories: z.enum(["auto-disable", "notify"]).optional().describe("What to do about a security warning: switch it off at once, or tell you."),
|
|
2558
|
+
});
|
|
2559
|
+
export const ExtensionUpdatesCheckedSchema = z.object({
|
|
2560
|
+
ok: z.literal(true).describe("The check ran."),
|
|
2561
|
+
checkedAt: z.string().describe("When, so a screen can date the answer."),
|
|
1576
2562
|
});
|
|
1577
|
-
export const ExtensionUpdatesCheckedSchema = z.object({ ok: z.literal(true), checkedAt: z.string() });
|
|
1578
2563
|
export const ExtensionSummarySchema = z.object({
|
|
1579
|
-
id: extensionId,
|
|
1580
|
-
manifest: ExtensionManifestSchema,
|
|
1581
|
-
commit: z.string(),
|
|
1582
|
-
source: z
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
2564
|
+
id: extensionId.describe("The extension's id."),
|
|
2565
|
+
manifest: ExtensionManifestSchema.describe("What it declares about itself: what it contributes, what it needs, and what it may reach."),
|
|
2566
|
+
commit: z.string().describe("Exactly which commit is installed."),
|
|
2567
|
+
source: z
|
|
2568
|
+
.enum(["builtin", "installed", "workspace"])
|
|
2569
|
+
.describe("Where the code comes from: baked into the sandbox image and not removable, installed from a repository at a pinned commit, or written in this workspace and edited in place."),
|
|
2570
|
+
enabled: z
|
|
2571
|
+
.boolean()
|
|
2572
|
+
.describe("The owner's switch. A switched-off extension is still listed, which is what makes it switchable back on, but nothing it contributes is wired up."),
|
|
2573
|
+
essential: z
|
|
2574
|
+
.boolean()
|
|
2575
|
+
.optional()
|
|
2576
|
+
.describe("Its switch is fixed on, because it is the only way to see or stop an engine the sandbox runs regardless. Hiding that page would not stop the spending, only your ability to notice it. Declared by the core about its own surfaces, never by an extension about itself, which would be a pack making itself un-removable."),
|
|
2577
|
+
usage: z
|
|
2578
|
+
.record(z.string(), z.object({ calls: z.number().int().nonnegative().describe("How many times."), last: z.string().describe("When, most recently.") }))
|
|
2579
|
+
.optional()
|
|
2580
|
+
.describe("How much of the reach it asked for it has actually used, keyed by what it declared. Absent means never observed doing anything, which is a different claim from uses none of them, and the two have to stay tellable apart: reading either as these permissions are unnecessary turns evidence into a guess with a number on it."),
|
|
1586
2581
|
backend: z
|
|
1587
2582
|
.object({
|
|
1588
|
-
state: z
|
|
1589
|
-
|
|
2583
|
+
state: z
|
|
2584
|
+
.enum(["running", "error", "absent", "incompatible", "starting", "stopped"])
|
|
2585
|
+
.describe("How its server half is doing. Absent means the code is not in this image at all; incompatible means it needs a different sandbox version."),
|
|
2586
|
+
detail: z
|
|
2587
|
+
.string()
|
|
2588
|
+
.optional()
|
|
2589
|
+
.describe("What went wrong, so a backend that failed to start is a sentence rather than an address that answers nothing."),
|
|
1590
2590
|
})
|
|
1591
|
-
.optional()
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
2591
|
+
.optional()
|
|
2592
|
+
.describe("Present only for an extension that ships a server half."),
|
|
2593
|
+
update: ExtensionUpdateSchema.optional().describe("A newer version waiting. All five of these exist only for one installed from a repository: a built-in updates with the image and one written here is edited live."),
|
|
2594
|
+
advisory: ExtensionAdvisorySchema.optional().describe("A security warning about the installed version."),
|
|
2595
|
+
health: ExtensionHealthSchema.optional().describe("How it has behaved since the last update, which is what decides whether that update sticks."),
|
|
2596
|
+
previous: z
|
|
2597
|
+
.object({
|
|
2598
|
+
ref: z.string().describe("The commit that was running before."),
|
|
2599
|
+
version: z.string().optional().describe("What it called itself."),
|
|
2600
|
+
})
|
|
2601
|
+
.optional()
|
|
2602
|
+
.describe("The version kept one step back, which is what going back means."),
|
|
2603
|
+
updatePolicy: ExtensionUpdatePolicySchema.optional().describe("The owner's standing answer for this one: tell me, have an agent look, or just do it."),
|
|
2604
|
+
});
|
|
2605
|
+
export const InvalidWorkspaceExtensionSchema = z.object({
|
|
2606
|
+
dir: z.string().describe("Which folder."),
|
|
2607
|
+
error: z.string().describe("Why it could not be read."),
|
|
1597
2608
|
});
|
|
1598
|
-
export const InvalidWorkspaceExtensionSchema = z.object({ dir: z.string(), error: z.string() });
|
|
1599
2609
|
export const ExtensionsListSchema = z.object({
|
|
1600
|
-
extensions: z.array(ExtensionSummarySchema),
|
|
1601
|
-
invalid: z
|
|
1602
|
-
|
|
2610
|
+
extensions: z.array(ExtensionSummarySchema).describe("What is installed."),
|
|
2611
|
+
invalid: z
|
|
2612
|
+
.array(InvalidWorkspaceExtensionSchema)
|
|
2613
|
+
.describe("Extensions written here that could not be read at all. Listed rather than dropped, because there is no install moment at which to reject a broken one, so this is its only way of saying anything."),
|
|
2614
|
+
updatesCheckedAt: z
|
|
2615
|
+
.string()
|
|
2616
|
+
.optional()
|
|
2617
|
+
.describe("When updates were last looked for. Absent until the first check has run. Sent so a screen can say checked an hour ago rather than presenting staleness as certainty."),
|
|
1603
2618
|
});
|
|
1604
2619
|
export const ExtensionSettingsSchema = z.object({
|
|
1605
|
-
settings: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])),
|
|
1606
|
-
secretsSet: z
|
|
2620
|
+
settings: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).describe("The values, minus anything marked secret."),
|
|
2621
|
+
secretsSet: z
|
|
2622
|
+
.array(z.string())
|
|
2623
|
+
.describe("Which of its secret settings actually hold a value. Names only: the values themselves never come back."),
|
|
1607
2624
|
});
|
|
1608
2625
|
export const ExtensionSettingsInputSchema = z.object({
|
|
1609
|
-
id: z.string(),
|
|
1610
|
-
settings: z
|
|
2626
|
+
id: z.string().describe("Which extension."),
|
|
2627
|
+
settings: z
|
|
2628
|
+
.record(z.string(), z.union([z.string(), z.number(), z.boolean()]))
|
|
2629
|
+
.describe("The values to write. A key the extension never declared is refused rather than quietly stored."),
|
|
2630
|
+
});
|
|
2631
|
+
export const ExtensionEnabledInputSchema = z.object({
|
|
2632
|
+
id: z.string().describe("Which extension."),
|
|
2633
|
+
enabled: z.boolean().describe("On or off."),
|
|
1611
2634
|
});
|
|
1612
|
-
export const ExtensionEnabledInputSchema = z.object({ id: z.string(), enabled: z.boolean() });
|
|
1613
2635
|
export const WorkspaceExtensionCreateSchema = z.object({
|
|
1614
|
-
publisher: z
|
|
1615
|
-
|
|
2636
|
+
publisher: z
|
|
2637
|
+
.string()
|
|
2638
|
+
.regex(/^[a-z0-9][a-z0-9-]*$/)
|
|
2639
|
+
.describe("Who it is by, which together with the name makes its id."),
|
|
2640
|
+
name: z
|
|
2641
|
+
.string()
|
|
2642
|
+
.regex(/^[a-z0-9][a-z0-9-]*$/)
|
|
2643
|
+
.describe("What it is called."),
|
|
2644
|
+
});
|
|
2645
|
+
export const WorkspaceExtensionCreatedSchema = z.object({
|
|
2646
|
+
id: z.string().describe("The id it was given."),
|
|
2647
|
+
dir: z.string().describe("Where its files are, so you can open them."),
|
|
2648
|
+
});
|
|
2649
|
+
export const ExtensionUsageInputSchema = z.object({
|
|
2650
|
+
id: z.string().describe("Which extension."),
|
|
2651
|
+
used: z.record(z.string(), z.number().int().positive()).describe("Which of its declared powers it exercised, and how many times."),
|
|
2652
|
+
});
|
|
2653
|
+
export const ExtensionProcessParamSchema = z.object({
|
|
2654
|
+
id: z.string().describe("Which extension."),
|
|
2655
|
+
name: z.string().describe("Which of its declared processes."),
|
|
1616
2656
|
});
|
|
1617
|
-
export const WorkspaceExtensionCreatedSchema = z.object({ id: z.string(), dir: z.string() });
|
|
1618
|
-
export const ExtensionUsageInputSchema = z.object({ id: z.string(), used: z.record(z.string(), z.number().int().positive()) });
|
|
1619
|
-
export const ExtensionProcessParamSchema = z.object({ id: z.string(), name: z.string() });
|
|
1620
2657
|
export const ExtensionProcessStatusSchema = z.object({
|
|
1621
|
-
name: z.string(),
|
|
1622
|
-
running: z.boolean(),
|
|
1623
|
-
port: z.number().optional(),
|
|
1624
|
-
previewUrl: z.string().optional(),
|
|
2658
|
+
name: z.string().describe("Which process."),
|
|
2659
|
+
running: z.boolean().describe("Whether it is up."),
|
|
2660
|
+
port: z.number().optional().describe("The port it was given."),
|
|
2661
|
+
previewUrl: z.string().optional().describe("Where to open it, when it has an address."),
|
|
1625
2662
|
});
|
|
1626
2663
|
export const WorkspaceEventKindSchema = z.enum(["turn.settled", "agent.landed", "deps.broken", "deps.fixed"]);
|
|
1627
2664
|
export const WorkspaceEventSchema = z.object({
|
|
@@ -1642,26 +2679,56 @@ export const WorkspaceEventSchema = z.object({
|
|
|
1642
2679
|
.optional(),
|
|
1643
2680
|
});
|
|
1644
2681
|
export const TriggerSchema = z.discriminatedUnion("kind", [
|
|
1645
|
-
z.object({ kind: z.literal("schedule"), cron: z.string().min(1) }),
|
|
1646
|
-
z.object({ kind: z.literal("event"), token: z.string().min(1).optional() }),
|
|
1647
2682
|
z.object({
|
|
1648
|
-
kind: z.literal("
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
2683
|
+
kind: z.literal("schedule").describe("On a clock."),
|
|
2684
|
+
cron: z.string().min(1).describe("When, in cron notation."),
|
|
2685
|
+
}),
|
|
2686
|
+
z.object({
|
|
2687
|
+
kind: z.literal("event").describe("When something calls its webhook."),
|
|
2688
|
+
token: z
|
|
2689
|
+
.string()
|
|
2690
|
+
.min(1)
|
|
2691
|
+
.optional()
|
|
2692
|
+
.describe("The credential a caller presents. It is the only one in the exchange, because an outside sender has no identity here."),
|
|
2693
|
+
}),
|
|
2694
|
+
z.object({
|
|
2695
|
+
kind: z.literal("listener").describe("When a message arrives from somewhere outside."),
|
|
2696
|
+
provider: z.string().min(1).describe("Which service to listen to."),
|
|
2697
|
+
channelId: z.string().min(1).optional().describe("Narrow it to one channel or thread."),
|
|
2698
|
+
eventType: z.string().min(1).optional().describe("Narrow it to one kind of event."),
|
|
2699
|
+
mentioned: z.boolean().optional().describe("Only when the agent is actually addressed, rather than on everything said in earshot."),
|
|
2700
|
+
branch: z
|
|
2701
|
+
.string()
|
|
2702
|
+
.min(1)
|
|
2703
|
+
.optional()
|
|
2704
|
+
.describe("Narrow it to one branch, for the sources that have branches. Absent means every branch of the repositories it matches."),
|
|
2705
|
+
allowedOrigins: z.array(z.string()).optional().describe("Which websites may reach the chat widget. Absent or empty admits nobody."),
|
|
2706
|
+
}),
|
|
2707
|
+
z.object({
|
|
2708
|
+
kind: z.literal("workspace").describe("When something happens to the files or the repositories."),
|
|
2709
|
+
event: WorkspaceEventKindSchema.describe("Which happening."),
|
|
2710
|
+
repo: z.string().min(1).optional().describe("Narrow it to one repository. Absent means any of them."),
|
|
1655
2711
|
}),
|
|
1656
|
-
z.object({ kind: z.literal("workspace"), event: WorkspaceEventKindSchema, repo: z.string().min(1).optional() }),
|
|
1657
2712
|
]);
|
|
1658
2713
|
export const WebchatConfigSchema = z.object({
|
|
1659
|
-
access: z
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
2714
|
+
access: z
|
|
2715
|
+
.enum(["public", "google"])
|
|
2716
|
+
.optional()
|
|
2717
|
+
.describe("Who may write to it. Absent means anyone, which is the anonymous support box it looks like."),
|
|
2718
|
+
requireName: z
|
|
2719
|
+
.boolean()
|
|
2720
|
+
.optional()
|
|
2721
|
+
.describe("Ask a visitor for a name first. Cosmetic: the name is typed, so it reaches the model as something a stranger said, never as identity."),
|
|
2722
|
+
antiBot: z
|
|
2723
|
+
.enum(["turnstile", "pow"])
|
|
2724
|
+
.optional()
|
|
2725
|
+
.describe("How to keep bots out: a third-party check that needs the site's own keys, or a puzzle the sandbox sets and the widget solves, so a site with no such account still has something. Absent leaves the site allowlist and the rate limit as the whole boundary."),
|
|
2726
|
+
turnstileSiteKey: z.string().optional().describe("The public half of those keys, which ships to the visitor's browser."),
|
|
2727
|
+
turnstileSecret: z.string().optional().describe("The private half, which the sandbox keeps and the widget never sees."),
|
|
2728
|
+
googleClientId: z
|
|
2729
|
+
.string()
|
|
2730
|
+
.optional()
|
|
2731
|
+
.describe("The site's own sign-in client id. It cannot be ours: a sign-in is only issued to an approved origin, and no single client can list every customer's domain."),
|
|
1665
2732
|
title: z.string().max(80).optional(),
|
|
1666
2733
|
greeting: z.string().max(500).optional(),
|
|
1667
2734
|
accent: z
|
|
@@ -1700,40 +2767,64 @@ export const WebchatMessageSchema = z.object({
|
|
|
1700
2767
|
.optional(),
|
|
1701
2768
|
});
|
|
1702
2769
|
export const AutomationSchema = z.object({
|
|
1703
|
-
id: entryId,
|
|
1704
|
-
trigger: TriggerSchema,
|
|
1705
|
-
guard: z
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
2770
|
+
id: entryId.describe("The automation's id."),
|
|
2771
|
+
trigger: TriggerSchema.describe("What sets it off: a schedule, an event in the workspace, a message arriving from outside, or a webhook."),
|
|
2772
|
+
guard: z
|
|
2773
|
+
.string()
|
|
2774
|
+
.min(1)
|
|
2775
|
+
.optional()
|
|
2776
|
+
.describe("A command run before the wake that decides whether there is anything to do. Skipped by the guard is often the most useful thing an automation can report."),
|
|
2777
|
+
prompt: z.string().min(1).describe("What the woken agent is told."),
|
|
2778
|
+
webchat: WebchatConfigSchema.optional().describe("Settings for the public chat widget, for an automation that answers visitors."),
|
|
2779
|
+
allowedTools: z
|
|
2780
|
+
.array(z.string().min(1))
|
|
2781
|
+
.optional()
|
|
2782
|
+
.describe("Narrow the woken turn to these tools. For one driven by an outside message this list is the real boundary, because prompt wording is only advice and an empty toolbox is not."),
|
|
2783
|
+
agent: AgentProviderSchema.optional().describe("Which provider serves the wake."),
|
|
2784
|
+
account: z.string().optional().describe("Which account pays for it."),
|
|
2785
|
+
actsAs: entryId.optional().describe("Which persona it speaks as. An unwatched turn naming none reaches no signed-in account at all."),
|
|
2786
|
+
harness: AgentHarnessSchema.optional().describe("Which agentic loop runs it."),
|
|
2787
|
+
model: z.string().optional().describe("Which model runs it."),
|
|
2788
|
+
requireApproval: z.boolean().optional().describe("Hold every fire for a person instead of running it. Only a person can release one of those."),
|
|
2789
|
+
holdForSeconds: z.number().optional().describe("Hold each fire this long before running it anyway, which is a delay rather than a decision."),
|
|
2790
|
+
chore: z
|
|
2791
|
+
.boolean()
|
|
2792
|
+
.optional()
|
|
2793
|
+
.describe("This automation is a maintenance job, which is what files it under chores rather than among ordinary automations."),
|
|
2794
|
+
enabled: z.boolean().describe("Whether it fires at all."),
|
|
1718
2795
|
});
|
|
1719
2796
|
export const AutomationApprovalSchema = z.object({
|
|
1720
|
-
id: entryId,
|
|
1721
|
-
automationId: z.string(),
|
|
1722
|
-
payload: z
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
2797
|
+
id: entryId.describe("This waiting item's own id, which approving and rejecting take."),
|
|
2798
|
+
automationId: z.string().describe("Which automation it came from."),
|
|
2799
|
+
payload: z
|
|
2800
|
+
.string()
|
|
2801
|
+
.optional()
|
|
2802
|
+
.describe("What set it off, kept whole so an approved wake carries the same thing it would have had. Absent for one on a schedule, which carries nothing."),
|
|
2803
|
+
origin: AgentOriginSchema.optional().describe("Where the message came from, kept alongside the payload so an approved wake appears on the board exactly as an automatic one would have."),
|
|
2804
|
+
title: z.string().optional().describe("What the conversation would be called."),
|
|
2805
|
+
conversationId: z
|
|
2806
|
+
.string()
|
|
2807
|
+
.optional()
|
|
2808
|
+
.describe("The thread this belongs to, when it has one, so approving continues that conversation rather than opening a new one. Without it, one visitor's chat becomes a card per approved message and an agent that meets them again every turn."),
|
|
2809
|
+
sessionId: z.string().optional().describe("The provider session that thread last ran on."),
|
|
2810
|
+
createdAt: z.number().describe("When it started waiting, in milliseconds."),
|
|
2811
|
+
autoRunAt: z
|
|
2812
|
+
.number()
|
|
2813
|
+
.optional()
|
|
2814
|
+
.describe("When it goes ahead on its own, in milliseconds, for a hold that is only a delay. Absent for one that genuinely waits on a person."),
|
|
1729
2815
|
});
|
|
1730
2816
|
export const AgentsListSchema = z.object({
|
|
1731
|
-
agents: z.array(AgentSummarySchema),
|
|
1732
|
-
rev: z
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
2817
|
+
agents: z.array(AgentSummarySchema).describe("The conversations."),
|
|
2818
|
+
rev: z
|
|
2819
|
+
.number()
|
|
2820
|
+
.describe("Which version of the fleet this is. The fleet is published as whole snapshots, so without a version a list read before a change but delivered after it would silently undo that change. Drop any list older than the newest you have already applied."),
|
|
2821
|
+
held: z
|
|
2822
|
+
.array(AutomationApprovalSchema)
|
|
2823
|
+
.default([])
|
|
2824
|
+
.describe("Automations waiting at the door for a yes, put alongside the running conversations so needs-you sits beside working rather than on a page nobody opens."),
|
|
2825
|
+
});
|
|
2826
|
+
export const AutomationApprovalsListSchema = z.object({ approvals: z.array(AutomationApprovalSchema).describe("Everything waiting for a yes.") });
|
|
2827
|
+
export const AutomationApprovalIdParamSchema = z.object({ id: z.string().describe("Which waiting item.") });
|
|
1737
2828
|
export const AutomationRunSchema = z.object({
|
|
1738
2829
|
at: z.number(),
|
|
1739
2830
|
outcome: z.enum(["completed", "skipped", "error", "interrupted"]),
|
|
@@ -1790,197 +2881,379 @@ const StepIdSchema = z
|
|
|
1790
2881
|
export const WorkflowHandoffSchema = z.enum(["fresh", "continue"]);
|
|
1791
2882
|
const WORKFLOW_STEPS_MAX = 24;
|
|
1792
2883
|
export const WorkflowStepSchema = z.object({
|
|
1793
|
-
id: StepIdSchema,
|
|
1794
|
-
title: z.string().min(1).max(60),
|
|
1795
|
-
goal: z
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
2884
|
+
id: StepIdSchema.describe("This step's own name, which other steps use to say they wait on it."),
|
|
2885
|
+
title: z.string().min(1).max(60).describe("What to call it on screen. Short: the instruction below is where the detail goes."),
|
|
2886
|
+
goal: z
|
|
2887
|
+
.string()
|
|
2888
|
+
.min(1)
|
|
2889
|
+
.optional()
|
|
2890
|
+
.describe("What done means for this step, in your words. It is what the step is judged against, and a different sentence from what it is told to do."),
|
|
2891
|
+
prompt: z
|
|
2892
|
+
.string()
|
|
2893
|
+
.min(1)
|
|
2894
|
+
.optional()
|
|
2895
|
+
.describe("What the step is told to do. The goal is the suite is green; this is run the tests, take the top failure, fix it. Leaving it out hands over the run's own request untouched, which is right for a step whose whole job is do what was asked."),
|
|
2896
|
+
needs: z
|
|
2897
|
+
.array(StepIdSchema)
|
|
2898
|
+
.describe("Which steps must finish first. Empty means it starts when the run does. Naming a step that does not exist, or a loop between steps, is refused when the workflow is saved."),
|
|
2899
|
+
handoff: WorkflowHandoffSchema.describe("How it meets what came before: a fresh conversation handed the previous step's result, or the same conversation carried on."),
|
|
2900
|
+
output: LoopOutputSchema.describe("What it has to produce for the step to count."),
|
|
2901
|
+
checks: z.array(LoopCheckSchema).describe("What has to pass before it counts as done."),
|
|
2902
|
+
context: LoopContextSchema.describe("How the step's own repeats meet each other. A long-running step wants to start clean each round; a short polish-this step wants to carry on."),
|
|
2903
|
+
maxSpendUsd: z
|
|
2904
|
+
.number()
|
|
2905
|
+
.positive()
|
|
2906
|
+
.optional()
|
|
2907
|
+
.describe("A ceiling on what this step may spend. The one resource that cannot be recovered after an unattended fan-out, which is why it is here and iteration limits are not. Absent is uncapped."),
|
|
2908
|
+
agent: AgentProviderSchema.optional().describe("Which provider runs it."),
|
|
2909
|
+
harness: AgentHarnessSchema.optional().describe("Which agentic loop runs it."),
|
|
2910
|
+
account: z.string().optional().describe("Which account pays for it."),
|
|
2911
|
+
model: z.string().optional().describe("Which model runs it."),
|
|
2912
|
+
actsAs: entryId
|
|
2913
|
+
.optional()
|
|
2914
|
+
.describe("Which persona it acts as. Unpinned, a step gets the strict unwatched default: every tool, and no signed-in accounts at all. Pinning one is how a release check gets a voice, a folder to work in, or the single account it may post from."),
|
|
1808
2915
|
});
|
|
1809
2916
|
export const WorkflowGateSchema = z.object({
|
|
1810
|
-
step: StepIdSchema,
|
|
1811
|
-
field: z
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
2917
|
+
step: StepIdSchema.describe("Which step's answer carries the decision. Usually a last step that weighs up the ones before it, though nothing requires that."),
|
|
2918
|
+
field: z
|
|
2919
|
+
.string()
|
|
2920
|
+
.min(1)
|
|
2921
|
+
.describe("Which of that step's declared answers to read. A declared field is the one part of a step's answer that was checked rather than fished out of prose, which is the whole rule here. Checked when the workflow is saved."),
|
|
2922
|
+
pass: z
|
|
2923
|
+
.array(z.string().min(1))
|
|
2924
|
+
.min(1)
|
|
2925
|
+
.describe("Which values mean ship it. Everything else fails. A list of what passes rather than what fails, because a step answering mostly-pass or pass-with-notes must not ship, and this gets that right without anybody having had to enumerate the ways a model can hedge."),
|
|
2926
|
+
token: z
|
|
2927
|
+
.string()
|
|
2928
|
+
.optional()
|
|
2929
|
+
.describe("The credential the calling pipeline presents. It is the only one in the exchange, because a build runner has no identity of its own here."),
|
|
2930
|
+
dailyMax: z
|
|
2931
|
+
.number()
|
|
2932
|
+
.int()
|
|
2933
|
+
.positive()
|
|
2934
|
+
.optional()
|
|
2935
|
+
.describe("How many runs a day, across every caller. A gate is a paid door with nobody in the loop: one wired into a push-triggered pipeline is a fan-out of conversations per commit. Absent is a small default rather than unlimited."),
|
|
1815
2936
|
});
|
|
1816
2937
|
export const GATE_DAILY_MAX_DEFAULT = 20;
|
|
1817
2938
|
export const GateOutcomeSchema = z.enum(["pass", "fail", "blocked"]);
|
|
1818
2939
|
export const GateVerdictSchema = z.object({
|
|
1819
|
-
outcome: GateOutcomeSchema,
|
|
1820
|
-
reason: z.string(),
|
|
1821
|
-
runId: z.string(),
|
|
1822
|
-
value: z
|
|
2940
|
+
outcome: GateOutcomeSchema.describe("Ship it, do not, or we could not tell. That third answer exists because could not reach a judgement is not the product is broken: a gate that reported its own outages as failures is one a team switches off, so it should be the honest answer far more often than the convenient one, and it means a neutral build rather than a red one."),
|
|
2941
|
+
reason: z.string().describe("Why, in one line. Realistically the only part of this a build log will ever show."),
|
|
2942
|
+
runId: z.string().describe("The run behind the verdict, so somebody can go and read it."),
|
|
2943
|
+
value: z
|
|
2944
|
+
.string()
|
|
2945
|
+
.optional()
|
|
2946
|
+
.describe("What the step actually answered. Absent when there was nothing to read, which is most of the could-not-tell cases."),
|
|
1823
2947
|
});
|
|
1824
2948
|
export const WorkflowSchema = z.object({
|
|
1825
|
-
id: entryId,
|
|
1826
|
-
name: z.string().min(1).max(80),
|
|
1827
|
-
description: z.string().max(400).optional(),
|
|
1828
|
-
steps: z
|
|
1829
|
-
|
|
1830
|
-
|
|
2949
|
+
id: entryId.describe("The workflow's id."),
|
|
2950
|
+
name: z.string().min(1).max(80).describe("What to call it."),
|
|
2951
|
+
description: z.string().max(400).optional().describe("What it is for."),
|
|
2952
|
+
steps: z
|
|
2953
|
+
.array(WorkflowStepSchema)
|
|
2954
|
+
.min(1)
|
|
2955
|
+
.max(WORKFLOW_STEPS_MAX)
|
|
2956
|
+
.describe("The steps, each with what it waits on. Every one runs in its own private copy of the repos, always, because parallel steps sharing a tree collide."),
|
|
2957
|
+
gate: WorkflowGateSchema.optional().describe("Present means a machine can run this design and get a ship-it answer back. Absent means an ordinary workflow, started by a person, with no outside door onto it at all."),
|
|
2958
|
+
maxParallel: z
|
|
2959
|
+
.number()
|
|
2960
|
+
.int()
|
|
2961
|
+
.min(1)
|
|
2962
|
+
.max(8)
|
|
2963
|
+
.describe("How many steps may run at once. Bounded, because a fan-out of twelve is twelve model sessions, twelve working copies and twelve times the burn rate, on one machine."),
|
|
1831
2964
|
});
|
|
1832
2965
|
export const WorkflowStepStateSchema = z.enum(["pending", "running", "done", "failed", "skipped", "stopped"]);
|
|
1833
2966
|
export const WorkflowStepRunSchema = z.object({
|
|
1834
|
-
stepId: StepIdSchema,
|
|
1835
|
-
state: WorkflowStepStateSchema,
|
|
1836
|
-
conversationId: z
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
2967
|
+
stepId: StepIdSchema.describe("Which step this is."),
|
|
2968
|
+
state: WorkflowStepStateSchema.describe("How it went. Skipped carries what the others cannot: it never ran, because something it was waiting on did not finish. That is why a failed run shows one red step and a trail of grey ones."),
|
|
2969
|
+
conversationId: z
|
|
2970
|
+
.string()
|
|
2971
|
+
.describe("The conversation it ran on, and the way from a node on the graph to a real record. Shared with the step before it when they were chained, which is what makes those two one card."),
|
|
2972
|
+
startedAt: z.number().optional().describe("When it began, in milliseconds."),
|
|
2973
|
+
endedAt: z.number().optional().describe("When it ended, in milliseconds."),
|
|
2974
|
+
iterations: z.number().int().min(0).describe("How many rounds it took."),
|
|
2975
|
+
costUsd: z.number().optional().describe("What it cost, in dollars."),
|
|
2976
|
+
loopState: LoopStateSchema.optional().describe("How its repeating ended. Out of rounds and stuck both come out as a failed step, and the difference between them is the difference between give it more room and more room will not help."),
|
|
2977
|
+
detail: z.string().optional().describe("What went wrong, when something did."),
|
|
2978
|
+
document: LoopDocumentSchema.optional().describe("What it produced, once it has produced something that passes its own declared shape. This is what the steps after it are handed."),
|
|
2979
|
+
report: z
|
|
2980
|
+
.string()
|
|
2981
|
+
.optional()
|
|
2982
|
+
.describe("The start of its closing words. Bounded, so a long answer is not silently cut down to its last few thousand characters and the record stays a sensible size."),
|
|
2983
|
+
reportPath: z
|
|
2984
|
+
.string()
|
|
2985
|
+
.optional()
|
|
2986
|
+
.describe("Where the whole answer is, as a workspace path. Every step can read it, so a long handoff need not be copied into anybody's prompt."),
|
|
1846
2987
|
});
|
|
1847
2988
|
export const WorkflowRunStateSchema = z.enum(["running", "done", "failed", "stopped", "overspent", "error"]);
|
|
1848
2989
|
export const WorkflowRunSchema = z.object({
|
|
1849
|
-
runId: z.string().min(1),
|
|
1850
|
-
workflow: WorkflowSchema,
|
|
1851
|
-
repos: z
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
2990
|
+
runId: z.string().min(1).describe("This run's id."),
|
|
2991
|
+
workflow: WorkflowSchema.describe("The design as it stood when the run started, copied rather than looked up. The run has to keep showing the graph it actually ran, not the one edited twice since, and a run of a deleted workflow has to stay readable."),
|
|
2992
|
+
repos: z
|
|
2993
|
+
.array(RepoBaseSchema)
|
|
2994
|
+
.min(1)
|
|
2995
|
+
.max(50)
|
|
2996
|
+
.describe("The workspace as this run began, one exact commit per repository. Every step branches from these, even if the shared tree moves while a wide fan-out is still opening its copies, so the steps can be compared with each other afterwards."),
|
|
2997
|
+
request: z
|
|
2998
|
+
.string()
|
|
2999
|
+
.optional()
|
|
3000
|
+
.describe("What this run was asked to do, handed to every step on top of its own instructions. It is what makes one saved design worth keeping: two models, one task is a shape, and the task is different every time. Absent for a run started with nowhere to type one."),
|
|
3001
|
+
state: WorkflowRunStateSchema.describe("How the run is going. Finished means every step that ran got there; a run with skipped steps counts as failed, because a graph that never reached its end did not do what it was asked whatever the survivors managed."),
|
|
3002
|
+
startedAt: z.number().describe("When it began, in milliseconds."),
|
|
3003
|
+
endedAt: z.number().optional().describe("When it ended, in milliseconds."),
|
|
3004
|
+
resumed: z.number().int().min(0).describe("How many times the sandbox restarted under it and picked it back up."),
|
|
3005
|
+
detail: z.string().optional().describe("What went wrong, when something did."),
|
|
3006
|
+
steps: z
|
|
3007
|
+
.array(WorkflowStepRunSchema)
|
|
3008
|
+
.describe("One entry per step, in the design's own order. Every one is written down as waiting when the run starts, so the picture is complete from the first frame and a missing step never has to mean two things."),
|
|
3009
|
+
archivedAt: z
|
|
3010
|
+
.number()
|
|
3011
|
+
.optional()
|
|
3012
|
+
.describe("When it was put away, in milliseconds. The record stays readable and every step's branch, transcript and counters are untouched. Its conversations are put away with it, and brought back with it. Absent means live on the board."),
|
|
3013
|
+
});
|
|
3014
|
+
export const WorkflowSummarySchema = WorkflowSchema.extend({ runs: z.array(WorkflowRunSchema).describe("Its runs, newest first.") });
|
|
3015
|
+
export const WorkflowsListSchema = z.object({ workflows: z.array(WorkflowSummarySchema).describe("Every saved design with its own run history.") });
|
|
3016
|
+
export const WorkflowRunsListSchema = z.object({
|
|
3017
|
+
runs: z.array(WorkflowRunSchema).describe("Every run across every workflow, newest first, including runs of workflows since deleted."),
|
|
3018
|
+
});
|
|
3019
|
+
export const WorkflowIdParamSchema = z.object({ id: z.string().describe("Which workflow.") });
|
|
3020
|
+
export const WorkflowRunIdParamSchema = z.object({ runId: z.string().describe("Which run.") });
|
|
3021
|
+
export const WorkflowRunStartSchema = WorkflowIdParamSchema.extend({
|
|
3022
|
+
request: z
|
|
3023
|
+
.string()
|
|
3024
|
+
.min(1)
|
|
3025
|
+
.max(20_000)
|
|
3026
|
+
.optional()
|
|
3027
|
+
.describe("What to point it at. Optional, because a design whose steps already say what they want is complete on its own; only one written as a shape needs today's sentence."),
|
|
3028
|
+
});
|
|
3029
|
+
export const WorkflowSaveSchema = z.object({
|
|
3030
|
+
workflow: WorkflowSchema.describe("The design to write."),
|
|
3031
|
+
create: z
|
|
3032
|
+
.boolean()
|
|
3033
|
+
.describe("Whether you mean to make a new one or replace an existing one. Said outright rather than inferred, so an id that happens to collide is a refusal instead of one saved design quietly overwriting another."),
|
|
3034
|
+
});
|
|
1868
3035
|
export const CiHostSchema = z.enum(["github", "gitlab"]);
|
|
1869
3036
|
export const PipelineStatusSchema = z.enum(["running", "success", "failed", "canceled", "skipped"]);
|
|
1870
3037
|
export const PipelineRunSchema = z.object({
|
|
1871
|
-
repo: z.string(),
|
|
1872
|
-
host: CiHostSchema,
|
|
1873
|
-
project: z.string(),
|
|
1874
|
-
runId: z.number(),
|
|
1875
|
-
title: z
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
3038
|
+
repo: z.string().describe("Which workspace repository it belongs to."),
|
|
3039
|
+
host: CiHostSchema.describe("Which forge is running it."),
|
|
3040
|
+
project: z.string().describe("The project there, as that forge names it."),
|
|
3041
|
+
runId: z.number().describe("The forge's own id for the run, which is what re-running and cancelling take."),
|
|
3042
|
+
title: z
|
|
3043
|
+
.string()
|
|
3044
|
+
.optional()
|
|
3045
|
+
.describe("The run's headline, usually the commit subject or the pull request's title. Absent means falling back to the branch and commit."),
|
|
3046
|
+
authorName: z.string().optional().describe("Who the forge credits for setting it off."),
|
|
3047
|
+
authorAvatarUrl: z.string().optional().describe("Their picture, hosted by the forge. Absent means drawing their initials instead."),
|
|
3048
|
+
trigger: z
|
|
3049
|
+
.string()
|
|
3050
|
+
.optional()
|
|
3051
|
+
.describe("What set it off, in the forge's own word rather than flattened into a shared vocabulary, because the forge's word is the precise one."),
|
|
3052
|
+
branch: z.string().describe("Which branch."),
|
|
3053
|
+
sha: z.string().describe("Which commit."),
|
|
3054
|
+
status: PipelineStatusSchema.describe("How it is going. Running covers everything still moving, since the only distinction that matters is that against the three ways it can stop."),
|
|
3055
|
+
url: z.string().describe("Its page on the forge."),
|
|
3056
|
+
createdAt: z.number().describe("When it started, in milliseconds."),
|
|
3057
|
+
durationSeconds: z.number().optional().describe("How long it took."),
|
|
3058
|
+
failedJobs: z
|
|
3059
|
+
.array(z.string())
|
|
3060
|
+
.optional()
|
|
3061
|
+
.describe("What broke, by name. Fetched only for failed runs, so that a notification or a screen can say what went wrong rather than just that something did."),
|
|
1886
3062
|
});
|
|
1887
3063
|
export const PipelineJobSchema = z.object({
|
|
1888
|
-
name: z.string(),
|
|
1889
|
-
status: PipelineStatusSchema,
|
|
1890
|
-
stage: z.string().optional(),
|
|
1891
|
-
needs: z
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
3064
|
+
name: z.string().describe("The job's name."),
|
|
3065
|
+
status: PipelineStatusSchema.describe("How it went."),
|
|
3066
|
+
stage: z.string().optional().describe("Which stage it belongs to, where the pipeline groups its jobs that way."),
|
|
3067
|
+
needs: z
|
|
3068
|
+
.array(z.string())
|
|
3069
|
+
.optional()
|
|
3070
|
+
.describe("Which jobs in this run it declared it waits on: the real shape of the pipeline. Absent means nothing could be read, which is different from an empty list, which is the claim that it waits on nothing."),
|
|
3071
|
+
startedAt: z.number().optional().describe("When it began, in milliseconds. Absent while it is queued."),
|
|
3072
|
+
finishedAt: z.number().optional().describe("When it ended, in milliseconds."),
|
|
3073
|
+
durationSeconds: z.number().optional().describe("How long it took."),
|
|
3074
|
+
webUrl: z.string().optional().describe("Its page on the forge, which is the shortest path from this step failed to the log that says why."),
|
|
1896
3075
|
});
|
|
1897
3076
|
export const CiJobsResponseSchema = z.object({
|
|
1898
|
-
jobs: z.array(PipelineJobSchema),
|
|
3077
|
+
jobs: z.array(PipelineJobSchema).describe("The steps inside one run. Fetched separately from the run list, so that list stays cheap."),
|
|
1899
3078
|
});
|
|
1900
3079
|
export const CiRepoSchema = z.object({
|
|
1901
|
-
repo: z.string(),
|
|
1902
|
-
host: CiHostSchema,
|
|
1903
|
-
project: z.string(),
|
|
1904
|
-
url: z.string(),
|
|
1905
|
-
hookWarning: z
|
|
3080
|
+
repo: z.string().describe("Which workspace repository."),
|
|
3081
|
+
host: CiHostSchema.describe("Which forge it lives on."),
|
|
3082
|
+
project: z.string().describe("The project there."),
|
|
3083
|
+
url: z.string().describe("Its page on the forge."),
|
|
3084
|
+
hookWarning: z
|
|
3085
|
+
.string()
|
|
3086
|
+
.optional()
|
|
3087
|
+
.describe("Present when the sandbox could not register for instant notifications, with what happened and what to paste in by hand. Without them the sandbox polls instead, so this costs a couple of minutes' delay rather than the feature."),
|
|
1906
3088
|
});
|
|
1907
3089
|
export const CI_POLL_INTERVAL_MS = 2 * 60_000;
|
|
1908
3090
|
export const CiRunsResponseSchema = z.object({
|
|
1909
|
-
repos: z.array(CiRepoSchema),
|
|
1910
|
-
runs: z.array(PipelineRunSchema),
|
|
1911
|
-
seenAt: z
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
export const
|
|
3091
|
+
repos: z.array(CiRepoSchema).describe("Which workspace repositories are wired to a forge, and how each one's notifications are set up."),
|
|
3092
|
+
runs: z.array(PipelineRunSchema).describe("Runs across all of them, newest first."),
|
|
3093
|
+
seenAt: z
|
|
3094
|
+
.number()
|
|
3095
|
+
.optional()
|
|
3096
|
+
.describe("When this was last looked at, in milliseconds, so a badge can tell new breakages from ones already read without a second call. Absent means never, so everything counts as new."),
|
|
3097
|
+
});
|
|
3098
|
+
export const CiSeenResponseSchema = z.object({
|
|
3099
|
+
seenAt: z.number().describe("The timestamp that was written, handed back so a caller can update without asking again."),
|
|
3100
|
+
});
|
|
3101
|
+
export const CiRunParamSchema = z.object({
|
|
3102
|
+
repo: z
|
|
3103
|
+
.string()
|
|
3104
|
+
.describe("Which workspace repository. The project behind it is resolved fresh each call, so a stale screen cannot act on one the workspace no longer maps to."),
|
|
3105
|
+
runId: z.number().describe("Which run, by the forge's own id."),
|
|
3106
|
+
});
|
|
3107
|
+
export const CiFixParamSchema = CiRunParamSchema.extend({
|
|
3108
|
+
pick: AgentRunPickSchema.describe("Which model to open the conversation on, when somebody chose one. Leave it out for the sandbox's own choice, which is the ordinary path."),
|
|
3109
|
+
});
|
|
3110
|
+
export const CiFixResponseSchema = z.object({
|
|
3111
|
+
conversationId: z.string().describe("The conversation that was opened, already holding the failure. Open it to watch, or attach to its turn."),
|
|
3112
|
+
});
|
|
1917
3113
|
export const PrepushStatusSchema = z.enum(["idle", "running", "passed", "failed", "error", "cancelled"]);
|
|
1918
3114
|
export const PrepushRunSchema = z.object({
|
|
1919
|
-
status: PrepushStatusSchema,
|
|
1920
|
-
command: z
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
3115
|
+
status: PrepushStatusSchema.describe("Where the run is. Failed and error are deliberately different: failed means the code is wrong, error means the command could not be run at all, and calling the second one a test failure would send an agent hunting a bug that is not there."),
|
|
3116
|
+
command: z
|
|
3117
|
+
.string()
|
|
3118
|
+
.describe("What actually ran, echoed here rather than read back from the settings, so a result looked at after the setting changed still says what produced it."),
|
|
3119
|
+
startedAt: z.number().optional().describe("When it began, in milliseconds."),
|
|
3120
|
+
finishedAt: z.number().optional().describe("When it ended, in milliseconds."),
|
|
3121
|
+
exitCode: z.number().optional().describe("How the command exited."),
|
|
3122
|
+
timedOut: z.boolean().optional().describe("It was killed for taking too long rather than finishing."),
|
|
3123
|
+
session: z
|
|
3124
|
+
.string()
|
|
3125
|
+
.optional()
|
|
3126
|
+
.describe("The terminal it runs in, which is where to watch it. Absent where the sandbox has no terminals, in which case there is nothing to attach to."),
|
|
3127
|
+
output: z
|
|
3128
|
+
.string()
|
|
3129
|
+
.describe("The end of what it printed, as plain text with the colour codes and redrawn progress lines resolved away. The end rather than the beginning, because a suite's verdict is at the end. Empty while it runs, and for one that was killed."),
|
|
1927
3130
|
});
|
|
1928
3131
|
export const DraftStatusSchema = z.enum(["proposed", "approved", "posting", "posted", "failed"]);
|
|
1929
3132
|
export const DraftSchema = z.object({
|
|
1930
|
-
platform: z
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
3133
|
+
platform: z
|
|
3134
|
+
.string()
|
|
3135
|
+
.min(1)
|
|
3136
|
+
.describe("Where it should go. A plain name, so a new site needs no change here; an unknown one simply fails when it tries to post."),
|
|
3137
|
+
actsAs: entryId
|
|
3138
|
+
.optional()
|
|
3139
|
+
.describe("Whose name it goes out under. Needed for anywhere that requires being logged in, because an unwatched turn naming nobody is allowed no account at all. Never guessed: one site can be connected five times over, and picking for you means picking wrong in public with no undo."),
|
|
3140
|
+
content: z.string().min(1).describe("The post itself."),
|
|
3141
|
+
title: z.string().optional().describe("A title, where the site wants one."),
|
|
3142
|
+
target: z
|
|
3143
|
+
.string()
|
|
3144
|
+
.optional()
|
|
3145
|
+
.describe("Where on the site: a community, a channel. Or the address of the thing this replies to, in which case it is a reply, and on some sites the difference between a thread's address and one comment's is the difference between talking to the room and answering the person."),
|
|
3146
|
+
media: z.array(z.string()).optional().describe("Anything to attach, as workspace paths."),
|
|
3147
|
+
scheduledAt: z
|
|
3148
|
+
.number()
|
|
3149
|
+
.optional()
|
|
3150
|
+
.describe("When it should go out, in milliseconds. An agent may propose without one and you set it when approving; an approved draft with no time goes as soon as it is picked up."),
|
|
3151
|
+
status: DraftStatusSchema.default("proposed").describe("Where it is: proposed by the agent, approved by you, being sent, sent, or failed. Rejecting is deleting it; retrying is approving a failed one again."),
|
|
3152
|
+
createdAt: z.number().optional().describe("When it was written, in milliseconds."),
|
|
3153
|
+
postingAt: z
|
|
3154
|
+
.number()
|
|
3155
|
+
.optional()
|
|
3156
|
+
.describe("When sending started, in milliseconds. Needed to tell a send that is under way from one whose run died mid-flight, which the scheduled time cannot: a post due last week is not a post that has been sending since last week."),
|
|
3157
|
+
postedAt: z.number().optional().describe("When it went out, in milliseconds."),
|
|
3158
|
+
postedUrl: z
|
|
3159
|
+
.string()
|
|
3160
|
+
.optional()
|
|
3161
|
+
.describe("Where it landed, when the site hands back an address. The one thing a sent draft can offer that reading it cannot: the post itself, to go and look at."),
|
|
3162
|
+
error: z.string().optional().describe("Why it failed, written as a sentence for a person to read rather than as a code."),
|
|
3163
|
+
});
|
|
3164
|
+
export const DraftSummarySchema = DraftSchema.extend({ id: entryId.describe("The draft's id.") });
|
|
3165
|
+
export const DraftsListSchema = z.object({
|
|
3166
|
+
drafts: z.array(DraftSummarySchema).describe("The queue."),
|
|
3167
|
+
invalid: z
|
|
3168
|
+
.array(z.string())
|
|
3169
|
+
.describe("Drafts that could not be read at all. Listed rather than skipped, because an agent writes these files directly and a malformed one would otherwise never post and never say why."),
|
|
3170
|
+
});
|
|
3171
|
+
export const DraftIdParamSchema = z.object({ id: entryId.describe("Which draft.") });
|
|
1947
3172
|
export const PanelSummarySchema = z.object({
|
|
1948
|
-
repo: z.string(),
|
|
1949
|
-
hasPanel: z.boolean(),
|
|
1950
|
-
running: z.boolean(),
|
|
1951
|
-
healthy: z
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
3173
|
+
repo: z.string().describe("Which repository."),
|
|
3174
|
+
hasPanel: z.boolean().describe("Whether it has anything runnable at all."),
|
|
3175
|
+
running: z.boolean().describe("Whether the sandbox has it running."),
|
|
3176
|
+
healthy: z
|
|
3177
|
+
.boolean()
|
|
3178
|
+
.describe("Whether anything it owns is actually answering. A different question: a server still installing is running and not yet healthy, and one somebody started by hand is healthy without the sandbox running it."),
|
|
3179
|
+
port: z
|
|
3180
|
+
.number()
|
|
3181
|
+
.optional()
|
|
3182
|
+
.describe("The port the sandbox told it to use. What it actually bound is below, and for a repository that pins its own ports those are different numbers."),
|
|
3183
|
+
servers: z
|
|
3184
|
+
.array(z.object({
|
|
3185
|
+
url: z.string().describe("Where it answers, with the right scheme: a server on its own certificate is served over https."),
|
|
3186
|
+
dir: z
|
|
3187
|
+
.string()
|
|
3188
|
+
.optional()
|
|
3189
|
+
.describe("Which part of the repository it belongs to, which for a repository whose dev command fans out is the only thing telling them apart."),
|
|
3190
|
+
session: z
|
|
3191
|
+
.string()
|
|
3192
|
+
.optional()
|
|
3193
|
+
.describe("The terminal it runs in: the sandbox's when it started it, yours when you did, and absent when nothing here owns it, which is the case worth designing for."),
|
|
3194
|
+
}))
|
|
3195
|
+
.describe("Every server this repository is really serving, found by looking at what is listening. Empty when nothing answers."),
|
|
3196
|
+
previewUrl: z.string().optional().describe("Where to open it from outside. Absent on a sandbox with no outside address."),
|
|
3197
|
+
role: z
|
|
3198
|
+
.enum(["intent", "desired-state", "app"])
|
|
3199
|
+
.optional()
|
|
3200
|
+
.describe("Which of the workspace's three fixed roles this repository fills. Absent for one that was simply cloned in."),
|
|
3201
|
+
deployConfig: z.boolean().describe("It declares infrastructure."),
|
|
3202
|
+
desiredState: z.boolean().describe("That declaration has been resolved at least once."),
|
|
3203
|
+
directoryUi: z.boolean().describe("It carries a small interface of its own."),
|
|
3204
|
+
monorepo: z.boolean().describe("It holds several packages."),
|
|
3205
|
+
vitest: z.boolean().describe("It has tests that can be run."),
|
|
3206
|
+
userStories: z
|
|
3207
|
+
.boolean()
|
|
3208
|
+
.describe("It carries stories an agent could test the running app against. The one fact here that says nothing about the language."),
|
|
3209
|
+
docs: z.boolean().describe("It carries generated architecture documentation."),
|
|
3210
|
+
});
|
|
3211
|
+
export const PanelsListSchema = z.object({
|
|
3212
|
+
panels: z
|
|
3213
|
+
.array(PanelSummarySchema)
|
|
3214
|
+
.describe("One entry per repository, worked out in a single pass so nothing has to walk the workspace file by file."),
|
|
3215
|
+
});
|
|
3216
|
+
export const PanelRepoParamSchema = z.object({ repo: z.string().describe("Which repository.") });
|
|
1966
3217
|
export const PortSummarySchema = z.object({
|
|
1967
|
-
port: z.number(),
|
|
1968
|
-
host: z
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
3218
|
+
port: z.number().describe("The port number."),
|
|
3219
|
+
host: z
|
|
3220
|
+
.enum(["127.0.0.1", "::1"])
|
|
3221
|
+
.describe("Which loopback address it actually answers on. Some tools bind only one of the two, and anything dialling it has to know which."),
|
|
3222
|
+
forwardable: z
|
|
3223
|
+
.boolean()
|
|
3224
|
+
.describe("Whether it can be exposed at all. Some listeners answer only at their own address and nowhere else; those are listed for honesty and refused for forwarding."),
|
|
3225
|
+
kind: z
|
|
3226
|
+
.enum(["workspace", "system"])
|
|
3227
|
+
.describe("Whether somebody's own work put it there, or the sandbox's own machinery did. Only the first kind is worth previewing."),
|
|
3228
|
+
title: z
|
|
3229
|
+
.string()
|
|
3230
|
+
.describe("What a person would call it. Always present: a listener nothing can explain is still named, because the button beside it publishes the port to the internet."),
|
|
3231
|
+
purpose: z.string().describe("One sentence about what it is for, including when the honest answer is that nothing could work it out."),
|
|
3232
|
+
origin: z
|
|
3233
|
+
.enum(["terminal", "agent", "panel", "extension", "container", "sandbox", "unknown"])
|
|
3234
|
+
.describe("Who put it there, which is the question somebody is really asking: mine, my agent's, or the box's own."),
|
|
3235
|
+
pid: z.number().optional().describe("The process holding it. Absent when nothing could be matched to the socket."),
|
|
3236
|
+
command: z.string().optional().describe("The command behind it, as it was run. Absent only when nothing could be attributed at all."),
|
|
3237
|
+
cwd: z.string().optional().describe("Where it is running from, which is how a port gets attributed to a repository."),
|
|
3238
|
+
session: z
|
|
3239
|
+
.string()
|
|
3240
|
+
.optional()
|
|
3241
|
+
.describe('The terminal it came from, to watch it in or stop it from. Absent when nothing in its ancestry is one, which is the honest "you cannot reach this from here".'),
|
|
3242
|
+
forwarded: z.boolean().describe("Whether it is currently reachable from outside."),
|
|
3243
|
+
previewUrl: z.string().optional().describe("Where to open it. Present only while forwarded, and only on a sandbox that has an outside address."),
|
|
3244
|
+
});
|
|
3245
|
+
export const PortsListSchema = z.object({
|
|
3246
|
+
ports: z
|
|
3247
|
+
.array(PortSummarySchema)
|
|
3248
|
+
.describe("Everything listening inside the sandbox right now, read fresh each time rather than from a register the sandbox keeps."),
|
|
3249
|
+
});
|
|
3250
|
+
export const PortParamSchema = z.object({ port: z.number().int().min(1).max(65535).describe("Which port.") });
|
|
3251
|
+
export const PortForwardResultSchema = z.object({
|
|
3252
|
+
previewUrl: z
|
|
3253
|
+
.string()
|
|
3254
|
+
.optional()
|
|
3255
|
+
.describe("Where it can now be reached. Absent on a sandbox with no outside address, where the mapping exists but has no public name."),
|
|
3256
|
+
});
|
|
1984
3257
|
export const MachineSandboxSchema = z.object({
|
|
1985
3258
|
slug: z.string(),
|
|
1986
3259
|
container: z.string(),
|
|
@@ -2069,99 +3342,178 @@ export const SyncStatusSchema = z.object({
|
|
|
2069
3342
|
machines: z.array(MachineReportSchema).optional(),
|
|
2070
3343
|
});
|
|
2071
3344
|
export const PublicFileSchema = z.object({
|
|
2072
|
-
path: z.string(),
|
|
2073
|
-
size: z.number(),
|
|
2074
|
-
modifiedAt: z.number(),
|
|
2075
|
-
url: z.string().optional(),
|
|
2076
|
-
blocked: z
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
export const
|
|
3345
|
+
path: z.string().describe("Where it sits inside the outbox."),
|
|
3346
|
+
size: z.number().describe("Size in bytes."),
|
|
3347
|
+
modifiedAt: z.number().describe("When it last changed, in milliseconds."),
|
|
3348
|
+
url: z.string().optional().describe("Its public address. Absent when this sandbox has no outside address, or when the file is being refused."),
|
|
3349
|
+
blocked: z
|
|
3350
|
+
.string()
|
|
3351
|
+
.optional()
|
|
3352
|
+
.describe("Why a file sitting in the outbox is not being served: a hidden name, a credential-shaped name, contents that look like a token, or sheer size. Only the publisher sees this; a stranger asking for the same file gets the same nothing every other miss gets."),
|
|
3353
|
+
});
|
|
3354
|
+
export const PublicListSchema = z.object({
|
|
3355
|
+
url: z.string().optional().describe("Your public address, which every file's own hangs off. Absent on a sandbox with nowhere to publish to."),
|
|
3356
|
+
files: z.array(PublicFileSchema).describe("What the outbox holds."),
|
|
3357
|
+
});
|
|
3358
|
+
export const PublishSchema = z.object({
|
|
3359
|
+
path: z
|
|
3360
|
+
.string()
|
|
3361
|
+
.min(1)
|
|
3362
|
+
.describe("What to publish, as a workspace path. It is copied rather than moved, so a repository does not lose its build output because somebody shared it."),
|
|
3363
|
+
});
|
|
3364
|
+
export const UnpublishSchema = z.object({
|
|
3365
|
+
path: z.string().min(1).describe("What to withdraw, as a path inside the outbox rather than a workspace path."),
|
|
3366
|
+
});
|
|
3367
|
+
export const PublishResultSchema = z.object({
|
|
3368
|
+
path: z.string().describe("Where it landed inside the outbox."),
|
|
3369
|
+
url: z.string().optional().describe("Its public address. Absent on a sandbox with nowhere to publish to."),
|
|
3370
|
+
});
|
|
2082
3371
|
export const ShareDetailSchema = z.enum(["messages", "everything"]);
|
|
2083
3372
|
export const SharedConversationSchema = z.object({
|
|
2084
|
-
id: z
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
3373
|
+
id: z
|
|
3374
|
+
.string()
|
|
3375
|
+
.describe("The share's own id, minted fresh each time, so sharing one conversation twice gives two links. Deliberately not the conversation's id, which is memorable by design and would make a page's address guessable."),
|
|
3376
|
+
conversationId: z.string().describe("Which conversation it was taken from."),
|
|
3377
|
+
title: z.string().describe("The title on the page, which is the sharer's choice rather than the conversation's own."),
|
|
3378
|
+
detail: ShareDetailSchema.describe("How much travels: the two speakers' words alone, or the whole record including the agent's work and thinking, which necessarily publishes the code and command output in it."),
|
|
3379
|
+
sharedAt: z
|
|
3380
|
+
.number()
|
|
3381
|
+
.describe("When the snapshot was taken, in milliseconds. A share is frozen, so this dates what a recipient can see rather than when the conversation happened."),
|
|
3382
|
+
messages: z.number().describe("How many messages are behind the link."),
|
|
3383
|
+
url: z.string().optional().describe("The page's address. Absent on a sandbox with nowhere to publish to."),
|
|
3384
|
+
});
|
|
3385
|
+
export const ShareListSchema = z.object({ shares: z.array(SharedConversationSchema).describe("Every conversation currently published as a page.") });
|
|
2093
3386
|
export const ShareCreateSchema = z.object({
|
|
2094
|
-
conversationId: z.string().min(1),
|
|
2095
|
-
title: z.string().min(1).max(80),
|
|
2096
|
-
detail: ShareDetailSchema,
|
|
3387
|
+
conversationId: z.string().min(1).describe("Which conversation to publish."),
|
|
3388
|
+
title: z.string().min(1).max(80).describe("The title for the page. The conversation's own name is only what a dialog would open with."),
|
|
3389
|
+
detail: ShareDetailSchema.describe("How much to publish. Two levels rather than a set of switches, because every extra toggle is another thing to get wrong about a link that cannot be recalled."),
|
|
2097
3390
|
});
|
|
2098
|
-
export const ShareUpdateSchema = z.object({
|
|
2099
|
-
|
|
3391
|
+
export const ShareUpdateSchema = z.object({
|
|
3392
|
+
id: z.string().min(1).describe("Which share to re-take. Its link stays the same, which matters because it has already been sent."),
|
|
3393
|
+
});
|
|
3394
|
+
export const ShareRemoveSchema = z.object({ id: z.string().min(1).describe("Which share to take down.") });
|
|
2100
3395
|
export const TerminalSessionSchema = z.object({
|
|
2101
|
-
name: z.string(),
|
|
2102
|
-
label: z.string().optional(),
|
|
2103
|
-
kind: z
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
3396
|
+
name: z.string().describe("Its id, and what the close route takes."),
|
|
3397
|
+
label: z.string().optional().describe("What to call it on screen."),
|
|
3398
|
+
kind: z
|
|
3399
|
+
.enum(["shell", "panel", "agent", "job", "process"])
|
|
3400
|
+
.describe("What sort of thing it is: a terminal somebody opened, a repository's dev server, where an agent's commands run, a job the sandbox started, or a background process that is watched rather than typed into."),
|
|
3401
|
+
running: z
|
|
3402
|
+
.boolean()
|
|
3403
|
+
.describe("Whether it is alive. A finished one-shot job leaves a dead shell behind, which reads as false and is how it gets swept up."),
|
|
3404
|
+
activityAt: z.number().describe("When it last produced output, in milliseconds. Zero means it did not say, which is unknown rather than 1970."),
|
|
3405
|
+
exitCode: z.number().optional().describe("How the last thing in it ended. Absent while that pane is still alive."),
|
|
3406
|
+
command: z
|
|
3407
|
+
.string()
|
|
3408
|
+
.optional()
|
|
3409
|
+
.describe("What is running in it right now. Absent when it is sitting at a prompt. Not a second spelling of whether it is alive: this says whether anything is happening, which is what a close button should ask about before it ends something."),
|
|
3410
|
+
extensionId: z.string().optional().describe("Which extension declared this process, when one did."),
|
|
3411
|
+
processName: z
|
|
3412
|
+
.string()
|
|
3413
|
+
.optional()
|
|
3414
|
+
.describe("Which of that extension's processes it is, which together with the id above addresses its start and stop routes."),
|
|
3415
|
+
help: z
|
|
3416
|
+
.object({
|
|
3417
|
+
requestId: z.string().describe("What to send back when you answer, through the agent reply route."),
|
|
3418
|
+
message: z.string().describe("What the agent needs, in its own words."),
|
|
3419
|
+
requestedAt: z.number().describe("When it asked, in milliseconds."),
|
|
3420
|
+
})
|
|
3421
|
+
.optional()
|
|
3422
|
+
.describe("The agent has stopped at something only a person can clear, and is waiting at this terminal. Present only while it is waiting."),
|
|
3423
|
+
});
|
|
3424
|
+
export const TerminalsListSchema = z.object({
|
|
3425
|
+
sessions: z
|
|
3426
|
+
.array(TerminalSessionSchema)
|
|
3427
|
+
.describe("Every live surface the sandbox is holding, in one list, because the question they all answer is the same one."),
|
|
2111
3428
|
});
|
|
2112
|
-
export const
|
|
2113
|
-
export const TerminalNameParamSchema = z.object({ name: z.string() });
|
|
3429
|
+
export const TerminalNameParamSchema = z.object({ name: z.string().describe("Which terminal.") });
|
|
2114
3430
|
export const TerminalScrollbackQuerySchema = z.object({
|
|
2115
|
-
name: z.string(),
|
|
2116
|
-
lines: z.coerce.number().min(1).max(100_000).default(20_000),
|
|
3431
|
+
name: z.string().describe("Which terminal."),
|
|
3432
|
+
lines: z.coerce.number().min(1).max(100_000).default(20_000).describe("How far back to ask for. Clamped to the history that actually exists."),
|
|
2117
3433
|
});
|
|
2118
3434
|
export const TerminalScrollbackSchema = z.object({
|
|
2119
|
-
name: z.string(),
|
|
2120
|
-
text: z.string(),
|
|
2121
|
-
lines: z.number(),
|
|
2122
|
-
truncated: z.boolean(),
|
|
3435
|
+
name: z.string().describe("Which terminal this is from."),
|
|
3436
|
+
text: z.string().describe("The history, oldest line first, with wrapped lines rejoined so a copied address or path comes back whole."),
|
|
3437
|
+
lines: z.number().describe("How many lines you got."),
|
|
3438
|
+
truncated: z.boolean().describe("It stopped because you asked for that many, not because the history ran out."),
|
|
2123
3439
|
});
|
|
2124
3440
|
export const BrowserPageSchema = z.object({
|
|
2125
|
-
id: z
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
3441
|
+
id: z
|
|
3442
|
+
.string()
|
|
3443
|
+
.describe("Stable for the life of the page, which is what lets a tab survive a refresh of this list. Its address changes as the agent navigates and its position changes when a sibling closes."),
|
|
3444
|
+
title: z.string().optional().describe("The page's title. Absent mid-navigation, which is exactly when a tab still has to be drawn."),
|
|
3445
|
+
url: z.string().describe("Where it is."),
|
|
3446
|
+
active: z.boolean().describe("The one the agent last touched, or for a finished session, the one it ended on. Exactly one page has this."),
|
|
2129
3447
|
});
|
|
2130
3448
|
export const BrowserSessionSchema = z.object({
|
|
2131
|
-
name: z.string(),
|
|
2132
|
-
label: z.string(),
|
|
2133
|
-
server: z
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
3449
|
+
name: z.string().describe("Its id, and what the close route takes."),
|
|
3450
|
+
label: z.string().describe("What to call it on screen: the open page's title, or its site, or which browser this is."),
|
|
3451
|
+
server: z
|
|
3452
|
+
.string()
|
|
3453
|
+
.describe("Which browser drives it: the credential-free one, or a signed-in account's. The difference between a throwaway page and one logged in as you, which is worth saying out loud."),
|
|
3454
|
+
running: z
|
|
3455
|
+
.boolean()
|
|
3456
|
+
.describe("Whether it is still open. A closed one is listed for a while with the pages it had, as the record of where the agent went."),
|
|
3457
|
+
activityAt: z.number().describe("When it last did anything, in milliseconds."),
|
|
3458
|
+
finishedAt: z.number().optional().describe("When it closed, in milliseconds. Absent while it is open."),
|
|
3459
|
+
help: z
|
|
3460
|
+
.object({
|
|
3461
|
+
requestId: z.string().describe("What to send back when you answer, through the agent reply route."),
|
|
3462
|
+
message: z.string().describe("What the agent needs, in its own words."),
|
|
3463
|
+
requestedAt: z.number().describe("When it asked, in milliseconds."),
|
|
3464
|
+
})
|
|
3465
|
+
.optional()
|
|
3466
|
+
.describe("The agent has hit something only a person can clear: a captcha, a password it does not hold, a check on your phone. Present only while it is waiting."),
|
|
3467
|
+
pages: z
|
|
3468
|
+
.array(BrowserPageSchema)
|
|
3469
|
+
.describe("Every page it has open. A browser holds several at once, which is the reason it is listed apart from the terminals."),
|
|
2139
3470
|
});
|
|
2140
|
-
export const BrowsersListSchema = z.object({
|
|
2141
|
-
|
|
3471
|
+
export const BrowsersListSchema = z.object({
|
|
3472
|
+
sessions: z.array(BrowserSessionSchema).describe("Every browser the agents have running, open or recently closed."),
|
|
3473
|
+
});
|
|
3474
|
+
export const BrowserNameParamSchema = z.object({ name: z.string().describe("Which browser.") });
|
|
2142
3475
|
export const SubagentKindSchema = z.enum(["subagent", "codex", "grok"]);
|
|
2143
3476
|
export const SubagentStatusSchema = z.enum(["pending", "running", "blocked", "completed", "failed", "killed", "paused"]);
|
|
2144
3477
|
export const SubagentSessionSchema = z.object({
|
|
2145
|
-
id: z
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
3478
|
+
id: z
|
|
3479
|
+
.string()
|
|
3480
|
+
.describe("The id of the tool call that started it, which every side already holds, so a card links to its helper with the id it has and the helper points back the same way."),
|
|
3481
|
+
kind: SubagentKindSchema.describe("What sort of helper: one the runtime spawned, or a separate tool the agent drove from a shell. It changes only how you watch it."),
|
|
3482
|
+
conversationId: z.string().describe("The conversation whose turn started it, and the way back to the chat it belongs to."),
|
|
3483
|
+
agentType: z.string().optional().describe("What kind of helper it is."),
|
|
3484
|
+
description: z.string().optional().describe("What it was asked to do, in one line."),
|
|
3485
|
+
model: z.string().optional().describe("Which model it runs on."),
|
|
3486
|
+
spawnDepth: z
|
|
3487
|
+
.number()
|
|
3488
|
+
.optional()
|
|
3489
|
+
.describe("How deep in the chain it sits, where one means the turn itself started it. A helper can start helpers, and a flat list that could not say so would read as though the turn started all of them."),
|
|
3490
|
+
background: z
|
|
3491
|
+
.boolean()
|
|
3492
|
+
.optional()
|
|
3493
|
+
.describe("The parent carried on working instead of waiting for it. This is the whole reason the list exists: such a helper used to be invisible until its result landed, sometimes minutes later."),
|
|
3494
|
+
status: SubagentStatusSchema.describe("How it is going. Blocked means it needs an answer, which a parent and an operator act on differently from it simply working."),
|
|
3495
|
+
startedAt: z.number().describe("When it started, in milliseconds."),
|
|
3496
|
+
endedAt: z.number().optional().describe("When it finished, in milliseconds. Absent while it works."),
|
|
3497
|
+
activityAt: z.number().describe("When it last did anything, in milliseconds."),
|
|
3498
|
+
tokens: z
|
|
3499
|
+
.number()
|
|
3500
|
+
.optional()
|
|
3501
|
+
.describe("What it has spent. Its own, so a parent's cost and the sum of its helpers' are two different true numbers."),
|
|
3502
|
+
toolUses: z.number().optional().describe("How many tools it has used."),
|
|
3503
|
+
lastTool: z.string().optional().describe("The last one it reached for."),
|
|
3504
|
+
summary: z
|
|
3505
|
+
.string()
|
|
3506
|
+
.optional()
|
|
3507
|
+
.describe("Its report: what it concluded, without opening its record. The question a finished helper gets read for."),
|
|
3508
|
+
error: z.string().optional().describe("Why it failed, when it did."),
|
|
3509
|
+
terminal: z
|
|
3510
|
+
.string()
|
|
3511
|
+
.optional()
|
|
3512
|
+
.describe("The terminal its command runs in, when there is one. Absent for a helper with no process of its own, which is watched by reading its record instead."),
|
|
3513
|
+
});
|
|
3514
|
+
export const SubagentsListSchema = z.object({
|
|
3515
|
+
sessions: z.array(SubagentSessionSchema).describe("Every helper this sandbox's conversations have started."),
|
|
2163
3516
|
});
|
|
2164
|
-
export const SubagentsListSchema = z.object({ sessions: z.array(SubagentSessionSchema) });
|
|
2165
3517
|
export const SubagentIdParamSchema = z.object({ id: z.string() });
|
|
2166
3518
|
const environmentFileSchema = z.object({ content: z.string(), hash: z.string() });
|
|
2167
3519
|
export const EnvironmentSchema = z.object({
|
|
@@ -2257,109 +3609,203 @@ export const SecretSetSchema = z.object({
|
|
|
2257
3609
|
key: z
|
|
2258
3610
|
.string()
|
|
2259
3611
|
.regex(/^[A-Za-z_][A-Za-z0-9_]*$/)
|
|
2260
|
-
.max(128)
|
|
2261
|
-
|
|
3612
|
+
.max(128)
|
|
3613
|
+
.describe("The name to store it under, which is the name a process will find it by."),
|
|
3614
|
+
value: z.string().min(1).describe("The value. It goes straight to your sandbox and never through the platform."),
|
|
2262
3615
|
});
|
|
2263
|
-
export const SecretKeysSchema = z.object({
|
|
2264
|
-
|
|
2265
|
-
|
|
3616
|
+
export const SecretKeysSchema = z.object({
|
|
3617
|
+
keys: z.array(z.string()).describe("The names that exist here. Only the names: the values never leave the sandbox."),
|
|
3618
|
+
});
|
|
3619
|
+
export const SecretKeyParamSchema = z.object({ key: z.string().describe("Which secret, by name.") });
|
|
3620
|
+
export const SecretRevealSchema = z.object({ value: z.string().describe("The value itself. The only place in this API one is ever returned.") });
|
|
2266
3621
|
export const SecretInventoryEntrySchema = z.object({
|
|
2267
|
-
key: z.string(),
|
|
2268
|
-
kind: z
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
3622
|
+
key: z.string().describe("What identifies it. Unique across the whole inventory, so several accounts of one provider each get their own entry."),
|
|
3623
|
+
kind: z
|
|
3624
|
+
.enum(["env", "generated", "capability", "provider"])
|
|
3625
|
+
.describe("Where it came from: you set it, the sandbox generated it, a connection needs it, or it is a model account's credential."),
|
|
3626
|
+
label: z.string().optional().describe("A friendlier name, for entries that have one."),
|
|
3627
|
+
status: z.enum(["missing", "set", "connected"]).describe("Whether it exists and, for a connection, whether it is working."),
|
|
3628
|
+
requiredBy: z
|
|
3629
|
+
.array(z.object({ resourceId: z.string().describe("Which resource."), type: z.string().describe("What kind of resource it is.") }))
|
|
3630
|
+
.describe("What is waiting on it. Empty for a connection's or an account's own credential."),
|
|
3631
|
+
storedAt: z.string().describe("Where it actually lives, in words."),
|
|
3632
|
+
revealable: z.boolean().describe("Whether its value can be shown at all. Everything except a model account's credential can be."),
|
|
3633
|
+
ci: z
|
|
3634
|
+
.object({
|
|
3635
|
+
synced: z.boolean().describe("Whether the pipeline has it."),
|
|
3636
|
+
pushedAt: z.string().optional().describe("When it was last sent there."),
|
|
3637
|
+
})
|
|
3638
|
+
.optional()
|
|
3639
|
+
.describe("Whether a copy has been given to the build pipeline."),
|
|
3640
|
+
lastUse: z
|
|
3641
|
+
.object({
|
|
3642
|
+
at: z.number().describe("When, in milliseconds."),
|
|
3643
|
+
lane: z.enum(["shell", "code", "browser"]).describe("How it was used: a command, a script, or typed into a page."),
|
|
3644
|
+
detail: z
|
|
3645
|
+
.string()
|
|
3646
|
+
.optional()
|
|
3647
|
+
.describe("Where it went: the start of the command or script, or the site. Names and destinations only, never values."),
|
|
3648
|
+
})
|
|
3649
|
+
.optional()
|
|
3650
|
+
.describe("The last time an agent actually spent this secret. Absent while it never has been, which most never are."),
|
|
3651
|
+
});
|
|
3652
|
+
export const SecretInventorySchema = z.object({
|
|
3653
|
+
entries: z
|
|
3654
|
+
.array(SecretInventoryEntrySchema)
|
|
3655
|
+
.describe("One entry per secret this sandbox knows about, from every place they live. No values, ever."),
|
|
3656
|
+
});
|
|
2278
3657
|
export const AdapterHealthSchema = z.object({
|
|
2279
|
-
state: z
|
|
2280
|
-
|
|
2281
|
-
|
|
3658
|
+
state: z
|
|
3659
|
+
.enum(["ready", "unavailable", "unknown"])
|
|
3660
|
+
.describe("Whether this runtime can serve a turn. Unknown is a real answer rather than a soft no: a check that could not run must not grey out a provider you can in fact use."),
|
|
3661
|
+
detail: z.string().optional().describe("Why it cannot, and what to do about it. Absent when it can."),
|
|
3662
|
+
checkedAt: z.number().describe("When it was last checked, in milliseconds."),
|
|
2282
3663
|
});
|
|
2283
3664
|
export const StagedUpdateSchema = z.object({
|
|
2284
|
-
version: z.string().optional(),
|
|
2285
|
-
channel: z
|
|
2286
|
-
|
|
3665
|
+
version: z.string().optional().describe("What the downloaded build says it is. Absent means ready but unnamed, never that nothing is ready."),
|
|
3666
|
+
channel: z
|
|
3667
|
+
.string()
|
|
3668
|
+
.describe("Which channel it was taken from. Not necessarily the one this sandbox follows: downloading a beta build is not the same as moving onto beta."),
|
|
3669
|
+
at: z.number().describe("When the download finished, in milliseconds, which answers whether this is still the update being offered."),
|
|
2287
3670
|
});
|
|
2288
3671
|
export const InfoSchema = z.object({
|
|
2289
|
-
name: z.string().optional(),
|
|
2290
|
-
image: z.string().optional(),
|
|
2291
|
-
version: z.string().optional(),
|
|
2292
|
-
latest: z.string().optional(),
|
|
2293
|
-
updateAvailable: z.boolean().optional(),
|
|
2294
|
-
runtimes: z
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
3672
|
+
name: z.string().optional().describe("What this sandbox is called."),
|
|
3673
|
+
image: z.string().optional().describe("The image it is running."),
|
|
3674
|
+
version: z.string().optional().describe("The version of that image."),
|
|
3675
|
+
latest: z.string().optional().describe("The newest published version on its channel."),
|
|
3676
|
+
updateAvailable: z.boolean().optional().describe("Whether those two differ."),
|
|
3677
|
+
runtimes: z
|
|
3678
|
+
.record(z.string(), AdapterHealthSchema)
|
|
3679
|
+
.optional()
|
|
3680
|
+
.describe("Which agent runtimes can serve a turn right now, keyed by runtime. Absent until the first check has run, which reads the same as every entry being unknown."),
|
|
3681
|
+
channel: z.string().optional().describe("Which release channel this sandbox follows."),
|
|
3682
|
+
previousImage: z
|
|
3683
|
+
.string()
|
|
3684
|
+
.optional()
|
|
3685
|
+
.describe("The image the last update replaced, which is what a rollback would return to. Absent means there is nothing to go back to."),
|
|
3686
|
+
updateNotes: z
|
|
3687
|
+
.array(z.string())
|
|
3688
|
+
.optional()
|
|
3689
|
+
.describe("What is in the update, in the words of the people it is for, newest first. Absent or empty whenever there is nothing worth saying, which reads on screen exactly as it did before there were notes at all."),
|
|
3690
|
+
moreUpdateNotes: z
|
|
3691
|
+
.number()
|
|
3692
|
+
.optional()
|
|
3693
|
+
.describe("How many further notes there are beyond the ones sent, for a sandbox left alone a long time. Absent or zero means you have all of them."),
|
|
3694
|
+
breakingNotes: z
|
|
3695
|
+
.array(z.string())
|
|
3696
|
+
.optional()
|
|
3697
|
+
.describe("What the update takes away, uncapped, because a warning that fell off a shortened list is a breaking update taken unwarned. Absent for the overwhelming majority, which break nothing."),
|
|
3698
|
+
staged: StagedUpdateSchema.optional().describe("An update already downloaded and built on the machine running this container, waiting only for the restart that applies it. That restart is seconds, where an unprepared update is minutes, which is a different decision entirely. Absent when nothing is waiting."),
|
|
2301
3699
|
});
|
|
2302
3700
|
export const ManifestProblemSchema = z.object({
|
|
2303
|
-
kind: z
|
|
2304
|
-
|
|
2305
|
-
|
|
3701
|
+
kind: z
|
|
3702
|
+
.enum(["unreadable", "unknownKey", "invalidEntry"])
|
|
3703
|
+
.describe("What to do about it. Unreadable means the whole file is being ignored and everything in it is at its default. An unknown key means only that key is ignored. An invalid entry means one item of a list was skipped and the rest is fine."),
|
|
3704
|
+
detail: z.string().describe("What exactly was wrong."),
|
|
3705
|
+
suggestion: z.string().optional().describe("The name it was probably meant to be, when one is close enough to guess honestly."),
|
|
3706
|
+
});
|
|
3707
|
+
export const ManifestProblemReportSchema = z.object({
|
|
3708
|
+
path: z.string().describe("The file, as a workspace path. The file is the unit somebody fixes, which is why problems are grouped by it."),
|
|
3709
|
+
problems: z
|
|
3710
|
+
.array(ManifestProblemSchema)
|
|
3711
|
+
.describe("Everything currently wrong with it. A file with nothing wrong is absent rather than present and empty."),
|
|
2306
3712
|
});
|
|
2307
|
-
export const ManifestProblemReportSchema = z.object({ path: z.string(), problems: z.array(ManifestProblemSchema) });
|
|
2308
3713
|
export const ManifestProblemsSchema = z.array(ManifestProblemReportSchema);
|
|
2309
|
-
export const DaemonSessionSchema = z.object({
|
|
3714
|
+
export const DaemonSessionSchema = z.object({
|
|
3715
|
+
token: z.string().describe("The credential every other call carries. Present it as a bearer token."),
|
|
3716
|
+
expiresAt: z.number().describe("When it stops working, in milliseconds, so a caller can renew ahead of it without reading the token."),
|
|
3717
|
+
email: z.string().describe("Who the sandbox verified you as."),
|
|
3718
|
+
});
|
|
2310
3719
|
export const ActivityEventSchema = z.object({
|
|
2311
|
-
id: z.string(),
|
|
2312
|
-
at: z.number(),
|
|
2313
|
-
provider: z.string().optional(),
|
|
2314
|
-
account: z
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
3720
|
+
id: z.string().describe("The entry's own id."),
|
|
3721
|
+
at: z.number().describe("When it happened, in milliseconds. Also what you page by."),
|
|
3722
|
+
provider: z.string().optional().describe("Which outside service, when one was involved. Absent for the sandbox's own events."),
|
|
3723
|
+
account: z
|
|
3724
|
+
.string()
|
|
3725
|
+
.optional()
|
|
3726
|
+
.describe("Which account handled it. Absent for the sandbox's own events and for work run on a provider's default."),
|
|
3727
|
+
direction: z.enum(["in", "out", "system"]).describe("Whether something arrived, something went out, or the sandbox did it to itself."),
|
|
3728
|
+
type: z
|
|
3729
|
+
.string()
|
|
3730
|
+
.describe("Exactly what happened: a message received or sent, a reaction, a turn starting or ending, a rule doing something. A rule that ran and passed says nothing here, because a feed of green ticks is one the eye learns to skip."),
|
|
3731
|
+
channelId: z.string().optional().describe("Which channel or thread it happened in."),
|
|
3732
|
+
author: z.string().optional().describe("Who sent it, for something that arrived."),
|
|
3733
|
+
content: z.string().optional().describe("The message, in full, whichever direction it went."),
|
|
3734
|
+
method: z.string().optional().describe("The verb of an outgoing call."),
|
|
3735
|
+
endpoint: z.string().optional().describe("The address of an outgoing call. Credentials travel in headers, so they are never here."),
|
|
3736
|
+
sessionId: z.string().optional().describe("The provider session behind it."),
|
|
3737
|
+
turnId: z
|
|
3738
|
+
.string()
|
|
3739
|
+
.optional()
|
|
3740
|
+
.describe("Ties one turn's entries together. A turn writes several, and read as separate rows they say one thing several times, so a feed groups on this."),
|
|
3741
|
+
conversationId: z
|
|
3742
|
+
.string()
|
|
3743
|
+
.optional()
|
|
3744
|
+
.describe("Which conversation. This, rather than the provider session, is what the same agent means across a feed, because a session is retired whenever the model changes."),
|
|
3745
|
+
title: z
|
|
3746
|
+
.string()
|
|
3747
|
+
.optional()
|
|
3748
|
+
.describe("What that conversation was called at the time. Copied in rather than looked up, because an audit entry must still read as words years later, after the conversation has been renamed or pruned."),
|
|
3749
|
+
origin: AgentOriginSchema.optional().describe("What woke the conversation from outside, when something did. It is how a turn gets filed under the chat service that caused it rather than under the model that served it."),
|
|
3750
|
+
automationIds: z.array(z.string()).optional().describe("Which automations were involved."),
|
|
3751
|
+
outcome: z.enum(["ok", "error"]).optional().describe("How it ended."),
|
|
3752
|
+
error: z.string().optional().describe("What went wrong, when something did."),
|
|
3753
|
+
extra: z
|
|
3754
|
+
.record(z.string(), z.unknown())
|
|
3755
|
+
.optional()
|
|
3756
|
+
.describe("Whatever else the source had to say: attachments, participants, a recording's path. Shape varies by source."),
|
|
2331
3757
|
});
|
|
2332
3758
|
export const ActivityQuerySchema = z.object({
|
|
2333
|
-
provider: z.string().optional(),
|
|
2334
|
-
limit: z.coerce.number().min(1).max(500).default(100),
|
|
2335
|
-
before: z.coerce.number().optional(),
|
|
3759
|
+
provider: z.string().optional().describe("Narrow it to one outside service."),
|
|
3760
|
+
limit: z.coerce.number().min(1).max(500).default(100).describe("How many entries to return."),
|
|
3761
|
+
before: z.coerce.number().optional().describe("Only entries older than this timestamp, so paging walks backwards through the feed."),
|
|
2336
3762
|
});
|
|
2337
|
-
export const ActivityListSchema = z.object({ events: z.array(ActivityEventSchema) });
|
|
3763
|
+
export const ActivityListSchema = z.object({ events: z.array(ActivityEventSchema).describe("The audit entries, newest first.") });
|
|
2338
3764
|
export const ActivityConnectionSchema = z.object({
|
|
2339
|
-
capabilityId: z.string(),
|
|
2340
|
-
provider: z.string(),
|
|
2341
|
-
gateway: z
|
|
2342
|
-
|
|
3765
|
+
capabilityId: z.string().describe("Which connection."),
|
|
3766
|
+
provider: z.string().describe("Which service it is."),
|
|
3767
|
+
gateway: z
|
|
3768
|
+
.enum(["ready", "connecting", "pairing", "disconnected", "idle"])
|
|
3769
|
+
.describe("Idle means it is up but has nothing to listen for, which is different from a connection that should be up and is not. Pairing means somebody started a sign-in and never finished it, which no amount of waiting will fix."),
|
|
3770
|
+
lastError: z.string().optional().describe("The most recent thing that went wrong on it."),
|
|
2343
3771
|
});
|
|
2344
3772
|
export const ActivityStatusSchema = z.object({
|
|
2345
|
-
connections: z
|
|
2346
|
-
|
|
3773
|
+
connections: z
|
|
3774
|
+
.array(ActivityConnectionSchema)
|
|
3775
|
+
.describe("Each source feeding the record, and whether it is working. Probed now rather than remembered."),
|
|
3776
|
+
voice: z
|
|
3777
|
+
.object({
|
|
3778
|
+
channelId: z.string().describe("Which channel."),
|
|
3779
|
+
channelName: z.string().describe("What it is called."),
|
|
3780
|
+
startedAt: z.number().describe("When it joined, in milliseconds."),
|
|
3781
|
+
participants: z.array(z.string()).describe("Who else is in it."),
|
|
3782
|
+
})
|
|
3783
|
+
.optional()
|
|
3784
|
+
.describe("A voice call the sandbox is currently in, when it is in one."),
|
|
2347
3785
|
});
|
|
2348
3786
|
export const UsageTurnSchema = z.object({
|
|
2349
|
-
at: z.number(),
|
|
2350
|
-
day: z.string(),
|
|
2351
|
-
provider: z.string(),
|
|
2352
|
-
account: z.string().optional(),
|
|
2353
|
-
model: z
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
3787
|
+
at: z.number().describe("When the turn ended, in milliseconds."),
|
|
3788
|
+
day: z.string().describe("The day it fell in, as YYYY-MM-DD in UTC, worked out once so nothing downstream has to do timezone arithmetic."),
|
|
3789
|
+
provider: z.string().describe("Which model provider served it."),
|
|
3790
|
+
account: z.string().optional().describe("Which account paid. Absent for a turn run on a plain key, which belongs to no account."),
|
|
3791
|
+
model: z
|
|
3792
|
+
.string()
|
|
3793
|
+
.optional()
|
|
3794
|
+
.describe("The model that actually ran, past whatever was asked for and every default. Absent only when the provider's own default served it without being named."),
|
|
3795
|
+
harness: z.string().describe("Which agentic loop it ran on."),
|
|
3796
|
+
conversationId: z
|
|
3797
|
+
.string()
|
|
3798
|
+
.optional()
|
|
3799
|
+
.describe("Which conversation it belonged to, so spending can be traced to a card. Absent only for an internal one-off with no conversation at all."),
|
|
3800
|
+
turns: z
|
|
3801
|
+
.number()
|
|
3802
|
+
.describe("The provider's own count for the request, since one exchange can be several under the hood. One when it reported none."),
|
|
3803
|
+
inputTokens: z.number().describe("Tokens sent."),
|
|
3804
|
+
outputTokens: z.number().describe("Tokens received."),
|
|
3805
|
+
cacheReadTokens: z.number().describe("Tokens served from cache, which cost less."),
|
|
3806
|
+
cacheCreationTokens: z.number().describe("Tokens written to cache, which cost more up front and less afterwards."),
|
|
3807
|
+
costUsd: z.number().describe("What it cost, in dollars."),
|
|
3808
|
+
durationMs: z.number().describe("How long it took, in milliseconds."),
|
|
2363
3809
|
terse: z.boolean().optional(),
|
|
2364
3810
|
iqSearchArm: z.boolean().optional(),
|
|
2365
3811
|
iqSearchCohort: z.string().optional(),
|
|
@@ -2371,25 +3817,32 @@ export const UsageTurnSchema = z.object({
|
|
|
2371
3817
|
tierRouted: z.boolean().optional(),
|
|
2372
3818
|
});
|
|
2373
3819
|
export const UsageRollupRowSchema = z.object({
|
|
2374
|
-
day: z.string(),
|
|
2375
|
-
provider: z.string(),
|
|
2376
|
-
account: z.string().optional(),
|
|
2377
|
-
model: z.string().optional(),
|
|
2378
|
-
harness: z.string(),
|
|
2379
|
-
conversationId: z.string().optional(),
|
|
2380
|
-
turns: z.number(),
|
|
2381
|
-
inputTokens: z.number(),
|
|
2382
|
-
outputTokens: z.number(),
|
|
2383
|
-
cacheReadTokens: z.number(),
|
|
2384
|
-
cacheCreationTokens: z.number(),
|
|
2385
|
-
costUsd: z.number(),
|
|
2386
|
-
durationMs: z.number(),
|
|
3820
|
+
day: z.string().describe("The day, as YYYY-MM-DD in UTC."),
|
|
3821
|
+
provider: z.string().describe("Which model provider."),
|
|
3822
|
+
account: z.string().optional().describe("Which account. Absent for work run on a plain key."),
|
|
3823
|
+
model: z.string().optional().describe("Which model."),
|
|
3824
|
+
harness: z.string().describe("Which agentic loop."),
|
|
3825
|
+
conversationId: z.string().optional().describe("Which conversation."),
|
|
3826
|
+
turns: z.number().describe("Turns in this group."),
|
|
3827
|
+
inputTokens: z.number().describe("Tokens sent."),
|
|
3828
|
+
outputTokens: z.number().describe("Tokens received."),
|
|
3829
|
+
cacheReadTokens: z.number().describe("Tokens served from cache."),
|
|
3830
|
+
cacheCreationTokens: z.number().describe("Tokens written to cache."),
|
|
3831
|
+
costUsd: z.number().describe("What the group cost, in dollars."),
|
|
3832
|
+
durationMs: z.number().describe("Time spent, in milliseconds."),
|
|
2387
3833
|
});
|
|
2388
3834
|
export const DayWindowQuerySchema = z.object({
|
|
2389
|
-
from: z.string().optional(),
|
|
2390
|
-
to: z
|
|
3835
|
+
from: z.string().optional().describe("First day to include, as YYYY-MM-DD in UTC. Leave it out for everything up to the end day."),
|
|
3836
|
+
to: z
|
|
3837
|
+
.string()
|
|
3838
|
+
.optional()
|
|
3839
|
+
.describe("Last day to include, as YYYY-MM-DD in UTC, and it is included rather than excluded. Leave it out for everything from the start day onwards."),
|
|
3840
|
+
});
|
|
3841
|
+
export const UsageRollupSchema = z.object({
|
|
3842
|
+
rows: z
|
|
3843
|
+
.array(UsageRollupRowSchema)
|
|
3844
|
+
.describe("Spending grouped by day, provider, account, model and conversation. Everything a cost screen shows is a rearrangement of these rows, which is why there is no second call for any of it."),
|
|
2391
3845
|
});
|
|
2392
|
-
export const UsageRollupSchema = z.object({ rows: z.array(UsageRollupRowSchema) });
|
|
2393
3846
|
export const UsageAccountSchema = z.object({
|
|
2394
3847
|
provider: z.string(),
|
|
2395
3848
|
account: z.string(),
|
|
@@ -2402,94 +3855,178 @@ export const UsageAccountSchema = z.object({
|
|
|
2402
3855
|
});
|
|
2403
3856
|
export const UsageSummarySchema = z.object({ accounts: z.array(UsageAccountSchema) });
|
|
2404
3857
|
export const LogFileEntrySchema = z.object({
|
|
2405
|
-
name: z.string(),
|
|
2406
|
-
sizeBytes: z.number(),
|
|
2407
|
-
modifiedAt: z.number(),
|
|
3858
|
+
name: z.string().describe("Its name, which is what the read route takes."),
|
|
3859
|
+
sizeBytes: z.number().describe("Size in bytes."),
|
|
3860
|
+
modifiedAt: z.number().describe("When it last changed, in milliseconds."),
|
|
3861
|
+
});
|
|
3862
|
+
export const LogsListSchema = z.object({
|
|
3863
|
+
files: z.array(LogFileEntrySchema).describe("Every log the sandbox keeps: captured terminal output, command runs, and its own log."),
|
|
2408
3864
|
});
|
|
2409
|
-
export const LogsListSchema = z.object({ files: z.array(LogFileEntrySchema) });
|
|
2410
3865
|
export const LogReadQuerySchema = z.object({
|
|
2411
|
-
name: z.string().min(1),
|
|
2412
|
-
bytes: z.coerce
|
|
3866
|
+
name: z.string().min(1).describe("Which log. It travels in the query rather than the address, because log names contain slashes."),
|
|
3867
|
+
bytes: z.coerce
|
|
3868
|
+
.number()
|
|
3869
|
+
.min(1)
|
|
3870
|
+
.max(1_048_576)
|
|
3871
|
+
.default(65_536)
|
|
3872
|
+
.describe("How much of the end to read. The newest bytes win when the file is larger."),
|
|
2413
3873
|
});
|
|
2414
3874
|
export const LogReadSchema = z.object({
|
|
2415
|
-
name: z.string(),
|
|
2416
|
-
sizeBytes: z.number(),
|
|
2417
|
-
text: z.string(),
|
|
2418
|
-
truncated: z.boolean(),
|
|
3875
|
+
name: z.string().describe("Which log this is from."),
|
|
3876
|
+
sizeBytes: z.number().describe("How large the whole file is."),
|
|
3877
|
+
text: z.string().describe("The end of it, as text."),
|
|
3878
|
+
truncated: z.boolean().describe("There is more before what you got."),
|
|
2419
3879
|
});
|
|
2420
3880
|
export const PresenceReportSchema = z.object({
|
|
2421
|
-
clientId: z.string(),
|
|
2422
|
-
idle: z.boolean(),
|
|
2423
|
-
view: z.string().optional(),
|
|
2424
|
-
sessionId: z.string().optional(),
|
|
2425
|
-
path: z
|
|
3881
|
+
clientId: z.string().describe("This connection's own id, the same one it gave the event stream."),
|
|
3882
|
+
idle: z.boolean().describe("Whether the person has stopped doing anything."),
|
|
3883
|
+
view: z.string().optional().describe("Which view they are on."),
|
|
3884
|
+
sessionId: z.string().optional().describe("Which conversation they have open."),
|
|
3885
|
+
path: z
|
|
3886
|
+
.string()
|
|
3887
|
+
.optional()
|
|
3888
|
+
.describe("Which file they are looking at. Sent whole rather than merged: leaving a field out clears it, so a tab that closes a file drops the path in the same report."),
|
|
2426
3889
|
});
|
|
2427
3890
|
export const WebPushChannelSchema = z.object({
|
|
2428
|
-
kind: z.literal("webpush"),
|
|
2429
|
-
endpoint: z.url(),
|
|
2430
|
-
keys: z
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
3891
|
+
kind: z.literal("webpush").describe("A browser, which the sandbox can reach directly and encrypt end to end."),
|
|
3892
|
+
endpoint: z.url().describe("Where that browser's push service accepts sends. It also identifies the device everywhere else in this group."),
|
|
3893
|
+
keys: z
|
|
3894
|
+
.object({
|
|
3895
|
+
p256dh: z.string().min(1).describe("The browser's public key, for encrypting what is sent."),
|
|
3896
|
+
auth: z.string().min(1).describe("The browser's secret, for the same."),
|
|
3897
|
+
})
|
|
3898
|
+
.describe("What the browser handed you when it subscribed. Post it back exactly as it came; nothing reshapes it."),
|
|
2434
3899
|
});
|
|
2435
3900
|
export const RelayChannelSchema = z.object({
|
|
2436
|
-
kind: z
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
3901
|
+
kind: z
|
|
3902
|
+
.literal("relay")
|
|
3903
|
+
.describe("A native app, whose operating system only accepts sends from the app's publisher, so the sandbox posts through a relay instead. The message passes through that relay readable, which is the price of the publisher having to be in the loop."),
|
|
3904
|
+
url: z.url().describe("Where to post a send. Recorded rather than assumed, so the sandbox need not know any platform by name."),
|
|
3905
|
+
deviceId: z.string().min(1).describe("The device's id, which also identifies this registration everywhere else in this group."),
|
|
3906
|
+
secret: z.string().min(1).describe("Proof that this sandbox may notify this device. The relay never learns which sandbox is calling."),
|
|
2440
3907
|
});
|
|
2441
3908
|
export const PushChannelSchema = z.discriminatedUnion("kind", [WebPushChannelSchema, RelayChannelSchema]);
|
|
2442
3909
|
export const channelId = (channel) => (channel.kind === "webpush" ? channel.endpoint : channel.deviceId);
|
|
2443
3910
|
export const PushNotificationSchema = z.object({
|
|
2444
|
-
title: z.string().min(1),
|
|
2445
|
-
body: z
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
3911
|
+
title: z.string().min(1).describe("The headline."),
|
|
3912
|
+
body: z
|
|
3913
|
+
.string()
|
|
3914
|
+
.describe("The line under it. Push services cap the whole payload at a few kilobytes, which is why nothing here carries a transcript or a diff: a notification is a pointer back, not a delivery."),
|
|
3915
|
+
url: z.string().optional().describe("Where tapping it goes. An existing tab is focused rather than a new one opened."),
|
|
3916
|
+
tag: z
|
|
3917
|
+
.string()
|
|
3918
|
+
.optional()
|
|
3919
|
+
.describe("Collapses repeats: a second notification with the same tag replaces the first instead of stacking beside it."),
|
|
3920
|
+
requireInteraction: z
|
|
3921
|
+
.boolean()
|
|
3922
|
+
.optional()
|
|
3923
|
+
.describe("Keep it on screen until it is dismissed. Used when the agent is waiting for you, where one that fades away is a question that went unanswered in silence."),
|
|
3924
|
+
});
|
|
3925
|
+
export const PushConfigSchema = z.object({
|
|
3926
|
+
publicKey: z.string().describe("The key a browser needs in order to subscribe. Native apps ignore it."),
|
|
3927
|
+
subscribed: z
|
|
3928
|
+
.boolean()
|
|
3929
|
+
.describe("Whether the asking device is already registered, so a toggle can show its real state instead of trusting the device's own permission, which can be granted with nothing behind it."),
|
|
3930
|
+
});
|
|
3931
|
+
export const PushChannelIdSchema = z.object({
|
|
3932
|
+
id: z.string().min(1).describe("Which device: a browser's push address, or a native install's device id."),
|
|
3933
|
+
});
|
|
3934
|
+
export const PushConfigQuerySchema = z.object({
|
|
3935
|
+
id: z
|
|
3936
|
+
.string()
|
|
3937
|
+
.min(1)
|
|
3938
|
+
.optional()
|
|
3939
|
+
.describe("Which device is asking. Without it the answer can only speak for the sandbox as a whole, which is rarely the question."),
|
|
3940
|
+
});
|
|
3941
|
+
export const PushTestSchema = z.object({
|
|
3942
|
+
delivered: z
|
|
3943
|
+
.number()
|
|
3944
|
+
.int()
|
|
3945
|
+
.nonnegative()
|
|
3946
|
+
.describe("How many devices actually accepted it. A count rather than a yes, because this button exists to prove a chain nobody can inspect, and the sandbox having accepted the request is not the question being asked."),
|
|
3947
|
+
});
|
|
2454
3948
|
export const PROBE_IDS = ["outdated", "audit", "knip", "jscpd", "ui", "bundle"];
|
|
2455
3949
|
export const ProbeIdSchema = z.enum(PROBE_IDS);
|
|
2456
3950
|
export const OutdatedPackageSchema = z.object({
|
|
2457
|
-
name: z.string(),
|
|
2458
|
-
current: z.string(),
|
|
2459
|
-
latest: z.string(),
|
|
2460
|
-
kind: z
|
|
2461
|
-
|
|
3951
|
+
name: z.string().describe("The dependency."),
|
|
3952
|
+
current: z.string().describe("What you are on."),
|
|
3953
|
+
latest: z.string().describe("What is published."),
|
|
3954
|
+
kind: z
|
|
3955
|
+
.enum(["major", "minor", "patch"])
|
|
3956
|
+
.describe("How far apart those are. This is not one number because forty patch releases behind is a morning's work and one major version is a project."),
|
|
3957
|
+
section: z
|
|
3958
|
+
.string()
|
|
3959
|
+
.describe("Which part of the manifest declares it. A major version behind on a build-time tool is a different risk from one that ships."),
|
|
2462
3960
|
});
|
|
2463
3961
|
export const AdvisorySchema = z.object({
|
|
2464
|
-
name: z.string(),
|
|
2465
|
-
severity: z.enum(["critical", "high", "moderate", "low", "info"]),
|
|
2466
|
-
title: z
|
|
2467
|
-
|
|
2468
|
-
|
|
3962
|
+
name: z.string().describe("The dependency it concerns."),
|
|
3963
|
+
severity: z.enum(["critical", "high", "moderate", "low", "info"]).describe("How bad it is said to be."),
|
|
3964
|
+
title: z
|
|
3965
|
+
.string()
|
|
3966
|
+
.describe("What it is, in one line. No scoring vector and no reference list: those are for reading on the advisory's own page, and carrying them would put a kilobyte of prose per finding on every poll."),
|
|
3967
|
+
patched: z
|
|
3968
|
+
.string()
|
|
3969
|
+
.optional()
|
|
3970
|
+
.describe("Which versions fix it. Absent means no fix has been published, which is exactly when nothing should offer to upgrade and something should say so instead."),
|
|
3971
|
+
dev: z.boolean().describe("Whether it only reaches build-time tooling, which is a different problem from one that reaches what you ship."),
|
|
2469
3972
|
});
|
|
2470
3973
|
export const DeadCodeSchema = z.object({
|
|
2471
|
-
files: z.number().int().nonnegative(),
|
|
2472
|
-
exports: z.number().int().nonnegative(),
|
|
2473
|
-
types: z.number().int().nonnegative(),
|
|
2474
|
-
dependencies: z.number().int().nonnegative(),
|
|
2475
|
-
devDependencies: z.number().int().nonnegative(),
|
|
2476
|
-
sample: z
|
|
3974
|
+
files: z.number().int().nonnegative().describe("Files nothing reaches."),
|
|
3975
|
+
exports: z.number().int().nonnegative().describe("Exported things nothing uses."),
|
|
3976
|
+
types: z.number().int().nonnegative().describe("Types nothing uses."),
|
|
3977
|
+
dependencies: z.number().int().nonnegative().describe("Declared dependencies nothing imports."),
|
|
3978
|
+
devDependencies: z.number().int().nonnegative().describe("The same, for build-time ones."),
|
|
3979
|
+
sample: z
|
|
3980
|
+
.array(z.string())
|
|
3981
|
+
.describe("A handful of the files, so a reader need not take the count on faith. Counts and a sample rather than the whole list, because an agent re-measures against the live tree anyway."),
|
|
2477
3982
|
});
|
|
2478
3983
|
export const DuplicationSchema = z.object({
|
|
2479
|
-
percentage: z
|
|
2480
|
-
|
|
2481
|
-
|
|
3984
|
+
percentage: z
|
|
3985
|
+
.number()
|
|
3986
|
+
.describe("How much of the scanned code is duplicated. A share rather than a count, because a count grows with the repository and would mean something different every quarter."),
|
|
3987
|
+
clones: z.number().int().nonnegative().describe("How many duplicated stretches were found."),
|
|
3988
|
+
top: z
|
|
3989
|
+
.array(z.object({
|
|
3990
|
+
lines: z.number().int().nonnegative().describe("How long the duplicated stretch is."),
|
|
3991
|
+
first: z.string().describe("One of the two places."),
|
|
3992
|
+
second: z.string().describe("The other."),
|
|
3993
|
+
}))
|
|
3994
|
+
.describe("The largest of them."),
|
|
2482
3995
|
});
|
|
2483
3996
|
export const UiScanSchema = z.object({
|
|
2484
|
-
components: z.array(z.string()),
|
|
2485
|
-
bypasses: z
|
|
2486
|
-
|
|
3997
|
+
components: z.array(z.string()).describe("The interface's own source files, with tests, stories and generated output left out."),
|
|
3998
|
+
bypasses: z
|
|
3999
|
+
.array(z.object({
|
|
4000
|
+
path: z.string().describe("The file."),
|
|
4001
|
+
count: z.number().int().positive().describe("How many times, in that file."),
|
|
4002
|
+
}))
|
|
4003
|
+
.describe("Where the design system was routed around and a value hard-coded instead. Counted per file, because a reader deciding what to open is served by a file and a number, not by eleven snippets."),
|
|
4004
|
+
idioms: z
|
|
4005
|
+
.array(z.object({
|
|
4006
|
+
id: z
|
|
4007
|
+
.string()
|
|
4008
|
+
.describe("Which outdated idiom. Looked up rather than listed here, so a sandbox one version behind can still report one this list has never heard of."),
|
|
4009
|
+
files: z.array(z.string()).describe("The files still on it."),
|
|
4010
|
+
}))
|
|
4011
|
+
.describe("Files still written the way their framework has since replaced."),
|
|
2487
4012
|
});
|
|
2488
4013
|
export const BundleSchema = z.object({
|
|
2489
|
-
dir: z
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
4014
|
+
dir: z
|
|
4015
|
+
.string()
|
|
4016
|
+
.describe("Which folder was measured. Read from build output already on disk rather than by building, so this is sometimes a commit behind and never leaves anything in your working tree."),
|
|
4017
|
+
totalBytes: z.number().int().nonnegative().describe("The whole thing, raw."),
|
|
4018
|
+
totalGzip: z
|
|
4019
|
+
.number()
|
|
4020
|
+
.int()
|
|
4021
|
+
.nonnegative()
|
|
4022
|
+
.describe("The whole thing, compressed. The ratio between the two is the difference between big and big-and-incompressible, which are different problems."),
|
|
4023
|
+
assets: z
|
|
4024
|
+
.array(z.object({
|
|
4025
|
+
path: z.string().describe("The file."),
|
|
4026
|
+
bytes: z.number().int().nonnegative().describe("Its raw size."),
|
|
4027
|
+
gzip: z.number().int().nonnegative().describe("Its compressed size."),
|
|
4028
|
+
}))
|
|
4029
|
+
.describe("What is in it, piece by piece."),
|
|
2493
4030
|
});
|
|
2494
4031
|
export const ProbeStateSchema = z.enum(["ok", "unavailable", "failed"]);
|
|
2495
4032
|
export const ProbeFactsSchema = z.discriminatedUnion("id", [
|
|
@@ -2501,66 +4038,109 @@ export const ProbeFactsSchema = z.discriminatedUnion("id", [
|
|
|
2501
4038
|
z.object({ id: z.literal("bundle"), bundle: BundleSchema }),
|
|
2502
4039
|
]);
|
|
2503
4040
|
export const ProbeResultSchema = z.object({
|
|
2504
|
-
id: ProbeIdSchema,
|
|
2505
|
-
state: ProbeStateSchema,
|
|
2506
|
-
ranAt: z.number(),
|
|
2507
|
-
tookMs: z.number().int().nonnegative(),
|
|
2508
|
-
facts: ProbeFactsSchema.optional(),
|
|
2509
|
-
reason: z
|
|
4041
|
+
id: ProbeIdSchema.describe("Which measurement this is."),
|
|
4042
|
+
state: ProbeStateSchema.describe("Whether the tool ran and reported, is not part of this repository at all, or broke. The middle one is not evidence of health: the check simply cannot be made here."),
|
|
4043
|
+
ranAt: z.number().describe("When it last finished, in milliseconds, which is what its age is measured from."),
|
|
4044
|
+
tookMs: z.number().int().nonnegative().describe("How long it took. Worth knowing before asking for it again: some of these run for minutes."),
|
|
4045
|
+
facts: ProbeFactsSchema.optional().describe("What it found, including finding nothing, which is a real answer and the one that keeps a chore quiet."),
|
|
4046
|
+
reason: z
|
|
4047
|
+
.string()
|
|
4048
|
+
.optional()
|
|
4049
|
+
.describe("Why it broke, quoted from the tool rather than summarised, or, when it never ran, what is missing. Never a sentence built from the check's own name, which would have an unmeasured check claiming there is nothing to measure."),
|
|
2510
4050
|
});
|
|
2511
4051
|
export const ChorePackageSchema = z.object({
|
|
2512
|
-
dir: z.string(),
|
|
2513
|
-
name: z.string(),
|
|
2514
|
-
engines: z.record(z.string(), z.string()).optional(),
|
|
2515
|
-
dependencies: z.array(z.string()),
|
|
2516
|
-
devDependencies: z.array(z.string()),
|
|
2517
|
-
documented: z.boolean(),
|
|
4052
|
+
dir: z.string().describe("Where the package lives."),
|
|
4053
|
+
name: z.string().describe("What it declares itself as."),
|
|
4054
|
+
engines: z.record(z.string(), z.string()).optional().describe("Which runtime versions it says it needs, verbatim."),
|
|
4055
|
+
dependencies: z.array(z.string()).describe("What it depends on."),
|
|
4056
|
+
devDependencies: z.array(z.string()).describe("What it needs only to build."),
|
|
4057
|
+
documented: z.boolean().describe("Whether it has a README, which in this workspace is what a package's own documentation is."),
|
|
2518
4058
|
});
|
|
2519
4059
|
export const ChoreShapeSchema = z.object({
|
|
2520
|
-
docs: z
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
4060
|
+
docs: z
|
|
4061
|
+
.array(z.string())
|
|
4062
|
+
.describe("The repository's own architecture documents, when it has any. Their existence is the question: a repository with none has never been through the documentation flow at all."),
|
|
4063
|
+
dockerfiles: z.array(z.string()).describe("Container definitions in it."),
|
|
4064
|
+
ci: z.array(z.string()).describe("Pipeline definitions in it."),
|
|
4065
|
+
lockfile: z.boolean().describe("Whether dependencies are pinned to exact versions, which is what makes a security audit mean anything."),
|
|
4066
|
+
packageManifest: z
|
|
4067
|
+
.boolean()
|
|
4068
|
+
.describe("Whether it is a JavaScript project at all. A Rust or Go repository has no majors to be behind on, and offering it those checks would be this surface guessing at what it is looking at."),
|
|
4069
|
+
deps: z
|
|
4070
|
+
.array(z.string())
|
|
4071
|
+
.describe("Every dependency name declared anywhere in the repository. Names rather than a verdict about which framework this is, because that judgement belongs to whatever reads this, not to a sandbox baked months ago."),
|
|
2526
4072
|
});
|
|
2527
4073
|
export const ChoreSignalsSchema = z.object({
|
|
2528
|
-
packages: z.array(ChorePackageSchema),
|
|
2529
|
-
shape: ChoreShapeSchema,
|
|
2530
|
-
hotspots: z
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
4074
|
+
packages: z.array(ChorePackageSchema).describe("Each package in the repository, as its own manifest declares it."),
|
|
4075
|
+
shape: ChoreShapeSchema.describe("What the repository is made of, which decides whether a given chore is even a sensible question to ask of it."),
|
|
4076
|
+
hotspots: z
|
|
4077
|
+
.array(WorkspaceHotspotSchema)
|
|
4078
|
+
.describe("Files that change often and are complicated at once, capped tight: a chore only asks whether something has entered the top of the ranking."),
|
|
4079
|
+
keyModules: z.array(WorkspaceKeyModuleSchema).describe("The parts the rest of the code leans on most, capped the same way."),
|
|
4080
|
+
totals: z
|
|
4081
|
+
.object({
|
|
4082
|
+
files: z.number().describe("Files counted."),
|
|
4083
|
+
symbols: z.number().describe("Named things they export."),
|
|
4084
|
+
complexity: z.number().describe("Branch points added up."),
|
|
4085
|
+
hotspots: z.number().describe("How many files qualify as hotspots at all."),
|
|
4086
|
+
})
|
|
4087
|
+
.describe("The repository in numbers."),
|
|
4088
|
+
indexed: z.boolean().describe("Whether the index these rankings came from is finished. Nothing should act on a half-built one."),
|
|
2534
4089
|
});
|
|
2535
4090
|
export const ChoreOutcomeSchema = z.enum(["acted", "reported", "clean"]);
|
|
2536
4091
|
export const ChoreLedgerEntrySchema = z.object({
|
|
2537
|
-
repo: z.string(),
|
|
2538
|
-
chore: z.string(),
|
|
2539
|
-
ranAt: z.number(),
|
|
2540
|
-
runId: z.string(),
|
|
2541
|
-
outcome: ChoreOutcomeSchema,
|
|
2542
|
-
digest: z
|
|
2543
|
-
|
|
4092
|
+
repo: z.string().describe("Which repository."),
|
|
4093
|
+
chore: z.string().describe("Which chore."),
|
|
4094
|
+
ranAt: z.number().describe("When it ran, in milliseconds."),
|
|
4095
|
+
runId: z.string().describe("The conversation that ran it, so its whole record can be opened."),
|
|
4096
|
+
outcome: ChoreOutcomeSchema.describe("What it concluded: it did something, it wrote something down, or it looked and found the finding to be false. That last one matters most, or the same turn starts again for ever."),
|
|
4097
|
+
digest: z
|
|
4098
|
+
.string()
|
|
4099
|
+
.describe("A fingerprint of the evidence standing at the time. A chore whose evidence has since changed is due again on its own merits; one whose evidence has not stays quiet."),
|
|
4100
|
+
snoozedUntil: z
|
|
4101
|
+
.number()
|
|
4102
|
+
.optional()
|
|
4103
|
+
.describe("Not until then, in milliseconds. The chore stays visible and stays out of the badge. Different from switching it off, which is a setting."),
|
|
2544
4104
|
});
|
|
2545
4105
|
export const RunningProbeSchema = z.object({
|
|
2546
|
-
repo: z.string(),
|
|
2547
|
-
id: ProbeIdSchema,
|
|
2548
|
-
askedAt: z.number(),
|
|
2549
|
-
startedAt: z
|
|
4106
|
+
repo: z.string().describe("Which repository."),
|
|
4107
|
+
id: ProbeIdSchema.describe("Which measurement."),
|
|
4108
|
+
askedAt: z.number().describe("When it was asked for, in milliseconds, so one still waiting can say how long it has waited."),
|
|
4109
|
+
startedAt: z
|
|
4110
|
+
.number()
|
|
4111
|
+
.optional()
|
|
4112
|
+
.describe("When it actually began. Absent while it is queued behind another, which is a real and common state: there is one lane for the whole sandbox."),
|
|
2550
4113
|
});
|
|
2551
4114
|
export const ChoresReportSchema = z.object({
|
|
2552
|
-
repos: z
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
4115
|
+
repos: z
|
|
4116
|
+
.array(z.object({
|
|
4117
|
+
repo: z.string().describe("Which repository."),
|
|
4118
|
+
probes: z
|
|
4119
|
+
.array(ProbeResultSchema)
|
|
4120
|
+
.describe("The expensive measurements, served from a cache with an age on each rather than run on demand."),
|
|
4121
|
+
signals: ChoreSignalsSchema.describe("The cheap facts, worked out fresh every time."),
|
|
4122
|
+
}))
|
|
4123
|
+
.describe("Every repository's standing evidence. One answer for all of them, because a badge polls this on a timer and one request per repository is the kind of poll that shows up in a battery graph."),
|
|
4124
|
+
ledger: z.array(ChoreLedgerEntrySchema).describe("What has already been done about all of it."),
|
|
4125
|
+
running: z
|
|
4126
|
+
.array(RunningProbeSchema)
|
|
4127
|
+
.describe("What is being measured right now and what is waiting behind it. Part of this read rather than a route of its own, because a screen that had to ask twice would show the two halves disagreeing."),
|
|
4128
|
+
node: z
|
|
4129
|
+
.string()
|
|
4130
|
+
.describe("The runtime version this sandbox is actually running, read off the process rather than off a manifest, because what is installed is the fact that matters and a declared range is a wish."),
|
|
4131
|
+
});
|
|
4132
|
+
export const ChoreProbeRequestSchema = z.object({
|
|
4133
|
+
repo: z.string().min(1).describe("Which repository."),
|
|
4134
|
+
id: ProbeIdSchema.describe("Which measurement to retake, ahead of its usual schedule."),
|
|
2556
4135
|
});
|
|
2557
|
-
export const ChoreProbeRequestSchema = z.object({ repo: z.string().min(1), id: ProbeIdSchema });
|
|
2558
4136
|
export const ChoreLedgerWriteSchema = ChoreLedgerEntrySchema;
|
|
2559
4137
|
export const ReadinessCheckSchema = z.object({
|
|
2560
|
-
id: z.string(),
|
|
2561
|
-
label: z.string(),
|
|
2562
|
-
status: z.enum(["pass", "warn", "fail"]),
|
|
2563
|
-
detail: z.string(),
|
|
4138
|
+
id: z.string().describe("Which check."),
|
|
4139
|
+
label: z.string().describe("What it is called."),
|
|
4140
|
+
status: z.enum(["pass", "warn", "fail"]).describe("How it went. A warning is a real third answer rather than a soft failure."),
|
|
4141
|
+
detail: z.string().describe("What it found."),
|
|
4142
|
+
});
|
|
4143
|
+
export const ExtensionReadinessSchema = z.object({
|
|
4144
|
+
checks: z.array(ReadinessCheckSchema).describe("Everything that can be checked from the extension's own files, for an author about to publish."),
|
|
2564
4145
|
});
|
|
2565
|
-
export const ExtensionReadinessSchema = z.object({ checks: z.array(ReadinessCheckSchema) });
|
|
2566
4146
|
//# sourceMappingURL=schemas.js.map
|