@iruidong/code 0.1.5 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/QUICKSTART.md +28 -33
  2. package/README.md +21 -53
  3. package/dist/cli.js +159 -570
  4. package/package.json +1 -1
package/QUICKSTART.md CHANGED
@@ -10,46 +10,36 @@ ruidong --version
10
10
  Expected output:
11
11
 
12
12
  ```bash
13
- Ruidong Code v0.1.5
13
+ Ruidong Code v0.1.8
14
14
  ```
15
15
 
16
- ## 2. Initialize provider config
16
+ ## 2. Configure your shell
17
17
 
18
- ### Option A: Wizard
18
+ ### Option A: `iruidong`
19
19
 
20
20
  ```bash
21
- ruidong init
22
- ```
23
-
24
- Use this if you want Ruidong Code to guide you through endpoint, API key, and model selection. The wizard saves them directly to `~/.ruidong-code/config.json`.
25
-
26
- ### Option B: Preset profile
27
-
28
- `iruidong`:
21
+ cat >> ~/.zshrc <<'EOF'
22
+ export ANTHROPIC_BASE_URL="https://iruidong.com"
23
+ export ANTHROPIC_AUTH_TOKEN="your_api_key"
24
+ export ANTHROPIC_MODEL="glm"
25
+ EOF
29
26
 
30
- ```bash
31
- ruidong init --force --profile iruidong
27
+ source ~/.zshrc
32
28
  ```
33
29
 
34
- `crs`:
30
+ ### Option B: `crs`
35
31
 
36
32
  ```bash
37
- ruidong init --force --profile crs
38
- ```
33
+ cat >> ~/.zshrc <<'EOF'
34
+ export ANTHROPIC_BASE_URL="http://18.141.210.162:3000/api"
35
+ export ANTHROPIC_API_KEY="your_api_key"
36
+ export ANTHROPIC_MODEL="sonnet"
37
+ EOF
39
38
 
40
- ### Option C: Custom gateway
41
-
42
- ```bash
43
- ruidong init --force \
44
- --provider anthropic-compatible \
45
- --base-url https://your-gateway.example/v1 \
46
- --key "your_api_key" \
47
- --model qwen
39
+ source ~/.zshrc
48
40
  ```
49
41
 
50
- If you do not know the model ID yet, omit `--model`. After startup you can choose one with `/model`.
51
-
52
- Advanced users can still use `--key-env`, `--api-key-env`, or `--auth-token-env` to avoid writing a raw key into config.
42
+ If you use `bash`, replace `~/.zshrc` with `~/.bashrc`.
53
43
 
54
44
  ## 3. Verify headless mode
55
45
 
@@ -57,8 +47,6 @@ Advanced users can still use `--key-env`, `--api-key-env`, or `--auth-token-env`
57
47
  ruidong -p "你好,请只回复 OK" --bare
58
48
  ```
59
49
 
60
- If your config already contains a default model, this should return a short response immediately.
61
-
62
50
  If your gateway requires an explicit model:
63
51
 
64
52
  ```bash
@@ -76,7 +64,6 @@ Useful first commands:
76
64
 
77
65
  ```text
78
66
  /model
79
- /init
80
67
  /mcp
81
68
  /plugin
82
69
  ```
@@ -95,14 +82,22 @@ Legacy `CLAUDE.md` names are still supported for compatibility.
95
82
  Auth errors:
96
83
 
97
84
  ```bash
98
- cat ~/.ruidong-code/config.json
85
+ env | egrep '^(ANTHROPIC|RUIDONG)_'
99
86
  ruidong doctor
100
87
  ```
101
88
 
102
- Need to rebuild config:
89
+ If your team uses shell variables, do not also keep another provider in `~/.ruidong-code/config.json`.
90
+
91
+ If an old `~/.ruidong-code/config.json` keeps interfering, remove it:
92
+
93
+ ```bash
94
+ rm -f ~/.ruidong-code/config.json
95
+ ```
96
+
97
+ If you tested an old temporary setup flow before, also clear any config-dir override:
103
98
 
104
99
  ```bash
105
- ruidong init --force
100
+ unset RUIDONG_CONFIG_DIR CLAUDE_CONFIG_DIR
106
101
  ```
107
102
 
108
103
  Need more debug output:
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ruidong Code
2
2
 
3
- Ruidong Code is a terminal coding assistant CLI that works with Anthropic-compatible gateways and relay services. You can point it at your own API URL, choose a default model, and keep runtime settings in `~/.ruidong-code/config.json`.
3
+ Ruidong Code is a terminal coding assistant CLI that works with Anthropic-compatible gateways and relay services. The recommended setup is the same as standard Claude Code deployments: put `ANTHROPIC_*` variables in your shell profile, then run `ruidong` directly. `~/.ruidong-code/config.json` is optional.
4
4
 
5
5
  ## Install
6
6
 
@@ -13,39 +13,33 @@ Node.js `>=18` is required.
13
13
 
14
14
  ## Quick Start
15
15
 
16
- ### 1. Initialize config
16
+ ### 1. Configure your shell
17
17
 
18
- Interactive wizard:
18
+ `iruidong` example:
19
19
 
20
20
  ```bash
21
- ruidong init
22
- ```
23
-
24
- The wizard now asks for:
25
-
26
- - API endpoint URL
27
- - API key
28
- - Default model
29
-
30
- and saves them to `~/.ruidong-code/config.json`.
21
+ cat >> ~/.zshrc <<'EOF'
22
+ export ANTHROPIC_BASE_URL="https://iruidong.com"
23
+ export ANTHROPIC_AUTH_TOKEN="your_api_key"
24
+ export ANTHROPIC_MODEL="glm"
25
+ EOF
31
26
 
32
- Preset profiles:
33
-
34
- ```bash
35
- ruidong init --force --profile iruidong
36
- ruidong init --force --profile crs
27
+ source ~/.zshrc
37
28
  ```
38
29
 
39
- Custom gateway:
30
+ `crs` example:
40
31
 
41
32
  ```bash
42
- ruidong init --force \
43
- --provider anthropic-compatible \
44
- --base-url https://your-gateway.example/v1 \
45
- --key "your_api_key"
33
+ cat >> ~/.zshrc <<'EOF'
34
+ export ANTHROPIC_BASE_URL="http://18.141.210.162:3000/api"
35
+ export ANTHROPIC_API_KEY="your_api_key"
36
+ export ANTHROPIC_MODEL="sonnet"
37
+ EOF
38
+
39
+ source ~/.zshrc
46
40
  ```
47
41
 
48
- Advanced users can still use environment variables with `--key-env`, `--api-key-env`, or `--auth-token-env`.
42
+ If you use `bash`, write the same variables to `~/.bashrc`.
49
43
 
50
44
  ### 2. Start using it
51
45
 
@@ -62,33 +56,8 @@ Non-interactive check:
62
56
  ruidong -p "你好,请只回复 OK" --bare
63
57
  ```
64
58
 
65
- ## Config Model
66
-
67
- Ruidong Code stores runtime config in:
68
-
69
- ```bash
70
- ~/.ruidong-code/config.json
71
- ```
72
-
73
- Common provider fields:
74
-
75
- ```json
76
- {
77
- "provider": {
78
- "id": "anthropic-compatible",
79
- "baseUrl": "https://your-gateway.example/v1",
80
- "authToken": "your_api_key",
81
- "authMode": "auto",
82
- "defaultModel": "glm"
83
- }
84
- }
85
- ```
86
-
87
- Supported init flows:
88
-
89
- - `iruidong`: built-in preset for `https://iruidong.com`
90
- - `crs`: built-in preset for the CRS relay profile
91
- - `anthropic-compatible`: generic gateway mode
59
+ Ruidong Code also ships with a built-in official marketplace URL:
60
+ `https://marketplace.iruidong.com/marketplace.json`.
92
61
 
93
62
  ## Instruction Files
94
63
 
@@ -103,7 +72,6 @@ Legacy `CLAUDE.md` and `CLAUDE.local.md` are still read for compatibility.
103
72
 
104
73
  ```bash
105
74
  ruidong --help
106
- ruidong init --help
107
75
  ruidong -p "summarize this repo" --bare
108
76
  ruidong doctor
109
77
  ```
@@ -111,7 +79,6 @@ ruidong doctor
111
79
  Inside an interactive session:
112
80
 
113
81
  - `/model`
114
- - `/init`
115
82
  - `/mcp`
116
83
  - `/plugin`
117
84
 
@@ -120,6 +87,7 @@ Inside an interactive session:
120
87
  - [Quick Start](./QUICKSTART.md)
121
88
  - [同事安装说明](./docs/TEAM_INSTALL_GUIDE_CN.md)
122
89
  - [双平台配置说明](./docs/PLATFORM_SPLIT_CN.md)
90
+ - [公开 Marketplace 部署](./docs/RUIDONG_PUBLIC_MARKETPLACE_DEPLOYMENT_CN.md)
123
91
 
124
92
  ## Release Verification
125
93
 
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // ruidong v0.1.5 (built from source)
2
+ // ruidong v0.1.8 (built from source)
3
3
  // Copyright (c) Anthropic PBC. All rights reserved.
4
4
  import { createRequire as __createRequire } from "module";const require=__createRequire(import.meta.url);
5
5
  var __defProp = Object.defineProperty;
@@ -81,8 +81,8 @@ var __callDispose = (stack, error, hasError) => {
81
81
  var PUBLIC_CLI_VERSION, BUILD_TIME, API_COMPAT_VERSION, API_COMPAT_VERSION_BASE;
82
82
  var init_version = __esm({
83
83
  "build-src/src/constants/version.ts"() {
84
- PUBLIC_CLI_VERSION = "0.1.5";
85
- BUILD_TIME = "2026-04-01T06:00:31.912Z";
84
+ PUBLIC_CLI_VERSION = "0.1.8";
85
+ BUILD_TIME = "2026-04-03T12:30:00.000Z";
86
86
  API_COMPAT_VERSION = "2.1.88";
87
87
  API_COMPAT_VERSION_BASE = API_COMPAT_VERSION.match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/)?.[0];
88
88
  }
@@ -13003,18 +13003,36 @@ import {
13003
13003
  } from "fs";
13004
13004
  import { join as join21 } from "path";
13005
13005
  import { z as z9 } from "zod/v4";
13006
+ function isPlaceholderUrl(rawUrl) {
13007
+ if (!rawUrl) {
13008
+ return false;
13009
+ }
13010
+ try {
13011
+ const { hostname: hostname3 } = new URL(rawUrl);
13012
+ return hostname3 === "example.com" || hostname3 === "example.org" || hostname3 === "example.net" || hostname3.endsWith(".example.com") || hostname3.endsWith(".example.org") || hostname3.endsWith(".example.net");
13013
+ } catch {
13014
+ return false;
13015
+ }
13016
+ }
13017
+ function sanitizeConfiguredUrl(rawUrl, label) {
13018
+ if (!rawUrl) {
13019
+ return void 0;
13020
+ }
13021
+ if (!isPlaceholderUrl(rawUrl)) {
13022
+ return rawUrl;
13023
+ }
13024
+ logForDebugging(
13025
+ `[Ruidong config] Ignoring placeholder ${label}: ${rawUrl}`,
13026
+ { level: "warn" }
13027
+ );
13028
+ return void 0;
13029
+ }
13006
13030
  function getRuidongConfigHomeDir() {
13007
13031
  return (getConfiguredClaudeConfigHomeDir() ?? getDefaultRuidongConfigHomeDir()).normalize("NFC");
13008
13032
  }
13009
13033
  function getRuidongConfigPath() {
13010
13034
  return join21(getRuidongConfigHomeDir(), "config.json");
13011
13035
  }
13012
- function resetRuidongConfigCache() {
13013
- configCache = void 0;
13014
- }
13015
- function hasRuidongConfig() {
13016
- return existsSync5(getRuidongConfigPath());
13017
- }
13018
13036
  function getRuidongConfig() {
13019
13037
  if (configCache !== void 0) {
13020
13038
  return configCache;
@@ -13039,9 +13057,13 @@ function getRuidongRuntimeProviderConfig() {
13039
13057
  if (!provider) {
13040
13058
  return null;
13041
13059
  }
13060
+ const baseUrl = sanitizeConfiguredUrl(provider.baseUrl, "provider.baseUrl");
13061
+ if (provider.id === "anthropic-compatible" && !baseUrl) {
13062
+ return null;
13063
+ }
13042
13064
  return {
13043
13065
  id: provider.id,
13044
- baseUrl: provider.baseUrl,
13066
+ baseUrl,
13045
13067
  apiKey: resolveSecretValue(provider.apiKey),
13046
13068
  authToken: resolveSecretValue(provider.authToken),
13047
13069
  authMode: provider.authMode ?? "auto",
@@ -13068,7 +13090,7 @@ function getResolvedRuidongVoiceConfig() {
13068
13090
  ...voice2.stt && {
13069
13091
  stt: {
13070
13092
  provider: voice2.stt.provider,
13071
- baseUrl: voice2.stt.baseUrl,
13093
+ baseUrl: sanitizeConfiguredUrl(voice2.stt.baseUrl, "voice.stt.baseUrl"),
13072
13094
  apiKey: resolveSecretValue(voice2.stt.apiKey),
13073
13095
  model: voice2.stt.model,
13074
13096
  language: voice2.stt.language,
@@ -13083,6 +13105,9 @@ function setEnvIfUnset(key, value) {
13083
13105
  }
13084
13106
  process.env[key] = value;
13085
13107
  }
13108
+ function hasExplicitEnvValue(key) {
13109
+ return Boolean(process.env[key]?.trim());
13110
+ }
13086
13111
  function setManagedEnv(key, value) {
13087
13112
  const normalizedValue = value?.trim();
13088
13113
  if (!normalizedValue) {
@@ -13134,6 +13159,9 @@ function selectConfiguredCredential(provider) {
13134
13159
  return "api-key";
13135
13160
  }
13136
13161
  function applyProviderCredentialEnv(provider) {
13162
+ if (hasExplicitEnvValue("ANTHROPIC_API_KEY") || hasExplicitEnvValue("ANTHROPIC_AUTH_TOKEN")) {
13163
+ return;
13164
+ }
13137
13165
  const selectedCredential = selectConfiguredCredential(provider);
13138
13166
  if (!selectedCredential) {
13139
13167
  return;
@@ -13168,7 +13196,10 @@ function applyOfficialMarketplaceConfig(official) {
13168
13196
  );
13169
13197
  break;
13170
13198
  case "git":
13171
- setEnvIfUnset("RUIDONG_OFFICIAL_MARKETPLACE_GIT_URL", source.url);
13199
+ setEnvIfUnset(
13200
+ "RUIDONG_OFFICIAL_MARKETPLACE_GIT_URL",
13201
+ sanitizeConfiguredUrl(source.url, "marketplace.official.source.url")
13202
+ );
13172
13203
  setEnvIfUnset("RUIDONG_OFFICIAL_MARKETPLACE_REF", source.ref);
13173
13204
  setEnvIfUnset("RUIDONG_OFFICIAL_MARKETPLACE_PATH", source.path);
13174
13205
  setEnvIfUnset(
@@ -13177,7 +13208,10 @@ function applyOfficialMarketplaceConfig(official) {
13177
13208
  );
13178
13209
  break;
13179
13210
  case "url":
13180
- setEnvIfUnset("RUIDONG_OFFICIAL_MARKETPLACE_URL", source.url);
13211
+ setEnvIfUnset(
13212
+ "RUIDONG_OFFICIAL_MARKETPLACE_URL",
13213
+ sanitizeConfiguredUrl(source.url, "marketplace.official.source.url")
13214
+ );
13181
13215
  break;
13182
13216
  }
13183
13217
  }
@@ -13189,73 +13223,35 @@ function applyRuidongRuntimeConfig() {
13189
13223
  const provider = config2.provider;
13190
13224
  if (provider) {
13191
13225
  applyProviderFlags(provider.id);
13192
- if (provider.baseUrl !== void 0) {
13193
- setManagedEnv("ANTHROPIC_BASE_URL", provider.baseUrl);
13226
+ const providerBaseUrl = sanitizeConfiguredUrl(
13227
+ provider.baseUrl,
13228
+ "provider.baseUrl"
13229
+ );
13230
+ if (providerBaseUrl !== void 0) {
13231
+ setEnvIfUnset("ANTHROPIC_BASE_URL", providerBaseUrl);
13194
13232
  }
13195
13233
  applyProviderCredentialEnv(provider);
13196
13234
  if (provider.authMode !== void 0) {
13197
- setManagedEnv("ANTHROPIC_AUTH_MODE", provider.authMode);
13235
+ setEnvIfUnset("ANTHROPIC_AUTH_MODE", provider.authMode);
13198
13236
  }
13199
13237
  if (provider.defaultModel !== void 0) {
13200
- setManagedEnv("ANTHROPIC_MODEL", provider.defaultModel);
13238
+ setEnvIfUnset("ANTHROPIC_MODEL", provider.defaultModel);
13201
13239
  }
13202
13240
  }
13203
13241
  applyOfficialMarketplaceConfig(config2.marketplace?.official);
13204
13242
  setEnvIfUnset(
13205
13243
  "RUIDONG_OFFICIAL_MCP_REGISTRY_URL",
13206
- config2.mcp?.officialRegistryUrl
13244
+ sanitizeConfiguredUrl(
13245
+ config2.mcp?.officialRegistryUrl,
13246
+ "mcp.officialRegistryUrl"
13247
+ )
13207
13248
  );
13208
13249
  }
13209
- function writeRuidongConfig(config2) {
13210
- mkdirSync3(getRuidongConfigHomeDir(), { recursive: true });
13211
- writeFileSync2(getRuidongConfigPath(), `${JSON.stringify(config2, null, 2)}
13212
- `, {
13213
- encoding: "utf-8"
13214
- });
13215
- resetRuidongConfigCache();
13216
- }
13217
- function copyMissingEntries(fromDir, toDir) {
13218
- if (!existsSync5(fromDir)) {
13219
- return 0;
13220
- }
13221
- let copied = 0;
13222
- mkdirSync3(toDir, { recursive: true });
13223
- for (const entry of readdirSync2(fromDir, { withFileTypes: true })) {
13224
- const sourcePath = join21(fromDir, entry.name);
13225
- const targetPath = join21(toDir, entry.name);
13226
- if (existsSync5(targetPath)) {
13227
- continue;
13228
- }
13229
- cpSync(sourcePath, targetPath, { recursive: true });
13230
- copied++;
13231
- }
13232
- return copied;
13233
- }
13234
- function migrateLegacyClaudeHomeToRuidongHome() {
13235
- const targetDir = getRuidongConfigHomeDir();
13236
- const legacyDir = getLegacyClaudeConfigHomeDir();
13237
- if (targetDir === legacyDir) {
13238
- return { migrated: false, copiedEntries: 0, copiedGlobalConfig: false };
13239
- }
13240
- const copiedEntries = copyMissingEntries(legacyDir, targetDir);
13241
- const legacyGlobalConfig = getLegacyGlobalClaudeFile();
13242
- const ruidongGlobalConfig = join21(targetDir, "global.json");
13243
- let copiedGlobalConfig = false;
13244
- if (existsSync5(legacyGlobalConfig) && !existsSync5(ruidongGlobalConfig)) {
13245
- mkdirSync3(targetDir, { recursive: true });
13246
- cpSync(legacyGlobalConfig, ruidongGlobalConfig);
13247
- copiedGlobalConfig = true;
13248
- }
13249
- return {
13250
- migrated: copiedEntries > 0 || copiedGlobalConfig,
13251
- copiedEntries,
13252
- copiedGlobalConfig
13253
- };
13254
- }
13255
13250
  var RuidongProviderIdSchema, RuidongAuthModeSchema, RuidongVoiceSttProviderSchema, OfficialMarketplaceSourceSchema, RuidongConfigSchema, configCache;
13256
13251
  var init_ruidongConfig = __esm({
13257
13252
  "build-src/src/utils/ruidongConfig.ts"() {
13258
13253
  init_envUtils();
13254
+ init_debug();
13259
13255
  init_env();
13260
13256
  RuidongProviderIdSchema = z9.enum([
13261
13257
  "anthropic",
@@ -25961,7 +25957,10 @@ function parseKey(keypress) {
25961
25957
  wheelDown: keypress.name === "wheeldown",
25962
25958
  home: keypress.name === "home",
25963
25959
  end: keypress.name === "end",
25964
- return: keypress.name === "return",
25960
+ // Some terminals emit LF as "enter" while others emit CR as "return".
25961
+ // Treat both as the same submit key so onboarding and chat input behave
25962
+ // consistently across Terminal/iTerm/SSH combinations.
25963
+ return: keypress.name === "return" || keypress.name === "enter",
25965
25964
  escape: keypress.name === "escape",
25966
25965
  fn: keypress.fn,
25967
25966
  ctrl: keypress.ctrl,
@@ -39506,12 +39505,19 @@ function buildOfficialMarketplaceSource() {
39506
39505
  ...sparsePaths && { sparsePaths }
39507
39506
  };
39508
39507
  }
39508
+ const githubRepo = getOptionalEnv("RUIDONG_OFFICIAL_MARKETPLACE_REPO");
39509
+ if (githubRepo) {
39510
+ return {
39511
+ source: "github",
39512
+ repo: githubRepo,
39513
+ ...ref && { ref },
39514
+ ...path15 && { path: path15 },
39515
+ ...sparsePaths && { sparsePaths }
39516
+ };
39517
+ }
39509
39518
  return {
39510
- source: "github",
39511
- repo: getOptionalEnv("RUIDONG_OFFICIAL_MARKETPLACE_REPO") ?? DEFAULT_OFFICIAL_MARKETPLACE_REPO,
39512
- ...ref && { ref },
39513
- ...path15 && { path: path15 },
39514
- ...sparsePaths && { sparsePaths }
39519
+ source: "url",
39520
+ url: DEFAULT_OFFICIAL_MARKETPLACE_URL
39515
39521
  };
39516
39522
  }
39517
39523
  function isConfiguredOfficialMarketplaceName(marketplace) {
@@ -39552,11 +39558,11 @@ function getOfficialMarketplaceGcsArcPrefix() {
39552
39558
  const override = getOptionalEnv("RUIDONG_OFFICIAL_MARKETPLACE_GCS_ARC_PREFIX");
39553
39559
  return override ?? `marketplaces/${OFFICIAL_MARKETPLACE_NAME}/`;
39554
39560
  }
39555
- var DEFAULT_OFFICIAL_MARKETPLACE_NAME, DEFAULT_OFFICIAL_MARKETPLACE_REPO, ANTHROPIC_OFFICIAL_MARKETPLACE_REPO, ANTHROPIC_OFFICIAL_MARKETPLACE_GCS_BASE, OFFICIAL_MARKETPLACE_NAME, OFFICIAL_MARKETPLACE_SOURCE;
39561
+ var DEFAULT_OFFICIAL_MARKETPLACE_NAME, DEFAULT_OFFICIAL_MARKETPLACE_URL, ANTHROPIC_OFFICIAL_MARKETPLACE_REPO, ANTHROPIC_OFFICIAL_MARKETPLACE_GCS_BASE, OFFICIAL_MARKETPLACE_NAME, OFFICIAL_MARKETPLACE_SOURCE;
39556
39562
  var init_officialMarketplace = __esm({
39557
39563
  "build-src/src/utils/plugins/officialMarketplace.ts"() {
39558
- DEFAULT_OFFICIAL_MARKETPLACE_NAME = "ruidong-marketplace-seed";
39559
- DEFAULT_OFFICIAL_MARKETPLACE_REPO = "Jackwwg83/ruidong-marketplace-seed";
39564
+ DEFAULT_OFFICIAL_MARKETPLACE_NAME = "ruidong-marketplace";
39565
+ DEFAULT_OFFICIAL_MARKETPLACE_URL = "https://marketplace.iruidong.com/marketplace.json";
39560
39566
  ANTHROPIC_OFFICIAL_MARKETPLACE_REPO = "anthropics/claude-plugins-official";
39561
39567
  ANTHROPIC_OFFICIAL_MARKETPLACE_GCS_BASE = "https://downloads.claude.ai/claude-code-releases/plugins/claude-plugins-official";
39562
39568
  OFFICIAL_MARKETPLACE_NAME = getOptionalEnv("RUIDONG_OFFICIAL_MARKETPLACE_NAME") ?? DEFAULT_OFFICIAL_MARKETPLACE_NAME;
@@ -75142,7 +75148,7 @@ async function setupSdkMcpClients(sdkMcpConfigs, sendMcpMessage) {
75142
75148
  {
75143
75149
  name: "ruidong-code",
75144
75150
  title: "ruidong",
75145
- version: "0.1.5",
75151
+ version: "0.1.8",
75146
75152
  description: "Ruidong Code agentic coding tool",
75147
75153
  websiteUrl: PRODUCT_URL
75148
75154
  },
@@ -75565,7 +75571,7 @@ var init_client3 = __esm({
75565
75571
  {
75566
75572
  name: "ruidong-code",
75567
75573
  title: "ruidong",
75568
- version: "0.1.5",
75574
+ version: "0.1.8",
75569
75575
  description: "Ruidong Code agentic coding tool",
75570
75576
  websiteUrl: PRODUCT_URL
75571
75577
  },
@@ -87264,7 +87270,7 @@ async function installGlobalPackage(specificVersion) {
87264
87270
  );
87265
87271
  logEvent("tengu_auto_updater_lock_contention", {
87266
87272
  pid: process.pid,
87267
- currentVersion: "0.1.5"
87273
+ currentVersion: "0.1.8"
87268
87274
  });
87269
87275
  return "in_progress";
87270
87276
  }
@@ -87273,7 +87279,7 @@ async function installGlobalPackage(specificVersion) {
87273
87279
  if (!env.isRunningWithBun() && env.isNpmFromWindowsPath()) {
87274
87280
  logError(new Error("Windows NPM detected in WSL environment"));
87275
87281
  logEvent("tengu_auto_updater_windows_npm_in_wsl", {
87276
- currentVersion: "0.1.5"
87282
+ currentVersion: "0.1.8"
87277
87283
  });
87278
87284
  console.error(`
87279
87285
  Error: Windows NPM detected in WSL
@@ -87617,7 +87623,7 @@ function detectProviderConfigWarnings() {
87617
87623
  if (usingThirdPartyEndpoint && !resolvedApiKey && !resolvedAuthToken) {
87618
87624
  warnings.push({
87619
87625
  issue: "Third-party endpoint is configured but no API credential is available",
87620
- fix: `Set ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN, or run: ${CLI_COMMAND2} init --force --endpoint <url> --key-env <ENV_NAME> --model <model>`
87626
+ fix: "Set ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN in your shell profile, then restart the terminal"
87621
87627
  });
87622
87628
  }
87623
87629
  if (requestedAuthMode === "auto" && resolvedApiKey && resolvedAuthToken) {
@@ -87940,7 +87946,7 @@ function detectLinuxGlobPatternWarnings() {
87940
87946
  }
87941
87947
  async function getDoctorDiagnostic() {
87942
87948
  const installationType = await getCurrentInstallationType();
87943
- const version2 = typeof MACRO !== "undefined" && "0.1.5" ? "0.1.5" : "unknown";
87949
+ const version2 = typeof MACRO !== "undefined" && "0.1.8" ? "0.1.8" : "unknown";
87944
87950
  const installationPath = await getInstallationPath();
87945
87951
  const invokedBinary = getInvokedBinary();
87946
87952
  const multipleInstallations = await detectMultipleInstallations();
@@ -89020,7 +89026,7 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
89020
89026
  version2 = maxVersion;
89021
89027
  }
89022
89028
  }
89023
- if (!forceReinstall && version2 === "0.1.5" && await versionIsAvailable(version2) && await isPossibleClaudeBinary(executablePath)) {
89029
+ if (!forceReinstall && version2 === "0.1.8" && await versionIsAvailable(version2) && await isPossibleClaudeBinary(executablePath)) {
89024
89030
  logForDebugging(`Found ${version2} at ${executablePath}, skipping install`);
89025
89031
  logEvent("tengu_native_update_complete", {
89026
89032
  latency_ms: Date.now() - startTime,
@@ -185106,6 +185112,19 @@ var init_modifiers = __esm({
185106
185112
 
185107
185113
  // build-src/src/hooks/useTextInput.ts
185108
185114
  import stripAnsi6 from "strip-ansi";
185115
+ function getCoalescedSubmitSuffix(input) {
185116
+ const suffixes = ["\r\n", "\r", "\n"];
185117
+ for (const suffix of suffixes) {
185118
+ if (input.length > suffix.length && input.endsWith(suffix) && !input.slice(0, -suffix.length).includes("\r") && !input.slice(0, -suffix.length).includes("\n") && input[input.length - suffix.length - 1] !== "\\") {
185119
+ return suffix;
185120
+ }
185121
+ }
185122
+ return null;
185123
+ }
185124
+ function stripCoalescedSubmitSuffix(input) {
185125
+ const suffix = getCoalescedSubmitSuffix(input);
185126
+ return suffix ? input.slice(0, -suffix.length) : input;
185127
+ }
185109
185128
  function mapInput(input_map) {
185110
185129
  const map = new Map(input_map);
185111
185130
  return function(input) {
@@ -185378,7 +185397,10 @@ function useTextInput({
185378
185397
  case (input === "\x1B[F" || input === "\x1B[4~"):
185379
185398
  return cursor.endOfLine();
185380
185399
  default: {
185381
- const text = stripAnsi6(input).replace(/(?<=[^\\\r\n])\r$/, "").replace(/\r/g, "\n");
185400
+ const text = stripAnsi6(stripCoalescedSubmitSuffix(input)).replace(
185401
+ /\r/g,
185402
+ "\n"
185403
+ );
185382
185404
  if (cursor.isAtStart() && isInputModeCharacter(input)) {
185383
185405
  return cursor.insert(text).left();
185384
185406
  }
@@ -185406,11 +185428,16 @@ function useTextInput({
185406
185428
  if (filteredInput === "" && input !== "") {
185407
185429
  return;
185408
185430
  }
185409
- if (!key.backspace && !key.delete && input.includes("\x7F")) {
185410
- const delCount = (input.match(/\x7f/g) || []).length;
185431
+ const coalescedSubmitSuffix = key.return ? null : getCoalescedSubmitSuffix(filteredInput);
185432
+ if (!key.backspace && !key.delete && /[\x08\x7f]/.test(stripCoalescedSubmitSuffix(filteredInput))) {
185433
+ const text = stripAnsi6(stripCoalescedSubmitSuffix(filteredInput));
185411
185434
  let currentCursor = cursor;
185412
- for (let i = 0; i < delCount; i++) {
185413
- currentCursor = currentCursor.deleteTokenBefore() ?? currentCursor.backspace();
185435
+ for (const char of text) {
185436
+ if (char === "\b" || char === "\x7F") {
185437
+ currentCursor = currentCursor.deleteTokenBefore() ?? currentCursor.backspace();
185438
+ continue;
185439
+ }
185440
+ currentCursor = currentCursor.insert(char === "\r" ? "\n" : char);
185414
185441
  }
185415
185442
  if (!cursor.equals(currentCursor)) {
185416
185443
  if (cursor.text !== currentCursor.text) {
@@ -185420,6 +185447,9 @@ function useTextInput({
185420
185447
  }
185421
185448
  resetKillAccumulation();
185422
185449
  resetYankState();
185450
+ if (coalescedSubmitSuffix) {
185451
+ onSubmit?.(currentCursor.text);
185452
+ }
185423
185453
  return;
185424
185454
  }
185425
185455
  if (!isKillKey2(key, filteredInput)) {
@@ -185436,9 +185466,7 @@ function useTextInput({
185436
185466
  }
185437
185467
  setOffset(nextCursor.offset);
185438
185468
  }
185439
- if (filteredInput.length > 1 && filteredInput.endsWith("\r") && !filteredInput.slice(0, -1).includes("\r") && // Backslash+CR is a stale VS Code Shift+Enter binding, not
185440
- // coalesced Enter. See default handler above.
185441
- filteredInput[filteredInput.length - 2] !== "\\") {
185469
+ if (coalescedSubmitSuffix) {
185442
185470
  onSubmit?.(nextCursor.text);
185443
185471
  }
185444
185472
  }
@@ -187880,7 +187908,7 @@ ${sanitizedDescription}
187880
187908
  **Environment Info**
187881
187909
  - Platform: ${env.platform}
187882
187910
  - Terminal: ${env.terminal}
187883
- - Version: ${"0.1.5"}
187911
+ - Version: ${"0.1.8"}
187884
187912
  - Feedback ID: ${feedbackId}
187885
187913
 
187886
187914
  **Errors**
@@ -254194,7 +254222,7 @@ function generateHtmlReport(data, insights) {
254194
254222
  </html>`;
254195
254223
  }
254196
254224
  function buildExportData(data, insights, facets, remoteStats) {
254197
- const version2 = typeof MACRO !== "undefined" ? "0.1.5" : "unknown";
254225
+ const version2 = typeof MACRO !== "undefined" ? "0.1.8" : "unknown";
254198
254226
  const remote_hosts_collected = remoteStats?.hosts.filter((h) => h.sessionCount > 0).map((h) => h.name);
254199
254227
  const facets_summary = {
254200
254228
  total: facets.size,
@@ -257958,7 +257986,7 @@ var init_sessionStorage = __esm({
257958
257986
  init_settings2();
257959
257987
  init_slowOperations();
257960
257988
  init_uuid();
257961
- VERSION2 = typeof MACRO !== "undefined" ? "0.1.5" : "unknown";
257989
+ VERSION2 = typeof MACRO !== "undefined" ? "0.1.8" : "unknown";
257962
257990
  MAX_TOMBSTONE_REWRITE_BYTES = 50 * 1024 * 1024;
257963
257991
  SKIP_FIRST_PROMPT_PATTERN = /^(?:\s*<[a-z][\w-]*[\s>]|\[Request interrupted by user[^\]]*\])/;
257964
257992
  EPHEMERAL_PROGRESS_TYPES = /* @__PURE__ */ new Set([
@@ -267064,7 +267092,8 @@ async function verifyApiKey(apiKey, isNonInteractiveSession) {
267064
267092
  return true;
267065
267093
  }
267066
267094
  try {
267067
- const model = getSmallFastModel();
267095
+ const model = process.env.ANTHROPIC_MODEL?.trim() !== "" ? getMainLoopModel() : getSmallFastModel();
267096
+ const verificationTimeoutMs = parseInt(process.env.RUIDONG_VERIFY_API_TIMEOUT_MS || "", 10) || 15e3;
267068
267097
  const betas = getModelBetas(model);
267069
267098
  return await returnValue(
267070
267099
  withRetry(
@@ -267084,6 +267113,8 @@ async function verifyApiKey(apiKey, isNonInteractiveSession) {
267084
267113
  ...betas.length > 0 && { betas },
267085
267114
  metadata: getAPIMetadata(),
267086
267115
  ...getExtraBodyParams()
267116
+ }, {
267117
+ signal: AbortSignal.timeout(verificationTimeoutMs)
267087
267118
  });
267088
267119
  return true;
267089
267120
  },
@@ -267863,6 +267894,12 @@ ${deferredToolList}
267863
267894
  queryCheckpoint("query_response_headers_received");
267864
267895
  streamRequestId = result.request_id;
267865
267896
  streamResponse = result.response;
267897
+ const responseContentType = streamResponse.headers.get("content-type")?.toLowerCase();
267898
+ if (!isFirstPartyAnthropicBaseUrl() && responseContentType && !responseContentType.includes("text/event-stream")) {
267899
+ throw new Error(
267900
+ `Streaming endpoint returned non-SSE content-type: ${responseContentType}`
267901
+ );
267902
+ }
267866
267903
  return result.data;
267867
267904
  },
267868
267905
  {
@@ -267889,10 +267926,9 @@ ${deferredToolList}
267889
267926
  usage = EMPTY_USAGE;
267890
267927
  stopReason = null;
267891
267928
  isAdvisorInProgress = false;
267892
- const streamWatchdogEnabled = isEnvTruthy(
267893
- process.env.CLAUDE_ENABLE_STREAM_WATCHDOG
267894
- );
267895
- const STREAM_IDLE_TIMEOUT_MS = parseInt(process.env.CLAUDE_STREAM_IDLE_TIMEOUT_MS || "", 10) || 9e4;
267929
+ const isThirdPartyStreaming = !isFirstPartyAnthropicBaseUrl();
267930
+ const streamWatchdogEnabled = isThirdPartyStreaming || isEnvTruthy(process.env.CLAUDE_ENABLE_STREAM_WATCHDOG);
267931
+ const STREAM_IDLE_TIMEOUT_MS = parseInt(process.env.CLAUDE_STREAM_IDLE_TIMEOUT_MS || "", 10) || (isThirdPartyStreaming ? 3e4 : 9e4);
267896
267932
  const STREAM_IDLE_WARNING_MS = STREAM_IDLE_TIMEOUT_MS / 2;
267897
267933
  let streamIdleAborted = false;
267898
267934
  let streamWatchdogFiredAt = null;
@@ -305346,6 +305382,27 @@ async function checkAndInstallOfficialMarketplace() {
305346
305382
  });
305347
305383
  return { installed: false, skipped: true, reason: "policy_blocked" };
305348
305384
  }
305385
+ if (OFFICIAL_MARKETPLACE_SOURCE.source === "url") {
305386
+ logForDebugging(
305387
+ "Attempting to auto-install official marketplace from built-in URL source"
305388
+ );
305389
+ await addMarketplaceSource(OFFICIAL_MARKETPLACE_SOURCE);
305390
+ saveGlobalConfig((current) => ({
305391
+ ...current,
305392
+ officialMarketplaceAutoInstallAttempted: true,
305393
+ officialMarketplaceAutoInstalled: true,
305394
+ officialMarketplaceAutoInstallFailReason: void 0,
305395
+ officialMarketplaceAutoInstallRetryCount: void 0,
305396
+ officialMarketplaceAutoInstallLastAttemptTime: void 0,
305397
+ officialMarketplaceAutoInstallNextRetryTime: void 0
305398
+ }));
305399
+ logEvent("tengu_official_marketplace_auto_install", {
305400
+ installed: true,
305401
+ skipped: false,
305402
+ via_url: true
305403
+ });
305404
+ return { installed: true, skipped: false };
305405
+ }
305349
305406
  const cacheDir = getMarketplacesCacheDir();
305350
305407
  const installLocation = join139(cacheDir, OFFICIAL_MARKETPLACE_NAME);
305351
305408
  const gcsSha = await fetchOfficialMarketplaceFromGcs(
@@ -335614,473 +335671,6 @@ var init_mcp5 = __esm({
335614
335671
  }
335615
335672
  });
335616
335673
 
335617
- // build-src/src/cli/handlers/ruidongConfig.ts
335618
- var ruidongConfig_exports = {};
335619
- __export(ruidongConfig_exports, {
335620
- ruidongInitHandler: () => ruidongInitHandler
335621
- });
335622
- import { createInterface } from "node:readline/promises";
335623
- function applyFriendlyAliases(options) {
335624
- const hasExplicitCredential = Boolean(options.apiKey) || Boolean(options.apiKeyEnv) || Boolean(options.authToken) || Boolean(options.authTokenEnv);
335625
- const prefersGenericKey = !hasExplicitCredential && Boolean(options.key || options.keyEnv);
335626
- return {
335627
- ...options,
335628
- baseUrl: options.baseUrl ?? options.endpoint,
335629
- defaultModel: options.defaultModel ?? options.model,
335630
- authToken: options.authToken ?? (prefersGenericKey ? options.key : void 0),
335631
- authTokenEnv: options.authTokenEnv ?? (prefersGenericKey && options.keyEnv ? options.keyEnv : void 0),
335632
- authMode: options.authMode ?? (prefersGenericKey ? "auto" : void 0)
335633
- };
335634
- }
335635
- function hasSetupInput(options) {
335636
- return Boolean(options.profile) || Boolean(options.provider) || Boolean(options.endpoint) || Boolean(options.baseUrl) || Boolean(options.key) || Boolean(options.keyEnv) || Boolean(options.apiKey) || Boolean(options.apiKeyEnv) || Boolean(options.authToken) || Boolean(options.authTokenEnv) || Boolean(options.authMode) || Boolean(options.model) || Boolean(options.defaultModel);
335637
- }
335638
- function shouldRunInitWizard(options) {
335639
- if (!isInteractiveTerminal()) {
335640
- return false;
335641
- }
335642
- if (options.wizard) {
335643
- return true;
335644
- }
335645
- return !hasSetupInput(options);
335646
- }
335647
- function applyProfilePreset(options) {
335648
- if (!options.profile) {
335649
- return options;
335650
- }
335651
- const preset = INIT_PROFILE_PRESETS[options.profile];
335652
- return {
335653
- ...options,
335654
- provider: options.provider ?? preset.provider,
335655
- baseUrl: options.baseUrl ?? preset.baseUrl,
335656
- authMode: options.authMode ?? preset.authMode,
335657
- defaultModel: options.defaultModel ?? preset.defaultModel,
335658
- apiKeyEnv: options.apiKeyEnv ?? preset.apiKeyEnv,
335659
- authTokenEnv: options.authTokenEnv ?? preset.authTokenEnv
335660
- };
335661
- }
335662
- function shouldDefaultToAuthToken(provider) {
335663
- return provider === "anthropic-compatible" || provider === "deepseek" || provider === "qwen";
335664
- }
335665
- function resolveApiKeySetting(options) {
335666
- if (options.apiKey) {
335667
- return options.apiKey;
335668
- }
335669
- if (options.apiKeyEnv) {
335670
- return `env:${options.apiKeyEnv}`;
335671
- }
335672
- return "env:RUIDONG_API_KEY";
335673
- }
335674
- function resolveAuthTokenSetting(options) {
335675
- if (options.authToken) {
335676
- return options.authToken;
335677
- }
335678
- if (options.authTokenEnv) {
335679
- return `env:${options.authTokenEnv}`;
335680
- }
335681
- if (shouldDefaultToAuthToken(options.provider)) {
335682
- return "env:RUIDONG_API_KEY";
335683
- }
335684
- return void 0;
335685
- }
335686
- function resolveAuthMode2(options) {
335687
- if (options.authMode) {
335688
- return options.authMode;
335689
- }
335690
- if (shouldDefaultToAuthToken(options.provider)) {
335691
- return "auto";
335692
- }
335693
- return resolveAuthTokenSetting(options) ? "bearer" : "auto";
335694
- }
335695
- function buildMarketplaceConfig(options) {
335696
- if (options.officialMarketplaceUrl) {
335697
- return {
335698
- official: {
335699
- name: options.officialMarketplaceName ?? "ruidong-marketplace-seed",
335700
- source: {
335701
- source: "url",
335702
- url: options.officialMarketplaceUrl
335703
- }
335704
- }
335705
- };
335706
- }
335707
- if (options.officialMarketplaceGitUrl) {
335708
- return {
335709
- official: {
335710
- name: options.officialMarketplaceName ?? "ruidong-marketplace-seed",
335711
- source: {
335712
- source: "git",
335713
- url: options.officialMarketplaceGitUrl,
335714
- ...options.officialMarketplaceRef && {
335715
- ref: options.officialMarketplaceRef
335716
- },
335717
- ...options.officialMarketplacePath && {
335718
- path: options.officialMarketplacePath
335719
- },
335720
- ...options.officialMarketplaceSparse && options.officialMarketplaceSparse.length > 0 && {
335721
- sparsePaths: options.officialMarketplaceSparse
335722
- }
335723
- }
335724
- }
335725
- };
335726
- }
335727
- return {
335728
- official: {
335729
- name: options.officialMarketplaceName ?? "ruidong-marketplace-seed",
335730
- source: {
335731
- source: "github",
335732
- repo: options.officialMarketplaceRepo ?? "Jackwwg83/ruidong-marketplace-seed",
335733
- ...options.officialMarketplaceRef && {
335734
- ref: options.officialMarketplaceRef
335735
- },
335736
- ...options.officialMarketplacePath && {
335737
- path: options.officialMarketplacePath
335738
- },
335739
- ...options.officialMarketplaceSparse && options.officialMarketplaceSparse.length > 0 && {
335740
- sparsePaths: options.officialMarketplaceSparse
335741
- }
335742
- }
335743
- }
335744
- };
335745
- }
335746
- function resolveSecretSettingValue(secretSetting) {
335747
- if (!secretSetting) {
335748
- return void 0;
335749
- }
335750
- if (!secretSetting.startsWith("env:")) {
335751
- return secretSetting;
335752
- }
335753
- const envName = secretSetting.slice(4).trim();
335754
- return envName ? process.env[envName] : void 0;
335755
- }
335756
- function isInteractiveTerminal() {
335757
- return process.stdin.isTTY === true && process.stdout.isTTY === true;
335758
- }
335759
- async function promptLine(rl, prompt, defaultValue) {
335760
- const suffix = defaultValue ? ` [${defaultValue}]` : "";
335761
- const answer = (await rl.question(`${prompt}${suffix}: `)).trim();
335762
- return answer || defaultValue || "";
335763
- }
335764
- async function promptWizardMode(rl) {
335765
- process.stdout.write(
335766
- "Ruidong Code setup\n\n 1. Generic gateway (recommended)\n 2. Claude relay (crs preset)\n 3. iruidong gateway\n\n"
335767
- );
335768
- while (true) {
335769
- const answer = (await rl.question("Choose setup mode [1-3] [1]: ")).trim();
335770
- const normalized = answer || "1";
335771
- if (normalized === "1") {
335772
- return "generic";
335773
- }
335774
- if (normalized === "2") {
335775
- return "crs";
335776
- }
335777
- if (normalized === "3") {
335778
- return "iruidong";
335779
- }
335780
- process.stdout.write("Please choose 1, 2, or 3.\n");
335781
- }
335782
- }
335783
- async function promptEndpoint(rl, initialValue) {
335784
- while (true) {
335785
- const candidate = await promptLine(rl, "API endpoint URL", initialValue);
335786
- try {
335787
- const parsed = new URL(candidate);
335788
- if (parsed.protocol === "http:" || parsed.protocol === "https:") {
335789
- return candidate;
335790
- }
335791
- } catch {
335792
- }
335793
- process.stdout.write("Please enter a valid http:// or https:// URL.\n");
335794
- }
335795
- }
335796
- async function promptSecretValue(rl, label, existingValue) {
335797
- if (existingValue && existingValue.trim()) {
335798
- return existingValue.trim();
335799
- }
335800
- while (true) {
335801
- const value = (await rl.question(`${label}: `)).trim();
335802
- if (value) {
335803
- return value;
335804
- }
335805
- process.stdout.write("Please enter a non-empty API key.\n");
335806
- }
335807
- }
335808
- async function maybeConfirmOverwriteExistingConfig() {
335809
- if (!hasRuidongConfig() || !isInteractiveTerminal()) {
335810
- return true;
335811
- }
335812
- const rl = createInterface({
335813
- input: process.stdin,
335814
- output: process.stdout
335815
- });
335816
- try {
335817
- const answer = (await rl.question(
335818
- `Ruidong config already exists at ${getRuidongConfigPath()}. Overwrite it? [y/N]: `
335819
- )).trim().toLowerCase();
335820
- return answer === "y" || answer === "yes";
335821
- } finally {
335822
- rl.close();
335823
- }
335824
- }
335825
- async function runInitWizard(options) {
335826
- const rl = createInterface({
335827
- input: process.stdin,
335828
- output: process.stdout
335829
- });
335830
- try {
335831
- const mode = await promptWizardMode(rl);
335832
- if (mode === "crs") {
335833
- const apiKey = await promptSecretValue(
335834
- rl,
335835
- "API key (will be saved to ~/.ruidong-code/config.json)",
335836
- options.apiKey ?? options.key
335837
- );
335838
- return {
335839
- ...options,
335840
- profile: "crs",
335841
- apiKey
335842
- };
335843
- }
335844
- if (mode === "iruidong") {
335845
- const authToken = await promptSecretValue(
335846
- rl,
335847
- "API key (will be saved to ~/.ruidong-code/config.json)",
335848
- options.authToken ?? options.key
335849
- );
335850
- return {
335851
- ...options,
335852
- profile: "iruidong",
335853
- authToken
335854
- };
335855
- }
335856
- const baseUrl = await promptEndpoint(rl, options.baseUrl ?? options.endpoint);
335857
- const key = await promptSecretValue(
335858
- rl,
335859
- "API key (will be saved to ~/.ruidong-code/config.json)",
335860
- options.key ?? options.authToken ?? options.apiKey
335861
- );
335862
- process.stdout.write(
335863
- "\nDefault model is optional. Ruidong Code will now try to discover models from the gateway.\n\n"
335864
- );
335865
- return {
335866
- ...options,
335867
- provider: options.provider ?? "anthropic-compatible",
335868
- baseUrl,
335869
- key
335870
- };
335871
- } finally {
335872
- rl.close();
335873
- }
335874
- }
335875
- function moveSuggestedModelToFront(models, suggestedModel) {
335876
- if (!suggestedModel) {
335877
- return [...models];
335878
- }
335879
- const index = models.findIndex(
335880
- (model) => model.toLowerCase() === suggestedModel.toLowerCase()
335881
- );
335882
- if (index <= 0) {
335883
- return [...models];
335884
- }
335885
- const reordered = [...models];
335886
- const [match] = reordered.splice(index, 1);
335887
- reordered.unshift(match);
335888
- return reordered;
335889
- }
335890
- async function promptForDefaultModel(models, suggestedModel) {
335891
- const orderedModels = moveSuggestedModelToFront(models, suggestedModel);
335892
- const visibleModels = orderedModels.slice(0, MAX_DISCOVERED_MODELS_TO_PRINT);
335893
- process.stdout.write("\nDiscovered gateway models:\n");
335894
- for (const [index, model] of visibleModels.entries()) {
335895
- const recommended = suggestedModel && model.toLowerCase() === suggestedModel.toLowerCase() ? " (recommended)" : "";
335896
- process.stdout.write(` ${String(index + 1).padStart(2, " ")}. ${model}${recommended}
335897
- `);
335898
- }
335899
- if (orderedModels.length > visibleModels.length) {
335900
- process.stdout.write(
335901
- ` ...and ${String(orderedModels.length - visibleModels.length)} more hidden models
335902
- `
335903
- );
335904
- }
335905
- const question = suggestedModel ? `Select default model [1-${String(visibleModels.length)}], type a model id, press Enter to use ${suggestedModel}, or type "skip" to choose later with /model: ` : `Select default model [1-${String(visibleModels.length)}], type a model id, or press Enter to choose later with /model: `;
335906
- const rl = createInterface({
335907
- input: process.stdin,
335908
- output: process.stdout
335909
- });
335910
- try {
335911
- const rawAnswer = (await rl.question(question)).trim();
335912
- if (!rawAnswer) {
335913
- return suggestedModel;
335914
- }
335915
- if (/^(skip|none|later)$/i.test(rawAnswer)) {
335916
- return void 0;
335917
- }
335918
- const selectedIndex = Number(rawAnswer);
335919
- if (Number.isInteger(selectedIndex) && selectedIndex >= 1 && selectedIndex <= visibleModels.length) {
335920
- return visibleModels[selectedIndex - 1];
335921
- }
335922
- return rawAnswer;
335923
- } finally {
335924
- rl.close();
335925
- }
335926
- }
335927
- async function resolveDefaultModelChoice(options, explicitDefaultModel) {
335928
- if (explicitDefaultModel) {
335929
- return options.defaultModel;
335930
- }
335931
- const suggestedModel = options.defaultModel;
335932
- if (!options.baseUrl) {
335933
- return suggestedModel;
335934
- }
335935
- const authTokenSetting = resolveAuthTokenSetting(options);
335936
- const apiKeySetting = authTokenSetting ? void 0 : resolveApiKeySetting(options);
335937
- const discoveredModels = await discoverAnthropicCompatibleModels({
335938
- baseUrl: options.baseUrl,
335939
- authMode: resolveAuthMode2(options),
335940
- apiKey: resolveSecretSettingValue(apiKeySetting),
335941
- authToken: resolveSecretSettingValue(authTokenSetting)
335942
- });
335943
- if (discoveredModels === null) {
335944
- return suggestedModel;
335945
- }
335946
- if (discoveredModels.length === 0) {
335947
- return suggestedModel;
335948
- }
335949
- if (discoveredModels.length === 1) {
335950
- const autoSelectedModel = discoveredModels[0];
335951
- process.stdout.write(
335952
- `Discovered a single gateway model: ${autoSelectedModel}
335953
- Using it as the default model.
335954
-
335955
- `
335956
- );
335957
- return autoSelectedModel;
335958
- }
335959
- if (!isInteractiveTerminal()) {
335960
- return suggestedModel;
335961
- }
335962
- return promptForDefaultModel(discoveredModels, suggestedModel);
335963
- }
335964
- async function ruidongInitHandler(options) {
335965
- const wizardOptions = shouldRunInitWizard(options) ? await runInitWizard(options) : options;
335966
- const optionsWithAliases = applyFriendlyAliases(wizardOptions);
335967
- const explicitDefaultModel = Boolean(optionsWithAliases.defaultModel);
335968
- const optionsWithProfile = applyProfilePreset(optionsWithAliases);
335969
- if (hasRuidongConfig() && !optionsWithProfile.force) {
335970
- if (await maybeConfirmOverwriteExistingConfig()) {
335971
- optionsWithProfile.force = true;
335972
- } else {
335973
- process.stdout.write("Init cancelled.\n");
335974
- process.exit(0);
335975
- }
335976
- }
335977
- const shouldMigrateHome = optionsWithProfile.migrateHome === true || process.env.RUIDONG_CONFIG_DIR === void 0 && process.env.CLAUDE_CONFIG_DIR === void 0;
335978
- const migrationResult = shouldMigrateHome ? migrateLegacyClaudeHomeToRuidongHome() : { migrated: false, copiedEntries: 0, copiedGlobalConfig: false };
335979
- const provider = optionsWithProfile.provider ?? "anthropic-compatible";
335980
- const resolvedOptions = {
335981
- ...optionsWithProfile,
335982
- provider
335983
- };
335984
- const defaultModel = await resolveDefaultModelChoice(
335985
- resolvedOptions,
335986
- explicitDefaultModel
335987
- );
335988
- const resolvedOptionsWithModel = {
335989
- ...resolvedOptions,
335990
- defaultModel
335991
- };
335992
- const authToken = resolveAuthTokenSetting(resolvedOptionsWithModel);
335993
- const config2 = {
335994
- provider: {
335995
- id: provider,
335996
- authMode: resolveAuthMode2(resolvedOptionsWithModel),
335997
- ...authToken ? { authToken } : { apiKey: resolveApiKeySetting(resolvedOptionsWithModel) },
335998
- ...resolvedOptionsWithModel.baseUrl && {
335999
- baseUrl: resolvedOptionsWithModel.baseUrl
336000
- },
336001
- ...resolvedOptionsWithModel.defaultModel && {
336002
- defaultModel: resolvedOptionsWithModel.defaultModel
336003
- }
336004
- },
336005
- marketplace: buildMarketplaceConfig(resolvedOptionsWithModel),
336006
- ...resolvedOptionsWithModel.officialMcpRegistryUrl && {
336007
- mcp: {
336008
- officialRegistryUrl: resolvedOptionsWithModel.officialMcpRegistryUrl
336009
- }
336010
- }
336011
- };
336012
- writeRuidongConfig(config2);
336013
- process.stdout.write(
336014
- `Ruidong config written to ${getRuidongConfigPath()}
336015
-
336016
- ${resolvedOptionsWithModel.profile ? `Profile: ${resolvedOptionsWithModel.profile}
336017
- ` : ""}Provider: ${config2.provider?.id ?? "anthropic-compatible"}
336018
- Auth mode: ${config2.provider?.authMode ?? "auto"}
336019
- Default model: ${config2.provider?.defaultModel ?? "not set (choose later with /model)"}
336020
- Official marketplace: ${config2.marketplace?.official?.name ?? "ruidong-marketplace-seed"}
336021
- ${config2.provider?.authToken ? `Credential storage: ${config2.provider.authToken.startsWith("env:") ? `env var ${config2.provider.authToken.slice(4)}` : "saved directly in config.json"}
336022
- ` : `Credential storage: ${config2.provider?.apiKey?.startsWith("env:") ? `env var ${config2.provider.apiKey.slice(4)}` : "saved directly in config.json"}
336023
- `}`
336024
- );
336025
- if (migrationResult.migrated) {
336026
- process.stdout.write(
336027
- `
336028
- Migrated legacy home into ${getRuidongConfigPath().replace(/\\/g, "/").replace(/\/config\.json$/, "")}
336029
- Copied home entries: ${String(migrationResult.copiedEntries)}
336030
- Copied global config: ${migrationResult.copiedGlobalConfig ? "yes" : "no"}
336031
- `
336032
- );
336033
- }
336034
- if (config2.provider?.apiKey?.startsWith("env:")) {
336035
- process.stdout.write(
336036
- `
336037
- Next step:
336038
- export ${config2.provider.apiKey.slice(4)}=your_api_key_here
336039
- `
336040
- );
336041
- }
336042
- if (config2.provider?.authToken?.startsWith("env:")) {
336043
- process.stdout.write(
336044
- `
336045
- Next step:
336046
- export ${config2.provider.authToken.slice(4)}=your_auth_token_here
336047
- `
336048
- );
336049
- }
336050
- if (!config2.provider?.defaultModel) {
336051
- process.stdout.write(
336052
- `
336053
- After launch:
336054
- run /model to choose a gateway model interactively
336055
- `
336056
- );
336057
- }
336058
- }
336059
- var INIT_PROFILE_PRESETS, MAX_DISCOVERED_MODELS_TO_PRINT;
336060
- var init_ruidongConfig2 = __esm({
336061
- "build-src/src/cli/handlers/ruidongConfig.ts"() {
336062
- init_ruidongConfig();
336063
- init_providerModelDiscovery();
336064
- INIT_PROFILE_PRESETS = {
336065
- crs: {
336066
- provider: "anthropic",
336067
- baseUrl: "http://18.141.210.162:3000/api",
336068
- authMode: "api-key",
336069
- defaultModel: "sonnet",
336070
- apiKeyEnv: "RUIDONG_API_KEY"
336071
- },
336072
- iruidong: {
336073
- provider: "anthropic-compatible",
336074
- baseUrl: "https://iruidong.com",
336075
- authMode: "auto",
336076
- defaultModel: "glm",
336077
- authTokenEnv: "RUIDONG_API_KEY"
336078
- }
336079
- };
336080
- MAX_DISCOVERED_MODELS_TO_PRINT = 25;
336081
- }
336082
- });
336083
-
336084
335674
  // build-src/src/cli/handlers/plugins.ts
336085
335675
  var plugins_exports = {};
336086
335676
  __export(plugins_exports, {
@@ -340294,13 +339884,6 @@ Auth: unix socket -R \u2192 local proxy`, "info");
340294
339884
  await runConnectHeadless(connectConfig, prompt, opts.outputFormat, interactive);
340295
339885
  });
340296
339886
  }
340297
- program.command("init").description("Create or update ~/.ruidong-code/config.json for Ruidong Code runtime configuration").option("--force", "Overwrite existing Ruidong config").option("--wizard", "Run the interactive setup wizard (default when no init options are provided)").option("--profile <profile>", "Quick profile preset: crs or iruidong").option("--endpoint <url>", "User-friendly alias for --base-url").option("--key <key>", "User-friendly provider key (auto-mapped to compatible auth settings)").option("--key-env <name>", "User-friendly alias to read provider key from env (example: RUIDONG_API_KEY)").option("--model <model>", "Optional alias for --default-model. If omitted, init can discover models or you can choose later via /model").option("--provider <provider>", "Provider id: anthropic, anthropic-compatible, deepseek, qwen, bedrock, vertex, or foundry").option("--base-url <url>", "Provider base URL (recommended for anthropic-compatible gateways)").option("--api-key <key>", "Write a direct API key into the config file").option("--api-key-env <name>", "Store an env reference instead of a raw key (default: RUIDONG_API_KEY)").option("--auth-token <token>", "Write a direct auth token into the config file (for relay/proxy deployments)").option("--auth-token-env <name>", "Store an env reference for auth token mode").option("--auth-mode <mode>", "Provider auth mode: auto, api-key, or bearer").option("--default-model <model>", "Optional default model. If omitted, init can discover models or you can choose later via /model").option("--official-marketplace-name <name>", "Official marketplace name to register", "ruidong-marketplace-seed").option("--official-marketplace-repo <repo>", "GitHub repo for the official marketplace", "Jackwwg83/ruidong-marketplace-seed").option("--official-marketplace-git-url <url>", "Git URL for the official marketplace").option("--official-marketplace-url <url>", "Direct URL for the official marketplace manifest").option("--official-marketplace-ref <ref>", "Git ref for the official marketplace").option("--official-marketplace-path <path>", "Path to marketplace.json inside the git repo").option("--official-marketplace-sparse <paths...>", "Sparse checkout paths for monorepo marketplace sources").option("--official-mcp-registry-url <url>", "URL for the official MCP registry feed").option("--migrate-home", "Copy missing files from legacy config home into ~/.ruidong-code before writing config").action(async (options) => {
340298
- const {
340299
- ruidongInitHandler: ruidongInitHandler2
340300
- } = await Promise.resolve().then(() => (init_ruidongConfig2(), ruidongConfig_exports));
340301
- await ruidongInitHandler2(options);
340302
- process.exit(0);
340303
- });
340304
339887
  const auth = program.command("auth").description("Manage authentication").configureHelp(createSortedHelpConfig());
340305
339888
  auth.command("login").description("Sign in to your Anthropic account").option("--email <email>", "Pre-populate email address on the login page").option("--sso", "Force SSO login flow").option("--console", "Use Anthropic Console (API usage billing) instead of Claude subscription").option("--claudeai", "Use Claude subscription (default)").action(async ({
340306
339889
  email,
@@ -340879,6 +340462,12 @@ async function main2() {
340879
340462
  console.log(`Ruidong Code v${PUBLIC_CLI_VERSION}`);
340880
340463
  return;
340881
340464
  }
340465
+ if (args[0] === "init") {
340466
+ console.error("`ruidong init` has been removed.");
340467
+ console.error("Configure your shell with ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY, then run `ruidong`.");
340468
+ process.exitCode = 1;
340469
+ return;
340470
+ }
340882
340471
  const {
340883
340472
  profileCheckpoint: profileCheckpoint2
340884
340473
  } = await Promise.resolve().then(() => (init_startupProfiler(), startupProfiler_exports));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iruidong/code",
3
- "version": "0.1.5",
3
+ "version": "0.1.8",
4
4
  "description": "Ruidong Code CLI for anthropic-compatible coding workflows",
5
5
  "type": "module",
6
6
  "private": false,