Skip to content

Embedded library: theme Proxy throws "Theme not initialized" and initTheme() fails when PI_PACKAGE_DIR points at a shim #6102

Description

@wloonis

Summary

When @earendil-works/pi-coding-agent is embedded as a library (not used through the TUI), code paths that touch the global theme throw

Theme not initialized. Call initTheme() first.

because initTheme() is only called by the TUI at startup, and the theme global is a throwing Proxy until then. Additionally, when a host does call initTheme(), theme file loading can fail because PI_PACKAGE_DIR may resolve to a shim directory that has no dist/modes/interactive/theme/.

Environment

  • @earendil-works/pi-coding-agent 0.80.2
  • Usage: embedded as a library with extensions enabled. The extension loader (and some shared code) reads theme, which is uninitialized in a non-TUI host.

Root cause

  • dist/modes/interactive/theme/theme.js:601const THEME_KEY = Symbol.for("@earendil-works/pi-coding-agent:theme") is a global.
  • dist/modes/interactive/theme/theme.js:609 — the global is a Proxy whose get trap throws "Theme not initialized. Call initTheme() first." until initTheme() runs.
  • dist/modes/interactive/theme/theme.js:631initTheme(themeName, enableWatcher) calls loadTheme(), which reads theme JSON files from ${PI_PACKAGE_DIR}/dist/modes/interactive/theme/.
  • The TUI calls initTheme() at startup. A library embedder that never touches the TUI still imports code paths that read theme (via the extension loader), and gets the throw.
  • PI_PACKAGE_DIR resolution (ensurePiPackageDirShim) can land on a shim directory that only has a bare package.json and no dist/modes/interactive/theme/, so even calling initTheme() from a host fails to locate the theme files.

Reproduction

import { /* anything that pulls in the extension loader */ } from "@earendil-works/pi-coding-agent";
// create a session with extensions enabled; extension loading reads `theme`
// → throws "Theme not initialized. Call initTheme() first."

Proposal

  • Make theme lazily resolve to a safe default / no-op when accessed outside the TUI (or auto-initialize on first access), so library embedders don't have to know about initTheme().
  • Ensure initTheme() resolves the real package directory (not the shim) for theme file loading, so hosts that do call it succeed regardless of PI_PACKAGE_DIR pointing at a shim.

Workaround currently used by Archon (host side, not a real fix)

Archon's Pi provider temporarily repoints PI_PACKAGE_DIR to the real package directory (resolved via import.meta.resolve('@earendil-works/pi-coding-agent')) and calls initTheme(undefined, false) before creating sessions.

Happy to open a PR if there's interest.

Metadata

Metadata

Assignees

No one assigned

    Labels

    no-actionThis issue has been rejected after triage

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions