From 43d9d94051a3b7a012e404d87ae45bb197644872 Mon Sep 17 00:00:00 2001 From: alpertarhan Date: Mon, 7 Sep 2026 15:15:26 +0300 Subject: [PATCH 1/2] feat: silent visual defaults and host-adaptive config locations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Silent by default: the dashboard widget and its footer status line were installed automatically in active repositories. Users who only want the tools now get exactly that — dashboard.enabled defaults to false, so nothing is drawn on screen until it is enabled explicitly; watch notifications still follow dashboard.notifications independently. Host-adaptive config: config paths were hardcoded to ~/.pi/agent and /.pi. Under omp the toolkit now prefers the active agent directory (~/.omp/agent) and the project .omp/ directory, falling back to the legacy .pi locations when they already hold a config so existing shared setups keep working on upgrade. pi behavior is unchanged. The host context is resolved once at session start in the extension entry, which keeps config.ts free of pi-coding-agent imports (they would drag optional dependencies into the test graph). Verified live on both hosts: omp resolves the legacy shared config and activates in-repository (forgejo_context current reports the resolved repo), pi regression unchanged; vitest 212/212. --- CHANGELOG.md | 5 ++++ src/config.ts | 53 ++++++++++++++++++++++++++++++++++++---- src/extension.ts | 18 ++++++++++++++ test/config-refs.test.ts | 2 +- 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e816172..de65d1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [Unreleased] +### Changed + +- The dashboard widget and its footer status are now off by default (`dashboard.enabled: false`): a repository still activates the tools and skills, but nothing is drawn on screen until the dashboard is enabled explicitly. Watch notifications keep following `dashboard.notifications` independently. +- Host-adaptive config locations: under omp the active agent directory (`~/.omp/agent`) and project `.omp/` directory are preferred, with a legacy fallback so an existing `~/.pi/agent/forgejo.json` or `/.pi/forgejo.json` keeps working unchanged; pi paths are untouched. + ## [0.9.0] - 2026-09-07 ### Added diff --git a/src/config.ts b/src/config.ts index da1c2eb..138e793 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,3 +1,4 @@ +import { existsSync } from "node:fs"; import { readFile } from "node:fs/promises"; import { homedir } from "node:os"; import { dirname, isAbsolute, resolve } from "node:path"; @@ -18,7 +19,7 @@ import type { } from "./types.js"; const DEFAULT_DASHBOARD: DashboardConfig = { - enabled: true, + enabled: false, scope: "all", refreshSeconds: 90, previewLimit: 3, @@ -398,16 +399,58 @@ export async function loadGlobalAllowedMutations( throw new ConfigError(`${globalConfigPath} must contain a JSON object`); return parseAllowedMutationKeys(value.allowedMutations); } +interface ConfigHostContext { + isOmp: boolean; + agentDir?: string | undefined; +} + +let hostContext: ConfigHostContext | undefined; +/** + * Called by the extension entry once the host module is available. Keeps + * config.ts free of pi-coding-agent imports (which would drag optional + * dependencies into the test graph) while letting the running host decide + * where config lives. + */ +export function setConfigHostContext(context: ConfigHostContext | undefined): void { + hostContext = context; +} + +/** + * Host-adaptive config locations with a legacy fallback. + * + * pi keeps its historical paths (~/.pi/agent/forgejo.json, /.pi/). + * Under omp the active agent directory is ~/.omp/agent and the project + * config directory is .omp/, but a config left at the legacy .pi location + * keeps working so existing shared setups do not break on upgrade. + */ export function configPaths( cwd: string, env: NodeJS.ProcessEnv = process.env, ): { global: string; project: string } { + const legacyGlobal = resolve(homedir(), ".pi", "agent", "forgejo.json"); + let global = legacyGlobal; + let project = resolve(cwd, ".pi", "forgejo.json"); + if (hostContext?.isOmp) { + const hostGlobal = hostContext.agentDir + ? resolve(hostContext.agentDir, "forgejo.json") + : legacyGlobal; + const hostProject = resolve(cwd, ".omp", "forgejo.json"); + const legacyProject = resolve(cwd, ".pi", "forgejo.json"); + global = existsSync(hostGlobal) + ? hostGlobal + : existsSync(legacyGlobal) + ? legacyGlobal + : hostGlobal; + project = existsSync(hostProject) + ? hostProject + : existsSync(legacyProject) + ? legacyProject + : hostProject; + } return { - global: env.PI_FORGEJO_CONFIG - ? resolve(env.PI_FORGEJO_CONFIG) - : resolve(homedir(), ".pi", "agent", "forgejo.json"), - project: resolve(cwd, ".pi", "forgejo.json"), + global: env.PI_FORGEJO_CONFIG ? resolve(env.PI_FORGEJO_CONFIG) : global, + project, }; } diff --git a/src/extension.ts b/src/extension.ts index c3bd0b0..f00ac3f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -4,6 +4,7 @@ import type { ExtensionContext, } from "@earendil-works/pi-coding-agent"; import type { AutocompleteProvider } from "@earendil-works/pi-tui"; +import { setConfigHostContext } from "./config.js"; import { runForgejoSetup, type SetupStage } from "./setup.js"; import { createForgejoAutocompleteProvider } from "./dashboard/autocomplete.js"; import { DashboardNotifier } from "./dashboard/notifier.js"; @@ -462,6 +463,23 @@ export default function forgejoExtension(pi: ExtensionAPI): void { }); pi.on("session_start", async (_event, ctx) => { + // Host-adaptive config location: resolve the running host (pi vs omp) + // before any config read so omp sessions follow ~/.omp/agent while + // legacy .pi configs keep working. Done here so config.ts itself stays + // free of pi-coding-agent imports (optional deps in the test graph). + try { + const hostModule = (await import( + "@earendil-works/pi-coding-agent" + )) as unknown as Record; + const getAgentDir = hostModule.getAgentDir as (() => string) | undefined; + setConfigHostContext({ + isOmp: "StatusLineComponent" in hostModule, + agentDir: + typeof getAgentDir === "function" ? getAgentDir() : undefined, + }); + } catch { + setConfigHostContext(undefined); + } forgejoTools.reset(); forgejoActive = false; cleanup(); diff --git a/test/config-refs.test.ts b/test/config-refs.test.ts index 37af959..a5bfe91 100644 --- a/test/config-refs.test.ts +++ b/test/config-refs.test.ts @@ -27,7 +27,7 @@ describe("Forgejo configuration", () => { remoteHosts: ["forgejo.work.example", "forgejo-work"], }); expect(config.dashboard).toEqual({ - enabled: true, + enabled: false, scope: "all", refreshSeconds: 90, previewLimit: 3, From ef7fef1690991d3c240065ae5ce5fa0df624dd8a Mon Sep 17 00:00:00 2001 From: alpertarhan Date: Mon, 7 Sep 2026 15:21:16 +0300 Subject: [PATCH 2/2] fix: resolve the forgejo host context from the environment The Node 22 build/import smoke test follows runtime imports; importing pi-coding-agent from the extension entry dragged its optional pi-server dependency into the bundle and broke the build. pi sets PI_CODING_AGENT=true for extensions and omp does not, so the host and agent directory are now derived purely from the environment (PI_CODING_AGENT / PI_CODING_AGENT_DIR / OMP_PROFILE), with no module import at all. --- src/extension.ts | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index f00ac3f..46cf4c8 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,3 +1,5 @@ +import { homedir } from "node:os"; +import { resolve } from "node:path"; import { fileURLToPath } from "node:url"; import type { ExtensionAPI, @@ -463,23 +465,23 @@ export default function forgejoExtension(pi: ExtensionAPI): void { }); pi.on("session_start", async (_event, ctx) => { - // Host-adaptive config location: resolve the running host (pi vs omp) - // before any config read so omp sessions follow ~/.omp/agent while - // legacy .pi configs keep working. Done here so config.ts itself stays - // free of pi-coding-agent imports (optional deps in the test graph). - try { - const hostModule = (await import( - "@earendil-works/pi-coding-agent" - )) as unknown as Record; - const getAgentDir = hostModule.getAgentDir as (() => string) | undefined; - setConfigHostContext({ - isOmp: "StatusLineComponent" in hostModule, - agentDir: - typeof getAgentDir === "function" ? getAgentDir() : undefined, - }); - } catch { - setConfigHostContext(undefined); - } + // Host-adaptive config location: pi sets PI_CODING_AGENT=true for + // extensions, omp does not. Resolved from the environment (never a + // pi-coding-agent import, which would pull optional dependencies into + // build graphs). PI_CODING_AGENT_DIR relocates the agent dir on both + // hosts; omp profiles live under ~/.omp/profiles//agent. + const isPi = process.env.PI_CODING_AGENT === "true"; + const profile = process.env.OMP_PROFILE?.trim(); + setConfigHostContext({ + isOmp: !isPi, + agentDir: + process.env.PI_CODING_AGENT_DIR?.trim() || + (isPi + ? resolve(homedir(), ".pi", "agent") + : profile + ? resolve(homedir(), ".omp", "profiles", profile, "agent") + : resolve(homedir(), ".omp", "agent")), + }); forgejoTools.reset(); forgejoActive = false; cleanup();