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.
- package/CHANGELOG.md +31 -4
- package/README.md +3 -2
- package/config.ts +815 -803
- package/constants.ts +113 -121
- package/index.ts +6 -7
- package/lib/built-in-toggle.ts +426 -426
- package/lib/model-detection.ts +1 -1
- package/package.json +74 -74
- package/provider-helper.ts +29 -7
- package/providers/anyapi/anyapi.ts +270 -0
- package/providers/cline/cline-auth.ts +473 -473
- package/providers/cline/cline-xml-bridge.ts +1506 -1506
- package/providers/cline/cline.ts +205 -205
- package/providers/dynamic-built-in/index.ts +718 -718
- package/providers/kilo/kilo-auth.ts +152 -155
- package/providers/kilo/kilo.ts +14 -13
- package/providers/opencode-session.ts +514 -463
- package/providers/qoder/auth.ts +548 -548
- package/providers/qoder/qoder.ts +119 -119
- package/providers/qoder/stream.ts +585 -585
- package/providers/qoder/thinking-parser.ts +251 -251
- package/providers/qoder/transform.ts +192 -192
- package/providers/tokenrouter/tokenrouter.ts +636 -637
- package/providers/qwen/qwen-auth.ts +0 -416
- package/providers/qwen/qwen-models.ts +0 -101
- package/providers/qwen/qwen.ts +0 -200
package/providers/qoder/qoder.ts
CHANGED
|
@@ -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 };
|