palmier 0.6.7 → 0.6.9
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 +14 -0
- package/dist/agents/agent-instructions.md +7 -37
- package/dist/agents/agent.d.ts +2 -2
- package/dist/agents/aider.d.ts +1 -1
- package/dist/agents/aider.js +3 -6
- package/dist/agents/claude.d.ts +1 -1
- package/dist/agents/claude.js +3 -6
- package/dist/agents/cline.d.ts +1 -1
- package/dist/agents/cline.js +3 -6
- package/dist/agents/codex.d.ts +1 -1
- package/dist/agents/codex.js +3 -6
- package/dist/agents/copilot.d.ts +1 -1
- package/dist/agents/copilot.js +3 -6
- package/dist/agents/cursor.d.ts +1 -1
- package/dist/agents/cursor.js +3 -6
- package/dist/agents/deepagents.d.ts +1 -1
- package/dist/agents/deepagents.js +3 -6
- package/dist/agents/droid.d.ts +1 -1
- package/dist/agents/droid.js +3 -6
- package/dist/agents/gemini.d.ts +1 -1
- package/dist/agents/gemini.js +3 -6
- package/dist/agents/goose.d.ts +1 -1
- package/dist/agents/goose.js +3 -6
- package/dist/agents/hermes.d.ts +1 -1
- package/dist/agents/hermes.js +3 -6
- package/dist/agents/kimi.d.ts +1 -1
- package/dist/agents/kimi.js +3 -6
- package/dist/agents/kiro.d.ts +1 -1
- package/dist/agents/kiro.js +3 -6
- package/dist/agents/openclaw.d.ts +1 -1
- package/dist/agents/openclaw.js +3 -6
- package/dist/agents/opencode.d.ts +1 -1
- package/dist/agents/opencode.js +3 -6
- package/dist/agents/qoder.d.ts +1 -1
- package/dist/agents/qoder.js +3 -6
- package/dist/agents/qwen.d.ts +1 -1
- package/dist/agents/qwen.js +3 -6
- package/dist/agents/shared-prompt.d.ts +3 -2
- package/dist/agents/shared-prompt.js +6 -4
- package/dist/commands/run.js +3 -7
- package/dist/mcp-handler.js +1 -1
- package/dist/mcp-tools.d.ts +6 -1
- package/dist/mcp-tools.js +72 -6
- package/dist/pwa/assets/{index-DAI3J-jU.css → index-C6Lz09EY.css} +1 -1
- package/dist/pwa/assets/{index-RrJvjqz9.js → index-CZejk2al.js} +42 -42
- package/dist/pwa/assets/{web-EzNEHXEh.js → web-C48txJFl.js} +1 -1
- package/dist/pwa/assets/{web-DQteXlI7.js → web-zj8Blync.js} +1 -1
- package/dist/pwa/index.html +2 -2
- package/dist/pwa/service-worker.js +1 -1
- package/dist/rpc-handler.js +27 -68
- package/dist/spawn-command.js +3 -1
- package/dist/task.js +2 -3
- package/dist/transports/http-transport.js +4 -5
- package/dist/types.d.ts +0 -1
- package/package.json +2 -2
- package/palmier-server/README.md +1 -1
- package/palmier-server/pwa/src/App.css +9 -0
- package/palmier-server/pwa/src/components/TaskCard.tsx +36 -8
- package/palmier-server/pwa/src/components/TaskForm.tsx +63 -53
- package/palmier-server/pwa/src/constants.ts +1 -1
- package/palmier-server/spec.md +1 -1
- package/src/agents/agent-instructions.md +7 -37
- package/src/agents/agent.ts +2 -2
- package/src/agents/aider.ts +3 -6
- package/src/agents/claude.ts +3 -6
- package/src/agents/cline.ts +3 -6
- package/src/agents/codex.ts +3 -6
- package/src/agents/copilot.ts +3 -6
- package/src/agents/cursor.ts +3 -6
- package/src/agents/deepagents.ts +3 -6
- package/src/agents/droid.ts +3 -6
- package/src/agents/gemini.ts +3 -6
- package/src/agents/goose.ts +3 -6
- package/src/agents/hermes.ts +3 -6
- package/src/agents/kimi.ts +3 -6
- package/src/agents/kiro.ts +3 -6
- package/src/agents/openclaw.ts +3 -6
- package/src/agents/opencode.ts +3 -6
- package/src/agents/qoder.ts +3 -6
- package/src/agents/qwen.ts +3 -6
- package/src/agents/shared-prompt.ts +7 -4
- package/src/commands/run.ts +3 -7
- package/src/mcp-handler.ts +1 -1
- package/src/mcp-tools.ts +78 -7
- package/src/rpc-handler.ts +29 -72
- package/src/spawn-command.ts +3 -1
- package/src/task.ts +2 -3
- package/src/transports/http-transport.ts +4 -5
- package/src/types.ts +0 -1
- package/test/agent-instructions.test.ts +137 -9
- package/test/agent-output-parsing.test.ts +1 -0
- package/test/task-parsing.test.ts +3 -3
- package/dist/commands/plan-generation.md +0 -22
- package/src/commands/plan-generation.md +0 -22
package/palmier-server/spec.md
CHANGED
|
@@ -12,7 +12,7 @@ The host supports **Linux** (systemd) and **Windows** (Task Scheduler for both d
|
|
|
12
12
|
|
|
13
13
|
### 1.2 Components
|
|
14
14
|
|
|
15
|
-
* **Host Binary (Node.js):** Runs persistently on the user's host machine as a NATS + HTTP RPC handler. Manages file system operations (task CRUD), OS-level scheduling (systemd), and task generation. Provides a CLI with commands: `palmier init` (provisioning), `palmier pair` (generate pairing code for device pairing), `palmier clients` (manage client tokens), `palmier run <task-id>` (executes a task via the configured agent tool), `palmier uninstall` (stop daemon and remove all scheduled tasks), and `palmier serve` (persistent RPC handler, default command). The `serve` process always starts a local HTTP server (bound to `127.0.0.1` by default, or `0.0.0.0` if LAN mode is enabled) alongside the NATS transport.
|
|
15
|
+
* **Host Binary (Node.js):** Runs persistently on the user's host machine as a NATS + HTTP RPC handler. Manages file system operations (task CRUD), OS-level scheduling (systemd), and task generation. Provides a CLI with commands: `palmier init` (provisioning), `palmier pair` (generate pairing code for device pairing), `palmier clients` (manage client tokens), `palmier run <task-id>` (executes a task via the configured agent tool), `palmier uninstall` (stop daemon and remove all scheduled tasks), and `palmier serve` (persistent RPC handler, default command). The `serve` process always starts a local HTTP server (bound to `127.0.0.1` by default, or `0.0.0.0` if LAN mode is enabled) alongside the NATS transport. Exposes a localhost-only MCP server at `/mcp` (streamable HTTP transport) with tools: `notify`, `request-input`, `request-confirmation`, `device-geolocation`. The same tools are auto-generated as REST endpoints (`/notify`, `/request-input`, etc.) from a shared tool registry — zero duplication. REST endpoints require `taskId` in the body for session identification. `/request-permission` remains a separate endpoint (not part of the MCP tool registry). MCP sessions track agent names from `initialize` clientInfo for logging and UI display. `palmier run` is a short-lived process invoked by systemd. Task execution is abstracted through an `AgentTool` interface (`src/agents/agent.ts`) so different AI CLI tools can be supported — each agent implements `getPlanGenerationCommandLine()`, `getTaskRunCommandLine()`, and `init()`. The task's `agent` field (e.g., `"claude"`) selects which agent is used.
|
|
16
16
|
|
|
17
17
|
* **Web Server (Node.js):** Serves the PWA assets (React) via `app.palmier.me` (Cloudflare proxied), manages Web Push VAPID keys, and provides host registration. Uses **PostgreSQL** for persistent storage (host registrations, push subscriptions, FCM tokens). Connects to NATS via TCP to subscribe to `host-event.>` for sending push notifications (confirmations, dismissals, completion/failure). For `POST /api/push/respond` (confirmation responses via push notification action buttons), the Web Server forwards the response to the host via the `task.user_input` NATS RPC. Subscribes to `host.*.push.send` NATS subjects to relay push notification requests from the host CLI. Subscribes to `host.*.fcm.geolocation` to relay device geolocation requests via FCM. Co-located with the NATS server on the same machine.
|
|
18
18
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
You are an AI agent executing a task on behalf of the user
|
|
1
|
+
You are an AI agent executing a task on behalf of the user. Follow these instructions carefully.
|
|
2
2
|
|
|
3
3
|
## Reporting Output
|
|
4
4
|
|
|
@@ -13,46 +13,16 @@ When you are done, output exactly one of these markers as the very last line (no
|
|
|
13
13
|
|
|
14
14
|
## Permissions
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Whenever a tool you are trying to use is denied or you lack the required permissions, print each required permission on its own line using this exact format:
|
|
17
17
|
[PALMIER_PERMISSION] <tool_name> | <description>
|
|
18
18
|
|
|
19
19
|
## HTTP Endpoints
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
```json
|
|
25
|
-
{"taskId": "{{TASK_ID}}", "description": "optional context", "questions": ["question 1", "question 2"]}
|
|
26
|
-
```
|
|
27
|
-
- `taskId` (required, string): The current task ID.
|
|
28
|
-
- `questions` (required, string array): Questions to present to the user.
|
|
29
|
-
- `description` (optional, string): Context or heading for the input request.
|
|
30
|
-
- Response: `{"values": ["answer1", "answer2"]}` on success, or `{"aborted": true}` if the user declines.
|
|
31
|
-
- When you need information from the user (credentials, answers to questions, preferences, clarifications, etc.), do not guess, fail, or prompt via stdout, even in a non-interactive environment. Use this endpoint instead.
|
|
32
|
-
|
|
33
|
-
**`POST /request-confirmation`** — Request confirmation from the user. The request blocks until the user confirms or aborts.
|
|
34
|
-
```json
|
|
35
|
-
{"taskId": "{{TASK_ID}}", "description": "What the user is confirming"}
|
|
36
|
-
```
|
|
37
|
-
- `taskId` (required, string): The current task ID.
|
|
38
|
-
- `description` (required, string): What the user is confirming.
|
|
39
|
-
- Response: `{"confirmed": true}` or `{"confirmed": false}`.
|
|
40
|
-
|
|
41
|
-
**`POST /device-geolocation`** — Get the GPS location of the user's mobile device. Blocks until the device responds (up to 30 seconds).
|
|
42
|
-
```json
|
|
43
|
-
{"taskId": "{{TASK_ID}}"}
|
|
44
|
-
```
|
|
45
|
-
- `taskId` (required, string): The current task ID.
|
|
46
|
-
- Response: `{"latitude": ..., "longitude": ..., "accuracy": ..., "timestamp": ...}` on success, or `{"error": "..."}` on failure.
|
|
47
|
-
|
|
48
|
-
**`POST /notify`** — Send a push notification to the user's device.
|
|
49
|
-
```json
|
|
50
|
-
{"taskId": "{{TASK_ID}}", "title": "...", "body": "..."}
|
|
51
|
-
```
|
|
52
|
-
- `taskId` (required, string): The current task ID.
|
|
53
|
-
- `title` (required, string): Notification title.
|
|
54
|
-
- `body` (required, string): Notification body.
|
|
21
|
+
{{ENDPOINT_DOCS}}
|
|
22
|
+
|
|
23
|
+
The task to execute follows below:
|
|
55
24
|
|
|
56
25
|
---
|
|
57
26
|
|
|
58
|
-
|
|
27
|
+
{{TASK_DESCRIPTION}}
|
|
28
|
+
|
package/src/agents/agent.ts
CHANGED
|
@@ -31,8 +31,8 @@ export interface CommandLine {
|
|
|
31
31
|
* Abstracts how plans are generated and tasks are executed across different AI agents.
|
|
32
32
|
*/
|
|
33
33
|
export interface AgentTool {
|
|
34
|
-
/** Return the command and args
|
|
35
|
-
|
|
34
|
+
/** Return the command and args for a short, non-interactive prompt (e.g. generating a task name). */
|
|
35
|
+
getPromptCommandLine(prompt: string): CommandLine;
|
|
36
36
|
|
|
37
37
|
/** Return the command and args used to run a task. If followupPrompt is provided, use it instead of the task's prompt,
|
|
38
38
|
* and treat it as a continuation of the original run (reuse the same session, etc).
|
package/src/agents/aider.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class Aider implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "aider",
|
|
12
|
-
args: ["--message", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "aider", args: ["--message", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = [];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/claude.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class ClaudeAgent implements AgentTool {
|
|
8
8
|
supportsPermissions = true;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "claude",
|
|
12
|
-
args: ["-p", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "claude", args: ["-p", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = ["--permission-mode", yolo ? "bypassPermissions" : "acceptEdits", "-p"];
|
|
20
17
|
|
|
21
18
|
if (!yolo) {
|
package/src/agents/cline.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class Cline implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "cline ",
|
|
12
|
-
args: ["--yolo", "-p", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "cline ", args: ["--yolo", "-p", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = [];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/codex.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class CodexAgent implements AgentTool {
|
|
8
8
|
supportsPermissions = true;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "codex",
|
|
12
|
-
args: ["exec", "--skip-git-repo-check", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "codex", args: ["exec", "--skip-git-repo-check", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = ["exec", "--skip-git-repo-check", "--sandbox", yolo ? "danger-full-access" : "workspace-write"];
|
|
20
17
|
|
|
21
18
|
if (!yolo) {
|
package/src/agents/copilot.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class CopilotAgent implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "copilot",
|
|
12
|
-
args: ["-p", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "copilot", args: ["-p", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = ["-p", prompt];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/cursor.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class Cursor implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "cursor",
|
|
12
|
-
args: ["-p", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "cursor", args: ["-p", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = [];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/deepagents.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class DeepAgents implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "deepagents",
|
|
12
|
-
args: ["--non-interactive", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "deepagents", args: ["--non-interactive", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = [];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/droid.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class DroidAgent implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "droid",
|
|
12
|
-
args: ["exec", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "droid", args: ["exec", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = ["exec", "--session-id", task.frontmatter.id];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/gemini.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class GeminiAgent implements AgentTool {
|
|
8
8
|
supportsPermissions = true;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "gemini",
|
|
12
|
-
args: ["--prompt", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "gemini", args: ["--prompt", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = ["--approval-mode", yolo ? "yolo" : "auto_edit"];
|
|
20
17
|
|
|
21
18
|
if (!yolo) {
|
package/src/agents/goose.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class GooseAgent implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "goose",
|
|
12
|
-
args: ["run", "--text", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "goose", args: ["run", "--text", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = ["run"];
|
|
20
17
|
|
|
21
18
|
if (followupPrompt) {args.push("--resume");} // continue mode for followups
|
package/src/agents/hermes.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class Hermes implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "hermes",
|
|
12
|
-
args: ["chat", "-q", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "hermes", args: ["chat", "-q", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = ["chat"];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/kimi.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class KimiAgent implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "kimi",
|
|
12
|
-
args: ["-p", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "kimi", args: ["-p", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = [];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/kiro.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class Kiro implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "kiro-cli",
|
|
12
|
-
args: ["--no-interactive", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "kiro-cli", args: ["--no-interactive", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = [];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/openclaw.ts
CHANGED
|
@@ -5,16 +5,13 @@ import { getAgentInstructions } from "./shared-prompt.js";
|
|
|
5
5
|
|
|
6
6
|
export class OpenClawAgent implements AgentTool {
|
|
7
7
|
supportsPermissions = false;
|
|
8
|
-
|
|
9
|
-
return {
|
|
10
|
-
command: "openclaw",
|
|
11
|
-
args: ["agent", "--local", "--agent", "main", "--message", prompt],
|
|
12
|
-
};
|
|
8
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
9
|
+
return { command: "openclaw", args: ["agent", "--local", "--agent", "main", "--message", prompt] };
|
|
13
10
|
}
|
|
14
11
|
|
|
15
12
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
16
13
|
const yolo = extraPermissions === "yolo";
|
|
17
|
-
const prompt = followupPrompt ??
|
|
14
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
18
15
|
// OpenClaw does not support stdin as prompt.
|
|
19
16
|
const args = ["agent", "--local", "--session-id", task.frontmatter.id, "--message", prompt];
|
|
20
17
|
|
package/src/agents/opencode.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class OpenCodeAgent implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "opencode",
|
|
12
|
-
args: ["run", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "opencode", args: ["run", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = ["run"];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/qoder.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class Qoder implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "qodercli",
|
|
12
|
-
args: ["-p", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "qodercli", args: ["-p", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = [];
|
|
20
17
|
|
|
21
18
|
if (yolo) {
|
package/src/agents/qwen.ts
CHANGED
|
@@ -6,16 +6,13 @@ import { SHELL } from "../platform/index.js";
|
|
|
6
6
|
|
|
7
7
|
export class QwenAgent implements AgentTool {
|
|
8
8
|
supportsPermissions = false;
|
|
9
|
-
|
|
10
|
-
return {
|
|
11
|
-
command: "qwen",
|
|
12
|
-
args: ["-p", prompt],
|
|
13
|
-
};
|
|
9
|
+
getPromptCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return { command: "qwen", args: ["-p", prompt] };
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
14
|
const yolo = extraPermissions === "yolo";
|
|
18
|
-
const prompt = followupPrompt ??
|
|
15
|
+
const prompt = followupPrompt ?? getAgentInstructions(task, yolo || !this.supportsPermissions);
|
|
19
16
|
const args = ["--approval-mode", yolo ? "yolo" : "auto-edit"];
|
|
20
17
|
|
|
21
18
|
if (followupPrompt) { args.push("-c"); }
|
|
@@ -2,6 +2,8 @@ import * as fs from "fs";
|
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
import { loadConfig } from "../config.js";
|
|
5
|
+
import { generateEndpointDocs } from "../mcp-tools.js";
|
|
6
|
+
import type { ParsedTask } from "../types.js";
|
|
5
7
|
|
|
6
8
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
9
|
|
|
@@ -11,13 +13,14 @@ const AGENT_INSTRUCTIONS_TEMPLATE = fs.readFileSync(
|
|
|
11
13
|
);
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
|
-
*
|
|
16
|
+
* Build the full agent prompt: instructions + endpoint docs + task description.
|
|
15
17
|
*/
|
|
16
|
-
export function getAgentInstructions(
|
|
18
|
+
export function getAgentInstructions(task: ParsedTask, skipPermissions?: boolean): string {
|
|
17
19
|
const port = loadConfig().httpPort ?? 9966;
|
|
20
|
+
const taskDescription = task.frontmatter.user_prompt;
|
|
18
21
|
let instructions = AGENT_INSTRUCTIONS_TEMPLATE
|
|
19
|
-
.replace(/\{\{
|
|
20
|
-
.replace(/\{\{
|
|
22
|
+
.replace(/\{\{ENDPOINT_DOCS\}\}/g, generateEndpointDocs(port, task.frontmatter.id))
|
|
23
|
+
.replace(/\{\{TASK_DESCRIPTION\}\}/g, taskDescription);
|
|
21
24
|
if (skipPermissions) {
|
|
22
25
|
instructions = instructions.replace(/## Permissions\r?\n[\s\S]*?(?=## |\r?\n---)/m, "");
|
|
23
26
|
}
|
package/src/commands/run.ts
CHANGED
|
@@ -65,9 +65,6 @@ async function invokeAgentWithRetries(
|
|
|
65
65
|
const { command, args, stdin, env: agentEnv } = ctx.agent.getTaskRunCommandLine(
|
|
66
66
|
invokeTask, undefined, ctx.task.frontmatter.yolo_mode ? "yolo" : ctx.transientPermissions,
|
|
67
67
|
);
|
|
68
|
-
const truncate = (s: string, max = 100) => s.length > max ? s.slice(0, max) + "…" : s;
|
|
69
|
-
const displayArgs = args.map((a) => truncate(a));
|
|
70
|
-
console.log(`[invoke] ${command} ${displayArgs.join(" ")}${stdin ? ` (stdin: ${truncate(stdin, 100)})` : ""}`);
|
|
71
68
|
const result = await spawnCommand(command, args, {
|
|
72
69
|
cwd: getRunDir(ctx.taskDir, ctx.runId),
|
|
73
70
|
env: { ...ctx.guiEnv, ...agentEnv, PALMIER_RUN_DIR: getRunDir(ctx.taskDir, ctx.runId), PALMIER_HTTP_PORT: String(ctx.config.httpPort ?? 9966) },
|
|
@@ -275,7 +272,7 @@ export async function runCommand(taskId: string): Promise<void> {
|
|
|
275
272
|
await appendAndNotify(ctx, {
|
|
276
273
|
role: "user",
|
|
277
274
|
time: Date.now(),
|
|
278
|
-
content: task.
|
|
275
|
+
content: task.frontmatter.user_prompt,
|
|
279
276
|
});
|
|
280
277
|
|
|
281
278
|
const result = await invokeAgentWithRetries(ctx, task);
|
|
@@ -365,7 +362,6 @@ async function runCommandTriggeredMode(
|
|
|
365
362
|
const perLinePrompt = `${ctx.task.frontmatter.user_prompt}\n\nProcess this input:\n${line}`;
|
|
366
363
|
const perLineTask: ParsedTask = {
|
|
367
364
|
frontmatter: { ...ctx.task.frontmatter, user_prompt: perLinePrompt },
|
|
368
|
-
body: "",
|
|
369
365
|
};
|
|
370
366
|
|
|
371
367
|
const result = await invokeAgentWithRetries(ctx, perLineTask);
|
|
@@ -516,10 +512,10 @@ async function requestConfirmation(
|
|
|
516
512
|
taskDir: string,
|
|
517
513
|
): Promise<boolean> {
|
|
518
514
|
const port = config.httpPort ?? 9966;
|
|
519
|
-
const res = await fetch(`http://localhost:${port}/request-confirmation`, {
|
|
515
|
+
const res = await fetch(`http://localhost:${port}/request-confirmation?taskId=${encodeURIComponent(task.frontmatter.id)}`, {
|
|
520
516
|
method: "POST",
|
|
521
517
|
headers: { "Content-Type": "application/json" },
|
|
522
|
-
body: JSON.stringify({
|
|
518
|
+
body: JSON.stringify({ description: `Run task "${task.frontmatter.name || task.frontmatter.id}"?` }),
|
|
523
519
|
});
|
|
524
520
|
const body = await res.json() as { confirmed?: boolean; error?: string };
|
|
525
521
|
if (typeof body.confirmed !== "boolean") {
|
package/src/mcp-handler.ts
CHANGED
|
@@ -90,7 +90,7 @@ export async function handleMcpRequest(body: string, sessionId: string | undefin
|
|
|
90
90
|
body: rpcResult(id, {
|
|
91
91
|
tools: agentTools.map((t) => ({
|
|
92
92
|
name: t.name,
|
|
93
|
-
description: t.description,
|
|
93
|
+
description: t.description.join(" "),
|
|
94
94
|
inputSchema: t.inputSchema,
|
|
95
95
|
})),
|
|
96
96
|
}),
|