Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Agents Orchestrator

A desktop orchestrator application built with Electron, allowing users to automate interactions with command-line AI agents (such as Claude and Codex) through a drag-and-drop block interface and an embedded pseudo-terminal (PTY).

Several agents can run at once — one session per account — with a tab per session and a quick-send bar for ad-hoc prompts.

Project Status

Version: 0.2.0

Field guide

The docs/ field guide turns the account model, first-run recovery path, multi-agent recipe, output-aware waiting, and privacy boundaries into a responsive, interactive walkthrough. It is plain HTML, CSS, and JavaScript: no build step, backend, analytics, remote runtime assets, or account data access. Open docs/index.html directly in a browser.

Multi-account agent control

Each session is "which agent, as which account", and the guarantee behind that pairing is stated rather than implied:

Level What it means How a session starts
L1 · routed A Codex alias owned by ai-agent-entrypoint, which builds the child environment agent-entrypoint.ps1 codex shell <alias>
L2 · env-only A local profile that points the agent at its own state directory (CLAUDE_CONFIG_DIR, GROK_HOME, …) for that child process powershell.exe with env overrides
L0 · native No account selected plain powershell.exe
  • Routed accounts are discovered, not configured here. The app asks ai-agent-entrypoint for its Codex aliases and launches through it. This app never reads or writes that manifest and is not a source of account truth.
  • Local profiles cover the CLIs nobody manages yet. Claude Code, Grok, and Gemini have no managed routing layer, so a profile gives each account its own state directory and you log in once inside that session. This is a weaker guarantee than a routed account, and the UI says so — it is never described as isolation.
  • No credentials are stored by this app. Profile environments accept paths and flags only; a key that looks like a token, API key, or password is rejected with an explanation. Discovery output containing canonical account paths is stripped before it reaches the UI, the log, or an exported workflow.
  • Routed launches fail closed. If an alias cannot be resolved, the session refuses to start rather than quietly falling back to the native login.

Sessions appear as tabs above the terminal; all of them keep running and buffering while hidden. The quick-send bar targets the current session, every session of one agent, or all of them at once.

Release Notes

v0.2.0 (multi-account agents)

  • Multiple concurrent agent sessions, one per account, each with its own terminal tab, status dot, and assurance badge. Background sessions keep rendering, so nothing is lost while you watch another one.
  • Agent accounts panel listing routed Codex accounts discovered from ai-agent-entrypoint alongside local env-only profiles you manage here. Click one to open a session.
  • Quick-send bar for ad-hoc prompts to one session, all sessions of one agent, or every session — using the same human-paced typing as the workflow engine.
  • New blocks: 🤖 Agent Session opens an account, 📨 Send to Agent prompts a specific one, and 👂 Wait for Agent continues when new PTY output goes idle or contains chosen text. Its timeout is a logged backstop, not the normal synchronization mechanism. Existing workflows keep working unchanged.
  • Output-aware waiting lives beside the PTY. SessionRegistry keeps a bounded, main-process-only activity buffer; workflow sends take an opaque sequence checkpoint so a fast reply cannot disappear between blocks. Buffered output never crosses into workflow JSON or session metadata.
  • Routed account source setting: the Agents panel can browse, save, or clear the machine-local ai-agent-entrypoint checkout path. A blank value keeps sibling auto-detection, so a machine without the sibling checkout now has an in-app recovery path.
  • A workflow run no longer kills every process. It closes only the sessions the previous run opened; sessions you started by hand are left alone.
  • Killing a session kills its process tree (SIGTERM, then taskkill /T after a grace window), so a routed pwsh with an agent child leaves nothing behind. Bulk closes and app shutdown serialize ConPTY exits to avoid a native node-pty baton-removal race.
  • Validated IPC. Payloads are type- and range-checked; send-input previously threw on any non-string.
  • Persisted settings: terminal theme, window geometry, and panel sizes survive a restart.
  • Real test suites: npm run test:unit (node --test over the main-process modules) plus the Electron self-test, now covering typing, quick-send targeting, launch specs, the credential boundary, and the path-leak boundary.
  • Fixed: declaration-order fragility in the panel resizers, two competing Escape handlers, and keypress "enter" sending LF where the input block sent CR.
  • Replaced the deprecated xterm / xterm-addon-fit packages with @xterm/xterm and @xterm/addon-fit; the title-bar version is read from package.json instead of hardcoded.

v0.1.9 (review & fixes)

  • Fixed: opening a saved workflow disarmed its schedule. Opening or importing a workflow wrongly marked its next scheduled occurrence as already-fired (a suppression only meant for freshly-created/template schedules that default to "now"). Saved workflows with a future schedule now stay armed when opened.
  • Escape closes any open modal (Templates / My Workflows / Schedules), not just the Schedules dialog.
  • Robust delete detection: deleting the on-disk copy of the currently-open workflow now flags it unsaved even when its id needed sanitizing for the filename.

v0.1.8

  • My Workflows manager: The 📂 Load button now opens an in-app My Workflows browser that lists every saved workflow (with block count and any schedule time), instead of a bare file dialog. Click a row to open it, delete one from disk with its 🗑️ button, start a blank one with + New, or pull a .json from anywhere with 📥 Import file…. The schedule board stays in sync after deletes.
  • Unsaved-changes safety: An amber dot appears next to the workflow name whenever there are unsaved edits, and switching away (opening another workflow, New, a template, or importing a file) now asks before discarding them. Saving, loading, and scheduled runs clear the flag.

v0.1.7

  • Testable scheduling core: The trigger/countdown time math (next-run for once/cron, the due-window check, and countdown formatting) is extracted into a pure, dependency-free schedule.js that takes now as an argument. Behavior is unchanged, but it's now deterministically covered by the headless self-test — once returns the absolute time, cron rolls forward exactly 24h once today's window passes, the grace window fires late-but-not-stale ticks, and countdown formatting clamps/pads/prefixes days. Scheduling regressions now fail npm test.

v0.1.6

  • Live loop progress: While a workflow runs, the active Loop block shows a live iteration badge (e.g. 2/3) that turns green when the loop finishes, and the status line reads 🔄 Loop 2/3. Driven by a new onLoopIteration engine hook, covered by the self-test.
  • Loop grouping visuals: Loop / End Loop markers share a tinted background so the pair reads as brackets, and the connector lines between nested blocks are indented to form a continuous nesting rail down the loop body.
  • Drop-to-position: Dragging a block from the palette now inserts it where you drop it (a glowing insertion line previews the spot) instead of always appending to the end. Dropping a Loop still seeds its matching End Loop at that position.

v0.1.5

  • Loop structure validation in the editor: Unbalanced loop markers (a Loop with no End Loop, or a stray End Loop) are now flagged inline with a dashed warning outline and an explanatory tooltip, plus a summary banner above the block list. The run still proceeds safely (the engine skips broken markers) — the warnings just make the structure obvious while editing.
  • Self-test coverage: The headless npm test now also verifies every shipped template is structurally sound (balanced loops) and checks the unmatched-marker index reporting, so a malformed template or loop-analysis regression fails the build.

v0.1.4

  • Real Loop block: The loop block now actually repeats. It pairs with a new End Loop (loopEnd) block — every block between a Loop and its matching End Loop runs count times. Adding a Loop auto-seeds its End Loop, nested loops are supported, and the loop body is visually indented by nesting depth. Unbalanced markers (a Loop with no End, or a stray End) are skipped with a warning instead of breaking the run.
  • Workflow Templates: A new 🧩 Templates picker offers pre-built starting points (Claude Auto Session, a Loop example, a nightly run + hibernate, and a quick command). Selecting one replaces the current workflow; directory/time placeholders are filled with sensible local defaults and never auto-fire on load.
  • Headless engine self-test: npm test (electron . --self-test) runs the engine's loop control flow in a dry-run mode with no real PTYs, asserts simple/nested/zero-count/unbalanced loop behavior plus the pure loop helpers, and exits non-zero on any regression.

v0.1.3

  • Added a one-click current-time control beside Schedule datetime fields.
  • Marked default/current-minute Schedule targets as handled in the countdown board so they do not appear as immediately due.
  • Preserved manual scheduling behavior: editing a Schedule to a future time still arms it normally.

v0.1.2

  • Default/demo Schedule blocks now display the current local system time immediately.
  • Newly-created Schedule blocks still suppress the just-created current-minute target once, preventing accidental immediate auto-runs while keeping future edits schedulable.

v0.1.1

  • Hardened app shutdown: quitting from the tray now stops the scheduler heartbeat, detaches power monitor listeners, cancels pending hibernate timers, releases the keep-awake blocker, tears down the tray, and terminates tracked PTYs through one idempotent cleanup path.
  • Guarded main-to-renderer IPC sends so process output, process exit, sleep-state, and scheduler heartbeat events do not throw while the renderer is closing.
  • New Schedule blocks now default their datetime-local value to the current local system time at the moment the block is created.
  • Fixed a startup Content Security Policy console error by explicitly allowing local data: images used by CSS controls.
  • Added renderer-side IPC rejection handling for terminal input and resize calls during process teardown.
  • Prevented overlapping scheduled workflow refreshes when renderer ticks and main-process heartbeat ticks arrive close together.
  • Added npm run smoke for a quick Electron startup/shutdown smoke test that exercises the normal quit cleanup path.
  • Ignored local mcps/ tool descriptor caches in Git and packaged builds.

Completed Features

  • Multi-Account Agent Sessions: Several agents run at once, one PTY per account, each with a terminal tab carrying its agent, account name, live status dot, and assurance badge. Hidden sessions keep running and buffering. Routed Codex accounts come from ai-agent-entrypoint; local env-only profiles cover the CLIs it does not manage yet. See "Multi-account agent control" above.
  • Quick Send: A prompt bar under the terminal fires an ad-hoc command at the current session, every session of one agent, or all of them — using the same human-paced typing as the workflow engine.
  • Visual Workflow Builder: Users can construct automation workflows by combining blocks (Schedule, Directory, Agent Session, Send to Agent, Wait for Agent, Command, Wait, Send Input, Keypress, Loop / End Loop, Log, Hibernate PC).
  • Loops: A Loop block repeats every block up to its matching End Loop a configurable number of times. Nested loops are supported and the loop body is indented (with a continuous nesting rail) so the structure is readable at a glance. A live iteration badge (2/3) tracks progress during a run, unbalanced loop markers are flagged inline (dashed outline + tooltip) and summarized in a banner, and the engine still runs safely by skipping broken markers.
  • Drag-to-Position Editing: Blocks dragged from the palette land exactly where they are dropped (with a live insertion-line preview); they can still be reordered afterward by their drag handles.
  • Templates: A 🧩 Templates picker provides pre-built workflows (including a Loop example) as one-click starting points.
  • Persistent Storage: Workflows are saved to and loaded from %APPDATA%/agents-orchestrator/workflows/, with atomic writes and resilient loading so one malformed workflow file does not break the whole schedule list.
  • Workflow Library: A 📂 My Workflows browser lists every saved workflow in-app — open, delete, start a new blank one, or import a .json from disk. An unsaved-changes indicator and a discard prompt prevent accidentally losing edits when switching between workflows.
  • Automated PTY Execution: The engine executes terminal applications in the background using node-pty with modern Windows ConPTY enabled, providing full ANSI color support and proper terminal layout.
  • Dual-Pane Output: The UI features a horizontally resizable right panel split into:
    • Log: A clear visual timeline of automation steps and system messages.
    • Terminal: A tabbed stack of fully interactive xterm.js terminals, one per live session.
  • Theme Switcher: Users can toggle between three terminal themes (PowerShell Blue, Hacker Dark, and Light Mode). The choice is remembered across restarts, along with window geometry and panel sizes.
  • Interactive Terminal: Terminals stay fully interactive. Keystrokes are forwarded via IPC to the PTY behind the visible tab.
  • Process Cleanup: Starting a run closes only the sessions the previous run opened — sessions you started by hand are left alone. Aborting kills every PTY the run spawned, and each kill escalates from SIGTERM to a whole-tree taskkill after a grace window, so a routed shell with an agent child leaves nothing behind.
  • Single-Instance Guard: Electron's single-instance lock prevents duplicate tray apps, duplicate scheduler ticks, and conflicting hibernate timers. Launching a second instance focuses the existing window instead.
  • Input Simulation: Simulates human typing speeds for text input blocks to avoid characters being swallowed by async CLI UI redrawing loops.
  • Scheduled Countdown Board: A ⏱ Schedules panel lists every scheduled workflow (saved on disk + the one being edited), each with a live countdown to its next run. The bottom toolbar always shows "next in HH:MM:SS". Due once jobs auto-run at their time; cron mode repeats daily.
  • Schedule Defaults: Default and newly added Schedule blocks use the current local system time as their trigger time, with a one-click control to reset back to now. Loaded workflows preserve their saved schedule values.
  • Delayed Hibernate (power saving): A 💤 Hibernate PC block arms a delayed system hibernate (shutdown /h) after a configurable delay — e.g. ping an agent, then hibernate to save power once it's done. The timer lives in the main process so it fires reliably even when the window is minimized to the tray or the screen is locked. While armed, a top banner shows a live countdown with a ✕ Cancel hibernate button to force-abort it. Arming is non-blocking, so it can sit at the end of a workflow.
  • Timestamped Logs: Every renderer Log line and every main-process console line is prefixed with an HH:MM:SS.mmm timestamp.
  • Custom App Icon: A real snowflake icon (PNG + multi-size Windows .ico) is used for the window, taskbar, tray, and packaged .exe — no default Electron icon. Regenerate from src/assets/icon-source.png with npm run icons.

Architecture Notes

  • Account routing is delegated, not reimplemented. ai-agent-entrypoint owns the Codex account manifest and child-environment construction; this app discovers its aliases and launches through it. Bringing another CLI under managed routing is a decision for that repository. AGENTS.md records the boundary and the rules the code enforces.
  • Sessions are first class. src/main/sessions.js holds a registry of PTYs, each tagged with its profile and assurance level. It also owns output activity checkpoints and bounded matching buffers for Wait for Agent. Its describe() deliberately omits env, cwd, the resolved executable, and all PTY text, because a routed session's environment and output can contain machine-local paths.
  • Main-process modules are CommonJS and unit-tested (src/main/, tests/*.test.js); renderer modules are ES modules covered by the Electron self-test. Pure logic lives in whichever half can test it deterministically.
  • The renderer (app.js) owns the single, persistent set of process IPC listeners (output/exit/error); the engine reacts via handleProcessExit / handleProcessError hooks rather than registering its own listeners. This avoids the terminal listener being torn down between runs and prevents double-rendered output.
  • Main-process lifecycle cleanup is centralized and idempotent. before-quit and will-quit both run the same shutdown path so timers, power blockers, tray state, and PTYs are cleaned up consistently.
  • mcps/ is treated as a local tool descriptor cache. It is not part of the app source and is ignored by Git and packaged builds.
  • Pure, side-effect-free logic is factored into dependency-free modules so it can be unit-tested deterministically: loop structure (matchingLoopEnd / analyzeLoops in engine.js) and scheduling time math (schedule.js). The headless npm test (electron . --self-test) exercises these with no real PTYs and exits non-zero on regression.

Known Issues & Unfinished Work

  • CLI-specific prompt controls: Highly interactive CLIs can consume the first Enter, so typed submission still uses a deliberate double-tap. When a workflow needs proof of a semantic response, configure Wait for Agent with Output contains; idle-only completion observes silence, not success.
  • Terminal Layout Shifts: Xterm dimensions may occasionally desync with the internal PTY dimensions if the window is resized very rapidly while a process is initializing.

Development

# Install dependencies
npm install

# Run locally
npm start

# Syntax-check every JavaScript file under the source roots
npm run check

# Run a quick Electron startup/shutdown smoke test
npm run smoke

# Run both suites: main-process unit tests + the headless renderer self-test
npm test

# Either half on its own
npm run test:unit   # node --test over src/main/
npm run test:app    # electron . --self-test

# Regenerate icon assets (icon.png + icon.ico) from src/assets/icon-source.png
npm run icons

# Build for Windows x64 (embeds icon.ico into the .exe)
npm run build

About

Visual AI Agent automation orchestrator — block-based CLI workflow scheduler with an embedded PTY terminal (Electron)

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages