@hk_net/pi-thinking-command 0.1.3 → 0.1.5

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # `/thinking` command extension for pi
2
2
 
3
- Adds a `/thinking` slash command to pi for changing the active thinking/reasoning level from inside a session.
3
+ Adds a `/thinking` slash command to pi `>=0.80.10` for changing the active thinking/reasoning level from inside a session.
4
4
 
5
5
  Normally in pi, changing the thinking/reasoning level means opening the settings menu, navigating to **Thinking**, and selecting the requested level. This extension is a convenience shortcut for that workflow, so you can switch levels directly with commands such as `/thinking low` or `/thinking xhigh`.
6
6
 
@@ -36,7 +36,7 @@ After installing, restart pi or run:
36
36
  ## Usage
37
37
 
38
38
  ```text
39
- /thinking [off|minimal|low|medium|high|xhigh]
39
+ /thinking [off|minimal|low|medium|high|xhigh|max]
40
40
  ```
41
41
 
42
42
  Examples:
@@ -47,6 +47,7 @@ Examples:
47
47
  /thinking medium
48
48
  /thinking high
49
49
  /thinking xhigh
50
+ /thinking max
50
51
  ```
51
52
 
52
53
  If no argument is provided, `/thinking` sets the level to `medium`.
@@ -58,7 +59,8 @@ If no argument is provided, `/thinking` sets the level to `medium`.
58
59
  - `low` — light reasoning
59
60
  - `medium` — balanced default reasoning
60
61
  - `high` — more reasoning for harder tasks
61
- - `xhigh` — maximum reasoning budget
62
+ - `xhigh` — very high reasoning budget
63
+ - `max` — maximum reasoning budget
62
64
 
63
65
  > **Note:** If the current model does not support the requested level, pi clamps to the
64
66
  > nearest supported level (searching both up and down the level hierarchy).
@@ -67,6 +69,7 @@ If no argument is provided, `/thinking` sets the level to `medium`.
67
69
 
68
70
  - Registers the `/thinking` command.
69
71
  - Provides argument completions for all supported levels.
72
+ - Autocompletes `/th...` to `/thinking` without Pi's trailing-space insertion, then presents the level picker.
70
73
  - Shows a `thinking` status item with the current level.
71
74
  - Updates the status item when the thinking level changes.
72
75
  - Validates input and displays an error for unknown levels.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hk_net/pi-thinking-command",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Pi extension that adds a /thinking slash command for changing reasoning level",
5
5
  "type": "module",
6
6
  "private": false,
@@ -26,8 +26,8 @@
26
26
  "README.md"
27
27
  ],
28
28
  "peerDependencies": {
29
- "@earendil-works/pi-coding-agent": ">=0.80.2",
30
- "@earendil-works/pi-tui": ">=0.80.2"
29
+ "@earendil-works/pi-coding-agent": ">=0.80.10",
30
+ "@earendil-works/pi-tui": ">=0.80.10"
31
31
  },
32
32
  "pi": {
33
33
  "extensions": [
@@ -1,9 +1,9 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import type { AutocompleteItem } from "@earendil-works/pi-tui";
3
3
 
4
- type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
4
+ type ThinkingLevel = Parameters<ExtensionAPI["setThinkingLevel"]>[0];
5
5
 
6
- const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"] as const satisfies readonly ThinkingLevel[];
6
+ const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"] as const satisfies readonly ThinkingLevel[];
7
7
 
8
8
  const THINKING_LEVEL_DESCRIPTIONS: Record<ThinkingLevel, string> = {
9
9
  off: "Disable extended thinking",
@@ -11,15 +11,16 @@ const THINKING_LEVEL_DESCRIPTIONS: Record<ThinkingLevel, string> = {
11
11
  low: "Light reasoning",
12
12
  medium: "Balanced default reasoning",
13
13
  high: "More reasoning for harder tasks",
14
- xhigh: "Maximum reasoning budget",
14
+ xhigh: "Very high reasoning budget",
15
+ max: "Maximum reasoning budget",
15
16
  };
16
17
 
17
- function normalizeThinkingLevel(input: string): ThinkingLevel | undefined {
18
+ export function normalizeThinkingLevel(input: string): ThinkingLevel | undefined {
18
19
  const normalized = input.toLowerCase().trim();
19
20
  return THINKING_LEVELS.find((level) => level === normalized);
20
21
  }
21
22
 
22
- function getThinkingLevelCompletions(prefix: string): AutocompleteItem[] | null {
23
+ export function getThinkingLevelCompletions(prefix: string): AutocompleteItem[] | null {
23
24
  const normalizedPrefix = prefix.toLowerCase().trimStart();
24
25
  const matches = THINKING_LEVELS.filter((level) => level.startsWith(normalizedPrefix));
25
26
 
@@ -32,8 +33,71 @@ function getThinkingLevelCompletions(prefix: string): AutocompleteItem[] | null
32
33
  }));
33
34
  }
34
35
 
36
+ export function isThinkingCommandPrefix(value: string): boolean {
37
+ return value.startsWith("/th") && "/thinking".startsWith(value);
38
+ }
39
+
35
40
  export default function thinkingShortcutExtension(pi: ExtensionAPI) {
36
41
  pi.on("session_start", (_event, ctx) => {
42
+ ctx.ui.addAutocompleteProvider((current) => ({
43
+ async getSuggestions(lines, cursorLine, cursorCol, options) {
44
+ const line = lines[cursorLine] ?? "";
45
+ const beforeCursor = line.slice(0, cursorCol);
46
+ if (cursorCol === line.length && isThinkingCommandPrefix(beforeCursor)) {
47
+ if (beforeCursor === "/thinking") {
48
+ return { prefix: "", items: getThinkingLevelCompletions("") ?? [] };
49
+ }
50
+ return {
51
+ prefix: beforeCursor,
52
+ items: [{ value: "thinking", label: "thinking", description: "Set the thinking level" }],
53
+ };
54
+ }
55
+ if (beforeCursor === "/thinking ") {
56
+ return { prefix: "", items: getThinkingLevelCompletions("") ?? [] };
57
+ }
58
+ return current.getSuggestions(lines, cursorLine, cursorCol, options);
59
+ },
60
+
61
+ applyCompletion(lines, cursorLine, cursorCol, item, prefix) {
62
+ const line = lines[cursorLine] ?? "";
63
+ const beforeCursor = line.slice(0, cursorCol);
64
+ if (cursorCol === line.length && isThinkingCommandPrefix(beforeCursor)) {
65
+ if (beforeCursor !== "/thinking") {
66
+ return {
67
+ lines: [...lines.slice(0, cursorLine), "/thinking", ...lines.slice(cursorLine + 1)],
68
+ cursorLine,
69
+ cursorCol: "/thinking".length,
70
+ };
71
+ }
72
+ const nextLine = `/thinking ${item.value}`;
73
+ return {
74
+ lines: [...lines.slice(0, cursorLine), nextLine, ...lines.slice(cursorLine + 1)],
75
+ cursorLine,
76
+ cursorCol: nextLine.length,
77
+ };
78
+ }
79
+ if (beforeCursor === "/thinking " && cursorCol === line.length) {
80
+ const nextLine = `/thinking ${item.value}`;
81
+ return {
82
+ lines: [...lines.slice(0, cursorLine), nextLine, ...lines.slice(cursorLine + 1)],
83
+ cursorLine,
84
+ cursorCol: nextLine.length,
85
+ };
86
+ }
87
+ return current.applyCompletion(lines, cursorLine, cursorCol, item, prefix);
88
+ },
89
+
90
+ shouldTriggerFileCompletion(lines, cursorLine, cursorCol) {
91
+ const line = lines[cursorLine] ?? "";
92
+ const beforeCursor = line.slice(0, cursorCol);
93
+ if (
94
+ (isThinkingCommandPrefix(beforeCursor) || beforeCursor === "/thinking ") &&
95
+ cursorCol === line.length
96
+ ) return false;
97
+ return current.shouldTriggerFileCompletion?.(lines, cursorLine, cursorCol) ?? true;
98
+ },
99
+ }));
100
+
37
101
  ctx.ui.setStatus("thinking", `level: ${pi.getThinkingLevel()}`);
38
102
 
39
103
  ctx.ui.addAutocompleteProvider((current) => ({
@@ -69,7 +133,7 @@ export default function thinkingShortcutExtension(pi: ExtensionAPI) {
69
133
  });
70
134
 
71
135
  pi.registerCommand("thinking", {
72
- description: "Set the thinking level. Usage: /thinking [off|minimal|low|medium|high|xhigh]",
136
+ description: "Set the thinking level. Usage: /thinking [off|minimal|low|medium|high|xhigh|max]",
73
137
  getArgumentCompletions: getThinkingLevelCompletions,
74
138
  handler: async (args, ctx) => {
75
139
  const input = args?.trim() || "medium";