palmier 0.7.9 → 0.8.1

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 (41) hide show
  1. package/dist/commands/run.js +55 -0
  2. package/dist/commands/serve.js +22 -2
  3. package/dist/device-capabilities.d.ts +1 -1
  4. package/dist/event-queues.d.ts +36 -0
  5. package/dist/event-queues.js +53 -0
  6. package/dist/mcp-tools.js +2 -2
  7. package/dist/platform/windows.js +5 -2
  8. package/dist/pwa/assets/index-CQxcuDhM.css +1 -0
  9. package/dist/pwa/assets/index-DQfOEB03.js +120 -0
  10. package/dist/pwa/assets/{web-CF-N8Di6.js → web-D7Kq3Nvk.js} +1 -1
  11. package/dist/pwa/assets/{web-BpM3fNCn.js → web-DOyOiwsW.js} +1 -1
  12. package/dist/pwa/index.html +2 -2
  13. package/dist/pwa/service-worker.js +1 -1
  14. package/dist/rpc-handler.js +6 -5
  15. package/dist/transports/http-transport.js +15 -0
  16. package/dist/types.d.ts +6 -5
  17. package/package.json +1 -1
  18. package/palmier-server/README.md +1 -1
  19. package/palmier-server/pwa/src/App.css +5 -0
  20. package/palmier-server/pwa/src/App.tsx +15 -1
  21. package/palmier-server/pwa/src/components/HostMenu.tsx +155 -456
  22. package/palmier-server/pwa/src/components/SessionsView.tsx +9 -3
  23. package/palmier-server/pwa/src/components/TaskCard.tsx +12 -4
  24. package/palmier-server/pwa/src/components/TaskForm.tsx +79 -32
  25. package/palmier-server/pwa/src/components/TasksView.tsx +5 -0
  26. package/palmier-server/pwa/src/constants.ts +1 -1
  27. package/palmier-server/pwa/src/native/Device.ts +48 -0
  28. package/palmier-server/pwa/src/pages/PairHost.tsx +18 -2
  29. package/palmier-server/pwa/src/types.ts +1 -1
  30. package/palmier-server/spec.md +12 -2
  31. package/src/commands/run.ts +61 -0
  32. package/src/commands/serve.ts +22 -2
  33. package/src/device-capabilities.ts +1 -1
  34. package/src/event-queues.ts +56 -0
  35. package/src/mcp-tools.ts +2 -2
  36. package/src/platform/windows.ts +5 -2
  37. package/src/rpc-handler.ts +8 -7
  38. package/src/transports/http-transport.ts +14 -0
  39. package/src/types.ts +6 -5
  40. package/dist/pwa/assets/index-FP1Mipr6.js +0 -120
  41. package/dist/pwa/assets/index-bLTn8zBj.css +0 -1
package/src/mcp-tools.ts CHANGED
@@ -687,8 +687,8 @@ const sendEmailTool: ToolDefinition = {
687
687
  async handler(args, ctx) {
688
688
  if (!ctx.nc) throw new ToolError("Not connected to server (NATS unavailable)", 503);
689
689
 
690
- const device = getCapabilityDevice("email");
691
- if (!device) throw new ToolError("No device has email access enabled", 400);
690
+ const device = getCapabilityDevice("send-email");
691
+ if (!device) throw new ToolError("No device has send-email access enabled", 400);
692
692
 
693
693
  const { to, subject, body, cc, bcc } = args as { to: string; subject?: string; body?: string; cc?: string; bcc?: string };
694
694
  if (!to) throw new ToolError("to is required", 400);
@@ -192,11 +192,14 @@ export class WindowsPlatform implements PlatformService {
192
192
  const script = process.argv[1] || "palmier";
193
193
  const tr = `"${process.execPath}" "${script}" run ${taskId}`;
194
194
 
195
- // Build trigger XML elements
195
+ // Build trigger XML elements. Event-based schedule types (on_new_notification,
196
+ // on_new_sms) carry no values and are driven by the run process, not the OS
197
+ // scheduler — they intentionally produce only the dummy trigger below.
196
198
  const triggerElements: string[] = [];
197
199
  const scheduleType = task.frontmatter.schedule_type;
198
200
  const scheduleValues = task.frontmatter.schedule_values;
199
- if (task.frontmatter.schedule_enabled && scheduleType && scheduleValues?.length) {
201
+ const isTimerSchedule = scheduleType === "crons" || scheduleType === "specific_times";
202
+ if (task.frontmatter.schedule_enabled && isTimerSchedule && scheduleValues?.length) {
200
203
  for (const value of scheduleValues) {
201
204
  try {
202
205
  triggerElements.push(scheduleValueToXml(scheduleType, value));
@@ -14,6 +14,7 @@ import { publishHostEvent } from "./events.js";
14
14
  import { getCapabilityDevice, setCapabilityDevice, clearCapabilityDevice, type DeviceCapability } from "./device-capabilities.js";
15
15
  import { currentVersion, performUpdate } from "./update-checker.js";
16
16
  import { parseReportFiles, parseTaskOutcome, stripPalmierMarkers } from "./commands/run.js";
17
+ import { clearTaskQueue } from "./event-queues.js";
17
18
  import type { HostConfig, ParsedTask, RpcMessage, ConversationMessage } from "./types.js";
18
19
 
19
20
  /**
@@ -162,8 +163,8 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
162
163
  // is active. Includes any prompts already waiting so a reconnecting
163
164
  // PWA can render their modals without replaying events.
164
165
  const capabilities: Record<string, string | null> = {};
165
- for (const cap of ["location", "notifications", "sms", "contacts", "calendar", "alert", "battery", "dnd"] as const) {
166
- capabilities[cap] = getCapabilityDevice(cap)?.clientToken ?? null;
166
+ for (const capability of ["location", "notifications", "sms", "contacts", "calendar", "alert", "battery", "dnd", "send-email"] as const) {
167
+ capabilities[capability] = getCapabilityDevice(capability)?.clientToken ?? null;
167
168
  }
168
169
  return {
169
170
  agents: config.agents ?? [],
@@ -194,7 +195,7 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
194
195
  const params = request.params as {
195
196
  user_prompt: string;
196
197
  agent: string;
197
- schedule_type?: "crons" | "specific_times";
198
+ schedule_type?: "crons" | "specific_times" | "on_new_notification" | "on_new_sms";
198
199
  schedule_values?: string[];
199
200
  schedule_enabled?: boolean;
200
201
  requires_confirmation?: boolean;
@@ -217,9 +218,8 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
217
218
  agent: params.agent,
218
219
  schedule_enabled: params.schedule_enabled ?? true,
219
220
  requires_confirmation: params.requires_confirmation ?? true,
220
- ...(params.schedule_type && params.schedule_values?.length
221
- ? { schedule_type: params.schedule_type, schedule_values: params.schedule_values }
222
- : {}),
221
+ ...(params.schedule_type ? { schedule_type: params.schedule_type } : {}),
222
+ ...(params.schedule_values?.length ? { schedule_values: params.schedule_values } : {}),
223
223
  ...(params.yolo_mode ? { yolo_mode: true } : {}),
224
224
  ...(params.foreground_mode ? { foreground_mode: true } : {}),
225
225
  ...(params.command ? { command: params.command } : {}),
@@ -238,7 +238,7 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
238
238
  id: string;
239
239
  user_prompt?: string;
240
240
  agent?: string;
241
- schedule_type?: "crons" | "specific_times" | null;
241
+ schedule_type?: "crons" | "specific_times" | "on_new_notification" | "on_new_sms" | null;
242
242
  schedule_values?: string[] | null;
243
243
  schedule_enabled?: boolean;
244
244
  requires_confirmation?: boolean;
@@ -307,6 +307,7 @@ export function createRpcHandler(config: HostConfig, nc?: NatsConnection) {
307
307
  const params = request.params as { id: string };
308
308
 
309
309
  getPlatform().removeTaskTimer(params.id);
310
+ clearTaskQueue(params.id);
310
311
  removeFromTaskList(config.projectRoot, params.id);
311
312
 
312
313
  return { ok: true, task_id: params.id };
@@ -9,6 +9,7 @@ import type { HostConfig, RpcMessage, RequiredPermission } from "../types.js";
9
9
  import { agentToolMap, agentResources, ToolError, type ToolContext } from "../mcp-tools.js";
10
10
  import { handleMcpRequest, getAgentName, getResourceSubscriptions } from "../mcp-handler.js";
11
11
  import { getTaskDir } from "../task.js";
12
+ import { popEvent } from "../event-queues.js";
12
13
 
13
14
  // ── Bundled PWA asset serving ───────────────────────────────────────────
14
15
 
@@ -279,6 +280,19 @@ export async function startHttpTransport(
279
280
  return;
280
281
  }
281
282
 
283
+ // ── Event queue pop (used by event-triggered palmier run) ─────────
284
+
285
+ if (req.method === "POST" && pathname === "/task-event/pop") {
286
+ if (!isLocalhost(req)) { sendJson(res, 403, { error: "localhost only" }); return; }
287
+ const taskId = url.searchParams.get("taskId");
288
+ if (!taskId) {
289
+ sendJson(res, 400, { error: "taskId query parameter is required" });
290
+ return;
291
+ }
292
+ sendJson(res, 200, popEvent(taskId));
293
+ return;
294
+ }
295
+
282
296
  // ── Localhost-only endpoints (no auth) ─────────────────────────────
283
297
 
284
298
  if (req.method === "POST" && pathname === "/event") {
package/src/types.ts CHANGED
@@ -22,12 +22,13 @@ export interface TaskFrontmatter {
22
22
  user_prompt: string;
23
23
  agent: string;
24
24
  /**
25
- * Task schedule. `schedule_values` is homogeneous per `schedule_type`:
26
- * - `crons`: array of cron expressions (e.g. "0 9 * * *")
27
- * - `specific_times`: array of local datetime strings (e.g. "2026-04-20T09:00")
28
- * Both fields are present together or absent together.
25
+ * Task schedule.
26
+ * - `crons`: `schedule_values` holds cron expressions (e.g. "0 9 * * *")
27
+ * - `specific_times`: `schedule_values` holds local datetime strings (e.g. "2026-04-20T09:00")
28
+ * - `on_new_notification`: fires on each new Android notification from NATS; no `schedule_values`
29
+ * - `on_new_sms`: fires on each new SMS from NATS; no `schedule_values`
29
30
  */
30
- schedule_type?: "crons" | "specific_times";
31
+ schedule_type?: "crons" | "specific_times" | "on_new_notification" | "on_new_sms";
31
32
  schedule_values?: string[];
32
33
  schedule_enabled: boolean;
33
34
  requires_confirmation: boolean;