palmier 0.6.8 → 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/dist/agents/agent.d.ts +2 -2
- package/dist/agents/aider.d.ts +1 -1
- package/dist/agents/aider.js +2 -5
- package/dist/agents/claude.d.ts +1 -1
- package/dist/agents/claude.js +2 -5
- package/dist/agents/cline.d.ts +1 -1
- package/dist/agents/cline.js +2 -5
- package/dist/agents/codex.d.ts +1 -1
- package/dist/agents/codex.js +2 -5
- package/dist/agents/copilot.d.ts +1 -1
- package/dist/agents/copilot.js +2 -5
- package/dist/agents/cursor.d.ts +1 -1
- package/dist/agents/cursor.js +2 -5
- package/dist/agents/deepagents.d.ts +1 -1
- package/dist/agents/deepagents.js +2 -5
- package/dist/agents/droid.d.ts +1 -1
- package/dist/agents/droid.js +2 -5
- package/dist/agents/gemini.d.ts +1 -1
- package/dist/agents/gemini.js +2 -5
- package/dist/agents/goose.d.ts +1 -1
- package/dist/agents/goose.js +2 -5
- package/dist/agents/hermes.d.ts +1 -1
- package/dist/agents/hermes.js +2 -5
- package/dist/agents/kimi.d.ts +1 -1
- package/dist/agents/kimi.js +2 -5
- package/dist/agents/kiro.d.ts +1 -1
- package/dist/agents/kiro.js +2 -5
- package/dist/agents/openclaw.d.ts +1 -1
- package/dist/agents/openclaw.js +2 -5
- package/dist/agents/opencode.d.ts +1 -1
- package/dist/agents/opencode.js +2 -5
- package/dist/agents/qoder.d.ts +1 -1
- package/dist/agents/qoder.js +2 -5
- package/dist/agents/qwen.d.ts +1 -1
- package/dist/agents/qwen.js +2 -5
- package/dist/agents/shared-prompt.js +1 -1
- package/dist/commands/run.js +1 -2
- package/dist/mcp-tools.d.ts +1 -1
- package/dist/mcp-tools.js +2 -2
- package/dist/pwa/assets/{index-C8vJwUNi.js → index-CZejk2al.js} +1 -1
- package/dist/pwa/assets/{web-NxTETXZK.js → web-C48txJFl.js} +1 -1
- package/dist/pwa/assets/{web-6UChJFov.js → web-zj8Blync.js} +1 -1
- package/dist/pwa/index.html +1 -1
- package/dist/pwa/service-worker.js +1 -1
- package/dist/rpc-handler.js +27 -67
- package/dist/task.js +2 -3
- package/dist/types.d.ts +0 -1
- package/package.json +2 -2
- package/palmier-server/pwa/src/constants.ts +1 -1
- package/src/agents/agent.ts +2 -2
- package/src/agents/aider.ts +2 -5
- package/src/agents/claude.ts +2 -5
- package/src/agents/cline.ts +2 -5
- package/src/agents/codex.ts +2 -5
- package/src/agents/copilot.ts +2 -5
- package/src/agents/cursor.ts +2 -5
- package/src/agents/deepagents.ts +2 -5
- package/src/agents/droid.ts +2 -5
- package/src/agents/gemini.ts +2 -5
- package/src/agents/goose.ts +2 -5
- package/src/agents/hermes.ts +2 -5
- package/src/agents/kimi.ts +2 -5
- package/src/agents/kiro.ts +2 -5
- package/src/agents/openclaw.ts +2 -5
- package/src/agents/opencode.ts +2 -5
- package/src/agents/qoder.ts +2 -5
- package/src/agents/qwen.ts +2 -5
- package/src/agents/shared-prompt.ts +1 -1
- package/src/commands/run.ts +1 -2
- package/src/mcp-tools.ts +2 -2
- package/src/rpc-handler.ts +29 -71
- package/src/task.ts +2 -3
- package/src/types.ts +0 -1
- package/test/agent-instructions.test.ts +84 -19
- 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/test/fixtures/agent-instructions-snapshot.md +0 -58
package/dist/task.js
CHANGED
|
@@ -22,14 +22,13 @@ export function parseTaskContent(content) {
|
|
|
22
22
|
throw new Error("TASK.md is missing valid YAML frontmatter delimiters (---)");
|
|
23
23
|
}
|
|
24
24
|
const frontmatter = parseYaml(match[1]);
|
|
25
|
-
const body = (match[2] || "").trim();
|
|
26
25
|
if (!frontmatter.id) {
|
|
27
26
|
throw new Error("TASK.md frontmatter must include at least: id");
|
|
28
27
|
}
|
|
29
28
|
frontmatter.name ??= frontmatter.user_prompt?.slice(0, 60) ?? "";
|
|
30
29
|
frontmatter.agent ??= "claude";
|
|
31
30
|
frontmatter.triggers_enabled ??= true;
|
|
32
|
-
return { frontmatter
|
|
31
|
+
return { frontmatter };
|
|
33
32
|
}
|
|
34
33
|
/**
|
|
35
34
|
* Write a TASK.md file to the given task directory.
|
|
@@ -38,7 +37,7 @@ export function parseTaskContent(content) {
|
|
|
38
37
|
export function writeTaskFile(taskDir, task) {
|
|
39
38
|
fs.mkdirSync(taskDir, { recursive: true });
|
|
40
39
|
const yamlStr = stringifyYaml(task.frontmatter).trim();
|
|
41
|
-
const content = `---\n${yamlStr}\n---\n
|
|
40
|
+
const content = `---\n${yamlStr}\n---\n`;
|
|
42
41
|
const filePath = path.join(taskDir, "TASK.md");
|
|
43
42
|
fs.writeFileSync(filePath, content, "utf-8");
|
|
44
43
|
}
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "palmier",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"description": "Palmier host CLI - provisions, executes tasks, and serves NATS RPC",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Hongxu Cai",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"dev": "tsx src/index.ts",
|
|
23
|
-
"build": "tsc && node -e \"const fs=require('fs');fs.cpSync('src/
|
|
23
|
+
"build": "tsc && node -e \"const fs=require('fs');fs.cpSync('src/agents/agent-instructions.md','dist/agents/agent-instructions.md');const p=process.env.PALMIER_PWA_DIST||'../palmier-server/pwa/dist';if(fs.existsSync(p))fs.cpSync(p,'dist/pwa',{recursive:true});else console.warn('PWA dist not found at '+p+', skipping')\"",
|
|
24
24
|
"test": "tsx --test test/**/*.test.ts",
|
|
25
25
|
"prepare": "npm run build",
|
|
26
26
|
"start": "node dist/index.js"
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Bump when a breaking host change is made. */
|
|
2
|
-
export const MIN_HOST_VERSION = "0.6.
|
|
2
|
+
export const MIN_HOST_VERSION = "0.6.8";
|
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,11 +6,8 @@ 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 {
|
package/src/agents/claude.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/cline.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/codex.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/copilot.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/cursor.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/deepagents.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/droid.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/gemini.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/goose.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/hermes.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/kimi.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/kiro.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/openclaw.ts
CHANGED
|
@@ -5,11 +5,8 @@ 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 {
|
package/src/agents/opencode.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/qoder.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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 {
|
package/src/agents/qwen.ts
CHANGED
|
@@ -6,11 +6,8 @@ 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,7 +17,7 @@ const AGENT_INSTRUCTIONS_TEMPLATE = fs.readFileSync(
|
|
|
17
17
|
*/
|
|
18
18
|
export function getAgentInstructions(task: ParsedTask, skipPermissions?: boolean): string {
|
|
19
19
|
const port = loadConfig().httpPort ?? 9966;
|
|
20
|
-
const taskDescription = task.
|
|
20
|
+
const taskDescription = task.frontmatter.user_prompt;
|
|
21
21
|
let instructions = AGENT_INSTRUCTIONS_TEMPLATE
|
|
22
22
|
.replace(/\{\{ENDPOINT_DOCS\}\}/g, generateEndpointDocs(port, task.frontmatter.id))
|
|
23
23
|
.replace(/\{\{TASK_DESCRIPTION\}\}/g, taskDescription);
|
package/src/commands/run.ts
CHANGED
|
@@ -272,7 +272,7 @@ export async function runCommand(taskId: string): Promise<void> {
|
|
|
272
272
|
await appendAndNotify(ctx, {
|
|
273
273
|
role: "user",
|
|
274
274
|
time: Date.now(),
|
|
275
|
-
content: task.
|
|
275
|
+
content: task.frontmatter.user_prompt,
|
|
276
276
|
});
|
|
277
277
|
|
|
278
278
|
const result = await invokeAgentWithRetries(ctx, task);
|
|
@@ -362,7 +362,6 @@ async function runCommandTriggeredMode(
|
|
|
362
362
|
const perLinePrompt = `${ctx.task.frontmatter.user_prompt}\n\nProcess this input:\n${line}`;
|
|
363
363
|
const perLineTask: ParsedTask = {
|
|
364
364
|
frontmatter: { ...ctx.task.frontmatter, user_prompt: perLinePrompt },
|
|
365
|
-
body: "",
|
|
366
365
|
};
|
|
367
366
|
|
|
368
367
|
const result = await invokeAgentWithRetries(ctx, perLineTask);
|
package/src/mcp-tools.ts
CHANGED
|
@@ -208,14 +208,14 @@ export const agentToolMap = new Map<string, ToolDefinition>(agentTools.map((t) =
|
|
|
208
208
|
/**
|
|
209
209
|
* Generate the HTTP Endpoints markdown section for agent-instructions.md from the tool registry.
|
|
210
210
|
*/
|
|
211
|
-
export function generateEndpointDocs(port: number, taskId: string): string {
|
|
211
|
+
export function generateEndpointDocs(port: number, taskId: string, tools: ToolDefinition[] = agentTools): string {
|
|
212
212
|
const baseUrl = `http://localhost:${port}`;
|
|
213
213
|
const lines: string[] = [
|
|
214
214
|
`The following HTTP endpoints are available during task execution. Use curl to call them.`,
|
|
215
215
|
"",
|
|
216
216
|
];
|
|
217
217
|
|
|
218
|
-
for (const tool of
|
|
218
|
+
for (const tool of tools) {
|
|
219
219
|
const schema = tool.inputSchema as { properties?: Record<string, { type?: string; description?: string; items?: { type?: string } }>; required?: string[] };
|
|
220
220
|
const props = schema.properties ?? {};
|
|
221
221
|
const required = new Set(schema.required ?? []);
|
package/src/rpc-handler.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as path from "path";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
4
|
import { spawn, type ChildProcess } from "child_process";
|
|
6
|
-
import { parse as parseYaml } from "yaml";
|
|
7
5
|
import { type NatsConnection } from "nats";
|
|
8
6
|
import { listTasks, parseTaskFile, writeTaskFile, getTaskDir, readTaskStatus, writeTaskStatus, readHistory, deleteHistoryEntry, appendTaskList, removeFromTaskList, appendHistory, createRunDir, appendRunMessage, getRunDir } from "./task.js";
|
|
9
7
|
import { resolvePending, getPending } from "./pending-requests.js";
|
|
@@ -18,13 +16,6 @@ import { currentVersion, performUpdate } from "./update-checker.js";
|
|
|
18
16
|
import { parseReportFiles, parseTaskOutcome, stripPalmierMarkers } from "./commands/run.js";
|
|
19
17
|
import type { HostConfig, ParsedTask, RpcMessage, ConversationMessage } from "./types.js";
|
|
20
18
|
|
|
21
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
22
|
-
|
|
23
|
-
const PLAN_GENERATION_PROMPT = fs.readFileSync(
|
|
24
|
-
path.join(__dirname, "commands", "plan-generation.md"),
|
|
25
|
-
"utf-8",
|
|
26
|
-
);
|
|
27
|
-
|
|
28
19
|
/**
|
|
29
20
|
* Parse RESULT frontmatter and conversation messages.
|
|
30
21
|
*/
|
|
@@ -115,39 +106,30 @@ function parseAttr(attrs: string, name: string): string | undefined {
|
|
|
115
106
|
}
|
|
116
107
|
|
|
117
108
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
109
|
+
* Generate a concise task name from a user prompt using the given agent.
|
|
110
|
+
* Falls back to the raw prompt on failure.
|
|
120
111
|
*/
|
|
121
|
-
async function
|
|
112
|
+
async function generateName(
|
|
122
113
|
projectRoot: string,
|
|
123
114
|
userPrompt: string,
|
|
124
115
|
agentName: string,
|
|
125
|
-
): Promise<
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
const { command, args, stdin, env: agentEnv } =
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (fmMatch) {
|
|
142
|
-
try {
|
|
143
|
-
const fm = parseYaml(fmMatch[1]) as { task_name?: string };
|
|
144
|
-
name = fm.task_name ?? "";
|
|
145
|
-
} catch {
|
|
146
|
-
// If frontmatter parsing fails, treat entire output as body
|
|
147
|
-
}
|
|
148
|
-
body = fmMatch[2].trimStart();
|
|
116
|
+
): Promise<string> {
|
|
117
|
+
const prompt = `Generate a concise 3-6 word name for this task. Reply with ONLY the name, nothing else.\n\nTask: ${userPrompt}`;
|
|
118
|
+
const agent = getAgent(agentName);
|
|
119
|
+
const { command, args, stdin, env: agentEnv } = agent.getPromptCommandLine(prompt);
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const { output } = await spawnCommand(command, args, {
|
|
123
|
+
cwd: projectRoot,
|
|
124
|
+
timeout: 30_000,
|
|
125
|
+
stdin,
|
|
126
|
+
...(agentEnv ? { env: agentEnv } : {}),
|
|
127
|
+
});
|
|
128
|
+
const name = output.trim().replace(/^["']|["']$/g, "").slice(0, 80);
|
|
129
|
+
return name || userPrompt;
|
|
130
|
+
} catch {
|
|
131
|
+
return userPrompt;
|
|
149
132
|
}
|
|
150
|
-
return { name, body };
|
|
151
133
|
}
|
|
152
134
|
|
|
153
135
|
/** Active follow-up child processes, keyed by "taskId:runId". */
|
|
@@ -163,7 +145,6 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
|
|
|
163
145
|
const pending = getPending(task.frontmatter.id);
|
|
164
146
|
return {
|
|
165
147
|
...task.frontmatter,
|
|
166
|
-
body: task.body,
|
|
167
148
|
status: status ? {
|
|
168
149
|
...status,
|
|
169
150
|
...(pending?.type === "permission" ? { pending_permission: pending.params } : {}),
|
|
@@ -215,25 +196,13 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
|
|
|
215
196
|
command?: string;
|
|
216
197
|
};
|
|
217
198
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if (params.user_prompt.length <= 50) {
|
|
222
|
-
name = params.user_prompt;
|
|
223
|
-
} else {
|
|
224
|
-
try {
|
|
225
|
-
const plan = await generatePlan(config.projectRoot, params.user_prompt, params.agent);
|
|
226
|
-
name = plan.name;
|
|
227
|
-
body = plan.body;
|
|
228
|
-
} catch (err: unknown) {
|
|
229
|
-
const error = err as { stdout?: string; stderr?: string };
|
|
230
|
-
return { error: "plan generation failed", stdout: error.stdout, stderr: error.stderr };
|
|
231
|
-
}
|
|
232
|
-
}
|
|
199
|
+
const name = params.user_prompt.length <= 50
|
|
200
|
+
? params.user_prompt
|
|
201
|
+
: await generateName(config.projectRoot, params.user_prompt, params.agent);
|
|
233
202
|
|
|
234
203
|
const id = randomUUID();
|
|
235
204
|
const taskDir = getTaskDir(config.projectRoot, id);
|
|
236
|
-
const task = {
|
|
205
|
+
const task: ParsedTask = {
|
|
237
206
|
frontmatter: {
|
|
238
207
|
id,
|
|
239
208
|
name,
|
|
@@ -246,7 +215,6 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
|
|
|
246
215
|
...(params.foreground_mode ? { foreground_mode: true } : {}),
|
|
247
216
|
...(params.command ? { command: params.command } : {}),
|
|
248
217
|
},
|
|
249
|
-
body,
|
|
250
218
|
};
|
|
251
219
|
|
|
252
220
|
writeTaskFile(taskDir, task);
|
|
@@ -272,10 +240,9 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
|
|
|
272
240
|
const taskDir = getTaskDir(config.projectRoot, params.id);
|
|
273
241
|
const existing = parseTaskFile(taskDir);
|
|
274
242
|
|
|
275
|
-
// Detect whether
|
|
243
|
+
// Detect whether name needs regeneration
|
|
276
244
|
const promptChanged = params.user_prompt !== undefined && params.user_prompt !== existing.frontmatter.user_prompt;
|
|
277
245
|
const agentChanged = params.agent !== undefined && params.agent !== existing.frontmatter.agent;
|
|
278
|
-
const needsRegeneration = promptChanged || agentChanged || !existing.body;
|
|
279
246
|
|
|
280
247
|
// Merge updates
|
|
281
248
|
if (params.user_prompt !== undefined) existing.frontmatter.user_prompt = params.user_prompt;
|
|
@@ -297,19 +264,11 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
|
|
|
297
264
|
}
|
|
298
265
|
}
|
|
299
266
|
|
|
300
|
-
// Regenerate
|
|
301
|
-
if (
|
|
302
|
-
existing.frontmatter.name = existing.frontmatter.user_prompt
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
try {
|
|
306
|
-
const plan = await generatePlan(config.projectRoot, existing.frontmatter.user_prompt, existing.frontmatter.agent);
|
|
307
|
-
existing.frontmatter.name = plan.name;
|
|
308
|
-
existing.body = plan.body;
|
|
309
|
-
} catch (err: unknown) {
|
|
310
|
-
const error = err as { stdout?: string; stderr?: string };
|
|
311
|
-
return { error: "plan generation failed", stdout: error.stdout, stderr: error.stderr };
|
|
312
|
-
}
|
|
267
|
+
// Regenerate name when prompt or agent changes
|
|
268
|
+
if (promptChanged || agentChanged) {
|
|
269
|
+
existing.frontmatter.name = existing.frontmatter.user_prompt.length <= 50
|
|
270
|
+
? existing.frontmatter.user_prompt
|
|
271
|
+
: await generateName(config.projectRoot, existing.frontmatter.user_prompt, existing.frontmatter.agent);
|
|
313
272
|
}
|
|
314
273
|
|
|
315
274
|
writeTaskFile(taskDir, existing);
|
|
@@ -356,7 +315,6 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
|
|
|
356
315
|
...(params.foreground_mode ? { foreground_mode: true } : {}),
|
|
357
316
|
...(params.command ? { command: params.command } : {}),
|
|
358
317
|
},
|
|
359
|
-
body: "",
|
|
360
318
|
};
|
|
361
319
|
|
|
362
320
|
writeTaskFile(taskDir, task);
|
package/src/task.ts
CHANGED
|
@@ -29,7 +29,6 @@ export function parseTaskContent(content: string): ParsedTask {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
const frontmatter = parseYaml(match[1]) as TaskFrontmatter;
|
|
32
|
-
const body = (match[2] || "").trim();
|
|
33
32
|
|
|
34
33
|
if (!frontmatter.id) {
|
|
35
34
|
throw new Error("TASK.md frontmatter must include at least: id");
|
|
@@ -39,7 +38,7 @@ export function parseTaskContent(content: string): ParsedTask {
|
|
|
39
38
|
frontmatter.agent ??= "claude";
|
|
40
39
|
frontmatter.triggers_enabled ??= true;
|
|
41
40
|
|
|
42
|
-
return { frontmatter
|
|
41
|
+
return { frontmatter };
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
/**
|
|
@@ -50,7 +49,7 @@ export function writeTaskFile(taskDir: string, task: ParsedTask): void {
|
|
|
50
49
|
fs.mkdirSync(taskDir, { recursive: true });
|
|
51
50
|
|
|
52
51
|
const yamlStr = stringifyYaml(task.frontmatter).trim();
|
|
53
|
-
const content = `---\n${yamlStr}\n---\n
|
|
52
|
+
const content = `---\n${yamlStr}\n---\n`;
|
|
54
53
|
|
|
55
54
|
const filePath = path.join(taskDir, "TASK.md");
|
|
56
55
|
fs.writeFileSync(filePath, content, "utf-8");
|