@ikuma.cloud/pix-mcp 0.0.11 → 0.0.12

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikuma.cloud/pix-mcp",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/index.ts CHANGED
@@ -25,6 +25,7 @@ import {
25
25
  formatResult,
26
26
  removeEditablePromptGuard,
27
27
  } from "./output.ts";
28
+ import { inputPromptArgument } from "./prompt-argument-input.ts";
28
29
  import { pickPrompt } from "./prompt-picker.ts";
29
30
  import { pickResource } from "./resource-picker.ts";
30
31
  import {
@@ -457,19 +458,14 @@ export default function mcp(pi: ExtensionAPI) {
457
458
  };
458
459
  ensureCurrent();
459
460
 
460
- const dialogOptions = ctx.signal ? { signal: ctx.signal } : undefined;
461
461
  const argumentTokens: PromptArgumentToken[] = [];
462
462
  for (const argument of item.prompt.arguments ?? []) {
463
463
  const description = compact(argument.description ?? "", 160);
464
- const label = `${argument.name} (${argument.required ? "required" : "optional"})`;
465
- const guidance = argument.required
466
- ? "Enter a value"
467
- : "Leave empty to omit";
468
- const value = await ctx.ui.input(
469
- [label, description, guidance].filter(Boolean).join("\n"),
470
- undefined,
471
- dialogOptions,
472
- );
464
+ const value = await inputPromptArgument(ctx, {
465
+ label: `${argument.name} (${argument.required ? "required" : "optional"})`,
466
+ ...(description ? { description } : {}),
467
+ guidance: argument.required ? "Enter a value" : "Leave empty to omit",
468
+ });
473
469
  if (value === undefined) return;
474
470
  ctx.signal?.throwIfAborted();
475
471
  ensureCurrent();
@@ -0,0 +1,83 @@
1
+ import {
2
+ ExtensionInputComponent,
3
+ type ExtensionCommandContext,
4
+ type Theme,
5
+ } from "@earendil-works/pi-coding-agent";
6
+ import type { TUI } from "@earendil-works/pi-tui";
7
+
8
+ export interface PromptArgumentInputOptions {
9
+ label: string;
10
+ description?: string;
11
+ guidance: string;
12
+ signal?: AbortSignal;
13
+ }
14
+
15
+ class PromptArgumentInputComponent extends ExtensionInputComponent {
16
+ readonly #tui: TUI;
17
+ readonly #signal: AbortSignal | undefined;
18
+ readonly #onAbort: () => void;
19
+
20
+ constructor(
21
+ tui: TUI,
22
+ theme: Theme,
23
+ done: (value: string | undefined) => void,
24
+ options: PromptArgumentInputOptions,
25
+ ) {
26
+ let finished = false;
27
+ const finish = (value: string | undefined) => {
28
+ if (finished) return;
29
+ finished = true;
30
+ done(value);
31
+ };
32
+ const details = [
33
+ ...(options.description ? [theme.fg("dim", options.description)] : []),
34
+ theme.fg("muted", options.guidance),
35
+ ].join("\n");
36
+ super(
37
+ options.label,
38
+ undefined,
39
+ (value) => finish(value),
40
+ () => finish(undefined),
41
+ { tui, description: details },
42
+ );
43
+ this.#tui = tui;
44
+ this.#signal = options.signal;
45
+ this.#onAbort = () => finish(undefined);
46
+ options.signal?.addEventListener("abort", this.#onAbort, { once: true });
47
+ if (options.signal?.aborted) this.#onAbort();
48
+ }
49
+
50
+ override handleInput(data: string): void {
51
+ super.handleInput(data);
52
+ this.#tui.requestRender();
53
+ }
54
+
55
+ override dispose(): void {
56
+ this.#signal?.removeEventListener("abort", this.#onAbort);
57
+ super.dispose();
58
+ }
59
+ }
60
+
61
+ export function createPromptArgumentInput(
62
+ tui: TUI,
63
+ theme: Theme,
64
+ done: (value: string | undefined) => void,
65
+ options: PromptArgumentInputOptions,
66
+ ): ExtensionInputComponent {
67
+ return new PromptArgumentInputComponent(tui, theme, done, options);
68
+ }
69
+
70
+ // Pi 0.87.1's ctx.ui.input renders every title line as accent and ignores its
71
+ // placeholder. Reuse its native component through custom UI to style details.
72
+ export async function inputPromptArgument(
73
+ ctx: ExtensionCommandContext,
74
+ options: Omit<PromptArgumentInputOptions, "signal">,
75
+ ): Promise<string | undefined> {
76
+ if (ctx.signal?.aborted) return;
77
+ return ctx.ui.custom<string | undefined>((tui, theme, _keybindings, done) =>
78
+ createPromptArgumentInput(tui, theme, done, {
79
+ ...options,
80
+ ...(ctx.signal ? { signal: ctx.signal } : {}),
81
+ }),
82
+ );
83
+ }