palmier 0.5.1 → 0.5.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.
Files changed (42) hide show
  1. package/dist/agents/agent-instructions.md +7 -11
  2. package/dist/agents/agent.d.ts +8 -3
  3. package/dist/agents/agent.js +7 -1
  4. package/dist/agents/claude.d.ts +2 -1
  5. package/dist/agents/claude.js +10 -5
  6. package/dist/agents/codex.d.ts +2 -1
  7. package/dist/agents/codex.js +10 -6
  8. package/dist/agents/copilot.d.ts +2 -1
  9. package/dist/agents/copilot.js +10 -3
  10. package/dist/agents/gemini.d.ts +2 -1
  11. package/dist/agents/gemini.js +11 -7
  12. package/dist/agents/kimi.d.ts +9 -0
  13. package/dist/agents/kimi.js +35 -0
  14. package/dist/agents/openclaw.d.ts +2 -1
  15. package/dist/agents/openclaw.js +3 -1
  16. package/dist/agents/qwen.d.ts +9 -0
  17. package/dist/agents/qwen.js +32 -0
  18. package/dist/agents/shared-prompt.d.ts +1 -1
  19. package/dist/agents/shared-prompt.js +6 -2
  20. package/dist/commands/run.js +12 -3
  21. package/dist/rpc-handler.js +7 -3
  22. package/dist/task.d.ts +13 -3
  23. package/dist/task.js +39 -7
  24. package/dist/transports/http-transport.js +23 -6
  25. package/dist/types.d.ts +1 -0
  26. package/package.json +1 -1
  27. package/src/agents/agent-instructions.md +7 -11
  28. package/src/agents/agent.ts +16 -4
  29. package/src/agents/claude.ts +11 -6
  30. package/src/agents/codex.ts +11 -7
  31. package/src/agents/copilot.ts +10 -4
  32. package/src/agents/gemini.ts +12 -8
  33. package/src/agents/kimi.ts +37 -0
  34. package/src/agents/openclaw.ts +4 -2
  35. package/src/agents/qwen.ts +34 -0
  36. package/src/agents/shared-prompt.ts +6 -2
  37. package/src/commands/run.ts +14 -3
  38. package/src/rpc-handler.ts +9 -3
  39. package/src/task.ts +43 -8
  40. package/src/transports/http-transport.ts +25 -6
  41. package/src/types.ts +1 -0
  42. package/test/agent-instructions.test.ts +31 -0
@@ -3,7 +3,8 @@ import * as os from "os";
3
3
  import { StringCodec, type NatsConnection } from "nats";
4
4
  import { validateSession, addSession } from "../session-store.js";
5
5
  import { registerPending } from "../pending-requests.js";
6
- import { getTaskDir, parseTaskFile, appendRunMessage } from "../task.js";
6
+ import * as fs from "node:fs";
7
+ import { getTaskDir, parseTaskFile, spliceUserMessage } from "../task.js";
7
8
  import type { HostConfig, RpcMessage, RequiredPermission } from "../types.js";
8
9
 
9
10
  const PWA_ORIGIN = "https://app.palmier.me";
@@ -99,6 +100,18 @@ export function detectLanIp(): string {
99
100
  return "127.0.0.1";
100
101
  }
101
102
 
103
+ /** Find the latest (highest-numbered) run directory for a task. */
104
+ function findLatestRunId(taskDir: string): string | null {
105
+ try {
106
+ const dirs = fs.readdirSync(taskDir)
107
+ .filter((f) => /^\d+$/.test(f) && fs.statSync(`${taskDir}/${f}`).isDirectory())
108
+ .sort();
109
+ return dirs.length > 0 ? dirs[dirs.length - 1] : null;
110
+ } catch {
111
+ return null;
112
+ }
113
+ }
114
+
102
115
  /**
103
116
  * Start the HTTP transport: server with RPC, SSE, PWA proxy, pairing, and
104
117
  * localhost-only agent endpoints (notify, request-input, confirmation, permission).
@@ -262,6 +275,9 @@ export async function startHttpTransport(
262
275
  const taskDir = getTaskDir(config.projectRoot, taskId);
263
276
  const task = parseTaskFile(taskDir);
264
277
 
278
+ // Resolve runId: use provided value, otherwise find the latest run directory
279
+ const effectiveRunId = runId ?? findLatestRunId(taskDir);
280
+
265
281
  const pendingPromise = registerPending(taskId, "input", descriptions);
266
282
 
267
283
  await publishEvent(taskId, {
@@ -273,17 +289,20 @@ export async function startHttpTransport(
273
289
 
274
290
  const response = await pendingPromise;
275
291
 
292
+ const questionsBlock = "\n\n" + descriptions.map((d) => `**${d}**`).join("\n");
293
+
276
294
  if (response.length === 1 && response[0] === "aborted") {
277
295
  await publishEvent(taskId, { event_type: "input-resolved", host_id: config.hostId, status: "aborted" });
278
- if (runId) {
279
- appendRunMessage(taskDir, runId, { role: "user", time: Date.now(), content: "Input request aborted.", type: "input" });
296
+ if (effectiveRunId) {
297
+ spliceUserMessage(taskDir, effectiveRunId, { role: "user", time: Date.now(), content: "Aborted", type: "input" }, questionsBlock);
298
+ await publishEvent(taskId, { event_type: "result-updated", run_id: effectiveRunId });
280
299
  }
281
300
  sendJson(res, 200, { aborted: true });
282
301
  } else {
283
302
  await publishEvent(taskId, { event_type: "input-resolved", host_id: config.hostId, status: "provided" });
284
- if (runId) {
285
- const lines = descriptions.map((desc, i) => `**${desc}** ${response[i]}`);
286
- appendRunMessage(taskDir, runId, { role: "user", time: Date.now(), content: lines.join("\n"), type: "input" });
303
+ if (effectiveRunId) {
304
+ spliceUserMessage(taskDir, effectiveRunId, { role: "user", time: Date.now(), content: response.join("\n"), type: "input" }, questionsBlock);
305
+ await publishEvent(taskId, { event_type: "result-updated", run_id: effectiveRunId });
287
306
  }
288
307
  sendJson(res, 200, { values: response });
289
308
  }
package/src/types.ts CHANGED
@@ -23,6 +23,7 @@ export interface TaskFrontmatter {
23
23
  triggers: Trigger[];
24
24
  triggers_enabled: boolean;
25
25
  requires_confirmation: boolean;
26
+ yolo_mode?: boolean;
26
27
  permissions?: RequiredPermission[];
27
28
  command?: string;
28
29
  }
@@ -0,0 +1,31 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { getAgentInstructions } from "../src/agents/shared-prompt.js";
4
+
5
+ describe("getAgentInstructions", () => {
6
+ it("includes Permissions section by default", () => {
7
+ const result = getAgentInstructions("test-task-id");
8
+ assert.match(result, /## Permissions/);
9
+ assert.match(result, /PALMIER_PERMISSION/);
10
+ });
11
+
12
+ it("strips Permissions section when skipPermissions is true", () => {
13
+ const result = getAgentInstructions("test-task-id", true);
14
+ assert.doesNotMatch(result, /## Permissions/);
15
+ assert.doesNotMatch(result, /PALMIER_PERMISSION/);
16
+ });
17
+
18
+ it("preserves other sections when Permissions is stripped", () => {
19
+ const result = getAgentInstructions("test-task-id", true);
20
+ assert.match(result, /## Reporting Output/);
21
+ assert.match(result, /## Completion/);
22
+ assert.match(result, /## HTTP Endpoints/);
23
+ });
24
+
25
+ it("replaces template variables", () => {
26
+ const result = getAgentInstructions("my-task-123");
27
+ assert.match(result, /my-task-123/);
28
+ assert.doesNotMatch(result, /\{\{TASK_ID\}\}/);
29
+ assert.doesNotMatch(result, /\{\{PORT\}\}/);
30
+ });
31
+ });