@akiojin/gwt 2.12.1 → 2.13.0
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/cli/ui/components/App.d.ts.map +1 -1
- package/dist/cli/ui/components/App.js +72 -3
- package/dist/cli/ui/components/App.js.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.d.ts +3 -1
- package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.js +154 -32
- package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
- package/dist/cli/ui/hooks/useGitData.d.ts.map +1 -1
- package/dist/cli/ui/hooks/useGitData.js +17 -0
- package/dist/cli/ui/hooks/useGitData.js.map +1 -1
- package/dist/cli/ui/types.d.ts +2 -0
- package/dist/cli/ui/types.d.ts.map +1 -1
- package/dist/cli/ui/utils/branchFormatter.d.ts.map +1 -1
- package/dist/cli/ui/utils/branchFormatter.js +7 -2
- package/dist/cli/ui/utils/branchFormatter.js.map +1 -1
- package/dist/cli/ui/utils/modelOptions.d.ts.map +1 -1
- package/dist/cli/ui/utils/modelOptions.js +7 -0
- package/dist/cli/ui/utils/modelOptions.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/logging/logger.d.ts +24 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +57 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/logging/rotation.d.ts +6 -0
- package/dist/logging/rotation.d.ts.map +1 -0
- package/dist/logging/rotation.js +26 -0
- package/dist/logging/rotation.js.map +1 -0
- package/dist/web/server/index.d.ts.map +1 -1
- package/dist/web/server/index.js +3 -3
- package/dist/web/server/index.js.map +1 -1
- package/dist/web/server/routes/branches.d.ts +2 -2
- package/dist/web/server/routes/branches.d.ts.map +1 -1
- package/dist/web/server/routes/branches.js.map +1 -1
- package/dist/web/server/routes/config.d.ts +2 -2
- package/dist/web/server/routes/config.d.ts.map +1 -1
- package/dist/web/server/routes/config.js.map +1 -1
- package/dist/web/server/routes/index.d.ts +2 -2
- package/dist/web/server/routes/index.d.ts.map +1 -1
- package/dist/web/server/routes/index.js.map +1 -1
- package/dist/web/server/routes/sessions.d.ts +2 -2
- package/dist/web/server/routes/sessions.d.ts.map +1 -1
- package/dist/web/server/routes/sessions.js.map +1 -1
- package/dist/web/server/routes/worktrees.d.ts +2 -2
- package/dist/web/server/routes/worktrees.d.ts.map +1 -1
- package/dist/web/server/routes/worktrees.js.map +1 -1
- package/dist/web/server/types.d.ts +4 -0
- package/dist/web/server/types.d.ts.map +1 -0
- package/dist/web/server/types.js +2 -0
- package/dist/web/server/types.js.map +1 -0
- package/dist/worktree.d.ts +1 -0
- package/dist/worktree.d.ts.map +1 -1
- package/dist/worktree.js.map +1 -1
- package/package.json +3 -2
- package/src/cli/ui/__tests__/components/ModelSelectorScreen.initial.test.tsx +13 -13
- package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +81 -33
- package/src/cli/ui/__tests__/performance/branchList.performance.test.tsx +7 -3
- package/src/cli/ui/components/App.tsx +88 -2
- package/src/cli/ui/components/screens/BranchListScreen.tsx +198 -32
- package/src/cli/ui/hooks/useGitData.ts +20 -0
- package/src/cli/ui/types.ts +3 -0
- package/src/cli/ui/utils/branchFormatter.ts +7 -2
- package/src/cli/ui/utils/modelOptions.test.ts +14 -0
- package/src/cli/ui/utils/modelOptions.ts +7 -0
- package/src/index.ts +7 -0
- package/src/logging/logger.ts +79 -0
- package/src/logging/rotation.ts +25 -0
- package/src/web/server/index.ts +6 -4
- package/src/web/server/routes/branches.ts +2 -2
- package/src/web/server/routes/config.ts +2 -2
- package/src/web/server/routes/index.ts +2 -2
- package/src/web/server/routes/sessions.ts +2 -2
- package/src/web/server/routes/worktrees.ts +2 -2
- package/src/web/server/types.ts +14 -0
- package/src/worktree.ts +1 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import pino, { type LoggerOptions, type Logger } from "pino";
|
|
5
|
+
import { pruneOldLogs } from "./rotation.js";
|
|
6
|
+
|
|
7
|
+
type Category = "cli" | "server" | "worker" | string;
|
|
8
|
+
|
|
9
|
+
export interface LoggerConfig {
|
|
10
|
+
level?: string;
|
|
11
|
+
logDir?: string;
|
|
12
|
+
filename?: string;
|
|
13
|
+
category?: Category;
|
|
14
|
+
base?: Record<string, unknown>;
|
|
15
|
+
keepDays?: number;
|
|
16
|
+
/** For tests or sync writes use pino.destination sync */
|
|
17
|
+
sync?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create a pino logger with unified structure and category field.
|
|
22
|
+
* - Writes to a single file stream (no per-component files)
|
|
23
|
+
* - Adds `category` to each log record
|
|
24
|
+
* - Prunes files older than keepDays at startup
|
|
25
|
+
*/
|
|
26
|
+
export function createLogger(config: LoggerConfig = {}): Logger {
|
|
27
|
+
const level = config.level ?? process.env.LOG_LEVEL ?? "info";
|
|
28
|
+
const cwdBase = path.basename(process.cwd()) || "workspace";
|
|
29
|
+
const defaultLogDir = path.join(os.homedir(), ".gwt", "logs", cwdBase);
|
|
30
|
+
const logDir = config.logDir ?? defaultLogDir;
|
|
31
|
+
const filename = config.filename ?? `${formatDate(new Date())}.jsonl`;
|
|
32
|
+
const category = config.category ?? "default";
|
|
33
|
+
const keepDays = config.keepDays ?? 7;
|
|
34
|
+
|
|
35
|
+
if (!fs.existsSync(logDir)) {
|
|
36
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Startup rotation
|
|
40
|
+
pruneOldLogs(logDir, keepDays);
|
|
41
|
+
|
|
42
|
+
const destination = path.join(logDir, filename);
|
|
43
|
+
|
|
44
|
+
const options: LoggerOptions = {
|
|
45
|
+
level,
|
|
46
|
+
base: {
|
|
47
|
+
category,
|
|
48
|
+
...(config.base ?? {}),
|
|
49
|
+
},
|
|
50
|
+
timestamp: pino.stdTimeFunctions.isoTime,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
if (config.sync) {
|
|
54
|
+
const destinationStream = pino.destination({ dest: destination, sync: true });
|
|
55
|
+
return pino(options, destinationStream);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const transport = pino.transport({
|
|
59
|
+
targets: [
|
|
60
|
+
{
|
|
61
|
+
target: "pino/file",
|
|
62
|
+
options: { destination, mkdir: true, append: true },
|
|
63
|
+
level,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return pino(options, transport);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Convenience logger for quick use (category defaults to "default"). */
|
|
72
|
+
export const logger = createLogger();
|
|
73
|
+
|
|
74
|
+
export function formatDate(date: Date): string {
|
|
75
|
+
const year = date.getFullYear();
|
|
76
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
77
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
78
|
+
return `${year}-${month}-${day}`;
|
|
79
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Delete log files older than `keepDays` from the given directory.
|
|
6
|
+
* This is called at startup to enforce 7-day retention without size limits.
|
|
7
|
+
*/
|
|
8
|
+
export function pruneOldLogs(logDir: string, keepDays = 7): void {
|
|
9
|
+
if (!fs.existsSync(logDir)) return;
|
|
10
|
+
|
|
11
|
+
const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1000;
|
|
12
|
+
|
|
13
|
+
for (const entry of fs.readdirSync(logDir)) {
|
|
14
|
+
const full = path.join(logDir, entry);
|
|
15
|
+
try {
|
|
16
|
+
const stat = fs.statSync(full);
|
|
17
|
+
if (!stat.isFile()) continue;
|
|
18
|
+
if (stat.mtime.getTime() < cutoff) {
|
|
19
|
+
fs.unlinkSync(full);
|
|
20
|
+
}
|
|
21
|
+
} catch {
|
|
22
|
+
// Ignore individual file errors to avoid breaking startup
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package/src/web/server/index.ts
CHANGED
|
@@ -14,6 +14,8 @@ import { PTYManager } from "./pty/manager.js";
|
|
|
14
14
|
import { WebSocketHandler } from "./websocket/handler.js";
|
|
15
15
|
import { registerRoutes } from "./routes/index.js";
|
|
16
16
|
import { importOsEnvIntoSharedConfig } from "./env/importer.js";
|
|
17
|
+
import { createLogger } from "../../logging/logger.js";
|
|
18
|
+
import type { WebFastifyInstance } from "./types.js";
|
|
17
19
|
|
|
18
20
|
const __filename = fileURLToPath(import.meta.url);
|
|
19
21
|
const __dirname = dirname(__filename);
|
|
@@ -22,10 +24,10 @@ const __dirname = dirname(__filename);
|
|
|
22
24
|
* Webサーバーを起動
|
|
23
25
|
*/
|
|
24
26
|
export async function startWebServer(): Promise<void> {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const serverLogger = createLogger({ category: "server" });
|
|
28
|
+
|
|
29
|
+
const fastify: WebFastifyInstance = Fastify({
|
|
30
|
+
loggerInstance: serverLogger,
|
|
29
31
|
});
|
|
30
32
|
|
|
31
33
|
// PTYマネージャーとWebSocketハンドラーを初期化
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* ブランチ関連のREST APIエンドポイント。
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { FastifyInstance } from "fastify";
|
|
8
7
|
import {
|
|
9
8
|
listBranches,
|
|
10
9
|
getBranchByName,
|
|
@@ -16,12 +15,13 @@ import type {
|
|
|
16
15
|
BranchSyncRequest,
|
|
17
16
|
BranchSyncResult,
|
|
18
17
|
} from "../../../types/api.js";
|
|
18
|
+
import type { WebFastifyInstance } from "../types.js";
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* ブランチ関連のルートを登録
|
|
22
22
|
*/
|
|
23
23
|
export async function registerBranchRoutes(
|
|
24
|
-
fastify:
|
|
24
|
+
fastify: WebFastifyInstance,
|
|
25
25
|
): Promise<void> {
|
|
26
26
|
// GET /api/branches - すべてのブランチ一覧を取得
|
|
27
27
|
fastify.get<{ Reply: ApiResponse<Branch[]> }>(
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Config Routes
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { FastifyInstance } from "fastify";
|
|
6
5
|
import { loadToolsConfig, saveToolsConfig } from "../../../config/tools.js";
|
|
7
6
|
import {
|
|
8
7
|
loadEnvHistory,
|
|
@@ -17,6 +16,7 @@ import type {
|
|
|
17
16
|
} from "../../../types/api.js";
|
|
18
17
|
import type { CustomAITool as FileCustomAITool } from "../../../types/tools.js";
|
|
19
18
|
import { getImportedEnvKeys } from "../env/importer.js";
|
|
19
|
+
import type { WebFastifyInstance } from "../types.js";
|
|
20
20
|
|
|
21
21
|
function normalizeEnv(
|
|
22
22
|
env: Record<string, string> | undefined,
|
|
@@ -135,7 +135,7 @@ function diffEnvHistory(
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
export async function registerConfigRoutes(
|
|
138
|
-
fastify:
|
|
138
|
+
fastify: WebFastifyInstance,
|
|
139
139
|
): Promise<void> {
|
|
140
140
|
fastify.get<{ Reply: ApiResponse<ConfigPayload> }>(
|
|
141
141
|
"/api/config",
|
|
@@ -5,19 +5,19 @@
|
|
|
5
5
|
* 仕様: specs/SPEC-d5e56259/contracts/rest-api.yaml
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { FastifyInstance } from "fastify";
|
|
9
8
|
import type { PTYManager } from "../pty/manager.js";
|
|
10
9
|
import { registerBranchRoutes } from "./branches.js";
|
|
11
10
|
import { registerWorktreeRoutes } from "./worktrees.js";
|
|
12
11
|
import { registerSessionRoutes } from "./sessions.js";
|
|
13
12
|
import { registerConfigRoutes } from "./config.js";
|
|
14
13
|
import type { HealthResponse } from "../../../types/api.js";
|
|
14
|
+
import type { WebFastifyInstance } from "../types.js";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* すべてのルートを登録
|
|
18
18
|
*/
|
|
19
19
|
export async function registerRoutes(
|
|
20
|
-
fastify:
|
|
20
|
+
fastify: WebFastifyInstance,
|
|
21
21
|
ptyManager: PTYManager,
|
|
22
22
|
): Promise<void> {
|
|
23
23
|
// ヘルスチェック
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* AI Toolセッション関連のREST APIエンドポイント。
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { FastifyInstance } from "fastify";
|
|
8
7
|
import type { PTYManager } from "../pty/manager.js";
|
|
9
8
|
import type {
|
|
10
9
|
ApiResponse,
|
|
@@ -13,12 +12,13 @@ import type {
|
|
|
13
12
|
} from "../../../types/api.js";
|
|
14
13
|
import { saveSession } from "../../../config/index.js";
|
|
15
14
|
import { execa } from "execa";
|
|
15
|
+
import type { WebFastifyInstance } from "../types.js";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* セッション関連のルートを登録
|
|
19
19
|
*/
|
|
20
20
|
export async function registerSessionRoutes(
|
|
21
|
-
fastify:
|
|
21
|
+
fastify: WebFastifyInstance,
|
|
22
22
|
ptyManager: PTYManager,
|
|
23
23
|
): Promise<void> {
|
|
24
24
|
// GET /api/sessions - すべてのセッション一覧を取得
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* Worktree関連のREST APIエンドポイント。
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { FastifyInstance } from "fastify";
|
|
8
7
|
import {
|
|
9
8
|
listWorktrees,
|
|
10
9
|
getWorktreeByPath,
|
|
@@ -16,12 +15,13 @@ import type {
|
|
|
16
15
|
Worktree,
|
|
17
16
|
CreateWorktreeRequest,
|
|
18
17
|
} from "../../../types/api.js";
|
|
18
|
+
import type { WebFastifyInstance } from "../types.js";
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Worktree関連のルートを登録
|
|
22
22
|
*/
|
|
23
23
|
export async function registerWorktreeRoutes(
|
|
24
|
-
fastify:
|
|
24
|
+
fastify: WebFastifyInstance,
|
|
25
25
|
): Promise<void> {
|
|
26
26
|
// GET /api/worktrees - すべてのWorktree一覧を取得
|
|
27
27
|
fastify.get<{ Reply: ApiResponse<Worktree[]> }>(
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
FastifyInstance,
|
|
3
|
+
RawReplyDefaultExpression,
|
|
4
|
+
RawRequestDefaultExpression,
|
|
5
|
+
RawServerDefault,
|
|
6
|
+
} from "fastify";
|
|
7
|
+
import type { Logger } from "pino";
|
|
8
|
+
|
|
9
|
+
export type WebFastifyInstance = FastifyInstance<
|
|
10
|
+
RawServerDefault,
|
|
11
|
+
RawRequestDefaultExpression<RawServerDefault>,
|
|
12
|
+
RawReplyDefaultExpression<RawServerDefault>,
|
|
13
|
+
Logger
|
|
14
|
+
>;
|