feat(cli): command architecture — agents, missions, and gateway-aware prdy
DB schema: - Extend agents table with projectId, ownerId, systemPrompt, allowedTools, skills, isSystem columns and indexes - Add agentId FK to conversations table with index Brain: - New agents repository (findAll, findById, findByName, findByProject, findSystem, findAccessible, create, update, remove) - Wire into Brain interface and createBrain factory Gateway: - New AgentConfigsController at /api/agents with full CRUD + ownership guards - Consolidate /api/missions — user-scoped CRUD replaces old project-ownership model, add /api/missions/:id/tasks sub-routes (replaces coord mission-tasks) - Slim coord controller to file-based endpoints only (agent tool consumption) - Remove DB-backed methods from CoordService (now handled by Brain repos) - Wire agentConfigId into AgentService.createSession for DB config merging - Add agentId field to ChatSocketMessageDto and ChatMessagePayload CLI: - New `mosaic agent` command (--list, --new, --show, --update, --delete) - New `mosaic mission` command (--list, --init, --plan, --update, task sub) - New `mosaic prdy` gateway-aware wrapper (--init, --update, --project) - Shared with-auth helper and select-dialog utility - TUI: accept --agent and --project flags, pass agentId to socket, display agent name in top bar - Gateway API client: add agents, projects, missions, mission-tasks helpers - Add @clack/prompts dependency - Refactor sessions commands to use with-auth helper Types: - Add agentId to ChatMessagePayload Tests: - Update resource-ownership test for user-scoped missions (NotFoundException) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -190,18 +190,32 @@ export const events = pgTable(
|
||||
(t) => [index('events_type_idx').on(t.type), index('events_date_idx').on(t.date)],
|
||||
);
|
||||
|
||||
export const agents = pgTable('agents', {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
name: text('name').notNull(),
|
||||
provider: text('provider').notNull(),
|
||||
model: text('model').notNull(),
|
||||
status: text('status', { enum: ['idle', 'active', 'error', 'offline'] })
|
||||
.notNull()
|
||||
.default('idle'),
|
||||
config: jsonb('config'),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
});
|
||||
export const agents = pgTable(
|
||||
'agents',
|
||||
{
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
name: text('name').notNull(),
|
||||
provider: text('provider').notNull(),
|
||||
model: text('model').notNull(),
|
||||
status: text('status', { enum: ['idle', 'active', 'error', 'offline'] })
|
||||
.notNull()
|
||||
.default('idle'),
|
||||
projectId: uuid('project_id').references(() => projects.id, { onDelete: 'set null' }),
|
||||
ownerId: text('owner_id').references(() => users.id, { onDelete: 'set null' }),
|
||||
systemPrompt: text('system_prompt'),
|
||||
allowedTools: jsonb('allowed_tools').$type<string[]>(),
|
||||
skills: jsonb('skills').$type<string[]>(),
|
||||
isSystem: boolean('is_system').notNull().default(false),
|
||||
config: jsonb('config'),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
},
|
||||
(t) => [
|
||||
index('agents_project_id_idx').on(t.projectId),
|
||||
index('agents_owner_id_idx').on(t.ownerId),
|
||||
index('agents_is_system_idx').on(t.isSystem),
|
||||
],
|
||||
);
|
||||
|
||||
export const tickets = pgTable(
|
||||
'tickets',
|
||||
@@ -243,6 +257,7 @@ export const conversations = pgTable(
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: 'cascade' }),
|
||||
projectId: uuid('project_id').references(() => projects.id, { onDelete: 'set null' }),
|
||||
agentId: uuid('agent_id').references(() => agents.id, { onDelete: 'set null' }),
|
||||
archived: boolean('archived').notNull().default(false),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
@@ -250,6 +265,7 @@ export const conversations = pgTable(
|
||||
(t) => [
|
||||
index('conversations_user_id_idx').on(t.userId),
|
||||
index('conversations_project_id_idx').on(t.projectId),
|
||||
index('conversations_agent_id_idx').on(t.agentId),
|
||||
index('conversations_archived_idx').on(t.archived),
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user