agent-mp 0.5.0 → 0.5.2

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.
@@ -7,7 +7,7 @@ import chalk from 'chalk';
7
7
  import { execSync } from 'child_process';
8
8
  import { CLI_REGISTRY } from '../types.js';
9
9
  import { writeJson, ensureDir, readJson, listDir, fileExists } from '../utils/fs.js';
10
- import { loadAuth, saveAuth, loadCliConfig, saveCliConfig, loadProjectConfig } from '../utils/config.js';
10
+ import { loadAuth, saveAuth, loadCliConfig, saveCliConfig, loadProjectConfig, resolveProjectDir } from '../utils/config.js';
11
11
  import { log } from '../utils/logger.js';
12
12
  import { AgentEngine, ExitError } from '../core/engine.js';
13
13
  import { qwenLogin, qwenAuthStatus, QWEN_AGENT_HOME, fetchQwenModels } from '../utils/qwen-auth.js';
@@ -594,7 +594,7 @@ async function cmdStatus(fi) {
594
594
  roleRows.push({ key: 'global fallback', value: `${cliConfig.fallback_global.cli}/${cliConfig.fallback_global.model}` });
595
595
  }
596
596
  sections.push({ title: 'Roles — full cmd', rows: roleRows });
597
- const dir = process.cwd();
597
+ const dir = await resolveProjectDir(process.cwd());
598
598
  try {
599
599
  const config = await loadProjectConfig(dir);
600
600
  const projectRows = [
@@ -711,7 +711,7 @@ function cmdHelp(fi) {
711
711
  fi.println(renderSectionBox('Commands', commands));
712
712
  }
713
713
  async function cmdTasks(fi) {
714
- const dir = process.cwd();
714
+ const dir = await resolveProjectDir(process.cwd());
715
715
  const tasksDir = path.join(dir, '.agent', 'tasks');
716
716
  const tasks = await listDir(tasksDir);
717
717
  if (tasks.length === 0) {
@@ -858,13 +858,15 @@ export async function runRepl(resumeSession) {
858
858
  const { activeCli } = init;
859
859
  const rl = init.rl;
860
860
  const session = resumeSession ?? newSession(process.cwd());
861
+ // Resolve actual project root (may be deeper than cwd)
862
+ const projectDir = await resolveProjectDir(process.cwd());
861
863
  // Show project status and FORCE role configuration if missing
862
864
  let hasRoles = false;
863
865
  let welcomeRoles;
864
- let welcomeProject = path.basename(process.cwd());
866
+ let welcomeProject = path.basename(projectDir);
865
867
  let welcomeStack = 'generic';
866
868
  try {
867
- const config = await loadProjectConfig(process.cwd());
869
+ const config = await loadProjectConfig(projectDir);
868
870
  welcomeProject = config.project;
869
871
  welcomeStack = config.stack;
870
872
  if (config.roles?.orchestrator?.cli && config.roles?.implementor?.cli && config.roles?.reviewer?.cli) {
@@ -915,8 +917,7 @@ export async function runRepl(resumeSession) {
915
917
  process.stdout.write(renderHelpHint() + '\n\n');
916
918
  // Print coordinator header BEFORE fi.setup() so no blank lines appear between them
917
919
  try {
918
- const dir = process.cwd();
919
- const config = await loadProjectConfig(dir);
920
+ const config = await loadProjectConfig(projectDir);
920
921
  if (config.roles?.orchestrator?.cli) {
921
922
  process.stdout.write('\n');
922
923
  process.stdout.write(chalk.bold.cyan('═'.repeat(46)) + '\n');
@@ -990,7 +991,7 @@ export async function runRepl(resumeSession) {
990
991
  await cmdStatus(fi);
991
992
  break;
992
993
  case 'run': {
993
- const dir = process.cwd();
994
+ const dir = await resolveProjectDir(process.cwd());
994
995
  const config = await loadProjectConfig(dir);
995
996
  if (args[0] === 'orch' || args[0] === 'orchestrator') {
996
997
  const task = args.slice(1).join(' ');
@@ -1027,7 +1028,7 @@ export async function runRepl(resumeSession) {
1027
1028
  }
1028
1029
  case 'explorer':
1029
1030
  case 'exp': {
1030
- const dir = process.cwd();
1031
+ const dir = await resolveProjectDir(process.cwd());
1031
1032
  const config = await loadProjectConfig(dir);
1032
1033
  const task = args.join(' ');
1033
1034
  const engine = new AgentEngine(config, dir, gCoordinatorCmd, rl, fi, handleCmd);
@@ -1099,7 +1100,7 @@ export async function runRepl(resumeSession) {
1099
1100
  session.messages.push({ role: 'user', content: trimmed, ts: new Date().toISOString() });
1100
1101
  await saveSession(session);
1101
1102
  try {
1102
- const dir = process.cwd();
1103
+ const dir = await resolveProjectDir(process.cwd());
1103
1104
  const config = await loadProjectConfig(dir);
1104
1105
  if (!config.roles?.orchestrator?.cli) {
1105
1106
  fi.println(chalk.red(' No roles configured. Run /config-multi first.'));
@@ -1141,7 +1142,8 @@ export async function runRole(role, arg, model) {
1141
1142
  // In that case, skip REPL and run headless — no coordinator needed
1142
1143
  const ROLE_BINS = new Set(['agent-orch', 'agent-impl', 'agent-rev', 'agent-explorer']);
1143
1144
  const isNativeBin = ROLE_BINS.has(PKG_NAME);
1144
- const dir = process.cwd();
1145
+ // Resolve the actual project root (may be deeper than cwd)
1146
+ const dir = await resolveProjectDir(process.cwd());
1145
1147
  let config;
1146
1148
  try {
1147
1149
  config = await loadProjectConfig(dir);
@@ -1,4 +1,12 @@
1
1
  import { AgentConfig } from '../types.js';
2
+ /**
3
+ * Resolve the actual project root starting from a given directory.
4
+ * If .agent/config.json exists in the start dir, use it directly
5
+ * (the user already configured this as the project root).
6
+ * If not, walk up the directory tree looking for .agent/config.json.
7
+ * Returns the resolved project root.
8
+ */
9
+ export declare function resolveProjectDir(startDir: string): Promise<string>;
2
10
  export declare const PKG_NAME: string;
3
11
  export declare const AGENT_HOME: string;
4
12
  export declare const AUTH_FILE: string;
@@ -3,6 +3,39 @@ import * as fsSync from 'fs';
3
3
  import * as path from 'path';
4
4
  import * as os from 'os';
5
5
  const KNOWN_PKGS = ['agent-mp', 'agent-orch', 'agent-impl', 'agent-rev', 'agent-explorer'];
6
+ /**
7
+ * Resolve the actual project root starting from a given directory.
8
+ * If .agent/config.json exists in the start dir, use it directly
9
+ * (the user already configured this as the project root).
10
+ * If not, walk up the directory tree looking for .agent/config.json.
11
+ * Returns the resolved project root.
12
+ */
13
+ export async function resolveProjectDir(startDir) {
14
+ // If .agent/config.json exists in current dir, use it — user already configured this
15
+ if (await fileExists(path.join(startDir, '.agent', 'config.json'))) {
16
+ return startDir;
17
+ }
18
+ // Walk up the directory tree looking for .agent/config.json
19
+ let current = startDir;
20
+ while (current !== path.dirname(current)) {
21
+ const parent = path.dirname(current);
22
+ if (await fileExists(path.join(parent, '.agent', 'config.json'))) {
23
+ return parent;
24
+ }
25
+ current = parent;
26
+ }
27
+ // No .agent/config.json found — return original dir (will fail gracefully)
28
+ return startDir;
29
+ }
30
+ async function fileExists(p) {
31
+ try {
32
+ await fs.stat(p);
33
+ return true;
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
6
39
  function resolvePackageName() {
7
40
  // 1. Read package.json (reliable for both global installs and dev mode)
8
41
  const __filename = new URL(import.meta.url).pathname;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-mp",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Deterministic multi-agent CLI orchestrator — plan, code, review",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",