@sema-agent/client-core 0.97.0 → 0.98.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 +429 -0
- package/README.md +74 -36
- package/dist/adapt/arms.d.ts +1 -0
- package/dist/adapt/arms.js +128 -34
- package/dist/adapt/ids.d.ts +12 -1
- package/dist/adapt/ids.js +59 -8
- package/dist/adapt/instanceLedger.d.ts +50 -0
- package/dist/adapt/instanceLedger.js +147 -0
- package/dist/adapt/textStream.d.ts +1 -0
- package/dist/adapt/textStream.js +24 -7
- package/dist/adapt/toolCards.d.ts +27 -5
- package/dist/adapt/toolCards.js +39 -6
- package/dist/adapt/wireShapes.js +6 -2
- package/dist/adapt.d.ts +2 -0
- package/dist/adapt.js +8 -3
- package/dist/adapter/activeRunSelfHeal.d.ts +5 -0
- package/dist/adapter/activeRunSelfHeal.js +51 -28
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -5
- package/dist/adapter/downstream/eventToSdkMessage.js +27 -34
- package/dist/adapter/downstream/terminalToSdkResult.js +11 -4
- package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +5 -2
- package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -0
- package/dist/adapter/runStream.js +29 -13
- package/dist/adapter/types.d.ts +4 -4
- package/dist/agentSession/backgroundView.js +2 -1
- package/dist/agentSession/engineAgentRegistryRead.d.ts +2 -2
- package/dist/agentSession/engineAgentRegistryRead.js +12 -13
- package/dist/agentsWireCaps.d.ts +8 -6
- package/dist/agentsWireCaps.js +177 -162
- package/dist/approvalDecidedByCapability.d.ts +0 -4
- package/dist/approvalDecidedByCapability.js +0 -6
- package/dist/approvalsStreamLiveCapability.d.ts +0 -4
- package/dist/approvalsStreamLiveCapability.js +0 -6
- package/dist/assistantInbox.d.ts +34 -0
- package/dist/assistantInbox.js +118 -0
- package/dist/centerWiringCapability.js +9 -1
- package/dist/clientSlice.d.ts +0 -9
- package/dist/clientSlice.js +0 -3
- package/dist/cloudConfigWireCaps.d.ts +4 -2
- package/dist/cloudConfigWireCaps.js +81 -61
- package/dist/compensations.js +1 -1
- package/dist/connectorStatus.d.ts +21 -0
- package/dist/connectorStatus.js +112 -0
- package/dist/controlRouter.d.ts +14 -1
- package/dist/controlRouter.js +68 -17
- package/dist/coreValuePorts.d.ts +3 -3
- package/dist/decideReceipt.d.ts +2 -2
- package/dist/decideReceipt.js +5 -2
- package/dist/declared/supportFloorDeclared.js +3 -3
- package/dist/deviceExecutorManagementCapability.d.ts +0 -4
- package/dist/deviceExecutorManagementCapability.js +0 -6
- package/dist/deviceRebind.d.ts +49 -1
- package/dist/deviceRebind.js +221 -3
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +250 -76
- package/dist/engineAgentAbsence.d.ts +1 -1
- package/dist/engineAgentPanelStore.d.ts +5 -4
- package/dist/engineAgentPanelStore.js +3 -12
- package/dist/engineCapReader.d.ts +0 -4
- package/dist/engineCapReader.js +1 -5
- package/dist/engineCapsCache.d.ts +4 -0
- package/dist/engineCapsCache.js +17 -12
- package/dist/engineClosedSets.d.ts +1 -0
- package/dist/engineClosedSets.js +4 -1
- package/dist/engineErrorCodes.d.ts +9 -2
- package/dist/engineErrorCodes.js +9 -1
- package/dist/engineIdentity.d.ts +1 -0
- package/dist/engineIdentity.js +8 -0
- package/dist/engineRowRef.d.ts +28 -0
- package/dist/engineRowRef.js +111 -0
- package/dist/engineSessionMessages.d.ts +67 -0
- package/dist/engineSessionMessages.js +364 -0
- package/dist/engineToolDirectory.d.ts +18 -0
- package/dist/engineToolDirectory.js +85 -0
- package/dist/engineUrl.d.ts +18 -0
- package/dist/engineUrl.js +52 -0
- package/dist/env/uiLanguage.d.ts +9 -0
- package/dist/env/uiLanguage.js +35 -0
- package/dist/eventLeg.d.ts +92 -0
- package/dist/eventLeg.js +285 -0
- package/dist/executionLaneCapability.d.ts +0 -4
- package/dist/executionLaneCapability.js +3 -16
- package/dist/fileHistoryCaptureCapability.d.ts +0 -4
- package/dist/fileHistoryCaptureCapability.js +5 -7
- package/dist/fleet/fleetLedger.d.ts +0 -3
- package/dist/fleet/fleetLedger.js +21 -36
- package/dist/fleet/fleetProjection.d.ts +2 -2
- package/dist/fleet/fleetProjection.js +10 -8
- package/dist/frameBinding.d.ts +5 -0
- package/dist/frameBinding.js +23 -0
- package/dist/gateFailureCodes.d.ts +2 -0
- package/dist/gateFailureCodes.js +15 -0
- package/dist/gateOutcome.d.ts +3 -1
- package/dist/gateOutcome.js +25 -6
- package/dist/gateVocabulary.d.ts +5 -0
- package/dist/gateVocabulary.js +64 -2
- package/dist/generated/engineAskFaceTables.js +2 -2
- package/dist/generated/engineFactTables.d.ts +6 -3
- package/dist/generated/engineFactTables.js +22 -4
- package/dist/generated/engineNoticeTables.js +9 -0
- package/dist/generated/toolNameTables.d.ts +1 -0
- package/dist/generated/toolNameTables.js +1 -0
- package/dist/hitl/allowRuleShadow.d.ts +6 -1
- package/dist/hitl/allowRuleShadow.js +21 -17
- package/dist/hitl/approvalCardReading.d.ts +15 -0
- package/dist/hitl/approvalCardReading.js +154 -0
- package/dist/hitl/approvalCardReasons.d.ts +13 -0
- package/dist/hitl/approvalCardReasons.js +120 -0
- package/dist/hitl/approvalHolds.d.ts +47 -15
- package/dist/hitl/approvalHolds.js +134 -28
- package/dist/hitl/approvalResolution.d.ts +51 -26
- package/dist/hitl/approvalResolution.js +86 -122
- package/dist/hitl/approvalsFeed.js +6 -18
- package/dist/hitl/askClassPair.d.ts +2 -0
- package/dist/hitl/askClassPair.js +1 -0
- package/dist/hitl/askGateWire.d.ts +20 -2
- package/dist/hitl/askGateWire.js +49 -1
- package/dist/hitl/askParkRowRouting.d.ts +5 -0
- package/dist/hitl/askParkRowRouting.js +32 -1
- package/dist/hitl/askSettlementLine.d.ts +18 -0
- package/dist/hitl/askSettlementLine.js +79 -0
- package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
- package/dist/hitl/automaticAnswerVerdict.js +21 -5
- package/dist/hitl/crashConverged.d.ts +11 -20
- package/dist/hitl/crashConverged.js +56 -0
- package/dist/hitl/crashConvergedNotice.d.ts +3 -1
- package/dist/hitl/crashConvergedNotice.js +48 -11
- package/dist/hitl/decisionConflict.js +3 -10
- package/dist/hitl/decisionRefusal.d.ts +40 -1
- package/dist/hitl/decisionRefusal.js +199 -42
- package/dist/hitl/frameRouter.d.ts +5 -2
- package/dist/hitl/frameRouter.js +20 -16
- package/dist/hitl/gateLedger.d.ts +2 -0
- package/dist/hitl/gateLedger.js +50 -13
- package/dist/hitl/hitlBridge.d.ts +1 -2
- package/dist/hitl/hitlBridge.js +10 -7
- package/dist/hitl/livePendingAsk.d.ts +3 -3
- package/dist/hitl/livePendingAsk.js +7 -18
- package/dist/hitl/parkResolver.d.ts +2 -24
- package/dist/hitl/parkResolver.js +61 -97
- package/dist/hitl/persistedRulesWire.d.ts +24 -0
- package/dist/hitl/persistedRulesWire.js +122 -2
- package/dist/hitl/planReviewWire.d.ts +26 -13
- package/dist/hitl/planReviewWire.js +112 -78
- package/dist/hitl/refusedToolNameProse.d.ts +0 -1
- package/dist/hitl/refusedToolNameProse.js +0 -3
- package/dist/hitl/replayedApproval.d.ts +4 -3
- package/dist/hitl/replayedApproval.js +7 -4
- package/dist/hitl/sessionPolicyDeliverable.js +2 -4
- package/dist/hitl/sessionPolicyWire.d.ts +32 -20
- package/dist/hitl/sessionPolicyWire.js +162 -52
- package/dist/hitl/standingRows.d.ts +20 -2
- package/dist/hitl/standingRows.js +69 -8
- package/dist/hitl/toolApprovalWire.d.ts +87 -152
- package/dist/hitl/toolApprovalWire.js +591 -380
- package/dist/hookMatcherVerdict.d.ts +6 -1
- package/dist/hookMatcherVerdict.js +14 -7
- package/dist/hooksWireCaps.d.ts +2 -2
- package/dist/hooksWireCaps.js +59 -55
- package/dist/i18n/messages.en.d.ts +121 -0
- package/dist/i18n/messages.en.js +119 -0
- package/dist/i18n/messages.zh.d.ts +3 -0
- package/dist/i18n/messages.zh.js +120 -0
- package/dist/i18n/translate.d.ts +25 -0
- package/dist/i18n/translate.js +127 -0
- package/dist/index.d.ts +53 -18
- package/dist/index.js +38 -10
- package/dist/inheritEnvCapability.d.ts +31 -0
- package/dist/inheritEnvCapability.js +104 -0
- package/dist/liveModelCatalog.d.ts +1 -2
- package/dist/liveModelCatalog.js +2 -6
- package/dist/liveQuestionStore.d.ts +2 -21
- package/dist/mcpLiveness.d.ts +2 -1
- package/dist/mcpProbeWire.d.ts +6 -1
- package/dist/mcpProbeWire.js +1 -1
- package/dist/mcpWireCaps.d.ts +13 -2
- package/dist/mcpWireCaps.js +48 -0
- package/dist/memoryEntriesWire.d.ts +4 -9
- package/dist/model/modelSupplyRules.d.ts +0 -2
- package/dist/model/modelSupplyRules.js +3 -12
- package/dist/model/modelsPolicy.d.ts +0 -5
- package/dist/model/modelsPolicy.js +6 -36
- package/dist/model/subagentModelWord.d.ts +31 -0
- package/dist/model/subagentModelWord.js +261 -0
- package/dist/notifications.d.ts +6 -0
- package/dist/notifications.js +71 -23
- package/dist/outputStyleSeatCapability.d.ts +0 -3
- package/dist/outputStyleSeatCapability.js +0 -3
- package/dist/ownKey.d.ts +15 -0
- package/dist/ownKey.js +60 -3
- package/dist/panelReduce.d.ts +15 -9
- package/dist/panelReduce.js +680 -549
- package/dist/panelStateHolder.d.ts +3 -7
- package/dist/panelStateHolder.js +14 -130
- package/dist/peerLaneCapability.d.ts +0 -4
- package/dist/peerLaneCapability.js +0 -6
- package/dist/permissionRulesWriteCapability.d.ts +0 -4
- package/dist/permissionRulesWriteCapability.js +0 -6
- package/dist/permissionWireCaps.d.ts +2 -2
- package/dist/permissionWireCaps.js +2 -0
- package/dist/permissionsAllowGrantCapability.d.ts +0 -4
- package/dist/permissionsAllowGrantCapability.js +0 -6
- package/dist/permissionsDeclaration.d.ts +0 -11
- package/dist/permissionsDeclaration.js +60 -53
- package/dist/pluginHooksWire.d.ts +1 -1
- package/dist/pluginHooksWire.js +3 -6
- package/dist/preemptWire.d.ts +44 -0
- package/dist/preemptWire.js +83 -0
- package/dist/printToolResultFrame.js +15 -4
- package/dist/replayBody.d.ts +3 -0
- package/dist/replayBody.js +14 -0
- package/dist/request/taskRequest.d.ts +0 -1
- package/dist/request/taskRequest.js +0 -3
- package/dist/resumeRefusalCopy.d.ts +2 -1
- package/dist/resumeRefusalCopy.js +38 -2
- package/dist/retryStatus.d.ts +8 -0
- package/dist/retryStatus.js +106 -1
- package/dist/rewindArchiveCapability.d.ts +0 -4
- package/dist/rewindArchiveCapability.js +2 -10
- package/dist/rewindArchiveReading.d.ts +0 -1
- package/dist/rewindArchiveReading.js +0 -3
- package/dist/runCancelContext.d.ts +2 -1
- package/dist/runCancelContext.js +4 -2
- package/dist/runReattachPolicy.d.ts +31 -0
- package/dist/runReattachPolicy.js +46 -0
- package/dist/runTerminal.d.ts +3 -6
- package/dist/runTerminal.js +8 -9
- package/dist/sandboxWire.d.ts +3 -1
- package/dist/sandboxWire.js +76 -27
- package/dist/scenarioWire.js +1 -1
- package/dist/seam.d.ts +24 -2
- package/dist/seam.js +15 -3
- package/dist/seatContract.d.ts +53 -10
- package/dist/seatContract.js +132 -81
- package/dist/sessionPolicyCapability.d.ts +0 -4
- package/dist/sessionPolicyCapability.js +0 -6
- package/dist/sessionSyncFileHistoryCapability.d.ts +0 -3
- package/dist/sessionSyncFileHistoryCapability.js +0 -3
- package/dist/skillToolListsCapability.d.ts +0 -3
- package/dist/skillToolListsCapability.js +0 -3
- package/dist/sqlEngineCapability.d.ts +0 -4
- package/dist/sqlEngineCapability.js +0 -6
- package/dist/steerPriorityCapability.d.ts +0 -3
- package/dist/steerPriorityCapability.js +0 -3
- package/dist/streamDrainingLegs.d.ts +4 -0
- package/dist/streamDrainingLegs.js +6 -1
- package/dist/subagent/engineCompactWire.d.ts +0 -1
- package/dist/subagent/engineCompactWire.js +7 -5
- package/dist/subagent/engineTaskHandleWire.js +4 -7
- package/dist/subagentContentStore.js +1 -11
- package/dist/submitReopen.d.ts +24 -0
- package/dist/submitReopen.js +75 -0
- package/dist/terminalStatuses.d.ts +3 -0
- package/dist/terminalStatuses.js +10 -2
- package/dist/toolResult.d.ts +10 -1
- package/dist/toolResult.js +34 -6
- package/dist/toolRoster.d.ts +0 -2
- package/dist/toolRoster.js +0 -2
- package/dist/turnFailurePresentation.d.ts +28 -0
- package/dist/turnFailurePresentation.js +205 -0
- package/dist/userInvokedSkillsCapability.d.ts +0 -3
- package/dist/userInvokedSkillsCapability.js +0 -3
- package/dist/webSearchBackendCapability.d.ts +0 -4
- package/dist/webSearchBackendCapability.js +0 -6
- package/dist/wireErrorTriage.js +5 -24
- package/dist/wireFailureShape.d.ts +62 -5
- package/dist/wireFailureShape.js +105 -5
- package/dist/wireRefusalCopy.d.ts +12 -2
- package/dist/wireRefusalCopy.js +50 -52
- package/dist/workflowsJournalCapability.d.ts +0 -4
- package/dist/workflowsJournalCapability.js +0 -6
- package/dist/writeProtectionCapability.d.ts +0 -4
- package/dist/writeProtectionCapability.js +0 -6
- package/docs/INTEGRATION-CLIENTS.md +1305 -46
- package/package.json +5 -4
- package/dist/attachmentSeatCapability.d.ts +0 -12
- package/dist/attachmentSeatCapability.js +0 -23
- package/dist/hitl/approvalOutcomeNote.d.ts +0 -10
- package/dist/hitl/approvalOutcomeNote.js +0 -29
- package/dist/sessionReadRedactionCapability.d.ts +0 -13
- package/dist/sessionReadRedactionCapability.js +0 -35
package/dist/controlRouter.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { cancelConflictContent, cancelConflictFromError } from './wireRefusalCopy.js';
|
|
2
|
+
import { PROTOCOL_ERROR_NAME, protocolErrorNameOf } from './wireFailureShape.js';
|
|
2
3
|
import { steerPriorityMode } from './steerPriorityCapability.js';
|
|
4
|
+
import { preemptReadingOfAck, preemptReadingOfError } from './preemptWire.js';
|
|
3
5
|
export class ControlSafetyError extends Error {
|
|
4
6
|
code;
|
|
5
7
|
cause;
|
|
@@ -86,8 +88,11 @@ export class ControlRouter {
|
|
|
86
88
|
if (this.taskId === null) {
|
|
87
89
|
throw controlSafetyRefusal('not_found', 'no run in flight to cancel');
|
|
88
90
|
}
|
|
91
|
+
return this.cancelRun(this.taskId, opts);
|
|
92
|
+
}
|
|
93
|
+
async cancelRun(taskId, opts) {
|
|
89
94
|
try {
|
|
90
|
-
return await this.client.runs.cancel(
|
|
95
|
+
return await this.client.runs.cancel(taskId, opts?.signal !== undefined ? { signal: opts.signal } : undefined);
|
|
91
96
|
}
|
|
92
97
|
catch (e) {
|
|
93
98
|
const conflict = cancelConflictFromError(e);
|
|
@@ -100,6 +105,53 @@ export class ControlRouter {
|
|
|
100
105
|
throw e;
|
|
101
106
|
}
|
|
102
107
|
}
|
|
108
|
+
async preempt(opts) {
|
|
109
|
+
const taskId = this.taskId;
|
|
110
|
+
if (taskId === null)
|
|
111
|
+
return Object.freeze({ kind: 'no-run' });
|
|
112
|
+
let signal;
|
|
113
|
+
let fallback = 'cancel';
|
|
114
|
+
try {
|
|
115
|
+
const s = opts?.signal;
|
|
116
|
+
if (s !== undefined && s !== null)
|
|
117
|
+
signal = s;
|
|
118
|
+
const f = opts?.onUnavailable;
|
|
119
|
+
if (f !== undefined && f !== 'cancel')
|
|
120
|
+
fallback = 'report';
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
fallback = 'report';
|
|
124
|
+
}
|
|
125
|
+
let verb;
|
|
126
|
+
let slice;
|
|
127
|
+
try {
|
|
128
|
+
slice = this.client.assistant;
|
|
129
|
+
const v = slice?.preempt;
|
|
130
|
+
if (typeof v === 'function')
|
|
131
|
+
verb = v;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
verb = undefined;
|
|
135
|
+
}
|
|
136
|
+
let reading;
|
|
137
|
+
if (verb === undefined) {
|
|
138
|
+
reading = { kind: 'lane-absent' };
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
try {
|
|
142
|
+
reading = preemptReadingOfAck(taskId, await verb.call(slice, taskId, signal !== undefined ? { signal } : undefined));
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
reading = preemptReadingOfError(e);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (reading.kind !== 'lane-absent')
|
|
149
|
+
return Object.freeze(reading);
|
|
150
|
+
if (fallback === 'report')
|
|
151
|
+
return Object.freeze({ kind: 'unavailable' });
|
|
152
|
+
const ack = await this.cancelRun(taskId, signal !== undefined ? { signal } : undefined);
|
|
153
|
+
return Object.freeze({ kind: 'cancelled-instead', ack });
|
|
154
|
+
}
|
|
103
155
|
}
|
|
104
156
|
export function errCodes(e) {
|
|
105
157
|
if (!e || typeof e !== 'object')
|
|
@@ -122,16 +174,16 @@ const STEERING_CODE_TO_SAFETY = new Map([
|
|
|
122
174
|
['steering.blocked_by_hook', 'blocked_by_hook'],
|
|
123
175
|
['steering.ledger_unavailable', 'ledger_unavailable'],
|
|
124
176
|
]);
|
|
125
|
-
const STEERING_NAME_TO_SAFETY =
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
177
|
+
const STEERING_NAME_TO_SAFETY = {
|
|
178
|
+
SteeringNotRunningError: 'not_running',
|
|
179
|
+
SteeringInvalidContentError: 'invalid_content',
|
|
180
|
+
SteeringAmbiguousTargetError: 'ambiguous_target',
|
|
181
|
+
SteeringStillRunningError: 'still_running',
|
|
182
|
+
SteeringLedgerUnavailableError: 'ledger_unavailable',
|
|
183
|
+
SteeringQueueFullError: 'queue_full',
|
|
184
|
+
SteeringDuplicateInputIdError: 'duplicate_input_id',
|
|
185
|
+
SteeringError: 'steering_other',
|
|
186
|
+
};
|
|
135
187
|
const STEERING_COPY = {
|
|
136
188
|
not_running: {
|
|
137
189
|
happened: 'that run is not accepting messages right now — it has just finished, is running on another server, or is not the active run of its session',
|
|
@@ -232,13 +284,12 @@ function steeringSafetyOf(e, verdict) {
|
|
|
232
284
|
return refused !== undefined && refused.safety === verdict ? verdict : 'steering_other';
|
|
233
285
|
}
|
|
234
286
|
function steeringVerdict(e) {
|
|
235
|
-
const { code
|
|
287
|
+
const { code } = errCodes(e);
|
|
236
288
|
if (typeof code === 'string' && code.startsWith('steering.')) {
|
|
237
289
|
return STEERING_CODE_TO_SAFETY.get(code) ?? 'steering_other';
|
|
238
290
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return undefined;
|
|
291
|
+
const protocolName = protocolErrorNameOf(e);
|
|
292
|
+
return protocolName !== undefined ? STEERING_NAME_TO_SAFETY[protocolName] : undefined;
|
|
242
293
|
}
|
|
243
294
|
export function steerRefusalAdviceOf(e) {
|
|
244
295
|
try {
|
|
@@ -308,6 +359,6 @@ export function steerBodyOf(input, reading) {
|
|
|
308
359
|
return Object.freeze({ ...base, priority });
|
|
309
360
|
}
|
|
310
361
|
function isNotFound(e) {
|
|
311
|
-
const {
|
|
312
|
-
return
|
|
362
|
+
const { status } = errCodes(e);
|
|
363
|
+
return status === 404 || (typeof e === 'object' && e !== null && protocolErrorNameOf(e) === PROTOCOL_ERROR_NAME.NotFoundError);
|
|
313
364
|
}
|
package/dist/coreValuePorts.d.ts
CHANGED
|
@@ -73,7 +73,7 @@ export interface RouteCredentialView {
|
|
|
73
73
|
}
|
|
74
74
|
export type RouteAdjudicationView = {
|
|
75
75
|
ok: true;
|
|
76
|
-
posture: 'per-model' | 'paired' | '
|
|
76
|
+
posture: 'per-model' | 'paired' | 'keyless' | (string & {});
|
|
77
77
|
} | {
|
|
78
78
|
ok: false;
|
|
79
79
|
code: 'route.credential_mismatch' | 'route.credential_missing' | (string & {});
|
|
@@ -100,12 +100,12 @@ export interface RuleToolNameVerdictView {
|
|
|
100
100
|
export interface CoreValuePorts {
|
|
101
101
|
resolveAutonomousLoopPrompt: (prompt: string, opts?: AutonomousLoopPromptOptionsView) => string | null;
|
|
102
102
|
loosenReasons: (prior: SessionPermissionRules, next: SessionPermissionRules) => string[];
|
|
103
|
-
combinePolicies
|
|
103
|
+
combinePolicies(...policies: CoreToolPolicyHandle[]): CoreToolPolicyHandle;
|
|
104
104
|
createAllowDenyPolicy: (opts: AllowDenyPolicyOptionsView) => CoreToolPolicyHandle;
|
|
105
105
|
MCP_NAMESPACE: CoreProtocolNamespaceView;
|
|
106
106
|
protocolOf: (name: string) => CoreProtocolNamespaceView | undefined;
|
|
107
107
|
ruleToolGrammarOf: (toolName: string) => RuleGrammarView | undefined;
|
|
108
|
-
validatePermissionRules
|
|
108
|
+
validatePermissionRules(rules: PermissionRuleView[], opts?: ValidatePermissionRulesOptionsView): PermissionRuleIssueView[];
|
|
109
109
|
mintNamespacePrefix(ns: CoreProtocolNamespaceView, peer: string): string;
|
|
110
110
|
compileAllowList(entries: readonly string[], behavior: 'allow' | 'deny', roster?: ReadonlySet<string>): AllowListReadingView;
|
|
111
111
|
routeKeyOf(url: string | undefined): string;
|
package/dist/decideReceipt.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type GateOutcomeView } from './gateOutcome.js';
|
|
2
2
|
import { type ResumeReopenDetail } from './hitl/suspendedReopen.js';
|
|
3
|
-
import { type
|
|
3
|
+
import { type CrashConvergedRowReading } from './hitl/crashConverged.js';
|
|
4
4
|
import type { AskRowEndingCause } from '@sema-agent/sdk';
|
|
5
5
|
export interface DecideReceiptView {
|
|
6
6
|
status?: string;
|
|
@@ -35,7 +35,7 @@ export interface AskGoneDetail {
|
|
|
35
35
|
code: 'gone.ask';
|
|
36
36
|
state?: 'VOID' | 'DENIED';
|
|
37
37
|
endingCause?: AskRowEndingCause;
|
|
38
|
-
holderGone?:
|
|
38
|
+
holderGone?: CrashConvergedRowReading['cause'];
|
|
39
39
|
}
|
|
40
40
|
export declare function askGoneFromError(e: unknown): AskGoneDetail | null;
|
|
41
41
|
export declare function askGoneContent(detail: AskGoneDetail): string;
|
package/dist/decideReceipt.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { gateOutcomeOf } from './gateOutcome.js';
|
|
2
|
+
import { readOwnDataValue } from './ownKey.js';
|
|
2
3
|
import { resumeReopenFromError } from './hitl/suspendedReopen.js';
|
|
3
|
-
import { ASK_GONE, DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_PARK_FORKED, DECIDE_WORKFLOW_PARKS_UNREADABLE, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, isDecideParkMovedCode, } from './engineErrorCodes.js';
|
|
4
|
+
import { ASK_GONE, DECIDE_CLAIM_LOST, CONFLICT_NOT_RESUMABLE, GATE_NOT_TOOL_APPROVAL, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_PARK_FORKED, DECIDE_WORKFLOW_PARKS_UNREADABLE, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, isDecideParkMovedCode, } from './engineErrorCodes.js';
|
|
4
5
|
import { effectiveWireErrorCode } from './wireErrorTriage.js';
|
|
5
6
|
import { readErrorString, readErrorStrictStringList, readThrownExtra } from './wireFailureShape.js';
|
|
6
7
|
import { isCrashConvergedCause } from './hitl/crashConverged.js';
|
|
@@ -16,7 +17,7 @@ export function readDecideReceipt(result) {
|
|
|
16
17
|
const status = Object.hasOwn(r, 'status') ? str(r.status) : undefined;
|
|
17
18
|
const taskId = Object.hasOwn(r, 'taskId') ? str(r.taskId) : undefined;
|
|
18
19
|
const sessionId = Object.hasOwn(r, 'sessionId') ? str(r.sessionId) : undefined;
|
|
19
|
-
const idempotent =
|
|
20
|
+
const idempotent = readOwnDataValue(r, 'idempotent') === true ? true : undefined;
|
|
20
21
|
const handoffTaskId = status === STATUS_RESUMING && taskId !== undefined ? taskId : undefined;
|
|
21
22
|
const executionOutcome = Object.hasOwn(r, 'executionOutcome')
|
|
22
23
|
? gateOutcomeOf({ gate: r.executionOutcome })
|
|
@@ -117,6 +118,8 @@ const DECIDE_PARK_MOVED_WHAT = Object.freeze({
|
|
|
117
118
|
[DECIDE_NOT_PARKED]: 'This approval was no longer waiting when the decision arrived (the agent was stopped, the approval was decided elsewhere, or the session it belongs to was deleted; this client cannot tell which)',
|
|
118
119
|
[DECIDE_GATE_MOVED]: 'This approval moved while the decision was on its way (it was parked again, or settled elsewhere; this client cannot tell which)',
|
|
119
120
|
[DECIDE_CLAIM_LOST]: 'Another decision on this approval got there first, or an earlier attempt is still holding it until the engine clears that hold on its own; this client cannot tell which',
|
|
121
|
+
[CONFLICT_NOT_RESUMABLE]: 'The run was no longer waiting to be resumed when the decision arrived (it had been resumed, decided, or expired before this decision; this client cannot tell which)',
|
|
122
|
+
[GATE_NOT_TOOL_APPROVAL]: 'The run is waiting at a different kind of gate than a tool approval, so this tool approval decision had nothing to act on',
|
|
120
123
|
});
|
|
121
124
|
export function decideParkMovedContent(detail) {
|
|
122
125
|
let code;
|
|
@@ -15,11 +15,7 @@ export type DeviceExecutorManagementReading = {
|
|
|
15
15
|
wsPath?: string;
|
|
16
16
|
};
|
|
17
17
|
export declare function projectDeviceExecutorManagementCapability(caps: unknown): DeviceExecutorManagementReading | undefined;
|
|
18
|
-
export declare function noteEngineCapsForDeviceExecutorManagement(baseUrl: string, caps: unknown, opts?: {
|
|
19
|
-
generation?: number;
|
|
20
|
-
}): void;
|
|
21
18
|
export declare function observedDeviceExecutorManagement(baseUrl?: string | undefined): DeviceExecutorManagementReading;
|
|
22
19
|
export declare function deviceManagementVerbsAvailable(reading: DeviceExecutorManagementReading): 'yes' | 'no' | 'unknown';
|
|
23
20
|
export declare function deviceLaneOpen(reading: DeviceExecutorManagementReading): 'yes' | 'no' | 'unknown';
|
|
24
21
|
export declare function deviceExecutorManagementDoctorDetail(reading: DeviceExecutorManagementReading): string;
|
|
25
|
-
export declare function __resetDeviceExecutorManagementReadingsForTests(): void;
|
|
@@ -44,9 +44,6 @@ const reader = createEngineCapReader({
|
|
|
44
44
|
name: 'deviceExecutor.management',
|
|
45
45
|
project: projectDeviceExecutorManagementCapability,
|
|
46
46
|
});
|
|
47
|
-
export function noteEngineCapsForDeviceExecutorManagement(baseUrl, caps, opts) {
|
|
48
|
-
reader.note(baseUrl, caps, opts);
|
|
49
|
-
}
|
|
50
47
|
export function observedDeviceExecutorManagement(baseUrl = engineWireTarget()?.baseUrl) {
|
|
51
48
|
return reader.observed(baseUrl);
|
|
52
49
|
}
|
|
@@ -103,6 +100,3 @@ export function deviceExecutorManagementDoctorDetail(reading) {
|
|
|
103
100
|
}
|
|
104
101
|
}
|
|
105
102
|
}
|
|
106
|
-
export function __resetDeviceExecutorManagementReadingsForTests() {
|
|
107
|
-
reader.__resetForTests();
|
|
108
|
-
}
|
package/dist/deviceRebind.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import type { AgentClient } from '@sema-agent/sdk';
|
|
1
|
+
import type { AgentClient, DeviceEnrollRequest } from '@sema-agent/sdk';
|
|
2
2
|
export type DeviceListVerb = Pick<AgentClient['devices'], 'list'>;
|
|
3
3
|
export type DeviceSessionBindingVerb = Pick<AgentClient['devices'], 'sessionBinding'>;
|
|
4
4
|
export type DeviceRebindVerb = Pick<AgentClient['devices'], 'rebind'>;
|
|
5
|
+
export type DeviceIssueEnrollTokenVerb = Pick<AgentClient['devices'], 'issueEnrollToken'>;
|
|
6
|
+
export type DeviceEnrollVerb = Pick<AgentClient['devices'], 'enroll'>;
|
|
7
|
+
export type DeviceRevokeVerb = Pick<AgentClient['devices'], 'revoke'>;
|
|
5
8
|
export interface DeviceRosterRow {
|
|
6
9
|
readonly deviceId: string;
|
|
7
10
|
readonly name?: string;
|
|
@@ -86,3 +89,48 @@ export declare function reconcileRebindOutcome(before: DeviceBindingReading, toD
|
|
|
86
89
|
readonly serverMayStillBeRunning: boolean;
|
|
87
90
|
}): DeviceRebindReconcileVerdict;
|
|
88
91
|
export declare function rebindProvesRequestNotApplied(outcome: DeviceRebindOutcome): boolean;
|
|
92
|
+
export type DeviceRegistrationVerb = 'issue' | 'enroll' | 'revoke';
|
|
93
|
+
export interface DeviceRateLimited {
|
|
94
|
+
readonly kind: 'rate-limited';
|
|
95
|
+
readonly retryAfterSec?: number;
|
|
96
|
+
}
|
|
97
|
+
export type DeviceEnrollTokenOutcome = {
|
|
98
|
+
readonly kind: 'ok';
|
|
99
|
+
readonly token: string;
|
|
100
|
+
readonly expiresAt?: string;
|
|
101
|
+
readonly ttlSec?: number;
|
|
102
|
+
} | DeviceRateLimited | DeviceUnreadable | DeviceLaneAbsent | DeviceRefused | DeviceTransport | DeviceUnarmed;
|
|
103
|
+
export type DeviceEnrollOutcome = {
|
|
104
|
+
readonly kind: 'ok';
|
|
105
|
+
readonly deviceId: string;
|
|
106
|
+
} | {
|
|
107
|
+
readonly kind: 'enrollment-invalid';
|
|
108
|
+
} | DeviceRateLimited | DeviceRebindUnconfirmed | DeviceLaneAbsent | DeviceRefused | DeviceUnarmed;
|
|
109
|
+
export type DeviceRevokeOutcome = {
|
|
110
|
+
readonly kind: 'ok';
|
|
111
|
+
readonly deviceId: string;
|
|
112
|
+
readonly revokedAt?: string;
|
|
113
|
+
} | {
|
|
114
|
+
readonly kind: 'not-found';
|
|
115
|
+
} | DeviceRebindUnconfirmed | DeviceLaneAbsent | DeviceRefused | DeviceUnarmed;
|
|
116
|
+
export declare function issueEnrollToken(devices: DeviceIssueEnrollTokenVerb | null | undefined, opts?: {
|
|
117
|
+
readonly signal?: AbortSignal | undefined;
|
|
118
|
+
}): Promise<DeviceEnrollTokenOutcome>;
|
|
119
|
+
export interface DeviceEnrollOptions {
|
|
120
|
+
readonly signal?: AbortSignal | undefined;
|
|
121
|
+
readonly acceptDeviceId?: ((deviceId: string) => boolean) | undefined;
|
|
122
|
+
}
|
|
123
|
+
export declare function enrollDevice(devices: DeviceEnrollVerb | null | undefined, req: DeviceEnrollRequest, opts?: DeviceEnrollOptions): Promise<DeviceEnrollOutcome>;
|
|
124
|
+
export declare function revokeDevice(devices: DeviceRevokeVerb | null | undefined, deviceId: string, opts?: {
|
|
125
|
+
readonly reason?: string | undefined;
|
|
126
|
+
readonly signal?: AbortSignal | undefined;
|
|
127
|
+
}): Promise<DeviceRevokeOutcome>;
|
|
128
|
+
declare const IDENTITY_MISMATCH = "device.identity_mismatch";
|
|
129
|
+
export interface DeviceIdentityMismatch {
|
|
130
|
+
readonly code: typeof IDENTITY_MISMATCH;
|
|
131
|
+
readonly boundDeviceId?: string;
|
|
132
|
+
}
|
|
133
|
+
export declare function deviceIdentityMismatchOf(err: {} | null | undefined): DeviceIdentityMismatch | null;
|
|
134
|
+
export declare function deviceIdentityMismatchLine(detail: DeviceIdentityMismatch): string;
|
|
135
|
+
export declare function deviceRegistrationOutcomeLine(verb: DeviceRegistrationVerb, outcome: DeviceEnrollTokenOutcome | DeviceEnrollOutcome | DeviceRevokeOutcome): string | undefined;
|
|
136
|
+
export {};
|
package/dist/deviceRebind.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { atMostOnceVerdictOf } from './atMostOnce.js';
|
|
2
2
|
import { readOwnDataValue } from './ownKey.js';
|
|
3
|
+
import { isDisplayableWireCode, readErrorString, readThrownSlot, wireFailureShapeOf } from './wireFailureShape.js';
|
|
3
4
|
const LANE_ABSENT = 'capability.device_lane_required';
|
|
4
5
|
const RUN_STORE_ABSENT = 'capability.run_store_required';
|
|
5
6
|
const NOT_FOUND = 'not_found.device';
|
|
@@ -40,9 +41,13 @@ function isArraySafely(v) {
|
|
|
40
41
|
return false;
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
function scrubbed(redact, v) {
|
|
45
|
+
return v !== undefined && redact !== undefined && v.includes(redact) ? undefined : v;
|
|
46
|
+
}
|
|
47
|
+
function refusedOf(status, code, e, redact) {
|
|
48
|
+
const message = scrubbed(redact, nonEmpty(slot(e, 'message')));
|
|
49
|
+
const errorCode = scrubbed(redact, code);
|
|
50
|
+
return { kind: 'refused', status, ...(errorCode !== undefined ? { errorCode } : {}), ...(message !== undefined ? { message } : {}) };
|
|
46
51
|
}
|
|
47
52
|
function transportOf(v) {
|
|
48
53
|
return { kind: 'transport', ...(v.name !== undefined ? { detail: v.name } : {}) };
|
|
@@ -240,3 +245,216 @@ export function rebindProvesRequestNotApplied(outcome) {
|
|
|
240
245
|
return false;
|
|
241
246
|
}
|
|
242
247
|
}
|
|
248
|
+
const RATE_LIMITED = 'limit.rate_exceeded';
|
|
249
|
+
const ENROLLMENT_INVALID = 'device.enrollment_invalid';
|
|
250
|
+
function rateLimitedOf(e) {
|
|
251
|
+
const sec = wireFailureShapeOf(e).retryAfterSec;
|
|
252
|
+
return { kind: 'rate-limited', ...(sec !== undefined ? { retryAfterSec: sec } : {}) };
|
|
253
|
+
}
|
|
254
|
+
function unconfirmedOf(v, redact) {
|
|
255
|
+
const name = scrubbed(redact, v.name);
|
|
256
|
+
return v.status !== undefined
|
|
257
|
+
? { kind: 'unconfirmed', why: 'server-error', detail: String(v.status), mayStillBeRunning: true }
|
|
258
|
+
: { kind: 'unconfirmed', why: 'transport', ...(name !== undefined ? { detail: name } : {}), mayStillBeRunning: true };
|
|
259
|
+
}
|
|
260
|
+
const acceptedUnreadable = () => ({ kind: 'unconfirmed', why: 'accepted-unreadable', mayStillBeRunning: false });
|
|
261
|
+
function localRefusal(message) {
|
|
262
|
+
return { kind: 'refused', status: 0, errorCode: 'request.field_invalid', message };
|
|
263
|
+
}
|
|
264
|
+
function issueFailureOf(e) {
|
|
265
|
+
const v = atMostOnceVerdictOf(e);
|
|
266
|
+
const common = commonOf(v.status, v.code);
|
|
267
|
+
if (common !== null)
|
|
268
|
+
return common.kind === 'not-found' ? refusedOf(404, NOT_FOUND, e) : common;
|
|
269
|
+
if (v.status === 429 && v.code === RATE_LIMITED)
|
|
270
|
+
return rateLimitedOf(e);
|
|
271
|
+
return v.status !== undefined ? refusedOf(v.status, v.code, e) : transportOf(v);
|
|
272
|
+
}
|
|
273
|
+
export async function issueEnrollToken(devices, opts) {
|
|
274
|
+
const verb = verbOf(devices, 'issueEnrollToken');
|
|
275
|
+
if (verb === undefined)
|
|
276
|
+
return { kind: 'unarmed' };
|
|
277
|
+
let body;
|
|
278
|
+
try {
|
|
279
|
+
body = await verb.call(devices, signalOpts(opts));
|
|
280
|
+
}
|
|
281
|
+
catch (e) {
|
|
282
|
+
return issueFailureOf(e);
|
|
283
|
+
}
|
|
284
|
+
const token = nonEmpty(own(body, 'token'));
|
|
285
|
+
if (token === undefined)
|
|
286
|
+
return { kind: 'unreadable', why: 'the enrollment token response carries no token — refusing to treat it as a token' };
|
|
287
|
+
const expiresAt = nonEmpty(own(body, 'expiresAt'));
|
|
288
|
+
const ttl = own(body, 'ttlSec');
|
|
289
|
+
const ttlSec = typeof ttl === 'number' && Number.isInteger(ttl) && ttl > 0 ? ttl : undefined;
|
|
290
|
+
return { kind: 'ok', token, ...(expiresAt !== undefined ? { expiresAt } : {}), ...(ttlSec !== undefined ? { ttlSec } : {}) };
|
|
291
|
+
}
|
|
292
|
+
function enrollFailureOf(e, token) {
|
|
293
|
+
const v = atMostOnceVerdictOf(e);
|
|
294
|
+
const common = commonOf(v.status, v.code);
|
|
295
|
+
if (common !== null)
|
|
296
|
+
return common.kind === 'not-found' ? refusedOf(404, NOT_FOUND, e, token) : common;
|
|
297
|
+
if (v.status === 403 && v.code === ENROLLMENT_INVALID)
|
|
298
|
+
return { kind: 'enrollment-invalid' };
|
|
299
|
+
if (v.status === 429 && v.code === RATE_LIMITED)
|
|
300
|
+
return rateLimitedOf(e);
|
|
301
|
+
if (v.status === 503 && v.code === SERVICE_TOKEN_REQUIRED)
|
|
302
|
+
return refusedOf(v.status, v.code, e, token);
|
|
303
|
+
if (v.delivery === 'rejected' && v.status !== undefined)
|
|
304
|
+
return refusedOf(v.status, v.code, e, token);
|
|
305
|
+
return unconfirmedOf(v, token);
|
|
306
|
+
}
|
|
307
|
+
export async function enrollDevice(devices, req, opts) {
|
|
308
|
+
const token = nonEmpty(own(req, 'token'));
|
|
309
|
+
const pubkey = nonEmpty(own(req, 'pubkey'));
|
|
310
|
+
const platformOs = nonEmpty(own(req, 'platformOs'));
|
|
311
|
+
const workspaceRoot = nonEmpty(own(req, 'workspaceRoot'));
|
|
312
|
+
if (token === undefined || pubkey === undefined || platformOs === undefined || workspaceRoot === undefined) {
|
|
313
|
+
return localRefusal('the enrollment request is missing a required detail (token, public key, platform or workspace root), so nothing was sent');
|
|
314
|
+
}
|
|
315
|
+
const platformArch = nonEmpty(own(req, 'platformArch'));
|
|
316
|
+
const displayName = nonEmpty(own(req, 'displayName'));
|
|
317
|
+
const verb = verbOf(devices, 'enroll');
|
|
318
|
+
if (verb === undefined)
|
|
319
|
+
return { kind: 'unarmed' };
|
|
320
|
+
const wire = {
|
|
321
|
+
token,
|
|
322
|
+
pubkey,
|
|
323
|
+
platformOs,
|
|
324
|
+
...(platformArch !== undefined ? { platformArch } : {}),
|
|
325
|
+
...(displayName !== undefined ? { displayName } : {}),
|
|
326
|
+
workspaceRoot,
|
|
327
|
+
};
|
|
328
|
+
let body;
|
|
329
|
+
try {
|
|
330
|
+
body = await verb.call(devices, wire, signalOpts(opts));
|
|
331
|
+
}
|
|
332
|
+
catch (e) {
|
|
333
|
+
return enrollFailureOf(e, token);
|
|
334
|
+
}
|
|
335
|
+
const deviceId = nonEmpty(own(body, 'deviceId'));
|
|
336
|
+
if (deviceId === undefined || scrubbed(token, deviceId) === undefined)
|
|
337
|
+
return acceptedUnreadable();
|
|
338
|
+
const accept = opts === undefined || opts === null ? undefined : own(opts, 'acceptDeviceId');
|
|
339
|
+
if (typeof accept === 'function') {
|
|
340
|
+
let verdict;
|
|
341
|
+
try {
|
|
342
|
+
verdict = accept(deviceId);
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
verdict = false;
|
|
346
|
+
}
|
|
347
|
+
if (verdict !== true)
|
|
348
|
+
return acceptedUnreadable();
|
|
349
|
+
}
|
|
350
|
+
return { kind: 'ok', deviceId };
|
|
351
|
+
}
|
|
352
|
+
function revokeFailureOf(e) {
|
|
353
|
+
const v = atMostOnceVerdictOf(e);
|
|
354
|
+
const common = commonOf(v.status, v.code);
|
|
355
|
+
if (common !== null)
|
|
356
|
+
return common;
|
|
357
|
+
if (v.status === 503 && v.code === SERVICE_TOKEN_REQUIRED)
|
|
358
|
+
return refusedOf(v.status, v.code, e);
|
|
359
|
+
if (v.delivery === 'rejected' && v.status !== undefined)
|
|
360
|
+
return refusedOf(v.status, v.code, e);
|
|
361
|
+
return unconfirmedOf(v);
|
|
362
|
+
}
|
|
363
|
+
export async function revokeDevice(devices, deviceId, opts) {
|
|
364
|
+
const id = nonEmpty(deviceId);
|
|
365
|
+
if (id === undefined)
|
|
366
|
+
return localRefusal('the device id is missing, so nothing was sent');
|
|
367
|
+
const verb = verbOf(devices, 'revoke');
|
|
368
|
+
if (verb === undefined)
|
|
369
|
+
return { kind: 'unarmed' };
|
|
370
|
+
const reason = nonEmpty(own(opts, 'reason'));
|
|
371
|
+
let body;
|
|
372
|
+
try {
|
|
373
|
+
body = await verb.call(devices, id, reason !== undefined ? { reason } : {}, signalOpts(opts));
|
|
374
|
+
}
|
|
375
|
+
catch (e) {
|
|
376
|
+
return revokeFailureOf(e);
|
|
377
|
+
}
|
|
378
|
+
if (own(body, 'deviceId') !== id || own(body, 'status') !== 'revoked')
|
|
379
|
+
return acceptedUnreadable();
|
|
380
|
+
const revokedAt = nonEmpty(own(body, 'revokedAt'));
|
|
381
|
+
return { kind: 'ok', deviceId: id, ...(revokedAt !== undefined ? { revokedAt } : {}) };
|
|
382
|
+
}
|
|
383
|
+
const IDENTITY_MISMATCH = 'device.identity_mismatch';
|
|
384
|
+
const IDENTITY_MISMATCH_TEXT_PREFIX = `[${IDENTITY_MISMATCH}] `;
|
|
385
|
+
export function deviceIdentityMismatchOf(err) {
|
|
386
|
+
if (err === null || err === undefined)
|
|
387
|
+
return null;
|
|
388
|
+
if (typeof err === 'string')
|
|
389
|
+
return err.startsWith(IDENTITY_MISMATCH_TEXT_PREFIX) ? { code: IDENTITY_MISMATCH } : null;
|
|
390
|
+
if (typeof err !== 'object' && typeof err !== 'function')
|
|
391
|
+
return null;
|
|
392
|
+
const code = readThrownSlot(err, 'errorCode', 'data');
|
|
393
|
+
const message = readThrownSlot(err, 'message');
|
|
394
|
+
if (code !== IDENTITY_MISMATCH && !(typeof message === 'string' && message.startsWith(IDENTITY_MISMATCH_TEXT_PREFIX)))
|
|
395
|
+
return null;
|
|
396
|
+
const bound = readErrorString(err, 'boundDeviceId');
|
|
397
|
+
return Object.freeze({ code: IDENTITY_MISMATCH, ...(bound !== undefined && bound !== '' ? { boundDeviceId: bound } : {}) });
|
|
398
|
+
}
|
|
399
|
+
export function deviceIdentityMismatchLine(detail) {
|
|
400
|
+
const bound = nonEmpty(own(detail, 'boundDeviceId'));
|
|
401
|
+
return [
|
|
402
|
+
'This session was rebound to a different device after that work was minted',
|
|
403
|
+
bound !== undefined && isDisplayableWireCode(bound) ? `It now runs on ${bound}` : 'The engine line above names the device it now runs on',
|
|
404
|
+
'The engine refuses to silently re-target it — the new device has a different workspace',
|
|
405
|
+
"Re-initiate the work on the currently bound device (the session's device binding shows which one that is)",
|
|
406
|
+
].join(' · ');
|
|
407
|
+
}
|
|
408
|
+
export function deviceRegistrationOutcomeLine(verb, outcome) {
|
|
409
|
+
if (verb !== 'issue' && verb !== 'enroll' && verb !== 'revoke')
|
|
410
|
+
return undefined;
|
|
411
|
+
const kind = own(outcome, 'kind');
|
|
412
|
+
switch (kind) {
|
|
413
|
+
case 'rate-limited': {
|
|
414
|
+
const sec = own(outcome, 'retryAfterSec');
|
|
415
|
+
return typeof sec === 'number' && Number.isFinite(sec) && sec > 0
|
|
416
|
+
? `Too many device requests were sent in a short time — wait ${sec} second${sec === 1 ? '' : 's'} and try again.`
|
|
417
|
+
: 'Too many device requests were sent in a short time — wait a moment and try again.';
|
|
418
|
+
}
|
|
419
|
+
case 'enrollment-invalid':
|
|
420
|
+
return 'Enrollment was refused. The token may have expired, may already have been used by another device, or may have been issued to a different account. Ask for a new enrollment token and try again.';
|
|
421
|
+
case 'not-found':
|
|
422
|
+
return 'No such device is visible to you — it may not exist, may belong to someone else, or may already be revoked; the engine deliberately does not say which.';
|
|
423
|
+
case 'lane-absent':
|
|
424
|
+
return own(outcome, 'runStoreOnly') === true
|
|
425
|
+
? 'Device lane not enabled — this engine has the device lane but no run store.'
|
|
426
|
+
: 'Device lane not enabled on this engine.';
|
|
427
|
+
case 'refused': {
|
|
428
|
+
const status = own(outcome, 'status');
|
|
429
|
+
if (status === 0)
|
|
430
|
+
return 'The request is incomplete, so nothing was sent.';
|
|
431
|
+
const code = own(outcome, 'errorCode');
|
|
432
|
+
const shown = typeof code === 'string' && isDisplayableWireCode(code) ? ` ${code}` : '';
|
|
433
|
+
return `The engine refused this request (${typeof status === 'number' ? String(status) : 'no status'}${shown}).`;
|
|
434
|
+
}
|
|
435
|
+
case 'unconfirmed': {
|
|
436
|
+
const accepted = own(outcome, 'why') === 'accepted-unreadable';
|
|
437
|
+
if (verb === 'enroll') {
|
|
438
|
+
return accepted
|
|
439
|
+
? 'The engine accepted the enrollment but did not report the resulting device — it may be enrolled. Sending the same token and public key again is safe: it returns the same device.'
|
|
440
|
+
: 'The enrollment request went out but no confirmation came back — the device may or may not be enrolled. Sending the same token and public key again is safe: it returns the same device.';
|
|
441
|
+
}
|
|
442
|
+
if (verb === 'revoke') {
|
|
443
|
+
return accepted
|
|
444
|
+
? 'The engine accepted the revocation but did not confirm it — the device may be revoked. Revoking again is safe: a second revocation succeeds without changing anything.'
|
|
445
|
+
: 'The revocation request went out but no confirmation came back — the device may or may not be revoked. Revoking again is safe: a second revocation succeeds without changing anything.';
|
|
446
|
+
}
|
|
447
|
+
return accepted
|
|
448
|
+
? 'The engine accepted the request but did not confirm it — it may or may not have taken effect.'
|
|
449
|
+
: 'The request went out but no confirmation came back — it may or may not have taken effect.';
|
|
450
|
+
}
|
|
451
|
+
case 'transport':
|
|
452
|
+
return 'The request did not reach the engine, or no answer came back — nothing was confirmed.';
|
|
453
|
+
case 'unreadable':
|
|
454
|
+
return 'The engine answered, but the answer could not be read.';
|
|
455
|
+
case 'unarmed':
|
|
456
|
+
return 'No device-management connection is set up here, so nothing was sent.';
|
|
457
|
+
default:
|
|
458
|
+
return undefined;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare const REDACTION_MARKER_PREFIX = "\u00ABredacted";
|
|
2
2
|
export declare function looksLikeKnownSecret(s: string): boolean;
|
|
3
|
+
export declare function isDiagnosticValueWord(value: string): boolean;
|
|
3
4
|
export declare function washCredentials(text: string): string;
|
|
4
5
|
export type DisplayMark = 'escape' | 'dot' | 'space';
|
|
5
6
|
export interface DisplayFace {
|