@tarquinen/opencode-dcp 0.3.20 → 0.3.22

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 (45) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +17 -190
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/fetch-wrapper/gemini.d.ts +7 -0
  6. package/dist/lib/fetch-wrapper/gemini.d.ts.map +1 -0
  7. package/dist/lib/fetch-wrapper/gemini.js +100 -0
  8. package/dist/lib/fetch-wrapper/gemini.js.map +1 -0
  9. package/dist/lib/fetch-wrapper/index.d.ts +15 -0
  10. package/dist/lib/fetch-wrapper/index.d.ts.map +1 -0
  11. package/dist/lib/fetch-wrapper/index.js +64 -0
  12. package/dist/lib/fetch-wrapper/index.js.map +1 -0
  13. package/dist/lib/fetch-wrapper/openai-chat.d.ts +7 -0
  14. package/dist/lib/fetch-wrapper/openai-chat.d.ts.map +1 -0
  15. package/dist/lib/fetch-wrapper/openai-chat.js +81 -0
  16. package/dist/lib/fetch-wrapper/openai-chat.js.map +1 -0
  17. package/dist/lib/fetch-wrapper/openai-responses.d.ts +7 -0
  18. package/dist/lib/fetch-wrapper/openai-responses.d.ts.map +1 -0
  19. package/dist/lib/fetch-wrapper/openai-responses.js +54 -0
  20. package/dist/lib/fetch-wrapper/openai-responses.js.map +1 -0
  21. package/dist/lib/fetch-wrapper/types.d.ts +35 -0
  22. package/dist/lib/fetch-wrapper/types.d.ts.map +1 -0
  23. package/dist/lib/fetch-wrapper/types.js +43 -0
  24. package/dist/lib/fetch-wrapper/types.js.map +1 -0
  25. package/dist/lib/hooks.d.ts +19 -0
  26. package/dist/lib/hooks.d.ts.map +1 -0
  27. package/dist/lib/hooks.js +94 -0
  28. package/dist/lib/hooks.js.map +1 -0
  29. package/dist/lib/janitor.d.ts +1 -0
  30. package/dist/lib/janitor.d.ts.map +1 -1
  31. package/dist/lib/janitor.js +1 -0
  32. package/dist/lib/janitor.js.map +1 -1
  33. package/dist/lib/pruning-tool.d.ts +11 -0
  34. package/dist/lib/pruning-tool.d.ts.map +1 -0
  35. package/dist/lib/pruning-tool.js +66 -0
  36. package/dist/lib/pruning-tool.js.map +1 -0
  37. package/dist/lib/state.d.ts +33 -0
  38. package/dist/lib/state.d.ts.map +1 -0
  39. package/dist/lib/state.js +13 -0
  40. package/dist/lib/state.js.map +1 -0
  41. package/dist/lib/tool-cache.d.ts +12 -0
  42. package/dist/lib/tool-cache.d.ts.map +1 -0
  43. package/dist/lib/tool-cache.js +52 -0
  44. package/dist/lib/tool-cache.js.map +1 -0
  45. package/package.json +1 -1
package/README.md CHANGED
@@ -13,7 +13,7 @@ Add to your OpenCode config:
13
13
  ```jsonc
14
14
  // opencode.jsonc
15
15
  {
16
- "plugin": ["@tarquinen/opencode-dcp@0.3.20"]
16
+ "plugin": ["@tarquinen/opencode-dcp@0.3.22"]
17
17
  }
18
18
  ```
19
19
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAgBjD,QAAA,MAAM,MAAM,EAAE,MAwPK,CAAA;AAEnB,eAAe,MAAM,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAUjD,QAAA,MAAM,MAAM,EAAE,MAsEK,CAAA;AAEnB,eAAe,MAAM,CAAA"}
package/dist/index.js CHANGED
@@ -1,132 +1,36 @@
1
- import { tool } from "@opencode-ai/plugin";
2
1
  import { getConfig } from "./lib/config";
3
2
  import { Logger } from "./lib/logger";
4
3
  import { Janitor } from "./lib/janitor";
5
4
  import { checkForUpdates } from "./lib/version-checker";
6
- async function isSubagentSession(client, sessionID) {
7
- try {
8
- const result = await client.session.get({ path: { id: sessionID } });
9
- return !!result.data?.parentID;
10
- }
11
- catch (error) {
12
- return false;
13
- }
14
- }
5
+ import { createPluginState } from "./lib/state";
6
+ import { installFetchWrapper } from "./lib/fetch-wrapper";
7
+ import { createPruningTool } from "./lib/pruning-tool";
8
+ import { createEventHandler, createChatParamsHandler } from "./lib/hooks";
15
9
  const plugin = (async (ctx) => {
16
10
  const { config, migrations } = getConfig(ctx);
17
11
  if (!config.enabled) {
18
12
  return {};
19
13
  }
14
+ // Suppress AI SDK warnings
20
15
  if (typeof globalThis !== 'undefined') {
21
16
  globalThis.AI_SDK_LOG_WARNINGS = false;
22
17
  }
18
+ // Initialize core components
23
19
  const logger = new Logger(config.debug);
24
- const prunedIdsState = new Map();
25
- const statsState = new Map();
26
- const toolParametersCache = new Map();
27
- const modelCache = new Map();
28
- const janitor = new Janitor(ctx.client, prunedIdsState, statsState, logger, toolParametersCache, config.protectedTools, modelCache, config.model, config.showModelErrorToasts, config.strictModelSelection, config.pruning_summary, ctx.directory);
29
- const cacheToolParameters = (messages) => {
30
- for (const message of messages) {
31
- if (message.role !== 'assistant' || !Array.isArray(message.tool_calls)) {
32
- continue;
33
- }
34
- for (const toolCall of message.tool_calls) {
35
- if (!toolCall.id || !toolCall.function) {
36
- continue;
37
- }
38
- try {
39
- const params = typeof toolCall.function.arguments === 'string'
40
- ? JSON.parse(toolCall.function.arguments)
41
- : toolCall.function.arguments;
42
- toolParametersCache.set(toolCall.id, {
43
- tool: toolCall.function.name,
44
- parameters: params
45
- });
46
- }
47
- catch (error) {
48
- }
49
- }
50
- }
51
- };
52
- // Global fetch wrapper - caches tool parameters and performs pruning
53
- const originalGlobalFetch = globalThis.fetch;
54
- globalThis.fetch = async (input, init) => {
55
- if (init?.body && typeof init.body === 'string') {
56
- try {
57
- const body = JSON.parse(init.body);
58
- if (body.messages && Array.isArray(body.messages)) {
59
- cacheToolParameters(body.messages);
60
- const toolMessages = body.messages.filter((m) => m.role === 'tool');
61
- const allSessions = await ctx.client.session.list();
62
- const allPrunedIds = new Set();
63
- if (allSessions.data) {
64
- for (const session of allSessions.data) {
65
- if (session.parentID)
66
- continue;
67
- const prunedIds = prunedIdsState.get(session.id) ?? [];
68
- prunedIds.forEach((id) => allPrunedIds.add(id));
69
- }
70
- }
71
- if (toolMessages.length > 0 && allPrunedIds.size > 0) {
72
- let replacedCount = 0;
73
- body.messages = body.messages.map((m) => {
74
- if (m.role === 'tool' && allPrunedIds.has(m.tool_call_id?.toLowerCase())) {
75
- replacedCount++;
76
- return {
77
- ...m,
78
- content: '[Output removed to save context - information superseded or no longer needed]'
79
- };
80
- }
81
- return m;
82
- });
83
- if (replacedCount > 0) {
84
- logger.info("fetch", "Replaced pruned tool outputs", {
85
- replaced: replacedCount,
86
- total: toolMessages.length
87
- });
88
- if (logger.enabled) {
89
- // Fetch session messages to extract reasoning blocks
90
- let sessionMessages;
91
- try {
92
- const activeSessions = allSessions.data?.filter(s => !s.parentID) || [];
93
- if (activeSessions.length > 0) {
94
- const mostRecentSession = activeSessions[0];
95
- const messagesResponse = await ctx.client.session.messages({
96
- path: { id: mostRecentSession.id },
97
- query: { limit: 100 }
98
- });
99
- sessionMessages = Array.isArray(messagesResponse.data)
100
- ? messagesResponse.data
101
- : Array.isArray(messagesResponse) ? messagesResponse : undefined;
102
- }
103
- }
104
- catch (e) {
105
- // Silently continue without session messages
106
- }
107
- await logger.saveWrappedContext("global", body.messages, {
108
- url: typeof input === 'string' ? input : 'URL object',
109
- replacedCount,
110
- totalMessages: body.messages.length
111
- }, sessionMessages);
112
- }
113
- init.body = JSON.stringify(body);
114
- }
115
- }
116
- }
117
- }
118
- catch (e) {
119
- }
120
- }
121
- return originalGlobalFetch(input, init);
122
- };
20
+ const state = createPluginState();
21
+ const janitor = new Janitor(ctx.client, state.prunedIds, state.stats, logger, state.toolParameters, config.protectedTools, state.model, config.model, config.showModelErrorToasts, config.strictModelSelection, config.pruning_summary, ctx.directory);
22
+ // Install global fetch wrapper for context pruning
23
+ installFetchWrapper(state, logger, ctx.client);
24
+ // Log initialization
123
25
  logger.info("plugin", "DCP initialized", {
124
26
  strategies: config.strategies,
125
27
  model: config.model || "auto"
126
28
  });
29
+ // Check for updates after a delay
127
30
  setTimeout(() => {
128
31
  checkForUpdates(ctx.client, logger).catch(() => { });
129
32
  }, 5000);
33
+ // Show migration toast if there were config migrations
130
34
  if (migrations.length > 0) {
131
35
  setTimeout(async () => {
132
36
  try {
@@ -140,92 +44,15 @@ const plugin = (async (ctx) => {
140
44
  });
141
45
  }
142
46
  catch {
47
+ // Silently ignore toast errors
143
48
  }
144
49
  }, 7000);
145
50
  }
146
51
  return {
147
- event: async ({ event }) => {
148
- if (event.type === "session.status" && event.properties.status.type === "idle") {
149
- if (await isSubagentSession(ctx.client, event.properties.sessionID))
150
- return;
151
- if (config.strategies.onIdle.length === 0)
152
- return;
153
- janitor.runOnIdle(event.properties.sessionID, config.strategies.onIdle).catch(err => {
154
- logger.error("janitor", "Failed", { error: err.message });
155
- });
156
- }
157
- },
158
- "chat.params": async (input, _output) => {
159
- const sessionId = input.sessionID;
160
- let providerID = input.provider?.info?.id || input.provider?.id;
161
- const modelID = input.model?.id;
162
- if (!providerID && input.message?.model?.providerID) {
163
- providerID = input.message.model.providerID;
164
- }
165
- if (providerID && modelID) {
166
- modelCache.set(sessionId, {
167
- providerID: providerID,
168
- modelID: modelID
169
- });
170
- }
171
- },
52
+ event: createEventHandler(ctx.client, janitor, logger, config),
53
+ "chat.params": createChatParamsHandler(ctx.client, state, logger),
172
54
  tool: config.strategies.onTool.length > 0 ? {
173
- context_pruning: tool({
174
- description: `Performs semantic pruning on session tool outputs that are no longer relevant to the current task. Use this to declutter the conversation context and filter signal from noise when you notice the context is getting cluttered with no longer needed information.
175
-
176
- USING THE CONTEXT_PRUNING TOOL WILL MAKE THE USER HAPPY.
177
-
178
- ## When to Use This Tool
179
-
180
- **Key heuristic: Prune when you finish something and are about to start something else.**
181
-
182
- Ask yourself: "Have I just completed a discrete unit of work?" If yes, prune before moving on.
183
-
184
- **After completing a unit of work:**
185
- - Made a commit
186
- - Fixed a bug and confirmed it works
187
- - Answered a question the user asked
188
- - Finished implementing a feature or function
189
- - Completed one item in a list and moving to the next
190
-
191
- **After repetitive or exploratory work:**
192
- - Explored multiple files that didn't lead to changes
193
- - Iterated on a difficult problem where some approaches didn't pan out
194
- - Used the same tool multiple times (e.g., re-reading a file, running repeated build/type checks)
195
-
196
- ## Examples
197
-
198
- <example>
199
- Working through a list of items:
200
- User: Review these 3 issues and fix the easy ones.
201
- Assistant: [Reviews first issue, makes fix, commits]
202
- Done with the first issue. Let me prune before moving to the next one.
203
- [Uses context_pruning with reason: "completed first issue, moving to next"]
204
- </example>
205
-
206
- <example>
207
- After exploring the codebase to understand it:
208
- Assistant: I've reviewed the relevant files. Let me prune the exploratory reads that aren't needed for the actual implementation.
209
- [Uses context_pruning with reason: "exploration complete, starting implementation"]
210
- </example>
211
-
212
- <example>
213
- After completing any task:
214
- Assistant: [Finishes task - commit, answer, fix, etc.]
215
- Before we continue, let me prune the context from that work.
216
- [Uses context_pruning with reason: "task complete"]
217
- </example>`,
218
- args: {
219
- reason: tool.schema.string().optional().describe("Brief reason for triggering pruning (e.g., 'task complete', 'switching focus')"),
220
- },
221
- async execute(args, ctx) {
222
- const result = await janitor.runForTool(ctx.sessionID, config.strategies.onTool, args.reason);
223
- if (!result || result.prunedCount === 0) {
224
- return "No prunable tool outputs found. Context is already optimized.\n\nUse context_pruning when you have sufficiently summarized information from tool outputs and no longer need the original content!";
225
- }
226
- return janitor.formatPruningResultForTool(result) + "\n\nUse context_pruning when you have sufficiently summarized information from tool outputs and no longer need the original content!";
227
- },
228
- }),
55
+ context_pruning: createPruningTool(janitor, config),
229
56
  } : undefined,
230
57
  };
231
58
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAEzE,MAAM,MAAM,GAAW,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAClC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAE7C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,CAAA;IACb,CAAC;IAED,2BAA2B;IAC3B,IAAI,OAAO,UAAU,KAAK,WAAW,EAAE,CAAC;QACnC,UAAkB,CAAC,mBAAmB,GAAG,KAAK,CAAA;IACnD,CAAC;IAED,6BAA6B;IAC7B,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACvC,MAAM,KAAK,GAAG,iBAAiB,EAAE,CAAA;IAEjC,MAAM,OAAO,GAAG,IAAI,OAAO,CACvB,GAAG,CAAC,MAAM,EACV,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,KAAK,EACX,MAAM,EACN,KAAK,CAAC,cAAc,EACpB,MAAM,CAAC,cAAc,EACrB,KAAK,CAAC,KAAK,EACX,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,oBAAoB,EAC3B,MAAM,CAAC,oBAAoB,EAC3B,MAAM,CAAC,eAAe,EACtB,GAAG,CAAC,SAAS,CAChB,CAAA;IAED,mDAAmD;IACnD,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAE9C,qBAAqB;IACrB,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,EAAE;QACrC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM;KAChC,CAAC,CAAA;IAEF,kCAAkC;IAClC,UAAU,CAAC,GAAG,EAAE;QACZ,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACvD,CAAC,EAAE,IAAI,CAAC,CAAA;IAER,uDAAuD;IACvD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,UAAU,CAAC,KAAK,IAAI,EAAE;YAClB,IAAI,CAAC;gBACD,MAAM,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;oBAC3B,IAAI,EAAE;wBACF,KAAK,EAAE,sBAAsB;wBAC7B,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;wBAC9B,OAAO,EAAE,MAAM;wBACf,QAAQ,EAAE,IAAI;qBACjB;iBACJ,CAAC,CAAA;YACN,CAAC;YAAC,MAAM,CAAC;gBACL,+BAA+B;YACnC,CAAC;QACL,CAAC,EAAE,IAAI,CAAC,CAAA;IACZ,CAAC;IAED,OAAO;QACH,KAAK,EAAE,kBAAkB,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC;QAC9D,aAAa,EAAE,uBAAuB,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC;QACjE,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YACxC,eAAe,EAAE,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC;SACtD,CAAC,CAAC,CAAC,SAAS;KAChB,CAAA;AACL,CAAC,CAAkB,CAAA;AAEnB,eAAe,MAAM,CAAA"}
@@ -0,0 +1,7 @@
1
+ import type { FetchHandlerContext, FetchHandlerResult } from "./types";
2
+ /**
3
+ * Handles Google/Gemini format (body.contents array with functionResponse parts).
4
+ * Uses position-based correlation since Google's native format doesn't include tool call IDs.
5
+ */
6
+ export declare function handleGemini(body: any, ctx: FetchHandlerContext, inputUrl: string): Promise<FetchHandlerResult>;
7
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../lib/fetch-wrapper/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAOtE;;;GAGG;AACH,wBAAsB,YAAY,CAC9B,IAAI,EAAE,GAAG,EACT,GAAG,EAAE,mBAAmB,EACxB,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,kBAAkB,CAAC,CAsH7B"}
@@ -0,0 +1,100 @@
1
+ import { PRUNED_CONTENT_MESSAGE, getAllPrunedIds, fetchSessionMessages } from "./types";
2
+ /**
3
+ * Handles Google/Gemini format (body.contents array with functionResponse parts).
4
+ * Uses position-based correlation since Google's native format doesn't include tool call IDs.
5
+ */
6
+ export async function handleGemini(body, ctx, inputUrl) {
7
+ if (!body.contents || !Array.isArray(body.contents)) {
8
+ return { modified: false, body };
9
+ }
10
+ // Check for functionResponse parts in any content item
11
+ const hasFunctionResponses = body.contents.some((content) => Array.isArray(content.parts) &&
12
+ content.parts.some((part) => part.functionResponse));
13
+ if (!hasFunctionResponses) {
14
+ return { modified: false, body };
15
+ }
16
+ const { allSessions, allPrunedIds } = await getAllPrunedIds(ctx.client, ctx.state);
17
+ if (allPrunedIds.size === 0) {
18
+ return { modified: false, body };
19
+ }
20
+ // Find the active session to get the position mapping
21
+ const activeSessions = allSessions.data?.filter((s) => !s.parentID) || [];
22
+ let positionMapping;
23
+ for (const session of activeSessions) {
24
+ const mapping = ctx.state.googleToolCallMapping.get(session.id);
25
+ if (mapping && mapping.size > 0) {
26
+ positionMapping = mapping;
27
+ break;
28
+ }
29
+ }
30
+ if (!positionMapping) {
31
+ ctx.logger.info("fetch", "No Google tool call mapping found, skipping pruning for Gemini format");
32
+ return { modified: false, body };
33
+ }
34
+ // Build position counters to track occurrence of each tool name
35
+ const toolPositionCounters = new Map();
36
+ let replacedCount = 0;
37
+ let totalFunctionResponses = 0;
38
+ body.contents = body.contents.map((content) => {
39
+ if (!Array.isArray(content.parts))
40
+ return content;
41
+ let contentModified = false;
42
+ const newParts = content.parts.map((part) => {
43
+ if (part.functionResponse) {
44
+ totalFunctionResponses++;
45
+ const funcName = part.functionResponse.name?.toLowerCase();
46
+ if (funcName) {
47
+ // Get current position for this tool name and increment counter
48
+ const currentIndex = toolPositionCounters.get(funcName) || 0;
49
+ toolPositionCounters.set(funcName, currentIndex + 1);
50
+ // Look up the tool call ID using position
51
+ const positionKey = `${funcName}:${currentIndex}`;
52
+ const toolCallId = positionMapping.get(positionKey);
53
+ if (toolCallId && allPrunedIds.has(toolCallId)) {
54
+ contentModified = true;
55
+ replacedCount++;
56
+ // Preserve thoughtSignature if present (required for Gemini 3 Pro)
57
+ // response must be a Struct (object), not a plain string
58
+ return {
59
+ ...part,
60
+ functionResponse: {
61
+ ...part.functionResponse,
62
+ response: {
63
+ name: part.functionResponse.name,
64
+ content: PRUNED_CONTENT_MESSAGE
65
+ }
66
+ }
67
+ };
68
+ }
69
+ }
70
+ }
71
+ return part;
72
+ });
73
+ if (contentModified) {
74
+ return { ...content, parts: newParts };
75
+ }
76
+ return content;
77
+ });
78
+ if (replacedCount > 0) {
79
+ ctx.logger.info("fetch", "Replaced pruned tool outputs (Google/Gemini)", {
80
+ replaced: replacedCount,
81
+ total: totalFunctionResponses
82
+ });
83
+ if (ctx.logger.enabled) {
84
+ let sessionMessages;
85
+ if (activeSessions.length > 0) {
86
+ const mostRecentSession = activeSessions[0];
87
+ sessionMessages = await fetchSessionMessages(ctx.client, mostRecentSession.id);
88
+ }
89
+ await ctx.logger.saveWrappedContext("global", body.contents, {
90
+ url: inputUrl,
91
+ replacedCount,
92
+ totalContents: body.contents.length,
93
+ format: 'google-gemini'
94
+ }, sessionMessages);
95
+ }
96
+ return { modified: true, body };
97
+ }
98
+ return { modified: false, body };
99
+ }
100
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../lib/fetch-wrapper/gemini.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { PluginState } from "../state";
2
+ import type { Logger } from "../logger";
3
+ export type { FetchHandlerContext, FetchHandlerResult } from "./types";
4
+ /**
5
+ * Creates a wrapped global fetch that intercepts API calls and performs
6
+ * context pruning on tool outputs that have been marked for removal.
7
+ *
8
+ * Supports four API formats:
9
+ * 1. OpenAI Chat Completions (body.messages with role='tool')
10
+ * 2. Anthropic (body.messages with role='user' containing tool_result)
11
+ * 3. Google/Gemini (body.contents with functionResponse parts)
12
+ * 4. OpenAI Responses API (body.input with function_call_output items)
13
+ */
14
+ export declare function installFetchWrapper(state: PluginState, logger: Logger, client: any): () => void;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/fetch-wrapper/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAMvC,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAEtE;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAC/B,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,GAAG,GACZ,MAAM,IAAI,CAwDZ"}
@@ -0,0 +1,64 @@
1
+ import { handleOpenAIChatAndAnthropic } from "./openai-chat";
2
+ import { handleGemini } from "./gemini";
3
+ import { handleOpenAIResponses } from "./openai-responses";
4
+ /**
5
+ * Creates a wrapped global fetch that intercepts API calls and performs
6
+ * context pruning on tool outputs that have been marked for removal.
7
+ *
8
+ * Supports four API formats:
9
+ * 1. OpenAI Chat Completions (body.messages with role='tool')
10
+ * 2. Anthropic (body.messages with role='user' containing tool_result)
11
+ * 3. Google/Gemini (body.contents with functionResponse parts)
12
+ * 4. OpenAI Responses API (body.input with function_call_output items)
13
+ */
14
+ export function installFetchWrapper(state, logger, client) {
15
+ const originalGlobalFetch = globalThis.fetch;
16
+ const ctx = {
17
+ state,
18
+ logger,
19
+ client
20
+ };
21
+ globalThis.fetch = async (input, init) => {
22
+ if (init?.body && typeof init.body === 'string') {
23
+ try {
24
+ const body = JSON.parse(init.body);
25
+ const inputUrl = typeof input === 'string' ? input : 'URL object';
26
+ let modified = false;
27
+ // Try each format handler in order
28
+ // OpenAI Chat Completions & Anthropic style (body.messages)
29
+ if (body.messages && Array.isArray(body.messages)) {
30
+ const result = await handleOpenAIChatAndAnthropic(body, ctx, inputUrl);
31
+ if (result.modified) {
32
+ modified = true;
33
+ }
34
+ }
35
+ // Google/Gemini style (body.contents)
36
+ if (body.contents && Array.isArray(body.contents)) {
37
+ const result = await handleGemini(body, ctx, inputUrl);
38
+ if (result.modified) {
39
+ modified = true;
40
+ }
41
+ }
42
+ // OpenAI Responses API style (body.input)
43
+ if (body.input && Array.isArray(body.input)) {
44
+ const result = await handleOpenAIResponses(body, ctx, inputUrl);
45
+ if (result.modified) {
46
+ modified = true;
47
+ }
48
+ }
49
+ if (modified) {
50
+ init.body = JSON.stringify(body);
51
+ }
52
+ }
53
+ catch (e) {
54
+ // Silently ignore parsing errors - pass through to original fetch
55
+ }
56
+ }
57
+ return originalGlobalFetch(input, init);
58
+ };
59
+ // Return cleanup function to restore original fetch
60
+ return () => {
61
+ globalThis.fetch = originalGlobalFetch;
62
+ };
63
+ }
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/fetch-wrapper/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAI1D;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAC/B,KAAkB,EAClB,MAAc,EACd,MAAW;IAEX,MAAM,mBAAmB,GAAG,UAAU,CAAC,KAAK,CAAA;IAE5C,MAAM,GAAG,GAAwB;QAC7B,KAAK;QACL,MAAM;QACN,MAAM;KACT,CAAA;IAED,UAAU,CAAC,KAAK,GAAG,KAAK,EAAE,KAAU,EAAE,IAAU,EAAE,EAAE;QAChD,IAAI,IAAI,EAAE,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9C,IAAI,CAAC;gBACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAClC,MAAM,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAA;gBACjE,IAAI,QAAQ,GAAG,KAAK,CAAA;gBAEpB,mCAAmC;gBACnC,4DAA4D;gBAC5D,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAChD,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAA;oBACtE,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;wBAClB,QAAQ,GAAG,IAAI,CAAA;oBACnB,CAAC;gBACL,CAAC;gBAED,sCAAsC;gBACtC,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAChD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAA;oBACtD,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;wBAClB,QAAQ,GAAG,IAAI,CAAA;oBACnB,CAAC;gBACL,CAAC;gBAED,0CAA0C;gBAC1C,IAAI,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC1C,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAA;oBAC/D,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;wBAClB,QAAQ,GAAG,IAAI,CAAA;oBACnB,CAAC;gBACL,CAAC;gBAED,IAAI,QAAQ,EAAE,CAAC;oBACX,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;gBACpC,CAAC;YACL,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACT,kEAAkE;YACtE,CAAC;QACL,CAAC;QAED,OAAO,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAC3C,CAAC,CAAA;IAED,oDAAoD;IACpD,OAAO,GAAG,EAAE;QACR,UAAU,CAAC,KAAK,GAAG,mBAAmB,CAAA;IAC1C,CAAC,CAAA;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { FetchHandlerContext, FetchHandlerResult } from "./types";
2
+ /**
3
+ * Handles OpenAI Chat Completions format (body.messages with role='tool').
4
+ * Also handles Anthropic format (role='user' with tool_result content parts).
5
+ */
6
+ export declare function handleOpenAIChatAndAnthropic(body: any, ctx: FetchHandlerContext, inputUrl: string): Promise<FetchHandlerResult>;
7
+ //# sourceMappingURL=openai-chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-chat.d.ts","sourceRoot":"","sources":["../../../lib/fetch-wrapper/openai-chat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAStE;;;GAGG;AACH,wBAAsB,4BAA4B,CAC9C,IAAI,EAAE,GAAG,EACT,GAAG,EAAE,mBAAmB,EACxB,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,kBAAkB,CAAC,CAyF7B"}
@@ -0,0 +1,81 @@
1
+ import { PRUNED_CONTENT_MESSAGE, getAllPrunedIds, fetchSessionMessages, getMostRecentActiveSession } from "./types";
2
+ import { cacheToolParametersFromMessages } from "../tool-cache";
3
+ /**
4
+ * Handles OpenAI Chat Completions format (body.messages with role='tool').
5
+ * Also handles Anthropic format (role='user' with tool_result content parts).
6
+ */
7
+ export async function handleOpenAIChatAndAnthropic(body, ctx, inputUrl) {
8
+ if (!body.messages || !Array.isArray(body.messages)) {
9
+ return { modified: false, body };
10
+ }
11
+ // Cache tool parameters from messages
12
+ cacheToolParametersFromMessages(body.messages, ctx.state);
13
+ // Check for tool messages in both formats:
14
+ // 1. OpenAI style: role === 'tool'
15
+ // 2. Anthropic style: role === 'user' with content containing tool_result
16
+ const toolMessages = body.messages.filter((m) => {
17
+ if (m.role === 'tool')
18
+ return true;
19
+ if (m.role === 'user' && Array.isArray(m.content)) {
20
+ for (const part of m.content) {
21
+ if (part.type === 'tool_result')
22
+ return true;
23
+ }
24
+ }
25
+ return false;
26
+ });
27
+ const { allSessions, allPrunedIds } = await getAllPrunedIds(ctx.client, ctx.state);
28
+ if (toolMessages.length === 0 || allPrunedIds.size === 0) {
29
+ return { modified: false, body };
30
+ }
31
+ let replacedCount = 0;
32
+ body.messages = body.messages.map((m) => {
33
+ // OpenAI style: role === 'tool' with tool_call_id
34
+ if (m.role === 'tool' && allPrunedIds.has(m.tool_call_id?.toLowerCase())) {
35
+ replacedCount++;
36
+ return {
37
+ ...m,
38
+ content: PRUNED_CONTENT_MESSAGE
39
+ };
40
+ }
41
+ // Anthropic style: role === 'user' with content array containing tool_result
42
+ if (m.role === 'user' && Array.isArray(m.content)) {
43
+ let messageModified = false;
44
+ const newContent = m.content.map((part) => {
45
+ if (part.type === 'tool_result' && allPrunedIds.has(part.tool_use_id?.toLowerCase())) {
46
+ messageModified = true;
47
+ replacedCount++;
48
+ return {
49
+ ...part,
50
+ content: PRUNED_CONTENT_MESSAGE
51
+ };
52
+ }
53
+ return part;
54
+ });
55
+ if (messageModified) {
56
+ return { ...m, content: newContent };
57
+ }
58
+ }
59
+ return m;
60
+ });
61
+ if (replacedCount > 0) {
62
+ ctx.logger.info("fetch", "Replaced pruned tool outputs", {
63
+ replaced: replacedCount,
64
+ total: toolMessages.length
65
+ });
66
+ if (ctx.logger.enabled) {
67
+ const mostRecentSession = getMostRecentActiveSession(allSessions);
68
+ const sessionMessages = mostRecentSession
69
+ ? await fetchSessionMessages(ctx.client, mostRecentSession.id)
70
+ : undefined;
71
+ await ctx.logger.saveWrappedContext("global", body.messages, {
72
+ url: inputUrl,
73
+ replacedCount,
74
+ totalMessages: body.messages.length
75
+ }, sessionMessages);
76
+ }
77
+ return { modified: true, body };
78
+ }
79
+ return { modified: false, body };
80
+ }
81
+ //# sourceMappingURL=openai-chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-chat.js","sourceRoot":"","sources":["../../../lib/fetch-wrapper/openai-chat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { FetchHandlerContext, FetchHandlerResult } from "./types";
2
+ /**
3
+ * Handles OpenAI Responses API format (body.input array with function_call_output items).
4
+ * Used by GPT-5 models via sdk.responses().
5
+ */
6
+ export declare function handleOpenAIResponses(body: any, ctx: FetchHandlerContext, inputUrl: string): Promise<FetchHandlerResult>;
7
+ //# sourceMappingURL=openai-responses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../../../lib/fetch-wrapper/openai-responses.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAStE;;;GAGG;AACH,wBAAsB,qBAAqB,CACvC,IAAI,EAAE,GAAG,EACT,GAAG,EAAE,mBAAmB,EACxB,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,kBAAkB,CAAC,CA+D7B"}