diff --git a/src/agents/cli-runner.ts b/src/agents/cli-runner.ts index f654ce112..30a456606 100644 --- a/src/agents/cli-runner.ts +++ b/src/agents/cli-runner.ts @@ -4,7 +4,7 @@ import type { ThinkLevel } from "../auto-reply/thinking.js"; import type { ClawdbotConfig } from "../config/config.js"; import { isTruthyEnvValue } from "../infra/env.js"; import { shouldLogVerbose } from "../globals.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { runCommandWithTimeout } from "../process/exec.js"; import { resolveUserPath } from "../utils.js"; import { resolveClawdbotDocsPath } from "./docs-path.js"; diff --git a/src/agents/pi-embedded-runner/logger.ts b/src/agents/pi-embedded-runner/logger.ts index 4ea4e6709..872bee138 100644 --- a/src/agents/pi-embedded-runner/logger.ts +++ b/src/agents/pi-embedded-runner/logger.ts @@ -1,3 +1,3 @@ -import { createSubsystemLogger } from "../../logging.js"; +import { createSubsystemLogger } from "../../logging/subsystem.js"; export const log = createSubsystemLogger("agent/embedded"); diff --git a/src/agents/pi-embedded-subscribe.ts b/src/agents/pi-embedded-subscribe.ts index 489a95043..fed64fdde 100644 --- a/src/agents/pi-embedded-subscribe.ts +++ b/src/agents/pi-embedded-subscribe.ts @@ -1,6 +1,6 @@ import { parseReplyDirectives } from "../auto-reply/reply/reply-directives.js"; import { formatToolAggregate } from "../auto-reply/tool-meta.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import type { InlineCodeState } from "../markdown/code-spans.js"; import { buildCodeSpanIndex, createInlineCodeState } from "../markdown/code-spans.js"; import { EmbeddedBlockChunker } from "./pi-embedded-block-chunker.js"; diff --git a/src/agents/skills/refresh.ts b/src/agents/skills/refresh.ts index ee2d9a557..26dc75f9c 100644 --- a/src/agents/skills/refresh.ts +++ b/src/agents/skills/refresh.ts @@ -3,7 +3,7 @@ import path from "node:path"; import chokidar, { type FSWatcher } from "chokidar"; import type { ClawdbotConfig } from "../../config/config.js"; -import { createSubsystemLogger } from "../../logging.js"; +import { createSubsystemLogger } from "../../logging/subsystem.js"; import { CONFIG_DIR, resolveUserPath } from "../../utils.js"; type SkillsChangeEvent = { diff --git a/src/agents/skills/workspace.ts b/src/agents/skills/workspace.ts index 1ba430c64..b231e2d45 100644 --- a/src/agents/skills/workspace.ts +++ b/src/agents/skills/workspace.ts @@ -8,7 +8,7 @@ import { } from "@mariozechner/pi-coding-agent"; import type { ClawdbotConfig } from "../../config/config.js"; -import { createSubsystemLogger } from "../../logging.js"; +import { createSubsystemLogger } from "../../logging/subsystem.js"; import { CONFIG_DIR, resolveUserPath } from "../../utils.js"; import { resolveBundledSkillsDir } from "./bundled-dir.js"; import { shouldIncludeSkill } from "./config.js"; diff --git a/src/agents/tool-images.ts b/src/agents/tool-images.ts index 814f9903c..aa1594aeb 100644 --- a/src/agents/tool-images.ts +++ b/src/agents/tool-images.ts @@ -1,7 +1,7 @@ import type { AgentToolResult } from "@mariozechner/pi-agent-core"; import type { ImageContent } from "@mariozechner/pi-ai"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { getImageMetadata, resizeToJpeg } from "../media/image-ops.js"; type ToolContentBlock = AgentToolResult["content"][number]; diff --git a/src/agents/tools/sessions-send-tool.a2a.ts b/src/agents/tools/sessions-send-tool.a2a.ts index ab52b70a1..a98c34a23 100644 --- a/src/agents/tools/sessions-send-tool.a2a.ts +++ b/src/agents/tools/sessions-send-tool.a2a.ts @@ -2,7 +2,7 @@ import crypto from "node:crypto"; import { callGateway } from "../../gateway/call.js"; import { formatErrorMessage } from "../../infra/errors.js"; -import { createSubsystemLogger } from "../../logging.js"; +import { createSubsystemLogger } from "../../logging/subsystem.js"; import type { GatewayMessageChannel } from "../../utils/message-channel.js"; import { AGENT_LANE_NESTED } from "../lanes.js"; import { readLatestAssistantReply, runAgentStep } from "./agent-step.js"; diff --git a/src/browser/chrome.ts b/src/browser/chrome.ts index 76e2ee00e..eebf399bc 100644 --- a/src/browser/chrome.ts +++ b/src/browser/chrome.ts @@ -5,7 +5,7 @@ import path from "node:path"; import WebSocket from "ws"; import { ensurePortAvailable } from "../infra/ports.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { CONFIG_DIR } from "../utils.js"; import { getHeadersWithAuth, normalizeCdpWsUrl } from "./cdp.js"; import { appendCdpPath } from "./cdp.helpers.js"; diff --git a/src/browser/server.ts b/src/browser/server.ts index edfb9ab76..9fb9a5f81 100644 --- a/src/browser/server.ts +++ b/src/browser/server.ts @@ -2,7 +2,7 @@ import type { Server } from "node:http"; import express from "express"; import { loadConfig } from "../config/config.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { resolveBrowserConfig, resolveProfile, shouldStartLocalBrowserServer } from "./config.js"; import { ensureChromeExtensionRelayServer } from "./extension-relay.js"; import { registerBrowserRoutes } from "./routes/index.js"; diff --git a/src/cli/gateway-cli/run.ts b/src/cli/gateway-cli/run.ts index 5c83aa2ff..ede01fa1f 100644 --- a/src/cli/gateway-cli/run.ts +++ b/src/cli/gateway-cli/run.ts @@ -15,11 +15,8 @@ import { setGatewayWsLogStyle } from "../../gateway/ws-logging.js"; import { setVerbose } from "../../globals.js"; import { GatewayLockError } from "../../infra/gateway-lock.js"; import { formatPortDiagnostics, inspectPortUsage } from "../../infra/ports.js"; -import { - createSubsystemLogger, - setConsoleSubsystemFilter, - setConsoleTimestampPrefix, -} from "../../logging.js"; +import { setConsoleSubsystemFilter, setConsoleTimestampPrefix } from "../../logging/console.js"; +import { createSubsystemLogger } from "../../logging/subsystem.js"; import { defaultRuntime } from "../../runtime.js"; import { forceFreePortAndWait } from "../ports.js"; import { ensureDevGatewayConfig } from "./dev.js"; diff --git a/src/cli/program/context.ts b/src/cli/program/context.ts index dc38eb41f..0fde7ad3d 100644 --- a/src/cli/program/context.ts +++ b/src/cli/program/context.ts @@ -1,3 +1,8 @@ +import { listChannelPlugins } from "../../channels/plugins/index.js"; +import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js"; +import { loadConfig } from "../../config/config.js"; +import { createSubsystemLogger } from "../../logging/subsystem.js"; +import { loadClawdbotPlugins } from "../../plugins/loader.js"; import { VERSION } from "../../version.js"; import { resolveCliChannelOptions } from "../channel-options.js"; diff --git a/src/commands/onboarding/plugin-install.ts b/src/commands/onboarding/plugin-install.ts index 4c4443ff6..bf1e43e6e 100644 --- a/src/commands/onboarding/plugin-install.ts +++ b/src/commands/onboarding/plugin-install.ts @@ -3,7 +3,7 @@ import path from "node:path"; import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js"; import type { ChannelPluginCatalogEntry } from "../../channels/plugins/catalog.js"; import type { ClawdbotConfig } from "../../config/config.js"; -import { createSubsystemLogger } from "../../logging.js"; +import { createSubsystemLogger } from "../../logging/subsystem.js"; import { recordPluginInstall } from "../../plugins/installs.js"; import { enablePluginInConfig } from "../../plugins/enable.js"; import { loadClawdbotPlugins } from "../../plugins/loader.js"; diff --git a/src/discord/monitor/listeners.ts b/src/discord/monitor/listeners.ts index 96b102cd2..1d8f66250 100644 --- a/src/discord/monitor/listeners.ts +++ b/src/discord/monitor/listeners.ts @@ -9,7 +9,7 @@ import { import { danger } from "../../globals.js"; import { formatDurationSeconds } from "../../infra/format-duration.js"; import { enqueueSystemEvent } from "../../infra/system-events.js"; -import { createSubsystemLogger } from "../../logging.js"; +import { createSubsystemLogger } from "../../logging/subsystem.js"; import { resolveAgentRoute } from "../../routing/resolve-route.js"; import { normalizeDiscordSlug, @@ -22,7 +22,7 @@ import { resolveDiscordChannelInfo } from "./message-utils.js"; type LoadedConfig = ReturnType; type RuntimeEnv = import("../../runtime.js").RuntimeEnv; -type Logger = ReturnType; +type Logger = ReturnType; export type DiscordMessageEvent = Parameters[0]; diff --git a/src/gateway/boot.ts b/src/gateway/boot.ts index aa2a13d8f..f12093cde 100644 --- a/src/gateway/boot.ts +++ b/src/gateway/boot.ts @@ -6,7 +6,7 @@ import type { CliDeps } from "../cli/deps.js"; import type { ClawdbotConfig } from "../config/config.js"; import { resolveMainSessionKey } from "../config/sessions/main-session.js"; import { agentCommand } from "../commands/agent.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { type RuntimeEnv, defaultRuntime } from "../runtime.js"; const log = createSubsystemLogger("gateway/boot"); diff --git a/src/gateway/server-channels.ts b/src/gateway/server-channels.ts index b9593fbfc..53e1a8d27 100644 --- a/src/gateway/server-channels.ts +++ b/src/gateway/server-channels.ts @@ -4,7 +4,7 @@ import type { ChannelAccountSnapshot } from "../channels/plugins/types.js"; import type { ClawdbotConfig } from "../config/config.js"; import { formatErrorMessage } from "../infra/errors.js"; import { resetDirectoryCache } from "../infra/outbound/target-resolver.js"; -import type { createSubsystemLogger } from "../logging.js"; +import type { createSubsystemLogger } from "../logging/subsystem.js"; import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js"; import type { RuntimeEnv } from "../runtime.js"; diff --git a/src/gateway/server-http.ts b/src/gateway/server-http.ts index c345f6299..1f3b89bfa 100644 --- a/src/gateway/server-http.ts +++ b/src/gateway/server-http.ts @@ -7,7 +7,7 @@ import { import type { WebSocketServer } from "ws"; import { handleA2uiHttpRequest } from "../canvas-host/a2ui.js"; import type { CanvasHostHandler } from "../canvas-host/server.js"; -import type { createSubsystemLogger } from "../logging.js"; +import type { createSubsystemLogger } from "../logging/subsystem.js"; import { handleSlackHttpRequest } from "../slack/http/index.js"; import { handleControlUiHttpRequest } from "./control-ui.js"; import { diff --git a/src/gateway/server-runtime-state.ts b/src/gateway/server-runtime-state.ts index 1d4f86dd5..60dc4fed5 100644 --- a/src/gateway/server-runtime-state.ts +++ b/src/gateway/server-runtime-state.ts @@ -3,7 +3,7 @@ import { WebSocketServer } from "ws"; import { CANVAS_HOST_PATH } from "../canvas-host/a2ui.js"; import { type CanvasHostHandler, createCanvasHostHandler } from "../canvas-host/server.js"; import type { CliDeps } from "../cli/deps.js"; -import type { createSubsystemLogger } from "../logging.js"; +import type { createSubsystemLogger } from "../logging/subsystem.js"; import type { RuntimeEnv } from "../runtime.js"; import type { ResolvedGatewayAuth } from "./auth.js"; import type { ChatAbortControllerEntry } from "./chat-abort.js"; diff --git a/src/gateway/server-ws-runtime.ts b/src/gateway/server-ws-runtime.ts index 57bd5a3b0..a20cf85e7 100644 --- a/src/gateway/server-ws-runtime.ts +++ b/src/gateway/server-ws-runtime.ts @@ -1,5 +1,5 @@ import type { WebSocketServer } from "ws"; -import type { createSubsystemLogger } from "../logging.js"; +import type { createSubsystemLogger } from "../logging/subsystem.js"; import type { ResolvedGatewayAuth } from "./auth.js"; import { attachGatewayWsConnectionHandler } from "./server/ws-connection.js"; import type { GatewayWsClient } from "./server/ws-types.js"; diff --git a/src/gateway/server/hooks.ts b/src/gateway/server/hooks.ts index e6980dfd9..66afca384 100644 --- a/src/gateway/server/hooks.ts +++ b/src/gateway/server/hooks.ts @@ -7,7 +7,7 @@ import { runCronIsolatedAgentTurn } from "../../cron/isolated-agent.js"; import type { CronJob } from "../../cron/types.js"; import { requestHeartbeatNow } from "../../infra/heartbeat-wake.js"; import { enqueueSystemEvent } from "../../infra/system-events.js"; -import type { createSubsystemLogger } from "../../logging.js"; +import type { createSubsystemLogger } from "../../logging/subsystem.js"; import type { HookMessageChannel, HooksConfigResolved } from "../hooks.js"; import { createHooksRequestHandler } from "../server-http.js"; diff --git a/src/gateway/server/plugins-http.ts b/src/gateway/server/plugins-http.ts index 956b2ea8f..948a41a17 100644 --- a/src/gateway/server/plugins-http.ts +++ b/src/gateway/server/plugins-http.ts @@ -1,6 +1,6 @@ import type { IncomingMessage, ServerResponse } from "node:http"; -import type { createSubsystemLogger } from "../../logging.js"; +import type { createSubsystemLogger } from "../../logging/subsystem.js"; import type { PluginRegistry } from "../../plugins/registry.js"; type SubsystemLogger = ReturnType; diff --git a/src/gateway/server/ws-connection.ts b/src/gateway/server/ws-connection.ts index 13f24d4f7..365b20474 100644 --- a/src/gateway/server/ws-connection.ts +++ b/src/gateway/server/ws-connection.ts @@ -3,7 +3,7 @@ import { randomUUID } from "node:crypto"; import type { WebSocket, WebSocketServer } from "ws"; import { resolveCanvasHostUrl } from "../../infra/canvas-host-url.js"; import { listSystemPresence, upsertPresence } from "../../infra/system-presence.js"; -import type { createSubsystemLogger } from "../../logging.js"; +import type { createSubsystemLogger } from "../../logging/subsystem.js"; import { isWebchatClient } from "../../utils/message-channel.js"; import type { ResolvedGatewayAuth } from "../auth.js"; diff --git a/src/gateway/server/ws-connection/message-handler.ts b/src/gateway/server/ws-connection/message-handler.ts index 116562531..320ccc5f2 100644 --- a/src/gateway/server/ws-connection/message-handler.ts +++ b/src/gateway/server/ws-connection/message-handler.ts @@ -4,7 +4,7 @@ import os from "node:os"; import type { WebSocket } from "ws"; import { upsertPresence } from "../../../infra/system-presence.js"; import { rawDataToString } from "../../../infra/ws.js"; -import type { createSubsystemLogger } from "../../../logging.js"; +import type { createSubsystemLogger } from "../../../logging/subsystem.js"; import { isGatewayCliClient, isWebchatClient } from "../../../utils/message-channel.js"; import type { ResolvedGatewayAuth } from "../../auth.js"; import { authorizeGatewayConnect } from "../../auth.js"; diff --git a/src/gateway/ws-log.ts b/src/gateway/ws-log.ts index 27f86c61a..fccfc5b36 100644 --- a/src/gateway/ws-log.ts +++ b/src/gateway/ws-log.ts @@ -1,7 +1,8 @@ import chalk from "chalk"; import { isVerbose } from "../globals.js"; import { parseAgentSessionKey } from "../routing/session-key.js"; -import { createSubsystemLogger, shouldLogSubsystemToConsole } from "../logging.js"; +import { shouldLogSubsystemToConsole } from "../logging/console.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { getDefaultRedactPatterns, redactSensitiveText } from "../logging/redact.js"; import { DEFAULT_WS_SLOW_MS, getGatewayWsLogStyle } from "./ws-logging.js"; diff --git a/src/hooks/gmail-watcher.ts b/src/hooks/gmail-watcher.ts index c9efad1a0..a3ccd5025 100644 --- a/src/hooks/gmail-watcher.ts +++ b/src/hooks/gmail-watcher.ts @@ -8,7 +8,7 @@ import { type ChildProcess, spawn } from "node:child_process"; import { hasBinary } from "../agents/skills.js"; import type { ClawdbotConfig } from "../config/config.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { runCommandWithTimeout } from "../process/exec.js"; import { buildGogWatchServeArgs, diff --git a/src/infra/bonjour.test.ts b/src/infra/bonjour.test.ts index f5786fcd6..aa5ab3d7e 100644 --- a/src/infra/bonjour.test.ts +++ b/src/infra/bonjour.test.ts @@ -4,19 +4,22 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import * as logging from "../logging.js"; -const createService = vi.fn(); -const shutdown = vi.fn(); -const registerUnhandledRejectionHandler = vi.fn(); - -const logWarn = vi.fn(); -const logDebug = vi.fn(); -const getLoggerInfo = vi.fn(); +const mocks = vi.hoisted(() => ({ + createService: vi.fn(), + shutdown: vi.fn(), + registerUnhandledRejectionHandler: vi.fn(), + logWarn: vi.fn(), + logDebug: vi.fn(), +})); +const { createService, shutdown, registerUnhandledRejectionHandler, logWarn, logDebug } = mocks; const asString = (value: unknown, fallback: string) => typeof value === "string" && value.trim() ? value : fallback; -vi.mock("../logger.js", () => { +vi.mock("../logger.js", async () => { + const actual = await vi.importActual("../logger.js"); return { + ...actual, logWarn: (message: string) => logWarn(message), logDebug: (message: string) => logDebug(message), logInfo: vi.fn(), @@ -73,7 +76,6 @@ describe("gateway bonjour advertiser", () => { registerUnhandledRejectionHandler.mockReset(); logWarn.mockReset(); logDebug.mockReset(); - getLoggerInfo.mockReset(); vi.useRealTimers(); vi.restoreAllMocks(); }); diff --git a/src/infra/heartbeat-runner.ts b/src/infra/heartbeat-runner.ts index c5609b3ad..3c01396cb 100644 --- a/src/infra/heartbeat-runner.ts +++ b/src/infra/heartbeat-runner.ts @@ -22,7 +22,7 @@ import { } from "../config/sessions.js"; import type { AgentDefaultsConfig } from "../config/types.agent-defaults.js"; import { formatErrorMessage } from "../infra/errors.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { getQueueSize } from "../process/command-queue.js"; import { defaultRuntime, type RuntimeEnv } from "../runtime.js"; import { normalizeAgentId } from "../routing/session-key.js"; diff --git a/src/infra/skills-remote.ts b/src/infra/skills-remote.ts index 10b7b7d32..e4bc88c5a 100644 --- a/src/infra/skills-remote.ts +++ b/src/infra/skills-remote.ts @@ -4,7 +4,7 @@ import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent import type { ClawdbotConfig } from "../config/config.js"; import type { NodeBridgeServer } from "./bridge/server.js"; import { listNodePairing, updatePairedNodeMetadata } from "./node-pairing.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { bumpSkillsSnapshotVersion } from "../agents/skills/refresh.js"; type RemoteNodeRecord = { diff --git a/src/infra/state-migrations.ts b/src/infra/state-migrations.ts index 76d167fb8..c8c90e993 100644 --- a/src/infra/state-migrations.ts +++ b/src/infra/state-migrations.ts @@ -7,7 +7,7 @@ import type { ClawdbotConfig } from "../config/config.js"; import { resolveOAuthDir, resolveStateDir } from "../config/paths.js"; import type { SessionEntry } from "../config/sessions.js"; import { saveSessionStore } from "../config/sessions.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { buildAgentMainSessionKey, DEFAULT_ACCOUNT_ID, diff --git a/src/logger.ts b/src/logger.ts index 082592216..6015cf344 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,5 +1,6 @@ import { danger, info, logVerboseConsole, success, warn } from "./globals.js"; -import { createSubsystemLogger, getLogger } from "./logging.js"; +import { getLogger } from "./logging/logger.js"; +import { createSubsystemLogger } from "./logging/subsystem.js"; import { defaultRuntime, type RuntimeEnv } from "./runtime.js"; const subsystemPrefixRe = /^([a-z][a-z0-9-]{1,20}):\s+(.*)$/i; diff --git a/src/logging/config.ts b/src/logging/config.ts new file mode 100644 index 000000000..ccb766550 --- /dev/null +++ b/src/logging/config.ts @@ -0,0 +1,22 @@ +import fs from "node:fs"; + +import json5 from "json5"; + +import { resolveConfigPath } from "../config/paths.js"; +import type { ClawdbotConfig } from "../config/types.js"; + +type LoggingConfig = ClawdbotConfig["logging"]; + +export function readLoggingConfig(): LoggingConfig | undefined { + const configPath = resolveConfigPath(); + try { + if (!fs.existsSync(configPath)) return undefined; + const raw = fs.readFileSync(configPath, "utf-8"); + const parsed = json5.parse(raw) as Record; + const logging = parsed?.logging; + if (!logging || typeof logging !== "object" || Array.isArray(logging)) return undefined; + return logging as LoggingConfig; + } catch { + return undefined; + } +} diff --git a/src/logging/console.ts b/src/logging/console.ts index afa7a612c..68c3d2066 100644 --- a/src/logging/console.ts +++ b/src/logging/console.ts @@ -1,11 +1,12 @@ import { createRequire } from "node:module"; import util from "node:util"; -import type { ClawdbotConfig } from "../config/config.js"; +import type { ClawdbotConfig } from "../config/types.js"; import { isVerbose } from "../globals.js"; import { stripAnsi } from "../terminal/ansi.js"; import { type LogLevel, normalizeLogLevel } from "./levels.js"; import { getLogger, type LoggerSettings } from "./logger.js"; +import { readLoggingConfig } from "./config.js"; import { loggingState } from "./state.js"; export type ConsoleStyle = "pretty" | "compact" | "json"; @@ -31,10 +32,9 @@ function normalizeConsoleStyle(style?: string): ConsoleStyle { } function resolveConsoleSettings(): ConsoleSettings { - let cfg: ClawdbotConfig["logging"] | undefined; - if (loggingState.overrideSettings) { - cfg = loggingState.overrideSettings as LoggerSettings; - } else { + let cfg: ClawdbotConfig["logging"] | undefined = + (loggingState.overrideSettings as LoggerSettings | null) ?? readLoggingConfig(); + if (!cfg) { try { const loaded = requireConfig("../config/config.js") as { loadConfig?: () => ClawdbotConfig; diff --git a/src/logging/logger.ts b/src/logging/logger.ts index 31c61d19a..3bf729388 100644 --- a/src/logging/logger.ts +++ b/src/logging/logger.ts @@ -4,9 +4,10 @@ import path from "node:path"; import { Logger as TsLogger } from "tslog"; -import type { ClawdbotConfig } from "../config/config.js"; +import type { ClawdbotConfig } from "../config/types.js"; import type { ConsoleStyle } from "./console.js"; import { type LogLevel, levelToMinLevel, normalizeLogLevel } from "./levels.js"; +import { readLoggingConfig } from "./config.js"; import { loggingState } from "./state.js"; // Pin to /tmp so mac Debug UI and docs match; os.tmpdir() can be a per-user @@ -36,10 +37,9 @@ type ResolvedSettings = { export type LoggerResolvedSettings = ResolvedSettings; function resolveSettings(): ResolvedSettings { - let cfg: ClawdbotConfig["logging"] | undefined; - if (loggingState.overrideSettings) { - cfg = loggingState.overrideSettings as LoggerSettings; - } else { + let cfg: ClawdbotConfig["logging"] | undefined = + (loggingState.overrideSettings as LoggerSettings | null) ?? readLoggingConfig(); + if (!cfg) { try { const loaded = requireConfig("../config/config.js") as { loadConfig?: () => ClawdbotConfig; diff --git a/src/media/host.test.ts b/src/media/host.test.ts index 24c8f627b..d229d5ee0 100644 --- a/src/media/host.test.ts +++ b/src/media/host.test.ts @@ -3,11 +3,15 @@ import type { Server } from "node:http"; import { beforeEach, describe, expect, it, vi } from "vitest"; -const saveMediaSource = vi.fn(); -const getTailnetHostname = vi.fn(); -const ensurePortAvailable = vi.fn(); -const startMediaServer = vi.fn(); -const logInfo = vi.fn(); +const mocks = vi.hoisted(() => ({ + saveMediaSource: vi.fn(), + getTailnetHostname: vi.fn(), + ensurePortAvailable: vi.fn(), + startMediaServer: vi.fn(), + logInfo: vi.fn(), +})); +const { saveMediaSource, getTailnetHostname, ensurePortAvailable, startMediaServer, logInfo } = + mocks; vi.mock("./store.js", () => ({ saveMediaSource })); vi.mock("../infra/tailscale.js", () => ({ getTailnetHostname })); @@ -16,7 +20,10 @@ vi.mock("../infra/ports.js", async () => { return { ensurePortAvailable, PortInUseError: actual.PortInUseError }; }); vi.mock("./server.js", () => ({ startMediaServer })); -vi.mock("../logger.js", () => ({ logInfo })); +vi.mock("../logger.js", async () => { + const actual = await vi.importActual("../logger.js"); + return { ...actual, logInfo }; +}); const { ensureMediaHosted } = await import("./host.js"); const { PortInUseError } = await import("../infra/ports.js"); diff --git a/src/memory/batch-gemini.ts b/src/memory/batch-gemini.ts index cd55abe2f..728fe2de0 100644 --- a/src/memory/batch-gemini.ts +++ b/src/memory/batch-gemini.ts @@ -1,4 +1,4 @@ -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { isTruthyEnvValue } from "../infra/env.js"; import type { GeminiEmbeddingClient } from "./embeddings-gemini.js"; import { hashText } from "./internal.js"; diff --git a/src/memory/embeddings-gemini.ts b/src/memory/embeddings-gemini.ts index 44c27f519..423522775 100644 --- a/src/memory/embeddings-gemini.ts +++ b/src/memory/embeddings-gemini.ts @@ -1,6 +1,6 @@ import { resolveApiKeyForProvider } from "../agents/model-auth.js"; import { isTruthyEnvValue } from "../infra/env.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import type { EmbeddingProvider, EmbeddingProviderOptions } from "./embeddings.js"; export type GeminiEmbeddingClient = { diff --git a/src/memory/manager.ts b/src/memory/manager.ts index 56eab4375..b94e5f3de 100644 --- a/src/memory/manager.ts +++ b/src/memory/manager.ts @@ -10,7 +10,7 @@ import type { ResolvedMemorySearchConfig } from "../agents/memory-search.js"; import { resolveMemorySearchConfig } from "../agents/memory-search.js"; import type { ClawdbotConfig } from "../config/config.js"; import { resolveSessionTranscriptsDirForAgent } from "../config/sessions/paths.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { onSessionTranscriptUpdate } from "../sessions/transcript-events.js"; import { resolveUserPath } from "../utils.js"; import { diff --git a/src/memory/session-files.ts b/src/memory/session-files.ts index d5ba8dd54..82f8c1e09 100644 --- a/src/memory/session-files.ts +++ b/src/memory/session-files.ts @@ -2,7 +2,7 @@ import fs from "node:fs/promises"; import path from "node:path"; import { resolveSessionTranscriptsDirForAgent } from "../config/sessions/paths.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { hashText } from "./internal.js"; const log = createSubsystemLogger("memory"); diff --git a/src/memory/sync-memory-files.ts b/src/memory/sync-memory-files.ts index 437f9f7fb..53fed7ebe 100644 --- a/src/memory/sync-memory-files.ts +++ b/src/memory/sync-memory-files.ts @@ -1,6 +1,6 @@ import type { DatabaseSync } from "node:sqlite"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { buildFileEntry, listMemoryFiles, type MemoryFileEntry } from "./internal.js"; const log = createSubsystemLogger("memory"); diff --git a/src/memory/sync-session-files.ts b/src/memory/sync-session-files.ts index 327ddf886..e2aba7101 100644 --- a/src/memory/sync-session-files.ts +++ b/src/memory/sync-session-files.ts @@ -1,6 +1,6 @@ import type { DatabaseSync } from "node:sqlite"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import type { SessionFileEntry } from "./session-files.js"; import { buildSessionEntry, diff --git a/src/plugins/cli.ts b/src/plugins/cli.ts index c0d885582..6a3571b2d 100644 --- a/src/plugins/cli.ts +++ b/src/plugins/cli.ts @@ -3,7 +3,7 @@ import type { Command } from "commander"; import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js"; import type { ClawdbotConfig } from "../config/config.js"; import { loadConfig } from "../config/config.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { loadClawdbotPlugins } from "./loader.js"; import type { PluginLogger } from "./types.js"; diff --git a/src/plugins/hook-runner-global.ts b/src/plugins/hook-runner-global.ts index e01f61c51..368d76684 100644 --- a/src/plugins/hook-runner-global.ts +++ b/src/plugins/hook-runner-global.ts @@ -5,7 +5,7 @@ * and can be called from anywhere in the codebase. */ -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { createHookRunner, type HookRunner } from "./hooks.js"; import type { PluginRegistry } from "./registry.js"; diff --git a/src/plugins/providers.ts b/src/plugins/providers.ts index 2b3f80bd2..e81aad7c5 100644 --- a/src/plugins/providers.ts +++ b/src/plugins/providers.ts @@ -1,4 +1,4 @@ -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { loadClawdbotPlugins, type PluginLoadOptions } from "./loader.js"; import type { ProviderPlugin } from "./types.js"; diff --git a/src/plugins/services.ts b/src/plugins/services.ts index 538618daf..604224477 100644 --- a/src/plugins/services.ts +++ b/src/plugins/services.ts @@ -1,6 +1,6 @@ import type { ClawdbotConfig } from "../config/config.js"; import { STATE_DIR_CLAWDBOT } from "../config/paths.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import type { PluginRegistry } from "./registry.js"; const log = createSubsystemLogger("plugins"); diff --git a/src/plugins/status.ts b/src/plugins/status.ts index 75d77390e..91000dd28 100644 --- a/src/plugins/status.ts +++ b/src/plugins/status.ts @@ -1,7 +1,7 @@ import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js"; import { resolveDefaultAgentWorkspaceDir } from "../agents/workspace.js"; import { loadConfig } from "../config/config.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { loadClawdbotPlugins } from "./loader.js"; import type { PluginRegistry } from "./registry.js"; diff --git a/src/plugins/tools.ts b/src/plugins/tools.ts index 6935a8e6d..df945bbf7 100644 --- a/src/plugins/tools.ts +++ b/src/plugins/tools.ts @@ -1,6 +1,6 @@ import type { AnyAgentTool } from "../agents/tools/common.js"; import { normalizeToolName } from "../agents/tool-policy.js"; -import { createSubsystemLogger } from "../logging.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { loadClawdbotPlugins } from "./loader.js"; import type { ClawdbotPluginToolContext } from "./types.js"; diff --git a/src/web/auto-reply/loggers.ts b/src/web/auto-reply/loggers.ts index 3a1ba4e4c..b52722893 100644 --- a/src/web/auto-reply/loggers.ts +++ b/src/web/auto-reply/loggers.ts @@ -1,4 +1,4 @@ -import { createSubsystemLogger } from "../../logging.js"; +import { createSubsystemLogger } from "../../logging/subsystem.js"; export const whatsappLog = createSubsystemLogger("gateway/channels/whatsapp"); export const whatsappInboundLog = whatsappLog.child("inbound"); diff --git a/src/web/inbound/monitor.ts b/src/web/inbound/monitor.ts index c6e6189b6..3633cbce9 100644 --- a/src/web/inbound/monitor.ts +++ b/src/web/inbound/monitor.ts @@ -3,7 +3,8 @@ import { DisconnectReason, isJidGroup } from "@whiskeysockets/baileys"; import { formatLocationText } from "../../channels/location.js"; import { logVerbose, shouldLogVerbose } from "../../globals.js"; import { recordChannelActivity } from "../../infra/channel-activity.js"; -import { createSubsystemLogger, getChildLogger } from "../../logging.js"; +import { getChildLogger } from "../../logging/logger.js"; +import { createSubsystemLogger } from "../../logging/subsystem.js"; import { saveMediaBuffer } from "../../media/store.js"; import { createInboundDebouncer } from "../../auto-reply/inbound-debounce.js"; import { jidToE164, resolveJidToE164 } from "../../utils.js"; diff --git a/src/web/outbound.ts b/src/web/outbound.ts index 8639e5af1..d67abb2a1 100644 --- a/src/web/outbound.ts +++ b/src/web/outbound.ts @@ -1,6 +1,7 @@ import { randomUUID } from "node:crypto"; -import { createSubsystemLogger, getChildLogger } from "../logging.js"; +import { getChildLogger } from "../logging/logger.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; import { normalizePollInput, type PollInput } from "../polls.js"; import { toWhatsappJid } from "../utils.js"; import { type ActiveWebSendOptions, requireActiveWebListener } from "./active-listener.js";