@oh-my-pi/pi-coding-agent 1.341.0 → 2.0.1337

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 (151) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +1 -1
  3. package/examples/custom-tools/subagent/index.ts +1 -1
  4. package/package.json +5 -3
  5. package/src/cli/args.ts +5 -6
  6. package/src/cli/file-processor.ts +3 -3
  7. package/src/cli/list-models.ts +2 -2
  8. package/src/cli/plugin-cli.ts +1 -1
  9. package/src/cli/session-picker.ts +2 -2
  10. package/src/cli.ts +1 -1
  11. package/src/config.ts +3 -3
  12. package/src/core/agent-session.ts +157 -15
  13. package/src/core/bash-executor.ts +50 -10
  14. package/src/core/compaction/branch-summarization.ts +5 -5
  15. package/src/core/compaction/compaction.ts +3 -3
  16. package/src/core/compaction/index.ts +3 -3
  17. package/src/core/custom-commands/bundled/review/index.ts +156 -0
  18. package/src/core/custom-commands/index.ts +15 -0
  19. package/src/core/custom-commands/loader.ts +232 -0
  20. package/src/core/custom-commands/types.ts +112 -0
  21. package/src/core/custom-tools/index.ts +3 -3
  22. package/src/core/custom-tools/loader.ts +10 -8
  23. package/src/core/custom-tools/types.ts +11 -6
  24. package/src/core/custom-tools/wrapper.ts +2 -1
  25. package/src/core/exec.ts +22 -12
  26. package/src/core/export-html/index.ts +5 -5
  27. package/src/core/file-mentions.ts +54 -0
  28. package/src/core/hooks/index.ts +5 -5
  29. package/src/core/hooks/loader.ts +21 -16
  30. package/src/core/hooks/runner.ts +6 -6
  31. package/src/core/hooks/tool-wrapper.ts +2 -2
  32. package/src/core/hooks/types.ts +12 -15
  33. package/src/core/index.ts +6 -6
  34. package/src/core/logger.ts +112 -0
  35. package/src/core/mcp/client.ts +3 -3
  36. package/src/core/mcp/config.ts +1 -1
  37. package/src/core/mcp/index.ts +12 -12
  38. package/src/core/mcp/loader.ts +2 -2
  39. package/src/core/mcp/manager.ts +6 -6
  40. package/src/core/mcp/tool-bridge.ts +3 -3
  41. package/src/core/mcp/transports/http.ts +1 -1
  42. package/src/core/mcp/transports/index.ts +2 -2
  43. package/src/core/mcp/transports/stdio.ts +1 -1
  44. package/src/core/messages.ts +22 -0
  45. package/src/core/model-registry.ts +2 -2
  46. package/src/core/model-resolver.ts +2 -2
  47. package/src/core/plugins/doctor.ts +1 -1
  48. package/src/core/plugins/index.ts +6 -6
  49. package/src/core/plugins/installer.ts +4 -4
  50. package/src/core/plugins/loader.ts +4 -9
  51. package/src/core/plugins/manager.ts +5 -5
  52. package/src/core/plugins/paths.ts +3 -3
  53. package/src/core/sdk.ts +77 -35
  54. package/src/core/session-manager.ts +6 -6
  55. package/src/core/settings-manager.ts +16 -3
  56. package/src/core/skills.ts +5 -5
  57. package/src/core/slash-commands.ts +60 -45
  58. package/src/core/system-prompt.ts +6 -6
  59. package/src/core/title-generator.ts +2 -2
  60. package/src/core/tools/bash.ts +32 -155
  61. package/src/core/tools/context.ts +2 -2
  62. package/src/core/tools/edit-diff.ts +3 -3
  63. package/src/core/tools/edit.ts +18 -5
  64. package/src/core/tools/exa/company.ts +3 -3
  65. package/src/core/tools/exa/index.ts +16 -17
  66. package/src/core/tools/exa/linkedin.ts +3 -3
  67. package/src/core/tools/exa/mcp-client.ts +9 -9
  68. package/src/core/tools/exa/render.ts +5 -5
  69. package/src/core/tools/exa/researcher.ts +3 -3
  70. package/src/core/tools/exa/search.ts +6 -5
  71. package/src/core/tools/exa/types.ts +5 -6
  72. package/src/core/tools/exa/websets.ts +3 -3
  73. package/src/core/tools/find.ts +3 -3
  74. package/src/core/tools/grep.ts +3 -3
  75. package/src/core/tools/index.ts +48 -34
  76. package/src/core/tools/ls.ts +4 -4
  77. package/src/core/tools/lsp/client.ts +161 -90
  78. package/src/core/tools/lsp/config.ts +1 -1
  79. package/src/core/tools/lsp/edits.ts +2 -2
  80. package/src/core/tools/lsp/index.ts +15 -13
  81. package/src/core/tools/lsp/render.ts +2 -2
  82. package/src/core/tools/lsp/rust-analyzer.ts +3 -3
  83. package/src/core/tools/lsp/utils.ts +1 -1
  84. package/src/core/tools/notebook.ts +1 -1
  85. package/src/core/tools/output.ts +175 -0
  86. package/src/core/tools/read.ts +7 -7
  87. package/src/core/tools/renderers.ts +92 -13
  88. package/src/core/tools/review.ts +268 -0
  89. package/src/core/tools/task/agents.ts +1 -1
  90. package/src/core/tools/task/bundled-agents/reviewer.md +52 -37
  91. package/src/core/tools/task/discovery.ts +2 -2
  92. package/src/core/tools/task/executor.ts +145 -28
  93. package/src/core/tools/task/index.ts +78 -30
  94. package/src/core/tools/task/model-resolver.ts +30 -20
  95. package/src/core/tools/task/parallel.ts +1 -1
  96. package/src/core/tools/task/render.ts +219 -30
  97. package/src/core/tools/task/subprocess-tool-registry.ts +89 -0
  98. package/src/core/tools/task/types.ts +36 -2
  99. package/src/core/tools/web-fetch.ts +5 -3
  100. package/src/core/tools/web-search/auth.ts +1 -1
  101. package/src/core/tools/web-search/index.ts +17 -15
  102. package/src/core/tools/web-search/providers/anthropic.ts +2 -2
  103. package/src/core/tools/web-search/providers/exa.ts +3 -5
  104. package/src/core/tools/web-search/providers/perplexity.ts +1 -1
  105. package/src/core/tools/web-search/render.ts +3 -3
  106. package/src/core/tools/write.ts +4 -4
  107. package/src/index.ts +29 -18
  108. package/src/main.ts +37 -32
  109. package/src/migrations.ts +3 -3
  110. package/src/modes/index.ts +5 -5
  111. package/src/modes/interactive/components/armin.ts +1 -1
  112. package/src/modes/interactive/components/assistant-message.ts +1 -1
  113. package/src/modes/interactive/components/bash-execution.ts +4 -4
  114. package/src/modes/interactive/components/bordered-loader.ts +2 -2
  115. package/src/modes/interactive/components/branch-summary-message.ts +2 -2
  116. package/src/modes/interactive/components/compaction-summary-message.ts +2 -2
  117. package/src/modes/interactive/components/diff.ts +1 -1
  118. package/src/modes/interactive/components/dynamic-border.ts +1 -1
  119. package/src/modes/interactive/components/footer.ts +5 -5
  120. package/src/modes/interactive/components/hook-editor.ts +2 -2
  121. package/src/modes/interactive/components/hook-input.ts +2 -2
  122. package/src/modes/interactive/components/hook-message.ts +3 -3
  123. package/src/modes/interactive/components/hook-selector.ts +2 -2
  124. package/src/modes/interactive/components/model-selector.ts +281 -59
  125. package/src/modes/interactive/components/oauth-selector.ts +3 -3
  126. package/src/modes/interactive/components/plugin-settings.ts +4 -4
  127. package/src/modes/interactive/components/queue-mode-selector.ts +2 -2
  128. package/src/modes/interactive/components/session-selector.ts +4 -4
  129. package/src/modes/interactive/components/settings-defs.ts +1 -1
  130. package/src/modes/interactive/components/settings-selector.ts +5 -5
  131. package/src/modes/interactive/components/show-images-selector.ts +2 -2
  132. package/src/modes/interactive/components/theme-selector.ts +2 -2
  133. package/src/modes/interactive/components/thinking-selector.ts +2 -2
  134. package/src/modes/interactive/components/tool-execution.ts +26 -8
  135. package/src/modes/interactive/components/tree-selector.ts +3 -3
  136. package/src/modes/interactive/components/user-message-selector.ts +2 -2
  137. package/src/modes/interactive/components/user-message.ts +1 -1
  138. package/src/modes/interactive/components/welcome.ts +2 -2
  139. package/src/modes/interactive/interactive-mode.ts +85 -41
  140. package/src/modes/interactive/theme/theme.ts +8 -7
  141. package/src/modes/print-mode.ts +4 -3
  142. package/src/modes/rpc/rpc-client.ts +4 -4
  143. package/src/modes/rpc/rpc-mode.ts +21 -11
  144. package/src/modes/rpc/rpc-types.ts +3 -3
  145. package/src/utils/changelog.ts +2 -2
  146. package/src/utils/clipboard.ts +1 -1
  147. package/src/utils/shell-snapshot.ts +218 -0
  148. package/src/utils/shell.ts +93 -13
  149. package/src/utils/tools-manager.ts +1 -1
  150. package/examples/custom-tools/subagent/agents/reviewer.md +0 -35
  151. package/src/core/tools/exa/logger.ts +0 -56
@@ -14,16 +14,16 @@
14
14
 
15
15
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
16
16
  import { Type } from "@sinclair/typebox";
17
- import type { Theme } from "../../../modes/interactive/theme/theme.js";
18
- import type { CustomTool, CustomToolContext, RenderResultOptions } from "../../custom-tools/types.js";
19
- import { callExaTool, findApiKey as findExaKey, formatSearchResults, isSearchResponse } from "../exa/mcp-client.js";
20
- import { renderExaCall, renderExaResult } from "../exa/render.js";
21
- import type { ExaRenderDetails } from "../exa/types.js";
22
- import { searchAnthropic } from "./providers/anthropic.js";
23
- import { searchExa } from "./providers/exa.js";
24
- import { findApiKey as findPerplexityKey, searchPerplexity } from "./providers/perplexity.js";
25
- import { formatAge, renderWebSearchCall, renderWebSearchResult, type WebSearchRenderDetails } from "./render.js";
26
- import type { WebSearchProvider, WebSearchResponse } from "./types.js";
17
+ import type { Theme } from "../../../modes/interactive/theme/theme";
18
+ import type { CustomTool, CustomToolContext, RenderResultOptions } from "../../custom-tools/types";
19
+ import { callExaTool, findApiKey as findExaKey, formatSearchResults, isSearchResponse } from "../exa/mcp-client";
20
+ import { renderExaCall, renderExaResult } from "../exa/render";
21
+ import type { ExaRenderDetails } from "../exa/types";
22
+ import { searchAnthropic } from "./providers/anthropic";
23
+ import { searchExa } from "./providers/exa";
24
+ import { findApiKey as findPerplexityKey, searchPerplexity } from "./providers/perplexity";
25
+ import { formatAge, renderWebSearchCall, renderWebSearchResult, type WebSearchRenderDetails } from "./render";
26
+ import type { WebSearchProvider, WebSearchResponse } from "./types";
27
27
 
28
28
  /** Web search parameters schema */
29
29
  export const webSearchSchema = Type.Object({
@@ -345,7 +345,9 @@ Parameters:
345
345
  parameters: webSearchDeepSchema,
346
346
 
347
347
  async execute(_toolCallId, params, _onUpdate, _ctx, _signal) {
348
- return executeExaTool("deep_search_exa", params as Record<string, unknown>, "web_search_deep");
348
+ const { num_results, ...rest } = params as Record<string, unknown>;
349
+ const args = { ...rest, type: "deep", numResults: num_results ?? 10 };
350
+ return executeExaTool("web_search_exa", args, "web_search_deep");
349
351
  },
350
352
 
351
353
  renderCall(args, theme) {
@@ -404,7 +406,7 @@ Parameters:
404
406
  parameters: webSearchCrawlSchema,
405
407
 
406
408
  async execute(_toolCallId, params, _onUpdate, _ctx, _signal) {
407
- return executeExaTool("crawling_exa", params as Record<string, unknown>, "web_search_crawl");
409
+ return executeExaTool("crawling", params as Record<string, unknown>, "web_search_crawl");
408
410
  },
409
411
 
410
412
  renderCall(args, theme) {
@@ -435,7 +437,7 @@ Parameters:
435
437
  parameters: webSearchLinkedinSchema,
436
438
 
437
439
  async execute(_toolCallId, params, _onUpdate, _ctx, _signal) {
438
- return executeExaTool("linkedin_search_exa", params as Record<string, unknown>, "web_search_linkedin");
440
+ return executeExaTool("linkedin_search", params as Record<string, unknown>, "web_search_linkedin");
439
441
  },
440
442
 
441
443
  renderCall(args, theme) {
@@ -465,7 +467,7 @@ Parameters:
465
467
  parameters: webSearchCompanySchema,
466
468
 
467
469
  async execute(_toolCallId, params, _onUpdate, _ctx, _signal) {
468
- return executeExaTool("company_research_exa", params as Record<string, unknown>, "web_search_company");
470
+ return executeExaTool("company_research", params as Record<string, unknown>, "web_search_company");
469
471
  },
470
472
 
471
473
  renderCall(args, theme) {
@@ -534,4 +536,4 @@ export async function hasExaWebSearch(): Promise<boolean> {
534
536
  return exaKey !== null;
535
537
  }
536
538
 
537
- export type { WebSearchProvider, WebSearchResponse } from "./types.js";
539
+ export type { WebSearchProvider, WebSearchResponse } from "./types";
@@ -5,7 +5,7 @@
5
5
  * Returns synthesized answers with citations and source metadata.
6
6
  */
7
7
 
8
- import { buildAnthropicHeaders, buildAnthropicUrl, findAnthropicAuth, getEnv } from "../auth.js";
8
+ import { buildAnthropicHeaders, buildAnthropicUrl, findAnthropicAuth, getEnv } from "../auth";
9
9
  import type {
10
10
  AnthropicApiResponse,
11
11
  AnthropicAuthConfig,
@@ -13,7 +13,7 @@ import type {
13
13
  WebSearchCitation,
14
14
  WebSearchResponse,
15
15
  WebSearchSource,
16
- } from "../types.js";
16
+ } from "../types";
17
17
 
18
18
  const DEFAULT_MODEL = "claude-sonnet-4-5-20250514";
19
19
  const DEFAULT_MAX_TOKENS = 4096;
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import * as os from "node:os";
9
- import type { WebSearchResponse, WebSearchSource } from "../types.js";
9
+ import type { WebSearchResponse, WebSearchSource } from "../types";
10
10
 
11
11
  const EXA_MCP_URL = "https://mcp.exa.ai/mcp";
12
12
 
@@ -248,10 +248,8 @@ export async function searchExa(params: ExaSearchParams): Promise<WebSearchRespo
248
248
 
249
249
  const args: Record<string, unknown> = {
250
250
  query: params.query,
251
- num_results: params.num_results ?? 10,
251
+ numResults: params.num_results ?? 10,
252
252
  type: params.type ?? "auto",
253
- text: true, // Include text for richer results
254
- highlights: true,
255
253
  };
256
254
 
257
255
  if (params.include_domains?.length) {
@@ -267,7 +265,7 @@ export async function searchExa(params: ExaSearchParams): Promise<WebSearchRespo
267
265
  args.end_published_date = params.end_published_date;
268
266
  }
269
267
 
270
- const response = await callExaMCP(apiKey, "web_search", args);
268
+ const response = await callExaMCP(apiKey, "web_search_exa", args);
271
269
 
272
270
  if (response.error) {
273
271
  throw new Error(`Exa MCP error: ${response.error.message}`);
@@ -12,7 +12,7 @@ import type {
12
12
  WebSearchCitation,
13
13
  WebSearchResponse,
14
14
  WebSearchSource,
15
- } from "../types.js";
15
+ } from "../types";
16
16
 
17
17
  const PERPLEXITY_API_URL = "https://api.perplexity.ai/chat/completions";
18
18
 
@@ -6,9 +6,9 @@
6
6
 
7
7
  import type { Component } from "@oh-my-pi/pi-tui";
8
8
  import { Text } from "@oh-my-pi/pi-tui";
9
- import type { Theme } from "../../../modes/interactive/theme/theme.js";
10
- import type { RenderResultOptions } from "../../custom-tools/types.js";
11
- import type { WebSearchResponse } from "./types.js";
9
+ import type { Theme } from "../../../modes/interactive/theme/theme";
10
+ import type { RenderResultOptions } from "../../custom-tools/types";
11
+ import type { WebSearchResponse } from "./types";
12
12
 
13
13
  // Tree formatting constants
14
14
  const TREE_MID = "├─";
@@ -1,9 +1,9 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
1
3
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
2
4
  import { Type } from "@sinclair/typebox";
3
- import { mkdir, writeFile } from "fs/promises";
4
- import { dirname } from "path";
5
- import type { FileDiagnosticsResult, FileFormatResult } from "./lsp/index.js";
6
- import { resolveToCwd } from "./path-utils.js";
5
+ import type { FileDiagnosticsResult, FileFormatResult } from "./lsp/index";
6
+ import { resolveToCwd } from "./path-utils";
7
7
 
8
8
  const writeSchema = Type.Object({
9
9
  path: Type.String({ description: "Path to the file to write (relative or absolute)" }),
package/src/index.ts CHANGED
@@ -10,9 +10,9 @@ export {
10
10
  type ModelCycleResult,
11
11
  type PromptOptions,
12
12
  type SessionStats,
13
- } from "./core/agent-session.js";
13
+ } from "./core/agent-session";
14
14
  // Auth and model registry
15
- export { type ApiKeyCredential, type AuthCredential, AuthStorage, type OAuthCredential } from "./core/auth-storage.js";
15
+ export { type ApiKeyCredential, type AuthCredential, AuthStorage, type OAuthCredential } from "./core/auth-storage";
16
16
  // Compaction
17
17
  export {
18
18
  type BranchPreparation,
@@ -35,7 +35,16 @@ export {
35
35
  prepareBranchEntries,
36
36
  serializeConversation,
37
37
  shouldCompact,
38
- } from "./core/compaction/index.js";
38
+ } from "./core/compaction/index";
39
+ // Custom commands
40
+ export type {
41
+ CustomCommand,
42
+ CustomCommandAPI,
43
+ CustomCommandFactory,
44
+ CustomCommandSource,
45
+ CustomCommandsLoadResult,
46
+ LoadedCustomCommand,
47
+ } from "./core/custom-commands/types";
39
48
  // Custom tools
40
49
  export type {
41
50
  AgentToolUpdateCallback,
@@ -49,9 +58,9 @@ export type {
49
58
  ExecResult,
50
59
  LoadedCustomTool,
51
60
  RenderResultOptions,
52
- } from "./core/custom-tools/index.js";
53
- export { discoverAndLoadCustomTools, loadCustomTools } from "./core/custom-tools/index.js";
54
- export type * from "./core/hooks/index.js";
61
+ } from "./core/custom-tools/index";
62
+ export { discoverAndLoadCustomTools, loadCustomTools } from "./core/custom-tools/index";
63
+ export type * from "./core/hooks/index";
55
64
  // Hook system types and type guards
56
65
  export {
57
66
  isBashToolResult,
@@ -61,9 +70,11 @@ export {
61
70
  isLsToolResult,
62
71
  isReadToolResult,
63
72
  isWriteToolResult,
64
- } from "./core/hooks/index.js";
65
- export { convertToLlm } from "./core/messages.js";
66
- export { ModelRegistry } from "./core/model-registry.js";
73
+ } from "./core/hooks/index";
74
+ // Logging
75
+ export { type Logger, logger } from "./core/logger";
76
+ export { convertToLlm } from "./core/messages";
77
+ export { ModelRegistry } from "./core/model-registry";
67
78
  // SDK for programmatic usage
68
79
  export {
69
80
  type BuildSystemPromptOptions,
@@ -98,7 +109,7 @@ export {
98
109
  loadSettings,
99
110
  // Pre-built tools (use process.cwd())
100
111
  readOnlyTools,
101
- } from "./core/sdk.js";
112
+ } from "./core/sdk";
102
113
  export {
103
114
  type BranchSummaryEntry,
104
115
  buildSessionContext,
@@ -120,7 +131,7 @@ export {
120
131
  SessionManager,
121
132
  type SessionMessageEntry,
122
133
  type ThinkingLevelChangeEntry,
123
- } from "./core/session-manager.js";
134
+ } from "./core/session-manager";
124
135
  export {
125
136
  type CompactionSettings,
126
137
  type LspSettings,
@@ -128,7 +139,7 @@ export {
128
139
  type Settings,
129
140
  SettingsManager,
130
141
  type SkillsSettings,
131
- } from "./core/settings-manager.js";
142
+ } from "./core/settings-manager";
132
143
  // Skills
133
144
  export {
134
145
  formatSkillsForPrompt,
@@ -139,7 +150,7 @@ export {
139
150
  type Skill,
140
151
  type SkillFrontmatter,
141
152
  type SkillWarning,
142
- } from "./core/skills.js";
153
+ } from "./core/skills";
143
154
  // Tools
144
155
  export {
145
156
  type BashToolDetails,
@@ -159,14 +170,14 @@ export {
159
170
  type WriteToolDetails,
160
171
  type WriteToolOptions,
161
172
  writeTool,
162
- } from "./core/tools/index.js";
163
- export type { FileDiagnosticsResult } from "./core/tools/lsp/index.js";
173
+ } from "./core/tools/index";
174
+ export type { FileDiagnosticsResult } from "./core/tools/lsp/index";
164
175
  // Main entry point
165
- export { main } from "./main.js";
176
+ export { main } from "./main";
166
177
  // UI components for hooks and custom tools
167
- export { BorderedLoader } from "./modes/interactive/components/bordered-loader.js";
178
+ export { BorderedLoader } from "./modes/interactive/components/bordered-loader";
168
179
  // Theme utilities for custom tools
169
- export { getMarkdownTheme } from "./modes/interactive/theme/theme.js";
180
+ export { getMarkdownTheme } from "./modes/interactive/theme/theme";
170
181
 
171
182
  // TypeBox helper for string enums (convenience for custom tools)
172
183
  import { type TSchema, Type } from "@sinclair/typebox";
package/src/main.ts CHANGED
@@ -5,33 +5,33 @@
5
5
  * createAgentSession() options. The SDK does the heavy lifting.
6
6
  */
7
7
 
8
+ import { existsSync } from "node:fs";
9
+ import { join } from "node:path";
8
10
  import { type ImageContent, supportsXhigh } from "@oh-my-pi/pi-ai";
9
11
  import chalk from "chalk";
10
- import { existsSync } from "fs";
11
- import { join } from "path";
12
- import { type Args, parseArgs, printHelp } from "./cli/args.js";
13
- import { processFileArguments } from "./cli/file-processor.js";
14
- import { listModels } from "./cli/list-models.js";
15
- import { parsePluginArgs, printPluginHelp, runPluginCommand } from "./cli/plugin-cli.js";
16
- import { selectSession } from "./cli/session-picker.js";
17
- import { CONFIG_DIR_NAME, getAgentDir, getModelsPath, VERSION } from "./config.js";
18
- import type { AgentSession } from "./core/agent-session.js";
19
- import type { LoadedCustomTool } from "./core/custom-tools/index.js";
20
- import { exportFromFile } from "./core/export-html/index.js";
21
- import type { HookUIContext } from "./core/index.js";
22
- import type { ModelRegistry } from "./core/model-registry.js";
23
- import { resolveModelScope, type ScopedModel } from "./core/model-resolver.js";
24
- import { type CreateAgentSessionOptions, createAgentSession, discoverAuthStorage, discoverModels } from "./core/sdk.js";
25
- import { SessionManager } from "./core/session-manager.js";
26
- import { SettingsManager } from "./core/settings-manager.js";
27
- import { resolvePromptInput } from "./core/system-prompt.js";
28
- import { printTimings, time } from "./core/timings.js";
29
- import { allTools } from "./core/tools/index.js";
30
- import { runMigrations } from "./migrations.js";
31
- import { InteractiveMode, installTerminalCrashHandlers, runPrintMode, runRpcMode } from "./modes/index.js";
32
- import { initTheme, stopThemeWatcher } from "./modes/interactive/theme/theme.js";
33
- import { getChangelogPath, getNewEntries, parseChangelog } from "./utils/changelog.js";
34
- import { ensureTool } from "./utils/tools-manager.js";
12
+ import { type Args, parseArgs, printHelp } from "./cli/args";
13
+ import { processFileArguments } from "./cli/file-processor";
14
+ import { listModels } from "./cli/list-models";
15
+ import { parsePluginArgs, printPluginHelp, runPluginCommand } from "./cli/plugin-cli";
16
+ import { selectSession } from "./cli/session-picker";
17
+ import { CONFIG_DIR_NAME, getAgentDir, getModelsPath, VERSION } from "./config";
18
+ import type { AgentSession } from "./core/agent-session";
19
+ import type { LoadedCustomTool } from "./core/custom-tools/index";
20
+ import { exportFromFile } from "./core/export-html/index";
21
+ import type { HookUIContext } from "./core/index";
22
+ import type { ModelRegistry } from "./core/model-registry";
23
+ import { parseModelPattern, resolveModelScope, type ScopedModel } from "./core/model-resolver";
24
+ import { type CreateAgentSessionOptions, createAgentSession, discoverAuthStorage, discoverModels } from "./core/sdk";
25
+ import { SessionManager } from "./core/session-manager";
26
+ import { SettingsManager } from "./core/settings-manager";
27
+ import { resolvePromptInput } from "./core/system-prompt";
28
+ import { printTimings, time } from "./core/timings";
29
+ import { allTools } from "./core/tools/index";
30
+ import { runMigrations } from "./migrations";
31
+ import { InteractiveMode, installTerminalCrashHandlers, runPrintMode, runRpcMode } from "./modes/index";
32
+ import { initTheme, stopThemeWatcher } from "./modes/interactive/theme/theme";
33
+ import { getChangelogPath, getNewEntries, parseChangelog } from "./utils/changelog";
34
+ import { ensureTool } from "./utils/tools-manager";
35
35
 
36
36
  async function checkForNewVersion(currentVersion: string): Promise<string | undefined> {
37
37
  try {
@@ -213,12 +213,12 @@ function discoverSystemPromptFile(): string | undefined {
213
213
  return undefined;
214
214
  }
215
215
 
216
- function buildSessionOptions(
216
+ async function buildSessionOptions(
217
217
  parsed: Args,
218
218
  scopedModels: ScopedModel[],
219
219
  sessionManager: SessionManager | undefined,
220
220
  modelRegistry: ModelRegistry,
221
- ): CreateAgentSessionOptions {
221
+ ): Promise<CreateAgentSessionOptions> {
222
222
  const options: CreateAgentSessionOptions = {};
223
223
 
224
224
  // Auto-discover SYSTEM.md if no CLI system prompt provided
@@ -230,11 +230,15 @@ function buildSessionOptions(
230
230
  options.sessionManager = sessionManager;
231
231
  }
232
232
 
233
- // Model from CLI
234
- if (parsed.provider && parsed.model) {
235
- const model = modelRegistry.find(parsed.provider, parsed.model);
233
+ // Model from CLI (--model) - uses same fuzzy matching as --models
234
+ if (parsed.model) {
235
+ const available = await modelRegistry.getAvailable();
236
+ const { model, warning } = parseModelPattern(parsed.model, available);
237
+ if (warning) {
238
+ console.warn(chalk.yellow(`Warning: ${warning}`));
239
+ }
236
240
  if (!model) {
237
- console.error(chalk.red(`Model ${parsed.provider}/${parsed.model} not found`));
241
+ console.error(chalk.red(`Model "${parsed.model}" not found`));
238
242
  process.exit(1);
239
243
  }
240
244
  options.model = model;
@@ -269,6 +273,7 @@ function buildSessionOptions(
269
273
  // Tools
270
274
  if (parsed.tools) {
271
275
  options.tools = parsed.tools.map((name) => allTools[name]);
276
+ options.explicitTools = parsed.tools;
272
277
  }
273
278
 
274
279
  // Skills
@@ -398,7 +403,7 @@ export async function main(args: string[]) {
398
403
  sessionManager = SessionManager.open(selectedPath);
399
404
  }
400
405
 
401
- const sessionOptions = buildSessionOptions(parsed, scopedModels, sessionManager, modelRegistry);
406
+ const sessionOptions = await buildSessionOptions(parsed, scopedModels, sessionManager, modelRegistry);
402
407
  sessionOptions.authStorage = authStorage;
403
408
  sessionOptions.modelRegistry = modelRegistry;
404
409
  sessionOptions.hasUI = isInteractive;
package/src/migrations.ts CHANGED
@@ -2,9 +2,9 @@
2
2
  * One-time migrations that run on startup.
3
3
  */
4
4
 
5
- import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync } from "fs";
6
- import { dirname, join } from "path";
7
- import { getAgentDir } from "./config.js";
5
+ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
6
+ import { dirname, join } from "node:path";
7
+ import { getAgentDir } from "./config";
8
8
 
9
9
  /**
10
10
  * Migrate legacy oauth.json and settings.json apiKeys to auth.json.
@@ -36,8 +36,8 @@ export function installTerminalCrashHandlers(): void {
36
36
  });
37
37
  }
38
38
 
39
- export { InteractiveMode } from "./interactive/interactive-mode.js";
40
- export { runPrintMode } from "./print-mode.js";
41
- export { type ModelInfo, RpcClient, type RpcClientOptions, type RpcEventListener } from "./rpc/rpc-client.js";
42
- export { runRpcMode } from "./rpc/rpc-mode.js";
43
- export type { RpcCommand, RpcResponse, RpcSessionState } from "./rpc/rpc-types.js";
39
+ export { InteractiveMode } from "./interactive/interactive-mode";
40
+ export { runPrintMode } from "./print-mode";
41
+ export { type ModelInfo, RpcClient, type RpcClientOptions, type RpcEventListener } from "./rpc/rpc-client";
42
+ export { runRpcMode } from "./rpc/rpc-mode";
43
+ export type { RpcCommand, RpcResponse, RpcSessionState } from "./rpc/rpc-types";
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import type { Component, TUI } from "@oh-my-pi/pi-tui";
6
- import { theme } from "../theme/theme.js";
6
+ import { theme } from "../theme/theme";
7
7
 
8
8
  // XBM image: 31x36 pixels, LSB first, 1=background, 0=foreground
9
9
  const WIDTH = 31;
@@ -1,6 +1,6 @@
1
1
  import type { AssistantMessage } from "@oh-my-pi/pi-ai";
2
2
  import { Container, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
3
- import { getMarkdownTheme, theme } from "../theme/theme.js";
3
+ import { getMarkdownTheme, theme } from "../theme/theme";
4
4
 
5
5
  /**
6
6
  * Component that renders a complete assistant message
@@ -9,10 +9,10 @@ import {
9
9
  DEFAULT_MAX_LINES,
10
10
  type TruncationResult,
11
11
  truncateTail,
12
- } from "../../../core/tools/truncate.js";
13
- import { theme } from "../theme/theme.js";
14
- import { DynamicBorder } from "./dynamic-border.js";
15
- import { truncateToVisualLines } from "./visual-truncate.js";
12
+ } from "../../../core/tools/truncate";
13
+ import { theme } from "../theme/theme";
14
+ import { DynamicBorder } from "./dynamic-border";
15
+ import { truncateToVisualLines } from "./visual-truncate";
16
16
 
17
17
  // Preview line limit when not expanded (matches tool execution behavior)
18
18
  const PREVIEW_LINES = 20;
@@ -1,6 +1,6 @@
1
1
  import { CancellableLoader, Container, Spacer, Text, type TUI } from "@oh-my-pi/pi-tui";
2
- import type { Theme } from "../theme/theme.js";
3
- import { DynamicBorder } from "./dynamic-border.js";
2
+ import type { Theme } from "../theme/theme";
3
+ import { DynamicBorder } from "./dynamic-border";
4
4
 
5
5
  /** Loader wrapped with borders for hook UI */
6
6
  export class BorderedLoader extends Container {
@@ -1,6 +1,6 @@
1
1
  import { Box, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
2
- import type { BranchSummaryMessage } from "../../../core/messages.js";
3
- import { getMarkdownTheme, theme } from "../theme/theme.js";
2
+ import type { BranchSummaryMessage } from "../../../core/messages";
3
+ import { getMarkdownTheme, theme } from "../theme/theme";
4
4
 
5
5
  /**
6
6
  * Component that renders a branch summary message with collapsed/expanded state.
@@ -1,6 +1,6 @@
1
1
  import { Box, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
2
- import type { CompactionSummaryMessage } from "../../../core/messages.js";
3
- import { getMarkdownTheme, theme } from "../theme/theme.js";
2
+ import type { CompactionSummaryMessage } from "../../../core/messages";
3
+ import { getMarkdownTheme, theme } from "../theme/theme";
4
4
 
5
5
  /**
6
6
  * Component that renders a compaction message with collapsed/expanded state.
@@ -1,5 +1,5 @@
1
1
  import * as Diff from "diff";
2
- import { theme } from "../theme/theme.js";
2
+ import { theme } from "../theme/theme";
3
3
 
4
4
  /**
5
5
  * Parse diff line to extract prefix, line number, and content.
@@ -1,5 +1,5 @@
1
1
  import type { Component } from "@oh-my-pi/pi-tui";
2
- import { theme } from "../theme/theme.js";
2
+ import { theme } from "../theme/theme";
3
3
 
4
4
  /**
5
5
  * Dynamic border component that adjusts to viewport width.
@@ -1,10 +1,10 @@
1
+ import { execSync } from "node:child_process";
2
+ import { existsSync, type FSWatcher, readFileSync, watch } from "node:fs";
3
+ import { dirname, join } from "node:path";
1
4
  import type { AssistantMessage } from "@oh-my-pi/pi-ai";
2
5
  import { type Component, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
3
- import { execSync } from "child_process";
4
- import { existsSync, type FSWatcher, readFileSync, watch } from "fs";
5
- import { dirname, join } from "path";
6
- import type { AgentSession } from "../../../core/agent-session.js";
7
- import { theme } from "../theme/theme.js";
6
+ import type { AgentSession } from "../../../core/agent-session";
7
+ import { theme } from "../theme/theme";
8
8
 
9
9
  // Nerd Font icons (matching Claude/statusline-nerd.sh)
10
10
  const ICONS = {
@@ -7,8 +7,8 @@ import * as fs from "node:fs";
7
7
  import * as os from "node:os";
8
8
  import * as path from "node:path";
9
9
  import { Container, Editor, isCtrlG, isEscape, Spacer, Text, type TUI } from "@oh-my-pi/pi-tui";
10
- import { getEditorTheme, theme } from "../theme/theme.js";
11
- import { DynamicBorder } from "./dynamic-border.js";
10
+ import { getEditorTheme, theme } from "../theme/theme";
11
+ import { DynamicBorder } from "./dynamic-border";
12
12
 
13
13
  export class HookEditorComponent extends Container {
14
14
  private editor: Editor;
@@ -3,8 +3,8 @@
3
3
  */
4
4
 
5
5
  import { Container, Input, isEnter, isEscape, Spacer, Text } from "@oh-my-pi/pi-tui";
6
- import { theme } from "../theme/theme.js";
7
- import { DynamicBorder } from "./dynamic-border.js";
6
+ import { theme } from "../theme/theme";
7
+ import { DynamicBorder } from "./dynamic-border";
8
8
 
9
9
  export class HookInputComponent extends Container {
10
10
  private input: Input;
@@ -1,9 +1,9 @@
1
1
  import type { TextContent } from "@oh-my-pi/pi-ai";
2
2
  import type { Component } from "@oh-my-pi/pi-tui";
3
3
  import { Box, Container, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
4
- import type { HookMessageRenderer } from "../../../core/hooks/types.js";
5
- import type { HookMessage } from "../../../core/messages.js";
6
- import { getMarkdownTheme, theme } from "../theme/theme.js";
4
+ import type { HookMessageRenderer } from "../../../core/hooks/types";
5
+ import type { HookMessage } from "../../../core/messages";
6
+ import { getMarkdownTheme, theme } from "../theme/theme";
7
7
 
8
8
  /**
9
9
  * Component that renders a custom message entry from hooks.
@@ -4,8 +4,8 @@
4
4
  */
5
5
 
6
6
  import { Container, isArrowDown, isArrowUp, isEnter, isEscape, Spacer, Text } from "@oh-my-pi/pi-tui";
7
- import { theme } from "../theme/theme.js";
8
- import { DynamicBorder } from "./dynamic-border.js";
7
+ import { theme } from "../theme/theme";
8
+ import { DynamicBorder } from "./dynamic-border";
9
9
 
10
10
  export class HookSelectorComponent extends Container {
11
11
  private options: string[];