@otto-code/protocol 0.7.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-attention-notification.d.ts +2 -0
- package/dist/agent-attention-notification.js +2 -1
- package/dist/agent-deep-link.d.ts +8 -0
- package/dist/agent-deep-link.js +49 -0
- package/dist/agent-labels.js +4 -4
- package/dist/agent-personalities.d.ts +2 -2
- package/dist/agent-personalities.js +17 -17
- package/dist/agent-teams.d.ts +4 -4
- package/dist/agent-teams.js +5 -5
- package/dist/agent-types.d.ts +12 -10
- package/dist/agent-types.js +1 -1
- package/dist/artifacts/rpc-schemas.js +4 -4
- package/dist/artifacts/types.js +3 -3
- package/dist/binary-frames/file-transfer.d.ts +1 -0
- package/dist/binary-frames/file-transfer.js +1 -0
- package/dist/browser-automation/rpc-schemas.js +1 -1
- package/dist/client-capabilities.d.ts +3 -0
- package/dist/client-capabilities.js +9 -0
- package/dist/daemon-endpoints.d.ts +1 -1
- package/dist/default-personalities.js +11 -11
- package/dist/effort.d.ts +1 -1
- package/dist/effort.js +2 -2
- package/dist/forge-manifest.d.ts +66 -0
- package/dist/forge-manifest.js +92 -0
- package/dist/generated/validation/ws-outbound.aot.js +77653 -51519
- package/dist/git-hosting.js +3 -3
- package/dist/git-remote.d.ts +17 -0
- package/dist/git-remote.js +23 -2
- package/dist/judge-verdict.d.ts +1 -1
- package/dist/judge-verdict.js +2 -2
- package/dist/messages.d.ts +10634 -135
- package/dist/messages.js +1744 -193
- package/dist/model-tiers.d.ts +3 -3
- package/dist/model-tiers.js +4 -4
- package/dist/observed-subagent-title.d.ts +2 -2
- package/dist/observed-subagent-title.js +4 -4
- package/dist/orchestration.d.ts +3 -3
- package/dist/orchestration.js +32 -32
- package/dist/otto-config-schema.d.ts +21 -0
- package/dist/otto-config-schema.js +23 -1
- package/dist/provider-config.d.ts +92 -3
- package/dist/provider-config.js +58 -6
- package/dist/provider-manifest.d.ts +11 -1
- package/dist/provider-manifest.js +53 -5
- package/dist/schedule/cadence.d.ts +6 -0
- package/dist/schedule/cadence.js +28 -0
- package/dist/schedule/rpc-schemas.d.ts +4 -4
- package/dist/schedule/rpc-schemas.js +1 -1
- package/dist/schedule/types.d.ts +1 -1
- package/dist/schedule/types.js +3 -3
- package/dist/tool-call-display.d.ts +1 -1
- package/dist/tool-call-display.js +3 -3
- package/dist/tool-name-normalization.d.ts +2 -2
- package/dist/tool-name-normalization.js +2 -2
- package/dist/validation/ws-outbound-schema-metadata.d.ts +1950 -52
- package/dist/widgets/bridge.d.ts +5 -5
- package/dist/widgets/bridge.js +5 -5
- package/dist/widgets/document.d.ts +1 -1
- package/dist/widgets/document.js +4 -4
- package/dist/widgets/icons.d.ts +1 -1
- package/dist/widgets/icons.js +1 -1
- package/dist/widgets/theme.d.ts +2 -2
- package/dist/widgets/theme.js +2 -2
- package/dist/widgets/types.d.ts +5 -5
- package/dist/widgets/types.js +5 -5
- package/package.json +1 -1
package/dist/provider-config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { AgentProviderSchema } from "./provider-manifest.js";
|
|
2
|
+
import { AgentProviderSchema, OTTO_BRAIN_PROVIDER_ID } from "./provider-manifest.js";
|
|
3
3
|
const ProviderCommandDefaultSchema = z.object({
|
|
4
4
|
mode: z.literal("default"),
|
|
5
5
|
});
|
|
@@ -38,7 +38,7 @@ export const ProviderProfileModelSchema = z.object({
|
|
|
38
38
|
* Coarse categories for Otto's agent-facing tool catalog. Providers that receive
|
|
39
39
|
* Otto tools natively (see the openai-compat provider) can be scoped to a subset
|
|
40
40
|
* of these groups; omitting the selection means all groups. Kept deliberately
|
|
41
|
-
* coarse
|
|
41
|
+
* coarse - users pick groups, not individual tools.
|
|
42
42
|
*/
|
|
43
43
|
export const OTTO_TOOL_GROUPS = [
|
|
44
44
|
"preview",
|
|
@@ -97,7 +97,7 @@ const McpSseServerConfigSchema = z.object({
|
|
|
97
97
|
/**
|
|
98
98
|
* Canonical MCP server config. Shared by AgentSessionConfig (per-agent servers
|
|
99
99
|
* sent at create time) and ProviderOverride (provider-level servers in the
|
|
100
|
-
* daemon config). stdio entries execute arbitrary commands as the daemon user
|
|
100
|
+
* daemon config). stdio entries execute arbitrary commands as the daemon user -
|
|
101
101
|
* both sources sit behind existing trust boundaries (daemon-side config file,
|
|
102
102
|
* authenticated agent-create RPC).
|
|
103
103
|
*/
|
|
@@ -106,6 +106,50 @@ export const McpServerConfigSchema = z.discriminatedUnion("type", [
|
|
|
106
106
|
McpHttpServerConfigSchema,
|
|
107
107
|
McpSseServerConfigSchema,
|
|
108
108
|
]);
|
|
109
|
+
/**
|
|
110
|
+
* OAuth tokens held for a connector whose MCP server authenticates over OAuth
|
|
111
|
+
* 2.1 (the "log in, don't paste a token" path). Mirrors the SDK's OAuthTokens
|
|
112
|
+
* shape. Secret-bearing, so it is host-owned like every other credential in
|
|
113
|
+
* daemon config and is redacted before the config is sent to a client.
|
|
114
|
+
*
|
|
115
|
+
* `expiresAt` is absolute epoch MILLISECONDS, not the `expires_in` duration the
|
|
116
|
+
* token endpoint returns: a duration is only meaningful next to the instant it
|
|
117
|
+
* was issued, and that instant is not on the wire.
|
|
118
|
+
*/
|
|
119
|
+
export const ConnectorOAuthTokensSchema = z.object({
|
|
120
|
+
accessToken: z.string().min(1),
|
|
121
|
+
tokenType: z.string().optional(),
|
|
122
|
+
refreshToken: z.string().optional(),
|
|
123
|
+
scope: z.string().optional(),
|
|
124
|
+
expiresAt: z.number().optional(),
|
|
125
|
+
});
|
|
126
|
+
/**
|
|
127
|
+
* The OAuth client identity this daemon registered with a connector's
|
|
128
|
+
* authorization server, kept so a second login reuses the registration instead
|
|
129
|
+
* of re-running dynamic client registration. Keyed alongside the redirect URI it
|
|
130
|
+
* was registered against: if the loopback port moves, the registration is stale
|
|
131
|
+
* and must be redone.
|
|
132
|
+
*/
|
|
133
|
+
export const ConnectorOAuthClientSchema = z.object({
|
|
134
|
+
clientId: z.string().min(1),
|
|
135
|
+
clientSecret: z.string().optional(),
|
|
136
|
+
redirectUri: z.string().min(1),
|
|
137
|
+
});
|
|
138
|
+
/**
|
|
139
|
+
* Everything the daemon persists about a connector's authorization. Absent means
|
|
140
|
+
* the connector either needs no credential or carries a static token in its
|
|
141
|
+
* transport (env var for stdio, Authorization header for http/sse) - this block
|
|
142
|
+
* is only for the interactive OAuth path.
|
|
143
|
+
*/
|
|
144
|
+
export const ConnectorAuthStateSchema = z.object({
|
|
145
|
+
kind: z.literal("oauth"),
|
|
146
|
+
tokens: ConnectorOAuthTokensSchema.optional(),
|
|
147
|
+
client: ConnectorOAuthClientSchema.optional(),
|
|
148
|
+
/** Account label shown in the UI once connected (email / workspace name). */
|
|
149
|
+
account: z.string().optional(),
|
|
150
|
+
/** Epoch ms of the last successful authorization; drives "Connected on ...". */
|
|
151
|
+
authorizedAt: z.number().optional(),
|
|
152
|
+
});
|
|
109
153
|
/**
|
|
110
154
|
* Per-workspace state for a connector, keyed by workspace cwd in
|
|
111
155
|
* ConnectorConfig.workspaces. Phase 1 leaves this inert (the daemon does not
|
|
@@ -136,6 +180,11 @@ export const ConnectorConfigSchema = z.object({
|
|
|
136
180
|
enabled: z.boolean().optional(),
|
|
137
181
|
/** Tool names (unqualified, as the server reports them) withheld from the model. */
|
|
138
182
|
disabledTools: z.array(z.string()).optional(),
|
|
183
|
+
/**
|
|
184
|
+
* OAuth authorization state, when this connector logs in rather than taking a
|
|
185
|
+
* pasted token. Optional so every existing connector parses unchanged.
|
|
186
|
+
*/
|
|
187
|
+
auth: ConnectorAuthStateSchema.optional(),
|
|
139
188
|
/** Per-workspace activation keyed by workspace cwd. Phase 2; inert today. */
|
|
140
189
|
workspaces: z.record(z.string(), ConnectorWorkspaceStateSchema).optional(),
|
|
141
190
|
/** Display ordering in the UI; lower sorts first. */
|
|
@@ -165,7 +214,7 @@ export const COMPACTION_THRESHOLD_PERCENTS = [50, 60, 70, 80, 90];
|
|
|
165
214
|
/**
|
|
166
215
|
* Max model→tool→model rounds per turn for providers whose tool loop the
|
|
167
216
|
* daemon owns (openai-compat). The turn stops with an error after this many
|
|
168
|
-
* rounds without a final answer
|
|
217
|
+
* rounds without a final answer - a runaway-loop safety valve, most often hit
|
|
169
218
|
* by smaller local models that keep calling tools instead of converging.
|
|
170
219
|
* Bounds keep the setting a sane guard rail rather than an off switch.
|
|
171
220
|
*/
|
|
@@ -233,10 +282,13 @@ const PROVIDER_ID_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
|
233
282
|
export const ProviderOverridesSchema = z
|
|
234
283
|
.record(z.string(), ProviderOverrideSchema)
|
|
235
284
|
.superRefine((providers, ctx) => {
|
|
236
|
-
|
|
285
|
+
// otto-brain is builtin (endpoint comes from brain settings, not
|
|
286
|
+
// extends/label) but not a valid `extends` target for a custom provider,
|
|
287
|
+
// so it's added only here rather than to BUILTIN_PROVIDER_IDS itself.
|
|
288
|
+
const builtinProviderIdSet = new Set([...BUILTIN_PROVIDER_IDS, OTTO_BRAIN_PROVIDER_ID]);
|
|
237
289
|
// "acp" spawns a generic ACP agent process; "openai-compatible" is served
|
|
238
290
|
// natively by the daemon against an OpenAI-compatible HTTP endpoint
|
|
239
|
-
// (LM Studio, Ollama, vLLM, ...)
|
|
291
|
+
// (LM Studio, Ollama, vLLM, ...) - no external binary involved.
|
|
240
292
|
const validExtendsValues = new Set([
|
|
241
293
|
...BUILTIN_PROVIDER_IDS,
|
|
242
294
|
"acp",
|
|
@@ -8,6 +8,7 @@ export interface AgentModeVisuals {
|
|
|
8
8
|
}
|
|
9
9
|
export type AgentProviderModeDefinition = Omit<AgentMode, "icon" | "colorTier"> & AgentModeVisuals & {
|
|
10
10
|
isUnattended?: boolean;
|
|
11
|
+
selectsModel?: boolean;
|
|
11
12
|
userSelectable?: boolean;
|
|
12
13
|
};
|
|
13
14
|
export interface AgentProviderDefinition {
|
|
@@ -23,6 +24,15 @@ export interface AgentProviderDefinition {
|
|
|
23
24
|
defaultModel?: string;
|
|
24
25
|
};
|
|
25
26
|
}
|
|
27
|
+
export declare const OMP_MODES: AgentProviderModeDefinition[];
|
|
28
|
+
/**
|
|
29
|
+
* The daemon's built-in local AI host (see the definition below). Exported so
|
|
30
|
+
* other protocol/server/client code can recognize this id without repeating
|
|
31
|
+
* the string literal - notably ProviderOverridesSchema's builtin-provider
|
|
32
|
+
* check in provider-config.ts, which otherwise requires `extends`/`label` on
|
|
33
|
+
* any `providers.otto-brain` config entry.
|
|
34
|
+
*/
|
|
35
|
+
export declare const OTTO_BRAIN_PROVIDER_ID = "otto-brain";
|
|
26
36
|
export declare const AGENT_PROVIDER_DEFINITIONS: AgentProviderDefinition[];
|
|
27
37
|
export declare const DEV_AGENT_PROVIDER_DEFINITIONS: AgentProviderDefinition[];
|
|
28
38
|
export declare function getAgentProviderDefinition(provider: string, definitions?: AgentProviderDefinition[]): AgentProviderDefinition;
|
|
@@ -33,7 +43,7 @@ export declare function isValidAgentProvider(value: string, validIds?: Iterable<
|
|
|
33
43
|
export declare function getUnattendedModeId(provider: string, definitions?: AgentProviderDefinition[]): string | undefined;
|
|
34
44
|
/**
|
|
35
45
|
* Whether a user may pick this mode themselves. False only for modes explicitly
|
|
36
|
-
* flagged `userSelectable: false` in the static manifest (Claude "dontAsk")
|
|
46
|
+
* flagged `userSelectable: false` in the static manifest (Claude "dontAsk") - a
|
|
37
47
|
* system-assigned mode that agents can run in but no one selects by hand. Unknown
|
|
38
48
|
* modes (dynamic/ACP, custom providers) default to selectable. The flag is a
|
|
39
49
|
* static property of the mode, so this always consults the built-in manifest
|
|
@@ -27,11 +27,15 @@ const CLAUDE_MODES = [
|
|
|
27
27
|
description: "Uses a model classifier to review permission prompts automatically",
|
|
28
28
|
icon: "LocalPolice",
|
|
29
29
|
colorTier: "moderate",
|
|
30
|
+
// Auto also lets the CLI pick the model per turn. Codex's unrelated "auto"
|
|
31
|
+
// mode is a permission level only, which is exactly why this is a flag and
|
|
32
|
+
// not a check on the mode id.
|
|
33
|
+
selectsModel: true,
|
|
30
34
|
},
|
|
31
35
|
{
|
|
32
36
|
id: "dontAsk",
|
|
33
37
|
label: "Don't Ask",
|
|
34
|
-
description: "Runs without prompting
|
|
38
|
+
description: "Runs without prompting; actions not pre-approved are denied",
|
|
35
39
|
// Guarded unattended mode: more dangerous than acceptEdits (edits only) but
|
|
36
40
|
// safer than bypass (deny-by-default vs. run-everything), so it sits at the
|
|
37
41
|
// "moderate" tier alongside Auto.
|
|
@@ -39,7 +43,7 @@ const CLAUDE_MODES = [
|
|
|
39
43
|
colorTier: "moderate",
|
|
40
44
|
isUnattended: true,
|
|
41
45
|
// System-assigned only: the coercion target for unattended runs and for Auto
|
|
42
|
-
// on models that can't run it (Haiku). Users never pick it
|
|
46
|
+
// on models that can't run it (Haiku). Users never pick it - it's hidden from
|
|
43
47
|
// mode dropdowns and locks the control when it's an agent's active mode.
|
|
44
48
|
userSelectable: false,
|
|
45
49
|
},
|
|
@@ -127,7 +131,7 @@ const MOCK_LOAD_TEST_MODES = [
|
|
|
127
131
|
{
|
|
128
132
|
id: "dontAsk",
|
|
129
133
|
label: "Don't Ask",
|
|
130
|
-
description: "Runs without prompting
|
|
134
|
+
description: "Runs without prompting; actions not pre-approved are denied",
|
|
131
135
|
icon: "ShieldCheck",
|
|
132
136
|
colorTier: "moderate",
|
|
133
137
|
// Dev-only mirror of Claude's guarded unattended mode so deterministic E2E
|
|
@@ -147,6 +151,38 @@ const MOCK_SLOW_MODES = [
|
|
|
147
151
|
colorTier: "dangerous",
|
|
148
152
|
},
|
|
149
153
|
];
|
|
154
|
+
export const OMP_MODES = [
|
|
155
|
+
{
|
|
156
|
+
id: "full",
|
|
157
|
+
label: "Full Access",
|
|
158
|
+
description: "Launches OMP with yolo approval mode so tools run without prompts.",
|
|
159
|
+
icon: "ShieldOff",
|
|
160
|
+
colorTier: "dangerous",
|
|
161
|
+
isUnattended: true,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: "write",
|
|
165
|
+
label: "Write Approval",
|
|
166
|
+
description: "Launches OMP with write approval mode: reads are free, writes require approval.",
|
|
167
|
+
icon: "ShieldAlert",
|
|
168
|
+
colorTier: "moderate",
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: "ask",
|
|
172
|
+
label: "Always Ask",
|
|
173
|
+
description: "Launches OMP with always-ask approval mode for write and exec tools.",
|
|
174
|
+
icon: "ShieldCheck",
|
|
175
|
+
colorTier: "safe",
|
|
176
|
+
},
|
|
177
|
+
];
|
|
178
|
+
/**
|
|
179
|
+
* The daemon's built-in local AI host (see the definition below). Exported so
|
|
180
|
+
* other protocol/server/client code can recognize this id without repeating
|
|
181
|
+
* the string literal - notably ProviderOverridesSchema's builtin-provider
|
|
182
|
+
* check in provider-config.ts, which otherwise requires `extends`/`label` on
|
|
183
|
+
* any `providers.otto-brain` config entry.
|
|
184
|
+
*/
|
|
185
|
+
export const OTTO_BRAIN_PROVIDER_ID = "otto-brain";
|
|
150
186
|
export const AGENT_PROVIDER_DEFINITIONS = [
|
|
151
187
|
{
|
|
152
188
|
id: "claude",
|
|
@@ -202,7 +238,19 @@ export const AGENT_PROVIDER_DEFINITIONS = [
|
|
|
202
238
|
label: "OMP",
|
|
203
239
|
description: "Pi-compatible coding agent distributed as Oh My Pi",
|
|
204
240
|
enabledByDefault: false,
|
|
205
|
-
defaultModeId:
|
|
241
|
+
defaultModeId: "ask",
|
|
242
|
+
modes: OMP_MODES,
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
// The daemon's own local AI host. Built in rather than a catalog-installed
|
|
246
|
+
// OpenAI-compatible profile: its endpoint and credential come from the
|
|
247
|
+
// brain settings (Settings -> Host -> Otto Brain), never from per-provider
|
|
248
|
+
// URL/API-key fields. Modes are empty here for the same reason every
|
|
249
|
+
// openai-compat provider's are: the client reports them at catalog time.
|
|
250
|
+
id: OTTO_BRAIN_PROVIDER_ID,
|
|
251
|
+
label: "Otto Brain",
|
|
252
|
+
description: "Otto's built-in local AI host. Serves your local models over an OpenAI-compatible endpoint, no external server required.",
|
|
253
|
+
defaultModeId: "default",
|
|
206
254
|
modes: [],
|
|
207
255
|
},
|
|
208
256
|
];
|
|
@@ -247,7 +295,7 @@ export function getUnattendedModeId(provider, definitions = [
|
|
|
247
295
|
}
|
|
248
296
|
/**
|
|
249
297
|
* Whether a user may pick this mode themselves. False only for modes explicitly
|
|
250
|
-
* flagged `userSelectable: false` in the static manifest (Claude "dontAsk")
|
|
298
|
+
* flagged `userSelectable: false` in the static manifest (Claude "dontAsk") - a
|
|
251
299
|
* system-assigned mode that agents can run in but no one selects by hand. Unknown
|
|
252
300
|
* modes (dynamic/ACP, custom providers) default to selectable. The flag is a
|
|
253
301
|
* static property of the mode, so this always consults the built-in manifest
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert an exact rolling interval to an equivalent five-field cron cadence.
|
|
3
|
+
* Returns null when cron's calendar boundaries would change the interval.
|
|
4
|
+
*/
|
|
5
|
+
export declare function everyMsToFiveFieldCron(everyMs: number): string | null;
|
|
6
|
+
//# sourceMappingURL=cadence.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert an exact rolling interval to an equivalent five-field cron cadence.
|
|
3
|
+
* Returns null when cron's calendar boundaries would change the interval.
|
|
4
|
+
*/
|
|
5
|
+
export function everyMsToFiveFieldCron(everyMs) {
|
|
6
|
+
const minutes = everyMs / 60000;
|
|
7
|
+
if (!Number.isInteger(minutes) || minutes <= 0) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
if (minutes < 60 && 60 % minutes === 0) {
|
|
11
|
+
return `*/${minutes} * * * *`;
|
|
12
|
+
}
|
|
13
|
+
if (minutes === 60) {
|
|
14
|
+
return "0 * * * *";
|
|
15
|
+
}
|
|
16
|
+
if (minutes % 60 !== 0) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const hours = minutes / 60;
|
|
20
|
+
if (hours < 24 && 24 % hours === 0) {
|
|
21
|
+
return `0 */${hours} * * *`;
|
|
22
|
+
}
|
|
23
|
+
if (hours === 24) {
|
|
24
|
+
return "0 0 * * *";
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=cadence.js.map
|
|
@@ -129,6 +129,7 @@ export declare const ScheduleCreateResponseSchema: z.ZodObject<{
|
|
|
129
129
|
}>;
|
|
130
130
|
createdAt: z.ZodString;
|
|
131
131
|
updatedAt: z.ZodString;
|
|
132
|
+
expiresAt: z.ZodNullable<z.ZodString>;
|
|
132
133
|
cadence: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
133
134
|
type: z.ZodLiteral<"every">;
|
|
134
135
|
everyMs: z.ZodNumber;
|
|
@@ -179,7 +180,6 @@ export declare const ScheduleCreateResponseSchema: z.ZodObject<{
|
|
|
179
180
|
lastRunProvider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
180
181
|
lastRunModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
181
182
|
pausedAt: z.ZodNullable<z.ZodString>;
|
|
182
|
-
expiresAt: z.ZodNullable<z.ZodString>;
|
|
183
183
|
maxRuns: z.ZodNullable<z.ZodNumber>;
|
|
184
184
|
}, z.core.$strip>>;
|
|
185
185
|
error: z.ZodNullable<z.ZodString>;
|
|
@@ -200,6 +200,7 @@ export declare const ScheduleListResponseSchema: z.ZodObject<{
|
|
|
200
200
|
}>;
|
|
201
201
|
createdAt: z.ZodString;
|
|
202
202
|
updatedAt: z.ZodString;
|
|
203
|
+
expiresAt: z.ZodNullable<z.ZodString>;
|
|
203
204
|
cadence: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
204
205
|
type: z.ZodLiteral<"every">;
|
|
205
206
|
everyMs: z.ZodNumber;
|
|
@@ -250,7 +251,6 @@ export declare const ScheduleListResponseSchema: z.ZodObject<{
|
|
|
250
251
|
lastRunProvider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
251
252
|
lastRunModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
252
253
|
pausedAt: z.ZodNullable<z.ZodString>;
|
|
253
|
-
expiresAt: z.ZodNullable<z.ZodString>;
|
|
254
254
|
maxRuns: z.ZodNullable<z.ZodNumber>;
|
|
255
255
|
}, z.core.$strip>>;
|
|
256
256
|
error: z.ZodNullable<z.ZodString>;
|
|
@@ -385,6 +385,7 @@ export declare const SchedulePauseResponseSchema: z.ZodObject<{
|
|
|
385
385
|
}>;
|
|
386
386
|
createdAt: z.ZodString;
|
|
387
387
|
updatedAt: z.ZodString;
|
|
388
|
+
expiresAt: z.ZodNullable<z.ZodString>;
|
|
388
389
|
cadence: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
389
390
|
type: z.ZodLiteral<"every">;
|
|
390
391
|
everyMs: z.ZodNumber;
|
|
@@ -435,7 +436,6 @@ export declare const SchedulePauseResponseSchema: z.ZodObject<{
|
|
|
435
436
|
lastRunProvider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
436
437
|
lastRunModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
437
438
|
pausedAt: z.ZodNullable<z.ZodString>;
|
|
438
|
-
expiresAt: z.ZodNullable<z.ZodString>;
|
|
439
439
|
maxRuns: z.ZodNullable<z.ZodNumber>;
|
|
440
440
|
}, z.core.$strip>>;
|
|
441
441
|
error: z.ZodNullable<z.ZodString>;
|
|
@@ -456,6 +456,7 @@ export declare const ScheduleResumeResponseSchema: z.ZodObject<{
|
|
|
456
456
|
}>;
|
|
457
457
|
createdAt: z.ZodString;
|
|
458
458
|
updatedAt: z.ZodString;
|
|
459
|
+
expiresAt: z.ZodNullable<z.ZodString>;
|
|
459
460
|
cadence: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
460
461
|
type: z.ZodLiteral<"every">;
|
|
461
462
|
everyMs: z.ZodNumber;
|
|
@@ -506,7 +507,6 @@ export declare const ScheduleResumeResponseSchema: z.ZodObject<{
|
|
|
506
507
|
lastRunProvider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
507
508
|
lastRunModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
508
509
|
pausedAt: z.ZodNullable<z.ZodString>;
|
|
509
|
-
expiresAt: z.ZodNullable<z.ZodString>;
|
|
510
510
|
maxRuns: z.ZodNullable<z.ZodNumber>;
|
|
511
511
|
}, z.core.$strip>>;
|
|
512
512
|
error: z.ZodNullable<z.ZodString>;
|
|
@@ -62,7 +62,7 @@ export const ScheduleRunOnceRequestSchema = z.object({
|
|
|
62
62
|
});
|
|
63
63
|
const ScheduleUpdateNewAgentConfigSchema = z.object({
|
|
64
64
|
provider: z.string().trim().min(1).optional(),
|
|
65
|
-
// Personality binding by name
|
|
65
|
+
// Personality binding by name - or the "@team-scheduler" sentinel. Explicit
|
|
66
66
|
// null clears a stored binding; omission leaves it untouched.
|
|
67
67
|
personality: z.string().trim().min(1).nullable().optional(),
|
|
68
68
|
model: z.string().trim().min(1).nullable().optional(),
|
package/dist/schedule/types.d.ts
CHANGED
|
@@ -159,6 +159,7 @@ export declare const ScheduleSummarySchema: z.ZodObject<{
|
|
|
159
159
|
}>;
|
|
160
160
|
createdAt: z.ZodString;
|
|
161
161
|
updatedAt: z.ZodString;
|
|
162
|
+
expiresAt: z.ZodNullable<z.ZodString>;
|
|
162
163
|
cadence: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
163
164
|
type: z.ZodLiteral<"every">;
|
|
164
165
|
everyMs: z.ZodNumber;
|
|
@@ -209,7 +210,6 @@ export declare const ScheduleSummarySchema: z.ZodObject<{
|
|
|
209
210
|
lastRunProvider: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
210
211
|
lastRunModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
211
212
|
pausedAt: z.ZodNullable<z.ZodString>;
|
|
212
|
-
expiresAt: z.ZodNullable<z.ZodString>;
|
|
213
213
|
maxRuns: z.ZodNullable<z.ZodNumber>;
|
|
214
214
|
}, z.core.$strip>;
|
|
215
215
|
export type ScheduleSummary = z.infer<typeof ScheduleSummarySchema>;
|
package/dist/schedule/types.js
CHANGED
|
@@ -24,7 +24,7 @@ export const ScheduleTargetSchema = z.discriminatedUnion("type", [
|
|
|
24
24
|
cwd: z.string().trim().min(1),
|
|
25
25
|
// Optional Agent Personality binding (by name). When set, each run
|
|
26
26
|
// re-resolves the personality against the run cwd and hard-fails if it is
|
|
27
|
-
// unavailable
|
|
27
|
+
// unavailable - so schedule runs pick up personality edits between runs.
|
|
28
28
|
personality: z.string().trim().min(1).optional(),
|
|
29
29
|
modeId: z.string().trim().min(1).optional(),
|
|
30
30
|
model: z.string().trim().min(1).optional(),
|
|
@@ -57,7 +57,7 @@ export const ScheduleRunSchema = z.object({
|
|
|
57
57
|
status: z.enum(["running", "succeeded", "failed"]),
|
|
58
58
|
agentId: z.guid().nullable(),
|
|
59
59
|
workspaceId: z.string().nullable().optional(),
|
|
60
|
-
// Who actually executed this run
|
|
60
|
+
// Who actually executed this run - the resolved personality (if any),
|
|
61
61
|
// provider, and model. Stamped when the run starts (so a failed run still
|
|
62
62
|
// records its executor). Optional for back-compat: runs written before these
|
|
63
63
|
// fields existed omit them.
|
|
@@ -80,7 +80,7 @@ export const StoredScheduleSchema = z.object({
|
|
|
80
80
|
lastRunAt: z.string().nullable(),
|
|
81
81
|
lastRunStatus: z.enum(["succeeded", "failed"]).nullable().optional(),
|
|
82
82
|
lastRunError: z.string().nullable().optional(),
|
|
83
|
-
// Executor of the most recent run
|
|
83
|
+
// Executor of the most recent run - mirrors the run-level fields above so the
|
|
84
84
|
// schedule card can show "who ran it last" (personality · provider · model)
|
|
85
85
|
// without loading the full run history (ScheduleSummary omits `runs`).
|
|
86
86
|
// Optional for back-compat: schedules that never ran, or predate these
|
|
@@ -12,7 +12,7 @@ export interface ToolCallDisplayModel {
|
|
|
12
12
|
* shows a tool/action name without a full timeline item to run through
|
|
13
13
|
* {@link buildToolCallDisplayModel} (the visualizer's action labels, sub-agent
|
|
14
14
|
* activity rows). Strips the MCP/Otto namespace, consults the known-tool
|
|
15
|
-
* registry, then title-cases as a fallback
|
|
15
|
+
* registry, then title-cases as a fallback - so "mcp__otto__spawn_task",
|
|
16
16
|
* "otto.spawn_task", and a bare "spawn_task" all render as "Spawn Task".
|
|
17
17
|
*/
|
|
18
18
|
export declare function getToolDisplayName(name: string): string;
|
|
@@ -6,7 +6,7 @@ function isRecord(value) {
|
|
|
6
6
|
function readString(value) {
|
|
7
7
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
8
8
|
}
|
|
9
|
-
// Curated display names
|
|
9
|
+
// Curated display names - the registry of tools we explicitly "know about".
|
|
10
10
|
// Keyed by the lowercased leaf name (transport namespace already stripped).
|
|
11
11
|
//
|
|
12
12
|
// Only tools whose bare id does NOT title-case cleanly on its own need an entry
|
|
@@ -15,7 +15,7 @@ function readString(value) {
|
|
|
15
15
|
// camelCase ("WebSearch") names are handled by the algorithmic humanizer below
|
|
16
16
|
// and do NOT need listing.
|
|
17
17
|
//
|
|
18
|
-
// Anything not here falls through to the humanizer and still renders readably
|
|
18
|
+
// Anything not here falls through to the humanizer and still renders readably -
|
|
19
19
|
// so an unmapped tool shows up looking slightly generic (e.g. a stray provider
|
|
20
20
|
// tool), which is the cue to add it here. Extend this map to teach Otto a tool.
|
|
21
21
|
const KNOWN_TOOL_DISPLAY_NAMES = {
|
|
@@ -66,7 +66,7 @@ function humanizeToolName(name) {
|
|
|
66
66
|
* shows a tool/action name without a full timeline item to run through
|
|
67
67
|
* {@link buildToolCallDisplayModel} (the visualizer's action labels, sub-agent
|
|
68
68
|
* activity rows). Strips the MCP/Otto namespace, consults the known-tool
|
|
69
|
-
* registry, then title-cases as a fallback
|
|
69
|
+
* registry, then title-cases as a fallback - so "mcp__otto__spawn_task",
|
|
70
70
|
* "otto.spawn_task", and a bare "spawn_task" all render as "Spawn Task".
|
|
71
71
|
*/
|
|
72
72
|
export function getToolDisplayName(name) {
|
|
@@ -10,13 +10,13 @@ export declare function getOttoToolLeafName(name: string): string | null;
|
|
|
10
10
|
*
|
|
11
11
|
* Tools hosted over MCP arrive namespaced as `mcp__<server>__<tool>` (Claude
|
|
12
12
|
* Code format). The `mcp__<server>__` part is transport plumbing that means
|
|
13
|
-
* nothing to a reader
|
|
13
|
+
* nothing to a reader - "Create Issue", not "mcp__linear__create_issue". This
|
|
14
14
|
* generalizes {@link getOttoToolLeafName} to ANY server so every MCP tool reads
|
|
15
15
|
* cleanly, not just Otto's own.
|
|
16
16
|
*
|
|
17
17
|
* Returns `null` when the name carries no `mcp__…__` namespace, so callers keep
|
|
18
18
|
* plain tool names (`Read`, `bash`) and dotted/other forms untouched. Case is
|
|
19
|
-
* preserved
|
|
19
|
+
* preserved - MCP tool ids are already snake_case and callers humanize after.
|
|
20
20
|
* `speak` is never treated as namespaced (it renders as a chat bubble, not an
|
|
21
21
|
* action row).
|
|
22
22
|
*/
|
|
@@ -74,13 +74,13 @@ export function getOttoToolLeafName(name) {
|
|
|
74
74
|
*
|
|
75
75
|
* Tools hosted over MCP arrive namespaced as `mcp__<server>__<tool>` (Claude
|
|
76
76
|
* Code format). The `mcp__<server>__` part is transport plumbing that means
|
|
77
|
-
* nothing to a reader
|
|
77
|
+
* nothing to a reader - "Create Issue", not "mcp__linear__create_issue". This
|
|
78
78
|
* generalizes {@link getOttoToolLeafName} to ANY server so every MCP tool reads
|
|
79
79
|
* cleanly, not just Otto's own.
|
|
80
80
|
*
|
|
81
81
|
* Returns `null` when the name carries no `mcp__…__` namespace, so callers keep
|
|
82
82
|
* plain tool names (`Read`, `bash`) and dotted/other forms untouched. Case is
|
|
83
|
-
* preserved
|
|
83
|
+
* preserved - MCP tool ids are already snake_case and callers humanize after.
|
|
84
84
|
* `speak` is never treated as namespaced (it renders as a chat bubble, not an
|
|
85
85
|
* action row).
|
|
86
86
|
*/
|