@iruidong/code 0.1.7 → 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.
package/QUICKSTART.md CHANGED
@@ -10,7 +10,7 @@ ruidong --version
10
10
  Expected output:
11
11
 
12
12
  ```bash
13
- Ruidong Code v0.1.7
13
+ Ruidong Code v0.1.8
14
14
  ```
15
15
 
16
16
  ## 2. Configure your shell
@@ -94,6 +94,12 @@ If an old `~/.ruidong-code/config.json` keeps interfering, remove it:
94
94
  rm -f ~/.ruidong-code/config.json
95
95
  ```
96
96
 
97
+ If you tested an old temporary setup flow before, also clear any config-dir override:
98
+
99
+ ```bash
100
+ unset RUIDONG_CONFIG_DIR CLAUDE_CONFIG_DIR
101
+ ```
102
+
97
103
  Need more debug output:
98
104
 
99
105
  ```bash
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // ruidong v0.1.7 (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,7 +81,7 @@ 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.7";
84
+ PUBLIC_CLI_VERSION = "0.1.8";
85
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];
@@ -13003,6 +13003,30 @@ 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
  }
@@ -13033,9 +13057,13 @@ function getRuidongRuntimeProviderConfig() {
13033
13057
  if (!provider) {
13034
13058
  return null;
13035
13059
  }
13060
+ const baseUrl = sanitizeConfiguredUrl(provider.baseUrl, "provider.baseUrl");
13061
+ if (provider.id === "anthropic-compatible" && !baseUrl) {
13062
+ return null;
13063
+ }
13036
13064
  return {
13037
13065
  id: provider.id,
13038
- baseUrl: provider.baseUrl,
13066
+ baseUrl,
13039
13067
  apiKey: resolveSecretValue(provider.apiKey),
13040
13068
  authToken: resolveSecretValue(provider.authToken),
13041
13069
  authMode: provider.authMode ?? "auto",
@@ -13062,7 +13090,7 @@ function getResolvedRuidongVoiceConfig() {
13062
13090
  ...voice2.stt && {
13063
13091
  stt: {
13064
13092
  provider: voice2.stt.provider,
13065
- baseUrl: voice2.stt.baseUrl,
13093
+ baseUrl: sanitizeConfiguredUrl(voice2.stt.baseUrl, "voice.stt.baseUrl"),
13066
13094
  apiKey: resolveSecretValue(voice2.stt.apiKey),
13067
13095
  model: voice2.stt.model,
13068
13096
  language: voice2.stt.language,
@@ -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,8 +13223,12 @@ function applyRuidongRuntimeConfig() {
13189
13223
  const provider = config2.provider;
13190
13224
  if (provider) {
13191
13225
  applyProviderFlags(provider.id);
13192
- if (provider.baseUrl !== void 0) {
13193
- setEnvIfUnset("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) {
@@ -13203,13 +13241,17 @@ function applyRuidongRuntimeConfig() {
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
13250
  var RuidongProviderIdSchema, RuidongAuthModeSchema, RuidongVoiceSttProviderSchema, OfficialMarketplaceSourceSchema, RuidongConfigSchema, configCache;
13210
13251
  var init_ruidongConfig = __esm({
13211
13252
  "build-src/src/utils/ruidongConfig.ts"() {
13212
13253
  init_envUtils();
13254
+ init_debug();
13213
13255
  init_env();
13214
13256
  RuidongProviderIdSchema = z9.enum([
13215
13257
  "anthropic",
@@ -75106,7 +75148,7 @@ async function setupSdkMcpClients(sdkMcpConfigs, sendMcpMessage) {
75106
75148
  {
75107
75149
  name: "ruidong-code",
75108
75150
  title: "ruidong",
75109
- version: "0.1.7",
75151
+ version: "0.1.8",
75110
75152
  description: "Ruidong Code agentic coding tool",
75111
75153
  websiteUrl: PRODUCT_URL
75112
75154
  },
@@ -75529,7 +75571,7 @@ var init_client3 = __esm({
75529
75571
  {
75530
75572
  name: "ruidong-code",
75531
75573
  title: "ruidong",
75532
- version: "0.1.7",
75574
+ version: "0.1.8",
75533
75575
  description: "Ruidong Code agentic coding tool",
75534
75576
  websiteUrl: PRODUCT_URL
75535
75577
  },
@@ -87228,7 +87270,7 @@ async function installGlobalPackage(specificVersion) {
87228
87270
  );
87229
87271
  logEvent("tengu_auto_updater_lock_contention", {
87230
87272
  pid: process.pid,
87231
- currentVersion: "0.1.7"
87273
+ currentVersion: "0.1.8"
87232
87274
  });
87233
87275
  return "in_progress";
87234
87276
  }
@@ -87237,7 +87279,7 @@ async function installGlobalPackage(specificVersion) {
87237
87279
  if (!env.isRunningWithBun() && env.isNpmFromWindowsPath()) {
87238
87280
  logError(new Error("Windows NPM detected in WSL environment"));
87239
87281
  logEvent("tengu_auto_updater_windows_npm_in_wsl", {
87240
- currentVersion: "0.1.7"
87282
+ currentVersion: "0.1.8"
87241
87283
  });
87242
87284
  console.error(`
87243
87285
  Error: Windows NPM detected in WSL
@@ -87581,7 +87623,7 @@ function detectProviderConfigWarnings() {
87581
87623
  if (usingThirdPartyEndpoint && !resolvedApiKey && !resolvedAuthToken) {
87582
87624
  warnings.push({
87583
87625
  issue: "Third-party endpoint is configured but no API credential is available",
87584
- 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"
87585
87627
  });
87586
87628
  }
87587
87629
  if (requestedAuthMode === "auto" && resolvedApiKey && resolvedAuthToken) {
@@ -87904,7 +87946,7 @@ function detectLinuxGlobPatternWarnings() {
87904
87946
  }
87905
87947
  async function getDoctorDiagnostic() {
87906
87948
  const installationType = await getCurrentInstallationType();
87907
- const version2 = typeof MACRO !== "undefined" && "0.1.7" ? "0.1.7" : "unknown";
87949
+ const version2 = typeof MACRO !== "undefined" && "0.1.8" ? "0.1.8" : "unknown";
87908
87950
  const installationPath = await getInstallationPath();
87909
87951
  const invokedBinary = getInvokedBinary();
87910
87952
  const multipleInstallations = await detectMultipleInstallations();
@@ -88984,7 +89026,7 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
88984
89026
  version2 = maxVersion;
88985
89027
  }
88986
89028
  }
88987
- if (!forceReinstall && version2 === "0.1.7" && await versionIsAvailable(version2) && await isPossibleClaudeBinary(executablePath)) {
89029
+ if (!forceReinstall && version2 === "0.1.8" && await versionIsAvailable(version2) && await isPossibleClaudeBinary(executablePath)) {
88988
89030
  logForDebugging(`Found ${version2} at ${executablePath}, skipping install`);
88989
89031
  logEvent("tengu_native_update_complete", {
88990
89032
  latency_ms: Date.now() - startTime,
@@ -185070,6 +185112,19 @@ var init_modifiers = __esm({
185070
185112
 
185071
185113
  // build-src/src/hooks/useTextInput.ts
185072
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
+ }
185073
185128
  function mapInput(input_map) {
185074
185129
  const map = new Map(input_map);
185075
185130
  return function(input) {
@@ -185342,7 +185397,10 @@ function useTextInput({
185342
185397
  case (input === "\x1B[F" || input === "\x1B[4~"):
185343
185398
  return cursor.endOfLine();
185344
185399
  default: {
185345
- 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
+ );
185346
185404
  if (cursor.isAtStart() && isInputModeCharacter(input)) {
185347
185405
  return cursor.insert(text).left();
185348
185406
  }
@@ -185370,11 +185428,16 @@ function useTextInput({
185370
185428
  if (filteredInput === "" && input !== "") {
185371
185429
  return;
185372
185430
  }
185373
- if (!key.backspace && !key.delete && input.includes("\x7F")) {
185374
- 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));
185375
185434
  let currentCursor = cursor;
185376
- for (let i = 0; i < delCount; i++) {
185377
- 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);
185378
185441
  }
185379
185442
  if (!cursor.equals(currentCursor)) {
185380
185443
  if (cursor.text !== currentCursor.text) {
@@ -185384,6 +185447,9 @@ function useTextInput({
185384
185447
  }
185385
185448
  resetKillAccumulation();
185386
185449
  resetYankState();
185450
+ if (coalescedSubmitSuffix) {
185451
+ onSubmit?.(currentCursor.text);
185452
+ }
185387
185453
  return;
185388
185454
  }
185389
185455
  if (!isKillKey2(key, filteredInput)) {
@@ -185400,9 +185466,7 @@ function useTextInput({
185400
185466
  }
185401
185467
  setOffset(nextCursor.offset);
185402
185468
  }
185403
- if (filteredInput.length > 1 && filteredInput.endsWith("\r") && !filteredInput.slice(0, -1).includes("\r") && // Backslash+CR is a stale VS Code Shift+Enter binding, not
185404
- // coalesced Enter. See default handler above.
185405
- filteredInput[filteredInput.length - 2] !== "\\") {
185469
+ if (coalescedSubmitSuffix) {
185406
185470
  onSubmit?.(nextCursor.text);
185407
185471
  }
185408
185472
  }
@@ -187844,7 +187908,7 @@ ${sanitizedDescription}
187844
187908
  **Environment Info**
187845
187909
  - Platform: ${env.platform}
187846
187910
  - Terminal: ${env.terminal}
187847
- - Version: ${"0.1.7"}
187911
+ - Version: ${"0.1.8"}
187848
187912
  - Feedback ID: ${feedbackId}
187849
187913
 
187850
187914
  **Errors**
@@ -254158,7 +254222,7 @@ function generateHtmlReport(data, insights) {
254158
254222
  </html>`;
254159
254223
  }
254160
254224
  function buildExportData(data, insights, facets, remoteStats) {
254161
- const version2 = typeof MACRO !== "undefined" ? "0.1.7" : "unknown";
254225
+ const version2 = typeof MACRO !== "undefined" ? "0.1.8" : "unknown";
254162
254226
  const remote_hosts_collected = remoteStats?.hosts.filter((h) => h.sessionCount > 0).map((h) => h.name);
254163
254227
  const facets_summary = {
254164
254228
  total: facets.size,
@@ -257922,7 +257986,7 @@ var init_sessionStorage = __esm({
257922
257986
  init_settings2();
257923
257987
  init_slowOperations();
257924
257988
  init_uuid();
257925
- VERSION2 = typeof MACRO !== "undefined" ? "0.1.7" : "unknown";
257989
+ VERSION2 = typeof MACRO !== "undefined" ? "0.1.8" : "unknown";
257926
257990
  MAX_TOMBSTONE_REWRITE_BYTES = 50 * 1024 * 1024;
257927
257991
  SKIP_FIRST_PROMPT_PATTERN = /^(?:\s*<[a-z][\w-]*[\s>]|\[Request interrupted by user[^\]]*\])/;
257928
257992
  EPHEMERAL_PROGRESS_TYPES = /* @__PURE__ */ new Set([
@@ -267028,7 +267092,8 @@ async function verifyApiKey(apiKey, isNonInteractiveSession) {
267028
267092
  return true;
267029
267093
  }
267030
267094
  try {
267031
- 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;
267032
267097
  const betas = getModelBetas(model);
267033
267098
  return await returnValue(
267034
267099
  withRetry(
@@ -267048,6 +267113,8 @@ async function verifyApiKey(apiKey, isNonInteractiveSession) {
267048
267113
  ...betas.length > 0 && { betas },
267049
267114
  metadata: getAPIMetadata(),
267050
267115
  ...getExtraBodyParams()
267116
+ }, {
267117
+ signal: AbortSignal.timeout(verificationTimeoutMs)
267051
267118
  });
267052
267119
  return true;
267053
267120
  },
@@ -267827,6 +267894,12 @@ ${deferredToolList}
267827
267894
  queryCheckpoint("query_response_headers_received");
267828
267895
  streamRequestId = result.request_id;
267829
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
+ }
267830
267903
  return result.data;
267831
267904
  },
267832
267905
  {
@@ -267853,10 +267926,9 @@ ${deferredToolList}
267853
267926
  usage = EMPTY_USAGE;
267854
267927
  stopReason = null;
267855
267928
  isAdvisorInProgress = false;
267856
- const streamWatchdogEnabled = isEnvTruthy(
267857
- process.env.CLAUDE_ENABLE_STREAM_WATCHDOG
267858
- );
267859
- 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);
267860
267932
  const STREAM_IDLE_WARNING_MS = STREAM_IDLE_TIMEOUT_MS / 2;
267861
267933
  let streamIdleAborted = false;
267862
267934
  let streamWatchdogFiredAt = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iruidong/code",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Ruidong Code CLI for anthropic-compatible coding workflows",
5
5
  "type": "module",
6
6
  "private": false,