opencode-immune 1.0.4 → 1.0.6

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 +40 -2
  2. package/package.json +1 -1
package/dist/plugin.js CHANGED
@@ -13,6 +13,7 @@ function createState(input) {
13
13
  retryTimers: new Map(),
14
14
  retryCount: new Map(),
15
15
  managedSessionsCachePath: (0, path_1.join)(input.directory, ".opencode", "state", "opencode-immune-managed-sessions.json"),
16
+ diagnosticsLogPath: (0, path_1.join)(input.directory, ".opencode", "state", "opencode-immune-debug.log"),
16
17
  lastEditAttempt: null,
17
18
  toolCallCount: 0,
18
19
  todoWriteUsed: false,
@@ -66,6 +67,17 @@ async function writeManagedSessionsCache(state) {
66
67
  console.log(`[opencode-immune] Pruned ${removed} expired managed ultrawork session(s) while writing cache.`);
67
68
  }
68
69
  }
70
+ async function writeDiagnosticLog(state, event, data = {}) {
71
+ try {
72
+ const cacheDir = (0, path_1.join)(state.input.directory, ".opencode", "state");
73
+ await (0, promises_1.mkdir)(cacheDir, { recursive: true });
74
+ const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data });
75
+ await (0, promises_1.appendFile)(state.diagnosticsLogPath, `${line}\n`, "utf-8");
76
+ }
77
+ catch {
78
+ // diagnostics must never affect runtime behavior
79
+ }
80
+ }
69
81
  async function loadManagedSessionsCache(state) {
70
82
  try {
71
83
  const raw = await (0, promises_1.readFile)(state.managedSessionsCachePath, "utf-8");
@@ -219,6 +231,26 @@ async function forceRetryManagedSession(state, sessionID, reason) {
219
231
  const retryText = retryAgent === ULTRAWORK_AGENT
220
232
  ? "[SYSTEM: Previous API call failed with a transient error. Re-read memory-bank/tasks.md, check the Phase Status block, and continue the pipeline. Use the exact neutral prompt from your Step 5 table for the next router call. Do NOT analyze or evaluate file contents.]"
221
233
  : `[SYSTEM: Previous API call failed with a transient error. Resume the current task in your current role as ${retryAgent}. Continue from the existing session state. Do not restart from scratch unless the current session state is missing.]`;
234
+ await writeDiagnosticLog(state, "force-retry:start", {
235
+ sessionID,
236
+ reason,
237
+ retryAgent,
238
+ managedKind: managedSession.kind,
239
+ rootSessionID: managedSession.rootSessionID,
240
+ fallbackModel,
241
+ });
242
+ try {
243
+ await state.input.client.session.abort({
244
+ path: { id: sessionID },
245
+ });
246
+ await writeDiagnosticLog(state, "force-retry:abort-success", { sessionID });
247
+ }
248
+ catch (err) {
249
+ await writeDiagnosticLog(state, "force-retry:abort-failed", {
250
+ sessionID,
251
+ error: err instanceof Error ? err.message : String(err),
252
+ });
253
+ }
222
254
  await state.input.client.session.promptAsync({
223
255
  body: {
224
256
  ...(fallbackModel ? { model: fallbackModel } : {}),
@@ -236,6 +268,12 @@ async function forceRetryManagedSession(state, sessionID, reason) {
236
268
  (fallbackModel
237
269
  ? ` using fallback model ${fallbackModel.providerID}/${fallbackModel.modelID}`
238
270
  : ""));
271
+ await writeDiagnosticLog(state, "force-retry:prompt-sent", {
272
+ sessionID,
273
+ reason,
274
+ retryAgent,
275
+ fallbackModel,
276
+ });
239
277
  }
240
278
  // ═══════════════════════════════════════════════════════════════════════════════
241
279
  // UTILITY: ERROR BOUNDARY
@@ -784,8 +822,6 @@ const RATE_LIMIT_MESSAGE_PATTERN = /too many requests|rate_limit|rate limit/i;
784
822
  function createMultiCycleHandler(state) {
785
823
  return async (input, output) => {
786
824
  const sessionID = input.sessionID;
787
- if (!isManagedRootUltraworkSession(state, sessionID))
788
- return;
789
825
  // Extract text content from parts
790
826
  const parts = output.parts ?? [];
791
827
  let messageContent = "";
@@ -817,6 +853,8 @@ function createMultiCycleHandler(state) {
817
853
  state.retryTimers.set(sessionID, timer);
818
854
  }
819
855
  }
856
+ if (!isManagedRootUltraworkSession(state, sessionID))
857
+ return;
820
858
  // ── PRE_COMMIT: execute /commit ──
821
859
  if (messageContent.includes(PRE_COMMIT_MARKER) && !state.commitPending) {
822
860
  state.commitPending = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-immune",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "OpenCode plugin: session recovery, auto-retry, multi-cycle automation, context monitoring",
5
5
  "exports": {
6
6
  "./server": "./dist/plugin.js"