@oh-my-pi/pi-coding-agent 15.11.1 → 15.11.3

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.
Files changed (69) hide show
  1. package/CHANGELOG.md +36 -1
  2. package/dist/cli.js +643 -627
  3. package/dist/types/config/settings-schema.d.ts +36 -0
  4. package/dist/types/extensibility/custom-commands/types.d.ts +6 -3
  5. package/dist/types/extensibility/custom-tools/loader.d.ts +2 -1
  6. package/dist/types/extensibility/custom-tools/types.d.ts +8 -4
  7. package/dist/types/extensibility/extensions/types.d.ts +2 -2
  8. package/dist/types/extensibility/hooks/types.d.ts +8 -4
  9. package/dist/types/irc/bus.d.ts +15 -2
  10. package/dist/types/lsp/format-options.d.ts +32 -0
  11. package/dist/types/mnemopi/state.d.ts +29 -1
  12. package/dist/types/modes/components/plan-review-overlay.d.ts +2 -0
  13. package/dist/types/modes/rpc/rpc-client.d.ts +10 -1
  14. package/dist/types/modes/rpc/rpc-mode.d.ts +2 -0
  15. package/dist/types/modes/rpc/rpc-types.d.ts +30 -0
  16. package/dist/types/modes/theme/theme.d.ts +1 -1
  17. package/dist/types/session/agent-session.d.ts +17 -3
  18. package/dist/types/slash-commands/available-commands.d.ts +34 -0
  19. package/dist/types/tools/bash.d.ts +1 -1
  20. package/dist/types/tools/browser/attach.d.ts +4 -4
  21. package/dist/types/tools/browser/registry.d.ts +1 -0
  22. package/dist/types/tools/irc.d.ts +3 -2
  23. package/dist/types/tools/path-utils.d.ts +5 -5
  24. package/dist/types/utils/git.d.ts +1 -1
  25. package/package.json +11 -11
  26. package/src/config/settings-schema.ts +40 -0
  27. package/src/exec/bash-executor.ts +21 -6
  28. package/src/extensibility/custom-commands/loader.ts +3 -1
  29. package/src/extensibility/custom-commands/types.ts +6 -3
  30. package/src/extensibility/custom-tools/loader.ts +4 -7
  31. package/src/extensibility/custom-tools/types.ts +8 -4
  32. package/src/extensibility/extensions/loader.ts +2 -1
  33. package/src/extensibility/extensions/types.ts +2 -2
  34. package/src/extensibility/hooks/loader.ts +3 -1
  35. package/src/extensibility/hooks/types.ts +8 -4
  36. package/src/internal-urls/docs-index.generated.ts +4 -4
  37. package/src/irc/bus.ts +14 -3
  38. package/src/lsp/clients/lsp-linter-client.ts +2 -10
  39. package/src/lsp/defaults.json +6 -0
  40. package/src/lsp/format-options.ts +119 -0
  41. package/src/lsp/index.ts +2 -10
  42. package/src/lsp/render.ts +2 -28
  43. package/src/memories/index.ts +2 -0
  44. package/src/mnemopi/backend.ts +4 -8
  45. package/src/mnemopi/state.ts +42 -3
  46. package/src/modes/acp/acp-agent.ts +4 -67
  47. package/src/modes/components/plan-review-overlay.ts +32 -3
  48. package/src/modes/controllers/streaming-reveal.ts +16 -8
  49. package/src/modes/interactive-mode.ts +54 -2
  50. package/src/modes/rpc/rpc-client.ts +32 -0
  51. package/src/modes/rpc/rpc-mode.ts +82 -7
  52. package/src/modes/rpc/rpc-types.ts +23 -0
  53. package/src/modes/theme/theme.ts +7 -7
  54. package/src/modes/utils/ui-helpers.ts +13 -4
  55. package/src/prompts/memories/consolidation_system.md +4 -0
  56. package/src/prompts/system/irc-autoreply.md +6 -0
  57. package/src/prompts/system/irc-incoming.md +1 -1
  58. package/src/prompts/tools/bash.md +1 -0
  59. package/src/prompts/tools/irc.md +1 -1
  60. package/src/session/agent-session.ts +96 -7
  61. package/src/slash-commands/available-commands.ts +105 -0
  62. package/src/tools/bash.ts +5 -1
  63. package/src/tools/browser/attach.ts +26 -7
  64. package/src/tools/browser/registry.ts +11 -1
  65. package/src/tools/irc.ts +16 -4
  66. package/src/tools/job.ts +7 -3
  67. package/src/tools/path-utils.ts +56 -25
  68. package/src/tools/search.ts +11 -0
  69. package/src/utils/git.ts +7 -2
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": "15.11.1",
4
+ "version": "15.11.3",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -47,16 +47,16 @@
47
47
  "@agentclientprotocol/sdk": "0.22.1",
48
48
  "@babel/parser": "^7.29.7",
49
49
  "@mozilla/readability": "^0.6.0",
50
- "@oh-my-pi/hashline": "15.11.1",
51
- "@oh-my-pi/omp-stats": "15.11.1",
52
- "@oh-my-pi/pi-agent-core": "15.11.1",
53
- "@oh-my-pi/pi-ai": "15.11.1",
54
- "@oh-my-pi/pi-catalog": "15.11.1",
55
- "@oh-my-pi/pi-mnemopi": "15.11.1",
56
- "@oh-my-pi/pi-natives": "15.11.1",
57
- "@oh-my-pi/pi-tui": "15.11.1",
58
- "@oh-my-pi/pi-utils": "15.11.1",
59
- "@oh-my-pi/snapcompact": "15.11.1",
50
+ "@oh-my-pi/hashline": "15.11.3",
51
+ "@oh-my-pi/omp-stats": "15.11.3",
52
+ "@oh-my-pi/pi-agent-core": "15.11.3",
53
+ "@oh-my-pi/pi-ai": "15.11.3",
54
+ "@oh-my-pi/pi-catalog": "15.11.3",
55
+ "@oh-my-pi/pi-mnemopi": "15.11.3",
56
+ "@oh-my-pi/pi-natives": "15.11.3",
57
+ "@oh-my-pi/pi-tui": "15.11.3",
58
+ "@oh-my-pi/pi-utils": "15.11.3",
59
+ "@oh-my-pi/snapcompact": "15.11.3",
60
60
  "@opentelemetry/api": "^1.9.1",
61
61
  "@opentelemetry/context-async-hooks": "^2.7.1",
62
62
  "@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
@@ -1093,6 +1093,46 @@ export const SETTINGS_SCHEMA = {
1093
1093
  ui: { tab: "interaction", label: "Collapse Changelog", description: "Show condensed changelog after updates" },
1094
1094
  },
1095
1095
 
1096
+ "magicKeywords.enabled": {
1097
+ type: "boolean",
1098
+ default: true,
1099
+ ui: {
1100
+ tab: "interaction",
1101
+ label: "Magic Keywords",
1102
+ description: "Enable hidden notices for standalone ultrathink, orchestrate, and workflowz keywords",
1103
+ },
1104
+ },
1105
+
1106
+ "magicKeywords.ultrathink": {
1107
+ type: "boolean",
1108
+ default: true,
1109
+ ui: {
1110
+ tab: "interaction",
1111
+ label: "Ultrathink Keyword",
1112
+ description: "Let standalone ultrathink request maximum automatic thinking and append its hidden notice",
1113
+ },
1114
+ },
1115
+
1116
+ "magicKeywords.orchestrate": {
1117
+ type: "boolean",
1118
+ default: true,
1119
+ ui: {
1120
+ tab: "interaction",
1121
+ label: "Orchestrate Keyword",
1122
+ description: "Let standalone orchestrate append its hidden multi-agent orchestration notice",
1123
+ },
1124
+ },
1125
+
1126
+ "magicKeywords.workflow": {
1127
+ type: "boolean",
1128
+ default: true,
1129
+ ui: {
1130
+ tab: "interaction",
1131
+ label: "Workflow Keyword",
1132
+ description: "Let standalone workflowz append its hidden eval workflow notice",
1133
+ },
1134
+ },
1135
+
1096
1136
  // Notifications
1097
1137
  "completion.notify": {
1098
1138
  type: "enum",
@@ -56,6 +56,8 @@ export interface BashResult {
56
56
  const shellSessions = new Map<string, Shell>();
57
57
  const brokenShellSessions = new Set<string>();
58
58
  const shellSessionQuarantines = new Map<string, Promise<unknown>>();
59
+ /** Session keys with a command currently in flight on the persistent Shell. */
60
+ const shellSessionsInUse = new Set<string>();
59
61
 
60
62
  function quarantineShellSession(
61
63
  sessionKey: string,
@@ -223,8 +225,14 @@ export async function executeBash(command: string, options?: BashExecutorOptions
223
225
  shellSessions.delete(sessionKey);
224
226
  }
225
227
 
226
- let shellSession = persistentSessionBroken ? undefined : shellSessions.get(sessionKey);
227
- if (!shellSession && !persistentSessionBroken) {
228
+ // A persistent Shell runs one command at a time (the native session is a
229
+ // mutex-guarded queue and `abort()` kills every in-flight run on it). When
230
+ // parallel bash calls overlap on the same key, the first one owns the
231
+ // persistent session; the rest degrade to isolated one-shot shells — the
232
+ // same path quarantined sessions take.
233
+ const sessionBusy = shellSessionsInUse.has(sessionKey);
234
+ let shellSession = persistentSessionBroken || sessionBusy ? undefined : shellSessions.get(sessionKey);
235
+ if (!shellSession && !persistentSessionBroken && !sessionBusy) {
228
236
  shellSession = new Shell({
229
237
  sessionEnv: shellEnv,
230
238
  snapshotPath: snapshotPath ?? undefined,
@@ -232,6 +240,10 @@ export async function executeBash(command: string, options?: BashExecutorOptions
232
240
  });
233
241
  shellSessions.set(sessionKey, shellSession);
234
242
  }
243
+ const ownsPersistentSession = shellSession !== undefined;
244
+ if (ownsPersistentSession) {
245
+ shellSessionsInUse.add(sessionKey);
246
+ }
235
247
  const userSignal = options?.signal;
236
248
  const runAbortController = new AbortController();
237
249
  let abortCleanupPromise: Promise<void> | undefined;
@@ -393,10 +405,13 @@ export async function executeBash(command: string, options?: BashExecutorOptions
393
405
  if (userSignal) {
394
406
  userSignal.removeEventListener("abort", abortHandler);
395
407
  }
396
- if (resetSession || options?.sessionKey?.includes(":async:")) {
397
- // `:async:` keys are per-job (jobId is unique), so the Shell would
398
- // otherwise stay in the process-global map forever after completion.
399
- shellSessions.delete(sessionKey);
408
+ if (ownsPersistentSession) {
409
+ shellSessionsInUse.delete(sessionKey);
410
+ if (resetSession || options?.sessionKey?.includes(":async:")) {
411
+ // `:async:` keys are per-job (jobId is unique), so the Shell would
412
+ // otherwise stay in the process-global map forever after completion.
413
+ shellSessions.delete(sessionKey);
414
+ }
400
415
  }
401
416
  }
402
417
  }
@@ -10,6 +10,8 @@ import { getAgentDir, getProjectDir, isEnoent, logger } from "@oh-my-pi/pi-utils
10
10
  import * as zod from "zod/v4";
11
11
  import { getConfigDirs } from "../../config";
12
12
  import { execCommand } from "../../exec/exec";
13
+ // Runtime self-reference: dereference this namespace only inside loader functions to keep the index.ts cycle safe.
14
+ import * as PiCodingAgent from "../../index";
13
15
  import * as typebox from "../typebox";
14
16
  import { GreenCommand } from "./bundled/ci-green";
15
17
  import { ReviewCommand } from "./bundled/review";
@@ -185,7 +187,7 @@ export async function loadCustomCommands(options: LoadCustomCommandsOptions = {}
185
187
  execCommand(command, args, execOptions?.cwd ?? cwd, execOptions),
186
188
  typebox,
187
189
  zod,
188
- pi: await import("@oh-my-pi/pi-coding-agent"),
190
+ pi: PiCodingAgent,
189
191
  };
190
192
 
191
193
  // 1. Load bundled commands first (lowest priority - can be overridden)
@@ -5,7 +5,10 @@
5
5
  * Unlike markdown commands which expand to prompts, custom commands can execute
6
6
  * arbitrary logic with full access to the hook context.
7
7
  */
8
+ import type * as Zod from "zod/v4";
8
9
  import type { ExecOptions, ExecResult, HookCommandContext } from "../../extensibility/hooks/types";
10
+ import type * as PiCodingAgent from "../../index";
11
+ import type * as TypeBox from "../typebox";
9
12
 
10
13
  // Re-export for custom commands to use
11
14
  export type { ExecOptions, ExecResult, HookCommandContext };
@@ -20,11 +23,11 @@ export interface CustomCommandAPI {
20
23
  /** Execute a shell command */
21
24
  exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
22
25
  /** Injected zod-backed typebox shim (legacy/compat). */
23
- typebox: typeof import("../typebox");
26
+ typebox: typeof TypeBox;
24
27
  /** Injected zod module for Zod-authored custom commands. */
25
- zod: typeof import("zod/v4");
28
+ zod: typeof Zod;
26
29
  /** Injected pi-coding-agent exports */
27
- pi: typeof import("../..");
30
+ pi: typeof PiCodingAgent;
28
31
  }
29
32
 
30
33
  /**
@@ -14,6 +14,8 @@ import type { ExecOptions } from "../../exec/exec";
14
14
  import { execCommand } from "../../exec/exec";
15
15
  import type { HookUIContext } from "../../extensibility/hooks/types";
16
16
  import { getAllPluginToolPaths } from "../../extensibility/plugins/loader";
17
+ // Runtime self-reference: dereference this namespace only inside loader functions to keep the index.ts cycle safe.
18
+ import * as PiCodingAgent from "../../index";
17
19
  import * as typebox from "../typebox";
18
20
  import { createNoOpUIContext, resolvePath } from "../utils";
19
21
  import type { CustomToolAPI, CustomToolFactory, LoadedCustomTool, ToolLoadError } from "./types";
@@ -88,7 +90,7 @@ export class CustomToolLoader {
88
90
  #seenNames: Set<string>;
89
91
 
90
92
  constructor(
91
- pi: typeof import("@oh-my-pi/pi-coding-agent"),
93
+ pi: typeof PiCodingAgent,
92
94
  cwd: string,
93
95
  builtInToolNames: string[],
94
96
  pushPendingAction?: (action: {
@@ -174,12 +176,7 @@ export async function loadCustomTools(
174
176
  reject?(reason: string): Promise<AgentToolResult<unknown> | undefined>;
175
177
  }) => void,
176
178
  ) {
177
- const loader = new CustomToolLoader(
178
- await import("@oh-my-pi/pi-coding-agent"),
179
- cwd,
180
- builtInToolNames,
181
- pushPendingAction,
182
- );
179
+ const loader = new CustomToolLoader(PiCodingAgent, cwd, builtInToolNames, pushPendingAction);
183
180
  await loader.load(pathsWithSources);
184
181
  return {
185
182
  tools: loader.tools,
@@ -14,14 +14,18 @@ import type {
14
14
  import type { CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
15
15
  import type { FetchImpl, Model, Static, TSchema } from "@oh-my-pi/pi-ai";
16
16
  import type { Component } from "@oh-my-pi/pi-tui";
17
+ import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
18
+ import type * as Zod from "zod/v4";
17
19
  import type { Rule } from "../../capability/rule";
18
20
  import type { ModelRegistry } from "../../config/model-registry";
19
21
  import type { Settings } from "../../config/settings";
20
22
  import type { ExecOptions, ExecResult } from "../../exec/exec";
21
23
  import type { HookUIContext } from "../../extensibility/hooks/types";
24
+ import type * as PiCodingAgent from "../../index";
22
25
  import type { Theme } from "../../modes/theme/theme";
23
26
  import type { ReadonlySessionManager } from "../../session/session-manager";
24
27
  import type { TodoItem } from "../../tools/todo";
28
+ import type * as TypeBox from "../typebox";
25
29
 
26
30
  /** Alias for clarity */
27
31
  export type CustomToolUIContext = HookUIContext;
@@ -56,13 +60,13 @@ export interface CustomToolAPI {
56
60
  /** Whether UI is available (false in print/RPC mode) */
57
61
  hasUI: boolean;
58
62
  /** File logger for error/warning/debug messages */
59
- logger: typeof import("@oh-my-pi/pi-utils").logger;
63
+ logger: typeof PiLogger;
60
64
  /** Injected zod-backed typebox shim (legacy/compat — Zod-authored tools are preferred). */
61
- typebox: typeof import("../typebox");
65
+ typebox: typeof TypeBox;
62
66
  /** Injected zod module for Zod-authored custom tools. */
63
- zod: typeof import("zod/v4");
67
+ zod: typeof Zod;
64
68
  /** Injected pi-coding-agent exports */
65
- pi: typeof import("../..");
69
+ pi: typeof PiCodingAgent;
66
70
  /** Push a preview action that can later be resolved with the hidden resolve tool */
67
71
  pushPendingAction(action: CustomToolPendingAction): void;
68
72
  }
@@ -6,7 +6,6 @@ import * as fs from "node:fs/promises";
6
6
  import * as path from "node:path";
7
7
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
8
8
  import type { ImageContent, Model, TextContent, TSchema } from "@oh-my-pi/pi-ai";
9
- import * as PiCodingAgent from "@oh-my-pi/pi-coding-agent";
10
9
  import type { KeyId } from "@oh-my-pi/pi-tui";
11
10
  import { hasFsCode, isEacces, isEnoent, logger } from "@oh-my-pi/pi-utils";
12
11
  import * as Zod from "zod/v4";
@@ -15,6 +14,8 @@ import { loadCapability } from "../../discovery";
15
14
  import { getExtensionNameFromPath } from "../../discovery/helpers";
16
15
  import type { ExecOptions } from "../../exec/exec";
17
16
  import { execCommand } from "../../exec/exec";
17
+ // Runtime self-reference: dereference this namespace only inside loader functions to keep the index.ts cycle safe.
18
+ import * as PiCodingAgent from "../../index";
18
19
  import type { CustomMessage } from "../../session/messages";
19
20
  import { EventBus } from "../../utils/event-bus";
20
21
  import { installLegacyPiSpecifierShim, loadLegacyPiModule } from "../plugins/legacy-pi-compat";
@@ -30,7 +30,6 @@ import type {
30
30
  TSchema,
31
31
  } from "@oh-my-pi/pi-ai";
32
32
  import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/oauth/types";
33
- import type * as piCodingAgent from "@oh-my-pi/pi-coding-agent";
34
33
  import type { AutocompleteItem, Component, EditorTheme, KeyId, TUI } from "@oh-my-pi/pi-tui";
35
34
  import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
36
35
  import type * as Zod from "zod/v4";
@@ -40,6 +39,7 @@ import type { EditToolDetails } from "../../edit";
40
39
  import type { PythonResult } from "../../eval/py/executor";
41
40
  import type { BashResult } from "../../exec/bash-executor";
42
41
  import type { ExecOptions, ExecResult } from "../../exec/exec";
42
+ import type * as PiCodingAgent from "../../index";
43
43
  import type { MemoryRuntimeContext } from "../../memory-backend";
44
44
  import type { CustomEditor } from "../../modes/components/custom-editor";
45
45
  import type { Theme } from "../../modes/theme/theme";
@@ -893,7 +893,7 @@ export interface ExtensionAPI {
893
893
  zod: typeof Zod;
894
894
 
895
895
  /** Injected pi-coding-agent exports for accessing SDK utilities */
896
- pi: typeof piCodingAgent;
896
+ pi: typeof PiCodingAgent;
897
897
 
898
898
  // =========================================================================
899
899
  // Event Subscription
@@ -7,6 +7,8 @@ import * as zod from "zod/v4";
7
7
  import { hookCapability } from "../../capability/hook";
8
8
  import type { Hook } from "../../discovery";
9
9
  import { loadCapability } from "../../discovery";
10
+ // Runtime self-reference: dereference this namespace only inside loader functions to keep the index.ts cycle safe.
11
+ import * as PiCodingAgent from "../../index";
10
12
  import type { HookMessage } from "../../session/messages";
11
13
  import type { SessionManager } from "../../session/session-manager";
12
14
  import * as typebox from "../typebox";
@@ -138,7 +140,7 @@ async function createHookAPI(
138
140
  logger,
139
141
  typebox,
140
142
  zod,
141
- pi: await import("@oh-my-pi/pi-coding-agent"),
143
+ pi: PiCodingAgent,
142
144
  } as HookAPI;
143
145
 
144
146
  return {
@@ -1,8 +1,11 @@
1
1
  import type { ImageContent, Message, Model, TextContent } from "@oh-my-pi/pi-ai";
2
2
  import type { Component, TUI } from "@oh-my-pi/pi-tui";
3
+ import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
4
+ import type * as Zod from "zod/v4";
3
5
  import type { ModelRegistry } from "../../config/model-registry";
4
6
  import type { EditToolDetails } from "../../edit";
5
7
  import type { ExecOptions, ExecResult } from "../../exec/exec";
8
+ import type * as PiCodingAgent from "../../index";
6
9
  import type { Theme } from "../../modes/theme/theme";
7
10
  import type { HookMessage } from "../../session/messages";
8
11
  import type { ReadonlySessionManager, SessionManager } from "../../session/session-manager";
@@ -39,6 +42,7 @@ import type {
39
42
  TurnEndEvent,
40
43
  TurnStartEvent,
41
44
  } from "../shared-events";
45
+ import type * as TypeBox from "../typebox";
42
46
 
43
47
  // Re-export for backward compatibility
44
48
  export type { ExecOptions, ExecResult } from "../../exec/exec";
@@ -577,13 +581,13 @@ export interface HookAPI {
577
581
  exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
578
582
 
579
583
  /** File logger for error/warning/debug messages */
580
- logger: typeof import("@oh-my-pi/pi-utils").logger;
584
+ logger: typeof PiLogger;
581
585
  /** Injected zod-backed typebox shim (legacy/compat — prefer `zod`). */
582
- typebox: typeof import("../typebox");
586
+ typebox: typeof TypeBox;
583
587
  /** Injected zod module for Zod-authored hooks. */
584
- zod: typeof import("zod/v4");
588
+ zod: typeof Zod;
585
589
  /** Injected pi-coding-agent exports */
586
- pi: typeof import("../..");
590
+ pi: typeof PiCodingAgent;
587
591
  }
588
592
 
589
593
  /**