@kodrunhq/opencode-autopilot 1.17.0 → 1.18.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/assets/commands/oc-doctor.md +17 -0
- package/bin/configure-tui.ts +1 -1
- package/package.json +1 -1
- package/src/config/v7.ts +3 -3
- package/src/config.ts +105 -21
- package/src/health/checks.ts +69 -1
- package/src/health/runner.ts +8 -2
- package/src/tools/configure.ts +1 -1
- package/src/types/background.ts +51 -0
- package/src/types/mcp.ts +27 -0
- package/src/types/recovery.ts +39 -0
- package/src/types/routing.ts +39 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
# opencode-autopilot
|
|
3
|
+
description: Run plugin health diagnostics — config validity, agent injection, native suppression, assets, memory, commands, and v7 config fields (background, routing, recovery, mcp)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Invoke the `oc_doctor` tool to run a full health check on the opencode-autopilot plugin.
|
|
7
|
+
|
|
8
|
+
`oc_doctor` runs the current built-in health checks and reports the results by diagnostic area. These checks cover:
|
|
9
|
+
|
|
10
|
+
- **Config health** — The plugin config exists, parses correctly, and required modern config sections such as `background`, `routing`, `recovery`, and `mcp` are present or reported as needing migration.
|
|
11
|
+
- **Agent setup** — Expected autopilot agents are present in the OpenCode config, and native `plan`/`build` agents are suppressed as subagents.
|
|
12
|
+
- **Assets and installation paths** — Bundled asset directories and the global `~/.config/opencode/` target are accessible.
|
|
13
|
+
- **Skill loading** — Skills load correctly and are filtered against the detected project stack.
|
|
14
|
+
- **Memory storage** — The memory SQLite database is available, readable, or cleanly reported as not yet initialized on first install.
|
|
15
|
+
- **Command files** — Expected slash command files exist and have valid YAML frontmatter.
|
|
16
|
+
|
|
17
|
+
Each failing check includes a **Fix** suggestion. Run this after installation, after upgrades, or whenever something feels off.
|
package/bin/configure-tui.ts
CHANGED
|
@@ -307,7 +307,7 @@ export async function runConfigure(configPath: string = CONFIG_PATH): Promise<vo
|
|
|
307
307
|
|
|
308
308
|
const newConfig = {
|
|
309
309
|
...baseConfig,
|
|
310
|
-
version:
|
|
310
|
+
version: 7 as const,
|
|
311
311
|
configured: true,
|
|
312
312
|
groups: groupsRecord,
|
|
313
313
|
overrides: baseConfig.overrides ?? {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kodrunhq/opencode-autopilot",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"description": "Curated agents, skills, and commands for the OpenCode AI coding CLI — autonomous orchestrator, multi-agent code review, model fallback, and in-session asset creation tools.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"keywords": [
|
package/src/config/v7.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type PluginConfigV7 = Omit<PluginConfig, "version"> & {
|
|
|
5
5
|
readonly background?: {
|
|
6
6
|
readonly enabled: boolean;
|
|
7
7
|
readonly maxConcurrent: number;
|
|
8
|
-
readonly
|
|
8
|
+
readonly persistence: boolean;
|
|
9
9
|
};
|
|
10
10
|
readonly autonomy?: {
|
|
11
11
|
readonly enabled: boolean;
|
|
@@ -21,7 +21,7 @@ export function migrateV6toV7(v6Config: PluginConfig): PluginConfigV7 {
|
|
|
21
21
|
background: {
|
|
22
22
|
enabled: true,
|
|
23
23
|
maxConcurrent: 5,
|
|
24
|
-
|
|
24
|
+
persistence: true,
|
|
25
25
|
},
|
|
26
26
|
autonomy: {
|
|
27
27
|
enabled: false,
|
|
@@ -35,7 +35,7 @@ export const v7ConfigDefaults = {
|
|
|
35
35
|
background: {
|
|
36
36
|
enabled: true,
|
|
37
37
|
maxConcurrent: 5,
|
|
38
|
-
|
|
38
|
+
persistence: true,
|
|
39
39
|
},
|
|
40
40
|
autonomy: {
|
|
41
41
|
enabled: false,
|
package/src/config.ts
CHANGED
|
@@ -10,6 +10,10 @@ import {
|
|
|
10
10
|
testModeDefaults,
|
|
11
11
|
} from "./orchestrator/fallback/fallback-config";
|
|
12
12
|
import { AGENT_REGISTRY, ALL_GROUP_IDS } from "./registry/model-groups";
|
|
13
|
+
import { backgroundConfigSchema, backgroundDefaults } from "./types/background";
|
|
14
|
+
import { mcpConfigSchema, mcpDefaults } from "./types/mcp";
|
|
15
|
+
import { recoveryConfigSchema, recoveryDefaults } from "./types/recovery";
|
|
16
|
+
import { routingConfigSchema, routingDefaults } from "./types/routing";
|
|
13
17
|
import { ensureDir, isEnoentError } from "./utils/fs-helpers";
|
|
14
18
|
import { getGlobalConfigDir } from "./utils/paths";
|
|
15
19
|
|
|
@@ -182,14 +186,47 @@ const pluginConfigSchemaV6 = z
|
|
|
182
186
|
}
|
|
183
187
|
});
|
|
184
188
|
|
|
185
|
-
|
|
186
|
-
export const pluginConfigSchema = pluginConfigSchemaV6;
|
|
189
|
+
type PluginConfigV6 = z.infer<typeof pluginConfigSchemaV6>;
|
|
187
190
|
|
|
188
|
-
|
|
191
|
+
const pluginConfigSchemaV7 = z
|
|
192
|
+
.object({
|
|
193
|
+
version: z.literal(7),
|
|
194
|
+
configured: z.boolean(),
|
|
195
|
+
groups: z.record(z.string(), groupModelAssignmentSchema).default({}),
|
|
196
|
+
overrides: z.record(z.string(), agentOverrideSchema).default({}),
|
|
197
|
+
orchestrator: orchestratorConfigSchema.default(orchestratorDefaults),
|
|
198
|
+
confidence: confidenceConfigSchema.default(confidenceDefaults),
|
|
199
|
+
fallback: fallbackConfigSchemaV6.default(fallbackDefaultsV6),
|
|
200
|
+
memory: memoryConfigSchema.default(memoryDefaults),
|
|
201
|
+
background: backgroundConfigSchema.default(backgroundDefaults),
|
|
202
|
+
autonomy: z
|
|
203
|
+
.object({
|
|
204
|
+
enabled: z.boolean().default(false),
|
|
205
|
+
verification: z.enum(["strict", "normal", "lenient"]).default("normal"),
|
|
206
|
+
maxIterations: z.number().int().min(1).max(50).default(10),
|
|
207
|
+
})
|
|
208
|
+
.default({ enabled: false, verification: "normal", maxIterations: 10 }),
|
|
209
|
+
routing: routingConfigSchema.default(routingDefaults),
|
|
210
|
+
recovery: recoveryConfigSchema.default(recoveryDefaults),
|
|
211
|
+
mcp: mcpConfigSchema.default(mcpDefaults),
|
|
212
|
+
})
|
|
213
|
+
.superRefine((config, ctx) => {
|
|
214
|
+
for (const groupId of Object.keys(config.groups)) {
|
|
215
|
+
if (!ALL_GROUP_IDS.includes(groupId as (typeof ALL_GROUP_IDS)[number])) {
|
|
216
|
+
ctx.addIssue({
|
|
217
|
+
code: z.ZodIssueCode.custom,
|
|
218
|
+
path: ["groups", groupId],
|
|
219
|
+
message: `Unknown group id "${groupId}". Expected one of: ${ALL_GROUP_IDS.join(", ")}`,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
});
|
|
189
224
|
|
|
190
|
-
export const
|
|
225
|
+
export const pluginConfigSchema = pluginConfigSchemaV7;
|
|
226
|
+
|
|
227
|
+
export type PluginConfig = z.infer<typeof pluginConfigSchemaV7>;
|
|
191
228
|
|
|
192
|
-
|
|
229
|
+
export const CONFIG_PATH = join(getGlobalConfigDir(), "opencode-autopilot.json");
|
|
193
230
|
|
|
194
231
|
function migrateV1toV2(v1Config: PluginConfigV1): PluginConfigV2 {
|
|
195
232
|
return {
|
|
@@ -274,7 +311,7 @@ function migrateV4toV5(v4Config: PluginConfigV4): PluginConfigV5 {
|
|
|
274
311
|
};
|
|
275
312
|
}
|
|
276
313
|
|
|
277
|
-
function migrateV5toV6(v5Config: PluginConfigV5):
|
|
314
|
+
function migrateV5toV6(v5Config: PluginConfigV5): PluginConfigV6 {
|
|
278
315
|
return {
|
|
279
316
|
version: 6 as const,
|
|
280
317
|
configured: v5Config.configured,
|
|
@@ -287,68 +324,106 @@ function migrateV5toV6(v5Config: PluginConfigV5): PluginConfig {
|
|
|
287
324
|
};
|
|
288
325
|
}
|
|
289
326
|
|
|
290
|
-
|
|
327
|
+
export const v7ConfigDefaults = {
|
|
328
|
+
background: backgroundDefaults,
|
|
329
|
+
autonomy: {
|
|
330
|
+
enabled: false,
|
|
331
|
+
verification: "normal" as const,
|
|
332
|
+
maxIterations: 10,
|
|
333
|
+
},
|
|
334
|
+
routing: routingDefaults,
|
|
335
|
+
recovery: recoveryDefaults,
|
|
336
|
+
mcp: mcpDefaults,
|
|
337
|
+
} as const;
|
|
338
|
+
|
|
339
|
+
export function migrateV6toV7(v6Config: PluginConfigV6): PluginConfig {
|
|
340
|
+
return {
|
|
341
|
+
version: 7 as const,
|
|
342
|
+
configured: v6Config.configured,
|
|
343
|
+
groups: v6Config.groups,
|
|
344
|
+
overrides: v6Config.overrides,
|
|
345
|
+
orchestrator: v6Config.orchestrator,
|
|
346
|
+
confidence: v6Config.confidence,
|
|
347
|
+
fallback: v6Config.fallback,
|
|
348
|
+
memory: v6Config.memory,
|
|
349
|
+
background: backgroundDefaults,
|
|
350
|
+
autonomy: {
|
|
351
|
+
enabled: false,
|
|
352
|
+
verification: "normal",
|
|
353
|
+
maxIterations: 10,
|
|
354
|
+
},
|
|
355
|
+
routing: routingDefaults,
|
|
356
|
+
recovery: recoveryDefaults,
|
|
357
|
+
mcp: mcpDefaults,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
291
360
|
|
|
292
361
|
export async function loadConfig(configPath: string = CONFIG_PATH): Promise<PluginConfig | null> {
|
|
293
362
|
try {
|
|
294
363
|
const raw = await readFile(configPath, "utf-8");
|
|
295
364
|
const parsed = JSON.parse(raw);
|
|
296
365
|
|
|
297
|
-
|
|
366
|
+
const v7Result = pluginConfigSchemaV7.safeParse(parsed);
|
|
367
|
+
if (v7Result.success) return v7Result.data;
|
|
368
|
+
|
|
298
369
|
const v6Result = pluginConfigSchemaV6.safeParse(parsed);
|
|
299
|
-
if (v6Result.success)
|
|
370
|
+
if (v6Result.success) {
|
|
371
|
+
const migrated = migrateV6toV7(v6Result.data);
|
|
372
|
+
await saveConfig(migrated, configPath);
|
|
373
|
+
return migrated;
|
|
374
|
+
}
|
|
300
375
|
|
|
301
|
-
// Try v5 and migrate to v6
|
|
302
376
|
const v5Result = pluginConfigSchemaV5.safeParse(parsed);
|
|
303
377
|
if (v5Result.success) {
|
|
304
|
-
const
|
|
378
|
+
const v6 = migrateV5toV6(v5Result.data);
|
|
379
|
+
const migrated = migrateV6toV7(v6);
|
|
305
380
|
await saveConfig(migrated, configPath);
|
|
306
381
|
return migrated;
|
|
307
382
|
}
|
|
308
383
|
|
|
309
|
-
// Try v4 → v5 → v6
|
|
310
384
|
const v4Result = pluginConfigSchemaV4.safeParse(parsed);
|
|
311
385
|
if (v4Result.success) {
|
|
312
386
|
const v5 = migrateV4toV5(v4Result.data);
|
|
313
|
-
const
|
|
387
|
+
const v6 = migrateV5toV6(v5);
|
|
388
|
+
const migrated = migrateV6toV7(v6);
|
|
314
389
|
await saveConfig(migrated, configPath);
|
|
315
390
|
return migrated;
|
|
316
391
|
}
|
|
317
392
|
|
|
318
|
-
// Try v3 → v4 → v5 → v6
|
|
319
393
|
const v3Result = pluginConfigSchemaV3.safeParse(parsed);
|
|
320
394
|
if (v3Result.success) {
|
|
321
395
|
const v4 = migrateV3toV4(v3Result.data);
|
|
322
396
|
const v5 = migrateV4toV5(v4);
|
|
323
|
-
const
|
|
397
|
+
const v6 = migrateV5toV6(v5);
|
|
398
|
+
const migrated = migrateV6toV7(v6);
|
|
324
399
|
await saveConfig(migrated, configPath);
|
|
325
400
|
return migrated;
|
|
326
401
|
}
|
|
327
402
|
|
|
328
|
-
// Try v2 → v3 → v4 → v5 → v6
|
|
329
403
|
const v2Result = pluginConfigSchemaV2.safeParse(parsed);
|
|
330
404
|
if (v2Result.success) {
|
|
331
405
|
const v3 = migrateV2toV3(v2Result.data);
|
|
332
406
|
const v4 = migrateV3toV4(v3);
|
|
333
407
|
const v5 = migrateV4toV5(v4);
|
|
334
|
-
const
|
|
408
|
+
const v6 = migrateV5toV6(v5);
|
|
409
|
+
const migrated = migrateV6toV7(v6);
|
|
335
410
|
await saveConfig(migrated, configPath);
|
|
336
411
|
return migrated;
|
|
337
412
|
}
|
|
338
413
|
|
|
339
|
-
// Try v1 → v2 → v3 → v4 → v5 → v6
|
|
340
414
|
const v1Result = pluginConfigSchemaV1.safeParse(parsed);
|
|
341
415
|
if (v1Result.success) {
|
|
342
416
|
const v2 = migrateV1toV2(v1Result.data);
|
|
343
417
|
const v3 = migrateV2toV3(v2);
|
|
344
418
|
const v4 = migrateV3toV4(v3);
|
|
345
419
|
const v5 = migrateV4toV5(v4);
|
|
346
|
-
const
|
|
420
|
+
const v6 = migrateV5toV6(v5);
|
|
421
|
+
const migrated = migrateV6toV7(v6);
|
|
347
422
|
await saveConfig(migrated, configPath);
|
|
348
423
|
return migrated;
|
|
349
424
|
}
|
|
350
425
|
|
|
351
|
-
return
|
|
426
|
+
return pluginConfigSchemaV7.parse(parsed);
|
|
352
427
|
} catch (error: unknown) {
|
|
353
428
|
if (isEnoentError(error)) return null;
|
|
354
429
|
throw error;
|
|
@@ -371,7 +446,7 @@ export function isFirstLoad(config: PluginConfig | null): boolean {
|
|
|
371
446
|
|
|
372
447
|
export function createDefaultConfig(): PluginConfig {
|
|
373
448
|
return {
|
|
374
|
-
version:
|
|
449
|
+
version: 7 as const,
|
|
375
450
|
configured: false,
|
|
376
451
|
groups: {},
|
|
377
452
|
overrides: {},
|
|
@@ -379,5 +454,14 @@ export function createDefaultConfig(): PluginConfig {
|
|
|
379
454
|
confidence: confidenceDefaults,
|
|
380
455
|
fallback: fallbackDefaultsV6,
|
|
381
456
|
memory: memoryDefaults,
|
|
457
|
+
background: backgroundDefaults,
|
|
458
|
+
autonomy: {
|
|
459
|
+
enabled: false,
|
|
460
|
+
verification: "normal",
|
|
461
|
+
maxIterations: 10,
|
|
462
|
+
},
|
|
463
|
+
routing: routingDefaults,
|
|
464
|
+
recovery: recoveryDefaults,
|
|
465
|
+
mcp: mcpDefaults,
|
|
382
466
|
};
|
|
383
467
|
}
|
package/src/health/checks.ts
CHANGED
|
@@ -44,7 +44,7 @@ export async function configHealthCheck(configPath?: string): Promise<HealthResu
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const LATEST_CONFIG_VERSION =
|
|
47
|
+
const LATEST_CONFIG_VERSION = 7;
|
|
48
48
|
|
|
49
49
|
export async function configVersionCheck(configPath?: string): Promise<HealthResult> {
|
|
50
50
|
try {
|
|
@@ -141,6 +141,74 @@ export async function configGroupsCheck(configPath?: string): Promise<HealthResu
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
/** v7 config fields that must be present on a v7 config. */
|
|
145
|
+
const V7_REQUIRED_FIELDS: readonly string[] = Object.freeze([
|
|
146
|
+
"background",
|
|
147
|
+
"routing",
|
|
148
|
+
"recovery",
|
|
149
|
+
"mcp",
|
|
150
|
+
]);
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Check that v7 configs contain all four new top-level fields introduced in v7:
|
|
154
|
+
* background, routing, recovery, and mcp.
|
|
155
|
+
* Inspects the raw on-disk JSON so that Zod default-filling does not mask
|
|
156
|
+
* actually-missing fields. Pre-v7 configs receive a pass with a migration notice.
|
|
157
|
+
*/
|
|
158
|
+
export async function configV7FieldsCheck(configPath?: string): Promise<HealthResult> {
|
|
159
|
+
const resolvedPath = configPath ?? join(getGlobalConfigDir(), "opencode-autopilot.json");
|
|
160
|
+
try {
|
|
161
|
+
let raw: Record<string, unknown>;
|
|
162
|
+
try {
|
|
163
|
+
const content = await readFile(resolvedPath, "utf-8");
|
|
164
|
+
raw = JSON.parse(content) as Record<string, unknown>;
|
|
165
|
+
} catch (error: unknown) {
|
|
166
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
167
|
+
return Object.freeze({
|
|
168
|
+
name: "config-v7-fields",
|
|
169
|
+
status: "fail" as const,
|
|
170
|
+
message: "Config file not found",
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const version = typeof raw.version === "number" ? raw.version : 0;
|
|
177
|
+
|
|
178
|
+
if (version < 7) {
|
|
179
|
+
return Object.freeze({
|
|
180
|
+
name: "config-v7-fields",
|
|
181
|
+
status: "pass" as const,
|
|
182
|
+
message: `Config v${version} will gain v7 fields (background, routing, recovery, mcp) on next load`,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const missingFields = V7_REQUIRED_FIELDS.filter((field) => !(field in raw));
|
|
187
|
+
|
|
188
|
+
if (missingFields.length > 0) {
|
|
189
|
+
return Object.freeze({
|
|
190
|
+
name: "config-v7-fields",
|
|
191
|
+
status: "fail" as const,
|
|
192
|
+
message: `Config v7 is missing required fields: ${missingFields.join(", ")}`,
|
|
193
|
+
details: Object.freeze(missingFields),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return Object.freeze({
|
|
198
|
+
name: "config-v7-fields",
|
|
199
|
+
status: "pass" as const,
|
|
200
|
+
message: `Config v7 fields present: ${V7_REQUIRED_FIELDS.join(", ")}`,
|
|
201
|
+
});
|
|
202
|
+
} catch (error: unknown) {
|
|
203
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
204
|
+
return Object.freeze({
|
|
205
|
+
name: "config-v7-fields",
|
|
206
|
+
status: "fail" as const,
|
|
207
|
+
message: `Config v7 fields check failed: ${msg}`,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
144
212
|
/** Standard agent names, derived from the agents barrel export. */
|
|
145
213
|
const STANDARD_AGENT_NAMES: readonly string[] = Object.freeze([
|
|
146
214
|
"researcher",
|
package/src/health/runner.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
assetHealthCheck,
|
|
5
5
|
commandHealthCheck,
|
|
6
6
|
configHealthCheck,
|
|
7
|
+
configV7FieldsCheck,
|
|
7
8
|
memoryHealthCheck,
|
|
8
9
|
nativeAgentSuppressionHealthCheck,
|
|
9
10
|
skillHealthCheck,
|
|
@@ -43,16 +44,20 @@ export async function runHealthChecks(options?: {
|
|
|
43
44
|
}): Promise<HealthReport> {
|
|
44
45
|
const start = Date.now();
|
|
45
46
|
|
|
47
|
+
const configOutcome = await Promise.allSettled([configHealthCheck(options?.configPath)]);
|
|
48
|
+
|
|
46
49
|
const settled = await Promise.allSettled([
|
|
47
|
-
configHealthCheck(options?.configPath),
|
|
48
50
|
agentHealthCheck(options?.openCodeConfig ?? null),
|
|
49
51
|
nativeAgentSuppressionHealthCheck(options?.openCodeConfig ?? null),
|
|
50
52
|
assetHealthCheck(options?.assetsDir, options?.targetDir),
|
|
51
53
|
skillHealthCheck(options?.projectRoot ?? process.cwd()),
|
|
52
54
|
memoryHealthCheck(options?.targetDir),
|
|
53
55
|
commandHealthCheck(options?.targetDir),
|
|
56
|
+
configV7FieldsCheck(options?.configPath),
|
|
54
57
|
]);
|
|
55
58
|
|
|
59
|
+
const allSettled = [...configOutcome, ...settled];
|
|
60
|
+
|
|
56
61
|
const fallbackNames = [
|
|
57
62
|
"config-validity",
|
|
58
63
|
"agent-injection",
|
|
@@ -61,9 +66,10 @@ export async function runHealthChecks(options?: {
|
|
|
61
66
|
"skill-loading",
|
|
62
67
|
"memory-db",
|
|
63
68
|
"command-accessibility",
|
|
69
|
+
"config-v7-fields",
|
|
64
70
|
];
|
|
65
71
|
const results: readonly HealthResult[] = Object.freeze(
|
|
66
|
-
|
|
72
|
+
allSettled.map((outcome, i) => settledToResult(outcome, fallbackNames[i])),
|
|
67
73
|
);
|
|
68
74
|
|
|
69
75
|
const allPassed = results.every((r) => r.status === "pass");
|
package/src/tools/configure.ts
CHANGED
|
@@ -314,7 +314,7 @@ async function handleCommit(configPath?: string): Promise<string> {
|
|
|
314
314
|
}
|
|
315
315
|
const newConfig = {
|
|
316
316
|
...currentConfig,
|
|
317
|
-
version:
|
|
317
|
+
version: 7 as const,
|
|
318
318
|
configured: true,
|
|
319
319
|
groups: groupsRecord,
|
|
320
320
|
overrides: currentConfig.overrides ?? {},
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const TaskStatusSchema = z.enum(["pending", "running", "completed", "failed", "cancelled"]);
|
|
4
|
+
export type TaskStatus = z.infer<typeof TaskStatusSchema>;
|
|
5
|
+
|
|
6
|
+
export const TaskResultSchema = z.object({
|
|
7
|
+
taskId: z.string().min(1),
|
|
8
|
+
status: TaskStatusSchema,
|
|
9
|
+
output: z.string().optional(),
|
|
10
|
+
error: z.string().optional(),
|
|
11
|
+
startedAt: z.number().optional(),
|
|
12
|
+
completedAt: z.number().optional(),
|
|
13
|
+
durationMs: z.number().optional(),
|
|
14
|
+
});
|
|
15
|
+
export type TaskResult = z.infer<typeof TaskResultSchema>;
|
|
16
|
+
|
|
17
|
+
export const BackgroundTaskSchema = z.object({
|
|
18
|
+
id: z.string().min(1),
|
|
19
|
+
name: z.string().min(1),
|
|
20
|
+
status: TaskStatusSchema,
|
|
21
|
+
agentId: z.string().optional(),
|
|
22
|
+
priority: z.number().int().min(0).max(100).default(50),
|
|
23
|
+
createdAt: z.number(),
|
|
24
|
+
result: TaskResultSchema.optional(),
|
|
25
|
+
metadata: z.record(z.string(), z.unknown()).default({}),
|
|
26
|
+
});
|
|
27
|
+
export type BackgroundTask = z.infer<typeof BackgroundTaskSchema>;
|
|
28
|
+
|
|
29
|
+
export const AgentSlotSchema = z.object({
|
|
30
|
+
slotId: z.string().min(1),
|
|
31
|
+
agentId: z.string().min(1),
|
|
32
|
+
capacity: z.number().int().min(1).max(100).default(1),
|
|
33
|
+
activeTaskCount: z.number().int().min(0).default(0),
|
|
34
|
+
reserved: z.boolean().default(false),
|
|
35
|
+
});
|
|
36
|
+
export type AgentSlot = z.infer<typeof AgentSlotSchema>;
|
|
37
|
+
|
|
38
|
+
export const ConcurrencyLimitsSchema = z.object({
|
|
39
|
+
global: z.number().int().min(1).max(50).default(5),
|
|
40
|
+
perAgent: z.number().int().min(1).max(10).default(2),
|
|
41
|
+
perCategory: z.record(z.string(), z.number().int().min(1).max(20)).default({}),
|
|
42
|
+
});
|
|
43
|
+
export type ConcurrencyLimits = z.infer<typeof ConcurrencyLimitsSchema>;
|
|
44
|
+
|
|
45
|
+
export const backgroundConfigSchema = z.object({
|
|
46
|
+
enabled: z.boolean().default(false),
|
|
47
|
+
maxConcurrent: z.number().int().min(1).max(50).default(5),
|
|
48
|
+
persistence: z.boolean().default(true),
|
|
49
|
+
});
|
|
50
|
+
export type BackgroundConfig = z.infer<typeof backgroundConfigSchema>;
|
|
51
|
+
export const backgroundDefaults = backgroundConfigSchema.parse({});
|
package/src/types/mcp.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const McpSkillSchema = z.object({
|
|
4
|
+
name: z.string().min(1),
|
|
5
|
+
description: z.string().optional(),
|
|
6
|
+
enabled: z.boolean().default(true),
|
|
7
|
+
version: z.string().optional(),
|
|
8
|
+
config: z.record(z.string(), z.unknown()).default({}),
|
|
9
|
+
});
|
|
10
|
+
export type McpSkill = z.infer<typeof McpSkillSchema>;
|
|
11
|
+
|
|
12
|
+
export const McpServerSchema = z.object({
|
|
13
|
+
id: z.string().min(1),
|
|
14
|
+
url: z.string().url().optional(),
|
|
15
|
+
transport: z.enum(["stdio", "http", "sse"]).default("stdio"),
|
|
16
|
+
enabled: z.boolean().default(true),
|
|
17
|
+
skills: z.array(z.string()).default([]),
|
|
18
|
+
metadata: z.record(z.string(), z.unknown()).default({}),
|
|
19
|
+
});
|
|
20
|
+
export type McpServer = z.infer<typeof McpServerSchema>;
|
|
21
|
+
|
|
22
|
+
export const mcpConfigSchema = z.object({
|
|
23
|
+
enabled: z.boolean().default(false),
|
|
24
|
+
skills: z.record(z.string(), z.unknown()).default({}),
|
|
25
|
+
});
|
|
26
|
+
export type McpConfig = z.infer<typeof mcpConfigSchema>;
|
|
27
|
+
export const mcpDefaults = mcpConfigSchema.parse({});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const ErrorCategorySchema = z.enum([
|
|
4
|
+
"rate_limit",
|
|
5
|
+
"auth_failure",
|
|
6
|
+
"quota_exceeded",
|
|
7
|
+
"service_unavailable",
|
|
8
|
+
"timeout",
|
|
9
|
+
"network",
|
|
10
|
+
"validation",
|
|
11
|
+
"unknown",
|
|
12
|
+
]);
|
|
13
|
+
export type ErrorCategory = z.infer<typeof ErrorCategorySchema>;
|
|
14
|
+
|
|
15
|
+
export const RecoveryStrategySchema = z.enum([
|
|
16
|
+
"retry",
|
|
17
|
+
"fallback_model",
|
|
18
|
+
"skip",
|
|
19
|
+
"abort",
|
|
20
|
+
"user_prompt",
|
|
21
|
+
]);
|
|
22
|
+
export type RecoveryStrategy = z.infer<typeof RecoveryStrategySchema>;
|
|
23
|
+
|
|
24
|
+
export const RecoveryActionSchema = z.object({
|
|
25
|
+
strategy: RecoveryStrategySchema,
|
|
26
|
+
errorCategory: ErrorCategorySchema,
|
|
27
|
+
maxAttempts: z.number().int().min(1).max(10).default(3),
|
|
28
|
+
backoffMs: z.number().int().min(0).default(1000),
|
|
29
|
+
fallbackAgentId: z.string().optional(),
|
|
30
|
+
metadata: z.record(z.string(), z.unknown()).default({}),
|
|
31
|
+
});
|
|
32
|
+
export type RecoveryAction = z.infer<typeof RecoveryActionSchema>;
|
|
33
|
+
|
|
34
|
+
export const recoveryConfigSchema = z.object({
|
|
35
|
+
enabled: z.boolean().default(true),
|
|
36
|
+
maxRetries: z.number().int().min(0).max(10).default(3),
|
|
37
|
+
});
|
|
38
|
+
export type RecoveryConfig = z.infer<typeof recoveryConfigSchema>;
|
|
39
|
+
export const recoveryDefaults = recoveryConfigSchema.parse({});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const CategorySchema = z.enum([
|
|
4
|
+
"quick",
|
|
5
|
+
"visual-engineering",
|
|
6
|
+
"ultrabrain",
|
|
7
|
+
"artistry",
|
|
8
|
+
"writing",
|
|
9
|
+
"unspecified-high",
|
|
10
|
+
"unspecified-low",
|
|
11
|
+
]);
|
|
12
|
+
export type Category = z.infer<typeof CategorySchema>;
|
|
13
|
+
|
|
14
|
+
export const CategoryConfigSchema = z.object({
|
|
15
|
+
enabled: z.boolean().default(true),
|
|
16
|
+
agentId: z.string().optional(),
|
|
17
|
+
modelGroup: z.string().optional(),
|
|
18
|
+
maxTokenBudget: z.number().int().min(1000).optional(),
|
|
19
|
+
timeoutSeconds: z.number().int().min(1).max(3600).optional(),
|
|
20
|
+
skills: z.array(z.string()).default([]),
|
|
21
|
+
metadata: z.record(z.string(), z.unknown()).default({}),
|
|
22
|
+
});
|
|
23
|
+
export type CategoryConfig = z.infer<typeof CategoryConfigSchema>;
|
|
24
|
+
|
|
25
|
+
export const RoutingDecisionSchema = z.object({
|
|
26
|
+
category: CategorySchema,
|
|
27
|
+
confidence: z.number().min(0).max(1),
|
|
28
|
+
agentId: z.string().optional(),
|
|
29
|
+
reasoning: z.string().optional(),
|
|
30
|
+
appliedConfig: CategoryConfigSchema.optional(),
|
|
31
|
+
});
|
|
32
|
+
export type RoutingDecision = z.infer<typeof RoutingDecisionSchema>;
|
|
33
|
+
|
|
34
|
+
export const routingConfigSchema = z.object({
|
|
35
|
+
enabled: z.boolean().default(false),
|
|
36
|
+
categories: z.record(z.string(), CategoryConfigSchema).default({}),
|
|
37
|
+
});
|
|
38
|
+
export type RoutingConfig = z.infer<typeof routingConfigSchema>;
|
|
39
|
+
export const routingDefaults = routingConfigSchema.parse({});
|