my-pi 0.1.1 → 0.1.3

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.
@@ -60,6 +60,10 @@ function parse_chain_yaml(raw) {
60
60
  if (current && current_step) current.steps.push(current_step);
61
61
  return chains;
62
62
  }
63
+ function should_inject_chain_prompt(event) {
64
+ const selected_tools = event.systemPromptOptions?.selectedTools;
65
+ return !selected_tools || selected_tools.includes("run_chain");
66
+ }
63
67
  function parse_agent_file(filePath) {
64
68
  try {
65
69
  const { frontmatter, body } = parseFrontmatter(readFileSync(filePath, "utf-8"));
@@ -290,6 +294,7 @@ async function chain(pi) {
290
294
  });
291
295
  pi.on("before_agent_start", async (event) => {
292
296
  if (!active_chain || chains.length === 0) return {};
297
+ if (!should_inject_chain_prompt(event)) return {};
293
298
  const flow = active_chain.steps.map((s) => s.agent).join(" -> ");
294
299
  const step_list = active_chain.steps.map((s, i) => {
295
300
  const desc = agents.get(s.agent.toLowerCase())?.description || "unknown";
@@ -340,7 +345,7 @@ Switch chains with /chain <name>.` };
340
345
  }
341
346
  //#endregion
342
347
  //#region src/extensions/config.ts
343
- const DEFAULT_CONFIG$2 = {
348
+ const DEFAULT_CONFIG$3 = {
344
349
  version: 1,
345
350
  enabled: {}
346
351
  };
@@ -434,6 +439,17 @@ const BUILTIN_EXTENSIONS = [
434
439
  description: "Claude Code style PostToolUse hook compatibility from .claude, .rulesync, and .pi configs",
435
440
  cli_flag: "--no-hooks",
436
441
  aliases: ["hooks-resolution", "hooks"]
442
+ },
443
+ {
444
+ key: "working-indicator",
445
+ label: "Working indicator",
446
+ description: "Customizable streaming working indicator with /working-indicator command",
447
+ cli_flag: "--no-working-indicator",
448
+ aliases: [
449
+ "working-indicator",
450
+ "indicator",
451
+ "spinner"
452
+ ]
437
453
  }
438
454
  ];
439
455
  function get_builtin_extensions_config_path() {
@@ -441,7 +457,7 @@ function get_builtin_extensions_config_path() {
441
457
  }
442
458
  function load_builtin_extensions_config() {
443
459
  const path = get_builtin_extensions_config_path();
444
- if (!existsSync(path)) return { ...DEFAULT_CONFIG$2 };
460
+ if (!existsSync(path)) return { ...DEFAULT_CONFIG$3 };
445
461
  try {
446
462
  const raw = readFileSync(path, "utf-8");
447
463
  const parsed = JSON.parse(raw);
@@ -455,7 +471,7 @@ function load_builtin_extensions_config() {
455
471
  enabled
456
472
  };
457
473
  } catch {
458
- return { ...DEFAULT_CONFIG$2 };
474
+ return { ...DEFAULT_CONFIG$3 };
459
475
  }
460
476
  }
461
477
  function save_builtin_extensions_config(config) {
@@ -2515,6 +2531,14 @@ function load_mcp_config(cwd) {
2515
2531
  }
2516
2532
  //#endregion
2517
2533
  //#region src/extensions/mcp.ts
2534
+ function create_server_states(configs) {
2535
+ return new Map(configs.map((config) => [config.name, {
2536
+ config,
2537
+ tool_names: [],
2538
+ enabled: true,
2539
+ status: "disconnected"
2540
+ }]));
2541
+ }
2518
2542
  function remove_server_tools_from_active(pi, tool_names) {
2519
2543
  const tool_set = new Set(tool_names);
2520
2544
  pi.setActiveTools(pi.getActiveTools().filter((tool) => !tool_set.has(tool)));
@@ -2527,16 +2551,56 @@ function format_server_status(state) {
2527
2551
  default: return state.enabled ? "not connected yet" : "disabled";
2528
2552
  }
2529
2553
  }
2554
+ function count_pending_enabled_servers(servers) {
2555
+ return Array.from(servers.values()).filter((state) => state.enabled && state.status !== "connected").length;
2556
+ }
2557
+ function update_mcp_status(ctx, servers) {
2558
+ if (servers.size === 0) {
2559
+ ctx.ui.setStatus("mcp", void 0);
2560
+ return;
2561
+ }
2562
+ const states = Array.from(servers.values());
2563
+ const enabled = states.filter((state) => state.enabled).length;
2564
+ const connected = states.filter((state) => state.enabled && state.status === "connected").length;
2565
+ const connecting = states.filter((state) => state.enabled && state.status === "connecting").length;
2566
+ const failed = states.filter((state) => state.enabled && state.status === "failed").length;
2567
+ const fragments = [`MCP ${connected}/${enabled} connected`];
2568
+ if (connecting > 0) fragments.push(`${connecting} connecting`);
2569
+ if (failed > 0) fragments.push(`${failed} failed`);
2570
+ ctx.ui.setStatus("mcp", ctx.ui.theme.fg("dim", fragments.join(" · ")));
2571
+ }
2572
+ function set_connect_feedback(ctx, pending_server_count) {
2573
+ const label = pending_server_count === 1 ? "Connecting 1 MCP server..." : `Connecting ${pending_server_count} MCP servers...`;
2574
+ ctx.ui.setWorkingMessage(label);
2575
+ ctx.ui.setWorkingIndicator({
2576
+ frames: [
2577
+ ctx.ui.theme.fg("dim", "·"),
2578
+ ctx.ui.theme.fg("muted", "•"),
2579
+ ctx.ui.theme.fg("accent", "●"),
2580
+ ctx.ui.theme.fg("muted", "•")
2581
+ ],
2582
+ intervalMs: 120
2583
+ });
2584
+ ctx.ui.setStatus("mcp", ctx.ui.theme.fg("dim", label));
2585
+ return () => {
2586
+ ctx.ui.setWorkingMessage();
2587
+ ctx.ui.setWorkingIndicator();
2588
+ };
2589
+ }
2590
+ function should_wait_for_mcp_connections(event) {
2591
+ const selected_tools = event.systemPromptOptions?.selectedTools;
2592
+ return !selected_tools || selected_tools.some((tool) => tool.startsWith("mcp__"));
2593
+ }
2530
2594
  async function mcp(pi) {
2531
- const configs = load_mcp_config(process.cwd());
2532
- const servers = new Map(configs.map((config) => [config.name, {
2533
- config,
2534
- tool_names: [],
2535
- enabled: true,
2536
- status: "disconnected"
2537
- }]));
2595
+ let initialized_cwd = null;
2596
+ let servers = /* @__PURE__ */ new Map();
2538
2597
  const registered_tool_names = /* @__PURE__ */ new Set();
2539
- const connect_server = async (state) => {
2598
+ const ensure_servers = (cwd) => {
2599
+ if (initialized_cwd !== null) return;
2600
+ servers = create_server_states(load_mcp_config(cwd));
2601
+ initialized_cwd = cwd;
2602
+ };
2603
+ const connect_server = async (state, ctx) => {
2540
2604
  if (state.status === "connected") return;
2541
2605
  if (state.connect_promise) {
2542
2606
  await state.connect_promise;
@@ -2545,6 +2609,7 @@ async function mcp(pi) {
2545
2609
  state.connect_promise = (async () => {
2546
2610
  state.status = "connecting";
2547
2611
  state.error = void 0;
2612
+ if (ctx) update_mcp_status(ctx, servers);
2548
2613
  const client = new McpClient(state.config);
2549
2614
  try {
2550
2615
  await client.connect();
@@ -2588,19 +2653,39 @@ async function mcp(pi) {
2588
2653
  throw error;
2589
2654
  } finally {
2590
2655
  state.connect_promise = void 0;
2656
+ if (ctx) update_mcp_status(ctx, servers);
2591
2657
  }
2592
2658
  })();
2593
2659
  await state.connect_promise;
2594
2660
  };
2595
2661
  const connect_all_servers = async (options = {}) => {
2596
- await Promise.allSettled(Array.from(servers.values()).filter((state) => state.enabled).filter((state) => options.include_failed || state.status !== "failed").map((state) => connect_server(state)));
2662
+ await Promise.allSettled(Array.from(servers.values()).filter((state) => state.enabled).filter((state) => options.include_failed || state.status !== "failed").map((state) => connect_server(state, options.ctx)));
2663
+ if (options.ctx) update_mcp_status(options.ctx, servers);
2597
2664
  };
2598
- pi.on("session_start", async () => {
2599
- connect_all_servers();
2665
+ pi.on("session_start", async (_event, ctx) => {
2666
+ ensure_servers(ctx.cwd);
2667
+ update_mcp_status(ctx, servers);
2668
+ connect_all_servers({ ctx });
2600
2669
  });
2601
- pi.on("before_agent_start", async (event) => {
2602
- await connect_all_servers();
2603
- return event;
2670
+ pi.on("before_agent_start", async (event, ctx) => {
2671
+ ensure_servers(ctx.cwd);
2672
+ if (!should_wait_for_mcp_connections(event)) {
2673
+ connect_all_servers({ ctx });
2674
+ return event;
2675
+ }
2676
+ const pending_server_count = count_pending_enabled_servers(servers);
2677
+ if (pending_server_count === 0) {
2678
+ update_mcp_status(ctx, servers);
2679
+ return event;
2680
+ }
2681
+ const restore_feedback = set_connect_feedback(ctx, pending_server_count);
2682
+ try {
2683
+ await connect_all_servers({ ctx });
2684
+ return event;
2685
+ } finally {
2686
+ restore_feedback();
2687
+ update_mcp_status(ctx, servers);
2688
+ }
2604
2689
  });
2605
2690
  pi.registerCommand("mcp", {
2606
2691
  description: "Manage MCP servers (list, enable, disable)",
@@ -2624,6 +2709,7 @@ async function mcp(pi) {
2624
2709
  return null;
2625
2710
  },
2626
2711
  handler: async (args, ctx) => {
2712
+ ensure_servers(ctx.cwd);
2627
2713
  const [sub, ...rest] = args.trim().split(/\s+/);
2628
2714
  const name = rest.join(" ");
2629
2715
  switch (sub || "list") {
@@ -2634,6 +2720,7 @@ async function mcp(pi) {
2634
2720
  }
2635
2721
  const lines = [];
2636
2722
  for (const [sname, state] of servers.entries()) lines.push(`${sname} (${format_server_status(state)}) — ${state.tool_names.length} tools${state.error ? ` — ${state.error}` : ""}`);
2723
+ update_mcp_status(ctx, servers);
2637
2724
  ctx.ui.notify(lines.join("\n"));
2638
2725
  break;
2639
2726
  }
@@ -2650,7 +2737,8 @@ async function mcp(pi) {
2650
2737
  server.enabled = true;
2651
2738
  if (server.status === "connected") {
2652
2739
  const active = pi.getActiveTools();
2653
- pi.setActiveTools([...active, ...server.tool_names]);
2740
+ pi.setActiveTools([...new Set([...active, ...server.tool_names])]);
2741
+ update_mcp_status(ctx, servers);
2654
2742
  ctx.ui.notify(`Enabled ${name}`);
2655
2743
  return;
2656
2744
  }
@@ -2658,7 +2746,8 @@ async function mcp(pi) {
2658
2746
  server.status = "disconnected";
2659
2747
  server.error = void 0;
2660
2748
  }
2661
- connect_server(server);
2749
+ update_mcp_status(ctx, servers);
2750
+ connect_server(server, ctx);
2662
2751
  ctx.ui.notify(`Enabling ${name} and connecting in background`);
2663
2752
  break;
2664
2753
  }
@@ -2674,6 +2763,7 @@ async function mcp(pi) {
2674
2763
  }
2675
2764
  server.enabled = false;
2676
2765
  remove_server_tools_from_active(pi, server.tool_names);
2766
+ update_mcp_status(ctx, servers);
2677
2767
  ctx.ui.notify(`Disabled ${name}`);
2678
2768
  break;
2679
2769
  }
@@ -2681,13 +2771,14 @@ async function mcp(pi) {
2681
2771
  }
2682
2772
  }
2683
2773
  });
2684
- pi.on("session_shutdown", async () => {
2774
+ pi.on("session_shutdown", async (_event, ctx) => {
2685
2775
  await Promise.allSettled(Array.from(servers.values()).map(async (server) => {
2686
2776
  await server.connect_promise?.catch(() => {});
2687
2777
  await server.client?.disconnect();
2688
2778
  server.client = void 0;
2689
2779
  if (server.status !== "failed") server.status = "disconnected";
2690
2780
  }));
2781
+ ctx.ui.setStatus("mcp", void 0);
2691
2782
  });
2692
2783
  }
2693
2784
  //#endregion
@@ -2959,6 +3050,24 @@ function format_token_count(count) {
2959
3050
  if (count < 1e7) return `${(count / 1e6).toFixed(1)}M`;
2960
3051
  return `${Math.round(count / 1e6)}M`;
2961
3052
  }
3053
+ function render_footer_status_line(theme, width, left_items, right_item) {
3054
+ const left = sanitize_status_text(left_items.join(" "));
3055
+ const right = right_item ? sanitize_status_text(right_item) : "";
3056
+ if (!left && !right) return void 0;
3057
+ if (!right) return truncateToWidth(theme.fg("dim", left), width, theme.fg("dim", "..."));
3058
+ if (!left) {
3059
+ const themed_right = theme.fg("dim", right);
3060
+ const right_width = visibleWidth(themed_right);
3061
+ return right_width >= width ? truncateToWidth(themed_right, width, theme.fg("dim", "...")) : `${" ".repeat(width - right_width)}${themed_right}`;
3062
+ }
3063
+ const right_width = visibleWidth(right);
3064
+ if (right_width >= width) return truncateToWidth(theme.fg("dim", right), width, theme.fg("dim", "..."));
3065
+ const min_gap = 1;
3066
+ const truncated_left = truncateToWidth(left, Math.max(0, width - right_width - min_gap), "...");
3067
+ const left_width = visibleWidth(truncated_left);
3068
+ const gap = Math.max(min_gap, width - left_width - right_width);
3069
+ return theme.fg("dim", truncated_left) + " ".repeat(gap) + theme.fg("dim", right);
3070
+ }
2962
3071
  function get_current_thinking_level(ctx) {
2963
3072
  const entries = ctx.sessionManager.getEntries();
2964
3073
  for (let i = entries.length - 1; i >= 0; i--) {
@@ -3038,14 +3147,8 @@ function render_footer_lines(ctx, theme, footer_data, width, active_base_name, a
3038
3147
  const dim_remainder = theme.fg("dim", remainder);
3039
3148
  const lines = [truncateToWidth(theme.fg("dim", pwd), width, theme.fg("dim", "...")), dim_stats_left + dim_remainder];
3040
3149
  const prompt_status = get_footer_prompt_status(active_base_name, active_layers);
3041
- if (prompt_status) {
3042
- const themed_status = theme.fg("dim", prompt_status);
3043
- const status_width = visibleWidth(themed_status);
3044
- const aligned_status = status_width >= width ? truncateToWidth(themed_status, width, theme.fg("dim", "...")) : `${" ".repeat(width - status_width)}${themed_status}`;
3045
- lines.push(aligned_status);
3046
- }
3047
- const other_statuses = Array.from(footer_data.getExtensionStatuses().entries()).filter(([key]) => key !== "preset").sort(([a], [b]) => a.localeCompare(b)).map(([, text]) => sanitize_status_text(text));
3048
- if (other_statuses.length > 0) lines.push(truncateToWidth(other_statuses.join(" "), width, theme.fg("dim", "...")));
3150
+ const combined_status_line = render_footer_status_line(theme, width, Array.from(footer_data.getExtensionStatuses().entries()).filter(([key]) => key !== "preset").sort(([a], [b]) => a.localeCompare(b)).map(([, text]) => sanitize_status_text(text)), prompt_status);
3151
+ if (combined_status_line) lines.push(combined_status_line);
3049
3152
  return lines;
3050
3153
  }
3051
3154
  function set_status(ctx, active_base_name, active_layers) {
@@ -3508,6 +3611,10 @@ async function prompt_presets(pi) {
3508
3611
  //#endregion
3509
3612
  //#region src/extensions/recall.ts
3510
3613
  const DEFAULT_DB_PATH = join(process.env.HOME, ".pi", "pirecall.db");
3614
+ function should_inject_recall_prompt(event) {
3615
+ const selected_tools = event.systemPromptOptions?.selectedTools;
3616
+ return !selected_tools || selected_tools.includes("bash");
3617
+ }
3511
3618
  function sync_recall_db_in_background() {
3512
3619
  if (!existsSync(DEFAULT_DB_PATH)) return;
3513
3620
  try {
@@ -3523,6 +3630,7 @@ async function recall(pi) {
3523
3630
  sync_recall_db_in_background();
3524
3631
  });
3525
3632
  pi.on("before_agent_start", async (event) => {
3633
+ if (!should_inject_recall_prompt(event)) return {};
3526
3634
  return { systemPrompt: event.systemPrompt + `
3527
3635
 
3528
3636
  ## Session Recall
@@ -3661,7 +3769,7 @@ async function session_name(pi) {
3661
3769
  }
3662
3770
  //#endregion
3663
3771
  //#region src/skills/config.ts
3664
- const DEFAULT_CONFIG$1 = {
3772
+ const DEFAULT_CONFIG$2 = {
3665
3773
  version: 1,
3666
3774
  enabled: {},
3667
3775
  defaults: "all-disabled"
@@ -3671,7 +3779,7 @@ function get_config_path() {
3671
3779
  }
3672
3780
  function load_skills_config() {
3673
3781
  const path = get_config_path();
3674
- if (!existsSync(path)) return { ...DEFAULT_CONFIG$1 };
3782
+ if (!existsSync(path)) return { ...DEFAULT_CONFIG$2 };
3675
3783
  try {
3676
3784
  const raw = readFileSync(path, "utf-8");
3677
3785
  const parsed = JSON.parse(raw);
@@ -3681,7 +3789,7 @@ function load_skills_config() {
3681
3789
  defaults: parsed.defaults ?? "all-enabled"
3682
3790
  };
3683
3791
  } catch {
3684
- return { ...DEFAULT_CONFIG$1 };
3792
+ return { ...DEFAULT_CONFIG$2 };
3685
3793
  }
3686
3794
  }
3687
3795
  function save_skills_config(config) {
@@ -4408,7 +4516,7 @@ async function skills(pi) {
4408
4516
  }
4409
4517
  //#endregion
4410
4518
  //#region src/extensions/telemetry-config.ts
4411
- const DEFAULT_CONFIG = {
4519
+ const DEFAULT_CONFIG$1 = {
4412
4520
  version: 1,
4413
4521
  enabled: false
4414
4522
  };
@@ -4424,15 +4532,15 @@ function resolve_telemetry_db_path(cwd, override_path) {
4424
4532
  }
4425
4533
  function load_telemetry_config() {
4426
4534
  const path = get_telemetry_config_path();
4427
- if (!existsSync(path)) return { ...DEFAULT_CONFIG };
4535
+ if (!existsSync(path)) return { ...DEFAULT_CONFIG$1 };
4428
4536
  try {
4429
4537
  const parsed = JSON.parse(readFileSync(path, "utf-8"));
4430
4538
  return {
4431
- version: typeof parsed.version === "number" ? parsed.version : DEFAULT_CONFIG.version,
4432
- enabled: typeof parsed.enabled === "boolean" ? parsed.enabled : DEFAULT_CONFIG.enabled
4539
+ version: typeof parsed.version === "number" ? parsed.version : DEFAULT_CONFIG$1.version,
4540
+ enabled: typeof parsed.enabled === "boolean" ? parsed.enabled : DEFAULT_CONFIG$1.enabled
4433
4541
  };
4434
4542
  } catch {
4435
- return { ...DEFAULT_CONFIG };
4543
+ return { ...DEFAULT_CONFIG$1 };
4436
4544
  }
4437
4545
  }
4438
4546
  function save_telemetry_config(config) {
@@ -4591,6 +4699,10 @@ function infer_run_outcome(event) {
4591
4699
  error_message: null
4592
4700
  };
4593
4701
  }
4702
+ function describe_session_shutdown(event) {
4703
+ const base = `session shutdown (${event.reason})`;
4704
+ return event.targetSessionFile ? `${base} → ${event.targetSessionFile}` : base;
4705
+ }
4594
4706
  function format_telemetry_status(options) {
4595
4707
  const override_label = options.override === void 0 ? "none" : options.override ? "--telemetry" : "--no-telemetry";
4596
4708
  return [
@@ -4983,12 +5095,12 @@ function create_telemetry_extension(options = {}) {
4983
5095
  headers_json: summarize_headers(event.headers)
4984
5096
  });
4985
5097
  });
4986
- pi.on("session_shutdown", async () => {
5098
+ pi.on("session_shutdown", async (event) => {
4987
5099
  if (store && active_run) store.finish_run({
4988
5100
  id: active_run.id,
4989
5101
  ended_at: now(),
4990
5102
  success: null,
4991
- error_message: "session shutdown"
5103
+ error_message: describe_session_shutdown(event)
4992
5104
  });
4993
5105
  close_store();
4994
5106
  active_run = null;
@@ -4999,6 +5111,108 @@ function create_telemetry_extension(options = {}) {
4999
5111
  }
5000
5112
  create_telemetry_extension();
5001
5113
  //#endregion
5114
+ //#region src/extensions/working-indicator-config.ts
5115
+ const DEFAULT_CONFIG = {
5116
+ version: 1,
5117
+ mode: "default"
5118
+ };
5119
+ function get_working_indicator_config_path() {
5120
+ return join(getAgentDir(), "working-indicator.json");
5121
+ }
5122
+ function load_working_indicator_config() {
5123
+ const path = get_working_indicator_config_path();
5124
+ if (!existsSync(path)) return { ...DEFAULT_CONFIG };
5125
+ try {
5126
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
5127
+ return {
5128
+ version: typeof parsed.version === "number" ? parsed.version : DEFAULT_CONFIG.version,
5129
+ mode: is_working_indicator_mode(parsed.mode) ? parsed.mode : DEFAULT_CONFIG.mode
5130
+ };
5131
+ } catch {
5132
+ return { ...DEFAULT_CONFIG };
5133
+ }
5134
+ }
5135
+ function save_working_indicator_config(config) {
5136
+ const path = get_working_indicator_config_path();
5137
+ const dir = dirname(path);
5138
+ if (!existsSync(dir)) mkdirSync(dir, {
5139
+ recursive: true,
5140
+ mode: 448
5141
+ });
5142
+ const tmp = `${path}.tmp-${Date.now()}`;
5143
+ writeFileSync(tmp, JSON.stringify(config, null, " ") + "\n", { mode: 384 });
5144
+ renameSync(tmp, path);
5145
+ }
5146
+ function is_working_indicator_mode(value) {
5147
+ return value === "default" || value === "dot" || value === "none";
5148
+ }
5149
+ //#endregion
5150
+ //#region src/extensions/working-indicator.ts
5151
+ const COMMAND_MODES = [
5152
+ "dot",
5153
+ "none",
5154
+ "reset"
5155
+ ];
5156
+ function get_working_indicator(ctx, mode) {
5157
+ switch (mode) {
5158
+ case "dot": return { frames: [ctx.ui.theme.fg("accent", "●")] };
5159
+ case "none": return { frames: [] };
5160
+ case "default": return;
5161
+ }
5162
+ }
5163
+ function describe_working_indicator_mode(mode) {
5164
+ switch (mode) {
5165
+ case "dot": return "static dot";
5166
+ case "none": return "hidden";
5167
+ case "default": return "pi default spinner";
5168
+ }
5169
+ }
5170
+ function parse_working_indicator_mode(input) {
5171
+ const normalized = input.trim().toLowerCase();
5172
+ if (!normalized) return null;
5173
+ if (normalized === "reset" || normalized === "default") return "default";
5174
+ if (normalized === "dot" || normalized === "none") return normalized;
5175
+ return null;
5176
+ }
5177
+ function apply_working_indicator(ctx, mode) {
5178
+ ctx.ui.setWorkingIndicator(get_working_indicator(ctx, mode));
5179
+ }
5180
+ async function working_indicator(pi) {
5181
+ let mode = load_working_indicator_config().mode;
5182
+ pi.on("session_start", async (_event, ctx) => {
5183
+ mode = load_working_indicator_config().mode;
5184
+ apply_working_indicator(ctx, mode);
5185
+ });
5186
+ pi.registerCommand("working-indicator", {
5187
+ description: "Set the streaming working indicator: dot, none, or reset",
5188
+ getArgumentCompletions: (prefix) => {
5189
+ const value = prefix.trim().toLowerCase();
5190
+ return COMMAND_MODES.filter((entry) => entry.startsWith(value)).map((entry) => ({
5191
+ value: entry,
5192
+ label: entry
5193
+ }));
5194
+ },
5195
+ handler: async (args, ctx) => {
5196
+ const next = parse_working_indicator_mode(args);
5197
+ if (next === null) {
5198
+ if (!args.trim()) {
5199
+ ctx.ui.notify(`Working indicator: ${describe_working_indicator_mode(mode)}`, "info");
5200
+ return;
5201
+ }
5202
+ ctx.ui.notify("Usage: /working-indicator [dot|none|reset]", "error");
5203
+ return;
5204
+ }
5205
+ mode = next;
5206
+ save_working_indicator_config({
5207
+ version: 1,
5208
+ mode
5209
+ });
5210
+ apply_working_indicator(ctx, mode);
5211
+ ctx.ui.notify(`Working indicator set to: ${describe_working_indicator_mode(mode)}`, "info");
5212
+ }
5213
+ });
5214
+ }
5215
+ //#endregion
5002
5216
  //#region src/api.ts
5003
5217
  const BUILTIN_EXTENSION_FACTORIES = {
5004
5218
  mcp,
@@ -5011,7 +5225,8 @@ const BUILTIN_EXTENSION_FACTORIES = {
5011
5225
  lsp: lsp_default,
5012
5226
  "session-name": session_name,
5013
5227
  "confirm-destructive": confirm_destructive,
5014
- "hooks-resolution": hooks_resolution_default
5228
+ "hooks-resolution": hooks_resolution_default,
5229
+ "working-indicator": working_indicator
5015
5230
  };
5016
5231
  const PACKAGE_THEME_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "..", "themes");
5017
5232
  const PI_AGENT_DIR_ENV = "PI_CODING_AGENT_DIR";
@@ -5031,6 +5246,7 @@ function get_force_disabled_builtins(options) {
5031
5246
  if (!options.session_name) force_disabled.add("session-name");
5032
5247
  if (!options.confirm_destructive) force_disabled.add("confirm-destructive");
5033
5248
  if (!options.hooks_resolution) force_disabled.add("hooks-resolution");
5249
+ if (!options.working_indicator) force_disabled.add("working-indicator");
5034
5250
  return force_disabled;
5035
5251
  }
5036
5252
  function create_builtin_extension_factory(key, extension, force_disabled) {
@@ -5052,7 +5268,7 @@ function create_extensions_override(managed_inline_paths) {
5052
5268
  };
5053
5269
  }
5054
5270
  async function create_my_pi(options = {}) {
5055
- const { cwd = process.cwd(), agent_dir, extensions = [], extensionFactories: user_factories = [], mcp = true, skills = true, chain = true, filter_output = true, handoff = true, recall = true, prompt_presets = true, lsp = true, session_name = true, confirm_destructive = true, hooks_resolution = true, telemetry, telemetry_db_path, model, system_prompt, append_system_prompt } = options;
5271
+ const { cwd = process.cwd(), agent_dir, extensions = [], extensionFactories: user_factories = [], mcp = true, skills = true, chain = true, filter_output = true, handoff = true, recall = true, prompt_presets = true, lsp = true, session_name = true, confirm_destructive = true, hooks_resolution = true, working_indicator = true, telemetry, telemetry_db_path, model, system_prompt, append_system_prompt } = options;
5056
5272
  const effective_agent_dir = resolve_agent_dir(cwd, agent_dir);
5057
5273
  if (agent_dir) process.env[PI_AGENT_DIR_ENV] = effective_agent_dir;
5058
5274
  const resolved_extensions = extensions.map((p) => resolve(cwd, p));
@@ -5067,7 +5283,8 @@ async function create_my_pi(options = {}) {
5067
5283
  lsp,
5068
5284
  session_name,
5069
5285
  confirm_destructive,
5070
- hooks_resolution
5286
+ hooks_resolution,
5287
+ working_indicator
5071
5288
  });
5072
5289
  const managed_extension_factories = [
5073
5290
  create_telemetry_extension({
@@ -5125,4 +5342,4 @@ async function create_my_pi(options = {}) {
5125
5342
  //#endregion
5126
5343
  export { create_my_pi as n, runPrintMode$1 as r, InteractiveMode$1 as t };
5127
5344
 
5128
- //# sourceMappingURL=api-Dxi4curf.js.map
5345
+ //# sourceMappingURL=api-q7uQTUHx.js.map