gsd-pi 2.73.1-dev.9a4cd44 → 2.73.1-dev.a2eb797
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.
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +15 -15
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -6
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +95 -1
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +88 -0
- /package/dist/web/standalone/.next/static/{ASJ2RGD7E1iiUYzA0xT2i → rCeJUc4hHW3VT0ARiIinf}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{ASJ2RGD7E1iiUYzA0xT2i → rCeJUc4hHW3VT0ARiIinf}/_ssgManifest.js +0 -0
|
@@ -97,6 +97,31 @@ interface ParsedTextInputField {
|
|
|
97
97
|
secure: boolean;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
interface SDKInputImageBlock {
|
|
101
|
+
type: "image";
|
|
102
|
+
source: {
|
|
103
|
+
type: "base64";
|
|
104
|
+
media_type: string;
|
|
105
|
+
data: string;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
interface SDKInputTextBlock {
|
|
110
|
+
type: "text";
|
|
111
|
+
text: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
type SDKInputUserContentBlock = SDKInputImageBlock | SDKInputTextBlock;
|
|
115
|
+
|
|
116
|
+
interface SDKInputUserMessage {
|
|
117
|
+
type: "user";
|
|
118
|
+
message: {
|
|
119
|
+
role: "user";
|
|
120
|
+
content: SDKInputUserContentBlock[];
|
|
121
|
+
};
|
|
122
|
+
parent_tool_use_id: null;
|
|
123
|
+
}
|
|
124
|
+
|
|
100
125
|
const OTHER_OPTION_LABEL = "None of the above";
|
|
101
126
|
const SENSITIVE_FIELD_PATTERN = /(password|passphrase|secret|token|api[_\s-]*key|private[_\s-]*key|credential)/i;
|
|
102
127
|
|
|
@@ -223,6 +248,74 @@ export function buildPromptFromContext(context: Context): string {
|
|
|
223
248
|
return parts.join("\n\n");
|
|
224
249
|
}
|
|
225
250
|
|
|
251
|
+
function stripDataUriPrefix(value: string): string {
|
|
252
|
+
const commaIndex = value.indexOf(",");
|
|
253
|
+
if (value.startsWith("data:") && commaIndex !== -1) {
|
|
254
|
+
return value.slice(commaIndex + 1);
|
|
255
|
+
}
|
|
256
|
+
return value;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function inferMimeTypeFromDataUri(value: string): string | null {
|
|
260
|
+
const match = /^data:([^;,]+);base64,/.exec(value);
|
|
261
|
+
return match?.[1] ?? null;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export function extractImageBlocksFromContext(context: Context): SDKInputImageBlock[] {
|
|
265
|
+
const imageBlocks: SDKInputImageBlock[] = [];
|
|
266
|
+
|
|
267
|
+
for (const msg of context.messages) {
|
|
268
|
+
if (msg.role !== "user" || !Array.isArray(msg.content)) continue;
|
|
269
|
+
for (const part of msg.content) {
|
|
270
|
+
if (!part || typeof part !== "object") continue;
|
|
271
|
+
const block = part as { type?: unknown; data?: unknown; mimeType?: unknown };
|
|
272
|
+
if (block.type !== "image" || typeof block.data !== "string") continue;
|
|
273
|
+
|
|
274
|
+
const mimeType =
|
|
275
|
+
typeof block.mimeType === "string" && block.mimeType.length > 0
|
|
276
|
+
? block.mimeType
|
|
277
|
+
: inferMimeTypeFromDataUri(block.data);
|
|
278
|
+
if (!mimeType) continue;
|
|
279
|
+
|
|
280
|
+
imageBlocks.push({
|
|
281
|
+
type: "image",
|
|
282
|
+
source: {
|
|
283
|
+
type: "base64",
|
|
284
|
+
media_type: mimeType,
|
|
285
|
+
data: stripDataUriPrefix(block.data),
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return imageBlocks;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function buildSdkQueryPrompt(
|
|
295
|
+
context: Context,
|
|
296
|
+
textPrompt: string = buildPromptFromContext(context),
|
|
297
|
+
): string | AsyncIterable<SDKInputUserMessage> {
|
|
298
|
+
const imageBlocks = extractImageBlocksFromContext(context);
|
|
299
|
+
if (imageBlocks.length === 0) {
|
|
300
|
+
return textPrompt;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const content: SDKInputUserContentBlock[] = [...imageBlocks];
|
|
304
|
+
if (textPrompt) {
|
|
305
|
+
content.push({ type: "text", text: textPrompt });
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const sdkMessage: SDKInputUserMessage = {
|
|
309
|
+
type: "user",
|
|
310
|
+
message: { role: "user", content },
|
|
311
|
+
parent_tool_use_id: null,
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
return (async function* () {
|
|
315
|
+
yield sdkMessage;
|
|
316
|
+
})();
|
|
317
|
+
}
|
|
318
|
+
|
|
226
319
|
// ---------------------------------------------------------------------------
|
|
227
320
|
// Error helper
|
|
228
321
|
// ---------------------------------------------------------------------------
|
|
@@ -828,6 +921,7 @@ async function pumpSdkMessages(
|
|
|
828
921
|
}
|
|
829
922
|
|
|
830
923
|
const prompt = buildPromptFromContext(context);
|
|
924
|
+
const queryPrompt = buildSdkQueryPrompt(context, prompt);
|
|
831
925
|
const permissionMode = await resolveClaudePermissionMode();
|
|
832
926
|
const sdkOpts = buildSdkOptions(
|
|
833
927
|
modelId,
|
|
@@ -844,7 +938,7 @@ async function pumpSdkMessages(
|
|
|
844
938
|
);
|
|
845
939
|
|
|
846
940
|
const queryResult = sdk.query({
|
|
847
|
-
prompt,
|
|
941
|
+
prompt: queryPrompt,
|
|
848
942
|
options: {
|
|
849
943
|
...sdkOpts,
|
|
850
944
|
abortController: controller,
|
|
@@ -10,8 +10,10 @@ import {
|
|
|
10
10
|
mergePendingToolCalls,
|
|
11
11
|
resolveClaudePermissionMode,
|
|
12
12
|
buildPromptFromContext,
|
|
13
|
+
buildSdkQueryPrompt,
|
|
13
14
|
buildSdkOptions,
|
|
14
15
|
createClaudeCodeElicitationHandler,
|
|
16
|
+
extractImageBlocksFromContext,
|
|
15
17
|
extractToolResultsFromSdkUserMessage,
|
|
16
18
|
getClaudeLookupCommand,
|
|
17
19
|
parseAskUserQuestionsElicitation,
|
|
@@ -167,6 +169,92 @@ describe("stream-adapter — full context prompt (#2859)", () => {
|
|
|
167
169
|
});
|
|
168
170
|
});
|
|
169
171
|
|
|
172
|
+
describe("stream-adapter — image prompt forwarding (#4183)", () => {
|
|
173
|
+
test("extractImageBlocksFromContext maps user image parts to Anthropic base64 image blocks", () => {
|
|
174
|
+
const context: Context = {
|
|
175
|
+
messages: [
|
|
176
|
+
{
|
|
177
|
+
role: "user",
|
|
178
|
+
content: [
|
|
179
|
+
{ type: "text", text: "look" },
|
|
180
|
+
{
|
|
181
|
+
type: "image",
|
|
182
|
+
data: "data:image/png;base64,abc123",
|
|
183
|
+
mimeType: "image/png",
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
} as Message,
|
|
187
|
+
],
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const imageBlocks = extractImageBlocksFromContext(context);
|
|
191
|
+
assert.deepEqual(imageBlocks, [
|
|
192
|
+
{
|
|
193
|
+
type: "image",
|
|
194
|
+
source: {
|
|
195
|
+
type: "base64",
|
|
196
|
+
media_type: "image/png",
|
|
197
|
+
data: "abc123",
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
]);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
test("buildSdkQueryPrompt returns plain string when no images exist in context", () => {
|
|
204
|
+
const context: Context = {
|
|
205
|
+
messages: [{ role: "user", content: "hello" } as Message],
|
|
206
|
+
};
|
|
207
|
+
const textPrompt = buildPromptFromContext(context);
|
|
208
|
+
|
|
209
|
+
const prompt = buildSdkQueryPrompt(context, textPrompt);
|
|
210
|
+
assert.equal(typeof prompt, "string");
|
|
211
|
+
assert.equal(prompt, textPrompt);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test("buildSdkQueryPrompt wraps images and prompt text in an SDK user message iterable", async () => {
|
|
215
|
+
const context: Context = {
|
|
216
|
+
messages: [
|
|
217
|
+
{
|
|
218
|
+
role: "user",
|
|
219
|
+
content: [
|
|
220
|
+
{ type: "image", data: "ZmFrZQ==", mimeType: "image/jpeg" },
|
|
221
|
+
{ type: "text", text: "What is in this image?" },
|
|
222
|
+
],
|
|
223
|
+
} as Message,
|
|
224
|
+
],
|
|
225
|
+
};
|
|
226
|
+
const textPrompt = buildPromptFromContext(context);
|
|
227
|
+
|
|
228
|
+
const prompt = buildSdkQueryPrompt(context, textPrompt);
|
|
229
|
+
assert.notEqual(typeof prompt, "string");
|
|
230
|
+
assert.ok(prompt && typeof (prompt as any)[Symbol.asyncIterator] === "function");
|
|
231
|
+
|
|
232
|
+
const messages: any[] = [];
|
|
233
|
+
for await (const item of prompt as AsyncIterable<any>) {
|
|
234
|
+
messages.push(item);
|
|
235
|
+
}
|
|
236
|
+
assert.equal(messages.length, 1);
|
|
237
|
+
assert.deepEqual(messages[0], {
|
|
238
|
+
type: "user",
|
|
239
|
+
message: {
|
|
240
|
+
role: "user",
|
|
241
|
+
content: [
|
|
242
|
+
{
|
|
243
|
+
type: "image",
|
|
244
|
+
source: {
|
|
245
|
+
type: "base64",
|
|
246
|
+
media_type: "image/jpeg",
|
|
247
|
+
data: "ZmFrZQ==",
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
{ type: "text", text: textPrompt },
|
|
251
|
+
],
|
|
252
|
+
},
|
|
253
|
+
parent_tool_use_id: null,
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
170
258
|
// ---------------------------------------------------------------------------
|
|
171
259
|
// Bug #4102 — transcript fabrication regression tests
|
|
172
260
|
// ---------------------------------------------------------------------------
|
|
File without changes
|
|
File without changes
|