@oh-my-pi/pi-coding-agent 14.6.1 → 14.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [14.6.2] - 2026-05-03
6
+ ### Added
7
+
8
+ - Added `statusLine.sessionAccent` to disable session-name accent coloring for the editor border and status line gap ([#918](https://github.com/can1357/oh-my-pi/issues/918))
9
+
10
+ ### Fixed
11
+
12
+ - Disabled repeated OSC 11 background-color polling under WSL to avoid Windows terminal tab crashes while keeping initial and event-driven appearance detection ([#914](https://github.com/can1357/oh-my-pi/issues/914))
13
+
14
+ - Fixed SSH ControlMaster socket paths to use OpenSSH's connection hash (`%C`) so connections to the same host with different users, ports, or jump hosts do not share a master session.
15
+
16
+
5
17
  ## [14.6.1] - 2026-05-02
6
18
  ### Changed
7
19
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-coding-agent",
4
- "version": "14.6.1",
4
+ "version": "14.6.2",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/can1357/oh-my-pi",
7
7
  "author": "Can Boluk",
@@ -46,12 +46,12 @@
46
46
  "dependencies": {
47
47
  "@agentclientprotocol/sdk": "0.20.0",
48
48
  "@mozilla/readability": "^0.6.0",
49
- "@oh-my-pi/omp-stats": "14.6.1",
50
- "@oh-my-pi/pi-agent-core": "14.6.1",
51
- "@oh-my-pi/pi-ai": "14.6.1",
52
- "@oh-my-pi/pi-natives": "14.6.1",
53
- "@oh-my-pi/pi-tui": "14.6.1",
54
- "@oh-my-pi/pi-utils": "14.6.1",
49
+ "@oh-my-pi/omp-stats": "14.6.2",
50
+ "@oh-my-pi/pi-agent-core": "14.6.2",
51
+ "@oh-my-pi/pi-ai": "14.6.2",
52
+ "@oh-my-pi/pi-natives": "14.6.2",
53
+ "@oh-my-pi/pi-tui": "14.6.2",
54
+ "@oh-my-pi/pi-utils": "14.6.2",
55
55
  "@puppeteer/browsers": "^2.13.0",
56
56
  "@sinclair/typebox": "^0.34.49",
57
57
  "@xterm/headless": "^6.0.0",
@@ -304,6 +304,16 @@ export const SETTINGS_SCHEMA = {
304
304
  submenu: true,
305
305
  },
306
306
  },
307
+
308
+ "statusLine.sessionAccent": {
309
+ type: "boolean",
310
+ default: true,
311
+ ui: {
312
+ tab: "appearance",
313
+ label: "Session Accent",
314
+ description: "Use the session name color for the editor border and status line gap",
315
+ },
316
+ },
307
317
  "tools.artifactSpillThreshold": {
308
318
  type: "number",
309
319
  default: 50,
@@ -713,6 +713,10 @@ const SETTING_HOOKS: Partial<Record<SettingPath, SettingHook<any>>> = {
713
713
  let globalInstance: Settings | null = null;
714
714
  let globalInstancePromise: Promise<Settings> | null = null;
715
715
 
716
+ export function isSettingsInitialized(): boolean {
717
+ return globalInstance !== null;
718
+ }
719
+
716
720
  /**
717
721
  * Reset the global singleton for testing.
718
722
  * @internal
@@ -194,6 +194,7 @@ export interface StatusLinePreviewSettings {
194
194
  leftSegments?: StatusLineSegmentId[];
195
195
  rightSegments?: StatusLineSegmentId[];
196
196
  separator?: StatusLineSeparatorStyle;
197
+ sessionAccent?: boolean;
197
198
  }
198
199
 
199
200
  export interface SettingsCallbacks {
@@ -563,6 +564,7 @@ export class SettingsSelectorComponent extends Container {
563
564
  leftSegments: settings.get("statusLine.leftSegments"),
564
565
  rightSegments: settings.get("statusLine.rightSegments"),
565
566
  separator: settings.get("statusLine.separator"),
567
+ sessionAccent: settings.get("statusLine.sessionAccent"),
566
568
  };
567
569
  this.callbacks.onStatusLinePreview?.(statusLineSettings);
568
570
  this.#updateStatusPreview();
@@ -36,6 +36,7 @@ export interface StatusLineSettings {
36
36
  separator?: StatusLineSeparatorStyle;
37
37
  segmentOptions?: StatusLineSegmentOptions;
38
38
  showHookStatus?: boolean;
39
+ sessionAccent?: boolean;
39
40
  }
40
41
 
41
42
  // ═══════════════════════════════════════════════════════════════════════════
@@ -80,6 +81,7 @@ export class StatusLineComponent implements Component {
80
81
  separator: settings.get("statusLine.separator"),
81
82
  showHookStatus: settings.get("statusLine.showHookStatus"),
82
83
  segmentOptions: settings.getGroup("statusLine").segmentOptions,
84
+ sessionAccent: settings.get("statusLine.sessionAccent"),
83
85
  };
84
86
  }
85
87
 
@@ -514,7 +516,8 @@ export class StatusLineComponent implements Component {
514
516
  leftWidth = groupWidth(left, leftCapWidth, leftSepWidth);
515
517
  rightWidth = groupWidth(right, rightCapWidth, rightSepWidth);
516
518
  const gapWidth = Math.max(1, topFillWidth - leftWidth - rightWidth);
517
- const sessionName = this.session.sessionManager?.getSessionName();
519
+ const sessionName =
520
+ effectiveSettings.sessionAccent !== false ? this.session.sessionManager?.getSessionName() : undefined;
518
521
  const accentHex = sessionName ? getSessionAccentHex(sessionName) : undefined;
519
522
  const gapColor = getSessionAccentAnsi(accentHex) ?? theme.getFgAnsi("border");
520
523
  const gapFill = `${gapColor}${theme.boxRound.horizontal.repeat(gapWidth)}\x1b[39m`;
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * Handles /mcp subcommands for managing MCP servers.
5
5
  */
6
+ import * as path from "node:path";
6
7
  import { Spacer, Text } from "@oh-my-pi/pi-tui";
7
8
  import { getMCPConfigPath, getProjectDir } from "@oh-my-pi/pi-utils";
8
9
  import type { SourceMeta } from "../../capability/types";
@@ -656,6 +657,28 @@ export class MCPCommandController {
656
657
  if (projectConfig.mcpServers?.[name]) {
657
658
  return { filePath: projectPath, scope: "project", config: projectConfig.mcpServers[name] };
658
659
  }
660
+
661
+ // Check standalone fallback files (mcp.json, .mcp.json) in the project root —
662
+ // these match the discovery paths used by the mcp-json provider. Reads run in
663
+ // parallel (mirroring user/project above) but precedence is preserved by the
664
+ // for-loop's iteration order: mcp.json wins over .mcp.json on a same-name hit.
665
+ const standalonePaths = [path.join(cwd, "mcp.json"), path.join(cwd, ".mcp.json")];
666
+ const fallbackConfigs = await Promise.all(
667
+ standalonePaths.map(async fallbackPath => {
668
+ try {
669
+ return await readMCPConfigFile(fallbackPath);
670
+ } catch {
671
+ // Malformed JSON in a standalone file — skip and continue lookup.
672
+ return null;
673
+ }
674
+ }),
675
+ );
676
+ for (const [index, fallbackConfig] of fallbackConfigs.entries()) {
677
+ const config = fallbackConfig?.mcpServers?.[name];
678
+ if (config) {
679
+ return { filePath: standalonePaths[index]!, scope: "project", config };
680
+ }
681
+ }
659
682
  return null;
660
683
  }
661
684
 
@@ -118,6 +118,7 @@ export class SelectorController {
118
118
  rightSegments: settings.get("statusLine.rightSegments"),
119
119
  separator: settings.get("statusLine.separator"),
120
120
  showHookStatus: settings.get("statusLine.showHookStatus"),
121
+ sessionAccent: settings.get("statusLine.sessionAccent"),
121
122
  ...previewSettings,
122
123
  });
123
124
  this.ctx.updateEditorTopBorder();
@@ -140,6 +141,7 @@ export class SelectorController {
140
141
  rightSegments: settings.get("statusLine.rightSegments"),
141
142
  separator: settings.get("statusLine.separator"),
142
143
  showHookStatus: settings.get("statusLine.showHookStatus"),
144
+ sessionAccent: settings.get("statusLine.sessionAccent"),
143
145
  });
144
146
  this.ctx.updateEditorTopBorder();
145
147
  this.ctx.ui.requestRender();
@@ -332,8 +334,12 @@ export class SelectorController {
332
334
  break;
333
335
  }
334
336
  case "statusLinePreset":
337
+ case "statusLine.preset":
335
338
  case "statusLineSeparator":
339
+ case "statusLine.separator":
336
340
  case "statusLineShowHooks":
341
+ case "statusLine.showHookStatus":
342
+ case "statusLine.sessionAccent":
337
343
  case "statusLineSegments":
338
344
  case "statusLineModelThinking":
339
345
  case "statusLinePathAbbreviate":
@@ -351,6 +357,7 @@ export class SelectorController {
351
357
  rightSegments: settings.get("statusLine.rightSegments"),
352
358
  separator: settings.get("statusLine.separator"),
353
359
  showHookStatus: settings.get("statusLine.showHookStatus"),
360
+ sessionAccent: settings.get("statusLine.sessionAccent"),
354
361
  segmentOptions: settings.get("statusLine.segmentOptions"),
355
362
  };
356
363
  this.ctx.statusLine.updateSettings(statusLineSettings);
@@ -28,7 +28,7 @@ import {
28
28
  import { APP_NAME, getProjectDir, hsvToRgb, isEnoent, logger, postmortem, prompt } from "@oh-my-pi/pi-utils";
29
29
  import chalk from "chalk";
30
30
  import { KeybindingsManager } from "../config/keybindings";
31
- import { type Settings, settings } from "../config/settings";
31
+ import { isSettingsInitialized, type Settings, settings } from "../config/settings";
32
32
  import type {
33
33
  ExtensionUIContext,
34
34
  ExtensionUIDialogOptions,
@@ -644,7 +644,8 @@ export class InteractiveMode implements InteractiveModeContext {
644
644
  } else if (this.isPythonMode) {
645
645
  this.editor.borderColor = theme.getPythonModeBorderColor();
646
646
  } else {
647
- const sessionName = this.sessionManager.getSessionName();
647
+ const accentEnabled = !isSettingsInitialized() || settings.get("statusLine.sessionAccent") !== false;
648
+ const sessionName = accentEnabled ? this.sessionManager.getSessionName() : undefined;
648
649
  const hex = sessionName ? getSessionAccentHex(sessionName) : undefined;
649
650
  const ansi = getSessionAccentAnsi(hex);
650
651
  if (ansi) {
@@ -25,7 +25,7 @@ export interface SSHHostInfo {
25
25
  }
26
26
 
27
27
  const CONTROL_DIR = getSshControlDir();
28
- const CONTROL_PATH = path.join(CONTROL_DIR, "%h.sock");
28
+ const CONTROL_PATH = path.join(CONTROL_DIR, "%C.sock");
29
29
  const HOST_INFO_DIR = getRemoteHostDir();
30
30
  const HOST_INFO_VERSION = 2;
31
31
 
@@ -465,6 +465,7 @@ async function spillLargeResultToArtifact(
465
465
  ): Promise<AgentToolResult> {
466
466
  const sessionManager = context?.sessionManager;
467
467
  if (!sessionManager) return result;
468
+ if (toolName === "read") return result;
468
469
  const { threshold, tailBytes, tailLines } = getSpillConfig(context?.settings);
469
470
 
470
471
  // Skip if tool already saved an artifact