@playcraft/cli 0.1.20 → 0.1.21

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.
@@ -246,11 +246,15 @@ async function executeTurn(state, scopeKey, operation, payload, recovery) {
246
246
  const reserved = state.journal.getOperation(scopeKey) ?? operation;
247
247
  if (result.outcome === 'uncertain' || result.outcome === 'failed' || !result.turnId) {
248
248
  const failed = result.outcome === 'failed';
249
+ // Codex no longer knows the thread although the binding said it could continue. Marking the
250
+ // binding lost lets the same turn, sent again with the conversation, rebind the session.
251
+ const threadLost = failed && result.error === 'unknown_thread';
249
252
  await state.journal.putSession({
250
253
  ...(state.journal.getSession(sessionId) ?? binding),
251
254
  turnStatus: failed ? undefined : 'starting',
252
255
  turnBlock: failed ? undefined : 'uncertain',
253
256
  activeTurnId: undefined,
257
+ ...(threadLost ? { recoverability: 'history_only' } : {}),
254
258
  });
255
259
  return persist(state, scopeKey, transitionOperation(reserved, failed ? 'failed' : 'uncertain', {
256
260
  error: result.outcome === 'failed' ? result.error : 'native_receipt_lost',
@@ -1,7 +1,7 @@
1
1
  import { readObservedFile, withObservedFile } from '../workspaces/revisions.js';
2
2
  import { registerWorkspace, revisionScope, workspaceRoot, WorkspaceContextError } from '../workspaces/registry.js';
3
3
  import { randomUUID } from 'node:crypto';
4
- import { workspaceRegistrationRequestSchema, HTTP_STATUS_BY_ERROR, assertLeaseFence, buildHandshakeDocument, capability, findUntrustedRuntimeFields, gitFileRefSchema, hashOperationPayload, sourceAckSchema, operationAcceptRequestSchema, operationKindSchema, operationScopeKey, resolveIdempotentAccept, nativeHistoryReadSchema, runtimeError, runtimeConnectivityDocumentSchema, unavailableRuntimeCapabilities, } from '@playcraft/common/cloud-workspace/runtime';
4
+ import { workspaceRegistrationRequestSchema, HTTP_STATUS_BY_ERROR, assertLeaseFence, buildHandshakeDocument, capability, findUntrustedRuntimeFields, gitFileRefSchema, hashOperationPayload, isLostThreadError, sourceAckSchema, operationAcceptRequestSchema, operationKindSchema, operationScopeKey, resolveIdempotentAccept, nativeHistoryReadSchema, runtimeError, runtimeConnectivityDocumentSchema, unavailableRuntimeCapabilities, } from '@playcraft/common/cloud-workspace/runtime';
5
5
  import { controlTokenMatches, extractControlToken } from './auth.js';
6
6
  import { applyRuntimeEndpointPatch } from './endpoints.js';
7
7
  import { canExecuteKind, executeOperation } from './dispatch.js';
@@ -383,7 +383,12 @@ async function acceptOperation(state, request, response) {
383
383
  }));
384
384
  return;
385
385
  }
386
- if (decision.action === 'reuse') {
386
+ // A turn refused for a lost thread never reached Codex. Sent again with the conversation, it
387
+ // runs afresh under the same request, so the message is shown and answered only once.
388
+ const retryWithRecovery = decision.action === 'reuse' && parsed.data.kind === 'session.turn'
389
+ && Boolean(parsed.data.sessionRecovery) && decision.operation.status === 'failed'
390
+ && isLostThreadError(decision.operation.error);
391
+ if (decision.action === 'reuse' && !retryWithRecovery) {
387
392
  if (decision.operation.status === 'uncertain') {
388
393
  writeError(response, runtimeError('uncertain_operation', decision.operation.error ?? 'native_receipt_lost', {
389
394
  operationId: decision.operation.operationId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcraft/cli",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -48,8 +48,8 @@
48
48
  "@gltf-transform/core": "^4.3.0",
49
49
  "@gltf-transform/extensions": "^4.3.0",
50
50
  "@gltf-transform/functions": "^4.3.0",
51
- "@playcraft/build": "^0.1.20",
52
- "@playcraft/common": "^0.1.20",
51
+ "@playcraft/build": "^0.1.21",
52
+ "@playcraft/common": "^0.1.21",
53
53
  "better-sqlite3-pinned": "npm:better-sqlite3@13.0.3",
54
54
  "chokidar": "^4.0.3",
55
55
  "commander": "^13.1.0",