@anionex/dsh-turn-rewind 0.2.2 → 0.2.3

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.
@@ -291,11 +291,20 @@ export function createRewindHttpHandler(ctx, engine, coordinator) {
291
291
  if (request.method === 'POST') {
292
292
  const body = objectBody(await readBody(request));
293
293
  const mode = body.mode;
294
- if (mode !== 'code' && mode !== 'both') {
295
- throw new ChangeLedgerError('INVALID_ARGUMENTS', 'mode must be "code" or "both"');
294
+ if (mode !== 'code' && mode !== 'both' && mode !== 'messages') {
295
+ throw new ChangeLedgerError('INVALID_ARGUMENTS', 'mode must be "code", "both", or "messages"');
296
296
  }
297
297
  const sessionId = requiredText(body.sessionId, 'sessionId');
298
298
  const messageSeq = nonNegativeInteger(body.messageSeq, 'messageSeq');
299
+ // Messages-only rewind never reads or writes project files, so it needs
300
+ // neither a checkpoint nor an exclusive workspace: it resolves the turn
301
+ // boundary straight from the Session log and forks there.
302
+ if (mode === 'messages') {
303
+ const target = messageTarget(await readSession(ctx, sessionId), messageSeq);
304
+ const fork = await createConversationRestart(ctx, sessionId, target);
305
+ json(response, 200, { status: 'completed', mode, sessionId: fork.sessionId });
306
+ return;
307
+ }
299
308
  const checkpointId = requiredText(body.checkpointId, 'checkpointId');
300
309
  const checkpoint = await checkpointForRequest(ctx, engine, sessionId, messageSeq, checkpointId);
301
310
  const activeSessionIds = await sharedWorkspaceSessions(ctx.agents, checkpoint.cwd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anionex/dsh-turn-rewind",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Turn-level conversation and workspace rewind for DeepSeek Harness, powered by a persistent Change Ledger",
5
5
  "repository": {
6
6
  "type": "git",
@@ -455,11 +455,20 @@ export function createRewindHttpHandler(
455
455
  if (request.method === 'POST') {
456
456
  const body = objectBody(await readBody(request))
457
457
  const mode = body.mode
458
- if (mode !== 'code' && mode !== 'both') {
459
- throw new ChangeLedgerError('INVALID_ARGUMENTS', 'mode must be "code" or "both"')
458
+ if (mode !== 'code' && mode !== 'both' && mode !== 'messages') {
459
+ throw new ChangeLedgerError('INVALID_ARGUMENTS', 'mode must be "code", "both", or "messages"')
460
460
  }
461
461
  const sessionId = requiredText(body.sessionId, 'sessionId')
462
462
  const messageSeq = nonNegativeInteger(body.messageSeq, 'messageSeq')
463
+ // Messages-only rewind never reads or writes project files, so it needs
464
+ // neither a checkpoint nor an exclusive workspace: it resolves the turn
465
+ // boundary straight from the Session log and forks there.
466
+ if (mode === 'messages') {
467
+ const target = messageTarget(await readSession(ctx, sessionId), messageSeq)
468
+ const fork = await createConversationRestart(ctx, sessionId, target)
469
+ json(response, 200, { status: 'completed', mode, sessionId: fork.sessionId })
470
+ return
471
+ }
463
472
  const checkpointId = requiredText(body.checkpointId, 'checkpointId')
464
473
  const checkpoint = await checkpointForRequest(ctx, engine, sessionId, messageSeq, checkpointId)
465
474
  const activeSessionIds = await sharedWorkspaceSessions(ctx.agents, checkpoint.cwd)
@@ -608,7 +617,7 @@ async function checkpointForRequest(
608
617
  async function createConversationRestart(
609
618
  ctx: ConversationRestartContext,
610
619
  sourceId: string,
611
- checkpoint: MessageCheckpoint,
620
+ checkpoint: MessageTarget,
612
621
  ): Promise<{ readonly sessionId: string }> {
613
622
  const source = await readSession(ctx, sourceId)
614
623
  const current = messageTarget(source, checkpoint.messageSeq)