devchain-cli 0.7.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/drizzle/0027_legal_malice.sql +17 -0
- package/dist/drizzle/0028_populate_provider_configs.sql +19 -0
- package/dist/drizzle/0029_merge_profiles_by_family_slug.sql +116 -0
- package/dist/drizzle/0030_set_agents_provider_config_id.sql +14 -0
- package/dist/drizzle/0031_remove_legacy_profile_columns.sql +68 -0
- package/dist/drizzle/0032_agents_provider_config_not_null.sql +52 -0
- package/dist/drizzle/0033_profile_provider_configs_name.sql +38 -0
- package/dist/drizzle/0034_sessions_agent_running_unique.sql +30 -0
- package/dist/drizzle/0035_provider_config_position.sql +26 -0
- package/dist/drizzle/PHASE2_MIGRATION_GUIDE.md +109 -0
- package/dist/drizzle/meta/0027_snapshot.json +3648 -0
- package/dist/drizzle/meta/0035_snapshot.json +3670 -0
- package/dist/drizzle/meta/_journal.json +64 -1
- package/dist/drizzle/migration-guard.sql +17 -0
- package/dist/drizzle/phase2-rollback.sql +44 -0
- package/dist/node_modules/@devchain/shared/schemas/export-schema.d.ts +101 -12
- package/dist/node_modules/@devchain/shared/schemas/export-schema.d.ts.map +1 -1
- package/dist/node_modules/@devchain/shared/schemas/export-schema.js +20 -0
- package/dist/node_modules/@devchain/shared/schemas/export-schema.js.map +1 -1
- package/dist/node_modules/@devchain/shared/tsconfig.tsbuildinfo +1 -1
- package/dist/server/modules/agents/controllers/agents.controller.d.ts +15 -0
- package/dist/server/modules/agents/controllers/agents.controller.js +120 -57
- package/dist/server/modules/agents/controllers/agents.controller.js.map +1 -1
- package/dist/server/modules/core/services/preflight.service.d.ts +6 -0
- package/dist/server/modules/core/services/preflight.service.js +143 -57
- package/dist/server/modules/core/services/preflight.service.js.map +1 -1
- package/dist/server/modules/epics/services/epics.service.d.ts +10 -4
- package/dist/server/modules/epics/services/epics.service.js +8 -5
- package/dist/server/modules/epics/services/epics.service.js.map +1 -1
- package/dist/server/modules/events/catalog/epic.created.d.ts +18 -0
- package/dist/server/modules/events/catalog/epic.created.js +8 -0
- package/dist/server/modules/events/catalog/epic.created.js.map +1 -1
- package/dist/server/modules/events/catalog/epic.updated.d.ts +18 -0
- package/dist/server/modules/events/catalog/epic.updated.js +8 -0
- package/dist/server/modules/events/catalog/epic.updated.js.map +1 -1
- package/dist/server/modules/events/catalog/index.d.ts +36 -0
- package/dist/server/modules/events/subscribers/epic-assignment-notifier.subscriber.d.ts +1 -0
- package/dist/server/modules/events/subscribers/epic-assignment-notifier.subscriber.js +33 -2
- package/dist/server/modules/events/subscribers/epic-assignment-notifier.subscriber.js.map +1 -1
- package/dist/server/modules/events/subscribers/review-comment-notifier.subscriber.js +12 -5
- package/dist/server/modules/events/subscribers/review-comment-notifier.subscriber.js.map +1 -1
- package/dist/server/modules/mcp/services/mcp.service.js +16 -2
- package/dist/server/modules/mcp/services/mcp.service.js.map +1 -1
- package/dist/server/modules/mcp/services/terminal-activity.service.d.ts +1 -1
- package/dist/server/modules/mcp/services/terminal-activity.service.js +22 -2
- package/dist/server/modules/mcp/services/terminal-activity.service.js.map +1 -1
- package/dist/server/modules/profiles/controllers/profiles.controller.d.ts +11 -8
- package/dist/server/modules/profiles/controllers/profiles.controller.js +88 -14
- package/dist/server/modules/profiles/controllers/profiles.controller.js.map +1 -1
- package/dist/server/modules/profiles/controllers/provider-configs.controller.d.ts +9 -0
- package/dist/server/modules/profiles/controllers/provider-configs.controller.js +94 -0
- package/dist/server/modules/profiles/controllers/provider-configs.controller.js.map +1 -0
- package/dist/server/modules/profiles/dto.d.ts +81 -6
- package/dist/server/modules/profiles/dto.js +45 -3
- package/dist/server/modules/profiles/dto.js.map +1 -1
- package/dist/server/modules/profiles/profiles.module.js +2 -1
- package/dist/server/modules/profiles/profiles.module.js.map +1 -1
- package/dist/server/modules/projects/controllers/projects.controller.d.ts +78 -19
- package/dist/server/modules/projects/controllers/projects.controller.js +243 -17
- package/dist/server/modules/projects/controllers/projects.controller.js.map +1 -1
- package/dist/server/modules/projects/dtos/export.dto.d.ts +44 -0
- package/dist/server/modules/projects/dtos/export.dto.js +10 -0
- package/dist/server/modules/projects/dtos/export.dto.js.map +1 -1
- package/dist/server/modules/projects/services/projects.service.d.ts +48 -11
- package/dist/server/modules/projects/services/projects.service.js +359 -27
- package/dist/server/modules/projects/services/projects.service.js.map +1 -1
- package/dist/server/modules/providers/controllers/providers.controller.js +12 -7
- package/dist/server/modules/providers/controllers/providers.controller.js.map +1 -1
- package/dist/server/modules/registry/controllers/templates.controller.d.ts +2 -2
- package/dist/server/modules/registry/services/registry-orchestration.service.js +11 -0
- package/dist/server/modules/registry/services/registry-orchestration.service.js.map +1 -1
- package/dist/server/modules/registry/services/template-upgrade.service.js +6 -0
- package/dist/server/modules/registry/services/template-upgrade.service.js.map +1 -1
- package/dist/server/modules/registry/services/unified-template.service.d.ts +2 -1
- package/dist/server/modules/registry/services/unified-template.service.js +61 -0
- package/dist/server/modules/registry/services/unified-template.service.js.map +1 -1
- package/dist/server/modules/reviews/services/reviews.service.js +8 -0
- package/dist/server/modules/reviews/services/reviews.service.js.map +1 -1
- package/dist/server/modules/sessions/services/activity-tracker.service.d.ts +2 -0
- package/dist/server/modules/sessions/services/activity-tracker.service.js +20 -0
- package/dist/server/modules/sessions/services/activity-tracker.service.js.map +1 -1
- package/dist/server/modules/sessions/services/sessions-message-pool.service.js +2 -2
- package/dist/server/modules/sessions/services/sessions-message-pool.service.js.map +1 -1
- package/dist/server/modules/sessions/services/sessions.service.d.ts +3 -1
- package/dist/server/modules/sessions/services/sessions.service.js +275 -144
- package/dist/server/modules/sessions/services/sessions.service.js.map +1 -1
- package/dist/server/modules/sessions/utils/env-builder.d.ts +8 -0
- package/dist/server/modules/sessions/utils/env-builder.js +62 -0
- package/dist/server/modules/sessions/utils/env-builder.js.map +1 -0
- package/dist/server/modules/settings/dtos/settings.dto.d.ts +84 -8
- package/dist/server/modules/settings/dtos/settings.dto.js +15 -2
- package/dist/server/modules/settings/dtos/settings.dto.js.map +1 -1
- package/dist/server/modules/settings/services/settings.service.d.ts +10 -1
- package/dist/server/modules/settings/services/settings.service.js +275 -0
- package/dist/server/modules/settings/services/settings.service.js.map +1 -1
- package/dist/server/modules/storage/db/db.provider.js +2 -0
- package/dist/server/modules/storage/db/db.provider.js.map +1 -1
- package/dist/server/modules/storage/db/schema.d.ts +185 -28
- package/dist/server/modules/storage/db/schema.js +32 -6
- package/dist/server/modules/storage/db/schema.js.map +1 -1
- package/dist/server/modules/storage/interfaces/storage.interface.d.ts +17 -1
- package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
- package/dist/server/modules/storage/local/local-storage.service.d.ts +15 -1
- package/dist/server/modules/storage/local/local-storage.service.js +352 -21
- package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
- package/dist/server/modules/storage/models/domain.models.d.ts +26 -7
- package/dist/server/modules/subscribers/actions/restart-agent.action.js +17 -19
- package/dist/server/modules/subscribers/actions/restart-agent.action.js.map +1 -1
- package/dist/server/modules/subscribers/events/event-fields-catalog.js +4 -0
- package/dist/server/modules/subscribers/events/event-fields-catalog.js.map +1 -1
- package/dist/server/modules/terminal/services/pty.service.js +6 -1
- package/dist/server/modules/terminal/services/pty.service.js.map +1 -1
- package/dist/server/modules/watchers/services/watcher-runner.service.js +27 -8
- package/dist/server/modules/watchers/services/watcher-runner.service.js.map +1 -1
- package/dist/{templates/claude-opus.json → server/templates/dev-loop.json} +365 -209
- package/dist/server/tsconfig.tsbuildinfo +1 -1
- package/dist/server/ui/assets/{ReviewDetailPage-I54h-2L-.js → ReviewDetailPage-YlFGGJv7.js} +2 -2
- package/dist/server/ui/assets/ReviewsPage-Diegg4jt.js +19 -0
- package/dist/server/ui/assets/index-DuMIsIyY.css +32 -0
- package/dist/server/ui/assets/index-sEtQpiB4.js +868 -0
- package/dist/server/ui/assets/{useReviewSubscription-C0GEsiRw.js → useReviewSubscription-CMhQ2m0h.js} +22 -22
- package/dist/server/ui/index.html +2 -2
- package/dist/{server/templates/claude-opus.json → templates/dev-loop.json} +365 -209
- package/package.json +9 -4
- package/dist/node_modules/@devchain/shared/schemas/export-schema.spec.d.ts +0 -2
- package/dist/node_modules/@devchain/shared/schemas/export-schema.spec.d.ts.map +0 -1
- package/dist/node_modules/@devchain/shared/schemas/export-schema.spec.js +0 -88
- package/dist/node_modules/@devchain/shared/schemas/export-schema.spec.js.map +0 -1
- package/dist/server/templates/claude-codex-advanced.json +0 -470
- package/dist/server/templates/simple-codex.json +0 -469
- package/dist/server/ui/assets/ReviewsPage-B4ua5hiX.js +0 -19
- package/dist/server/ui/assets/index-CqcmnFBh.css +0 -32
- package/dist/server/ui/assets/index-JbUMpbg7.js +0 -858
- package/dist/templates/claude-codex-advanced.json +0 -470
- package/dist/templates/simple-codex.json +0 -469
|
@@ -62,6 +62,32 @@ let LocalStorageService = class LocalStorageService {
|
|
|
62
62
|
getFeatureFlags() {
|
|
63
63
|
return { ...feature_flags_1.DEFAULT_FEATURE_FLAGS };
|
|
64
64
|
}
|
|
65
|
+
parseProviderConfigEnv(envJson, configId, profileId) {
|
|
66
|
+
if (!envJson) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const parsed = JSON.parse(envJson);
|
|
71
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
72
|
+
throw new Error('env must be an object');
|
|
73
|
+
}
|
|
74
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
75
|
+
if (typeof value !== 'string') {
|
|
76
|
+
throw new Error(`env["${key}"] must be a string, got ${typeof value}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return parsed;
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
83
|
+
logger.warn({ configId, profileId, error: message }, 'Failed to parse provider config env JSON');
|
|
84
|
+
throw new error_types_1.ValidationError(`Invalid JSON in provider config env field: ${message}`, {
|
|
85
|
+
configId,
|
|
86
|
+
profileId,
|
|
87
|
+
rawValue: envJson.slice(0, 100) + (envJson.length > 100 ? '...' : ''),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
65
91
|
async ensureValidEpicParent(projectId, parentId, childId) {
|
|
66
92
|
if (!parentId) {
|
|
67
93
|
return;
|
|
@@ -181,10 +207,11 @@ let LocalStorageService = class LocalStorageService {
|
|
|
181
207
|
createdAt: now,
|
|
182
208
|
updatedAt: now,
|
|
183
209
|
};
|
|
184
|
-
const { projects, statuses, prompts, agentProfiles, agents, tags, promptTags } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
210
|
+
const { projects, statuses, prompts, agentProfiles, agents, tags, promptTags, profileProviderConfigs, providers, } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
185
211
|
const statusIdMap = {};
|
|
186
212
|
const promptIdMap = {};
|
|
187
213
|
const profileIdMap = {};
|
|
214
|
+
const configIdMap = {};
|
|
188
215
|
const agentIdMap = {};
|
|
189
216
|
const createdPrompts = [];
|
|
190
217
|
const sqlite = (0, sqlite_raw_1.getRawSqliteClient)(this.db);
|
|
@@ -266,9 +293,7 @@ let LocalStorageService = class LocalStorageService {
|
|
|
266
293
|
id: profileId,
|
|
267
294
|
projectId: project.id,
|
|
268
295
|
name: prof.name,
|
|
269
|
-
providerId: prof.providerId,
|
|
270
296
|
familySlug: prof.familySlug ?? null,
|
|
271
|
-
options: prof.options,
|
|
272
297
|
systemPrompt: null,
|
|
273
298
|
instructions: prof.instructions,
|
|
274
299
|
temperature: prof.temperature != null ? Math.round(prof.temperature * 100) : null,
|
|
@@ -278,6 +303,53 @@ let LocalStorageService = class LocalStorageService {
|
|
|
278
303
|
});
|
|
279
304
|
if (prof.id)
|
|
280
305
|
profileIdMap[prof.id] = profileId;
|
|
306
|
+
if (prof.providerConfigs && prof.providerConfigs.length > 0) {
|
|
307
|
+
const sortedConfigs = [...prof.providerConfigs].sort((a, b) => {
|
|
308
|
+
const posA = a.position ?? 0;
|
|
309
|
+
const posB = b.position ?? 0;
|
|
310
|
+
return posA - posB;
|
|
311
|
+
});
|
|
312
|
+
for (const config of sortedConfigs) {
|
|
313
|
+
const provider = await this.db
|
|
314
|
+
.select()
|
|
315
|
+
.from(providers)
|
|
316
|
+
.where(eq(providers.name, config.providerName))
|
|
317
|
+
.limit(1);
|
|
318
|
+
if (!provider[0]) {
|
|
319
|
+
throw new error_types_1.ValidationError(`Provider not found: ${config.providerName}`);
|
|
320
|
+
}
|
|
321
|
+
const configId = randomUUID();
|
|
322
|
+
await this.db.insert(profileProviderConfigs).values({
|
|
323
|
+
id: configId,
|
|
324
|
+
profileId: profileId,
|
|
325
|
+
providerId: provider[0].id,
|
|
326
|
+
name: config.name,
|
|
327
|
+
options: config.options ?? null,
|
|
328
|
+
env: config.env ? JSON.stringify(config.env) : null,
|
|
329
|
+
position: config.position ?? sortedConfigs.indexOf(config),
|
|
330
|
+
createdAt: now,
|
|
331
|
+
updatedAt: now,
|
|
332
|
+
});
|
|
333
|
+
if (!configIdMap[profileId]) {
|
|
334
|
+
configIdMap[profileId] = configId;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
const configId = randomUUID();
|
|
340
|
+
await this.db.insert(profileProviderConfigs).values({
|
|
341
|
+
id: configId,
|
|
342
|
+
profileId: profileId,
|
|
343
|
+
providerId: prof.providerId,
|
|
344
|
+
name: prof.name,
|
|
345
|
+
options: prof.options ?? null,
|
|
346
|
+
env: null,
|
|
347
|
+
position: 0,
|
|
348
|
+
createdAt: now,
|
|
349
|
+
updatedAt: now,
|
|
350
|
+
});
|
|
351
|
+
configIdMap[profileId] = configId;
|
|
352
|
+
}
|
|
281
353
|
}
|
|
282
354
|
for (const a of template.agents) {
|
|
283
355
|
const oldProfileId = a.profileId ?? '';
|
|
@@ -287,12 +359,19 @@ let LocalStorageService = class LocalStorageService {
|
|
|
287
359
|
profileId: oldProfileId || null,
|
|
288
360
|
});
|
|
289
361
|
}
|
|
362
|
+
const configId = configIdMap[newProfileId];
|
|
363
|
+
if (!configId) {
|
|
364
|
+
throw new error_types_1.ValidationError(`Config mapping missing for agent ${a.name}`, {
|
|
365
|
+
profileId: newProfileId,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
290
368
|
const agentId = randomUUID();
|
|
291
369
|
await this.db.insert(agents).values({
|
|
292
370
|
id: agentId,
|
|
293
371
|
projectId: project.id,
|
|
294
372
|
name: a.name,
|
|
295
373
|
profileId: newProfileId,
|
|
374
|
+
providerConfigId: configId,
|
|
296
375
|
description: a.description ?? null,
|
|
297
376
|
createdAt: now,
|
|
298
377
|
updatedAt: now,
|
|
@@ -1731,6 +1810,15 @@ let LocalStorageService = class LocalStorageService {
|
|
|
1731
1810
|
offset,
|
|
1732
1811
|
};
|
|
1733
1812
|
}
|
|
1813
|
+
async listProvidersByIds(ids) {
|
|
1814
|
+
if (ids.length === 0) {
|
|
1815
|
+
return [];
|
|
1816
|
+
}
|
|
1817
|
+
const { providers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
1818
|
+
const { inArray } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
1819
|
+
const results = await this.db.select().from(providers).where(inArray(providers.id, ids));
|
|
1820
|
+
return results;
|
|
1821
|
+
}
|
|
1734
1822
|
async updateProvider(id, data) {
|
|
1735
1823
|
const { providers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
1736
1824
|
const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
@@ -1778,9 +1866,7 @@ let LocalStorageService = class LocalStorageService {
|
|
|
1778
1866
|
id: randomUUID(),
|
|
1779
1867
|
projectId: data.projectId ?? null,
|
|
1780
1868
|
name: data.name,
|
|
1781
|
-
providerId: data.providerId,
|
|
1782
1869
|
familySlug: data.familySlug ?? null,
|
|
1783
|
-
options: data.options ?? null,
|
|
1784
1870
|
systemPrompt: data.systemPrompt ?? null,
|
|
1785
1871
|
instructions: data.instructions ?? null,
|
|
1786
1872
|
temperature: data.temperature ?? null,
|
|
@@ -1792,9 +1878,7 @@ let LocalStorageService = class LocalStorageService {
|
|
|
1792
1878
|
id: profile.id,
|
|
1793
1879
|
projectId: profile.projectId,
|
|
1794
1880
|
name: profile.name,
|
|
1795
|
-
providerId: profile.providerId,
|
|
1796
1881
|
familySlug: profile.familySlug,
|
|
1797
|
-
options: profile.options,
|
|
1798
1882
|
systemPrompt: profile.systemPrompt,
|
|
1799
1883
|
instructions: profile.instructions,
|
|
1800
1884
|
temperature: profile.temperature != null ? Math.round(profile.temperature * 100) : null,
|
|
@@ -1819,7 +1903,6 @@ let LocalStorageService = class LocalStorageService {
|
|
|
1819
1903
|
return {
|
|
1820
1904
|
...profile,
|
|
1821
1905
|
temperature: profile.temperature != null ? profile.temperature / 100 : null,
|
|
1822
|
-
options: profile.options ?? null,
|
|
1823
1906
|
};
|
|
1824
1907
|
}
|
|
1825
1908
|
async listAgentProfiles(options = {}) {
|
|
@@ -1844,7 +1927,6 @@ let LocalStorageService = class LocalStorageService {
|
|
|
1844
1927
|
items: items.map((p) => ({
|
|
1845
1928
|
...p,
|
|
1846
1929
|
temperature: p.temperature != null ? p.temperature / 100 : null,
|
|
1847
|
-
options: p.options ?? null,
|
|
1848
1930
|
})),
|
|
1849
1931
|
total: items.length,
|
|
1850
1932
|
limit,
|
|
@@ -1865,9 +1947,6 @@ let LocalStorageService = class LocalStorageService {
|
|
|
1865
1947
|
if (data.instructions !== undefined) {
|
|
1866
1948
|
updateData.instructions = data.instructions ?? null;
|
|
1867
1949
|
}
|
|
1868
|
-
if (data.options !== undefined) {
|
|
1869
|
-
updateData.options = data.options ?? null;
|
|
1870
|
-
}
|
|
1871
1950
|
if (data.familySlug !== undefined) {
|
|
1872
1951
|
updateData.familySlug = data.familySlug ?? null;
|
|
1873
1952
|
}
|
|
@@ -1953,9 +2032,9 @@ let LocalStorageService = class LocalStorageService {
|
|
|
1953
2032
|
if (!base.items.length)
|
|
1954
2033
|
return { ...base, items: [] };
|
|
1955
2034
|
const ids = base.items.map((p) => p.id);
|
|
1956
|
-
const { agentProfilePrompts, prompts } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2035
|
+
const { agentProfilePrompts, prompts, profileProviderConfigs, providers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
1957
2036
|
const { inArray, asc, eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
1958
|
-
const
|
|
2037
|
+
const promptRows = await this.db
|
|
1959
2038
|
.select({
|
|
1960
2039
|
profileId: agentProfilePrompts.profileId,
|
|
1961
2040
|
promptId: agentProfilePrompts.promptId,
|
|
@@ -1966,28 +2045,259 @@ let LocalStorageService = class LocalStorageService {
|
|
|
1966
2045
|
.innerJoin(prompts, eq(agentProfilePrompts.promptId, prompts.id))
|
|
1967
2046
|
.where(inArray(agentProfilePrompts.profileId, ids))
|
|
1968
2047
|
.orderBy(asc(agentProfilePrompts.profileId), asc(agentProfilePrompts.createdAt));
|
|
1969
|
-
const
|
|
1970
|
-
for (const r of
|
|
2048
|
+
const groupedPrompts = new Map();
|
|
2049
|
+
for (const r of promptRows) {
|
|
1971
2050
|
const pid = r.profileId;
|
|
1972
|
-
const arr =
|
|
2051
|
+
const arr = groupedPrompts.get(pid) ?? [];
|
|
1973
2052
|
arr.push({
|
|
1974
2053
|
promptId: r.promptId,
|
|
1975
2054
|
title: r.title,
|
|
1976
2055
|
createdAt: r.createdAt,
|
|
1977
2056
|
});
|
|
1978
|
-
|
|
2057
|
+
groupedPrompts.set(pid, arr);
|
|
2058
|
+
}
|
|
2059
|
+
const configRows = await this.db
|
|
2060
|
+
.select({
|
|
2061
|
+
profileId: profileProviderConfigs.profileId,
|
|
2062
|
+
providerId: profileProviderConfigs.providerId,
|
|
2063
|
+
createdAt: profileProviderConfigs.createdAt,
|
|
2064
|
+
})
|
|
2065
|
+
.from(profileProviderConfigs)
|
|
2066
|
+
.where(inArray(profileProviderConfigs.profileId, ids))
|
|
2067
|
+
.orderBy(asc(profileProviderConfigs.profileId), asc(profileProviderConfigs.createdAt));
|
|
2068
|
+
const providerIds = [...new Set(configRows.map((r) => r.providerId))];
|
|
2069
|
+
const providerMap = new Map();
|
|
2070
|
+
if (providerIds.length > 0) {
|
|
2071
|
+
const providerRows = await this.db
|
|
2072
|
+
.select({ id: providers.id, name: providers.name })
|
|
2073
|
+
.from(providers)
|
|
2074
|
+
.where(inArray(providers.id, providerIds));
|
|
2075
|
+
for (const p of providerRows) {
|
|
2076
|
+
providerMap.set(p.id, { id: p.id, name: p.name });
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
const firstProviderByProfile = new Map();
|
|
2080
|
+
for (const r of configRows) {
|
|
2081
|
+
const pid = r.profileId;
|
|
2082
|
+
if (!firstProviderByProfile.has(pid)) {
|
|
2083
|
+
const provider = providerMap.get(r.providerId);
|
|
2084
|
+
if (provider) {
|
|
2085
|
+
firstProviderByProfile.set(pid, provider);
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
1979
2088
|
}
|
|
1980
2089
|
const items = base.items.map((p) => {
|
|
1981
|
-
const arr =
|
|
2090
|
+
const arr = groupedPrompts.get(p.id) ?? [];
|
|
1982
2091
|
const promptsDetailed = arr.map((row, idx) => ({
|
|
1983
2092
|
promptId: row.promptId,
|
|
1984
2093
|
title: row.title,
|
|
1985
2094
|
order: idx + 1,
|
|
1986
2095
|
}));
|
|
1987
|
-
|
|
2096
|
+
const provider = firstProviderByProfile.get(p.id);
|
|
2097
|
+
return { ...p, prompts: promptsDetailed, ...(provider && { provider }) };
|
|
1988
2098
|
});
|
|
1989
2099
|
return { ...base, items };
|
|
1990
2100
|
}
|
|
2101
|
+
async createProfileProviderConfig(data) {
|
|
2102
|
+
const { randomUUID } = await Promise.resolve().then(() => __importStar(require('crypto')));
|
|
2103
|
+
const now = new Date().toISOString();
|
|
2104
|
+
const { profileProviderConfigs } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2105
|
+
const { eq, sql } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
2106
|
+
let position = data.position;
|
|
2107
|
+
if (position === undefined) {
|
|
2108
|
+
const maxResult = await this.db
|
|
2109
|
+
.select({ maxPos: sql `COALESCE(MAX(${profileProviderConfigs.position}), -1)` })
|
|
2110
|
+
.from(profileProviderConfigs)
|
|
2111
|
+
.where(eq(profileProviderConfigs.profileId, data.profileId));
|
|
2112
|
+
position = (maxResult[0]?.maxPos ?? -1) + 1;
|
|
2113
|
+
}
|
|
2114
|
+
const config = {
|
|
2115
|
+
id: randomUUID(),
|
|
2116
|
+
profileId: data.profileId,
|
|
2117
|
+
providerId: data.providerId,
|
|
2118
|
+
name: data.name,
|
|
2119
|
+
options: data.options ?? null,
|
|
2120
|
+
env: data.env ?? null,
|
|
2121
|
+
position,
|
|
2122
|
+
createdAt: now,
|
|
2123
|
+
updatedAt: now,
|
|
2124
|
+
};
|
|
2125
|
+
await this.db.insert(profileProviderConfigs).values({
|
|
2126
|
+
id: config.id,
|
|
2127
|
+
profileId: config.profileId,
|
|
2128
|
+
providerId: config.providerId,
|
|
2129
|
+
name: config.name,
|
|
2130
|
+
options: config.options,
|
|
2131
|
+
env: config.env ? JSON.stringify(config.env) : null,
|
|
2132
|
+
position: config.position,
|
|
2133
|
+
createdAt: config.createdAt,
|
|
2134
|
+
updatedAt: config.updatedAt,
|
|
2135
|
+
});
|
|
2136
|
+
logger.info({ configId: config.id, profileId: config.profileId, position }, 'Created profile provider config');
|
|
2137
|
+
return config;
|
|
2138
|
+
}
|
|
2139
|
+
async getProfileProviderConfig(id) {
|
|
2140
|
+
const { profileProviderConfigs } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2141
|
+
const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
2142
|
+
const result = await this.db
|
|
2143
|
+
.select()
|
|
2144
|
+
.from(profileProviderConfigs)
|
|
2145
|
+
.where(eq(profileProviderConfigs.id, id))
|
|
2146
|
+
.limit(1);
|
|
2147
|
+
if (!result[0]) {
|
|
2148
|
+
throw new error_types_1.NotFoundError('ProfileProviderConfig', id);
|
|
2149
|
+
}
|
|
2150
|
+
const row = result[0];
|
|
2151
|
+
return {
|
|
2152
|
+
id: row.id,
|
|
2153
|
+
profileId: row.profileId,
|
|
2154
|
+
providerId: row.providerId,
|
|
2155
|
+
name: row.name,
|
|
2156
|
+
options: row.options,
|
|
2157
|
+
env: this.parseProviderConfigEnv(row.env, row.id, row.profileId),
|
|
2158
|
+
position: row.position,
|
|
2159
|
+
createdAt: row.createdAt,
|
|
2160
|
+
updatedAt: row.updatedAt,
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
async listProfileProviderConfigsByProfile(profileId) {
|
|
2164
|
+
const { profileProviderConfigs } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2165
|
+
const { eq, asc } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
2166
|
+
const results = await this.db
|
|
2167
|
+
.select()
|
|
2168
|
+
.from(profileProviderConfigs)
|
|
2169
|
+
.where(eq(profileProviderConfigs.profileId, profileId))
|
|
2170
|
+
.orderBy(asc(profileProviderConfigs.position), asc(profileProviderConfigs.id));
|
|
2171
|
+
return results.map((row) => ({
|
|
2172
|
+
id: row.id,
|
|
2173
|
+
profileId: row.profileId,
|
|
2174
|
+
providerId: row.providerId,
|
|
2175
|
+
name: row.name,
|
|
2176
|
+
options: row.options,
|
|
2177
|
+
env: this.parseProviderConfigEnv(row.env, row.id, row.profileId),
|
|
2178
|
+
position: row.position,
|
|
2179
|
+
createdAt: row.createdAt,
|
|
2180
|
+
updatedAt: row.updatedAt,
|
|
2181
|
+
}));
|
|
2182
|
+
}
|
|
2183
|
+
async listProfileProviderConfigsByIds(ids) {
|
|
2184
|
+
if (ids.length === 0) {
|
|
2185
|
+
return [];
|
|
2186
|
+
}
|
|
2187
|
+
const { profileProviderConfigs } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2188
|
+
const { inArray } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
2189
|
+
const results = await this.db
|
|
2190
|
+
.select()
|
|
2191
|
+
.from(profileProviderConfigs)
|
|
2192
|
+
.where(inArray(profileProviderConfigs.id, ids));
|
|
2193
|
+
return results.map((row) => ({
|
|
2194
|
+
id: row.id,
|
|
2195
|
+
profileId: row.profileId,
|
|
2196
|
+
providerId: row.providerId,
|
|
2197
|
+
name: row.name,
|
|
2198
|
+
options: row.options,
|
|
2199
|
+
env: this.parseProviderConfigEnv(row.env, row.id, row.profileId),
|
|
2200
|
+
position: row.position,
|
|
2201
|
+
createdAt: row.createdAt,
|
|
2202
|
+
updatedAt: row.updatedAt,
|
|
2203
|
+
}));
|
|
2204
|
+
}
|
|
2205
|
+
async listAllProfileProviderConfigs() {
|
|
2206
|
+
const { profileProviderConfigs } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2207
|
+
const results = await this.db.select().from(profileProviderConfigs);
|
|
2208
|
+
return results.map((row) => ({
|
|
2209
|
+
id: row.id,
|
|
2210
|
+
profileId: row.profileId,
|
|
2211
|
+
providerId: row.providerId,
|
|
2212
|
+
name: row.name,
|
|
2213
|
+
options: row.options,
|
|
2214
|
+
env: this.parseProviderConfigEnv(row.env, row.id, row.profileId),
|
|
2215
|
+
position: row.position,
|
|
2216
|
+
createdAt: row.createdAt,
|
|
2217
|
+
updatedAt: row.updatedAt,
|
|
2218
|
+
}));
|
|
2219
|
+
}
|
|
2220
|
+
async updateProfileProviderConfig(id, data) {
|
|
2221
|
+
const { profileProviderConfigs } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2222
|
+
const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
2223
|
+
const now = new Date().toISOString();
|
|
2224
|
+
const updateData = { updatedAt: now };
|
|
2225
|
+
if (data.providerId !== undefined) {
|
|
2226
|
+
updateData.providerId = data.providerId;
|
|
2227
|
+
}
|
|
2228
|
+
if (data.name !== undefined) {
|
|
2229
|
+
updateData.name = data.name;
|
|
2230
|
+
}
|
|
2231
|
+
if (data.options !== undefined) {
|
|
2232
|
+
updateData.options = data.options;
|
|
2233
|
+
}
|
|
2234
|
+
if (data.env !== undefined) {
|
|
2235
|
+
updateData.env = data.env ? JSON.stringify(data.env) : null;
|
|
2236
|
+
}
|
|
2237
|
+
if (data.position !== undefined) {
|
|
2238
|
+
updateData.position = data.position;
|
|
2239
|
+
}
|
|
2240
|
+
await this.db
|
|
2241
|
+
.update(profileProviderConfigs)
|
|
2242
|
+
.set(updateData)
|
|
2243
|
+
.where(eq(profileProviderConfigs.id, id));
|
|
2244
|
+
logger.info({ configId: id }, 'Updated profile provider config');
|
|
2245
|
+
return this.getProfileProviderConfig(id);
|
|
2246
|
+
}
|
|
2247
|
+
async deleteProfileProviderConfig(id) {
|
|
2248
|
+
const { profileProviderConfigs } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2249
|
+
const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
2250
|
+
const { agents } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2251
|
+
const agentRefs = await this.db
|
|
2252
|
+
.select({ id: agents.id })
|
|
2253
|
+
.from(agents)
|
|
2254
|
+
.where(eq(agents.providerConfigId, id))
|
|
2255
|
+
.limit(1);
|
|
2256
|
+
if (agentRefs.length > 0) {
|
|
2257
|
+
throw new error_types_1.ValidationError('Cannot delete provider config: still referenced by agents', {
|
|
2258
|
+
configId: id,
|
|
2259
|
+
referencingAgentId: agentRefs[0].id,
|
|
2260
|
+
});
|
|
2261
|
+
}
|
|
2262
|
+
await this.db.delete(profileProviderConfigs).where(eq(profileProviderConfigs.id, id));
|
|
2263
|
+
logger.info({ configId: id }, 'Deleted profile provider config');
|
|
2264
|
+
}
|
|
2265
|
+
async reorderProfileProviderConfigs(profileId, configIds) {
|
|
2266
|
+
const { profileProviderConfigs } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2267
|
+
const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
2268
|
+
const sqlite = (0, sqlite_raw_1.getRawSqliteClient)(this.db);
|
|
2269
|
+
if (!sqlite || typeof sqlite.exec !== 'function') {
|
|
2270
|
+
throw new error_types_1.StorageError('Unable to access underlying SQLite client for transaction control');
|
|
2271
|
+
}
|
|
2272
|
+
try {
|
|
2273
|
+
sqlite.exec('BEGIN IMMEDIATE TRANSACTION');
|
|
2274
|
+
const configs = await this.db
|
|
2275
|
+
.select({ position: profileProviderConfigs.position })
|
|
2276
|
+
.from(profileProviderConfigs)
|
|
2277
|
+
.where(eq(profileProviderConfigs.profileId, profileId));
|
|
2278
|
+
const maxPosition = Math.max(0, ...configs.map((c) => c.position ?? 0));
|
|
2279
|
+
const tempBase = maxPosition + 1000;
|
|
2280
|
+
for (let i = 0; i < configIds.length; i++) {
|
|
2281
|
+
await this.db
|
|
2282
|
+
.update(profileProviderConfigs)
|
|
2283
|
+
.set({ position: tempBase + i })
|
|
2284
|
+
.where(eq(profileProviderConfigs.id, configIds[i]));
|
|
2285
|
+
}
|
|
2286
|
+
for (let i = 0; i < configIds.length; i++) {
|
|
2287
|
+
await this.db
|
|
2288
|
+
.update(profileProviderConfigs)
|
|
2289
|
+
.set({ position: i })
|
|
2290
|
+
.where(eq(profileProviderConfigs.id, configIds[i]));
|
|
2291
|
+
}
|
|
2292
|
+
sqlite.exec('COMMIT');
|
|
2293
|
+
logger.info({ profileId, configIds }, 'Reordered provider configs');
|
|
2294
|
+
}
|
|
2295
|
+
catch (error) {
|
|
2296
|
+
sqlite.exec('ROLLBACK');
|
|
2297
|
+
logger.error({ error, profileId, configIds }, 'Failed to reorder provider configs, rolled back');
|
|
2298
|
+
throw error;
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
1991
2301
|
async createAgent(data) {
|
|
1992
2302
|
const { randomUUID } = await Promise.resolve().then(() => __importStar(require('crypto')));
|
|
1993
2303
|
const now = new Date().toISOString();
|
|
@@ -1996,6 +2306,7 @@ let LocalStorageService = class LocalStorageService {
|
|
|
1996
2306
|
id: randomUUID(),
|
|
1997
2307
|
...data,
|
|
1998
2308
|
description: data.description ?? null,
|
|
2309
|
+
providerConfigId: data.providerConfigId,
|
|
1999
2310
|
createdAt: now,
|
|
2000
2311
|
updatedAt: now,
|
|
2001
2312
|
};
|
|
@@ -2007,10 +2318,19 @@ let LocalStorageService = class LocalStorageService {
|
|
|
2007
2318
|
profileId: agent.profileId,
|
|
2008
2319
|
});
|
|
2009
2320
|
}
|
|
2321
|
+
const config = await this.getProfileProviderConfig(agent.providerConfigId);
|
|
2322
|
+
if (config.profileId !== agent.profileId) {
|
|
2323
|
+
throw new error_types_1.ValidationError('Provider config does not belong to the specified profile.', {
|
|
2324
|
+
providerConfigId: agent.providerConfigId,
|
|
2325
|
+
configProfileId: config.profileId,
|
|
2326
|
+
expectedProfileId: agent.profileId,
|
|
2327
|
+
});
|
|
2328
|
+
}
|
|
2010
2329
|
await this.db.insert(agents).values({
|
|
2011
2330
|
id: agent.id,
|
|
2012
2331
|
projectId: agent.projectId,
|
|
2013
2332
|
profileId: agent.profileId,
|
|
2333
|
+
providerConfigId: agent.providerConfigId,
|
|
2014
2334
|
name: agent.name,
|
|
2015
2335
|
description: agent.description,
|
|
2016
2336
|
createdAt: agent.createdAt,
|
|
@@ -2067,10 +2387,13 @@ let LocalStorageService = class LocalStorageService {
|
|
|
2067
2387
|
const { agents } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
|
|
2068
2388
|
const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
|
|
2069
2389
|
const now = new Date().toISOString();
|
|
2070
|
-
if (data.projectId !== undefined ||
|
|
2390
|
+
if (data.projectId !== undefined ||
|
|
2391
|
+
data.profileId !== undefined ||
|
|
2392
|
+
data.providerConfigId !== undefined) {
|
|
2071
2393
|
const current = await this.getAgent(id);
|
|
2072
2394
|
const newProjectId = data.projectId ?? current.projectId;
|
|
2073
2395
|
const newProfileId = data.profileId ?? current.profileId;
|
|
2396
|
+
const newProviderConfigId = data.providerConfigId ?? current.providerConfigId;
|
|
2074
2397
|
const profile = await this.getAgentProfile(newProfileId);
|
|
2075
2398
|
if (profile.projectId !== newProjectId) {
|
|
2076
2399
|
throw new error_types_1.ValidationError('Agent.profileId must belong to the same project as the agent.', {
|
|
@@ -2079,6 +2402,14 @@ let LocalStorageService = class LocalStorageService {
|
|
|
2079
2402
|
profileId: newProfileId,
|
|
2080
2403
|
});
|
|
2081
2404
|
}
|
|
2405
|
+
const config = await this.getProfileProviderConfig(newProviderConfigId);
|
|
2406
|
+
if (config.profileId !== newProfileId) {
|
|
2407
|
+
throw new error_types_1.ValidationError('Provider config does not belong to the specified profile.', {
|
|
2408
|
+
providerConfigId: newProviderConfigId,
|
|
2409
|
+
configProfileId: config.profileId,
|
|
2410
|
+
expectedProfileId: newProfileId,
|
|
2411
|
+
});
|
|
2412
|
+
}
|
|
2082
2413
|
}
|
|
2083
2414
|
await this.db
|
|
2084
2415
|
.update(agents)
|