@xiaoso/dsh-tool-plus 0.1.0-beta.3 → 0.1.0-beta.4

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 (155) hide show
  1. package/lib/abort-D1_Z5Ut5.mjs +51 -0
  2. package/lib/abort-dIkZBV7Q.mjs +51 -0
  3. package/lib/amazon-bedrock-B0nxT06F.mjs +917 -0
  4. package/lib/amazon-bedrock-WQhvjHYu.mjs +917 -0
  5. package/lib/anthropic-CJCauvYz.mjs +3115 -0
  6. package/lib/anthropic-CZghe_9U.mjs +3115 -0
  7. package/lib/anthropic-sCMH7JID.mjs +262 -0
  8. package/lib/anthropic-tTntD8BD.mjs +262 -0
  9. package/lib/api-key-login-BzqNdM2y.mjs +157 -0
  10. package/lib/api-key-login-CWVwvHT1.mjs +157 -0
  11. package/lib/aws-credentials-CXryMobh.mjs +867 -0
  12. package/lib/aws-credentials-ChG79ey-.mjs +867 -0
  13. package/lib/azure-openai-responses-Cgmc-rbL.mjs +274 -0
  14. package/lib/azure-openai-responses-DuukbD0F.mjs +274 -0
  15. package/lib/bun-shim.mjs +81 -6
  16. package/lib/bundled-references-Cavaffah.mjs +55 -0
  17. package/lib/bundled-references-sLN0YdXU.mjs +55 -0
  18. package/lib/callback-server-CQ5Jo8F-.mjs +398 -0
  19. package/lib/callback-server-DDSrZ6l_.mjs +398 -0
  20. package/lib/client.js +1 -1
  21. package/lib/cursor-B3zg7EHj.mjs +273 -0
  22. package/lib/cursor-B6TUEmgP.mjs +135 -0
  23. package/lib/cursor-D8gvtTL3.mjs +135 -0
  24. package/lib/cursor-DkSX2h3H.mjs +5441 -0
  25. package/lib/cursor-aJrXeYCb.mjs +273 -0
  26. package/lib/cursor-mJQwUKXK.mjs +5441 -0
  27. package/lib/device-code-DBo3B5nh.mjs +51 -0
  28. package/lib/device-code-DIb0FU-H.mjs +51 -0
  29. package/lib/devin-BHZZyMhO.mjs +95 -0
  30. package/lib/devin-BK7DHeca.mjs +114 -0
  31. package/lib/devin-CfMp3cXS.mjs +95 -0
  32. package/lib/devin-D9zR5B_R.mjs +542 -0
  33. package/lib/devin-Q1yem3lp.mjs +114 -0
  34. package/lib/devin-vNZTNUON.mjs +542 -0
  35. package/lib/error-Dd8DIqs-.mjs +1449 -0
  36. package/lib/error-yCSG0mGC.mjs +1449 -0
  37. package/lib/event-stream-BbFZJy-z.mjs +151 -0
  38. package/lib/event-stream-loUa0s1T.mjs +151 -0
  39. package/lib/fs-promises-shim-Bx0fpxuk.mjs +57 -0
  40. package/lib/github-copilot-B1yiyVRh.mjs +104 -0
  41. package/lib/github-copilot-BWT3eAOF.mjs +208 -0
  42. package/lib/github-copilot-CYkjeTi3.mjs +208 -0
  43. package/lib/github-copilot-jscUZ8Hf.mjs +104 -0
  44. package/lib/gitlab-duo-CM7Ref1H.mjs +155 -0
  45. package/lib/gitlab-duo-gubO4FNw.mjs +155 -0
  46. package/lib/gitlab-duo-workflow-BGAF6JDw.mjs +91 -0
  47. package/lib/gitlab-duo-workflow-D78tdn8E.mjs +91 -0
  48. package/lib/google-BS4T25Pn.mjs +30 -0
  49. package/lib/google-TFe-7-of.mjs +30 -0
  50. package/lib/google-antigravity-DGmwC2KV.mjs +198 -0
  51. package/lib/google-antigravity-DNYhgTpA.mjs +198 -0
  52. package/lib/google-auth-B6gjsZvg.mjs +232 -0
  53. package/lib/google-auth-De7_s3eo.mjs +232 -0
  54. package/lib/google-gemini-cli-CWu8HvXW.mjs +211 -0
  55. package/lib/google-gemini-cli-Cb97bzQc.mjs +850 -0
  56. package/lib/google-gemini-cli-Cqds_Q5T.mjs +850 -0
  57. package/lib/google-gemini-cli-Dsztq0N5.mjs +211 -0
  58. package/lib/google-oauth-shared-CuEHaDDj.mjs +147 -0
  59. package/lib/google-oauth-shared-yqlyqPPC.mjs +147 -0
  60. package/lib/google-shared-CgKmmdO3.mjs +760 -0
  61. package/lib/google-shared-Dr-VG-ap.mjs +760 -0
  62. package/lib/google-vertex-BDN2tLaD.mjs +99 -0
  63. package/lib/google-vertex-DopVOQOG.mjs +99 -0
  64. package/lib/identity-Da1GPU9a.mjs +219 -0
  65. package/lib/identity-xRP7_eSR.mjs +219 -0
  66. package/lib/idle-iterator-Baoyn3Hp.mjs +366 -0
  67. package/lib/idle-iterator-DUjKQEGT.mjs +366 -0
  68. package/lib/index.mjs +1731 -1178
  69. package/lib/kimi--wUOWER5.mjs +236 -0
  70. package/lib/kimi-Dh0pv3WZ.mjs +236 -0
  71. package/lib/markit-BL3cH47U.mjs +1417 -0
  72. package/lib/markit-BNiNY6SE.mjs +1417 -0
  73. package/lib/minimax-code-DCbuA6Yk.mjs +53 -0
  74. package/lib/minimax-code-Uq8Qu9LW.mjs +53 -0
  75. package/lib/models-D_XnT6ay.mjs +104660 -0
  76. package/lib/models-SGASygJ3.mjs +104660 -0
  77. package/lib/ollama-DPzBmq89.mjs +589 -0
  78. package/lib/ollama-DoBz5SFm.mjs +589 -0
  79. package/lib/openai-codex-Bi-4S4PX.mjs +255 -0
  80. package/lib/openai-codex-Ch8CkT3p.mjs +255 -0
  81. package/lib/openai-codex-responses-CvxL_FMF.mjs +3144 -0
  82. package/lib/openai-codex-responses-pejZgdZo.mjs +3144 -0
  83. package/lib/openai-completions-CF8IyNtP.mjs +1360 -0
  84. package/lib/openai-completions-DIf361kF.mjs +1360 -0
  85. package/lib/openai-reasoning-fallback-Nj6yB2rY.mjs +286 -0
  86. package/lib/openai-reasoning-fallback-OdJREP1o.mjs +286 -0
  87. package/lib/openai-responses-BqXJInHX.mjs +867 -0
  88. package/lib/openai-responses-Db_a-U4-.mjs +867 -0
  89. package/lib/opencode-DhMolSoB.mjs +38 -0
  90. package/lib/opencode-Rq_Q2vAO.mjs +38 -0
  91. package/lib/perplexity-C4iLVMUj.mjs +194 -0
  92. package/lib/perplexity-Uu7Jzg5b.mjs +194 -0
  93. package/lib/proxy-DDqrmjjC.mjs +190 -0
  94. package/lib/proxy-pM_NIv-H.mjs +190 -0
  95. package/lib/request-debug-HJMoJncL.mjs +183 -0
  96. package/lib/sanitize-text-CfcXzw5X.mjs +33 -0
  97. package/lib/scrapers-BkFfcPHj.mjs +9198 -0
  98. package/lib/scrapers-CVptboMs.mjs +9198 -0
  99. package/lib/scrapers-nhQAvc8d.mjs +9198 -0
  100. package/lib/shell-snapshot-fn-env.sh +67 -43
  101. package/lib/src-BgpusnsB.mjs +5076 -0
  102. package/lib/src-lDmkSRbm.mjs +5006 -0
  103. package/lib/stream-BlldLkVq.mjs +10236 -0
  104. package/lib/stream-CRtexYLe.mjs +10236 -0
  105. package/lib/stream-markup-healing-DMsxBx1L.mjs +491 -0
  106. package/lib/stream-markup-healing-KMkiAA00.mjs +491 -0
  107. package/lib/turndown-DN7ByzEI.mjs +667 -0
  108. package/lib/types/config/settings.d.ts +9 -1
  109. package/lib/types/config/truncate.d.ts +9 -5
  110. package/lib/types/tools/bash/background.d.ts +1 -1
  111. package/lib/types/tools/bash/bash-executor.d.ts +4 -0
  112. package/lib/types/tools/bash/bash-interceptor.d.ts +10 -8
  113. package/lib/types/tools/bash/cd-workdir.d.ts +35 -0
  114. package/lib/types/tools/bash/non-interactive-env.d.ts +2 -0
  115. package/lib/types/tools/bash/render.d.ts +4 -3
  116. package/lib/types/tools/bash/sanitize-text.d.ts +5 -0
  117. package/lib/types/tools/bash/shell-snapshot.d.ts +4 -1
  118. package/lib/types/tools/bash/shell-tokenize.d.ts +60 -0
  119. package/lib/types/tools/bash/streaming-output.d.ts +12 -212
  120. package/lib/types/tools/bash/which.d.ts +20 -0
  121. package/lib/types/tools/bash/windows-shell.d.ts +31 -0
  122. package/lib/types/tools/edit/adapter/index.d.ts +25 -3
  123. package/lib/types/tools/edit/adapter/tools/auto-generated-guard.d.ts +7 -17
  124. package/lib/types/tools/glob/adapter/index.d.ts +27 -1
  125. package/lib/types/tools/grep/adapter/index.d.ts +29 -1
  126. package/lib/types/tools/omp/edit/dispatch.d.ts +43 -0
  127. package/lib/types/tools/omp/edit/hashline/noop-loop-guard.d.ts +3 -1
  128. package/lib/types/tools/omp/tools/auto-generated-guard.d.ts +20 -0
  129. package/lib/types/tools/omp/tools/write.d.ts +4 -4
  130. package/lib/types/tools/shared/auto-generated-guard.dsh.d.ts +16 -4
  131. package/lib/types/tools/shared/bun-shim.d.ts +4 -0
  132. package/lib/types/tools/shared/fs-promises-shim.d.ts +3 -1
  133. package/lib/types/tools/shared/omp-prompt.d.ts +13 -7
  134. package/lib/types/tools/shared/session-state.d.ts +9 -3
  135. package/lib/utils-Bw139LTz.mjs +8119 -0
  136. package/lib/utils-CZw4tVZQ.mjs +12315 -0
  137. package/lib/utils-CiGN7OHR.mjs +12315 -0
  138. package/lib/utils-Cp76gCyk.mjs +8119 -0
  139. package/lib/utils-D0GRDgAr.mjs +12315 -0
  140. package/lib/utils-D2YknRk4.mjs +51 -0
  141. package/lib/utils-DzXZDfYc.mjs +51 -0
  142. package/lib/vision-guard-01qSwFpf.mjs +92 -0
  143. package/lib/vision-guard-DzZGaOga.mjs +92 -0
  144. package/lib/wafer-CgtPHerf.mjs +17 -0
  145. package/lib/wafer-cBtrn6q9.mjs +17 -0
  146. package/lib/xai-oauth-Buk8XVvM.mjs +446 -0
  147. package/lib/xai-oauth-CMal8l1O.mjs +446 -0
  148. package/lib/xiaomi-CZgwvX2G.mjs +157 -0
  149. package/lib/xiaomi-D2qT5cAC.mjs +157 -0
  150. package/lib/zai-7DWMkEqM.mjs +203 -0
  151. package/lib/zai-C59YnomG.mjs +203 -0
  152. package/lib/zip-Cg9ANN_U.mjs +1316 -0
  153. package/lib/zip-D36ZKsP8.mjs +1316 -0
  154. package/package.json +1 -1
  155. package/presets/package.json +1 -1
@@ -0,0 +1,157 @@
1
+ import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
+ __installBunShim();
3
+ import { _ as OnPromptRequiredError, c as OAuthError, h as LoginCancelledError, m as ApiKeyRequiredError } from "./error-Dd8DIqs-.mjs";
4
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/xiaomi.ts
5
+ /**
6
+ * Xiaomi MiMo login flow.
7
+ *
8
+ * Xiaomi MiMo provides OpenAI-compatible models via
9
+ * https://api.xiaomimimo.com/v1.
10
+ *
11
+ * Standard Xiaomi login opens the pay-as-you-go API key console. Token Plan
12
+ * login opens plan management so users copy the regional `tp-...` key.
13
+ */
14
+ const PROVIDER_ID = "xiaomi";
15
+ const PROVIDER_NAME = "Xiaomi MiMo";
16
+ const STANDARD_AUTH_URL = "https://platform.xiaomimimo.com/#/console/api-keys";
17
+ const TOKEN_PLAN_AUTH_URL = "https://platform.xiaomimimo.com/console/plan-manage";
18
+ const STANDARD_API_BASE_URL = "https://api.xiaomimimo.com/v1";
19
+ const TOKEN_PLAN_KEY_PREFIX = "tp-";
20
+ const STANDARD_VALIDATION_MODEL = "mimo-v2.5";
21
+ const TOKEN_PLAN_VALIDATION_MODEL = "mimo-v2.5";
22
+ const TOKEN_PLAN_VALIDATION_ENDPOINTS = {
23
+ sgp: {
24
+ baseUrl: "https://token-plan-sgp.xiaomimimo.com/v1",
25
+ model: TOKEN_PLAN_VALIDATION_MODEL
26
+ },
27
+ ams: {
28
+ baseUrl: "https://token-plan-ams.xiaomimimo.com/v1",
29
+ model: TOKEN_PLAN_VALIDATION_MODEL
30
+ },
31
+ cn: {
32
+ baseUrl: "https://token-plan-cn.xiaomimimo.com/v1",
33
+ model: TOKEN_PLAN_VALIDATION_MODEL
34
+ }
35
+ };
36
+ const TOKEN_PLAN_REGION_NAMES = {
37
+ sgp: "Singapore",
38
+ ams: "Europe",
39
+ cn: "China"
40
+ };
41
+ function isTokenPlanKey(apiKey) {
42
+ return apiKey.startsWith(TOKEN_PLAN_KEY_PREFIX);
43
+ }
44
+ const VALIDATION_TIMEOUT_MS = 15e3;
45
+ async function validateXiaomiApiKey(apiKey, tokenPlanRegion, signal, fetchOverride) {
46
+ const fetchImpl = fetchOverride ?? fetch;
47
+ const endpoints = tokenPlanRegion ? [TOKEN_PLAN_VALIDATION_ENDPOINTS[tokenPlanRegion]] : isTokenPlanKey(apiKey) ? [
48
+ TOKEN_PLAN_VALIDATION_ENDPOINTS.sgp,
49
+ TOKEN_PLAN_VALIDATION_ENDPOINTS.ams,
50
+ TOKEN_PLAN_VALIDATION_ENDPOINTS.cn
51
+ ] : [{
52
+ baseUrl: STANDARD_API_BASE_URL,
53
+ model: STANDARD_VALIDATION_MODEL
54
+ }];
55
+ let lastError = null;
56
+ for (const ep of endpoints) {
57
+ const timeoutSignal = AbortSignal.timeout(VALIDATION_TIMEOUT_MS);
58
+ const requestSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
59
+ try {
60
+ const response = await fetchImpl(`${ep.baseUrl}/chat/completions`, {
61
+ method: "POST",
62
+ headers: {
63
+ "Content-Type": "application/json",
64
+ Authorization: `Bearer ${apiKey}`
65
+ },
66
+ body: JSON.stringify({
67
+ model: ep.model,
68
+ max_tokens: 1,
69
+ messages: [{
70
+ role: "user",
71
+ content: "ping"
72
+ }]
73
+ }),
74
+ signal: requestSignal
75
+ });
76
+ if (response.ok) return;
77
+ if (response.status === 401) {
78
+ let details = "";
79
+ try {
80
+ details = (await response.text()).trim();
81
+ } catch {}
82
+ lastError = new OAuthError(details ? `${PROVIDER_NAME} API key validation failed (${response.status}): ${details}` : `${PROVIDER_NAME} API key validation failed (${response.status})`, {
83
+ kind: "validation",
84
+ provider: PROVIDER_ID,
85
+ status: response.status
86
+ });
87
+ continue;
88
+ }
89
+ let details = "";
90
+ try {
91
+ details = (await response.text()).trim();
92
+ } catch {}
93
+ const message = details ? `${PROVIDER_NAME} API key validation failed (${response.status}): ${details}` : `${PROVIDER_NAME} API key validation failed (${response.status})`;
94
+ throw new OAuthError(message, {
95
+ kind: "validation",
96
+ provider: PROVIDER_ID,
97
+ status: response.status
98
+ });
99
+ } catch (e) {
100
+ if (e instanceof DOMException && e.name === "AbortError" && signal?.aborted) throw e;
101
+ lastError = e instanceof Error ? e : new Error(String(e));
102
+ }
103
+ }
104
+ throw lastError ?? new OAuthError(`${PROVIDER_NAME} API key validation failed`, {
105
+ kind: "validation",
106
+ provider: PROVIDER_ID
107
+ });
108
+ }
109
+ /**
110
+ * Login to Xiaomi MiMo.
111
+ *
112
+ * Opens browser to API keys page, prompts user to paste their API key.
113
+ * Returns the API key directly (not OAuthCredentials - this isn't OAuth).
114
+ */
115
+ async function loginXiaomi(options) {
116
+ const fetchImpl = options.fetch ?? fetch;
117
+ if (!options.onPrompt) throw new OnPromptRequiredError(PROVIDER_NAME);
118
+ options.onAuth?.({
119
+ url: STANDARD_AUTH_URL,
120
+ instructions: "Copy your API key from the Xiaomi MiMo console"
121
+ });
122
+ const apiKey = await options.onPrompt({
123
+ message: "Paste your Xiaomi API key (sk-... or token-plan tp-...)",
124
+ placeholder: "sk-... or tp-..."
125
+ });
126
+ if (options.signal?.aborted) throw new LoginCancelledError();
127
+ const trimmed = apiKey.trim();
128
+ if (!trimmed) throw new ApiKeyRequiredError();
129
+ options.onProgress?.(`Validating ${PROVIDER_ID} API key...`);
130
+ await validateXiaomiApiKey(trimmed, void 0, options.signal, fetchImpl);
131
+ return trimmed;
132
+ }
133
+ /**
134
+ * Login to a regional Xiaomi Token Plan endpoint.
135
+ *
136
+ * Prompts for a token-plan API key and validates it against the selected region.
137
+ */
138
+ async function loginXiaomiTokenPlan(options, region) {
139
+ const fetchImpl = options.fetch ?? fetch;
140
+ if (!options.onPrompt) throw new OnPromptRequiredError(`Xiaomi Token Plan (${TOKEN_PLAN_REGION_NAMES[region]})`);
141
+ options.onAuth?.({
142
+ url: TOKEN_PLAN_AUTH_URL,
143
+ instructions: `Copy your token-plan API key for the ${TOKEN_PLAN_REGION_NAMES[region]} region`
144
+ });
145
+ const apiKey = await options.onPrompt({
146
+ message: `Paste your Xiaomi Token Plan ${TOKEN_PLAN_REGION_NAMES[region]} API key (tp-...)`,
147
+ placeholder: "tp-..."
148
+ });
149
+ if (options.signal?.aborted) throw new LoginCancelledError();
150
+ const trimmed = apiKey.trim();
151
+ if (!trimmed) throw new ApiKeyRequiredError();
152
+ options.onProgress?.(`Validating Xiaomi Token Plan (${TOKEN_PLAN_REGION_NAMES[region]}) API key...`);
153
+ await validateXiaomiApiKey(trimmed, region, options.signal, fetchImpl);
154
+ return trimmed;
155
+ }
156
+ //#endregion
157
+ export { loginXiaomi, loginXiaomiTokenPlan };
@@ -0,0 +1,203 @@
1
+ import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
+ __installBunShim();
3
+ import { V as ProviderHttpError, c as OAuthError, h as LoginCancelledError } from "./error-yCSG0mGC.mjs";
4
+ import { t as OAuthCallbackFlow } from "./callback-server-DDSrZ6l_.mjs";
5
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/zai.ts
6
+ /**
7
+ * Z.ai / GLM OAuth flow (GLM Coding Plan · Sign in)
8
+ *
9
+ * Mirrors ZCode's desktop "Individual Plan" browser sign-in: an
10
+ * authorization-code flow (no PKCE) against chat.z.ai, a JSON token exchange
11
+ * that yields a short-lived OAuth access token, and a business-API sequence
12
+ * that provisions a durable `id.secret` API key. The minted key is placed in
13
+ * {@link OAuthCredentials.access}; `getOAuthApiKey` returns it verbatim as the
14
+ * request bearer for the `zai` provider, so no dialect change is needed.
15
+ */
16
+ const env = (key) => {
17
+ const value = process.env[key];
18
+ return typeof value === "string" && value.length > 0 ? value : void 0;
19
+ };
20
+ const CLIENT_ID = env("ZAI_OAUTH_CLIENT_ID") ?? "client_P8X5CMWmlaRO9gyO-KSqtg";
21
+ const AUTHORIZE_URL = env("ZAI_OAUTH_AUTHORIZE_URL") ?? "https://chat.z.ai/api/oauth/authorize";
22
+ const TOKEN_URL = env("ZAI_OAUTH_TOKEN_URL") ?? "https://zcode.z.ai/api/v1/oauth/token";
23
+ const BIZ_BASE = env("ZAI_BIZ_BASE") ?? "https://api.z.ai";
24
+ /** Business-login endpoint: exchanges the OAuth access token for a biz token. */
25
+ const BUSINESS_LOGIN_URL = env("ZAI_BUSINESS_LOGIN_URL") ?? "https://api.z.ai/api/auth/z/login";
26
+ /** OMP's own key name so sign-in never mutates ZCode's `zcode-api-key`. */
27
+ const KEY_NAME = "oh-my-pi";
28
+ const CALLBACK_PORT = 54548;
29
+ const CALLBACK_PATH = "/callback";
30
+ /** Durable minted key never expires; matches the perplexity NEVER_EXPIRES sentinel. */
31
+ const NEVER_EXPIRES = 864e13;
32
+ function formatErrorDetails(error) {
33
+ if (error instanceof Error) return error.message;
34
+ return String(error);
35
+ }
36
+ /**
37
+ * Z.ai's `{ code, msg, data, success }` envelope. The OAuth token endpoint
38
+ * signals success with `code: 0`; the biz endpoints (`api.z.ai`) use
39
+ * `code: 200` / `success: true`. Accept both; throw `msg` on failure. Bodies
40
+ * without a status wrapper pass through unchanged.
41
+ */
42
+ function isSuccessCode(code) {
43
+ if (code == null) return true;
44
+ if (typeof code === "number") return code === 0 || code === 200;
45
+ if (typeof code === "string") return code === "0" || code === "200";
46
+ return false;
47
+ }
48
+ function unwrapEnvelope(body, operation) {
49
+ if (body && typeof body === "object" && ("code" in body || "success" in body)) {
50
+ const envelope = body;
51
+ if (envelope.success === false || !isSuccessCode(envelope.code)) throw new OAuthError(`Z.ai ${operation} failed: ${envelope.msg ?? `code ${String(envelope.code)}`}`, {
52
+ kind: "token-exchange",
53
+ provider: "zai"
54
+ });
55
+ return "data" in envelope ? envelope.data : envelope;
56
+ }
57
+ return body;
58
+ }
59
+ async function getJson(url, headers, fetchImpl) {
60
+ const response = await fetchImpl(url, {
61
+ method: "GET",
62
+ headers,
63
+ signal: AbortSignal.timeout(3e4)
64
+ });
65
+ const responseBody = await response.text();
66
+ if (!response.ok) throw new ProviderHttpError(`HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`, response.status);
67
+ return responseBody.length > 0 ? JSON.parse(responseBody) : void 0;
68
+ }
69
+ async function postJson(url, body, headers, fetchImpl) {
70
+ const response = await fetchImpl(url, {
71
+ method: "POST",
72
+ headers: {
73
+ ...headers,
74
+ "Content-Type": "application/json"
75
+ },
76
+ body: JSON.stringify(body),
77
+ signal: AbortSignal.timeout(3e4)
78
+ });
79
+ const responseBody = await response.text();
80
+ if (!response.ok) throw new ProviderHttpError(`HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`, response.status);
81
+ return responseBody.length > 0 ? JSON.parse(responseBody) : void 0;
82
+ }
83
+ /** Coerce an api_keys list response (bare array or common wrapper shapes) to an array. */
84
+ function asKeyArray(value) {
85
+ if (Array.isArray(value)) return value;
86
+ if (value && typeof value === "object") {
87
+ const record = value;
88
+ for (const field of [
89
+ "list",
90
+ "keys",
91
+ "apiKeys",
92
+ "records"
93
+ ]) if (Array.isArray(record[field])) return record[field];
94
+ }
95
+ return [];
96
+ }
97
+ function trimmedString(value) {
98
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
99
+ }
100
+ /**
101
+ * Exchange the short-lived OAuth access token for a durable biz token via
102
+ * ZCode's business-login endpoint. The biz APIs reject the raw OAuth token;
103
+ * they require this token.
104
+ */
105
+ async function businessLogin(oauthAccessToken, fetchImpl) {
106
+ const data = unwrapEnvelope(await postJson(BUSINESS_LOGIN_URL, { token: oauthAccessToken }, {}, fetchImpl), "business login");
107
+ const bizToken = trimmedString(data?.access_token) ?? trimmedString(data?.accessToken);
108
+ if (!bizToken) throw new OAuthError("Z.ai business login returned no access token", {
109
+ kind: "token-exchange",
110
+ provider: "zai"
111
+ });
112
+ return bizToken;
113
+ }
114
+ /**
115
+ * Provision the durable Z.ai API key from a short-lived OAuth access token,
116
+ * mirroring ZCode: business-login → resolve default org/project from
117
+ * `getCustomerInfo` → find/create the OMP-named key → obtain its secret →
118
+ * return `${apiKey}.${secretKey}` (the 49-char durable key).
119
+ */
120
+ async function mintZaiApiKey(oauthAccessToken, fetchImpl) {
121
+ const auth = { Authorization: `Bearer ${await businessLogin(oauthAccessToken, fetchImpl)}` };
122
+ const customer = unwrapEnvelope(await getJson(`${BIZ_BASE}/api/biz/customer/getCustomerInfo`, auth, fetchImpl), "customer lookup");
123
+ const orgs = Array.isArray(customer?.organizations) ? customer.organizations : [];
124
+ const org = orgs.find((o) => o?.isDefault) ?? orgs[0];
125
+ const projects = Array.isArray(org?.projects) ? org.projects : [];
126
+ const project = projects.find((p) => p?.isDefault) ?? projects[0];
127
+ const organizationId = trimmedString(org?.organizationId);
128
+ const projectId = trimmedString(project?.projectId);
129
+ if (!organizationId || !projectId) throw new OAuthError("Z.ai key provisioning failed: no organization/project on account", {
130
+ kind: "token-exchange",
131
+ provider: "zai"
132
+ });
133
+ const keysUrl = `${BIZ_BASE}/api/biz/v1/organization/${organizationId}/projects/${projectId}/api_keys`;
134
+ const apiKey = trimmedString((asKeyArray(unwrapEnvelope(await getJson(keysUrl, auth, fetchImpl), "api key list")).find((key) => key.name === KEY_NAME) ?? unwrapEnvelope(await postJson(keysUrl, { name: KEY_NAME }, auth, fetchImpl), "api key create"))?.apiKey);
135
+ if (!apiKey) throw new OAuthError("Z.ai key provisioning returned no apiKey", {
136
+ kind: "token-exchange",
137
+ provider: "zai"
138
+ });
139
+ const secretKey = trimmedString(unwrapEnvelope(await getJson(`${keysUrl}/copy/${encodeURIComponent(apiKey)}`, auth, fetchImpl), "api key copy")?.secretKey);
140
+ if (!secretKey) throw new OAuthError("Z.ai key provisioning returned no secretKey", {
141
+ kind: "token-exchange",
142
+ provider: "zai"
143
+ });
144
+ return `${apiKey}.${secretKey}`;
145
+ }
146
+ var ZaiOAuthFlow = class extends OAuthCallbackFlow {
147
+ #fetch;
148
+ constructor(ctrl) {
149
+ super(ctrl, CALLBACK_PORT, CALLBACK_PATH);
150
+ this.#fetch = ctrl.fetch ?? fetch;
151
+ }
152
+ async generateAuthUrl(state, redirectUri) {
153
+ const authParams = new URLSearchParams({
154
+ redirect_uri: redirectUri,
155
+ response_type: "code",
156
+ client_id: CLIENT_ID,
157
+ state
158
+ });
159
+ return {
160
+ url: `${AUTHORIZE_URL}?${authParams.toString()}`,
161
+ instructions: "Complete Z.ai login in your browser. If the browser cannot reach this machine, paste the final redirect URL or authorization code when prompted."
162
+ };
163
+ }
164
+ async exchangeToken(code, state, redirectUri) {
165
+ if (this.ctrl.signal?.aborted) throw new LoginCancelledError(`OAuth callback cancelled: ${this.ctrl.signal.reason}`);
166
+ let body;
167
+ try {
168
+ body = await postJson(TOKEN_URL, {
169
+ provider: "zai",
170
+ code,
171
+ redirect_uri: redirectUri,
172
+ state
173
+ }, {}, this.#fetch);
174
+ } catch (error) {
175
+ throw new OAuthError(`Token exchange request failed. url=${TOKEN_URL}; redirect_uri=${redirectUri}; details=${formatErrorDetails(error)}`, {
176
+ kind: "token-exchange",
177
+ provider: "zai",
178
+ cause: error
179
+ });
180
+ }
181
+ const data = unwrapEnvelope(body, "token exchange");
182
+ const oauthAccessToken = trimmedString(data?.zai?.access_token);
183
+ if (!oauthAccessToken) throw new OAuthError("Z.ai token response missing access token", {
184
+ kind: "validation",
185
+ provider: "zai"
186
+ });
187
+ return {
188
+ access: await mintZaiApiKey(oauthAccessToken, this.#fetch),
189
+ refresh: "",
190
+ expires: NEVER_EXPIRES,
191
+ email: typeof data?.user?.email === "string" ? data.user.email : void 0,
192
+ accountId: typeof data?.user?.id === "string" || typeof data?.user?.id === "number" ? String(data.user.id) : void 0
193
+ };
194
+ }
195
+ };
196
+ /**
197
+ * Login with Z.ai OAuth (GLM Coding Plan).
198
+ */
199
+ async function loginZaiOAuth(ctrl) {
200
+ return new ZaiOAuthFlow(ctrl).login();
201
+ }
202
+ //#endregion
203
+ export { loginZaiOAuth };
@@ -0,0 +1,203 @@
1
+ import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
+ __installBunShim();
3
+ import { V as ProviderHttpError, c as OAuthError, h as LoginCancelledError } from "./error-Dd8DIqs-.mjs";
4
+ import { t as OAuthCallbackFlow } from "./callback-server-CQ5Jo8F-.mjs";
5
+ //#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/zai.ts
6
+ /**
7
+ * Z.ai / GLM OAuth flow (GLM Coding Plan · Sign in)
8
+ *
9
+ * Mirrors ZCode's desktop "Individual Plan" browser sign-in: an
10
+ * authorization-code flow (no PKCE) against chat.z.ai, a JSON token exchange
11
+ * that yields a short-lived OAuth access token, and a business-API sequence
12
+ * that provisions a durable `id.secret` API key. The minted key is placed in
13
+ * {@link OAuthCredentials.access}; `getOAuthApiKey` returns it verbatim as the
14
+ * request bearer for the `zai` provider, so no dialect change is needed.
15
+ */
16
+ const env = (key) => {
17
+ const value = process.env[key];
18
+ return typeof value === "string" && value.length > 0 ? value : void 0;
19
+ };
20
+ const CLIENT_ID = env("ZAI_OAUTH_CLIENT_ID") ?? "client_P8X5CMWmlaRO9gyO-KSqtg";
21
+ const AUTHORIZE_URL = env("ZAI_OAUTH_AUTHORIZE_URL") ?? "https://chat.z.ai/api/oauth/authorize";
22
+ const TOKEN_URL = env("ZAI_OAUTH_TOKEN_URL") ?? "https://zcode.z.ai/api/v1/oauth/token";
23
+ const BIZ_BASE = env("ZAI_BIZ_BASE") ?? "https://api.z.ai";
24
+ /** Business-login endpoint: exchanges the OAuth access token for a biz token. */
25
+ const BUSINESS_LOGIN_URL = env("ZAI_BUSINESS_LOGIN_URL") ?? "https://api.z.ai/api/auth/z/login";
26
+ /** OMP's own key name so sign-in never mutates ZCode's `zcode-api-key`. */
27
+ const KEY_NAME = "oh-my-pi";
28
+ const CALLBACK_PORT = 54548;
29
+ const CALLBACK_PATH = "/callback";
30
+ /** Durable minted key never expires; matches the perplexity NEVER_EXPIRES sentinel. */
31
+ const NEVER_EXPIRES = 864e13;
32
+ function formatErrorDetails(error) {
33
+ if (error instanceof Error) return error.message;
34
+ return String(error);
35
+ }
36
+ /**
37
+ * Z.ai's `{ code, msg, data, success }` envelope. The OAuth token endpoint
38
+ * signals success with `code: 0`; the biz endpoints (`api.z.ai`) use
39
+ * `code: 200` / `success: true`. Accept both; throw `msg` on failure. Bodies
40
+ * without a status wrapper pass through unchanged.
41
+ */
42
+ function isSuccessCode(code) {
43
+ if (code == null) return true;
44
+ if (typeof code === "number") return code === 0 || code === 200;
45
+ if (typeof code === "string") return code === "0" || code === "200";
46
+ return false;
47
+ }
48
+ function unwrapEnvelope(body, operation) {
49
+ if (body && typeof body === "object" && ("code" in body || "success" in body)) {
50
+ const envelope = body;
51
+ if (envelope.success === false || !isSuccessCode(envelope.code)) throw new OAuthError(`Z.ai ${operation} failed: ${envelope.msg ?? `code ${String(envelope.code)}`}`, {
52
+ kind: "token-exchange",
53
+ provider: "zai"
54
+ });
55
+ return "data" in envelope ? envelope.data : envelope;
56
+ }
57
+ return body;
58
+ }
59
+ async function getJson(url, headers, fetchImpl) {
60
+ const response = await fetchImpl(url, {
61
+ method: "GET",
62
+ headers,
63
+ signal: AbortSignal.timeout(3e4)
64
+ });
65
+ const responseBody = await response.text();
66
+ if (!response.ok) throw new ProviderHttpError(`HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`, response.status);
67
+ return responseBody.length > 0 ? JSON.parse(responseBody) : void 0;
68
+ }
69
+ async function postJson(url, body, headers, fetchImpl) {
70
+ const response = await fetchImpl(url, {
71
+ method: "POST",
72
+ headers: {
73
+ ...headers,
74
+ "Content-Type": "application/json"
75
+ },
76
+ body: JSON.stringify(body),
77
+ signal: AbortSignal.timeout(3e4)
78
+ });
79
+ const responseBody = await response.text();
80
+ if (!response.ok) throw new ProviderHttpError(`HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`, response.status);
81
+ return responseBody.length > 0 ? JSON.parse(responseBody) : void 0;
82
+ }
83
+ /** Coerce an api_keys list response (bare array or common wrapper shapes) to an array. */
84
+ function asKeyArray(value) {
85
+ if (Array.isArray(value)) return value;
86
+ if (value && typeof value === "object") {
87
+ const record = value;
88
+ for (const field of [
89
+ "list",
90
+ "keys",
91
+ "apiKeys",
92
+ "records"
93
+ ]) if (Array.isArray(record[field])) return record[field];
94
+ }
95
+ return [];
96
+ }
97
+ function trimmedString(value) {
98
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
99
+ }
100
+ /**
101
+ * Exchange the short-lived OAuth access token for a durable biz token via
102
+ * ZCode's business-login endpoint. The biz APIs reject the raw OAuth token;
103
+ * they require this token.
104
+ */
105
+ async function businessLogin(oauthAccessToken, fetchImpl) {
106
+ const data = unwrapEnvelope(await postJson(BUSINESS_LOGIN_URL, { token: oauthAccessToken }, {}, fetchImpl), "business login");
107
+ const bizToken = trimmedString(data?.access_token) ?? trimmedString(data?.accessToken);
108
+ if (!bizToken) throw new OAuthError("Z.ai business login returned no access token", {
109
+ kind: "token-exchange",
110
+ provider: "zai"
111
+ });
112
+ return bizToken;
113
+ }
114
+ /**
115
+ * Provision the durable Z.ai API key from a short-lived OAuth access token,
116
+ * mirroring ZCode: business-login → resolve default org/project from
117
+ * `getCustomerInfo` → find/create the OMP-named key → obtain its secret →
118
+ * return `${apiKey}.${secretKey}` (the 49-char durable key).
119
+ */
120
+ async function mintZaiApiKey(oauthAccessToken, fetchImpl) {
121
+ const auth = { Authorization: `Bearer ${await businessLogin(oauthAccessToken, fetchImpl)}` };
122
+ const customer = unwrapEnvelope(await getJson(`${BIZ_BASE}/api/biz/customer/getCustomerInfo`, auth, fetchImpl), "customer lookup");
123
+ const orgs = Array.isArray(customer?.organizations) ? customer.organizations : [];
124
+ const org = orgs.find((o) => o?.isDefault) ?? orgs[0];
125
+ const projects = Array.isArray(org?.projects) ? org.projects : [];
126
+ const project = projects.find((p) => p?.isDefault) ?? projects[0];
127
+ const organizationId = trimmedString(org?.organizationId);
128
+ const projectId = trimmedString(project?.projectId);
129
+ if (!organizationId || !projectId) throw new OAuthError("Z.ai key provisioning failed: no organization/project on account", {
130
+ kind: "token-exchange",
131
+ provider: "zai"
132
+ });
133
+ const keysUrl = `${BIZ_BASE}/api/biz/v1/organization/${organizationId}/projects/${projectId}/api_keys`;
134
+ const apiKey = trimmedString((asKeyArray(unwrapEnvelope(await getJson(keysUrl, auth, fetchImpl), "api key list")).find((key) => key.name === KEY_NAME) ?? unwrapEnvelope(await postJson(keysUrl, { name: KEY_NAME }, auth, fetchImpl), "api key create"))?.apiKey);
135
+ if (!apiKey) throw new OAuthError("Z.ai key provisioning returned no apiKey", {
136
+ kind: "token-exchange",
137
+ provider: "zai"
138
+ });
139
+ const secretKey = trimmedString(unwrapEnvelope(await getJson(`${keysUrl}/copy/${encodeURIComponent(apiKey)}`, auth, fetchImpl), "api key copy")?.secretKey);
140
+ if (!secretKey) throw new OAuthError("Z.ai key provisioning returned no secretKey", {
141
+ kind: "token-exchange",
142
+ provider: "zai"
143
+ });
144
+ return `${apiKey}.${secretKey}`;
145
+ }
146
+ var ZaiOAuthFlow = class extends OAuthCallbackFlow {
147
+ #fetch;
148
+ constructor(ctrl) {
149
+ super(ctrl, CALLBACK_PORT, CALLBACK_PATH);
150
+ this.#fetch = ctrl.fetch ?? fetch;
151
+ }
152
+ async generateAuthUrl(state, redirectUri) {
153
+ const authParams = new URLSearchParams({
154
+ redirect_uri: redirectUri,
155
+ response_type: "code",
156
+ client_id: CLIENT_ID,
157
+ state
158
+ });
159
+ return {
160
+ url: `${AUTHORIZE_URL}?${authParams.toString()}`,
161
+ instructions: "Complete Z.ai login in your browser. If the browser cannot reach this machine, paste the final redirect URL or authorization code when prompted."
162
+ };
163
+ }
164
+ async exchangeToken(code, state, redirectUri) {
165
+ if (this.ctrl.signal?.aborted) throw new LoginCancelledError(`OAuth callback cancelled: ${this.ctrl.signal.reason}`);
166
+ let body;
167
+ try {
168
+ body = await postJson(TOKEN_URL, {
169
+ provider: "zai",
170
+ code,
171
+ redirect_uri: redirectUri,
172
+ state
173
+ }, {}, this.#fetch);
174
+ } catch (error) {
175
+ throw new OAuthError(`Token exchange request failed. url=${TOKEN_URL}; redirect_uri=${redirectUri}; details=${formatErrorDetails(error)}`, {
176
+ kind: "token-exchange",
177
+ provider: "zai",
178
+ cause: error
179
+ });
180
+ }
181
+ const data = unwrapEnvelope(body, "token exchange");
182
+ const oauthAccessToken = trimmedString(data?.zai?.access_token);
183
+ if (!oauthAccessToken) throw new OAuthError("Z.ai token response missing access token", {
184
+ kind: "validation",
185
+ provider: "zai"
186
+ });
187
+ return {
188
+ access: await mintZaiApiKey(oauthAccessToken, this.#fetch),
189
+ refresh: "",
190
+ expires: NEVER_EXPIRES,
191
+ email: typeof data?.user?.email === "string" ? data.user.email : void 0,
192
+ accountId: typeof data?.user?.id === "string" || typeof data?.user?.id === "number" ? String(data.user.id) : void 0
193
+ };
194
+ }
195
+ };
196
+ /**
197
+ * Login with Z.ai OAuth (GLM Coding Plan).
198
+ */
199
+ async function loginZaiOAuth(ctrl) {
200
+ return new ZaiOAuthFlow(ctrl).login();
201
+ }
202
+ //#endregion
203
+ export { loginZaiOAuth };