@defai.digital/automatosx 5.1.2 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -583,12 +583,12 @@ var init_cache = __esm({
583
583
  });
584
584
 
585
585
  // src/types/path.ts
586
- var PathError2;
586
+ var PathError;
587
587
  var init_path = __esm({
588
588
  "src/types/path.ts"() {
589
589
  "use strict";
590
590
  init_esm_shims();
591
- PathError2 = class extends Error {
591
+ PathError = class extends Error {
592
592
  constructor(message, context) {
593
593
  super(message);
594
594
  this.context = context;
@@ -669,7 +669,7 @@ var init_path_resolver = __esm({
669
669
  */
670
670
  resolveUserPath(userPath) {
671
671
  if (process.platform !== "win32" && isWindowsPath(userPath)) {
672
- throw new PathError2(
672
+ throw new PathError(
673
673
  `Windows paths are not supported on ${process.platform}`,
674
674
  { path: userPath, type: "invalid_path" }
675
675
  );
@@ -776,7 +776,7 @@ var init_path_resolver = __esm({
776
776
  validateInProject(path3) {
777
777
  const boundary = this.checkBoundaries(path3);
778
778
  if (boundary === "outside_boundaries" || boundary === "system_restricted") {
779
- throw new PathError2("Path outside project directory", {
779
+ throw new PathError("Path outside project directory", {
780
780
  path: path3,
781
781
  projectDir: this.config.projectDir,
782
782
  boundary
@@ -868,7 +868,7 @@ var init_base_provider = __esm({
868
868
  async checkCLIAvailability() {
869
869
  try {
870
870
  const { spawn } = await import("child_process");
871
- return new Promise((resolve10) => {
871
+ return new Promise((resolve9) => {
872
872
  const child = spawn(this.config.command, ["--version"], {
873
873
  stdio: "ignore",
874
874
  timeout: 5e3
@@ -877,7 +877,7 @@ var init_base_provider = __esm({
877
877
  child.on("close", (code) => {
878
878
  if (!resolved) {
879
879
  resolved = true;
880
- resolve10(code === 0 || code === 1);
880
+ resolve9(code === 0 || code === 1);
881
881
  }
882
882
  });
883
883
  child.on("error", (error) => {
@@ -885,9 +885,9 @@ var init_base_provider = __esm({
885
885
  resolved = true;
886
886
  if (error.code === "ENOENT") {
887
887
  logger.warn(`CLI command not found: ${this.config.command}`);
888
- resolve10(false);
888
+ resolve9(false);
889
889
  } else {
890
- resolve10(true);
890
+ resolve9(true);
891
891
  }
892
892
  }
893
893
  });
@@ -895,7 +895,7 @@ var init_base_provider = __esm({
895
895
  if (!resolved) {
896
896
  resolved = true;
897
897
  child.kill();
898
- resolve10(false);
898
+ resolve9(false);
899
899
  }
900
900
  }, 5e3);
901
901
  });
@@ -1098,7 +1098,7 @@ var init_base_provider = __esm({
1098
1098
  return Math.ceil(text.length / 4);
1099
1099
  }
1100
1100
  sleep(ms) {
1101
- return new Promise((resolve10) => setTimeout(resolve10, ms));
1101
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
1102
1102
  }
1103
1103
  /**
1104
1104
  * Convert ExecutionRequest to messages array for cache key generation
@@ -1243,7 +1243,7 @@ This is a placeholder response. Set AUTOMATOSX_MOCK_PROVIDERS=false to use real
1243
1243
  */
1244
1244
  async executeRealCLI(prompt, request) {
1245
1245
  const { spawn } = await import("child_process");
1246
- return new Promise((resolve10, reject) => {
1246
+ return new Promise((resolve9, reject) => {
1247
1247
  let stdout = "";
1248
1248
  let stderr = "";
1249
1249
  let hasTimedOut = false;
@@ -1321,7 +1321,7 @@ Details: ${errorMsg}`
1321
1321
  if (!stdout.trim()) {
1322
1322
  reject(new Error("Claude CLI returned empty response"));
1323
1323
  } else {
1324
- resolve10({ content: stdout.trim() });
1324
+ resolve9({ content: stdout.trim() });
1325
1325
  }
1326
1326
  }
1327
1327
  });
@@ -1515,7 +1515,7 @@ This is a placeholder response. Set AUTOMATOSX_MOCK_PROVIDERS=false to use real
1515
1515
  */
1516
1516
  async executeRealCLI(prompt, request) {
1517
1517
  const { spawn } = await import("child_process");
1518
- return new Promise((resolve10, reject) => {
1518
+ return new Promise((resolve9, reject) => {
1519
1519
  let stdout = "";
1520
1520
  let stderr = "";
1521
1521
  let hasTimedOut = false;
@@ -1551,7 +1551,7 @@ This is a placeholder response. Set AUTOMATOSX_MOCK_PROVIDERS=false to use real
1551
1551
  if (code !== 0) {
1552
1552
  reject(new Error(`Gemini CLI exited with code ${code}: ${stderr}`));
1553
1553
  } else {
1554
- resolve10({ content: stdout.trim() });
1554
+ resolve9({ content: stdout.trim() });
1555
1555
  }
1556
1556
  });
1557
1557
  child.on("error", (error) => {
@@ -1716,7 +1716,7 @@ This is a placeholder response. Set AUTOMATOSX_MOCK_PROVIDERS=false to use real
1716
1716
  */
1717
1717
  async executeRealCLI(prompt, request) {
1718
1718
  const { spawn } = await import("child_process");
1719
- return new Promise((resolve10, reject) => {
1719
+ return new Promise((resolve9, reject) => {
1720
1720
  let stdout = "";
1721
1721
  let stderr = "";
1722
1722
  let hasTimedOut = false;
@@ -1751,7 +1751,7 @@ This is a placeholder response. Set AUTOMATOSX_MOCK_PROVIDERS=false to use real
1751
1751
  if (code !== 0) {
1752
1752
  reject(new Error(`OpenAI CLI exited with code ${code}: ${stderr}`));
1753
1753
  } else {
1754
- resolve10({ content: stdout.trim() });
1754
+ resolve9({ content: stdout.trim() });
1755
1755
  }
1756
1756
  });
1757
1757
  child.on("error", (error) => {
@@ -2014,16 +2014,8 @@ var DEFAULT_CONFIG = {
2014
2014
  timeout: 15e5,
2015
2015
  // 25 minutes (v5.1.0: increased from 15 min based on user feedback)
2016
2016
  enableCycleDetection: true
2017
- },
2018
- workspace: {
2019
- maxFileSize: 10485760,
2020
- // 10 MB
2021
- maxFiles: 100,
2022
- cleanupAfterDays: 7,
2023
- autoCleanup: true,
2024
- permissions: 448,
2025
- basePath: ".automatosx/workspaces"
2026
2017
  }
2018
+ // v5.2: workspace moved to root level
2027
2019
  },
2028
2020
  memory: {
2029
2021
  maxEntries: 1e4,
@@ -2056,10 +2048,10 @@ var DEFAULT_CONFIG = {
2056
2048
  }
2057
2049
  },
2058
2050
  workspace: {
2059
- basePath: ".automatosx/workspaces",
2060
- autoCleanup: true,
2061
- cleanupDays: 7,
2062
- maxFiles: 100
2051
+ prdPath: "automatosx/PRD",
2052
+ tmpPath: "automatosx/tmp",
2053
+ autoCleanupTmp: true,
2054
+ tmpCleanupDays: 7
2063
2055
  },
2064
2056
  logging: {
2065
2057
  level: "info",
@@ -2256,37 +2248,6 @@ var ConfigError = class _ConfigError extends BaseError {
2256
2248
  );
2257
2249
  }
2258
2250
  };
2259
- var PathError = class _PathError extends BaseError {
2260
- constructor(message, code = "E1103" /* PATH_INVALID */, suggestions = [], context, isOperational = true) {
2261
- super(message, code, suggestions, context, isOperational);
2262
- }
2263
- static traversal(path3) {
2264
- return new _PathError(
2265
- `Path traversal attempt detected: ${path3}`,
2266
- "E1100" /* PATH_TRAVERSAL */,
2267
- [
2268
- "Use relative paths within the project directory",
2269
- 'Avoid using ".." in file paths',
2270
- "Check your file path for security issues"
2271
- ],
2272
- { path: path3 },
2273
- false
2274
- // Security error, not operational
2275
- );
2276
- }
2277
- static notFound(path3, type = "Path") {
2278
- return new _PathError(
2279
- `${type} not found: ${path3}`,
2280
- "E1101" /* PATH_NOT_FOUND */,
2281
- [
2282
- "Check that the path exists and is accessible",
2283
- "Verify you have the correct permissions",
2284
- `Use "automatosx list" to see available ${type.toLowerCase()}s`
2285
- ],
2286
- { path: path3, type }
2287
- );
2288
- }
2289
- };
2290
2251
  var ProviderError = class _ProviderError extends BaseError {
2291
2252
  constructor(message, code = "E1301" /* PROVIDER_UNAVAILABLE */, suggestions = [], context) {
2292
2253
  super(message, code, suggestions, context);
@@ -2653,50 +2614,50 @@ function validateWorkspace(workspace) {
2653
2614
  });
2654
2615
  return errors;
2655
2616
  }
2656
- if (typeof workspace.basePath !== "string") {
2617
+ if (typeof workspace.prdPath !== "string") {
2657
2618
  errors.push({
2658
- path: `${basePath}.basePath`,
2659
- message: "basePath must be a string",
2660
- value: workspace.basePath
2619
+ path: `${basePath}.prdPath`,
2620
+ message: "prdPath must be a string",
2621
+ value: workspace.prdPath
2661
2622
  });
2662
- } else if (workspace.basePath.trim() === "") {
2623
+ } else if (workspace.prdPath.trim() === "") {
2663
2624
  errors.push({
2664
- path: `${basePath}.basePath`,
2665
- message: "basePath cannot be empty",
2666
- value: workspace.basePath
2625
+ path: `${basePath}.prdPath`,
2626
+ message: "prdPath cannot be empty",
2627
+ value: workspace.prdPath
2667
2628
  });
2668
2629
  }
2669
- if (typeof workspace.autoCleanup !== "boolean") {
2630
+ if (typeof workspace.tmpPath !== "string") {
2670
2631
  errors.push({
2671
- path: `${basePath}.autoCleanup`,
2672
- message: "autoCleanup must be a boolean",
2673
- value: workspace.autoCleanup
2632
+ path: `${basePath}.tmpPath`,
2633
+ message: "tmpPath must be a string",
2634
+ value: workspace.tmpPath
2674
2635
  });
2675
- }
2676
- if (typeof workspace.cleanupDays !== "number") {
2636
+ } else if (workspace.tmpPath.trim() === "") {
2677
2637
  errors.push({
2678
- path: `${basePath}.cleanupDays`,
2679
- message: "cleanupDays must be a number",
2680
- value: workspace.cleanupDays
2638
+ path: `${basePath}.tmpPath`,
2639
+ message: "tmpPath cannot be empty",
2640
+ value: workspace.tmpPath
2681
2641
  });
2682
- } else if (workspace.cleanupDays < 1) {
2642
+ }
2643
+ if (typeof workspace.autoCleanupTmp !== "boolean") {
2683
2644
  errors.push({
2684
- path: `${basePath}.cleanupDays`,
2685
- message: "cleanupDays must be >= 1",
2686
- value: workspace.cleanupDays
2645
+ path: `${basePath}.autoCleanupTmp`,
2646
+ message: "autoCleanupTmp must be a boolean",
2647
+ value: workspace.autoCleanupTmp
2687
2648
  });
2688
2649
  }
2689
- if (typeof workspace.maxFiles !== "number") {
2650
+ if (typeof workspace.tmpCleanupDays !== "number") {
2690
2651
  errors.push({
2691
- path: `${basePath}.maxFiles`,
2692
- message: "maxFiles must be a number",
2693
- value: workspace.maxFiles
2652
+ path: `${basePath}.tmpCleanupDays`,
2653
+ message: "tmpCleanupDays must be a number",
2654
+ value: workspace.tmpCleanupDays
2694
2655
  });
2695
- } else if (workspace.maxFiles < 1) {
2656
+ } else if (workspace.tmpCleanupDays < 1) {
2696
2657
  errors.push({
2697
- path: `${basePath}.maxFiles`,
2698
- message: "maxFiles must be >= 1",
2699
- value: workspace.maxFiles
2658
+ path: `${basePath}.tmpCleanupDays`,
2659
+ message: "tmpCleanupDays must be >= 1",
2660
+ value: workspace.tmpCleanupDays
2700
2661
  });
2701
2662
  }
2702
2663
  return errors;
@@ -3160,26 +3121,6 @@ function validateConfig2(config) {
3160
3121
  errors.push(`Orchestration: delegation.timeout must be <= ${VALIDATION_LIMITS.MAX_TIMEOUT}ms`);
3161
3122
  }
3162
3123
  }
3163
- if (!isPositiveInteger(config.orchestration.workspace.maxFileSize)) {
3164
- errors.push("Orchestration: workspace.maxFileSize must be a positive integer");
3165
- } else {
3166
- if (config.orchestration.workspace.maxFileSize < VALIDATION_LIMITS.MIN_FILE_SIZE) {
3167
- errors.push(`Orchestration: workspace.maxFileSize must be >= ${VALIDATION_LIMITS.MIN_FILE_SIZE} bytes`);
3168
- }
3169
- if (config.orchestration.workspace.maxFileSize > VALIDATION_LIMITS.MAX_FILE_SIZE) {
3170
- errors.push(`Orchestration: workspace.maxFileSize must be <= ${VALIDATION_LIMITS.MAX_FILE_SIZE} bytes (100MB max)`);
3171
- }
3172
- }
3173
- if (!isPositiveInteger(config.orchestration.workspace.maxFiles)) {
3174
- errors.push("Orchestration: workspace.maxFiles must be a positive integer");
3175
- } else if (config.orchestration.workspace.maxFiles > 1e4) {
3176
- errors.push("Orchestration: workspace.maxFiles must be <= 10000");
3177
- }
3178
- if (!isPositiveInteger(config.orchestration.workspace.cleanupAfterDays)) {
3179
- errors.push("Orchestration: workspace.cleanupAfterDays must be a positive integer");
3180
- } else if (config.orchestration.workspace.cleanupAfterDays > 365) {
3181
- errors.push("Orchestration: workspace.cleanupAfterDays must be <= 365 days");
3182
- }
3183
3124
  }
3184
3125
  if (!isPositiveInteger(config.memory.maxEntries)) {
3185
3126
  errors.push("Memory: maxEntries must be a positive integer");
@@ -3257,15 +3198,16 @@ function validateConfig2(config) {
3257
3198
  }
3258
3199
  }
3259
3200
  }
3260
- if (!isPositiveInteger(config.workspace.cleanupDays)) {
3261
- errors.push("Workspace: cleanupDays must be a positive integer");
3262
- } else if (config.workspace.cleanupDays > 365) {
3263
- errors.push("Workspace: cleanupDays must be <= 365 days");
3201
+ if (typeof config.workspace.prdPath !== "string" || !config.workspace.prdPath.trim()) {
3202
+ errors.push("Workspace: prdPath must be a non-empty string");
3203
+ }
3204
+ if (typeof config.workspace.tmpPath !== "string" || !config.workspace.tmpPath.trim()) {
3205
+ errors.push("Workspace: tmpPath must be a non-empty string");
3264
3206
  }
3265
- if (!isPositiveInteger(config.workspace.maxFiles)) {
3266
- errors.push("Workspace: maxFiles must be a positive integer");
3267
- } else if (config.workspace.maxFiles > 1e4) {
3268
- errors.push("Workspace: maxFiles must be <= 10000");
3207
+ if (!isPositiveInteger(config.workspace.tmpCleanupDays)) {
3208
+ errors.push("Workspace: tmpCleanupDays must be a positive integer");
3209
+ } else if (config.workspace.tmpCleanupDays > 365) {
3210
+ errors.push("Workspace: tmpCleanupDays must be <= 365 days");
3269
3211
  }
3270
3212
  if (config.logging?.retention) {
3271
3213
  if (!isPositiveInteger(config.logging.retention.maxSizeBytes)) {
@@ -3365,8 +3307,9 @@ function validateConfig2(config) {
3365
3307
  { name: "Abilities: basePath", value: config.abilities?.basePath },
3366
3308
  { name: "Abilities: fallbackPath", value: config.abilities?.fallbackPath },
3367
3309
  { name: "Orchestration: session.persistPath", value: config.orchestration?.session.persistPath },
3368
- { name: "Orchestration: workspace.basePath", value: config.orchestration?.workspace.basePath },
3369
- { name: "Workspace: basePath", value: config.workspace.basePath }
3310
+ // v5.2: Workspace moved to root level
3311
+ { name: "Workspace: prdPath", value: config.workspace.prdPath },
3312
+ { name: "Workspace: tmpPath", value: config.workspace.tmpPath }
3370
3313
  ];
3371
3314
  for (const { name, value } of pathFields) {
3372
3315
  if (value && typeof value === "string" && !isValidRelativePath(value)) {
@@ -3631,11 +3574,11 @@ async function listConfig(config, verbose) {
3631
3574
  console.log(chalk3.bold.white("\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
3632
3575
  console.log(chalk3.bold.white("\u2502 ") + chalk3.bold.cyan("Workspace"));
3633
3576
  console.log(chalk3.bold.white("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
3634
- console.log(formatKeyValue(" Base Path ", chalk3.blue(config.workspace.basePath)));
3635
- console.log(formatKeyValue(" Auto Cleanup ", config.workspace.autoCleanup ? chalk3.green("\u2713 Enabled") : chalk3.gray("\u2717 Disabled")));
3577
+ console.log(formatKeyValue(" PRD Path ", chalk3.blue(config.workspace.prdPath)));
3578
+ console.log(formatKeyValue(" Tmp Path ", chalk3.blue(config.workspace.tmpPath)));
3579
+ console.log(formatKeyValue(" Auto Cleanup ", config.workspace.autoCleanupTmp ? chalk3.green("\u2713 Enabled") : chalk3.gray("\u2717 Disabled")));
3636
3580
  if (verbose) {
3637
- console.log(formatKeyValue(" Cleanup Days ", chalk3.yellow(config.workspace.cleanupDays.toString())));
3638
- console.log(formatKeyValue(" Max Files ", chalk3.yellow(config.workspace.maxFiles.toString())));
3581
+ console.log(formatKeyValue(" Cleanup Days ", chalk3.yellow(config.workspace.tmpCleanupDays.toString())));
3639
3582
  }
3640
3583
  console.log(chalk3.bold.white("\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
3641
3584
  console.log(chalk3.bold.white("\u2502 ") + chalk3.bold.cyan("Logging"));
@@ -3725,21 +3668,24 @@ function setNestedValue(obj, path3, value) {
3725
3668
 
3726
3669
  // src/cli/commands/init.ts
3727
3670
  init_esm_shims();
3728
- import { mkdir as mkdir2, writeFile as writeFile3, access as access2 } from "fs/promises";
3671
+ import { mkdir as mkdir2, writeFile as writeFile3, access as access2, readdir, copyFile, rm, stat } from "fs/promises";
3729
3672
  import { resolve as resolve3, join as join2, dirname as dirname2 } from "path";
3730
3673
  import { fileURLToPath as fileURLToPath2 } from "url";
3731
- import { constants as constants2 } from "fs";
3674
+ import { constants as constants2, existsSync as existsSync3 } from "fs";
3732
3675
  import chalk4 from "chalk";
3733
3676
  init_logger();
3734
3677
  var __filename2 = fileURLToPath2(import.meta.url);
3735
3678
  var __dirname2 = dirname2(__filename2);
3736
3679
  function getPackageRoot() {
3737
- const currentDir = __dirname2;
3738
- if (currentDir.includes("/dist")) {
3739
- return join2(currentDir, "..");
3740
- } else {
3741
- return join2(currentDir, "../../..");
3680
+ let current = __dirname2;
3681
+ const root = "/";
3682
+ while (current !== root) {
3683
+ if (existsSync3(join2(current, "package.json"))) {
3684
+ return current;
3685
+ }
3686
+ current = dirname2(current);
3742
3687
  }
3688
+ throw new Error("Could not find package root (no package.json found)");
3743
3689
  }
3744
3690
  var initCommand = {
3745
3691
  command: "init [path]",
@@ -3759,8 +3705,25 @@ var initCommand = {
3759
3705
  handler: async (argv2) => {
3760
3706
  const projectDir = resolve3(argv2.path || ".");
3761
3707
  const automatosxDir = join2(projectDir, ".automatosx");
3762
- console.log(chalk4.blue.bold("\n\u{1F916} AutomatosX v4.0 - Project Initialization\n"));
3708
+ const configPath = join2(projectDir, "automatosx.config.json");
3709
+ const packageRoot = getPackageRoot();
3710
+ let version = "5.1.2";
3763
3711
  try {
3712
+ const packageJson = JSON.parse(
3713
+ await import("fs/promises").then((fs2) => fs2.readFile(join2(packageRoot, "package.json"), "utf-8"))
3714
+ );
3715
+ version = packageJson.version;
3716
+ } catch {
3717
+ }
3718
+ console.log(chalk4.blue.bold(`
3719
+ \u{1F916} AutomatosX v${version} - Project Initialization
3720
+ `));
3721
+ const createdResources = [];
3722
+ let shouldRollback = false;
3723
+ try {
3724
+ console.log(chalk4.cyan("\u{1F50D} Validating environment..."));
3725
+ await validateEnvironment(packageRoot);
3726
+ console.log(chalk4.green(" \u2713 Environment validation passed"));
3764
3727
  const exists = await checkExists2(automatosxDir);
3765
3728
  if (exists && !argv2.force) {
3766
3729
  console.log(chalk4.yellow("\u26A0\uFE0F AutomatosX is already initialized in this directory"));
@@ -3773,23 +3736,31 @@ var initCommand = {
3773
3736
  }
3774
3737
  console.log(chalk4.cyan("\u{1F4C1} Creating directory structure..."));
3775
3738
  await createDirectoryStructure(automatosxDir);
3739
+ createdResources.push(automatosxDir);
3776
3740
  console.log(chalk4.green(" \u2713 Directories created"));
3741
+ console.log(chalk4.cyan("\u{1F465} Installing team configurations..."));
3742
+ const teamCount = await copyExampleTeams(automatosxDir, packageRoot);
3743
+ console.log(chalk4.green(` \u2713 ${teamCount} team configurations installed`));
3777
3744
  console.log(chalk4.cyan("\u{1F916} Installing example agents..."));
3778
- await copyExampleAgents(automatosxDir);
3779
- console.log(chalk4.green(" \u2713 5 example agents installed"));
3745
+ const agentCount = await copyExampleAgents(automatosxDir, packageRoot);
3746
+ console.log(chalk4.green(` \u2713 ${agentCount} example agents installed`));
3780
3747
  console.log(chalk4.cyan("\u26A1 Installing example abilities..."));
3781
- await copyExampleAbilities(automatosxDir);
3782
- console.log(chalk4.green(" \u2713 15 example abilities installed"));
3748
+ const abilityCount = await copyExampleAbilities(automatosxDir, packageRoot);
3749
+ console.log(chalk4.green(` \u2713 ${abilityCount} example abilities installed`));
3783
3750
  console.log(chalk4.cyan("\u{1F4CB} Installing agent templates..."));
3784
- await copyExampleTemplates(automatosxDir);
3785
- console.log(chalk4.green(" \u2713 5 agent templates installed"));
3751
+ const templateCount = await copyExampleTemplates(automatosxDir, packageRoot);
3752
+ console.log(chalk4.green(` \u2713 ${templateCount} agent templates installed`));
3786
3753
  console.log(chalk4.cyan("\u2699\uFE0F Generating configuration..."));
3787
- const configPath = join2(projectDir, "automatosx.config.json");
3788
3754
  await createDefaultConfig(configPath, argv2.force ?? false);
3755
+ createdResources.push(configPath);
3789
3756
  console.log(chalk4.green(" \u2713 Configuration created"));
3790
3757
  console.log(chalk4.cyan("\u{1F50C} Setting up Claude Code integration..."));
3791
- await setupClaudeIntegration(projectDir);
3758
+ await setupClaudeIntegration(projectDir, packageRoot);
3759
+ createdResources.push(join2(projectDir, ".claude"));
3792
3760
  console.log(chalk4.green(" \u2713 Claude Code integration configured"));
3761
+ console.log(chalk4.cyan("\u{1F527} Initializing git repository..."));
3762
+ await initializeGitRepository(projectDir);
3763
+ console.log(chalk4.green(" \u2713 Git repository initialized"));
3793
3764
  console.log(chalk4.cyan("\u{1F4DD} Updating .gitignore..."));
3794
3765
  await updateGitignore(projectDir);
3795
3766
  console.log(chalk4.green(" \u2713 .gitignore updated"));
@@ -3815,15 +3786,28 @@ var initCommand = {
3815
3786
  console.log(chalk4.gray(" \u2022 Use /ax command in Claude Code"));
3816
3787
  console.log(chalk4.gray(' \u2022 Example: /ax assistant "Explain this code"'));
3817
3788
  console.log(chalk4.gray(" \u2022 MCP tools available in .claude/mcp/\n"));
3818
- logger.info("AutomatosX initialized", { projectDir, automatosxDir });
3789
+ logger.info("AutomatosX initialized", {
3790
+ projectDir,
3791
+ automatosxDir,
3792
+ counts: { teams: teamCount, agents: agentCount, abilities: abilityCount, templates: templateCount }
3793
+ });
3819
3794
  } catch (error) {
3795
+ shouldRollback = true;
3796
+ if (createdResources.length > 0 && !argv2.force) {
3797
+ console.log(chalk4.yellow("\n\u26A0\uFE0F Initialization failed. Rolling back changes..."));
3798
+ await rollbackCreatedResources(createdResources);
3799
+ console.log(chalk4.green(" \u2713 Rollback completed"));
3800
+ }
3820
3801
  printError(error, {
3821
3802
  verbose: false,
3822
3803
  showCode: true,
3823
3804
  showSuggestions: true,
3824
3805
  colors: true
3825
3806
  });
3826
- logger.error("Initialization failed", { error: error.message });
3807
+ logger.error("Initialization failed", {
3808
+ error: error.message,
3809
+ rolledBack: shouldRollback && createdResources.length > 0
3810
+ });
3827
3811
  process.exit(1);
3828
3812
  }
3829
3813
  }
@@ -3849,57 +3833,116 @@ async function createDirectoryStructure(baseDir) {
3849
3833
  // v5.1: MCP memory export directory
3850
3834
  join2(baseDir, "sessions"),
3851
3835
  // v5.1: Session persistence
3852
- join2(baseDir, "workspaces"),
3836
+ // v5.2: Removed 'workspaces' - automatosx/PRD and automatosx/tmp created on-demand
3853
3837
  join2(baseDir, "logs")
3854
3838
  ];
3855
3839
  for (const dir of dirs) {
3856
3840
  await mkdir2(dir, { recursive: true });
3857
3841
  }
3858
3842
  }
3859
- async function copyExampleAgents(baseDir) {
3860
- const { readdir: readdir8, copyFile: copyFile2 } = await import("fs/promises");
3861
- const examplesDir = join2(getPackageRoot(), "examples/agents");
3843
+ async function validateEnvironment(packageRoot) {
3844
+ const requiredDirs = [
3845
+ "examples/agents",
3846
+ "examples/abilities",
3847
+ "examples/templates",
3848
+ "examples/teams"
3849
+ ];
3850
+ const errors = [];
3851
+ for (const dir of requiredDirs) {
3852
+ const fullPath = join2(packageRoot, dir);
3853
+ try {
3854
+ await stat(fullPath);
3855
+ } catch {
3856
+ errors.push(`Missing required directory: ${dir}`);
3857
+ }
3858
+ }
3859
+ if (errors.length > 0) {
3860
+ throw new Error(
3861
+ `Environment validation failed:
3862
+ ${errors.map((e) => ` \u2022 ${e}`).join("\n")}
3863
+
3864
+ This usually means the package is corrupted. Try reinstalling:
3865
+ npm uninstall -g @defai.digital/automatosx
3866
+ npm install -g @defai.digital/automatosx`
3867
+ );
3868
+ }
3869
+ }
3870
+ async function rollbackCreatedResources(resources) {
3871
+ for (const resource of resources.reverse()) {
3872
+ try {
3873
+ await rm(resource, { recursive: true, force: true });
3874
+ logger.info("Rolled back resource", { resource });
3875
+ } catch (error) {
3876
+ logger.warn("Failed to rollback resource", {
3877
+ resource,
3878
+ error: error.message
3879
+ });
3880
+ }
3881
+ }
3882
+ }
3883
+ async function copyExampleTeams(baseDir, packageRoot) {
3884
+ const examplesDir = join2(packageRoot, "examples/teams");
3885
+ const targetDir = join2(baseDir, "teams");
3886
+ const files = await readdir(examplesDir);
3887
+ let count = 0;
3888
+ for (const file of files) {
3889
+ if (file.endsWith(".yaml")) {
3890
+ await copyFile(join2(examplesDir, file), join2(targetDir, file));
3891
+ count++;
3892
+ }
3893
+ }
3894
+ if (count === 0) {
3895
+ throw new Error(`No team configuration files found in ${examplesDir}`);
3896
+ }
3897
+ return count;
3898
+ }
3899
+ async function copyExampleAgents(baseDir, packageRoot) {
3900
+ const examplesDir = join2(packageRoot, "examples/agents");
3862
3901
  const targetDir = join2(baseDir, "agents");
3863
- try {
3864
- const files = await readdir8(examplesDir);
3865
- for (const file of files) {
3866
- if (file.endsWith(".yaml")) {
3867
- await copyFile2(join2(examplesDir, file), join2(targetDir, file));
3868
- }
3902
+ const files = await readdir(examplesDir);
3903
+ let count = 0;
3904
+ for (const file of files) {
3905
+ if (file.endsWith(".yaml")) {
3906
+ await copyFile(join2(examplesDir, file), join2(targetDir, file));
3907
+ count++;
3869
3908
  }
3870
- } catch (error) {
3871
- logger.warn("Could not copy example agents", { error: error.message });
3872
3909
  }
3910
+ if (count === 0) {
3911
+ throw new Error(`No agent files found in ${examplesDir}`);
3912
+ }
3913
+ return count;
3873
3914
  }
3874
- async function copyExampleAbilities(baseDir) {
3875
- const { readdir: readdir8, copyFile: copyFile2 } = await import("fs/promises");
3876
- const examplesDir = join2(getPackageRoot(), "examples/abilities");
3915
+ async function copyExampleAbilities(baseDir, packageRoot) {
3916
+ const examplesDir = join2(packageRoot, "examples/abilities");
3877
3917
  const targetDir = join2(baseDir, "abilities");
3878
- try {
3879
- const files = await readdir8(examplesDir);
3880
- for (const file of files) {
3881
- if (file.endsWith(".md")) {
3882
- await copyFile2(join2(examplesDir, file), join2(targetDir, file));
3883
- }
3918
+ const files = await readdir(examplesDir);
3919
+ let count = 0;
3920
+ for (const file of files) {
3921
+ if (file.endsWith(".md")) {
3922
+ await copyFile(join2(examplesDir, file), join2(targetDir, file));
3923
+ count++;
3884
3924
  }
3885
- } catch (error) {
3886
- logger.warn("Could not copy example abilities", { error: error.message });
3887
3925
  }
3926
+ if (count === 0) {
3927
+ throw new Error(`No ability files found in ${examplesDir}`);
3928
+ }
3929
+ return count;
3888
3930
  }
3889
- async function copyExampleTemplates(baseDir) {
3890
- const { readdir: readdir8, copyFile: copyFile2 } = await import("fs/promises");
3891
- const examplesDir = join2(getPackageRoot(), "examples/templates");
3931
+ async function copyExampleTemplates(baseDir, packageRoot) {
3932
+ const examplesDir = join2(packageRoot, "examples/templates");
3892
3933
  const targetDir = join2(baseDir, "templates");
3893
- try {
3894
- const files = await readdir8(examplesDir);
3895
- for (const file of files) {
3896
- if (file.endsWith(".yaml")) {
3897
- await copyFile2(join2(examplesDir, file), join2(targetDir, file));
3898
- }
3934
+ const files = await readdir(examplesDir);
3935
+ let count = 0;
3936
+ for (const file of files) {
3937
+ if (file.endsWith(".yaml")) {
3938
+ await copyFile(join2(examplesDir, file), join2(targetDir, file));
3939
+ count++;
3899
3940
  }
3900
- } catch (error) {
3901
- logger.warn("Could not copy agent templates", { error: error.message });
3902
3941
  }
3942
+ if (count === 0) {
3943
+ throw new Error(`No template files found in ${examplesDir}`);
3944
+ }
3945
+ return count;
3903
3946
  }
3904
3947
  async function createDefaultConfig(configPath, force) {
3905
3948
  const exists = await checkExists2(configPath);
@@ -3915,31 +3958,73 @@ async function createDefaultConfig(configPath, force) {
3915
3958
  const content = JSON.stringify(config, null, 2);
3916
3959
  await writeFile3(configPath, content, "utf-8");
3917
3960
  }
3918
- async function setupClaudeIntegration(projectDir) {
3919
- const { readdir: readdir8, copyFile: copyFile2 } = await import("fs/promises");
3920
- const examplesBaseDir = join2(getPackageRoot(), "examples/claude");
3961
+ async function setupClaudeIntegration(projectDir, packageRoot) {
3962
+ const examplesBaseDir = join2(packageRoot, "examples/claude");
3921
3963
  const claudeDir = join2(projectDir, ".claude");
3922
3964
  const commandsDir = join2(claudeDir, "commands");
3923
3965
  const mcpDir = join2(claudeDir, "mcp");
3924
3966
  await mkdir2(commandsDir, { recursive: true });
3925
3967
  await mkdir2(mcpDir, { recursive: true });
3926
- try {
3927
- const commandsSourceDir = join2(examplesBaseDir, "commands");
3928
- const commandFiles = await readdir8(commandsSourceDir);
3929
- for (const file of commandFiles) {
3930
- if (file.endsWith(".md")) {
3931
- await copyFile2(join2(commandsSourceDir, file), join2(commandsDir, file));
3932
- }
3968
+ const commandsSourceDir = join2(examplesBaseDir, "commands");
3969
+ const commandFiles = await readdir(commandsSourceDir);
3970
+ for (const file of commandFiles) {
3971
+ if (file.endsWith(".md")) {
3972
+ await copyFile(join2(commandsSourceDir, file), join2(commandsDir, file));
3933
3973
  }
3934
- const mcpSourceDir = join2(examplesBaseDir, "mcp");
3935
- const mcpFiles = await readdir8(mcpSourceDir);
3936
- for (const file of mcpFiles) {
3937
- if (file.endsWith(".json")) {
3938
- await copyFile2(join2(mcpSourceDir, file), join2(mcpDir, file));
3939
- }
3974
+ }
3975
+ const mcpSourceDir = join2(examplesBaseDir, "mcp");
3976
+ const mcpFiles = await readdir(mcpSourceDir);
3977
+ for (const file of mcpFiles) {
3978
+ if (file.endsWith(".json")) {
3979
+ await copyFile(join2(mcpSourceDir, file), join2(mcpDir, file));
3980
+ }
3981
+ }
3982
+ }
3983
+ async function initializeGitRepository(projectDir) {
3984
+ const gitDir = join2(projectDir, ".git");
3985
+ try {
3986
+ const isGitRepo = await checkExists2(gitDir);
3987
+ if (isGitRepo) {
3988
+ logger.info("Git repository already exists, skipping initialization");
3989
+ return;
3940
3990
  }
3991
+ const { spawn } = await import("child_process");
3992
+ await new Promise((resolve9, reject) => {
3993
+ const child = spawn("git", ["init"], {
3994
+ cwd: projectDir,
3995
+ stdio: "pipe"
3996
+ });
3997
+ let stderr = "";
3998
+ child.stderr?.on("data", (data) => {
3999
+ stderr += data.toString();
4000
+ });
4001
+ child.on("close", (code) => {
4002
+ if (code !== 0) {
4003
+ reject(new Error(`git init failed with code ${code}: ${stderr}`));
4004
+ } else {
4005
+ logger.info("Git repository initialized successfully");
4006
+ resolve9();
4007
+ }
4008
+ });
4009
+ child.on("error", (error) => {
4010
+ reject(error);
4011
+ });
4012
+ });
3941
4013
  } catch (error) {
3942
- logger.warn("Could not copy Claude integration files", { error: error.message });
4014
+ const errorMessage = error.message;
4015
+ if (errorMessage.includes("ENOENT") || errorMessage.includes("spawn git")) {
4016
+ console.log(chalk4.yellow(" \u26A0\uFE0F Git is not installed - skipping repository initialization"));
4017
+ console.log(chalk4.gray(" Note: Codex CLI requires git. Install git to use Codex provider."));
4018
+ logger.warn("Git not found, skipping repository initialization", {
4019
+ error: errorMessage
4020
+ });
4021
+ } else {
4022
+ console.log(chalk4.yellow(" \u26A0\uFE0F Failed to initialize git repository"));
4023
+ console.log(chalk4.gray(` ${errorMessage}`));
4024
+ logger.warn("Git initialization failed", {
4025
+ error: errorMessage
4026
+ });
4027
+ }
3943
4028
  }
3944
4029
  }
3945
4030
  async function updateGitignore(projectDir) {
@@ -3948,8 +4033,8 @@ async function updateGitignore(projectDir) {
3948
4033
  "",
3949
4034
  "# AutomatosX",
3950
4035
  ".automatosx/memory/",
3951
- ".automatosx/workspaces/",
3952
4036
  ".automatosx/logs/",
4037
+ "automatosx/tmp/ # v5.2: Temporary files",
3953
4038
  "automatosx.config.json # Optional: remove to track config",
3954
4039
  ""
3955
4040
  ].join("\n");
@@ -3974,7 +4059,7 @@ async function updateGitignore(projectDir) {
3974
4059
  init_esm_shims();
3975
4060
  init_logger();
3976
4061
  init_path_resolver();
3977
- import { readdir } from "fs/promises";
4062
+ import { readdir as readdir2 } from "fs/promises";
3978
4063
  import { join as join3 } from "path";
3979
4064
  import chalk5 from "chalk";
3980
4065
  var listCommand = {
@@ -4017,13 +4102,13 @@ var listCommand = {
4017
4102
  };
4018
4103
  async function listAgents(pathResolver) {
4019
4104
  const agentsDir = pathResolver.getAgentsDirectory();
4020
- const { existsSync: existsSync9 } = await import("fs");
4105
+ const { existsSync: existsSync10 } = await import("fs");
4021
4106
  const projectDir = await detectProjectRoot();
4022
4107
  const examplesDir = join3(projectDir, "examples", "agents");
4023
4108
  try {
4024
4109
  const agentFiles = [];
4025
- if (existsSync9(agentsDir)) {
4026
- const files = await readdir(agentsDir);
4110
+ if (existsSync10(agentsDir)) {
4111
+ const files = await readdir2(agentsDir);
4027
4112
  for (const file of files) {
4028
4113
  if (file.endsWith(".yaml") || file.endsWith(".yml")) {
4029
4114
  agentFiles.push({
@@ -4034,8 +4119,8 @@ async function listAgents(pathResolver) {
4034
4119
  }
4035
4120
  }
4036
4121
  }
4037
- if (existsSync9(examplesDir)) {
4038
- const files = await readdir(examplesDir);
4122
+ if (existsSync10(examplesDir)) {
4123
+ const files = await readdir2(examplesDir);
4039
4124
  for (const file of files) {
4040
4125
  if (file.endsWith(".yaml") || file.endsWith(".yml")) {
4041
4126
  const alreadyLoaded = agentFiles.some((a) => a.file === file);
@@ -4090,7 +4175,7 @@ async function listAgents(pathResolver) {
4090
4175
  async function listAbilities(pathResolver) {
4091
4176
  const abilitiesDir = pathResolver.getAbilitiesDirectory();
4092
4177
  try {
4093
- const files = await readdir(abilitiesDir);
4178
+ const files = await readdir2(abilitiesDir);
4094
4179
  const abilityFiles = files.filter((f) => f.endsWith(".md"));
4095
4180
  if (abilityFiles.length === 0) {
4096
4181
  console.log(chalk5.yellow("\n\u26A0\uFE0F No abilities found\n"));
@@ -4338,7 +4423,7 @@ var Router = class {
4338
4423
  init_esm_shims();
4339
4424
  import Database from "better-sqlite3";
4340
4425
  import * as sqliteVec from "sqlite-vec";
4341
- import { existsSync as existsSync3, mkdirSync } from "fs";
4426
+ import { existsSync as existsSync4, mkdirSync } from "fs";
4342
4427
  import { dirname as dirname4 } from "path";
4343
4428
 
4344
4429
  // src/types/memory.ts
@@ -4391,7 +4476,7 @@ var MemoryManager = class _MemoryManager {
4391
4476
  };
4392
4477
  this.validateCleanupConfig();
4393
4478
  const dir = dirname4(this.config.dbPath);
4394
- if (!existsSync3(dir)) {
4479
+ if (!existsSync4(dir)) {
4395
4480
  mkdirSync(dir, { recursive: true });
4396
4481
  }
4397
4482
  this.db = new Database(this.config.dbPath);
@@ -5147,9 +5232,9 @@ var MemoryManager = class _MemoryManager {
5147
5232
  }
5148
5233
  try {
5149
5234
  const { dirname: dirname9 } = await import("path");
5150
- const { mkdir: mkdir7 } = await import("fs/promises");
5235
+ const { mkdir: mkdir6 } = await import("fs/promises");
5151
5236
  const destDir = dirname9(destPath);
5152
- await mkdir7(destDir, { recursive: true });
5237
+ await mkdir6(destDir, { recursive: true });
5153
5238
  await this.db.backup(destPath);
5154
5239
  logger.info("Database backup created", { destPath });
5155
5240
  } catch (error) {
@@ -5165,7 +5250,7 @@ var MemoryManager = class _MemoryManager {
5165
5250
  throw new MemoryError("Memory manager not initialized", "DATABASE_ERROR");
5166
5251
  }
5167
5252
  try {
5168
- if (!existsSync3(srcPath)) {
5253
+ if (!existsSync4(srcPath)) {
5169
5254
  throw new MemoryError(
5170
5255
  `Backup file not found: ${srcPath}`,
5171
5256
  "DATABASE_ERROR",
@@ -5206,7 +5291,7 @@ var MemoryManager = class _MemoryManager {
5206
5291
  } = options || {};
5207
5292
  try {
5208
5293
  const destDir = dirname4(filePath);
5209
- if (!existsSync3(destDir)) {
5294
+ if (!existsSync4(destDir)) {
5210
5295
  mkdirSync(destDir, { recursive: true });
5211
5296
  }
5212
5297
  let query = "SELECT e.* FROM memory_entries e";
@@ -5304,7 +5389,7 @@ var MemoryManager = class _MemoryManager {
5304
5389
  clearExisting = false
5305
5390
  } = options || {};
5306
5391
  try {
5307
- if (!existsSync3(filePath)) {
5392
+ if (!existsSync4(filePath)) {
5308
5393
  throw new MemoryError(
5309
5394
  `Import file not found: ${filePath}`,
5310
5395
  "DATABASE_ERROR",
@@ -5410,7 +5495,7 @@ var MemoryManager = class _MemoryManager {
5410
5495
  // src/core/session-manager.ts
5411
5496
  init_esm_shims();
5412
5497
  import { randomUUID } from "crypto";
5413
- import { readFile as readFile2, writeFile as writeFile4, mkdir as mkdir3, rename, copyFile, unlink } from "fs/promises";
5498
+ import { readFile as readFile2, writeFile as writeFile4, mkdir as mkdir3, rename, copyFile as copyFile2, unlink } from "fs/promises";
5414
5499
  import { dirname as dirname5 } from "path";
5415
5500
 
5416
5501
  // src/types/orchestration.ts
@@ -5432,14 +5517,6 @@ var SessionError = class extends Error {
5432
5517
  this.name = "SessionError";
5433
5518
  }
5434
5519
  };
5435
- var WorkspaceError = class extends Error {
5436
- constructor(message, workspacePath, reason) {
5437
- super(message);
5438
- this.workspacePath = workspacePath;
5439
- this.reason = reason;
5440
- this.name = "WorkspaceError";
5441
- }
5442
- };
5443
5520
 
5444
5521
  // src/core/session-manager.ts
5445
5522
  init_logger();
@@ -5874,8 +5951,8 @@ var SessionManager = class _SessionManager {
5874
5951
  * const result = await sessionManager.cleanupOldSessions();
5875
5952
  * console.log(`Removed ${result.removedCount} sessions`);
5876
5953
  *
5877
- * // Use removedSessionIds to cleanup corresponding workspaces
5878
- * await workspaceManager.cleanupSessionWorkspaces(result.removedSessionIds);
5954
+ * // v5.2: Session workspaces no longer exist
5955
+ * // All agents share automatosx/PRD and automatosx/tmp
5879
5956
  * ```
5880
5957
  */
5881
5958
  async cleanupOldSessions(maxAgeDays = 7) {
@@ -6101,7 +6178,7 @@ var SessionManager = class _SessionManager {
6101
6178
  }
6102
6179
  try {
6103
6180
  const backupPath = `${this.persistencePath}.corrupted.${Date.now()}`;
6104
- await copyFile(this.persistencePath, backupPath);
6181
+ await copyFile2(this.persistencePath, backupPath);
6105
6182
  logger.error("Corrupted sessions file backed up, starting fresh", {
6106
6183
  path: this.persistencePath,
6107
6184
  backupPath,
@@ -6141,488 +6218,291 @@ var SessionManager = class _SessionManager {
6141
6218
 
6142
6219
  // src/core/workspace-manager.ts
6143
6220
  init_esm_shims();
6221
+ init_logger();
6144
6222
  import { promises as fs } from "fs";
6145
6223
  import path2 from "path";
6146
- init_logger();
6147
6224
  var WorkspaceManager = class _WorkspaceManager {
6148
- workspacesRoot;
6149
- sharedRoot;
6150
- sessionsRoot;
6151
- persistentRoot;
6152
- /** Maximum file size for writeToSession (from config) */
6153
- maxFileSize;
6154
- /** UUID v4 validation regex (static for performance) */
6155
- static UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
6225
+ projectDir;
6226
+ prdDir;
6227
+ tmpDir;
6228
+ directoriesEnsured = false;
6229
+ /** Maximum file size in bytes (10MB) */
6230
+ static MAX_FILE_SIZE = 10 * 1024 * 1024;
6156
6231
  /**
6157
6232
  * Create WorkspaceManager
6158
6233
  *
6159
6234
  * @param projectDir - Project directory path
6160
- * @param config - Workspace configuration (optional, defaults to 10MB max file size)
6235
+ * @param config - Optional workspace configuration
6161
6236
  */
6162
6237
  constructor(projectDir, config) {
6163
- this.workspacesRoot = path2.join(projectDir, ".automatosx", "workspaces");
6164
- this.sharedRoot = path2.join(this.workspacesRoot, "shared");
6165
- this.sessionsRoot = path2.join(this.sharedRoot, "sessions");
6166
- this.persistentRoot = path2.join(this.sharedRoot, "persistent");
6167
- this.maxFileSize = config?.maxFileSize ?? 10 * 1024 * 1024;
6168
- }
6169
- /**
6170
- * Initialize workspace structure
6171
- *
6172
- * Creates all necessary directories for workspace management.
6173
- *
6174
- * @example
6175
- * ```typescript
6176
- * await workspaceManager.initialize();
6177
- * ```
6178
- */
6179
- async initialize() {
6180
- await fs.mkdir(this.workspacesRoot, { recursive: true });
6181
- await fs.mkdir(this.sharedRoot, { recursive: true });
6182
- await fs.mkdir(this.sessionsRoot, { recursive: true });
6183
- await fs.mkdir(this.persistentRoot, { recursive: true });
6184
- logger.debug("Workspace structure initialized", {
6185
- workspacesRoot: this.workspacesRoot
6186
- });
6238
+ this.projectDir = projectDir;
6239
+ const prdPath = config?.prdPath ?? "automatosx/PRD";
6240
+ const tmpPath = config?.tmpPath ?? "automatosx/tmp";
6241
+ this.prdDir = path2.join(projectDir, prdPath);
6242
+ this.tmpDir = path2.join(projectDir, tmpPath);
6187
6243
  }
6188
6244
  /**
6189
- * Create workspace for a session
6245
+ * Ensure PRD/tmp directories exist (lazy initialization with caching)
6190
6246
  *
6191
- * @param sessionId - Session ID
6192
- * @throws {WorkspaceError} If creation fails
6193
- *
6194
- * @example
6195
- * ```typescript
6196
- * await workspaceManager.createSessionWorkspace('session-123');
6197
- * ```
6247
+ * Creates directories only when needed, not during init.
6248
+ * Uses caching to avoid repeated filesystem checks.
6198
6249
  */
6199
- async createSessionWorkspace(sessionId) {
6200
- const sessionDir = this.getSessionDir(sessionId);
6201
- const specsDir = path2.join(sessionDir, "specs");
6202
- const outputsDir = path2.join(sessionDir, "outputs");
6203
- try {
6204
- await fs.mkdir(sessionDir, { recursive: true });
6205
- await fs.mkdir(specsDir, { recursive: true });
6206
- await fs.mkdir(outputsDir, { recursive: true });
6207
- logger.info("Session workspace created", {
6208
- sessionId,
6209
- path: sessionDir
6210
- });
6211
- } catch (error) {
6212
- throw new WorkspaceError(
6213
- `Failed to create session workspace: ${error.message}`,
6214
- sessionDir,
6215
- "creation_failed"
6216
- );
6250
+ async ensureDirectories() {
6251
+ if (this.directoriesEnsured) {
6252
+ return;
6217
6253
  }
6254
+ await fs.mkdir(this.prdDir, { recursive: true });
6255
+ await fs.mkdir(this.tmpDir, { recursive: true });
6256
+ this.directoriesEnsured = true;
6257
+ logger.debug("Workspace directories ensured", {
6258
+ prdDir: this.prdDir,
6259
+ tmpDir: this.tmpDir
6260
+ });
6218
6261
  }
6219
6262
  /**
6220
- * Get agent's output directory within a session
6221
- *
6222
- * @param sessionId - Session ID
6223
- * @param agentName - Agent name
6224
- * @returns Path to agent's output directory
6225
- */
6226
- getAgentOutputDir(sessionId, agentName) {
6227
- return path2.join(this.getSessionDir(sessionId), "outputs", agentName);
6228
- }
6229
- /**
6230
- * Validate session ID format (must be valid UUID v4)
6263
+ * Validate file size
6231
6264
  *
6232
- * @param sessionId - Session ID to validate
6233
- * @throws {WorkspaceError} If session ID is invalid
6265
+ * @param content - File content
6266
+ * @throws {Error} If file size exceeds MAX_FILE_SIZE
6234
6267
  */
6235
- validateSessionId(sessionId) {
6236
- if (!_WorkspaceManager.UUID_V4_REGEX.test(sessionId)) {
6237
- throw new WorkspaceError(
6238
- `Invalid session ID format: ${sessionId}. Session IDs must be valid UUID v4.`,
6239
- void 0,
6240
- "invalid_session_id"
6268
+ validateFileSize(content) {
6269
+ const sizeInBytes = Buffer.byteLength(content, "utf-8");
6270
+ if (sizeInBytes > _WorkspaceManager.MAX_FILE_SIZE) {
6271
+ throw new Error(
6272
+ `File too large: ${sizeInBytes} bytes (max: ${_WorkspaceManager.MAX_FILE_SIZE} bytes)`
6241
6273
  );
6242
6274
  }
6243
6275
  }
6244
6276
  /**
6245
- * Get session directory path
6277
+ * Validate path security (prevent path traversal attacks)
6246
6278
  *
6247
- * @param sessionId - Session ID
6248
- * @returns Session directory path
6249
- */
6250
- getSessionDir(sessionId) {
6251
- this.validateSessionId(sessionId);
6252
- return path2.join(this.sessionsRoot, sessionId);
6253
- }
6254
- /**
6255
- * Validate that a file path is safe (prevents path traversal attacks)
6279
+ * Security checks:
6280
+ * 1. Reject absolute paths
6281
+ * 2. Normalize path and check for '..' at start
6282
+ * 3. Verify resolved path is within base directory
6256
6283
  *
6257
6284
  * @param baseDir - Base directory that file must be within
6258
6285
  * @param filePath - Relative file path to validate
6259
6286
  * @returns Resolved absolute path
6260
- * @throws {WorkspaceError} If path is unsafe
6261
- *
6262
- * Security checks:
6263
- * 1. Normalize path to resolve '..' and '.'
6264
- * 2. Resolve to absolute path
6265
- * 3. Verify resolved path is within base directory
6266
- * 4. Prevent symlink attacks by checking real path
6287
+ * @throws {Error} If path is unsafe
6267
6288
  */
6268
- async validatePath(baseDir, filePath) {
6289
+ validatePath(baseDir, filePath) {
6290
+ if (!filePath || !filePath.trim()) {
6291
+ throw new Error("File path cannot be empty");
6292
+ }
6269
6293
  if (path2.isAbsolute(filePath)) {
6270
- throw new WorkspaceError(
6271
- `Absolute paths not allowed: ${filePath}`,
6272
- filePath,
6273
- "permission_denied"
6274
- );
6294
+ throw new Error(`Absolute paths not allowed: ${filePath}`);
6275
6295
  }
6276
6296
  const normalized = path2.normalize(filePath);
6277
6297
  if (normalized.startsWith("..")) {
6278
- throw new WorkspaceError(
6279
- `Path traversal detected: ${filePath}`,
6280
- filePath,
6281
- "permission_denied"
6282
- );
6298
+ throw new Error(`Path traversal detected: ${filePath}`);
6299
+ }
6300
+ if (normalized === "." || normalized === "./") {
6301
+ throw new Error("Cannot write to base directory itself");
6283
6302
  }
6284
6303
  const resolved = path2.resolve(baseDir, normalized);
6285
6304
  const resolvedBase = path2.resolve(baseDir);
6286
6305
  if (!resolved.startsWith(resolvedBase + path2.sep) && resolved !== resolvedBase) {
6287
- throw new WorkspaceError(
6288
- `Path outside workspace: ${filePath}`,
6289
- filePath,
6290
- "permission_denied"
6291
- );
6306
+ throw new Error(`Path outside workspace: ${filePath}`);
6292
6307
  }
6293
6308
  return resolved;
6294
6309
  }
6295
6310
  /**
6296
- * Get agent's private workspace directory
6311
+ * Write PRD document
6297
6312
  *
6298
- * @param agentName - Agent name
6299
- * @returns Agent workspace path
6300
- */
6301
- getAgentWorkspaceDir(agentName) {
6302
- return path2.join(this.workspacesRoot, agentName);
6303
- }
6304
- /**
6305
- * Write file to session workspace (agent's output area)
6313
+ * PRD documents are permanent and should contain:
6314
+ * - Feature designs (feature-*.md)
6315
+ * - Workflow plans (workflow-*.md)
6316
+ * - Architecture proposals (proposal-*.md)
6306
6317
  *
6307
- * @param sessionId - Session ID
6308
- * @param agentName - Agent writing the file
6309
- * @param filePath - Relative file path within agent's output
6318
+ * @param fileName - Relative file path within PRD/
6310
6319
  * @param content - File content
6311
- * @param callerAgent - Optional: Agent profile of the caller (for permission verification)
6312
- * @throws {WorkspaceError} If write fails, path is invalid, or permission denied
6320
+ * @throws {Error} If path is invalid, file too large, or write fails
6313
6321
  *
6314
6322
  * @example
6315
6323
  * ```typescript
6316
- * await workspaceManager.writeToSession(
6317
- * 'session-123',
6318
- * 'backend',
6319
- * 'api/users.ts',
6320
- * 'export interface User { ... }',
6321
- * backendProfile // Verify caller is actually 'backend'
6322
- * );
6324
+ * await workspaceManager.writePRD('feature-auth.md', '# Authentication Feature...');
6323
6325
  * ```
6324
6326
  */
6325
- async writeToSession(sessionId, agentName, filePath, content, callerAgent) {
6326
- if (callerAgent && callerAgent.name !== agentName) {
6327
- throw new WorkspaceError(
6328
- `Agent '${callerAgent.name}' is not authorized to write to '${agentName}' workspace`,
6329
- void 0,
6330
- "permission_denied"
6331
- );
6332
- }
6333
- const agentOutputDir = this.getAgentOutputDir(sessionId, agentName);
6334
- const fullPath = await this.validatePath(agentOutputDir, filePath);
6335
- const fileSize = Buffer.byteLength(content, "utf-8");
6336
- if (fileSize > this.maxFileSize) {
6337
- throw new WorkspaceError(
6338
- `File too large: ${fileSize} bytes (max: ${this.maxFileSize} bytes)`,
6339
- fullPath,
6340
- "quota_exceeded"
6341
- );
6342
- }
6343
- try {
6344
- await fs.mkdir(path2.dirname(fullPath), { recursive: true });
6345
- await fs.writeFile(fullPath, content, "utf-8");
6346
- logger.debug("File written to session workspace", {
6347
- sessionId,
6348
- agentName,
6349
- filePath,
6350
- size: content.length
6351
- });
6352
- } catch (error) {
6353
- throw new WorkspaceError(
6354
- `Failed to write file: ${error.message}`,
6355
- fullPath,
6356
- "permission_denied"
6357
- );
6358
- }
6327
+ async writePRD(fileName, content) {
6328
+ await this.ensureDirectories();
6329
+ this.validateFileSize(content);
6330
+ const fullPath = this.validatePath(this.prdDir, fileName);
6331
+ await fs.mkdir(path2.dirname(fullPath), { recursive: true });
6332
+ await fs.writeFile(fullPath, content, "utf-8");
6333
+ logger.info("PRD document created", { fileName, size: content.length });
6359
6334
  }
6360
6335
  /**
6361
- * Read file from another agent's workspace (within a session)
6336
+ * Write temporary file
6362
6337
  *
6363
- * Requires permission check: requestingAgent must have targetAgent
6364
- * in their canReadWorkspaces whitelist.
6338
+ * Temporary files should contain:
6339
+ * - Test scripts
6340
+ * - Analysis tools
6341
+ * - Temporary reports
6365
6342
  *
6366
- * @param requestingAgent - Agent profile requesting access
6367
- * @param targetAgent - Target agent whose workspace to read
6368
- * @param sessionId - Session ID
6369
- * @param filePath - Relative file path within target agent's output
6370
- * @returns File content
6371
- * @throws {WorkspaceError} If permission denied or file not found
6343
+ * These files can be cleaned up anytime.
6344
+ *
6345
+ * @param fileName - Relative file path within tmp/
6346
+ * @param content - File content
6347
+ * @throws {Error} If path is invalid, file too large, or write fails
6372
6348
  *
6373
6349
  * @example
6374
6350
  * ```typescript
6375
- * const spec = await workspaceManager.readFromAgentWorkspace(
6376
- * frontendProfile,
6377
- * 'backend',
6378
- * 'session-123',
6379
- * 'api-spec.md'
6380
- * );
6351
+ * await workspaceManager.writeTmp('test.sh', '#!/bin/bash\necho "test"');
6381
6352
  * ```
6382
6353
  */
6383
- async readFromAgentWorkspace(requestingAgent, targetAgent, sessionId, filePath) {
6384
- const canRead = requestingAgent.orchestration?.canReadWorkspaces;
6385
- if (!canRead || !canRead.includes(targetAgent)) {
6386
- throw new WorkspaceError(
6387
- `Agent '${requestingAgent.name}' is not authorized to read '${targetAgent}' workspace`,
6388
- void 0,
6389
- "permission_denied"
6390
- );
6391
- }
6392
- const agentOutputDir = this.getAgentOutputDir(sessionId, targetAgent);
6393
- const fullPath = await this.validatePath(agentOutputDir, filePath);
6394
- try {
6395
- const content = await fs.readFile(fullPath, "utf-8");
6396
- logger.debug("File read from agent workspace", {
6397
- requestingAgent: requestingAgent.name,
6398
- targetAgent,
6399
- sessionId,
6400
- filePath
6401
- });
6402
- return content;
6403
- } catch (error) {
6404
- const err = error;
6405
- if (err.code === "ENOENT") {
6406
- throw new WorkspaceError(
6407
- `File not found: ${filePath}`,
6408
- fullPath,
6409
- "not_found"
6410
- );
6411
- }
6412
- throw new WorkspaceError(
6413
- `Failed to read file: ${err.message}`,
6414
- fullPath,
6415
- "permission_denied"
6416
- );
6417
- }
6354
+ async writeTmp(fileName, content) {
6355
+ await this.ensureDirectories();
6356
+ this.validateFileSize(content);
6357
+ const fullPath = this.validatePath(this.tmpDir, fileName);
6358
+ await fs.mkdir(path2.dirname(fullPath), { recursive: true });
6359
+ await fs.writeFile(fullPath, content, "utf-8");
6360
+ logger.debug("Temporary file created", { fileName, size: content.length });
6418
6361
  }
6419
6362
  /**
6420
- * Write to persistent shared workspace (cross-session)
6421
- *
6422
- * Requires permission check: agent must have canWriteToShared enabled.
6363
+ * Read PRD document
6423
6364
  *
6424
- * @param agent - Agent profile
6425
- * @param filePath - Relative file path
6426
- * @param content - File content
6427
- * @throws {WorkspaceError} If permission denied or write fails
6365
+ * @param fileName - Relative file path within PRD/
6366
+ * @returns File content
6367
+ * @throws {Error} If path is invalid or file not found
6428
6368
  *
6429
6369
  * @example
6430
6370
  * ```typescript
6431
- * await workspaceManager.writeToShared(
6432
- * agentProfile,
6433
- * 'templates/api-template.ts',
6434
- * 'export const template = ...'
6435
- * );
6371
+ * const content = await workspaceManager.readPRD('feature-auth.md');
6436
6372
  * ```
6437
6373
  */
6438
- async writeToShared(agent, filePath, content) {
6439
- if (!agent.orchestration?.canWriteToShared) {
6440
- throw new WorkspaceError(
6441
- `Agent '${agent.name}' is not authorized to write to shared workspace`,
6442
- void 0,
6443
- "permission_denied"
6444
- );
6445
- }
6446
- const fullPath = await this.validatePath(this.persistentRoot, filePath);
6447
- const fileSize = Buffer.byteLength(content, "utf-8");
6448
- if (fileSize > this.maxFileSize) {
6449
- throw new WorkspaceError(
6450
- `File too large: ${fileSize} bytes (max: ${this.maxFileSize} bytes)`,
6451
- fullPath,
6452
- "quota_exceeded"
6453
- );
6454
- }
6455
- try {
6456
- await fs.mkdir(path2.dirname(fullPath), { recursive: true });
6457
- await fs.writeFile(fullPath, content, "utf-8");
6458
- logger.info("File written to persistent shared workspace", {
6459
- agentName: agent.name,
6460
- filePath,
6461
- size: fileSize
6462
- });
6463
- } catch (error) {
6464
- throw new WorkspaceError(
6465
- `Failed to write to shared workspace: ${error.message}`,
6466
- fullPath,
6467
- "permission_denied"
6468
- );
6469
- }
6374
+ async readPRD(fileName) {
6375
+ const fullPath = this.validatePath(this.prdDir, fileName);
6376
+ return await fs.readFile(fullPath, "utf-8");
6470
6377
  }
6471
6378
  /**
6472
- * List files in session workspace for a specific agent
6379
+ * Read temporary file
6380
+ *
6381
+ * @param fileName - Relative file path within tmp/
6382
+ * @returns File content
6383
+ * @throws {Error} If path is invalid or file not found
6384
+ */
6385
+ async readTmp(fileName) {
6386
+ const fullPath = this.validatePath(this.tmpDir, fileName);
6387
+ return await fs.readFile(fullPath, "utf-8");
6388
+ }
6389
+ /**
6390
+ * List all PRD documents
6473
6391
  *
6474
- * @param sessionId - Session ID
6475
- * @param agentName - Agent name
6476
6392
  * @returns Array of relative file paths
6477
- * @throws {WorkspaceError} If listing fails
6478
6393
  *
6479
6394
  * @example
6480
6395
  * ```typescript
6481
- * const files = await workspaceManager.listSessionFiles('session-123', 'backend');
6482
- * console.log(files); // ['api-spec.md', 'models/user.ts']
6396
+ * const prdFiles = await workspaceManager.listPRD();
6397
+ * // ['feature-auth.md', 'workflow-ci-cd.md']
6483
6398
  * ```
6484
6399
  */
6485
- async listSessionFiles(sessionId, agentName) {
6486
- const agentOutputDir = this.getAgentOutputDir(sessionId, agentName);
6400
+ async listPRD() {
6487
6401
  try {
6488
- const files = [];
6489
- await this.collectFiles(agentOutputDir, agentOutputDir, files);
6490
- return files;
6402
+ await this.ensureDirectories();
6403
+ return await this.listFiles(this.prdDir);
6491
6404
  } catch (error) {
6492
6405
  const err = error;
6493
6406
  if (err.code === "ENOENT") {
6494
6407
  return [];
6495
6408
  }
6496
- throw new WorkspaceError(
6497
- `Failed to list files: ${err.message}`,
6498
- agentOutputDir,
6499
- "permission_denied"
6500
- );
6409
+ throw error;
6501
6410
  }
6502
6411
  }
6503
6412
  /**
6504
- * Recursively collect files from a directory
6413
+ * List all temporary files
6505
6414
  *
6506
- * @param dir - Directory to scan
6507
- * @param baseDir - Base directory for relative paths
6508
- * @param files - Array to collect file paths
6415
+ * @returns Array of relative file paths
6509
6416
  */
6510
- async collectFiles(dir, baseDir, files) {
6417
+ async listTmp() {
6511
6418
  try {
6512
- const entries = await fs.readdir(dir, { withFileTypes: true });
6513
- for (const entry of entries) {
6514
- const fullPath = path2.join(dir, entry.name);
6515
- try {
6516
- if (entry.isDirectory()) {
6517
- await this.collectFiles(fullPath, baseDir, files);
6518
- } else {
6519
- const relativePath = path2.relative(baseDir, fullPath);
6520
- files.push(relativePath);
6521
- }
6522
- } catch (err) {
6523
- const error = err;
6524
- if (error.code === "ENOENT") {
6525
- logger.debug("File removed during traversal", { path: fullPath });
6526
- continue;
6527
- }
6528
- throw err;
6529
- }
6530
- }
6531
- } catch (err) {
6532
- const error = err;
6533
- if (error.code === "ENOENT") {
6534
- logger.debug("Directory removed during traversal", { path: dir });
6535
- return;
6419
+ await this.ensureDirectories();
6420
+ return await this.listFiles(this.tmpDir);
6421
+ } catch (error) {
6422
+ const err = error;
6423
+ if (err.code === "ENOENT") {
6424
+ return [];
6536
6425
  }
6537
- throw err;
6426
+ throw error;
6538
6427
  }
6539
6428
  }
6540
6429
  /**
6541
- * Cleanup old session workspaces
6542
- *
6543
- * Removes session workspaces older than specified days.
6544
- * Should be called in sync with SessionManager cleanup.
6430
+ * Clean up temporary files (recursively)
6545
6431
  *
6546
- * @param sessionIds - Active session IDs to keep
6547
- * @returns Number of sessions cleaned up
6432
+ * @param olderThanDays - Optional: Only remove files older than N days
6433
+ * @returns Number of files removed
6548
6434
  *
6549
6435
  * @example
6550
6436
  * ```typescript
6551
- * const activeSessions = await sessionManager.getActiveSessions();
6552
- * const activeIds = activeSessions.map(s => s.id);
6553
- * const removed = await workspaceManager.cleanupSessions(activeIds);
6437
+ * // Remove all temporary files
6438
+ * await workspaceManager.cleanupTmp();
6439
+ *
6440
+ * // Remove files older than 7 days
6441
+ * await workspaceManager.cleanupTmp(7);
6554
6442
  * ```
6555
6443
  */
6556
- async cleanupSessions(sessionIds) {
6444
+ async cleanupTmp(olderThanDays) {
6557
6445
  try {
6558
- const sessionDirs = await fs.readdir(this.sessionsRoot);
6559
- const activeSet = new Set(sessionIds);
6560
- let removed = 0;
6561
- for (const sessionId of sessionDirs) {
6562
- if (!activeSet.has(sessionId)) {
6563
- try {
6564
- const sessionDir = this.getSessionDir(sessionId);
6565
- await fs.rm(sessionDir, { recursive: true, force: true });
6566
- removed++;
6567
- logger.debug("Session workspace removed", { sessionId });
6568
- } catch (err) {
6569
- if (err instanceof WorkspaceError && err.reason === "invalid_session_id") {
6570
- logger.warn("Skipping invalid session directory", { sessionId });
6571
- continue;
6572
- }
6573
- throw err;
6574
- }
6575
- }
6576
- }
6577
- if (removed > 0) {
6578
- logger.info("Session workspaces cleaned up", { removed });
6579
- }
6580
- return removed;
6446
+ await this.ensureDirectories();
6447
+ return await this.cleanupDirectory(this.tmpDir, olderThanDays);
6581
6448
  } catch (error) {
6582
- logger.warn("Failed to cleanup session workspaces", {
6583
- error: error.message
6449
+ const err = error;
6450
+ if (err.code === "ENOENT") {
6451
+ return 0;
6452
+ }
6453
+ logger.warn("Failed to cleanup temporary files", {
6454
+ error: err.message
6584
6455
  });
6585
6456
  return 0;
6586
6457
  }
6587
6458
  }
6588
6459
  /**
6589
- * Cleanup specific session workspaces by session IDs
6460
+ * Helper: Clean up directory recursively
6590
6461
  *
6591
- * Removes workspace directories for the specified session IDs.
6592
- * Useful when coordinating with SessionManager cleanup.
6593
- *
6594
- * @param sessionIds - Session IDs to remove
6595
- * @returns Number of workspaces removed
6596
- *
6597
- * @example
6598
- * ```typescript
6599
- * const result = await sessionManager.cleanupOldSessions(7);
6600
- * await workspaceManager.cleanupSessionWorkspaces(result.removedSessionIds);
6601
- * ```
6462
+ * @param dir - Directory to clean
6463
+ * @param olderThanDays - Optional: Only remove files older than N days
6464
+ * @returns Number of files removed
6602
6465
  */
6603
- async cleanupSessionWorkspaces(sessionIds) {
6466
+ async cleanupDirectory(dir, olderThanDays) {
6604
6467
  let removed = 0;
6605
- for (const sessionId of sessionIds) {
6606
- try {
6607
- const sessionDir = this.getSessionDir(sessionId);
6608
- await fs.rm(sessionDir, { recursive: true, force: true });
6609
- removed++;
6610
- logger.debug("Session workspace removed", { sessionId });
6611
- } catch (error) {
6612
- const err = error;
6613
- if (err.code !== "ENOENT") {
6614
- logger.warn("Failed to remove session workspace", {
6615
- sessionId,
6616
- error: err.message
6468
+ try {
6469
+ const entries = await fs.readdir(dir, { withFileTypes: true });
6470
+ for (const entry of entries) {
6471
+ const filePath = path2.join(dir, entry.name);
6472
+ if (entry.isDirectory()) {
6473
+ removed += await this.cleanupDirectory(filePath, olderThanDays);
6474
+ continue;
6475
+ }
6476
+ if (olderThanDays !== void 0) {
6477
+ try {
6478
+ const stats = await fs.stat(filePath);
6479
+ const ageInDays = (Date.now() - stats.mtimeMs) / (1e3 * 60 * 60 * 24);
6480
+ if (ageInDays < olderThanDays) {
6481
+ continue;
6482
+ }
6483
+ } catch (statError) {
6484
+ continue;
6485
+ }
6486
+ }
6487
+ try {
6488
+ await fs.unlink(filePath);
6489
+ removed++;
6490
+ } catch (rmError) {
6491
+ logger.warn("Failed to remove temporary file", {
6492
+ path: path2.relative(this.tmpDir, filePath),
6493
+ error: rmError.message
6617
6494
  });
6618
6495
  }
6619
6496
  }
6620
- }
6621
- if (removed > 0) {
6622
- logger.info("Session workspaces cleaned up", {
6623
- removed,
6624
- total: sessionIds.length
6625
- });
6497
+ if (removed > 0) {
6498
+ logger.info("Temporary files cleaned up", { removed, olderThanDays });
6499
+ }
6500
+ } catch (error) {
6501
+ const err = error;
6502
+ if (err.code === "ENOENT") {
6503
+ return removed;
6504
+ }
6505
+ throw error;
6626
6506
  }
6627
6507
  return removed;
6628
6508
  }
@@ -6634,70 +6514,95 @@ var WorkspaceManager = class _WorkspaceManager {
6634
6514
  * @example
6635
6515
  * ```typescript
6636
6516
  * const stats = await workspaceManager.getStats();
6637
- * console.log(`${stats.totalSessions} session workspaces`);
6517
+ * console.log(`PRD files: ${stats.prdFiles}, Tmp files: ${stats.tmpFiles}`);
6638
6518
  * ```
6639
6519
  */
6640
6520
  async getStats() {
6641
6521
  try {
6642
- const sessionDirs = await fs.readdir(this.sessionsRoot);
6643
- const agentDirs = await fs.readdir(this.workspacesRoot);
6644
- const agentWorkspaces = agentDirs.filter(
6645
- (name) => name !== "shared"
6646
- ).length;
6647
- const stats = {
6648
- totalSessions: sessionDirs.length,
6649
- totalSizeBytes: 0,
6650
- agentWorkspaces
6522
+ await this.ensureDirectories();
6523
+ const prdFiles = await this.listFiles(this.prdDir);
6524
+ const tmpFiles = await this.listFiles(this.tmpDir);
6525
+ let prdSize = 0;
6526
+ for (const file of prdFiles) {
6527
+ try {
6528
+ const stats = await fs.stat(path2.join(this.prdDir, file));
6529
+ prdSize += stats.size;
6530
+ } catch {
6531
+ }
6532
+ }
6533
+ let tmpSize = 0;
6534
+ for (const file of tmpFiles) {
6535
+ try {
6536
+ const stats = await fs.stat(path2.join(this.tmpDir, file));
6537
+ tmpSize += stats.size;
6538
+ } catch {
6539
+ }
6540
+ }
6541
+ return {
6542
+ prdFiles: prdFiles.length,
6543
+ tmpFiles: tmpFiles.length,
6544
+ totalSizeBytes: prdSize + tmpSize,
6545
+ prdSizeBytes: prdSize,
6546
+ tmpSizeBytes: tmpSize
6651
6547
  };
6652
- return stats;
6653
6548
  } catch (error) {
6654
6549
  logger.warn("Failed to get workspace stats", {
6655
6550
  error: error.message
6656
6551
  });
6657
6552
  return {
6658
- totalSessions: 0,
6553
+ prdFiles: 0,
6554
+ tmpFiles: 0,
6659
6555
  totalSizeBytes: 0,
6660
- agentWorkspaces: 0
6556
+ prdSizeBytes: 0,
6557
+ tmpSizeBytes: 0
6661
6558
  };
6662
6559
  }
6663
6560
  }
6664
6561
  /**
6665
- * Create agent's private workspace
6562
+ * Helper: List files recursively in a directory
6666
6563
  *
6667
- * @param agentName - Agent name
6668
- *
6669
- * @example
6670
- * ```typescript
6671
- * await workspaceManager.createAgentWorkspace('backend');
6672
- * ```
6564
+ * @param dir - Directory to scan
6565
+ * @returns Array of relative file paths
6673
6566
  */
6674
- async createAgentWorkspace(agentName) {
6675
- const agentDir = this.getAgentWorkspaceDir(agentName);
6676
- const draftsDir = path2.join(agentDir, "drafts");
6677
- const tempDir = path2.join(agentDir, "temp");
6567
+ async listFiles(dir) {
6568
+ const files = [];
6678
6569
  try {
6679
- await fs.mkdir(agentDir, { recursive: true });
6680
- await fs.mkdir(draftsDir, { recursive: true });
6681
- await fs.mkdir(tempDir, { recursive: true });
6682
- logger.debug("Agent workspace created", {
6683
- agentName,
6684
- path: agentDir
6685
- });
6686
- } catch (error) {
6687
- throw new WorkspaceError(
6688
- `Failed to create agent workspace: ${error.message}`,
6689
- agentDir,
6690
- "creation_failed"
6691
- );
6570
+ const entries = await fs.readdir(dir, { withFileTypes: true });
6571
+ for (const entry of entries) {
6572
+ const fullPath = path2.join(dir, entry.name);
6573
+ const relativePath = path2.relative(dir, fullPath);
6574
+ try {
6575
+ if (entry.isDirectory()) {
6576
+ const subFiles = await this.listFiles(fullPath);
6577
+ files.push(...subFiles.map((f) => path2.join(relativePath, f)));
6578
+ } else {
6579
+ files.push(relativePath);
6580
+ }
6581
+ } catch (err) {
6582
+ const error = err;
6583
+ if (error.code === "ENOENT") {
6584
+ logger.debug("File removed during traversal", { path: relativePath });
6585
+ continue;
6586
+ }
6587
+ throw err;
6588
+ }
6589
+ }
6590
+ } catch (err) {
6591
+ const error = err;
6592
+ if (error.code === "ENOENT") {
6593
+ logger.debug("Directory removed during traversal", { path: dir });
6594
+ return files;
6595
+ }
6596
+ throw err;
6692
6597
  }
6598
+ return files;
6693
6599
  }
6694
6600
  };
6695
6601
 
6696
6602
  // src/agents/context-manager.ts
6697
6603
  init_esm_shims();
6698
6604
  init_logger();
6699
- import { mkdir as mkdir4, chmod } from "fs/promises";
6700
- import { join as join4, resolve as resolve5 } from "path";
6605
+ import { join as join4 } from "path";
6701
6606
  var PROVIDER_ALIASES = {
6702
6607
  "claude": "claude-code",
6703
6608
  "gemini": "gemini-cli",
@@ -6734,16 +6639,7 @@ var ContextManager = class {
6734
6639
  const workingDir = process.cwd();
6735
6640
  const agentDirName = agent.name.replace(/[^a-zA-Z0-9-]/g, "-").toLowerCase();
6736
6641
  const agentWorkspace = join4(projectDir, ".automatosx", "workspaces", agentDirName);
6737
- const resolvedWorkspace = resolve5(agentWorkspace);
6738
- const resolvedProject = resolve5(projectDir);
6739
- if (!resolvedWorkspace.startsWith(resolvedProject)) {
6740
- throw PathError.traversal(agentWorkspace);
6741
- }
6742
- await mkdir4(agentWorkspace, { recursive: true });
6743
- if (process.platform !== "win32") {
6744
- await chmod(agentWorkspace, 448);
6745
- }
6746
- logger.debug("Agent workspace created", { workspace: agentWorkspace });
6642
+ logger.debug("Agent workspace path defined (not created)", { workspace: agentWorkspace });
6747
6643
  let session;
6748
6644
  if (options?.sessionId) {
6749
6645
  if (!this.config.sessionManager) {
@@ -6763,7 +6659,7 @@ var ContextManager = class {
6763
6659
  if (this.config.workspaceManager && this.config.profileLoader) {
6764
6660
  const allAgents = await this.config.profileLoader.listProfiles();
6765
6661
  const availableAgents = allAgents.filter((a) => a !== agent.name);
6766
- const sharedWorkspace = session ? join4(projectDir, ".automatosx", "workspaces", "shared", "sessions", session.id) : join4(projectDir, ".automatosx", "workspaces", "shared", "persistent");
6662
+ const sharedWorkspace = join4(projectDir, "automatosx", "PRD");
6767
6663
  const maxDelegationDepth = agent.orchestration?.maxDelegationDepth ?? 2;
6768
6664
  orchestration = {
6769
6665
  isDelegationEnabled: true,
@@ -7016,19 +6912,20 @@ var ContextManager = class {
7016
6912
  return provider;
7017
6913
  }
7018
6914
  /**
7019
- * Cleanup context (delete workspace if needed)
6915
+ * Cleanup context
6916
+ *
6917
+ * v5.2: No cleanup needed - agent workspaces no longer created
7020
6918
  */
7021
6919
  async cleanup(context) {
7022
- logger.debug("Context cleanup", {
7023
- agent: context.agent.name,
7024
- workspace: context.agentWorkspace
6920
+ logger.debug("Context cleanup (no-op in v5.2)", {
6921
+ agent: context.agent.name
7025
6922
  });
7026
6923
  }
7027
6924
  };
7028
6925
 
7029
6926
  // src/agents/profile-loader.ts
7030
6927
  init_esm_shims();
7031
- import { readFile as readFile3, readdir as readdir2 } from "fs/promises";
6928
+ import { readFile as readFile3, readdir as readdir3 } from "fs/promises";
7032
6929
  import { join as join5, extname as extname2, basename, dirname as dirname6 } from "path";
7033
6930
  import { fileURLToPath as fileURLToPath3 } from "url";
7034
6931
  import { load as load2 } from "js-yaml";
@@ -7150,7 +7047,7 @@ var ProfileLoader = class {
7150
7047
  */
7151
7048
  async listProfilesFromDir(dir) {
7152
7049
  try {
7153
- const files = await readdir2(dir);
7050
+ const files = await readdir3(dir);
7154
7051
  return files.filter((file) => extname2(file) === ".yaml" || extname2(file) === ".yml").map((file) => basename(file, extname2(file)));
7155
7052
  } catch (error) {
7156
7053
  if (error.code === "ENOENT") {
@@ -7244,7 +7141,7 @@ var ProfileLoader = class {
7244
7141
  async listProfiles() {
7245
7142
  const profileSet = /* @__PURE__ */ new Set();
7246
7143
  try {
7247
- const files = await readdir2(this.profilesDir);
7144
+ const files = await readdir3(this.profilesDir);
7248
7145
  const profiles = files.filter((file) => extname2(file) === ".yaml" || extname2(file) === ".yml").map((file) => basename(file, extname2(file)));
7249
7146
  profiles.forEach((p) => profileSet.add(p));
7250
7147
  } catch (error) {
@@ -7253,7 +7150,7 @@ var ProfileLoader = class {
7253
7150
  }
7254
7151
  }
7255
7152
  try {
7256
- const files = await readdir2(this.fallbackProfilesDir);
7153
+ const files = await readdir3(this.fallbackProfilesDir);
7257
7154
  const profiles = files.filter((file) => extname2(file) === ".yaml" || extname2(file) === ".yml").map((file) => basename(file, extname2(file)));
7258
7155
  profiles.forEach((p) => profileSet.add(p));
7259
7156
  } catch (error) {
@@ -7493,19 +7390,6 @@ var ProfileLoader = class {
7493
7390
  throw new AgentValidationError("orchestration.maxDelegationDepth must be a non-negative integer (0 = no delegation allowed)");
7494
7391
  }
7495
7392
  }
7496
- if (orch.canReadWorkspaces !== void 0) {
7497
- if (!Array.isArray(orch.canReadWorkspaces)) {
7498
- throw new AgentValidationError("orchestration.canReadWorkspaces must be an array");
7499
- }
7500
- orch.canReadWorkspaces.forEach((workspace, i) => {
7501
- if (typeof workspace !== "string") {
7502
- throw new AgentValidationError(`orchestration.canReadWorkspaces[${i}] must be a string`);
7503
- }
7504
- });
7505
- }
7506
- if (orch.canWriteToShared !== void 0 && typeof orch.canWriteToShared !== "boolean") {
7507
- throw new AgentValidationError("orchestration.canWriteToShared must be a boolean");
7508
- }
7509
7393
  }
7510
7394
  return true;
7511
7395
  }
@@ -7628,7 +7512,7 @@ var ProfileLoader = class {
7628
7512
  init_esm_shims();
7629
7513
  init_logger();
7630
7514
  init_cache();
7631
- import { readFile as readFile4, readdir as readdir3 } from "fs/promises";
7515
+ import { readFile as readFile4, readdir as readdir4 } from "fs/promises";
7632
7516
  import { join as join6, extname as extname3, basename as basename2, dirname as dirname7 } from "path";
7633
7517
  import { fileURLToPath as fileURLToPath4 } from "url";
7634
7518
  var __filename4 = fileURLToPath4(import.meta.url);
@@ -7729,7 +7613,7 @@ ${content}`);
7729
7613
  */
7730
7614
  async listAbilities() {
7731
7615
  try {
7732
- const files = await readdir3(this.abilitiesDir);
7616
+ const files = await readdir4(this.abilitiesDir);
7733
7617
  const abilities = files.filter((file) => extname3(file) === ".md").map((file) => basename2(file, extname3(file)));
7734
7618
  return abilities.sort();
7735
7619
  } catch (error) {
@@ -7749,7 +7633,7 @@ ${content}`);
7749
7633
 
7750
7634
  // src/core/team-manager.ts
7751
7635
  init_esm_shims();
7752
- import { readFile as readFile5, readdir as readdir4 } from "fs/promises";
7636
+ import { readFile as readFile5, readdir as readdir5 } from "fs/promises";
7753
7637
  import { join as join7, extname as extname4, basename as basename3 } from "path";
7754
7638
  import { load as load3 } from "js-yaml";
7755
7639
 
@@ -7817,7 +7701,7 @@ var TeamManager = class {
7817
7701
  async getAllTeams() {
7818
7702
  logger.debug("Loading all teams");
7819
7703
  try {
7820
- const files = await readdir4(this.teamsDir);
7704
+ const files = await readdir5(this.teamsDir);
7821
7705
  const teamFiles = files.filter((f) => extname4(f) === ".yaml" || extname4(f) === ".yml");
7822
7706
  const teams = [];
7823
7707
  for (const file of teamFiles) {
@@ -7844,7 +7728,7 @@ var TeamManager = class {
7844
7728
  */
7845
7729
  async listTeams() {
7846
7730
  try {
7847
- const files = await readdir4(this.teamsDir);
7731
+ const files = await readdir5(this.teamsDir);
7848
7732
  return files.filter((f) => extname4(f) === ".yaml" || extname4(f) === ".yml").map((f) => basename3(f, extname4(f)));
7849
7733
  } catch (error) {
7850
7734
  if (error.code === "ENOENT") {
@@ -7919,9 +7803,6 @@ var TeamManager = class {
7919
7803
  if (team.sharedAbilities && !Array.isArray(team.sharedAbilities)) {
7920
7804
  throw new TeamValidationError("sharedAbilities must be an array");
7921
7805
  }
7922
- if (team.orchestration?.canReadWorkspaces && !Array.isArray(team.orchestration.canReadWorkspaces)) {
7923
- throw new TeamValidationError("orchestration.canReadWorkspaces must be an array");
7924
- }
7925
7806
  logger.debug("Team validation passed", { name: team.name });
7926
7807
  }
7927
7808
  };
@@ -8646,7 +8527,7 @@ ${context.task}`;
8646
8527
  * Sleep for specified milliseconds
8647
8528
  */
8648
8529
  sleep(ms) {
8649
- return new Promise((resolve10) => setTimeout(resolve10, ms));
8530
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
8650
8531
  }
8651
8532
  /**
8652
8533
  * Delegate a task to another agent
@@ -8738,7 +8619,6 @@ ${context.task}`;
8738
8619
  session = await this.sessionManager.createSession(request.task, request.fromAgent);
8739
8620
  sessionId = session.id;
8740
8621
  await this.sessionManager.addAgent(sessionId, request.toAgent);
8741
- await this.workspaceManager.createSessionWorkspace(sessionId);
8742
8622
  }
8743
8623
  } else {
8744
8624
  logger.debug("Text-only delegation mode (no SessionManager/WorkspaceManager)", {
@@ -8761,13 +8641,7 @@ ${context.task}`;
8761
8641
  verbose: false,
8762
8642
  showProgress: true
8763
8643
  });
8764
- let files = [];
8765
- if (this.workspaceManager && sessionId) {
8766
- files = await this.workspaceManager.listSessionFiles(
8767
- sessionId,
8768
- request.toAgent
8769
- );
8770
- }
8644
+ const files = [];
8771
8645
  const memoryIds = [];
8772
8646
  const endTime = /* @__PURE__ */ new Date();
8773
8647
  const duration = endTime.getTime() - startTime.getTime();
@@ -8828,7 +8702,7 @@ init_logger();
8828
8702
 
8829
8703
  // src/mcp/utils/validation.ts
8830
8704
  init_esm_shims();
8831
- import { resolve as resolve6, isAbsolute as isAbsolute2, sep as sep2 } from "path";
8705
+ import { resolve as resolve5, isAbsolute as isAbsolute2, sep as sep2 } from "path";
8832
8706
  var ValidationError = class extends Error {
8833
8707
  constructor(message, code = -32602 /* InvalidParams */, details) {
8834
8708
  super(message);
@@ -8888,8 +8762,8 @@ function validatePathParameter(path3, paramName, projectRoot = process.cwd()) {
8888
8762
  );
8889
8763
  }
8890
8764
  try {
8891
- const resolvedPath = resolve6(projectRoot, path3);
8892
- const normalizedRoot = resolve6(projectRoot);
8765
+ const resolvedPath = resolve5(projectRoot, path3);
8766
+ const normalizedRoot = resolve5(projectRoot);
8893
8767
  if (!resolvedPath.startsWith(normalizedRoot + sep2) && resolvedPath !== normalizedRoot) {
8894
8768
  throw new ValidationError(
8895
8769
  `Invalid ${paramName}: path escapes project boundary`,
@@ -9423,12 +9297,12 @@ function createMemoryDeleteHandler(deps) {
9423
9297
  // src/mcp/tools/memory-export.ts
9424
9298
  init_esm_shims();
9425
9299
  init_logger();
9426
- import { resolve as resolve7, basename as basename4 } from "path";
9300
+ import { resolve as resolve6, basename as basename4 } from "path";
9427
9301
  function resolveExportPath(pathResolver, userPath) {
9428
9302
  const exportsDir = pathResolver.resolveProjectPath(".automatosx/memory/exports");
9429
9303
  validatePathParameter(userPath, "export path", exportsDir);
9430
9304
  const filename = basename4(userPath);
9431
- const absolutePath = resolve7(exportsDir, filename);
9305
+ const absolutePath = resolve6(exportsDir, filename);
9432
9306
  if (!pathResolver.validatePath(absolutePath, exportsDir)) {
9433
9307
  throw new Error("Export path must be within .automatosx/memory/exports directory");
9434
9308
  }
@@ -9461,12 +9335,12 @@ function createMemoryExportHandler(deps) {
9461
9335
  // src/mcp/tools/memory-import.ts
9462
9336
  init_esm_shims();
9463
9337
  init_logger();
9464
- import { resolve as resolve8, basename as basename5 } from "path";
9338
+ import { resolve as resolve7, basename as basename5 } from "path";
9465
9339
  function resolveImportPath(pathResolver, userPath) {
9466
9340
  const exportsDir = pathResolver.resolveProjectPath(".automatosx/memory/exports");
9467
9341
  validatePathParameter(userPath, "import path", exportsDir);
9468
9342
  const filename = basename5(userPath);
9469
- const absolutePath = resolve8(exportsDir, filename);
9343
+ const absolutePath = resolve7(exportsDir, filename);
9470
9344
  if (!pathResolver.validatePath(absolutePath, exportsDir)) {
9471
9345
  throw new Error("Import path must be within .automatosx/memory/exports directory");
9472
9346
  }
@@ -9663,7 +9537,6 @@ var McpServer = class {
9663
9537
  });
9664
9538
  await this.sessionManager.initialize();
9665
9539
  this.workspaceManager = new WorkspaceManager(projectDir);
9666
- await this.workspaceManager.initialize();
9667
9540
  this.contextManager = new ContextManager({
9668
9541
  profileLoader: this.profileLoader,
9669
9542
  abilitiesManager,
@@ -10372,7 +10245,7 @@ var mcpCommand = {
10372
10245
 
10373
10246
  // src/cli/commands/memory.ts
10374
10247
  init_esm_shims();
10375
- import { resolve as resolve9 } from "path";
10248
+ import { resolve as resolve8 } from "path";
10376
10249
  import chalk8 from "chalk";
10377
10250
  import Table from "cli-table3";
10378
10251
 
@@ -10493,7 +10366,7 @@ var DEFAULT_DB_PATH = ".automatosx/memory/memory.db";
10493
10366
  async function getMemoryManager(dbPath) {
10494
10367
  const path3 = dbPath || DEFAULT_DB_PATH;
10495
10368
  return await MemoryManager.create({
10496
- dbPath: resolve9(path3),
10369
+ dbPath: resolve8(path3),
10497
10370
  maxEntries: 1e5,
10498
10371
  autoCleanup: false,
10499
10372
  trackAccess: true
@@ -10810,8 +10683,8 @@ var deleteCommand = {
10810
10683
  input: process.stdin,
10811
10684
  output: process.stdout
10812
10685
  });
10813
- const answer = await new Promise((resolve10) => {
10814
- rl.question(chalk8.yellow("\nAre you sure you want to delete this entry? (y/N): "), resolve10);
10686
+ const answer = await new Promise((resolve9) => {
10687
+ rl.question(chalk8.yellow("\nAre you sure you want to delete this entry? (y/N): "), resolve9);
10815
10688
  });
10816
10689
  rl.close();
10817
10690
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
@@ -11885,7 +11758,7 @@ init_logger();
11885
11758
  import chalk12 from "chalk";
11886
11759
  import { join as join9 } from "path";
11887
11760
  import { writeFileSync } from "fs";
11888
- import { mkdir as mkdir5 } from "fs/promises";
11761
+ import { mkdir as mkdir4 } from "fs/promises";
11889
11762
 
11890
11763
  // src/utils/output-formatter.ts
11891
11764
  init_esm_shims();
@@ -12146,7 +12019,6 @@ var runCommand = {
12146
12019
  });
12147
12020
  await sessionManager.initialize();
12148
12021
  workspaceManager = new WorkspaceManager(projectDir);
12149
- await workspaceManager.initialize();
12150
12022
  if (argv2.session) {
12151
12023
  const session = await sessionManager.getSession(argv2.session);
12152
12024
  if (!session) {
@@ -12292,7 +12164,7 @@ var runCommand = {
12292
12164
  try {
12293
12165
  const savePath = argv2.save;
12294
12166
  const saveDir = join9(savePath, "..");
12295
- await mkdir5(saveDir, { recursive: true });
12167
+ await mkdir4(saveDir, { recursive: true });
12296
12168
  let outputData;
12297
12169
  if (argv2.format === "json") {
12298
12170
  outputData = JSON.stringify({
@@ -12390,7 +12262,7 @@ Result: ${multiStageResult.finalOutput}`;
12390
12262
  try {
12391
12263
  const savePath = argv2.save;
12392
12264
  const saveDir = join9(savePath, "..");
12393
- await mkdir5(saveDir, { recursive: true });
12265
+ await mkdir4(saveDir, { recursive: true });
12394
12266
  const outputData = formatForSave(result, argv2.format || "text", {
12395
12267
  agent: resolvedAgentName,
12396
12268
  task: argv2.task
@@ -12437,7 +12309,7 @@ Response: ${result.response.content}`;
12437
12309
  if (router) {
12438
12310
  router.destroy();
12439
12311
  }
12440
- await new Promise((resolve10) => setImmediate(resolve10));
12312
+ await new Promise((resolve9) => setImmediate(resolve9));
12441
12313
  console.log(chalk12.green.bold("\u2705 Complete\n"));
12442
12314
  process.exit(0);
12443
12315
  } catch (error) {
@@ -12464,7 +12336,7 @@ Response: ${result.response.content}`;
12464
12336
  logger.debug("Context cleanup error", { error: errMsg });
12465
12337
  });
12466
12338
  }
12467
- await new Promise((resolve10) => setImmediate(resolve10));
12339
+ await new Promise((resolve9) => setImmediate(resolve9));
12468
12340
  } catch (cleanupError) {
12469
12341
  const errMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
12470
12342
  logger.debug("Cleanup error ignored", { error: errMsg });
@@ -12717,8 +12589,8 @@ init_gemini_provider();
12717
12589
  init_openai_provider();
12718
12590
  init_logger();
12719
12591
  import chalk14 from "chalk";
12720
- import { existsSync as existsSync4 } from "fs";
12721
- import { readdir as readdir5, stat } from "fs/promises";
12592
+ import { existsSync as existsSync5 } from "fs";
12593
+ import { readdir as readdir6, stat as stat2 } from "fs/promises";
12722
12594
  import { join as join11 } from "path";
12723
12595
  import { createRequire as createRequire3 } from "module";
12724
12596
  import os from "os";
@@ -12833,17 +12705,17 @@ var statusCommand2 = {
12833
12705
  project: projectInfo,
12834
12706
  configuration: {
12835
12707
  configFile: join11(detectedProjectDir, "automatosx.config.json"),
12836
- configExists: existsSync4(join11(detectedProjectDir, "automatosx.config.json")),
12708
+ configExists: existsSync5(join11(detectedProjectDir, "automatosx.config.json")),
12837
12709
  logLevel: config.logging.level,
12838
12710
  memoryMaxEntries: config.memory.maxEntries,
12839
12711
  memoryRetentionDays: config.memory.cleanupDays
12840
12712
  },
12841
12713
  directories: {
12842
- automatosx: { path: automatosxDir, exists: existsSync4(automatosxDir) },
12843
- agents: { path: agentsDir, exists: existsSync4(agentsDir), count: agentCount },
12844
- abilities: { path: abilitiesDir, exists: existsSync4(abilitiesDir), count: abilityCount },
12845
- memory: { path: memoryDir, exists: existsSync4(memoryDir), ...memoryStats },
12846
- workspaces: { path: workspacesDir, exists: existsSync4(workspacesDir), ...workspaceStats }
12714
+ automatosx: { path: automatosxDir, exists: existsSync5(automatosxDir) },
12715
+ agents: { path: agentsDir, exists: existsSync5(agentsDir), count: agentCount },
12716
+ abilities: { path: abilitiesDir, exists: existsSync5(abilitiesDir), count: abilityCount },
12717
+ memory: { path: memoryDir, exists: existsSync5(memoryDir), ...memoryStats },
12718
+ workspaces: { path: workspacesDir, exists: existsSync5(workspacesDir), ...workspaceStats }
12847
12719
  },
12848
12720
  providers: providerHealth,
12849
12721
  router: {
@@ -12966,11 +12838,11 @@ var statusCommand2 = {
12966
12838
  }
12967
12839
  };
12968
12840
  async function getWorkspaceStatistics(workspacesDir) {
12969
- if (!existsSync4(workspacesDir)) {
12841
+ if (!existsSync5(workspacesDir)) {
12970
12842
  return { workspaces: 0, totalSizeBytes: 0, files: 0 };
12971
12843
  }
12972
12844
  try {
12973
- const entries = await readdir5(workspacesDir, { withFileTypes: true });
12845
+ const entries = await readdir6(workspacesDir, { withFileTypes: true });
12974
12846
  const workspaces = entries.filter((e) => e.isDirectory());
12975
12847
  let totalSizeBytes = 0;
12976
12848
  let files = 0;
@@ -12991,7 +12863,7 @@ async function getWorkspaceStatistics(workspacesDir) {
12991
12863
  }
12992
12864
  }
12993
12865
  async function getMemoryStatistics(memoryDir) {
12994
- if (!existsSync4(memoryDir)) {
12866
+ if (!existsSync5(memoryDir)) {
12995
12867
  return { files: 0, sizeBytes: 0 };
12996
12868
  }
12997
12869
  try {
@@ -13009,7 +12881,7 @@ async function getDirectoryStats(dirPath) {
13009
12881
  let totalSize = 0;
13010
12882
  let totalFiles = 0;
13011
12883
  try {
13012
- const entries = await readdir5(dirPath, { withFileTypes: true });
12884
+ const entries = await readdir6(dirPath, { withFileTypes: true });
13013
12885
  for (const entry of entries) {
13014
12886
  const fullPath = join11(dirPath, entry.name);
13015
12887
  if (entry.isDirectory()) {
@@ -13017,7 +12889,7 @@ async function getDirectoryStats(dirPath) {
13017
12889
  totalSize += subStats.size;
13018
12890
  totalFiles += subStats.files;
13019
12891
  } else if (entry.isFile()) {
13020
- const stats = await stat(fullPath);
12892
+ const stats = await stat2(fullPath);
13021
12893
  totalSize += stats.size;
13022
12894
  totalFiles++;
13023
12895
  }
@@ -13027,11 +12899,11 @@ async function getDirectoryStats(dirPath) {
13027
12899
  return { size: totalSize, files: totalFiles };
13028
12900
  }
13029
12901
  async function countFiles(dirPath, extensions) {
13030
- if (!existsSync4(dirPath)) {
12902
+ if (!existsSync5(dirPath)) {
13031
12903
  return 0;
13032
12904
  }
13033
12905
  try {
13034
- const files = await readdir5(dirPath);
12906
+ const files = await readdir6(dirPath);
13035
12907
  return files.filter((f) => extensions.some((ext) => f.endsWith(ext))).length;
13036
12908
  } catch (error) {
13037
12909
  logger.warn("Failed to count files", { dirPath, error: error.message });
@@ -13040,7 +12912,7 @@ async function countFiles(dirPath, extensions) {
13040
12912
  }
13041
12913
  async function getProjectInfo(projectDir) {
13042
12914
  const packageJsonPath = join11(projectDir, "package.json");
13043
- if (!existsSync4(packageJsonPath)) {
12915
+ if (!existsSync5(packageJsonPath)) {
13044
12916
  return {};
13045
12917
  }
13046
12918
  try {
@@ -13126,8 +12998,8 @@ var updateCommand = {
13126
12998
  input: process.stdin,
13127
12999
  output: process.stdout
13128
13000
  });
13129
- const answer = await new Promise((resolve10) => {
13130
- rl.question(chalk15.yellow("Would you like to update now? (y/N) "), resolve10);
13001
+ const answer = await new Promise((resolve9) => {
13002
+ rl.question(chalk15.yellow("Would you like to update now? (y/N) "), resolve9);
13131
13003
  });
13132
13004
  rl.close();
13133
13005
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
@@ -13230,11 +13102,13 @@ init_esm_shims();
13230
13102
  import chalk16 from "chalk";
13231
13103
  var listCommand4 = {
13232
13104
  command: "list",
13233
- describe: "List workspace files",
13105
+ describe: "List workspace files (PRD or tmp)",
13234
13106
  builder: (yargs2) => {
13235
- return yargs2.option("session", {
13236
- describe: "Session ID to list files for",
13237
- type: "string"
13107
+ return yargs2.option("type", {
13108
+ describe: "Workspace type to list",
13109
+ type: "string",
13110
+ choices: ["prd", "tmp"],
13111
+ default: "prd"
13238
13112
  }).option("json", {
13239
13113
  describe: "Output as JSON",
13240
13114
  type: "boolean",
@@ -13246,42 +13120,23 @@ var listCommand4 = {
13246
13120
  const { detectProjectRoot: detectProjectRoot2 } = await Promise.resolve().then(() => (init_path_resolver(), path_resolver_exports));
13247
13121
  const projectDir = await detectProjectRoot2(process.cwd());
13248
13122
  const workspaceManager = new WorkspaceManager(projectDir);
13249
- if (argv2.session) {
13250
- const sessionManager = await createSessionManager();
13251
- const session = await sessionManager.getSession(argv2.session);
13252
- if (!session) {
13253
- console.log(chalk16.red.bold(`
13254
- \u2717 Session not found: ${argv2.session}
13255
- `));
13256
- process.exit(1);
13257
- }
13258
- console.log(chalk16.blue.bold(`
13259
- \u{1F4C1} Session Workspace Files
13260
- `));
13261
- console.log(chalk16.gray(`Session: ${argv2.session}`));
13262
- console.log(chalk16.gray(`Task: ${session.task}
13123
+ const files = argv2.type === "tmp" ? await workspaceManager.listTmp() : await workspaceManager.listPRD();
13124
+ if (argv2.json) {
13125
+ console.log(JSON.stringify({ type: argv2.type, files }, null, 2));
13126
+ process.exit(0);
13127
+ }
13128
+ console.log(chalk16.blue.bold(`
13129
+ \u{1F4C1} ${argv2.type === "tmp" ? "Temporary" : "PRD"} Files
13263
13130
  `));
13264
- for (const agentName of session.agents) {
13265
- const files = await workspaceManager.listSessionFiles(argv2.session, agentName);
13266
- if (files.length > 0) {
13267
- console.log(chalk16.cyan(`
13268
- ${agentName}:`));
13269
- files.forEach((file) => {
13270
- console.log(chalk16.gray(` - ${file}`));
13271
- });
13272
- }
13273
- }
13274
- console.log();
13131
+ if (files.length === 0) {
13132
+ console.log(chalk16.gray(" (No files)\n"));
13275
13133
  } else {
13276
- const stats = await workspaceManager.getStats();
13277
- if (argv2.json) {
13278
- console.log(JSON.stringify(stats, null, 2));
13279
- process.exit(0);
13280
- }
13281
- console.log(chalk16.blue.bold("\n\u{1F4CA} Workspace Statistics\n"));
13282
- console.log(chalk16.gray(`Session workspaces: ${chalk16.white(stats.totalSessions)}`));
13283
- console.log(chalk16.gray(`Agent workspaces: ${chalk16.white(stats.agentWorkspaces)}`));
13284
- console.log();
13134
+ files.forEach((file) => {
13135
+ console.log(chalk16.gray(` - ${file}`));
13136
+ });
13137
+ console.log(chalk16.gray(`
13138
+ Total: ${files.length} file(s)
13139
+ `));
13285
13140
  }
13286
13141
  process.exit(0);
13287
13142
  } catch (error) {
@@ -13312,9 +13167,9 @@ var statsCommand2 = {
13312
13167
  process.exit(0);
13313
13168
  }
13314
13169
  console.log(chalk16.blue.bold("\n\u{1F4CA} Workspace Statistics\n"));
13315
- console.log(chalk16.gray(`Session workspaces: ${chalk16.white(stats.totalSessions)}`));
13316
- console.log(chalk16.gray(`Agent workspaces: ${chalk16.white(stats.agentWorkspaces)}`));
13317
- console.log(chalk16.gray(`Total size: ${chalk16.white((stats.totalSizeBytes / 1024 / 1024).toFixed(2))} MB`));
13170
+ console.log(chalk16.gray(`PRD files: ${chalk16.white(stats.prdFiles)}`));
13171
+ console.log(chalk16.gray(`Temporary files: ${chalk16.white(stats.tmpFiles)}`));
13172
+ console.log(chalk16.gray(`Total size: ${chalk16.white((stats.totalSizeBytes / 1024 / 1024).toFixed(2))} MB`));
13318
13173
  console.log();
13319
13174
  process.exit(0);
13320
13175
  } catch (error) {
@@ -13326,10 +13181,10 @@ var statsCommand2 = {
13326
13181
  };
13327
13182
  var cleanupCommand = {
13328
13183
  command: "cleanup",
13329
- describe: "Clean up old session workspaces",
13184
+ describe: "Clean up temporary files",
13330
13185
  builder: (yargs2) => {
13331
13186
  return yargs2.option("older-than", {
13332
- describe: "Clean up sessions older than N days",
13187
+ describe: "Clean up files older than N days",
13333
13188
  type: "number",
13334
13189
  default: 7
13335
13190
  }).option("confirm", {
@@ -13343,22 +13198,17 @@ var cleanupCommand = {
13343
13198
  const { detectProjectRoot: detectProjectRoot2 } = await Promise.resolve().then(() => (init_path_resolver(), path_resolver_exports));
13344
13199
  const projectDir = await detectProjectRoot2(process.cwd());
13345
13200
  const workspaceManager = new WorkspaceManager(projectDir);
13346
- const sessionManager = await createSessionManager();
13347
- const activeSessions = await sessionManager.getActiveSessions();
13348
- const activeIds = activeSessions.map((s) => s.id);
13349
13201
  if (!argv2.confirm) {
13350
13202
  console.log(chalk16.yellow(`
13351
- \u26A0 This will remove workspace files for inactive sessions`));
13352
- console.log(chalk16.gray(`Active sessions (${activeIds.length}) will be kept
13353
- `));
13203
+ \u26A0 This will remove temporary files older than ${argv2.olderThan} days`));
13354
13204
  console.log(chalk16.gray("Run with --confirm to proceed\n"));
13355
13205
  process.exit(0);
13356
13206
  }
13357
- const removed = await workspaceManager.cleanupSessions(activeIds);
13207
+ const removed = await workspaceManager.cleanupTmp(argv2.olderThan);
13358
13208
  console.log(chalk16.green.bold(`
13359
13209
  \u2713 Cleanup complete
13360
13210
  `));
13361
- console.log(chalk16.gray(`Removed ${removed} session workspace(s)
13211
+ console.log(chalk16.gray(`Removed ${removed} temporary file(s)
13362
13212
  `));
13363
13213
  process.exit(0);
13364
13214
  } catch (error) {
@@ -13383,9 +13233,9 @@ init_esm_shims();
13383
13233
 
13384
13234
  // src/cli/commands/agent/templates.ts
13385
13235
  init_esm_shims();
13386
- import { readdir as readdir6 } from "fs/promises";
13236
+ import { readdir as readdir7 } from "fs/promises";
13387
13237
  import { join as join12 } from "path";
13388
- import { existsSync as existsSync5 } from "fs";
13238
+ import { existsSync as existsSync6 } from "fs";
13389
13239
  import chalk17 from "chalk";
13390
13240
  var TEMPLATE_DESCRIPTIONS = {
13391
13241
  "basic-agent": {
@@ -13421,9 +13271,9 @@ var templatesCommand = {
13421
13271
  try {
13422
13272
  console.log(chalk17.blue.bold("\n\u{1F4CB} Available Agent Templates\n"));
13423
13273
  const projectTemplatesDir = join12(process.cwd(), ".automatosx", "templates");
13424
- const hasProjectTemplates = existsSync5(projectTemplatesDir);
13274
+ const hasProjectTemplates = existsSync6(projectTemplatesDir);
13425
13275
  const defaultTemplatesDir = join12(__dirname, "../../../../examples/templates");
13426
- const hasDefaultTemplates = existsSync5(defaultTemplatesDir);
13276
+ const hasDefaultTemplates = existsSync6(defaultTemplatesDir);
13427
13277
  if (!hasProjectTemplates && !hasDefaultTemplates) {
13428
13278
  console.log(chalk17.yellow("\u26A0 No templates found."));
13429
13279
  console.log(chalk17.gray('\nRun "ax init" to set up default templates.\n'));
@@ -13431,7 +13281,7 @@ var templatesCommand = {
13431
13281
  }
13432
13282
  const templatesDir = hasProjectTemplates ? projectTemplatesDir : defaultTemplatesDir;
13433
13283
  const templateSource = hasProjectTemplates ? "Project" : "Default";
13434
- const files = await readdir6(templatesDir);
13284
+ const files = await readdir7(templatesDir);
13435
13285
  const templates = files.filter((f) => f.endsWith(".yaml")).map((f) => f.replace(".yaml", ""));
13436
13286
  if (templates.length === 0) {
13437
13287
  console.log(chalk17.yellow("\u26A0 No templates found.\n"));
@@ -13480,8 +13330,8 @@ var templatesCommand = {
13480
13330
 
13481
13331
  // src/cli/commands/agent/create.ts
13482
13332
  init_esm_shims();
13483
- import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir6 } from "fs/promises";
13484
- import { existsSync as existsSync7 } from "fs";
13333
+ import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
13334
+ import { existsSync as existsSync8 } from "fs";
13485
13335
  import { join as join14 } from "path";
13486
13336
  import { load as loadYaml2 } from "js-yaml";
13487
13337
  import chalk18 from "chalk";
@@ -13621,8 +13471,8 @@ var templateEngine = new TemplateEngine();
13621
13471
 
13622
13472
  // src/cli/commands/agent/helpers.ts
13623
13473
  init_esm_shims();
13624
- import { readdir as readdir7 } from "fs/promises";
13625
- import { existsSync as existsSync6 } from "fs";
13474
+ import { readdir as readdir8 } from "fs/promises";
13475
+ import { existsSync as existsSync7 } from "fs";
13626
13476
  import { join as join13, extname as extname5, dirname as dirname8 } from "path";
13627
13477
  import { fileURLToPath as fileURLToPath5 } from "url";
13628
13478
  init_logger();
@@ -13631,9 +13481,9 @@ var __dirname5 = dirname8(__filename5);
13631
13481
  async function listAvailableTemplates() {
13632
13482
  const templates = [];
13633
13483
  const projectTemplatesDir = join13(process.cwd(), ".automatosx", "templates");
13634
- if (existsSync6(projectTemplatesDir)) {
13484
+ if (existsSync7(projectTemplatesDir)) {
13635
13485
  try {
13636
- const files = await readdir7(projectTemplatesDir);
13486
+ const files = await readdir8(projectTemplatesDir);
13637
13487
  for (const file of files) {
13638
13488
  if (extname5(file) === ".yaml" || extname5(file) === ".yml") {
13639
13489
  const name = file.replace(/\.(yaml|yml)$/, "");
@@ -13649,9 +13499,9 @@ async function listAvailableTemplates() {
13649
13499
  }
13650
13500
  }
13651
13501
  const builtinTemplatesDir = join13(__dirname5, "../../../../examples/templates");
13652
- if (existsSync6(builtinTemplatesDir)) {
13502
+ if (existsSync7(builtinTemplatesDir)) {
13653
13503
  try {
13654
- const files = await readdir7(builtinTemplatesDir);
13504
+ const files = await readdir8(builtinTemplatesDir);
13655
13505
  for (const file of files) {
13656
13506
  if (extname5(file) === ".yaml" || extname5(file) === ".yml") {
13657
13507
  const name = file.replace(/\.(yaml|yml)$/, "");
@@ -13844,14 +13694,14 @@ var createCommand2 = {
13844
13694
  console.log(chalk18.gray(" \u2022 Not contain consecutive hyphens\n"));
13845
13695
  process.exit(1);
13846
13696
  }
13847
- if (existsSync7(agentFile)) {
13697
+ if (existsSync8(agentFile)) {
13848
13698
  console.log(chalk18.red.bold(`
13849
13699
  \u2717 Agent already exists: ${argv2.agent}
13850
13700
  `));
13851
13701
  console.log(chalk18.gray("Use a different name or remove the existing agent first.\n"));
13852
13702
  process.exit(1);
13853
13703
  }
13854
- await mkdir6(agentsDir, { recursive: true });
13704
+ await mkdir5(agentsDir, { recursive: true });
13855
13705
  let templateName = argv2.template;
13856
13706
  if (!templateName) {
13857
13707
  if (argv2.interactive) {
@@ -13939,11 +13789,11 @@ var createCommand2 = {
13939
13789
  };
13940
13790
  async function findTemplate(name) {
13941
13791
  const projectTemplate = join14(process.cwd(), ".automatosx", "templates", `${name}.yaml`);
13942
- if (existsSync7(projectTemplate)) {
13792
+ if (existsSync8(projectTemplate)) {
13943
13793
  return projectTemplate;
13944
13794
  }
13945
13795
  const defaultTemplate = join14(__dirname, "../../../../examples/templates", `${name}.yaml`);
13946
- if (existsSync7(defaultTemplate)) {
13796
+ if (existsSync8(defaultTemplate)) {
13947
13797
  return defaultTemplate;
13948
13798
  }
13949
13799
  throw new Error(`Template not found: ${name}
@@ -13997,10 +13847,10 @@ function ask(question, defaultValue) {
13997
13847
  output: process.stdout
13998
13848
  });
13999
13849
  const prompt = defaultValue ? `${question} [${chalk18.gray(defaultValue)}]: ` : `${question}: `;
14000
- return new Promise((resolve10) => {
13850
+ return new Promise((resolve9) => {
14001
13851
  rl.question(prompt, (answer) => {
14002
13852
  rl.close();
14003
- resolve10(answer.trim() || defaultValue || "");
13853
+ resolve9(answer.trim() || defaultValue || "");
14004
13854
  });
14005
13855
  });
14006
13856
  }
@@ -14158,12 +14008,6 @@ var showCommand = {
14158
14008
  if (orch.maxDelegationDepth !== void 0) {
14159
14009
  console.log(chalk20.white(` Max Delegation Depth: ${orch.maxDelegationDepth}`));
14160
14010
  }
14161
- if (orch.canReadWorkspaces && orch.canReadWorkspaces.length > 0) {
14162
- console.log(chalk20.white(` Can Read Workspaces: ${orch.canReadWorkspaces.join(", ")}`));
14163
- }
14164
- if (orch.canWriteToShared !== void 0) {
14165
- console.log(chalk20.white(` Can Write to Shared: ${orch.canWriteToShared ? "Yes" : "No"}`));
14166
- }
14167
14011
  console.log();
14168
14012
  }
14169
14013
  const filePath = join16(agentsDir, `${argv2.agent}.yaml`);
@@ -14204,7 +14048,7 @@ var showCommand = {
14204
14048
  // src/cli/commands/agent/remove.ts
14205
14049
  init_esm_shims();
14206
14050
  import { unlink as unlink2 } from "fs/promises";
14207
- import { existsSync as existsSync8 } from "fs";
14051
+ import { existsSync as existsSync9 } from "fs";
14208
14052
  import { join as join17 } from "path";
14209
14053
  import chalk21 from "chalk";
14210
14054
  import * as readline2 from "readline";
@@ -14257,7 +14101,7 @@ var removeCommand = {
14257
14101
  process.exit(1);
14258
14102
  }
14259
14103
  const agentFile = join17(agentsDir, `${resolvedName}.yaml`);
14260
- if (!existsSync8(agentFile)) {
14104
+ if (!existsSync9(agentFile)) {
14261
14105
  console.log(chalk21.red.bold(`
14262
14106
  \u2717 Agent file not found: ${resolvedName}
14263
14107
  `));
@@ -14293,11 +14137,11 @@ function askConfirmation(question) {
14293
14137
  input: process.stdin,
14294
14138
  output: process.stdout
14295
14139
  });
14296
- return new Promise((resolve10) => {
14140
+ return new Promise((resolve9) => {
14297
14141
  rl.question(chalk21.yellow(`
14298
14142
  ${question} (y/N): `), (answer) => {
14299
14143
  rl.close();
14300
- resolve10(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
14144
+ resolve9(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
14301
14145
  });
14302
14146
  });
14303
14147
  }