@adaptic/maestro 1.8.1 → 1.8.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/package.json
CHANGED
|
@@ -10,13 +10,14 @@
|
|
|
10
10
|
// Install: launchd plist with KeepAlive: true
|
|
11
11
|
// =============================================================================
|
|
12
12
|
|
|
13
|
-
// The core daemon implementation
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
13
|
+
// The core daemon implementation is in sophie-daemon.mjs by default, but
|
|
14
|
+
// older agent repos may have a renamed copy at <firstname>-daemon.mjs (a
|
|
15
|
+
// pre-1.7 convention). This entry-point auto-detects the correct file so
|
|
16
|
+
// the launchd plist stays stable regardless of agent identity history.
|
|
17
17
|
|
|
18
|
-
import { resolve, dirname } from "node:path";
|
|
18
|
+
import { resolve, dirname, join } from "node:path";
|
|
19
19
|
import { fileURLToPath } from "node:url";
|
|
20
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
20
21
|
|
|
21
22
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
22
23
|
const AGENT_DIR = process.env.AGENT_DIR || resolve(__dirname, "../..");
|
|
@@ -54,5 +55,43 @@ try {
|
|
|
54
55
|
// Reactive daemon continues. Doctor / healthcheck will surface this.
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
//
|
|
58
|
-
|
|
58
|
+
// Locate the core daemon module. Try, in order:
|
|
59
|
+
// 1. ./sophie-daemon.mjs — canonical filename (post-Phase-2.5 SOT)
|
|
60
|
+
// 2. ./<firstName>-daemon.mjs — legacy rename from init-maestro Phase 1
|
|
61
|
+
// 3. The first scripts/daemon/*-daemon.mjs that isn't this file
|
|
62
|
+
function resolveCoreDaemon() {
|
|
63
|
+
const localCandidates = [];
|
|
64
|
+
const canonical = resolve(__dirname, "sophie-daemon.mjs");
|
|
65
|
+
localCandidates.push(canonical);
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
const agentJson = join(AGENT_DIR, "config", "agent.json");
|
|
69
|
+
if (existsSync(agentJson)) {
|
|
70
|
+
const { firstName } = JSON.parse(readFileSync(agentJson, "utf-8"));
|
|
71
|
+
if (firstName && typeof firstName === "string") {
|
|
72
|
+
const lower = firstName.toLowerCase();
|
|
73
|
+
localCandidates.push(resolve(__dirname, `${lower}-daemon.mjs`));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
} catch { /* identity unavailable — fall through */ }
|
|
77
|
+
|
|
78
|
+
for (const p of localCandidates) if (existsSync(p)) return p;
|
|
79
|
+
|
|
80
|
+
// Final fallback: scan the directory for *-daemon.mjs (excluding self).
|
|
81
|
+
try {
|
|
82
|
+
for (const name of readdirSync(__dirname)) {
|
|
83
|
+
if (name === "maestro-daemon.mjs") continue;
|
|
84
|
+
if (name.endsWith("-daemon.mjs")) return resolve(__dirname, name);
|
|
85
|
+
}
|
|
86
|
+
} catch { /* */ }
|
|
87
|
+
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const coreDaemon = resolveCoreDaemon();
|
|
92
|
+
if (!coreDaemon) {
|
|
93
|
+
console.error("[DAEMON] could not locate a core daemon module under scripts/daemon/. Expected sophie-daemon.mjs or <firstName>-daemon.mjs.");
|
|
94
|
+
process.exit(78);
|
|
95
|
+
}
|
|
96
|
+
// Import and run the daemon (handles its own .env loading).
|
|
97
|
+
await import(coreDaemon);
|
|
@@ -268,13 +268,27 @@ generate_trigger_plist "meeting-prep" "" "900"
|
|
|
268
268
|
# 6. Meeting action capture (every 30 minutes)
|
|
269
269
|
generate_trigger_plist "meeting-action-capture" "" "1800"
|
|
270
270
|
|
|
271
|
-
#
|
|
271
|
+
# 7a. Daily morning brief (06:30 local)
|
|
272
|
+
generate_trigger_plist "daily-morning-brief" \
|
|
273
|
+
" <key>Hour</key>
|
|
274
|
+
<integer>6</integer>
|
|
275
|
+
<key>Minute</key>
|
|
276
|
+
<integer>30</integer>"
|
|
277
|
+
|
|
278
|
+
# 7b. Midday sweep (daily at 12:00 local)
|
|
272
279
|
generate_trigger_plist "daily-midday-sweep" \
|
|
273
280
|
" <key>Hour</key>
|
|
274
281
|
<integer>12</integer>
|
|
275
282
|
<key>Minute</key>
|
|
276
283
|
<integer>0</integer>"
|
|
277
284
|
|
|
285
|
+
# 7c. Daily evening wrap (18:00 local)
|
|
286
|
+
generate_trigger_plist "daily-evening-wrap" \
|
|
287
|
+
" <key>Hour</key>
|
|
288
|
+
<integer>18</integer>
|
|
289
|
+
<key>Minute</key>
|
|
290
|
+
<integer>0</integer>"
|
|
291
|
+
|
|
278
292
|
# 8. Weekly hiring (Monday 09:00)
|
|
279
293
|
generate_trigger_plist "weekly-hiring" \
|
|
280
294
|
" <key>Weekday</key>
|
|
@@ -95,13 +95,20 @@ function listPlists(agentRoot) {
|
|
|
95
95
|
// Tests
|
|
96
96
|
// ---------------------------------------------------------------------------
|
|
97
97
|
|
|
98
|
-
test("generator emits
|
|
98
|
+
test("generator emits 15 plists with the agent's first name", async () => {
|
|
99
|
+
// Inventory (as of cadence-bus v1):
|
|
100
|
+
// daemon, poll-relay,
|
|
101
|
+
// inbox-processor, backlog-executor, meeting-prep, meeting-action-capture,
|
|
102
|
+
// daily-morning-brief, daily-midday-sweep, daily-evening-wrap,
|
|
103
|
+
// weekly-hiring, weekly-priorities, weekly-execution,
|
|
104
|
+
// weekly-engineering-health, weekly-strategic-memo,
|
|
105
|
+
// quarterly-self-assessment.
|
|
99
106
|
const root = await makeAgent("alice");
|
|
100
107
|
try {
|
|
101
108
|
const r = runGenerator(root);
|
|
102
109
|
assert.equal(r.status, 0, r.stderr);
|
|
103
110
|
const plists = listPlists(root);
|
|
104
|
-
assert.equal(plists.length,
|
|
111
|
+
assert.equal(plists.length, 15);
|
|
105
112
|
for (const p of plists) {
|
|
106
113
|
assert.match(p, /^ai\.adaptic\.alice-/);
|
|
107
114
|
}
|