pi-free 2.2.6 → 2.2.8

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.
@@ -1,119 +1,119 @@
1
- /**
2
- * Qoder Provider Extension
3
- *
4
- * Registers the Qoder provider with Pi, providing free access to top-tier
5
- * LLM models (DeepSeek V4 Pro/Flash, Qwen3.7 Plus/Max, GLM 5.1, Kimi K2.6,
6
- * MiniMax M3) through Qoder's OpenAI-compatible API.
7
- *
8
- * Qoder uses a custom authentication protocol (PAT exchange + COSY signing)
9
- * and a credits-based pricing model:
10
- * - Community Edition (free): basic models with daily message limits
11
- * - Pro / Pro+ / Ultra (paid): premium models via monthly credits
12
- *
13
- * Usage:
14
- * Install pi-free, then run /login qoder to authenticate
15
- * (PAT paste or browser OAuth)
16
- * /toggle-qoder switches between basic (free-tier) and all models
17
- *
18
- * Environment variables:
19
- * QODER_PERSONAL_ACCESS_TOKEN — PAT for headless auth (optional)
20
- * QODER_PAT — Alias for above
21
- */
22
-
23
- import type { Api, OAuthCredentials } from "@earendil-works/pi-ai";
24
- import type {
25
- ExtensionAPI,
26
- ProviderModelConfig,
27
- } from "@earendil-works/pi-coding-agent";
28
- import { BASE_URL_QODER, PROVIDER_QODER } from "../../constants.ts";
29
- import { getProviderShowPaid } from "../../config.ts";
30
- import {
31
- getCachedModels,
32
- isBasicModel,
33
- type QoderModelConfig,
34
- } from "./models.ts";
35
- import { getCachedCredentials, loginQoder, refreshQoderToken } from "./auth.ts";
36
- import { streamQoder } from "./stream.ts";
37
- import { enhanceWithCI } from "../../provider-helper.ts";
38
- import { registerWithGlobalToggle } from "../../lib/registry.ts";
39
- import { createToggleState } from "../../lib/toggle-state.ts";
40
-
41
- // =============================================================================
42
- // Extension Entry Point
43
- // =============================================================================
44
-
45
- export default async function qoderProvider(pi: ExtensionAPI) {
46
- const logger = (await import("../../lib/logger.ts")).createLogger("qoder");
47
-
48
- // Initial model fetch
49
- const allModels: QoderModelConfig[] = getCachedModels();
50
- const basicModels: QoderModelConfig[] = allModels.filter(isBasicModel);
51
- const stored = { free: basicModels, all: allModels };
52
-
53
- const toggleState = createToggleState({
54
- providerId: PROVIDER_QODER,
55
- initialShowPaid: getProviderShowPaid(PROVIDER_QODER),
56
- initialModels: stored,
57
- });
58
-
59
- // ── OAuth config (defined before reRegister so it's always available) ──
60
- const oauthConfig = {
61
- name: "Qoder (Browser OAuth / PAT)",
62
- login: async (callbacks: any): Promise<OAuthCredentials> => {
63
- return loginQoder(callbacks);
64
- },
65
- refreshToken: refreshQoderToken,
66
- getApiKey: (cred: OAuthCredentials) => cred.access,
67
- };
68
-
69
- // Re-register function — called by toggle, session refresh, login
70
- const reRegister = (models: ProviderModelConfig[]) => {
71
- const enhanced = enhanceWithCI(models, PROVIDER_QODER);
72
- pi.registerProvider(PROVIDER_QODER, {
73
- baseUrl: BASE_URL_QODER,
74
- api: "qoder-api" as Api,
75
- models: enhanced,
76
- oauth: oauthConfig,
77
- streamSimple: streamQoder,
78
- });
79
- };
80
-
81
- // Register with global toggle system so it participates in /toggle-free
82
- registerWithGlobalToggle(PROVIDER_QODER, stored, (m) => reRegister(m), false);
83
-
84
- // Per-provider toggle: /toggle-qoder (basic free-tier ↔ all models)
85
- pi.registerCommand("toggle-qoder", {
86
- description: "Toggle between basic (free-tier) and all Qoder models",
87
- handler: async (_args, ctx) => {
88
- try {
89
- const applied = toggleState.toggle(reRegister);
90
- const basicCount = stored.free.length;
91
- const premiumCount = stored.all.length - basicCount;
92
- if (applied.mode === "all") {
93
- ctx.ui.notify(
94
- `qoder: showing all ${stored.all.length} models (${basicCount} basic, ${premiumCount} premium)`,
95
- "info",
96
- );
97
- } else {
98
- ctx.ui.notify(
99
- `qoder: showing ${stored.free.length} basic (free-tier) models`,
100
- "info",
101
- );
102
- }
103
- } catch (err) {
104
- logger.error("[qoder] toggle failed", {
105
- error: err instanceof Error ? err.message : String(err),
106
- });
107
- ctx.ui.notify("qoder: toggle failed", "error");
108
- }
109
- },
110
- });
111
-
112
- // Initial registration respects the configured show-paid mode.
113
- toggleState.applyCurrent(reRegister);
114
-
115
- logger.info(`[qoder] Provider registered with ${allModels.length} models`);
116
- }
117
-
118
- // Re-export key symbols for testing
119
- export { loginQoder, refreshQoderToken, getCachedCredentials, streamQoder };
1
+ /**
2
+ * Qoder Provider Extension
3
+ *
4
+ * Registers the Qoder provider with Pi, providing free access to top-tier
5
+ * LLM models (DeepSeek V4 Pro/Flash, Qwen3.7 Plus/Max, GLM 5.1, Kimi K2.6,
6
+ * MiniMax M3) through Qoder's OpenAI-compatible API.
7
+ *
8
+ * Qoder uses a custom authentication protocol (PAT exchange + COSY signing)
9
+ * and a credits-based pricing model:
10
+ * - Community Edition (free): basic models with daily message limits
11
+ * - Pro / Pro+ / Ultra (paid): premium models via monthly credits
12
+ *
13
+ * Usage:
14
+ * Install pi-free, then run /login qoder to authenticate
15
+ * (PAT paste or browser OAuth)
16
+ * /toggle-qoder switches between basic (free-tier) and all models
17
+ *
18
+ * Environment variables:
19
+ * QODER_PERSONAL_ACCESS_TOKEN — PAT for headless auth (optional)
20
+ * QODER_PAT — Alias for above
21
+ */
22
+
23
+ import type { Api, OAuthCredentials } from "@earendil-works/pi-ai/compat";
24
+ import type {
25
+ ExtensionAPI,
26
+ ProviderModelConfig,
27
+ } from "@earendil-works/pi-coding-agent";
28
+ import { BASE_URL_QODER, PROVIDER_QODER } from "../../constants.ts";
29
+ import { getProviderShowPaid } from "../../config.ts";
30
+ import {
31
+ getCachedModels,
32
+ isBasicModel,
33
+ type QoderModelConfig,
34
+ } from "./models.ts";
35
+ import { getCachedCredentials, loginQoder, refreshQoderToken } from "./auth.ts";
36
+ import { streamQoder } from "./stream.ts";
37
+ import { enhanceWithCI } from "../../provider-helper.ts";
38
+ import { registerWithGlobalToggle } from "../../lib/registry.ts";
39
+ import { createToggleState } from "../../lib/toggle-state.ts";
40
+
41
+ // =============================================================================
42
+ // Extension Entry Point
43
+ // =============================================================================
44
+
45
+ export default async function qoderProvider(pi: ExtensionAPI) {
46
+ const logger = (await import("../../lib/logger.ts")).createLogger("qoder");
47
+
48
+ // Initial model fetch
49
+ const allModels: QoderModelConfig[] = getCachedModels();
50
+ const basicModels: QoderModelConfig[] = allModels.filter(isBasicModel);
51
+ const stored = { free: basicModels, all: allModels };
52
+
53
+ const toggleState = createToggleState({
54
+ providerId: PROVIDER_QODER,
55
+ initialShowPaid: getProviderShowPaid(PROVIDER_QODER),
56
+ initialModels: stored,
57
+ });
58
+
59
+ // ── OAuth config (defined before reRegister so it's always available) ──
60
+ const oauthConfig = {
61
+ name: "Qoder (Browser OAuth / PAT)",
62
+ login: async (callbacks: any): Promise<OAuthCredentials> => {
63
+ return loginQoder(callbacks);
64
+ },
65
+ refreshToken: refreshQoderToken,
66
+ getApiKey: (cred: OAuthCredentials) => cred.access,
67
+ };
68
+
69
+ // Re-register function — called by toggle, session refresh, login
70
+ const reRegister = (models: ProviderModelConfig[]) => {
71
+ const enhanced = enhanceWithCI(models, PROVIDER_QODER);
72
+ pi.registerProvider(PROVIDER_QODER, {
73
+ baseUrl: BASE_URL_QODER,
74
+ api: "qoder-api" as Api,
75
+ models: enhanced,
76
+ oauth: oauthConfig,
77
+ streamSimple: streamQoder,
78
+ });
79
+ };
80
+
81
+ // Register with global toggle system so it participates in /toggle-free
82
+ registerWithGlobalToggle(PROVIDER_QODER, stored, (m) => reRegister(m), false);
83
+
84
+ // Per-provider toggle: /toggle-qoder (basic free-tier ↔ all models)
85
+ pi.registerCommand("toggle-qoder", {
86
+ description: "Toggle between basic (free-tier) and all Qoder models",
87
+ handler: async (_args, ctx) => {
88
+ try {
89
+ const applied = toggleState.toggle(reRegister);
90
+ const basicCount = stored.free.length;
91
+ const premiumCount = stored.all.length - basicCount;
92
+ if (applied.mode === "all") {
93
+ ctx.ui.notify(
94
+ `qoder: showing all ${stored.all.length} models (${basicCount} basic, ${premiumCount} premium)`,
95
+ "info",
96
+ );
97
+ } else {
98
+ ctx.ui.notify(
99
+ `qoder: showing ${stored.free.length} basic (free-tier) models`,
100
+ "info",
101
+ );
102
+ }
103
+ } catch (err) {
104
+ logger.error("[qoder] toggle failed", {
105
+ error: err instanceof Error ? err.message : String(err),
106
+ });
107
+ ctx.ui.notify("qoder: toggle failed", "error");
108
+ }
109
+ },
110
+ });
111
+
112
+ // Initial registration respects the configured show-paid mode.
113
+ toggleState.applyCurrent(reRegister);
114
+
115
+ logger.info(`[qoder] Provider registered with ${allModels.length} models`);
116
+ }
117
+
118
+ // Re-export key symbols for testing
119
+ export { loginQoder, refreshQoderToken, getCachedCredentials, streamQoder };