jeopi-cli 16.4.2 → 16.4.4

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 (148) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/dist/cli.js +3033 -2991
  3. package/dist/types/advisor/advise-tool.d.ts +5 -1
  4. package/dist/types/advisor/config.d.ts +4 -3
  5. package/dist/types/advisor/runtime.d.ts +15 -0
  6. package/dist/types/cli/args.d.ts +2 -0
  7. package/dist/types/cli/update-cli.d.ts +4 -1
  8. package/dist/types/cli/usage-error.d.ts +4 -0
  9. package/dist/types/commit/agentic/agent.d.ts +1 -0
  10. package/dist/types/config/model-registry.d.ts +3 -3
  11. package/dist/types/config/model-resolver.d.ts +7 -1
  12. package/dist/types/config/models-config.d.ts +1 -1
  13. package/dist/types/config/settings-schema.d.ts +3 -13
  14. package/dist/types/eval/py/tool-bridge.d.ts +1 -0
  15. package/dist/types/extensibility/custom-tools/types.d.ts +3 -0
  16. package/dist/types/extensibility/extensions/runner.d.ts +3 -1
  17. package/dist/types/extensibility/extensions/types.d.ts +3 -0
  18. package/dist/types/internal-urls/memory-protocol.d.ts +6 -6
  19. package/dist/types/internal-urls/types.d.ts +7 -0
  20. package/dist/types/irc/bus.d.ts +4 -0
  21. package/dist/types/lsp/deferred-diagnostics.d.ts +11 -0
  22. package/dist/types/modes/components/move-overlay.d.ts +1 -1
  23. package/dist/types/modes/components/plan-review-overlay.d.ts +2 -0
  24. package/dist/types/modes/components/welcome.d.ts +4 -0
  25. package/dist/types/modes/magic-keyword-boundary.d.ts +9 -0
  26. package/dist/types/modes/orchestrate.d.ts +1 -1
  27. package/dist/types/modes/rpc/host-tools.d.ts +2 -0
  28. package/dist/types/modes/rpc/rpc-mode.d.ts +27 -7
  29. package/dist/types/modes/ultrathink.d.ts +1 -1
  30. package/dist/types/modes/utils/transcript-render-helpers.d.ts +9 -0
  31. package/dist/types/modes/workflow.d.ts +1 -1
  32. package/dist/types/session/agent-session.d.ts +6 -0
  33. package/dist/types/session/auth-broker-config.d.ts +2 -2
  34. package/dist/types/tools/bash-skill-urls.d.ts +3 -2
  35. package/dist/types/tools/browser/cmux/cmux-tab.d.ts +3 -1
  36. package/dist/types/tools/browser/cmux/rpc.d.ts +20 -0
  37. package/dist/types/tools/browser/launch.d.ts +1 -0
  38. package/dist/types/tools/browser/run-cancellation.d.ts +17 -2
  39. package/dist/types/tools/browser/run-output.d.ts +25 -0
  40. package/dist/types/tools/browser/tab-worker.d.ts +22 -0
  41. package/dist/types/utils/changelog.d.ts +35 -1
  42. package/package.json +12 -12
  43. package/src/advisor/__tests__/advisor.test.ts +13 -0
  44. package/src/advisor/__tests__/config.test.ts +36 -0
  45. package/src/advisor/advise-tool.ts +6 -1
  46. package/src/advisor/config.ts +11 -8
  47. package/src/advisor/runtime.ts +127 -0
  48. package/src/autolearn/controller.ts +15 -3
  49. package/src/cli/args.ts +12 -0
  50. package/src/cli/flag-tables.ts +21 -7
  51. package/src/cli/update-cli.ts +63 -13
  52. package/src/cli/usage-error.ts +7 -0
  53. package/src/commands/acp.ts +11 -2
  54. package/src/commands/launch.ts +12 -3
  55. package/src/commit/agentic/agent.ts +4 -0
  56. package/src/commit/agentic/index.ts +46 -21
  57. package/src/config/config-file.ts +30 -12
  58. package/src/config/model-registry.ts +7 -7
  59. package/src/config/model-resolver.ts +24 -6
  60. package/src/config/models-config.ts +1 -1
  61. package/src/config/settings-schema.ts +3 -15
  62. package/src/edit/index.ts +10 -76
  63. package/src/edit/renderer.ts +13 -10
  64. package/src/eval/__tests__/agent-bridge.test.ts +19 -14
  65. package/src/eval/__tests__/bridge-timeout.test.ts +60 -0
  66. package/src/eval/executor-base.ts +84 -7
  67. package/src/eval/js/shared/rewrite-imports.ts +31 -13
  68. package/src/eval/py/tool-bridge.ts +13 -14
  69. package/src/exec/non-interactive-env.ts +0 -1
  70. package/src/export/ttsr.ts +0 -3
  71. package/src/extensibility/custom-tools/loader.ts +70 -37
  72. package/src/extensibility/custom-tools/types.ts +3 -0
  73. package/src/extensibility/extensions/runner.ts +3 -0
  74. package/src/extensibility/extensions/types.ts +3 -0
  75. package/src/extensibility/plugins/legacy-pi-bundled-keys.ts +9 -1
  76. package/src/extensibility/plugins/legacy-pi-bundled-registry.ts +30 -3
  77. package/src/extensibility/plugins/manager.ts +21 -0
  78. package/src/internal-urls/docs-index.generated.txt +1 -1
  79. package/src/internal-urls/memory-protocol.ts +13 -8
  80. package/src/internal-urls/skill-protocol.ts +1 -1
  81. package/src/internal-urls/types.ts +7 -0
  82. package/src/irc/bus.ts +48 -18
  83. package/src/lsp/client.ts +7 -1
  84. package/src/lsp/deferred-diagnostics.ts +66 -0
  85. package/src/main.ts +13 -13
  86. package/src/mcp/tool-bridge.ts +57 -6
  87. package/src/mcp/transports/stdio.test.ts +45 -1
  88. package/src/mcp/transports/stdio.ts +6 -3
  89. package/src/modes/acp/acp-agent.ts +73 -2
  90. package/src/modes/acp/acp-event-mapper.ts +5 -0
  91. package/src/modes/acp/acp-mode.ts +11 -0
  92. package/src/modes/components/__tests__/move-overlay.test.ts +16 -1
  93. package/src/modes/components/advisor-config.ts +15 -7
  94. package/src/modes/components/chat-transcript-builder.ts +31 -11
  95. package/src/modes/components/move-overlay.ts +2 -3
  96. package/src/modes/components/plan-review-overlay.ts +7 -0
  97. package/src/modes/components/tips.txt +1 -1
  98. package/src/modes/components/welcome.ts +13 -14
  99. package/src/modes/controllers/command-controller.ts +8 -10
  100. package/src/modes/controllers/event-controller.ts +58 -42
  101. package/src/modes/controllers/input-controller.ts +9 -6
  102. package/src/modes/controllers/selector-controller.ts +3 -2
  103. package/src/modes/controllers/tan-command-controller.ts +40 -1
  104. package/src/modes/interactive-mode.ts +13 -0
  105. package/src/modes/magic-keyword-boundary.ts +23 -0
  106. package/src/modes/orchestrate.ts +6 -5
  107. package/src/modes/print-mode.ts +9 -0
  108. package/src/modes/rpc/host-tools.ts +13 -0
  109. package/src/modes/rpc/rpc-mode.ts +130 -56
  110. package/src/modes/ultrathink.ts +6 -5
  111. package/src/modes/utils/transcript-render-helpers.ts +44 -0
  112. package/src/modes/utils/ui-helpers.ts +16 -1
  113. package/src/modes/workflow.ts +5 -4
  114. package/src/prompts/system/eager-task.md +2 -2
  115. package/src/prompts/system/tan-context-switch.md +17 -0
  116. package/src/prompts/tools/browser.md +5 -5
  117. package/src/sdk.ts +3 -0
  118. package/src/session/agent-session.ts +267 -36
  119. package/src/session/auth-broker-config.ts +4 -4
  120. package/src/session/snapcompact-inline.ts +3 -19
  121. package/src/session/streaming-output.ts +40 -12
  122. package/src/slash-commands/builtin-registry.ts +8 -8
  123. package/src/task/executor.ts +8 -0
  124. package/src/task/render.ts +51 -44
  125. package/src/tools/bash-skill-urls.ts +7 -4
  126. package/src/tools/bash.ts +30 -33
  127. package/src/tools/browser/cmux/cmux-tab.ts +49 -50
  128. package/src/tools/browser/cmux/rpc.ts +50 -0
  129. package/src/tools/browser/launch.ts +8 -4
  130. package/src/tools/browser/run-cancellation.ts +44 -5
  131. package/src/tools/browser/run-output.ts +76 -0
  132. package/src/tools/browser/tab-worker.ts +280 -133
  133. package/src/tools/eval-render.ts +16 -14
  134. package/src/tools/glob.ts +20 -6
  135. package/src/tools/grep.ts +1 -0
  136. package/src/tools/image-gen.ts +3 -4
  137. package/src/tools/irc.ts +27 -13
  138. package/src/tools/path-utils.ts +6 -1
  139. package/src/tools/read.ts +14 -7
  140. package/src/tools/write.ts +22 -5
  141. package/src/tools/yield.ts +29 -1
  142. package/src/utils/changelog.ts +106 -9
  143. package/src/utils/git.ts +0 -1
  144. package/src/utils/title-generator.ts +72 -7
  145. package/src/web/search/index.ts +14 -6
  146. package/src/web/search/providers/perplexity.ts +18 -2
  147. package/dist/types/tools/bash-command-fixup.d.ts +0 -11
  148. package/src/tools/bash-command-fixup.ts +0 -37
@@ -24,23 +24,53 @@ import type { CustomToolAPI, CustomToolFactory, LoadedCustomTool, ToolLoadError
24
24
  /**
25
25
  * Load a single tool module using native Bun import.
26
26
  */
27
+ interface LoadToolResult {
28
+ tools: LoadedCustomTool[];
29
+ errors: ToolLoadError[];
30
+ }
31
+
32
+ function isLoadableCustomTool(value: unknown): value is LoadedCustomTool["tool"] {
33
+ return (
34
+ typeof value === "object" &&
35
+ value !== null &&
36
+ "name" in value &&
37
+ typeof value.name === "string" &&
38
+ value.name.length > 0 &&
39
+ "description" in value &&
40
+ typeof value.description === "string" &&
41
+ "parameters" in value &&
42
+ "execute" in value &&
43
+ typeof value.execute === "function"
44
+ );
45
+ }
46
+
47
+ function invalidToolError(path: string, index: number, source: ToolLoadError["source"]): ToolLoadError {
48
+ return {
49
+ path,
50
+ error: `Tool factory returned invalid tool at index ${index}: expected object with string name, string description, parameters, and execute function`,
51
+ source,
52
+ };
53
+ }
54
+
27
55
  async function loadTool(
28
56
  toolPath: string,
29
57
  cwd: string,
30
58
  sharedApi: CustomToolAPI,
31
59
  source?: { provider: string; providerName: string; level: "user" | "project" },
32
- ): Promise<{ tools: LoadedCustomTool[] | null; error: ToolLoadError | null }> {
60
+ ): Promise<LoadToolResult> {
33
61
  const resolvedPath = resolvePath(toolPath, cwd);
34
62
 
35
63
  // Skip declarative tool files (.md, .json) - these are metadata only, not executable modules
36
64
  if (resolvedPath.endsWith(".md") || resolvedPath.endsWith(".json")) {
37
65
  return {
38
- tools: null,
39
- error: {
40
- path: toolPath,
41
- error: "Declarative tool files (.md, .json) cannot be loaded as executable modules",
42
- source,
43
- },
66
+ tools: [],
67
+ errors: [
68
+ {
69
+ path: toolPath,
70
+ error: "Declarative tool files (.md, .json) cannot be loaded as executable modules",
71
+ source,
72
+ },
73
+ ],
44
74
  };
45
75
  }
46
76
 
@@ -49,23 +79,32 @@ async function loadTool(
49
79
  const factory = (module.default ?? module) as CustomToolFactory;
50
80
 
51
81
  if (typeof factory !== "function") {
52
- return { tools: null, error: { path: toolPath, error: "Tool must export a default function", source } };
82
+ return { tools: [], errors: [{ path: toolPath, error: "Tool must export a default function", source }] };
53
83
  }
54
84
 
55
- const toolResult = await factory(sharedApi);
85
+ const toolResult: unknown = await factory(sharedApi);
56
86
  const toolsArray = Array.isArray(toolResult) ? toolResult : [toolResult];
57
87
 
58
- const loadedTools: LoadedCustomTool[] = toolsArray.map(tool => ({
59
- path: toolPath,
60
- resolvedPath,
61
- tool,
62
- source,
63
- }));
88
+ const loadedTools: LoadedCustomTool[] = [];
89
+ const errors: ToolLoadError[] = [];
90
+ for (const [index, tool] of toolsArray.entries()) {
91
+ if (!isLoadableCustomTool(tool)) {
92
+ errors.push(invalidToolError(toolPath, index, source));
93
+ continue;
94
+ }
95
+
96
+ loadedTools.push({
97
+ path: toolPath,
98
+ resolvedPath,
99
+ tool,
100
+ source,
101
+ });
102
+ }
64
103
 
65
- return { tools: loadedTools, error: null };
104
+ return { tools: loadedTools, errors };
66
105
  } catch (err) {
67
106
  const message = err instanceof Error ? err.message : String(err);
68
- return { tools: null, error: { path: toolPath, error: `Failed to load tool: ${message}`, source } };
107
+ return { tools: [], errors: [{ path: toolPath, error: `Failed to load tool: ${message}`, source }] };
69
108
  }
70
109
  }
71
110
 
@@ -129,28 +168,22 @@ export class CustomToolLoader {
129
168
 
130
169
  async load(pathsWithSources: ToolPathWithSource[]): Promise<void> {
131
170
  for (const { path: toolPath, source } of pathsWithSources) {
132
- const { tools: loadedTools, error } = await loadTool(toolPath, this.#sharedApi.cwd, this.#sharedApi, source);
171
+ const { tools: loadedTools, errors } = await loadTool(toolPath, this.#sharedApi.cwd, this.#sharedApi, source);
172
+ this.errors.push(...errors);
133
173
 
134
- if (error) {
135
- this.errors.push(error);
136
- continue;
137
- }
138
-
139
- if (loadedTools) {
140
- for (const loadedTool of loadedTools) {
141
- // Check for name conflicts
142
- if (this.#seenNames.has(loadedTool.tool.name)) {
143
- this.errors.push({
144
- path: toolPath,
145
- error: `Tool name "${loadedTool.tool.name}" conflicts with existing tool`,
146
- source,
147
- });
148
- continue;
149
- }
150
-
151
- this.#seenNames.add(loadedTool.tool.name);
152
- this.tools.push(loadedTool);
174
+ for (const loadedTool of loadedTools) {
175
+ // Check for name conflicts
176
+ if (this.#seenNames.has(loadedTool.tool.name)) {
177
+ this.errors.push({
178
+ path: toolPath,
179
+ error: `Tool name "${loadedTool.tool.name}" conflicts with existing tool`,
180
+ source,
181
+ });
182
+ continue;
153
183
  }
184
+
185
+ this.#seenNames.add(loadedTool.tool.name);
186
+ this.tools.push(loadedTool);
154
187
  }
155
188
  }
156
189
  }
@@ -24,6 +24,7 @@ import type { Settings } from "../../config/settings";
24
24
  import type { ExecOptions, ExecResult } from "../../exec/exec";
25
25
  import type { HookUIContext } from "../../extensibility/hooks/types";
26
26
  import type * as PiCodingAgent from "../../index";
27
+ import type { LocalProtocolOptions } from "../../internal-urls/local-protocol";
27
28
  import type { Theme } from "../../modes/theme/theme";
28
29
  import type { ReadonlySessionManager } from "../../session/session-manager";
29
30
  import type { TodoItem } from "../../tools/todo";
@@ -96,6 +97,8 @@ export interface CustomToolContext {
96
97
  settings?: Settings;
97
98
  /** Fetch implementation for outbound HTTP; defaults to global fetch when omitted. */
98
99
  fetch?: FetchImpl;
100
+ /** Calling session's `local://` root mapping for tools that bridge out of the OMP process. */
101
+ localProtocolOptions?: LocalProtocolOptions;
99
102
  /** Whether to auto-approve all destructive tool operations (--auto-approve CLI flag) */
100
103
  autoApprove?: boolean;
101
104
  }
@@ -7,6 +7,7 @@ import type { KeyId } from "jeopi-tui";
7
7
  import { logger } from "jeopi-utils";
8
8
  import type { ModelRegistry } from "../../config/model-registry";
9
9
  import type { Settings } from "../../config/settings";
10
+ import type { LocalProtocolOptions } from "../../internal-urls/local-protocol";
10
11
  import type { MemoryRuntimeContext } from "../../memory-backend";
11
12
  import { type Theme, theme } from "../../modes/theme/theme";
12
13
  import type { SessionManager } from "../../session/session-manager";
@@ -255,6 +256,7 @@ export class ExtensionRunner {
255
256
  private readonly modelRegistry: ModelRegistry,
256
257
  getMemory?: () => MemoryRuntimeContext | undefined,
257
258
  private readonly settings?: Settings,
259
+ private readonly localProtocolOptions?: LocalProtocolOptions,
258
260
  ) {
259
261
  this.#uiContext = noOpUIContext;
260
262
  this.#getMemoryFn = getMemory;
@@ -537,6 +539,7 @@ export class ExtensionRunner {
537
539
  hasPendingMessages: () => this.#hasPendingMessagesFn(),
538
540
  shutdown: () => this.#shutdownHandler(),
539
541
  getSystemPrompt: () => this.#getSystemPromptFn(),
542
+ localProtocolOptions: this.localProtocolOptions,
540
543
  memory: this.#getMemoryFn?.(),
541
544
  };
542
545
  }
@@ -42,6 +42,7 @@ import type { PythonResult } from "../../eval/py/executor";
42
42
  import type { BashResult } from "../../exec/bash-executor";
43
43
  import type { ExecOptions, ExecResult } from "../../exec/exec";
44
44
  import type * as PiCodingAgent from "../../index";
45
+ import type { LocalProtocolOptions } from "../../internal-urls/local-protocol";
45
46
  import type { MemoryRuntimeContext } from "../../memory-backend";
46
47
  import type { CustomEditor } from "../../modes/components/custom-editor";
47
48
  import type { Theme } from "../../modes/theme/theme";
@@ -346,6 +347,8 @@ export interface ExtensionContext {
346
347
  sessionManager: ReadonlySessionManager;
347
348
  /** Model registry for API key resolution */
348
349
  modelRegistry: ModelRegistry;
350
+ /** Calling session's `local://` root mapping for external tool bridges. */
351
+ localProtocolOptions?: LocalProtocolOptions;
349
352
  /** Current model (may be undefined) */
350
353
  model: Model | undefined;
351
354
  /** Read-only model query facade: list / current / resolve / family. */
@@ -92,6 +92,7 @@ export const BUNDLED_PI_REGISTRY_KEYS: ReadonlySet<string> = new Set([
92
92
  "@oh-my-pi/pi-ai/providers/openai-codex/request-transformer",
93
93
  "@oh-my-pi/pi-ai/providers/openai-codex/response-handler",
94
94
  "@oh-my-pi/pi-ai/usage/claude",
95
+ "@oh-my-pi/pi-ai/usage/cursor",
95
96
  "@oh-my-pi/pi-ai/usage/gemini",
96
97
  "@oh-my-pi/pi-ai/usage/github-copilot",
97
98
  "@oh-my-pi/pi-ai/usage/google-antigravity",
@@ -278,6 +279,7 @@ export const BUNDLED_PI_REGISTRY_KEYS: ReadonlySet<string> = new Set([
278
279
  "@oh-my-pi/pi-coding-agent/cli/ttsr-cli",
279
280
  "@oh-my-pi/pi-coding-agent/cli/update-cli",
280
281
  "@oh-my-pi/pi-coding-agent/cli/usage-cli",
282
+ "@oh-my-pi/pi-coding-agent/cli/usage-error",
281
283
  "@oh-my-pi/pi-coding-agent/cli/web-search-cli",
282
284
  "@oh-my-pi/pi-coding-agent/cli/worktree-cli",
283
285
  "@oh-my-pi/pi-coding-agent/cli/gallery-fixtures/agentic",
@@ -471,6 +473,7 @@ export const BUNDLED_PI_REGISTRY_KEYS: ReadonlySet<string> = new Set([
471
473
  "@oh-my-pi/pi-coding-agent/extensibility/plugins/marketplace-auto-update",
472
474
  "@oh-my-pi/pi-coding-agent/extensibility/plugins/parser",
473
475
  "@oh-my-pi/pi-coding-agent/extensibility/plugins/runtime-config",
476
+ "@oh-my-pi/pi-coding-agent/extensibility/plugins/trust",
474
477
  "@oh-my-pi/pi-coding-agent/extensibility/plugins/types",
475
478
  "@oh-my-pi/pi-coding-agent/extensibility/plugins/marketplace/cache",
476
479
  "@oh-my-pi/pi-coding-agent/extensibility/plugins/marketplace/fetcher",
@@ -511,6 +514,7 @@ export const BUNDLED_PI_REGISTRY_KEYS: ReadonlySet<string> = new Set([
511
514
  "@oh-my-pi/pi-coding-agent/eval/py/tool-bridge",
512
515
  "@oh-my-pi/pi-coding-agent/lsp/client",
513
516
  "@oh-my-pi/pi-coding-agent/lsp/config",
517
+ "@oh-my-pi/pi-coding-agent/lsp/deferred-diagnostics",
514
518
  "@oh-my-pi/pi-coding-agent/lsp/diagnostics-ledger",
515
519
  "@oh-my-pi/pi-coding-agent/lsp/edits",
516
520
  "@oh-my-pi/pi-coding-agent/lsp/format-options",
@@ -566,6 +570,7 @@ export const BUNDLED_PI_REGISTRY_KEYS: ReadonlySet<string> = new Set([
566
570
  "@oh-my-pi/pi-coding-agent/modes/interactive-mode",
567
571
  "@oh-my-pi/pi-coding-agent/modes/internal-url-autocomplete",
568
572
  "@oh-my-pi/pi-coding-agent/modes/loop-limit",
573
+ "@oh-my-pi/pi-coding-agent/modes/magic-keyword-boundary",
569
574
  "@oh-my-pi/pi-coding-agent/modes/magic-keywords",
570
575
  "@oh-my-pi/pi-coding-agent/modes/markdown-prose",
571
576
  "@oh-my-pi/pi-coding-agent/modes/oauth-manual-input",
@@ -778,6 +783,7 @@ export const BUNDLED_PI_REGISTRY_KEYS: ReadonlySet<string> = new Set([
778
783
  "@oh-my-pi/pi-coding-agent/task/discovery",
779
784
  "@oh-my-pi/pi-coding-agent/task/executor",
780
785
  "@oh-my-pi/pi-coding-agent/task/isolation-runner",
786
+ "@oh-my-pi/pi-coding-agent/task/model-tier-classifier",
781
787
  "@oh-my-pi/pi-coding-agent/task/name-generator",
782
788
  "@oh-my-pi/pi-coding-agent/task/omp-command",
783
789
  "@oh-my-pi/pi-coding-agent/task/output-manager",
@@ -800,7 +806,6 @@ export const BUNDLED_PI_REGISTRY_KEYS: ReadonlySet<string> = new Set([
800
806
  "@oh-my-pi/pi-coding-agent/tools/ast-edit",
801
807
  "@oh-my-pi/pi-coding-agent/tools/ast-grep",
802
808
  "@oh-my-pi/pi-coding-agent/tools/auto-generated-guard",
803
- "@oh-my-pi/pi-coding-agent/tools/bash-command-fixup",
804
809
  "@oh-my-pi/pi-coding-agent/tools/bash-interactive",
805
810
  "@oh-my-pi/pi-coding-agent/tools/bash-interceptor",
806
811
  "@oh-my-pi/pi-coding-agent/tools/bash-pty-selection",
@@ -847,6 +852,7 @@ export const BUNDLED_PI_REGISTRY_KEYS: ReadonlySet<string> = new Set([
847
852
  "@oh-my-pi/pi-coding-agent/tools/output-meta",
848
853
  "@oh-my-pi/pi-coding-agent/tools/output-schema-validator",
849
854
  "@oh-my-pi/pi-coding-agent/tools/path-utils",
855
+ "@oh-my-pi/pi-coding-agent/tools/path-write-lock",
850
856
  "@oh-my-pi/pi-coding-agent/tools/plan-mode-guard",
851
857
  "@oh-my-pi/pi-coding-agent/tools/read",
852
858
  "@oh-my-pi/pi-coding-agent/tools/render-utils",
@@ -857,11 +863,13 @@ export const BUNDLED_PI_REGISTRY_KEYS: ReadonlySet<string> = new Set([
857
863
  "@oh-my-pi/pi-coding-agent/tools/search-tool-bm25",
858
864
  "@oh-my-pi/pi-coding-agent/tools/sqlite-reader",
859
865
  "@oh-my-pi/pi-coding-agent/tools/ssh",
866
+ "@oh-my-pi/pi-coding-agent/tools/subagent",
860
867
  "@oh-my-pi/pi-coding-agent/tools/todo",
861
868
  "@oh-my-pi/pi-coding-agent/tools/tool-errors",
862
869
  "@oh-my-pi/pi-coding-agent/tools/tool-result",
863
870
  "@oh-my-pi/pi-coding-agent/tools/tool-timeouts",
864
871
  "@oh-my-pi/pi-coding-agent/tools/tts",
872
+ "@oh-my-pi/pi-coding-agent/tools/vision-verify",
865
873
  "@oh-my-pi/pi-coding-agent/tools/write",
866
874
  "@oh-my-pi/pi-coding-agent/tools/yield",
867
875
  "@oh-my-pi/pi-coding-agent/tui/code-cell",
@@ -116,6 +116,7 @@ import * as bundledPiAiProvidersVisionGuard from "jeopi-ai/providers/vision-guar
116
116
  import * as bundledPiAiRegistry from "jeopi-ai/registry";
117
117
  import * as bundledPiAiRegistryOauth from "jeopi-ai/registry/oauth";
118
118
  import * as bundledPiAiUsageClaude from "jeopi-ai/usage/claude";
119
+ import * as bundledPiAiUsageCursor from "jeopi-ai/usage/cursor";
119
120
  import * as bundledPiAiUsageGemini from "jeopi-ai/usage/gemini";
120
121
  import * as bundledPiAiUsageGithubCopilot from "jeopi-ai/usage/github-copilot";
121
122
  import * as bundledPiAiUsageGoogleAntigravity from "jeopi-ai/usage/google-antigravity";
@@ -252,6 +253,7 @@ import * as bundledPiCodingAgentCliTinyModelsCli from "jeopi-cli/cli/tiny-models
252
253
  import * as bundledPiCodingAgentCliTtsrCli from "jeopi-cli/cli/ttsr-cli";
253
254
  import * as bundledPiCodingAgentCliUpdateCli from "jeopi-cli/cli/update-cli";
254
255
  import * as bundledPiCodingAgentCliUsageCli from "jeopi-cli/cli/usage-cli";
256
+ import * as bundledPiCodingAgentCliUsageError from "jeopi-cli/cli/usage-error";
255
257
  import * as bundledPiCodingAgentCliWebSearchCli from "jeopi-cli/cli/web-search-cli";
256
258
  import * as bundledPiCodingAgentCliWorktreeCli from "jeopi-cli/cli/worktree-cli";
257
259
  import * as bundledPiCodingAgentCommandsAcp from "jeopi-cli/commands/acp";
@@ -463,6 +465,7 @@ import * as bundledPiCodingAgentExtensibilityPluginsMarketplaceTypes from "jeopi
463
465
  import * as bundledPiCodingAgentExtensibilityPluginsMarketplaceAutoUpdate from "jeopi-cli/extensibility/plugins/marketplace-auto-update";
464
466
  import * as bundledPiCodingAgentExtensibilityPluginsParser from "jeopi-cli/extensibility/plugins/parser";
465
467
  import * as bundledPiCodingAgentExtensibilityPluginsRuntimeConfig from "jeopi-cli/extensibility/plugins/runtime-config";
468
+ import * as bundledPiCodingAgentExtensibilityPluginsTrust from "jeopi-cli/extensibility/plugins/trust";
466
469
  import * as bundledPiCodingAgentExtensibilityPluginsTypes from "jeopi-cli/extensibility/plugins/types";
467
470
  import * as bundledPiCodingAgentExtensibilitySessionHandlerTypes from "jeopi-cli/extensibility/session-handler-types";
468
471
  import * as bundledPiCodingAgentExtensibilitySharedEvents from "jeopi-cli/extensibility/shared-events";
@@ -508,6 +511,7 @@ import * as bundledPiCodingAgentLspClientsBiomeClient from "jeopi-cli/lsp/client
508
511
  import * as bundledPiCodingAgentLspClientsLspLinterClient from "jeopi-cli/lsp/clients/lsp-linter-client";
509
512
  import * as bundledPiCodingAgentLspClientsSwiftlintClient from "jeopi-cli/lsp/clients/swiftlint-client";
510
513
  import * as bundledPiCodingAgentLspConfig from "jeopi-cli/lsp/config";
514
+ import * as bundledPiCodingAgentLspDeferredDiagnostics from "jeopi-cli/lsp/deferred-diagnostics";
511
515
  import * as bundledPiCodingAgentLspDiagnosticsLedger from "jeopi-cli/lsp/diagnostics-ledger";
512
516
  import * as bundledPiCodingAgentLspEdits from "jeopi-cli/lsp/edits";
513
517
  import * as bundledPiCodingAgentLspFormatOptions from "jeopi-cli/lsp/format-options";
@@ -666,6 +670,7 @@ import * as bundledPiCodingAgentModesImageReferences from "jeopi-cli/modes/image
666
670
  import * as bundledPiCodingAgentModesInteractiveMode from "jeopi-cli/modes/interactive-mode";
667
671
  import * as bundledPiCodingAgentModesInternalUrlAutocomplete from "jeopi-cli/modes/internal-url-autocomplete";
668
672
  import * as bundledPiCodingAgentModesLoopLimit from "jeopi-cli/modes/loop-limit";
673
+ import * as bundledPiCodingAgentModesMagicKeywordBoundary from "jeopi-cli/modes/magic-keyword-boundary";
669
674
  import * as bundledPiCodingAgentModesMagicKeywords from "jeopi-cli/modes/magic-keywords";
670
675
  import * as bundledPiCodingAgentModesMarkdownProse from "jeopi-cli/modes/markdown-prose";
671
676
  import * as bundledPiCodingAgentModesOauthManualInput from "jeopi-cli/modes/oauth-manual-input";
@@ -779,6 +784,7 @@ import * as bundledPiCodingAgentTaskCriticGate from "jeopi-cli/task/critic-gate"
779
784
  import * as bundledPiCodingAgentTaskDiscovery from "jeopi-cli/task/discovery";
780
785
  import * as bundledPiCodingAgentTaskExecutor from "jeopi-cli/task/executor";
781
786
  import * as bundledPiCodingAgentTaskIsolationRunner from "jeopi-cli/task/isolation-runner";
787
+ import * as bundledPiCodingAgentTaskModelTierClassifier from "jeopi-cli/task/model-tier-classifier";
782
788
  import * as bundledPiCodingAgentTaskNameGenerator from "jeopi-cli/task/name-generator";
783
789
  import * as bundledPiCodingAgentTaskOmpCommand from "jeopi-cli/task/omp-command";
784
790
  import * as bundledPiCodingAgentTaskOutputManager from "jeopi-cli/task/output-manager";
@@ -803,7 +809,6 @@ import * as bundledPiCodingAgentToolsAstEdit from "jeopi-cli/tools/ast-edit";
803
809
  import * as bundledPiCodingAgentToolsAstGrep from "jeopi-cli/tools/ast-grep";
804
810
  import * as bundledPiCodingAgentToolsAutoGeneratedGuard from "jeopi-cli/tools/auto-generated-guard";
805
811
  import * as bundledPiCodingAgentToolsBash from "jeopi-cli/tools/bash";
806
- import * as bundledPiCodingAgentToolsBashCommandFixup from "jeopi-cli/tools/bash-command-fixup";
807
812
  import * as bundledPiCodingAgentToolsBashInteractive from "jeopi-cli/tools/bash-interactive";
808
813
  import * as bundledPiCodingAgentToolsBashInterceptor from "jeopi-cli/tools/bash-interceptor";
809
814
  import * as bundledPiCodingAgentToolsBashPtySelection from "jeopi-cli/tools/bash-pty-selection";
@@ -849,6 +854,7 @@ import * as bundledPiCodingAgentToolsMemoryRetain from "jeopi-cli/tools/memory-r
849
854
  import * as bundledPiCodingAgentToolsOutputMeta from "jeopi-cli/tools/output-meta";
850
855
  import * as bundledPiCodingAgentToolsOutputSchemaValidator from "jeopi-cli/tools/output-schema-validator";
851
856
  import * as bundledPiCodingAgentToolsPathUtils from "jeopi-cli/tools/path-utils";
857
+ import * as bundledPiCodingAgentToolsPathWriteLock from "jeopi-cli/tools/path-write-lock";
852
858
  import * as bundledPiCodingAgentToolsPlanModeGuard from "jeopi-cli/tools/plan-mode-guard";
853
859
  import * as bundledPiCodingAgentToolsRead from "jeopi-cli/tools/read";
854
860
  import * as bundledPiCodingAgentToolsRenderUtils from "jeopi-cli/tools/render-utils";
@@ -859,11 +865,13 @@ import * as bundledPiCodingAgentToolsReview from "jeopi-cli/tools/review";
859
865
  import * as bundledPiCodingAgentToolsSearchToolBm25 from "jeopi-cli/tools/search-tool-bm25";
860
866
  import * as bundledPiCodingAgentToolsSqliteReader from "jeopi-cli/tools/sqlite-reader";
861
867
  import * as bundledPiCodingAgentToolsSsh from "jeopi-cli/tools/ssh";
868
+ import * as bundledPiCodingAgentToolsSubagent from "jeopi-cli/tools/subagent";
862
869
  import * as bundledPiCodingAgentToolsTodo from "jeopi-cli/tools/todo";
863
870
  import * as bundledPiCodingAgentToolsToolErrors from "jeopi-cli/tools/tool-errors";
864
871
  import * as bundledPiCodingAgentToolsToolResult from "jeopi-cli/tools/tool-result";
865
872
  import * as bundledPiCodingAgentToolsToolTimeouts from "jeopi-cli/tools/tool-timeouts";
866
873
  import * as bundledPiCodingAgentToolsTts from "jeopi-cli/tools/tts";
874
+ import * as bundledPiCodingAgentToolsVisionVerify from "jeopi-cli/tools/vision-verify";
867
875
  import * as bundledPiCodingAgentToolsWrite from "jeopi-cli/tools/write";
868
876
  import * as bundledPiCodingAgentToolsYield from "jeopi-cli/tools/yield";
869
877
  import * as bundledPiCodingAgentTui from "jeopi-cli/tui";
@@ -1224,6 +1232,7 @@ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string
1224
1232
  "@oh-my-pi/pi-ai/providers/openai-codex/response-handler":
1225
1233
  bundledPiAiProvidersOpenaiCodexResponseHandler as unknown as Readonly<Record<string, unknown>>,
1226
1234
  "@oh-my-pi/pi-ai/usage/claude": bundledPiAiUsageClaude as unknown as Readonly<Record<string, unknown>>,
1235
+ "@oh-my-pi/pi-ai/usage/cursor": bundledPiAiUsageCursor as unknown as Readonly<Record<string, unknown>>,
1227
1236
  "@oh-my-pi/pi-ai/usage/gemini": bundledPiAiUsageGemini as unknown as Readonly<Record<string, unknown>>,
1228
1237
  "@oh-my-pi/pi-ai/usage/github-copilot": bundledPiAiUsageGithubCopilot as unknown as Readonly<
1229
1238
  Record<string, unknown>
@@ -1628,6 +1637,9 @@ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string
1628
1637
  "@oh-my-pi/pi-coding-agent/cli/usage-cli": bundledPiCodingAgentCliUsageCli as unknown as Readonly<
1629
1638
  Record<string, unknown>
1630
1639
  >,
1640
+ "@oh-my-pi/pi-coding-agent/cli/usage-error": bundledPiCodingAgentCliUsageError as unknown as Readonly<
1641
+ Record<string, unknown>
1642
+ >,
1631
1643
  "@oh-my-pi/pi-coding-agent/cli/web-search-cli": bundledPiCodingAgentCliWebSearchCli as unknown as Readonly<
1632
1644
  Record<string, unknown>
1633
1645
  >,
@@ -2121,6 +2133,8 @@ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string
2121
2133
  bundledPiCodingAgentExtensibilityPluginsParser as unknown as Readonly<Record<string, unknown>>,
2122
2134
  "@oh-my-pi/pi-coding-agent/extensibility/plugins/runtime-config":
2123
2135
  bundledPiCodingAgentExtensibilityPluginsRuntimeConfig as unknown as Readonly<Record<string, unknown>>,
2136
+ "@oh-my-pi/pi-coding-agent/extensibility/plugins/trust":
2137
+ bundledPiCodingAgentExtensibilityPluginsTrust as unknown as Readonly<Record<string, unknown>>,
2124
2138
  "@oh-my-pi/pi-coding-agent/extensibility/plugins/types":
2125
2139
  bundledPiCodingAgentExtensibilityPluginsTypes as unknown as Readonly<Record<string, unknown>>,
2126
2140
  "@oh-my-pi/pi-coding-agent/extensibility/plugins/marketplace/cache":
@@ -2218,6 +2232,8 @@ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string
2218
2232
  "@oh-my-pi/pi-coding-agent/lsp/config": bundledPiCodingAgentLspConfig as unknown as Readonly<
2219
2233
  Record<string, unknown>
2220
2234
  >,
2235
+ "@oh-my-pi/pi-coding-agent/lsp/deferred-diagnostics":
2236
+ bundledPiCodingAgentLspDeferredDiagnostics as unknown as Readonly<Record<string, unknown>>,
2221
2237
  "@oh-my-pi/pi-coding-agent/lsp/diagnostics-ledger": bundledPiCodingAgentLspDiagnosticsLedger as unknown as Readonly<
2222
2238
  Record<string, unknown>
2223
2239
  >,
@@ -2366,6 +2382,8 @@ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string
2366
2382
  "@oh-my-pi/pi-coding-agent/modes/loop-limit": bundledPiCodingAgentModesLoopLimit as unknown as Readonly<
2367
2383
  Record<string, unknown>
2368
2384
  >,
2385
+ "@oh-my-pi/pi-coding-agent/modes/magic-keyword-boundary":
2386
+ bundledPiCodingAgentModesMagicKeywordBoundary as unknown as Readonly<Record<string, unknown>>,
2369
2387
  "@oh-my-pi/pi-coding-agent/modes/magic-keywords": bundledPiCodingAgentModesMagicKeywords as unknown as Readonly<
2370
2388
  Record<string, unknown>
2371
2389
  >,
@@ -2854,6 +2872,8 @@ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string
2854
2872
  "@oh-my-pi/pi-coding-agent/task/isolation-runner": bundledPiCodingAgentTaskIsolationRunner as unknown as Readonly<
2855
2873
  Record<string, unknown>
2856
2874
  >,
2875
+ "@oh-my-pi/pi-coding-agent/task/model-tier-classifier":
2876
+ bundledPiCodingAgentTaskModelTierClassifier as unknown as Readonly<Record<string, unknown>>,
2857
2877
  "@oh-my-pi/pi-coding-agent/task/name-generator": bundledPiCodingAgentTaskNameGenerator as unknown as Readonly<
2858
2878
  Record<string, unknown>
2859
2879
  >,
@@ -2914,8 +2934,6 @@ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string
2914
2934
  >,
2915
2935
  "@oh-my-pi/pi-coding-agent/tools/auto-generated-guard":
2916
2936
  bundledPiCodingAgentToolsAutoGeneratedGuard as unknown as Readonly<Record<string, unknown>>,
2917
- "@oh-my-pi/pi-coding-agent/tools/bash-command-fixup":
2918
- bundledPiCodingAgentToolsBashCommandFixup as unknown as Readonly<Record<string, unknown>>,
2919
2937
  "@oh-my-pi/pi-coding-agent/tools/bash-interactive": bundledPiCodingAgentToolsBashInteractive as unknown as Readonly<
2920
2938
  Record<string, unknown>
2921
2939
  >,
@@ -3041,6 +3059,9 @@ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string
3041
3059
  "@oh-my-pi/pi-coding-agent/tools/path-utils": bundledPiCodingAgentToolsPathUtils as unknown as Readonly<
3042
3060
  Record<string, unknown>
3043
3061
  >,
3062
+ "@oh-my-pi/pi-coding-agent/tools/path-write-lock": bundledPiCodingAgentToolsPathWriteLock as unknown as Readonly<
3063
+ Record<string, unknown>
3064
+ >,
3044
3065
  "@oh-my-pi/pi-coding-agent/tools/plan-mode-guard": bundledPiCodingAgentToolsPlanModeGuard as unknown as Readonly<
3045
3066
  Record<string, unknown>
3046
3067
  >,
@@ -3069,6 +3090,9 @@ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string
3069
3090
  Record<string, unknown>
3070
3091
  >,
3071
3092
  "@oh-my-pi/pi-coding-agent/tools/ssh": bundledPiCodingAgentToolsSsh as unknown as Readonly<Record<string, unknown>>,
3093
+ "@oh-my-pi/pi-coding-agent/tools/subagent": bundledPiCodingAgentToolsSubagent as unknown as Readonly<
3094
+ Record<string, unknown>
3095
+ >,
3072
3096
  "@oh-my-pi/pi-coding-agent/tools/todo": bundledPiCodingAgentToolsTodo as unknown as Readonly<
3073
3097
  Record<string, unknown>
3074
3098
  >,
@@ -3082,6 +3106,9 @@ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string
3082
3106
  Record<string, unknown>
3083
3107
  >,
3084
3108
  "@oh-my-pi/pi-coding-agent/tools/tts": bundledPiCodingAgentToolsTts as unknown as Readonly<Record<string, unknown>>,
3109
+ "@oh-my-pi/pi-coding-agent/tools/vision-verify": bundledPiCodingAgentToolsVisionVerify as unknown as Readonly<
3110
+ Record<string, unknown>
3111
+ >,
3085
3112
  "@oh-my-pi/pi-coding-agent/tools/write": bundledPiCodingAgentToolsWrite as unknown as Readonly<
3086
3113
  Record<string, unknown>
3087
3114
  >,
@@ -212,6 +212,16 @@ export class PluginManager {
212
212
  }
213
213
  }
214
214
 
215
+ async #removeDependencyEntry(pkgJsonPath: string, name: string): Promise<void> {
216
+ const pkgJson: { dependencies?: Record<string, string>; [key: string]: unknown } =
217
+ await Bun.file(pkgJsonPath).json();
218
+ if (!pkgJson.dependencies || !(name in pkgJson.dependencies)) {
219
+ return;
220
+ }
221
+ delete pkgJson.dependencies[name];
222
+ await Bun.write(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
223
+ }
224
+
215
225
  #collectInstalledNames(deps: Record<string, string>, config: PluginRuntimeConfig): Set<string> {
216
226
  const installedNames = new Set<string>();
217
227
  for (const name of Object.keys(deps)) {
@@ -451,6 +461,17 @@ export class PluginManager {
451
461
  // validation throws.
452
462
  let actualName: string | undefined;
453
463
  try {
464
+ // Bun treats a dependency replacement from `repo#old-ref` to the same
465
+ // package at `repo`/`repo#new-ref` as a self-edge and bails with
466
+ // DependencyLoop. Remove only the stale manifest edge; rollback restores
467
+ // the original package.json and node_modules snapshot on failure.
468
+ if (gitSource && existingActualName) {
469
+ const installedSource = parseGitUrl(depsBefore[existingActualName] ?? "");
470
+ if (installedSource && installedSource.ref !== gitSource.ref) {
471
+ await this.#removeDependencyEntry(pkgJsonPath, existingActualName);
472
+ }
473
+ }
474
+
454
475
  // Step 1: write the spec into plugins/package.json + node_modules.
455
476
  const installProc = Bun.spawn(["bun", "install", packageInstallSpec], {
456
477
  cwd: getPluginsDir(),