@olhapi/maestro 0.1.5-rc.14 → 0.1.5-rc.15
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/README.md +15 -51
- package/bin/maestro.js +20 -9
- package/lib/get-exe-path.js +118 -0
- package/package.json +11 -15
- package/bin/maestro +0 -16
- package/bin/maestro.cmd +0 -8
- package/bin/maestro.ps1 +0 -4
- package/lib/browser.js +0 -79
- package/lib/cli.js +0 -306
- package/lib/docker-plan.js +0 -941
- package/lib/install-skills.js +0 -110
- package/lib/runtime-state.js +0 -82
- package/share/skills/maestro/SKILL.md +0 -38
- package/share/skills/maestro/references/operations.md +0 -21
- package/share/skills/maestro/references/project-work.md +0 -44
- package/share/skills/maestro/references/readiness.md +0 -18
- package/share/skills/maestro/references/setup.md +0 -45
package/lib/install-skills.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
const fs = require("node:fs");
|
|
2
|
-
const os = require("node:os");
|
|
3
|
-
const path = require("node:path");
|
|
4
|
-
|
|
5
|
-
const maestroSkillName = "maestro";
|
|
6
|
-
|
|
7
|
-
function bundledSkillDir(baseDir = path.join(__dirname, "..")) {
|
|
8
|
-
const packagedPath = path.join(baseDir, "share", "skills", maestroSkillName);
|
|
9
|
-
if (fs.existsSync(packagedPath)) {
|
|
10
|
-
return packagedPath;
|
|
11
|
-
}
|
|
12
|
-
return path.resolve(baseDir, "..", "..", "..", "skills", maestroSkillName);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function bundledSkillPaths(options = {}) {
|
|
16
|
-
const fsModule = options.fs || fs;
|
|
17
|
-
const root = bundledSkillDir(options.baseDir);
|
|
18
|
-
const paths = [];
|
|
19
|
-
|
|
20
|
-
walkFiles(root, root, fsModule, (relativePath) => {
|
|
21
|
-
paths.push(relativePath);
|
|
22
|
-
});
|
|
23
|
-
return paths.sort();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function readBundledSkillFile(relativePath, options = {}) {
|
|
27
|
-
const fsModule = options.fs || fs;
|
|
28
|
-
return fsModule.readFileSync(path.join(bundledSkillDir(options.baseDir), relativePath));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function installBundledSkills(options = {}) {
|
|
32
|
-
const homeDir = options.homeDir || os.homedir();
|
|
33
|
-
const targets = options.targets || [
|
|
34
|
-
path.join(homeDir, ".agents", "skills", maestroSkillName),
|
|
35
|
-
path.join(homeDir, ".claude", "skills", maestroSkillName),
|
|
36
|
-
];
|
|
37
|
-
const sourceRoot = bundledSkillDir(options.baseDir);
|
|
38
|
-
const fsModule = options.fs || fs;
|
|
39
|
-
|
|
40
|
-
for (const target of targets) {
|
|
41
|
-
installTree(sourceRoot, target, fsModule);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return targets;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function installTree(sourceRoot, dest, fsModule) {
|
|
48
|
-
const parent = path.dirname(dest);
|
|
49
|
-
fsModule.mkdirSync(parent, { recursive: true });
|
|
50
|
-
|
|
51
|
-
const tmpDir = fsModule.mkdtempSync(path.join(parent, `.${path.basename(dest)}.tmp-`));
|
|
52
|
-
try {
|
|
53
|
-
copyTree(sourceRoot, tmpDir, fsModule);
|
|
54
|
-
|
|
55
|
-
const backupDir = `${dest}.bak`;
|
|
56
|
-
fsModule.rmSync(backupDir, { force: true, recursive: true });
|
|
57
|
-
let hadBackup = false;
|
|
58
|
-
if (fsModule.existsSync(dest)) {
|
|
59
|
-
fsModule.renameSync(dest, backupDir);
|
|
60
|
-
hadBackup = true;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
try {
|
|
64
|
-
fsModule.renameSync(tmpDir, dest);
|
|
65
|
-
} catch (error) {
|
|
66
|
-
if (hadBackup) {
|
|
67
|
-
try {
|
|
68
|
-
fsModule.renameSync(backupDir, dest);
|
|
69
|
-
} catch (restoreError) {
|
|
70
|
-
throw new Error(`install bundled skill: ${error.message} (failed to restore previous install: ${restoreError.message})`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
throw new Error(`install bundled skill: ${error.message}`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
fsModule.rmSync(backupDir, { force: true, recursive: true });
|
|
77
|
-
} finally {
|
|
78
|
-
fsModule.rmSync(tmpDir, { force: true, recursive: true });
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function copyTree(sourceRoot, destRoot, fsModule) {
|
|
83
|
-
walkFiles(sourceRoot, sourceRoot, fsModule, (relativePath, sourcePath, stat) => {
|
|
84
|
-
const targetPath = path.join(destRoot, relativePath);
|
|
85
|
-
fsModule.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
86
|
-
const mode = stat.mode & 0o111 ? 0o755 : 0o644;
|
|
87
|
-
fsModule.writeFileSync(targetPath, fsModule.readFileSync(sourcePath), { mode });
|
|
88
|
-
fsModule.chmodSync(targetPath, mode);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function walkFiles(root, currentRoot, fsModule, visitor) {
|
|
93
|
-
const entries = fsModule.readdirSync(currentRoot, { withFileTypes: true });
|
|
94
|
-
for (const entry of entries) {
|
|
95
|
-
const absolutePath = path.join(currentRoot, entry.name);
|
|
96
|
-
if (entry.isDirectory()) {
|
|
97
|
-
walkFiles(root, absolutePath, fsModule, visitor);
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
const relativePath = path.relative(root, absolutePath);
|
|
101
|
-
visitor(relativePath, absolutePath, fsModule.statSync(absolutePath));
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
module.exports = {
|
|
106
|
-
bundledSkillDir,
|
|
107
|
-
bundledSkillPaths,
|
|
108
|
-
installBundledSkills,
|
|
109
|
-
readBundledSkillFile,
|
|
110
|
-
};
|
package/lib/runtime-state.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
const fs = require("node:fs");
|
|
2
|
-
const os = require("node:os");
|
|
3
|
-
const path = require("node:path");
|
|
4
|
-
|
|
5
|
-
const DEFAULT_IMAGE_REPOSITORY = "ghcr.io/olhapi/maestro";
|
|
6
|
-
|
|
7
|
-
function sanitizeVersion(version) {
|
|
8
|
-
return String(version || "").trim().replace(/^v/, "");
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function launcherDir(homeDir = os.homedir()) {
|
|
12
|
-
return path.join(homeDir, ".maestro", "launcher");
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function runtimeStatePath(homeDir = os.homedir()) {
|
|
16
|
-
return path.join(launcherDir(homeDir), "runtime.json");
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function imageRefForVersion(version, imageRepository = DEFAULT_IMAGE_REPOSITORY) {
|
|
20
|
-
const tag = sanitizeVersion(version);
|
|
21
|
-
if (!tag) {
|
|
22
|
-
throw new Error("image version is required");
|
|
23
|
-
}
|
|
24
|
-
return `${imageRepository}:${tag}`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function readRuntimeState(options = {}) {
|
|
28
|
-
const fsModule = options.fs || fs;
|
|
29
|
-
const homeDir = options.homeDir || os.homedir();
|
|
30
|
-
const statePath = runtimeStatePath(homeDir);
|
|
31
|
-
if (!fsModule.existsSync(statePath)) {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
const raw = fsModule.readFileSync(statePath, "utf8");
|
|
35
|
-
const parsed = JSON.parse(raw);
|
|
36
|
-
if (!parsed || typeof parsed !== "object" || typeof parsed.image !== "string") {
|
|
37
|
-
throw new Error(`invalid runtime state at ${statePath}`);
|
|
38
|
-
}
|
|
39
|
-
return parsed;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function writeRuntimeState(image, options = {}) {
|
|
43
|
-
const fsModule = options.fs || fs;
|
|
44
|
-
const homeDir = options.homeDir || os.homedir();
|
|
45
|
-
const statePath = runtimeStatePath(homeDir);
|
|
46
|
-
fsModule.mkdirSync(path.dirname(statePath), { recursive: true });
|
|
47
|
-
const payload = {
|
|
48
|
-
image,
|
|
49
|
-
updated_at: new Date().toISOString(),
|
|
50
|
-
};
|
|
51
|
-
fsModule.writeFileSync(statePath, `${JSON.stringify(payload, null, 2)}\n`);
|
|
52
|
-
return payload;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function resolveImageRef(options = {}) {
|
|
56
|
-
const env = options.env || process.env;
|
|
57
|
-
const runtimeState = options.runtimeState === undefined ? readRuntimeState(options) : options.runtimeState;
|
|
58
|
-
const packageVersion = sanitizeVersion(options.packageVersion);
|
|
59
|
-
const imageRepository = options.imageRepository || DEFAULT_IMAGE_REPOSITORY;
|
|
60
|
-
|
|
61
|
-
if (typeof env.MAESTRO_IMAGE === "string" && env.MAESTRO_IMAGE.trim() !== "") {
|
|
62
|
-
return env.MAESTRO_IMAGE.trim();
|
|
63
|
-
}
|
|
64
|
-
if (runtimeState && typeof runtimeState.image === "string" && runtimeState.image.trim() !== "") {
|
|
65
|
-
return runtimeState.image.trim();
|
|
66
|
-
}
|
|
67
|
-
if (!packageVersion) {
|
|
68
|
-
throw new Error("package version is required to resolve the default runtime image");
|
|
69
|
-
}
|
|
70
|
-
return imageRefForVersion(packageVersion, imageRepository);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
module.exports = {
|
|
74
|
-
DEFAULT_IMAGE_REPOSITORY,
|
|
75
|
-
imageRefForVersion,
|
|
76
|
-
launcherDir,
|
|
77
|
-
readRuntimeState,
|
|
78
|
-
resolveImageRef,
|
|
79
|
-
runtimeStatePath,
|
|
80
|
-
sanitizeVersion,
|
|
81
|
-
writeRuntimeState,
|
|
82
|
-
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: maestro
|
|
3
|
-
description: Use Maestro to initialize workflows, run the local loop, bridge MCP, and manage projects, epics, issues, and readiness checks.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Maestro CLI Skill
|
|
7
|
-
|
|
8
|
-
Use this skill when a task involves Maestro's local orchestration flow, repo setup, queue management, or readiness checks.
|
|
9
|
-
|
|
10
|
-
## Prefer Maestro when
|
|
11
|
-
|
|
12
|
-
- You need to create or refresh `WORKFLOW.md`.
|
|
13
|
-
- You want to start or supervise the local daemon.
|
|
14
|
-
- You need to connect another agent to the live queue through MCP.
|
|
15
|
-
- You are creating, updating, moving, or inspecting projects, epics, or issues.
|
|
16
|
-
- You want to verify repo readiness before launch.
|
|
17
|
-
|
|
18
|
-
## Start with the smallest command that fits
|
|
19
|
-
|
|
20
|
-
- `maestro workflow init .` for repo bootstrap.
|
|
21
|
-
- `maestro run` for the local loop and dashboard.
|
|
22
|
-
- `maestro mcp` only after the daemon is already running.
|
|
23
|
-
- `maestro verify`, `maestro doctor`, or `maestro spec-check` for readiness and validation.
|
|
24
|
-
|
|
25
|
-
## Common flows
|
|
26
|
-
|
|
27
|
-
- Setup and launch: see [setup](references/setup.md)
|
|
28
|
-
- Day-to-day operations: see [operations](references/operations.md)
|
|
29
|
-
- Projects and issues: see [project-work](references/project-work.md)
|
|
30
|
-
- Readiness checks: see [readiness](references/readiness.md)
|
|
31
|
-
|
|
32
|
-
## Working style
|
|
33
|
-
|
|
34
|
-
- Prefer exact, repo-local commands over generic advice.
|
|
35
|
-
- Keep changes scoped to the issue or project being worked.
|
|
36
|
-
- Use `--json` when the output will feed another tool or agent.
|
|
37
|
-
- Reuse the live daemon and existing workflow file before inventing a new setup.
|
|
38
|
-
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Operations
|
|
2
|
-
|
|
3
|
-
Use these commands when the daemon is running and you want to inspect or steer live work.
|
|
4
|
-
|
|
5
|
-
## Status and runtime
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
maestro status
|
|
9
|
-
maestro status --dashboard --api-url http://127.0.0.1:8787
|
|
10
|
-
maestro sessions --api-url http://127.0.0.1:8787
|
|
11
|
-
maestro events --api-url http://127.0.0.1:8787
|
|
12
|
-
maestro runtime-series --api-url http://127.0.0.1:8787
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## When to use
|
|
16
|
-
|
|
17
|
-
- Use `status` for a quick health check.
|
|
18
|
-
- Use `sessions` when multiple runs are in flight.
|
|
19
|
-
- Use `events` when you need a recent timeline of what happened.
|
|
20
|
-
- Use `runtime-series` when you need token or activity trends over time.
|
|
21
|
-
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# Projects and issues
|
|
2
|
-
|
|
3
|
-
Use these commands for the local queue and issue lifecycle.
|
|
4
|
-
|
|
5
|
-
## Projects
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
maestro project create <name> --repo <repo_path>
|
|
9
|
-
maestro project list
|
|
10
|
-
maestro project show <id>
|
|
11
|
-
maestro project update <id>
|
|
12
|
-
maestro project delete <id>
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Epics
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
maestro epic create <name> --project <project_id>
|
|
19
|
-
maestro epic list
|
|
20
|
-
maestro epic show <id>
|
|
21
|
-
maestro epic update <id>
|
|
22
|
-
maestro epic delete <id>
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Issues
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
maestro issue create <title>
|
|
29
|
-
maestro issue list
|
|
30
|
-
maestro issue show <identifier>
|
|
31
|
-
maestro issue update <identifier>
|
|
32
|
-
maestro issue move <identifier> <state>
|
|
33
|
-
maestro issue block <identifier> <blocker_identifier...>
|
|
34
|
-
maestro issue unblock <identifier> <blocker_identifier...>
|
|
35
|
-
maestro issue comments list <identifier>
|
|
36
|
-
maestro issue assets add <identifier> <path>
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Guidance
|
|
40
|
-
|
|
41
|
-
- Use `--project` and labels to keep work scoped.
|
|
42
|
-
- Use `move` when you need to change queue state, not when you only want to update metadata.
|
|
43
|
-
- Use comments and assets for review context rather than burying details in the issue title.
|
|
44
|
-
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# Readiness
|
|
2
|
-
|
|
3
|
-
Use these commands before launch or when the repo needs a sanity check.
|
|
4
|
-
|
|
5
|
-
## Validation commands
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
maestro verify
|
|
9
|
-
maestro doctor
|
|
10
|
-
maestro spec-check
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Guidance
|
|
14
|
-
|
|
15
|
-
- Use `verify` when you want the normal readiness check and remediation guidance.
|
|
16
|
-
- Use `doctor` when you want the same checks with a different presentation.
|
|
17
|
-
- Use `spec-check` when you want a read-only validation pass.
|
|
18
|
-
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# Setup
|
|
2
|
-
|
|
3
|
-
Use these commands when you are preparing a repo or teaching another agent how to connect to Maestro.
|
|
4
|
-
|
|
5
|
-
## Bundle install
|
|
6
|
-
|
|
7
|
-
Install the Maestro skill bundle into the current user's personal skill directories:
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
maestro install --skills
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
The installer writes the skill to:
|
|
14
|
-
|
|
15
|
-
- `~/.agents/skills/maestro` for Codex
|
|
16
|
-
- `~/.claude/skills/maestro` for Claude Code
|
|
17
|
-
|
|
18
|
-
## Workflow bootstrap
|
|
19
|
-
|
|
20
|
-
Create or refresh the repo contract:
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
maestro workflow init .
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Use `--defaults` when you want the non-interactive scaffold. Use `--force` only when overwriting an existing file is intentional.
|
|
27
|
-
|
|
28
|
-
## Launch the loop
|
|
29
|
-
|
|
30
|
-
Start the daemon after the workflow file is in place:
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
maestro run
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Attach MCP
|
|
37
|
-
|
|
38
|
-
Bridge the live daemon over stdio for a connected coding agent:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
maestro mcp
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Start `maestro run` first, then point the agent at the same database.
|
|
45
|
-
|