@botconnector/bccli 0.5.0 → 0.5.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.
- package/LICENSE +21 -203
- package/{legacy/dist/chunk-XP5MTJN2.js → dist/chunk-6YRTPXGY.js} +1 -1
- package/{legacy/dist → dist}/cli.js +22 -4
- package/dist/onboarding.d.ts +6 -0
- package/{legacy/dist/serve-HUQNVOSP.js → dist/serve-R2IHP26A.js} +1 -1
- package/{legacy/dist/update-5V425FIK.js → dist/update-XC3B6SJC.js} +1 -1
- package/package.json +51 -47
- package/THIRD_PARTY_NOTICES.md +0 -9
- package/branding.mjs +0 -347
- package/cli.mjs +0 -128
- package/core.mjs +0 -260
- package/credentials.mjs +0 -52
- package/gateway.mjs +0 -2
- package/legacy/LICENSE +0 -21
- package/legacy/package.json +0 -77
- package/legacy-compat.mjs +0 -42
- package/model-command.mjs +0 -61
- package/provider-cli.mjs +0 -76
- package/providers.mjs +0 -179
- package/proxy.mjs +0 -242
- package/startup-menu.mjs +0 -121
- /package/{legacy/README.en.md → README.en.md} +0 -0
- /package/{legacy/README.md → README.md} +0 -0
- /package/{legacy/dist → dist}/abort.d.ts +0 -0
- /package/{legacy/dist → dist}/acp-HWHF25KU.js +0 -0
- /package/{legacy/dist → dist}/acp.d.ts +0 -0
- /package/{legacy/dist → dist}/agent.d.ts +0 -0
- /package/{legacy/dist → dist}/agents.d.ts +0 -0
- /package/{legacy/dist → dist}/args-XA77XUMD.js +0 -0
- /package/{legacy/dist → dist}/args.d.ts +0 -0
- /package/{legacy/dist → dist}/budget.d.ts +0 -0
- /package/{legacy/dist → dist}/checkpoints.d.ts +0 -0
- /package/{legacy/dist → dist}/chunk-2IP5F3EK.js +0 -0
- /package/{legacy/dist → dist}/chunk-5CVHTYBQ.js +0 -0
- /package/{legacy/dist → dist}/chunk-6LO6YRDY.js +0 -0
- /package/{legacy/dist → dist}/chunk-6PJRWKVI.js +0 -0
- /package/{legacy/dist → dist}/chunk-7OTFZK4B.js +0 -0
- /package/{legacy/dist → dist}/chunk-7U7CMKKI.js +0 -0
- /package/{legacy/dist → dist}/chunk-A3NBWIEQ.js +0 -0
- /package/{legacy/dist → dist}/chunk-FY543EQW.js +0 -0
- /package/{legacy/dist → dist}/chunk-IDZLHEVL.js +0 -0
- /package/{legacy/dist → dist}/chunk-IF5RNXBI.js +0 -0
- /package/{legacy/dist → dist}/chunk-M5T4AM4I.js +0 -0
- /package/{legacy/dist → dist}/chunk-NGFWBVHD.js +0 -0
- /package/{legacy/dist → dist}/chunk-OCEQ2TRJ.js +0 -0
- /package/{legacy/dist → dist}/chunk-OK2USAXX.js +0 -0
- /package/{legacy/dist → dist}/chunk-PSO7R5AD.js +0 -0
- /package/{legacy/dist → dist}/chunk-RLSQAZBT.js +0 -0
- /package/{legacy/dist → dist}/chunk-VPFCIUC6.js +0 -0
- /package/{legacy/dist → dist}/chunk-YGBTNDPK.js +0 -0
- /package/{legacy/dist → dist}/chunk-YYTFJUO2.js +0 -0
- /package/{legacy/dist → dist}/chunk-ZXWRLN7E.js +0 -0
- /package/{legacy/dist → dist}/cli.d.ts +0 -0
- /package/{legacy/dist → dist}/clipboardImage.d.ts +0 -0
- /package/{legacy/dist → dist}/commands.d.ts +0 -0
- /package/{legacy/dist → dist}/completion-IRVEVW6H.js +0 -0
- /package/{legacy/dist → dist}/completion.d.ts +0 -0
- /package/{legacy/dist → dist}/config-OVWCUVY7.js +0 -0
- /package/{legacy/dist → dist}/config-S3CZUIBB.js +0 -0
- /package/{legacy/dist → dist}/config.d.ts +0 -0
- /package/{legacy/dist → dist}/context.d.ts +0 -0
- /package/{legacy/dist → dist}/contextWindow.d.ts +0 -0
- /package/{legacy/dist → dist}/diff.d.ts +0 -0
- /package/{legacy/dist → dist}/exit.d.ts +0 -0
- /package/{legacy/dist → dist}/extensions.d.ts +0 -0
- /package/{legacy/dist → dist}/ghBotCli-FYKJDJOD.js +0 -0
- /package/{legacy/dist → dist}/ghBotCli.d.ts +0 -0
- /package/{legacy/dist → dist}/ghBotDispatch.d.ts +0 -0
- /package/{legacy/dist → dist}/ghBotRunner.d.ts +0 -0
- /package/{legacy/dist → dist}/ghBotServe.d.ts +0 -0
- /package/{legacy/dist → dist}/ghBotWebhook.d.ts +0 -0
- /package/{legacy/dist → dist}/hooks.d.ts +0 -0
- /package/{legacy/dist → dist}/i18n/id.d.ts +0 -0
- /package/{legacy/dist → dist}/i18n.d.ts +0 -0
- /package/{legacy/dist → dist}/integrationCli-GY73S2K7.js +0 -0
- /package/{legacy/dist → dist}/integrationCli.d.ts +0 -0
- /package/{legacy/dist → dist}/keybinds.d.ts +0 -0
- /package/{legacy/dist → dist}/login-KSN63EM4.js +0 -0
- /package/{legacy/dist → dist}/login.d.ts +0 -0
- /package/{legacy/dist → dist}/lsp.d.ts +0 -0
- /package/{legacy/dist → dist}/mcp/catalog.d.ts +0 -0
- /package/{legacy/dist → dist}/mcp/config.d.ts +0 -0
- /package/{legacy/dist → dist}/mcp/manager.d.ts +0 -0
- /package/{legacy/dist → dist}/mcp/oauth.d.ts +0 -0
- /package/{legacy/dist → dist}/mcpCli-VWSCCDWT.js +0 -0
- /package/{legacy/dist → dist}/mcpCli.d.ts +0 -0
- /package/{legacy/dist → dist}/mcpServer/serve.d.ts +0 -0
- /package/{legacy/dist → dist}/mcpServer/server.d.ts +0 -0
- /package/{legacy/dist → dist}/models.d.ts +0 -0
- /package/{legacy/dist → dist}/modelsCli-4Q6KFWV2.js +0 -0
- /package/{legacy/dist → dist}/modelsCli.d.ts +0 -0
- /package/{legacy/dist → dist}/npmRunner-LU43GM3W.js +0 -0
- /package/{legacy/dist → dist}/npmRunner.d.ts +0 -0
- /package/{legacy/dist → dist}/oauthLogin-JWXQZTMZ.js +0 -0
- /package/{legacy/dist → dist}/oauthLogin.d.ts +0 -0
- /package/{legacy/dist → dist}/permissions.d.ts +0 -0
- /package/{legacy/dist → dist}/pluginSpec.d.ts +0 -0
- /package/{legacy/dist → dist}/plugins.d.ts +0 -0
- /package/{legacy/dist → dist}/pluginsCli-7XWDLJEL.js +0 -0
- /package/{legacy/dist → dist}/pluginsCli.d.ts +0 -0
- /package/{legacy/dist → dist}/prCli-FH7N26D4.js +0 -0
- /package/{legacy/dist → dist}/prCli.d.ts +0 -0
- /package/{legacy/dist → dist}/presets.d.ts +0 -0
- /package/{legacy/dist → dist}/print.d.ts +0 -0
- /package/{legacy/dist → dist}/provider.d.ts +0 -0
- /package/{legacy/dist → dist}/providerCli-YMG4G56R.js +0 -0
- /package/{legacy/dist → dist}/providerCli.d.ts +0 -0
- /package/{legacy/dist → dist}/providers.d.ts +0 -0
- /package/{legacy/dist → dist}/reasoning.d.ts +0 -0
- /package/{legacy/dist → dist}/repomap.d.ts +0 -0
- /package/{legacy/dist → dist}/sdk.d.ts +0 -0
- /package/{legacy/dist → dist}/sdk.js +0 -0
- /package/{legacy/dist → dist}/serve-HSFF6MGB.js +0 -0
- /package/{legacy/dist → dist}/serve.d.ts +0 -0
- /package/{legacy/dist → dist}/serveHeartbeat.d.ts +0 -0
- /package/{legacy/dist → dist}/serveProtocol.d.ts +0 -0
- /package/{legacy/dist → dist}/session-YM36TGU7.js +0 -0
- /package/{legacy/dist → dist}/session.d.ts +0 -0
- /package/{legacy/dist → dist}/setup-3YB6EKYX.js +0 -0
- /package/{legacy/dist → dist}/setup.d.ts +0 -0
- /package/{legacy/dist → dist}/slash/copy.d.ts +0 -0
- /package/{legacy/dist → dist}/slash/diff.d.ts +0 -0
- /package/{legacy/dist → dist}/slash/doctor.d.ts +0 -0
- /package/{legacy/dist → dist}/slash/export.d.ts +0 -0
- /package/{legacy/dist → dist}/slash/info.d.ts +0 -0
- /package/{legacy/dist → dist}/slash/memory.d.ts +0 -0
- /package/{legacy/dist → dist}/statsCli-I4TSDU3X.js +0 -0
- /package/{legacy/dist → dist}/statsCli.d.ts +0 -0
- /package/{legacy/dist → dist}/textToolCalls.d.ts +0 -0
- /package/{legacy/dist → dist}/thinking.d.ts +0 -0
- /package/{legacy/dist → dist}/tokenBudget.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/bash.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/diagnostics.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/edit.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/fetch.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/glob.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/globSafety.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/grep.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/ignore.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/index.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/memory.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/paths.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/plan.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/read.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/repomap.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/sandbox.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/shell.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/skill.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/task.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/todo.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/types.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/websearch.d.ts +0 -0
- /package/{legacy/dist → dist}/tools/write.d.ts +0 -0
- /package/{legacy/dist → dist}/transferCli-3B4LMOYI.js +0 -0
- /package/{legacy/dist → dist}/transferCli.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/App.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/DiffView.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/EditableText.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/LinePrompt.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/ListPicker.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/Markdown.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/McpMenu.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/ModelPicker.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/PermissionPrompt.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/PlanApproval.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/PromptInput.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/ProviderMenu.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/Spinner.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/StatusBar.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/TodoList.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/ToolBlock.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/complete.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/index.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/lineEdit.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/liveCap.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/markdownLayout.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/replay.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/stdinFilter.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/table.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/theme.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/thinkingMouse.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/transcript.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/tty.d.ts +0 -0
- /package/{legacy/dist → dist}/ui/vim.d.ts +0 -0
- /package/{legacy/dist → dist}/ui-TAZMRXRI.js +0 -0
- /package/{legacy/dist → dist}/update.d.ts +0 -0
- /package/{legacy/dist → dist}/verify.d.ts +0 -0
- /package/{legacy/dist → dist}/version.d.ts +0 -0
- /package/{legacy/dist → dist}/webBudget.d.ts +0 -0
- /package/{legacy/dist → dist}/worktree.d.ts +0 -0
package/branding.mjs
DELETED
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
// BCCLI white-label view overlay for the pinned upstream Qwen package.
|
|
2
|
-
// Never mutate the original npm dependency or weaken --bare isolation.
|
|
3
|
-
import { createHash } from 'node:crypto'
|
|
4
|
-
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'
|
|
5
|
-
import { basename, dirname, join } from 'node:path'
|
|
6
|
-
import { BCCLI_MODEL_COMMAND } from './model-command.mjs'
|
|
7
|
-
|
|
8
|
-
const VERSION = '0.26.3'
|
|
9
|
-
const SOURCE_HASHES = Object.freeze({
|
|
10
|
-
'chunks/chunk-OYUATJK2.js': '3fa61c12bc1cba19d70151381519be337b99e2e60dac8edf6d066107a8419a1d',
|
|
11
|
-
'chunks/startInteractiveUI-CECFAXVK.js': 'd9acfeb1105032c9edccf223acfc6a8384256099883303c1622b12d92eea0b83',
|
|
12
|
-
'chunks/start-opentui-ui-Q34XCEMN.js': 'e5a8d1ff1ce494f6df26b03023daf2b930cb093ebfbfbcf9e2bcd3b349e6f107',
|
|
13
|
-
'chunks/chunk-OV3EBH6J.js': '3b20ea65e93e6ee00625f9d86906c3d28c45529b4b4dbe72dc050bdae3904505',
|
|
14
|
-
'chunks/chunk-W3YCOEIP.js': '02828393f6e477a7f36cecff876a6af2d36ece3eb838fceb096d9245eb7fc5f7',
|
|
15
|
-
'chunks/chunk-7L4WTOM2.js': '4d8053c956cc7881b7f87ae2c0e96bf1adc942a37ac37de3d76eaeb9367041fc',
|
|
16
|
-
'chunks/chunk-QUFSNRKR.js': 'f52e1917c7956b02208b39982bbf7b45fb52c294418ebd93f7f2f0677c1aaa2d',
|
|
17
|
-
'chunks/chunk-2PLSL3VQ.js': 'f475f043f1ab8314a64699ebb45e43026bb1a1fe65f1ac259f1898afb8a6c5d9',
|
|
18
|
-
'chunks/chunk-ERV2ECV3.js': '7d2511a8317ee2c44edd2fd62b43966b9acfbfaac79175cd0cc9fb9ed42051c6',
|
|
19
|
-
'chunks/server-SJNWHHV4.js': '42ceeddc69dda95fbaac276cbd94e99432892305d169d248e760c9d94aab6eaf',
|
|
20
|
-
})
|
|
21
|
-
const BRAND_REVISION = 'bccli-new-20261030-neutral-identity-v3'
|
|
22
|
-
// Deliberately not Qwen's blue→purple→rose gradient. BotConnector-facing
|
|
23
|
-
// coding CLI uses a distinct teal→green→amber palette in dark/light themes.
|
|
24
|
-
export const BCCLI_COLORS = Object.freeze(['#00AFA0', '#22C55E', '#EAB308'])
|
|
25
|
-
const BCCLI_ASCII = [
|
|
26
|
-
'',
|
|
27
|
-
'██████╗ ██████╗ ██████╗██╗ ██╗',
|
|
28
|
-
'██╔══██╗██╔════╝ ██╔════╝██║ ██║',
|
|
29
|
-
'██████╔╝██║ ██║ ██║ ██║',
|
|
30
|
-
'██╔══██╗██║ ██║ ██║ ██║',
|
|
31
|
-
'██████╔╝╚██████╗ ╚██████╗███████╗██║',
|
|
32
|
-
'╚═════╝ ╚═════╝ ╚═════╝╚══════╝╚═╝',
|
|
33
|
-
'',
|
|
34
|
-
].join('\n')
|
|
35
|
-
|
|
36
|
-
const digest = (value) => createHash('sha256').update(value).digest('hex')
|
|
37
|
-
|
|
38
|
-
function replaceExactly(text, oldValue, newValue, expectedCount, label) {
|
|
39
|
-
if (text.split(oldValue).length - 1 !== expectedCount) {
|
|
40
|
-
throw Error('BCCLI branding unsupported by installed engine: ' + label)
|
|
41
|
-
}
|
|
42
|
-
return text.split(oldValue).join(newValue)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function replaceOnce(text, oldValue, newValue, label) {
|
|
46
|
-
if (text.split(oldValue).length !== 2) {
|
|
47
|
-
throw Error('BCCLI branding unsupported by installed engine: ' + label)
|
|
48
|
-
}
|
|
49
|
-
return text.replace(oldValue, newValue)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// Embedded slash commands are part of the upstream renderer bundle. BCCLI's
|
|
54
|
-
// Gateway owns authentication, model eligibility and release management, so
|
|
55
|
-
// those commands must not open arbitrary upstream provider settings or invoke
|
|
56
|
-
// the upstream npm / standalone auto-updater.
|
|
57
|
-
export function guardUpstreamProviderCommands(text) {
|
|
58
|
-
const replacements = [
|
|
59
|
-
{
|
|
60
|
-
command: 'auth',
|
|
61
|
-
detect: 'dialog:"auth"',
|
|
62
|
-
code: 'var authCommand={name:"auth",altNames:["connect","login","provider"],get description(){return "Choose provider, add API key and select a model in BCCLI"},kind:"built-in",supportedModes:["interactive"],action:__name((context)=>{if(context.executionMode && context.executionMode!=="interactive")return{type:"message",messageType:"error",content:"Provider switching requires an interactive terminal."};process.exit(51)},"action")};',
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
command: 'model',
|
|
66
|
-
detect: 'dialog:"model"',
|
|
67
|
-
code: BCCLI_MODEL_COMMAND,
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
command: 'settings',
|
|
71
|
-
detect: 'dialog:"settings"',
|
|
72
|
-
code: 'var settingsCommand={name:"settings",get description(){return "View safe BCCLI settings"},kind:"built-in",supportedModes:["interactive","non_interactive","acp"],action:__name(context=>({type:"message",messageType:"info",content:"BCCLI | BotConnector Settings\\nGateway: https://api.botconnector.id/v1 (fixed)\\nModel: "+(context.services?.config?.getModel?.()||"unknown")+"\\nAuth: existing bccli-legacy login (bc-cloud) or BOTCONNECTOR_API_KEY override\\nPermissions: ask before file changes and shell commands\\nUse /model to switch AI, /auth for connection help, /permissions for tool approvals, /theme to change appearance. Upstream provider and project-settings editors are disabled."}),"action")};',
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
command: 'about',
|
|
76
|
-
detect: 'Qwen Code v',
|
|
77
|
-
code: 'var aboutCommand={name:"status",altNames:["about"],get description(){return "Show BCCLI and BotConnector session diagnostics"},kind:"built-in",supportedModes:["interactive","non_interactive","acp"],canRunDuringStreaming:true,action:__name((context,arg)=>{const config=context.services?.config;const input=String(context.invocation?.args||arg||"").trim().toLowerCase();const message=input==="credits"?"BCCLI coding-agent runtime: based on Qwen Code 0.26.3 (Apache-2.0). Source attribution and license notices are retained in the installed runtime. Product repository: https://github.com/farijarifriyanto-debug/bccli":"BCCLI | BotConnector\\nAI model: "+(config?.getModel?.()||"unknown")+"\\nGateway: https://api.botconnector.id/v1\\nProvider routing: managed by BotConnector\\nPermissions: default (ask)\\nSource: https://github.com/farijarifriyanto-debug/bccli\\nEngine runtime: 0.26.3\\nFor open-source engine credits use /about credits.";return{type:"message",messageType:"info",content:message}},"action")};',
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
command: 'docs',
|
|
81
|
-
detect: 'qwen-code-docs',
|
|
82
|
-
code: 'var docsCommand={name:"docs",get description(){return "BCCLI product documentation"},kind:"built-in",supportedModes:["interactive","non_interactive","acp"],action:__name(()=>({type:"message",messageType:"info",content:"BCCLI documentation and releases: https://github.com/farijarifriyanto-debug/bccli#readme"}),"action")};',
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
command: 'update',
|
|
86
|
-
detect: 'Check for Qwen Code updates',
|
|
87
|
-
code: 'var updateCommand={name:"update",get description(){return "BCCLI release information"},kind:"built-in",supportedModes:["interactive","non_interactive","acp"],action:__name(()=>({type:"message",messageType:"info",content:"BCCLI updates are managed by the BotConnector release channel (@botconnector/bccli). The upstream engine updater is disabled; use the BotConnector release channel. Visit https://github.com/farijarifriyanto-debug/bccli/releases for product releases."}),"action")};',
|
|
88
|
-
},
|
|
89
|
-
]
|
|
90
|
-
let result = text
|
|
91
|
-
for (const { command, detect, code } of replacements) {
|
|
92
|
-
const marker = 'var ' + command + 'Command='
|
|
93
|
-
const pos = result.indexOf(marker)
|
|
94
|
-
if (pos < 0 || result.indexOf(marker, pos + 1) !== -1) {
|
|
95
|
-
throw Error('BCCLI upstream command locator changed: ' + command)
|
|
96
|
-
}
|
|
97
|
-
// /status has subCommands after its top-level action. Matching the first
|
|
98
|
-
// generic action end would accidentally remove neighbouring commands!
|
|
99
|
-
// This entire command is bounded by its own esbuild shim boundary.
|
|
100
|
-
const shimBoundary = command === 'about'
|
|
101
|
-
const suffix = shimBoundary ? '};init_esbuild_shims();' : ',"action")};'
|
|
102
|
-
const end = result.indexOf(suffix, pos)
|
|
103
|
-
const maxLength = shimBoundary ? 2500 : 18000
|
|
104
|
-
if (end < 0 || end - pos > maxLength) {
|
|
105
|
-
throw Error('BCCLI upstream command end changed: ' + command)
|
|
106
|
-
}
|
|
107
|
-
const original = result.slice(pos, end + suffix.length)
|
|
108
|
-
if (!original.includes(detect)) {
|
|
109
|
-
throw Error('BCCLI upstream command behavior changed: ' + command)
|
|
110
|
-
}
|
|
111
|
-
result = result.slice(0, pos) + code + (shimBoundary ? 'init_esbuild_shims();' : '') + result.slice(end + suffix.length)
|
|
112
|
-
}
|
|
113
|
-
return result
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Human-facing labels only. Do not rewrite license notices, import names, or
|
|
117
|
-
// file formats such as QWEN.md, which are still used by the upstream engine.
|
|
118
|
-
function renameProductLanguage(text) {
|
|
119
|
-
const labels = [
|
|
120
|
-
['To see changes, Qwen Code must be restarted.', 'To see changes, BCCLI must be restarted.'],
|
|
121
|
-
['To apply the trust changes, Qwen Code must be restarted.', 'To apply trust changes, restart BCCLI.'],
|
|
122
|
-
["Press 'r' to restart Qwen Code", "Press 'r' to restart BCCLI"],
|
|
123
|
-
["Qwen Code won't ask before using allowed tools.", "BCCLI won't ask before using allowed tools."],
|
|
124
|
-
["Qwen Code will ask before using these tools.", "BCCLI will ask before using these tools."],
|
|
125
|
-
["Qwen Code is not allowed to use denied tools.", "BCCLI is not allowed to use denied tools."],
|
|
126
|
-
["Qwen Code will be able to read files in this directory", "BCCLI will be able to read files in this directory"],
|
|
127
|
-
["Qwen Code can read files in the workspace", "BCCLI can read files in the workspace"],
|
|
128
|
-
['Qwen Code is restarting to apply the trust changes', 'BCCLI is restarting to apply the trust changes'],
|
|
129
|
-
['Qwen Code understands your codebase', 'BCCLI helps you understand your codebase'],
|
|
130
|
-
['Available Qwen Code CLI tools:', 'Available BCCLI coding tools:'],
|
|
131
|
-
['This menu is read-only. To add or modify hooks, edit settings.json directly or ask Qwen Code.', 'This menu is read-only. Changes to hooks require trusted BCCLI configuration.'],
|
|
132
|
-
['To re-enable hooks, remove "disableAllHooks" from settings.json or ask Qwen Code.', 'To re-enable hooks, update trusted BCCLI hook configuration.'],
|
|
133
|
-
['Generate with Qwen Code (Recommended)', 'Generate with BCCLI'],
|
|
134
|
-
['Trusting a folder allows Qwen Code to execute commands it suggests.', 'Trusting a folder allows BCCLI to execute approved commands.'],
|
|
135
|
-
['Reinstall Qwen Code or use the npm installation method.', 'Reinstall BCCLI using the official npm package.'],
|
|
136
|
-
['Do you want to connect ${ideName??"your editor"} to Qwen Code?', 'Do you want to connect ${ideName??"your editor"} to BCCLI?'],
|
|
137
|
-
['var DEFAULT_TITLE="Qwen Code"', 'var DEFAULT_TITLE="BCCLI"'],
|
|
138
|
-
['var NOTIFICATION_TITLE="Qwen Code"', 'var NOTIFICATION_TITLE="BCCLI"'],
|
|
139
|
-
['Qwen Code needs your permission', 'BCCLI needs your permission'],
|
|
140
|
-
['Qwen Code is waiting for your input', 'BCCLI is waiting for your input'],
|
|
141
|
-
['title:"Qwen Code"', 'title:"BCCLI"'],
|
|
142
|
-
['children:"Qwen Code"', 'children:"BCCLI"'],
|
|
143
|
-
['Approving lets Qwen Code start it and run its tools.', 'Approving lets BCCLI start it and run its tools.'],
|
|
144
|
-
['var DOCS_URL="https://qwenlm.github.io/qwen-code-docs/"', 'var DOCS_URL="https://github.com/farijarifriyanto-debug/bccli#readme"'],
|
|
145
|
-
['var HELP_DOCS_URL="https://qwenlm.github.io/qwen-code-docs/"', 'var HELP_DOCS_URL="https://github.com/farijarifriyanto-debug/bccli#readme"'],
|
|
146
|
-
['Review messages held from other Qwen Code sessions', 'Review messages held from other BCCLI sessions'],
|
|
147
|
-
['Qwen Code will be able to read, edit, and execute files there.', 'BCCLI will be able to read, edit, and execute files there.'],
|
|
148
|
-
['Re-run /doctor memory after restarting Qwen Code', 'Re-run /doctor memory after restarting BCCLI'],
|
|
149
|
-
['restart Qwen Code to recover memory', 'restart BCCLI to recover memory'],
|
|
150
|
-
['Restart Qwen Code first', 'Restart BCCLI first'],
|
|
151
|
-
['Right before Qwen Code concludes its response', 'Right before BCCLI concludes its response'],
|
|
152
|
-
['Manage Qwen Code hooks', 'Manage BCCLI hooks'],
|
|
153
|
-
['run Qwen Code in one of these supported IDEs', 'run BCCLI in one of these supported IDEs'],
|
|
154
|
-
['List available Qwen Code tools.', 'List available BCCLI tools.'],
|
|
155
|
-
['Qwen Code is unavailable in this WSL session', 'BCCLI is unavailable in this WSL session'],
|
|
156
|
-
['<title>Qwen Code Insights</title>', '<title>BCCLI Insights</title>'],
|
|
157
|
-
["Set up Qwen Code's status line UI", "Set up BCCLI's status line UI"],
|
|
158
|
-
['Start Qwen Code with', 'Start BCCLI with'],
|
|
159
|
-
|
|
160
|
-
]
|
|
161
|
-
let out = text
|
|
162
|
-
for (const [before, after] of labels) out = out.split(before).join(after)
|
|
163
|
-
return out
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export function patchUiChunk(file, text) {
|
|
167
|
-
if (file === 'chunks/server-SJNWHHV4.js') {
|
|
168
|
-
// An additional bundled server/agent instruction uses an upstream product
|
|
169
|
-
// identity. Neutralize only that exact clause; never invent a model name.
|
|
170
|
-
return replaceOnce(text,
|
|
171
|
-
'You are Qwen Code, a general-purpose agentic assistant',
|
|
172
|
-
'You are a general-purpose agentic assistant',
|
|
173
|
-
'server agent product identity')
|
|
174
|
-
}
|
|
175
|
-
if (file === 'chunks/chunk-OYUATJK2.js') {
|
|
176
|
-
const pattern = /var shortAsciiLogo=\x60[\s\S]*?\x60;/
|
|
177
|
-
const matches = text.match(new RegExp(pattern.source, 'g'))
|
|
178
|
-
if (matches?.length !== 1) throw Error('BCCLI branding logo locator changed upstream.')
|
|
179
|
-
return text.replace(pattern, () => 'var shortAsciiLogo=' + String.fromCharCode(96) + BCCLI_ASCII + String.fromCharCode(96) + ';')
|
|
180
|
-
}
|
|
181
|
-
if (file === 'chunks/startInteractiveUI-CECFAXVK.js') {
|
|
182
|
-
let result = replaceOnce(
|
|
183
|
-
text,
|
|
184
|
-
'customBannerTitle?customBannerTitle:">_ Qwen Code"',
|
|
185
|
-
'customBannerTitle?customBannerTitle:">_ BCCLI | BotConnector"',
|
|
186
|
-
'Ink banner title',
|
|
187
|
-
)
|
|
188
|
-
result = replaceOnce(result,
|
|
189
|
-
'Add a QWEN.md file to give Qwen Code persistent project context.',
|
|
190
|
-
'Use /help to explore BCCLI tools and commands.',
|
|
191
|
-
'Ink startup tip',
|
|
192
|
-
)
|
|
193
|
-
result = replaceOnce(result,
|
|
194
|
-
'You can resume a previous conversation by running qwen --continue or qwen --resume.',
|
|
195
|
-
'Continue the latest BCCLI session in this project using bccli -c.',
|
|
196
|
-
'Ink resume tip')
|
|
197
|
-
result = replaceOnce(result,
|
|
198
|
-
'You can run any shell commands from Qwen Code using ! (e.g. !ls).',
|
|
199
|
-
'Run terminal commands with ! (e.g. !ls), subject to your permissions.',
|
|
200
|
-
'Ink terminal tip')
|
|
201
|
-
result = replaceOnce(result,
|
|
202
|
-
'qwen --resume ${sessionId}',
|
|
203
|
-
'bccli -c',
|
|
204
|
-
'Ink session-exit command')
|
|
205
|
-
return renameProductLanguage(result)
|
|
206
|
-
}
|
|
207
|
-
if (file === 'chunks/start-opentui-ui-Q34XCEMN.js') {
|
|
208
|
-
let result = replaceOnce(
|
|
209
|
-
text, 'custom.title??">_ Qwen Code"', 'custom.title??">_ BCCLI | BotConnector"',
|
|
210
|
-
'OpenTUI banner title',
|
|
211
|
-
)
|
|
212
|
-
result = replaceOnce(result,
|
|
213
|
-
'var DEFAULT_GRADIENT=["#4796E4","#847ACE","#C3677F"]',
|
|
214
|
-
'var DEFAULT_GRADIENT='+JSON.stringify(BCCLI_COLORS),
|
|
215
|
-
'OpenTUI default gradient')
|
|
216
|
-
result = replaceOnce(result,
|
|
217
|
-
'addField("Qwen Code",cliVersion',
|
|
218
|
-
'addField("BCCLI engine",cliVersion',
|
|
219
|
-
'OpenTUI diagnostic label')
|
|
220
|
-
result = replaceOnce(result,
|
|
221
|
-
'To continue this session, run qwen --resume ${stats.sessionId}',
|
|
222
|
-
'To resume the latest session in this project, run bccli -c',
|
|
223
|
-
'OpenTUI project-quit resume command')
|
|
224
|
-
result = replaceOnce(result,
|
|
225
|
-
'qwen --resume ${sessionId}',
|
|
226
|
-
'bccli -c',
|
|
227
|
-
'OpenTUI transcript resume command')
|
|
228
|
-
return renameProductLanguage(result)
|
|
229
|
-
}
|
|
230
|
-
if (file === 'chunks/chunk-QUFSNRKR.js') {
|
|
231
|
-
return renameProductLanguage(replaceOnce(text,
|
|
232
|
-
'children:["qwen --resume ",stats.sessionId]',
|
|
233
|
-
'children:["bccli -c (latest session in this project)", ""]',
|
|
234
|
-
'Ink summary session-resume command'))
|
|
235
|
-
}
|
|
236
|
-
if (file === 'chunks/chunk-2PLSL3VQ.js') {
|
|
237
|
-
return replaceOnce(text,
|
|
238
|
-
"To enable automatic tool execution, use the -y flag (YOLO mode):" + String.fromCharCode(10) + "Example: qwen -p 'your prompt' -y",
|
|
239
|
-
"BCCLI requires an interactive approval for this tool. Re-run in interactive mode and approve the tool; unattended auto-approval is disabled.",
|
|
240
|
-
'headless approval warning')
|
|
241
|
-
}
|
|
242
|
-
if (file === 'chunks/chunk-ERV2ECV3.js') {
|
|
243
|
-
return replaceExactly(text,
|
|
244
|
-
'Qwen Code requires permission to use ',
|
|
245
|
-
'BCCLI requires permission to use ', 4,
|
|
246
|
-
'user-facing tool permission errors')
|
|
247
|
-
}
|
|
248
|
-
if (file === 'chunks/chunk-OV3EBH6J.js') {
|
|
249
|
-
return replaceOnce(text,
|
|
250
|
-
'You are Qwen Code, ${role} developed by Alibaba Group, ${focus}.',
|
|
251
|
-
'You are an AI coding assistant, ${role}, ${focus}.',
|
|
252
|
-
'neutral core agent introduction')
|
|
253
|
-
}
|
|
254
|
-
if (file === 'chunks/chunk-W3YCOEIP.js') {
|
|
255
|
-
let result = replaceExactly(
|
|
256
|
-
text,
|
|
257
|
-
'GradientColors:["#4796E4","#847ACE","#C3677F"]',
|
|
258
|
-
'GradientColors:'+JSON.stringify(BCCLI_COLORS), 2,
|
|
259
|
-
'Ink light/dark gradient')
|
|
260
|
-
result = replaceOnce(result,'AccentPurple:"#8B5CF6"','AccentPurple:"#047857"','light brand accent')
|
|
261
|
-
result = replaceOnce(result,'AccentPurple:"#CBA6F7"','AccentPurple:"#34D399"','dark brand accent')
|
|
262
|
-
result = replaceOnce(result,'AccentBlue:"#3B82F6"','AccentBlue:"#0891B2"','light focus blue')
|
|
263
|
-
return replaceOnce(result,'AccentBlue:"#89B4FA"','AccentBlue:"#22D3EE"','dark focus cyan')
|
|
264
|
-
}
|
|
265
|
-
if (file === 'chunks/chunk-7L4WTOM2.js') {
|
|
266
|
-
let result = replaceOnce(text,
|
|
267
|
-
'https://github.com/QwenLM/qwen-code/issues/new?template=bug_report.yml&title={title}&info={info}',
|
|
268
|
-
'https://github.com/farijarifriyanto-debug/bccli/issues/new?title={title}&body={info}',
|
|
269
|
-
'user-facing /bug report link')
|
|
270
|
-
result = replaceOnce(result,
|
|
271
|
-
'You are Qwen Code, an interactive CLI agent.',
|
|
272
|
-
'You are an AI coding assistant operating in a terminal.',
|
|
273
|
-
'neutral project initialization prompt')
|
|
274
|
-
result = guardUpstreamProviderCommands(result)
|
|
275
|
-
result = replaceOnce(result,
|
|
276
|
-
'get description(){return t("for help on Qwen Code")}',
|
|
277
|
-
'get description(){return t("BCCLI help and keyboard shortcuts")}',
|
|
278
|
-
'Help command description')
|
|
279
|
-
return renameProductLanguage(result)
|
|
280
|
-
}
|
|
281
|
-
throw Error('Unrecognized BCCLI branding file.')
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function assertSource(packageDir) {
|
|
285
|
-
const metadata = JSON.parse(readFileSync(join(packageDir, 'package.json'), 'utf8'))
|
|
286
|
-
if (metadata.name !== '@qwen-code/qwen-code' || metadata.version !== VERSION) {
|
|
287
|
-
throw Error('BCCLI branding needs the pinned Qwen Code engine ' + VERSION + '.')
|
|
288
|
-
}
|
|
289
|
-
const patched = {}
|
|
290
|
-
for (const [relative, expected] of Object.entries(SOURCE_HASHES)) {
|
|
291
|
-
const original = readFileSync(join(packageDir, relative))
|
|
292
|
-
if (digest(original) !== expected) {
|
|
293
|
-
throw Error('Qwen Code view bundle changed: aborting BCCLI branded startup (' + relative + ').')
|
|
294
|
-
}
|
|
295
|
-
patched[relative] = patchUiChunk(relative, original.toString('utf8'))
|
|
296
|
-
}
|
|
297
|
-
return patched
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function validCache(target, manifest) {
|
|
301
|
-
if (!existsSync(join(target, '.bccli-brand-marker.json'))) return false
|
|
302
|
-
try {
|
|
303
|
-
const stored = JSON.parse(readFileSync(join(target, '.bccli-brand-marker.json'), 'utf8'))
|
|
304
|
-
if (JSON.stringify(stored) !== JSON.stringify(manifest)) return false
|
|
305
|
-
for (const [relative, hash] of Object.entries(manifest.outputHashes)) {
|
|
306
|
-
if (digest(readFileSync(join(target, relative))) !== hash) return false
|
|
307
|
-
}
|
|
308
|
-
return existsSync(join(target, 'cli-entry.js'))
|
|
309
|
-
} catch { return false }
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Make an isolated, revision-pinned white-label copy of the upstream package.
|
|
314
|
-
* No model, provider, tool, permission, or auth logic is modified.
|
|
315
|
-
* The source node_modules/@qwen-code/qwen-code package remains byte-identical.
|
|
316
|
-
*/
|
|
317
|
-
export function prepareBrandedQwen(entrypoint, { cacheRoot } = {}) {
|
|
318
|
-
const packageDir = dirname(entrypoint)
|
|
319
|
-
// Keep the copy within the same npm dependency tree so Node resolves native
|
|
320
|
-
// and bundled imports exactly as the installed upstream runtime does.
|
|
321
|
-
cacheRoot ??= join(dirname(dirname(packageDir)), '.cache', 'bccli-branded-engines')
|
|
322
|
-
const patched = assertSource(packageDir)
|
|
323
|
-
const outputHashes = Object.fromEntries(Object.entries(patched).map(([file, value]) => [file, digest(value)]))
|
|
324
|
-
const manifest = { revision: BRAND_REVISION, version: VERSION, sourceHashes: SOURCE_HASHES, outputHashes }
|
|
325
|
-
const target = join(cacheRoot, VERSION + '-' + digest(JSON.stringify(manifest)).slice(0,12))
|
|
326
|
-
if (existsSync(target)) {
|
|
327
|
-
if (!validCache(target, manifest)) throw Error('BCCLI branded engine cache differs from the pinned build; manual cleanup required.')
|
|
328
|
-
return join(target, basename(entrypoint))
|
|
329
|
-
}
|
|
330
|
-
mkdirSync(cacheRoot, { recursive: true })
|
|
331
|
-
const tmp = mkdtempSync(join(cacheRoot, '.building-'))
|
|
332
|
-
try {
|
|
333
|
-
cpSync(packageDir, tmp, { recursive: true, errorOnExist: false })
|
|
334
|
-
for (const [relative, output] of Object.entries(patched)) {
|
|
335
|
-
writeFileSync(join(tmp, relative), output, 'utf8')
|
|
336
|
-
}
|
|
337
|
-
writeFileSync(join(tmp, '.bccli-brand-marker.json'), JSON.stringify(manifest), 'utf8')
|
|
338
|
-
try { renameSync(tmp, target) }
|
|
339
|
-
catch (err) {
|
|
340
|
-
if (!validCache(target, manifest)) throw err
|
|
341
|
-
}
|
|
342
|
-
} finally {
|
|
343
|
-
if (existsSync(tmp)) rmSync(tmp, { recursive: true, force: true })
|
|
344
|
-
}
|
|
345
|
-
if (!validCache(target, manifest)) throw Error('BCCLI branded engine copy failed verification.')
|
|
346
|
-
return join(target, basename(entrypoint))
|
|
347
|
-
}
|
package/cli.mjs
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { readFileSync } from 'node:fs'
|
|
3
|
-
import { DEFAULT_MODEL, assertCandidateRuntimeSupported, discoverModels, launchQwen, parseArgs, resolveQwenEntrypoint, resolveTrustedMcpConfig, selectModel } from './core.mjs'
|
|
4
|
-
import { prepareBrandedQwen } from './branding.mjs'
|
|
5
|
-
import { botConnectorCredentialStatus } from './credentials.mjs'
|
|
6
|
-
import { resolveProvider, selectedProvider, providerDefinition, isConfigured } from './providers.mjs'
|
|
7
|
-
import { runProviderCommand } from './provider-cli.mjs'
|
|
8
|
-
import { startupMenu, autoSelectStartup, PROVIDER_SWITCH_EXIT } from './startup-menu.mjs'
|
|
9
|
-
import { legacyCompatibilityMode, runLegacyCli } from './legacy-compat.mjs'
|
|
10
|
-
|
|
11
|
-
function help() {
|
|
12
|
-
console.log([
|
|
13
|
-
'BCCLI | BotConnector Coding Agent',
|
|
14
|
-
'Usage:',
|
|
15
|
-
' bccli models [--json]',
|
|
16
|
-
' bccli run --model MODEL "prompt" [--mcp-config OWNER_CONFIG_PATH]',
|
|
17
|
-
' bccli -p "prompt" [-m MODEL] (text-only headless alias)',
|
|
18
|
-
' bccli --version',
|
|
19
|
-
' bccli chat [--model MODEL] [--mcp-config OWNER_CONFIG_PATH]',
|
|
20
|
-
' bccli resume [--model MODEL] [prompt]',
|
|
21
|
-
' bccli -c [-m MODEL] [prompt] (resume latest current-project session)',
|
|
22
|
-
' bccli -r [SESSION_UUID] [-m MODEL] (native Qwen session picker or specific session)',
|
|
23
|
-
' bccli auth status (offline; does not print API key)',
|
|
24
|
-
' bccli provider add botconnector (enter a new Cloud key securely)',
|
|
25
|
-
' bccli provider remove botconnector (remove only the newly saved key)',
|
|
26
|
-
' bccli mcp|connect|acp|serve|plugins|completion|stats (legacy-compatible)',
|
|
27
|
-
' bccli -p "task" --output-format json|stream-json (legacy-compatible)',
|
|
28
|
-
' bccli provider list|add|use|remove [ID] (manage provider keys)',
|
|
29
|
-
' bccli models --provider ID (list models for provider)',
|
|
30
|
-
' bccli chat --provider ID --model MODEL_ID',
|
|
31
|
-
' bccli (open chat directly with active provider and last model)',
|
|
32
|
-
' bccli --choose (open provider/model picker explicitly)',
|
|
33
|
-
' During chat: /provider or /auth to reopen provider and key picker.',
|
|
34
|
-
'',
|
|
35
|
-
'Credentials: hidden in-terminal input; Windows DPAPI encrypted per-user storage, or existing login/env.',
|
|
36
|
-
'Provider choices: botconnector, openai, openrouter, deepseek, groq, xai.',
|
|
37
|
-
'Key entry: bccli --choose or bccli provider add botconnector (hidden terminal prompt).',
|
|
38
|
-
'Model choice: --model; BotConnector defaults to ling-3.0-flash. Other providers need --model.',
|
|
39
|
-
'Security: allowlisted provider endpoints, ephemeral local token, --bare and default approvals.',
|
|
40
|
-
'MCP: explicit JSON only, directly under ~/.bccli-preview/ (no project configs).',
|
|
41
|
-
'Text-only -p alias; public --output-format JSON/stream-json are not yet supported.',
|
|
42
|
-
'Local new-engine RC; the public npm stable release is unchanged.',
|
|
43
|
-
].join('\n'))
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function main() {
|
|
47
|
-
const argv = process.argv.slice(2)
|
|
48
|
-
if (legacyCompatibilityMode(argv)) return runLegacyCli(argv)
|
|
49
|
-
if (argv.length === 0 && !process.stdin.isTTY) { help(); return 2 }
|
|
50
|
-
if (argv[0] === '--help' || argv[0] === '-h' || argv[0] === 'help') { help(); return 0 }
|
|
51
|
-
if (argv.length === 1 && (argv[0] === '--version' || argv[0] === '-v')) {
|
|
52
|
-
// Offline informational command: never inspect credentials or contact Gateway.
|
|
53
|
-
const pkg = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8'))
|
|
54
|
-
console.log(pkg.version)
|
|
55
|
-
return 0
|
|
56
|
-
}
|
|
57
|
-
const forceChoose = argv.length === 1 && argv[0] === '--choose'
|
|
58
|
-
const args = forceChoose ? { command: 'chat', prompt: '', model: undefined } : parseArgs(argv)
|
|
59
|
-
if (args.command === 'provider') return runProviderCommand(args.prompt.trim() ? args.prompt.trim().split(/\s+/) : [])
|
|
60
|
-
if (args.command === 'auth') {
|
|
61
|
-
const status = botConnectorCredentialStatus()
|
|
62
|
-
if (isConfigured('botconnector')) {
|
|
63
|
-
console.log('BotConnector credential configured via ' +
|
|
64
|
-
(status.configured
|
|
65
|
-
? (status.source === 'environment' ? 'BOTCONNECTOR_API_KEY environment variable.' : 'existing public BCCLI bc-cloud login or new protected BCCLI key.')
|
|
66
|
-
: 'protected BCCLI provider storage.') +
|
|
67
|
-
' Not verified online. No AI request was sent.')
|
|
68
|
-
return 0
|
|
69
|
-
}
|
|
70
|
-
console.error('BotConnector credential not configured or unreadable. ' +
|
|
71
|
-
'Run "bccli provider add botconnector" or set BOTCONNECTOR_API_KEY. ' +
|
|
72
|
-
'No credential was changed and no AI request was sent.')
|
|
73
|
-
return 1
|
|
74
|
-
}
|
|
75
|
-
if (args.command !== 'models') assertCandidateRuntimeSupported()
|
|
76
|
-
if (args.command === 'models') {
|
|
77
|
-
const profile = resolveProvider(args.provider ?? selectedProvider())
|
|
78
|
-
const models = await discoverModels({ key: profile.key, endpoint: profile.endpoint })
|
|
79
|
-
if (args.json) console.log(JSON.stringify({ data: models }, null, 2))
|
|
80
|
-
else models.forEach((item) => console.log(item.id))
|
|
81
|
-
return 0
|
|
82
|
-
}
|
|
83
|
-
if (!args.prompt && !process.stdin.isTTY) throw Error('Interactive mode requires a TTY; use -p "prompt".')
|
|
84
|
-
const mcpConfig = resolveTrustedMcpConfig(args.mcpConfig)
|
|
85
|
-
let chosen
|
|
86
|
-
const showPicker = args.command === 'chat' && !args.prompt && !args.model
|
|
87
|
-
if (showPicker) {
|
|
88
|
-
chosen = forceChoose ? undefined : await autoSelectStartup({
|
|
89
|
-
...(args.provider ? { providerId: args.provider } : {}),
|
|
90
|
-
})
|
|
91
|
-
if (!chosen) chosen = await startupMenu({
|
|
92
|
-
...(args.provider ? { currentProvider: () => args.provider } : {}),
|
|
93
|
-
})
|
|
94
|
-
} else {
|
|
95
|
-
const providerId = args.provider ?? selectedProvider()
|
|
96
|
-
const profile = resolveProvider(providerId)
|
|
97
|
-
const models = await discoverModels({ key: profile.key, endpoint: profile.endpoint })
|
|
98
|
-
const requested = args.model ??
|
|
99
|
-
(providerId === 'botconnector' ? (process.env.BOTCONNECTOR_MODEL_ID ?? DEFAULT_MODEL) : undefined)
|
|
100
|
-
if (!requested) throw Error('Use --model MODEL_ID for ' + providerId + '.')
|
|
101
|
-
chosen = { providerId, model: selectModel(models, requested), key: profile.key, endpoint: profile.endpoint }
|
|
102
|
-
}
|
|
103
|
-
const entrypoint = prepareBrandedQwen(resolveQwenEntrypoint())
|
|
104
|
-
let continueSession = args.command === 'resume'
|
|
105
|
-
let resumeSession = args.resumeSession
|
|
106
|
-
for (;;) {
|
|
107
|
-
console.log('BCCLI | ' + providerDefinition(chosen.providerId).name + ' | ' + chosen.model)
|
|
108
|
-
const code = await launchQwen({
|
|
109
|
-
key: chosen.key, model: chosen.model, prompt: args.prompt,
|
|
110
|
-
mcpConfig, entrypoint, upstream: chosen.endpoint,
|
|
111
|
-
providerId: chosen.providerId, continueSession, resumeSession,
|
|
112
|
-
})
|
|
113
|
-
if (code !== PROVIDER_SWITCH_EXIT) return code
|
|
114
|
-
if (args.prompt || !process.stdin.isTTY) throw Error('Provider menu requires an interactive terminal.')
|
|
115
|
-
// /provider and /auth close the current engine cleanly, then the parent
|
|
116
|
-
// asks for a key and model. Keys never enter the Qwen agent process.
|
|
117
|
-
resumeSession = undefined // Native picker is used only on the first launch.
|
|
118
|
-
const previousProvider = chosen.providerId
|
|
119
|
-
chosen = await startupMenu()
|
|
120
|
-
continueSession = previousProvider === chosen.providerId
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
main().then((code) => { process.exitCode = code }, (error) => {
|
|
125
|
-
// Error messages deliberately never contain credentials or raw HTTP response bodies.
|
|
126
|
-
console.error('BCCLI: ' + (error instanceof Error ? error.message : 'Unexpected error.'))
|
|
127
|
-
process.exitCode = 1
|
|
128
|
-
})
|