@skaile/workspaces 0.10.1 → 0.11.0

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 (34) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/base-assets/connectors/flow/run-flow.js +1 -1
  3. package/dist/bridge/drivers/claude-sdk.js +42 -1
  4. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  5. package/dist/bridge/drivers/codex.js +1 -1
  6. package/dist/bridge/drivers/echo.js +1 -1
  7. package/dist/bridge/drivers/omp.js +1 -1
  8. package/dist/bridge/index.js +2 -2
  9. package/dist/bridge/src/drivers/claude-sdk.d.ts +22 -0
  10. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  11. package/dist/{chunk-OVM36NYF.js → chunk-L6PKR6YY.js} +197 -83
  12. package/dist/chunk-L6PKR6YY.js.map +1 -0
  13. package/dist/{chunk-OSJH4SPO.js → chunk-VMU2WEN7.js} +3 -3
  14. package/dist/{chunk-OSJH4SPO.js.map → chunk-VMU2WEN7.js.map} +1 -1
  15. package/dist/{chunk-S7RACIZI.js → chunk-YOFKTALB.js} +2 -2
  16. package/dist/{chunk-S7RACIZI.js.map → chunk-YOFKTALB.js.map} +1 -1
  17. package/dist/{chunk-IFRUVHOQ.js → chunk-ZLLUIIZR.js} +2 -2
  18. package/dist/{chunk-IFRUVHOQ.js.map → chunk-ZLLUIIZR.js.map} +1 -1
  19. package/dist/cli/index.js +5 -5
  20. package/dist/runner/index.js +3 -3
  21. package/dist/runner/src/ai-credential-refresh.d.ts +74 -0
  22. package/dist/runner/src/ai-credential-refresh.d.ts.map +1 -0
  23. package/dist/runner/src/serve-credentials.d.ts +21 -0
  24. package/dist/runner/src/serve-credentials.d.ts.map +1 -1
  25. package/dist/runner/src/serve.d.ts +2 -2
  26. package/dist/runner/src/serve.d.ts.map +1 -1
  27. package/dist/sdk/bridge.js +2 -2
  28. package/dist/sdk/index.js +3 -3
  29. package/dist/sdk/runner.js +3 -3
  30. package/dist/{setup-QIEPIYH2.js → setup-QAOUBECX.js} +4 -4
  31. package/dist/{setup-QIEPIYH2.js.map → setup-QAOUBECX.js.map} +1 -1
  32. package/dist/tui/index.js +3 -3
  33. package/package.json +1 -1
  34. package/dist/chunk-OVM36NYF.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c0f3b15: Two-part hardening of the AI-credential 401 path:
8
+
9
+ **Bridge: defer the auth-error event when self-heal is pending.** The
10
+ `claude-sdk` driver used to emit a `{ type: "error" }` agent-event from
11
+ `failTurn()` _before_ its `onAuthError` self-heal callback decided
12
+ whether the credential could be refreshed. The runner forwarded every
13
+ such event to the platform, so users saw a flash of `Failed to
14
+ authenticate. API Error: 401` even on every successful self-heal.
15
+ `failTurn()` now suppresses the downstream emission when the failure
16
+ is an `AuthError` on the first attempt AND an `onAuthError` callback is
17
+ configured; the event is emitted only if the self-heal callback returns
18
+ failure (or throws), or if the retry's own `failTurn` runs. Every auth
19
+ failure still produces exactly one downstream `error` event — none on
20
+ silent recovery, one on terminal failure.
21
+
22
+ **Runner: proactive AI-credential refresh.** New
23
+ `createAiCredentialRefreshScheduler` factory in
24
+ `runner/src/ai-credential-refresh.ts`. After the initial Claude Code
25
+ credentials blob lands at `session_init`, the runner parses
26
+ `claudeAiOauth.expiresAt`, schedules a single `setTimeout` to fire 5
27
+ minutes before expiry, and on fire calls
28
+ `host.refresh_credential { reason: 'refresh' }` via the existing
29
+ mediator path. Successful mints (proactive or reactive retry-401) chain
30
+ the next fire. Static tokens (`expiresAt: null`) and standalone CLI
31
+ sessions short-circuit to no-op. The reactive retry-401 path stays as
32
+ the safety net. Cancelled in `cleanup()` so SIGTERM / hibernate does
33
+ not leak the timer.
34
+
35
+ The new helper `extractClaudeAiOauthExpiresAt(json)` is exported from
36
+ the runner for callers that need to inspect the credentials blob
37
+ without persisting it.
38
+
39
+ Pair with the platform-side enablement of `SKAILE_AIP_AUTO_REFRESH` to
40
+ also pre-warm the platform's credential cache every 15 minutes; the
41
+ runner's proactive timer is the primary defence against in-container
42
+ 401s and is independent of that flag.
43
+
3
44
  ## 0.10.1
4
45
 
5
46
  ### Patch Changes
@@ -1,4 +1,4 @@
1
- export { resumeFlow, runFlow } from '../../../chunk-IFRUVHOQ.js';
1
+ export { resumeFlow, runFlow } from '../../../chunk-ZLLUIIZR.js';
2
2
  import '../../../chunk-GCJXPUHG.js';
3
3
  import '../../../chunk-IPUYL6TD.js';
4
4
  import '../../../chunk-UHSC75L7.js';
@@ -1,7 +1,7 @@
1
1
  import { classifyClaudeSdkError, AuthError } from '../../chunk-EWP5HZBV.js';
2
2
  import { fetchProviderModels } from '../../chunk-KOVLSBXK.js';
3
3
  import { dispatchCapability } from '../../chunk-RRVQAE5D.js';
4
- import { registerDriver, DRIVER_CATALOG, AgentDriver, getBridgeLogger } from '../../chunk-S7RACIZI.js';
4
+ import { registerDriver, DRIVER_CATALOG, AgentDriver, getBridgeLogger } from '../../chunk-YOFKTALB.js';
5
5
  import '../../chunk-24UIWON4.js';
6
6
  import '../../chunk-NSBPE2FW.js';
7
7
  import { spawnSync } from 'child_process';
@@ -237,6 +237,17 @@ var ClaudeSdkDriver = class extends AgentDriver {
237
237
  turnReject = null;
238
238
  /** Guards against duplicate agent_end emissions per turn. */
239
239
  turnCompleted = false;
240
+ /**
241
+ * Mirror of the `_retryCount` argument of the in-flight {@link prompt} call.
242
+ * Read by {@link failTurn} to decide whether to defer the `agent-event:
243
+ * error` emission for a self-healable auth error. `0` means "first
244
+ * attempt"; `prompt()` increments to `1` before recursing on its
245
+ * `onAuthError` self-heal branch.
246
+ *
247
+ * Set unconditionally at the top of every {@link prompt} invocation; never
248
+ * reset elsewhere — the next call's set is the only legitimate transition.
249
+ */
250
+ currentRetryCount = 0;
240
251
  /** Tracks whether a session has been started (for continue: true). */
241
252
  hasSession = false;
242
253
  /** Session ID from the SDK — used for streamInput messages. */
@@ -313,6 +324,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
313
324
  * occurs after a container crash that prevented the SDK from flushing its session file.
314
325
  */
315
326
  async prompt(message, _retryCount = 0) {
327
+ this.currentRetryCount = _retryCount;
316
328
  if (!this.sdk) await this.start();
317
329
  let retrying = false;
318
330
  if (_retryCount === 0) this._lastTokens = null;
@@ -439,6 +451,18 @@ var ClaudeSdkDriver = class extends AgentDriver {
439
451
  retrying = true;
440
452
  return this.prompt(message, _retryCount + 1);
441
453
  }
454
+ try {
455
+ this.emit("agent-event", {
456
+ type: "error",
457
+ error: err.message,
458
+ detail: err.detail
459
+ });
460
+ } catch (emitErr) {
461
+ this.log.warn(
462
+ "agent-event listener threw during deferred auth-error surfacing; suppressing",
463
+ { error: emitErr instanceof Error ? emitErr.message : String(emitErr) }
464
+ );
465
+ }
442
466
  }
443
467
  throw err;
444
468
  } finally {
@@ -761,6 +785,17 @@ var ClaudeSdkDriver = class extends AgentDriver {
761
785
  * caller transitions even if the listener chain misbehaves; the emit is
762
786
  * wrapped in try/catch so a listener failure cannot leak out.
763
787
  *
788
+ * Self-heal deferral: when the failure is an {@link AuthError} on the
789
+ * first attempt (`currentRetryCount === 0`) AND the caller wired an
790
+ * `onAuthError` callback, the downstream `agent-event: error` emission
791
+ * is deferred. The rejected turn promise still travels to {@link prompt}'s
792
+ * catch block where the self-heal runs; if the retry succeeds the user
793
+ * never sees a 401, if the retry fails the second `failTurn` call (now
794
+ * with `currentRetryCount === 1`) emits the error normally. This stops
795
+ * the historical "401 flashes in the UI even though self-heal worked"
796
+ * misbehaviour where the bridge emitted the error event before the
797
+ * retry decision was known.
798
+ *
764
799
  * Spec: `_devlog/specs/2026-05-07-unified-credential-mediation.md`
765
800
  * § "Runner-side handling on 401" (the AI 401 mediation path that
766
801
  * exposed this hang).
@@ -771,6 +806,12 @@ var ClaudeSdkDriver = class extends AgentDriver {
771
806
  this.turnResolve = null;
772
807
  this.turnReject = null;
773
808
  }
809
+ this.turnCompleted = true;
810
+ const willSelfHeal = err instanceof AuthError && this.currentRetryCount === 0 && this.config.onAuthError != null;
811
+ if (willSelfHeal) {
812
+ this.log.info("deferring auth-error event; self-heal will attempt refresh");
813
+ return;
814
+ }
774
815
  try {
775
816
  this.emit("agent-event", {
776
817
  type: "error",