Repository navigation
refactor(subagents): separate provider instances from drivers #379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -177,92 +177,56 @@ | |
| "providers": { | ||
| "type": "array", | ||
| "items": { | ||
| "oneOf": [ | ||
| { | ||
| "type": "object", | ||
| "properties": { | ||
| "id": { | ||
| "type": "string", | ||
| "enum": [ | ||
| "codex", | ||
| "claude", | ||
| "cursor", | ||
| "copilot", | ||
| "grok" | ||
| ] | ||
| }, | ||
| "enabled": { | ||
| "type": "boolean" | ||
| }, | ||
| "model": { | ||
| "type": "string", | ||
| "minLength": 1 | ||
| }, | ||
| "effort": { | ||
| "type": "string", | ||
| "minLength": 1 | ||
| }, | ||
| "env": { | ||
| "type": "object", | ||
| "propertyNames": { | ||
| "type": "string", | ||
| "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" | ||
| }, | ||
| "additionalProperties": { | ||
| "type": "string" | ||
| } | ||
| }, | ||
| "command": { | ||
| "type": "string", | ||
| "minLength": 1, | ||
| "pattern": "\\S" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "id", | ||
| "enabled" | ||
| ], | ||
| "additionalProperties": false | ||
| "type": "object", | ||
| "properties": { | ||
| "id": { | ||
| "type": "string", | ||
| "minLength": 1 | ||
| }, | ||
| "driver": { | ||
| "type": "string", | ||
| "enum": [ | ||
| "codex", | ||
| "claude", | ||
| "opencode", | ||
| "pi", | ||
| "cursor", | ||
| "copilot", | ||
| "grok" | ||
| ] | ||
| }, | ||
| "enabled": { | ||
| "type": "boolean" | ||
| }, | ||
| { | ||
| "model": { | ||
| "type": "string", | ||
| "minLength": 1 | ||
| }, | ||
| "effort": { | ||
| "type": "string", | ||
| "minLength": 1 | ||
| }, | ||
| "env": { | ||
| "type": "object", | ||
| "properties": { | ||
| "id": { | ||
| "type": "string", | ||
| "enum": [ | ||
| "opencode", | ||
| "pi" | ||
| ] | ||
| }, | ||
| "enabled": { | ||
| "type": "boolean" | ||
| }, | ||
| "model": { | ||
| "type": "string", | ||
| "minLength": 1 | ||
| }, | ||
| "effort": { | ||
| "type": "string", | ||
| "minLength": 1 | ||
| }, | ||
| "env": { | ||
| "type": "object", | ||
| "propertyNames": { | ||
| "type": "string", | ||
| "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" | ||
| }, | ||
| "additionalProperties": { | ||
| "type": "string" | ||
| } | ||
| } | ||
| "propertyNames": { | ||
| "type": "string", | ||
| "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" | ||
| }, | ||
| "required": [ | ||
| "id", | ||
| "enabled" | ||
| ], | ||
| "additionalProperties": false | ||
| "additionalProperties": { | ||
| "type": "string" | ||
| } | ||
| }, | ||
| "command": { | ||
| "type": "string", | ||
| "minLength": 1, | ||
| "pattern": "\\S" | ||
| } | ||
| ] | ||
| }, | ||
| "required": [ | ||
| "id", | ||
| "enabled" | ||
| ], | ||
| "additionalProperties": false | ||
|
Comment on lines
+225
to
+229
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The published schema accepts a named provider without a ArtifactsExecutable provider schema and runtime comparison
Base schema validation before the PR change
PR schema validation after the change
|
||
| } | ||
| } | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,6 +47,11 @@ const migrations: Migration[] = [ | |
| name: "local-agent-turns", | ||
| up: migrateLocalAgentTurns, | ||
| }, | ||
| { | ||
| version: 9, | ||
| name: "local-agent-provider-instances", | ||
| up: migrateLocalAgentProviderInstances, | ||
| }, | ||
| ]; | ||
|
|
||
| export function migrateDatabase(sqlite: Database.Database): void { | ||
|
|
@@ -289,6 +294,22 @@ function migrateLocalAgentTurns(sqlite: Database.Database): void { | |
| `); | ||
| } | ||
|
|
||
| function migrateLocalAgentProviderInstances(sqlite: Database.Database): void { | ||
| const columns = sqlite.prepare("pragma table_info(local_agent_sessions)").all() as Array<{ | ||
| name: string; | ||
| }>; | ||
| const names = new Set(columns.map((column) => column.name)); | ||
| if (names.has("provider") && !names.has("provider_instance_id")) { | ||
| sqlite.exec("alter table local_agent_sessions rename column provider to provider_instance_id"); | ||
| } | ||
| addColumnIfMissing(sqlite, "local_agent_sessions", "driver", "text"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The migration backfills ArtifactsSQLite migration and fresh-schema reproduction script
Fresh schema rejects NULL drivers
Migrated schema accepts NULL drivers
|
||
| sqlite.exec(` | ||
| update local_agent_sessions | ||
| set driver = provider_instance_id | ||
| where driver is null or driver = '' | ||
| `); | ||
| } | ||
|
|
||
| function addColumnIfMissing( | ||
| sqlite: Database.Database, | ||
| table: "workspace_sessions" | "local_agent_sessions", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
The JSON schema is looser than the runtime validator.
The JSON schema accepts any
idwithoutdriver, so{"id":"codex-work","enabled":true}passes it. The runtime check insrc/local-agent-config.tsrejects that entry with "must declare a driver". The schema also allowscommandforopencodeandpi, but the runtime rejects it. Editors that use$schemawill report these configs as valid, and the daemon will then fail at load. Addif/thenconditions to the schema:idis not one of the built-in driver ids, requiredriver.driverisopencodeorpi, or ifidisopencodeorpianddriveris absent, forbidcommand.🤖 Prompt for AI Agents