@kodrunhq/opencode-autopilot 1.16.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/bin/inspect.ts +2 -2
- package/package.json +1 -1
- package/src/config/index.ts +29 -0
- package/src/config/migrations.ts +196 -0
- package/src/config/v7.ts +45 -0
- package/src/config.ts +108 -24
- package/src/health/checks.ts +165 -0
- package/src/health/runner.ts +8 -2
- package/src/health/types.ts +1 -1
- package/src/index.ts +25 -2
- package/src/kernel/transaction.ts +48 -0
- package/src/kernel/types.ts +1 -2
- package/src/logging/domains.ts +39 -0
- package/src/logging/forensic-writer.ts +177 -0
- package/src/logging/index.ts +4 -0
- package/src/logging/logger.ts +44 -0
- package/src/logging/performance.ts +59 -0
- package/src/logging/rotation.ts +261 -0
- package/src/logging/types.ts +33 -0
- package/src/memory/capture-utils.ts +149 -0
- package/src/memory/capture.ts +16 -197
- package/src/memory/decay.ts +11 -2
- package/src/memory/injector.ts +4 -1
- package/src/memory/lessons.ts +85 -0
- package/src/memory/observations.ts +177 -0
- package/src/memory/preferences.ts +718 -0
- package/src/memory/projects.ts +83 -0
- package/src/memory/repository.ts +46 -1001
- package/src/memory/retrieval.ts +5 -1
- package/src/observability/context-display.ts +8 -0
- package/src/observability/event-handlers.ts +44 -6
- package/src/observability/forensic-log.ts +10 -2
- package/src/observability/forensic-schemas.ts +9 -1
- package/src/observability/log-reader.ts +20 -1
- package/src/orchestrator/error-context.ts +24 -0
- package/src/orchestrator/handlers/build-utils.ts +118 -0
- package/src/orchestrator/handlers/build.ts +13 -148
- package/src/orchestrator/handlers/retrospective.ts +0 -1
- package/src/orchestrator/lesson-memory.ts +7 -2
- package/src/orchestrator/orchestration-logger.ts +46 -31
- package/src/orchestrator/progress.ts +63 -0
- package/src/review/memory.ts +11 -3
- package/src/review/parse-findings.ts +116 -0
- package/src/review/pipeline.ts +3 -107
- package/src/review/selection.ts +38 -4
- package/src/scoring/time-provider.ts +23 -0
- package/src/tools/configure.ts +1 -1
- package/src/tools/doctor.ts +2 -2
- package/src/tools/logs.ts +32 -6
- package/src/tools/orchestrate.ts +11 -9
- package/src/tools/replay.ts +42 -0
- package/src/tools/review.ts +8 -2
- package/src/tools/summary.ts +43 -0
- 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
- package/src/utils/random.ts +33 -0
- package/src/ux/session-summary.ts +56 -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/bin/inspect.ts
CHANGED
|
@@ -249,7 +249,7 @@ export async function inspectCliCore(
|
|
|
249
249
|
);
|
|
250
250
|
}
|
|
251
251
|
case "project": {
|
|
252
|
-
const details = getProjectDetails(parsed.projectRef
|
|
252
|
+
const details = getProjectDetails(parsed.projectRef ?? "", dbInput);
|
|
253
253
|
if (details === null) {
|
|
254
254
|
return makeError(`Project not found: ${parsed.projectRef}`, parsed.json);
|
|
255
255
|
}
|
|
@@ -260,7 +260,7 @@ export async function inspectCliCore(
|
|
|
260
260
|
);
|
|
261
261
|
}
|
|
262
262
|
case "paths": {
|
|
263
|
-
const details = getProjectDetails(parsed.projectRef
|
|
263
|
+
const details = getProjectDetails(parsed.projectRef ?? "", dbInput);
|
|
264
264
|
if (details === null) {
|
|
265
265
|
return makeError(`Project not found: ${parsed.projectRef}`, parsed.json);
|
|
266
266
|
}
|
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": [
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export {
|
|
2
|
+
CONFIG_PATH,
|
|
3
|
+
confidenceConfigSchema,
|
|
4
|
+
confidenceDefaults,
|
|
5
|
+
createDefaultConfig,
|
|
6
|
+
isFirstLoad,
|
|
7
|
+
loadConfig,
|
|
8
|
+
memoryConfigSchema,
|
|
9
|
+
memoryDefaults,
|
|
10
|
+
orchestratorConfigSchema,
|
|
11
|
+
orchestratorDefaults,
|
|
12
|
+
type PluginConfig,
|
|
13
|
+
pluginConfigSchema,
|
|
14
|
+
saveConfig,
|
|
15
|
+
} from "../config";
|
|
16
|
+
// Re-export migration schemas and functions for backward compatibility
|
|
17
|
+
export {
|
|
18
|
+
migrateV1toV2,
|
|
19
|
+
migrateV2toV3,
|
|
20
|
+
migrateV3toV4,
|
|
21
|
+
migrateV4toV5,
|
|
22
|
+
migrateV5toV6,
|
|
23
|
+
pluginConfigSchemaV1,
|
|
24
|
+
pluginConfigSchemaV2,
|
|
25
|
+
pluginConfigSchemaV3,
|
|
26
|
+
pluginConfigSchemaV4,
|
|
27
|
+
pluginConfigSchemaV5,
|
|
28
|
+
} from "./migrations";
|
|
29
|
+
export { migrateV6toV7, type PluginConfigV7, v7ConfigDefaults } from "./v7";
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
confidenceConfigSchema,
|
|
4
|
+
confidenceDefaults,
|
|
5
|
+
memoryConfigSchema,
|
|
6
|
+
memoryDefaults,
|
|
7
|
+
orchestratorConfigSchema,
|
|
8
|
+
orchestratorDefaults,
|
|
9
|
+
} from "../config";
|
|
10
|
+
import {
|
|
11
|
+
fallbackConfigSchema,
|
|
12
|
+
fallbackDefaults,
|
|
13
|
+
testModeDefaults,
|
|
14
|
+
} from "../orchestrator/fallback/fallback-config";
|
|
15
|
+
import { AGENT_REGISTRY, ALL_GROUP_IDS } from "../registry/model-groups";
|
|
16
|
+
|
|
17
|
+
export const pluginConfigSchemaV1 = z.object({
|
|
18
|
+
version: z.literal(1),
|
|
19
|
+
configured: z.boolean(),
|
|
20
|
+
models: z.record(z.string(), z.string()),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export type PluginConfigV1 = z.infer<typeof pluginConfigSchemaV1>;
|
|
24
|
+
|
|
25
|
+
export const pluginConfigSchemaV2 = z.object({
|
|
26
|
+
version: z.literal(2),
|
|
27
|
+
configured: z.boolean(),
|
|
28
|
+
models: z.record(z.string(), z.string()),
|
|
29
|
+
orchestrator: orchestratorConfigSchema.default(orchestratorDefaults),
|
|
30
|
+
confidence: confidenceConfigSchema.default(confidenceDefaults),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export type PluginConfigV2 = z.infer<typeof pluginConfigSchemaV2>;
|
|
34
|
+
|
|
35
|
+
export const pluginConfigSchemaV3 = z.object({
|
|
36
|
+
version: z.literal(3),
|
|
37
|
+
configured: z.boolean(),
|
|
38
|
+
models: z.record(z.string(), z.string()),
|
|
39
|
+
orchestrator: orchestratorConfigSchema.default(orchestratorDefaults),
|
|
40
|
+
confidence: confidenceConfigSchema.default(confidenceDefaults),
|
|
41
|
+
fallback: fallbackConfigSchema.default(fallbackDefaults),
|
|
42
|
+
fallback_models: z.union([z.string(), z.array(z.string())]).optional(),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export type PluginConfigV3 = z.infer<typeof pluginConfigSchemaV3>;
|
|
46
|
+
|
|
47
|
+
const groupModelAssignmentSchema = z.object({
|
|
48
|
+
primary: z.string().min(1),
|
|
49
|
+
fallbacks: z.array(z.string().min(1)).default([]),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const agentOverrideSchema = z.object({
|
|
53
|
+
primary: z.string().min(1),
|
|
54
|
+
fallbacks: z.array(z.string().min(1)).optional(),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
export const pluginConfigSchemaV4 = z
|
|
58
|
+
.object({
|
|
59
|
+
version: z.literal(4),
|
|
60
|
+
configured: z.boolean(),
|
|
61
|
+
groups: z.record(z.string(), groupModelAssignmentSchema).default({}),
|
|
62
|
+
overrides: z.record(z.string(), agentOverrideSchema).default({}),
|
|
63
|
+
orchestrator: orchestratorConfigSchema.default(orchestratorDefaults),
|
|
64
|
+
confidence: confidenceConfigSchema.default(confidenceDefaults),
|
|
65
|
+
fallback: fallbackConfigSchema.default(fallbackDefaults),
|
|
66
|
+
})
|
|
67
|
+
.superRefine((config, ctx) => {
|
|
68
|
+
for (const groupId of Object.keys(config.groups)) {
|
|
69
|
+
if (!ALL_GROUP_IDS.includes(groupId as (typeof ALL_GROUP_IDS)[number])) {
|
|
70
|
+
ctx.addIssue({
|
|
71
|
+
code: z.ZodIssueCode.custom,
|
|
72
|
+
path: ["groups", groupId],
|
|
73
|
+
message: `Unknown group id "${groupId}". Expected one of: ${ALL_GROUP_IDS.join(", ")}`,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export type PluginConfigV4 = z.infer<typeof pluginConfigSchemaV4>;
|
|
80
|
+
|
|
81
|
+
export const pluginConfigSchemaV5 = z
|
|
82
|
+
.object({
|
|
83
|
+
version: z.literal(5),
|
|
84
|
+
configured: z.boolean(),
|
|
85
|
+
groups: z.record(z.string(), groupModelAssignmentSchema).default({}),
|
|
86
|
+
overrides: z.record(z.string(), agentOverrideSchema).default({}),
|
|
87
|
+
orchestrator: orchestratorConfigSchema.default(orchestratorDefaults),
|
|
88
|
+
confidence: confidenceConfigSchema.default(confidenceDefaults),
|
|
89
|
+
fallback: fallbackConfigSchema.default(fallbackDefaults),
|
|
90
|
+
memory: memoryConfigSchema.default(memoryDefaults),
|
|
91
|
+
})
|
|
92
|
+
.superRefine((config, ctx) => {
|
|
93
|
+
for (const groupId of Object.keys(config.groups)) {
|
|
94
|
+
if (!ALL_GROUP_IDS.includes(groupId as (typeof ALL_GROUP_IDS)[number])) {
|
|
95
|
+
ctx.addIssue({
|
|
96
|
+
code: z.ZodIssueCode.custom,
|
|
97
|
+
path: ["groups", groupId],
|
|
98
|
+
message: `Unknown group id "${groupId}". Expected one of: ${ALL_GROUP_IDS.join(", ")}`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export type PluginConfigV5 = z.infer<typeof pluginConfigSchemaV5>;
|
|
105
|
+
|
|
106
|
+
export function migrateV1toV2(v1Config: PluginConfigV1): PluginConfigV2 {
|
|
107
|
+
return {
|
|
108
|
+
version: 2 as const,
|
|
109
|
+
configured: v1Config.configured,
|
|
110
|
+
models: v1Config.models,
|
|
111
|
+
orchestrator: orchestratorDefaults,
|
|
112
|
+
confidence: confidenceDefaults,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function migrateV2toV3(v2Config: PluginConfigV2): PluginConfigV3 {
|
|
117
|
+
return {
|
|
118
|
+
version: 3 as const,
|
|
119
|
+
configured: v2Config.configured,
|
|
120
|
+
models: v2Config.models,
|
|
121
|
+
orchestrator: v2Config.orchestrator,
|
|
122
|
+
confidence: v2Config.confidence,
|
|
123
|
+
fallback: fallbackDefaults,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function migrateV3toV4(v3Config: PluginConfigV3): PluginConfigV4 {
|
|
128
|
+
const groups: Record<string, { primary: string; fallbacks: string[] }> = {};
|
|
129
|
+
const overrides: Record<string, { primary: string }> = {};
|
|
130
|
+
|
|
131
|
+
for (const [agentName, modelId] of Object.entries(v3Config.models)) {
|
|
132
|
+
const entry = AGENT_REGISTRY[agentName];
|
|
133
|
+
if (!entry) {
|
|
134
|
+
overrides[agentName] = { primary: modelId };
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const groupId = entry.group;
|
|
139
|
+
if (!groups[groupId]) {
|
|
140
|
+
groups[groupId] = { primary: modelId, fallbacks: [] };
|
|
141
|
+
} else if (groups[groupId].primary !== modelId) {
|
|
142
|
+
overrides[agentName] = { primary: modelId };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const globalFallbacks = v3Config.fallback_models
|
|
147
|
+
? typeof v3Config.fallback_models === "string"
|
|
148
|
+
? [v3Config.fallback_models]
|
|
149
|
+
: [...v3Config.fallback_models]
|
|
150
|
+
: [];
|
|
151
|
+
|
|
152
|
+
for (const group of Object.values(groups)) {
|
|
153
|
+
if (group.fallbacks.length === 0 && globalFallbacks.length > 0) {
|
|
154
|
+
group.fallbacks = [...globalFallbacks];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
version: 4 as const,
|
|
160
|
+
configured: v3Config.configured,
|
|
161
|
+
groups,
|
|
162
|
+
overrides,
|
|
163
|
+
orchestrator: v3Config.orchestrator,
|
|
164
|
+
confidence: v3Config.confidence,
|
|
165
|
+
fallback: v3Config.fallback,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function migrateV4toV5(v4Config: PluginConfigV4): PluginConfigV5 {
|
|
170
|
+
return {
|
|
171
|
+
version: 5 as const,
|
|
172
|
+
configured: v4Config.configured,
|
|
173
|
+
groups: v4Config.groups,
|
|
174
|
+
overrides: v4Config.overrides,
|
|
175
|
+
orchestrator: v4Config.orchestrator,
|
|
176
|
+
confidence: v4Config.confidence,
|
|
177
|
+
fallback: v4Config.fallback,
|
|
178
|
+
memory: memoryDefaults,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function migrateV5toV6(
|
|
183
|
+
v5Config: PluginConfigV5,
|
|
184
|
+
_fallbackDefaultsV6: typeof fallbackDefaults,
|
|
185
|
+
) {
|
|
186
|
+
return {
|
|
187
|
+
version: 6 as const,
|
|
188
|
+
configured: v5Config.configured,
|
|
189
|
+
groups: v5Config.groups,
|
|
190
|
+
overrides: v5Config.overrides,
|
|
191
|
+
orchestrator: v5Config.orchestrator,
|
|
192
|
+
confidence: v5Config.confidence,
|
|
193
|
+
fallback: { ...v5Config.fallback, testMode: testModeDefaults },
|
|
194
|
+
memory: v5Config.memory,
|
|
195
|
+
};
|
|
196
|
+
}
|
package/src/config/v7.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { PluginConfig } from "../config";
|
|
2
|
+
|
|
3
|
+
export type PluginConfigV7 = Omit<PluginConfig, "version"> & {
|
|
4
|
+
readonly version: 7;
|
|
5
|
+
readonly background?: {
|
|
6
|
+
readonly enabled: boolean;
|
|
7
|
+
readonly maxConcurrent: number;
|
|
8
|
+
readonly persistence: boolean;
|
|
9
|
+
};
|
|
10
|
+
readonly autonomy?: {
|
|
11
|
+
readonly enabled: boolean;
|
|
12
|
+
readonly verification: "strict" | "normal" | "lenient";
|
|
13
|
+
readonly maxIterations: number;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function migrateV6toV7(v6Config: PluginConfig): PluginConfigV7 {
|
|
18
|
+
return {
|
|
19
|
+
...v6Config,
|
|
20
|
+
version: 7,
|
|
21
|
+
background: {
|
|
22
|
+
enabled: true,
|
|
23
|
+
maxConcurrent: 5,
|
|
24
|
+
persistence: true,
|
|
25
|
+
},
|
|
26
|
+
autonomy: {
|
|
27
|
+
enabled: false,
|
|
28
|
+
verification: "normal",
|
|
29
|
+
maxIterations: 10,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const v7ConfigDefaults = {
|
|
35
|
+
background: {
|
|
36
|
+
enabled: true,
|
|
37
|
+
maxConcurrent: 5,
|
|
38
|
+
persistence: true,
|
|
39
|
+
},
|
|
40
|
+
autonomy: {
|
|
41
|
+
enabled: false,
|
|
42
|
+
verification: "normal",
|
|
43
|
+
maxIterations: 10,
|
|
44
|
+
},
|
|
45
|
+
} as const;
|
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
|
|
|
@@ -53,8 +57,8 @@ export const confidenceConfigSchema = z.object({
|
|
|
53
57
|
});
|
|
54
58
|
|
|
55
59
|
// Pre-compute full defaults for nested schema defaults
|
|
56
|
-
const orchestratorDefaults = orchestratorConfigSchema.parse({});
|
|
57
|
-
const confidenceDefaults = confidenceConfigSchema.parse({});
|
|
60
|
+
export const orchestratorDefaults = orchestratorConfigSchema.parse({});
|
|
61
|
+
export const confidenceDefaults = confidenceConfigSchema.parse({});
|
|
58
62
|
|
|
59
63
|
// --- V2 schema (internal, for migration) ---
|
|
60
64
|
|
|
@@ -90,7 +94,7 @@ export const memoryConfigSchema = z.object({
|
|
|
90
94
|
decayHalfLifeDays: z.number().min(7).max(365).default(90),
|
|
91
95
|
});
|
|
92
96
|
|
|
93
|
-
const memoryDefaults = memoryConfigSchema.parse({});
|
|
97
|
+
export const memoryDefaults = memoryConfigSchema.parse({});
|
|
94
98
|
|
|
95
99
|
// --- V4 sub-schemas ---
|
|
96
100
|
|
|
@@ -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
|
}
|