@skaile/workspaces 1.15.0 → 1.15.1

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 (36) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/bridge/drivers/claude-sdk.js +31 -26
  3. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  4. package/dist/bridge/drivers/codex.js +1 -1
  5. package/dist/bridge/drivers/continue.js +2 -2
  6. package/dist/bridge/drivers/echo.js +1 -1
  7. package/dist/bridge/drivers/gemini.js +3 -3
  8. package/dist/bridge/drivers/goose.js +2 -2
  9. package/dist/bridge/drivers/omp.js +1 -1
  10. package/dist/bridge/drivers/opencode.js +2 -2
  11. package/dist/bridge/drivers/qwen.js +3 -3
  12. package/dist/bridge/index.js +2 -2
  13. package/dist/bridge/src/drivers/claude-sdk.d.ts +12 -56
  14. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  15. package/dist/{chunk-LTQOZIJO.js → chunk-ACWCVB5Q.js} +2 -2
  16. package/dist/{chunk-LTQOZIJO.js.map → chunk-ACWCVB5Q.js.map} +1 -1
  17. package/dist/{chunk-SELNYOEO.js → chunk-DB264AVQ.js} +2 -2
  18. package/dist/{chunk-SELNYOEO.js.map → chunk-DB264AVQ.js.map} +1 -1
  19. package/dist/{chunk-HA53HVIS.js → chunk-EKGB4ZWR.js} +4 -4
  20. package/dist/{chunk-HA53HVIS.js.map → chunk-EKGB4ZWR.js.map} +1 -1
  21. package/dist/{chunk-F3ET4UGP.js → chunk-M5GJT3D7.js} +3 -3
  22. package/dist/{chunk-F3ET4UGP.js.map → chunk-M5GJT3D7.js.map} +1 -1
  23. package/dist/{chunk-XW3SWH7C.js → chunk-MNKUZUN2.js} +3 -3
  24. package/dist/{chunk-XW3SWH7C.js.map → chunk-MNKUZUN2.js.map} +1 -1
  25. package/dist/{chunk-6ZLMG5GR.js → chunk-O5VCUU6D.js} +4 -4
  26. package/dist/{chunk-6ZLMG5GR.js.map → chunk-O5VCUU6D.js.map} +1 -1
  27. package/dist/cli/index.js +5 -5
  28. package/dist/factory-assets/connectors/flow/run-flow.js +1 -1
  29. package/dist/runner/index.js +3 -3
  30. package/dist/sdk/bridge.js +2 -2
  31. package/dist/sdk/index.js +3 -3
  32. package/dist/sdk/runner.js +3 -3
  33. package/dist/{setup-OJC74Q2Q.js → setup-WJPNUE32.js} +4 -4
  34. package/dist/{setup-OJC74Q2Q.js.map → setup-WJPNUE32.js.map} +1 -1
  35. package/dist/tui/index.js +3 -3
  36. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.15.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#449](https://github.com/skaile-ai/workspaces/pull/449) [`1f50da7`](https://github.com/skaile-ai/workspaces/commit/1f50da7ada57f19801162b86f23161dafa54f275) Thanks [@peteralbert](https://github.com/peteralbert)! - Serialize concurrent Claude SDK prompts so each logical turn completes before the next begins.
8
+
3
9
  ## 1.15.0
4
10
 
5
11
  ### Minor Changes
@@ -2,7 +2,7 @@ import { SUPPORTED_CLOUDS, buildClaudeCloudEnv } from '../../chunk-ISQWMBKD.js';
2
2
  import { dispatchCapability } from '../../chunk-RRVQAE5D.js';
3
3
  import { fetchProviderModels } from '../../chunk-BMQKMOQY.js';
4
4
  import { AuthError, classifyClaudeSdkError, reclassifyAuthAsAccountUnavailable, AccountUnavailableError } from '../../chunk-GAH4YRCI.js';
5
- import { BUILTIN_DRIVER_CATALOG, AgentDriver, getBridgeLogger } from '../../chunk-LTQOZIJO.js';
5
+ import { BUILTIN_DRIVER_CATALOG, AgentDriver, getBridgeLogger } from '../../chunk-ACWCVB5Q.js';
6
6
  import '../../chunk-6E6PKKAD.js';
7
7
  import '../../chunk-JB35MVBN.js';
8
8
  import '../../chunk-NSBPE2FW.js';
@@ -348,11 +348,10 @@ var ClaudeSdkDriver = class extends AgentDriver {
348
348
  /** Rejects when the current turn errors. */
349
349
  turnReject = null;
350
350
  /**
351
- * The in-flight turn's promise, awaited when a new prompt supersedes a pending question.
352
- * Deliberately outlives {@link completeTurn} / {@link failTurn} only {@link prompt}'s
353
- * `finally` clears it, and not on a retry recursion. Nulling it earlier reopens #436.
351
+ * Settled tail for complete logical prompts. Rejections are swallowed only on
352
+ * the tail so one failed turn cannot wedge later callers.
354
353
  */
355
- turnPromise = null;
354
+ promptTail = Promise.resolve();
356
355
  /** Guards against duplicate agent_end emissions per turn. */
357
356
  turnCompleted = false;
358
357
  /** `Date.now()` of the most recent SDK message — the watchdog's liveness signal. */
@@ -365,7 +364,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
365
364
  * been spent. Read by {@link failTurn} to decide whether to defer the
366
365
  * `agent-event: error` emission for a self-healable auth error.
367
366
  *
368
- * Set unconditionally at the top of every {@link prompt} invocation; never
367
+ * Set unconditionally at the top of every {@link runPrompt} attempt; never
369
368
  * reset elsewhere — the next call's set is the only legitimate transition.
370
369
  */
371
370
  authSelfHealUsed = false;
@@ -459,16 +458,23 @@ var ClaudeSdkDriver = class extends AgentDriver {
459
458
  * "No conversation found with session ID …" — a recoverable stale-resume error that
460
459
  * occurs after a container crash that prevented the SDK from flushing its session file.
461
460
  */
462
- async prompt(message, _budget = freshRetryBudget()) {
461
+ prompt(message) {
462
+ this.denyPendingQuestion("superseded by a new prompt");
463
+ const queuedPrompt = this.promptTail.then(() => this.runPrompt(message, freshRetryBudget()));
464
+ this.promptTail = queuedPrompt.then(
465
+ () => void 0,
466
+ () => void 0
467
+ );
468
+ return queuedPrompt;
469
+ }
470
+ /**
471
+ * Runs one complete logical prompt inside its acquired FIFO slot.
472
+ *
473
+ * Retries recurse here rather than through {@link prompt}, so they cannot
474
+ * enqueue behind themselves and deadlock.
475
+ */
476
+ async runPrompt(message, _budget) {
463
477
  if (!this.sdk) await this.start();
464
- if (this.pendingQuestion) {
465
- this.denyPendingQuestion("superseded by a new prompt");
466
- let awaited = null;
467
- while (this.turnPromise && this.turnPromise !== awaited) {
468
- awaited = this.turnPromise;
469
- await awaited.catch(() => void 0);
470
- }
471
- }
472
478
  this.authSelfHealUsed = _budget.auth;
473
479
  let retrying = false;
474
480
  const isFirstAttempt = !_budget.staleResume && !_budget.poison && !_budget.auth;
@@ -482,7 +488,6 @@ var ClaudeSdkDriver = class extends AgentDriver {
482
488
  this.turnResolve = resolve;
483
489
  this.turnReject = reject;
484
490
  });
485
- this.turnPromise = turnPromise;
486
491
  try {
487
492
  if (this.query) {
488
493
  const userMsg = this.buildUserMessage(message);
@@ -493,7 +498,6 @@ var ClaudeSdkDriver = class extends AgentDriver {
493
498
  } catch (err) {
494
499
  this.turnResolve = null;
495
500
  this.turnReject = null;
496
- this.turnPromise = null;
497
501
  this.running = false;
498
502
  throw err;
499
503
  }
@@ -506,21 +510,21 @@ var ClaudeSdkDriver = class extends AgentDriver {
506
510
  if (isStaleResume) {
507
511
  this.prepareStaleResumeRetry();
508
512
  retrying = true;
509
- return this.prompt(message, { ..._budget, staleResume: true });
513
+ return this.runPrompt(message, { ..._budget, staleResume: true });
510
514
  }
511
515
  const isPoisonedHistory = !_budget.poison && /invalid_request_error/i.test(errMsg) && /media[_ ]?type|could not process image|image exceeds|cache_control/i.test(errMsg);
512
516
  const poisonSessionId = this.config.resumeSessionId || this.sessionId;
513
517
  if (isPoisonedHistory && poisonSessionId) {
514
518
  if (this.attemptPoisonScrubRetry(poisonSessionId)) {
515
519
  retrying = true;
516
- return this.prompt(message, { ..._budget, poison: true });
520
+ return this.runPrompt(message, { ..._budget, poison: true });
517
521
  }
518
522
  }
519
523
  const isAuthError = err instanceof AuthError && !_budget.auth;
520
524
  if (isAuthError && this.config.onAuthError) {
521
525
  if (await this.attemptAuthSelfHeal(err)) {
522
526
  retrying = true;
523
- return this.prompt(message, { ..._budget, auth: true });
527
+ return this.runPrompt(message, { ..._budget, auth: true });
524
528
  }
525
529
  }
526
530
  throw err;
@@ -529,7 +533,6 @@ var ClaudeSdkDriver = class extends AgentDriver {
529
533
  this.disarmTurnStallWatchdog();
530
534
  this.turnResolve = null;
531
535
  this.turnReject = null;
532
- this.turnPromise = null;
533
536
  this.running = false;
534
537
  }
535
538
  }
@@ -1494,20 +1497,22 @@ var ClaudeSdkDriver = class extends AgentDriver {
1494
1497
  */
1495
1498
  async abort() {
1496
1499
  this.denyPendingQuestion("turn aborted before the question was answered");
1497
- if (this.query) {
1500
+ const abortedQuery = this.query;
1501
+ const abortedController = this.abortController;
1502
+ if (abortedQuery) {
1498
1503
  try {
1499
- await this.query.interrupt();
1504
+ await abortedQuery.interrupt();
1500
1505
  } catch {
1501
1506
  }
1502
1507
  }
1503
- this.abortController?.abort();
1508
+ abortedController?.abort();
1504
1509
  const deadline = Date.now() + ABORT_GRACE_MS;
1505
- while (this.query && Date.now() < deadline) {
1510
+ while (abortedQuery && this.query === abortedQuery && Date.now() < deadline) {
1506
1511
  await new Promise((resolve) => {
1507
1512
  setTimeout(resolve, 100).unref?.();
1508
1513
  });
1509
1514
  }
1510
- if (this.query) {
1515
+ if (abortedQuery && this.query === abortedQuery) {
1511
1516
  this.log.warn("query did not unwind after abort; forcing teardown");
1512
1517
  this.hardResetQuery();
1513
1518
  this.completeTurn();