@sema-agent/client-core 0.86.0 → 0.88.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.
- package/CHANGELOG.md +128 -0
- package/README.md +18 -12
- package/dist/adapt/arms.js +9 -0
- package/dist/adapter/downstream/eventToSdkMessage.js +14 -1
- package/dist/adapter/downstream/terminalToSdkResult.js +4 -1
- package/dist/adapter/downstream/wiringManifestView.d.ts +2 -0
- package/dist/adapter/downstream/wiringManifestView.js +1 -0
- package/dist/adapter/runStream.js +75 -2
- package/dist/adapter/types.d.ts +3 -0
- package/dist/decideReceipt.d.ts +1 -1
- package/dist/decideReceipt.js +1 -1
- package/dist/detachWire.d.ts +6 -1
- package/dist/detachWire.js +22 -1
- package/dist/displayUntrusted.d.ts +4 -0
- package/dist/displayUntrusted.js +1657 -573
- package/dist/engineErrorCodes.d.ts +2 -0
- package/dist/engineErrorCodes.js +1 -0
- package/dist/engineNoticeCodes.d.ts +20 -0
- package/dist/engineNoticeCodes.js +71 -0
- package/dist/engineWireFor.d.ts +1 -0
- package/dist/engineWireFor.js +1 -1
- package/dist/gateOutcome.d.ts +4 -0
- package/dist/gateOutcome.js +5 -0
- package/dist/generated/engineFactTables.d.ts +1 -0
- package/dist/generated/engineFactTables.js +3 -0
- package/dist/generated/engineNoticeTables.js +2 -0
- package/dist/hitl/crashConverged.d.ts +2 -1
- package/dist/hitl/crashConverged.js +23 -3
- package/dist/hitl/hitlBridge.d.ts +4 -0
- package/dist/hitl/hitlBridge.js +6 -0
- package/dist/hitl/parkResolver.js +17 -12
- package/dist/hitl/planReviewWire.js +30 -10
- package/dist/hitl/suspendedReopen.d.ts +7 -0
- package/dist/hitl/suspendedReopen.js +38 -7
- package/dist/hitl/toolApprovalWire.js +4 -5
- package/dist/index.d.ts +7 -0
- package/dist/index.js +4 -0
- package/dist/promptDelivery.d.ts +20 -0
- package/dist/promptDelivery.js +153 -0
- package/dist/registryConflict.d.ts +3 -0
- package/dist/registryConflict.js +44 -0
- package/dist/request/taskRequest.d.ts +1 -0
- package/dist/request/taskRequest.js +25 -1
- package/dist/resumeRefusalCopy.d.ts +8 -6
- package/dist/resumeRefusalCopy.js +41 -19
- package/dist/rewindArchiveCapability.js +5 -0
- package/dist/seam.d.ts +12 -1
- package/dist/seam.js +7 -0
- package/dist/sessionMemoryErase.d.ts +76 -0
- package/dist/sessionMemoryErase.js +432 -0
- package/dist/subagent/engineSubagentResume.js +2 -1
- package/dist/toolHistoryMismatch.d.ts +63 -0
- package/dist/toolHistoryMismatch.js +425 -0
- package/dist/workflowClient.d.ts +3 -2
- package/dist/workflowClient.js +3 -3
- package/docs/INTEGRATION-CLIENTS.md +598 -13
- package/package.json +2 -2
|
@@ -48,6 +48,8 @@ export declare const REWIND_ERROR_CODE_PREFIXES: readonly ["resume_at.", "rewind
|
|
|
48
48
|
export declare function isRewindFamilyCode(code: string | undefined): boolean;
|
|
49
49
|
export declare const RESUME_USAGE_WINDOW_EXHAUSTED = "resume.usage_window_exhausted";
|
|
50
50
|
export declare const RESUME_PREFLIGHT_REJECTED = "resume.preflight_rejected";
|
|
51
|
+
export declare const RESUME_SESSION_NOT_FOUND = "resume.session_not_found";
|
|
52
|
+
export type StatusDerivedCoarseCode = (typeof STATUS_DERIVED_COARSE_CODES)[number];
|
|
51
53
|
export declare const RESUME_PLACEMENT_MISMATCH = "resume.placement_mismatch";
|
|
52
54
|
export declare const RESUME_CONTEXT_UNAVAILABLE = "conflict.resume_context_unavailable";
|
|
53
55
|
export declare const RESUME_RETRY_LATER_CODES: readonly string[];
|
package/dist/engineErrorCodes.js
CHANGED
|
@@ -106,6 +106,7 @@ export function isRewindFamilyCode(code) {
|
|
|
106
106
|
}
|
|
107
107
|
export const RESUME_USAGE_WINDOW_EXHAUSTED = 'resume.usage_window_exhausted';
|
|
108
108
|
export const RESUME_PREFLIGHT_REJECTED = 'resume.preflight_rejected';
|
|
109
|
+
export const RESUME_SESSION_NOT_FOUND = 'resume.session_not_found';
|
|
109
110
|
export const RESUME_PLACEMENT_MISMATCH = 'resume.placement_mismatch';
|
|
110
111
|
export const RESUME_CONTEXT_UNAVAILABLE = 'conflict.resume_context_unavailable';
|
|
111
112
|
export const RESUME_RETRY_LATER_CODES = Object.freeze([
|
|
@@ -137,6 +137,24 @@ export interface LegacyModeSeedMigratedFactsView {
|
|
|
137
137
|
runId: string;
|
|
138
138
|
}
|
|
139
139
|
export declare function readLegacyModeSeedMigrated(notice: unknown): LegacyModeSeedMigratedFactsView | undefined;
|
|
140
|
+
export interface ToolTurnRepairView {
|
|
141
|
+
form: string;
|
|
142
|
+
toolCallIds: readonly string[];
|
|
143
|
+
}
|
|
144
|
+
export interface ToolTurnRepairedFactsView {
|
|
145
|
+
repairs: readonly ToolTurnRepairView[];
|
|
146
|
+
sessionId: string;
|
|
147
|
+
runId: string;
|
|
148
|
+
}
|
|
149
|
+
export declare function readToolTurnRepaired(notice: unknown): ToolTurnRepairedFactsView | undefined;
|
|
150
|
+
export interface ModelUnreachableFactsView {
|
|
151
|
+
code: string;
|
|
152
|
+
targetHost: string;
|
|
153
|
+
proxyInUse?: string;
|
|
154
|
+
remedy: string;
|
|
155
|
+
sessionId: string;
|
|
156
|
+
}
|
|
157
|
+
export declare function readModelUnreachable(notice: unknown): ModelUnreachableFactsView | undefined;
|
|
140
158
|
export declare const ENGINE_NOTICE_FACT_READERS: Readonly<{
|
|
141
159
|
readonly 'mcp.injection_dropped': typeof readMcpInjectionDrop;
|
|
142
160
|
readonly 'delegation.ask_unresolvable': typeof readAskUnresolvable;
|
|
@@ -153,6 +171,8 @@ export declare const ENGINE_NOTICE_FACT_READERS: Readonly<{
|
|
|
153
171
|
readonly 'permission.ask_released_by_mode': typeof readAskReleasedByMode;
|
|
154
172
|
readonly 'permission.read_deny_unapplied': typeof readReadDenyUnapplied;
|
|
155
173
|
readonly 'resume.legacy_mode_seed_migrated': typeof readLegacyModeSeedMigrated;
|
|
174
|
+
readonly 'context.tool_turn_repaired': typeof readToolTurnRepaired;
|
|
175
|
+
readonly 'server.model_unreachable': typeof readModelUnreachable;
|
|
156
176
|
}>;
|
|
157
177
|
type FactReaderTable = typeof ENGINE_NOTICE_FACT_READERS;
|
|
158
178
|
export type EngineNoticeFactsCode = keyof FactReaderTable;
|
|
@@ -7,6 +7,7 @@ export const SERVER_NOTICE_AUDIENCE = Object.freeze({
|
|
|
7
7
|
'instructions.source_changed': 'user',
|
|
8
8
|
'memory.layer_locked_legacy': 'operator',
|
|
9
9
|
'session.records_skipped': 'user',
|
|
10
|
+
'server.model_unreachable': 'user',
|
|
10
11
|
});
|
|
11
12
|
function audienceRow(table, code) {
|
|
12
13
|
return Object.hasOwn(table, code) ? table[code] : undefined;
|
|
@@ -483,6 +484,74 @@ function readLegacyModeSeedMigratedOf(notice) {
|
|
|
483
484
|
const permissionMode = nonEmpty(optionalSeat(mo, 'permissionMode'));
|
|
484
485
|
return { ...(permissionMode !== undefined ? { permissionMode } : {}), droppedKeys, sessionId, runId };
|
|
485
486
|
}
|
|
487
|
+
export function readToolTurnRepaired(notice) {
|
|
488
|
+
return guardedRead(notice, readToolTurnRepairedOf);
|
|
489
|
+
}
|
|
490
|
+
function ownSeat(o, key) {
|
|
491
|
+
return Object.hasOwn(o, key) ? o[key] : undefined;
|
|
492
|
+
}
|
|
493
|
+
function optionalOwnSeat(o, key) {
|
|
494
|
+
try {
|
|
495
|
+
return ownSeat(o, key);
|
|
496
|
+
}
|
|
497
|
+
catch {
|
|
498
|
+
return undefined;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
function readToolTurnRepairedOf(notice) {
|
|
502
|
+
if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
|
|
503
|
+
return undefined;
|
|
504
|
+
const n = notice;
|
|
505
|
+
if (n.code !== 'context.tool_turn_repaired')
|
|
506
|
+
return undefined;
|
|
507
|
+
const d = n.detail;
|
|
508
|
+
if (typeof d !== 'object' || d === null || Array.isArray(d))
|
|
509
|
+
return undefined;
|
|
510
|
+
const o = d;
|
|
511
|
+
const rawRepairs = ownSeat(o, 'repairs');
|
|
512
|
+
if (!Array.isArray(rawRepairs) || rawRepairs.length === 0)
|
|
513
|
+
return undefined;
|
|
514
|
+
const count = rawRepairs.length;
|
|
515
|
+
const repairs = [];
|
|
516
|
+
for (let i = 0; i < count; i++) {
|
|
517
|
+
const item = rawRepairs[i];
|
|
518
|
+
if (typeof item !== 'object' || item === null || Array.isArray(item))
|
|
519
|
+
return undefined;
|
|
520
|
+
const it = item;
|
|
521
|
+
const form = nonEmpty(ownSeat(it, 'form'));
|
|
522
|
+
const toolCallIds = nameList(ownSeat(it, 'toolCallIds'));
|
|
523
|
+
if (form === undefined || toolCallIds === undefined || toolCallIds.length === 0)
|
|
524
|
+
return undefined;
|
|
525
|
+
repairs.push(Object.freeze({ form, toolCallIds }));
|
|
526
|
+
}
|
|
527
|
+
const sessionId = nonEmpty(ownSeat(o, 'sessionId'));
|
|
528
|
+
const runId = nonEmpty(ownSeat(o, 'runId'));
|
|
529
|
+
if (sessionId === undefined || runId === undefined)
|
|
530
|
+
return undefined;
|
|
531
|
+
return { repairs: Object.freeze(repairs), sessionId, runId };
|
|
532
|
+
}
|
|
533
|
+
export function readModelUnreachable(notice) {
|
|
534
|
+
return guardedRead(notice, readModelUnreachableOf);
|
|
535
|
+
}
|
|
536
|
+
function readModelUnreachableOf(notice) {
|
|
537
|
+
if (typeof notice !== 'object' || notice === null || Array.isArray(notice))
|
|
538
|
+
return undefined;
|
|
539
|
+
const n = notice;
|
|
540
|
+
if (n.code !== 'server.model_unreachable')
|
|
541
|
+
return undefined;
|
|
542
|
+
const d = n.detail;
|
|
543
|
+
if (typeof d !== 'object' || d === null || Array.isArray(d))
|
|
544
|
+
return undefined;
|
|
545
|
+
const o = d;
|
|
546
|
+
const code = nonEmpty(ownSeat(o, 'code'));
|
|
547
|
+
const targetHost = nonEmpty(ownSeat(o, 'targetHost'));
|
|
548
|
+
const remedy = nonEmpty(ownSeat(o, 'remedy'));
|
|
549
|
+
const sessionId = nonEmpty(ownSeat(o, 'sessionId'));
|
|
550
|
+
if (code === undefined || targetHost === undefined || remedy === undefined || sessionId === undefined)
|
|
551
|
+
return undefined;
|
|
552
|
+
const proxyInUse = nonEmpty(optionalOwnSeat(o, 'proxyInUse'));
|
|
553
|
+
return { code, targetHost, ...(proxyInUse !== undefined ? { proxyInUse } : {}), remedy, sessionId };
|
|
554
|
+
}
|
|
486
555
|
export const ENGINE_NOTICE_FACT_READERS = Object.freeze({
|
|
487
556
|
'mcp.injection_dropped': readMcpInjectionDrop,
|
|
488
557
|
'delegation.ask_unresolvable': readAskUnresolvable,
|
|
@@ -499,6 +568,8 @@ export const ENGINE_NOTICE_FACT_READERS = Object.freeze({
|
|
|
499
568
|
'permission.ask_released_by_mode': readAskReleasedByMode,
|
|
500
569
|
'permission.read_deny_unapplied': readReadDenyUnapplied,
|
|
501
570
|
'resume.legacy_mode_seed_migrated': readLegacyModeSeedMigrated,
|
|
571
|
+
'context.tool_turn_repaired': readToolTurnRepaired,
|
|
572
|
+
'server.model_unreachable': readModelUnreachable,
|
|
502
573
|
});
|
|
503
574
|
const _factReaderTablePin = true;
|
|
504
575
|
void _factReaderTablePin;
|
package/dist/engineWireFor.d.ts
CHANGED
|
@@ -40,4 +40,5 @@ export type EngineWireNoAnswerKind = 'deadline' | 'time-limit' | 'connection-los
|
|
|
40
40
|
export declare function noAnswerKindOf(e: object | null | undefined): EngineWireNoAnswerKind | null;
|
|
41
41
|
export declare function noAnswerDetailFrom(e: object | null | undefined): string | null;
|
|
42
42
|
export declare function sendOnce<T>(signal: AbortSignal | null | undefined, run: () => Promise<T>): Promise<T>;
|
|
43
|
+
export declare function provablyNotSent(e: object | null | undefined): boolean;
|
|
43
44
|
export declare function settleInjected<T>(ms: number, signal: AbortSignal | null | undefined, run: (signal: AbortSignal) => Promise<T>): Promise<T>;
|
package/dist/engineWireFor.js
CHANGED
|
@@ -331,7 +331,7 @@ export async function sendOnce(signal, run) {
|
|
|
331
331
|
throw error;
|
|
332
332
|
}
|
|
333
333
|
}
|
|
334
|
-
function provablyNotSent(e) {
|
|
334
|
+
export function provablyNotSent(e) {
|
|
335
335
|
try {
|
|
336
336
|
return e !== null && typeof e === 'object' && (markedNotSent(e) || failedBeforeSend(e));
|
|
337
337
|
}
|
package/dist/gateOutcome.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DeniedBy, Settlement } from '@sema-agent/sdk';
|
|
2
2
|
import { type CcToolDenialKind } from './gateVocabulary.js';
|
|
3
|
+
import { CORE_MODE_RELEASE_REASONS } from './generated/engineFactTables.js';
|
|
3
4
|
export type GateDispositionView = {
|
|
4
5
|
kind: 'allowed';
|
|
5
6
|
classifier?: GateClassifierRoundView;
|
|
@@ -31,6 +32,9 @@ export interface GateModeReleaseView {
|
|
|
31
32
|
mandate?: string;
|
|
32
33
|
reason?: string;
|
|
33
34
|
}
|
|
35
|
+
export declare const GATE_MODE_RELEASE_REASON_WORDS: readonly ["rule_unreadable"];
|
|
36
|
+
export type GateModeReleaseReasonWord = (typeof CORE_MODE_RELEASE_REASONS)[number];
|
|
37
|
+
export declare function isGateModeReleaseReasonWord(v: unknown): v is GateModeReleaseReasonWord;
|
|
34
38
|
export interface SettlementWhoView {
|
|
35
39
|
party: string;
|
|
36
40
|
approver?: string;
|
package/dist/gateOutcome.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { ccToolDenialKindForSettledBy, isCcToolDenialKind, isGateDeniedByWord } from './gateVocabulary.js';
|
|
2
2
|
import { GATE_PARKED_ERROR_CODE } from './engineErrorCodes.js';
|
|
3
|
+
import { CORE_MODE_RELEASE_REASONS } from './generated/engineFactTables.js';
|
|
3
4
|
function str(v) {
|
|
4
5
|
return typeof v === 'string' && v.length > 0 ? v : undefined;
|
|
5
6
|
}
|
|
7
|
+
export const GATE_MODE_RELEASE_REASON_WORDS = CORE_MODE_RELEASE_REASONS;
|
|
8
|
+
export function isGateModeReleaseReasonWord(v) {
|
|
9
|
+
return typeof v === 'string' && CORE_MODE_RELEASE_REASONS.includes(v);
|
|
10
|
+
}
|
|
6
11
|
export const SETTLEMENT_KIND_WORDS = Object.freeze([
|
|
7
12
|
'human_allowed',
|
|
8
13
|
'human_refused',
|
|
@@ -8,3 +8,4 @@ export declare const CORE_DENIED_BY_VALUES: readonly ["policy", "hook", "org", "
|
|
|
8
8
|
export declare const CORE_PERMISSION_MODE_FOLD_REASONS: readonly string[];
|
|
9
9
|
export declare const CORE_ENGINE_CARD_TYPES: readonly string[];
|
|
10
10
|
export declare const CORE_TOOL_DECLARATION_CODES: readonly string[];
|
|
11
|
+
export declare const CORE_MODE_RELEASE_REASONS: readonly ["rule_unreadable"];
|
|
@@ -65,6 +65,7 @@ export const CORE_ENGINE_NOTICE_CODES = Object.freeze([
|
|
|
65
65
|
"route.base_url_changed_key_unchanged",
|
|
66
66
|
"route.response_model_mismatch",
|
|
67
67
|
"route.tool_call_id_folded",
|
|
68
|
+
"context.tool_turn_repaired",
|
|
68
69
|
"task.user_steer_undrained",
|
|
69
70
|
"task.user_followup_undrained",
|
|
70
71
|
"steering.parked_input_blocked",
|
|
@@ -147,6 +148,7 @@ export const CORE_NOTICE_AUDIENCE = Object.freeze({
|
|
|
147
148
|
"route.base_url_changed_key_unchanged": "operator",
|
|
148
149
|
"route.response_model_mismatch": "operator",
|
|
149
150
|
"route.tool_call_id_folded": "operator",
|
|
151
|
+
"context.tool_turn_repaired": "operator",
|
|
150
152
|
"task.user_steer_undrained": "user",
|
|
151
153
|
"task.user_followup_undrained": "user",
|
|
152
154
|
"steering.parked_input_blocked": "user",
|
|
@@ -8,12 +8,13 @@ export interface CrashConvergedRow {
|
|
|
8
8
|
readonly ts: number;
|
|
9
9
|
readonly expiresAtMs: number;
|
|
10
10
|
readonly decision: 'denied';
|
|
11
|
-
readonly cause: 'crashed_before_park';
|
|
11
|
+
readonly cause: 'crashed_before_park' | 'shutdown_before_park';
|
|
12
12
|
readonly orphanState: CrashConvergedOrphanState;
|
|
13
13
|
readonly originalDecision?: 'approve';
|
|
14
14
|
readonly decidedAtMs?: number;
|
|
15
15
|
readonly convergedAtMs: number;
|
|
16
16
|
readonly resumeSafe: boolean;
|
|
17
|
+
readonly needsHumanReason?: 'approved_then_interrupted' | 'pending_unsafe' | 'unstable_row' | 'contradictory';
|
|
17
18
|
}
|
|
18
19
|
export interface ApprovalsListEnvelope {
|
|
19
20
|
pending: PendingCheckpoint[];
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
const CRASH_CONVERGED_CAUSE_WORDS = Object.freeze({
|
|
2
|
+
crashed_before_park: true,
|
|
3
|
+
shutdown_before_park: true,
|
|
4
|
+
});
|
|
5
|
+
const isCrashConvergedCause = (v) => typeof v === 'string' && Object.hasOwn(CRASH_CONVERGED_CAUSE_WORDS, v);
|
|
1
6
|
const isString = (v) => typeof v === 'string';
|
|
2
7
|
const isNumber = (v) => typeof v === 'number';
|
|
3
8
|
const nonEmptyString = (v) => typeof v === 'string' && v.length > 0;
|
|
@@ -45,7 +50,7 @@ function readCrashConvergedRow(v) {
|
|
|
45
50
|
return null;
|
|
46
51
|
if (o.decision !== 'denied')
|
|
47
52
|
return null;
|
|
48
|
-
if (o.cause
|
|
53
|
+
if (!isCrashConvergedCause(o.cause))
|
|
49
54
|
return null;
|
|
50
55
|
if (o.orphanState !== 'pending' && o.orphanState !== 'decided')
|
|
51
56
|
return null;
|
|
@@ -71,6 +76,15 @@ function readCrashConvergedRow(v) {
|
|
|
71
76
|
return null;
|
|
72
77
|
}
|
|
73
78
|
}
|
|
79
|
+
function needsHumanReasonOf(reading) {
|
|
80
|
+
if (reading.unstable)
|
|
81
|
+
return 'unstable_row';
|
|
82
|
+
if (reading.orphanState === 'pending' ? reading.hasApprovalEvidence : reading.resumeSafe === true)
|
|
83
|
+
return 'contradictory';
|
|
84
|
+
if (reading.orphanState === 'decided')
|
|
85
|
+
return 'approved_then_interrupted';
|
|
86
|
+
return 'pending_unsafe';
|
|
87
|
+
}
|
|
74
88
|
export function projectCrashConverged(env) {
|
|
75
89
|
const resumeSafe = [];
|
|
76
90
|
const needsHuman = [];
|
|
@@ -96,10 +110,16 @@ export function projectCrashConverged(env) {
|
|
|
96
110
|
}
|
|
97
111
|
const row = reading.row;
|
|
98
112
|
const consistentlyUnexecuted = reading.orphanState === 'pending' && !reading.hasApprovalEvidence;
|
|
99
|
-
if (!reading.unstable && consistentlyUnexecuted && reading.resumeSafe === true)
|
|
113
|
+
if (!reading.unstable && consistentlyUnexecuted && reading.resumeSafe === true) {
|
|
114
|
+
Reflect.deleteProperty(row, 'needsHumanReason');
|
|
100
115
|
resumeSafe.push(row);
|
|
101
|
-
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
Object.defineProperty(row, 'needsHumanReason', {
|
|
119
|
+
value: needsHumanReasonOf(reading), enumerable: true, writable: true, configurable: true,
|
|
120
|
+
});
|
|
102
121
|
needsHuman.push(row);
|
|
122
|
+
}
|
|
103
123
|
}
|
|
104
124
|
}
|
|
105
125
|
catch {
|
|
@@ -47,6 +47,10 @@ export type PlanReviewModeAfter = (typeof PLAN_REVIEW_MODE_AFTER_WORDS)[number];
|
|
|
47
47
|
export declare function isPlanReviewModeAfter(v: string | undefined): v is PlanReviewModeAfter;
|
|
48
48
|
export type HitlSafetyCode = 'binding_mismatch' | 'no_pending' | 'wrong_gate' | 'bad_plan_edit' | 'bad_plan_mode' | 'empty_answer';
|
|
49
49
|
export type HitlFailureStage = 'fetch' | 'input' | 'card' | 'decide' | 'orchestration';
|
|
50
|
+
export declare const NO_APPROVAL_CARD_PORT_REASON = "no approval card port installed (print/non-REPL mode, or host forgot installApprovalCardPort)";
|
|
51
|
+
export declare const APPROVAL_CARD_PORT_KEY_MISMATCH_REASON = "no approval card port installed for the default session key, but a non-default sessionKey has one \u2014 likely a keyed-install/default-read mismatch (installApprovalCardPortFor vs the zero-arg default-key read), not a missing install";
|
|
52
|
+
export declare const NO_QUESTION_OVERLAY_REASON = "no question overlay mounted (print/non-REPL mode)";
|
|
53
|
+
export declare function isNoDecisionSurfaceReason(reason: string): boolean;
|
|
50
54
|
export interface HitlDecideDenyOutcome {
|
|
51
55
|
decision: 'deny';
|
|
52
56
|
reason?: string | undefined;
|
package/dist/hitl/hitlBridge.js
CHANGED
|
@@ -25,6 +25,12 @@ export const PLAN_REVIEW_MODE_AFTER_WORDS = Object.freeze(['default', 'acceptEdi
|
|
|
25
25
|
export function isPlanReviewModeAfter(v) {
|
|
26
26
|
return v !== undefined && PLAN_REVIEW_MODE_AFTER_WORDS.includes(v);
|
|
27
27
|
}
|
|
28
|
+
export const NO_APPROVAL_CARD_PORT_REASON = 'no approval card port installed (print/non-REPL mode, or host forgot installApprovalCardPort)';
|
|
29
|
+
export const APPROVAL_CARD_PORT_KEY_MISMATCH_REASON = 'no approval card port installed for the default session key, but a non-default sessionKey has one — likely a keyed-install/default-read mismatch (installApprovalCardPortFor vs the zero-arg default-key read), not a missing install';
|
|
30
|
+
export const NO_QUESTION_OVERLAY_REASON = 'no question overlay mounted (print/non-REPL mode)';
|
|
31
|
+
export function isNoDecisionSurfaceReason(reason) {
|
|
32
|
+
return reason === NO_APPROVAL_CARD_PORT_REASON || reason === APPROVAL_CARD_PORT_KEY_MISMATCH_REASON || reason === NO_QUESTION_OVERLAY_REASON;
|
|
33
|
+
}
|
|
28
34
|
export class HitlSafetyError extends Error {
|
|
29
35
|
code;
|
|
30
36
|
constructor(message, code) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { putOwnKey } from '../ownKey.js';
|
|
2
|
-
import { DecideTransportRetryExhaustedError, HitlBridge, HitlSafetyError, findPendingForTask, readDecideCurrentPending, readWireErrorCode, } from './hitlBridge.js';
|
|
2
|
+
import { DecideTransportRetryExhaustedError, HitlBridge, HitlSafetyError, NO_QUESTION_OVERLAY_REASON, findPendingForTask, isNoDecisionSurfaceReason, readDecideCurrentPending, readWireErrorCode, } from './hitlBridge.js';
|
|
3
3
|
import { PARKED_RESUME_STARTUP_FAILED, RESUME_POLICY_FOLD_CODE, isDecideParkMovedCode } from '../engineErrorCodes.js';
|
|
4
4
|
import { publishQuestionFrame, registerLocalQuestionResponder, hasQuestionOverlay, } from '../liveQuestionStore.js';
|
|
5
5
|
import { hostLog } from '../host.js';
|
|
@@ -75,7 +75,7 @@ export function toAnsweredOutput(questions, answer) {
|
|
|
75
75
|
}
|
|
76
76
|
async function surfaceGateAndDecide(deps, taskId, askArgsByCall, signal, parkGatedCallId, onPresented) {
|
|
77
77
|
if (!hasQuestionOverlay()) {
|
|
78
|
-
return { kind: 'failed', stage: 'card', reason:
|
|
78
|
+
return { kind: 'failed', stage: 'card', reason: NO_QUESTION_OVERLAY_REASON };
|
|
79
79
|
}
|
|
80
80
|
const found = await findPendingForTask(deps.client, taskId, isAskTool, signal ? { signal } : undefined, parkGatedCallId, (row) => isAskTool(typeof row.toolName === 'string' ? row.toolName : undefined));
|
|
81
81
|
if (!found.ok)
|
|
@@ -301,7 +301,8 @@ export async function resolvePark(park, ctx) {
|
|
|
301
301
|
: outcome.kind === 'retracted'
|
|
302
302
|
? 'the approval card was retracted by the host without a decision (nothing was sent; the run stays parked and remains decidable elsewhere)'
|
|
303
303
|
: undefined;
|
|
304
|
-
|
|
304
|
+
const noDecisionSurface = outcome.kind === 'failed' && outcome.stage === 'card' && isNoDecisionSurfaceReason(outcome.reason);
|
|
305
|
+
return { kind: 'failsoft', events: failsoftEvents(park, ctx, outcome.kind === 'aborted', failedReason, undefined, noDecisionSurface) };
|
|
305
306
|
}
|
|
306
307
|
led.dropHeldForDecidedPark(outcome.gatedCallId, park.gatedCallId);
|
|
307
308
|
if (outcome.gatedCallId) {
|
|
@@ -324,7 +325,15 @@ export async function resolvePark(park, ctx) {
|
|
|
324
325
|
...(handoffTaskId !== undefined ? { handoffTaskId } : {}),
|
|
325
326
|
};
|
|
326
327
|
}
|
|
327
|
-
function
|
|
328
|
+
function failsoftReasonSentence(park, failedReason, terminal) {
|
|
329
|
+
if (terminal !== undefined)
|
|
330
|
+
return terminal.errorMessage;
|
|
331
|
+
if (failedReason === undefined)
|
|
332
|
+
return undefined;
|
|
333
|
+
return (`${park.gate === 'fs' ? 'Tool approval' : 'AskUserQuestion'} gate could not be answered: ${failedReason}` +
|
|
334
|
+
' — the run is still parked on this approval: decide it on the card when it is shown again, or cancel the run.');
|
|
335
|
+
}
|
|
336
|
+
function failsoftEvents(park, ctx, gateAbortedByUser, failedReason, terminal, noDecisionSurface = false) {
|
|
328
337
|
const events = [
|
|
329
338
|
...flushHeldWithInterruptRewrite(ctx.led, {
|
|
330
339
|
terminal: park.pendingDone,
|
|
@@ -332,19 +341,15 @@ function failsoftEvents(park, ctx, gateAbortedByUser, failedReason, terminal) {
|
|
|
332
341
|
gateAbortedByUser,
|
|
333
342
|
}),
|
|
334
343
|
];
|
|
344
|
+
const reason = failsoftReasonSentence(park, failedReason, terminal);
|
|
335
345
|
if (park.pendingDone) {
|
|
336
|
-
events.push(park.pendingDone);
|
|
346
|
+
events.push(reason === undefined || noDecisionSurface ? park.pendingDone : { ...park.pendingDone, _sema_park_failed_reason: reason });
|
|
337
347
|
}
|
|
338
348
|
else if (terminal !== undefined) {
|
|
339
349
|
events.push({ type: 'failed', ...terminal });
|
|
340
350
|
}
|
|
341
|
-
else if (
|
|
342
|
-
events.push({
|
|
343
|
-
type: 'failed',
|
|
344
|
-
errorCode: 'hitl_unanswered',
|
|
345
|
-
errorMessage: `${park.gate === 'fs' ? 'Tool approval' : 'AskUserQuestion'} gate could not be answered: ${failedReason}` +
|
|
346
|
-
' — the run is still parked on this approval: decide it on the card when it is shown again, or cancel the run.',
|
|
347
|
-
});
|
|
351
|
+
else if (reason !== undefined) {
|
|
352
|
+
events.push({ type: 'failed', errorCode: 'hitl_unanswered', errorMessage: reason });
|
|
348
353
|
}
|
|
349
354
|
return events;
|
|
350
355
|
}
|
|
@@ -346,9 +346,11 @@ let decideDispatchSeq = 0;
|
|
|
346
346
|
function planReviewOpsOf(taskId) {
|
|
347
347
|
return planReviewDecisionOps.filter((op) => op.taskId === taskId);
|
|
348
348
|
}
|
|
349
|
-
function settlePlanReviewDecisionOp(op) {
|
|
350
|
-
if (op.settledAt
|
|
351
|
-
|
|
349
|
+
function settlePlanReviewDecisionOp(op, by) {
|
|
350
|
+
if (op.settledAt !== null)
|
|
351
|
+
return;
|
|
352
|
+
op.settledAt = ++planReviewLedgerClock;
|
|
353
|
+
op.settler = by;
|
|
352
354
|
}
|
|
353
355
|
function pushPlanReviewDecisionOp(op) {
|
|
354
356
|
planReviewDecisionOps.push(op);
|
|
@@ -366,18 +368,31 @@ function dropPlanReviewDecisionOp(op) {
|
|
|
366
368
|
if (i >= 0)
|
|
367
369
|
planReviewDecisionOps.splice(i, 1);
|
|
368
370
|
}
|
|
371
|
+
function claimablePlanReviewDecisionOp(taskId) {
|
|
372
|
+
const open = planReviewDecisionOps.find((o) => o.taskId === taskId && o.phase === 'handed' && o.settledAt === null);
|
|
373
|
+
if (open !== undefined)
|
|
374
|
+
return open;
|
|
375
|
+
let leftBehind;
|
|
376
|
+
for (const o of planReviewDecisionOps) {
|
|
377
|
+
if (o.taskId !== taskId || o.phase !== 'handed' || o.settler !== 'gate_left')
|
|
378
|
+
continue;
|
|
379
|
+
if (leftBehind === undefined || o.handedAt > leftBehind.handedAt)
|
|
380
|
+
leftBehind = o;
|
|
381
|
+
}
|
|
382
|
+
return leftBehind;
|
|
383
|
+
}
|
|
369
384
|
export function notePlanReviewDecisionHandedOver(taskId) {
|
|
370
385
|
if (typeof taskId !== 'string' || taskId === '')
|
|
371
386
|
return null;
|
|
372
387
|
if (planReviewDecisionOps.some((op) => op.taskId === taskId && op.settledAt === null))
|
|
373
388
|
return null;
|
|
374
|
-
const op = { taskId, handedAt: ++planReviewLedgerClock, settledAt: null, phase: 'handed', notApplied: false, ownCallOpen: false };
|
|
389
|
+
const op = { taskId, handedAt: ++planReviewLedgerClock, settledAt: null, settler: null, phase: 'handed', notApplied: false, ownCallOpen: false };
|
|
375
390
|
pushPlanReviewDecisionOp(op);
|
|
376
391
|
return {
|
|
377
392
|
settle: () => {
|
|
378
393
|
if (op.phase !== 'handed')
|
|
379
394
|
return;
|
|
380
|
-
settlePlanReviewDecisionOp(op);
|
|
395
|
+
settlePlanReviewDecisionOp(op, 'host');
|
|
381
396
|
},
|
|
382
397
|
revoke: () => {
|
|
383
398
|
if (op.phase !== 'handed' || op.settledAt !== null)
|
|
@@ -412,7 +427,7 @@ export function notePlanReviewGateLeft(taskId) {
|
|
|
412
427
|
if (typeof taskId !== 'string' || taskId === '')
|
|
413
428
|
return;
|
|
414
429
|
for (const op of planReviewOpsOf(taskId))
|
|
415
|
-
settlePlanReviewDecisionOp(op);
|
|
430
|
+
settlePlanReviewDecisionOp(op, 'gate_left');
|
|
416
431
|
}
|
|
417
432
|
export function latestPlanReviewDecisionMark(taskId) {
|
|
418
433
|
if (typeof taskId !== 'string' || taskId === '')
|
|
@@ -434,12 +449,17 @@ async function decidePlanReviewFor(taskId, decision, permissionModeAfter, opts,
|
|
|
434
449
|
hostLog('error', `planReviewWire: decidePlanReview(${decision}) for task ${taskId} REFUSED — a decision for this task is already in flight (duplicate delivery latched)`);
|
|
435
450
|
return;
|
|
436
451
|
}
|
|
437
|
-
let op =
|
|
452
|
+
let op = claimablePlanReviewDecisionOp(taskId);
|
|
438
453
|
if (op === undefined) {
|
|
439
|
-
op = { taskId: typeof taskId === 'string' ? taskId : String(taskId), handedAt: ++planReviewLedgerClock, settledAt: null, phase: 'posting', notApplied: false, ownCallOpen: true };
|
|
454
|
+
op = { taskId: typeof taskId === 'string' ? taskId : String(taskId), handedAt: ++planReviewLedgerClock, settledAt: null, settler: null, phase: 'posting', notApplied: false, ownCallOpen: true };
|
|
440
455
|
pushPlanReviewDecisionOp(op);
|
|
441
456
|
}
|
|
442
457
|
else {
|
|
458
|
+
if (op.settler === 'gate_left') {
|
|
459
|
+
op.settledAt = null;
|
|
460
|
+
op.settler = null;
|
|
461
|
+
op.notApplied = false;
|
|
462
|
+
}
|
|
443
463
|
op.phase = 'posting';
|
|
444
464
|
op.ownCallOpen = true;
|
|
445
465
|
}
|
|
@@ -451,7 +471,7 @@ async function decidePlanReviewFor(taskId, decision, permissionModeAfter, opts,
|
|
|
451
471
|
const settle = (notApplied) => {
|
|
452
472
|
if (notApplied)
|
|
453
473
|
mine.notApplied = true;
|
|
454
|
-
settlePlanReviewDecisionOp(mine);
|
|
474
|
+
settlePlanReviewDecisionOp(mine, 'package');
|
|
455
475
|
};
|
|
456
476
|
const dispatchNo = ++decideDispatchSeq;
|
|
457
477
|
hostLog('debug', `planReviewWire: decidePlanReview dispatch #${dispatchNo} task=${taskId} decision=${decision} mode=${permissionModeAfter ?? '-'}`);
|
|
@@ -460,7 +480,7 @@ async function decidePlanReviewFor(taskId, decision, permissionModeAfter, opts,
|
|
|
460
480
|
}
|
|
461
481
|
finally {
|
|
462
482
|
releaseLatch();
|
|
463
|
-
settlePlanReviewDecisionOp(mine);
|
|
483
|
+
settlePlanReviewDecisionOp(mine, 'package');
|
|
464
484
|
mine.ownCallOpen = false;
|
|
465
485
|
}
|
|
466
486
|
}
|
|
@@ -7,3 +7,10 @@ export type SuspendedReopenReading = {
|
|
|
7
7
|
readonly kind: 'unstated';
|
|
8
8
|
};
|
|
9
9
|
export declare function suspendedReopenOf(ev: unknown): SuspendedReopenReading;
|
|
10
|
+
export interface ResumeReopenDetail {
|
|
11
|
+
code: string;
|
|
12
|
+
reason: 'env_failed' | 'tool_unavailable' | 'tool_contract_mismatch';
|
|
13
|
+
retriable: true;
|
|
14
|
+
}
|
|
15
|
+
export declare function resumeReopenFromError(err: unknown): ResumeReopenDetail | null;
|
|
16
|
+
export declare function resumeReopenContent(detail: ResumeReopenDetail): string;
|
|
@@ -1,13 +1,44 @@
|
|
|
1
|
+
import { RESUME_REOPEN_CODES, RESUME_ENV_FAILED, RESUME_TOOL_UNAVAILABLE } from '../engineErrorCodes.js';
|
|
1
2
|
const UNSTATED = Object.freeze({ kind: 'unstated' });
|
|
2
3
|
const NOT_REOPENED = Object.freeze({ kind: 'not_reopened' });
|
|
3
4
|
export function suspendedReopenOf(ev) {
|
|
4
|
-
if (ev === null || typeof ev !== 'object'
|
|
5
|
+
if (ev === null || typeof ev !== 'object')
|
|
5
6
|
return UNSTATED;
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
try {
|
|
8
|
+
if (Array.isArray(ev))
|
|
9
|
+
return UNSTATED;
|
|
10
|
+
const o = ev;
|
|
11
|
+
if (!Object.hasOwn(o, 'reopened'))
|
|
12
|
+
return UNSTATED;
|
|
13
|
+
const v = o.reopened;
|
|
14
|
+
if (v === null)
|
|
15
|
+
return NOT_REOPENED;
|
|
16
|
+
return typeof v === 'string' && v.length > 0 ? { kind: 'reopened', code: v } : UNSTATED;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
8
19
|
return UNSTATED;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function resumeReopenFromError(err) {
|
|
23
|
+
if (typeof err !== 'object' || err === null)
|
|
24
|
+
return null;
|
|
25
|
+
const code = err.errorCode;
|
|
26
|
+
if (typeof code !== 'string' || !RESUME_REOPEN_CODES.includes(code))
|
|
27
|
+
return null;
|
|
28
|
+
if (err.retriable !== true)
|
|
29
|
+
return null;
|
|
30
|
+
const reason = code.slice('resume.'.length);
|
|
31
|
+
return { code, reason, retriable: true };
|
|
32
|
+
}
|
|
33
|
+
export function resumeReopenContent(detail) {
|
|
34
|
+
const first = detail.code === RESUME_ENV_FAILED
|
|
35
|
+
? 'The execution environment for this parked work could not be brought back'
|
|
36
|
+
: detail.code === RESUME_TOOL_UNAVAILABLE
|
|
37
|
+
? 'The tool this approval was granted for is not available on this engine'
|
|
38
|
+
: 'The tool this approval was granted for has changed since the approval was recorded';
|
|
39
|
+
return [
|
|
40
|
+
first,
|
|
41
|
+
'The engine re-parked the work before consuming anything — the approval is still pending and your decision was not consumed',
|
|
42
|
+
'Re-fetch the pending approvals and decide again on an engine where the same tool is available',
|
|
43
|
+
].join(' · ');
|
|
13
44
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_DENY_REASON, DecideTransportRetryExhaustedError, HitlBridge, HitlSafetyError, denyReasonForWire, findPendingForTask, readDecideCurrentPending, readWireErrorCode, } from './hitlBridge.js';
|
|
1
|
+
import { APPROVAL_CARD_PORT_KEY_MISMATCH_REASON, DEFAULT_DENY_REASON, DecideTransportRetryExhaustedError, HitlBridge, NO_APPROVAL_CARD_PORT_REASON, HitlSafetyError, denyReasonForWire, findPendingForTask, readDecideCurrentPending, readWireErrorCode, } from './hitlBridge.js';
|
|
2
2
|
import { askParkRowArm } from './askParkRowRouting.js';
|
|
3
3
|
import { hostLog } from '../host.js';
|
|
4
4
|
import { readOwnNonEmptyString } from '../ownKey.js';
|
|
@@ -120,10 +120,9 @@ function cardPortMissReason() {
|
|
|
120
120
|
const otherKeysInstalled = cardPortByKey
|
|
121
121
|
.keys()
|
|
122
122
|
.some((k) => k !== DEFAULT_SESSION_KEY && cardPortByKey.get(k) != null);
|
|
123
|
-
if (otherKeysInstalled)
|
|
124
|
-
return
|
|
125
|
-
|
|
126
|
-
return 'no approval card port installed (print/non-REPL mode, or host forgot installApprovalCardPort)';
|
|
123
|
+
if (otherKeysInstalled)
|
|
124
|
+
return APPROVAL_CARD_PORT_KEY_MISMATCH_REASON;
|
|
125
|
+
return NO_APPROVAL_CARD_PORT_REASON;
|
|
127
126
|
}
|
|
128
127
|
function rememberRefusedByServer(e) {
|
|
129
128
|
switch (readWireErrorCode(e)) {
|
package/dist/index.d.ts
CHANGED
|
@@ -145,6 +145,11 @@ export * from './principalWire.js';
|
|
|
145
145
|
export * from './wireErrorTriage.js';
|
|
146
146
|
export * from './corruptSession.js';
|
|
147
147
|
export * from './corruptSessionCopy.js';
|
|
148
|
+
export { classifyToolHistoryMismatch, resolveToolHistoryRewindTarget } from './toolHistoryMismatch.js';
|
|
149
|
+
export { classifyRegistryConflict, isScopeGoneError } from './registryConflict.js';
|
|
150
|
+
export type { RegistryConflictClass } from './registryConflict.js';
|
|
151
|
+
export { createPromptDeliveryLedger, promptKnownUndelivered, withoutUndeliveredPrompts } from './promptDelivery.js';
|
|
152
|
+
export type { PromptDeliveryLedger, PromptDeliveryRecord } from './promptDelivery.js';
|
|
148
153
|
export * from './resumeRefusalCopy.js';
|
|
149
154
|
export * from './wireRefusalCopy.js';
|
|
150
155
|
export * from './inheritEnvWire.js';
|
|
@@ -197,6 +202,8 @@ export { readEngineAgentRegistry, isEngineAgentRegistryListingSuperseded } from
|
|
|
197
202
|
export type { EngineAgentRegistryClient } from './agentSession/engineAgentRegistryRead.js';
|
|
198
203
|
export { stopEngineSessionBackground, engineSessionBackgroundReceiptReadingOf, ENGINE_SESSION_BACKGROUND_RECEIPT_STATES, } from './agentSession/engineSessionBackgroundStop.js';
|
|
199
204
|
export type { EngineSessionBackgroundStopClient, EngineSessionBackgroundStopWire, EngineSessionBackgroundStopOptions, EngineSessionBackgroundReceipt, EngineSessionBackgroundStopUnavailableWhy, EngineSessionBackgroundStopRefusedWhy, EngineSessionBackgroundStopResult, EngineSessionBackgroundReceiptState, EngineSessionBackgroundReceiptReading, } from './agentSession/engineSessionBackgroundStop.js';
|
|
205
|
+
export { eraseSessionMemory, sessionMemoryEraseOutcome, SESSION_MEMORY_ERASE_REFUSAL_REASONS, SESSION_MEMORY_ERASE_UNCONFIRMED_WHYS, SESSION_MEMORY_ERASE_RETRIES, } from './sessionMemoryErase.js';
|
|
206
|
+
export type { SessionMemoryEraseWire, SessionMemoryEraseCall, SessionMemoryEraseOptions, SessionMemoryEraseSent, SessionMemoryEraseNotSentWhy, SessionMemoryEraseJson, SessionMemoryEraseAnswer, SessionMemoryEraseRefusalReason, SessionMemoryEraseUnconfirmedWhy, SessionMemoryEraseRetry, SessionMemoryEraseOutcome, } from './sessionMemoryErase.js';
|
|
200
207
|
export * from './model/catalog.js';
|
|
201
208
|
export * from './model/catalogLoader.js';
|
|
202
209
|
export * from './model/providerAuth.js';
|
package/dist/index.js
CHANGED
|
@@ -133,6 +133,9 @@ export * from './principalWire.js';
|
|
|
133
133
|
export * from './wireErrorTriage.js';
|
|
134
134
|
export * from './corruptSession.js';
|
|
135
135
|
export * from './corruptSessionCopy.js';
|
|
136
|
+
export { classifyToolHistoryMismatch, resolveToolHistoryRewindTarget } from './toolHistoryMismatch.js';
|
|
137
|
+
export { classifyRegistryConflict, isScopeGoneError } from './registryConflict.js';
|
|
138
|
+
export { createPromptDeliveryLedger, promptKnownUndelivered, withoutUndeliveredPrompts } from './promptDelivery.js';
|
|
136
139
|
export * from './resumeRefusalCopy.js';
|
|
137
140
|
export * from './wireRefusalCopy.js';
|
|
138
141
|
export * from './inheritEnvWire.js';
|
|
@@ -181,6 +184,7 @@ export * from './agentSession/backgroundView.js';
|
|
|
181
184
|
export { READ_CREDENTIAL_NOT_ACCEPTED_NOTICE } from './readCredentialRefusal.js';
|
|
182
185
|
export { readEngineAgentRegistry, isEngineAgentRegistryListingSuperseded } from './agentSession/engineAgentRegistryRead.js';
|
|
183
186
|
export { stopEngineSessionBackground, engineSessionBackgroundReceiptReadingOf, ENGINE_SESSION_BACKGROUND_RECEIPT_STATES, } from './agentSession/engineSessionBackgroundStop.js';
|
|
187
|
+
export { eraseSessionMemory, sessionMemoryEraseOutcome, SESSION_MEMORY_ERASE_REFUSAL_REASONS, SESSION_MEMORY_ERASE_UNCONFIRMED_WHYS, SESSION_MEMORY_ERASE_RETRIES, } from './sessionMemoryErase.js';
|
|
184
188
|
export * from './model/catalog.js';
|
|
185
189
|
export * from './model/catalogLoader.js';
|
|
186
190
|
export * from './model/providerAuth.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentEvent } from '@sema-agent/sdk';
|
|
2
|
+
import { type SelfHealOutcome } from './adapter/activeRunSelfHeal.js';
|
|
3
|
+
export interface PromptDeliveryRecord {
|
|
4
|
+
readonly u: string;
|
|
5
|
+
readonly s: 'a' | 'd';
|
|
6
|
+
}
|
|
7
|
+
export interface PromptDeliveryLedger {
|
|
8
|
+
attempted(batchUuids: readonly string[]): readonly PromptDeliveryRecord[];
|
|
9
|
+
deliveredByFrame(batchUuids: readonly string[], event: AgentEvent): readonly PromptDeliveryRecord[];
|
|
10
|
+
deliveredBySteerReceipt(batchUuids: readonly string[], outcome: SelfHealOutcome): readonly PromptDeliveryRecord[];
|
|
11
|
+
isAttempted(uuid: string): boolean;
|
|
12
|
+
isDelivered(uuid: string): boolean;
|
|
13
|
+
knownUndelivered(uuid: string): boolean;
|
|
14
|
+
batchOf(uuid: string): readonly string[] | undefined;
|
|
15
|
+
toRecords(): readonly PromptDeliveryRecord[];
|
|
16
|
+
fromRecords(records: readonly PromptDeliveryRecord[]): readonly PromptDeliveryRecord[];
|
|
17
|
+
}
|
|
18
|
+
export declare function createPromptDeliveryLedger(): PromptDeliveryLedger;
|
|
19
|
+
export declare function promptKnownUndelivered(ledger: PromptDeliveryLedger, message: object | null | undefined): boolean;
|
|
20
|
+
export declare function withoutUndeliveredPrompts<T>(ledger: PromptDeliveryLedger, messages: readonly T[]): T[];
|