@skaile/workspaces 3.12.0 → 3.14.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 (80) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{asset-feeds-553UV3SZ.js → asset-feeds-STHKKTW3.js} +4 -4
  3. package/dist/{asset-feeds-553UV3SZ.js.map → asset-feeds-STHKKTW3.js.map} +1 -1
  4. package/dist/asset-manager/index.js +1 -1
  5. package/dist/{chunk-O7BTSMLV.js → chunk-5F33LGZL.js} +3 -3
  6. package/dist/{chunk-O7BTSMLV.js.map → chunk-5F33LGZL.js.map} +1 -1
  7. package/dist/{chunk-DJ2Y5KAJ.js → chunk-GY5SLCH2.js} +212 -39
  8. package/dist/chunk-GY5SLCH2.js.map +1 -0
  9. package/dist/{chunk-PY255PK6.js → chunk-HYFJPR7W.js} +6 -6
  10. package/dist/{chunk-PY255PK6.js.map → chunk-HYFJPR7W.js.map} +1 -1
  11. package/dist/{chunk-YSAYNSML.js → chunk-KKMRT6GU.js} +3 -3
  12. package/dist/chunk-KKMRT6GU.js.map +1 -0
  13. package/dist/{chunk-TUZ4MUVP.js → chunk-NELENR57.js} +3 -3
  14. package/dist/{chunk-TUZ4MUVP.js.map → chunk-NELENR57.js.map} +1 -1
  15. package/dist/{chunk-BCCF5O5X.js → chunk-URB2QZ4W.js} +2 -2
  16. package/dist/{chunk-BCCF5O5X.js.map → chunk-URB2QZ4W.js.map} +1 -1
  17. package/dist/{chunk-SVCJ5WRP.js → chunk-UTW6YKAC.js} +2 -2
  18. package/dist/{chunk-SVCJ5WRP.js.map → chunk-UTW6YKAC.js.map} +1 -1
  19. package/dist/{chunk-4DAERG6K.js → chunk-XICDQVOG.js} +3 -3
  20. package/dist/{chunk-4DAERG6K.js.map → chunk-XICDQVOG.js.map} +1 -1
  21. package/dist/{chunk-Q7EIHMSP.js → chunk-Y6JJHOLR.js} +6 -6
  22. package/dist/{chunk-Q7EIHMSP.js.map → chunk-Y6JJHOLR.js.map} +1 -1
  23. package/dist/{chunk-LIUBSGYL.js → chunk-Z7W4B7P2.js} +3 -3
  24. package/dist/{chunk-LIUBSGYL.js.map → chunk-Z7W4B7P2.js.map} +1 -1
  25. package/dist/cli/index.js +26 -26
  26. package/dist/connectors/index.js +1 -1
  27. package/dist/{ensure-sources-IT6FNUI7.js → ensure-sources-BFVKV773.js} +4 -4
  28. package/dist/{ensure-sources-IT6FNUI7.js.map → ensure-sources-BFVKV773.js.map} +1 -1
  29. package/dist/factory-assets/connectors/box.js +1 -1
  30. package/dist/factory-assets/connectors/deploy.js +1 -1
  31. package/dist/factory-assets/connectors/devserver.js +1 -1
  32. package/dist/factory-assets/connectors/flow/adapter.js +1 -1
  33. package/dist/factory-assets/connectors/flow/run-flow.js +2 -2
  34. package/dist/factory-assets/connectors/flow.js +1 -1
  35. package/dist/factory-assets/connectors/git.js +1 -1
  36. package/dist/factory-assets/connectors/gmail.js +1 -1
  37. package/dist/factory-assets/connectors/googledrive.js +1 -1
  38. package/dist/factory-assets/connectors/local.js +1 -1
  39. package/dist/factory-assets/connectors/mattermost.js +1 -1
  40. package/dist/factory-assets/connectors/memory.js +1 -1
  41. package/dist/factory-assets/connectors/minio.js +1 -1
  42. package/dist/factory-assets/connectors/postgres.js +1 -1
  43. package/dist/factory-assets/connectors/s3.js +1 -1
  44. package/dist/factory-assets/connectors/sharepoint.js +1 -1
  45. package/dist/factory-assets/connectors/sqlite.js +1 -1
  46. package/dist/factory-assets/connectors/static-server.js +1 -1
  47. package/dist/factory-assets/connectors/tunnel.js +1 -1
  48. package/dist/factory-assets/connectors/webdav.js +1 -1
  49. package/dist/factory-assets/connectors/xstate-store.js +1 -1
  50. package/dist/factory-assets/connectors/xstate.js +1 -1
  51. package/dist/{helpers-RKVDZOID.js → helpers-CQV2V2SL.js} +4 -4
  52. package/dist/{helpers-RKVDZOID.js.map → helpers-CQV2V2SL.js.map} +1 -1
  53. package/dist/{library-publish-NFD7TLV7.js → library-publish-6FZCXPYU.js} +6 -6
  54. package/dist/{library-publish-NFD7TLV7.js.map → library-publish-6FZCXPYU.js.map} +1 -1
  55. package/dist/{open-library-UHCMZWK5.js → open-library-4EOFZ4QD.js} +5 -5
  56. package/dist/{open-library-UHCMZWK5.js.map → open-library-4EOFZ4QD.js.map} +1 -1
  57. package/dist/{project-MURYBN6B.js → project-J7RSKBAU.js} +5 -5
  58. package/dist/{project-MURYBN6B.js.map → project-J7RSKBAU.js.map} +1 -1
  59. package/dist/runner/index.js +4 -4
  60. package/dist/runner/src/compaction/orchestrator.d.ts +66 -4
  61. package/dist/runner/src/compaction/orchestrator.d.ts.map +1 -1
  62. package/dist/runner/src/compaction/prompt.d.ts +6 -1
  63. package/dist/runner/src/compaction/prompt.d.ts.map +1 -1
  64. package/dist/runner/src/resource-handler.d.ts +12 -0
  65. package/dist/runner/src/resource-handler.d.ts.map +1 -1
  66. package/dist/sdk/asset-manager.js +1 -1
  67. package/dist/sdk/index.js +4 -4
  68. package/dist/sdk/runner.js +4 -4
  69. package/dist/{source-3BDAWE4X.js → source-AJ27AS6D.js} +6 -6
  70. package/dist/{source-3BDAWE4X.js.map → source-AJ27AS6D.js.map} +1 -1
  71. package/dist/{source-manifest-publish-PRC7KC3J.js → source-manifest-publish-UCA2O5UA.js} +7 -7
  72. package/dist/{source-manifest-publish-PRC7KC3J.js.map → source-manifest-publish-UCA2O5UA.js.map} +1 -1
  73. package/dist/tui/index.js +5 -5
  74. package/dist/tui/index.js.map +1 -1
  75. package/dist/types/src/events.d.ts +11 -0
  76. package/dist/types/src/events.d.ts.map +1 -1
  77. package/dist/workspace-plugin/index.js +1 -1
  78. package/package.json +2 -1
  79. package/dist/chunk-DJ2Y5KAJ.js.map +0 -1
  80. package/dist/chunk-YSAYNSML.js.map +0 -1
@@ -1,9 +1,9 @@
1
- import { WorkspacePlugin } from './chunk-SVCJ5WRP.js';
1
+ import { WorkspacePlugin } from './chunk-UTW6YKAC.js';
2
2
  import { assembleSystemPrompt, buildCapabilitiesPromptSection } from './chunk-W3UDISS2.js';
3
3
  import { WebSocketServerTransport } from './chunk-WQ7DE5UC.js';
4
- import { resolveFlowPath } from './chunk-TUZ4MUVP.js';
4
+ import { resolveFlowPath } from './chunk-NELENR57.js';
5
5
  import { findAiAssetsRoot, deployCatalogEntry, undeployCatalogEntry } from './chunk-GHWJHOYX.js';
6
- import { registerBuiltinConnectors, buildConnectorPromptSection, findMissingPackages, installNpmPackages, ConnectorManager, ConnectorStartupError, buildSdkConnectorTools, driveOrchestratorTurn, SessionNodeExecutor, SessionSubpromptRunner, SessionInlineSubFlowRunner, buildSdkFlowTools } from './chunk-YSAYNSML.js';
6
+ import { registerBuiltinConnectors, buildConnectorPromptSection, findMissingPackages, installNpmPackages, ConnectorManager, ConnectorStartupError, buildSdkConnectorTools, driveOrchestratorTurn, SessionNodeExecutor, SessionSubpromptRunner, SessionInlineSubFlowRunner, buildSdkFlowTools } from './chunk-KKMRT6GU.js';
7
7
  import { loadConnectorDeclarations, SecretProviderChain, PreMintedSecretProvider, InMemorySecretProvider, resolvedConfigToDeclarations, isKnownSecretRef, deriveSingleMaterializedConnectorDeclaration } from './chunk-3UU3D2Q3.js';
8
8
  import { EventNormalizer } from './chunk-2A7BV6WT.js';
9
9
  import { SUPPORTED_CLOUDS, probeResumeTranscript, CLOUD_SECRET_ENV_KEYS } from './chunk-RUFTB7QN.js';
@@ -2688,6 +2688,11 @@ function isBinaryBuffer(buf) {
2688
2688
  }
2689
2689
  return false;
2690
2690
  }
2691
+ function nulTailPaddingLength(buf) {
2692
+ let end = buf.length;
2693
+ while (end > 0 && buf[end - 1] === 0) end--;
2694
+ return buf.length - end;
2695
+ }
2691
2696
  function getAuthoritativeSize(state) {
2692
2697
  const provider = state;
2693
2698
  return typeof provider?.authoritativeSize === "function" ? (relPath) => provider.authoritativeSize(relPath) : void 0;
@@ -2770,7 +2775,9 @@ async function handleMountResourceRequest(command, manager, emit) {
2770
2775
  bytes = buf.subarray(0, authSize);
2771
2776
  }
2772
2777
  }
2773
- if (isBinaryBuffer(bytes)) {
2778
+ const padding = nulTailPaddingLength(bytes);
2779
+ const body = bytes.subarray(0, bytes.length - padding);
2780
+ if (padding > 0 && body.length === 0 || isBinaryBuffer(body)) {
2774
2781
  data = {
2775
2782
  data: bytes.toString("base64"),
2776
2783
  contentType,
@@ -2778,7 +2785,7 @@ async function handleMountResourceRequest(command, manager, emit) {
2778
2785
  };
2779
2786
  } else {
2780
2787
  data = {
2781
- data: bytes.toString("utf-8"),
2788
+ data: body.toString("utf-8"),
2782
2789
  contentType,
2783
2790
  encoding: "utf-8"
2784
2791
  };
@@ -3237,6 +3244,14 @@ What still needs to be done or is waiting on user input.
3237
3244
 
3238
3245
  ### Context
3239
3246
  User preferences, constraints, or instructions that must carry forward.`;
3247
+ var RE_COMPACTION_MERGE_INSTRUCTION = `This conversation has already been compacted once. The summary below replaced
3248
+ everything that came before it, and your reply will in turn replace this
3249
+ summary -- anything you leave out is lost for good.
3250
+
3251
+ Your reply must be the COMPLETE merged summary in the section format above:
3252
+ restate everything from the previous summary that still matters, then fold in
3253
+ what has happened since. Do NOT reply with a delta, a diff, a list of changes,
3254
+ or a note that the previous summary still applies.`;
3240
3255
  function buildCompactionPrompt(opts) {
3241
3256
  const base = opts.agentPrompt ?? DEFAULT_COMPACTION_PROMPT;
3242
3257
  const parts = [base];
@@ -3249,6 +3264,19 @@ function buildCompactionPrompt(opts) {
3249
3264
  ${allDirectives.map((d) => `- ${d}`).join("\n")}`
3250
3265
  );
3251
3266
  }
3267
+ if (opts.previousSummary) {
3268
+ parts.push(
3269
+ `
3270
+
3271
+ ## Previous Summary
3272
+
3273
+ <previous_summary>
3274
+ ${opts.previousSummary}
3275
+ </previous_summary>
3276
+
3277
+ ${RE_COMPACTION_MERGE_INSTRUCTION}`
3278
+ );
3279
+ }
3252
3280
  if (opts.focus) {
3253
3281
  parts.push(`
3254
3282
 
@@ -3280,6 +3308,31 @@ var TokenThresholdStrategy = class {
3280
3308
  var MIN_SUMMARY_CHARS = 200;
3281
3309
  var MAX_COMPRESSION_RATIO = 0.9;
3282
3310
  var DEFAULT_CONTEXT_WINDOW = 2e5;
3311
+ var ONE_MILLION_CONTEXT_WINDOW = 1e6;
3312
+ var ONE_MILLION_ALIAS_PATTERN = /\[1m\]|-1m$/i;
3313
+ var DEFAULT_COMPACTION_TIMEOUT_MS = 10 * 6e4;
3314
+ function compactionTimeoutMs() {
3315
+ const raw = Number(process.env.SKAILE_COMPACTION_TIMEOUT_MS);
3316
+ return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_COMPACTION_TIMEOUT_MS;
3317
+ }
3318
+ var RETRYABLE_ERROR_CODES = /* @__PURE__ */ new Set(["timeout", "unknown"]);
3319
+ var RETRY_FOCUS_DIRECTIVE = `The previous attempt to write this summary did not finish in time, most likely
3320
+ because it ran long. Be economical: compress aggressively, and drop low-value
3321
+ detail rather than exceeding a few hundred words.
3322
+
3323
+ Cover exactly the same ground as before -- if a previous summary appears above,
3324
+ still restate everything in it that still matters. The saving comes from
3325
+ tighter prose, never from leaving material out.`;
3326
+ var ABORT_SETTLE_GRACE_MS = 5e3;
3327
+ var MAX_CARRIED_SUMMARY_CHARS = 24e3;
3328
+ var MAX_FAILURE_DIAGNOSTIC_CHARS = 4e3;
3329
+ function truncateTo(text, max) {
3330
+ if (text.length <= max) return text;
3331
+ return `${text.slice(0, max)}... [truncated]`;
3332
+ }
3333
+ function truncateDiagnostic(text) {
3334
+ return truncateTo(text, MAX_FAILURE_DIAGNOSTIC_CHARS);
3335
+ }
3283
3336
  var RATE_LIMIT_TEXT_MAX_CHARS = 1500;
3284
3337
  var RATE_LIMIT_TEXT_PATTERNS = [
3285
3338
  /you('?| ha)ve hit your (rate |usage )?limit/i,
@@ -3296,6 +3349,12 @@ function contextTokens(usage) {
3296
3349
  const cacheCreation = usage?.cacheCreationTokens ?? 0;
3297
3350
  return Math.max(input, cacheRead) + cacheCreation;
3298
3351
  }
3352
+ function resolveContextWindow(driverWindow, model) {
3353
+ if (model && ONE_MILLION_ALIAS_PATTERN.test(model)) {
3354
+ return Math.max(driverWindow ?? 0, ONE_MILLION_CONTEXT_WINDOW);
3355
+ }
3356
+ return driverWindow || DEFAULT_CONTEXT_WINDOW;
3357
+ }
3299
3358
  function detectRateLimitInSummary(text) {
3300
3359
  if (text.length > RATE_LIMIT_TEXT_MAX_CHARS) return false;
3301
3360
  return RATE_LIMIT_TEXT_PATTERNS.some((p) => p.test(text));
@@ -3317,6 +3376,12 @@ var CompactionOrchestrator = class {
3317
3376
  _isCompacting = false;
3318
3377
  lastCompactionSeq = null;
3319
3378
  lastCompactionTime = null;
3379
+ /**
3380
+ * Summary of the last successful compaction, carried into the next one.
3381
+ * Per-instance, in step with `lastCompactionSeq`: a driver rebuild resets
3382
+ * both, so the first compaction after one is not treated as a re-compaction.
3383
+ */
3384
+ lastSummary = null;
3320
3385
  currentSeq = 0;
3321
3386
  messagesSinceCompaction = 0;
3322
3387
  constructor(opts) {
@@ -3346,7 +3411,10 @@ var CompactionOrchestrator = class {
3346
3411
  shouldCompact() {
3347
3412
  if (!this.config.enabled) return false;
3348
3413
  const usage = this.driver.getTokenUsage();
3349
- const contextWindow = this.driver.getContextWindow() || DEFAULT_CONTEXT_WINDOW;
3414
+ const contextWindow = resolveContextWindow(
3415
+ this.driver.getContextWindow(),
3416
+ this.driver.getModel() ?? null
3417
+ );
3350
3418
  const estimatedTokens = this.contextFill(usage);
3351
3419
  if (estimatedTokens <= 0) return false;
3352
3420
  return this.strategy.shouldCompact({
@@ -3366,8 +3434,17 @@ var CompactionOrchestrator = class {
3366
3434
  this._isCompacting = false;
3367
3435
  }
3368
3436
  }
3369
- async _doCompact(trigger, focus) {
3370
- const tokensBefore = this.contextFill(this.driver.getTokenUsage());
3437
+ /**
3438
+ * One compaction attempt, plus at most one narrowed retry.
3439
+ *
3440
+ * @param retryOf Set only by the retry path. It suppresses a second
3441
+ * `onCompactionStart` (the retry continues the same compaction phase),
3442
+ * guarantees the retry can never itself retry, and carries the first
3443
+ * attempt's context reading forward.
3444
+ */
3445
+ async _doCompact(trigger, focus, retryOf) {
3446
+ const isRetry = retryOf !== void 0;
3447
+ const tokensBefore = retryOf?.tokensBefore ?? this.contextFill(this.driver.getTokenUsage());
3371
3448
  const driverSessionId = this.driver.runtimeSessionId ?? null;
3372
3449
  const driverModel = this.driver.getModel() ?? null;
3373
3450
  const driverProvider = this.driver.driverInfo?.id ?? null;
@@ -3384,25 +3461,37 @@ var CompactionOrchestrator = class {
3384
3461
  modelAtCompaction: driverModel,
3385
3462
  capabilitySignatureAtCompaction
3386
3463
  };
3387
- this.opts.onCompactionStart?.(trigger);
3388
- this.opts.onLog?.(`[compaction] Starting (trigger=${trigger}, tokens=${tokensBefore})`);
3464
+ if (!isRetry) this.opts.onCompactionStart?.(trigger);
3465
+ this.opts.onLog?.(
3466
+ `[compaction] ${isRetry ? "Retrying" : "Starting"} (trigger=${trigger}, tokens=${tokensBefore})`
3467
+ );
3389
3468
  const prompt = buildCompactionPrompt({
3390
3469
  agentPrompt: this.opts.agentCompactionPrompt,
3391
3470
  skillDirectives: this.opts.skillDirectives,
3392
3471
  mcpDirectives: this.opts.mcpDirectives,
3393
- focus
3472
+ focus,
3473
+ // A re-compaction's reply replaces the previous summary, so the model has
3474
+ // to see it — otherwise it answers with a delta that fails validation.
3475
+ previousSummary: coversFromSeq > 0 ? this._carriedSummary() : void 0
3394
3476
  });
3395
- const { summaryText, promptError, elapsedMs } = await this._runCompactionPrompt(prompt);
3477
+ const { summaryText, promptError, elapsedMs, timedOut } = await this._runCompactionPrompt(prompt);
3396
3478
  const attempt = { ...attemptBase, elapsedMs };
3397
3479
  if (promptError !== null) {
3398
- this._emitThrownFailure(attempt, promptError);
3480
+ const errorCode = this._emitThrownFailure(attempt, promptError, timedOut);
3481
+ this._beginCooldown();
3482
+ if (this._shouldRetry(trigger, errorCode, focus, isRetry)) {
3483
+ return await this._doCompact(trigger, RETRY_FOCUS_DIRECTIVE, { tokensBefore });
3484
+ }
3485
+ this.opts.onCompactionEnd?.();
3399
3486
  return null;
3400
3487
  }
3401
3488
  const actualUsage = this.driver.getTokenUsage();
3402
3489
  const tokensAfter = actualUsage?.outputTokens ?? Math.ceil(summaryText.length / 4);
3403
3490
  const validation = validateCompactionOutput(summaryText, tokensBefore, tokensAfter);
3404
3491
  if (!validation.ok) {
3405
- this._emitValidationFailure(attempt, validation.errorCode, tokensAfter);
3492
+ this._emitValidationFailure(attempt, validation.errorCode, tokensAfter, summaryText);
3493
+ this._beginCooldown();
3494
+ this.opts.onCompactionEnd?.();
3406
3495
  return null;
3407
3496
  }
3408
3497
  return await this._completeCompaction(
@@ -3414,6 +3503,40 @@ var CompactionOrchestrator = class {
3414
3503
  coversFromSeq
3415
3504
  );
3416
3505
  }
3506
+ /**
3507
+ * The previous summary as it goes into a re-compaction prompt, capped so the
3508
+ * prompt cannot grow without bound. Truncating loses context the model is
3509
+ * being asked to restate, so it is logged when it happens.
3510
+ */
3511
+ _carriedSummary() {
3512
+ const summary = this.lastSummary;
3513
+ if (!summary) return void 0;
3514
+ if (summary.length <= MAX_CARRIED_SUMMARY_CHARS) return summary;
3515
+ this.opts.onLog?.(
3516
+ `[compaction] Previous summary truncated to ${MAX_CARRIED_SUMMARY_CHARS} of ${summary.length} chars`
3517
+ );
3518
+ return truncateTo(summary, MAX_CARRIED_SUMMARY_CHARS);
3519
+ }
3520
+ /**
3521
+ * Start the anti-thrash cooldown after a failed attempt.
3522
+ *
3523
+ * `TokenThresholdStrategy` skips its cooldown gate entirely while
3524
+ * `lastCompactionTime` is null, and only success used to set it — so any
3525
+ * failing session re-ran a full-context compaction on every single turn.
3526
+ */
3527
+ _beginCooldown() {
3528
+ this.lastCompactionTime = Date.now();
3529
+ }
3530
+ /**
3531
+ * Whether a failed attempt earns the one narrowed retry.
3532
+ *
3533
+ * Only automatic (threshold) compactions retry: a `manual` or `hibernate`
3534
+ * caller owns the decision to try again, and a caller-supplied `focus` would
3535
+ * be discarded by the retry's own directive.
3536
+ */
3537
+ _shouldRetry(trigger, errorCode, focus, isRetry) {
3538
+ return !isRetry && trigger === "threshold" && focus === void 0 && RETRYABLE_ERROR_CODES.has(errorCode);
3539
+ }
3417
3540
  /**
3418
3541
  * Drive the compaction `prompt()` call, capturing summary text from the
3419
3542
  * driver's raw bridge-level events and any thrown error. The listener is
@@ -3422,6 +3545,10 @@ var CompactionOrchestrator = class {
3422
3545
  * `elapsedMs` is the wall-clock cost of the `prompt()` call. It is the only
3423
3546
  * thing that separates a genuinely empty model response from a turn that was
3424
3547
  * settled by something other than the model, which resolves in milliseconds.
3548
+ *
3549
+ * The call is bounded by {@link compactionTimeoutMs}; on expiry the turn is
3550
+ * aborted and `timedOut` is returned so the caller can record a classified
3551
+ * `timeout` rather than wait out the driver's much longer stall watchdog.
3425
3552
  */
3426
3553
  async _runCompactionPrompt(prompt) {
3427
3554
  let summaryText = "";
@@ -3457,58 +3584,103 @@ var CompactionOrchestrator = class {
3457
3584
  }
3458
3585
  };
3459
3586
  let promptError = null;
3587
+ let timedOut = false;
3588
+ let timer;
3460
3589
  const startedAt = Date.now();
3590
+ const timeoutMs = compactionTimeoutMs();
3461
3591
  try {
3462
3592
  this.driver.on("agent-event", captureHandler);
3463
- await this.driver.prompt(prompt);
3593
+ const running = this.driver.prompt(prompt);
3594
+ const expiry = new Promise((resolve4) => {
3595
+ timer = setTimeout(() => resolve4("expired"), timeoutMs);
3596
+ });
3597
+ const outcome = await Promise.race([running.then(() => "settled"), expiry]);
3598
+ if (outcome === "expired") {
3599
+ timedOut = true;
3600
+ const settled = running.then(
3601
+ () => void 0,
3602
+ () => void 0
3603
+ );
3604
+ promptError = new Error(
3605
+ `Compaction prompt did not complete within ${timeoutMs}ms; the turn was aborted.`
3606
+ );
3607
+ const aborted = this.driver.abort().catch((abortErr) => {
3608
+ this.opts.onLog?.(`[compaction] abort after timeout failed: ${String(abortErr)}`);
3609
+ });
3610
+ let settleTimer;
3611
+ const graceExpired = new Promise((resolve4) => {
3612
+ settleTimer = setTimeout(resolve4, ABORT_SETTLE_GRACE_MS);
3613
+ settleTimer.unref?.();
3614
+ });
3615
+ await Promise.race([Promise.all([aborted, settled]), graceExpired]);
3616
+ clearTimeout(settleTimer);
3617
+ }
3464
3618
  } catch (err) {
3465
3619
  promptError = err;
3466
3620
  } finally {
3621
+ clearTimeout(timer);
3467
3622
  this.driver.removeListener("agent-event", captureHandler);
3468
3623
  }
3469
- return { summaryText, promptError, elapsedMs: Date.now() - startedAt };
3624
+ return { summaryText, promptError, elapsedMs: Date.now() - startedAt, timedOut };
3470
3625
  }
3471
3626
  /**
3472
3627
  * Record a `failed` attempt for a thrown `prompt()` error: classify the
3473
- * error, map it to an error code, log, emit the attempt event, and signal
3474
- * compaction end.
3628
+ * error, map it to an error code, log the raw text, and emit the attempt
3629
+ * event. Signalling compaction end is the caller's job — a retry continues
3630
+ * the same phase.
3631
+ *
3632
+ * @param timedOut Set when the bound in {@link _runCompactionPrompt} expired.
3633
+ * The synthetic message carries none of the classifier's keywords, so
3634
+ * round-tripping it would report the opaque `unknown` this bound replaces.
3635
+ * @returns The error code recorded, so the caller can decide about a retry.
3475
3636
  */
3476
- _emitThrownFailure(attemptBase, promptError) {
3477
- const classified = classifyClaudeSdkError(
3478
- promptError instanceof Error ? promptError.message : String(promptError)
3479
- );
3480
- const errorCode = classified.category === "rate_limit" ? "rate_limit" : classified.category === "auth" ? "auth" : classified.category === "network" ? "timeout" : classified.category === "validation" ? "parse_error" : classified.category;
3637
+ _emitThrownFailure(attemptBase, promptError, timedOut = false) {
3638
+ const rawMessage = promptError instanceof Error ? promptError.message : String(promptError);
3639
+ const classified = classifyClaudeSdkError(rawMessage);
3640
+ const classifiedCode = classified.category === "rate_limit" ? "rate_limit" : classified.category === "auth" ? "auth" : classified.category === "network" ? "timeout" : classified.category === "validation" ? "parse_error" : classified.category;
3641
+ const errorCode = timedOut ? "timeout" : classifiedCode;
3642
+ const diagnostic = truncateDiagnostic(classified.message);
3481
3643
  this.opts.onLog?.(`[compaction] Failed: ${classified.message} (${errorCode})`);
3482
3644
  this.opts.onCompactionAttempt?.({
3645
+ // Spread first: `status`/`validatedAt` below are load-bearing (see the
3646
+ // summary comment) and must not be override-able from the base object.
3647
+ ...attemptBase,
3483
3648
  type: "compaction_attempt",
3484
3649
  status: "failed",
3485
3650
  errorCode,
3486
- summary: "",
3651
+ errorMessage: diagnostic,
3652
+ // Mirrored so the platform's existing `summary` column explains the
3653
+ // failure with no schema change. Safe: a failed attempt is never
3654
+ // restored — restoration needs `success` plus a `validatedAt` stamp.
3655
+ summary: diagnostic,
3487
3656
  outputTokens: 0,
3488
- validatedAt: null,
3489
- ...attemptBase
3657
+ validatedAt: null
3490
3658
  });
3491
- this.opts.onCompactionEnd?.();
3659
+ return errorCode;
3492
3660
  }
3493
3661
  /**
3494
3662
  * Record a `failed` attempt for output that passed `prompt()` but failed
3495
- * structural validation. Logs, emits the attempt event, and signals
3496
- * compaction end.
3663
+ * structural validation. The rejected text is persisted so the next
3664
+ * occurrence is diagnosable from the row alone; signalling compaction end is
3665
+ * the caller's job.
3497
3666
  */
3498
- _emitValidationFailure(attemptBase, errorCode, tokensAfter) {
3667
+ _emitValidationFailure(attemptBase, errorCode, tokensAfter, rejectedText) {
3499
3668
  this.opts.onLog?.(
3500
3669
  `[compaction] Output failed validation (${errorCode}); recording failed attempt`
3501
3670
  );
3502
3671
  this.opts.onCompactionAttempt?.({
3672
+ // Spread first — see _emitThrownFailure.
3673
+ ...attemptBase,
3503
3674
  type: "compaction_attempt",
3504
3675
  status: "failed",
3505
3676
  errorCode,
3506
- summary: "",
3677
+ errorMessage: `Compaction output rejected by validation (${errorCode}): ${rejectedText.length} chars, ${tokensAfter} output tokens`,
3678
+ // The rejected text itself, not a summary — see _emitThrownFailure on
3679
+ // why persisting it here cannot leak into a restored session.
3680
+ summary: truncateDiagnostic(rejectedText),
3507
3681
  outputTokens: tokensAfter,
3508
- validatedAt: null,
3509
- ...attemptBase
3682
+ validatedAt: null
3510
3683
  });
3511
- this.opts.onCompactionEnd?.();
3512
3684
  }
3513
3685
  /**
3514
3686
  * Success path: emit the attempt + snapshot events, update internal state,
@@ -3526,17 +3698,18 @@ var CompactionOrchestrator = class {
3526
3698
  tokensAfter
3527
3699
  };
3528
3700
  this.opts.onCompactionAttempt?.({
3701
+ ...attemptBase,
3529
3702
  type: "compaction_attempt",
3530
3703
  status: "success",
3531
3704
  errorCode: null,
3532
3705
  summary: summaryText,
3533
3706
  outputTokens: tokensAfter,
3534
- validatedAt,
3535
- ...attemptBase
3707
+ validatedAt
3536
3708
  });
3537
3709
  this.opts.onSnapshot?.(snapshot);
3538
3710
  this.lastCompactionSeq = this.currentSeq + 1;
3539
3711
  this.lastCompactionTime = Date.now();
3712
+ this.lastSummary = summaryText;
3540
3713
  this.messagesSinceCompaction = 0;
3541
3714
  this.opts.onCompactionEnd?.();
3542
3715
  if (trigger !== "hibernate") {
@@ -7020,6 +7193,6 @@ function touchSession(state) {
7020
7193
  return { ...state, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
7021
7194
  }
7022
7195
 
7023
- export { CLAUDE_CODE_CREDENTIALS_KEY, COMPILE_MANIFEST_FILENAME, CapabilityRegistry, DEFAULT_CAPABILITY_CALL_TIMEOUT_MS, DEFAULT_COALESCE_MS, DEFAULT_FLOW_MUTATE_CONNECTOR_WAIT_MS, MOUNT_LIST_MAX_DEPTH, MOUNT_LIST_MAX_ENTRIES, MOUNT_READ_DEADLINE_FACTOR, MOUNT_TREE_OP_DEADLINE_FACTOR, MarkdownStreamer, PreInitRingSink, agentDefinitionExists, bootstrapCapabilityRegistry, bootstrapRunnerLogStore, buildAgentResources, buildClientCapabilityHandler, buildConnectorTokenMediator, buildContextSection, buildEnvironmentSection, buildResourcesAvailablePayload, buildStoreSnapshotReplay, builtinCapabilities, capabilityLogInstance, clearPreInitRingSink, clearSession, compileComposition, computeCapabilitySignature, connectorRefreshKind, createAgentSession, createFlowConnectorReadiness, createSessionStimulusBus, defineCapability, deleteSession, dispatchRunnerCapabilityInvocation, emitSystemPromptComposed, ensureClaudeSettingsDisablesConnectors, ensureGitConfigInclude, executeConnectorMutate, extractClaudeAiOauthExpiresAt, getPreInitRingSink, handleMountResourceRequest, handleResourceRequest, hasNonTerminalFlow, hostOpResumeStimulus, installPreInitRingSink, isTerminalFlowStatus, listSessions, loadAgentManifest, loadCompileManifest, loadCompileManifestFromDir, loadSession, loadSessionById, mcpAuthSecretKey, newSession, pickRepointedManager, planFlowMutate, reconcilePendingDecisions, registerActiveFlow, registerCompositionCapabilities, rejectCapabilityOnApprovalDeny, resetRunnerLogStore, resolveAgentComposition, resolveAgentMixins, resolveBinding, resolveCapabilityCallTimeoutMs, resolveCapabilityResult, resolveComposition, resolveFlowMutateConnectorWaitMs, resolveMixin, runAgentChat, saveSession, setCurrentSession, setUpFlowConnector, startAgentServer, stimulusFromMetas, touchSession, validateInputResponse, writeClaudeCodeCredentialsFile };
7024
- //# sourceMappingURL=chunk-DJ2Y5KAJ.js.map
7025
- //# sourceMappingURL=chunk-DJ2Y5KAJ.js.map
7196
+ export { CLAUDE_CODE_CREDENTIALS_KEY, COMPILE_MANIFEST_FILENAME, CapabilityRegistry, DEFAULT_CAPABILITY_CALL_TIMEOUT_MS, DEFAULT_COALESCE_MS, DEFAULT_FLOW_MUTATE_CONNECTOR_WAIT_MS, MOUNT_LIST_MAX_DEPTH, MOUNT_LIST_MAX_ENTRIES, MOUNT_READ_DEADLINE_FACTOR, MOUNT_TREE_OP_DEADLINE_FACTOR, MarkdownStreamer, PreInitRingSink, agentDefinitionExists, bootstrapCapabilityRegistry, bootstrapRunnerLogStore, buildAgentResources, buildClientCapabilityHandler, buildConnectorTokenMediator, buildContextSection, buildEnvironmentSection, buildResourcesAvailablePayload, buildStoreSnapshotReplay, builtinCapabilities, capabilityLogInstance, clearPreInitRingSink, clearSession, compileComposition, computeCapabilitySignature, connectorRefreshKind, createAgentSession, createFlowConnectorReadiness, createSessionStimulusBus, defineCapability, deleteSession, dispatchRunnerCapabilityInvocation, emitSystemPromptComposed, ensureClaudeSettingsDisablesConnectors, ensureGitConfigInclude, executeConnectorMutate, extractClaudeAiOauthExpiresAt, getPreInitRingSink, handleMountResourceRequest, handleResourceRequest, hasNonTerminalFlow, hostOpResumeStimulus, installPreInitRingSink, isTerminalFlowStatus, listSessions, loadAgentManifest, loadCompileManifest, loadCompileManifestFromDir, loadSession, loadSessionById, mcpAuthSecretKey, newSession, nulTailPaddingLength, pickRepointedManager, planFlowMutate, reconcilePendingDecisions, registerActiveFlow, registerCompositionCapabilities, rejectCapabilityOnApprovalDeny, resetRunnerLogStore, resolveAgentComposition, resolveAgentMixins, resolveBinding, resolveCapabilityCallTimeoutMs, resolveCapabilityResult, resolveComposition, resolveFlowMutateConnectorWaitMs, resolveMixin, runAgentChat, saveSession, setCurrentSession, setUpFlowConnector, startAgentServer, stimulusFromMetas, touchSession, validateInputResponse, writeClaudeCodeCredentialsFile };
7197
+ //# sourceMappingURL=chunk-GY5SLCH2.js.map
7198
+ //# sourceMappingURL=chunk-GY5SLCH2.js.map