@oh-my-pi/pi-coding-agent 14.0.5 → 14.1.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 (101) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/package.json +8 -8
  3. package/src/async/index.ts +1 -0
  4. package/src/async/job-manager.ts +43 -10
  5. package/src/async/support.ts +5 -0
  6. package/src/cli/list-models.ts +96 -57
  7. package/src/commit/agentic/tools/analyze-file.ts +1 -2
  8. package/src/commit/model-selection.ts +16 -13
  9. package/src/config/mcp-schema.json +1 -1
  10. package/src/config/model-equivalence.ts +675 -0
  11. package/src/config/model-registry.ts +242 -45
  12. package/src/config/model-resolver.ts +282 -65
  13. package/src/config/settings-schema.ts +27 -3
  14. package/src/config/settings.ts +1 -1
  15. package/src/cursor.ts +64 -23
  16. package/src/edit/index.ts +254 -89
  17. package/src/edit/modes/chunk.ts +336 -57
  18. package/src/edit/modes/hashline.ts +51 -26
  19. package/src/edit/modes/patch.ts +16 -10
  20. package/src/edit/modes/replace.ts +15 -7
  21. package/src/edit/renderer.ts +248 -94
  22. package/src/export/html/template.css +82 -0
  23. package/src/export/html/template.generated.ts +1 -1
  24. package/src/export/html/template.js +614 -97
  25. package/src/extensibility/custom-tools/types.ts +0 -3
  26. package/src/extensibility/extensions/loader.ts +16 -0
  27. package/src/extensibility/extensions/runner.ts +2 -7
  28. package/src/extensibility/extensions/types.ts +8 -4
  29. package/src/internal-urls/docs-index.generated.ts +4 -4
  30. package/src/internal-urls/jobs-protocol.ts +2 -1
  31. package/src/ipy/executor.ts +447 -52
  32. package/src/ipy/kernel.ts +39 -13
  33. package/src/lsp/client.ts +55 -1
  34. package/src/lsp/index.ts +8 -0
  35. package/src/lsp/types.ts +6 -0
  36. package/src/main.ts +6 -2
  37. package/src/memories/index.ts +7 -6
  38. package/src/modes/acp/acp-agent.ts +4 -1
  39. package/src/modes/components/bash-execution.ts +16 -4
  40. package/src/modes/components/model-selector.ts +221 -64
  41. package/src/modes/components/status-line/presets.ts +17 -6
  42. package/src/modes/components/status-line/segments.ts +15 -0
  43. package/src/modes/components/status-line-segment-editor.ts +1 -0
  44. package/src/modes/components/status-line.ts +7 -1
  45. package/src/modes/components/tool-execution.ts +145 -75
  46. package/src/modes/controllers/command-controller.ts +42 -1
  47. package/src/modes/controllers/event-controller.ts +4 -1
  48. package/src/modes/controllers/extension-ui-controller.ts +28 -5
  49. package/src/modes/controllers/input-controller.ts +9 -3
  50. package/src/modes/controllers/selector-controller.ts +17 -6
  51. package/src/modes/interactive-mode.ts +19 -3
  52. package/src/modes/print-mode.ts +13 -4
  53. package/src/modes/prompt-action-autocomplete.ts +3 -5
  54. package/src/modes/rpc/rpc-mode.ts +8 -2
  55. package/src/modes/shared.ts +2 -2
  56. package/src/modes/types.ts +1 -0
  57. package/src/modes/utils/ui-helpers.ts +1 -0
  58. package/src/prompts/system/system-prompt.md +5 -1
  59. package/src/prompts/tools/bash.md +16 -1
  60. package/src/prompts/tools/cancel-job.md +1 -1
  61. package/src/prompts/tools/chunk-edit.md +191 -163
  62. package/src/prompts/tools/hashline.md +11 -11
  63. package/src/prompts/tools/patch.md +10 -5
  64. package/src/prompts/tools/{await.md → poll.md} +1 -1
  65. package/src/prompts/tools/read-chunk.md +12 -3
  66. package/src/prompts/tools/read.md +9 -0
  67. package/src/prompts/tools/task.md +2 -2
  68. package/src/prompts/tools/vim.md +98 -0
  69. package/src/prompts/tools/write.md +1 -0
  70. package/src/sdk.ts +758 -725
  71. package/src/session/agent-session.ts +187 -40
  72. package/src/session/session-manager.ts +50 -4
  73. package/src/slash-commands/builtin-registry.ts +17 -0
  74. package/src/task/executor.ts +9 -5
  75. package/src/task/index.ts +3 -5
  76. package/src/task/types.ts +2 -2
  77. package/src/tools/bash.ts +240 -57
  78. package/src/tools/cancel-job.ts +2 -1
  79. package/src/tools/find.ts +5 -2
  80. package/src/tools/grep.ts +77 -8
  81. package/src/tools/index.ts +48 -19
  82. package/src/tools/inspect-image.ts +1 -1
  83. package/src/tools/{await-tool.ts → poll-tool.ts} +38 -31
  84. package/src/tools/python.ts +293 -278
  85. package/src/tools/read.ts +218 -1
  86. package/src/tools/sqlite-reader.ts +623 -0
  87. package/src/tools/submit-result.ts +5 -2
  88. package/src/tools/todo-write.ts +8 -2
  89. package/src/tools/vim.ts +966 -0
  90. package/src/tools/write.ts +187 -1
  91. package/src/utils/commit-message-generator.ts +1 -0
  92. package/src/utils/edit-mode.ts +2 -1
  93. package/src/utils/git.ts +24 -1
  94. package/src/utils/session-color.ts +55 -0
  95. package/src/utils/title-generator.ts +16 -7
  96. package/src/vim/buffer.ts +309 -0
  97. package/src/vim/commands.ts +382 -0
  98. package/src/vim/engine.ts +2426 -0
  99. package/src/vim/parser.ts +151 -0
  100. package/src/vim/render.ts +252 -0
  101. package/src/vim/types.ts +197 -0
@@ -6,6 +6,7 @@
6
6
  * - `omp --mode json "prompt"` - JSON event stream
7
7
  */
8
8
  import type { AssistantMessage, ImageContent } from "@oh-my-pi/pi-ai";
9
+ import { sanitizeText } from "@oh-my-pi/pi-natives";
9
10
  import type { AgentSession } from "../session/agent-session";
10
11
 
11
12
  /**
@@ -72,11 +73,14 @@ export async function runPrintMode(session: AgentSession, options: PrintModeOpti
72
73
  },
73
74
  getThinkingLevel: () => session.thinkingLevel,
74
75
  setThinkingLevel: level => session.setThinkingLevel(level),
76
+ getSessionName: () => session.sessionManager.getSessionName(),
77
+ setSessionName: async name => {
78
+ await session.sessionManager.setSessionName(name, "user");
79
+ },
75
80
  },
76
81
  // ExtensionContextActions
77
82
  {
78
83
  getModel: () => session.model,
79
- getSearchDb: () => session.searchDb,
80
84
  isIdle: () => !session.isStreaming,
81
85
  abort: () => session.abort(),
82
86
  hasPendingMessages: () => session.queuedMessageCount > 0,
@@ -166,14 +170,19 @@ export async function runPrintMode(session: AgentSession, options: PrintModeOpti
166
170
 
167
171
  // Check for error/aborted
168
172
  if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") {
169
- process.stderr.write(`${assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`}\n`);
170
- process.exit(1);
173
+ const errorLine = sanitizeText(assistantMsg.errorMessage || `Request ${assistantMsg.stopReason}`);
174
+ const flushed = process.stderr.write(`${errorLine}\n`);
175
+ if (flushed) {
176
+ process.exit(1);
177
+ } else {
178
+ process.stderr.once("drain", () => process.exit(1));
179
+ }
171
180
  }
172
181
 
173
182
  // Output text content
174
183
  for (const content of assistantMsg.content) {
175
184
  if (content.type === "text") {
176
- process.stdout.write(`${content.text}\n`);
185
+ process.stdout.write(`${sanitizeText(content.text)}\n`);
177
186
  }
178
187
  }
179
188
  }
@@ -1,4 +1,3 @@
1
- import type { SearchDb } from "@oh-my-pi/pi-natives";
2
1
  import {
3
2
  type AutocompleteItem,
4
3
  type AutocompleteProvider,
@@ -24,7 +23,6 @@ interface PromptActionAutocompleteItem extends AutocompleteItem {
24
23
  interface PromptActionAutocompleteOptions {
25
24
  commands: SlashCommand[];
26
25
  basePath: string;
27
- searchDb?: SearchDb;
28
26
  keybindings: KeybindingsManager;
29
27
  copyCurrentLine: () => void;
30
28
  copyPrompt: () => void;
@@ -92,8 +90,8 @@ export class PromptActionAutocompleteProvider implements AutocompleteProvider {
92
90
  #baseProvider: CombinedAutocompleteProvider;
93
91
  #actions: PromptActionDefinition[];
94
92
 
95
- constructor(commands: SlashCommand[], basePath: string, actions: PromptActionDefinition[], searchDb?: SearchDb) {
96
- this.#baseProvider = new CombinedAutocompleteProvider(commands, basePath, searchDb);
93
+ constructor(commands: SlashCommand[], basePath: string, actions: PromptActionDefinition[]) {
94
+ this.#baseProvider = new CombinedAutocompleteProvider(commands, basePath);
97
95
  this.#actions = actions;
98
96
  }
99
97
 
@@ -229,5 +227,5 @@ export function createPromptActionAutocompleteProvider(
229
227
  },
230
228
  ];
231
229
 
232
- return new PromptActionAutocompleteProvider(options.commands, options.basePath, actions, options.searchDb);
230
+ return new PromptActionAutocompleteProvider(options.commands, options.basePath, actions);
233
231
  }
@@ -440,11 +440,14 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
440
440
  },
441
441
  getThinkingLevel: () => session.thinkingLevel,
442
442
  setThinkingLevel: level => session.setThinkingLevel(level),
443
+ getSessionName: () => session.sessionManager.getSessionName(),
444
+ setSessionName: async name => {
445
+ await session.sessionManager.setSessionName(name, "user");
446
+ },
443
447
  },
444
448
  // ExtensionContextActions
445
449
  {
446
450
  getModel: () => session.agent.state.model,
447
- getSearchDb: () => session.searchDb,
448
451
  isIdle: () => !session.isStreaming,
449
452
  abort: () => session.abort(),
450
453
  hasPendingMessages: () => session.queuedMessageCount > 0,
@@ -751,7 +754,10 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
751
754
  if (!name) {
752
755
  return error(id, "set_session_name", "Session name cannot be empty");
753
756
  }
754
- session.setSessionName(name);
757
+ const applied = await session.setSessionName(name, "user");
758
+ if (!applied) {
759
+ return error(id, "set_session_name", "Session name cannot be empty");
760
+ }
755
761
  return success(id, "set_session_name");
756
762
  }
757
763
 
@@ -5,10 +5,10 @@ import { theme } from "./theme/theme";
5
5
  // Text Sanitization
6
6
  // ═══════════════════════════════════════════════════════════════════════════
7
7
 
8
- /** Sanitize text for display in a single-line status. Replaces newlines/tabs with space, collapses runs, trims. */
8
+ /** Sanitize text for display in a single-line status. Strips C0/C1 control characters (including ANSI ESC), collapses whitespace, trims. */
9
9
  export function sanitizeStatusText(text: string): string {
10
10
  return text
11
- .replace(/[\r\n\t]/g, " ")
11
+ .replace(/[\u0000-\u001f\u007f-\u009f]/g, " ")
12
12
  .replace(/ +/g, " ")
13
13
  .trim();
14
14
  }
@@ -187,6 +187,7 @@ export interface InteractiveModeContext {
187
187
  handleCompactCommand(customInstructions?: string): Promise<void>;
188
188
  handleHandoffCommand(customInstructions?: string): Promise<void>;
189
189
  handleMoveCommand(targetPath: string): Promise<void>;
190
+ handleRenameCommand(title: string): Promise<void>;
190
191
  handleMemoryCommand(text: string): Promise<void>;
191
192
  handleSTTToggle(): Promise<void>;
192
193
  executeCompaction(customInstructionsOrOptions?: string | CompactOptions, isAuto?: boolean): Promise<void>;
@@ -297,6 +297,7 @@ export class UiHelpers {
297
297
  tool,
298
298
  this.ctx.ui,
299
299
  this.ctx.sessionManager.getCwd(),
300
+ content.id,
300
301
  );
301
302
  component.setExpanded(this.ctx.toolOutputExpanded);
302
303
  this.ctx.chatContainer.addChild(component);
@@ -54,6 +54,7 @@ Push back when warranted: state the downside, propose an alternative, but **MUST
54
54
  - (1) Correctness first, (2) Brevity second, (3) Politeness third.
55
55
  - Prefer concise, information-dense writing.
56
56
  - Avoid repeating the user's request or narrating routine tool calls.
57
+ - Do not give time estimates or predictions for how long tasks will take. Focus on what needs to be done, not how long it might take.
57
58
  </communication>
58
59
 
59
60
  <instruction-priority>
@@ -101,6 +102,8 @@ You generate code inside-out: starting at the function body, working outward. Th
101
102
  - **DRY at 2.** When you write the same pattern a second time, stop and extract a shared helper. Two copies is a maintenance fork. Three copies is a bug.
102
103
  - Write maintainable code. Add brief comments when they clarify non-obvious intent, invariants, edge cases, or tradeoffs. Prefer explaining why over restating what the code already does.
103
104
  - **Earn every line.** A 12-line switch for a 3-way mapping is a lookup table. A one-liner wrapper that exists only for test access is a design smell.
105
+ - **No speculative complexity.** Do not create helpers, utilities, or abstractions for one-time operations. Do not design for hypothetical future requirements. Three similar lines of code is better than a premature abstraction. The right amount of complexity is what the task actually requires.
106
+ - **Trust internal code.** Do not add error handling, fallbacks, or validation for scenarios that cannot happen. Only validate at system boundaries — user input, external APIs, network responses. Do not use feature flags or backwards-compatibility shims when you can just change the code.
104
107
  </code-integrity>
105
108
 
106
109
  <stakes>
@@ -338,7 +341,8 @@ You are not making code that works. You are making code that communicates — to
338
341
  **One job, one level of abstraction.** If you need "and" to describe what something does, it should be two things. Code that mixes levels — orchestrating a flow while also handling parsing, formatting, or low-level manipulation — has no coherent owner and no coherent test. Each piece operates at one level and delegates everything else.
339
342
  **Fix where the invariant is violated, not where the violation is observed.** If a function returns the wrong thing, fix the function — not the caller's workaround. If a type is wrong, fix the type — not the cast. The right fix location is always where the contract is broken.
340
343
  **New code makes old code obsolete. Remove it.** When you introduce an abstraction, find what it replaces: old helpers, compatibility branches, stale tests, documentation describing removed behavior. Remove them in the same change.
341
- **No forwarding addresses.** Deleted or moved code leaves no trace — no `// moved to X` comments, no re-exports from the old location, no aliases kept "for now."
344
+ **No forwarding addresses.** Deleted or moved code leaves no trace — no `// moved to X` comments, no re-exports from the old location, no aliases kept "for now," no renaming unused parameters to `_var`, no `// removed` tombstones. If something is unused, delete it completely.
345
+ **Prefer editing over creating.** Do not create new files unless they are necessary to achieve the goal. Editing an existing file prevents file bloat and builds on existing work. A new file must earn its existence.
342
346
  **After writing, inhabit the call site.** Read your own code as someone who has never seen the implementation. Does the interface honestly reflect what happened? Is any accepted input silently discarded? Does any pattern exist in more than one place? Fix it.
343
347
  When a tool call fails, read the full error before doing anything else. When a file changed since you last read it, re-read before editing.
344
348
  {{#has tools "ask"}}- You **MUST** ask before destructive commands like `git checkout/restore/reset`, overwriting changes, or deleting code you didn't write.{{else}}- You **MUST NOT** run destructive git commands, overwrite changes, or delete code you didn't write.{{/has}}
@@ -12,8 +12,23 @@ Executes bash command in shell session for terminal operations like git, bun, ca
12
12
  - Internal URLs are also auto-resolved to filesystem paths before execution.
13
13
  {{#if asyncEnabled}}
14
14
  - Use `async: true` for long-running commands when you don't need immediate output; the call returns a background job ID and the result is delivered automatically as a follow-up.
15
+ {{/if}}
16
+ {{#if autoBackgroundEnabled}}
17
+ - Long-running non-PTY bash commands may auto-background after about {{autoBackgroundThresholdSeconds}}s and continue as background jobs automatically.
18
+ {{/if}}
19
+ {{#if asyncEnabled}}
20
+ {{else}}
21
+ {{#if autoBackgroundEnabled}}
22
+ - Auto-backgrounded jobs use the same background-job pipeline as explicit async execution.
23
+ {{/if}}
24
+ {{/if}}
25
+ {{#if asyncEnabled}}
15
26
  - Use `read jobs://` to inspect all background jobs and `read jobs://<job-id>` for detailed status/output when needed.
16
- - When you need to wait for async results before continuing, call `await` — it blocks until jobs complete. Do NOT poll `read jobs://` in a loop or yield and hope for delivery.
27
+ - When you need to wait for async results before continuing, call `poll` — it blocks until jobs complete. Do NOT poll `read jobs://` in a loop or yield and hope for delivery.
28
+ {{else}}
29
+ {{#if autoBackgroundEnabled}}
30
+ - If a command auto-backgrounds, use `read jobs://` to inspect jobs and `poll` when you need to wait for completion instead of polling in a loop.
31
+ {{/if}}
17
32
  {{/if}}
18
33
  </instruction>
19
34
 
@@ -1,4 +1,4 @@
1
- Cancels a running background job started via async tool execution.
1
+ Cancels a running background job started via async tool execution or bash auto-backgrounding.
2
2
 
3
3
  You **SHOULD** use this when a background `bash` or `task` job is no longer needed or is stuck.
4
4