palmier 1.1.21 → 1.1.23
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/README.md +2 -19
- package/dist/agent-tools.d.ts +1 -1
- package/dist/agent-tools.js +36 -48
- package/dist/agents/agent-instructions.md +3 -1
- package/dist/agents/agent.d.ts +3 -8
- package/dist/agents/agent.js +0 -1
- package/dist/agents/aider.js +2 -7
- package/dist/agents/claude.js +2 -11
- package/dist/agents/cline.js +2 -7
- package/dist/agents/codex.js +2 -4
- package/dist/agents/copilot.js +2 -10
- package/dist/agents/cursor.js +2 -7
- package/dist/agents/deepagents.js +2 -7
- package/dist/agents/droid.js +2 -7
- package/dist/agents/goose.js +2 -4
- package/dist/agents/grok.js +2 -7
- package/dist/agents/hermes.js +2 -7
- package/dist/agents/kimi.js +2 -6
- package/dist/agents/kiro.js +2 -7
- package/dist/agents/openclaw.js +1 -1
- package/dist/agents/opencode.js +2 -7
- package/dist/agents/qoder.js +2 -7
- package/dist/agents/qwen.js +2 -4
- package/dist/agents/shared-prompt.js +3 -8
- package/dist/agents/wizard.js +0 -1
- package/dist/commands/pair.js +2 -4
- package/dist/commands/run.js +3 -15
- package/dist/commands/serve.js +5 -6
- package/dist/index.js +0 -22
- package/dist/nats-client.d.ts +1 -1
- package/dist/nats-client.js +1 -1
- package/dist/password-store.d.ts +1 -3
- package/dist/password-store.js +1 -7
- package/dist/pwa/assets/index-BPB3G_2J.css +1 -0
- package/dist/pwa/assets/{index-rqAuAC0q.js → index-De8hDN5I.js} +42 -46
- package/dist/pwa/assets/{web-ew6AFUex.js → web-BQ0rMZ_X.js} +1 -1
- package/dist/pwa/assets/{web-DQDmufih.js → web-miCfAJBc.js} +1 -1
- package/dist/pwa/assets/{web-Dp5Zj6HJ.js → web-o_D8jqAS.js} +1 -1
- package/dist/pwa/index.html +2 -2
- package/dist/rpc-handler.js +14 -15
- package/dist/task.d.ts +10 -0
- package/dist/task.js +42 -0
- package/dist/transports/http-transport.d.ts +1 -1
- package/dist/transports/http-transport.js +1 -3
- package/dist/transports/nats-transport.d.ts +1 -1
- package/dist/transports/nats-transport.js +3 -5
- package/dist/types.d.ts +0 -2
- package/package.json +2 -2
- package/dist/commands/passwords.d.ts +0 -3
- package/dist/commands/passwords.js +0 -25
- package/dist/pwa/assets/index-ByB7B0d2.css +0 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ The control surface is bidirectional:
|
|
|
13
13
|
* **Phone → agents:** start ad-hoc sessions, register schedule- or event-triggered tasks, inspect session output, and respond to agent input/confirmation requests.
|
|
14
14
|
* **Agents → phone:** agents can read device state (location, calendar, contacts, notifications, SMS, battery) and trigger actions (push notifications, full-screen alarms, SMS, email, contact/calendar writes, ringer mode).
|
|
15
15
|
|
|
16
|
-
Capability access is opt-in per device: each capability is gated behind an Android permission and a per-host toggle.
|
|
16
|
+
Capability access is opt-in per device: each capability is gated behind an Android permission and a per-host toggle. Agents always run in yolo mode (all tool calls auto-approved) when their CLI supports it.
|
|
17
17
|
|
|
18
18
|
## Quick Start
|
|
19
19
|
|
|
@@ -158,21 +158,7 @@ Revoking the linked device also clears the host's linked-device record; device c
|
|
|
158
158
|
|
|
159
159
|
Palmier can store website passwords and PINs like a browser's password manager so agents can sign in to sites without ever seeing the credentials. When an agent driving a browser (via the `playwright-cli` skill) reaches a login or PIN field, it calls the `fill-password` tool with the page URL, the username, and the field's element ref. Palmier matches the saved secret by **origin**, fills it directly into the live browser session, and presses Enter to submit the form in the same step — so the plaintext secret sits on the page for as little time as possible and never enters the agent's context. If nothing is saved for that `(origin, username)`, Palmier prompts you in the app with a masked dialog. The dialog has a "Save for next time" checkbox (on by default): leave it checked to store the secret for reuse, or uncheck it to fill it just this once without saving. Either way it is filled into the page. The plaintext secret is never returned to the agent and is never written to task history.
|
|
160
160
|
|
|
161
|
-
Saved passwords and PINs are encrypted at rest with AES-256-GCM under a host-local key, both stored in `~/.config/palmier/` (`passwords.enc` and `password-key`). Manage them from the app via **Manage saved passwords** in the side panel (lists origin and username only, with per-entry delete)
|
|
162
|
-
|
|
163
|
-
```bash
|
|
164
|
-
# List saved passwords (origin and username only — never the password)
|
|
165
|
-
palmier passwords list
|
|
166
|
-
|
|
167
|
-
# Delete a specific saved password
|
|
168
|
-
palmier passwords delete https://example.com alice
|
|
169
|
-
|
|
170
|
-
# Delete every saved password for an origin
|
|
171
|
-
palmier passwords delete https://example.com
|
|
172
|
-
|
|
173
|
-
# Delete all saved passwords
|
|
174
|
-
palmier passwords clear
|
|
175
|
-
```
|
|
161
|
+
Saved passwords and PINs are encrypted at rest with AES-256-GCM under a host-local key, both stored in `~/.config/palmier/` (`passwords.enc` and `password-key`). Manage them from the app via **Manage saved passwords** in the side panel (lists origin and username only, with per-entry delete).
|
|
176
162
|
|
|
177
163
|
### The `init` Command
|
|
178
164
|
|
|
@@ -229,9 +215,6 @@ The default network interface is detected once during `palmier init` and saved t
|
|
|
229
215
|
| `palmier clients list` | List active client tokens |
|
|
230
216
|
| `palmier clients revoke <token>` | Revoke a specific client token |
|
|
231
217
|
| `palmier clients revoke-all` | Revoke all client tokens |
|
|
232
|
-
| `palmier passwords list` | List saved passwords (origin and username only) |
|
|
233
|
-
| `palmier passwords delete <origin> [username]` | Delete a saved password (omit username to delete all for the origin) |
|
|
234
|
-
| `palmier passwords clear` | Delete all saved passwords |
|
|
235
218
|
| `palmier info` | Show host connection info (address, mode) |
|
|
236
219
|
| `palmier serve` | Run the persistent RPC handler (default command) |
|
|
237
220
|
| `palmier restart` | Restart the palmier serve daemon |
|
package/dist/agent-tools.d.ts
CHANGED
package/dist/agent-tools.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { StringCodec } from "nats";
|
|
2
1
|
import { registerPending } from "./pending-requests.js";
|
|
3
2
|
import { getLinkedDevice } from "./linked-device.js";
|
|
4
3
|
import { getNotifications } from "./notification-store.js";
|
|
@@ -33,11 +32,10 @@ const notifyTool = {
|
|
|
33
32
|
throw new ToolError("title and body are required", 400);
|
|
34
33
|
if (!ctx.nc)
|
|
35
34
|
throw new ToolError("NATS not connected — push notifications require server mode", 503);
|
|
36
|
-
const sc = StringCodec();
|
|
37
35
|
const payload = { hostId: ctx.config.hostId, title, body, session_id: ctx.taskId };
|
|
38
36
|
const subject = `host.${ctx.config.hostId}.push.send`;
|
|
39
|
-
const reply = await ctx.nc.request(subject,
|
|
40
|
-
const result = JSON.parse(
|
|
37
|
+
const reply = await ctx.nc.request(subject, JSON.stringify(payload), { timeout: 15_000 });
|
|
38
|
+
const result = JSON.parse(reply.string());
|
|
41
39
|
if (result.ok)
|
|
42
40
|
return { ok: true };
|
|
43
41
|
throw new ToolError(result.error ?? "Push notification failed", 502);
|
|
@@ -309,9 +307,8 @@ const deviceGeolocationTool = {
|
|
|
309
307
|
const device = getLinkedDevice();
|
|
310
308
|
if (!device)
|
|
311
309
|
throw new ToolError("No linked device configured", 400);
|
|
312
|
-
const
|
|
313
|
-
const
|
|
314
|
-
const ack = JSON.parse(sc.decode(ackReply.data));
|
|
310
|
+
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.geolocation`, JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.taskId, fcmToken: device.fcmToken }), { timeout: 5_000 });
|
|
311
|
+
const ack = JSON.parse(ackReply.string());
|
|
315
312
|
if (ack.error)
|
|
316
313
|
throw new ToolError(ack.error, 502);
|
|
317
314
|
const locationPromise = new Promise((resolve, reject) => {
|
|
@@ -323,7 +320,7 @@ const deviceGeolocationTool = {
|
|
|
323
320
|
(async () => {
|
|
324
321
|
for await (const msg of sub) {
|
|
325
322
|
clearTimeout(timer);
|
|
326
|
-
resolve(
|
|
323
|
+
resolve(msg.string());
|
|
327
324
|
}
|
|
328
325
|
})();
|
|
329
326
|
});
|
|
@@ -350,9 +347,8 @@ const readContactsTool = {
|
|
|
350
347
|
const device = getLinkedDevice();
|
|
351
348
|
if (!device)
|
|
352
349
|
throw new ToolError("No linked device configured", 400);
|
|
353
|
-
const
|
|
354
|
-
const
|
|
355
|
-
const ack = JSON.parse(sc.decode(ackReply.data));
|
|
350
|
+
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.contacts`, JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.taskId, fcmToken: device.fcmToken, action: "read" }), { timeout: 5_000 });
|
|
351
|
+
const ack = JSON.parse(ackReply.string());
|
|
356
352
|
if (ack.error)
|
|
357
353
|
throw new ToolError(ack.error, 502);
|
|
358
354
|
const responsePromise = new Promise((resolve, reject) => {
|
|
@@ -364,7 +360,7 @@ const readContactsTool = {
|
|
|
364
360
|
(async () => {
|
|
365
361
|
for await (const msg of sub) {
|
|
366
362
|
clearTimeout(timer);
|
|
367
|
-
resolve(
|
|
363
|
+
resolve(msg.string());
|
|
368
364
|
}
|
|
369
365
|
})();
|
|
370
366
|
});
|
|
@@ -399,12 +395,11 @@ const createContactTool = {
|
|
|
399
395
|
const { name, phone, email } = args;
|
|
400
396
|
if (!name)
|
|
401
397
|
throw new ToolError("name is required", 400);
|
|
402
|
-
const
|
|
403
|
-
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.contacts`, sc.encode(JSON.stringify({
|
|
398
|
+
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.contacts`, JSON.stringify({
|
|
404
399
|
hostId: ctx.config.hostId, requestId: ctx.taskId, fcmToken: device.fcmToken,
|
|
405
400
|
action: "create", name, phone, email,
|
|
406
|
-
})
|
|
407
|
-
const ack = JSON.parse(
|
|
401
|
+
}), { timeout: 5_000 });
|
|
402
|
+
const ack = JSON.parse(ackReply.string());
|
|
408
403
|
if (ack.error)
|
|
409
404
|
throw new ToolError(ack.error, 502);
|
|
410
405
|
const responsePromise = new Promise((resolve, reject) => {
|
|
@@ -416,7 +411,7 @@ const createContactTool = {
|
|
|
416
411
|
(async () => {
|
|
417
412
|
for await (const msg of sub) {
|
|
418
413
|
clearTimeout(timer);
|
|
419
|
-
resolve(
|
|
414
|
+
resolve(msg.string());
|
|
420
415
|
}
|
|
421
416
|
})();
|
|
422
417
|
});
|
|
@@ -448,14 +443,13 @@ const readCalendarTool = {
|
|
|
448
443
|
if (!device)
|
|
449
444
|
throw new ToolError("No linked device configured", 400);
|
|
450
445
|
const { startDate, endDate } = args;
|
|
451
|
-
const
|
|
452
|
-
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.calendar`, sc.encode(JSON.stringify({
|
|
446
|
+
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.calendar`, JSON.stringify({
|
|
453
447
|
hostId: ctx.config.hostId, requestId: ctx.taskId, fcmToken: device.fcmToken,
|
|
454
448
|
action: "read",
|
|
455
449
|
...(startDate ? { startDate: String(startDate) } : {}),
|
|
456
450
|
...(endDate ? { endDate: String(endDate) } : {}),
|
|
457
|
-
})
|
|
458
|
-
const ack = JSON.parse(
|
|
451
|
+
}), { timeout: 5_000 });
|
|
452
|
+
const ack = JSON.parse(ackReply.string());
|
|
459
453
|
if (ack.error)
|
|
460
454
|
throw new ToolError(ack.error, 502);
|
|
461
455
|
const responsePromise = new Promise((resolve, reject) => {
|
|
@@ -467,7 +461,7 @@ const readCalendarTool = {
|
|
|
467
461
|
(async () => {
|
|
468
462
|
for await (const msg of sub) {
|
|
469
463
|
clearTimeout(timer);
|
|
470
|
-
resolve(
|
|
464
|
+
resolve(msg.string());
|
|
471
465
|
}
|
|
472
466
|
})();
|
|
473
467
|
});
|
|
@@ -504,15 +498,14 @@ const createCalendarEventTool = {
|
|
|
504
498
|
const { title, startTime, endTime, location, description } = args;
|
|
505
499
|
if (!title || !startTime || !endTime)
|
|
506
500
|
throw new ToolError("title, startTime, and endTime are required", 400);
|
|
507
|
-
const
|
|
508
|
-
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.calendar`, sc.encode(JSON.stringify({
|
|
501
|
+
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.calendar`, JSON.stringify({
|
|
509
502
|
hostId: ctx.config.hostId, requestId: ctx.taskId, fcmToken: device.fcmToken,
|
|
510
503
|
action: "create",
|
|
511
504
|
title, startTime: String(startTime), endTime: String(endTime),
|
|
512
505
|
...(location ? { location } : {}),
|
|
513
506
|
...(description ? { description } : {}),
|
|
514
|
-
})
|
|
515
|
-
const ack = JSON.parse(
|
|
507
|
+
}), { timeout: 5_000 });
|
|
508
|
+
const ack = JSON.parse(ackReply.string());
|
|
516
509
|
if (ack.error)
|
|
517
510
|
throw new ToolError(ack.error, 502);
|
|
518
511
|
const responsePromise = new Promise((resolve, reject) => {
|
|
@@ -524,7 +517,7 @@ const createCalendarEventTool = {
|
|
|
524
517
|
(async () => {
|
|
525
518
|
for await (const msg of sub) {
|
|
526
519
|
clearTimeout(timer);
|
|
527
|
-
resolve(
|
|
520
|
+
resolve(msg.string());
|
|
528
521
|
}
|
|
529
522
|
})();
|
|
530
523
|
});
|
|
@@ -558,12 +551,11 @@ const sendSmsTool = {
|
|
|
558
551
|
const { to, body } = args;
|
|
559
552
|
if (!to || !body)
|
|
560
553
|
throw new ToolError("to and body are required", 400);
|
|
561
|
-
const
|
|
562
|
-
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.sms`, sc.encode(JSON.stringify({
|
|
554
|
+
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.sms`, JSON.stringify({
|
|
563
555
|
hostId: ctx.config.hostId, requestId: ctx.taskId, fcmToken: device.fcmToken,
|
|
564
556
|
action: "send", to, body,
|
|
565
|
-
})
|
|
566
|
-
const ack = JSON.parse(
|
|
557
|
+
}), { timeout: 5_000 });
|
|
558
|
+
const ack = JSON.parse(ackReply.string());
|
|
567
559
|
if (ack.error)
|
|
568
560
|
throw new ToolError(ack.error, 502);
|
|
569
561
|
const responsePromise = new Promise((resolve, reject) => {
|
|
@@ -575,7 +567,7 @@ const sendSmsTool = {
|
|
|
575
567
|
(async () => {
|
|
576
568
|
for await (const msg of sub) {
|
|
577
569
|
clearTimeout(timer);
|
|
578
|
-
resolve(
|
|
570
|
+
resolve(msg.string());
|
|
579
571
|
}
|
|
580
572
|
})();
|
|
581
573
|
});
|
|
@@ -610,15 +602,14 @@ const sendAlarmTool = {
|
|
|
610
602
|
const { title, description } = args;
|
|
611
603
|
if (!title)
|
|
612
604
|
throw new ToolError("title is required", 400);
|
|
613
|
-
const sc = StringCodec();
|
|
614
605
|
const payload = {
|
|
615
606
|
hostId: ctx.config.hostId, requestId: ctx.taskId, fcmToken: device.fcmToken,
|
|
616
607
|
title,
|
|
617
608
|
};
|
|
618
609
|
if (description)
|
|
619
610
|
payload.description = description;
|
|
620
|
-
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.alarm`,
|
|
621
|
-
const ack = JSON.parse(
|
|
611
|
+
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.alarm`, JSON.stringify(payload), { timeout: 5_000 });
|
|
612
|
+
const ack = JSON.parse(ackReply.string());
|
|
622
613
|
if (ack.error)
|
|
623
614
|
throw new ToolError(ack.error, 502);
|
|
624
615
|
const responsePromise = new Promise((resolve, reject) => {
|
|
@@ -630,7 +621,7 @@ const sendAlarmTool = {
|
|
|
630
621
|
(async () => {
|
|
631
622
|
for await (const msg of sub) {
|
|
632
623
|
clearTimeout(timer);
|
|
633
|
-
resolve(
|
|
624
|
+
resolve(msg.string());
|
|
634
625
|
}
|
|
635
626
|
})();
|
|
636
627
|
});
|
|
@@ -657,9 +648,8 @@ const readBatteryTool = {
|
|
|
657
648
|
const device = getLinkedDevice();
|
|
658
649
|
if (!device)
|
|
659
650
|
throw new ToolError("No linked device configured", 400);
|
|
660
|
-
const
|
|
661
|
-
const
|
|
662
|
-
const ack = JSON.parse(sc.decode(ackReply.data));
|
|
651
|
+
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.battery`, JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.taskId, fcmToken: device.fcmToken }), { timeout: 5_000 });
|
|
652
|
+
const ack = JSON.parse(ackReply.string());
|
|
663
653
|
if (ack.error)
|
|
664
654
|
throw new ToolError(ack.error, 502);
|
|
665
655
|
const responsePromise = new Promise((resolve, reject) => {
|
|
@@ -671,7 +661,7 @@ const readBatteryTool = {
|
|
|
671
661
|
(async () => {
|
|
672
662
|
for await (const msg of sub) {
|
|
673
663
|
clearTimeout(timer);
|
|
674
|
-
resolve(
|
|
664
|
+
resolve(msg.string());
|
|
675
665
|
}
|
|
676
666
|
})();
|
|
677
667
|
});
|
|
@@ -704,9 +694,8 @@ const setRingerModeTool = {
|
|
|
704
694
|
const { mode } = args;
|
|
705
695
|
if (!["normal", "vibrate", "silent"].includes(mode))
|
|
706
696
|
throw new ToolError("mode must be 'normal', 'vibrate', or 'silent'", 400);
|
|
707
|
-
const
|
|
708
|
-
const
|
|
709
|
-
const ack = JSON.parse(sc.decode(ackReply.data));
|
|
697
|
+
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.ringer`, JSON.stringify({ hostId: ctx.config.hostId, requestId: ctx.taskId, fcmToken: device.fcmToken, mode }), { timeout: 5_000 });
|
|
698
|
+
const ack = JSON.parse(ackReply.string());
|
|
710
699
|
if (ack.error)
|
|
711
700
|
throw new ToolError(ack.error, 502);
|
|
712
701
|
const responsePromise = new Promise((resolve, reject) => {
|
|
@@ -718,7 +707,7 @@ const setRingerModeTool = {
|
|
|
718
707
|
(async () => {
|
|
719
708
|
for await (const msg of sub) {
|
|
720
709
|
clearTimeout(timer);
|
|
721
|
-
resolve(
|
|
710
|
+
resolve(msg.string());
|
|
722
711
|
}
|
|
723
712
|
})();
|
|
724
713
|
});
|
|
@@ -755,7 +744,6 @@ const sendEmailTool = {
|
|
|
755
744
|
const { to, subject, body, cc, bcc } = args;
|
|
756
745
|
if (!to)
|
|
757
746
|
throw new ToolError("to is required", 400);
|
|
758
|
-
const sc = StringCodec();
|
|
759
747
|
const payload = {
|
|
760
748
|
hostId: ctx.config.hostId, requestId: ctx.taskId, fcmToken: device.fcmToken,
|
|
761
749
|
to,
|
|
@@ -768,8 +756,8 @@ const sendEmailTool = {
|
|
|
768
756
|
payload.cc = cc;
|
|
769
757
|
if (bcc)
|
|
770
758
|
payload.bcc = bcc;
|
|
771
|
-
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.email`,
|
|
772
|
-
const ack = JSON.parse(
|
|
759
|
+
const ackReply = await ctx.nc.request(`host.${ctx.config.hostId}.fcm.email`, JSON.stringify(payload), { timeout: 5_000 });
|
|
760
|
+
const ack = JSON.parse(ackReply.string());
|
|
773
761
|
if (ack.error)
|
|
774
762
|
throw new ToolError(ack.error, 502);
|
|
775
763
|
const responsePromise = new Promise((resolve, reject) => {
|
|
@@ -781,7 +769,7 @@ const sendEmailTool = {
|
|
|
781
769
|
(async () => {
|
|
782
770
|
for await (const msg of sub) {
|
|
783
771
|
clearTimeout(timer);
|
|
784
|
-
resolve(
|
|
772
|
+
resolve(msg.string());
|
|
785
773
|
}
|
|
786
774
|
})();
|
|
787
775
|
});
|
|
@@ -29,7 +29,9 @@ Whenever a tool you are trying to use is denied or you lack the required permiss
|
|
|
29
29
|
|
|
30
30
|
## Browsers
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Whenever the task needs a browser, launch it with the Playwright CLI (`playwright-cli open`). Do not use any other browser tool, automation library, or launch method.
|
|
33
|
+
|
|
34
|
+
When launching, always pass `--headed` (never run headless) and `--persistent` (reuse a persistent profile so logins and cookies survive across runs).
|
|
33
35
|
|
|
34
36
|
When the task is finished, close any browser you opened with the Playwright CLI `close` command (pass the same `-s=<session>` if you used one) before printing the completion marker.
|
|
35
37
|
|
package/dist/agents/agent.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ParsedTask
|
|
1
|
+
import type { ParsedTask } from "../types.js";
|
|
2
2
|
export interface CommandLine {
|
|
3
3
|
args: string[];
|
|
4
4
|
/** If provided, the string is written to the process's stdin and then the pipe is closed. */
|
|
@@ -28,8 +28,6 @@ export interface AgentTool {
|
|
|
28
28
|
/** Whether this agent supports permission overrides (e.g. --allowedTools).
|
|
29
29
|
* When falsy, the permissions section is omitted from agent instructions. */
|
|
30
30
|
supportsPermissions?: boolean;
|
|
31
|
-
/** Whether this agent supports yolo mode (auto-approve all tools). */
|
|
32
|
-
supportsYolo?: boolean;
|
|
33
31
|
/** When true, the run loop persists the agent's stderr output only if the invocation fails. */
|
|
34
32
|
suppressStdErr?: boolean;
|
|
35
33
|
/** Matches the model name (capture group 1) in the banner the CLI prints on stderr.
|
|
@@ -40,10 +38,8 @@ export interface AgentTool {
|
|
|
40
38
|
* Surfaced next to the agent in the installer. */
|
|
41
39
|
freeUsage?: string;
|
|
42
40
|
/** Return the command and args used to run a task. If followupPrompt is provided, use it instead of the task's prompt,
|
|
43
|
-
* and treat it as a continuation of the original run (reuse the same session, etc).
|
|
44
|
-
|
|
45
|
-
* or pass `"yolo"` to enable yolo mode (auto-approve all tools, skip permission instructions). */
|
|
46
|
-
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string, extraPermissions?: RequiredPermission[] | "yolo"): CommandLine;
|
|
41
|
+
* and treat it as a continuation of the original run (reuse the same session, etc). */
|
|
42
|
+
getTaskRunCommandLine(task: ParsedTask, followupPrompt?: string): CommandLine;
|
|
47
43
|
}
|
|
48
44
|
export declare function getPromptCommandLine(agent: AgentTool, prompt: string): CommandLine;
|
|
49
45
|
export declare function probeAgent(agent: AgentTool): Promise<boolean>;
|
|
@@ -56,7 +52,6 @@ export interface DetectedAgent {
|
|
|
56
52
|
key: string;
|
|
57
53
|
label: string;
|
|
58
54
|
supportsPermissions?: boolean;
|
|
59
|
-
supportsYolo?: boolean;
|
|
60
55
|
npmPackage?: string;
|
|
61
56
|
/** Runtime marker for "managed by Palmier" — present iff Palmier installed/manages this agent. */
|
|
62
57
|
version?: string;
|
package/dist/agents/agent.js
CHANGED
|
@@ -121,7 +121,6 @@ export async function detectAgents(previous, newlyInstalled) {
|
|
|
121
121
|
key,
|
|
122
122
|
label: agent.label,
|
|
123
123
|
supportsPermissions: agent.supportsPermissions,
|
|
124
|
-
supportsYolo: agent.supportsYolo,
|
|
125
124
|
...(agent.npmPackage ? { npmPackage: agent.npmPackage } : {}),
|
|
126
125
|
...(version ? { version } : {}),
|
|
127
126
|
});
|
package/dist/agents/aider.js
CHANGED
|
@@ -4,14 +4,9 @@ export const aiderAgent = {
|
|
|
4
4
|
command: "aider",
|
|
5
5
|
promptArgs: ["--message"],
|
|
6
6
|
probeArg: "--version",
|
|
7
|
-
|
|
8
|
-
getTaskRunCommandLine(task, followupPrompt, extraPermissions) {
|
|
9
|
-
const yolo = extraPermissions === "yolo";
|
|
7
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
10
8
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
11
|
-
const args = [];
|
|
12
|
-
if (yolo) {
|
|
13
|
-
args.push("--yes-always");
|
|
14
|
-
}
|
|
9
|
+
const args = ["--yes-always"];
|
|
15
10
|
args.push("--message", prompt);
|
|
16
11
|
return { args };
|
|
17
12
|
},
|
package/dist/agents/claude.js
CHANGED
|
@@ -6,20 +6,11 @@ export const claudeAgent = {
|
|
|
6
6
|
probeArg: "--version",
|
|
7
7
|
authArgs: ["auth", "login"],
|
|
8
8
|
supportsPermissions: true,
|
|
9
|
-
supportsYolo: true,
|
|
10
9
|
npmPackage: "@anthropic-ai/claude-code",
|
|
11
10
|
freeUsage: "Free with Claude Pro",
|
|
12
|
-
getTaskRunCommandLine(task, followupPrompt
|
|
13
|
-
const yolo = extraPermissions === "yolo";
|
|
11
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
14
12
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
15
|
-
const args = ["--permission-mode",
|
|
16
|
-
if (!yolo) {
|
|
17
|
-
args.push("--allowedTools", "WebFetch", "Skill(playwright-cli:*)", "Bash(curl:*)", "Bash(wget:*)", "Bash(playwright:*)", "Bash(playwright-cli:*)");
|
|
18
|
-
const allPerms = [...(task.frontmatter.permissions ?? []), ...(extraPermissions ?? [])];
|
|
19
|
-
for (const p of allPerms) {
|
|
20
|
-
args.push(p.name);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
13
|
+
const args = ["--permission-mode", "bypassPermissions", "-p"];
|
|
23
14
|
if (followupPrompt) {
|
|
24
15
|
args.push("-c");
|
|
25
16
|
}
|
package/dist/agents/cline.js
CHANGED
|
@@ -4,15 +4,10 @@ export const clineAgent = {
|
|
|
4
4
|
command: "cline",
|
|
5
5
|
promptArgs: ["--yolo", "-p"],
|
|
6
6
|
probeArg: "--version",
|
|
7
|
-
supportsYolo: true,
|
|
8
7
|
npmPackage: "cline",
|
|
9
|
-
getTaskRunCommandLine(task, followupPrompt
|
|
10
|
-
const yolo = extraPermissions === "yolo";
|
|
8
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
11
9
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
12
|
-
const args = [];
|
|
13
|
-
if (yolo) {
|
|
14
|
-
args.push("--yolo");
|
|
15
|
-
}
|
|
10
|
+
const args = ["--yolo"];
|
|
16
11
|
args.push(prompt);
|
|
17
12
|
return { args };
|
|
18
13
|
},
|
package/dist/agents/codex.js
CHANGED
|
@@ -5,15 +5,13 @@ export const codexAgent = {
|
|
|
5
5
|
promptArgs: ["exec", "--skip-git-repo-check"],
|
|
6
6
|
probeArg: "--version",
|
|
7
7
|
authArgs: ["login"],
|
|
8
|
-
supportsYolo: true,
|
|
9
8
|
suppressStdErr: true,
|
|
10
9
|
stderrModelPattern: /^model: (.+)$/m,
|
|
11
10
|
npmPackage: "@openai/codex",
|
|
12
11
|
freeUsage: "Free Tier",
|
|
13
|
-
getTaskRunCommandLine(task, followupPrompt
|
|
14
|
-
const yolo = extraPermissions === "yolo";
|
|
12
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
15
13
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
16
|
-
const args = ["exec", "--skip-git-repo-check", "--sandbox",
|
|
14
|
+
const args = ["exec", "--skip-git-repo-check", "--sandbox", "danger-full-access"];
|
|
17
15
|
if (followupPrompt) {
|
|
18
16
|
args.push("resume", "--last");
|
|
19
17
|
}
|
package/dist/agents/copilot.js
CHANGED
|
@@ -5,21 +5,13 @@ export const copilotAgent = {
|
|
|
5
5
|
promptArgs: ["-p"],
|
|
6
6
|
probeArg: "-v",
|
|
7
7
|
authArgs: ["login"],
|
|
8
|
-
supportsYolo: true,
|
|
9
8
|
suppressStdErr: true,
|
|
10
9
|
npmPackage: "@github/copilot",
|
|
11
10
|
freeUsage: "Free Tier",
|
|
12
|
-
getTaskRunCommandLine(task, followupPrompt
|
|
13
|
-
const yolo = extraPermissions === "yolo";
|
|
11
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
14
12
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
15
13
|
const args = ["-p", prompt];
|
|
16
|
-
|
|
17
|
-
args.push("--yolo");
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
const allPerms = [...(task.frontmatter.permissions ?? []), ...(extraPermissions ?? [])];
|
|
21
|
-
args.push(`--allow-tool=${["web_fetch", ...allPerms.map((p) => p.name)].join(",")}`);
|
|
22
|
-
}
|
|
14
|
+
args.push("--yolo");
|
|
23
15
|
if (followupPrompt) {
|
|
24
16
|
args.push("--continue");
|
|
25
17
|
}
|
package/dist/agents/cursor.js
CHANGED
|
@@ -4,14 +4,9 @@ export const cursorAgent = {
|
|
|
4
4
|
command: "cursor",
|
|
5
5
|
promptArgs: ["-p"],
|
|
6
6
|
probeArg: "--version",
|
|
7
|
-
|
|
8
|
-
getTaskRunCommandLine(task, followupPrompt, extraPermissions) {
|
|
9
|
-
const yolo = extraPermissions === "yolo";
|
|
7
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
10
8
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
11
|
-
const args = [];
|
|
12
|
-
if (yolo) {
|
|
13
|
-
args.push("--force");
|
|
14
|
-
}
|
|
9
|
+
const args = ["--force"];
|
|
15
10
|
if (followupPrompt) {
|
|
16
11
|
args.push("--continue");
|
|
17
12
|
}
|
|
@@ -4,14 +4,9 @@ export const deepAgentsAgent = {
|
|
|
4
4
|
command: "deepagents",
|
|
5
5
|
promptArgs: ["--non-interactive"],
|
|
6
6
|
probeArg: "--version",
|
|
7
|
-
|
|
8
|
-
getTaskRunCommandLine(task, followupPrompt, extraPermissions) {
|
|
9
|
-
const yolo = extraPermissions === "yolo";
|
|
7
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
10
8
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
11
|
-
const args = [];
|
|
12
|
-
if (yolo) {
|
|
13
|
-
args.push("--auto-approve");
|
|
14
|
-
}
|
|
9
|
+
const args = ["--auto-approve"];
|
|
15
10
|
if (followupPrompt) {
|
|
16
11
|
args.push("--resume");
|
|
17
12
|
}
|
package/dist/agents/droid.js
CHANGED
|
@@ -4,15 +4,10 @@ export const droidAgent = {
|
|
|
4
4
|
command: "droid",
|
|
5
5
|
promptArgs: ["exec"],
|
|
6
6
|
probeArg: "--version",
|
|
7
|
-
supportsYolo: true,
|
|
8
7
|
npmPackage: "@factory/cli",
|
|
9
|
-
getTaskRunCommandLine(task, followupPrompt
|
|
10
|
-
const yolo = extraPermissions === "yolo";
|
|
8
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
11
9
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
12
|
-
const args = ["exec", "--session-id", task.frontmatter.id];
|
|
13
|
-
if (yolo) {
|
|
14
|
-
args.push("--skip-permissions-unsafe");
|
|
15
|
-
}
|
|
10
|
+
const args = ["exec", "--session-id", task.frontmatter.id, "--skip-permissions-unsafe"];
|
|
16
11
|
args.push(prompt);
|
|
17
12
|
return { args };
|
|
18
13
|
},
|
package/dist/agents/goose.js
CHANGED
|
@@ -4,15 +4,13 @@ export const gooseAgent = {
|
|
|
4
4
|
command: "goose",
|
|
5
5
|
promptArgs: ["run", "--text"],
|
|
6
6
|
probeArg: "--version",
|
|
7
|
-
|
|
8
|
-
getTaskRunCommandLine(task, followupPrompt, extraPermissions) {
|
|
9
|
-
const yolo = extraPermissions === "yolo";
|
|
7
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
10
8
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
11
9
|
const args = ["run"];
|
|
12
10
|
if (followupPrompt) {
|
|
13
11
|
args.push("--resume");
|
|
14
12
|
}
|
|
15
13
|
args.push("--text", prompt);
|
|
16
|
-
return { args,
|
|
14
|
+
return { args, env: { GOOSE_MODE: "auto" } };
|
|
17
15
|
},
|
|
18
16
|
};
|
package/dist/agents/grok.js
CHANGED
|
@@ -5,16 +5,11 @@ export const grokAgent = {
|
|
|
5
5
|
promptArgs: ["-p"],
|
|
6
6
|
probeArg: "--version",
|
|
7
7
|
authArgs: ["login"],
|
|
8
|
-
supportsYolo: true,
|
|
9
8
|
npmPackage: "@xai-official/grok",
|
|
10
9
|
freeUsage: "Free Tier",
|
|
11
|
-
getTaskRunCommandLine(task, followupPrompt
|
|
12
|
-
const yolo = extraPermissions === "yolo";
|
|
10
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
13
11
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
14
|
-
const args = [];
|
|
15
|
-
if (yolo) {
|
|
16
|
-
args.push("--always-approve");
|
|
17
|
-
}
|
|
12
|
+
const args = ["--always-approve"];
|
|
18
13
|
if (followupPrompt) {
|
|
19
14
|
args.push("-c");
|
|
20
15
|
}
|
package/dist/agents/hermes.js
CHANGED
|
@@ -4,14 +4,9 @@ export const hermesAgent = {
|
|
|
4
4
|
command: "hermes",
|
|
5
5
|
promptArgs: ["chat", "-q"],
|
|
6
6
|
probeArg: "--version",
|
|
7
|
-
|
|
8
|
-
getTaskRunCommandLine(task, followupPrompt, extraPermissions) {
|
|
9
|
-
const yolo = extraPermissions === "yolo";
|
|
7
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
10
8
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
11
|
-
const args = ["chat"];
|
|
12
|
-
if (yolo) {
|
|
13
|
-
args.push("--trust-all-tools");
|
|
14
|
-
}
|
|
9
|
+
const args = ["chat", "--trust-all-tools"];
|
|
15
10
|
if (followupPrompt) {
|
|
16
11
|
args.push("--continue");
|
|
17
12
|
}
|
package/dist/agents/kimi.js
CHANGED
|
@@ -4,19 +4,15 @@ export const kimiAgent = {
|
|
|
4
4
|
command: "kimi",
|
|
5
5
|
promptArgs: ["-p"],
|
|
6
6
|
probeArg: "--version",
|
|
7
|
-
supportsYolo: false,
|
|
8
7
|
suppressStdErr: true,
|
|
9
8
|
npmPackage: "@moonshot-ai/kimi-code",
|
|
10
|
-
getTaskRunCommandLine(task, followupPrompt
|
|
11
|
-
const yolo = extraPermissions === "yolo";
|
|
9
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
12
10
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
13
11
|
const args = [];
|
|
14
|
-
if (yolo) {
|
|
15
|
-
args.push("--yolo");
|
|
16
|
-
}
|
|
17
12
|
if (followupPrompt) {
|
|
18
13
|
args.push("--continue");
|
|
19
14
|
}
|
|
15
|
+
// Print mode (-p) already implies yolo.
|
|
20
16
|
args.push("-p", prompt);
|
|
21
17
|
return { args };
|
|
22
18
|
},
|
package/dist/agents/kiro.js
CHANGED
|
@@ -4,14 +4,9 @@ export const kiroAgent = {
|
|
|
4
4
|
command: "kiro-cli",
|
|
5
5
|
promptArgs: ["--no-interactive"],
|
|
6
6
|
probeArg: "--version",
|
|
7
|
-
|
|
8
|
-
getTaskRunCommandLine(task, followupPrompt, extraPermissions) {
|
|
9
|
-
const yolo = extraPermissions === "yolo";
|
|
7
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
10
8
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
11
|
-
const args = [];
|
|
12
|
-
if (yolo) {
|
|
13
|
-
args.push("--trust-all-tools");
|
|
14
|
-
}
|
|
9
|
+
const args = ["--trust-all-tools"];
|
|
15
10
|
if (followupPrompt) {
|
|
16
11
|
args.push("--resume");
|
|
17
12
|
}
|
package/dist/agents/openclaw.js
CHANGED
|
@@ -5,7 +5,7 @@ export const openClawAgent = {
|
|
|
5
5
|
promptArgs: ["agent", "--local", "--agent", "main", "--message"],
|
|
6
6
|
probeArg: "--version",
|
|
7
7
|
npmPackage: "openclaw",
|
|
8
|
-
getTaskRunCommandLine(task, followupPrompt
|
|
8
|
+
getTaskRunCommandLine(task, followupPrompt) {
|
|
9
9
|
const prompt = followupPrompt ?? getAgentInstructions(task);
|
|
10
10
|
// OpenClaw does not support stdin as prompt.
|
|
11
11
|
const args = ["agent", "--local", "--session-id", task.frontmatter.id, "--message", prompt];
|