@sema-agent/client-core 0.90.0 → 0.92.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 +365 -0
- package/README.md +48 -32
- package/dist/adapt/arms.js +13 -12
- package/dist/adapt/panelTasks.d.ts +0 -2
- package/dist/adapt/panelTasks.js +6 -26
- package/dist/adapt.js +2 -2
- package/dist/adapter/activeRunSelfHeal.d.ts +0 -2
- package/dist/adapter/activeRunSelfHeal.js +5 -27
- package/dist/adapter/downstream/eventToSdkMessage.js +4 -2
- package/dist/adapter/downstream/terminalToSdkResult.js +16 -7
- package/dist/adapter/downstream/wiringManifestView.d.ts +6 -0
- package/dist/adapter/downstream/wiringManifestView.js +16 -0
- package/dist/adapter/runStream.js +39 -20
- package/dist/askSurvivesStandingAnswer.d.ts +13 -0
- package/dist/askSurvivesStandingAnswer.js +53 -0
- package/dist/attachmentSeatCapability.d.ts +11 -0
- package/dist/attachmentSeatCapability.js +27 -0
- package/dist/attachmentsWireCaps.d.ts +9 -0
- package/dist/attachmentsWireCaps.js +74 -21
- package/dist/autoModeUnavailable.js +3 -2
- package/dist/cloudConfigWireCaps.js +5 -4
- package/dist/compensations.js +13 -17
- package/dist/controlRouter.d.ts +32 -25
- package/dist/controlRouter.js +166 -63
- package/dist/coreValuePorts.d.ts +4 -2
- package/dist/coreValuePorts.js +5 -0
- package/dist/decideFailureNote.js +7 -3
- package/dist/decideReceipt.d.ts +9 -0
- package/dist/decideReceipt.js +62 -1
- package/dist/disableSkillsWire.d.ts +1 -0
- package/dist/disableSkillsWire.js +8 -1
- package/dist/displayUntrusted.js +155 -5
- package/dist/effectiveFacts.d.ts +14 -4
- package/dist/effectiveFacts.js +45 -5
- package/dist/engineAgentAbsence.js +2 -1
- package/dist/engineCapReader.js +16 -10
- package/dist/engineCapsCache.d.ts +5 -1
- package/dist/engineCapsCache.js +69 -8
- package/dist/engineClosedSets.d.ts +2 -0
- package/dist/engineClosedSets.js +3 -0
- package/dist/engineErrorCodes.d.ts +17 -0
- package/dist/engineErrorCodes.js +47 -0
- package/dist/engineNoticeCodes.d.ts +14 -0
- package/dist/engineNoticeCodes.js +71 -0
- package/dist/executionLaneCapability.js +2 -0
- package/dist/gateOutcome.js +2 -17
- package/dist/gateVocabulary.d.ts +2 -4
- package/dist/gateVocabulary.js +3 -11
- package/dist/generated/engineFactTables.d.ts +27 -0
- package/dist/generated/engineFactTables.js +128 -0
- package/dist/generated/engineNoticeTables.js +3 -0
- package/dist/generated/settingsSchemaTables.d.ts +8 -0
- package/dist/generated/settingsSchemaTables.js +40 -0
- package/dist/hitl/allowRuleShadow.d.ts +21 -0
- package/dist/hitl/allowRuleShadow.js +167 -0
- package/dist/hitl/askClassPair.d.ts +14 -0
- package/dist/hitl/askClassPair.js +42 -0
- package/dist/hitl/askGateWire.d.ts +1 -1
- package/dist/hitl/askGateWire.js +2 -1
- package/dist/hitl/askSurvivesPosture.d.ts +5 -0
- package/dist/hitl/askSurvivesPosture.js +17 -0
- package/dist/hitl/automaticAnswerVerdict.d.ts +21 -0
- package/dist/hitl/automaticAnswerVerdict.js +143 -0
- package/dist/hitl/crashConverged.d.ts +8 -0
- package/dist/hitl/crashConverged.js +58 -1
- package/dist/hitl/crashConvergedNotice.d.ts +4 -0
- package/dist/hitl/crashConvergedNotice.js +57 -0
- package/dist/hitl/frameRouter.d.ts +2 -0
- package/dist/hitl/frameRouter.js +66 -14
- package/dist/hitl/gateLedger.d.ts +6 -0
- package/dist/hitl/gateLedger.js +34 -5
- package/dist/hitl/hitlBridge.d.ts +7 -4
- package/dist/hitl/hitlHostSurface.d.ts +2 -0
- package/dist/hitl/hitlHostSurface.js +7 -0
- package/dist/hitl/livePendingAsk.js +24 -5
- package/dist/hitl/parkResolver.d.ts +7 -2
- package/dist/hitl/parkResolver.js +21 -7
- package/dist/hitl/persistedRulesWire.d.ts +4 -1
- package/dist/hitl/persistedRulesWire.js +9 -2
- package/dist/hitl/planReviewWire.d.ts +1 -1
- package/dist/hitl/planReviewWire.js +19 -5
- package/dist/hitl/replayedApproval.d.ts +21 -0
- package/dist/hitl/replayedApproval.js +89 -0
- package/dist/hitl/sessionPolicyDeliverable.js +20 -2
- package/dist/hitl/sessionPolicyWire.d.ts +13 -0
- package/dist/hitl/sessionPolicyWire.js +75 -2
- package/dist/hitl/suspendedReopen.js +2 -2
- package/dist/hitl/toolApprovalWire.d.ts +9 -1
- package/dist/hitl/toolApprovalWire.js +40 -40
- package/dist/hookMatcherVerdict.d.ts +29 -0
- package/dist/hookMatcherVerdict.js +266 -0
- package/dist/humanTurn.d.ts +91 -0
- package/dist/humanTurn.js +252 -0
- package/dist/humanTurnRead.d.ts +105 -0
- package/dist/humanTurnRead.js +331 -0
- package/dist/index.d.ts +38 -11
- package/dist/index.js +27 -8
- package/dist/inheritEnvWire.js +4 -5
- package/dist/liveModelCatalog.d.ts +2 -0
- package/dist/liveModelCatalog.js +51 -3
- package/dist/mcpLiveness.js +2 -1
- package/dist/memoryVerbsWire.d.ts +1 -1
- package/dist/memoryVerbsWire.js +3 -0
- package/dist/model/catalog.js +2 -1
- package/dist/model/providerPresets.d.ts +3 -1
- package/dist/model/tierVocabulary.d.ts +2 -1
- package/dist/model/tierVocabulary.js +3 -8
- package/dist/peerFrames.js +2 -2
- package/dist/permissionRuleIssue.d.ts +1 -1
- package/dist/permissionRuleIssue.js +31 -9
- package/dist/permissionsAllowGrantCapability.d.ts +2 -1
- package/dist/permissionsAllowGrantCapability.js +11 -2
- package/dist/permissionsDeclaration.d.ts +29 -0
- package/dist/permissionsDeclaration.js +155 -66
- package/dist/pluginHooksWire.js +2 -11
- package/dist/promptDelivery.d.ts +11 -3
- package/dist/promptDelivery.js +164 -29
- package/dist/promptProfileWireCaps.d.ts +2 -1
- package/dist/protocolSegment.d.ts +9 -0
- package/dist/protocolSegment.js +28 -0
- package/dist/providerRejection.d.ts +1 -0
- package/dist/providerRejection.js +20 -0
- package/dist/readDenyTiers.d.ts +10 -0
- package/dist/readDenyTiers.js +29 -0
- package/dist/request/taskRequest.js +3 -17
- package/dist/resumeRefusalCopy.d.ts +11 -0
- package/dist/resumeRefusalCopy.js +61 -4
- package/dist/rewindArchiveCapability.js +4 -4
- package/dist/rewindWireCaps.d.ts +2 -1
- package/dist/rewindWireCaps.js +19 -2
- package/dist/ruleCompileVerdict.d.ts +2 -0
- package/dist/ruleCompileVerdict.js +13 -0
- package/dist/ruleRemovalConsequence.d.ts +2 -1
- package/dist/runCancelContext.d.ts +12 -0
- package/dist/runCancelContext.js +83 -1
- package/dist/seam.d.ts +2 -0
- package/dist/seam.js +1 -1
- package/dist/seatContract.d.ts +2 -1
- package/dist/sessionMemoryStatus.d.ts +2 -4
- package/dist/sessionSyncFileHistoryCapability.d.ts +18 -0
- package/dist/sessionSyncFileHistoryCapability.js +50 -0
- package/dist/skillToolListsCapability.d.ts +18 -0
- package/dist/skillToolListsCapability.js +50 -0
- package/dist/sqlEngineCapability.js +1 -8
- package/dist/steerPriorityCapability.d.ts +18 -0
- package/dist/steerPriorityCapability.js +80 -0
- package/dist/steerReceipt.d.ts +9 -0
- package/dist/steerReceipt.js +25 -0
- package/dist/subagent/engineSubagentSteer.js +2 -9
- package/dist/supportFloor.js +2 -2
- package/dist/taskRequestWords.d.ts +7 -1
- package/dist/taskRequestWords.js +18 -8
- package/dist/toolHistoryBadTurn.d.ts +1 -0
- package/dist/toolHistoryBadTurn.js +89 -0
- package/dist/toolHistoryMismatch.d.ts +2 -1
- package/dist/toolHistoryMismatch.js +19 -6
- package/dist/toolResult.d.ts +8 -0
- package/dist/toolResult.js +47 -3
- package/dist/types/engineState.d.ts +2 -12
- package/dist/userAttachmentEnvelope.d.ts +61 -0
- package/dist/userAttachmentEnvelope.js +204 -0
- package/dist/userInvokedSkillsCapability.d.ts +18 -0
- package/dist/userInvokedSkillsCapability.js +50 -0
- package/dist/wireFailureShape.d.ts +3 -0
- package/dist/wireFailureShape.js +8 -0
- package/dist/wireRefusalCopy.d.ts +6 -0
- package/dist/wireRefusalCopy.js +26 -3
- package/dist/workflowsJournalCapability.d.ts +18 -0
- package/dist/workflowsJournalCapability.js +50 -0
- package/dist/writeProtectionCapability.d.ts +2 -4
- package/docs/INTEGRATION-CLIENTS.md +1489 -16
- package/package.json +3 -3
package/dist/promptDelivery.d.ts
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import type { AgentEvent } from '@sema-agent/sdk';
|
|
2
2
|
import { type SelfHealOutcome } from './adapter/activeRunSelfHeal.js';
|
|
3
|
+
import type { HumanTurnDelivered } from './humanTurn.js';
|
|
3
4
|
export interface PromptDeliveryRecord {
|
|
4
5
|
readonly u: string;
|
|
5
6
|
readonly s: 'a' | 'd';
|
|
7
|
+
readonly by?: 'frame' | 'steer_receipt';
|
|
8
|
+
readonly share?: 'full' | 'partial';
|
|
6
9
|
}
|
|
7
10
|
export interface PromptDeliveryLedger {
|
|
8
|
-
attempted(batchUuids: readonly string[]
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
attempted(batchUuids: readonly string[], opts?: {
|
|
12
|
+
readonly generation?: number;
|
|
13
|
+
}): readonly PromptDeliveryRecord[];
|
|
14
|
+
deliveredByFrame(batchUuids: readonly string[] | HumanTurnDelivered, event: AgentEvent): readonly PromptDeliveryRecord[];
|
|
15
|
+
deliveredBySteerReceipt(batchUuids: readonly string[] | HumanTurnDelivered, outcome: SelfHealOutcome): readonly PromptDeliveryRecord[];
|
|
11
16
|
isAttempted(uuid: string): boolean;
|
|
12
17
|
isDelivered(uuid: string): boolean;
|
|
13
18
|
knownUndelivered(uuid: string): boolean;
|
|
19
|
+
deliveryShareOf(uuid: string): 'full' | 'partial' | undefined;
|
|
20
|
+
undeliveredInGeneration(generation: number): readonly string[];
|
|
21
|
+
droppedKeyCount(): number;
|
|
14
22
|
batchOf(uuid: string): readonly string[] | undefined;
|
|
15
23
|
toRecords(): readonly PromptDeliveryRecord[];
|
|
16
24
|
fromRecords(records: readonly PromptDeliveryRecord[]): readonly PromptDeliveryRecord[];
|
package/dist/promptDelivery.js
CHANGED
|
@@ -1,8 +1,43 @@
|
|
|
1
1
|
import { activeRunBusySignal } from './adapter/runStream.js';
|
|
2
2
|
import { selfHealSubmissionDisposition } from './adapter/activeRunSelfHeal.js';
|
|
3
3
|
const uuidOk = (u) => typeof u === 'string' && u.length > 0;
|
|
4
|
+
function isArraySafe(v) {
|
|
5
|
+
try {
|
|
6
|
+
return Array.isArray(v);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const generationOk = (g) => typeof g === 'number' && Number.isSafeInteger(g) && g >= 0;
|
|
13
|
+
function generationOpt(opts) {
|
|
14
|
+
if (typeof opts !== 'object' || opts === null)
|
|
15
|
+
return undefined;
|
|
16
|
+
try {
|
|
17
|
+
const g = opts.generation;
|
|
18
|
+
return generationOk(g) ? g : undefined;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const levelOf = (rec) => !Object.hasOwn(rec, 'by') ? 1 : Object.hasOwn(rec, 'share') && rec.share === 'partial' ? 2 : 3;
|
|
25
|
+
function deliveredByWord(v) {
|
|
26
|
+
const words = { frame: true, steer_receipt: true };
|
|
27
|
+
return typeof v === 'string' && Object.hasOwn(words, v) ? v : undefined;
|
|
28
|
+
}
|
|
29
|
+
function deliveredShareWord(v) {
|
|
30
|
+
const words = { full: true, partial: true };
|
|
31
|
+
return typeof v === 'string' && Object.hasOwn(words, v) ? v : undefined;
|
|
32
|
+
}
|
|
33
|
+
function ownExtension(rec, key) {
|
|
34
|
+
const desc = Object.getOwnPropertyDescriptor(rec, key);
|
|
35
|
+
if (desc === undefined)
|
|
36
|
+
return key in rec ? { kind: 'unreadable' } : { kind: 'absent' };
|
|
37
|
+
return 'value' in desc ? { kind: 'value', value: desc.value } : { kind: 'unreadable' };
|
|
38
|
+
}
|
|
4
39
|
function cleanBatch(batch) {
|
|
5
|
-
if (!
|
|
40
|
+
if (!isArraySafe(batch))
|
|
6
41
|
return [];
|
|
7
42
|
const out = [];
|
|
8
43
|
const seen = new Set();
|
|
@@ -19,17 +54,73 @@ function cleanBatch(batch) {
|
|
|
19
54
|
}
|
|
20
55
|
return out;
|
|
21
56
|
}
|
|
22
|
-
function readRecord(
|
|
23
|
-
if (typeof
|
|
57
|
+
function readRecord(raw) {
|
|
58
|
+
if (typeof raw !== 'object' || raw === null)
|
|
24
59
|
return undefined;
|
|
60
|
+
let u;
|
|
61
|
+
let s;
|
|
25
62
|
try {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
63
|
+
if (Array.isArray(raw))
|
|
64
|
+
return undefined;
|
|
65
|
+
u = raw.u;
|
|
66
|
+
s = raw.s;
|
|
29
67
|
}
|
|
30
68
|
catch {
|
|
31
69
|
return undefined;
|
|
32
70
|
}
|
|
71
|
+
if (!uuidOk(u) || (s !== 'a' && s !== 'd'))
|
|
72
|
+
return undefined;
|
|
73
|
+
const legacy = { u, s };
|
|
74
|
+
try {
|
|
75
|
+
let rec = legacy;
|
|
76
|
+
if (s === 'd') {
|
|
77
|
+
const byExt = ownExtension(raw, 'by');
|
|
78
|
+
const shareExt = ownExtension(raw, 'share');
|
|
79
|
+
const by = byExt.kind === 'value' ? deliveredByWord(byExt.value) : undefined;
|
|
80
|
+
const share = shareExt.kind === 'value' ? deliveredShareWord(shareExt.value) : undefined;
|
|
81
|
+
if (by !== undefined && (shareExt.kind === 'absent' || share !== undefined))
|
|
82
|
+
rec = share === undefined ? { u, s, by } : { u, s, by, share };
|
|
83
|
+
}
|
|
84
|
+
const dropped = Object.keys(raw).filter((k) => !Object.hasOwn(rec, k)).length;
|
|
85
|
+
return { rec, dropped };
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return { rec: legacy, dropped: 0 };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function readTierStrict(holder, key) {
|
|
92
|
+
try {
|
|
93
|
+
if (!Object.hasOwn(holder, key))
|
|
94
|
+
return [];
|
|
95
|
+
const raw = holder[key];
|
|
96
|
+
if (!Array.isArray(raw))
|
|
97
|
+
return null;
|
|
98
|
+
const out = [];
|
|
99
|
+
const seen = new Set();
|
|
100
|
+
for (const u of raw) {
|
|
101
|
+
if (!uuidOk(u) || seen.has(u))
|
|
102
|
+
continue;
|
|
103
|
+
seen.add(u);
|
|
104
|
+
out.push(u);
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function batchTiers(batch) {
|
|
113
|
+
const none = { full: [], partial: [] };
|
|
114
|
+
if (isArraySafe(batch))
|
|
115
|
+
return { full: cleanBatch(batch), partial: [] };
|
|
116
|
+
if (typeof batch !== 'object' || batch === null)
|
|
117
|
+
return none;
|
|
118
|
+
const full = readTierStrict(batch, 'full');
|
|
119
|
+
const partial = readTierStrict(batch, 'partial');
|
|
120
|
+
if (full === null || partial === null)
|
|
121
|
+
return none;
|
|
122
|
+
const inFull = new Set(full);
|
|
123
|
+
return { full, partial: partial.filter((u) => !inFull.has(u)) };
|
|
33
124
|
}
|
|
34
125
|
const PRE_RUN_FRAME_TYPES = new Set(['meta', 'approval_request', 'approval_revoke']);
|
|
35
126
|
export function frameProvesDelivery(event) {
|
|
@@ -56,9 +147,11 @@ export function frameProvesDelivery(event) {
|
|
|
56
147
|
}
|
|
57
148
|
}
|
|
58
149
|
function outcomeProvesDelivery(outcome) {
|
|
59
|
-
if (typeof outcome !== 'object' || outcome === null
|
|
150
|
+
if (typeof outcome !== 'object' || outcome === null)
|
|
60
151
|
return false;
|
|
61
152
|
try {
|
|
153
|
+
if (Array.isArray(outcome))
|
|
154
|
+
return false;
|
|
62
155
|
return selfHealSubmissionDisposition(outcome) === 'handed-off';
|
|
63
156
|
}
|
|
64
157
|
catch {
|
|
@@ -67,48 +160,88 @@ function outcomeProvesDelivery(outcome) {
|
|
|
67
160
|
}
|
|
68
161
|
export function createPromptDeliveryLedger() {
|
|
69
162
|
const attemptedSet = new Set();
|
|
70
|
-
const
|
|
163
|
+
const deliveredLevel = new Map();
|
|
71
164
|
const batchOfMap = new Map();
|
|
165
|
+
const generationOf = new Map();
|
|
72
166
|
const log = [];
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
167
|
+
let droppedKeys = 0;
|
|
168
|
+
const keep = (rec, into) => {
|
|
169
|
+
const frozen = Object.freeze(rec);
|
|
170
|
+
log.push(frozen);
|
|
171
|
+
into.push(frozen);
|
|
172
|
+
};
|
|
173
|
+
const add = (rec, into) => {
|
|
174
|
+
if (rec.s === 'a') {
|
|
175
|
+
if (attemptedSet.has(rec.u))
|
|
176
|
+
return;
|
|
177
|
+
attemptedSet.add(rec.u);
|
|
178
|
+
keep(rec, into);
|
|
76
179
|
return;
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
180
|
+
}
|
|
181
|
+
const level = levelOf(rec);
|
|
182
|
+
if ((deliveredLevel.get(rec.u) ?? 0) >= level)
|
|
183
|
+
return;
|
|
184
|
+
deliveredLevel.set(rec.u, level);
|
|
185
|
+
keep(rec, into);
|
|
81
186
|
};
|
|
82
|
-
const markDelivered = (
|
|
187
|
+
const markDelivered = (batch, by) => {
|
|
83
188
|
const added = [];
|
|
84
|
-
|
|
85
|
-
|
|
189
|
+
const { full, partial } = batchTiers(batch);
|
|
190
|
+
for (const u of full)
|
|
191
|
+
add({ u, s: 'd', by }, added);
|
|
192
|
+
for (const u of partial)
|
|
193
|
+
add({ u, s: 'd', by, share: 'partial' }, added);
|
|
86
194
|
return Object.freeze(added);
|
|
87
195
|
};
|
|
196
|
+
const levelNow = (uuid) => (uuidOk(uuid) ? (deliveredLevel.get(uuid) ?? 0) : 0);
|
|
197
|
+
const knownUndeliveredUuid = (uuid) => uuidOk(uuid) && attemptedSet.has(uuid) && !deliveredLevel.has(uuid);
|
|
88
198
|
const ledger = Object.freeze({
|
|
89
|
-
attempted(batchUuids) {
|
|
199
|
+
attempted(batchUuids, opts) {
|
|
200
|
+
const generation = generationOpt(opts);
|
|
90
201
|
const batch = Object.freeze(cleanBatch(batchUuids));
|
|
91
202
|
const added = [];
|
|
92
203
|
for (const u of batch) {
|
|
93
204
|
batchOfMap.set(u, batch);
|
|
94
|
-
|
|
205
|
+
if (generation !== undefined) {
|
|
206
|
+
generationOf.delete(u);
|
|
207
|
+
generationOf.set(u, generation);
|
|
208
|
+
}
|
|
209
|
+
add({ u, s: 'a' }, added);
|
|
95
210
|
}
|
|
96
211
|
return Object.freeze(added);
|
|
97
212
|
},
|
|
98
213
|
deliveredByFrame(batchUuids, event) {
|
|
99
|
-
return frameProvesDelivery(event) ? markDelivered(batchUuids) : Object.freeze([]);
|
|
214
|
+
return frameProvesDelivery(event) ? markDelivered(batchUuids, 'frame') : Object.freeze([]);
|
|
100
215
|
},
|
|
101
216
|
deliveredBySteerReceipt(batchUuids, outcome) {
|
|
102
|
-
return outcomeProvesDelivery(outcome) ? markDelivered(batchUuids) : Object.freeze([]);
|
|
217
|
+
return outcomeProvesDelivery(outcome) ? markDelivered(batchUuids, 'steer_receipt') : Object.freeze([]);
|
|
103
218
|
},
|
|
104
219
|
isAttempted: (uuid) => uuidOk(uuid) && attemptedSet.has(uuid),
|
|
105
|
-
isDelivered: (uuid) =>
|
|
106
|
-
knownUndelivered: (uuid) =>
|
|
220
|
+
isDelivered: (uuid) => levelNow(uuid) >= 2,
|
|
221
|
+
knownUndelivered: (uuid) => knownUndeliveredUuid(uuid),
|
|
222
|
+
deliveryShareOf: (uuid) => {
|
|
223
|
+
const level = levelNow(uuid);
|
|
224
|
+
return level === 3 ? 'full' : level === 2 ? 'partial' : undefined;
|
|
225
|
+
},
|
|
226
|
+
undeliveredInGeneration(generation) {
|
|
227
|
+
const out = [];
|
|
228
|
+
if (!generationOk(generation))
|
|
229
|
+
return Object.freeze(out);
|
|
230
|
+
for (const [u, g] of generationOf) {
|
|
231
|
+
if (g !== generation)
|
|
232
|
+
continue;
|
|
233
|
+
generationOf.delete(u);
|
|
234
|
+
if (knownUndeliveredUuid(u))
|
|
235
|
+
out.push(u);
|
|
236
|
+
}
|
|
237
|
+
return Object.freeze(out);
|
|
238
|
+
},
|
|
239
|
+
droppedKeyCount: () => droppedKeys,
|
|
107
240
|
batchOf: (uuid) => (uuidOk(uuid) ? batchOfMap.get(uuid) : undefined),
|
|
108
241
|
toRecords: () => Object.freeze([...log]),
|
|
109
242
|
fromRecords(records) {
|
|
110
243
|
const added = [];
|
|
111
|
-
if (!
|
|
244
|
+
if (!isArraySafe(records))
|
|
112
245
|
return Object.freeze(added);
|
|
113
246
|
let list;
|
|
114
247
|
try {
|
|
@@ -118,9 +251,11 @@ export function createPromptDeliveryLedger() {
|
|
|
118
251
|
return Object.freeze(added);
|
|
119
252
|
}
|
|
120
253
|
for (const raw of list) {
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
123
|
-
|
|
254
|
+
const read = readRecord(raw);
|
|
255
|
+
if (read === undefined)
|
|
256
|
+
continue;
|
|
257
|
+
droppedKeys += read.dropped;
|
|
258
|
+
add(read.rec, added);
|
|
124
259
|
}
|
|
125
260
|
return Object.freeze(added);
|
|
126
261
|
},
|
|
@@ -152,7 +287,7 @@ export function promptKnownUndelivered(ledger, message) {
|
|
|
152
287
|
}
|
|
153
288
|
export function withoutUndeliveredPrompts(ledger, messages) {
|
|
154
289
|
assertLedger(ledger, 'withoutUndeliveredPrompts');
|
|
155
|
-
if (!
|
|
290
|
+
if (!isArraySafe(messages))
|
|
156
291
|
return [];
|
|
157
292
|
return messages.filter((m) => !promptKnownUndelivered(ledger, m));
|
|
158
293
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TaskRequest } from '@sema-agent/sdk';
|
|
1
2
|
import { type EnvLike } from './hostEnv.js';
|
|
2
|
-
export type PromptProfile = '
|
|
3
|
+
export type PromptProfile = NonNullable<TaskRequest['promptProfile']>;
|
|
3
4
|
export declare function promptProfileFromEnv(env?: EnvLike): PromptProfile | undefined;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { hasCoreValuePort, mintNamespacePrefix, protocolOf } from './coreValuePorts.js';
|
|
2
|
+
export function protocolSegmentOf(name) {
|
|
3
|
+
const ns = protocolOf(name);
|
|
4
|
+
if (ns === undefined)
|
|
5
|
+
return hasCoreValuePort('protocolOf') ? { kind: 'ok' } : { kind: 'unknown' };
|
|
6
|
+
let parsed;
|
|
7
|
+
try {
|
|
8
|
+
parsed = ns.parse(name);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return { kind: 'unknown' };
|
|
12
|
+
}
|
|
13
|
+
const peer = parsed?.peer;
|
|
14
|
+
if (typeof peer !== 'string')
|
|
15
|
+
return { kind: 'ok' };
|
|
16
|
+
if (peer.includes('*'))
|
|
17
|
+
return { kind: 'unminted' };
|
|
18
|
+
let minted;
|
|
19
|
+
try {
|
|
20
|
+
minted = mintNamespacePrefix(ns, peer);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return { kind: 'unknown' };
|
|
24
|
+
}
|
|
25
|
+
if (typeof minted !== 'string')
|
|
26
|
+
return { kind: 'unknown' };
|
|
27
|
+
return minted === `${ns.prefix}${peer}__` ? { kind: 'ok' } : { kind: 'unminted', minted };
|
|
28
|
+
}
|
|
@@ -4,4 +4,5 @@ export interface ProviderRejectionResend {
|
|
|
4
4
|
resend: 'edit_and_resend' | 'not_by_editing';
|
|
5
5
|
text: string;
|
|
6
6
|
}
|
|
7
|
+
export declare function readProviderRejectionResendKey(v: object | null | undefined): ProviderRejectionResend | undefined;
|
|
7
8
|
export declare function providerRejectionResend(detail: RunTerminalFailureDetail | null | undefined, carrier?: ToolHistoryErrorCarrier | null): ProviderRejectionResend | undefined;
|
|
@@ -29,6 +29,26 @@ function toolHistoryMismatchCarrier(carrier) {
|
|
|
29
29
|
return carrier !== undefined && carrier !== null && classifyToolHistoryMismatch(carrier) !== null;
|
|
30
30
|
}
|
|
31
31
|
const PROVIDER_REJECTED = 'provider_rejected';
|
|
32
|
+
const RESEND_TEXT_STATUS = /\(HTTP (\d{3})\)/;
|
|
33
|
+
export function readProviderRejectionResendKey(v) {
|
|
34
|
+
try {
|
|
35
|
+
if (typeof v !== 'object' || v === null || Array.isArray(v))
|
|
36
|
+
return undefined;
|
|
37
|
+
const got = v;
|
|
38
|
+
const resend = got.resend;
|
|
39
|
+
const text = got.text;
|
|
40
|
+
if (typeof text !== 'string' || (resend !== 'edit_and_resend' && resend !== 'not_by_editing'))
|
|
41
|
+
return undefined;
|
|
42
|
+
const hit = RESEND_TEXT_STATUS.exec(text);
|
|
43
|
+
if (hit === null || hit[1] === undefined)
|
|
44
|
+
return undefined;
|
|
45
|
+
const again = providerRejectionResend({ kind: PROVIDER_REJECTED, status: Number(hit[1]) });
|
|
46
|
+
return again !== undefined && again.resend === resend && again.text === text ? { resend: again.resend, text: again.text } : undefined;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
32
52
|
export function providerRejectionResend(detail, carrier) {
|
|
33
53
|
let read;
|
|
34
54
|
try {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const READ_DENY_BUILTIN_TIERS: readonly ["credentials", "shell-history", "browser", "wallet", "agent-config"];
|
|
2
|
+
export declare const READ_DENY_DEFAULT_TIERS: readonly ["credentials", "agent-config"];
|
|
3
|
+
export type ReadDenyBuiltinTiersParse = {
|
|
4
|
+
readonly ok: true;
|
|
5
|
+
readonly value: string | null;
|
|
6
|
+
} | {
|
|
7
|
+
readonly ok: false;
|
|
8
|
+
readonly why: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function parseReadDenyBuiltinTiers(input: string): ReadDenyBuiltinTiersParse;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { displayUntrusted } from './displayUntrusted.js';
|
|
2
|
+
import { CORE_READ_DENY_BUILTIN_TIERS, CORE_READ_DENY_DEFAULT_TIERS } from './generated/engineFactTables.js';
|
|
3
|
+
export const READ_DENY_BUILTIN_TIERS = CORE_READ_DENY_BUILTIN_TIERS;
|
|
4
|
+
export const READ_DENY_DEFAULT_TIERS = CORE_READ_DENY_DEFAULT_TIERS;
|
|
5
|
+
const NONE_WORD = 'none';
|
|
6
|
+
const SHOWN_ITEM_MAX = 40;
|
|
7
|
+
const SHOWN_ITEM_WINDOW = 2000;
|
|
8
|
+
const refuse = (why) => ({ ok: false, why });
|
|
9
|
+
const shown = (item) => displayUntrusted(item.length > SHOWN_ITEM_WINDOW ? item.slice(0, SHOWN_ITEM_WINDOW) : item, { max: SHOWN_ITEM_MAX });
|
|
10
|
+
export function parseReadDenyBuiltinTiers(input) {
|
|
11
|
+
if (typeof input !== 'string')
|
|
12
|
+
return refuse(`expected a string: comma-separated tier names, or the single word "${NONE_WORD}"`);
|
|
13
|
+
const text = input.trim();
|
|
14
|
+
if (text === '')
|
|
15
|
+
return { ok: true, value: null };
|
|
16
|
+
const parts = text.split(',').map((p) => p.trim());
|
|
17
|
+
if (parts.some((p) => p === ''))
|
|
18
|
+
return refuse('an empty entry between commas');
|
|
19
|
+
if (parts.includes(NONE_WORD)) {
|
|
20
|
+
return parts.length === 1 ? { ok: true, value: NONE_WORD } : refuse(`"${NONE_WORD}" must be the only entry`);
|
|
21
|
+
}
|
|
22
|
+
const known = READ_DENY_BUILTIN_TIERS;
|
|
23
|
+
const unknown = parts.filter((p) => !known.includes(p));
|
|
24
|
+
if (unknown.length > 0) {
|
|
25
|
+
const more = unknown.length > 1 ? ` (and ${unknown.length - 1} more)` : '';
|
|
26
|
+
return refuse(`unknown tier "${shown(unknown[0])}"${more}; known tiers: ${known.join(', ')}`);
|
|
27
|
+
}
|
|
28
|
+
return { ok: true, value: parts.join(',') };
|
|
29
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { refuseBadDisableSkills, refuseDisableSkillsConflict } from '../disableSkillsWire.js';
|
|
2
2
|
import { ATTACHMENTS_SPEC_KEYS, AttachmentsSpecRefused } from '../attachmentsWireCaps.js';
|
|
3
|
-
import {
|
|
3
|
+
import { retiredAttachmentsKeyOf } from '../taskRequestWords.js';
|
|
4
4
|
export const REQUEST_FIELD_MATRIX = [
|
|
5
5
|
{ field: 'objective', lanes: ['interactive', 'print', 'utility'], live: false, why: '本 turn 的真实输入,每条车道都必需', whyUtilityLane: '恒座:三条车道都必须带上本次提交的模型面输入' },
|
|
6
6
|
{ field: 'sessionId', lanes: ['interactive', 'print', 'utility'], live: false, why: '单命名空间(TP-A Step 2):壳 id 即引擎 session id;print 在非 live 下保留 mock 常量', whyUtilityLane: '恒座:side-channel 提交走**独立**会话 id(壳另铸一个,绝不复用用户会话那一个 —— 复用会把这次提交的转录混进用户会话)' },
|
|
@@ -44,7 +44,7 @@ export const REQUEST_FIELD_MATRIX = [
|
|
|
44
44
|
{ field: 'systemPrompt', lanes: ['interactive', 'print', 'utility'], live: false, why: '整段替换系统提示(sdk `TaskRequest.systemPrompt`;上游字符数超限 400 响亮拒,本层原样透传)。三条车道都有来源:交互面 = CC QueryParams.systemPrompt,无人值守面 = `--system-prompt[-file]` 一类旗,side-channel 面 = 壳整段给出的那一份。与追加位 `appendSystemPrompt` 不是一个位(那一位归 live 兜底层,见 `LIVE_DEFAULT_FIELDS`)', whyUtilityLane: '有座:side-channel 提交的系统提示由壳整段给出 —— 它不是用户会话的续谈,不该继承用户那一份' },
|
|
45
45
|
{ field: 'reasoningEffort', lanes: ['interactive', 'print', 'utility'], live: false, why: '思考档位(sdk `TaskRequest.reasoningEffort` 七词闭集;上游对表外词 400 响亮拒 ⇒ 本层不预铸第二判官)。档位是请求级的位、与车道无关:交互面 = `/effort` 拨盘,无人值守面 = 档位旗。🔴 端交的必须是**档位词**:「思考 token 数」今天没有上游对位(见 `UPSTREAM_ABSENT_REQUEST_INTENTS` 的 `maxThinkingTokens`),别把一个数字折成档位词发出去', whyUtilityLane: '有座:side-channel 该用显式低档(省钱省时);与 model 同一条理由 —— 本车道上这两位都由壳显式给,不跟用户会话的拨盘走' },
|
|
46
46
|
{ field: 'model', lanes: ['interactive', 'print', 'utility'], live: false, why: '模型选择(sdk `TaskRequest.model`;交互面 = `/model` 中途换模型的拨盘,无人值守面 = 模型旗 / 部署缺省那一路,side-channel 面 = 壳显式挑的那一只)。三条车道都有来源、都是提交面。🔴 0.79.0 改口:修前「print 的模型走另一条路」这句理由被用户面实测证伪 —— 无人值守车道传了模型名却整键不上请求体,于是同一个坏名字在交互态被引擎 400 点名、在无人值守态却安静换成部署缺省并在首帧回显一个没生效的名字。一个**选择**类声明被静默丢掉,后果与收紧类声明被静默丢掉同形(端不读回执就以为生效)—— 与 `excludeTools` 补 print 座同律。本层原样透传、不预判模型名(名字的合法性归引擎,本层不铸第二判官)', whyUtilityLane: '有座:side-channel 显式挑便宜的那只模型(不跟用户会话的 `/model` 拨盘走)' },
|
|
47
|
-
{ field: 'images', lanes: ['interactive'], live: false, why: '
|
|
47
|
+
{ field: 'images', lanes: ['interactive', 'print'], live: false, why: '图片输入(sdk `TaskRequest.images`;base64 / url 两形,原样透传)。两条用户车道都是提交面、都有来源:交互面 = 粘贴图与 `@` 图片像素,一次性车道 = 结构化输入里的图片块。张数、单张与合计的座位判定归人类提交装配口 `encodeHumanTurn`(两条车道同一份判定,本表不另判);请求体与图片张数的上限归上游判', whyUtilityLane: '无座:贴图是交互动作,side-channel 的提交体里没有图片块' },
|
|
48
48
|
{ field: 'resumeAt/resumeAtMode/restoreFiles/rewindFilesTo', lanes: ['interactive'], live: false, why: 'E18 `/rewind` 是交互命令;四键同生同灭(CC-145:core 6.0.0 起 both 臂发 restoreFiles;CC-223 起退役键 rewindFiles 不再有座 —— 交它按表外子键响亮拒;resumeAtMode 是 both/conversation 两臂恒带的排他截语义位)', whyUtilityLane: '无座:回退是交互命令,而 side-channel 是一次性的独立会话,没有可回退的历史' },
|
|
49
49
|
{ field: 'clientContext', lanes: ['interactive'], live: false, why: 'IANA 时区 + 可选邮箱 → core 本地化 `# Environment` 的 today;print 同样跑在用户机器上,缺席让引擎误标 (UTC)', gap: true, whyUtilityLane: '无座:本地化 today 的用途在用户会话的环境段,而 side-channel 的系统提示由壳整段给出 —— 这一列我判不准要不要(与本行 `gap` 同一条待办:要补先单独立项)' },
|
|
50
50
|
{ field: 'scratchpadDir', lanes: ['interactive'], live: true, why: '[816]③ per-session 暂存目录;print 也有 session,缺席让 `-p` 的工具写不进 exemptDir', gap: true, whyUtilityLane: '无座:per-session 暂存目录是给**工具**写的,零工具面上没人写' },
|
|
@@ -458,7 +458,7 @@ const withoutRetiredAttachmentsKeys = (v) => {
|
|
|
458
458
|
return v;
|
|
459
459
|
let drop;
|
|
460
460
|
for (const key of Object.keys(v)) {
|
|
461
|
-
const why =
|
|
461
|
+
const why = retiredAttachmentsKeyOf(key, 'key')?.why;
|
|
462
462
|
if (why === undefined)
|
|
463
463
|
continue;
|
|
464
464
|
const d = Object.getOwnPropertyDescriptor(v, key);
|
|
@@ -483,13 +483,6 @@ const refuseBadExcludeAllTools = (v) => {
|
|
|
483
483
|
`收到 ${coarseShape(v)}。这一位是**整只工具面卸载**的收紧声明:本层若把坏值静默删键,这一次运行会挂上声明人以为已经卸掉的全部工具。` +
|
|
484
484
|
'错误文本只报形状,不回显值。');
|
|
485
485
|
};
|
|
486
|
-
const RETIRED_APPROVER_POSTURE_KEY = 'approverPosture';
|
|
487
|
-
const refuseRetiredApproverPosture = () => {
|
|
488
|
-
throw new TypeError('buildTaskRequest: "approverPosture" 是退役键(引擎 core 7.34.0 起在任务规格入口按名拒收;服务端 7.106.0 起提交体带它整条 400 ' +
|
|
489
|
-
'request.body_shape,unknownKeys 点名它)。它只是一句渲给模型看的审批姿态声明,从不授权任何东西 —— 删掉它不改变这一次运行被允许做什么。' +
|
|
490
|
-
'本包在装配前拒:在场即拒,任何值同判(undefined / null = 缺席)。处置:删掉这个键,不要改发别的键来顶替它;' +
|
|
491
|
-
'若确实要引擎侧放行审批,那是另一件事:显式给权限模式 permissionMode(那是一项授权,受部署策略管)。错误文本只报键名,不回显值。');
|
|
492
|
-
};
|
|
493
486
|
const refuseBadFileHistory = (v) => {
|
|
494
487
|
if (v === undefined || v === null)
|
|
495
488
|
return;
|
|
@@ -715,17 +708,12 @@ export function assembleTaskRequest(input, lane) {
|
|
|
715
708
|
};
|
|
716
709
|
const unknownKeys = [];
|
|
717
710
|
const lateOmitted = [];
|
|
718
|
-
let retiredApproverPosture = false;
|
|
719
711
|
for (const key of Object.keys(src)) {
|
|
720
712
|
if (hasOwn(INPUT_KEY_ROUTES, key))
|
|
721
713
|
continue;
|
|
722
714
|
const stray = Reflect.get(src, key);
|
|
723
715
|
if (!present(stray))
|
|
724
716
|
continue;
|
|
725
|
-
if (key === RETIRED_APPROVER_POSTURE_KEY) {
|
|
726
|
-
retiredApproverPosture = true;
|
|
727
|
-
continue;
|
|
728
|
-
}
|
|
729
717
|
const route = routeOfTopLevelKey(key);
|
|
730
718
|
if (route === undefined) {
|
|
731
719
|
unknownKeys.push(key);
|
|
@@ -756,8 +744,6 @@ export function assembleTaskRequest(input, lane) {
|
|
|
756
744
|
retiredRewindFiles = true;
|
|
757
745
|
unknownKeys.push(`rewind.${sub}`);
|
|
758
746
|
}
|
|
759
|
-
if (retiredApproverPosture)
|
|
760
|
-
refuseRetiredApproverPosture();
|
|
761
747
|
if (retiredRewindFiles) {
|
|
762
748
|
throw new TypeError('buildTaskRequest: "rewind.rewindFiles" 是退役键(引擎 core 6.0.0 起退役:「逐轮捕获」那一义被引擎忽略 —— 文件首触追踪恒开,' +
|
|
763
749
|
'无需请求;「回退时一并还原文件」那一义被引擎拒收、改名为 restoreFiles)。本包在装配前拒:在场即拒,true / false 同判。' +
|
|
@@ -46,3 +46,14 @@ export interface ParkedResumeStartupDetail {
|
|
|
46
46
|
}
|
|
47
47
|
export declare function parkedResumeStartupFromError(err: unknown, decision?: ParkedResumeStartupDecision): ParkedResumeStartupDetail | null;
|
|
48
48
|
export declare function parkedResumeStartupContent(detail: ParkedResumeStartupDetail): string;
|
|
49
|
+
export interface CheckpointUnsupportedVersionDetail {
|
|
50
|
+
code: 'checkpoint.unsupported_version';
|
|
51
|
+
retriable: true;
|
|
52
|
+
}
|
|
53
|
+
export declare function checkpointUnsupportedVersionFromError(err: unknown): CheckpointUnsupportedVersionDetail | null;
|
|
54
|
+
export type CheckpointUnsupportedParkKind = 'tool_approval' | 'plan_review' | 'resource_park' | 'wake' | 'workflow_host';
|
|
55
|
+
export interface CheckpointUnsupportedVersionContext {
|
|
56
|
+
readonly parkKind?: CheckpointUnsupportedParkKind;
|
|
57
|
+
readonly runId?: string;
|
|
58
|
+
}
|
|
59
|
+
export declare function checkpointUnsupportedVersionContent(detail: CheckpointUnsupportedVersionDetail, ctx?: CheckpointUnsupportedVersionContext): string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readErrorNumber, readErrorString } from './wireFailureShape.js';
|
|
2
|
-
import { RESUME_CONTEXT_UNAVAILABLE, RESUME_PLACEMENT_MISMATCH, RESUME_PREFLIGHT_REJECTED, RESUME_POLICY_FOLD_CODE, PARKED_RESUME_STARTUP_FAILED, isStatusDerivedCoarseCode, RESUME_SESSION_NOT_FOUND, } from './engineErrorCodes.js';
|
|
2
|
+
import { RESUME_CONTEXT_UNAVAILABLE, RESUME_PLACEMENT_MISMATCH, RESUME_PREFLIGHT_REJECTED, RESUME_POLICY_FOLD_CODE, PARKED_RESUME_STARTUP_FAILED, isStatusDerivedCoarseCode, RESUME_SESSION_NOT_FOUND, REQUEST_FIELD_CONFLICT, CHECKPOINT_UNSUPPORTED_VERSION, refusalSaysStillPending, } from './engineErrorCodes.js';
|
|
3
3
|
import { capForDisplay } from './fleetTaskDesc.js';
|
|
4
4
|
import { resumeRetryLaterFromError } from './wireErrorTriage.js';
|
|
5
5
|
export const RESUME_REFUSAL_CODES = Object.freeze([
|
|
@@ -88,8 +88,8 @@ export function resumePolicyBlockContent(detail) {
|
|
|
88
88
|
export { resumeReopenFromError, resumeReopenContent } from './hitl/suspendedReopen.js';
|
|
89
89
|
const RESUME_SESSION_NOT_FOUND_TAIL = `(${RESUME_SESSION_NOT_FOUND})`;
|
|
90
90
|
const REQUIRE_EXISTING_BY_STATUS = new Map([
|
|
91
|
-
[404, Object.freeze({ form: 'session_not_found', coarse: 'not_found.resource' })],
|
|
92
|
-
[422, Object.freeze({ form: 'session_id_missing', coarse: 'request.unprocessable' })],
|
|
91
|
+
[404, Object.freeze({ form: 'session_not_found', code: RESUME_SESSION_NOT_FOUND, coarse: 'not_found.resource' })],
|
|
92
|
+
[422, Object.freeze({ form: 'session_id_missing', code: REQUEST_FIELD_CONFLICT, coarse: 'request.unprocessable' })],
|
|
93
93
|
]);
|
|
94
94
|
export function requireExistingSessionRefusalFromError(err) {
|
|
95
95
|
if (typeof err !== 'object' || err === null)
|
|
@@ -101,7 +101,7 @@ export function requireExistingSessionRefusalFromError(err) {
|
|
|
101
101
|
if (byStatus === undefined)
|
|
102
102
|
return null;
|
|
103
103
|
const code = o['errorCode'];
|
|
104
|
-
if (code ===
|
|
104
|
+
if (code === byStatus.code)
|
|
105
105
|
return Object.freeze({ code: RESUME_SESSION_NOT_FOUND, form: byStatus.form });
|
|
106
106
|
if (code !== byStatus.coarse)
|
|
107
107
|
return null;
|
|
@@ -196,3 +196,60 @@ const PARKED_RESUME_STARTUP_SENTENCES = Object.freeze({
|
|
|
196
196
|
export function parkedResumeStartupContent(detail) {
|
|
197
197
|
return detail.cause === 'resume_rejected' ? PARKED_RESUME_STARTUP_SENTENCES.resume_rejected : PARKED_RESUME_STARTUP_SENTENCES.undetermined;
|
|
198
198
|
}
|
|
199
|
+
export function checkpointUnsupportedVersionFromError(err) {
|
|
200
|
+
if (typeof err !== 'object' || err === null)
|
|
201
|
+
return null;
|
|
202
|
+
let code;
|
|
203
|
+
try {
|
|
204
|
+
code = err.errorCode;
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
if (code !== CHECKPOINT_UNSUPPORTED_VERSION || !refusalSaysStillPending(err))
|
|
210
|
+
return null;
|
|
211
|
+
return { code: CHECKPOINT_UNSUPPORTED_VERSION, retriable: true };
|
|
212
|
+
}
|
|
213
|
+
function checkpointUnsupportedHasRun(kind) {
|
|
214
|
+
switch (kind) {
|
|
215
|
+
case 'tool_approval':
|
|
216
|
+
case 'plan_review':
|
|
217
|
+
case 'resource_park':
|
|
218
|
+
return true;
|
|
219
|
+
case 'wake':
|
|
220
|
+
case 'workflow_host':
|
|
221
|
+
return false;
|
|
222
|
+
default:
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const CHECKPOINT_UNSUPPORTED_WHAT = 'This server cannot continue this parked work in the form it was stored in';
|
|
227
|
+
const CHECKPOINT_UNSUPPORTED_STILL_WAITING = 'Nothing was decided or resumed and the parked work is still waiting, but sending the same request again will not by itself continue it';
|
|
228
|
+
const CHECKPOINT_UNSUPPORTED_DRAIN = " — whoever operates this deployment can find such parked work before an upgrade with the server's pre-upgrade drain check";
|
|
229
|
+
export function checkpointUnsupportedVersionContent(detail, ctx) {
|
|
230
|
+
void detail;
|
|
231
|
+
let kind;
|
|
232
|
+
let runId;
|
|
233
|
+
try {
|
|
234
|
+
kind = ctx?.parkKind;
|
|
235
|
+
runId = ctx?.runId;
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
kind = undefined;
|
|
239
|
+
runId = undefined;
|
|
240
|
+
}
|
|
241
|
+
const hasRun = checkpointUnsupportedHasRun(kind);
|
|
242
|
+
let outlet;
|
|
243
|
+
if (hasRun === true) {
|
|
244
|
+
const named = typeof runId === 'string' && runId.length > 0 ? ` (${capForDisplay(runId, 80)})` : '';
|
|
245
|
+
outlet = `If it was parked before this server was upgraded, cancel its run${named} first, then submit the work again as a new task`;
|
|
246
|
+
}
|
|
247
|
+
else if (hasRun === false) {
|
|
248
|
+
outlet = 'If it was parked before this server was upgraded, there is no run to cancel: start a new task in that conversation';
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
outlet =
|
|
252
|
+
'If it was parked before this server was upgraded, submit the work again as a new task: when it still has a run waiting on it (a tool approval, a plan review or a paused resource), cancel that run first; when it was waiting to be woken up, or was a workflow step continuing its host conversation, there is no run to cancel, so start a new task in that conversation';
|
|
253
|
+
}
|
|
254
|
+
return [CHECKPOINT_UNSUPPORTED_WHAT, CHECKPOINT_UNSUPPORTED_STILL_WAITING, outlet + CHECKPOINT_UNSUPPORTED_DRAIN].join(' · ');
|
|
255
|
+
}
|
|
@@ -109,17 +109,17 @@ export function rewindConversationDoctorDetail(reading) {
|
|
|
109
109
|
}
|
|
110
110
|
export function rewindRestoreFilesEpochDetail(reading) {
|
|
111
111
|
if (reading.kind !== 'present') {
|
|
112
|
-
return 'restore-files request
|
|
112
|
+
return 'restore-files request key not observed — this process has no usable capabilities reading for this engine, so a rewind with code restore still sends the key';
|
|
113
113
|
}
|
|
114
114
|
switch (reading.restoreFilesEpoch) {
|
|
115
115
|
case 'on':
|
|
116
116
|
return 'this engine announces the restore-files request key (tracked-set restore semantics)';
|
|
117
117
|
case 'off':
|
|
118
|
-
return 'this engine does not announce the restore-files request key
|
|
118
|
+
return 'this engine does not announce the restore-files request key, so a rewind with code restore built from this reading leaves the key out and moves the conversation only';
|
|
119
119
|
case 'not_reported':
|
|
120
|
-
return 'this engine does not report the restore-files epoch bit (older engine)
|
|
120
|
+
return 'this engine does not report the restore-files epoch bit (older engine), so a rewind with code restore built from this reading leaves the key out and moves the conversation only';
|
|
121
121
|
case 'malformed':
|
|
122
|
-
return 'the restore-files epoch bit is reported in an unreadable shape
|
|
122
|
+
return 'the restore-files epoch bit is reported in an unreadable shape, so a rewind with code restore built from this reading leaves the key out and moves the conversation only';
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
export function forgetRewindArchiveReading(baseUrl) {
|
package/dist/rewindWireCaps.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RewindArchiveReading } from './rewindArchiveCapability.js';
|
|
1
2
|
export interface SeamRewindSpec {
|
|
2
3
|
resumeAt?: string;
|
|
3
4
|
resumeAtMode?: 'at' | 'before';
|
|
@@ -5,5 +6,5 @@ export interface SeamRewindSpec {
|
|
|
5
6
|
rewindFilesTo?: string;
|
|
6
7
|
}
|
|
7
8
|
export type RewindMode = 'both' | 'conversation' | 'code';
|
|
8
|
-
export declare function rewindSpecForMode(mode: RewindMode, targetEntryId: string): SeamRewindSpec;
|
|
9
|
+
export declare function rewindSpecForMode(mode: RewindMode, targetEntryId: string, reading?: RewindArchiveReading): SeamRewindSpec;
|
|
9
10
|
export declare function projectRewind(pending: SeamRewindSpec | undefined): SeamRewindSpec;
|