Commit Graph

355 Commits

Author SHA1 Message Date
adil 4c31685584 fix(cli): prompt user for repo when remote is not auto-detected
Instead of silently omitting the repo field when no GitHub remote is
found, interactively ask the user to enter their owner/repo. This way
users on GitLab or other hosts can provide the correct value during
first-run setup rather than having to manually edit the yaml afterward.

If the user skips the prompt, the config is still valid (repo remains
optional) with a clear warning about what features are unavailable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:13:03 +05:30
adil 2cf9128101 refactor: clean up redundant requireRepo calls and nullish coalescing
- Use ?? instead of || for ownerRepo fallback (semantically correct for
  null-to-undefined conversion)
- Extract requireRepo() result into a local variable in tracker-gitlab's
  updateIssue and issueUrl to avoid redundant validation calls

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:13:02 +05:30
adil 17ea240f68 fix(cli): stop writing broken yaml when `ao start` runs in a new folder
- Make `repo` field optional in ProjectConfig and Zod schema so projects
  without a detected GitHub remote can still load and run
- Remove placeholder `repo: "owner/repo"` from autoCreateConfig() and
  addProjectToConfig() — omit the field entirely when no remote is found
- Always use actual workingDir for `path` instead of unreliable `~/<projectId>`
  fallback for non-git directories
- Add null guards for `project.repo` across SCM plugins, tracker plugins,
  lifecycle manager, webhooks, and prompt builders to prevent crashes when
  repo is not configured

Closes #1154

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:13:01 +05:30
adil e666c88098 fix(cli): address review — verify dashboard process before kill, restore exit on SIGINT
1. Port scan now uses killDashboardOnPort() which checks `ps -p <pid> -o args=`
   for next-server/start-all.js before killing, avoiding collateral damage to
   unrelated services on nearby ports.

2. SIGINT/SIGTERM handlers now call process.exit() after killing the child,
   restoring default exit behavior so Ctrl+C doesn't leave the parent hung
   if the child is unresponsive.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:12:58 +05:30
adil 4958512d9e test(cli): add coverage for port scan fallback and c8 ignore for signal handlers
Adds test for stopDashboard finding an orphaned dashboard on a reassigned
port via the port-range scan fallback. Marks signal handler body with
c8 ignore since it only fires on process termination.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:12:57 +05:30
adil e620a182c9 fix(cli): kill dashboard child on SIGINT and scan ports in stopDashboard (#645)
Two bugs caused `ao stop` to fail when the dashboard port was auto-reassigned:

1. Ctrl+C did not propagate to the dashboard child process because Node.js
   doesn't guarantee signal forwarding. Added SIGINT/SIGTERM/exit handlers
   in runStartup() to explicitly kill the dashboard child.

2. stopDashboard() only checked the configured port, missing orphaned
   dashboards on reassigned ports. Refactored into killOnPort() helper
   and added a port-range scan fallback (up to MAX_PORT_SCAN ports).

Closes #645

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 22:12:56 +05:30
adil 24a29194eb fix(cli): fix flaky multi-project test by setting non-interactive caller
The "errors when multiple projects and no arg" test expects the error
path (not the prompt path) in resolveProject. Set mockIsHumanCaller
to false so the test reliably hits the non-interactive error branch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 17:42:47 +05:30
adil f5818c8b88 test(cli): add tests for already-running detection and path-based dedup
Cover the moved isAlreadyRunning() check (non-TTY exit, quit, open,
restart, new orchestrator) and the path-based dedup guard in
addProjectToConfig(). Uses hoisted mocks for isAlreadyRunning,
isHumanCaller, promptSelect, unregister, and waitForExit to ensure
proper test isolation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 17:42:47 +05:30
adil cea7bfa51c fix(cli): prevent duplicate YAML entry when `ao start` detects already-running instance
Move the `isAlreadyRunning()` check before any config-mutating operations
so that running `ao start` on an already-running project no longer writes
a phantom duplicate entry to agent-orchestrator.yaml. The "new orchestrator"
choice is deferred via a flag until after config is loaded.

Also add path-based deduplication in `addProjectToConfig()` so that a
project whose resolved path already exists in config is returned as-is
instead of being appended with a numeric suffix.

Closes #1150

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 17:42:47 +05:30
Dhruv Sharma ad10dbf7aa
Merge pull request #1119 from harshitsinghbhandari/feat/1072
feat(power): prevent macOS idle sleep while AO is running
2026-04-14 17:26:58 +05:30
Harsh Batheja 95fbecc379
refactor(cli): remove lifecycle-worker subprocess, poll in-process (#1186)
* refactor(cli): remove lifecycle-worker subprocess model, run polling in-process

Replaces the per-project `ao lifecycle-worker` subprocess with an in-process
polling loop managed inside `lifecycle-service`. All registered projects are
now polled from the single long-lived `ao start` process.

- Drops the `lifecycle-worker` command and its registration.
- Rewrites `lifecycle-service` around a `Map<projectId, ActiveLoop>`,
  with SIGINT/SIGTERM/beforeExit graceful shutdown.
- Removes PID-file coordination (PID file, log file, status, etc.) —
  these only existed to track subprocess state.
- Per-project error isolation is preserved: the core lifecycle manager's
  `pollAll()` already catches per-cycle errors, and stop failures in one
  project can't prevent others from stopping.
- Updates `start`/`spawn` callers and tests to drop the PID/logFile shape.
- Adds `lifecycle-service.test.ts` covering idempotency, unknown projects,
  error isolation across projects, and graceful stop-all.

Closes #1185

* fix(cli): address bugbot review on lifecycle-service in-process refactor

- `ao spawn` / `ao batch-spawn` no longer call `ensureLifecycleWorker`.
  That call used to start `setInterval` polling in the one-shot spawn
  process, which (a) kept the CLI alive forever after the session spawned
  and (b) duplicated polling already running in `ao start`. Replaced with
  a `warnIfAONotRunning()` helper that checks `running.json` and prints a
  hint if the orchestrator isn't up.
- `ao stop` no longer calls `stopLifecycleWorker`. That call always ran
  against a fresh in-memory map (stop is a separate process from start),
  so it always returned false and printed "Lifecycle worker not running"
  misleadingly. SIGTERM to the `ao start` PID already triggers the shared
  shutdown handler in `lifecycle-service`, which stops every loop.
- Drop duplicated shutdown closure inside `registerSignalsOnce` — signal
  handlers now reference `stopAllLifecycleWorkers` directly.
- Update tests accordingly: spawn.test.ts mocks `running-state.getRunning`,
  start.test.ts drops `stopLifecycleWorker` expectations.

* fix(cli): drop SIGINT/SIGTERM listeners from lifecycle-service

Installing listeners for those signals removes Node.js's default
"exit on signal" behavior (per Node docs: "its default behavior will
be removed — Node.js will no longer exit"). Since the registered
listener doesn't call process.exit(), the `ao start` process would
hang on SIGTERM with the setInterval timer keeping the event loop
alive forever — effectively breaking `ao stop`.

Default signal handling terminates the process cleanly; the OS
reclaims the interval timer and dashboard child. `stopAllLifecycleWorkers`
stays exported for callers that want explicit cleanup before exit.

* fix(cli): project-scoped spawn warning + flush lifecycle health on exit

Addresses reviewer feedback on PR #1186:

- `warnIfAONotRunning` now takes a projectId and warns not only when no
  AO is running, but also when the running instance isn't polling the
  target project (e.g. `ao start A` then `ao spawn` in B left users
  silent about the fact that B wasn't being polled).
- `running.json` now records only the project this `ao start` actually
  polls, not every project in config. Previously this list was a lie —
  `ensureLifecycleWorker` is called for the selected project only.
- `ao start` installs SIGINT/SIGTERM handlers that call
  `stopAllLifecycleWorkers()` (flushing per-project "stopped" health
  state) and then `process.exit()`. Installing the handler safely
  requires an explicit exit because SIGINT/SIGTERM listeners remove
  Node's default exit behavior.

* fix(cli): remove dead stopLifecycleWorker, add missing test mock

Addresses bugbot comments on PR #1186:

- Delete `stopLifecycleWorker` from `lifecycle-service.ts`. It was only
  called from `ao stop` in the old subprocess model; in the in-process
  model, SIGTERM to the `ao start` pid + the shutdown handler in
  `start.ts` covers cleanup. No production caller remains.
- Add `stopAllLifecycleWorkers: vi.fn()` to `start.test.ts`'s
  `lifecycle-service.js` mock. Without it, `vi.mock` replaced the module
  and the named import resolved to undefined; the shutdown handler's
  try/catch would silently swallow the resulting TypeError, hiding any
  regression in how shutdown is wired.
- Update `lifecycle-service.test.ts` to drop references to the removed
  export (one test removed, one repurposed as a no-op smoke test for
  `stopAllLifecycleWorkers` against an empty active map).
2026-04-14 17:23:33 +05:30
yyovil 50ee804e2f test(cli): load markdown prompt templates 2026-04-13 21:28:27 +05:30
Dhruv Sharma ab1e4fb069
Merge pull request #1180 from yyovil/add/type-resolution
Add node type resolution for non-web packages
2026-04-13 19:56:36 +05:30
yyovil 9bed49d453 fix: scope node types to node packages 2026-04-13 18:25:21 +05:30
Ashish Huddar 07f01ef6a5
feat(cli): install-aware ao update, startup notifier, doctor version check (#1156)
* feat(cli): install-aware update command, startup notifier, and doctor version check

Make `ao update` detect whether AO was installed via npm or git source and
route accordingly: git installs use the existing shell script, npm installs
prompt to run `npm install -g @aoagents/ao@latest`, and unknown installs
print guidance. Add `--check` flag for JSON version info output.

Add a startup version notifier that reads a cached update check (no network
on startup) and prints a one-liner to stderr when outdated. Background
cache refresh runs after command completion via unref'd timer.

Add a version freshness check to `ao doctor` using cached data only (no
network dependency in diagnostics).

Closes #1136

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test(cli): high coverage for update service, command routing, and notifier

Add comprehensive tests per maintainer request for full coverage of all
update paths:

update-check.ts (57 tests):
- isVersionOutdated: major/minor/patch comparisons, equal, newer, missing parts
- detectInstallMethod: all 4 scenarios (git, npm-global, partial, unknown)
- readCachedUpdateInfo: fresh, expired, 23h boundary, version mismatch,
  invalid JSON, missing fields, empty file
- fetchLatestVersion: success, 404, 500, network error, timeout, non-JSON,
  missing version, non-string version, AbortSignal presence
- checkForUpdate: cache hit, cache bypass with force, stale cache fetch,
  cache write on success, no cache write on failure, version match,
  unreachable registry, result shape
- maybeShowUpdateNotice: positive print case, not outdated, no cache,
  non-TTY, AO_NO_UPDATE_NOTIFIER, CI, AGENT_ORCHESTRATOR_CI,
  each skipArg (update/doctor/--version/-V/--help/-h)
- scheduleBackgroundRefresh: does not throw

update.ts (17 tests):
- conflicting flags rejection
- --check: valid JSON output, forces fresh fetch, no side effects
- git: default args, --skip-smoke, --smoke-only, cache invalidation
- npm-global: no script-runner, already up-to-date, registry unreachable
  exits non-zero, --skip-smoke warning, forces fresh fetch
- unknown: help message, shows latest version, registry unreachable,
  suggests npm command

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): address all review feedback — coverage gaps, code fixes, Codex findings

Code fixes:
- Extract classifyInstallPath() for testable npm-global detection
- Convert IS_TTY from module-level constant to isTTY() function call
  (testable without import-time mocking)
- Fix non-TTY npm update silently exiting 0 → now exits 1 so scripts
  detect that no upgrade happened (Codex P2)
- Handle pre-release version tags in isVersionOutdated() — strips
  suffixes before comparing, handles NaN safely
- Export getCacheDir() and writeCache() for test coverage

Test coverage (69 + 24 + 9 + 3 = 105 tests):
- classifyInstallPath: npm-global (Unix + Windows paths), git, partial, unknown
- isVersionOutdated: pre-release tags, NaN handling, same-with-prerelease
- getCacheDir: XDG_CACHE_HOME override, fallback to ~/.cache
- writeCache: success, EACCES mkdir failure, ENOSPC write failure
- handleNpmUpdate full flow: confirm → spawn success, spawn failure with
  sudo suggestion, spawn error (ENOENT), non-TTY exit, flag warning,
  user decline, registry unreachable
- --check with unreachable registry still outputs valid JSON
- maybeShowUpdateNotice: happy path print, AGENT_ORCHESTRATOR_CI guard,
  each skipArg individually
- scheduleBackgroundRefresh: no-throw, swallows errors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): move background refresh earlier, distinguish local vs global node_modules

- Move scheduleBackgroundRefresh() before parseAsync() so the fetch runs
  in parallel with command execution. Short-lived commands now have a
  better chance of seeding the cache before exit. (Codex P2)
- Distinguish global npm installs (lib/node_modules, .pnpm store) from
  local project node_modules (npx, linked installs). Local installs now
  classify as "unknown" instead of "npm-global" to avoid suggesting
  npm install -g to npx users. (Codex P2)
- Add tests: pnpm global store path, nvm global path, npx local path

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(lint): remove forbidden import() type annotations in test mocks

Replace `vi.importActual<typeof import("node:fs")>(...)` with untyped
`vi.importActual(...)` to satisfy @typescript-eslint/consistent-type-imports.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): don't misclassify local pnpm installs as npm-global

Local pnpm projects have node_modules/.pnpm/ which matched the /.pnpm/
heuristic. Replace with /pnpm/global/ check which only matches pnpm's
actual global store path (~/.local/share/pnpm/global/...).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): non-TTY exits 0, remove misleading sudo suggestion

- Non-TTY ao update now exits 0 after printing the command. Exit 1
  implied error but the user just needs to run the command manually.
- Remove blanket sudo suggestion on npm failure. npm can exit 1 for
  many reasons (network, version conflict, engine mismatch). Just
  print the exit code and let the user diagnose.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): pnpm global support, defer background refresh after parseAsync

- Detect pnpm global installs separately from npm global. pnpm users
  now see `pnpm add -g @aoagents/ao@latest` instead of the npm command.
  New InstallMethod value: "pnpm-global".
- Move scheduleBackgroundRefresh() to .then() after parseAsync() completes.
  Prevents in-flight fetch from holding the event loop open during
  short-lived commands when the registry is slow/offline. (Codex P2)
- Use info.recommendedCommand instead of hardcoded npm string in
  handleNpmUpdate, so the correct package manager command is always used.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): use actual command name in error message, not hardcoded "npm"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(cli): handle signaled npm update exits

* fix(cli): detect prereleases behind stable releases

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:46:26 +05:30
i-trytoohard 36a64c98b7
chore: bump all package versions to 0.2.5 (#1190)
* chore: release 0.2.5

Realign main with npm registry after off-branch publish of 0.2.3/0.2.4.
Bump all 21 linked packages to 0.2.5 and cherry-pick the startup-grace-period
fix for #989 (was in 5e4244a8 but never merged to main).

Also sync non-linked plugin versions (notifier-discord, notifier-openclaw,
scm-gitlab, tracker-gitlab) to their current npm versions.

* Revert "chore: release 0.2.5"

This reverts commit eb17f32834.

* chore: bump all package versions to 0.2.5, remove release workflow

- Bump all 25 packages to 0.2.5 to realign with npm registry
- Update package-version test to expect 0.2.5
- Remove stale .changeset/linear-spawn-branch-name.md
- Delete .github/workflows/release.yml (changesets-based NPM publish)

---------

Co-authored-by: Prateek <karnalprateek@gmail.com>
Co-authored-by: AO Bot <ao-bot@composio.dev>
2026-04-13 05:47:08 +05:30
yyovil d73ec8edfd fix(cli): update stale ao-core imports (#1143) 2026-04-12 03:56:37 +05:30
yyovil c48b078a7b
Merge pull request #982 from yyovil/fix/cli-config-not-found-error-981
fix(cli): catch ConfigNotFoundError for clean error output
2026-04-12 00:42:15 +05:30
Dhruv Sharma 663c61e16d fix: merge main and address review findings for prompt-driven spawn
- Merge main to pick up @composio/ao-core → @aoagents/ao-core rename
  and decomposer removal (#1104)
- Fix @composio/ao-core import in prompt-spawn.test.ts → @aoagents/ao-core
- Remove unreachable dead code in CLI spawn (empty-string guard after || undefined)
- Update format.ts JSDoc to document 8-item fallback chain including userPrompt
- Add clarifying comment on validation/sanitization separation in spawn route
- Integrate userPrompt display into redesigned SessionCard footer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 21:44:57 +05:30
harshitsinghbhandari 8436505862 fix(power): address PR review feedback for sleep prevention
- Fix test flakiness: Use configurable property descriptor for process.platform
  mocking to prevent TypeError on property redefinition
- Fix spawn detection: Return null when caffeinate fails to spawn (child.pid
  undefined) instead of returning handle that does nothing
- Fix TypeScript: Make power config optional in OrchestratorConfig interface
  to avoid breaking existing consumers (populated post-validation)
- Add test for spawn failure case

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-11 21:06:32 +05:30
adil 0f4e2bcc3c feat(cli): hide orchestrator sessions from `ao session ls` by default (#1088)
Orchestrator sessions are control-plane sessions that clutter the ls
output alongside worker sessions. Filter them out using the existing
`isOrchestratorSessionName()` helper. Add `--all` / `-a` flag to
include them when needed.

Closes #1088

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 12:25:14 +05:30
Dhruv Sharma ba899f9c30
Merge pull request #1104 from ComposioHQ/feat/issue-1045
refactor: remove ao spawn --decompose feature
2026-04-11 10:22:22 +05:30
harshitsinghbhandari 5e1414e7ad feat(power): prevent macOS idle sleep while AO is running (#1072)
Add idle sleep prevention on macOS using `caffeinate -i -w <pid>` to keep
the Mac awake while AO is running, enabling remote dashboard access (e.g.,
via Tailscale) without the machine going to sleep.

Changes:
- Add `preventIdleSleep()` helper in packages/cli/src/lib/prevent-sleep.ts
- Add `power.preventIdleSleep` config option (defaults to true on macOS)
- Wire sleep prevention into `ao start` command
- Add tests for the helper function and config validation
- Document the feature in README and example config

Note: Lid-close sleep is enforced by macOS hardware and cannot be prevented
by userspace assertions. Use clamshell mode for that use case.

Closes #1072

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-11 00:11:45 +05:30
Dhruv Sharma b7464e5657 fix(spawn): persist userPrompt to metadata and prevent injection
writeMetadata() used a hard-coded field whitelist that silently dropped
userPrompt. The in-memory Session.metadata also never included it, so
the spawn response always returned null. Additionally, prompts containing
newlines could inject arbitrary key=value pairs into the flat-file
metadata format.

Fixes:
- Add userPrompt to writeMetadata() whitelist and readMetadata() return
- Populate session.metadata with userPrompt during spawn
- Strip newlines from prompts in both web API and CLI (defense-in-depth)
- Harden serializeMetadata() to replace newlines in all values
- Add prompt length validation (4096 max) in CLI to match web API

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 18:54:48 +05:30
Dhruv Sharma ff9bb76e63
Merge pull request #1076 from harshitsinghbhandari/feat/cursor-agent-support
feat: add Cursor agent CLI support (#1060)
2026-04-10 15:29:55 +05:30
Harsh Batheja 3fb2ddf06d refactor: remove --decompose feature entirely
The --decompose flag and supporting decomposer module had two
unfixable bugs (#1045): it crashed when ANTHROPIC_API_KEY was unset,
and it created multiple branches/PRs per issue, fragmenting history
and complicating review/merge. Removing the feature instead of
patching either bug.

- Delete packages/core/src/decomposer.ts and all re-exports
- Drop @anthropic-ai/sdk dependency from @composio/ao-core
- Remove --decompose / --max-depth options from ao spawn
- Remove decomposer field from ProjectConfig (zod default-strip
  silently ignores existing decomposer: blocks in user yaml)
- Remove lineage / siblings from SessionSpawnConfig and the
  prompt-builder Layer 4 block (only used by decomposer)
- Gut the matching backlog reactor branch in web/services.ts
  so the polling path no longer hits the same bugs
- Remove decompose parameter from openclaw-plugin ao_spawn tool
- Drop decomposer mocks from web services.test.ts
2026-04-10 13:02:52 +05:30
harshitsinghbhandari e47b03807c fix(agent-cursor): address Cursor Bugbot security findings
1. Add symlink check for .cursor directory in extractCursorSummary
   to match getCursorSessionMtime behavior (prevents path traversal)

2. Add vitest alias for @aoagents/ao-plugin-agent-cursor in CLI tests
   (fixes missing module resolution in tests)

3. Add lstatSync check before readFileSync in getLaunchCommand
   to reject symlinked systemPromptFile paths (security hardening)

4. Add test coverage for symlink rejection behavior

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 12:16:37 +05:30
harshitsinghbhandari f154f87add fix: merge upstream main and resolve conflicts for cursor agent
- Resolve @composio → @aoagents package renaming conflicts
- Add cursor agent to BUILTIN_PLUGINS in plugin-registry.ts
- Add cursor agent to AGENT_PLUGINS in detect-agent.ts
- Add cursor agent import and registration in plugins.ts
- Add cursor agent dependency and import in web services.ts
- Update cursor plugin package naming to @aoagents/ao-plugin-agent-cursor
- Add cursor agent to changeset linked group
- Fix test imports to use new @aoagents package naming

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-10 11:48:27 +05:30
ChiragArora31 98c5e1518c Merge upstream/main into feat/session-ls-json 2026-04-10 06:43:25 +05:30
Dhruv Sharma c9c41ad6dc
Merge pull request #967 from ChiragArora31/fix/notifier-alias-lifecycle-routing
fix(core): resolve notifier aliases in lifecycle routing
2026-04-10 03:02:36 +05:30
ChiragArora31 ea3da99c51 Merge upstream/main into feat/session-ls-json 2026-04-09 22:24:37 +05:30
ChiragArora31 f9edbee5d2 fix(cli): classify metadata orchestrators in session ls json 2026-04-09 22:16:49 +05:30
ChiragArora31 8ea1c38532 Merge upstream/main into fix/notifier-alias-lifecycle-routing 2026-04-09 21:55:05 +05:30
Prateek 27712442f8 fix: restore GitHub repo URLs to ComposioHQ/agent-orchestrator — only npm scope changed 2026-04-09 16:00:32 +00:00
Prateek 4f2616674f fix: address bugbot comments — missed renames in preflight, tests, and shell scripts 2026-04-09 16:00:31 +00:00
Prateek 967e864f5a chore: rename @composio scope to @aoagents across all packages
Renames all npm package scopes from @composio/* to @aoagents/* and
updates GitHub repo references from ComposioHQ/agent-orchestrator
to aoagents/ao throughout the codebase.

- All package.json names and dependencies
- README badges, links, and install instructions
- Documentation references
- Changeset config
- Source code imports and test files
2026-04-09 15:59:33 +00:00
ChiragArora31 49df74172b fix(core): preserve alias-specific notifier instances 2026-04-09 19:47:26 +05:30
harshitsinghbhandari f3224e9193 fix(cursor): correct getRestoreCommand signature and update documentation
Address critical PR review findings from #1076.

## Changes

### Critical Fix
- **cursor/index.ts:308**: Add required parameters to getRestoreCommand signature
  - Was: `async getRestoreCommand(): Promise<string | null>`
  - Now: `async getRestoreCommand(_session: Session, _project: ProjectConfig): Promise<string | null>`
  - Fixes interface contract violation that would cause silent runtime failures
  - Parameters prefixed with _ since method always returns null (Cursor doesn't support resume)

### Documentation Improvements
- **cursor/index.ts:125-127**: Add comment explaining --auto-approve flag
  - Clarifies that --auto-approve is equivalent to Aider's --yes flag
  - Maps to same permission semantics across agents
- **cli/config-instruction.ts:24,144**: Add cursor to available agents list
  - Update defaults example to include cursor
  - Update "Available plugins" reference to include cursor

### Type Imports
- **cursor/index.ts:19**: Import ProjectConfig type for getRestoreCommand signature

## Testing
-  cursor plugin tests: 51/51 passing
-  cursor plugin typecheck: clean
-  No regressions introduced

## Why These Changes Are Needed

**Before:**
- getRestoreCommand signature mismatch would cause silent failures when core system calls it with parameters
- Config documentation didn't mention cursor as available agent option
- No explanation why --auto-approve differs from Aider's --yes naming

**After:**
- Interface contract properly satisfied
- Documentation complete and helpful
- Clear code comments explaining design decisions

Addresses: ComposioHQ/agent-orchestrator#1076

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-04-09 19:29:26 +05:30
harshitsinghbhandari 04f3a7c27f fix(cursor): register plugin in all discovery/resolution layers
Address PR review feedback from #1076 to make Cursor agent fully functional.

## Changes

### Plugin Registration (High Severity Fixes)
- **core/plugin-registry.ts**: Add cursor to BUILTIN_PLUGINS array for config-based resolution
- **cli/plugins.ts**: Import and register cursor in agentPlugins map for getAgent/getAgentByName
- **cli/detect-agent.ts**: Add cursor to AGENT_PLUGINS array for detectAvailableAgents()
- **web/services.ts**: Import and register cursor plugin for dashboard SessionManager/LifecycleManager
- **web/package.json**: Add @composio/ao-plugin-agent-cursor dependency

### Activity Detection Fix (Medium Severity)
- **cursor/index.ts**: Remove overly broad blocked detection patterns (error:/failed:)
  - Compiler errors, test failures, and linter output are normal tool output
  - Terminal-based detection can't distinguish between actionable agent errors and normal output
  - Follow Aider/OpenCode pattern: only Claude Code detects blocked (has native JSONL)
  - Added comment explaining why blocked detection is removed
- **cursor/index.test.ts**: Remove blocked detection test cases

## Why These Changes Are Needed

Before these fixes:
- `defaults.agent: cursor` in config would throw "Unknown agent plugin: cursor"
- `ao spawn --agent cursor` would fail
- Dashboard couldn't resolve cursor agent (SessionManager/LifecycleManager failures)
- `detectAvailableAgents()` never discovered Cursor
- False "blocked" states when agent encountered normal compiler errors

After these fixes:
- Cursor agent fully discoverable and usable via config and CLI
- Dashboard can spawn and manage Cursor sessions
- Activity detection matches other terminal-based agents (Aider, OpenCode)
- No false positives from normal tool output

## Testing
-  cursor plugin tests: 51/51 passing (reduced from 52 due to removed blocked tests)
-  core typecheck: clean
-  web typecheck: clean
-  CLI can import cursor plugin without errors

Addresses: ComposioHQ/agent-orchestrator#1076

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-04-09 19:17:41 +05:30
harshitsinghbhandari 464f771a76 feat: add Cursor agent CLI support (#1060)
Implement a new agent plugin for Cursor CLI following the existing agent plugin pattern.

## Changes
- Create `packages/plugins/agent-cursor/` with full Agent interface implementation
- Add Cursor plugin to CLI dependencies
- Implement all required methods:
  - getLaunchCommand - command to start Cursor CLI with flags
  - getEnvironment - env vars including ~/.ao/bin in PATH
  - detectActivity - terminal output classification for Cursor prompts
  - getActivityState - JSONL/activity-based state detection with fallbacks
  - isProcessRunning - process liveness check (tmux TTY + PID)
  - setupWorkspaceHooks - PATH wrappers for git/gh metadata capture
  - getSessionInfo - extract summary from .cursor directory if available
  - recordActivity - delegate to shared recordTerminalActivity
  - postLaunchSetup - ensure hooks are installed post-launch
  - getRestoreCommand - returns null (Cursor doesn't support session resume)

## Testing
- Comprehensive test suite with 52 passing tests covering:
  - Manifest validation
  - Command generation with permission modes
  - Process detection (tmux + process runtime)
  - Activity detection from terminal output
  - Activity state cascade (JSONL → git commits → session mtime → fallback)
  - All required getActivityState contract states (exited, waiting_input, blocked, active, idle)
  - Session info extraction
  - Environment setup

## Pattern
Follows the Aider agent pattern using:
- PATH wrappers (`~/.ao/bin/gh`, `~/.ao/bin/git`) for metadata capture
- AO Activity JSONL for terminal-derived activity detection
- Age-based decay for active/ready/idle state transitions
- Process name regex matching both `cursor` and `.cursor` (dot-prefixed)

Closes #1060

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-04-09 18:51:33 +05:30
Dhruv Sharma aa2177698a feat(spawn): support prompt-driven sessions without a tracker issue (#974)
- Add --prompt <text> flag to `ao spawn` CLI
- Accept prompt field in POST /api/spawn web route
- Persist userPrompt to session metadata on spawn
- Add userPrompt to DashboardSession type and serialize.ts mapping
- Show userPrompt in SessionCard footer for prompt-only sessions
- Include userPrompt in SessionDetail headline fallback chain
- Update orchestrator-prompt.ts with prompt-driven spawn examples

Closes #974
2026-04-09 18:43:55 +05:30
adil 6ecaabe3e6 fix(cli): remove 'Next step' hint from ao start output (#947)
Remove the post-startup "Next step: ao spawn <issue-number>" hint
per reviewer feedback — the dashboard already guides users.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 00:05:06 +05:30
adil 2f4968c461 refactor(cli): extract DEFAULT_PORT constant to shared module (#947)
Replace hardcoded magic number 3000 across spawn.ts, session.ts,
open.ts, dashboard.ts, and start.ts with a shared DEFAULT_PORT
constant from lib/constants.ts. Fixes Bugbot review feedback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 03:40:25 +05:30
adil 98547a9f74 fix(cli): clear spinner mock calls between tests (#947)
Add mockClear() before mockReturnThis() in spawn test beforeEach to
prevent call history accumulating across tests. Fixes Bugbot review
feedback about stale mock.calls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 03:40:06 +05:30
adil 48a6f94f50 fix(cli): use ao session attach fallback when --no-dashboard (#947)
When dashboard is disabled, print `ao session attach <id>` instead of
an unreachable dashboard URL. Fixes Bugbot review feedback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 03:40:06 +05:30
adil 24ecfc2926 fix(cli): replace all tmux attach output with dashboard URLs (#947)
Replace raw `tmux attach -t` commands in CLI output with web dashboard
URLs (`http://localhost:{port}/sessions/{sessionId}`) across all four
CLI commands: spawn, session restore, open, and start.

Add `stripHashPrefix` helper in session-utils to extract AO session IDs
from hash-prefixed tmux session names. Remove unused `tmuxTarget`
variable from start command.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 03:40:06 +05:30
adil 5322220f6e fix(cli): consolidate spawn output into single message, add dashboard caveat
Address review feedback:
- Remove duplicate created/spawned messages — use single spinner.succeed
- Add "(if running)" qualifier for dashboard mention since ao spawn
  does not start the dashboard itself
- Update test mock to expose spinner for output assertions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 03:40:06 +05:30
adil 5ad370e8d1 fix(cli): simplify spawn success message, use ao session attach (#947)
Replace verbose multi-line spawn output (worktree, branch, raw tmux
attach) with a single-line message that directs users to the dashboard
or `ao session attach <id>` instead of exposing internal tmux session
hashes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 03:40:06 +05:30
adil fe6fb4f7a2 fix(cli): print session URL instead of tmux attach in ao start (#947)
When dashboard is enabled, `ao start` now prints the session detail page
URL (e.g. http://localhost:3000/sessions/<id>) instead of the tmux attach
command. Falls back to tmux attach when --no-dashboard is used.

Closes #947

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 03:40:06 +05:30
yyovil e1a42cd834 fix(cli): add Error: prefix to ConfigNotFoundError output and fix test assertion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 1549183539ad
2026-04-07 22:33:40 +05:30
yyovil 9a49e5d7b3 fix(cli): remove redundant Error: prefix from ConfigNotFoundError output
The issue acceptance criteria expects a clean message without an "Error:"
prefix. Revert the prefix addition so the output matches the spec.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 392be8980a3b
2026-04-07 22:17:47 +05:30
yyovil 7f658ca498
Apply suggestions from code review
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-07 21:47:35 +05:30
yyovil d43a083296 fix(cli): catch ConfigNotFoundError for clean error output
Use parseAsync() with a .catch() handler in the CLI entrypoint so that
ConfigNotFoundError prints a single actionable message instead of a raw
Node.js stack trace. Add tests covering the error handler and re-throw
paths to satisfy diff coverage requirements.

Fixes #981

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 2acdb7413776
2026-04-07 19:35:04 +05:30
Ashish Huddar 48d655d932
fix: reduce dashboard JS bundle from 1.7MB to 170KB (#792) (#928)
* fix: reduce dashboard JS bundle from 1.7MB to 170KB (gzipped) (#792)

Switch `ao start` default from `next dev` (7.6MB uncompressed) to optimized
production builds (128KB per route). Add `--dev` flag for HMR when editing
dashboard UI. Add bundle analyzer, server-only guards, and lazy-load
DirectTerminal via next/dynamic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: skip dashboard rebuild when assets exist, fix CI timeout

Skip the production build step when .next/BUILD_ID and dist-server/
already exist (e.g. after pnpm build in CI). Add c8 ignore for
untestable process-spawning startup code to fix diff coverage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: adopt PR #903 patterns — centralize rebuild logic and add preflight web artifact checks

Extract rebuildDashboardProductionArtifacts into dashboard-rebuild.ts, add
isInstalledUnderNodeModules/assertDashboardRebuildSupported guards, remove
findProcessWebDir, and verify .next/BUILD_ID + dist-server/start-all.js in
preflight. Dashboard command now always uses production server.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: skip production preflight in --dev mode, add coverage for rebuild helpers

- Skip preflight.checkBuilt() when --dev is passed (dev mode uses HMR,
  doesn't need .next/BUILD_ID or dist-server/start-all.js)
- Add c8 ignore to dashboard.ts process-spawning code (matches start.ts pattern)
- Add tests for rebuildDashboardProductionArtifacts (success, failure, npm guard)
- Add preflight tests for npm-install web artifact hint paths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: align preflight skip with actual dev-server condition

Only skip production artifact preflight when both --dev is passed AND
we're in the monorepo (where dev mode actually works). For npm global
installs, --dev is silently ignored and production server runs, so
preflight must still validate .next/BUILD_ID and dist-server/start-all.js.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: match @next/bundle-analyzer version to next@^15.1.0

The @next/* packages follow the Next.js release train. Pin the bundle
analyzer to ^15.1.0 to match the project's next dependency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: correct recovery command for npm installs and remove redundant guard

- Change stale-build recovery suggestion from "ao update" (which only
  works in source checkouts) to "npm install -g @composio/ao@latest"
  for npm global installs
- Remove redundant assertDashboardRebuildSupported call in dashboard.ts
  since rebuildDashboardProductionArtifacts already calls it internally

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 16:12:51 +05:30
Ashish Huddar d8b8645bc7
fix(cli): ao start navigates to session page instead of orchestrator selection (#958)
* fix(cli): ao start navigates to session page instead of orchestrator selection

When ao start finds existing orchestrators, it now auto-selects the most
recently active one and opens /sessions/{id} directly, rather than the
/orchestrators selection page. This matches the behavior users expect:
landing on the agent terminal immediately on startup.

Closes #954

* fix(cli): navigate to session page for single orchestrator, selection page for multiple

When ao start finds existing orchestrators:
- 1 orchestrator: navigate directly to /sessions/{id} (fix for #954)
- 2+ orchestrators: keep /orchestrators?project={id} selection page so users
  can choose among sessions or spawn a new one — the main dashboard only
  links one orchestrator per project, making the selection page the only
  startup path for multi-orchestrator projects.

Addresses review feedback on #958.
2026-04-07 09:48:41 +05:30
Ashish Huddar 30ee327daf
fix(notifier): remove desktop notifications from default configs (#962)
* fix(notifier): remove desktop notifications from all default configs (#960)

Desktop notifications via osascript open blank Finder windows on macOS
without providing useful information. Remove 'desktop' from all default
notifier lists so new users are not affected. Existing configs that
explicitly list 'desktop' continue to work unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(cli): add coverage for autoCreateConfig default notifiers

Line 585 in start.ts (`notifiers: []`) was not covered by the diff
coverage check. Added a test that exercises `autoCreateConfig` via
`createConfigOnly()`, verifying that the generated config does not
include 'desktop' in `defaults.notifiers`.

Required infrastructure additions:
- Mock `node:process` so `import { cwd } from "node:process"` in
  start.ts can be overridden per-test via `mockProcessCwd`
- Set `detectProjectType` mock to return `{ languages: [], frameworks: [] }`
  instead of null to avoid crash in autoCreateConfig

Closes #960

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(config): disable all notifications by default — fully opt-in

Change DefaultPluginsSchema.notifiers default from ["composio"] to []
and notificationRouting defaults to all empty arrays, so no notifications
are sent unless the user explicitly configures them. Addresses reviewer
feedback that composio notifier should not be active out of the box.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(config): use empty object as notificationRouting default

Empty array entries like { urgent: [] } block the ?? fallback in
notifyHuman (lifecycle-manager.ts:1169) because [] is not null/undefined.
Using {} lets unlisted priorities fall back to defaults.notifiers, so
explicit per-user notifier config is respected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 08:59:51 +05:30
ChiragArora31 8f8552817f fix(cli): avoid json work in session ls default path 2026-04-07 08:51:28 +05:30
ChiragArora31 f19f46b30e feat(cli): add json output to session ls 2026-04-07 08:41:10 +05:30
ChiragArora31 4d22931180 fix(core): resolve notifier aliases in lifecycle routing 2026-04-07 08:23:03 +05:30
Harsh Batheja 9ac659066a
revert: remove model rate-limit pause functionality (PR #367) (#908)
* Revert "fix: pause workers on model limits and stabilize session visibility (#367)"

This reverts commit 003eb78adb.

* fix: resolve post-revert type errors and broken test references

- Fix dangling import { in session-manager.ts (leftover from removing globalPause imports)
- Fix duplicate registerStop body in start.ts (leftover parent-version code after catch block)
- Remove --keep-session flag from stop command (was added by #367)
- Fix PullRequestsPage.tsx useSessionEvents call removing dropped initialGlobalPause arg
- Remove globalPause test cases from spawn.test.ts, communication.test.ts, api-routes.test.ts
- Remove unused updateMetadata imports from test files

* fix: remove unused allSessions variable after globalPause removal
2026-04-06 14:58:41 +05:30
Ashish Huddar 0e3f6c8698 Merge remote-tracking branch 'origin/main' into ashish921998/404-loading-pages 2026-04-06 09:10:23 +05:30
Ashish Huddar 52bcce8f2b feat(web): add dashboard error boundaries 2026-04-06 00:32:53 +05:30
Harshit Singh Bhandari 35eca3107c
Merge pull request #909 from harshitsinghbhandari/fix/prevent-duplicate-orchestrators
fix: prevent ao start from spawning duplicate orchestrators
2026-04-05 22:47:06 +05:30
Ashish Huddar 129149e166 fix(cli): resolve ao-core vitest subpaths 2026-04-05 22:38:55 +05:30
Ashish Huddar 1d30731247 fix(cli,web): stabilize isolated workspace checks 2026-04-05 22:28:12 +05:30
harshitsinghbhandari e2b43ec0b2 fix comments 2026-04-05 18:41:46 +05:30
suraj_markup 86ac556e8e
Merge pull request #864 from yyovil/emdash/fix-ao-version-p0h
fix(cli): ao's version mismatch problem
2026-04-04 23:41:13 +05:30
harshitsinghbhandari a21b97656b fix: correct tmux target fallback and deduplicate orchestrator listing
- Fix tmux target to use session ID when runtimeHandle is missing,
  preventing references to non-existent sessions
- Extract mapSessionsToOrchestrators helper to eliminate duplicate
  orchestrator listing logic between page.tsx and API route

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-04 22:43:11 +05:30
harshitsinghbhandari 25b3f31a1c test: update start command tests for auto-select behavior
Update existing test to verify the new --no-dashboard auto-select
behavior and add a separate test for dashboard-enabled selection
message.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-04 22:10:11 +05:30
harshitsinghbhandari f9abcdf32f fix: auto-select orchestrator when --no-dashboard is used
When --no-dashboard is used and existing orchestrators are found,
auto-select the most recently active one instead of deferring to
dashboard selection (which isn't available). This ensures the CLI
remains usable without the dashboard.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-04 21:57:56 +05:30
harshitsinghbhandari d54ca026c1 fix: wrap session listing in try/catch for proper error handling
The sm.list() call was outside the existing try/catch that handles
orchestrator setup failures. If listing sessions throws, the spinner
could be left running and the dashboard process could leak.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-04 21:56:53 +05:30
harshitsinghbhandari 2a1b513e7d fix tests 2026-04-04 21:52:50 +05:30
harshitsinghbhandari 71bdf75f53 add missing mock list 2026-04-04 19:32:01 +05:30
harshitsinghbhandari 0b7b3153a9 fix: prevent ao start from spawning duplicate orchestrators
When ao start is run and existing orchestrator sessions exist for the
project, the CLI now skips spawning a new one. Instead:

- Detects existing orchestrator sessions before spawning
- Opens the dashboard to a new /orchestrators page for session selection
- Users can resume an existing orchestrator or start a new one

Changes:
- packages/cli/src/commands/start.ts: Check for existing orchestrators,
  redirect to selection page if found
- packages/web/src/app/api/orchestrators/route.ts: Add GET endpoint to
  list orchestrators for a project
- packages/web/src/app/orchestrators/page.tsx: New page for orchestrator
  selection
- packages/web/src/components/OrchestratorSelector.tsx: UI component for
  selecting or spawning orchestrators
- packages/web/src/components/__tests__/OrchestratorSelector.test.tsx:
  Tests for the selector component

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-04 19:05:51 +05:30
Harsh Batheja 34bc5bb2d5
feat: support multiple concurrent orchestrators with isolated worktrees (#870)
* feat: support multiple concurrent orchestrators with isolated worktrees

- Each orchestrator session gets a numbered ID ({prefix}-orchestrator-N)
  and an isolated git worktree, replacing the single shared orchestrator
- reserveNextOrchestratorIdentity atomically reserves the next available
  number and detects conflicting project prefix configurations early
- isOrchestratorSession / isOrchestratorSessionName accept optional
  allSessionPrefixes for cross-project false-positive prevention
- getProjectPause and resolveGlobalPause track the longest active pause
  across all concurrent orchestrators instead of returning the first found
- cleanupWorktreeAndMetadata helper used consistently on all failure paths
  including post-launch; system prompt file included in cleanup
- pollBacklog, status.ts, ProjectSidebar, sessions page, global-pause,
  project-utils, serialize, and sessions API route all pass
  allSessionPrefixes to isOrchestratorSession
- Web sessions/[id]/page.tsx fetches project prefix map and passes it
  through prefixByProjectRef to avoid stale closure in fetchProjectSessions

* fix: seed sseAttentionLevels from fresh sessions on full refresh

When scheduleRefresh dispatches a reset action, derive sseAttentionLevels
from the freshly fetched sessions using getAttentionLevel. This clears
phantom entries for removed sessions and seeds correct levels for new
sessions, preventing stale favicon color and attention counts until the
next SSE snapshot.

* fix: merge duplicate @/lib/types imports into single import statement

Combining the separate import type and value import from @/lib/types
into one import to satisfy the no-duplicate-imports lint rule.
2026-04-04 12:30:51 +05:30
harshitsinghbhandari ddba72a485 Merge branch 'main' of https://github.com/ComposioHQ/agent-orchestrator into feat/736 2026-04-03 02:40:53 +05:30
harshitsinghbhandari 9a3a18b2c7 performed review and fixed 2026-04-03 01:23:37 +05:30
harshitsinghbhandari add74f1a46 fix: handle optional plugin field in CLI and web packages
Update all usages of project.tracker.plugin and project.scm.plugin
to use optional chaining since the plugin field is now optional
when package or path fields are specified.

Files updated:
- CLI: doctor.ts, status.ts, verify.ts
- Web: issues/route.ts, verify/route.ts, scm-webhooks.ts,
       serialize.ts, services.ts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-02 19:19:44 +05:30
Your Name 9e78fe3b23 fix: resolve prompt delivery persistence and false warnings 2026-04-02 17:41:46 +05:30
yyovil b5018998db refactor CLI version wiring for diff coverage
Extract getCliVersion and createProgram so the version-path changes are covered by the PR Diff Coverage workflow.
2026-04-02 17:34:19 +05:30
Your Name feecc6f177 fix: robust prompt delivery with retries and CLI warnings 2026-04-02 17:27:53 +05:30
yyovil 76b5e42c6f added missing tests for added loc 2026-04-02 01:02:28 +05:30
yyovil 2b8c7e8d9a Reverted back to createRequire method instead of static imports in ESM because of compatibility issues with node < v20.10.0 2026-04-02 00:10:01 +05:30
Yyovil c4cd7c7098
Apply suggestion from @Copilot
node16 will do the trick

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-01 23:37:37 +05:30
yyovil 58266a96e3 Fixed ao's version mismatch problem 2026-04-01 22:30:22 +05:30
ChiragArora31 4d33d25126 fix: detect nested project directories in CLI auto-resolution 2026-04-01 18:28:57 +05:30
Dhruv Sharma 2febded969
Merge pull request #836 from ChiragArora31/feat/status-watch-mode
feat(cli): add watch mode to ao status
2026-04-01 12:28:32 +05:30
ChiragArora31 10a41cfafa fix(cli/status): validate --interval only when --watch is used
The --interval flag is only relevant when --watch is enabled.
Previously, passing `--interval 0` without `--watch` threw an error,
whereas `--interval 5` was silently ignored. Now, invalid intervals
are ignored when `--watch` is omitted, ensuring consistent behavior.

Also adds a test case to prevent regression.
2026-04-01 11:05:30 +05:30
ChiragArora31 5a186fbb7f test(cli/status): add tests to hit 80% diff coverage threshold
Cover the following previously-uncovered lines in status.ts:
- 65-69: maybeClearScreen() isTTY branch
- 255-256: maybeClearScreen() call on watch refresh (refreshing=true)
- 262-266: loadConfig() throw → fallback to tmux session discovery
- 269-271: unknown --project flag → process.exit(1)
- 388, 390-396, 398: tracker block (registry.get, listIssues, error catch)
- 402-405: unverified issues warning banner
- 424-436: setInterval guard skips render when already in progress

Also hoists mockGetPluginRegistry as a vi.fn() so individual tests
can override the plugin registry returned by getPluginRegistry.
2026-04-01 10:37:12 +05:30
ChiragArora31 70232baf29 fix(cli): clean up status watch timer on shutdown 2026-04-01 09:27:38 +05:30
ChiragArora31 2d6bc7671d feat: add watch mode to status command 2026-04-01 09:26:59 +05:30
ChiragArora31 4420ab1773 feat(cli): add plugin resolution checks to ao doctor 2026-04-01 06:39:14 +05:30
Dhruv Sharma 7d7fb92d7b
Merge pull request #837 from fireddd/ci/diff-coverage-threshold
ci: add diff coverage workflow enforcing 80% on changed code only
2026-03-31 20:58:33 +05:30
Dhruv Sharma 124f7d30ee Merge main into feat/openclaw-dx - resolve conflicts
Conflicts resolved in 3 files:
- plugin-marketplace.ts: take main's createRequire approach, keep isAbsolute fix
- plugin-scaffold.ts: take main's newline escaping (superset of backslash fix)
- plugin.test.ts: take main's importOriginal pattern

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 20:05:16 +05:30
Dhruv Sharma 1701e03aac
Merge pull request #833 from ComposioHQ/feat/plugin-marketplace
Feat/plugin marketplace
2026-03-31 20:01:39 +05:30
Harsh Batheja 66aa92aec0
fix: use pnpm dev in monorepo to start terminal WebSocket servers (#846)
In dev mode, `npx next dev` only starts Next.js without the terminal
WebSocket servers. Detect monorepo by checking for `server/` dir and
use `pnpm run dev` which runs both via concurrently.
2026-03-31 19:13:49 +05:30
Dhruv Sharma fe1d45b0a7 fix: address production failure modes from adversarial review
- Rollback plugin config on setup failure so a half-configured
  notifier is never left enabled (non-transactional install fix)
- Use atomic temp+rename for health summary writes to prevent
  corruption under concurrent notifications
- Scope credential injection to only when OpenClaw notifier is
  configured, avoiding ambient secret exposure to unrelated projects

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:39:49 +05:30
Dhruv Sharma 166ace7477 refactor: extract fetch timeout into named constant
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:38:28 +05:30
Dhruv Sharma 6cfb1cc864 fix: guard statSync against permission errors, add fetch timeout
- Wrap statSync in try/catch in resolveLocalPluginEntrypoint so
  permission-denied errors return null instead of crashing
- Add 30s AbortSignal timeout to refreshMarketplaceCatalog fetch
  to prevent indefinite hangs on slow networks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 14:37:52 +05:30
Dhruv Sharma d36c0947cf refactor: deduplicate plugin resolution logic between core and CLI
Export isPluginModule, normalizeImportedPluginModule,
resolvePackageExportsEntry, and resolveLocalPluginEntrypoint from
@composio/ao-core and import them in the CLI instead of maintaining
independent copies that have already diverged.

Removes ~70 lines of duplicated code from plugin-marketplace.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:53:30 +05:30
Dhruv Sharma 153c298a46 fix: resolve plugin-registry.json from package root
createRequire resolves relative to the compiled dist/lib/ directory
where the JSON file doesn't exist. Use readFileSync with a path
resolved from the package root (../../src/assets/) which works from
both src/lib/ and dist/lib/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:45:54 +05:30
fireddd e6c3a06427 ci: add diff coverage workflow enforcing 80% on changed code only
Uses diff-cover to check that newly added or modified lines in PRs
have at least 80% test coverage, without requiring the entire
codebase to meet the threshold.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 09:26:36 +05:30
Dhruv Sharma 6930f2ee12 fix: use createRequire for JSON import (Node16 module compat)
Import attributes aren't supported with module: "Node16". Switch to
createRequire for the plugin-registry.json import and copy assets
to dist during build.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 05:11:24 +05:30
Dhruv Sharma 2c0a32da24 fix: use createRequire for JSON import (Node16 module compat)
Import attributes (`with { type: "json" }`) require module >= node18.
Use createRequire instead since tsconfig targets Node16.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 05:10:50 +05:30
Dhruv Sharma 545bede0b4 fix: add JSON import attribute for Node.js 20 compatibility
Add `with { type: "json" }` to the plugin-registry.json import to
satisfy Node.js 20's ERR_IMPORT_ASSERTION_TYPE_MISSING requirement.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 05:08:13 +05:30
Dhruv Sharma 42adf3f35d fix: add JSON import attribute for plugin-registry.json
Node.js v20 requires `with { type: "json" }` for JSON module imports.
This fixes the ERR_IMPORT_ASSERTION_TYPE_MISSING error in the onboarding
integration test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 05:07:56 +05:30
Dhruv Sharma 7eac80cec4 fix: resolve lint errors in plugin, start, and test files
- Remove unused `resolve` import from plugin.ts
- Use strict equality (`!== null && !== undefined`) instead of `!=` in start.ts
- Attach `cause` to re-thrown errors in plugin install/update rollback
- Fix forbidden `import()` type annotation in plugin test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 05:05:50 +05:30
Dhruv Sharma 89d6f95723 fix: export runSetupAction, fix lint errors in plugin command
- Export runSetupAction from setup.ts (fixes TS2459 build error)
- Use rollbackErr as cause in re-thrown errors (preserve-caught-error)
- Remove import() type annotation from test mock (consistent-type-imports)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 05:04:29 +05:30
Dhruv Sharma 41989b71bc fix: remove dead code, validate SHELL path, and guard health JSON parsing
- Remove unused printPluginList wrapper (all callers use printPluginListFromCatalog directly)
- Remove unused getAgentFromRegistry export (all callers use getAgentByNameFromRegistry)
- Validate SHELL env var starts with / before passing to spawnSync
- Add shape validation for openclaw-health.json parsed content

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 05:01:28 +05:30
Dhruv Sharma 1df727782c fix: resolve pre-existing lint errors in plugin command
- Remove unused `resolve` import from node:path
- Add `{ cause: err }` to re-thrown errors (preserve-caught-error rule)
- Fix import() type annotation in plugin test (consistent-type-imports)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 05:00:30 +05:30
Dhruv Sharma 1271ef8fbd fix: add missing default exports fallback and remove dead code
- Add top-level "default" key fallback in CLI's resolvePackageExportsEntry
  to match core's plugin-registry.ts (fixes local plugin resolution for
  packages using exports: { "default": "./dist/index.js" })
- Remove dead exports: MARKETPLACE_PLUGIN_CATALOG, printPluginList,
  getAgentFromRegistry, resolveInstalledPluginSpecifier
- Fix incomplete string escaping in plugin scaffold (backslash/newline)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 04:57:25 +05:30
Dhruv Sharma 846ddc4135 refactor: enhance OpenClaw plugin interfaces and improve setup options 2026-03-31 04:56:03 +05:30
Dhruv Sharma 76c3a78d68 add OpenClaw health checks to ao doctor 2026-03-31 04:02:33 +05:30
Dhruv Sharma b613158675 auto-detect OpenClaw in non-interactive setup 2026-03-31 04:02:33 +05:30
Dhruv Sharma 85924b82a8 wire OpenClaw status and credentials into ao start 2026-03-31 04:02:33 +05:30
Dhruv Sharma 4d142eac1f add credential resolver for OpenClaw key sharing 2026-03-31 04:02:33 +05:30
Dhruv Sharma a10ceb6c09 enhance openclaw-probe with installation detection 2026-03-31 04:02:33 +05:30
Dhruv Sharma 7445e134c4 add plugin spec and update docs 2026-03-31 04:02:25 +05:30
Dhruv Sharma 594c371e37 add browser-open error handling 2026-03-31 04:02:25 +05:30
Dhruv Sharma 9ba04391d9 use plugin store for shared loader paths 2026-03-31 04:02:25 +05:30
Dhruv Sharma b4b111a910 add ao plugin CLI commands 2026-03-31 04:02:25 +05:30
Dhruv Sharma df9409eceb add plugin scaffold generator 2026-03-31 04:02:25 +05:30
Dhruv Sharma bd60fb7b52 extract marketplace catalog to JSON with refresh 2026-03-31 04:02:25 +05:30
Dhruv Sharma 39396d4534 add cli error formatter and plugin store 2026-03-31 04:02:25 +05:30
Gautam Tayal 79938be822 refactor(cli): replace clack prompts with custom promptSelect function 2026-03-30 15:32:15 +05:30
Gautam Tayal fbf177300e refactor(cli): simplify agent selection prompt by removing unnecessary confirmation step 2026-03-30 15:32:15 +05:30
Gautam Tayal da8aabe0f2 feat(cli): add interactive option for agent configuration prompt before starting 2026-03-30 15:32:15 +05:30
Gautam Tayal 2282e0e9c9 fix: update jsdocs 2026-03-30 15:32:15 +05:30
Gautam Tayal 7d42dd7672 fix(cli): reload project configuration after saving changes 2026-03-30 15:32:15 +05:30
Gautam Tayal 56b36613f6 refactor(cli): streamline agent handling in spawn command 2026-03-30 15:32:15 +05:30
Gautam Tayal 7ca7632e73 refactor(cli): remove save to config option 2026-03-30 15:32:15 +05:30
Gautam Tayal 8c23903fa2 feat: add agent selection prompt 2026-03-30 15:32:15 +05:30
Dhruv Sharma d65d72e5c1
Merge pull request #797 from gautamtayal1/refactor/migrate-to-clack-prompts
refactor(cli): replace readline prompts with clack prompts
2026-03-29 22:17:49 +05:30
Harshit Singh Bhandari 8f271c4da5
Merge pull request #795 from harshitsinghbhandari/main
Fix: Resolved OpenCode discovery flakiness via extended timeouts, enabled integration test suite, and parallelized CLI session/status I/O for 80% faster response times.
2026-03-29 19:01:07 +05:30
harshitsinghbhandari 844c97cb63 minor fix 2026-03-29 18:52:34 +05:30
Gautam Tayal 5ba73016e0 fix: update promptSelect to handle undefined initialValue 2026-03-29 18:39:32 +05:30
harshitsinghbhandari e858cef29b perf(cli): parallelize tmux activity and agent introspection in fallback 'ao status' 2026-03-29 18:28:16 +05:30
harshitsinghbhandari 124cc33745 perf(cli): parallelize I/O calls in 'ao session ls' for faster listing 2026-03-29 18:28:04 +05:30
Gautam Tayal a180520575 refactor(cli): replace readline prompts with clack prompts 2026-03-29 18:06:27 +05:30
github-actions[bot] d1e937b855 chore: version packages 2026-03-29 09:21:26 +00:00
Gautam Tayal b010e322e0 fix 2026-03-28 21:47:31 +05:30
Gautam Tayal e03d22871e fix 2026-03-28 21:46:16 +05:30
Gautam Tayal db7a7039e9 fix 2026-03-28 21:41:51 +05:30
Gautam Tayal 3860a42424 fix 2026-03-28 21:40:21 +05:30
Gautam Tayal b83347402b fix 2026-03-28 13:58:41 +05:30
Gautam Tayal 8da1c2e54f fix 2026-03-28 13:18:10 +05:30
Gautam Tayal 71d7411ada refactor(cli): update project resolution to prompt user for selection in multi-project scenarios 2026-03-28 13:10:10 +05:30
Dhruv Sharma 5933991252
Merge pull request #631 from illegalcall/feat/openclaw-integration
feat: OpenClaw plugin, AO skill, Discord notifier, and setup wizard
2026-03-27 09:48:25 +05:30
Ashish Huddar af6c4c5add
Merge pull request #634 from ComposioHQ/feat/issue-633
chore(web): mobile-responsive layout for dashboard and session views
2026-03-27 01:44:07 +05:30
Dhruv Sharma 373654f4e1 fix yaml test 2026-03-27 01:41:08 +05:30