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.
- package/dist/plugin.js +36 -3
- 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
|
|
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.
|
|
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 (!
|
|
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,
|