heartbeat-opencode-plugin 0.1.1 → 0.1.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 +1 -1
- package/scheduler/index.ts +38 -1
package/package.json
CHANGED
package/scheduler/index.ts
CHANGED
|
@@ -75,6 +75,17 @@ const OPENCODE_FALLBACK_PATHS = [
|
|
|
75
75
|
"/opt/homebrew/bin/opencode",
|
|
76
76
|
"/usr/local/bin/opencode",
|
|
77
77
|
];
|
|
78
|
+
const DEFAULT_EXEC_PATH_ENTRIES = [
|
|
79
|
+
"/opt/homebrew/bin",
|
|
80
|
+
"/opt/homebrew/sbin",
|
|
81
|
+
"/usr/local/bin",
|
|
82
|
+
"/usr/local/sbin",
|
|
83
|
+
"/usr/bin",
|
|
84
|
+
"/bin",
|
|
85
|
+
"/usr/sbin",
|
|
86
|
+
"/sbin",
|
|
87
|
+
"/Library/Apple/usr/bin",
|
|
88
|
+
];
|
|
78
89
|
const OUTPUT_TAG_NOTE =
|
|
79
90
|
"Runtime contract: while running Heartbeat programs, every emitted status/output line must be prefixed with [program][taskId] for grepability.";
|
|
80
91
|
|
|
@@ -161,6 +172,24 @@ function resolveOpencodeCommand(command: string): string {
|
|
|
161
172
|
return command;
|
|
162
173
|
}
|
|
163
174
|
|
|
175
|
+
function buildExecutablePath(): string {
|
|
176
|
+
const currentEntries = (process.env.PATH ?? "")
|
|
177
|
+
.split(path.delimiter)
|
|
178
|
+
.map((entry) => entry.trim())
|
|
179
|
+
.filter(Boolean);
|
|
180
|
+
|
|
181
|
+
const merged = [...currentEntries, ...DEFAULT_EXEC_PATH_ENTRIES];
|
|
182
|
+
const unique = Array.from(new Set(merged));
|
|
183
|
+
return unique.join(path.delimiter);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function buildJobEnv(): NodeJS.ProcessEnv {
|
|
187
|
+
return {
|
|
188
|
+
...process.env,
|
|
189
|
+
PATH: buildExecutablePath(),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
164
193
|
function readJob(jobId: string): Job | null {
|
|
165
194
|
const file = jobFilePath(jobId);
|
|
166
195
|
if (!fs.existsSync(file)) return null;
|
|
@@ -422,6 +451,7 @@ export function runJob(jobId: string): Promise<RunResult> {
|
|
|
422
451
|
writeJob(job);
|
|
423
452
|
|
|
424
453
|
appendJobLog(job, `Starting job "${job.name}"`);
|
|
454
|
+
const jobEnv = buildJobEnv();
|
|
425
455
|
const resolvedCommand = job.kind === "opencode"
|
|
426
456
|
? resolveOpencodeCommand(job.command)
|
|
427
457
|
: job.command;
|
|
@@ -431,12 +461,13 @@ export function runJob(jobId: string): Promise<RunResult> {
|
|
|
431
461
|
}
|
|
432
462
|
appendJobLog(job, `Command: ${resolvedCommand} ${job.args.join(" ")}`);
|
|
433
463
|
appendJobLog(job, `Workdir: ${job.workdir}`);
|
|
464
|
+
appendJobLog(job, `PATH: ${jobEnv.PATH ?? ""}`);
|
|
434
465
|
|
|
435
466
|
let child: ReturnType<typeof spawn>;
|
|
436
467
|
try {
|
|
437
468
|
child = spawn(resolvedCommand, job.args, {
|
|
438
469
|
cwd: job.workdir,
|
|
439
|
-
env:
|
|
470
|
+
env: jobEnv,
|
|
440
471
|
shell: false,
|
|
441
472
|
stdio: ["ignore", "pipe", "pipe"],
|
|
442
473
|
});
|
|
@@ -690,6 +721,7 @@ function buildCalendarXml(calendars: CalendarEntry[]): string {
|
|
|
690
721
|
function createLaunchdPlist(job: Job): string {
|
|
691
722
|
const label = getConfigLaunchdLabel(job.id);
|
|
692
723
|
const parsed = parseCronToLaunchd(job.schedule);
|
|
724
|
+
const executablePath = buildExecutablePath();
|
|
693
725
|
|
|
694
726
|
const scheduleBlock = parsed.startInterval
|
|
695
727
|
? ` <key>StartInterval</key>\n <integer>${parsed.startInterval}</integer>`
|
|
@@ -711,6 +743,11 @@ function createLaunchdPlist(job: Job): string {
|
|
|
711
743
|
<string>run</string>
|
|
712
744
|
<string>${escapeXml(job.id)}</string>
|
|
713
745
|
</array>
|
|
746
|
+
<key>EnvironmentVariables</key>
|
|
747
|
+
<dict>
|
|
748
|
+
<key>PATH</key>
|
|
749
|
+
<string>${escapeXml(executablePath)}</string>
|
|
750
|
+
</dict>
|
|
714
751
|
${scheduleBlock}
|
|
715
752
|
<key>StandardOutPath</key>
|
|
716
753
|
<string>${escapeXml(sharedLogPath())}</string>
|