@oh-my-pi/pi-coding-agent 14.3.0 → 14.4.1

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 (120) hide show
  1. package/CHANGELOG.md +98 -1
  2. package/package.json +7 -7
  3. package/src/autoresearch/prompt.md +1 -1
  4. package/src/commit/agentic/prompts/analyze-file.md +1 -1
  5. package/src/config/model-registry.ts +67 -15
  6. package/src/config/prompt-templates.ts +5 -5
  7. package/src/config/settings-schema.ts +4 -4
  8. package/src/cursor.ts +3 -8
  9. package/src/discovery/helpers.ts +3 -3
  10. package/src/edit/diff.ts +50 -47
  11. package/src/edit/index.ts +86 -57
  12. package/src/edit/line-hash.ts +743 -24
  13. package/src/edit/modes/apply-patch.ts +0 -9
  14. package/src/edit/modes/atom.ts +893 -0
  15. package/src/edit/modes/chunk.ts +14 -24
  16. package/src/edit/modes/hashline.ts +193 -146
  17. package/src/edit/modes/patch.ts +5 -9
  18. package/src/edit/modes/replace.ts +6 -11
  19. package/src/edit/renderer.ts +14 -10
  20. package/src/edit/streaming.ts +50 -16
  21. package/src/exec/bash-executor.ts +2 -4
  22. package/src/export/html/template.generated.ts +1 -1
  23. package/src/export/html/template.js +4 -12
  24. package/src/extensibility/custom-tools/types.ts +2 -0
  25. package/src/extensibility/custom-tools/wrapper.ts +2 -1
  26. package/src/internal-urls/docs-index.generated.ts +2 -2
  27. package/src/lsp/defaults.json +142 -652
  28. package/src/lsp/index.ts +1 -1
  29. package/src/mcp/render.ts +1 -8
  30. package/src/modes/components/assistant-message.ts +4 -0
  31. package/src/modes/components/diff.ts +23 -14
  32. package/src/modes/components/footer.ts +21 -16
  33. package/src/modes/components/session-selector.ts +3 -3
  34. package/src/modes/components/settings-defs.ts +6 -1
  35. package/src/modes/components/todo-reminder.ts +1 -8
  36. package/src/modes/components/tool-execution.ts +1 -4
  37. package/src/modes/controllers/selector-controller.ts +1 -1
  38. package/src/modes/print-mode.ts +8 -0
  39. package/src/prompts/agents/librarian.md +1 -1
  40. package/src/prompts/agents/reviewer.md +4 -4
  41. package/src/prompts/ci-green-request.md +1 -1
  42. package/src/prompts/review-request.md +1 -1
  43. package/src/prompts/system/subagent-system-prompt.md +3 -3
  44. package/src/prompts/system/subagent-yield-reminder.md +11 -0
  45. package/src/prompts/system/system-prompt.md +3 -0
  46. package/src/prompts/tools/ask.md +3 -2
  47. package/src/prompts/tools/ast-edit.md +16 -20
  48. package/src/prompts/tools/ast-grep.md +19 -24
  49. package/src/prompts/tools/atom.md +87 -0
  50. package/src/prompts/tools/chunk-edit.md +37 -161
  51. package/src/prompts/tools/debug.md +4 -5
  52. package/src/prompts/tools/exit-plan-mode.md +4 -5
  53. package/src/prompts/tools/find.md +4 -8
  54. package/src/prompts/tools/github.md +18 -0
  55. package/src/prompts/tools/grep.md +4 -5
  56. package/src/prompts/tools/hashline.md +22 -89
  57. package/src/prompts/tools/{gemini-image.md → image-gen.md} +1 -1
  58. package/src/prompts/tools/inspect-image.md +6 -6
  59. package/src/prompts/tools/lsp.md +1 -1
  60. package/src/prompts/tools/patch.md +12 -19
  61. package/src/prompts/tools/python.md +3 -2
  62. package/src/prompts/tools/read-chunk.md +2 -3
  63. package/src/prompts/tools/read.md +2 -2
  64. package/src/prompts/tools/ssh.md +8 -17
  65. package/src/prompts/tools/todo-write.md +54 -41
  66. package/src/sdk.ts +14 -9
  67. package/src/session/agent-session.ts +25 -2
  68. package/src/session/session-manager.ts +4 -1
  69. package/src/task/executor.ts +43 -48
  70. package/src/task/render.ts +11 -13
  71. package/src/tools/ask.ts +7 -7
  72. package/src/tools/ast-edit.ts +45 -41
  73. package/src/tools/ast-grep.ts +77 -85
  74. package/src/tools/bash.ts +8 -9
  75. package/src/tools/browser.ts +32 -30
  76. package/src/tools/calculator.ts +4 -4
  77. package/src/tools/cancel-job.ts +1 -1
  78. package/src/tools/checkpoint.ts +2 -2
  79. package/src/tools/debug.ts +41 -37
  80. package/src/tools/exit-plan-mode.ts +1 -1
  81. package/src/tools/find.ts +4 -4
  82. package/src/tools/gh-renderer.ts +12 -4
  83. package/src/tools/gh.ts +509 -697
  84. package/src/tools/grep.ts +116 -131
  85. package/src/tools/{gemini-image.ts → image-gen.ts} +459 -60
  86. package/src/tools/index.ts +14 -32
  87. package/src/tools/inspect-image.ts +3 -3
  88. package/src/tools/json-tree.ts +114 -114
  89. package/src/tools/match-line-format.ts +8 -7
  90. package/src/tools/notebook.ts +8 -7
  91. package/src/tools/poll-tool.ts +2 -1
  92. package/src/tools/python.ts +9 -23
  93. package/src/tools/read.ts +32 -25
  94. package/src/tools/render-mermaid.ts +1 -1
  95. package/src/tools/render-utils.ts +18 -0
  96. package/src/tools/renderers.ts +2 -2
  97. package/src/tools/report-tool-issue.ts +3 -2
  98. package/src/tools/resolve.ts +1 -1
  99. package/src/tools/review.ts +12 -10
  100. package/src/tools/search-tool-bm25.ts +2 -4
  101. package/src/tools/ssh.ts +4 -4
  102. package/src/tools/todo-write.ts +172 -147
  103. package/src/tools/vim.ts +14 -15
  104. package/src/tools/write.ts +4 -4
  105. package/src/tools/{submit-result.ts → yield.ts} +11 -13
  106. package/src/utils/edit-mode.ts +2 -1
  107. package/src/utils/file-display-mode.ts +10 -5
  108. package/src/utils/git.ts +9 -5
  109. package/src/utils/shell-snapshot.ts +2 -3
  110. package/src/vim/render.ts +4 -4
  111. package/src/prompts/system/subagent-submit-reminder.md +0 -11
  112. package/src/prompts/tools/gh-issue-view.md +0 -11
  113. package/src/prompts/tools/gh-pr-checkout.md +0 -12
  114. package/src/prompts/tools/gh-pr-diff.md +0 -12
  115. package/src/prompts/tools/gh-pr-push.md +0 -12
  116. package/src/prompts/tools/gh-pr-view.md +0 -11
  117. package/src/prompts/tools/gh-repo-view.md +0 -11
  118. package/src/prompts/tools/gh-run-watch.md +0 -12
  119. package/src/prompts/tools/gh-search-issues.md +0 -11
  120. package/src/prompts/tools/gh-search-prs.md +0 -11
@@ -22,16 +22,21 @@ export interface FileDisplayModeSession {
22
22
  /**
23
23
  * Computes effective line display mode from session settings/env.
24
24
  * Hashline mode takes precedence and implies line-addressed output everywhere.
25
- * Hashlines are suppressed when the edit tool is not available (e.g. explore agents).
25
+ * Hashlines are suppressed when the edit tool is not available (e.g. explore agents)
26
+ * and when the caller signals a `raw` read — raw output should be returned as-is
27
+ * without injecting hashline anchors or line numbers.
26
28
  */
27
- export function resolveFileDisplayMode(session: FileDisplayModeSession): FileDisplayMode {
29
+ export function resolveFileDisplayMode(session: FileDisplayModeSession, options?: { raw?: boolean }): FileDisplayMode {
28
30
  const { settings } = session;
29
31
  const hasEditTool = session.hasEditTool ?? true;
30
- const hashLines = hasEditTool && resolveEditMode(session) === "hashline" && settings.get("readHashLines") !== false;
31
- const chunked = hasEditTool && resolveEditMode(session) === "chunk";
32
+ const editMode = resolveEditMode(session);
33
+ const usesHashLineAnchors = editMode === "hashline" || editMode === "atom";
34
+ const raw = options?.raw === true;
35
+ const hashLines = !raw && hasEditTool && usesHashLineAnchors && settings.get("readHashLines") !== false;
36
+ const chunked = !raw && hasEditTool && editMode === "chunk";
32
37
  return {
33
38
  hashLines,
34
- lineNumbers: hashLines || settings.get("readLineNumbers") === true,
39
+ lineNumbers: !raw && (hashLines || settings.get("readLineNumbers") === true),
35
40
  chunked,
36
41
  };
37
42
  }
package/src/utils/git.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
- import { $which, isEnoent, Snowflake } from "@oh-my-pi/pi-utils";
4
+ import { $which, hasFsCode, isEnoent, Snowflake } from "@oh-my-pi/pi-utils";
5
5
  import {
6
6
  parseDiffHunks as parseCommitDiffHunks,
7
7
  parseFileDiffs,
@@ -322,6 +322,10 @@ async function writeTempPatch(content: string): Promise<string> {
322
322
 
323
323
  type EntryType = "directory" | "file";
324
324
 
325
+ function isOptionalGitMetadataUnavailable(err: unknown): boolean {
326
+ return isEnoent(err) || hasFsCode(err, "ENFILE") || hasFsCode(err, "EMFILE");
327
+ }
328
+
325
329
  function getEntryTypeSync(gitEntryPath: string): EntryType | null {
326
330
  try {
327
331
  const stat = fs.statSync(gitEntryPath);
@@ -329,7 +333,7 @@ function getEntryTypeSync(gitEntryPath: string): EntryType | null {
329
333
  if (stat.isFile()) return "file";
330
334
  return null;
331
335
  } catch (err) {
332
- if (isEnoent(err)) return null;
336
+ if (isOptionalGitMetadataUnavailable(err)) return null;
333
337
  throw err;
334
338
  }
335
339
  }
@@ -341,7 +345,7 @@ async function getEntryType(gitEntryPath: string): Promise<EntryType | null> {
341
345
  if (stat.isFile()) return "file";
342
346
  return null;
343
347
  } catch (err) {
344
- if (isEnoent(err)) return null;
348
+ if (isOptionalGitMetadataUnavailable(err)) return null;
345
349
  throw err;
346
350
  }
347
351
  }
@@ -350,7 +354,7 @@ function readOptionalTextSync(filePath: string): string | null {
350
354
  try {
351
355
  return fs.readFileSync(filePath, "utf8");
352
356
  } catch (err) {
353
- if (isEnoent(err)) return null;
357
+ if (isOptionalGitMetadataUnavailable(err)) return null;
354
358
  throw err;
355
359
  }
356
360
  }
@@ -359,7 +363,7 @@ async function readOptionalText(filePath: string): Promise<string | null> {
359
363
  try {
360
364
  return await Bun.file(filePath).text();
361
365
  } catch (err) {
362
- if (isEnoent(err)) return null;
366
+ if (isOptionalGitMetadataUnavailable(err)) return null;
363
367
  throw err;
364
368
  }
365
369
  }
@@ -59,10 +59,9 @@ done
59
59
  echo "# Functions" >> "$SNAPSHOT_FILE"
60
60
  # Force autoload all functions first
61
61
  declare -f > /dev/null 2>&1
62
- # Get user function names - filter system/private ones, use base64 for special chars
62
+ # Get user function names - filter system/private ones
63
63
  declare -F 2>/dev/null | cut -d' ' -f3 | grep -vE '^(_|__)' | grep -vE '${commonToolsRegex}' | while read func; do
64
- encoded_func=$(declare -f "$func" | base64)
65
- echo "eval \\"\\$(echo '$encoded_func' | base64 -d)\\" > /dev/null 2>&1" >> "$SNAPSHOT_FILE"
64
+ declare -f "$func" >> "$SNAPSHOT_FILE" 2>/dev/null
66
65
  done
67
66
  `;
68
67
 
package/src/vim/render.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { extractSegments } from "@oh-my-pi/pi-tui";
2
- import { truncateToWidth } from "../tools/render-utils";
2
+ import { formatCodeFrameLine, truncateToWidth } from "../tools/render-utils";
3
3
  import type {
4
4
  VimErrorLocation,
5
5
  VimFocusLine,
@@ -207,7 +207,7 @@ export function renderVimDetails(details: VimToolDetails): string {
207
207
  }
208
208
 
209
209
  if (details.focus) {
210
- const focusPrefix = `>${String(details.focus.line).padStart(String(details.viewport.end).length, " ")}│`;
210
+ const focusPrefix = formatCodeFrameLine(">", details.focus.line, "", String(details.viewport.end).length);
211
211
  const caretPrefix = `${" ".repeat(focusPrefix.length)} `;
212
212
  const caretPadding = " ".repeat(Math.max(0, details.focus.caretCol));
213
213
  lines.push("Focus:");
@@ -219,8 +219,8 @@ export function renderVimDetails(details: VimToolDetails): string {
219
219
  const padWidth = String(details.viewport.end).length;
220
220
  lines.push("Viewport:");
221
221
  for (const line of details.viewportLines) {
222
- const prefix = line.isCursor ? ">" : line.isSelected ? "*" : " ";
223
- lines.push(`${prefix}${String(line.line).padStart(padWidth, " ")}│${renderPlainViewportCursor(line)}`);
222
+ const marker = line.isCursor ? ">" : line.isSelected ? "*" : " ";
223
+ lines.push(formatCodeFrameLine(marker, line.line, renderPlainViewportCursor(line), padWidth));
224
224
  }
225
225
  }
226
226
 
@@ -1,11 +0,0 @@
1
- <system-reminder>
2
- You stopped without calling submit_result. This is reminder {{retryCount}} of {{maxRetries}}.
3
-
4
- You **MUST** call submit_result as your only action now. Choose one:
5
- - If task is complete: call submit_result with your result in `result.data`
6
- - If task failed: call submit_result with `result.error` describing what happened
7
-
8
- You **MUST NOT** give up if you can still complete the task through exploration (using available tools or repo context). If you submit an error, you **MUST** include what you tried and the exact blocker.
9
-
10
- You **MUST NOT** output text without a tool call. You **MUST** call submit_result to finish.
11
- </system-reminder>
@@ -1,11 +0,0 @@
1
- Reads a GitHub issue through the local GitHub CLI.
2
-
3
- <instruction>
4
- - Accepts an issue number or full GitHub issue URL
5
- - Use `repo` when you have a number but no active GitHub repository context
6
- - Keep `comments` enabled when discussion context matters; disable it for a lighter summary
7
- </instruction>
8
-
9
- <output>
10
- Returns issue metadata, body text, and optionally visible comments in a readable format.
11
- </output>
@@ -1,12 +0,0 @@
1
- Checks out a GitHub pull request into a dedicated git worktree through the local GitHub CLI.
2
-
3
- <instruction>
4
- - Accepts a pull request number, URL, or branch name
5
- - Omitting `pr` targets the pull request associated with the current branch
6
- - Creates or reuses a local `pr-<number>` branch by default, fetches the contributor head branch, and creates a dedicated worktree for it
7
- - Configures the local branch to push back to the pull request head branch instead of accidentally publishing to the base repository
8
- </instruction>
9
-
10
- <output>
11
- Returns the worktree path, local branch name, remote name, and remote branch configured for future pushes.
12
- </output>
@@ -1,12 +0,0 @@
1
- Reads a GitHub pull request diff through the local GitHub CLI.
2
-
3
- <instruction>
4
- - Accepts a pull request number, URL, or branch name
5
- - Omitting `pr` targets the pull request associated with the current branch
6
- - Use `nameOnly: true` when you only need changed file names
7
- - Use `exclude` to drop generated or irrelevant paths from the diff
8
- </instruction>
9
-
10
- <output>
11
- Returns a unified diff or changed-file list for the selected pull request.
12
- </output>
@@ -1,12 +0,0 @@
1
- Pushes a checked-out pull request branch back to its source branch through local git.
2
-
3
- <instruction>
4
- - Defaults to the current checked-out git branch
5
- - Requires branch metadata recorded by `gh_pr_checkout`; fail instead of pushing if the branch was not checked out with `gh_pr_checkout`
6
- - Pushes back to the contributor fork and PR head branch recorded in that metadata
7
- - Use `forceWithLease` only when rewriting the branch intentionally
8
- </instruction>
9
-
10
- <output>
11
- Returns the local branch, remote, remote branch, and push target that were used.
12
- </output>
@@ -1,11 +0,0 @@
1
- Reads a GitHub pull request through the local GitHub CLI.
2
-
3
- <instruction>
4
- - Accepts a pull request number, URL, or branch name
5
- - Omitting `pr` targets the pull request associated with the current branch
6
- - Use this for PR metadata, body, changed-file summaries, review discussion, inline review comments, and issue-comment context
7
- </instruction>
8
-
9
- <output>
10
- Returns pull request metadata, body text, changed files, and optionally visible reviews, inline review comments, and issue comments in a readable format.
11
- </output>
@@ -1,11 +0,0 @@
1
- Reads GitHub repository metadata using the local GitHub CLI.
2
-
3
- <instruction>
4
- - Prefer this when you need authenticated repository context or GitHub CLI default-repo resolution
5
- - Use `repo` to target an explicit `OWNER/REPO`; otherwise the current checkout or `gh` default repo is used
6
- - This tool is read-only and returns repository metadata, not raw file contents
7
- </instruction>
8
-
9
- <output>
10
- Returns a concise repository summary including description, branch, visibility, stars, forks, and related metadata.
11
- </output>
@@ -1,12 +0,0 @@
1
- Watches a GitHub Actions workflow run through the local GitHub CLI.
2
-
3
- <instruction>
4
- - Accepts a run ID or full Actions run URL
5
- - Omitting `run` watches the workflow runs for the current HEAD commit in the current GitHub repository context
6
- - Omitting `branch` falls back to the current checked-out git branch
7
- - Fast-fails after the first detected job failure, waits briefly to collect concurrent failures, and then fetches tailed logs for the failed jobs
8
- </instruction>
9
-
10
- <output>
11
- Streams live run snapshots while polling, then returns the final run status, job list, and tailed logs for failed jobs when available. When failed-job logs are fetched, the full failed-job logs are also saved as a session artifact for on-demand reads. When `run` is omitted, the snapshots cover all workflow runs created for the current HEAD commit.
12
- </output>
@@ -1,11 +0,0 @@
1
- Searches GitHub issues through the local GitHub CLI.
2
-
3
- <instruction>
4
- - `query` supports normal GitHub issue search syntax
5
- - Use `repo` to scope results to a single repository when relevant
6
- - Prefer small limits and refine the query instead of pulling large result sets
7
- </instruction>
8
-
9
- <output>
10
- Returns a concise list of matching issues with repository, state, labels, timestamps, and URLs.
11
- </output>
@@ -1,11 +0,0 @@
1
- Searches GitHub pull requests through the local GitHub CLI.
2
-
3
- <instruction>
4
- - `query` supports normal GitHub pull request search syntax
5
- - Use `repo` to scope results to a single repository when relevant
6
- - Prefer small limits and refine the query instead of pulling large result sets
7
- </instruction>
8
-
9
- <output>
10
- Returns a concise list of matching pull requests with repository, state, labels, timestamps, and URLs.
11
- </output>