palmier 0.2.5 → 0.2.7
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/.github/workflows/ci.yml +16 -0
- package/LICENSE +190 -0
- package/README.md +286 -219
- package/dist/agents/agent.d.ts +6 -3
- package/dist/agents/agent.js +2 -0
- package/dist/agents/claude.d.ts +1 -1
- package/dist/agents/claude.js +12 -9
- package/dist/agents/codex.d.ts +1 -1
- package/dist/agents/codex.js +12 -10
- package/dist/agents/gemini.d.ts +1 -1
- package/dist/agents/gemini.js +13 -9
- package/dist/agents/openclaw.d.ts +2 -2
- package/dist/agents/openclaw.js +8 -7
- package/dist/agents/shared-prompt.d.ts +5 -4
- package/dist/agents/shared-prompt.js +10 -8
- package/dist/commands/agents.js +11 -0
- package/dist/commands/info.js +0 -22
- package/dist/commands/init.js +59 -95
- package/dist/commands/lan.d.ts +8 -0
- package/dist/commands/lan.js +51 -0
- package/dist/commands/mcpserver.js +12 -27
- package/dist/commands/pair.d.ts +1 -1
- package/dist/commands/pair.js +52 -56
- package/dist/commands/plan-generation.md +24 -32
- package/dist/commands/restart.d.ts +5 -0
- package/dist/commands/restart.js +9 -0
- package/dist/commands/run.js +311 -124
- package/dist/commands/serve.d.ts +1 -1
- package/dist/commands/serve.js +77 -17
- package/dist/commands/task-cleanup.d.ts +14 -0
- package/dist/commands/task-cleanup.js +84 -0
- package/dist/config.js +3 -17
- package/dist/events.d.ts +9 -0
- package/dist/events.js +46 -0
- package/dist/index.js +15 -0
- package/dist/platform/linux.d.ts +2 -0
- package/dist/platform/linux.js +22 -1
- package/dist/platform/platform.d.ts +4 -0
- package/dist/platform/windows.d.ts +3 -0
- package/dist/platform/windows.js +99 -82
- package/dist/rpc-handler.d.ts +2 -1
- package/dist/rpc-handler.js +43 -52
- package/dist/spawn-command.d.ts +29 -6
- package/dist/spawn-command.js +38 -15
- package/dist/transports/http-transport.d.ts +1 -1
- package/dist/transports/http-transport.js +103 -18
- package/dist/transports/nats-transport.d.ts +4 -2
- package/dist/transports/nats-transport.js +3 -4
- package/dist/types.d.ts +5 -5
- package/package.json +5 -3
- package/src/agents/agent.ts +8 -3
- package/src/agents/claude.ts +44 -43
- package/src/agents/codex.ts +11 -12
- package/src/agents/gemini.ts +12 -10
- package/src/agents/openclaw.ts +8 -7
- package/src/agents/shared-prompt.ts +10 -8
- package/src/commands/agents.ts +11 -0
- package/src/commands/info.ts +0 -24
- package/src/commands/init.ts +62 -119
- package/src/commands/lan.ts +58 -0
- package/src/commands/mcpserver.ts +12 -31
- package/src/commands/pair.ts +50 -63
- package/src/commands/plan-generation.md +24 -32
- package/src/commands/restart.ts +9 -0
- package/src/commands/run.ts +375 -143
- package/src/commands/serve.ts +96 -17
- package/src/config.ts +3 -18
- package/src/cross-spawn.d.ts +5 -0
- package/src/events.ts +51 -0
- package/src/index.ts +17 -0
- package/src/platform/linux.ts +25 -1
- package/src/platform/platform.ts +6 -0
- package/src/platform/windows.ts +100 -89
- package/src/rpc-handler.ts +46 -55
- package/src/spawn-command.ts +120 -83
- package/src/transports/http-transport.ts +123 -19
- package/src/transports/nats-transport.ts +4 -4
- package/src/types.ts +6 -8
package/dist/commands/pair.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
1
3
|
import * as http from "node:http";
|
|
2
4
|
import { StringCodec } from "nats";
|
|
3
|
-
import { loadConfig } from "../config.js";
|
|
5
|
+
import { loadConfig, CONFIG_DIR } from "../config.js";
|
|
4
6
|
import { connectNats } from "../nats-client.js";
|
|
5
|
-
import { detectLanIp } from "../transports/http-transport.js";
|
|
6
7
|
import { addSession } from "../session-store.js";
|
|
7
8
|
const CODE_CHARS = "ABCDEFGHJKMNPQRSTUVWXYZ23456789"; // no O/0/I/1/L
|
|
8
9
|
const CODE_LENGTH = 6;
|
|
9
10
|
const EXPIRY_MS = 5 * 60 * 1000; // 5 minutes
|
|
11
|
+
const LAN_LOCKFILE = path.join(CONFIG_DIR, "lan.json");
|
|
10
12
|
function generateCode() {
|
|
11
13
|
const bytes = new Uint8Array(CODE_LENGTH);
|
|
12
14
|
crypto.getRandomValues(bytes);
|
|
@@ -14,15 +16,13 @@ function generateCode() {
|
|
|
14
16
|
}
|
|
15
17
|
function buildPairResponse(config, label) {
|
|
16
18
|
const session = addSession(label);
|
|
17
|
-
|
|
19
|
+
return {
|
|
18
20
|
hostId: config.hostId,
|
|
19
21
|
sessionToken: session.token,
|
|
20
22
|
};
|
|
21
|
-
return response;
|
|
22
23
|
}
|
|
23
24
|
/**
|
|
24
|
-
* POST to the running
|
|
25
|
-
* Returns true if paired, false if expired/failed.
|
|
25
|
+
* POST to the running LAN server and long-poll until paired or expired.
|
|
26
26
|
*/
|
|
27
27
|
function lanPairRegister(port, code) {
|
|
28
28
|
const body = JSON.stringify({ code, expiryMs: EXPIRY_MS });
|
|
@@ -33,7 +33,7 @@ function lanPairRegister(port, code) {
|
|
|
33
33
|
path: "/internal/pair-register",
|
|
34
34
|
method: "POST",
|
|
35
35
|
headers: { "Content-Type": "application/json" },
|
|
36
|
-
timeout: EXPIRY_MS + 5000,
|
|
36
|
+
timeout: EXPIRY_MS + 5000,
|
|
37
37
|
}, (res) => {
|
|
38
38
|
const chunks = [];
|
|
39
39
|
res.on("data", (chunk) => chunks.push(chunk));
|
|
@@ -47,26 +47,30 @@ function lanPairRegister(port, code) {
|
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
49
|
});
|
|
50
|
-
req.on("error", (
|
|
51
|
-
|
|
52
|
-
console.error("Make sure `palmier serve` is running first.");
|
|
53
|
-
resolve(false);
|
|
54
|
-
});
|
|
55
|
-
req.on("timeout", () => {
|
|
56
|
-
req.destroy();
|
|
57
|
-
resolve(false);
|
|
58
|
-
});
|
|
50
|
+
req.on("error", () => resolve(false));
|
|
51
|
+
req.on("timeout", () => { req.destroy(); resolve(false); });
|
|
59
52
|
req.end(body);
|
|
60
53
|
});
|
|
61
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Read the LAN lockfile to check if `palmier lan` is running.
|
|
57
|
+
*/
|
|
58
|
+
function getLanPort() {
|
|
59
|
+
try {
|
|
60
|
+
const raw = fs.readFileSync(LAN_LOCKFILE, "utf-8");
|
|
61
|
+
return JSON.parse(raw).port;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
62
67
|
/**
|
|
63
68
|
* Generate an OTP code and wait for a PWA client to pair.
|
|
64
|
-
* Listens on NATS
|
|
69
|
+
* Listens on NATS always, and also on the LAN server if `palmier lan` is running.
|
|
65
70
|
*/
|
|
66
71
|
export async function pairCommand() {
|
|
67
72
|
const config = loadConfig();
|
|
68
73
|
const code = generateCode();
|
|
69
|
-
const mode = config.mode ?? "nats";
|
|
70
74
|
let paired = false;
|
|
71
75
|
function onPaired() {
|
|
72
76
|
paired = true;
|
|
@@ -79,48 +83,40 @@ export async function pairCommand() {
|
|
|
79
83
|
console.log("");
|
|
80
84
|
console.log(` ${code}`);
|
|
81
85
|
console.log("");
|
|
82
|
-
if (mode === "lan" || mode === "auto") {
|
|
83
|
-
const ip = detectLanIp();
|
|
84
|
-
const port = config.directPort ?? 7400;
|
|
85
|
-
console.log(` LAN Address: ${ip}:${port}`);
|
|
86
|
-
console.log("");
|
|
87
|
-
}
|
|
88
86
|
console.log("Code expires in 5 minutes.");
|
|
89
|
-
// NATS pairing (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
label = body.label;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
catch { /* empty body is fine */ }
|
|
111
|
-
const response = buildPairResponse(config, label);
|
|
112
|
-
if (msg.reply) {
|
|
113
|
-
msg.respond(sc.encode(JSON.stringify(response)));
|
|
87
|
+
// NATS pairing (always active)
|
|
88
|
+
const nc = await connectNats(config);
|
|
89
|
+
const sc = StringCodec();
|
|
90
|
+
const subject = `pair.${code}`;
|
|
91
|
+
const sub = nc.subscribe(subject, { max: 1 });
|
|
92
|
+
cleanups.push(() => {
|
|
93
|
+
sub.unsubscribe();
|
|
94
|
+
nc.close();
|
|
95
|
+
});
|
|
96
|
+
(async () => {
|
|
97
|
+
for await (const msg of sub) {
|
|
98
|
+
if (paired)
|
|
99
|
+
break;
|
|
100
|
+
let label;
|
|
101
|
+
try {
|
|
102
|
+
if (msg.data && msg.data.length > 0) {
|
|
103
|
+
const body = JSON.parse(sc.decode(msg.data));
|
|
104
|
+
label = body.label;
|
|
114
105
|
}
|
|
115
|
-
onPaired();
|
|
116
106
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
107
|
+
catch { /* empty body is fine */ }
|
|
108
|
+
const response = buildPairResponse(config, label);
|
|
109
|
+
if (msg.reply) {
|
|
110
|
+
msg.respond(sc.encode(JSON.stringify(response)));
|
|
111
|
+
}
|
|
112
|
+
onPaired();
|
|
113
|
+
}
|
|
114
|
+
})();
|
|
115
|
+
// LAN pairing — if `palmier lan` is running, also register with it
|
|
116
|
+
const lanPort = getLanPort();
|
|
117
|
+
if (lanPort) {
|
|
122
118
|
(async () => {
|
|
123
|
-
const result = await lanPairRegister(
|
|
119
|
+
const result = await lanPairRegister(lanPort, code);
|
|
124
120
|
if (result)
|
|
125
121
|
onPaired();
|
|
126
122
|
})();
|
|
@@ -1,32 +1,24 @@
|
|
|
1
|
-
You are a task planning assistant. Given a task description, produce a
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
###
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
### 3. Output Format (if applicable)
|
|
26
|
-
If the task produces a report, email, or other formatted output, specify the exact structure, sections, tone, and any templates the agent should follow.
|
|
27
|
-
|
|
28
|
-
Use Markdown formatting throughout — headings, code blocks, and tables where appropriate.
|
|
29
|
-
|
|
30
|
-
**Important:** Any relative times or dates in the task description (e.g., "yesterday", "last week") are relative to when the task is executed, not when this plan is generated. The agent must resolve them at execution time.
|
|
31
|
-
|
|
32
|
-
**Task description:**
|
|
1
|
+
You are a task planning assistant. Given a task description, produce a Markdown execution plan for an agent. **Do not execute any part of the plan yourself.**
|
|
2
|
+
|
|
3
|
+
Output a raw YAML frontmatter block (delimited by `---`) followed by the plan body. Do NOT wrap frontmatter in code fences. The first line of output must be `---`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
task_name: <short name, 3-6 words>
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
**Frontmatter:** `task_name` — concise label (e.g., "Clean up temp files", "Backup database daily").
|
|
10
|
+
|
|
11
|
+
**Plan body:**
|
|
12
|
+
|
|
13
|
+
### 1. Goal
|
|
14
|
+
What the task accomplishes and the expected end state.
|
|
15
|
+
|
|
16
|
+
### 2. Plan
|
|
17
|
+
Numbered sequence of concrete, actionable steps. Include conditional branches where behavior may vary. Each step must be unambiguous.
|
|
18
|
+
|
|
19
|
+
### 3. Output Format (if applicable)
|
|
20
|
+
If the task produces formatted output (report, email, etc.), specify structure, sections, tone, and templates.
|
|
21
|
+
|
|
22
|
+
Relative times in the task description (e.g., "yesterday") are relative to execution time, not plan generation time.
|
|
23
|
+
|
|
24
|
+
**Task description:**
|