palmier 0.9.5 → 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 (258) hide show
  1. package/README.md +30 -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 +3 -4
  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/apple-touch-icon.png +0 -0
  91. package/dist/pwa/assets/index-D1bIhEbd.css +1 -0
  92. package/dist/pwa/assets/{index-Cvffaohh.js → index-DWvRAUiy.js} +31 -31
  93. package/dist/pwa/assets/{web-qdLcAD7T.js → web-C4iZbqTC.js} +1 -1
  94. package/dist/pwa/assets/{web-ChtbM4nv.js → web-CBFqJGX6.js} +1 -1
  95. package/dist/pwa/assets/{web-hExASsqW.js → web-DL4uXOpS.js} +1 -1
  96. package/dist/pwa/favicon.ico +0 -0
  97. package/dist/pwa/index.html +3 -3
  98. package/dist/pwa/manifest.webmanifest +1 -1
  99. package/dist/pwa/pwa-192x192.png +0 -0
  100. package/dist/pwa/pwa-512x512.png +0 -0
  101. package/dist/pwa/service-worker.js +1 -1
  102. package/dist/rpc-handler.d.ts +0 -1
  103. package/dist/rpc-handler.js +3 -10
  104. package/dist/sms-store.d.ts +0 -1
  105. package/dist/sms-store.js +0 -1
  106. package/dist/spawn-command.d.ts +0 -1
  107. package/dist/spawn-command.js +0 -1
  108. package/dist/task.d.ts +1 -1
  109. package/dist/task.js +14 -1
  110. package/dist/transports/http-transport.d.ts +0 -1
  111. package/dist/transports/http-transport.js +0 -1
  112. package/dist/transports/nats-transport.d.ts +0 -1
  113. package/dist/transports/nats-transport.js +0 -1
  114. package/dist/types.d.ts +0 -1
  115. package/dist/types.js +0 -1
  116. package/dist/update-checker.d.ts +0 -1
  117. package/dist/update-checker.js +0 -1
  118. package/package.json +5 -1
  119. package/.github/workflows/ci.yml +0 -16
  120. package/.github/workflows/publish.yml +0 -37
  121. package/CLAUDE.md +0 -22
  122. package/dist/pwa/assets/index-DBgOYBrB.css +0 -1
  123. package/palmier-server/.github/workflows/ci.yml +0 -21
  124. package/palmier-server/.github/workflows/deploy.yml +0 -38
  125. package/palmier-server/CLAUDE.md +0 -17
  126. package/palmier-server/PRODUCTION.md +0 -358
  127. package/palmier-server/README.md +0 -231
  128. package/palmier-server/nats.conf +0 -19
  129. package/palmier-server/package.json +0 -15
  130. package/palmier-server/pnpm-lock.yaml +0 -7639
  131. package/palmier-server/pnpm-workspace.yaml +0 -3
  132. package/palmier-server/pwa/index.html +0 -16
  133. package/palmier-server/pwa/logo/logo-prompt.md +0 -28
  134. package/palmier-server/pwa/logo/logo_20260330.png +0 -0
  135. package/palmier-server/pwa/package.json +0 -34
  136. package/palmier-server/pwa/public/apple-touch-icon.png +0 -0
  137. package/palmier-server/pwa/public/favicon.ico +0 -0
  138. package/palmier-server/pwa/public/pwa-192x192.png +0 -0
  139. package/palmier-server/pwa/public/pwa-512x512.png +0 -0
  140. package/palmier-server/pwa/src/App.css +0 -3004
  141. package/palmier-server/pwa/src/App.tsx +0 -59
  142. package/palmier-server/pwa/src/agentLabels.ts +0 -11
  143. package/palmier-server/pwa/src/api.ts +0 -67
  144. package/palmier-server/pwa/src/components/CapabilityToggles.tsx +0 -170
  145. package/palmier-server/pwa/src/components/ConnectionStatusIcon.tsx +0 -114
  146. package/palmier-server/pwa/src/components/HostMenu.tsx +0 -429
  147. package/palmier-server/pwa/src/components/PermissionsDialog.tsx +0 -34
  148. package/palmier-server/pwa/src/components/PullToRefreshIndicator.tsx +0 -46
  149. package/palmier-server/pwa/src/components/RunDetailView.tsx +0 -343
  150. package/palmier-server/pwa/src/components/SessionComposer.tsx +0 -157
  151. package/palmier-server/pwa/src/components/SessionsView.tsx +0 -326
  152. package/palmier-server/pwa/src/components/SwipeToDeleteRow.tsx +0 -170
  153. package/palmier-server/pwa/src/components/TabBar.tsx +0 -40
  154. package/palmier-server/pwa/src/components/TaskCard.tsx +0 -255
  155. package/palmier-server/pwa/src/components/TaskForm.tsx +0 -764
  156. package/palmier-server/pwa/src/components/TasksView.tsx +0 -179
  157. package/palmier-server/pwa/src/constants.ts +0 -2
  158. package/palmier-server/pwa/src/contexts/HostConnectionContext.tsx +0 -432
  159. package/palmier-server/pwa/src/contexts/HostStoreContext.tsx +0 -124
  160. package/palmier-server/pwa/src/draftGuard.ts +0 -24
  161. package/palmier-server/pwa/src/formatTime.ts +0 -44
  162. package/palmier-server/pwa/src/hooks/useBackClose.ts +0 -75
  163. package/palmier-server/pwa/src/hooks/useMediaQuery.ts +0 -17
  164. package/palmier-server/pwa/src/hooks/usePullToRefresh.ts +0 -102
  165. package/palmier-server/pwa/src/hooks/usePushSubscription.ts +0 -77
  166. package/palmier-server/pwa/src/main.tsx +0 -14
  167. package/palmier-server/pwa/src/native/Device.ts +0 -49
  168. package/palmier-server/pwa/src/pages/Dashboard.tsx +0 -542
  169. package/palmier-server/pwa/src/pages/PairHost.tsx +0 -232
  170. package/palmier-server/pwa/src/pages/PairSetup.tsx +0 -134
  171. package/palmier-server/pwa/src/service-worker.ts +0 -142
  172. package/palmier-server/pwa/src/types.ts +0 -75
  173. package/palmier-server/pwa/src/vite-env.d.ts +0 -11
  174. package/palmier-server/pwa/tsconfig.json +0 -21
  175. package/palmier-server/pwa/tsconfig.node.json +0 -19
  176. package/palmier-server/pwa/vite.config.ts +0 -47
  177. package/palmier-server/server/.env.example +0 -20
  178. package/palmier-server/server/package.json +0 -36
  179. package/palmier-server/server/src/db.ts +0 -44
  180. package/palmier-server/server/src/fcm.ts +0 -74
  181. package/palmier-server/server/src/index.ts +0 -688
  182. package/palmier-server/server/src/nats-jwt.ts +0 -299
  183. package/palmier-server/server/src/nats-setup.ts +0 -48
  184. package/palmier-server/server/src/nats.ts +0 -33
  185. package/palmier-server/server/src/notify.ts +0 -34
  186. package/palmier-server/server/src/push.ts +0 -68
  187. package/palmier-server/server/src/routes/device.ts +0 -224
  188. package/palmier-server/server/src/routes/fcm.ts +0 -64
  189. package/palmier-server/server/src/routes/hosts.ts +0 -56
  190. package/palmier-server/server/src/routes/push.ts +0 -101
  191. package/palmier-server/server/tsconfig.json +0 -20
  192. package/palmier-server/spec.md +0 -533
  193. package/src/agents/agent-instructions.md +0 -28
  194. package/src/agents/agent.ts +0 -114
  195. package/src/agents/aider.ts +0 -35
  196. package/src/agents/claude.ts +0 -39
  197. package/src/agents/cline.ts +0 -35
  198. package/src/agents/codex.ts +0 -40
  199. package/src/agents/copilot.ts +0 -37
  200. package/src/agents/cursor.ts +0 -36
  201. package/src/agents/deepagents.ts +0 -36
  202. package/src/agents/droid.ts +0 -35
  203. package/src/agents/gemini.ts +0 -43
  204. package/src/agents/goose.ts +0 -33
  205. package/src/agents/hermes.ts +0 -36
  206. package/src/agents/kimi.ts +0 -35
  207. package/src/agents/kiro.ts +0 -36
  208. package/src/agents/openclaw.ts +0 -29
  209. package/src/agents/opencode.ts +0 -36
  210. package/src/agents/qoder.ts +0 -36
  211. package/src/agents/qwen.ts +0 -32
  212. package/src/agents/shared-prompt.ts +0 -30
  213. package/src/client-store.ts +0 -68
  214. package/src/commands/clients.ts +0 -29
  215. package/src/commands/info.ts +0 -29
  216. package/src/commands/init.ts +0 -165
  217. package/src/commands/pair.ts +0 -137
  218. package/src/commands/restart.ts +0 -6
  219. package/src/commands/run.ts +0 -608
  220. package/src/commands/serve.ts +0 -211
  221. package/src/commands/uninstall.ts +0 -9
  222. package/src/config.ts +0 -36
  223. package/src/cross-spawn.d.ts +0 -5
  224. package/src/event-queues.ts +0 -41
  225. package/src/events.ts +0 -29
  226. package/src/index.ts +0 -111
  227. package/src/linked-device.ts +0 -52
  228. package/src/mcp-handler.ts +0 -200
  229. package/src/mcp-tools.ts +0 -839
  230. package/src/nats-client.ts +0 -19
  231. package/src/network.ts +0 -96
  232. package/src/notification-store.ts +0 -30
  233. package/src/pending-requests.ts +0 -73
  234. package/src/platform/index.ts +0 -20
  235. package/src/platform/linux.ts +0 -296
  236. package/src/platform/macos.ts +0 -329
  237. package/src/platform/platform.ts +0 -31
  238. package/src/platform/windows.ts +0 -299
  239. package/src/rpc-handler.ts +0 -694
  240. package/src/sms-store.ts +0 -28
  241. package/src/spawn-command.ts +0 -123
  242. package/src/task.ts +0 -330
  243. package/src/transports/http-transport.ts +0 -478
  244. package/src/transports/nats-transport.ts +0 -76
  245. package/src/types.ts +0 -89
  246. package/src/update-checker.ts +0 -40
  247. package/test/agent-instructions.test.ts +0 -209
  248. package/test/agent-output-parsing.test.ts +0 -74
  249. package/test/linux-cron.test.ts +0 -41
  250. package/test/macos-plist.test.ts +0 -112
  251. package/test/notification-store.test.ts +0 -57
  252. package/test/pairing.test.ts +0 -35
  253. package/test/result-state.test.ts +0 -110
  254. package/test/task-parsing.test.ts +0 -82
  255. package/test/taskrun-messages.test.ts +0 -224
  256. package/test/tsconfig.json +0 -9
  257. package/test/windows-xml.test.ts +0 -89
  258. 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
- }