opencode-immune 1.0.76 → 1.0.77

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.
@@ -3777,7 +3777,7 @@ import { fileURLToPath } from "url";
3777
3777
  import { createHash } from "crypto";
3778
3778
  import { tmpdir } from "os";
3779
3779
  import { execFile } from "child_process";
3780
- var PLUGIN_VERSION = "1.0.76";
3780
+ var PLUGIN_VERSION = "1.0.77";
3781
3781
  var PLUGIN_PACKAGE_NAME = "opencode-immune";
3782
3782
  var PLUGIN_DIRNAME = dirname(fileURLToPath(import.meta.url));
3783
3783
  function getServerAuthHeaders() {
@@ -3852,7 +3852,6 @@ function createState(input) {
3852
3852
  providerRetryWatchdogs: /* @__PURE__ */ new Map(),
3853
3853
  childFallbackRequests: /* @__PURE__ */ new Map(),
3854
3854
  sessionErrorRetryCount: /* @__PURE__ */ new Map(),
3855
- ultraworkPermissionSessions: /* @__PURE__ */ new Set(),
3856
3855
  fallbackAgentByAgent: /* @__PURE__ */ new Map(),
3857
3856
  baseAgentByFallbackAgent: /* @__PURE__ */ new Map(),
3858
3857
  fallbackModelCandidates: [],
@@ -3889,23 +3888,6 @@ function createState(input) {
3889
3888
  };
3890
3889
  }
3891
3890
  var ULTRAWORK_AGENT = "0-ultrawork";
3892
- var ULTRAWORK_SESSION_PERMISSION = [
3893
- { permission: "read", pattern: "*", action: "allow" },
3894
- { permission: "edit", pattern: "*", action: "allow" },
3895
- { permission: "glob", pattern: "*", action: "allow" },
3896
- { permission: "grep", pattern: "*", action: "allow" },
3897
- { permission: "list", pattern: "*", action: "allow" },
3898
- { permission: "bash", pattern: "*", action: "allow" },
3899
- { permission: "task", pattern: "*", action: "allow" },
3900
- { permission: "external_directory", pattern: "*", action: "allow" },
3901
- { permission: "todowrite", pattern: "*", action: "allow" },
3902
- { permission: "question", pattern: "*", action: "allow" },
3903
- { permission: "webfetch", pattern: "*", action: "allow" },
3904
- { permission: "websearch", pattern: "*", action: "allow" },
3905
- { permission: "codesearch", pattern: "*", action: "allow" },
3906
- { permission: "lsp", pattern: "*", action: "allow" },
3907
- { permission: "skill", pattern: "*", action: "allow" }
3908
- ];
3909
3891
  var DIAGNOSTIC_LOG_MAX_BYTES = 5 * 1024 * 1024;
3910
3892
  var activeLogDirectory = null;
3911
3893
  var MANAGED_SESSION_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
@@ -3913,6 +3895,8 @@ var PROVIDER_RETRY_WATCHDOG_MS = 3e4;
3913
3895
  var RETRY_PROMPT_DELIVERY_ATTEMPTS = 3;
3914
3896
  var CHILD_FALLBACK_REQUEST_TTL_MS = 10 * 60 * 1e3;
3915
3897
  var AUTO_CYCLE_LOCK_TTL_MS = 30 * 60 * 1e3;
3898
+ var PROJECT_TMP_RELATIVE_PATH = ".opencode/tmp";
3899
+ var PROJECT_LOG_RELATIVE_PATH = ".opencode/state/logs";
3916
3900
  var MODEL_NAME_CAPABILITY_SCORE = {
3917
3901
  "claude-opus-4-7": 100,
3918
3902
  "gpt-5.5": 100,
@@ -3932,11 +3916,16 @@ function isManagedRootUltraworkSession(state, sessionID) {
3932
3916
  const record = getManagedSession(state, sessionID);
3933
3917
  return !!record && record.kind === "root";
3934
3918
  }
3919
+ function getProjectTmpDir(state) {
3920
+ return join(state.input.directory, PROJECT_TMP_RELATIVE_PATH);
3921
+ }
3922
+ function getProjectLogDir(state) {
3923
+ return join(state.input.directory, PROJECT_LOG_RELATIVE_PATH);
3924
+ }
3935
3925
  async function createManagedUltraworkSession(state, title) {
3936
3926
  const result = await state.client.session.create({
3937
3927
  directory: state.input.directory,
3938
- title,
3939
- permission: ULTRAWORK_SESSION_PERMISSION
3928
+ title
3940
3929
  });
3941
3930
  if (result.error || !result.response.ok) {
3942
3931
  throw new Error(
@@ -3984,31 +3973,7 @@ async function startAutoCycleInNewSession(state, options) {
3984
3973
  state.autoResumeInFlight = false;
3985
3974
  }
3986
3975
  }
3987
- async function applyUltraworkSessionPermissions(state, sessionID) {
3988
- if (state.ultraworkPermissionSessions.has(sessionID)) return;
3989
- try {
3990
- const result = await state.client.session.update({
3991
- directory: state.input.directory,
3992
- sessionID,
3993
- permission: ULTRAWORK_SESSION_PERMISSION
3994
- });
3995
- if (result.error || !result.response.ok) {
3996
- pluginLog.warn(
3997
- `[opencode-immune] Failed to apply ultrawork permissions to session ${sessionID}:`,
3998
- result.error ?? result.response.status
3999
- );
4000
- return;
4001
- }
4002
- state.ultraworkPermissionSessions.add(sessionID);
4003
- } catch (err) {
4004
- pluginLog.warn(
4005
- `[opencode-immune] Failed to apply ultrawork permissions to session ${sessionID}:`,
4006
- err
4007
- );
4008
- }
4009
- }
4010
3976
  async function promptManagedSession(state, sessionID, text, options = {}) {
4011
- await applyUltraworkSessionPermissions(state, sessionID);
4012
3977
  const result = await state.client.session.promptAsync({
4013
3978
  directory: state.input.directory,
4014
3979
  sessionID,
@@ -4149,7 +4114,6 @@ async function addManagedUltraworkSession(state, sessionID, timestamp = Date.now
4149
4114
  return;
4150
4115
  }
4151
4116
  state.managedUltraworkSessions.set(sessionID, nextRecord);
4152
- await applyUltraworkSessionPermissions(state, sessionID);
4153
4117
  }
4154
4118
  async function addManagedChildSession(state, sessionID, parentSessionID, timestamp = Date.now()) {
4155
4119
  const parent = state.managedUltraworkSessions.get(parentSessionID);
@@ -4202,7 +4166,6 @@ async function removeManagedUltraworkSession(state, sessionID, reason) {
4202
4166
  cancelPendingSessionRetry(state, sessionID, reason);
4203
4167
  cancelProviderRetryWatchdog(state, sessionID, reason);
4204
4168
  state.sessionErrorRetryCount.delete(sessionID);
4205
- state.ultraworkPermissionSessions.delete(sessionID);
4206
4169
  const existed = state.managedUltraworkSessions.delete(sessionID);
4207
4170
  if (!existed) return;
4208
4171
  writePluginLog(
@@ -6083,17 +6046,59 @@ function createPermissionAskHandler(state) {
6083
6046
  state.recoveryContext = recovery;
6084
6047
  await addManagedUltraworkSession(state, sessionID);
6085
6048
  pluginLog.info(
6086
- `[opencode-immune] Permission request recovered AUTO-RESUME session ${sessionID}; applying managed ultrawork auto-allow.`
6049
+ `[opencode-immune] Permission request recovered AUTO-RESUME session ${sessionID}; tracking as managed ultrawork session.`
6087
6050
  );
6088
6051
  }
6089
- output.status = "allow";
6090
- await writeDiagnosticLog(state, "permission:auto-allow", {
6052
+ const permissionType = getPermissionType(input);
6053
+ const patterns = getPermissionPatterns(input);
6054
+ if (isManagedUltraworkSession(state, sessionID) && permissionType === "external_directory" && patterns.some(isExternalTmpPattern)) {
6055
+ output.status = "deny";
6056
+ await writeDiagnosticLog(state, "permission:auto-deny-external-tmp", {
6057
+ sessionID,
6058
+ status: output.status,
6059
+ permission: permissionType,
6060
+ patterns,
6061
+ projectTmpDir: getProjectTmpDir(state),
6062
+ projectLogDir: getProjectLogDir(state)
6063
+ });
6064
+ return;
6065
+ }
6066
+ await writeDiagnosticLog(state, "permission:ask", {
6091
6067
  sessionID,
6092
- permission: input.permission,
6093
- patterns: input.patterns
6068
+ status: output.status,
6069
+ permission: permissionType,
6070
+ patterns
6094
6071
  });
6095
6072
  };
6096
6073
  }
6074
+ function getPermissionType(input) {
6075
+ if (!input || typeof input !== "object") return void 0;
6076
+ const value = input;
6077
+ return typeof value.type === "string" ? value.type : typeof value.permission === "string" ? value.permission : void 0;
6078
+ }
6079
+ function getPermissionPatterns(input) {
6080
+ if (!input || typeof input !== "object") return [];
6081
+ const value = input;
6082
+ const source = value.pattern ?? value.patterns;
6083
+ if (Array.isArray(source)) return source.filter((item) => typeof item === "string");
6084
+ return typeof source === "string" ? [source] : [];
6085
+ }
6086
+ function isExternalTmpPattern(pattern) {
6087
+ return pattern === "/tmp" || pattern.startsWith("/tmp/") || pattern === "/tmp/*";
6088
+ }
6089
+ function createShellEnvHandler(state) {
6090
+ return async (_input, output) => {
6091
+ const projectTmpDir = getProjectTmpDir(state);
6092
+ const projectLogDir = getProjectLogDir(state);
6093
+ await mkdir(projectTmpDir, { recursive: true });
6094
+ await mkdir(projectLogDir, { recursive: true });
6095
+ output.env.TMPDIR = projectTmpDir;
6096
+ output.env.TMP = projectTmpDir;
6097
+ output.env.TEMP = projectTmpDir;
6098
+ output.env.OPENCODE_TMP_DIR = projectTmpDir;
6099
+ output.env.OPENCODE_LOG_DIR = projectLogDir;
6100
+ };
6101
+ }
6097
6102
  async function server(input) {
6098
6103
  const state = createState(input);
6099
6104
  checkPluginUpdate(state).catch(() => {
@@ -6233,6 +6238,11 @@ async function server(input) {
6233
6238
  state,
6234
6239
  "permission.ask",
6235
6240
  createPermissionAskHandler(state)
6241
+ ),
6242
+ "shell.env": withErrorBoundary(
6243
+ state,
6244
+ "shell.env",
6245
+ createShellEnvHandler(state)
6236
6246
  )
6237
6247
  };
6238
6248
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-immune",
3
- "version": "1.0.76",
3
+ "version": "1.0.77",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin: session recovery, auto-retry, multi-cycle automation, context monitoring",
6
6
  "exports": {
@@ -12,7 +12,7 @@
12
12
  "dist/plugin/server.js"
13
13
  ],
14
14
  "scripts": {
15
- "build": "esbuild plugin.ts --bundle --platform=node --format=esm --target=node22 --outfile=dist/plugin/server.js",
15
+ "build": "esbuild plugin.ts --bundle --platform=node --format=esm --target=node22 --outfile=dist/plugin/server.js && esbuild plugin.ts --bundle --platform=node --format=esm --target=node22 --outfile=dist/plugin.js",
16
16
  "dev": "node ./node_modules/typescript/bin/tsc --project tsconfig.json --watch",
17
17
  "prepublishOnly": "npm run build"
18
18
  },