@comfanion/usethis_search 4.2.0-dev.1 → 4.2.0-dev.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.
@@ -126,33 +126,47 @@ export function createWorkspaceInjectionHandler(state: SessionState) {
126
126
  workspace += `</workspace_context>`
127
127
 
128
128
  // ── Inject into messages ──────────────────────────────────────────────
129
- // Find the last real user message and inject workspace BEFORE it
130
- // This way AI sees files as "already available context"
131
-
132
- const lastUserIdx = findLastUserMessageIndex(output.messages)
133
- if (lastUserIdx === -1) return
134
-
135
- // Create synthetic workspace message (inserted before last user message)
136
- const workspaceMessage: Message = {
137
- info: {
138
- role: "user",
139
- // Mark as synthetic so DCP doesn't prune it
140
- _synthetic: true,
141
- _workspace_injection: true,
142
- },
143
- parts: [
144
- {
145
- type: "text",
146
- content: workspace,
147
- // Anthropic prompt caching — content that doesn't change
148
- // between turns gets cached at 90% discount
149
- cache_control: { type: "ephemeral" },
150
- },
151
- ],
152
- }
129
+ // Get base message for creating proper synthetic message
130
+ const lastUserMessage = findLastUserMessage(output.messages)
131
+ if (!lastUserMessage) return
132
+
133
+ // Create proper synthetic workspace message (like DCP does)
134
+ const workspaceMessage = createSyntheticUserMessage(lastUserMessage, workspace)
153
135
 
154
- // Insert before last user message
155
- output.messages.splice(lastUserIdx, 0, workspaceMessage)
136
+ // Add to end of messages (like DCP does with push, not splice)
137
+ output.messages.push(workspaceMessage)
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Create a properly-formed synthetic user message for workspace injection.
143
+ * Follows OpenCode SDK message format to avoid "Invalid prompt" errors.
144
+ */
145
+ function createSyntheticUserMessage(baseMessage: Message, content: string): Message {
146
+ const userInfo = baseMessage.info as any
147
+ const now = Date.now()
148
+
149
+ return {
150
+ info: {
151
+ id: "msg_workspace_01234567890123",
152
+ sessionID: userInfo.sessionID,
153
+ role: "user",
154
+ agent: userInfo.agent || "code",
155
+ model: userInfo.model,
156
+ time: { created: now },
157
+ variant: userInfo.variant,
158
+ },
159
+ parts: [
160
+ {
161
+ id: "prt_workspace_01234567890123",
162
+ sessionID: userInfo.sessionID,
163
+ messageID: "msg_workspace_01234567890123",
164
+ type: "text",
165
+ text: content, // TEXT not content!
166
+ // Anthropic prompt caching for 90% token savings
167
+ cache_control: { type: "ephemeral" },
168
+ },
169
+ ],
156
170
  }
157
171
  }
158
172
 
@@ -240,15 +254,13 @@ function formatChunk(entry: ReturnType<typeof workspaceCache.getAll>[0]): string
240
254
  return block
241
255
  }
242
256
 
243
- function findLastUserMessageIndex(messages: Message[]): number {
257
+ function findLastUserMessage(messages: Message[]): Message | null {
244
258
  for (let i = messages.length - 1; i >= 0; i--) {
245
259
  if (messages[i]?.info?.role === "user") {
246
- // Skip synthetic messages
247
- if ((messages[i].info as any)._synthetic) continue
248
- return i
260
+ return messages[i]
249
261
  }
250
262
  }
251
- return -1
263
+ return null
252
264
  }
253
265
 
254
266
  // ── Search output pruning ────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comfanion/usethis_search",
3
- "version": "4.2.0-dev.1",
3
+ "version": "4.2.0-dev.2",
4
4
  "description": "OpenCode plugin: semantic search with chunk-based workspace injection (v4.2-dev: chunk-level context, granular detach, improved token efficiency)",
5
5
  "type": "module",
6
6
  "main": "./index.ts",