refactor(db): rename agent_runs/agent_run_actions to scout_*
Rename Drizzle table definitions: agentRuns → scoutRuns, agentRunActions → scoutRunActions. Column agentId → scoutId. Hand-crafted migration 0007_scouts_rename.sql uses ALTER TABLE RENAME + CREATE/INSERT/DROP for column rename (SQLite limitation). Updated all main-process consumers (backend-client, agent-scheduler, router). Renderer-side type/component rename deferred to Tasks 8-9. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
import { getLocalAgents, saveLocalAgent, getDeviceId } from '../store';
|
||||
import { getBackendClient } from '../api/backend-client';
|
||||
import { getDb } from '../db';
|
||||
import { agentRuns } from '../db/schema';
|
||||
import { scoutRuns } from '../db/schema';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Constants
|
||||
@@ -99,9 +99,9 @@ async function tickAgentScheduler(): Promise<void> {
|
||||
// the agent finds nothing to create/update.
|
||||
if (response?.id) {
|
||||
try {
|
||||
await getDb().insert(agentRuns).values({
|
||||
await getDb().insert(scoutRuns).values({
|
||||
id: response.id,
|
||||
agentId: agent.id,
|
||||
scoutId: agent.id,
|
||||
status: 'running',
|
||||
startedAt: now,
|
||||
}).onConflictDoNothing();
|
||||
|
||||
@@ -32,7 +32,7 @@ import type {
|
||||
} from '../../shared/api-types';
|
||||
import { DrizzleExecutor } from './drizzle-executor';
|
||||
import { getDb } from '../db';
|
||||
import { agentRuns, agentRunActions } from '../db/schema';
|
||||
import { scoutRuns, scoutRunActions } from '../db/schema';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Agent run logging helpers
|
||||
@@ -60,10 +60,10 @@ async function recordRunAction(
|
||||
entityTitle: string | null,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await getDb().insert(agentRunActions).values({
|
||||
await getDb().insert(scoutRunActions).values({
|
||||
id: crypto.randomUUID(),
|
||||
runId,
|
||||
agentId,
|
||||
scoutId: agentId,
|
||||
verb,
|
||||
entityType,
|
||||
entityId: entityId ?? null,
|
||||
@@ -989,9 +989,9 @@ export class BackendClient {
|
||||
void (async () => {
|
||||
try {
|
||||
const db = getDb();
|
||||
await db.update(agentRuns)
|
||||
await db.update(scoutRuns)
|
||||
.set({ status: status === 'success' ? 'completed' : status === 'partial' ? 'partial' : 'failed', completedAt: Date.now() })
|
||||
.where(eq(agentRuns.id, runContext.runId));
|
||||
.where(eq(scoutRuns.id, runContext.runId));
|
||||
} catch (err) {
|
||||
console.warn('[RunLog] Failed to close run:', err);
|
||||
}
|
||||
|
||||
44
src/main/db/migrations/0007_scouts_rename.sql
Normal file
44
src/main/db/migrations/0007_scouts_rename.sql
Normal file
@@ -0,0 +1,44 @@
|
||||
-- Rename agent_runs → scout_runs and agent_run_actions → scout_run_actions
|
||||
-- SQLite supports ALTER TABLE RENAME TO; column rename (agent_id → scout_id) requires recreate.
|
||||
|
||||
-- Step 1: rename agent_runs table
|
||||
ALTER TABLE `agent_runs` RENAME TO `scout_runs`;
|
||||
--> statement-breakpoint
|
||||
|
||||
-- Step 2: rename agent_run_actions table
|
||||
ALTER TABLE `agent_run_actions` RENAME TO `scout_run_actions`;
|
||||
--> statement-breakpoint
|
||||
|
||||
-- Step 3: rename agent_id column in scout_runs (SQLite requires full table recreate for column rename)
|
||||
CREATE TABLE `__new_scout_runs` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`scout_id` text NOT NULL,
|
||||
`status` text DEFAULT 'running' NOT NULL,
|
||||
`started_at` integer NOT NULL,
|
||||
`completed_at` integer
|
||||
);
|
||||
--> statement-breakpoint
|
||||
INSERT INTO `__new_scout_runs` SELECT `id`, `agent_id`, `status`, `started_at`, `completed_at` FROM `scout_runs`;
|
||||
--> statement-breakpoint
|
||||
DROP TABLE `scout_runs`;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `__new_scout_runs` RENAME TO `scout_runs`;
|
||||
--> statement-breakpoint
|
||||
|
||||
-- Step 4: rename agent_id column in scout_run_actions
|
||||
CREATE TABLE `__new_scout_run_actions` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`run_id` text NOT NULL,
|
||||
`scout_id` text NOT NULL,
|
||||
`verb` text NOT NULL,
|
||||
`entity_type` text NOT NULL,
|
||||
`entity_id` text,
|
||||
`entity_title` text,
|
||||
`created_at` integer NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
INSERT INTO `__new_scout_run_actions` SELECT `id`, `run_id`, `agent_id`, `verb`, `entity_type`, `entity_id`, `entity_title`, `created_at` FROM `scout_run_actions`;
|
||||
--> statement-breakpoint
|
||||
DROP TABLE `scout_run_actions`;
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE `__new_scout_run_actions` RENAME TO `scout_run_actions`;
|
||||
1058
src/main/db/migrations/meta/0007_snapshot.json
Normal file
1058
src/main/db/migrations/meta/0007_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -50,6 +50,13 @@
|
||||
"when": 1778777130582,
|
||||
"tag": "0006_misty_cammi",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"version": "6",
|
||||
"when": 1747353600000,
|
||||
"tag": "0007_scouts_rename",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -169,18 +169,18 @@ export const taskBriefChats = sqliteTable('task_brief_chats', {
|
||||
export type TaskBriefChat = InferSelectModel<typeof taskBriefChats>;
|
||||
export type NewTaskBriefChat = InferInsertModel<typeof taskBriefChats>;
|
||||
|
||||
export const agentRuns = sqliteTable('agent_runs', {
|
||||
export const scoutRuns = sqliteTable('scout_runs', {
|
||||
id: text('id').primaryKey(),
|
||||
agentId: text('agent_id').notNull(),
|
||||
scoutId: text('scout_id').notNull(),
|
||||
status: text('status', { enum: ['running', 'completed', 'failed', 'partial'] }).notNull().default('running'),
|
||||
startedAt: integer('started_at', { mode: 'number' }).notNull(),
|
||||
completedAt: integer('completed_at', { mode: 'number' }),
|
||||
});
|
||||
|
||||
export const agentRunActions = sqliteTable('agent_run_actions', {
|
||||
export const scoutRunActions = sqliteTable('scout_run_actions', {
|
||||
id: text('id').primaryKey(),
|
||||
runId: text('run_id').notNull(),
|
||||
agentId: text('agent_id').notNull(),
|
||||
scoutId: text('scout_id').notNull(),
|
||||
/** 'created' | 'updated' | 'deleted' | 'commented' */
|
||||
verb: text('verb').notNull(),
|
||||
/** 'task' | 'note' | 'project' | 'timeline' | 'comment' */
|
||||
@@ -190,10 +190,10 @@ export const agentRunActions = sqliteTable('agent_run_actions', {
|
||||
createdAt: integer('created_at', { mode: 'number' }).notNull(),
|
||||
});
|
||||
|
||||
export type AgentRun = InferSelectModel<typeof agentRuns>;
|
||||
export type NewAgentRun = InferInsertModel<typeof agentRuns>;
|
||||
export type AgentRunAction = InferSelectModel<typeof agentRunActions>;
|
||||
export type NewAgentRunAction = InferInsertModel<typeof agentRunActions>;
|
||||
export type ScoutRun = InferSelectModel<typeof scoutRuns>;
|
||||
export type NewScoutRun = InferInsertModel<typeof scoutRuns>;
|
||||
export type ScoutRunAction = InferSelectModel<typeof scoutRunActions>;
|
||||
export type NewScoutRunAction = InferInsertModel<typeof scoutRunActions>;
|
||||
|
||||
export type NoteEdit = InferSelectModel<typeof noteEdits>;
|
||||
export type NewNoteEdit = InferInsertModel<typeof noteEdits>;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { dialog, shell } from 'electron';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { stat } from 'node:fs/promises';
|
||||
import { getDb } from '../db';
|
||||
import { clients, projects, tasks, timelineEvents, timelineEventDependencies, notes, noteEdits, taskComments, taskAttachments, agentRuns, agentRunActions, taskBriefings, taskBriefChats } from '../db/schema';
|
||||
import { clients, projects, tasks, timelineEvents, timelineEventDependencies, notes, noteEdits, taskComments, taskAttachments, scoutRuns, scoutRunActions, taskBriefings, taskBriefChats } from '../db/schema';
|
||||
import { copyIntoTask, deleteStored, absolutePath, deleteTaskDir } from '../attachments/storage';
|
||||
import { createHash } from 'crypto';
|
||||
import { getStore, getDeviceId, getLocalAgents, getLocalAgent, saveLocalAgent, deleteLocalAgent, getFormatPrefs, setFormatPrefs, getUiLanguage, setUiLanguage, getTimelineZoom, setTimelineZoom } from '../store';
|
||||
@@ -1289,18 +1289,18 @@ const agentRouter = router({
|
||||
const offset = input.offset ?? 0;
|
||||
const rows = await db
|
||||
.select()
|
||||
.from(agentRuns)
|
||||
.where(eq(agentRuns.agentId, input.agentId))
|
||||
.orderBy(desc(agentRuns.startedAt))
|
||||
.from(scoutRuns)
|
||||
.where(eq(scoutRuns.scoutId, input.agentId))
|
||||
.orderBy(desc(scoutRuns.startedAt))
|
||||
.limit(limit)
|
||||
.offset(offset);
|
||||
|
||||
// Compute per-run action counts in one query
|
||||
const runIds = rows.map(r => r.id);
|
||||
const actionRows = runIds.length > 0
|
||||
? await db.select({ runId: agentRunActions.runId, verb: agentRunActions.verb, entityType: agentRunActions.entityType })
|
||||
.from(agentRunActions)
|
||||
.where(inArray(agentRunActions.runId, runIds))
|
||||
? await db.select({ runId: scoutRunActions.runId, verb: scoutRunActions.verb, entityType: scoutRunActions.entityType })
|
||||
.from(scoutRunActions)
|
||||
.where(inArray(scoutRunActions.runId, runIds))
|
||||
: [];
|
||||
|
||||
type ActionCounts = { created: number; updated: number; deleted: number };
|
||||
@@ -1332,9 +1332,9 @@ const agentRouter = router({
|
||||
const db = getDb();
|
||||
return await db
|
||||
.select()
|
||||
.from(agentRunActions)
|
||||
.where(eq(agentRunActions.runId, input.runId))
|
||||
.orderBy(asc(agentRunActions.createdAt));
|
||||
.from(scoutRunActions)
|
||||
.where(eq(scoutRunActions.runId, input.runId))
|
||||
.orderBy(asc(scoutRunActions.createdAt));
|
||||
} catch (err) {
|
||||
console.error('[Agent] runActions error:', err);
|
||||
return [];
|
||||
@@ -1383,9 +1383,9 @@ const agentRouter = router({
|
||||
// Create the run row so it appears in history even with zero mutations
|
||||
if (result?.id) {
|
||||
try {
|
||||
await getDb().insert(agentRuns).values({
|
||||
await getDb().insert(scoutRuns).values({
|
||||
id: result.id,
|
||||
agentId: agent.id,
|
||||
scoutId: agent.id,
|
||||
status: 'running',
|
||||
startedAt: Date.now(),
|
||||
}).onConflictDoNothing();
|
||||
|
||||
Reference in New Issue
Block a user