@iinm/plain-agent 1.10.24 → 1.10.25
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 +54 -36
- package/package.json +1 -1
- package/src/cli/interactive.mjs +2 -0
- package/src/main.mjs +1 -0
package/README.md
CHANGED
|
@@ -72,7 +72,7 @@ String values in tool inputs are treated as file paths and validated against the
|
|
|
72
72
|
- No directory traversal (`..` is not allowed)
|
|
73
73
|
- The file must be tracked by Git (not ignored)
|
|
74
74
|
|
|
75
|
-
**Note**: validation only applies when the agent explicitly passes file paths to tools. It cannot catch file access inside scripts the agent writes — something like `bash -c "rm -rf /"` is beyond its reach. Always use a sandbox when
|
|
75
|
+
**Note**: validation only applies when the agent explicitly passes file paths to tools. It cannot catch file access inside scripts the agent writes — something like `bash -c "rm -rf /"` is beyond its reach. Always use a sandbox when auto-approving script execution.
|
|
76
76
|
|
|
77
77
|
### Sandbox
|
|
78
78
|
|
|
@@ -81,11 +81,12 @@ A Docker-based wrapper called `plain-sandbox` is included, but the interface is
|
|
|
81
81
|
|
|
82
82
|
```js
|
|
83
83
|
{
|
|
84
|
-
// Sandbox environment for the exec_command and tmux_command tools
|
|
85
84
|
"sandbox": {
|
|
86
85
|
// Commands are wrapped and executed with this command
|
|
86
|
+
// Build the image before first use: plain-sandbox --verbose echo done
|
|
87
87
|
"command": "plain-sandbox",
|
|
88
|
-
"args": ["--allow-write", "--skip-build", "--keep-alive", "30"],
|
|
88
|
+
"args": ["--allow-write", "--mount-readonly", ".plain-agent/config.json", "--skip-build", "--keep-alive", "30"],
|
|
89
|
+
// ↑ --mount-readonly: prevents the agent from overwriting its own config
|
|
89
90
|
// separator is inserted between sandbox flags and the user command to prevent bypasses
|
|
90
91
|
"separator": "--",
|
|
91
92
|
|
|
@@ -117,7 +118,6 @@ A few design choices keep token usage low:
|
|
|
117
118
|
|
|
118
119
|
- Minimal system prompt — the [system prompt](https://github.com/iinm/plain-agent/blob/main/src/prompt.mjs) contains only what the agent needs to function.
|
|
119
120
|
- Output truncation — when a command or MCP tool produces large output, it is truncated and saved to a file. The agent can then read only the relevant parts.
|
|
120
|
-
- (Experimental) [Hashline-based](https://blog.can.ac/2026/02/12/the-harness-problem/) patch_file tool.
|
|
121
121
|
|
|
122
122
|
### Claude Code Compatibility
|
|
123
123
|
|
|
@@ -457,6 +457,31 @@ Files are loaded in the following order. Settings in later files override earlie
|
|
|
457
457
|
└── agents/ # Project-specific agent roles
|
|
458
458
|
```
|
|
459
459
|
|
|
460
|
+
|
|
461
|
+
<details>
|
|
462
|
+
<summary><b>Minimal example (file editing and web search only — no script execution, no sandbox required)</b></summary>
|
|
463
|
+
|
|
464
|
+
```js
|
|
465
|
+
{
|
|
466
|
+
"autoApproval": {
|
|
467
|
+
"defaultAction": "ask",
|
|
468
|
+
"maxApprovals": 100,
|
|
469
|
+
"patterns": [
|
|
470
|
+
{
|
|
471
|
+
"toolName": { "$regex": "^(write_file|patch_file)$" },
|
|
472
|
+
"action": "allow"
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
"toolName": { "$regex": "^(web_search|web_fetch)$" },
|
|
476
|
+
"action": "allow"
|
|
477
|
+
}
|
|
478
|
+
]
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
</details>
|
|
484
|
+
|
|
460
485
|
<details>
|
|
461
486
|
<summary><b>YOLO mode example (requires a sandbox for safety)</b></summary>
|
|
462
487
|
|
|
@@ -472,11 +497,11 @@ Files are loaded in the following order. Settings in later files override earlie
|
|
|
472
497
|
"action": "allow"
|
|
473
498
|
},
|
|
474
499
|
{
|
|
475
|
-
"toolName": "
|
|
500
|
+
"toolName": { "$regex": "^(web_search|web_fetch)$" },
|
|
476
501
|
"action": "allow"
|
|
477
502
|
},
|
|
478
503
|
{
|
|
479
|
-
"toolName":
|
|
504
|
+
"toolName": "exec_command",
|
|
480
505
|
"action": "allow"
|
|
481
506
|
}
|
|
482
507
|
// ⚠️ Never do this. MCP runs outside the sandbox, so it can send anything externally.
|
|
@@ -487,8 +512,10 @@ Files are loaded in the following order. Settings in later files override earlie
|
|
|
487
512
|
]
|
|
488
513
|
},
|
|
489
514
|
"sandbox": {
|
|
515
|
+
// ⚠️ Build the image before first use: plain-sandbox --verbose echo done
|
|
490
516
|
"command": "plain-sandbox",
|
|
491
|
-
"args": ["--allow-write", "--skip-build", "--keep-alive", "30"],
|
|
517
|
+
"args": ["--allow-write", "--mount-readonly", ".plain-agent/config.json", "--skip-build", "--keep-alive", "30"],
|
|
518
|
+
// ↑ --mount-readonly: prevents the agent from overwriting its own config
|
|
492
519
|
"separator": "--"
|
|
493
520
|
}
|
|
494
521
|
}
|
|
@@ -518,7 +545,7 @@ Files are loaded in the following order. Settings in later files override earlie
|
|
|
518
545
|
"action": "allow"
|
|
519
546
|
},
|
|
520
547
|
|
|
521
|
-
// ⚠️
|
|
548
|
+
// ⚠️ When auto-approving execution, scripts can access unauthorized files and networks. Always use a sandbox.
|
|
522
549
|
{
|
|
523
550
|
"toolName": "exec_command",
|
|
524
551
|
"input": { "command": "npm", "args": ["run", { "$regex": "^(lint|test)$" }] },
|
|
@@ -549,8 +576,10 @@ Files are loaded in the following order. Settings in later files override earlie
|
|
|
549
576
|
// Sandbox environment for the exec_command and tmux_command tools
|
|
550
577
|
"sandbox": {
|
|
551
578
|
// Commands are wrapped and executed with this command
|
|
579
|
+
// Build the image before first use: plain-sandbox --verbose echo done
|
|
552
580
|
"command": "plain-sandbox",
|
|
553
|
-
"args": ["--allow-write", "--skip-build", "--keep-alive", "30"],
|
|
581
|
+
"args": ["--allow-write", "--mount-readonly", ".plain-agent/config.json", "--skip-build", "--keep-alive", "30"],
|
|
582
|
+
// ↑ --mount-readonly: prevents the agent from overwriting its own config
|
|
554
583
|
// separator is inserted between sandbox flags and the user command to prevent bypasses
|
|
555
584
|
"separator": "--",
|
|
556
585
|
|
|
@@ -749,33 +778,6 @@ Press **Ctrl-O** to start recording, then press it again to stop. Partial transc
|
|
|
749
778
|
is a letter (a-z) or one of `[ \ ] ^ _`. Defaults to `"ctrl-o"`.
|
|
750
779
|
- `recorder` — Override automatic recorder detection, e.g. `{ "command": "sox", "args": ["-q", "-d", "-b", "16", "-c", "1", "-r", "24000", "-e", "signed-integer", "-t", "raw", "-"] }`. It must write raw 16-bit little-endian mono PCM to stdout at 24 kHz (OpenAI) or 16 kHz (Gemini).
|
|
751
780
|
|
|
752
|
-
## Development
|
|
753
|
-
|
|
754
|
-
```sh
|
|
755
|
-
# Run lint, typecheck, and tests
|
|
756
|
-
npm run check
|
|
757
|
-
|
|
758
|
-
# Fix lint issues
|
|
759
|
-
npm run fix
|
|
760
|
-
# or
|
|
761
|
-
npm run fix -- --unsafe
|
|
762
|
-
|
|
763
|
-
# Update dependencies
|
|
764
|
-
npx npm-check-updates -t minor -c 3
|
|
765
|
-
npx npm-check-updates -t minor -c 3 -u
|
|
766
|
-
```
|
|
767
|
-
|
|
768
|
-
## Release
|
|
769
|
-
|
|
770
|
-
```sh
|
|
771
|
-
npm version <major|minor|patch>
|
|
772
|
-
|
|
773
|
-
git push --follow-tags
|
|
774
|
-
gh release create $(git describe --tags) --generate-notes
|
|
775
|
-
|
|
776
|
-
npm publish --access public
|
|
777
|
-
```
|
|
778
|
-
|
|
779
781
|
## Appendix: Creating Least-Privilege Users for Cloud Providers
|
|
780
782
|
|
|
781
783
|
<details>
|
|
@@ -921,3 +923,19 @@ gcloud iam service-accounts add-iam-policy-binding "$service_account_email" \
|
|
|
921
923
|
gcloud auth print-access-token --impersonate-service-account "$service_account_email"
|
|
922
924
|
```
|
|
923
925
|
</details>
|
|
926
|
+
|
|
927
|
+
## Developer Notes
|
|
928
|
+
|
|
929
|
+
<details>
|
|
930
|
+
<summary>Release</summary>
|
|
931
|
+
|
|
932
|
+
```sh
|
|
933
|
+
npm version <major|minor|patch>
|
|
934
|
+
|
|
935
|
+
git push --follow-tags
|
|
936
|
+
gh release create $(git describe --tags) --generate-notes
|
|
937
|
+
|
|
938
|
+
npm publish --access public
|
|
939
|
+
```
|
|
940
|
+
</details>
|
|
941
|
+
|
package/package.json
CHANGED
package/src/cli/interactive.mjs
CHANGED
|
@@ -391,6 +391,8 @@ export function startInteractiveSession({
|
|
|
391
391
|
|
|
392
392
|
// Handle readline close (e.g., stdin closed externally)
|
|
393
393
|
cli.on("close", handleExit);
|
|
394
|
+
process.on("SIGTERM", handleExit);
|
|
395
|
+
process.on("SIGHUP", handleExit);
|
|
394
396
|
|
|
395
397
|
const handleCommand = createCommandHandler({
|
|
396
398
|
agentCommands,
|
package/src/main.mjs
CHANGED
|
@@ -165,6 +165,7 @@ export async function main(argv = process.argv) {
|
|
|
165
165
|
const sandboxStr = [
|
|
166
166
|
appConfig.sandbox.command,
|
|
167
167
|
...(appConfig.sandbox.args || []),
|
|
168
|
+
...(appConfig.sandbox.separator ? [appConfig.sandbox.separator] : []),
|
|
168
169
|
].join(" ");
|
|
169
170
|
console.log(styleText("green", "\n📦 Sandbox: on"));
|
|
170
171
|
console.log(` ⤷ ${sandboxStr}`);
|