@sema-agent/client-core 0.109.0 → 0.110.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.
Files changed (123) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/README.md +46 -22
  3. package/dist/adapt/arms.js +20 -7
  4. package/dist/adapter/downstream/eventToSdkMessage.js +11 -6
  5. package/dist/declared/supportFloorDeclared.js +1 -1
  6. package/dist/displayUntrusted.js +132 -14
  7. package/dist/engineErrorCodes.d.ts +3 -0
  8. package/dist/engineErrorCodes.js +3 -0
  9. package/dist/engineHealthFacts.d.ts +9 -0
  10. package/dist/engineHealthFacts.js +21 -1
  11. package/dist/engineInlineTaskStats.d.ts +4 -3
  12. package/dist/engineInlineTaskStats.js +18 -2
  13. package/dist/engineNoticeCodes.d.ts +10 -0
  14. package/dist/engineNoticeCodes.js +33 -1
  15. package/dist/engineRepoint.d.ts +140 -0
  16. package/dist/engineRepoint.js +285 -0
  17. package/dist/engineRowRef.js +2 -0
  18. package/dist/engineSessionMessages.d.ts +2 -1
  19. package/dist/engineSessionMessages.js +5 -0
  20. package/dist/errorSupplementRoles.js +2 -1
  21. package/dist/fleet/fleetProjection.js +3 -2
  22. package/dist/generated/engineFactTables.d.ts +2 -0
  23. package/dist/generated/engineFactTables.js +12 -0
  24. package/dist/generated/sdkFactTables.d.ts +1 -0
  25. package/dist/generated/sdkFactTables.js +4 -0
  26. package/dist/hitl/approvalAskers.d.ts +6 -0
  27. package/dist/hitl/approvalAskers.js +30 -0
  28. package/dist/hitl/approvalCardReasons.js +6 -3
  29. package/dist/hitl/approvalRequestFrameReading.d.ts +7 -0
  30. package/dist/hitl/approvalRequestFrameReading.js +11 -0
  31. package/dist/hitl/approvalResolution.d.ts +8 -1
  32. package/dist/hitl/approvalResolution.js +4 -0
  33. package/dist/hitl/askGateWire.js +0 -2
  34. package/dist/hitl/automaticAnswerVerdict.js +2 -2
  35. package/dist/hitl/decisionConflict.js +6 -3
  36. package/dist/hitl/decisionRefusal.js +1 -0
  37. package/dist/hitl/decisionSend.d.ts +3 -0
  38. package/dist/hitl/decisionSend.js +29 -11
  39. package/dist/hitl/editedApprovalAcceptance.d.ts +25 -0
  40. package/dist/hitl/editedApprovalAcceptance.js +26 -0
  41. package/dist/hitl/frameRouter.js +4 -18
  42. package/dist/hitl/gateLedger.d.ts +0 -4
  43. package/dist/hitl/gateLedger.js +0 -19
  44. package/dist/hitl/hitlBridge.d.ts +1 -0
  45. package/dist/hitl/hitlBridge.js +4 -4
  46. package/dist/hitl/hitlHostSurface.d.ts +1 -0
  47. package/dist/hitl/hitlHostSurface.js +7 -2
  48. package/dist/hitl/hostWithdrawal.d.ts +15 -0
  49. package/dist/hitl/hostWithdrawal.js +38 -0
  50. package/dist/hitl/parkResolver.js +25 -9
  51. package/dist/hitl/persistedRulesWire.js +2 -2
  52. package/dist/hitl/planReviewWire.js +14 -4
  53. package/dist/hitl/sessionPolicyWire.js +6 -4
  54. package/dist/hitl/standingRows.d.ts +1 -0
  55. package/dist/hitl/standingRows.js +15 -1
  56. package/dist/hitl/toolApprovalWire.d.ts +35 -8
  57. package/dist/hitl/toolApprovalWire.js +235 -33
  58. package/dist/hooksWireCaps.js +31 -1
  59. package/dist/hostTurnSettings.d.ts +10 -4
  60. package/dist/hostTurnSettings.js +112 -5
  61. package/dist/i18n/messages.en.d.ts +83 -0
  62. package/dist/i18n/messages.en.js +86 -2
  63. package/dist/i18n/messages.zh.js +96 -2
  64. package/dist/index.d.ts +21 -7
  65. package/dist/index.js +14 -4
  66. package/dist/inheritEnvCapability.js +2 -0
  67. package/dist/inputAuthor.d.ts +16 -0
  68. package/dist/inputAuthor.js +44 -0
  69. package/dist/interruptRefusalNote.d.ts +2 -0
  70. package/dist/interruptRefusalNote.js +17 -0
  71. package/dist/liveModelCatalog.d.ts +2 -0
  72. package/dist/liveModelCatalog.js +21 -7
  73. package/dist/liveQuestionStore.d.ts +4 -1
  74. package/dist/liveQuestionStore.js +12 -3
  75. package/dist/mcpEngineLeg.d.ts +3 -0
  76. package/dist/mcpEngineLeg.js +38 -1
  77. package/dist/mcpPanel.js +2 -0
  78. package/dist/mcpReconnect.d.ts +9 -1
  79. package/dist/mcpReconnect.js +121 -16
  80. package/dist/modelCapabilityProbe.js +4 -3
  81. package/dist/modsFace.d.ts +8 -1
  82. package/dist/modsFace.js +27 -0
  83. package/dist/notifications.d.ts +17 -6
  84. package/dist/notifications.js +67 -19
  85. package/dist/ownKey.d.ts +0 -5
  86. package/dist/ownKey.js +0 -7
  87. package/dist/peerFrames.d.ts +40 -2
  88. package/dist/peerFrames.js +158 -3
  89. package/dist/pluginHooksWire.d.ts +2 -1
  90. package/dist/pluginHooksWire.js +56 -1
  91. package/dist/replayBody.js +10 -2
  92. package/dist/request/taskRequest.d.ts +5 -0
  93. package/dist/request/taskRequest.js +138 -21
  94. package/dist/resumeRefusalCopy.d.ts +1 -3
  95. package/dist/resumeRefusalCopy.js +2 -1
  96. package/dist/retryStatus.d.ts +2 -2
  97. package/dist/retryStatus.js +2 -0
  98. package/dist/seam.d.ts +12 -1
  99. package/dist/seam.js +7 -1
  100. package/dist/seatContract.d.ts +86 -9
  101. package/dist/seatContract.js +196 -7
  102. package/dist/sessionBackground.js +2 -1
  103. package/dist/sessionBackgroundHandoff.js +2 -1
  104. package/dist/sessionEngine.d.ts +2 -0
  105. package/dist/sessionEngine.js +111 -0
  106. package/dist/sessionMemoryStatus.d.ts +2 -1
  107. package/dist/sessionSyncFileHistory.d.ts +4 -0
  108. package/dist/sessionSyncFileHistory.js +28 -0
  109. package/dist/sseIdleTriage.d.ts +13 -1
  110. package/dist/sseIdleTriage.js +24 -6
  111. package/dist/subagent/engineSubagentTail.js +6 -0
  112. package/dist/terminalStatuses.d.ts +1 -0
  113. package/dist/terminalStatuses.js +4 -1
  114. package/dist/turnFailurePresentation.js +9 -2
  115. package/dist/typePins.d.ts +11 -0
  116. package/dist/usageAnalytics.d.ts +17 -0
  117. package/dist/usageAnalytics.js +44 -2
  118. package/dist/wireFailureShape.d.ts +2 -5
  119. package/dist/wireFailureShape.js +10 -20
  120. package/dist/wireRefusalCopy.d.ts +10 -0
  121. package/dist/wireRefusalCopy.js +76 -0
  122. package/docs/INTEGRATION-CLIENTS.md +2126 -20
  123. package/package.json +3 -3
@@ -0,0 +1,140 @@
1
+ import { type DeviceListVerb } from './deviceRebind.js';
2
+ import { type SessionMapStorePort } from './sessionMap.js';
3
+ import { type MessageRef } from './i18n/translate.js';
4
+ declare const HELLO_REJECT_WORDS: readonly ["auth_failed", "revoked", "protocol_version_unsupported", "draining", "already_connected"];
5
+ export type DeviceHelloRejectWord = (typeof HELLO_REJECT_WORDS)[number];
6
+ export type DeviceHelloReading = {
7
+ readonly kind: 'ack';
8
+ } | {
9
+ readonly kind: 'reject';
10
+ readonly code: DeviceHelloRejectWord;
11
+ } | {
12
+ readonly kind: 'unreadable';
13
+ };
14
+ export declare function deviceHelloReadingOf(frame: {} | null | undefined): DeviceHelloReading;
15
+ export interface EngineRepointInput {
16
+ readonly from: string;
17
+ readonly to: string;
18
+ readonly expectDeviceId?: string;
19
+ }
20
+ export interface EngineRepointHandshakeTarget {
21
+ readonly address: string;
22
+ readonly deviceId: string;
23
+ }
24
+ export type EngineRepointHandshakePort = (target: EngineRepointHandshakeTarget, opts?: {
25
+ readonly signal?: AbortSignal;
26
+ }) => Promise<{} | null | undefined> | {} | null | undefined;
27
+ export interface EngineRepointRoster {
28
+ readonly credential: 'operator' | 'non-operator';
29
+ readonly address: string;
30
+ readonly devices: DeviceListVerb | null | undefined;
31
+ }
32
+ export type EngineRepointRecordReading = {
33
+ readonly kind: 'absent';
34
+ } | EngineRepointRecordPresent | {
35
+ readonly kind: 'unreadable';
36
+ };
37
+ export interface EngineRepointRecordPresent {
38
+ readonly kind: 'present';
39
+ readonly status: 'active' | 'enrolling' | 'revoked';
40
+ readonly deviceId?: string;
41
+ }
42
+ export type EngineRepointMoveResult = {
43
+ readonly kind: 'moved';
44
+ } | {
45
+ readonly kind: 'failed';
46
+ };
47
+ export interface EngineRepointRecordPort {
48
+ read(address: string): EngineRepointRecordReading | Promise<EngineRepointRecordReading>;
49
+ move(from: string, to: string): EngineRepointMoveResult | Promise<EngineRepointMoveResult>;
50
+ }
51
+ export interface EngineRepointSessionsPort {
52
+ stores(): readonly SessionMapStorePort[] | Promise<readonly SessionMapStorePort[]>;
53
+ }
54
+ export interface EngineRepointPorts {
55
+ readonly handshake?: EngineRepointHandshakePort;
56
+ readonly roster?: EngineRepointRoster;
57
+ readonly record: EngineRepointRecordPort;
58
+ readonly sessions: EngineRepointSessionsPort;
59
+ readonly signal?: AbortSignal;
60
+ }
61
+ export type EngineRepointProofState = 'proven' | 'unproven' | 'unreadable';
62
+ export type EngineRepointHandshakeProof = {
63
+ readonly state: 'proven';
64
+ } | {
65
+ readonly state: 'unproven';
66
+ readonly why: 'auth_failed' | 'revoked';
67
+ } | {
68
+ readonly state: 'unreadable';
69
+ readonly why: 'draining' | 'already_connected' | 'protocol_version_unsupported' | 'unreadable_frame' | 'transport' | 'unarmed';
70
+ };
71
+ export type EngineRepointRosterProof = {
72
+ readonly state: 'proven';
73
+ } | {
74
+ readonly state: 'unproven';
75
+ readonly why: 'not-listed' | 'lane-absent';
76
+ } | {
77
+ readonly state: 'unreadable';
78
+ readonly why: 'operator-credential' | 'credential-unknown' | 'address-unbound' | 'list-incomplete' | 'refused' | 'transport' | 'unreadable' | 'unarmed';
79
+ };
80
+ export interface EngineRepointProofs {
81
+ readonly handshake: EngineRepointHandshakeProof;
82
+ readonly roster: EngineRepointRosterProof;
83
+ }
84
+ export type EngineRepointVerdict = 'apply' | 'unverified' | 'undetermined';
85
+ export interface EngineRepointExit {
86
+ readonly path: 'reenroll-at-engine-address';
87
+ readonly address: string;
88
+ readonly removeDeviceId: string;
89
+ }
90
+ export interface EngineRepointSessionTally {
91
+ readonly moved: number;
92
+ readonly unaffected: number;
93
+ readonly conflict: number;
94
+ readonly unreadable: number;
95
+ readonly storeFailed: number;
96
+ }
97
+ export type EngineRepointRefusal = 'address-invalid' | 'same-address' | 'record-absent' | 'record-not-active' | 'record-unreadable' | 'target-occupied' | 'unarmed';
98
+ export type EngineRepointResult = EngineRepointDone | EngineRepointPartial | EngineRepointUnverified | EngineRepointUndetermined | EngineRepointStoreFailed | EngineRepointRefused;
99
+ export interface EngineRepointDone {
100
+ readonly kind: 'repointed';
101
+ readonly deviceId: string;
102
+ readonly record: 'moved' | 'already-there';
103
+ readonly sessions: EngineRepointSessionTally;
104
+ readonly proofs: EngineRepointProofs;
105
+ }
106
+ export interface EngineRepointPartial {
107
+ readonly kind: 'partial';
108
+ readonly stage: 'sessions' | 'sessions-list';
109
+ readonly deviceId: string;
110
+ readonly record: 'moved' | 'already-there';
111
+ readonly sessions: EngineRepointSessionTally;
112
+ readonly proofs: EngineRepointProofs;
113
+ }
114
+ export interface EngineRepointUnverified {
115
+ readonly kind: 'unverified';
116
+ readonly deviceId: string;
117
+ readonly proofs: EngineRepointProofs;
118
+ readonly exit: EngineRepointExit;
119
+ }
120
+ export interface EngineRepointUndetermined {
121
+ readonly kind: 'undetermined';
122
+ readonly deviceId: string;
123
+ readonly proofs: EngineRepointProofs;
124
+ readonly exit: EngineRepointExit;
125
+ readonly retryable: true;
126
+ }
127
+ export interface EngineRepointStoreFailed {
128
+ readonly kind: 'store-failed';
129
+ readonly stage: 'record';
130
+ readonly deviceId: string;
131
+ }
132
+ export interface EngineRepointRefused {
133
+ readonly kind: 'refused';
134
+ readonly reason: EngineRepointRefusal;
135
+ readonly recordStatus?: 'enrolling' | 'revoked';
136
+ }
137
+ export declare function engineRepointVerdictOf(proofs: {} | null | undefined): EngineRepointVerdict;
138
+ export declare function repointEngine(input: EngineRepointInput, ports: EngineRepointPorts): Promise<EngineRepointResult>;
139
+ export declare function engineRepointMessageOf(result: {} | null | undefined): MessageRef | undefined;
140
+ export {};
@@ -0,0 +1,285 @@
1
+ import { listDevices } from './deviceRebind.js';
2
+ import { engineUrlTransportVerdict, normalizeEngineBaseUrl } from './engineUrl.js';
3
+ import { engineNamespaceKeyFor } from './sessionMap.js';
4
+ import { repointSessionEngine } from './sessionEngine.js';
5
+ import { slotReadOf } from './wireFailureShape.js';
6
+ import { msg } from './i18n/translate.js';
7
+ const HELLO_REJECT_WORDS = Object.freeze(['auth_failed', 'revoked', 'protocol_version_unsupported', 'draining', 'already_connected']);
8
+ const HELLO_ACK = Object.freeze({ kind: 'ack' });
9
+ const HELLO_UNREADABLE = Object.freeze({ kind: 'unreadable' });
10
+ function dataOf(o, key) {
11
+ if (o === null || typeof o !== 'object')
12
+ return undefined;
13
+ const s = slotReadOf(o, key);
14
+ return s.presence === 'present' ? s.value : undefined;
15
+ }
16
+ const isObject = (v) => v !== null && typeof v === 'object';
17
+ export function deviceHelloReadingOf(frame) {
18
+ const t = dataOf(frame, 't');
19
+ if (t === 'helloAck')
20
+ return dataOf(frame, 'ok') === true ? HELLO_ACK : HELLO_UNREADABLE;
21
+ if (t === 'helloReject') {
22
+ const code = dataOf(frame, 'code');
23
+ const word = HELLO_REJECT_WORDS.find((w) => w === code);
24
+ return word === undefined ? HELLO_UNREADABLE : Object.freeze({ kind: 'reject', code: word });
25
+ }
26
+ return HELLO_UNREADABLE;
27
+ }
28
+ const freeze = (v) => Object.freeze(v);
29
+ function methodOf(o, key) {
30
+ if (!isObject(o))
31
+ return undefined;
32
+ try {
33
+ const v = o[key];
34
+ return typeof v === 'function' ? v : undefined;
35
+ }
36
+ catch {
37
+ return undefined;
38
+ }
39
+ }
40
+ const HS_PROVEN = freeze({ state: 'proven' });
41
+ async function handshakeProofOf(port, target, signal) {
42
+ if (typeof port !== 'function')
43
+ return freeze({ state: 'unreadable', why: 'unarmed' });
44
+ let frame;
45
+ try {
46
+ frame = await port(target, signal !== undefined ? { signal } : undefined);
47
+ }
48
+ catch {
49
+ return freeze({ state: 'unreadable', why: 'transport' });
50
+ }
51
+ const r = deviceHelloReadingOf(frame);
52
+ if (r.kind === 'ack')
53
+ return HS_PROVEN;
54
+ if (r.kind === 'unreadable')
55
+ return freeze({ state: 'unreadable', why: 'unreadable_frame' });
56
+ if (r.code === 'auth_failed' || r.code === 'revoked')
57
+ return freeze({ state: 'unproven', why: r.code });
58
+ return freeze({ state: 'unreadable', why: r.code });
59
+ }
60
+ const RO_PROVEN = freeze({ state: 'proven' });
61
+ async function rosterProofOf(roster, target, deviceId, signal) {
62
+ if (!isObject(roster))
63
+ return freeze({ state: 'unreadable', why: 'unarmed' });
64
+ const credential = dataOf(roster, 'credential');
65
+ if (credential === 'operator')
66
+ return freeze({ state: 'unreadable', why: 'operator-credential' });
67
+ if (credential !== 'non-operator')
68
+ return freeze({ state: 'unreadable', why: 'credential-unknown' });
69
+ const listed = addressOf(dataOf(roster, 'address'), false);
70
+ if (listed === undefined || engineNamespaceKeyFor(listed) !== engineNamespaceKeyFor(target))
71
+ return freeze({ state: 'unreadable', why: 'address-unbound' });
72
+ const devices = dataOf(roster, 'devices');
73
+ const out = await listDevices(devices, signal !== undefined ? { signal } : undefined);
74
+ switch (out.kind) {
75
+ case 'ok':
76
+ if (out.devices.some((d) => d.deviceId === deviceId))
77
+ return RO_PROVEN;
78
+ return out.dropped > 0
79
+ ? freeze({ state: 'unreadable', why: 'list-incomplete' })
80
+ : freeze({ state: 'unproven', why: 'not-listed' });
81
+ case 'lane-absent':
82
+ return freeze({ state: 'unproven', why: 'lane-absent' });
83
+ case 'refused':
84
+ return freeze({ state: 'unreadable', why: 'refused' });
85
+ case 'transport':
86
+ return freeze({ state: 'unreadable', why: 'transport' });
87
+ case 'unarmed':
88
+ return freeze({ state: 'unreadable', why: 'unarmed' });
89
+ default:
90
+ return freeze({ state: 'unreadable', why: 'unreadable' });
91
+ }
92
+ }
93
+ function proofStateOf(proofs, key) {
94
+ const state = dataOf(dataOf(proofs, key), 'state');
95
+ return state === 'proven' || state === 'unproven' ? state : 'unreadable';
96
+ }
97
+ export function engineRepointVerdictOf(proofs) {
98
+ const a = proofStateOf(proofs, 'handshake');
99
+ const b = proofStateOf(proofs, 'roster');
100
+ if (a === 'unreadable' || b === 'unreadable')
101
+ return 'undetermined';
102
+ return a === 'unproven' || b === 'unproven' ? 'unverified' : 'apply';
103
+ }
104
+ const UNREADABLE_RECORD = freeze({ k: 'unreadable' });
105
+ async function recordFactOf(read, port, address) {
106
+ let raw;
107
+ try {
108
+ raw = await read.call(port, address);
109
+ }
110
+ catch {
111
+ return UNREADABLE_RECORD;
112
+ }
113
+ const kind = dataOf(raw, 'kind');
114
+ if (kind === 'absent')
115
+ return freeze({ k: 'absent' });
116
+ if (kind !== 'present')
117
+ return UNREADABLE_RECORD;
118
+ const status = dataOf(raw, 'status');
119
+ if (status === 'enrolling' || status === 'revoked')
120
+ return freeze({ k: 'other', status });
121
+ if (status !== 'active')
122
+ return UNREADABLE_RECORD;
123
+ const deviceId = dataOf(raw, 'deviceId');
124
+ return typeof deviceId === 'string' && deviceId !== '' ? freeze({ k: 'active', deviceId }) : UNREADABLE_RECORD;
125
+ }
126
+ function planOf(from, to, expectDeviceId) {
127
+ if (from.k === 'unreadable' || to.k === 'unreadable')
128
+ return { kind: 'refused', reason: 'record-unreadable' };
129
+ if (from.k === 'other')
130
+ return { kind: 'refused', reason: 'record-not-active', recordStatus: from.status };
131
+ if (from.k === 'active') {
132
+ if (to.k === 'absent')
133
+ return { kind: 'move', deviceId: from.deviceId };
134
+ if (to.k === 'active' && to.deviceId === from.deviceId)
135
+ return { kind: 'move', deviceId: from.deviceId };
136
+ return { kind: 'refused', reason: 'target-occupied' };
137
+ }
138
+ if (to.k === 'active')
139
+ return expectDeviceId !== undefined && to.deviceId === expectDeviceId ? { kind: 'finish', deviceId: to.deviceId } : { kind: 'refused', reason: 'record-absent' };
140
+ if (to.k === 'other')
141
+ return { kind: 'refused', reason: 'record-not-active', recordStatus: to.status };
142
+ return { kind: 'refused', reason: 'record-absent' };
143
+ }
144
+ const refusedOf = (reason, recordStatus) => freeze(recordStatus === undefined ? { kind: 'refused', reason } : { kind: 'refused', reason, recordStatus });
145
+ function addressOf(raw, forTarget) {
146
+ const n = normalizeEngineBaseUrl(typeof raw === 'string' ? raw : undefined);
147
+ if (!n.ok)
148
+ return undefined;
149
+ if (forTarget && !engineUrlTransportVerdict(n.url).ok)
150
+ return undefined;
151
+ return n.url;
152
+ }
153
+ function tallyOf(c) {
154
+ return freeze({ moved: c.moved, unaffected: c.unaffected, conflict: c.conflict, unreadable: c.unreadable, storeFailed: c.storeFailed });
155
+ }
156
+ function storeListOf(list) {
157
+ try {
158
+ if (!Array.isArray(list))
159
+ return undefined;
160
+ }
161
+ catch {
162
+ return undefined;
163
+ }
164
+ const len = dataOf(list, 'length');
165
+ if (typeof len !== 'number' || !Number.isSafeInteger(len) || len < 0)
166
+ return undefined;
167
+ const out = [];
168
+ for (let i = 0; i < len; i += 1)
169
+ out.push(dataOf(list, String(i)));
170
+ return out;
171
+ }
172
+ export async function repointEngine(input, ports) {
173
+ try {
174
+ const from = addressOf(dataOf(input, 'from'), false);
175
+ const to = addressOf(dataOf(input, 'to'), true);
176
+ if (from === undefined || to === undefined)
177
+ return refusedOf('address-invalid');
178
+ if (engineNamespaceKeyFor(from) === engineNamespaceKeyFor(to))
179
+ return refusedOf('same-address');
180
+ const recordPort = dataOf(ports, 'record');
181
+ const sessionsPort = dataOf(ports, 'sessions');
182
+ const read = methodOf(recordPort, 'read');
183
+ const move = methodOf(recordPort, 'move');
184
+ const listStores = methodOf(sessionsPort, 'stores');
185
+ if (read === undefined || move === undefined || listStores === undefined)
186
+ return refusedOf('unarmed');
187
+ const handshake = dataOf(ports, 'handshake');
188
+ const roster = dataOf(ports, 'roster');
189
+ const signalRaw = dataOf(ports, 'signal');
190
+ const signal = isObject(signalRaw) ? signalRaw : undefined;
191
+ const expectRaw = dataOf(input, 'expectDeviceId');
192
+ const expectDeviceId = typeof expectRaw === 'string' && expectRaw !== '' ? expectRaw : undefined;
193
+ const [fromFact, toFact] = await Promise.all([recordFactOf(read, recordPort, from), recordFactOf(read, recordPort, to)]);
194
+ const plan = planOf(fromFact, toFact, expectDeviceId);
195
+ if (plan.kind === 'refused')
196
+ return refusedOf(plan.reason, plan.recordStatus);
197
+ const deviceId = plan.deviceId;
198
+ const [hs, ro] = await Promise.all([handshakeProofOf(handshake, freeze({ address: to, deviceId }), signal), rosterProofOf(roster, to, deviceId, signal)]);
199
+ const proofs = freeze({ handshake: hs, roster: ro });
200
+ const verdict = engineRepointVerdictOf(proofs);
201
+ if (verdict !== 'apply') {
202
+ const exit = freeze({ path: 'reenroll-at-engine-address', address: to, removeDeviceId: deviceId });
203
+ return verdict === 'unverified'
204
+ ? freeze({ kind: 'unverified', deviceId, proofs, exit })
205
+ : freeze({ kind: 'undetermined', deviceId, proofs, exit, retryable: true });
206
+ }
207
+ if (plan.kind === 'move') {
208
+ let moved = false;
209
+ try {
210
+ moved = dataOf(await move.call(recordPort, from, to), 'kind') === 'moved';
211
+ }
212
+ catch {
213
+ moved = false;
214
+ }
215
+ if (moved) {
216
+ const [afterFrom, afterTo] = await Promise.all([recordFactOf(read, recordPort, from), recordFactOf(read, recordPort, to)]);
217
+ moved = afterFrom.k === 'absent' && afterTo.k === 'active' && afterTo.deviceId === deviceId;
218
+ }
219
+ if (!moved)
220
+ return freeze({ kind: 'store-failed', stage: 'record', deviceId });
221
+ }
222
+ const record = plan.kind === 'move' ? 'moved' : 'already-there';
223
+ const counts = { moved: 0, unaffected: 0, conflict: 0, unreadable: 0, storeFailed: 0 };
224
+ let stores;
225
+ try {
226
+ stores = storeListOf(await listStores.call(sessionsPort));
227
+ }
228
+ catch {
229
+ stores = undefined;
230
+ }
231
+ if (stores === undefined)
232
+ return freeze({ kind: 'partial', stage: 'sessions-list', deviceId, record, sessions: tallyOf(counts), proofs });
233
+ for (const store of stores) {
234
+ const r = repointSessionEngine(store, from, to);
235
+ if (r === 'moved')
236
+ counts.moved += 1;
237
+ else if (r === 'unaffected')
238
+ counts.unaffected += 1;
239
+ else if (r === 'conflict')
240
+ counts.conflict += 1;
241
+ else if (r === 'store-failed')
242
+ counts.storeFailed += 1;
243
+ else
244
+ counts.unreadable += 1;
245
+ }
246
+ const sessions = tallyOf(counts);
247
+ return counts.conflict + counts.unreadable + counts.storeFailed > 0
248
+ ? freeze({ kind: 'partial', stage: 'sessions', deviceId, record, sessions, proofs })
249
+ : freeze({ kind: 'repointed', deviceId, record, sessions, proofs });
250
+ }
251
+ catch {
252
+ return refusedOf('unarmed');
253
+ }
254
+ }
255
+ const REFUSAL_KEYS = {
256
+ 'address-invalid': 'session.devices.repoint.refused.addressInvalid',
257
+ 'same-address': 'session.devices.repoint.refused.sameAddress',
258
+ 'record-absent': 'session.devices.repoint.refused.recordAbsent',
259
+ 'record-not-active': 'session.devices.repoint.refused.recordNotActive',
260
+ 'record-unreadable': 'session.devices.repoint.refused.recordUnreadable',
261
+ 'target-occupied': 'session.devices.repoint.refused.targetOccupied',
262
+ unarmed: 'session.devices.repoint.refused.unarmed',
263
+ };
264
+ export function engineRepointMessageOf(result) {
265
+ const kind = dataOf(result, 'kind');
266
+ switch (kind) {
267
+ case 'repointed':
268
+ return msg('session.devices.repoint.done');
269
+ case 'partial':
270
+ return msg('session.devices.repoint.partial');
271
+ case 'unverified':
272
+ return msg('session.devices.repoint.unverified');
273
+ case 'undetermined':
274
+ return msg('session.devices.repoint.undetermined');
275
+ case 'store-failed':
276
+ return msg('session.devices.repoint.storeFailed');
277
+ case 'refused': {
278
+ const reason = dataOf(result, 'reason');
279
+ const word = Object.keys(REFUSAL_KEYS).find((w) => w === reason);
280
+ return word === undefined ? undefined : msg(REFUSAL_KEYS[word]);
281
+ }
282
+ default:
283
+ return undefined;
284
+ }
285
+ }
@@ -102,6 +102,8 @@ export const TRANSCRIPT_ROW_SIDECAR_KEYS = Object.freeze([
102
102
  '_sema_task_notification',
103
103
  '_sema_answered_by',
104
104
  '_sema_rewrite',
105
+ '_sema_run_origin',
106
+ '_sema_run_origin_unreadable',
105
107
  ]);
106
108
  export function parkHeldCallIdOf(carrier) {
107
109
  return readFrameStringKey(carrier, 'toolCallId');
@@ -1,3 +1,4 @@
1
+ import { type RunOriginRowKeys } from './inputAuthor.js';
1
2
  export type EngineHistoryJson = string | number | boolean | null | readonly EngineHistoryJson[] | {
2
3
  readonly [key: string]: EngineHistoryJson;
3
4
  };
@@ -44,7 +45,7 @@ export interface EngineHistoryMessageBody {
44
45
  readonly content: string | readonly EngineHistoryBlock[];
45
46
  readonly model?: string;
46
47
  }
47
- export interface EngineHistoryMessage {
48
+ export interface EngineHistoryMessage extends RunOriginRowKeys {
48
49
  readonly type: 'user' | 'assistant';
49
50
  readonly uuid: string;
50
51
  readonly session_id: string;
@@ -1,4 +1,5 @@
1
1
  import { isGateParkedToolEnd } from './gateOutcome.js';
2
+ import { runOriginRowKeys } from './inputAuthor.js';
2
3
  import { appendOwnElement, ownDataField, ownSendableField } from './ownKey.js';
3
4
  const isObjectLike = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
4
5
  function optionalOwn(o, key) {
@@ -344,14 +345,17 @@ export function projectEngineSessionMessages(rows, opts) {
344
345
  for (let i = 0; i < count; i += 1) {
345
346
  let outcome;
346
347
  let timestamp;
348
+ let originRow;
347
349
  try {
348
350
  const row = ownDataField(rows, String(i));
349
351
  outcome = projectRow(row, tally);
350
352
  timestamp = outcome.kind === 'message' && isObjectLike(row) ? timestampOf(row) : undefined;
353
+ originRow = outcome.kind === 'message' && isObjectLike(row) && ownDataField(row, 'role') === 'user' ? row : undefined;
351
354
  }
352
355
  catch {
353
356
  outcome = unreadable();
354
357
  timestamp = undefined;
358
+ originRow = undefined;
355
359
  }
356
360
  if (outcome.kind === 'skip') {
357
361
  tally[outcome.why] += 1;
@@ -362,6 +366,7 @@ export function projectEngineSessionMessages(rows, opts) {
362
366
  uuid: `restored-${sessionId}-${messages.length + 1}`,
363
367
  session_id: sessionId,
364
368
  ...(timestamp !== undefined ? { timestamp } : {}),
369
+ ...(originRow !== undefined ? runOriginRowKeys(originRow) : {}),
365
370
  message: outcome.body,
366
371
  parent_tool_use_id: null,
367
372
  });
@@ -5,7 +5,7 @@ import { resumeReopenContent } from './hitl/suspendedReopen.js';
5
5
  import { idempotencyPayloadMismatchContent } from './engineErrorCodes.js';
6
6
  import { inheritEnvRefusalContent } from './inheritEnvWire.js';
7
7
  import { projectSeedRefusalContent } from './projectSeed.js';
8
- import { usageWindowExhaustedContent, fleetLeaseUnavailableContent, settingsPermissionBucketRefusalContent, fieldLimitRefusalContent, autonomyLaneRefusalContent, sessionArchiveStampedContent, unsupportedRuleRefusalContent, admissionWallRefusalContent, hostPostureRefusalContent, toolDeclarationRefusalContent, envCredentialRefusalContent, sessionIdRetiredContent, runConcurrencyCapContent, } from './wireRefusalCopy.js';
8
+ import { usageWindowExhaustedContent, fleetLeaseUnavailableContent, settingsPermissionBucketRefusalContent, fieldLimitRefusalContent, autonomyLaneRefusalContent, sessionArchiveStampedContent, unsupportedRuleRefusalContent, admissionWallRefusalContent, hostPostureRefusalContent, toolDeclarationRefusalContent, envCredentialRefusalContent, sessionIdRetiredContent, runConcurrencyCapContent, unreadRequestMembersContent, } from './wireRefusalCopy.js';
9
9
  import { catalogDefaultRefusalContent } from './model/catalogDefault.js';
10
10
  const ROLE_BY_READER = new Map([
11
11
  [corruptSessionContent, 'replacement'],
@@ -28,6 +28,7 @@ const ROLE_BY_READER = new Map([
28
28
  [envCredentialRefusalContent, 'replacement'],
29
29
  [sessionIdRetiredContent, 'replacement'],
30
30
  [runConcurrencyCapContent, 'replacement'],
31
+ [unreadRequestMembersContent, 'replacement'],
31
32
  [admissionWallRefusalContent, 'supplement'],
32
33
  [hostPostureRefusalContent, 'supplement'],
33
34
  [toolDeclarationRefusalContent, 'supplement'],
@@ -3,7 +3,8 @@ import { rowIdTail } from '../workflow.js';
3
3
  import { cycleSeqValue } from '../cycleOrder.js';
4
4
  import { frozenSet } from '../frozenSet.js';
5
5
  import { guardedRead, readOwnDataValue } from '../ownKey.js';
6
- import { CORE_RESERVED_AGENT_NAMES, CORE_WORKFLOW_AGENT_PARKED_ERROR_CODE } from '../generated/engineFactTables.js';
6
+ import { CORE_RESERVED_AGENT_NAMES } from '../generated/engineFactTables.js';
7
+ import { isCoreWorkflowRunParkedEnd } from '../terminalStatuses.js';
7
8
  import { runParkedOf as coreRunParkedOf } from '../coreValuePorts.js';
8
9
  export function coerceTaskStatus(s) {
9
10
  if (s === 'parked')
@@ -34,7 +35,7 @@ export function workflowRunDisplayStatusOf(run) {
34
35
  const status = runField(run, 'status');
35
36
  if (parkedWindowOf(run, status))
36
37
  return 'awaiting approval';
37
- if (status === 'failed' && runField(run, 'errorCode') === CORE_WORKFLOW_AGENT_PARKED_ERROR_CODE)
38
+ if (isCoreWorkflowRunParkedEnd(status, runField(run, 'errorCode')))
38
39
  return 'awaiting approval';
39
40
  switch (status) {
40
41
  case 'completed':
@@ -75,3 +75,5 @@ export declare const CORE_PRESENT_PLAN_TOOL_NAME: "ExitPlanMode";
75
75
  export declare const CORE_WORKFLOW_AGENT_PARKED_ERROR_CODE: "workflow.agent_parked";
76
76
  export declare const CORE_REFUSAL_ECHO_KINDS: readonly ["path", "command", "pattern"];
77
77
  export declare const CORE_DISCARDED_DELIVERY_PATHS: readonly ["live", "box", "drain", "notice"];
78
+ export declare const CORE_INPUT_AUTHORS: readonly ["operator", "parent_model", "workflow", "peer", "observer", "engine", "extension"];
79
+ export declare const CORE_RUN_ORIGINS: readonly ["scheduled"];
@@ -477,3 +477,15 @@ export const CORE_DISCARDED_DELIVERY_PATHS = Object.freeze([
477
477
  "drain",
478
478
  "notice",
479
479
  ]);
480
+ export const CORE_INPUT_AUTHORS = Object.freeze([
481
+ "operator",
482
+ "parent_model",
483
+ "workflow",
484
+ "peer",
485
+ "observer",
486
+ "engine",
487
+ "extension",
488
+ ]);
489
+ export const CORE_RUN_ORIGINS = Object.freeze([
490
+ "scheduled",
491
+ ]);
@@ -10,3 +10,4 @@ export declare const SDK_PERMISSION_MODE_PERSIST_MISSES: readonly ["claim_releas
10
10
  export declare const SDK_DECIDE_BINDING_KEYS: readonly ["boundCallId", "boundInputHash"];
11
11
  export declare const SDK_APPROVAL_QUEUE_KINDS: readonly ["checkpoint", "peer_inbound"];
12
12
  export declare const SDK_SESSION_MEMORY_UNOBSERVED_REASONS: readonly ["no_settled_run", "run_result_missing", "run_result_unobserved", "memory_not_mounted", "no_leaf"];
13
+ export declare const SDK_STREAM_ENDED_REASONS: readonly ["empty_legs", "consecutive_failures"];
@@ -63,3 +63,7 @@ export const SDK_SESSION_MEMORY_UNOBSERVED_REASONS = Object.freeze([
63
63
  "memory_not_mounted",
64
64
  "no_leaf",
65
65
  ]);
66
+ export const SDK_STREAM_ENDED_REASONS = Object.freeze([
67
+ "empty_legs",
68
+ "consecutive_failures",
69
+ ]);
@@ -9,5 +9,11 @@ export interface ApprovalAskReasonByPolicy {
9
9
  readonly words: string;
10
10
  }
11
11
  export type ApprovalAskReason = ApprovalAskReasonByHook | ApprovalAskReasonByPolicy;
12
+ export interface ApprovalRequestedBy {
13
+ readonly kind: 'extension';
14
+ readonly name: string;
15
+ }
12
16
  export declare function approvalAskReasonsOf(carrier: object | null | undefined): readonly ApprovalAskReason[] | undefined;
17
+ export declare function requestedByViewOf(v: object | null | undefined): ApprovalRequestedBy | undefined;
18
+ export declare function approvalRequestedByOf(carrier: object | null | undefined): ApprovalRequestedBy | undefined;
13
19
  export declare function approvalAgentIdOf(carrier: object | null | undefined): string | undefined;
@@ -67,6 +67,36 @@ export function approvalAskReasonsOf(carrier) {
67
67
  return undefined;
68
68
  }
69
69
  }
70
+ export function requestedByViewOf(v) {
71
+ try {
72
+ if (typeof v !== 'object' || v === null || Array.isArray(v))
73
+ return undefined;
74
+ const kind = slotReadOf(v, 'kind');
75
+ if (kind.presence !== 'present' || kind.value !== 'extension')
76
+ return undefined;
77
+ const name = ownNonEmptyText(v, 'name');
78
+ if (name === undefined)
79
+ return undefined;
80
+ return Object.freeze({ kind: 'extension', name });
81
+ }
82
+ catch {
83
+ return undefined;
84
+ }
85
+ }
86
+ export function approvalRequestedByOf(carrier) {
87
+ try {
88
+ if (typeof carrier !== 'object' || carrier === null)
89
+ return undefined;
90
+ const slot = slotReadOf(carrier, 'requestedBy');
91
+ if (slot.presence !== 'present')
92
+ return undefined;
93
+ const v = slot.value;
94
+ return typeof v === 'object' && v !== null ? requestedByViewOf(v) : undefined;
95
+ }
96
+ catch {
97
+ return undefined;
98
+ }
99
+ }
70
100
  export function approvalAgentIdOf(carrier) {
71
101
  try {
72
102
  if (typeof carrier !== 'object' || carrier === null)
@@ -4,7 +4,7 @@ import { approvalMandateDetail, askOriginNoteOf } from '../gateVocabulary.js';
4
4
  import { readAskOrigin, readOwnDataValue, guardedRead } from '../ownKey.js';
5
5
  import { elideMiddleForDisplay } from '../noticePresentation.js';
6
6
  import { allowRuleShadowSentence } from './allowRuleShadow.js';
7
- import { approvalUnreadableWhyWordOf } from './approvalRequestFrameReading.js';
7
+ import { cardPayloadReadingOf } from './approvalRequestFrameReading.js';
8
8
  import { mandatedApprovalDetailOf } from './automaticAnswerVerdict.js';
9
9
  import { approvalBoundGrantsDetail, approvalIsMandated, approvalPriorCardsDetail, askProbeReasonDetail, classifierNoRulingDetail, readApprovalBoundGrants, readApprovalClassifierNoRuling, readApprovalMandate, readDenialLimitFallback, } from './toolApprovalWire.js';
10
10
  export const APPROVAL_CARD_REASON_SOURCES = Object.freeze([
@@ -31,7 +31,7 @@ function engineMessageLine(engineMessage) {
31
31
  return settled.length <= MESSAGE_DISPLAY_MAX ? settled : displayUntrusted(engineMessage, { max: MESSAGE_DISPLAY_MAX });
32
32
  }
33
33
  function payloadUnreadableDetail(why, lang) {
34
- switch (typeof why === 'string' ? approvalUnreadableWhyWordOf(why) : undefined) {
34
+ switch (why) {
35
35
  case 'version_unknown':
36
36
  return renderMessage(msg('approval.card.payloadUnreadable.versionUnknown'), lang);
37
37
  case 'kind_unknown':
@@ -82,7 +82,10 @@ export function approvalCardReasons(card, opts, lang) {
82
82
  catch {
83
83
  denialLimitReadable = false;
84
84
  }
85
- add('payload_unreadable', () => (ownData(card, 'cardPayloadUnreadable') === true ? payloadUnreadableDetail(ownData(card, 'cardPayloadUnreadableWhy'), lang) : undefined));
85
+ add('payload_unreadable', () => {
86
+ const reading = cardPayloadReadingOf(card);
87
+ return reading.payloadUnreadable ? payloadUnreadableDetail(reading.why, lang) : undefined;
88
+ });
86
89
  add('prior_cards', () => approvalPriorCardsDetail(card, lang));
87
90
  add('message', () => {
88
91
  const engineMessage = ownData(card, 'message');
@@ -11,4 +11,11 @@ export type ApprovalRequestFrameReading = {
11
11
  export declare function approvalRequestFrameReadingThrowing(frame: object | null | undefined): ApprovalRequestFrameReading;
12
12
  export declare function approvalRequestFrameReadingOf(frame: object | null | undefined): ApprovalRequestFrameReading;
13
13
  export declare function approvalUnreadableWhyWordOf(v: string): ApprovalRequestFrameUnreadableWhy | undefined;
14
+ export type CardPayloadReading = {
15
+ readonly payloadUnreadable: false;
16
+ } | {
17
+ readonly payloadUnreadable: true;
18
+ readonly why?: ApprovalRequestFrameUnreadableWhy;
19
+ };
20
+ export declare function cardPayloadReadingOf(card: object | null | undefined): CardPayloadReading;
14
21
  export declare function approvalFrameUnreadableWhyOf(reading: ApprovalRequestFrameReading | null | undefined): ApprovalRequestFrameUnreadableWhy | undefined;