@rdmind/rdmind 0.1.8-alpha.9 → 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/cli.js +2147 -1814
  2. package/locales/en.js +90 -191
  3. package/locales/zh.js +102 -213
  4. package/package.json +2 -2
package/cli.js CHANGED
@@ -132660,7 +132660,7 @@ var init_loggingContentGenerator = __esm({
132660
132660
  this._logApiResponse(
132661
132661
  response.responseId ?? requestId,
132662
132662
  durationMs,
132663
- response.modelVersion || req.model,
132663
+ req.model,
132664
132664
  userPromptId,
132665
132665
  response.usageMetadata,
132666
132666
  JSON.stringify(response)
@@ -141204,10 +141204,18 @@ var init_pipeline = __esm({
141204
141204
  userPromptId,
141205
141205
  false,
141206
141206
  async (openaiRequest) => {
141207
+ const extraBody = this.contentGeneratorConfig.model?.toLowerCase().includes("glm-4.7") ? {
141208
+ thinking: {
141209
+ type: "enabled",
141210
+ clear_thinking: false
141211
+ // Enable preserved/interleaved thinking
141212
+ }
141213
+ } : void 0;
141207
141214
  const openaiResponse = await this.client.chat.completions.create(
141208
141215
  openaiRequest,
141209
141216
  {
141210
- signal: request4.config?.abortSignal
141217
+ signal: request4.config?.abortSignal,
141218
+ ...extraBody ? { extra_body: extraBody } : {}
141211
141219
  }
141212
141220
  );
141213
141221
  const geminiResponse = this.converter.convertOpenAIResponseToGemini(openaiResponse);
@@ -141221,10 +141229,18 @@ var init_pipeline = __esm({
141221
141229
  userPromptId,
141222
141230
  true,
141223
141231
  async (openaiRequest, context2) => {
141232
+ const extraBody = this.contentGeneratorConfig.model?.toLowerCase().includes("glm-4.7") ? {
141233
+ thinking: {
141234
+ type: "enabled",
141235
+ clear_thinking: false
141236
+ // Enable preserved/interleaved thinking
141237
+ }
141238
+ } : void 0;
141224
141239
  const stream2 = await this.client.chat.completions.create(
141225
141240
  openaiRequest,
141226
141241
  {
141227
- signal: request4.config?.abortSignal
141242
+ signal: request4.config?.abortSignal,
141243
+ ...extraBody ? { extra_body: extraBody } : {}
141228
141244
  }
141229
141245
  );
141230
141246
  return this.processStreamWithLogging(stream2, context2, request4);
@@ -156072,7 +156088,7 @@ __export(geminiContentGenerator_exports2, {
156072
156088
  createGeminiContentGenerator: () => createGeminiContentGenerator
156073
156089
  });
156074
156090
  function createGeminiContentGenerator(config2, gcConfig) {
156075
- const version2 = "0.1.8-alpha.9";
156091
+ const version2 = "0.1.8";
156076
156092
  const userAgent2 = config2.userAgent || `QwenCode/${version2} (${process.platform}; ${process.arch})`;
156077
156093
  const baseHeaders = {
156078
156094
  "User-Agent": userAgent2
@@ -156143,7 +156159,7 @@ function createContentGeneratorConfig(config2, authType, generationConfig) {
156143
156159
  }
156144
156160
  return {
156145
156161
  ...newContentGeneratorConfig,
156146
- model: newContentGeneratorConfig?.model || "qwen3-coder-plus"
156162
+ model: newContentGeneratorConfig?.model || "gemini-3-flash-preview(low)"
156147
156163
  };
156148
156164
  }
156149
156165
  if (authType === "anthropic" /* USE_ANTHROPIC */) {
@@ -225563,8 +225579,8 @@ var init_xhsSSOAuth = __esm({
225563
225579
  DEFAULT_TIMEOUT_MS = 1e4;
225564
225580
  DEFAULT_API_TIMEOUT_MS = 5e3;
225565
225581
  COMPANY_DEFAULT_CONFIG = {
225566
- baseUrl: "https://runway.devops.xiaohongshu.com/openai/qwen/v1",
225567
- model: "qwen3-coder-plus"
225582
+ baseUrl: "https://runway.devops.rednote.life/openai/google/v1",
225583
+ model: "gemini-3-flash-preview(low)"
225568
225584
  };
225569
225585
  ssoAuthEvents = new EventEmitter6();
225570
225586
  __name(getRequestSSOId, "getRequestSSOId");
@@ -233717,8 +233733,8 @@ var init_git_commit = __esm({
233717
233733
  "packages/core/src/generated/git-commit.ts"() {
233718
233734
  "use strict";
233719
233735
  init_esbuild_shims();
233720
- GIT_COMMIT_INFO = "f23f6fb2";
233721
- CLI_VERSION = "0.1.8-alpha.9";
233736
+ GIT_COMMIT_INFO = "8f0613d7";
233737
+ CLI_VERSION = "0.1.8";
233722
233738
  }
233723
233739
  });
233724
233740
 
@@ -304859,6 +304875,7 @@ var init_en3 = __esm({
304859
304875
  "(Use Enter to select{{tabText}})": "(Use Enter to select{{tabText}})",
304860
304876
  ", Tab to change focus": ", Tab to change focus",
304861
304877
  "To see changes, RDMind must be restarted. Press r to exit and apply changes now.": "To see changes, RDMind must be restarted. Press r to exit and apply changes now.",
304878
+ 'The command "/{{command}}" is not supported in non-interactive mode.': 'The command "/{{command}}" is not supported in non-interactive mode.',
304862
304879
  // ============================================================================
304863
304880
  // Settings Labels
304864
304881
  // ============================================================================
@@ -305090,6 +305107,10 @@ var init_en3 = __esm({
305090
305107
  "Already generating summary, wait for previous request to complete": "Already generating summary, wait for previous request to complete",
305091
305108
  "No conversation found to summarize.": "No conversation found to summarize.",
305092
305109
  "Failed to generate project context summary: {{error}}": "Failed to generate project context summary: {{error}}",
305110
+ "Saved project summary to {{filePathForDisplay}}.": "Saved project summary to {{filePathForDisplay}}.",
305111
+ "Saving project summary...": "Saving project summary...",
305112
+ "Generating project summary...": "Generating project summary...",
305113
+ "Failed to generate summary - no text content received from LLM response": "Failed to generate summary - no text content received from LLM response",
305093
305114
  // ============================================================================
305094
305115
  // Commands - Model
305095
305116
  // ============================================================================
@@ -305100,8 +305121,8 @@ var init_en3 = __esm({
305100
305121
  // ============================================================================
305101
305122
  // Commands - Clear
305102
305123
  // ============================================================================
305103
- "Clearing terminal and resetting chat.": "Clearing terminal and resetting chat.",
305104
- "Clearing terminal.": "Clearing terminal.",
305124
+ "Starting a new session, resetting chat, and clearing terminal.": "Starting a new session, resetting chat, and clearing terminal.",
305125
+ "Starting a new session and clearing.": "Starting a new session and clearing.",
305105
305126
  // ============================================================================
305106
305127
  // Commands - Compress
305107
305128
  // ============================================================================
@@ -305365,183 +305386,142 @@ var init_en3 = __esm({
305365
305386
  // ============================================================================
305366
305387
  "Waiting for user confirmation...": "Waiting for user confirmation...",
305367
305388
  "(esc to cancel, {{time}})": "(esc to cancel, {{time}})",
305368
- "I'm Feeling Lucky": "I'm Feeling Lucky",
305369
- "Shipping awesomeness... ": "Shipping awesomeness... ",
305370
- "Painting the serifs back on...": "Painting the serifs back on...",
305371
- "Navigating the slime mold...": "Navigating the slime mold...",
305372
- "Consulting the digital spirits...": "Consulting the digital spirits...",
305373
- "Reticulating splines...": "Reticulating splines...",
305374
- "Warming up the AI hamsters...": "Warming up the AI hamsters...",
305375
- "Asking the magic conch shell...": "Asking the magic conch shell...",
305376
- "Generating witty retort...": "Generating witty retort...",
305377
- "Polishing the algorithms...": "Polishing the algorithms...",
305378
- "Don't rush perfection (or my code)...": "Don't rush perfection (or my code)...",
305379
- "Brewing fresh bytes...": "Brewing fresh bytes...",
305380
- "Counting electrons...": "Counting electrons...",
305381
- "Engaging cognitive processors...": "Engaging cognitive processors...",
305382
- "Checking for syntax errors in the universe...": "Checking for syntax errors in the universe...",
305383
- "One moment, optimizing humor...": "One moment, optimizing humor...",
305384
- "Shuffling punchlines...": "Shuffling punchlines...",
305385
- "Untangling neural nets...": "Untangling neural nets...",
305386
- "Compiling brilliance...": "Compiling brilliance...",
305387
- "Loading wit.exe...": "Loading wit.exe...",
305388
- "Summoning the cloud of wisdom...": "Summoning the cloud of wisdom...",
305389
- "Preparing a witty response...": "Preparing a witty response...",
305390
- "Just a sec, I'm debugging reality...": "Just a sec, I'm debugging reality...",
305391
- "Confuzzling the options...": "Confuzzling the options...",
305392
- "Tuning the cosmic frequencies...": "Tuning the cosmic frequencies...",
305393
- "Crafting a response worthy of your patience...": "Crafting a response worthy of your patience...",
305394
- "Compiling the 1s and 0s...": "Compiling the 1s and 0s...",
305395
- "Resolving dependencies... and existential crises...": "Resolving dependencies... and existential crises...",
305396
- "Defragmenting memories... both RAM and personal...": "Defragmenting memories... both RAM and personal...",
305397
- "Rebooting the humor module...": "Rebooting the humor module...",
305398
- "Caching the essentials (mostly cat memes)...": "Caching the essentials (mostly cat memes)...",
305399
- "Optimizing for ludicrous speed": "Optimizing for ludicrous speed",
305400
- "Swapping bits... don't tell the bytes...": "Swapping bits... don't tell the bytes...",
305401
- "Garbage collecting... be right back...": "Garbage collecting... be right back...",
305402
- "Assembling the interwebs...": "Assembling the interwebs...",
305403
- "Converting coffee into code...": "Converting coffee into code...",
305404
- "Updating the syntax for reality...": "Updating the syntax for reality...",
305405
- "Rewiring the synapses...": "Rewiring the synapses...",
305406
- "Looking for a misplaced semicolon...": "Looking for a misplaced semicolon...",
305407
- "Greasin' the cogs of the machine...": "Greasin' the cogs of the machine...",
305408
- "Pre-heating the servers...": "Pre-heating the servers...",
305409
- "Calibrating the flux capacitor...": "Calibrating the flux capacitor...",
305410
- "Engaging the improbability drive...": "Engaging the improbability drive...",
305411
- "Channeling the Force...": "Channeling the Force...",
305412
- "Aligning the stars for optimal response...": "Aligning the stars for optimal response...",
305413
- "So say we all...": "So say we all...",
305414
- "Loading the next great idea...": "Loading the next great idea...",
305415
- "Just a moment, I'm in the zone...": "Just a moment, I'm in the zone...",
305416
- "Preparing to dazzle you with brilliance...": "Preparing to dazzle you with brilliance...",
305417
- "Just a tick, I'm polishing my wit...": "Just a tick, I'm polishing my wit...",
305418
- "Hold tight, I'm crafting a masterpiece...": "Hold tight, I'm crafting a masterpiece...",
305419
- "Just a jiffy, I'm debugging the universe...": "Just a jiffy, I'm debugging the universe...",
305420
- "Just a moment, I'm aligning the pixels...": "Just a moment, I'm aligning the pixels...",
305421
- "Just a sec, I'm optimizing the humor...": "Just a sec, I'm optimizing the humor...",
305422
- "Just a moment, I'm tuning the algorithms...": "Just a moment, I'm tuning the algorithms...",
305423
- "Warp speed engaged...": "Warp speed engaged...",
305424
- "Mining for more Dilithium crystals...": "Mining for more Dilithium crystals...",
305425
- "Don't panic...": "Don't panic...",
305426
- "Following the white rabbit...": "Following the white rabbit...",
305427
- "The truth is in here... somewhere...": "The truth is in here... somewhere...",
305428
- "Blowing on the cartridge...": "Blowing on the cartridge...",
305429
- "Loading... Do a barrel roll!": "Loading... Do a barrel roll!",
305430
- "Waiting for the respawn...": "Waiting for the respawn...",
305431
- "Finishing the Kessel Run in less than 12 parsecs...": "Finishing the Kessel Run in less than 12 parsecs...",
305432
- "The cake is not a lie, it's just still loading...": "The cake is not a lie, it's just still loading...",
305433
- "Fiddling with the character creation screen...": "Fiddling with the character creation screen...",
305434
- "Just a moment, I'm finding the right meme...": "Just a moment, I'm finding the right meme...",
305435
- "Pressing 'A' to continue...": "Pressing 'A' to continue...",
305436
- "Herding digital cats...": "Herding digital cats...",
305437
- "Polishing the pixels...": "Polishing the pixels...",
305438
- "Finding a suitable loading screen pun...": "Finding a suitable loading screen pun...",
305439
- "Distracting you with this witty phrase...": "Distracting you with this witty phrase...",
305440
- "Almost there... probably...": "Almost there... probably...",
305441
- "Our hamsters are working as fast as they can...": "Our hamsters are working as fast as they can...",
305442
- "Giving Cloudy a pat on the head...": "Giving Cloudy a pat on the head...",
305443
- "Petting the cat...": "Petting the cat...",
305444
- "Rickrolling my boss...": "Rickrolling my boss...",
305445
- "Never gonna give you up, never gonna let you down...": "Never gonna give you up, never gonna let you down...",
305446
- "Slapping the bass...": "Slapping the bass...",
305447
- "Tasting the snozberries...": "Tasting the snozberries...",
305448
- "I'm going the distance, I'm going for speed...": "I'm going the distance, I'm going for speed...",
305449
- "Is this the real life? Is this just fantasy?...": "Is this the real life? Is this just fantasy?...",
305450
- "I've got a good feeling about this...": "I've got a good feeling about this...",
305451
- "Poking the bear...": "Poking the bear...",
305452
- "Doing research on the latest memes...": "Doing research on the latest memes...",
305453
- "Figuring out how to make this more witty...": "Figuring out how to make this more witty...",
305454
- "Hmmm... let me think...": "Hmmm... let me think...",
305455
- "What do you call a fish with no eyes? A fsh...": "What do you call a fish with no eyes? A fsh...",
305456
- "Why did the computer go to therapy? It had too many bytes...": "Why did the computer go to therapy? It had too many bytes...",
305457
- "Why don't programmers like nature? It has too many bugs...": "Why don't programmers like nature? It has too many bugs...",
305458
- "Why do programmers prefer dark mode? Because light attracts bugs...": "Why do programmers prefer dark mode? Because light attracts bugs...",
305459
- "Why did the developer go broke? Because they used up all their cache...": "Why did the developer go broke? Because they used up all their cache...",
305460
- "What can you do with a broken pencil? Nothing, it's pointless...": "What can you do with a broken pencil? Nothing, it's pointless...",
305461
- "Applying percussive maintenance...": "Applying percussive maintenance...",
305462
- "Searching for the correct USB orientation...": "Searching for the correct USB orientation...",
305463
- "Ensuring the magic smoke stays inside the wires...": "Ensuring the magic smoke stays inside the wires...",
305464
- "Rewriting in Rust for no particular reason...": "Rewriting in Rust for no particular reason...",
305465
- "Trying to exit Vim...": "Trying to exit Vim...",
305466
- "Spinning up the hamster wheel...": "Spinning up the hamster wheel...",
305467
- "That's not a bug, it's an undocumented feature...": "That's not a bug, it's an undocumented feature...",
305468
- "Engage.": "Engage.",
305469
- "I'll be back... with an answer.": "I'll be back... with an answer.",
305470
- "My other process is a TARDIS...": "My other process is a TARDIS...",
305471
- "Communing with the machine spirit...": "Communing with the machine spirit...",
305472
- "Letting the thoughts marinate...": "Letting the thoughts marinate...",
305473
- "Just remembered where I put my keys...": "Just remembered where I put my keys...",
305474
- "Pondering the orb...": "Pondering the orb...",
305475
- "I've seen things you people wouldn't believe... like a user who reads loading messages.": "I've seen things you people wouldn't believe... like a user who reads loading messages.",
305476
- "Initiating thoughtful gaze...": "Initiating thoughtful gaze...",
305477
- "What's a computer's favorite snack? Microchips.": "What's a computer's favorite snack? Microchips.",
305478
- "Why do Java developers wear glasses? Because they don't C#.": "Why do Java developers wear glasses? Because they don't C#.",
305479
- "Charging the laser... pew pew!": "Charging the laser... pew pew!",
305480
- "Dividing by zero... just kidding!": "Dividing by zero... just kidding!",
305481
- "Looking for an adult superviso... I mean, processing.": "Looking for an adult superviso... I mean, processing.",
305482
- "Making it go beep boop.": "Making it go beep boop.",
305483
- "Buffering... because even AIs need a moment.": "Buffering... because even AIs need a moment.",
305484
- "Entangling quantum particles for a faster response...": "Entangling quantum particles for a faster response...",
305485
- "Polishing the chrome... on the algorithms.": "Polishing the chrome... on the algorithms.",
305486
- "Are you not entertained? (Working on it!)": "Are you not entertained? (Working on it!)",
305487
- "Summoning the code gremlins... to help, of course.": "Summoning the code gremlins... to help, of course.",
305488
- "Just waiting for the dial-up tone to finish...": "Just waiting for the dial-up tone to finish...",
305489
- "Recalibrating the humor-o-meter.": "Recalibrating the humor-o-meter.",
305490
- "My other loading screen is even funnier.": "My other loading screen is even funnier.",
305491
- "Pretty sure there's a cat walking on the keyboard somewhere...": "Pretty sure there's a cat walking on the keyboard somewhere...",
305492
- "Enhancing... Enhancing... Still loading.": "Enhancing... Enhancing... Still loading.",
305493
- "It's not a bug, it's a feature... of this loading screen.": "It's not a bug, it's a feature... of this loading screen.",
305494
- "Have you tried turning it off and on again? (The loading screen, not me.)": "Have you tried turning it off and on again? (The loading screen, not me.)",
305495
- "Constructing additional pylons...": "Constructing additional pylons...",
305496
- "Summoning the soul of programmers...": "Summoning the soul of programmers...",
305497
- "Fixing that bug that's not a bug, it's a feature...": "Fixing that bug that's not a bug, it's a feature...",
305498
- "Removing pinyin comments from code...": "Removing pinyin comments from code...",
305499
- "Debating whether array index starts from 0 or 1...": "Debating whether array index starts from 0 or 1...",
305500
- "Thinking about refactoring...": "Thinking about refactoring...",
305501
- "Cleaning up stack overflow...": "Cleaning up stack overflow...",
305502
- "Naming variables properly...": "Naming variables properly...",
305503
- "Commenting code written 3 months ago...": "Commenting code written 3 months ago...",
305504
- "Praying for no bugs...": "Praying for no bugs...",
305505
- "Resolving dependencies...": "Resolving dependencies...",
305506
- "Waiting for product manager to change requirements...": "Waiting for product manager to change requirements...",
305507
- "Postponing project deadline...": "Postponing project deadline...",
305508
- 'Preparing another "almost done"...': 'Preparing another "almost done"...',
305509
- "Taking a break...": "Taking a break...",
305510
- "Making goji berry tea...": "Making goji berry tea...",
305511
- "Ordering takeout...": "Ordering takeout...",
305512
- "Pretending to be busy...": "Pretending to be busy...",
305513
- "Recharging faith...": "Recharging faith...",
305514
- "Downloading more RAM...": "Downloading more RAM...",
305515
- "Feeding the server...": "Feeding the server...",
305516
- "Waking up sleeping code...": "Waking up sleeping code...",
305517
- "Feeding data to AI...": "Feeding data to AI...",
305518
- "Opening imagination...": "Opening imagination...",
305519
- "Boiling water for tea...": "Boiling water for tea...",
305520
- "Waiting for the elevator...": "Waiting for the elevator...",
305521
- "Taking a number in queue...": "Taking a number in queue...",
305522
- "Waiting for traffic light...": "Waiting for traffic light...",
305523
- "Charging...": "Charging...",
305524
- "Buffering life...": "Buffering life...",
305525
- "Contemplating the meaning of life...": "Contemplating the meaning of life...",
305526
- "What to eat today? Thinking...": "What to eat today? Thinking...",
305527
- "Pretending to work...": "Pretending to work...",
305528
- "Let me think, just a moment...": "Let me think, just a moment...",
305529
- "Brewing inspiration...": "Brewing inspiration...",
305530
- "Take a deep breath, almost done...": "Take a deep breath, almost done...",
305531
- "Don't worry, good things take time...": "Don't worry, good things take time...",
305532
- "Stay calm, exciting things coming...": "Stay calm, exciting things coming...",
305533
- "Greeting the server...": "Greeting the server...",
305534
- "Organizing thoughts...": "Organizing thoughts...",
305535
- "Preparing my words...": "Preparing my words...",
305536
- "Looking up information...": "Looking up information...",
305537
- "Sorting out my thoughts...": "Sorting out my thoughts...",
305538
- "Analyzing the problem...": "Analyzing the problem...",
305539
- "Looking for the best solution...": "Looking for the best solution...",
305540
- "Loading...": "Loading...",
305541
- "Processing, please wait...": "Processing, please wait...",
305542
- "Almost there...": "Almost there...",
305543
- "Working hard...": "Working hard...",
305544
- "Almost... almost...": "Almost... almost...",
305389
+ // ============================================================================
305390
+ // Loading Phrases
305391
+ // ============================================================================
305392
+ WITTY_LOADING_PHRASES: [
305393
+ "I'm Feeling Lucky",
305394
+ "Shipping awesomeness... ",
305395
+ "Painting the serifs back on...",
305396
+ "Navigating the slime mold...",
305397
+ "Consulting the digital spirits...",
305398
+ "Reticulating splines...",
305399
+ "Warming up the AI hamsters...",
305400
+ "Asking the magic conch shell...",
305401
+ "Generating witty retort...",
305402
+ "Polishing the algorithms...",
305403
+ "Don't rush perfection (or my code)...",
305404
+ "Brewing fresh bytes...",
305405
+ "Counting electrons...",
305406
+ "Engaging cognitive processors...",
305407
+ "Checking for syntax errors in the universe...",
305408
+ "One moment, optimizing humor...",
305409
+ "Shuffling punchlines...",
305410
+ "Untangling neural nets...",
305411
+ "Compiling brilliance...",
305412
+ "Loading wit.exe...",
305413
+ "Summoning the cloud of wisdom...",
305414
+ "Preparing a witty response...",
305415
+ "Just a sec, I'm debugging reality...",
305416
+ "Confuzzling the options...",
305417
+ "Tuning the cosmic frequencies...",
305418
+ "Crafting a response worthy of your patience...",
305419
+ "Compiling the 1s and 0s...",
305420
+ "Resolving dependencies... and existential crises...",
305421
+ "Defragmenting memories... both RAM and personal...",
305422
+ "Rebooting the humor module...",
305423
+ "Caching the essentials (mostly cat memes)...",
305424
+ "Optimizing for ludicrous speed",
305425
+ "Swapping bits... don't tell the bytes...",
305426
+ "Garbage collecting... be right back...",
305427
+ "Assembling the interwebs...",
305428
+ "Converting coffee into code...",
305429
+ "Updating the syntax for reality...",
305430
+ "Rewiring the synapses...",
305431
+ "Looking for a misplaced semicolon...",
305432
+ "Greasin' the cogs of the machine...",
305433
+ "Pre-heating the servers...",
305434
+ "Calibrating the flux capacitor...",
305435
+ "Engaging the improbability drive...",
305436
+ "Channeling the Force...",
305437
+ "Aligning the stars for optimal response...",
305438
+ "So say we all...",
305439
+ "Loading the next great idea...",
305440
+ "Just a moment, I'm in the zone...",
305441
+ "Preparing to dazzle you with brilliance...",
305442
+ "Just a tick, I'm polishing my wit...",
305443
+ "Hold tight, I'm crafting a masterpiece...",
305444
+ "Just a jiffy, I'm debugging the universe...",
305445
+ "Just a moment, I'm aligning the pixels...",
305446
+ "Just a sec, I'm optimizing the humor...",
305447
+ "Just a moment, I'm tuning the algorithms...",
305448
+ "Warp speed engaged...",
305449
+ "Mining for more Dilithium crystals...",
305450
+ "Don't panic...",
305451
+ "Following the white rabbit...",
305452
+ "The truth is in here... somewhere...",
305453
+ "Blowing on the cartridge...",
305454
+ "Loading... Do a barrel roll!",
305455
+ "Waiting for the respawn...",
305456
+ "Finishing the Kessel Run in less than 12 parsecs...",
305457
+ "The cake is not a lie, it's just still loading...",
305458
+ "Fiddling with the character creation screen...",
305459
+ "Just a moment, I'm finding the right meme...",
305460
+ "Pressing 'A' to continue...",
305461
+ "Herding digital cats...",
305462
+ "Polishing the pixels...",
305463
+ "Finding a suitable loading screen pun...",
305464
+ "Distracting you with this witty phrase...",
305465
+ "Almost there... probably...",
305466
+ "Our hamsters are working as fast as they can...",
305467
+ "Giving Cloudy a pat on the head...",
305468
+ "Petting the cat...",
305469
+ "Rickrolling my boss...",
305470
+ "Never gonna give you up, never gonna let you down...",
305471
+ "Slapping the bass...",
305472
+ "Tasting the snozberries...",
305473
+ "I'm going the distance, I'm going for speed...",
305474
+ "Is this the real life? Is this just fantasy?...",
305475
+ "I've got a good feeling about this...",
305476
+ "Poking the bear...",
305477
+ "Doing research on the latest memes...",
305478
+ "Figuring out how to make this more witty...",
305479
+ "Hmmm... let me think...",
305480
+ "What do you call a fish with no eyes? A fsh...",
305481
+ "Why did the computer go to therapy? It had too many bytes...",
305482
+ "Why don't programmers like nature? It has too many bugs...",
305483
+ "Why do programmers prefer dark mode? Because light attracts bugs...",
305484
+ "Why did the developer go broke? Because they used up all their cache...",
305485
+ "What can you do with a broken pencil? Nothing, it's pointless...",
305486
+ "Applying percussive maintenance...",
305487
+ "Searching for the correct USB orientation...",
305488
+ "Ensuring the magic smoke stays inside the wires...",
305489
+ "Rewriting in Rust for no particular reason...",
305490
+ "Trying to exit Vim...",
305491
+ "Spinning up the hamster wheel...",
305492
+ "That's not a bug, it's an undocumented feature...",
305493
+ "Engage.",
305494
+ "I'll be back... with an answer.",
305495
+ "My other process is a TARDIS...",
305496
+ "Communing with the machine spirit...",
305497
+ "Letting the thoughts marinate...",
305498
+ "Just remembered where I put my keys...",
305499
+ "Pondering the orb...",
305500
+ "I've seen things you people wouldn't believe... like a user who reads loading messages.",
305501
+ "Initiating thoughtful gaze...",
305502
+ "What's a computer's favorite snack? Microchips.",
305503
+ "Why do Java developers wear glasses? Because they don't C#.",
305504
+ "Charging the laser... pew pew!",
305505
+ "Dividing by zero... just kidding!",
305506
+ "Looking for an adult superviso... I mean, processing.",
305507
+ "Making it go beep boop.",
305508
+ "Buffering... because even AIs need a moment.",
305509
+ "Entangling quantum particles for a faster response...",
305510
+ "Polishing the chrome... on the algorithms.",
305511
+ "Are you not entertained? (Working on it!)",
305512
+ "Summoning the code gremlins... to help, of course.",
305513
+ "Just waiting for the dial-up tone to finish...",
305514
+ "Recalibrating the humor-o-meter.",
305515
+ "My other loading screen is even funnier.",
305516
+ "Pretty sure there's a cat walking on the keyboard somewhere...",
305517
+ "Enhancing... Enhancing... Still loading.",
305518
+ "It's not a bug, it's a feature... of this loading screen.",
305519
+ "Have you tried turning it off and on again? (The loading screen, not me.)",
305520
+ "Constructing additional pylons..."
305521
+ ],
305522
+ // ============================================================================
305523
+ // OpenSpec Commands
305524
+ // ============================================================================
305545
305525
  "Initialize OpenSpec in a project with RDMind integration": "Initialize OpenSpec in a project with RDMind integration",
305546
305526
  "Initialize OpenSpec in the current directory": "Initialize OpenSpec in the current directory",
305547
305527
  "Scaffold a new OpenSpec change and validate strictly.": "Scaffold a new OpenSpec change and validate strictly.",
@@ -305647,7 +305627,7 @@ var init_zh = __esm({
305647
305627
  "(empty prompt)": "(\u7A7A\u63D0\u793A\u8BCD)",
305648
305628
  "No sessions found. Start a new session with {{cmd}}.": "\u672A\u53D1\u73B0\u4F1A\u8BDD\u3002\u8BF7\u4F7F\u7528 {{cmd}} \u5F00\u59CB\u65B0\u4F1A\u8BDD\u3002",
305649
305629
  "No saved session found with ID {{sessionId}}. Run `rdmind --resume` without an ID to choose from existing sessions.": "\u672A\u53D1\u73B0 ID \u4E3A {{sessionId}} \u7684\u5DF2\u4FDD\u5B58\u4F1A\u8BDD\u3002\u8BF7\u8FD0\u884C\u4E0D\u5E26 ID \u7684 `rdmind --resume` \u4EE5\u4ECE\u73B0\u6709\u4F1A\u8BDD\u4E2D\u9009\u62E9\u3002",
305650
- "Clear conversation history and free up context": "\u6E05\u9664\u5BF9\u8BDD\u5386\u53F2",
305630
+ "Clear conversation history and free up context": "\u6E05\u9664\u5BF9\u8BDD\u5386\u53F2\u5E76\u91CA\u653E\u4E0A\u4E0B\u6587",
305651
305631
  "Compresses the context by replacing it with a summary.": "\u901A\u8FC7\u7528\u6458\u8981\u66FF\u6362\u6765\u538B\u7F29\u4E0A\u4E0B\u6587",
305652
305632
  "open full RDMind documentation in your browser": "\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\u5B8C\u6574\u7684 RDMind \u6587\u6863",
305653
305633
  "Configuration not available.": "\u914D\u7F6E\u4E0D\u53EF\u7528",
@@ -305767,6 +305747,7 @@ var init_zh = __esm({
305767
305747
  "(Use Enter to select{{tabText}})": "\uFF08\u4F7F\u7528 Enter \u9009\u62E9{{tabText}}\uFF09",
305768
305748
  ", Tab to change focus": "\uFF0CTab \u5207\u6362\u7126\u70B9",
305769
305749
  "To see changes, RDMind must be restarted. Press r to exit and apply changes now.": "\u8981\u67E5\u770B\u66F4\u6539\uFF0C\u5FC5\u987B\u91CD\u542F RDMind\u3002\u6309 r \u9000\u51FA\u5E76\u7ACB\u5373\u5E94\u7528\u66F4\u6539\u3002",
305750
+ 'The command "/{{command}}" is not supported in non-interactive mode.': '\u4E0D\u652F\u6301\u5728\u975E\u4EA4\u4E92\u6A21\u5F0F\u4E0B\u4F7F\u7528\u547D\u4EE4 "/{{command}}"\u3002',
305770
305751
  // ============================================================================
305771
305752
  // Settings Labels
305772
305753
  // ============================================================================
@@ -305998,6 +305979,10 @@ var init_zh = __esm({
305998
305979
  "Already generating summary, wait for previous request to complete": "\u6B63\u5728\u751F\u6210\u6458\u8981\uFF0C\u8BF7\u7B49\u5F85\u4E0A\u4E00\u4E2A\u8BF7\u6C42\u5B8C\u6210",
305999
305980
  "No conversation found to summarize.": "\u672A\u627E\u5230\u8981\u603B\u7ED3\u7684\u5BF9\u8BDD",
306000
305981
  "Failed to generate project context summary: {{error}}": "\u751F\u6210\u9879\u76EE\u4E0A\u4E0B\u6587\u6458\u8981\u5931\u8D25\uFF1A{{error}}",
305982
+ "Saved project summary to {{filePathForDisplay}}.": "\u9879\u76EE\u6458\u8981\u5DF2\u4FDD\u5B58\u5230 {{filePathForDisplay}}",
305983
+ "Saving project summary...": "\u6B63\u5728\u4FDD\u5B58\u9879\u76EE\u6458\u8981...",
305984
+ "Generating project summary...": "\u6B63\u5728\u751F\u6210\u9879\u76EE\u6458\u8981...",
305985
+ "Failed to generate summary - no text content received from LLM response": "\u751F\u6210\u6458\u8981\u5931\u8D25 - \u672A\u4ECE LLM \u54CD\u5E94\u4E2D\u63A5\u6536\u5230\u6587\u672C\u5185\u5BB9",
306001
305986
  // ============================================================================
306002
305987
  // Commands - Model
306003
305988
  // ============================================================================
@@ -306008,8 +305993,8 @@ var init_zh = __esm({
306008
305993
  // ============================================================================
306009
305994
  // Commands - Clear
306010
305995
  // ============================================================================
306011
- "Clearing terminal and resetting chat.": "\u6B63\u5728\u6E05\u5C4F\u5E76\u91CD\u7F6E\u804A\u5929",
306012
- "Clearing terminal.": "\u6B63\u5728\u6E05\u5C4F",
305996
+ "Starting a new session, resetting chat, and clearing terminal.": "\u6B63\u5728\u5F00\u59CB\u65B0\u4F1A\u8BDD\uFF0C\u91CD\u7F6E\u804A\u5929\u5E76\u6E05\u5C4F\u3002",
305997
+ "Starting a new session and clearing.": "\u6B63\u5728\u5F00\u59CB\u65B0\u4F1A\u8BDD\u5E76\u6E05\u5C4F\u3002",
306013
305998
  // ============================================================================
306014
305999
  // Commands - Compress
306015
306000
  // ============================================================================
@@ -306273,183 +306258,90 @@ var init_zh = __esm({
306273
306258
  // ============================================================================
306274
306259
  "Waiting for user confirmation...": "\u7B49\u5F85\u7528\u6237\u786E\u8BA4...",
306275
306260
  "(esc to cancel, {{time}})": "\uFF08\u6309 esc \u53D6\u6D88\uFF0C{{time}}\uFF09",
306276
- "I'm Feeling Lucky": "\u6211\u611F\u89C9\u5F88\u5E78\u8FD0",
306277
- "Shipping awesomeness... ": "\u6B63\u5728\u8FD0\u9001\u7CBE\u5F69\u5185\u5BB9... ",
306278
- "Painting the serifs back on...": "\u6B63\u5728\u91CD\u65B0\u7ED8\u5236\u886C\u7EBF...",
306279
- "Navigating the slime mold...": "\u6B63\u5728\u5BFC\u822A\u7C98\u6DB2\u9709\u83CC...",
306280
- "Consulting the digital spirits...": "\u6B63\u5728\u54A8\u8BE2\u6570\u5B57\u7CBE\u7075...",
306281
- "Reticulating splines...": "\u6B63\u5728\u7F51\u683C\u5316\u6837\u6761\u66F2\u7EBF...",
306282
- "Warming up the AI hamsters...": "\u6B63\u5728\u9884\u70ED AI \u4ED3\u9F20...",
306283
- "Asking the magic conch shell...": "\u6B63\u5728\u8BE2\u95EE\u9B54\u6CD5\u6D77\u87BA\u58F3...",
306284
- "Generating witty retort...": "\u6B63\u5728\u751F\u6210\u673A\u667A\u7684\u53CD\u9A73...",
306285
- "Polishing the algorithms...": "\u6B63\u5728\u6253\u78E8\u7B97\u6CD5...",
306286
- "Don't rush perfection (or my code)...": "\u4E0D\u8981\u6025\u4E8E\u8FFD\u6C42\u5B8C\u7F8E\uFF08\u6216\u6211\u7684\u4EE3\u7801\uFF09...",
306287
- "Brewing fresh bytes...": "\u6B63\u5728\u917F\u9020\u65B0\u9C9C\u5B57\u8282...",
306288
- "Counting electrons...": "\u6B63\u5728\u8BA1\u7B97\u7535\u5B50...",
306289
- "Engaging cognitive processors...": "\u6B63\u5728\u542F\u52A8\u8BA4\u77E5\u5904\u7406\u5668...",
306290
- "Checking for syntax errors in the universe...": "\u6B63\u5728\u68C0\u67E5\u5B87\u5B99\u4E2D\u7684\u8BED\u6CD5\u9519\u8BEF...",
306291
- "One moment, optimizing humor...": "\u7A0D\u7B49\u7247\u523B\uFF0C\u6B63\u5728\u4F18\u5316\u5E7D\u9ED8\u611F...",
306292
- "Shuffling punchlines...": "\u6B63\u5728\u6D17\u724C\u7B11\u70B9...",
306293
- "Untangling neural nets...": "\u6B63\u5728\u89E3\u5F00\u795E\u7ECF\u7F51\u7EDC...",
306294
- "Compiling brilliance...": "\u6B63\u5728\u7F16\u8BD1\u667A\u6167...",
306295
- "Loading wit.exe...": "\u6B63\u5728\u52A0\u8F7D wit.exe...",
306296
- "Summoning the cloud of wisdom...": "\u6B63\u5728\u53EC\u5524\u667A\u6167\u4E91...",
306297
- "Preparing a witty response...": "\u6B63\u5728\u51C6\u5907\u673A\u667A\u7684\u56DE\u590D...",
306298
- "Just a sec, I'm debugging reality...": "\u7A0D\u7B49\u7247\u523B\uFF0C\u6211\u6B63\u5728\u8C03\u8BD5\u73B0\u5B9E...",
306299
- "Confuzzling the options...": "\u6B63\u5728\u6DF7\u6DC6\u9009\u9879...",
306300
- "Tuning the cosmic frequencies...": "\u6B63\u5728\u8C03\u8C10\u5B87\u5B99\u9891\u7387...",
306301
- "Crafting a response worthy of your patience...": "\u6B63\u5728\u5236\u4F5C\u503C\u5F97\u60A8\u8010\u5FC3\u7B49\u5F85\u7684\u56DE\u590D...",
306302
- "Compiling the 1s and 0s...": "\u6B63\u5728\u7F16\u8BD1 1 \u548C 0...",
306303
- "Resolving dependencies... and existential crises...": "\u6B63\u5728\u89E3\u51B3\u4F9D\u8D56\u5173\u7CFB...\u548C\u5B58\u5728\u4E3B\u4E49\u5371\u673A...",
306304
- "Defragmenting memories... both RAM and personal...": "\u6B63\u5728\u6574\u7406\u8BB0\u5FC6\u788E\u7247...\u5305\u62EC RAM \u548C\u4E2A\u4EBA\u8BB0\u5FC6...",
306305
- "Rebooting the humor module...": "\u6B63\u5728\u91CD\u542F\u5E7D\u9ED8\u6A21\u5757...",
306306
- "Caching the essentials (mostly cat memes)...": "\u6B63\u5728\u7F13\u5B58\u5FC5\u9700\u54C1\uFF08\u4E3B\u8981\u662F\u732B\u54AA\u8868\u60C5\u5305\uFF09...",
306307
- "Optimizing for ludicrous speed": "\u6B63\u5728\u4F18\u5316\u5230\u8352\u8C2C\u7684\u901F\u5EA6",
306308
- "Swapping bits... don't tell the bytes...": "\u6B63\u5728\u4EA4\u6362\u4F4D...\u4E0D\u8981\u544A\u8BC9\u5B57\u8282...",
306309
- "Garbage collecting... be right back...": "\u6B63\u5728\u5783\u573E\u56DE\u6536...\u9A6C\u4E0A\u56DE\u6765...",
306310
- "Assembling the interwebs...": "\u6B63\u5728\u7EC4\u88C5\u4E92\u8054\u7F51...",
306311
- "Converting coffee into code...": "\u6B63\u5728\u5C06\u5496\u5561\u8F6C\u6362\u4E3A\u4EE3\u7801...",
306312
- "Updating the syntax for reality...": "\u6B63\u5728\u66F4\u65B0\u73B0\u5B9E\u7684\u8BED\u6CD5...",
306313
- "Rewiring the synapses...": "\u6B63\u5728\u91CD\u65B0\u8FDE\u63A5\u7A81\u89E6...",
306314
- "Looking for a misplaced semicolon...": "\u6B63\u5728\u5BFB\u627E\u6D88\u5931\u7684\u5206\u53F7...",
306315
- "Greasin' the cogs of the machine...": "\u6B63\u5728\u7ED9\u673A\u5668\u7684\u9F7F\u8F6E\u4E0A\u6CB9...",
306316
- "Pre-heating the servers...": "\u6B63\u5728\u9884\u70ED\u670D\u52A1\u5668...",
306317
- "Calibrating the flux capacitor...": "\u6B63\u5728\u6821\u51C6\u901A\u91CF\u7535\u5BB9\u5668...",
306318
- "Engaging the improbability drive...": "\u6B63\u5728\u542F\u52A8\u4E0D\u53EF\u80FD\u6027\u9A71\u52A8\u5668...",
306319
- "Channeling the Force...": "\u6B63\u5728\u5F15\u5BFC\u539F\u529B...",
306320
- "Aligning the stars for optimal response...": "\u6B63\u5728\u5BF9\u9F50\u661F\u661F\u4EE5\u83B7\u5F97\u6700\u4F73\u56DE\u590D...",
306321
- "So say we all...": "\u6211\u4EEC\u90FD\u8BF4...",
306322
- "Loading the next great idea...": "\u6B63\u5728\u52A0\u8F7D\u4E0B\u4E00\u4E2A\u4F1F\u5927\u7684\u60F3\u6CD5...",
306323
- "Just a moment, I'm in the zone...": "\u7A0D\u7B49\u7247\u523B\uFF0C\u6211\u6B63\u8FDB\u5165\u72B6\u6001...",
306324
- "Preparing to dazzle you with brilliance...": "\u6B63\u5728\u51C6\u5907\u7528\u667A\u6167\u8BA9\u60A8\u773C\u82B1\u7F2D\u4E71...",
306325
- "Just a tick, I'm polishing my wit...": "\u7A0D\u7B49\u7247\u523B\uFF0C\u6211\u6B63\u5728\u6253\u78E8\u6211\u7684\u667A\u6167...",
306326
- "Hold tight, I'm crafting a masterpiece...": "\u8BF7\u7A0D\u7B49\uFF0C\u6211\u6B63\u5728\u5236\u4F5C\u6770\u4F5C...",
306327
- "Just a jiffy, I'm debugging the universe...": "\u7A0D\u7B49\u7247\u523B\uFF0C\u6211\u6B63\u5728\u8C03\u8BD5\u5B87\u5B99...",
306328
- "Just a moment, I'm aligning the pixels...": "\u7A0D\u7B49\u7247\u523B\uFF0C\u6211\u6B63\u5728\u5BF9\u9F50\u50CF\u7D20...",
306329
- "Just a sec, I'm optimizing the humor...": "\u7A0D\u7B49\u7247\u523B\uFF0C\u6211\u6B63\u5728\u4F18\u5316\u5E7D\u9ED8\u611F...",
306330
- "Just a moment, I'm tuning the algorithms...": "\u7A0D\u7B49\u7247\u523B\uFF0C\u6211\u6B63\u5728\u8C03\u6574\u7B97\u6CD5...",
306331
- "Warp speed engaged...": "\u66F2\u901F\u5DF2\u542F\u52A8...",
306332
- "Mining for more Dilithium crystals...": "\u6B63\u5728\u6316\u6398\u66F4\u591A\u4E8C\u9502\u6676\u4F53...",
306333
- "Don't panic...": "\u4E0D\u8981\u60CA\u614C...",
306334
- "Following the white rabbit...": "\u6B63\u5728\u8DDF\u968F\u767D\u5154...",
306335
- "The truth is in here... somewhere...": "\u771F\u76F8\u5728\u8FD9\u91CC...\u67D0\u4E2A\u5730\u65B9...",
306336
- "Blowing on the cartridge...": "\u6B63\u5728\u5439\u5361\u5E26...",
306337
- "Loading... Do a barrel roll!": "\u6B63\u5728\u52A0\u8F7D...\u505A\u4E2A\u6876\u6EDA\uFF01",
306338
- "Waiting for the respawn...": "\u7B49\u5F85\u91CD\u751F...",
306339
- "Finishing the Kessel Run in less than 12 parsecs...": "\u6B63\u5728\u4EE5\u4E0D\u5230 12 \u79D2\u5DEE\u8DDD\u5B8C\u6210\u51EF\u585E\u5C14\u822A\u7EBF...",
306340
- "The cake is not a lie, it's just still loading...": "\u86CB\u7CD5\u4E0D\u662F\u8C0E\u8A00\uFF0C\u53EA\u662F\u8FD8\u5728\u52A0\u8F7D...",
306341
- "Fiddling with the character creation screen...": "\u6B63\u5728\u6446\u5F04\u89D2\u8272\u521B\u5EFA\u754C\u9762...",
306342
- "Just a moment, I'm finding the right meme...": "\u7A0D\u7B49\u7247\u523B\uFF0C\u6211\u6B63\u5728\u5BFB\u627E\u5408\u9002\u7684\u8868\u60C5\u5305...",
306343
- "Pressing 'A' to continue...": "\u6309 'A' \u7EE7\u7EED...",
306344
- "Herding digital cats...": "\u6B63\u5728\u653E\u7267\u6570\u5B57\u732B...",
306345
- "Polishing the pixels...": "\u6B63\u5728\u6253\u78E8\u50CF\u7D20...",
306346
- "Finding a suitable loading screen pun...": "\u6B63\u5728\u5BFB\u627E\u5408\u9002\u7684\u52A0\u8F7D\u5C4F\u5E55\u53CC\u5173\u8BED...",
306347
- "Distracting you with this witty phrase...": "\u6B63\u5728\u7528\u8FD9\u4E2A\u673A\u667A\u7684\u77ED\u8BED\u5206\u6563\u60A8\u7684\u6CE8\u610F\u529B...",
306348
- "Almost there... probably...": "\u5FEB\u5230\u4E86...\u53EF\u80FD...",
306349
- "Our hamsters are working as fast as they can...": "\u6211\u4EEC\u7684\u4ED3\u9F20\u6B63\u5728\u5C3D\u53EF\u80FD\u5FEB\u5730\u5DE5\u4F5C...",
306350
- "Giving Cloudy a pat on the head...": "\u6B63\u5728\u62CD\u62CD Cloudy \u7684\u5934...",
306351
- "Petting the cat...": "\u6B63\u5728\u629A\u6478\u732B\u54AA...",
306352
- "Rickrolling my boss...": "\u6B63\u5728 Rickroll \u6211\u7684\u8001\u677F...",
306353
- "Never gonna give you up, never gonna let you down...": "\u6C38\u8FDC\u4E0D\u4F1A\u653E\u5F03\u4F60\uFF0C\u6C38\u8FDC\u4E0D\u4F1A\u8BA9\u4F60\u5931\u671B...",
306354
- "Slapping the bass...": "\u6B63\u5728\u62CD\u6253\u4F4E\u97F3...",
306355
- "Tasting the snozberries...": "\u6B63\u5728\u54C1\u5C1D snozberries...",
306356
- "I'm going the distance, I'm going for speed...": "\u6211\u8981\u8D70\u5F97\u66F4\u8FDC\uFF0C\u6211\u8981\u8FFD\u6C42\u901F\u5EA6...",
306357
- "Is this the real life? Is this just fantasy?...": "\u8FD9\u662F\u771F\u5B9E\u7684\u751F\u6D3B\u5417\uFF1F\u8FD8\u662F\u53EA\u662F\u5E7B\u60F3\uFF1F...",
306358
- "I've got a good feeling about this...": "\u6211\u5BF9\u8FD9\u4E2A\u611F\u89C9\u5F88\u597D...",
306359
- "Poking the bear...": "\u6B63\u5728\u6233\u718A...",
306360
- "Doing research on the latest memes...": "\u6B63\u5728\u7814\u7A76\u6700\u65B0\u7684\u8868\u60C5\u5305...",
306361
- "Figuring out how to make this more witty...": "\u6B63\u5728\u60F3\u529E\u6CD5\u8BA9\u8FD9\u66F4\u6709\u8DA3...",
306362
- "Hmmm... let me think...": "\u55EF...\u8BA9\u6211\u60F3\u60F3...",
306363
- "What do you call a fish with no eyes? A fsh...": "\u6CA1\u6709\u773C\u775B\u7684\u9C7C\u53EB\u4EC0\u4E48\uFF1F\u4E00\u6761\u9C7C...",
306364
- "Why did the computer go to therapy? It had too many bytes...": "\u4E3A\u4EC0\u4E48\u7535\u8111\u53BB\u770B\u5FC3\u7406\u533B\u751F\uFF1F\u56E0\u4E3A\u5B83\u6709\u592A\u591A\u5B57\u8282...",
306365
- "Why don't programmers like nature? It has too many bugs...": "\u4E3A\u4EC0\u4E48\u7A0B\u5E8F\u5458\u4E0D\u559C\u6B22\u5927\u81EA\u7136\uFF1F\u56E0\u4E3A\u866B\u5B50\u592A\u591A\u4E86...",
306366
- "Why do programmers prefer dark mode? Because light attracts bugs...": "\u4E3A\u4EC0\u4E48\u7A0B\u5E8F\u5458\u559C\u6B22\u6697\u8272\u6A21\u5F0F\uFF1F\u56E0\u4E3A\u5149\u4F1A\u5438\u5F15\u866B\u5B50...",
306367
- "Why did the developer go broke? Because they used up all their cache...": "\u4E3A\u4EC0\u4E48\u5F00\u53D1\u8005\u7834\u4EA7\u4E86\uFF1F\u56E0\u4E3A\u4ED6\u4EEC\u7528\u5B8C\u4E86\u6240\u6709\u7F13\u5B58...",
306368
- "What can you do with a broken pencil? Nothing, it's pointless...": "\u4F60\u80FD\u7528\u65AD\u4E86\u7684\u94C5\u7B14\u505A\u4EC0\u4E48\uFF1F\u4EC0\u4E48\u90FD\u4E0D\u80FD\uFF0C\u56E0\u4E3A\u5B83\u6CA1\u6709\u7B14\u5C16...",
306369
- "Applying percussive maintenance...": "\u6B63\u5728\u5E94\u7528\u6572\u51FB\u7EF4\u62A4...",
306370
- "Searching for the correct USB orientation...": "\u6B63\u5728\u5BFB\u627E\u6B63\u786E\u7684 USB \u65B9\u5411...",
306371
- "Ensuring the magic smoke stays inside the wires...": "\u786E\u4FDD\u9B54\u6CD5\u70DF\u96FE\u7559\u5728\u7535\u7EBF\u5185...",
306372
- "Rewriting in Rust for no particular reason...": "\u6B63\u5728\u7528 Rust \u91CD\u5199\uFF0C\u6CA1\u6709\u7279\u522B\u7684\u539F\u56E0...",
306373
- "Trying to exit Vim...": "\u6B63\u5728\u5C1D\u8BD5\u9000\u51FA Vim...",
306374
- "Spinning up the hamster wheel...": "\u6B63\u5728\u542F\u52A8\u4ED3\u9F20\u8F6E...",
306375
- "That's not a bug, it's an undocumented feature...": "\u8FD9\u4E0D\u662F\u4E00\u4E2A\u9519\u8BEF\uFF0C\u8FD9\u662F\u4E00\u4E2A\u672A\u8BB0\u5F55\u7684\u529F\u80FD...",
306376
- "Engage.": "\u542F\u52A8\u3002",
306377
- "I'll be back... with an answer.": "\u6211\u4F1A\u56DE\u6765\u7684...\u5E26\u7740\u7B54\u6848\u3002",
306378
- "My other process is a TARDIS...": "\u6211\u7684\u53E6\u4E00\u4E2A\u8FDB\u7A0B\u662F TARDIS...",
306379
- "Communing with the machine spirit...": "\u6B63\u5728\u4E0E\u673A\u5668\u7CBE\u795E\u4EA4\u6D41...",
306380
- "Letting the thoughts marinate...": "\u8BA9\u60F3\u6CD5\u6162\u6162\u915D\u917F...",
306381
- "Just remembered where I put my keys...": "\u521A\u521A\u60F3\u8D77\u6211\u628A\u94A5\u5319\u653E\u5728\u54EA\u91CC\u4E86...",
306382
- "Pondering the orb...": "\u6B63\u5728\u601D\u8003\u7403\u4F53...",
306383
- "I've seen things you people wouldn't believe... like a user who reads loading messages.": "\u6211\u89C1\u8FC7\u4F60\u4EEC\u4E0D\u4F1A\u76F8\u4FE1\u7684\u4E8B\u60C5...\u6BD4\u5982\u4E00\u4E2A\u9605\u8BFB\u52A0\u8F7D\u6D88\u606F\u7684\u7528\u6237\u3002",
306384
- "Initiating thoughtful gaze...": "\u6B63\u5728\u542F\u52A8\u6DF1\u601D\u51DD\u89C6...",
306385
- "What's a computer's favorite snack? Microchips.": "\u7535\u8111\u6700\u559C\u6B22\u7684\u96F6\u98DF\u662F\u4EC0\u4E48\uFF1F\u5FAE\u82AF\u7247\u3002",
306386
- "Why do Java developers wear glasses? Because they don't C#.": "\u4E3A\u4EC0\u4E48 Java \u5F00\u53D1\u8005\u6234\u773C\u955C\uFF1F\u56E0\u4E3A\u4ED6\u4EEC\u4E0D\u4F1A C#\u3002",
306387
- "Charging the laser... pew pew!": "\u6B63\u5728\u7ED9\u6FC0\u5149\u5145\u7535...\u7830\u7830\uFF01",
306388
- "Dividing by zero... just kidding!": "\u9664\u4EE5\u96F6...\u53EA\u662F\u5F00\u73A9\u7B11\uFF01",
306389
- "Looking for an adult superviso... I mean, processing.": "\u6B63\u5728\u5BFB\u627E\u6210\u4EBA\u76D1\u7763...\u6211\u662F\u8BF4\uFF0C\u5904\u7406\u4E2D\u3002",
306390
- "Making it go beep boop.": "\u8BA9\u5B83\u53D1\u51FA\u54D4\u54D4\u58F0\u3002",
306391
- "Buffering... because even AIs need a moment.": "\u6B63\u5728\u7F13\u51B2...\u56E0\u4E3A\u5373\u4F7F\u662F AI \u4E5F\u9700\u8981\u7247\u523B\u3002",
306392
- "Entangling quantum particles for a faster response...": "\u6B63\u5728\u7EA0\u7F20\u91CF\u5B50\u7C92\u5B50\u4EE5\u83B7\u5F97\u66F4\u5FEB\u7684\u56DE\u590D...",
306393
- "Polishing the chrome... on the algorithms.": "\u6B63\u5728\u6253\u78E8\u94EC...\u5728\u7B97\u6CD5\u4E0A\u3002",
306394
- "Are you not entertained? (Working on it!)": "\u4F60\u4E0D\u89C9\u5F97\u6709\u8DA3\u5417\uFF1F\uFF08\u6B63\u5728\u52AA\u529B\uFF01\uFF09",
306395
- "Summoning the code gremlins... to help, of course.": "\u6B63\u5728\u53EC\u5524\u4EE3\u7801\u5C0F\u7CBE\u7075...\u5F53\u7136\u662F\u6765\u5E2E\u5FD9\u7684\u3002",
306396
- "Just waiting for the dial-up tone to finish...": "\u53EA\u662F\u7B49\u5F85\u62E8\u53F7\u97F3\u7ED3\u675F...",
306397
- "Recalibrating the humor-o-meter.": "\u6B63\u5728\u91CD\u65B0\u6821\u51C6\u5E7D\u9ED8\u8BA1\u3002",
306398
- "My other loading screen is even funnier.": "\u6211\u7684\u53E6\u4E00\u4E2A\u52A0\u8F7D\u5C4F\u5E55\u66F4\u6709\u8DA3\u3002",
306399
- "Pretty sure there's a cat walking on the keyboard somewhere...": "\u5F88\u786E\u5B9A\u6709\u53EA\u732B\u5728\u67D0\u4E2A\u5730\u65B9\u952E\u76D8\u4E0A\u8D70...",
306400
- "Enhancing... Enhancing... Still loading.": "\u6B63\u5728\u589E\u5F3A...\u6B63\u5728\u589E\u5F3A...\u4ECD\u5728\u52A0\u8F7D\u3002",
306401
- "It's not a bug, it's a feature... of this loading screen.": "\u8FD9\u4E0D\u662F\u4E00\u4E2A\u9519\u8BEF\uFF0C\u8FD9\u662F\u4E00\u4E2A\u529F\u80FD...\u8FD9\u4E2A\u52A0\u8F7D\u5C4F\u5E55\u7684\u529F\u80FD\u3002",
306402
- "Have you tried turning it off and on again? (The loading screen, not me.)": "\u4F60\u8BD5\u8FC7\u628A\u5B83\u5173\u6389\u518D\u6253\u5F00\u5417\uFF1F\uFF08\u52A0\u8F7D\u5C4F\u5E55\uFF0C\u4E0D\u662F\u6211\u3002\uFF09",
306403
- "Constructing additional pylons...": "\u6B63\u5728\u5EFA\u9020\u989D\u5916\u7684\u80FD\u91CF\u5854...",
306404
- "Summoning the soul of programmers...": "\u6B63\u5728\u53EC\u5524\u7A0B\u5E8F\u5458\u7684\u7075\u9B42...",
306405
- "Fixing that bug that's not a bug, it's a feature...": "\u6B63\u5728\u4FEE\u590D\u90A3\u4E2A\u4E0D\u7B97 bug \u7684 feature...",
306406
- "Removing pinyin comments from code...": "\u6B63\u5728\u6E05\u9664\u4EE3\u7801\u91CC\u7684\u62FC\u97F3\u6CE8\u91CA...",
306407
- "Debating whether array index starts from 0 or 1...": "\u6B63\u5728\u4E89\u8BBA\u6570\u7EC4\u4E0B\u6807\u4ECE 0 \u8FD8\u662F\u4ECE 1...",
306408
- "Thinking about refactoring...": "\u6B63\u5728\u601D\u8003\u8981\u4E0D\u8981\u91CD\u6784...",
306409
- "Cleaning up stack overflow...": "\u6B63\u5728\u6E05\u7406\u5806\u6808\u6EA2\u51FA...",
306410
- "Naming variables properly...": "\u6B63\u5728\u7ED9\u53D8\u91CF\u8D77\u4E2A\u597D\u540D\u5B57...",
306411
- "Commenting code written 3 months ago...": "\u6B63\u5728\u6CE8\u91CA\u4E09\u4E2A\u6708\u524D\u5199\u7684\u4EE3\u7801...",
306412
- "Praying for no bugs...": "\u6B63\u5728\u7948\u7977\u4E0D\u8981\u6709 bug...",
306413
- "Resolving dependencies...": "\u6B63\u5728\u89E3\u51B3\u4F9D\u8D56\u5173\u7CFB...",
306414
- "Waiting for product manager to change requirements...": "\u6B63\u5728\u7B49\u5F85\u4EA7\u54C1\u7ECF\u7406\u6539\u9700\u6C42...",
306415
- "Postponing project deadline...": "\u6B63\u5728\u5EF6\u671F\u9879\u76EE\u622A\u6B62\u65E5\u671F...",
306416
- 'Preparing another "almost done"...': '\u6B63\u5728\u51C6\u5907\u53C8\u4E00\u6B21"\u5FEB\u597D\u4E86"...',
306417
- "Taking a break...": "\u6B63\u5728\u6478\u9C7C...",
306418
- "Making goji berry tea...": "\u6B63\u5728\u6CE1\u67B8\u675E...",
306419
- "Ordering takeout...": "\u6B63\u5728\u70B9\u5916\u5356...",
306420
- "Pretending to be busy...": "\u6B63\u5728\u5047\u88C5\u5F88\u5FD9...",
306421
- "Recharging faith...": "\u6B63\u5728\u5145\u503C\u4FE1\u4EF0...",
306422
- "Downloading more RAM...": "\u6B63\u5728\u4E0B\u8F7D\u66F4\u591A\u5185\u5B58...",
306423
- "Feeding the server...": "\u6B63\u5728\u6295\u5582\u670D\u52A1\u5668...",
306424
- "Waking up sleeping code...": "\u6B63\u5728\u5524\u9192\u6C89\u7761\u7684\u4EE3\u7801...",
306425
- "Feeding data to AI...": "\u6B63\u5728\u7ED9 AI \u5582\u6570\u636E...",
306426
- "Opening imagination...": "\u6B63\u5728\u6253\u5F00\u8111\u6D1E...",
306427
- "Boiling water for tea...": "\u6B63\u5728\u70E7\u5F00\u6C34\u6CE1\u8336...",
306428
- "Waiting for the elevator...": "\u6B63\u5728\u7B49\u7535\u68AF...",
306429
- "Taking a number in queue...": "\u6B63\u5728\u6392\u961F\u53D6\u53F7...",
306430
- "Waiting for traffic light...": "\u6B63\u5728\u7B49\u7EA2\u7EFF\u706F...",
306431
- "Charging...": "\u6B63\u5728\u5145\u7535\u4E2D...",
306432
- "Buffering life...": "\u6B63\u5728\u7F13\u51B2\u4EBA\u751F...",
306433
- "Contemplating the meaning of life...": "\u6B63\u5728\u601D\u8003\u4EBA\u751F\u7684\u610F\u4E49...",
306434
- "What to eat today? Thinking...": "\u4ECA\u5929\u5403\u4EC0\u4E48\uFF1F\u6B63\u5728\u601D\u8003\u4E2D...",
306435
- "Pretending to work...": "\u6B63\u5728\u5047\u88C5\u5728\u5DE5\u4F5C...",
306436
- "Let me think, just a moment...": "\u8BA9\u6211\u60F3\u60F3\uFF0C\u7A0D\u7B49\u4E00\u4E0B...",
306437
- "Brewing inspiration...": "\u6B63\u5728\u915D\u917F\u7075\u611F...",
306438
- "Take a deep breath, almost done...": "\u6DF1\u547C\u5438\uFF0C\u9A6C\u4E0A\u5C31\u597D...",
306439
- "Don't worry, good things take time...": "\u4E0D\u8981\u7740\u6025\uFF0C\u597D\u996D\u4E0D\u6015\u665A...",
306440
- "Stay calm, exciting things coming...": "\u7A0D\u5B89\u52FF\u8E81\uFF0C\u7CBE\u5F69\u5373\u5C06\u5448\u73B0...",
306441
- "Greeting the server...": "\u6B63\u5728\u5411\u670D\u52A1\u5668\u95EE\u597D...",
306442
- "Organizing thoughts...": "\u6B63\u5728\u6574\u7406\u601D\u7EEA...",
306443
- "Preparing my words...": "\u6B63\u5728\u7EC4\u7EC7\u8BED\u8A00...",
306444
- "Looking up information...": "\u6B63\u5728\u67E5\u9605\u8D44\u6599...",
306445
- "Sorting out my thoughts...": "\u8BA9\u6211\u7406\u4E00\u7406\u601D\u8DEF...",
306446
- "Analyzing the problem...": "\u6B63\u5728\u5206\u6790\u95EE\u9898...",
306447
- "Looking for the best solution...": "\u6B63\u5728\u5BFB\u627E\u6700\u4F73\u65B9\u6848...",
306448
- "Loading...": "\u6B63\u5728\u52A0\u8F7D...",
306449
- "Processing, please wait...": "\u5904\u7406\u4E2D\uFF0C\u8BF7\u7A0D\u5019...",
306450
- "Almost there...": "\u9A6C\u4E0A\u5C31\u597D...",
306451
- "Working hard...": "\u6B63\u5728\u52AA\u529B\u5DE5\u4F5C\u4E2D...",
306452
- "Almost... almost...": "\u5FEB\u4E86\uFF0C\u5FEB\u4E86...",
306261
+ WITTY_LOADING_PHRASES: [
306262
+ // --- 编程/技术相关 ---
306263
+ "\u6B63\u5728\u53EC\u5524\u7A0B\u5E8F\u5458\u7684\u7075\u9B42...",
306264
+ "\u6B63\u5728\u4FEE\u590D\u90A3\u4E2A\u4E0D\u7B97 bug \u7684 feature...",
306265
+ "\u6B63\u5728\u6E05\u9664\u4EE3\u7801\u91CC\u7684\u62FC\u97F3\u6CE8\u91CA...",
306266
+ "\u6B63\u5728\u4E89\u8BBA\u6570\u7EC4\u4E0B\u6807\u4ECE 0 \u8FD8\u662F\u4ECE 1...",
306267
+ "\u6B63\u5728\u601D\u8003\u8981\u4E0D\u8981\u91CD\u6784...",
306268
+ "\u6B63\u5728\u5BFB\u627E\u6D88\u5931\u7684\u5206\u53F7...",
306269
+ "\u6B63\u5728\u6E05\u7406\u5806\u6808\u6EA2\u51FA...",
306270
+ "\u6B63\u5728\u7ED9\u53D8\u91CF\u8D77\u4E2A\u597D\u540D\u5B57...",
306271
+ "\u6B63\u5728\u6CE8\u91CA\u4E09\u4E2A\u6708\u524D\u5199\u7684\u4EE3\u7801...",
306272
+ "\u6B63\u5728\u7948\u7977\u4E0D\u8981\u6709 bug...",
306273
+ "\u6B63\u5728\u5C1D\u8BD5\u9000\u51FA Vim...",
306274
+ "\u6B63\u5728\u5BFB\u627E\u6B63\u786E\u7684 USB \u65B9\u5411...",
306275
+ "\u8FD9\u4E0D\u662F\u4E00\u4E2A\u9519\u8BEF\uFF0C\u8FD9\u662F\u4E00\u4E2A\u672A\u8BB0\u5F55\u7684\u529F\u80FD...",
306276
+ "\u6B63\u5728\u6253\u78E8\u7B97\u6CD5...",
306277
+ "\u6B63\u5728\u7F16\u8BD1\u667A\u6167...",
306278
+ "\u6B63\u5728\u89E3\u5F00\u795E\u7ECF\u7F51\u7EDC...",
306279
+ "\u6B63\u5728\u5783\u573E\u56DE\u6536...\u9A6C\u4E0A\u56DE\u6765...",
306280
+ "\u6B63\u5728\u89E3\u51B3\u4F9D\u8D56\u5173\u7CFB...",
306281
+ "\u6B63\u5728\u5C06\u5496\u5561\u8F6C\u6362\u4E3A\u4EE3\u7801...",
306282
+ // --- 工作/职场相关 ---
306283
+ "\u6B63\u5728\u7B49\u5F85\u4EA7\u54C1\u7ECF\u7406\u6539\u9700\u6C42...",
306284
+ "\u6B63\u5728\u5EF6\u671F\u9879\u76EE\u622A\u6B62\u65E5\u671F...",
306285
+ '\u6B63\u5728\u51C6\u5907\u53C8\u4E00\u6B21"\u5FEB\u597D\u4E86"...',
306286
+ "\u6B63\u5728\u6478\u9C7C...",
306287
+ "\u6B63\u5728\u6CE1\u67B8\u675E...",
306288
+ "\u6B63\u5728\u70B9\u5916\u5356...",
306289
+ "\u6B63\u5728\u5047\u88C5\u5F88\u5FD9...",
306290
+ // --- 合作愉快系列 ---
306291
+ "\u6B63\u5728\u8BE2\u95EE\u4EA7\u54C1\u7ECF\u7406\uFF1A\u8FD9\u9700\u6C42\u662F\u771F\u7684\u5417\uFF1F",
306292
+ "\u6B63\u5728\u7ED9\u4EA7\u54C1\u7ECF\u7406\u753B\u997C\uFF0C\u8BF7\u7A0D\u7B49...",
306293
+ // --- 温暖治愈系列 ---
306294
+ "\u6BCF\u4E00\u884C\u4EE3\u7801\uFF0C\u90FD\u5728\u52AA\u529B\u8BA9\u4E16\u754C\u53D8\u5F97\u66F4\u597D\u4E00\u70B9\u70B9...",
306295
+ "\u6BCF\u4E00\u4E2A\u4F1F\u5927\u7684\u60F3\u6CD5\uFF0C\u90FD\u503C\u5F97\u8FD9\u4EFD\u8010\u5FC3\u7684\u7B49\u5F85...",
306296
+ "\u522B\u6025\uFF0C\u7F8E\u597D\u7684\u4E8B\u7269\u603B\u662F\u9700\u8981\u4E00\u70B9\u65F6\u95F4\u53BB\u915D\u917F...",
306297
+ "\u613F\u4F60\u7684\u4EE3\u7801\u6C38\u65E0 Bug\uFF0C\u613F\u4F60\u7684\u68A6\u60F3\u7EC8\u5C06\u6210\u771F...",
306298
+ "\u54EA\u6015\u53EA\u6709 0.1% \u7684\u8FDB\u5EA6\uFF0C\u4E5F\u662F\u5728\u5411\u76EE\u6807\u9760\u8FD1...",
306299
+ "\u52A0\u8F7D\u7684\u662F\u5B57\u8282\uFF0C\u627F\u8F7D\u7684\u662F\u5BF9\u6280\u672F\u7684\u70ED\u7231...",
306300
+ // --- 互联网文化/梗 ---
306301
+ "\u6B63\u5728\u5145\u503C\u4FE1\u4EF0...",
306302
+ "\u6B63\u5728\u4E0B\u8F7D\u66F4\u591A\u5185\u5B58...",
306303
+ "\u6B63\u5728\u6295\u5582\u670D\u52A1\u5668...",
306304
+ "\u6B63\u5728\u5524\u9192\u6C89\u7761\u7684\u4EE3\u7801...",
306305
+ "\u6B63\u5728\u7ED9 AI \u5582\u6570\u636E...",
306306
+ "\u6B63\u5728\u6253\u5F00\u8111\u6D1E...",
306307
+ // --- 日常生活 ---
306308
+ "\u6B63\u5728\u70E7\u5F00\u6C34\u6CE1\u8336...",
306309
+ "\u6B63\u5728\u7B49\u7535\u68AF...",
306310
+ "\u6B63\u5728\u6392\u961F\u53D6\u53F7...",
306311
+ "\u6B63\u5728\u7B49\u7EA2\u7EFF\u706F...",
306312
+ "\u6B63\u5728\u5145\u7535\u4E2D...",
306313
+ "\u6B63\u5728\u7F13\u51B2\u4EBA\u751F...",
306314
+ // --- 轻松幽默 ---
306315
+ "\u6B63\u5728\u601D\u8003\u4EBA\u751F\u7684\u610F\u4E49...",
306316
+ "\u4ECA\u5929\u5403\u4EC0\u4E48\uFF1F\u6B63\u5728\u601D\u8003\u4E2D...",
306317
+ "\u6B63\u5728\u5047\u88C5\u5728\u5DE5\u4F5C...",
306318
+ "\u8BA9\u6211\u60F3\u60F3\uFF0C\u7A0D\u7B49\u4E00\u4E0B...",
306319
+ "\u6B63\u5728\u915D\u917F\u7075\u611F...",
306320
+ "\u6DF1\u547C\u5438\uFF0C\u9A6C\u4E0A\u5C31\u597D...",
306321
+ "\u4E0D\u8981\u7740\u6025\uFF0C\u597D\u996D\u4E0D\u6015\u665A...",
306322
+ "\u7A0D\u5B89\u52FF\u8E81\uFF0C\u7CBE\u5F69\u5373\u5C06\u5448\u73B0...",
306323
+ "\u55EF...\u8BA9\u6211\u60F3\u60F3...",
306324
+ // --- 技术向但接地气 ---
306325
+ "\u6B63\u5728\u5411\u670D\u52A1\u5668\u95EE\u597D...",
306326
+ "\u6B63\u5728\u6574\u7406\u601D\u7EEA...",
306327
+ "\u6B63\u5728\u7EC4\u7EC7\u8BED\u8A00...",
306328
+ "\u6B63\u5728\u67E5\u9605\u8D44\u6599...",
306329
+ "\u8BA9\u6211\u7406\u4E00\u7406\u601D\u8DEF...",
306330
+ "\u6B63\u5728\u5206\u6790\u95EE\u9898...",
306331
+ "\u6B63\u5728\u5BFB\u627E\u6700\u4F73\u65B9\u6848...",
306332
+ "\u6B63\u5728\u542F\u52A8\u8BA4\u77E5\u5904\u7406\u5668...",
306333
+ "\u6B63\u5728\u5236\u4F5C\u503C\u5F97\u60A8\u8010\u5FC3\u7B49\u5F85\u7684\u56DE\u590D...",
306334
+ // --- 保持通用性 ---
306335
+ "\u6B63\u5728\u52A0\u8F7D...",
306336
+ "\u5904\u7406\u4E2D\uFF0C\u8BF7\u7A0D\u5019...",
306337
+ "\u9A6C\u4E0A\u5C31\u597D...",
306338
+ "\u6B63\u5728\u52AA\u529B\u5DE5\u4F5C\u4E2D...",
306339
+ "\u5FEB\u4E86\uFF0C\u5FEB\u4E86...",
306340
+ "\u5FEB\u5230\u4E86...\u53EF\u80FD..."
306341
+ ],
306342
+ // ============================================================================
306343
+ // OpenSpec Commands
306344
+ // ============================================================================
306453
306345
  "Initialize OpenSpec in a project with RDMind integration": "\u5728\u9879\u76EE\u4E2D\u521D\u59CB\u5316 OpenSpec\uFF08\u96C6\u6210 RDMind\uFF09",
306454
306346
  "Initialize OpenSpec in the current directory": "\u5728\u5F53\u524D\u76EE\u5F55\u521D\u59CB\u5316 OpenSpec",
306455
306347
  "Scaffold a new OpenSpec change and validate strictly.": "\u642D\u5EFA\u65B0\u7684 OpenSpec \u53D8\u66F4\u5E76\u4E25\u683C\u9A8C\u8BC1\u3002",
@@ -332090,7 +331982,7 @@ var loadYoga = (() => {
332090
331982
  pa.unshift(a2);
332091
331983
  }
332092
331984
  __name(sa, "sa");
332093
- var F4 = 0, ta = null, G2 = null;
331985
+ var F4 = 0, ta2 = null, G2 = null;
332094
331986
  function x3(a2) {
332095
331987
  if (h3.onAbort) h3.onAbort(a2);
332096
331988
  a2 = "Aborted(" + a2 + ")";
@@ -333233,7 +333125,7 @@ var loadYoga = (() => {
333233
333125
  qa.unshift(h3.asm.F);
333234
333126
  F4--;
333235
333127
  h3.monitorRunDependencies && h3.monitorRunDependencies(F4);
333236
- 0 == F4 && (null !== ta && (clearInterval(ta), ta = null), G2 && (e4 = G2, G2 = null, e4()));
333128
+ 0 == F4 && (null !== ta2 && (clearInterval(ta2), ta2 = null), G2 && (e4 = G2, G2 = null, e4()));
333237
333129
  }
333238
333130
  __name(a2, "a");
333239
333131
  function b2(e4) {
@@ -344157,7 +344049,7 @@ __name(getPackageJson, "getPackageJson");
344157
344049
  // packages/cli/src/utils/version.ts
344158
344050
  async function getCliVersion() {
344159
344051
  const pkgJson = await getPackageJson();
344160
- return "0.1.8-alpha.9";
344052
+ return "0.1.8";
344161
344053
  }
344162
344054
  __name(getCliVersion, "getCliVersion");
344163
344055
 
@@ -348122,6 +348014,26 @@ import * as path83 from "node:path";
348122
348014
  import { fileURLToPath as fileURLToPath13, pathToFileURL as pathToFileURL2 } from "node:url";
348123
348015
  import { homedir as homedir18 } from "node:os";
348124
348016
 
348017
+ // packages/cli/src/i18n/languages.ts
348018
+ init_esbuild_shims();
348019
+ var SUPPORTED_LANGUAGES = [
348020
+ {
348021
+ code: "en",
348022
+ id: "en-US",
348023
+ fullName: "English"
348024
+ },
348025
+ {
348026
+ code: "zh",
348027
+ id: "zh-CN",
348028
+ fullName: "Chinese"
348029
+ }
348030
+ ];
348031
+ function getLanguageNameFromLocale(locale) {
348032
+ const lang = SUPPORTED_LANGUAGES.find((l3) => l3.code === locale);
348033
+ return lang?.fullName || "English";
348034
+ }
348035
+ __name(getLanguageNameFromLocale, "getLanguageNameFromLocale");
348036
+
348125
348037
  // import("./locales/**/*.js") in packages/cli/src/i18n/index.ts
348126
348038
  var globImport_locales_js = __glob({
348127
348039
  "./locales/en.js": () => Promise.resolve().then(() => (init_en3(), en_exports)),
@@ -348249,9 +348161,20 @@ function getCurrentLanguage() {
348249
348161
  __name(getCurrentLanguage, "getCurrentLanguage");
348250
348162
  function t4(key, params) {
348251
348163
  const translation = translations[key] ?? key;
348164
+ if (Array.isArray(translation)) {
348165
+ return key;
348166
+ }
348252
348167
  return interpolate(translation, params);
348253
348168
  }
348254
348169
  __name(t4, "t");
348170
+ function ta(key) {
348171
+ const translation = translations[key];
348172
+ if (Array.isArray(translation)) {
348173
+ return translation;
348174
+ }
348175
+ return [];
348176
+ }
348177
+ __name(ta, "ta");
348255
348178
  async function initializeI18n(lang) {
348256
348179
  await setLanguageAsync(lang ?? "auto");
348257
348180
  }
@@ -351625,10 +351548,346 @@ function validateTheme(settings) {
351625
351548
  }
351626
351549
  __name(validateTheme, "validateTheme");
351627
351550
 
351551
+ // packages/cli/src/ui/commands/languageCommand.ts
351552
+ init_esbuild_shims();
351553
+
351554
+ // packages/cli/src/ui/commands/types.ts
351555
+ init_esbuild_shims();
351556
+
351557
+ // packages/cli/src/ui/commands/languageCommand.ts
351558
+ init_settings();
351559
+ init_core5();
351560
+ import * as fs80 from "node:fs";
351561
+ import * as path86 from "node:path";
351562
+ var LLM_OUTPUT_LANGUAGE_RULE_FILENAME = "output-language.md";
351563
+ var LLM_OUTPUT_LANGUAGE_MARKER_PREFIX = "qwen-code:llm-output-language:";
351564
+ function parseUiLanguageArg(input) {
351565
+ const lowered = input.trim().toLowerCase();
351566
+ if (!lowered) return null;
351567
+ for (const lang of SUPPORTED_LANGUAGES) {
351568
+ if (lowered === lang.code || lowered === lang.id.toLowerCase() || lowered === lang.fullName.toLowerCase()) {
351569
+ return lang.code;
351570
+ }
351571
+ }
351572
+ return null;
351573
+ }
351574
+ __name(parseUiLanguageArg, "parseUiLanguageArg");
351575
+ function formatUiLanguageDisplay(lang) {
351576
+ const option2 = SUPPORTED_LANGUAGES.find((o3) => o3.code === lang);
351577
+ return option2 ? `${option2.fullName}\uFF08${option2.id}\uFF09` : lang;
351578
+ }
351579
+ __name(formatUiLanguageDisplay, "formatUiLanguageDisplay");
351580
+ function sanitizeLanguageForMarker(language) {
351581
+ return language.replace(/[\r\n]/g, " ").replace(/--!?>/g, "").replace(/--/g, "");
351582
+ }
351583
+ __name(sanitizeLanguageForMarker, "sanitizeLanguageForMarker");
351584
+ function generateLlmOutputLanguageRule(language) {
351585
+ const markerLanguage = sanitizeLanguageForMarker(language);
351586
+ return `# Output language preference: ${language}
351587
+ <!-- ${LLM_OUTPUT_LANGUAGE_MARKER_PREFIX} ${markerLanguage} -->
351588
+
351589
+ ## Goal
351590
+ Prefer responding in **${language}** for normal assistant messages and explanations.
351591
+
351592
+ ## Keep technical artifacts unchanged
351593
+ Do **not** translate or rewrite:
351594
+ - Code blocks, CLI commands, file paths, stack traces, logs, JSON keys, identifiers
351595
+ - Exact quoted text from the user (keep quotes verbatim)
351596
+
351597
+ ## When a conflict exists
351598
+ If higher-priority instructions (system/developer) require a different behavior, follow them.
351599
+
351600
+ ## Tool / system outputs
351601
+ Raw tool/system outputs may contain fixed-format English. Preserve them verbatim, and if needed, add a short **${language}** explanation below.
351602
+ `;
351603
+ }
351604
+ __name(generateLlmOutputLanguageRule, "generateLlmOutputLanguageRule");
351605
+ function getLlmOutputLanguageRulePath() {
351606
+ return path86.join(
351607
+ Storage.getGlobalQwenDir(),
351608
+ LLM_OUTPUT_LANGUAGE_RULE_FILENAME
351609
+ );
351610
+ }
351611
+ __name(getLlmOutputLanguageRulePath, "getLlmOutputLanguageRulePath");
351612
+ function normalizeLanguageName(language) {
351613
+ const lowered = language.toLowerCase();
351614
+ const fullName = getLanguageNameFromLocale(lowered);
351615
+ if (fullName !== "English" || lowered === "en") {
351616
+ return fullName;
351617
+ }
351618
+ return language;
351619
+ }
351620
+ __name(normalizeLanguageName, "normalizeLanguageName");
351621
+ function extractLlmOutputLanguageFromRuleFileContent(content) {
351622
+ const markerMatch = content.match(
351623
+ new RegExp(
351624
+ String.raw`<!--\s*${LLM_OUTPUT_LANGUAGE_MARKER_PREFIX}\s*(.*?)\s*-->`,
351625
+ "i"
351626
+ )
351627
+ );
351628
+ if (markerMatch?.[1]) {
351629
+ const lang = markerMatch[1].trim();
351630
+ if (lang) return lang;
351631
+ }
351632
+ const headingMatch = content.match(
351633
+ /^#.*?CRITICAL:\s*(.*?)\s+Output Language Rule\b/im
351634
+ );
351635
+ if (headingMatch?.[1]) {
351636
+ const lang = headingMatch[1].trim();
351637
+ if (lang) return lang;
351638
+ }
351639
+ return null;
351640
+ }
351641
+ __name(extractLlmOutputLanguageFromRuleFileContent, "extractLlmOutputLanguageFromRuleFileContent");
351642
+ function initializeLlmOutputLanguage() {
351643
+ const filePath = getLlmOutputLanguageRulePath();
351644
+ if (fs80.existsSync(filePath)) {
351645
+ return;
351646
+ }
351647
+ const detectedLocale = detectSystemLanguage();
351648
+ const languageName = getLanguageNameFromLocale(detectedLocale);
351649
+ const content = generateLlmOutputLanguageRule(languageName);
351650
+ const dir = path86.dirname(filePath);
351651
+ fs80.mkdirSync(dir, { recursive: true });
351652
+ fs80.writeFileSync(filePath, content, "utf-8");
351653
+ }
351654
+ __name(initializeLlmOutputLanguage, "initializeLlmOutputLanguage");
351655
+ function getCurrentLlmOutputLanguage() {
351656
+ const filePath = getLlmOutputLanguageRulePath();
351657
+ if (fs80.existsSync(filePath)) {
351658
+ try {
351659
+ const content = fs80.readFileSync(filePath, "utf-8");
351660
+ return extractLlmOutputLanguageFromRuleFileContent(content);
351661
+ } catch {
351662
+ }
351663
+ }
351664
+ return null;
351665
+ }
351666
+ __name(getCurrentLlmOutputLanguage, "getCurrentLlmOutputLanguage");
351667
+ async function setUiLanguage(context2, lang) {
351668
+ const { services } = context2;
351669
+ const { settings } = services;
351670
+ if (!services.config) {
351671
+ return {
351672
+ type: "message",
351673
+ messageType: "error",
351674
+ content: t4("Configuration not available.")
351675
+ };
351676
+ }
351677
+ await setLanguageAsync(lang);
351678
+ if (settings && typeof settings.setValue === "function") {
351679
+ try {
351680
+ settings.setValue("User" /* User */, "general.language", lang);
351681
+ } catch (error2) {
351682
+ console.warn("Failed to save language setting:", error2);
351683
+ }
351684
+ }
351685
+ context2.ui.reloadCommands();
351686
+ return {
351687
+ type: "message",
351688
+ messageType: "info",
351689
+ content: t4("UI language changed to {{lang}}", {
351690
+ lang: formatUiLanguageDisplay(lang)
351691
+ })
351692
+ };
351693
+ }
351694
+ __name(setUiLanguage, "setUiLanguage");
351695
+ function generateLlmOutputLanguageRuleFile(language) {
351696
+ try {
351697
+ const filePath = getLlmOutputLanguageRulePath();
351698
+ const normalizedLanguage = normalizeLanguageName(language);
351699
+ const content = generateLlmOutputLanguageRule(normalizedLanguage);
351700
+ const dir = path86.dirname(filePath);
351701
+ fs80.mkdirSync(dir, { recursive: true });
351702
+ fs80.writeFileSync(filePath, content, "utf-8");
351703
+ return Promise.resolve({
351704
+ type: "message",
351705
+ messageType: "info",
351706
+ content: [
351707
+ t4("LLM output language rule file generated at {{path}}", {
351708
+ path: filePath
351709
+ }),
351710
+ "",
351711
+ t4("Please restart the application for the changes to take effect.")
351712
+ ].join("\n")
351713
+ });
351714
+ } catch (error2) {
351715
+ return Promise.resolve({
351716
+ type: "message",
351717
+ messageType: "error",
351718
+ content: t4(
351719
+ "Failed to generate LLM output language rule file: {{error}}",
351720
+ {
351721
+ error: error2 instanceof Error ? error2.message : String(error2)
351722
+ }
351723
+ )
351724
+ });
351725
+ }
351726
+ }
351727
+ __name(generateLlmOutputLanguageRuleFile, "generateLlmOutputLanguageRuleFile");
351728
+ var languageCommand = {
351729
+ name: "language",
351730
+ get description() {
351731
+ return t4("View or change the language setting");
351732
+ },
351733
+ kind: "built-in" /* BUILT_IN */,
351734
+ action: /* @__PURE__ */ __name(async (context2, args) => {
351735
+ const { services } = context2;
351736
+ if (!services.config) {
351737
+ return {
351738
+ type: "message",
351739
+ messageType: "error",
351740
+ content: t4("Configuration not available.")
351741
+ };
351742
+ }
351743
+ const trimmedArgs = args.trim();
351744
+ const parts = trimmedArgs.split(/\s+/);
351745
+ const firstArg = parts[0].toLowerCase();
351746
+ const subArgs = parts.slice(1).join(" ");
351747
+ if (firstArg === "ui" || firstArg === "output") {
351748
+ const subCommand = languageCommand.subCommands?.find(
351749
+ (s5) => s5.name === firstArg
351750
+ );
351751
+ if (subCommand?.action) {
351752
+ return subCommand.action(
351753
+ context2,
351754
+ subArgs
351755
+ );
351756
+ }
351757
+ }
351758
+ if (!trimmedArgs) {
351759
+ const currentUiLang = getCurrentLanguage();
351760
+ const currentLlmLang = getCurrentLlmOutputLanguage();
351761
+ const message = [
351762
+ t4("Current UI language: {{lang}}", {
351763
+ lang: formatUiLanguageDisplay(currentUiLang)
351764
+ }),
351765
+ currentLlmLang ? t4("Current LLM output language: {{lang}}", { lang: currentLlmLang }) : t4("LLM output language not set"),
351766
+ "",
351767
+ t4("Available subcommands:"),
351768
+ ` /language ui [${SUPPORTED_LANGUAGES.map((o3) => o3.id).join("|")}] - ${t4("Set UI language")}`,
351769
+ ` /language output <language> - ${t4("Set LLM output language")}`
351770
+ ].join("\n");
351771
+ return {
351772
+ type: "message",
351773
+ messageType: "info",
351774
+ content: message
351775
+ };
351776
+ }
351777
+ const targetLang = parseUiLanguageArg(trimmedArgs);
351778
+ if (targetLang) {
351779
+ return setUiLanguage(context2, targetLang);
351780
+ }
351781
+ return {
351782
+ type: "message",
351783
+ messageType: "error",
351784
+ content: [
351785
+ t4("Invalid command. Available subcommands:"),
351786
+ ` - /language ui [${SUPPORTED_LANGUAGES.map((o3) => o3.id).join("|")}] - ${t4("Set UI language")}`,
351787
+ " - /language output <language> - " + t4("Set LLM output language")
351788
+ ].join("\n")
351789
+ };
351790
+ }, "action"),
351791
+ subCommands: [
351792
+ {
351793
+ name: "ui",
351794
+ get description() {
351795
+ return t4("Set UI language");
351796
+ },
351797
+ kind: "built-in" /* BUILT_IN */,
351798
+ action: /* @__PURE__ */ __name(async (context2, args) => {
351799
+ const trimmedArgs = args.trim();
351800
+ if (!trimmedArgs) {
351801
+ return {
351802
+ type: "message",
351803
+ messageType: "info",
351804
+ content: [
351805
+ t4("Set UI language"),
351806
+ "",
351807
+ t4("Usage: /language ui [{{options}}]", {
351808
+ options: SUPPORTED_LANGUAGES.map((o3) => o3.id).join("|")
351809
+ }),
351810
+ "",
351811
+ t4("Available options:"),
351812
+ ...SUPPORTED_LANGUAGES.map(
351813
+ (o3) => ` - ${o3.id}: ${t4(o3.fullName)}`
351814
+ ),
351815
+ "",
351816
+ t4(
351817
+ "To request additional UI language packs, please open an issue on GitHub."
351818
+ )
351819
+ ].join("\n")
351820
+ };
351821
+ }
351822
+ const targetLang = parseUiLanguageArg(trimmedArgs);
351823
+ if (!targetLang) {
351824
+ return {
351825
+ type: "message",
351826
+ messageType: "error",
351827
+ content: t4("Invalid language. Available: {{options}}", {
351828
+ options: SUPPORTED_LANGUAGES.map((o3) => o3.id).join(",")
351829
+ })
351830
+ };
351831
+ }
351832
+ return setUiLanguage(context2, targetLang);
351833
+ }, "action"),
351834
+ subCommands: SUPPORTED_LANGUAGES.map(createUiLanguageSubCommand)
351835
+ },
351836
+ {
351837
+ name: "output",
351838
+ get description() {
351839
+ return t4("Set LLM output language");
351840
+ },
351841
+ kind: "built-in" /* BUILT_IN */,
351842
+ action: /* @__PURE__ */ __name(async (context2, args) => {
351843
+ const trimmedArgs = args.trim();
351844
+ if (!trimmedArgs) {
351845
+ return {
351846
+ type: "message",
351847
+ messageType: "info",
351848
+ content: [
351849
+ t4("Set LLM output language"),
351850
+ "",
351851
+ t4("Usage: /language output <language>"),
351852
+ ` ${t4("Example: /language output \u4E2D\u6587")}`,
351853
+ ` ${t4("Example: /language output English")}`,
351854
+ ` ${t4("Example: /language output \u65E5\u672C\u8A9E")}`
351855
+ ].join("\n")
351856
+ };
351857
+ }
351858
+ return generateLlmOutputLanguageRuleFile(trimmedArgs);
351859
+ }, "action")
351860
+ }
351861
+ ]
351862
+ };
351863
+ function createUiLanguageSubCommand(option2) {
351864
+ return {
351865
+ name: option2.id,
351866
+ get description() {
351867
+ return t4("Set UI language to {{name}}", { name: option2.fullName });
351868
+ },
351869
+ kind: "built-in" /* BUILT_IN */,
351870
+ action: /* @__PURE__ */ __name(async (context2, args) => {
351871
+ if (args.trim().length > 0) {
351872
+ return {
351873
+ type: "message",
351874
+ messageType: "error",
351875
+ content: t4(
351876
+ "Language subcommands do not accept additional arguments."
351877
+ )
351878
+ };
351879
+ }
351880
+ return setUiLanguage(context2, option2.code);
351881
+ }, "action")
351882
+ };
351883
+ }
351884
+ __name(createUiLanguageSubCommand, "createUiLanguageSubCommand");
351885
+
351628
351886
  // packages/cli/src/core/initializer.ts
351629
351887
  async function initializeApp(config2, settings) {
351630
351888
  const languageSetting = process.env["RDMind_LANG"] || settings.merged.general?.language || "auto";
351631
351889
  await initializeI18n(languageSetting);
351890
+ initializeLlmOutputLanguage();
351632
351891
  const authType = settings.merged.security?.auth?.selectedType;
351633
351892
  const authError = await performInitialAuth(config2, authType);
351634
351893
  if (authError) {
@@ -351761,6 +352020,108 @@ import { randomUUID as randomUUID7 } from "node:crypto";
351761
352020
  init_esbuild_shims();
351762
352021
  init_core5();
351763
352022
 
352023
+ // packages/cli/src/ui/utils/computeStats.ts
352024
+ init_esbuild_shims();
352025
+ function calculateErrorRate(metrics2) {
352026
+ if (metrics2.api.totalRequests === 0) {
352027
+ return 0;
352028
+ }
352029
+ return metrics2.api.totalErrors / metrics2.api.totalRequests * 100;
352030
+ }
352031
+ __name(calculateErrorRate, "calculateErrorRate");
352032
+ function calculateAverageLatency(metrics2) {
352033
+ if (metrics2.api.totalRequests === 0) {
352034
+ return 0;
352035
+ }
352036
+ return metrics2.api.totalLatencyMs / metrics2.api.totalRequests;
352037
+ }
352038
+ __name(calculateAverageLatency, "calculateAverageLatency");
352039
+ function calculateCacheHitRate(metrics2) {
352040
+ if (metrics2.tokens.prompt === 0) {
352041
+ return 0;
352042
+ }
352043
+ return metrics2.tokens.cached / metrics2.tokens.prompt * 100;
352044
+ }
352045
+ __name(calculateCacheHitRate, "calculateCacheHitRate");
352046
+ var computeSessionStats = /* @__PURE__ */ __name((metrics2) => {
352047
+ const { models, tools, files } = metrics2;
352048
+ const totalApiTime = Object.values(models).reduce(
352049
+ (acc, model) => acc + model.api.totalLatencyMs,
352050
+ 0
352051
+ );
352052
+ const totalToolTime = tools.totalDurationMs;
352053
+ const agentActiveTime = totalApiTime + totalToolTime;
352054
+ const apiTimePercent = agentActiveTime > 0 ? totalApiTime / agentActiveTime * 100 : 0;
352055
+ const toolTimePercent = agentActiveTime > 0 ? totalToolTime / agentActiveTime * 100 : 0;
352056
+ const totalCachedTokens = Object.values(models).reduce(
352057
+ (acc, model) => acc + model.tokens.cached,
352058
+ 0
352059
+ );
352060
+ const totalPromptTokens = Object.values(models).reduce(
352061
+ (acc, model) => acc + model.tokens.prompt,
352062
+ 0
352063
+ );
352064
+ const cacheEfficiency = totalPromptTokens > 0 ? totalCachedTokens / totalPromptTokens * 100 : 0;
352065
+ const totalDecisions = tools.totalDecisions.accept + tools.totalDecisions.reject + tools.totalDecisions.modify;
352066
+ const successRate = tools.totalCalls > 0 ? tools.totalSuccess / tools.totalCalls * 100 : 0;
352067
+ const agreementRate = totalDecisions > 0 ? tools.totalDecisions.accept / totalDecisions * 100 : 0;
352068
+ return {
352069
+ totalApiTime,
352070
+ totalToolTime,
352071
+ agentActiveTime,
352072
+ apiTimePercent,
352073
+ toolTimePercent,
352074
+ cacheEfficiency,
352075
+ totalDecisions,
352076
+ successRate,
352077
+ agreementRate,
352078
+ totalCachedTokens,
352079
+ totalPromptTokens,
352080
+ totalLinesAdded: files.totalLinesAdded,
352081
+ totalLinesRemoved: files.totalLinesRemoved
352082
+ };
352083
+ }, "computeSessionStats");
352084
+
352085
+ // packages/cli/src/nonInteractiveCliCommands.ts
352086
+ init_esbuild_shims();
352087
+
352088
+ // packages/cli/src/utils/commands.ts
352089
+ init_esbuild_shims();
352090
+ var parseSlashCommand = /* @__PURE__ */ __name((query, commands) => {
352091
+ const trimmed2 = query.trim();
352092
+ const parts = trimmed2.substring(1).trim().split(/\s+/);
352093
+ const commandPath = parts.filter((p2) => p2);
352094
+ let currentCommands = commands;
352095
+ let commandToExecute;
352096
+ let pathIndex = 0;
352097
+ const canonicalPath = [];
352098
+ for (const part of commandPath) {
352099
+ let foundCommand = currentCommands.find((cmd) => cmd.name === part);
352100
+ if (!foundCommand) {
352101
+ foundCommand = currentCommands.find(
352102
+ (cmd) => cmd.altNames?.includes(part)
352103
+ );
352104
+ }
352105
+ if (foundCommand) {
352106
+ commandToExecute = foundCommand;
352107
+ canonicalPath.push(foundCommand.name);
352108
+ pathIndex++;
352109
+ if (foundCommand.subCommands) {
352110
+ currentCommands = foundCommand.subCommands;
352111
+ } else {
352112
+ break;
352113
+ }
352114
+ } else {
352115
+ break;
352116
+ }
352117
+ }
352118
+ const args = parts.slice(pathIndex).join(" ");
352119
+ return { commandToExecute, args, canonicalPath };
352120
+ }, "parseSlashCommand");
352121
+
352122
+ // packages/cli/src/nonInteractiveCliCommands.ts
352123
+ init_core5();
352124
+
351764
352125
  // packages/cli/src/services/CommandService.ts
351765
352126
  init_esbuild_shims();
351766
352127
  var CommandService = class _CommandService {
@@ -351844,9 +352205,6 @@ init_esbuild_shims();
351844
352205
  // packages/cli/src/ui/commands/aboutCommand.ts
351845
352206
  init_esbuild_shims();
351846
352207
 
351847
- // packages/cli/src/ui/commands/types.ts
351848
- init_esbuild_shims();
351849
-
351850
352208
  // packages/cli/src/ui/types.ts
351851
352209
  init_esbuild_shims();
351852
352210
  var import_react26 = __toESM(require_react(), 1);
@@ -351930,7 +352288,7 @@ var formatDuration = /* @__PURE__ */ __name((milliseconds) => {
351930
352288
 
351931
352289
  // packages/cli/src/generated/git-commit.ts
351932
352290
  init_esbuild_shims();
351933
- var GIT_COMMIT_INFO2 = "f23f6fb2";
352291
+ var GIT_COMMIT_INFO2 = "8f0613d7";
351934
352292
 
351935
352293
  // packages/cli/src/utils/systemInfo.ts
351936
352294
  async function getNpmVersion() {
@@ -352345,7 +352703,8 @@ var compressCommand = {
352345
352703
  kind: "built-in" /* BUILT_IN */,
352346
352704
  action: /* @__PURE__ */ __name(async (context2) => {
352347
352705
  const { ui: ui2 } = context2;
352348
- if (ui2.pendingItem) {
352706
+ const executionMode = context2.executionMode ?? "interactive";
352707
+ if (executionMode === "interactive" && ui2.pendingItem) {
352349
352708
  ui2.addItem(
352350
352709
  {
352351
352710
  type: "error" /* ERROR */,
@@ -352364,11 +352723,72 @@ var compressCommand = {
352364
352723
  compressionStatus: null
352365
352724
  }
352366
352725
  };
352367
- try {
352368
- ui2.setPendingItem(pendingMessage);
352726
+ const config2 = context2.services.config;
352727
+ const geminiClient = config2?.getGeminiClient();
352728
+ if (!config2 || !geminiClient) {
352729
+ return {
352730
+ type: "message",
352731
+ messageType: "error",
352732
+ content: t4("Config not loaded.")
352733
+ };
352734
+ }
352735
+ const doCompress = /* @__PURE__ */ __name(async () => {
352369
352736
  const promptId = `compress-${Date.now()}`;
352370
- const compressed = await context2.services.config?.getGeminiClient()?.tryCompressChat(promptId, true);
352371
- if (compressed) {
352737
+ return await geminiClient.tryCompressChat(promptId, true);
352738
+ }, "doCompress");
352739
+ if (executionMode === "acp") {
352740
+ const messages = /* @__PURE__ */ __name(async function* () {
352741
+ try {
352742
+ yield {
352743
+ messageType: "info",
352744
+ content: "Compressing context..."
352745
+ };
352746
+ const compressed = await doCompress();
352747
+ if (!compressed) {
352748
+ yield {
352749
+ messageType: "error",
352750
+ content: t4("Failed to compress chat history.")
352751
+ };
352752
+ return;
352753
+ }
352754
+ yield {
352755
+ messageType: "info",
352756
+ content: `Context compressed (${compressed.originalTokenCount} -> ${compressed.newTokenCount}).`
352757
+ };
352758
+ } catch (e4) {
352759
+ yield {
352760
+ messageType: "error",
352761
+ content: t4("Failed to compress chat history: {{error}}", {
352762
+ error: e4 instanceof Error ? e4.message : String(e4)
352763
+ })
352764
+ };
352765
+ }
352766
+ }, "messages");
352767
+ return { type: "stream_messages", messages: messages() };
352768
+ }
352769
+ try {
352770
+ if (executionMode === "interactive") {
352771
+ ui2.setPendingItem(pendingMessage);
352772
+ }
352773
+ const compressed = await doCompress();
352774
+ if (!compressed) {
352775
+ if (executionMode === "interactive") {
352776
+ ui2.addItem(
352777
+ {
352778
+ type: "error" /* ERROR */,
352779
+ text: t4("Failed to compress chat history.")
352780
+ },
352781
+ Date.now()
352782
+ );
352783
+ return;
352784
+ }
352785
+ return {
352786
+ type: "message",
352787
+ messageType: "error",
352788
+ content: t4("Failed to compress chat history.")
352789
+ };
352790
+ }
352791
+ if (executionMode === "interactive") {
352372
352792
  ui2.addItem(
352373
352793
  {
352374
352794
  type: "compression" /* COMPRESSION */,
@@ -352381,27 +352801,37 @@ var compressCommand = {
352381
352801
  },
352382
352802
  Date.now()
352383
352803
  );
352384
- } else {
352804
+ return;
352805
+ }
352806
+ return {
352807
+ type: "message",
352808
+ messageType: "info",
352809
+ content: `Context compressed (${compressed.originalTokenCount} -> ${compressed.newTokenCount}).`
352810
+ };
352811
+ } catch (e4) {
352812
+ if (executionMode === "interactive") {
352385
352813
  ui2.addItem(
352386
352814
  {
352387
352815
  type: "error" /* ERROR */,
352388
- text: t4("Failed to compress chat history.")
352816
+ text: t4("Failed to compress chat history: {{error}}", {
352817
+ error: e4 instanceof Error ? e4.message : String(e4)
352818
+ })
352389
352819
  },
352390
352820
  Date.now()
352391
352821
  );
352822
+ return;
352392
352823
  }
352393
- } catch (e4) {
352394
- ui2.addItem(
352395
- {
352396
- type: "error" /* ERROR */,
352397
- text: t4("Failed to compress chat history: {{error}}", {
352398
- error: e4 instanceof Error ? e4.message : String(e4)
352399
- })
352400
- },
352401
- Date.now()
352402
- );
352824
+ return {
352825
+ type: "message",
352826
+ messageType: "error",
352827
+ content: t4("Failed to compress chat history: {{error}}", {
352828
+ error: e4 instanceof Error ? e4.message : String(e4)
352829
+ })
352830
+ };
352403
352831
  } finally {
352404
- ui2.setPendingItem(null);
352832
+ if (executionMode === "interactive") {
352833
+ ui2.setPendingItem(null);
352834
+ }
352405
352835
  }
352406
352836
  }, "action")
352407
352837
  };
@@ -352455,11 +352885,11 @@ var copyCommand = {
352455
352885
 
352456
352886
  // packages/cli/src/ui/commands/createCommand.ts
352457
352887
  init_esbuild_shims();
352458
- import * as fs80 from "fs";
352459
- import * as path86 from "path";
352888
+ import * as fs81 from "fs";
352889
+ import * as path87 from "path";
352460
352890
  import { fileURLToPath as fileURLToPath14 } from "url";
352461
352891
  var __filename6 = fileURLToPath14(import.meta.url);
352462
- var __dirname9 = path86.dirname(__filename6);
352892
+ var __dirname9 = path87.dirname(__filename6);
352463
352893
  function validateProjectName(name3) {
352464
352894
  return /^[a-z][a-z0-9-]*[a-z0-9]$|^[a-z]$/.test(name3);
352465
352895
  }
@@ -352473,20 +352903,20 @@ function getIdlExamplePath() {
352473
352903
  // 1. npm 发布:
352474
352904
  // __dirname 就是 node_modules/@rdmind/rdmind/
352475
352905
  // 模板在 node_modules/@rdmind/rdmind/templates/
352476
- path86.join(__dirname9, "templates", "idl-template/wiki/example"),
352906
+ path87.join(__dirname9, "templates", "idl-template/wiki/example"),
352477
352907
  // 2. 开发环境:相对于工作区根目录的idl-template
352478
- path86.join(
352908
+ path87.join(
352479
352909
  __dirname9,
352480
352910
  "..",
352481
352911
  "packages/cli/templates/idl-template/wiki/example"
352482
352912
  )
352483
352913
  ];
352484
352914
  for (const templatePath of possiblePaths) {
352485
- if (fs80.existsSync(templatePath)) {
352915
+ if (fs81.existsSync(templatePath)) {
352486
352916
  return templatePath;
352487
352917
  }
352488
352918
  }
352489
- return path86.join(process.cwd(), "idl-template");
352919
+ return path87.join(process.cwd(), "idl-template");
352490
352920
  }
352491
352921
  __name(getIdlExamplePath, "getIdlExamplePath");
352492
352922
  function getTemplatePath() {
@@ -352494,16 +352924,16 @@ function getTemplatePath() {
352494
352924
  // 1. npm 安装
352495
352925
  // __dirname 就是 node_modules/@rdmind/rdmind/
352496
352926
  // 模板在 node_modules/@rdmind/rdmind/template/
352497
- path86.join(__dirname9, "template"),
352927
+ path87.join(__dirname9, "template"),
352498
352928
  // 2. 开发环境:
352499
- path86.join(__dirname9, "..", "packages/cli/template")
352929
+ path87.join(__dirname9, "..", "packages/cli/template")
352500
352930
  ];
352501
352931
  for (const templatePath of possiblePaths) {
352502
- if (fs80.existsSync(templatePath)) {
352932
+ if (fs81.existsSync(templatePath)) {
352503
352933
  return templatePath;
352504
352934
  }
352505
352935
  }
352506
- return path86.join(process.cwd(), "sns-demo");
352936
+ return path87.join(process.cwd(), "sns-demo");
352507
352937
  }
352508
352938
  __name(getTemplatePath, "getTemplatePath");
352509
352939
  function replaceIdlProjectNames(content, oldName, newName) {
@@ -352547,18 +352977,18 @@ function replaceProjectNames(content, oldName, newName, businessModule) {
352547
352977
  }
352548
352978
  __name(replaceProjectNames, "replaceProjectNames");
352549
352979
  async function copyAndReplaceFile(srcFile, destFile, oldName, newName, businessModule, isIdlProject = false) {
352550
- const destDir = path86.dirname(destFile);
352551
- if (!fs80.existsSync(destDir)) {
352552
- fs80.mkdirSync(destDir, { recursive: true });
352980
+ const destDir = path87.dirname(destFile);
352981
+ if (!fs81.existsSync(destDir)) {
352982
+ fs81.mkdirSync(destDir, { recursive: true });
352553
352983
  }
352554
- const content = fs80.readFileSync(srcFile, "utf8");
352984
+ const content = fs81.readFileSync(srcFile, "utf8");
352555
352985
  let newContent;
352556
352986
  if (isIdlProject) {
352557
352987
  newContent = replaceIdlProjectNames(content, oldName, newName);
352558
352988
  } else {
352559
352989
  newContent = replaceProjectNames(content, oldName, newName, businessModule);
352560
352990
  }
352561
- fs80.writeFileSync(destFile, newContent, "utf8");
352991
+ fs81.writeFileSync(destFile, newContent, "utf8");
352562
352992
  }
352563
352993
  __name(copyAndReplaceFile, "copyAndReplaceFile");
352564
352994
  function shouldSkipItem(itemName) {
@@ -352596,12 +353026,12 @@ function shouldSkipItem(itemName) {
352596
353026
  }
352597
353027
  __name(shouldSkipItem, "shouldSkipItem");
352598
353028
  async function copyAndReplaceDir(srcDir, destDir, oldName, newName, businessModule, isIdlProject = false) {
352599
- if (!fs80.existsSync(destDir)) {
352600
- fs80.mkdirSync(destDir, { recursive: true });
353029
+ if (!fs81.existsSync(destDir)) {
353030
+ fs81.mkdirSync(destDir, { recursive: true });
352601
353031
  }
352602
- const items = fs80.readdirSync(srcDir);
353032
+ const items = fs81.readdirSync(srcDir);
352603
353033
  for (const item of items) {
352604
- const srcPath = path86.join(srcDir, item);
353034
+ const srcPath = path87.join(srcDir, item);
352605
353035
  if (shouldSkipItem(item)) {
352606
353036
  continue;
352607
353037
  }
@@ -352614,7 +353044,7 @@ async function copyAndReplaceDir(srcDir, destDir, oldName, newName, businessModu
352614
353044
  const pathParts = packageDirName.split("-");
352615
353045
  const currentDestPath = destDir;
352616
353046
  for (let i3 = 0; i3 < pathParts.length; i3++) {
352617
- const partPath = path86.join(
353047
+ const partPath = path87.join(
352618
353048
  currentDestPath,
352619
353049
  ...pathParts.slice(0, i3 + 1)
352620
353050
  );
@@ -352628,8 +353058,8 @@ async function copyAndReplaceDir(srcDir, destDir, oldName, newName, businessModu
352628
353058
  isIdlProject
352629
353059
  );
352630
353060
  } else {
352631
- if (!fs80.existsSync(partPath)) {
352632
- fs80.mkdirSync(partPath, { recursive: true });
353061
+ if (!fs81.existsSync(partPath)) {
353062
+ fs81.mkdirSync(partPath, { recursive: true });
352633
353063
  }
352634
353064
  }
352635
353065
  }
@@ -352646,8 +353076,8 @@ async function copyAndReplaceDir(srcDir, destDir, oldName, newName, businessModu
352646
353076
  destItemName = item.replace(/sns-demo/g, newName);
352647
353077
  }
352648
353078
  }
352649
- const destPath = path86.join(destDir, destItemName);
352650
- const stats = fs80.statSync(srcPath);
353079
+ const destPath = path87.join(destDir, destItemName);
353080
+ const stats = fs81.statSync(srcPath);
352651
353081
  if (stats.isDirectory()) {
352652
353082
  await copyAndReplaceDir(
352653
353083
  srcPath,
@@ -352672,7 +353102,7 @@ async function copyAndReplaceDir(srcDir, destDir, oldName, newName, businessModu
352672
353102
  __name(copyAndReplaceDir, "copyAndReplaceDir");
352673
353103
  async function createJavaProject(context2, projectName, businessModule) {
352674
353104
  const templatePath = getTemplatePath();
352675
- if (!fs80.existsSync(templatePath)) {
353105
+ if (!fs81.existsSync(templatePath)) {
352676
353106
  context2.ui.addItem(
352677
353107
  {
352678
353108
  type: "error" /* ERROR */,
@@ -352683,8 +353113,8 @@ async function createJavaProject(context2, projectName, businessModule) {
352683
353113
  );
352684
353114
  return;
352685
353115
  }
352686
- const targetPath = path86.join(process.cwd(), projectName);
352687
- if (fs80.existsSync(targetPath)) {
353116
+ const targetPath = path87.join(process.cwd(), projectName);
353117
+ if (fs81.existsSync(targetPath)) {
352688
353118
  context2.ui.addItem(
352689
353119
  {
352690
353120
  type: "error" /* ERROR */,
@@ -352733,9 +353163,9 @@ ${projectName}/
352733
353163
  Date.now()
352734
353164
  );
352735
353165
  } catch (error2) {
352736
- if (fs80.existsSync(targetPath)) {
353166
+ if (fs81.existsSync(targetPath)) {
352737
353167
  try {
352738
- fs80.rmSync(targetPath, { recursive: true, force: true });
353168
+ fs81.rmSync(targetPath, { recursive: true, force: true });
352739
353169
  } catch (cleanupError) {
352740
353170
  console.warn(
352741
353171
  "Warning: Could not clean up failed project creation:",
@@ -352821,7 +353251,7 @@ var javaFlsCommand = {
352821
353251
  };
352822
353252
  async function createIdlProject(context2, projectName) {
352823
353253
  const templatePath = getIdlExamplePath();
352824
- if (!fs80.existsSync(templatePath)) {
353254
+ if (!fs81.existsSync(templatePath)) {
352825
353255
  context2.ui.addItem(
352826
353256
  {
352827
353257
  type: "error" /* ERROR */,
@@ -352833,8 +353263,8 @@ async function createIdlProject(context2, projectName) {
352833
353263
  return;
352834
353264
  }
352835
353265
  const projectDirectoryName = projectName;
352836
- const targetPath = path86.join(process.cwd(), projectDirectoryName);
352837
- if (fs80.existsSync(targetPath)) {
353266
+ const targetPath = path87.join(process.cwd(), projectDirectoryName);
353267
+ if (fs81.existsSync(targetPath)) {
352838
353268
  context2.ui.addItem(
352839
353269
  {
352840
353270
  type: "error" /* ERROR */,
@@ -352892,9 +353322,9 @@ ${projectDirectoryName}/
352892
353322
  Date.now()
352893
353323
  );
352894
353324
  } catch (error2) {
352895
- if (fs80.existsSync(targetPath)) {
353325
+ if (fs81.existsSync(targetPath)) {
352896
353326
  try {
352897
- fs80.rmSync(targetPath, { recursive: true, force: true });
353327
+ fs81.rmSync(targetPath, { recursive: true, force: true });
352898
353328
  } catch (cleanupError) {
352899
353329
  console.warn(
352900
353330
  "Warning: Could not clean up failed project creation:",
@@ -353085,8 +353515,8 @@ var docsCommand = {
353085
353515
  init_esbuild_shims();
353086
353516
  init_core5();
353087
353517
  import * as os32 from "node:os";
353088
- import * as path87 from "node:path";
353089
- import * as fs81 from "node:fs/promises";
353518
+ import * as path88 from "node:path";
353519
+ import * as fs82 from "node:fs/promises";
353090
353520
  function expandHomeDir(p2) {
353091
353521
  if (!p2) {
353092
353522
  return "";
@@ -353097,7 +353527,7 @@ function expandHomeDir(p2) {
353097
353527
  } else if (p2 === "~" || p2.startsWith("~/")) {
353098
353528
  expandedPath = os32.homedir() + p2.substring(1);
353099
353529
  }
353100
- return path87.normalize(expandedPath);
353530
+ return path88.normalize(expandedPath);
353101
353531
  }
353102
353532
  __name(expandHomeDir, "expandHomeDir");
353103
353533
  var directoryCommand = {
@@ -353405,25 +353835,25 @@ async function resolveCompletionPaths(partialPath, baseDir) {
353405
353835
  resolvedPath = baseDir;
353406
353836
  displayPrefix = "";
353407
353837
  } else if (partialPath.startsWith("~")) {
353408
- resolvedPath = path87.join(os32.homedir(), partialPath.slice(1));
353838
+ resolvedPath = path88.join(os32.homedir(), partialPath.slice(1));
353409
353839
  } else {
353410
- resolvedPath = path87.isAbsolute(partialPath) ? path87.resolve(partialPath || "/") : path87.resolve(baseDir, partialPath || ".");
353840
+ resolvedPath = path88.isAbsolute(partialPath) ? path88.resolve(partialPath || "/") : path88.resolve(baseDir, partialPath || ".");
353411
353841
  }
353412
353842
  let targetDir = resolvedPath;
353413
353843
  let filterPrefix = "";
353414
353844
  if (partialPath && !partialPath.endsWith("/") && !/^\.\/?$/.test(partialPath)) {
353415
- targetDir = path87.dirname(resolvedPath);
353416
- filterPrefix = path87.basename(resolvedPath);
353845
+ targetDir = path88.dirname(resolvedPath);
353846
+ filterPrefix = path88.basename(resolvedPath);
353417
353847
  }
353418
- const entries = await fs81.readdir(targetDir, { withFileTypes: true });
353848
+ const entries = await fs82.readdir(targetDir, { withFileTypes: true });
353419
353849
  return entries.filter((entry) => entry.isDirectory()).filter((entry) => !filterPrefix || entry.name.startsWith(filterPrefix)).map((entry) => {
353420
353850
  let completionPath;
353421
353851
  if (partialPath.endsWith("/")) {
353422
- completionPath = path87.posix.join(displayPrefix, entry.name) + "/";
353852
+ completionPath = path88.posix.join(displayPrefix, entry.name) + "/";
353423
353853
  } else {
353424
- const prefixDir = displayPrefix.includes("/") ? path87.posix.dirname(displayPrefix) : "";
353854
+ const prefixDir = displayPrefix.includes("/") ? path88.posix.dirname(displayPrefix) : "";
353425
353855
  if (prefixDir && prefixDir !== ".") {
353426
- completionPath = path87.posix.join(prefixDir, entry.name) + "/";
353856
+ completionPath = path88.posix.join(prefixDir, entry.name) + "/";
353427
353857
  } else {
353428
353858
  completionPath = entry.name + "/";
353429
353859
  if (displayPrefix && displayPrefix !== "." && !displayPrefix.includes("/")) {
@@ -353620,7 +354050,7 @@ var helpCommand = {
353620
354050
  init_esbuild_shims();
353621
354051
  init_core5();
353622
354052
  init_core5();
353623
- import path88 from "node:path";
354053
+ import path89 from "node:path";
353624
354054
  init_settings();
353625
354055
  function getIdeStatusMessage(ideClient) {
353626
354056
  const connection = ideClient.getConnectionStatus();
@@ -353651,13 +354081,13 @@ __name(getIdeStatusMessage, "getIdeStatusMessage");
353651
354081
  function formatFileList(openFiles) {
353652
354082
  const basenameCounts = /* @__PURE__ */ new Map();
353653
354083
  for (const file of openFiles) {
353654
- const basename21 = path88.basename(file.path);
354084
+ const basename21 = path89.basename(file.path);
353655
354085
  basenameCounts.set(basename21, (basenameCounts.get(basename21) || 0) + 1);
353656
354086
  }
353657
354087
  const fileList = openFiles.map((file) => {
353658
- const basename21 = path88.basename(file.path);
354088
+ const basename21 = path89.basename(file.path);
353659
354089
  const isDuplicate = (basenameCounts.get(basename21) || 0) > 1;
353660
- const parentDir = path88.basename(path88.dirname(file.path));
354090
+ const parentDir = path89.basename(path89.dirname(file.path));
353661
354091
  const displayName = isDuplicate ? `${basename21} (/${parentDir})` : basename21;
353662
354092
  return ` - ${displayName}${file.isActive ? " (active)" : ""}`;
353663
354093
  }).join("\n");
@@ -354637,8 +355067,8 @@ var importCommand = {
354637
355067
  // packages/cli/src/ui/commands/initCommand.ts
354638
355068
  init_esbuild_shims();
354639
355069
  init_core5();
354640
- import * as fs82 from "node:fs";
354641
- import * as path89 from "node:path";
355070
+ import * as fs83 from "node:fs";
355071
+ import * as path90 from "node:path";
354642
355072
  var import_react27 = __toESM(require_react(), 1);
354643
355073
  var initCommand = {
354644
355074
  name: "init",
@@ -354656,11 +355086,11 @@ var initCommand = {
354656
355086
  }
354657
355087
  const targetDir = context2.services.config.getTargetDir();
354658
355088
  const contextFileName = getCurrentGeminiMdFilename();
354659
- const contextFilePath = path89.join(targetDir, contextFileName);
355089
+ const contextFilePath = path90.join(targetDir, contextFileName);
354660
355090
  try {
354661
- if (fs82.existsSync(contextFilePath)) {
355091
+ if (fs83.existsSync(contextFilePath)) {
354662
355092
  try {
354663
- const existing = fs82.readFileSync(contextFilePath, "utf8");
355093
+ const existing = fs83.readFileSync(contextFilePath, "utf8");
354664
355094
  if (existing && existing.trim().length > 0) {
354665
355095
  if (!context2.overwriteConfirmed) {
354666
355096
  return {
@@ -354682,7 +355112,7 @@ var initCommand = {
354682
355112
  }
354683
355113
  }
354684
355114
  try {
354685
- fs82.writeFileSync(contextFilePath, "", "utf8");
355115
+ fs83.writeFileSync(contextFilePath, "", "utf8");
354686
355116
  context2.ui.addItem(
354687
355117
  {
354688
355118
  type: "info",
@@ -354745,354 +355175,6 @@ Write the complete content to the \`${contextFileName}\` file. The output must b
354745
355175
  }, "action")
354746
355176
  };
354747
355177
 
354748
- // packages/cli/src/ui/commands/languageCommand.ts
354749
- init_esbuild_shims();
354750
- init_settings();
354751
- init_core5();
354752
- import * as fs83 from "node:fs";
354753
- import * as path90 from "node:path";
354754
- var LLM_OUTPUT_LANGUAGE_RULE_FILENAME = "output-language.md";
354755
- function generateLlmOutputLanguageRule(language) {
354756
- return `# \u26A0\uFE0F CRITICAL: ${language} Output Language Rule - HIGHEST PRIORITY \u26A0\uFE0F
354757
-
354758
- ## \u{1F6A8} MANDATORY RULE - NO EXCEPTIONS \u{1F6A8}
354759
-
354760
- **YOU MUST RESPOND IN ${language.toUpperCase()} FOR EVERY SINGLE OUTPUT, REGARDLESS OF THE USER'S INPUT LANGUAGE.**
354761
-
354762
- This is a **NON-NEGOTIABLE** requirement. Even if the user writes in English, says "hi", asks a simple question, or explicitly requests another language, **YOU MUST ALWAYS RESPOND IN ${language.toUpperCase()}.**
354763
-
354764
- ## What Must Be in ${language}
354765
-
354766
- **EVERYTHING** you output: conversation replies, tool call descriptions, success/error messages, generated file content (comments, documentation), and all explanatory text.
354767
-
354768
- **Tool outputs**: All descriptive text from \`read_file\`, \`write_file\`, \`codebase_search\`, \`run_terminal_cmd\`, \`todo_write\`, \`web_search\`, etc. MUST be in ${language}.
354769
-
354770
- ## Examples
354771
-
354772
- ### \u2705 CORRECT:
354773
- - User says "hi" \u2192 Respond in ${language} (e.g., "Bonjour" if ${language} is French)
354774
- - Tool result \u2192 "\u5DF2\u6210\u529F\u8BFB\u53D6\u6587\u4EF6 config.json" (if ${language} is Chinese)
354775
- - Error \u2192 "\u65E0\u6CD5\u627E\u5230\u6307\u5B9A\u7684\u6587\u4EF6" (if ${language} is Chinese)
354776
-
354777
- ### \u274C WRONG:
354778
- - User says "hi" \u2192 "Hello" in English
354779
- - Tool result \u2192 "Successfully read file" in English
354780
- - Error \u2192 "File not found" in English
354781
-
354782
- ## Notes
354783
-
354784
- - Code elements (variable/function names, syntax) can remain in English
354785
- - Comments, documentation, and all other text MUST be in ${language}
354786
-
354787
- **THIS RULE IS ACTIVE NOW. ALL OUTPUTS MUST BE IN ${language.toUpperCase()}. NO EXCEPTIONS.**
354788
- `;
354789
- }
354790
- __name(generateLlmOutputLanguageRule, "generateLlmOutputLanguageRule");
354791
- function getLlmOutputLanguageRulePath() {
354792
- return path90.join(
354793
- Storage.getGlobalQwenDir(),
354794
- LLM_OUTPUT_LANGUAGE_RULE_FILENAME
354795
- );
354796
- }
354797
- __name(getLlmOutputLanguageRulePath, "getLlmOutputLanguageRulePath");
354798
- function getCurrentLlmOutputLanguage() {
354799
- const filePath = getLlmOutputLanguageRulePath();
354800
- if (fs83.existsSync(filePath)) {
354801
- try {
354802
- const content = fs83.readFileSync(filePath, "utf-8");
354803
- const match2 = content.match(/^#.*?(\w+)\s+Output Language Rule/i);
354804
- if (match2) {
354805
- return match2[1];
354806
- }
354807
- } catch {
354808
- }
354809
- }
354810
- return null;
354811
- }
354812
- __name(getCurrentLlmOutputLanguage, "getCurrentLlmOutputLanguage");
354813
- async function setUiLanguage(context2, lang) {
354814
- const { services } = context2;
354815
- const { settings } = services;
354816
- if (!services.config) {
354817
- return {
354818
- type: "message",
354819
- messageType: "error",
354820
- content: t4("Configuration not available.")
354821
- };
354822
- }
354823
- await setLanguageAsync(lang);
354824
- if (settings && typeof settings.setValue === "function") {
354825
- try {
354826
- settings.setValue("User" /* User */, "general.language", lang);
354827
- } catch (error2) {
354828
- console.warn("Failed to save language setting:", error2);
354829
- }
354830
- }
354831
- context2.ui.reloadCommands();
354832
- const langDisplayNames = {
354833
- zh: "\u4E2D\u6587\uFF08zh-CN\uFF09",
354834
- en: "English\uFF08en-US\uFF09"
354835
- };
354836
- return {
354837
- type: "message",
354838
- messageType: "info",
354839
- content: t4("UI language changed to {{lang}}", {
354840
- lang: langDisplayNames[lang] || lang
354841
- })
354842
- };
354843
- }
354844
- __name(setUiLanguage, "setUiLanguage");
354845
- function generateLlmOutputLanguageRuleFile(language) {
354846
- try {
354847
- const filePath = getLlmOutputLanguageRulePath();
354848
- const content = generateLlmOutputLanguageRule(language);
354849
- const dir = path90.dirname(filePath);
354850
- fs83.mkdirSync(dir, { recursive: true });
354851
- fs83.writeFileSync(filePath, content, "utf-8");
354852
- return Promise.resolve({
354853
- type: "message",
354854
- messageType: "info",
354855
- content: [
354856
- t4("LLM output language rule file generated at {{path}}", {
354857
- path: filePath
354858
- }),
354859
- "",
354860
- t4("Please restart the application for the changes to take effect.")
354861
- ].join("\n")
354862
- });
354863
- } catch (error2) {
354864
- return Promise.resolve({
354865
- type: "message",
354866
- messageType: "error",
354867
- content: t4(
354868
- "Failed to generate LLM output language rule file: {{error}}",
354869
- {
354870
- error: error2 instanceof Error ? error2.message : String(error2)
354871
- }
354872
- )
354873
- });
354874
- }
354875
- }
354876
- __name(generateLlmOutputLanguageRuleFile, "generateLlmOutputLanguageRuleFile");
354877
- var languageCommand = {
354878
- name: "language",
354879
- get description() {
354880
- return t4("View or change the language setting");
354881
- },
354882
- kind: "built-in" /* BUILT_IN */,
354883
- action: /* @__PURE__ */ __name(async (context2, args) => {
354884
- const { services } = context2;
354885
- if (!services.config) {
354886
- return {
354887
- type: "message",
354888
- messageType: "error",
354889
- content: t4("Configuration not available.")
354890
- };
354891
- }
354892
- const trimmedArgs = args.trim();
354893
- if (!trimmedArgs) {
354894
- const currentUiLang = getCurrentLanguage();
354895
- const currentLlmLang = getCurrentLlmOutputLanguage();
354896
- const message = [
354897
- t4("Current UI language: {{lang}}", { lang: currentUiLang }),
354898
- currentLlmLang ? t4("Current LLM output language: {{lang}}", { lang: currentLlmLang }) : t4("LLM output language not set"),
354899
- "",
354900
- t4("Available subcommands:"),
354901
- ` /language ui [zh-CN|en-US] - ${t4("Set UI language")}`,
354902
- ` /language output <language> - ${t4("Set LLM output language")}`
354903
- ].join("\n");
354904
- return {
354905
- type: "message",
354906
- messageType: "info",
354907
- content: message
354908
- };
354909
- }
354910
- const parts = trimmedArgs.split(/\s+/);
354911
- const subcommand = parts[0].toLowerCase();
354912
- if (subcommand === "ui") {
354913
- if (parts.length === 1) {
354914
- return {
354915
- type: "message",
354916
- messageType: "info",
354917
- content: [
354918
- t4("Set UI language"),
354919
- "",
354920
- t4("Usage: /language ui [zh-CN|en-US]"),
354921
- "",
354922
- t4("Available options:"),
354923
- t4(" - zh-CN: Simplified Chinese"),
354924
- t4(" - en-US: English"),
354925
- "",
354926
- t4(
354927
- "To request additional UI language packs, please open an issue on GitHub."
354928
- )
354929
- ].join("\n")
354930
- };
354931
- }
354932
- const langArg = parts[1].toLowerCase();
354933
- let targetLang = null;
354934
- if (langArg === "en" || langArg === "english" || langArg === "en-us") {
354935
- targetLang = "en";
354936
- } else if (langArg === "zh" || langArg === "chinese" || langArg === "\u4E2D\u6587" || langArg === "zh-cn") {
354937
- targetLang = "zh";
354938
- } else {
354939
- return {
354940
- type: "message",
354941
- messageType: "error",
354942
- content: t4("Invalid language. Available: en-US, zh-CN")
354943
- };
354944
- }
354945
- return setUiLanguage(context2, targetLang);
354946
- } else if (subcommand === "output") {
354947
- if (parts.length === 1) {
354948
- return {
354949
- type: "message",
354950
- messageType: "info",
354951
- content: [
354952
- t4("Set LLM output language"),
354953
- "",
354954
- t4("Usage: /language output <language>"),
354955
- ` ${t4("Example: /language output \u4E2D\u6587")}`
354956
- ].join("\n")
354957
- };
354958
- }
354959
- const language = parts.slice(1).join(" ");
354960
- return generateLlmOutputLanguageRuleFile(language);
354961
- } else {
354962
- const langArg = trimmedArgs.toLowerCase();
354963
- let targetLang = null;
354964
- if (langArg === "en" || langArg === "english" || langArg === "en-us") {
354965
- targetLang = "en";
354966
- } else if (langArg === "zh" || langArg === "chinese" || langArg === "\u4E2D\u6587" || langArg === "zh-cn") {
354967
- targetLang = "zh";
354968
- } else {
354969
- return {
354970
- type: "message",
354971
- messageType: "error",
354972
- content: [
354973
- t4("Invalid command. Available subcommands:"),
354974
- " - /language ui [zh-CN|en-US] - " + t4("Set UI language"),
354975
- " - /language output <language> - " + t4("Set LLM output language")
354976
- ].join("\n")
354977
- };
354978
- }
354979
- return setUiLanguage(context2, targetLang);
354980
- }
354981
- }, "action"),
354982
- subCommands: [
354983
- {
354984
- name: "ui",
354985
- get description() {
354986
- return t4("Set UI language");
354987
- },
354988
- kind: "built-in" /* BUILT_IN */,
354989
- action: /* @__PURE__ */ __name(async (context2, args) => {
354990
- const trimmedArgs = args.trim();
354991
- if (!trimmedArgs) {
354992
- return {
354993
- type: "message",
354994
- messageType: "info",
354995
- content: [
354996
- t4("Set UI language"),
354997
- "",
354998
- t4("Usage: /language ui [zh-CN|en-US]"),
354999
- "",
355000
- t4("Available options:"),
355001
- t4(" - zh-CN: Simplified Chinese"),
355002
- t4(" - en-US: English"),
355003
- "",
355004
- t4(
355005
- "To request additional UI language packs, please open an issue on GitHub."
355006
- )
355007
- ].join("\n")
355008
- };
355009
- }
355010
- const langArg = trimmedArgs.toLowerCase();
355011
- let targetLang = null;
355012
- if (langArg === "en" || langArg === "english" || langArg === "en-us") {
355013
- targetLang = "en";
355014
- } else if (langArg === "zh" || langArg === "chinese" || langArg === "\u4E2D\u6587" || langArg === "zh-cn") {
355015
- targetLang = "zh";
355016
- } else {
355017
- return {
355018
- type: "message",
355019
- messageType: "error",
355020
- content: t4("Invalid language. Available: en-US, zh-CN")
355021
- };
355022
- }
355023
- return setUiLanguage(context2, targetLang);
355024
- }, "action"),
355025
- subCommands: [
355026
- {
355027
- name: "zh-CN",
355028
- altNames: ["zh", "chinese", "\u4E2D\u6587"],
355029
- get description() {
355030
- return t4("Set UI language to Simplified Chinese (zh-CN)");
355031
- },
355032
- kind: "built-in" /* BUILT_IN */,
355033
- action: /* @__PURE__ */ __name(async (context2, args) => {
355034
- if (args.trim().length > 0) {
355035
- return {
355036
- type: "message",
355037
- messageType: "error",
355038
- content: t4(
355039
- "Language subcommands do not accept additional arguments."
355040
- )
355041
- };
355042
- }
355043
- return setUiLanguage(context2, "zh");
355044
- }, "action")
355045
- },
355046
- {
355047
- name: "en-US",
355048
- altNames: ["en", "english"],
355049
- get description() {
355050
- return t4("Set UI language to English (en-US)");
355051
- },
355052
- kind: "built-in" /* BUILT_IN */,
355053
- action: /* @__PURE__ */ __name(async (context2, args) => {
355054
- if (args.trim().length > 0) {
355055
- return {
355056
- type: "message",
355057
- messageType: "error",
355058
- content: t4(
355059
- "Language subcommands do not accept additional arguments."
355060
- )
355061
- };
355062
- }
355063
- return setUiLanguage(context2, "en");
355064
- }, "action")
355065
- }
355066
- ]
355067
- },
355068
- {
355069
- name: "output",
355070
- get description() {
355071
- return t4("Set LLM output language");
355072
- },
355073
- kind: "built-in" /* BUILT_IN */,
355074
- action: /* @__PURE__ */ __name(async (context2, args) => {
355075
- const trimmedArgs = args.trim();
355076
- if (!trimmedArgs) {
355077
- return {
355078
- type: "message",
355079
- messageType: "info",
355080
- content: [
355081
- t4("Set LLM output language"),
355082
- "",
355083
- t4("Usage: /language output <language>"),
355084
- ` ${t4("Example: /language output \u4E2D\u6587")}`,
355085
- ` ${t4("Example: /language output English")}`,
355086
- ` ${t4("Example: /language output \u65E5\u672C\u8A9E")}`
355087
- ].join("\n")
355088
- };
355089
- }
355090
- return generateLlmOutputLanguageRuleFile(trimmedArgs);
355091
- }, "action")
355092
- }
355093
- ]
355094
- };
355095
-
355096
355178
  // packages/cli/src/ui/commands/mcpCommand.ts
355097
355179
  init_esbuild_shims();
355098
355180
  init_core5();
@@ -356920,6 +357002,7 @@ var summaryCommand = {
356920
357002
  action: /* @__PURE__ */ __name(async (context2) => {
356921
357003
  const { config: config2 } = context2.services;
356922
357004
  const { ui: ui2 } = context2;
357005
+ const executionMode = context2.executionMode ?? "interactive";
356923
357006
  if (!config2) {
356924
357007
  return {
356925
357008
  type: "message",
@@ -356935,7 +357018,7 @@ var summaryCommand = {
356935
357018
  content: t4("No chat client available to generate summary.")
356936
357019
  };
356937
357020
  }
356938
- if (ui2.pendingItem) {
357021
+ if (executionMode === "interactive" && ui2.pendingItem) {
356939
357022
  ui2.addItem(
356940
357023
  {
356941
357024
  type: "error",
@@ -356953,25 +357036,17 @@ var summaryCommand = {
356953
357036
  )
356954
357037
  };
356955
357038
  }
356956
- try {
357039
+ const getChatHistory = /* @__PURE__ */ __name(() => {
356957
357040
  const chat = geminiClient.getChat();
356958
- const history = chat.getHistory();
356959
- if (history.length <= 2) {
356960
- return {
356961
- type: "message",
356962
- messageType: "info",
356963
- content: t4("No conversation found to summarize.")
356964
- };
356965
- }
356966
- const pendingMessage = {
356967
- type: "summary",
356968
- summary: {
356969
- isPending: true,
356970
- stage: "generating"
356971
- }
356972
- };
356973
- ui2.setPendingItem(pendingMessage);
356974
- const conversationContext = history.map((message) => ({
357041
+ return chat.getHistory();
357042
+ }, "getChatHistory");
357043
+ const validateChatHistory = /* @__PURE__ */ __name((history2) => {
357044
+ if (history2.length <= 2) {
357045
+ throw new Error(t4("No conversation found to summarize."));
357046
+ }
357047
+ }, "validateChatHistory");
357048
+ const generateSummaryMarkdown = /* @__PURE__ */ __name(async (history2) => {
357049
+ const conversationContext = history2.map((message) => ({
356975
357050
  role: message.role,
356976
357051
  parts: message.parts
356977
357052
  }));
@@ -356995,16 +357070,14 @@ var summaryCommand = {
356995
357070
  const markdownSummary = parts?.map((part) => part.text).filter((text) => typeof text === "string").join("") || "";
356996
357071
  if (!markdownSummary) {
356997
357072
  throw new Error(
356998
- "Failed to generate summary - no text content received from LLM response"
357073
+ t4(
357074
+ "Failed to generate summary - no text content received from LLM response"
357075
+ )
356999
357076
  );
357000
357077
  }
357001
- ui2.setPendingItem({
357002
- type: "summary",
357003
- summary: {
357004
- isPending: true,
357005
- stage: "saving"
357006
- }
357007
- });
357078
+ return markdownSummary;
357079
+ }, "generateSummaryMarkdown");
357080
+ const saveSummaryToDisk = /* @__PURE__ */ __name(async (markdownSummary) => {
357008
357081
  const projectRoot = config2.getProjectRoot();
357009
357082
  const qwenDir = path94.join(projectRoot, ".rdmind");
357010
357083
  try {
@@ -357020,42 +357093,137 @@ var summaryCommand = {
357020
357093
  **Update time**: ${(/* @__PURE__ */ new Date()).toISOString()}
357021
357094
  `;
357022
357095
  await fsPromises5.writeFile(summaryPath, summaryContent, "utf8");
357096
+ return {
357097
+ filePathForDisplay: ".qwen/PROJECT_SUMMARY.md",
357098
+ fullPath: summaryPath
357099
+ };
357100
+ }, "saveSummaryToDisk");
357101
+ const emitInteractivePending = /* @__PURE__ */ __name((stage) => {
357102
+ if (executionMode !== "interactive") {
357103
+ return;
357104
+ }
357105
+ const pendingMessage = {
357106
+ type: "summary",
357107
+ summary: {
357108
+ isPending: true,
357109
+ stage
357110
+ }
357111
+ };
357112
+ ui2.setPendingItem(pendingMessage);
357113
+ }, "emitInteractivePending");
357114
+ const completeInteractive = /* @__PURE__ */ __name((filePathForDisplay) => {
357115
+ if (executionMode !== "interactive") {
357116
+ return;
357117
+ }
357023
357118
  ui2.setPendingItem(null);
357024
357119
  const completedSummaryItem = {
357025
357120
  type: "summary",
357026
357121
  summary: {
357027
357122
  isPending: false,
357028
357123
  stage: "completed",
357029
- filePath: ".rdmind/PROJECT_SUMMARY.md"
357124
+ filePath: filePathForDisplay
357030
357125
  }
357031
357126
  };
357032
357127
  ui2.addItem(completedSummaryItem, Date.now());
357033
- return {
357034
- type: "message",
357035
- messageType: "info",
357036
- content: ""
357037
- // Empty content since we show the message in UI component
357038
- };
357039
- } catch (error2) {
357128
+ }, "completeInteractive");
357129
+ const formatErrorMessage = /* @__PURE__ */ __name((error2) => t4("Failed to generate project context summary: {{error}}", {
357130
+ error: error2 instanceof Error ? error2.message : String(error2)
357131
+ }), "formatErrorMessage");
357132
+ const failInteractive = /* @__PURE__ */ __name((error2) => {
357133
+ if (executionMode !== "interactive") {
357134
+ return;
357135
+ }
357040
357136
  ui2.setPendingItem(null);
357041
357137
  ui2.addItem(
357042
357138
  {
357043
357139
  type: "error",
357044
- text: `\u274C ${t4(
357045
- "Failed to generate project context summary: {{error}}",
357046
- {
357047
- error: error2 instanceof Error ? error2.message : String(error2)
357048
- }
357049
- )}`
357140
+ text: `\u274C ${formatErrorMessage(error2)}`
357050
357141
  },
357051
357142
  Date.now()
357052
357143
  );
357144
+ }, "failInteractive");
357145
+ const formatSuccessMessage = /* @__PURE__ */ __name((filePathForDisplay) => t4("Saved project summary to {{filePathForDisplay}}.", {
357146
+ filePathForDisplay
357147
+ }), "formatSuccessMessage");
357148
+ const returnNoConversationMessage = /* @__PURE__ */ __name(() => {
357149
+ const msg = t4("No conversation found to summarize.");
357150
+ if (executionMode === "acp") {
357151
+ const messages = /* @__PURE__ */ __name(async function* () {
357152
+ yield {
357153
+ messageType: "info",
357154
+ content: msg
357155
+ };
357156
+ }, "messages");
357157
+ return {
357158
+ type: "stream_messages",
357159
+ messages: messages()
357160
+ };
357161
+ }
357162
+ return {
357163
+ type: "message",
357164
+ messageType: "info",
357165
+ content: msg
357166
+ };
357167
+ }, "returnNoConversationMessage");
357168
+ const executeSummaryGeneration = /* @__PURE__ */ __name(async (history2) => {
357169
+ emitInteractivePending("generating");
357170
+ const markdownSummary = await generateSummaryMarkdown(history2);
357171
+ emitInteractivePending("saving");
357172
+ const { filePathForDisplay } = await saveSummaryToDisk(markdownSummary);
357173
+ completeInteractive(filePathForDisplay);
357174
+ return { markdownSummary, filePathForDisplay };
357175
+ }, "executeSummaryGeneration");
357176
+ const history = getChatHistory();
357177
+ try {
357178
+ validateChatHistory(history);
357179
+ } catch (_error) {
357180
+ return returnNoConversationMessage();
357181
+ }
357182
+ if (executionMode === "acp") {
357183
+ const messages = /* @__PURE__ */ __name(async function* () {
357184
+ try {
357185
+ yield {
357186
+ messageType: "info",
357187
+ content: t4("Generating project summary...")
357188
+ };
357189
+ const { filePathForDisplay } = await executeSummaryGeneration(history);
357190
+ yield {
357191
+ messageType: "info",
357192
+ content: formatSuccessMessage(filePathForDisplay)
357193
+ };
357194
+ } catch (error2) {
357195
+ failInteractive(error2);
357196
+ yield {
357197
+ messageType: "error",
357198
+ content: formatErrorMessage(error2)
357199
+ };
357200
+ }
357201
+ }, "messages");
357202
+ return {
357203
+ type: "stream_messages",
357204
+ messages: messages()
357205
+ };
357206
+ }
357207
+ try {
357208
+ const { filePathForDisplay } = await executeSummaryGeneration(history);
357209
+ if (executionMode === "non_interactive") {
357210
+ return {
357211
+ type: "message",
357212
+ messageType: "info",
357213
+ content: formatSuccessMessage(filePathForDisplay)
357214
+ };
357215
+ }
357216
+ return {
357217
+ type: "message",
357218
+ messageType: "info",
357219
+ content: ""
357220
+ };
357221
+ } catch (error2) {
357222
+ failInteractive(error2);
357053
357223
  return {
357054
357224
  type: "message",
357055
357225
  messageType: "error",
357056
- content: t4("Failed to generate project context summary: {{error}}", {
357057
- error: error2 instanceof Error ? error2.message : String(error2)
357058
- })
357226
+ content: formatErrorMessage(error2)
357059
357227
  };
357060
357228
  }
357061
357229
  }, "action")
@@ -358468,67 +358636,908 @@ var BuiltinCommandLoader = class {
358468
358636
  }
358469
358637
  };
358470
358638
 
358471
- // packages/cli/src/ui/utils/computeStats.ts
358639
+ // packages/cli/src/services/FileCommandLoader.ts
358472
358640
  init_esbuild_shims();
358473
- function calculateErrorRate(metrics2) {
358474
- if (metrics2.api.totalRequests === 0) {
358475
- return 0;
358641
+ var import_toml = __toESM(require_toml(), 1);
358642
+ init_esm11();
358643
+ init_zod();
358644
+ init_core5();
358645
+ import { promises as fs90 } from "node:fs";
358646
+ import path98 from "node:path";
358647
+
358648
+ // packages/cli/src/services/prompt-processors/argumentProcessor.ts
358649
+ init_esbuild_shims();
358650
+ init_core5();
358651
+ var DefaultArgumentProcessor = class {
358652
+ static {
358653
+ __name(this, "DefaultArgumentProcessor");
358476
358654
  }
358477
- return metrics2.api.totalErrors / metrics2.api.totalRequests * 100;
358655
+ async process(prompt, context2) {
358656
+ if (context2.invocation?.args) {
358657
+ return appendToLastTextPart(prompt, context2.invocation.raw);
358658
+ }
358659
+ return prompt;
358660
+ }
358661
+ };
358662
+
358663
+ // packages/cli/src/services/prompt-processors/types.ts
358664
+ init_esbuild_shims();
358665
+ var SHORTHAND_ARGS_PLACEHOLDER = "{{args}}";
358666
+ var SHELL_INJECTION_TRIGGER = "!{";
358667
+ var AT_FILE_INJECTION_TRIGGER = "@{";
358668
+
358669
+ // packages/cli/src/services/prompt-processors/shellProcessor.ts
358670
+ init_esbuild_shims();
358671
+ init_core5();
358672
+
358673
+ // packages/cli/src/services/prompt-processors/injectionParser.ts
358674
+ init_esbuild_shims();
358675
+ function extractInjections(prompt, trigger, contextName) {
358676
+ const injections = [];
358677
+ let index = 0;
358678
+ while (index < prompt.length) {
358679
+ const startIndex = prompt.indexOf(trigger, index);
358680
+ if (startIndex === -1) {
358681
+ break;
358682
+ }
358683
+ let currentIndex = startIndex + trigger.length;
358684
+ let braceCount = 1;
358685
+ let foundEnd = false;
358686
+ while (currentIndex < prompt.length) {
358687
+ const char = prompt[currentIndex];
358688
+ if (char === "{") {
358689
+ braceCount++;
358690
+ } else if (char === "}") {
358691
+ braceCount--;
358692
+ if (braceCount === 0) {
358693
+ const injectionContent = prompt.substring(
358694
+ startIndex + trigger.length,
358695
+ currentIndex
358696
+ );
358697
+ const endIndex = currentIndex + 1;
358698
+ injections.push({
358699
+ content: injectionContent.trim(),
358700
+ startIndex,
358701
+ endIndex
358702
+ });
358703
+ index = endIndex;
358704
+ foundEnd = true;
358705
+ break;
358706
+ }
358707
+ }
358708
+ currentIndex++;
358709
+ }
358710
+ if (!foundEnd) {
358711
+ const contextInfo = contextName ? ` in command '${contextName}'` : "";
358712
+ throw new Error(
358713
+ `Invalid syntax${contextInfo}: Unclosed injection starting at index ${startIndex} ('${trigger}'). Ensure braces are balanced. Paths or commands with unbalanced braces are not supported directly.`
358714
+ );
358715
+ }
358716
+ }
358717
+ return injections;
358478
358718
  }
358479
- __name(calculateErrorRate, "calculateErrorRate");
358480
- function calculateAverageLatency(metrics2) {
358481
- if (metrics2.api.totalRequests === 0) {
358482
- return 0;
358719
+ __name(extractInjections, "extractInjections");
358720
+
358721
+ // packages/cli/src/services/prompt-processors/shellProcessor.ts
358722
+ var ConfirmationRequiredError = class extends Error {
358723
+ constructor(message, commandsToConfirm) {
358724
+ super(message);
358725
+ this.commandsToConfirm = commandsToConfirm;
358726
+ this.name = "ConfirmationRequiredError";
358483
358727
  }
358484
- return metrics2.api.totalLatencyMs / metrics2.api.totalRequests;
358728
+ static {
358729
+ __name(this, "ConfirmationRequiredError");
358730
+ }
358731
+ };
358732
+ var ShellProcessor = class {
358733
+ constructor(commandName) {
358734
+ this.commandName = commandName;
358735
+ }
358736
+ static {
358737
+ __name(this, "ShellProcessor");
358738
+ }
358739
+ async process(prompt, context2) {
358740
+ return flatMapTextParts(
358741
+ prompt,
358742
+ (text) => this.processString(text, context2)
358743
+ );
358744
+ }
358745
+ async processString(prompt, context2) {
358746
+ const userArgsRaw = context2.invocation?.args || "";
358747
+ if (!prompt.includes(SHELL_INJECTION_TRIGGER)) {
358748
+ return [
358749
+ { text: prompt.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsRaw) }
358750
+ ];
358751
+ }
358752
+ const config2 = context2.services.config;
358753
+ if (!config2) {
358754
+ throw new Error(
358755
+ `Security configuration not loaded. Cannot verify shell command permissions for '${this.commandName}'. Aborting.`
358756
+ );
358757
+ }
358758
+ const { sessionShellAllowlist } = context2.session;
358759
+ const injections = extractInjections(
358760
+ prompt,
358761
+ SHELL_INJECTION_TRIGGER,
358762
+ this.commandName
358763
+ );
358764
+ if (injections.length === 0) {
358765
+ return [
358766
+ { text: prompt.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsRaw) }
358767
+ ];
358768
+ }
358769
+ const { shell: shell2 } = getShellConfiguration();
358770
+ const userArgsEscaped = escapeShellArg(userArgsRaw, shell2);
358771
+ const resolvedInjections = injections.map(
358772
+ (injection) => {
358773
+ const command2 = injection.content;
358774
+ if (command2 === "") {
358775
+ return { ...injection, resolvedCommand: void 0 };
358776
+ }
358777
+ const resolvedCommand = command2.replaceAll(
358778
+ SHORTHAND_ARGS_PLACEHOLDER,
358779
+ userArgsEscaped
358780
+ );
358781
+ return { ...injection, resolvedCommand };
358782
+ }
358783
+ );
358784
+ const commandsToConfirm = /* @__PURE__ */ new Set();
358785
+ for (const injection of resolvedInjections) {
358786
+ const command2 = injection.resolvedCommand;
358787
+ if (!command2) continue;
358788
+ const { allAllowed, disallowedCommands, blockReason, isHardDenial } = checkCommandPermissions(command2, config2, sessionShellAllowlist);
358789
+ if (!allAllowed) {
358790
+ if (isHardDenial) {
358791
+ throw new Error(
358792
+ `${this.commandName} cannot be run. Blocked command: "${command2}". Reason: ${blockReason || "Blocked by configuration."}`
358793
+ );
358794
+ }
358795
+ if (config2.getApprovalMode() !== "yolo" /* YOLO */) {
358796
+ disallowedCommands.forEach((uc) => commandsToConfirm.add(uc));
358797
+ }
358798
+ }
358799
+ }
358800
+ if (commandsToConfirm.size > 0) {
358801
+ throw new ConfirmationRequiredError(
358802
+ "Shell command confirmation required",
358803
+ Array.from(commandsToConfirm)
358804
+ );
358805
+ }
358806
+ let processedPrompt = "";
358807
+ let lastIndex = 0;
358808
+ for (const injection of resolvedInjections) {
358809
+ const segment = prompt.substring(lastIndex, injection.startIndex);
358810
+ processedPrompt += segment.replaceAll(
358811
+ SHORTHAND_ARGS_PLACEHOLDER,
358812
+ userArgsRaw
358813
+ );
358814
+ if (injection.resolvedCommand) {
358815
+ const activeTheme = themeManager.getActiveTheme();
358816
+ const shellExecutionConfig = {
358817
+ ...config2.getShellExecutionConfig(),
358818
+ defaultFg: activeTheme.colors.Foreground,
358819
+ defaultBg: activeTheme.colors.Background
358820
+ };
358821
+ const { result } = await ShellExecutionService.execute(
358822
+ injection.resolvedCommand,
358823
+ config2.getTargetDir(),
358824
+ () => {
358825
+ },
358826
+ new AbortController().signal,
358827
+ config2.getShouldUseNodePtyShell(),
358828
+ shellExecutionConfig
358829
+ );
358830
+ const executionResult = await result;
358831
+ if (executionResult.error && !executionResult.aborted) {
358832
+ throw new Error(
358833
+ `Failed to start shell command in '${this.commandName}': ${executionResult.error.message}. Command: ${injection.resolvedCommand}`
358834
+ );
358835
+ }
358836
+ processedPrompt += executionResult.output;
358837
+ if (executionResult.aborted) {
358838
+ processedPrompt += `
358839
+ [Shell command '${injection.resolvedCommand}' aborted]`;
358840
+ } else if (executionResult.exitCode !== 0 && executionResult.exitCode !== null) {
358841
+ processedPrompt += `
358842
+ [Shell command '${injection.resolvedCommand}' exited with code ${executionResult.exitCode}]`;
358843
+ } else if (executionResult.signal !== null) {
358844
+ processedPrompt += `
358845
+ [Shell command '${injection.resolvedCommand}' terminated by signal ${executionResult.signal}]`;
358846
+ }
358847
+ }
358848
+ lastIndex = injection.endIndex;
358849
+ }
358850
+ const finalSegment = prompt.substring(lastIndex);
358851
+ processedPrompt += finalSegment.replaceAll(
358852
+ SHORTHAND_ARGS_PLACEHOLDER,
358853
+ userArgsRaw
358854
+ );
358855
+ return [{ text: processedPrompt }];
358856
+ }
358857
+ };
358858
+
358859
+ // packages/cli/src/services/prompt-processors/atFileProcessor.ts
358860
+ init_esbuild_shims();
358861
+ init_core5();
358862
+ var AtFileProcessor = class {
358863
+ constructor(commandName) {
358864
+ this.commandName = commandName;
358865
+ }
358866
+ static {
358867
+ __name(this, "AtFileProcessor");
358868
+ }
358869
+ async process(input, context2) {
358870
+ const config2 = context2.services.config;
358871
+ if (!config2) {
358872
+ return input;
358873
+ }
358874
+ return flatMapTextParts(input, async (text) => {
358875
+ if (!text.includes(AT_FILE_INJECTION_TRIGGER)) {
358876
+ return [{ text }];
358877
+ }
358878
+ const injections = extractInjections(
358879
+ text,
358880
+ AT_FILE_INJECTION_TRIGGER,
358881
+ this.commandName
358882
+ );
358883
+ if (injections.length === 0) {
358884
+ return [{ text }];
358885
+ }
358886
+ const output = [];
358887
+ let lastIndex = 0;
358888
+ for (const injection of injections) {
358889
+ const prefix = text.substring(lastIndex, injection.startIndex);
358890
+ if (prefix) {
358891
+ output.push({ text: prefix });
358892
+ }
358893
+ const pathStr = injection.content;
358894
+ try {
358895
+ const fileContentParts = await readPathFromWorkspace(pathStr, config2);
358896
+ if (fileContentParts.length === 0) {
358897
+ const uiMessage = `File '@{${pathStr}}' was ignored by .gitignore or .rdmindignore and was not included in the prompt.`;
358898
+ context2.ui.addItem(
358899
+ { type: "info" /* INFO */, text: uiMessage },
358900
+ Date.now()
358901
+ );
358902
+ }
358903
+ output.push(...fileContentParts);
358904
+ } catch (error2) {
358905
+ const message = error2 instanceof Error ? error2.message : String(error2);
358906
+ const uiMessage = `Failed to inject content for '@{${pathStr}}': ${message}`;
358907
+ console.error(
358908
+ `[AtFileProcessor] ${uiMessage}. Leaving placeholder in prompt.`
358909
+ );
358910
+ context2.ui.addItem(
358911
+ { type: "error" /* ERROR */, text: uiMessage },
358912
+ Date.now()
358913
+ );
358914
+ const placeholder = text.substring(
358915
+ injection.startIndex,
358916
+ injection.endIndex
358917
+ );
358918
+ output.push({ text: placeholder });
358919
+ }
358920
+ lastIndex = injection.endIndex;
358921
+ }
358922
+ const suffix = text.substring(lastIndex);
358923
+ if (suffix) {
358924
+ output.push({ text: suffix });
358925
+ }
358926
+ return output;
358927
+ });
358928
+ }
358929
+ };
358930
+
358931
+ // packages/cli/src/services/FileCommandLoader.ts
358932
+ var TomlCommandDefSchema = external_exports.object({
358933
+ prompt: external_exports.string({
358934
+ required_error: "The 'prompt' field is required.",
358935
+ invalid_type_error: "The 'prompt' field must be a string."
358936
+ }),
358937
+ description: external_exports.string().optional()
358938
+ });
358939
+ var FileCommandLoader = class {
358940
+ constructor(config2) {
358941
+ this.config = config2;
358942
+ this.folderTrustEnabled = !!config2?.getFolderTrustFeature();
358943
+ this.folderTrust = !!config2?.getFolderTrust();
358944
+ this.projectRoot = config2?.getProjectRoot() || process.cwd();
358945
+ }
358946
+ static {
358947
+ __name(this, "FileCommandLoader");
358948
+ }
358949
+ projectRoot;
358950
+ folderTrustEnabled;
358951
+ folderTrust;
358952
+ /**
358953
+ * Loads all commands from user, project, and extension directories.
358954
+ * Returns commands in order: user → project → extensions (alphabetically).
358955
+ *
358956
+ * Order is important for conflict resolution in CommandService:
358957
+ * - User/project commands (without extensionName) use "last wins" strategy
358958
+ * - Extension commands (with extensionName) get renamed if conflicts exist
358959
+ *
358960
+ * @param signal An AbortSignal to cancel the loading process.
358961
+ * @returns A promise that resolves to an array of all loaded SlashCommands.
358962
+ */
358963
+ async loadCommands(signal) {
358964
+ const allCommands = [];
358965
+ const globOptions = {
358966
+ nodir: true,
358967
+ dot: true,
358968
+ signal,
358969
+ follow: true
358970
+ };
358971
+ const commandDirs = this.getCommandDirectories();
358972
+ for (const dirInfo of commandDirs) {
358973
+ try {
358974
+ const files = await glob("**/*.toml", {
358975
+ ...globOptions,
358976
+ cwd: dirInfo.path
358977
+ });
358978
+ if (this.folderTrustEnabled && !this.folderTrust) {
358979
+ return [];
358980
+ }
358981
+ const commandPromises = files.map(
358982
+ (file) => this.parseAndAdaptFile(
358983
+ path98.join(dirInfo.path, file),
358984
+ dirInfo.path,
358985
+ dirInfo.extensionName
358986
+ )
358987
+ );
358988
+ const commands = (await Promise.all(commandPromises)).filter(
358989
+ (cmd) => cmd !== null
358990
+ );
358991
+ allCommands.push(...commands);
358992
+ } catch (error2) {
358993
+ const isEnoent = error2.code === "ENOENT";
358994
+ const isAbortError2 = error2 instanceof Error && error2.name === "AbortError";
358995
+ if (!isEnoent && !isAbortError2) {
358996
+ console.error(
358997
+ `[FileCommandLoader] Error loading commands from ${dirInfo.path}:`,
358998
+ error2
358999
+ );
359000
+ }
359001
+ }
359002
+ }
359003
+ return allCommands;
359004
+ }
359005
+ /**
359006
+ * Get all command directories in order for loading.
359007
+ * User commands → Project commands → Extension commands
359008
+ * This order ensures extension commands can detect all conflicts.
359009
+ */
359010
+ getCommandDirectories() {
359011
+ const dirs = [];
359012
+ const storage = this.config?.storage ?? new Storage(this.projectRoot);
359013
+ dirs.push({ path: Storage.getUserCommandsDir() });
359014
+ dirs.push({ path: storage.getProjectCommandsDir() });
359015
+ if (this.config) {
359016
+ const activeExtensions = this.config.getExtensions().filter((ext2) => ext2.isActive).sort((a2, b2) => a2.name.localeCompare(b2.name));
359017
+ const extensionCommandDirs = activeExtensions.map((ext2) => ({
359018
+ path: path98.join(ext2.path, "commands"),
359019
+ extensionName: ext2.name
359020
+ }));
359021
+ dirs.push(...extensionCommandDirs);
359022
+ }
359023
+ return dirs;
359024
+ }
359025
+ /**
359026
+ * Parses a single .toml file and transforms it into a SlashCommand object.
359027
+ * @param filePath The absolute path to the .toml file.
359028
+ * @param baseDir The root command directory for name calculation.
359029
+ * @param extensionName Optional extension name to prefix commands with.
359030
+ * @returns A promise resolving to a SlashCommand, or null if the file is invalid.
359031
+ */
359032
+ async parseAndAdaptFile(filePath, baseDir, extensionName) {
359033
+ let fileContent;
359034
+ try {
359035
+ fileContent = await fs90.readFile(filePath, "utf-8");
359036
+ } catch (error2) {
359037
+ console.error(
359038
+ `[FileCommandLoader] Failed to read file ${filePath}:`,
359039
+ error2 instanceof Error ? error2.message : String(error2)
359040
+ );
359041
+ return null;
359042
+ }
359043
+ let parsed;
359044
+ try {
359045
+ parsed = import_toml.default.parse(fileContent);
359046
+ } catch (error2) {
359047
+ console.error(
359048
+ `[FileCommandLoader] Failed to parse TOML file ${filePath}:`,
359049
+ error2 instanceof Error ? error2.message : String(error2)
359050
+ );
359051
+ return null;
359052
+ }
359053
+ const validationResult = TomlCommandDefSchema.safeParse(parsed);
359054
+ if (!validationResult.success) {
359055
+ console.error(
359056
+ `[FileCommandLoader] Skipping invalid command file: ${filePath}. Validation errors:`,
359057
+ validationResult.error.flatten()
359058
+ );
359059
+ return null;
359060
+ }
359061
+ const validDef = validationResult.data;
359062
+ const relativePathWithExt = path98.relative(baseDir, filePath);
359063
+ const relativePath = relativePathWithExt.substring(
359064
+ 0,
359065
+ relativePathWithExt.length - 5
359066
+ // length of '.toml'
359067
+ );
359068
+ const baseCommandName = relativePath.split(path98.sep).map((segment) => segment.replaceAll(":", "_")).join(":");
359069
+ const defaultDescription = `Custom command from ${path98.basename(filePath)}`;
359070
+ let description = validDef.description || defaultDescription;
359071
+ if (extensionName) {
359072
+ description = `[${extensionName}] ${description}`;
359073
+ }
359074
+ const processors = [];
359075
+ const usesArgs = validDef.prompt.includes(SHORTHAND_ARGS_PLACEHOLDER);
359076
+ const usesShellInjection = validDef.prompt.includes(
359077
+ SHELL_INJECTION_TRIGGER
359078
+ );
359079
+ const usesAtFileInjection = validDef.prompt.includes(
359080
+ AT_FILE_INJECTION_TRIGGER
359081
+ );
359082
+ if (usesAtFileInjection) {
359083
+ processors.push(new AtFileProcessor(baseCommandName));
359084
+ }
359085
+ if (usesShellInjection || usesArgs) {
359086
+ processors.push(new ShellProcessor(baseCommandName));
359087
+ }
359088
+ if (!usesArgs) {
359089
+ processors.push(new DefaultArgumentProcessor());
359090
+ }
359091
+ return {
359092
+ name: baseCommandName,
359093
+ description,
359094
+ kind: "file" /* FILE */,
359095
+ extensionName,
359096
+ action: /* @__PURE__ */ __name(async (context2, _args) => {
359097
+ if (!context2.invocation) {
359098
+ console.error(
359099
+ `[FileCommandLoader] Critical error: Command '${baseCommandName}' was executed without invocation context.`
359100
+ );
359101
+ return {
359102
+ type: "submit_prompt",
359103
+ content: [{ text: validDef.prompt }]
359104
+ // Fallback to unprocessed prompt
359105
+ };
359106
+ }
359107
+ try {
359108
+ let processedContent = [
359109
+ { text: validDef.prompt }
359110
+ ];
359111
+ for (const processor of processors) {
359112
+ processedContent = await processor.process(
359113
+ processedContent,
359114
+ context2
359115
+ );
359116
+ }
359117
+ return {
359118
+ type: "submit_prompt",
359119
+ content: processedContent
359120
+ };
359121
+ } catch (e4) {
359122
+ if (e4 instanceof ConfirmationRequiredError) {
359123
+ return {
359124
+ type: "confirm_shell_commands",
359125
+ commandsToConfirm: e4.commandsToConfirm,
359126
+ originalInvocation: {
359127
+ raw: context2.invocation.raw
359128
+ }
359129
+ };
359130
+ }
359131
+ throw e4;
359132
+ }
359133
+ }, "action")
359134
+ };
359135
+ }
359136
+ };
359137
+
359138
+ // packages/cli/src/services/MarkdownCommandLoader.ts
359139
+ init_esbuild_shims();
359140
+ init_esm11();
359141
+ init_zod();
359142
+ import { promises as fs91 } from "node:fs";
359143
+ import path99 from "node:path";
359144
+ var MarkdownCommandDefSchema = external_exports.object({
359145
+ name: external_exports.string(),
359146
+ id: external_exports.string().optional(),
359147
+ category: external_exports.string().optional(),
359148
+ description: external_exports.string()
359149
+ });
359150
+ var MarkdownCommandLoader = class {
359151
+ static {
359152
+ __name(this, "MarkdownCommandLoader");
359153
+ }
359154
+ projectRoot;
359155
+ folderTrustEnabled;
359156
+ folderTrust;
359157
+ constructor(config2) {
359158
+ this.folderTrustEnabled = !!config2?.getFolderTrustFeature();
359159
+ this.folderTrust = !!config2?.getFolderTrust();
359160
+ this.projectRoot = config2?.getProjectRoot() || process.cwd();
359161
+ }
359162
+ /**
359163
+ * Loads all markdown commands from OpenSpec directories.
359164
+ */
359165
+ async loadCommands(signal) {
359166
+ if (this.folderTrustEnabled && !this.folderTrust) {
359167
+ return [];
359168
+ }
359169
+ const allCommands = [];
359170
+ const globOptions = {
359171
+ nodir: true,
359172
+ dot: true,
359173
+ signal,
359174
+ follow: true
359175
+ };
359176
+ const commandDirs = this.getOpenSpecCommandDirectories();
359177
+ for (const dirPath of commandDirs) {
359178
+ try {
359179
+ const files = await glob("**/*.md", {
359180
+ ...globOptions,
359181
+ cwd: dirPath
359182
+ });
359183
+ const commandPromises = files.map(
359184
+ (file) => this.parseAndAdaptFile(path99.join(dirPath, file))
359185
+ );
359186
+ const commands = (await Promise.all(commandPromises)).filter(
359187
+ (cmd) => cmd !== null
359188
+ );
359189
+ allCommands.push(...commands);
359190
+ } catch (error2) {
359191
+ const isEnoent = error2.code === "ENOENT";
359192
+ const isAbortError2 = error2 instanceof Error && error2.name === "AbortError";
359193
+ if (!isEnoent && !isAbortError2) {
359194
+ console.error(
359195
+ `[MarkdownCommandLoader] Error loading commands from ${dirPath}:`,
359196
+ error2
359197
+ );
359198
+ }
359199
+ }
359200
+ }
359201
+ return allCommands;
359202
+ }
359203
+ /**
359204
+ * Get directories containing OpenSpec markdown command files.
359205
+ */
359206
+ getOpenSpecCommandDirectories() {
359207
+ const rdmindCommandsDir = path99.join(
359208
+ this.projectRoot,
359209
+ ".rdmind",
359210
+ "commands"
359211
+ );
359212
+ return [rdmindCommandsDir];
359213
+ }
359214
+ /**
359215
+ * Parses a markdown file with YAML front matter and converts it to a SlashCommand.
359216
+ */
359217
+ async parseAndAdaptFile(filePath) {
359218
+ let fileContent;
359219
+ try {
359220
+ fileContent = await fs91.readFile(filePath, "utf-8");
359221
+ } catch (error2) {
359222
+ console.error(
359223
+ `[MarkdownCommandLoader] Failed to read file ${filePath}:`,
359224
+ error2 instanceof Error ? error2.message : String(error2)
359225
+ );
359226
+ return null;
359227
+ }
359228
+ const frontMatterResult = this.parseFrontMatter(fileContent);
359229
+ if (!frontMatterResult) {
359230
+ return null;
359231
+ }
359232
+ const { frontMatter, content } = frontMatterResult;
359233
+ const validationResult = MarkdownCommandDefSchema.safeParse(frontMatter);
359234
+ if (!validationResult.success) {
359235
+ console.error(
359236
+ `[MarkdownCommandLoader] Invalid front matter in ${filePath}:`,
359237
+ validationResult.error.flatten()
359238
+ );
359239
+ return null;
359240
+ }
359241
+ const validDef = validationResult.data;
359242
+ const commandName = validDef.name.startsWith("/") ? validDef.name.substring(1) : validDef.name;
359243
+ let description = validDef.description;
359244
+ if (commandName === "openspec-proposal") {
359245
+ description = t4("Scaffold a new OpenSpec change and validate strictly.");
359246
+ } else if (commandName === "openspec-apply") {
359247
+ description = t4(
359248
+ "Implement an approved OpenSpec change and keep tasks in sync."
359249
+ );
359250
+ } else if (commandName === "openspec-archive") {
359251
+ description = t4("Archive a deployed OpenSpec change and update specs.");
359252
+ }
359253
+ return {
359254
+ name: commandName,
359255
+ description,
359256
+ kind: "file" /* FILE */,
359257
+ action: /* @__PURE__ */ __name(async (context2, args) => {
359258
+ const prompt = content.trim() + (args ? `
359259
+
359260
+ ${args}` : "");
359261
+ return {
359262
+ type: "submit_prompt",
359263
+ content: [{ text: prompt }]
359264
+ };
359265
+ }, "action")
359266
+ };
359267
+ }
359268
+ /**
359269
+ * Parses YAML front matter from markdown content.
359270
+ */
359271
+ parseFrontMatter(content) {
359272
+ const lines = content.split("\n");
359273
+ if (lines[0]?.trim() !== "---") {
359274
+ return null;
359275
+ }
359276
+ let endIndex = -1;
359277
+ for (let i3 = 1; i3 < lines.length; i3++) {
359278
+ if (lines[i3]?.trim() === "---") {
359279
+ endIndex = i3;
359280
+ break;
359281
+ }
359282
+ }
359283
+ if (endIndex === -1) {
359284
+ return null;
359285
+ }
359286
+ const frontMatterLines = lines.slice(1, endIndex);
359287
+ const contentLines = lines.slice(endIndex + 1);
359288
+ try {
359289
+ const frontMatter = {};
359290
+ for (const line of frontMatterLines) {
359291
+ const trimmed2 = line.trim();
359292
+ if (trimmed2 && !trimmed2.startsWith("#")) {
359293
+ const colonIndex = trimmed2.indexOf(":");
359294
+ if (colonIndex > 0) {
359295
+ const key = trimmed2.substring(0, colonIndex).trim();
359296
+ const value = trimmed2.substring(colonIndex + 1).trim();
359297
+ frontMatter[key] = value;
359298
+ }
359299
+ }
359300
+ }
359301
+ return {
359302
+ frontMatter,
359303
+ content: contentLines.join("\n")
359304
+ };
359305
+ } catch (error2) {
359306
+ console.error("Failed to parse front matter:", error2);
359307
+ return null;
359308
+ }
359309
+ }
359310
+ };
359311
+
359312
+ // packages/cli/src/ui/noninteractive/nonInteractiveUi.ts
359313
+ init_esbuild_shims();
359314
+ function createNonInteractiveUI() {
359315
+ return {
359316
+ addItem: /* @__PURE__ */ __name((_item, _timestamp) => 0, "addItem"),
359317
+ clear: /* @__PURE__ */ __name(() => {
359318
+ }, "clear"),
359319
+ setDebugMessage: /* @__PURE__ */ __name((_message) => {
359320
+ }, "setDebugMessage"),
359321
+ loadHistory: /* @__PURE__ */ __name((_newHistory) => {
359322
+ }, "loadHistory"),
359323
+ pendingItem: null,
359324
+ setPendingItem: /* @__PURE__ */ __name((_item) => {
359325
+ }, "setPendingItem"),
359326
+ toggleVimEnabled: /* @__PURE__ */ __name(async () => false, "toggleVimEnabled"),
359327
+ setGeminiMdFileCount: /* @__PURE__ */ __name((_count) => {
359328
+ }, "setGeminiMdFileCount"),
359329
+ reloadCommands: /* @__PURE__ */ __name(() => {
359330
+ }, "reloadCommands"),
359331
+ extensionsUpdateState: /* @__PURE__ */ new Map(),
359332
+ dispatchExtensionStateUpdate: /* @__PURE__ */ __name((_action) => {
359333
+ }, "dispatchExtensionStateUpdate"),
359334
+ addConfirmUpdateExtensionRequest: /* @__PURE__ */ __name((_request) => {
359335
+ }, "addConfirmUpdateExtensionRequest")
359336
+ };
358485
359337
  }
358486
- __name(calculateAverageLatency, "calculateAverageLatency");
358487
- function calculateCacheHitRate(metrics2) {
358488
- if (metrics2.tokens.prompt === 0) {
358489
- return 0;
359338
+ __name(createNonInteractiveUI, "createNonInteractiveUI");
359339
+
359340
+ // packages/cli/src/nonInteractiveCliCommands.ts
359341
+ var ALLOWED_BUILTIN_COMMANDS_NON_INTERACTIVE = [
359342
+ "init",
359343
+ "summary",
359344
+ "compress"
359345
+ ];
359346
+ function handleCommandResult(result) {
359347
+ switch (result.type) {
359348
+ case "submit_prompt":
359349
+ return {
359350
+ type: "submit_prompt",
359351
+ content: result.content
359352
+ };
359353
+ case "message":
359354
+ return {
359355
+ type: "message",
359356
+ messageType: result.messageType,
359357
+ content: result.content
359358
+ };
359359
+ case "stream_messages":
359360
+ return {
359361
+ type: "stream_messages",
359362
+ messages: result.messages
359363
+ };
359364
+ /**
359365
+ * Currently return types below are never generated due to the
359366
+ * whitelist of allowed slash commands in ACP and non-interactive mode.
359367
+ * We'll try to add more supported return types in the future.
359368
+ */
359369
+ case "tool":
359370
+ return {
359371
+ type: "unsupported",
359372
+ reason: "Tool execution from slash commands is not supported in non-interactive mode.",
359373
+ originalType: "tool"
359374
+ };
359375
+ case "quit":
359376
+ return {
359377
+ type: "unsupported",
359378
+ reason: "Quit command is not supported in non-interactive mode. The process will exit naturally after completion.",
359379
+ originalType: "quit"
359380
+ };
359381
+ case "dialog":
359382
+ return {
359383
+ type: "unsupported",
359384
+ reason: `Dialog '${result.dialog}' cannot be opened in non-interactive mode.`,
359385
+ originalType: "dialog"
359386
+ };
359387
+ case "load_history":
359388
+ return {
359389
+ type: "unsupported",
359390
+ reason: "Loading history is not supported in non-interactive mode. Each invocation starts with a fresh context.",
359391
+ originalType: "load_history"
359392
+ };
359393
+ case "confirm_shell_commands":
359394
+ return {
359395
+ type: "unsupported",
359396
+ reason: "Shell command confirmation is not supported in non-interactive mode. Use YOLO mode or pre-approve commands.",
359397
+ originalType: "confirm_shell_commands"
359398
+ };
359399
+ case "confirm_action":
359400
+ return {
359401
+ type: "unsupported",
359402
+ reason: "Action confirmation is not supported in non-interactive mode. Commands requiring confirmation cannot be executed.",
359403
+ originalType: "confirm_action"
359404
+ };
359405
+ default: {
359406
+ const _exhaustive = result;
359407
+ return {
359408
+ type: "unsupported",
359409
+ reason: `Unknown command result type: ${_exhaustive.type}`,
359410
+ originalType: "unknown"
359411
+ };
359412
+ }
358490
359413
  }
358491
- return metrics2.tokens.cached / metrics2.tokens.prompt * 100;
358492
359414
  }
358493
- __name(calculateCacheHitRate, "calculateCacheHitRate");
358494
- var computeSessionStats = /* @__PURE__ */ __name((metrics2) => {
358495
- const { models, tools, files } = metrics2;
358496
- const totalApiTime = Object.values(models).reduce(
358497
- (acc, model) => acc + model.api.totalLatencyMs,
358498
- 0
359415
+ __name(handleCommandResult, "handleCommandResult");
359416
+ function filterCommandsForNonInteractive(commands, allowedBuiltinCommandNames) {
359417
+ return commands.filter((cmd) => {
359418
+ if (cmd.kind === "file" /* FILE */) {
359419
+ return true;
359420
+ }
359421
+ if (cmd.kind === "markdown" /* MARKDOWN */) {
359422
+ return true;
359423
+ }
359424
+ if (cmd.kind === "built-in" /* BUILT_IN */) {
359425
+ return allowedBuiltinCommandNames.has(cmd.name);
359426
+ }
359427
+ return false;
359428
+ });
359429
+ }
359430
+ __name(filterCommandsForNonInteractive, "filterCommandsForNonInteractive");
359431
+ var handleSlashCommand = /* @__PURE__ */ __name(async (rawQuery, abortController, config2, settings, allowedBuiltinCommandNames = [
359432
+ ...ALLOWED_BUILTIN_COMMANDS_NON_INTERACTIVE
359433
+ ]) => {
359434
+ const trimmed2 = rawQuery.trim();
359435
+ if (!trimmed2.startsWith("/")) {
359436
+ return { type: "no_command" };
359437
+ }
359438
+ const isAcpMode = config2.getExperimentalZedIntegration();
359439
+ const isInteractive = config2.isInteractive();
359440
+ const executionMode = isAcpMode ? "acp" : isInteractive ? "interactive" : "non_interactive";
359441
+ const allowedBuiltinSet = new Set(allowedBuiltinCommandNames ?? []);
359442
+ const allLoaders = [
359443
+ new BuiltinCommandLoader(config2),
359444
+ new FileCommandLoader(config2),
359445
+ new MarkdownCommandLoader(config2)
359446
+ ];
359447
+ const commandService = await CommandService.create(
359448
+ allLoaders,
359449
+ abortController.signal
358499
359450
  );
358500
- const totalToolTime = tools.totalDurationMs;
358501
- const agentActiveTime = totalApiTime + totalToolTime;
358502
- const apiTimePercent = agentActiveTime > 0 ? totalApiTime / agentActiveTime * 100 : 0;
358503
- const toolTimePercent = agentActiveTime > 0 ? totalToolTime / agentActiveTime * 100 : 0;
358504
- const totalCachedTokens = Object.values(models).reduce(
358505
- (acc, model) => acc + model.tokens.cached,
358506
- 0
359451
+ const allCommands = commandService.getCommands();
359452
+ const filteredCommands = filterCommandsForNonInteractive(
359453
+ allCommands,
359454
+ allowedBuiltinSet
358507
359455
  );
358508
- const totalPromptTokens = Object.values(models).reduce(
358509
- (acc, model) => acc + model.tokens.prompt,
358510
- 0
359456
+ const { commandToExecute, args } = parseSlashCommand(
359457
+ rawQuery,
359458
+ filteredCommands
358511
359459
  );
358512
- const cacheEfficiency = totalPromptTokens > 0 ? totalCachedTokens / totalPromptTokens * 100 : 0;
358513
- const totalDecisions = tools.totalDecisions.accept + tools.totalDecisions.reject + tools.totalDecisions.modify;
358514
- const successRate = tools.totalCalls > 0 ? tools.totalSuccess / tools.totalCalls * 100 : 0;
358515
- const agreementRate = totalDecisions > 0 ? tools.totalDecisions.accept / totalDecisions * 100 : 0;
358516
- return {
358517
- totalApiTime,
358518
- totalToolTime,
358519
- agentActiveTime,
358520
- apiTimePercent,
358521
- toolTimePercent,
358522
- cacheEfficiency,
358523
- totalDecisions,
358524
- successRate,
358525
- agreementRate,
358526
- totalCachedTokens,
358527
- totalPromptTokens,
358528
- totalLinesAdded: files.totalLinesAdded,
358529
- totalLinesRemoved: files.totalLinesRemoved
359460
+ if (!commandToExecute) {
359461
+ const { commandToExecute: knownCommand } = parseSlashCommand(
359462
+ rawQuery,
359463
+ allCommands
359464
+ );
359465
+ if (knownCommand) {
359466
+ return {
359467
+ type: "unsupported",
359468
+ reason: t4(
359469
+ 'The command "/{{command}}" is not supported in non-interactive mode.',
359470
+ { command: knownCommand.name }
359471
+ ),
359472
+ originalType: "filtered_command"
359473
+ };
359474
+ }
359475
+ return { type: "no_command" };
359476
+ }
359477
+ if (!commandToExecute.action) {
359478
+ return { type: "no_command" };
359479
+ }
359480
+ const sessionStats = {
359481
+ sessionId: config2?.getSessionId(),
359482
+ sessionStartTime: /* @__PURE__ */ new Date(),
359483
+ metrics: uiTelemetryService.getMetrics(),
359484
+ lastPromptTokenCount: 0,
359485
+ promptCount: 1
358530
359486
  };
358531
- }, "computeSessionStats");
359487
+ const logger6 = new Logger(config2?.getSessionId() || "", config2?.storage);
359488
+ const context2 = {
359489
+ executionMode,
359490
+ services: {
359491
+ config: config2,
359492
+ settings,
359493
+ git: void 0,
359494
+ logger: logger6
359495
+ },
359496
+ ui: createNonInteractiveUI(),
359497
+ session: {
359498
+ stats: sessionStats,
359499
+ sessionShellAllowlist: /* @__PURE__ */ new Set()
359500
+ },
359501
+ invocation: {
359502
+ raw: trimmed2,
359503
+ name: commandToExecute.name,
359504
+ args
359505
+ }
359506
+ };
359507
+ const result = await commandToExecute.action(context2, args);
359508
+ if (!result) {
359509
+ return {
359510
+ type: "message",
359511
+ messageType: "info",
359512
+ content: "Command executed successfully."
359513
+ };
359514
+ }
359515
+ return handleCommandResult(result);
359516
+ }, "handleSlashCommand");
359517
+ var getAvailableCommands = /* @__PURE__ */ __name(async (config2, abortSignal, allowedBuiltinCommandNames = [
359518
+ ...ALLOWED_BUILTIN_COMMANDS_NON_INTERACTIVE
359519
+ ]) => {
359520
+ try {
359521
+ const allowedBuiltinSet = new Set(allowedBuiltinCommandNames ?? []);
359522
+ const loaders = [
359523
+ new FileCommandLoader(config2),
359524
+ new MarkdownCommandLoader(config2)
359525
+ ];
359526
+ if (allowedBuiltinSet.size > 0) {
359527
+ loaders.push(new BuiltinCommandLoader(config2));
359528
+ }
359529
+ const commandService = await CommandService.create(loaders, abortSignal);
359530
+ const commands = commandService.getCommands();
359531
+ const filteredCommands = filterCommandsForNonInteractive(
359532
+ commands,
359533
+ allowedBuiltinSet
359534
+ );
359535
+ return filteredCommands.filter((cmd) => !cmd.hidden);
359536
+ } catch (error2) {
359537
+ console.error("Error loading available commands:", error2);
359538
+ return [];
359539
+ }
359540
+ }, "getAvailableCommands");
358532
359541
 
358533
359542
  // packages/cli/src/utils/nonInteractiveHelpers.ts
358534
359543
  function normalizePartList(parts) {
@@ -358593,19 +359602,15 @@ function computeUsageFromMetrics(metrics2) {
358593
359602
  return usage2;
358594
359603
  }
358595
359604
  __name(computeUsageFromMetrics, "computeUsageFromMetrics");
358596
- async function loadSlashCommandNames(config2) {
359605
+ async function loadSlashCommandNames(config2, allowedBuiltinCommandNames) {
358597
359606
  const controller = new AbortController();
358598
359607
  try {
358599
- const service = await CommandService.create(
358600
- [new BuiltinCommandLoader(config2)],
358601
- controller.signal
359608
+ const commands = await getAvailableCommands(
359609
+ config2,
359610
+ controller.signal,
359611
+ allowedBuiltinCommandNames
358602
359612
  );
358603
- const names = /* @__PURE__ */ new Set();
358604
- const commands = service.getCommands();
358605
- for (const command2 of commands) {
358606
- names.add(command2.name);
358607
- }
358608
- return Array.from(names).sort();
359613
+ return commands.map((cmd) => cmd.name).sort();
358609
359614
  } catch (error2) {
358610
359615
  if (config2.getDebugMode()) {
358611
359616
  console.error(
@@ -358619,7 +359624,7 @@ async function loadSlashCommandNames(config2) {
358619
359624
  }
358620
359625
  }
358621
359626
  __name(loadSlashCommandNames, "loadSlashCommandNames");
358622
- async function buildSystemMessage(config2, sessionId, permissionMode) {
359627
+ async function buildSystemMessage(config2, sessionId, permissionMode, allowedBuiltinCommandNames) {
358623
359628
  const toolRegistry = config2.getToolRegistry();
358624
359629
  const tools = toolRegistry ? toolRegistry.getAllToolNames() : [];
358625
359630
  const mcpServers = config2.getMcpServers();
@@ -358627,7 +359632,10 @@ async function buildSystemMessage(config2, sessionId, permissionMode) {
358627
359632
  name: name3,
358628
359633
  status: getMCPServerStatus(name3)
358629
359634
  })) : [];
358630
- const slashCommands = await loadSlashCommandNames(config2);
359635
+ const slashCommands = await loadSlashCommandNames(
359636
+ config2,
359637
+ allowedBuiltinCommandNames
359638
+ );
358631
359639
  let agentNames = [];
358632
359640
  try {
358633
359641
  const subagentManager = config2.getSubagentManager();
@@ -359880,866 +360888,6 @@ var StreamJsonOutputAdapter = class extends BaseJsonOutputAdapter {
359880
360888
  }
359881
360889
  };
359882
360890
 
359883
- // packages/cli/src/nonInteractiveCliCommands.ts
359884
- init_esbuild_shims();
359885
-
359886
- // packages/cli/src/utils/commands.ts
359887
- init_esbuild_shims();
359888
- var parseSlashCommand = /* @__PURE__ */ __name((query, commands) => {
359889
- const trimmed2 = query.trim();
359890
- const parts = trimmed2.substring(1).trim().split(/\s+/);
359891
- const commandPath = parts.filter((p2) => p2);
359892
- let currentCommands = commands;
359893
- let commandToExecute;
359894
- let pathIndex = 0;
359895
- const canonicalPath = [];
359896
- for (const part of commandPath) {
359897
- let foundCommand = currentCommands.find((cmd) => cmd.name === part);
359898
- if (!foundCommand) {
359899
- foundCommand = currentCommands.find(
359900
- (cmd) => cmd.altNames?.includes(part)
359901
- );
359902
- }
359903
- if (foundCommand) {
359904
- commandToExecute = foundCommand;
359905
- canonicalPath.push(foundCommand.name);
359906
- pathIndex++;
359907
- if (foundCommand.subCommands) {
359908
- currentCommands = foundCommand.subCommands;
359909
- } else {
359910
- break;
359911
- }
359912
- } else {
359913
- break;
359914
- }
359915
- }
359916
- const args = parts.slice(pathIndex).join(" ");
359917
- return { commandToExecute, args, canonicalPath };
359918
- }, "parseSlashCommand");
359919
-
359920
- // packages/cli/src/nonInteractiveCliCommands.ts
359921
- init_core5();
359922
-
359923
- // packages/cli/src/services/FileCommandLoader.ts
359924
- init_esbuild_shims();
359925
- var import_toml = __toESM(require_toml(), 1);
359926
- init_esm11();
359927
- init_zod();
359928
- init_core5();
359929
- import { promises as fs90 } from "node:fs";
359930
- import path98 from "node:path";
359931
-
359932
- // packages/cli/src/services/prompt-processors/argumentProcessor.ts
359933
- init_esbuild_shims();
359934
- init_core5();
359935
- var DefaultArgumentProcessor = class {
359936
- static {
359937
- __name(this, "DefaultArgumentProcessor");
359938
- }
359939
- async process(prompt, context2) {
359940
- if (context2.invocation?.args) {
359941
- return appendToLastTextPart(prompt, context2.invocation.raw);
359942
- }
359943
- return prompt;
359944
- }
359945
- };
359946
-
359947
- // packages/cli/src/services/prompt-processors/types.ts
359948
- init_esbuild_shims();
359949
- var SHORTHAND_ARGS_PLACEHOLDER = "{{args}}";
359950
- var SHELL_INJECTION_TRIGGER = "!{";
359951
- var AT_FILE_INJECTION_TRIGGER = "@{";
359952
-
359953
- // packages/cli/src/services/prompt-processors/shellProcessor.ts
359954
- init_esbuild_shims();
359955
- init_core5();
359956
-
359957
- // packages/cli/src/services/prompt-processors/injectionParser.ts
359958
- init_esbuild_shims();
359959
- function extractInjections(prompt, trigger, contextName) {
359960
- const injections = [];
359961
- let index = 0;
359962
- while (index < prompt.length) {
359963
- const startIndex = prompt.indexOf(trigger, index);
359964
- if (startIndex === -1) {
359965
- break;
359966
- }
359967
- let currentIndex = startIndex + trigger.length;
359968
- let braceCount = 1;
359969
- let foundEnd = false;
359970
- while (currentIndex < prompt.length) {
359971
- const char = prompt[currentIndex];
359972
- if (char === "{") {
359973
- braceCount++;
359974
- } else if (char === "}") {
359975
- braceCount--;
359976
- if (braceCount === 0) {
359977
- const injectionContent = prompt.substring(
359978
- startIndex + trigger.length,
359979
- currentIndex
359980
- );
359981
- const endIndex = currentIndex + 1;
359982
- injections.push({
359983
- content: injectionContent.trim(),
359984
- startIndex,
359985
- endIndex
359986
- });
359987
- index = endIndex;
359988
- foundEnd = true;
359989
- break;
359990
- }
359991
- }
359992
- currentIndex++;
359993
- }
359994
- if (!foundEnd) {
359995
- const contextInfo = contextName ? ` in command '${contextName}'` : "";
359996
- throw new Error(
359997
- `Invalid syntax${contextInfo}: Unclosed injection starting at index ${startIndex} ('${trigger}'). Ensure braces are balanced. Paths or commands with unbalanced braces are not supported directly.`
359998
- );
359999
- }
360000
- }
360001
- return injections;
360002
- }
360003
- __name(extractInjections, "extractInjections");
360004
-
360005
- // packages/cli/src/services/prompt-processors/shellProcessor.ts
360006
- var ConfirmationRequiredError = class extends Error {
360007
- constructor(message, commandsToConfirm) {
360008
- super(message);
360009
- this.commandsToConfirm = commandsToConfirm;
360010
- this.name = "ConfirmationRequiredError";
360011
- }
360012
- static {
360013
- __name(this, "ConfirmationRequiredError");
360014
- }
360015
- };
360016
- var ShellProcessor = class {
360017
- constructor(commandName) {
360018
- this.commandName = commandName;
360019
- }
360020
- static {
360021
- __name(this, "ShellProcessor");
360022
- }
360023
- async process(prompt, context2) {
360024
- return flatMapTextParts(
360025
- prompt,
360026
- (text) => this.processString(text, context2)
360027
- );
360028
- }
360029
- async processString(prompt, context2) {
360030
- const userArgsRaw = context2.invocation?.args || "";
360031
- if (!prompt.includes(SHELL_INJECTION_TRIGGER)) {
360032
- return [
360033
- { text: prompt.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsRaw) }
360034
- ];
360035
- }
360036
- const config2 = context2.services.config;
360037
- if (!config2) {
360038
- throw new Error(
360039
- `Security configuration not loaded. Cannot verify shell command permissions for '${this.commandName}'. Aborting.`
360040
- );
360041
- }
360042
- const { sessionShellAllowlist } = context2.session;
360043
- const injections = extractInjections(
360044
- prompt,
360045
- SHELL_INJECTION_TRIGGER,
360046
- this.commandName
360047
- );
360048
- if (injections.length === 0) {
360049
- return [
360050
- { text: prompt.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsRaw) }
360051
- ];
360052
- }
360053
- const { shell: shell2 } = getShellConfiguration();
360054
- const userArgsEscaped = escapeShellArg(userArgsRaw, shell2);
360055
- const resolvedInjections = injections.map(
360056
- (injection) => {
360057
- const command2 = injection.content;
360058
- if (command2 === "") {
360059
- return { ...injection, resolvedCommand: void 0 };
360060
- }
360061
- const resolvedCommand = command2.replaceAll(
360062
- SHORTHAND_ARGS_PLACEHOLDER,
360063
- userArgsEscaped
360064
- );
360065
- return { ...injection, resolvedCommand };
360066
- }
360067
- );
360068
- const commandsToConfirm = /* @__PURE__ */ new Set();
360069
- for (const injection of resolvedInjections) {
360070
- const command2 = injection.resolvedCommand;
360071
- if (!command2) continue;
360072
- const { allAllowed, disallowedCommands, blockReason, isHardDenial } = checkCommandPermissions(command2, config2, sessionShellAllowlist);
360073
- if (!allAllowed) {
360074
- if (isHardDenial) {
360075
- throw new Error(
360076
- `${this.commandName} cannot be run. Blocked command: "${command2}". Reason: ${blockReason || "Blocked by configuration."}`
360077
- );
360078
- }
360079
- if (config2.getApprovalMode() !== "yolo" /* YOLO */) {
360080
- disallowedCommands.forEach((uc) => commandsToConfirm.add(uc));
360081
- }
360082
- }
360083
- }
360084
- if (commandsToConfirm.size > 0) {
360085
- throw new ConfirmationRequiredError(
360086
- "Shell command confirmation required",
360087
- Array.from(commandsToConfirm)
360088
- );
360089
- }
360090
- let processedPrompt = "";
360091
- let lastIndex = 0;
360092
- for (const injection of resolvedInjections) {
360093
- const segment = prompt.substring(lastIndex, injection.startIndex);
360094
- processedPrompt += segment.replaceAll(
360095
- SHORTHAND_ARGS_PLACEHOLDER,
360096
- userArgsRaw
360097
- );
360098
- if (injection.resolvedCommand) {
360099
- const activeTheme = themeManager.getActiveTheme();
360100
- const shellExecutionConfig = {
360101
- ...config2.getShellExecutionConfig(),
360102
- defaultFg: activeTheme.colors.Foreground,
360103
- defaultBg: activeTheme.colors.Background
360104
- };
360105
- const { result } = await ShellExecutionService.execute(
360106
- injection.resolvedCommand,
360107
- config2.getTargetDir(),
360108
- () => {
360109
- },
360110
- new AbortController().signal,
360111
- config2.getShouldUseNodePtyShell(),
360112
- shellExecutionConfig
360113
- );
360114
- const executionResult = await result;
360115
- if (executionResult.error && !executionResult.aborted) {
360116
- throw new Error(
360117
- `Failed to start shell command in '${this.commandName}': ${executionResult.error.message}. Command: ${injection.resolvedCommand}`
360118
- );
360119
- }
360120
- processedPrompt += executionResult.output;
360121
- if (executionResult.aborted) {
360122
- processedPrompt += `
360123
- [Shell command '${injection.resolvedCommand}' aborted]`;
360124
- } else if (executionResult.exitCode !== 0 && executionResult.exitCode !== null) {
360125
- processedPrompt += `
360126
- [Shell command '${injection.resolvedCommand}' exited with code ${executionResult.exitCode}]`;
360127
- } else if (executionResult.signal !== null) {
360128
- processedPrompt += `
360129
- [Shell command '${injection.resolvedCommand}' terminated by signal ${executionResult.signal}]`;
360130
- }
360131
- }
360132
- lastIndex = injection.endIndex;
360133
- }
360134
- const finalSegment = prompt.substring(lastIndex);
360135
- processedPrompt += finalSegment.replaceAll(
360136
- SHORTHAND_ARGS_PLACEHOLDER,
360137
- userArgsRaw
360138
- );
360139
- return [{ text: processedPrompt }];
360140
- }
360141
- };
360142
-
360143
- // packages/cli/src/services/prompt-processors/atFileProcessor.ts
360144
- init_esbuild_shims();
360145
- init_core5();
360146
- var AtFileProcessor = class {
360147
- constructor(commandName) {
360148
- this.commandName = commandName;
360149
- }
360150
- static {
360151
- __name(this, "AtFileProcessor");
360152
- }
360153
- async process(input, context2) {
360154
- const config2 = context2.services.config;
360155
- if (!config2) {
360156
- return input;
360157
- }
360158
- return flatMapTextParts(input, async (text) => {
360159
- if (!text.includes(AT_FILE_INJECTION_TRIGGER)) {
360160
- return [{ text }];
360161
- }
360162
- const injections = extractInjections(
360163
- text,
360164
- AT_FILE_INJECTION_TRIGGER,
360165
- this.commandName
360166
- );
360167
- if (injections.length === 0) {
360168
- return [{ text }];
360169
- }
360170
- const output = [];
360171
- let lastIndex = 0;
360172
- for (const injection of injections) {
360173
- const prefix = text.substring(lastIndex, injection.startIndex);
360174
- if (prefix) {
360175
- output.push({ text: prefix });
360176
- }
360177
- const pathStr = injection.content;
360178
- try {
360179
- const fileContentParts = await readPathFromWorkspace(pathStr, config2);
360180
- if (fileContentParts.length === 0) {
360181
- const uiMessage = `File '@{${pathStr}}' was ignored by .gitignore or .rdmindignore and was not included in the prompt.`;
360182
- context2.ui.addItem(
360183
- { type: "info" /* INFO */, text: uiMessage },
360184
- Date.now()
360185
- );
360186
- }
360187
- output.push(...fileContentParts);
360188
- } catch (error2) {
360189
- const message = error2 instanceof Error ? error2.message : String(error2);
360190
- const uiMessage = `Failed to inject content for '@{${pathStr}}': ${message}`;
360191
- console.error(
360192
- `[AtFileProcessor] ${uiMessage}. Leaving placeholder in prompt.`
360193
- );
360194
- context2.ui.addItem(
360195
- { type: "error" /* ERROR */, text: uiMessage },
360196
- Date.now()
360197
- );
360198
- const placeholder = text.substring(
360199
- injection.startIndex,
360200
- injection.endIndex
360201
- );
360202
- output.push({ text: placeholder });
360203
- }
360204
- lastIndex = injection.endIndex;
360205
- }
360206
- const suffix = text.substring(lastIndex);
360207
- if (suffix) {
360208
- output.push({ text: suffix });
360209
- }
360210
- return output;
360211
- });
360212
- }
360213
- };
360214
-
360215
- // packages/cli/src/services/FileCommandLoader.ts
360216
- var TomlCommandDefSchema = external_exports.object({
360217
- prompt: external_exports.string({
360218
- required_error: "The 'prompt' field is required.",
360219
- invalid_type_error: "The 'prompt' field must be a string."
360220
- }),
360221
- description: external_exports.string().optional()
360222
- });
360223
- var FileCommandLoader = class {
360224
- constructor(config2) {
360225
- this.config = config2;
360226
- this.folderTrustEnabled = !!config2?.getFolderTrustFeature();
360227
- this.folderTrust = !!config2?.getFolderTrust();
360228
- this.projectRoot = config2?.getProjectRoot() || process.cwd();
360229
- }
360230
- static {
360231
- __name(this, "FileCommandLoader");
360232
- }
360233
- projectRoot;
360234
- folderTrustEnabled;
360235
- folderTrust;
360236
- /**
360237
- * Loads all commands from user, project, and extension directories.
360238
- * Returns commands in order: user → project → extensions (alphabetically).
360239
- *
360240
- * Order is important for conflict resolution in CommandService:
360241
- * - User/project commands (without extensionName) use "last wins" strategy
360242
- * - Extension commands (with extensionName) get renamed if conflicts exist
360243
- *
360244
- * @param signal An AbortSignal to cancel the loading process.
360245
- * @returns A promise that resolves to an array of all loaded SlashCommands.
360246
- */
360247
- async loadCommands(signal) {
360248
- const allCommands = [];
360249
- const globOptions = {
360250
- nodir: true,
360251
- dot: true,
360252
- signal,
360253
- follow: true
360254
- };
360255
- const commandDirs = this.getCommandDirectories();
360256
- for (const dirInfo of commandDirs) {
360257
- try {
360258
- const files = await glob("**/*.toml", {
360259
- ...globOptions,
360260
- cwd: dirInfo.path
360261
- });
360262
- if (this.folderTrustEnabled && !this.folderTrust) {
360263
- return [];
360264
- }
360265
- const commandPromises = files.map(
360266
- (file) => this.parseAndAdaptFile(
360267
- path98.join(dirInfo.path, file),
360268
- dirInfo.path,
360269
- dirInfo.extensionName
360270
- )
360271
- );
360272
- const commands = (await Promise.all(commandPromises)).filter(
360273
- (cmd) => cmd !== null
360274
- );
360275
- allCommands.push(...commands);
360276
- } catch (error2) {
360277
- const isEnoent = error2.code === "ENOENT";
360278
- const isAbortError2 = error2 instanceof Error && error2.name === "AbortError";
360279
- if (!isEnoent && !isAbortError2) {
360280
- console.error(
360281
- `[FileCommandLoader] Error loading commands from ${dirInfo.path}:`,
360282
- error2
360283
- );
360284
- }
360285
- }
360286
- }
360287
- return allCommands;
360288
- }
360289
- /**
360290
- * Get all command directories in order for loading.
360291
- * User commands → Project commands → Extension commands
360292
- * This order ensures extension commands can detect all conflicts.
360293
- */
360294
- getCommandDirectories() {
360295
- const dirs = [];
360296
- const storage = this.config?.storage ?? new Storage(this.projectRoot);
360297
- dirs.push({ path: Storage.getUserCommandsDir() });
360298
- dirs.push({ path: storage.getProjectCommandsDir() });
360299
- if (this.config) {
360300
- const activeExtensions = this.config.getExtensions().filter((ext2) => ext2.isActive).sort((a2, b2) => a2.name.localeCompare(b2.name));
360301
- const extensionCommandDirs = activeExtensions.map((ext2) => ({
360302
- path: path98.join(ext2.path, "commands"),
360303
- extensionName: ext2.name
360304
- }));
360305
- dirs.push(...extensionCommandDirs);
360306
- }
360307
- return dirs;
360308
- }
360309
- /**
360310
- * Parses a single .toml file and transforms it into a SlashCommand object.
360311
- * @param filePath The absolute path to the .toml file.
360312
- * @param baseDir The root command directory for name calculation.
360313
- * @param extensionName Optional extension name to prefix commands with.
360314
- * @returns A promise resolving to a SlashCommand, or null if the file is invalid.
360315
- */
360316
- async parseAndAdaptFile(filePath, baseDir, extensionName) {
360317
- let fileContent;
360318
- try {
360319
- fileContent = await fs90.readFile(filePath, "utf-8");
360320
- } catch (error2) {
360321
- console.error(
360322
- `[FileCommandLoader] Failed to read file ${filePath}:`,
360323
- error2 instanceof Error ? error2.message : String(error2)
360324
- );
360325
- return null;
360326
- }
360327
- let parsed;
360328
- try {
360329
- parsed = import_toml.default.parse(fileContent);
360330
- } catch (error2) {
360331
- console.error(
360332
- `[FileCommandLoader] Failed to parse TOML file ${filePath}:`,
360333
- error2 instanceof Error ? error2.message : String(error2)
360334
- );
360335
- return null;
360336
- }
360337
- const validationResult = TomlCommandDefSchema.safeParse(parsed);
360338
- if (!validationResult.success) {
360339
- console.error(
360340
- `[FileCommandLoader] Skipping invalid command file: ${filePath}. Validation errors:`,
360341
- validationResult.error.flatten()
360342
- );
360343
- return null;
360344
- }
360345
- const validDef = validationResult.data;
360346
- const relativePathWithExt = path98.relative(baseDir, filePath);
360347
- const relativePath = relativePathWithExt.substring(
360348
- 0,
360349
- relativePathWithExt.length - 5
360350
- // length of '.toml'
360351
- );
360352
- const baseCommandName = relativePath.split(path98.sep).map((segment) => segment.replaceAll(":", "_")).join(":");
360353
- const defaultDescription = `Custom command from ${path98.basename(filePath)}`;
360354
- let description = validDef.description || defaultDescription;
360355
- if (extensionName) {
360356
- description = `[${extensionName}] ${description}`;
360357
- }
360358
- const processors = [];
360359
- const usesArgs = validDef.prompt.includes(SHORTHAND_ARGS_PLACEHOLDER);
360360
- const usesShellInjection = validDef.prompt.includes(
360361
- SHELL_INJECTION_TRIGGER
360362
- );
360363
- const usesAtFileInjection = validDef.prompt.includes(
360364
- AT_FILE_INJECTION_TRIGGER
360365
- );
360366
- if (usesAtFileInjection) {
360367
- processors.push(new AtFileProcessor(baseCommandName));
360368
- }
360369
- if (usesShellInjection || usesArgs) {
360370
- processors.push(new ShellProcessor(baseCommandName));
360371
- }
360372
- if (!usesArgs) {
360373
- processors.push(new DefaultArgumentProcessor());
360374
- }
360375
- return {
360376
- name: baseCommandName,
360377
- description,
360378
- kind: "file" /* FILE */,
360379
- extensionName,
360380
- action: /* @__PURE__ */ __name(async (context2, _args) => {
360381
- if (!context2.invocation) {
360382
- console.error(
360383
- `[FileCommandLoader] Critical error: Command '${baseCommandName}' was executed without invocation context.`
360384
- );
360385
- return {
360386
- type: "submit_prompt",
360387
- content: [{ text: validDef.prompt }]
360388
- // Fallback to unprocessed prompt
360389
- };
360390
- }
360391
- try {
360392
- let processedContent = [
360393
- { text: validDef.prompt }
360394
- ];
360395
- for (const processor of processors) {
360396
- processedContent = await processor.process(
360397
- processedContent,
360398
- context2
360399
- );
360400
- }
360401
- return {
360402
- type: "submit_prompt",
360403
- content: processedContent
360404
- };
360405
- } catch (e4) {
360406
- if (e4 instanceof ConfirmationRequiredError) {
360407
- return {
360408
- type: "confirm_shell_commands",
360409
- commandsToConfirm: e4.commandsToConfirm,
360410
- originalInvocation: {
360411
- raw: context2.invocation.raw
360412
- }
360413
- };
360414
- }
360415
- throw e4;
360416
- }
360417
- }, "action")
360418
- };
360419
- }
360420
- };
360421
-
360422
- // packages/cli/src/services/MarkdownCommandLoader.ts
360423
- init_esbuild_shims();
360424
- init_esm11();
360425
- init_zod();
360426
- import { promises as fs91 } from "node:fs";
360427
- import path99 from "node:path";
360428
- var MarkdownCommandDefSchema = external_exports.object({
360429
- name: external_exports.string(),
360430
- id: external_exports.string().optional(),
360431
- category: external_exports.string().optional(),
360432
- description: external_exports.string()
360433
- });
360434
- var MarkdownCommandLoader = class {
360435
- static {
360436
- __name(this, "MarkdownCommandLoader");
360437
- }
360438
- projectRoot;
360439
- folderTrustEnabled;
360440
- folderTrust;
360441
- constructor(config2) {
360442
- this.folderTrustEnabled = !!config2?.getFolderTrustFeature();
360443
- this.folderTrust = !!config2?.getFolderTrust();
360444
- this.projectRoot = config2?.getProjectRoot() || process.cwd();
360445
- }
360446
- /**
360447
- * Loads all markdown commands from OpenSpec directories.
360448
- */
360449
- async loadCommands(signal) {
360450
- if (this.folderTrustEnabled && !this.folderTrust) {
360451
- return [];
360452
- }
360453
- const allCommands = [];
360454
- const globOptions = {
360455
- nodir: true,
360456
- dot: true,
360457
- signal,
360458
- follow: true
360459
- };
360460
- const commandDirs = this.getOpenSpecCommandDirectories();
360461
- for (const dirPath of commandDirs) {
360462
- try {
360463
- const files = await glob("**/*.md", {
360464
- ...globOptions,
360465
- cwd: dirPath
360466
- });
360467
- const commandPromises = files.map(
360468
- (file) => this.parseAndAdaptFile(path99.join(dirPath, file))
360469
- );
360470
- const commands = (await Promise.all(commandPromises)).filter(
360471
- (cmd) => cmd !== null
360472
- );
360473
- allCommands.push(...commands);
360474
- } catch (error2) {
360475
- const isEnoent = error2.code === "ENOENT";
360476
- const isAbortError2 = error2 instanceof Error && error2.name === "AbortError";
360477
- if (!isEnoent && !isAbortError2) {
360478
- console.error(
360479
- `[MarkdownCommandLoader] Error loading commands from ${dirPath}:`,
360480
- error2
360481
- );
360482
- }
360483
- }
360484
- }
360485
- return allCommands;
360486
- }
360487
- /**
360488
- * Get directories containing OpenSpec markdown command files.
360489
- */
360490
- getOpenSpecCommandDirectories() {
360491
- const rdmindCommandsDir = path99.join(
360492
- this.projectRoot,
360493
- ".rdmind",
360494
- "commands"
360495
- );
360496
- return [rdmindCommandsDir];
360497
- }
360498
- /**
360499
- * Parses a markdown file with YAML front matter and converts it to a SlashCommand.
360500
- */
360501
- async parseAndAdaptFile(filePath) {
360502
- let fileContent;
360503
- try {
360504
- fileContent = await fs91.readFile(filePath, "utf-8");
360505
- } catch (error2) {
360506
- console.error(
360507
- `[MarkdownCommandLoader] Failed to read file ${filePath}:`,
360508
- error2 instanceof Error ? error2.message : String(error2)
360509
- );
360510
- return null;
360511
- }
360512
- const frontMatterResult = this.parseFrontMatter(fileContent);
360513
- if (!frontMatterResult) {
360514
- return null;
360515
- }
360516
- const { frontMatter, content } = frontMatterResult;
360517
- const validationResult = MarkdownCommandDefSchema.safeParse(frontMatter);
360518
- if (!validationResult.success) {
360519
- console.error(
360520
- `[MarkdownCommandLoader] Invalid front matter in ${filePath}:`,
360521
- validationResult.error.flatten()
360522
- );
360523
- return null;
360524
- }
360525
- const validDef = validationResult.data;
360526
- const commandName = validDef.name.startsWith("/") ? validDef.name.substring(1) : validDef.name;
360527
- let description = validDef.description;
360528
- if (commandName === "openspec-proposal") {
360529
- description = t4("Scaffold a new OpenSpec change and validate strictly.");
360530
- } else if (commandName === "openspec-apply") {
360531
- description = t4(
360532
- "Implement an approved OpenSpec change and keep tasks in sync."
360533
- );
360534
- } else if (commandName === "openspec-archive") {
360535
- description = t4("Archive a deployed OpenSpec change and update specs.");
360536
- }
360537
- return {
360538
- name: commandName,
360539
- description,
360540
- kind: "file" /* FILE */,
360541
- action: /* @__PURE__ */ __name(async (context2, args) => {
360542
- const prompt = content.trim() + (args ? `
360543
-
360544
- ${args}` : "");
360545
- return {
360546
- type: "submit_prompt",
360547
- content: [{ text: prompt }]
360548
- };
360549
- }, "action")
360550
- };
360551
- }
360552
- /**
360553
- * Parses YAML front matter from markdown content.
360554
- */
360555
- parseFrontMatter(content) {
360556
- const lines = content.split("\n");
360557
- if (lines[0]?.trim() !== "---") {
360558
- return null;
360559
- }
360560
- let endIndex = -1;
360561
- for (let i3 = 1; i3 < lines.length; i3++) {
360562
- if (lines[i3]?.trim() === "---") {
360563
- endIndex = i3;
360564
- break;
360565
- }
360566
- }
360567
- if (endIndex === -1) {
360568
- return null;
360569
- }
360570
- const frontMatterLines = lines.slice(1, endIndex);
360571
- const contentLines = lines.slice(endIndex + 1);
360572
- try {
360573
- const frontMatter = {};
360574
- for (const line of frontMatterLines) {
360575
- const trimmed2 = line.trim();
360576
- if (trimmed2 && !trimmed2.startsWith("#")) {
360577
- const colonIndex = trimmed2.indexOf(":");
360578
- if (colonIndex > 0) {
360579
- const key = trimmed2.substring(0, colonIndex).trim();
360580
- const value = trimmed2.substring(colonIndex + 1).trim();
360581
- frontMatter[key] = value;
360582
- }
360583
- }
360584
- }
360585
- return {
360586
- frontMatter,
360587
- content: contentLines.join("\n")
360588
- };
360589
- } catch (error2) {
360590
- console.error("Failed to parse front matter:", error2);
360591
- return null;
360592
- }
360593
- }
360594
- };
360595
-
360596
- // packages/cli/src/ui/noninteractive/nonInteractiveUi.ts
360597
- init_esbuild_shims();
360598
- function createNonInteractiveUI() {
360599
- return {
360600
- addItem: /* @__PURE__ */ __name((_item, _timestamp) => 0, "addItem"),
360601
- clear: /* @__PURE__ */ __name(() => {
360602
- }, "clear"),
360603
- setDebugMessage: /* @__PURE__ */ __name((_message) => {
360604
- }, "setDebugMessage"),
360605
- loadHistory: /* @__PURE__ */ __name((_newHistory) => {
360606
- }, "loadHistory"),
360607
- pendingItem: null,
360608
- setPendingItem: /* @__PURE__ */ __name((_item) => {
360609
- }, "setPendingItem"),
360610
- toggleVimEnabled: /* @__PURE__ */ __name(async () => false, "toggleVimEnabled"),
360611
- setGeminiMdFileCount: /* @__PURE__ */ __name((_count) => {
360612
- }, "setGeminiMdFileCount"),
360613
- reloadCommands: /* @__PURE__ */ __name(() => {
360614
- }, "reloadCommands"),
360615
- extensionsUpdateState: /* @__PURE__ */ new Map(),
360616
- dispatchExtensionStateUpdate: /* @__PURE__ */ __name((_action) => {
360617
- }, "dispatchExtensionStateUpdate"),
360618
- addConfirmUpdateExtensionRequest: /* @__PURE__ */ __name((_request) => {
360619
- }, "addConfirmUpdateExtensionRequest")
360620
- };
360621
- }
360622
- __name(createNonInteractiveUI, "createNonInteractiveUI");
360623
-
360624
- // packages/cli/src/nonInteractiveCliCommands.ts
360625
- function filterCommandsForNonInteractive(commands, allowedBuiltinCommandNames) {
360626
- return commands.filter((cmd) => {
360627
- if (cmd.kind === "file" /* FILE */) {
360628
- return true;
360629
- }
360630
- if (cmd.kind === "markdown" /* MARKDOWN */) {
360631
- return true;
360632
- }
360633
- if (cmd.kind === "built-in" /* BUILT_IN */) {
360634
- return allowedBuiltinCommandNames.has(cmd.name);
360635
- }
360636
- return false;
360637
- });
360638
- }
360639
- __name(filterCommandsForNonInteractive, "filterCommandsForNonInteractive");
360640
- var handleSlashCommand = /* @__PURE__ */ __name(async (rawQuery, abortController, config2, settings, allowedBuiltinCommandNames) => {
360641
- const trimmed2 = rawQuery.trim();
360642
- if (!trimmed2.startsWith("/")) {
360643
- return;
360644
- }
360645
- const allowedBuiltinSet = new Set(allowedBuiltinCommandNames ?? []);
360646
- const loaders = [
360647
- new FileCommandLoader(config2),
360648
- new MarkdownCommandLoader(config2)
360649
- ];
360650
- if (allowedBuiltinSet.size > 0) {
360651
- loaders.push(new BuiltinCommandLoader(config2));
360652
- }
360653
- const commandService = await CommandService.create(
360654
- loaders,
360655
- abortController.signal
360656
- );
360657
- const commands = commandService.getCommands();
360658
- const filteredCommands = filterCommandsForNonInteractive(
360659
- commands,
360660
- allowedBuiltinSet
360661
- );
360662
- const { commandToExecute, args } = parseSlashCommand(
360663
- rawQuery,
360664
- filteredCommands
360665
- );
360666
- if (commandToExecute) {
360667
- if (commandToExecute.action) {
360668
- const sessionStats = {
360669
- sessionId: config2?.getSessionId(),
360670
- sessionStartTime: /* @__PURE__ */ new Date(),
360671
- metrics: uiTelemetryService.getMetrics(),
360672
- lastPromptTokenCount: 0,
360673
- promptCount: 1
360674
- };
360675
- const logger6 = new Logger(config2?.getSessionId() || "", config2?.storage);
360676
- const context2 = {
360677
- services: {
360678
- config: config2,
360679
- settings,
360680
- git: void 0,
360681
- logger: logger6
360682
- },
360683
- ui: createNonInteractiveUI(),
360684
- session: {
360685
- stats: sessionStats,
360686
- sessionShellAllowlist: /* @__PURE__ */ new Set()
360687
- },
360688
- invocation: {
360689
- raw: trimmed2,
360690
- name: commandToExecute.name,
360691
- args
360692
- }
360693
- };
360694
- const result = await commandToExecute.action(context2, args);
360695
- if (result) {
360696
- switch (result.type) {
360697
- case "submit_prompt":
360698
- return result.content;
360699
- case "message":
360700
- if (result.messageType === "info") {
360701
- console.log(result.content);
360702
- } else {
360703
- console.error(result.content);
360704
- }
360705
- return;
360706
- case "confirm_shell_commands":
360707
- throw new FatalInputError(
360708
- "Exiting due to a confirmation prompt requested by the command."
360709
- );
360710
- default:
360711
- throw new FatalInputError(
360712
- "Exiting due to command result that is not supported in non-interactive mode."
360713
- );
360714
- }
360715
- }
360716
- }
360717
- }
360718
- return;
360719
- }, "handleSlashCommand");
360720
- var getAvailableCommands = /* @__PURE__ */ __name(async (config2, settings, abortSignal, allowedBuiltinCommandNames) => {
360721
- try {
360722
- const allowedBuiltinSet = new Set(allowedBuiltinCommandNames ?? []);
360723
- const loaders = [
360724
- new FileCommandLoader(config2),
360725
- new MarkdownCommandLoader(config2)
360726
- ];
360727
- if (allowedBuiltinSet.size > 0) {
360728
- loaders.push(new BuiltinCommandLoader(config2));
360729
- }
360730
- const commandService = await CommandService.create(loaders, abortSignal);
360731
- const commands = commandService.getCommands();
360732
- const filteredCommands = filterCommandsForNonInteractive(
360733
- commands,
360734
- allowedBuiltinSet
360735
- );
360736
- return filteredCommands.filter((cmd) => !cmd.hidden);
360737
- } catch (error2) {
360738
- console.error("Error loading available commands:", error2);
360739
- return [];
360740
- }
360741
- }, "getAvailableCommands");
360742
-
360743
360891
  // packages/cli/src/ui/hooks/atCommandProcessor.ts
360744
360892
  init_esbuild_shims();
360745
360893
  init_core5();
@@ -361081,6 +361229,36 @@ __name(handleAtCommand, "handleAtCommand");
361081
361229
 
361082
361230
  // packages/cli/src/nonInteractiveCli.ts
361083
361231
  init_errors7();
361232
+ async function emitNonInteractiveFinalMessage(params) {
361233
+ const { message, isError, adapter, config: config2 } = params;
361234
+ if (!adapter) {
361235
+ const target = isError ? process.stderr : process.stdout;
361236
+ target.write(`${message}
361237
+ `);
361238
+ return;
361239
+ }
361240
+ adapter.startAssistantMessage();
361241
+ adapter.processEvent({
361242
+ type: "content" /* Content */,
361243
+ value: message
361244
+ });
361245
+ adapter.finalizeAssistantMessage();
361246
+ const metrics2 = uiTelemetryService.getMetrics();
361247
+ const usage2 = computeUsageFromMetrics(metrics2);
361248
+ const outputFormat = config2.getOutputFormat();
361249
+ const stats = outputFormat === "json" /* JSON */ ? uiTelemetryService.getMetrics() : void 0;
361250
+ adapter.emitResult({
361251
+ isError,
361252
+ durationMs: Date.now() - params.startTimeMs,
361253
+ apiDurationMs: 0,
361254
+ numTurns: 0,
361255
+ errorMessage: isError ? message : void 0,
361256
+ usage: usage2,
361257
+ stats,
361258
+ summary: message
361259
+ });
361260
+ }
361261
+ __name(emitNonInteractiveFinalMessage, "emitNonInteractiveFinalMessage");
361084
361262
  async function runNonInteractive(config2, settings, input, prompt_id, options2 = {}) {
361085
361263
  return promptIdContext.run(prompt_id, async () => {
361086
361264
  let adapter;
@@ -361118,6 +361296,14 @@ async function runNonInteractive(config2, settings, input, prompt_id, options2 =
361118
361296
  process.stdout.on("error", stdoutErrorHandler);
361119
361297
  process.on("SIGINT", shutdownHandler);
361120
361298
  process.on("SIGTERM", shutdownHandler);
361299
+ if (adapter) {
361300
+ const systemMessage = await buildSystemMessage(
361301
+ config2,
361302
+ sessionId,
361303
+ permissionMode
361304
+ );
361305
+ adapter.emitMessage(systemMessage);
361306
+ }
361121
361307
  let initialPartList = extractPartsFromUserMessage(
361122
361308
  options2.userMessage
361123
361309
  );
@@ -361130,9 +361316,43 @@ async function runNonInteractive(config2, settings, input, prompt_id, options2 =
361130
361316
  config2,
361131
361317
  settings
361132
361318
  );
361133
- if (slashCommandResult) {
361134
- initialPartList = slashCommandResult;
361135
- slashHandled = true;
361319
+ switch (slashCommandResult.type) {
361320
+ case "submit_prompt":
361321
+ initialPartList = slashCommandResult.content;
361322
+ slashHandled = true;
361323
+ break;
361324
+ case "message": {
361325
+ await emitNonInteractiveFinalMessage({
361326
+ message: slashCommandResult.content,
361327
+ isError: slashCommandResult.messageType === "error",
361328
+ adapter,
361329
+ config: config2,
361330
+ startTimeMs: startTime
361331
+ });
361332
+ return;
361333
+ }
361334
+ case "stream_messages":
361335
+ throw new FatalInputError(
361336
+ "Stream messages mode is not supported in non-interactive CLI"
361337
+ );
361338
+ case "unsupported": {
361339
+ await emitNonInteractiveFinalMessage({
361340
+ message: slashCommandResult.reason,
361341
+ isError: true,
361342
+ adapter,
361343
+ config: config2,
361344
+ startTimeMs: startTime
361345
+ });
361346
+ return;
361347
+ }
361348
+ case "no_command":
361349
+ break;
361350
+ default: {
361351
+ const _exhaustive = slashCommandResult;
361352
+ throw new FatalInputError(
361353
+ `Unhandled slash command result type: ${_exhaustive.type}`
361354
+ );
361355
+ }
361136
361356
  }
361137
361357
  }
361138
361358
  if (!slashHandled) {
@@ -361158,14 +361378,6 @@ async function runNonInteractive(config2, settings, input, prompt_id, options2 =
361158
361378
  }
361159
361379
  const initialParts = normalizePartList(initialPartList);
361160
361380
  let currentMessages = [{ role: "user", parts: initialParts }];
361161
- if (adapter) {
361162
- const systemMessage = await buildSystemMessage(
361163
- config2,
361164
- sessionId,
361165
- permissionMode
361166
- );
361167
- adapter.emitMessage(systemMessage);
361168
- }
361169
361381
  let isFirstTurn = true;
361170
361382
  while (true) {
361171
361383
  turnCount++;
@@ -361846,7 +362058,7 @@ var SystemController = class extends BaseController {
361846
362058
  };
361847
362059
  }
361848
362060
  /**
361849
- * Load slash command names using CommandService
362061
+ * Load slash command names using getAvailableCommands
361850
362062
  *
361851
362063
  * @param signal - AbortSignal to respect for cancellation
361852
362064
  * @returns Promise resolving to array of slash command names
@@ -361856,19 +362068,11 @@ var SystemController = class extends BaseController {
361856
362068
  return [];
361857
362069
  }
361858
362070
  try {
361859
- const service = await CommandService.create(
361860
- [new BuiltinCommandLoader(this.context.config)],
361861
- signal
361862
- );
362071
+ const commands = await getAvailableCommands(this.context.config, signal);
361863
362072
  if (signal.aborted) {
361864
362073
  return [];
361865
362074
  }
361866
- const names = /* @__PURE__ */ new Set();
361867
- const commands = service.getCommands();
361868
- for (const command2 of commands) {
361869
- names.add(command2.name);
361870
- }
361871
- return Array.from(names).sort();
362075
+ return commands.map((cmd) => cmd.name).sort();
361872
362076
  } catch (error2) {
361873
362077
  if (signal.aborted) {
361874
362078
  return [];
@@ -390188,13 +390392,6 @@ var import_react82 = __toESM(require_react(), 1);
390188
390392
  // packages/cli/src/config/xhsSsoProviders.ts
390189
390393
  init_esbuild_shims();
390190
390394
  var XHS_SSO_MODELS = [
390191
- {
390192
- id: "kimi-k2-turbo-preview",
390193
- displayName: "kimi-k2-turbo-preview",
390194
- baseUrl: "https://runway.devops.xiaohongshu.com/openai/moonshot/v1",
390195
- contextWindow: "256K",
390196
- description: "kimi k2 \u7684\u9AD8\u901F\u7248\u672C"
390197
- },
390198
390395
  {
390199
390396
  id: "qwen3-coder-plus",
390200
390397
  displayName: "qwen3-coder-plus",
@@ -390236,6 +390433,13 @@ var XHS_SSO_MODELS = [
390236
390433
  baseUrl: "https://runway.devops.rednote.life/openai/google/v1",
390237
390434
  contextWindow: "1M",
390238
390435
  description: "Google \u9AD8\u901F\u667A\u80FD\u6A21\u578B(\u601D\u8003\u65F6\u95F4\u957F)"
390436
+ },
390437
+ {
390438
+ id: "glm-4.7",
390439
+ displayName: "glm-4.7",
390440
+ baseUrl: "https://runway.devops.xiaohongshu.com/openai/zhipu/paas/v4/",
390441
+ contextWindow: "200K",
390442
+ description: "\u667A\u8C31\u6700\u65B0\u65D7\u8230\u6A21\u578B\uFF0C\u9762\u5411 Agentic Coding \u573A\u666F\u5F3A\u5316"
390239
390443
  }
390240
390444
  ];
390241
390445
 
@@ -396127,6 +396331,11 @@ var useSlashCommandProcessor = /* @__PURE__ */ __name((config2, settings, addIte
396127
396331
  true
396128
396332
  );
396129
396333
  }
396334
+ case "stream_messages": {
396335
+ throw new Error(
396336
+ "stream_messages result type is not supported in interactive mode"
396337
+ );
396338
+ }
396130
396339
  default: {
396131
396340
  const unhandled = result;
396132
396341
  throw new Error(
@@ -398821,10 +399030,13 @@ var WITTY_LOADING_PHRASES = [
398821
399030
  ];
398822
399031
  var PHRASE_CHANGE_INTERVAL_MS = 15e3;
398823
399032
  var usePhraseCycler = /* @__PURE__ */ __name((isActive, isWaiting, customPhrases) => {
398824
- const loadingPhrases = (0, import_react120.useMemo)(
398825
- () => customPhrases && customPhrases.length > 0 ? customPhrases : WITTY_LOADING_PHRASES.map((phrase) => t4(phrase)),
398826
- [customPhrases]
398827
- );
399033
+ const loadingPhrases = (0, import_react120.useMemo)(() => {
399034
+ if (customPhrases && customPhrases.length > 0) {
399035
+ return customPhrases;
399036
+ }
399037
+ const translatedPhrases = ta("WITTY_LOADING_PHRASES");
399038
+ return translatedPhrases.length > 0 ? translatedPhrases : WITTY_LOADING_PHRASES;
399039
+ }, [customPhrases]);
398828
399040
  const [currentLoadingPhrase, setCurrentLoadingPhrase] = (0, import_react120.useState)(
398829
399041
  loadingPhrases[0]
398830
399042
  );
@@ -401969,7 +402181,9 @@ ${installationInfo.updateMessage}`;
401969
402181
  updateProcess.on("close", (code2) => {
401970
402182
  if (code2 === 0) {
401971
402183
  updateEventEmitter.emit("update-success", {
401972
- message: t4("Update successful! The new version will be used on your next run.")
402184
+ message: t4(
402185
+ "Update successful! The new version will be used on your next run."
402186
+ )
401973
402187
  });
401974
402188
  } else {
401975
402189
  updateEventEmitter.emit("update-failed", {
@@ -402019,7 +402233,9 @@ function setUpdateHandler(addItem, setUpdateInfo) {
402019
402233
  addItem(
402020
402234
  {
402021
402235
  type: "info" /* INFO */,
402022
- text: t4("Update successful! The new version will be used on your next run.")
402236
+ text: t4(
402237
+ "Update successful! The new version will be used on your next run."
402238
+ )
402023
402239
  },
402024
402240
  Date.now()
402025
402241
  );
@@ -405611,7 +405827,11 @@ async function showResumeSessionPicker(cwd7 = process.cwd()) {
405611
405827
  const sessionService = new SessionService(cwd7);
405612
405828
  const hasSession = await sessionService.loadLastSession();
405613
405829
  if (!hasSession) {
405614
- console.log(t4("No sessions found. Start a new session with {{cmd}}.", { cmd: "rdmind" }));
405830
+ console.log(
405831
+ t4("No sessions found. Start a new session with {{cmd}}.", {
405832
+ cmd: "rdmind"
405833
+ })
405834
+ );
405615
405835
  return void 0;
405616
405836
  }
405617
405837
  clearScreen2();
@@ -405766,8 +405986,22 @@ var authenticateUpdateSchema = external_exports.object({
405766
405986
  authUri: external_exports.string()
405767
405987
  })
405768
405988
  });
405989
+ var acpMetaSchema = external_exports.record(external_exports.unknown()).nullable().optional();
405990
+ var modelIdSchema = external_exports.string();
405991
+ var modelInfoSchema = external_exports.object({
405992
+ _meta: acpMetaSchema,
405993
+ description: external_exports.string().nullable().optional(),
405994
+ modelId: modelIdSchema,
405995
+ name: external_exports.string()
405996
+ });
405997
+ var sessionModelStateSchema = external_exports.object({
405998
+ _meta: acpMetaSchema,
405999
+ availableModels: external_exports.array(modelInfoSchema),
406000
+ currentModelId: modelIdSchema
406001
+ });
405769
406002
  var newSessionResponseSchema = external_exports.object({
405770
- sessionId: external_exports.string()
406003
+ sessionId: external_exports.string(),
406004
+ models: sessionModelStateSchema
405771
406005
  });
405772
406006
  var loadSessionResponseSchema = external_exports.null();
405773
406007
  var sessionListItemSchema = external_exports.object({
@@ -405981,6 +406215,10 @@ var currentModeUpdateSchema = external_exports.object({
405981
406215
  sessionUpdate: external_exports.literal("current_mode_update"),
405982
406216
  modeId: approvalModeValueSchema
405983
406217
  });
406218
+ var currentModelUpdateSchema = external_exports.object({
406219
+ sessionUpdate: external_exports.literal("current_model_update"),
406220
+ model: modelInfoSchema
406221
+ });
405984
406222
  var sessionUpdateSchema = external_exports.union([
405985
406223
  external_exports.object({
405986
406224
  content: contentBlockSchema,
@@ -406022,6 +406260,7 @@ var sessionUpdateSchema = external_exports.union([
406022
406260
  sessionUpdate: external_exports.literal("plan")
406023
406261
  }),
406024
406262
  currentModeUpdateSchema,
406263
+ currentModelUpdateSchema,
406025
406264
  availableCommandsUpdateSchema
406026
406265
  ]);
406027
406266
  var agentResponseSchema = external_exports.union([
@@ -406135,6 +406374,13 @@ var AgentSideConnection = class {
406135
406374
  params
406136
406375
  );
406137
406376
  }
406377
+ /**
406378
+ * Sends a custom notification to the client.
406379
+ * Used for extension-specific notifications that are not part of the core ACP protocol.
406380
+ */
406381
+ async sendCustomNotification(method, params) {
406382
+ return await this.#connection.sendNotification(method, params);
406383
+ }
406138
406384
  /**
406139
406385
  * Request permission before running a tool
406140
406386
  *
@@ -407131,7 +407377,6 @@ var SubAgentTracker = class {
407131
407377
  };
407132
407378
 
407133
407379
  // packages/cli/src/acp-integration/session/Session.ts
407134
- var ALLOWED_BUILTIN_COMMANDS_FOR_ACP = ["init"];
407135
407380
  var Session3 = class {
407136
407381
  constructor(id, chat, config2, client, settings) {
407137
407382
  this.chat = chat;
@@ -407202,13 +407447,14 @@ var Session3 = class {
407202
407447
  inputText,
407203
407448
  pendingSend,
407204
407449
  this.config,
407205
- this.settings,
407206
- ALLOWED_BUILTIN_COMMANDS_FOR_ACP
407450
+ this.settings
407207
407451
  );
407208
- if (slashCommandResult) {
407209
- parts = slashCommandResult;
407210
- } else {
407211
- parts = await this.#resolvePrompt(params.prompt, pendingSend.signal);
407452
+ parts = await this.#processSlashCommandResult(
407453
+ slashCommandResult,
407454
+ params.prompt
407455
+ );
407456
+ if (parts === null) {
407457
+ return { stopReason: "end_turn" };
407212
407458
  }
407213
407459
  } else {
407214
407460
  parts = await this.#resolvePrompt(params.prompt, pendingSend.signal);
@@ -407298,9 +407544,7 @@ var Session3 = class {
407298
407544
  try {
407299
407545
  const slashCommands = await getAvailableCommands(
407300
407546
  this.config,
407301
- this.settings,
407302
- abortController.signal,
407303
- ALLOWED_BUILTIN_COMMANDS_FOR_ACP
407547
+ abortController.signal
407304
407548
  );
407305
407549
  const availableCommands = slashCommands.map(
407306
407550
  (cmd) => ({
@@ -407547,6 +407791,71 @@ var Session3 = class {
407547
407791
  return errorResponse(error2);
407548
407792
  }
407549
407793
  }
407794
+ /**
407795
+ * Processes the result of a slash command execution.
407796
+ *
407797
+ * Supported result types in ACP mode:
407798
+ * - submit_prompt: Submits content to the model
407799
+ * - stream_messages: Streams multiple messages to the client (ACP-specific)
407800
+ * - unsupported: Command cannot be executed in ACP mode
407801
+ * - no_command: No command was found, use original prompt
407802
+ *
407803
+ * Note: 'message' type is not supported in ACP mode - commands should use
407804
+ * 'stream_messages' instead for consistent async handling.
407805
+ *
407806
+ * @param result The result from handleSlashCommand
407807
+ * @param originalPrompt The original prompt blocks
407808
+ * @returns Parts to use for the prompt, or null if command was handled without needing model interaction
407809
+ */
407810
+ async #processSlashCommandResult(result, originalPrompt) {
407811
+ switch (result.type) {
407812
+ case "submit_prompt":
407813
+ return normalizePartList(result.content);
407814
+ case "message": {
407815
+ await this.client.sendCustomNotification("_qwencode/slash_command", {
407816
+ sessionId: this.sessionId,
407817
+ command: originalPrompt.filter((block2) => block2.type === "text").map((block2) => block2.type === "text" ? block2.text : "").join(" "),
407818
+ messageType: result.messageType,
407819
+ message: result.content || ""
407820
+ });
407821
+ if (result.messageType === "error") {
407822
+ throw new Error(result.content || "Slash command failed.");
407823
+ }
407824
+ return null;
407825
+ }
407826
+ case "stream_messages": {
407827
+ const command2 = originalPrompt.filter((block2) => block2.type === "text").map((block2) => block2.type === "text" ? block2.text : "").join(" ");
407828
+ for await (const msg of result.messages) {
407829
+ await this.client.sendCustomNotification("_qwencode/slash_command", {
407830
+ sessionId: this.sessionId,
407831
+ command: command2,
407832
+ messageType: msg.messageType,
407833
+ message: msg.content
407834
+ });
407835
+ if (msg.messageType === "error") {
407836
+ throw new Error(msg.content || "Slash command failed.");
407837
+ }
407838
+ }
407839
+ return null;
407840
+ }
407841
+ case "unsupported": {
407842
+ const unsupportedError = `Slash command not supported in ACP integration: ${result.reason}`;
407843
+ throw new Error(unsupportedError);
407844
+ }
407845
+ case "no_command":
407846
+ return originalPrompt.map((block2) => {
407847
+ if (block2.type === "text") {
407848
+ return { text: block2.text };
407849
+ }
407850
+ throw new Error(`Unsupported block type: ${block2.type}`);
407851
+ });
407852
+ default: {
407853
+ const _exhaustive = result;
407854
+ const unknownError = `Unknown slash command result type: ${_exhaustive.type}`;
407855
+ throw new Error(unknownError);
407856
+ }
407857
+ }
407858
+ }
407550
407859
  async #resolvePrompt(message, abortSignal) {
407551
407860
  const FILE_URI_SCHEME = "file://";
407552
407861
  const embeddedContext = [];
@@ -407891,7 +408200,7 @@ var GeminiAgent = class {
407891
408200
  name: APPROVAL_MODE_INFO[mode].name,
407892
408201
  description: APPROVAL_MODE_INFO[mode].description
407893
408202
  }));
407894
- const version2 = "0.1.8-alpha.9";
408203
+ const version2 = "0.1.8";
407895
408204
  return {
407896
408205
  protocolVersion: PROTOCOL_VERSION,
407897
408206
  agentInfo: {
@@ -407947,8 +408256,25 @@ var GeminiAgent = class {
407947
408256
  await this.ensureAuthenticated(config2);
407948
408257
  this.setupFileSystem(config2);
407949
408258
  const session = await this.createAndStoreSession(config2);
408259
+ const configuredModel = (config2.getModel() || this.config.getModel() || "").trim();
408260
+ const modelId = configuredModel || "default";
408261
+ const modelName = configuredModel || modelId;
407950
408262
  return {
407951
- sessionId: session.getId()
408263
+ sessionId: session.getId(),
408264
+ models: {
408265
+ currentModelId: modelId,
408266
+ availableModels: [
408267
+ {
408268
+ modelId,
408269
+ name: modelName,
408270
+ description: null,
408271
+ _meta: {
408272
+ contextLimit: tokenLimit(modelId)
408273
+ }
408274
+ }
408275
+ ],
408276
+ _meta: null
408277
+ }
407952
408278
  };
407953
408279
  }
407954
408280
  async newSessionConfig(cwd7, mcpServers, sessionId) {
@@ -408074,8 +408400,10 @@ var GeminiAgent = class {
408074
408400
  async createAndStoreSession(config2, conversation) {
408075
408401
  const sessionId = config2.getSessionId();
408076
408402
  const geminiClient = config2.getGeminiClient();
408077
- const history = conversation ? buildApiHistoryFromConversation(conversation) : void 0;
408078
- const chat = history ? await geminiClient.startChat(history) : await geminiClient.startChat();
408403
+ if (!geminiClient.isInitialized()) {
408404
+ await geminiClient.initialize();
408405
+ }
408406
+ const chat = geminiClient.getChat();
408079
408407
  const session = new Session3(
408080
408408
  sessionId,
408081
408409
  chat,
@@ -408511,6 +408839,11 @@ main().catch((error2) => {
408511
408839
  * Copyright 2025 RDMind
408512
408840
  * SPDX-License-Identifier: Apache-2.0
408513
408841
  */
408842
+ /**
408843
+ * @license
408844
+ * Copyright 2025 Qwen team
408845
+ * SPDX-License-Identifier: Apache-2.0
408846
+ */
408514
408847
  /*! Bundled license information:
408515
408848
 
408516
408849
  undici/lib/web/fetch/body.js: