@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 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 (Claude Code uses this)
20
- # Get your key: https://console.anthropic.com/settings/keys
21
- # Subscription: Anthropic API plan (pay-per-token) or Max subscription
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptic/maestro",
3
- "version": "1.9.1",
3
+ "version": "1.9.2",
4
4
  "description": "Maestro — Autonomous AI agent operating system. Deploy AI employees on dedicated Mac minis.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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.