pi-landstrip 0.3.0 → 0.3.1
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/index.ts +33 -13
- package/package.json +2 -2
package/index.ts
CHANGED
|
@@ -72,12 +72,11 @@ interface LandstripErrorResponse {
|
|
|
72
72
|
category: 'policy' | 'tool' | 'platform' | 'system';
|
|
73
73
|
file?: string;
|
|
74
74
|
program?: string;
|
|
75
|
-
|
|
76
|
-
kind?: 'launch' | 'encoding';
|
|
75
|
+
type?: 'filesystem' | 'network' | 'platform' | 'launch' | 'encoding';
|
|
77
76
|
message: string;
|
|
78
77
|
}
|
|
79
78
|
|
|
80
|
-
const LANDSTRIP_VERSION = [0, 9,
|
|
79
|
+
const LANDSTRIP_VERSION = [0, 9, 5] as const;
|
|
81
80
|
const SUPPORTED_PLATFORMS = new Set<NodeJS.Platform>(['linux', 'darwin', 'win32']);
|
|
82
81
|
|
|
83
82
|
const DEFAULT_CONFIG: SandboxConfig = {
|
|
@@ -353,6 +352,9 @@ function parseLandstripErrors(output: string): LandstripErrorResponse[] {
|
|
|
353
352
|
parsed !== null &&
|
|
354
353
|
typeof parsed.category === 'string' &&
|
|
355
354
|
['policy', 'tool', 'platform', 'system'].includes(parsed.category) &&
|
|
355
|
+
(parsed.type === undefined ||
|
|
356
|
+
(typeof parsed.type === 'string' &&
|
|
357
|
+
['filesystem', 'network', 'platform', 'launch', 'encoding'].includes(parsed.type))) &&
|
|
356
358
|
typeof parsed.message === 'string' &&
|
|
357
359
|
parsed.message.length > 0
|
|
358
360
|
) {
|
|
@@ -371,14 +373,14 @@ function formatLandstripErrors(errors: LandstripErrorResponse[]): string {
|
|
|
371
373
|
.map((err) => {
|
|
372
374
|
const parts: string[] = [`landstrip: ${err.category}`];
|
|
373
375
|
|
|
374
|
-
if (err.
|
|
375
|
-
parts.push(`(${err.
|
|
376
|
+
if (err.file) {
|
|
377
|
+
parts.push(` (${err.file})`);
|
|
376
378
|
}
|
|
377
379
|
if (err.program) {
|
|
378
380
|
parts.push(` ${err.program}`);
|
|
379
381
|
}
|
|
380
|
-
if (err.
|
|
381
|
-
parts.push(`:${err.
|
|
382
|
+
if (err.type) {
|
|
383
|
+
parts.push(`:${err.type}`);
|
|
382
384
|
}
|
|
383
385
|
parts.push(`: ${err.message}`);
|
|
384
386
|
|
|
@@ -828,7 +830,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
828
830
|
});
|
|
829
831
|
}
|
|
830
832
|
|
|
831
|
-
function createLandstripBashOps(
|
|
833
|
+
function createLandstripBashOps(
|
|
834
|
+
ctx: ExtensionContext,
|
|
835
|
+
onStderr: (data: Buffer) => void = () => {},
|
|
836
|
+
): BashOperations {
|
|
832
837
|
return {
|
|
833
838
|
async exec(command, cwd, { onData, signal, timeout, env }) {
|
|
834
839
|
if (!existsSync(cwd)) throw new Error(`Working directory does not exist: ${cwd}`);
|
|
@@ -881,7 +886,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
881
886
|
|
|
882
887
|
signal?.addEventListener('abort', onAbort, { once: true });
|
|
883
888
|
child.stdout?.on('data', onData);
|
|
884
|
-
child.stderr?.on('data',
|
|
889
|
+
child.stderr?.on('data', (data: Buffer) => {
|
|
890
|
+
onStderr(data);
|
|
891
|
+
onData(data);
|
|
892
|
+
});
|
|
885
893
|
|
|
886
894
|
child.on('error', (error) => {
|
|
887
895
|
cleanup();
|
|
@@ -910,18 +918,30 @@ export default function (pi: ExtensionAPI) {
|
|
|
910
918
|
onUpdate: AgentToolUpdateCallback<BashToolDetails | undefined> | undefined,
|
|
911
919
|
ctx: ExtensionContext,
|
|
912
920
|
): Promise<AgentToolResult<BashToolDetails | undefined>> {
|
|
921
|
+
let landstripStderr = '';
|
|
913
922
|
const sandboxedBash = createBashToolDefinition(localCwd, {
|
|
914
|
-
operations: createLandstripBashOps(ctx)
|
|
923
|
+
operations: createLandstripBashOps(ctx, (data) => {
|
|
924
|
+
landstripStderr += data.toString('utf8');
|
|
925
|
+
}),
|
|
915
926
|
shellPath: userShellPath,
|
|
916
927
|
});
|
|
917
928
|
|
|
918
929
|
const run = () => sandboxedBash.execute(id, params, signal, onUpdate, ctx);
|
|
919
|
-
|
|
930
|
+
let result: AgentToolResult<BashToolDetails | undefined>;
|
|
931
|
+
try {
|
|
932
|
+
result = await run();
|
|
933
|
+
} catch (error) {
|
|
934
|
+
const landstripErrors = parseLandstripErrors(landstripStderr);
|
|
935
|
+
if (landstripErrors.length > 0) {
|
|
936
|
+
throw new Error(formatLandstripErrors(landstripErrors));
|
|
937
|
+
}
|
|
938
|
+
throw error;
|
|
939
|
+
}
|
|
920
940
|
const outputText = result.content
|
|
921
941
|
.filter((content) => content.type === 'text')
|
|
922
942
|
.map((content) => content.text)
|
|
923
943
|
.join('\n');
|
|
924
|
-
const landstripErrors = parseLandstripErrors(
|
|
944
|
+
const landstripErrors = parseLandstripErrors(landstripStderr);
|
|
925
945
|
if (landstripErrors.length > 0) {
|
|
926
946
|
const message = formatLandstripErrors(landstripErrors);
|
|
927
947
|
result.content.unshift({ type: 'text', text: `\n${message}\n` });
|
|
@@ -1010,7 +1030,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1010
1030
|
if (!hasMinimumVersion(version, LANDSTRIP_VERSION)) {
|
|
1011
1031
|
sandboxEnabled = false;
|
|
1012
1032
|
sandboxReady = false;
|
|
1013
|
-
ctx.ui.notify(`landstrip 0.9.
|
|
1033
|
+
ctx.ui.notify(`landstrip 0.9.5 or newer is required; found: ${version}`, 'error');
|
|
1014
1034
|
return false;
|
|
1015
1035
|
}
|
|
1016
1036
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-landstrip",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Landlock-based sandboxing for pi with interactive permission prompts",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"landstrip",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@earendil-works/pi-tui": "^0.78.0",
|
|
33
|
-
"@jarkkojs/landstrip": "^0.9.
|
|
33
|
+
"@jarkkojs/landstrip": "^0.9.5"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@earendil-works/pi-coding-agent": "^0.78.0",
|