@iaforged/context-code 1.0.77 → 1.0.79

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.
Files changed (121) hide show
  1. package/README.md +68 -68
  2. package/cli.js +8515 -8515
  3. package/context-bootstrap.js +27 -27
  4. package/dist/src/bootstrap/state.js +3 -0
  5. package/dist/src/bridge/bridgeMain.js +40 -40
  6. package/dist/src/cli/print.js +12 -12
  7. package/dist/src/commands/agent/agent.js +8 -0
  8. package/dist/src/commands/commit-push-pr.js +55 -55
  9. package/dist/src/commands/createMovedToPluginCommand.js +9 -9
  10. package/dist/src/commands/init-verifiers.js +238 -238
  11. package/dist/src/commands/init.js +216 -216
  12. package/dist/src/commands/install.js +2 -2
  13. package/dist/src/commands/login/login.js +24 -10
  14. package/dist/src/commands/orchestrate/index.js +1 -1
  15. package/dist/src/commands/orchestrate/orchestrate.js +110 -24
  16. package/dist/src/commands/profile/profile.js +15 -1
  17. package/dist/src/commands/provider/index.js +1 -1
  18. package/dist/src/commands/provider/provider.js +34 -1
  19. package/dist/src/commands/review.js +22 -22
  20. package/dist/src/commands/run/index.js +2 -2
  21. package/dist/src/commands/run/run.js +63 -61
  22. package/dist/src/commands/team/index.js +1 -1
  23. package/dist/src/commands/team/team.js +84 -76
  24. package/dist/src/commands/team-auto/teamAuto.js +89 -29
  25. package/dist/src/commands/terminalSetup/terminalSetup.js +24 -24
  26. package/dist/src/commands/usage/index.js +7 -0
  27. package/dist/src/commands/usage/usage.js +5 -0
  28. package/dist/src/commands/workspace/workspace.js +39 -31
  29. package/dist/src/commands.js +0 -2
  30. package/dist/src/components/ConsoleOAuthFlow.js +92 -14
  31. package/dist/src/components/ModelPicker.js +2 -0
  32. package/dist/src/components/agents/generateAgent.js +92 -92
  33. package/dist/src/components/grove/Grove.js +10 -10
  34. package/dist/src/components/permissions/AskUserQuestionPermissionRequest/AskUserQuestionPermissionRequest.js +8 -8
  35. package/dist/src/constants/geminiOAuth.js +13 -0
  36. package/dist/src/constants/github-app.js +134 -134
  37. package/dist/src/constants/prompts.js +123 -123
  38. package/dist/src/coordinator/coordinatorMode.js +252 -252
  39. package/dist/src/hooks/useTypeahead.js +7 -7
  40. package/dist/src/ink/reconciler.js +7 -7
  41. package/dist/src/main.js +5 -5
  42. package/dist/src/memdir/findRelevantMemories.js +6 -6
  43. package/dist/src/services/MagicDocs/prompts.js +56 -56
  44. package/dist/src/services/PromptSuggestion/promptSuggestion.js +29 -29
  45. package/dist/src/services/SessionMemory/prompts.js +66 -66
  46. package/dist/src/services/api/openai.js +584 -21
  47. package/dist/src/services/limits/adapters/ollama.js +3 -3
  48. package/dist/src/services/oauth/geminiCli.js +107 -0
  49. package/dist/src/services/orchestration/execution/AgentTaskExecutor.js +5 -3
  50. package/dist/src/services/orchestration/execution/OrchestrationExecutionRuntime.js +18 -18
  51. package/dist/src/services/orchestration/global/reporting.js +2 -2
  52. package/dist/src/services/toolUseSummary/toolUseSummaryGenerator.js +9 -9
  53. package/dist/src/skills/bundled/batch.js +78 -78
  54. package/dist/src/skills/bundled/claudeApi.js +34 -34
  55. package/dist/src/skills/bundled/claudeInChrome.js +4 -4
  56. package/dist/src/skills/bundled/debug.js +36 -36
  57. package/dist/src/skills/bundled/scheduleRemoteAgents.js +151 -151
  58. package/dist/src/skills/bundled/skillify.js +132 -132
  59. package/dist/src/skills/bundled/stuck.js +53 -53
  60. package/dist/src/skills/bundled/updateConfig.js +418 -418
  61. package/dist/src/tasks/RemoteAgentTask/RemoteAgentTask.js +26 -26
  62. package/dist/src/tools/AgentTool/AgentTool.js +7 -7
  63. package/dist/src/tools/AgentTool/built-in/claudeCodeGuideAgent.js +67 -67
  64. package/dist/src/tools/AgentTool/built-in/exploreAgent.js +32 -32
  65. package/dist/src/tools/AgentTool/built-in/generalPurposeAgent.js +13 -13
  66. package/dist/src/tools/AgentTool/built-in/planAgent.js +49 -49
  67. package/dist/src/tools/AgentTool/built-in/statuslineSetup.js +129 -129
  68. package/dist/src/tools/AgentTool/built-in/verificationAgent.js +119 -119
  69. package/dist/src/tools/AgentTool/prompt.js +131 -131
  70. package/dist/src/tools/AgentTool/runAgent.js +9 -9
  71. package/dist/src/tools/BashTool/BashTool.js +10 -10
  72. package/dist/src/tools/BashTool/prompt.js +94 -94
  73. package/dist/src/tools/ConfigTool/prompt.js +29 -29
  74. package/dist/src/tools/EnterWorktreeTool/prompt.js +27 -27
  75. package/dist/src/tools/FileReadTool/prompt.js +12 -12
  76. package/dist/src/tools/PowerShellTool/prompt.js +82 -82
  77. package/dist/src/tools/RemoteTriggerTool/prompt.js +9 -9
  78. package/dist/src/tools/ScheduleCronTool/prompt.js +37 -37
  79. package/dist/src/tools/TeamCreateTool/prompt.js +110 -110
  80. package/dist/src/tools/TeamDeleteTool/prompt.js +13 -13
  81. package/dist/src/utils/advisor.js +15 -15
  82. package/dist/src/utils/api.js +2 -2
  83. package/dist/src/utils/auth.js +207 -2
  84. package/dist/src/utils/autoUpdater.js +18 -18
  85. package/dist/src/utils/bash/ShellSnapshot.js +86 -86
  86. package/dist/src/utils/bash/commands.js +61 -61
  87. package/dist/src/utils/claudeInChrome/prompt.js +53 -53
  88. package/dist/src/utils/claudeInChrome/setup.js +8 -8
  89. package/dist/src/utils/databaseMcp/server/queries.js +632 -632
  90. package/dist/src/utils/deepLink/registerProtocol.js +35 -35
  91. package/dist/src/utils/deepLink/terminalLauncher.js +12 -12
  92. package/dist/src/utils/hooks/execAgentHook.js +7 -7
  93. package/dist/src/utils/hooks/execPromptHook.js +4 -4
  94. package/dist/src/utils/hooks/skillImprovement.js +36 -36
  95. package/dist/src/utils/logoV2Utils.js +1 -1
  96. package/dist/src/utils/mcp/dateTimeParser.js +9 -9
  97. package/dist/src/utils/messages.js +191 -191
  98. package/dist/src/utils/model/model.js +18 -0
  99. package/dist/src/utils/model/modelOptions.js +51 -1
  100. package/dist/src/utils/model/modelStrings.js +5 -1
  101. package/dist/src/utils/model/modelSupportOverrides.js +3 -0
  102. package/dist/src/utils/model/providerBaseUrls.js +6 -1
  103. package/dist/src/utils/model/providerCatalog.js +64 -28
  104. package/dist/src/utils/model/providerModels.js +88 -17
  105. package/dist/src/utils/model/providerProfiles.js +8 -0
  106. package/dist/src/utils/model/providerProfilesDb.js +578 -393
  107. package/dist/src/utils/model/providerSwitch.js +12 -0
  108. package/dist/src/utils/model/providerWorkspaces.js +2 -0
  109. package/dist/src/utils/model/providers.js +65 -2
  110. package/dist/src/utils/orchestration/store/providerWorkspaceStore.js +3 -1
  111. package/dist/src/utils/orchestration/store/runStore.js +47 -47
  112. package/dist/src/utils/orchestration/store/teamStore.js +61 -61
  113. package/dist/src/utils/powershell/parser.js +253 -253
  114. package/dist/src/utils/sessionTitle.js +12 -12
  115. package/dist/src/utils/sideQuestion.js +17 -17
  116. package/dist/src/utils/status.js +1 -1
  117. package/dist/src/utils/swarm/backends/registry.js +9 -9
  118. package/dist/src/utils/telemetry/instrumentation.js +9 -9
  119. package/dist/src/utils/teleport.js +15 -15
  120. package/dist/src/utils/undercover.js +28 -28
  121. package/package.json +1 -1
@@ -9,7 +9,7 @@ let database = null;
9
9
  let initialized = false;
10
10
  let sqliteUnavailable = false;
11
11
  const DB_FILENAME = 'provider-state.sqlite3';
12
- const SCHEMA_VERSION = 7;
12
+ const SCHEMA_VERSION = 8;
13
13
  const ACTIVE_PROVIDER_STATE_KEY = 'active_provider';
14
14
  const ACTIVE_PROFILE_STATE_KEY = 'active_profile_id';
15
15
  const PROFILED_PROVIDERS = [
@@ -18,6 +18,8 @@ const PROFILED_PROVIDERS = [
18
18
  'openrouter',
19
19
  'ollama',
20
20
  'ollama-cloud',
21
+ 'gemini-api',
22
+ 'gemini-google',
21
23
  'zai',
22
24
  'minimax',
23
25
  ];
@@ -27,6 +29,8 @@ const DEFAULT_PROFILE_NAMES = {
27
29
  openrouter: 'main',
28
30
  ollama: 'local',
29
31
  'ollama-cloud': 'main',
32
+ 'gemini-api': 'main',
33
+ 'gemini-google': 'main',
30
34
  zai: 'main',
31
35
  minimax: 'main',
32
36
  };
@@ -36,6 +40,8 @@ const DEFAULT_AGENT_NAMES = {
36
40
  openrouter: 'openrouter',
37
41
  ollama: 'ollama-local',
38
42
  'ollama-cloud': 'ollama-cloud',
43
+ 'gemini-api': 'gemini-api',
44
+ 'gemini-google': 'gemini-google',
39
45
  zai: 'z-ai',
40
46
  minimax: 'minimax',
41
47
  };
@@ -43,6 +49,8 @@ const DEFAULT_PROFILE_BASE_URLS = {
43
49
  openrouter: 'https://openrouter.ai/api/v1',
44
50
  ollama: 'http://localhost:11434/v1',
45
51
  'ollama-cloud': 'http://localhost:11434/v1',
52
+ 'gemini-api': 'https://generativelanguage.googleapis.com/v1beta/openai',
53
+ 'gemini-google': 'https://generativelanguage.googleapis.com/v1beta/openai',
46
54
  zai: 'https://api.z.ai/api/coding/paas/v4',
47
55
  minimax: 'https://api.minimax.io/anthropic',
48
56
  };
@@ -50,8 +58,10 @@ const DEFAULT_WORKSPACE_DISPLAY_NAMES = {
50
58
  claude: 'Claude',
51
59
  openai: 'OpenAI',
52
60
  openrouter: 'OpenRouter',
53
- ollama: 'Ollama Local',
61
+ ollama: 'Ollama',
54
62
  'ollama-cloud': 'Ollama Cloud',
63
+ 'gemini-api': 'Gemini API',
64
+ 'gemini-google': 'Gemini Google',
55
65
  zai: 'Z.AI',
56
66
  minimax: 'MiniMax',
57
67
  };
@@ -59,6 +69,8 @@ const BASE_URL_PROVIDERS = [
59
69
  'openrouter',
60
70
  'ollama',
61
71
  'ollama-cloud',
72
+ 'gemini-api',
73
+ 'gemini-google',
62
74
  'zai',
63
75
  'minimax',
64
76
  ];
@@ -81,15 +93,189 @@ function buildDefaultAgentName(provider, name) {
81
93
  }
82
94
  function seedDefaultProviderWorkspaces(db) {
83
95
  const now = new Date().toISOString();
84
- const insertWorkspace = db.prepare(`
85
- INSERT OR IGNORE INTO provider_workspaces (
86
- id, provider, display_name, domain_focus, is_enabled, created_at, updated_at
87
- ) VALUES (?, ?, ?, ?, ?, ?, ?)
96
+ const insertWorkspace = db.prepare(`
97
+ INSERT OR IGNORE INTO provider_workspaces (
98
+ id, provider, display_name, domain_focus, is_enabled, created_at, updated_at
99
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
88
100
  `);
89
101
  for (const provider of PROFILED_PROVIDERS) {
90
102
  insertWorkspace.run(randomUUID(), provider, DEFAULT_WORKSPACE_DISPLAY_NAMES[provider], null, 1, now, now);
91
103
  }
92
104
  }
105
+ function tableExists(db, tableName) {
106
+ const row = db
107
+ .prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?`)
108
+ .get(tableName);
109
+ return Boolean(row);
110
+ }
111
+ function columnExists(db, tableName, columnName) {
112
+ return db
113
+ .prepare(`PRAGMA table_info(${tableName})`)
114
+ .all()
115
+ .some(row => row.name === columnName);
116
+ }
117
+ function rebuildOrchestrationTasksWithoutLegacyDomain(db) {
118
+ if (!tableExists(db, 'orchestration_tasks') ||
119
+ !columnExists(db, 'orchestration_tasks', 'team_domain_id')) {
120
+ return;
121
+ }
122
+ db.exec(`
123
+ CREATE TABLE IF NOT EXISTS orchestration_tasks_v8 (
124
+ id TEXT PRIMARY KEY,
125
+ run_id TEXT NOT NULL,
126
+ parent_task_id TEXT NULL,
127
+ scope_type TEXT NOT NULL,
128
+ team_unit_id TEXT NULL,
129
+ assigned_agent_id TEXT NULL,
130
+ title TEXT NOT NULL,
131
+ instructions TEXT NOT NULL,
132
+ status TEXT NOT NULL,
133
+ result_summary TEXT NULL,
134
+ created_at TEXT NOT NULL,
135
+ finished_at TEXT NULL,
136
+ FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE,
137
+ FOREIGN KEY (parent_task_id) REFERENCES orchestration_tasks_v8(id) ON DELETE SET NULL,
138
+ FOREIGN KEY (team_unit_id) REFERENCES team_units(id) ON DELETE SET NULL,
139
+ FOREIGN KEY (assigned_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
140
+ );
141
+
142
+ INSERT OR REPLACE INTO orchestration_tasks_v8 (
143
+ id, run_id, parent_task_id, scope_type, team_unit_id, assigned_agent_id, title, instructions, status, result_summary, created_at, finished_at
144
+ )
145
+ SELECT id, run_id, parent_task_id, scope_type, team_unit_id, assigned_agent_id, title, instructions, status, result_summary, created_at, finished_at
146
+ FROM orchestration_tasks;
147
+
148
+ DROP TABLE orchestration_tasks;
149
+ ALTER TABLE orchestration_tasks_v8 RENAME TO orchestration_tasks;
150
+
151
+ CREATE INDEX IF NOT EXISTS idx_orchestration_tasks_run_id
152
+ ON orchestration_tasks(run_id);
153
+ CREATE INDEX IF NOT EXISTS idx_orchestration_tasks_team_unit_id
154
+ ON orchestration_tasks(team_unit_id);
155
+ CREATE INDEX IF NOT EXISTS idx_orchestration_tasks_assigned_agent_id
156
+ ON orchestration_tasks(assigned_agent_id);
157
+ `);
158
+ }
159
+ function rebuildCapabilityRankingsWithoutLegacyDomain(db) {
160
+ if (!tableExists(db, 'provider_agent_capability_rankings') ||
161
+ !columnExists(db, 'provider_agent_capability_rankings', 'team_domain_id')) {
162
+ return;
163
+ }
164
+ db.exec(`
165
+ CREATE TABLE IF NOT EXISTS provider_agent_capability_rankings_v8 (
166
+ id TEXT PRIMARY KEY,
167
+ team_unit_id TEXT NULL,
168
+ capability TEXT NOT NULL,
169
+ agent_id TEXT NOT NULL,
170
+ score REAL NOT NULL DEFAULT 0,
171
+ reason TEXT NULL,
172
+ source TEXT NULL,
173
+ created_at TEXT NOT NULL,
174
+ updated_at TEXT NOT NULL,
175
+ FOREIGN KEY (team_unit_id) REFERENCES team_units(id) ON DELETE CASCADE,
176
+ FOREIGN KEY (agent_id) REFERENCES provider_agents(id) ON DELETE CASCADE,
177
+ UNIQUE (team_unit_id, capability, agent_id)
178
+ );
179
+
180
+ INSERT OR REPLACE INTO provider_agent_capability_rankings_v8 (
181
+ id, team_unit_id, capability, agent_id, score, reason, source, created_at, updated_at
182
+ )
183
+ SELECT id, team_unit_id, capability, agent_id, score, reason, source, created_at, updated_at
184
+ FROM provider_agent_capability_rankings;
185
+
186
+ DROP TABLE provider_agent_capability_rankings;
187
+ ALTER TABLE provider_agent_capability_rankings_v8 RENAME TO provider_agent_capability_rankings;
188
+
189
+ CREATE INDEX IF NOT EXISTS idx_provider_agent_capability_rankings_team_unit
190
+ ON provider_agent_capability_rankings(team_unit_id);
191
+ CREATE INDEX IF NOT EXISTS idx_provider_agent_capability_rankings_capability
192
+ ON provider_agent_capability_rankings(capability);
193
+ CREATE INDEX IF NOT EXISTS idx_provider_agent_capability_rankings_agent
194
+ ON provider_agent_capability_rankings(agent_id);
195
+ `);
196
+ }
197
+ function migrateTeamUnitsSchema(db) {
198
+ db.exec(`PRAGMA foreign_keys = OFF;`);
199
+ try {
200
+ if (tableExists(db, 'team_domains')) {
201
+ db.exec(`
202
+ INSERT OR IGNORE INTO team_units (
203
+ id, team_id, unit_name, workspace_id, local_orchestrator_agent_id, lead_agent_id, selection_mode, required, created_at, updated_at
204
+ )
205
+ SELECT id, team_id, domain_name, workspace_id, local_orchestrator_agent_id, lead_agent_id, selection_mode, required, created_at, updated_at
206
+ FROM team_domains;
207
+ `);
208
+ }
209
+ if (tableExists(db, 'team_domain_members')) {
210
+ db.exec(`
211
+ INSERT OR IGNORE INTO team_unit_members (
212
+ id, team_unit_id, agent_id, duty, priority, created_at, updated_at
213
+ )
214
+ SELECT id, team_domain_id, agent_id, duty, priority, created_at, updated_at
215
+ FROM team_domain_members;
216
+ `);
217
+ }
218
+ if (tableExists(db, 'orchestration_tasks') &&
219
+ !columnExists(db, 'orchestration_tasks', 'team_unit_id')) {
220
+ db.exec(`ALTER TABLE orchestration_tasks ADD COLUMN team_unit_id TEXT NULL;`);
221
+ }
222
+ if (tableExists(db, 'orchestration_tasks') &&
223
+ columnExists(db, 'orchestration_tasks', 'team_domain_id') &&
224
+ columnExists(db, 'orchestration_tasks', 'team_unit_id')) {
225
+ db.exec(`
226
+ UPDATE orchestration_tasks
227
+ SET team_unit_id = team_domain_id
228
+ WHERE team_unit_id IS NULL AND team_domain_id IS NOT NULL;
229
+ `);
230
+ }
231
+ rebuildOrchestrationTasksWithoutLegacyDomain(db);
232
+ if (tableExists(db, 'orchestration_domain_reports')) {
233
+ db.exec(`
234
+ INSERT OR IGNORE INTO orchestration_team_reports (
235
+ id, run_id, team_unit_id, local_orchestrator_agent_id, status, summary, blockers, output, metrics_json, created_at, updated_at, submitted_at
236
+ )
237
+ SELECT id, run_id, team_domain_id, local_orchestrator_agent_id, status, summary, blockers, output, metrics_json, created_at, updated_at, submitted_at
238
+ FROM orchestration_domain_reports;
239
+ `);
240
+ }
241
+ if (tableExists(db, 'provider_agent_capability_rankings') &&
242
+ !columnExists(db, 'provider_agent_capability_rankings', 'team_unit_id')) {
243
+ db.exec(`ALTER TABLE provider_agent_capability_rankings ADD COLUMN team_unit_id TEXT NULL;`);
244
+ }
245
+ if (tableExists(db, 'provider_agent_capability_rankings') &&
246
+ columnExists(db, 'provider_agent_capability_rankings', 'team_domain_id') &&
247
+ columnExists(db, 'provider_agent_capability_rankings', 'team_unit_id')) {
248
+ db.exec(`
249
+ UPDATE provider_agent_capability_rankings
250
+ SET team_unit_id = team_domain_id
251
+ WHERE team_unit_id IS NULL AND team_domain_id IS NOT NULL;
252
+ `);
253
+ }
254
+ rebuildCapabilityRankingsWithoutLegacyDomain(db);
255
+ db.exec(`
256
+ DROP TABLE IF EXISTS orchestration_domain_reports;
257
+ DROP TABLE IF EXISTS team_domain_members;
258
+ DROP TABLE IF EXISTS team_domains;
259
+ `);
260
+ }
261
+ finally {
262
+ db.exec(`PRAGMA foreign_keys = ON;`);
263
+ }
264
+ if (tableExists(db, 'orchestration_tasks') &&
265
+ columnExists(db, 'orchestration_tasks', 'team_unit_id')) {
266
+ db.exec(`
267
+ CREATE INDEX IF NOT EXISTS idx_orchestration_tasks_team_unit_id
268
+ ON orchestration_tasks(team_unit_id);
269
+ `);
270
+ }
271
+ if (tableExists(db, 'provider_agent_capability_rankings') &&
272
+ columnExists(db, 'provider_agent_capability_rankings', 'team_unit_id')) {
273
+ db.exec(`
274
+ CREATE INDEX IF NOT EXISTS idx_provider_agent_capability_rankings_team_unit
275
+ ON provider_agent_capability_rankings(team_unit_id);
276
+ `);
277
+ }
278
+ }
93
279
  function getDatabasePath() {
94
280
  return join(getClaudeConfigHomeDir(), DB_FILENAME);
95
281
  }
@@ -183,34 +369,34 @@ function seedLegacyProfiles() {
183
369
  function migrateFromLegacyConfig(db) {
184
370
  const config = getGlobalConfig();
185
371
  const seeded = seedLegacyProfiles();
186
- const insertProfile = db.prepare(`
187
- INSERT OR REPLACE INTO provider_profiles (
188
- id, provider, name, agent_name, base_url, last_model, created_at, updated_at
189
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
372
+ const insertProfile = db.prepare(`
373
+ INSERT OR REPLACE INTO provider_profiles (
374
+ id, provider, name, agent_name, base_url, last_model, created_at, updated_at
375
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
190
376
  `);
191
- const upsertLastProfile = db.prepare(`
192
- INSERT INTO provider_last_profile (provider, profile_id)
193
- VALUES (?, ?)
194
- ON CONFLICT(provider) DO UPDATE SET profile_id = excluded.profile_id
377
+ const upsertLastProfile = db.prepare(`
378
+ INSERT INTO provider_last_profile (provider, profile_id)
379
+ VALUES (?, ?)
380
+ ON CONFLICT(provider) DO UPDATE SET profile_id = excluded.profile_id
195
381
  `);
196
- const upsertRuntime = db.prepare(`
197
- INSERT INTO provider_runtime_state (key, value)
198
- VALUES (?, ?)
199
- ON CONFLICT(key) DO UPDATE SET value = excluded.value
382
+ const upsertRuntime = db.prepare(`
383
+ INSERT INTO provider_runtime_state (key, value)
384
+ VALUES (?, ?)
385
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value
200
386
  `);
201
- const upsertLastModel = db.prepare(`
202
- INSERT INTO provider_last_model (provider, last_model, updated_at)
203
- VALUES (?, ?, ?)
204
- ON CONFLICT(provider) DO UPDATE SET
205
- last_model = excluded.last_model,
206
- updated_at = excluded.updated_at
387
+ const upsertLastModel = db.prepare(`
388
+ INSERT INTO provider_last_model (provider, last_model, updated_at)
389
+ VALUES (?, ?, ?)
390
+ ON CONFLICT(provider) DO UPDATE SET
391
+ last_model = excluded.last_model,
392
+ updated_at = excluded.updated_at
207
393
  `);
208
- const upsertBaseUrl = db.prepare(`
209
- INSERT INTO provider_base_url (provider, base_url, updated_at)
210
- VALUES (?, ?, ?)
211
- ON CONFLICT(provider) DO UPDATE SET
212
- base_url = excluded.base_url,
213
- updated_at = excluded.updated_at
394
+ const upsertBaseUrl = db.prepare(`
395
+ INSERT INTO provider_base_url (provider, base_url, updated_at)
396
+ VALUES (?, ?, ?)
397
+ ON CONFLICT(provider) DO UPDATE SET
398
+ base_url = excluded.base_url,
399
+ updated_at = excluded.updated_at
214
400
  `);
215
401
  for (const profile of Object.values(seeded.profiles ?? {})) {
216
402
  insertProfile.run(profile.id, profile.provider, profile.name, profile.agentName, profile.baseUrl ?? null, profile.lastModel ?? null, profile.createdAt, profile.updatedAt);
@@ -240,6 +426,8 @@ function migrateFromLegacyConfig(db) {
240
426
  null,
241
427
  ollama: config.lastModelByProvider?.ollama ?? null,
242
428
  'ollama-cloud': config.lastModelByProvider?.['ollama-cloud'] ?? null,
429
+ 'gemini-api': config.lastModelByProvider?.['gemini-api'] ?? null,
430
+ 'gemini-google': config.lastModelByProvider?.['gemini-google'] ?? null,
243
431
  zai: config.lastModelByProvider?.zai ?? null,
244
432
  minimax: config.lastModelByProvider?.minimax ?? null,
245
433
  };
@@ -277,342 +465,339 @@ function ensureInitialized() {
277
465
  if (initialized) {
278
466
  return db;
279
467
  }
280
- db.exec(`
281
- PRAGMA journal_mode = WAL;
282
- PRAGMA foreign_keys = ON;
283
- PRAGMA synchronous = NORMAL;
284
-
285
- CREATE TABLE IF NOT EXISTS provider_profiles (
286
- id TEXT PRIMARY KEY,
287
- provider TEXT NOT NULL,
288
- name TEXT NOT NULL,
289
- agent_name TEXT NOT NULL,
290
- base_url TEXT NULL,
291
- last_model TEXT NULL,
292
- created_at TEXT NOT NULL,
293
- updated_at TEXT NOT NULL
294
- );
295
-
296
- CREATE TABLE IF NOT EXISTS provider_last_profile (
297
- provider TEXT PRIMARY KEY,
298
- profile_id TEXT NOT NULL,
299
- FOREIGN KEY (profile_id) REFERENCES provider_profiles(id) ON DELETE CASCADE
300
- );
301
-
302
- CREATE TABLE IF NOT EXISTS provider_runtime_state (
303
- key TEXT PRIMARY KEY,
304
- value TEXT NULL
305
- );
306
-
307
- CREATE TABLE IF NOT EXISTS provider_last_model (
308
- provider TEXT PRIMARY KEY,
309
- last_model TEXT NULL,
310
- updated_at TEXT NOT NULL
311
- );
312
-
313
- CREATE TABLE IF NOT EXISTS provider_base_url (
314
- provider TEXT PRIMARY KEY,
315
- base_url TEXT NOT NULL,
316
- updated_at TEXT NOT NULL
317
- );
318
-
319
- CREATE TABLE IF NOT EXISTS provider_workspaces (
320
- id TEXT PRIMARY KEY,
321
- provider TEXT NOT NULL UNIQUE,
322
- display_name TEXT NOT NULL,
323
- domain_focus TEXT NULL,
324
- is_enabled INTEGER NOT NULL DEFAULT 1,
325
- created_at TEXT NOT NULL,
326
- updated_at TEXT NOT NULL
327
- );
328
-
329
- CREATE TABLE IF NOT EXISTS provider_agents (
330
- id TEXT PRIMARY KEY,
331
- workspace_id TEXT NOT NULL,
332
- profile_id TEXT NOT NULL,
333
- name TEXT NOT NULL,
334
- role_kind TEXT NULL,
335
- system_prompt TEXT NULL,
336
- model_override TEXT NULL,
337
- tool_policy TEXT NULL,
338
- autonomy_level TEXT NULL,
339
- is_orchestrator INTEGER NOT NULL DEFAULT 0,
340
- is_enabled INTEGER NOT NULL DEFAULT 1,
341
- created_at TEXT NOT NULL,
342
- updated_at TEXT NOT NULL,
343
- FOREIGN KEY (workspace_id) REFERENCES provider_workspaces(id) ON DELETE CASCADE,
344
- FOREIGN KEY (profile_id) REFERENCES provider_profiles(id) ON DELETE CASCADE,
345
- UNIQUE (workspace_id, name)
346
- );
347
-
348
- CREATE INDEX IF NOT EXISTS idx_provider_agents_workspace_id
349
- ON provider_agents(workspace_id);
350
- CREATE INDEX IF NOT EXISTS idx_provider_agents_profile_id
351
- ON provider_agents(profile_id);
352
-
353
- CREATE TABLE IF NOT EXISTS provider_agent_capabilities (
354
- id TEXT PRIMARY KEY,
355
- agent_id TEXT NOT NULL,
356
- capability TEXT NOT NULL,
357
- weight REAL NOT NULL DEFAULT 1,
358
- created_at TEXT NOT NULL,
359
- updated_at TEXT NOT NULL,
360
- FOREIGN KEY (agent_id) REFERENCES provider_agents(id) ON DELETE CASCADE,
361
- UNIQUE (agent_id, capability)
362
- );
363
-
364
- CREATE INDEX IF NOT EXISTS idx_provider_agent_capabilities_agent_id
365
- ON provider_agent_capabilities(agent_id);
366
-
367
- CREATE TABLE IF NOT EXISTS teams (
368
- id TEXT PRIMARY KEY,
369
- name TEXT NOT NULL UNIQUE,
370
- description TEXT NULL,
371
- global_orchestrator_agent_id TEXT NULL,
372
- is_enabled INTEGER NOT NULL DEFAULT 1,
373
- created_at TEXT NOT NULL,
374
- updated_at TEXT NOT NULL,
375
- FOREIGN KEY (global_orchestrator_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
376
- );
377
-
378
- CREATE TABLE IF NOT EXISTS team_domains (
379
- id TEXT PRIMARY KEY,
380
- team_id TEXT NOT NULL,
381
- domain_name TEXT NOT NULL,
382
- workspace_id TEXT NULL,
383
- local_orchestrator_agent_id TEXT NULL,
384
- lead_agent_id TEXT NULL,
385
- selection_mode TEXT NOT NULL DEFAULT 'manual',
386
- required INTEGER NOT NULL DEFAULT 0,
387
- created_at TEXT NOT NULL,
388
- updated_at TEXT NOT NULL,
389
- FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE,
390
- FOREIGN KEY (workspace_id) REFERENCES provider_workspaces(id) ON DELETE SET NULL,
391
- FOREIGN KEY (local_orchestrator_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL,
392
- FOREIGN KEY (lead_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL,
393
- UNIQUE (team_id, domain_name)
394
- );
395
-
396
- CREATE INDEX IF NOT EXISTS idx_team_domains_team_id
397
- ON team_domains(team_id);
398
- CREATE INDEX IF NOT EXISTS idx_team_domains_workspace_id
399
- ON team_domains(workspace_id);
400
- CREATE INDEX IF NOT EXISTS idx_team_domains_local_orchestrator_agent_id
401
- ON team_domains(local_orchestrator_agent_id);
402
- CREATE INDEX IF NOT EXISTS idx_team_domains_lead_agent_id
403
- ON team_domains(lead_agent_id);
404
-
405
- CREATE TABLE IF NOT EXISTS team_domain_members (
406
- id TEXT PRIMARY KEY,
407
- team_domain_id TEXT NOT NULL,
408
- agent_id TEXT NOT NULL,
409
- duty TEXT NULL,
410
- priority INTEGER NOT NULL DEFAULT 0,
411
- created_at TEXT NOT NULL,
412
- updated_at TEXT NOT NULL,
413
- FOREIGN KEY (team_domain_id) REFERENCES team_domains(id) ON DELETE CASCADE,
414
- FOREIGN KEY (agent_id) REFERENCES provider_agents(id) ON DELETE CASCADE,
415
- UNIQUE (team_domain_id, agent_id)
416
- );
417
-
418
- CREATE INDEX IF NOT EXISTS idx_team_domain_members_team_domain_id
419
- ON team_domain_members(team_domain_id);
420
- CREATE INDEX IF NOT EXISTS idx_team_domain_members_agent_id
421
- ON team_domain_members(agent_id);
422
-
423
- CREATE TABLE IF NOT EXISTS orchestration_runs (
424
- id TEXT PRIMARY KEY,
425
- team_id TEXT NOT NULL,
426
- goal TEXT NOT NULL,
427
- global_orchestrator_agent_id TEXT NULL,
428
- status TEXT NOT NULL,
429
- created_at TEXT NOT NULL,
430
- started_at TEXT NULL,
431
- finished_at TEXT NULL,
432
- FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE,
433
- FOREIGN KEY (global_orchestrator_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
434
- );
435
-
436
- CREATE INDEX IF NOT EXISTS idx_orchestration_runs_team_id
437
- ON orchestration_runs(team_id);
438
- CREATE INDEX IF NOT EXISTS idx_orchestration_runs_status
439
- ON orchestration_runs(status);
440
-
441
- CREATE TABLE IF NOT EXISTS orchestration_tasks (
442
- id TEXT PRIMARY KEY,
443
- run_id TEXT NOT NULL,
444
- parent_task_id TEXT NULL,
445
- scope_type TEXT NOT NULL,
446
- team_domain_id TEXT NULL,
447
- assigned_agent_id TEXT NULL,
448
- title TEXT NOT NULL,
449
- instructions TEXT NOT NULL,
450
- status TEXT NOT NULL,
451
- result_summary TEXT NULL,
452
- created_at TEXT NOT NULL,
453
- finished_at TEXT NULL,
454
- FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE,
455
- FOREIGN KEY (parent_task_id) REFERENCES orchestration_tasks(id) ON DELETE SET NULL,
456
- FOREIGN KEY (team_domain_id) REFERENCES team_domains(id) ON DELETE SET NULL,
457
- FOREIGN KEY (assigned_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
458
- );
459
-
460
- CREATE INDEX IF NOT EXISTS idx_orchestration_tasks_run_id
461
- ON orchestration_tasks(run_id);
462
- CREATE INDEX IF NOT EXISTS idx_orchestration_tasks_team_domain_id
463
- ON orchestration_tasks(team_domain_id);
464
- CREATE INDEX IF NOT EXISTS idx_orchestration_tasks_assigned_agent_id
465
- ON orchestration_tasks(assigned_agent_id);
466
-
467
- CREATE TABLE IF NOT EXISTS orchestration_messages (
468
- id TEXT PRIMARY KEY,
469
- run_id TEXT NOT NULL,
470
- task_id TEXT NULL,
471
- from_agent_id TEXT NULL,
472
- to_agent_id TEXT NULL,
473
- message_type TEXT NOT NULL,
474
- content TEXT NOT NULL,
475
- created_at TEXT NOT NULL,
476
- FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE,
477
- FOREIGN KEY (task_id) REFERENCES orchestration_tasks(id) ON DELETE SET NULL,
478
- FOREIGN KEY (from_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL,
479
- FOREIGN KEY (to_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
480
- );
481
-
482
- CREATE INDEX IF NOT EXISTS idx_orchestration_messages_run_id
483
- ON orchestration_messages(run_id);
484
- CREATE INDEX IF NOT EXISTS idx_orchestration_messages_task_id
485
- ON orchestration_messages(task_id);
486
-
487
- CREATE TABLE IF NOT EXISTS orchestration_task_results (
488
- id TEXT PRIMARY KEY,
489
- run_id TEXT NOT NULL,
490
- task_id TEXT NOT NULL,
491
- agent_id TEXT NULL,
492
- result_type TEXT NOT NULL,
493
- status TEXT NOT NULL,
494
- summary TEXT NULL,
495
- content TEXT NULL,
496
- metadata_json TEXT NULL,
497
- created_at TEXT NOT NULL,
498
- FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE,
499
- FOREIGN KEY (task_id) REFERENCES orchestration_tasks(id) ON DELETE CASCADE,
500
- FOREIGN KEY (agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
501
- );
502
-
503
- CREATE INDEX IF NOT EXISTS idx_orchestration_task_results_run_id
504
- ON orchestration_task_results(run_id);
505
- CREATE INDEX IF NOT EXISTS idx_orchestration_task_results_task_id
506
- ON orchestration_task_results(task_id);
507
- CREATE INDEX IF NOT EXISTS idx_orchestration_task_results_agent_id
508
- ON orchestration_task_results(agent_id);
509
-
510
- CREATE TABLE IF NOT EXISTS orchestration_domain_reports (
511
- id TEXT PRIMARY KEY,
512
- run_id TEXT NOT NULL,
513
- team_domain_id TEXT NOT NULL,
514
- local_orchestrator_agent_id TEXT NULL,
515
- status TEXT NOT NULL,
516
- summary TEXT NOT NULL,
517
- blockers TEXT NULL,
518
- output TEXT NULL,
519
- metrics_json TEXT NULL,
520
- created_at TEXT NOT NULL,
521
- updated_at TEXT NOT NULL,
522
- submitted_at TEXT NULL,
523
- FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE,
524
- FOREIGN KEY (team_domain_id) REFERENCES team_domains(id) ON DELETE CASCADE,
525
- FOREIGN KEY (local_orchestrator_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL,
526
- UNIQUE (run_id, team_domain_id)
527
- );
528
-
529
- CREATE INDEX IF NOT EXISTS idx_orchestration_domain_reports_run_id
530
- ON orchestration_domain_reports(run_id);
531
- CREATE INDEX IF NOT EXISTS idx_orchestration_domain_reports_team_domain_id
532
- ON orchestration_domain_reports(team_domain_id);
533
-
534
- CREATE TABLE IF NOT EXISTS orchestration_run_reports (
535
- id TEXT PRIMARY KEY,
536
- run_id TEXT NOT NULL UNIQUE,
537
- status TEXT NOT NULL,
538
- summary TEXT NOT NULL,
539
- output TEXT NULL,
540
- risks TEXT NULL,
541
- next_steps TEXT NULL,
542
- metrics_json TEXT NULL,
543
- created_at TEXT NOT NULL,
544
- updated_at TEXT NOT NULL,
545
- submitted_at TEXT NULL,
546
- FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE
547
- );
548
-
549
- CREATE INDEX IF NOT EXISTS idx_orchestration_run_reports_run_id
550
- ON orchestration_run_reports(run_id);
551
-
552
- CREATE TABLE IF NOT EXISTS provider_agent_capability_rankings (
553
- id TEXT PRIMARY KEY,
554
- team_domain_id TEXT NULL,
555
- capability TEXT NOT NULL,
556
- agent_id TEXT NOT NULL,
557
- score REAL NOT NULL DEFAULT 0,
558
- reason TEXT NULL,
559
- source TEXT NULL,
560
- created_at TEXT NOT NULL,
561
- updated_at TEXT NOT NULL,
562
- FOREIGN KEY (team_domain_id) REFERENCES team_domains(id) ON DELETE CASCADE,
563
- FOREIGN KEY (agent_id) REFERENCES provider_agents(id) ON DELETE CASCADE,
564
- UNIQUE (team_domain_id, capability, agent_id)
565
- );
566
-
567
- CREATE INDEX IF NOT EXISTS idx_provider_agent_capability_rankings_domain
568
- ON provider_agent_capability_rankings(team_domain_id);
569
- CREATE INDEX IF NOT EXISTS idx_provider_agent_capability_rankings_capability
570
- ON provider_agent_capability_rankings(capability);
571
- CREATE INDEX IF NOT EXISTS idx_provider_agent_capability_rankings_agent
572
- ON provider_agent_capability_rankings(agent_id);
573
-
574
- CREATE TABLE IF NOT EXISTS secure_storage (
575
- key TEXT PRIMARY KEY,
576
- value TEXT NOT NULL
577
- );
578
-
579
- CREATE TABLE IF NOT EXISTS projects (
580
- path TEXT PRIMARY KEY,
581
- name TEXT NOT NULL,
582
- created_at TEXT NOT NULL
583
- );
584
-
585
- CREATE TABLE IF NOT EXISTS permission_rules (
586
- id TEXT PRIMARY KEY,
587
- scope TEXT NOT NULL,
588
- scope_path TEXT NULL,
589
- tool_name TEXT NOT NULL,
590
- behavior TEXT NOT NULL,
591
- created_at TEXT NOT NULL,
592
- expires_at TEXT NULL,
593
- UNIQUE (scope, scope_path, tool_name)
594
- );
595
-
596
- CREATE INDEX IF NOT EXISTS idx_permission_rules_scope
597
- ON permission_rules(scope, scope_path);
598
- CREATE INDEX IF NOT EXISTS idx_permission_rules_tool_name
599
- ON permission_rules(tool_name);
600
-
601
- CREATE TABLE IF NOT EXISTS permission_mode_config (
602
- id TEXT PRIMARY KEY,
603
- scope TEXT NOT NULL,
604
- scope_path TEXT NULL,
605
- mode TEXT NOT NULL,
606
- updated_at TEXT NOT NULL,
607
- UNIQUE (scope, scope_path)
608
- );
609
-
610
- CREATE TABLE IF NOT EXISTS trusted_directories (
611
- path TEXT PRIMARY KEY,
612
- trust_level TEXT NOT NULL DEFAULT 'full',
613
- created_at TEXT NOT NULL
614
- );
468
+ db.exec(`
469
+ PRAGMA journal_mode = WAL;
470
+ PRAGMA foreign_keys = ON;
471
+ PRAGMA synchronous = NORMAL;
472
+
473
+ CREATE TABLE IF NOT EXISTS provider_profiles (
474
+ id TEXT PRIMARY KEY,
475
+ provider TEXT NOT NULL,
476
+ name TEXT NOT NULL,
477
+ agent_name TEXT NOT NULL,
478
+ base_url TEXT NULL,
479
+ last_model TEXT NULL,
480
+ created_at TEXT NOT NULL,
481
+ updated_at TEXT NOT NULL
482
+ );
483
+
484
+ CREATE TABLE IF NOT EXISTS provider_last_profile (
485
+ provider TEXT PRIMARY KEY,
486
+ profile_id TEXT NOT NULL,
487
+ FOREIGN KEY (profile_id) REFERENCES provider_profiles(id) ON DELETE CASCADE
488
+ );
489
+
490
+ CREATE TABLE IF NOT EXISTS provider_runtime_state (
491
+ key TEXT PRIMARY KEY,
492
+ value TEXT NULL
493
+ );
494
+
495
+ CREATE TABLE IF NOT EXISTS provider_last_model (
496
+ provider TEXT PRIMARY KEY,
497
+ last_model TEXT NULL,
498
+ updated_at TEXT NOT NULL
499
+ );
500
+
501
+ CREATE TABLE IF NOT EXISTS provider_base_url (
502
+ provider TEXT PRIMARY KEY,
503
+ base_url TEXT NOT NULL,
504
+ updated_at TEXT NOT NULL
505
+ );
506
+
507
+ CREATE TABLE IF NOT EXISTS provider_workspaces (
508
+ id TEXT PRIMARY KEY,
509
+ provider TEXT NOT NULL UNIQUE,
510
+ display_name TEXT NOT NULL,
511
+ domain_focus TEXT NULL,
512
+ is_enabled INTEGER NOT NULL DEFAULT 1,
513
+ created_at TEXT NOT NULL,
514
+ updated_at TEXT NOT NULL
515
+ );
516
+
517
+ CREATE TABLE IF NOT EXISTS provider_agents (
518
+ id TEXT PRIMARY KEY,
519
+ workspace_id TEXT NOT NULL,
520
+ profile_id TEXT NOT NULL,
521
+ name TEXT NOT NULL,
522
+ role_kind TEXT NULL,
523
+ system_prompt TEXT NULL,
524
+ model_override TEXT NULL,
525
+ tool_policy TEXT NULL,
526
+ autonomy_level TEXT NULL,
527
+ is_orchestrator INTEGER NOT NULL DEFAULT 0,
528
+ is_enabled INTEGER NOT NULL DEFAULT 1,
529
+ created_at TEXT NOT NULL,
530
+ updated_at TEXT NOT NULL,
531
+ FOREIGN KEY (workspace_id) REFERENCES provider_workspaces(id) ON DELETE CASCADE,
532
+ FOREIGN KEY (profile_id) REFERENCES provider_profiles(id) ON DELETE CASCADE,
533
+ UNIQUE (workspace_id, name)
534
+ );
535
+
536
+ CREATE INDEX IF NOT EXISTS idx_provider_agents_workspace_id
537
+ ON provider_agents(workspace_id);
538
+ CREATE INDEX IF NOT EXISTS idx_provider_agents_profile_id
539
+ ON provider_agents(profile_id);
540
+
541
+ CREATE TABLE IF NOT EXISTS provider_agent_capabilities (
542
+ id TEXT PRIMARY KEY,
543
+ agent_id TEXT NOT NULL,
544
+ capability TEXT NOT NULL,
545
+ weight REAL NOT NULL DEFAULT 1,
546
+ created_at TEXT NOT NULL,
547
+ updated_at TEXT NOT NULL,
548
+ FOREIGN KEY (agent_id) REFERENCES provider_agents(id) ON DELETE CASCADE,
549
+ UNIQUE (agent_id, capability)
550
+ );
551
+
552
+ CREATE INDEX IF NOT EXISTS idx_provider_agent_capabilities_agent_id
553
+ ON provider_agent_capabilities(agent_id);
554
+
555
+ CREATE TABLE IF NOT EXISTS teams (
556
+ id TEXT PRIMARY KEY,
557
+ name TEXT NOT NULL UNIQUE,
558
+ description TEXT NULL,
559
+ global_orchestrator_agent_id TEXT NULL,
560
+ is_enabled INTEGER NOT NULL DEFAULT 1,
561
+ created_at TEXT NOT NULL,
562
+ updated_at TEXT NOT NULL,
563
+ FOREIGN KEY (global_orchestrator_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
564
+ );
565
+
566
+ CREATE TABLE IF NOT EXISTS team_units (
567
+ id TEXT PRIMARY KEY,
568
+ team_id TEXT NOT NULL,
569
+ unit_name TEXT NOT NULL,
570
+ workspace_id TEXT NULL,
571
+ local_orchestrator_agent_id TEXT NULL,
572
+ lead_agent_id TEXT NULL,
573
+ selection_mode TEXT NOT NULL DEFAULT 'manual',
574
+ required INTEGER NOT NULL DEFAULT 0,
575
+ created_at TEXT NOT NULL,
576
+ updated_at TEXT NOT NULL,
577
+ FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE,
578
+ FOREIGN KEY (workspace_id) REFERENCES provider_workspaces(id) ON DELETE SET NULL,
579
+ FOREIGN KEY (local_orchestrator_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL,
580
+ FOREIGN KEY (lead_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL,
581
+ UNIQUE (team_id, unit_name)
582
+ );
583
+
584
+ CREATE INDEX IF NOT EXISTS idx_team_units_team_id
585
+ ON team_units(team_id);
586
+ CREATE INDEX IF NOT EXISTS idx_team_units_workspace_id
587
+ ON team_units(workspace_id);
588
+ CREATE INDEX IF NOT EXISTS idx_team_units_local_orchestrator_agent_id
589
+ ON team_units(local_orchestrator_agent_id);
590
+ CREATE INDEX IF NOT EXISTS idx_team_units_lead_agent_id
591
+ ON team_units(lead_agent_id);
592
+
593
+ CREATE TABLE IF NOT EXISTS team_unit_members (
594
+ id TEXT PRIMARY KEY,
595
+ team_unit_id TEXT NOT NULL,
596
+ agent_id TEXT NOT NULL,
597
+ duty TEXT NULL,
598
+ priority INTEGER NOT NULL DEFAULT 0,
599
+ created_at TEXT NOT NULL,
600
+ updated_at TEXT NOT NULL,
601
+ FOREIGN KEY (team_unit_id) REFERENCES team_units(id) ON DELETE CASCADE,
602
+ FOREIGN KEY (agent_id) REFERENCES provider_agents(id) ON DELETE CASCADE,
603
+ UNIQUE (team_unit_id, agent_id)
604
+ );
605
+
606
+ CREATE INDEX IF NOT EXISTS idx_team_unit_members_team_unit_id
607
+ ON team_unit_members(team_unit_id);
608
+ CREATE INDEX IF NOT EXISTS idx_team_unit_members_agent_id
609
+ ON team_unit_members(agent_id);
610
+
611
+ CREATE TABLE IF NOT EXISTS orchestration_runs (
612
+ id TEXT PRIMARY KEY,
613
+ team_id TEXT NOT NULL,
614
+ goal TEXT NOT NULL,
615
+ global_orchestrator_agent_id TEXT NULL,
616
+ status TEXT NOT NULL,
617
+ created_at TEXT NOT NULL,
618
+ started_at TEXT NULL,
619
+ finished_at TEXT NULL,
620
+ FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE,
621
+ FOREIGN KEY (global_orchestrator_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
622
+ );
623
+
624
+ CREATE INDEX IF NOT EXISTS idx_orchestration_runs_team_id
625
+ ON orchestration_runs(team_id);
626
+ CREATE INDEX IF NOT EXISTS idx_orchestration_runs_status
627
+ ON orchestration_runs(status);
628
+
629
+ CREATE TABLE IF NOT EXISTS orchestration_tasks (
630
+ id TEXT PRIMARY KEY,
631
+ run_id TEXT NOT NULL,
632
+ parent_task_id TEXT NULL,
633
+ scope_type TEXT NOT NULL,
634
+ team_unit_id TEXT NULL,
635
+ assigned_agent_id TEXT NULL,
636
+ title TEXT NOT NULL,
637
+ instructions TEXT NOT NULL,
638
+ status TEXT NOT NULL,
639
+ result_summary TEXT NULL,
640
+ created_at TEXT NOT NULL,
641
+ finished_at TEXT NULL,
642
+ FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE,
643
+ FOREIGN KEY (parent_task_id) REFERENCES orchestration_tasks(id) ON DELETE SET NULL,
644
+ FOREIGN KEY (team_unit_id) REFERENCES team_units(id) ON DELETE SET NULL,
645
+ FOREIGN KEY (assigned_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
646
+ );
647
+
648
+ CREATE INDEX IF NOT EXISTS idx_orchestration_tasks_run_id
649
+ ON orchestration_tasks(run_id);
650
+ CREATE INDEX IF NOT EXISTS idx_orchestration_tasks_assigned_agent_id
651
+ ON orchestration_tasks(assigned_agent_id);
652
+
653
+ CREATE TABLE IF NOT EXISTS orchestration_messages (
654
+ id TEXT PRIMARY KEY,
655
+ run_id TEXT NOT NULL,
656
+ task_id TEXT NULL,
657
+ from_agent_id TEXT NULL,
658
+ to_agent_id TEXT NULL,
659
+ message_type TEXT NOT NULL,
660
+ content TEXT NOT NULL,
661
+ created_at TEXT NOT NULL,
662
+ FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE,
663
+ FOREIGN KEY (task_id) REFERENCES orchestration_tasks(id) ON DELETE SET NULL,
664
+ FOREIGN KEY (from_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL,
665
+ FOREIGN KEY (to_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
666
+ );
667
+
668
+ CREATE INDEX IF NOT EXISTS idx_orchestration_messages_run_id
669
+ ON orchestration_messages(run_id);
670
+ CREATE INDEX IF NOT EXISTS idx_orchestration_messages_task_id
671
+ ON orchestration_messages(task_id);
672
+
673
+ CREATE TABLE IF NOT EXISTS orchestration_task_results (
674
+ id TEXT PRIMARY KEY,
675
+ run_id TEXT NOT NULL,
676
+ task_id TEXT NOT NULL,
677
+ agent_id TEXT NULL,
678
+ result_type TEXT NOT NULL,
679
+ status TEXT NOT NULL,
680
+ summary TEXT NULL,
681
+ content TEXT NULL,
682
+ metadata_json TEXT NULL,
683
+ created_at TEXT NOT NULL,
684
+ FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE,
685
+ FOREIGN KEY (task_id) REFERENCES orchestration_tasks(id) ON DELETE CASCADE,
686
+ FOREIGN KEY (agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL
687
+ );
688
+
689
+ CREATE INDEX IF NOT EXISTS idx_orchestration_task_results_run_id
690
+ ON orchestration_task_results(run_id);
691
+ CREATE INDEX IF NOT EXISTS idx_orchestration_task_results_task_id
692
+ ON orchestration_task_results(task_id);
693
+ CREATE INDEX IF NOT EXISTS idx_orchestration_task_results_agent_id
694
+ ON orchestration_task_results(agent_id);
695
+
696
+ CREATE TABLE IF NOT EXISTS orchestration_team_reports (
697
+ id TEXT PRIMARY KEY,
698
+ run_id TEXT NOT NULL,
699
+ team_unit_id TEXT NOT NULL,
700
+ local_orchestrator_agent_id TEXT NULL,
701
+ status TEXT NOT NULL,
702
+ summary TEXT NOT NULL,
703
+ blockers TEXT NULL,
704
+ output TEXT NULL,
705
+ metrics_json TEXT NULL,
706
+ created_at TEXT NOT NULL,
707
+ updated_at TEXT NOT NULL,
708
+ submitted_at TEXT NULL,
709
+ FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE,
710
+ FOREIGN KEY (team_unit_id) REFERENCES team_units(id) ON DELETE CASCADE,
711
+ FOREIGN KEY (local_orchestrator_agent_id) REFERENCES provider_agents(id) ON DELETE SET NULL,
712
+ UNIQUE (run_id, team_unit_id)
713
+ );
714
+
715
+ CREATE INDEX IF NOT EXISTS idx_orchestration_team_reports_run_id
716
+ ON orchestration_team_reports(run_id);
717
+ CREATE INDEX IF NOT EXISTS idx_orchestration_team_reports_team_unit_id
718
+ ON orchestration_team_reports(team_unit_id);
719
+
720
+ CREATE TABLE IF NOT EXISTS orchestration_run_reports (
721
+ id TEXT PRIMARY KEY,
722
+ run_id TEXT NOT NULL UNIQUE,
723
+ status TEXT NOT NULL,
724
+ summary TEXT NOT NULL,
725
+ output TEXT NULL,
726
+ risks TEXT NULL,
727
+ next_steps TEXT NULL,
728
+ metrics_json TEXT NULL,
729
+ created_at TEXT NOT NULL,
730
+ updated_at TEXT NOT NULL,
731
+ submitted_at TEXT NULL,
732
+ FOREIGN KEY (run_id) REFERENCES orchestration_runs(id) ON DELETE CASCADE
733
+ );
734
+
735
+ CREATE INDEX IF NOT EXISTS idx_orchestration_run_reports_run_id
736
+ ON orchestration_run_reports(run_id);
737
+
738
+ CREATE TABLE IF NOT EXISTS provider_agent_capability_rankings (
739
+ id TEXT PRIMARY KEY,
740
+ team_unit_id TEXT NULL,
741
+ capability TEXT NOT NULL,
742
+ agent_id TEXT NOT NULL,
743
+ score REAL NOT NULL DEFAULT 0,
744
+ reason TEXT NULL,
745
+ source TEXT NULL,
746
+ created_at TEXT NOT NULL,
747
+ updated_at TEXT NOT NULL,
748
+ FOREIGN KEY (team_unit_id) REFERENCES team_units(id) ON DELETE CASCADE,
749
+ FOREIGN KEY (agent_id) REFERENCES provider_agents(id) ON DELETE CASCADE,
750
+ UNIQUE (team_unit_id, capability, agent_id)
751
+ );
752
+
753
+ CREATE INDEX IF NOT EXISTS idx_provider_agent_capability_rankings_capability
754
+ ON provider_agent_capability_rankings(capability);
755
+ CREATE INDEX IF NOT EXISTS idx_provider_agent_capability_rankings_agent
756
+ ON provider_agent_capability_rankings(agent_id);
757
+
758
+ CREATE TABLE IF NOT EXISTS secure_storage (
759
+ key TEXT PRIMARY KEY,
760
+ value TEXT NOT NULL
761
+ );
762
+
763
+ CREATE TABLE IF NOT EXISTS projects (
764
+ path TEXT PRIMARY KEY,
765
+ name TEXT NOT NULL,
766
+ created_at TEXT NOT NULL
767
+ );
768
+
769
+ CREATE TABLE IF NOT EXISTS permission_rules (
770
+ id TEXT PRIMARY KEY,
771
+ scope TEXT NOT NULL,
772
+ scope_path TEXT NULL,
773
+ tool_name TEXT NOT NULL,
774
+ behavior TEXT NOT NULL,
775
+ created_at TEXT NOT NULL,
776
+ expires_at TEXT NULL,
777
+ UNIQUE (scope, scope_path, tool_name)
778
+ );
779
+
780
+ CREATE INDEX IF NOT EXISTS idx_permission_rules_scope
781
+ ON permission_rules(scope, scope_path);
782
+ CREATE INDEX IF NOT EXISTS idx_permission_rules_tool_name
783
+ ON permission_rules(tool_name);
784
+
785
+ CREATE TABLE IF NOT EXISTS permission_mode_config (
786
+ id TEXT PRIMARY KEY,
787
+ scope TEXT NOT NULL,
788
+ scope_path TEXT NULL,
789
+ mode TEXT NOT NULL,
790
+ updated_at TEXT NOT NULL,
791
+ UNIQUE (scope, scope_path)
792
+ );
793
+
794
+ CREATE TABLE IF NOT EXISTS trusted_directories (
795
+ path TEXT PRIMARY KEY,
796
+ trust_level TEXT NOT NULL DEFAULT 'full',
797
+ created_at TEXT NOT NULL
798
+ );
615
799
  `);
800
+ migrateTeamUnitsSchema(db);
616
801
  const userVersionRow = db
617
802
  .prepare(`PRAGMA user_version`)
618
803
  .get();
@@ -704,8 +889,8 @@ export function readProviderProfilesState() {
704
889
  return seedLegacyProfiles();
705
890
  }
706
891
  const profiles = db
707
- .prepare(`SELECT id, provider, name, agent_name, base_url, last_model, created_at, updated_at
708
- FROM provider_profiles
892
+ .prepare(`SELECT id, provider, name, agent_name, base_url, last_model, created_at, updated_at
893
+ FROM provider_profiles
709
894
  ORDER BY provider, created_at, id`)
710
895
  .all()
711
896
  .map(rowToProfile)
@@ -743,17 +928,17 @@ export function writeProviderProfilesState(state) {
743
928
  db.exec(`DELETE FROM provider_last_model`);
744
929
  db.exec(`DELETE FROM provider_base_url`);
745
930
  }
746
- const insertProfile = db.prepare(`
747
- INSERT INTO provider_profiles (
748
- id, provider, name, agent_name, base_url, last_model, created_at, updated_at
749
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
931
+ const insertProfile = db.prepare(`
932
+ INSERT INTO provider_profiles (
933
+ id, provider, name, agent_name, base_url, last_model, created_at, updated_at
934
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
750
935
  `);
751
936
  for (const profile of profiles) {
752
937
  insertProfile.run(profile.id, profile.provider, profile.name, profile.agentName, profile.baseUrl ?? null, profile.lastModel ?? null, profile.createdAt, profile.updatedAt);
753
938
  }
754
- const insertLastProfile = db.prepare(`
755
- INSERT INTO provider_last_profile (provider, profile_id)
756
- VALUES (?, ?)
939
+ const insertLastProfile = db.prepare(`
940
+ INSERT INTO provider_last_profile (provider, profile_id)
941
+ VALUES (?, ?)
757
942
  `);
758
943
  for (const [provider, profileId] of Object.entries(state.lastProfileIdByProvider ?? {})) {
759
944
  if (profileId) {
@@ -761,9 +946,9 @@ export function writeProviderProfilesState(state) {
761
946
  }
762
947
  }
763
948
  if (state.activeProfileId) {
764
- db.prepare(`
765
- INSERT INTO provider_runtime_state (key, value)
766
- VALUES ('${ACTIVE_PROFILE_STATE_KEY}', ?)
949
+ db.prepare(`
950
+ INSERT INTO provider_runtime_state (key, value)
951
+ VALUES ('${ACTIVE_PROFILE_STATE_KEY}', ?)
767
952
  `).run(state.activeProfileId);
768
953
  }
769
954
  db.exec('COMMIT');
@@ -792,10 +977,10 @@ function writeRuntimeStateValue(key, value) {
792
977
  db.prepare(`DELETE FROM provider_runtime_state WHERE key = ?`).run(key);
793
978
  return;
794
979
  }
795
- db.prepare(`
796
- INSERT INTO provider_runtime_state (key, value)
797
- VALUES (?, ?)
798
- ON CONFLICT(key) DO UPDATE SET value = excluded.value
980
+ db.prepare(`
981
+ INSERT INTO provider_runtime_state (key, value)
982
+ VALUES (?, ?)
983
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value
799
984
  `).run(key, value);
800
985
  }
801
986
  catch {
@@ -805,12 +990,12 @@ function writeRuntimeStateValue(key, value) {
805
990
  function upsertLastModelForProvider(provider, model) {
806
991
  try {
807
992
  const db = ensureInitialized();
808
- db.prepare(`
809
- INSERT INTO provider_last_model (provider, last_model, updated_at)
810
- VALUES (?, ?, ?)
811
- ON CONFLICT(provider) DO UPDATE SET
812
- last_model = excluded.last_model,
813
- updated_at = excluded.updated_at
993
+ db.prepare(`
994
+ INSERT INTO provider_last_model (provider, last_model, updated_at)
995
+ VALUES (?, ?, ?)
996
+ ON CONFLICT(provider) DO UPDATE SET
997
+ last_model = excluded.last_model,
998
+ updated_at = excluded.updated_at
814
999
  `).run(provider, model, new Date().toISOString());
815
1000
  }
816
1001
  catch {
@@ -863,12 +1048,12 @@ export function getStoredProviderBaseUrl(provider) {
863
1048
  export function setStoredProviderBaseUrl(provider, baseUrl) {
864
1049
  try {
865
1050
  const db = ensureInitialized();
866
- db.prepare(`
867
- INSERT INTO provider_base_url (provider, base_url, updated_at)
868
- VALUES (?, ?, ?)
869
- ON CONFLICT(provider) DO UPDATE SET
870
- base_url = excluded.base_url,
871
- updated_at = excluded.updated_at
1051
+ db.prepare(`
1052
+ INSERT INTO provider_base_url (provider, base_url, updated_at)
1053
+ VALUES (?, ?, ?)
1054
+ ON CONFLICT(provider) DO UPDATE SET
1055
+ base_url = excluded.base_url,
1056
+ updated_at = excluded.updated_at
872
1057
  `).run(provider, baseUrl, new Date().toISOString());
873
1058
  }
874
1059
  catch {