@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.
Files changed (37) hide show
  1. package/package.json +11 -17
  2. package/skills/ask-user/SKILL.md +0 -48
  3. package/src/commands/agent-sop/agent-sop.ts +0 -58
  4. package/src/commands/clear/clear.ts +0 -32
  5. package/src/commands/diff/diff.ts +0 -32
  6. package/src/commands/models/models.test.ts +0 -95
  7. package/src/commands/models/models.ts +0 -367
  8. package/src/commands/models/patch-builtin.test.ts +0 -66
  9. package/src/commands/models/patch-builtin.ts +0 -120
  10. package/src/commands/tools.test.ts +0 -15
  11. package/src/commands/update/update.test.ts +0 -112
  12. package/src/commands/update/update.ts +0 -271
  13. package/src/index.ts +0 -45
  14. package/src/lib/data.ts +0 -33
  15. package/src/nudge/capability.test.ts +0 -258
  16. package/src/nudge/capability.ts +0 -189
  17. package/src/nudge/index.ts +0 -17
  18. package/src/nudge/tools.test.ts +0 -157
  19. package/src/nudge/tools.ts +0 -212
  20. package/src/tool/ask/ask.test.ts +0 -243
  21. package/src/tool/ask/components.ts +0 -55
  22. package/src/tool/ask/helpers.ts +0 -77
  23. package/src/tool/ask/index.ts +0 -130
  24. package/src/tool/ask/questionnaire.ts +0 -693
  25. package/src/tool/ask/rpc.ts +0 -84
  26. package/src/tool/ask/schema.ts +0 -69
  27. package/src/tool/ask/single-select-layout.test.ts +0 -124
  28. package/src/tool/ask/single-select-layout.ts +0 -237
  29. package/src/tool/ask/types.ts +0 -17
  30. package/src/tool/todo/todo.test.ts +0 -646
  31. package/src/tool/todo/todo.ts +0 -218
  32. package/src/tool/toolbox/toolbox.test.ts +0 -314
  33. package/src/tool/toolbox/toolbox.ts +0 -570
  34. package/src/ui/diagnostics.ts +0 -145
  35. package/src/ui/footer.ts +0 -512
  36. package/src/ui/welcome.test.ts +0 -124
  37. package/src/ui/welcome.ts +0 -369
@@ -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
- }