pi-dashscope 1.0.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 (3) hide show
  1. package/README.md +69 -0
  2. package/index.ts +174 -0
  3. package/package.json +25 -0
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # pi-dashscope
2
+
3
+ Alibaba DashScope (ModelStudio) provider for [pi.dev](https://pi.dev) — routes Qwen3 / GLM-4 / Kimi models through the OpenAI-compatible coding endpoint.
4
+
5
+ ## Models
6
+
7
+ | ID | Name | Context | Output | Thinking |
8
+ |---|---|---|---|---|
9
+ | `qwen3.5-plus` | Qwen 3.5 Plus | 960K | 64K | ✅ |
10
+ | `qwen3-max-2026-01-23` | Qwen3 Max (2026-01-23) | 252K | 32K | ✅ |
11
+ | `qwen3-coder-plus` | Qwen3 Coder Plus | 975K | 64K | ❌ |
12
+ | `qwen3-coder-next` | Qwen3 Coder Next | 200K | 64K | ❌ |
13
+ | `glm-4.7` | GLM-4.7 | 166K | 16K | ✅ |
14
+ | `kimi-k2.5` | Kimi K2.5 | 252K | 32K | ✅ |
15
+
16
+ ## Install Pi
17
+
18
+ ### Prerequisites
19
+
20
+ ```
21
+ npm i @mariozechner/pi-coding-agent
22
+ ```
23
+
24
+ ### Installation
25
+
26
+ ```bash
27
+ # Install using npm package
28
+ pi install npm:pi-dashscope
29
+ ```
30
+
31
+ ### Verify Installation
32
+
33
+ After installation, verify it's working:
34
+
35
+ ```bash
36
+ # List available models
37
+ pi model list
38
+
39
+ # Check if dashscope models appear:
40
+ # dashscope/qwen3.5-plus
41
+ # dashscope/qwen3-max-2026-01-23
42
+ # etc.
43
+ ```
44
+
45
+ ## Configuration
46
+
47
+ ### Interactive setup (recommended)
48
+
49
+ After installing, run the configure command inside pi:
50
+
51
+ ```
52
+ /dashscope-configure
53
+ ```
54
+
55
+ It will prompt you for your API key and save it to `~/.pi/agent/dashscope.json`. The key is applied immediately — no restart needed.
56
+
57
+ ### Environment variable
58
+
59
+ Set `DASHSCOPE_API_KEY` in your environment (takes precedence over the saved config):
60
+
61
+ ```bash
62
+ export DASHSCOPE_API_KEY=sk-sp-...
63
+ ```
64
+
65
+ Get your API key from the [Model Studio console](https://modelstudio.console.alibabacloud.com).
66
+
67
+ ## Usage
68
+
69
+ After installing, use `/model` or `Ctrl+L` in pi to select a `dashscope/...` model. Use `Ctrl+T` to toggle thinking for models that support it.
package/index.ts ADDED
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Alibaba DashScope (ModelStudio) provider for pi.dev
3
+ *
4
+ * Registers the DashScope OpenAI-compatible coding endpoint with all
5
+ * configured Qwen3 / GLM-4 / Kimi models.
6
+ *
7
+ * Usage:
8
+ * # Install from local path
9
+ * pi install ./pi-dashscope
10
+ *
11
+ * # Or test in-place without installing
12
+ * pi -e ./pi-dashscope
13
+ *
14
+ * # Configure your API key interactively
15
+ * /dashscope-configure
16
+ *
17
+ * # Or set via environment variable (takes precedence over saved config)
18
+ * DASHSCOPE_API_KEY=sk-sp-... pi
19
+ *
20
+ * # Then switch models with /model or Ctrl+L
21
+ * # Look for "dashscope/..." entries
22
+ */
23
+
24
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
25
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
26
+ import { homedir } from "node:os";
27
+ import { join } from "node:path";
28
+
29
+ const CONFIG_FILE = join(homedir(), ".pi", "agent", "dashscope.json");
30
+
31
+ function readStoredKey(): string | undefined {
32
+ try {
33
+ if (existsSync(CONFIG_FILE)) {
34
+ const data = JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
35
+ return typeof data.apiKey === "string" ? data.apiKey : undefined;
36
+ }
37
+ } catch {
38
+ // ignore malformed config
39
+ }
40
+ return undefined;
41
+ }
42
+
43
+ function saveKey(apiKey: string): void {
44
+ const dir = join(homedir(), ".pi", "agent");
45
+ mkdirSync(dir, { recursive: true });
46
+ writeFileSync(CONFIG_FILE, JSON.stringify({ apiKey }, null, 2), "utf-8");
47
+ }
48
+
49
+ const DASHSCOPE_MODELS = [
50
+ // ── Qwen 3.5 Plus ──────────────────────────────────────────────────────
51
+ // Extended thinking enabled | 960K context | 64K output
52
+ {
53
+ id: "qwen3.5-plus",
54
+ name: "Qwen 3.5 Plus",
55
+ reasoning: true,
56
+ input: ["text"] as ["text"],
57
+ contextWindow: 983616,
58
+ maxTokens: 65536,
59
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
60
+ compat: { thinkingFormat: "qwen" },
61
+ },
62
+ // ── Qwen3 Max 2026-01-23 ───────────────────────────────────────────────
63
+ // Extended thinking enabled | 252K context | 32K output
64
+ {
65
+ id: "qwen3-max-2026-01-23",
66
+ name: "Qwen3 Max (2026-01-23)",
67
+ reasoning: true,
68
+ input: ["text"] as ["text"],
69
+ contextWindow: 258048,
70
+ maxTokens: 32768,
71
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
72
+ compat: { thinkingFormat: "qwen" },
73
+ },
74
+ // ── Qwen3 Coder Plus ───────────────────────────────────────────────────
75
+ // No thinking | 975K context | 64K output
76
+ {
77
+ id: "qwen3-coder-plus",
78
+ name: "Qwen3 Coder Plus",
79
+ reasoning: false,
80
+ input: ["text"] as ["text"],
81
+ contextWindow: 997952,
82
+ maxTokens: 65536,
83
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
84
+ },
85
+ // ── Qwen3 Coder Next ───────────────────────────────────────────────────
86
+ // No thinking | 200K context | 64K output
87
+ {
88
+ id: "qwen3-coder-next",
89
+ name: "Qwen3 Coder Next",
90
+ reasoning: false,
91
+ input: ["text"] as ["text"],
92
+ contextWindow: 204800,
93
+ maxTokens: 65536,
94
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
95
+ },
96
+ // ── GLM-4.7 ────────────────────────────────────────────────────────────
97
+ // Extended thinking enabled | 166K context | 16K output
98
+ {
99
+ id: "glm-4.7",
100
+ name: "GLM-4.7",
101
+ reasoning: true,
102
+ input: ["text"] as ["text"],
103
+ contextWindow: 169984,
104
+ maxTokens: 16384,
105
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
106
+ compat: { thinkingFormat: "qwen" },
107
+ },
108
+ // ── Kimi K2.5 ─────────────────────────────────────────────────────────
109
+ // Extended thinking enabled | 252K context | 32K output
110
+ {
111
+ id: "kimi-k2.5",
112
+ name: "Kimi K2.5",
113
+ reasoning: true,
114
+ input: ["text"] as ["text"],
115
+ contextWindow: 258048,
116
+ maxTokens: 32768,
117
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
118
+ compat: { thinkingFormat: "zai" },
119
+ },
120
+ ];
121
+
122
+ const DASHSCOPE_BASE_URL = "https://coding-intl.dashscope.aliyuncs.com/v1";
123
+
124
+ export default function (pi: ExtensionAPI) {
125
+ // Resolve API key: env var takes precedence, then saved config, then env var name
126
+ // (pi resolves env var name strings automatically, so "BAILIAN_API_KEY" is a
127
+ // valid apiKey value that tells pi to look up process.env.BAILIAN_API_KEY).
128
+ const resolvedKey = process.env.DASHSCOPE_API_KEY ?? readStoredKey() ?? "DASHSCOPE_API_KEY";
129
+
130
+ pi.registerProvider("dashscope", {
131
+ baseUrl: DASHSCOPE_BASE_URL,
132
+ apiKey: resolvedKey,
133
+ api: "openai-completions",
134
+ models: DASHSCOPE_MODELS,
135
+ });
136
+
137
+ pi.on("session_start", async (_event, ctx) => {
138
+ const hasKey = process.env.DASHSCOPE_API_KEY !== undefined || readStoredKey() !== undefined;
139
+ if (!hasKey) {
140
+ ctx.ui.notify(
141
+ "DashScope: No API key configured. Run /dashscope-configure to set up.",
142
+ "warning",
143
+ );
144
+ }
145
+ });
146
+
147
+ pi.registerCommand("dashscope-configure", {
148
+ description: "Configure your Alibaba DashScope API key",
149
+ handler: async (_args, ctx) => {
150
+ const apiKey = await ctx.ui.input(
151
+ "DashScope API key (from https://modelstudio.console.alibabacloud.com):",
152
+ "sk-sp-...",
153
+ );
154
+
155
+ if (!apiKey || apiKey.trim() === "") {
156
+ ctx.ui.notify("No API key provided. Configuration cancelled.", "warning");
157
+ return;
158
+ }
159
+
160
+ const trimmedKey = apiKey.trim();
161
+ saveKey(trimmedKey);
162
+
163
+ // Re-register provider immediately with the new key — no reload needed.
164
+ pi.registerProvider("dashscope", {
165
+ baseUrl: DASHSCOPE_BASE_URL,
166
+ apiKey: trimmedKey,
167
+ api: "openai-completions",
168
+ models: DASHSCOPE_MODELS,
169
+ });
170
+
171
+ ctx.ui.notify("DashScope API key saved and applied successfully!", "success");
172
+ },
173
+ });
174
+ }
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "pi-dashscope",
3
+ "version": "1.0.0",
4
+ "description": "Alibaba DashScope (ModelStudio) provider for pi.dev — Qwen3, GLM-4, Kimi via OpenAI-compatible coding API",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "mkurman",
8
+ "files": [
9
+ "index.ts",
10
+ "README.md"
11
+ ],
12
+ "keywords": [
13
+ "pi-package"
14
+ ],
15
+ "pi": {
16
+ "extensions": [
17
+ "./index.ts"
18
+ ]
19
+ },
20
+ "scripts": {
21
+ "clean": "echo 'nothing to clean'",
22
+ "build": "echo 'nothing to build'",
23
+ "check": "echo 'nothing to check'"
24
+ }
25
+ }