opencode-rules-md 0.6.5

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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +650 -0
  3. package/dist/cli.mjs +374 -0
  4. package/dist/src/active-rules-state.d.ts +12 -0
  5. package/dist/src/active-rules-state.d.ts.map +1 -0
  6. package/dist/src/active-rules-state.js +118 -0
  7. package/dist/src/active-rules-state.js.map +1 -0
  8. package/dist/src/cli/config.d.ts +62 -0
  9. package/dist/src/cli/config.d.ts.map +1 -0
  10. package/dist/src/cli/config.js +246 -0
  11. package/dist/src/cli/config.js.map +1 -0
  12. package/dist/src/cli/install.d.ts +21 -0
  13. package/dist/src/cli/install.d.ts.map +1 -0
  14. package/dist/src/cli/install.js +63 -0
  15. package/dist/src/cli/install.js.map +1 -0
  16. package/dist/src/cli/main.d.ts +19 -0
  17. package/dist/src/cli/main.d.ts.map +1 -0
  18. package/dist/src/cli/main.js +135 -0
  19. package/dist/src/cli/main.js.map +1 -0
  20. package/dist/src/cli/real-fs.d.ts +26 -0
  21. package/dist/src/cli/real-fs.d.ts.map +1 -0
  22. package/dist/src/cli/real-fs.js +42 -0
  23. package/dist/src/cli/real-fs.js.map +1 -0
  24. package/dist/src/cli/status.d.ts +19 -0
  25. package/dist/src/cli/status.d.ts.map +1 -0
  26. package/dist/src/cli/status.js +58 -0
  27. package/dist/src/cli/status.js.map +1 -0
  28. package/dist/src/debug.d.ts +3 -0
  29. package/dist/src/debug.d.ts.map +1 -0
  30. package/dist/src/debug.js +8 -0
  31. package/dist/src/debug.js.map +1 -0
  32. package/dist/src/git-branch.d.ts +2 -0
  33. package/dist/src/git-branch.d.ts.map +1 -0
  34. package/dist/src/git-branch.js +30 -0
  35. package/dist/src/git-branch.js.map +1 -0
  36. package/dist/src/index.d.ts +26 -0
  37. package/dist/src/index.d.ts.map +1 -0
  38. package/dist/src/index.js +55 -0
  39. package/dist/src/index.js.map +1 -0
  40. package/dist/src/mcp-tools.d.ts +8 -0
  41. package/dist/src/mcp-tools.d.ts.map +1 -0
  42. package/dist/src/mcp-tools.js +18 -0
  43. package/dist/src/mcp-tools.js.map +1 -0
  44. package/dist/src/message-context.d.ts +55 -0
  45. package/dist/src/message-context.d.ts.map +1 -0
  46. package/dist/src/message-context.js +110 -0
  47. package/dist/src/message-context.js.map +1 -0
  48. package/dist/src/message-paths.d.ts +34 -0
  49. package/dist/src/message-paths.d.ts.map +1 -0
  50. package/dist/src/message-paths.js +112 -0
  51. package/dist/src/message-paths.js.map +1 -0
  52. package/dist/src/project-fingerprint.d.ts +2 -0
  53. package/dist/src/project-fingerprint.d.ts.map +1 -0
  54. package/dist/src/project-fingerprint.js +61 -0
  55. package/dist/src/project-fingerprint.js.map +1 -0
  56. package/dist/src/rule-discovery.d.ts +49 -0
  57. package/dist/src/rule-discovery.d.ts.map +1 -0
  58. package/dist/src/rule-discovery.js +143 -0
  59. package/dist/src/rule-discovery.js.map +1 -0
  60. package/dist/src/rule-filter.d.ts +61 -0
  61. package/dist/src/rule-filter.d.ts.map +1 -0
  62. package/dist/src/rule-filter.js +180 -0
  63. package/dist/src/rule-filter.js.map +1 -0
  64. package/dist/src/rule-metadata.d.ts +29 -0
  65. package/dist/src/rule-metadata.d.ts.map +1 -0
  66. package/dist/src/rule-metadata.js +100 -0
  67. package/dist/src/rule-metadata.js.map +1 -0
  68. package/dist/src/runtime-chat.d.ts +34 -0
  69. package/dist/src/runtime-chat.d.ts.map +1 -0
  70. package/dist/src/runtime-chat.js +39 -0
  71. package/dist/src/runtime-chat.js.map +1 -0
  72. package/dist/src/runtime-context.d.ts +25 -0
  73. package/dist/src/runtime-context.d.ts.map +1 -0
  74. package/dist/src/runtime-context.js +109 -0
  75. package/dist/src/runtime-context.js.map +1 -0
  76. package/dist/src/runtime.d.ts +31 -0
  77. package/dist/src/runtime.d.ts.map +1 -0
  78. package/dist/src/runtime.js +238 -0
  79. package/dist/src/runtime.js.map +1 -0
  80. package/dist/src/session-store.d.ts +34 -0
  81. package/dist/src/session-store.d.ts.map +1 -0
  82. package/dist/src/session-store.js +90 -0
  83. package/dist/src/session-store.js.map +1 -0
  84. package/dist/src/utils.d.ts +15 -0
  85. package/dist/src/utils.d.ts.map +1 -0
  86. package/dist/src/utils.js +19 -0
  87. package/dist/src/utils.js.map +1 -0
  88. package/dist/tui/data/rules.d.ts +63 -0
  89. package/dist/tui/data/rules.d.ts.map +1 -0
  90. package/dist/tui/data/rules.js +173 -0
  91. package/dist/tui/data/rules.js.map +1 -0
  92. package/dist/tui/index.d.ts +8 -0
  93. package/dist/tui/index.d.ts.map +1 -0
  94. package/dist/tui/index.js +13 -0
  95. package/dist/tui/index.js.map +1 -0
  96. package/dist/tui/slots/sidebar-content.d.ts +11 -0
  97. package/dist/tui/slots/sidebar-content.d.ts.map +1 -0
  98. package/dist/tui/slots/sidebar-content.js +150 -0
  99. package/dist/tui/slots/sidebar-content.js.map +1 -0
  100. package/package.json +101 -0
  101. package/src/active-rules-state.ts +166 -0
  102. package/src/cli/config.ts +312 -0
  103. package/src/cli/install.ts +94 -0
  104. package/src/cli/main.ts +167 -0
  105. package/src/cli/real-fs.ts +65 -0
  106. package/src/cli/status.ts +80 -0
  107. package/src/debug.ts +9 -0
  108. package/src/git-branch.ts +37 -0
  109. package/src/index.ts +68 -0
  110. package/src/mcp-tools.ts +24 -0
  111. package/src/message-context.ts +139 -0
  112. package/src/message-paths.ts +153 -0
  113. package/src/project-fingerprint.ts +72 -0
  114. package/src/rule-discovery.ts +205 -0
  115. package/src/rule-filter.ts +269 -0
  116. package/src/rule-metadata.ts +161 -0
  117. package/src/runtime-chat.ts +68 -0
  118. package/src/runtime-context.ts +136 -0
  119. package/src/runtime.ts +369 -0
  120. package/src/session-store.ts +129 -0
  121. package/src/utils.ts +36 -0
  122. package/tui/.atl/.skill-registry.cache.json +3 -0
  123. package/tui/.atl/skill-registry.md +57 -0
  124. package/tui/data/rules.ts +230 -0
  125. package/tui/index.tsx +23 -0
  126. package/tui/slots/sidebar-content.tsx +364 -0
  127. package/tui/types/opencode-plugin-tui.d.ts +78 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/session-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Utility functions for OpenCode Rules Plugin
3
+ *
4
+ * This module serves as a compatibility facade that re-exports
5
+ * from focused modules:
6
+ * - rule-discovery.ts: File discovery and caching
7
+ * - rule-metadata.ts: Frontmatter parsing
8
+ * - rule-filter.ts: Rule filtering and formatting
9
+ * - message-paths.ts: Message path extraction
10
+ */
11
+ export { discoverRuleFiles, clearRuleCache, type DiscoveredRule, } from './rule-discovery.js';
12
+ export { parseRuleMetadata } from './rule-metadata.js';
13
+ export { promptMatchesKeywords, toolsMatchAvailable, readAndFormatRules, type RuleFilterContext, type FilterResult, } from './rule-filter.js';
14
+ export { extractFilePathsFromMessages, type Message, type MessagePart, } from './message-paths.js';
15
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,KAAK,cAAc,GACpB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGvD,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,YAAY,GAClB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,4BAA4B,EAC5B,KAAK,OAAO,EACZ,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Utility functions for OpenCode Rules Plugin
3
+ *
4
+ * This module serves as a compatibility facade that re-exports
5
+ * from focused modules:
6
+ * - rule-discovery.ts: File discovery and caching
7
+ * - rule-metadata.ts: Frontmatter parsing
8
+ * - rule-filter.ts: Rule filtering and formatting
9
+ * - message-paths.ts: Message path extraction
10
+ */
11
+ // Re-export from rule-discovery
12
+ export { discoverRuleFiles, clearRuleCache, } from './rule-discovery.js';
13
+ // Re-export from rule-metadata (RuleMetadata is internal, not re-exported)
14
+ export { parseRuleMetadata } from './rule-metadata.js';
15
+ // Re-export from rule-filter
16
+ export { promptMatchesKeywords, toolsMatchAvailable, readAndFormatRules, } from './rule-filter.js';
17
+ // Re-export from message-paths
18
+ export { extractFilePathsFromMessages, } from './message-paths.js';
19
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,gCAAgC;AAChC,OAAO,EACL,iBAAiB,EACjB,cAAc,GAEf,MAAM,qBAAqB,CAAC;AAE7B,2EAA2E;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,6BAA6B;AAC7B,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,GAGnB,MAAM,kBAAkB,CAAC;AAE1B,+BAA+B;AAC/B,OAAO,EACL,4BAA4B,GAG7B,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,63 @@
1
+ import type { RuleMetadata } from '../../src/rule-metadata';
2
+ /** Represents a rule as displayed in the sidebar */
3
+ export interface SidebarRuleEntry {
4
+ /** Display name (filename stem, disambiguated if needed) */
5
+ name: string;
6
+ /** Relative file path from the rules directory root */
7
+ path: string;
8
+ /** Whether this rule came from global or project-local rules dir */
9
+ source: 'global' | 'project';
10
+ /** Whether the rule has any conditional metadata */
11
+ isConditional: boolean;
12
+ /** Human-readable condition summary */
13
+ conditionSummary: string;
14
+ /** Full metadata for expanded view */
15
+ metadata: RuleMetadata;
16
+ /**
17
+ * Active state of the rule.
18
+ * - true: rule is active (matched by evaluation or unconditional without state file)
19
+ * - false: rule is not active (not matched by evaluation)
20
+ * - null: state not yet determined (conditional rule without state file)
21
+ */
22
+ isActive: boolean | null;
23
+ }
24
+ export interface LoadSidebarRulesResult {
25
+ rules: SidebarRuleEntry[];
26
+ skippedCount: number;
27
+ /** Whether active rules state was successfully read from disk */
28
+ hasEvaluationState: boolean;
29
+ }
30
+ /**
31
+ * Load all discovered rules formatted for sidebar display.
32
+ * Reuses discoverRuleFiles/getCachedRule from the server plugin.
33
+ *
34
+ * @param projectDir - Project directory or null (global rules only)
35
+ * @param sessionId - Optional session ID to read active rules state
36
+ */
37
+ export declare function loadSidebarRules(projectDir: string | null, sessionId?: string): Promise<LoadSidebarRulesResult>;
38
+ /**
39
+ * Determine if a rule file is project-local or global.
40
+ * Uses path.sep boundary check to avoid matching partial prefixes
41
+ * (e.g., /project/.opencode/rules-extra/ should not match).
42
+ */
43
+ export declare function ruleSource(filePath: string, projectDir: string | null): 'global' | 'project';
44
+ /**
45
+ * Check if metadata has any conditional fields set.
46
+ */
47
+ export declare function hasConditions(meta: RuleMetadata | undefined): boolean;
48
+ /**
49
+ * Build a human-readable, comma-separated summary of active conditions.
50
+ * E.g., "globs: src/*.ts, keywords: auth, security"
51
+ */
52
+ export declare function formatConditionSummary(meta: RuleMetadata): string;
53
+ /**
54
+ * Three-pass name disambiguation.
55
+ * Pass 1: Extract filename stem from each entry's path.
56
+ * Pass 2: For duplicate stems, prefix with parent directory.
57
+ * Pass 3: If still ambiguous (same parent or root-level), use full relative
58
+ * path (including extension) as the display name.
59
+ *
60
+ * Mutates entries[].name in place.
61
+ */
62
+ export declare function disambiguateNames(entries: SidebarRuleEntry[]): void;
63
+ //# sourceMappingURL=rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../tui/data/rules.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAI5D,oDAAoD;AACpD,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,oDAAoD;IACpD,aAAa,EAAE,OAAO,CAAC;IACvB,uCAAuC;IACvC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,QAAQ,EAAE,YAAY,CAAC;IACvB;;;;;OAKG;IACH,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,sBAAsB,CAAC,CAkEjC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,QAAQ,GAAG,SAAS,CAKtB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,OAAO,CAcrE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CA+BjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAmCnE"}
@@ -0,0 +1,173 @@
1
+ // tui/data/rules.ts
2
+ import { discoverRuleFiles, getCachedRule } from '../../src/rule-discovery';
3
+ import { readActiveRulesState } from '../../src/active-rules-state';
4
+ import path from 'path';
5
+ /**
6
+ * Load all discovered rules formatted for sidebar display.
7
+ * Reuses discoverRuleFiles/getCachedRule from the server plugin.
8
+ *
9
+ * @param projectDir - Project directory or null (global rules only)
10
+ * @param sessionId - Optional session ID to read active rules state
11
+ */
12
+ export async function loadSidebarRules(projectDir, sessionId) {
13
+ // discoverRuleFiles accepts string | undefined, not null
14
+ const discovered = await discoverRuleFiles(projectDir ?? undefined);
15
+ // Read active rules state if sessionId provided
16
+ const activeState = sessionId ? await readActiveRulesState(sessionId) : null;
17
+ const hasEvaluationState = activeState !== null;
18
+ const matchedPathsSet = hasEvaluationState
19
+ ? new Set(activeState.matchedRulePaths)
20
+ : null;
21
+ const entries = [];
22
+ let skippedCount = 0;
23
+ for (const rule of discovered) {
24
+ const cached = await getCachedRule(rule.filePath);
25
+ if (!cached) {
26
+ // getCachedRule() already logs a warning for read failures,
27
+ // so we only increment the counter here — no duplicate log.
28
+ skippedCount++;
29
+ continue;
30
+ }
31
+ const meta = cached.metadata;
32
+ const source = ruleSource(rule.filePath, projectDir);
33
+ const isConditional = hasConditions(meta);
34
+ const conditionSummary = isConditional
35
+ ? formatConditionSummary(meta)
36
+ : 'always active';
37
+ // Determine isActive based on state file or fallback logic
38
+ let isActive;
39
+ if (matchedPathsSet !== null) {
40
+ // With state file: check if this rule's absolute path is in matchedPaths
41
+ isActive = matchedPathsSet.has(rule.filePath);
42
+ }
43
+ else {
44
+ // Without state file: unconditional = true, conditional = null
45
+ isActive = isConditional ? null : true;
46
+ }
47
+ entries.push({
48
+ name: '', // placeholder — set in disambiguation pass
49
+ path: rule.relativePath,
50
+ source,
51
+ isConditional,
52
+ conditionSummary,
53
+ metadata: meta ?? {},
54
+ isActive,
55
+ });
56
+ }
57
+ disambiguateNames(entries);
58
+ // Sort: project first, then global. Active rules to top, then alpha by name.
59
+ const activeOrder = (v) => v === true ? 0 : v === null ? 1 : 2;
60
+ entries.sort((a, b) => {
61
+ if (a.source !== b.source)
62
+ return a.source === 'project' ? -1 : 1;
63
+ const activeCmp = activeOrder(a.isActive) - activeOrder(b.isActive);
64
+ if (activeCmp !== 0)
65
+ return activeCmp;
66
+ const nameCompare = a.name.localeCompare(b.name);
67
+ if (nameCompare !== 0)
68
+ return nameCompare;
69
+ return a.path.localeCompare(b.path);
70
+ });
71
+ return { rules: entries, skippedCount, hasEvaluationState };
72
+ }
73
+ /**
74
+ * Determine if a rule file is project-local or global.
75
+ * Uses path.sep boundary check to avoid matching partial prefixes
76
+ * (e.g., /project/.opencode/rules-extra/ should not match).
77
+ */
78
+ export function ruleSource(filePath, projectDir) {
79
+ if (!projectDir)
80
+ return 'global';
81
+ const projectRulesPrefix = path.join(projectDir, '.opencode', 'rules') + path.sep;
82
+ return filePath.startsWith(projectRulesPrefix) ? 'project' : 'global';
83
+ }
84
+ /**
85
+ * Check if metadata has any conditional fields set.
86
+ */
87
+ export function hasConditions(meta) {
88
+ if (!meta)
89
+ return false;
90
+ return !!(meta.globs ||
91
+ meta.keywords ||
92
+ meta.tools ||
93
+ meta.model ||
94
+ meta.agent ||
95
+ meta.command ||
96
+ meta.project ||
97
+ meta.branch ||
98
+ meta.os ||
99
+ meta.ci !== undefined);
100
+ }
101
+ /**
102
+ * Build a human-readable, comma-separated summary of active conditions.
103
+ * E.g., "globs: src/*.ts, keywords: auth, security"
104
+ */
105
+ export function formatConditionSummary(meta) {
106
+ const parts = [];
107
+ const arrayFields = [
108
+ ['globs', 'globs'],
109
+ ['keywords', 'keywords'],
110
+ ['tools', 'tools'],
111
+ ['model', 'model'],
112
+ ['agent', 'agent'],
113
+ ['command', 'command'],
114
+ ['project', 'project'],
115
+ ['branch', 'branch'],
116
+ ['os', 'os'],
117
+ ];
118
+ for (const [field, label] of arrayFields) {
119
+ const value = meta[field];
120
+ if (Array.isArray(value) && value.length > 0) {
121
+ parts.push(`${label}: ${value.join(', ')}`);
122
+ }
123
+ }
124
+ if (meta.ci !== undefined) {
125
+ parts.push(`ci: ${String(meta.ci)}`);
126
+ }
127
+ if (meta.match) {
128
+ parts.push(`match: ${meta.match}`);
129
+ }
130
+ return parts.join(', ');
131
+ }
132
+ /**
133
+ * Three-pass name disambiguation.
134
+ * Pass 1: Extract filename stem from each entry's path.
135
+ * Pass 2: For duplicate stems, prefix with parent directory.
136
+ * Pass 3: If still ambiguous (same parent or root-level), use full relative
137
+ * path (including extension) as the display name.
138
+ *
139
+ * Mutates entries[].name in place.
140
+ */
141
+ export function disambiguateNames(entries) {
142
+ // Pass 1: assign stem names (filename without extension, using last dot)
143
+ for (const entry of entries) {
144
+ const basename = path.basename(entry.path);
145
+ const dotIndex = basename.lastIndexOf('.');
146
+ entry.name = dotIndex > 0 ? basename.substring(0, dotIndex) : basename;
147
+ }
148
+ // Pass 2: detect and resolve collisions with parent directory prefix
149
+ const stemCounts = new Map();
150
+ for (const entry of entries) {
151
+ stemCounts.set(entry.name, (stemCounts.get(entry.name) ?? 0) + 1);
152
+ }
153
+ for (const entry of entries) {
154
+ if ((stemCounts.get(entry.name) ?? 0) <= 1)
155
+ continue;
156
+ const dir = path.dirname(entry.path);
157
+ if (dir && dir !== '.') {
158
+ const parent = path.basename(dir);
159
+ entry.name = `${parent}/${entry.name}`;
160
+ }
161
+ }
162
+ // Pass 3: if still ambiguous, use full relative path WITH extension
163
+ const nameCounts = new Map();
164
+ for (const entry of entries) {
165
+ nameCounts.set(entry.name, (nameCounts.get(entry.name) ?? 0) + 1);
166
+ }
167
+ for (const entry of entries) {
168
+ if ((nameCounts.get(entry.name) ?? 0) > 1) {
169
+ entry.name = entry.path;
170
+ }
171
+ }
172
+ }
173
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../tui/data/rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /** @jsxImportSource @opentui/solid */
2
+ import type { TuiPlugin } from '@opencode-ai/plugin/tui';
3
+ declare const _default: {
4
+ id: "opencode-rules-md";
5
+ tui: TuiPlugin;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../tui/index.tsx"],"names":[],"mappings":"AACA,sCAAsC;AACtC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;;;;;AAoBzD,wBAA2B"}
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "@opentui/solid/jsx-runtime";
2
+ import { SidebarContent } from './slots/sidebar-content';
3
+ const id = 'opencode-rules-md';
4
+ const tui = async (api) => {
5
+ api.slots.register({
6
+ order: 350,
7
+ slots: {
8
+ sidebar_content: (ctx, props) => (_jsx(SidebarContent, { sessionId: props.session_id, api: api, theme: ctx.theme })),
9
+ },
10
+ });
11
+ };
12
+ export default { id, tui };
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../tui/index.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,MAAM,EAAE,GAAG,mBAA4B,CAAC;AAExC,MAAM,GAAG,GAAc,KAAK,EAAC,GAAG,EAAC,EAAE;IACjC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;QACjB,KAAK,EAAE,GAAG;QACV,KAAK,EAAE;YACL,eAAe,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAC/B,KAAC,cAAc,IACb,SAAS,EAAE,KAAK,CAAC,UAAU,EAC3B,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,GAAG,CAAC,KAAK,GAChB,CACH;SACF;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,eAAe,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ /** @jsxImportSource @opentui/solid */
2
+ import { type JSX } from 'solid-js';
3
+ import type { TuiPluginApi, TuiTheme } from '@opencode-ai/plugin/tui';
4
+ interface SidebarContentProps {
5
+ sessionId: string;
6
+ api: TuiPluginApi;
7
+ theme: TuiTheme;
8
+ }
9
+ export declare function SidebarContent(props: SidebarContentProps): JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=sidebar-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidebar-content.d.ts","sourceRoot":"","sources":["../../../tui/slots/sidebar-content.tsx"],"names":[],"mappings":"AACA,sCAAsC;AACtC,OAAO,EAOL,KAAK,GAAG,EACT,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGtE,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,YAAY,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAyID,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,GAAG,CAAC,OAAO,CAgNtE"}
@@ -0,0 +1,150 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@opentui/solid/jsx-runtime";
2
+ // tui/slots/sidebar-content.tsx
3
+ /** @jsxImportSource @opentui/solid */
4
+ import { createSignal, createEffect, createMemo, onCleanup, Show, For, } from 'solid-js';
5
+ import { loadSidebarRules } from '../data/rules';
6
+ function RuleSection(props) {
7
+ const activeCount = createMemo(() => props.rules.filter(r => r.isActive === true).length);
8
+ const headerCount = createMemo(() => {
9
+ if (props.hasEvaluationState) {
10
+ return `(${activeCount()}/${props.rules.length})`;
11
+ }
12
+ return `(${props.rules.length})`;
13
+ });
14
+ const bulletColor = (rule) => {
15
+ return rule.isActive === true ? props.theme.success : props.theme.textMuted;
16
+ };
17
+ return (_jsx(Show, { when: props.rules.length > 0, children: _jsxs("box", { children: [_jsxs("box", { flexDirection: "row", gap: 1, onMouseDown: () => props.onToggle(), children: [_jsx("text", { fg: props.theme.text, children: props.open ? '▼' : '▶' }), _jsxs("text", { fg: props.theme.text, children: [props.title, _jsx(Show, { when: !props.open, children: _jsxs("span", { style: { fg: props.theme.textMuted }, children: [' ', headerCount()] }) })] })] }), _jsx(Show, { when: props.open, children: _jsx(For, { each: props.rules, children: (rule, localIndex) => {
18
+ const globalIndex = () => props.globalOffset + localIndex();
19
+ return (_jsxs("box", { flexDirection: "column", onMouseDown: () => props.onExpandToggle(globalIndex()), children: [_jsxs("box", { flexDirection: "row", gap: 1, children: [_jsx("text", { fg: bulletColor(rule), children: "\u2022" }), _jsx("text", { fg: props.theme.text, children: rule.name })] }), _jsx(Show, { when: props.expandedIndex === globalIndex(), children: _jsxs("box", { flexDirection: "column", paddingLeft: 4, children: [_jsx("text", { fg: props.theme.textMuted, children: rule.path }), _jsx(Show, { when: (rule.metadata.globs?.length ?? 0) > 0, children: _jsxs("text", { fg: props.theme.textMuted, children: ["Globs: ", rule.metadata.globs.join(', ')] }) }), _jsx(Show, { when: (rule.metadata.keywords?.length ?? 0) > 0, children: _jsxs("text", { fg: props.theme.textMuted, children: ["Keywords: ", rule.metadata.keywords.join(', ')] }) }), _jsx(Show, { when: (rule.metadata.tools?.length ?? 0) > 0, children: _jsxs("text", { fg: props.theme.textMuted, children: ["Tools: ", rule.metadata.tools.join(', ')] }) }), _jsx(Show, { when: (rule.metadata.model?.length ?? 0) > 0, children: _jsxs("text", { fg: props.theme.textMuted, children: ["Model: ", rule.metadata.model.join(', ')] }) }), _jsx(Show, { when: (rule.metadata.agent?.length ?? 0) > 0, children: _jsxs("text", { fg: props.theme.textMuted, children: ["Agent: ", rule.metadata.agent.join(', ')] }) }), _jsx(Show, { when: (rule.metadata.command?.length ?? 0) > 0, children: _jsxs("text", { fg: props.theme.textMuted, children: ["Command: ", rule.metadata.command.join(', ')] }) }), _jsx(Show, { when: (rule.metadata.project?.length ?? 0) > 0, children: _jsxs("text", { fg: props.theme.textMuted, children: ["Project: ", rule.metadata.project.join(', ')] }) }), _jsx(Show, { when: (rule.metadata.branch?.length ?? 0) > 0, children: _jsxs("text", { fg: props.theme.textMuted, children: ["Branch: ", rule.metadata.branch.join(', ')] }) }), _jsx(Show, { when: (rule.metadata.os?.length ?? 0) > 0, children: _jsxs("text", { fg: props.theme.textMuted, children: ["OS: ", rule.metadata.os.join(', ')] }) }), _jsx(Show, { when: rule.metadata.ci !== undefined, children: _jsxs("text", { fg: props.theme.textMuted, children: ["CI: ", String(rule.metadata.ci)] }) }), _jsx(Show, { when: rule.metadata.match, children: _jsxs("text", { fg: props.theme.textMuted, children: ["Match: ", rule.metadata.match] }) })] }) })] }));
20
+ } }) })] }) }));
21
+ }
22
+ export function SidebarContent(props) {
23
+ const [rules, setRules] = createSignal([]);
24
+ const [status, setStatus] = createSignal('loading');
25
+ const [skippedCount, setSkippedCount] = createSignal(0);
26
+ const [hasEvaluationState, setHasEvaluationState] = createSignal(false);
27
+ const [expandedIndex, setExpandedIndex] = createSignal(null);
28
+ const [lastDir, setLastDir] = createSignal(undefined);
29
+ const [lastSessionId, setLastSessionId] = createSignal(undefined);
30
+ const [projectOpen, setProjectOpen] = createSignal(false);
31
+ const [globalOpen, setGlobalOpen] = createSignal(false);
32
+ const [refreshCounter, setRefreshCounter] = createSignal(0);
33
+ const theme = () => props.theme.current;
34
+ const resolveProjectDir = () => {
35
+ return props.api.state.path.directory ?? null;
36
+ };
37
+ // Monotonic counter to detect stale async results
38
+ let requestId = 0;
39
+ // Debounce timer for event-driven refresh
40
+ let debounceTimer = null;
41
+ // Initial load: triggered by session/directory change, resets all UI state
42
+ const loadRulesInitial = async () => {
43
+ const thisRequest = ++requestId;
44
+ const dir = resolveProjectDir();
45
+ const sessionId = props.sessionId;
46
+ setLastDir(dir);
47
+ setLastSessionId(sessionId);
48
+ setStatus('loading');
49
+ try {
50
+ const result = await loadSidebarRules(dir, sessionId);
51
+ // Discard if a newer request started
52
+ if (requestId !== thisRequest)
53
+ return;
54
+ setRules(result.rules);
55
+ setSkippedCount(result.skippedCount);
56
+ setHasEvaluationState(result.hasEvaluationState);
57
+ setStatus('loaded');
58
+ }
59
+ catch (err) {
60
+ // Discard if a newer request started
61
+ if (requestId !== thisRequest)
62
+ return;
63
+ console.error('[opencode-rules-md] Failed to load rules:', err);
64
+ setStatus('error');
65
+ }
66
+ };
67
+ // Refresh load: triggered by events, only updates rule data (no UI state reset)
68
+ const loadRulesRefresh = async () => {
69
+ // Skip refresh if initial load is still in flight
70
+ if (status() === 'loading')
71
+ return;
72
+ const thisRequest = ++requestId;
73
+ const dir = resolveProjectDir();
74
+ const sessionId = props.sessionId;
75
+ try {
76
+ const result = await loadSidebarRules(dir, sessionId);
77
+ // Discard if a newer request started
78
+ if (requestId !== thisRequest)
79
+ return;
80
+ setRules(result.rules);
81
+ setSkippedCount(result.skippedCount);
82
+ setHasEvaluationState(result.hasEvaluationState);
83
+ setStatus('loaded');
84
+ }
85
+ catch (err) {
86
+ // Discard if a newer request started
87
+ if (requestId !== thisRequest)
88
+ return;
89
+ console.error('[opencode-rules-md] Failed to refresh rules:', err);
90
+ }
91
+ };
92
+ // Effect 1: Initial load on session/directory change
93
+ createEffect(() => {
94
+ const currentSessionId = props.sessionId;
95
+ const currentDir = resolveProjectDir();
96
+ // Check if session or directory changed
97
+ if (currentSessionId !== lastSessionId() || currentDir !== lastDir()) {
98
+ // Clear pending debounce from previous session
99
+ if (debounceTimer !== null) {
100
+ clearTimeout(debounceTimer);
101
+ debounceTimer = null;
102
+ }
103
+ // Reset UI state on session/directory change
104
+ setExpandedIndex(null);
105
+ setProjectOpen(false);
106
+ setGlobalOpen(false);
107
+ void loadRulesInitial();
108
+ }
109
+ });
110
+ // Effect 2: Refresh on event-driven updates (refreshCounter changes)
111
+ createEffect(() => {
112
+ const counter = refreshCounter();
113
+ if (counter > 0) {
114
+ void loadRulesRefresh();
115
+ }
116
+ });
117
+ // Subscribe to OpenCode events with debounce
118
+ const triggerRefresh = (event) => {
119
+ // Filter events to current sessionId before debouncing
120
+ // OpenCode SDK events nest sessionID inside properties: { type, properties: { sessionID, ... } }
121
+ const eventSessionID = event.properties.sessionID;
122
+ if (typeof eventSessionID === 'string' &&
123
+ eventSessionID !== props.sessionId) {
124
+ return;
125
+ }
126
+ if (debounceTimer !== null) {
127
+ clearTimeout(debounceTimer);
128
+ }
129
+ debounceTimer = setTimeout(() => {
130
+ debounceTimer = null;
131
+ setRefreshCounter(c => c + 1);
132
+ }, 150);
133
+ };
134
+ const unsubMessageUpdated = props.api.event.on('message.updated', triggerRefresh);
135
+ const unsubSessionStatus = props.api.event.on('session.status', triggerRefresh);
136
+ onCleanup(() => {
137
+ if (debounceTimer !== null) {
138
+ clearTimeout(debounceTimer);
139
+ }
140
+ unsubMessageUpdated();
141
+ unsubSessionStatus();
142
+ });
143
+ const toggleExpand = (index) => {
144
+ setExpandedIndex(prev => (prev === index ? null : index));
145
+ };
146
+ const projectRules = createMemo(() => rules().filter(r => r.source === 'project'));
147
+ const globalRules = createMemo(() => rules().filter(r => r.source === 'global'));
148
+ return (_jsxs("box", { children: [_jsx("text", { fg: theme().text, children: _jsx("b", { children: "Rules" }) }), _jsx(Show, { when: status() === 'loading', children: _jsx("text", { fg: theme().textMuted, children: "Loading..." }) }), _jsx(Show, { when: status() === 'error', children: _jsx("text", { fg: theme().textMuted, children: "Failed to load rules" }) }), _jsxs(Show, { when: status() === 'loaded', children: [_jsxs(Show, { when: rules().length > 0, fallback: _jsx("text", { fg: theme().textMuted, children: "No rules found" }), children: [_jsx(RuleSection, { title: "Project", rules: projectRules(), theme: theme(), open: projectOpen(), onToggle: () => setProjectOpen(x => !x), expandedIndex: expandedIndex(), globalOffset: 0, onExpandToggle: toggleExpand, hasEvaluationState: hasEvaluationState() }), _jsx(RuleSection, { title: "Global", rules: globalRules(), theme: theme(), open: globalOpen(), onToggle: () => setGlobalOpen(x => !x), expandedIndex: expandedIndex(), globalOffset: projectRules().length, onExpandToggle: toggleExpand, hasEvaluationState: hasEvaluationState() })] }), _jsx(Show, { when: skippedCount() > 0, children: _jsxs("text", { fg: theme().textMuted, children: [skippedCount(), " rules skipped (unreadable)"] }) })] })] }));
149
+ }
150
+ //# sourceMappingURL=sidebar-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidebar-content.js","sourceRoot":"","sources":["../../../tui/slots/sidebar-content.tsx"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,101 @@
1
+ {
2
+ "name": "opencode-rules-md",
3
+ "version": "0.6.5",
4
+ "description": "OpenCode plugin that discovers and injects markdown rules into system prompts",
5
+ "main": "dist/src/index.js",
6
+ "types": "dist/src/index.d.ts",
7
+ "type": "module",
8
+ "bin": {
9
+ "opencode-rules-md": "./dist/cli.mjs"
10
+ },
11
+ "oc-plugin": [
12
+ "server",
13
+ "tui"
14
+ ],
15
+ "keywords": [
16
+ "opencode",
17
+ "plugin",
18
+ "rules",
19
+ "system-prompt",
20
+ "typescript"
21
+ ],
22
+ "author": "MetalbolicX",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/MetalbolicX/opencode-rules-md.git"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/MetalbolicX/opencode-rules-md/issues"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "!dist/**/*.test.*",
34
+ "!dist/**/*.spec.*",
35
+ "!dist/**/test-fixtures.*",
36
+ "!dist/**/api-surface.typecheck.*",
37
+ "src/",
38
+ "!src/**/*.test.ts",
39
+ "!src/**/*.spec.ts",
40
+ "!src/test-fixtures.ts",
41
+ "!src/api-surface.typecheck.ts",
42
+ "tui/",
43
+ "!tui/**/*.test.ts",
44
+ "!tui/**/*.test.tsx",
45
+ "!tui/**/*.spec.ts",
46
+ "!tui/**/*.spec.tsx",
47
+ "README.md",
48
+ "LICENSE"
49
+ ],
50
+ "exports": {
51
+ ".": {
52
+ "types": "./dist/src/index.d.ts",
53
+ "import": "./dist/src/index.js"
54
+ },
55
+ "./tui": {
56
+ "types": "./dist/tui/index.d.ts",
57
+ "import": "./tui/index.tsx"
58
+ },
59
+ "./cli": {
60
+ "types": "./dist/cli/main.d.ts",
61
+ "import": "./dist/cli.mjs"
62
+ }
63
+ },
64
+ "peerDependencies": {
65
+ "@opencode-ai/plugin": "^1.3.9",
66
+ "@opencode-ai/sdk": "^1.3.9"
67
+ },
68
+ "devDependencies": {
69
+ "@opencode-ai/plugin": "^1.3.9",
70
+ "@opencode-ai/sdk": "^1.3.9",
71
+ "@opentui/core": "^0.4.3",
72
+ "@opentui/solid": "^0.4.3",
73
+ "@types/minimatch": "^5.1.2",
74
+ "@types/node": "^20.19.30",
75
+ "@typescript-eslint/eslint-plugin": "^8.63.0",
76
+ "@typescript-eslint/parser": "^8.63.0",
77
+ "eslint": "^10.6.0",
78
+ "prettier": "^3.8.1",
79
+ "solid-js": "1.9.14",
80
+ "typescript": "^5.9.3",
81
+ "vitest": "^2.1.8"
82
+ },
83
+ "dependencies": {
84
+ "@opentui/core": "^0.4.3",
85
+ "@opentui/solid": "^0.4.3",
86
+ "minimatch": "^9.0.5",
87
+ "solid-js": "1.9.14",
88
+ "yaml": "^2.8.2"
89
+ },
90
+ "scripts": {
91
+ "build": "tsc && bun run build:cli",
92
+ "build:cli": "bun build src/cli/main.ts --outfile dist/cli.mjs --target node",
93
+ "dev": "tsc --watch",
94
+ "test": "vitest",
95
+ "test:run": "vitest run",
96
+ "lint": "eslint src tui",
97
+ "format": "prettier --write 'src/**/*.ts' 'tui/**/*.tsx' 'tui/**/*.ts'",
98
+ "format:check": "prettier --check 'src/**/*.ts' 'tui/**/*.tsx' 'tui/**/*.ts'",
99
+ "clean": "rm -rf dist"
100
+ }
101
+ }