@xynogen/pix-core 0.2.3 → 0.3.0
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/package.json +11 -17
- package/skills/ask-user/SKILL.md +0 -48
- package/src/commands/agent-sop/agent-sop.ts +0 -58
- package/src/commands/clear/clear.ts +0 -32
- package/src/commands/diff/diff.ts +0 -32
- package/src/commands/models/models.test.ts +0 -95
- package/src/commands/models/models.ts +0 -367
- package/src/commands/models/patch-builtin.test.ts +0 -66
- package/src/commands/models/patch-builtin.ts +0 -120
- package/src/commands/tools.test.ts +0 -15
- package/src/commands/update/update.test.ts +0 -112
- package/src/commands/update/update.ts +0 -271
- package/src/index.ts +0 -45
- package/src/lib/data.ts +0 -33
- package/src/nudge/capability.test.ts +0 -258
- package/src/nudge/capability.ts +0 -189
- package/src/nudge/index.ts +0 -17
- package/src/nudge/tools.test.ts +0 -157
- package/src/nudge/tools.ts +0 -212
- package/src/tool/ask/ask.test.ts +0 -243
- package/src/tool/ask/components.ts +0 -55
- package/src/tool/ask/helpers.ts +0 -77
- package/src/tool/ask/index.ts +0 -130
- package/src/tool/ask/questionnaire.ts +0 -693
- package/src/tool/ask/rpc.ts +0 -84
- package/src/tool/ask/schema.ts +0 -69
- package/src/tool/ask/single-select-layout.test.ts +0 -124
- package/src/tool/ask/single-select-layout.ts +0 -237
- package/src/tool/ask/types.ts +0 -17
- package/src/tool/todo/todo.test.ts +0 -646
- package/src/tool/todo/todo.ts +0 -218
- package/src/tool/toolbox/toolbox.test.ts +0 -314
- package/src/tool/toolbox/toolbox.ts +0 -570
- package/src/ui/diagnostics.ts +0 -145
- package/src/ui/footer.ts +0 -512
- package/src/ui/welcome.test.ts +0 -124
- package/src/ui/welcome.ts +0 -369
package/src/tool/ask/index.ts
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { Text } from "@earendil-works/pi-tui";
|
|
3
|
-
|
|
4
|
-
import { buildResponseText } from "./helpers.js";
|
|
5
|
-
import { AskQuestionnaire } from "./questionnaire.js";
|
|
6
|
-
import { rpcFallback } from "./rpc.js";
|
|
7
|
-
import type { Params } from "./schema.js";
|
|
8
|
-
import {
|
|
9
|
-
MAX_OPTIONS,
|
|
10
|
-
MAX_QUESTIONS,
|
|
11
|
-
MIN_OPTIONS,
|
|
12
|
-
ParamsSchema,
|
|
13
|
-
SENTINEL_CHAT,
|
|
14
|
-
SENTINEL_FREEFORM,
|
|
15
|
-
} from "./schema.js";
|
|
16
|
-
import type { QuestionAnswer, QuestionnaireResult } from "./types.js";
|
|
17
|
-
|
|
18
|
-
// ── Re-exports (consumed by tests and single-select-layout) ───────────
|
|
19
|
-
|
|
20
|
-
export {
|
|
21
|
-
buildResponseText,
|
|
22
|
-
formatAnswerScalar,
|
|
23
|
-
hasAnyPreview,
|
|
24
|
-
sentinelsFor,
|
|
25
|
-
} from "./helpers.js";
|
|
26
|
-
export type { OptionData, QuestionData } from "./schema.js";
|
|
27
|
-
export type {
|
|
28
|
-
AnswerKind,
|
|
29
|
-
QuestionAnswer,
|
|
30
|
-
QuestionnaireResult,
|
|
31
|
-
} from "./types.js";
|
|
32
|
-
|
|
33
|
-
// ── Tool registration ──────────────────────────────────────────────────
|
|
34
|
-
|
|
35
|
-
export default function registerAsk(pi: ExtensionAPI): void {
|
|
36
|
-
pi.registerTool({
|
|
37
|
-
name: "ask_user",
|
|
38
|
-
label: "Ask",
|
|
39
|
-
description: `Ask the user up to ${MAX_QUESTIONS} structured questions (${MIN_OPTIONS}-${MAX_OPTIONS} options each) when requirements are ambiguous.`,
|
|
40
|
-
promptSnippet: `Ask the user up to ${MAX_QUESTIONS} structured questions (${MIN_OPTIONS}-${MAX_OPTIONS} options each) when requirements are ambiguous`,
|
|
41
|
-
promptGuidelines: [
|
|
42
|
-
`Use ask whenever the user's request is underspecified and you cannot proceed without concrete decisions — you can ask up to ${MAX_QUESTIONS} questions per invocation.`,
|
|
43
|
-
`Each question MUST have ${MIN_OPTIONS}-${MAX_OPTIONS} options. Every option requires a concise label (1-5 words) and a description explaining what the choice means or its trade-offs. The user can additionally type a custom answer ("${SENTINEL_FREEFORM}" row is appended automatically to single-select questions) or pick "${SENTINEL_CHAT}" to abandon the questionnaire.`,
|
|
44
|
-
`Set multiSelect: true when multiple answers are valid; this suppresses the "${SENTINEL_FREEFORM}" row. Provide an options[].preview markdown string when an option benefits from richer side-by-side context (mockups, code snippets, diagrams, configs) — single-select only. NOTE: any non-empty preview on a single-select question ALSO suppresses the "${SENTINEL_FREEFORM}" row (no room in the side-by-side layout); "${SENTINEL_CHAT}" remains the escape hatch. If you recommend a specific option, make it the first option and append "(Recommended)" to its label.`,
|
|
45
|
-
"Do not stack multiple ask calls back-to-back — group all clarifying questions into one invocation.",
|
|
46
|
-
],
|
|
47
|
-
executionMode: "sequential",
|
|
48
|
-
parameters: ParamsSchema,
|
|
49
|
-
|
|
50
|
-
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
51
|
-
if (signal?.aborted) {
|
|
52
|
-
return {
|
|
53
|
-
content: [{ type: "text", text: "Cancelled" }],
|
|
54
|
-
details: { answers: [], cancelled: true },
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const typed = params as unknown as Params;
|
|
59
|
-
|
|
60
|
-
if (!Array.isArray(typed.questions) || typed.questions.length === 0) {
|
|
61
|
-
return {
|
|
62
|
-
content: [
|
|
63
|
-
{ type: "text", text: "At least one question is required." },
|
|
64
|
-
],
|
|
65
|
-
isError: true,
|
|
66
|
-
details: { answers: [], cancelled: true },
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (!ctx.hasUI) {
|
|
71
|
-
const result = await rpcFallback(ctx.ui, typed);
|
|
72
|
-
const text = result.cancelled
|
|
73
|
-
? "User cancelled the questionnaire"
|
|
74
|
-
: buildResponseText(result.answers, typed.questions);
|
|
75
|
-
return { content: [{ type: "text", text }], details: result };
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const result = await ctx.ui.custom<QuestionnaireResult | null>(
|
|
79
|
-
(tui, theme, keybindings, done) => {
|
|
80
|
-
if (signal) {
|
|
81
|
-
signal.addEventListener(
|
|
82
|
-
"abort",
|
|
83
|
-
() => done({ answers: [], cancelled: true }),
|
|
84
|
-
{ once: true },
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
return new AskQuestionnaire(typed, tui, theme, keybindings, done);
|
|
88
|
-
},
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
if (!result || result.cancelled) {
|
|
92
|
-
return {
|
|
93
|
-
content: [{ type: "text", text: "User cancelled the questionnaire" }],
|
|
94
|
-
details: result ?? { answers: [], cancelled: true },
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const text = buildResponseText(result.answers, typed.questions);
|
|
99
|
-
return { content: [{ type: "text", text }], details: result };
|
|
100
|
-
},
|
|
101
|
-
|
|
102
|
-
renderCall(args, theme) {
|
|
103
|
-
const questions = Array.isArray(args.questions) ? args.questions : [];
|
|
104
|
-
const count = questions.length;
|
|
105
|
-
const firstQ = (questions[0]?.question ?? "") as string;
|
|
106
|
-
let text = theme.fg("toolTitle", theme.bold(`ask (${count}) `));
|
|
107
|
-
text += theme.fg("muted", firstQ);
|
|
108
|
-
if (count > 1) text += theme.fg("dim", ` +${count - 1} more`);
|
|
109
|
-
return new Text(text, 0, 0);
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
renderResult(result, options, theme) {
|
|
113
|
-
const details = result.details as
|
|
114
|
-
| { answers?: QuestionAnswer[]; cancelled?: boolean }
|
|
115
|
-
| undefined;
|
|
116
|
-
if (options.isPartial) {
|
|
117
|
-
return new Text(theme.fg("muted", "Waiting for user input..."), 0, 0);
|
|
118
|
-
}
|
|
119
|
-
if (!details || details.cancelled || !details.answers?.length) {
|
|
120
|
-
return new Text(theme.fg("warning", "Cancelled"), 0, 0);
|
|
121
|
-
}
|
|
122
|
-
const texts = details.answers.map((a) => {
|
|
123
|
-
const v =
|
|
124
|
-
a.kind === "multi" ? (a.selected ?? []).join(", ") : (a.answer ?? "");
|
|
125
|
-
return `${a.questionIndex + 1}: ${v}`;
|
|
126
|
-
});
|
|
127
|
-
return new Text(theme.fg("success", `✓ ${texts.join(" • ")}`), 0, 0);
|
|
128
|
-
},
|
|
129
|
-
});
|
|
130
|
-
}
|