mirror of
https://github.com/aljazceru/claude-code-viewer.git
synced 2025-12-18 22:04:19 +01:00
refactor: move directories
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { homedir } from "node:os";
|
||||
import { resolve } from "node:path";
|
||||
import { encodeProjectId } from "../src/server/service/project/id";
|
||||
import { encodeProjectId } from "../src/server/core/project/functions/id";
|
||||
|
||||
// biome-ignore lint/complexity/useLiteralKeys: env var
|
||||
export const globalClaudeDirectoryPath = process.env["GLOBAL_CLAUDE_DIR"]
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { NodeContext } from "@effect/platform-node";
|
||||
import { Effect } from "effect";
|
||||
import { handle } from "hono/vercel";
|
||||
import { ClaudeCodeLifeCycleService } from "../../../server/core/claude-code/services/ClaudeCodeLifeCycleService";
|
||||
import { ClaudeCodePermissionService } from "../../../server/core/claude-code/services/ClaudeCodePermissionService";
|
||||
import { ClaudeCodeSessionProcessService } from "../../../server/core/claude-code/services/ClaudeCodeSessionProcessService";
|
||||
import { EventBus } from "../../../server/core/events/services/EventBus";
|
||||
import { FileWatcherService } from "../../../server/core/events/services/fileWatcher";
|
||||
import { ProjectRepository } from "../../../server/core/project/infrastructure/ProjectRepository";
|
||||
import { ProjectMetaService } from "../../../server/core/project/services/ProjectMetaService";
|
||||
import { SessionRepository } from "../../../server/core/session/infrastructure/SessionRepository";
|
||||
import { VirtualConversationDatabase } from "../../../server/core/session/infrastructure/VirtualConversationDatabase";
|
||||
import { SessionMetaService } from "../../../server/core/session/services/SessionMetaService";
|
||||
import { honoApp } from "../../../server/hono/app";
|
||||
import { InitializeService } from "../../../server/hono/initialize";
|
||||
import { routes } from "../../../server/hono/route";
|
||||
import { ClaudeCodeLifeCycleService } from "../../../server/service/claude-code/ClaudeCodeLifeCycleService";
|
||||
import { ClaudeCodePermissionService } from "../../../server/service/claude-code/ClaudeCodePermissionService";
|
||||
import { ClaudeCodeSessionProcessService } from "../../../server/service/claude-code/ClaudeCodeSessionProcessService";
|
||||
import { EventBus } from "../../../server/service/events/EventBus";
|
||||
import { FileWatcherService } from "../../../server/service/events/fileWatcher";
|
||||
import { ProjectMetaService } from "../../../server/service/project/ProjectMetaService";
|
||||
import { ProjectRepository } from "../../../server/service/project/ProjectRepository";
|
||||
import { SessionMetaService } from "../../../server/service/session/SessionMetaService";
|
||||
import { SessionRepository } from "../../../server/service/session/SessionRepository";
|
||||
import { VirtualConversationDatabase } from "../../../server/service/session/VirtualConversationDatabase";
|
||||
|
||||
const program = routes(honoApp);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
import { useCallback } from "react";
|
||||
import { honoClient } from "../../lib/api/client";
|
||||
import { configQuery } from "../../lib/api/queries";
|
||||
import type { Config } from "../../server/config/config";
|
||||
import type { Config } from "../../server/lib/config/config";
|
||||
|
||||
export const useConfig = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ParsedCommand } from "../../../../server/service/parseCommandXml";
|
||||
import type { ParsedCommand } from "../../../../server/core/claude-code/functions/parseCommandXml";
|
||||
|
||||
export const firstCommandToTitle = (firstCommand: ParsedCommand) => {
|
||||
switch (firstCommand.kind) {
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from "@/components/ui/collapsible";
|
||||
import type { Conversation } from "@/lib/conversation-schema";
|
||||
import type { ToolResultContent } from "@/lib/conversation-schema/content/ToolResultContentSchema";
|
||||
import type { ErrorJsonl } from "../../../../../../../server/service/types";
|
||||
import type { ErrorJsonl } from "../../../../../../../server/core/types";
|
||||
import { useSidechain } from "../../hooks/useSidechain";
|
||||
import { ConversationItem } from "./ConversationItem";
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FC } from "react";
|
||||
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { parseCommandXml } from "../../../../../../../server/service/parseCommandXml";
|
||||
import { parseCommandXml } from "../../../../../../../server/core/claude-code/functions/parseCommandXml";
|
||||
import { MarkdownContent } from "../../../../../../components/MarkdownContent";
|
||||
|
||||
export const UserTextContent: FC<{ text: string; id?: string }> = ({
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { FC } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { Session } from "../../../../../../../server/service/types";
|
||||
import type { Session } from "../../../../../../../server/core/types";
|
||||
import { NewChatModal } from "../../../../components/newChat/NewChatModal";
|
||||
import { firstCommandToTitle } from "../../../../services/firstCommandToTitle";
|
||||
import { sessionProcessesAtom } from "../../store/sessionProcessesAtom";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { DirectoryListingResult } from "../../server/service/directory-browser/getDirectoryListing";
|
||||
import type { FileCompletionResult } from "../../server/service/file-completion/getFileCompletion";
|
||||
import type { DirectoryListingResult } from "../../server/core/directory-browser/functions/getDirectoryListing";
|
||||
import type { FileCompletionResult } from "../../server/core/file-completion/functions/getFileCompletion";
|
||||
import { honoClient } from "./client";
|
||||
|
||||
export const projectListQuery = {
|
||||
|
||||
@@ -7,7 +7,7 @@ describe("computeClaudeProjectFilePath", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
vi.doMock("../../lib/env", () => ({
|
||||
vi.doMock("../../../lib/env", () => ({
|
||||
env: {
|
||||
get: (key: string) => {
|
||||
if (key === "GLOBAL_CLAUDE_DIR") {
|
||||
@@ -1,5 +1,5 @@
|
||||
import path from "node:path";
|
||||
import { claudeProjectsDirPath } from "../paths";
|
||||
import { claudeProjectsDirPath } from "../../../lib/config/paths";
|
||||
|
||||
export function computeClaudeProjectFilePath(projectPath: string): string {
|
||||
return path.join(
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { SDKMessage, SDKUserMessage } from "@anthropic-ai/claude-code";
|
||||
import { controllablePromise } from "../../../lib/controllablePromise";
|
||||
import { controllablePromise } from "../../../../lib/controllablePromise";
|
||||
|
||||
export type OnMessage = (message: SDKMessage) => void | Promise<void>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { ErrorJsonl } from "../../types";
|
||||
import { parseJsonl } from "./parseJsonl";
|
||||
import type { ErrorJsonl } from "./types";
|
||||
|
||||
describe("parseJsonl", () => {
|
||||
describe("正常系: 有効なJSONLをパースできる", () => {
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ConversationSchema } from "../../lib/conversation-schema";
|
||||
import type { ErrorJsonl } from "./types";
|
||||
import { ConversationSchema } from "../../../../lib/conversation-schema";
|
||||
import type { ErrorJsonl } from "../../types";
|
||||
|
||||
export const parseJsonl = (content: string) => {
|
||||
const lines = content
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Effect } from "effect";
|
||||
import type { UserEntry } from "../../../../lib/conversation-schema/entry/UserEntrySchema";
|
||||
import * as ClaudeCode from "../ClaudeCode";
|
||||
import type { InitMessageContext } from "../createMessageGenerator";
|
||||
import type { InitMessageContext } from "../types";
|
||||
import * as ClaudeCode from "./ClaudeCode";
|
||||
import type * as CCTask from "./ClaudeCodeTask";
|
||||
import * as ClaudeCodeVersion from "./ClaudeCodeVersion";
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { query as originalQuery } from "@anthropic-ai/claude-code";
|
||||
import { Command, Path } from "@effect/platform";
|
||||
import { Effect } from "effect";
|
||||
import { env } from "../../lib/env";
|
||||
import * as ClaudeCodeVersion from "./models/ClaudeCodeVersion";
|
||||
import { env } from "../../../lib/env";
|
||||
import * as ClaudeCodeVersion from "./ClaudeCodeVersion";
|
||||
|
||||
type CCQuery = typeof originalQuery;
|
||||
type CCQueryPrompt = Parameters<CCQuery>[0]["prompt"];
|
||||
@@ -3,18 +3,18 @@ import type { FileSystem, Path } from "@effect/platform";
|
||||
import type { CommandExecutor } from "@effect/platform/CommandExecutor";
|
||||
import { Context, Effect, Layer, Runtime } from "effect";
|
||||
import { ulid } from "ulid";
|
||||
import { controllablePromise } from "../../../lib/controllablePromise";
|
||||
import type { Config } from "../../config/config";
|
||||
import type { InferEffect } from "../../lib/effect/types";
|
||||
import { EventBus } from "../events/EventBus";
|
||||
import type { SessionMetaService } from "../session/SessionMetaService";
|
||||
import { SessionRepository } from "../session/SessionRepository";
|
||||
import { VirtualConversationDatabase } from "../session/VirtualConversationDatabase";
|
||||
import * as ClaudeCode from "./ClaudeCode";
|
||||
import { controllablePromise } from "../../../../lib/controllablePromise";
|
||||
import type { Config } from "../../../lib/config/config";
|
||||
import type { InferEffect } from "../../../lib/effect/types";
|
||||
import { EventBus } from "../../events/services/EventBus";
|
||||
import { SessionRepository } from "../../session/infrastructure/SessionRepository";
|
||||
import { VirtualConversationDatabase } from "../../session/infrastructure/VirtualConversationDatabase";
|
||||
import type { SessionMetaService } from "../../session/services/SessionMetaService";
|
||||
import { createMessageGenerator } from "../functions/createMessageGenerator";
|
||||
import * as CCSessionProcess from "../models/CCSessionProcess";
|
||||
import * as ClaudeCode from "../models/ClaudeCode";
|
||||
import { ClaudeCodePermissionService } from "./ClaudeCodePermissionService";
|
||||
import { ClaudeCodeSessionProcessService } from "./ClaudeCodeSessionProcessService";
|
||||
import { createMessageGenerator } from "./MessageGenerator";
|
||||
import * as CCSessionProcess from "./models/CCSessionProcess";
|
||||
|
||||
export type MessageGenerator = () => AsyncGenerator<
|
||||
SDKUserMessage,
|
||||
@@ -4,11 +4,11 @@ import { ulid } from "ulid";
|
||||
import type {
|
||||
PermissionRequest,
|
||||
PermissionResponse,
|
||||
} from "../../../types/permissions";
|
||||
import type { Config } from "../../config/config";
|
||||
import type { InferEffect } from "../../lib/effect/types";
|
||||
import { EventBus } from "../events/EventBus";
|
||||
import * as ClaudeCode from "./ClaudeCode";
|
||||
} from "../../../../types/permissions";
|
||||
import type { Config } from "../../../lib/config/config";
|
||||
import type { InferEffect } from "../../../lib/effect/types";
|
||||
import { EventBus } from "../../events/services/EventBus";
|
||||
import * as ClaudeCode from "../models/ClaudeCode";
|
||||
|
||||
const LayerImpl = Effect.gen(function* () {
|
||||
const pendingPermissionRequestsRef = yield* Ref.make<
|
||||
@@ -4,12 +4,12 @@ import type {
|
||||
} from "@anthropic-ai/claude-code";
|
||||
import { Effect, Layer } from "effect";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { EventBus } from "../events/EventBus";
|
||||
import type { InternalEventDeclaration } from "../events/InternalEventDeclaration";
|
||||
import { EventBus } from "../../events/services/EventBus";
|
||||
import type { InternalEventDeclaration } from "../../events/types/InternalEventDeclaration";
|
||||
import type * as CCSessionProcess from "../models/CCSessionProcess";
|
||||
import type * as CCTask from "../models/ClaudeCodeTask";
|
||||
import type { InitMessageContext } from "../types";
|
||||
import { ClaudeCodeSessionProcessService } from "./ClaudeCodeSessionProcessService";
|
||||
import type { InitMessageContext } from "./createMessageGenerator";
|
||||
import type * as CCSessionProcess from "./models/CCSessionProcess";
|
||||
import type * as CCTask from "./models/ClaudeCodeTask";
|
||||
|
||||
// Helper function to create mock session process definition
|
||||
const createMockSessionProcessDef = (
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { SDKResultMessage } from "@anthropic-ai/claude-code";
|
||||
import { Context, Data, Effect, Layer, Ref } from "effect";
|
||||
import type { InferEffect } from "../../lib/effect/types";
|
||||
import { EventBus } from "../events/EventBus";
|
||||
import type { InitMessageContext } from "./createMessageGenerator";
|
||||
import * as CCSessionProcess from "./models/CCSessionProcess";
|
||||
import type * as CCTask from "./models/ClaudeCodeTask";
|
||||
import type { InferEffect } from "../../../lib/effect/types";
|
||||
import { EventBus } from "../../events/services/EventBus";
|
||||
import * as CCSessionProcess from "../models/CCSessionProcess";
|
||||
import type * as CCTask from "../models/ClaudeCodeTask";
|
||||
import type { InitMessageContext } from "../types";
|
||||
|
||||
class SessionProcessNotFoundError extends Data.TaggedError(
|
||||
"SessionProcessNotFoundError",
|
||||
5
src/server/core/claude-code/types.ts
Normal file
5
src/server/core/claude-code/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import type { SDKSystemMessage } from "@anthropic-ai/claude-code";
|
||||
|
||||
export type InitMessageContext = {
|
||||
initMessage: SDKSystemMessage;
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Effect } from "effect";
|
||||
import type { SSEStreamingApi } from "hono/streaming";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { PermissionRequest } from "../../../types/permissions";
|
||||
import type { PermissionRequest } from "../../../../types/permissions";
|
||||
import { TypeSafeSSE } from "./typeSafeSSE";
|
||||
|
||||
describe("typeSafeSSE", () => {
|
||||
@@ -153,7 +153,7 @@ describe("typeSafeSSE", () => {
|
||||
const program = Effect.gen(function* () {
|
||||
const typeSafeSSE = yield* TypeSafeSSE;
|
||||
|
||||
yield* typeSafeSSE.writeSSE("permission_requested", {
|
||||
yield* typeSafeSSE.writeSSE("permissionRequested", {
|
||||
permissionRequest: mockPermissionRequest,
|
||||
});
|
||||
|
||||
@@ -170,10 +170,10 @@ describe("typeSafeSSE", () => {
|
||||
if (!item) {
|
||||
throw new Error("item is undefined");
|
||||
}
|
||||
expect(item.event).toBe("permission_requested");
|
||||
expect(item.event).toBe("permissionRequested");
|
||||
|
||||
const data = JSON.parse(item.data);
|
||||
expect(data.kind).toBe("permission_requested");
|
||||
expect(data.kind).toBe("permissionRequested");
|
||||
expect(data.permissionRequest.id).toBe("permission-1");
|
||||
expect(data.timestamp).toBeDefined();
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Context, Effect, Layer } from "effect";
|
||||
import type { SSEStreamingApi } from "hono/streaming";
|
||||
import { ulid } from "ulid";
|
||||
import type { SSEEventDeclaration } from "../../../types/sse";
|
||||
import type { SSEEventDeclaration } from "../../../../types/sse";
|
||||
|
||||
interface TypeSafeSSEService {
|
||||
readonly writeSSE: <EventName extends keyof SSEEventDeclaration>(
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Effect } from "effect";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { PermissionRequest } from "../../../types/permissions";
|
||||
import type { PublicSessionProcess } from "../../../types/session-process";
|
||||
import type { CCSessionProcessState } from "../claude-code/models/CCSessionProcess";
|
||||
import type { PermissionRequest } from "../../../../types/permissions";
|
||||
import type { PublicSessionProcess } from "../../../../types/session-process";
|
||||
import type { CCSessionProcessState } from "../../claude-code/models/CCSessionProcess";
|
||||
import type { InternalEventDeclaration } from "../types/InternalEventDeclaration";
|
||||
import { EventBus } from "./EventBus";
|
||||
import type { InternalEventDeclaration } from "./InternalEventDeclaration";
|
||||
|
||||
describe("EventBus", () => {
|
||||
describe("basic event processing", () => {
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Context, Effect, Layer } from "effect";
|
||||
import type { InternalEventDeclaration } from "./InternalEventDeclaration";
|
||||
import type { InternalEventDeclaration } from "../types/InternalEventDeclaration";
|
||||
|
||||
type Listener<T> = (data: T) => void | Promise<void>;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Effect } from "effect";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { InternalEventDeclaration } from "../types/InternalEventDeclaration";
|
||||
import { EventBus } from "./EventBus";
|
||||
import { FileWatcherService } from "./fileWatcher";
|
||||
import type { InternalEventDeclaration } from "./InternalEventDeclaration";
|
||||
|
||||
describe("FileWatcherService", () => {
|
||||
describe("startWatching", () => {
|
||||
@@ -2,8 +2,8 @@ import { type FSWatcher, watch } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { Context, Effect, Layer, Ref } from "effect";
|
||||
import z from "zod";
|
||||
import { claudeProjectsDirPath } from "../paths";
|
||||
import { encodeProjectIdFromSessionFilePath } from "../project/id";
|
||||
import { claudeProjectsDirPath } from "../../../lib/config/paths";
|
||||
import { encodeProjectIdFromSessionFilePath } from "../../project/functions/id";
|
||||
import { EventBus } from "./EventBus";
|
||||
|
||||
const fileRegExp = /(?<projectId>.*?)\/(?<sessionId>.*?)\.jsonl/;
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { PermissionRequest } from "../../../types/permissions";
|
||||
import type { PublicSessionProcess } from "../../../types/session-process";
|
||||
import type * as CCSessionProcess from "../claude-code/models/CCSessionProcess";
|
||||
import type { PermissionRequest } from "../../../../types/permissions";
|
||||
import type { PublicSessionProcess } from "../../../../types/session-process";
|
||||
import type * as CCSessionProcess from "../../claude-code/models/CCSessionProcess";
|
||||
|
||||
export type InternalEventDeclaration = {
|
||||
// biome-ignore lint/complexity/noBannedTypes: correct type
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { GitBranch, GitResult } from "./types";
|
||||
import { executeGitCommand, parseLines } from "./utils";
|
||||
import { executeGitCommand, parseLines } from "../functions/utils";
|
||||
import type { GitBranch, GitResult } from "../types";
|
||||
|
||||
/**
|
||||
* Get all branches (local and remote) in the repository
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { GitCommit, GitResult } from "./types";
|
||||
import { executeGitCommand, parseLines } from "./utils";
|
||||
import { executeGitCommand, parseLines } from "../functions/utils";
|
||||
import type { GitCommit, GitResult } from "../types";
|
||||
|
||||
/**
|
||||
* Get the last 20 commits from the current branch
|
||||
@@ -4,6 +4,11 @@ import parseGitDiff, {
|
||||
type AnyChunk,
|
||||
type AnyFileChange,
|
||||
} from "parse-git-diff";
|
||||
import {
|
||||
executeGitCommand,
|
||||
parseLines,
|
||||
stripAnsiColors,
|
||||
} from "../functions/utils";
|
||||
import type {
|
||||
GitComparisonResult,
|
||||
GitDiff,
|
||||
@@ -11,8 +16,7 @@ import type {
|
||||
GitDiffHunk,
|
||||
GitDiffLine,
|
||||
GitResult,
|
||||
} from "./types";
|
||||
import { executeGitCommand, parseLines, stripAnsiColors } from "./utils";
|
||||
} from "../types";
|
||||
|
||||
/**
|
||||
* Convert parse-git-diff file change to GitDiffFile
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { GitDiffFile, GitResult, GitStatus } from "./types";
|
||||
import {
|
||||
executeGitCommand,
|
||||
getFileStatus,
|
||||
parseLines,
|
||||
parseStatusLine,
|
||||
} from "./utils";
|
||||
} from "../functions/utils";
|
||||
import type { GitDiffFile, GitResult, GitStatus } from "../types";
|
||||
|
||||
/**
|
||||
* Get git status information including staged, unstaged, and untracked files
|
||||
@@ -3,7 +3,7 @@ import { existsSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
import type { GitError, GitResult } from "./types";
|
||||
import type { GitError, GitResult } from "../types";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { execSync } from "node:child_process";
|
||||
import { decodeProjectId } from "../project/id";
|
||||
import { decodeProjectId } from "../../project/functions/id";
|
||||
|
||||
export interface McpServer {
|
||||
name: string;
|
||||
@@ -1,9 +1,9 @@
|
||||
import { FileSystem, Path } from "@effect/platform";
|
||||
import { SystemError } from "@effect/platform/Error";
|
||||
import { Effect, Layer, Option } from "effect";
|
||||
import { PersistentService } from "../../lib/storage/FileCacheStorage/PersistantService";
|
||||
import type { ProjectMeta } from "../types";
|
||||
import { ProjectMetaService } from "./ProjectMetaService";
|
||||
import { PersistentService } from "../../../lib/storage/FileCacheStorage/PersistentService";
|
||||
import type { ProjectMeta } from "../../types";
|
||||
import { ProjectMetaService } from "../services/ProjectMetaService";
|
||||
import { ProjectRepository } from "./ProjectRepository";
|
||||
|
||||
/**
|
||||
@@ -1,11 +1,11 @@
|
||||
import { resolve } from "node:path";
|
||||
import { FileSystem } from "@effect/platform";
|
||||
import { Context, Effect, Layer, Option } from "effect";
|
||||
import type { InferEffect } from "../../lib/effect/types";
|
||||
import { claudeProjectsDirPath } from "../paths";
|
||||
import type { Project } from "../types";
|
||||
import { decodeProjectId, encodeProjectId } from "./id";
|
||||
import { ProjectMetaService } from "./ProjectMetaService";
|
||||
import { claudeProjectsDirPath } from "../../../lib/config/paths";
|
||||
import type { InferEffect } from "../../../lib/effect/types";
|
||||
import type { Project } from "../../types";
|
||||
import { decodeProjectId, encodeProjectId } from "../functions/id";
|
||||
import { ProjectMetaService } from "../services/ProjectMetaService";
|
||||
|
||||
const LayerImpl = Effect.gen(function* () {
|
||||
const fs = yield* FileSystem.FileSystem;
|
||||
7
src/server/core/project/schema.ts
Normal file
7
src/server/core/project/schema.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const projectMetaSchema = z.object({
|
||||
projectName: z.string().nullable(),
|
||||
projectPath: z.string().nullable(),
|
||||
sessionCount: z.number(),
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FileSystem, Path } from "@effect/platform";
|
||||
import { Effect, Layer, Option } from "effect";
|
||||
import { PersistentService } from "../../lib/storage/FileCacheStorage/PersistantService";
|
||||
import { ProjectMetaService } from "./ProjectMetaService";
|
||||
import { PersistentService } from "../../../lib/storage/FileCacheStorage/PersistentService";
|
||||
import { ProjectMetaService } from "../services/ProjectMetaService";
|
||||
|
||||
/**
|
||||
* Helper function to create a FileSystem mock layer
|
||||
@@ -5,11 +5,11 @@ import { z } from "zod";
|
||||
import {
|
||||
FileCacheStorage,
|
||||
makeFileCacheStorageLayer,
|
||||
} from "../../lib/storage/FileCacheStorage";
|
||||
import { PersistentService } from "../../lib/storage/FileCacheStorage/PersistantService";
|
||||
import { parseJsonl } from "../parseJsonl";
|
||||
import type { ProjectMeta } from "../types";
|
||||
import { decodeProjectId } from "./id";
|
||||
} from "../../../lib/storage/FileCacheStorage";
|
||||
import { PersistentService } from "../../../lib/storage/FileCacheStorage/PersistentService";
|
||||
import { parseJsonl } from "../../claude-code/functions/parseJsonl";
|
||||
import type { ProjectMeta } from "../../types";
|
||||
import { decodeProjectId } from "../functions/id";
|
||||
|
||||
const ProjectPathSchema = z.string().nullable();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { basename, extname, resolve } from "node:path";
|
||||
import { decodeProjectId } from "../project/id";
|
||||
import { decodeProjectId } from "../../project/functions/id";
|
||||
|
||||
export const encodeSessionId = (jsonlFilePath: string) => {
|
||||
return basename(jsonlFilePath, extname(jsonlFilePath));
|
||||
@@ -1,13 +1,13 @@
|
||||
import { FileSystem, Path } from "@effect/platform";
|
||||
import { SystemError } from "@effect/platform/Error";
|
||||
import { Effect, Layer, Option } from "effect";
|
||||
import type { Conversation } from "../../../lib/conversation-schema";
|
||||
import { PersistentService } from "../../lib/storage/FileCacheStorage/PersistantService";
|
||||
import { decodeProjectId } from "../project/id";
|
||||
import type { ErrorJsonl, SessionDetail, SessionMeta } from "../types";
|
||||
import { SessionMetaService } from "./SessionMetaService";
|
||||
import { SessionRepository } from "./SessionRepository";
|
||||
import { VirtualConversationDatabase } from "./VirtualConversationDatabase";
|
||||
import type { Conversation } from "../../../../lib/conversation-schema";
|
||||
import { PersistentService } from "../../../lib/storage/FileCacheStorage/PersistentService";
|
||||
import { decodeProjectId } from "../../project/functions/id";
|
||||
import type { ErrorJsonl, SessionDetail, SessionMeta } from "../../types";
|
||||
import { SessionRepository } from "../infrastructure/SessionRepository";
|
||||
import { VirtualConversationDatabase } from "../infrastructure/VirtualConversationDatabase";
|
||||
import { SessionMetaService } from "../services/SessionMetaService";
|
||||
|
||||
/**
|
||||
* Helper function to create a FileSystem mock layer
|
||||
@@ -1,13 +1,13 @@
|
||||
import { resolve } from "node:path";
|
||||
import { FileSystem } from "@effect/platform";
|
||||
import { Context, Effect, Layer, Option } from "effect";
|
||||
import { parseCommandXml } from "../parseCommandXml";
|
||||
import { parseJsonl } from "../parseJsonl";
|
||||
import { decodeProjectId } from "../project/id";
|
||||
import type { Session, SessionDetail } from "../types";
|
||||
import { decodeSessionId, encodeSessionId } from "./id";
|
||||
import { SessionMetaService } from "./SessionMetaService";
|
||||
import { VirtualConversationDatabase } from "./VirtualConversationDatabase";
|
||||
import { parseCommandXml } from "../../claude-code/functions/parseCommandXml";
|
||||
import { parseJsonl } from "../../claude-code/functions/parseJsonl";
|
||||
import { decodeProjectId } from "../../project/functions/id";
|
||||
import type { Session, SessionDetail } from "../../types";
|
||||
import { decodeSessionId, encodeSessionId } from "../functions/id";
|
||||
import { VirtualConversationDatabase } from "../infrastructure/VirtualConversationDatabase";
|
||||
import { SessionMetaService } from "../services/SessionMetaService";
|
||||
|
||||
const getSession = (projectId: string, sessionId: string) =>
|
||||
Effect.gen(function* () {
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Effect } from "effect";
|
||||
import type { Conversation } from "../../../lib/conversation-schema";
|
||||
import type { ErrorJsonl } from "../types";
|
||||
import type { Conversation } from "../../../../lib/conversation-schema";
|
||||
import type { ErrorJsonl } from "../../types";
|
||||
import { VirtualConversationDatabase } from "./VirtualConversationDatabase";
|
||||
|
||||
describe("VirtualConversationDatabase", () => {
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Context, Effect, Layer, Ref } from "effect";
|
||||
import type { Conversation } from "../../../lib/conversation-schema";
|
||||
import type { ErrorJsonl } from "../types";
|
||||
import type { Conversation } from "../../../../lib/conversation-schema";
|
||||
import type { ErrorJsonl } from "../../types";
|
||||
|
||||
/**
|
||||
* For interactively experience, handle sessions not already persisted to the filesystem.
|
||||
7
src/server/core/session/schema.ts
Normal file
7
src/server/core/session/schema.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { z } from "zod";
|
||||
import { parsedCommandSchema } from "../claude-code/functions/parseCommandXml";
|
||||
|
||||
export const sessionMetaSchema = z.object({
|
||||
messageCount: z.number(),
|
||||
firstCommand: parsedCommandSchema.nullable(),
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FileSystem, Path } from "@effect/platform";
|
||||
import { Effect, Layer } from "effect";
|
||||
import { PersistentService } from "../../lib/storage/FileCacheStorage/PersistantService";
|
||||
import { SessionMetaService } from "./SessionMetaService";
|
||||
import { PersistentService } from "../../../lib/storage/FileCacheStorage/PersistentService";
|
||||
import { SessionMetaService } from "../services/SessionMetaService";
|
||||
|
||||
/**
|
||||
* Helper function to create a FileSystem mock layer
|
||||
@@ -3,16 +3,16 @@ import { Context, Effect, Layer, Ref } from "effect";
|
||||
import {
|
||||
FileCacheStorage,
|
||||
makeFileCacheStorageLayer,
|
||||
} from "../../lib/storage/FileCacheStorage";
|
||||
import { PersistentService } from "../../lib/storage/FileCacheStorage/PersistantService";
|
||||
} from "../../../lib/storage/FileCacheStorage";
|
||||
import { PersistentService } from "../../../lib/storage/FileCacheStorage/PersistentService";
|
||||
import {
|
||||
type ParsedCommand,
|
||||
parseCommandXml,
|
||||
parsedCommandSchema,
|
||||
} from "../parseCommandXml";
|
||||
import { parseJsonl } from "../parseJsonl";
|
||||
import type { SessionMeta } from "../types";
|
||||
import { decodeSessionId } from "./id";
|
||||
} from "../../claude-code/functions/parseCommandXml";
|
||||
import { parseJsonl } from "../../claude-code/functions/parseJsonl";
|
||||
import type { SessionMeta } from "../../types";
|
||||
import { decodeSessionId } from "../functions/id";
|
||||
|
||||
const ignoreCommands = [
|
||||
"/clear",
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { z } from "zod";
|
||||
import type { Conversation } from "../../lib/conversation-schema";
|
||||
import type { projectMetaSchema, sessionMetaSchema } from "./schema";
|
||||
import type { projectMetaSchema } from "./project/schema";
|
||||
import type { sessionMetaSchema } from "./session/schema";
|
||||
|
||||
export type Project = {
|
||||
id: string;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Hono } from "hono";
|
||||
import type { Config } from "../config/config";
|
||||
import type { Config } from "../lib/config/config";
|
||||
|
||||
export type HonoContext = {
|
||||
Variables: {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Effect, Layer, Ref } from "effect";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { EventBus } from "../service/events/EventBus";
|
||||
import { FileWatcherService } from "../service/events/fileWatcher";
|
||||
import type { InternalEventDeclaration } from "../service/events/InternalEventDeclaration";
|
||||
import { ProjectMetaService } from "../service/project/ProjectMetaService";
|
||||
import { ProjectRepository } from "../service/project/ProjectRepository";
|
||||
import { SessionMetaService } from "../service/session/SessionMetaService";
|
||||
import { SessionRepository } from "../service/session/SessionRepository";
|
||||
import { VirtualConversationDatabase } from "../service/session/VirtualConversationDatabase";
|
||||
import { EventBus } from "../core/events/services/EventBus";
|
||||
import { FileWatcherService } from "../core/events/services/fileWatcher";
|
||||
import type { InternalEventDeclaration } from "../core/events/types/InternalEventDeclaration";
|
||||
import { ProjectRepository } from "../core/project/infrastructure/ProjectRepository";
|
||||
import { ProjectMetaService } from "../core/project/services/ProjectMetaService";
|
||||
import { SessionRepository } from "../core/session/infrastructure/SessionRepository";
|
||||
import { VirtualConversationDatabase } from "../core/session/infrastructure/VirtualConversationDatabase";
|
||||
import { SessionMetaService } from "../core/session/services/SessionMetaService";
|
||||
import { InitializeService } from "./initialize";
|
||||
|
||||
describe("InitializeService", () => {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Context, Effect, Layer, Ref, Schedule } from "effect";
|
||||
import { EventBus } from "../service/events/EventBus";
|
||||
import { FileWatcherService } from "../service/events/fileWatcher";
|
||||
import type { InternalEventDeclaration } from "../service/events/InternalEventDeclaration";
|
||||
import { ProjectMetaService } from "../service/project/ProjectMetaService";
|
||||
import { ProjectRepository } from "../service/project/ProjectRepository";
|
||||
import { SessionMetaService } from "../service/session/SessionMetaService";
|
||||
import { SessionRepository } from "../service/session/SessionRepository";
|
||||
import { VirtualConversationDatabase } from "../service/session/VirtualConversationDatabase";
|
||||
import { EventBus } from "../core/events/services/EventBus";
|
||||
import { FileWatcherService } from "../core/events/services/fileWatcher";
|
||||
import type { InternalEventDeclaration } from "../core/events/types/InternalEventDeclaration";
|
||||
import { ProjectRepository } from "../core/project/infrastructure/ProjectRepository";
|
||||
import { ProjectMetaService } from "../core/project/services/ProjectMetaService";
|
||||
import { SessionRepository } from "../core/session/infrastructure/SessionRepository";
|
||||
import { VirtualConversationDatabase } from "../core/session/infrastructure/VirtualConversationDatabase";
|
||||
import { SessionMetaService } from "../core/session/services/SessionMetaService";
|
||||
|
||||
interface InitializeServiceInterface {
|
||||
readonly startInitialization: () => Effect.Effect<void>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getCookie, setCookie } from "hono/cookie";
|
||||
import { createMiddleware } from "hono/factory";
|
||||
import { configSchema } from "../../config/config";
|
||||
import { configSchema } from "../../lib/config/config";
|
||||
import type { HonoContext } from "../app";
|
||||
|
||||
export const configMiddleware = createMiddleware<HonoContext>(
|
||||
|
||||
@@ -9,28 +9,28 @@ import { streamSSE } from "hono/streaming";
|
||||
import prexit from "prexit";
|
||||
import { z } from "zod";
|
||||
import type { PublicSessionProcess } from "../../types/session-process";
|
||||
import { configSchema } from "../config/config";
|
||||
import { computeClaudeProjectFilePath } from "../core/claude-code/functions/computeClaudeProjectFilePath";
|
||||
import { ClaudeCodeLifeCycleService } from "../core/claude-code/services/ClaudeCodeLifeCycleService";
|
||||
import { ClaudeCodePermissionService } from "../core/claude-code/services/ClaudeCodePermissionService";
|
||||
import { getDirectoryListing } from "../core/directory-browser/functions/getDirectoryListing";
|
||||
import { adaptInternalEventToSSE } from "../core/events/functions/adaptInternalEventToSSE";
|
||||
import { TypeSafeSSE } from "../core/events/functions/typeSafeSSE";
|
||||
import { EventBus } from "../core/events/services/EventBus";
|
||||
import type { InternalEventDeclaration } from "../core/events/types/InternalEventDeclaration";
|
||||
import { getFileCompletion } from "../core/file-completion/functions/getFileCompletion";
|
||||
import { getBranches } from "../core/git/functions/getBranches";
|
||||
import { getCommits } from "../core/git/functions/getCommits";
|
||||
import { getDiff } from "../core/git/functions/getDiff";
|
||||
import { getMcpList } from "../core/mcp/functions/getMcpList";
|
||||
import { encodeProjectId } from "../core/project/functions/id";
|
||||
import { ProjectRepository } from "../core/project/infrastructure/ProjectRepository";
|
||||
import type { ProjectMetaService } from "../core/project/services/ProjectMetaService";
|
||||
import { SessionRepository } from "../core/session/infrastructure/SessionRepository";
|
||||
import type { VirtualConversationDatabase } from "../core/session/infrastructure/VirtualConversationDatabase";
|
||||
import type { SessionMetaService } from "../core/session/services/SessionMetaService";
|
||||
import { configSchema } from "../lib/config/config";
|
||||
import { claudeCommandsDirPath } from "../lib/config/paths";
|
||||
import { env } from "../lib/env";
|
||||
import { ClaudeCodeLifeCycleService } from "../service/claude-code/ClaudeCodeLifeCycleService";
|
||||
import { ClaudeCodePermissionService } from "../service/claude-code/ClaudeCodePermissionService";
|
||||
import { computeClaudeProjectFilePath } from "../service/claude-code/computeClaudeProjectFilePath";
|
||||
import { getDirectoryListing } from "../service/directory-browser/getDirectoryListing";
|
||||
import { adaptInternalEventToSSE } from "../service/events/adaptInternalEventToSSE";
|
||||
import { EventBus } from "../service/events/EventBus";
|
||||
import type { InternalEventDeclaration } from "../service/events/InternalEventDeclaration";
|
||||
import { TypeSafeSSE } from "../service/events/typeSafeSSE";
|
||||
import { getFileCompletion } from "../service/file-completion/getFileCompletion";
|
||||
import { getBranches } from "../service/git/getBranches";
|
||||
import { getCommits } from "../service/git/getCommits";
|
||||
import { getDiff } from "../service/git/getDiff";
|
||||
import { getMcpList } from "../service/mcp/getMcpList";
|
||||
import { claudeCommandsDirPath } from "../service/paths";
|
||||
import { encodeProjectId } from "../service/project/id";
|
||||
import type { ProjectMetaService } from "../service/project/ProjectMetaService";
|
||||
import { ProjectRepository } from "../service/project/ProjectRepository";
|
||||
import type { SessionMetaService } from "../service/session/SessionMetaService";
|
||||
import { SessionRepository } from "../service/session/SessionRepository";
|
||||
import type { VirtualConversationDatabase } from "../service/session/VirtualConversationDatabase";
|
||||
import type { HonoAppType } from "./app";
|
||||
import { InitializeService } from "./initialize";
|
||||
import { configMiddleware } from "./middleware/config.middleware";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { homedir } from "node:os";
|
||||
import { resolve } from "node:path";
|
||||
import { env } from "../lib/env";
|
||||
import { env } from "../env";
|
||||
|
||||
const GLOBAL_CLAUDE_DIR = env.get("GLOBAL_CLAUDE_DIR");
|
||||
|
||||
@@ -2,7 +2,7 @@ import { resolve } from "node:path";
|
||||
import { FileSystem } from "@effect/platform";
|
||||
import { Context, Effect, Layer } from "effect";
|
||||
import { z } from "zod";
|
||||
import { claudeCodeViewerCacheDirPath } from "../../../service/paths";
|
||||
import { claudeCodeViewerCacheDirPath } from "../../config/paths";
|
||||
|
||||
const saveSchema = z.array(z.tuple([z.string(), z.unknown()]));
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FileSystem } from "@effect/platform";
|
||||
import { Effect, Layer, Ref } from "effect";
|
||||
import { z } from "zod";
|
||||
import { FileCacheStorage, makeFileCacheStorageLayer } from "./index";
|
||||
import { PersistentService } from "./PersistantService";
|
||||
import { PersistentService } from "./PersistentService";
|
||||
|
||||
// Schema for testing
|
||||
const UserSchema = z.object({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { FileSystem } from "@effect/platform";
|
||||
import { Context, Effect, Layer, Ref, Runtime } from "effect";
|
||||
import type { z } from "zod";
|
||||
import { PersistentService } from "./PersistantService";
|
||||
import { PersistentService } from "./PersistentService";
|
||||
|
||||
export interface FileCacheStorageService<T> {
|
||||
readonly get: (key: string) => Effect.Effect<T | undefined>;
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
import type {
|
||||
SDKMessage,
|
||||
SDKSystemMessage,
|
||||
SDKUserMessage,
|
||||
} from "@anthropic-ai/claude-code";
|
||||
|
||||
export type OnMessage = (message: SDKMessage) => void | Promise<void>;
|
||||
|
||||
export type MessageGenerator = () => AsyncGenerator<
|
||||
SDKUserMessage,
|
||||
void,
|
||||
unknown
|
||||
>;
|
||||
|
||||
const createPromise = <T>() => {
|
||||
let promiseResolve: ((value: T) => void) | undefined;
|
||||
let promiseReject: ((reason?: unknown) => void) | undefined;
|
||||
|
||||
const promise = new Promise<T>((resolve, reject) => {
|
||||
promiseResolve = resolve;
|
||||
promiseReject = reject;
|
||||
});
|
||||
|
||||
if (!promiseResolve || !promiseReject) {
|
||||
throw new Error("Illegal state: Promise not created");
|
||||
}
|
||||
|
||||
return {
|
||||
promise,
|
||||
resolve: promiseResolve,
|
||||
reject: promiseReject,
|
||||
} as const;
|
||||
};
|
||||
|
||||
export type InitMessageContext = {
|
||||
initMessage: SDKSystemMessage;
|
||||
};
|
||||
|
||||
export const createMessageGenerator = (
|
||||
firstMessage: string,
|
||||
): {
|
||||
generateMessages: MessageGenerator;
|
||||
setNextMessage: (message: string) => void;
|
||||
setInitMessagePromise: () => void;
|
||||
resolveInitMessage: (context: InitMessageContext) => void;
|
||||
awaitInitMessage: (ctx: InitMessageContext) => Promise<void>;
|
||||
} => {
|
||||
let sendMessagePromise = createPromise<string>();
|
||||
let receivedInitMessagePromise = createPromise<InitMessageContext>();
|
||||
|
||||
const createMessage = (message: string): SDKUserMessage => {
|
||||
return {
|
||||
type: "user",
|
||||
message: {
|
||||
role: "user",
|
||||
content: message,
|
||||
},
|
||||
} as SDKUserMessage;
|
||||
};
|
||||
|
||||
async function* generateMessages(): ReturnType<MessageGenerator> {
|
||||
yield createMessage(firstMessage);
|
||||
|
||||
while (true) {
|
||||
const message = await sendMessagePromise.promise;
|
||||
sendMessagePromise = createPromise<string>();
|
||||
|
||||
yield createMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
const setNextMessage = (message: string) => {
|
||||
sendMessagePromise.resolve(message);
|
||||
};
|
||||
|
||||
const setInitMessagePromise = () => {
|
||||
receivedInitMessagePromise = createPromise<InitMessageContext>();
|
||||
};
|
||||
|
||||
const resolveInitMessage = (context: InitMessageContext) => {
|
||||
receivedInitMessagePromise.resolve(context);
|
||||
};
|
||||
|
||||
const awaitInitMessage = async () => {
|
||||
await receivedInitMessagePromise.promise;
|
||||
};
|
||||
|
||||
return {
|
||||
generateMessages,
|
||||
setNextMessage,
|
||||
setInitMessagePromise,
|
||||
resolveInitMessage,
|
||||
awaitInitMessage,
|
||||
};
|
||||
};
|
||||
@@ -1,32 +0,0 @@
|
||||
// Git service utilities for claude-code-viewer
|
||||
// Provides comprehensive Git operations including branch management, diff generation, and status checking
|
||||
|
||||
export * from "./getBranches";
|
||||
// Re-export main functions for convenience
|
||||
export { branchExists, getBranches, getCurrentBranch } from "./getBranches";
|
||||
export * from "./getCommits";
|
||||
export { getCommits } from "./getCommits";
|
||||
export * from "./getDiff";
|
||||
export { compareBranches, getDiff } from "./getDiff";
|
||||
export * from "./getStatus";
|
||||
export {
|
||||
getStatus,
|
||||
getUncommittedChanges,
|
||||
isWorkingDirectoryClean,
|
||||
} from "./getStatus";
|
||||
// Types re-export for convenience
|
||||
export type {
|
||||
GitBranch,
|
||||
GitCommit,
|
||||
GitComparisonResult,
|
||||
GitDiff,
|
||||
GitDiffFile,
|
||||
GitDiffHunk,
|
||||
GitDiffLine,
|
||||
GitError,
|
||||
GitResult,
|
||||
GitStatus,
|
||||
} from "./types";
|
||||
export * from "./types";
|
||||
export * from "./utils";
|
||||
export { executeGitCommand, isGitRepository } from "./utils";
|
||||
@@ -1,13 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { parsedCommandSchema } from "./parseCommandXml";
|
||||
|
||||
export const projectMetaSchema = z.object({
|
||||
projectName: z.string().nullable(),
|
||||
projectPath: z.string().nullable(),
|
||||
sessionCount: z.number(),
|
||||
});
|
||||
|
||||
export const sessionMetaSchema = z.object({
|
||||
messageCount: z.number(),
|
||||
firstCommand: parsedCommandSchema.nullable(),
|
||||
});
|
||||
Reference in New Issue
Block a user