devchain-cli 0.7.2 → 0.8.1
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} +379 -197
- 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} +379 -197
- package/package.json +12 -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
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
CREATE TABLE `profile_provider_configs` (
|
|
2
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
3
|
+
`profile_id` text NOT NULL,
|
|
4
|
+
`provider_id` text NOT NULL,
|
|
5
|
+
`options` text,
|
|
6
|
+
`env` text,
|
|
7
|
+
`created_at` text NOT NULL,
|
|
8
|
+
`updated_at` text NOT NULL,
|
|
9
|
+
FOREIGN KEY (`profile_id`) REFERENCES `agent_profiles`(`id`) ON UPDATE no action ON DELETE cascade,
|
|
10
|
+
FOREIGN KEY (`provider_id`) REFERENCES `providers`(`id`) ON UPDATE no action ON DELETE no action
|
|
11
|
+
);
|
|
12
|
+
--> statement-breakpoint
|
|
13
|
+
CREATE INDEX `profile_provider_configs_profile_id_idx` ON `profile_provider_configs` (`profile_id`);
|
|
14
|
+
--> statement-breakpoint
|
|
15
|
+
CREATE INDEX `profile_provider_configs_provider_id_idx` ON `profile_provider_configs` (`provider_id`);
|
|
16
|
+
--> statement-breakpoint
|
|
17
|
+
ALTER TABLE `agents` ADD `provider_config_id` text REFERENCES profile_provider_configs(id);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- Phase 2 Migration: Populate profile_provider_configs from existing profiles
|
|
2
|
+
-- For each profile with a providerId, create a corresponding provider config record
|
|
3
|
+
|
|
4
|
+
INSERT INTO profile_provider_configs (id, profile_id, provider_id, options, env, created_at, updated_at)
|
|
5
|
+
SELECT
|
|
6
|
+
lower(hex(randomblob(4))) || '-' || lower(hex(randomblob(2))) || '-4' || substr(lower(hex(randomblob(2))),2) || '-' || substr('89ab',abs(random()) % 4 + 1, 1) || substr(lower(hex(randomblob(2))),2) || '-' || lower(hex(randomblob(6))) as id,
|
|
7
|
+
id as profile_id,
|
|
8
|
+
provider_id,
|
|
9
|
+
options,
|
|
10
|
+
NULL as env,
|
|
11
|
+
datetime('now') as created_at,
|
|
12
|
+
datetime('now') as updated_at
|
|
13
|
+
FROM agent_profiles
|
|
14
|
+
WHERE provider_id IS NOT NULL
|
|
15
|
+
AND NOT EXISTS (
|
|
16
|
+
SELECT 1 FROM profile_provider_configs ppc
|
|
17
|
+
WHERE ppc.profile_id = agent_profiles.id
|
|
18
|
+
AND ppc.provider_id = agent_profiles.provider_id
|
|
19
|
+
);
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
-- Phase 2 Migration: Auto-merge profiles by familySlug
|
|
2
|
+
-- For each (projectId, familySlug) group with multiple profiles:
|
|
3
|
+
-- 1. Keep oldest as canonical
|
|
4
|
+
-- 2. Capture agent→providerId mapping (BEFORE profile deletion)
|
|
5
|
+
-- 3. Move provider configs to canonical
|
|
6
|
+
-- 4. Set agents.provider_config_id based on original providerId
|
|
7
|
+
-- 5. Update agents to point to canonical profile
|
|
8
|
+
-- 6. Delete merged profiles
|
|
9
|
+
|
|
10
|
+
-- Step 1: Create temp table identifying canonical profiles (oldest per group)
|
|
11
|
+
CREATE TEMP TABLE canonical_profiles AS
|
|
12
|
+
WITH ranked AS (
|
|
13
|
+
SELECT
|
|
14
|
+
id,
|
|
15
|
+
project_id,
|
|
16
|
+
family_slug,
|
|
17
|
+
created_at,
|
|
18
|
+
ROW_NUMBER() OVER (PARTITION BY project_id, family_slug ORDER BY created_at ASC) as rn
|
|
19
|
+
FROM agent_profiles
|
|
20
|
+
WHERE family_slug IS NOT NULL
|
|
21
|
+
)
|
|
22
|
+
SELECT id as canonical_id, project_id, family_slug
|
|
23
|
+
FROM ranked
|
|
24
|
+
WHERE rn = 1
|
|
25
|
+
AND EXISTS (
|
|
26
|
+
SELECT 1 FROM ranked r2
|
|
27
|
+
WHERE r2.project_id = ranked.project_id
|
|
28
|
+
AND r2.family_slug = ranked.family_slug
|
|
29
|
+
AND r2.rn > 1
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
--> statement-breakpoint
|
|
33
|
+
|
|
34
|
+
-- Step 2: Create temp table with profiles to merge (non-canonical in groups)
|
|
35
|
+
CREATE TEMP TABLE profiles_to_merge AS
|
|
36
|
+
WITH ranked AS (
|
|
37
|
+
SELECT
|
|
38
|
+
id,
|
|
39
|
+
project_id,
|
|
40
|
+
family_slug,
|
|
41
|
+
ROW_NUMBER() OVER (PARTITION BY project_id, family_slug ORDER BY created_at ASC) as rn
|
|
42
|
+
FROM agent_profiles
|
|
43
|
+
WHERE family_slug IS NOT NULL
|
|
44
|
+
)
|
|
45
|
+
SELECT ranked.id as merge_id, cp.canonical_id
|
|
46
|
+
FROM ranked
|
|
47
|
+
JOIN canonical_profiles cp
|
|
48
|
+
ON ranked.project_id = cp.project_id
|
|
49
|
+
AND ranked.family_slug = cp.family_slug
|
|
50
|
+
WHERE ranked.rn > 1;
|
|
51
|
+
|
|
52
|
+
--> statement-breakpoint
|
|
53
|
+
|
|
54
|
+
-- Step 3: Capture agent→providerId mapping BEFORE profiles are merged/deleted
|
|
55
|
+
-- This preserves which provider each agent was originally using
|
|
56
|
+
CREATE TEMP TABLE agent_original_provider AS
|
|
57
|
+
SELECT a.id as agent_id, ap.provider_id
|
|
58
|
+
FROM agents a
|
|
59
|
+
JOIN agent_profiles ap ON a.profile_id = ap.id
|
|
60
|
+
WHERE a.profile_id IN (SELECT merge_id FROM profiles_to_merge);
|
|
61
|
+
|
|
62
|
+
--> statement-breakpoint
|
|
63
|
+
|
|
64
|
+
-- Step 4: Update provider configs - move from merged profiles to canonical
|
|
65
|
+
UPDATE profile_provider_configs
|
|
66
|
+
SET profile_id = (
|
|
67
|
+
SELECT canonical_id FROM profiles_to_merge ptm
|
|
68
|
+
WHERE ptm.merge_id = profile_provider_configs.profile_id
|
|
69
|
+
)
|
|
70
|
+
WHERE profile_id IN (SELECT merge_id FROM profiles_to_merge);
|
|
71
|
+
|
|
72
|
+
--> statement-breakpoint
|
|
73
|
+
|
|
74
|
+
-- Step 5: Set agents.provider_config_id based on original providerId
|
|
75
|
+
-- Match each agent to the config in their new canonical profile that has the same providerId
|
|
76
|
+
UPDATE agents
|
|
77
|
+
SET provider_config_id = (
|
|
78
|
+
SELECT ppc.id
|
|
79
|
+
FROM agent_original_provider aop
|
|
80
|
+
JOIN profiles_to_merge ptm ON agents.profile_id = ptm.merge_id
|
|
81
|
+
JOIN profile_provider_configs ppc ON ppc.profile_id = ptm.canonical_id
|
|
82
|
+
WHERE aop.agent_id = agents.id
|
|
83
|
+
AND ppc.provider_id = aop.provider_id
|
|
84
|
+
LIMIT 1
|
|
85
|
+
)
|
|
86
|
+
WHERE profile_id IN (SELECT merge_id FROM profiles_to_merge)
|
|
87
|
+
AND provider_config_id IS NULL;
|
|
88
|
+
|
|
89
|
+
--> statement-breakpoint
|
|
90
|
+
|
|
91
|
+
-- Step 6: Update agents - point to canonical profile
|
|
92
|
+
UPDATE agents
|
|
93
|
+
SET profile_id = (
|
|
94
|
+
SELECT canonical_id FROM profiles_to_merge ptm
|
|
95
|
+
WHERE ptm.merge_id = agents.profile_id
|
|
96
|
+
)
|
|
97
|
+
WHERE profile_id IN (SELECT merge_id FROM profiles_to_merge);
|
|
98
|
+
|
|
99
|
+
--> statement-breakpoint
|
|
100
|
+
|
|
101
|
+
-- Step 7: Delete merged profiles
|
|
102
|
+
DELETE FROM agent_profiles
|
|
103
|
+
WHERE id IN (SELECT merge_id FROM profiles_to_merge);
|
|
104
|
+
|
|
105
|
+
--> statement-breakpoint
|
|
106
|
+
|
|
107
|
+
-- Step 8: Cleanup temp tables
|
|
108
|
+
DROP TABLE agent_original_provider;
|
|
109
|
+
|
|
110
|
+
--> statement-breakpoint
|
|
111
|
+
|
|
112
|
+
DROP TABLE profiles_to_merge;
|
|
113
|
+
|
|
114
|
+
--> statement-breakpoint
|
|
115
|
+
|
|
116
|
+
DROP TABLE canonical_profiles;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
-- Phase 2 Migration: Set agents.providerConfigId
|
|
2
|
+
-- For agents not handled by 0029 (non-merged profiles), set providerConfigId
|
|
3
|
+
-- Match config by profile's provider_id (not by creation order)
|
|
4
|
+
|
|
5
|
+
UPDATE agents
|
|
6
|
+
SET provider_config_id = (
|
|
7
|
+
SELECT ppc.id
|
|
8
|
+
FROM profile_provider_configs ppc
|
|
9
|
+
JOIN agent_profiles ap ON ap.id = agents.profile_id
|
|
10
|
+
WHERE ppc.profile_id = agents.profile_id
|
|
11
|
+
AND ppc.provider_id = ap.provider_id
|
|
12
|
+
LIMIT 1
|
|
13
|
+
)
|
|
14
|
+
WHERE provider_config_id IS NULL;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
-- Phase 4: Remove legacy providerId and options columns from agent_profiles
|
|
2
|
+
-- Provider configuration now lives in profile_provider_configs table
|
|
3
|
+
-- This migration:
|
|
4
|
+
-- 1. Rebuilds agent_profiles without providerId and options columns
|
|
5
|
+
-- 2. Replaces family_provider_unique index with family_unique index
|
|
6
|
+
|
|
7
|
+
-- Note: foreign_keys are disabled in db.provider.ts before running migrations
|
|
8
|
+
-- (PRAGMA foreign_keys=OFF has no effect inside a transaction)
|
|
9
|
+
|
|
10
|
+
-- Step 1: Create new table without providerId and options columns
|
|
11
|
+
CREATE TABLE `__new_agent_profiles` (
|
|
12
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
13
|
+
`project_id` text,
|
|
14
|
+
`name` text NOT NULL,
|
|
15
|
+
`family_slug` text,
|
|
16
|
+
`system_prompt` text,
|
|
17
|
+
`instructions` text,
|
|
18
|
+
`temperature` integer,
|
|
19
|
+
`max_tokens` integer,
|
|
20
|
+
`created_at` text NOT NULL,
|
|
21
|
+
`updated_at` text NOT NULL,
|
|
22
|
+
FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`) ON UPDATE no action ON DELETE cascade
|
|
23
|
+
);
|
|
24
|
+
--> statement-breakpoint
|
|
25
|
+
|
|
26
|
+
-- Step 2: Copy data (excluding providerId and options)
|
|
27
|
+
INSERT INTO `__new_agent_profiles` (
|
|
28
|
+
`id`,
|
|
29
|
+
`project_id`,
|
|
30
|
+
`name`,
|
|
31
|
+
`family_slug`,
|
|
32
|
+
`system_prompt`,
|
|
33
|
+
`instructions`,
|
|
34
|
+
`temperature`,
|
|
35
|
+
`max_tokens`,
|
|
36
|
+
`created_at`,
|
|
37
|
+
`updated_at`
|
|
38
|
+
)
|
|
39
|
+
SELECT
|
|
40
|
+
`id`,
|
|
41
|
+
`project_id`,
|
|
42
|
+
`name`,
|
|
43
|
+
`family_slug`,
|
|
44
|
+
`system_prompt`,
|
|
45
|
+
`instructions`,
|
|
46
|
+
`temperature`,
|
|
47
|
+
`max_tokens`,
|
|
48
|
+
`created_at`,
|
|
49
|
+
`updated_at`
|
|
50
|
+
FROM `agent_profiles`;
|
|
51
|
+
--> statement-breakpoint
|
|
52
|
+
|
|
53
|
+
-- Step 3: Drop old table
|
|
54
|
+
DROP TABLE `agent_profiles`;
|
|
55
|
+
--> statement-breakpoint
|
|
56
|
+
|
|
57
|
+
-- Step 4: Rename new table
|
|
58
|
+
ALTER TABLE `__new_agent_profiles` RENAME TO `agent_profiles`;
|
|
59
|
+
--> statement-breakpoint
|
|
60
|
+
|
|
61
|
+
-- Step 5: Recreate indexes
|
|
62
|
+
-- Keep: unique constraint on (project_id, name)
|
|
63
|
+
CREATE UNIQUE INDEX `agent_profiles_project_name_unique` ON `agent_profiles` (`project_id`, `name`);
|
|
64
|
+
--> statement-breakpoint
|
|
65
|
+
|
|
66
|
+
-- New: unique constraint on (project_id, family_slug) - profiles are now provider-independent
|
|
67
|
+
-- Note: Replaces old agent_profiles_family_provider_unique which included provider_id
|
|
68
|
+
CREATE UNIQUE INDEX `agent_profiles_family_unique` ON `agent_profiles` (`project_id`, `family_slug`) WHERE `family_slug` IS NOT NULL;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
-- Phase 4: Make agents.providerConfigId NOT NULL
|
|
2
|
+
-- Prerequisites:
|
|
3
|
+
-- - Migration 0030 must have run to set all providerConfigId values
|
|
4
|
+
-- - No agents should have NULL providerConfigId
|
|
5
|
+
-- This migration will FAIL if any agent has NULL providerConfigId
|
|
6
|
+
-- (the INSERT into the NOT NULL column will fail naturally)
|
|
7
|
+
|
|
8
|
+
-- Rebuild agents table with NOT NULL constraint
|
|
9
|
+
-- Note: foreign_keys are disabled in db.provider.ts before running migrations
|
|
10
|
+
-- (PRAGMA foreign_keys=OFF has no effect inside a transaction)
|
|
11
|
+
|
|
12
|
+
CREATE TABLE `__new_agents` (
|
|
13
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
14
|
+
`project_id` text NOT NULL,
|
|
15
|
+
`profile_id` text NOT NULL,
|
|
16
|
+
`provider_config_id` text NOT NULL,
|
|
17
|
+
`name` text NOT NULL,
|
|
18
|
+
`description` text,
|
|
19
|
+
`created_at` text NOT NULL,
|
|
20
|
+
`updated_at` text NOT NULL,
|
|
21
|
+
FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`) ON UPDATE no action ON DELETE cascade,
|
|
22
|
+
FOREIGN KEY (`profile_id`) REFERENCES `agent_profiles`(`id`) ON UPDATE no action ON DELETE no action,
|
|
23
|
+
FOREIGN KEY (`provider_config_id`) REFERENCES `profile_provider_configs`(`id`) ON UPDATE no action ON DELETE restrict
|
|
24
|
+
);
|
|
25
|
+
--> statement-breakpoint
|
|
26
|
+
|
|
27
|
+
INSERT INTO `__new_agents` (
|
|
28
|
+
`id`,
|
|
29
|
+
`project_id`,
|
|
30
|
+
`profile_id`,
|
|
31
|
+
`provider_config_id`,
|
|
32
|
+
`name`,
|
|
33
|
+
`description`,
|
|
34
|
+
`created_at`,
|
|
35
|
+
`updated_at`
|
|
36
|
+
)
|
|
37
|
+
SELECT
|
|
38
|
+
`id`,
|
|
39
|
+
`project_id`,
|
|
40
|
+
`profile_id`,
|
|
41
|
+
`provider_config_id`,
|
|
42
|
+
`name`,
|
|
43
|
+
`description`,
|
|
44
|
+
`created_at`,
|
|
45
|
+
`updated_at`
|
|
46
|
+
FROM `agents`;
|
|
47
|
+
--> statement-breakpoint
|
|
48
|
+
|
|
49
|
+
DROP TABLE `agents`;
|
|
50
|
+
--> statement-breakpoint
|
|
51
|
+
|
|
52
|
+
ALTER TABLE `__new_agents` RENAME TO `agents`;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
-- Migration: Add name column to profile_provider_configs
|
|
2
|
+
-- This enables multiple configs per provider per profile (GLM use case)
|
|
3
|
+
|
|
4
|
+
-- Step 1: Add name column with default empty string
|
|
5
|
+
ALTER TABLE profile_provider_configs ADD COLUMN name TEXT NOT NULL DEFAULT '';
|
|
6
|
+
--> statement-breakpoint
|
|
7
|
+
|
|
8
|
+
-- Step 2: Backfill existing rows with deterministic names (provider_name + order suffix if needed)
|
|
9
|
+
-- Uses a CTE to assign row numbers per profile, then updates with provider-based names
|
|
10
|
+
WITH ranked_configs AS (
|
|
11
|
+
SELECT
|
|
12
|
+
ppc.id,
|
|
13
|
+
p.name AS provider_name,
|
|
14
|
+
ROW_NUMBER() OVER (
|
|
15
|
+
PARTITION BY ppc.profile_id, ppc.provider_id
|
|
16
|
+
ORDER BY ppc.created_at ASC, ppc.id ASC
|
|
17
|
+
) AS rn,
|
|
18
|
+
COUNT(*) OVER (
|
|
19
|
+
PARTITION BY ppc.profile_id, ppc.provider_id
|
|
20
|
+
) AS total_for_provider
|
|
21
|
+
FROM profile_provider_configs ppc
|
|
22
|
+
JOIN providers p ON p.id = ppc.provider_id
|
|
23
|
+
)
|
|
24
|
+
UPDATE profile_provider_configs
|
|
25
|
+
SET name = (
|
|
26
|
+
SELECT
|
|
27
|
+
CASE
|
|
28
|
+
WHEN rc.total_for_provider = 1 THEN rc.provider_name
|
|
29
|
+
ELSE rc.provider_name || '-' || rc.rn
|
|
30
|
+
END
|
|
31
|
+
FROM ranked_configs rc
|
|
32
|
+
WHERE rc.id = profile_provider_configs.id
|
|
33
|
+
)
|
|
34
|
+
WHERE name = '';
|
|
35
|
+
--> statement-breakpoint
|
|
36
|
+
|
|
37
|
+
-- Step 3: Create unique index on (profile_id, name)
|
|
38
|
+
CREATE UNIQUE INDEX profile_provider_configs_profile_name_idx ON profile_provider_configs(profile_id, name);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
-- Migration 0034: Clean up duplicate sessions and add unique index
|
|
2
|
+
-- This migration ensures only one running session per agent exists before adding the constraint
|
|
3
|
+
|
|
4
|
+
-- Step 1: Clean up any existing duplicate running sessions
|
|
5
|
+
-- For each agent with multiple running sessions, keep exactly one and mark the rest as 'stopped'
|
|
6
|
+
-- Uses window function for deterministic ordering even when started_at timestamps are identical
|
|
7
|
+
UPDATE sessions
|
|
8
|
+
SET status = 'stopped',
|
|
9
|
+
ended_at = datetime('now'),
|
|
10
|
+
updated_at = datetime('now')
|
|
11
|
+
WHERE id IN (
|
|
12
|
+
-- Find all duplicate sessions (rn > 1 means not the first for that agent)
|
|
13
|
+
SELECT id FROM (
|
|
14
|
+
SELECT id,
|
|
15
|
+
ROW_NUMBER() OVER (
|
|
16
|
+
PARTITION BY agent_id
|
|
17
|
+
ORDER BY started_at DESC, created_at DESC, id DESC
|
|
18
|
+
) as rn
|
|
19
|
+
FROM sessions
|
|
20
|
+
WHERE status = 'running'
|
|
21
|
+
AND agent_id IS NOT NULL
|
|
22
|
+
) ranked
|
|
23
|
+
WHERE rn > 1
|
|
24
|
+
);
|
|
25
|
+
--> statement-breakpoint
|
|
26
|
+
|
|
27
|
+
-- Step 2: Add partial unique index to prevent future duplicates
|
|
28
|
+
-- This is a safety net for the application-level lock (withAgentLock in SessionsService)
|
|
29
|
+
-- to catch any edge cases where concurrent requests might create duplicate sessions
|
|
30
|
+
CREATE UNIQUE INDEX `idx_sessions_agent_running` ON `sessions` (`agent_id`) WHERE status = 'running' AND agent_id IS NOT NULL;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
-- Migration: Add position column to profile_provider_configs
|
|
2
|
+
-- This enables drag-and-drop ordering of provider configs within a profile
|
|
3
|
+
|
|
4
|
+
-- Step 1: Add position column with default 0
|
|
5
|
+
ALTER TABLE profile_provider_configs ADD COLUMN position INTEGER NOT NULL DEFAULT 0;
|
|
6
|
+
--> statement-breakpoint
|
|
7
|
+
|
|
8
|
+
-- Step 2: Backfill positions based on createdAt order per profile
|
|
9
|
+
-- Uses CTE with ROW_NUMBER() to assign sequential positions (0, 1, 2, ...)
|
|
10
|
+
WITH ranked AS (
|
|
11
|
+
SELECT
|
|
12
|
+
id,
|
|
13
|
+
ROW_NUMBER() OVER (PARTITION BY profile_id ORDER BY created_at ASC, id ASC) - 1 AS pos
|
|
14
|
+
FROM profile_provider_configs
|
|
15
|
+
)
|
|
16
|
+
UPDATE profile_provider_configs
|
|
17
|
+
SET position = (
|
|
18
|
+
SELECT pos
|
|
19
|
+
FROM ranked
|
|
20
|
+
WHERE ranked.id = profile_provider_configs.id
|
|
21
|
+
);
|
|
22
|
+
--> statement-breakpoint
|
|
23
|
+
|
|
24
|
+
-- Step 3: Create unique index on (profile_id, position)
|
|
25
|
+
CREATE UNIQUE INDEX profile_provider_configs_profile_position_idx
|
|
26
|
+
ON profile_provider_configs(profile_id, position);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Phase 2 Migration Guide: Profile Provider Configs
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Phase 2 migrations populate the `profile_provider_configs` table and merge duplicate profiles.
|
|
6
|
+
|
|
7
|
+
**Migrations:**
|
|
8
|
+
- `0028_populate_provider_configs.sql` - Create configs from existing profiles
|
|
9
|
+
- `0029_merge_profiles_by_family_slug.sql` - Merge profiles with same familySlug
|
|
10
|
+
- `0030_set_agents_provider_config_id.sql` - Set agent config references
|
|
11
|
+
|
|
12
|
+
## Pre-Migration Checklist
|
|
13
|
+
|
|
14
|
+
### 1. Stop All Sessions
|
|
15
|
+
|
|
16
|
+
Before running migrations, ensure no active sessions exist:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
sqlite3 ~/.devchain/devchain.db < apps/local-app/drizzle/migration-guard.sql
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If any output is shown, stop the sessions first:
|
|
23
|
+
```bash
|
|
24
|
+
# List running sessions
|
|
25
|
+
sqlite3 ~/.devchain/devchain.db "SELECT id, agent_id FROM sessions WHERE status='running';"
|
|
26
|
+
|
|
27
|
+
# Stop sessions via UI or terminate tmux sessions
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2. Create Backup
|
|
31
|
+
|
|
32
|
+
**CRITICAL:** Always backup before migrating:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
cp ~/.devchain/devchain.db ~/.devchain/devchain.db.backup-$(date +%Y%m%d-%H%M%S)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 3. Verify Backup
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
sqlite3 ~/.devchain/devchain.db.backup-* "SELECT COUNT(*) FROM agent_profiles;"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Running Migrations
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pnpm --filter local-app db:migrate
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Or manually:
|
|
51
|
+
```bash
|
|
52
|
+
sqlite3 ~/.devchain/devchain.db < apps/local-app/drizzle/0028_populate_provider_configs.sql
|
|
53
|
+
sqlite3 ~/.devchain/devchain.db < apps/local-app/drizzle/0029_merge_profiles_by_family_slug.sql
|
|
54
|
+
sqlite3 ~/.devchain/devchain.db < apps/local-app/drizzle/0030_set_agents_provider_config_id.sql
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Post-Migration Verification
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Verify configs created
|
|
61
|
+
sqlite3 ~/.devchain/devchain.db "SELECT COUNT(*) FROM profile_provider_configs;"
|
|
62
|
+
|
|
63
|
+
# Verify no duplicate familySlug groups
|
|
64
|
+
sqlite3 ~/.devchain/devchain.db "SELECT project_id, family_slug, COUNT(*) FROM agent_profiles WHERE family_slug IS NOT NULL GROUP BY project_id, family_slug HAVING COUNT(*) > 1;"
|
|
65
|
+
|
|
66
|
+
# Verify all agents have config
|
|
67
|
+
sqlite3 ~/.devchain/devchain.db "SELECT COUNT(*) FROM agents WHERE provider_config_id IS NULL;"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Rollback Procedure
|
|
71
|
+
|
|
72
|
+
### Recommended: Restore from Backup
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Stop the application
|
|
76
|
+
# Restore backup
|
|
77
|
+
cp ~/.devchain/devchain.db.backup-YYYYMMDD-HHMMSS ~/.devchain/devchain.db
|
|
78
|
+
|
|
79
|
+
# Restart the application
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Alternative: Partial Rollback Script
|
|
83
|
+
|
|
84
|
+
**WARNING:** The partial rollback script cannot restore deleted profiles from the merge step.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
sqlite3 ~/.devchain/devchain.db < apps/local-app/drizzle/phase2-rollback.sql
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This will:
|
|
91
|
+
1. Clear `agents.provider_config_id` (set to NULL)
|
|
92
|
+
2. Delete all `profile_provider_configs` records
|
|
93
|
+
3. Remove migration tracking entries
|
|
94
|
+
|
|
95
|
+
**NOT restored:** Profiles deleted during merge (0029) cannot be restored without backup.
|
|
96
|
+
|
|
97
|
+
## Troubleshooting
|
|
98
|
+
|
|
99
|
+
### Migration fails with "database is locked"
|
|
100
|
+
- Stop all sessions and the application
|
|
101
|
+
- Ensure no other process is accessing the database
|
|
102
|
+
|
|
103
|
+
### Agents have NULL providerConfigId after migration
|
|
104
|
+
- Verify profile has a config: `SELECT * FROM profile_provider_configs WHERE profile_id = '<profile_id>';`
|
|
105
|
+
- Re-run migration 0030
|
|
106
|
+
|
|
107
|
+
### Profile configs missing
|
|
108
|
+
- Check if profile has providerId: `SELECT provider_id FROM agent_profiles WHERE id = '<profile_id>';`
|
|
109
|
+
- Profiles with NULL providerId don't get configs created
|