@bike4mind/cli 3.4.0 → 4.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.
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env node
2
+ import { b as logger, g as DeviceFlowClient, h as AuthenticatedApiClient, t as ConfigStore } from "./ConfigStore-BwqsQ0U9.mjs";
3
+ import { t as version } from "./package-CQaam4Dq.mjs";
4
+ import { isAxiosError } from "axios";
5
+ import { Readable } from "node:stream";
6
+ //#region src/auth/OAuthClient.ts
7
+ /**
8
+ * The CLI's RFC 8628 `client_id`; the desktop app registers under its own. Typed against the
9
+ * server allowlist so dropping this id there fails this build rather than this client's logins
10
+ * (see OAUTH_DEVICE_CLIENT_IDS).
11
+ */
12
+ const CLI_OAUTH_CLIENT_ID = "b4m-cli";
13
+ /**
14
+ * The shared device-flow client, pinned to the CLI's registration.
15
+ */
16
+ var OAuthClient = class extends DeviceFlowClient {
17
+ constructor(baseURL = "http://localhost:3000") {
18
+ super({
19
+ baseUrl: baseURL,
20
+ clientId: CLI_OAUTH_CLIENT_ID
21
+ });
22
+ }
23
+ };
24
+ //#endregion
25
+ //#region src/auth/providerKeyFailure.ts
26
+ const PROVIDER_KEY_ERROR_CODES = /* @__PURE__ */ new Set(["provider_not_configured", "provider_rejected"]);
27
+ /**
28
+ * A 401 whose body names a missing or rejected AI-provider key (e.g. /api/ai/tts). The
29
+ * Bike4Mind credential was accepted, so refreshing or re-authenticating cannot fix it.
30
+ * Shared by the ApiClient refresh interceptor and mapApiError in mcp/b4mApiClient.ts.
31
+ */
32
+ function isProviderKeyFailure(data) {
33
+ const body = decodeBinaryBody(data);
34
+ if (!body || typeof body !== "object") return false;
35
+ const { errorCode } = body;
36
+ return typeof errorCode === "string" && PROVIDER_KEY_ERROR_CODES.has(errorCode);
37
+ }
38
+ /**
39
+ * An arraybuffer-typed request (every @bike4mind/sdk call, through ApiClient.fetch) gets its
40
+ * error body as raw bytes, and the refresh interceptor sees it before any caller can decode it.
41
+ */
42
+ function decodeBinaryBody(data) {
43
+ const bytes = data instanceof ArrayBuffer ? Buffer.from(data) : ArrayBuffer.isView(data) ? Buffer.from(data.buffer, data.byteOffset, data.byteLength) : void 0;
44
+ if (!bytes) return data;
45
+ try {
46
+ return JSON.parse(bytes.toString("utf8"));
47
+ } catch {
48
+ return;
49
+ }
50
+ }
51
+ //#endregion
52
+ //#region src/auth/ApiClient.ts
53
+ const USER_AGENT = `b4m-cli/${version}`;
54
+ /**
55
+ * Per-request timeout. Generous by design: a waited chat (POST /api/chat with wait:true)
56
+ * runs a full server-side quest, so the bound only exists to stop a hung backend from
57
+ * wedging a caller forever, not to cap a normal long quest. Override with B4M_API_TIMEOUT_MS
58
+ * (0 disables the timeout entirely).
59
+ */
60
+ const DEFAULT_API_TIMEOUT_MS = 6e5;
61
+ function resolveTimeoutMs() {
62
+ const raw = process.env.B4M_API_TIMEOUT_MS;
63
+ if (raw === void 0 || raw.trim() === "") return DEFAULT_API_TIMEOUT_MS;
64
+ const parsed = Number(raw);
65
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_API_TIMEOUT_MS;
66
+ }
67
+ /**
68
+ * The shared authenticated client, wired to the CLI's storage, logger and branding.
69
+ */
70
+ var ApiClient = class extends AuthenticatedApiClient {
71
+ /**
72
+ * @param apiKey - When set, requests authenticate with this instance API key via
73
+ * the `x-api-key` header and the OAuth-JWT path (Bearer injection + refresh-on-401)
74
+ * is bypassed entirely. Omit to keep the default stored-JWT behavior unchanged.
75
+ */
76
+ constructor(baseURL = "http://localhost:3000", configStore, apiKey) {
77
+ super({
78
+ baseUrl: baseURL,
79
+ tokenStore: configStore || new ConfigStore(),
80
+ oauthClient: new OAuthClient(baseURL),
81
+ logger,
82
+ apiKey,
83
+ timeoutMs: resolveTimeoutMs(),
84
+ headers: {
85
+ "User-Agent": USER_AGENT,
86
+ "X-B4M-Client": USER_AGENT
87
+ },
88
+ reauthMessages: {
89
+ refreshFailed: "Authentication expired. Please run `b4m login` again.",
90
+ stillUnauthorized: "Authentication failed. Please run /login to authenticate.",
91
+ notLoggedIn: "Authentication failed: not logged in. Please run `b4m login` to authenticate."
92
+ },
93
+ isPassThrough401: isProviderKeyFailure
94
+ });
95
+ this.fetch = async (input, init = {}) => {
96
+ const headers = Object.fromEntries(new Headers(init.headers));
97
+ try {
98
+ return toFetchResponse(await this.getAxiosInstance().request({
99
+ url: input instanceof Request ? input.url : String(input),
100
+ method: init.method ?? "GET",
101
+ headers,
102
+ data: init.body ?? void 0,
103
+ signal: init.signal ?? void 0,
104
+ responseType: /text\/event-stream/i.test(headers.accept ?? "") ? "stream" : "arraybuffer",
105
+ ...init.redirect && init.redirect !== "follow" ? { maxRedirects: 0 } : {}
106
+ }));
107
+ } catch (error) {
108
+ if (isAxiosError(error) && error.response) return toFetchResponse(error.response);
109
+ throw error;
110
+ }
111
+ };
112
+ }
113
+ get baseURL() {
114
+ return this.getAxiosInstance().defaults.baseURL ?? "";
115
+ }
116
+ };
117
+ function toFetchResponse(response) {
118
+ const headers = new Headers();
119
+ for (const [name, value] of Object.entries(response.headers)) if (value !== void 0 && value !== null) headers.set(name, Array.isArray(value) ? value.join(", ") : String(value));
120
+ const body = [
121
+ 101,
122
+ 204,
123
+ 205,
124
+ 304
125
+ ].includes(response.status) ? null : response.data instanceof Readable ? Readable.toWeb(response.data) : response.data;
126
+ return new Response(body, {
127
+ status: response.status,
128
+ statusText: response.statusText,
129
+ headers
130
+ });
131
+ }
132
+ //#endregion
133
+ export { isProviderKeyFailure as n, OAuthClient as r, ApiClient as t };