opencode-recall 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -0
  3. package/dist/index.d.ts +4 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +123 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/config.d.ts +73 -0
  8. package/dist/lib/config.d.ts.map +1 -0
  9. package/dist/lib/config.js +779 -0
  10. package/dist/lib/config.js.map +1 -0
  11. package/dist/lib/explore-tool.d.ts +11 -0
  12. package/dist/lib/explore-tool.d.ts.map +1 -0
  13. package/dist/lib/explore-tool.js +240 -0
  14. package/dist/lib/explore-tool.js.map +1 -0
  15. package/dist/lib/hooks.d.ts +10 -0
  16. package/dist/lib/hooks.d.ts.map +1 -0
  17. package/dist/lib/hooks.js +58 -0
  18. package/dist/lib/hooks.js.map +1 -0
  19. package/dist/lib/logger.d.ts +31 -0
  20. package/dist/lib/logger.d.ts.map +1 -0
  21. package/dist/lib/logger.js +183 -0
  22. package/dist/lib/logger.js.map +1 -0
  23. package/dist/lib/messages/index.d.ts +3 -0
  24. package/dist/lib/messages/index.d.ts.map +1 -0
  25. package/dist/lib/messages/index.js +3 -0
  26. package/dist/lib/messages/index.js.map +1 -0
  27. package/dist/lib/messages/inject.d.ts +5 -0
  28. package/dist/lib/messages/inject.d.ts.map +1 -0
  29. package/dist/lib/messages/inject.js +114 -0
  30. package/dist/lib/messages/inject.js.map +1 -0
  31. package/dist/lib/messages/prune.d.ts +5 -0
  32. package/dist/lib/messages/prune.d.ts.map +1 -0
  33. package/dist/lib/messages/prune.js +179 -0
  34. package/dist/lib/messages/prune.js.map +1 -0
  35. package/dist/lib/messages/utils.d.ts +10 -0
  36. package/dist/lib/messages/utils.d.ts.map +1 -0
  37. package/dist/lib/messages/utils.js +193 -0
  38. package/dist/lib/messages/utils.js.map +1 -0
  39. package/dist/lib/prompts/agent/rcl-explorer.d.ts +2 -0
  40. package/dist/lib/prompts/agent/rcl-explorer.d.ts.map +1 -0
  41. package/dist/lib/prompts/agent/rcl-explorer.js +39 -0
  42. package/dist/lib/prompts/agent/rcl-explorer.js.map +1 -0
  43. package/dist/lib/prompts/discard-tool-spec.d.ts +2 -0
  44. package/dist/lib/prompts/discard-tool-spec.d.ts.map +1 -0
  45. package/dist/lib/prompts/discard-tool-spec.js +41 -0
  46. package/dist/lib/prompts/discard-tool-spec.js.map +1 -0
  47. package/dist/lib/prompts/extract-tool-spec.d.ts +2 -0
  48. package/dist/lib/prompts/extract-tool-spec.d.ts.map +1 -0
  49. package/dist/lib/prompts/extract-tool-spec.js +48 -0
  50. package/dist/lib/prompts/extract-tool-spec.js.map +1 -0
  51. package/dist/lib/prompts/index.d.ts +2 -0
  52. package/dist/lib/prompts/index.d.ts.map +1 -0
  53. package/dist/lib/prompts/index.js +41 -0
  54. package/dist/lib/prompts/index.js.map +1 -0
  55. package/dist/lib/prompts/nudge/both.d.ts +2 -0
  56. package/dist/lib/prompts/nudge/both.d.ts.map +1 -0
  57. package/dist/lib/prompts/nudge/both.js +11 -0
  58. package/dist/lib/prompts/nudge/both.js.map +1 -0
  59. package/dist/lib/prompts/nudge/discard.d.ts +2 -0
  60. package/dist/lib/prompts/nudge/discard.d.ts.map +1 -0
  61. package/dist/lib/prompts/nudge/discard.js +10 -0
  62. package/dist/lib/prompts/nudge/discard.js.map +1 -0
  63. package/dist/lib/prompts/nudge/extract.d.ts +2 -0
  64. package/dist/lib/prompts/nudge/extract.d.ts.map +1 -0
  65. package/dist/lib/prompts/nudge/extract.js +10 -0
  66. package/dist/lib/prompts/nudge/extract.js.map +1 -0
  67. package/dist/lib/prompts/restore-tool-spec.d.ts +2 -0
  68. package/dist/lib/prompts/restore-tool-spec.d.ts.map +1 -0
  69. package/dist/lib/prompts/restore-tool-spec.js +21 -0
  70. package/dist/lib/prompts/restore-tool-spec.js.map +1 -0
  71. package/dist/lib/prompts/system/both.d.ts +2 -0
  72. package/dist/lib/prompts/system/both.d.ts.map +1 -0
  73. package/dist/lib/prompts/system/both.js +72 -0
  74. package/dist/lib/prompts/system/both.js.map +1 -0
  75. package/dist/lib/prompts/system/core.d.ts +2 -0
  76. package/dist/lib/prompts/system/core.d.ts.map +1 -0
  77. package/dist/lib/prompts/system/core.js +26 -0
  78. package/dist/lib/prompts/system/core.js.map +1 -0
  79. package/dist/lib/prompts/system/discard.d.ts +2 -0
  80. package/dist/lib/prompts/system/discard.d.ts.map +1 -0
  81. package/dist/lib/prompts/system/discard.js +63 -0
  82. package/dist/lib/prompts/system/discard.js.map +1 -0
  83. package/dist/lib/prompts/system/extract.d.ts +2 -0
  84. package/dist/lib/prompts/system/extract.d.ts.map +1 -0
  85. package/dist/lib/prompts/system/extract.js +63 -0
  86. package/dist/lib/prompts/system/extract.js.map +1 -0
  87. package/dist/lib/protected-file-patterns.d.ts +12 -0
  88. package/dist/lib/protected-file-patterns.d.ts.map +1 -0
  89. package/dist/lib/protected-file-patterns.js +69 -0
  90. package/dist/lib/protected-file-patterns.js.map +1 -0
  91. package/dist/lib/pruned-blobs.d.ts +19 -0
  92. package/dist/lib/pruned-blobs.d.ts.map +1 -0
  93. package/dist/lib/pruned-blobs.js +111 -0
  94. package/dist/lib/pruned-blobs.js.map +1 -0
  95. package/dist/lib/rcl-pointer.d.ts +3 -0
  96. package/dist/lib/rcl-pointer.d.ts.map +1 -0
  97. package/dist/lib/rcl-pointer.js +63 -0
  98. package/dist/lib/rcl-pointer.js.map +1 -0
  99. package/dist/lib/restore-tool.d.ts +15 -0
  100. package/dist/lib/restore-tool.d.ts.map +1 -0
  101. package/dist/lib/restore-tool.js +142 -0
  102. package/dist/lib/restore-tool.js.map +1 -0
  103. package/dist/lib/shared-utils.d.ts +4 -0
  104. package/dist/lib/shared-utils.d.ts.map +1 -0
  105. package/dist/lib/shared-utils.js +14 -0
  106. package/dist/lib/shared-utils.js.map +1 -0
  107. package/dist/lib/state/index.d.ts +4 -0
  108. package/dist/lib/state/index.d.ts.map +1 -0
  109. package/dist/lib/state/index.js +4 -0
  110. package/dist/lib/state/index.js.map +1 -0
  111. package/dist/lib/state/persistence.d.ts +16 -0
  112. package/dist/lib/state/persistence.d.ts.map +1 -0
  113. package/dist/lib/state/persistence.js +73 -0
  114. package/dist/lib/state/persistence.js.map +1 -0
  115. package/dist/lib/state/state.d.ts +8 -0
  116. package/dist/lib/state/state.d.ts.map +1 -0
  117. package/dist/lib/state/state.js +114 -0
  118. package/dist/lib/state/state.js.map +1 -0
  119. package/dist/lib/state/tool-cache.d.ts +13 -0
  120. package/dist/lib/state/tool-cache.d.ts.map +1 -0
  121. package/dist/lib/state/tool-cache.js +79 -0
  122. package/dist/lib/state/tool-cache.js.map +1 -0
  123. package/dist/lib/state/types.d.ts +33 -0
  124. package/dist/lib/state/types.d.ts.map +1 -0
  125. package/dist/lib/state/types.js +2 -0
  126. package/dist/lib/state/types.js.map +1 -0
  127. package/dist/lib/state/utils.d.ts +2 -0
  128. package/dist/lib/state/utils.d.ts.map +1 -0
  129. package/dist/lib/state/utils.js +10 -0
  130. package/dist/lib/state/utils.js.map +1 -0
  131. package/dist/lib/strategies/deduplication.d.ts +10 -0
  132. package/dist/lib/strategies/deduplication.d.ts.map +1 -0
  133. package/dist/lib/strategies/deduplication.js +94 -0
  134. package/dist/lib/strategies/deduplication.js.map +1 -0
  135. package/dist/lib/strategies/index.d.ts +5 -0
  136. package/dist/lib/strategies/index.d.ts.map +1 -0
  137. package/dist/lib/strategies/index.js +5 -0
  138. package/dist/lib/strategies/index.js.map +1 -0
  139. package/dist/lib/strategies/purge-errors.d.ts +13 -0
  140. package/dist/lib/strategies/purge-errors.d.ts.map +1 -0
  141. package/dist/lib/strategies/purge-errors.js +59 -0
  142. package/dist/lib/strategies/purge-errors.js.map +1 -0
  143. package/dist/lib/strategies/supersede-writes.d.ts +13 -0
  144. package/dist/lib/strategies/supersede-writes.d.ts.map +1 -0
  145. package/dist/lib/strategies/supersede-writes.js +84 -0
  146. package/dist/lib/strategies/supersede-writes.js.map +1 -0
  147. package/dist/lib/strategies/tools.d.ts +14 -0
  148. package/dist/lib/strategies/tools.d.ts.map +1 -0
  149. package/dist/lib/strategies/tools.js +135 -0
  150. package/dist/lib/strategies/tools.js.map +1 -0
  151. package/dist/lib/strategies/utils.d.ts +13 -0
  152. package/dist/lib/strategies/utils.d.ts.map +1 -0
  153. package/dist/lib/strategies/utils.js +93 -0
  154. package/dist/lib/strategies/utils.js.map +1 -0
  155. package/dist/lib/ui/notification.d.ts +8 -0
  156. package/dist/lib/ui/notification.d.ts.map +1 -0
  157. package/dist/lib/ui/notification.js +54 -0
  158. package/dist/lib/ui/notification.js.map +1 -0
  159. package/dist/lib/ui/utils.d.ts +15 -0
  160. package/dist/lib/ui/utils.d.ts.map +1 -0
  161. package/dist/lib/ui/utils.js +87 -0
  162. package/dist/lib/ui/utils.js.map +1 -0
  163. package/package.json +63 -0
@@ -0,0 +1,114 @@
1
+ import { loadSessionState } from "./persistence";
2
+ import { isSubAgentSession } from "./utils";
3
+ import { getLastUserMessage, isMessageCompacted } from "../shared-utils";
4
+ export const checkSession = async (client, state, logger, messages) => {
5
+ const lastUserMessage = getLastUserMessage(messages);
6
+ if (!lastUserMessage) {
7
+ return;
8
+ }
9
+ const lastSessionId = lastUserMessage.info.sessionID;
10
+ if (state.sessionId === null || state.sessionId !== lastSessionId) {
11
+ logger.info(`Session changed: ${state.sessionId} -> ${lastSessionId}`);
12
+ try {
13
+ await ensureSessionInitialized(client, state, lastSessionId, logger, messages);
14
+ }
15
+ catch (err) {
16
+ logger.error("Failed to initialize session state", { error: err.message });
17
+ }
18
+ }
19
+ const lastCompactionTimestamp = findLastCompactionTimestamp(messages);
20
+ if (lastCompactionTimestamp > state.lastCompaction) {
21
+ state.lastCompaction = lastCompactionTimestamp;
22
+ state.toolParameters.clear();
23
+ state.prune.toolIds = [];
24
+ logger.info("Detected compaction from messages - cleared tool cache", {
25
+ timestamp: lastCompactionTimestamp,
26
+ });
27
+ }
28
+ state.currentTurn = countTurns(state, messages);
29
+ };
30
+ export function createSessionState() {
31
+ return {
32
+ sessionId: null,
33
+ isSubAgent: false,
34
+ prune: {
35
+ toolIds: [],
36
+ },
37
+ stats: {
38
+ pruneTokenCounter: 0,
39
+ totalPruneTokens: 0,
40
+ },
41
+ toolParameters: new Map(),
42
+ nudgeCounter: 0,
43
+ lastToolPrune: false,
44
+ lastCompaction: 0,
45
+ currentTurn: 0,
46
+ variant: undefined,
47
+ };
48
+ }
49
+ export function resetSessionState(state) {
50
+ state.sessionId = null;
51
+ state.isSubAgent = false;
52
+ state.prune = {
53
+ toolIds: [],
54
+ };
55
+ state.stats = {
56
+ pruneTokenCounter: 0,
57
+ totalPruneTokens: 0,
58
+ };
59
+ state.toolParameters.clear();
60
+ state.nudgeCounter = 0;
61
+ state.lastToolPrune = false;
62
+ state.lastCompaction = 0;
63
+ state.currentTurn = 0;
64
+ state.variant = undefined;
65
+ }
66
+ export async function ensureSessionInitialized(client, state, sessionId, logger, messages) {
67
+ if (state.sessionId === sessionId) {
68
+ return;
69
+ }
70
+ logger.info("session ID = " + sessionId);
71
+ logger.info("Initializing session state", { sessionId: sessionId });
72
+ resetSessionState(state);
73
+ state.sessionId = sessionId;
74
+ const isSubAgent = await isSubAgentSession(client, sessionId);
75
+ state.isSubAgent = isSubAgent;
76
+ logger.info("isSubAgent = " + isSubAgent);
77
+ state.lastCompaction = findLastCompactionTimestamp(messages);
78
+ state.currentTurn = countTurns(state, messages);
79
+ const persisted = await loadSessionState(sessionId, logger);
80
+ if (persisted === null) {
81
+ return;
82
+ }
83
+ state.prune = {
84
+ toolIds: persisted.prune.toolIds || [],
85
+ };
86
+ state.stats = {
87
+ pruneTokenCounter: persisted.stats?.pruneTokenCounter || 0,
88
+ totalPruneTokens: persisted.stats?.totalPruneTokens || 0,
89
+ };
90
+ }
91
+ function findLastCompactionTimestamp(messages) {
92
+ for (let i = messages.length - 1; i >= 0; i--) {
93
+ const msg = messages[i];
94
+ if (msg.info.role === "assistant" && msg.info.summary === true) {
95
+ return msg.info.time.created;
96
+ }
97
+ }
98
+ return 0;
99
+ }
100
+ export function countTurns(state, messages) {
101
+ let turnCount = 0;
102
+ for (const msg of messages) {
103
+ if (isMessageCompacted(state, msg)) {
104
+ continue;
105
+ }
106
+ for (const part of msg.parts) {
107
+ if (part.type === "step-start") {
108
+ turnCount++;
109
+ }
110
+ }
111
+ }
112
+ return turnCount;
113
+ }
114
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../lib/state/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { SessionState, WithParts } from "./index";
2
+ import type { Logger } from "../logger";
3
+ import { PluginConfig } from "../config";
4
+ /**
5
+ * Sync tool parameters from OpenCode's session.messages() API.
6
+ */
7
+ export declare function syncToolCache(state: SessionState, config: PluginConfig, logger: Logger, messages: WithParts[]): Promise<void>;
8
+ /**
9
+ * Trim the tool parameters cache to prevent unbounded memory growth.
10
+ * Uses FIFO eviction - removes oldest entries first.
11
+ */
12
+ export declare function trimToolParametersCache(state: SessionState): void;
13
+ //# sourceMappingURL=tool-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-cache.d.ts","sourceRoot":"","sources":["../../../lib/state/tool-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAc,SAAS,EAAE,MAAM,SAAS,CAAA;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAKxC;;GAEG;AACH,wBAAsB,aAAa,CAC/B,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,SAAS,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CAuEf;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAajE"}
@@ -0,0 +1,79 @@
1
+ import { isMessageCompacted } from "../shared-utils";
2
+ const MAX_TOOL_CACHE_SIZE = 1000;
3
+ /**
4
+ * Sync tool parameters from OpenCode's session.messages() API.
5
+ */
6
+ export async function syncToolCache(state, config, logger, messages) {
7
+ try {
8
+ logger.info("Syncing tool parameters from OpenCode messages");
9
+ state.nudgeCounter = 0;
10
+ let turnCounter = 0;
11
+ for (const msg of messages) {
12
+ if (isMessageCompacted(state, msg)) {
13
+ continue;
14
+ }
15
+ for (const part of msg.parts) {
16
+ if (part.type === "step-start") {
17
+ turnCounter++;
18
+ continue;
19
+ }
20
+ if (part.type !== "tool" || !part.callID) {
21
+ continue;
22
+ }
23
+ const turnProtectionEnabled = config.turnProtection.enabled;
24
+ const turnProtectionTurns = config.turnProtection.turns;
25
+ const restoreProtectionTurns = config.tools.settings.restoreProtectionTurns;
26
+ const isRestoreTool = part.tool === "rcl_restore";
27
+ const isProtectedByTurn = isRestoreTool
28
+ ? restoreProtectionTurns > 0 &&
29
+ state.currentTurn - turnCounter < restoreProtectionTurns
30
+ : turnProtectionEnabled &&
31
+ turnProtectionTurns > 0 &&
32
+ state.currentTurn - turnCounter < turnProtectionTurns;
33
+ state.lastToolPrune = part.tool === "discard" || part.tool === "extract";
34
+ const allProtectedTools = config.tools.settings.protectedTools;
35
+ if (part.tool === "discard" || part.tool === "extract") {
36
+ state.nudgeCounter = 0;
37
+ }
38
+ else if (!allProtectedTools.includes(part.tool) && !isProtectedByTurn) {
39
+ state.nudgeCounter++;
40
+ }
41
+ if (state.toolParameters.has(part.callID)) {
42
+ continue;
43
+ }
44
+ if (isProtectedByTurn) {
45
+ continue;
46
+ }
47
+ state.toolParameters.set(part.callID, {
48
+ tool: part.tool,
49
+ parameters: part.state?.input ?? {},
50
+ status: part.state.status,
51
+ error: part.state.status === "error" ? part.state.error : undefined,
52
+ turn: turnCounter,
53
+ });
54
+ logger.info(`Cached tool id: ${part.callID} (created on turn ${turnCounter})`);
55
+ }
56
+ }
57
+ logger.info(`Synced cache - size: ${state.toolParameters.size}, currentTurn: ${state.currentTurn}, nudgeCounter: ${state.nudgeCounter}`);
58
+ trimToolParametersCache(state);
59
+ }
60
+ catch (error) {
61
+ logger.warn("Failed to sync tool parameters from OpenCode", {
62
+ error: error instanceof Error ? error.message : String(error),
63
+ });
64
+ }
65
+ }
66
+ /**
67
+ * Trim the tool parameters cache to prevent unbounded memory growth.
68
+ * Uses FIFO eviction - removes oldest entries first.
69
+ */
70
+ export function trimToolParametersCache(state) {
71
+ if (state.toolParameters.size <= MAX_TOOL_CACHE_SIZE) {
72
+ return;
73
+ }
74
+ const keysToRemove = Array.from(state.toolParameters.keys()).slice(0, state.toolParameters.size - MAX_TOOL_CACHE_SIZE);
75
+ for (const key of keysToRemove) {
76
+ state.toolParameters.delete(key);
77
+ }
78
+ }
79
+ //# sourceMappingURL=tool-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-cache.js","sourceRoot":"","sources":["../../../lib/state/tool-cache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAEpD,MAAM,mBAAmB,GAAG,IAAI,CAAA;AAEhC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAC/B,KAAmB,EACnB,MAAoB,EACpB,MAAc,EACd,QAAqB;IAErB,IAAI,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAA;QAE7D,KAAK,CAAC,YAAY,GAAG,CAAC,CAAA;QACtB,IAAI,WAAW,GAAG,CAAC,CAAA;QAEnB,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,kBAAkB,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;gBACjC,SAAQ;YACZ,CAAC;YAED,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC3B,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAC7B,WAAW,EAAE,CAAA;oBACb,SAAQ;gBACZ,CAAC;gBAED,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACvC,SAAQ;gBACZ,CAAC;gBAED,MAAM,qBAAqB,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAA;gBAC3D,MAAM,mBAAmB,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAA;gBACvD,MAAM,sBAAsB,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,sBAAsB,CAAA;gBAC3E,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,KAAK,aAAa,CAAA;gBACjD,MAAM,iBAAiB,GAAG,aAAa;oBACnC,CAAC,CAAC,sBAAsB,GAAG,CAAC;wBAC1B,KAAK,CAAC,WAAW,GAAG,WAAW,GAAG,sBAAsB;oBAC1D,CAAC,CAAC,qBAAqB;wBACrB,mBAAmB,GAAG,CAAC;wBACvB,KAAK,CAAC,WAAW,GAAG,WAAW,GAAG,mBAAmB,CAAA;gBAE3D,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,CAAA;gBAExE,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAA;gBAE9D,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBACrD,KAAK,CAAC,YAAY,GAAG,CAAC,CAAA;gBAC1B,CAAC;qBAAM,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACtE,KAAK,CAAC,YAAY,EAAE,CAAA;gBACxB,CAAC;gBAED,IAAI,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACxC,SAAQ;gBACZ,CAAC;gBAED,IAAI,iBAAiB,EAAE,CAAC;oBACpB,SAAQ;gBACZ,CAAC;gBAED,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE;oBAClC,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,UAAU,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;oBACnC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAgC;oBACnD,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;oBACnE,IAAI,EAAE,WAAW;iBACpB,CAAC,CAAA;gBACF,MAAM,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,MAAM,qBAAqB,WAAW,GAAG,CAAC,CAAA;YAClF,CAAC;QACL,CAAC;QAED,MAAM,CAAC,IAAI,CACP,wBAAwB,KAAK,CAAC,cAAc,CAAC,IAAI,kBAAkB,KAAK,CAAC,WAAW,mBAAmB,KAAK,CAAC,YAAY,EAAE,CAC9H,CAAA;QACD,uBAAuB,CAAC,KAAK,CAAC,CAAA;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,8CAA8C,EAAE;YACxD,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,CAAC,CAAA;IACN,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAmB;IACvD,IAAI,KAAK,CAAC,cAAc,CAAC,IAAI,IAAI,mBAAmB,EAAE,CAAC;QACnD,OAAM;IACV,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAC9D,CAAC,EACD,KAAK,CAAC,cAAc,CAAC,IAAI,GAAG,mBAAmB,CAClD,CAAA;IAED,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC7B,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;AACL,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { Message, Part } from "@opencode-ai/sdk/v2";
2
+ export interface WithParts {
3
+ info: Message;
4
+ parts: Part[];
5
+ }
6
+ export type ToolStatus = "pending" | "running" | "completed" | "error";
7
+ export interface ToolParameterEntry {
8
+ tool: string;
9
+ parameters: any;
10
+ status?: ToolStatus;
11
+ error?: string;
12
+ turn: number;
13
+ }
14
+ export interface SessionStats {
15
+ pruneTokenCounter: number;
16
+ totalPruneTokens: number;
17
+ }
18
+ export interface Prune {
19
+ toolIds: string[];
20
+ }
21
+ export interface SessionState {
22
+ sessionId: string | null;
23
+ isSubAgent: boolean;
24
+ prune: Prune;
25
+ stats: SessionStats;
26
+ toolParameters: Map<string, ToolParameterEntry>;
27
+ nudgeCounter: number;
28
+ lastToolPrune: boolean;
29
+ lastCompaction: number;
30
+ currentTurn: number;
31
+ variant: string | undefined;
32
+ }
33
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../lib/state/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAEnD,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,IAAI,EAAE,CAAA;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAA;AAEtE,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,GAAG,CAAA;IACf,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,YAAY;IACzB,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,KAAK;IAClB,OAAO,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,OAAO,CAAA;IACnB,KAAK,EAAE,KAAK,CAAA;IACZ,KAAK,EAAE,YAAY,CAAA;IACnB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;IAC/C,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,OAAO,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAC9B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../lib/state/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare function isSubAgentSession(client: any, sessionID: string): Promise<boolean>;
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../lib/state/utils.ts"],"names":[],"mappings":"AAAA,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOxF"}
@@ -0,0 +1,10 @@
1
+ export async function isSubAgentSession(client, sessionID) {
2
+ try {
3
+ const result = await client.session.get({ path: { id: sessionID } });
4
+ return !!result.data?.parentID;
5
+ }
6
+ catch (error) {
7
+ return false;
8
+ }
9
+ }
10
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../lib/state/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAW,EAAE,SAAiB;IAClE,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAA;QACpE,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAA;IAClC,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QAClB,OAAO,KAAK,CAAA;IAChB,CAAC;AACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { PluginConfig } from "../config";
2
+ import { Logger } from "../logger";
3
+ import type { SessionState, WithParts } from "../state";
4
+ /**
5
+ * Deduplication strategy - prunes older tool calls that have identical
6
+ * tool name and parameters, keeping only the most recent occurrence.
7
+ * Modifies the session state in place to add pruned tool call IDs.
8
+ */
9
+ export declare const deduplicate: (state: SessionState, logger: Logger, config: PluginConfig, messages: WithParts[]) => void;
10
+ //# sourceMappingURL=deduplication.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deduplication.d.ts","sourceRoot":"","sources":["../../../lib/strategies/deduplication.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAKvD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACpB,OAAO,YAAY,EACnB,QAAQ,MAAM,EACd,QAAQ,YAAY,EACpB,UAAU,SAAS,EAAE,KACtB,IAiEF,CAAA"}
@@ -0,0 +1,94 @@
1
+ import { buildToolIdList } from "../messages/utils";
2
+ import { getFilePathFromParameters, isProtectedFilePath } from "../protected-file-patterns";
3
+ import { calculateTokensSaved } from "./utils";
4
+ /**
5
+ * Deduplication strategy - prunes older tool calls that have identical
6
+ * tool name and parameters, keeping only the most recent occurrence.
7
+ * Modifies the session state in place to add pruned tool call IDs.
8
+ */
9
+ export const deduplicate = (state, logger, config, messages) => {
10
+ if (!config.strategies.deduplication.enabled) {
11
+ return;
12
+ }
13
+ // Build list of all tool call IDs from messages (chronological order)
14
+ const allToolIds = buildToolIdList(state, messages, logger);
15
+ if (allToolIds.length === 0) {
16
+ return;
17
+ }
18
+ // Filter out IDs already pruned
19
+ const alreadyPruned = new Set(state.prune.toolIds);
20
+ const unprunedIds = allToolIds.filter((id) => !alreadyPruned.has(id));
21
+ if (unprunedIds.length === 0) {
22
+ return;
23
+ }
24
+ const protectedTools = config.strategies.deduplication.protectedTools;
25
+ // Group by signature (tool name + normalized parameters)
26
+ const signatureMap = new Map();
27
+ for (const id of unprunedIds) {
28
+ const metadata = state.toolParameters.get(id);
29
+ if (!metadata) {
30
+ // logger.warn(`Missing metadata for tool call ID: ${id}`)
31
+ continue;
32
+ }
33
+ // Skip protected tools
34
+ if (protectedTools.includes(metadata.tool)) {
35
+ continue;
36
+ }
37
+ const filePath = getFilePathFromParameters(metadata.parameters);
38
+ if (isProtectedFilePath(filePath, config.protectedFilePatterns)) {
39
+ continue;
40
+ }
41
+ const signature = createToolSignature(metadata.tool, metadata.parameters);
42
+ if (!signatureMap.has(signature)) {
43
+ signatureMap.set(signature, []);
44
+ }
45
+ signatureMap.get(signature).push(id);
46
+ }
47
+ // Find duplicates - keep only the most recent (last) in each group
48
+ const newPruneIds = [];
49
+ for (const [, ids] of signatureMap.entries()) {
50
+ if (ids.length > 1) {
51
+ // All except last (most recent) should be pruned
52
+ const idsToRemove = ids.slice(0, -1);
53
+ newPruneIds.push(...idsToRemove);
54
+ }
55
+ }
56
+ state.stats.totalPruneTokens += calculateTokensSaved(state, messages, newPruneIds);
57
+ if (newPruneIds.length > 0) {
58
+ state.prune.toolIds.push(...newPruneIds);
59
+ logger.debug(`Marked ${newPruneIds.length} duplicate tool calls for pruning`);
60
+ }
61
+ };
62
+ function createToolSignature(tool, parameters) {
63
+ if (!parameters) {
64
+ return tool;
65
+ }
66
+ const normalized = normalizeParameters(parameters);
67
+ const sorted = sortObjectKeys(normalized);
68
+ return `${tool}::${JSON.stringify(sorted)}`;
69
+ }
70
+ function normalizeParameters(params) {
71
+ if (typeof params !== "object" || params === null)
72
+ return params;
73
+ if (Array.isArray(params))
74
+ return params;
75
+ const normalized = {};
76
+ for (const [key, value] of Object.entries(params)) {
77
+ if (value !== undefined && value !== null) {
78
+ normalized[key] = value;
79
+ }
80
+ }
81
+ return normalized;
82
+ }
83
+ function sortObjectKeys(obj) {
84
+ if (typeof obj !== "object" || obj === null)
85
+ return obj;
86
+ if (Array.isArray(obj))
87
+ return obj.map(sortObjectKeys);
88
+ const sorted = {};
89
+ for (const key of Object.keys(obj).sort()) {
90
+ sorted[key] = sortObjectKeys(obj[key]);
91
+ }
92
+ return sorted;
93
+ }
94
+ //# sourceMappingURL=deduplication.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deduplication.js","sourceRoot":"","sources":["../../../lib/strategies/deduplication.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { deduplicate } from "./deduplication";
2
+ export { createDiscardTool, createExtractTool } from "./tools";
3
+ export { supersedeWrites } from "./supersede-writes";
4
+ export { purgeErrors } from "./purge-errors";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/strategies/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,5 @@
1
+ export { deduplicate } from "./deduplication";
2
+ export { createDiscardTool, createExtractTool } from "./tools";
3
+ export { supersedeWrites } from "./supersede-writes";
4
+ export { purgeErrors } from "./purge-errors";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/strategies/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,13 @@
1
+ import { PluginConfig } from "../config";
2
+ import { Logger } from "../logger";
3
+ import type { SessionState, WithParts } from "../state";
4
+ /**
5
+ * Purge Errors strategy - prunes tool inputs for tools that errored
6
+ * after they are older than a configurable number of turns.
7
+ * The error message is preserved, but the (potentially large) inputs
8
+ * are removed to save context.
9
+ *
10
+ * Modifies the session state in place to add pruned tool call IDs.
11
+ */
12
+ export declare const purgeErrors: (state: SessionState, logger: Logger, config: PluginConfig, messages: WithParts[]) => void;
13
+ //# sourceMappingURL=purge-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"purge-errors.d.ts","sourceRoot":"","sources":["../../../lib/strategies/purge-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAKvD;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,GACpB,OAAO,YAAY,EACnB,QAAQ,MAAM,EACd,QAAQ,YAAY,EACpB,UAAU,SAAS,EAAE,KACtB,IA2DF,CAAA"}
@@ -0,0 +1,59 @@
1
+ import { buildToolIdList } from "../messages/utils";
2
+ import { getFilePathFromParameters, isProtectedFilePath } from "../protected-file-patterns";
3
+ import { calculateTokensSaved } from "./utils";
4
+ /**
5
+ * Purge Errors strategy - prunes tool inputs for tools that errored
6
+ * after they are older than a configurable number of turns.
7
+ * The error message is preserved, but the (potentially large) inputs
8
+ * are removed to save context.
9
+ *
10
+ * Modifies the session state in place to add pruned tool call IDs.
11
+ */
12
+ export const purgeErrors = (state, logger, config, messages) => {
13
+ if (!config.strategies.purgeErrors.enabled) {
14
+ return;
15
+ }
16
+ // Build list of all tool call IDs from messages (chronological order)
17
+ const allToolIds = buildToolIdList(state, messages, logger);
18
+ if (allToolIds.length === 0) {
19
+ return;
20
+ }
21
+ // Filter out IDs already pruned
22
+ const alreadyPruned = new Set(state.prune.toolIds);
23
+ const unprunedIds = allToolIds.filter((id) => !alreadyPruned.has(id));
24
+ if (unprunedIds.length === 0) {
25
+ return;
26
+ }
27
+ const protectedTools = config.strategies.purgeErrors.protectedTools;
28
+ const turnThreshold = config.strategies.purgeErrors.turns;
29
+ const newPruneIds = [];
30
+ for (const id of unprunedIds) {
31
+ const metadata = state.toolParameters.get(id);
32
+ if (!metadata) {
33
+ continue;
34
+ }
35
+ // Skip protected tools
36
+ if (protectedTools.includes(metadata.tool)) {
37
+ continue;
38
+ }
39
+ const filePath = getFilePathFromParameters(metadata.parameters);
40
+ if (isProtectedFilePath(filePath, config.protectedFilePatterns)) {
41
+ continue;
42
+ }
43
+ // Only process error tools
44
+ if (metadata.status !== "error") {
45
+ continue;
46
+ }
47
+ // Check if the tool is old enough to prune
48
+ const turnAge = state.currentTurn - metadata.turn;
49
+ if (turnAge >= turnThreshold) {
50
+ newPruneIds.push(id);
51
+ }
52
+ }
53
+ if (newPruneIds.length > 0) {
54
+ state.stats.totalPruneTokens += calculateTokensSaved(state, messages, newPruneIds);
55
+ state.prune.toolIds.push(...newPruneIds);
56
+ logger.debug(`Marked ${newPruneIds.length} error tool calls for pruning (older than ${turnThreshold} turns)`);
57
+ }
58
+ };
59
+ //# sourceMappingURL=purge-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"purge-errors.js","sourceRoot":"","sources":["../../../lib/strategies/purge-errors.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAC3F,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE9C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CACvB,KAAmB,EACnB,MAAc,EACd,MAAoB,EACpB,QAAqB,EACjB,EAAE;IACN,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QACzC,OAAM;IACV,CAAC;IAED,sEAAsE;IACtE,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;IAC3D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAM;IACV,CAAC;IAED,gCAAgC;IAChC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAClD,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IAErE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAM;IACV,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,cAAc,CAAA;IACnE,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAA;IAEzD,MAAM,WAAW,GAAa,EAAE,CAAA;IAEhC,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,SAAQ;QACZ,CAAC;QAED,uBAAuB;QACvB,IAAI,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,SAAQ;QACZ,CAAC;QAED,MAAM,QAAQ,GAAG,yBAAyB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;QAC/D,IAAI,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,qBAAqB,CAAC,EAAE,CAAC;YAC9D,SAAQ;QACZ,CAAC;QAED,2BAA2B;QAC3B,IAAI,QAAQ,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,SAAQ;QACZ,CAAC;QAED,2CAA2C;QAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAA;QACjD,IAAI,OAAO,IAAI,aAAa,EAAE,CAAC;YAC3B,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACxB,CAAC;IACL,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,KAAK,CAAC,gBAAgB,IAAI,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;QAClF,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAA;QACxC,MAAM,CAAC,KAAK,CACR,UAAU,WAAW,CAAC,MAAM,6CAA6C,aAAa,SAAS,CAClG,CAAA;IACL,CAAC;AACL,CAAC,CAAA"}
@@ -0,0 +1,13 @@
1
+ import { PluginConfig } from "../config";
2
+ import { Logger } from "../logger";
3
+ import type { SessionState, WithParts } from "../state";
4
+ /**
5
+ * Supersede Writes strategy - prunes write tool inputs for files that have
6
+ * subsequently been read. When a file is written and later read, the original
7
+ * write content becomes redundant since the current file state is captured
8
+ * in the read result.
9
+ *
10
+ * Modifies the session state in place to add pruned tool call IDs.
11
+ */
12
+ export declare const supersedeWrites: (state: SessionState, logger: Logger, config: PluginConfig, messages: WithParts[]) => void;
13
+ //# sourceMappingURL=supersede-writes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supersede-writes.d.ts","sourceRoot":"","sources":["../../../lib/strategies/supersede-writes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAKvD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GACxB,OAAO,YAAY,EACnB,QAAQ,MAAM,EACd,QAAQ,YAAY,EACpB,UAAU,SAAS,EAAE,KACtB,IAoFF,CAAA"}
@@ -0,0 +1,84 @@
1
+ import { buildToolIdList } from "../messages/utils";
2
+ import { getFilePathFromParameters, isProtectedFilePath } from "../protected-file-patterns";
3
+ import { calculateTokensSaved } from "./utils";
4
+ /**
5
+ * Supersede Writes strategy - prunes write tool inputs for files that have
6
+ * subsequently been read. When a file is written and later read, the original
7
+ * write content becomes redundant since the current file state is captured
8
+ * in the read result.
9
+ *
10
+ * Modifies the session state in place to add pruned tool call IDs.
11
+ */
12
+ export const supersedeWrites = (state, logger, config, messages) => {
13
+ if (!config.strategies.supersedeWrites.enabled) {
14
+ return;
15
+ }
16
+ // Build list of all tool call IDs from messages (chronological order)
17
+ const allToolIds = buildToolIdList(state, messages, logger);
18
+ if (allToolIds.length === 0) {
19
+ return;
20
+ }
21
+ // Filter out IDs already pruned
22
+ const alreadyPruned = new Set(state.prune.toolIds);
23
+ const unprunedIds = allToolIds.filter((id) => !alreadyPruned.has(id));
24
+ if (unprunedIds.length === 0) {
25
+ return;
26
+ }
27
+ // Track write tools by file path: filePath -> [{ id, index }]
28
+ // We track index to determine chronological order
29
+ const writesByFile = new Map();
30
+ // Track read file paths with their index
31
+ const readsByFile = new Map();
32
+ for (let i = 0; i < allToolIds.length; i++) {
33
+ const id = allToolIds[i];
34
+ const metadata = state.toolParameters.get(id);
35
+ if (!metadata) {
36
+ continue;
37
+ }
38
+ const filePath = getFilePathFromParameters(metadata.parameters);
39
+ if (!filePath) {
40
+ continue;
41
+ }
42
+ if (isProtectedFilePath(filePath, config.protectedFilePatterns)) {
43
+ continue;
44
+ }
45
+ if (metadata.tool === "write") {
46
+ if (!writesByFile.has(filePath)) {
47
+ writesByFile.set(filePath, []);
48
+ }
49
+ writesByFile.get(filePath).push({ id, index: i });
50
+ }
51
+ else if (metadata.tool === "read") {
52
+ if (!readsByFile.has(filePath)) {
53
+ readsByFile.set(filePath, []);
54
+ }
55
+ readsByFile.get(filePath).push(i);
56
+ }
57
+ }
58
+ // Find writes that are superseded by subsequent reads
59
+ const newPruneIds = [];
60
+ for (const [filePath, writes] of writesByFile.entries()) {
61
+ const reads = readsByFile.get(filePath);
62
+ if (!reads || reads.length === 0) {
63
+ continue;
64
+ }
65
+ // For each write, check if there's a read that comes after it
66
+ for (const write of writes) {
67
+ // Skip if already pruned
68
+ if (alreadyPruned.has(write.id)) {
69
+ continue;
70
+ }
71
+ // Check if any read comes after this write
72
+ const hasSubsequentRead = reads.some((readIndex) => readIndex > write.index);
73
+ if (hasSubsequentRead) {
74
+ newPruneIds.push(write.id);
75
+ }
76
+ }
77
+ }
78
+ if (newPruneIds.length > 0) {
79
+ state.stats.totalPruneTokens += calculateTokensSaved(state, messages, newPruneIds);
80
+ state.prune.toolIds.push(...newPruneIds);
81
+ logger.debug(`Marked ${newPruneIds.length} superseded write tool calls for pruning`);
82
+ }
83
+ };
84
+ //# sourceMappingURL=supersede-writes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supersede-writes.js","sourceRoot":"","sources":["../../../lib/strategies/supersede-writes.ts"],"names":[],"mappings":"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"}