feat: update codex live automation and plan flows

This commit is contained in:
2026-04-24 08:06:36 +09:00
parent 916107dbe5
commit f2d6310efa
47 changed files with 2767 additions and 507 deletions

View File

@@ -6,6 +6,11 @@ import {
PLAN_TABLE,
planAutomationTypeSchema,
} from './plan-service.js';
import {
resolveAutomationType,
resolveStoredAutomationTypeId,
type AutomationTypeRecord,
} from './automation-type-config-service.js';
export const BOARD_POSTS_TABLE = 'board_posts';
@@ -58,7 +63,7 @@ function mapBoardPostRow(row: Record<string, unknown>): BoardPostItem {
title: String(row.title ?? ''),
content,
preview: createPreview(content),
automationType: normalizePlanAutomationType(row.automation_type),
automationType: resolveStoredAutomationTypeId(row),
automationPlanItemId: row.automation_plan_item_id === null || row.automation_plan_item_id === undefined
? null
: Number(row.automation_plan_item_id),
@@ -74,19 +79,27 @@ function isBoardPostAutomationLocked(row: Record<string, unknown>) {
return Boolean(row.automation_received_at || row.automation_plan_item_id);
}
export function buildBoardPostPlanNote(title: string, content: string) {
export function buildBoardPostPlanNote(title: string, content: string, automationType?: Pick<AutomationTypeRecord, 'name' | 'description'> | null) {
const normalizedTitle = title.trim();
const normalizedContent = content.trim();
const normalizedAutomationTypeName = String(automationType?.name ?? '').trim();
const normalizedAutomationContext = String(automationType?.description ?? '').trim();
return [
'# 자동화 작업메모',
'',
`- 게시판 제목: ${normalizedTitle}`,
'- 메모 출처: board_posts 자동화 접수',
normalizedAutomationTypeName ? `- 선택 자동화 유형: ${normalizedAutomationTypeName}` : null,
'',
'## 선택된 유형 context',
normalizedAutomationContext || '선택된 자동화 유형 context 없음',
'',
'## 요청 본문',
normalizedContent,
].join('\n');
]
.filter((line): line is string => line !== null)
.join('\n');
}
function resolveInsertedId(result: unknown): number | null {
@@ -159,6 +172,7 @@ export async function ensureBoardPostsTable() {
['title', (table) => table.string('title', 200).notNullable().defaultTo('제목 없음')],
['content', (table) => table.text('content').notNullable().defaultTo('')],
['automation_type', (table) => table.string('automation_type', 40).notNullable().defaultTo('none')],
['automation_type_id', (table) => table.string('automation_type_id', 120).nullable()],
['automation_plan_item_id', (table) => table.integer('automation_plan_item_id').nullable()],
['automation_received_at', (table) => table.timestamp('automation_received_at', { useTz: true }).nullable()],
['created_at', (table) => table.timestamp('created_at', { useTz: true }).notNullable().defaultTo(db.fn.now())],
@@ -187,6 +201,11 @@ export async function ensureBoardPostsTable() {
await db(BOARD_POSTS_TABLE)
.where({ automation_type: 'general_development' })
.update({ automation_type: 'auto_worker' });
await db(BOARD_POSTS_TABLE)
.whereNull('automation_type_id')
.update({
automation_type_id: db.raw('automation_type'),
});
}
export async function listBoardPosts() {
@@ -206,10 +225,12 @@ export async function getBoardPost(id: number) {
export async function createBoardPost(payload: z.infer<typeof boardPostPayloadSchema>) {
await ensureBoardPostsTable();
const parsedPayload = boardPostPayloadSchema.parse(payload);
const automationType = await resolveAutomationType(parsedPayload.automationType);
const insertQuery = db(BOARD_POSTS_TABLE).insert({
title: parsedPayload.title,
content: parsedPayload.content,
automation_type: parsedPayload.automationType,
automation_type: automationType.behaviorType,
automation_type_id: automationType.id,
created_at: db.fn.now(),
updated_at: db.fn.now(),
});
@@ -255,10 +276,12 @@ export async function receiveBoardPostAutomation(id: number) {
const title = String(currentRow.title ?? '').trim();
const content = String(currentRow.content ?? '').trim();
const workId = `board-post-${id}`;
const automationType = await resolveAutomationType(currentRow.automation_type_id ?? currentRow.automation_type);
const insertQuery = trx(PLAN_TABLE).insert({
work_id: workId,
note: buildBoardPostPlanNote(title, content),
note: buildBoardPostPlanNote(title, content, automationType),
automation_type: normalizePlanAutomationType(currentRow.automation_type),
automation_type_id: currentRow.automation_type_id ?? currentRow.automation_type,
status: '등록',
release_target: 'release',
jangsing_processing_required: true,
@@ -303,6 +326,7 @@ export async function receiveBoardPostAutomation(id: number) {
export async function updateBoardPost(id: number, payload: z.infer<typeof boardPostPayloadSchema>) {
await ensureBoardPostsTable();
const parsedPayload = boardPostPayloadSchema.parse(payload);
const automationType = await resolveAutomationType(parsedPayload.automationType);
return db.transaction(async (trx) => {
const currentRow = await trx(BOARD_POSTS_TABLE).where({ id }).forUpdate().first();
@@ -319,7 +343,8 @@ export async function updateBoardPost(id: number, payload: z.infer<typeof boardP
.update({
title: parsedPayload.title,
content: parsedPayload.content,
automation_type: parsedPayload.automationType,
automation_type: automationType.behaviorType,
automation_type_id: automationType.id,
updated_at: trx.fn.now(),
});