@zigai/pi-mode 0.4.0 → 0.4.1

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,51 +1,12 @@
1
1
  # Pi Mode
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/@zigai/pi-mode.svg?color=blue)](https://www.npmjs.com/package/@zigai/pi-mode)
4
- [![npm downloads](https://img.shields.io/npm/dm/@zigai/pi-mode.svg)](https://www.npmjs.com/package/@zigai/pi-mode)
5
- [![license](https://img.shields.io/npm/l/@zigai/pi-mode.svg)](../../LICENSE)
6
-
7
- This Pi extension adds prompt modes for model and thinking-level switching.
8
-
9
- ## Install
3
+ This package has been renamed to `@zigai/pi-model-modes`.
10
4
 
11
5
  ```sh
12
- pi install npm:@zigai/pi-mode
6
+ pi install npm:@zigai/pi-model-modes
13
7
  ```
14
8
 
15
- ## Features
16
-
17
- - Adds `/mode` for selecting and configuring prompt modes.
18
- - Adds `Ctrl+Shift+M` to select a mode.
19
- - Adds `Ctrl+Space` to cycle modes.
20
- - Can show the current mode in the prompt editor border when enabled.
21
- - Colors the prompt editor border from the active mode, with an opt-in setting for thinking-derived border colors.
22
-
23
- Modes can store a provider, model, thinking level, and optional color. By default, Pi Mode hides Pi's transient `Thinking level: …` status message because the active thinking level is already visible in the footer.
24
-
25
- ## Configuration
26
-
27
- Configure global settings at `~/.pi/agent/pi-mode/config.json`.
28
-
29
- | Option | Type | Default | Description |
30
- | ----------------------------- | --------- | ----------- | -------------------------------------------------------------------------- |
31
- | `version` | `number` | `1` | Config format version. |
32
- | `currentMode` | `string` | `"default"` | Mode selected at startup. |
33
- | `modeShowName` | `boolean` | `false` | Shows the current mode name in the prompt editor border. |
34
- | `modeUseThinkingBorderColors` | `boolean` | `false` | Uses thinking-derived border colors when a mode has no explicit color. |
35
- | `modeShowThinkingLevelStatus` | `boolean` | `false` | Shows Pi's transient thinking-level status message. |
36
- | `modes` | `object` | `{}` | Named modes with optional `provider`, `modelId`, `thinkingLevel`, `color`. |
37
-
38
- ```json
39
- {
40
- "$schema": "./config.schema.json",
41
- "version": 1,
42
- "currentMode": "default",
43
- "modeShowName": false,
44
- "modeUseThinkingBorderColors": false,
45
- "modeShowThinkingLevelStatus": false,
46
- "modes": {}
47
- }
48
- ```
9
+ This old package name remains as a compatibility shim.
49
10
 
50
11
  ## License
51
12
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zigai/pi-mode",
3
- "version": "0.4.0",
4
- "description": "Pi package that adds prompt modes for model and thinking-level switching.",
3
+ "version": "0.4.1",
4
+ "description": "Compatibility shim for the renamed @zigai/pi-model-modes package.",
5
5
  "keywords": [
6
6
  "mode",
7
7
  "pi",
@@ -31,12 +31,7 @@
31
31
  "access": "public"
32
32
  },
33
33
  "dependencies": {
34
- "typebox": "^1.1.38"
35
- },
36
- "peerDependencies": {
37
- "@earendil-works/pi-agent-core": "*",
38
- "@earendil-works/pi-ai": "*",
39
- "@earendil-works/pi-coding-agent": "*"
34
+ "@zigai/pi-model-modes": "^0.4.0"
40
35
  },
41
36
  "pi": {
42
37
  "extensions": [
package/src/index.ts CHANGED
@@ -1,49 +1 @@
1
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
- import { applyModeEditor } from "./editor.ts";
3
- import {
4
- cycleMode,
5
- handleModeCommand,
6
- handleModelSelect,
7
- handleSessionActivated,
8
- selectModeUI,
9
- } from "./mode-state.ts";
10
- import { setSettingsContext } from "./settings.ts";
11
- import { applyThinkingLevelStatusPatch } from "./status.ts";
12
-
13
- export default function (pi: ExtensionAPI) {
14
- void applyThinkingLevelStatusPatch();
15
-
16
- pi.registerCommand("mode", {
17
- description: "Select prompt mode",
18
- handler: async (args, ctx) => {
19
- await handleModeCommand(pi, ctx, args);
20
- },
21
- });
22
-
23
- pi.registerShortcut("ctrl+shift+m", {
24
- description: "Select prompt mode",
25
- handler: async (ctx) => {
26
- await selectModeUI(pi, ctx);
27
- },
28
- });
29
-
30
- pi.registerShortcut("ctrl+space", {
31
- description: "Cycle prompt mode",
32
- handler: async (ctx) => {
33
- await cycleMode(pi, ctx, 1);
34
- },
35
- });
36
-
37
- pi.on("session_start", async (_event, ctx) => {
38
- setSettingsContext(ctx);
39
- // Install the editor wrapper before loading mode files so startup renders use
40
- // the configured border color immediately instead of briefly showing Pi's
41
- // thinking-level border color.
42
- applyModeEditor(pi, ctx);
43
- await handleSessionActivated(pi, ctx);
44
- });
45
-
46
- pi.on("model_select", async (event, ctx) => {
47
- await handleModelSelect(pi, ctx, event);
48
- });
49
- }
1
+ export { default } from "@zigai/pi-model-modes/src/index.ts";
@@ -1,29 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://raw.githubusercontent.com/zigai/pi-tweaks/main/packages/pi-mode/config.schema.json",
4
- "title": "Pi mode config",
5
- "type": "object",
6
- "additionalProperties": false,
7
- "properties": {
8
- "$schema": { "type": "string" },
9
- "version": { "type": "number", "default": 1 },
10
- "currentMode": { "type": "string", "default": "default" },
11
- "modeShowName": { "type": "boolean", "default": false },
12
- "modeUseThinkingBorderColors": { "type": "boolean", "default": false },
13
- "modeShowThinkingLevelStatus": { "type": "boolean", "default": false },
14
- "modes": {
15
- "type": "object",
16
- "additionalProperties": {
17
- "type": "object",
18
- "additionalProperties": false,
19
- "properties": {
20
- "provider": { "type": "string" },
21
- "modelId": { "type": "string" },
22
- "thinkingLevel": {},
23
- "color": { "type": "string" }
24
- }
25
- },
26
- "default": {}
27
- }
28
- }
29
- }
package/src/constants.ts DELETED
@@ -1,24 +0,0 @@
1
- import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
2
-
3
- export const DEFAULT_MODE_ORDER = ["default"] as const;
4
- export const CUSTOM_MODE_NAME = "custom" as const;
5
-
6
- export const MODE_UI_CONFIGURE = "Configure modes…";
7
- export const MODE_UI_ADD = "Add mode…";
8
- export const MODE_UI_SHOW_NAME_ON = "Show mode name: on";
9
- export const MODE_UI_SHOW_NAME_OFF = "Show mode name: off";
10
- export const MODE_UI_THINKING_COLORS_ON = "Thinking border colors: on";
11
- export const MODE_UI_THINKING_COLORS_OFF = "Thinking border colors: off";
12
- export const MODE_UI_THINKING_STATUS_ON = "Thinking level status: on";
13
- export const MODE_UI_THINKING_STATUS_OFF = "Thinking level status: off";
14
- export const MODE_UI_BACK = "Back";
15
-
16
- export const ALL_THINKING_LEVELS: ThinkingLevel[] = [
17
- "off",
18
- "minimal",
19
- "low",
20
- "medium",
21
- "high",
22
- "xhigh",
23
- ];
24
- export const THINKING_UNSET_LABEL = "(don't change)";
package/src/editor.ts DELETED
@@ -1,101 +0,0 @@
1
- import {
2
- CustomEditor,
3
- type ExtensionAPI,
4
- type ExtensionContext,
5
- } from "@earendil-works/pi-coding-agent";
6
- import { getCurrentMode, getModeBorderColor, setRequestEditorRender } from "./mode-state.ts";
7
- import { shouldShowModeName } from "./settings.ts";
8
-
9
- const ANSI_SGR = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g");
10
- const stripAnsi = (value: string) => value.replace(ANSI_SGR, "");
11
- const MODE_FACTORY_BASE = Symbol.for("zigai.pi-mode.editor-factory-base");
12
-
13
- type EditorFactory = NonNullable<ReturnType<ExtensionContext["ui"]["getEditorComponent"]>>;
14
-
15
- type EditorLike = CustomEditor & {
16
- borderColor: (text: string) => string;
17
- getText(): string;
18
- render(width: number): string[];
19
- };
20
-
21
- type WrappedEditorFactory = EditorFactory & {
22
- [MODE_FACTORY_BASE]?: EditorFactory | undefined;
23
- };
24
-
25
- function modeLabelLine(lines: string[], width: number, editor: EditorLike): string[] {
26
- if (!shouldShowModeName()) return lines;
27
-
28
- const mode = getCurrentMode();
29
- if (mode.length === 0) return lines;
30
-
31
- const topPlain = stripAnsi(lines[0] ?? "");
32
- const scrollPrefixMatch = /^(─── ↑ \d+ more )/.exec(topPlain);
33
- const prefix = scrollPrefixMatch?.[1] ?? "──";
34
-
35
- let label = mode;
36
- let labelLeftSpace = " ";
37
- if (prefix.endsWith(" ")) {
38
- labelLeftSpace = "";
39
- }
40
- const labelRightSpace = " ";
41
- const minRightBorder = 1;
42
- const maxLabelLen = Math.max(
43
- 0,
44
- width - prefix.length - labelLeftSpace.length - labelRightSpace.length - minRightBorder,
45
- );
46
- if (maxLabelLen <= 0) return lines;
47
- if (label.length > maxLabelLen) label = label.slice(0, maxLabelLen);
48
-
49
- const labelChunk = `${labelLeftSpace}${label}${labelRightSpace}`;
50
- const remaining = width - prefix.length - labelChunk.length;
51
- if (remaining < 0) return lines;
52
-
53
- const right = "─".repeat(Math.max(0, remaining));
54
- const borderColor = editor.borderColor;
55
- lines[0] = borderColor(prefix) + borderColor(labelChunk) + borderColor(right);
56
- return lines;
57
- }
58
-
59
- function enhanceEditor(
60
- editor: EditorLike,
61
- pi: ExtensionAPI,
62
- ctx: ExtensionContext,
63
- requestRender: () => void,
64
- ): EditorLike {
65
- const originalRender = editor.render.bind(editor);
66
- const defaultBorderColor = editor.borderColor;
67
- editor.render = (width: number) => modeLabelLine(originalRender(width), width, editor);
68
-
69
- const borderColor = (text: string) => {
70
- const isBashMode = editor.getText().trimStart().startsWith("!");
71
- if (isBashMode) {
72
- return ctx.ui.theme.getBashModeBorderColor()(text);
73
- }
74
- return getModeBorderColor(ctx, pi, getCurrentMode(), defaultBorderColor)(text);
75
- };
76
-
77
- Object.defineProperty(editor, "borderColor", {
78
- get: () => borderColor,
79
- set: () => {},
80
- configurable: true,
81
- enumerable: true,
82
- });
83
-
84
- setRequestEditorRender(requestRender);
85
- return editor;
86
- }
87
-
88
- export function applyModeEditor(pi: ExtensionAPI, ctx: ExtensionContext): void {
89
- if (!ctx.hasUI) return;
90
-
91
- const existing = ctx.ui.getEditorComponent() as WrappedEditorFactory | undefined;
92
- const baseFactory = existing?.[MODE_FACTORY_BASE] ?? existing;
93
- const factory = ((tui, theme, keybindings) => {
94
- const editor = (baseFactory?.(tui, theme, keybindings) ??
95
- new CustomEditor(tui, theme, keybindings)) as EditorLike;
96
- return enhanceEditor(editor, pi, ctx, () => tui.requestRender());
97
- }) as WrappedEditorFactory;
98
- factory[MODE_FACTORY_BASE] = baseFactory;
99
-
100
- ctx.ui.setEditorComponent(factory);
101
- }