palmier 0.1.8 → 0.2.0
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/CLAUDE.md +5 -0
- package/README.md +51 -5
- package/dist/commands/hook.js +32 -5
- package/dist/commands/init.js +16 -29
- package/dist/commands/run.d.ts +1 -0
- package/dist/commands/run.js +81 -73
- package/dist/commands/serve.js +73 -28
- package/dist/commands/task-generation.md +28 -0
- package/dist/index.js +0 -7
- package/dist/systemd.d.ts +1 -5
- package/dist/systemd.js +54 -114
- package/dist/task.js +2 -0
- package/dist/types.d.ts +5 -24
- package/package.json +33 -35
- package/src/commands/init.ts +121 -141
- package/src/commands/run.ts +205 -197
- package/src/commands/serve.ts +287 -240
- package/src/commands/task-generation.md +28 -0
- package/src/index.ts +0 -8
- package/src/nats-client.ts +15 -15
- package/src/systemd.ts +164 -232
- package/src/task.ts +3 -0
- package/src/types.ts +41 -63
- package/src/commands/hook.ts +0 -240
package/src/commands/init.ts
CHANGED
|
@@ -1,141 +1,121 @@
|
|
|
1
|
-
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
import { execSync } from "child_process";
|
|
4
|
-
import { homedir } from "os";
|
|
5
|
-
import { saveConfig } from "../config.js";
|
|
6
|
-
import type { AgentConfig } from "../types.js";
|
|
7
|
-
|
|
8
|
-
export interface InitOptions {
|
|
9
|
-
token: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Provision this agent by exchanging a base64 provisioning token for permanent credentials.
|
|
14
|
-
*/
|
|
15
|
-
export async function initCommand(options: InitOptions): Promise<void> {
|
|
16
|
-
// 1. Decode base64 provisioning token
|
|
17
|
-
let decoded: { server: string; token: string };
|
|
18
|
-
try {
|
|
19
|
-
const jsonStr = Buffer.from(options.token, "base64").toString("utf-8");
|
|
20
|
-
decoded = JSON.parse(jsonStr) as { server: string; token: string };
|
|
21
|
-
} catch {
|
|
22
|
-
console.error("Failed to decode provisioning token. Ensure it is a valid base64-encoded JSON string.");
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (!decoded.server || !decoded.token) {
|
|
27
|
-
console.error("Invalid provisioning token: missing 'server' or 'token' field.");
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
console.log(`Claiming agent at ${decoded.server}...`);
|
|
32
|
-
|
|
33
|
-
// 2. POST to server to claim agent
|
|
34
|
-
let claimResponse: {
|
|
35
|
-
agentId: string;
|
|
36
|
-
userId: string;
|
|
37
|
-
natsUrl: string;
|
|
38
|
-
natsWsUrl: string;
|
|
39
|
-
natsToken: string;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const res = await fetch(`${decoded.server}/api/agents/claim`, {
|
|
44
|
-
method: "POST",
|
|
45
|
-
headers: { "Content-Type": "application/json" },
|
|
46
|
-
body: JSON.stringify({ provisioning_token: options.token }),
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
if (!res.ok) {
|
|
50
|
-
const body = await res.text();
|
|
51
|
-
console.error(`Failed to claim agent: ${res.status} ${res.statusText}\n${body}`);
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
claimResponse = (await res.json()) as typeof claimResponse;
|
|
56
|
-
} catch (err) {
|
|
57
|
-
console.error(`Failed to reach server: ${err}`);
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// 3. Save config
|
|
62
|
-
const config: AgentConfig = {
|
|
63
|
-
agentId: claimResponse.agentId,
|
|
64
|
-
userId: claimResponse.userId,
|
|
65
|
-
natsUrl: claimResponse.natsUrl,
|
|
66
|
-
natsWsUrl: claimResponse.natsWsUrl,
|
|
67
|
-
natsToken: claimResponse.natsToken,
|
|
68
|
-
projectRoot: process.cwd(),
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
saveConfig(config);
|
|
72
|
-
console.log(`Agent provisioned. ID: ${config.agentId}`);
|
|
73
|
-
console.log("Config saved to ~/.config/palmier/agent.json");
|
|
74
|
-
|
|
75
|
-
// 4.
|
|
76
|
-
const
|
|
77
|
-
fs.mkdirSync(
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
console.log("
|
|
121
|
-
|
|
122
|
-
// 6. Enable and start the service
|
|
123
|
-
try {
|
|
124
|
-
execSync("systemctl --user daemon-reload", { stdio: "inherit" });
|
|
125
|
-
execSync("systemctl --user enable --now palmier-agent.service", { stdio: "inherit" });
|
|
126
|
-
console.log("Palmier agent service enabled and started.");
|
|
127
|
-
} catch (err) {
|
|
128
|
-
console.error(`Warning: failed to enable systemd service: ${err}`);
|
|
129
|
-
console.error("You may need to start it manually: systemctl --user enable --now palmier-agent.service");
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// 7. Enable lingering so service runs without active login session
|
|
133
|
-
try {
|
|
134
|
-
execSync(`loginctl enable-linger ${process.env.USER || ""}`, { stdio: "inherit" });
|
|
135
|
-
console.log("Login lingering enabled.");
|
|
136
|
-
} catch (err) {
|
|
137
|
-
console.error(`Warning: failed to enable linger: ${err}`);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
console.log("\nAgent initialization complete!");
|
|
141
|
-
}
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { saveConfig } from "../config.js";
|
|
6
|
+
import type { AgentConfig } from "../types.js";
|
|
7
|
+
|
|
8
|
+
export interface InitOptions {
|
|
9
|
+
token: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Provision this agent by exchanging a base64 provisioning token for permanent credentials.
|
|
14
|
+
*/
|
|
15
|
+
export async function initCommand(options: InitOptions): Promise<void> {
|
|
16
|
+
// 1. Decode base64 provisioning token
|
|
17
|
+
let decoded: { server: string; token: string };
|
|
18
|
+
try {
|
|
19
|
+
const jsonStr = Buffer.from(options.token, "base64").toString("utf-8");
|
|
20
|
+
decoded = JSON.parse(jsonStr) as { server: string; token: string };
|
|
21
|
+
} catch {
|
|
22
|
+
console.error("Failed to decode provisioning token. Ensure it is a valid base64-encoded JSON string.");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!decoded.server || !decoded.token) {
|
|
27
|
+
console.error("Invalid provisioning token: missing 'server' or 'token' field.");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log(`Claiming agent at ${decoded.server}...`);
|
|
32
|
+
|
|
33
|
+
// 2. POST to server to claim agent
|
|
34
|
+
let claimResponse: {
|
|
35
|
+
agentId: string;
|
|
36
|
+
userId: string;
|
|
37
|
+
natsUrl: string;
|
|
38
|
+
natsWsUrl: string;
|
|
39
|
+
natsToken: string;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const res = await fetch(`${decoded.server}/api/agents/claim`, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: { "Content-Type": "application/json" },
|
|
46
|
+
body: JSON.stringify({ provisioning_token: options.token }),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
const body = await res.text();
|
|
51
|
+
console.error(`Failed to claim agent: ${res.status} ${res.statusText}\n${body}`);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
claimResponse = (await res.json()) as typeof claimResponse;
|
|
56
|
+
} catch (err) {
|
|
57
|
+
console.error(`Failed to reach server: ${err}`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 3. Save config
|
|
62
|
+
const config: AgentConfig = {
|
|
63
|
+
agentId: claimResponse.agentId,
|
|
64
|
+
userId: claimResponse.userId,
|
|
65
|
+
natsUrl: claimResponse.natsUrl,
|
|
66
|
+
natsWsUrl: claimResponse.natsWsUrl,
|
|
67
|
+
natsToken: claimResponse.natsToken,
|
|
68
|
+
projectRoot: process.cwd(),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
saveConfig(config);
|
|
72
|
+
console.log(`Agent provisioned. ID: ${config.agentId}`);
|
|
73
|
+
console.log("Config saved to ~/.config/palmier/agent.json");
|
|
74
|
+
|
|
75
|
+
// 4. Install systemd user service for palmier serve
|
|
76
|
+
const unitDir = path.join(homedir(), ".config", "systemd", "user");
|
|
77
|
+
fs.mkdirSync(unitDir, { recursive: true });
|
|
78
|
+
|
|
79
|
+
const palmierBin = process.argv[1] || "palmier";
|
|
80
|
+
|
|
81
|
+
const serviceContent = `[Unit]
|
|
82
|
+
Description=Palmier Agent
|
|
83
|
+
After=network-online.target
|
|
84
|
+
Wants=network-online.target
|
|
85
|
+
|
|
86
|
+
[Service]
|
|
87
|
+
Type=simple
|
|
88
|
+
ExecStart=${palmierBin} serve
|
|
89
|
+
WorkingDirectory=${config.projectRoot}
|
|
90
|
+
Restart=on-failure
|
|
91
|
+
RestartSec=5
|
|
92
|
+
Environment=PATH=${process.env.PATH || "/usr/local/bin:/usr/bin:/bin"}
|
|
93
|
+
|
|
94
|
+
[Install]
|
|
95
|
+
WantedBy=default.target
|
|
96
|
+
`;
|
|
97
|
+
|
|
98
|
+
const servicePath = path.join(unitDir, "palmier-agent.service");
|
|
99
|
+
fs.writeFileSync(servicePath, serviceContent, "utf-8");
|
|
100
|
+
console.log("Systemd service installed at:", servicePath);
|
|
101
|
+
|
|
102
|
+
// 6. Enable and start the service
|
|
103
|
+
try {
|
|
104
|
+
execSync("systemctl --user daemon-reload", { stdio: "inherit" });
|
|
105
|
+
execSync("systemctl --user enable --now palmier-agent.service", { stdio: "inherit" });
|
|
106
|
+
console.log("Palmier agent service enabled and started.");
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error(`Warning: failed to enable systemd service: ${err}`);
|
|
109
|
+
console.error("You may need to start it manually: systemctl --user enable --now palmier-agent.service");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 7. Enable lingering so service runs without active login session
|
|
113
|
+
try {
|
|
114
|
+
execSync(`loginctl enable-linger ${process.env.USER || ""}`, { stdio: "inherit" });
|
|
115
|
+
console.log("Login lingering enabled.");
|
|
116
|
+
} catch (err) {
|
|
117
|
+
console.error(`Warning: failed to enable linger: ${err}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log("\nAgent initialization complete!");
|
|
121
|
+
}
|