@pi-archimedes/sudo 2.10.3 → 2.11.0
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/package.json +6 -6
- package/src/tool-declarations.test.ts +39 -0
- package/src/tool.ts +10 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-archimedes/sudo",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/danielcherubini/pi-archimedes.git"
|
|
@@ -19,16 +19,16 @@
|
|
|
19
19
|
"./guard": "./src/guard.ts"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@pi-archimedes/core": "2.
|
|
22
|
+
"@pi-archimedes/core": "2.11.0"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@earendil-works/pi-coding-agent": ">=0.
|
|
26
|
-
"@earendil-works/pi-tui": ">=0.
|
|
25
|
+
"@earendil-works/pi-coding-agent": ">=0.99.0",
|
|
26
|
+
"@earendil-works/pi-tui": ">=0.99.0",
|
|
27
27
|
"typebox": ">=1.1.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@earendil-works/pi-coding-agent": "
|
|
31
|
-
"@earendil-works/pi-tui": "
|
|
30
|
+
"@earendil-works/pi-coding-agent": "1.2.0",
|
|
31
|
+
"@earendil-works/pi-tui": "1.2.0",
|
|
32
32
|
"typebox": "^1.1.38",
|
|
33
33
|
"typescript": "^6.0.0"
|
|
34
34
|
},
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task 11 item 3 — what pi's callers are told about `sudo_exec`.
|
|
3
|
+
*
|
|
4
|
+
* `annotations` are author-declared hints with MCP's meaning, and pi documents
|
|
5
|
+
* them as unverified — the input for a permission gate that decides which calls
|
|
6
|
+
* to confirm, not a guarantee (`pi: dist/core/extensions/types.d.ts`,
|
|
7
|
+
* `ToolAnnotations`). So this test pins the declaration, nothing more: `sudo_exec`
|
|
8
|
+
* runs arbitrary privileged commands, so it is destructive and not read-only.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, it, expect } from "vitest";
|
|
12
|
+
import { createSudoExecTool } from "./tool.js";
|
|
13
|
+
|
|
14
|
+
const tool = createSudoExecTool() as unknown as {
|
|
15
|
+
name: string;
|
|
16
|
+
annotations?: { readOnlyHint?: boolean; destructiveHint?: boolean; idempotentHint?: boolean; openWorldHint?: boolean };
|
|
17
|
+
exposure?: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
describe("sudo_exec annotations", () => {
|
|
21
|
+
it("says it is destructive", () => {
|
|
22
|
+
expect(tool.annotations?.destructiveHint).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("says it is not read-only", () => {
|
|
26
|
+
expect(tool.annotations?.readOnlyHint).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("leaves the hints it has not earned undeclared", () => {
|
|
30
|
+
// idempotentHint would be a lie — a second `sudo rm` is not a no-op — and
|
|
31
|
+
// openWorldHint belongs to the tools that reach the web, not this one.
|
|
32
|
+
expect(tool.annotations?.idempotentHint).toBeUndefined();
|
|
33
|
+
expect(tool.annotations?.openWorldHint).toBeUndefined();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("stays reachable by default (direct exposure, active on registration)", () => {
|
|
37
|
+
expect(tool.exposure ?? "direct").toBe("direct");
|
|
38
|
+
});
|
|
39
|
+
});
|
package/src/tool.ts
CHANGED
|
@@ -385,6 +385,16 @@ export function createSudoExecTool(options: {
|
|
|
385
385
|
label: "sudo",
|
|
386
386
|
description: SUDO_EXEC_DESCRIPTION,
|
|
387
387
|
parameters: SudoExecParamsSchema,
|
|
388
|
+
/**
|
|
389
|
+
* Author-declared hints with MCP's meaning, which pi passes to whatever a
|
|
390
|
+
* permission extension does with them and documents as unverified
|
|
391
|
+
* (`pi: dist/core/extensions/types.d.ts`, `ToolAnnotations`). This one is
|
|
392
|
+
* worth declaring: the tool runs an arbitrary command as root, so it may
|
|
393
|
+
* overwrite or delete rather than only add, and it is not read-only. The
|
|
394
|
+
* confirmation this package does in its own handler is unchanged — a hint
|
|
395
|
+
* is not a gate.
|
|
396
|
+
*/
|
|
397
|
+
annotations: { destructiveHint: true, readOnlyHint: false },
|
|
388
398
|
|
|
389
399
|
// NOTE: no return-type annotation on execute — pi reads `isError` at
|
|
390
400
|
// runtime though AgentToolResult omits it; the inferred union escapes
|