refactor: finish companion rename migration

Complete the remaining pi-to-companion rename across companion-os, web, vm-orchestrator, docker, and archived fixtures.

Verification:
- semantic rg sweeps for Pi/piConfig/getPi/.pi runtime references
- npm run check in apps/companion-os (fails in this worktree: biome not found)

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Harivansh Rathi 2026-03-10 07:39:32 -05:00
parent e8fe3d54af
commit 536241053c
303 changed files with 3603 additions and 3602 deletions

View file

@ -5,10 +5,10 @@
*
* Test with: npx tsx src/cli-new.ts [args...]
*/
process.title = "pi";
process.title = "companion";
import { bedrockProviderModule } from "@mariozechner/pi-ai/bedrock-provider";
import { setBedrockProviderModule } from "@mariozechner/pi-ai";
import { bedrockProviderModule } from "@mariozechner/companion-ai/bedrock-provider";
import { setBedrockProviderModule } from "@mariozechner/companion-ai";
import { EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
import { main } from "./main.js";

View file

@ -2,7 +2,7 @@
* CLI argument parsing and help display
*/
import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
import type { ThinkingLevel } from "@mariozechner/companion-agent-core";
import chalk from "chalk";
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "../config.js";
import {
@ -245,7 +245,7 @@ ${chalk.bold("Options:")}
--export <file> Export session file to HTML and exit
--list-models [search] List available models (with optional fuzzy search)
--verbose Force verbose startup (overrides quietStartup setting)
--offline Disable startup network operations (same as PI_OFFLINE=1)
--offline Disable startup network operations (same as COMPANION_OFFLINE=1)
--help, -h Show this help
--version, -v Show version number
@ -324,10 +324,10 @@ ${chalk.bold("Environment Variables:")}
AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)
AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)
${ENV_AGENT_DIR.padEnd(32)} - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)
PI_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
PI_OFFLINE - Disable startup network operations when set to 1/true/yes
PI_SHARE_VIEWER_URL - Base URL for /share command (default: https://pi.dev/session/)
PI_AI_ANTIGRAVITY_VERSION - Override Antigravity User-Agent version (e.g., 1.23.0)
COMPANION_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
COMPANION_OFFLINE - Disable startup network operations when set to 1/true/yes
COMPANION_SHARE_VIEWER_URL - Base URL for /share command (default: https://companion.dev/session/)
COMPANION_AI_ANTIGRAVITY_VERSION - Override Antigravity User-Agent version (e.g., 1.23.0)
${chalk.bold(`Available Tools (default: ${defaultToolsText}):`)}
read - Read file contents

View file

@ -1,8 +1,8 @@
/**
* TUI config selector for `pi config` command
* TUI config selector for `companion config` command
*/
import { ProcessTerminal, TUI } from "@mariozechner/pi-tui";
import { ProcessTerminal, TUI } from "@mariozechner/companion-tui";
import type { ResolvedPaths } from "../core/package-manager.js";
import type { SettingsManager } from "../core/settings-manager.js";
import { ConfigSelectorComponent } from "../modes/interactive/components/config-selector.js";

View file

@ -3,7 +3,7 @@
*/
import { access, readFile, stat } from "node:fs/promises";
import type { ImageContent } from "@mariozechner/pi-ai";
import type { ImageContent } from "@mariozechner/companion-ai";
import chalk from "chalk";
import { resolve } from "path";
import { resolveReadPath } from "../core/tools/path-utils.js";

View file

@ -2,8 +2,8 @@
* List available models with optional fuzzy search
*/
import type { Api, Model } from "@mariozechner/pi-ai";
import { fuzzyFilter } from "@mariozechner/pi-tui";
import type { Api, Model } from "@mariozechner/companion-ai";
import { fuzzyFilter } from "@mariozechner/companion-tui";
import type { ModelRegistry } from "../core/model-registry.js";
/**

View file

@ -2,7 +2,7 @@
* TUI session selector for --resume flag
*/
import { ProcessTerminal, TUI } from "@mariozechner/pi-tui";
import { ProcessTerminal, TUI } from "@mariozechner/companion-tui";
import { KeybindingsManager } from "../core/keybindings.js";
import type {
SessionInfo,

View file

@ -73,7 +73,7 @@ export function getUpdateInstruction(packageName: string): string {
const method = detectInstallMethod();
switch (method) {
case "bun-binary":
return `Download from: https://github.com/badlogic/pi-mono/releases/latest`;
return `Download from: https://github.com/badlogic/companion-mono/releases/latest`;
case "pnpm":
return `Run: pnpm install -g ${packageName}`;
case "yarn":
@ -99,7 +99,7 @@ export function getUpdateInstruction(packageName: string): string {
*/
export function getPackageDir(): string {
// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)
const envDir = process.env.PI_PACKAGE_DIR;
const envDir = process.env.COMPANION_PACKAGE_DIR;
if (envDir) {
if (envDir === "~") return homedir();
if (envDir.startsWith("~/")) return homedir() + envDir.slice(1);
@ -174,31 +174,32 @@ export function getChangelogPath(): string {
}
// =============================================================================
// App Config (from package.json piConfig)
// App Config (from package.json companionConfig)
// =============================================================================
const pkg = JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"));
export const APP_NAME: string = pkg.piConfig?.name || "pi";
export const CONFIG_DIR_NAME: string = pkg.piConfig?.configDir || ".pi";
export const APP_NAME: string = pkg.companionConfig?.name || "companion";
export const CONFIG_DIR_NAME: string =
pkg.companionConfig?.configDir || ".companion";
export const VERSION: string = pkg.version;
// e.g., PI_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR
// e.g., COMPANION_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR
export const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;
const DEFAULT_SHARE_VIEWER_URL = "https://pi.dev/session/";
const DEFAULT_SHARE_VIEWER_URL = "https://companion.dev/session/";
/** Get the share viewer URL for a gist ID */
export function getShareViewerUrl(gistId: string): string {
const baseUrl = process.env.PI_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;
const baseUrl = process.env.COMPANION_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;
return `${baseUrl}#${gistId}`;
}
// =============================================================================
// User Config Paths (~/.pi/agent/*)
// User Config Paths (~/.companion/agent/*)
// =============================================================================
/** Get the agent config directory (e.g., ~/.pi/agent/) */
/** Get the agent config directory (e.g., ~/.companion/agent/) */
export function getAgentDir(): string {
const envDir = process.env[ENV_AGENT_DIR];
if (envDir) {

View file

@ -22,20 +22,20 @@ import type {
AgentState,
AgentTool,
ThinkingLevel,
} from "@mariozechner/pi-agent-core";
} from "@mariozechner/companion-agent-core";
import type {
AssistantMessage,
ImageContent,
Message,
Model,
TextContent,
} from "@mariozechner/pi-ai";
} from "@mariozechner/companion-ai";
import {
isContextOverflow,
modelsAreEqual,
resetApiProviders,
supportsXhigh,
} from "@mariozechner/pi-ai";
} from "@mariozechner/companion-ai";
import { getDocsPath } from "../config.js";
import { theme } from "../modes/interactive/theme/theme.js";
import { stripFrontmatter } from "../utils/frontmatter.js";
@ -1023,7 +1023,7 @@ export class AgentSession {
/**
* Send a prompt to the agent.
* - Handles extension commands (registered via pi.registerCommand) immediately, even during streaming
* - Handles extension commands (registered via companion.registerCommand) immediately, even during streaming
* - Expands file-based prompt templates by default
* - During streaming, queues via steer() or followUp() based on streamingBehavior option
* - Validates model and API key before sending (when not streaming)
@ -1034,7 +1034,7 @@ export class AgentSession {
const expandPromptTemplates = options?.expandPromptTemplates ?? true;
// Handle extension commands first (execute immediately, even during streaming)
// Extension commands manage their own LLM interaction via pi.sendMessage()
// Extension commands manage their own LLM interaction via companion.sendMessage()
if (expandPromptTemplates && text.startsWith("/")) {
const handled = await this._tryExecuteExtensionCommand(text);
if (handled) {

View file

@ -2,7 +2,7 @@
* Credential storage for API keys and OAuth tokens.
* Handles loading, saving, and refreshing credentials from auth.json.
*
* Uses file locking to prevent race conditions when multiple pi instances
* Uses file locking to prevent race conditions when multiple companion instances
* try to refresh tokens simultaneously.
*/
@ -11,12 +11,12 @@ import {
type OAuthCredentials,
type OAuthLoginCallbacks,
type OAuthProviderId,
} from "@mariozechner/pi-ai";
} from "@mariozechner/companion-ai";
import {
getOAuthApiKey,
getOAuthProvider,
getOAuthProviders,
} from "@mariozechner/pi-ai/oauth";
} from "@mariozechner/companion-ai/oauth";
import {
chmodSync,
existsSync,
@ -373,7 +373,7 @@ export class AuthStorage {
/**
* Refresh OAuth token with backend locking to prevent race conditions.
* Multiple pi instances may try to refresh simultaneously when tokens expire.
* Multiple companion instances may try to refresh simultaneously when tokens expire.
*/
private async refreshOAuthTokenWithLock(
providerId: OAuthProviderId,

View file

@ -120,7 +120,7 @@ export function executeBash(
// Start writing to temp file if exceeds threshold
if (totalBytes > DEFAULT_MAX_BYTES && !tempFilePath) {
const id = randomBytes(8).toString("hex");
tempFilePath = join(tmpdir(), `pi-bash-${id}.log`);
tempFilePath = join(tmpdir(), `companion-bash-${id}.log`);
tempFileStream = createWriteStream(tempFilePath);
// Write already-buffered chunks to temp file
for (const chunk of outputChunks) {
@ -223,7 +223,7 @@ export async function executeBashWithOperations(
// Start writing to temp file if exceeds threshold
if (totalBytes > DEFAULT_MAX_BYTES && !tempFilePath) {
const id = randomBytes(8).toString("hex");
tempFilePath = join(tmpdir(), `pi-bash-${id}.log`);
tempFilePath = join(tmpdir(), `companion-bash-${id}.log`);
tempFileStream = createWriteStream(tempFilePath);
for (const chunk of outputChunks) {
tempFileStream.write(chunk);

View file

@ -5,9 +5,9 @@
* a summary of the branch being left so context isn't lost.
*/
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { Model } from "@mariozechner/pi-ai";
import { completeSimple } from "@mariozechner/pi-ai";
import type { AgentMessage } from "@mariozechner/companion-agent-core";
import type { Model } from "@mariozechner/companion-ai";
import { completeSimple } from "@mariozechner/companion-ai";
import {
convertToLlm,
createBranchSummaryMessage,
@ -206,7 +206,7 @@ export function prepareBranchEntries(
// First pass: collect file ops from ALL entries (even if they don't fit in token budget)
// This ensures we capture cumulative file tracking from nested branch summaries
// Only extract from pi-generated summaries (fromHook !== true), not extension-generated ones
// Only extract from companion-generated summaries (fromHook !== true), not extension-generated ones
for (const entry of entries) {
if (entry.type === "branch_summary" && !entry.fromHook && entry.details) {
const details = entry.details as BranchSummaryDetails;

View file

@ -5,9 +5,9 @@
* and after compaction the session is reloaded.
*/
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { AssistantMessage, Model, Usage } from "@mariozechner/pi-ai";
import { completeSimple } from "@mariozechner/pi-ai";
import type { AgentMessage } from "@mariozechner/companion-agent-core";
import type { AssistantMessage, Model, Usage } from "@mariozechner/companion-ai";
import { completeSimple } from "@mariozechner/companion-ai";
import {
convertToLlm,
createBranchSummaryMessage,
@ -45,7 +45,7 @@ function extractFileOperations(
): FileOperations {
const fileOps = createFileOps();
// Collect from previous compaction's details (if pi-generated)
// Collect from previous compaction's details (if companion-generated)
if (prevCompactionIndex >= 0) {
const prevCompaction = entries[prevCompactionIndex] as CompactionEntry;
if (!prevCompaction.fromHook && prevCompaction.details) {

View file

@ -2,8 +2,8 @@
* Shared utilities for compaction and branch summarization.
*/
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { Message } from "@mariozechner/pi-ai";
import type { AgentMessage } from "@mariozechner/companion-agent-core";
import type { Message } from "@mariozechner/companion-ai";
// ============================================================================
// File Operation Tracking

View file

@ -1,3 +1,3 @@
import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
import type { ThinkingLevel } from "@mariozechner/companion-agent-core";
export const DEFAULT_THINKING_LEVEL: ThinkingLevel = "medium";

View file

@ -1,4 +1,4 @@
import type { AgentState } from "@mariozechner/pi-agent-core";
import type { AgentState } from "@mariozechner/companion-agent-core";
import { existsSync, readFileSync, writeFileSync } from "fs";
import { basename, join } from "path";
import { APP_NAME, getExportTemplateDir } from "../../config.js";

View file

@ -27,7 +27,7 @@
// Parse URL parameters for deep linking: leafId and targetId
// Check for injected params (when loaded in iframe via srcdoc) or use window.location
const injectedParams = document.querySelector('meta[name="pi-url-params"]');
const injectedParams = document.querySelector('meta[name="companion-url-params"]');
const searchString = injectedParams
? injectedParams.content
: window.location.search.substring(1);
@ -1227,7 +1227,7 @@
function buildShareUrl(entryId) {
// Check for injected base URL (used when loaded in iframe via srcdoc)
const baseUrlMeta = document.querySelector(
'meta[name="pi-share-base-url"]',
'meta[name="companion-share-base-url"]',
);
const baseUrl = baseUrlMeta
? baseUrlMeta.content

View file

@ -5,7 +5,7 @@
* and converting the ANSI output to HTML.
*/
import type { ImageContent, TextContent } from "@mariozechner/pi-ai";
import type { ImageContent, TextContent } from "@mariozechner/companion-ai";
import type { Theme } from "../../modes/interactive/theme/theme.js";
import type { ToolDefinition } from "../extensions/types.js";
import { ansiLinesToHtml } from "./ansi-to-html.js";

View file

@ -4864,7 +4864,7 @@ var hljs = (function () {
keyword:
"and break do else elseif end for goto if in local not or repeat return then until while",
built_in:
"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove",
"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp companion cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove",
},
contains: i.concat([
{
@ -6293,7 +6293,7 @@ var hljs = (function () {
literal:
"NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10",
built_in:
"LETTERS letters month.abb month.name pi T F abs acos acosh all any anyNA Arg as.call as.character as.complex as.double as.environment as.integer as.logical as.null.default as.numeric as.raw asin asinh atan atanh attr attributes baseenv browser c call ceiling class Conj cos cosh cospi cummax cummin cumprod cumsum digamma dim dimnames emptyenv exp expression floor forceAndCall gamma gc.time globalenv Im interactive invisible is.array is.atomic is.call is.character is.complex is.double is.environment is.expression is.finite is.function is.infinite is.integer is.language is.list is.logical is.matrix is.na is.name is.nan is.null is.numeric is.object is.pairlist is.raw is.recursive is.single is.symbol lazyLoadDBfetch length lgamma list log max min missing Mod names nargs nzchar oldClass on.exit pos.to.env proc.time prod quote range Re rep retracemem return round seq_along seq_len seq.int sign signif sin sinh sinpi sqrt standardGeneric substitute sum switch tan tanh tanpi tracemem trigamma trunc unclass untracemem UseMethod xtfrm",
"LETTERS letters month.abb month.name companion T F abs acos acosh all any anyNA Arg as.call as.character as.complex as.double as.environment as.integer as.logical as.null.default as.numeric as.raw asin asinh atan atanh attr attributes baseenv browser c call ceiling class Conj cos cosh cospi cummax cummin cumprod cumsum digamma dim dimnames emptyenv exp expression floor forceAndCall gamma gc.time globalenv Im interactive invisible is.array is.atomic is.call is.character is.complex is.double is.environment is.expression is.finite is.function is.infinite is.integer is.language is.list is.logical is.matrix is.na is.name is.nan is.null is.numeric is.object is.pairlist is.raw is.recursive is.single is.symbol lazyLoadDBfetch length lgamma list log max min missing Mod names nargs nzchar oldClass on.exit pos.to.env proc.time prod quote range Re rep retracemem return round seq_along seq_len seq.int sign signif sin sinh sinpi sqrt standardGeneric substitute sum switch tan tanh tanpi tracemem trigamma trunc unclass untracemem UseMethod xtfrm",
},
contains: [
e.COMMENT(/#'/, /$/, {

View file

@ -10,18 +10,18 @@ import * as os from "node:os";
import * as path from "node:path";
import { fileURLToPath } from "node:url";
import { createJiti } from "@mariozechner/jiti";
import * as _bundledPiAgentCore from "@mariozechner/pi-agent-core";
import * as _bundledPiAi from "@mariozechner/pi-ai";
import * as _bundledPiAiOauth from "@mariozechner/pi-ai/oauth";
import type { KeyId } from "@mariozechner/pi-tui";
import * as _bundledPiTui from "@mariozechner/pi-tui";
import * as _bundledPiAgentCore from "@mariozechner/companion-agent-core";
import * as _bundledPiAi from "@mariozechner/companion-ai";
import * as _bundledPiAiOauth from "@mariozechner/companion-ai/oauth";
import type { KeyId } from "@mariozechner/companion-tui";
import * as _bundledPiTui from "@mariozechner/companion-tui";
// Static imports of packages that extensions may use.
// These MUST be static so Bun bundles them into the compiled binary.
// The virtualModules option then makes them available to extensions.
import * as _bundledTypebox from "@sinclair/typebox";
import { getAgentDir, isBunBinary } from "../../config.js";
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
// avoiding a circular dependency. Extensions can import from @mariozechner/pi-coding-agent.
// avoiding a circular dependency. Extensions can import from @mariozechner/companion-coding-agent.
import * as _bundledPiCodingAgent from "../../index.js";
import { createEventBus, type EventBus } from "../event-bus.js";
import type { ExecOptions } from "../exec.js";
@ -41,11 +41,11 @@ import type {
/** Modules available to extensions via virtualModules (for compiled Bun binary) */
const VIRTUAL_MODULES: Record<string, unknown> = {
"@sinclair/typebox": _bundledTypebox,
"@mariozechner/pi-agent-core": _bundledPiAgentCore,
"@mariozechner/pi-tui": _bundledPiTui,
"@mariozechner/pi-ai": _bundledPiAi,
"@mariozechner/pi-ai/oauth": _bundledPiAiOauth,
"@mariozechner/pi-coding-agent": _bundledPiCodingAgent,
"@mariozechner/companion-agent-core": _bundledPiAgentCore,
"@mariozechner/companion-tui": _bundledPiTui,
"@mariozechner/companion-ai": _bundledPiAi,
"@mariozechner/companion-ai/oauth": _bundledPiAiOauth,
"@mariozechner/companion-coding-agent": _bundledPiCodingAgent,
};
const require = createRequire(import.meta.url);
@ -80,22 +80,22 @@ function getAliases(): Record<string, string> {
};
_aliases = {
"@mariozechner/pi-coding-agent": packageIndex,
"@mariozechner/pi-agent-core": resolveWorkspaceOrImport(
"@mariozechner/companion-coding-agent": packageIndex,
"@mariozechner/companion-agent-core": resolveWorkspaceOrImport(
"agent/dist/index.js",
"@mariozechner/pi-agent-core",
"@mariozechner/companion-agent-core",
),
"@mariozechner/pi-tui": resolveWorkspaceOrImport(
"@mariozechner/companion-tui": resolveWorkspaceOrImport(
"tui/dist/index.js",
"@mariozechner/pi-tui",
"@mariozechner/companion-tui",
),
"@mariozechner/pi-ai": resolveWorkspaceOrImport(
"@mariozechner/companion-ai": resolveWorkspaceOrImport(
"ai/dist/index.js",
"@mariozechner/pi-ai",
"@mariozechner/companion-ai",
),
"@mariozechner/pi-ai/oauth": resolveWorkspaceOrImport(
"@mariozechner/companion-ai/oauth": resolveWorkspaceOrImport(
"ai/dist/oauth.js",
"@mariozechner/pi-ai/oauth",
"@mariozechner/companion-ai/oauth",
),
"@sinclair/typebox": typeboxRoot,
};
@ -454,8 +454,8 @@ function readPiManifest(packageJsonPath: string): PiManifest | null {
try {
const content = fs.readFileSync(packageJsonPath, "utf-8");
const pkg = JSON.parse(content);
if (pkg.pi && typeof pkg.pi === "object") {
return pkg.pi as PiManifest;
if (pkg.companion && typeof pkg.companion === "object") {
return pkg.companion as PiManifest;
}
return null;
} catch {
@ -471,13 +471,13 @@ function isExtensionFile(name: string): boolean {
* Resolve extension entry points from a directory.
*
* Checks for:
* 1. package.json with "pi.extensions" field -> returns declared paths
* 1. package.json with "companion.extensions" field -> returns declared paths
* 2. index.ts or index.js -> returns the index file
*
* Returns resolved paths or null if no entry points found.
*/
function resolveExtensionEntries(dir: string): string[] | null {
// Check for package.json with "pi" field first
// Check for package.json with "companion" field first
const packageJsonPath = path.join(dir, "package.json");
if (fs.existsSync(packageJsonPath)) {
const manifest = readPiManifest(packageJsonPath);
@ -514,7 +514,7 @@ function resolveExtensionEntries(dir: string): string[] | null {
* Discovery rules:
* 1. Direct files: `extensions/*.ts` or `*.js` load
* 2. Subdirectory with index: `extensions/* /index.ts` or `index.js` load
* 3. Subdirectory with package.json: `extensions/* /package.json` with "pi" field load what it declares
* 3. Subdirectory with package.json: `extensions/* /package.json` with "companion" field load what it declares
*
* No recursion beyond one level. Complex packages must use package.json manifest.
*/
@ -577,8 +577,8 @@ export async function discoverAndLoadExtensions(
}
};
// 1. Project-local extensions: cwd/.pi/extensions/
const localExtDir = path.join(cwd, ".pi", "extensions");
// 1. Project-local extensions: cwd/.companion/extensions/
const localExtDir = path.join(cwd, ".companion", "extensions");
addPaths(discoverExtensionsInDir(localExtDir));
// 2. Global extensions: agentDir/extensions/
@ -589,7 +589,7 @@ export async function discoverAndLoadExtensions(
for (const p of configuredPaths) {
const resolved = resolvePath(p, cwd);
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
// Check for package.json with pi manifest or index.ts
// Check for package.json with companion manifest or index.ts
const entries = resolveExtensionEntries(resolved);
if (entries) {
addPaths(entries);

View file

@ -2,9 +2,9 @@
* Extension runner - executes extensions and manages their lifecycle.
*/
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { ImageContent, Model } from "@mariozechner/pi-ai";
import type { KeyId } from "@mariozechner/pi-tui";
import type { AgentMessage } from "@mariozechner/companion-agent-core";
import type { ImageContent, Model } from "@mariozechner/companion-ai";
import type { KeyId } from "@mariozechner/companion-tui";
import { type Theme, theme } from "../../modes/interactive/theme/theme.js";
import type { ResourceDiagnostic } from "../diagnostics.js";
import type { KeyAction, KeybindingsConfig } from "../keybindings.js";

View file

@ -13,7 +13,7 @@ import type {
AgentToolResult,
AgentToolUpdateCallback,
ThinkingLevel,
} from "@mariozechner/pi-agent-core";
} from "@mariozechner/companion-agent-core";
import type {
Api,
AssistantMessageEvent,
@ -26,7 +26,7 @@ import type {
SimpleStreamOptions,
TextContent,
ToolResultMessage,
} from "@mariozechner/pi-ai";
} from "@mariozechner/companion-ai";
import type {
AutocompleteItem,
Component,
@ -36,7 +36,7 @@ import type {
OverlayHandle,
OverlayOptions,
TUI,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type { Static, TSchema } from "@sinclair/typebox";
import type { Theme } from "../../modes/interactive/theme/theme.js";
import type { BashResult } from "../bash-executor.js";
@ -223,12 +223,12 @@ export interface ExtensionUIContext {
* - `keybindings`: KeybindingsManager for app-level keybindings
*
* For full app keybinding support (escape, ctrl+d, model switching, etc.),
* extend `CustomEditor` from `@mariozechner/pi-coding-agent` and call
* extend `CustomEditor` from `@mariozechner/companion-coding-agent` and call
* `super.handleInput(data)` for keys you don't handle.
*
* @example
* ```ts
* import { CustomEditor } from "@mariozechner/pi-coding-agent";
* import { CustomEditor } from "@mariozechner/companion-coding-agent";
*
* class VimEditor extends CustomEditor {
* private mode: "normal" | "insert" = "insert";
@ -316,7 +316,7 @@ export interface ExtensionContext {
abort(): void;
/** Whether there are queued messages waiting */
hasPendingMessages(): boolean;
/** Gracefully shutdown pi and exit. Available in all contexts. */
/** Gracefully shutdown companion and exit. Available in all contexts. */
shutdown(): void;
/** Get current context usage for the active model. */
getContextUsage(): ContextUsage | undefined;
@ -1251,7 +1251,7 @@ export interface ExtensionAPI {
*
* @example
* // Register a new provider with custom models
* pi.registerProvider("my-proxy", {
* companion.registerProvider("my-proxy", {
* baseUrl: "https://proxy.example.com",
* apiKey: "PROXY_API_KEY",
* api: "anthropic-messages",
@ -1270,13 +1270,13 @@ export interface ExtensionAPI {
*
* @example
* // Override baseUrl for an existing provider
* pi.registerProvider("anthropic", {
* companion.registerProvider("anthropic", {
* baseUrl: "https://proxy.example.com"
* });
*
* @example
* // Register provider with OAuth support
* pi.registerProvider("corporate-ai", {
* companion.registerProvider("corporate-ai", {
* baseUrl: "https://ai.corp.com",
* api: "openai-responses",
* models: [...],
@ -1301,7 +1301,7 @@ export interface ExtensionAPI {
* the initial load phase.
*
* @example
* pi.unregisterProvider("my-proxy");
* companion.unregisterProvider("my-proxy");
*/
unregisterProvider(name: string): void;
@ -1313,7 +1313,7 @@ export interface ExtensionAPI {
// Provider Registration Types
// ============================================================================
/** Configuration for registering a provider via pi.registerProvider(). */
/** Configuration for registering a provider via companion.registerProvider(). */
export interface ProviderConfig {
/** Base URL for the API endpoint. Required when defining models. */
baseUrl?: string;
@ -1381,7 +1381,7 @@ export interface ProviderModelConfig {
}
/** Extension factory function type. Supports both sync and async initialization. */
export type ExtensionFactory = (pi: ExtensionAPI) => void | Promise<void>;
export type ExtensionFactory = (companion: ExtensionAPI) => void | Promise<void>;
// ============================================================================
// Loaded Extension Types
@ -1480,7 +1480,7 @@ export interface ExtensionRuntimeState {
}
/**
* Action implementations for pi.* API methods.
* Action implementations for companion.* API methods.
* Provided to runner.initialize(), copied into the shared runtime.
*/
export interface ExtensionActions {

View file

@ -5,7 +5,7 @@
import type {
AgentTool,
AgentToolUpdateCallback,
} from "@mariozechner/pi-agent-core";
} from "@mariozechner/companion-agent-core";
import type { ExtensionRunner } from "./runner.js";
import type { RegisteredTool, ToolCallEventResult } from "./types.js";

View file

@ -1,4 +1,4 @@
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { AgentMessage } from "@mariozechner/companion-agent-core";
import type { AgentSession } from "../agent-session.js";
import type {
GatewayMessageRequest,

View file

@ -61,7 +61,7 @@ let activeGatewayRuntime: GatewayRuntime | null = null;
type JsonRecord = Record<string, unknown>;
type PiChannelsSettings = JsonRecord & {
type CompanionChannelsSettings = JsonRecord & {
adapters?: Record<string, JsonRecord>;
bridge?: JsonRecord;
slack?: JsonRecord;
@ -1031,7 +1031,7 @@ export class GatewayRuntime {
path.slice(this.config.webhook.basePath.length).replace(/^\/+/, "") ||
"default";
if (this.config.webhook.secret) {
const presentedSecret = request.headers["x-pi-webhook-secret"];
const presentedSecret = request.headers["x-companion-webhook-secret"];
if (presentedSecret !== this.config.webhook.secret) {
this.writeJson(response, 401, { error: "Invalid webhook secret" });
return;
@ -1388,7 +1388,7 @@ export class GatewayRuntime {
this.primarySession.settingsManager.applyOverrides(patch as Settings);
}
private getPiChannelsSettings(): PiChannelsSettings {
private getCompanionChannelsSettings(): CompanionChannelsSettings {
const globalSettings = this.primarySession.settingsManager.getGlobalSettings();
const projectSettings =
this.primarySession.settingsManager.getProjectSettings();
@ -1396,12 +1396,12 @@ export class GatewayRuntime {
isRecord(globalSettings) ? globalSettings : {},
isRecord(projectSettings) ? projectSettings : {},
);
const piChannels = mergedSettings["pi-channels"];
return isRecord(piChannels) ? (piChannels as PiChannelsSettings) : {};
const piChannels = mergedSettings["companion-channels"];
return isRecord(piChannels) ? (piChannels as CompanionChannelsSettings) : {};
}
private buildSlackChannelStatus(
config: PiChannelsSettings,
config: CompanionChannelsSettings,
bridgeEnabled: boolean,
): ChannelStatus {
const adapters = isRecord(config.adapters) ? config.adapters : {};
@ -1419,13 +1419,13 @@ export class GatewayRuntime {
if (hasConfig) {
if (!adapter) {
error = 'Slack requires `pi-channels.adapters.slack = { "type": "slack" }`.';
error = 'Slack requires `companion-channels.adapters.slack = { "type": "slack" }`.';
} else if (adapterType !== "slack") {
error = 'Slack adapter type must be "slack".';
} else if (!appToken) {
error = "Slack requires pi-channels.slack.appToken.";
error = "Slack requires companion-channels.slack.appToken.";
} else if (!botToken) {
error = "Slack requires pi-channels.slack.botToken.";
error = "Slack requires companion-channels.slack.botToken.";
} else {
configured = true;
}
@ -1433,7 +1433,7 @@ export class GatewayRuntime {
if (configured && !bridgeEnabled) {
error =
"Slack is configured, but pi-channels.bridge.enabled is false, so messages will not reach the agent.";
"Slack is configured, but companion-channels.bridge.enabled is false, so messages will not reach the agent.";
}
return {
@ -1447,7 +1447,7 @@ export class GatewayRuntime {
}
private buildTelegramChannelStatus(
config: PiChannelsSettings,
config: CompanionChannelsSettings,
bridgeEnabled: boolean,
): ChannelStatus {
const adapters = isRecord(config.adapters) ? config.adapters : {};
@ -1464,14 +1464,14 @@ export class GatewayRuntime {
if (hasConfig) {
if (!adapter) {
error =
'Telegram requires `pi-channels.adapters.telegram = { "type": "telegram", "botToken": "...", "polling": true }`.';
'Telegram requires `companion-channels.adapters.telegram = { "type": "telegram", "botToken": "...", "polling": true }`.';
} else if (adapterType !== "telegram") {
error = 'Telegram adapter type must be "telegram".';
} else if (!botToken) {
error = "Telegram requires pi-channels.adapters.telegram.botToken.";
error = "Telegram requires companion-channels.adapters.telegram.botToken.";
} else if (!pollingEnabled) {
error =
"Telegram requires pi-channels.adapters.telegram.polling = true.";
"Telegram requires companion-channels.adapters.telegram.polling = true.";
} else {
configured = true;
}
@ -1479,7 +1479,7 @@ export class GatewayRuntime {
if (configured && !bridgeEnabled) {
error =
"Telegram is configured, but pi-channels.bridge.enabled is false, so messages will not reach the agent.";
"Telegram is configured, but companion-channels.bridge.enabled is false, so messages will not reach the agent.";
}
return {
@ -1493,7 +1493,7 @@ export class GatewayRuntime {
}
private handleGetChannelsStatus(): ChannelStatus[] {
const config = this.getPiChannelsSettings();
const config = this.getCompanionChannelsSettings();
const bridgeEnabled = config.bridge?.enabled === true;
return [

View file

@ -1,4 +1,4 @@
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { AgentMessage } from "@mariozechner/companion-agent-core";
import type { HistoryMessage, HistoryPart } from "./types.js";
export interface GatewayTransientToolResult {

View file

@ -1,4 +1,4 @@
import type { ImageContent } from "@mariozechner/pi-ai";
import type { ImageContent } from "@mariozechner/companion-ai";
import type { AgentSession } from "../agent-session.js";
export interface GatewayConfig {

View file

@ -6,7 +6,7 @@ import {
type KeyId,
matchesKey,
setEditorKeybindings,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { existsSync, readFileSync } from "fs";
import { join } from "path";
import { getAgentDir } from "../config.js";

View file

@ -9,17 +9,17 @@ import {
import { createRequire } from "node:module";
import { homedir } from "node:os";
import { basename, join, resolve } from "node:path";
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { AgentMessage } from "@mariozechner/companion-agent-core";
import {
completeSimple,
type Model,
type TextContent,
} from "@mariozechner/pi-ai";
} from "@mariozechner/companion-ai";
import { parseFrontmatter } from "../../utils/frontmatter.js";
import type { SettingsManager } from "../settings-manager.js";
import type { ReadonlySessionManager } from "../session-manager.js";
const DEFAULT_STORAGE_DIR = join(homedir(), ".pi", "memory");
const DEFAULT_STORAGE_DIR = join(homedir(), ".companion", "memory");
const MAX_EPISODE_CHARS = 4_000;
const MAX_EPISODES = 5_000;
const DEFAULT_CORE_TOKEN_BUDGET = 700;
@ -1487,9 +1487,9 @@ function resolveLegacyProjectDir(
cwd: string,
): string | null {
const settings = asRecord(settingsManager.getGlobalSettings()) ?? {};
const legacySettings = asRecord(settings["pi-memory-md"]) ?? {};
const legacySettings = asRecord(settings["companion-memory-md"]) ?? {};
const configuredRoot =
asString(legacySettings.localPath) ?? join(homedir(), ".pi", "memory-md");
asString(legacySettings.localPath) ?? join(homedir(), ".companion", "memory-md");
const legacyRoot = expandHomePath(configuredRoot);
const legacyProjectDir = join(legacyRoot, basename(cwd));
if (existsSync(legacyProjectDir)) {

View file

@ -5,8 +5,8 @@
* and provides a transformer to convert them to LLM-compatible messages.
*/
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { ImageContent, Message, TextContent } from "@mariozechner/pi-ai";
import type { AgentMessage } from "@mariozechner/companion-agent-core";
import type { ImageContent, Message, TextContent } from "@mariozechner/companion-ai";
export const COMPACTION_SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:
@ -67,7 +67,7 @@ export interface CompactionSummaryMessage {
}
// Extend CustomAgentMessages via declaration merging
declare module "@mariozechner/pi-agent-core" {
declare module "@mariozechner/companion-agent-core" {
interface CustomAgentMessages {
bashExecution: BashExecutionMessage;
custom: CustomMessage;

View file

@ -16,11 +16,11 @@ import {
registerApiProvider,
resetApiProviders,
type SimpleStreamOptions,
} from "@mariozechner/pi-ai";
} from "@mariozechner/companion-ai";
import {
registerOAuthProvider,
resetOAuthProviders,
} from "@mariozechner/pi-ai/oauth";
} from "@mariozechner/companion-ai/oauth";
import { type Static, Type } from "@sinclair/typebox";
import AjvModule from "ajv";
import { existsSync, readFileSync } from "fs";

View file

@ -2,13 +2,13 @@
* Model resolution, scoping, and initial selection
*/
import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
import type { ThinkingLevel } from "@mariozechner/companion-agent-core";
import {
type Api,
type KnownProvider,
type Model,
modelsAreEqual,
} from "@mariozechner/pi-ai";
} from "@mariozechner/companion-ai";
import chalk from "chalk";
import { minimatch } from "minimatch";
import { isValidThinkingLevel } from "../cli/args.js";

View file

@ -20,7 +20,7 @@ import type { PackageSource, SettingsManager } from "./settings-manager.js";
const NETWORK_TIMEOUT_MS = 10000;
function isOfflineModeEnabled(): boolean {
const value = process.env.PI_OFFLINE;
const value = process.env.COMPANION_OFFLINE;
if (!value) return false;
return (
value === "1" ||
@ -445,8 +445,8 @@ function collectAutoThemeEntries(dir: string): string[] {
function readPiManifestFile(packageJsonPath: string): PiManifest | null {
try {
const content = readFileSync(packageJsonPath, "utf-8");
const pkg = JSON.parse(content) as { pi?: PiManifest };
return pkg.pi ?? null;
const pkg = JSON.parse(content) as { companion?: PiManifest };
return pkg.companion ?? null;
} catch {
return null;
}
@ -1529,7 +1529,7 @@ export class DefaultPackageManager implements PackageManager {
this.ensureGitIgnore(installRoot);
const packageJsonPath = join(installRoot, "package.json");
if (!existsSync(packageJsonPath)) {
const pkgJson = { name: "pi-extensions", private: true };
const pkgJson = { name: "companion-extensions", private: true };
writeFileSync(packageJsonPath, JSON.stringify(pkgJson, null, 2), "utf-8");
}
}
@ -1595,7 +1595,7 @@ export class DefaultPackageManager implements PackageManager {
.update(`${prefix}-${suffix ?? ""}`)
.digest("hex")
.slice(0, 8);
return join(tmpdir(), "pi-extensions", prefix, hash, suffix ?? "");
return join(tmpdir(), "companion-extensions", prefix, hash, suffix ?? "");
}
private getBaseDirForScope(scope: SourceScope): string {
@ -1784,8 +1784,8 @@ export class DefaultPackageManager implements PackageManager {
try {
const content = readFileSync(packageJsonPath, "utf-8");
const pkg = JSON.parse(content) as { pi?: PiManifest };
return pkg.pi ?? null;
const pkg = JSON.parse(content) as { companion?: PiManifest };
return pkg.companion ?? null;
} catch {
return null;
}

View file

@ -3,8 +3,8 @@ import {
Agent,
type AgentMessage,
type ThinkingLevel,
} from "@mariozechner/pi-agent-core";
import type { Message, Model } from "@mariozechner/pi-ai";
} from "@mariozechner/companion-agent-core";
import type { Message, Model } from "@mariozechner/companion-ai";
import { getAgentDir, getDocsPath } from "../config.js";
import { AgentSession } from "./agent-session.js";
import { AuthStorage } from "./auth-storage.js";
@ -52,7 +52,7 @@ import {
export interface CreateAgentSessionOptions {
/** Working directory for project-local discovery. Default: process.cwd() */
cwd?: string;
/** Global config directory. Default: ~/.pi/agent */
/** Global config directory. Default: ~/.companion/agent */
agentDir?: string;
/** Auth storage for credentials. Default: AuthStorage.create(agentDir/auth.json) */
@ -149,7 +149,7 @@ function getDefaultAgentDir(): string {
* const { session } = await createAgentSession();
*
* // With explicit model
* import { getModel } from '@mariozechner/pi-ai';
* import { getModel } from '@mariozechner/companion-ai';
* const { session } = await createAgentSession({
* model: getModel('anthropic', 'claude-opus-4-6'),
* thinkingLevel: 'high',

View file

@ -1,5 +1,5 @@
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { ImageContent, Message, TextContent } from "@mariozechner/pi-ai";
import type { AgentMessage } from "@mariozechner/companion-agent-core";
import type { ImageContent, Message, TextContent } from "@mariozechner/companion-ai";
import { randomUUID } from "crypto";
import {
appendFileSync,
@ -72,7 +72,7 @@ export interface CompactionEntry<T = unknown> extends SessionEntryBase {
tokensBefore: number;
/** Extension-specific data (e.g., ArtifactIndex, version markers for structured compaction) */
details?: T;
/** True if generated by an extension, undefined/false if pi-generated (backward compatible) */
/** True if generated by an extension, undefined/false if companion-generated (backward compatible) */
fromHook?: boolean;
}
@ -82,7 +82,7 @@ export interface BranchSummaryEntry<T = unknown> extends SessionEntryBase {
summary: string;
/** Extension-specific data (not sent to LLM) */
details?: T;
/** True if generated by an extension, false if pi-generated */
/** True if generated by an extension, false if companion-generated */
fromHook?: boolean;
}
@ -448,7 +448,7 @@ export function buildSessionContext(
/**
* Compute the default session directory for a cwd.
* Encodes cwd into a safe directory name under ~/.pi/agent/sessions/.
* Encodes cwd into a safe directory name under ~/.companion/agent/sessions/.
*/
function getDefaultSessionDir(cwd: string): string {
const safePath = `--${cwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
@ -1332,7 +1332,7 @@ export class SessionManager {
/**
* Create a new session.
* @param cwd Working directory (stored in session header)
* @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).
* @param sessionDir Optional session directory. If omitted, uses default (~/.companion/agent/sessions/<encoded-cwd>/).
*/
static create(cwd: string, sessionDir?: string): SessionManager {
const dir = sessionDir ?? getDefaultSessionDir(cwd);
@ -1359,7 +1359,7 @@ export class SessionManager {
/**
* Continue the most recent session, or create new if none.
* @param cwd Working directory
* @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).
* @param sessionDir Optional session directory. If omitted, uses default (~/.companion/agent/sessions/<encoded-cwd>/).
*/
static continueRecent(cwd: string, sessionDir?: string): SessionManager {
const dir = sessionDir ?? getDefaultSessionDir(cwd);
@ -1438,7 +1438,7 @@ export class SessionManager {
/**
* List all sessions for a directory.
* @param cwd Working directory (used to compute default session directory)
* @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).
* @param sessionDir Optional session directory. If omitted, uses default (~/.companion/agent/sessions/<encoded-cwd>/).
* @param onProgress Optional callback for progress updates (loaded, total)
*/
static async list(

View file

@ -1,4 +1,4 @@
import type { Transport } from "@mariozechner/pi-ai";
import type { Transport } from "@mariozechner/companion-ai";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
import { dirname, join } from "path";
import lockfile from "proper-lockfile";
@ -944,7 +944,7 @@ export class SettingsManager {
if (this.settings.terminal?.clearOnShrink !== undefined) {
return this.settings.terminal.clearOnShrink;
}
return process.env.PI_CLEAR_ON_SHRINK === "1";
return process.env.COMPANION_CLEAR_ON_SHRINK === "1";
}
setClearOnShrink(enabled: boolean): void {
@ -1023,7 +1023,7 @@ export class SettingsManager {
getShowHardwareCursor(): boolean {
return (
this.settings.showHardwareCursor ?? process.env.PI_HARDWARE_CURSOR === "1"
this.settings.showHardwareCursor ?? process.env.COMPANION_HARDWARE_CURSOR === "1"
);
}

View file

@ -361,7 +361,7 @@ function escapeXml(str: string): string {
export interface LoadSkillsOptions {
/** Working directory for project-local skills. Default: process.cwd() */
cwd?: string;
/** Agent config directory for global skills. Default: ~/.pi/agent */
/** Agent config directory for global skills. Default: ~/.companion/agent */
agentDir?: string;
/** Explicit skill paths (files or directories) */
skillPaths?: string[];

View file

@ -40,5 +40,5 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
name: "reload",
description: "Reload extensions, skills, prompts, and themes",
},
{ name: "quit", description: "Quit pi" },
{ name: "quit", description: "Quit companion" },
];

View file

@ -1,9 +1,9 @@
/**
* Central timing instrumentation for startup profiling.
* Enable with PI_TIMING=1 environment variable.
* Enable with COMPANION_TIMING=1 environment variable.
*/
const ENABLED = process.env.PI_TIMING === "1";
const ENABLED = process.env.COMPANION_TIMING === "1";
const timings: Array<{ label: string; ms: number }> = [];
let lastTime = Date.now();

View file

@ -2,7 +2,7 @@ import { randomBytes } from "node:crypto";
import { createWriteStream, existsSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import type { AgentTool } from "@mariozechner/pi-agent-core";
import type { AgentTool } from "@mariozechner/companion-agent-core";
import { type Static, Type } from "@sinclair/typebox";
import { spawn } from "child_process";
import {
@ -23,7 +23,7 @@ import {
*/
function getTempFilePath(): string {
const id = randomBytes(8).toString("hex");
return join(tmpdir(), `pi-bash-${id}.log`);
return join(tmpdir(), `companion-bash-${id}.log`);
}
/**

View file

@ -3,7 +3,7 @@ import { randomBytes } from "node:crypto";
import { existsSync, mkdirSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import type { AgentTool } from "@mariozechner/pi-agent-core";
import type { AgentTool } from "@mariozechner/companion-agent-core";
import { type Static, Type } from "@sinclair/typebox";
import { getAgentDir } from "../../config.js";
import {
@ -28,7 +28,7 @@ const browserSnapshotModes = ["interactive", "full"] as const;
const browserLoadStates = ["load", "domcontentloaded", "networkidle"] as const;
const DEFAULT_BROWSER_COMMAND =
process.env.PI_AGENT_BROWSER_COMMAND || "agent-browser";
process.env.COMPANION_AGENT_BROWSER_COMMAND || "agent-browser";
const DEFAULT_BROWSER_TIMEOUT_SECONDS = 90;
const browserSchema = Type.Object({
@ -78,7 +78,7 @@ const browserSchema = Type.Object({
stateName: Type.Optional(
Type.String({
description:
"Named browser state checkpoint stored under ~/.pi/agent/browser/states/",
"Named browser state checkpoint stored under ~/.companion/agent/browser/states/",
}),
),
});
@ -230,7 +230,7 @@ function getBrowserStateDir(cwd: string, options?: BrowserToolOptions): string {
function createTempScreenshotPath(): string {
const id = randomBytes(8).toString("hex");
return join(tmpdir(), `pi-browser-screenshot-${id}.png`);
return join(tmpdir(), `companion-browser-screenshot-${id}.png`);
}
function normalizeOutput(chunks: Buffer[]): string {

View file

@ -1,4 +1,4 @@
import type { AgentTool } from "@mariozechner/pi-agent-core";
import type { AgentTool } from "@mariozechner/companion-agent-core";
import { type Static, Type } from "@sinclair/typebox";
import { constants } from "fs";
import {

View file

@ -1,4 +1,4 @@
import type { AgentTool } from "@mariozechner/pi-agent-core";
import type { AgentTool } from "@mariozechner/companion-agent-core";
import { type Static, Type } from "@sinclair/typebox";
import { spawnSync } from "child_process";
import { existsSync } from "fs";

View file

@ -1,5 +1,5 @@
import { createInterface } from "node:readline";
import type { AgentTool } from "@mariozechner/pi-agent-core";
import type { AgentTool } from "@mariozechner/companion-agent-core";
import { type Static, Type } from "@sinclair/typebox";
import { spawn } from "child_process";
import { readFileSync, statSync } from "fs";

View file

@ -77,7 +77,7 @@ export {
writeTool,
} from "./write.js";
import type { AgentTool } from "@mariozechner/pi-agent-core";
import type { AgentTool } from "@mariozechner/companion-agent-core";
import { type BashToolOptions, bashTool, createBashTool } from "./bash.js";
import {
browserTool,
@ -91,7 +91,7 @@ import { createLsTool, lsTool } from "./ls.js";
import { createReadTool, type ReadToolOptions, readTool } from "./read.js";
import { createWriteTool, writeTool } from "./write.js";
/** Tool type (AgentTool from pi-ai) */
/** Tool type (AgentTool from companion-ai) */
export type Tool = AgentTool<any>;
// Read-only tools for exploration without modification (using process.cwd())

View file

@ -1,4 +1,4 @@
import type { AgentTool } from "@mariozechner/pi-agent-core";
import type { AgentTool } from "@mariozechner/companion-agent-core";
import { type Static, Type } from "@sinclair/typebox";
import { existsSync, readdirSync, statSync } from "fs";
import nodePath from "path";

View file

@ -1,5 +1,5 @@
import type { AgentTool } from "@mariozechner/pi-agent-core";
import type { ImageContent, TextContent } from "@mariozechner/pi-ai";
import type { AgentTool } from "@mariozechner/companion-agent-core";
import type { ImageContent, TextContent } from "@mariozechner/companion-ai";
import { type Static, Type } from "@sinclair/typebox";
import { constants } from "fs";
import { access as fsAccess, readFile as fsReadFile } from "fs/promises";

View file

@ -1,4 +1,4 @@
import type { AgentTool } from "@mariozechner/pi-agent-core";
import type { AgentTool } from "@mariozechner/companion-agent-core";
import { type Static, Type } from "@sinclair/typebox";
import { mkdir as fsMkdir, writeFile as fsWriteFile } from "fs/promises";
import { dirname } from "path";

View file

@ -10,7 +10,7 @@ import {
type ImageContent,
modelsAreEqual,
supportsXhigh,
} from "@mariozechner/pi-ai";
} from "@mariozechner/companion-ai";
import chalk from "chalk";
import { createInterface } from "readline";
import { type Args, parseArgs, printHelp } from "./cli/args.js";
@ -123,7 +123,7 @@ function printDaemonHelp(): void {
${APP_NAME} gateway [options] [messages...]
${APP_NAME} daemon [options] [messages...]
Run pi as a long-lived gateway (non-interactive) with extensions enabled.
Run companion as a long-lived gateway (non-interactive) with extensions enabled.
Messages passed as positional args are sent once at startup.
Options:
@ -154,7 +154,7 @@ function printPackageCommandHelp(command: PackageCommand): void {
Install a package and add it to settings.
Options:
-l, --local Install project-locally (.pi/settings.json)
-l, --local Install project-locally (.companion/settings.json)
Examples:
${APP_NAME} install npm:@foo/bar
@ -173,7 +173,7 @@ Examples:
Remove a package and its source from settings.
Options:
-l, --local Remove from project settings (.pi/settings.json)
-l, --local Remove from project settings (.companion/settings.json)
Example:
${APP_NAME} remove npm:@foo/bar
@ -661,10 +661,10 @@ export async function main(args: string[]) {
const isGatewayCommand = args[0] === "daemon" || args[0] === "gateway";
const parsedArgs = isGatewayCommand ? args.slice(1) : args;
const offlineMode =
parsedArgs.includes("--offline") || isTruthyEnvFlag(process.env.PI_OFFLINE);
parsedArgs.includes("--offline") || isTruthyEnvFlag(process.env.COMPANION_OFFLINE);
if (offlineMode) {
process.env.PI_OFFLINE = "1";
process.env.PI_SKIP_VERSION_CHECK = "1";
process.env.COMPANION_OFFLINE = "1";
process.env.COMPANION_SKIP_VERSION_CHECK = "1";
}
if (await handlePackageCommand(args)) {
@ -993,7 +993,7 @@ export async function main(args: string[]) {
} catch (error) {
const message =
error instanceof Error ? error.stack || error.message : String(error);
console.error(`[pi-gateway] daemon crashed: ${message}`);
console.error(`[companion-gateway] daemon crashed: ${message}`);
try {
session.dispose();
} catch {
@ -1005,20 +1005,20 @@ export async function main(args: string[]) {
if (runtimeMs < GATEWAY_MIN_RUNTIME_MS) {
consecutiveFailures += 1;
console.error(
`[pi-gateway] exited quickly (${runtimeMs}ms), failure ${consecutiveFailures}/${GATEWAY_MAX_CONSECUTIVE_FAILURES}`,
`[companion-gateway] exited quickly (${runtimeMs}ms), failure ${consecutiveFailures}/${GATEWAY_MAX_CONSECUTIVE_FAILURES}`,
);
if (consecutiveFailures >= GATEWAY_MAX_CONSECUTIVE_FAILURES) {
console.error("[pi-gateway] crash loop detected, exiting");
console.error("[companion-gateway] crash loop detected, exiting");
process.exit(1);
}
} else {
consecutiveFailures = 0;
console.error(`[pi-gateway] exited after ${runtimeMs}ms, restarting`);
console.error(`[companion-gateway] exited after ${runtimeMs}ms, restarting`);
}
if (GATEWAY_RESTART_DELAY_MS > 0) {
console.error(
`[pi-gateway] restarting in ${GATEWAY_RESTART_DELAY_MS}ms`,
`[companion-gateway] restarting in ${GATEWAY_RESTART_DELAY_MS}ms`,
);
await sleep(GATEWAY_RESTART_DELAY_MS);
}

View file

@ -16,9 +16,9 @@ import { dirname, join } from "path";
import { CONFIG_DIR_NAME, getAgentDir, getBinDir } from "./config.js";
const MIGRATION_GUIDE_URL =
"https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration";
"https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration";
const EXTENSIONS_DOC_URL =
"https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/extensions.md";
"https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/docs/extensions.md";
/**
* Migrate legacy oauth.json and settings.json apiKeys to auth.json.
@ -80,13 +80,13 @@ export function migrateAuthToAuthJson(): string[] {
}
/**
* Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.
* Migrate sessions from ~/.companion/agent/*.jsonl to proper session directories.
*
* Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of
* ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them
* Bug in v0.30.0: Sessions were saved to ~/.companion/agent/ instead of
* ~/.companion/agent/sessions/<encoded-cwd>/. This migration moves them
* to the correct location based on the cwd in their session header.
*
* See: https://github.com/badlogic/pi-mono/issues/320
* See: https://github.com/badlogic/companion-mono/issues/320
*/
export function migrateSessionsFromAgentRoot(): void {
const agentDir = getAgentDir();
@ -207,7 +207,7 @@ function migrateToolsToBin(): void {
/**
* Check for deprecated hooks/ and tools/ directories.
* Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.
* Note: tools/ may contain fd/rg binaries extracted by companion, so only warn if it has other files.
*/
function checkDeprecatedExtensionDirs(
baseDir: string,

View file

@ -6,7 +6,7 @@
* until explicitly stopped.
*/
import type { ImageContent } from "@mariozechner/pi-ai";
import type { ImageContent } from "@mariozechner/companion-ai";
import type { AgentSession } from "../core/agent-session.js";
import {
GatewayRuntime,
@ -98,13 +98,13 @@ export async function runDaemonMode(
resolveReady = resolve;
});
const gatewayBind =
process.env.PI_GATEWAY_BIND ?? options.gateway.bind ?? "127.0.0.1";
process.env.COMPANION_GATEWAY_BIND ?? options.gateway.bind ?? "127.0.0.1";
const gatewayPort =
Number.parseInt(process.env.PI_GATEWAY_PORT ?? "", 10) ||
Number.parseInt(process.env.COMPANION_GATEWAY_PORT ?? "", 10) ||
options.gateway.port ||
8787;
const gatewayToken =
process.env.PI_GATEWAY_TOKEN ?? options.gateway.bearerToken;
process.env.COMPANION_GATEWAY_TOKEN ?? options.gateway.bearerToken;
const gateway = new GatewayRuntime({
config: {
bind: gatewayBind,
@ -118,7 +118,7 @@ export async function runDaemonMode(
enabled: options.gateway.webhook?.enabled ?? true,
basePath: options.gateway.webhook?.basePath ?? "/webhooks",
secret:
process.env.PI_GATEWAY_WEBHOOK_SECRET ??
process.env.COMPANION_GATEWAY_WEBHOOK_SECRET ??
options.gateway.webhook?.secret,
},
},
@ -126,7 +126,7 @@ export async function runDaemonMode(
primarySession: session,
createSession: options.createSession,
log: (message) => {
console.error(`[pi-gateway] ${message}`);
console.error(`[companion-gateway] ${message}`);
},
});
setActiveGatewayRuntime(gateway);
@ -135,7 +135,7 @@ export async function runDaemonMode(
if (isShuttingDown) return;
isShuttingDown = true;
console.error(`[pi-gateway] shutdown requested: ${reason}`);
console.error(`[companion-gateway] shutdown requested: ${reason}`);
setActiveGatewayRuntime(null);
await gateway.stop();
@ -151,7 +151,7 @@ export async function runDaemonMode(
const handleShutdownSignal = (signal: NodeJS.Signals) => {
void shutdown("signal").catch((error) => {
console.error(
`[pi-gateway] shutdown failed for ${signal}: ${error instanceof Error ? error.message : String(error)}`,
`[companion-gateway] shutdown failed for ${signal}: ${error instanceof Error ? error.message : String(error)}`,
);
resolveReady({ reason: "shutdown" });
});
@ -162,7 +162,7 @@ export async function runDaemonMode(
const sighupHandler = () => handleShutdownSignal("SIGHUP");
const unhandledRejectionHandler = (error: unknown) => {
console.error(
`[pi-gateway] unhandled rejection: ${error instanceof Error ? error.message : String(error)}`,
`[companion-gateway] unhandled rejection: ${error instanceof Error ? error.message : String(error)}`,
);
};
@ -177,7 +177,7 @@ export async function runDaemonMode(
shutdownHandler: () => {
void shutdown("extension").catch((error) => {
console.error(
`[pi-gateway] extension shutdown failed: ${error instanceof Error ? error.message : String(error)}`,
`[companion-gateway] extension shutdown failed: ${error instanceof Error ? error.message : String(error)}`,
);
resolveReady({ reason: "shutdown" });
});
@ -208,7 +208,7 @@ export async function runDaemonMode(
await gateway.start();
console.error(
`[pi-gateway] startup complete (session=${session.sessionId ?? "unknown"}, bind=${gatewayBind}, port=${gatewayPort})`,
`[companion-gateway] startup complete (session=${session.sessionId ?? "unknown"}, bind=${gatewayBind}, port=${gatewayPort})`,
);
// Keep process alive forever.

View file

@ -2,7 +2,7 @@
* Armin says hi! A fun easter egg with animated XBM art.
*/
import type { Component, TUI } from "@mariozechner/pi-tui";
import type { Component, TUI } from "@mariozechner/companion-tui";
import { theme } from "../theme/theme.js";
// XBM image: 31x36 pixels, LSB first, 1=background, 0=foreground

View file

@ -1,11 +1,11 @@
import type { AssistantMessage } from "@mariozechner/pi-ai";
import type { AssistantMessage } from "@mariozechner/companion-ai";
import {
Container,
Markdown,
type MarkdownTheme,
Spacer,
Text,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { getMarkdownTheme, theme } from "../theme/theme.js";
/**

View file

@ -8,7 +8,7 @@ import {
Spacer,
Text,
type TUI,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import stripAnsi from "strip-ansi";
import {
DEFAULT_MAX_BYTES,

View file

@ -5,7 +5,7 @@ import {
Spacer,
Text,
type TUI,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type { Theme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";
import { keyHint } from "./keybinding-hints.js";

View file

@ -4,7 +4,7 @@ import {
type MarkdownTheme,
Spacer,
Text,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type { BranchSummaryMessage } from "../../../core/messages.js";
import { getMarkdownTheme, theme } from "../theme/theme.js";
import { editorKey } from "./keybinding-hints.js";

View file

@ -4,7 +4,7 @@ import {
type MarkdownTheme,
Spacer,
Text,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type { CompactionSummaryMessage } from "../../../core/messages.js";
import { getMarkdownTheme, theme } from "../theme/theme.js";
import { editorKey } from "./keybinding-hints.js";

View file

@ -13,7 +13,7 @@ import {
Spacer,
truncateToWidth,
visibleWidth,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { CONFIG_DIR_NAME } from "../../../config.js";
import type {
PathMetadata,
@ -68,7 +68,7 @@ function getGroupLabel(metadata: PathMetadata): string {
}
// Top-level resources
if (metadata.source === "auto") {
return metadata.scope === "user" ? "User (~/.pi/agent/)" : "Project (.pi/)";
return metadata.scope === "user" ? "User (~/.companion/agent/)" : "Project (.companion/)";
}
return metadata.scope === "user" ? "User settings" : "Project settings";
}

View file

@ -2,7 +2,7 @@
* Reusable countdown timer for dialog components.
*/
import type { TUI } from "@mariozechner/pi-tui";
import type { TUI } from "@mariozechner/companion-tui";
export class CountdownTimer {
private intervalId: ReturnType<typeof setInterval> | undefined;

View file

@ -3,7 +3,7 @@ import {
type EditorOptions,
type EditorTheme,
type TUI,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type {
AppAction,
KeybindingsManager,

View file

@ -1,5 +1,5 @@
import type { TextContent } from "@mariozechner/pi-ai";
import type { Component } from "@mariozechner/pi-tui";
import type { TextContent } from "@mariozechner/companion-ai";
import type { Component } from "@mariozechner/companion-tui";
import {
Box,
Container,
@ -7,7 +7,7 @@ import {
type MarkdownTheme,
Spacer,
Text,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type { MessageRenderer } from "../../../core/extensions/types.js";
import type { CustomMessage } from "../../../core/messages.js";
import { getMarkdownTheme, theme } from "../theme/theme.js";

View file

@ -4,7 +4,7 @@
* A heartfelt tribute to dax (@thdxr) for providing free Kimi K2.5 access via OpenCode.
*/
import type { Component, TUI } from "@mariozechner/pi-tui";
import type { Component, TUI } from "@mariozechner/companion-tui";
import { theme } from "../theme/theme.js";
// 32x32 RGB image of dax, hex encoded (3 bytes per pixel)

View file

@ -1,4 +1,4 @@
import type { Component } from "@mariozechner/pi-tui";
import type { Component } from "@mariozechner/companion-tui";
import { theme } from "../theme/theme.js";
/**

View file

@ -16,7 +16,7 @@ import {
Spacer,
Text,
type TUI,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type { KeybindingsManager } from "../../../core/keybindings.js";
import { getEditorTheme, theme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";
@ -121,7 +121,7 @@ export class ExtensionEditorComponent extends Container implements Focusable {
const currentText = this.editor.getText();
const tmpFile = path.join(
os.tmpdir(),
`pi-extension-editor-${Date.now()}.md`,
`companion-extension-editor-${Date.now()}.md`,
);
try {

View file

@ -10,7 +10,7 @@ import {
Spacer,
Text,
type TUI,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { theme } from "../theme/theme.js";
import { CountdownTimer } from "./countdown-timer.js";
import { DynamicBorder } from "./dynamic-border.js";

View file

@ -9,7 +9,7 @@ import {
Spacer,
Text,
type TUI,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { theme } from "../theme/theme.js";
import { CountdownTimer } from "./countdown-timer.js";
import { DynamicBorder } from "./dynamic-border.js";

View file

@ -2,7 +2,7 @@ import {
type Component,
truncateToWidth,
visibleWidth,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type { AgentSession } from "../../../core/agent-session.js";
import type { ReadonlyFooterDataProvider } from "../../../core/footer-data-provider.js";
import { theme } from "../theme/theme.js";

View file

@ -6,7 +6,7 @@ import {
type EditorAction,
getEditorKeybindings,
type KeyId,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type {
AppAction,
KeybindingsManager,

View file

@ -1,4 +1,4 @@
import { getOAuthProviders } from "@mariozechner/pi-ai/oauth";
import { getOAuthProviders } from "@mariozechner/companion-ai/oauth";
import {
Container,
type Focusable,
@ -7,7 +7,7 @@ import {
Spacer,
Text,
type TUI,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { exec } from "child_process";
import { theme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";

View file

@ -1,4 +1,4 @@
import { type Model, modelsAreEqual } from "@mariozechner/pi-ai";
import { type Model, modelsAreEqual } from "@mariozechner/companion-ai";
import {
Container,
type Focusable,
@ -8,7 +8,7 @@ import {
Spacer,
Text,
type TUI,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type { ModelRegistry } from "../../../core/model-registry.js";
import type { SettingsManager } from "../../../core/settings-manager.js";
import { theme } from "../theme/theme.js";

View file

@ -1,11 +1,11 @@
import type { OAuthProviderInterface } from "@mariozechner/pi-ai";
import { getOAuthProviders } from "@mariozechner/pi-ai/oauth";
import type { OAuthProviderInterface } from "@mariozechner/companion-ai";
import { getOAuthProviders } from "@mariozechner/companion-ai/oauth";
import {
Container,
getEditorKeybindings,
Spacer,
TruncatedText,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type { AuthStorage } from "../../../core/auth-storage.js";
import { theme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";

View file

@ -1,4 +1,4 @@
import type { Model } from "@mariozechner/pi-ai";
import type { Model } from "@mariozechner/companion-ai";
import {
Container,
type Focusable,
@ -9,7 +9,7 @@ import {
matchesKey,
Spacer,
Text,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { theme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";

View file

@ -1,4 +1,4 @@
import { fuzzyMatch } from "@mariozechner/pi-tui";
import { fuzzyMatch } from "@mariozechner/companion-tui";
import type { SessionInfo } from "../../../core/session-manager.js";
export type SortMode = "threaded" | "recent" | "relevance";

View file

@ -13,7 +13,7 @@ import {
Text,
truncateToWidth,
visibleWidth,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { KeybindingsManager } from "../../../core/keybindings.js";
import type {
SessionInfo,
@ -607,7 +607,7 @@ class SessionList implements Component, Focusable {
void this.onDeleteSession?.(pathToDelete);
return;
}
// Allow both Escape and Ctrl+C to cancel (consistent with pi UX)
// Allow both Escape and Ctrl+C to cancel (consistent with companion UX)
if (
kb.matches(keyData, "selectCancel") ||
matchesKey(keyData, "ctrl+c")

View file

@ -1,5 +1,5 @@
import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
import type { Transport } from "@mariozechner/pi-ai";
import type { ThinkingLevel } from "@mariozechner/companion-agent-core";
import type { Transport } from "@mariozechner/companion-ai";
import {
Container,
getCapabilities,
@ -9,7 +9,7 @@ import {
SettingsList,
Spacer,
Text,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import {
getSelectListTheme,
getSettingsListTheme,

View file

@ -1,4 +1,4 @@
import { Container, type SelectItem, SelectList } from "@mariozechner/pi-tui";
import { Container, type SelectItem, SelectList } from "@mariozechner/companion-tui";
import { getSelectListTheme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";

View file

@ -1,4 +1,4 @@
import { Box, Markdown, type MarkdownTheme, Text } from "@mariozechner/pi-tui";
import { Box, Markdown, type MarkdownTheme, Text } from "@mariozechner/companion-tui";
import type { ParsedSkillBlock } from "../../../core/agent-session.js";
import { getMarkdownTheme, theme } from "../theme/theme.js";
import { editorKey } from "./keybinding-hints.js";

View file

@ -1,4 +1,4 @@
import { Container, type SelectItem, SelectList } from "@mariozechner/pi-tui";
import { Container, type SelectItem, SelectList } from "@mariozechner/companion-tui";
import { getAvailableThemes, getSelectListTheme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";

View file

@ -1,5 +1,5 @@
import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
import { Container, type SelectItem, SelectList } from "@mariozechner/pi-tui";
import type { ThinkingLevel } from "@mariozechner/companion-agent-core";
import { Container, type SelectItem, SelectList } from "@mariozechner/companion-tui";
import { getSelectListTheme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";

View file

@ -10,7 +10,7 @@ import {
Text,
type TUI,
truncateToWidth,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import stripAnsi from "strip-ansi";
import type { ToolDefinition } from "../../../core/extensions/types.js";
import {

View file

@ -9,7 +9,7 @@ import {
Text,
TruncatedText,
truncateToWidth,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import type { SessionTreeNode } from "../../../core/session-manager.js";
import { theme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";

View file

@ -5,7 +5,7 @@ import {
Spacer,
Text,
truncateToWidth,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { theme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";

View file

@ -3,7 +3,7 @@ import {
Markdown,
type MarkdownTheme,
Spacer,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { getMarkdownTheme, theme } from "../theme/theme.js";
const OSC133_ZONE_START = "\x1b]133;A\x07";

View file

@ -3,7 +3,7 @@
* Used by both tool-execution.ts and bash-execution.ts for consistent behavior.
*/
import { Text } from "@mariozechner/pi-tui";
import { Text } from "@mariozechner/companion-tui";
export interface VisualTruncateResult {
/** The visual lines to display */

View file

@ -7,14 +7,14 @@ import * as crypto from "node:crypto";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import type { AgentMessage } from "@mariozechner/pi-agent-core";
import type { AgentMessage } from "@mariozechner/companion-agent-core";
import type {
AssistantMessage,
ImageContent,
Message,
Model,
OAuthProviderId,
} from "@mariozechner/pi-ai";
} from "@mariozechner/companion-ai";
import type {
AutocompleteItem,
EditorAction,
@ -25,7 +25,7 @@ import type {
OverlayHandle,
OverlayOptions,
SlashCommand,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import {
CombinedAutocompleteProvider,
type Component,
@ -40,7 +40,7 @@ import {
TruncatedText,
TUI,
visibleWidth,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { spawn, spawnSync } from "child_process";
import {
APP_NAME,
@ -666,12 +666,12 @@ export class InteractiveMode {
* Check npm registry for a newer version.
*/
private async checkForNewVersion(): Promise<string | undefined> {
if (process.env.PI_SKIP_VERSION_CHECK || process.env.PI_OFFLINE)
if (process.env.COMPANION_SKIP_VERSION_CHECK || process.env.COMPANION_OFFLINE)
return undefined;
try {
const response = await fetch(
"https://registry.npmjs.org/@mariozechner/pi-coding-agent/latest",
"https://registry.npmjs.org/@mariozechner/companion-coding-agent/latest",
{
signal: AbortSignal.timeout(10000),
},
@ -2141,7 +2141,7 @@ export class InteractiveMode {
// Write to temp file
const tmpDir = os.tmpdir();
const ext = extensionForImageMimeType(image.mimeType) ?? "png";
const fileName = `pi-clipboard-${crypto.randomUUID()}.${ext}`;
const fileName = `companion-clipboard-${crypto.randomUUID()}.${ext}`;
const filePath = path.join(tmpDir, fileName);
fs.writeFileSync(filePath, Buffer.from(image.bytes));
@ -3110,7 +3110,7 @@ export class InteractiveMode {
const currentText =
this.editor.getExpandedText?.() ?? this.editor.getText();
const tmpFile = path.join(os.tmpdir(), `pi-editor-${Date.now()}.pi.md`);
const tmpFile = path.join(os.tmpdir(), `companion-editor-${Date.now()}.companion.md`);
try {
// Write current content to temp file
@ -3176,13 +3176,13 @@ export class InteractiveMode {
showNewVersionNotification(newVersion: string): void {
const action = theme.fg(
"accent",
getUpdateInstruction("@mariozechner/pi-coding-agent"),
getUpdateInstruction("@mariozechner/companion-coding-agent"),
);
const updateInstruction =
theme.fg("muted", `New version ${newVersion} is available. `) + action;
const changelogUrl = theme.fg(
"accent",
"https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md",
"https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/CHANGELOG.md",
);
const changelogLine = theme.fg("muted", "Changelog: ") + changelogUrl;

View file

@ -1,5 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
"$schema": "https://raw.githubusercontent.com/badlogic/companion-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
"name": "dark",
"vars": {
"cyan": "#00d7ff",

View file

@ -1,5 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
"$schema": "https://raw.githubusercontent.com/badlogic/companion-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
"name": "light",
"vars": {
"teal": "#5a8080",

View file

@ -1,7 +1,7 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Pi Coding Agent Theme",
"description": "Theme schema for Pi coding agent",
"title": "Companion Coding Agent Theme",
"description": "Theme schema for companion coding agent",
"type": "object",
"required": ["name", "colors"],
"properties": {

View file

@ -4,7 +4,7 @@ import type {
EditorTheme,
MarkdownTheme,
SelectListTheme,
} from "@mariozechner/pi-tui";
} from "@mariozechner/companion-tui";
import { type Static, Type } from "@sinclair/typebox";
import { TypeCompiler } from "@sinclair/typebox/compiler";
import chalk from "chalk";
@ -682,7 +682,7 @@ function getDefaultTheme(): string {
// ============================================================================
// Use globalThis to share theme across module loaders (tsx + jiti in dev mode)
const THEME_KEY = Symbol.for("@mariozechner/pi-coding-agent:theme");
const THEME_KEY = Symbol.for("@mariozechner/companion-coding-agent:theme");
// Export theme as a getter that reads from globalThis
// This ensures all module instances (tsx, jiti) see the same theme
@ -1144,7 +1144,7 @@ export function getEditorTheme(): EditorTheme {
};
}
export function getSettingsListTheme(): import("@mariozechner/pi-tui").SettingsListTheme {
export function getSettingsListTheme(): import("@mariozechner/companion-tui").SettingsListTheme {
return {
label: (text: string, selected: boolean) =>
selected ? theme.fg("accent", text) : text,

View file

@ -2,11 +2,11 @@
* Print mode (single-shot): Send prompts, output result, exit.
*
* Used for:
* - `pi -p "prompt"` - text output
* - `pi --mode json "prompt"` - JSON event stream
* - `companion -p "prompt"` - text output
* - `companion --mode json "prompt"` - JSON event stream
*/
import type { AssistantMessage, ImageContent } from "@mariozechner/pi-ai";
import type { AssistantMessage, ImageContent } from "@mariozechner/companion-ai";
import type { AgentSession } from "../core/agent-session.js";
/**

View file

@ -10,8 +10,8 @@ import type {
AgentEvent,
AgentMessage,
ThinkingLevel,
} from "@mariozechner/pi-agent-core";
import type { ImageContent } from "@mariozechner/pi-ai";
} from "@mariozechner/companion-agent-core";
import type { ImageContent } from "@mariozechner/companion-ai";
import type { SessionStats } from "../../core/agent-session.js";
import type { BashResult } from "../../core/bash-executor.js";
import type { CompactionResult } from "../../core/compaction/index.js";

View file

@ -5,8 +5,8 @@
* Responses and events are emitted as JSON lines on stdout.
*/
import type { AgentMessage, ThinkingLevel } from "@mariozechner/pi-agent-core";
import type { ImageContent, Model } from "@mariozechner/pi-ai";
import type { AgentMessage, ThinkingLevel } from "@mariozechner/companion-agent-core";
import type { ImageContent, Model } from "@mariozechner/companion-ai";
import type { SessionStats } from "../../core/agent-session.js";
import type { BashResult } from "../../core/bash-executor.js";
import type { CompactionResult } from "../../core/compaction/index.js";

View file

@ -1,4 +1,4 @@
import type { ImageContent } from "@mariozechner/pi-ai";
import type { ImageContent } from "@mariozechner/companion-ai";
import { loadPhoton } from "./photon.js";
export interface ImageResizeOptions {

View file

@ -20,7 +20,7 @@ const TOOLS_DIR = getBinDir();
const NETWORK_TIMEOUT_MS = 10000;
function isOfflineModeEnabled(): boolean {
const value = process.env.PI_OFFLINE;
const value = process.env.COMPANION_OFFLINE;
if (!value) return false;
return (
value === "1" ||