@adaptic/maestro 1.9.1 → 1.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +21 -3
- package/bin/maestro.mjs +37 -0
- package/package.json +1 -1
- package/scripts/daemon/cadence-consumer.mjs +14 -0
package/.env.example
CHANGED
|
@@ -16,11 +16,29 @@
|
|
|
16
16
|
# The agent's reasoning engines. At minimum you need Anthropic (Claude).
|
|
17
17
|
#
|
|
18
18
|
|
|
19
|
-
# REQUIRED — Primary reasoning engine
|
|
20
|
-
#
|
|
21
|
-
#
|
|
19
|
+
# REQUIRED — Primary reasoning engine. Two ways to authenticate:
|
|
20
|
+
#
|
|
21
|
+
# Option A — API key (pay-per-token)
|
|
22
|
+
# Set ANTHROPIC_API_KEY below to a valid sk-ant-api03-... key.
|
|
23
|
+
# Get one: https://console.anthropic.com/settings/keys
|
|
24
|
+
#
|
|
25
|
+
# Option B — Claude Code subscription (Pro/Max, OAuth via Keychain)
|
|
26
|
+
# LEAVE ANTHROPIC_API_KEY EMPTY *and* set MAESTRO_PREFER_SUBSCRIPTION_AUTH=1.
|
|
27
|
+
# This tells the cadence consumer to strip ANTHROPIC_API_KEY from every
|
|
28
|
+
# sub-session spawn so claude --print falls back to the keychain OAuth
|
|
29
|
+
# token. Most agents on a Mac mini with a Claude Code subscription
|
|
30
|
+
# should use this option — routine cadence ticks cost zero API credits.
|
|
31
|
+
#
|
|
32
|
+
# Doctor validates the key against api.anthropic.com on every run; an
|
|
33
|
+
# invalid key here will cascade 401s through every sub-session spawn.
|
|
22
34
|
ANTHROPIC_API_KEY=
|
|
23
35
|
|
|
36
|
+
# OPTIONAL — When set to 1, the cadence consumer strips ANTHROPIC_API_KEY
|
|
37
|
+
# from every claude --print sub-session env so claude falls back to
|
|
38
|
+
# Claude Code subscription auth (Keychain OAuth). Use this when the
|
|
39
|
+
# agent's Mac has a Claude Code Pro/Max subscription.
|
|
40
|
+
MAESTRO_PREFER_SUBSCRIPTION_AUTH=
|
|
41
|
+
|
|
24
42
|
# OPTIONAL — Supplemental model access (GPT-4, embeddings)
|
|
25
43
|
# Get your key: https://platform.openai.com/api-keys
|
|
26
44
|
# Subscription: OpenAI API plan (pay-per-token)
|
package/bin/maestro.mjs
CHANGED
|
@@ -1462,6 +1462,43 @@ function doctor() {
|
|
|
1462
1462
|
check("ANTHROPIC_API_KEY", true);
|
|
1463
1463
|
check("SLACK_USER_TOKEN", false);
|
|
1464
1464
|
check("GMAIL_APP_PASSWORD", false);
|
|
1465
|
+
|
|
1466
|
+
// Auth validity: if ANTHROPIC_API_KEY is set, ping the API to
|
|
1467
|
+
// verify it works. An invalid key in .env will silently be sent
|
|
1468
|
+
// to every `claude --print` sub-session and cause cascading 401s
|
|
1469
|
+
// (exactly the ravi-ai inbox-processor runaway). Better to catch
|
|
1470
|
+
// it here. Skips the check if the user opted out via
|
|
1471
|
+
// MAESTRO_PREFER_SUBSCRIPTION_AUTH=1 (subscription wins).
|
|
1472
|
+
const keyMatch = env.match(/^ANTHROPIC_API_KEY=(.+)$/m);
|
|
1473
|
+
const preferSubsMatch = env.match(/^MAESTRO_PREFER_SUBSCRIPTION_AUTH=(.+)$/m);
|
|
1474
|
+
const preferSubs = preferSubsMatch && /^1|true|yes$/i.test(preferSubsMatch[1].trim());
|
|
1475
|
+
if (keyMatch && !preferSubs) {
|
|
1476
|
+
const key = keyMatch[1].trim().replace(/^"|"$/g, "");
|
|
1477
|
+
try {
|
|
1478
|
+
const result = spawnSync("curl", [
|
|
1479
|
+
"-s", "-o", "/dev/null", "-w", "%{http_code}",
|
|
1480
|
+
"-X", "POST",
|
|
1481
|
+
"-H", `x-api-key: ${key}`,
|
|
1482
|
+
"-H", "anthropic-version: 2023-06-01",
|
|
1483
|
+
"-H", "content-type: application/json",
|
|
1484
|
+
"--max-time", "8",
|
|
1485
|
+
"https://api.anthropic.com/v1/messages",
|
|
1486
|
+
"-d", JSON.stringify({ model: "claude-haiku-4-5", max_tokens: 5, messages: [{ role: "user", content: "ping" }] }),
|
|
1487
|
+
], { encoding: "utf-8" });
|
|
1488
|
+
const code = (result.stdout || "").trim();
|
|
1489
|
+
if (code === "200") ok("ANTHROPIC_API_KEY validated against api.anthropic.com");
|
|
1490
|
+
else if (code === "401") {
|
|
1491
|
+
warn(`ANTHROPIC_API_KEY is INVALID (HTTP 401 from api.anthropic.com).`);
|
|
1492
|
+
warn(` This will cause every sub-session spawn to fail. Either:`);
|
|
1493
|
+
warn(` 1. Replace the key in .env with a valid one, OR`);
|
|
1494
|
+
warn(` 2. Set MAESTRO_PREFER_SUBSCRIPTION_AUTH=1 in .env to use Claude Code subscription auth.`);
|
|
1495
|
+
issues++;
|
|
1496
|
+
} else if (code) warn(`ANTHROPIC_API_KEY check returned HTTP ${code} (expected 200)`);
|
|
1497
|
+
else warn(`ANTHROPIC_API_KEY check skipped (no network / curl missing)`);
|
|
1498
|
+
} catch { warn("ANTHROPIC_API_KEY check failed (curl error)"); }
|
|
1499
|
+
} else if (preferSubs) {
|
|
1500
|
+
ok("MAESTRO_PREFER_SUBSCRIPTION_AUTH=1 — using Claude Code subscription (Keychain OAuth)");
|
|
1501
|
+
}
|
|
1465
1502
|
} else {
|
|
1466
1503
|
fail(".env file not found — copy from .env.example");
|
|
1467
1504
|
issues++;
|
package/package.json
CHANGED
|
@@ -183,6 +183,20 @@ function realSpawnSession({ agentRoot, cadence, promptPath, timeoutMs, log }) {
|
|
|
183
183
|
AGENT_DIR: agentRoot,
|
|
184
184
|
PATH: augmentedPath,
|
|
185
185
|
};
|
|
186
|
+
// Auth handling. Claude Code authenticates via macOS Keychain
|
|
187
|
+
// (OAuth from the user's Pro/Max subscription) when no API key is
|
|
188
|
+
// set, OR via the ANTHROPIC_API_KEY env var when one is present.
|
|
189
|
+
// If the env key is present BUT looks like a placeholder / empty
|
|
190
|
+
// string, we strip it so claude can fall back to Keychain OAuth.
|
|
191
|
+
// Set MAESTRO_PREFER_SUBSCRIPTION_AUTH=1 in .env to always strip
|
|
192
|
+
// the API key (force subscription auth) — useful when the agent
|
|
193
|
+
// owns a Claude Code Pro/Max subscription and shouldn't burn API
|
|
194
|
+
// credits for routine ticks.
|
|
195
|
+
const preferSubscription = process.env.MAESTRO_PREFER_SUBSCRIPTION_AUTH === "1";
|
|
196
|
+
const apiKey = env.ANTHROPIC_API_KEY || "";
|
|
197
|
+
if (preferSubscription || !apiKey.trim() || /^(your-api-key|placeholder|xxx+|sk-ant-xxx)/i.test(apiKey)) {
|
|
198
|
+
delete env.ANTHROPIC_API_KEY;
|
|
199
|
+
}
|
|
186
200
|
const started = Date.now();
|
|
187
201
|
|
|
188
202
|
// Per-run log file. Pattern is short enough to be tail-friendly.
|