@botconnector/bccli 0.4.0-beta.9 → 0.4.1

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 (183) hide show
  1. package/README.en.md +253 -0
  2. package/README.md +93 -6
  3. package/dist/abort.d.ts +5 -0
  4. package/dist/acp-3PHBAI64.js +182 -0
  5. package/dist/acp.d.ts +27 -0
  6. package/dist/agent.d.ts +143 -0
  7. package/dist/agents.d.ts +4 -0
  8. package/dist/args-W6BNKY7K.js +13 -0
  9. package/dist/args.d.ts +51 -0
  10. package/dist/budget.d.ts +23 -0
  11. package/dist/checkpoints.d.ts +34 -0
  12. package/dist/{chunk-BFZXRKW5.js → chunk-24JN75FZ.js} +29 -7
  13. package/dist/chunk-45SDLMTV.js +341 -0
  14. package/dist/chunk-75BECX4F.js +56 -0
  15. package/dist/{chunk-SJH3YLW4.js → chunk-BC7UXFE4.js} +69 -6
  16. package/dist/chunk-BGXNR74O.js +733 -0
  17. package/dist/chunk-BKGFA2PT.js +8 -0
  18. package/dist/{chunk-CLN4Z5E3.js → chunk-BLOYFIAD.js} +6 -3
  19. package/dist/chunk-BXQQCUAC.js +145 -0
  20. package/dist/chunk-FLQPE4S5.js +373 -0
  21. package/dist/chunk-GN4W3T6E.js +76 -0
  22. package/dist/{chunk-7S6JXQCH.js → chunk-JHPGOAXU.js} +2 -1
  23. package/dist/chunk-MFHCQQEN.js +201 -0
  24. package/dist/chunk-MHIYLXJC.js +143 -0
  25. package/dist/chunk-PSO7R5AD.js +10 -0
  26. package/dist/chunk-PZRKU4UM.js +2143 -0
  27. package/dist/chunk-QZKLZELZ.js +64 -0
  28. package/dist/chunk-R5RE46CW.js +231 -0
  29. package/dist/chunk-UZWJQF67.js +500 -0
  30. package/dist/{chunk-DX7CZTBB.js → chunk-WI22M2ID.js} +14 -9
  31. package/dist/chunk-WNACAUDK.js +946 -0
  32. package/dist/chunk-XV7ZVL4J.js +235 -0
  33. package/dist/cli.d.ts +1 -0
  34. package/dist/cli.js +150 -1382
  35. package/dist/clipboardImage.d.ts +17 -0
  36. package/dist/commands.d.ts +16 -0
  37. package/dist/completion-HPPFDAPB.js +125 -0
  38. package/dist/completion.d.ts +14 -0
  39. package/dist/{config-YUNKPCNB.js → config-DIDLDONU.js} +5 -2
  40. package/dist/config-IU76CPK2.js +34 -0
  41. package/dist/config.d.ts +97 -0
  42. package/dist/context.d.ts +13 -0
  43. package/dist/contextWindow.d.ts +3 -0
  44. package/dist/diff.d.ts +7 -0
  45. package/dist/exit.d.ts +9 -0
  46. package/dist/extensions.d.ts +34 -0
  47. package/dist/ghBotCli-E3VPHNZY.js +677 -0
  48. package/dist/ghBotCli.d.ts +9 -0
  49. package/dist/ghBotDispatch.d.ts +68 -0
  50. package/dist/ghBotRunner.d.ts +82 -0
  51. package/dist/ghBotServe.d.ts +21 -0
  52. package/dist/ghBotWebhook.d.ts +45 -0
  53. package/dist/hooks.d.ts +27 -0
  54. package/dist/i18n/id.d.ts +1 -0
  55. package/dist/i18n.d.ts +16 -0
  56. package/dist/integrationCli-Q2YPDTPG.js +685 -0
  57. package/dist/integrationCli.d.ts +9 -0
  58. package/dist/keybinds.d.ts +22 -0
  59. package/dist/login-FP3BB44A.js +16 -0
  60. package/dist/login.d.ts +19 -0
  61. package/dist/lsp.d.ts +47 -0
  62. package/dist/mcp/catalog.d.ts +14 -0
  63. package/dist/mcp/config.d.ts +36 -0
  64. package/dist/mcp/manager.d.ts +34 -0
  65. package/dist/mcp/oauth.d.ts +82 -0
  66. package/dist/{mcpCli-DZWQPTOS.js → mcpCli-SNBDUWJN.js} +42 -9
  67. package/dist/mcpCli.d.ts +3 -0
  68. package/dist/mcpServer/serve.d.ts +8 -0
  69. package/dist/mcpServer/server.d.ts +19 -0
  70. package/dist/models.d.ts +13 -0
  71. package/dist/modelsCli-CZ2HNGKR.js +36 -0
  72. package/dist/modelsCli.d.ts +15 -0
  73. package/dist/npmRunner-LU43GM3W.js +46 -0
  74. package/dist/npmRunner.d.ts +21 -0
  75. package/dist/oauthLogin-6FWQABJ7.js +210 -0
  76. package/dist/oauthLogin.d.ts +47 -0
  77. package/dist/permissions.d.ts +30 -0
  78. package/dist/pluginSpec.d.ts +25 -0
  79. package/dist/plugins.d.ts +45 -0
  80. package/dist/pluginsCli-LPIUUDWB.js +284 -0
  81. package/dist/pluginsCli.d.ts +16 -0
  82. package/dist/prCli-5IMV3VNQ.js +78 -0
  83. package/dist/prCli.d.ts +33 -0
  84. package/dist/presets.d.ts +8 -0
  85. package/dist/print.d.ts +14 -0
  86. package/dist/provider.d.ts +140 -0
  87. package/dist/providerCli-NMUFXAAS.js +15 -0
  88. package/dist/providerCli.d.ts +17 -0
  89. package/dist/providers.d.ts +6 -0
  90. package/dist/reasoning.d.ts +12 -0
  91. package/dist/repomap.d.ts +10 -0
  92. package/dist/sdk.d.ts +57 -0
  93. package/dist/sdk.js +5571 -0
  94. package/dist/serve-KWOECK5W.js +178 -0
  95. package/dist/serve-X2ZV4S5U.js +521 -0
  96. package/dist/serve.d.ts +37 -0
  97. package/dist/serveHeartbeat.d.ts +14 -0
  98. package/dist/serveProtocol.d.ts +47 -0
  99. package/dist/session-GKEXDJKZ.js +12 -0
  100. package/dist/session.d.ts +30 -0
  101. package/dist/setup-OV3NWQN5.js +24 -0
  102. package/dist/setup.d.ts +74 -0
  103. package/dist/slash/copy.d.ts +1 -0
  104. package/dist/slash/diff.d.ts +1 -0
  105. package/dist/slash/doctor.d.ts +18 -0
  106. package/dist/slash/export.d.ts +2 -0
  107. package/dist/slash/info.d.ts +45 -0
  108. package/dist/slash/memory.d.ts +10 -0
  109. package/dist/statsCli-CF3R7ATL.js +353 -0
  110. package/dist/statsCli.d.ts +62 -0
  111. package/dist/textToolCalls.d.ts +6 -0
  112. package/dist/thinking.d.ts +17 -0
  113. package/dist/tokenBudget.d.ts +22 -0
  114. package/dist/tools/bash.d.ts +52 -0
  115. package/dist/tools/diagnostics.d.ts +5 -0
  116. package/dist/tools/edit.d.ts +7 -0
  117. package/dist/tools/fetch.d.ts +41 -0
  118. package/dist/tools/glob.d.ts +5 -0
  119. package/dist/tools/globSafety.d.ts +7 -0
  120. package/dist/tools/grep.d.ts +13 -0
  121. package/dist/tools/ignore.d.ts +2 -0
  122. package/dist/tools/index.d.ts +12 -0
  123. package/dist/tools/memory.d.ts +13 -0
  124. package/dist/tools/paths.d.ts +2 -0
  125. package/dist/tools/plan.d.ts +10 -0
  126. package/dist/tools/read.d.ts +16 -0
  127. package/dist/tools/repomap.d.ts +2 -0
  128. package/dist/tools/sandbox.d.ts +12 -0
  129. package/dist/tools/shell.d.ts +18 -0
  130. package/dist/tools/skill.d.ts +3 -0
  131. package/dist/tools/task.d.ts +28 -0
  132. package/dist/tools/todo.d.ts +13 -0
  133. package/dist/tools/types.d.ts +52 -0
  134. package/dist/tools/websearch.d.ts +9 -0
  135. package/dist/tools/write.d.ts +5 -0
  136. package/dist/transferCli-YUFPI6AH.js +71 -0
  137. package/dist/transferCli.d.ts +23 -0
  138. package/dist/ui/App.d.ts +7 -0
  139. package/dist/ui/DiffView.d.ts +3 -0
  140. package/dist/ui/EditableText.d.ts +7 -0
  141. package/dist/ui/LinePrompt.d.ts +6 -0
  142. package/dist/ui/ListPicker.d.ts +11 -0
  143. package/dist/ui/Markdown.d.ts +8 -0
  144. package/dist/ui/McpMenu.d.ts +11 -0
  145. package/dist/ui/ModelPicker.d.ts +6 -0
  146. package/dist/ui/PermissionPrompt.d.ts +5 -0
  147. package/dist/ui/PlanApproval.d.ts +5 -0
  148. package/dist/ui/PromptInput.d.ts +18 -0
  149. package/dist/ui/ProviderMenu.d.ts +10 -0
  150. package/dist/ui/Spinner.d.ts +4 -0
  151. package/dist/ui/StatusBar.d.ts +9 -0
  152. package/dist/ui/TodoList.d.ts +4 -0
  153. package/dist/ui/ToolBlock.d.ts +14 -0
  154. package/dist/ui/complete.d.ts +1 -0
  155. package/dist/ui/focusReport.d.ts +1 -0
  156. package/dist/ui/index.d.ts +7 -0
  157. package/dist/ui/lineEdit.d.ts +42 -0
  158. package/dist/ui/replay.d.ts +4 -0
  159. package/dist/ui/table.d.ts +20 -0
  160. package/dist/ui/theme.d.ts +5 -0
  161. package/dist/ui/thinkingMouse.d.ts +33 -0
  162. package/dist/ui/transcript.d.ts +55 -0
  163. package/dist/ui/vim.d.ts +26 -0
  164. package/dist/ui-IVIFNUCC.js +2367 -0
  165. package/dist/update-TZ2G6KQ3.js +145 -0
  166. package/dist/update.d.ts +30 -0
  167. package/dist/verify.d.ts +16 -0
  168. package/dist/version.d.ts +1 -0
  169. package/dist/webBudget.d.ts +25 -0
  170. package/dist/worktree.d.ts +12 -0
  171. package/package.json +42 -8
  172. package/dist/args-JPVSGCGY.js +0 -12
  173. package/dist/chunk-2MGINW4O.js +0 -114
  174. package/dist/chunk-ELML4KVQ.js +0 -76
  175. package/dist/chunk-ISGBGFSU.js +0 -52
  176. package/dist/chunk-KV27KTOX.js +0 -254
  177. package/dist/chunk-U7GK73CK.js +0 -341
  178. package/dist/chunk-ZYCYTEKD.js +0 -96
  179. package/dist/integrationCli-BGT5UZU4.js +0 -223
  180. package/dist/login-6K32PIXV.js +0 -9
  181. package/dist/providerCli-Q7LRM2NP.js +0 -12
  182. package/dist/session-7UB77CEG.js +0 -9
  183. package/dist/ui-6GTQUJOE.js +0 -1415
@@ -0,0 +1,22 @@
1
+ export type KeybindAction = 'thinking' | 'toolOutput' | 'pasteImage';
2
+ export declare const KEYBIND_ACTIONS: KeybindAction[];
3
+ export declare const DEFAULT_KEYBINDS: Record<KeybindAction, string>;
4
+ export declare function defaultKeybinds(): Record<KeybindAction, Keybind>;
5
+ export interface Keybind {
6
+ /** The normalized spec, for display in notices and /help. */
7
+ spec: string;
8
+ ctrl: boolean;
9
+ meta: boolean;
10
+ /** Lowercase single letter. */
11
+ key: string;
12
+ }
13
+ /**
14
+ * Parses "ctrl+t" / "alt+x" / "ctrl+alt+o". A modifier is required: a bare letter
15
+ * would fire while the user types. Returns undefined for anything else so the
16
+ * caller can produce a localized ConfigError.
17
+ */
18
+ export declare function parseKeybind(raw: string): Keybind | undefined;
19
+ export declare function matchKeybind(kb: Keybind, input: string, key: {
20
+ ctrl?: boolean;
21
+ meta?: boolean;
22
+ }): boolean;
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ defaultLoginDeps,
4
+ readLine,
5
+ readSecret,
6
+ runLogin
7
+ } from "./chunk-BXQQCUAC.js";
8
+ import "./chunk-MFHCQQEN.js";
9
+ import "./chunk-FLQPE4S5.js";
10
+ import "./chunk-UZWJQF67.js";
11
+ export {
12
+ defaultLoginDeps,
13
+ readLine,
14
+ readSecret,
15
+ runLogin
16
+ };
@@ -0,0 +1,19 @@
1
+ export declare function readSecret(prompt: string): Promise<string>;
2
+ /** Prompt TANPA masking (kode otorisasi harus terlihat saat di-paste). Ctrl+C -> exit 130. */
3
+ export declare function readLine(prompt: string): Promise<string>;
4
+ import type { CliArgs } from './args';
5
+ import type { ABORT } from './oauthLogin';
6
+ export interface LoginDeps {
7
+ out(s: string): void;
8
+ err(s: string): void;
9
+ env: NodeJS.ProcessEnv;
10
+ isTTY: boolean;
11
+ open(url: string): void;
12
+ readLine(prompt: string): Promise<string | typeof ABORT>;
13
+ saveCredential(id: string, key: string): void;
14
+ removeCredential(id: string): boolean;
15
+ fetch: typeof fetch;
16
+ legacyAdd(providerId: string, cwd: string): Promise<number>;
17
+ }
18
+ export declare function defaultLoginDeps(): LoginDeps;
19
+ export declare function runLogin(providerId: string, cwd: string, args: CliArgs, deps: LoginDeps): Promise<number>;
package/dist/lsp.d.ts ADDED
@@ -0,0 +1,47 @@
1
+ export interface LspServer {
2
+ extensions: string[];
3
+ command: string;
4
+ args?: string[];
5
+ }
6
+ export interface LspDiagnostic {
7
+ line: number;
8
+ character: number;
9
+ severity: number;
10
+ message: string;
11
+ }
12
+ interface LspRawDiagnostic {
13
+ range?: {
14
+ start?: {
15
+ line?: number;
16
+ character?: number;
17
+ };
18
+ };
19
+ severity?: number;
20
+ message?: string;
21
+ }
22
+ /** The JSON-RPC messages this one-shot client cares about. */
23
+ export interface LspMessage {
24
+ id?: number;
25
+ method?: string;
26
+ result?: unknown;
27
+ params?: {
28
+ uri?: string;
29
+ diagnostics?: LspRawDiagnostic[];
30
+ };
31
+ }
32
+ export declare function encodeLsp(msg: unknown): Buffer;
33
+ /** Content-Length framed JSON-RPC reader; survives messages split across chunks. */
34
+ export declare function createLspParser(onMessage: (msg: LspMessage) => void): {
35
+ push(chunk: Buffer): void;
36
+ };
37
+ /**
38
+ * Open one file with one LSP server, wait for its first publishDiagnostics (or the timeout),
39
+ * then shut it down. A one-shot client on purpose: no long-lived servers to manage yet.
40
+ */
41
+ export declare function getDiagnostics(opts: {
42
+ server: LspServer;
43
+ cwd: string;
44
+ file: string;
45
+ timeoutMs?: number;
46
+ }): Promise<LspDiagnostic[]>;
47
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { McpServerConfig } from './config';
2
+ export interface CatalogInput {
3
+ key: string;
4
+ label: string;
5
+ secret?: boolean;
6
+ }
7
+ export interface CatalogEntry {
8
+ name: string;
9
+ description: string;
10
+ config: McpServerConfig;
11
+ inputs?: CatalogInput[];
12
+ }
13
+ export declare const CATALOG: CatalogEntry[];
14
+ export declare function fillTemplate(config: McpServerConfig, values: Record<string, string>): McpServerConfig;
@@ -0,0 +1,36 @@
1
+ export type McpServerConfig = {
2
+ type?: 'stdio';
3
+ command: string;
4
+ args?: string[];
5
+ env?: Record<string, string>;
6
+ } | {
7
+ type: 'http';
8
+ url: string;
9
+ headers?: Record<string, string>;
10
+ auth?: 'oauth';
11
+ };
12
+ export interface McpServerSpec {
13
+ name: string;
14
+ config: McpServerConfig;
15
+ source: 'global' | 'project';
16
+ }
17
+ /**
18
+ * Claude Code-style environment expansion at connect time: ${VAR} reads from the
19
+ * parent environment, ${VAR:-default} falls back when unset, and an unset variable
20
+ * without a default stays literal. This lets a server pull a secret from the parent
21
+ * env ("API_KEY": "${MY_KEY}") without pasting the value into mcp.json, while the
22
+ * stdio child still only receives the whitelist plus the resolved config env.
23
+ */
24
+ export declare function expandEnvVars(config: McpServerConfig, env: NodeJS.ProcessEnv): McpServerConfig;
25
+ export declare const globalMcpPath: (home: string) => string;
26
+ export declare const projectMcpPath: (cwd: string) => string;
27
+ export declare function readMcpFile(path: string): Record<string, McpServerConfig>;
28
+ export declare function addGlobalServer(home: string, name: string, config: McpServerConfig): void;
29
+ export declare function removeGlobalServer(home: string, name: string): void;
30
+ export declare function projectTrust(home: string, cwd: string, name: string, config: McpServerConfig): boolean | undefined;
31
+ export declare function setProjectTrust(home: string, cwd: string, name: string, allowed: boolean, config: McpServerConfig): void;
32
+ /** Global servers always; project servers only after a recorded yes. A project server never shadows a global one. */
33
+ export declare function serversToStart(home: string, cwd: string): {
34
+ start: McpServerSpec[];
35
+ needTrust: McpServerSpec[];
36
+ };
@@ -0,0 +1,34 @@
1
+ import type { Tool } from '../tools/types';
2
+ import type { McpServerSpec } from './config';
3
+ /** Safe env for spawned MCP servers: whitelist from the parent + the server's own config.env. */
4
+ export declare function mcpChildEnv(extra?: Record<string, string>): Record<string, string>;
5
+ export interface McpServerState {
6
+ name: string;
7
+ source: 'global' | 'project';
8
+ status: 'starting' | 'ready' | 'error';
9
+ error?: string;
10
+ tools: number;
11
+ }
12
+ /** OpenAI function names: [A-Za-z0-9_-], max 64 chars, unique. */
13
+ export declare function mcpToolName(server: string, tool: string, taken: Set<string>): string;
14
+ export declare class McpManager {
15
+ private readonly opts;
16
+ private readonly servers;
17
+ private readonly taken;
18
+ constructor(opts?: {
19
+ connectTimeoutMs?: number;
20
+ onChange?: () => void;
21
+ onToolsRemoved?: (names: string[]) => void;
22
+ /** Config home for the OAuth token store; enables authProvider on http servers. */
23
+ home?: string;
24
+ /** Overrides how the OAuth consent page is opened (tests inject a fake browser). */
25
+ open?: (url: URL) => void | Promise<void>;
26
+ });
27
+ start(specs: McpServerSpec[]): Promise<void>;
28
+ add(spec: McpServerSpec): Promise<void>;
29
+ private wrap;
30
+ remove(name: string): Promise<void>;
31
+ tools(): Tool[];
32
+ states(): McpServerState[];
33
+ stop(): Promise<void>;
34
+ }
@@ -0,0 +1,82 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { type OAuthClientProvider, type OAuthDiscoveryState } from '@modelcontextprotocol/sdk/client/auth.js';
3
+ import type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
4
+ import type { FetchLike } from '@modelcontextprotocol/sdk/shared/transport.js';
5
+ import type { McpServerConfig } from './config';
6
+ export interface OAuthStorage {
7
+ client?: OAuthClientInformationMixed;
8
+ tokens?: OAuthTokens;
9
+ codeVerifier?: string;
10
+ discovery?: OAuthDiscoveryState;
11
+ }
12
+ export type OAuthStore = Record<string, OAuthStorage>;
13
+ export declare const oauthStorePath: (home: string) => string;
14
+ export declare function hasStoredTokens(home: string, serverUrl: string): boolean;
15
+ export declare function clearTokens(home: string, serverUrl: string): boolean;
16
+ /**
17
+ * The browser is opened through a direct argv hand-off: on Windows `cmd /c start` re-parses
18
+ * its own command line, so an authorization URL from the MCP server could smuggle a second
19
+ * command with `&`. rundll32 plus `shell: false` never gives the URL to a shell, and only
20
+ * http(s) is ever opened (no `file:`/custom protocol handlers).
21
+ */
22
+ export declare function openCommand(url: URL, platform: NodeJS.Platform): {
23
+ command: string;
24
+ args: string[];
25
+ } | undefined;
26
+ /** Opens a URL in the user's browser (best effort; callers should also print the URL). */
27
+ export declare function defaultOpen(url: URL, deps?: {
28
+ platform?: NodeJS.Platform;
29
+ spawn?: typeof spawn;
30
+ }): void;
31
+ export interface FileOAuthProviderOptions {
32
+ home: string;
33
+ serverUrl: string;
34
+ redirectUrl?: string | URL;
35
+ open?: (url: URL) => void | Promise<void>;
36
+ }
37
+ /**
38
+ * File-backed OAuthClientProvider: client registration, tokens, PKCE verifier and
39
+ * discovery state per MCP server URL, stored in ~/.bccli/mcp-oauth.json (mode 600).
40
+ */
41
+ export declare class FileOAuthProvider implements OAuthClientProvider {
42
+ private readonly opts;
43
+ constructor(opts: FileOAuthProviderOptions);
44
+ /**
45
+ * Always defined: MCP SDK treats a missing redirectUrl as a non-interactive
46
+ * (client_credentials) flow and would try a token exchange without a code.
47
+ */
48
+ get redirectUrl(): string | URL;
49
+ get clientMetadata(): OAuthClientMetadata;
50
+ private entry;
51
+ private patch;
52
+ clientInformation(): OAuthClientInformationMixed | undefined;
53
+ saveClientInformation(clientInformation: OAuthClientInformationMixed): void;
54
+ tokens(): OAuthTokens | undefined;
55
+ saveTokens(tokens: OAuthTokens): void;
56
+ saveCodeVerifier(codeVerifier: string): void;
57
+ codeVerifier(): string;
58
+ redirectToAuthorization(authorizationUrl: URL): void | Promise<void>;
59
+ saveDiscoveryState(state: OAuthDiscoveryState): void;
60
+ discoveryState(): OAuthDiscoveryState | undefined;
61
+ invalidateCredentials(scope: 'all' | 'client' | 'tokens' | 'verifier' | 'discovery'): void;
62
+ }
63
+ /** Parses the loopback callback URL; an OAuth error response throws. */
64
+ export declare function parseCallback(input: string | URL): {
65
+ code: string;
66
+ state?: string;
67
+ };
68
+ /**
69
+ * Runs the MCP OAuth 2.1 (PKCE) flow for one http server: starts a loopback callback
70
+ * server, hands the SDK auth() orchestrator the FileOAuthProvider, opens the browser,
71
+ * waits for the code, exchanges it, and stores the tokens. Throws on deny/failure.
72
+ */
73
+ export declare function authorizeMcpServer(spec: {
74
+ name: string;
75
+ config: Extract<McpServerConfig, {
76
+ type?: 'http';
77
+ }>;
78
+ }, deps: {
79
+ home: string;
80
+ open?: (url: URL) => void | Promise<void>;
81
+ fetchFn?: FetchLike;
82
+ }): Promise<void>;
@@ -2,21 +2,32 @@
2
2
  import {
3
3
  CATALOG,
4
4
  fillTemplate
5
- } from "./chunk-DX7CZTBB.js";
5
+ } from "./chunk-WI22M2ID.js";
6
+ import {
7
+ authorizeMcpServer,
8
+ clearTokens
9
+ } from "./chunk-MFHCQQEN.js";
6
10
  import {
7
11
  addGlobalServer,
8
12
  globalMcpPath,
9
13
  readMcpFile,
10
14
  removeGlobalServer
11
- } from "./chunk-BFZXRKW5.js";
15
+ } from "./chunk-24JN75FZ.js";
12
16
  import {
13
17
  bccliHome
14
- } from "./chunk-2MGINW4O.js";
18
+ } from "./chunk-FLQPE4S5.js";
19
+ import {
20
+ t
21
+ } from "./chunk-UZWJQF67.js";
15
22
 
16
23
  // src/mcpCli.ts
17
24
  async function runMcpCommand(args, deps) {
18
25
  const home = bccliHome(deps.env);
19
26
  const [action = "list", name] = args.subArgs;
27
+ if (action === "serve") {
28
+ const { runMcpServe } = await import("./serve-KWOECK5W.js");
29
+ return runMcpServe(args, deps);
30
+ }
20
31
  const installed = readMcpFile(globalMcpPath(home));
21
32
  if (action === "list") {
22
33
  for (const entry2 of CATALOG) deps.out(`${installed[entry2.name] ? "\u2713" : "\u25CB"} ${entry2.name.padEnd(12)} ${entry2.description}`);
@@ -24,26 +35,48 @@ async function runMcpCommand(args, deps) {
24
35
  return 0;
25
36
  }
26
37
  if (!name) {
27
- deps.err(`Pemakaian: bccli mcp ${action} <nama>`);
38
+ deps.err(t("Usage: bccli mcp {action} <name>", { action }));
28
39
  return 1;
29
40
  }
30
41
  if (action === "remove") {
31
42
  removeGlobalServer(home, name);
32
- deps.out(`${name} dihapus.`);
43
+ deps.out(t("{name} removed.", { name }));
33
44
  return 0;
34
45
  }
46
+ if (action === "auth" || action === "logout") {
47
+ const config = installed[name];
48
+ if (config?.type !== "http") {
49
+ deps.err(
50
+ t("{name} is not an installed HTTP MCP server. Add it first with: bccli mcp add {name} --url <url>", { name })
51
+ );
52
+ return 1;
53
+ }
54
+ if (action === "logout") {
55
+ const removed = clearTokens(home, config.url);
56
+ deps.out(removed ? t("{name} logged out.", { name }) : t("{name} has no stored OAuth tokens.", { name }));
57
+ return 0;
58
+ }
59
+ try {
60
+ await authorizeMcpServer({ name, config }, { home });
61
+ deps.out(t("{name} authorized. Active in the next bccli session.", { name }));
62
+ return 0;
63
+ } catch (error) {
64
+ deps.err(t("OAuth login failed for {name}: {reason}", { name, reason: error.message }));
65
+ return 1;
66
+ }
67
+ }
35
68
  if (action !== "add") {
36
- deps.err(`Aksi tidak dikenal: ${action}. Pakai list, add, atau remove.`);
69
+ deps.err(t("Unknown action: {action}. Use list, add, remove, auth, logout, or serve.", { action }));
37
70
  return 1;
38
71
  }
39
72
  if (args.url) {
40
73
  addGlobalServer(home, name, { type: "http", url: args.url });
41
- deps.out(`${name} terpasang (${args.url}).`);
74
+ deps.out(t("{name} installed ({url}).", { name, url: args.url }));
42
75
  return 0;
43
76
  }
44
77
  const entry = CATALOG.find((c) => c.name === name);
45
78
  if (!entry) {
46
- deps.err(`${name} tidak ada di katalog. Untuk server remote lain pakai: bccli mcp add ${name} --url <url>`);
79
+ deps.err(t("{name} is not in the catalog. For another remote server use: bccli mcp add {name} --url <url>", { name }));
47
80
  return 1;
48
81
  }
49
82
  const values = Object.fromEntries(args.values.map((v) => [v.slice(0, v.indexOf("=")), v.slice(v.indexOf("=") + 1)]));
@@ -57,7 +90,7 @@ async function runMcpCommand(args, deps) {
57
90
  deps.err(`${error.message}${hint ? `. Contoh: bccli mcp add ${name} ${hint}` : ""}`);
58
91
  return 1;
59
92
  }
60
- deps.out(`${name} terpasang. Aktif di sesi bccli berikutnya.`);
93
+ deps.out(t("{name} installed. Active in the next bccli session.", { name }));
61
94
  return 0;
62
95
  }
63
96
  export {
@@ -0,0 +1,3 @@
1
+ import type { CliArgs } from './args';
2
+ import type { CliDeps } from './providerCli';
3
+ export declare function runMcpCommand(args: CliArgs, deps: CliDeps): Promise<number>;
@@ -0,0 +1,8 @@
1
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
2
+ import type { CliArgs } from '../args';
3
+ import type { CliDeps } from '../providerCli';
4
+ export interface McpServeDeps extends CliDeps {
5
+ /** Test seam: replaces the stdio transport (pass an InMemoryTransport half). */
6
+ transport?: Transport;
7
+ }
8
+ export declare function runMcpServe(args: CliArgs, deps: McpServeDeps): Promise<number>;
@@ -0,0 +1,19 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { type FetchToolOptions } from '../tools/fetch';
3
+ export interface McpServerDeps {
4
+ /** BotConnector API base, e.g. https://api.botconnector.id/v1 (no trailing slash). */
5
+ baseUrl: string;
6
+ /** Bearer key for paid endpoints (bc_chat); never logged or echoed. */
7
+ apiKey: string;
8
+ /** Default model id for bc_chat (provider prefix already stripped). */
9
+ defaultModel: string;
10
+ /** Injectable for tests; defaults to global fetch. */
11
+ fetchFn?: typeof fetch;
12
+ /** Injectable clock for the catalog cache; defaults to Date.now. */
13
+ now?: () => number;
14
+ /** Keenable endpoint for bc_search fallback; undefined = the public keyless endpoint. */
15
+ keenableURL?: string;
16
+ /** Passed to createFetchTool (DNS lookup / page fetch injection for tests). */
17
+ fetchTool?: FetchToolOptions;
18
+ }
19
+ export declare function createMcpServer(deps: McpServerDeps): McpServer;
@@ -0,0 +1,13 @@
1
+ import { type Config } from './config';
2
+ export interface ModelGroup {
3
+ providerId: string;
4
+ providerName: string;
5
+ models: string[];
6
+ error?: string;
7
+ }
8
+ export declare function listAllModels(config: Config, env?: NodeJS.ProcessEnv, opts?: {
9
+ fetch?: typeof fetch;
10
+ timeoutMs?: number;
11
+ only?: string;
12
+ keyOverride?: string;
13
+ }): Promise<ModelGroup[]>;
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ listAllModels
4
+ } from "./chunk-75BECX4F.js";
5
+ import "./chunk-JHPGOAXU.js";
6
+ import "./chunk-WNACAUDK.js";
7
+ import "./chunk-BLOYFIAD.js";
8
+ import {
9
+ loadConfig,
10
+ resolveModel
11
+ } from "./chunk-FLQPE4S5.js";
12
+ import {
13
+ t
14
+ } from "./chunk-UZWJQF67.js";
15
+
16
+ // src/modelsCli.ts
17
+ async function runModelsCommand(args, deps) {
18
+ const config = loadConfig(deps.cwd, deps.env);
19
+ const arg = (args.subArgs[0] ?? "").trim();
20
+ const providerId = arg ? arg.split("/")[0] : resolveModel(config, args.model ?? config.model, deps.env).providerId;
21
+ if (!Object.hasOwn(config.providers, providerId)) {
22
+ deps.err(t('Provider "{id}" is not in the config. Available: {list}', { id: providerId, list: Object.keys(config.providers).join(", ") }));
23
+ return 1;
24
+ }
25
+ const groups = await listAllModels(config, deps.env, { fetch: deps.fetch, only: providerId });
26
+ const group = groups.find((g) => g.providerId === providerId);
27
+ if (!group || group.error) {
28
+ deps.err(`${providerId}: ${group?.error ?? t("could not be reached")}`);
29
+ return 1;
30
+ }
31
+ deps.out(group.models.map((m) => `${providerId}/${m}`).join("\n"));
32
+ return 0;
33
+ }
34
+ export {
35
+ runModelsCommand
36
+ };
@@ -0,0 +1,15 @@
1
+ import type { CliArgs } from './args';
2
+ export interface ModelsDeps {
3
+ env: NodeJS.ProcessEnv;
4
+ cwd: string;
5
+ out(line: string): void;
6
+ err(line: string): void;
7
+ fetch?: typeof fetch;
8
+ }
9
+ /**
10
+ * `bccli models [provider|provider/model]`.
11
+ * No argument keeps the old behavior: list the models of the active provider.
12
+ * A provider id (or a full model ref, whose provider part is used) lists exactly
13
+ * that provider, even when it is keyless or comes from the project config.
14
+ */
15
+ export declare function runModelsCommand(args: CliArgs, deps: ModelsDeps): Promise<number>;
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/npmRunner.ts
4
+ import { spawnSync } from "child_process";
5
+ import { existsSync } from "fs";
6
+ import { delimiter, posix, win32 } from "path";
7
+ function findNpmCli(platform, env, exists, execPath) {
8
+ const path = platform === "win32" ? win32 : posix;
9
+ const sibling = path.join(path.dirname(execPath), "node_modules", "npm", "bin", "npm-cli.js");
10
+ if (exists(sibling)) return sibling;
11
+ const sep = platform === "win32" ? ";" : delimiter;
12
+ for (const dir of (env.PATH ?? "").split(sep)) {
13
+ if (!dir) continue;
14
+ const shim = path.join(dir, platform === "win32" ? "npm.cmd" : "npm");
15
+ if (!exists(shim)) continue;
16
+ const cli = path.join(dir, "node_modules", "npm", "bin", "npm-cli.js");
17
+ if (exists(cli)) return cli;
18
+ }
19
+ return null;
20
+ }
21
+ var text = (v) => typeof v === "string" ? v : v ? v.toString() : "";
22
+ function toResult(r) {
23
+ return {
24
+ code: r.status ?? 1,
25
+ stderr: text(r.stderr) || (r.error ? r.error.message : ""),
26
+ stdout: text(r.stdout)
27
+ };
28
+ }
29
+ function runNpmSync(prefix, argv, opts = {}) {
30
+ const platform = opts.platform ?? process.platform;
31
+ const spawn = opts.spawn ?? spawnSync;
32
+ const env = opts.env ?? process.env;
33
+ const exists = opts.exists ?? existsSync;
34
+ const execPath = opts.execPath ?? process.execPath;
35
+ if (platform !== "win32") {
36
+ return toResult(spawn("npm", ["--prefix", prefix, ...argv], { encoding: "utf8", env }));
37
+ }
38
+ const cli = findNpmCli(platform, env, exists, execPath);
39
+ if (!cli) {
40
+ return { code: 1, stderr: "npm CLI not found (looked beside the node executable and on PATH)" };
41
+ }
42
+ return toResult(spawn(execPath, [cli, "--prefix", prefix, ...argv], { encoding: "utf8", env }));
43
+ }
44
+ export {
45
+ runNpmSync
46
+ };
@@ -0,0 +1,21 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ /**
3
+ * Synchronous npm runner. On Windows it NEVER goes through cmd.exe: npm's own
4
+ * npm.cmd is just a shim around `node …\node_modules\npm\bin\npm-cli.js`, so we
5
+ * invoke that script with process.execPath and pass every argument as plain
6
+ * argv. Shell metacharacters in the prefix path (& % ( ) spaces, …) therefore
7
+ * need no quoting at all — nothing is ever joined into a command line.
8
+ */
9
+ export interface NpmRunResult {
10
+ code: number;
11
+ stderr: string;
12
+ stdout?: string;
13
+ }
14
+ export interface RunNpmOptions {
15
+ platform?: NodeJS.Platform;
16
+ spawn?: typeof spawnSync;
17
+ env?: NodeJS.ProcessEnv;
18
+ exists?: (path: string) => boolean;
19
+ execPath?: string;
20
+ }
21
+ export declare function runNpmSync(prefix: string, argv: string[], opts?: RunNpmOptions): NpmRunResult;