Skip to content

Commit 124a3ed

Browse files
authored
Merge pull request #34 from kc3hack/feat/nenrin/#31-page-optimize
feat: #31 page optimize
2 parents 97bd853 + 8cb1e1a commit 124a3ed

11 files changed

Lines changed: 1690 additions & 1092 deletions

File tree

backend/src/features/task-decompose/task-calendar.service.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {
33
TaskDecomposeRequest,
44
TaskDecomposeResult,
55
} from "./task-decompose.types";
6+
import { normalizeTaskTimezone } from "./task-timezone";
67
import type {
78
CalendarCreatedEvent,
89
CalendarSyncResult,
@@ -51,6 +52,23 @@ function buildEventSummary(
5152
return `[${index + 1}/${totalCount}] ${normalizedSubtask} | ${normalizedOverall}`;
5253
}
5354

55+
function toOverallTaskName(
56+
requestTask: string,
57+
breakdown: TaskDecomposeResult,
58+
): string {
59+
const summary = toSingleLine(breakdown.summary ?? "");
60+
if (summary.length > 0) {
61+
return summary;
62+
}
63+
64+
const goal = toSingleLine(breakdown.goal ?? "");
65+
if (goal.length > 0) {
66+
return goal;
67+
}
68+
69+
return toSingleLine(requestTask);
70+
}
71+
5472
function safeDate(value: string, fallback: Date): Date {
5573
const parsed = new Date(value);
5674
if (Number.isNaN(parsed.getTime())) {
@@ -279,8 +297,12 @@ export async function createCalendarEvents(
279297
input: CreateCalendarEventsInput,
280298
): Promise<CalendarSyncResult> {
281299
const accessToken = await getGoogleAccessToken(env, input.userId);
282-
const timezone = input.request.timezone ?? "UTC";
300+
const timezone = normalizeTaskTimezone(input.request.timezone);
283301
const calendarId = PRIMARY_CALENDAR_ID;
302+
const overallTaskName = toOverallTaskName(
303+
input.request.task,
304+
input.breakdown,
305+
);
284306

285307
const createdEvents: CalendarCreatedEvent[] = [];
286308
const totalCount = Math.max(input.breakdown.subtasks.length, 1);
@@ -296,7 +318,7 @@ export async function createCalendarEvents(
296318
const eventId = await createStableEventId(input.workflowId, index);
297319
const summary = buildEventSummary(
298320
subtask.title,
299-
input.request.task,
321+
overallTaskName,
300322
index,
301323
totalCount,
302324
);

backend/src/features/task-decompose/task-decompose.service.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import type {
33
TaskDecomposeResult,
44
TaskSubtask,
55
} from "./task-decompose.types";
6+
import { normalizeTaskTimezone } from "./task-timezone";
67

78
const AI_MODEL = "@cf/meta/llama-3.1-8b-instruct-fp8";
89
const DEFAULT_MAX_STEPS = 6;
910
const MIN_DURATION_MINUTES = 15;
1011
const MAX_DURATION_MINUTES = 240;
1112
const DEFAULT_INFERRED_DEADLINE_DAYS = 7;
12-
const DEFAULT_PLANNING_TIMEZONE = "Asia/Tokyo";
1313

1414
function asStringArray(value: unknown): string[] {
1515
if (!Array.isArray(value)) {
@@ -76,14 +76,6 @@ function fallbackSummary(task: string): string {
7676
return `"${task}" を実行可能な単位へ分解した計画です。`;
7777
}
7878

79-
function normalizeTimezone(timezone: string | undefined): string {
80-
if (!timezone || timezone.trim().length === 0) {
81-
return DEFAULT_PLANNING_TIMEZONE;
82-
}
83-
84-
return timezone.trim();
85-
}
86-
8779
function formatPromptDateInTimezone(date: Date, timezone: string): string {
8880
try {
8981
return new Intl.DateTimeFormat("en-CA", {
@@ -260,7 +252,7 @@ function normalizeResult(
260252

261253
function createPrompt(payload: TaskDecomposeRequest): string {
262254
const maxSteps = payload.maxSteps ?? DEFAULT_MAX_STEPS;
263-
const planningTimezone = normalizeTimezone(payload.timezone);
255+
const planningTimezone = normalizeTaskTimezone(payload.timezone);
264256
const now = new Date();
265257

266258
const deadlineGuidance = payload.deadline

backend/src/features/task-decompose/task-decompose.types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ export type TaskDecomposeRequest = {
77
maxSteps?: number;
88
};
99

10+
export type ValidatedTaskDecomposeRequest = Omit<
11+
TaskDecomposeRequest,
12+
"timezone"
13+
> & {
14+
timezone: string;
15+
};
16+
1017
export type TaskSubtask = {
1118
title: string;
1219
description: string;

backend/src/features/task-decompose/task-decompose.validation.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { TaskDecomposeRequest } from "./task-decompose.types";
1+
import type { ValidatedTaskDecomposeRequest } from "./task-decompose.types";
2+
import { normalizeTaskTimezone } from "./task-timezone";
23

34
const MAX_STEPS_LIMIT = 12;
45

@@ -20,17 +21,12 @@ function parseDeadline(value: unknown): string | undefined {
2021
return parsed.toISOString();
2122
}
2223

23-
function parseTimezone(value: unknown): string | undefined {
24+
function parseTimezone(value: unknown): string {
2425
if (typeof value !== "string") {
25-
return undefined;
26-
}
27-
28-
const trimmed = value.trim();
29-
if (trimmed.length === 0) {
30-
return undefined;
26+
return normalizeTaskTimezone(undefined);
3127
}
3228

33-
return trimmed;
29+
return normalizeTaskTimezone(value);
3430
}
3531

3632
function parseMaxSteps(value: unknown): number | undefined {
@@ -46,7 +42,9 @@ function parseMaxSteps(value: unknown): number | undefined {
4642
return Math.min(rounded, MAX_STEPS_LIMIT);
4743
}
4844

49-
export function toRequestPayload(input: unknown): TaskDecomposeRequest | null {
45+
export function toRequestPayload(
46+
input: unknown,
47+
): ValidatedTaskDecomposeRequest | null {
5048
if (!input || typeof input !== "object") {
5149
return null;
5250
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const DEFAULT_TASK_TIMEZONE = "Asia/Tokyo";
2+
3+
export function normalizeTaskTimezone(
4+
value: string | null | undefined,
5+
): string {
6+
if (!value || value.trim().length === 0) {
7+
return DEFAULT_TASK_TIMEZONE;
8+
}
9+
10+
const candidate = value.trim();
11+
try {
12+
return new Intl.DateTimeFormat("en-US", {
13+
timeZone: candidate,
14+
}).resolvedOptions().timeZone;
15+
} catch {
16+
return DEFAULT_TASK_TIMEZONE;
17+
}
18+
}

0 commit comments

Comments
 (0)