opencode-immune 1.0.58 → 1.0.60

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 (2) hide show
  1. package/dist/plugin.js +36 -3
  2. package/package.json +1 -1
package/dist/plugin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // .opencode/plugin.ts — opencode-immune plugin
2
2
  // Hybrid single-file architecture with factory functions, explicit state, error boundaries
3
3
  // See: memory-bank/creative/creative-plugin-architecture.md (Option C)
4
- import { createOpencodeClient as createOpencodeClientV2 } from "@opencode-ai/sdk/v2/client";
4
+ import { createOpencodeClient as createOpencodeClientV2 } from "@opencode-ai/sdk/v2";
5
5
  import { appendFile, mkdir, readFile, unlink, writeFile, stat, rm, rename, readdir, copyFile } from "fs/promises";
6
6
  import { join, dirname } from "path";
7
7
  import { fileURLToPath } from "url";
@@ -11,7 +11,7 @@ import { execFile } from "child_process";
11
11
  // ═══════════════════════════════════════════════════════════════════════════════
12
12
  // PLUGIN VERSION CHECK
13
13
  // ═══════════════════════════════════════════════════════════════════════════════
14
- const PLUGIN_VERSION = "1.0.58";
14
+ const PLUGIN_VERSION = "1.0.59";
15
15
  const PLUGIN_PACKAGE_NAME = "opencode-immune";
16
16
  const PLUGIN_DIRNAME = dirname(fileURLToPath(import.meta.url));
17
17
  function getServerAuthHeaders() {
@@ -96,6 +96,7 @@ function createState(input) {
96
96
  providerRetryWatchdogs: new Map(),
97
97
  childFallbackRequests: new Map(),
98
98
  sessionErrorRetryCount: new Map(),
99
+ ultraworkPermissionSessions: new Set(),
99
100
  fallbackAgentByAgent: new Map(),
100
101
  baseAgentByFallbackAgent: new Map(),
101
102
  ultraworkMarkerPath: join(input.directory, ".opencode", "state", "ultrawork-active.json"),
@@ -174,6 +175,20 @@ async function createManagedUltraworkSession(state, title) {
174
175
  await addManagedUltraworkSession(state, sessionID);
175
176
  return sessionID;
176
177
  }
178
+ async function applyUltraworkSessionPermissions(state, sessionID) {
179
+ if (state.ultraworkPermissionSessions.has(sessionID))
180
+ return;
181
+ const result = await state.client.session.update({
182
+ directory: state.input.directory,
183
+ sessionID,
184
+ permission: ULTRAWORK_SESSION_PERMISSION,
185
+ });
186
+ if (result.error || !result.response.ok) {
187
+ pluginLog.warn(`[opencode-immune] Failed to apply ultrawork permissions to session ${sessionID}:`, result.error ?? result.response.status);
188
+ return;
189
+ }
190
+ state.ultraworkPermissionSessions.add(sessionID);
191
+ }
177
192
  async function promptManagedSession(state, sessionID, text, options = {}) {
178
193
  const result = await state.client.session.promptAsync({
179
194
  directory: state.input.directory,
@@ -336,6 +351,7 @@ async function addManagedUltraworkSession(state, sessionID, timestamp = Date.now
336
351
  return;
337
352
  }
338
353
  state.managedUltraworkSessions.set(sessionID, nextRecord);
354
+ await applyUltraworkSessionPermissions(state, sessionID);
339
355
  }
340
356
  async function addManagedChildSession(state, sessionID, parentSessionID, timestamp = Date.now()) {
341
357
  const parent = state.managedUltraworkSessions.get(parentSessionID);
@@ -379,6 +395,7 @@ async function removeManagedUltraworkSession(state, sessionID, reason) {
379
395
  cancelPendingSessionRetry(state, sessionID, reason);
380
396
  cancelProviderRetryWatchdog(state, sessionID, reason);
381
397
  state.sessionErrorRetryCount.delete(sessionID);
398
+ state.ultraworkPermissionSessions.delete(sessionID);
382
399
  const existed = state.managedUltraworkSessions.delete(sessionID);
383
400
  if (!existed)
384
401
  return;
@@ -1681,6 +1698,13 @@ function createEventHandler(state) {
1681
1698
  const info = event.properties?.info;
1682
1699
  const sessionID = event.properties?.sessionID ?? info?.id;
1683
1700
  const error = event.properties?.error;
1701
+ if (eventType === "session.error") {
1702
+ await writeDiagnosticLog(state, "session-error:observed", {
1703
+ sessionID,
1704
+ action: getManagedSessionErrorAction(error),
1705
+ errorType: getRetryableErrorType(error),
1706
+ });
1707
+ }
1684
1708
  // Fallback: some SDK/schema errors can arrive without a valid sessionID
1685
1709
  // (for example: "Expected 'id' to be a string."). If there is exactly one
1686
1710
  // active managed root session, retry it as a best-effort recovery path.
@@ -2059,8 +2083,17 @@ function createMultiCycleHandler(state) {
2059
2083
  function createPermissionAskHandler(state) {
2060
2084
  return async (input, output) => {
2061
2085
  const sessionID = input.sessionID;
2062
- if (!isManagedUltraworkSession(state, sessionID))
2086
+ if (!sessionID)
2063
2087
  return;
2088
+ if (!isManagedUltraworkSession(state, sessionID)) {
2089
+ const markerActive = await isUltraworkMarkerActive(state);
2090
+ const recovery = markerActive ? await parseTasksFile(state.input.directory) : null;
2091
+ if (!recovery || recovery.phase === "ARCHIVE: DONE")
2092
+ return;
2093
+ state.recoveryContext = recovery;
2094
+ await addManagedUltraworkSession(state, sessionID);
2095
+ pluginLog.info(`[opencode-immune] Permission request recovered AUTO-RESUME session ${sessionID}; applying managed ultrawork auto-allow.`);
2096
+ }
2064
2097
  output.status = "allow";
2065
2098
  await writeDiagnosticLog(state, "permission:auto-allow", {
2066
2099
  sessionID,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-immune",
3
- "version": "1.0.58",
3
+ "version": "1.0.60",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin: session recovery, auto-retry, multi-cycle automation, context monitoring",
6
6
  "exports": {