Skip to content

Add subpath exports to @dexto/core for per-domain imports #679

@rahulkarajgikar

Description

@rahulkarajgikar

Problem

@dexto/core currently exposes almost its entire API surface through a single root barrel (src/index.tsexport * from every domain module). The only declared subpath export beyond . is ./utils/path.js.

This causes real issues for downstream consumers:

  1. Browser bundles pull in Node.js code — importing a single type like ApprovalStatus from @dexto/core drags in createLogger, OpenTelemetry, process references, and other server-only modules. This caused a ReferenceError: process is not defined in dexto-cloud's dashboard because chat-ui imported ApprovalStatus from the root.
  2. No tree-shaking — bundlers can't eliminate unused domains because everything flows through one barrel.
  3. Unclear public API boundaries — consumers can't tell which modules are meant to be imported independently vs. which are internal implementation details.

The infrastructure to fix this already exists — there are 20+ domain modules with clean barrel index.ts files, and tsup compiles every source file to mirrored dist/ paths. The package.json just doesn't declare the subpaths.

There's even a TODO in src/index.ts:

// TODO: Break down into subpath exports for better tree-shaking
// Consider adding exports like:
// - @dexto/core/telemetry
// - @dexto/core/llm
// - @dexto/core/session
// - @dexto/core/tools

Proposed change

Add a wildcard subpath export to package.json that maps each domain module:

{
  "exports": {
    ".": { "types": "...", "browser": "...", "default": "..." },
    "./*": {
      "types": "./dist/*/index.d.ts",
      "default": {
        "import": "./dist/*/index.js",
        "require": "./dist/*/index.cjs"
      }
    },
    "./utils/path": {
      "import": "./dist/utils/path.js",
      "require": "./dist/utils/path.cjs"
    },
    "./package.json": "./package.json"
  }
}

This enables per-domain imports that mirror the existing top-level modules:

import { StreamingEvent, StreamingEventName } from '@dexto/core/events';
import { ApprovalStatus, ApprovalRequest } from '@dexto/core/approval';
import { ContentPart } from '@dexto/core/context';
import { TokenUsage } from '@dexto/core/llm';
import { createLogger } from '@dexto/core/logger';
import { DextoAgent } from '@dexto/core/agent';
import { defineTool } from '@dexto/core/tools';

Domain modules that become subpaths

All existing src/*/index.ts barrels:

Subpath Domain
@dexto/core/agent DextoAgent, agent card, runtime config
@dexto/core/approval ApprovalStatus, ApprovalRequest, ApprovalManager
@dexto/core/context ContentPart, MessageContent, context manager
@dexto/core/errors Base errors, ErrorScope, ErrorType
@dexto/core/events StreamingEvent, event bus, event names
@dexto/core/hooks HookManager, hook types
@dexto/core/llm LLM registry, TokenUsage, providers
@dexto/core/logger createLogger, DextoLogger, transports
@dexto/core/mcp MCPManager, MCP types
@dexto/core/memory MemoryManager, memory types
@dexto/core/preferences Preferences
@dexto/core/prompts PromptManager, prompt schemas
@dexto/core/resources ResourceManager, resource types
@dexto/core/search SearchService
@dexto/core/session ChatSession, SessionManager
@dexto/core/storage StorageManager, blob types
@dexto/core/systemPrompt System prompt manager, contributors
@dexto/core/telemetry Telemetry, OTel config
@dexto/core/tools defineTool, ToolManager, tool types
@dexto/core/utils Path helpers, Zod utils, misc
@dexto/core/workspace WorkspaceManager

Behavior

  • Root import stays unchangedimport { DextoAgent } from '@dexto/core' continues to work and re-exports everything (backward compatible).
  • Subpath imports are additive — no breaking change, just new import paths available.
  • Browser safety comes naturally — browser code imports from lightweight subpaths like events or approval that don't have Node.js dependencies in their import graph.
  • sideEffects: false should be added to package.json to enable bundler tree-shaking.

Prior art

Mastra uses this exact pattern in @mastra/core — wildcard ./* export with explicit overrides for non-standard paths, minimal root barrel, and all their UI/client packages import from subpaths.

Checklist

  • Add ./* wildcard export to package.json
  • Add explicit overrides for any modules that don't follow src/<name>/index.ts convention (e.g. ./utils/path)
  • Add "sideEffects": false to package.json
  • Remove the TODO comment from src/index.ts
  • Verify @dexto/client-sdk and @dexto/agent-management still build (they import from root today)
  • Update dexto-cloud consumers to use subpath imports where it eliminates browser bundle issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions