shraga 0.1.57 → 0.1.58

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shraga",
3
- "version": "0.1.57",
3
+ "version": "0.1.58",
4
4
  "description": "The teammate you delegate coding to — a self-hostable, multi-user AI coding agent web UI (Claude Code, with a pluggable engine seam).",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -26,7 +26,7 @@ import { mountFeatures, registerFeature, resumeFeatureSession, collectFeatureFla
26
26
  import { registerSpaCatchAll } from './spa-catchall.ts';
27
27
  import { slackFeature } from './slack/feature.ts';
28
28
  import { dataPath } from './paths.ts';
29
- import { getAllSessions, getSession, getSessionHistory, upsertSession, appendMessage, saveConversation, loadConversation, setSessionDirectives, getAutoApprove, setAutoApprove, getSessionsByScheduleId, getSessionsVisibleTo, isSessionVisibleTo, setRunStatus, incrementRetryCount, resetRetryCount, getRunningSessions, getActiveLockCount, updateScheduledSessionStatus, setShuttingDown, backfillSessionVisibility, writePartial, readPartial, clearPartial, registerLivePartial, unregisterLivePartial, readLivePartial, acquireSessionLock, releaseSessionLock, replaceSessionLock, isSessionLocked, getSessionAbortController, forkSession, generateSessionTitle, type ConvBlock, type ConvMessage, type SessionMeta } from './sessions.ts';
29
+ import { getAllSessions, getSession, getSessionHistory, upsertSession, appendMessage, saveConversation, loadConversation, setSessionDirectives, getAutoApprove, setAutoApprove, getSessionsByScheduleId, getSessionsVisibleTo, isSessionVisibleTo, setRunStatus, incrementRetryCount, getRunningSessions, getActiveLockCount, updateScheduledSessionStatus, setShuttingDown, backfillSessionVisibility, writePartial, readPartial, clearPartial, registerLivePartial, unregisterLivePartial, readLivePartial, acquireSessionLock, releaseSessionLock, replaceSessionLock, isSessionLocked, getSessionAbortController, forkSession, generateSessionTitle, type ConvBlock, type ConvMessage, type SessionMeta } from './sessions.ts';
30
30
  import { setBroadcaster } from './session-bus.ts';
31
31
  import * as scheduler from './scheduler/index.ts';
32
32
  import { initPolls } from './polls.ts';
@@ -1325,7 +1325,6 @@ async function runStream(ws: WebSocket, session: WsSession, sid: string, promptT
1325
1325
  if (blocks.length) writePartial(sid, blocks);
1326
1326
  }, 5_000);
1327
1327
 
1328
- resetRetryCount(sid);
1329
1328
  setRunStatus(sid, 'running', 'web');
1330
1329
 
1331
1330
  let stopReason = '';
@@ -270,7 +270,16 @@ export function setRunStatus(sessionId: string, status: 'running' | 'idle', orig
270
270
  if (!s) return;
271
271
  s.runStatus = status;
272
272
  if (origin) s.runOrigin = origin;
273
- if (status === 'idle') s.lastStopReason = stopReason;
273
+ if (status === 'idle') {
274
+ s.lastStopReason = stopReason;
275
+ // runRetryCount caps crash-resume loops (interrupt → resume → interrupt). Reaching 'idle' at all
276
+ // proves this turn was NOT killed by a restart — the guard above drops idle writes during a
277
+ // drain, and a hard kill never gets here — so the loop is broken and the count starts over.
278
+ // It used to be reset only on the web path, so Slack and scheduler sessions accumulated it
279
+ // forever: after two interruptions in their whole life they permanently lost auto-resume and
280
+ // every later restart ended at "please send a message to continue".
281
+ s.runRetryCount = 0;
282
+ }
274
283
  s.lastModified = Date.now();
275
284
  saveIndex(sessions);
276
285
  }
@@ -385,7 +385,10 @@ export async function retrySlackSession(session: SessionMeta, prompt: string): P
385
385
  onUserQuestion: makeSlackQuestionHandler({ channel, threadTs, useUserToken }),
386
386
  }),
387
387
  session.sessionId,
388
- { partial: false, artifacts: false },
388
+ // Partial-capture ON: a recovery turn is the one most likely to be interrupted again (a
389
+ // restart loop, an upgrade retry), and with it off the second interruption had nothing to
390
+ // preserve and resumed from the original prompt instead of the cut-off point.
391
+ { partial: true, artifacts: false },
389
392
  ),
390
393
  );
391
394
  if (replyTs) { console.log(`[slack-bot] recovery reply posted: ${channel} ts=${replyTs}`); invalidateChannelContext(channel); }