opencode-landstrip 0.2.2 → 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 +56 -8
- package/package.json +13 -5
- package/tui.ts +20 -0
package/index.ts
CHANGED
|
@@ -54,8 +54,7 @@ interface LandstripErrorResponse {
|
|
|
54
54
|
category: 'policy' | 'tool' | 'platform' | 'system';
|
|
55
55
|
file?: string;
|
|
56
56
|
program?: string;
|
|
57
|
-
|
|
58
|
-
kind?: 'launch' | 'encoding';
|
|
57
|
+
type?: 'filesystem' | 'network' | 'platform' | 'launch' | 'encoding';
|
|
59
58
|
message: string;
|
|
60
59
|
}
|
|
61
60
|
|
|
@@ -75,7 +74,7 @@ interface BashSandboxState {
|
|
|
75
74
|
|
|
76
75
|
type ToastVariant = 'info' | 'success' | 'warning' | 'error';
|
|
77
76
|
|
|
78
|
-
const LANDSTRIP_VERSION = [0,
|
|
77
|
+
const LANDSTRIP_VERSION = [0, 10, 1] as const;
|
|
79
78
|
const SUPPORTED_PLATFORMS = new Set<NodeJS.Platform>(['linux', 'darwin', 'win32']);
|
|
80
79
|
|
|
81
80
|
const DEFAULT_CONFIG: SandboxConfig = {
|
|
@@ -384,6 +383,9 @@ function parseLandstripErrors(output: string): LandstripErrorResponse[] {
|
|
|
384
383
|
parsed !== null &&
|
|
385
384
|
typeof parsed.category === 'string' &&
|
|
386
385
|
['policy', 'tool', 'platform', 'system'].includes(parsed.category) &&
|
|
386
|
+
(parsed.type === undefined ||
|
|
387
|
+
(typeof parsed.type === 'string' &&
|
|
388
|
+
['filesystem', 'network', 'platform', 'launch', 'encoding'].includes(parsed.type))) &&
|
|
387
389
|
typeof parsed.message === 'string' &&
|
|
388
390
|
parsed.message.length > 0
|
|
389
391
|
) {
|
|
@@ -402,14 +404,14 @@ function formatLandstripErrors(errors: LandstripErrorResponse[]): string {
|
|
|
402
404
|
.map((err) => {
|
|
403
405
|
const parts: string[] = [`landstrip: ${err.category}`];
|
|
404
406
|
|
|
405
|
-
if (err.
|
|
406
|
-
parts.push(`(${err.
|
|
407
|
+
if (err.file) {
|
|
408
|
+
parts.push(` (${err.file})`);
|
|
407
409
|
}
|
|
408
410
|
if (err.program) {
|
|
409
411
|
parts.push(` ${err.program}`);
|
|
410
412
|
}
|
|
411
|
-
if (err.
|
|
412
|
-
parts.push(`:${err.
|
|
413
|
+
if (err.type) {
|
|
414
|
+
parts.push(`:${err.type}`);
|
|
413
415
|
}
|
|
414
416
|
parts.push(`: ${err.message}`);
|
|
415
417
|
|
|
@@ -777,7 +779,7 @@ export default (async ({ client, directory }: PluginInput, options?: PluginOptio
|
|
|
777
779
|
if (!hasMinimumVersion(version, LANDSTRIP_VERSION)) {
|
|
778
780
|
landstripCheck = {
|
|
779
781
|
ok: false,
|
|
780
|
-
reason: `landstrip 0.
|
|
782
|
+
reason: `landstrip 0.10.1 or newer is required; found: ${version}`,
|
|
781
783
|
};
|
|
782
784
|
return landstripCheck;
|
|
783
785
|
}
|
|
@@ -898,6 +900,38 @@ export default (async ({ client, directory }: PluginInput, options?: PluginOptio
|
|
|
898
900
|
args.description = landstripDescription(args.description);
|
|
899
901
|
}
|
|
900
902
|
|
|
903
|
+
function buildConfigSummary(config: SandboxConfig): string {
|
|
904
|
+
const { globalPath, projectPath } = getConfigPaths(directory);
|
|
905
|
+
const check = checkLandstrip();
|
|
906
|
+
const version = check?.ok === true ? check.version : 'unknown';
|
|
907
|
+
const status = config.enabled && check?.ok === true ? 'enabled' : 'disabled';
|
|
908
|
+
|
|
909
|
+
const lines = [
|
|
910
|
+
'Sandbox Configuration',
|
|
911
|
+
` Status: ${status}`,
|
|
912
|
+
` Project config: ${projectPath}`,
|
|
913
|
+
` Global config: ${globalPath}`,
|
|
914
|
+
` landstrip: ${binaryPath()} (v${version})`,
|
|
915
|
+
'',
|
|
916
|
+
'Network (bash commands go through HTTP proxy):',
|
|
917
|
+
` Allow local binding: ${config.network.allowLocalBinding}`,
|
|
918
|
+
` Allow all Unix sockets: ${config.network.allowAllUnixSockets}`,
|
|
919
|
+
...(config.network.allowUnixSockets.length > 0
|
|
920
|
+
? [` Allow Unix sockets: ${config.network.allowUnixSockets.join(', ')}`]
|
|
921
|
+
: []),
|
|
922
|
+
` Allowed domains: ${config.network.allowedDomains.join(', ') || '(none)'}`,
|
|
923
|
+
` Denied domains: ${config.network.deniedDomains.join(', ') || '(none)'}`,
|
|
924
|
+
'',
|
|
925
|
+
'Filesystem (bash + read/write/edit tools):',
|
|
926
|
+
` Deny Read: ${config.filesystem.denyRead.join(', ') || '(none)'}`,
|
|
927
|
+
` Allow Read: ${config.filesystem.allowRead.join(', ') || '(none)'}`,
|
|
928
|
+
` Allow Write: ${config.filesystem.allowWrite.join(', ') || '(none)'}`,
|
|
929
|
+
` Deny Write: ${config.filesystem.denyWrite.join(', ') || '(none)'}`,
|
|
930
|
+
];
|
|
931
|
+
|
|
932
|
+
return lines.join('\n');
|
|
933
|
+
}
|
|
934
|
+
|
|
901
935
|
const hooks: Hooks = {
|
|
902
936
|
config: async (config) => {
|
|
903
937
|
configuredShell = configuredShellPath(config);
|
|
@@ -972,6 +1006,20 @@ export default (async ({ client, directory }: PluginInput, options?: PluginOptio
|
|
|
972
1006
|
await cleanupBash(input.callID);
|
|
973
1007
|
},
|
|
974
1008
|
|
|
1009
|
+
'command.execute.before': async (input, output) => {
|
|
1010
|
+
if (input.command !== 'sandbox') return;
|
|
1011
|
+
|
|
1012
|
+
const config = loadConfig(directory, optionOverrides);
|
|
1013
|
+
const summary = buildConfigSummary(config);
|
|
1014
|
+
output.parts.unshift({
|
|
1015
|
+
id: `landstrip-sandbox-${Date.now()}`,
|
|
1016
|
+
sessionID: input.sessionID,
|
|
1017
|
+
messageID: input.sessionID,
|
|
1018
|
+
type: 'text',
|
|
1019
|
+
text: `\n${summary}\n`,
|
|
1020
|
+
});
|
|
1021
|
+
},
|
|
1022
|
+
|
|
975
1023
|
dispose: async () => {
|
|
976
1024
|
await Promise.all([...activeBash.keys()].map((callID) => cleanupBash(callID)));
|
|
977
1025
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-landstrip",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Landlock-based sandboxing for opencode with landstrip",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"landlock",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"index.ts",
|
|
18
|
+
"tui.ts",
|
|
18
19
|
"README.md",
|
|
19
20
|
"sandbox.json"
|
|
20
21
|
],
|
|
@@ -28,24 +29,31 @@
|
|
|
28
29
|
"./server": {
|
|
29
30
|
"import": "./index.ts",
|
|
30
31
|
"types": "./index.ts"
|
|
32
|
+
},
|
|
33
|
+
"./tui": {
|
|
34
|
+
"import": "./tui.ts",
|
|
35
|
+
"types": "./tui.ts"
|
|
31
36
|
}
|
|
32
37
|
},
|
|
33
38
|
"scripts": {
|
|
34
|
-
"fmt": "oxfmt index.ts package.json tsconfig.json sandbox.json .oxfmtrc.json README.md test/*.test.mjs",
|
|
35
|
-
"lint": "oxlint index.ts",
|
|
39
|
+
"fmt": "oxfmt index.ts tui.ts package.json tsconfig.json sandbox.json .oxfmtrc.json README.md test/*.test.mjs",
|
|
40
|
+
"lint": "oxlint index.ts tui.ts",
|
|
36
41
|
"check": "tsc --noEmit",
|
|
37
42
|
"test": "node --test test/*.test.mjs",
|
|
38
43
|
"all": "npm run fmt && npm run lint && npm run check && npm test",
|
|
39
|
-
"ci:fmt": "oxfmt --check index.ts package.json tsconfig.json sandbox.json .oxfmtrc.json README.md test/*.test.mjs",
|
|
44
|
+
"ci:fmt": "oxfmt --check index.ts tui.ts package.json tsconfig.json sandbox.json .oxfmtrc.json README.md test/*.test.mjs",
|
|
40
45
|
"ci:lint": "npm run lint",
|
|
41
46
|
"ci:check": "npm run check",
|
|
42
47
|
"ci:test": "npm test"
|
|
43
48
|
},
|
|
44
49
|
"dependencies": {
|
|
45
|
-
"@jarkkojs/landstrip": "^0.
|
|
50
|
+
"@jarkkojs/landstrip": "^0.10.1"
|
|
46
51
|
},
|
|
47
52
|
"devDependencies": {
|
|
48
53
|
"@opencode-ai/plugin": "^1.16.2",
|
|
54
|
+
"@opentui/core": ">=0.3.2",
|
|
55
|
+
"@opentui/keymap": ">=0.3.2",
|
|
56
|
+
"@opentui/solid": ">=0.3.2",
|
|
49
57
|
"@types/node": "^24.0.0",
|
|
50
58
|
"oxfmt": "^0.53.0",
|
|
51
59
|
"oxlint": "^1.68.0",
|
package/tui.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (C) Jarkko Sakkinen 2026
|
|
3
|
+
|
|
4
|
+
import type { TuiPlugin } from '@opencode-ai/plugin/tui';
|
|
5
|
+
|
|
6
|
+
const tui: TuiPlugin = async (api) => {
|
|
7
|
+
api.command?.register(() => [
|
|
8
|
+
{
|
|
9
|
+
title: 'Sandbox',
|
|
10
|
+
value: 'sandbox',
|
|
11
|
+
description: 'Show sandbox configuration',
|
|
12
|
+
category: 'plugin',
|
|
13
|
+
slash: {
|
|
14
|
+
name: 'sandbox',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
]);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default tui;
|