palmier 0.6.1 → 0.6.2
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/DISCLAIMER.md +2 -2
- package/dist/agents/agent-instructions.md +1 -1
- package/dist/agents/agent.d.ts +2 -0
- package/dist/agents/agent.js +21 -0
- package/dist/agents/aider.d.ts +9 -0
- package/dist/agents/aider.js +32 -0
- package/dist/agents/cursor.d.ts +9 -0
- package/dist/agents/cursor.js +35 -0
- package/dist/agents/deepagents.d.ts +9 -0
- package/dist/agents/deepagents.js +35 -0
- package/dist/agents/droid.d.ts +9 -0
- package/dist/agents/droid.js +32 -0
- package/dist/agents/goose.d.ts +9 -0
- package/dist/agents/goose.js +32 -0
- package/dist/agents/opencode.d.ts +9 -0
- package/dist/agents/opencode.js +35 -0
- package/dist/agents/openhands.d.ts +9 -0
- package/dist/agents/openhands.js +35 -0
- package/dist/commands/run.js +2 -2
- package/dist/pwa/assets/{index-C7Ib48wG.js → index-ByhOhTz1.js} +1 -1
- package/dist/pwa/index.html +2 -2
- package/dist/pwa/manifest.webmanifest +1 -1
- package/dist/pwa/service-worker.js +1 -1
- package/dist/rpc-handler.js +4 -3
- package/dist/transports/http-transport.js +3 -1
- package/package.json +1 -1
- package/palmier-server/pwa/index.html +1 -1
- package/palmier-server/pwa/src/constants.ts +1 -1
- package/palmier-server/pwa/src/service-worker.ts +3 -3
- package/palmier-server/pwa/vite.config.ts +1 -1
- package/palmier-server/server/src/index.ts +2 -0
- package/palmier-server/spec.md +1 -1
- package/src/agents/agent-instructions.md +1 -1
- package/src/agents/agent.ts +23 -0
- package/src/agents/aider.ts +37 -0
- package/src/agents/cursor.ts +38 -0
- package/src/agents/deepagents.ts +38 -0
- package/src/agents/droid.ts +37 -0
- package/src/agents/goose.ts +35 -0
- package/src/agents/opencode.ts +38 -0
- package/src/agents/openhands.ts +38 -0
- package/src/commands/run.ts +2 -2
- package/src/rpc-handler.ts +4 -3
- package/src/transports/http-transport.ts +3 -2
package/src/agents/agent.ts
CHANGED
|
@@ -2,16 +2,25 @@ import type { ParsedTask, RequiredPermission } from "../types.js";
|
|
|
2
2
|
import { ClaudeAgent } from "./claude.js";
|
|
3
3
|
import { GeminiAgent } from "./gemini.js";
|
|
4
4
|
import { CodexAgent } from "./codex.js";
|
|
5
|
+
import { DroidAgent } from "./droid.js";
|
|
5
6
|
import { OpenClawAgent } from "./openclaw.js";
|
|
6
7
|
import { CopilotAgent } from "./copilot.js";
|
|
7
8
|
import { QwenAgent } from "./qwen.js";
|
|
8
9
|
import { KimiAgent } from "./kimi.js";
|
|
10
|
+
import { GooseAgent } from "./goose.js";
|
|
11
|
+
import { OpenCodeAgent } from "./opencode.js";
|
|
12
|
+
import { DeepAgents } from "./deepagents.js";
|
|
13
|
+
import { Aider } from "./aider.js";
|
|
14
|
+
import { OpenHands } from "./openhands.js";
|
|
15
|
+
import { Cursor } from "./cursor.js";
|
|
9
16
|
|
|
10
17
|
export interface CommandLine {
|
|
11
18
|
command: string;
|
|
12
19
|
args: string[];
|
|
13
20
|
/** If provided, the string is written to the process's stdin and then the pipe is closed. */
|
|
14
21
|
stdin?: string;
|
|
22
|
+
/** Additional environment variables to set for the spawned process. */
|
|
23
|
+
env?: Record<string, string>;
|
|
15
24
|
}
|
|
16
25
|
|
|
17
26
|
/**
|
|
@@ -45,16 +54,30 @@ const agentRegistry: Record<string, AgentTool> = {
|
|
|
45
54
|
copilot: new CopilotAgent(),
|
|
46
55
|
qwen: new QwenAgent(),
|
|
47
56
|
kimi: new KimiAgent(),
|
|
57
|
+
droid: new DroidAgent(),
|
|
58
|
+
goose: new GooseAgent(),
|
|
59
|
+
opencode: new OpenCodeAgent(),
|
|
60
|
+
deepagents: new DeepAgents(),
|
|
61
|
+
aider: new Aider(),
|
|
62
|
+
openhands: new OpenHands(),
|
|
63
|
+
cursor: new Cursor(),
|
|
48
64
|
};
|
|
49
65
|
|
|
50
66
|
const agentLabels: Record<string, string> = {
|
|
51
67
|
claude: "Claude Code",
|
|
52
68
|
gemini: "Gemini CLI",
|
|
53
69
|
codex: "Codex CLI",
|
|
70
|
+
droid: "Droid CLI",
|
|
54
71
|
openclaw: "OpenClaw",
|
|
55
72
|
copilot: "Copilot CLI",
|
|
56
73
|
qwen: "Qwen Code",
|
|
57
74
|
kimi: "Kimi Code",
|
|
75
|
+
goose: "Goose CLI",
|
|
76
|
+
opencode: "OpenCode",
|
|
77
|
+
deepagents: "Deep Agents CLI",
|
|
78
|
+
aider: "Aider",
|
|
79
|
+
openhands: "OpenHands",
|
|
80
|
+
cursor: "Cursor CLI",
|
|
58
81
|
};
|
|
59
82
|
|
|
60
83
|
export interface DetectedAgent {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ParsedTask, RequiredPermission } from "../types.js";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import type { AgentTool, CommandLine } from "./agent.js";
|
|
4
|
+
import { getAgentInstructions } from "./shared-prompt.js";
|
|
5
|
+
import { SHELL } from "../platform/index.js";
|
|
6
|
+
|
|
7
|
+
export class Aider implements AgentTool {
|
|
8
|
+
supportsPermissions = false;
|
|
9
|
+
getPlanGenerationCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return {
|
|
11
|
+
command: "aider",
|
|
12
|
+
args: ["--message", prompt],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
|
+
const yolo = extraPermissions === "yolo";
|
|
18
|
+
const prompt = followupPrompt ?? (getAgentInstructions(task.frontmatter.id, yolo || !this.supportsPermissions) + "\n\n" + (task.body || task.frontmatter.user_prompt));
|
|
19
|
+
const args = [];
|
|
20
|
+
|
|
21
|
+
if (yolo) {
|
|
22
|
+
args.push("--yes-always");
|
|
23
|
+
}
|
|
24
|
+
args.push("--message", prompt);
|
|
25
|
+
|
|
26
|
+
return { command: "aider", args};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async init(): Promise<boolean> {
|
|
30
|
+
try {
|
|
31
|
+
execSync("aider --version", { stdio: "ignore", shell: SHELL });
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ParsedTask, RequiredPermission } from "../types.js";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import type { AgentTool, CommandLine } from "./agent.js";
|
|
4
|
+
import { getAgentInstructions } from "./shared-prompt.js";
|
|
5
|
+
import { SHELL } from "../platform/index.js";
|
|
6
|
+
|
|
7
|
+
export class Cursor implements AgentTool {
|
|
8
|
+
supportsPermissions = false;
|
|
9
|
+
getPlanGenerationCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return {
|
|
11
|
+
command: "cursor",
|
|
12
|
+
args: ["-p", prompt],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
|
+
const yolo = extraPermissions === "yolo";
|
|
18
|
+
const prompt = followupPrompt ?? (getAgentInstructions(task.frontmatter.id, yolo || !this.supportsPermissions) + "\n\n" + (task.body || task.frontmatter.user_prompt));
|
|
19
|
+
const args = [];
|
|
20
|
+
|
|
21
|
+
if (yolo) {
|
|
22
|
+
args.push("--force");
|
|
23
|
+
}
|
|
24
|
+
if (followupPrompt) {args.push("--continue");} // continue mode for followups
|
|
25
|
+
args.push("-p", prompt);
|
|
26
|
+
|
|
27
|
+
return { command: "cursor", args};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async init(): Promise<boolean> {
|
|
31
|
+
try {
|
|
32
|
+
execSync("cursor --version", { stdio: "ignore", shell: SHELL });
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ParsedTask, RequiredPermission } from "../types.js";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import type { AgentTool, CommandLine } from "./agent.js";
|
|
4
|
+
import { getAgentInstructions } from "./shared-prompt.js";
|
|
5
|
+
import { SHELL } from "../platform/index.js";
|
|
6
|
+
|
|
7
|
+
export class DeepAgents implements AgentTool {
|
|
8
|
+
supportsPermissions = false;
|
|
9
|
+
getPlanGenerationCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return {
|
|
11
|
+
command: "deepagents",
|
|
12
|
+
args: ["--non-interactive", prompt],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
|
+
const yolo = extraPermissions === "yolo";
|
|
18
|
+
const prompt = followupPrompt ?? (getAgentInstructions(task.frontmatter.id, yolo || !this.supportsPermissions) + "\n\n" + (task.body || task.frontmatter.user_prompt));
|
|
19
|
+
const args = [];
|
|
20
|
+
|
|
21
|
+
if (yolo) {
|
|
22
|
+
args.push("--auto-approve");
|
|
23
|
+
}
|
|
24
|
+
if (followupPrompt) {args.push("--resume");} // continue mode for followups
|
|
25
|
+
args.push("--non-interactive", prompt);
|
|
26
|
+
|
|
27
|
+
return { command: "deepagents", args};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async init(): Promise<boolean> {
|
|
31
|
+
try {
|
|
32
|
+
execSync("deepagents --version", { stdio: "ignore", shell: SHELL });
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ParsedTask, RequiredPermission } from "../types.js";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import type { AgentTool, CommandLine } from "./agent.js";
|
|
4
|
+
import { getAgentInstructions } from "./shared-prompt.js";
|
|
5
|
+
import { SHELL } from "../platform/index.js";
|
|
6
|
+
|
|
7
|
+
export class DroidAgent implements AgentTool {
|
|
8
|
+
supportsPermissions = false;
|
|
9
|
+
getPlanGenerationCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return {
|
|
11
|
+
command: "droid",
|
|
12
|
+
args: ["exec", prompt],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
|
+
const yolo = extraPermissions === "yolo";
|
|
18
|
+
const prompt = followupPrompt ?? (getAgentInstructions(task.frontmatter.id, yolo || !this.supportsPermissions) + "\n\n" + (task.body || task.frontmatter.user_prompt));
|
|
19
|
+
const args = ["exec", "--session-id", task.frontmatter.id];
|
|
20
|
+
|
|
21
|
+
if (yolo) {
|
|
22
|
+
args.push("--skip-permissions-unsafe");
|
|
23
|
+
}
|
|
24
|
+
args.push(prompt);
|
|
25
|
+
|
|
26
|
+
return { command: "droid", args};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async init(): Promise<boolean> {
|
|
30
|
+
try {
|
|
31
|
+
execSync("droid --version", { stdio: "ignore", shell: SHELL });
|
|
32
|
+
} catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ParsedTask, RequiredPermission } from "../types.js";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import type { AgentTool, CommandLine } from "./agent.js";
|
|
4
|
+
import { getAgentInstructions } from "./shared-prompt.js";
|
|
5
|
+
import { SHELL } from "../platform/index.js";
|
|
6
|
+
|
|
7
|
+
export class GooseAgent implements AgentTool {
|
|
8
|
+
supportsPermissions = false;
|
|
9
|
+
getPlanGenerationCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return {
|
|
11
|
+
command: "goose",
|
|
12
|
+
args: ["run", "--text", prompt],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
|
+
const yolo = extraPermissions === "yolo";
|
|
18
|
+
const prompt = followupPrompt ?? (getAgentInstructions(task.frontmatter.id, yolo || !this.supportsPermissions) + "\n\n" + (task.body || task.frontmatter.user_prompt));
|
|
19
|
+
const args = ["run"];
|
|
20
|
+
|
|
21
|
+
if (followupPrompt) {args.push("--resume");} // continue mode for followups
|
|
22
|
+
args.push("--text", prompt);
|
|
23
|
+
|
|
24
|
+
return { command: "goose", args, ...(yolo ? { env: { GOOSE_MODE: "auto" } } : {}) };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async init(): Promise<boolean> {
|
|
28
|
+
try {
|
|
29
|
+
execSync("goose --version", { stdio: "ignore", shell: SHELL });
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ParsedTask, RequiredPermission } from "../types.js";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import type { AgentTool, CommandLine } from "./agent.js";
|
|
4
|
+
import { getAgentInstructions } from "./shared-prompt.js";
|
|
5
|
+
import { SHELL } from "../platform/index.js";
|
|
6
|
+
|
|
7
|
+
export class OpenCodeAgent implements AgentTool {
|
|
8
|
+
supportsPermissions = false;
|
|
9
|
+
getPlanGenerationCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return {
|
|
11
|
+
command: "opencode",
|
|
12
|
+
args: ["run", prompt],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
|
+
const yolo = extraPermissions === "yolo";
|
|
18
|
+
const prompt = followupPrompt ?? (getAgentInstructions(task.frontmatter.id, yolo || !this.supportsPermissions) + "\n\n" + (task.body || task.frontmatter.user_prompt));
|
|
19
|
+
const args = ["run"];
|
|
20
|
+
|
|
21
|
+
if (yolo) {
|
|
22
|
+
args.push("--dangerously-skip-permissions");
|
|
23
|
+
}
|
|
24
|
+
if (followupPrompt) {args.push("--continue");} // continue mode for followups
|
|
25
|
+
args.push(prompt);
|
|
26
|
+
|
|
27
|
+
return { command: "opencode", args};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async init(): Promise<boolean> {
|
|
31
|
+
try {
|
|
32
|
+
execSync("opencode --version", { stdio: "ignore", shell: SHELL });
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ParsedTask, RequiredPermission } from "../types.js";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import type { AgentTool, CommandLine } from "./agent.js";
|
|
4
|
+
import { getAgentInstructions } from "./shared-prompt.js";
|
|
5
|
+
import { SHELL } from "../platform/index.js";
|
|
6
|
+
|
|
7
|
+
export class OpenHands implements AgentTool {
|
|
8
|
+
supportsPermissions = false;
|
|
9
|
+
getPlanGenerationCommandLine(prompt: string): CommandLine {
|
|
10
|
+
return {
|
|
11
|
+
command: "openhands",
|
|
12
|
+
args: ["--headless", "-t", prompt],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine {
|
|
17
|
+
const yolo = extraPermissions === "yolo";
|
|
18
|
+
const prompt = followupPrompt ?? (getAgentInstructions(task.frontmatter.id, yolo || !this.supportsPermissions) + "\n\n" + (task.body || task.frontmatter.user_prompt));
|
|
19
|
+
const args = ["--headless"];
|
|
20
|
+
|
|
21
|
+
if (yolo) {
|
|
22
|
+
args.push("--always-approve");
|
|
23
|
+
}
|
|
24
|
+
if (followupPrompt) {args.push("--resume", "--last");} // continue mode for followups
|
|
25
|
+
args.push("-t", prompt);
|
|
26
|
+
|
|
27
|
+
return { command: "openhands", args};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async init(): Promise<boolean> {
|
|
31
|
+
try {
|
|
32
|
+
execSync("openhands --version", { stdio: "ignore", shell: SHELL });
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/commands/run.ts
CHANGED
|
@@ -62,7 +62,7 @@ async function invokeAgentWithRetries(
|
|
|
62
62
|
}, 500);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
const { command, args, stdin } = ctx.agent.getTaskRunCommandLine(
|
|
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
68
|
const truncate = (s: string, max = 100) => s.length > max ? s.slice(0, max) + "…" : s;
|
|
@@ -70,7 +70,7 @@ async function invokeAgentWithRetries(
|
|
|
70
70
|
console.log(`[invoke] ${command} ${displayArgs.join(" ")}${stdin ? ` (stdin: ${truncate(stdin, 100)})` : ""}`);
|
|
71
71
|
const result = await spawnCommand(command, args, {
|
|
72
72
|
cwd: getRunDir(ctx.taskDir, ctx.runId),
|
|
73
|
-
env: { ...ctx.guiEnv, PALMIER_TASK_ID: ctx.task.frontmatter.id, PALMIER_RUN_DIR: getRunDir(ctx.taskDir, ctx.runId), PALMIER_HTTP_PORT: String(ctx.config.httpPort ?? 9966) },
|
|
73
|
+
env: { ...ctx.guiEnv, ...agentEnv, PALMIER_TASK_ID: ctx.task.frontmatter.id, PALMIER_RUN_DIR: getRunDir(ctx.taskDir, ctx.runId), PALMIER_HTTP_PORT: String(ctx.config.httpPort ?? 9966) },
|
|
74
74
|
echoStdout: true,
|
|
75
75
|
resolveOnFailure: true,
|
|
76
76
|
stdin,
|
package/src/rpc-handler.ts
CHANGED
|
@@ -124,13 +124,14 @@ async function generatePlan(
|
|
|
124
124
|
): Promise<{ name: string; body: string }> {
|
|
125
125
|
const fullPrompt = PLAN_GENERATION_PROMPT + userPrompt;
|
|
126
126
|
const planAgent = getAgent(agentName);
|
|
127
|
-
const { command, args, stdin } = planAgent.getPlanGenerationCommandLine(fullPrompt);
|
|
127
|
+
const { command, args, stdin, env: agentEnv } = planAgent.getPlanGenerationCommandLine(fullPrompt);
|
|
128
128
|
console.log(`[generatePlan] Running: ${command} ${args.join(" ")}`);
|
|
129
129
|
|
|
130
130
|
const { output } = await spawnCommand(command, args, {
|
|
131
131
|
cwd: projectRoot,
|
|
132
132
|
timeout: 120_000,
|
|
133
133
|
stdin,
|
|
134
|
+
...(agentEnv ? { env: agentEnv } : {}),
|
|
134
135
|
});
|
|
135
136
|
|
|
136
137
|
let name = "";
|
|
@@ -423,7 +424,7 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
|
|
|
423
424
|
|
|
424
425
|
// Fire-and-forget: invoke agent inline as a child of the serve process
|
|
425
426
|
const followupAgent = getAgent(followupTask.frontmatter.agent);
|
|
426
|
-
const { command: cmd, args: cmdArgs, stdin } = followupAgent.getTaskRunCommandLine(
|
|
427
|
+
const { command: cmd, args: cmdArgs, stdin, env: followupAgentEnv } = followupAgent.getTaskRunCommandLine(
|
|
427
428
|
followupTask, params.message, followupTask.frontmatter.yolo_mode ? "yolo" : followupTask.frontmatter.permissions,
|
|
428
429
|
);
|
|
429
430
|
|
|
@@ -431,7 +432,7 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
|
|
|
431
432
|
const child = crossSpawn(cmd, cmdArgs, {
|
|
432
433
|
cwd: followupRunDir,
|
|
433
434
|
stdio: [stdin != null ? "pipe" : "ignore", "pipe", "pipe"],
|
|
434
|
-
env: { ...process.env, PALMIER_TASK_ID: params.id },
|
|
435
|
+
env: { ...process.env, ...followupAgentEnv, PALMIER_TASK_ID: params.id },
|
|
435
436
|
windowsHide: true,
|
|
436
437
|
});
|
|
437
438
|
if (stdin != null) child.stdin!.end(stdin);
|
|
@@ -225,11 +225,12 @@ export async function startHttpTransport(
|
|
|
225
225
|
|
|
226
226
|
try {
|
|
227
227
|
const body = await readBody(req);
|
|
228
|
-
const { title, body: notifBody } = JSON.parse(body) as { title: string; body: string };
|
|
228
|
+
const { taskId: notifTaskId, title, body: notifBody } = JSON.parse(body) as { taskId?: string; title: string; body: string };
|
|
229
229
|
if (!title || !notifBody) { sendJson(res, 400, { error: "title and body are required" }); return; }
|
|
230
230
|
|
|
231
231
|
const sc = StringCodec();
|
|
232
|
-
const payload = { hostId: config.hostId, title, body: notifBody };
|
|
232
|
+
const payload: Record<string, string> = { hostId: config.hostId, title, body: notifBody };
|
|
233
|
+
if (notifTaskId) payload.task_id = notifTaskId;
|
|
233
234
|
const subject = `host.${config.hostId}.push.send`;
|
|
234
235
|
const reply = await nc.request(subject, sc.encode(JSON.stringify(payload)), { timeout: 15_000 });
|
|
235
236
|
const result = JSON.parse(sc.decode(reply.data)) as { ok?: boolean; error?: string };
|