@adaptic/maestro 1.1.5 → 1.1.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptic/maestro",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "Maestro — Autonomous AI agent operating system. Deploy AI employees on dedicated Mac minis.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,85 @@
1
+ #!/bin/bash
2
+ # =============================================================================
3
+ # boot-claude-session.sh — Launch interactive Claude Code session on boot
4
+ # =============================================================================
5
+ #
6
+ # Opens Terminal.app with a Claude Code interactive session in the agent's
7
+ # working directory. Called via launchd at login.
8
+ #
9
+ # This is separate from the sophie-daemon (which runs headless as a Node.js
10
+ # process for polling/dispatching). This script provides a visible, interactive
11
+ # Claude Code session that the operator can observe and interact with.
12
+ #
13
+ # Usage:
14
+ # ./scripts/setup/boot-claude-session.sh [agent-dir]
15
+ #
16
+ # =============================================================================
17
+
18
+ set -euo pipefail
19
+
20
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
+ MAESTRO_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
22
+
23
+ # Detect agent directory — prefer sophie-ai if it exists
24
+ AGENT_DIR="${1:?Agent directory required as first argument (e.g. ~/sophie-ai)}"
25
+ if [ ! -d "$AGENT_DIR" ]; then
26
+ echo "ERROR: Agent directory does not exist: $AGENT_DIR" >&2
27
+ exit 1
28
+ fi
29
+
30
+ AGENT_NAME=$(basename "$AGENT_DIR")
31
+ LOG_FILE="$MAESTRO_DIR/logs/watchdog/$(date +%Y-%m-%d)-boot-session.log"
32
+ mkdir -p "$(dirname "$LOG_FILE")"
33
+
34
+ log() {
35
+ echo "[$(date -u +"%Y-%m-%dT%H:%M:%SZ")] $1" | tee -a "$LOG_FILE"
36
+ }
37
+
38
+ # Wait for the system to settle after login (network, services, etc.)
39
+ log "Waiting 15s for system to settle..."
40
+ sleep 15
41
+
42
+ # Check for emergency stop
43
+ if [ -f "$AGENT_DIR/.emergency-stop" ]; then
44
+ log "Emergency stop active — not starting Claude session"
45
+ exit 0
46
+ fi
47
+
48
+ if [ -f "$MAESTRO_DIR/.emergency-stop" ]; then
49
+ log "Emergency stop active in maestro — not starting Claude session"
50
+ exit 0
51
+ fi
52
+
53
+ # Check if claude CLI is available
54
+ if ! command -v claude &>/dev/null; then
55
+ # Try common paths
56
+ CLAUDE_PATH=""
57
+ for p in "$HOME/.local/bin/claude" "/opt/homebrew/bin/claude" "/usr/local/bin/claude"; do
58
+ if [ -x "$p" ]; then
59
+ CLAUDE_PATH="$p"
60
+ break
61
+ fi
62
+ done
63
+
64
+ if [ -z "$CLAUDE_PATH" ]; then
65
+ log "ERROR: claude CLI not found"
66
+ exit 1
67
+ fi
68
+ else
69
+ CLAUDE_PATH=$(which claude)
70
+ fi
71
+
72
+ log "Starting Claude Code session in $AGENT_DIR (claude: $CLAUDE_PATH)"
73
+
74
+ # Open Terminal.app with Claude Code running in the agent directory
75
+ osascript <<APPLESCRIPT
76
+ tell application "Terminal"
77
+ activate
78
+ -- Open a new window with claude running in the agent directory
79
+ do script "cd '$AGENT_DIR' && clear && echo '╔══════════════════════════════════════════════════════════╗' && echo '║ Sophie AI — Boot Session ($(date +%Y-%m-%d)) ║' && echo '╠══════════════════════════════════════════════════════════╣' && echo '║ Agent dir: $AGENT_DIR' && echo '║ Claude: $CLAUDE_PATH' && echo '╚══════════════════════════════════════════════════════════╝' && echo '' && '$CLAUDE_PATH'"
80
+ -- Set the window title
81
+ set custom title of front window to "$AGENT_NAME — Claude Code"
82
+ end tell
83
+ APPLESCRIPT
84
+
85
+ log "Terminal window opened with Claude Code session"
@@ -29,6 +29,10 @@ AGENT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
29
29
  AGENT_NAME=$(basename "$AGENT_DIR")
30
30
  CURRENT_USER=$(whoami)
31
31
 
32
+ # The directory from which this script was invoked — used as the boot-time
33
+ # Claude Code working directory (e.g. ~/sophie-ai, ~/wundr, etc.)
34
+ CALLER_DIR="${PWD}"
35
+
32
36
  # Colours
33
37
  RED='\033[0;31m'
34
38
  GREEN='\033[0;32m'
@@ -70,6 +74,32 @@ configure_auto_login() {
70
74
  defaults write com.apple.loginwindow LoginwindowLaunchesRelaunchApps -bool false
71
75
 
72
76
  ok "Auto-login enabled for $SUDO_USER"
77
+
78
+ # --- Disable all password gates that could block unattended operation -------
79
+ local real_home
80
+ real_home=$(eval echo "~$SUDO_USER")
81
+
82
+ # Disable "Require password after sleep or screen saver"
83
+ sudo -u "$SUDO_USER" defaults write com.apple.screensaver askForPassword -int 0
84
+ sudo -u "$SUDO_USER" defaults write com.apple.screensaver askForPasswordDelay -int 0
85
+ ok "Screen saver password prompt disabled"
86
+
87
+ # Disable screen lock via sysadminctl
88
+ sysadminctl -screenLock off 2>/dev/null || true
89
+ ok "Screen lock disabled"
90
+
91
+ # Disable idle logout (Privacy & Security > Log out when idle)
92
+ defaults write /Library/Preferences/.GlobalPreferences com.apple.autologout.AutoLogOutDelay -int 0
93
+ ok "Idle auto-logout disabled"
94
+
95
+ # Disable screen lock on wake for current user
96
+ sudo -u "$SUDO_USER" defaults -currentHost write com.apple.screensaver idleTime -int 0
97
+ ok "Screen saver idle timer set to never"
98
+
99
+ # Prevent display from sleeping and requiring login on wake
100
+ # (already handled by pmset displaysleep 0, but belt-and-suspenders)
101
+ defaults write /Library/Preferences/com.apple.loginwindow DisableScreenLock -bool true 2>/dev/null || true
102
+
73
103
  warn "NOTE: FileVault must be disabled for auto-login to work"
74
104
  warn "Check: fdesetup status"
75
105
 
@@ -304,6 +334,64 @@ configure_app_launches() {
304
334
  chown "$real_user:staff" "$d" 2>/dev/null || true
305
335
  done
306
336
  ok "Log and state directories verified (owned by $real_user)"
337
+
338
+ # --- Claude Code boot session (opens Terminal with interactive claude) ------
339
+ local BOOT_SCRIPT="$AGENT_DIR/scripts/setup/boot-claude-session.sh"
340
+ if [ -f "$BOOT_SCRIPT" ]; then
341
+ chmod +x "$BOOT_SCRIPT"
342
+
343
+ local PLIST_NAME="ai.maestro.boot-claude-session"
344
+ local PLIST_PATH="$real_home/Library/LaunchAgents/${PLIST_NAME}.plist"
345
+ local real_home
346
+ real_home=$(eval echo "~$real_user")
347
+
348
+ # Use the directory from which configure-macos.sh was invoked
349
+ local boot_agent_dir="$CALLER_DIR"
350
+
351
+ cat > "$PLIST_PATH" << PLIST_EOF
352
+ <?xml version="1.0" encoding="UTF-8"?>
353
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
354
+ <plist version="1.0">
355
+ <dict>
356
+ <key>Label</key>
357
+ <string>${PLIST_NAME}</string>
358
+ <key>ProgramArguments</key>
359
+ <array>
360
+ <string>/bin/bash</string>
361
+ <string>${BOOT_SCRIPT}</string>
362
+ <string>${boot_agent_dir}</string>
363
+ </array>
364
+ <key>RunAtLoad</key>
365
+ <true/>
366
+ <key>StandardOutPath</key>
367
+ <string>${AGENT_DIR}/logs/watchdog/boot-session-stdout.log</string>
368
+ <key>StandardErrorPath</key>
369
+ <string>${AGENT_DIR}/logs/watchdog/boot-session-stderr.log</string>
370
+ <key>EnvironmentVariables</key>
371
+ <dict>
372
+ <key>PATH</key>
373
+ <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:${real_home}/.local/bin</string>
374
+ <key>HOME</key>
375
+ <string>${real_home}</string>
376
+ </dict>
377
+ </dict>
378
+ </plist>
379
+ PLIST_EOF
380
+
381
+ chown "$real_user:staff" "$PLIST_PATH" 2>/dev/null || true
382
+
383
+ # Load as the real user
384
+ if [ "$(id -u)" -eq 0 ]; then
385
+ su "$real_user" -c "launchctl unload '$PLIST_PATH' 2>/dev/null; launchctl load '$PLIST_PATH'" 2>/dev/null || true
386
+ else
387
+ launchctl unload "$PLIST_PATH" 2>/dev/null || true
388
+ launchctl load "$PLIST_PATH" 2>/dev/null || true
389
+ fi
390
+
391
+ ok "Claude Code boot session agent installed (opens Terminal + claude on login)"
392
+ else
393
+ warn "Boot session script not found at $BOOT_SCRIPT"
394
+ fi
307
395
  }
308
396
 
309
397
  # =============================================================================
@@ -533,7 +621,8 @@ main() {
533
621
  echo "╔══════════════════════════════════════════════════════════════╗"
534
622
  echo "║ Maestro — Mac Mini Configuration ║"
535
623
  echo "╠══════════════════════════════════════════════════════════════╣"
536
- echo "║ Agent directory: $AGENT_DIR"
624
+ echo "║ Maestro: $AGENT_DIR"
625
+ echo "║ Boot target: $CALLER_DIR"
537
626
  echo "║ Current user: $CURRENT_USER"
538
627
  echo "╚══════════════════════════════════════════════════════════════╝"
539
628
 
@@ -30,6 +30,10 @@ MAESTRO_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
30
30
  # The watchdog runs from maestro but protects the whole machine
31
31
  AGENT_DIR="${AGENT_DIR:-}"
32
32
 
33
+ # --- Ensure system paths are available ----------------------------------------
34
+ # launchd PATH may not include /usr/sbin where sysctl lives
35
+ export PATH="/usr/sbin:/usr/bin:/bin:/usr/local/bin:/opt/homebrew/bin:$PATH"
36
+
33
37
  # --- Configuration -----------------------------------------------------------
34
38
 
35
39
  # Total physical RAM in KB