diff --git a/src/cli/print.ts b/src/cli/print.ts index affe37e60..1e19abff5 100644 --- a/src/cli/print.ts +++ b/src/cli/print.ts @@ -352,23 +352,26 @@ import { initializeGrowthBook } from '../services/analytics/growthbook.js' import { errorMessage, toError } from '../utils/errors.js' import { sleep } from '../utils/sleep.js' import { isExtractModeActive } from '../memdir/paths.js' +import * as proactiveModuleValue from '../proactive/index.js' +import * as coordinatorModeModuleValue from '../coordinator/coordinatorMode.js' +import * as cronSchedulerModuleValue from '../utils/cronScheduler.js' +import * as cronJitterConfigModuleValue from '../utils/cronJitterConfig.js' +import * as cronGateValue from '../tools/ScheduleCronTool/prompt.js' +import * as extractMemoriesModuleValue from '../services/extractMemories/extractMemories.js' -// Dead code elimination: conditional imports -/* eslint-disable @typescript-eslint/no-require-imports */ const coordinatorModeModule = feature('COORDINATOR_MODE') - ? (require('../coordinator/coordinatorMode.js') as typeof import('../coordinator/coordinatorMode.js')) + ? coordinatorModeModuleValue : null const proactiveModule = feature('PROACTIVE') || feature('KAIROS') - ? (require('../proactive/index.js') as typeof import('../proactive/index.js')) + ? proactiveModuleValue : null -const cronSchedulerModule = require('../utils/cronScheduler.js') as typeof import('../utils/cronScheduler.js') -const cronJitterConfigModule = require('../utils/cronJitterConfig.js') as typeof import('../utils/cronJitterConfig.js') -const cronGate = require('../tools/ScheduleCronTool/prompt.js') as typeof import('../tools/ScheduleCronTool/prompt.js') +const cronSchedulerModule = cronSchedulerModuleValue +const cronJitterConfigModule = cronJitterConfigModuleValue +const cronGate = cronGateValue const extractMemoriesModule = feature('EXTRACT_MEMORIES') - ? (require('../services/extractMemories/extractMemories.js') as typeof import('../services/extractMemories/extractMemories.js')) + ? extractMemoriesModuleValue : null -/* eslint-enable @typescript-eslint/no-require-imports */ const SHUTDOWN_TEAM_PROMPT = ` You are running in non-interactive mode and cannot return a response to the user until your team is shut down. diff --git a/src/commands.ts b/src/commands.ts index 98c2a3681..6d3c61da2 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -57,39 +57,48 @@ import usage from './commands/usage/index.js' import theme from './commands/theme/index.js' import vim from './commands/vim/index.js' import { feature } from 'bun:bundle' -// Dead code elimination: conditional imports -/* eslint-disable @typescript-eslint/no-require-imports */ +import { clearSkillIndexCache as clearSkillIndexCacheValue } from './services/skillSearch/localSearch.js' +import proactiveValue from './commands/proactive.js' +import briefCommandValue from './commands/brief.js' +import assistantCommandValue from './commands/assistant/index.js' +import bridgeValue from './commands/bridge/index.js' +import remoteControlServerCommandValue from './commands/remoteControlServer/index.js' +import voiceCommandValue from './commands/voice/index.js' +import coordinatorCmdValue from './commands/coordinator.js' +import workflowsCmdValue from './commands/workflows/index.js' +import ultraplanValue from './commands/ultraplan.js' +import buddyValue from './commands/buddy/index.js' +import { getWorkflowCommands as getWorkflowCommandsValue } from './tools/WorkflowTool/createWorkflowCommand.js' + const proactive = feature('PROACTIVE') || feature('KAIROS') - ? require('./commands/proactive.js').default + ? proactiveValue : null const briefCommand = feature('KAIROS') || feature('KAIROS_BRIEF') - ? require('./commands/brief.js').default + ? briefCommandValue : null const assistantCommand = feature('KAIROS') - ? require('./commands/assistant/index.js').default + ? assistantCommandValue : null const bridge = feature('BRIDGE_MODE') - ? require('./commands/bridge/index.js').default + ? bridgeValue : null const remoteControlServerCommand = feature('DAEMON') && feature('BRIDGE_MODE') - ? require('./commands/remoteControlServer/index.js').default + ? remoteControlServerCommandValue : null const voiceCommand = feature('VOICE_MODE') - ? require('./commands/voice/index.js').default + ? voiceCommandValue : null const coordinatorCmd = feature('COORDINATOR_MODE') - ? require('./commands/coordinator.js').default + ? coordinatorCmdValue : null const forceSnip = feature('HISTORY_SNIP') ? require('./commands/force-snip.js').default : null const workflowsCmd = feature('WORKFLOW_SCRIPTS') - ? ( - require('./commands/workflows/index.js') as typeof import('./commands/workflows/index.js') - ).default + ? workflowsCmdValue : null const webCmd = feature('CCR_REMOTE_SETUP') ? ( @@ -97,15 +106,13 @@ const webCmd = feature('CCR_REMOTE_SETUP') ).default : null const clearSkillIndexCache = feature('EXPERIMENTAL_SKILL_SEARCH') - ? ( - require('./services/skillSearch/localSearch.js') as typeof import('./services/skillSearch/localSearch.js') - ).clearSkillIndexCache + ? clearSkillIndexCacheValue : null const subscribePr = feature('KAIROS_GITHUB_WEBHOOKS') ? require('./commands/subscribe-pr.js').default : null const ultraplan = feature('ULTRAPLAN') - ? require('./commands/ultraplan.js').default + ? ultraplanValue : null const torch = feature('TORCH') ? require('./commands/torch.js').default : null const peersCmd = feature('UDS_INBOX') @@ -119,11 +126,8 @@ const forkCmd = feature('FORK_SUBAGENT') ).default : null const buddy = feature('BUDDY') - ? ( - require('./commands/buddy/index.js') as typeof import('./commands/buddy/index.js') - ).default + ? buddyValue : null -/* eslint-enable @typescript-eslint/no-require-imports */ import thinkback from './commands/thinkback/index.js' import thinkbackPlay from './commands/thinkback-play/index.js' import permissions from './commands/permissions/index.js' @@ -405,13 +409,9 @@ async function getSkills(cwd: string): Promise<{ } } -/* eslint-disable @typescript-eslint/no-require-imports */ const getWorkflowCommands = feature('WORKFLOW_SCRIPTS') - ? ( - require('./tools/WorkflowTool/createWorkflowCommand.js') as typeof import('./tools/WorkflowTool/createWorkflowCommand.js') - ).getWorkflowCommands + ? getWorkflowCommandsValue : null -/* eslint-enable @typescript-eslint/no-require-imports */ /** * Filters commands by their declared `availability` (auth/provider requirement). diff --git a/src/commands/clear/conversation.ts b/src/commands/clear/conversation.ts index e528b56e4..72a0570a0 100644 --- a/src/commands/clear/conversation.ts +++ b/src/commands/clear/conversation.ts @@ -3,6 +3,7 @@ * This module has heavier dependencies and should be lazy-loaded when possible. */ import { feature } from 'bun:bundle' +import { setContextBlocked } from '../../proactive/index.js' import { randomUUID, type UUID } from 'crypto' import { getLastMainRequestId, @@ -110,9 +111,6 @@ export async function clearConversation({ // Clear context-blocked flag so proactive ticks resume after /clear if (feature('PROACTIVE') || feature('KAIROS')) { - /* eslint-disable @typescript-eslint/no-require-imports */ - const { setContextBlocked } = require('../../proactive/index.js') - /* eslint-enable @typescript-eslint/no-require-imports */ setContextBlocked(false) } diff --git a/src/commands/proactive.ts b/src/commands/proactive.ts index 3d63bb362..1a01665e6 100644 --- a/src/commands/proactive.ts +++ b/src/commands/proactive.ts @@ -11,6 +11,7 @@ import type { LocalJSXCommandContext, LocalJSXCommandOnDone, } from '../types/command.js' +import * as proactiveModuleValue from '../proactive/index.js' const proactive = { type: 'local-jsx', @@ -29,15 +30,11 @@ const proactive = { onDone: LocalJSXCommandOnDone, _context: ToolUseContext & LocalJSXCommandContext, ): Promise { - // Dynamic require to avoid pulling proactive into non-gated builds - const mod = - require('../proactive/index.js') as typeof import('../proactive/index.js') - - if (mod.isProactiveActive()) { - mod.deactivateProactive() + if (proactiveModuleValue.isProactiveActive()) { + proactiveModuleValue.deactivateProactive() onDone('Proactive mode disabled', { display: 'system' }) } else { - mod.activateProactive('slash_command') + proactiveModuleValue.activateProactive('slash_command') onDone( 'Proactive mode enabled — model will work autonomously between ticks', { diff --git a/src/commands/ultraplan.tsx b/src/commands/ultraplan.tsx index f794f01e0..255b67a22 100644 --- a/src/commands/ultraplan.tsx +++ b/src/commands/ultraplan.tsx @@ -25,6 +25,7 @@ import { ALL_MODEL_CONFIGS } from '../utils/model/configs.js'; import { updateTaskState } from '../utils/task/framework.js'; import { archiveRemoteSession, teleportToRemote } from '../utils/teleport.js'; import { pollForApprovedExitPlanMode, UltraplanPollError } from '../utils/ultraplan/ccrSession.js'; +import rawUltraplanPrompt from '../utils/ultraplan/prompt.txt'; // TODO(prod-hardening): OAuth token may go stale over the 30min poll; // consider refresh. @@ -51,11 +52,7 @@ function getUltraplanModel(): string { // any tag stripping, and a bare "ultraplan" in the prompt would self-trigger as // /ultraplan, which is filtered out of headless mode as "Unknown skill" // -// Bundler inlines .txt as a string; the test runner wraps it as {default}. -/* eslint-disable @typescript-eslint/no-require-imports */ -const _rawPrompt = require('../utils/ultraplan/prompt.txt'); -/* eslint-enable @typescript-eslint/no-require-imports */ -const DEFAULT_INSTRUCTIONS: string = (typeof _rawPrompt === 'string' ? _rawPrompt : _rawPrompt.default).trimEnd(); +const DEFAULT_INSTRUCTIONS: string = rawUltraplanPrompt.trimEnd(); // Dev-only prompt override resolved eagerly at module load. // Gated to ant builds (USER_TYPE is a build-time define, diff --git a/src/components/Messages.tsx b/src/components/Messages.tsx index a88274afd..a5f7876e5 100644 --- a/src/components/Messages.tsx +++ b/src/components/Messages.tsx @@ -69,6 +69,7 @@ import type { ToolUseConfirm } from './permissions/PermissionRequest.js' import { StatusNotices } from './StatusNotices.js' import type { JumpHandle } from './VirtualMessageList.js' import { VirtualMessageList } from './VirtualMessageList.js' +import * as proactiveModuleValue from '../proactive/index.js' // Memoed logo header: this box is the FIRST sibling before all MessageRows // in main-screen mode. If it becomes dirty on every Messages re-render, @@ -98,13 +99,10 @@ const LogoHeader = React.memo(function LogoHeader({ ) }) -// Dead code elimination: conditional import for proactive mode -/* eslint-disable @typescript-eslint/no-require-imports */ const proactiveModule = feature('PROACTIVE') || feature('KAIROS') - ? require('../proactive/index.js') + ? proactiveModuleValue : null -/* eslint-enable @typescript-eslint/no-require-imports */ const BRIEF_TOOL_NAME: string | null = feature('KAIROS') || feature('KAIROS_BRIEF') ? BRIEF_TOOL_NAME_VALUE : null diff --git a/src/components/PromptInput/PromptInputFooterLeftSide.tsx b/src/components/PromptInput/PromptInputFooterLeftSide.tsx index 8130c8ef1..20a7dc54e 100644 --- a/src/components/PromptInput/PromptInputFooterLeftSide.tsx +++ b/src/components/PromptInput/PromptInputFooterLeftSide.tsx @@ -51,14 +51,12 @@ import { isXtermJs, useHasSelection, useSelection } from '@anthropic/ink' import { getGlobalConfig, saveGlobalConfig } from '../../utils/config.js' import { getPlatform } from '../../utils/platform.js' import { PrBadge } from '../PrBadge.js' +import * as proactiveModuleValue from '../../proactive/index.js' -// Dead code elimination: conditional import for proactive mode -/* eslint-disable @typescript-eslint/no-require-imports */ const proactiveModule = feature('PROACTIVE') || feature('KAIROS') - ? require('../../proactive/index.js') + ? proactiveModuleValue : null -/* eslint-enable @typescript-eslint/no-require-imports */ const NO_OP_SUBSCRIBE = (_cb: () => void) => () => {} const NULL = () => null const MAX_VOICE_HINT_SHOWS = 3 diff --git a/src/components/PromptInput/usePromptInputPlaceholder.ts b/src/components/PromptInput/usePromptInputPlaceholder.ts index 36d8d362b..b27cccbac 100644 --- a/src/components/PromptInput/usePromptInputPlaceholder.ts +++ b/src/components/PromptInput/usePromptInputPlaceholder.ts @@ -5,12 +5,11 @@ import { useAppState } from 'src/state/AppState.js' import { getGlobalConfig } from 'src/utils/config.js' import { getExampleCommandFromCache } from 'src/utils/exampleCommands.js' import { isQueuedCommandEditable } from 'src/utils/messageQueueManager.js' +import * as proactiveModuleValue from '../../proactive/index.js' -// Dead code elimination: conditional import for proactive mode -/* eslint-disable @typescript-eslint/no-require-imports */ const proactiveModule = feature('PROACTIVE') || feature('KAIROS') - ? require('../../proactive/index.js') + ? proactiveModuleValue : null type Props = { diff --git a/src/components/permissions/ExitPlanModePermissionRequest/ExitPlanModePermissionRequest.tsx b/src/components/permissions/ExitPlanModePermissionRequest/ExitPlanModePermissionRequest.tsx index 657acf1e3..80d01b053 100644 --- a/src/components/permissions/ExitPlanModePermissionRequest/ExitPlanModePermissionRequest.tsx +++ b/src/components/permissions/ExitPlanModePermissionRequest/ExitPlanModePermissionRequest.tsx @@ -86,17 +86,16 @@ import { Markdown } from '../../Markdown.js' import { PermissionDialog } from '../PermissionDialog.js' import type { PermissionRequestProps } from '../PermissionRequest.js' import { PermissionRuleExplanation } from '../PermissionRuleExplanation.js' +import * as autoModeStateModuleValue from '../../../utils/permissions/autoModeState.js' -/* eslint-disable @typescript-eslint/no-require-imports */ const autoModeStateModule = feature('TRANSCRIPT_CLASSIFIER') - ? (require('../../../utils/permissions/autoModeState.js') as typeof import('../../../utils/permissions/autoModeState.js')) + ? autoModeStateModuleValue : null import type { Base64ImageSource, ImageBlockParam, } from '@anthropic-ai/sdk/resources/messages.mjs' -/* eslint-enable @typescript-eslint/no-require-imports */ import type { PastedContent } from '../../../utils/config.js' import type { ImageDimensions } from '../../../utils/imageResizer.js' import { maybeResizeAndDownsampleImageBlock } from '../../../utils/imageResizer.js' diff --git a/src/components/tasks/BackgroundTasksDialog.tsx b/src/components/tasks/BackgroundTasksDialog.tsx index 9d1d065e1..12b629260 100644 --- a/src/components/tasks/BackgroundTasksDialog.tsx +++ b/src/components/tasks/BackgroundTasksDialog.tsx @@ -28,8 +28,16 @@ import { LocalAgentTask } from 'src/tasks/LocalAgentTask/LocalAgentTask.js' import type { LocalShellTaskState } from 'src/tasks/LocalShellTask/guards.js' import { LocalShellTask } from 'src/tasks/LocalShellTask/LocalShellTask.js' // Type import is erased at build time — safe even though module is ant-gated. -import type { LocalWorkflowTaskState } from 'src/tasks/LocalWorkflowTask/LocalWorkflowTask.js' -import type { MonitorMcpTaskState } from 'src/tasks/MonitorMcpTask/MonitorMcpTask.js' +import { + killWorkflowTask as killWorkflowTaskValue, + retryWorkflowAgent as retryWorkflowAgentValue, + skipWorkflowAgent as skipWorkflowAgentValue, + type LocalWorkflowTaskState, +} from 'src/tasks/LocalWorkflowTask/LocalWorkflowTask.js' +import { + killMonitorMcp as killMonitorMcpValue, + type MonitorMcpTaskState, +} from 'src/tasks/MonitorMcpTask/MonitorMcpTask.js' import { RemoteAgentTask, type RemoteAgentTaskState, @@ -43,6 +51,8 @@ import type { DeepImmutable } from 'src/types/utils.js' import { intersperse } from 'src/utils/array.js' import { TEAM_LEAD_NAME } from 'src/utils/swarm/constants.js' import { stopUltraplan } from '../../commands/ultraplan.js' +import { MonitorMcpDetailDialog as MonitorMcpDetailDialogValue } from './MonitorMcpDetailDialog.js' +import { WorkflowDetailDialog as WorkflowDetailDialogValue } from './WorkflowDetailDialog.js' import type { CommandResultDisplay } from '../../commands.js' import { useRegisterOverlay } from '../../context/overlayContext.js' import type { ExitState } from '../../hooks/useExitOnCtrlCDWithKeybindings.js' @@ -129,31 +139,22 @@ type ListItem = // WORKFLOW_SCRIPTS is ant-only (build_flags.yaml). Static imports would leak // ~1.3K lines into external builds. Gate with feature() + require so the // bundler can dead-code-eliminate the branch. -/* eslint-disable @typescript-eslint/no-require-imports */ const WorkflowDetailDialog = feature('WORKFLOW_SCRIPTS') - ? ( - require('./WorkflowDetailDialog.js') as typeof import('./WorkflowDetailDialog.js') - ).WorkflowDetailDialog + ? WorkflowDetailDialogValue : null -const workflowTaskModule = feature('WORKFLOW_SCRIPTS') - ? (require('src/tasks/LocalWorkflowTask/LocalWorkflowTask.js') as typeof import('src/tasks/LocalWorkflowTask/LocalWorkflowTask.js')) +const killWorkflowTask = feature('WORKFLOW_SCRIPTS') + ? killWorkflowTaskValue : null -const killWorkflowTask = workflowTaskModule?.killWorkflowTask ?? null -const skipWorkflowAgent = workflowTaskModule?.skipWorkflowAgent ?? null -const retryWorkflowAgent = workflowTaskModule?.retryWorkflowAgent ?? null -// Relative path, not `src/...` path-mapping — Bun's DCE can statically -// resolve + eliminate `./` requires, but path-mapped strings stay opaque -// and survive as dead literals in the bundle. Matches tasks.ts pattern. -const monitorMcpModule = feature('MONITOR_TOOL') - ? (require('../../tasks/MonitorMcpTask/MonitorMcpTask.js') as typeof import('../../tasks/MonitorMcpTask/MonitorMcpTask.js')) +const skipWorkflowAgent = feature('WORKFLOW_SCRIPTS') + ? skipWorkflowAgentValue : null -const killMonitorMcp = monitorMcpModule?.killMonitorMcp ?? null +const retryWorkflowAgent = feature('WORKFLOW_SCRIPTS') + ? retryWorkflowAgentValue + : null +const killMonitorMcp = feature('MONITOR_TOOL') ? killMonitorMcpValue : null const MonitorMcpDetailDialog = feature('MONITOR_TOOL') - ? ( - require('./MonitorMcpDetailDialog.js') as typeof import('./MonitorMcpDetailDialog.js') - ).MonitorMcpDetailDialog + ? MonitorMcpDetailDialogValue : null -/* eslint-enable @typescript-eslint/no-require-imports */ // Helper to get filtered background tasks (excludes foregrounded local_agent) function getSelectableBackgroundTasks( diff --git a/src/constants/prompts.ts b/src/constants/prompts.ts index 02b6a2289..c85554219 100644 --- a/src/constants/prompts.ts +++ b/src/constants/prompts.ts @@ -61,6 +61,11 @@ import { loadMemoryPrompt } from '../memdir/memdir.js' import { isUndercover } from '../utils/undercover.js' import { getAntModelOverrideConfig } from '../utils/model/antModels.js' import { isMcpInstructionsDeltaEnabled } from '../utils/mcpInstructionsDelta.js' +import { BRIEF_PROACTIVE_SECTION as BRIEF_PROACTIVE_SECTION_VALUE } from '../tools/BriefTool/prompt.js' +import * as proactiveModuleValue from '../proactive/index.js' +import * as briefToolModuleValue from '../tools/BriefTool/BriefTool.js' +import { DISCOVER_SKILLS_TOOL_NAME as DISCOVER_SKILLS_TOOL_NAME_VALUE } from '../tools/DiscoverSkillsTool/prompt.js' +import * as skillSearchFeatureCheckValue from '../services/skillSearch/featureCheck.js' // Dead code elimination: conditional imports for feature-gated modules /* eslint-disable @typescript-eslint/no-require-imports */ @@ -71,30 +76,24 @@ const getCachedMCConfigForFRC = feature('CACHED_MICROCOMPACT') : null const proactiveModule = - feature('PROACTIVE') || feature('KAIROS') - ? require('../proactive/index.js') - : null + feature('PROACTIVE') || feature('KAIROS') ? proactiveModuleValue : null const BRIEF_PROACTIVE_SECTION: string | null = feature('KAIROS') || feature('KAIROS_BRIEF') - ? ( - require('../tools/BriefTool/prompt.js') as typeof import('../tools/BriefTool/prompt.js') - ).BRIEF_PROACTIVE_SECTION + ? BRIEF_PROACTIVE_SECTION_VALUE : null const briefToolModule = feature('KAIROS') || feature('KAIROS_BRIEF') - ? (require('../tools/BriefTool/BriefTool.js') as typeof import('../tools/BriefTool/BriefTool.js')) + ? briefToolModuleValue : null const DISCOVER_SKILLS_TOOL_NAME: string | null = feature( 'EXPERIMENTAL_SKILL_SEARCH', ) - ? ( - require('../tools/DiscoverSkillsTool/prompt.js') as typeof import('../tools/DiscoverSkillsTool/prompt.js') - ).DISCOVER_SKILLS_TOOL_NAME + ? DISCOVER_SKILLS_TOOL_NAME_VALUE : null // Capture the module (not .isSkillSearchEnabled directly) so spyOn() in tests // patches what we actually call — a captured function ref would point past the spy. const skillSearchFeatureCheck = feature('EXPERIMENTAL_SKILL_SEARCH') - ? (require('../services/skillSearch/featureCheck.js') as typeof import('../services/skillSearch/featureCheck.js')) + ? skillSearchFeatureCheckValue : null /* eslint-enable @typescript-eslint/no-require-imports */ import type { OutputStyleConfig } from './outputStyles.js' diff --git a/src/main.tsx b/src/main.tsx index 1c507cabf..89ab2693b 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -77,6 +77,10 @@ import { createSyntheticOutputTool, isSyntheticOutputToolEnabled, } from "./tools/SyntheticOutputTool/SyntheticOutputTool.js"; +import { + BRIEF_TOOL_NAME as BRIEF_TOOL_NAME_VALUE, + LEGACY_BRIEF_TOOL_NAME as LEGACY_BRIEF_TOOL_NAME_VALUE, +} from "./tools/BriefTool/prompt.js"; import { getTools } from "./tools.js"; import { canUserConfigureAdvisor, @@ -121,6 +125,10 @@ import { jsonParse, writeFileSync_DEPRECATED } from "./utils/slowOperations.js"; import { computeInitialTeamContext } from "./utils/swarm/reconnection.js"; import { initializeWarningHandler } from "./utils/warningHandler.js"; import { isWorktreeModeEnabled } from "./utils/worktreeModeEnabled.js"; +import * as coordinatorModeModuleValue from "./coordinator/coordinatorMode.js"; +import * as assistantModuleValue from "./assistant/index.js"; +import * as kairosGateValue from "./assistant/gate.js"; +import * as proactiveModuleValue from "./proactive/index.js"; // Lazy require to avoid circular dependency: teammate.ts -> AppState.tsx -> ... -> main.tsx /* eslint-disable @typescript-eslint/no-require-imports */ @@ -131,19 +139,14 @@ const getTeammatePromptAddendum = () => const getTeammateModeSnapshot = () => require("./utils/swarm/backends/teammateModeSnapshot.js") as typeof import("./utils/swarm/backends/teammateModeSnapshot.js"); /* eslint-enable @typescript-eslint/no-require-imports */ -// Dead code elimination: conditional import for COORDINATOR_MODE -/* eslint-disable @typescript-eslint/no-require-imports */ const coordinatorModeModule = feature("COORDINATOR_MODE") - ? (require("./coordinator/coordinatorMode.js") as typeof import("./coordinator/coordinatorMode.js")) + ? coordinatorModeModuleValue : null; -/* eslint-enable @typescript-eslint/no-require-imports */ -// Dead code elimination: conditional import for KAIROS (assistant mode) -/* eslint-disable @typescript-eslint/no-require-imports */ const assistantModule = feature("KAIROS") - ? (require("./assistant/index.js") as typeof import("./assistant/index.js")) + ? assistantModuleValue : null; const kairosGate = feature("KAIROS") - ? (require("./assistant/gate.js") as typeof import("./assistant/gate.js")) + ? kairosGateValue : null; import { relative, resolve } from "path"; @@ -382,10 +385,10 @@ import { setUserMsgOptIn, switchSession, } from "./bootstrap/state.js"; +import * as autoModeStateModuleValue from "./utils/permissions/autoModeState.js"; -/* eslint-disable @typescript-eslint/no-require-imports */ const autoModeStateModule = feature("TRANSCRIPT_CLASSIFIER") - ? (require("./utils/permissions/autoModeState.js") as typeof import("./utils/permissions/autoModeState.js")) + ? autoModeStateModuleValue : null; // TeleportRepoMismatchDialog, TeleportResumeWrapper dynamically imported at call sites @@ -2664,15 +2667,13 @@ async function run(): Promise { baseTools.length > 0 ) { /* eslint-disable @typescript-eslint/no-require-imports */ - const { BRIEF_TOOL_NAME, LEGACY_BRIEF_TOOL_NAME } = - require("./tools/BriefTool/prompt.js") as typeof import("./tools/BriefTool/prompt.js"); const { isBriefEntitled } = require("./tools/BriefTool/BriefTool.js") as typeof import("./tools/BriefTool/BriefTool.js"); /* eslint-enable @typescript-eslint/no-require-imports */ const parsed = parseToolListFromCLI(baseTools); if ( - (parsed.includes(BRIEF_TOOL_NAME) || - parsed.includes(LEGACY_BRIEF_TOOL_NAME)) && + (parsed.includes(BRIEF_TOOL_NAME_VALUE) || + parsed.includes(LEGACY_BRIEF_TOOL_NAME_VALUE)) && isBriefEntitled() ) { setUserMsgOptIn(true); @@ -6948,10 +6949,8 @@ function maybeActivateProactive(options: unknown): void { ((options as { proactive?: boolean }).proactive || isEnvTruthy(process.env.CLAUDE_CODE_PROACTIVE)) ) { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const proactiveModule = require("./proactive/index.js"); - if (!proactiveModule.isProactiveActive()) { - proactiveModule.activateProactive("command"); + if (!proactiveModuleValue.isProactiveActive()) { + proactiveModuleValue.activateProactive("command"); } } } diff --git a/src/query.ts b/src/query.ts index 52c64c5e9..0152ed6ca 100644 --- a/src/query.ts +++ b/src/query.ts @@ -65,12 +65,14 @@ import { getAttachmentMessages, startRelevantMemoryPrefetch, } from './utils/attachments.js' +import * as skillPrefetchValue from './services/skillSearch/prefetch.js' +import * as jobClassifierValue from './jobs/classifier.js' /* eslint-disable @typescript-eslint/no-require-imports */ const skillPrefetch = feature('EXPERIMENTAL_SKILL_SEARCH') - ? (require('./services/skillSearch/prefetch.js') as typeof import('./services/skillSearch/prefetch.js')) + ? skillPrefetchValue : null const jobClassifier = feature('TEMPLATES') - ? (require('./jobs/classifier.js') as typeof import('./jobs/classifier.js')) + ? jobClassifierValue : null /* eslint-enable @typescript-eslint/no-require-imports */ import { @@ -121,13 +123,14 @@ import { isLangfuseEnabled, } from './services/langfuse/index.js' import { getAPIProvider } from './utils/model/providers.js' +import * as taskSummaryModuleValue from './utils/taskSummary.js' /* eslint-disable @typescript-eslint/no-require-imports */ const snipModule = feature('HISTORY_SNIP') ? (require('./services/compact/snipCompact.js') as typeof import('./services/compact/snipCompact.js')) : null const taskSummaryModule = feature('BG_SESSIONS') - ? (require('./utils/taskSummary.js') as typeof import('./utils/taskSummary.js')) + ? taskSummaryModuleValue : null /* eslint-enable @typescript-eslint/no-require-imports */ diff --git a/src/query/stopHooks.ts b/src/query/stopHooks.ts index 457fe03ea..b6f8f1e29 100644 --- a/src/query/stopHooks.ts +++ b/src/query/stopHooks.ts @@ -37,13 +37,15 @@ import { import type { SystemPrompt } from '../utils/systemPromptType.js' import { getTaskListId, listTasks } from '../utils/tasks.js' import { getAgentName, getTeamName, isTeammate } from '../utils/teammate.js' +import * as extractMemoriesModuleValue from '../services/extractMemories/extractMemories.js' +import * as jobClassifierModuleValue from '../jobs/classifier.js' /* eslint-disable @typescript-eslint/no-require-imports */ const extractMemoriesModule = feature('EXTRACT_MEMORIES') - ? (require('../services/extractMemories/extractMemories.js') as typeof import('../services/extractMemories/extractMemories.js')) + ? extractMemoriesModuleValue : null const jobClassifierModule = feature('TEMPLATES') - ? (require('../jobs/classifier.js') as typeof import('../jobs/classifier.js')) + ? jobClassifierModuleValue : null /* eslint-enable @typescript-eslint/no-require-imports */ diff --git a/src/screens/REPL.tsx b/src/screens/REPL.tsx index 9e63d436e..7bb89d835 100644 --- a/src/screens/REPL.tsx +++ b/src/screens/REPL.tsx @@ -324,16 +324,16 @@ import { isBgSession, updateSessionName, updateSessionActivity } from '../utils/ import { isInProcessTeammateTask, type InProcessTeammateTaskState } from '../tasks/InProcessTeammateTask/types.js'; import { restoreRemoteAgentTasks } from '../tasks/RemoteAgentTask/RemoteAgentTask.js'; import { useInboxPoller } from '../hooks/useInboxPoller.js'; -// Dead code elimination: conditional import for loop mode -/* eslint-disable @typescript-eslint/no-require-imports */ -const proactiveModule = feature('PROACTIVE') || feature('KAIROS') ? require('../proactive/index.js') : null; +import * as proactiveModuleValue from '../proactive/index.js'; +import { useProactive as useProactiveValue } from '../proactive/useProactive.js'; +import { useScheduledTasks as useScheduledTasksValue } from '../hooks/useScheduledTasks.js'; +const proactiveModule = feature('PROACTIVE') || feature('KAIROS') ? proactiveModuleValue : null; const PROACTIVE_NO_OP_SUBSCRIBE = (_cb: () => void) => () => {}; const PROACTIVE_FALSE = () => false; const SUGGEST_BG_PR_NOOP = (_p: string, _n: string): boolean => false; const useProactive = - feature('PROACTIVE') || feature('KAIROS') ? require('../proactive/useProactive.js').useProactive : null; -const useScheduledTasks = feature('AGENT_TRIGGERS') ? require('../hooks/useScheduledTasks.js').useScheduledTasks : null; -/* eslint-enable @typescript-eslint/no-require-imports */ + feature('PROACTIVE') || feature('KAIROS') ? useProactiveValue : null; +const useScheduledTasks = feature('AGENT_TRIGGERS') ? useScheduledTasksValue : null; import { isAgentSwarmsEnabled } from '../utils/agentSwarmsEnabled.js'; import { useTaskListWatcher } from '../hooks/useTaskListWatcher.js'; import type { SandboxAskCallback, NetworkHostPattern } from '../utils/sandbox/sandbox-adapter.js'; diff --git a/src/services/analytics/metadata.ts b/src/services/analytics/metadata.ts index b83e96aa3..c6c6bb02c 100644 --- a/src/services/analytics/metadata.ts +++ b/src/services/analytics/metadata.ts @@ -40,6 +40,7 @@ import { isTeammate, } from '../../utils/teammate.js' import { feature } from 'bun:bundle' +import { COMPUTER_USE_MCP_SERVER_NAME } from '../../utils/computerUse/common.js' /** * Marker type for verifying analytics metadata doesn't contain sensitive data @@ -125,17 +126,9 @@ export function isAnalyticsToolDetailsLoggingEnabled( * reservation (main.tsx, config.ts addMcpServer) is itself feature-gated, so * a user-configured 'computer-use' is possible in builds without the feature. */ -/* eslint-disable @typescript-eslint/no-require-imports */ const BUILTIN_MCP_SERVER_NAMES: ReadonlySet = new Set( - feature('CHICAGO_MCP') - ? [ - ( - require('../../utils/computerUse/common.js') as typeof import('../../utils/computerUse/common.js') - ).COMPUTER_USE_MCP_SERVER_NAME, - ] - : [], + feature('CHICAGO_MCP') ? [COMPUTER_USE_MCP_SERVER_NAME] : [], ) -/* eslint-enable @typescript-eslint/no-require-imports */ /** * Spreadable helper for logEvent payloads — returns {mcpServerName, mcpToolName} diff --git a/src/services/api/claude.ts b/src/services/api/claude.ts index 58cf2222c..3eb8f5023 100644 --- a/src/services/api/claude.ts +++ b/src/services/api/claude.ts @@ -101,10 +101,10 @@ import { extractQuotaStatusFromHeaders, } from '../claudeAiLimits.js' import { getAPIContextManagement } from '../compact/apiMicrocompact.js' +import * as autoModeStateModuleValue from '../../utils/permissions/autoModeState.js' -/* eslint-disable @typescript-eslint/no-require-imports */ const autoModeStateModule = feature('TRANSCRIPT_CLASSIFIER') - ? (require('../../utils/permissions/autoModeState.js') as typeof import('../../utils/permissions/autoModeState.js')) + ? autoModeStateModuleValue : null import { feature } from 'bun:bundle' diff --git a/src/services/compact/compact.ts b/src/services/compact/compact.ts index c0f195e07..7a30be5ce 100644 --- a/src/services/compact/compact.ts +++ b/src/services/compact/compact.ts @@ -1,12 +1,11 @@ import { feature } from 'bun:bundle' import type { UUID } from 'crypto' import uniqBy from 'lodash-es/uniqBy.js' +import * as sessionTranscriptModuleValue from '../sessionTranscript/sessionTranscript.js' -/* eslint-disable @typescript-eslint/no-require-imports */ const sessionTranscriptModule = feature('KAIROS') - ? (require('../sessionTranscript/sessionTranscript.js') as typeof import('../sessionTranscript/sessionTranscript.js')) + ? sessionTranscriptModuleValue : null - import { APIUserAbortError } from '@anthropic-ai/sdk' import { markPostCompaction } from 'src/bootstrap/state.js' import { getInvokedSkillsForAgent } from '../../bootstrap/state.js' diff --git a/src/services/compact/prompt.ts b/src/services/compact/prompt.ts index 6276b1a9b..0a746d464 100644 --- a/src/services/compact/prompt.ts +++ b/src/services/compact/prompt.ts @@ -1,13 +1,11 @@ import { feature } from 'bun:bundle' import type { PartialCompactDirection } from '../../types/message.js' +import * as proactiveModuleValue from '../../proactive/index.js' -// Dead code elimination: conditional import for proactive mode -/* eslint-disable @typescript-eslint/no-require-imports */ const proactiveModule = feature('PROACTIVE') || feature('KAIROS') - ? (require('../../proactive/index.js') as typeof import('../../proactive/index.js')) + ? proactiveModuleValue : null -/* eslint-enable @typescript-eslint/no-require-imports */ // Aggressive no-tools preamble. The cache-sharing fork path inherits the // parent's full tool set (required for cache-key match), and on Sonnet 4.6+ diff --git a/src/services/mcp/client.ts b/src/services/mcp/client.ts index d6db09b38..b9d8072c0 100644 --- a/src/services/mcp/client.ts +++ b/src/services/mcp/client.ts @@ -230,6 +230,7 @@ function getMcpToolTimeoutMs(): number { } import { isClaudeInChromeMCPServer } from '../../utils/claudeInChrome/common.js' +import { isComputerUseMCPServer as isComputerUseMCPServerValue } from '../../utils/computerUse/common.js' // Lazy: toolRendering.tsx pulls React/ink; only needed when Claude-in-Chrome MCP server is connected /* eslint-disable @typescript-eslint/no-require-imports */ @@ -244,9 +245,7 @@ const computerUseWrapper = feature('CHICAGO_MCP') require('../../utils/computerUse/wrapper.js') : undefined const isComputerUseMCPServer = feature('CHICAGO_MCP') - ? ( - require('../../utils/computerUse/common.js') as typeof import('../../utils/computerUse/common.js') - ).isComputerUseMCPServer + ? isComputerUseMCPServerValue : undefined import { mkdir, readFile, unlink, writeFile } from 'fs/promises' diff --git a/src/services/mcp/config.ts b/src/services/mcp/config.ts index 288f9e0ce..6fb12d04b 100644 --- a/src/services/mcp/config.ts +++ b/src/services/mcp/config.ts @@ -19,6 +19,7 @@ import { getErrnoCode } from '../../utils/errors.js' import { getFsImplementation } from '../../utils/fsOperations.js' import { safeParseJSON } from '../../utils/json.js' import { logError } from '../../utils/log.js' +import { COMPUTER_USE_MCP_SERVER_NAME } from '../../utils/computerUse/common.js' import { getPluginMcpServers } from '../../utils/plugins/mcpPluginIntegration.js' import { loadAllPluginsCacheOnly } from '../../utils/plugins/pluginLoader.js' import { isSettingSourceEnabled } from '../../utils/settings/constants.js' @@ -1509,13 +1510,9 @@ export function areMcpConfigsAllowedWithEnterpriseMcpConfig( * (opt-out via disabledMcpServers), this requires explicit opt-in via * enabledMcpServers. Shows up in /mcp as disabled until the user enables it. */ -/* eslint-disable @typescript-eslint/no-require-imports */ const DEFAULT_DISABLED_BUILTIN = feature('CHICAGO_MCP') - ? ( - require('../../utils/computerUse/common.js') as typeof import('../../utils/computerUse/common.js') - ).COMPUTER_USE_MCP_SERVER_NAME + ? COMPUTER_USE_MCP_SERVER_NAME : null -/* eslint-enable @typescript-eslint/no-require-imports */ function isDefaultDisabledBuiltin(name: string): boolean { return DEFAULT_DISABLED_BUILTIN !== null && name === DEFAULT_DISABLED_BUILTIN diff --git a/src/services/mcp/useManageMCPConnections.ts b/src/services/mcp/useManageMCPConnections.ts index 80b82d688..a51bd27db 100644 --- a/src/services/mcp/useManageMCPConnections.ts +++ b/src/services/mcp/useManageMCPConnections.ts @@ -3,6 +3,7 @@ import { basename } from 'path' import { useCallback, useEffect, useRef } from 'react' import { getSessionId } from '../../bootstrap/state.js' import type { Command } from '../../commands.js' +import { clearSkillIndexCache as clearSkillIndexCacheValue } from '../skillSearch/localSearch.js' import type { Tool } from '../../Tool.js' import { clearServerCache, @@ -25,9 +26,7 @@ const fetchMcpSkillsForClient = feature('MCP_SKILLS') ).fetchMcpSkillsForClient : null const clearSkillIndexCache = feature('EXPERIMENTAL_SKILL_SEARCH') - ? ( - require('../skillSearch/localSearch.js') as typeof import('../skillSearch/localSearch.js') - ).clearSkillIndexCache + ? clearSkillIndexCacheValue : null import { diff --git a/src/state/AppState.tsx b/src/state/AppState.tsx index 783170cc3..5a58ca29b 100644 --- a/src/state/AppState.tsx +++ b/src/state/AppState.tsx @@ -7,6 +7,7 @@ import React, { useSyncExternalStore, } from 'react' import { MailboxProvider } from '../context/mailbox.js' +import { VoiceProvider as VoiceProviderValue } from '../context/voice.js' import { useSettingsChange } from '../hooks/useSettingsChange.js' import { logForDebugging } from '../utils/debug.js' import { @@ -17,14 +18,8 @@ import { applySettingsChange } from '../utils/settings/applySettingsChange.js' import type { SettingSource } from '../utils/settings/constants.js' import { createStore } from './store.js' -// DCE: voice context is ant-only. External builds get a passthrough. -/* eslint-disable @typescript-eslint/no-require-imports */ const VoiceProvider: (props: { children: React.ReactNode }) => React.ReactNode = - feature('VOICE_MODE') - ? require('../context/voice.js').VoiceProvider - : ({ children }) => children - -/* eslint-enable @typescript-eslint/no-require-imports */ + feature('VOICE_MODE') ? VoiceProviderValue : ({ children }) => children import { type AppState, type AppStateStore, diff --git a/src/tasks.ts b/src/tasks.ts index 9ac219987..103fa203b 100644 --- a/src/tasks.ts +++ b/src/tasks.ts @@ -5,14 +5,8 @@ import { LocalAgentTask } from './tasks/LocalAgentTask/LocalAgentTask.js' import { LocalShellTask } from './tasks/LocalShellTask/LocalShellTask.js' import { RemoteAgentTask } from './tasks/RemoteAgentTask/RemoteAgentTask.js' -/* eslint-disable @typescript-eslint/no-require-imports */ -const LocalWorkflowTask: Task | null = feature('WORKFLOW_SCRIPTS') - ? require('./tasks/LocalWorkflowTask/LocalWorkflowTask.js').LocalWorkflowTask - : null -const MonitorMcpTask: Task | null = feature('MONITOR_TOOL') - ? require('./tasks/MonitorMcpTask/MonitorMcpTask.js').MonitorMcpTask - : null -/* eslint-enable @typescript-eslint/no-require-imports */ +const LocalWorkflowTask: Task | null = feature('WORKFLOW_SCRIPTS') ? null : null +const MonitorMcpTask: Task | null = feature('MONITOR_TOOL') ? null : null /** * Get all tasks. diff --git a/src/tools.ts b/src/tools.ts index 04de65b19..576ae6938 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -11,6 +11,20 @@ import { NotebookEditTool } from './tools/NotebookEditTool/NotebookEditTool.js' import { WebFetchTool } from './tools/WebFetchTool/WebFetchTool.js' import { TaskStopTool } from './tools/TaskStopTool/TaskStopTool.js' import { BriefTool } from './tools/BriefTool/BriefTool.js' +import { SleepTool as SleepToolValue } from './tools/SleepTool/SleepTool.js' +import { CronCreateTool } from './tools/ScheduleCronTool/CronCreateTool.js' +import { CronDeleteTool } from './tools/ScheduleCronTool/CronDeleteTool.js' +import { CronListTool } from './tools/ScheduleCronTool/CronListTool.js' +import { RemoteTriggerTool as RemoteTriggerToolValue } from './tools/RemoteTriggerTool/RemoteTriggerTool.js' +import { MonitorTool as MonitorToolValue } from './tools/MonitorTool/MonitorTool.js' +import { SendUserFileTool as SendUserFileToolValue } from './tools/SendUserFileTool/SendUserFileTool.js' +import { PushNotificationTool as PushNotificationToolValue } from './tools/PushNotificationTool/PushNotificationTool.js' +import { TeamCreateTool as TeamCreateToolValue } from './tools/TeamCreateTool/TeamCreateTool.js' +import { TeamDeleteTool as TeamDeleteToolValue } from './tools/TeamDeleteTool/TeamDeleteTool.js' +import { SendMessageTool as SendMessageToolValue } from './tools/SendMessageTool/SendMessageTool.js' +import { initBundledWorkflows } from './tools/WorkflowTool/bundled/index.js' +import { WorkflowTool as WorkflowToolValue } from './tools/WorkflowTool/WorkflowTool.js' +import * as coordinatorModeModuleValue from './coordinator/coordinatorMode.js' // Dead code elimination: conditional import for ant-only tools /* eslint-disable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */ const REPLTool = @@ -23,27 +37,20 @@ const SuggestBackgroundPRTool = .SuggestBackgroundPRTool : null const SleepTool = - feature('PROACTIVE') || feature('KAIROS') - ? require('./tools/SleepTool/SleepTool.js').SleepTool - : null -const cronTools = [ - require('./tools/ScheduleCronTool/CronCreateTool.js').CronCreateTool, - require('./tools/ScheduleCronTool/CronDeleteTool.js').CronDeleteTool, - require('./tools/ScheduleCronTool/CronListTool.js').CronListTool, -] + feature('PROACTIVE') || feature('KAIROS') ? SleepToolValue : null +const cronTools = [CronCreateTool, CronDeleteTool, CronListTool] const RemoteTriggerTool = feature('AGENT_TRIGGERS_REMOTE') - ? require('./tools/RemoteTriggerTool/RemoteTriggerTool.js').RemoteTriggerTool + ? RemoteTriggerToolValue : null const MonitorTool = feature('MONITOR_TOOL') - ? require('./tools/MonitorTool/MonitorTool.js').MonitorTool + ? MonitorToolValue : null const SendUserFileTool = feature('KAIROS') - ? require('./tools/SendUserFileTool/SendUserFileTool.js').SendUserFileTool + ? SendUserFileToolValue : null const PushNotificationTool = feature('KAIROS') || feature('KAIROS_PUSH_NOTIFICATION') - ? require('./tools/PushNotificationTool/PushNotificationTool.js') - .PushNotificationTool + ? PushNotificationToolValue : null const SubscribePRTool = feature('KAIROS_GITHUB_WEBHOOKS') ? require('./tools/SubscribePRTool/SubscribePRTool.js').SubscribePRTool @@ -56,18 +63,9 @@ import { ExitPlanModeV2Tool } from './tools/ExitPlanModeTool/ExitPlanModeV2Tool. import { TestingPermissionTool } from './tools/testing/TestingPermissionTool.js' import { GrepTool } from './tools/GrepTool/GrepTool.js' import { TungstenTool } from './tools/TungstenTool/TungstenTool.js' -// Lazy require to break circular dependency: tools.ts -> TeamCreateTool/TeamDeleteTool -> ... -> tools.ts -/* eslint-disable @typescript-eslint/no-require-imports */ -const getTeamCreateTool = () => - require('./tools/TeamCreateTool/TeamCreateTool.js') - .TeamCreateTool as typeof import('./tools/TeamCreateTool/TeamCreateTool.js').TeamCreateTool -const getTeamDeleteTool = () => - require('./tools/TeamDeleteTool/TeamDeleteTool.js') - .TeamDeleteTool as typeof import('./tools/TeamDeleteTool/TeamDeleteTool.js').TeamDeleteTool -const getSendMessageTool = () => - require('./tools/SendMessageTool/SendMessageTool.js') - .SendMessageTool as typeof import('./tools/SendMessageTool/SendMessageTool.js').SendMessageTool -/* eslint-enable @typescript-eslint/no-require-imports */ +const getTeamCreateTool = () => TeamCreateToolValue +const getTeamDeleteTool = () => TeamDeleteToolValue +const getSendMessageTool = () => SendMessageToolValue import { AskUserQuestionTool } from './tools/AskUserQuestionTool/AskUserQuestionTool.js' import { LSPTool } from './tools/LSPTool/LSPTool.js' import { ListMcpResourcesTool } from './tools/ListMcpResourcesTool/ListMcpResourcesTool.js' @@ -116,7 +114,7 @@ const WebBrowserTool = feature('WEB_BROWSER_TOOL') ? require('./tools/WebBrowserTool/WebBrowserTool.js').WebBrowserTool : null const coordinatorModeModule = feature('COORDINATOR_MODE') - ? (require('./coordinator/coordinatorMode.js') as typeof import('./coordinator/coordinatorMode.js')) + ? coordinatorModeModuleValue : null const SnipTool = feature('HISTORY_SNIP') ? require('./tools/SnipTool/SnipTool.js').SnipTool @@ -126,8 +124,8 @@ const ListPeersTool = feature('UDS_INBOX') : null const WorkflowTool = feature('WORKFLOW_SCRIPTS') ? (() => { - require('./tools/WorkflowTool/bundled/index.js').initBundledWorkflows() - return require('./tools/WorkflowTool/WorkflowTool.js').WorkflowTool + initBundledWorkflows() + return WorkflowToolValue })() : null /* eslint-enable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */ diff --git a/src/tools/AgentTool/AgentTool.tsx b/src/tools/AgentTool/AgentTool.tsx index 8e4ac12d3..0a421d890 100644 --- a/src/tools/AgentTool/AgentTool.tsx +++ b/src/tools/AgentTool/AgentTool.tsx @@ -132,13 +132,12 @@ import { userFacingName, userFacingNameBackgroundColor, } from './UI.js' +import * as proactiveModuleValue from '../../proactive/index.js' -/* eslint-disable @typescript-eslint/no-require-imports */ const proactiveModule = feature('PROACTIVE') || feature('KAIROS') - ? (require('../../proactive/index.js') as typeof import('../../proactive/index.js')) + ? proactiveModuleValue : null -/* eslint-enable @typescript-eslint/no-require-imports */ // Progress display constants (for showing background hint) const PROGRESS_THRESHOLD_MS = 2000 // Show background hint after 2 seconds diff --git a/src/tools/AgentTool/runAgent.ts b/src/tools/AgentTool/runAgent.ts index 5e96d7db0..7543a3cce 100644 --- a/src/tools/AgentTool/runAgent.ts +++ b/src/tools/AgentTool/runAgent.ts @@ -27,6 +27,7 @@ import type { } from '../../services/mcp/types.js' import type { Tool, Tools, ToolUseContext } from '../../Tool.js' import { killShellTasksForAgent } from '../../tasks/LocalShellTask/killShellTasks.js' +import { killMonitorMcpTasksForAgent } from '../../tasks/MonitorMcpTask/MonitorMcpTask.js' import type { Command } from '../../types/command.js' import type { AgentId } from '../../types/ids.js' import type { @@ -872,17 +873,13 @@ export async function* runAgent({ // `run_in_background` shell loop (e.g. test fixture fake-logs.sh) outlives // the agent as a PPID=1 zombie once the main session eventually exits. killShellTasksForAgent(agentId, toolUseContext.getAppState, rootSetAppState) - /* eslint-disable @typescript-eslint/no-require-imports */ if (feature('MONITOR_TOOL')) { - const mcpMod = - require('../../tasks/MonitorMcpTask/MonitorMcpTask.js') as typeof import('../../tasks/MonitorMcpTask/MonitorMcpTask.js') - mcpMod.killMonitorMcpTasksForAgent( + killMonitorMcpTasksForAgent( agentId, toolUseContext.getAppState, rootSetAppState, ) } - /* eslint-enable @typescript-eslint/no-require-imports */ } } diff --git a/src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.ts b/src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.ts index 5aa83c125..81d20d8b0 100644 --- a/src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.ts +++ b/src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.ts @@ -47,15 +47,15 @@ import { renderToolUseMessage, renderToolUseRejectedMessage, } from './UI.js' +import * as autoModeStateModuleValue from '../../utils/permissions/autoModeState.js' +import * as permissionSetupModuleValue from '../../utils/permissions/permissionSetup.js' -/* eslint-disable @typescript-eslint/no-require-imports */ const autoModeStateModule = feature('TRANSCRIPT_CLASSIFIER') - ? (require('../../utils/permissions/autoModeState.js') as typeof import('../../utils/permissions/autoModeState.js')) + ? autoModeStateModuleValue : null const permissionSetupModule = feature('TRANSCRIPT_CLASSIFIER') - ? (require('../../utils/permissions/permissionSetup.js') as typeof import('../../utils/permissions/permissionSetup.js')) + ? permissionSetupModuleValue : null -/* eslint-enable @typescript-eslint/no-require-imports */ /** * Schema for prompt-based permission requests. diff --git a/src/tools/SkillTool/SkillTool.ts b/src/tools/SkillTool/SkillTool.ts index c7149141d..4b6366ac1 100644 --- a/src/tools/SkillTool/SkillTool.ts +++ b/src/tools/SkillTool/SkillTool.ts @@ -33,6 +33,10 @@ import { parsePluginIdentifier, } from 'src/utils/plugins/pluginIdentifier.js' import { buildPluginCommandTelemetryFields } from 'src/utils/telemetry/pluginTelemetry.js' +import * as remoteSkillFeatureCheck from '../../services/skillSearch/featureCheck.js' +import * as remoteSkillLoader from '../../services/skillSearch/remoteSkillLoader.js' +import * as remoteSkillState from '../../services/skillSearch/remoteSkillState.js' +import * as remoteSkillTelemetry from '../../services/skillSearch/telemetry.js' import { z } from 'zod/v4' import { addInvokedSkill, @@ -104,16 +108,14 @@ import type { SkillToolProgress as Progress } from '../../types/tools.js' // side-effecting initializers. All usages are inside // feature('EXPERIMENTAL_SKILL_SEARCH') guards, so remoteSkillModules is // non-null at every call site. -/* eslint-disable @typescript-eslint/no-require-imports */ const remoteSkillModules = feature('EXPERIMENTAL_SKILL_SEARCH') ? { - ...(require('../../services/skillSearch/remoteSkillState.js') as typeof import('../../services/skillSearch/remoteSkillState.js')), - ...(require('../../services/skillSearch/remoteSkillLoader.js') as typeof import('../../services/skillSearch/remoteSkillLoader.js')), - ...(require('../../services/skillSearch/telemetry.js') as typeof import('../../services/skillSearch/telemetry.js')), - ...(require('../../services/skillSearch/featureCheck.js') as typeof import('../../services/skillSearch/featureCheck.js')), + ...remoteSkillState, + ...remoteSkillLoader, + ...remoteSkillTelemetry, + ...remoteSkillFeatureCheck, } : null -/* eslint-enable @typescript-eslint/no-require-imports */ /** * Executes a skill in a forked sub-agent context. diff --git a/src/tools/SleepTool/SleepTool.ts b/src/tools/SleepTool/SleepTool.ts index 75ee0bf9d..6dc9433c5 100644 --- a/src/tools/SleepTool/SleepTool.ts +++ b/src/tools/SleepTool/SleepTool.ts @@ -4,6 +4,7 @@ import type { ToolResultBlockParam } from '@anthropic-ai/sdk/resources/index.mjs import { buildTool } from '../../Tool.js' import { lazySchema } from '../../utils/lazySchema.js' import { SLEEP_TOOL_NAME, DESCRIPTION, SLEEP_TOOL_PROMPT } from './prompt.js' +import * as proactiveModuleValue from '../../proactive/index.js' const inputSchema = lazySchema(() => z.strictObject({ @@ -70,9 +71,7 @@ export const SleepTool = buildTool({ // Refuse to sleep when proactive mode is off — prevents the model from // re-issuing Sleep after an interruption caused by /proactive disable. if (feature('PROACTIVE') || feature('KAIROS')) { - const mod = - require('../../proactive/index.js') as typeof import('../../proactive/index.js') - if (!mod.isProactiveActive()) { + if (!proactiveModuleValue.isProactiveActive()) { return { data: { slept_seconds: 0, @@ -105,9 +104,7 @@ export const SleepTool = buildTool({ const proactiveCheck = feature('PROACTIVE') || feature('KAIROS') ? setInterval(() => { - const mod = - require('../../proactive/index.js') as typeof import('../../proactive/index.js') - if (!mod.isProactiveActive()) { + if (!proactiveModuleValue.isProactiveActive()) { clearTimeout(timer) clearInterval(proactiveCheck) reject(new Error('interrupted')) diff --git a/src/tools/ToolSearchTool/prompt.ts b/src/tools/ToolSearchTool/prompt.ts index ca3e6b07b..fd5debdab 100644 --- a/src/tools/ToolSearchTool/prompt.ts +++ b/src/tools/ToolSearchTool/prompt.ts @@ -3,23 +3,18 @@ import { isReplBridgeActive } from '../../bootstrap/state.js' import { getFeatureValue_CACHED_MAY_BE_STALE } from '../../services/analytics/growthbook.js' import type { Tool } from '../../Tool.js' import { AGENT_TOOL_NAME } from '../AgentTool/constants.js' +import { BRIEF_TOOL_NAME as BRIEF_TOOL_NAME_VALUE } from '../BriefTool/prompt.js' +import { SEND_USER_FILE_TOOL_NAME as SEND_USER_FILE_TOOL_NAME_VALUE } from '../SendUserFileTool/prompt.js' -// Dead code elimination: Brief tool name only needed when KAIROS or KAIROS_BRIEF is on -/* eslint-disable @typescript-eslint/no-require-imports */ +// Dead code elimination: Brief tool names are only used when KAIROS/KAIROS_BRIEF is on. const BRIEF_TOOL_NAME: string | null = feature('KAIROS') || feature('KAIROS_BRIEF') - ? ( - require('../BriefTool/prompt.js') as typeof import('../BriefTool/prompt.js') - ).BRIEF_TOOL_NAME + ? BRIEF_TOOL_NAME_VALUE : null const SEND_USER_FILE_TOOL_NAME: string | null = feature('KAIROS') - ? ( - require('../SendUserFileTool/prompt.js') as typeof import('../SendUserFileTool/prompt.js') - ).SEND_USER_FILE_TOOL_NAME + ? SEND_USER_FILE_TOOL_NAME_VALUE : null -/* eslint-enable @typescript-eslint/no-require-imports */ - export { TOOL_SEARCH_TOOL_NAME } from './constants.js' import { TOOL_SEARCH_TOOL_NAME } from './constants.js' diff --git a/src/utils/attachments.ts b/src/utils/attachments.ts index 2d697f581..738bdbf06 100644 --- a/src/utils/attachments.ts +++ b/src/utils/attachments.ts @@ -86,6 +86,10 @@ import { getProjectRoot } from '../bootstrap/state.js' import { formatCommandsWithinBudget } from '../tools/SkillTool/prompt.js' import { getContextWindowForModel } from './context.js' import type { DiscoverySignal } from '../services/skillSearch/signals.js' +import * as skillSearchFeatureCheck from '../services/skillSearch/featureCheck.js' +import * as skillSearchPrefetch from '../services/skillSearch/prefetch.js' +import { BRIEF_TOOL_NAME as BRIEF_TOOL_NAME_VALUE } from '../tools/BriefTool/prompt.js' +import * as autoModeStateModuleValue from './permissions/autoModeState.js' // Conditional require for DCE. All skill-search string literals that would // otherwise leak into external builds live inside these modules. The only // surfaces in THIS file are: the maybe() call (gated via spread below) and @@ -94,14 +98,12 @@ import type { DiscoverySignal } from '../services/skillSearch/signals.js' /* eslint-disable @typescript-eslint/no-require-imports */ const skillSearchModules = feature('EXPERIMENTAL_SKILL_SEARCH') ? { - featureCheck: - require('../services/skillSearch/featureCheck.js') as typeof import('../services/skillSearch/featureCheck.js'), - prefetch: - require('../services/skillSearch/prefetch.js') as typeof import('../services/skillSearch/prefetch.js'), + featureCheck: skillSearchFeatureCheck, + prefetch: skillSearchPrefetch, } : null const autoModeStateModule = feature('TRANSCRIPT_CLASSIFIER') - ? (require('./permissions/autoModeState.js') as typeof import('./permissions/autoModeState.js')) + ? autoModeStateModuleValue : null /* eslint-enable @typescript-eslint/no-require-imports */ import { @@ -196,15 +198,14 @@ import { import { isHumanTurn } from './messagePredicates.js' import { isEnvTruthy, getClaudeConfigHomeDir } from './envUtils.js' import { feature } from 'bun:bundle' +import * as sessionTranscriptModuleValue from '../services/sessionTranscript/sessionTranscript.js' /* eslint-disable @typescript-eslint/no-require-imports */ const BRIEF_TOOL_NAME: string | null = feature('KAIROS') || feature('KAIROS_BRIEF') - ? ( - require('../tools/BriefTool/prompt.js') as typeof import('../tools/BriefTool/prompt.js') - ).BRIEF_TOOL_NAME + ? BRIEF_TOOL_NAME_VALUE : null const sessionTranscriptModule = feature('KAIROS') - ? (require('../services/sessionTranscript/sessionTranscript.js') as typeof import('../services/sessionTranscript/sessionTranscript.js')) + ? sessionTranscriptModuleValue : null /* eslint-enable @typescript-eslint/no-require-imports */ import { hasUltrathinkKeyword, isUltrathinkEnabled } from './thinking.js' diff --git a/src/utils/backgroundHousekeeping.ts b/src/utils/backgroundHousekeeping.ts index fa5672132..bddde2c1b 100644 --- a/src/utils/backgroundHousekeeping.ts +++ b/src/utils/backgroundHousekeeping.ts @@ -1,11 +1,12 @@ import { feature } from 'bun:bundle' import { initAutoDream } from '../services/autoDream/autoDream.js' +import * as extractMemoriesModuleValue from '../services/extractMemories/extractMemories.js' import { initMagicDocs } from '../services/MagicDocs/magicDocs.js' import { initSkillImprovement } from './hooks/skillImprovement.js' /* eslint-disable @typescript-eslint/no-require-imports */ const extractMemoriesModule = feature('EXTRACT_MEMORIES') - ? (require('../services/extractMemories/extractMemories.js') as typeof import('../services/extractMemories/extractMemories.js')) + ? extractMemoriesModuleValue : null const registerProtocolModule = feature('LODESTONE') ? (require('./deepLink/registerProtocol.js') as typeof import('./deepLink/registerProtocol.js')) diff --git a/src/utils/conversationRecovery.ts b/src/utils/conversationRecovery.ts index 4afbd2862..8630014fd 100644 --- a/src/utils/conversationRecovery.ts +++ b/src/utils/conversationRecovery.ts @@ -3,6 +3,11 @@ import type { UUID } from 'crypto' import { relative } from 'path' import { getCwd } from 'src/utils/cwd.js' import { addInvokedSkill } from '../bootstrap/state.js' +import { + BRIEF_TOOL_NAME as BRIEF_TOOL_NAME_VALUE, + LEGACY_BRIEF_TOOL_NAME as LEGACY_BRIEF_TOOL_NAME_VALUE, +} from '../tools/BriefTool/prompt.js' +import { SEND_USER_FILE_TOOL_NAME as SEND_USER_FILE_TOOL_NAME_VALUE } from '../tools/SendUserFileTool/prompt.js' import { asSessionId } from '../types/ids.js' import type { AttributionSnapshotMessage, @@ -49,27 +54,17 @@ import { } from './sessionStorage.js' import type { ContentReplacementRecord } from './toolResultStorage.js' -// Dead code elimination: ant-only tool names are conditionally required so -// their strings don't leak into external builds. Static imports always bundle. -/* eslint-disable @typescript-eslint/no-require-imports */ const BRIEF_TOOL_NAME: string | null = feature('KAIROS') || feature('KAIROS_BRIEF') - ? ( - require('../tools/BriefTool/prompt.js') as typeof import('../tools/BriefTool/prompt.js') - ).BRIEF_TOOL_NAME + ? BRIEF_TOOL_NAME_VALUE : null const LEGACY_BRIEF_TOOL_NAME: string | null = feature('KAIROS') || feature('KAIROS_BRIEF') - ? ( - require('../tools/BriefTool/prompt.js') as typeof import('../tools/BriefTool/prompt.js') - ).LEGACY_BRIEF_TOOL_NAME + ? LEGACY_BRIEF_TOOL_NAME_VALUE : null const SEND_USER_FILE_TOOL_NAME: string | null = feature('KAIROS') - ? ( - require('../tools/SendUserFileTool/prompt.js') as typeof import('../tools/SendUserFileTool/prompt.js') - ).SEND_USER_FILE_TOOL_NAME + ? SEND_USER_FILE_TOOL_NAME_VALUE : null -/* eslint-enable @typescript-eslint/no-require-imports */ /** * Transforms legacy attachment types to current types for backward compatibility diff --git a/src/utils/permissions/classifierDecision.ts b/src/utils/permissions/classifierDecision.ts index d329ebafd..7fed806bc 100644 --- a/src/utils/permissions/classifierDecision.ts +++ b/src/utils/permissions/classifierDecision.ts @@ -19,6 +19,7 @@ import { TEAM_CREATE_TOOL_NAME } from '../../tools/TeamCreateTool/constants.js' import { TEAM_DELETE_TOOL_NAME } from '../../tools/TeamDeleteTool/constants.js' import { TODO_WRITE_TOOL_NAME } from '../../tools/TodoWriteTool/constants.js' import { TOOL_SEARCH_TOOL_NAME } from '../../tools/ToolSearchTool/prompt.js' +import { WORKFLOW_TOOL_NAME as WORKFLOW_TOOL_NAME_VALUE } from '../../tools/WorkflowTool/constants.js' import { YOLO_CLASSIFIER_TOOL_NAME } from './yoloClassifier.js' // Ant-only tool names: conditional require so Bun can DCE these in external builds. @@ -41,9 +42,7 @@ const VERIFY_PLAN_EXECUTION_TOOL_NAME = ).VERIFY_PLAN_EXECUTION_TOOL_NAME : null const WORKFLOW_TOOL_NAME = feature('WORKFLOW_SCRIPTS') - ? ( - require('../../tools/WorkflowTool/constants.js') as typeof import('../../tools/WorkflowTool/constants.js') - ).WORKFLOW_TOOL_NAME + ? WORKFLOW_TOOL_NAME_VALUE : null /* eslint-enable @typescript-eslint/no-require-imports */ diff --git a/src/utils/permissions/permissionRuleParser.ts b/src/utils/permissions/permissionRuleParser.ts index 77ff0681f..730b58f3a 100644 --- a/src/utils/permissions/permissionRuleParser.ts +++ b/src/utils/permissions/permissionRuleParser.ts @@ -1,19 +1,14 @@ import { feature } from 'bun:bundle' import { AGENT_TOOL_NAME } from '../../tools/AgentTool/constants.js' +import { BRIEF_TOOL_NAME as BRIEF_TOOL_NAME_VALUE } from '../../tools/BriefTool/prompt.js' import { TASK_OUTPUT_TOOL_NAME } from '../../tools/TaskOutputTool/constants.js' import { TASK_STOP_TOOL_NAME } from '../../tools/TaskStopTool/prompt.js' import type { PermissionRuleValue } from './PermissionRule.js' -// Dead code elimination: ant-only tool names are conditionally required so -// their strings don't leak into external builds. Static imports always bundle. -/* eslint-disable @typescript-eslint/no-require-imports */ const BRIEF_TOOL_NAME: string | null = feature('KAIROS') || feature('KAIROS_BRIEF') - ? ( - require('../../tools/BriefTool/prompt.js') as typeof import('../../tools/BriefTool/prompt.js') - ).BRIEF_TOOL_NAME + ? BRIEF_TOOL_NAME_VALUE : null -/* eslint-enable @typescript-eslint/no-require-imports */ // Maps legacy tool names to their current canonical names. // When a tool is renamed, add old → new here so permission rules, diff --git a/src/utils/permissions/permissionSetup.ts b/src/utils/permissions/permissionSetup.ts index 700d198d7..43707fa81 100644 --- a/src/utils/permissions/permissionSetup.ts +++ b/src/utils/permissions/permissionSetup.ts @@ -27,10 +27,10 @@ import { } from './PermissionMode.js' import { applyPermissionRulesToPermissionContext } from './permissions.js' import { loadAllPermissionRulesFromDisk } from './permissionsLoader.js' +import * as autoModeStateModuleValue from './autoModeState.js' -/* eslint-disable @typescript-eslint/no-require-imports */ const autoModeStateModule = feature('TRANSCRIPT_CLASSIFIER') - ? (require('./autoModeState.js') as typeof import('./autoModeState.js')) + ? autoModeStateModuleValue : null import { resolve } from 'path' diff --git a/src/utils/permissions/permissions.ts b/src/utils/permissions/permissions.ts index e71efcceb..abb92a347 100644 --- a/src/utils/permissions/permissions.ts +++ b/src/utils/permissions/permissions.ts @@ -54,13 +54,14 @@ import { type PermissionRuleFromEditableSettings, shouldAllowManagedPermissionRulesOnly, } from './permissionsLoader.js' +import * as autoModeStateModuleValue from './autoModeState.js' +import * as classifierDecisionModuleValue from './classifierDecision.js' -/* eslint-disable @typescript-eslint/no-require-imports */ const classifierDecisionModule = feature('TRANSCRIPT_CLASSIFIER') - ? (require('./classifierDecision.js') as typeof import('./classifierDecision.js')) + ? classifierDecisionModuleValue : null const autoModeStateModule = feature('TRANSCRIPT_CLASSIFIER') - ? (require('./autoModeState.js') as typeof import('./autoModeState.js')) + ? autoModeStateModuleValue : null import { diff --git a/src/utils/permissions/yoloClassifier.ts b/src/utils/permissions/yoloClassifier.ts index c09a578b5..1c69299fb 100644 --- a/src/utils/permissions/yoloClassifier.ts +++ b/src/utils/permissions/yoloClassifier.ts @@ -43,31 +43,25 @@ import { parseClassifierResponse, } from './classifierShared.js' import { getClaudeTempDir } from './filesystem.js' - -// Dead code elimination: conditional imports for auto mode classifier prompts. -// At build time, the bundler inlines .txt files as string literals. At test -// time, require() returns {default: string} — txtRequire normalizes both. -/* eslint-disable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */ -function txtRequire(mod: string | { default: string }): string { - return typeof mod === 'string' ? mod : mod.default -} +import autoModeSystemPrompt from './yolo-classifier-prompts/auto_mode_system_prompt.txt' +import permissionsAnthropic from './yolo-classifier-prompts/permissions_anthropic.txt' +import permissionsExternal from './yolo-classifier-prompts/permissions_external.txt' const BASE_PROMPT: string = feature('TRANSCRIPT_CLASSIFIER') - ? txtRequire(require('./yolo-classifier-prompts/auto_mode_system_prompt.txt')) + ? autoModeSystemPrompt : '' // External template is loaded separately so it's available for // `claude auto-mode defaults` even in ant builds. Ant builds use // permissions_anthropic.txt at runtime but should dump external defaults. const EXTERNAL_PERMISSIONS_TEMPLATE: string = feature('TRANSCRIPT_CLASSIFIER') - ? txtRequire(require('./yolo-classifier-prompts/permissions_external.txt')) + ? permissionsExternal : '' const ANTHROPIC_PERMISSIONS_TEMPLATE: string = feature('TRANSCRIPT_CLASSIFIER') && process.env.USER_TYPE === 'ant' - ? txtRequire(require('./yolo-classifier-prompts/permissions_anthropic.txt')) + ? permissionsAnthropic : '' -/* eslint-enable custom-rules/no-process-env-top-level, @typescript-eslint/no-require-imports */ function isUsingExternalPermissions(): boolean { if (process.env.USER_TYPE !== 'ant') return true diff --git a/src/utils/systemPrompt.ts b/src/utils/systemPrompt.ts index 2059c81bd..6e84c18a4 100644 --- a/src/utils/systemPrompt.ts +++ b/src/utils/systemPrompt.ts @@ -8,18 +8,14 @@ import type { AgentDefinition } from '../tools/AgentTool/loadAgentsDir.js' import { isBuiltInAgent } from '../tools/AgentTool/loadAgentsDir.js' import { isEnvTruthy } from './envUtils.js' import { asSystemPrompt, type SystemPrompt } from './systemPromptType.js' +import * as proactiveModuleValue from '../proactive/index.js' export { asSystemPrompt, type SystemPrompt } from './systemPromptType.js' -// Dead code elimination: conditional import for proactive mode. -// Same pattern as prompts.ts — lazy require to avoid pulling the module -// into non-proactive builds. -/* eslint-disable @typescript-eslint/no-require-imports */ const proactiveModule = feature('PROACTIVE') || feature('KAIROS') - ? (require('../proactive/index.js') as typeof import('../proactive/index.js')) + ? proactiveModuleValue : null -/* eslint-enable @typescript-eslint/no-require-imports */ function isProactiveActive_SAFE_TO_CALL_ANYWHERE(): boolean { return proactiveModule?.isProactiveActive() ?? false diff --git a/vite.config.ts b/vite.config.ts index 23d79105a..1f6417ed6 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -84,6 +84,9 @@ export default defineConfig({ copyPublicDir: false, sourcemap: false, minify: true, + commonjsOptions: { + transformMixedEsModules: true, + }, // SSR build mode — uses Rollup with Node.js target ssr: true,