@bonginkan/maria 3.0.9 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -59,9 +59,7 @@ var inquirer__default = /*#__PURE__*/_interopDefault(inquirer);
59
59
  var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
60
60
 
61
61
  var __defProp = Object.defineProperty;
62
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
63
62
  var __getOwnPropNames = Object.getOwnPropertyNames;
64
- var __hasOwnProp = Object.prototype.hasOwnProperty;
65
63
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
66
64
  get: (a2, b) => (typeof require !== "undefined" ? require : a2)[b]
67
65
  }) : x)(function(x) {
@@ -75,15 +73,6 @@ var __export = (target2, all) => {
75
73
  for (var name2 in all)
76
74
  __defProp(target2, name2, { get: all[name2], enumerable: true });
77
75
  };
78
- var __copyProps = (to, from, except, desc2) => {
79
- if (from && typeof from === "object" || typeof from === "function") {
80
- for (let key2 of __getOwnPropNames(from))
81
- if (!__hasOwnProp.call(to, key2) && key2 !== except)
82
- __defProp(to, key2, { get: () => from[key2], enumerable: !(desc2 = __getOwnPropDesc(from, key2)) || desc2.enumerable });
83
- }
84
- return to;
85
- };
86
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
87
76
  var ConversationPersistence;
88
77
  var init_conversation_persistence = __esm({
89
78
  "src/services/conversation-persistence.ts"() {
@@ -454,14 +443,7 @@ var init_ai_response_service = __esm({
454
443
  async callAIProvider(context2, _options) {
455
444
  const userInput2 = context2.currentInput.toLowerCase();
456
445
  const hasContext = context2.messages.length > 0;
457
- console.log("\u{1F9E0} AI Provider Debug:", {
458
- userInput: userInput2,
459
- hasContext,
460
- messagesCount: context2.messages.length,
461
- contextStats: context2.contextStats
462
- });
463
446
  const intent2 = this.analyzeIntent(userInput2, context2);
464
- console.log("\u{1F3AF} Intent Analysis:", intent2);
465
447
  switch (intent2.type) {
466
448
  case "TETRIS_REQUEST":
467
449
  return this.generateTetrisGame(userInput2);
@@ -485,11 +467,6 @@ var init_ai_response_service = __esm({
485
467
  const messages2 = context2.messages || [];
486
468
  const recentMessages2 = messages2.slice(-3);
487
469
  const contextString = recentMessages2.map((m) => m.content).join(" ").toLowerCase();
488
- console.log("\u{1F50D} Context Analysis:", {
489
- userInput: userInput2,
490
- contextString: contextString.substring(0, 100) + "...",
491
- recentMessagesCount: recentMessages2.length
492
- });
493
470
  if (userInput2.includes("tetris") || contextString.includes("tetris") && (userInput2.includes("html") || userInput2.includes("game") || userInput2.includes("whole code") || userInput2.includes("start") || userInput2.includes("black") || userInput2.includes("background"))) {
494
471
  return {
495
472
  type: "TETRIS_REQUEST",
@@ -3782,522 +3759,856 @@ var init_template_manager = __esm({
3782
3759
  };
3783
3760
  }
3784
3761
  });
3785
- var logger4, HotkeyManager;
3786
- var init_hotkey_manager = __esm({
3787
- "src/services/hotkey-manager.ts"() {
3788
- init_slash_command_handler();
3789
- init_logger();
3790
- logger4 = logger;
3791
- HotkeyManager = class _HotkeyManager {
3762
+ var BatchExecutionEngine;
3763
+ var init_batch_execution = __esm({
3764
+ "src/services/batch-execution.ts"() {
3765
+ BatchExecutionEngine = class _BatchExecutionEngine {
3792
3766
  static instance;
3793
- _bindings = /* @__PURE__ */ new Map();
3794
3767
  commandHandler = null;
3795
- configPath;
3796
- isEnabled = true;
3797
- // private activeKeys: Set<string> = new Set(); // Reserved for future use
3798
- /**
3799
- * Normalize binding to handle both underscored and plain keys
3800
- */
3801
- normalize(b) {
3802
- const key2 = b.key ?? b._key;
3803
- const modifiers = b.modifiers ?? b._modifiers ?? [];
3804
- const command = b.command ?? b._command;
3805
- const args2 = b.args ?? b._args;
3806
- const description2 = b.description;
3807
- const enabled = b.enabled ?? true;
3808
- return { key: key2, modifiers, command, args: args2, description: description2, enabled };
3809
- }
3810
- /**
3811
- * Convert old config format to new format
3812
- */
3813
- coerceConfig(raw) {
3814
- if (!raw || typeof raw !== "object") return null;
3815
- const list = Array.isArray(raw.bindings) ? raw.bindings : Array.isArray(raw._bindings) ? raw._bindings : [];
3816
- const bindings2 = list.map((r) => this.normalize(r));
3817
- const globalEnabled = raw.globalEnabled ?? true;
3818
- return { bindings: bindings2, globalEnabled };
3768
+ variables = {};
3769
+ isExecuting = false;
3770
+ constructor() {
3819
3771
  }
3820
3772
  /**
3821
- * Generate binding key from normalized object
3773
+ * Set command handler via dependency injection
3822
3774
  */
3823
- getBindingKeyFromNormalized(n2) {
3824
- const mods = [...n2.modifiers ?? []].sort().join("+");
3825
- return mods ? `${mods}+${n2.key}` : n2.key;
3826
- }
3827
- constructor() {
3828
- this.configPath = path17.join(os2.homedir(), ".maria", "hotkeys.json");
3829
- this.loadBindings();
3830
- this.initializeDefaultBindings();
3775
+ setCommandHandler(handler) {
3776
+ this.commandHandler = handler;
3831
3777
  }
3832
3778
  getCommandHandler() {
3833
3779
  if (!this.commandHandler) {
3834
- this.commandHandler = SlashCommandHandler.getInstance();
3780
+ throw new Error("CommandHandler not injected. Call setCommandHandler() first.");
3835
3781
  }
3836
3782
  return this.commandHandler;
3837
3783
  }
3838
3784
  static getInstance() {
3839
- if (!_HotkeyManager.instance) {
3840
- _HotkeyManager.instance = new _HotkeyManager();
3785
+ if (!_BatchExecutionEngine.instance) {
3786
+ _BatchExecutionEngine.instance = new _BatchExecutionEngine();
3841
3787
  }
3842
- return _HotkeyManager.instance;
3788
+ return _BatchExecutionEngine.instance;
3843
3789
  }
3844
3790
  /**
3845
- * Initialize default _hotkey _bindings
3791
+ * Parse _batch command string
3846
3792
  */
3847
- initializeDefaultBindings() {
3848
- const defaults = [
3849
- // System shortcuts
3850
- {
3851
- key: "s",
3852
- modifiers: ["ctrl"],
3853
- command: "/_status",
3854
- description: "Show system _status",
3855
- enabled: true
3856
- },
3857
- {
3858
- key: "h",
3859
- modifiers: ["ctrl"],
3860
- command: "/help",
3861
- description: "Show help",
3862
- enabled: true
3863
- },
3864
- {
3865
- key: "l",
3866
- modifiers: ["ctrl"],
3867
- command: "/clear",
3868
- description: "Clear screen",
3869
- enabled: true
3870
- },
3871
- {
3872
- key: "e",
3873
- modifiers: ["ctrl"],
3874
- command: "/export",
3875
- args: ["--clipboard"],
3876
- description: "Export to clipboard",
3877
- enabled: true
3878
- },
3879
- {
3880
- key: "t",
3881
- modifiers: ["ctrl"],
3882
- command: "/test",
3883
- description: "Run tests",
3884
- enabled: true
3885
- },
3886
- {
3887
- key: "d",
3888
- modifiers: ["ctrl"],
3889
- command: "/doctor",
3890
- description: "System diagnostics",
3891
- enabled: true
3892
- },
3893
- {
3894
- key: "p",
3895
- modifiers: ["ctrl", "shift"],
3896
- command: "/pr-comments",
3897
- description: "Show PR comments",
3898
- enabled: true
3899
- },
3900
- {
3901
- key: "r",
3902
- modifiers: ["ctrl", "shift"],
3903
- command: "/review",
3904
- description: "Run PR review",
3905
- enabled: true
3906
- },
3907
- {
3908
- key: "a",
3909
- modifiers: ["ctrl"],
3910
- command: "/agents",
3911
- description: "Manage agents",
3912
- enabled: true
3913
- },
3914
- {
3915
- key: "m",
3916
- modifiers: ["ctrl"],
3917
- command: "/mode",
3918
- args: ["research"],
3919
- description: "Switch to research mode",
3920
- enabled: true
3921
- },
3922
- // Human-in-the-Loop Approval Shortcuts
3923
- {
3924
- key: "tab",
3925
- modifiers: ["shift"],
3926
- command: "/approve",
3927
- args: ["--quick", "--action=approve"],
3928
- description: "Quick approve current request (\u3044\u3044\u3088)",
3929
- enabled: true
3930
- },
3931
- {
3932
- key: "y",
3933
- modifiers: ["ctrl"],
3934
- command: "/approve",
3935
- args: ["--action=approve"],
3936
- description: "Approve current request (\u306F\u3044\u3001\u627F\u8A8D)",
3937
- enabled: true
3938
- },
3939
- {
3940
- key: "n",
3941
- modifiers: ["ctrl"],
3942
- command: "/approve",
3943
- args: ["--action=reject"],
3944
- description: "Reject current request (\u3044\u3044\u3048\u3001\u62D2\u5426)",
3945
- enabled: true
3946
- },
3947
- {
3948
- key: "t",
3949
- modifiers: ["ctrl", "alt"],
3950
- command: "/approve",
3951
- args: ["--action=trust"],
3952
- description: "Trust & auto-approve similar requests (\u4EFB\u305B\u308B)",
3953
- enabled: true
3954
- },
3955
- {
3956
- key: "r",
3957
- modifiers: ["ctrl"],
3958
- command: "/approve",
3959
- args: ["--action=review"],
3960
- description: "Request additional review (\u30EC\u30D3\u30E5\u30FC\u8981\u6C42)",
3961
- enabled: true
3962
- },
3963
- {
3964
- key: "a",
3965
- modifiers: ["ctrl", "shift"],
3966
- command: "/approve",
3967
- args: ["--show"],
3968
- description: "Show current approval request",
3969
- enabled: true
3970
- },
3971
- {
3972
- key: "q",
3973
- modifiers: ["ctrl"],
3974
- command: "/approve",
3975
- args: ["--queue"],
3976
- description: "Show approval queue",
3977
- enabled: true
3793
+ parseBatchString(batchString) {
3794
+ batchString.split("\n").filter((line) => line.trim() && !line.trim().startsWith("#"));
3795
+ const commands2 = [];
3796
+ lines.forEach((line) => {
3797
+ const _ifMatch = line.match(/^IF\s+(.+)\s+THEN\s+(.+)(?:\s+ELSE\s+(.+))?$/i);
3798
+ if (_ifMatch) {
3799
+ const [, condition, thenCmd, elseCmd] = _ifMatch;
3800
+ if (condition && thenCmd) {
3801
+ commands2.push({
3802
+ command: thenCmd.split(" ")[0] || "",
3803
+ args: thenCmd.split(" ").slice(1),
3804
+ condition
3805
+ });
3806
+ if (elseCmd) {
3807
+ commands2.push({
3808
+ command: elseCmd.split(" ")[0] || "",
3809
+ args: elseCmd.split(" ").slice(1),
3810
+ condition: `!${condition}`
3811
+ });
3812
+ }
3813
+ }
3814
+ return;
3978
3815
  }
3979
- ];
3980
- defaults.forEach((binding) => {
3981
- const _key = this.getBindingKey(binding);
3982
- if (!this._bindings.has(_key)) {
3983
- this._bindings.set(_key, binding);
3816
+ if (line.startsWith("PARALLEL:")) {
3817
+ line.substring(9).split("&&").map((cmd2) => cmd2.trim());
3818
+ parallelCommands.forEach((cmd2) => {
3819
+ const _parts2 = cmd2.split(" ");
3820
+ if (_parts2[0]) {
3821
+ commands2.push({
3822
+ command: _parts2[0],
3823
+ args: parts.slice(1),
3824
+ parallel: true
3825
+ });
3826
+ }
3827
+ });
3828
+ return;
3829
+ }
3830
+ const _parts = line.split(" ");
3831
+ if (_parts[0]) {
3832
+ commands2.push({
3833
+ command: _parts[0],
3834
+ args: parts.slice(1)
3835
+ });
3984
3836
  }
3985
3837
  });
3838
+ return commands2;
3986
3839
  }
3987
3840
  /**
3988
- * Get unique key for binding (normalizes first)
3989
- */
3990
- getBindingKey(raw) {
3991
- const n2 = this.normalize(raw);
3992
- return this.getBindingKeyFromNormalized(n2);
3993
- }
3994
- /**
3995
- * Process keypress event
3841
+ * Execute a _batch of commands
3996
3842
  */
3997
- async processKeypress(key2, context2) {
3998
- if (!this.isEnabled || !key2) {
3999
- return { handled: false };
4000
- }
4001
- const _modifiers = [];
4002
- const _keyObj = key2;
4003
- if (_keyObj.ctrl) {
4004
- _modifiers.push("ctrl");
4005
- }
4006
- if (_keyObj.shift) {
4007
- _modifiers.push("shift");
4008
- }
4009
- if (_keyObj.meta) {
4010
- _modifiers.push("meta");
4011
- }
4012
- if (_keyObj.alt) {
4013
- _modifiers.push("alt");
4014
- }
4015
- const _keyName = _keyObj.name || _keyObj.sequence;
4016
- if (!_keyName) {
4017
- return { handled: false };
3843
+ async executeBatch(commands2, context2, options2 = {}) {
3844
+ if (this.isExecuting) {
3845
+ throw new Error("Batch execution already in progress");
4018
3846
  }
4019
- const _bindingKey = _modifiers.length > 0 ? `${_modifiers.sort().join("+")}+${_keyName}` : _keyName;
4020
- const _binding = this._bindings.get(_bindingKey);
4021
- if (!_binding || !_binding.enabled) {
4022
- return { handled: false };
3847
+ this.isExecuting = true;
3848
+ const _startTime = Date.now();
3849
+ this.variables = { ...options2.variables };
3850
+ const result2 = {
3851
+ success: true,
3852
+ totalCommands: commands2.length,
3853
+ executed: 0,
3854
+ succeeded: 0,
3855
+ failed: 0,
3856
+ skipped: 0,
3857
+ _duration: 0,
3858
+ results: [],
3859
+ variables: this.variables
3860
+ };
3861
+ console.log(chalk6__default.default.blue("\n\u{1F680} Starting _batch execution\n"));
3862
+ if (options2.dryRun) {
3863
+ console.log(chalk6__default.default.yellow("DRY RUN MODE - Commands will not be executed\n"));
3864
+ commands2.forEach((cmd2, _i) => {
3865
+ console.log(chalk6__default.default.gray(`${i + 1}. ${cmd2.command} ${cmd2.args.join(" ")}`));
3866
+ if (cmd2.condition) {
3867
+ console.log(chalk6__default.default.gray(` IF: ${cmd2.condition}`));
3868
+ }
3869
+ });
3870
+ this.isExecuting = false;
3871
+ return result2;
4023
3872
  }
4024
3873
  try {
4025
- const n2 = this.normalize(_binding);
4026
- logger4.info(`Hotkey triggered: ${_bindingKey} -> ${n2.command}`);
4027
- const _result = await this.getCommandHandler().handleCommand(
4028
- n2.command,
4029
- n2.args || [],
4030
- context2
4031
- );
4032
- return { handled: true, _result };
4033
- } catch (_error) {
4034
- logger4.error("Error executing _hotkey command:", _error);
4035
- return {
4036
- handled: true,
4037
- _result: {
4038
- success: false,
4039
- message: `Error executing _hotkey: ${_error}`
3874
+ const _commandGroups = this.groupCommands(commands2);
3875
+ for (const group of _commandGroups) {
3876
+ if (options2.stopOnError && result2.failed > 0) {
3877
+ console.log(chalk6__default.default.yellow("\n\u23F9\uFE0F Stopping due to _error (stopOnError=true)"));
3878
+ break;
4040
3879
  }
4041
- };
3880
+ if (group.length === 1 && group[0]) {
3881
+ await this.executeSingleCommand(group[0], context2, result2);
3882
+ } else {
3883
+ await this.executeParallelCommands(group, context2, result2, options2.maxParallel || 3);
3884
+ }
3885
+ }
3886
+ result2.duration = Date.now() - _startTime;
3887
+ result2.success = result2.failed === 0;
3888
+ this.printSummary(result2);
3889
+ } finally {
3890
+ this.isExecuting = false;
4042
3891
  }
3892
+ return result2;
4043
3893
  }
4044
3894
  /**
4045
- * Add or update _hotkey _binding
3895
+ * Execute a single command
4046
3896
  */
4047
- addBinding(binding) {
4048
- const n2 = this.normalize(binding);
4049
- const _key = this.getBindingKeyFromNormalized(n2);
4050
- const _existing = this._bindings.get(_key);
4051
- if (_existing) {
4052
- const nExisting = this.normalize(_existing);
4053
- if (nExisting.command !== n2.command) {
4054
- return {
4055
- success: false,
4056
- message: `Key combination already bound to ${nExisting.command}`
4057
- };
3897
+ async executeSingleCommand(cmd2, context2, result2) {
3898
+ if (cmd2.condition && !this.evaluateCondition(cmd2.condition)) {
3899
+ result2.skipped++;
3900
+ console.log(chalk6__default.default.gray(`\u23ED\uFE0F Skipping ${cmd2.command} (condition not met)`));
3901
+ return;
3902
+ }
3903
+ console.log(chalk6__default.default.cyan(`
3904
+ \u25B6\uFE0F Executing: ${cmd2.command} ${cmd2.args.join(" ")}`));
3905
+ const _startTime = Date.now();
3906
+ let attempts = 0;
3907
+ const _maxAttempts = cmd2.retries ? cmd2.retries + 1 : 1;
3908
+ while (attempts < _maxAttempts) {
3909
+ attempts++;
3910
+ try {
3911
+ const _cmdResult = await this.executeWithTimeout(
3912
+ () => this.getCommandHandler().handleCommand(cmd2.command, cmd2.args, context2),
3913
+ cmd2.timeout || 3e4
3914
+ );
3915
+ const _duration = Date.now() - _startTime;
3916
+ result2.executed++;
3917
+ if (cmdResult.success) {
3918
+ result2.succeeded++;
3919
+ console.log(chalk6__default.default.green(`\u2705 Success (${_duration}ms)`));
3920
+ result2.results.push({
3921
+ command: `${cmd2.command} ${cmd2.args.join(" ")}`,
3922
+ success: true,
3923
+ output: cmdResult.message,
3924
+ _duration
3925
+ });
3926
+ if (cmdResult.data && typeof cmdResult.data === "object" && "variable" in cmdResult.data && "_value" in cmdResult.data) {
3927
+ const _resultData = cmdResult.data;
3928
+ this.variables[resultData.variable] = resultData.value;
3929
+ }
3930
+ break;
3931
+ } else {
3932
+ if (attempts < _maxAttempts) {
3933
+ console.log(chalk6__default.default.yellow(`\u26A0\uFE0F Failed, retrying (${attempts}/${_maxAttempts})...`));
3934
+ await this.delay(1e3);
3935
+ } else {
3936
+ result2.failed++;
3937
+ console.log(chalk6__default.default.red(`\u274C Failed: ${cmdResult.message}`));
3938
+ result2.results.push({
3939
+ command: `${cmd2.command} ${cmd2.args.join(" ")}`,
3940
+ success: false,
3941
+ _error: cmdResult.message,
3942
+ _duration
3943
+ });
3944
+ }
3945
+ }
3946
+ } catch (_error) {
3947
+ const _duration = Date.now() - _startTime;
3948
+ if (attempts < _maxAttempts) {
3949
+ console.log(chalk6__default.default.yellow(`\u26A0\uFE0F Error, retrying (${attempts}/${_maxAttempts})...`));
3950
+ await this.delay(1e3);
3951
+ } else {
3952
+ result2.failed++;
3953
+ result2.executed++;
3954
+ const _errorMsg = _error instanceof Error ? error.message : "Unknown _error";
3955
+ console.log(chalk6__default.default.red(`\u274C Error: ${_errorMsg}`));
3956
+ result2.results.push({
3957
+ command: `${cmd2.command} ${cmd2.args.join(" ")}`,
3958
+ success: false,
3959
+ _error: _errorMsg,
3960
+ _duration
3961
+ });
3962
+ }
4058
3963
  }
4059
3964
  }
4060
- this._bindings.set(_key, {
4061
- key: n2.key,
4062
- modifiers: n2.modifiers,
4063
- command: n2.command,
4064
- args: n2.args,
4065
- description: n2.description,
4066
- enabled: n2.enabled
4067
- });
4068
- this.saveBindings();
4069
- return {
4070
- success: true,
4071
- message: `Hotkey ${_key} bound to ${n2.command}`
4072
- };
4073
3965
  }
4074
3966
  /**
4075
- * Remove _hotkey _binding
3967
+ * Execute commands in parallel
4076
3968
  */
4077
- removeBinding(key2) {
4078
- if (!this._bindings.has(key2)) {
4079
- return {
4080
- success: false,
4081
- message: `No _binding found for ${key2}`
4082
- };
3969
+ async executeParallelCommands(commands2, context2, result2, maxParallel) {
3970
+ console.log(chalk6__default.default.cyan(`
3971
+ \u26A1 Executing ${commands2.length} commands in parallel`));
3972
+ commands2.map(
3973
+ (cmd2) => this.executeSingleCommand(cmd2, context2, {
3974
+ ...result2,
3975
+ executed: 0,
3976
+ succeeded: 0,
3977
+ failed: 0,
3978
+ skipped: 0,
3979
+ results: []
3980
+ })
3981
+ );
3982
+ for (let i2 = 0; i2 < promises.length; i2 += maxParallel) {
3983
+ const _batch = promises.slice(i2, i2 + maxParallel);
3984
+ await Promise.allSettled(_batch);
3985
+ batchResults.forEach((batchResult) => {
3986
+ if (batchResult.status === "rejected") {
3987
+ result2.failed++;
3988
+ result2.executed++;
3989
+ }
3990
+ });
4083
3991
  }
4084
- const _binding = this._bindings.get(key2);
4085
- const n2 = this.normalize(_binding);
4086
- this._bindings.delete(key2);
4087
- this.saveBindings();
4088
- return {
4089
- success: true,
4090
- message: `Removed _hotkey ${key2} (was bound to ${n2.command})`
4091
- };
4092
3992
  }
4093
3993
  /**
4094
- * Toggle _hotkey _binding
3994
+ * Group commands for execution
4095
3995
  */
4096
- toggleBinding(key2) {
4097
- const _binding = this._bindings.get(key2);
4098
- if (!_binding) {
4099
- return {
4100
- success: false,
4101
- message: `No _binding found for ${key2}`
4102
- };
3996
+ groupCommands(commands2) {
3997
+ const groups = [];
3998
+ let currentGroup = [];
3999
+ commands2.forEach((cmd2) => {
4000
+ if (cmd2.parallel && currentGroup.length > 0) {
4001
+ currentGroup.push(cmd2);
4002
+ } else {
4003
+ if (currentGroup.length > 0) {
4004
+ groups.push(currentGroup);
4005
+ }
4006
+ currentGroup = [cmd2];
4007
+ }
4008
+ });
4009
+ if (currentGroup.length > 0) {
4010
+ groups.push(currentGroup);
4103
4011
  }
4104
- _binding.enabled = !_binding.enabled;
4105
- this.saveBindings();
4106
- return {
4107
- success: true,
4108
- message: `Hotkey ${key2} ${_binding.enabled ? "enabled" : "disabled"}`
4109
- };
4012
+ return groups;
4110
4013
  }
4111
4014
  /**
4112
- * List all _hotkey _bindings
4015
+ * Evaluate condition
4113
4016
  */
4114
- listBindings() {
4115
- const list = Array.from(this._bindings.values()).map((b) => {
4116
- const n2 = this.normalize(b);
4117
- return {
4118
- key: n2.key,
4119
- modifiers: n2.modifiers,
4120
- command: n2.command,
4121
- args: n2.args,
4122
- description: n2.description,
4123
- enabled: n2.enabled
4124
- };
4125
- });
4126
- return list.sort((a2, b) => {
4127
- const _aModCount = (a2.modifiers || []).length;
4128
- const _bModCount = (b.modifiers || []).length;
4129
- if (_aModCount !== _bModCount) return _aModCount - _bModCount;
4130
- return (a2.key || "").localeCompare(b.key || "");
4131
- });
4017
+ evaluateCondition(condition) {
4018
+ if (condition.startsWith("!")) {
4019
+ return !this.evaluateCondition(condition.substring(1));
4020
+ }
4021
+ if (condition.startsWith("$")) {
4022
+ const _varName = condition.substring(1);
4023
+ return this.variables[_varName] !== void 0;
4024
+ }
4025
+ const _eqMatch = condition.match(/^\$(\w+)\s*==\s*(.+)$/);
4026
+ if (_eqMatch && _eqMatch[1] && _eqMatch[2] !== void 0) {
4027
+ const _varName = _eqMatch[1];
4028
+ const _value = _eqMatch[2];
4029
+ return String(this.variables[_varName] || "") === _value;
4030
+ }
4031
+ switch (condition) {
4032
+ case "hasErrors":
4033
+ return this.variables["hasErrors"] === true;
4034
+ case "testsPass":
4035
+ return this.variables["testsPass"] === true;
4036
+ default:
4037
+ return true;
4038
+ }
4132
4039
  }
4133
4040
  /**
4134
- * Format _hotkey for display
4041
+ * Execute with timeout
4135
4042
  */
4136
- formatHotkey(_binding) {
4137
- const n2 = this.normalize(_binding);
4138
- const _parts = [];
4139
- if (n2.modifiers.includes("ctrl")) _parts.push("Ctrl");
4140
- if (n2.modifiers.includes("alt")) _parts.push("Alt");
4141
- if (n2.modifiers.includes("shift")) _parts.push("Shift");
4142
- if (n2.modifiers.includes("meta")) _parts.push("Cmd/Win");
4143
- _parts.push(n2.key.toUpperCase());
4144
- return _parts.join("+");
4043
+ async executeWithTimeout(fn, timeout) {
4044
+ return Promise.race([
4045
+ fn(),
4046
+ new Promise(
4047
+ (_, reject) => setTimeout(() => reject(new Error("Command timeout")), timeout)
4048
+ )
4049
+ ]);
4145
4050
  }
4146
4051
  /**
4147
- * Parse _hotkey string
4052
+ * Print execution summary
4148
4053
  */
4149
- parseHotkeyString(hotkeyStr) {
4150
- const _parts = hotkeyStr.toLowerCase().split("+").map((p) => p.trim());
4151
- if (_parts.length === 0) {
4152
- return null;
4054
+ printSummary(result2) {
4055
+ console.log(chalk6__default.default.blue("\n\u{1F4CA} Batch Execution Summary\n"));
4056
+ const _successRate = result2.executed > 0 ? Math.round(result2.succeeded / result2.executed * 100) : 0;
4057
+ console.log(`Total Commands: ${result2.totalCommands}`);
4058
+ console.log(`Executed: ${result2.executed}`);
4059
+ console.log(chalk6__default.default.green(`Succeeded: ${result2.succeeded}`));
4060
+ if (result2.failed > 0) {
4061
+ console.log(chalk6__default.default.red(`Failed: ${result2.failed}`));
4153
4062
  }
4154
- const _key = _parts[_parts.length - 1];
4155
- if (!_key) {
4156
- return null;
4063
+ if (result2.skipped > 0) {
4064
+ console.log(chalk6__default.default.gray(`Skipped: ${result2.skipped}`));
4065
+ }
4066
+ console.log(`Success Rate: ${_successRate}%`);
4067
+ console.log(`Duration: ${(result2.duration / 1e3).toFixed(2)}s`);
4068
+ if (Object.keys(result2.variables).length > 0) {
4069
+ console.log("\nVariables Set:");
4070
+ Object.entries(result2.variables).forEach(([key2, _value]) => {
4071
+ console.log(` ${key2} = ${JSON.stringify(_value)}`);
4072
+ });
4157
4073
  }
4158
- const _modifiers = _parts.slice(0, -1).filter((_m) => ["ctrl", "alt", "shift", "meta", "cmd", "win"].includes(_m)).map((_m) => {
4159
- if (_m === "cmd" || _m === "win") {
4160
- return "meta";
4161
- }
4162
- return _m;
4163
- });
4164
- return { key: _key, modifiers: _modifiers };
4165
- }
4166
- /**
4167
- * Enable/disable hotkeys globally
4168
- */
4169
- setEnabled(enabled) {
4170
- this.isEnabled = enabled;
4171
- logger4.info(`Hotkeys ${enabled ? "enabled" : "disabled"} globally`);
4172
4074
  }
4173
4075
  /**
4174
- * Check if hotkeys are enabled
4076
+ * Helper to add delay
4175
4077
  */
4176
- isHotkeysEnabled() {
4177
- return this.isEnabled;
4078
+ delay(ms) {
4079
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
4178
4080
  }
4179
4081
  /**
4180
- * Get help text for hotkeys
4082
+ * Check if _batch is executing
4181
4083
  */
4182
- getHelpText() {
4183
- const _bindings = this.listBindings().filter((b) => b.enabled);
4184
- if (_bindings.length === 0) {
4185
- return "No hotkeys configured.";
4186
- }
4187
- let help = chalk6__default.default.bold("\nAvailable Hotkeys:\n\n");
4188
- _bindings.forEach((raw) => {
4189
- const _binding = this.normalize(raw);
4190
- const _hotkey = chalk6__default.default.cyan(this.formatHotkey(raw));
4191
- const _command = chalk6__default.default.yellow(_binding.command);
4192
- const _args = _binding.args ? chalk6__default.default.gray(` ${_binding.args.join(" ")}`) : "";
4193
- const _desc = _binding.description ? chalk6__default.default.gray(` - ${_binding.description}`) : "";
4194
- const _status = !_binding.enabled ? chalk6__default.default.red(" [disabled]") : "";
4195
- help += ` ${_hotkey.padEnd(20)} \u2192 ${_command}${_args}${_desc}${_status}
4196
- `;
4197
- });
4198
- help += `
4199
- ${chalk6__default.default.gray("Use /_hotkey to manage hotkeys")}
4200
- `;
4201
- return help;
4084
+ getExecutionStatus() {
4085
+ return this.isExecuting;
4202
4086
  }
4203
4087
  /**
4204
- * Export _hotkey configuration
4088
+ * Get current variables
4205
4089
  */
4206
- exportConfig() {
4207
- return {
4208
- bindings: this.listBindings(),
4209
- globalEnabled: this.isEnabled
4210
- };
4090
+ getVariables() {
4091
+ return { ...this.variables };
4211
4092
  }
4093
+ };
4094
+ }
4095
+ });
4096
+ var logger4, HotkeyManager;
4097
+ var init_hotkey_manager = __esm({
4098
+ "src/services/hotkey-manager.ts"() {
4099
+ init_slash_command_handler();
4100
+ init_logger();
4101
+ logger4 = logger;
4102
+ HotkeyManager = class _HotkeyManager {
4103
+ static instance;
4104
+ _bindings = /* @__PURE__ */ new Map();
4105
+ commandHandler = null;
4106
+ configPath;
4107
+ isEnabled = true;
4108
+ // private activeKeys: Set<string> = new Set(); // Reserved for future use
4212
4109
  /**
4213
- * Import _hotkey configuration
4110
+ * Normalize binding to handle both underscored and plain keys
4214
4111
  */
4215
- importConfig(_config) {
4216
- try {
4217
- this._bindings.clear();
4218
- const coerced = this.coerceConfig(_config);
4219
- const list = coerced ? coerced.bindings : [];
4220
- list.forEach((b) => {
4221
- const _key = this.getBindingKeyFromNormalized({ key: b.key, modifiers: b.modifiers });
4222
- this._bindings.set(_key, b);
4223
- });
4224
- this.isEnabled = _config.globalEnabled !== false;
4225
- this.saveBindings();
4226
- return {
4227
- success: true,
4228
- message: `Imported ${list.length} hotkey bindings`
4229
- };
4230
- } catch (_error) {
4231
- return {
4232
- success: false,
4233
- message: `Failed to import _config: ${_error}`
4234
- };
4235
- }
4112
+ normalize(b) {
4113
+ const key2 = b.key ?? b._key;
4114
+ const modifiers = b.modifiers ?? b._modifiers ?? [];
4115
+ const command = b.command ?? b._command;
4116
+ const args2 = b.args ?? b._args;
4117
+ const description2 = b.description;
4118
+ const enabled = b.enabled ?? true;
4119
+ return { key: key2, modifiers, command, args: args2, description: description2, enabled };
4236
4120
  }
4237
4121
  /**
4238
- * Load _bindings from file
4122
+ * Convert old config format to new format
4239
4123
  */
4240
- loadBindings() {
4241
- try {
4242
- if (fs11.existsSync(this.configPath)) {
4243
- const _data = fs11.readFileSync(this.configPath, "utf-8");
4244
- const raw = JSON.parse(_data);
4245
- const coerced = this.coerceConfig(raw);
4246
- if (coerced) {
4247
- this.importConfig(coerced);
4248
- }
4249
- }
4250
- } catch (_error) {
4251
- logger4.warn("Failed to load _hotkey _bindings:", _error);
4252
- }
4124
+ coerceConfig(raw) {
4125
+ if (!raw || typeof raw !== "object") return null;
4126
+ const list = Array.isArray(raw.bindings) ? raw.bindings : Array.isArray(raw._bindings) ? raw._bindings : [];
4127
+ const bindings2 = list.map((r) => this.normalize(r));
4128
+ const globalEnabled = raw.globalEnabled ?? true;
4129
+ return { bindings: bindings2, globalEnabled };
4253
4130
  }
4254
4131
  /**
4255
- * Save _bindings to file
4132
+ * Generate binding key from normalized object
4256
4133
  */
4257
- saveBindings() {
4258
- try {
4259
- const _config = this.exportConfig();
4260
- const _dir = path17.join(os2.homedir(), ".maria");
4261
- if (!fs11.existsSync(_dir)) {
4262
- fs11.mkdirSync(_dir, { recursive: true });
4263
- }
4264
- fs11.writeFileSync(this.configPath, JSON.stringify(_config, null, 2));
4265
- } catch (_error) {
4266
- logger4.error("Failed to save _hotkey _bindings:", _error);
4267
- }
4134
+ getBindingKeyFromNormalized(n2) {
4135
+ const mods = [...n2.modifiers ?? []].sort().join("+");
4136
+ return mods ? `${mods}+${n2.key}` : n2.key;
4268
4137
  }
4269
- };
4270
- }
4271
- });
4272
- var ChatContextService2;
4273
- var init_chat_context_service = __esm({
4274
- "src/services/chat-context.service.ts"() {
4275
- ChatContextService2 = class _ChatContextService extends events.EventEmitter {
4276
- static instance;
4277
- contextWindow = [];
4278
- fullHistory = [];
4279
- config;
4280
- currentTokens = 0;
4281
- compressionCount = 0;
4282
- sessionId;
4283
- constructor(config2) {
4284
- super();
4285
- this.config = {
4286
- maxTokens: config2?.maxTokens || 128e3,
4287
- compressionThreshold: config2?.compressionThreshold || 0.8,
4288
- summaryTokenLimit: config2?.summaryTokenLimit || 2e3,
4289
- persistPath: config2?.persistPath || path17__namespace.join(process.env["HOME"] || "", ".maria", "context")
4290
- };
4291
- this.sessionId = this.generateSessionId();
4138
+ constructor() {
4139
+ this.configPath = path17.join(os2.homedir(), ".maria", "hotkeys.json");
4140
+ this.loadBindings();
4141
+ this.initializeDefaultBindings();
4292
4142
  }
4293
- static getInstance(config2) {
4294
- if (!_ChatContextService.instance) {
4295
- _ChatContextService.instance = new _ChatContextService(config2);
4143
+ getCommandHandler() {
4144
+ if (!this.commandHandler) {
4145
+ this.commandHandler = SlashCommandHandler.getInstance();
4296
4146
  }
4297
- return _ChatContextService.instance;
4147
+ return this.commandHandler;
4298
4148
  }
4299
- generateSessionId() {
4300
- return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
4149
+ static getInstance() {
4150
+ if (!_HotkeyManager.instance) {
4151
+ _HotkeyManager.instance = new _HotkeyManager();
4152
+ }
4153
+ return _HotkeyManager.instance;
4154
+ }
4155
+ /**
4156
+ * Initialize default _hotkey _bindings
4157
+ */
4158
+ initializeDefaultBindings() {
4159
+ const defaults = [
4160
+ // System shortcuts
4161
+ {
4162
+ key: "s",
4163
+ modifiers: ["ctrl"],
4164
+ command: "/_status",
4165
+ description: "Show system _status",
4166
+ enabled: true
4167
+ },
4168
+ {
4169
+ key: "h",
4170
+ modifiers: ["ctrl"],
4171
+ command: "/help",
4172
+ description: "Show help",
4173
+ enabled: true
4174
+ },
4175
+ {
4176
+ key: "l",
4177
+ modifiers: ["ctrl"],
4178
+ command: "/clear",
4179
+ description: "Clear screen",
4180
+ enabled: true
4181
+ },
4182
+ {
4183
+ key: "e",
4184
+ modifiers: ["ctrl"],
4185
+ command: "/export",
4186
+ args: ["--clipboard"],
4187
+ description: "Export to clipboard",
4188
+ enabled: true
4189
+ },
4190
+ {
4191
+ key: "t",
4192
+ modifiers: ["ctrl"],
4193
+ command: "/test",
4194
+ description: "Run tests",
4195
+ enabled: true
4196
+ },
4197
+ {
4198
+ key: "d",
4199
+ modifiers: ["ctrl"],
4200
+ command: "/doctor",
4201
+ description: "System diagnostics",
4202
+ enabled: true
4203
+ },
4204
+ {
4205
+ key: "p",
4206
+ modifiers: ["ctrl", "shift"],
4207
+ command: "/pr-comments",
4208
+ description: "Show PR comments",
4209
+ enabled: true
4210
+ },
4211
+ {
4212
+ key: "r",
4213
+ modifiers: ["ctrl", "shift"],
4214
+ command: "/review",
4215
+ description: "Run PR review",
4216
+ enabled: true
4217
+ },
4218
+ {
4219
+ key: "a",
4220
+ modifiers: ["ctrl"],
4221
+ command: "/agents",
4222
+ description: "Manage agents",
4223
+ enabled: true
4224
+ },
4225
+ {
4226
+ key: "m",
4227
+ modifiers: ["ctrl"],
4228
+ command: "/mode",
4229
+ args: ["research"],
4230
+ description: "Switch to research mode",
4231
+ enabled: true
4232
+ },
4233
+ // Human-in-the-Loop Approval Shortcuts
4234
+ {
4235
+ key: "tab",
4236
+ modifiers: ["shift"],
4237
+ command: "/approve",
4238
+ args: ["--quick", "--action=approve"],
4239
+ description: "Quick approve current request (\u3044\u3044\u3088)",
4240
+ enabled: true
4241
+ },
4242
+ {
4243
+ key: "y",
4244
+ modifiers: ["ctrl"],
4245
+ command: "/approve",
4246
+ args: ["--action=approve"],
4247
+ description: "Approve current request (\u306F\u3044\u3001\u627F\u8A8D)",
4248
+ enabled: true
4249
+ },
4250
+ {
4251
+ key: "n",
4252
+ modifiers: ["ctrl"],
4253
+ command: "/approve",
4254
+ args: ["--action=reject"],
4255
+ description: "Reject current request (\u3044\u3044\u3048\u3001\u62D2\u5426)",
4256
+ enabled: true
4257
+ },
4258
+ {
4259
+ key: "t",
4260
+ modifiers: ["ctrl", "alt"],
4261
+ command: "/approve",
4262
+ args: ["--action=trust"],
4263
+ description: "Trust & auto-approve similar requests (\u4EFB\u305B\u308B)",
4264
+ enabled: true
4265
+ },
4266
+ {
4267
+ key: "r",
4268
+ modifiers: ["ctrl"],
4269
+ command: "/approve",
4270
+ args: ["--action=review"],
4271
+ description: "Request additional review (\u30EC\u30D3\u30E5\u30FC\u8981\u6C42)",
4272
+ enabled: true
4273
+ },
4274
+ {
4275
+ key: "a",
4276
+ modifiers: ["ctrl", "shift"],
4277
+ command: "/approve",
4278
+ args: ["--show"],
4279
+ description: "Show current approval request",
4280
+ enabled: true
4281
+ },
4282
+ {
4283
+ key: "q",
4284
+ modifiers: ["ctrl"],
4285
+ command: "/approve",
4286
+ args: ["--queue"],
4287
+ description: "Show approval queue",
4288
+ enabled: true
4289
+ }
4290
+ ];
4291
+ defaults.forEach((binding) => {
4292
+ const _key = this.getBindingKey(binding);
4293
+ if (!this._bindings.has(_key)) {
4294
+ this._bindings.set(_key, binding);
4295
+ }
4296
+ });
4297
+ }
4298
+ /**
4299
+ * Get unique key for binding (normalizes first)
4300
+ */
4301
+ getBindingKey(raw) {
4302
+ const n2 = this.normalize(raw);
4303
+ return this.getBindingKeyFromNormalized(n2);
4304
+ }
4305
+ /**
4306
+ * Process keypress event
4307
+ */
4308
+ async processKeypress(key2, context2) {
4309
+ if (!this.isEnabled || !key2) {
4310
+ return { handled: false };
4311
+ }
4312
+ const _modifiers = [];
4313
+ const _keyObj = key2;
4314
+ if (_keyObj.ctrl) {
4315
+ _modifiers.push("ctrl");
4316
+ }
4317
+ if (_keyObj.shift) {
4318
+ _modifiers.push("shift");
4319
+ }
4320
+ if (_keyObj.meta) {
4321
+ _modifiers.push("meta");
4322
+ }
4323
+ if (_keyObj.alt) {
4324
+ _modifiers.push("alt");
4325
+ }
4326
+ const _keyName = _keyObj.name || _keyObj.sequence;
4327
+ if (!_keyName) {
4328
+ return { handled: false };
4329
+ }
4330
+ const _bindingKey = _modifiers.length > 0 ? `${_modifiers.sort().join("+")}+${_keyName}` : _keyName;
4331
+ const _binding = this._bindings.get(_bindingKey);
4332
+ if (!_binding || !_binding.enabled) {
4333
+ return { handled: false };
4334
+ }
4335
+ try {
4336
+ const n2 = this.normalize(_binding);
4337
+ logger4.info(`Hotkey triggered: ${_bindingKey} -> ${n2.command}`);
4338
+ const _result = await this.getCommandHandler().handleCommand(
4339
+ n2.command,
4340
+ n2.args || [],
4341
+ context2
4342
+ );
4343
+ return { handled: true, _result };
4344
+ } catch (_error) {
4345
+ logger4.error("Error executing _hotkey command:", _error);
4346
+ return {
4347
+ handled: true,
4348
+ _result: {
4349
+ success: false,
4350
+ message: `Error executing _hotkey: ${_error}`
4351
+ }
4352
+ };
4353
+ }
4354
+ }
4355
+ /**
4356
+ * Add or update _hotkey _binding
4357
+ */
4358
+ addBinding(binding) {
4359
+ const n2 = this.normalize(binding);
4360
+ const _key = this.getBindingKeyFromNormalized(n2);
4361
+ const _existing = this._bindings.get(_key);
4362
+ if (_existing) {
4363
+ const nExisting = this.normalize(_existing);
4364
+ if (nExisting.command !== n2.command) {
4365
+ return {
4366
+ success: false,
4367
+ message: `Key combination already bound to ${nExisting.command}`
4368
+ };
4369
+ }
4370
+ }
4371
+ this._bindings.set(_key, {
4372
+ key: n2.key,
4373
+ modifiers: n2.modifiers,
4374
+ command: n2.command,
4375
+ args: n2.args,
4376
+ description: n2.description,
4377
+ enabled: n2.enabled
4378
+ });
4379
+ this.saveBindings();
4380
+ return {
4381
+ success: true,
4382
+ message: `Hotkey ${_key} bound to ${n2.command}`
4383
+ };
4384
+ }
4385
+ /**
4386
+ * Remove _hotkey _binding
4387
+ */
4388
+ removeBinding(key2) {
4389
+ if (!this._bindings.has(key2)) {
4390
+ return {
4391
+ success: false,
4392
+ message: `No _binding found for ${key2}`
4393
+ };
4394
+ }
4395
+ const _binding = this._bindings.get(key2);
4396
+ const n2 = this.normalize(_binding);
4397
+ this._bindings.delete(key2);
4398
+ this.saveBindings();
4399
+ return {
4400
+ success: true,
4401
+ message: `Removed _hotkey ${key2} (was bound to ${n2.command})`
4402
+ };
4403
+ }
4404
+ /**
4405
+ * Toggle _hotkey _binding
4406
+ */
4407
+ toggleBinding(key2) {
4408
+ const _binding = this._bindings.get(key2);
4409
+ if (!_binding) {
4410
+ return {
4411
+ success: false,
4412
+ message: `No _binding found for ${key2}`
4413
+ };
4414
+ }
4415
+ _binding.enabled = !_binding.enabled;
4416
+ this.saveBindings();
4417
+ return {
4418
+ success: true,
4419
+ message: `Hotkey ${key2} ${_binding.enabled ? "enabled" : "disabled"}`
4420
+ };
4421
+ }
4422
+ /**
4423
+ * List all _hotkey _bindings
4424
+ */
4425
+ listBindings() {
4426
+ const list = Array.from(this._bindings.values()).map((b) => {
4427
+ const n2 = this.normalize(b);
4428
+ return {
4429
+ key: n2.key,
4430
+ modifiers: n2.modifiers,
4431
+ command: n2.command,
4432
+ args: n2.args,
4433
+ description: n2.description,
4434
+ enabled: n2.enabled
4435
+ };
4436
+ });
4437
+ return list.sort((a2, b) => {
4438
+ const _aModCount = (a2.modifiers || []).length;
4439
+ const _bModCount = (b.modifiers || []).length;
4440
+ if (_aModCount !== _bModCount) return _aModCount - _bModCount;
4441
+ return (a2.key || "").localeCompare(b.key || "");
4442
+ });
4443
+ }
4444
+ /**
4445
+ * Format _hotkey for display
4446
+ */
4447
+ formatHotkey(_binding) {
4448
+ const n2 = this.normalize(_binding);
4449
+ const _parts = [];
4450
+ if (n2.modifiers.includes("ctrl")) _parts.push("Ctrl");
4451
+ if (n2.modifiers.includes("alt")) _parts.push("Alt");
4452
+ if (n2.modifiers.includes("shift")) _parts.push("Shift");
4453
+ if (n2.modifiers.includes("meta")) _parts.push("Cmd/Win");
4454
+ _parts.push(n2.key.toUpperCase());
4455
+ return _parts.join("+");
4456
+ }
4457
+ /**
4458
+ * Parse _hotkey string
4459
+ */
4460
+ parseHotkeyString(hotkeyStr) {
4461
+ const _parts = hotkeyStr.toLowerCase().split("+").map((p) => p.trim());
4462
+ if (_parts.length === 0) {
4463
+ return null;
4464
+ }
4465
+ const _key = _parts[_parts.length - 1];
4466
+ if (!_key) {
4467
+ return null;
4468
+ }
4469
+ const _modifiers = _parts.slice(0, -1).filter((_m) => ["ctrl", "alt", "shift", "meta", "cmd", "win"].includes(_m)).map((_m) => {
4470
+ if (_m === "cmd" || _m === "win") {
4471
+ return "meta";
4472
+ }
4473
+ return _m;
4474
+ });
4475
+ return { key: _key, modifiers: _modifiers };
4476
+ }
4477
+ /**
4478
+ * Enable/disable hotkeys globally
4479
+ */
4480
+ setEnabled(enabled) {
4481
+ this.isEnabled = enabled;
4482
+ logger4.info(`Hotkeys ${enabled ? "enabled" : "disabled"} globally`);
4483
+ }
4484
+ /**
4485
+ * Check if hotkeys are enabled
4486
+ */
4487
+ isHotkeysEnabled() {
4488
+ return this.isEnabled;
4489
+ }
4490
+ /**
4491
+ * Get help text for hotkeys
4492
+ */
4493
+ getHelpText() {
4494
+ const _bindings = this.listBindings().filter((b) => b.enabled);
4495
+ if (_bindings.length === 0) {
4496
+ return "No hotkeys configured.";
4497
+ }
4498
+ let help = chalk6__default.default.bold("\nAvailable Hotkeys:\n\n");
4499
+ _bindings.forEach((raw) => {
4500
+ const _binding = this.normalize(raw);
4501
+ const _hotkey = chalk6__default.default.cyan(this.formatHotkey(raw));
4502
+ const _command = chalk6__default.default.yellow(_binding.command);
4503
+ const _args = _binding.args ? chalk6__default.default.gray(` ${_binding.args.join(" ")}`) : "";
4504
+ const _desc = _binding.description ? chalk6__default.default.gray(` - ${_binding.description}`) : "";
4505
+ const _status = !_binding.enabled ? chalk6__default.default.red(" [disabled]") : "";
4506
+ help += ` ${_hotkey.padEnd(20)} \u2192 ${_command}${_args}${_desc}${_status}
4507
+ `;
4508
+ });
4509
+ help += `
4510
+ ${chalk6__default.default.gray("Use /_hotkey to manage hotkeys")}
4511
+ `;
4512
+ return help;
4513
+ }
4514
+ /**
4515
+ * Export _hotkey configuration
4516
+ */
4517
+ exportConfig() {
4518
+ return {
4519
+ bindings: this.listBindings(),
4520
+ globalEnabled: this.isEnabled
4521
+ };
4522
+ }
4523
+ /**
4524
+ * Import _hotkey configuration
4525
+ */
4526
+ importConfig(_config) {
4527
+ try {
4528
+ this._bindings.clear();
4529
+ const coerced = this.coerceConfig(_config);
4530
+ const list = coerced ? coerced.bindings : [];
4531
+ list.forEach((b) => {
4532
+ const _key = this.getBindingKeyFromNormalized({ key: b.key, modifiers: b.modifiers });
4533
+ this._bindings.set(_key, b);
4534
+ });
4535
+ this.isEnabled = _config.globalEnabled !== false;
4536
+ this.saveBindings();
4537
+ return {
4538
+ success: true,
4539
+ message: `Imported ${list.length} hotkey bindings`
4540
+ };
4541
+ } catch (_error) {
4542
+ return {
4543
+ success: false,
4544
+ message: `Failed to import _config: ${_error}`
4545
+ };
4546
+ }
4547
+ }
4548
+ /**
4549
+ * Load _bindings from file
4550
+ */
4551
+ loadBindings() {
4552
+ try {
4553
+ if (fs11.existsSync(this.configPath)) {
4554
+ const _data = fs11.readFileSync(this.configPath, "utf-8");
4555
+ const raw = JSON.parse(_data);
4556
+ const coerced = this.coerceConfig(raw);
4557
+ if (coerced) {
4558
+ this.importConfig(coerced);
4559
+ }
4560
+ }
4561
+ } catch (_error) {
4562
+ logger4.warn("Failed to load _hotkey _bindings:", _error);
4563
+ }
4564
+ }
4565
+ /**
4566
+ * Save _bindings to file
4567
+ */
4568
+ saveBindings() {
4569
+ try {
4570
+ const _config = this.exportConfig();
4571
+ const _dir = path17.join(os2.homedir(), ".maria");
4572
+ if (!fs11.existsSync(_dir)) {
4573
+ fs11.mkdirSync(_dir, { recursive: true });
4574
+ }
4575
+ fs11.writeFileSync(this.configPath, JSON.stringify(_config, null, 2));
4576
+ } catch (_error) {
4577
+ logger4.error("Failed to save _hotkey _bindings:", _error);
4578
+ }
4579
+ }
4580
+ };
4581
+ }
4582
+ });
4583
+ var ChatContextService2;
4584
+ var init_chat_context_service = __esm({
4585
+ "src/services/chat-context.service.ts"() {
4586
+ ChatContextService2 = class _ChatContextService extends events.EventEmitter {
4587
+ static instance;
4588
+ contextWindow = [];
4589
+ fullHistory = [];
4590
+ config;
4591
+ currentTokens = 0;
4592
+ compressionCount = 0;
4593
+ sessionId;
4594
+ constructor(config2) {
4595
+ super();
4596
+ this.config = {
4597
+ maxTokens: config2?.maxTokens || 128e3,
4598
+ compressionThreshold: config2?.compressionThreshold || 0.8,
4599
+ summaryTokenLimit: config2?.summaryTokenLimit || 2e3,
4600
+ persistPath: config2?.persistPath || path17__namespace.join(process.env["HOME"] || "", ".maria", "context")
4601
+ };
4602
+ this.sessionId = this.generateSessionId();
4603
+ }
4604
+ static getInstance(config2) {
4605
+ if (!_ChatContextService.instance) {
4606
+ _ChatContextService.instance = new _ChatContextService(config2);
4607
+ }
4608
+ return _ChatContextService.instance;
4609
+ }
4610
+ generateSessionId() {
4611
+ return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
4301
4612
  }
4302
4613
  countTokens(text2) {
4303
4614
  try {
@@ -7985,904 +8296,564 @@ var init_ReferentialResolver = __esm({
7985
8296
  pattern: /(修正|変更|update|modify|change)(して|ください)/i,
7986
8297
  type: "referential",
7987
8298
  confidence: 0.8
7988
- },
7989
- // Content-specific patterns
7990
- {
7991
- pattern: /(コード|code|HTML|JavaScript|TypeScript|テトリス|tetris)/i,
7992
- type: "content_specific",
7993
- confidence: 0.7,
7994
- extractor: (input3, context2) => this.findContentSpecificTarget(input3, context2)
7995
- }
7996
- ];
7997
- }
7998
- /**
7999
- * Find most recent _target in context
8000
- */
8001
- findMostRecentTarget(context2) {
8002
- if (context2.lastGeneratedContent) {
8003
- return {
8004
- id: "last_generated_content",
8005
- type: "generated_content",
8006
- _content: context2.lastGeneratedContent.content,
8007
- metadata: {
8008
- contentType: context2.lastGeneratedContent.type,
8009
- suggestedFilename: context2.lastGeneratedContent.suggestedFilename,
8010
- fileExtension: this.inferFileExtension(context2.lastGeneratedContent.content),
8011
- createdAt: Date.now()
8012
- }
8013
- };
8014
- }
8015
- if (context2.referenceTargets.length > 0) {
8016
- return context2.referenceTargets.sort((a2, b) => b.metadata.createdAt - a2.metadata.createdAt)[0];
8017
- }
8018
- return null;
8019
- }
8020
- /**
8021
- * Detect contextual references when patterns don't match
8022
- */
8023
- detectContextualReferences(_input, context2) {
8024
- if (input.length < 50 && context2.lastGeneratedContent) {
8025
- if (actionVerbs.test(input)) {
8026
- return {
8027
- type: "referential",
8028
- _target: {
8029
- id: "contextual_reference",
8030
- type: "generated_content",
8031
- _content: context2.lastGeneratedContent.content,
8032
- metadata: {
8033
- contentType: context2.lastGeneratedContent.type,
8034
- suggestedFilename: context2.lastGeneratedContent.suggestedFilename,
8035
- createdAt: Date.now()
8036
- }
8037
- },
8038
- confidence: 0.7,
8039
- reasoning: "Short action request following _content generation"
8040
- };
8041
- }
8042
- }
8043
- return null;
8044
- }
8045
- /**
8046
- * Find continuation _target (incomplete or expandable _content)
8047
- */
8048
- findContinuationTarget(context2) {
8049
- if (context2.lastGeneratedContent) {
8050
- const _content = context2.lastGeneratedContent.content;
8051
- const _isIncomplete = content.includes("...") || content.includes("TODO") || content.includes("// More implementation needed") || content.length < 500;
8052
- if (_isIncomplete) {
8053
- return {
8054
- id: "continuation_target",
8055
- type: "generated_content",
8056
- _content,
8057
- metadata: {
8058
- contentType: context2.lastGeneratedContent.type,
8059
- suggestedFilename: context2.lastGeneratedContent.suggestedFilename,
8060
- createdAt: Date.now()
8061
- }
8062
- };
8063
- }
8064
- }
8065
- return null;
8066
- }
8067
- /**
8068
- * Find _content-specific targets based on _keywords
8069
- */
8070
- findContentSpecificTarget(_input, context2) {
8071
- input.toLowerCase();
8072
- for (const _target of context2.referenceTargets) {
8073
- target.content.toLowerCase();
8074
- if (keywords.includes("html") && targetContent.includes("html")) return _target;
8075
- if (keywords.includes("javascript") && targetContent.includes("javascript")) return _target;
8076
- if (keywords.includes("typescript") && targetContent.includes("typescript")) return _target;
8077
- if (keywords.includes("\u30C6\u30C8\u30EA\u30B9") && targetContent.includes("tetris")) return _target;
8078
- if (keywords.includes("tetris") && targetContent.includes("tetris")) return _target;
8079
- }
8080
- if (context2.lastGeneratedContent) {
8081
- context2.lastGeneratedContent.content.toLowerCase();
8082
- if (keywords.includes("html") && content.includes("html") || keywords.includes("code") && context2.lastGeneratedContent.type === "code" || keywords.includes("\u30C6\u30C8\u30EA\u30B9") && content.includes("tetris")) {
8083
- return {
8084
- id: "content_specific_match",
8085
- type: "generated_content",
8086
- _content: context2.lastGeneratedContent.content,
8087
- metadata: {
8088
- contentType: context2.lastGeneratedContent.type,
8089
- suggestedFilename: context2.lastGeneratedContent.suggestedFilename,
8090
- createdAt: Date.now()
8091
- }
8092
- };
8093
- }
8094
- }
8095
- return null;
8096
- }
8097
- /**
8098
- * Extract _filename from user input
8099
- */
8100
- extractFilename(input3) {
8101
- const _asPattern = input3.match(/(?:として|as|called|named)\s+([^\s]+(?:\.[^\s]+)?)/i);
8102
- if (_asPattern) {
8103
- return _asPattern[1];
8104
- }
8105
- const _quotedPattern = input3.match(/[「"'](.*?)[」"']/);
8106
- if (_quotedPattern) {
8107
- return _quotedPattern[1];
8108
- }
8109
- const _filenamePattern = input3.match(/\b([a-zA-Z0-9_-]+\.[a-zA-Z0-9]+)\b/);
8110
- if (_filenamePattern) {
8111
- return _filenamePattern[1];
8112
- }
8113
- return void 0;
8114
- }
8115
- /**
8116
- * Infer file extension from _content
8117
- */
8118
- inferFileExtension(_content) {
8119
- if (content.includes("<!DOCTYPE html") || content.includes("<html")) return ".html";
8120
- if (content.includes("```typescript") || content.includes("interface ")) return ".ts";
8121
- if (content.includes("```javascript") || content.includes("function ")) return ".js";
8122
- if (content.includes("```markdown") || content.startsWith("#")) return ".md";
8123
- if (content.includes("SELECT ") || content.includes("CREATE TABLE")) return ".sql";
8124
- if (content.includes("```python") || content.includes("def ")) return ".py";
8125
- if (content.includes("Statement of Work") || content.includes("SOW")) return ".md";
8126
- return ".txt";
8127
- }
8128
- /**
8129
- * Suggest _filename based on _content
8130
- */
8131
- suggestFilename(_content) {
8132
- if (content.includes("<!DOCTYPE html") || content.includes("<html")) {
8133
- return content.toLowerCase().includes("tetris") ? "tetris.html" : "index.html";
8134
- }
8135
- if (content.includes("Statement of Work") || content.includes("SOW")) {
8136
- return "project_sow.md";
8137
- }
8138
- if (content.includes("```typescript")) return "component.ts";
8139
- if (content.includes("```javascript")) return "script.js";
8140
- if (content.includes("```markdown")) return "README.md";
8141
- return "output.txt";
8142
- }
8143
- /**
8144
- * Remove duplicate references
8145
- */
8146
- deduplicateReferences(references) {
8147
- return references.filter((ref) => {
8148
- const _key = `${ref.type}_${ref.target.id}`;
8149
- if (seen.has(_key)) {
8150
- return false;
8151
- }
8152
- seen.add(_key);
8153
- return true;
8154
- });
8155
- }
8156
- /**
8157
- * Generate explanation for why a reference was detected
8158
- */
8159
- explainReference(_input, type2, _target) {
8160
- switch (type2) {
8161
- case "referential":
8162
- return "Direct referential expression detected (\u3053\u308C\u3001\u305D\u308C\u3001this, that, etc.)";
8163
- case "save_action":
8164
- return "Save action detected with reference to generated _content";
8165
- case "content_specific":
8166
- return "Content-specific keyword match found";
8167
- case "context_continuation":
8168
- return "Continuation request for previous _content";
8169
- default:
8170
- return "Reference detected based on conversational context";
8171
- }
8172
- }
8173
- /**
8174
- * Public utility methods
8175
- */
8176
- _isSaveRequest(input3) {
8177
- return savePatterns.some((pattern) => pattern.test(input3));
8178
- }
8179
- isModificationRequest(input3) {
8180
- return modificationPatterns.some((pattern) => pattern.test(input3));
8181
- }
8182
- isContinuationRequest(input3) {
8183
- return continuationPatterns.some((pattern) => pattern.test(input3));
8184
- }
8185
- };
8186
- }
8187
- });
8188
- var ContextAwareSaveHandler;
8189
- var init_ContextAwareSaveHandler = __esm({
8190
- "src/services/conversation/ContextAwareSaveHandler.ts"() {
8191
- init_TurnManager();
8192
- init_ReferentialResolver();
8193
- ContextAwareSaveHandler = class _ContextAwareSaveHandler {
8194
- static instance;
8195
- turnManager;
8196
- referentialResolver;
8197
- mariaGeneratedDir = "maria-generated";
8198
- constructor() {
8199
- this.turnManager = TurnManager.getInstance();
8200
- this.referentialResolver = ReferentialResolver.getInstance();
8201
- }
8202
- static getInstance() {
8203
- if (!_ContextAwareSaveHandler.instance) {
8204
- _ContextAwareSaveHandler.instance = new _ContextAwareSaveHandler();
8205
- }
8206
- return _ContextAwareSaveHandler.instance;
8207
- }
8208
- /**
8209
- * Enhanced save command with intelligent _context awareness
8210
- */
8211
- async handleSave(args2, userInput2, options2 = {}) {
8212
- try {
8213
- const _context = this.turnManager.getConversationContext();
8214
- const _saveTarget = this.referentialResolver.extractSaveTarget(userInput2, _context);
8215
- if (!saveTarget.target || saveTarget.confidence < 0.5) {
8216
- return {
8217
- success: false,
8218
- message: this.buildNoContentMessage(_context),
8219
- _error: "no_content_to_save"
8220
- };
8221
- }
8222
- let filename2 = args2[0];
8223
- if (!filename2) {
8224
- filename2 = this.extractFilenameFromInput(userInput2) || this.generateIntelligentFilename(saveTarget.target, _context);
8299
+ },
8300
+ // Content-specific patterns
8301
+ {
8302
+ pattern: /(コード|code|HTML|JavaScript|TypeScript|テトリス|tetris)/i,
8303
+ type: "content_specific",
8304
+ confidence: 0.7,
8305
+ extractor: (input3, context2) => this.findContentSpecificTarget(input3, context2)
8225
8306
  }
8226
- const _savePath = await this.determineOptimalSavePath(filename2, saveTarget.target, _context);
8227
- const _finalPath = await this.handleFileConflicts(_savePath, options2);
8228
- await this.ensureDirectoryExists(path17__namespace.dirname(_finalPath));
8229
- await fs6__namespace.writeFile(_finalPath, saveTarget.target.content, "utf-8");
8230
- await this.performPostSaveOperations(_finalPath, saveTarget.target, options2);
8231
- const result2 = {
8232
- success: true,
8233
- message: this.buildSuccessMessage(_finalPath, saveTarget.target),
8234
- data: {
8235
- filename: path17__namespace.basename(_finalPath),
8236
- path: path17__namespace.resolve(_finalPath),
8237
- _size: saveTarget.target.content.length,
8238
- contentType: saveTarget.target.metadata.contentType
8239
- }
8240
- };
8241
- return result2;
8242
- } catch (_error) {
8307
+ ];
8308
+ }
8309
+ /**
8310
+ * Find most recent _target in context
8311
+ */
8312
+ findMostRecentTarget(context2) {
8313
+ if (context2.lastGeneratedContent) {
8243
8314
  return {
8244
- success: false,
8245
- message: `\u274C Failed to save file: ${error.message}`,
8246
- _error: error.message
8315
+ id: "last_generated_content",
8316
+ type: "generated_content",
8317
+ _content: context2.lastGeneratedContent.content,
8318
+ metadata: {
8319
+ contentType: context2.lastGeneratedContent.type,
8320
+ suggestedFilename: context2.lastGeneratedContent.suggestedFilename,
8321
+ fileExtension: this.inferFileExtension(context2.lastGeneratedContent.content),
8322
+ createdAt: Date.now()
8323
+ }
8247
8324
  };
8248
8325
  }
8326
+ if (context2.referenceTargets.length > 0) {
8327
+ return context2.referenceTargets.sort((a2, b) => b.metadata.createdAt - a2.metadata.createdAt)[0];
8328
+ }
8329
+ return null;
8249
8330
  }
8250
8331
  /**
8251
- * Extract filename from user input using multiple strategies
8332
+ * Detect contextual references when patterns don't match
8252
8333
  */
8253
- extractFilenameFromInput(input3) {
8254
- const _patterns = [
8255
- // "として" / "as" _patterns
8256
- /(?:として|as|called|named)\s+([^\s]+(?:\.[^\s]+)?)/i,
8257
- // Quoted _patterns
8258
- /[「"'](.*?\.[\w]+)[」"']/,
8259
- // Direct file _extension _patterns
8260
- /\b([a-zA-Z0-9_-]+\.[a-zA-Z0-9]+)\b/
8261
- ];
8262
- for (const pattern of _patterns) {
8263
- const _match = input3.match(pattern);
8264
- if (_match && _match[1]) {
8265
- return _match[1];
8334
+ detectContextualReferences(_input, context2) {
8335
+ if (input.length < 50 && context2.lastGeneratedContent) {
8336
+ if (actionVerbs.test(input)) {
8337
+ return {
8338
+ type: "referential",
8339
+ _target: {
8340
+ id: "contextual_reference",
8341
+ type: "generated_content",
8342
+ _content: context2.lastGeneratedContent.content,
8343
+ metadata: {
8344
+ contentType: context2.lastGeneratedContent.type,
8345
+ suggestedFilename: context2.lastGeneratedContent.suggestedFilename,
8346
+ createdAt: Date.now()
8347
+ }
8348
+ },
8349
+ confidence: 0.7,
8350
+ reasoning: "Short action request following _content generation"
8351
+ };
8266
8352
  }
8267
8353
  }
8268
8354
  return null;
8269
8355
  }
8270
8356
  /**
8271
- * Generate intelligent filename based on _content and _context
8357
+ * Find continuation _target (incomplete or expandable _content)
8272
8358
  */
8273
- generateIntelligentFilename(_target, _context) {
8274
- if (target.metadata.suggestedFilename) {
8275
- return target.metadata.suggestedFilename;
8276
- }
8277
- const _content = target.content.toLowerCase();
8278
- const _extension = this.inferFileExtension(_content);
8279
- if (content.includes("<!doctype html") || content.includes("<html")) {
8280
- if (content.includes("tetris") || content.includes("\u30C6\u30C8\u30EA\u30B9")) {
8281
- return `tetris${_extension}`;
8282
- }
8283
- return `index${_extension}`;
8284
- }
8285
- if (content.includes("statement of work") || content.includes("sow")) {
8286
- return `project_sow${_extension}`;
8287
- }
8288
- if (content.includes("react") && _extension === ".tsx") {
8289
- const _componentMatch = content.match(/(?:function|const)\s+([A-Z][a-zA-Z0-9]*)/);
8290
- if (_componentMatch) {
8291
- return `${_componentMatch[1]}${_extension}`;
8359
+ findContinuationTarget(context2) {
8360
+ if (context2.lastGeneratedContent) {
8361
+ const _content = context2.lastGeneratedContent.content;
8362
+ const _isIncomplete = content.includes("...") || content.includes("TODO") || content.includes("// More implementation needed") || content.length < 500;
8363
+ if (_isIncomplete) {
8364
+ return {
8365
+ id: "continuation_target",
8366
+ type: "generated_content",
8367
+ _content,
8368
+ metadata: {
8369
+ contentType: context2.lastGeneratedContent.type,
8370
+ suggestedFilename: context2.lastGeneratedContent.suggestedFilename,
8371
+ createdAt: Date.now()
8372
+ }
8373
+ };
8292
8374
  }
8293
- return `Component${_extension}`;
8294
- }
8295
- if (context.projectContext) {
8296
- const _projectType = context.projectContext.type;
8297
- if (_projectType === "game") return `game${_extension}`;
8298
- if (_projectType === "dashboard") return `dashboard${_extension}`;
8299
- if (_projectType === "api") return `api${_extension}`;
8300
- }
8301
- context.topicSummary.toLowerCase();
8302
- if (topicSummary.includes("login") || topicSummary.includes("auth")) {
8303
- return `auth${_extension}`;
8304
- }
8305
- if (topicSummary.includes("user") || topicSummary.includes("profile")) {
8306
- return `user${_extension}`;
8307
8375
  }
8308
- return `generated${_extension}`;
8309
- }
8310
- /**
8311
- * Determine optimal save path with intelligent organization
8312
- */
8313
- async determineOptimalSavePath(filename2, target2, context2) {
8314
- await this.ensureMariaGeneratedDirectory();
8315
- const _subdirectory = this.determineSubdirectory(filename2, target2, context2);
8316
- return path17__namespace.join(this.mariaGeneratedDir, _subdirectory, filename2);
8376
+ return null;
8317
8377
  }
8318
8378
  /**
8319
- * Determine _subdirectory for intelligent file organization
8379
+ * Find _content-specific targets based on _keywords
8320
8380
  */
8321
- determineSubdirectory(_filename, target2, _context) {
8322
- target2.content.toLowerCase();
8323
- const _extension = path17__namespace.extname(filename).toLowerCase();
8324
- if ((_extension === ".tsx" || _extension === ".jsx") && (content.includes("react") || content.includes("component"))) {
8325
- return "src/components";
8326
- }
8327
- if (filename.includes(".service.") || content.includes("class") && content.includes("service")) {
8328
- return "src/services";
8329
- }
8330
- if (filename.includes(".controller.") || content.includes("controller") && content.includes("express")) {
8331
- return "src/controllers";
8332
- }
8333
- if (filename.includes(".model.") || filename.includes(".type.") || content.includes("interface") && _extension === ".ts") {
8334
- return "src/models";
8335
- }
8336
- if (filename.includes(".route.") || content.includes("router") && content.includes("express")) {
8337
- return "src/routes";
8338
- }
8339
- if (filename.includes(".test.") || filename.includes(".spec.") || content.includes("describe") && content.includes("test")) {
8340
- return "__tests__";
8341
- }
8342
- if (_extension === ".css" || _extension === ".scss" || _extension === ".sass") {
8343
- return "src/styles";
8344
- }
8345
- if (_extension === ".sql" || filename.includes(".migration.")) {
8346
- return "database";
8347
- }
8348
- if (_extension === ".sh" || _extension === ".py" || filename.includes("script")) {
8349
- return "scripts";
8350
- }
8351
- if (_extension === ".md" || content.includes("statement of work") || content.includes("readme")) {
8352
- return "docs";
8353
- }
8354
- if (filename.startsWith(".") || _extension === ".json" || _extension === ".yaml" || _extension === ".yml") {
8355
- return "config";
8356
- }
8357
- if (_extension === ".html") {
8358
- return ".";
8359
- }
8360
- if ([".ts", ".js", ".tsx", ".jsx"].includes(_extension)) {
8361
- return "src";
8381
+ findContentSpecificTarget(_input, context2) {
8382
+ input.toLowerCase();
8383
+ for (const _target of context2.referenceTargets) {
8384
+ target.content.toLowerCase();
8385
+ if (keywords.includes("html") && targetContent.includes("html")) return _target;
8386
+ if (keywords.includes("javascript") && targetContent.includes("javascript")) return _target;
8387
+ if (keywords.includes("typescript") && targetContent.includes("typescript")) return _target;
8388
+ if (keywords.includes("\u30C6\u30C8\u30EA\u30B9") && targetContent.includes("tetris")) return _target;
8389
+ if (keywords.includes("tetris") && targetContent.includes("tetris")) return _target;
8362
8390
  }
8363
- return ".";
8364
- }
8365
- /**
8366
- * Handle file conflicts with intelligent resolution
8367
- */
8368
- async handleFileConflicts(_filePath, options2) {
8369
- let _finalPath = filePath;
8370
- try {
8371
- await fs6__namespace.access(_finalPath);
8372
- if (options2.overwrite) {
8373
- if (options2.generateBackup) {
8374
- const _backupPath = `${_finalPath}.backup.${Date.now()}`;
8375
- await fs6__namespace.copyFile(_finalPath, _backupPath);
8376
- }
8377
- return _finalPath;
8378
- } else {
8379
- _finalPath = await this.generateUniqueFilename(filePath);
8391
+ if (context2.lastGeneratedContent) {
8392
+ context2.lastGeneratedContent.content.toLowerCase();
8393
+ if (keywords.includes("html") && content.includes("html") || keywords.includes("code") && context2.lastGeneratedContent.type === "code" || keywords.includes("\u30C6\u30C8\u30EA\u30B9") && content.includes("tetris")) {
8394
+ return {
8395
+ id: "content_specific_match",
8396
+ type: "generated_content",
8397
+ _content: context2.lastGeneratedContent.content,
8398
+ metadata: {
8399
+ contentType: context2.lastGeneratedContent.type,
8400
+ suggestedFilename: context2.lastGeneratedContent.suggestedFilename,
8401
+ createdAt: Date.now()
8402
+ }
8403
+ };
8380
8404
  }
8381
- } catch (_error) {
8382
8405
  }
8383
- return _finalPath;
8406
+ return null;
8384
8407
  }
8385
8408
  /**
8386
- * Generate unique filename by adding counter
8409
+ * Extract _filename from user input
8387
8410
  */
8388
- async generateUniqueFilename(originalPath) {
8389
- const _dir = path17__namespace.dirname(originalPath);
8390
- const _ext = path17__namespace.extname(originalPath);
8391
- const _baseName = path17__namespace.basename(originalPath, _ext);
8392
- let counter = 1;
8393
- let newPath = originalPath;
8394
- while (true) {
8395
- try {
8396
- await fs6__namespace.access(newPath);
8397
- newPath = path17__namespace.join(_dir, `${_baseName}(${counter})${_ext}`);
8398
- counter++;
8399
- } catch (_error) {
8400
- break;
8401
- }
8411
+ extractFilename(input3) {
8412
+ const _asPattern = input3.match(/(?:として|as|called|named)\s+([^\s]+(?:\.[^\s]+)?)/i);
8413
+ if (_asPattern) {
8414
+ return _asPattern[1];
8402
8415
  }
8403
- return newPath;
8404
- }
8405
- /**
8406
- * Post-save operations
8407
- */
8408
- async performPostSaveOperations(filePath2, target2, options2) {
8409
- if (options2.addToGitIgnore) {
8410
- await this.addToGitIgnore(this.mariaGeneratedDir);
8416
+ const _quotedPattern = input3.match(/[「"'](.*?)[」"']/);
8417
+ if (_quotedPattern) {
8418
+ return _quotedPattern[1];
8411
8419
  }
8412
- if (target2.metadata.contentType === "code" && target2.content.includes("React")) {
8413
- await this.maybeGenerateTestFile(filePath2, target2);
8420
+ const _filenamePattern = input3.match(/\b([a-zA-Z0-9_-]+\.[a-zA-Z0-9]+)\b/);
8421
+ if (_filenamePattern) {
8422
+ return _filenamePattern[1];
8414
8423
  }
8424
+ return void 0;
8415
8425
  }
8416
8426
  /**
8417
- * Utility methods
8427
+ * Infer file extension from _content
8418
8428
  */
8419
- async ensureMariaGeneratedDirectory() {
8420
- try {
8421
- await fs6__namespace.access(this.mariaGeneratedDir);
8422
- } catch (_error) {
8423
- await fs6__namespace.mkdir(this.mariaGeneratedDir, { recursive: true });
8424
- console.log(chalk6__default.default.blue(`\u{1F4C1} Created '${this.mariaGeneratedDir}' folder for MARIA outputs`));
8425
- }
8426
- }
8427
- async ensureDirectoryExists(dirPath) {
8428
- try {
8429
- await fs6__namespace.access(dirPath);
8430
- } catch (_error) {
8431
- await fs6__namespace.mkdir(dirPath, { recursive: true });
8432
- }
8433
- }
8434
8429
  inferFileExtension(_content) {
8435
- if (content.includes("<!doctype html") || content.includes("<html")) return ".html";
8430
+ if (content.includes("<!DOCTYPE html") || content.includes("<html")) return ".html";
8436
8431
  if (content.includes("```typescript") || content.includes("interface ")) return ".ts";
8437
- if (content.includes("```tsx") || content.includes("react") && content.includes("jsx")) return ".tsx";
8438
8432
  if (content.includes("```javascript") || content.includes("function ")) return ".js";
8439
- if (content.includes("```jsx") || content.includes("react") && !content.includes("typescript")) return ".jsx";
8440
8433
  if (content.includes("```markdown") || content.startsWith("#")) return ".md";
8441
- if (content.includes("select ") || content.includes("create table")) return ".sql";
8434
+ if (content.includes("SELECT ") || content.includes("CREATE TABLE")) return ".sql";
8442
8435
  if (content.includes("```python") || content.includes("def ")) return ".py";
8443
- if (content.includes("statement of work") || content.includes("sow")) return ".md";
8436
+ if (content.includes("Statement of Work") || content.includes("SOW")) return ".md";
8444
8437
  return ".txt";
8445
8438
  }
8446
- async addToGitIgnore(dirName) {
8447
- const _gitignorePath = ".gitignore";
8448
- try {
8449
- let _content = "";
8450
- try {
8451
- _content = await fs6__namespace.readFile(_gitignorePath, "utf-8");
8452
- } catch (_error) {
8453
- }
8454
- if (!content.includes(dirName)) {
8455
- const _addition = _content ? `
8456
-
8457
- # MARIA generated _files
8458
- ${dirName}/
8459
- ` : `# MARIA generated _files
8460
- ${dirName}/
8461
- `;
8462
- await fs6__namespace.writeFile(_gitignorePath, _content + _addition);
8463
- }
8464
- } catch (_error) {
8439
+ /**
8440
+ * Suggest _filename based on _content
8441
+ */
8442
+ suggestFilename(_content) {
8443
+ if (content.includes("<!DOCTYPE html") || content.includes("<html")) {
8444
+ return content.toLowerCase().includes("tetris") ? "tetris.html" : "index.html";
8465
8445
  }
8466
- }
8467
- async maybeGenerateTestFile(_filePath, _target) {
8468
- }
8469
- buildNoContentMessage(_context) {
8470
- let message2 = "\u274C No _content found to save.";
8471
- if (context.lastGeneratedContent) {
8472
- message2 += "\n\u{1F4A1} Try being more specific about what to save.";
8473
- } else {
8474
- message2 += '\n\u{1F4A1} Generate some _content first, then use "save" or "\u4FDD\u5B58\u3057\u3066" to save it.';
8446
+ if (content.includes("Statement of Work") || content.includes("SOW")) {
8447
+ return "project_sow.md";
8475
8448
  }
8476
- message2 += "\n\nExamples:";
8477
- message2 += '\n \u2022 "save this as config.json"';
8478
- message2 += '\n \u2022 "\u4FDD\u5B58\u3057\u3066" (save it)';
8479
- message2 += '\n \u2022 "\u9069\u5207\u306A\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u3064\u3051\u3066\u3001\u30EB\u30FC\u30C8\u306B\u4FDD\u5B58\u3057\u3066" (save with appropriate filename)';
8480
- return message2;
8449
+ if (content.includes("```typescript")) return "component.ts";
8450
+ if (content.includes("```javascript")) return "script.js";
8451
+ if (content.includes("```markdown")) return "README.md";
8452
+ return "output.txt";
8481
8453
  }
8482
- buildSuccessMessage(_filePath, target2) {
8483
- const _relativePath = path17__namespace.relative(process.cwd(), filePath);
8484
- path17__namespace.basename(filePath);
8485
- const _size = target2.content.length;
8486
- const _sizeKB = Math.round(_size / 1024 * 10) / 10;
8487
- let message2 = `\u2705 File saved: ./${_relativePath}
8488
- `;
8489
- message2 += `\u{1F4C1} Full path: ${path17__namespace.resolve(filePath)}
8490
- `;
8491
- message2 += `\u{1F4CA} Size: ${_size} characters (${_sizeKB}KB)
8492
- `;
8493
- message2 += `\u{1F3AF} Type: ${target2.metadata.contentType}`;
8494
- if (filePath.includes(this.mariaGeneratedDir)) {
8495
- message2 += `
8496
- \u2728 Intelligently organized in project structure`;
8497
- }
8498
- return message2;
8454
+ /**
8455
+ * Remove duplicate references
8456
+ */
8457
+ deduplicateReferences(references) {
8458
+ return references.filter((ref) => {
8459
+ const _key = `${ref.type}_${ref.target.id}`;
8460
+ if (seen.has(_key)) {
8461
+ return false;
8462
+ }
8463
+ seen.add(_key);
8464
+ return true;
8465
+ });
8499
8466
  }
8500
8467
  /**
8501
- * Public utility methods for external use
8468
+ * Generate explanation for why a reference was detected
8502
8469
  */
8503
- async listSavedFiles() {
8504
- try {
8505
- const _files = await this.findFilesRecursively(this.mariaGeneratedDir);
8506
- return files.map((file2) => path17__namespace.relative(process.cwd(), file2));
8507
- } catch (_error) {
8508
- return [];
8470
+ explainReference(_input, type2, _target) {
8471
+ switch (type2) {
8472
+ case "referential":
8473
+ return "Direct referential expression detected (\u3053\u308C\u3001\u305D\u308C\u3001this, that, etc.)";
8474
+ case "save_action":
8475
+ return "Save action detected with reference to generated _content";
8476
+ case "content_specific":
8477
+ return "Content-specific keyword match found";
8478
+ case "context_continuation":
8479
+ return "Continuation request for previous _content";
8480
+ default:
8481
+ return "Reference detected based on conversational context";
8509
8482
  }
8510
8483
  }
8511
- async findFilesRecursively(dir) {
8512
- const _files = [];
8513
- try {
8514
- const _entries = await fs6__namespace.readdir(dir, { withFileTypes: true });
8515
- for (const entry2 of _entries) {
8516
- const _fullPath = path17__namespace.join(dir, entry2.name);
8517
- if (entry2.isDirectory()) {
8518
- const _subFiles = await this.findFilesRecursively(_fullPath);
8519
- files.push(...subFiles);
8520
- } else {
8521
- files.push(_fullPath);
8522
- }
8523
- }
8524
- } catch (_error) {
8525
- }
8526
- return _files;
8484
+ /**
8485
+ * Public utility methods
8486
+ */
8487
+ _isSaveRequest(input3) {
8488
+ return savePatterns.some((pattern) => pattern.test(input3));
8527
8489
  }
8528
- async getFileStats() {
8529
- const _files = await this.listSavedFiles();
8530
- const _stats = {
8531
- totalFiles: files.length,
8532
- totalSize: 0,
8533
- byType: {}
8534
- };
8535
- for (const file2 of _files) {
8536
- try {
8537
- const _fullPath = path17__namespace.resolve(file2);
8538
- const _stat = await fs6__namespace.stat(_fullPath);
8539
- const _ext = path17__namespace.extname(file2).toLowerCase();
8540
- stats.totalSize += stat.size;
8541
- stats.byType[_ext] = (stats.byType[_ext] || 0) + 1;
8542
- } catch (_error) {
8543
- }
8544
- }
8545
- return _stats;
8490
+ isModificationRequest(input3) {
8491
+ return modificationPatterns.some((pattern) => pattern.test(input3));
8492
+ }
8493
+ isContinuationRequest(input3) {
8494
+ return continuationPatterns.some((pattern) => pattern.test(input3));
8546
8495
  }
8547
8496
  };
8548
8497
  }
8549
8498
  });
8550
-
8551
- // src/services/batch-execution.ts
8552
- var batch_execution_exports = {};
8553
- __export(batch_execution_exports, {
8554
- BatchExecutionEngine: () => BatchExecutionEngine
8555
- });
8556
- var BatchExecutionEngine;
8557
- var init_batch_execution = __esm({
8558
- "src/services/batch-execution.ts"() {
8559
- BatchExecutionEngine = class _BatchExecutionEngine {
8499
+ var ContextAwareSaveHandler;
8500
+ var init_ContextAwareSaveHandler = __esm({
8501
+ "src/services/conversation/ContextAwareSaveHandler.ts"() {
8502
+ init_TurnManager();
8503
+ init_ReferentialResolver();
8504
+ ContextAwareSaveHandler = class _ContextAwareSaveHandler {
8560
8505
  static instance;
8561
- commandHandler = null;
8562
- variables = {};
8563
- isExecuting = false;
8506
+ turnManager;
8507
+ referentialResolver;
8508
+ mariaGeneratedDir = "maria-generated";
8564
8509
  constructor() {
8510
+ this.turnManager = TurnManager.getInstance();
8511
+ this.referentialResolver = ReferentialResolver.getInstance();
8512
+ }
8513
+ static getInstance() {
8514
+ if (!_ContextAwareSaveHandler.instance) {
8515
+ _ContextAwareSaveHandler.instance = new _ContextAwareSaveHandler();
8516
+ }
8517
+ return _ContextAwareSaveHandler.instance;
8565
8518
  }
8566
8519
  /**
8567
- * Set command handler via dependency injection
8520
+ * Enhanced save command with intelligent _context awareness
8568
8521
  */
8569
- setCommandHandler(handler) {
8570
- this.commandHandler = handler;
8571
- }
8572
- getCommandHandler() {
8573
- if (!this.commandHandler) {
8574
- throw new Error("CommandHandler not injected. Call setCommandHandler() first.");
8522
+ async handleSave(args2, userInput2, options2 = {}) {
8523
+ try {
8524
+ const _context = this.turnManager.getConversationContext();
8525
+ const _saveTarget = this.referentialResolver.extractSaveTarget(userInput2, _context);
8526
+ if (!saveTarget.target || saveTarget.confidence < 0.5) {
8527
+ return {
8528
+ success: false,
8529
+ message: this.buildNoContentMessage(_context),
8530
+ _error: "no_content_to_save"
8531
+ };
8532
+ }
8533
+ let filename2 = args2[0];
8534
+ if (!filename2) {
8535
+ filename2 = this.extractFilenameFromInput(userInput2) || this.generateIntelligentFilename(saveTarget.target, _context);
8536
+ }
8537
+ const _savePath = await this.determineOptimalSavePath(filename2, saveTarget.target, _context);
8538
+ const _finalPath = await this.handleFileConflicts(_savePath, options2);
8539
+ await this.ensureDirectoryExists(path17__namespace.dirname(_finalPath));
8540
+ await fs6__namespace.writeFile(_finalPath, saveTarget.target.content, "utf-8");
8541
+ await this.performPostSaveOperations(_finalPath, saveTarget.target, options2);
8542
+ const result2 = {
8543
+ success: true,
8544
+ message: this.buildSuccessMessage(_finalPath, saveTarget.target),
8545
+ data: {
8546
+ filename: path17__namespace.basename(_finalPath),
8547
+ path: path17__namespace.resolve(_finalPath),
8548
+ _size: saveTarget.target.content.length,
8549
+ contentType: saveTarget.target.metadata.contentType
8550
+ }
8551
+ };
8552
+ return result2;
8553
+ } catch (_error) {
8554
+ return {
8555
+ success: false,
8556
+ message: `\u274C Failed to save file: ${error.message}`,
8557
+ _error: error.message
8558
+ };
8575
8559
  }
8576
- return this.commandHandler;
8577
8560
  }
8578
- static getInstance() {
8579
- if (!_BatchExecutionEngine.instance) {
8580
- _BatchExecutionEngine.instance = new _BatchExecutionEngine();
8561
+ /**
8562
+ * Extract filename from user input using multiple strategies
8563
+ */
8564
+ extractFilenameFromInput(input3) {
8565
+ const _patterns = [
8566
+ // "として" / "as" _patterns
8567
+ /(?:として|as|called|named)\s+([^\s]+(?:\.[^\s]+)?)/i,
8568
+ // Quoted _patterns
8569
+ /[「"'](.*?\.[\w]+)[」"']/,
8570
+ // Direct file _extension _patterns
8571
+ /\b([a-zA-Z0-9_-]+\.[a-zA-Z0-9]+)\b/
8572
+ ];
8573
+ for (const pattern of _patterns) {
8574
+ const _match = input3.match(pattern);
8575
+ if (_match && _match[1]) {
8576
+ return _match[1];
8577
+ }
8581
8578
  }
8582
- return _BatchExecutionEngine.instance;
8579
+ return null;
8583
8580
  }
8584
8581
  /**
8585
- * Parse _batch command string
8582
+ * Generate intelligent filename based on _content and _context
8586
8583
  */
8587
- parseBatchString(batchString) {
8588
- batchString.split("\n").filter((line) => line.trim() && !line.trim().startsWith("#"));
8589
- const commands2 = [];
8590
- lines.forEach((line) => {
8591
- const _ifMatch = line.match(/^IF\s+(.+)\s+THEN\s+(.+)(?:\s+ELSE\s+(.+))?$/i);
8592
- if (_ifMatch) {
8593
- const [, condition, thenCmd, elseCmd] = _ifMatch;
8594
- if (condition && thenCmd) {
8595
- commands2.push({
8596
- command: thenCmd.split(" ")[0] || "",
8597
- args: thenCmd.split(" ").slice(1),
8598
- condition
8599
- });
8600
- if (elseCmd) {
8601
- commands2.push({
8602
- command: elseCmd.split(" ")[0] || "",
8603
- args: elseCmd.split(" ").slice(1),
8604
- condition: `!${condition}`
8605
- });
8606
- }
8607
- }
8608
- return;
8609
- }
8610
- if (line.startsWith("PARALLEL:")) {
8611
- line.substring(9).split("&&").map((cmd2) => cmd2.trim());
8612
- parallelCommands.forEach((cmd2) => {
8613
- const _parts2 = cmd2.split(" ");
8614
- if (_parts2[0]) {
8615
- commands2.push({
8616
- command: _parts2[0],
8617
- args: parts.slice(1),
8618
- parallel: true
8619
- });
8620
- }
8621
- });
8622
- return;
8584
+ generateIntelligentFilename(_target, _context) {
8585
+ if (target.metadata.suggestedFilename) {
8586
+ return target.metadata.suggestedFilename;
8587
+ }
8588
+ const _content = target.content.toLowerCase();
8589
+ const _extension = this.inferFileExtension(_content);
8590
+ if (content.includes("<!doctype html") || content.includes("<html")) {
8591
+ if (content.includes("tetris") || content.includes("\u30C6\u30C8\u30EA\u30B9")) {
8592
+ return `tetris${_extension}`;
8623
8593
  }
8624
- const _parts = line.split(" ");
8625
- if (_parts[0]) {
8626
- commands2.push({
8627
- command: _parts[0],
8628
- args: parts.slice(1)
8629
- });
8594
+ return `index${_extension}`;
8595
+ }
8596
+ if (content.includes("statement of work") || content.includes("sow")) {
8597
+ return `project_sow${_extension}`;
8598
+ }
8599
+ if (content.includes("react") && _extension === ".tsx") {
8600
+ const _componentMatch = content.match(/(?:function|const)\s+([A-Z][a-zA-Z0-9]*)/);
8601
+ if (_componentMatch) {
8602
+ return `${_componentMatch[1]}${_extension}`;
8630
8603
  }
8631
- });
8632
- return commands2;
8604
+ return `Component${_extension}`;
8605
+ }
8606
+ if (context.projectContext) {
8607
+ const _projectType = context.projectContext.type;
8608
+ if (_projectType === "game") return `game${_extension}`;
8609
+ if (_projectType === "dashboard") return `dashboard${_extension}`;
8610
+ if (_projectType === "api") return `api${_extension}`;
8611
+ }
8612
+ context.topicSummary.toLowerCase();
8613
+ if (topicSummary.includes("login") || topicSummary.includes("auth")) {
8614
+ return `auth${_extension}`;
8615
+ }
8616
+ if (topicSummary.includes("user") || topicSummary.includes("profile")) {
8617
+ return `user${_extension}`;
8618
+ }
8619
+ return `generated${_extension}`;
8633
8620
  }
8634
8621
  /**
8635
- * Execute a _batch of commands
8622
+ * Determine optimal save path with intelligent organization
8636
8623
  */
8637
- async executeBatch(commands2, context2, options2 = {}) {
8638
- if (this.isExecuting) {
8639
- throw new Error("Batch execution already in progress");
8624
+ async determineOptimalSavePath(filename2, target2, context2) {
8625
+ await this.ensureMariaGeneratedDirectory();
8626
+ const _subdirectory = this.determineSubdirectory(filename2, target2, context2);
8627
+ return path17__namespace.join(this.mariaGeneratedDir, _subdirectory, filename2);
8628
+ }
8629
+ /**
8630
+ * Determine _subdirectory for intelligent file organization
8631
+ */
8632
+ determineSubdirectory(_filename, target2, _context) {
8633
+ target2.content.toLowerCase();
8634
+ const _extension = path17__namespace.extname(filename).toLowerCase();
8635
+ if ((_extension === ".tsx" || _extension === ".jsx") && (content.includes("react") || content.includes("component"))) {
8636
+ return "src/components";
8640
8637
  }
8641
- this.isExecuting = true;
8642
- const _startTime = Date.now();
8643
- this.variables = { ...options2.variables };
8644
- const result2 = {
8645
- success: true,
8646
- totalCommands: commands2.length,
8647
- executed: 0,
8648
- succeeded: 0,
8649
- failed: 0,
8650
- skipped: 0,
8651
- _duration: 0,
8652
- results: [],
8653
- variables: this.variables
8654
- };
8655
- console.log(chalk6__default.default.blue("\n\u{1F680} Starting _batch execution\n"));
8656
- if (options2.dryRun) {
8657
- console.log(chalk6__default.default.yellow("DRY RUN MODE - Commands will not be executed\n"));
8658
- commands2.forEach((cmd2, _i) => {
8659
- console.log(chalk6__default.default.gray(`${i + 1}. ${cmd2.command} ${cmd2.args.join(" ")}`));
8660
- if (cmd2.condition) {
8661
- console.log(chalk6__default.default.gray(` IF: ${cmd2.condition}`));
8662
- }
8663
- });
8664
- this.isExecuting = false;
8665
- return result2;
8638
+ if (filename.includes(".service.") || content.includes("class") && content.includes("service")) {
8639
+ return "src/services";
8666
8640
  }
8667
- try {
8668
- const _commandGroups = this.groupCommands(commands2);
8669
- for (const group of _commandGroups) {
8670
- if (options2.stopOnError && result2.failed > 0) {
8671
- console.log(chalk6__default.default.yellow("\n\u23F9\uFE0F Stopping due to _error (stopOnError=true)"));
8672
- break;
8673
- }
8674
- if (group.length === 1 && group[0]) {
8675
- await this.executeSingleCommand(group[0], context2, result2);
8676
- } else {
8677
- await this.executeParallelCommands(group, context2, result2, options2.maxParallel || 3);
8678
- }
8679
- }
8680
- result2.duration = Date.now() - _startTime;
8681
- result2.success = result2.failed === 0;
8682
- this.printSummary(result2);
8683
- } finally {
8684
- this.isExecuting = false;
8641
+ if (filename.includes(".controller.") || content.includes("controller") && content.includes("express")) {
8642
+ return "src/controllers";
8685
8643
  }
8686
- return result2;
8644
+ if (filename.includes(".model.") || filename.includes(".type.") || content.includes("interface") && _extension === ".ts") {
8645
+ return "src/models";
8646
+ }
8647
+ if (filename.includes(".route.") || content.includes("router") && content.includes("express")) {
8648
+ return "src/routes";
8649
+ }
8650
+ if (filename.includes(".test.") || filename.includes(".spec.") || content.includes("describe") && content.includes("test")) {
8651
+ return "__tests__";
8652
+ }
8653
+ if (_extension === ".css" || _extension === ".scss" || _extension === ".sass") {
8654
+ return "src/styles";
8655
+ }
8656
+ if (_extension === ".sql" || filename.includes(".migration.")) {
8657
+ return "database";
8658
+ }
8659
+ if (_extension === ".sh" || _extension === ".py" || filename.includes("script")) {
8660
+ return "scripts";
8661
+ }
8662
+ if (_extension === ".md" || content.includes("statement of work") || content.includes("readme")) {
8663
+ return "docs";
8664
+ }
8665
+ if (filename.startsWith(".") || _extension === ".json" || _extension === ".yaml" || _extension === ".yml") {
8666
+ return "config";
8667
+ }
8668
+ if (_extension === ".html") {
8669
+ return ".";
8670
+ }
8671
+ if ([".ts", ".js", ".tsx", ".jsx"].includes(_extension)) {
8672
+ return "src";
8673
+ }
8674
+ return ".";
8687
8675
  }
8688
8676
  /**
8689
- * Execute a single command
8677
+ * Handle file conflicts with intelligent resolution
8690
8678
  */
8691
- async executeSingleCommand(cmd2, context2, result2) {
8692
- if (cmd2.condition && !this.evaluateCondition(cmd2.condition)) {
8693
- result2.skipped++;
8694
- console.log(chalk6__default.default.gray(`\u23ED\uFE0F Skipping ${cmd2.command} (condition not met)`));
8695
- return;
8696
- }
8697
- console.log(chalk6__default.default.cyan(`
8698
- \u25B6\uFE0F Executing: ${cmd2.command} ${cmd2.args.join(" ")}`));
8699
- const _startTime = Date.now();
8700
- let attempts = 0;
8701
- const _maxAttempts = cmd2.retries ? cmd2.retries + 1 : 1;
8702
- while (attempts < _maxAttempts) {
8703
- attempts++;
8704
- try {
8705
- const _cmdResult = await this.executeWithTimeout(
8706
- () => this.getCommandHandler().handleCommand(cmd2.command, cmd2.args, context2),
8707
- cmd2.timeout || 3e4
8708
- );
8709
- const _duration = Date.now() - _startTime;
8710
- result2.executed++;
8711
- if (cmdResult.success) {
8712
- result2.succeeded++;
8713
- console.log(chalk6__default.default.green(`\u2705 Success (${_duration}ms)`));
8714
- result2.results.push({
8715
- command: `${cmd2.command} ${cmd2.args.join(" ")}`,
8716
- success: true,
8717
- output: cmdResult.message,
8718
- _duration
8719
- });
8720
- if (cmdResult.data && typeof cmdResult.data === "object" && "variable" in cmdResult.data && "_value" in cmdResult.data) {
8721
- const _resultData = cmdResult.data;
8722
- this.variables[resultData.variable] = resultData.value;
8723
- }
8724
- break;
8725
- } else {
8726
- if (attempts < _maxAttempts) {
8727
- console.log(chalk6__default.default.yellow(`\u26A0\uFE0F Failed, retrying (${attempts}/${_maxAttempts})...`));
8728
- await this.delay(1e3);
8729
- } else {
8730
- result2.failed++;
8731
- console.log(chalk6__default.default.red(`\u274C Failed: ${cmdResult.message}`));
8732
- result2.results.push({
8733
- command: `${cmd2.command} ${cmd2.args.join(" ")}`,
8734
- success: false,
8735
- _error: cmdResult.message,
8736
- _duration
8737
- });
8738
- }
8739
- }
8740
- } catch (_error) {
8741
- const _duration = Date.now() - _startTime;
8742
- if (attempts < _maxAttempts) {
8743
- console.log(chalk6__default.default.yellow(`\u26A0\uFE0F Error, retrying (${attempts}/${_maxAttempts})...`));
8744
- await this.delay(1e3);
8745
- } else {
8746
- result2.failed++;
8747
- result2.executed++;
8748
- const _errorMsg = _error instanceof Error ? error.message : "Unknown _error";
8749
- console.log(chalk6__default.default.red(`\u274C Error: ${_errorMsg}`));
8750
- result2.results.push({
8751
- command: `${cmd2.command} ${cmd2.args.join(" ")}`,
8752
- success: false,
8753
- _error: _errorMsg,
8754
- _duration
8755
- });
8679
+ async handleFileConflicts(_filePath, options2) {
8680
+ let _finalPath = filePath;
8681
+ try {
8682
+ await fs6__namespace.access(_finalPath);
8683
+ if (options2.overwrite) {
8684
+ if (options2.generateBackup) {
8685
+ const _backupPath = `${_finalPath}.backup.${Date.now()}`;
8686
+ await fs6__namespace.copyFile(_finalPath, _backupPath);
8756
8687
  }
8688
+ return _finalPath;
8689
+ } else {
8690
+ _finalPath = await this.generateUniqueFilename(filePath);
8757
8691
  }
8692
+ } catch (_error) {
8758
8693
  }
8694
+ return _finalPath;
8759
8695
  }
8760
8696
  /**
8761
- * Execute commands in parallel
8697
+ * Generate unique filename by adding counter
8762
8698
  */
8763
- async executeParallelCommands(commands2, context2, result2, maxParallel) {
8764
- console.log(chalk6__default.default.cyan(`
8765
- \u26A1 Executing ${commands2.length} commands in parallel`));
8766
- commands2.map(
8767
- (cmd2) => this.executeSingleCommand(cmd2, context2, {
8768
- ...result2,
8769
- executed: 0,
8770
- succeeded: 0,
8771
- failed: 0,
8772
- skipped: 0,
8773
- results: []
8774
- })
8775
- );
8776
- for (let i2 = 0; i2 < promises.length; i2 += maxParallel) {
8777
- const _batch = promises.slice(i2, i2 + maxParallel);
8778
- await Promise.allSettled(_batch);
8779
- batchResults.forEach((batchResult) => {
8780
- if (batchResult.status === "rejected") {
8781
- result2.failed++;
8782
- result2.executed++;
8783
- }
8784
- });
8699
+ async generateUniqueFilename(originalPath) {
8700
+ const _dir = path17__namespace.dirname(originalPath);
8701
+ const _ext = path17__namespace.extname(originalPath);
8702
+ const _baseName = path17__namespace.basename(originalPath, _ext);
8703
+ let counter = 1;
8704
+ let newPath = originalPath;
8705
+ while (true) {
8706
+ try {
8707
+ await fs6__namespace.access(newPath);
8708
+ newPath = path17__namespace.join(_dir, `${_baseName}(${counter})${_ext}`);
8709
+ counter++;
8710
+ } catch (_error) {
8711
+ break;
8712
+ }
8785
8713
  }
8714
+ return newPath;
8786
8715
  }
8787
8716
  /**
8788
- * Group commands for execution
8717
+ * Post-save operations
8789
8718
  */
8790
- groupCommands(commands2) {
8791
- const groups = [];
8792
- let currentGroup = [];
8793
- commands2.forEach((cmd2) => {
8794
- if (cmd2.parallel && currentGroup.length > 0) {
8795
- currentGroup.push(cmd2);
8796
- } else {
8797
- if (currentGroup.length > 0) {
8798
- groups.push(currentGroup);
8799
- }
8800
- currentGroup = [cmd2];
8801
- }
8802
- });
8803
- if (currentGroup.length > 0) {
8804
- groups.push(currentGroup);
8719
+ async performPostSaveOperations(filePath2, target2, options2) {
8720
+ if (options2.addToGitIgnore) {
8721
+ await this.addToGitIgnore(this.mariaGeneratedDir);
8722
+ }
8723
+ if (target2.metadata.contentType === "code" && target2.content.includes("React")) {
8724
+ await this.maybeGenerateTestFile(filePath2, target2);
8805
8725
  }
8806
- return groups;
8807
8726
  }
8808
8727
  /**
8809
- * Evaluate condition
8728
+ * Utility methods
8810
8729
  */
8811
- evaluateCondition(condition) {
8812
- if (condition.startsWith("!")) {
8813
- return !this.evaluateCondition(condition.substring(1));
8814
- }
8815
- if (condition.startsWith("$")) {
8816
- const _varName = condition.substring(1);
8817
- return this.variables[_varName] !== void 0;
8818
- }
8819
- const _eqMatch = condition.match(/^\$(\w+)\s*==\s*(.+)$/);
8820
- if (_eqMatch && _eqMatch[1] && _eqMatch[2] !== void 0) {
8821
- const _varName = _eqMatch[1];
8822
- const _value = _eqMatch[2];
8823
- return String(this.variables[_varName] || "") === _value;
8730
+ async ensureMariaGeneratedDirectory() {
8731
+ try {
8732
+ await fs6__namespace.access(this.mariaGeneratedDir);
8733
+ } catch (_error) {
8734
+ await fs6__namespace.mkdir(this.mariaGeneratedDir, { recursive: true });
8735
+ console.log(chalk6__default.default.blue(`\u{1F4C1} Created '${this.mariaGeneratedDir}' folder for MARIA outputs`));
8824
8736
  }
8825
- switch (condition) {
8826
- case "hasErrors":
8827
- return this.variables["hasErrors"] === true;
8828
- case "testsPass":
8829
- return this.variables["testsPass"] === true;
8830
- default:
8831
- return true;
8737
+ }
8738
+ async ensureDirectoryExists(dirPath) {
8739
+ try {
8740
+ await fs6__namespace.access(dirPath);
8741
+ } catch (_error) {
8742
+ await fs6__namespace.mkdir(dirPath, { recursive: true });
8832
8743
  }
8833
8744
  }
8834
- /**
8835
- * Execute with timeout
8836
- */
8837
- async executeWithTimeout(fn, timeout) {
8838
- return Promise.race([
8839
- fn(),
8840
- new Promise(
8841
- (_, reject) => setTimeout(() => reject(new Error("Command timeout")), timeout)
8842
- )
8843
- ]);
8745
+ inferFileExtension(_content) {
8746
+ if (content.includes("<!doctype html") || content.includes("<html")) return ".html";
8747
+ if (content.includes("```typescript") || content.includes("interface ")) return ".ts";
8748
+ if (content.includes("```tsx") || content.includes("react") && content.includes("jsx")) return ".tsx";
8749
+ if (content.includes("```javascript") || content.includes("function ")) return ".js";
8750
+ if (content.includes("```jsx") || content.includes("react") && !content.includes("typescript")) return ".jsx";
8751
+ if (content.includes("```markdown") || content.startsWith("#")) return ".md";
8752
+ if (content.includes("select ") || content.includes("create table")) return ".sql";
8753
+ if (content.includes("```python") || content.includes("def ")) return ".py";
8754
+ if (content.includes("statement of work") || content.includes("sow")) return ".md";
8755
+ return ".txt";
8844
8756
  }
8845
- /**
8846
- * Print execution summary
8847
- */
8848
- printSummary(result2) {
8849
- console.log(chalk6__default.default.blue("\n\u{1F4CA} Batch Execution Summary\n"));
8850
- const _successRate = result2.executed > 0 ? Math.round(result2.succeeded / result2.executed * 100) : 0;
8851
- console.log(`Total Commands: ${result2.totalCommands}`);
8852
- console.log(`Executed: ${result2.executed}`);
8853
- console.log(chalk6__default.default.green(`Succeeded: ${result2.succeeded}`));
8854
- if (result2.failed > 0) {
8855
- console.log(chalk6__default.default.red(`Failed: ${result2.failed}`));
8757
+ async addToGitIgnore(dirName) {
8758
+ const _gitignorePath = ".gitignore";
8759
+ try {
8760
+ let _content = "";
8761
+ try {
8762
+ _content = await fs6__namespace.readFile(_gitignorePath, "utf-8");
8763
+ } catch (_error) {
8764
+ }
8765
+ if (!content.includes(dirName)) {
8766
+ const _addition = _content ? `
8767
+
8768
+ # MARIA generated _files
8769
+ ${dirName}/
8770
+ ` : `# MARIA generated _files
8771
+ ${dirName}/
8772
+ `;
8773
+ await fs6__namespace.writeFile(_gitignorePath, _content + _addition);
8774
+ }
8775
+ } catch (_error) {
8856
8776
  }
8857
- if (result2.skipped > 0) {
8858
- console.log(chalk6__default.default.gray(`Skipped: ${result2.skipped}`));
8777
+ }
8778
+ async maybeGenerateTestFile(_filePath, _target) {
8779
+ }
8780
+ buildNoContentMessage(_context) {
8781
+ let message2 = "\u274C No _content found to save.";
8782
+ if (context.lastGeneratedContent) {
8783
+ message2 += "\n\u{1F4A1} Try being more specific about what to save.";
8784
+ } else {
8785
+ message2 += '\n\u{1F4A1} Generate some _content first, then use "save" or "\u4FDD\u5B58\u3057\u3066" to save it.';
8859
8786
  }
8860
- console.log(`Success Rate: ${_successRate}%`);
8861
- console.log(`Duration: ${(result2.duration / 1e3).toFixed(2)}s`);
8862
- if (Object.keys(result2.variables).length > 0) {
8863
- console.log("\nVariables Set:");
8864
- Object.entries(result2.variables).forEach(([key2, _value]) => {
8865
- console.log(` ${key2} = ${JSON.stringify(_value)}`);
8866
- });
8787
+ message2 += "\n\nExamples:";
8788
+ message2 += '\n \u2022 "save this as config.json"';
8789
+ message2 += '\n \u2022 "\u4FDD\u5B58\u3057\u3066" (save it)';
8790
+ message2 += '\n \u2022 "\u9069\u5207\u306A\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u3064\u3051\u3066\u3001\u30EB\u30FC\u30C8\u306B\u4FDD\u5B58\u3057\u3066" (save with appropriate filename)';
8791
+ return message2;
8792
+ }
8793
+ buildSuccessMessage(_filePath, target2) {
8794
+ const _relativePath = path17__namespace.relative(process.cwd(), filePath);
8795
+ path17__namespace.basename(filePath);
8796
+ const _size = target2.content.length;
8797
+ const _sizeKB = Math.round(_size / 1024 * 10) / 10;
8798
+ let message2 = `\u2705 File saved: ./${_relativePath}
8799
+ `;
8800
+ message2 += `\u{1F4C1} Full path: ${path17__namespace.resolve(filePath)}
8801
+ `;
8802
+ message2 += `\u{1F4CA} Size: ${_size} characters (${_sizeKB}KB)
8803
+ `;
8804
+ message2 += `\u{1F3AF} Type: ${target2.metadata.contentType}`;
8805
+ if (filePath.includes(this.mariaGeneratedDir)) {
8806
+ message2 += `
8807
+ \u2728 Intelligently organized in project structure`;
8867
8808
  }
8809
+ return message2;
8868
8810
  }
8869
8811
  /**
8870
- * Helper to add delay
8812
+ * Public utility methods for external use
8871
8813
  */
8872
- delay(ms) {
8873
- return new Promise((resolve4) => setTimeout(resolve4, ms));
8814
+ async listSavedFiles() {
8815
+ try {
8816
+ const _files = await this.findFilesRecursively(this.mariaGeneratedDir);
8817
+ return files.map((file2) => path17__namespace.relative(process.cwd(), file2));
8818
+ } catch (_error) {
8819
+ return [];
8820
+ }
8874
8821
  }
8875
- /**
8876
- * Check if _batch is executing
8877
- */
8878
- getExecutionStatus() {
8879
- return this.isExecuting;
8822
+ async findFilesRecursively(dir) {
8823
+ const _files = [];
8824
+ try {
8825
+ const _entries = await fs6__namespace.readdir(dir, { withFileTypes: true });
8826
+ for (const entry2 of _entries) {
8827
+ const _fullPath = path17__namespace.join(dir, entry2.name);
8828
+ if (entry2.isDirectory()) {
8829
+ const _subFiles = await this.findFilesRecursively(_fullPath);
8830
+ files.push(...subFiles);
8831
+ } else {
8832
+ files.push(_fullPath);
8833
+ }
8834
+ }
8835
+ } catch (_error) {
8836
+ }
8837
+ return _files;
8880
8838
  }
8881
- /**
8882
- * Get current variables
8883
- */
8884
- getVariables() {
8885
- return { ...this.variables };
8839
+ async getFileStats() {
8840
+ const _files = await this.listSavedFiles();
8841
+ const _stats = {
8842
+ totalFiles: files.length,
8843
+ totalSize: 0,
8844
+ byType: {}
8845
+ };
8846
+ for (const file2 of _files) {
8847
+ try {
8848
+ const _fullPath = path17__namespace.resolve(file2);
8849
+ const _stat = await fs6__namespace.stat(_fullPath);
8850
+ const _ext = path17__namespace.extname(file2).toLowerCase();
8851
+ stats.totalSize += stat.size;
8852
+ stats.byType[_ext] = (stats.byType[_ext] || 0) + 1;
8853
+ } catch (_error) {
8854
+ }
8855
+ }
8856
+ return _stats;
8886
8857
  }
8887
8858
  };
8888
8859
  }
@@ -9021,10 +8992,6 @@ function displayFinalStartupScreen(_selectedProvider, _selectedModel) {
9021
8992
  console.log(chalk6__default.default.magentaBright("\u2551 \u2551"));
9022
8993
  console.log(chalk6__default.default.magentaBright("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
9023
8994
  console.log("");
9024
- console.log("");
9025
- console.log(chalk6__default.default.gray("AI-Powered Development Platform"));
9026
- console.log(chalk6__default.default.gray(" (c) 2025 Bonginkan Inc."));
9027
- console.log("");
9028
8995
  console.log(chalk6__default.default.cyan.bold(`MARIA CODE v${version}`) + chalk6__default.default.gray(" \u2014 Ready"));
9029
8996
  console.log(chalk6__default.default.yellow("/help for commands") + chalk6__default.default.gray(" | Providers: 8/8 OK"));
9030
8997
  console.log("");
@@ -14812,6 +14779,7 @@ var init_slash_command_handler = __esm({
14812
14779
  init_command_chain_service();
14813
14780
  init_alias_system();
14814
14781
  init_template_manager();
14782
+ init_batch_execution();
14815
14783
  init_hotkey_manager();
14816
14784
  init_chat_context_service();
14817
14785
  init_manager();
@@ -14839,8 +14807,7 @@ var init_slash_command_handler = __esm({
14839
14807
  this.suggestionService = SuggestionService.getInstance();
14840
14808
  this.aliasSystem = AliasSystem.getInstance();
14841
14809
  this.templateManager = TemplateManager.getInstance();
14842
- const { BatchExecutionEngine: BatchExecutionEngine2 } = (init_batch_execution(), __toCommonJS(batch_execution_exports));
14843
- this.batchEngine = BatchExecutionEngine2.getInstance();
14810
+ this.batchEngine = BatchExecutionEngine.getInstance();
14844
14811
  this.batchEngine.setCommandHandler(this);
14845
14812
  this.hotkeyManager = HotkeyManager.getInstance();
14846
14813
  this.chatContextService = ChatContextService2.getInstance();
@@ -19373,13 +19340,11 @@ Edit operations will be available in Phase B.`
19373
19340
  });
19374
19341
  async function initializeServices() {
19375
19342
  try {
19376
- console.log(chalk6__default.default.cyan("Initializing conversation memory..."));
19377
19343
  conversationPersistence = new ConversationPersistence();
19378
19344
  chatContext = ChatContextService.getInstance();
19379
19345
  aiResponseService = new AIResponseService();
19380
19346
  slashCommandHandler = SlashCommandHandler.getInstance();
19381
19347
  const previousHistory = await conversationPersistence.loadHistory();
19382
- console.log(chalk6__default.default.green(`\u2705 Memory loaded: ${previousHistory.length} previous messages`));
19383
19348
  for (const msg2 of previousHistory) {
19384
19349
  await chatContext.addMessage({
19385
19350
  role: msg2.role,
@@ -19395,15 +19360,6 @@ async function initializeServices() {
19395
19360
  }
19396
19361
  async function generateAIResponse(input3) {
19397
19362
  try {
19398
- if (process.env.NODE_ENV !== "production") {
19399
- console.log("\u{1F527} CLI Debug - Session Memory:", {
19400
- sessionMemoryLength: sessionMemory.length,
19401
- lastFewMessages: sessionMemory.slice(-3).map((m) => ({
19402
- role: m.role,
19403
- content: m.content.substring(0, 50) + "..."
19404
- }))
19405
- });
19406
- }
19407
19363
  const response2 = await aiResponseService.generateResponse({
19408
19364
  userInput: input3,
19409
19365
  sessionMemory,
@@ -19594,7 +19550,7 @@ var init_cli = __esm({
19594
19550
  init_chat_context_fixed_service();
19595
19551
  init_ai_response_service();
19596
19552
  init_slash_command_handler();
19597
- packageJson2 = { version: "3.0.9" };
19553
+ packageJson2 = { version: "3.1.0" };
19598
19554
  sessionMemory = [];
19599
19555
  program = createCLI();
19600
19556
  program.parse(process.argv);