@tarquinen/opencode-dcp 0.4.17 → 1.0.0-beta.2

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/README.md +58 -30
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +19 -59
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/config.d.ts +30 -13
  6. package/dist/lib/config.d.ts.map +1 -1
  7. package/dist/lib/config.js +339 -121
  8. package/dist/lib/config.js.map +1 -1
  9. package/dist/lib/hooks.d.ts +5 -13
  10. package/dist/lib/hooks.d.ts.map +1 -1
  11. package/dist/lib/hooks.js +26 -125
  12. package/dist/lib/hooks.js.map +1 -1
  13. package/dist/lib/logger.d.ts +5 -9
  14. package/dist/lib/logger.d.ts.map +1 -1
  15. package/dist/lib/logger.js +30 -160
  16. package/dist/lib/logger.js.map +1 -1
  17. package/dist/lib/messages/index.d.ts +2 -0
  18. package/dist/lib/messages/index.d.ts.map +1 -0
  19. package/dist/lib/messages/index.js +2 -0
  20. package/dist/lib/messages/index.js.map +1 -0
  21. package/dist/lib/messages/prune.d.ts +6 -0
  22. package/dist/lib/messages/prune.d.ts.map +1 -0
  23. package/dist/lib/messages/prune.js +85 -0
  24. package/dist/lib/messages/prune.js.map +1 -0
  25. package/dist/lib/messages/utils.d.ts +10 -0
  26. package/dist/lib/messages/utils.d.ts.map +1 -0
  27. package/dist/lib/messages/utils.js +103 -0
  28. package/dist/lib/messages/utils.js.map +1 -0
  29. package/dist/lib/model-selector.js +3 -3
  30. package/dist/lib/model-selector.js.map +1 -1
  31. package/dist/lib/{core/prompt.d.ts → prompt.d.ts} +1 -1
  32. package/dist/lib/prompt.d.ts.map +1 -0
  33. package/dist/lib/{core/prompt.js → prompt.js} +2 -6
  34. package/dist/lib/prompt.js.map +1 -0
  35. package/dist/lib/prompts/pruning.txt +1 -1
  36. package/dist/lib/prompts/tool.txt +3 -3
  37. package/dist/lib/state/index.d.ts +3 -27
  38. package/dist/lib/state/index.d.ts.map +1 -1
  39. package/dist/lib/state/index.js +3 -40
  40. package/dist/lib/state/index.js.map +1 -1
  41. package/dist/lib/state/persistence.d.ts +4 -4
  42. package/dist/lib/state/persistence.d.ts.map +1 -1
  43. package/dist/lib/state/persistence.js +24 -20
  44. package/dist/lib/state/persistence.js.map +1 -1
  45. package/dist/lib/state/state.d.ts +7 -0
  46. package/dist/lib/state/state.d.ts.map +1 -0
  47. package/dist/lib/state/state.js +76 -0
  48. package/dist/lib/state/state.js.map +1 -0
  49. package/dist/lib/state/tool-cache.d.ts +4 -6
  50. package/dist/lib/state/tool-cache.d.ts.map +1 -1
  51. package/dist/lib/state/tool-cache.js +20 -46
  52. package/dist/lib/state/tool-cache.js.map +1 -1
  53. package/dist/lib/state/types.d.ts +30 -0
  54. package/dist/lib/state/types.d.ts.map +1 -0
  55. package/dist/lib/state/types.js +2 -0
  56. package/dist/lib/state/types.js.map +1 -0
  57. package/dist/lib/strategies/deduplication.d.ts +10 -0
  58. package/dist/lib/strategies/deduplication.d.ts.map +1 -0
  59. package/dist/lib/strategies/deduplication.js +89 -0
  60. package/dist/lib/strategies/deduplication.js.map +1 -0
  61. package/dist/lib/strategies/index.d.ts +4 -0
  62. package/dist/lib/strategies/index.d.ts.map +1 -0
  63. package/dist/lib/strategies/index.js +4 -0
  64. package/dist/lib/strategies/index.js.map +1 -0
  65. package/dist/lib/strategies/on-idle.d.ts +14 -0
  66. package/dist/lib/strategies/on-idle.d.ts.map +1 -0
  67. package/dist/lib/strategies/on-idle.js +216 -0
  68. package/dist/lib/strategies/on-idle.js.map +1 -0
  69. package/dist/lib/strategies/prune-tool.d.ts +17 -0
  70. package/dist/lib/strategies/prune-tool.d.ts.map +1 -0
  71. package/dist/lib/strategies/prune-tool.js +70 -0
  72. package/dist/lib/strategies/prune-tool.js.map +1 -0
  73. package/dist/lib/ui/display-utils.d.ts +3 -12
  74. package/dist/lib/ui/display-utils.d.ts.map +1 -1
  75. package/dist/lib/ui/display-utils.js +12 -79
  76. package/dist/lib/ui/display-utils.js.map +1 -1
  77. package/dist/lib/ui/notification.d.ts +7 -23
  78. package/dist/lib/ui/notification.d.ts.map +1 -1
  79. package/dist/lib/ui/notification.js +38 -47
  80. package/dist/lib/ui/notification.js.map +1 -1
  81. package/dist/lib/utils.d.ts +9 -0
  82. package/dist/lib/utils.d.ts.map +1 -0
  83. package/dist/lib/utils.js +61 -0
  84. package/dist/lib/utils.js.map +1 -0
  85. package/package.json +1 -1
  86. package/dist/lib/core/janitor.d.ts +0 -38
  87. package/dist/lib/core/janitor.d.ts.map +0 -1
  88. package/dist/lib/core/janitor.js +0 -294
  89. package/dist/lib/core/janitor.js.map +0 -1
  90. package/dist/lib/core/prompt.d.ts.map +0 -1
  91. package/dist/lib/core/prompt.js.map +0 -1
  92. package/dist/lib/core/strategies/deduplication.d.ts +0 -7
  93. package/dist/lib/core/strategies/deduplication.d.ts.map +0 -1
  94. package/dist/lib/core/strategies/deduplication.js +0 -76
  95. package/dist/lib/core/strategies/deduplication.js.map +0 -1
  96. package/dist/lib/core/strategies/index.d.ts +0 -51
  97. package/dist/lib/core/strategies/index.d.ts.map +0 -1
  98. package/dist/lib/core/strategies/index.js +0 -48
  99. package/dist/lib/core/strategies/index.js.map +0 -1
  100. package/dist/lib/fetch-wrapper/formats/anthropic.d.ts +0 -8
  101. package/dist/lib/fetch-wrapper/formats/anthropic.d.ts.map +0 -1
  102. package/dist/lib/fetch-wrapper/formats/anthropic.js +0 -96
  103. package/dist/lib/fetch-wrapper/formats/anthropic.js.map +0 -1
  104. package/dist/lib/fetch-wrapper/formats/bedrock.d.ts +0 -8
  105. package/dist/lib/fetch-wrapper/formats/bedrock.d.ts.map +0 -1
  106. package/dist/lib/fetch-wrapper/formats/bedrock.js +0 -97
  107. package/dist/lib/fetch-wrapper/formats/bedrock.js.map +0 -1
  108. package/dist/lib/fetch-wrapper/formats/gemini.d.ts +0 -8
  109. package/dist/lib/fetch-wrapper/formats/gemini.d.ts.map +0 -1
  110. package/dist/lib/fetch-wrapper/formats/gemini.js +0 -134
  111. package/dist/lib/fetch-wrapper/formats/gemini.js.map +0 -1
  112. package/dist/lib/fetch-wrapper/formats/index.d.ts +0 -6
  113. package/dist/lib/fetch-wrapper/formats/index.d.ts.map +0 -1
  114. package/dist/lib/fetch-wrapper/formats/index.js +0 -6
  115. package/dist/lib/fetch-wrapper/formats/index.js.map +0 -1
  116. package/dist/lib/fetch-wrapper/formats/openai-chat.d.ts +0 -3
  117. package/dist/lib/fetch-wrapper/formats/openai-chat.d.ts.map +0 -1
  118. package/dist/lib/fetch-wrapper/formats/openai-chat.js +0 -100
  119. package/dist/lib/fetch-wrapper/formats/openai-chat.js.map +0 -1
  120. package/dist/lib/fetch-wrapper/formats/openai-responses.d.ts +0 -3
  121. package/dist/lib/fetch-wrapper/formats/openai-responses.d.ts.map +0 -1
  122. package/dist/lib/fetch-wrapper/formats/openai-responses.js +0 -63
  123. package/dist/lib/fetch-wrapper/formats/openai-responses.js.map +0 -1
  124. package/dist/lib/fetch-wrapper/gc-tracker.d.ts +0 -4
  125. package/dist/lib/fetch-wrapper/gc-tracker.d.ts.map +0 -1
  126. package/dist/lib/fetch-wrapper/gc-tracker.js +0 -61
  127. package/dist/lib/fetch-wrapper/gc-tracker.js.map +0 -1
  128. package/dist/lib/fetch-wrapper/handler.d.ts +0 -3
  129. package/dist/lib/fetch-wrapper/handler.d.ts.map +0 -1
  130. package/dist/lib/fetch-wrapper/handler.js +0 -118
  131. package/dist/lib/fetch-wrapper/handler.js.map +0 -1
  132. package/dist/lib/fetch-wrapper/index.d.ts +0 -18
  133. package/dist/lib/fetch-wrapper/index.d.ts.map +0 -1
  134. package/dist/lib/fetch-wrapper/index.js +0 -107
  135. package/dist/lib/fetch-wrapper/index.js.map +0 -1
  136. package/dist/lib/fetch-wrapper/prunable-list.d.ts +0 -8
  137. package/dist/lib/fetch-wrapper/prunable-list.d.ts.map +0 -1
  138. package/dist/lib/fetch-wrapper/prunable-list.js +0 -38
  139. package/dist/lib/fetch-wrapper/prunable-list.js.map +0 -1
  140. package/dist/lib/fetch-wrapper/tool-tracker.d.ts +0 -9
  141. package/dist/lib/fetch-wrapper/tool-tracker.d.ts.map +0 -1
  142. package/dist/lib/fetch-wrapper/tool-tracker.js +0 -12
  143. package/dist/lib/fetch-wrapper/tool-tracker.js.map +0 -1
  144. package/dist/lib/fetch-wrapper/types.d.ts +0 -62
  145. package/dist/lib/fetch-wrapper/types.d.ts.map +0 -1
  146. package/dist/lib/fetch-wrapper/types.js +0 -7
  147. package/dist/lib/fetch-wrapper/types.js.map +0 -1
  148. package/dist/lib/pruning-tool.d.ts +0 -20
  149. package/dist/lib/pruning-tool.d.ts.map +0 -1
  150. package/dist/lib/pruning-tool.js +0 -160
  151. package/dist/lib/pruning-tool.js.map +0 -1
  152. package/dist/lib/state/id-mapping.d.ts +0 -25
  153. package/dist/lib/state/id-mapping.d.ts.map +0 -1
  154. package/dist/lib/state/id-mapping.js +0 -51
  155. package/dist/lib/state/id-mapping.js.map +0 -1
  156. package/dist/lib/tokenizer.d.ts +0 -3
  157. package/dist/lib/tokenizer.d.ts.map +0 -1
  158. package/dist/lib/tokenizer.js +0 -16
  159. package/dist/lib/tokenizer.js.map +0 -1
  160. package/dist/lib/version-checker.d.ts +0 -9
  161. package/dist/lib/version-checker.d.ts.map +0 -1
  162. package/dist/lib/version-checker.js +0 -77
  163. package/dist/lib/version-checker.js.map +0 -1
@@ -1,66 +1,40 @@
1
- /** Maximum number of entries to keep in the tool parameters cache */
2
- const MAX_TOOL_CACHE_SIZE = 500;
1
+ const MAX_TOOL_CACHE_SIZE = 1000;
3
2
  /**
4
3
  * Sync tool parameters from OpenCode's session.messages() API.
5
- * This is the single source of truth for tool parameters, replacing
6
- * format-specific parsing from LLM API requests.
7
4
  */
8
- export async function syncToolCache(client, sessionId, state, tracker, protectedTools, logger) {
5
+ export async function syncToolCache(state, config, logger, messages) {
9
6
  try {
10
- const messagesResponse = await client.session.messages({
11
- path: { id: sessionId },
12
- query: { limit: 500 }
13
- });
14
- const messages = messagesResponse.data || messagesResponse;
15
- if (!Array.isArray(messages)) {
16
- return;
17
- }
18
- let synced = 0;
19
- // Build lowercase set of pruned IDs for comparison (IDs in state may be mixed case)
20
- const prunedIdsLower = tracker
21
- ? new Set((state.prunedIds.get(sessionId) ?? []).map(id => id.toLowerCase()))
22
- : null;
7
+ logger.info("Syncing tool parameters from OpenCode messages");
8
+ state.nudgeCounter = 0;
23
9
  for (const msg of messages) {
24
- if (!msg.parts)
25
- continue;
26
10
  for (const part of msg.parts) {
27
- if (part.type !== "tool" || !part.callID)
11
+ if (part.type !== "tool" || !part.callID) {
28
12
  continue;
29
- const id = part.callID.toLowerCase();
30
- // Track tool results for nudge injection
31
- if (tracker && !tracker.seenToolResultIds.has(id)) {
32
- tracker.seenToolResultIds.add(id);
33
- // Only count non-protected tools toward nudge threshold
34
- // Also skip already-pruned tools to avoid re-counting on restart
35
- if ((!part.tool || !protectedTools?.has(part.tool)) && !prunedIdsLower?.has(id)) {
36
- tracker.toolResultCount++;
37
- }
38
13
  }
39
- if (state.toolParameters.has(id))
40
- continue;
41
- if (part.tool && protectedTools?.has(part.tool))
14
+ if (part.tool === "prune") {
15
+ state.nudgeCounter = 0;
16
+ }
17
+ else if (!config.strategies.pruneTool.protectedTools.includes(part.tool)) {
18
+ state.nudgeCounter++;
19
+ }
20
+ state.lastToolPrune = part.tool === "prune";
21
+ if (state.toolParameters.has(part.callID)) {
42
22
  continue;
43
- const status = part.state?.status;
44
- state.toolParameters.set(id, {
23
+ }
24
+ state.toolParameters.set(part.callID, {
45
25
  tool: part.tool,
46
26
  parameters: part.state?.input ?? {},
47
- status,
48
- error: status === "error" ? part.state?.error : undefined,
27
+ status: part.state.status,
28
+ error: part.state.status === "error" ? part.state.error : undefined,
29
+ compacted: part.state.status === "completed" && !!part.state.time.compacted,
49
30
  });
50
- synced++;
51
31
  }
52
32
  }
33
+ // logger.info(`nudgeCounter=${state.nudgeCounter}, lastToolPrune=${state.lastToolPrune}`)
53
34
  trimToolParametersCache(state);
54
- if (logger && synced > 0) {
55
- logger.debug("tool-cache", "Synced tool parameters from OpenCode", {
56
- sessionId: sessionId.slice(0, 8),
57
- synced
58
- });
59
- }
60
35
  }
61
36
  catch (error) {
62
- logger?.warn("tool-cache", "Failed to sync tool parameters from OpenCode", {
63
- sessionId: sessionId.slice(0, 8),
37
+ logger.warn("Failed to sync tool parameters from OpenCode", {
64
38
  error: error instanceof Error ? error.message : String(error)
65
39
  });
66
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tool-cache.js","sourceRoot":"","sources":["../../../lib/state/tool-cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool-cache.js","sourceRoot":"","sources":["../../../lib/state/tool-cache.ts"],"names":[],"mappings":"AAIA,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;QAEtB,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YACzB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC3B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACvC,SAAQ;gBACZ,CAAC;gBAED,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBACxB,KAAK,CAAC,YAAY,GAAG,CAAC,CAAA;gBAC1B,CAAC;qBAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzE,KAAK,CAAC,YAAY,EAAE,CAAA;gBACxB,CAAC;gBACD,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,KAAK,OAAO,CAAA;gBAE3C,IAAI,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACxC,SAAQ;gBACZ,CAAC;gBAED,KAAK,CAAC,cAAc,CAAC,GAAG,CACpB,IAAI,CAAC,MAAM,EACX;oBACI,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,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS;iBAC9E,CACJ,CAAA;YACL,CAAC;QACL,CAAC;QAED,0FAA0F;QAE1F,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;SACvD,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,GAAG,mBAAmB,CAAC,CAAA;IAE9D,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC7B,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACpC,CAAC;AACL,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { Message, Part } from "@opencode-ai/sdk";
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
+ compacted?: boolean;
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
+ }
30
+ //# 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,kBAAkB,CAAA;AAEhD,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,SAAS,CAAC,EAAE,OAAO,CAAA;CACtB;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;CACzB"}
@@ -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,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;AAIvD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACpB,OAAO,YAAY,EACnB,QAAQ,MAAM,EACd,QAAQ,YAAY,EACpB,UAAU,SAAS,EAAE,KACtB,IA4DF,CAAA"}
@@ -0,0 +1,89 @@
1
+ import { calculateTokensSaved } from "../utils";
2
+ import { buildToolIdList } from "../messages/utils";
3
+ /**
4
+ * Deduplication strategy - prunes older tool calls that have identical
5
+ * tool name and parameters, keeping only the most recent occurrence.
6
+ * Modifies the session state in place to add pruned tool call IDs.
7
+ */
8
+ export const deduplicate = (state, logger, config, messages) => {
9
+ if (!config.strategies.deduplication.enabled) {
10
+ return;
11
+ }
12
+ // Build list of all tool call IDs from messages (chronological order)
13
+ const allToolIds = buildToolIdList(messages);
14
+ if (allToolIds.length === 0) {
15
+ return;
16
+ }
17
+ // Filter out IDs already pruned
18
+ const alreadyPruned = new Set(state.prune.toolIds);
19
+ const unprunedIds = allToolIds.filter(id => !alreadyPruned.has(id));
20
+ if (unprunedIds.length === 0) {
21
+ return;
22
+ }
23
+ const protectedTools = config.strategies.deduplication.protectedTools;
24
+ // Group by signature (tool name + normalized parameters)
25
+ const signatureMap = new Map();
26
+ for (const id of unprunedIds) {
27
+ const metadata = state.toolParameters.get(id);
28
+ if (!metadata) {
29
+ logger.warn(`Missing metadata for tool call ID: ${id}`);
30
+ continue;
31
+ }
32
+ // Skip protected tools
33
+ if (protectedTools.includes(metadata.tool)) {
34
+ continue;
35
+ }
36
+ const signature = createToolSignature(metadata.tool, metadata.parameters);
37
+ if (!signatureMap.has(signature)) {
38
+ signatureMap.set(signature, []);
39
+ }
40
+ signatureMap.get(signature).push(id);
41
+ }
42
+ // Find duplicates - keep only the most recent (last) in each group
43
+ const newPruneIds = [];
44
+ for (const [, ids] of signatureMap.entries()) {
45
+ if (ids.length > 1) {
46
+ // All except last (most recent) should be pruned
47
+ const idsToRemove = ids.slice(0, -1);
48
+ newPruneIds.push(...idsToRemove);
49
+ }
50
+ }
51
+ state.stats.totalPruneTokens += calculateTokensSaved(messages, newPruneIds);
52
+ if (newPruneIds.length > 0) {
53
+ state.prune.toolIds.push(...newPruneIds);
54
+ logger.debug(`Marked ${newPruneIds.length} duplicate tool calls for pruning`);
55
+ }
56
+ };
57
+ function createToolSignature(tool, parameters) {
58
+ if (!parameters) {
59
+ return tool;
60
+ }
61
+ const normalized = normalizeParameters(parameters);
62
+ const sorted = sortObjectKeys(normalized);
63
+ return `${tool}::${JSON.stringify(sorted)}`;
64
+ }
65
+ function normalizeParameters(params) {
66
+ if (typeof params !== 'object' || params === null)
67
+ return params;
68
+ if (Array.isArray(params))
69
+ return params;
70
+ const normalized = {};
71
+ for (const [key, value] of Object.entries(params)) {
72
+ if (value !== undefined && value !== null) {
73
+ normalized[key] = value;
74
+ }
75
+ }
76
+ return normalized;
77
+ }
78
+ function sortObjectKeys(obj) {
79
+ if (typeof obj !== 'object' || obj === null)
80
+ return obj;
81
+ if (Array.isArray(obj))
82
+ return obj.map(sortObjectKeys);
83
+ const sorted = {};
84
+ for (const key of Object.keys(obj).sort()) {
85
+ sorted[key] = sortObjectKeys(obj[key]);
86
+ }
87
+ return sorted;
88
+ }
89
+ //# 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,4 @@
1
+ export { deduplicate } from "./deduplication";
2
+ export { runOnIdle } from "./on-idle";
3
+ export { createPruneTool } from "./prune-tool";
4
+ //# 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,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,4 @@
1
+ export { deduplicate } from "./deduplication";
2
+ export { runOnIdle } from "./on-idle";
3
+ export { createPruneTool } from "./prune-tool";
4
+ //# 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,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,14 @@
1
+ import type { SessionState } from "../state";
2
+ import type { Logger } from "../logger";
3
+ import type { PluginConfig } from "../config";
4
+ export interface OnIdleResult {
5
+ prunedCount: number;
6
+ tokensSaved: number;
7
+ prunedIds: string[];
8
+ }
9
+ /**
10
+ * Run the onIdle pruning strategy.
11
+ * This is called when the session transitions to idle state.
12
+ */
13
+ export declare function runOnIdle(client: any, state: SessionState, logger: Logger, config: PluginConfig, workingDirectory?: string): Promise<void | null>;
14
+ //# sourceMappingURL=on-idle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-idle.d.ts","sourceRoot":"","sources":["../../../lib/strategies/on-idle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAiC,MAAM,UAAU,CAAA;AAC3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAQ7C,MAAM,WAAW,YAAY;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,EAAE,CAAA;CACtB;AAoLD;;;GAGG;AACH,wBAAsB,SAAS,CAC3B,MAAM,EAAE,GAAG,EACX,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,YAAY,EACpB,gBAAgB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAgHtB"}
@@ -0,0 +1,216 @@
1
+ import { z } from "zod";
2
+ import { buildAnalysisPrompt } from "../prompt";
3
+ import { selectModel } from "../model-selector";
4
+ import { calculateTokensSaved } from "../utils";
5
+ import { findCurrentAgent } from "../messages/utils";
6
+ import { saveSessionState } from "../state/persistence";
7
+ import { sendUnifiedNotification } from "../ui/notification";
8
+ /**
9
+ * Parse messages to extract tool information.
10
+ */
11
+ function parseMessages(messages, toolParametersCache) {
12
+ const toolCallIds = [];
13
+ const toolMetadata = new Map();
14
+ for (const msg of messages) {
15
+ if (msg.parts) {
16
+ for (const part of msg.parts) {
17
+ if (part.type === "tool" && part.callID) {
18
+ toolCallIds.push(part.callID);
19
+ const cachedData = toolParametersCache.get(part.callID);
20
+ const parameters = cachedData?.parameters ?? part.state?.input ?? {};
21
+ toolMetadata.set(part.callID, {
22
+ tool: part.tool,
23
+ parameters: parameters,
24
+ status: part.state?.status,
25
+ error: part.state?.status === "error" ? part.state.error : undefined
26
+ });
27
+ }
28
+ }
29
+ }
30
+ }
31
+ return { toolCallIds, toolMetadata };
32
+ }
33
+ /**
34
+ * Replace pruned tool outputs in messages for LLM analysis.
35
+ */
36
+ function replacePrunedToolOutputs(messages, prunedIds) {
37
+ if (prunedIds.length === 0)
38
+ return messages;
39
+ const prunedIdsSet = new Set(prunedIds);
40
+ return messages.map(msg => {
41
+ if (!msg.parts)
42
+ return msg;
43
+ return {
44
+ ...msg,
45
+ parts: msg.parts.map((part) => {
46
+ if (part.type === 'tool' &&
47
+ part.callID &&
48
+ prunedIdsSet.has(part.callID) &&
49
+ part.state?.output) {
50
+ return {
51
+ ...part,
52
+ state: {
53
+ ...part.state,
54
+ output: '[Output removed to save context - information superseded or no longer needed]'
55
+ }
56
+ };
57
+ }
58
+ return part;
59
+ })
60
+ };
61
+ });
62
+ }
63
+ /**
64
+ * Run LLM analysis to determine which tool calls can be pruned.
65
+ */
66
+ async function runLlmAnalysis(client, state, logger, config, messages, unprunedToolCallIds, alreadyPrunedIds, toolMetadata, workingDirectory) {
67
+ const protectedToolCallIds = [];
68
+ const prunableToolCallIds = unprunedToolCallIds.filter(id => {
69
+ const metadata = toolMetadata.get(id);
70
+ if (metadata && config.strategies.onIdle.protectedTools.includes(metadata.tool)) {
71
+ protectedToolCallIds.push(id);
72
+ return false;
73
+ }
74
+ return true;
75
+ });
76
+ if (prunableToolCallIds.length === 0) {
77
+ return [];
78
+ }
79
+ // Get model info from messages
80
+ let validModelInfo = undefined;
81
+ if (messages.length > 0) {
82
+ const lastMessage = messages[messages.length - 1];
83
+ const model = lastMessage.info?.model;
84
+ if (model?.providerID && model?.modelID) {
85
+ validModelInfo = {
86
+ providerID: model.providerID,
87
+ modelID: model.modelID
88
+ };
89
+ }
90
+ }
91
+ const modelSelection = await selectModel(validModelInfo, logger, config.strategies.onIdle.model, workingDirectory);
92
+ logger.info(`OnIdle Model: ${modelSelection.modelInfo.providerID}/${modelSelection.modelInfo.modelID}`, {
93
+ source: modelSelection.source
94
+ });
95
+ if (modelSelection.failedModel && config.strategies.onIdle.showModelErrorToasts) {
96
+ const skipAi = modelSelection.source === 'fallback' && config.strategies.onIdle.strictModelSelection;
97
+ try {
98
+ await client.tui.showToast({
99
+ body: {
100
+ title: skipAi ? "DCP: AI analysis skipped" : "DCP: Model fallback",
101
+ message: skipAi
102
+ ? `${modelSelection.failedModel.providerID}/${modelSelection.failedModel.modelID} failed\nAI analysis skipped (strictModelSelection enabled)`
103
+ : `${modelSelection.failedModel.providerID}/${modelSelection.failedModel.modelID} failed\nUsing ${modelSelection.modelInfo.providerID}/${modelSelection.modelInfo.modelID}`,
104
+ variant: "info",
105
+ duration: 5000
106
+ }
107
+ });
108
+ }
109
+ catch {
110
+ // Ignore toast errors
111
+ }
112
+ }
113
+ if (modelSelection.source === 'fallback' && config.strategies.onIdle.strictModelSelection) {
114
+ logger.info("Skipping AI analysis (fallback model, strictModelSelection enabled)");
115
+ return [];
116
+ }
117
+ const { generateObject } = await import('ai');
118
+ const sanitizedMessages = replacePrunedToolOutputs(messages, alreadyPrunedIds);
119
+ const analysisPrompt = buildAnalysisPrompt(prunableToolCallIds, sanitizedMessages, alreadyPrunedIds, protectedToolCallIds);
120
+ const result = await generateObject({
121
+ model: modelSelection.model,
122
+ schema: z.object({
123
+ pruned_tool_call_ids: z.array(z.string()),
124
+ reasoning: z.string(),
125
+ }),
126
+ prompt: analysisPrompt
127
+ });
128
+ const rawLlmPrunedIds = result.object.pruned_tool_call_ids;
129
+ const llmPrunedIds = rawLlmPrunedIds.filter(id => prunableToolCallIds.includes(id));
130
+ // Always log LLM output as debug
131
+ const reasoning = result.object.reasoning.replace(/\n+/g, ' ').replace(/\s+/g, ' ').trim();
132
+ logger.debug(`OnIdle LLM output`, {
133
+ pruned_tool_call_ids: rawLlmPrunedIds,
134
+ reasoning: reasoning
135
+ });
136
+ return llmPrunedIds;
137
+ }
138
+ /**
139
+ * Run the onIdle pruning strategy.
140
+ * This is called when the session transitions to idle state.
141
+ */
142
+ export async function runOnIdle(client, state, logger, config, workingDirectory) {
143
+ try {
144
+ if (!state.sessionId) {
145
+ return null;
146
+ }
147
+ const sessionId = state.sessionId;
148
+ // Fetch session info and messages
149
+ const [sessionInfoResponse, messagesResponse] = await Promise.all([
150
+ client.session.get({ path: { id: sessionId } }),
151
+ client.session.messages({ path: { id: sessionId } })
152
+ ]);
153
+ const sessionInfo = sessionInfoResponse.data;
154
+ const messages = messagesResponse.data || messagesResponse;
155
+ if (!messages || messages.length < 3) {
156
+ return null;
157
+ }
158
+ const currentAgent = findCurrentAgent(messages);
159
+ const { toolCallIds, toolMetadata } = parseMessages(messages, state.toolParameters);
160
+ const alreadyPrunedIds = state.prune.toolIds;
161
+ const unprunedToolCallIds = toolCallIds.filter(id => !alreadyPrunedIds.includes(id));
162
+ if (unprunedToolCallIds.length === 0) {
163
+ return null;
164
+ }
165
+ // Count prunable tools (excluding protected)
166
+ const candidateCount = unprunedToolCallIds.filter(id => {
167
+ const metadata = toolMetadata.get(id);
168
+ return !metadata || !config.strategies.onIdle.protectedTools.includes(metadata.tool);
169
+ }).length;
170
+ if (candidateCount === 0) {
171
+ return null;
172
+ }
173
+ // Run LLM analysis
174
+ const llmPrunedIds = await runLlmAnalysis(client, state, logger, config, messages, unprunedToolCallIds, alreadyPrunedIds, toolMetadata, workingDirectory);
175
+ const newlyPrunedIds = llmPrunedIds.filter(id => !alreadyPrunedIds.includes(id));
176
+ if (newlyPrunedIds.length === 0) {
177
+ return null;
178
+ }
179
+ // Log the tool IDs being pruned with their tool names
180
+ for (const id of newlyPrunedIds) {
181
+ const metadata = toolMetadata.get(id);
182
+ const toolName = metadata?.tool || 'unknown';
183
+ logger.info(`OnIdle pruning tool: ${toolName}`, { callID: id });
184
+ }
185
+ // Update state
186
+ const allPrunedIds = [...new Set([...alreadyPrunedIds, ...newlyPrunedIds])];
187
+ state.prune.toolIds = allPrunedIds;
188
+ state.stats.pruneTokenCounter += calculateTokensSaved(messages, newlyPrunedIds);
189
+ // Build tool metadata map for notification
190
+ const prunedToolMetadata = new Map();
191
+ for (const id of newlyPrunedIds) {
192
+ const metadata = toolMetadata.get(id);
193
+ if (metadata) {
194
+ prunedToolMetadata.set(id, metadata);
195
+ }
196
+ }
197
+ // Send notification
198
+ await sendUnifiedNotification(client, logger, config, state, sessionId, newlyPrunedIds, prunedToolMetadata, undefined, // reason
199
+ currentAgent, workingDirectory || "");
200
+ state.stats.totalPruneTokens += state.stats.pruneTokenCounter;
201
+ state.stats.pruneTokenCounter = 0;
202
+ state.nudgeCounter = 0;
203
+ state.lastToolPrune = true;
204
+ // Persist state
205
+ const sessionName = sessionInfo?.title;
206
+ saveSessionState(state, logger, sessionName).catch(err => {
207
+ logger.error("Failed to persist state", { error: err.message });
208
+ });
209
+ logger.info(`OnIdle: Pruned ${newlyPrunedIds.length}/${candidateCount} tools`);
210
+ }
211
+ catch (error) {
212
+ logger.error("OnIdle analysis failed", { error: error.message });
213
+ return null;
214
+ }
215
+ }
216
+ //# sourceMappingURL=on-idle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"on-idle.js","sourceRoot":"","sources":["../../../lib/strategies/on-idle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { tool } from "@opencode-ai/plugin";
2
+ import type { SessionState } from "../state";
3
+ import type { PluginConfig } from "../config";
4
+ import type { Logger } from "../logger";
5
+ export interface PruneToolContext {
6
+ client: any;
7
+ state: SessionState;
8
+ logger: Logger;
9
+ config: PluginConfig;
10
+ workingDirectory: string;
11
+ }
12
+ /**
13
+ * Creates the prune tool definition.
14
+ * Accepts numeric IDs from the <prunable-tools> list and prunes those tool outputs.
15
+ */
16
+ export declare function createPruneTool(ctx: PruneToolContext): ReturnType<typeof tool>;
17
+ //# sourceMappingURL=prune-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune-tool.d.ts","sourceRoot":"","sources":["../../../lib/strategies/prune-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAiC,MAAM,UAAU,CAAA;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAO7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAMvC,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,GAAG,CAAA;IACX,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,YAAY,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;CAC3B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC3B,GAAG,EAAE,gBAAgB,GACtB,UAAU,CAAC,OAAO,IAAI,CAAC,CAoFzB"}
@@ -0,0 +1,70 @@
1
+ import { tool } from "@opencode-ai/plugin";
2
+ import { findCurrentAgent, buildToolIdList, getPruneToolIds } from "../messages/utils";
3
+ import { calculateTokensSaved } from "../utils";
4
+ import { sendUnifiedNotification } from "../ui/notification";
5
+ import { formatPruningResultForTool } from "../ui/display-utils";
6
+ import { ensureSessionInitialized } from "../state";
7
+ import { saveSessionState } from "../state/persistence";
8
+ import { loadPrompt } from "../prompt";
9
+ /** Tool description loaded from prompts/tool.txt */
10
+ const TOOL_DESCRIPTION = loadPrompt("tool");
11
+ /**
12
+ * Creates the prune tool definition.
13
+ * Accepts numeric IDs from the <prunable-tools> list and prunes those tool outputs.
14
+ */
15
+ export function createPruneTool(ctx) {
16
+ return tool({
17
+ description: TOOL_DESCRIPTION,
18
+ args: {
19
+ ids: tool.schema.array(tool.schema.string()).describe("First element is the reason ('completion', 'noise', 'consolidation'), followed by numeric IDs as strings to prune"),
20
+ },
21
+ async execute(args, toolCtx) {
22
+ const { client, state, logger, config, workingDirectory } = ctx;
23
+ const sessionId = toolCtx.sessionID;
24
+ if (!args.ids || args.ids.length === 0) {
25
+ return "No IDs provided. Check the <prunable-tools> list for available IDs to prune.";
26
+ }
27
+ // Parse reason from first element, numeric IDs from the rest
28
+ const reason = args.ids[0];
29
+ const validReasons = ["completion", "noise", "consolidation"];
30
+ if (typeof reason !== "string" || !validReasons.includes(reason)) {
31
+ return "No valid pruning reason found. Use 'completion', 'noise', or 'consolidation' as the first element.";
32
+ }
33
+ const numericToolIds = args.ids.slice(1)
34
+ .map(id => parseInt(id, 10))
35
+ .filter((n) => !isNaN(n));
36
+ if (numericToolIds.length === 0) {
37
+ return "No numeric IDs provided. Format: [reason, id1, id2, ...] where reason is 'completion', 'noise', or 'consolidation'.";
38
+ }
39
+ await ensureSessionInitialized(ctx.client, state, sessionId, logger);
40
+ // Fetch messages to calculate tokens and find current agent
41
+ const messagesResponse = await client.session.messages({
42
+ path: { id: sessionId }
43
+ });
44
+ const messages = messagesResponse.data || messagesResponse;
45
+ const currentAgent = findCurrentAgent(messages);
46
+ const toolIdList = buildToolIdList(messages);
47
+ const pruneToolIds = getPruneToolIds(numericToolIds, toolIdList);
48
+ state.prune.toolIds.push(...pruneToolIds);
49
+ const toolMetadata = new Map();
50
+ for (const id of pruneToolIds) {
51
+ const toolParameters = state.toolParameters.get(id);
52
+ if (toolParameters) {
53
+ toolMetadata.set(id, toolParameters);
54
+ }
55
+ else {
56
+ logger.debug("No metadata found for ID", { id });
57
+ }
58
+ }
59
+ state.stats.pruneTokenCounter += calculateTokensSaved(messages, pruneToolIds);
60
+ await sendUnifiedNotification(client, logger, config, state, sessionId, pruneToolIds, toolMetadata, reason, currentAgent, workingDirectory);
61
+ state.stats.totalPruneTokens += state.stats.pruneTokenCounter;
62
+ state.stats.pruneTokenCounter = 0;
63
+ state.nudgeCounter = 0;
64
+ saveSessionState(state, logger)
65
+ .catch(err => logger.error("Failed to persist state", { error: err.message }));
66
+ return formatPruningResultForTool(pruneToolIds, toolMetadata, workingDirectory);
67
+ },
68
+ });
69
+ }
70
+ //# sourceMappingURL=prune-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune-tool.js","sourceRoot":"","sources":["../../../lib/strategies/prune-tool.ts"],"names":[],"mappings":"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"}