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":"rule-metadata.js","sourceRoot":"","sources":["../../src/rule-metadata.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;AAgDlD;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,KAAc;IACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,MAAM,GAAG,KAAK;SACjB,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;SACjD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SAClB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,2CAA2C;IAC3C,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,+BAA+B;IAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACH,oCAAoC;QACpC,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,CAA6B,CAAC;QAClE,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1C,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAElC,8CAA8C;QAC9C,MAAM,WAAW,GAAuB;YACtC,OAAO;YACP,UAAU;YACV,OAAO;YACP,OAAO;YACP,OAAO;YACP,SAAS;YACT,SAAS;YACT,QAAQ;YACR,IAAI;SACL,CAAC;QAEF,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;YAChC,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACpD,IAAI,SAAS,EAAE,CAAC;gBACd,QAAQ,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;YAC9B,CAAC;QACH,CAAC;QAED,gDAAgD;QAChD,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YACnC,QAAQ,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;QAC1B,CAAC;QAED,kDAAkD;QAClD,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YACrD,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAChC,CAAC;QAED,yCAAyC;QACzC,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,sCAAsC;QACtC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CACV,kEAAkE,OAAO,EAAE,CAC5E,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,2CAA2C;IAC3C,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC3C,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,oEAAoE;IACpE,OAAO,OAAO,CAAC,SAAS,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AACrD,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { SessionStore } from './session-store.js';
2
+ import type { DebugLog } from './debug.js';
3
+ export interface ChatMessageInput {
4
+ sessionID?: string;
5
+ model?: {
6
+ modelID?: string;
7
+ };
8
+ agent?: string;
9
+ }
10
+ export interface ChatMessageOutput {
11
+ message?: {
12
+ role?: string;
13
+ };
14
+ parts?: Array<{
15
+ type?: string;
16
+ text?: string;
17
+ synthetic?: boolean;
18
+ }>;
19
+ }
20
+ /**
21
+ * Extract user prompt text from chat message parts.
22
+ * Returns empty string if no text parts found.
23
+ */
24
+ export declare function extractUserPromptFromParts(parts: Array<{
25
+ type?: string;
26
+ text?: string;
27
+ synthetic?: boolean;
28
+ }> | undefined): string;
29
+ /**
30
+ * Handle incoming chat messages to update session state.
31
+ * Captures user prompts, model IDs, and agent types.
32
+ */
33
+ export declare function handleChatMessage(input: ChatMessageInput, output: ChatMessageOutput, sessionStore: SessionStore, debugLog: DebugLog): void;
34
+ //# sourceMappingURL=runtime-chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-chat.d.ts","sourceRoot":"","sources":["../../src/runtime-chat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACtE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EACD,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAC5D,SAAS,GACZ,MAAM,CAGR;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,gBAAgB,EACvB,MAAM,EAAE,iBAAiB,EACzB,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,QAAQ,GACjB,IAAI,CA8BN"}
@@ -0,0 +1,39 @@
1
+ import { extractTextFromParts } from './message-context.js';
2
+ /**
3
+ * Extract user prompt text from chat message parts.
4
+ * Returns empty string if no text parts found.
5
+ */
6
+ export function extractUserPromptFromParts(parts) {
7
+ if (!parts)
8
+ return '';
9
+ return extractTextFromParts(parts);
10
+ }
11
+ /**
12
+ * Handle incoming chat messages to update session state.
13
+ * Captures user prompts, model IDs, and agent types.
14
+ */
15
+ export function handleChatMessage(input, output, sessionStore, debugLog) {
16
+ const sessionID = input?.sessionID;
17
+ if (!sessionID) {
18
+ debugLog('No sessionID in chat.message hook input');
19
+ return;
20
+ }
21
+ if (output?.message?.role !== 'user') {
22
+ return;
23
+ }
24
+ const userPrompt = extractUserPromptFromParts(output.parts);
25
+ sessionStore.upsert(sessionID, state => {
26
+ if (userPrompt) {
27
+ state.lastUserPrompt = userPrompt;
28
+ state.rulesInjected = false;
29
+ }
30
+ if (input.model?.modelID) {
31
+ state.lastModelID = input.model.modelID;
32
+ }
33
+ if (input.agent) {
34
+ state.lastAgentType = input.agent;
35
+ }
36
+ });
37
+ debugLog(`Updated session ${sessionID} from chat.message (model=${input.model?.modelID ?? 'none'}, agent=${input.agent ?? 'none'})`);
38
+ }
39
+ //# sourceMappingURL=runtime-chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-chat.js","sourceRoot":"","sources":["../../src/runtime-chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAe5D;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CACxC,KAEa;IAEb,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,oBAAoB,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAuB,EACvB,MAAyB,EACzB,YAA0B,EAC1B,QAAkB;IAElB,MAAM,SAAS,GAAG,KAAK,EAAE,SAAS,CAAC;IACnC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,QAAQ,CAAC,yCAAyC,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,IAAI,MAAM,EAAE,OAAO,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;QACrC,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,0BAA0B,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE5D,YAAY,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE;QACrC,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,CAAC,cAAc,GAAG,UAAU,CAAC;YAClC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC;QAC9B,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;YACzB,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;QAC1C,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,QAAQ,CACN,mBAAmB,SAAS,6BAA6B,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,MAAM,WAAW,KAAK,CAAC,KAAK,IAAI,MAAM,GAAG,CAC3H,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { RuleFilterContext } from './rule-filter.js';
2
+ import type { DebugLog } from './debug.js';
3
+ export interface BuildFilterContextOptions {
4
+ contextFilePaths: string[];
5
+ userPrompt: string | undefined;
6
+ availableToolIDs: string[];
7
+ modelID: string | undefined;
8
+ agentType: string | undefined;
9
+ }
10
+ /**
11
+ * Detect if running in a CI environment by checking common CI environment variables.
12
+ *
13
+ * If process.env.CI is explicitly set, it is treated as authoritative:
14
+ * - CI='false' or CI='0' or CI='' => return false (no provider var fallback)
15
+ * - CI='true' or CI='1' or any truthy value => return true
16
+ *
17
+ * If process.env.CI is not set (undefined), fall back to provider-specific detection.
18
+ */
19
+ export declare function detectCiEnvironment(): boolean;
20
+ /**
21
+ * Build the filter context object used for rule matching.
22
+ * Assembles runtime information from various sources.
23
+ */
24
+ export declare function buildFilterContext(opts: BuildFilterContextOptions, projectDirectory: string, debugLog: DebugLog): Promise<RuleFilterContext>;
25
+ //# sourceMappingURL=runtime-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-context.d.ts","sourceRoot":"","sources":["../../src/runtime-context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,yBAAyB;IACxC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAsBD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAmB7C;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,yBAAyB,EAC/B,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,iBAAiB,CAAC,CA+D5B"}
@@ -0,0 +1,109 @@
1
+ import { extractSlashCommand } from './message-context.js';
2
+ import { detectProjectTags } from './project-fingerprint.js';
3
+ import { getGitBranch } from './git-branch.js';
4
+ /**
5
+ * Parse an env variable value semantically: 'false', '0', '' => false; other non-empty => true.
6
+ * Returns undefined if the variable is not set.
7
+ */
8
+ function parseEnvBoolean(value) {
9
+ if (value === undefined)
10
+ return undefined;
11
+ if (value === '')
12
+ return false;
13
+ const lower = value.toLowerCase();
14
+ if (lower === 'false' || lower === '0')
15
+ return false;
16
+ return true;
17
+ }
18
+ /**
19
+ * Check if a string value represents a truthy CI environment variable.
20
+ * Treats 'false', '0', and empty strings as falsy; other non-empty values as truthy.
21
+ */
22
+ function isTruthyEnvValue(value) {
23
+ return parseEnvBoolean(value) === true;
24
+ }
25
+ /**
26
+ * Detect if running in a CI environment by checking common CI environment variables.
27
+ *
28
+ * If process.env.CI is explicitly set, it is treated as authoritative:
29
+ * - CI='false' or CI='0' or CI='' => return false (no provider var fallback)
30
+ * - CI='true' or CI='1' or any truthy value => return true
31
+ *
32
+ * If process.env.CI is not set (undefined), fall back to provider-specific detection.
33
+ */
34
+ export function detectCiEnvironment() {
35
+ const env = process.env;
36
+ const ciExplicit = parseEnvBoolean(env.CI);
37
+ if (ciExplicit !== undefined) {
38
+ return ciExplicit;
39
+ }
40
+ return (isTruthyEnvValue(env.CONTINUOUS_INTEGRATION) ||
41
+ isTruthyEnvValue(env.BUILD_NUMBER) ||
42
+ isTruthyEnvValue(env.GITHUB_ACTIONS) ||
43
+ isTruthyEnvValue(env.GITLAB_CI) ||
44
+ isTruthyEnvValue(env.CIRCLECI) ||
45
+ isTruthyEnvValue(env.TRAVIS) ||
46
+ isTruthyEnvValue(env.JENKINS_URL) ||
47
+ isTruthyEnvValue(env.BUILDKITE) ||
48
+ isTruthyEnvValue(env.TEAMCITY_VERSION));
49
+ }
50
+ /**
51
+ * Build the filter context object used for rule matching.
52
+ * Assembles runtime information from various sources.
53
+ */
54
+ export async function buildFilterContext(opts, projectDirectory, debugLog) {
55
+ const { contextFilePaths, userPrompt, availableToolIDs, modelID, agentType } = opts;
56
+ const command = extractSlashCommand(userPrompt);
57
+ let projectTags;
58
+ try {
59
+ projectTags = await detectProjectTags(projectDirectory);
60
+ if (projectTags.length === 0) {
61
+ projectTags = undefined;
62
+ }
63
+ }
64
+ catch {
65
+ projectTags = undefined;
66
+ }
67
+ let gitBranch;
68
+ try {
69
+ gitBranch = await getGitBranch(projectDirectory);
70
+ }
71
+ catch {
72
+ gitBranch = undefined;
73
+ }
74
+ const os = process.platform;
75
+ const ci = detectCiEnvironment();
76
+ const context = {
77
+ os,
78
+ ci,
79
+ };
80
+ if (contextFilePaths.length > 0) {
81
+ context.contextFilePaths = contextFilePaths;
82
+ }
83
+ if (userPrompt !== undefined) {
84
+ context.userPrompt = userPrompt;
85
+ }
86
+ if (availableToolIDs.length > 0) {
87
+ context.availableToolIDs = availableToolIDs;
88
+ }
89
+ if (modelID !== undefined) {
90
+ context.modelID = modelID;
91
+ }
92
+ if (agentType !== undefined) {
93
+ context.agentType = agentType;
94
+ }
95
+ if (command !== undefined) {
96
+ context.command = command;
97
+ }
98
+ if (projectTags !== undefined) {
99
+ context.projectTags = projectTags;
100
+ }
101
+ if (gitBranch !== undefined) {
102
+ context.gitBranch = gitBranch;
103
+ }
104
+ debugLog(`Filter context: model=${modelID ?? 'none'}, agent=${agentType ?? 'none'}, ` +
105
+ `command=${command ?? 'none'}, branch=${gitBranch ?? 'none'}, ` +
106
+ `os=${os}, ci=${ci}, projectTags=${projectTags?.join(',') ?? 'none'}`);
107
+ return context;
108
+ }
109
+ //# sourceMappingURL=runtime-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-context.js","sourceRoot":"","sources":["../../src/runtime-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type DiscoveredRule } from './rule-discovery.js';
2
+ import { type DebugLog } from './debug.js';
3
+ import type { SessionStore } from './session-store.js';
4
+ interface OpenCodeRulesRuntimeOptions {
5
+ client: unknown;
6
+ directory: string;
7
+ projectDirectory: string;
8
+ ruleFiles: DiscoveredRule[];
9
+ sessionStore: SessionStore;
10
+ debugLog?: DebugLog;
11
+ now?: () => number;
12
+ }
13
+ export declare class OpenCodeRulesRuntime {
14
+ private client;
15
+ private directory;
16
+ private projectDirectory;
17
+ private ruleFiles;
18
+ private sessionStore;
19
+ private debugLog;
20
+ private now;
21
+ constructor(opts: OpenCodeRulesRuntimeOptions);
22
+ createHooks(): Record<string, unknown>;
23
+ private onToolExecuteBefore;
24
+ private onMessagesTransform;
25
+ private onChatMessage;
26
+ private onSystemTransform;
27
+ private queryAvailableToolIDs;
28
+ private onSessionCompacting;
29
+ }
30
+ export {};
31
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAU1D,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAwBvD,UAAU,2BAA2B;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,GAAG,CAAe;gBAEd,IAAI,EAAE,2BAA2B;IAU7C,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;YAWxB,mBAAmB;YA2CnB,mBAAmB;YAiDnB,aAAa;YAOb,iBAAiB;YA+FjB,qBAAqB;YAoDrB,mBAAmB;CA6ClC"}
@@ -0,0 +1,238 @@
1
+ import { readAndFormatRules } from './rule-filter.js';
2
+ import { extractFilePathsFromMessages } from './message-paths.js';
3
+ import {} from './rule-discovery.js';
4
+ import { extractLatestUserPrompt, extractSessionID, normalizeContextPath, sanitizePathForContext, toExtractableMessages, } from './message-context.js';
5
+ import { extractConnectedMcpCapabilityIDs } from './mcp-tools.js';
6
+ import { createDebugLog } from './debug.js';
7
+ import { buildFilterContext, } from './runtime-context.js';
8
+ import { handleChatMessage, } from './runtime-chat.js';
9
+ import { writeActiveRulesState } from './active-rules-state.js';
10
+ export class OpenCodeRulesRuntime {
11
+ client;
12
+ directory;
13
+ projectDirectory;
14
+ ruleFiles;
15
+ sessionStore;
16
+ debugLog;
17
+ now;
18
+ constructor(opts) {
19
+ this.client = opts.client;
20
+ this.directory = opts.directory;
21
+ this.projectDirectory = opts.projectDirectory;
22
+ this.ruleFiles = opts.ruleFiles;
23
+ this.sessionStore = opts.sessionStore;
24
+ this.debugLog = opts.debugLog ?? createDebugLog();
25
+ this.now = opts.now ?? (() => Date.now());
26
+ }
27
+ createHooks() {
28
+ return {
29
+ 'tool.execute.before': this.onToolExecuteBefore.bind(this),
30
+ 'experimental.chat.messages.transform': this.onMessagesTransform.bind(this),
31
+ 'chat.message': this.onChatMessage.bind(this),
32
+ 'experimental.chat.system.transform': this.onSystemTransform.bind(this),
33
+ 'experimental.session.compacting': this.onSessionCompacting.bind(this),
34
+ };
35
+ }
36
+ async onToolExecuteBefore(input, output) {
37
+ const sessionID = input?.sessionID;
38
+ const toolName = input?.tool;
39
+ const args = output?.args;
40
+ if (!sessionID || !toolName || !args) {
41
+ return;
42
+ }
43
+ let filePath;
44
+ if (['read', 'edit', 'write'].includes(toolName)) {
45
+ const arg = args.filePath;
46
+ if (typeof arg === 'string' && arg.length > 0) {
47
+ filePath = arg;
48
+ }
49
+ }
50
+ else if (['glob', 'grep'].includes(toolName)) {
51
+ const arg = args.path;
52
+ if (typeof arg === 'string' && arg.length > 0) {
53
+ filePath = arg;
54
+ }
55
+ }
56
+ else if (toolName === 'bash') {
57
+ const arg = args.workdir;
58
+ if (typeof arg === 'string' && arg.length > 0) {
59
+ filePath = arg;
60
+ }
61
+ }
62
+ if (filePath) {
63
+ const normalized = normalizeContextPath(filePath, this.projectDirectory);
64
+ this.sessionStore.upsert(sessionID, state => {
65
+ state.contextPaths.add(normalized);
66
+ });
67
+ this.debugLog(`Recorded context path from tool ${toolName}: ${normalized}`);
68
+ }
69
+ }
70
+ async onMessagesTransform(_input, output) {
71
+ const sessionID = extractSessionID(output.messages);
72
+ if (!sessionID) {
73
+ this.debugLog('No sessionID found in messages');
74
+ return output;
75
+ }
76
+ const existingState = this.sessionStore.get(sessionID);
77
+ if (existingState && existingState.seededFromHistory) {
78
+ this.debugLog(`Session ${sessionID} already seeded, skipping rescan`);
79
+ return output;
80
+ }
81
+ const contextPaths = extractFilePathsFromMessages(toExtractableMessages(output.messages));
82
+ const userPrompt = extractLatestUserPrompt(output.messages);
83
+ this.sessionStore.upsert(sessionID, state => {
84
+ for (const p of contextPaths) {
85
+ state.contextPaths.add(normalizeContextPath(p, this.projectDirectory));
86
+ }
87
+ if (userPrompt && !state.lastUserPrompt) {
88
+ state.lastUserPrompt = userPrompt;
89
+ }
90
+ state.seededFromHistory = true;
91
+ state.seedCount = (state.seedCount ?? 0) + 1;
92
+ });
93
+ if (contextPaths.length > 0) {
94
+ this.debugLog(`Seeded ${contextPaths.length} context path(s) for session ${sessionID}: ${contextPaths
95
+ .slice(0, 5)
96
+ .join(', ')}${contextPaths.length > 5 ? '...' : ''}`);
97
+ }
98
+ if (userPrompt) {
99
+ this.debugLog(`Seeded user prompt for session ${sessionID} (len=${userPrompt.length})`);
100
+ }
101
+ return output;
102
+ }
103
+ async onChatMessage(input, output) {
104
+ handleChatMessage(input, output, this.sessionStore, this.debugLog);
105
+ }
106
+ async onSystemTransform(hookInput, output) {
107
+ const sessionID = hookInput?.sessionID;
108
+ const sessionState = sessionID
109
+ ? this.sessionStore.get(sessionID)
110
+ : undefined;
111
+ if (sessionID) {
112
+ const skip = this.sessionStore.shouldSkipInjection(sessionID, this.now(), 30_000);
113
+ if (skip) {
114
+ this.debugLog(`Session ${sessionID} is compacting - skipping rule injection`);
115
+ return output ?? {};
116
+ }
117
+ }
118
+ if (sessionState?.rulesInjected) {
119
+ this.debugLog(`Session ${sessionID} already has rules injected - skipping to prevent loop`);
120
+ return output ?? {};
121
+ }
122
+ const contextPaths = sessionState
123
+ ? Array.from(sessionState.contextPaths).sort((a, b) => a.localeCompare(b))
124
+ : [];
125
+ const userPrompt = sessionState?.lastUserPrompt;
126
+ const availableToolIDs = await this.queryAvailableToolIDs();
127
+ const filterContextOpts = {
128
+ contextFilePaths: contextPaths,
129
+ userPrompt,
130
+ availableToolIDs,
131
+ modelID: sessionState?.lastModelID,
132
+ agentType: sessionState?.lastAgentType,
133
+ };
134
+ const filterContext = await buildFilterContext(filterContextOpts, this.projectDirectory, this.debugLog);
135
+ const { formattedRules, matchedPaths } = await readAndFormatRules(this.ruleFiles, filterContext);
136
+ if (sessionID) {
137
+ writeActiveRulesState(sessionID, matchedPaths);
138
+ }
139
+ if (!formattedRules) {
140
+ this.debugLog('No applicable rules for current context');
141
+ return output ?? {};
142
+ }
143
+ this.debugLog('Injecting rules into system prompt');
144
+ if (!output) {
145
+ if (sessionID) {
146
+ this.sessionStore.upsert(sessionID, state => {
147
+ state.rulesInjected = true;
148
+ state.lastInjectedAt = this.now();
149
+ });
150
+ }
151
+ return { system: formattedRules };
152
+ }
153
+ if (Array.isArray(output.system)) {
154
+ output.system.push(formattedRules);
155
+ }
156
+ else {
157
+ output.system = output.system
158
+ ? `${output.system}\n\n${formattedRules}`
159
+ : formattedRules;
160
+ }
161
+ if (sessionID) {
162
+ this.sessionStore.upsert(sessionID, state => {
163
+ state.rulesInjected = true;
164
+ state.lastInjectedAt = this.now();
165
+ });
166
+ }
167
+ return output;
168
+ }
169
+ async queryAvailableToolIDs() {
170
+ const ids = new Set();
171
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
172
+ const client = this.client;
173
+ const query = { directory: this.directory };
174
+ const [toolResult, mcpResult] = await Promise.allSettled([
175
+ client.tool?.ids?.({ query }),
176
+ client.mcp?.status?.({ query }),
177
+ ]);
178
+ if (toolResult.status === 'fulfilled' &&
179
+ Array.isArray(toolResult.value?.data)) {
180
+ for (const id of toolResult.value.data) {
181
+ ids.add(id);
182
+ }
183
+ this.debugLog(`Built-in tools: ${toolResult.value.data.slice(0, 10).join(', ')}${toolResult.value.data.length > 10 ? '...' : ''} (${toolResult.value.data.length} total)`);
184
+ }
185
+ else if (toolResult.status === 'rejected') {
186
+ const message = toolResult.reason instanceof Error
187
+ ? toolResult.reason.message
188
+ : String(toolResult.reason);
189
+ console.warn(`[opencode-rules-md] Warning: Failed to query tool IDs: ${message}`);
190
+ }
191
+ if (mcpResult.status === 'fulfilled' && mcpResult.value?.data) {
192
+ const mcpIds = extractConnectedMcpCapabilityIDs(mcpResult.value.data);
193
+ for (const id of mcpIds) {
194
+ ids.add(id);
195
+ }
196
+ if (mcpIds.length > 0) {
197
+ this.debugLog(`MCP capability IDs: ${mcpIds.join(', ')}`);
198
+ }
199
+ }
200
+ else if (mcpResult.status === 'rejected') {
201
+ const message = mcpResult.reason instanceof Error
202
+ ? mcpResult.reason.message
203
+ : String(mcpResult.reason);
204
+ console.warn(`[opencode-rules-md] Warning: Failed to query MCP status: ${message}`);
205
+ }
206
+ return Array.from(ids);
207
+ }
208
+ async onSessionCompacting(input, output) {
209
+ const sessionID = input?.sessionID;
210
+ if (!sessionID) {
211
+ this.debugLog('No sessionID in compacting hook input');
212
+ return;
213
+ }
214
+ const sessionState = this.sessionStore.get(sessionID);
215
+ if (!sessionState || sessionState.contextPaths.size === 0) {
216
+ this.debugLog(`No context paths for session ${sessionID} during compaction`);
217
+ return;
218
+ }
219
+ this.sessionStore.markCompacting(sessionID, this.now());
220
+ const sortedPaths = Array.from(sessionState.contextPaths).sort((a, b) => a.localeCompare(b));
221
+ const maxPaths = 20;
222
+ const pathsToInclude = sortedPaths.slice(0, maxPaths);
223
+ const contextString = [
224
+ 'OpenCode Rules: Working context',
225
+ 'Current file paths in context:',
226
+ ...pathsToInclude.map(p => ` - ${sanitizePathForContext(p)}`),
227
+ ...(sortedPaths.length > maxPaths
228
+ ? [` ... and ${sortedPaths.length - maxPaths} more paths`]
229
+ : []),
230
+ ].join('\n');
231
+ if (!output.context) {
232
+ output.context = [];
233
+ }
234
+ output.context.push(contextString);
235
+ this.debugLog(`Added ${pathsToInclude.length} context path(s) to compaction for session ${sessionID}`);
236
+ }
237
+ }
238
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export interface SessionState {
2
+ contextPaths: Set<string>;
3
+ lastUserPrompt?: string;
4
+ lastUpdated: number;
5
+ isCompacting?: boolean;
6
+ compactingSince?: number;
7
+ seededFromHistory: boolean;
8
+ seedCount?: number;
9
+ lastModelID?: string;
10
+ lastAgentType?: string;
11
+ rulesInjected?: boolean;
12
+ lastInjectedAt?: number;
13
+ }
14
+ interface SessionStoreOptions {
15
+ max?: number;
16
+ }
17
+ export declare class SessionStore {
18
+ private stateMap;
19
+ private max;
20
+ private tick;
21
+ constructor(opts?: SessionStoreOptions);
22
+ setMax(limit: number): void;
23
+ ids(): string[];
24
+ get(sessionID: string): SessionState | undefined;
25
+ snapshot(sessionID: string): SessionState | undefined;
26
+ reset(): void;
27
+ upsert(sessionID: string, mutator: (state: SessionState) => void): void;
28
+ markCompacting(sessionID: string, nowMs: number): void;
29
+ shouldSkipInjection(sessionID: string, nowMs: number, ttlMs?: number): boolean;
30
+ private createDefaultState;
31
+ }
32
+ export declare function createSessionStore(opts?: SessionStoreOptions): SessionStore;
33
+ export {};
34
+ //# sourceMappingURL=session-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/session-store.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,mBAAmB;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,IAAI,CAAK;gBAEL,IAAI,GAAE,mBAAwB;IAI1C,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI3B,GAAG,IAAI,MAAM,EAAE;IAIf,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIhD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IASrD,KAAK,IAAI,IAAI;IAMb,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IA6BvE,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAOtD,mBAAmB,CACjB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,KAAK,SAAS,GACb,OAAO;IAqBV,OAAO,CAAC,kBAAkB;CAS3B;AAED,wBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,YAAY,CAE3E"}
@@ -0,0 +1,90 @@
1
+ export class SessionStore {
2
+ stateMap = new Map();
3
+ max;
4
+ tick = 0;
5
+ constructor(opts = {}) {
6
+ this.max = opts.max ?? 100;
7
+ }
8
+ setMax(limit) {
9
+ this.max = limit;
10
+ }
11
+ ids() {
12
+ return Array.from(this.stateMap.keys());
13
+ }
14
+ get(sessionID) {
15
+ return this.stateMap.get(sessionID);
16
+ }
17
+ snapshot(sessionID) {
18
+ const s = this.stateMap.get(sessionID);
19
+ if (!s)
20
+ return undefined;
21
+ return {
22
+ ...s,
23
+ contextPaths: new Set(s.contextPaths),
24
+ };
25
+ }
26
+ reset() {
27
+ this.stateMap.clear();
28
+ this.max = 100;
29
+ this.tick = 0;
30
+ }
31
+ upsert(sessionID, mutator) {
32
+ let state = this.stateMap.get(sessionID);
33
+ if (!state) {
34
+ state = this.createDefaultState();
35
+ this.stateMap.set(sessionID, state);
36
+ }
37
+ mutator(state);
38
+ // Match existing semantics: overwrite lastUpdated after mutation.
39
+ state.lastUpdated = ++this.tick;
40
+ while (this.stateMap.size > this.max) {
41
+ let oldestID = null;
42
+ let oldestTime = Infinity;
43
+ for (const [id, st] of this.stateMap.entries()) {
44
+ if (st.lastUpdated < oldestTime) {
45
+ oldestTime = st.lastUpdated;
46
+ oldestID = id;
47
+ }
48
+ }
49
+ if (oldestID) {
50
+ this.stateMap.delete(oldestID);
51
+ }
52
+ }
53
+ }
54
+ markCompacting(sessionID, nowMs) {
55
+ this.upsert(sessionID, state => {
56
+ state.isCompacting = true;
57
+ state.compactingSince = nowMs;
58
+ });
59
+ }
60
+ shouldSkipInjection(sessionID, nowMs, ttlMs = 30_000) {
61
+ const state = this.stateMap.get(sessionID);
62
+ if (!state?.isCompacting)
63
+ return false;
64
+ // Preserve existing behavior: missing timestamp means "still compacting".
65
+ if (!state.compactingSince) {
66
+ return true;
67
+ }
68
+ const expired = nowMs - state.compactingSince > ttlMs;
69
+ if (!expired) {
70
+ return true;
71
+ }
72
+ this.upsert(sessionID, s => {
73
+ s.isCompacting = false;
74
+ });
75
+ return false;
76
+ }
77
+ createDefaultState() {
78
+ // Match existing semantics: tick increments on creation, then again on upsert.
79
+ return {
80
+ contextPaths: new Set(),
81
+ lastUpdated: ++this.tick,
82
+ seededFromHistory: false,
83
+ seedCount: 0,
84
+ };
85
+ }
86
+ }
87
+ export function createSessionStore(opts) {
88
+ return new SessionStore(opts ?? { max: 100 });
89
+ }
90
+ //# sourceMappingURL=session-store.js.map