@yagni-app/code 0.3.5 → 1.0.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.
@@ -32,6 +32,7 @@ import { SPINNER_FRAMES } from "./pipeline/activityFeed.js";
32
32
  import { withResilience } from "./pipeline/resilience.js";
33
33
  import { runStage as defaultRunStage } from "./pipeline/runner.js";
34
34
  import { DEFAULT_RESILIENCE_POLICY } from "./pipeline/types.js";
35
+ import { logEvent } from "./errorSink.js";
35
36
  import { applyChildEvent, finalizeTask, formatWorkingMessage, newTaskProgress, progressSummaryText, receiptLine, renderSubagentResult, runningLines, } from "./subagentRender.js";
36
37
  /**
37
38
  * Read-only recon plus grounding. Mirrors the `plan` stage's allowlist for the
@@ -288,6 +289,7 @@ export function registerAdviseCommand(pi, tool) {
288
289
  }
289
290
  catch (err) {
290
291
  const message = err instanceof Error ? err.message : String(err);
292
+ logEvent({ source: "advisor", level: "error", event: "advise_failed", fields: { kind: "consult" } });
291
293
  notify(`/advise failed: ${message}`, "error");
292
294
  await pi.sendUserMessage(`/advise failed: ${message}`);
293
295
  }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * ask_user_question — structured human questions.
3
+ *
4
+ * Adapts Claude Code's `AskUserQuestion` tool into yagni-code: when the model
5
+ * genuinely needs a human (an architectural fork, a product-intent call with
6
+ * no recorded answer), it poses a closed question — 2-4 mutually exclusive
7
+ * options, each with a description explaining the tradeoff and an optional
8
+ * preview — and gets back a clean machine-readable answer instead of parsing
9
+ * free text.
10
+ *
11
+ * Rendering is via `ctx.ui.custom` (not the bare `ctx.ui.select` used for the
12
+ * permission "don't ask again" flow) so each option can show its description
13
+ * and, when any option carries a preview, a two-column layout surfaces the
14
+ * focused option's preview on the right. "Other" is a trailing editable row
15
+ * (always last, no label) whose text is the answer on Enter — no mode switch.
16
+ *
17
+ * No backend changes; no new dependencies. Only pi's TUI primitives. When
18
+ * there is no interactive UI (print / headless), execute() returns a short
19
+ * message so the tool never hangs waiting for a keyboard.
20
+ */
21
+ import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
22
+ import { Type } from "typebox";
23
+ declare const parameters: Type.TObject<{
24
+ questions: Type.TArray<Type.TObject<{
25
+ question: Type.TString;
26
+ header: Type.TString;
27
+ options: Type.TArray<Type.TObject<{
28
+ label: Type.TString;
29
+ description: Type.TString;
30
+ preview: Type.TOptional<Type.TString>;
31
+ }>>;
32
+ multiSelect: Type.TOptional<Type.TBoolean>;
33
+ }>>;
34
+ }>;
35
+ type QuestionOption = {
36
+ label: string;
37
+ description: string;
38
+ preview?: string;
39
+ };
40
+ type Question = {
41
+ question: string;
42
+ header: string;
43
+ options: QuestionOption[];
44
+ multiSelect?: boolean;
45
+ };
46
+ /** The structured answer bag stored on the tool result. */
47
+ type AskDetails = {
48
+ questions: Question[];
49
+ answers: Record<string, string>;
50
+ };
51
+ /** Build the ask_user_question tool. Register it unconditionally (like ask_advisor). */
52
+ export declare function makeAskUserQuestionTool(): ToolDefinition<typeof parameters, AskDetails>;
53
+ export {};
54
+ //# sourceMappingURL=askUserQuestionTool.d.ts.map