opencode-landstrip 0.16.6 → 0.16.8

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.
Files changed (3) hide show
  1. package/index.ts +22 -16
  2. package/package.json +2 -2
  3. package/tui.ts +1 -1
package/index.ts CHANGED
@@ -267,9 +267,10 @@ function extractBlockedPath(
267
267
  }
268
268
  }
269
269
 
270
- // If landstrip reported a trap but without a path, try to
271
- // extract the blocked path from the command itself
272
- if (landstripTraps.length > 0 && command) {
270
+ if (
271
+ landstripTraps.some((trap) => trap.kind === 'filesystem' || trap.kind === 'internal') &&
272
+ command
273
+ ) {
273
274
  for (const candidate of extractCandidatePaths(command)) {
274
275
  const resolved = canonicalizePath(candidate, baseDirectory);
275
276
  return resolved;
@@ -279,14 +280,6 @@ function extractBlockedPath(
279
280
  return null;
280
281
  }
281
282
 
282
- function extractBlockedWritePath(
283
- output: string,
284
- baseDirectory: string,
285
- command?: string,
286
- ): string | null {
287
- return extractBlockedPath(output, baseDirectory, command);
288
- }
289
-
290
283
  function evaluateReadPermission(
291
284
  path: string,
292
285
  config: SandboxConfig,
@@ -652,6 +645,15 @@ function socketQueryPort(baseDirectory: string): number | null {
652
645
  return readDiscoveryPort(baseDirectory);
653
646
  }
654
647
 
648
+ async function awaitQueryPort(baseDirectory: string): Promise<number | null> {
649
+ for (let attempt = 0; attempt < 5; attempt++) {
650
+ const port = socketQueryPort(baseDirectory);
651
+ if (port !== null) return port;
652
+ await new Promise((resolve) => setTimeout(resolve, 50));
653
+ }
654
+ return null;
655
+ }
656
+
655
657
  function buildWrappedCommand(
656
658
  policyPath: string,
657
659
  shell: string,
@@ -1062,7 +1064,7 @@ const plugin: Plugin = async ({ client, directory }: PluginInput, options?: Plug
1062
1064
  policy.path,
1063
1065
  configuredShell ?? process.env.SHELL ?? '/bin/sh',
1064
1066
  originalCommand,
1065
- socketQueryPort(directory),
1067
+ await awaitQueryPort(directory),
1066
1068
  );
1067
1069
 
1068
1070
  activeBash.set(callID, {
@@ -1239,7 +1241,7 @@ const plugin: Plugin = async ({ client, directory }: PluginInput, options?: Plug
1239
1241
  ?.catch?.(() => undefined);
1240
1242
  }
1241
1243
 
1242
- const blockedPath = extractBlockedWritePath(outputText, directory, state.originalCommand);
1244
+ const blockedPath = extractBlockedPath(outputText, directory, state.originalCommand);
1243
1245
  if (blockedPath) {
1244
1246
  await notifyOnce(
1245
1247
  `blocked:${blockedPath}`,
@@ -1252,7 +1254,11 @@ const plugin: Plugin = async ({ client, directory }: PluginInput, options?: Plug
1252
1254
  },
1253
1255
 
1254
1256
  'command.execute.before': async (input, output) => {
1255
- if (input.command.trim() === '/sandbox') {
1257
+ // OpenCode strips the leading slash before dispatching commands, so the
1258
+ // hook receives the bare name ("sandbox"); accept both forms so the
1259
+ // handler matches whether invoked by name or via tui.executeCommand.
1260
+ const command = input.command.trim().replace(/^\//, '');
1261
+ if (command === 'sandbox') {
1256
1262
  const config = loadConfig(directory, optionOverrides);
1257
1263
  pushCommandText(input, output, buildSandboxSummary(config));
1258
1264
  await client.tui
@@ -1263,7 +1269,7 @@ const plugin: Plugin = async ({ client, directory }: PluginInput, options?: Plug
1263
1269
  return;
1264
1270
  }
1265
1271
 
1266
- if (input.command.trim() === '/sandbox-disable') {
1272
+ if (command === 'sandbox-disable') {
1267
1273
  if (sandboxDisabled) {
1268
1274
  pushCommandText(
1269
1275
  input,
@@ -1290,7 +1296,7 @@ const plugin: Plugin = async ({ client, directory }: PluginInput, options?: Plug
1290
1296
  return;
1291
1297
  }
1292
1298
 
1293
- if (input.command.trim() === '/sandbox-enable') {
1299
+ if (command === 'sandbox-enable') {
1294
1300
  if (!sandboxDisabled) {
1295
1301
  pushCommandText(
1296
1302
  input,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-landstrip",
3
- "version": "0.16.6",
3
+ "version": "0.16.8",
4
4
  "description": "Landlock-based sandboxing for opencode with landstrip",
5
5
  "keywords": [
6
6
  "landlock",
@@ -49,7 +49,7 @@
49
49
  "ci:test": "npm test"
50
50
  },
51
51
  "dependencies": {
52
- "@landstrip/landstrip": "^0.16.8"
52
+ "@landstrip/landstrip": "^0.16.11"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@opencode-ai/plugin": "^1.17.7",
package/tui.ts CHANGED
@@ -593,4 +593,4 @@ const tui: TuiPlugin = async (api, options, meta) => {
593
593
  };
594
594
 
595
595
  export { tui };
596
- export default { tui };
596
+ export default { id: 'opencode-landstrip', tui };