palmier 0.9.6 → 0.9.7

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 (250) hide show
  1. package/README.md +28 -13
  2. package/dist/agents/agent.d.ts +0 -1
  3. package/dist/agents/agent.js +0 -1
  4. package/dist/agents/aider.d.ts +0 -1
  5. package/dist/agents/aider.js +0 -1
  6. package/dist/agents/claude.d.ts +0 -1
  7. package/dist/agents/claude.js +0 -1
  8. package/dist/agents/cline.d.ts +0 -1
  9. package/dist/agents/cline.js +0 -1
  10. package/dist/agents/codex.d.ts +0 -1
  11. package/dist/agents/codex.js +0 -1
  12. package/dist/agents/copilot.d.ts +0 -1
  13. package/dist/agents/copilot.js +0 -1
  14. package/dist/agents/cursor.d.ts +0 -1
  15. package/dist/agents/cursor.js +0 -1
  16. package/dist/agents/deepagents.d.ts +0 -1
  17. package/dist/agents/deepagents.js +0 -1
  18. package/dist/agents/droid.d.ts +0 -1
  19. package/dist/agents/droid.js +0 -1
  20. package/dist/agents/gemini.d.ts +0 -1
  21. package/dist/agents/gemini.js +0 -1
  22. package/dist/agents/goose.d.ts +0 -1
  23. package/dist/agents/goose.js +0 -1
  24. package/dist/agents/hermes.d.ts +0 -1
  25. package/dist/agents/hermes.js +0 -1
  26. package/dist/agents/kimi.d.ts +0 -1
  27. package/dist/agents/kimi.js +0 -1
  28. package/dist/agents/kiro.d.ts +0 -1
  29. package/dist/agents/kiro.js +0 -1
  30. package/dist/agents/openclaw.d.ts +0 -1
  31. package/dist/agents/openclaw.js +0 -1
  32. package/dist/agents/opencode.d.ts +0 -1
  33. package/dist/agents/opencode.js +0 -1
  34. package/dist/agents/qoder.d.ts +0 -1
  35. package/dist/agents/qoder.js +0 -1
  36. package/dist/agents/qwen.d.ts +0 -1
  37. package/dist/agents/qwen.js +0 -1
  38. package/dist/agents/shared-prompt.d.ts +0 -1
  39. package/dist/agents/shared-prompt.js +0 -1
  40. package/dist/client-store.d.ts +0 -1
  41. package/dist/client-store.js +0 -1
  42. package/dist/commands/clients.d.ts +0 -1
  43. package/dist/commands/clients.js +0 -1
  44. package/dist/commands/info.d.ts +0 -1
  45. package/dist/commands/info.js +0 -1
  46. package/dist/commands/init.d.ts +0 -1
  47. package/dist/commands/init.js +1 -2
  48. package/dist/commands/pair.d.ts +0 -1
  49. package/dist/commands/pair.js +0 -1
  50. package/dist/commands/restart.d.ts +0 -1
  51. package/dist/commands/restart.js +0 -1
  52. package/dist/commands/run.d.ts +0 -1
  53. package/dist/commands/run.js +0 -1
  54. package/dist/commands/serve.d.ts +0 -1
  55. package/dist/commands/serve.js +0 -1
  56. package/dist/commands/uninstall.d.ts +0 -1
  57. package/dist/commands/uninstall.js +0 -1
  58. package/dist/config.d.ts +0 -1
  59. package/dist/config.js +0 -1
  60. package/dist/event-queues.d.ts +0 -1
  61. package/dist/event-queues.js +0 -1
  62. package/dist/events.d.ts +0 -1
  63. package/dist/events.js +0 -1
  64. package/dist/index.d.ts +0 -1
  65. package/dist/index.js +0 -1
  66. package/dist/linked-device.d.ts +0 -1
  67. package/dist/linked-device.js +0 -1
  68. package/dist/mcp-handler.d.ts +0 -1
  69. package/dist/mcp-handler.js +0 -1
  70. package/dist/mcp-tools.d.ts +0 -1
  71. package/dist/mcp-tools.js +0 -1
  72. package/dist/nats-client.d.ts +0 -1
  73. package/dist/nats-client.js +0 -1
  74. package/dist/network.d.ts +0 -1
  75. package/dist/network.js +0 -1
  76. package/dist/notification-store.d.ts +0 -1
  77. package/dist/notification-store.js +0 -1
  78. package/dist/pending-requests.d.ts +0 -1
  79. package/dist/pending-requests.js +0 -1
  80. package/dist/platform/index.d.ts +0 -1
  81. package/dist/platform/index.js +0 -1
  82. package/dist/platform/linux.d.ts +0 -1
  83. package/dist/platform/linux.js +0 -1
  84. package/dist/platform/macos.d.ts +0 -1
  85. package/dist/platform/macos.js +0 -1
  86. package/dist/platform/platform.d.ts +0 -1
  87. package/dist/platform/platform.js +0 -1
  88. package/dist/platform/windows.d.ts +0 -1
  89. package/dist/platform/windows.js +0 -1
  90. package/dist/pwa/assets/{index-MLEFUP3r.js → index-DWvRAUiy.js} +31 -31
  91. package/dist/pwa/assets/{web-B1sKCc7e.js → web-C4iZbqTC.js} +1 -1
  92. package/dist/pwa/assets/{web-ETD-8ZHd.js → web-CBFqJGX6.js} +1 -1
  93. package/dist/pwa/assets/{web-B4xEa6WO.js → web-DL4uXOpS.js} +1 -1
  94. package/dist/pwa/index.html +2 -2
  95. package/dist/pwa/service-worker.js +1 -1
  96. package/dist/rpc-handler.d.ts +0 -1
  97. package/dist/rpc-handler.js +0 -1
  98. package/dist/sms-store.d.ts +0 -1
  99. package/dist/sms-store.js +0 -1
  100. package/dist/spawn-command.d.ts +0 -1
  101. package/dist/spawn-command.js +0 -1
  102. package/dist/task.d.ts +0 -1
  103. package/dist/task.js +0 -1
  104. package/dist/transports/http-transport.d.ts +0 -1
  105. package/dist/transports/http-transport.js +0 -1
  106. package/dist/transports/nats-transport.d.ts +0 -1
  107. package/dist/transports/nats-transport.js +0 -1
  108. package/dist/types.d.ts +0 -1
  109. package/dist/types.js +0 -1
  110. package/dist/update-checker.d.ts +0 -1
  111. package/dist/update-checker.js +0 -1
  112. package/package.json +5 -1
  113. package/.github/workflows/ci.yml +0 -16
  114. package/.github/workflows/publish.yml +0 -37
  115. package/CLAUDE.md +0 -22
  116. package/palmier-server/.github/workflows/ci.yml +0 -21
  117. package/palmier-server/.github/workflows/deploy.yml +0 -38
  118. package/palmier-server/CLAUDE.md +0 -17
  119. package/palmier-server/PRODUCTION.md +0 -358
  120. package/palmier-server/README.md +0 -231
  121. package/palmier-server/nats.conf +0 -19
  122. package/palmier-server/package.json +0 -15
  123. package/palmier-server/pnpm-lock.yaml +0 -7639
  124. package/palmier-server/pnpm-workspace.yaml +0 -3
  125. package/palmier-server/pwa/index.html +0 -16
  126. package/palmier-server/pwa/logo/logo_20260421.png +0 -0
  127. package/palmier-server/pwa/package.json +0 -34
  128. package/palmier-server/pwa/public/apple-touch-icon.png +0 -0
  129. package/palmier-server/pwa/public/favicon.ico +0 -0
  130. package/palmier-server/pwa/public/pwa-192x192.png +0 -0
  131. package/palmier-server/pwa/public/pwa-512x512.png +0 -0
  132. package/palmier-server/pwa/src/App.css +0 -3012
  133. package/palmier-server/pwa/src/App.tsx +0 -59
  134. package/palmier-server/pwa/src/agentLabels.ts +0 -11
  135. package/palmier-server/pwa/src/api.ts +0 -67
  136. package/palmier-server/pwa/src/components/CapabilityToggles.tsx +0 -170
  137. package/palmier-server/pwa/src/components/ConnectionStatusIcon.tsx +0 -113
  138. package/palmier-server/pwa/src/components/HostMenu.tsx +0 -429
  139. package/palmier-server/pwa/src/components/PermissionsDialog.tsx +0 -34
  140. package/palmier-server/pwa/src/components/PullToRefreshIndicator.tsx +0 -46
  141. package/palmier-server/pwa/src/components/RunDetailView.tsx +0 -343
  142. package/palmier-server/pwa/src/components/SessionComposer.tsx +0 -157
  143. package/palmier-server/pwa/src/components/SessionsView.tsx +0 -326
  144. package/palmier-server/pwa/src/components/SwipeToDeleteRow.tsx +0 -170
  145. package/palmier-server/pwa/src/components/TabBar.tsx +0 -40
  146. package/palmier-server/pwa/src/components/TaskCard.tsx +0 -255
  147. package/palmier-server/pwa/src/components/TaskForm.tsx +0 -766
  148. package/palmier-server/pwa/src/components/TasksView.tsx +0 -179
  149. package/palmier-server/pwa/src/constants.ts +0 -2
  150. package/palmier-server/pwa/src/contexts/HostConnectionContext.tsx +0 -432
  151. package/palmier-server/pwa/src/contexts/HostStoreContext.tsx +0 -124
  152. package/palmier-server/pwa/src/draftGuard.ts +0 -24
  153. package/palmier-server/pwa/src/formatTime.ts +0 -44
  154. package/palmier-server/pwa/src/hooks/useBackClose.ts +0 -75
  155. package/palmier-server/pwa/src/hooks/useMediaQuery.ts +0 -17
  156. package/palmier-server/pwa/src/hooks/usePullToRefresh.ts +0 -102
  157. package/palmier-server/pwa/src/hooks/usePushSubscription.ts +0 -77
  158. package/palmier-server/pwa/src/main.tsx +0 -14
  159. package/palmier-server/pwa/src/native/Device.ts +0 -49
  160. package/palmier-server/pwa/src/pages/Dashboard.tsx +0 -542
  161. package/palmier-server/pwa/src/pages/PairHost.tsx +0 -232
  162. package/palmier-server/pwa/src/pages/PairSetup.tsx +0 -134
  163. package/palmier-server/pwa/src/service-worker.ts +0 -142
  164. package/palmier-server/pwa/src/types.ts +0 -75
  165. package/palmier-server/pwa/src/vite-env.d.ts +0 -11
  166. package/palmier-server/pwa/tsconfig.json +0 -21
  167. package/palmier-server/pwa/tsconfig.node.json +0 -19
  168. package/palmier-server/pwa/vite.config.ts +0 -47
  169. package/palmier-server/server/.env.example +0 -20
  170. package/palmier-server/server/package.json +0 -36
  171. package/palmier-server/server/src/db.ts +0 -44
  172. package/palmier-server/server/src/fcm.ts +0 -74
  173. package/palmier-server/server/src/index.ts +0 -688
  174. package/palmier-server/server/src/nats-jwt.ts +0 -299
  175. package/palmier-server/server/src/nats-setup.ts +0 -48
  176. package/palmier-server/server/src/nats.ts +0 -33
  177. package/palmier-server/server/src/notify.ts +0 -34
  178. package/palmier-server/server/src/push.ts +0 -68
  179. package/palmier-server/server/src/routes/device.ts +0 -224
  180. package/palmier-server/server/src/routes/fcm.ts +0 -64
  181. package/palmier-server/server/src/routes/hosts.ts +0 -56
  182. package/palmier-server/server/src/routes/push.ts +0 -101
  183. package/palmier-server/server/tsconfig.json +0 -20
  184. package/palmier-server/spec.md +0 -533
  185. package/src/agents/agent-instructions.md +0 -28
  186. package/src/agents/agent.ts +0 -114
  187. package/src/agents/aider.ts +0 -35
  188. package/src/agents/claude.ts +0 -39
  189. package/src/agents/cline.ts +0 -35
  190. package/src/agents/codex.ts +0 -40
  191. package/src/agents/copilot.ts +0 -37
  192. package/src/agents/cursor.ts +0 -36
  193. package/src/agents/deepagents.ts +0 -36
  194. package/src/agents/droid.ts +0 -35
  195. package/src/agents/gemini.ts +0 -43
  196. package/src/agents/goose.ts +0 -33
  197. package/src/agents/hermes.ts +0 -36
  198. package/src/agents/kimi.ts +0 -35
  199. package/src/agents/kiro.ts +0 -36
  200. package/src/agents/openclaw.ts +0 -29
  201. package/src/agents/opencode.ts +0 -36
  202. package/src/agents/qoder.ts +0 -36
  203. package/src/agents/qwen.ts +0 -32
  204. package/src/agents/shared-prompt.ts +0 -30
  205. package/src/client-store.ts +0 -68
  206. package/src/commands/clients.ts +0 -29
  207. package/src/commands/info.ts +0 -29
  208. package/src/commands/init.ts +0 -165
  209. package/src/commands/pair.ts +0 -137
  210. package/src/commands/restart.ts +0 -6
  211. package/src/commands/run.ts +0 -608
  212. package/src/commands/serve.ts +0 -211
  213. package/src/commands/uninstall.ts +0 -9
  214. package/src/config.ts +0 -36
  215. package/src/cross-spawn.d.ts +0 -5
  216. package/src/event-queues.ts +0 -41
  217. package/src/events.ts +0 -29
  218. package/src/index.ts +0 -111
  219. package/src/linked-device.ts +0 -52
  220. package/src/mcp-handler.ts +0 -200
  221. package/src/mcp-tools.ts +0 -839
  222. package/src/nats-client.ts +0 -19
  223. package/src/network.ts +0 -96
  224. package/src/notification-store.ts +0 -30
  225. package/src/pending-requests.ts +0 -73
  226. package/src/platform/index.ts +0 -20
  227. package/src/platform/linux.ts +0 -296
  228. package/src/platform/macos.ts +0 -329
  229. package/src/platform/platform.ts +0 -31
  230. package/src/platform/windows.ts +0 -299
  231. package/src/rpc-handler.ts +0 -691
  232. package/src/sms-store.ts +0 -28
  233. package/src/spawn-command.ts +0 -123
  234. package/src/task.ts +0 -343
  235. package/src/transports/http-transport.ts +0 -478
  236. package/src/transports/nats-transport.ts +0 -76
  237. package/src/types.ts +0 -89
  238. package/src/update-checker.ts +0 -40
  239. package/test/agent-instructions.test.ts +0 -209
  240. package/test/agent-output-parsing.test.ts +0 -74
  241. package/test/linux-cron.test.ts +0 -41
  242. package/test/macos-plist.test.ts +0 -112
  243. package/test/notification-store.test.ts +0 -57
  244. package/test/pairing.test.ts +0 -35
  245. package/test/result-state.test.ts +0 -110
  246. package/test/task-parsing.test.ts +0 -82
  247. package/test/taskrun-messages.test.ts +0 -224
  248. package/test/tsconfig.json +0 -9
  249. package/test/windows-xml.test.ts +0 -89
  250. package/tsconfig.json +0 -19
@@ -1,82 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { parseTaskContent } from "../src/task.js";
4
-
5
- describe("parseTaskContent", () => {
6
- it("parses valid frontmatter and body", () => {
7
- const content = `---
8
- id: abc123
9
- name: Test Task
10
- user_prompt: Do something
11
- agent: claude
12
- triggers: []
13
- triggers_enabled: true
14
- requires_confirmation: false
15
- ---
16
- This is the task body.`;
17
-
18
- const result = parseTaskContent(content);
19
- assert.equal(result.frontmatter.id, "abc123");
20
- assert.equal(result.frontmatter.name, "Test Task");
21
- assert.equal(result.frontmatter.agent, "claude");
22
- assert.equal(result.frontmatter.user_prompt, "Do something");
23
- });
24
-
25
- it("defaults agent to claude when not specified", () => {
26
- const content = `---
27
- id: abc123
28
- user_prompt: Do something
29
- triggers: []
30
- triggers_enabled: true
31
- requires_confirmation: false
32
- ---`;
33
-
34
- const result = parseTaskContent(content);
35
- assert.equal(result.frontmatter.agent, "claude");
36
- });
37
-
38
- it("defaults schedule_enabled to true", () => {
39
- const content = `---
40
- id: abc123
41
- user_prompt: Do something
42
- requires_confirmation: false
43
- ---`;
44
-
45
- const result = parseTaskContent(content);
46
- assert.equal(result.frontmatter.schedule_enabled, true);
47
- });
48
-
49
- it("derives name from user_prompt when not specified", () => {
50
- const content = `---
51
- id: abc123
52
- user_prompt: A very long prompt that should be truncated to sixty characters maximum length here
53
- triggers: []
54
- triggers_enabled: true
55
- requires_confirmation: false
56
- ---`;
57
-
58
- const result = parseTaskContent(content);
59
- assert.equal(result.frontmatter.name.length, 60);
60
- });
61
-
62
- it("throws on missing frontmatter delimiters", () => {
63
- assert.throws(() => parseTaskContent("no frontmatter here"), /missing valid YAML/);
64
- });
65
-
66
- it("throws on missing id", () => {
67
- assert.throws(() => parseTaskContent("---\nname: test\n---\n"), /must include at least: id/);
68
- });
69
-
70
- it("handles empty body gracefully", () => {
71
- const content = `---
72
- id: abc123
73
- user_prompt: test
74
- triggers: []
75
- triggers_enabled: true
76
- requires_confirmation: false
77
- ---`;
78
-
79
- const result = parseTaskContent(content);
80
- assert.equal(result.frontmatter.id, "abc123");
81
- });
82
- });
@@ -1,224 +0,0 @@
1
- import { describe, it, beforeEach } from "node:test";
2
- import assert from "node:assert/strict";
3
- import * as fs from "fs";
4
- import * as os from "os";
5
- import * as path from "path";
6
- import {
7
- createRunDir,
8
- appendRunMessage,
9
- readRunMessages,
10
- beginStreamingMessage,
11
- spliceUserMessage,
12
- } from "../src/task.js";
13
-
14
- let taskDir: string;
15
- let runId: string;
16
-
17
- function setup() {
18
- taskDir = fs.mkdtempSync(path.join(os.tmpdir(), "palmier-test-"));
19
- runId = createRunDir(taskDir, "Test Task", 1000, "claude");
20
- }
21
-
22
- describe("appendRunMessage + readRunMessages", () => {
23
- beforeEach(setup);
24
-
25
- it("writes and reads a user message", () => {
26
- appendRunMessage(taskDir, runId, { role: "user", time: 1001, content: "Hello" });
27
- const msgs = readRunMessages(taskDir, runId);
28
- assert.equal(msgs.length, 1);
29
- assert.equal(msgs[0].role, "user");
30
- assert.equal(msgs[0].content, "Hello");
31
- assert.equal(msgs[0].time, 1001);
32
- });
33
-
34
- it("writes and reads an assistant message", () => {
35
- appendRunMessage(taskDir, runId, { role: "assistant", time: 1002, content: "Hi there" });
36
- const msgs = readRunMessages(taskDir, runId);
37
- assert.equal(msgs.length, 1);
38
- assert.equal(msgs[0].role, "assistant");
39
- assert.equal(msgs[0].content, "Hi there");
40
- });
41
-
42
- it("writes and reads a status message", () => {
43
- appendRunMessage(taskDir, runId, { role: "status", time: 1003, content: "", type: "started" });
44
- const msgs = readRunMessages(taskDir, runId);
45
- assert.equal(msgs.length, 1);
46
- assert.equal(msgs[0].role, "status");
47
- assert.equal(msgs[0].type, "started");
48
- });
49
-
50
- it("preserves message type", () => {
51
- appendRunMessage(taskDir, runId, { role: "user", time: 1004, content: "Confirmed", type: "confirmation" });
52
- const msgs = readRunMessages(taskDir, runId);
53
- assert.equal(msgs[0].type, "confirmation");
54
- });
55
-
56
- it("preserves attachments", () => {
57
- appendRunMessage(taskDir, runId, { role: "assistant", time: 1005, content: "Done", attachments: ["report.md", "chart.png"] });
58
- const msgs = readRunMessages(taskDir, runId);
59
- assert.deepEqual(msgs[0].attachments, ["report.md", "chart.png"]);
60
- });
61
-
62
- it("reads multiple messages in order", () => {
63
- appendRunMessage(taskDir, runId, { role: "status", time: 1000, content: "", type: "started" });
64
- appendRunMessage(taskDir, runId, { role: "user", time: 1001, content: "Do something" });
65
- appendRunMessage(taskDir, runId, { role: "assistant", time: 1002, content: "Done" });
66
- appendRunMessage(taskDir, runId, { role: "status", time: 1003, content: "", type: "finished" });
67
- const msgs = readRunMessages(taskDir, runId);
68
- assert.equal(msgs.length, 4);
69
- assert.equal(msgs[0].type, "started");
70
- assert.equal(msgs[1].role, "user");
71
- assert.equal(msgs[2].role, "assistant");
72
- assert.equal(msgs[3].type, "finished");
73
- });
74
- });
75
-
76
- describe("confirmation flow", () => {
77
- beforeEach(setup);
78
-
79
- it("records confirmation with assistant prompt, user response, and status", () => {
80
- appendRunMessage(taskDir, runId, { role: "status", time: 1000, content: "", type: "started" });
81
- appendRunMessage(taskDir, runId, { role: "assistant", time: 1001, content: '**Task Confirmation**\n\nRun task "My Task"?', type: "confirmation" });
82
- appendRunMessage(taskDir, runId, { role: "user", time: 1002, content: "Confirmed", type: "confirmation" });
83
- appendRunMessage(taskDir, runId, { role: "status", time: 1003, content: "", type: "confirmation" });
84
-
85
- const msgs = readRunMessages(taskDir, runId);
86
- assert.equal(msgs.length, 4);
87
- assert.equal(msgs[1].role, "assistant");
88
- assert.ok(msgs[1].content.includes("Task Confirmation"));
89
- assert.equal(msgs[2].role, "user");
90
- assert.equal(msgs[2].content, "Confirmed");
91
- assert.equal(msgs[3].role, "status");
92
- assert.equal(msgs[3].type, "confirmation");
93
- });
94
-
95
- it("records aborted confirmation", () => {
96
- appendRunMessage(taskDir, runId, { role: "status", time: 1000, content: "", type: "started" });
97
- appendRunMessage(taskDir, runId, { role: "assistant", time: 1001, content: '**Task Confirmation**\n\nRun task "My Task"?', type: "confirmation" });
98
- appendRunMessage(taskDir, runId, { role: "user", time: 1002, content: "Aborted", type: "confirmation" });
99
- appendRunMessage(taskDir, runId, { role: "status", time: 1003, content: "", type: "aborted" });
100
-
101
- const msgs = readRunMessages(taskDir, runId);
102
- assert.equal(msgs.length, 4);
103
- assert.equal(msgs[2].content, "Aborted");
104
- assert.equal(msgs[3].type, "aborted");
105
- });
106
- });
107
-
108
- describe("beginStreamingMessage", () => {
109
- beforeEach(setup);
110
-
111
- it("streams chunks and finalizes", () => {
112
- const writer = beginStreamingMessage(taskDir, runId, 2000);
113
- writer.write("Hello ");
114
- writer.write("world");
115
- writer.end();
116
-
117
- const msgs = readRunMessages(taskDir, runId);
118
- assert.equal(msgs.length, 1);
119
- assert.equal(msgs[0].role, "assistant");
120
- assert.equal(msgs[0].content, "Hello world");
121
- });
122
-
123
- it("attaches report files to the last assistant message", () => {
124
- const writer = beginStreamingMessage(taskDir, runId, 2000);
125
- writer.write("Generated report.");
126
- writer.end(["report.md", "chart.png"]);
127
-
128
- const msgs = readRunMessages(taskDir, runId);
129
- assert.equal(msgs.length, 1);
130
- assert.deepEqual(msgs[0].attachments, ["report.md", "chart.png"]);
131
- });
132
- });
133
-
134
- describe("spliceUserMessage", () => {
135
- beforeEach(setup);
136
-
137
- it("splits assistant stream for user input", () => {
138
- const writer = beginStreamingMessage(taskDir, runId, 2000);
139
- writer.write("Working on it...");
140
-
141
- spliceUserMessage(taskDir, runId, { role: "user", time: 2001, content: "my-api-key", type: "input" });
142
-
143
- writer.write("Continuing with key.");
144
- writer.end();
145
-
146
- const msgs = readRunMessages(taskDir, runId);
147
- assert.equal(msgs.length, 3);
148
- assert.equal(msgs[0].role, "assistant");
149
- assert.equal(msgs[0].content, "Working on it...");
150
- assert.equal(msgs[1].role, "user");
151
- assert.equal(msgs[1].content, "my-api-key");
152
- assert.equal(msgs[1].type, "input");
153
- assert.equal(msgs[2].role, "assistant");
154
- assert.equal(msgs[2].content, "Continuing with key.");
155
- });
156
-
157
- it("appends assistant text before splicing", () => {
158
- const writer = beginStreamingMessage(taskDir, runId, 2000);
159
- writer.write("Processing");
160
-
161
- spliceUserMessage(
162
- taskDir, runId,
163
- { role: "user", time: 2001, content: "answer1", type: "input" },
164
- "\n\n**What is your key?**",
165
- );
166
-
167
- writer.write("Done.");
168
- writer.end();
169
-
170
- const msgs = readRunMessages(taskDir, runId);
171
- assert.equal(msgs.length, 3);
172
- assert.ok(msgs[0].content.includes("What is your key?"));
173
- assert.equal(msgs[1].content, "answer1");
174
- assert.equal(msgs[2].content, "Done.");
175
- });
176
-
177
- it("attaches reports to last assistant message after splice", () => {
178
- const writer = beginStreamingMessage(taskDir, runId, 2000);
179
- writer.write("Part 1");
180
-
181
- spliceUserMessage(taskDir, runId, { role: "user", time: 2001, content: "input", type: "input" });
182
-
183
- writer.write("Part 2");
184
- writer.end(["report.md"]);
185
-
186
- const msgs = readRunMessages(taskDir, runId);
187
- // Attachments should be on the last assistant message (after splice), not the first
188
- assert.equal(msgs[0].attachments, undefined);
189
- assert.deepEqual(msgs[2].attachments, ["report.md"]);
190
- });
191
- });
192
-
193
- describe("permission flow", () => {
194
- beforeEach(setup);
195
-
196
- it("records permission grant as user message", () => {
197
- appendRunMessage(taskDir, runId, { role: "status", time: 1000, content: "", type: "started" });
198
- appendRunMessage(taskDir, runId, { role: "user", time: 1001, content: "Do something" });
199
- // Simulate agent output with permission request (via streaming)
200
- const writer = beginStreamingMessage(taskDir, runId, 1002);
201
- writer.write("I need permission.\n\n**Permissions requested:**\n- **Read** Read files\n");
202
- writer.end();
203
- // Permission granted
204
- appendRunMessage(taskDir, runId, { role: "user", time: 1003, content: "Granted", type: "permission" });
205
-
206
- const msgs = readRunMessages(taskDir, runId);
207
- assert.equal(msgs.length, 4);
208
- assert.equal(msgs[3].role, "user");
209
- assert.equal(msgs[3].content, "Granted");
210
- assert.equal(msgs[3].type, "permission");
211
- });
212
-
213
- it("records permission denial", () => {
214
- appendRunMessage(taskDir, runId, { role: "user", time: 1001, content: "Do something" });
215
- const writer = beginStreamingMessage(taskDir, runId, 1002);
216
- writer.write("Need permission.");
217
- writer.end();
218
- appendRunMessage(taskDir, runId, { role: "user", time: 1003, content: "Denied", type: "permission" });
219
-
220
- const msgs = readRunMessages(taskDir, runId);
221
- assert.equal(msgs[2].content, "Denied");
222
- assert.equal(msgs[2].type, "permission");
223
- });
224
- });
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../tsconfig.json",
3
- "compilerOptions": {
4
- "rootDir": "..",
5
- "noEmit": true,
6
- "types": ["node"]
7
- },
8
- "include": ["./**/*", "../src/**/*"]
9
- }
@@ -1,89 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { scheduleValueToXml, buildTaskXml } from "../src/platform/windows.js";
4
-
5
- describe("scheduleValueToXml", () => {
6
- it("converts a specific_times value to TimeTrigger", () => {
7
- const xml = scheduleValueToXml("specific_times", "2026-03-28T09:00");
8
- assert.equal(xml, "<TimeTrigger><StartBoundary>2026-03-28T09:00:00</StartBoundary></TimeTrigger>");
9
- });
10
-
11
- it("converts hourly cron to TimeTrigger with PT1H repetition", () => {
12
- const xml = scheduleValueToXml("crons", "0 * * * *");
13
- assert.ok(xml.includes("<Interval>PT1H</Interval>"), "should have hourly interval");
14
- assert.ok(xml.includes("<TimeTrigger>"), "should be a TimeTrigger");
15
- });
16
-
17
- it("converts daily cron to CalendarTrigger with DaysInterval", () => {
18
- const xml = scheduleValueToXml("crons", "30 9 * * *");
19
- assert.ok(xml.includes("<ScheduleByDay>"), "should use ScheduleByDay");
20
- assert.ok(xml.includes("<DaysInterval>1</DaysInterval>"), "should have interval 1");
21
- assert.ok(xml.includes("T09:30:00"), "should encode time as 09:30");
22
- });
23
-
24
- it("converts weekly cron to CalendarTrigger with DaysOfWeek", () => {
25
- const xml = scheduleValueToXml("crons", "0 10 * * 1");
26
- assert.ok(xml.includes("<ScheduleByWeek>"), "should use ScheduleByWeek");
27
- assert.ok(xml.includes("<Monday />"), "day 1 should be Monday");
28
- assert.ok(xml.includes("T10:00:00"), "should encode time as 10:00");
29
- });
30
-
31
- it("converts weekly cron for Sunday (day 0)", () => {
32
- const xml = scheduleValueToXml("crons", "0 8 * * 0");
33
- assert.ok(xml.includes("<Sunday />"), "day 0 should be Sunday");
34
- });
35
-
36
- it("converts weekly cron for Sunday (day 7)", () => {
37
- const xml = scheduleValueToXml("crons", "0 8 * * 7");
38
- assert.ok(xml.includes("<Sunday />"), "day 7 should also be Sunday");
39
- });
40
-
41
- it("converts monthly cron to CalendarTrigger with DaysOfMonth", () => {
42
- const xml = scheduleValueToXml("crons", "0 14 15 * *");
43
- assert.ok(xml.includes("<ScheduleByMonth>"), "should use ScheduleByMonth");
44
- assert.ok(xml.includes("<Day>15</Day>"), "should have day 15");
45
- assert.ok(xml.includes("T14:00:00"), "should encode time as 14:00");
46
- assert.ok(xml.includes("<January />"), "should include January");
47
- assert.ok(xml.includes("<December />"), "should include December");
48
- });
49
-
50
- it("throws on invalid cron expression", () => {
51
- assert.throws(() => scheduleValueToXml("crons", "bad"), /Invalid cron/);
52
- });
53
- });
54
-
55
- describe("buildTaskXml", () => {
56
- it("produces valid XML structure with StopExisting policy", () => {
57
- const tr = '"C:\\Program Files\\nodejs\\node.exe" "C:\\palmier\\dist\\index.js" run abc123';
58
- const triggers = ['<TimeTrigger><StartBoundary>2000-01-01T00:00:00</StartBoundary></TimeTrigger>'];
59
- const xml = buildTaskXml(tr, triggers);
60
-
61
- assert.ok(xml.includes('<?xml version="1.0" encoding="UTF-16"?>'), "should have XML declaration");
62
- assert.ok(xml.includes("<LogonType>S4U</LogonType>"), "should use S4U logon type");
63
- assert.ok(xml.includes("<RunLevel>LeastPrivilege</RunLevel>"), "should use least privilege");
64
- assert.ok(xml.includes("<MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>"), "should set StopExisting");
65
- assert.ok(xml.includes("<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>"), "should allow on battery");
66
- assert.ok(xml.includes("<Command>C:\\Program Files\\nodejs\\node.exe</Command>"), "should extract command");
67
- assert.ok(xml.includes("<Arguments>C:\\palmier\\dist\\index.js run abc123</Arguments>"), "should extract arguments");
68
- });
69
-
70
- it("handles multiple triggers", () => {
71
- const tr = '"node" "palmier" run test';
72
- const triggers = [
73
- '<TimeTrigger><StartBoundary>2000-01-01T09:00:00</StartBoundary></TimeTrigger>',
74
- '<CalendarTrigger><StartBoundary>2000-01-01T14:00:00</StartBoundary></CalendarTrigger>',
75
- ];
76
- const xml = buildTaskXml(tr, triggers);
77
-
78
- assert.ok(xml.includes("<Triggers><TimeTrigger>"), "should contain first trigger");
79
- assert.ok(xml.includes("</TimeTrigger><CalendarTrigger>"), "triggers should be concatenated");
80
- });
81
-
82
- it("parses command with spaces in path", () => {
83
- const tr = '"C:\\Program Files\\nodejs\\node.exe" "C:\\My Folder\\script.js" serve';
84
- const xml = buildTaskXml(tr, []);
85
-
86
- assert.ok(xml.includes("<Command>C:\\Program Files\\nodejs\\node.exe</Command>"));
87
- assert.ok(xml.includes("<Arguments>C:\\My Folder\\script.js serve</Arguments>"));
88
- });
89
- });
package/tsconfig.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "Node16",
5
- "moduleResolution": "Node16",
6
- "outDir": "dist",
7
- "rootDir": "src",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "forceConsistentCasingInFileNames": true,
12
- "resolveJsonModule": true,
13
- "declaration": true,
14
- "declarationMap": true,
15
- "sourceMap": true
16
- },
17
- "include": ["src/**/*"],
18
- "exclude": ["node_modules", "dist"]
19
- }