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.
@@ -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. Write Claude Code hooks config
76
- const claudeSettingsDir = path.join(process.cwd(), ".claude");
77
- fs.mkdirSync(claudeSettingsDir, { recursive: true });
78
-
79
- const hookEntry = { hooks: [{ type: "command", command: "palmier hook" }] };
80
- const hooksConfig = {
81
- hooks: {
82
- PermissionRequest: [hookEntry],
83
- Notification: [hookEntry],
84
- Stop: [hookEntry],
85
- },
86
- };
87
-
88
- fs.writeFileSync(
89
- path.join(claudeSettingsDir, "settings.json"),
90
- JSON.stringify(hooksConfig, null, 2),
91
- "utf-8"
92
- );
93
- console.log("Claude Code hooks config written to .claude/settings.json");
94
-
95
- // 5. Install systemd user service for palmier serve
96
- const unitDir = path.join(homedir(), ".config", "systemd", "user");
97
- fs.mkdirSync(unitDir, { recursive: true });
98
-
99
- const palmierBin = process.argv[1] || "palmier";
100
-
101
- const serviceContent = `[Unit]
102
- Description=Palmier Agent
103
- After=network-online.target
104
- Wants=network-online.target
105
-
106
- [Service]
107
- Type=simple
108
- ExecStart=${palmierBin} serve
109
- WorkingDirectory=${config.projectRoot}
110
- Restart=on-failure
111
- RestartSec=5
112
- Environment=PATH=${process.env.PATH || "/usr/local/bin:/usr/bin:/bin"}
113
-
114
- [Install]
115
- WantedBy=default.target
116
- `;
117
-
118
- const servicePath = path.join(unitDir, "palmier-agent.service");
119
- fs.writeFileSync(servicePath, serviceContent, "utf-8");
120
- console.log("Systemd service installed at:", servicePath);
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
+ }