lsd-pi 1.1.10 → 1.2.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 (49) hide show
  1. package/dist/resources/extensions/slash-commands/index.js +2 -0
  2. package/dist/resources/extensions/slash-commands/init.js +47 -0
  3. package/dist/resources/extensions/slash-commands/plan.js +231 -50
  4. package/dist/resources/extensions/slash-commands/tools.js +14 -27
  5. package/dist/resources/extensions/subagent/index.js +5 -10
  6. package/package.json +1 -1
  7. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  8. package/packages/pi-coding-agent/dist/core/agent-session.js +11 -5
  9. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  10. package/packages/pi-coding-agent/dist/core/resource-loader-lsd-md.test.js +59 -7
  11. package/packages/pi-coding-agent/dist/core/resource-loader-lsd-md.test.js.map +1 -1
  12. package/packages/pi-coding-agent/dist/core/resource-loader.js +4 -4
  13. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  14. package/packages/pi-coding-agent/dist/core/sdk.d.ts +1 -1
  15. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  16. package/packages/pi-coding-agent/dist/core/sdk.js +18 -7
  17. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  18. package/packages/pi-coding-agent/dist/core/sdk.test.js +80 -0
  19. package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
  20. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +12 -5
  21. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  22. package/packages/pi-coding-agent/dist/core/settings-manager.js +23 -9
  23. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  24. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +8 -4
  25. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  26. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +32 -5
  27. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  28. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  29. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +8 -0
  30. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  31. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  32. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +34 -25
  33. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  34. package/packages/pi-coding-agent/package.json +1 -1
  35. package/packages/pi-coding-agent/src/core/agent-session.ts +13 -5
  36. package/packages/pi-coding-agent/src/core/resource-loader-lsd-md.test.ts +67 -7
  37. package/packages/pi-coding-agent/src/core/resource-loader.ts +4 -4
  38. package/packages/pi-coding-agent/src/core/sdk.test.ts +100 -0
  39. package/packages/pi-coding-agent/src/core/sdk.ts +23 -8
  40. package/packages/pi-coding-agent/src/core/settings-manager.ts +36 -15
  41. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +41 -10
  42. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +11 -0
  43. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +43 -27
  44. package/pkg/package.json +1 -1
  45. package/src/resources/extensions/slash-commands/index.ts +2 -0
  46. package/src/resources/extensions/slash-commands/init.ts +55 -0
  47. package/src/resources/extensions/slash-commands/plan.ts +268 -52
  48. package/src/resources/extensions/slash-commands/tools.ts +15 -29
  49. package/src/resources/extensions/subagent/index.ts +5 -10
@@ -178,6 +178,17 @@ export interface InteractiveModeOptions {
178
178
  runSetupWizard?: () => Promise<void>;
179
179
  }
180
180
 
181
+ function getToolNamesForProfile(
182
+ profile: "balanced" | "full",
183
+ editMode: "standard" | "hashline",
184
+ availableToolNames: string[],
185
+ ): string[] {
186
+ const balancedToolNames = editMode === "hashline"
187
+ ? ["hashline_read", "bash", "hashline_edit", "write", "lsp", "bg_shell", "tool_search", "tool_enable", "Skill", "subagent", "await_subagent", "ask_user_questions"]
188
+ : ["read", "bash", "edit", "write", "lsp", "bg_shell", "tool_search", "tool_enable", "Skill", "subagent", "await_subagent", "ask_user_questions"];
189
+ return profile === "full" ? availableToolNames : balancedToolNames;
190
+ }
191
+
181
192
  export class InteractiveMode {
182
193
  private session: AgentSession;
183
194
  private ui: TUI;
@@ -2405,13 +2416,13 @@ export class InteractiveMode {
2405
2416
  await handleAgentEvent(this as any, event);
2406
2417
  }
2407
2418
 
2408
- private getLatestPlanModeState(): { active?: boolean; latestPlanPath?: string } | undefined {
2419
+ private getLatestPlanModeState(): { active?: boolean; latestPlanPath?: string; approvalStatus?: string } | undefined {
2409
2420
  try {
2410
2421
  const entries = this.session.sessionManager.getEntries();
2411
2422
  for (let i = entries.length - 1; i >= 0; i--) {
2412
2423
  const entry = entries[i];
2413
2424
  if (entry.type === "custom" && entry.customType === "plan-mode-state" && entry.data && typeof entry.data === "object") {
2414
- return entry.data as { active?: boolean; latestPlanPath?: string };
2425
+ return entry.data as { active?: boolean; latestPlanPath?: string; approvalStatus?: string };
2415
2426
  }
2416
2427
  }
2417
2428
  } catch {
@@ -2421,17 +2432,26 @@ export class InteractiveMode {
2421
2432
  }
2422
2433
 
2423
2434
  private getPlanModeEditorBadge(): string {
2435
+ // Show badge when actively in plan mode OR when plan is approved (executing)
2436
+ // Only clear when plan is cancelled or there's no plan state at all.
2437
+ const permMode = getPermissionMode();
2424
2438
  const planState = this.getLatestPlanModeState();
2425
- if (!planState?.active) return "";
2426
2439
 
2427
- const planName = planState.latestPlanPath
2440
+ const inPlanMode = permMode === "plan";
2441
+ const planApproved = planState?.approvalStatus === "approved" && !planState?.active;
2442
+
2443
+ if (!inPlanMode && !planApproved) return "";
2444
+
2445
+ const planName = planState?.latestPlanPath
2428
2446
  ? path.basename(planState.latestPlanPath).replace(/\.md$/i, "")
2429
2447
  : "draft";
2430
- const badgeText = ` plan ${planName} · /plan to show plan `;
2448
+ const badgeText = inPlanMode
2449
+ ? ` plan ${planName} · /plan to show plan `
2450
+ : ` plan ${planName} · executing `;
2431
2451
 
2432
2452
  // Deterministic "random" color per plan so it feels varied without flickering.
2433
2453
  const palette = [18, 19, 20, 24, 25, 26, 27, 54, 55, 56, 57, 60, 88, 89, 90, 124, 125, 126, 160, 161, 162];
2434
- const seed = planState.latestPlanPath ?? planName;
2454
+ const seed = planState?.latestPlanPath ?? planName;
2435
2455
  const digest = crypto.createHash("sha256").update(seed).digest();
2436
2456
  const bg256 = palette[digest[0] % palette.length] ?? 25;
2437
2457
 
@@ -3407,11 +3427,12 @@ export class InteractiveMode {
3407
3427
  planModeReasoningModel: this.settingsManager.getPlanModeReasoningModel() ?? "default",
3408
3428
  planModeReviewModel: this.settingsManager.getPlanModeReviewModel() ?? "default",
3409
3429
  planModeCodingModel: this.settingsManager.getPlanModeCodingModel() ?? "default",
3430
+ autoSuggestPlanMode: this.settingsManager.getAutoSuggestPlanMode(),
3431
+ autoSwitchPlanModel: this.settingsManager.getAutoSwitchPlanModel(),
3410
3432
  showImages: this.settingsManager.getShowImages(),
3411
3433
  autoResizeImages: this.settingsManager.getImageAutoResize(),
3412
3434
  blockImages: this.settingsManager.getBlockImages(),
3413
3435
  enableSkillCommands: this.settingsManager.getEnableSkillCommands(),
3414
- toolSearch: this.settingsManager.getToolSearch(),
3415
3436
  toolProfile: this.settingsManager.getToolProfile(),
3416
3437
  codexRotate: this.settingsManager.getCodexRotate(),
3417
3438
  cacheTimer: this.settingsManager.getCacheTimer(),
@@ -3420,6 +3441,7 @@ export class InteractiveMode {
3420
3441
  followUpMode: this.session.followUpMode,
3421
3442
  transport: this.settingsManager.getTransport(),
3422
3443
  thinkingLevel: this.session.thinkingLevel,
3444
+ anthropicAdaptiveByDefault: this.settingsManager.getAnthropicAdaptiveByDefault(),
3423
3445
  availableThinkingLevels: this.session.getAvailableThinkingLevels(),
3424
3446
  currentTheme: this.settingsManager.getTheme() || "dark",
3425
3447
  currentThemeAccent: this.settingsManager.getThemeAccent() || "default",
@@ -3554,6 +3576,14 @@ export class InteractiveMode {
3554
3576
  `Plan coding model: ${modelRef === "default" ? "use current/default model" : modelRef}`,
3555
3577
  );
3556
3578
  },
3579
+ onAutoSuggestPlanModeChange: (enabled) => {
3580
+ this.settingsManager.setAutoSuggestPlanMode(enabled);
3581
+ this.showStatus(`Auto-suggest plan mode: ${enabled ? "enabled" : "disabled"}`);
3582
+ },
3583
+ onAutoSwitchPlanModelChange: (enabled) => {
3584
+ this.settingsManager.setAutoSwitchPlanModel(enabled);
3585
+ this.showStatus(`OpusPlan mode: ${enabled ? "enabled" : "disabled"}`);
3586
+ },
3557
3587
  onShowImagesChange: (enabled) => {
3558
3588
  this.settingsManager.setShowImages(enabled);
3559
3589
  for (const child of this.chatContainer.children) {
@@ -3572,28 +3602,10 @@ export class InteractiveMode {
3572
3602
  this.settingsManager.setEnableSkillCommands(enabled);
3573
3603
  this.setupAutocomplete();
3574
3604
  },
3575
- onToolSearchChange: (enabled) => {
3576
- const profile = enabled ? "minimal" : "balanced";
3577
- this.settingsManager.setToolProfile(profile);
3578
- const nextActiveToolNames = profile === "minimal"
3579
- ? (this.session.editMode === "hashline"
3580
- ? ["hashline_read", "bash", "lsp", "tool_search", "tool_enable"]
3581
- : ["read", "bash", "lsp", "tool_search", "tool_enable"])
3582
- : (this.session.editMode === "hashline"
3583
- ? ["hashline_read", "bash", "hashline_edit", "write", "lsp", "bg_shell", "tool_search", "tool_enable", "Skill", "subagent", "await_subagent"]
3584
- : ["read", "bash", "edit", "write", "lsp", "bg_shell", "tool_search", "tool_enable", "Skill", "subagent", "await_subagent"]);
3585
- this.session.setActiveToolsByName(nextActiveToolNames);
3586
- this.showStatus(`Tool profile: ${profile}`);
3587
- },
3588
3605
  onToolProfileChange: (profile) => {
3589
3606
  this.settingsManager.setToolProfile(profile);
3590
- const nextActiveToolNames = profile === "minimal"
3591
- ? (this.session.editMode === "hashline"
3592
- ? ["hashline_read", "bash", "lsp", "tool_search", "tool_enable"]
3593
- : ["read", "bash", "lsp", "tool_search", "tool_enable"])
3594
- : (this.session.editMode === "hashline"
3595
- ? ["hashline_read", "bash", "hashline_edit", "write", "lsp", "bg_shell", "tool_search", "tool_enable", "Skill", "subagent", "await_subagent"]
3596
- : ["read", "bash", "edit", "write", "lsp", "bg_shell", "tool_search", "tool_enable", "Skill", "subagent", "await_subagent"]);
3607
+ const allToolNames = this.session.getAllTools().map((tool) => tool.name);
3608
+ const nextActiveToolNames = getToolNamesForProfile(profile, this.session.editMode, allToolNames);
3597
3609
  this.session.setActiveToolsByName(nextActiveToolNames);
3598
3610
  this.showStatus(`Tool profile: ${profile}`);
3599
3611
  },
@@ -3642,6 +3654,10 @@ export class InteractiveMode {
3642
3654
  this.footer.invalidate();
3643
3655
  this.updateEditorBorderColor();
3644
3656
  },
3657
+ onAnthropicAdaptiveByDefaultChange: (enabled) => {
3658
+ this.settingsManager.setAnthropicAdaptiveByDefault(enabled);
3659
+ this.showStatus(`Anthropic adaptive default: ${enabled ? "enabled" : "disabled"}`);
3660
+ },
3645
3661
  onThemeChange: (themeName) => {
3646
3662
  const result = setTheme(themeName, true, this.settingsManager.getThemeAccent());
3647
3663
  this.settingsManager.setTheme(themeName);
package/pkg/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lsd-pi",
3
- "version": "1.1.8",
3
+ "version": "1.2.0",
4
4
  "piConfig": {
5
5
  "name": "lsd",
6
6
  "configDir": ".lsd"
@@ -2,6 +2,7 @@ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
2
2
  import auditCommand from "./audit.js";
3
3
  import clearCommand from "./clear.js";
4
4
  import contextCommand from "./context.js";
5
+ import initCommand from "./init.js";
5
6
  import planCommand from "./plan.js";
6
7
  import toolSearchExtension from "./tools.js";
7
8
 
@@ -9,6 +10,7 @@ export default function slashCommands(pi: ExtensionAPI) {
9
10
  auditCommand(pi);
10
11
  clearCommand(pi);
11
12
  contextCommand(pi);
13
+ initCommand(pi);
12
14
  planCommand(pi);
13
15
  toolSearchExtension(pi);
14
16
  }
@@ -0,0 +1,55 @@
1
+ import { getAgentDir, type ExtensionAPI, type ExtensionCommandContext } from "@gsd/pi-coding-agent";
2
+ import { existsSync, writeFileSync } from "node:fs";
3
+ import { join, resolve } from "node:path";
4
+
5
+ const STARTER_CONTENT = `# Project Context
6
+
7
+ ## Overview
8
+ - Add a short description of this project and its purpose.
9
+
10
+ ## Commands
11
+ - Build:
12
+ - Test:
13
+ - Lint:
14
+
15
+ ## Conventions
16
+ - Add coding conventions, architecture notes, and review expectations.
17
+ `;
18
+
19
+ function ensureFile(filePath: string): "created" | "exists" {
20
+ if (existsSync(filePath)) {
21
+ return "exists";
22
+ }
23
+ writeFileSync(filePath, STARTER_CONTENT, "utf-8");
24
+ return "created";
25
+ }
26
+
27
+ export default function initCommand(pi: ExtensionAPI) {
28
+ pi.registerCommand("init", {
29
+ description: "Initialize global and project LSD.md files if they do not exist",
30
+ async handler(_args: string, ctx: ExtensionCommandContext) {
31
+ const globalPath = resolve(getAgentDir(), "..", "LSD.md");
32
+ const projectPath = join(ctx.cwd, "LSD.md");
33
+
34
+ const globalStatus = ensureFile(globalPath);
35
+ const projectStatus = ensureFile(projectPath);
36
+
37
+ await ctx.reload();
38
+
39
+ const lines = ["Initialized LSD.md files", ""];
40
+ lines.push(`Global: ${globalStatus === "created" ? "created" : "exists"} ${globalPath}`);
41
+ lines.push(`Project: ${projectStatus === "created" ? "created" : "exists"} ${projectPath}`);
42
+
43
+ if (globalStatus === "exists" && projectStatus === "exists") {
44
+ lines.push("");
45
+ lines.push("Nothing changed.");
46
+ }
47
+
48
+ pi.sendMessage({
49
+ customType: "init:report",
50
+ content: lines.join("\n"),
51
+ display: true,
52
+ });
53
+ },
54
+ });
55
+ }