@rdmind/rdmind 0.2.3-alpha.5 → 0.2.3

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/cli.js CHANGED
@@ -157519,18 +157519,24 @@ var init_converter2 = __esm({
157519
157519
  }
157520
157520
  model;
157521
157521
  schemaCompliance;
157522
- constructor(model, schemaCompliance = "auto") {
157522
+ disableCacheControl;
157523
+ constructor(model, schemaCompliance = "auto", disableCacheControl = false) {
157523
157524
  this.model = model;
157524
157525
  this.schemaCompliance = schemaCompliance;
157526
+ this.disableCacheControl = disableCacheControl;
157525
157527
  }
157526
157528
  convertGeminiRequestToAnthropic(request4) {
157527
157529
  const messages = [];
157528
- const system = this.extractTextFromContentUnion(
157530
+ const systemText = this.extractTextFromContentUnion(
157529
157531
  request4.config?.systemInstruction
157530
157532
  );
157531
157533
  this.processContents(request4.contents, messages);
157534
+ const system = this.disableCacheControl ? systemText : this.buildSystemWithCacheControl(systemText);
157535
+ if (!this.disableCacheControl) {
157536
+ this.addCacheControlToMessages(messages);
157537
+ }
157532
157538
  return {
157533
- system: system || void 0,
157539
+ system,
157534
157540
  messages
157535
157541
  };
157536
157542
  }
@@ -157570,6 +157576,13 @@ var init_converter2 = __esm({
157570
157576
  });
157571
157577
  }
157572
157578
  }
157579
+ if (!this.disableCacheControl && tools.length > 0) {
157580
+ const lastToolIndex = tools.length - 1;
157581
+ tools[lastToolIndex] = {
157582
+ ...tools[lastToolIndex],
157583
+ cache_control: { type: "ephemeral" }
157584
+ };
157585
+ }
157573
157586
  return tools;
157574
157587
  }
157575
157588
  convertAnthropicResponseToGemini(response) {
@@ -157858,6 +157871,44 @@ var init_converter2 = __esm({
157858
157871
  isContentObject(content) {
157859
157872
  return typeof content === "object" && content !== null && "role" in content && "parts" in content && Array.isArray(content["parts"]);
157860
157873
  }
157874
+ /**
157875
+ * Build system content blocks with cache_control.
157876
+ * Anthropic prompt caching requires cache_control on system content.
157877
+ */
157878
+ buildSystemWithCacheControl(systemText) {
157879
+ if (!systemText) {
157880
+ return systemText;
157881
+ }
157882
+ return [
157883
+ {
157884
+ type: "text",
157885
+ text: systemText,
157886
+ cache_control: { type: "ephemeral" }
157887
+ }
157888
+ ];
157889
+ }
157890
+ /**
157891
+ * Add cache_control to the last user message's content.
157892
+ * This enables prompt caching for the conversation context.
157893
+ */
157894
+ addCacheControlToMessages(messages) {
157895
+ for (let i3 = messages.length - 1; i3 >= 0; i3--) {
157896
+ const msg = messages[i3];
157897
+ if (msg.role === "user") {
157898
+ const content = Array.isArray(msg.content) ? msg.content : [{ type: "text", text: msg.content }];
157899
+ if (content.length > 0) {
157900
+ const lastContent = content[content.length - 1];
157901
+ if (typeof lastContent === "object" && "type" in lastContent && lastContent.type === "text" && "text" in lastContent && lastContent.text) {
157902
+ lastContent.cache_control = {
157903
+ type: "ephemeral"
157904
+ };
157905
+ }
157906
+ msg.content = content;
157907
+ }
157908
+ break;
157909
+ }
157910
+ }
157911
+ }
157861
157912
  };
157862
157913
  }
157863
157914
  });
@@ -157895,7 +157946,8 @@ var init_anthropicContentGenerator = __esm({
157895
157946
  });
157896
157947
  this.converter = new AnthropicContentConverter(
157897
157948
  contentGeneratorConfig.model,
157898
- contentGeneratorConfig.schemaCompliance
157949
+ contentGeneratorConfig.schemaCompliance,
157950
+ contentGeneratorConfig.disableCacheControl
157899
157951
  );
157900
157952
  }
157901
157953
  static {
@@ -158441,7 +158493,7 @@ __export(geminiContentGenerator_exports2, {
158441
158493
  createGeminiContentGenerator: () => createGeminiContentGenerator
158442
158494
  });
158443
158495
  function createGeminiContentGenerator(config2, gcConfig) {
158444
- const version2 = "0.2.3-alpha.5";
158496
+ const version2 = "0.2.3";
158445
158497
  const userAgent2 = config2.userAgent || `QwenCode/${version2} (${process.platform}; ${process.arch})`;
158446
158498
  const baseHeaders = {
158447
158499
  "User-Agent": userAgent2
@@ -174616,13 +174668,208 @@ function stripShellWrapper(command2) {
174616
174668
  return command2.trim();
174617
174669
  }
174618
174670
  function detectCommandSubstitution(command2) {
174671
+ const isCommentStart = /* @__PURE__ */ __name((index) => {
174672
+ if (command2[index] !== "#") return false;
174673
+ if (index === 0) return true;
174674
+ const prev = command2[index - 1];
174675
+ if (prev === " " || prev === " " || prev === "\n" || prev === "\r") {
174676
+ return true;
174677
+ }
174678
+ return [";", "&", "|", "(", ")", "<", ">"].includes(prev);
174679
+ }, "isCommentStart");
174680
+ const isWordBoundary = /* @__PURE__ */ __name((char) => {
174681
+ if (char === " " || char === " " || char === "\n" || char === "\r") {
174682
+ return true;
174683
+ }
174684
+ return [";", "&", "|", "<", ">", "(", ")"].includes(char);
174685
+ }, "isWordBoundary");
174686
+ const parseHeredocOperator = /* @__PURE__ */ __name((startIndex) => {
174687
+ if (command2[startIndex] !== "<" || command2[startIndex + 1] !== "<") {
174688
+ return null;
174689
+ }
174690
+ let i4 = startIndex + 2;
174691
+ const stripLeadingTabs = command2[i4] === "-";
174692
+ if (stripLeadingTabs) i4++;
174693
+ while (i4 < command2.length && (command2[i4] === " " || command2[i4] === " ")) {
174694
+ i4++;
174695
+ }
174696
+ let delimiter2 = "";
174697
+ let isQuotedDelimiter = false;
174698
+ let inSingleQuotes2 = false;
174699
+ let inDoubleQuotes2 = false;
174700
+ while (i4 < command2.length) {
174701
+ const char = command2[i4];
174702
+ if (!inSingleQuotes2 && !inDoubleQuotes2 && isWordBoundary(char)) {
174703
+ break;
174704
+ }
174705
+ if (!inSingleQuotes2 && !inDoubleQuotes2) {
174706
+ if (char === "'") {
174707
+ isQuotedDelimiter = true;
174708
+ inSingleQuotes2 = true;
174709
+ i4++;
174710
+ continue;
174711
+ }
174712
+ if (char === '"') {
174713
+ isQuotedDelimiter = true;
174714
+ inDoubleQuotes2 = true;
174715
+ i4++;
174716
+ continue;
174717
+ }
174718
+ if (char === "\\") {
174719
+ isQuotedDelimiter = true;
174720
+ i4++;
174721
+ if (i4 >= command2.length) break;
174722
+ delimiter2 += command2[i4];
174723
+ i4++;
174724
+ continue;
174725
+ }
174726
+ delimiter2 += char;
174727
+ i4++;
174728
+ continue;
174729
+ }
174730
+ if (inSingleQuotes2) {
174731
+ if (char === "'") {
174732
+ inSingleQuotes2 = false;
174733
+ i4++;
174734
+ continue;
174735
+ }
174736
+ delimiter2 += char;
174737
+ i4++;
174738
+ continue;
174739
+ }
174740
+ if (char === '"') {
174741
+ inDoubleQuotes2 = false;
174742
+ i4++;
174743
+ continue;
174744
+ }
174745
+ if (char === "\\") {
174746
+ isQuotedDelimiter = true;
174747
+ i4++;
174748
+ if (i4 >= command2.length) break;
174749
+ delimiter2 += command2[i4];
174750
+ i4++;
174751
+ continue;
174752
+ }
174753
+ delimiter2 += char;
174754
+ i4++;
174755
+ }
174756
+ if (delimiter2.length === 0) {
174757
+ return null;
174758
+ }
174759
+ return {
174760
+ nextIndex: i4,
174761
+ heredoc: {
174762
+ delimiter: delimiter2,
174763
+ isQuotedDelimiter,
174764
+ stripLeadingTabs
174765
+ }
174766
+ };
174767
+ }, "parseHeredocOperator");
174768
+ const lineHasCommandSubstitution = /* @__PURE__ */ __name((line) => {
174769
+ for (let i4 = 0; i4 < line.length; i4++) {
174770
+ const char = line[i4];
174771
+ const nextChar = line[i4 + 1];
174772
+ if (char === "\\") {
174773
+ i4++;
174774
+ continue;
174775
+ }
174776
+ if (char === "$" && nextChar === "(") {
174777
+ return true;
174778
+ }
174779
+ if (char === "`") {
174780
+ return true;
174781
+ }
174782
+ }
174783
+ return false;
174784
+ }, "lineHasCommandSubstitution");
174785
+ const consumeHeredocBodies = /* @__PURE__ */ __name((startIndex, pending) => {
174786
+ let i4 = startIndex;
174787
+ for (const heredoc of pending) {
174788
+ let pendingDollarLineContinuation = false;
174789
+ while (i4 <= command2.length) {
174790
+ const lineStart = i4;
174791
+ while (i4 < command2.length && command2[i4] !== "\n" && command2[i4] !== "\r") {
174792
+ i4++;
174793
+ }
174794
+ const lineEnd = i4;
174795
+ let newlineLength = 0;
174796
+ if (i4 < command2.length && command2[i4] === "\r" && command2[i4 + 1] === "\n") {
174797
+ newlineLength = 2;
174798
+ } else if (i4 < command2.length && (command2[i4] === "\n" || command2[i4] === "\r")) {
174799
+ newlineLength = 1;
174800
+ }
174801
+ const rawLine = command2.slice(lineStart, lineEnd);
174802
+ const effectiveLine = heredoc.stripLeadingTabs ? rawLine.replace(/^\t+/, "") : rawLine;
174803
+ if (effectiveLine === heredoc.delimiter) {
174804
+ i4 = lineEnd + newlineLength;
174805
+ break;
174806
+ }
174807
+ if (!heredoc.isQuotedDelimiter) {
174808
+ if (pendingDollarLineContinuation && effectiveLine.startsWith("(")) {
174809
+ return { nextIndex: i4, hasSubstitution: true };
174810
+ }
174811
+ if (lineHasCommandSubstitution(effectiveLine)) {
174812
+ return { nextIndex: i4, hasSubstitution: true };
174813
+ }
174814
+ pendingDollarLineContinuation = false;
174815
+ if (newlineLength > 0 && rawLine.length >= 2 && rawLine.endsWith("\\") && rawLine[rawLine.length - 2] === "$") {
174816
+ let backslashCount = 0;
174817
+ for (let j2 = rawLine.length - 3; j2 >= 0 && rawLine[j2] === "\\"; j2--) {
174818
+ backslashCount++;
174819
+ }
174820
+ const isEscapedDollar = backslashCount % 2 === 1;
174821
+ pendingDollarLineContinuation = !isEscapedDollar;
174822
+ }
174823
+ }
174824
+ i4 = lineEnd + newlineLength;
174825
+ if (newlineLength === 0) {
174826
+ break;
174827
+ }
174828
+ }
174829
+ }
174830
+ return { nextIndex: i4, hasSubstitution: false };
174831
+ }, "consumeHeredocBodies");
174619
174832
  let inSingleQuotes = false;
174620
174833
  let inDoubleQuotes = false;
174621
174834
  let inBackticks = false;
174835
+ let inComment = false;
174836
+ const pendingHeredocs = [];
174622
174837
  let i3 = 0;
174623
174838
  while (i3 < command2.length) {
174624
174839
  const char = command2[i3];
174625
174840
  const nextChar = command2[i3 + 1];
174841
+ if (!inSingleQuotes && !inDoubleQuotes && !inBackticks) {
174842
+ if (char === "\r" && nextChar === "\n") {
174843
+ inComment = false;
174844
+ if (pendingHeredocs.length > 0) {
174845
+ const result = consumeHeredocBodies(i3 + 2, pendingHeredocs);
174846
+ if (result.hasSubstitution) return true;
174847
+ pendingHeredocs.length = 0;
174848
+ i3 = result.nextIndex;
174849
+ continue;
174850
+ }
174851
+ } else if (char === "\n" || char === "\r") {
174852
+ inComment = false;
174853
+ if (pendingHeredocs.length > 0) {
174854
+ const result = consumeHeredocBodies(i3 + 1, pendingHeredocs);
174855
+ if (result.hasSubstitution) return true;
174856
+ pendingHeredocs.length = 0;
174857
+ i3 = result.nextIndex;
174858
+ continue;
174859
+ }
174860
+ }
174861
+ }
174862
+ if (!inSingleQuotes && !inDoubleQuotes && !inBackticks) {
174863
+ if (!inComment && isCommentStart(i3)) {
174864
+ inComment = true;
174865
+ i3++;
174866
+ continue;
174867
+ }
174868
+ if (inComment) {
174869
+ i3++;
174870
+ continue;
174871
+ }
174872
+ }
174626
174873
  if (char === "\\" && !inSingleQuotes) {
174627
174874
  i3 += 2;
174628
174875
  continue;
@@ -174634,6 +174881,14 @@ function detectCommandSubstitution(command2) {
174634
174881
  } else if (char === "`" && !inSingleQuotes) {
174635
174882
  inBackticks = !inBackticks;
174636
174883
  }
174884
+ if (!inSingleQuotes && !inDoubleQuotes && !inBackticks && char === "<" && nextChar === "<") {
174885
+ const parsed = parseHeredocOperator(i3);
174886
+ if (parsed) {
174887
+ pendingHeredocs.push(parsed.heredoc);
174888
+ i3 = parsed.nextIndex;
174889
+ continue;
174890
+ }
174891
+ }
174637
174892
  if (!inSingleQuotes) {
174638
174893
  if (char === "$" && nextChar === "(") {
174639
174894
  return true;
@@ -174644,7 +174899,7 @@ function detectCommandSubstitution(command2) {
174644
174899
  if (char === ">" && nextChar === "(" && !inDoubleQuotes && !inBackticks) {
174645
174900
  return true;
174646
174901
  }
174647
- if (char === "`" && !inBackticks) {
174902
+ if (char === "`") {
174648
174903
  return true;
174649
174904
  }
174650
174905
  }
@@ -176921,6 +177176,7 @@ var init_subagent = __esm({
176921
177176
  abortController,
176922
177177
  promptId,
176923
177178
  turnCounter,
177179
+ toolsList,
176924
177180
  currentResponseId
176925
177181
  );
176926
177182
  } else {
@@ -177006,8 +177262,49 @@ var init_subagent = __esm({
177006
177262
  * @returns {Promise<Content[]>} A promise that resolves to an array of `Content` parts representing the tool responses,
177007
177263
  * which are then used to update the chat history.
177008
177264
  */
177009
- async processFunctionCalls(functionCalls, abortController, promptId, currentRound, responseId) {
177265
+ async processFunctionCalls(functionCalls, abortController, promptId, currentRound, toolsList, responseId) {
177010
177266
  const toolResponseParts = [];
177267
+ const allowedToolNames = new Set(toolsList.map((t5) => t5.name));
177268
+ const authorizedCalls = [];
177269
+ for (const fc of functionCalls) {
177270
+ const callId = fc.id ?? `${fc.name}-${Date.now()}`;
177271
+ if (!allowedToolNames.has(fc.name)) {
177272
+ const toolName = String(fc.name);
177273
+ const errorMessage = `Tool "${toolName}" not found. Tools must use the exact names provided.`;
177274
+ this.eventEmitter?.emit("tool_call" /* TOOL_CALL */, {
177275
+ subagentId: this.subagentId,
177276
+ round: currentRound,
177277
+ callId,
177278
+ name: toolName,
177279
+ args: fc.args ?? {},
177280
+ description: `Tool "${toolName}" not found`,
177281
+ timestamp: Date.now()
177282
+ });
177283
+ const functionResponsePart = {
177284
+ functionResponse: {
177285
+ id: callId,
177286
+ name: toolName,
177287
+ response: { error: errorMessage }
177288
+ }
177289
+ };
177290
+ this.eventEmitter?.emit("tool_result" /* TOOL_RESULT */, {
177291
+ subagentId: this.subagentId,
177292
+ round: currentRound,
177293
+ callId,
177294
+ name: toolName,
177295
+ success: false,
177296
+ error: errorMessage,
177297
+ responseParts: [functionResponsePart],
177298
+ resultDisplay: errorMessage,
177299
+ durationMs: 0,
177300
+ timestamp: Date.now()
177301
+ });
177302
+ this.recordToolCallStats(toolName, false, 0, errorMessage);
177303
+ toolResponseParts.push(functionResponsePart);
177304
+ continue;
177305
+ }
177306
+ authorizedCalls.push(fc);
177307
+ }
177011
177308
  const responded = /* @__PURE__ */ new Set();
177012
177309
  let resolveBatch = null;
177013
177310
  const scheduler = new CoreToolScheduler({
@@ -177019,29 +177316,7 @@ var init_subagent = __esm({
177019
177316
  const duration3 = call.durationMs ?? 0;
177020
177317
  const success = call.status === "success";
177021
177318
  const errorMessage = call.status === "error" || call.status === "cancelled" ? call.response.error?.message : void 0;
177022
- this.executionStats.totalToolCalls += 1;
177023
- if (success) {
177024
- this.executionStats.successfulToolCalls += 1;
177025
- } else {
177026
- this.executionStats.failedToolCalls += 1;
177027
- }
177028
- const tu = this.toolUsage.get(toolName) || {
177029
- count: 0,
177030
- success: 0,
177031
- failure: 0,
177032
- totalDurationMs: 0,
177033
- averageDurationMs: 0
177034
- };
177035
- tu.count += 1;
177036
- if (success) {
177037
- tu.success += 1;
177038
- } else {
177039
- tu.failure += 1;
177040
- tu.lastError = errorMessage || "Unknown error";
177041
- }
177042
- tu.totalDurationMs = (tu.totalDurationMs || 0) + duration3;
177043
- tu.averageDurationMs = tu.count > 0 ? tu.totalDurationMs / tu.count : 0;
177044
- this.toolUsage.set(toolName, tu);
177319
+ this.recordToolCallStats(toolName, success, duration3, errorMessage);
177045
177320
  this.eventEmitter?.emit("tool_result" /* TOOL_RESULT */, {
177046
177321
  subagentId: this.subagentId,
177047
177322
  round: currentRound,
@@ -177050,22 +177325,10 @@ var init_subagent = __esm({
177050
177325
  success,
177051
177326
  error: errorMessage,
177052
177327
  responseParts: call.response.responseParts,
177053
- /**
177054
- * Tools like todoWrite will add some extra contents to the result,
177055
- * making it unable to deserialize the `responseParts` to a JSON object.
177056
- * While `resultDisplay` is normally a string, if not we stringify it,
177057
- * so that we can deserialize it to a JSON object when needed.
177058
- */
177059
177328
  resultDisplay: call.response.resultDisplay ? typeof call.response.resultDisplay === "string" ? call.response.resultDisplay : JSON.stringify(call.response.resultDisplay) : void 0,
177060
177329
  durationMs: duration3,
177061
177330
  timestamp: Date.now()
177062
177331
  });
177063
- this.stats.recordToolCall(
177064
- toolName,
177065
- success,
177066
- duration3,
177067
- this.toolUsage.get(toolName)?.lastError
177068
- );
177069
177332
  await this.hooks?.postToolUse?.({
177070
177333
  subagentId: this.subagentId,
177071
177334
  name: this.name,
@@ -177122,7 +177385,7 @@ var init_subagent = __esm({
177122
177385
  onEditorClose: /* @__PURE__ */ __name(() => {
177123
177386
  }, "onEditorClose")
177124
177387
  });
177125
- const requests = functionCalls.map((fc) => {
177388
+ const requests = authorizedCalls.map((fc) => {
177126
177389
  const toolName = String(fc.name || "unknown");
177127
177390
  const callId = fc.id ?? `${fc.name}-${Date.now()}`;
177128
177391
  const args = fc.args ?? {};
@@ -177255,6 +177518,41 @@ var init_subagent = __esm({
177255
177518
  return "";
177256
177519
  }
177257
177520
  }
177521
+ /**
177522
+ * Records tool call statistics for both successful and failed tool calls.
177523
+ * This includes updating aggregate stats, per-tool usage, and the statistics service.
177524
+ */
177525
+ recordToolCallStats(toolName, success, durationMs, errorMessage) {
177526
+ this.executionStats.totalToolCalls += 1;
177527
+ if (success) {
177528
+ this.executionStats.successfulToolCalls += 1;
177529
+ } else {
177530
+ this.executionStats.failedToolCalls += 1;
177531
+ }
177532
+ const tu = this.toolUsage.get(toolName) || {
177533
+ count: 0,
177534
+ success: 0,
177535
+ failure: 0,
177536
+ totalDurationMs: 0,
177537
+ averageDurationMs: 0
177538
+ };
177539
+ tu.count += 1;
177540
+ if (success) {
177541
+ tu.success += 1;
177542
+ } else {
177543
+ tu.failure += 1;
177544
+ tu.lastError = errorMessage || "Unknown error";
177545
+ }
177546
+ tu.totalDurationMs = (tu.totalDurationMs || 0) + durationMs;
177547
+ tu.averageDurationMs = tu.count > 0 ? tu.totalDurationMs / tu.count : 0;
177548
+ this.toolUsage.set(toolName, tu);
177549
+ this.stats.recordToolCall(
177550
+ toolName,
177551
+ success,
177552
+ durationMs,
177553
+ this.toolUsage.get(toolName)?.lastError
177554
+ );
177555
+ }
177258
177556
  buildChatSystemPrompt(context2) {
177259
177557
  if (!this.promptConfig.systemPrompt) {
177260
177558
  return "";
@@ -191309,21 +191607,53 @@ var init_esm11 = __esm({
191309
191607
  // packages/core/src/services/fileSystemService.ts
191310
191608
  import fs31 from "node:fs/promises";
191311
191609
  import * as path27 from "node:path";
191312
- var StandardFileSystemService;
191610
+ function hasUTF8BOM(buffer) {
191611
+ return buffer.length >= 3 && buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191;
191612
+ }
191613
+ var FileEncoding, StandardFileSystemService;
191313
191614
  var init_fileSystemService = __esm({
191314
191615
  "packages/core/src/services/fileSystemService.ts"() {
191315
191616
  "use strict";
191316
191617
  init_esbuild_shims();
191317
191618
  init_esm11();
191619
+ FileEncoding = {
191620
+ UTF8: "utf-8",
191621
+ UTF8_BOM: "utf-8-bom"
191622
+ };
191623
+ __name(hasUTF8BOM, "hasUTF8BOM");
191318
191624
  StandardFileSystemService = class {
191319
191625
  static {
191320
191626
  __name(this, "StandardFileSystemService");
191321
191627
  }
191322
191628
  async readTextFile(filePath) {
191323
- return fs31.readFile(filePath, "utf-8");
191629
+ return fs31.readFile(filePath, FileEncoding.UTF8);
191630
+ }
191631
+ async writeTextFile(filePath, content, options2) {
191632
+ const bom = options2?.bom ?? false;
191633
+ if (bom) {
191634
+ const normalizedContent = content.charCodeAt(0) === 65279 ? content.slice(1) : content;
191635
+ const bomBuffer = Buffer.from([239, 187, 191]);
191636
+ const contentBuffer = Buffer.from(normalizedContent, "utf-8");
191637
+ await fs31.writeFile(filePath, Buffer.concat([bomBuffer, contentBuffer]));
191638
+ } else {
191639
+ await fs31.writeFile(filePath, content, "utf-8");
191640
+ }
191324
191641
  }
191325
- async writeTextFile(filePath, content) {
191326
- await fs31.writeFile(filePath, content, "utf-8");
191642
+ async detectFileBOM(filePath) {
191643
+ let fd;
191644
+ try {
191645
+ fd = await fs31.open(filePath, "r");
191646
+ const buffer = Buffer.alloc(3);
191647
+ const { bytesRead } = await fd.read(buffer, 0, 3, 0);
191648
+ if (bytesRead < 3) {
191649
+ return false;
191650
+ }
191651
+ return hasUTF8BOM(buffer);
191652
+ } catch {
191653
+ return false;
191654
+ } finally {
191655
+ await fd?.close();
191656
+ }
191327
191657
  }
191328
191658
  findFiles(fileName, searchPaths) {
191329
191659
  return searchPaths.flatMap((searchPath) => {
@@ -208889,22 +209219,6 @@ function normalizeBasicCharacters(text) {
208889
209219
  }
208890
209220
  return normalized2;
208891
209221
  }
208892
- function stripTrailingWhitespacePreserveNewlines(text) {
208893
- const pieces = text.split(/(\r\n|\n|\r)/);
208894
- let result = "";
208895
- for (let i3 = 0; i3 < pieces.length; i3++) {
208896
- const segment = pieces[i3];
208897
- if (segment === void 0) {
208898
- continue;
208899
- }
208900
- if (i3 % 2 === 0) {
208901
- result += segment.trimEnd();
208902
- } else {
208903
- result += segment;
208904
- }
208905
- }
208906
- return result;
208907
- }
208908
209222
  function normalizeLineForComparison(value) {
208909
209223
  return normalizeBasicCharacters(value).trimEnd();
208910
209224
  }
@@ -209048,11 +209362,10 @@ function adjustNewStringForTrailingLine(newString, removedTrailingLine) {
209048
209362
  return removedTrailingLine ? removeTrailingNewline(newString) : newString;
209049
209363
  }
209050
209364
  function normalizeEditStrings(fileContent, oldString, newString) {
209051
- const trimmedNewString = stripTrailingWhitespacePreserveNewlines(newString);
209052
209365
  if (fileContent === null || oldString === "") {
209053
209366
  return {
209054
209367
  oldString,
209055
- newString: trimmedNewString
209368
+ newString
209056
209369
  };
209057
209370
  }
209058
209371
  const canonicalOriginal = findMatchedSlice(fileContent, oldString);
@@ -209060,14 +209373,14 @@ function normalizeEditStrings(fileContent, oldString, newString) {
209060
209373
  return {
209061
209374
  oldString: canonicalOriginal.slice,
209062
209375
  newString: adjustNewStringForTrailingLine(
209063
- trimmedNewString,
209376
+ newString,
209064
209377
  canonicalOriginal.removedTrailingFinalEmptyLine
209065
209378
  )
209066
209379
  };
209067
209380
  }
209068
209381
  return {
209069
209382
  oldString,
209070
- newString: trimmedNewString
209383
+ newString
209071
209384
  };
209072
209385
  }
209073
209386
  function maybeAugmentOldStringForDeletion(fileContent, oldString, newString) {
@@ -209177,7 +209490,6 @@ var init_editHelper = __esm({
209177
209490
  "\u3000": " "
209178
209491
  };
209179
209492
  __name(normalizeBasicCharacters, "normalizeBasicCharacters");
209180
- __name(stripTrailingWhitespacePreserveNewlines, "stripTrailingWhitespacePreserveNewlines");
209181
209493
  LINE_COMPARISON_PASSES = [
209182
209494
  (value) => value,
209183
209495
  (value) => value.trimEnd()
@@ -209225,6 +209537,7 @@ var init_edit = __esm({
209225
209537
  init_paths();
209226
209538
  init_errors();
209227
209539
  init_config3();
209540
+ init_fileSystemService();
209228
209541
  init_diffOptions();
209229
209542
  init_read_file();
209230
209543
  init_tool_names();
@@ -209456,7 +209769,14 @@ var init_edit = __esm({
209456
209769
  }
209457
209770
  try {
209458
209771
  this.ensureParentDirectoriesExist(this.params.file_path);
209459
- await this.config.getFileSystemService().writeTextFile(this.params.file_path, editData.newContent);
209772
+ if (editData.isNewFile) {
209773
+ const useBOM = this.config.getDefaultFileEncoding() === FileEncoding.UTF8_BOM;
209774
+ await this.config.getFileSystemService().writeTextFile(this.params.file_path, editData.newContent, {
209775
+ bom: useBOM
209776
+ });
209777
+ } else {
209778
+ await this.config.getFileSystemService().writeTextFile(this.params.file_path, editData.newContent);
209779
+ }
209460
209780
  const fileName = path35.basename(this.params.file_path);
209461
209781
  const originallyProposedContent = this.params.ai_proposed_content || editData.newContent;
209462
209782
  const diffStat = getDiffStat(
@@ -224253,6 +224573,7 @@ var init_write_file = __esm({
224253
224573
  init_config3();
224254
224574
  init_tools();
224255
224575
  init_tool_error();
224576
+ init_fileSystemService();
224256
224577
  init_paths();
224257
224578
  init_errors();
224258
224579
  init_diffOptions();
@@ -224365,7 +224686,13 @@ var init_write_file = __esm({
224365
224686
  if (!fs46.existsSync(dirName)) {
224366
224687
  fs46.mkdirSync(dirName, { recursive: true });
224367
224688
  }
224368
- await this.config.getFileSystemService().writeTextFile(file_path, fileContent);
224689
+ let useBOM = false;
224690
+ if (!isNewFile) {
224691
+ useBOM = await this.config.getFileSystemService().detectFileBOM(file_path);
224692
+ } else {
224693
+ useBOM = this.config.getDefaultFileEncoding() === FileEncoding.UTF8_BOM;
224694
+ }
224695
+ await this.config.getFileSystemService().writeTextFile(file_path, fileContent, { bom: useBOM });
224369
224696
  const fileName = path49.basename(file_path);
224370
224697
  const currentContentForDiff = correctedContentResult.error ? "" : originalContent;
224371
224698
  const fileDiff = createPatch(
@@ -249910,6 +250237,7 @@ var init_config3 = __esm({
249910
250237
  eventEmitter;
249911
250238
  useSmartEdit;
249912
250239
  channel;
250240
+ defaultFileEncoding;
249913
250241
  constructor(params) {
249914
250242
  this.sessionId = params.sessionId ?? randomUUID6();
249915
250243
  this.sessionData = params.sessionData;
@@ -250011,6 +250339,7 @@ var init_config3 = __esm({
250011
250339
  this.enableToolOutputTruncation = params.enableToolOutputTruncation ?? true;
250012
250340
  this.useSmartEdit = params.useSmartEdit ?? false;
250013
250341
  this.channel = params.channel;
250342
+ this.defaultFileEncoding = params.defaultFileEncoding ?? FileEncoding.UTF8;
250014
250343
  this.storage = new Storage(this.targetDir);
250015
250344
  this.vlmSwitchMode = params.vlmSwitchMode;
250016
250345
  this.inputFormat = params.inputFormat ?? "text" /* TEXT */;
@@ -250621,6 +250950,13 @@ var init_config3 = __esm({
250621
250950
  getChannel() {
250622
250951
  return this.channel;
250623
250952
  }
250953
+ /**
250954
+ * Get the default file encoding for new files.
250955
+ * @returns FileEncodingType
250956
+ */
250957
+ getDefaultFileEncoding() {
250958
+ return this.defaultFileEncoding;
250959
+ }
250624
250960
  /**
250625
250961
  * Get the current FileSystemService
250626
250962
  */
@@ -254958,8 +255294,8 @@ var init_git_commit = __esm({
254958
255294
  "packages/core/src/generated/git-commit.ts"() {
254959
255295
  "use strict";
254960
255296
  init_esbuild_shims();
254961
- GIT_COMMIT_INFO = "3234c50a0";
254962
- CLI_VERSION = "0.2.3-alpha.5";
255297
+ GIT_COMMIT_INFO = "1d2d79a6c";
255298
+ CLI_VERSION = "0.2.3";
254963
255299
  }
254964
255300
  });
254965
255301
 
@@ -261029,6 +261365,7 @@ __export(core_exports5, {
261029
261365
  FatalTurnLimitedError: () => FatalTurnLimitedError,
261030
261366
  FetchError: () => FetchError,
261031
261367
  FileDiscoveryService: () => FileDiscoveryService,
261368
+ FileEncoding: () => FileEncoding,
261032
261369
  FileExclusions: () => FileExclusions,
261033
261370
  FileOperation: () => FileOperation,
261034
261371
  FileSchema: () => FileSchema,
@@ -299797,6 +300134,19 @@ var init_settingsSchema = __esm({
299797
300134
  default: true,
299798
300135
  description: "Enable saving chat history to disk. Disabling this will also prevent --continue and --resume from working.",
299799
300136
  showInDialog: false
300137
+ },
300138
+ defaultFileEncoding: {
300139
+ type: "enum",
300140
+ label: "Default File Encoding",
300141
+ category: "General",
300142
+ requiresRestart: false,
300143
+ default: "utf-8",
300144
+ description: 'Default encoding for new files. Use "utf-8" (default) for UTF-8 without BOM, or "utf-8-bom" for UTF-8 with BOM. Only change this if your project specifically requires BOM.',
300145
+ showInDialog: false,
300146
+ options: [
300147
+ { value: "utf-8", label: "UTF-8 (without BOM)" },
300148
+ { value: "utf-8-bom", label: "UTF-8 with BOM" }
300149
+ ]
299800
300150
  }
299801
300151
  }
299802
300152
  },
@@ -300155,7 +300505,7 @@ var init_settingsSchema = __esm({
300155
300505
  category: "Generation Configuration",
300156
300506
  requiresRestart: false,
300157
300507
  default: false,
300158
- description: "Disable cache control for DashScope providers.",
300508
+ description: "Disable cache control for Anthropic and DashScope providers.",
300159
300509
  parentKey: "generationConfig",
300160
300510
  showInDialog: false
300161
300511
  },
@@ -309614,6 +309964,7 @@ var init_en3 = __esm({
309614
309964
  "auto-accept edits": "auto-accept edits",
309615
309965
  "Accepting edits": "Accepting edits",
309616
309966
  "(shift + tab to cycle)": "(shift + tab to cycle)",
309967
+ "(tab to cycle)": "(tab to cycle)",
309617
309968
  "Execute shell commands via {{symbol}} (e.g., {{example1}}) or use natural language (e.g., {{example2}}).": "Execute shell commands via {{symbol}} (e.g., {{example1}}) or use natural language (e.g., {{example2}}).",
309618
309969
  "!": "!",
309619
309970
  "!npm run start": "!npm run start",
@@ -310423,6 +310774,7 @@ var init_en3 = __esm({
310423
310774
  "Type / to open the command popup; Tab autocompletes slash commands and saved prompts.": "Type / to open the command popup; Tab autocompletes slash commands and saved prompts.",
310424
310775
  "You can resume a previous conversation by running rdmind --continue or rdmind --resume.": "You can resume a previous conversation by running rdmind --continue or rdmind --resume.",
310425
310776
  "You can switch permission mode quickly with Shift+Tab or /approval-mode.": "You can switch permission mode quickly with Shift+Tab or /approval-mode.",
310777
+ "You can switch permission mode quickly with Tab or /approval-mode.": "You can switch permission mode quickly with Tab or /approval-mode.",
310426
310778
  "RDMind now supports custom commands, sub-agents, skills and other features. Check the documentation for usage help.": "RDMind now supports custom commands, sub-agents, skills and other features. Check the documentation for usage help.",
310427
310779
  "Try asking RDMind to help you commit code.": "Try asking RDMind to help you commit code.",
310428
310780
  "RDMind can read REDoc. Please do not upload documents involving user privacy and core algorithms.": "RDMind can read REDoc. Please do not upload documents involving user privacy and core algorithms.",
@@ -310697,6 +311049,7 @@ var init_zh = __esm({
310697
311049
  "auto-accept edits": "\u81EA\u52A8\u63A5\u53D7\u7F16\u8F91",
310698
311050
  "Accepting edits": "\u63A5\u53D7\u7F16\u8F91",
310699
311051
  "(shift + tab to cycle)": "(shift + tab \u5207\u6362)",
311052
+ "(tab to cycle)": "(\u6309 tab \u5207\u6362)",
310700
311053
  "Execute shell commands via {{symbol}} (e.g., {{example1}}) or use natural language (e.g., {{example2}}).": "\u901A\u8FC7 {{symbol}} \u6267\u884C shell \u547D\u4EE4\uFF08\u4F8B\u5982\uFF0C{{example1}}\uFF09\u6216\u4F7F\u7528\u81EA\u7136\u8BED\u8A00\uFF08\u4F8B\u5982\uFF0C{{example2}}\uFF09",
310701
311054
  "!": "!",
310702
311055
  "!npm run start": "!npm run start",
@@ -311506,6 +311859,7 @@ var init_zh = __esm({
311506
311859
  "Type / to open the command popup; Tab autocompletes slash commands and saved prompts.": "\u8F93\u5165 / \u6253\u5F00\u547D\u4EE4\u5F39\u7A97\uFF1B\u6309 Tab \u81EA\u52A8\u8865\u5168\u659C\u6760\u547D\u4EE4\u548C\u4FDD\u5B58\u7684\u63D0\u793A\u8BCD\u3002",
311507
311860
  "You can resume a previous conversation by running rdmind --continue or rdmind --resume.": "\u8FD0\u884C rdmind --continue \u6216 rdmind --resume \u53EF\u7EE7\u7EED\u4E4B\u524D\u7684\u4F1A\u8BDD\u3002",
311508
311861
  "You can switch permission mode quickly with Shift+Tab or /approval-mode.": "\u6309 Shift+Tab \u6216\u8F93\u5165 /approval-mode \u53EF\u5FEB\u901F\u5207\u6362\u6743\u9650\u6A21\u5F0F\u3002",
311862
+ "You can switch permission mode quickly with Tab or /approval-mode.": "\u6309 Tab \u6216\u8F93\u5165 /approval-mode \u53EF\u5FEB\u901F\u5207\u6362\u6743\u9650\u6A21\u5F0F\u3002",
311509
311863
  "RDMind now supports custom commands, sub-agents, skills and other features. Check the documentation for usage help.": "RDMind \u73B0\u5DF2\u652F\u6301\u81EA\u5B9A\u4E49\u547D\u4EE4\u3001\u5B50\u4EE3\u7406\u3001\u6280\u80FD\u7B49\u7279\u6027\uFF0C\u67E5\u9605\u6587\u6863\u83B7\u5F97\u4F7F\u7528\u5E2E\u52A9\u3002",
311510
311864
  "Try asking RDMind to help you commit code.": "\u8BD5\u8BD5\u8BA9 RDMind \u5E2E\u4F60\u63D0\u4EA4\u4EE3\u7801\u3002",
311511
311865
  "RDMind can read REDoc. Please do not upload documents involving user privacy and core algorithms.": "RDMind \u53EF\u4EE5\u8BFB\u61C2 REDoc\uFF0C\u6CE8\u610F\u4E0D\u8981\u4E0A\u4F20\u6D89\u53CA\u7528\u6237\u9690\u79C1\u548C\u6838\u5FC3\u7B97\u6CD5\u7684\u6587\u6863\u3002",
@@ -360858,7 +361212,7 @@ __name(getPackageJson, "getPackageJson");
360858
361212
  // packages/cli/src/utils/version.ts
360859
361213
  async function getCliVersion() {
360860
361214
  const pkgJson = await getPackageJson();
360861
- return "0.2.3-alpha.5";
361215
+ return "0.2.3";
360862
361216
  }
360863
361217
  __name(getCliVersion, "getCliVersion");
360864
361218
 
@@ -365468,6 +365822,7 @@ async function loadCliConfig(settings, argv, cwd7 = process.cwd(), overrideExten
365468
365822
  // NOTE: do NOT set a yargs default for `chat-recording`, otherwise argv will
365469
365823
  // always be true and the settings file can never disable recording.
365470
365824
  chatRecording: argv.chatRecording ?? settings.general?.chatRecording ?? true,
365825
+ defaultFileEncoding: settings.general?.defaultFileEncoding ?? FileEncoding.UTF8,
365471
365826
  lsp: {
365472
365827
  enabled: lspEnabled
365473
365828
  }
@@ -368588,7 +368943,7 @@ var formatDuration = /* @__PURE__ */ __name((milliseconds) => {
368588
368943
 
368589
368944
  // packages/cli/src/generated/git-commit.ts
368590
368945
  init_esbuild_shims();
368591
- var GIT_COMMIT_INFO2 = "3234c50a0";
368946
+ var GIT_COMMIT_INFO2 = "1d2d79a6c";
368592
368947
 
368593
368948
  // packages/cli/src/utils/systemInfo.ts
368594
368949
  async function getNpmVersion() {
@@ -404549,7 +404904,7 @@ var Help = /* @__PURE__ */ __name(({ commands, width }) => /* @__PURE__ */ (0, i
404549
404904
  t4("Cancel operation / Clear input (double press)")
404550
404905
  ] }),
404551
404906
  /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(Text3, { color: theme.text.primary, children: [
404552
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Text3, { bold: true, color: theme.text.accent, children: "Shift+Tab" }),
404907
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(Text3, { bold: true, color: theme.text.accent, children: process.platform === "win32" ? "Tab" : "Shift+Tab" }),
404553
404908
  " ",
404554
404909
  "- ",
404555
404910
  t4("Cycle approval modes")
@@ -405324,6 +405679,8 @@ var startupTips = [
405324
405679
  "You can run any shell commands from RDMind using ! (e.g. !ls).",
405325
405680
  "Type / to open the command popup; Tab autocompletes slash commands and saved prompts.",
405326
405681
  "You can resume a previous conversation by running rdmind --continue or rdmind --resume.",
405682
+ process.platform === "win32" ? "You can switch permission mode quickly with Tab or /approval-mode." : "You can switch permission mode quickly with Shift+Tab or /approval-mode.",
405683
+ "You can resume a previous conversation by running rdmind --continue or rdmind --resume.",
405327
405684
  "You can switch permission mode quickly with Shift+Tab or /approval-mode.",
405328
405685
  "RDMind now supports custom commands, sub-agents, skills and other features. Check the documentation for usage help.",
405329
405686
  "Try asking RDMind to help you commit code.",
@@ -408613,14 +408970,15 @@ var XHS_SSO_MODELS = [
408613
408970
  baseUrl: "https://runway.devops.xiaohongshu.com/openai/moonshot/v1",
408614
408971
  contextWindow: "256K",
408615
408972
  description: "\u5728 Agent\u3001\u4EE3\u7801\u3001\u89C6\u89C9\u7406\u89E3\u53CA\u4E00\u7CFB\u5217\u901A\u7528\u667A\u80FD\u4EFB\u52A1\u4E0A\u53D6\u5F97\u5F00\u6E90 SoTA \u8868\u73B0"
408616
- },
408617
- {
408618
- id: "claude-opus-4-5@20251101",
408619
- displayName: "Claude Opus 4.5",
408620
- baseUrl: "https://runway.devops.rednote.life/openai/google/anthropic/v1",
408621
- contextWindow: "200K",
408622
- description: "Anthropic \u6700\u5F3A\u5927\u7684\u6A21\u578B\uFF0C\u64C5\u957F\u590D\u6742\u63A8\u7406\u548C\u4EE3\u7801\u751F\u6210"
408623
408973
  }
408974
+ // 暂时注释,待稳定后发布
408975
+ // {
408976
+ // id: 'claude-opus-4-5@20251101',
408977
+ // displayName: 'Claude Opus 4.5',
408978
+ // baseUrl: 'https://runway.devops.rednote.life/openai/google/anthropic/v1',
408979
+ // contextWindow: '200K',
408980
+ // description: 'Anthropic 最强大的模型,擅长复杂推理和代码生成',
408981
+ // },
408624
408982
  ];
408625
408983
 
408626
408984
  // packages/cli/src/ui/components/XhsSsoModelConfigFlow.tsx
@@ -412343,21 +412701,22 @@ var AutoAcceptIndicator = /* @__PURE__ */ __name(({
412343
412701
  let textColor = "";
412344
412702
  let textContent2 = "";
412345
412703
  let subText = "";
412704
+ const cycleText = process.platform === "win32" ? ` ${t4("(tab to cycle)")}` : ` ${t4("(shift + tab to cycle)")}`;
412346
412705
  switch (approvalMode) {
412347
412706
  case "plan" /* PLAN */:
412348
412707
  textColor = theme.status.success;
412349
412708
  textContent2 = t4("plan mode");
412350
- subText = ` ${t4("(shift + tab to cycle)")}`;
412709
+ subText = cycleText;
412351
412710
  break;
412352
412711
  case "auto-edit" /* AUTO_EDIT */:
412353
412712
  textColor = theme.status.warning;
412354
412713
  textContent2 = t4("auto-accept edits");
412355
- subText = ` ${t4("(shift + tab to cycle)")}`;
412714
+ subText = cycleText;
412356
412715
  break;
412357
412716
  case "yolo" /* YOLO */:
412358
412717
  textColor = theme.status.error;
412359
412718
  textContent2 = t4("YOLO mode");
412360
- subText = ` ${t4("(shift + tab to cycle)")}`;
412719
+ subText = cycleText;
412361
412720
  break;
412362
412721
  case "default" /* DEFAULT */:
412363
412722
  default:
@@ -412499,7 +412858,10 @@ var getShortcuts = /* @__PURE__ */ __name(() => [
412499
412858
  { key: "/", description: t4("for commands") },
412500
412859
  { key: "@", description: t4("for file paths") },
412501
412860
  { key: "esc esc", description: t4("to clear input") },
412502
- { key: "shift+tab", description: t4("to cycle approvals") },
412861
+ {
412862
+ key: process.platform === "win32" ? "tab" : "shift+tab",
412863
+ description: t4("to cycle approvals")
412864
+ },
412503
412865
  { key: "ctrl+c", description: t4("to quit") },
412504
412866
  { key: getNewlineKey(), description: t4("for newline") + " \u23CE" },
412505
412867
  { key: "ctrl+l", description: t4("to clear screen") },
@@ -421034,7 +421396,9 @@ function useAutoAcceptIndicator({
421034
421396
  }, [currentConfigValue]);
421035
421397
  useKeypress(
421036
421398
  (key) => {
421037
- if (key.shift && key.name === "tab") {
421399
+ const isShiftTab = key.shift && key.name === "tab";
421400
+ const isWindowsTab = process.platform === "win32" && key.name === "tab" && !key.ctrl && !key.meta;
421401
+ if (isShiftTab || isWindowsTab) {
421038
421402
  const currentMode = config2.getApprovalMode();
421039
421403
  const currentIndex = APPROVAL_MODES.indexOf(currentMode);
421040
421404
  const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % APPROVAL_MODES.length;
@@ -425567,16 +425931,32 @@ var AcpFileSystemService = class {
425567
425931
  }
425568
425932
  return response.content;
425569
425933
  }
425570
- async writeTextFile(filePath, content) {
425934
+ async writeTextFile(filePath, content, options2) {
425571
425935
  if (!this.capabilities.writeTextFile) {
425572
- return this.fallback.writeTextFile(filePath, content);
425936
+ return this.fallback.writeTextFile(filePath, content, options2);
425573
425937
  }
425938
+ const finalContent = options2?.bom ? "\uFEFF" + content : content;
425574
425939
  await this.client.writeTextFile({
425575
425940
  path: filePath,
425576
- content,
425941
+ content: finalContent,
425577
425942
  sessionId: this.sessionId
425578
425943
  });
425579
425944
  }
425945
+ async detectFileBOM(filePath) {
425946
+ if (this.capabilities.readTextFile) {
425947
+ try {
425948
+ const response = await this.client.readTextFile({
425949
+ path: filePath,
425950
+ sessionId: this.sessionId,
425951
+ line: null,
425952
+ limit: 1
425953
+ });
425954
+ return response.content.charCodeAt(0) === 65279;
425955
+ } catch {
425956
+ }
425957
+ }
425958
+ return this.fallback.detectFileBOM(filePath);
425959
+ }
425580
425960
  findFiles(fileName, searchPaths) {
425581
425961
  return this.fallback.findFiles(fileName, searchPaths);
425582
425962
  }
@@ -427248,7 +427628,7 @@ var GeminiAgent = class {
427248
427628
  name: APPROVAL_MODE_INFO[mode].name,
427249
427629
  description: APPROVAL_MODE_INFO[mode].description
427250
427630
  }));
427251
- const version2 = "0.2.3-alpha.5";
427631
+ const version2 = "0.2.3";
427252
427632
  return {
427253
427633
  protocolVersion: PROTOCOL_VERSION,
427254
427634
  agentInfo: {
package/locales/en.js CHANGED
@@ -23,6 +23,7 @@ export default {
23
23
  'auto-accept edits': 'auto-accept edits',
24
24
  'Accepting edits': 'Accepting edits',
25
25
  '(shift + tab to cycle)': '(shift + tab to cycle)',
26
+ '(tab to cycle)': '(tab to cycle)',
26
27
  'Execute shell commands via {{symbol}} (e.g., {{example1}}) or use natural language (e.g., {{example2}}).':
27
28
  'Execute shell commands via {{symbol}} (e.g., {{example1}}) or use natural language (e.g., {{example2}}).',
28
29
  '!': '!',
@@ -1142,6 +1143,8 @@ export default {
1142
1143
  'You can resume a previous conversation by running rdmind --continue or rdmind --resume.',
1143
1144
  'You can switch permission mode quickly with Shift+Tab or /approval-mode.':
1144
1145
  'You can switch permission mode quickly with Shift+Tab or /approval-mode.',
1146
+ 'You can switch permission mode quickly with Tab or /approval-mode.':
1147
+ 'You can switch permission mode quickly with Tab or /approval-mode.',
1145
1148
  'RDMind now supports custom commands, sub-agents, skills and other features. Check the documentation for usage help.':
1146
1149
  'RDMind now supports custom commands, sub-agents, skills and other features. Check the documentation for usage help.',
1147
1150
  'Try asking RDMind to help you commit code.':
package/locales/zh.js CHANGED
@@ -22,6 +22,7 @@ export default {
22
22
  'auto-accept edits': '自动接受编辑',
23
23
  'Accepting edits': '接受编辑',
24
24
  '(shift + tab to cycle)': '(shift + tab 切换)',
25
+ '(tab to cycle)': '(按 tab 切换)',
25
26
  'Execute shell commands via {{symbol}} (e.g., {{example1}}) or use natural language (e.g., {{example2}}).':
26
27
  '通过 {{symbol}} 执行 shell 命令(例如,{{example1}})或使用自然语言(例如,{{example2}})',
27
28
  '!': '!',
@@ -1078,6 +1079,8 @@ export default {
1078
1079
  '运行 rdmind --continue 或 rdmind --resume 可继续之前的会话。',
1079
1080
  'You can switch permission mode quickly with Shift+Tab or /approval-mode.':
1080
1081
  '按 Shift+Tab 或输入 /approval-mode 可快速切换权限模式。',
1082
+ 'You can switch permission mode quickly with Tab or /approval-mode.':
1083
+ '按 Tab 或输入 /approval-mode 可快速切换权限模式。',
1081
1084
  'RDMind now supports custom commands, sub-agents, skills and other features. Check the documentation for usage help.':
1082
1085
  'RDMind 现已支持自定义命令、子代理、技能等特性,查阅文档获得使用帮助。',
1083
1086
  'Try asking RDMind to help you commit code.': '试试让 RDMind 帮你提交代码。',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rdmind/rdmind",
3
- "version": "0.2.3-alpha.5",
3
+ "version": "0.2.3",
4
4
  "description": "RDMind - AI-powered coding assistant",
5
5
  "type": "module",
6
6
  "main": "cli.js",
@@ -20,7 +20,7 @@
20
20
  "locales"
21
21
  ],
22
22
  "config": {
23
- "sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.2.3-alpha.5"
23
+ "sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.2.3"
24
24
  },
25
25
  "publishConfig": {
26
26
  "access": "public"