@oh-my-pi/pi-coding-agent 8.0.20 → 8.1.0

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 (166) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/package.json +14 -11
  3. package/scripts/generate-wasm-b64.ts +24 -0
  4. package/src/capability/context-file.ts +1 -1
  5. package/src/capability/extension-module.ts +1 -1
  6. package/src/capability/extension.ts +1 -1
  7. package/src/capability/hook.ts +1 -1
  8. package/src/capability/instruction.ts +1 -1
  9. package/src/capability/mcp.ts +1 -1
  10. package/src/capability/prompt.ts +1 -1
  11. package/src/capability/rule.ts +1 -1
  12. package/src/capability/settings.ts +1 -1
  13. package/src/capability/skill.ts +1 -1
  14. package/src/capability/slash-command.ts +1 -1
  15. package/src/capability/ssh.ts +1 -1
  16. package/src/capability/system-prompt.ts +1 -1
  17. package/src/capability/tool.ts +1 -1
  18. package/src/cli/args.ts +1 -1
  19. package/src/cli/plugin-cli.ts +1 -5
  20. package/src/commit/agentic/agent.ts +309 -0
  21. package/src/commit/agentic/fallback.ts +96 -0
  22. package/src/commit/agentic/index.ts +359 -0
  23. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  24. package/src/commit/agentic/prompts/session-user.md +26 -0
  25. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  26. package/src/commit/agentic/prompts/system.md +40 -0
  27. package/src/commit/agentic/state.ts +74 -0
  28. package/src/commit/agentic/tools/analyze-file.ts +131 -0
  29. package/src/commit/agentic/tools/git-file-diff.ts +194 -0
  30. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  31. package/src/commit/agentic/tools/git-overview.ts +84 -0
  32. package/src/commit/agentic/tools/index.ts +56 -0
  33. package/src/commit/agentic/tools/propose-changelog.ts +128 -0
  34. package/src/commit/agentic/tools/propose-commit.ts +154 -0
  35. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  36. package/src/commit/agentic/tools/split-commit.ts +284 -0
  37. package/src/commit/agentic/topo-sort.ts +44 -0
  38. package/src/commit/agentic/trivial.ts +51 -0
  39. package/src/commit/agentic/validation.ts +200 -0
  40. package/src/commit/analysis/conventional.ts +169 -0
  41. package/src/commit/analysis/index.ts +4 -0
  42. package/src/commit/analysis/scope.ts +242 -0
  43. package/src/commit/analysis/summary.ts +114 -0
  44. package/src/commit/analysis/validation.ts +66 -0
  45. package/src/commit/changelog/detect.ts +36 -0
  46. package/src/commit/changelog/generate.ts +112 -0
  47. package/src/commit/changelog/index.ts +233 -0
  48. package/src/commit/changelog/parse.ts +44 -0
  49. package/src/commit/cli.ts +93 -0
  50. package/src/commit/git/diff.ts +148 -0
  51. package/src/commit/git/errors.ts +11 -0
  52. package/src/commit/git/index.ts +217 -0
  53. package/src/commit/git/operations.ts +53 -0
  54. package/src/commit/index.ts +5 -0
  55. package/src/commit/map-reduce/.map-phase.ts.kate-swp +0 -0
  56. package/src/commit/map-reduce/index.ts +63 -0
  57. package/src/commit/map-reduce/map-phase.ts +193 -0
  58. package/src/commit/map-reduce/reduce-phase.ts +147 -0
  59. package/src/commit/map-reduce/utils.ts +9 -0
  60. package/src/commit/message.ts +11 -0
  61. package/src/commit/model-selection.ts +84 -0
  62. package/src/commit/pipeline.ts +242 -0
  63. package/src/commit/prompts/analysis-system.md +155 -0
  64. package/src/commit/prompts/analysis-user.md +41 -0
  65. package/src/commit/prompts/changelog-system.md +56 -0
  66. package/src/commit/prompts/changelog-user.md +19 -0
  67. package/src/commit/prompts/file-observer-system.md +26 -0
  68. package/src/commit/prompts/file-observer-user.md +9 -0
  69. package/src/commit/prompts/reduce-system.md +60 -0
  70. package/src/commit/prompts/reduce-user.md +17 -0
  71. package/src/commit/prompts/summary-retry.md +4 -0
  72. package/src/commit/prompts/summary-system.md +52 -0
  73. package/src/commit/prompts/summary-user.md +13 -0
  74. package/src/commit/prompts/types-description.md +2 -0
  75. package/src/commit/types.ts +109 -0
  76. package/src/commit/utils/exclusions.ts +42 -0
  77. package/src/config/file-lock.ts +111 -0
  78. package/src/config/model-registry.ts +16 -7
  79. package/src/config/settings-manager.ts +115 -40
  80. package/src/config.ts +5 -5
  81. package/src/discovery/agents-md.ts +1 -1
  82. package/src/discovery/builtin.ts +1 -1
  83. package/src/discovery/claude.ts +1 -1
  84. package/src/discovery/cline.ts +1 -1
  85. package/src/discovery/codex.ts +1 -1
  86. package/src/discovery/cursor.ts +1 -1
  87. package/src/discovery/gemini.ts +1 -1
  88. package/src/discovery/github.ts +1 -1
  89. package/src/discovery/index.ts +11 -11
  90. package/src/discovery/mcp-json.ts +1 -1
  91. package/src/discovery/ssh.ts +1 -1
  92. package/src/discovery/vscode.ts +1 -1
  93. package/src/discovery/windsurf.ts +1 -1
  94. package/src/extensibility/custom-commands/loader.ts +1 -1
  95. package/src/extensibility/custom-commands/types.ts +1 -1
  96. package/src/extensibility/custom-tools/loader.ts +1 -1
  97. package/src/extensibility/custom-tools/types.ts +1 -1
  98. package/src/extensibility/extensions/loader.ts +1 -1
  99. package/src/extensibility/extensions/types.ts +1 -1
  100. package/src/extensibility/hooks/loader.ts +1 -1
  101. package/src/extensibility/hooks/types.ts +3 -3
  102. package/src/index.ts +10 -10
  103. package/src/ipy/executor.ts +97 -1
  104. package/src/lsp/index.ts +1 -1
  105. package/src/lsp/render.ts +90 -46
  106. package/src/main.ts +16 -3
  107. package/src/mcp/loader.ts +3 -3
  108. package/src/migrations.ts +3 -3
  109. package/src/modes/components/assistant-message.ts +29 -1
  110. package/src/modes/components/tool-execution.ts +5 -3
  111. package/src/modes/components/tree-selector.ts +1 -1
  112. package/src/modes/controllers/extension-ui-controller.ts +1 -1
  113. package/src/modes/controllers/selector-controller.ts +1 -1
  114. package/src/modes/interactive-mode.ts +5 -3
  115. package/src/modes/rpc/rpc-client.ts +1 -1
  116. package/src/modes/rpc/rpc-mode.ts +1 -4
  117. package/src/modes/rpc/rpc-types.ts +1 -1
  118. package/src/modes/theme/mermaid-cache.ts +89 -0
  119. package/src/modes/theme/theme.ts +2 -0
  120. package/src/modes/types.ts +2 -2
  121. package/src/patch/index.ts +3 -9
  122. package/src/patch/shared.ts +33 -5
  123. package/src/prompts/tools/task.md +2 -0
  124. package/src/sdk.ts +60 -22
  125. package/src/session/agent-session.ts +3 -3
  126. package/src/session/agent-storage.ts +32 -28
  127. package/src/session/artifacts.ts +24 -1
  128. package/src/session/auth-storage.ts +25 -10
  129. package/src/session/storage-migration.ts +12 -53
  130. package/src/system-prompt.ts +2 -2
  131. package/src/task/.executor.ts.kate-swp +0 -0
  132. package/src/task/executor.ts +1 -1
  133. package/src/task/index.ts +10 -1
  134. package/src/task/output-manager.ts +94 -0
  135. package/src/task/render.ts +7 -12
  136. package/src/task/worker.ts +1 -1
  137. package/src/tools/ask.ts +35 -13
  138. package/src/tools/bash.ts +80 -87
  139. package/src/tools/calculator.ts +42 -40
  140. package/src/tools/complete.ts +1 -1
  141. package/src/tools/fetch.ts +67 -104
  142. package/src/tools/find.ts +83 -86
  143. package/src/tools/grep.ts +80 -96
  144. package/src/tools/index.ts +10 -7
  145. package/src/tools/ls.ts +39 -65
  146. package/src/tools/notebook.ts +48 -64
  147. package/src/tools/output-utils.ts +1 -1
  148. package/src/tools/python.ts +71 -183
  149. package/src/tools/read.ts +74 -15
  150. package/src/tools/render-utils.ts +1 -15
  151. package/src/tools/ssh.ts +43 -24
  152. package/src/tools/todo-write.ts +27 -15
  153. package/src/tools/write.ts +93 -64
  154. package/src/tui/code-cell.ts +115 -0
  155. package/src/tui/file-list.ts +48 -0
  156. package/src/tui/index.ts +11 -0
  157. package/src/tui/output-block.ts +73 -0
  158. package/src/tui/status-line.ts +40 -0
  159. package/src/tui/tree-list.ts +56 -0
  160. package/src/tui/types.ts +17 -0
  161. package/src/tui/utils.ts +49 -0
  162. package/src/vendor/photon/photon_rs_bg.wasm.b64.js +1 -0
  163. package/src/web/search/auth.ts +1 -1
  164. package/src/web/search/index.ts +1 -1
  165. package/src/web/search/render.ts +119 -163
  166. package/tsconfig.json +0 -42
package/CHANGELOG.md CHANGED
@@ -2,6 +2,111 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ### Added
6
+ - Added `omp commit` command to generate conventional commits with changelog updates
7
+ - Added agentic commit mode with commit-specific tools and `--legacy` fallback
8
+ - Added configurable settings for map-reduce analysis including concurrency, timeout, file thresholds, and token limits
9
+ - Added support for excluding YAML lock files (`.lock.yml`, `.lock.yaml`, `-lock.yml`, `-lock.yaml`) from commit analysis
10
+ - Added new TUI component library with reusable rendering utilities including code cells, file lists, tree lists, status lines, and output blocks
11
+ - Added renderCodeCell component for displaying code with optional output sections, supporting syntax highlighting and status indicators
12
+ - Added renderFileList component for rendering file/directory listings with language icons and metadata
13
+ - Added renderTreeList component for hierarchical tree-based item rendering with expand/collapse support
14
+ - Added renderStatusLine component for standardized tool status headers with icons, descriptions, and metadata
15
+ - Added renderOutputBlock component for bordered output containers with structured sections
16
+ - Added renderOutputBlock to Bash tool for improved output formatting with status indicators
17
+ - Added `--legacy` flag to `omp commit` for using the deterministic pipeline instead of agentic mode
18
+ - Added split commit support to automatically create multiple atomic commits for unrelated changes
19
+ - Added git hunk inspection tools for fine-grained diff analysis in commit generation
20
+ - Added commit message validation with filler word and meta phrase detection
21
+ - Added automatic unicode normalization in commit summaries
22
+ - Added real-time progress output to agentic commit mode showing thinking status, tool calls, and completion summary
23
+ - Added hunk-level staging support in split commits allowing partial file changes per commit
24
+ - Added dependency ordering for split commits ensuring commits are applied in correct sequence
25
+ - Added circular dependency detection with validation errors for split commit plans
26
+ - Added parallel file analysis with cross-file context awareness via `analyze_files` tool
27
+ - Added AGENTS.md context file discovery for commit generation
28
+ - Added progress indicators during changelog generation and model resolution
29
+ - Added propose_changelog tool for agent-provided changelog entries in agentic commit workflow
30
+ - Added fallback commit generation when agentic mode fails, using file pattern analysis and heuristic-based type inference
31
+ - Added trivial change detection to automatically classify whitespace-only and import-reorganization commits
32
+ - Added support for pre-computed file observations in commit agent to skip redundant analyze_files calls
33
+ - Added diff content caching with smart file prioritization to optimize token usage in large changesets
34
+ - Added lock file filtering (17 patterns including Cargo.lock, package-lock.json, bun.lock) from commit analysis
35
+ - Added changelog deletion support to remove outdated entries via the changelog proposal interface
36
+ - Added support for pre-computed changelog entries in commit agent to display existing unreleased sections for potential deletion
37
+ - Added `ExistingChangelogEntries` interface to track changelog sections by path for changelog proposal context
38
+ - Added conditional `analyze_files` skipping in commit agent when pre-analyzed observations are provided
39
+ - Added guidance to commit agent prompts instructing subagents to write files directly instead of returning changes for manual application
40
+ - Added mermaid diagram rendering with terminal graphics support (Kitty/iTerm2) for markdown output
41
+ - Added renderMermaidToPng utility for converting mermaid code blocks to terminal-displayable PNG images via mmdc CLI
42
+ - Added mermaid block extraction with content-addressed hashing for deduplication and cache lookup
43
+ - Added background mermaid pre-rendering in assistant messages for responsive diagram display
44
+ - Added two-level mermaid caching with pending deduplication to prevent redundant renders
45
+ - Added Python kernel session pooling with MAX_KERNEL_SESSIONS limit and automatic eviction of oldest sessions
46
+ - Added automatic idle kernel session cleanup timer (5-minute timeout, 30-second interval)
47
+ - Added WASM binary generation script for photon module distribution
48
+
49
+ ### Changed
50
+ - Changed changelog diff truncation limit to be configurable via settings
51
+ - Changed tool result rendering to use new TUI component library across multiple tools (bash, calculator, fetch, find, grep, ls, notebook, python, read, ssh, write, lsp, web search) for consistent output formatting
52
+ - Changed Bash tool output rendering to use renderOutputBlock with proper section handling and width-aware truncation
53
+ - Changed Python tool output rendering to use renderCodeCell component for code cell display with status indicators
54
+ - Changed Read tool output rendering to use renderCodeCell with syntax highlighting and warnings display
55
+ - Changed Write tool output rendering to use renderCodeCell for code display with streaming preview support
56
+ - Changed Fetch tool output rendering to use renderOutputBlock with metadata and content preview sections
57
+ - Changed LSP tool output rendering to use renderStatusLine and renderOutputBlock for structured output display
58
+ - Changed Web Search result rendering to use renderOutputBlock with answer, sources, related questions, and metadata sections
59
+ - Changed Find, Grep, and Ls tools to use renderFileList and renderTreeList for consistent file/item listing
60
+ - Changed Calculator tool result rendering to use renderTreeList for result item display
61
+ - Changed Notebook and TodoWrite tools to use new TUI rendering components for consistent output format
62
+ - Refactored render-utils to move tree-related utilities to TUI module (getTreeBranch, getTreeContinuePrefix)
63
+ - Changed import organization in sdk.ts for consistency
64
+ - Changed tool result rendering to merge call and result displays, showing tool arguments (command, pattern, query, path) in result headers for Bash, Calculator, Fetch, Find, Grep, Ls, LSP, Notebook, Read, SSH, TodoWrite, Web Search, and Write tools
65
+ - Changed Read tool title to display line range when offset or limit arguments are provided
66
+ - Changed worker instantiation to use direct URL import instead of pre-bundled worker files
67
+ - Changed `omp commit` to use agentic mode by default with tool-based git inspection
68
+ - Changed agentic commit progress output to show real-time thinking previews and structured tool argument details
69
+ - Changed agentic commit progress output to display full multi-line assistant messages and render tool arguments with tree-style formatting for improved readability
70
+ - Changed agentic commit progress output to render assistant messages as formatted Markdown with proper word wrapping
71
+ - Changed output block border color to reflect state (error, success, warning) for improved visual feedback
72
+ - Changed LSP hover rendering to display documentation text before code blocks in both collapsed and expanded views
73
+ - Changed Write tool to show streaming preview of content being written with syntax highlighting
74
+ - Changed Read tool to display resolved path information when reading from URLs or symlinks
75
+ - Changed Calculator tool result display to show both expression and output (e.g., `2+2 = 4`) instead of just the result
76
+ - Changed Python tool output to group status information under a labeled section for clearer organization
77
+ - Changed SSH tool output to apply consistent styling to non-ANSI output lines
78
+ - Changed Todo Write tool to respect expanded/collapsed state and use standard preview limits
79
+ - Changed Web Search related questions to respect expanded/collapsed state instead of always showing all items
80
+ - Changed empty and error state rendering across multiple tools (Find, Grep, Ls, Notebook, Calculator, Ask) to include consistent status headers
81
+ - Changed split commit to support hunk selectors (all, indices, or line ranges) instead of whole-file staging
82
+ - Changed `analyze_file` tool to `analyze_files` for batch parallel analysis of multiple files
83
+ - Switched agentic commit from auto-generated changelogs to agent-proposed entries with validation and retry logic
84
+ - Commit agent now resolves a separate smaller model for commit generation instead of reusing the primary model
85
+ - Normalized code formatting and indentation across tool renderers and UI components
86
+ - Changed git-file-diff tool to prioritize files by type and respect token budget limits with intelligent truncation
87
+ - Changed git-overview tool to filter and report excluded lock files separately from staged files
88
+ - Changed analyze-file tool to include file type inference and enriched related files with line counts
89
+ - Changed propose-changelog tool to support optional deletion entries for removing existing changelog items
90
+ - Changed commit agent to accept pre-computed file observations and format them into session prompts
91
+ - Changed changelog skip condition in `applyChangelogProposals` to also check for empty deletions object
92
+ - Changed `createCommitTools()` to build tools array incrementally with conditional `analyze_files` inclusion based on `enableAnalyzeFiles` flag
93
+ - Changed system prompt guidance to clarify that pre-computed observations prevent redundant `analyze_files` calls
94
+ - Removed map-reduce preprocessing phase from commit agent for faster iteration
95
+ - Changed commit agent to process full diff text directly instead of pre-computed file observations
96
+ - Changed commit agent initialization to load settingsManager, authStorage, modelRegistry, and stagedFiles in parallel
97
+ - Changed commit agent prompt to remove pre-computed observations guidance and encourage direct analyze_files usage
98
+ - Changed AuthStorage from constructor-based instantiation to async factory method (AuthStorage.create())
99
+ - Changed Python kernel resource management with gateway shutdown on session disposal
100
+ - Updated TypeScript configuration for better publish-time configuration handling with tsconfig.publish.json
101
+
102
+ ### Fixed
103
+ - Fixed database busy errors during concurrent access by adding retry logic with exponential backoff when opening storage
104
+ - Find tool now rejects searches from root directory and enforces a 5-second timeout on fd operations
105
+ - Commit command now exits cleanly with exit code 0 on success
106
+ - Handle undefined code parameter in code cell renderer
107
+ - Fixed indentation formatting in split-commit tool function signature
108
+ - Fixed changelog application to process proposals containing only deletion entries without additions
109
+ - Fixed indentation formatting in Python tool output renderer
5
110
  ## [8.0.0] - 2026-01-23
6
111
  ### Added
7
112
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-coding-agent",
3
- "version": "8.0.20",
3
+ "version": "8.1.0",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "ompConfig": {
@@ -22,15 +22,17 @@
22
22
  "import": "./src/extensibility/hooks/index.ts"
23
23
  },
24
24
  "./prompts/*": "./src/prompts/*",
25
- "./*": "./src/*"
25
+ "./*": {
26
+ "types": "./src/*",
27
+ "import": "./src/*"
28
+ }
26
29
  },
27
30
  "files": [
28
31
  "src",
29
32
  "scripts",
30
33
  "docs",
31
34
  "examples",
32
- "CHANGELOG.md",
33
- "tsconfig.json"
35
+ "CHANGELOG.md"
34
36
  ],
35
37
  "scripts": {
36
38
  "check": "tsgo -p tsconfig.check.json",
@@ -38,17 +40,18 @@
38
40
  "clean": "rm -rf dist",
39
41
  "build": "tsgo -p tsconfig.build.json && chmod +x dist/cli.js",
40
42
  "build:binary": "bun run generate-wasm-b64 && bun build --compile ./src/cli.ts --outfile dist/omp",
43
+ "generate-wasm-b64": "bun scripts/generate-wasm-b64.ts",
41
44
  "generate-template": "bun scripts/generate-template.ts",
42
- "postinstall": "bun run generate-template || true",
45
+ "postinstall": "(bun run generate-wasm-b64 && bun run generate-template) || true",
43
46
  "test": "bun test",
44
- "prepublishOnly": "bun run generate-template && cp tsconfig.publish.json tsconfig.json"
47
+ "prepublishOnly": "cp tsconfig.publish.json tsconfig.json && bun run generate-template"
45
48
  },
46
49
  "dependencies": {
47
- "@oh-my-pi/omp-stats": "8.0.20",
48
- "@oh-my-pi/pi-agent-core": "8.0.20",
49
- "@oh-my-pi/pi-ai": "8.0.20",
50
- "@oh-my-pi/pi-tui": "8.0.20",
51
- "@oh-my-pi/pi-utils": "8.0.20",
50
+ "@oh-my-pi/omp-stats": "workspace:*",
51
+ "@oh-my-pi/pi-agent-core": "workspace:*",
52
+ "@oh-my-pi/pi-ai": "workspace:*",
53
+ "@oh-my-pi/pi-tui": "workspace:*",
54
+ "@oh-my-pi/pi-utils": "workspace:*",
52
55
  "@openai/agents": "^0.3.7",
53
56
  "@sinclair/typebox": "^0.34.46",
54
57
  "ajv": "^8.17.1",
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Generates a base64-encoded JavaScript module from the photon WASM file.
4
+ * This allows bundling the WASM binary inline for single-file distribution.
5
+ */
6
+
7
+ import { join } from "node:path";
8
+
9
+ const VENDOR_DIR = join(import.meta.dir, "../src/vendor/photon");
10
+ const WASM_PATH = join(VENDOR_DIR, "photon_rs_bg.wasm");
11
+ const OUTPUT_PATH = join(VENDOR_DIR, "photon_rs_bg.wasm.b64.js");
12
+
13
+ const wasmFile = Bun.file(WASM_PATH);
14
+ if (!(await wasmFile.exists())) {
15
+ console.error(`WASM file not found: ${WASM_PATH}`);
16
+ process.exit(1);
17
+ }
18
+
19
+ const wasmBytes = await wasmFile.arrayBuffer();
20
+ const base64 = Buffer.from(wasmBytes).toString("base64");
21
+ const content = `export default "${base64}";\n`;
22
+
23
+ await Bun.write(OUTPUT_PATH, content);
24
+ console.log(`Generated ${OUTPUT_PATH} (${Math.round(base64.length / 1024)}KB)`);
@@ -5,7 +5,7 @@
5
5
  * persistent guidance to the agent.
6
6
  */
7
7
 
8
- import { defineCapability } from "./index";
8
+ import { defineCapability } from ".";
9
9
  import type { SourceMeta } from "./types";
10
10
 
11
11
  /**
@@ -4,7 +4,7 @@
4
4
  * TypeScript/JavaScript extension modules loaded by the extension system.
5
5
  */
6
6
 
7
- import { defineCapability } from "./index";
7
+ import { defineCapability } from ".";
8
8
  import type { SourceMeta } from "./types";
9
9
 
10
10
  /**
@@ -4,7 +4,7 @@
4
4
  * Gemini-style extensions that provide MCP servers, tools, and context.
5
5
  */
6
6
 
7
- import { defineCapability } from "./index";
7
+ import { defineCapability } from ".";
8
8
  import type { MCPServer } from "./mcp";
9
9
  import type { SourceMeta } from "./types";
10
10
 
@@ -4,7 +4,7 @@
4
4
  * Pre/post tool execution hooks defined as shell scripts.
5
5
  */
6
6
 
7
- import { defineCapability } from "./index";
7
+ import { defineCapability } from ".";
8
8
  import type { SourceMeta } from "./types";
9
9
 
10
10
  /**
@@ -4,7 +4,7 @@
4
4
  * GitHub Copilot-style instructions with optional file pattern matching.
5
5
  */
6
6
 
7
- import { defineCapability } from "./index";
7
+ import { defineCapability } from ".";
8
8
  import type { SourceMeta } from "./types";
9
9
 
10
10
  /**
@@ -5,7 +5,7 @@
5
5
  * All providers translate their native format to this shape.
6
6
  */
7
7
 
8
- import { defineCapability } from "./index";
8
+ import { defineCapability } from ".";
9
9
  import type { SourceMeta } from "./types";
10
10
 
11
11
  /**
@@ -4,7 +4,7 @@
4
4
  * Reusable prompt templates (Codex format) available via /prompts: menu.
5
5
  */
6
6
 
7
- import { defineCapability } from "./index";
7
+ import { defineCapability } from ".";
8
8
  import type { SourceMeta } from "./types";
9
9
 
10
10
  /**
@@ -5,7 +5,7 @@
5
5
  * Translated to a canonical shape regardless of source format.
6
6
  */
7
7
 
8
- import { defineCapability } from "./index";
8
+ import { defineCapability } from ".";
9
9
  import type { SourceMeta } from "./types";
10
10
 
11
11
  /**
@@ -4,7 +4,7 @@
4
4
  * Configuration settings from various sources (JSON, TOML, etc.)
5
5
  */
6
6
 
7
- import { defineCapability } from "./index";
7
+ import { defineCapability } from ".";
8
8
  import type { SourceMeta } from "./types";
9
9
 
10
10
  /**
@@ -4,7 +4,7 @@
4
4
  * Skills provide specialized knowledge or workflows that extend agent capabilities.
5
5
  */
6
6
 
7
- import { defineCapability } from "./index";
7
+ import { defineCapability } from ".";
8
8
  import type { SourceMeta } from "./types";
9
9
 
10
10
  /**
@@ -4,7 +4,7 @@
4
4
  * File-based slash commands defined as markdown files.
5
5
  */
6
6
 
7
- import { defineCapability } from "./index";
7
+ import { defineCapability } from ".";
8
8
  import type { SourceMeta } from "./types";
9
9
 
10
10
  /**
@@ -4,7 +4,7 @@
4
4
  * Canonical shape for SSH host entries, regardless of source format.
5
5
  */
6
6
 
7
- import { defineCapability } from "./index";
7
+ import { defineCapability } from ".";
8
8
  import type { SourceMeta } from "./types";
9
9
 
10
10
  /**
@@ -5,7 +5,7 @@
5
5
  * Distinct from context-files which are user instructions shown in conversation.
6
6
  */
7
7
 
8
- import { defineCapability } from "./index";
8
+ import { defineCapability } from ".";
9
9
  import type { SourceMeta } from "./types";
10
10
 
11
11
  /**
@@ -4,7 +4,7 @@
4
4
  * User-defined tools that extend agent capabilities.
5
5
  */
6
6
 
7
- import { defineCapability } from "./index";
7
+ import { defineCapability } from ".";
8
8
  import type { SourceMeta } from "./types";
9
9
 
10
10
  /**
package/src/cli/args.ts CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
6
6
  import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "@oh-my-pi/pi-coding-agent/config";
7
- import { BUILTIN_TOOLS } from "@oh-my-pi/pi-coding-agent/tools/index";
7
+ import { BUILTIN_TOOLS } from "@oh-my-pi/pi-coding-agent/tools";
8
8
  import chalk from "chalk";
9
9
 
10
10
  export type Mode = "text" | "json" | "rpc";
@@ -5,11 +5,7 @@
5
5
  */
6
6
 
7
7
  import { APP_NAME } from "@oh-my-pi/pi-coding-agent/config";
8
- import {
9
- PluginManager,
10
- parseSettingValue,
11
- validateSetting,
12
- } from "@oh-my-pi/pi-coding-agent/extensibility/plugins/index";
8
+ import { PluginManager, parseSettingValue, validateSetting } from "@oh-my-pi/pi-coding-agent/extensibility/plugins";
13
9
  import { theme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
14
10
  import chalk from "chalk";
15
11
 
@@ -0,0 +1,309 @@
1
+ import type { Api, Model } from "@oh-my-pi/pi-ai";
2
+ import agentUserPrompt from "@oh-my-pi/pi-coding-agent/commit/agentic/prompts/session-user.md" with { type: "text" };
3
+ import agentSystemPrompt from "@oh-my-pi/pi-coding-agent/commit/agentic/prompts/system.md" with { type: "text" };
4
+ import type { CommitAgentState } from "@oh-my-pi/pi-coding-agent/commit/agentic/state";
5
+ import { createCommitTools } from "@oh-my-pi/pi-coding-agent/commit/agentic/tools";
6
+ import type { ControlledGit } from "@oh-my-pi/pi-coding-agent/commit/git";
7
+ import typesDescriptionPrompt from "@oh-my-pi/pi-coding-agent/commit/prompts/types-description.md" with {
8
+ type: "text",
9
+ };
10
+ import type { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry";
11
+ import { renderPromptTemplate } from "@oh-my-pi/pi-coding-agent/config/prompt-templates";
12
+ import type { SettingsManager } from "@oh-my-pi/pi-coding-agent/config/settings-manager";
13
+ import { getMarkdownTheme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
14
+ import { createAgentSession } from "@oh-my-pi/pi-coding-agent/sdk";
15
+ import type { AgentSessionEvent } from "@oh-my-pi/pi-coding-agent/session/agent-session";
16
+ import type { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage";
17
+ import { Markdown } from "@oh-my-pi/pi-tui";
18
+ import chalk from "chalk";
19
+
20
+ export interface CommitAgentInput {
21
+ cwd: string;
22
+ git: ControlledGit;
23
+ model: Model<Api>;
24
+ settingsManager: SettingsManager;
25
+ modelRegistry: ModelRegistry;
26
+ authStorage: AuthStorage;
27
+ userContext?: string;
28
+ contextFiles?: Array<{ path: string; content: string }>;
29
+ changelogTargets: string[];
30
+ requireChangelog: boolean;
31
+ diffText?: string;
32
+ existingChangelogEntries?: ExistingChangelogEntries[];
33
+ }
34
+
35
+ export interface ExistingChangelogEntries {
36
+ path: string;
37
+ sections: Array<{ name: string; items: string[] }>;
38
+ }
39
+
40
+ export async function runCommitAgentSession(input: CommitAgentInput): Promise<CommitAgentState> {
41
+ const typesDescription = renderPromptTemplate(typesDescriptionPrompt);
42
+ const systemPrompt = renderPromptTemplate(agentSystemPrompt, {
43
+ types_description: typesDescription,
44
+ });
45
+ const state: CommitAgentState = { diffText: input.diffText };
46
+ const spawns = "quick_task";
47
+ const tools = createCommitTools({
48
+ cwd: input.cwd,
49
+ git: input.git,
50
+ authStorage: input.authStorage,
51
+ modelRegistry: input.modelRegistry,
52
+ settingsManager: input.settingsManager,
53
+ spawns,
54
+ state,
55
+ changelogTargets: input.changelogTargets,
56
+ enableAnalyzeFiles: true,
57
+ });
58
+
59
+ const { session } = await createAgentSession({
60
+ cwd: input.cwd,
61
+ authStorage: input.authStorage,
62
+ modelRegistry: input.modelRegistry,
63
+ settingsManager: input.settingsManager,
64
+ model: input.model,
65
+ systemPrompt,
66
+ customTools: tools,
67
+ enableLsp: false,
68
+ enableMCP: false,
69
+ hasUI: false,
70
+ spawns,
71
+ toolNames: ["__none__"],
72
+ contextFiles: input.contextFiles,
73
+ disableExtensionDiscovery: true,
74
+ skills: [],
75
+ promptTemplates: [],
76
+ slashCommands: [],
77
+ });
78
+ let toolCalls = 0;
79
+ let messageCount = 0;
80
+ let isThinking = false;
81
+ let thinkingLineActive = false;
82
+ const toolArgsById = new Map<string, { name: string; args?: Record<string, unknown> }>();
83
+ const writeThinkingLine = (text: string) => {
84
+ const line = chalk.dim(`… ${text}`);
85
+ process.stdout.write(`\r\x1b[2K${line}`);
86
+ thinkingLineActive = true;
87
+ };
88
+ const clearThinkingLine = () => {
89
+ if (!thinkingLineActive) return;
90
+ process.stdout.write("\r\x1b[2K");
91
+ thinkingLineActive = false;
92
+ };
93
+ const unsubscribe = session.subscribe((event: AgentSessionEvent) => {
94
+ switch (event.type) {
95
+ case "message_start":
96
+ if (event.message.role === "assistant") {
97
+ isThinking = true;
98
+ thinkingLineActive = false;
99
+ }
100
+ break;
101
+ case "message_update": {
102
+ if (event.message?.role !== "assistant") break;
103
+ const preview = extractMessagePreview(event.message?.content ?? []);
104
+ if (!preview) break;
105
+ writeThinkingLine(preview);
106
+ break;
107
+ }
108
+ case "tool_execution_start":
109
+ toolCalls += 1;
110
+ toolArgsById.set(event.toolCallId, { name: event.toolName, args: event.args });
111
+ break;
112
+ case "message_end": {
113
+ const role = event.message?.role;
114
+ if (role === "assistant") {
115
+ messageCount += 1;
116
+ isThinking = false;
117
+ clearThinkingLine();
118
+ const messageText = extractMessageText(event.message?.content ?? []);
119
+ if (messageText) {
120
+ writeAssistantMessage(messageText);
121
+ }
122
+ }
123
+ break;
124
+ }
125
+ case "tool_execution_end": {
126
+ const stored = toolArgsById.get(event.toolCallId) ?? { name: event.toolName };
127
+ toolArgsById.delete(event.toolCallId);
128
+ clearThinkingLine();
129
+ const toolLabel = formatToolLabel(stored.name);
130
+ const symbol = event.isError ? "" : "";
131
+ writeStdout(`${symbol} ${toolLabel}`);
132
+ const argsLines = formatToolArgs(stored.args);
133
+ if (argsLines.length > 0) {
134
+ writeStdout(formatToolArgsBlock(argsLines));
135
+ }
136
+ break;
137
+ }
138
+ case "agent_end":
139
+ if (isThinking) {
140
+ isThinking = false;
141
+ }
142
+ writeStdout(`● agent finished (${messageCount} messages, ${toolCalls} tools)`);
143
+ break;
144
+ default:
145
+ break;
146
+ }
147
+ });
148
+
149
+ try {
150
+ const prompt = renderPromptTemplate(agentUserPrompt, {
151
+ user_context: input.userContext,
152
+ changelog_targets: input.changelogTargets.length > 0 ? input.changelogTargets.join("\n") : undefined,
153
+ existing_changelog_entries: input.existingChangelogEntries,
154
+ });
155
+ const MAX_RETRIES = 3;
156
+ let retryCount = 0;
157
+ const needsChangelog = input.requireChangelog && input.changelogTargets.length > 0;
158
+
159
+ await session.prompt(prompt, { expandPromptTemplates: false });
160
+ while (retryCount < MAX_RETRIES && !isProposalComplete(state, needsChangelog)) {
161
+ retryCount += 1;
162
+ const reminder = buildReminderMessage(state, needsChangelog, retryCount, MAX_RETRIES);
163
+ await session.prompt(reminder, { expandPromptTemplates: false });
164
+ }
165
+
166
+ return state;
167
+ } finally {
168
+ unsubscribe();
169
+ await session.dispose();
170
+ }
171
+ }
172
+
173
+ function writeStdout(message: string): void {
174
+ process.stdout.write(`${message}\n`);
175
+ }
176
+
177
+ function extractMessagePreview(content: Array<{ type: string; text?: string }>): string | null {
178
+ const textBlocks = content
179
+ .filter((block) => block.type === "text" && typeof block.text === "string")
180
+ .map((block) => block.text?.trim())
181
+ .filter((value): value is string => Boolean(value));
182
+ if (textBlocks.length === 0) return null;
183
+ const combined = textBlocks.join(" ").replace(/\s+/g, " ").trim();
184
+ return truncateToolArg(combined);
185
+ }
186
+
187
+ function extractMessageText(content: Array<{ type: string; text?: string }>): string | null {
188
+ const textBlocks = content
189
+ .filter((block) => block.type === "text" && typeof block.text === "string")
190
+ .map((block) => block.text ?? "")
191
+ .filter((value) => value.trim().length > 0);
192
+ if (textBlocks.length === 0) return null;
193
+ return textBlocks.join("\n").trim();
194
+ }
195
+
196
+ function writeAssistantMessage(message: string): void {
197
+ const lines = renderMarkdownLines(message);
198
+ if (lines.length === 0) return;
199
+ let firstContentIndex = lines.findIndex((line) => line.trim().length > 0);
200
+ if (firstContentIndex === -1) {
201
+ firstContentIndex = 0;
202
+ }
203
+ for (const [index, line] of lines.entries()) {
204
+ const prefix = index === firstContentIndex ? "● " : " ";
205
+ writeStdout(`${prefix}${line}`.trimEnd());
206
+ }
207
+ }
208
+
209
+ function renderMarkdownLines(message: string): string[] {
210
+ const width = Math.max(40, process.stdout.columns ?? 100);
211
+ const markdown = new Markdown(message, 0, 0, getMarkdownTheme());
212
+ return markdown.render(width);
213
+ }
214
+
215
+ function formatToolLabel(toolName: string): string {
216
+ const displayName = toolName
217
+ .split(/[_-]/)
218
+ .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
219
+ .join("");
220
+ return displayName;
221
+ }
222
+
223
+ function formatToolArgs(args?: Record<string, unknown>): string[] {
224
+ if (!args || Object.keys(args).length === 0) return [];
225
+ const lines: string[] = [];
226
+ const visit = (value: unknown, keyPath: string) => {
227
+ if (value === null || value === undefined) return;
228
+ if (Array.isArray(value)) {
229
+ if (value.length === 0) return;
230
+ const rendered = value.map((item) => renderPrimitive(item)).filter(Boolean);
231
+ if (rendered.length > 0) {
232
+ lines.push(`${keyPath}: ${rendered.join(", ")}`);
233
+ }
234
+ return;
235
+ }
236
+ if (typeof value === "object") {
237
+ const entries = Object.entries(value as Record<string, unknown>);
238
+ if (entries.length === 0) return;
239
+ for (const [childKey, childValue] of entries) {
240
+ visit(childValue, `${keyPath}.${childKey}`);
241
+ }
242
+ return;
243
+ }
244
+ const rendered = renderPrimitive(value);
245
+ if (rendered) {
246
+ lines.push(`${keyPath}: ${rendered}`);
247
+ }
248
+ };
249
+ for (const [key, value] of Object.entries(args)) {
250
+ visit(value, key);
251
+ }
252
+ return lines;
253
+ }
254
+
255
+ function renderPrimitive(value: unknown): string | null {
256
+ if (value === null || value === undefined) return null;
257
+ if (typeof value === "string") {
258
+ const trimmed = value.trim();
259
+ return trimmed.length > 0 ? trimmed : null;
260
+ }
261
+ if (typeof value === "number" || typeof value === "boolean") {
262
+ return String(value);
263
+ }
264
+ return null;
265
+ }
266
+
267
+ function formatToolArgsBlock(lines: string[]): string {
268
+ return lines
269
+ .map((line, index) => {
270
+ if (index === 0) return ` ⎿ ${line}`;
271
+ const branch = index === lines.length - 1 ? "└" : "├";
272
+ return ` ${branch} ${line}`;
273
+ })
274
+ .join("\n");
275
+ }
276
+
277
+ function isProposalComplete(state: CommitAgentState, requireChangelog: boolean): boolean {
278
+ const hasCommit = Boolean(state.proposal ?? state.splitProposal);
279
+ const hasChangelog = !requireChangelog || Boolean(state.changelogProposal);
280
+ return hasCommit && hasChangelog;
281
+ }
282
+
283
+ function buildReminderMessage(
284
+ state: CommitAgentState,
285
+ requireChangelog: boolean,
286
+ retryCount: number,
287
+ maxRetries: number,
288
+ ): string {
289
+ const missing: string[] = [];
290
+ if (!state.proposal && !state.splitProposal) {
291
+ missing.push("commit proposal (propose_commit or split_commit)");
292
+ }
293
+ if (requireChangelog && !state.changelogProposal) {
294
+ missing.push("changelog entries (propose_changelog)");
295
+ }
296
+ return `<system-reminder>
297
+ CRITICAL: You must call the required tools before finishing.
298
+
299
+ Missing: ${missing.join(", ") || "none"}.
300
+ Reminder ${retryCount} of ${maxRetries}.
301
+
302
+ Call the missing tool(s) now.
303
+ </system-reminder>`;
304
+ }
305
+
306
+ function truncateToolArg(value: string): string {
307
+ if (value.length <= 40) return value;
308
+ return `${value.slice(0, 37)}...`;
309
+ }