@sema-agent/client-core 0.102.0 → 0.104.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 +172 -0
- package/README.md +23 -17
- package/dist/adapt/toolCards.d.ts +2 -1
- package/dist/adapt/toolCards.js +3 -1
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +5 -1
- package/dist/adapter/downstream/eventToSdkMessage.js +23 -3
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +0 -1
- package/dist/adapter/downstream/terminalToSdkResult.js +3 -2
- package/dist/adapter/downstream/wiringManifestView.js +4 -1
- package/dist/agentSession/engineAgentRegistryRead.js +3 -0
- package/dist/cloudConfigWireCaps.js +6 -3
- package/dist/coreValuePorts.d.ts +3 -1
- package/dist/coreValuePorts.js +5 -0
- package/dist/credentialPlaneCapability.d.ts +22 -0
- package/dist/credentialPlaneCapability.js +75 -0
- package/dist/deviceExecutorManagementCapability.d.ts +1 -0
- package/dist/deviceExecutorManagementCapability.js +3 -1
- package/dist/deviceRebind.d.ts +17 -4
- package/dist/deviceRebind.js +43 -14
- package/dist/engineAgentAbsence.d.ts +1 -0
- package/dist/engineErrorCodes.d.ts +1 -0
- package/dist/engineErrorCodes.js +3 -1
- package/dist/engineNoticeCodes.d.ts +26 -0
- package/dist/engineNoticeCodes.js +121 -12
- package/dist/engineRowRef.js +1 -0
- package/dist/errorSupplementRoles.js +1 -3
- package/dist/eventLeg.js +2 -1
- package/dist/executionPlacementWords.d.ts +3 -0
- package/dist/executionPlacementWords.js +2 -0
- package/dist/fleet/fleetProjection.js +15 -9
- package/dist/gateOutcome.d.ts +20 -0
- package/dist/gateOutcome.js +89 -0
- package/dist/generated/engineAskFaceTables.js +2 -2
- package/dist/generated/engineFactTables.d.ts +8 -3
- package/dist/generated/engineFactTables.js +58 -2
- package/dist/generated/engineNoticeTables.js +30 -0
- package/dist/generated/settingsSchemaDefaultModel.d.ts +1 -1
- package/dist/generated/settingsSchemaDefaultModel.js +2 -2
- package/dist/generated/settingsSchemaFns.d.ts +15 -0
- package/dist/generated/settingsSchemaFns.js +25 -2
- package/dist/generated/settingsSchemaHooksClassifier.js +109 -29
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
- package/dist/generated/settingsSchemaMcpRequestEntry.js +213 -93
- package/dist/generated/settingsSchemaMcpServerName.d.ts +1 -0
- package/dist/generated/settingsSchemaMcpServerName.js +8 -0
- package/dist/generated/settingsSchemaOwnKeyRead.d.ts +1 -0
- package/dist/generated/settingsSchemaOwnKeyRead.js +172 -0
- package/dist/generated/settingsSchemaPlainJsonObject.d.ts +1 -0
- package/dist/generated/settingsSchemaPlainJsonObject.js +28 -0
- package/dist/generated/settingsSchemaSafetyMergeSpec.js +10 -7
- package/dist/generated/settingsSchemaTierWords.d.ts +1 -0
- package/dist/generated/settingsSchemaTierWords.js +7 -0
- package/dist/generated/settingsSchemaTypes.d.ts +3 -1
- package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
- package/dist/hitl/automaticAnswerVerdict.js +47 -11
- package/dist/hitl/decisionConflict.js +11 -11
- package/dist/hitl/decisionRefusal.d.ts +1 -0
- package/dist/hitl/decisionRefusal.js +4 -2
- package/dist/hitl/editedRuleTextPrecheck.d.ts +1 -0
- package/dist/hitl/editedRuleTextPrecheck.js +26 -1
- package/dist/hitl/persistedRulesWire.js +1 -0
- package/dist/hitl/planReviewWire.d.ts +2 -1
- package/dist/hitl/planReviewWire.js +8 -12
- package/dist/hitl/sessionPolicyDeliverable.d.ts +0 -1
- package/dist/hitl/sessionPolicyDeliverable.js +31 -10
- package/dist/hitl/sessionPolicyWire.js +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +20 -7
- package/dist/hitl/toolApprovalWire.js +171 -19
- package/dist/host.d.ts +0 -3
- package/dist/hostTurnSettings.js +3 -1
- package/dist/humanTurn.js +2 -2
- package/dist/i18n/messages.en.d.ts +5 -0
- package/dist/i18n/messages.en.js +6 -1
- package/dist/i18n/messages.zh.js +6 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.js +3 -1
- package/dist/inheritEnvWire.d.ts +1 -0
- package/dist/inheritEnvWire.js +8 -5
- package/dist/jsonFaithful.js +5 -3
- package/dist/mcpEngineLeg.d.ts +3 -0
- package/dist/mcpEngineLeg.js +4 -1
- package/dist/mcpLiveness.d.ts +18 -0
- package/dist/mcpLiveness.js +48 -1
- package/dist/mcpReconnect.d.ts +3 -0
- package/dist/mcpReconnect.js +6 -0
- package/dist/mcpStatusSupersetKeys.js +24 -1
- package/dist/mcpWireCaps.d.ts +2 -3
- package/dist/mcpWireCaps.js +10 -9
- package/dist/memoryEntriesWire.d.ts +35 -1
- package/dist/memoryEntriesWire.js +110 -14
- package/dist/modsFace.js +7 -3
- package/dist/postureKnob.js +1 -1
- package/dist/prepareRefusal.d.ts +0 -1
- package/dist/prepareRefusal.js +0 -3
- package/dist/printModelStatus.d.ts +1 -0
- package/dist/printModelStatus.js +6 -2
- package/dist/promptProfileWireCaps.d.ts +1 -3
- package/dist/promptProfileWireCaps.js +2 -2
- package/dist/request/taskRequest.d.ts +1 -1
- package/dist/request/taskRequest.js +3 -3
- package/dist/retryStatus.d.ts +20 -1
- package/dist/retryStatus.js +31 -7
- package/dist/ruleCompileVerdict.d.ts +1 -0
- package/dist/ruleCompileVerdict.js +3 -1
- package/dist/seatContract.d.ts +7 -7
- package/dist/seatContract.js +49 -10
- package/dist/sessionMemoryErase.js +24 -2
- package/dist/sessionRowTag.d.ts +24 -0
- package/dist/sessionRowTag.js +77 -0
- package/dist/systemReminderTag.js +14 -4
- package/dist/turnFailurePresentation.js +8 -1
- package/dist/wireFailureShape.d.ts +12 -1
- package/dist/wireFailureShape.js +58 -24
- package/dist/wireRefusalCopy.d.ts +0 -3
- package/dist/wireRefusalCopy.js +0 -17
- package/docs/INTEGRATION-CLIENTS.md +400 -14
- package/package.json +5 -5
|
@@ -2,7 +2,7 @@ import type { AdapterContext, AdapterOutput } from '../seam.js';
|
|
|
2
2
|
import { structuredToToolUseResult, type ToolKillCause, type ToolResultBody } from '../toolResult.js';
|
|
3
3
|
import { type Frame, type IdOf } from './ids.js';
|
|
4
4
|
import type { EngineRowRef } from '../engineRowRef.js';
|
|
5
|
-
import { type GateOutcomeView } from '../gateOutcome.js';
|
|
5
|
+
import { type GateOutcomeView, type ToolInputRewriteView } from '../gateOutcome.js';
|
|
6
6
|
type RichToolUseResult = NonNullable<ReturnType<typeof structuredToToolUseResult>>;
|
|
7
7
|
export interface ToolResultOutcome {
|
|
8
8
|
readonly body: ToolResultBody;
|
|
@@ -38,6 +38,7 @@ export interface ToolResultRowFlagParts {
|
|
|
38
38
|
readonly _sema_approval_window_expired?: true;
|
|
39
39
|
readonly _sema_denial_limit_window_expired?: true;
|
|
40
40
|
readonly _sema_answered_by?: string;
|
|
41
|
+
readonly _sema_rewrite?: ToolInputRewriteView;
|
|
41
42
|
}
|
|
42
43
|
export declare function toolResultRowFlagParts(arm: object | null | undefined, gate: GateOutcomeView | undefined): ToolResultRowFlagParts;
|
|
43
44
|
interface ToolEndPayload {
|
package/dist/adapt/toolCards.js
CHANGED
|
@@ -6,7 +6,7 @@ import { toolResultBlocksOf } from '../toolResultContent.js';
|
|
|
6
6
|
import { bashExitOf, bashExitReadingFailed } from '../bashExitReading.js';
|
|
7
7
|
import { isCcToolDenialKind } from '../gateVocabulary.js';
|
|
8
8
|
import { guardedRead, ownSnapshotWhenTyped, readFrameStringKey, readFrameTrueMark, readOwnDataValue } from '../ownKey.js';
|
|
9
|
-
import { gateDeniedBy, isApprovalWindowExpiredGate, isDeniedGate, isDenialLimitAutoDeniedGate } from '../gateOutcome.js';
|
|
9
|
+
import { gateDeniedBy, isApprovalWindowExpiredGate, isDeniedGate, isDenialLimitAutoDeniedGate, toolInputRewriteOf } from '../gateOutcome.js';
|
|
10
10
|
import { TOOL_END_INTERRUPTED_NEVER_STARTED } from '../engineErrorCodes.js';
|
|
11
11
|
function toolUseResultParts(v) {
|
|
12
12
|
return v !== undefined ? { tool_use_result: v } : {};
|
|
@@ -58,6 +58,7 @@ export function toolResultRowFlagParts(arm, gate) {
|
|
|
58
58
|
return {};
|
|
59
59
|
const notExecuted = readFrameTrueMark(arm, 'notExecuted');
|
|
60
60
|
const answeredBy = modAnsweredByOf(arm, notExecuted, gate);
|
|
61
|
+
const rewrite = toolInputRewriteOf(arm);
|
|
61
62
|
return {
|
|
62
63
|
...(notExecuted ? { _sema_not_executed: true } : {}),
|
|
63
64
|
...(readFrameTrueMark(arm, '_sema_collateral_abort') ? { _sema_collateral_abort: true } : {}),
|
|
@@ -65,6 +66,7 @@ export function toolResultRowFlagParts(arm, gate) {
|
|
|
65
66
|
...(isApprovalWindowExpiredGate(gate) ? { _sema_approval_window_expired: true } : {}),
|
|
66
67
|
...(isDenialLimitAutoDeniedGate(gate) ? { _sema_denial_limit_window_expired: true } : {}),
|
|
67
68
|
...(answeredBy !== undefined ? { _sema_answered_by: answeredBy } : {}),
|
|
69
|
+
...(rewrite !== undefined ? { _sema_rewrite: rewrite } : {}),
|
|
68
70
|
};
|
|
69
71
|
}
|
|
70
72
|
const MOD_ENGINE_ORIGIN = 'engine';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AgentEvent, CheckpointGate, TaskResult } from '@sema-agent/sdk';
|
|
2
2
|
import { type WiringManifestView } from './wiringManifestView.js';
|
|
3
3
|
import { type SDKMessage, type EmitContext, type ModelUsage } from '../types.js';
|
|
4
|
-
import { type McpLivenessView } from '../../mcpLiveness.js';
|
|
4
|
+
import { type McpAuthorizationView, type McpLivenessView } from '../../mcpLiveness.js';
|
|
5
5
|
import { type ContextUsageSectionRow, type PromptIdentityLayersRow, type PromptManifestIdentityRow, type PromptManifestSectionRow } from '../../ownKey.js';
|
|
6
6
|
export declare const INTERNAL_SDK_ARM_TYPES: ReadonlySet<string>;
|
|
7
7
|
export type EventProjectionNoneReason = 'usage_only' | 'terminal_delegated' | 'hitl_out_of_slice' | 'not_in_slice' | 'empty_payload';
|
|
@@ -38,6 +38,8 @@ export interface WiringManifestMcpEntryView {
|
|
|
38
38
|
httpStatus?: number;
|
|
39
39
|
liveness?: McpLivenessView;
|
|
40
40
|
livenessUnreadable?: true;
|
|
41
|
+
authorization?: McpAuthorizationView;
|
|
42
|
+
authorizationUnreadable?: true;
|
|
41
43
|
}
|
|
42
44
|
export declare function projectMcpSection(raw: unknown): WiringManifestMcpEntryView[] | undefined;
|
|
43
45
|
export type SubmitWiringManifestReading = {
|
|
@@ -76,6 +78,7 @@ export interface WiringManifestModMountedView {
|
|
|
76
78
|
readonly name: string;
|
|
77
79
|
readonly seat: string;
|
|
78
80
|
readonly tier: string;
|
|
81
|
+
readonly provenance?: string;
|
|
79
82
|
readonly events: readonly string[];
|
|
80
83
|
readonly observe?: readonly string[];
|
|
81
84
|
readonly skipped?: readonly WiringManifestModSkipView[];
|
|
@@ -84,6 +87,7 @@ export interface WiringManifestModRefusedView {
|
|
|
84
87
|
readonly name: string;
|
|
85
88
|
readonly seat: string;
|
|
86
89
|
readonly tier: string;
|
|
90
|
+
readonly provenance?: string;
|
|
87
91
|
readonly refusedBy: string;
|
|
88
92
|
readonly reason: string;
|
|
89
93
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { modRowsOf, readFleetSegment, readInstructionsSegment, wiringManifestViewOf } from './wiringManifestView.js';
|
|
2
2
|
import { stamp, snapshotSegmentIdentity, } from '../types.js';
|
|
3
3
|
import { turnUsageToModelUsage } from './turnUsageToModelUsage.js';
|
|
4
|
-
import { ccToolDenialKindForToolEnd, gateOutcomeOf } from '../../gateOutcome.js';
|
|
4
|
+
import { ccToolDenialKindForToolEnd, gateOutcomeOf, toolInputRewriteOf } from '../../gateOutcome.js';
|
|
5
5
|
import { projectToolRoster, projectToolRosterDelta } from '../../toolRoster.js';
|
|
6
6
|
import { projectHandsSection } from '../../handsSeam.js';
|
|
7
|
-
import { readMcpLiveness } from '../../mcpLiveness.js';
|
|
8
|
-
import { contextUsageReadingOf, humanInputAttachmentsOf, guardedRead, markMcpSectionDroppedNamedRows, ownSnapshotTyped, promptManifestIdentityOfFrame, promptManifestSectionViewOf, readFrameStringKey, readFrameTrueMark, readOwnDataNonEmptyString } from '../../ownKey.js';
|
|
7
|
+
import { readMcpAuthorization, readMcpLiveness } from '../../mcpLiveness.js';
|
|
8
|
+
import { contextUsageReadingOf, humanInputAttachmentsOf, guardedRead, markMcpSectionDroppedNamedRows, ownSnapshotTyped, promptManifestIdentityOfFrame, promptManifestSectionViewOf, readFrameStringKey, readFrameTrueMark, readOwnDataFiniteNumber, readOwnDataNonEmptyString } from '../../ownKey.js';
|
|
9
9
|
import { SEGMENT_END_IDENTITY_KEYS, eventSeq, stripToolUseSideChannels } from '../types.js';
|
|
10
10
|
import { frozenSet } from '../../frozenSet.js';
|
|
11
11
|
import { isCoreWorkflowRunTerminal } from '../../terminalStatuses.js';
|
|
@@ -73,6 +73,11 @@ const dropped = (why, type) => ({ kind: 'dropped', why, type });
|
|
|
73
73
|
function isCompactionStartedFrame(ev) {
|
|
74
74
|
return ev.type === 'compaction_started';
|
|
75
75
|
}
|
|
76
|
+
const BEYOND_FLOOR_ARMS = Object.freeze(['cross_boundary_taint', 'approval_complete', 'session_titled']);
|
|
77
|
+
function isBeyondFloorArm(ev) {
|
|
78
|
+
const word = ev.type;
|
|
79
|
+
return typeof word === 'string' && BEYOND_FLOOR_ARMS.includes(word);
|
|
80
|
+
}
|
|
76
81
|
function assertNeverArm(_ev) {
|
|
77
82
|
}
|
|
78
83
|
export function eventToSdkMessage(ev, ctx) {
|
|
@@ -106,6 +111,10 @@ function withEngineIdentity(p, ev, ctx, identityFrame = ev) {
|
|
|
106
111
|
function projectEvent(ev, ctx) {
|
|
107
112
|
if (isCompactionStartedFrame(ev))
|
|
108
113
|
return compactionStartedProjection(ev, ctx);
|
|
114
|
+
if (isBeyondFloorArm(ev)) {
|
|
115
|
+
const word = ev.type;
|
|
116
|
+
return word === 'cross_boundary_taint' ? nothing('not_in_slice') : dropped('unsupported_arm', word);
|
|
117
|
+
}
|
|
109
118
|
switch (ev.type) {
|
|
110
119
|
case 'task_started':
|
|
111
120
|
return taskStartedProjection(ev, ctx);
|
|
@@ -230,6 +239,7 @@ function projectEvent(ev, ctx) {
|
|
|
230
239
|
const denialKind = ccToolDenialKindForToolEnd(ev);
|
|
231
240
|
const toolEndNotExecuted = readFrameTrueMark(ev, 'notExecuted');
|
|
232
241
|
const toolEndAnsweredBy = readFrameStringKey(ev, 'answeredBy');
|
|
242
|
+
const toolEndRewrite = toolInputRewriteOf(ev);
|
|
233
243
|
return projected(stamp(ctx, armBody({
|
|
234
244
|
type: 'tool_end_result',
|
|
235
245
|
toolCallId: ev.toolCallId,
|
|
@@ -253,6 +263,7 @@ function projectEvent(ev, ctx) {
|
|
|
253
263
|
...(denialKind !== undefined ? { _sema_denial_kind: denialKind } : {}),
|
|
254
264
|
...(toolEndNotExecuted ? { notExecuted: true } : {}),
|
|
255
265
|
...(toolEndAnsweredBy !== undefined ? { answeredBy: toolEndAnsweredBy } : {}),
|
|
266
|
+
...(toolEndRewrite !== undefined ? { rewrite: toolEndRewrite } : {}),
|
|
256
267
|
...(ev.eventId !== undefined ? { eventId: ev.eventId } : {}),
|
|
257
268
|
...(ev.parentToolCallId !== undefined
|
|
258
269
|
? { parentToolCallId: ev.parentToolCallId }
|
|
@@ -272,6 +283,11 @@ function projectEvent(ev, ctx) {
|
|
|
272
283
|
const nonEmptyStr = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
|
|
273
284
|
const providerCondition = nonEmptyStr(ev.providerCondition);
|
|
274
285
|
const providerConditionSource = nonEmptyStr(ev.providerConditionSource);
|
|
286
|
+
const stWait = ev;
|
|
287
|
+
const sleptMsRaw = guardedRead(() => readOwnDataFiniteNumber(stWait, 'sleptMs'));
|
|
288
|
+
const sleptMs = sleptMsRaw !== undefined && sleptMsRaw >= 0 ? sleptMsRaw : undefined;
|
|
289
|
+
const waitSegment = readFrameStringKey(stWait, 'waitSegment');
|
|
290
|
+
const seat = readFrameStringKey(ev, 'seat');
|
|
275
291
|
return projected(stamp(ctx, armBody({
|
|
276
292
|
type: 'retry_status',
|
|
277
293
|
phase: ev.phase,
|
|
@@ -287,6 +303,9 @@ function projectEvent(ev, ctx) {
|
|
|
287
303
|
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
288
304
|
...(providerCondition !== undefined ? { providerCondition } : {}),
|
|
289
305
|
...(providerConditionSource !== undefined ? { providerConditionSource } : {}),
|
|
306
|
+
...(sleptMs !== undefined ? { sleptMs } : {}),
|
|
307
|
+
...(waitSegment !== undefined ? { waitSegment } : {}),
|
|
308
|
+
...(seat !== undefined ? { seat } : {}),
|
|
290
309
|
...(typeof ev.eventId === 'string' ? { eventId: ev.eventId } : {}),
|
|
291
310
|
...(typeof ev.parentToolCallId === 'string' ? { parentToolCallId: ev.parentToolCallId } : {}),
|
|
292
311
|
})));
|
|
@@ -555,6 +574,7 @@ export function projectMcpSection(raw) {
|
|
|
555
574
|
...(typeof r.delivered === 'string' && r.delivered.length > 0 ? { delivered: r.delivered } : {}),
|
|
556
575
|
...(typeof r.httpStatus === 'number' && Number.isFinite(r.httpStatus) ? { httpStatus: r.httpStatus } : {}),
|
|
557
576
|
...((cell) => cell.kind === 'observation' ? { liveness: cell.liveness } : cell.kind === 'unreadable' ? { livenessUnreadable: true } : {})(readMcpLiveness(r)),
|
|
577
|
+
...((cell) => cell.kind === 'record' ? { authorization: cell.authorization } : cell.kind === 'unreadable' ? { authorizationUnreadable: true } : {})(readMcpAuthorization(r)),
|
|
558
578
|
});
|
|
559
579
|
}
|
|
560
580
|
if (raw.length > 0 && rows.length === 0)
|
|
@@ -61,7 +61,6 @@ export interface PermissionDenialParts {
|
|
|
61
61
|
export interface SemaCostBreakdown {
|
|
62
62
|
readonly llmRootMicroUsd?: number;
|
|
63
63
|
readonly nestedSubagentMicroUsd?: number;
|
|
64
|
-
readonly memoryConsolidationMicroUsd?: number;
|
|
65
64
|
readonly suggestionsMicroUsd?: number;
|
|
66
65
|
readonly compactionMicroUsd?: number;
|
|
67
66
|
readonly [k: string]: number | undefined;
|
|
@@ -564,6 +564,8 @@ function printArmReadingOf(input) {
|
|
|
564
564
|
const stop_reason = printArmStopReasonOf(lastRow);
|
|
565
565
|
if (kind === 'completed')
|
|
566
566
|
return { arm: Object.freeze({ subtype: 'success', is_error: false, stop_reason }) };
|
|
567
|
+
if (kind === 'paused')
|
|
568
|
+
return { arm: Object.freeze({ subtype: 'error_during_execution', is_error: true, stop_reason }) };
|
|
567
569
|
if (kind === 'failed') {
|
|
568
570
|
const code = readOwnDataValue(terminal, 'code');
|
|
569
571
|
const limit = typeof code === 'string' ? resultLimitRowOfCode(code) : undefined;
|
|
@@ -644,7 +646,6 @@ function errorResult(ctx, parts) {
|
|
|
644
646
|
...('limit' in arm && arm.limit !== undefined ? { _sema_limit: arm.limit } : {}),
|
|
645
647
|
...(parts.wayOut !== undefined ? { _sema_wayOut: wayOutOnFrame(parts.wayOut) } : {}),
|
|
646
648
|
...(parts.codedDetail !== undefined ? { _sema_coded_detail: parts.codedDetail } : {}),
|
|
647
|
-
...(parts.errorCode !== undefined && parts.errorCode.length > 0 && errorsStateCode(errors[0], parts.errorCode) ? { _sema_error_code_in_text: true } : {}),
|
|
648
649
|
};
|
|
649
650
|
if (arm.subtype === 'success') {
|
|
650
651
|
return stamp(ctx, {
|
|
@@ -654,7 +655,6 @@ function errorResult(ctx, parts) {
|
|
|
654
655
|
subtype: 'success',
|
|
655
656
|
...head,
|
|
656
657
|
result,
|
|
657
|
-
errors,
|
|
658
658
|
...tail,
|
|
659
659
|
});
|
|
660
660
|
}
|
|
@@ -666,6 +666,7 @@ function errorResult(ctx, parts) {
|
|
|
666
666
|
...head,
|
|
667
667
|
errors,
|
|
668
668
|
...tail,
|
|
669
|
+
...(parts.errorCode !== undefined && parts.errorCode.length > 0 && errorsStateCode(errors[0], parts.errorCode) ? { _sema_error_code_in_text: true } : {}),
|
|
669
670
|
});
|
|
670
671
|
}
|
|
671
672
|
function errorsStateCode(first, code) {
|
|
@@ -127,6 +127,8 @@ function modRowOf(r) {
|
|
|
127
127
|
const name = nonEmpty(ownSlot(r, 'name'));
|
|
128
128
|
const seat = nonEmpty(ownSlot(r, 'seat'));
|
|
129
129
|
const tier = nonEmpty(ownSlot(r, 'tier'));
|
|
130
|
+
const provenance = nonEmpty(ownSlot(r, 'provenance'));
|
|
131
|
+
const provenancePart = provenance !== undefined ? { provenance } : {};
|
|
130
132
|
if (name === undefined || seat === undefined || tier === undefined)
|
|
131
133
|
return undefined;
|
|
132
134
|
const events = ownSlot(r, 'events');
|
|
@@ -143,7 +145,7 @@ function modRowOf(r) {
|
|
|
143
145
|
const why = nonEmpty(reason);
|
|
144
146
|
if (by === undefined || why === undefined)
|
|
145
147
|
return undefined;
|
|
146
|
-
const refused = { name, seat, tier, refusedBy: by, reason: why };
|
|
148
|
+
const refused = { name, seat, tier, ...provenancePart, refusedBy: by, reason: why };
|
|
147
149
|
return refused;
|
|
148
150
|
}
|
|
149
151
|
const eventList = events.state === 'value' ? ownStringList(events.value) : undefined;
|
|
@@ -155,6 +157,7 @@ function modRowOf(r) {
|
|
|
155
157
|
name,
|
|
156
158
|
seat,
|
|
157
159
|
tier,
|
|
160
|
+
...provenancePart,
|
|
158
161
|
events: eventList,
|
|
159
162
|
...(observeList !== undefined ? { observe: observeList } : {}),
|
|
160
163
|
...(skipList !== undefined && skipList.length > 0 ? { skipped: skipList } : {}),
|
|
@@ -2,6 +2,7 @@ import { errCodes } from '../controlRouter.js';
|
|
|
2
2
|
import { hostLog } from '../host.js';
|
|
3
3
|
import { isSessionIdPathSegment } from '../sessionIdSegment.js';
|
|
4
4
|
import { engineCapNestedValue } from '../engineCapsCache.js';
|
|
5
|
+
import { guardedRead, readOwnDataValue } from '../ownKey.js';
|
|
5
6
|
const unavailable = (why) => ({
|
|
6
7
|
kind: 'unavailable',
|
|
7
8
|
why,
|
|
@@ -75,12 +76,14 @@ function readRow(v) {
|
|
|
75
76
|
return undefined;
|
|
76
77
|
const description = Object.hasOwn(o, 'description') ? o.description : undefined;
|
|
77
78
|
const createdAt = Object.hasOwn(o, 'createdAt') ? o.createdAt : undefined;
|
|
79
|
+
const childSessionId = type === 'background_agent' ? guardedRead(() => readOwnDataValue(o, 'sessionId')) : undefined;
|
|
78
80
|
return {
|
|
79
81
|
id,
|
|
80
82
|
type,
|
|
81
83
|
status,
|
|
82
84
|
...(typeof description === 'string' && description.length > 0 ? { description } : {}),
|
|
83
85
|
...(typeof createdAt === 'number' && Number.isFinite(createdAt) ? { createdAt } : {}),
|
|
86
|
+
...(typeof childSessionId === 'string' && childSessionId.length > 0 ? { sessionId: childSessionId } : {}),
|
|
84
87
|
};
|
|
85
88
|
}
|
|
86
89
|
export async function readEngineAgentRegistry(client, sessionId, capsBaseUrl, opts) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mcpAllowToolsVerdict, mcpAssertionHeaderNotSentNotice, mcpElicitationVerdict, mcpToolAxesVerdict, mcpToolFacesVerdict, readMcpHttpIdentityHeaders } from './mcpWireCaps.js';
|
|
2
2
|
import { skillToolListsVerdict, toCappedSpec } from './skillsWireCaps.js';
|
|
3
|
-
import {
|
|
3
|
+
import { SETTINGS_DESCRIBE_BAD_MCP_SERVER_NAME, SETTINGS_IS_USABLE_MCP_SERVER_NAME, SETTINGS_READ_REQUEST_MCP_TRANSPORT } from './generated/settingsSchemaFns.js';
|
|
4
4
|
import { snapshotArgs, wireTransportOf } from './mcpWireTransport.js';
|
|
5
5
|
import { msg, renderMessage } from './i18n/translate.js';
|
|
6
6
|
import { TIER_ORDER } from './model/tierVocabulary.js';
|
|
@@ -66,7 +66,7 @@ export function cloudMcpToSpecs(servers, env) {
|
|
|
66
66
|
recordDrop(name, 'missing-field');
|
|
67
67
|
continue;
|
|
68
68
|
}
|
|
69
|
-
if (!
|
|
69
|
+
if (!SETTINGS_IS_USABLE_MCP_SERVER_NAME(name)) {
|
|
70
70
|
recordDrop(name, 'name-unusable');
|
|
71
71
|
continue;
|
|
72
72
|
}
|
|
@@ -148,10 +148,12 @@ export function cloudMcpToSpecs(servers, env) {
|
|
|
148
148
|
let axesDeclared;
|
|
149
149
|
let elicitationDeclared;
|
|
150
150
|
let allowDeclared;
|
|
151
|
+
let startupDeclared;
|
|
151
152
|
try {
|
|
152
153
|
axesDeclared = s.toolAxes;
|
|
153
154
|
elicitationDeclared = s.elicitation;
|
|
154
155
|
allowDeclared = s.allowTools;
|
|
156
|
+
startupDeclared = s.startupTimeoutMs;
|
|
155
157
|
}
|
|
156
158
|
catch {
|
|
157
159
|
recordDrop(name, 'entry-unreadable');
|
|
@@ -199,6 +201,7 @@ export function cloudMcpToSpecs(servers, env) {
|
|
|
199
201
|
...(elVerdict.elicitation !== undefined ? { elicitation: elVerdict.elicitation } : {}),
|
|
200
202
|
...(facesShipped !== undefined ? { toolFaces: facesShipped } : {}),
|
|
201
203
|
...(axesShipped !== undefined ? { toolAxes: axesShipped } : {}),
|
|
204
|
+
...(startupDeclared !== undefined ? { startupTimeoutMs: startupDeclared } : {}),
|
|
202
205
|
});
|
|
203
206
|
}
|
|
204
207
|
return { specs, missingEnv: [...new Set(missingEnv)], droppedServers, degradedServers };
|
|
@@ -859,7 +862,7 @@ function droppedMcpNotices(carrier) {
|
|
|
859
862
|
const label = name === undefined
|
|
860
863
|
? undefined
|
|
861
864
|
: reason === 'name-unusable'
|
|
862
|
-
?
|
|
865
|
+
? SETTINGS_DESCRIBE_BAD_MCP_SERVER_NAME(name)
|
|
863
866
|
: reason === 'transport-invalid' || reason === 'allow-tools-invalid' || reason === 'entry-unreadable'
|
|
864
867
|
? `"${capForDisplay(name, DEGRADED_NAME_SHOWN)}"${pathLabel}`
|
|
865
868
|
: `"${name}"${pathLabel}`;
|
package/dist/coreValuePorts.d.ts
CHANGED
|
@@ -149,8 +149,9 @@ export interface CoreValuePorts {
|
|
|
149
149
|
readMcpToolAxes(declared: {} | null | undefined): McpToolAxesReadView;
|
|
150
150
|
ANTHROPIC_DEFAULT_BASE_URL: string;
|
|
151
151
|
readToolFaces(declared: {} | null | undefined): McpToolFacesReadView;
|
|
152
|
+
ruleNameCovers: (ruleName: string, toolName: string) => boolean;
|
|
152
153
|
}
|
|
153
|
-
export declare const CORE_VALUE_PORT_NAMES: readonly ["resolveAutonomousLoopPrompt", "loosenReasons", "combinePolicies", "createAllowDenyPolicy", "MCP_NAMESPACE", "protocolOf", "ruleToolGrammarOf", "validatePermissionRules", "mintNamespacePrefix", "compileAllowList", "routeKeyOf", "joinRequestUrl", "resolveRouteCredential", "adjudicateModelRoute", "routePairingStatus", "judgeRuleToolName", "readRuleEntry", "readMcpToolAxes", "ANTHROPIC_DEFAULT_BASE_URL", "readToolFaces"];
|
|
154
|
+
export declare const CORE_VALUE_PORT_NAMES: readonly ["resolveAutonomousLoopPrompt", "loosenReasons", "combinePolicies", "createAllowDenyPolicy", "MCP_NAMESPACE", "protocolOf", "ruleToolGrammarOf", "validatePermissionRules", "mintNamespacePrefix", "compileAllowList", "routeKeyOf", "joinRequestUrl", "resolveRouteCredential", "adjudicateModelRoute", "routePairingStatus", "judgeRuleToolName", "readRuleEntry", "readMcpToolAxes", "ANTHROPIC_DEFAULT_BASE_URL", "readToolFaces", "ruleNameCovers"];
|
|
154
155
|
export type CoreValuePortName = (typeof CORE_VALUE_PORT_NAMES)[number];
|
|
155
156
|
export declare function installCoreValuePorts(ports: Partial<CoreValuePorts> | null): () => void;
|
|
156
157
|
export declare function hasCoreValuePorts(): boolean;
|
|
@@ -180,3 +181,4 @@ export declare function readRuleEntry(raw: {} | null | undefined, behavior: 'all
|
|
|
180
181
|
export declare function readMcpToolAxes(declared: {} | null | undefined): McpToolAxesReadView | undefined;
|
|
181
182
|
export declare function anthropicDefaultBaseUrl(): string | undefined;
|
|
182
183
|
export declare function readToolFaces(declared: {} | null | undefined): McpToolFacesReadView | undefined;
|
|
184
|
+
export declare function ruleNameCovers(ruleName: string, toolName: string): boolean | undefined;
|
package/dist/coreValuePorts.js
CHANGED
|
@@ -19,6 +19,7 @@ export const CORE_VALUE_PORT_NAMES = Object.freeze([
|
|
|
19
19
|
'readMcpToolAxes',
|
|
20
20
|
'ANTHROPIC_DEFAULT_BASE_URL',
|
|
21
21
|
'readToolFaces',
|
|
22
|
+
'ruleNameCovers',
|
|
22
23
|
]);
|
|
23
24
|
let installed = null;
|
|
24
25
|
export function installCoreValuePorts(ports) {
|
|
@@ -118,3 +119,7 @@ export function readToolFaces(declared) {
|
|
|
118
119
|
const fn = port('readToolFaces');
|
|
119
120
|
return fn === undefined ? undefined : fn(declared);
|
|
120
121
|
}
|
|
122
|
+
export function ruleNameCovers(ruleName, toolName) {
|
|
123
|
+
const fn = port('ruleNameCovers');
|
|
124
|
+
return fn === undefined ? undefined : fn(ruleName, toolName);
|
|
125
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type SandboxGitCredentialOriginView = {
|
|
2
|
+
readonly origin: string;
|
|
3
|
+
readonly delivers: true;
|
|
4
|
+
} | {
|
|
5
|
+
readonly origin: string;
|
|
6
|
+
readonly delivers: false;
|
|
7
|
+
readonly reason: string;
|
|
8
|
+
};
|
|
9
|
+
export type SandboxGitCredentialPlaneReading = {
|
|
10
|
+
readonly kind: 'unobserved';
|
|
11
|
+
} | {
|
|
12
|
+
readonly kind: 'not_reported';
|
|
13
|
+
} | {
|
|
14
|
+
readonly kind: 'unreadable';
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: 'off';
|
|
17
|
+
readonly reason: string;
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: 'on';
|
|
20
|
+
readonly origins: readonly SandboxGitCredentialOriginView[];
|
|
21
|
+
};
|
|
22
|
+
export declare function observedSandboxGitCredentialPlane(baseUrl?: string | undefined): SandboxGitCredentialPlaneReading;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { engineCapValue } from './engineCapsCache.js';
|
|
2
|
+
import { engineWireTargetBaseUrl } from './engineWireTarget.js';
|
|
3
|
+
import { ownDataField } from './ownKey.js';
|
|
4
|
+
const UNOBSERVED = Object.freeze({ kind: 'unobserved' });
|
|
5
|
+
const NOT_REPORTED = Object.freeze({ kind: 'not_reported' });
|
|
6
|
+
const UNREADABLE = Object.freeze({ kind: 'unreadable' });
|
|
7
|
+
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
8
|
+
const nonEmpty = (v) => typeof v === 'string' && v.length > 0;
|
|
9
|
+
function readOrigin(v) {
|
|
10
|
+
if (!isRecord(v))
|
|
11
|
+
return undefined;
|
|
12
|
+
const origin = ownDataField(v, 'origin');
|
|
13
|
+
const delivers = ownDataField(v, 'delivers');
|
|
14
|
+
if (!nonEmpty(origin))
|
|
15
|
+
return undefined;
|
|
16
|
+
if (delivers === true)
|
|
17
|
+
return Object.freeze({ origin, delivers: true });
|
|
18
|
+
if (delivers !== false)
|
|
19
|
+
return undefined;
|
|
20
|
+
const reason = ownDataField(v, 'reason');
|
|
21
|
+
return nonEmpty(reason) ? Object.freeze({ origin, delivers: false, reason }) : undefined;
|
|
22
|
+
}
|
|
23
|
+
function projectSandboxGit(plane) {
|
|
24
|
+
try {
|
|
25
|
+
if (!isRecord(plane))
|
|
26
|
+
return UNREADABLE;
|
|
27
|
+
const sg = ownDataField(plane, 'sandboxGit');
|
|
28
|
+
if (sg === undefined)
|
|
29
|
+
return NOT_REPORTED;
|
|
30
|
+
if (!isRecord(sg))
|
|
31
|
+
return UNREADABLE;
|
|
32
|
+
const state = ownDataField(sg, 'state');
|
|
33
|
+
if (state === 'off') {
|
|
34
|
+
const reason = ownDataField(sg, 'reason');
|
|
35
|
+
return nonEmpty(reason) ? Object.freeze({ kind: 'off', reason }) : UNREADABLE;
|
|
36
|
+
}
|
|
37
|
+
if (state !== 'on')
|
|
38
|
+
return UNREADABLE;
|
|
39
|
+
const list = ownDataField(sg, 'origins');
|
|
40
|
+
if (!Array.isArray(list))
|
|
41
|
+
return UNREADABLE;
|
|
42
|
+
const n = ownDataField(list, 'length');
|
|
43
|
+
if (typeof n !== 'number' || !Number.isInteger(n) || n < 0)
|
|
44
|
+
return UNREADABLE;
|
|
45
|
+
const origins = [];
|
|
46
|
+
for (let i = 0; i < n; i += 1) {
|
|
47
|
+
const row = readOrigin(ownDataField(list, String(i)));
|
|
48
|
+
if (row === undefined)
|
|
49
|
+
return UNREADABLE;
|
|
50
|
+
origins.push(row);
|
|
51
|
+
}
|
|
52
|
+
return Object.freeze({ kind: 'on', origins: Object.freeze(origins) });
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return UNREADABLE;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function observedSandboxGitCredentialPlane(baseUrl = engineWireTargetBaseUrl()) {
|
|
59
|
+
try {
|
|
60
|
+
const slot = engineCapValue(typeof baseUrl === 'string' && baseUrl.length > 0 ? baseUrl : undefined, 'credentialPlane');
|
|
61
|
+
switch (slot.kind) {
|
|
62
|
+
case 'unobserved':
|
|
63
|
+
return UNOBSERVED;
|
|
64
|
+
case 'not_reported':
|
|
65
|
+
return NOT_REPORTED;
|
|
66
|
+
case 'value':
|
|
67
|
+
return projectSandboxGit(slot.value);
|
|
68
|
+
default:
|
|
69
|
+
return UNREADABLE;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return UNOBSERVED;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -13,6 +13,7 @@ export type DeviceExecutorManagementReading = {
|
|
|
13
13
|
protocolVersion?: number;
|
|
14
14
|
maxInflightPerDevice?: number;
|
|
15
15
|
wsPath?: string;
|
|
16
|
+
relayUrl?: string;
|
|
16
17
|
};
|
|
17
18
|
export declare function projectDeviceExecutorManagementCapability(caps: unknown): DeviceExecutorManagementReading | undefined;
|
|
18
19
|
export declare function observedDeviceExecutorManagement(baseUrl?: string | undefined): DeviceExecutorManagementReading;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { engineWireTargetBaseUrl } from './engineWireTarget.js';
|
|
2
2
|
import { createEngineCapReader, unreadableReadingDetail } from './engineCapReader.js';
|
|
3
|
-
import { ownDataField } from './ownKey.js';
|
|
3
|
+
import { guardedRead, ownDataField } from './ownKey.js';
|
|
4
4
|
import { capForDisplay } from './fleetTaskDesc.js';
|
|
5
5
|
export function projectDeviceExecutorManagementCapability(caps) {
|
|
6
6
|
try {
|
|
@@ -28,12 +28,14 @@ export function projectDeviceExecutorManagementCapability(caps) {
|
|
|
28
28
|
const pv = ownDataField(d, 'protocolVersion');
|
|
29
29
|
const mi = ownDataField(d, 'maxInflightPerDevice');
|
|
30
30
|
const ws = ownDataField(d, 'wsPath');
|
|
31
|
+
const relay = guardedRead(() => ownDataField(d, 'relayUrl'));
|
|
31
32
|
return {
|
|
32
33
|
kind: 'present',
|
|
33
34
|
management,
|
|
34
35
|
...(typeof pv === 'number' && Number.isFinite(pv) ? { protocolVersion: pv } : {}),
|
|
35
36
|
...(typeof mi === 'number' && Number.isFinite(mi) && mi >= 0 ? { maxInflightPerDevice: mi } : {}),
|
|
36
37
|
...(typeof ws === 'string' && ws.length > 0 ? { wsPath: ws } : {}),
|
|
38
|
+
...(typeof relay === 'string' && relay.length > 0 ? { relayUrl: relay } : {}),
|
|
37
39
|
};
|
|
38
40
|
}
|
|
39
41
|
catch {
|
package/dist/deviceRebind.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { AgentClient, DeviceEnrollRequest } from '@sema-agent/sdk';
|
|
2
|
+
import { type ExecutionPlacementRole } from './executionPlacementWords.js';
|
|
2
3
|
export type DeviceListVerb = Pick<AgentClient['devices'], 'list'>;
|
|
3
|
-
export
|
|
4
|
+
export interface SessionExecutionPlacementVerb {
|
|
5
|
+
executionPlacement(sessionId: string, opts?: {
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
}): Promise<object>;
|
|
8
|
+
}
|
|
4
9
|
export type DeviceRebindVerb = Pick<AgentClient['devices'], 'rebind'>;
|
|
5
10
|
export type DeviceIssueEnrollTokenVerb = Pick<AgentClient['devices'], 'issueEnrollToken'>;
|
|
6
11
|
export type DeviceEnrollVerb = Pick<AgentClient['devices'], 'enroll'>;
|
|
@@ -14,7 +19,6 @@ export interface DeviceRosterRow {
|
|
|
14
19
|
export interface DeviceBindingReading {
|
|
15
20
|
readonly deviceId: string;
|
|
16
21
|
readonly rev: number;
|
|
17
|
-
readonly boundAt?: string;
|
|
18
22
|
}
|
|
19
23
|
export interface DeviceRefused {
|
|
20
24
|
readonly kind: 'refused';
|
|
@@ -37,6 +41,10 @@ export interface DeviceUnreadable {
|
|
|
37
41
|
export interface DeviceUnarmed {
|
|
38
42
|
readonly kind: 'unarmed';
|
|
39
43
|
}
|
|
44
|
+
export interface DeviceFaceUnsupported {
|
|
45
|
+
readonly kind: 'unsupported';
|
|
46
|
+
readonly reason: 'route' | 'capability';
|
|
47
|
+
}
|
|
40
48
|
export type DeviceListOutcome = {
|
|
41
49
|
readonly kind: 'ok';
|
|
42
50
|
readonly devices: readonly DeviceRosterRow[];
|
|
@@ -46,9 +54,12 @@ export type DeviceSessionBindingOutcome = {
|
|
|
46
54
|
readonly kind: 'ok';
|
|
47
55
|
readonly rootSessionId: string;
|
|
48
56
|
readonly boundDevice: DeviceBindingReading;
|
|
57
|
+
} | {
|
|
58
|
+
readonly kind: 'unbound';
|
|
59
|
+
readonly role: ExecutionPlacementRole;
|
|
49
60
|
} | {
|
|
50
61
|
readonly kind: 'not-found';
|
|
51
|
-
} |
|
|
62
|
+
} | DeviceFaceUnsupported | DeviceUnreadable | DeviceRefused | DeviceTransport | DeviceUnarmed;
|
|
52
63
|
export interface DeviceRebindInput {
|
|
53
64
|
readonly rootSessionId: string;
|
|
54
65
|
readonly toDeviceId: string;
|
|
@@ -69,6 +80,8 @@ export type DeviceRebindOutcome = {
|
|
|
69
80
|
} | {
|
|
70
81
|
readonly kind: 'active-run';
|
|
71
82
|
readonly activeTaskId?: string;
|
|
83
|
+
readonly children?: readonly string[];
|
|
84
|
+
readonly retirePath?: string;
|
|
72
85
|
} | {
|
|
73
86
|
readonly kind: 'rev-conflict';
|
|
74
87
|
readonly currentRev?: number;
|
|
@@ -79,7 +92,7 @@ export type DeviceRebindReconcileVerdict = 'landed' | 'already-there' | 'unchang
|
|
|
79
92
|
export declare function listDevices(devices: DeviceListVerb | null | undefined, opts?: {
|
|
80
93
|
readonly signal?: AbortSignal | undefined;
|
|
81
94
|
}): Promise<DeviceListOutcome>;
|
|
82
|
-
export declare function readSessionBinding(
|
|
95
|
+
export declare function readSessionBinding(sessions: SessionExecutionPlacementVerb | null | undefined, rootSessionId: string, opts?: {
|
|
83
96
|
readonly signal?: AbortSignal | undefined;
|
|
84
97
|
}): Promise<DeviceSessionBindingOutcome>;
|
|
85
98
|
export declare function rebindSession(devices: DeviceRebindVerb | null | undefined, req: DeviceRebindInput, opts?: {
|
package/dist/deviceRebind.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { atMostOnceVerdictOf } from './atMostOnce.js';
|
|
2
2
|
import { readOwnDataValue } from './ownKey.js';
|
|
3
|
-
import { isDisplayableWireCode, readErrorString, readThrownSlot, wireFailureShapeOf } from './wireFailureShape.js';
|
|
3
|
+
import { isDisplayableWireCode, readErrorString, readErrorStrictStringList, readThrownSlot, wireFailureShapeOf } from './wireFailureShape.js';
|
|
4
|
+
import { EXECUTION_PLACEMENT_DEVICE_LANE, EXECUTION_PLACEMENT_ROLES } from './executionPlacementWords.js';
|
|
4
5
|
const LANE_ABSENT = 'capability.device_lane_required';
|
|
5
6
|
const RUN_STORE_ABSENT = 'capability.run_store_required';
|
|
6
7
|
const NOT_FOUND = 'not_found.device';
|
|
7
8
|
const ACTIVE_RUN = 'device.rebind_active_run';
|
|
9
|
+
const SESSION_NOT_FOUND = 'not_found.session';
|
|
10
|
+
const ROUTE_ABSENT = 'not_found.route';
|
|
11
|
+
const SESSION_STORE_ABSENT = 'capability.session_store_required';
|
|
8
12
|
const REV_CONFLICT = 'device.rebind_rev_conflict';
|
|
9
13
|
const SERVICE_TOKEN_REQUIRED = 'auth.service_token_required';
|
|
10
14
|
function own(v, key) {
|
|
@@ -123,29 +127,50 @@ function bindingOf(raw) {
|
|
|
123
127
|
const rev = nonNegInt(own(raw, 'rev'));
|
|
124
128
|
if (deviceId === undefined || rev === undefined)
|
|
125
129
|
return null;
|
|
126
|
-
|
|
127
|
-
return { deviceId, rev, ...(boundAt !== undefined ? { boundAt } : {}) };
|
|
130
|
+
return { deviceId, rev };
|
|
128
131
|
}
|
|
129
|
-
|
|
130
|
-
const
|
|
132
|
+
function placementReadFailureOf(e) {
|
|
133
|
+
const v = atMostOnceVerdictOf(e);
|
|
134
|
+
if (v.status === 404 && v.code === SESSION_NOT_FOUND)
|
|
135
|
+
return { kind: 'not-found' };
|
|
136
|
+
if (v.status === 404 && v.code === ROUTE_ABSENT)
|
|
137
|
+
return { kind: 'unsupported', reason: 'route' };
|
|
138
|
+
if (v.status === 501 && v.code === SESSION_STORE_ABSENT)
|
|
139
|
+
return { kind: 'unsupported', reason: 'capability' };
|
|
140
|
+
return v.status !== undefined ? refusedOf(v.status, v.code, e) : transportOf(v);
|
|
141
|
+
}
|
|
142
|
+
const isPlacementRole = (v) => typeof v === 'string' && EXECUTION_PLACEMENT_ROLES.includes(v);
|
|
143
|
+
export async function readSessionBinding(sessions, rootSessionId, opts) {
|
|
144
|
+
if (typeof rootSessionId !== 'string' || rootSessionId === '') {
|
|
145
|
+
return { kind: 'refused', status: 0, errorCode: 'request.id_invalid', message: 'the session id to read the execution placement of must be a non-empty string — nothing was sent' };
|
|
146
|
+
}
|
|
147
|
+
const verb = verbOf(sessions, 'executionPlacement');
|
|
131
148
|
if (verb === undefined)
|
|
132
149
|
return { kind: 'unarmed' };
|
|
133
150
|
let body;
|
|
134
151
|
try {
|
|
135
|
-
body = await verb.call(
|
|
152
|
+
body = await verb.call(sessions, rootSessionId, signalOpts(opts));
|
|
136
153
|
}
|
|
137
154
|
catch (e) {
|
|
138
|
-
return
|
|
155
|
+
return placementReadFailureOf(e);
|
|
156
|
+
}
|
|
157
|
+
const role = own(body, 'role');
|
|
158
|
+
if (!isPlacementRole(role)) {
|
|
159
|
+
return { kind: 'unreadable', why: 'the execution placement it returned names no role this client knows (absent / writer / mirror / forking) — refusing to read it as "not bound"' };
|
|
139
160
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
161
|
+
if (role !== 'writer')
|
|
162
|
+
return { kind: 'unbound', role };
|
|
163
|
+
const lane = own(body, 'lane');
|
|
164
|
+
if (typeof lane !== 'string' || lane === '') {
|
|
165
|
+
return { kind: 'unreadable', why: "the writer's execution lane in the execution placement is missing or not a word — refusing to guess whether a device is bound" };
|
|
143
166
|
}
|
|
144
|
-
|
|
167
|
+
if (lane !== EXECUTION_PLACEMENT_DEVICE_LANE)
|
|
168
|
+
return { kind: 'unbound', role };
|
|
169
|
+
const bound = bindingOf(own(body, 'device'));
|
|
145
170
|
if (bound === null) {
|
|
146
|
-
return { kind: 'unreadable', why: 'the
|
|
171
|
+
return { kind: 'unreadable', why: 'the session is written on the device lane but the execution placement names no readable device (deviceId + rev) — the device is unknown, not unbound' };
|
|
147
172
|
}
|
|
148
|
-
return { kind: 'ok', rootSessionId
|
|
173
|
+
return { kind: 'ok', rootSessionId, boundDevice: bound };
|
|
149
174
|
}
|
|
150
175
|
function rebindFailureOf(e) {
|
|
151
176
|
const v = atMostOnceVerdictOf(e);
|
|
@@ -155,7 +180,11 @@ function rebindFailureOf(e) {
|
|
|
155
180
|
return common;
|
|
156
181
|
if (status === 409 && code === ACTIVE_RUN) {
|
|
157
182
|
const activeTaskId = nonEmpty(own(e, 'activeTaskId'));
|
|
158
|
-
|
|
183
|
+
if (activeTaskId !== undefined)
|
|
184
|
+
return { kind: 'active-run', activeTaskId };
|
|
185
|
+
const children = e !== null && typeof e === 'object' ? readErrorStrictStringList(e, 'children') : undefined;
|
|
186
|
+
const retirePath = e !== null && typeof e === 'object' ? nonEmpty(readErrorString(e, 'retirePath')) : undefined;
|
|
187
|
+
return { kind: 'active-run', ...(children !== undefined && retirePath !== undefined ? { children: Object.freeze([...children]), retirePath } : {}) };
|
|
159
188
|
}
|
|
160
189
|
if (status === 409 && code === REV_CONFLICT) {
|
|
161
190
|
const currentRev = nonNegInt(own(e, 'currentRev'));
|
|
@@ -55,6 +55,7 @@ export interface EngineAgentRegistryRowView {
|
|
|
55
55
|
readonly status: string;
|
|
56
56
|
readonly description?: string;
|
|
57
57
|
readonly createdAt?: number;
|
|
58
|
+
readonly sessionId?: string;
|
|
58
59
|
}
|
|
59
60
|
export type EngineAgentRegistryUnavailableWhy = 'no_list_face' | 'capability_unknown' | 'route_absent' | 'ownership_required' | 'read_failed';
|
|
60
61
|
export type EngineAgentRegistryListing = {
|
|
@@ -59,6 +59,7 @@ export declare function activeRunBusyCarrierOf(ev: unknown): Record<string, unkn
|
|
|
59
59
|
export declare const CORRUPT_SESSION_ERROR_CODE = "corrupt_session";
|
|
60
60
|
export declare const CORRUPT_ROW_ERROR_CODE = "corrupt";
|
|
61
61
|
export declare const MEMORY_CONTROL_PLANE_CORRUPT = "internal.memory_control_plane_corrupt";
|
|
62
|
+
export declare const RESUME_CONSTRAINT_REJECTED = "resume.constraint_rejected";
|
|
62
63
|
export declare function isCorruptSessionCode(code: string | null | undefined): boolean;
|
|
63
64
|
export declare const STOP_PARK_ARBITER_UNREACHABLE = "stop.park_arbiter_unreachable";
|
|
64
65
|
export declare const STOP_PARK_RESUME_WON = "stop.park_resume_won";
|