@sema-agent/client-core 0.83.4 → 0.83.6

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.
@@ -112,6 +112,7 @@ export type SelfHealOutcome = {
112
112
  kind: 'ask-decided-without-card';
113
113
  taskId: string;
114
114
  released: true;
115
+ releaseConfirmedByEngine?: true;
115
116
  } | {
116
117
  kind: 'ask-decided-release-unknown';
117
118
  taskId: string;
@@ -130,6 +131,7 @@ export type SelfHealOutcome = {
130
131
  } | {
131
132
  kind: 'running-cancelled';
132
133
  taskId: string;
134
+ releaseConfirmedByEngine?: true;
133
135
  } | {
134
136
  kind: 'running-cancel-timeout';
135
137
  taskId: string;
@@ -147,6 +149,7 @@ export type SelfHealOutcome = {
147
149
  } | {
148
150
  kind: 'stale-park-cancelled';
149
151
  taskId: string;
152
+ releaseConfirmedByEngine?: true;
150
153
  } | {
151
154
  kind: 'stale-park-cancel-timeout';
152
155
  taskId: string;
@@ -341,8 +341,14 @@ async function askParkArm(taskId, signal, runs, deps) {
341
341
  ...(deps?.signal !== undefined ? { signal: deps.signal } : {}),
342
342
  ...sessionOpts(deps),
343
343
  });
344
- if (release.released)
345
- return { kind: 'ask-decided-without-card', taskId, released: true };
344
+ if (release.released) {
345
+ return {
346
+ kind: 'ask-decided-without-card',
347
+ taskId,
348
+ released: true,
349
+ ...(release.lastHolder === 'released' ? { releaseConfirmedByEngine: true } : {}),
350
+ };
351
+ }
346
352
  if (release.lastStatus !== null && RUNNING_STATES.includes(release.lastStatus)) {
347
353
  return runningChoiceArm(taskId, release.lastStatus, signal, false, runs, deps);
348
354
  }
@@ -447,8 +453,9 @@ async function staleParkArm(taskId, busy, runs, deps) {
447
453
  if (stillGone !== 0)
448
454
  return reopenFailedAfterCard;
449
455
  const verdict = await cancelAndConfirmRelease(taskId, runs, durableGet, deps);
450
- if (verdict.outcome === 'released')
451
- return { kind: 'stale-park-cancelled', taskId };
456
+ if (verdict.outcome === 'released') {
457
+ return { kind: 'stale-park-cancelled', taskId, ...(verdict.engineStatedRelease ? { releaseConfirmedByEngine: true } : {}) };
458
+ }
452
459
  if (verdict.outcome === 'failed') {
453
460
  return { kind: 'stale-park-cancel-failed', taskId, detail: verdict.detail, delivery: verdict.delivery };
454
461
  }
@@ -488,7 +495,7 @@ async function cancelAndConfirmRelease(taskId, durable, durableGet, deps) {
488
495
  ...sessionOpts(deps),
489
496
  });
490
497
  if (verdict.released)
491
- return { outcome: 'released' };
498
+ return { outcome: 'released', engineStatedRelease: verdict.lastHolder === 'released' };
492
499
  if (cancelFailure !== null)
493
500
  return { outcome: 'failed', ...cancelFailure };
494
501
  return {
@@ -580,8 +587,9 @@ async function runningChoiceArm(taskId, status, busy, statusFromWire, runs, deps
580
587
  }
581
588
  if (choice === 'cancel' && canCancel && runs?.cancel !== undefined && runs.get !== undefined) {
582
589
  const verdict = await cancelAndConfirmRelease(taskId, runs, runs.get, deps);
583
- if (verdict.outcome === 'released')
584
- return { kind: 'running-cancelled', taskId };
590
+ if (verdict.outcome === 'released') {
591
+ return { kind: 'running-cancelled', taskId, ...(verdict.engineStatedRelease ? { releaseConfirmedByEngine: true } : {}) };
592
+ }
585
593
  if (verdict.outcome === 'failed') {
586
594
  return { kind: 'running-cancel-failed', taskId, detail: verdict.detail, delivery: verdict.delivery };
587
595
  }
@@ -690,8 +698,12 @@ function injectedSubmissionRow(outcome, following = false) {
690
698
  return (`${lead} is on hold: this session is busy with an earlier reply${id} that is waiting on a decision. ` +
691
699
  `sema kept the message queued and will send it after you answer the open card.`);
692
700
  case 'resending':
693
- return (`${lead} was held back because this session was busy with an earlier reply${id}; the session is free again, ` +
694
- `so sema is sending the message now — nothing for you to do.`);
701
+ return 'releaseConfirmedByEngine' in outcome && outcome.releaseConfirmedByEngine === true
702
+ ? `${lead} was held back because this session was busy with an earlier reply${id}; the session is free again, ` +
703
+ `so sema is sending the message now — nothing for you to do.`
704
+ : `${lead} was held back because this session was busy with an earlier reply${id}; that reply is now reported ` +
705
+ `as finished, so sema is sending the message now — nothing for you to do (if the session has not quite ` +
706
+ `freed up yet, it may be held back once more).`;
695
707
  case 'handed-off':
696
708
  return following
697
709
  ? `${lead} was passed to the reply already in progress${id} instead of starting a new one. ` +
@@ -749,8 +761,14 @@ function activeRunSelfHealBaseRow(outcome, signal, wayOut, following = false, ke
749
761
  `reopened it. Answer it and send your message again. (sema did NOT cancel the run: cancelling ` +
750
762
  `would have thrown the plan away on your behalf.)`);
751
763
  case 'ask-decided-without-card':
764
+ if (outcome.releaseConfirmedByEngine === true) {
765
+ return (`The previous turn was parked on an approval that your permission rules decided on their own (no card was ` +
766
+ `needed); run ${outcome.taskId} resumed and the engine confirmed it is no longer holding this session — ` +
767
+ `sema is re-sending your message.`);
768
+ }
752
769
  return (`The previous turn was parked on an approval that your permission rules decided on their own (no card was ` +
753
- `needed); run ${outcome.taskId} resumed and has since finished — sema is re-sending your message.`);
770
+ `needed); run ${outcome.taskId} resumed and has since finished — sema is re-sending your message; if that ` +
771
+ `run has not fully let go of the session yet, you may have to send it once more.`);
754
772
  case 'ask-decided-release-unknown':
755
773
  return (`The previous turn was parked on an approval that your permission rules decided on their own (no card was ` +
756
774
  `needed), so run ${outcome.taskId} should be resuming` +
@@ -838,8 +856,12 @@ function activeRunSelfHealBaseRow(outcome, signal, wayOut, following = false, ke
838
856
  `cancel that run. That run may or may not have received your message — watch what it does next ` +
839
857
  `before sending it again.`);
840
858
  case 'running-cancelled':
841
- return (`You chose to cancel run ${outcome.taskId}. The engine confirmed it is no longer holding this session, ` +
842
- `so sema is sending your message now.`);
859
+ return outcome.releaseConfirmedByEngine === true
860
+ ? `You chose to cancel run ${outcome.taskId}. The engine confirmed it is no longer holding this session, ` +
861
+ `so sema is sending your message now.`
862
+ : `You chose to cancel run ${outcome.taskId}. The engine now reports that run as finished, so sema is ` +
863
+ `sending your message now; if that run has not fully let go of the session yet, you may have to send ` +
864
+ `it once more.`;
843
865
  case 'running-cancel-timeout': {
844
866
  const waited = `${String(Math.max(1, Math.round(outcome.waitedMs / 1000)))}s`;
845
867
  if (outcome.aborted) {
@@ -872,6 +894,11 @@ function activeRunSelfHealBaseRow(outcome, signal, wayOut, following = false, ke
872
894
  `not allowed to read. Either way sema has nothing it can act on here, so it did NOT cancel anything. ` +
873
895
  `Your message was NOT sent; send it again (if the session really is free it will just run), or ${wayOut}.`);
874
896
  case 'stale-park-cancelled':
897
+ if (outcome.releaseConfirmedByEngine === true) {
898
+ return (`Run ${outcome.taskId} was parked on an approval that no longer exists on the engine, so there was ` +
899
+ `nothing left for you to answer. You chose to cancel that run, and the engine confirmed it is no longer ` +
900
+ `holding this session, so sema is sending your message again now.`);
901
+ }
875
902
  return (`Run ${outcome.taskId} was parked on an approval that no longer exists on the engine, so there was ` +
876
903
  `nothing left for you to answer. You chose to cancel that run: the engine now reports it as finished, ` +
877
904
  `so it will not resume — whatever that turn had left to do is not coming back. sema is sending your ` +
@@ -30,7 +30,7 @@ export const MIGRATED_COMPENSATIONS = [
30
30
  },
31
31
  {
32
32
  id: 'T36',
33
- what: '子代永不发终态 tick ⇒ 四处防御 sweep 兜住面板行,不让它们永远转圈',
33
+ what: '子代终态 tick 缺席时(老服务端 / 丢帧 / 断流)四处防御 sweep 兜住面板行,不让它们永远转圈;终态 tick 在场时按它落终态',
34
34
  disposition: 'in-library',
35
35
  libraryHalf: 'adapt.ts settlePanelTasks 的四个调用点(tool_end 关卡 / result / turn 末 / abort)',
36
36
  chromeArm: 'inline_task_stats',
@@ -6,6 +6,7 @@ export interface DisplayFace {
6
6
  readonly unsafe: RegExp | null;
7
7
  readonly fold: boolean;
8
8
  readonly mark: DisplayMark;
9
+ readonly keepBlanks?: boolean;
9
10
  }
10
11
  export declare const LEGACY_ESCAPE_FACE: DisplayFace;
11
12
  export declare const LEGACY_LABEL_FACE: DisplayFace;
@@ -20,5 +21,17 @@ export interface DisplayUntrustedOptions {
20
21
  readonly keepLayout?: boolean;
21
22
  readonly mark?: DisplayMark;
22
23
  readonly max?: number;
24
+ readonly escapeBackslashes?: boolean;
25
+ readonly blanks?: boolean;
26
+ }
27
+ export interface DisplayMarkSpan {
28
+ readonly start: number;
29
+ readonly end: number;
30
+ readonly codePoint: number;
31
+ }
32
+ export interface DisplayUntrustedMarked {
33
+ readonly text: string;
34
+ readonly marks: readonly DisplayMarkSpan[];
23
35
  }
24
36
  export declare function displayUntrusted(text: string, opts?: DisplayUntrustedOptions): string;
37
+ export declare function displayUntrustedMarks(text: string, opts?: DisplayUntrustedOptions): DisplayUntrustedMarked;