Skip to content

Refactor extension internals for maintainability#21

Merged
Vahor merged 5 commits into
mainfrom
refactor/maintainability
May 23, 2026
Merged

Refactor extension internals for maintainability#21
Vahor merged 5 commits into
mainfrom
refactor/maintainability

Conversation

@Vahor

@Vahor Vahor commented May 23, 2026

Copy link
Copy Markdown
Owner

Summary

This PR is a maintainability/readability refactor for the extension internals while keeping Effect + Schema in place.

Shared config and command schemas

  • Extracts the reusable command entry schema/type into @vahor/shared/runner/config.
  • Reuses that shared schema from both pi-hooks and pi-keymap instead of duplicating command config fields.
  • Allows $schema in config files at runtime, matching the generated editor schemas.
  • Makes config decoding stricter with onExcessProperty: "error", so unknown config keys fail instead of being silently dropped.

Shared config merging

  • Generalizes keyed-array merging instead of hardcoding keymaps.
  • When both sides of a config value are arrays of objects with a key, they are merged by key by default.
  • Project entries still override global entries with the same key, while unique global/project entries are preserved.
  • Moves the merge test into the adjacent __tests__ layout.

Runner internals

  • Splits the command runner into focused files:
    • config.ts for command schema/types
    • context.ts for context-message formatting/truncation
    • interactive.ts for interactive command execution
    • spinner.ts for status spinner rendering
    • types.ts for shared runner result types
  • Keeps runCommands as the small orchestration entrypoint.
  • Escapes embedded code fences before adding command output to context markdown.
  • Applies configured/default timeouts to interactive commands and terminates timed-out child processes.
  • Removes an unused renderer export.

pi-keymap internals

  • Splits the large extension entrypoint into focused modules:
    • actions.ts for running command/prompt entries
    • validation.ts for keymap validation and dead-end warnings
    • shortcuts.ts for direct and leader shortcut registration
  • Keeps src/index.ts focused on loading config and wiring startup behavior.
  • Aligns prompt behavior with docs: send defaults to false, including open: false prompts.
  • Avoids registering leader handlers when the configured leader key is invalid.

Docs and schemas

  • Updates README wording for command output rendering.
  • Documents that keymaps arrays are merged by key.
  • Updates timeout docs now that interactive commands honor timeouts.
  • Regenerates JSON schemas after the shared schema/runtime config updates.
  • Adds a changeset for both public packages.

Validation

  • bun run format
  • bun run typecheck
  • bun test
  • bun run schemas:check
  • bun run build

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@Vahor, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 1 review/hour. Refill in 45 minutes and 1 second.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4ef4e355-8db3-4843-bee4-6c6867270b7b

📥 Commits

Reviewing files that changed from the base of the PR and between 9b0c9b7 and 38d7e52.

📒 Files selected for processing (26)
  • .changeset/maintainability-refactor.md
  • lib/shared/package.json
  • lib/shared/src/config/__tests__/config.test.ts
  • lib/shared/src/config/__tests__/merge.test.ts
  • lib/shared/src/config/merge.ts
  • lib/shared/src/config/parse.ts
  • lib/shared/src/config/test/merge.test.ts
  • lib/shared/src/runner/config.ts
  • lib/shared/src/runner/context.ts
  • lib/shared/src/runner/index.ts
  • lib/shared/src/runner/interactive.ts
  • lib/shared/src/runner/renderer.ts
  • lib/shared/src/runner/spinner.ts
  • lib/shared/src/runner/types.ts
  • packages/pi-hooks/README.md
  • packages/pi-hooks/src/__tests__/config.test.ts
  • packages/pi-hooks/src/config.ts
  • packages/pi-hooks/src/index.ts
  • packages/pi-keymap/README.md
  • packages/pi-keymap/src/__tests__/config.test.ts
  • packages/pi-keymap/src/actions.ts
  • packages/pi-keymap/src/config.ts
  • packages/pi-keymap/src/index.ts
  • packages/pi-keymap/src/shortcuts.ts
  • packages/pi-keymap/src/validation.ts
  • scripts/generate-config-schemas.ts

Walkthrough

This PR refactors command execution and configuration handling across the pi-extensions ecosystem. It introduces a shared command entry schema in the lib/shared package, refactors the runner module into focused concerns, enforces stricter configuration validation with generic keyed-settings merging, and modularizes pi-hooks and pi-keymap to reuse the shared schema and logic.

Changes

Command Config Refactoring & Modularization

Layer / File(s) Summary
Shared command entry schema
lib/shared/src/runner/config.ts, lib/shared/package.json, .changeset/maintainability-refactor.md, scripts/generate-config-schemas.ts
CommandEntryStruct and CommandEntrySchema define a unified contract for command entries (string or object form with optional cwd, timeout, print, context, interactive), exported from shared and reused across pi-hooks and pi-keymap.
Config validation & merge generalization
lib/shared/src/config/parse.ts, lib/shared/src/config/merge.ts, lib/shared/src/config/__tests__/config.test.ts, lib/shared/src/config/test/merge.test.ts
decodeConfig now rejects excess properties, and mergeSettings generically merges arrays of keyed settings by key (not just keymaps), enabling flexible composition across config sources. Tests validate recursive object merging, default keyed-array combination, and project-level override precedence.
Shared runner infrastructure refactoring
lib/shared/src/runner/types.ts, lib/shared/src/runner/context.ts, lib/shared/src/runner/spinner.ts, lib/shared/src/runner/interactive.ts, lib/shared/src/runner/renderer.ts, lib/shared/src/runner/index.ts
Splits runner concerns into CommandResult type, context message formatting with truncation, spinner animation on a 100ms interval, TTY-aware interactive command execution, and refactored orchestration; removes the _label parameter and delegates to imported helpers.
Pi hooks integration with shared schema
packages/pi-hooks/src/config.ts, packages/pi-hooks/src/index.ts, packages/pi-hooks/README.md, packages/pi-hooks/src/__tests__/config.test.ts
Imports CommandEntrySchema from shared, eliminates local hook entry schema, enforces strict config validation (rejecting unknown event names), and removes the unused label argument from runCommands. Documentation clarifies that command output is rendered when print or context is enabled.
Keymap validation and action modules
packages/pi-keymap/src/validation.ts, packages/pi-keymap/src/actions.ts
Extracts keymap validation (entry action detection, label computation, direct/leader partitioning) into a dedicated module; introduces actions module to dispatch command execution and prompt workflows (send vs. editor-based) within keymap entries.
Keymap schema refactoring and shortcut registration
packages/pi-keymap/src/config.ts, packages/pi-keymap/src/shortcuts.ts
Updates keymap schema to reuse CommandEntrySchema, refactors leader-key resolution and command defaulting into composable helpers, and introduces direct and leader shortcut registration with trie-based multi-segment navigation and session lifecycle management.
Keymap index and test consolidation
packages/pi-keymap/src/index.ts, packages/pi-keymap/README.md, packages/pi-keymap/src/__tests__/config.test.ts
Refactors index to delegate validation and registration to imported modules, replacing 180+ lines of inline helpers; all config tests centralize strict schema validation via a local decodeConfig helper. Documentation clarifies recursive config merging, keymap entry override behavior, and output rendering conditions.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Refactor extension internals for maintainability' directly and accurately summarizes the main objective of this pull request, which is a comprehensive refactoring of extension code for improved maintainability and readability.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new

pkg-pr-new Bot commented May 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

bun add https://pkg.pr.new/@vahor/pi-hooks@21
bun add https://pkg.pr.new/@vahor/pi-keymap@21

commit: 38d7e52

@Vahor
Vahor force-pushed the refactor/maintainability branch 3 times, most recently from 5ce4081 to 9b0c9b7 Compare May 23, 2026 14:14
@Vahor

Vahor commented May 23, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/shared/src/config/test/merge.test.ts (1)

1-60: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Move this test file under __tests__/ to match the repository test layout rule.

This test uses Bun correctly, but its location under src/config/test/ does not follow the required __tests__/ placement convention.

As per coding guidelines, "Tests should be placed in __tests__/ directory alongside source files and use Bun test runner".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/shared/src/config/test/merge.test.ts` around lines 1 - 60, The test file
is misplaced; move the test that targets mergeSettings into the repository's
__tests__ layout: relocate the file containing the describe("mergeSettings",
...) block to an __tests__ directory adjacent to the source module, keep the
test contents (including the Bun import: import { describe, expect, test } from
"bun:test") unchanged, and update any relative imports if the new location
changes import paths for mergeSettings so the tests still import mergeSettings
correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/shared/src/runner/context.ts`:
- Around line 23-28: The code inserts raw result.stdout/result.stderr inside
triple-backtick fences in formatContextMessage which allows embedded ``` to
break the fence; fix by sanitizing fence delimiters before embedding: create or
use an escapeCodeFenceContent function and apply it to the outputs returned by
truncateContextOutput (i.e., replace occurrences of "```" with an escaped or
safe representation) and then use those escaped stdout/stderr when pushing the
fenced blocks in formatContextMessage so embedded backticks cannot terminate the
markdown fence.

In `@lib/shared/src/runner/index.ts`:
- Around line 64-68: The interactive branch currently calls
runInteractiveCommand(entry.command, resolvedCwd, ctx) without passing
entry.timeout, so interactive entries ignore configured timeouts; update the
call in the entry.interactive branch to pass the timeout (e.g.,
runInteractiveCommand(entry.command, resolvedCwd, ctx, entry.timeout) or
whatever the runInteractiveCommand signature expects), and ensure
runInteractiveCommand (and any helpers it uses) accept and honor that timeout
parameter so interactive and non-interactive pi.exec paths share the same
timeout behavior.

In `@lib/shared/src/runner/interactive.ts`:
- Around line 35-51: The interactive spawn path (spawn(...) creating child, and
the child.on("error") / child.on("exit") handlers in interactive.ts) lacks
timeout handling; add a timer when starting the child that, after the configured
timeout, kills the child process (first SIGTERM then SIGKILL if needed) and
calls finish with a timeout-specific CommandResult (e.g., code: 124 or a
distinct flag and stderr noting "timed out") to indicate timeout; ensure the
timer is cleared in both the "error" and "exit" handlers so normal completion
doesn't race with the timeout, and ensure child.kill is used safely (check
child.pid) to avoid orphaned processes.

In `@packages/pi-keymap/src/__tests__/config.test.ts`:
- Around line 5-8: Add a negative Jest test in
packages/pi-keymap/src/__tests__/config.test.ts that ensures decodeConfig (which
uses Schema.decodeUnknownSync with onExcessProperty: "error") rejects objects
with unknown keys: call decodeConfig with a valid minimal KeymapsConfigSchema
payload plus an extra unexpected property and assert it throws (e.g., expect(()
=> decodeConfig({...})).toThrow()) and optionally assert the error mentions the
excess property; reference decodeConfig, KeymapsConfigSchema and
Schema.decodeUnknownSync in the test.

In `@packages/pi-keymap/src/index.ts`:
- Around line 47-48: Avoid registering leader handlers when the configured
leader key is invalid: perform the leader validation before calling
registerLeaderKeymaps and only invoke registerLeaderKeymaps(leader, config, cwd,
pi, ctx) when that validation returns true (i.e., the leader config is usable);
leave registerDirectKeymaps(direct, cwd, pi, ctx) unchanged. Locate the existing
invalid-leader warning path and gate the call to registerLeaderKeymaps behind
its validation result so runtime leader handlers are not registered for invalid
configs.

---

Outside diff comments:
In `@lib/shared/src/config/test/merge.test.ts`:
- Around line 1-60: The test file is misplaced; move the test that targets
mergeSettings into the repository's __tests__ layout: relocate the file
containing the describe("mergeSettings", ...) block to an __tests__ directory
adjacent to the source module, keep the test contents (including the Bun import:
import { describe, expect, test } from "bun:test") unchanged, and update any
relative imports if the new location changes import paths for mergeSettings so
the tests still import mergeSettings correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4974703c-990a-4ea3-88e5-9db416ad565d

📥 Commits

Reviewing files that changed from the base of the PR and between df7aced and 9b0c9b7.

📒 Files selected for processing (25)
  • .changeset/maintainability-refactor.md
  • lib/shared/package.json
  • lib/shared/src/config/__tests__/config.test.ts
  • lib/shared/src/config/merge.ts
  • lib/shared/src/config/parse.ts
  • lib/shared/src/config/test/merge.test.ts
  • lib/shared/src/runner/config.ts
  • lib/shared/src/runner/context.ts
  • lib/shared/src/runner/index.ts
  • lib/shared/src/runner/interactive.ts
  • lib/shared/src/runner/renderer.ts
  • lib/shared/src/runner/spinner.ts
  • lib/shared/src/runner/types.ts
  • packages/pi-hooks/README.md
  • packages/pi-hooks/src/__tests__/config.test.ts
  • packages/pi-hooks/src/config.ts
  • packages/pi-hooks/src/index.ts
  • packages/pi-keymap/README.md
  • packages/pi-keymap/src/__tests__/config.test.ts
  • packages/pi-keymap/src/actions.ts
  • packages/pi-keymap/src/config.ts
  • packages/pi-keymap/src/index.ts
  • packages/pi-keymap/src/shortcuts.ts
  • packages/pi-keymap/src/validation.ts
  • scripts/generate-config-schemas.ts
💤 Files with no reviewable changes (1)
  • lib/shared/src/runner/renderer.ts

Comment thread lib/shared/src/runner/context.ts
Comment thread lib/shared/src/runner/index.ts
Comment thread lib/shared/src/runner/interactive.ts
Comment thread packages/pi-keymap/src/__tests__/config.test.ts
Comment thread packages/pi-keymap/src/index.ts Outdated
@Vahor
Vahor force-pushed the refactor/maintainability branch from 9b0c9b7 to 38d7e52 Compare May 23, 2026 14:27
@Vahor

Vahor commented May 23, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Vahor
Vahor merged commit 00e2ffc into main May 23, 2026
4 of 5 checks passed
@Vahor
Vahor deleted the refactor/maintainability branch May 23, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant