palmier 0.2.3 → 0.2.5
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/README.md +21 -30
- package/dist/agents/claude.js +5 -2
- package/dist/agents/codex.js +4 -2
- package/dist/agents/gemini.js +4 -2
- package/dist/commands/info.js +17 -10
- package/dist/commands/init.d.ts +2 -10
- package/dist/commands/init.js +102 -154
- package/dist/commands/pair.js +3 -3
- package/dist/commands/run.js +2 -13
- package/dist/commands/sessions.js +1 -4
- package/dist/config.js +1 -1
- package/dist/index.js +7 -7
- package/dist/platform/index.d.ts +4 -0
- package/dist/platform/index.js +12 -0
- package/dist/platform/linux.d.ts +11 -0
- package/dist/platform/linux.js +186 -0
- package/dist/platform/platform.d.ts +20 -0
- package/dist/platform/platform.js +2 -0
- package/dist/platform/windows.d.ts +11 -0
- package/dist/platform/windows.js +201 -0
- package/dist/rpc-handler.js +13 -30
- package/dist/spawn-command.d.ts +5 -2
- package/dist/spawn-command.js +2 -0
- package/dist/transports/http-transport.js +2 -7
- package/package.json +1 -1
- package/src/agents/claude.ts +6 -2
- package/src/agents/codex.ts +5 -2
- package/src/agents/gemini.ts +5 -2
- package/src/commands/info.ts +18 -10
- package/src/commands/init.ts +131 -180
- package/src/commands/pair.ts +4 -3
- package/src/commands/run.ts +3 -15
- package/src/commands/sessions.ts +1 -4
- package/src/config.ts +1 -1
- package/src/index.ts +8 -7
- package/src/platform/index.ts +16 -0
- package/src/platform/linux.ts +207 -0
- package/src/platform/platform.ts +25 -0
- package/src/platform/windows.ts +223 -0
- package/src/rpc-handler.ts +13 -37
- package/src/spawn-command.ts +7 -2
- package/src/transports/http-transport.ts +2 -5
- package/src/systemd.ts +0 -164
package/src/systemd.ts
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
import { homedir } from "os";
|
|
4
|
-
import { execSync } from "child_process";
|
|
5
|
-
import type { HostConfig } from "./types.js";
|
|
6
|
-
import type { ParsedTask } from "./types.js";
|
|
7
|
-
|
|
8
|
-
const UNIT_DIR = path.join(homedir(), ".config", "systemd", "user");
|
|
9
|
-
|
|
10
|
-
function getTimerName(taskId: string): string {
|
|
11
|
-
return `palmier-task-${taskId}.timer`;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function getServiceName(taskId: string): string {
|
|
15
|
-
return `palmier-task-${taskId}.service`;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Convert a cron expression (5-field) to a systemd OnCalendar string.
|
|
20
|
-
* Handles basic cron patterns: minute hour day-of-month month day-of-week
|
|
21
|
-
*/
|
|
22
|
-
export function cronToOnCalendar(cron: string): string {
|
|
23
|
-
const parts = cron.trim().split(/\s+/);
|
|
24
|
-
if (parts.length !== 5) {
|
|
25
|
-
throw new Error(`Invalid cron expression (expected 5 fields): ${cron}`);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
29
|
-
|
|
30
|
-
// Map cron day-of-week names/numbers to systemd abbreviated names
|
|
31
|
-
const dowMap: Record<string, string> = {
|
|
32
|
-
"0": "Sun",
|
|
33
|
-
"1": "Mon",
|
|
34
|
-
"2": "Tue",
|
|
35
|
-
"3": "Wed",
|
|
36
|
-
"4": "Thu",
|
|
37
|
-
"5": "Fri",
|
|
38
|
-
"6": "Sat",
|
|
39
|
-
"7": "Sun",
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// Convert day-of-week
|
|
43
|
-
let dow = dayOfWeek === "*" ? "*" : dayOfWeek;
|
|
44
|
-
if (dowMap[dow]) {
|
|
45
|
-
dow = dowMap[dow];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Build OnCalendar string
|
|
49
|
-
// Format: DayOfWeek Year-Month-Day Hour:Minute:Second
|
|
50
|
-
const monthPart = month === "*" ? "*" : month.padStart(2, "0");
|
|
51
|
-
const dayPart = dayOfMonth === "*" ? "*" : dayOfMonth.padStart(2, "0");
|
|
52
|
-
const hourPart = hour === "*" ? "*" : hour.padStart(2, "0");
|
|
53
|
-
const minutePart = minute === "*" ? "*" : minute.padStart(2, "0");
|
|
54
|
-
|
|
55
|
-
if (dow === "*") {
|
|
56
|
-
return `*-${monthPart}-${dayPart} ${hourPart}:${minutePart}:00`;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return `${dow} *-${monthPart}-${dayPart} ${hourPart}:${minutePart}:00`;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Install a systemd user timer + service for a task.
|
|
64
|
-
*/
|
|
65
|
-
export function installTaskTimer(config: HostConfig, task: ParsedTask): void {
|
|
66
|
-
fs.mkdirSync(UNIT_DIR, { recursive: true });
|
|
67
|
-
|
|
68
|
-
const taskId = task.frontmatter.id;
|
|
69
|
-
const serviceName = getServiceName(taskId);
|
|
70
|
-
const timerName = getTimerName(taskId);
|
|
71
|
-
|
|
72
|
-
// Determine the palmier binary path
|
|
73
|
-
const palmierBin = process.argv[1] || "palmier";
|
|
74
|
-
|
|
75
|
-
// Generate service unit
|
|
76
|
-
const serviceContent = `[Unit]
|
|
77
|
-
Description=Palmier Task: ${taskId}
|
|
78
|
-
|
|
79
|
-
[Service]
|
|
80
|
-
Type=oneshot
|
|
81
|
-
ExecStart=${palmierBin} run ${taskId}
|
|
82
|
-
WorkingDirectory=${config.projectRoot}
|
|
83
|
-
Environment=PATH=${process.env.PATH || "/usr/local/bin:/usr/bin:/bin"}
|
|
84
|
-
`;
|
|
85
|
-
|
|
86
|
-
// Write service unit (always needed for on-demand runs)
|
|
87
|
-
fs.writeFileSync(path.join(UNIT_DIR, serviceName), serviceContent, "utf-8");
|
|
88
|
-
daemonReload();
|
|
89
|
-
|
|
90
|
-
// Only create and enable a timer if there are actual triggers
|
|
91
|
-
const triggers = task.frontmatter.triggers || [];
|
|
92
|
-
const onCalendarLines: string[] = [];
|
|
93
|
-
for (const trigger of triggers) {
|
|
94
|
-
if (trigger.type === "cron") {
|
|
95
|
-
onCalendarLines.push(`OnCalendar=${cronToOnCalendar(trigger.value)}`);
|
|
96
|
-
} else if (trigger.type === "once") {
|
|
97
|
-
onCalendarLines.push(`OnActiveSec=${trigger.value}`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (onCalendarLines.length > 0) {
|
|
102
|
-
const timerContent = `[Unit]
|
|
103
|
-
Description=Timer for Palmier Task: ${taskId}
|
|
104
|
-
|
|
105
|
-
[Timer]
|
|
106
|
-
${onCalendarLines.join("\n")}
|
|
107
|
-
Persistent=true
|
|
108
|
-
|
|
109
|
-
[Install]
|
|
110
|
-
WantedBy=timers.target
|
|
111
|
-
`;
|
|
112
|
-
fs.writeFileSync(path.join(UNIT_DIR, timerName), timerContent, "utf-8");
|
|
113
|
-
daemonReload();
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
execSync(`systemctl --user enable --now ${timerName}`, { encoding: "utf-8" });
|
|
117
|
-
} catch (err: unknown) {
|
|
118
|
-
const e = err as { stderr?: string };
|
|
119
|
-
console.error(`Failed to enable timer ${timerName}: ${e.stderr || err}`);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Remove a task's systemd timer and service files.
|
|
126
|
-
*/
|
|
127
|
-
export function removeTaskTimer(taskId: string): void {
|
|
128
|
-
const timerName = getTimerName(taskId);
|
|
129
|
-
const serviceName = getServiceName(taskId);
|
|
130
|
-
|
|
131
|
-
const timerPath = path.join(UNIT_DIR, timerName);
|
|
132
|
-
const servicePath = path.join(UNIT_DIR, serviceName);
|
|
133
|
-
|
|
134
|
-
// Only stop/disable the timer if the file exists
|
|
135
|
-
if (fs.existsSync(timerPath)) {
|
|
136
|
-
try {
|
|
137
|
-
execSync(`systemctl --user stop ${timerName}`, { encoding: "utf-8" });
|
|
138
|
-
} catch {
|
|
139
|
-
// Timer might not be running
|
|
140
|
-
}
|
|
141
|
-
try {
|
|
142
|
-
execSync(`systemctl --user disable ${timerName}`, { encoding: "utf-8" });
|
|
143
|
-
} catch {
|
|
144
|
-
// Timer might not be enabled
|
|
145
|
-
}
|
|
146
|
-
fs.unlinkSync(timerPath);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (fs.existsSync(servicePath)) fs.unlinkSync(servicePath);
|
|
150
|
-
|
|
151
|
-
daemonReload();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Run systemctl --user daemon-reload.
|
|
156
|
-
*/
|
|
157
|
-
export function daemonReload(): void {
|
|
158
|
-
try {
|
|
159
|
-
execSync("systemctl --user daemon-reload", { encoding: "utf-8" });
|
|
160
|
-
} catch (err: unknown) {
|
|
161
|
-
const e = err as { stderr?: string };
|
|
162
|
-
console.error(`daemon-reload failed: ${e.stderr || err}`);
|
|
163
|
-
}
|
|
164
|
-
}
|