@defai.digital/automatosx 11.2.9 → 11.3.1

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/index.js CHANGED
@@ -19,7 +19,7 @@ import { Mutex } from 'async-mutex';
19
19
  import { promisify } from 'util';
20
20
  import yargs from 'yargs';
21
21
  import { hideBin } from 'yargs/helpers';
22
- import { randomUUID, createHash } from 'crypto';
22
+ import crypto2, { randomUUID, createHash } from 'crypto';
23
23
  import * as yaml4 from 'js-yaml';
24
24
  import yaml4__default, { load, dump } from 'js-yaml';
25
25
  import Table from 'cli-table3';
@@ -2943,8 +2943,18 @@ var init_base_provider = __esm({
2943
2943
  /**
2944
2944
  * Check if CLI is available - Template method pattern
2945
2945
  * Uses getCLICommand() to determine which CLI to check
2946
+ *
2947
+ * v11.2.9 Fix: Always return true in mock mode (AX_MOCK_PROVIDERS=true)
2948
+ * This allows integration tests in CI to run without installing actual provider CLIs
2946
2949
  */
2947
2950
  async checkCLIAvailable() {
2951
+ if (process.env.AX_MOCK_PROVIDERS === "true") {
2952
+ logger.debug(`${this.getCLICommand()} CLI availability check (mock mode)`, {
2953
+ available: true,
2954
+ mockMode: true
2955
+ });
2956
+ return true;
2957
+ }
2948
2958
  try {
2949
2959
  const cliCommand2 = this.getCLICommand();
2950
2960
  const result = findOnPath(cliCommand2);
@@ -3003,8 +3013,12 @@ ${fullPrompt}
3003
3013
  logger.debug(`Full prompt saved to ${debugPath}`);
3004
3014
  }
3005
3015
  const result = await this.executeCLI(fullPrompt);
3016
+ const latencyMs = Date.now() - startTime;
3006
3017
  this.health.consecutiveFailures = 0;
3007
3018
  this.health.available = true;
3019
+ this.health.errorRate = 0;
3020
+ this.health.latencyMs = latencyMs;
3021
+ this.health.lastCheck = Date.now();
3008
3022
  const response = {
3009
3023
  content: result,
3010
3024
  model: "default",
@@ -3015,7 +3029,7 @@ ${fullPrompt}
3015
3029
  completion: 0,
3016
3030
  total: 0
3017
3031
  },
3018
- latencyMs: Date.now() - startTime,
3032
+ latencyMs,
3019
3033
  finishReason: "stop",
3020
3034
  cached: false
3021
3035
  };
@@ -3035,6 +3049,8 @@ ${fullPrompt}
3035
3049
  this.health.consecutiveFailures++;
3036
3050
  this.health.available = false;
3037
3051
  this.health.errorRate = 1;
3052
+ this.health.latencyMs = Date.now() - startTime;
3053
+ this.health.lastCheck = Date.now();
3038
3054
  throw this.handleError(error);
3039
3055
  }
3040
3056
  }
@@ -3055,6 +3071,8 @@ ${fullPrompt}
3055
3071
  } catch (error) {
3056
3072
  this.health.available = false;
3057
3073
  this.health.errorRate = 1;
3074
+ this.health.lastCheck = Date.now();
3075
+ this.health.consecutiveFailures = this.health.consecutiveFailures + 1;
3058
3076
  return false;
3059
3077
  }
3060
3078
  }
@@ -3062,13 +3080,13 @@ ${fullPrompt}
3062
3080
  * Get health status
3063
3081
  */
3064
3082
  async healthCheck() {
3065
- const isAvailable = await this.isAvailable();
3083
+ await this.isAvailable();
3066
3084
  return {
3067
- available: isAvailable,
3085
+ available: this.health.available,
3068
3086
  latencyMs: this.health.latencyMs,
3069
- errorRate: isAvailable ? 0 : 1,
3070
- consecutiveFailures: isAvailable ? 0 : this.health.consecutiveFailures + 1,
3071
- lastCheckTime: Date.now()
3087
+ errorRate: this.health.errorRate,
3088
+ consecutiveFailures: this.health.consecutiveFailures,
3089
+ lastCheckTime: this.health.lastCheck
3072
3090
  };
3073
3091
  }
3074
3092
  /**
@@ -3786,8 +3804,9 @@ var init_cli_wrapper = __esm({
3786
3804
  child.stdin.write(prompt);
3787
3805
  child.stdin.end();
3788
3806
  }
3807
+ let rl = null;
3789
3808
  if (child.stdout && renderer) {
3790
- const rl = readline2__default.createInterface({
3809
+ rl = readline2__default.createInterface({
3791
3810
  input: child.stdout,
3792
3811
  crlfDelay: Infinity
3793
3812
  });
@@ -3795,6 +3814,11 @@ var init_cli_wrapper = __esm({
3795
3814
  stdout += line + "\n";
3796
3815
  renderer.processLine(line);
3797
3816
  });
3817
+ rl.on("error", (error) => {
3818
+ logger.warn("Readline error during streaming", {
3819
+ error: error.message
3820
+ });
3821
+ });
3798
3822
  } else if (child.stdout) {
3799
3823
  child.stdout.on("data", (data) => {
3800
3824
  stdout += data.toString();
@@ -3810,6 +3834,10 @@ var init_cli_wrapper = __esm({
3810
3834
  clearTimeout(timeoutHandle);
3811
3835
  timeoutHandle = null;
3812
3836
  }
3837
+ if (rl) {
3838
+ rl.close();
3839
+ rl = null;
3840
+ }
3813
3841
  this.activeProcesses.delete(child);
3814
3842
  if (hasTimedOut) {
3815
3843
  return;
@@ -3837,6 +3865,10 @@ var init_cli_wrapper = __esm({
3837
3865
  clearTimeout(timeoutHandle);
3838
3866
  timeoutHandle = null;
3839
3867
  }
3868
+ if (rl) {
3869
+ rl.close();
3870
+ rl = null;
3871
+ }
3840
3872
  this.activeProcesses.delete(child);
3841
3873
  if (!hasTimedOut) {
3842
3874
  if (renderer) {
@@ -5529,11 +5561,17 @@ ${result.content.substring(0, 1e3)}
5529
5561
  setupAutoSave() {
5530
5562
  this.autoSaveTimer = setInterval(async () => {
5531
5563
  if (this.pendingCheckpoint) {
5532
- await this.save(
5533
- this.pendingCheckpoint.workflowId,
5534
- this.pendingCheckpoint
5535
- );
5536
- this.pendingCheckpoint = null;
5564
+ try {
5565
+ await this.save(
5566
+ this.pendingCheckpoint.workflowId,
5567
+ this.pendingCheckpoint
5568
+ );
5569
+ this.pendingCheckpoint = null;
5570
+ } catch (error) {
5571
+ logger.warn("Auto-save failed", {
5572
+ error: error instanceof Error ? error.message : String(error)
5573
+ });
5574
+ }
5537
5575
  }
5538
5576
  }, this.options.autoSaveInterval);
5539
5577
  }
@@ -5545,13 +5583,29 @@ ${result.content.substring(0, 1e3)}
5545
5583
  }
5546
5584
  /**
5547
5585
  * Cleanup resources
5586
+ * BUG FIX: Flush pending checkpoint before destroying to prevent data loss
5548
5587
  */
5549
- destroy() {
5588
+ async destroy() {
5550
5589
  if (this.autoSaveTimer) {
5551
5590
  clearInterval(this.autoSaveTimer);
5552
5591
  this.autoSaveTimer = null;
5553
5592
  }
5554
- this.pendingCheckpoint = null;
5593
+ if (this.pendingCheckpoint) {
5594
+ try {
5595
+ await this.save(
5596
+ this.pendingCheckpoint.workflowId,
5597
+ this.pendingCheckpoint
5598
+ );
5599
+ logger.debug("Pending checkpoint flushed on destroy", {
5600
+ workflowId: this.pendingCheckpoint.workflowId
5601
+ });
5602
+ } catch (error) {
5603
+ logger.warn("Failed to flush pending checkpoint on destroy", {
5604
+ error: error instanceof Error ? error.message : String(error)
5605
+ });
5606
+ }
5607
+ this.pendingCheckpoint = null;
5608
+ }
5555
5609
  this.sdkCheckpointManager = null;
5556
5610
  logger.debug("CheckpointAdapter destroyed");
5557
5611
  }
@@ -7032,7 +7086,10 @@ var init_adapter2 = __esm({
7032
7086
  }
7033
7087
  if (this.checkpointAdapter) {
7034
7088
  try {
7035
- this.checkpointAdapter.destroy();
7089
+ const result = this.checkpointAdapter.destroy();
7090
+ if (result instanceof Promise) {
7091
+ await result;
7092
+ }
7036
7093
  this.checkpointAdapter = null;
7037
7094
  logger.debug("CheckpointAdapter destroyed");
7038
7095
  } catch (error) {
@@ -9263,7 +9320,7 @@ var PRECOMPILED_CONFIG = {
9263
9320
  "enableFreeTierPrioritization": true,
9264
9321
  "enableWorkloadAwareRouting": true
9265
9322
  },
9266
- "version": "11.2.9"
9323
+ "version": "11.3.1"
9267
9324
  };
9268
9325
 
9269
9326
  // src/core/config/schemas.ts
@@ -10117,6 +10174,7 @@ async function saveConfigFile(path7, config) {
10117
10174
  content = JSON.stringify(config, null, 2);
10118
10175
  }
10119
10176
  await writeFile(path7, content, "utf-8");
10177
+ configCache.clear();
10120
10178
  logger.info("Config saved successfully", { path: normalizePath(path7), format: ext });
10121
10179
  } catch (error) {
10122
10180
  if (error instanceof ConfigError) {
@@ -13191,12 +13249,6 @@ var setupCommand = {
13191
13249
  describe: "Force setup even if .automatosx already exists",
13192
13250
  type: "boolean",
13193
13251
  default: false
13194
- }).option("spec-kit", {
13195
- describe: "Automatically initialize GitHub Spec-Kit for spec-driven development",
13196
- type: "boolean"
13197
- }).option("skip-spec-kit", {
13198
- describe: "Skip Spec-Kit initialization (useful for CI/CD)",
13199
- type: "boolean"
13200
13252
  }).option("claude-code", {
13201
13253
  describe: "Setup Claude Code integration (generates manifests and registers MCP server)",
13202
13254
  type: "boolean",
@@ -13386,7 +13438,6 @@ var setupCommand = {
13386
13438
  console.log(chalk5.cyan("\u{1F4DD} Updating .gitignore..."));
13387
13439
  await updateGitignore(projectDir);
13388
13440
  console.log(chalk5.green(" \u2713 .gitignore updated"));
13389
- const specKitInitialized = await maybeInitializeSpecKit(projectDir, argv);
13390
13441
  let claudeCodeSetupSucceeded = false;
13391
13442
  if (argv.claudeCode) {
13392
13443
  console.log(chalk5.blue("\n\u{1F527} Setting up Claude Code integration...\n"));
@@ -13440,13 +13491,6 @@ var setupCommand = {
13440
13491
  console.log(chalk5.gray(' ax run backend "implement auth" --workflow auth-flow'));
13441
13492
  console.log(chalk5.gray(' ax run backend "create API" --workflow api-flow'));
13442
13493
  console.log(chalk5.gray(" \u2022 Available: auth-flow, feature-flow, api-flow, refactor-flow\n"));
13443
- if (specKitInitialized) {
13444
- console.log(chalk5.cyan("Spec Files (.specify/):"));
13445
- console.log(chalk5.gray(" \u2022 Spec files created for documentation"));
13446
- console.log(chalk5.gray(" \u2022 Use agents to work with specs:"));
13447
- console.log(chalk5.gray(' ax run product "Write spec for feature X"'));
13448
- console.log(chalk5.gray(" \u2022 Note: ax spec run removed in v11.0.0, use --workflow instead\n"));
13449
- }
13450
13494
  console.log(chalk5.cyan("Iterate Mode (Autonomous Multi-Iteration):"));
13451
13495
  console.log(chalk5.gray(" \u2022 Enable with --iterate flag for autonomous task loops"));
13452
13496
  console.log(chalk5.gray(' \u2022 Example: ax run quality "find bugs" --iterate --iterate-max-iterations 5'));
@@ -13881,9 +13925,9 @@ async function initializeGitRepository(projectDir) {
13881
13925
  logger.info("Git repository already exists, skipping initialization");
13882
13926
  return true;
13883
13927
  }
13884
- const { spawn: spawn9 } = await import('child_process');
13928
+ const { spawn: spawn10 } = await import('child_process');
13885
13929
  await new Promise((resolve13, reject) => {
13886
- const child = spawn9("git", ["init"], {
13930
+ const child = spawn10("git", ["init"], {
13887
13931
  cwd: projectDir,
13888
13932
  stdio: "pipe",
13889
13933
  shell: false
@@ -13964,155 +14008,6 @@ async function updateGitignore(projectDir) {
13964
14008
  logger.warn("Failed to update .gitignore", { error: error.message });
13965
14009
  }
13966
14010
  }
13967
- async function maybeInitializeSpecKit(projectDir, argv) {
13968
- const specifyDir = join(projectDir, ".specify");
13969
- const specifyExists = await checkExists2(specifyDir);
13970
- if (specifyExists) {
13971
- logger.info("Spec-Kit directory already exists, skipping initialization", {
13972
- path: specifyDir
13973
- });
13974
- return true;
13975
- }
13976
- if (argv.skipSpecKit) {
13977
- logger.info("Skipping Spec-Kit initialization (--skip-spec-kit flag)");
13978
- return false;
13979
- }
13980
- if (argv.specKit) {
13981
- console.log(chalk5.cyan("\n\u{1F4CB} Initializing GitHub Spec-Kit..."));
13982
- return await initializeSpecKit(projectDir);
13983
- }
13984
- if (process.stdout.isTTY && process.stdin.isTTY) {
13985
- console.log(chalk5.cyan("\n\u{1F4CB} GitHub Spec-Kit Integration"));
13986
- console.log(chalk5.gray(" Spec-Kit enables spec-driven development workflows."));
13987
- console.log(chalk5.gray(" It creates .specify/ directory with spec.md, plan.md, and tasks.md"));
13988
- console.log(chalk5.gray(" for structured planning and task management.\n"));
13989
- try {
13990
- const prompt = new PromptHelper();
13991
- try {
13992
- const answer = await prompt.question(
13993
- chalk5.cyan(" Initialize Spec-Kit now? (y/N): ")
13994
- );
13995
- const shouldInit = answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
13996
- if (shouldInit) {
13997
- console.log(chalk5.cyan("\n Initializing Spec-Kit..."));
13998
- return await initializeSpecKit(projectDir);
13999
- } else {
14000
- logger.info("User declined Spec-Kit initialization");
14001
- return false;
14002
- }
14003
- } finally {
14004
- prompt.close();
14005
- }
14006
- } catch (error) {
14007
- logger.warn("Failed to prompt for Spec-Kit initialization", {
14008
- error: error.message
14009
- });
14010
- return false;
14011
- }
14012
- }
14013
- logger.info("Non-interactive mode, skipping Spec-Kit initialization");
14014
- return false;
14015
- }
14016
- async function initializeSpecKit(projectDir) {
14017
- try {
14018
- const specifyDir = join(projectDir, ".specify");
14019
- await mkdir(specifyDir, { recursive: true });
14020
- const specTemplate = `# Project Specification
14021
-
14022
- ## Overview
14023
- <!-- Brief description of what this project does -->
14024
-
14025
- ## Goals
14026
- <!-- List the main goals and objectives -->
14027
-
14028
- ## Requirements
14029
- <!-- Detailed requirements -->
14030
-
14031
- ### Functional Requirements
14032
- <!-- What the system should do -->
14033
-
14034
- ### Non-Functional Requirements
14035
- <!-- Performance, security, scalability, etc. -->
14036
-
14037
- ## Success Criteria
14038
- <!-- How do we measure success? -->
14039
-
14040
- ## Out of Scope
14041
- <!-- What this project explicitly does NOT include -->
14042
- `;
14043
- const planTemplate = `# Technical Plan
14044
-
14045
- ## Architecture
14046
- <!-- High-level architecture diagram or description -->
14047
-
14048
- ## Technology Stack
14049
- <!-- Languages, frameworks, libraries, tools -->
14050
-
14051
- ## Implementation Approach
14052
- <!-- Step-by-step approach to implementation -->
14053
-
14054
- ## Data Model
14055
- <!-- Database schema, data structures -->
14056
-
14057
- ## API Design
14058
- <!-- API endpoints, interfaces -->
14059
-
14060
- ## Security Considerations
14061
- <!-- Authentication, authorization, data protection -->
14062
-
14063
- ## Testing Strategy
14064
- <!-- Unit tests, integration tests, E2E tests -->
14065
-
14066
- ## Deployment Plan
14067
- <!-- How will this be deployed? -->
14068
-
14069
- ## Risks and Mitigations
14070
- <!-- Potential risks and how to handle them -->
14071
- `;
14072
- const tasksTemplate = `# Tasks
14073
-
14074
- <!-- Task format: - [ ] id:task-id ops:"command" dep:dependency-id -->
14075
- <!-- Example: -->
14076
- <!-- - [ ] id:setup:env ops:"ax run devops 'Setup development environment'" -->
14077
- <!-- - [ ] id:impl:api ops:"ax run backend 'Implement REST API'" dep:setup:env -->
14078
- <!-- - [ ] id:test:api ops:"ax run quality 'Write API tests'" dep:impl:api -->
14079
-
14080
- ## Phase 1: Setup
14081
- - [ ] id:setup:env ops:"ax run devops 'Setup development environment'"
14082
- - [ ] id:setup:db ops:"ax run backend 'Setup database schema'" dep:setup:env
14083
-
14084
- ## Phase 2: Implementation
14085
- - [ ] id:impl:core ops:"ax run backend 'Implement core functionality'" dep:setup:db
14086
-
14087
- ## Phase 3: Testing
14088
- - [ ] id:test:unit ops:"ax run quality 'Write unit tests'" dep:impl:core
14089
- - [ ] id:test:integration ops:"ax run quality 'Write integration tests'" dep:impl:core
14090
-
14091
- ## Phase 4: Documentation
14092
- - [ ] id:docs:api ops:"ax run writer 'Write API documentation'" dep:impl:core
14093
- `;
14094
- await writeFile(join(specifyDir, "spec.md"), specTemplate, "utf8");
14095
- await writeFile(join(specifyDir, "plan.md"), planTemplate, "utf8");
14096
- await writeFile(join(specifyDir, "tasks.md"), tasksTemplate, "utf8");
14097
- console.log(chalk5.green(" \u2713 Spec-Kit set up successfully"));
14098
- console.log(chalk5.gray(" Files created: .specify/spec.md, plan.md, tasks.md"));
14099
- logger.info("Spec-Kit set up successfully", {
14100
- projectDir,
14101
- specifyDir
14102
- });
14103
- return true;
14104
- } catch (error) {
14105
- const errorMessage = error.message;
14106
- console.log(chalk5.yellow(" \u26A0\uFE0F Failed to initialize Spec-Kit"));
14107
- console.log(chalk5.gray(` ${errorMessage}
14108
- `));
14109
- logger.warn("Spec-Kit initialization failed (non-critical)", {
14110
- error: errorMessage,
14111
- projectDir
14112
- });
14113
- return false;
14114
- }
14115
- }
14116
14011
  async function setupGeminiIntegration(projectDir, packageRoot) {
14117
14012
  const geminiDir = join(projectDir, ".gemini");
14118
14013
  await mkdir(geminiDir, { recursive: true });
@@ -16146,12 +16041,12 @@ var listCommand = {
16146
16041
  };
16147
16042
  async function listAgents(pathResolver, format) {
16148
16043
  const agentsDir = pathResolver.getAgentsDirectory();
16149
- const { existsSync: existsSync25 } = await import('fs');
16044
+ const { existsSync: existsSync26 } = await import('fs');
16150
16045
  const projectDir = await detectProjectRoot();
16151
16046
  const examplesDir = join(projectDir, "examples", "agents");
16152
16047
  try {
16153
16048
  const agentFiles = [];
16154
- if (existsSync25(agentsDir)) {
16049
+ if (existsSync26(agentsDir)) {
16155
16050
  const files = await readdir(agentsDir);
16156
16051
  for (const file of files) {
16157
16052
  if (file.endsWith(".yaml") || file.endsWith(".yml")) {
@@ -16163,7 +16058,7 @@ async function listAgents(pathResolver, format) {
16163
16058
  }
16164
16059
  }
16165
16060
  }
16166
- if (existsSync25(examplesDir)) {
16061
+ if (existsSync26(examplesDir)) {
16167
16062
  const files = await readdir(examplesDir);
16168
16063
  for (const file of files) {
16169
16064
  if (file.endsWith(".yaml") || file.endsWith(".yml")) {
@@ -22176,8 +22071,8 @@ var ProjectContextLoader = class {
22176
22071
  const projectMatch = markdown.match(/>\s*Project:\s*(.+?)$/im);
22177
22072
  if (projectMatch && projectMatch[1]) {
22178
22073
  const parts = projectMatch[1].trim().split(/\s+v/);
22179
- metadata.name = parts[0];
22180
- if (parts[1]) {
22074
+ metadata.name = parts[0] || "";
22075
+ if (parts.length > 1 && parts[1]) {
22181
22076
  metadata.version = parts[1];
22182
22077
  }
22183
22078
  }
@@ -36202,6 +36097,707 @@ function formatForSave(result, format, metadata) {
36202
36097
  }
36203
36098
  return formatOutput(result, format, true);
36204
36099
  }
36100
+
36101
+ // src/core/workflow/index.ts
36102
+ init_esm_shims();
36103
+
36104
+ // src/core/workflow/workflow-mode.ts
36105
+ init_esm_shims();
36106
+ var WorkflowModeSchema = z.enum(["default", "plan", "iterate", "review"]);
36107
+ z.object({
36108
+ name: WorkflowModeSchema,
36109
+ description: z.string(),
36110
+ displayName: z.string(),
36111
+ allowedTools: z.array(z.string()).optional(),
36112
+ blockedTools: z.array(z.string()).optional(),
36113
+ systemInstructions: z.string(),
36114
+ allowNesting: z.boolean(),
36115
+ maxNestingDepth: z.number().int().positive().optional(),
36116
+ autoExitConditions: z.object({
36117
+ maxTurns: z.number().int().positive().optional(),
36118
+ onToolUse: z.array(z.string()).optional(),
36119
+ onKeywords: z.array(z.string()).optional()
36120
+ }).optional()
36121
+ });
36122
+ var WRITE_TOOLS = [
36123
+ "Write",
36124
+ "Edit",
36125
+ "NotebookEdit",
36126
+ "Bash"
36127
+ ];
36128
+ var DEFAULT_MODE_CONFIG = {
36129
+ name: "default",
36130
+ displayName: "Default",
36131
+ description: "Standard operation mode with all tools available",
36132
+ systemInstructions: "",
36133
+ allowNesting: true,
36134
+ maxNestingDepth: 3
36135
+ };
36136
+ var PLAN_MODE_CONFIG = {
36137
+ name: "plan",
36138
+ displayName: "Plan Mode",
36139
+ description: "Planning mode - read-only exploration without code modifications",
36140
+ blockedTools: [...WRITE_TOOLS],
36141
+ systemInstructions: `## Plan Mode Active
36142
+
36143
+ You are in **Plan Mode**. This mode is for exploration and planning only.
36144
+
36145
+ **Restrictions:**
36146
+ - You CANNOT use Write, Edit, or Bash tools that modify files
36147
+ - Focus on reading, searching, and understanding the codebase
36148
+ - Create a comprehensive plan before implementation
36149
+
36150
+ **Your Goals:**
36151
+ 1. Explore the codebase to understand existing patterns
36152
+ 2. Identify files that need to be modified
36153
+ 3. Design an implementation approach
36154
+ 4. Document your plan clearly
36155
+ 5. Use ExitPlanMode when ready to implement
36156
+
36157
+ **Remember:** No code modifications in this mode. Plan first, implement later.`,
36158
+ allowNesting: false,
36159
+ autoExitConditions: {
36160
+ onToolUse: ["ExitPlanMode"]
36161
+ }
36162
+ };
36163
+ var ITERATE_MODE_CONFIG = {
36164
+ name: "iterate",
36165
+ displayName: "Iterate Mode",
36166
+ description: "Continuous iteration mode for implementation with automatic continuation",
36167
+ systemInstructions: `## Iterate Mode Active
36168
+
36169
+ You are in **Iterate Mode**. This mode enables continuous task execution.
36170
+
36171
+ **Behavior:**
36172
+ - Continue working until the task is complete
36173
+ - After each step, assess progress and continue
36174
+ - Don't stop to ask for confirmation unless critical
36175
+ - Mark todos as completed as you finish them
36176
+
36177
+ **Guidelines:**
36178
+ 1. Work through tasks systematically
36179
+ 2. Test changes as you go when possible
36180
+ 3. Update todo list to track progress
36181
+ 4. Only pause for critical decisions or blockers
36182
+
36183
+ **Remember:** Keep iterating until the task is done or you hit a blocker.`,
36184
+ allowNesting: true,
36185
+ maxNestingDepth: 2
36186
+ };
36187
+ var REVIEW_MODE_CONFIG = {
36188
+ name: "review",
36189
+ displayName: "Review Mode",
36190
+ description: "Code review mode - analyze code quality, security, and best practices",
36191
+ blockedTools: [...WRITE_TOOLS],
36192
+ systemInstructions: `## Review Mode Active
36193
+
36194
+ You are in **Review Mode**. This mode is for code review and analysis.
36195
+
36196
+ **Focus Areas:**
36197
+ - Code quality and readability
36198
+ - Security vulnerabilities (OWASP Top 10)
36199
+ - Performance issues
36200
+ - Best practices and patterns
36201
+ - Test coverage gaps
36202
+
36203
+ **Output Format:**
36204
+ Provide structured feedback:
36205
+ 1. **Critical Issues** - Must fix before merge
36206
+ 2. **Warnings** - Should address
36207
+ 3. **Suggestions** - Nice to have improvements
36208
+ 4. **Positive Notes** - Good patterns observed
36209
+
36210
+ **Remember:** No code modifications. Provide actionable feedback only.`,
36211
+ allowNesting: false
36212
+ };
36213
+ var WORKFLOW_MODE_CONFIGS = {
36214
+ default: DEFAULT_MODE_CONFIG,
36215
+ plan: PLAN_MODE_CONFIG,
36216
+ iterate: ITERATE_MODE_CONFIG,
36217
+ review: REVIEW_MODE_CONFIG
36218
+ };
36219
+ function getWorkflowModeConfig(mode) {
36220
+ return WORKFLOW_MODE_CONFIGS[mode];
36221
+ }
36222
+ function isToolAllowedInMode(tool, mode) {
36223
+ const config = getWorkflowModeConfig(mode);
36224
+ if (config.allowedTools && config.allowedTools.length > 0) {
36225
+ return config.allowedTools.includes(tool);
36226
+ }
36227
+ if (config.blockedTools && config.blockedTools.length > 0) {
36228
+ return !config.blockedTools.includes(tool);
36229
+ }
36230
+ return true;
36231
+ }
36232
+ function isValidWorkflowMode(mode) {
36233
+ return Object.prototype.hasOwnProperty.call(WORKFLOW_MODE_CONFIGS, mode);
36234
+ }
36235
+ var WORKFLOW_MODES = WORKFLOW_MODE_CONFIGS;
36236
+
36237
+ // src/core/workflow/workflow-mode-manager.ts
36238
+ init_esm_shims();
36239
+ init_logger();
36240
+
36241
+ // src/core/orchestration/types.ts
36242
+ init_esm_shims();
36243
+ var INSTRUCTION_SOURCE = "automatosx";
36244
+ z.object({
36245
+ type: z.enum(["task", "memory", "session", "delegation", "mode", "context"]),
36246
+ priority: z.enum(["critical", "high", "normal", "low"]),
36247
+ content: z.string().min(1).max(5e3),
36248
+ source: z.literal(INSTRUCTION_SOURCE),
36249
+ expiresAfter: z.number().int().positive().optional(),
36250
+ createdAt: z.number(),
36251
+ createdAtTurn: z.number().int().nonnegative().optional(),
36252
+ id: z.string().optional()
36253
+ });
36254
+ var TodoItemSchema = z.object({
36255
+ id: z.string(),
36256
+ content: z.string().min(1).max(1e3),
36257
+ status: z.enum(["pending", "in_progress", "completed"]),
36258
+ activeForm: z.string().min(1).max(1e3),
36259
+ createdAt: z.number(),
36260
+ updatedAt: z.number().optional(),
36261
+ metadata: z.record(z.string(), z.unknown()).optional()
36262
+ });
36263
+ z.object({
36264
+ name: z.enum(["default", "plan", "iterate", "review"]),
36265
+ description: z.string(),
36266
+ displayName: z.string(),
36267
+ allowedTools: z.array(z.string()).optional(),
36268
+ blockedTools: z.array(z.string()).optional(),
36269
+ systemInstructions: z.string(),
36270
+ allowNesting: z.boolean(),
36271
+ maxNestingDepth: z.number().int().positive().optional(),
36272
+ autoExitConditions: z.object({
36273
+ maxTurns: z.number().int().positive().optional(),
36274
+ onToolUse: z.array(z.string()).optional(),
36275
+ onKeywords: z.array(z.string()).optional()
36276
+ }).optional()
36277
+ });
36278
+ z.object({
36279
+ todos: z.array(TodoItemSchema),
36280
+ currentTask: z.string().optional(),
36281
+ agentName: z.string().optional(),
36282
+ turnCount: z.number().int().nonnegative(),
36283
+ workflowMode: z.enum(["default", "plan", "iterate", "review"]),
36284
+ sessionId: z.string().optional(),
36285
+ parentAgent: z.string().optional(),
36286
+ memories: z.array(z.object({
36287
+ content: z.string(),
36288
+ relevance: z.number().min(0).max(1),
36289
+ agent: z.string().optional(),
36290
+ timestamp: z.number()
36291
+ })).optional()
36292
+ });
36293
+ var DEFAULT_TOKEN_BUDGET = {
36294
+ maxTotal: 2e3,
36295
+ perType: {
36296
+ task: 500,
36297
+ memory: 600,
36298
+ session: 300,
36299
+ delegation: 200,
36300
+ mode: 400,
36301
+ context: 300
36302
+ },
36303
+ criticalReserve: 300
36304
+ };
36305
+ var TokenBudgetConfigSchema = z.object({
36306
+ maxTotal: z.number().int().positive().max(1e4),
36307
+ perType: z.record(
36308
+ z.enum(["task", "memory", "session", "delegation", "mode", "context"]),
36309
+ z.number().int().nonnegative()
36310
+ ),
36311
+ criticalReserve: z.number().int().nonnegative()
36312
+ });
36313
+ var DEFAULT_ORCHESTRATION_CONFIG = {
36314
+ enabled: true,
36315
+ tokenBudget: DEFAULT_TOKEN_BUDGET,
36316
+ todoIntegration: {
36317
+ enabled: true,
36318
+ reminderFrequency: 3,
36319
+ compactMode: false
36320
+ },
36321
+ memoryIntegration: {
36322
+ enabled: true,
36323
+ maxEntries: 5,
36324
+ minRelevance: 0.5
36325
+ },
36326
+ sessionIntegration: {
36327
+ enabled: true,
36328
+ showCollaboration: true
36329
+ },
36330
+ agentTemplates: {
36331
+ enabled: true,
36332
+ reminderFrequency: 5
36333
+ }
36334
+ };
36335
+ z.object({
36336
+ enabled: z.boolean(),
36337
+ tokenBudget: TokenBudgetConfigSchema,
36338
+ todoIntegration: z.object({
36339
+ enabled: z.boolean(),
36340
+ reminderFrequency: z.number().int().positive(),
36341
+ compactMode: z.boolean()
36342
+ }),
36343
+ memoryIntegration: z.object({
36344
+ enabled: z.boolean(),
36345
+ maxEntries: z.number().int().nonnegative(),
36346
+ minRelevance: z.number().min(0).max(1)
36347
+ }),
36348
+ sessionIntegration: z.object({
36349
+ enabled: z.boolean(),
36350
+ showCollaboration: z.boolean()
36351
+ }),
36352
+ agentTemplates: z.object({
36353
+ enabled: z.boolean(),
36354
+ reminderFrequency: z.number().int().positive()
36355
+ })
36356
+ });
36357
+
36358
+ // src/core/workflow/workflow-mode-manager.ts
36359
+ var WorkflowModeManager = class {
36360
+ name = "workflow-mode";
36361
+ modeStack = [];
36362
+ transitionListeners = /* @__PURE__ */ new Set();
36363
+ turnCount = 0;
36364
+ constructor(initialMode = "default") {
36365
+ this.modeStack.push({
36366
+ mode: initialMode,
36367
+ enteredAt: Date.now(),
36368
+ enteredAtTurn: 0,
36369
+ reason: "initial"
36370
+ });
36371
+ logger.debug("WorkflowModeManager initialized", {
36372
+ initialMode
36373
+ });
36374
+ }
36375
+ /**
36376
+ * Get the top entry from the mode stack (private helper to reduce repetition)
36377
+ */
36378
+ getTopEntry() {
36379
+ return this.modeStack[this.modeStack.length - 1];
36380
+ }
36381
+ /**
36382
+ * Get the current active mode
36383
+ */
36384
+ getCurrentMode() {
36385
+ return this.getTopEntry()?.mode ?? "default";
36386
+ }
36387
+ /**
36388
+ * Get the current mode configuration
36389
+ */
36390
+ getCurrentModeConfig() {
36391
+ const mode = this.getCurrentMode();
36392
+ const entry = this.getTopEntry();
36393
+ const baseConfig = getWorkflowModeConfig(mode);
36394
+ if (entry?.customConfig) {
36395
+ const mergedAutoExit = entry.customConfig.autoExitConditions || baseConfig.autoExitConditions ? {
36396
+ ...baseConfig.autoExitConditions ?? {},
36397
+ ...entry.customConfig.autoExitConditions ?? {}
36398
+ } : void 0;
36399
+ return {
36400
+ ...baseConfig,
36401
+ ...entry.customConfig,
36402
+ // Deep merge for nested objects
36403
+ autoExitConditions: mergedAutoExit
36404
+ };
36405
+ }
36406
+ return baseConfig;
36407
+ }
36408
+ /**
36409
+ * Get the full mode stack
36410
+ */
36411
+ getModeStack() {
36412
+ return [...this.modeStack];
36413
+ }
36414
+ /**
36415
+ * Get the current stack depth
36416
+ */
36417
+ getStackDepth() {
36418
+ return this.modeStack.length;
36419
+ }
36420
+ /**
36421
+ * Push a new mode onto the stack
36422
+ */
36423
+ pushMode(mode, options) {
36424
+ const currentConfig = this.getCurrentModeConfig();
36425
+ if (!currentConfig.allowNesting) {
36426
+ logger.warn("Cannot push mode: current mode does not allow nesting", {
36427
+ currentMode: this.getCurrentMode(),
36428
+ attemptedMode: mode
36429
+ });
36430
+ return false;
36431
+ }
36432
+ const maxDepth = currentConfig.maxNestingDepth ?? 3;
36433
+ if (this.modeStack.length >= maxDepth) {
36434
+ logger.warn("Cannot push mode: max nesting depth reached", {
36435
+ currentDepth: this.modeStack.length,
36436
+ maxDepth
36437
+ });
36438
+ return false;
36439
+ }
36440
+ const previousMode = this.getCurrentMode();
36441
+ this.modeStack.push({
36442
+ mode,
36443
+ enteredAt: Date.now(),
36444
+ enteredAtTurn: this.turnCount,
36445
+ customConfig: options?.customConfig,
36446
+ reason: options?.reason
36447
+ });
36448
+ this.emitTransition({
36449
+ from: previousMode,
36450
+ to: mode,
36451
+ type: "push",
36452
+ timestamp: Date.now(),
36453
+ reason: options?.reason
36454
+ });
36455
+ logger.info("Pushed workflow mode", {
36456
+ from: previousMode,
36457
+ to: mode,
36458
+ stackDepth: this.modeStack.length,
36459
+ reason: options?.reason
36460
+ });
36461
+ return true;
36462
+ }
36463
+ /**
36464
+ * Pop the current mode from the stack
36465
+ */
36466
+ popMode(reason) {
36467
+ if (this.modeStack.length <= 1) {
36468
+ logger.warn("Cannot pop mode: at base level");
36469
+ return null;
36470
+ }
36471
+ const popped = this.modeStack.pop();
36472
+ const newMode = this.getCurrentMode();
36473
+ if (popped) {
36474
+ this.emitTransition({
36475
+ from: popped.mode,
36476
+ to: newMode,
36477
+ type: "pop",
36478
+ timestamp: Date.now(),
36479
+ reason
36480
+ });
36481
+ logger.info("Popped workflow mode", {
36482
+ from: popped.mode,
36483
+ to: newMode,
36484
+ stackDepth: this.modeStack.length,
36485
+ reason
36486
+ });
36487
+ }
36488
+ return popped?.mode ?? null;
36489
+ }
36490
+ /**
36491
+ * Replace the current mode (pop then push)
36492
+ */
36493
+ replaceMode(mode, options) {
36494
+ const previousMode = this.getCurrentMode();
36495
+ if (this.modeStack.length === 1) {
36496
+ this.modeStack[0] = {
36497
+ mode,
36498
+ enteredAt: Date.now(),
36499
+ enteredAtTurn: this.turnCount,
36500
+ customConfig: options?.customConfig,
36501
+ reason: options?.reason
36502
+ };
36503
+ } else {
36504
+ this.modeStack.pop();
36505
+ this.modeStack.push({
36506
+ mode,
36507
+ enteredAt: Date.now(),
36508
+ enteredAtTurn: this.turnCount,
36509
+ customConfig: options?.customConfig,
36510
+ reason: options?.reason
36511
+ });
36512
+ }
36513
+ this.emitTransition({
36514
+ from: previousMode,
36515
+ to: mode,
36516
+ type: "replace",
36517
+ timestamp: Date.now(),
36518
+ reason: options?.reason
36519
+ });
36520
+ logger.info("Replaced workflow mode", {
36521
+ from: previousMode,
36522
+ to: mode,
36523
+ reason: options?.reason
36524
+ });
36525
+ return true;
36526
+ }
36527
+ /**
36528
+ * Set mode directly (clears stack and sets new base mode)
36529
+ */
36530
+ setMode(mode, options) {
36531
+ const previousMode = this.getCurrentMode();
36532
+ this.modeStack = [{
36533
+ mode,
36534
+ enteredAt: Date.now(),
36535
+ enteredAtTurn: this.turnCount,
36536
+ customConfig: options?.customConfig,
36537
+ reason: options?.reason
36538
+ }];
36539
+ this.emitTransition({
36540
+ from: previousMode,
36541
+ to: mode,
36542
+ type: "replace",
36543
+ timestamp: Date.now(),
36544
+ reason: options?.reason
36545
+ });
36546
+ logger.info("Set workflow mode", {
36547
+ from: previousMode,
36548
+ to: mode,
36549
+ reason: options?.reason
36550
+ });
36551
+ }
36552
+ /**
36553
+ * Check if a tool is allowed in the current mode
36554
+ */
36555
+ isToolAllowed(tool) {
36556
+ return isToolAllowedInMode(tool, this.getCurrentMode());
36557
+ }
36558
+ /**
36559
+ * Get list of blocked tools in current mode
36560
+ */
36561
+ getBlockedTools() {
36562
+ const config = this.getCurrentModeConfig();
36563
+ return config.blockedTools || [];
36564
+ }
36565
+ /**
36566
+ * Filter a list of tools based on current mode
36567
+ */
36568
+ filterTools(tools) {
36569
+ return tools.filter((tool) => this.isToolAllowed(tool.name));
36570
+ }
36571
+ /**
36572
+ * Update turn count (for auto-exit tracking)
36573
+ */
36574
+ updateTurnCount(turn) {
36575
+ this.turnCount = turn;
36576
+ this.checkAutoExit();
36577
+ }
36578
+ /**
36579
+ * Check and handle auto-exit conditions
36580
+ */
36581
+ checkAutoExit() {
36582
+ const config = this.getCurrentModeConfig();
36583
+ const entry = this.getTopEntry();
36584
+ if (!config.autoExitConditions || !entry) return;
36585
+ if (config.autoExitConditions.maxTurns) {
36586
+ const turnsInMode = this.turnCount - entry.enteredAtTurn;
36587
+ if (turnsInMode >= config.autoExitConditions.maxTurns) {
36588
+ logger.info("Auto-exiting mode due to max turns", {
36589
+ mode: this.getCurrentMode(),
36590
+ turnsInMode,
36591
+ maxTurns: config.autoExitConditions.maxTurns
36592
+ });
36593
+ this.popMode("max_turns_reached");
36594
+ }
36595
+ }
36596
+ }
36597
+ /**
36598
+ * Notify that a tool was used (for auto-exit on tool use)
36599
+ */
36600
+ notifyToolUsed(tool) {
36601
+ const config = this.getCurrentModeConfig();
36602
+ if (config.autoExitConditions?.onToolUse?.includes(tool)) {
36603
+ logger.info("Auto-exiting mode due to tool use", {
36604
+ mode: this.getCurrentMode(),
36605
+ tool
36606
+ });
36607
+ this.popMode(`tool_used:${tool}`);
36608
+ }
36609
+ }
36610
+ /**
36611
+ * Add a mode transition listener
36612
+ */
36613
+ onTransition(listener) {
36614
+ this.transitionListeners.add(listener);
36615
+ return () => this.transitionListeners.delete(listener);
36616
+ }
36617
+ /**
36618
+ * Emit a transition event to all listeners
36619
+ */
36620
+ emitTransition(event) {
36621
+ for (const listener of this.transitionListeners) {
36622
+ try {
36623
+ listener(event);
36624
+ } catch (error) {
36625
+ logger.error("Mode transition listener error", {
36626
+ error: error instanceof Error ? error.message : String(error)
36627
+ });
36628
+ }
36629
+ }
36630
+ }
36631
+ // InstructionProvider implementation
36632
+ /**
36633
+ * Check if mode instructions should be generated
36634
+ */
36635
+ shouldGenerate(context) {
36636
+ return this.getCurrentMode() !== "default";
36637
+ }
36638
+ /**
36639
+ * Get mode-specific instructions
36640
+ */
36641
+ async getInstructions(context) {
36642
+ const config = this.getCurrentModeConfig();
36643
+ const instructions = [];
36644
+ if (config.systemInstructions && config.systemInstructions.length > 0) {
36645
+ instructions.push({
36646
+ type: "mode",
36647
+ priority: "high",
36648
+ content: config.systemInstructions,
36649
+ source: INSTRUCTION_SOURCE,
36650
+ createdAt: Date.now(),
36651
+ id: `mode-${config.name}-${Date.now()}`
36652
+ });
36653
+ }
36654
+ if (config.blockedTools && config.blockedTools.length > 0) {
36655
+ instructions.push({
36656
+ type: "mode",
36657
+ priority: "critical",
36658
+ content: `**Tool Restrictions:** The following tools are NOT available in ${config.displayName}: ${config.blockedTools.join(", ")}`,
36659
+ source: INSTRUCTION_SOURCE,
36660
+ createdAt: Date.now(),
36661
+ id: `mode-blocked-tools-${Date.now()}`
36662
+ });
36663
+ }
36664
+ return instructions;
36665
+ }
36666
+ /**
36667
+ * Reset to default state
36668
+ */
36669
+ reset() {
36670
+ const previousMode = this.getCurrentMode();
36671
+ this.modeStack = [{
36672
+ mode: "default",
36673
+ enteredAt: Date.now(),
36674
+ enteredAtTurn: 0,
36675
+ reason: "reset"
36676
+ }];
36677
+ this.turnCount = 0;
36678
+ if (previousMode !== "default") {
36679
+ this.emitTransition({
36680
+ from: previousMode,
36681
+ to: "default",
36682
+ type: "replace",
36683
+ timestamp: Date.now(),
36684
+ reason: "reset"
36685
+ });
36686
+ }
36687
+ logger.debug("WorkflowModeManager reset");
36688
+ }
36689
+ /**
36690
+ * Get status information for debugging
36691
+ */
36692
+ getStatus() {
36693
+ return {
36694
+ currentMode: this.getCurrentMode(),
36695
+ stackDepth: this.modeStack.length,
36696
+ stack: this.modeStack.map((entry) => ({
36697
+ mode: entry.mode,
36698
+ enteredAt: entry.enteredAt,
36699
+ reason: entry.reason
36700
+ })),
36701
+ blockedTools: this.getBlockedTools(),
36702
+ turnCount: this.turnCount
36703
+ };
36704
+ }
36705
+ };
36706
+
36707
+ // src/core/workflow/mode-state-manager.ts
36708
+ init_esm_shims();
36709
+ init_logger();
36710
+ init_path_resolver();
36711
+ var ModeStateSchema = z.object({
36712
+ mode: z.enum(["default", "plan", "iterate", "review"]),
36713
+ setAt: z.number(),
36714
+ setBy: z.string().optional(),
36715
+ reason: z.string().optional(),
36716
+ expiresAt: z.number().optional()
36717
+ });
36718
+ var STATE_FILE_PATH = ".automatosx/state/mode.json";
36719
+ var DEFAULT_EXPIRATION_MS = 4 * 60 * 60 * 1e3;
36720
+ async function getStateFilePath() {
36721
+ const projectRoot = await detectProjectRoot(process.cwd());
36722
+ return join(projectRoot, STATE_FILE_PATH);
36723
+ }
36724
+ async function loadModeState() {
36725
+ try {
36726
+ const statePath = await getStateFilePath();
36727
+ if (!existsSync(statePath)) {
36728
+ logger.debug("No mode state file found", { path: statePath });
36729
+ return null;
36730
+ }
36731
+ const content = readFileSync(statePath, "utf-8");
36732
+ const parsed = JSON.parse(content);
36733
+ const result = ModeStateSchema.safeParse(parsed);
36734
+ if (!result.success) {
36735
+ logger.warn("Invalid mode state file", {
36736
+ path: statePath,
36737
+ error: result.error.message
36738
+ });
36739
+ return null;
36740
+ }
36741
+ const state = result.data;
36742
+ if (state.expiresAt && Date.now() > state.expiresAt) {
36743
+ logger.debug("Mode state expired", {
36744
+ mode: state.mode,
36745
+ expiredAt: new Date(state.expiresAt).toISOString()
36746
+ });
36747
+ return null;
36748
+ }
36749
+ logger.debug("Loaded mode state", {
36750
+ mode: state.mode,
36751
+ setAt: new Date(state.setAt).toISOString()
36752
+ });
36753
+ return state;
36754
+ } catch (error) {
36755
+ logger.error("Failed to load mode state", {
36756
+ error: error instanceof Error ? error.message : String(error)
36757
+ });
36758
+ return null;
36759
+ }
36760
+ }
36761
+ async function saveModeState(mode, options) {
36762
+ try {
36763
+ const statePath = await getStateFilePath();
36764
+ const stateDir = dirname(statePath);
36765
+ if (!existsSync(stateDir)) {
36766
+ mkdirSync(stateDir, { recursive: true });
36767
+ }
36768
+ const state = {
36769
+ mode,
36770
+ setAt: Date.now(),
36771
+ setBy: options?.setBy ?? "cli",
36772
+ reason: options?.reason,
36773
+ expiresAt: Date.now() + (options?.expiresIn ?? DEFAULT_EXPIRATION_MS)
36774
+ };
36775
+ writeFileSync(statePath, JSON.stringify(state, null, 2), "utf-8");
36776
+ logger.debug("Saved mode state", {
36777
+ mode,
36778
+ expiresAt: new Date(state.expiresAt).toISOString()
36779
+ });
36780
+ return true;
36781
+ } catch (error) {
36782
+ logger.error("Failed to save mode state", {
36783
+ error: error instanceof Error ? error.message : String(error)
36784
+ });
36785
+ return false;
36786
+ }
36787
+ }
36788
+ async function getCurrentPersistedMode() {
36789
+ const state = await loadModeState();
36790
+ return state?.mode ?? "default";
36791
+ }
36792
+ function isModePersistenceEnabled() {
36793
+ return process.env.AX_DISABLE_MODE_PERSISTENCE !== "true";
36794
+ }
36795
+
36796
+ // src/core/workflow/workflow-progress-provider.ts
36797
+ init_esm_shims();
36798
+ init_logger();
36799
+
36800
+ // src/cli/commands/run.ts
36205
36801
  function displayAutoSelectionResult(selection, verbosity, showBanner = true) {
36206
36802
  if (!showBanner || !verbosity.shouldShow("showBanner")) return;
36207
36803
  const confidenceEmoji = selection.confidence === "high" ? "\u2705" : selection.confidence === "medium" ? "\u26A1" : "\u{1F4A1}";
@@ -36225,10 +36821,10 @@ var runCommand = {
36225
36821
  }).positional("task", {
36226
36822
  describe: "Task to execute",
36227
36823
  type: "string"
36228
- }).option("no-auto-select", {
36229
- describe: "Disable agent auto-selection (v11.1.0+)",
36824
+ }).option("auto-select", {
36825
+ describe: "Enable agent auto-selection when agent not found (v11.1.0+)",
36230
36826
  type: "boolean",
36231
- default: false
36827
+ default: true
36232
36828
  }).option("provider", {
36233
36829
  describe: "Override provider (claude, gemini, openai)",
36234
36830
  type: "string"
@@ -36301,10 +36897,6 @@ var runCommand = {
36301
36897
  describe: "Show execution timeline after completion (requires --parallel)",
36302
36898
  type: "boolean",
36303
36899
  default: true
36304
- }).option("no-spec", {
36305
- describe: "Bypass spec-kit suggestion for complex tasks (v5.8.3+)",
36306
- type: "boolean",
36307
- default: false
36308
36900
  }).option("sandbox", {
36309
36901
  describe: "Sandbox mode for code execution (v6.0.7 Phase 3)",
36310
36902
  type: "string",
@@ -36370,7 +36962,7 @@ var runCommand = {
36370
36962
  console.log(chalk5.gray(' ax run backend "implement API" # uses specified agent'));
36371
36963
  process.exit(1);
36372
36964
  }
36373
- if (!agentProvided && argv.noAutoSelect) {
36965
+ if (!agentProvided && argv.autoSelect === false) {
36374
36966
  console.log(chalk5.red.bold("\n\u274C Error: Agent name is required when --no-auto-select is used\n"));
36375
36967
  console.log(chalk5.gray("Usage: ax run <agent> <task> --no-auto-select"));
36376
36968
  process.exit(1);
@@ -36436,6 +37028,32 @@ var runCommand = {
36436
37028
  process.exit(1);
36437
37029
  }
36438
37030
  }
37031
+ if (!argv.workflow && !argv.iterate && isModePersistenceEnabled()) {
37032
+ const persistedMode = await getCurrentPersistedMode();
37033
+ if (persistedMode === "iterate") {
37034
+ argv.iterate = true;
37035
+ if (verbosity.shouldShow("showBanner")) {
37036
+ console.log(chalk5.cyan(`\u{1F4CB} Using persisted mode: iterate`));
37037
+ console.log(chalk5.gray(` (set via \`ax mode iterate\`, use \`ax mode default\` to clear)
37038
+ `));
37039
+ }
37040
+ logger.info("Applied persisted iterate mode");
37041
+ } else if (persistedMode === "plan") {
37042
+ if (verbosity.shouldShow("showBanner")) {
37043
+ console.log(chalk5.cyan(`\u{1F4CB} Using persisted mode: plan`));
37044
+ console.log(chalk5.gray(` (read-only exploration mode)
37045
+ `));
37046
+ }
37047
+ logger.info("Applied persisted plan mode");
37048
+ } else if (persistedMode === "review") {
37049
+ if (verbosity.shouldShow("showBanner")) {
37050
+ console.log(chalk5.cyan(`\u{1F4CB} Using persisted mode: review`));
37051
+ console.log(chalk5.gray(` (code review mode)
37052
+ `));
37053
+ }
37054
+ logger.info("Applied persisted review mode");
37055
+ }
37056
+ }
36439
37057
  if (verbosity.isQuiet()) {
36440
37058
  argv.showDependencyGraph = false;
36441
37059
  argv.showTimeline = false;
@@ -36505,7 +37123,7 @@ var runCommand = {
36505
37123
  }
36506
37124
  }
36507
37125
  } catch (error) {
36508
- if (argv.noAutoSelect) {
37126
+ if (argv.autoSelect === false) {
36509
37127
  console.error(chalk5.red.bold(`
36510
37128
  \u274C Agent not found: ${actualAgent}
36511
37129
  `));
@@ -38052,11 +38670,11 @@ async function getCurrentVersion() {
38052
38670
  return result.dependencies["@defai.digital/automatosx"]?.version || "unknown";
38053
38671
  } catch (error) {
38054
38672
  const { readFile: readFile24 } = await import('fs/promises');
38055
- const { dirname: dirname14, join: join49 } = await import('path');
38673
+ const { dirname: dirname15, join: join50 } = await import('path');
38056
38674
  const { fileURLToPath: fileURLToPath5 } = await import('url');
38057
38675
  const __filename3 = fileURLToPath5(import.meta.url);
38058
- const __dirname4 = dirname14(__filename3);
38059
- const pkgPath = join49(__dirname4, "../../../package.json");
38676
+ const __dirname4 = dirname15(__filename3);
38677
+ const pkgPath = join50(__dirname4, "../../../package.json");
38060
38678
  const content = await readFile24(pkgPath, "utf-8");
38061
38679
  const pkg = JSON.parse(content);
38062
38680
  return pkg.version;
@@ -44867,24 +45485,24 @@ async function handleList(config, argv) {
44867
45485
  });
44868
45486
  }
44869
45487
  }
44870
- let displayProviders = argv.available ? providers.filter((p) => p.enabled && !p.limitInfo?.isBlocked) : providers;
45488
+ let displayProviders2 = argv.available ? providers.filter((p) => p.enabled && !p.limitInfo?.isBlocked) : providers;
44871
45489
  switch (argv.sort) {
44872
45490
  case "cost":
44873
- displayProviders.sort((a, b) => {
45491
+ displayProviders2.sort((a, b) => {
44874
45492
  const costA = a.metadata ? (a.metadata.costPerToken.input + a.metadata.costPerToken.output) / 2 : Infinity;
44875
45493
  const costB = b.metadata ? (b.metadata.costPerToken.input + b.metadata.costPerToken.output) / 2 : Infinity;
44876
45494
  return costA - costB;
44877
45495
  });
44878
45496
  break;
44879
45497
  case "latency":
44880
- displayProviders.sort((a, b) => {
45498
+ displayProviders2.sort((a, b) => {
44881
45499
  const latA = a.metadata?.latencyEstimate.p95 || Infinity;
44882
45500
  const latB = b.metadata?.latencyEstimate.p95 || Infinity;
44883
45501
  return latA - latB;
44884
45502
  });
44885
45503
  break;
44886
45504
  case "reliability":
44887
- displayProviders.sort((a, b) => {
45505
+ displayProviders2.sort((a, b) => {
44888
45506
  const relA = a.metadata?.reliability.availability || 0;
44889
45507
  const relB = b.metadata?.reliability.availability || 0;
44890
45508
  return relB - relA;
@@ -44892,15 +45510,15 @@ async function handleList(config, argv) {
44892
45510
  break;
44893
45511
  case "priority":
44894
45512
  default:
44895
- displayProviders.sort((a, b) => a.priority - b.priority);
45513
+ displayProviders2.sort((a, b) => a.priority - b.priority);
44896
45514
  break;
44897
45515
  }
44898
45516
  if (argv.json) {
44899
- console.log(JSON.stringify({ providers: displayProviders }, null, 2));
45517
+ console.log(JSON.stringify({ providers: displayProviders2 }, null, 2));
44900
45518
  return;
44901
45519
  }
44902
45520
  console.log(chalk5.gray("Provider Status & Metadata:\n"));
44903
- for (const provider of displayProviders) {
45521
+ for (const provider of displayProviders2) {
44904
45522
  const status = provider.enabled ? provider.limitInfo?.isBlocked ? chalk5.red("\u25CF BLOCKED") : chalk5.green("\u25CF ENABLED") : chalk5.gray("\u25CB DISABLED");
44905
45523
  console.log(`${status} ${chalk5.bold(provider.name)} ${chalk5.gray(`(priority: ${provider.priority})`)}`);
44906
45524
  if (provider.metadata && argv.verbose) {
@@ -45088,10 +45706,10 @@ async function handleReset() {
45088
45706
  `));
45089
45707
  }
45090
45708
  async function handleTrace(workspacePath, argv) {
45091
- const { existsSync: existsSync25, readFileSync: readFileSync8, watchFile } = await import('fs');
45092
- const { join: join49 } = await import('path');
45093
- const traceFile = join49(workspacePath, ".automatosx/logs/router.trace.jsonl");
45094
- if (!existsSync25(traceFile)) {
45709
+ const { existsSync: existsSync26, readFileSync: readFileSync9, watchFile } = await import('fs');
45710
+ const { join: join50 } = await import('path');
45711
+ const traceFile = join50(workspacePath, ".automatosx/logs/router.trace.jsonl");
45712
+ if (!existsSync26(traceFile)) {
45095
45713
  console.log(chalk5.yellow("\n\u26A0\uFE0F No trace log found\n"));
45096
45714
  console.log(chalk5.gray(`Expected location: ${traceFile}
45097
45715
  `));
@@ -45108,7 +45726,7 @@ async function handleTrace(workspacePath, argv) {
45108
45726
  `));
45109
45727
  if (argv.follow) {
45110
45728
  console.log(chalk5.gray("Following trace log (Ctrl+C to exit)...\n"));
45111
- const content = readFileSync8(traceFile, "utf-8");
45729
+ const content = readFileSync9(traceFile, "utf-8");
45112
45730
  const lines = content.split("\n").filter((l) => l.trim());
45113
45731
  const recentLines = lines.slice(-(argv.lines || 20));
45114
45732
  for (const line of recentLines) {
@@ -45118,7 +45736,7 @@ async function handleTrace(workspacePath, argv) {
45118
45736
  const { unwatchFile } = await import('fs');
45119
45737
  watchFile(traceFile, { interval: 500 }, (curr, prev) => {
45120
45738
  if (curr.size > lastSize) {
45121
- const newContent = readFileSync8(traceFile, "utf-8");
45739
+ const newContent = readFileSync9(traceFile, "utf-8");
45122
45740
  const newLines = newContent.slice(lastSize).split("\n").filter((l) => l.trim());
45123
45741
  for (const line of newLines) {
45124
45742
  displayTraceEvent(line);
@@ -45136,7 +45754,7 @@ async function handleTrace(workspacePath, argv) {
45136
45754
  await new Promise(() => {
45137
45755
  });
45138
45756
  } else {
45139
- const content = readFileSync8(traceFile, "utf-8");
45757
+ const content = readFileSync9(traceFile, "utf-8");
45140
45758
  const lines = content.split("\n").filter((l) => l.trim());
45141
45759
  const recentLines = lines.slice(-(argv.lines || 20));
45142
45760
  if (recentLines.length === 0) {
@@ -46147,9 +46765,11 @@ async function checkDiskSpace(workingDir, verbose) {
46147
46765
  timeout: 5e3
46148
46766
  });
46149
46767
  const parts = dfOutput.trim().split(/\s+/);
46150
- const availableKB = parseInt(parts[3] || "0", 10);
46151
- const availableMB = Math.round(availableKB / 1024);
46152
- const availableGB = (availableKB / (1024 * 1024)).toFixed(2);
46768
+ const rawAvailable = parts.length > 3 ? parts[3] : "0";
46769
+ const availableKB = parseInt(rawAvailable || "0", 10);
46770
+ const safeAvailableKB = isNaN(availableKB) ? 0 : availableKB;
46771
+ const availableMB = Math.round(safeAvailableKB / 1024);
46772
+ const availableGB = (safeAvailableKB / (1024 * 1024)).toFixed(2);
46153
46773
  const hasEnoughSpace = availableMB > 100;
46154
46774
  results.push({
46155
46775
  name: "Available Disk Space",
@@ -47294,10 +47914,14 @@ var OptimizationAnalyzer = class {
47294
47914
  * Analyze usage and generate recommendations
47295
47915
  */
47296
47916
  async analyze(timeRange) {
47297
- logger.debug("Analyzing for optimization opportunities", { timeRange });
47917
+ logger.debug("Analyzing for optimization opportunities", {
47918
+ timeRange,
47919
+ provider: timeRange.provider
47920
+ });
47298
47921
  const summary = await this.analytics.generateSummary({
47299
47922
  startDate: timeRange.start,
47300
- endDate: timeRange.end
47923
+ endDate: timeRange.end,
47924
+ provider: timeRange.provider
47301
47925
  });
47302
47926
  const recommendations = [];
47303
47927
  recommendations.push(...this.findModelDowngradeOpportunities(summary));
@@ -47384,6 +48008,7 @@ var OptimizationAnalyzer = class {
47384
48008
  type: "cache_hit",
47385
48009
  startDate: timeRange.start,
47386
48010
  endDate: timeRange.end,
48011
+ provider: timeRange.provider,
47387
48012
  limit: 1e4
47388
48013
  });
47389
48014
  const totalExecutions = summary.executions.total;
@@ -47526,10 +48151,11 @@ var analyticsCommand = {
47526
48151
  }
47527
48152
  };
47528
48153
  async function summaryHandler(argv) {
48154
+ let telemetry;
47529
48155
  try {
47530
48156
  const config = await loadConfig(process.cwd());
47531
48157
  const telemetryConfig = config.telemetry || { enabled: false };
47532
- const telemetry = getTelemetryCollector({
48158
+ telemetry = getTelemetryCollector({
47533
48159
  ...telemetryConfig,
47534
48160
  enabled: true
47535
48161
  });
@@ -47537,15 +48163,19 @@ async function summaryHandler(argv) {
47537
48163
  const timeRange = parseTimePeriod(argv.period || "7d");
47538
48164
  const summary = await analytics.generateSummary({
47539
48165
  startDate: timeRange.startDate,
47540
- endDate: timeRange.endDate
48166
+ endDate: timeRange.endDate,
48167
+ provider: argv.provider
47541
48168
  });
47542
48169
  if (argv.format === "json") {
47543
48170
  console.log(JSON.stringify(summary, null, 2));
47544
48171
  return;
47545
48172
  }
47546
48173
  console.log(chalk5.bold.cyan("\n\u{1F4CA} AutomatosX Analytics Summary\n"));
47547
- console.log(chalk5.dim(`Period: ${formatPeriod(argv.period || "7d")}
47548
- `));
48174
+ console.log(chalk5.dim(`Period: ${formatPeriod(argv.period || "7d")}`));
48175
+ if (argv.provider) {
48176
+ console.log(chalk5.dim(`Provider filter: ${argv.provider}`));
48177
+ }
48178
+ console.log();
47549
48179
  console.log(chalk5.bold("Executions"));
47550
48180
  console.log(` Total: ${summary.executions.total}`);
47551
48181
  console.log(` Successful: ${chalk5.green(summary.executions.successful)}`);
@@ -47589,13 +48219,16 @@ async function summaryHandler(argv) {
47589
48219
  });
47590
48220
  logger.error("Analytics summary failed", { error: error.message });
47591
48221
  process.exit(1);
48222
+ } finally {
48223
+ await telemetry?.close();
47592
48224
  }
47593
48225
  }
47594
48226
  async function optimizeHandler(argv) {
48227
+ let telemetry;
47595
48228
  try {
47596
48229
  const config = await loadConfig(process.cwd());
47597
48230
  const telemetryConfig = config.telemetry || { enabled: false };
47598
- const telemetry = getTelemetryCollector({
48231
+ telemetry = getTelemetryCollector({
47599
48232
  ...telemetryConfig,
47600
48233
  enabled: true
47601
48234
  });
@@ -47604,15 +48237,19 @@ async function optimizeHandler(argv) {
47604
48237
  const timeRange = parseTimePeriod(argv.period || "7d");
47605
48238
  const recommendations = await optimizer.analyze({
47606
48239
  start: timeRange.startDate,
47607
- end: timeRange.endDate
48240
+ end: timeRange.endDate,
48241
+ provider: argv.provider
47608
48242
  });
47609
48243
  if (argv.format === "json") {
47610
48244
  console.log(JSON.stringify(recommendations, null, 2));
47611
48245
  return;
47612
48246
  }
47613
48247
  console.log(chalk5.bold.cyan("\n\u{1F4A1} Optimization Recommendations\n"));
47614
- console.log(chalk5.dim(`Period: ${formatPeriod(argv.period || "7d")}
47615
- `));
48248
+ console.log(chalk5.dim(`Period: ${formatPeriod(argv.period || "7d")}`));
48249
+ if (argv.provider) {
48250
+ console.log(chalk5.dim(`Provider filter: ${argv.provider}`));
48251
+ }
48252
+ console.log();
47616
48253
  if (recommendations.length === 0) {
47617
48254
  console.log(chalk5.green("\u2705 No optimization opportunities found. You're doing great!\n"));
47618
48255
  return;
@@ -47645,13 +48282,16 @@ async function optimizeHandler(argv) {
47645
48282
  });
47646
48283
  logger.error("Optimization analysis failed", { error: error.message });
47647
48284
  process.exit(1);
48285
+ } finally {
48286
+ await telemetry?.close();
47648
48287
  }
47649
48288
  }
47650
48289
  async function clearHandler(argv) {
48290
+ let telemetry;
47651
48291
  try {
47652
48292
  const config = await loadConfig(process.cwd());
47653
48293
  const telemetryConfig = config.telemetry || { enabled: false };
47654
- const telemetry = getTelemetryCollector({
48294
+ telemetry = getTelemetryCollector({
47655
48295
  ...telemetryConfig,
47656
48296
  enabled: true
47657
48297
  });
@@ -47678,13 +48318,16 @@ async function clearHandler(argv) {
47678
48318
  });
47679
48319
  logger.error("Clear telemetry failed", { error: error.message });
47680
48320
  process.exit(1);
48321
+ } finally {
48322
+ await telemetry?.close();
47681
48323
  }
47682
48324
  }
47683
48325
  async function statusHandler(argv) {
48326
+ let telemetry;
47684
48327
  try {
47685
48328
  const config = await loadConfig(process.cwd());
47686
48329
  const telemetryConfig = config.telemetry || { enabled: false };
47687
- const telemetry = getTelemetryCollector({
48330
+ telemetry = getTelemetryCollector({
47688
48331
  ...telemetryConfig,
47689
48332
  enabled: true
47690
48333
  });
@@ -47711,6 +48354,8 @@ async function statusHandler(argv) {
47711
48354
  });
47712
48355
  logger.error("Telemetry status failed", { error: error.message });
47713
48356
  process.exit(1);
48357
+ } finally {
48358
+ await telemetry?.close();
47714
48359
  }
47715
48360
  }
47716
48361
  function parseTimePeriod(period) {
@@ -48519,6 +49164,2782 @@ var uninstallCommand = {
48519
49164
  }
48520
49165
  };
48521
49166
 
49167
+ // src/cli/commands/mode.ts
49168
+ init_esm_shims();
49169
+ init_logger();
49170
+ var modeCommand = {
49171
+ command: "mode [mode]",
49172
+ describe: "Manage workflow modes for embedded instructions (v11.3.0)",
49173
+ builder: (yargs2) => {
49174
+ return yargs2.positional("mode", {
49175
+ describe: "Workflow mode to set (default, plan, iterate, review)",
49176
+ type: "string"
49177
+ }).option("list", {
49178
+ alias: "l",
49179
+ describe: "List available workflow modes",
49180
+ type: "boolean",
49181
+ default: false
49182
+ }).option("status", {
49183
+ alias: "s",
49184
+ describe: "Show current workflow mode status",
49185
+ type: "boolean",
49186
+ default: false
49187
+ }).example("$0 mode plan", "Enter plan mode (restricts code-modifying tools)").example("$0 mode iterate", "Enter iterate mode (for autonomous execution)").example("$0 mode default", "Return to default mode").example("$0 mode --list", "List all available modes").example("$0 mode --status", "Show current mode status");
49188
+ },
49189
+ handler: async (argv) => {
49190
+ try {
49191
+ if (argv.list) {
49192
+ displayModeList();
49193
+ return;
49194
+ }
49195
+ if (argv.status || !argv.mode) {
49196
+ await displayModeStatus();
49197
+ return;
49198
+ }
49199
+ const modeName = argv.mode.toLowerCase();
49200
+ if (!isValidWorkflowMode(modeName)) {
49201
+ console.error(chalk5.red.bold(`
49202
+ \u274C Invalid workflow mode: ${argv.mode}
49203
+ `));
49204
+ console.log(chalk5.gray("Available modes:"));
49205
+ Object.keys(WORKFLOW_MODES).forEach((mode) => {
49206
+ console.log(chalk5.cyan(` \u2022 ${mode}`));
49207
+ });
49208
+ console.log();
49209
+ process.exit(1);
49210
+ }
49211
+ const modeConfig = WORKFLOW_MODES[modeName];
49212
+ if (isModePersistenceEnabled()) {
49213
+ const saved = await saveModeState(modeName, {
49214
+ setBy: "cli",
49215
+ reason: `ax mode ${modeName}`
49216
+ });
49217
+ if (saved) {
49218
+ console.log(chalk5.green.bold(`
49219
+ \u2705 Workflow mode set to: ${modeName}
49220
+ `));
49221
+ console.log(chalk5.gray(`Description: ${modeConfig.description}`));
49222
+ } else {
49223
+ console.log(chalk5.yellow.bold(`
49224
+ \u26A0\uFE0F Mode set to: ${modeName} (not persisted)
49225
+ `));
49226
+ console.log(chalk5.gray(`Description: ${modeConfig.description}`));
49227
+ }
49228
+ } else {
49229
+ console.log(chalk5.green.bold(`
49230
+ \u2705 Workflow mode set to: ${modeName}
49231
+ `));
49232
+ console.log(chalk5.gray(`Description: ${modeConfig.description}`));
49233
+ console.log(chalk5.gray("(Mode persistence disabled via AX_DISABLE_MODE_PERSISTENCE)"));
49234
+ }
49235
+ if (modeConfig.blockedTools && modeConfig.blockedTools.length > 0) {
49236
+ console.log(chalk5.yellow("\nRestricted tools in this mode:"));
49237
+ modeConfig.blockedTools.forEach((tool) => {
49238
+ console.log(chalk5.yellow(` \u2022 ${tool}`));
49239
+ });
49240
+ }
49241
+ if (modeConfig.allowedTools && modeConfig.allowedTools.length > 0) {
49242
+ console.log(chalk5.cyan("\nAllowed tools in this mode:"));
49243
+ modeConfig.allowedTools.forEach((tool) => {
49244
+ console.log(chalk5.cyan(` \u2022 ${tool}`));
49245
+ });
49246
+ }
49247
+ console.log();
49248
+ if (modeName === "iterate") {
49249
+ console.log(chalk5.cyan('\u{1F4A1} Tip: Use `ax run <agent> "task"` and it will auto-use iterate mode'));
49250
+ } else if (modeName === "plan") {
49251
+ console.log(chalk5.cyan('\u{1F4A1} Tip: Use `ax run <agent> "task"` and it will auto-use plan mode'));
49252
+ console.log(chalk5.gray(" The mode will persist until you run `ax mode default`"));
49253
+ }
49254
+ console.log();
49255
+ logger.info("Workflow mode set", { mode: modeName, persisted: isModePersistenceEnabled() });
49256
+ } catch (error) {
49257
+ const err = error instanceof Error ? error : new Error(String(error));
49258
+ console.error(chalk5.red.bold(`
49259
+ \u274C Error: ${err.message}
49260
+ `));
49261
+ logger.error("Mode command failed", { error: err.message });
49262
+ process.exit(1);
49263
+ }
49264
+ }
49265
+ };
49266
+ function displayModeList() {
49267
+ console.log(chalk5.blue.bold("\n\u{1F4CB} Available Workflow Modes\n"));
49268
+ console.log(chalk5.dim("\u2500".repeat(60)));
49269
+ for (const [name, config] of Object.entries(WORKFLOW_MODES)) {
49270
+ console.log();
49271
+ console.log(chalk5.cyan.bold(` ${name}`));
49272
+ console.log(chalk5.gray(` ${config.description}`));
49273
+ if (config.blockedTools && config.blockedTools.length > 0) {
49274
+ console.log(chalk5.yellow(` Blocked: ${config.blockedTools.join(", ")}`));
49275
+ }
49276
+ if (config.maxNestingDepth !== void 0) {
49277
+ console.log(chalk5.gray(` Max nesting depth: ${config.maxNestingDepth}`));
49278
+ }
49279
+ }
49280
+ console.log();
49281
+ console.log(chalk5.dim("\u2500".repeat(60)));
49282
+ console.log(chalk5.gray("\nUsage: ax mode <mode-name>"));
49283
+ console.log(chalk5.gray("Example: ax mode plan\n"));
49284
+ }
49285
+ async function displayModeStatus() {
49286
+ const modeState = await loadModeState();
49287
+ const currentMode = modeState?.mode ?? "default";
49288
+ const modeConfig = WORKFLOW_MODES[currentMode];
49289
+ console.log(chalk5.blue.bold("\n\u{1F4CA} Workflow Mode Status\n"));
49290
+ console.log(chalk5.dim("\u2500".repeat(50)));
49291
+ console.log(` Current mode: ${chalk5.cyan.bold(currentMode)}`);
49292
+ console.log(` Description: ${chalk5.gray(modeConfig.description)}`);
49293
+ if (modeState) {
49294
+ const setAt = new Date(modeState.setAt);
49295
+ const expiresAt = modeState.expiresAt ? new Date(modeState.expiresAt) : null;
49296
+ console.log(` Set at: ${chalk5.gray(setAt.toLocaleString())}`);
49297
+ if (expiresAt) {
49298
+ const remainingMs = expiresAt.getTime() - Date.now();
49299
+ const remainingMins = Math.round(remainingMs / 6e4);
49300
+ if (remainingMs > 0) {
49301
+ console.log(` Expires in: ${chalk5.gray(`${remainingMins} minutes`)}`);
49302
+ } else {
49303
+ console.log(` Status: ${chalk5.yellow("expired (will use default)")}`);
49304
+ }
49305
+ }
49306
+ }
49307
+ if (modeConfig.blockedTools && modeConfig.blockedTools.length > 0) {
49308
+ console.log(` Blocked tools: ${chalk5.yellow(modeConfig.blockedTools.join(", "))}`);
49309
+ } else {
49310
+ console.log(` Blocked tools: ${chalk5.green("none")}`);
49311
+ }
49312
+ console.log(chalk5.dim("\u2500".repeat(50)));
49313
+ console.log();
49314
+ console.log(chalk5.gray("To change mode: ax mode <mode-name>"));
49315
+ console.log(chalk5.gray("To list modes: ax mode --list\n"));
49316
+ }
49317
+
49318
+ // src/cli/commands/debug-instructions.ts
49319
+ init_esm_shims();
49320
+ init_logger();
49321
+
49322
+ // src/core/orchestration/orchestration-service.ts
49323
+ init_esm_shims();
49324
+ init_logger();
49325
+
49326
+ // src/core/orchestration/instruction-injector.ts
49327
+ init_esm_shims();
49328
+ init_logger();
49329
+
49330
+ // src/core/orchestration/token-budget.ts
49331
+ init_esm_shims();
49332
+ init_logger();
49333
+ var PRIORITY_ORDER = {
49334
+ critical: 0,
49335
+ high: 1,
49336
+ normal: 2,
49337
+ low: 3
49338
+ };
49339
+ function createEmptyTypeUsage() {
49340
+ return {
49341
+ task: 0,
49342
+ memory: 0,
49343
+ session: 0,
49344
+ delegation: 0,
49345
+ mode: 0,
49346
+ context: 0
49347
+ };
49348
+ }
49349
+ var TokenBudgetManager = class _TokenBudgetManager {
49350
+ config;
49351
+ /** Characters per token estimate (conservative) */
49352
+ static CHARS_PER_TOKEN = 4;
49353
+ /** Overhead tokens for system-reminder XML tags and formatting */
49354
+ static FORMATTING_OVERHEAD_TOKENS = 50;
49355
+ constructor(config) {
49356
+ this.config = {
49357
+ ...DEFAULT_TOKEN_BUDGET,
49358
+ ...config,
49359
+ perType: {
49360
+ ...DEFAULT_TOKEN_BUDGET.perType,
49361
+ ...config?.perType
49362
+ }
49363
+ };
49364
+ logger.debug("TokenBudgetManager initialized", {
49365
+ maxTotal: this.config.maxTotal,
49366
+ criticalReserve: this.config.criticalReserve
49367
+ });
49368
+ }
49369
+ /**
49370
+ * Estimate tokens for a string
49371
+ */
49372
+ estimateTokens(content) {
49373
+ const characters = content.length;
49374
+ const tokens = Math.ceil(characters / _TokenBudgetManager.CHARS_PER_TOKEN);
49375
+ return {
49376
+ tokens,
49377
+ characters,
49378
+ isEstimate: true
49379
+ };
49380
+ }
49381
+ /**
49382
+ * Estimate tokens for an instruction (including formatting overhead)
49383
+ */
49384
+ estimateInstructionTokens(instruction) {
49385
+ const contentTokens = this.estimateTokens(instruction.content).tokens;
49386
+ return contentTokens + _TokenBudgetManager.FORMATTING_OVERHEAD_TOKENS;
49387
+ }
49388
+ /**
49389
+ * Allocate budget for instructions
49390
+ *
49391
+ * Priority order:
49392
+ * 1. Critical instructions (always included, use reserve)
49393
+ * 2. High priority (included if budget allows)
49394
+ * 3. Normal priority (included if budget allows)
49395
+ * 4. Low priority (only if significant budget remains)
49396
+ */
49397
+ allocateBudget(instructions) {
49398
+ const included = [];
49399
+ const excluded = [];
49400
+ const perTypeUsage = createEmptyTypeUsage();
49401
+ let tokensUsed = 0;
49402
+ const availableBudget = this.config.maxTotal;
49403
+ const sorted = [...instructions].sort((a, b) => {
49404
+ const aPriority = PRIORITY_ORDER[a.priority];
49405
+ const bPriority = PRIORITY_ORDER[b.priority];
49406
+ const priorityDiff = aPriority - bPriority;
49407
+ if (priorityDiff !== 0) return priorityDiff;
49408
+ return a.createdAt - b.createdAt;
49409
+ });
49410
+ for (const instruction of sorted) {
49411
+ const instructionTokens = this.estimateInstructionTokens(instruction);
49412
+ const typeLimit = this.config.perType[instruction.type] || 0;
49413
+ const currentTypeUsage = perTypeUsage[instruction.type] || 0;
49414
+ const wouldExceedTotal = tokensUsed + instructionTokens > availableBudget;
49415
+ const wouldExceedTypeLimit = currentTypeUsage + instructionTokens > typeLimit;
49416
+ if (instruction.priority === "critical") {
49417
+ const criticalBudget = availableBudget + this.config.criticalReserve;
49418
+ if (tokensUsed + instructionTokens <= criticalBudget) {
49419
+ included.push(instruction);
49420
+ tokensUsed += instructionTokens;
49421
+ perTypeUsage[instruction.type] = currentTypeUsage + instructionTokens;
49422
+ continue;
49423
+ }
49424
+ }
49425
+ if (!wouldExceedTotal && !wouldExceedTypeLimit) {
49426
+ included.push(instruction);
49427
+ tokensUsed += instructionTokens;
49428
+ perTypeUsage[instruction.type] = currentTypeUsage + instructionTokens;
49429
+ } else {
49430
+ excluded.push(instruction);
49431
+ logger.debug("Instruction excluded from budget", {
49432
+ type: instruction.type,
49433
+ priority: instruction.priority,
49434
+ tokens: instructionTokens,
49435
+ reason: wouldExceedTotal ? "total_limit" : "type_limit"
49436
+ });
49437
+ }
49438
+ }
49439
+ const result = {
49440
+ included,
49441
+ excluded,
49442
+ tokensUsed,
49443
+ remaining: availableBudget - tokensUsed,
49444
+ perTypeUsage
49445
+ };
49446
+ logger.debug("Budget allocation complete", {
49447
+ included: included.length,
49448
+ excluded: excluded.length,
49449
+ tokensUsed,
49450
+ remaining: result.remaining
49451
+ });
49452
+ return result;
49453
+ }
49454
+ /**
49455
+ * Check if an instruction fits within budget
49456
+ */
49457
+ fitsInBudget(instruction, currentUsage, typeUsage) {
49458
+ const instructionTokens = this.estimateInstructionTokens(instruction);
49459
+ const typeLimit = this.config.perType[instruction.type] || 0;
49460
+ const currentTypeUsage = typeUsage[instruction.type] || 0;
49461
+ if (instruction.priority === "critical") {
49462
+ return currentUsage + instructionTokens <= this.config.maxTotal + this.config.criticalReserve;
49463
+ }
49464
+ return currentUsage + instructionTokens <= this.config.maxTotal && currentTypeUsage + instructionTokens <= typeLimit;
49465
+ }
49466
+ /**
49467
+ * Get current configuration
49468
+ */
49469
+ getConfig() {
49470
+ return { ...this.config };
49471
+ }
49472
+ /**
49473
+ * Update configuration
49474
+ */
49475
+ updateConfig(updates) {
49476
+ this.config = {
49477
+ ...this.config,
49478
+ ...updates,
49479
+ perType: {
49480
+ ...this.config.perType,
49481
+ ...updates.perType
49482
+ }
49483
+ };
49484
+ logger.debug("TokenBudgetManager config updated", {
49485
+ maxTotal: this.config.maxTotal
49486
+ });
49487
+ }
49488
+ /**
49489
+ * Get remaining budget for a specific type
49490
+ */
49491
+ getRemainingTypeBudget(type, currentTypeUsage) {
49492
+ const limit = this.config.perType[type] || 0;
49493
+ const used = currentTypeUsage[type] || 0;
49494
+ return Math.max(0, limit - used);
49495
+ }
49496
+ /**
49497
+ * Format budget status for debugging
49498
+ */
49499
+ formatBudgetStatus(allocation) {
49500
+ const lines = [
49501
+ `Token Budget Status:`,
49502
+ ` Total: ${allocation.tokensUsed}/${this.config.maxTotal} (${allocation.remaining} remaining)`,
49503
+ ` Per-Type Usage:`
49504
+ ];
49505
+ for (const [type, used] of Object.entries(allocation.perTypeUsage)) {
49506
+ const limit = this.config.perType[type] || 0;
49507
+ lines.push(` ${type}: ${used}/${limit}`);
49508
+ }
49509
+ if (allocation.excluded.length > 0) {
49510
+ lines.push(` Excluded: ${allocation.excluded.length} instruction(s)`);
49511
+ }
49512
+ return lines.join("\n");
49513
+ }
49514
+ };
49515
+
49516
+ // src/core/orchestration/instruction-injector.ts
49517
+ var INSTRUCTION_TYPE_ORDER = ["mode", "task", "context", "memory", "session", "delegation"];
49518
+ var OrchestrationInstructionInjector = class {
49519
+ providers = /* @__PURE__ */ new Map();
49520
+ budgetManager;
49521
+ config;
49522
+ lastInjectionTime = 0;
49523
+ constructor(config) {
49524
+ this.config = {
49525
+ ...DEFAULT_ORCHESTRATION_CONFIG,
49526
+ ...config
49527
+ };
49528
+ this.budgetManager = new TokenBudgetManager(this.config.tokenBudget);
49529
+ logger.debug("OrchestrationInstructionInjector initialized", {
49530
+ enabled: this.config.enabled,
49531
+ providers: this.providers.size
49532
+ });
49533
+ }
49534
+ /**
49535
+ * Register an instruction provider
49536
+ */
49537
+ registerProvider(provider) {
49538
+ if (this.providers.has(provider.name)) {
49539
+ logger.warn("Provider already registered, replacing", {
49540
+ name: provider.name
49541
+ });
49542
+ }
49543
+ this.providers.set(provider.name, provider);
49544
+ logger.debug("Instruction provider registered", {
49545
+ name: provider.name,
49546
+ totalProviders: this.providers.size
49547
+ });
49548
+ }
49549
+ /**
49550
+ * Unregister an instruction provider
49551
+ */
49552
+ unregisterProvider(name) {
49553
+ const removed = this.providers.delete(name);
49554
+ if (removed) {
49555
+ logger.debug("Instruction provider unregistered", { name });
49556
+ }
49557
+ return removed;
49558
+ }
49559
+ /**
49560
+ * Get all registered providers
49561
+ */
49562
+ getProviders() {
49563
+ return Array.from(this.providers.values());
49564
+ }
49565
+ /**
49566
+ * Generate and inject instructions based on context
49567
+ */
49568
+ async inject(context, options = {}) {
49569
+ if (!this.config.enabled) {
49570
+ return this.emptyResult();
49571
+ }
49572
+ const startTime = Date.now();
49573
+ const allInstructions = [];
49574
+ for (const provider of this.providers.values()) {
49575
+ try {
49576
+ if (!provider.shouldGenerate(context)) {
49577
+ continue;
49578
+ }
49579
+ const instructions = await provider.getInstructions(context);
49580
+ let filtered = instructions;
49581
+ if (options.includeTypes) {
49582
+ filtered = filtered.filter((i) => options.includeTypes.includes(i.type));
49583
+ }
49584
+ if (options.excludeTypes) {
49585
+ filtered = filtered.filter((i) => !options.excludeTypes.includes(i.type));
49586
+ }
49587
+ allInstructions.push(...filtered);
49588
+ } catch (error) {
49589
+ logger.error("Provider failed to generate instructions", {
49590
+ provider: provider.name,
49591
+ error: error instanceof Error ? error.message : String(error)
49592
+ });
49593
+ }
49594
+ }
49595
+ const activeInstructions = this.filterExpiredInstructions(
49596
+ allInstructions,
49597
+ context.turnCount
49598
+ );
49599
+ let allocation;
49600
+ if (options.skipBudget) {
49601
+ allocation = {
49602
+ included: activeInstructions,
49603
+ excluded: [],
49604
+ tokensUsed: activeInstructions.reduce(
49605
+ (sum, i) => sum + this.budgetManager.estimateInstructionTokens(i),
49606
+ 0
49607
+ ),
49608
+ remaining: 0,
49609
+ perTypeUsage: this.calculateTypeUsage(activeInstructions)
49610
+ };
49611
+ } else {
49612
+ allocation = this.budgetManager.allocateBudget(activeInstructions);
49613
+ }
49614
+ const formattedText = this.formatInstructions(allocation.included);
49615
+ this.lastInjectionTime = Date.now();
49616
+ const duration = Date.now() - startTime;
49617
+ logger.debug("Instruction injection complete", {
49618
+ providers: this.providers.size,
49619
+ instructionsGenerated: allInstructions.length,
49620
+ instructionsIncluded: allocation.included.length,
49621
+ tokensUsed: allocation.tokensUsed,
49622
+ durationMs: duration
49623
+ });
49624
+ return {
49625
+ formattedText,
49626
+ instructions: allocation.included,
49627
+ allocation,
49628
+ hasInstructions: allocation.included.length > 0
49629
+ };
49630
+ }
49631
+ /**
49632
+ * Format instructions as system reminder tags
49633
+ */
49634
+ formatInstructions(instructions) {
49635
+ if (instructions.length === 0) {
49636
+ return "";
49637
+ }
49638
+ const grouped = /* @__PURE__ */ new Map();
49639
+ for (const instruction of instructions) {
49640
+ const existing = grouped.get(instruction.type) || [];
49641
+ existing.push(instruction);
49642
+ grouped.set(instruction.type, existing);
49643
+ }
49644
+ const parts = [];
49645
+ for (const type of INSTRUCTION_TYPE_ORDER) {
49646
+ const typeInstructions = grouped.get(type);
49647
+ if (!typeInstructions || typeInstructions.length === 0) continue;
49648
+ for (const instruction of typeInstructions) {
49649
+ parts.push(this.formatSingleInstruction(instruction));
49650
+ }
49651
+ }
49652
+ return parts.join("\n");
49653
+ }
49654
+ /**
49655
+ * Format a single instruction as a system reminder
49656
+ */
49657
+ formatSingleInstruction(instruction) {
49658
+ return `<system-reminder>
49659
+ ${instruction.content}
49660
+ </system-reminder>`;
49661
+ }
49662
+ /**
49663
+ * Filter out expired instructions
49664
+ */
49665
+ filterExpiredInstructions(instructions, currentTurn) {
49666
+ return instructions.filter((instruction) => {
49667
+ if (instruction.expiresAfter === void 0) {
49668
+ return true;
49669
+ }
49670
+ const createdAtTurn = instruction.createdAtTurn ?? currentTurn;
49671
+ const turnsSinceCreation = currentTurn - createdAtTurn;
49672
+ return turnsSinceCreation < instruction.expiresAfter;
49673
+ });
49674
+ }
49675
+ /**
49676
+ * Calculate per-type token usage
49677
+ */
49678
+ calculateTypeUsage(instructions) {
49679
+ const usage = createEmptyTypeUsage();
49680
+ for (const instruction of instructions) {
49681
+ const tokens = this.budgetManager.estimateInstructionTokens(instruction);
49682
+ usage[instruction.type] += tokens;
49683
+ }
49684
+ return usage;
49685
+ }
49686
+ /**
49687
+ * Create an empty result
49688
+ */
49689
+ emptyResult() {
49690
+ return {
49691
+ formattedText: "",
49692
+ instructions: [],
49693
+ allocation: {
49694
+ included: [],
49695
+ excluded: [],
49696
+ tokensUsed: 0,
49697
+ remaining: this.budgetManager.getConfig().maxTotal,
49698
+ perTypeUsage: createEmptyTypeUsage()
49699
+ },
49700
+ hasInstructions: false
49701
+ };
49702
+ }
49703
+ /**
49704
+ * Clear instruction cache (placeholder for future caching implementation)
49705
+ */
49706
+ clearCache() {
49707
+ logger.debug("Instruction cache cleared");
49708
+ }
49709
+ /**
49710
+ * Get current configuration
49711
+ */
49712
+ getConfig() {
49713
+ return { ...this.config };
49714
+ }
49715
+ /**
49716
+ * Update configuration
49717
+ */
49718
+ updateConfig(updates) {
49719
+ this.config = {
49720
+ ...this.config,
49721
+ ...updates
49722
+ };
49723
+ if (updates.tokenBudget) {
49724
+ this.budgetManager.updateConfig(updates.tokenBudget);
49725
+ }
49726
+ logger.debug("OrchestrationInstructionInjector config updated", {
49727
+ enabled: this.config.enabled
49728
+ });
49729
+ }
49730
+ /**
49731
+ * Get budget manager for direct access
49732
+ */
49733
+ getBudgetManager() {
49734
+ return this.budgetManager;
49735
+ }
49736
+ /**
49737
+ * Check if orchestration is enabled
49738
+ */
49739
+ isEnabled() {
49740
+ return this.config.enabled;
49741
+ }
49742
+ /**
49743
+ * Enable or disable orchestration
49744
+ */
49745
+ setEnabled(enabled) {
49746
+ this.config.enabled = enabled;
49747
+ logger.debug("Orchestration enabled state changed", { enabled });
49748
+ }
49749
+ };
49750
+
49751
+ // src/core/orchestration/todo-instruction-provider.ts
49752
+ init_esm_shims();
49753
+ init_logger();
49754
+ var DEFAULT_TODO_CONFIG = {
49755
+ enabled: true,
49756
+ reminderFrequency: 3,
49757
+ compactMode: false,
49758
+ maxCompactItems: 5,
49759
+ showCompleted: false
49760
+ };
49761
+ var TodoInstructionProvider = class {
49762
+ name = "todo";
49763
+ config;
49764
+ lastStateHash = "";
49765
+ lastReminderTurn = 0;
49766
+ constructor(config) {
49767
+ this.config = {
49768
+ ...DEFAULT_TODO_CONFIG,
49769
+ ...config
49770
+ };
49771
+ logger.debug("TodoInstructionProvider initialized", {
49772
+ enabled: this.config.enabled,
49773
+ reminderFrequency: this.config.reminderFrequency
49774
+ });
49775
+ }
49776
+ /**
49777
+ * Check if provider should generate instructions
49778
+ */
49779
+ shouldGenerate(context) {
49780
+ if (!this.config.enabled) {
49781
+ return false;
49782
+ }
49783
+ if (!context.todos || context.todos.length === 0) {
49784
+ return false;
49785
+ }
49786
+ const currentHash = computeTodoHash(context.todos);
49787
+ const stateChanged = currentHash !== this.lastStateHash;
49788
+ const turnsSinceReminder = context.turnCount - this.lastReminderTurn;
49789
+ const reminderDue = turnsSinceReminder >= this.config.reminderFrequency;
49790
+ return stateChanged || reminderDue;
49791
+ }
49792
+ /**
49793
+ * Generate instructions based on todo state
49794
+ */
49795
+ async getInstructions(context) {
49796
+ const instructions = [];
49797
+ if (!context.todos || context.todos.length === 0) {
49798
+ return instructions;
49799
+ }
49800
+ const currentHash = computeTodoHash(context.todos);
49801
+ const stateChanged = currentHash !== this.lastStateHash;
49802
+ const inProgressTasks = [];
49803
+ const pendingTasks = [];
49804
+ const completedTasks = [];
49805
+ for (const todo of context.todos) {
49806
+ switch (todo.status) {
49807
+ case "in_progress":
49808
+ inProgressTasks.push(todo);
49809
+ break;
49810
+ case "pending":
49811
+ pendingTasks.push(todo);
49812
+ break;
49813
+ case "completed":
49814
+ completedTasks.push(todo);
49815
+ break;
49816
+ }
49817
+ }
49818
+ let content;
49819
+ let priority;
49820
+ if (stateChanged) {
49821
+ content = this.formatFullTodoList(inProgressTasks, pendingTasks, completedTasks);
49822
+ priority = "high";
49823
+ } else if (this.config.compactMode) {
49824
+ content = this.formatCompactReminder(inProgressTasks, pendingTasks);
49825
+ priority = "normal";
49826
+ } else {
49827
+ content = this.formatStandardReminder(inProgressTasks, pendingTasks);
49828
+ priority = "normal";
49829
+ }
49830
+ instructions.push({
49831
+ type: "task",
49832
+ priority,
49833
+ content,
49834
+ source: INSTRUCTION_SOURCE,
49835
+ createdAt: Date.now(),
49836
+ createdAtTurn: context.turnCount,
49837
+ expiresAfter: this.config.reminderFrequency + 1,
49838
+ id: `todo-${currentHash.substring(0, 8)}`
49839
+ });
49840
+ this.lastStateHash = currentHash;
49841
+ this.lastReminderTurn = context.turnCount;
49842
+ logger.debug("Todo instructions generated", {
49843
+ inProgress: inProgressTasks.length,
49844
+ pending: pendingTasks.length,
49845
+ completed: completedTasks.length,
49846
+ stateChanged
49847
+ });
49848
+ return instructions;
49849
+ }
49850
+ /**
49851
+ * Format full todo list (used when state changes)
49852
+ */
49853
+ formatFullTodoList(inProgress, pending, completed) {
49854
+ const lines = [
49855
+ "## Current Task List"
49856
+ ];
49857
+ if (inProgress.length > 0) {
49858
+ lines.push("");
49859
+ lines.push("### Currently Working On:");
49860
+ for (const task of inProgress) {
49861
+ lines.push(`- **${task.activeForm}**`);
49862
+ }
49863
+ }
49864
+ if (pending.length > 0) {
49865
+ lines.push("");
49866
+ lines.push("### Pending Tasks:");
49867
+ for (const task of pending) {
49868
+ lines.push(`- [ ] ${task.content}`);
49869
+ }
49870
+ }
49871
+ if (this.config.showCompleted && completed.length > 0) {
49872
+ lines.push("");
49873
+ lines.push("### Completed:");
49874
+ for (const task of completed.slice(-3)) {
49875
+ lines.push(`- [x] ${task.content}`);
49876
+ }
49877
+ }
49878
+ lines.push("");
49879
+ lines.push("**Remember:** Complete the current in-progress task before starting new ones.");
49880
+ lines.push("Mark tasks as completed as soon as they are done.");
49881
+ return lines.join("\n");
49882
+ }
49883
+ /**
49884
+ * Format standard reminder
49885
+ */
49886
+ formatStandardReminder(inProgress, pending) {
49887
+ const lines = [];
49888
+ if (inProgress.length > 0) {
49889
+ lines.push(`**Current Task:** ${inProgress[0].activeForm}`);
49890
+ }
49891
+ if (pending.length > 0) {
49892
+ lines.push(`**Next:** ${pending[0].content}`);
49893
+ if (pending.length > 1) {
49894
+ lines.push(`(${pending.length - 1} more tasks pending)`);
49895
+ }
49896
+ }
49897
+ return lines.join("\n");
49898
+ }
49899
+ /**
49900
+ * Format compact reminder (minimal tokens)
49901
+ */
49902
+ formatCompactReminder(inProgress, pending) {
49903
+ const parts = [];
49904
+ if (inProgress.length > 0) {
49905
+ parts.push(`Doing: ${inProgress[0].activeForm}`);
49906
+ }
49907
+ if (pending.length > 0) {
49908
+ const count = Math.min(pending.length, this.config.maxCompactItems);
49909
+ parts.push(`Next: ${pending.slice(0, count).map((t) => t.content).join(", ")}`);
49910
+ }
49911
+ return parts.join(" | ");
49912
+ }
49913
+ /**
49914
+ * Get current configuration
49915
+ */
49916
+ getConfig() {
49917
+ return { ...this.config };
49918
+ }
49919
+ /**
49920
+ * Update configuration
49921
+ */
49922
+ updateConfig(updates) {
49923
+ this.config = {
49924
+ ...this.config,
49925
+ ...updates
49926
+ };
49927
+ logger.debug("TodoInstructionProvider config updated", {
49928
+ enabled: this.config.enabled,
49929
+ compactMode: this.config.compactMode
49930
+ });
49931
+ }
49932
+ /**
49933
+ * Reset state tracking (useful for testing)
49934
+ */
49935
+ reset() {
49936
+ this.lastStateHash = "";
49937
+ this.lastReminderTurn = 0;
49938
+ logger.debug("TodoInstructionProvider state reset");
49939
+ }
49940
+ };
49941
+ function computeTodoHash(todos) {
49942
+ const stateString = todos.map((t) => `${t.id}:${t.status}:${t.content}`).sort().join("|");
49943
+ return crypto2.createHash("sha256").update(stateString).digest("hex").substring(0, 16);
49944
+ }
49945
+
49946
+ // src/core/orchestration/memory-instruction-provider.ts
49947
+ init_esm_shims();
49948
+ init_logger();
49949
+ var DEFAULT_CONTENT_MAX_LENGTH = 500;
49950
+ var DEFAULT_MEMORY_CONFIG = {
49951
+ enabled: true,
49952
+ maxEntries: 5,
49953
+ minRelevance: 0.5,
49954
+ searchFrequency: 3,
49955
+ maxAge: 0,
49956
+ // No limit by default
49957
+ includeMetadata: true,
49958
+ cacheTTL: 6e4,
49959
+ // 1 minute
49960
+ contentMaxLength: DEFAULT_CONTENT_MAX_LENGTH
49961
+ };
49962
+ var MemoryInstructionProvider = class {
49963
+ name = "memory";
49964
+ config;
49965
+ searchProvider;
49966
+ cache;
49967
+ lastSearchTurn = 0;
49968
+ constructor(searchProvider, config) {
49969
+ this.config = {
49970
+ ...DEFAULT_MEMORY_CONFIG,
49971
+ ...config
49972
+ };
49973
+ this.searchProvider = searchProvider;
49974
+ logger.debug("MemoryInstructionProvider initialized", {
49975
+ enabled: this.config.enabled,
49976
+ maxEntries: this.config.maxEntries,
49977
+ hasSearchProvider: !!searchProvider
49978
+ });
49979
+ }
49980
+ /**
49981
+ * Set the memory search provider
49982
+ */
49983
+ setSearchProvider(provider) {
49984
+ this.searchProvider = provider;
49985
+ this.clearCache();
49986
+ logger.debug("Memory search provider set");
49987
+ }
49988
+ /**
49989
+ * Check if provider should generate instructions
49990
+ */
49991
+ shouldGenerate(context) {
49992
+ if (!this.config.enabled) {
49993
+ return false;
49994
+ }
49995
+ if (!this.searchProvider) {
49996
+ return false;
49997
+ }
49998
+ if (!context.currentTask && context.todos.length === 0) {
49999
+ return false;
50000
+ }
50001
+ const turnsSinceSearch = context.turnCount - this.lastSearchTurn;
50002
+ const searchDue = turnsSinceSearch >= this.config.searchFrequency;
50003
+ const cacheValid = this.cache && Date.now() - this.cache.timestamp < this.config.cacheTTL;
50004
+ return searchDue || !cacheValid;
50005
+ }
50006
+ /**
50007
+ * Generate instructions based on relevant memories
50008
+ */
50009
+ async getInstructions(context) {
50010
+ const instructions = [];
50011
+ if (!this.searchProvider) {
50012
+ return instructions;
50013
+ }
50014
+ const searchQuery = this.buildSearchQuery(context);
50015
+ if (!searchQuery) {
50016
+ return instructions;
50017
+ }
50018
+ try {
50019
+ const memories = await this.searchMemories(searchQuery, context);
50020
+ if (memories.length === 0) {
50021
+ return instructions;
50022
+ }
50023
+ this.lastSearchTurn = context.turnCount;
50024
+ const content = this.formatMemories(memories);
50025
+ instructions.push({
50026
+ type: "memory",
50027
+ priority: "normal",
50028
+ content,
50029
+ source: INSTRUCTION_SOURCE,
50030
+ createdAt: Date.now(),
50031
+ createdAtTurn: context.turnCount,
50032
+ expiresAfter: this.config.searchFrequency + 1,
50033
+ id: `memory-${Date.now()}`
50034
+ });
50035
+ logger.debug("Memory instructions generated", {
50036
+ memoriesFound: memories.length,
50037
+ query: searchQuery.substring(0, 50)
50038
+ });
50039
+ } catch (error) {
50040
+ logger.error("Failed to search memories", {
50041
+ error: error instanceof Error ? error.message : String(error)
50042
+ });
50043
+ }
50044
+ return instructions;
50045
+ }
50046
+ /**
50047
+ * Build search query from context
50048
+ */
50049
+ buildSearchQuery(context) {
50050
+ const parts = [];
50051
+ if (context.currentTask) {
50052
+ parts.push(context.currentTask);
50053
+ }
50054
+ let inProgressCount = 0;
50055
+ for (const todo of context.todos) {
50056
+ if (todo.status === "in_progress") {
50057
+ parts.push(todo.content);
50058
+ if (++inProgressCount >= 2) break;
50059
+ }
50060
+ }
50061
+ if (context.agentName) {
50062
+ parts.push(context.agentName);
50063
+ }
50064
+ if (parts.length === 0) {
50065
+ return null;
50066
+ }
50067
+ return parts.join(" ");
50068
+ }
50069
+ /**
50070
+ * Search for relevant memories
50071
+ */
50072
+ async searchMemories(query, context) {
50073
+ if (!this.searchProvider) {
50074
+ return [];
50075
+ }
50076
+ if (this.cache && this.cache.query === query) {
50077
+ const age = Date.now() - this.cache.timestamp;
50078
+ if (age < this.config.cacheTTL) {
50079
+ logger.debug("Using cached memory results", {
50080
+ cacheAge: age,
50081
+ resultCount: this.cache.results.length
50082
+ });
50083
+ return this.cache.results;
50084
+ }
50085
+ }
50086
+ const results = await this.searchProvider.search({
50087
+ text: query,
50088
+ limit: this.config.maxEntries * 2,
50089
+ // Get extra in case some are filtered
50090
+ filters: context.agentName ? { agentId: context.agentName } : void 0
50091
+ });
50092
+ const filtered = results.filter((r) => r.score >= this.config.minRelevance).filter((r) => this.isWithinMaxAge(r.createdAt)).slice(0, this.config.maxEntries);
50093
+ const memories = filtered.map((r) => ({
50094
+ content: r.content,
50095
+ relevance: r.score,
50096
+ agent: r.metadata?.agentId,
50097
+ timestamp: r.createdAt.getTime()
50098
+ }));
50099
+ this.cache = {
50100
+ query,
50101
+ results: memories,
50102
+ timestamp: Date.now()
50103
+ };
50104
+ return memories;
50105
+ }
50106
+ /**
50107
+ * Check if memory is within max age limit
50108
+ */
50109
+ isWithinMaxAge(createdAt) {
50110
+ if (this.config.maxAge === 0) {
50111
+ return true;
50112
+ }
50113
+ const age = Date.now() - createdAt.getTime();
50114
+ return age <= this.config.maxAge;
50115
+ }
50116
+ /**
50117
+ * Format memories into instruction content
50118
+ */
50119
+ formatMemories(memories) {
50120
+ const lines = [
50121
+ "## Relevant Context from Memory",
50122
+ ""
50123
+ ];
50124
+ for (let i = 0; i < memories.length; i++) {
50125
+ const memory = memories[i];
50126
+ if (!memory) continue;
50127
+ const relevancePercent = Math.round(memory.relevance * 100);
50128
+ if (this.config.includeMetadata && memory.agent) {
50129
+ lines.push(`### Memory ${i + 1} (${relevancePercent}% relevant, from ${memory.agent})`);
50130
+ } else {
50131
+ lines.push(`### Memory ${i + 1} (${relevancePercent}% relevant)`);
50132
+ }
50133
+ const content = memory.content.length > this.config.contentMaxLength ? memory.content.substring(0, this.config.contentMaxLength) + "..." : memory.content;
50134
+ lines.push(content);
50135
+ lines.push("");
50136
+ }
50137
+ lines.push("**Note:** Use this context to inform your decisions, but verify current state.");
50138
+ return lines.join("\n");
50139
+ }
50140
+ /**
50141
+ * Clear the memory cache
50142
+ */
50143
+ clearCache() {
50144
+ this.cache = void 0;
50145
+ logger.debug("Memory cache cleared");
50146
+ }
50147
+ /**
50148
+ * Get current configuration
50149
+ */
50150
+ getConfig() {
50151
+ return { ...this.config };
50152
+ }
50153
+ /**
50154
+ * Update configuration
50155
+ */
50156
+ updateConfig(updates) {
50157
+ this.config = {
50158
+ ...this.config,
50159
+ ...updates
50160
+ };
50161
+ if (updates.minRelevance !== void 0 || updates.maxEntries !== void 0) {
50162
+ this.clearCache();
50163
+ }
50164
+ logger.debug("MemoryInstructionProvider config updated", {
50165
+ enabled: this.config.enabled,
50166
+ maxEntries: this.config.maxEntries
50167
+ });
50168
+ }
50169
+ /**
50170
+ * Reset state
50171
+ */
50172
+ reset() {
50173
+ this.cache = void 0;
50174
+ this.lastSearchTurn = 0;
50175
+ logger.debug("MemoryInstructionProvider reset");
50176
+ }
50177
+ /**
50178
+ * Check if search provider is configured
50179
+ */
50180
+ hasSearchProvider() {
50181
+ return !!this.searchProvider;
50182
+ }
50183
+ };
50184
+
50185
+ // src/core/orchestration/session-instruction-provider.ts
50186
+ init_esm_shims();
50187
+ init_logger();
50188
+ var DEFAULT_SESSION_CONFIG = {
50189
+ enabled: true,
50190
+ showCollaboration: true,
50191
+ showProgress: true,
50192
+ reminderFrequency: 5,
50193
+ showHandoffContext: true
50194
+ };
50195
+ var SESSION_CACHE_TTL_MS = 3e4;
50196
+ var SessionInstructionProvider = class {
50197
+ name = "session";
50198
+ config;
50199
+ stateProvider;
50200
+ lastReminderTurn = 0;
50201
+ cachedState;
50202
+ cacheExpiry = 0;
50203
+ constructor(stateProvider, config) {
50204
+ this.config = {
50205
+ ...DEFAULT_SESSION_CONFIG,
50206
+ ...config
50207
+ };
50208
+ this.stateProvider = stateProvider;
50209
+ logger.debug("SessionInstructionProvider initialized", {
50210
+ enabled: this.config.enabled,
50211
+ hasStateProvider: !!stateProvider
50212
+ });
50213
+ }
50214
+ /**
50215
+ * Set the session state provider
50216
+ */
50217
+ setStateProvider(provider) {
50218
+ this.stateProvider = provider;
50219
+ this.clearCache();
50220
+ logger.debug("Session state provider set");
50221
+ }
50222
+ /**
50223
+ * Check if provider should generate instructions
50224
+ */
50225
+ shouldGenerate(context) {
50226
+ if (!this.config.enabled) {
50227
+ return false;
50228
+ }
50229
+ if (!context.sessionId && !this.stateProvider) {
50230
+ return false;
50231
+ }
50232
+ const turnsSinceReminder = context.turnCount - this.lastReminderTurn;
50233
+ return turnsSinceReminder >= this.config.reminderFrequency;
50234
+ }
50235
+ /**
50236
+ * Generate instructions based on session state
50237
+ */
50238
+ async getInstructions(context) {
50239
+ const instructions = [];
50240
+ const state = await this.getSessionState(context);
50241
+ if (!state && !context.sessionId) {
50242
+ return instructions;
50243
+ }
50244
+ const content = this.formatSessionContext(context, state);
50245
+ if (content) {
50246
+ instructions.push({
50247
+ type: "session",
50248
+ priority: "normal",
50249
+ content,
50250
+ source: INSTRUCTION_SOURCE,
50251
+ createdAt: Date.now(),
50252
+ createdAtTurn: context.turnCount,
50253
+ expiresAfter: this.config.reminderFrequency,
50254
+ id: `session-${context.sessionId ?? "default"}-${Date.now()}`
50255
+ });
50256
+ }
50257
+ this.lastReminderTurn = context.turnCount;
50258
+ logger.debug("Session instructions generated", {
50259
+ sessionId: context.sessionId,
50260
+ hasState: !!state
50261
+ });
50262
+ return instructions;
50263
+ }
50264
+ /**
50265
+ * Get session state from provider or cache
50266
+ */
50267
+ async getSessionState(context) {
50268
+ if (!context.sessionId) {
50269
+ return null;
50270
+ }
50271
+ if (this.cachedState && this.cachedState.id === context.sessionId && Date.now() < this.cacheExpiry) {
50272
+ return this.cachedState;
50273
+ }
50274
+ if (!this.stateProvider) {
50275
+ return null;
50276
+ }
50277
+ try {
50278
+ const state = await this.stateProvider.getSessionState(context.sessionId);
50279
+ if (state) {
50280
+ this.cachedState = state;
50281
+ this.cacheExpiry = Date.now() + SESSION_CACHE_TTL_MS;
50282
+ }
50283
+ return state;
50284
+ } catch (error) {
50285
+ logger.error("Failed to get session state", {
50286
+ sessionId: context.sessionId,
50287
+ error: error instanceof Error ? error.message : String(error)
50288
+ });
50289
+ return null;
50290
+ }
50291
+ }
50292
+ /**
50293
+ * Format session context into instruction content
50294
+ */
50295
+ formatSessionContext(context, state) {
50296
+ const lines = [];
50297
+ if (context.sessionId) {
50298
+ lines.push("## Session Context");
50299
+ lines.push("");
50300
+ }
50301
+ if (this.config.showCollaboration && state && state.participants.length > 1) {
50302
+ lines.push("### Multi-Agent Collaboration");
50303
+ lines.push(`- **Session:** ${state.id.substring(0, 8)}...`);
50304
+ lines.push(`- **Participants:** ${state.participants.join(", ")}`);
50305
+ if (state.activeAgent) {
50306
+ lines.push(`- **Currently Active:** ${state.activeAgent}`);
50307
+ }
50308
+ lines.push("");
50309
+ }
50310
+ if (this.config.showProgress && state) {
50311
+ const totalTasks = state.completedTasks + state.remainingTasks;
50312
+ if (totalTasks > 0) {
50313
+ const progress = Math.round(state.completedTasks / totalTasks * 100);
50314
+ lines.push("### Session Progress");
50315
+ lines.push(`- Completed: ${state.completedTasks}/${totalTasks} (${progress}%)`);
50316
+ if (state.remainingTasks > 0) {
50317
+ lines.push(`- Remaining: ${state.remainingTasks} task(s)`);
50318
+ }
50319
+ lines.push("");
50320
+ }
50321
+ }
50322
+ if (this.config.showHandoffContext && context.parentAgent) {
50323
+ lines.push("### Delegation Context");
50324
+ lines.push(`- **Delegated from:** ${context.parentAgent}`);
50325
+ if (context.currentTask) {
50326
+ lines.push(`- **Task:** ${context.currentTask}`);
50327
+ }
50328
+ lines.push("");
50329
+ lines.push("**Note:** Complete this task and return control to the parent agent.");
50330
+ lines.push("");
50331
+ }
50332
+ if (context.agentName && !context.parentAgent) {
50333
+ lines.push(`**Current Agent:** ${context.agentName}`);
50334
+ lines.push("");
50335
+ }
50336
+ if (lines.length <= 2) {
50337
+ return null;
50338
+ }
50339
+ return lines.join("\n");
50340
+ }
50341
+ /**
50342
+ * Clear cached state
50343
+ */
50344
+ clearCache() {
50345
+ this.cachedState = void 0;
50346
+ this.cacheExpiry = 0;
50347
+ logger.debug("Session cache cleared");
50348
+ }
50349
+ /**
50350
+ * Get current configuration
50351
+ */
50352
+ getConfig() {
50353
+ return { ...this.config };
50354
+ }
50355
+ /**
50356
+ * Update configuration
50357
+ */
50358
+ updateConfig(updates) {
50359
+ this.config = {
50360
+ ...this.config,
50361
+ ...updates
50362
+ };
50363
+ logger.debug("SessionInstructionProvider config updated", {
50364
+ enabled: this.config.enabled
50365
+ });
50366
+ }
50367
+ /**
50368
+ * Reset state
50369
+ */
50370
+ reset() {
50371
+ this.lastReminderTurn = 0;
50372
+ this.clearCache();
50373
+ logger.debug("SessionInstructionProvider reset");
50374
+ }
50375
+ /**
50376
+ * Check if state provider is configured
50377
+ */
50378
+ hasStateProvider() {
50379
+ return !!this.stateProvider;
50380
+ }
50381
+ };
50382
+
50383
+ // src/agents/agent-instruction-injector.ts
50384
+ init_esm_shims();
50385
+ init_logger();
50386
+
50387
+ // src/agents/instruction-templates.ts
50388
+ init_esm_shims();
50389
+ var BACKEND_TEMPLATE = {
50390
+ domain: "backend",
50391
+ displayName: "Backend Engineer",
50392
+ domainReminders: [
50393
+ "Follow RESTful API design principles",
50394
+ "Use proper HTTP status codes",
50395
+ "Implement input validation at API boundaries",
50396
+ "Consider database query performance",
50397
+ "Handle errors gracefully with meaningful messages"
50398
+ ],
50399
+ qualityChecklist: [
50400
+ "API endpoints follow REST conventions",
50401
+ "Database queries are optimized (no N+1)",
50402
+ "Input is validated before processing",
50403
+ "Errors are logged with context",
50404
+ "Sensitive data is not exposed in responses"
50405
+ ],
50406
+ delegationTriggers: [
50407
+ {
50408
+ keywords: ["security", "authentication", "authorization", "OWASP", "vulnerability"],
50409
+ suggestedAgent: "security",
50410
+ reason: "Security-related tasks benefit from specialized security review"
50411
+ },
50412
+ {
50413
+ keywords: ["frontend", "UI", "React", "CSS", "component"],
50414
+ suggestedAgent: "frontend",
50415
+ reason: "Frontend implementation should be handled by frontend specialist"
50416
+ },
50417
+ {
50418
+ keywords: ["test", "testing", "unit test", "integration test"],
50419
+ suggestedAgent: "quality",
50420
+ reason: "Testing strategy benefits from QA expertise"
50421
+ }
50422
+ ],
50423
+ antiPatterns: [
50424
+ "Avoid SQL injection by using parameterized queries",
50425
+ "Don't expose internal error details to clients",
50426
+ "Avoid synchronous blocking operations",
50427
+ "Don't hardcode configuration values"
50428
+ ],
50429
+ bestPractices: [
50430
+ "Use prepared statements for database queries",
50431
+ "Implement proper logging with correlation IDs",
50432
+ "Use dependency injection for testability",
50433
+ "Follow the principle of least privilege"
50434
+ ]
50435
+ };
50436
+ var FRONTEND_TEMPLATE = {
50437
+ domain: "frontend",
50438
+ displayName: "Frontend Engineer",
50439
+ domainReminders: [
50440
+ "Ensure accessibility (WCAG compliance)",
50441
+ "Optimize for performance (Core Web Vitals)",
50442
+ "Handle loading and error states",
50443
+ "Implement responsive design",
50444
+ "Consider keyboard navigation"
50445
+ ],
50446
+ qualityChecklist: [
50447
+ "Components are accessible (ARIA labels, roles)",
50448
+ "Loading states are handled",
50449
+ "Error boundaries catch failures gracefully",
50450
+ "Forms have proper validation feedback",
50451
+ "Images have alt text"
50452
+ ],
50453
+ delegationTriggers: [
50454
+ {
50455
+ keywords: ["API", "endpoint", "database", "backend", "server"],
50456
+ suggestedAgent: "backend",
50457
+ reason: "Backend changes should be handled by backend specialist"
50458
+ },
50459
+ {
50460
+ keywords: ["security", "XSS", "CSRF", "sanitize"],
50461
+ suggestedAgent: "security",
50462
+ reason: "Security concerns require specialized review"
50463
+ }
50464
+ ],
50465
+ antiPatterns: [
50466
+ "Avoid inline styles for reusable components",
50467
+ "Don't mutate state directly",
50468
+ "Avoid excessive re-renders",
50469
+ "Don't ignore accessibility requirements"
50470
+ ],
50471
+ bestPractices: [
50472
+ "Use semantic HTML elements",
50473
+ "Implement proper form validation",
50474
+ "Optimize bundle size",
50475
+ "Use React.memo for expensive components"
50476
+ ]
50477
+ };
50478
+ var SECURITY_TEMPLATE = {
50479
+ domain: "security",
50480
+ displayName: "Security Engineer",
50481
+ domainReminders: [
50482
+ "Apply OWASP Top 10 security guidelines",
50483
+ "Validate and sanitize ALL user input",
50484
+ "Use parameterized queries to prevent SQL injection",
50485
+ "Implement proper authentication and authorization",
50486
+ "Never expose sensitive data in logs or responses"
50487
+ ],
50488
+ qualityChecklist: [
50489
+ "Input validation is present at all entry points",
50490
+ "Authentication tokens are handled securely",
50491
+ "Sensitive data is encrypted at rest and in transit",
50492
+ "Error messages don't leak implementation details",
50493
+ "Dependencies are checked for known vulnerabilities"
50494
+ ],
50495
+ delegationTriggers: [
50496
+ {
50497
+ keywords: ["performance", "optimization", "speed", "latency"],
50498
+ suggestedAgent: "backend",
50499
+ reason: "Performance optimization is a backend concern"
50500
+ }
50501
+ ],
50502
+ antiPatterns: [
50503
+ "Never trust user input without validation",
50504
+ "Don't store passwords in plain text",
50505
+ "Avoid security through obscurity",
50506
+ "Don't disable security features for convenience"
50507
+ ],
50508
+ bestPractices: [
50509
+ "Follow the principle of least privilege",
50510
+ "Implement defense in depth",
50511
+ "Use secure defaults",
50512
+ "Fail securely (deny by default)"
50513
+ ]
50514
+ };
50515
+ var QUALITY_TEMPLATE = {
50516
+ domain: "quality",
50517
+ displayName: "Quality Assurance Engineer",
50518
+ domainReminders: [
50519
+ "Write tests that verify behavior, not implementation",
50520
+ "Cover edge cases and error scenarios",
50521
+ "Ensure test isolation (no shared state)",
50522
+ "Use meaningful test descriptions",
50523
+ "Follow the Arrange-Act-Assert pattern"
50524
+ ],
50525
+ qualityChecklist: [
50526
+ "Unit tests cover critical paths",
50527
+ "Integration tests verify component interactions",
50528
+ "Edge cases are tested",
50529
+ "Error handling is verified",
50530
+ "Tests are maintainable and readable"
50531
+ ],
50532
+ delegationTriggers: [
50533
+ {
50534
+ keywords: ["implement", "build", "create", "develop"],
50535
+ suggestedAgent: "backend",
50536
+ reason: "Implementation tasks should go to domain specialists"
50537
+ },
50538
+ {
50539
+ keywords: ["security", "vulnerability", "penetration"],
50540
+ suggestedAgent: "security",
50541
+ reason: "Security testing requires specialized expertise"
50542
+ }
50543
+ ],
50544
+ antiPatterns: [
50545
+ "Avoid testing implementation details",
50546
+ "Don't use flaky tests",
50547
+ "Avoid excessive mocking",
50548
+ "Don't ignore failing tests"
50549
+ ],
50550
+ bestPractices: [
50551
+ "Test behavior, not implementation",
50552
+ "Use descriptive test names",
50553
+ "Keep tests independent",
50554
+ "Follow the testing pyramid"
50555
+ ]
50556
+ };
50557
+ var ARCHITECTURE_TEMPLATE = {
50558
+ domain: "architecture",
50559
+ displayName: "Software Architect",
50560
+ domainReminders: [
50561
+ "Consider scalability implications",
50562
+ "Document architectural decisions (ADRs)",
50563
+ "Evaluate trade-offs explicitly",
50564
+ "Design for maintainability",
50565
+ "Consider operational concerns"
50566
+ ],
50567
+ qualityChecklist: [
50568
+ "Architecture supports future scaling",
50569
+ "Components have clear boundaries",
50570
+ "Dependencies are managed properly",
50571
+ "System is observable (logging, metrics)",
50572
+ "Failure modes are handled"
50573
+ ],
50574
+ delegationTriggers: [
50575
+ {
50576
+ keywords: ["implement", "code", "fix", "bug"],
50577
+ suggestedAgent: "backend",
50578
+ reason: "Implementation details should be handled by domain specialists"
50579
+ },
50580
+ {
50581
+ keywords: ["security", "compliance", "audit"],
50582
+ suggestedAgent: "security",
50583
+ reason: "Security architecture needs specialized review"
50584
+ }
50585
+ ],
50586
+ antiPatterns: [
50587
+ "Avoid premature optimization",
50588
+ "Don't over-engineer solutions",
50589
+ "Avoid tight coupling between components",
50590
+ "Don't ignore non-functional requirements"
50591
+ ],
50592
+ bestPractices: [
50593
+ "Design for change",
50594
+ "Use well-known patterns",
50595
+ "Document decisions and rationale",
50596
+ "Consider operational requirements"
50597
+ ]
50598
+ };
50599
+ var DEVOPS_TEMPLATE = {
50600
+ domain: "devops",
50601
+ displayName: "DevOps Engineer",
50602
+ domainReminders: [
50603
+ "Automate repetitive tasks",
50604
+ "Implement proper monitoring and alerting",
50605
+ "Follow infrastructure as code principles",
50606
+ "Consider disaster recovery",
50607
+ "Optimize for reliability and cost"
50608
+ ],
50609
+ qualityChecklist: [
50610
+ "Deployments are automated and repeatable",
50611
+ "Monitoring covers key metrics",
50612
+ "Alerts are actionable",
50613
+ "Backups are tested",
50614
+ "Security is integrated into CI/CD"
50615
+ ],
50616
+ delegationTriggers: [
50617
+ {
50618
+ keywords: ["code", "feature", "bug", "implement"],
50619
+ suggestedAgent: "backend",
50620
+ reason: "Application code changes should go to developers"
50621
+ },
50622
+ {
50623
+ keywords: ["security", "credentials", "secrets"],
50624
+ suggestedAgent: "security",
50625
+ reason: "Security-sensitive changes need security review"
50626
+ }
50627
+ ],
50628
+ antiPatterns: [
50629
+ "Avoid manual deployments",
50630
+ "Don't store secrets in code",
50631
+ "Avoid single points of failure",
50632
+ "Don't ignore monitoring gaps"
50633
+ ],
50634
+ bestPractices: [
50635
+ "Use infrastructure as code",
50636
+ "Implement CI/CD pipelines",
50637
+ "Follow GitOps practices",
50638
+ "Use immutable infrastructure"
50639
+ ]
50640
+ };
50641
+ var WRITER_TEMPLATE = {
50642
+ domain: "writer",
50643
+ displayName: "Technical Writer",
50644
+ domainReminders: [
50645
+ "Write for the target audience",
50646
+ "Use clear, concise language",
50647
+ "Include practical examples",
50648
+ "Structure content logically",
50649
+ "Keep documentation up to date"
50650
+ ],
50651
+ qualityChecklist: [
50652
+ "Documentation matches current code",
50653
+ "Examples are working and tested",
50654
+ "Content is well-organized",
50655
+ "Technical terms are explained",
50656
+ "Links and references are valid"
50657
+ ],
50658
+ delegationTriggers: [
50659
+ {
50660
+ keywords: ["implement", "code", "fix", "develop"],
50661
+ suggestedAgent: "backend",
50662
+ reason: "Code changes should be handled by developers"
50663
+ }
50664
+ ],
50665
+ antiPatterns: [
50666
+ "Avoid jargon without explanation",
50667
+ "Don't assume reader knowledge",
50668
+ "Avoid outdated examples",
50669
+ "Don't ignore code comments"
50670
+ ],
50671
+ bestPractices: [
50672
+ "Use consistent terminology",
50673
+ "Include code examples",
50674
+ "Keep documentation near code",
50675
+ "Update docs with code changes"
50676
+ ]
50677
+ };
50678
+ var STANDARD_TEMPLATE = {
50679
+ domain: "standard",
50680
+ displayName: "General Assistant",
50681
+ domainReminders: [
50682
+ "Understand the task before starting",
50683
+ "Ask clarifying questions when needed",
50684
+ "Break complex tasks into smaller steps",
50685
+ "Verify your work before completing",
50686
+ "Document your changes"
50687
+ ],
50688
+ qualityChecklist: [
50689
+ "Task requirements are understood",
50690
+ "Changes are tested",
50691
+ "Code follows project conventions",
50692
+ "Documentation is updated",
50693
+ "No regressions introduced"
50694
+ ],
50695
+ delegationTriggers: [
50696
+ {
50697
+ keywords: ["security", "vulnerability", "authentication"],
50698
+ suggestedAgent: "security",
50699
+ reason: "Security tasks need specialized attention"
50700
+ },
50701
+ {
50702
+ keywords: ["test", "testing", "QA", "quality"],
50703
+ suggestedAgent: "quality",
50704
+ reason: "Testing benefits from QA expertise"
50705
+ },
50706
+ {
50707
+ keywords: ["architecture", "design", "scalability"],
50708
+ suggestedAgent: "architecture",
50709
+ reason: "Architectural decisions need careful consideration"
50710
+ }
50711
+ ],
50712
+ antiPatterns: [
50713
+ "Avoid making changes without understanding context",
50714
+ "Don't skip testing",
50715
+ "Avoid large, monolithic changes",
50716
+ "Don't ignore existing patterns"
50717
+ ],
50718
+ bestPractices: [
50719
+ "Follow existing code conventions",
50720
+ "Write self-documenting code",
50721
+ "Test your changes",
50722
+ "Keep changes focused"
50723
+ ]
50724
+ };
50725
+ var FULLSTACK_TEMPLATE = {
50726
+ ...BACKEND_TEMPLATE,
50727
+ domain: "fullstack",
50728
+ displayName: "Fullstack Engineer"
50729
+ };
50730
+ var DATA_TEMPLATE = {
50731
+ ...BACKEND_TEMPLATE,
50732
+ domain: "data",
50733
+ displayName: "Data Engineer"
50734
+ };
50735
+ var MOBILE_TEMPLATE = {
50736
+ ...FRONTEND_TEMPLATE,
50737
+ domain: "mobile",
50738
+ displayName: "Mobile Engineer"
50739
+ };
50740
+ var RESEARCHER_TEMPLATE = {
50741
+ ...STANDARD_TEMPLATE,
50742
+ domain: "researcher",
50743
+ displayName: "Researcher"
50744
+ };
50745
+ var AGENT_TEMPLATES = {
50746
+ backend: BACKEND_TEMPLATE,
50747
+ frontend: FRONTEND_TEMPLATE,
50748
+ fullstack: FULLSTACK_TEMPLATE,
50749
+ security: SECURITY_TEMPLATE,
50750
+ quality: QUALITY_TEMPLATE,
50751
+ architecture: ARCHITECTURE_TEMPLATE,
50752
+ devops: DEVOPS_TEMPLATE,
50753
+ data: DATA_TEMPLATE,
50754
+ mobile: MOBILE_TEMPLATE,
50755
+ writer: WRITER_TEMPLATE,
50756
+ researcher: RESEARCHER_TEMPLATE,
50757
+ standard: STANDARD_TEMPLATE
50758
+ };
50759
+ function getAgentTemplate(domain) {
50760
+ return AGENT_TEMPLATES[domain] ?? STANDARD_TEMPLATE;
50761
+ }
50762
+ function isValidAgentDomain(domain) {
50763
+ return domain in AGENT_TEMPLATES;
50764
+ }
50765
+ function getDelegationSuggestions(text, currentDomain) {
50766
+ const template = getAgentTemplate(currentDomain);
50767
+ const suggestions = [];
50768
+ const textLower = text.toLowerCase();
50769
+ for (const trigger of template.delegationTriggers) {
50770
+ const matchedKeywords = trigger.keywords.filter(
50771
+ (kw) => textLower.includes(kw.toLowerCase())
50772
+ );
50773
+ if (matchedKeywords.length > 0) {
50774
+ suggestions.push({
50775
+ agent: trigger.suggestedAgent,
50776
+ reason: trigger.reason,
50777
+ keywords: matchedKeywords
50778
+ });
50779
+ }
50780
+ }
50781
+ return suggestions;
50782
+ }
50783
+
50784
+ // src/agents/agent-instruction-injector.ts
50785
+ var DEFAULT_AGENT_CONFIG = {
50786
+ enabled: true,
50787
+ reminderFrequency: 5,
50788
+ delegationDetection: true,
50789
+ minDelegationKeywords: 1,
50790
+ includeQualityChecklist: true,
50791
+ qualityChecklistFrequency: 10,
50792
+ includeAntiPatterns: true,
50793
+ contextAwareBoosting: true
50794
+ };
50795
+ var CONTEXT_KEYWORD_CATEGORIES = [
50796
+ {
50797
+ name: "security",
50798
+ keywords: ["auth", "authentication", "authorization", "login", "password", "token", "jwt", "oauth", "session", "credential", "encrypt", "decrypt", "hash", "secret", "permission", "role", "access control", "csrf", "xss", "injection", "sanitize", "validate input"],
50799
+ boostDomains: ["security"],
50800
+ additionalChecklist: [
50801
+ "Validate all user input before processing",
50802
+ "Use parameterized queries to prevent injection",
50803
+ "Ensure sensitive data is not logged or exposed",
50804
+ "Implement proper session management",
50805
+ "Follow OWASP Top 10 guidelines"
50806
+ ]
50807
+ },
50808
+ {
50809
+ name: "database",
50810
+ keywords: ["database", "db", "sql", "query", "migration", "schema", "table", "index", "transaction", "orm", "prisma", "mongoose", "postgresql", "mysql", "sqlite", "redis", "cache"],
50811
+ boostDomains: ["backend"],
50812
+ additionalChecklist: [
50813
+ "Use transactions for multi-step operations",
50814
+ "Add appropriate indexes for query performance",
50815
+ "Handle connection pooling properly",
50816
+ "Avoid N+1 query patterns",
50817
+ "Use prepared statements for security"
50818
+ ]
50819
+ },
50820
+ {
50821
+ name: "api",
50822
+ keywords: ["api", "endpoint", "rest", "graphql", "request", "response", "http", "status code", "route", "middleware", "cors", "rate limit"],
50823
+ boostDomains: ["backend"],
50824
+ additionalChecklist: [
50825
+ "Use appropriate HTTP status codes",
50826
+ "Validate request body and parameters",
50827
+ "Document API with clear examples",
50828
+ "Implement proper error responses",
50829
+ "Consider rate limiting for public endpoints"
50830
+ ]
50831
+ },
50832
+ {
50833
+ name: "testing",
50834
+ keywords: ["test", "testing", "unit test", "integration test", "e2e", "mock", "stub", "fixture", "coverage", "assert", "expect", "vitest", "jest", "cypress"],
50835
+ boostDomains: ["quality"],
50836
+ additionalChecklist: [
50837
+ "Test behavior, not implementation details",
50838
+ "Include edge cases and error scenarios",
50839
+ "Keep tests isolated and independent",
50840
+ "Use meaningful test descriptions",
50841
+ "Aim for high coverage on critical paths"
50842
+ ]
50843
+ },
50844
+ {
50845
+ name: "performance",
50846
+ keywords: ["performance", "optimize", "slow", "fast", "latency", "memory", "cpu", "bottleneck", "profiling", "benchmark", "cache", "lazy load", "debounce", "throttle"],
50847
+ boostDomains: ["backend", "devops"],
50848
+ additionalChecklist: [
50849
+ "Profile before optimizing",
50850
+ "Consider caching for expensive operations",
50851
+ "Avoid premature optimization",
50852
+ "Measure impact of changes",
50853
+ "Watch for memory leaks"
50854
+ ]
50855
+ },
50856
+ {
50857
+ name: "deployment",
50858
+ keywords: ["deploy", "deployment", "ci", "cd", "pipeline", "docker", "kubernetes", "container", "production", "staging", "environment", "config", "secret", "infrastructure"],
50859
+ boostDomains: ["devops"],
50860
+ additionalChecklist: [
50861
+ "Never hardcode secrets or credentials",
50862
+ "Use environment variables for configuration",
50863
+ "Ensure rollback strategy exists",
50864
+ "Test in staging before production",
50865
+ "Monitor deployment health"
50866
+ ]
50867
+ },
50868
+ {
50869
+ name: "frontend",
50870
+ keywords: ["ui", "ux", "component", "react", "vue", "angular", "css", "style", "responsive", "accessibility", "a11y", "wcag", "form", "validation", "state", "render"],
50871
+ boostDomains: ["frontend"],
50872
+ additionalChecklist: [
50873
+ "Ensure accessibility (ARIA labels, keyboard nav)",
50874
+ "Handle loading and error states",
50875
+ "Optimize for performance (memo, lazy loading)",
50876
+ "Test across different screen sizes",
50877
+ "Validate forms with clear error messages"
50878
+ ]
50879
+ }
50880
+ ];
50881
+ var AgentInstructionInjector = class {
50882
+ name = "agent-template";
50883
+ config;
50884
+ lastReminderTurn = 0;
50885
+ lastQualityCheckTurn = 0;
50886
+ currentDomain;
50887
+ recentTaskText = "";
50888
+ constructor(config) {
50889
+ this.config = {
50890
+ ...DEFAULT_AGENT_CONFIG,
50891
+ ...config
50892
+ };
50893
+ logger.debug("AgentInstructionInjector initialized", {
50894
+ enabled: this.config.enabled,
50895
+ reminderFrequency: this.config.reminderFrequency
50896
+ });
50897
+ }
50898
+ /**
50899
+ * Set the current agent domain
50900
+ */
50901
+ setDomain(domain) {
50902
+ if (isValidAgentDomain(domain)) {
50903
+ this.currentDomain = domain;
50904
+ logger.debug("Agent domain set", { domain });
50905
+ } else {
50906
+ this.currentDomain = "standard";
50907
+ logger.debug("Unknown domain, using standard", { domain });
50908
+ }
50909
+ }
50910
+ /**
50911
+ * Get the current domain
50912
+ */
50913
+ getDomain() {
50914
+ return this.currentDomain;
50915
+ }
50916
+ /**
50917
+ * Check if provider should generate instructions
50918
+ */
50919
+ shouldGenerate(context) {
50920
+ if (!this.config.enabled) {
50921
+ return false;
50922
+ }
50923
+ const domain = this.resolveDomain(context);
50924
+ if (!domain) {
50925
+ return false;
50926
+ }
50927
+ const taskText = this.extractTaskText(context);
50928
+ const turnsSinceReminder = context.turnCount - this.lastReminderTurn;
50929
+ const reminderDue = turnsSinceReminder >= this.config.reminderFrequency;
50930
+ const turnsSinceQuality = context.turnCount - this.lastQualityCheckTurn;
50931
+ const qualityDue = this.config.includeQualityChecklist && turnsSinceQuality >= this.config.qualityChecklistFrequency;
50932
+ const hasDelegationTriggers = this.config.delegationDetection && taskText !== this.recentTaskText && this.checkDelegationTriggers(context, domain, taskText);
50933
+ return reminderDue || qualityDue || hasDelegationTriggers;
50934
+ }
50935
+ /**
50936
+ * Generate instructions based on agent domain
50937
+ */
50938
+ async getInstructions(context) {
50939
+ const instructions = [];
50940
+ const domain = this.resolveDomain(context);
50941
+ if (!domain) {
50942
+ return instructions;
50943
+ }
50944
+ const template = getAgentTemplate(domain);
50945
+ const turnsSinceReminder = context.turnCount - this.lastReminderTurn;
50946
+ const turnsSinceQuality = context.turnCount - this.lastQualityCheckTurn;
50947
+ if (turnsSinceReminder >= this.config.reminderFrequency) {
50948
+ const reminderContent = this.formatDomainReminders(template);
50949
+ instructions.push({
50950
+ type: "delegation",
50951
+ priority: "normal",
50952
+ content: reminderContent,
50953
+ source: INSTRUCTION_SOURCE,
50954
+ createdAt: Date.now(),
50955
+ createdAtTurn: context.turnCount,
50956
+ expiresAfter: this.config.reminderFrequency,
50957
+ id: `agent-reminder-${domain}-${Date.now()}`
50958
+ });
50959
+ this.lastReminderTurn = context.turnCount;
50960
+ }
50961
+ if (this.config.includeQualityChecklist && turnsSinceQuality >= this.config.qualityChecklistFrequency) {
50962
+ const checklistContent = this.formatQualityChecklist(template);
50963
+ instructions.push({
50964
+ type: "delegation",
50965
+ priority: "normal",
50966
+ content: checklistContent,
50967
+ source: INSTRUCTION_SOURCE,
50968
+ createdAt: Date.now(),
50969
+ createdAtTurn: context.turnCount,
50970
+ expiresAfter: this.config.qualityChecklistFrequency,
50971
+ id: `agent-quality-${domain}-${Date.now()}`
50972
+ });
50973
+ this.lastQualityCheckTurn = context.turnCount;
50974
+ }
50975
+ const taskText = this.extractTaskText(context);
50976
+ if (this.config.delegationDetection) {
50977
+ if (taskText !== this.recentTaskText) {
50978
+ this.recentTaskText = taskText;
50979
+ const delegationContent = this.checkAndFormatDelegation(template, taskText);
50980
+ if (delegationContent) {
50981
+ instructions.push({
50982
+ type: "delegation",
50983
+ priority: "high",
50984
+ content: delegationContent,
50985
+ source: INSTRUCTION_SOURCE,
50986
+ createdAt: Date.now(),
50987
+ createdAtTurn: context.turnCount,
50988
+ expiresAfter: 3,
50989
+ id: `agent-delegation-${Date.now()}`
50990
+ });
50991
+ }
50992
+ }
50993
+ }
50994
+ if (this.config.contextAwareBoosting && taskText) {
50995
+ const detectedCategories = this.detectContextCategories(taskText);
50996
+ const contextBoostContent = this.formatContextBoost(detectedCategories);
50997
+ if (contextBoostContent) {
50998
+ instructions.push({
50999
+ type: "context",
51000
+ priority: "normal",
51001
+ content: contextBoostContent,
51002
+ source: INSTRUCTION_SOURCE,
51003
+ createdAt: Date.now(),
51004
+ createdAtTurn: context.turnCount,
51005
+ expiresAfter: 5,
51006
+ id: `agent-context-boost-${Date.now()}`
51007
+ });
51008
+ logger.debug("Context-aware boost applied", {
51009
+ categories: detectedCategories.map((c) => c.name)
51010
+ });
51011
+ }
51012
+ }
51013
+ logger.debug("Agent instructions generated", {
51014
+ domain,
51015
+ instructionCount: instructions.length
51016
+ });
51017
+ return instructions;
51018
+ }
51019
+ /**
51020
+ * Resolve domain from context or current setting
51021
+ */
51022
+ resolveDomain(context) {
51023
+ if (context.agentName && isValidAgentDomain(context.agentName)) {
51024
+ return context.agentName;
51025
+ }
51026
+ return this.currentDomain;
51027
+ }
51028
+ /**
51029
+ * Extract task text from context for delegation detection
51030
+ */
51031
+ extractTaskText(context) {
51032
+ const parts = [];
51033
+ if (context.currentTask) {
51034
+ parts.push(context.currentTask);
51035
+ }
51036
+ for (const todo of context.todos) {
51037
+ if (todo.status === "in_progress") {
51038
+ parts.push(todo.content);
51039
+ }
51040
+ }
51041
+ return parts.join(" ");
51042
+ }
51043
+ /**
51044
+ * Check if delegation triggers are present
51045
+ */
51046
+ checkDelegationTriggers(context, domain, taskText) {
51047
+ const resolvedDomain = domain ?? this.resolveDomain(context);
51048
+ if (!resolvedDomain) return false;
51049
+ const text = taskText ?? this.extractTaskText(context);
51050
+ if (!text) return false;
51051
+ const suggestions = getDelegationSuggestions(text, resolvedDomain);
51052
+ return suggestions.some((s) => s.keywords.length >= this.config.minDelegationKeywords);
51053
+ }
51054
+ /**
51055
+ * Format domain reminders
51056
+ */
51057
+ formatDomainReminders(template) {
51058
+ const lines = [
51059
+ `## ${template.displayName} Reminders`,
51060
+ ""
51061
+ ];
51062
+ for (const reminder of template.domainReminders) {
51063
+ lines.push(`- ${reminder}`);
51064
+ }
51065
+ if (this.config.includeAntiPatterns && template.antiPatterns.length > 0) {
51066
+ lines.push("");
51067
+ lines.push("**Avoid:**");
51068
+ for (const antiPattern of template.antiPatterns.slice(0, 3)) {
51069
+ lines.push(`- ${antiPattern}`);
51070
+ }
51071
+ }
51072
+ return lines.join("\n");
51073
+ }
51074
+ /**
51075
+ * Format quality checklist
51076
+ */
51077
+ formatQualityChecklist(template) {
51078
+ const lines = [
51079
+ `## Quality Checklist (${template.displayName})`,
51080
+ "",
51081
+ "Before completing, verify:"
51082
+ ];
51083
+ for (const item of template.qualityChecklist) {
51084
+ lines.push(`- [ ] ${item}`);
51085
+ }
51086
+ return lines.join("\n");
51087
+ }
51088
+ /**
51089
+ * Check for delegation triggers and format suggestion
51090
+ */
51091
+ checkAndFormatDelegation(template, taskText) {
51092
+ const suggestions = getDelegationSuggestions(taskText, template.domain);
51093
+ const relevantSuggestions = suggestions.filter(
51094
+ (s) => s.keywords.length >= this.config.minDelegationKeywords
51095
+ );
51096
+ if (relevantSuggestions.length === 0) {
51097
+ return null;
51098
+ }
51099
+ const lines = [
51100
+ "## Delegation Suggestion",
51101
+ ""
51102
+ ];
51103
+ for (const suggestion of relevantSuggestions) {
51104
+ lines.push(`**Consider delegating to @${suggestion.agent}**`);
51105
+ lines.push(`- Reason: ${suggestion.reason}`);
51106
+ lines.push(`- Triggered by: ${suggestion.keywords.join(", ")}`);
51107
+ lines.push("");
51108
+ }
51109
+ lines.push("Use `DELEGATE TO @agent: task` or `@agent task` syntax to delegate.");
51110
+ return lines.join("\n");
51111
+ }
51112
+ /**
51113
+ * Detect context categories from task text
51114
+ * @since v11.3.1
51115
+ */
51116
+ detectContextCategories(taskText) {
51117
+ if (!taskText || !this.config.contextAwareBoosting) {
51118
+ return [];
51119
+ }
51120
+ const textLower = taskText.toLowerCase();
51121
+ const matchedCategories = [];
51122
+ for (const category of CONTEXT_KEYWORD_CATEGORIES) {
51123
+ const matchCount = category.keywords.filter(
51124
+ (kw) => textLower.includes(kw.toLowerCase())
51125
+ ).length;
51126
+ if (matchCount > 0) {
51127
+ matchedCategories.push(category);
51128
+ }
51129
+ }
51130
+ return matchedCategories;
51131
+ }
51132
+ /**
51133
+ * Format context-aware boosted instructions
51134
+ * @since v11.3.1
51135
+ */
51136
+ formatContextBoost(categories) {
51137
+ if (categories.length === 0) {
51138
+ return null;
51139
+ }
51140
+ const lines = [];
51141
+ const allChecklistItems = /* @__PURE__ */ new Set();
51142
+ const categoryNames = [];
51143
+ for (const category of categories) {
51144
+ categoryNames.push(category.name);
51145
+ for (const item of category.additionalChecklist.slice(0, 3)) {
51146
+ allChecklistItems.add(item);
51147
+ }
51148
+ }
51149
+ if (allChecklistItems.size === 0) {
51150
+ return null;
51151
+ }
51152
+ lines.push(`## Context-Aware Reminders (${categoryNames.join(", ")})`);
51153
+ lines.push("");
51154
+ lines.push("Based on task keywords, ensure you:");
51155
+ for (const item of Array.from(allChecklistItems).slice(0, 5)) {
51156
+ lines.push(`- ${item}`);
51157
+ }
51158
+ return lines.join("\n");
51159
+ }
51160
+ /**
51161
+ * Get current configuration
51162
+ */
51163
+ getConfig() {
51164
+ return { ...this.config };
51165
+ }
51166
+ /**
51167
+ * Update configuration
51168
+ */
51169
+ updateConfig(updates) {
51170
+ this.config = {
51171
+ ...this.config,
51172
+ ...updates
51173
+ };
51174
+ logger.debug("AgentInstructionInjector config updated", {
51175
+ enabled: this.config.enabled
51176
+ });
51177
+ }
51178
+ /**
51179
+ * Reset state
51180
+ */
51181
+ reset() {
51182
+ this.lastReminderTurn = 0;
51183
+ this.lastQualityCheckTurn = 0;
51184
+ this.recentTaskText = "";
51185
+ logger.debug("AgentInstructionInjector reset");
51186
+ }
51187
+ };
51188
+
51189
+ // src/core/orchestration/orchestration-service.ts
51190
+ var OrchestrationService = class {
51191
+ config;
51192
+ injector;
51193
+ tokenBudgetManager;
51194
+ workflowModeManager;
51195
+ agentInjector;
51196
+ todoProvider;
51197
+ memoryProvider;
51198
+ sessionProvider;
51199
+ turnCount = 0;
51200
+ currentTodos = [];
51201
+ constructor(serviceConfig = {}) {
51202
+ this.config = {
51203
+ ...DEFAULT_ORCHESTRATION_CONFIG,
51204
+ ...serviceConfig
51205
+ };
51206
+ this.injector = new OrchestrationInstructionInjector(this.config);
51207
+ this.tokenBudgetManager = new TokenBudgetManager(this.config.tokenBudget);
51208
+ this.workflowModeManager = new WorkflowModeManager();
51209
+ this.agentInjector = new AgentInstructionInjector({
51210
+ enabled: this.config.agentTemplates?.enabled ?? true,
51211
+ reminderFrequency: this.config.agentTemplates?.reminderFrequency ?? 5
51212
+ });
51213
+ this.initializeProviders(serviceConfig);
51214
+ logger.debug("OrchestrationService initialized", {
51215
+ todoEnabled: this.config.todoIntegration?.enabled,
51216
+ memoryEnabled: this.config.memoryIntegration?.enabled,
51217
+ sessionEnabled: this.config.sessionIntegration?.enabled,
51218
+ agentTemplatesEnabled: this.config.agentTemplates?.enabled
51219
+ });
51220
+ }
51221
+ /**
51222
+ * Initialize instruction providers
51223
+ */
51224
+ initializeProviders(serviceConfig) {
51225
+ if (this.config.todoIntegration?.enabled !== false) {
51226
+ this.todoProvider = new TodoInstructionProvider({
51227
+ enabled: true,
51228
+ reminderFrequency: this.config.todoIntegration?.reminderFrequency ?? 3,
51229
+ compactMode: this.config.todoIntegration?.compactMode ?? false
51230
+ });
51231
+ this.injector.registerProvider(this.todoProvider);
51232
+ }
51233
+ if (this.config.memoryIntegration?.enabled !== false && serviceConfig.memorySearchProvider) {
51234
+ this.memoryProvider = new MemoryInstructionProvider(
51235
+ serviceConfig.memorySearchProvider,
51236
+ {
51237
+ enabled: true,
51238
+ maxEntries: this.config.memoryIntegration?.maxEntries ?? 5,
51239
+ minRelevance: this.config.memoryIntegration?.minRelevance ?? 0.5
51240
+ }
51241
+ );
51242
+ this.injector.registerProvider(this.memoryProvider);
51243
+ }
51244
+ if (this.config.sessionIntegration?.enabled !== false) {
51245
+ this.sessionProvider = new SessionInstructionProvider(
51246
+ serviceConfig.sessionStateProvider,
51247
+ {
51248
+ enabled: true,
51249
+ showCollaboration: this.config.sessionIntegration?.showCollaboration ?? true,
51250
+ showProgress: true,
51251
+ reminderFrequency: 5,
51252
+ showHandoffContext: true
51253
+ }
51254
+ );
51255
+ this.injector.registerProvider(this.sessionProvider);
51256
+ }
51257
+ if (this.config.agentTemplates?.enabled !== false) {
51258
+ if (serviceConfig.agentDomain) {
51259
+ this.agentInjector.setDomain(serviceConfig.agentDomain);
51260
+ }
51261
+ this.injector.registerProvider(this.agentInjector);
51262
+ }
51263
+ }
51264
+ /**
51265
+ * Set the current agent domain for agent-specific instructions
51266
+ */
51267
+ setAgentDomain(domain) {
51268
+ this.agentInjector.setDomain(domain);
51269
+ logger.debug("Agent domain set", { domain });
51270
+ }
51271
+ /**
51272
+ * Set the memory search provider
51273
+ */
51274
+ setMemoryProvider(provider) {
51275
+ if (this.memoryProvider) {
51276
+ this.memoryProvider.setSearchProvider(provider);
51277
+ } else if (this.config.memoryIntegration?.enabled !== false) {
51278
+ this.memoryProvider = new MemoryInstructionProvider(provider, {
51279
+ enabled: true,
51280
+ maxEntries: this.config.memoryIntegration?.maxEntries ?? 5,
51281
+ minRelevance: this.config.memoryIntegration?.minRelevance ?? 0.5
51282
+ });
51283
+ this.injector.registerProvider(this.memoryProvider);
51284
+ }
51285
+ }
51286
+ /**
51287
+ * Set the session state provider
51288
+ */
51289
+ setSessionProvider(provider) {
51290
+ if (this.sessionProvider) {
51291
+ this.sessionProvider.setStateProvider(provider);
51292
+ }
51293
+ }
51294
+ /**
51295
+ * Update the current todo list
51296
+ */
51297
+ updateTodos(todos) {
51298
+ this.currentTodos = todos;
51299
+ }
51300
+ /**
51301
+ * Set the workflow mode
51302
+ *
51303
+ * @throws Error if mode is not a valid WorkflowMode
51304
+ */
51305
+ setWorkflowMode(mode) {
51306
+ if (!isValidWorkflowMode(mode)) {
51307
+ throw new Error(`Invalid workflow mode: ${mode}. Valid modes: default, plan, iterate, review`);
51308
+ }
51309
+ this.workflowModeManager.setMode(mode);
51310
+ logger.debug("Workflow mode set", { mode });
51311
+ }
51312
+ /**
51313
+ * Get current workflow mode
51314
+ */
51315
+ getWorkflowMode() {
51316
+ return this.workflowModeManager.getCurrentMode();
51317
+ }
51318
+ /**
51319
+ * Check if a tool is allowed in current workflow mode
51320
+ */
51321
+ isToolAllowed(toolName) {
51322
+ return this.workflowModeManager.isToolAllowed(toolName);
51323
+ }
51324
+ /**
51325
+ * Filter tools based on current workflow mode
51326
+ */
51327
+ filterTools(tools) {
51328
+ return this.workflowModeManager.filterTools(tools);
51329
+ }
51330
+ /**
51331
+ * Increment turn count (called after each agent response)
51332
+ */
51333
+ incrementTurn() {
51334
+ this.turnCount++;
51335
+ this.workflowModeManager.updateTurnCount(this.turnCount);
51336
+ }
51337
+ /**
51338
+ * Get current turn count
51339
+ */
51340
+ getTurnCount() {
51341
+ return this.turnCount;
51342
+ }
51343
+ /**
51344
+ * Generate and inject instructions for the current context
51345
+ */
51346
+ async injectInstructions(options = {}) {
51347
+ const context = {
51348
+ todos: this.currentTodos,
51349
+ turnCount: this.turnCount,
51350
+ workflowMode: this.workflowModeManager.getCurrentMode(),
51351
+ currentTask: options.task,
51352
+ agentName: options.agentName,
51353
+ sessionId: options.sessionId,
51354
+ parentAgent: options.parentAgent
51355
+ };
51356
+ const result = await this.injector.inject(context);
51357
+ logger.debug("Instructions injected", {
51358
+ instructionCount: result.instructions.length,
51359
+ tokensUsed: result.allocation.tokensUsed,
51360
+ hasInstructions: result.hasInstructions
51361
+ });
51362
+ return {
51363
+ content: result.formattedText,
51364
+ instructions: result.instructions,
51365
+ tokenCount: result.allocation.tokensUsed,
51366
+ applied: result.hasInstructions
51367
+ };
51368
+ }
51369
+ /**
51370
+ * Format instructions as system reminder tags
51371
+ */
51372
+ formatAsSystemReminder(content) {
51373
+ if (!content || content.trim().length === 0) {
51374
+ return "";
51375
+ }
51376
+ return `<system-reminder>
51377
+ ${content}
51378
+ </system-reminder>`;
51379
+ }
51380
+ /**
51381
+ * Get debug information about current orchestration state
51382
+ */
51383
+ getDebugInfo() {
51384
+ const budgetConfig = this.tokenBudgetManager.getConfig();
51385
+ const providers = this.injector.getProviders().map((p) => p.name);
51386
+ return {
51387
+ turnCount: this.turnCount,
51388
+ workflowMode: this.workflowModeManager.getCurrentMode(),
51389
+ todoCount: this.currentTodos.length,
51390
+ providers,
51391
+ tokenBudget: {
51392
+ used: 0,
51393
+ // Would need to track this
51394
+ total: budgetConfig.maxTotal,
51395
+ remaining: budgetConfig.maxTotal
51396
+ }
51397
+ };
51398
+ }
51399
+ /**
51400
+ * Reset all state (for new conversations)
51401
+ */
51402
+ reset() {
51403
+ this.turnCount = 0;
51404
+ this.currentTodos = [];
51405
+ this.workflowModeManager.reset();
51406
+ this.agentInjector.reset();
51407
+ this.injector.clearCache();
51408
+ if (this.todoProvider) {
51409
+ this.todoProvider.reset();
51410
+ }
51411
+ if (this.memoryProvider) {
51412
+ this.memoryProvider.clearCache();
51413
+ }
51414
+ if (this.sessionProvider) {
51415
+ this.sessionProvider.reset();
51416
+ }
51417
+ logger.debug("OrchestrationService reset");
51418
+ }
51419
+ /**
51420
+ * Update configuration
51421
+ */
51422
+ updateConfig(updates) {
51423
+ this.config = {
51424
+ ...this.config,
51425
+ ...updates,
51426
+ tokenBudget: updates.tokenBudget ? { ...this.config.tokenBudget, ...updates.tokenBudget } : this.config.tokenBudget,
51427
+ todoIntegration: updates.todoIntegration ? { ...this.config.todoIntegration, ...updates.todoIntegration } : this.config.todoIntegration,
51428
+ memoryIntegration: updates.memoryIntegration ? { ...this.config.memoryIntegration, ...updates.memoryIntegration } : this.config.memoryIntegration,
51429
+ sessionIntegration: updates.sessionIntegration ? { ...this.config.sessionIntegration, ...updates.sessionIntegration } : this.config.sessionIntegration,
51430
+ agentTemplates: updates.agentTemplates ? { ...this.config.agentTemplates, ...updates.agentTemplates } : this.config.agentTemplates
51431
+ };
51432
+ if (updates.tokenBudget) {
51433
+ this.tokenBudgetManager.updateConfig(this.config.tokenBudget);
51434
+ }
51435
+ this.injector.updateConfig(updates);
51436
+ if (updates.todoIntegration && this.todoProvider) {
51437
+ const current = this.todoProvider.getConfig();
51438
+ this.todoProvider.updateConfig({
51439
+ enabled: updates.todoIntegration.enabled ?? current.enabled,
51440
+ reminderFrequency: updates.todoIntegration.reminderFrequency ?? current.reminderFrequency,
51441
+ compactMode: updates.todoIntegration.compactMode ?? current.compactMode
51442
+ });
51443
+ }
51444
+ if (updates.memoryIntegration && this.memoryProvider) {
51445
+ const current = this.memoryProvider.getConfig();
51446
+ this.memoryProvider.updateConfig({
51447
+ enabled: updates.memoryIntegration.enabled ?? current.enabled,
51448
+ maxEntries: updates.memoryIntegration.maxEntries ?? current.maxEntries,
51449
+ minRelevance: updates.memoryIntegration.minRelevance ?? current.minRelevance
51450
+ });
51451
+ }
51452
+ if (updates.sessionIntegration && this.sessionProvider) {
51453
+ const current = this.sessionProvider.getConfig();
51454
+ this.sessionProvider.updateConfig({
51455
+ enabled: updates.sessionIntegration.enabled ?? current.enabled,
51456
+ showCollaboration: updates.sessionIntegration.showCollaboration ?? current.showCollaboration
51457
+ });
51458
+ }
51459
+ if (updates.agentTemplates) {
51460
+ const agentUpdates = {};
51461
+ if (updates.agentTemplates.enabled !== void 0) {
51462
+ agentUpdates.enabled = updates.agentTemplates.enabled;
51463
+ }
51464
+ if (updates.agentTemplates.reminderFrequency !== void 0) {
51465
+ agentUpdates.reminderFrequency = updates.agentTemplates.reminderFrequency;
51466
+ }
51467
+ this.agentInjector.updateConfig(agentUpdates);
51468
+ }
51469
+ logger.debug("OrchestrationService config updated", { updates });
51470
+ }
51471
+ /**
51472
+ * Get current configuration
51473
+ */
51474
+ getConfig() {
51475
+ return { ...this.config };
51476
+ }
51477
+ };
51478
+
51479
+ // src/cli/commands/debug-instructions.ts
51480
+ var debugInstructionsCommand = {
51481
+ command: "debug:instructions",
51482
+ describe: "Show current embedded instructions state (v11.3.0)",
51483
+ builder: (yargs2) => {
51484
+ return yargs2.option("tokens", {
51485
+ alias: "t",
51486
+ describe: "Show token budget details",
51487
+ type: "boolean",
51488
+ default: false
51489
+ }).option("providers", {
51490
+ alias: "p",
51491
+ describe: "Show registered instruction providers",
51492
+ type: "boolean",
51493
+ default: false
51494
+ }).option("templates", {
51495
+ describe: "Show available agent templates",
51496
+ type: "boolean",
51497
+ default: false
51498
+ }).option("agent", {
51499
+ alias: "a",
51500
+ describe: "Show template for specific agent domain",
51501
+ type: "string"
51502
+ }).option("verbose", {
51503
+ alias: "v",
51504
+ describe: "Show verbose output",
51505
+ type: "boolean",
51506
+ default: false
51507
+ }).example("$0 debug:instructions", "Show overall instruction state").example("$0 debug:instructions --tokens", "Show token budget details").example("$0 debug:instructions --providers", "List instruction providers").example("$0 debug:instructions --templates", "List agent templates").example("$0 debug:instructions --agent backend", "Show backend agent template");
51508
+ },
51509
+ handler: async (argv) => {
51510
+ try {
51511
+ if (argv.tokens) {
51512
+ displayTokenBudget(argv.verbose);
51513
+ return;
51514
+ }
51515
+ if (argv.providers) {
51516
+ displayProviders(argv.verbose);
51517
+ return;
51518
+ }
51519
+ if (argv.templates) {
51520
+ displayAgentTemplates(argv.verbose);
51521
+ return;
51522
+ }
51523
+ if (argv.agent) {
51524
+ displayAgentTemplate(argv.agent, argv.verbose);
51525
+ return;
51526
+ }
51527
+ displayOverallState(argv.verbose);
51528
+ } catch (error) {
51529
+ const err = error instanceof Error ? error : new Error(String(error));
51530
+ console.error(chalk5.red.bold(`
51531
+ \u274C Error: ${err.message}
51532
+ `));
51533
+ logger.error("Debug instructions command failed", { error: err.message });
51534
+ process.exit(1);
51535
+ }
51536
+ }
51537
+ };
51538
+ function displayOverallState(verbose) {
51539
+ console.log(chalk5.blue.bold("\n\u{1F50D} Embedded Instructions Debug Info\n"));
51540
+ console.log(chalk5.dim("\u2550".repeat(60)));
51541
+ const service = new OrchestrationService();
51542
+ const debugInfo = service.getDebugInfo();
51543
+ console.log(chalk5.cyan("\n\u{1F4CA} Current State"));
51544
+ console.log(chalk5.dim("\u2500".repeat(40)));
51545
+ console.log(` Turn count: ${chalk5.yellow(debugInfo.turnCount)}`);
51546
+ console.log(` Workflow mode: ${chalk5.cyan(debugInfo.workflowMode)}`);
51547
+ console.log(` Active todos: ${chalk5.yellow(debugInfo.todoCount)}`);
51548
+ console.log(` Registered providers: ${chalk5.green(debugInfo.providers.length)}`);
51549
+ console.log(chalk5.cyan("\n\u{1F4B0} Token Budget"));
51550
+ console.log(chalk5.dim("\u2500".repeat(40)));
51551
+ console.log(` Used: ${chalk5.yellow(debugInfo.tokenBudget.used)} / ${debugInfo.tokenBudget.total}`);
51552
+ const usagePercent = Math.round(debugInfo.tokenBudget.used / debugInfo.tokenBudget.total * 100);
51553
+ const barLength = 30;
51554
+ const filledLength = Math.round(usagePercent / 100 * barLength);
51555
+ const bar = "\u2588".repeat(filledLength) + "\u2591".repeat(barLength - filledLength);
51556
+ const barColor = usagePercent > 80 ? chalk5.red : usagePercent > 50 ? chalk5.yellow : chalk5.green;
51557
+ console.log(` ${barColor(bar)} ${usagePercent}%`);
51558
+ if (debugInfo.providers.length > 0) {
51559
+ console.log(chalk5.cyan("\n\u{1F50C} Active Providers"));
51560
+ console.log(chalk5.dim("\u2500".repeat(40)));
51561
+ debugInfo.providers.forEach((provider, index) => {
51562
+ console.log(` ${index + 1}. ${chalk5.green(provider)}`);
51563
+ });
51564
+ }
51565
+ console.log(chalk5.cyan("\n\u{1F504} Workflow Modes"));
51566
+ console.log(chalk5.dim("\u2500".repeat(40)));
51567
+ Object.keys(WORKFLOW_MODES).forEach((mode) => {
51568
+ const isCurrent = mode === debugInfo.workflowMode;
51569
+ const prefix = isCurrent ? chalk5.green("\u25BA") : " ";
51570
+ const modeText = isCurrent ? chalk5.green.bold(mode) : chalk5.gray(mode);
51571
+ console.log(` ${prefix} ${modeText}`);
51572
+ });
51573
+ console.log(chalk5.dim("\n" + "\u2550".repeat(60)));
51574
+ console.log(chalk5.gray("\nUse --tokens, --providers, or --templates for detailed info.\n"));
51575
+ }
51576
+ function displayTokenBudget(verbose) {
51577
+ console.log(chalk5.blue.bold("\n\u{1F4B0} Token Budget Details\n"));
51578
+ console.log(chalk5.dim("\u2500".repeat(50)));
51579
+ const budgetManager = new TokenBudgetManager();
51580
+ const config = budgetManager.getConfig();
51581
+ console.log(`
51582
+ Total budget: ${chalk5.cyan(config.maxTotal)} tokens`);
51583
+ console.log(` Critical reserve: ${chalk5.yellow(config.criticalReserve)} tokens`);
51584
+ console.log(` Available: ${chalk5.green(config.maxTotal - config.criticalReserve)} tokens`);
51585
+ console.log(chalk5.cyan("\n Per-Type Allocations:"));
51586
+ const typeDescriptions = {
51587
+ task: "Todo/task reminders",
51588
+ memory: "Memory context",
51589
+ session: "Session state",
51590
+ delegation: "Agent delegation hints",
51591
+ mode: "Workflow mode instructions",
51592
+ context: "Context-aware boosted reminders"
51593
+ };
51594
+ Object.entries(config.perType).forEach(([type, budget]) => {
51595
+ console.log(` \u2022 ${chalk5.cyan(type)}: ${budget} tokens`);
51596
+ if (verbose && typeDescriptions[type]) {
51597
+ console.log(chalk5.gray(` ${typeDescriptions[type]}`));
51598
+ }
51599
+ });
51600
+ console.log(chalk5.cyan("\n Token Estimation:"));
51601
+ console.log(chalk5.gray(" ~4 characters = 1 token (approximation)"));
51602
+ console.log(chalk5.gray(" Actual usage may vary by content"));
51603
+ console.log(chalk5.dim("\n\u2500".repeat(50)));
51604
+ console.log();
51605
+ }
51606
+ function displayProviders(verbose) {
51607
+ console.log(chalk5.blue.bold("\n\u{1F50C} Instruction Providers\n"));
51608
+ console.log(chalk5.dim("\u2500".repeat(50)));
51609
+ const providers = [
51610
+ {
51611
+ name: "TodoInstructionProvider",
51612
+ description: "Generates task reminders from todo list",
51613
+ triggers: "Todo state changes, periodic reminders",
51614
+ priority: "high"
51615
+ },
51616
+ {
51617
+ name: "MemoryInstructionProvider",
51618
+ description: "Injects relevant context from memory",
51619
+ triggers: "Task keywords, memory relevance",
51620
+ priority: "normal"
51621
+ },
51622
+ {
51623
+ name: "SessionInstructionProvider",
51624
+ description: "Shows multi-agent collaboration state",
51625
+ triggers: "Session changes, periodic reminders",
51626
+ priority: "normal"
51627
+ },
51628
+ {
51629
+ name: "AgentInstructionInjector",
51630
+ description: "Domain-specific reminders and delegation hints",
51631
+ triggers: "Agent domain, task keywords",
51632
+ priority: "normal"
51633
+ },
51634
+ {
51635
+ name: "WorkflowModeManager",
51636
+ description: "Mode-specific instructions and tool filtering",
51637
+ triggers: "Mode changes",
51638
+ priority: "high"
51639
+ }
51640
+ ];
51641
+ providers.forEach((provider, index) => {
51642
+ console.log(`
51643
+ ${index + 1}. ${chalk5.cyan.bold(provider.name)}`);
51644
+ console.log(chalk5.gray(` ${provider.description}`));
51645
+ if (verbose) {
51646
+ console.log(` Triggers: ${chalk5.yellow(provider.triggers)}`);
51647
+ console.log(` Priority: ${chalk5.green(provider.priority)}`);
51648
+ }
51649
+ });
51650
+ console.log(chalk5.dim("\n\u2500".repeat(50)));
51651
+ console.log();
51652
+ }
51653
+ function displayAgentTemplates(verbose) {
51654
+ console.log(chalk5.blue.bold("\n\u{1F4CB} Agent Instruction Templates\n"));
51655
+ console.log(chalk5.dim("\u2500".repeat(50)));
51656
+ for (const [domain, template] of Object.entries(AGENT_TEMPLATES)) {
51657
+ console.log(`
51658
+ ${chalk5.cyan.bold(template.displayName)} (${domain})`);
51659
+ if (verbose) {
51660
+ console.log(chalk5.gray(` Reminders: ${template.domainReminders.length}`));
51661
+ console.log(chalk5.gray(` Checklist items: ${template.qualityChecklist.length}`));
51662
+ console.log(chalk5.gray(` Delegation triggers: ${template.delegationTriggers.length}`));
51663
+ console.log(chalk5.gray(` Anti-patterns: ${template.antiPatterns.length}`));
51664
+ console.log(chalk5.gray(` Best practices: ${template.bestPractices.length}`));
51665
+ }
51666
+ }
51667
+ console.log(chalk5.dim("\n\u2500".repeat(50)));
51668
+ console.log(chalk5.gray("\nUse --agent <domain> to see template details.\n"));
51669
+ }
51670
+ function displayAgentTemplate(domain, verbose) {
51671
+ const template = AGENT_TEMPLATES[domain];
51672
+ if (!template) {
51673
+ console.error(chalk5.red.bold(`
51674
+ \u274C Unknown agent domain: ${domain}
51675
+ `));
51676
+ console.log(chalk5.gray("Available domains:"));
51677
+ Object.keys(AGENT_TEMPLATES).forEach((d) => {
51678
+ console.log(chalk5.cyan(` \u2022 ${d}`));
51679
+ });
51680
+ console.log();
51681
+ process.exit(1);
51682
+ }
51683
+ console.log(chalk5.blue.bold(`
51684
+ \u{1F4CB} ${template.displayName} Agent Template
51685
+ `));
51686
+ console.log(chalk5.dim("\u2550".repeat(60)));
51687
+ console.log(chalk5.cyan("\n\u{1F514} Domain Reminders:"));
51688
+ template.domainReminders.forEach((reminder, i) => {
51689
+ console.log(` ${i + 1}. ${reminder}`);
51690
+ });
51691
+ console.log(chalk5.cyan("\n\u2705 Quality Checklist:"));
51692
+ template.qualityChecklist.forEach((item, i) => {
51693
+ console.log(` ${i + 1}. ${item}`);
51694
+ });
51695
+ if (template.delegationTriggers.length > 0) {
51696
+ console.log(chalk5.cyan("\n\u{1F500} Delegation Triggers:"));
51697
+ template.delegationTriggers.forEach((trigger, i) => {
51698
+ console.log(` ${i + 1}. \u2192 ${chalk5.yellow(trigger.suggestedAgent)}`);
51699
+ console.log(chalk5.gray(` Keywords: ${trigger.keywords.join(", ")}`));
51700
+ if (verbose) {
51701
+ console.log(chalk5.gray(` Reason: ${trigger.reason}`));
51702
+ }
51703
+ });
51704
+ }
51705
+ if (verbose && template.antiPatterns.length > 0) {
51706
+ console.log(chalk5.red("\n\u26A0\uFE0F Anti-Patterns to Avoid:"));
51707
+ template.antiPatterns.forEach((pattern, i) => {
51708
+ console.log(` ${i + 1}. ${pattern}`);
51709
+ });
51710
+ }
51711
+ if (verbose && template.bestPractices.length > 0) {
51712
+ console.log(chalk5.green("\n\u2728 Best Practices:"));
51713
+ template.bestPractices.forEach((practice, i) => {
51714
+ console.log(` ${i + 1}. ${practice}`);
51715
+ });
51716
+ }
51717
+ console.log(chalk5.dim("\n\u2550".repeat(60)));
51718
+ console.log();
51719
+ }
51720
+
51721
+ // src/cli/commands/shortcuts.ts
51722
+ init_esm_shims();
51723
+ init_logger();
51724
+ async function runAxCommand(args) {
51725
+ return new Promise((resolve13, reject) => {
51726
+ const nodeExe = process.argv[0];
51727
+ const cliScript = process.argv[1];
51728
+ if (!nodeExe || !cliScript) {
51729
+ reject(new Error("Cannot determine CLI path"));
51730
+ return;
51731
+ }
51732
+ const child = spawn(nodeExe, [cliScript, ...args], {
51733
+ stdio: "inherit",
51734
+ env: process.env
51735
+ });
51736
+ child.on("close", (code) => {
51737
+ if (code === 0) {
51738
+ resolve13();
51739
+ } else {
51740
+ reject(new Error(`Command exited with code ${code}`));
51741
+ }
51742
+ });
51743
+ child.on("error", reject);
51744
+ });
51745
+ }
51746
+ var planCommand = {
51747
+ command: "plan [task]",
51748
+ describe: "Enter plan mode and explore/plan a task (shortcut for ax mode plan + ax run)",
51749
+ builder: (yargs2) => {
51750
+ return yargs2.positional("task", {
51751
+ describe: "Task to plan (optional - if not provided, just sets mode)",
51752
+ type: "string"
51753
+ }).option("agent", {
51754
+ alias: "a",
51755
+ describe: "Agent to use (auto-selects if not specified)",
51756
+ type: "string"
51757
+ }).option("provider", {
51758
+ alias: "p",
51759
+ describe: "Override provider",
51760
+ type: "string"
51761
+ }).option("verbose", {
51762
+ alias: "v",
51763
+ describe: "Verbose output",
51764
+ type: "boolean",
51765
+ default: false
51766
+ }).option("quiet", {
51767
+ alias: "q",
51768
+ describe: "Quiet output",
51769
+ type: "boolean",
51770
+ default: false
51771
+ }).example("$0 plan", "Enter plan mode").example('$0 plan "design auth system"', "Plan a task with auto-selected agent").example('$0 plan "design API" --agent architecture', "Plan with specific agent");
51772
+ },
51773
+ handler: async (argv) => {
51774
+ try {
51775
+ const saved = await saveModeState("plan", {
51776
+ setBy: "shortcut",
51777
+ reason: "ax plan command"
51778
+ });
51779
+ if (!saved) {
51780
+ logger.warn("Failed to persist mode state, continuing anyway");
51781
+ }
51782
+ if (!argv.quiet) {
51783
+ console.log(chalk5.cyan.bold("\n\u{1F4CB} Plan Mode Activated\n"));
51784
+ console.log(chalk5.gray("Read-only exploration mode - no file modifications allowed"));
51785
+ console.log(chalk5.gray("Use `ax mode default` to exit plan mode\n"));
51786
+ }
51787
+ if (argv.task) {
51788
+ const runArgs = ["run"];
51789
+ if (argv.agent) runArgs.push(argv.agent);
51790
+ runArgs.push(argv.task);
51791
+ if (argv.provider) runArgs.push("--provider", argv.provider);
51792
+ if (argv.verbose) runArgs.push("--verbose");
51793
+ if (argv.quiet) runArgs.push("--quiet");
51794
+ await runAxCommand(runArgs);
51795
+ } else {
51796
+ console.log(chalk5.gray('No task specified. Use `ax run <agent> "task"` to run in plan mode.'));
51797
+ }
51798
+ logger.info("Plan shortcut executed", { task: argv.task, agent: argv.agent });
51799
+ } catch (error) {
51800
+ const err = error instanceof Error ? error : new Error(String(error));
51801
+ console.error(chalk5.red.bold(`
51802
+ \u274C Error: ${err.message}
51803
+ `));
51804
+ process.exit(1);
51805
+ }
51806
+ }
51807
+ };
51808
+ var iterateCommand = {
51809
+ command: "iterate [task]",
51810
+ describe: "Enter iterate mode and run a task autonomously (shortcut for ax mode iterate + ax run --iterate)",
51811
+ builder: (yargs2) => {
51812
+ return yargs2.positional("task", {
51813
+ describe: "Task to execute (optional - if not provided, just sets mode)",
51814
+ type: "string"
51815
+ }).option("agent", {
51816
+ alias: "a",
51817
+ describe: "Agent to use (auto-selects if not specified)",
51818
+ type: "string"
51819
+ }).option("timeout", {
51820
+ alias: "t",
51821
+ describe: "Max duration in minutes",
51822
+ type: "number"
51823
+ }).option("max-tokens", {
51824
+ describe: "Max total tokens",
51825
+ type: "number"
51826
+ }).option("provider", {
51827
+ alias: "p",
51828
+ describe: "Override provider",
51829
+ type: "string"
51830
+ }).option("verbose", {
51831
+ alias: "v",
51832
+ describe: "Verbose output",
51833
+ type: "boolean",
51834
+ default: false
51835
+ }).option("quiet", {
51836
+ alias: "q",
51837
+ describe: "Quiet output",
51838
+ type: "boolean",
51839
+ default: false
51840
+ }).example("$0 iterate", "Enter iterate mode").example('$0 iterate "implement auth"', "Run task in iterate mode").example('$0 iterate "fix bug" --agent backend', "Iterate with specific agent");
51841
+ },
51842
+ handler: async (argv) => {
51843
+ try {
51844
+ const saved = await saveModeState("iterate", {
51845
+ setBy: "shortcut",
51846
+ reason: "ax iterate command"
51847
+ });
51848
+ if (!saved) {
51849
+ logger.warn("Failed to persist mode state, continuing anyway");
51850
+ }
51851
+ if (!argv.quiet) {
51852
+ console.log(chalk5.cyan.bold("\n\u{1F504} Iterate Mode Activated\n"));
51853
+ console.log(chalk5.gray("Autonomous execution mode - agent will work continuously"));
51854
+ console.log(chalk5.gray("Use `ax mode default` to exit iterate mode\n"));
51855
+ }
51856
+ if (argv.task) {
51857
+ const runArgs = ["run"];
51858
+ if (argv.agent) runArgs.push(argv.agent);
51859
+ runArgs.push(argv.task);
51860
+ runArgs.push("--iterate");
51861
+ if (argv.timeout) runArgs.push("--iterate-timeout", String(argv.timeout));
51862
+ if (argv.maxTokens) runArgs.push("--iterate-max-tokens", String(argv.maxTokens));
51863
+ if (argv.provider) runArgs.push("--provider", argv.provider);
51864
+ if (argv.verbose) runArgs.push("--verbose");
51865
+ if (argv.quiet) runArgs.push("--quiet");
51866
+ await runAxCommand(runArgs);
51867
+ } else {
51868
+ console.log(chalk5.gray('No task specified. Use `ax run <agent> "task"` to run in iterate mode.'));
51869
+ }
51870
+ logger.info("Iterate shortcut executed", { task: argv.task, agent: argv.agent });
51871
+ } catch (error) {
51872
+ const err = error instanceof Error ? error : new Error(String(error));
51873
+ console.error(chalk5.red.bold(`
51874
+ \u274C Error: ${err.message}
51875
+ `));
51876
+ process.exit(1);
51877
+ }
51878
+ }
51879
+ };
51880
+ var reviewCommand = {
51881
+ command: "review [path]",
51882
+ describe: "Enter review mode and analyze code (shortcut for ax mode review + ax run quality)",
51883
+ builder: (yargs2) => {
51884
+ return yargs2.positional("path", {
51885
+ describe: "Path to review (file or directory)",
51886
+ type: "string"
51887
+ }).option("agent", {
51888
+ alias: "a",
51889
+ describe: "Agent to use (defaults to quality)",
51890
+ type: "string",
51891
+ default: "quality"
51892
+ }).option("provider", {
51893
+ alias: "p",
51894
+ describe: "Override provider",
51895
+ type: "string"
51896
+ }).option("verbose", {
51897
+ alias: "v",
51898
+ describe: "Verbose output",
51899
+ type: "boolean",
51900
+ default: false
51901
+ }).option("quiet", {
51902
+ alias: "q",
51903
+ describe: "Quiet output",
51904
+ type: "boolean",
51905
+ default: false
51906
+ }).example("$0 review", "Enter review mode").example("$0 review src/core/", "Review a directory").example("$0 review src/api.ts", "Review a specific file");
51907
+ },
51908
+ handler: async (argv) => {
51909
+ try {
51910
+ const saved = await saveModeState("review", {
51911
+ setBy: "shortcut",
51912
+ reason: "ax review command"
51913
+ });
51914
+ if (!saved) {
51915
+ logger.warn("Failed to persist mode state, continuing anyway");
51916
+ }
51917
+ if (!argv.quiet) {
51918
+ console.log(chalk5.cyan.bold("\n\u{1F50D} Review Mode Activated\n"));
51919
+ console.log(chalk5.gray("Code review mode - analyzing for quality, security, and best practices"));
51920
+ console.log(chalk5.gray("Use `ax mode default` to exit review mode\n"));
51921
+ }
51922
+ if (argv.path) {
51923
+ const task = `Review the code at ${argv.path} for quality, security, and best practices`;
51924
+ const runArgs = ["run", argv.agent || "quality", task];
51925
+ if (argv.provider) runArgs.push("--provider", argv.provider);
51926
+ if (argv.verbose) runArgs.push("--verbose");
51927
+ if (argv.quiet) runArgs.push("--quiet");
51928
+ await runAxCommand(runArgs);
51929
+ } else {
51930
+ console.log(chalk5.gray('No path specified. Use `ax run quality "Review <path>"` to review code.'));
51931
+ }
51932
+ logger.info("Review shortcut executed", { path: argv.path, agent: argv.agent });
51933
+ } catch (error) {
51934
+ const err = error instanceof Error ? error : new Error(String(error));
51935
+ console.error(chalk5.red.bold(`
51936
+ \u274C Error: ${err.message}
51937
+ `));
51938
+ process.exit(1);
51939
+ }
51940
+ }
51941
+ };
51942
+
48522
51943
  // src/cli/index.ts
48523
51944
  installExitHandlers();
48524
51945
  var VERSION2 = getVersion();
@@ -48541,7 +51962,7 @@ globalTracker.mark("cli_start");
48541
51962
  type: "string",
48542
51963
  description: "Path to custom config file",
48543
51964
  global: true
48544
- }).command(setupCommand).command(initCommand).command(configureCommand).command(cliCommand).command(agentCommand).command(listCommand).command(runCommand).command(resumeCommand).command(runsCommand).command(sessionCommand).command(workspaceCommand).command(cacheCommand).command(configCommand).command(statusCommand4).command(doctorCommand2).command(cleanupCommand2).command(analyticsCommand).command(memoryCommand).command(mcpCommand).command(geminiCommand).command(providerLimitsCommand).command(providersCommand).command(flagsCommand).command(specCommand).command(genCommand).command(updateCommand).command(uninstallCommand).demandCommand(1, "You must provide a command. Run --help for usage.").help().version(VERSION2).alias("h", "help").alias("v", "version").strict().wrap(Math.min(120, yargs().terminalWidth())).parse();
51965
+ }).command(setupCommand).command(initCommand).command(configureCommand).command(cliCommand).command(agentCommand).command(listCommand).command(runCommand).command(resumeCommand).command(runsCommand).command(sessionCommand).command(workspaceCommand).command(cacheCommand).command(configCommand).command(statusCommand4).command(doctorCommand2).command(cleanupCommand2).command(analyticsCommand).command(memoryCommand).command(mcpCommand).command(geminiCommand).command(providerLimitsCommand).command(providersCommand).command(flagsCommand).command(specCommand).command(genCommand).command(updateCommand).command(uninstallCommand).command(modeCommand).command(debugInstructionsCommand).command(planCommand).command(iterateCommand).command(reviewCommand).demandCommand(1, "You must provide a command. Run --help for usage.").help().version(VERSION2).alias("h", "help").alias("v", "version").strict().wrap(Math.min(120, yargs().terminalWidth())).parse();
48545
51966
  globalTracker.mark("yargs_parse_end");
48546
51967
  globalTracker.measure("yargs_parsing", "yargs_parse_start", "yargs_parse_end");
48547
51968
  globalTracker.mark("options_setup_start");