@sema-agent/client-core 0.98.0 → 0.99.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 +199 -0
- package/README.md +35 -22
- package/dist/adapt/arms.js +61 -20
- package/dist/adapt/panelTasks.d.ts +1 -1
- package/dist/adapt/panelTasks.js +2 -2
- package/dist/adapter/activeRunSelfHeal.d.ts +4 -3
- package/dist/adapter/activeRunSelfHeal.js +162 -293
- package/dist/adapter/downstream/eventToSdkMessage.js +52 -4
- package/dist/adapter/runStream.js +52 -37
- package/dist/adapter/types.js +2 -1
- package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
- package/dist/agentsWireCaps.d.ts +0 -3
- package/dist/agentsWireCaps.js +33 -24
- package/dist/cloudConfigWireCaps.d.ts +1 -1
- package/dist/cloudConfigWireCaps.js +26 -4
- package/dist/controlRouter.d.ts +4 -2
- package/dist/controlRouter.js +39 -51
- package/dist/coreValuePorts.d.ts +26 -1
- package/dist/coreValuePorts.js +10 -0
- package/dist/corruptSessionCopy.d.ts +2 -1
- package/dist/corruptSessionCopy.js +3 -3
- package/dist/declared/supportFloorDeclared.js +1 -1
- package/dist/detachWire.js +3 -2
- package/dist/devicesFace.d.ts +34 -0
- package/dist/devicesFace.js +90 -0
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +3 -0
- package/dist/engineAgentPanelStore.d.ts +7 -0
- package/dist/engineAgentPanelStore.js +14 -0
- package/dist/engineCapReader.d.ts +2 -1
- package/dist/engineCapReader.js +7 -5
- package/dist/engineCapsCache.d.ts +8 -0
- package/dist/engineCapsCache.js +59 -6
- package/dist/engineCapsChange.d.ts +2 -0
- package/dist/engineCapsChange.js +9 -0
- package/dist/engineErrorCodes.d.ts +2 -1
- package/dist/engineErrorCodes.js +2 -7
- package/dist/engineRowRef.js +3 -0
- package/dist/engineSessionMessages.d.ts +1 -0
- package/dist/engineSessionMessages.js +7 -1
- package/dist/engineTargetSeat.d.ts +27 -0
- package/dist/engineTargetSeat.js +199 -0
- package/dist/engineWireFor.js +3 -8
- package/dist/env/uiLanguage.d.ts +2 -1
- package/dist/env/uiLanguage.js +3 -2
- package/dist/eventLeg.d.ts +8 -0
- package/dist/eventLeg.js +61 -41
- package/dist/fileHistoryCaptureCapability.d.ts +2 -1
- package/dist/fileHistoryCaptureCapability.js +12 -18
- package/dist/fileHistoryLegNotice.d.ts +2 -1
- package/dist/fileHistoryLegNotice.js +3 -3
- package/dist/frameBinding.d.ts +3 -0
- package/dist/frameBinding.js +12 -0
- package/dist/gateOutcome.js +16 -2
- package/dist/gateVocabulary.d.ts +8 -7
- package/dist/gateVocabulary.js +71 -73
- package/dist/generated/engineFactTables.d.ts +17 -1
- package/dist/generated/engineFactTables.js +29 -0
- package/dist/generated/engineNoticeTables.js +9 -3
- package/dist/generated/settingsSchemaFns.d.ts +6 -0
- package/dist/generated/settingsSchemaFns.js +57 -0
- package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
- package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
- package/dist/generated/settingsSchemaTables.d.ts +1 -0
- package/dist/generated/settingsSchemaTables.js +4 -0
- package/dist/generated/settingsSchemaTypes.d.ts +105 -0
- package/dist/generated/settingsSchemaTypes.js +1 -0
- package/dist/hitl/allowRuleShadow.d.ts +2 -1
- package/dist/hitl/allowRuleShadow.js +17 -14
- package/dist/hitl/approvalCardReasons.d.ts +3 -2
- package/dist/hitl/approvalCardReasons.js +27 -28
- package/dist/hitl/approvalHolds.d.ts +3 -0
- package/dist/hitl/approvalHolds.js +73 -29
- package/dist/hitl/askClassPair.d.ts +1 -1
- package/dist/hitl/askClassPair.js +16 -0
- package/dist/hitl/askGateWire.js +2 -1
- package/dist/hitl/askSettlementLine.d.ts +14 -4
- package/dist/hitl/askSettlementLine.js +67 -47
- package/dist/hitl/automaticAnswerVerdict.d.ts +2 -1
- package/dist/hitl/automaticAnswerVerdict.js +8 -8
- package/dist/hitl/crashConvergedNotice.d.ts +5 -4
- package/dist/hitl/crashConvergedNotice.js +28 -41
- package/dist/hitl/frameRouter.js +7 -8
- package/dist/hitl/hitlBridge.d.ts +1 -0
- package/dist/hitl/hitlBridge.js +3 -3
- package/dist/hitl/persistedRulesWire.d.ts +6 -5
- package/dist/hitl/persistedRulesWire.js +55 -73
- package/dist/hitl/planReviewWire.d.ts +5 -0
- package/dist/hitl/planReviewWire.js +8 -0
- package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
- package/dist/hitl/sessionPolicyDeliverable.js +46 -3
- package/dist/hitl/sessionPolicyWire.d.ts +2 -1
- package/dist/hitl/sessionPolicyWire.js +23 -24
- package/dist/hitl/suspendedReopen.d.ts +2 -1
- package/dist/hitl/suspendedReopen.js +7 -10
- package/dist/hitl/toolApprovalWire.d.ts +17 -5
- package/dist/hitl/toolApprovalWire.js +79 -40
- package/dist/hooksWireCaps.js +145 -56
- package/dist/host.d.ts +21 -0
- package/dist/hostTurnSettings.d.ts +71 -0
- package/dist/hostTurnSettings.js +291 -0
- package/dist/humanTurn.d.ts +14 -1
- package/dist/humanTurn.js +100 -12
- package/dist/humanTurnRead.d.ts +2 -0
- package/dist/humanTurnRead.js +22 -1
- package/dist/i18n/messages.en.d.ts +582 -0
- package/dist/i18n/messages.en.js +582 -0
- package/dist/i18n/messages.zh.js +718 -1
- package/dist/index.d.ts +29 -13
- package/dist/index.js +18 -9
- package/dist/inheritEnvCapability.d.ts +3 -2
- package/dist/inheritEnvCapability.js +3 -3
- package/dist/inheritEnvWire.d.ts +3 -2
- package/dist/inheritEnvWire.js +12 -14
- package/dist/interactiveHalt.js +17 -6
- package/dist/liveModelCatalog.d.ts +2 -1
- package/dist/liveModelCatalog.js +14 -8
- package/dist/mcpPanel.d.ts +10 -1
- package/dist/mcpPanel.js +40 -13
- package/dist/mcpProbeCapability.d.ts +2 -1
- package/dist/mcpProbeCapability.js +7 -11
- package/dist/mcpProbeWire.d.ts +3 -1
- package/dist/mcpProbeWire.js +5 -0
- package/dist/mcpWireCaps.d.ts +34 -0
- package/dist/mcpWireCaps.js +117 -17
- package/dist/memoryEntriesWire.js +5 -10
- package/dist/model/onboardJudgement.d.ts +93 -0
- package/dist/model/onboardJudgement.js +415 -0
- package/dist/model/tierVocabulary.d.ts +2 -0
- package/dist/model/tierVocabulary.js +17 -5
- package/dist/modelCapabilityProbe.d.ts +64 -0
- package/dist/modelCapabilityProbe.js +600 -0
- package/dist/modelIdentityResolvability.d.ts +3 -0
- package/dist/modelIdentityResolvability.js +26 -17
- package/dist/ownKey.d.ts +7 -0
- package/dist/ownKey.js +34 -0
- package/dist/panelReduce.d.ts +6 -1
- package/dist/panelReduce.js +50 -3
- package/dist/permissionRuleIssue.js +2 -0
- package/dist/permissionRulesWriteCapability.d.ts +2 -1
- package/dist/permissionRulesWriteCapability.js +8 -6
- package/dist/pluginHooksWire.d.ts +46 -3
- package/dist/pluginHooksWire.js +217 -11
- package/dist/printModelStatus.d.ts +63 -0
- package/dist/printModelStatus.js +155 -0
- package/dist/request/taskRequest.d.ts +11 -5
- package/dist/request/taskRequest.js +112 -16
- package/dist/resumeRefusalCopy.d.ts +12 -9
- package/dist/resumeRefusalCopy.js +70 -143
- package/dist/retryStatus.d.ts +37 -0
- package/dist/retryStatus.js +79 -0
- package/dist/scenarioRefusal.d.ts +9 -0
- package/dist/scenarioRefusal.js +111 -0
- package/dist/seam.d.ts +25 -1
- package/dist/seam.js +10 -1
- package/dist/seatContract.d.ts +260 -10
- package/dist/seatContract.js +692 -19
- package/dist/selfOrchestrationDenial.js +7 -19
- package/dist/sessionIdSegment.d.ts +6 -0
- package/dist/sessionIdSegment.js +24 -0
- package/dist/sessionMemoryStatus.js +6 -11
- package/dist/sessionPolicyCapability.d.ts +2 -1
- package/dist/sessionPolicyCapability.js +8 -6
- package/dist/settingsHooksSalvage.d.ts +44 -0
- package/dist/settingsHooksSalvage.js +211 -0
- package/dist/skillToolListsCapability.d.ts +2 -1
- package/dist/skillToolListsCapability.js +8 -6
- package/dist/sseIdleTriage.js +3 -2
- package/dist/subagent/engineSubagentResume.js +15 -9
- package/dist/subagentContentStore.d.ts +3 -0
- package/dist/subagentContentStore.js +22 -0
- package/dist/toolHistoryMismatch.js +3 -2
- package/dist/toolRoster.d.ts +3 -2
- package/dist/toolRoster.js +21 -20
- package/dist/turnFailurePresentation.d.ts +12 -1
- package/dist/turnFailurePresentation.js +212 -15
- package/dist/usageAnalytics.js +6 -11
- package/dist/userAttachmentEnvelope.d.ts +1 -0
- package/dist/userAttachmentEnvelope.js +37 -7
- package/dist/userAttachmentSeat.d.ts +21 -0
- package/dist/userAttachmentSeat.js +75 -0
- package/dist/userInvokedSkillsCapability.d.ts +11 -1
- package/dist/userInvokedSkillsCapability.js +31 -7
- package/dist/wireErrorTriage.d.ts +7 -0
- package/dist/wireErrorTriage.js +23 -1
- package/dist/wireFailureShape.js +2 -1
- package/dist/wireRefusalCopy.d.ts +13 -1
- package/dist/wireRefusalCopy.js +24 -28
- package/dist/workflowsJournalCapability.d.ts +2 -1
- package/dist/workflowsJournalCapability.js +8 -6
- package/docs/INTEGRATION-CLIENTS.md +542 -30
- package/package.json +5 -5
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { msg, renderMessage } from './i18n/translate.js';
|
|
2
|
+
import { readBlockedBy, readErrorNumber, readErrorString, readThrownSlot } from './wireFailureShape.js';
|
|
2
3
|
import { guardedRead, ownDataField, readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
|
|
3
4
|
import { CORE_RESUME_STARTUP_CAUSES } from './generated/engineFactTables.js';
|
|
4
5
|
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, CHECKPOINT_WALLTIME_AXIS_RETIRED, CHECKPOINT_CONFIG_REFUSED, isRefusedParkCode, refusalSaysStillPending, refusalRetriableReading, } from './engineErrorCodes.js';
|
|
@@ -27,51 +28,30 @@ export function resumeRefusalFromError(err) {
|
|
|
27
28
|
...(timed.retryAfterSec !== undefined ? { retryAfterSec: timed.retryAfterSec } : {}),
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
|
-
export function resumeRefusalContent(detail) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
parts.push('The engine refused it before consuming anything — the parked work is untouched');
|
|
35
|
-
parts.push('Retry with the recorded root, or omit the placement root to inherit it');
|
|
36
|
-
return parts.join(' · ');
|
|
37
|
-
}
|
|
38
|
-
parts.push("The deployment's resume preflight refused this attempt");
|
|
39
|
-
parts.push('The refusal happened before the commit — your decision was not consumed');
|
|
40
|
-
parts.push(detail.waitable
|
|
41
|
-
? 'The engine supplied a wait, so this token stays redeemable once the obstacle clears'
|
|
42
|
-
:
|
|
43
|
-
'The engine supplied no wait, so this refusal does not say whether the token stays redeemable');
|
|
44
|
-
return parts.join(' · ');
|
|
31
|
+
export function resumeRefusalContent(detail, lang) {
|
|
32
|
+
if (detail.code === RESUME_PLACEMENT_MISMATCH)
|
|
33
|
+
return renderMessage(msg('resume.refusal.placementMismatch'), lang);
|
|
34
|
+
return renderMessage(msg(detail.waitable ? 'resume.refusal.preflightWaitable' : 'resume.refusal.preflightNoWait'), lang);
|
|
45
35
|
}
|
|
46
36
|
export function resumePolicyBlockFromError(err) {
|
|
47
37
|
if (typeof err !== 'object' || err === null)
|
|
48
38
|
return null;
|
|
49
39
|
const o = err;
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
outer = o['errorCode'];
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
40
|
+
const outer = guardedRead(() => ownDataField(err, 'errorCode'));
|
|
57
41
|
if (outer !== RESUME_POLICY_FOLD_CODE)
|
|
58
42
|
return null;
|
|
59
43
|
return { blockedBy: readBlockedBy(o) };
|
|
60
44
|
}
|
|
61
|
-
export function resumePolicyBlockContent(detail) {
|
|
45
|
+
export function resumePolicyBlockContent(detail, lang) {
|
|
62
46
|
const b = detail.blockedBy;
|
|
63
47
|
const reason = b.kind === 'named'
|
|
64
48
|
? isStatusDerivedCoarseCode(b.code)
|
|
65
|
-
?
|
|
66
|
-
:
|
|
49
|
+
? msg('resume.refusal.policyBlockReason.coarse', { code: b.code })
|
|
50
|
+
: msg('resume.refusal.policyBlockReason.named', { code: capForDisplay(b.code, 80) })
|
|
67
51
|
: b.kind === 'absent'
|
|
68
|
-
? '
|
|
69
|
-
: '
|
|
70
|
-
return
|
|
71
|
-
'The engine refused to resume this parked work at its admission check (the engine reports that its admission policy changed since the work was first accepted)',
|
|
72
|
-
reason,
|
|
73
|
-
"This refusal does not say whether anything was consumed before it or whether a retry would pass — check the task's current state before deciding again, and ask whoever operates this deployment if it keeps happening",
|
|
74
|
-
].join(' · ');
|
|
52
|
+
? msg('resume.refusal.policyBlockReason.absent')
|
|
53
|
+
: msg('resume.refusal.policyBlockReason.unreadable');
|
|
54
|
+
return renderMessage(msg('resume.refusal.policyBlock', { reason }), lang);
|
|
75
55
|
}
|
|
76
56
|
export { resumeReopenFromError, resumeReopenContent } from './hitl/suspendedReopen.js';
|
|
77
57
|
const REQUIRE_EXISTING_BY_STATUS = new Map([
|
|
@@ -82,27 +62,29 @@ export function requireExistingSessionRefusalFromError(err) {
|
|
|
82
62
|
if (typeof err !== 'object' || err === null)
|
|
83
63
|
return null;
|
|
84
64
|
try {
|
|
85
|
-
const
|
|
86
|
-
const status = o['status'];
|
|
65
|
+
const status = readThrownSlot(err, 'status', 'data');
|
|
87
66
|
const byStatus = typeof status === 'number' ? REQUIRE_EXISTING_BY_STATUS.get(status) : undefined;
|
|
88
67
|
if (byStatus === undefined)
|
|
89
68
|
return null;
|
|
90
|
-
return
|
|
69
|
+
return readThrownSlot(err, 'errorCode', 'data') === byStatus.code ? Object.freeze({ code: RESUME_SESSION_NOT_FOUND, form: byStatus.form }) : null;
|
|
91
70
|
}
|
|
92
71
|
catch {
|
|
93
72
|
return null;
|
|
94
73
|
}
|
|
95
74
|
}
|
|
96
|
-
const
|
|
97
|
-
session_not_found: '
|
|
98
|
-
session_id_missing: '
|
|
75
|
+
const REQUIRE_EXISTING_SESSION_KEYS = Object.freeze({
|
|
76
|
+
session_not_found: 'resume.refusal.requireExisting.sessionNotFound',
|
|
77
|
+
session_id_missing: 'resume.refusal.requireExisting.sessionIdMissing',
|
|
99
78
|
});
|
|
100
|
-
const REQUIRE_EXISTING_SESSION_GENERIC = '
|
|
101
|
-
export function requireExistingSessionRefusalContent(detail) {
|
|
79
|
+
const REQUIRE_EXISTING_SESSION_GENERIC = 'resume.refusal.requireExisting.generic';
|
|
80
|
+
export function requireExistingSessionRefusalContent(detail, lang) {
|
|
81
|
+
return renderMessage(msg(requireExistingSessionKey(detail)), lang);
|
|
82
|
+
}
|
|
83
|
+
function requireExistingSessionKey(detail) {
|
|
102
84
|
try {
|
|
103
85
|
const form = detail?.form;
|
|
104
|
-
return typeof form === 'string' && Object.hasOwn(
|
|
105
|
-
?
|
|
86
|
+
return typeof form === 'string' && Object.hasOwn(REQUIRE_EXISTING_SESSION_KEYS, form)
|
|
87
|
+
? REQUIRE_EXISTING_SESSION_KEYS[form]
|
|
106
88
|
: REQUIRE_EXISTING_SESSION_GENERIC;
|
|
107
89
|
}
|
|
108
90
|
catch {
|
|
@@ -112,8 +94,7 @@ export function requireExistingSessionRefusalContent(detail) {
|
|
|
112
94
|
export function resumeContextUnavailableFromError(err) {
|
|
113
95
|
if (typeof err !== 'object' || err === null)
|
|
114
96
|
return null;
|
|
115
|
-
|
|
116
|
-
if (e.errorCode !== RESUME_CONTEXT_UNAVAILABLE)
|
|
97
|
+
if (readThrownSlot(err, 'errorCode', 'data') !== RESUME_CONTEXT_UNAVAILABLE)
|
|
117
98
|
return null;
|
|
118
99
|
const sec = readErrorNumber(err, 'staleAfterSec');
|
|
119
100
|
const staleSec = sec !== undefined && Number.isInteger(sec) && sec >= 1 ? sec : undefined;
|
|
@@ -125,17 +106,11 @@ export function resumeContextUnavailableFromError(err) {
|
|
|
125
106
|
...(runId !== undefined ? { runId } : {}),
|
|
126
107
|
};
|
|
127
108
|
}
|
|
128
|
-
export function resumeContextUnavailableContent(d) {
|
|
109
|
+
export function resumeContextUnavailableContent(d, lang) {
|
|
129
110
|
const sec = d.staleAfterSec;
|
|
130
|
-
const retention = typeof sec === 'number' && Number.isSafeInteger(sec) && sec >= 1 ?
|
|
131
|
-
const third = (d.runId !== undefined
|
|
132
|
-
|
|
133
|
-
: 'The error carries no run id: go back to the run list, find this run and recover it yourself, then decide again; raising the conversation retention time only prevents this from happening again and cannot rescue this one') + retention;
|
|
134
|
-
return [
|
|
135
|
-
'This approval has nowhere to be delivered: the conversation that started this run has no usable context to continue it right now',
|
|
136
|
-
'Nothing was decided and your decision was not consumed; this card is still waiting',
|
|
137
|
-
third,
|
|
138
|
-
].join(' · ');
|
|
111
|
+
const retention = typeof sec === 'number' && Number.isSafeInteger(sec) && sec >= 1 ? msg('resume.refusal.contextRetention', { sec }) : '';
|
|
112
|
+
const third = msg(d.runId !== undefined ? 'resume.refusal.contextThird.withRun' : 'resume.refusal.contextThird.noRun', { retention });
|
|
113
|
+
return renderMessage(msg('resume.refusal.contextUnavailable', { third }), lang);
|
|
139
114
|
}
|
|
140
115
|
function parkedResumeStartupCauseWord(err) {
|
|
141
116
|
let named;
|
|
@@ -150,6 +125,7 @@ function parkedResumeStartupCauseWord(err) {
|
|
|
150
125
|
function isResumeStartupCause(v) {
|
|
151
126
|
return typeof v === 'string' && CORE_RESUME_STARTUP_CAUSES.includes(v);
|
|
152
127
|
}
|
|
128
|
+
const RESUME_CAUSE_CORE_AHEAD = Object.freeze(['transcript_corrupt']);
|
|
153
129
|
const _startupCausePin = true;
|
|
154
130
|
void _startupCausePin;
|
|
155
131
|
export function parkedResumeStartupFromError(err, decision) {
|
|
@@ -176,62 +152,28 @@ export function parkedResumeStartupFromError(err, decision) {
|
|
|
176
152
|
denyStaysOpen: true,
|
|
177
153
|
};
|
|
178
154
|
}
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
'The engine could not start the parked work to apply this decision (its session may be gone, or the engine rejected the decision itself; this client cannot tell which)',
|
|
183
|
-
PARKED_RESUME_STARTUP_STATE,
|
|
184
|
-
'If the card is still there, decide it again from the fresh list',
|
|
185
|
-
].join(' · '),
|
|
186
|
-
undetermined: [
|
|
187
|
-
'The engine could not start the parked work to apply this decision',
|
|
188
|
-
PARKED_RESUME_STARTUP_STATE,
|
|
189
|
-
'If the card is still there: when the engine rejected the decision itself (for example an answer given to the wrong question), correct it and decide again; when the approved tool is one the agent inherits from the task that started it, approving it again will not work on this server — deny the card, or wait for a server upgrade',
|
|
190
|
-
].join(' · '),
|
|
155
|
+
const PARKED_RESUME_STARTUP_KEYS = Object.freeze({
|
|
156
|
+
resume_rejected: 'resume.refusal.startup.resumeRejected',
|
|
157
|
+
undetermined: 'resume.refusal.startup.undetermined',
|
|
191
158
|
});
|
|
192
|
-
const
|
|
193
|
-
environment:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
'The engine could not start the parked work to apply this decision: the session of the agent it would resume is gone',
|
|
200
|
-
PARKED_RESUME_STARTUP_STATE,
|
|
201
|
-
'If the card is still there, deny it to close it; the work it was waiting on cannot be resumed',
|
|
202
|
-
].join(' · '),
|
|
203
|
-
tool_unavailable: [
|
|
204
|
-
'The engine could not start the parked work to apply this decision: the approved tool is not available to the resumed work (it is gone, or a different tool now has its name)',
|
|
205
|
-
PARKED_RESUME_STARTUP_STATE,
|
|
206
|
-
'This approval cannot run as decided — if the card is still there, decide it afresh (denying it settles it)',
|
|
207
|
-
].join(' · '),
|
|
208
|
-
configuration: [
|
|
209
|
-
"The engine could not start the parked work to apply this decision: this deployment's configuration refuses the resumed work",
|
|
210
|
-
PARKED_RESUME_STARTUP_STATE,
|
|
211
|
-
'Deciding again under the same configuration fails the same way — the configuration has to change first; denying the card settles it',
|
|
212
|
-
].join(' · '),
|
|
213
|
-
decision_rejected: [
|
|
214
|
-
'The engine could not start the parked work to apply this decision: the engine rejected the decision itself (for example an answer given to the wrong question, or an edited input the constraints refuse)',
|
|
215
|
-
PARKED_RESUME_STARTUP_STATE,
|
|
216
|
-
'If the card is still there, correct the decision and decide it again from the fresh list',
|
|
217
|
-
].join(' · '),
|
|
159
|
+
const PARKED_RESUME_STARTUP_CAUSE_KEYS = Object.freeze({
|
|
160
|
+
environment: 'resume.refusal.startup.cause.environment',
|
|
161
|
+
session_gone: 'resume.refusal.startup.cause.sessionGone',
|
|
162
|
+
tool_unavailable: 'resume.refusal.startup.cause.toolUnavailable',
|
|
163
|
+
configuration: 'resume.refusal.startup.cause.configuration',
|
|
164
|
+
decision_rejected: 'resume.refusal.startup.cause.decisionRejected',
|
|
165
|
+
transcript_corrupt: 'resume.refusal.startup.cause.transcriptCorrupt',
|
|
218
166
|
});
|
|
219
|
-
export function parkedResumeStartupContent(detail) {
|
|
167
|
+
export function parkedResumeStartupContent(detail, lang) {
|
|
220
168
|
const word = guardedRead(() => readOwnDataValue(detail, 'startupCause'));
|
|
221
169
|
if (isResumeStartupCause(word))
|
|
222
|
-
return
|
|
223
|
-
return detail.cause === 'resume_rejected' ?
|
|
170
|
+
return renderMessage(msg(PARKED_RESUME_STARTUP_CAUSE_KEYS[word]), lang);
|
|
171
|
+
return renderMessage(msg(detail.cause === 'resume_rejected' ? PARKED_RESUME_STARTUP_KEYS.resume_rejected : PARKED_RESUME_STARTUP_KEYS.undetermined), lang);
|
|
224
172
|
}
|
|
225
173
|
export function checkpointUnsupportedVersionFromError(err) {
|
|
226
174
|
if (typeof err !== 'object' || err === null)
|
|
227
175
|
return null;
|
|
228
|
-
|
|
229
|
-
try {
|
|
230
|
-
code = err.errorCode;
|
|
231
|
-
}
|
|
232
|
-
catch {
|
|
233
|
-
return null;
|
|
234
|
-
}
|
|
176
|
+
const code = guardedRead(() => ownDataField(err, 'errorCode'));
|
|
235
177
|
if (code !== CHECKPOINT_UNSUPPORTED_VERSION || !refusalSaysStillPending(err))
|
|
236
178
|
return null;
|
|
237
179
|
const writerVersion = readErrorString(err, 'writerVersion');
|
|
@@ -257,10 +199,7 @@ function checkpointUnsupportedHasRun(kind) {
|
|
|
257
199
|
return undefined;
|
|
258
200
|
}
|
|
259
201
|
}
|
|
260
|
-
|
|
261
|
-
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';
|
|
262
|
-
const CHECKPOINT_UNSUPPORTED_DRAIN = " — whoever operates this deployment can find such parked work before an upgrade with the server's pre-upgrade drain check";
|
|
263
|
-
export function checkpointUnsupportedVersionContent(detail, ctx) {
|
|
202
|
+
export function checkpointUnsupportedVersionContent(detail, ctx, lang) {
|
|
264
203
|
let writer;
|
|
265
204
|
let reader;
|
|
266
205
|
try {
|
|
@@ -272,11 +211,7 @@ export function checkpointUnsupportedVersionContent(detail, ctx) {
|
|
|
272
211
|
reader = undefined;
|
|
273
212
|
}
|
|
274
213
|
if (writerEngineIsNewer(writer, reader)) {
|
|
275
|
-
return
|
|
276
|
-
`This parked work was stored by a newer engine version (${String(writer)}) than this engine (${String(reader)})`,
|
|
277
|
-
CHECKPOINT_UNSUPPORTED_STILL_WAITING,
|
|
278
|
-
`Continue it on an engine at version ${String(writer)} or newer`,
|
|
279
|
-
].join(' · ');
|
|
214
|
+
return renderMessage(msg('resume.refusal.checkpoint.newerEngine', { writer: String(writer), reader: String(reader) }), lang);
|
|
280
215
|
}
|
|
281
216
|
let kind;
|
|
282
217
|
let runId;
|
|
@@ -291,17 +226,16 @@ export function checkpointUnsupportedVersionContent(detail, ctx) {
|
|
|
291
226
|
const hasRun = checkpointUnsupportedHasRun(kind);
|
|
292
227
|
let outlet;
|
|
293
228
|
if (hasRun === true) {
|
|
294
|
-
const named = typeof runId === 'string' && runId.length > 0 ?
|
|
295
|
-
outlet =
|
|
229
|
+
const named = typeof runId === 'string' && runId.length > 0 ? msg('resume.refusal.checkpoint.runNamed', { runId: capForDisplay(runId, 80) }) : '';
|
|
230
|
+
outlet = msg('resume.refusal.checkpoint.outletWithRun', { named });
|
|
296
231
|
}
|
|
297
232
|
else if (hasRun === false) {
|
|
298
|
-
outlet = '
|
|
233
|
+
outlet = msg('resume.refusal.checkpoint.outletNoRun');
|
|
299
234
|
}
|
|
300
235
|
else {
|
|
301
|
-
outlet =
|
|
302
|
-
'If it was parked before this server was upgraded, submit the work again as a new task (this client cannot tell which kind of parked work this is, so both ways out are given): 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';
|
|
236
|
+
outlet = msg('resume.refusal.checkpoint.outletUnknownKind');
|
|
303
237
|
}
|
|
304
|
-
return
|
|
238
|
+
return renderMessage(msg('resume.refusal.checkpoint.content', { outlet }), lang);
|
|
305
239
|
}
|
|
306
240
|
const REFUSED_PARK_FIELD_TOKEN = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
|
|
307
241
|
export function refusedParkFromError(failure) {
|
|
@@ -336,16 +270,14 @@ function refusedParkShownRunId(runId) {
|
|
|
336
270
|
function refusedParkWhy(code, field) {
|
|
337
271
|
switch (code) {
|
|
338
272
|
case CHECKPOINT_WALLTIME_AXIS_RETIRED:
|
|
339
|
-
return '
|
|
273
|
+
return msg('resume.refusal.park.whyWalltime');
|
|
340
274
|
case CHECKPOINT_CONFIG_REFUSED:
|
|
341
|
-
return field === 'inheritedGate'
|
|
342
|
-
? 'the permission-mode setting it was parked with can no longer be read'
|
|
343
|
-
: 'the engine refuses the task configuration it was parked with';
|
|
275
|
+
return msg(field === 'inheritedGate' ? 'resume.refusal.park.whyInheritedGate' : 'resume.refusal.park.whyConfigRefused');
|
|
344
276
|
default:
|
|
345
|
-
return '
|
|
277
|
+
return msg('resume.refusal.park.whyUnsupported');
|
|
346
278
|
}
|
|
347
279
|
}
|
|
348
|
-
export function refusedParkContent(input) {
|
|
280
|
+
export function refusedParkContent(input, lang) {
|
|
349
281
|
let what;
|
|
350
282
|
let lane;
|
|
351
283
|
let runId;
|
|
@@ -370,30 +302,25 @@ export function refusedParkContent(input) {
|
|
|
370
302
|
rawCode = field = stillPending = undefined;
|
|
371
303
|
}
|
|
372
304
|
const code = rawCode === CHECKPOINT_WALLTIME_AXIS_RETIRED || rawCode === CHECKPOINT_CONFIG_REFUSED ? rawCode : CHECKPOINT_UNSUPPORTED_VERSION;
|
|
373
|
-
const shownWhat = typeof what === 'string' && what !== '' ? capForDisplay(what, 40) : '
|
|
305
|
+
const shownWhat = typeof what === 'string' && what !== '' ? capForDisplay(what, 40) : msg('resume.refusal.park.whatDefault');
|
|
374
306
|
const why = refusedParkWhy(code, typeof field === 'string' ? field : undefined);
|
|
375
307
|
const shownRun = refusedParkShownRunId(runId);
|
|
376
|
-
const head =
|
|
377
|
-
|
|
378
|
-
const configMayReturn = code === CHECKPOINT_CONFIG_REFUSED && field !== 'inheritedGate' ? ' If that configuration is restored, the same answer can go through again.' : '';
|
|
308
|
+
const head = msg('resume.refusal.park.head', { what: shownWhat, why });
|
|
309
|
+
const configMayReturn = code === CHECKPOINT_CONFIG_REFUSED && field !== 'inheritedGate' ? msg('resume.refusal.park.configMayReturn') : '';
|
|
379
310
|
if (lane === 'print') {
|
|
380
|
-
if (stillPending === false)
|
|
381
|
-
return
|
|
382
|
-
}
|
|
311
|
+
if (stillPending === false)
|
|
312
|
+
return renderMessage(msg('resume.refusal.park.printEnded', { head, code }), lang);
|
|
383
313
|
const cancel = `POST /v1/runs/${shownRun ?? '<run id>'}/cancel`;
|
|
384
|
-
return
|
|
385
|
-
}
|
|
386
|
-
if (stillPending === false) {
|
|
387
|
-
return `${head} The engine ended that parked run, so this conversation is free: send the work again as a new message.`;
|
|
314
|
+
return renderMessage(msg('resume.refusal.park.printHolds', { head, configMayReturn, code, cancel }), lang);
|
|
388
315
|
}
|
|
389
|
-
|
|
316
|
+
if (stillPending === false)
|
|
317
|
+
return renderMessage(msg('resume.refusal.park.interactiveEnded', { head }), lang);
|
|
318
|
+
return renderMessage(msg('resume.refusal.park.interactiveBusy', { head, configMayReturn }), lang);
|
|
390
319
|
}
|
|
391
|
-
export function refusedParkBlockedContent(taskId, lane = 'interactive') {
|
|
320
|
+
export function refusedParkBlockedContent(taskId, lane = 'interactive', lang) {
|
|
392
321
|
const runId = refusedParkShownRunId(taskId);
|
|
393
|
-
const
|
|
394
|
-
if (lane === 'print')
|
|
395
|
-
return
|
|
396
|
-
}
|
|
397
|
-
return (`${head} To free this conversation, send a message to bring the card back and answer it — sema then offers to cancel ` +
|
|
398
|
-
`that run, after which you can send the work again as a new message.`);
|
|
322
|
+
const run = runId ?? '<unknown>';
|
|
323
|
+
if (lane === 'print')
|
|
324
|
+
return renderMessage(msg('resume.refusal.park.blockedPrint', { run, cancel: `POST /v1/runs/${runId ?? '<run id>'}/cancel` }), lang);
|
|
325
|
+
return renderMessage(msg('resume.refusal.park.blockedInteractive', { run }), lang);
|
|
399
326
|
}
|
package/dist/retryStatus.d.ts
CHANGED
|
@@ -71,6 +71,23 @@ export interface BrainStatusPayload {
|
|
|
71
71
|
}
|
|
72
72
|
export declare const BRAIN_STATUS_PAYLOAD_KEYS: readonly ["phase", "detail", "retryInSec", "retryInMs", "attempt", "maxRetries", "errClass", "retryAtMs", "errorStatus", "elapsedMs", "timeoutMs", "providerCondition", "providerConditionSource"];
|
|
73
73
|
export declare function mapBrainStatusToRetry(p: BrainStatusPayload, nowMs: number): RetryStatus | null;
|
|
74
|
+
export interface RetryStatusArmLike {
|
|
75
|
+
readonly phase?: string;
|
|
76
|
+
readonly detail?: string;
|
|
77
|
+
readonly retryInSec?: number;
|
|
78
|
+
readonly retryInMs?: number;
|
|
79
|
+
readonly attempt?: number;
|
|
80
|
+
readonly maxRetries?: number;
|
|
81
|
+
readonly errClass?: string;
|
|
82
|
+
readonly retryAtMs?: number;
|
|
83
|
+
readonly errorStatus?: number;
|
|
84
|
+
readonly elapsedMs?: number;
|
|
85
|
+
readonly timeoutMs?: number;
|
|
86
|
+
readonly providerCondition?: string;
|
|
87
|
+
readonly providerConditionSource?: string;
|
|
88
|
+
readonly parentToolCallId?: string;
|
|
89
|
+
}
|
|
90
|
+
export declare function retryStatusFromArm(arm: RetryStatusArmLike | null | undefined, nowMs: number): RetryStatus | null | undefined;
|
|
74
91
|
export interface RetryStatusNotice {
|
|
75
92
|
readonly line: string;
|
|
76
93
|
readonly recourse?: 'switch_model' | 'wait' | 'fix_request';
|
|
@@ -79,4 +96,24 @@ export interface RetryStatusNotice {
|
|
|
79
96
|
export declare function retryStatusNotice(status: RetryStatus | null, ctx?: {
|
|
80
97
|
readonly modelName?: string;
|
|
81
98
|
}): RetryStatusNotice;
|
|
99
|
+
export interface ApiErrorRowLike {
|
|
100
|
+
readonly _sema_api_error_status?: number;
|
|
101
|
+
readonly _sema_provider_condition?: string;
|
|
102
|
+
readonly _sema_api_error_code?: string;
|
|
103
|
+
}
|
|
104
|
+
export interface ApiErrorRowFacts {
|
|
105
|
+
readonly status?: number;
|
|
106
|
+
readonly providerCondition?: string;
|
|
107
|
+
readonly errorCode?: string;
|
|
108
|
+
}
|
|
109
|
+
export interface ApiErrorNotice {
|
|
110
|
+
readonly line: string;
|
|
111
|
+
readonly recourse?: NonNullable<RetryStatusNotice['recourse']> | 'check_credentials';
|
|
112
|
+
}
|
|
113
|
+
export interface ApiErrorNoticeCtx {
|
|
114
|
+
readonly modelName?: string;
|
|
115
|
+
readonly providerText?: string;
|
|
116
|
+
}
|
|
117
|
+
export declare function apiErrorFactsOfRow(row: ApiErrorRowLike | null | undefined): ApiErrorRowFacts;
|
|
118
|
+
export declare function apiErrorNotice(facts: ApiErrorRowFacts | null | undefined, ctx?: ApiErrorNoticeCtx): ApiErrorNotice | undefined;
|
|
82
119
|
export {};
|
package/dist/retryStatus.js
CHANGED
|
@@ -78,6 +78,47 @@ export function mapBrainStatusToRetry(p, nowMs) {
|
|
|
78
78
|
return { kind: 'error', deadline, ...extra, error: { formatted: '' } };
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
export function retryStatusFromArm(arm, nowMs) {
|
|
82
|
+
const object = guardedRead(() => typeof arm === 'object' && arm !== null && !Array.isArray(arm));
|
|
83
|
+
if (object !== true || arm === null || arm === undefined)
|
|
84
|
+
return undefined;
|
|
85
|
+
const bit = (key) => guardedRead(() => readOwnDataValue(arm, key));
|
|
86
|
+
if (typeof bit('parentToolCallId') === 'string')
|
|
87
|
+
return undefined;
|
|
88
|
+
const num = (key) => {
|
|
89
|
+
const v = bit(key);
|
|
90
|
+
return typeof v === 'number' && Number.isFinite(v) ? v : undefined;
|
|
91
|
+
};
|
|
92
|
+
const str = (key) => {
|
|
93
|
+
const v = bit(key);
|
|
94
|
+
return typeof v === 'string' ? v : undefined;
|
|
95
|
+
};
|
|
96
|
+
const word = (key) => {
|
|
97
|
+
const v = str(key);
|
|
98
|
+
return v !== undefined && v.length > 0 ? v : undefined;
|
|
99
|
+
};
|
|
100
|
+
const [detail, retryInSec, retryInMs, attempt, maxRetries, errClass, retryAtMs, errorStatus, elapsedMs, timeoutMs, providerCondition, providerConditionSource] = [
|
|
101
|
+
str('detail'), num('retryInSec'), num('retryInMs'), num('attempt'), num('maxRetries'), str('errClass'), num('retryAtMs'), num('errorStatus'), num('elapsedMs'), num('timeoutMs'), word('providerCondition'), word('providerConditionSource'),
|
|
102
|
+
];
|
|
103
|
+
const phase = str('phase');
|
|
104
|
+
if (phase === undefined)
|
|
105
|
+
return undefined;
|
|
106
|
+
return mapBrainStatusToRetry({
|
|
107
|
+
phase,
|
|
108
|
+
...(detail !== undefined ? { detail } : {}),
|
|
109
|
+
...(retryInSec !== undefined ? { retryInSec } : {}),
|
|
110
|
+
...(retryInMs !== undefined ? { retryInMs } : {}),
|
|
111
|
+
...(attempt !== undefined ? { attempt } : {}),
|
|
112
|
+
...(maxRetries !== undefined ? { maxRetries } : {}),
|
|
113
|
+
...(errClass !== undefined ? { errClass } : {}),
|
|
114
|
+
...(retryAtMs !== undefined ? { retryAtMs } : {}),
|
|
115
|
+
...(errorStatus !== undefined ? { errorStatus } : {}),
|
|
116
|
+
...(elapsedMs !== undefined ? { elapsedMs } : {}),
|
|
117
|
+
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
118
|
+
...(providerCondition !== undefined ? { providerCondition } : {}),
|
|
119
|
+
...(providerConditionSource !== undefined ? { providerConditionSource } : {}),
|
|
120
|
+
}, nowMs);
|
|
121
|
+
}
|
|
81
122
|
const WAIT_SWITCH_FRACTION = 0.5;
|
|
82
123
|
const CONDITION_READINGS = Object.freeze({
|
|
83
124
|
quota_exhausted: { clause: 'this account cannot be served by the model service until someone acts or its usage window resets', recourse: 'switch_model' },
|
|
@@ -179,3 +220,41 @@ export function retryStatusNotice(status, ctx) {
|
|
|
179
220
|
: undefined;
|
|
180
221
|
return sealNotice(`${prefix}${first}${note === undefined ? '' : ` · ${note}`}`, kind === 'stalled' ? 'reconnecting' : terminal ? 'gave_up' : 'retrying', recourse);
|
|
181
222
|
}
|
|
223
|
+
const API_ERROR_PROVIDER_TEXT_MAX = 200;
|
|
224
|
+
function isRecordObject(v) {
|
|
225
|
+
return guardedRead(() => typeof v === 'object' && v !== null && !Array.isArray(v)) === true;
|
|
226
|
+
}
|
|
227
|
+
export function apiErrorFactsOfRow(row) {
|
|
228
|
+
if (!isRecordObject(row))
|
|
229
|
+
return Object.freeze({});
|
|
230
|
+
const status = noticeHttp(noticeNumber(row, '_sema_api_error_status'));
|
|
231
|
+
const providerCondition = noticeText(row, '_sema_provider_condition');
|
|
232
|
+
const errorCode = noticeText(row, '_sema_api_error_code');
|
|
233
|
+
return Object.freeze({
|
|
234
|
+
...(status !== undefined ? { status } : {}),
|
|
235
|
+
...(providerCondition !== undefined ? { providerCondition } : {}),
|
|
236
|
+
...(errorCode !== undefined ? { errorCode } : {}),
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
export function apiErrorNotice(facts, ctx) {
|
|
240
|
+
if (!isRecordObject(facts))
|
|
241
|
+
return undefined;
|
|
242
|
+
const status = noticeHttp(noticeNumber(facts, 'status'));
|
|
243
|
+
const providerCondition = noticeText(facts, 'providerCondition');
|
|
244
|
+
if (status === undefined && conditionReadingOf(providerCondition) === undefined)
|
|
245
|
+
return undefined;
|
|
246
|
+
const rawText = noticeText(ctx, 'providerText');
|
|
247
|
+
const shownText = rawText === undefined ? undefined : washedText(displayUntrusted(rawText, { max: API_ERROR_PROVIDER_TEXT_MAX }));
|
|
248
|
+
const terminal = {
|
|
249
|
+
kind: 'error',
|
|
250
|
+
deadline: 0,
|
|
251
|
+
terminal: true,
|
|
252
|
+
...(status !== undefined ? { errorStatus: status } : {}),
|
|
253
|
+
...(providerCondition !== undefined ? { providerCondition } : {}),
|
|
254
|
+
error: { formatted: shownText ?? '' },
|
|
255
|
+
};
|
|
256
|
+
const modelName = noticeText(ctx, 'modelName');
|
|
257
|
+
const notice = retryStatusNotice(terminal, modelName !== undefined ? { modelName } : undefined);
|
|
258
|
+
const recourse = status === 401 || status === 403 ? 'check_credentials' : notice.recourse;
|
|
259
|
+
return Object.freeze(recourse === undefined ? { line: notice.line } : { line: notice.line, recourse });
|
|
260
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ScenarioRefusalReading {
|
|
2
|
+
readonly errorCode?: string;
|
|
3
|
+
readonly error?: string;
|
|
4
|
+
readonly scenario?: string;
|
|
5
|
+
readonly source?: 'ruling' | 'deployment';
|
|
6
|
+
}
|
|
7
|
+
export declare function scenarioRefusalOf(body: object): ScenarioRefusalReading | undefined | null;
|
|
8
|
+
export declare function scenarioRefusalFromError(err: {} | null | undefined): ScenarioRefusalReading | null;
|
|
9
|
+
export declare function scenarioRefusalContent(reading: ScenarioRefusalReading): string;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { capForDisplay } from './fleetTaskDesc.js';
|
|
2
|
+
import { readOwnDataValue } from './ownKey.js';
|
|
3
|
+
import { SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
|
|
4
|
+
import { readErrorRecord, readErrorString } from './wireFailureShape.js';
|
|
5
|
+
import { effectiveWireErrorCode } from './wireErrorTriage.js';
|
|
6
|
+
const SCENARIO_REFUSAL_ERROR_MAX = 200;
|
|
7
|
+
function detailBits(detail) {
|
|
8
|
+
if (detail === undefined)
|
|
9
|
+
return {};
|
|
10
|
+
let scenario;
|
|
11
|
+
let source;
|
|
12
|
+
try {
|
|
13
|
+
scenario = readOwnDataValue(detail, 'scenario');
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
scenario = undefined;
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
source = readOwnDataValue(detail, 'source');
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
source = undefined;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
...(typeof scenario === 'string' && scenario.length > 0 ? { scenario } : {}),
|
|
26
|
+
...(source === 'ruling' || source === 'deployment' ? { source } : {}),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const isPlainRecord = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
30
|
+
export function scenarioRefusalOf(body) {
|
|
31
|
+
let raw;
|
|
32
|
+
try {
|
|
33
|
+
const d = Object.getOwnPropertyDescriptor(body, 'scenarioRefusal');
|
|
34
|
+
if (d === undefined)
|
|
35
|
+
return undefined;
|
|
36
|
+
raw = 'value' in d ? d.value : undefined;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
if (!isPlainRecord(raw))
|
|
43
|
+
return Object.freeze({});
|
|
44
|
+
const own = (key) => {
|
|
45
|
+
try {
|
|
46
|
+
return readOwnDataValue(raw, key);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const errorCode = own('errorCode');
|
|
53
|
+
const error = own('error');
|
|
54
|
+
const detail = own('detail');
|
|
55
|
+
let bits = {};
|
|
56
|
+
try {
|
|
57
|
+
bits = detailBits(isPlainRecord(detail) ? detail : undefined);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
bits = {};
|
|
61
|
+
}
|
|
62
|
+
return Object.freeze({
|
|
63
|
+
...(typeof errorCode === 'string' && errorCode.length > 0 ? { errorCode } : {}),
|
|
64
|
+
...(typeof error === 'string' && error.length > 0 ? { error: capForDisplay(error, SCENARIO_REFUSAL_ERROR_MAX) } : {}),
|
|
65
|
+
...bits,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return Object.freeze({});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export function scenarioRefusalFromError(err) {
|
|
73
|
+
try {
|
|
74
|
+
if (err === null || typeof err !== 'object')
|
|
75
|
+
return null;
|
|
76
|
+
if (effectiveWireErrorCode(err) !== SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE)
|
|
77
|
+
return null;
|
|
78
|
+
const error = readErrorString(err, 'message');
|
|
79
|
+
return Object.freeze({
|
|
80
|
+
errorCode: SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE,
|
|
81
|
+
...(error !== undefined && error.length > 0 ? { error: capForDisplay(error, SCENARIO_REFUSAL_ERROR_MAX) } : {}),
|
|
82
|
+
...detailBits(readErrorRecord(err, 'detail')),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export function scenarioRefusalContent(reading) {
|
|
90
|
+
let code;
|
|
91
|
+
let scenario;
|
|
92
|
+
let source;
|
|
93
|
+
try {
|
|
94
|
+
code = isPlainRecord(reading) ? readOwnDataValue(reading, 'errorCode') : undefined;
|
|
95
|
+
scenario = isPlainRecord(reading) ? readOwnDataValue(reading, 'scenario') : undefined;
|
|
96
|
+
source = isPlainRecord(reading) ? readOwnDataValue(reading, 'source') : undefined;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
code = undefined;
|
|
100
|
+
scenario = undefined;
|
|
101
|
+
source = undefined;
|
|
102
|
+
}
|
|
103
|
+
if (code === SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE) {
|
|
104
|
+
const name = typeof scenario === 'string' && scenario.length > 0 ? ` ("${capForDisplay(scenario, 80)}")` : '';
|
|
105
|
+
const from = source === 'ruling' ? ', assigned to you by the configuration center,' : source === 'deployment' ? ", this deployment's default scenario," : '';
|
|
106
|
+
return (`This deployment cannot resolve your scenario: the scenario${name}${from} does not exist here, so it refuses whatever depends on your scenario — ` +
|
|
107
|
+
"new runs that do not name a scenario, and this session's list of MCP servers · Ask whoever operates the engine to fix the scenario assignment");
|
|
108
|
+
}
|
|
109
|
+
const tail = typeof code === 'string' && code.length > 0 ? ` (${capForDisplay(code, 80)})` : '';
|
|
110
|
+
return `This deployment's scenario check refused to resolve your scenario${tail}, so whatever depends on your scenario is not available — this session's list of MCP servers is unknown`;
|
|
111
|
+
}
|