feat: add inject mode, repeat_every interval, and content-based dedup - #17
Open
aorizondo wants to merge 59 commits into
Open
feat: add inject mode, repeat_every interval, and content-based dedup#17aorizondo wants to merge 59 commits into
aorizondo wants to merge 59 commits into
Conversation
…types - Remove unused writeRuleFile function and writeFileSync import - Convert TestDirs, MockPluginInput interfaces to internal - Remove CI_ENV_VARS export (only used internally) - Remove dead message part builders (textPart, readToolPart, globToolPart, mockMessage) - Remove unused type exports (TextPart, ToolInvocationPart, MessagePart, MockMessage) Raises desloppify objective score to 95.8%.
…ices Consolidate 3 field reference tables into 1 unified table with Category column. Compress keyword selection from ~30 to ~18 lines. Trim examples from 6 to 4. Add Overview section and Common Mistakes section. Reorder sections per writing-skills template. Fix CSO description to remove workflow summary.
Remove card styling (background, border, padding) and palette abstraction. Add collapsible Project/Global sections with collapse-by-default behavior, bold 'Rules' header, and arrow toggle indicators matching MCP/LSP sections.
Filesystem-based IPC for TUI sidebar to know which rules are active. Provides atomic writes with per-session serialization and fire-and-forget API.
- Validate sessionId against /^[A-Za-z0-9_-]+$/ to prevent path traversal - Add proper type guard for ActiveRulesState with full type checks - Reject invalid sessionIds early with debug logging
- Change readAndFormatRules() return from string to FilterResult object - Add matchedPaths array tracking which rule files were included - Update runtime.ts to call writeActiveRulesState before early return - Re-export FilterResult from utils.ts - Update all test call sites to destructure new return type - Add tests verifying matchedPaths behavior
…fect - Test that matching rules populate matchedRulePaths in state file - Test that no-match case writes empty matchedPaths array - Test that missing sessionID skips state write - Use _setStateDirForTesting for test isolation
Use readdirSync to assert state directory has no .json files instead of only checking readActiveRulesState for a specific key.
- Add isActive (boolean | null) to SidebarRuleEntry for UI state display - Add hasEvaluationState to LoadSidebarRulesResult - Update loadSidebarRules() with optional sessionId parameter to read state - Extend TuiPluginApi type shim with TuiEventBus interface and event property - Add comprehensive tests for isActive behavior with/without state file
- Subscribe to message.updated and session.status events via TuiEventBus - Debounce 150ms before re-reading rules on events - Verify sessionId/projectDir match before committing async results - Separate initial-load effect (resets UI state) from refresh effect - Add hasEvaluationState prop to RuleSection for header count format - Green bullet for isActive === true, grey for false/null - Header count shows (active/total) when hasEvaluationState, else (total) - Unsubscribe from events on cleanup via onCleanup
Check event payload for sessionId property at receipt time. If the event has a sessionId that doesn't match the current session, skip it immediately rather than waiting for the post-load staleness check.
- Add monotonic requestId counter to detect out-of-order async completions
- Call setStatus('loaded') in loadRulesRefresh to recover from error state
- Clear debounceTimer on session/directory change to prevent stale events
OpenCode SDK events nest sessionID inside properties object with capital D (event.properties.sessionID), not event.sessionId. Also improves vendored TuiEventBus type to match real event structure.
…h, and state persistence - Add TUI sidebar to Features list - Add active-rules-state.ts to Project Structure and Key Module Responsibilities - Update rule-filter.ts description to mention FilterResult return type - Replace inaccurate [P]/[G] prefix claim with collapsible section groups - Document active/inactive indicators, sort-to-top, and event-driven refresh - Add State Persistence step to How It Works flow
Add OPENCODE_CONFIG_DIR as highest-priority source for global rules, followed by XDG_CONFIG_HOME, then ~/.config fallback.
TUI integration
fix: Handle OPENCODE_CONFIG_DIR
OpenCode's plugin loader now uses @npmcli/arborist for isolated installs, which does not resolve optional peer dependencies from the host. Moving @opentui/solid, @opentui/core, and solid-js to direct dependencies ensures the JSX runtime is available in the plugin's isolated node_modules directory.
Bun's module linker in OpenCode's TUI process treats the yaml CJS package as async. Static ESM imports, default imports, and createRequire all fail. Use await import() which is the only supported path for async CJS modules in Bun.
The ./tui export referenced raw source (./tui/index.tsx) which caused Bun's module resolver to fail on .js import specifiers that only exist in the dist directory.
…ions, and native bun publish
- Add rulesInjected and lastInjectedAt to SessionState - Skip injection if rulesInjected is true - Reset rulesInjected when new user prompt arrives - Add test cases for the new state tracking - All 145 tests pass
Update NOTEs to github markdown syntax for proper rendering.
- Inject mode (`inject: system | user | both`) to control injection target - `repeat_every` metadata for configurable user-prompt injection intervals - Content-based dedup: skip rule contents already present in system prompt - Raw mode: zero-header injection (no preamble, no [Reinforcement Instructions]) - Remove chunking: single-message user injection with synthetic flag - Track individual rule contents in FilterResult for accurate dedup - Update tests for raw-mode system prompt injection - Update README with new metadata fields and behavior docs
Owner
|
Please rebase this onto the dev branch. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds three complementary features to give users fine-grained control over how and when rules are injected into agent prompts.
Changes
injectmetadata field (system | user | both): Controls whether a rule is injected into the system prompt, prepended to user messages, or both. Defaults tosystemfor backward compatibility.repeat_everymetadata field: Configures the minimum number of user turns between user-prompt injections. Accepts a number or a model-pattern map ({ "gpt-4*": 3, "default": 1 }).raw: true— no preamble (# OpenCode Rules\n\nPlease follow...) or header ([Reinforcement Instructions]) is added. Only the stripped rule content is injected.synthetic: trueuser message.MAX_CHUNK_CHARSandsplitContentIntoChunks(dead code after single-message simplification).Testing
Documentation
injectandrepeat_everymetadata field docs