pi-ui-extend 1.0.30 → 1.0.31
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/app/app.d.ts +1 -0
- package/dist/app/app.js +12 -0
- package/dist/app/extensions/extension-ui-controller.d.ts +6 -1
- package/dist/app/extensions/extension-ui-controller.js +16 -7
- package/dist/app/types.d.ts +7 -0
- package/dist/bundled-extensions/question/index.js +2 -1
- package/dist/bundled-extensions/question/result.d.ts +2 -2
- package/dist/bundled-extensions/question/result.js +21 -9
- package/dist/bundled-extensions/question/tui.js +50 -12
- package/dist/bundled-extensions/question/types.d.ts +14 -1
- package/dist/sdk.d.ts +1 -1
- package/external/pi-tools-suite/README.md +1 -1
- package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +1 -1
- package/external/pi-tools-suite/src/async-subagents/core/config.ts +1 -1
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +1 -1
- package/package.json +1 -1
package/dist/app/app.d.ts
CHANGED
|
@@ -86,6 +86,7 @@ export declare class PiUiExtendApp {
|
|
|
86
86
|
private setInput;
|
|
87
87
|
private resetInputAfterProgrammaticEdit;
|
|
88
88
|
private restoreTabInputState;
|
|
89
|
+
private restoreEditorSnapshot;
|
|
89
90
|
private clearPersistedInputDraft;
|
|
90
91
|
private insertVoiceTranscript;
|
|
91
92
|
private pasteInternalClipboard;
|
package/dist/app/app.js
CHANGED
|
@@ -345,6 +345,13 @@ export class PiUiExtendApp {
|
|
|
345
345
|
restoreSessionStatus: () => this.restoreSessionStatus(),
|
|
346
346
|
setInput: (value) => this.setInput(value),
|
|
347
347
|
getInput: () => this.input,
|
|
348
|
+
setInputState: (state) => this.restoreTabInputState(state),
|
|
349
|
+
getInputState: () => this.inputEditor.draftState,
|
|
350
|
+
setInputSnapshot: (snapshot) => this.restoreEditorSnapshot(snapshot),
|
|
351
|
+
getInputSnapshot: () => ({
|
|
352
|
+
text: this.inputEditor.expandedText,
|
|
353
|
+
images: this.inputEditor.images.map((image) => ({ ...image })),
|
|
354
|
+
}),
|
|
348
355
|
get entries() { return app.entries; },
|
|
349
356
|
deleteConversationEntry: (entryId) => this.conversationViewport.deleteEntry(entryId),
|
|
350
357
|
});
|
|
@@ -982,6 +989,11 @@ export class PiUiExtendApp {
|
|
|
982
989
|
this.inputEditor.restoreDraftState(state);
|
|
983
990
|
this.autocompleteController.dispose();
|
|
984
991
|
}
|
|
992
|
+
restoreEditorSnapshot(snapshot) {
|
|
993
|
+
this.restoreTabInputState({ text: snapshot.text, cursor: snapshot.text.length });
|
|
994
|
+
for (const image of snapshot.images)
|
|
995
|
+
this.inputEditor.attachImage(image.data, image.mimeType);
|
|
996
|
+
}
|
|
985
997
|
async clearPersistedInputDraft() {
|
|
986
998
|
await this.tabsController.setInputStateForTab(this.tabsController.activeInputTabId(), { text: "", cursor: 0 });
|
|
987
999
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Theme } from "../../theme.js";
|
|
2
2
|
import { type ToastKind, type ToastNotifier } from "../../ui.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { InputEditorDraftState } from "../../input-editor.js";
|
|
4
|
+
import type { Entry, ExtensionInputMouseEvent, ExtensionWidgetRegistration, ExtensionWidgetTheme, PixExtensionUIContext, PixEditorSnapshot, PixMenuController, WidgetPlacement, WidgetTuiHandle } from "../types.js";
|
|
4
5
|
export type ExtensionTerminalInputResult = {
|
|
5
6
|
consume: boolean;
|
|
6
7
|
data?: string;
|
|
@@ -21,6 +22,10 @@ export type ExtensionUiControllerHost = {
|
|
|
21
22
|
restoreSessionStatus(): void;
|
|
22
23
|
setInput(value: string): void;
|
|
23
24
|
getInput(): string;
|
|
25
|
+
setInputState(state: InputEditorDraftState): void;
|
|
26
|
+
getInputState(): InputEditorDraftState;
|
|
27
|
+
setInputSnapshot(snapshot: PixEditorSnapshot): void;
|
|
28
|
+
getInputSnapshot(): PixEditorSnapshot;
|
|
24
29
|
readonly entries: readonly Entry[];
|
|
25
30
|
deleteConversationEntry(entryId: string): void;
|
|
26
31
|
};
|
|
@@ -242,16 +242,25 @@ export class ExtensionUiController {
|
|
|
242
242
|
pasteToEditor: (text) => {
|
|
243
243
|
if (!this.isScopeActive(contextScopeKey))
|
|
244
244
|
return;
|
|
245
|
-
this.host.
|
|
245
|
+
this.host.setInputState({ text, cursor: text.length });
|
|
246
246
|
renderIfRunning();
|
|
247
247
|
},
|
|
248
248
|
setEditorText: (text) => {
|
|
249
249
|
if (!this.isScopeActive(contextScopeKey))
|
|
250
250
|
return;
|
|
251
|
-
this.host.
|
|
251
|
+
this.host.setInputState({ text, cursor: text.length });
|
|
252
252
|
renderIfRunning();
|
|
253
253
|
},
|
|
254
254
|
getEditorText: () => this.isScopeActive(contextScopeKey) ? this.host.getInput() : "",
|
|
255
|
+
getEditorSnapshot: () => this.isScopeActive(contextScopeKey)
|
|
256
|
+
? this.host.getInputSnapshot()
|
|
257
|
+
: { text: "", images: [] },
|
|
258
|
+
setEditorSnapshot: (snapshot) => {
|
|
259
|
+
if (!this.isScopeActive(contextScopeKey))
|
|
260
|
+
return;
|
|
261
|
+
this.host.setInputSnapshot(snapshot);
|
|
262
|
+
renderIfRunning();
|
|
263
|
+
},
|
|
255
264
|
editor: async (title, prefill) => await this.editorDialog(title, prefill, contextScopeKey),
|
|
256
265
|
addAutocompleteProvider: () => undefined,
|
|
257
266
|
setEditorComponent: () => undefined,
|
|
@@ -396,7 +405,7 @@ export class ExtensionUiController {
|
|
|
396
405
|
const scopeKey = this.normalizeScopeKey(options.scopeKey);
|
|
397
406
|
if (this.activeCustomUis.has(scopeKey))
|
|
398
407
|
throw new Error("Another extension custom UI is already active.");
|
|
399
|
-
const savedInput = options.savedInput ?? (this.isScopeActive(scopeKey) ? this.host.
|
|
408
|
+
const savedInput = options.savedInput ?? (this.isScopeActive(scopeKey) ? this.host.getInputState() : undefined);
|
|
400
409
|
return await new Promise((resolve, reject) => {
|
|
401
410
|
const active = {
|
|
402
411
|
key: CUSTOM_UI_WIDGET_KEY,
|
|
@@ -408,7 +417,7 @@ export class ExtensionUiController {
|
|
|
408
417
|
};
|
|
409
418
|
this.activeCustomUis.set(scopeKey, active);
|
|
410
419
|
if (options.editorInput !== undefined)
|
|
411
|
-
this.host.
|
|
420
|
+
this.host.setInputState({ text: options.editorInput, cursor: options.editorInput.length });
|
|
412
421
|
const done = (value) => {
|
|
413
422
|
if (active.settled || this.activeCustomUis.get(scopeKey) !== active)
|
|
414
423
|
return;
|
|
@@ -449,8 +458,8 @@ export class ExtensionUiController {
|
|
|
449
458
|
return;
|
|
450
459
|
active.settled = true;
|
|
451
460
|
this.activeCustomUis.delete(active.scopeKey);
|
|
452
|
-
if (this.isScopeActive(active.scopeKey) && active.savedInput !== undefined
|
|
453
|
-
this.host.
|
|
461
|
+
if (this.isScopeActive(active.scopeKey) && active.savedInput !== undefined) {
|
|
462
|
+
this.host.setInputState(active.savedInput);
|
|
454
463
|
}
|
|
455
464
|
try {
|
|
456
465
|
active.component?.dispose?.();
|
|
@@ -477,7 +486,7 @@ export class ExtensionUiController {
|
|
|
477
486
|
return undefined;
|
|
478
487
|
const active = this.activeCustomUis.get(scopeKey);
|
|
479
488
|
if (active && active.savedInput === undefined)
|
|
480
|
-
active.savedInput = this.host.
|
|
489
|
+
active.savedInput = this.host.getInputState();
|
|
481
490
|
return active;
|
|
482
491
|
}
|
|
483
492
|
isScopeActive(scopeKey) {
|
package/dist/app/types.d.ts
CHANGED
|
@@ -437,6 +437,11 @@ export type AboveInputRenderer = {
|
|
|
437
437
|
set(key: string, content: ExtensionWidgetContent): void;
|
|
438
438
|
clear(key: string): void;
|
|
439
439
|
};
|
|
440
|
+
/** Attachment-aware editor content with virtual paste/image tags resolved. */
|
|
441
|
+
export type PixEditorSnapshot = {
|
|
442
|
+
text: string;
|
|
443
|
+
images: readonly ImageContent[];
|
|
444
|
+
};
|
|
440
445
|
export type PixExtensionUIContext = Omit<ExtensionUIContext, "notify"> & {
|
|
441
446
|
notify(message: string, type?: ToastKind): void;
|
|
442
447
|
toast: ToastNotifier;
|
|
@@ -444,6 +449,8 @@ export type PixExtensionUIContext = Omit<ExtensionUIContext, "notify"> & {
|
|
|
444
449
|
renderAboveInput(key: string, content: ExtensionWidgetContent): void;
|
|
445
450
|
showMenu<T>(items: readonly PixMenuItem<T>[], options: PixMenuOptions): Promise<T | undefined>;
|
|
446
451
|
menu: PixMenuController;
|
|
452
|
+
getEditorSnapshot(): PixEditorSnapshot;
|
|
453
|
+
setEditorSnapshot(snapshot: PixEditorSnapshot): void;
|
|
447
454
|
};
|
|
448
455
|
export type WidgetTuiHandle = {
|
|
449
456
|
requestRender(force?: boolean): void;
|
|
@@ -20,7 +20,8 @@ export default function questionExtension(pi) {
|
|
|
20
20
|
const selections = await runQuestionnaire(questions, ctx);
|
|
21
21
|
if (selections == null)
|
|
22
22
|
return createQuestionToolResult(createCanceledQuestionResult("user_canceled"), questions);
|
|
23
|
-
|
|
23
|
+
const images = selections.flatMap((selection) => "customText" in selection ? selection.images ?? [] : []);
|
|
24
|
+
return createQuestionToolResult(createSuccessfulQuestionResult(questions, selections), questions, images);
|
|
24
25
|
},
|
|
25
26
|
});
|
|
26
27
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { CanceledQuestionResult, NormalizedQuestion, QuestionResultDetails, QuestionSelection, QuestionToolResult, SuccessfulQuestionResult } from "./types.js";
|
|
1
|
+
import type { CanceledQuestionResult, NormalizedQuestion, QuestionImageContent, QuestionResultDetails, QuestionSelection, QuestionToolResult, SuccessfulQuestionResult } from "./types.js";
|
|
2
2
|
export declare function createSuccessfulQuestionResult(questions: NormalizedQuestion[], selections: QuestionSelection[]): SuccessfulQuestionResult;
|
|
3
3
|
export declare function createCanceledQuestionResult(reason: CanceledQuestionResult["reason"], questions?: NormalizedQuestion[]): CanceledQuestionResult;
|
|
4
4
|
export declare function createFallbackPrompt(questions: NormalizedQuestion[]): string;
|
|
5
5
|
export declare function summarizeQuestionResult(result: QuestionResultDetails, questions?: NormalizedQuestion[]): string;
|
|
6
|
-
export declare function createQuestionToolResult(details: QuestionResultDetails, questions?: NormalizedQuestion[]): QuestionToolResult;
|
|
6
|
+
export declare function createQuestionToolResult(details: QuestionResultDetails, questions?: NormalizedQuestion[], images?: QuestionImageContent[]): QuestionToolResult;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { throwInvalid } from "./contract.js";
|
|
2
|
+
function formatAttachedImages(count) {
|
|
3
|
+
return `${count} image${count === 1 ? "" : "s"} attached`;
|
|
4
|
+
}
|
|
2
5
|
export function createSuccessfulQuestionResult(questions, selections) {
|
|
3
6
|
const selectionsById = new Map(selections.map((selection) => [selection.id, selection]));
|
|
4
7
|
return {
|
|
@@ -8,13 +11,16 @@ export function createSuccessfulQuestionResult(questions, selections) {
|
|
|
8
11
|
throwInvalid(`Missing answer for question "${question.id}".`, "Retry after collecting one answer for each normalized question.");
|
|
9
12
|
if ("customText" in selection) {
|
|
10
13
|
const customText = selection.customText.trim();
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
const imageCount = selection.images?.length ?? 0;
|
|
15
|
+
if (!customText && imageCount === 0)
|
|
16
|
+
throwInvalid(`Custom Answer for question "${question.id}" is empty after trimming.`, "Retry with non-empty Custom Answer text, an image, or choose a predefined Choice.");
|
|
17
|
+
const label = customText || formatAttachedImages(imageCount);
|
|
13
18
|
return {
|
|
14
19
|
id: question.id,
|
|
15
|
-
value: customText,
|
|
16
|
-
label
|
|
20
|
+
value: customText || label,
|
|
21
|
+
label,
|
|
17
22
|
wasCustom: true,
|
|
23
|
+
...(imageCount > 0 ? { imageCount } : {}),
|
|
18
24
|
};
|
|
19
25
|
}
|
|
20
26
|
const choiceIndex = question.choices.findIndex((choice) => choice.value === selection.choiceValue);
|
|
@@ -68,17 +74,23 @@ export function summarizeQuestionResult(result, questions = []) {
|
|
|
68
74
|
const questionLabels = new Map(questions.map((question) => [question.id, question.label]));
|
|
69
75
|
return `question answers: ${result.answers.map((answer) => {
|
|
70
76
|
const questionLabel = questionLabels.get(answer.id) ?? answer.id;
|
|
71
|
-
if (answer.wasCustom)
|
|
72
|
-
|
|
77
|
+
if (answer.wasCustom) {
|
|
78
|
+
const imageLabel = answer.imageCount ? formatAttachedImages(answer.imageCount) : undefined;
|
|
79
|
+
const imageSuffix = imageLabel && answer.label !== imageLabel ? `; ${imageLabel}` : "";
|
|
80
|
+
return `${questionLabel}: ${answer.label} (custom answer${imageSuffix})`;
|
|
81
|
+
}
|
|
73
82
|
return `${questionLabel}: ${answer.label} (choice ${answer.index})`;
|
|
74
83
|
}).join("; ")}.`;
|
|
75
84
|
}
|
|
76
|
-
export function createQuestionToolResult(details, questions = []) {
|
|
85
|
+
export function createQuestionToolResult(details, questions = [], images = []) {
|
|
77
86
|
return {
|
|
78
|
-
content: [
|
|
87
|
+
content: [
|
|
88
|
+
{
|
|
79
89
|
type: "text",
|
|
80
90
|
text: summarizeQuestionResult(details, questions),
|
|
81
|
-
}
|
|
91
|
+
},
|
|
92
|
+
...images.map((image) => ({ ...image })),
|
|
93
|
+
],
|
|
82
94
|
details,
|
|
83
95
|
};
|
|
84
96
|
}
|
|
@@ -97,6 +97,9 @@ function formatHeader(title, width) {
|
|
|
97
97
|
function clampIndex(index, length) {
|
|
98
98
|
return Math.max(0, Math.min(Math.max(0, length - 1), index));
|
|
99
99
|
}
|
|
100
|
+
function formatAttachedImages(count) {
|
|
101
|
+
return `${count} image${count === 1 ? "" : "s"} attached`;
|
|
102
|
+
}
|
|
100
103
|
export async function runQuestionnaire(questions, ctx) {
|
|
101
104
|
return ctx.ui.custom((tui, theme, _keybindings, done) => {
|
|
102
105
|
const selections = new Map();
|
|
@@ -104,6 +107,7 @@ export async function runQuestionnaire(questions, ctx) {
|
|
|
104
107
|
const reviewSubmitIndex = questions.length;
|
|
105
108
|
const pixCapabilities = tui.pix;
|
|
106
109
|
const usesSharedEditor = Boolean(pixCapabilities?.delegatedEditorInput && ctx.ui.setEditorText && ctx.ui.getEditorText);
|
|
110
|
+
const usesEditorSnapshots = Boolean(usesSharedEditor && ctx.ui.setEditorSnapshot && ctx.ui.getEditorSnapshot);
|
|
107
111
|
let questionIndex = 0;
|
|
108
112
|
let selectedChoiceIndex = 0;
|
|
109
113
|
let selectedReviewIndex = reviewSubmitIndex;
|
|
@@ -129,21 +133,45 @@ export async function runQuestionnaire(questions, ctx) {
|
|
|
129
133
|
function sharedEditorText() {
|
|
130
134
|
if (usesSharedEditor)
|
|
131
135
|
return ctx.ui.getEditorText?.() ?? "";
|
|
132
|
-
return customDrafts.get(currentQuestion().id) ?? "";
|
|
136
|
+
return customDrafts.get(currentQuestion().id)?.text ?? "";
|
|
137
|
+
}
|
|
138
|
+
function sharedEditorSnapshot() {
|
|
139
|
+
if (usesEditorSnapshots) {
|
|
140
|
+
const snapshot = ctx.ui.getEditorSnapshot?.();
|
|
141
|
+
if (snapshot)
|
|
142
|
+
return cloneEditorSnapshot(snapshot);
|
|
143
|
+
}
|
|
144
|
+
return { text: sharedEditorText(), images: [] };
|
|
145
|
+
}
|
|
146
|
+
function cloneEditorSnapshot(snapshot) {
|
|
147
|
+
return {
|
|
148
|
+
text: snapshot.text,
|
|
149
|
+
images: snapshot.images.map((image) => ({ ...image })),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function setSharedEditorSnapshot(snapshot) {
|
|
153
|
+
const cloned = cloneEditorSnapshot(snapshot);
|
|
154
|
+
customDrafts.set(currentQuestion().id, cloned);
|
|
155
|
+
if (usesEditorSnapshots)
|
|
156
|
+
ctx.ui.setEditorSnapshot?.(cloned);
|
|
157
|
+
else if (usesSharedEditor)
|
|
158
|
+
ctx.ui.setEditorText?.(cloned.text);
|
|
133
159
|
}
|
|
134
160
|
function setSharedEditorText(text) {
|
|
135
|
-
customDrafts.set(currentQuestion().id, text);
|
|
161
|
+
customDrafts.set(currentQuestion().id, { text, images: [] });
|
|
136
162
|
if (usesSharedEditor)
|
|
137
163
|
ctx.ui.setEditorText?.(text);
|
|
138
164
|
}
|
|
139
165
|
function clearSharedEditorText() {
|
|
140
|
-
if (
|
|
166
|
+
if (usesEditorSnapshots)
|
|
167
|
+
ctx.ui.setEditorSnapshot?.({ text: "", images: [] });
|
|
168
|
+
else if (usesSharedEditor)
|
|
141
169
|
ctx.ui.setEditorText?.("");
|
|
142
170
|
}
|
|
143
171
|
function captureCustomDraft() {
|
|
144
172
|
if (mode !== "custom")
|
|
145
173
|
return;
|
|
146
|
-
customDrafts.set(currentQuestion().id,
|
|
174
|
+
customDrafts.set(currentQuestion().id, sharedEditorSnapshot());
|
|
147
175
|
}
|
|
148
176
|
function getCompleteSelections() {
|
|
149
177
|
const orderedSelections = [];
|
|
@@ -172,8 +200,12 @@ export async function runQuestionnaire(questions, ctx) {
|
|
|
172
200
|
submitCompleteSelections();
|
|
173
201
|
}
|
|
174
202
|
function formatReviewAnswerLabel(question, selection) {
|
|
175
|
-
if ("customText" in selection)
|
|
176
|
-
|
|
203
|
+
if ("customText" in selection) {
|
|
204
|
+
const imageCount = selection.images?.length ?? 0;
|
|
205
|
+
const text = selection.customText || formatAttachedImages(imageCount);
|
|
206
|
+
const imageSuffix = selection.customText && imageCount > 0 ? ` (+${formatAttachedImages(imageCount)})` : "";
|
|
207
|
+
return `${CUSTOM_ANSWER_LABEL}: ${text}${imageSuffix}`;
|
|
208
|
+
}
|
|
177
209
|
return question.choices.find((choice) => choice.value === selection.choiceValue)?.label ?? "Unknown";
|
|
178
210
|
}
|
|
179
211
|
function selectionIndexForQuestion(question) {
|
|
@@ -250,11 +282,13 @@ export async function runQuestionnaire(questions, ctx) {
|
|
|
250
282
|
function enterCustomMode() {
|
|
251
283
|
const question = currentQuestion();
|
|
252
284
|
const existing = selections.get(question.id);
|
|
253
|
-
const prefill = existing && "customText" in existing
|
|
285
|
+
const prefill = existing && "customText" in existing
|
|
286
|
+
? { text: existing.customText, images: existing.images ?? [] }
|
|
287
|
+
: customDrafts.get(question.id) ?? { text: "", images: [] };
|
|
254
288
|
mode = "custom";
|
|
255
289
|
selectedChoiceIndex = customAnswerIndex(question);
|
|
256
290
|
customError = undefined;
|
|
257
|
-
|
|
291
|
+
setSharedEditorSnapshot(prefill);
|
|
258
292
|
refresh();
|
|
259
293
|
}
|
|
260
294
|
function selectChoice(index) {
|
|
@@ -271,15 +305,19 @@ export async function runQuestionnaire(questions, ctx) {
|
|
|
271
305
|
enterCustomMode();
|
|
272
306
|
}
|
|
273
307
|
function submitCustomAnswer() {
|
|
274
|
-
const
|
|
275
|
-
const trimmed = text.trim();
|
|
276
|
-
if (!trimmed) {
|
|
308
|
+
const snapshot = sharedEditorSnapshot();
|
|
309
|
+
const trimmed = snapshot.text.trim();
|
|
310
|
+
if (!trimmed && snapshot.images.length === 0) {
|
|
277
311
|
customError = "Custom Answer cannot be empty.";
|
|
278
312
|
refresh();
|
|
279
313
|
return;
|
|
280
314
|
}
|
|
281
315
|
const question = currentQuestion();
|
|
282
|
-
selections.set(question.id, {
|
|
316
|
+
selections.set(question.id, {
|
|
317
|
+
id: question.id,
|
|
318
|
+
customText: trimmed,
|
|
319
|
+
...(snapshot.images.length > 0 ? { images: snapshot.images } : {}),
|
|
320
|
+
});
|
|
283
321
|
customDrafts.delete(question.id);
|
|
284
322
|
clearSharedEditorText();
|
|
285
323
|
advanceAfterAnswer();
|
|
@@ -30,6 +30,7 @@ export interface PredefinedQuestionSelection {
|
|
|
30
30
|
export interface CustomQuestionSelection {
|
|
31
31
|
id: string;
|
|
32
32
|
customText: string;
|
|
33
|
+
images?: QuestionImageContent[];
|
|
33
34
|
}
|
|
34
35
|
export type QuestionSelection = PredefinedQuestionSelection | CustomQuestionSelection;
|
|
35
36
|
export interface QuestionAnswer {
|
|
@@ -38,6 +39,7 @@ export interface QuestionAnswer {
|
|
|
38
39
|
label: string;
|
|
39
40
|
wasCustom: boolean;
|
|
40
41
|
index?: number;
|
|
42
|
+
imageCount?: number;
|
|
41
43
|
}
|
|
42
44
|
export interface SuccessfulQuestionResult {
|
|
43
45
|
answers: QuestionAnswer[];
|
|
@@ -54,8 +56,17 @@ export interface TextContent {
|
|
|
54
56
|
type: "text";
|
|
55
57
|
text: string;
|
|
56
58
|
}
|
|
59
|
+
export interface QuestionImageContent {
|
|
60
|
+
type: "image";
|
|
61
|
+
data: string;
|
|
62
|
+
mimeType: string;
|
|
63
|
+
}
|
|
64
|
+
export interface QuestionEditorSnapshot {
|
|
65
|
+
text: string;
|
|
66
|
+
images: QuestionImageContent[];
|
|
67
|
+
}
|
|
57
68
|
export interface QuestionToolResult {
|
|
58
|
-
content: TextContent
|
|
69
|
+
content: Array<TextContent | QuestionImageContent>;
|
|
59
70
|
details: QuestionResultDetails;
|
|
60
71
|
}
|
|
61
72
|
export interface QuestionUiContext {
|
|
@@ -64,6 +75,8 @@ export interface QuestionUiContext {
|
|
|
64
75
|
custom<T>(factory: (tui: QuestionTui, theme: QuestionTheme, keybindings: unknown, done: (value: T) => void) => QuestionComponent): Promise<T | undefined>;
|
|
65
76
|
setEditorText?(text: string): void;
|
|
66
77
|
getEditorText?(): string;
|
|
78
|
+
setEditorSnapshot?(snapshot: QuestionEditorSnapshot): void;
|
|
79
|
+
getEditorSnapshot?(): QuestionEditorSnapshot;
|
|
67
80
|
notify?(message: string, level: "info" | "warning" | "error"): void;
|
|
68
81
|
};
|
|
69
82
|
}
|
package/dist/sdk.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { isToastKind, Toast, TOAST_KINDS } from "./ui.js";
|
|
2
2
|
export type { ToastEntry, ToastKind, ToastNotifier, ToastState } from "./ui.js";
|
|
3
|
-
export type { AboveInputRenderer, ExtensionWidgetComponent, ExtensionWidgetContent, ExtensionWidgetFactory, PixMenuController, PixMenuItem, PixMenuOptions, PixMenuSelectOptions, PixMenuVariant, PixExtensionUIContext, WidgetPlacement, WidgetTuiHandle, } from "./app/types.js";
|
|
3
|
+
export type { AboveInputRenderer, ExtensionWidgetComponent, ExtensionWidgetContent, ExtensionWidgetFactory, PixMenuController, PixMenuItem, PixMenuOptions, PixMenuSelectOptions, PixMenuVariant, PixExtensionUIContext, PixEditorSnapshot, WidgetPlacement, WidgetTuiHandle, } from "./app/types.js";
|
|
@@ -370,7 +370,7 @@ The canonical use case is an **`oracle`** role that consults a flagship model fr
|
|
|
370
370
|
"description": "Cross-provider second opinion: consult a flagship from a different provider than the parent to pressure-test a hard decision. Read-only; advise, do not edit.",
|
|
371
371
|
"model": "openai-codex/gpt-5.6-sol",
|
|
372
372
|
"fallbackModels": ["zai/glm-5.3"],
|
|
373
|
-
"thinking": "
|
|
373
|
+
"thinking": "max",
|
|
374
374
|
"modelByParent": {
|
|
375
375
|
"zai/*": { "model": "openai-codex/gpt-5.6-sol", "fallbackModels": ["zai/glm-5.3"] },
|
|
376
376
|
"openai-codex/*": "zai/glm-5.3",
|
|
@@ -244,7 +244,7 @@
|
|
|
244
244
|
"description": "Oracle: cross-provider flagship second opinion for hard or high-stakes uncertainty. Use sparingly to pressure-test architecture, plans, root-cause hypotheses, risk/security calls, or final recommendations when independent disagreement is valuable. Read-only; advise, do not edit.",
|
|
245
245
|
"model": "openai-codex/gpt-5.6-sol",
|
|
246
246
|
"fallbackModels": ["zai/glm-5.3"],
|
|
247
|
-
"thinking": "
|
|
247
|
+
"thinking": "max",
|
|
248
248
|
"tools": ["read", "grep", "bash"],
|
|
249
249
|
"modelByParent": {
|
|
250
250
|
"zai/*": { "model": "openai-codex/gpt-5.6-sol", "fallbackModels": ["zai/glm-5.3"] },
|
|
@@ -250,7 +250,7 @@ const BUILTIN_CONFIG: SubagentConfig = {
|
|
|
250
250
|
"antigravity/*": { model: "zai/glm-5.3", fallbackModels: ["openai-codex/gpt-5.6-sol"] },
|
|
251
251
|
"anthropic/*": { model: "openai-codex/gpt-5.6-sol", fallbackModels: ["zai/glm-5.3"] },
|
|
252
252
|
},
|
|
253
|
-
thinking: "
|
|
253
|
+
thinking: "max",
|
|
254
254
|
tools: ["read", "grep", "bash"],
|
|
255
255
|
promptAppend: "You are an oracle: a flagship model from a different provider giving a second opinion to the parent agent. Give a concise, decisive recommendation with key tradeoffs and risks. Disagree when warranted; do not rubber-stamp. Do not edit unless explicitly asked.",
|
|
256
256
|
},
|
|
@@ -341,7 +341,7 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = String.raw`{
|
|
|
341
341
|
"description": "Oracle: cross-provider flagship second opinion for hard or high-stakes uncertainty. Use sparingly to pressure-test architecture, plans, root-cause hypotheses, risk/security calls, or final recommendations when independent disagreement is valuable. Read-only; advise, do not edit.",
|
|
342
342
|
"model": "openai-codex/gpt-5.6-sol",
|
|
343
343
|
"fallbackModels": ["zai/glm-5.3"],
|
|
344
|
-
"thinking": "
|
|
344
|
+
"thinking": "max",
|
|
345
345
|
"tools": ["read", "grep", "bash"],
|
|
346
346
|
"modelByParent": {
|
|
347
347
|
"zai/*": { "model": "openai-codex/gpt-5.6-sol", "fallbackModels": ["zai/glm-5.3"] },
|
package/package.json
CHANGED