@sema-agent/client-core 0.84.0 → 0.85.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 +247 -0
- package/README.md +27 -13
- package/dist/abortableSleep.d.ts +10 -0
- package/dist/abortableSleep.js +37 -0
- package/dist/adapt/arms.js +1 -1
- package/dist/adapt.d.ts +1 -1
- package/dist/adapt.js +1 -1
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +1 -0
- package/dist/adapter/downstream/terminalToSdkResult.js +19 -10
- package/dist/adapter/runStream.js +6 -2
- package/dist/agentSession/engineSessionBackgroundStop.d.ts +50 -0
- package/dist/agentSession/engineSessionBackgroundStop.js +291 -0
- package/dist/agentsWireCaps.d.ts +2 -1
- package/dist/agentsWireCaps.js +8 -0
- package/dist/cloudConfigWireCaps.js +2 -1
- package/dist/corruptSession.d.ts +3 -0
- package/dist/corruptSession.js +29 -0
- package/dist/corruptSessionCopy.d.ts +1 -0
- package/dist/corruptSessionCopy.js +4 -0
- package/dist/decideFailureNote.d.ts +2 -1
- package/dist/decideFailureNote.js +8 -3
- package/dist/decideReceipt.d.ts +6 -0
- package/dist/decideReceipt.js +30 -1
- package/dist/detachWire.d.ts +1 -0
- package/dist/detachWire.js +13 -5
- package/dist/displayUntrusted.js +114 -18
- package/dist/effortWire.d.ts +2 -1
- package/dist/effortWire.js +2 -4
- package/dist/engineErrorCodes.d.ts +11 -0
- package/dist/engineErrorCodes.js +32 -0
- package/dist/engineNoticeCodes.d.ts +39 -4
- package/dist/engineNoticeCodes.js +117 -161
- package/dist/engineWireFor.d.ts +43 -0
- package/dist/engineWireFor.js +399 -0
- package/dist/engineWireSdk.d.ts +6 -0
- package/dist/fileHistoryCaptureCapability.d.ts +4 -1
- package/dist/fileHistoryCaptureCapability.js +43 -9
- package/dist/gateVocabulary.d.ts +1 -2
- package/dist/gateVocabulary.js +1 -22
- package/dist/generated/engineNoticeTables.d.ts +3 -0
- package/dist/generated/engineNoticeTables.js +156 -0
- package/dist/generated/toolNameTables.d.ts +2 -0
- package/dist/generated/toolNameTables.js +43 -0
- package/dist/headlessPermissionModeWire.js +2 -4
- package/dist/hitl/askGateWire.d.ts +1 -1
- package/dist/hitl/askGateWire.js +1 -1
- package/dist/hitl/frameRouter.js +4 -2
- package/dist/hitl/hitlHostSurface.js +1 -1
- package/dist/hitl/parkResolver.d.ts +1 -0
- package/dist/hitl/parkResolver.js +11 -3
- package/dist/hitl/planReviewWire.d.ts +41 -3
- package/dist/hitl/planReviewWire.js +264 -49
- package/dist/hitl/rosterMountedNames.d.ts +2 -0
- package/dist/hitl/rosterMountedNames.js +38 -0
- package/dist/hitl/sessionPolicyDeliverable.d.ts +8 -2
- package/dist/hitl/sessionPolicyDeliverable.js +39 -48
- package/dist/hitl/sessionPolicyWire.d.ts +40 -0
- package/dist/hitl/sessionPolicyWire.js +173 -0
- package/dist/hitl/toolApprovalWire.d.ts +4 -2
- package/dist/hitl/toolApprovalWire.js +6 -4
- package/dist/index.d.ts +10 -3
- package/dist/index.js +7 -2
- package/dist/liveInitToolFace.js +28 -10
- package/dist/permissionWireCaps.d.ts +2 -1
- package/dist/permissionWireCaps.js +2 -7
- package/dist/request/taskRequest.d.ts +2 -0
- package/dist/request/taskRequest.js +18 -1
- package/dist/resumeRefusalCopy.d.ts +11 -0
- package/dist/resumeRefusalCopy.js +42 -2
- package/dist/runTerminal.js +4 -0
- package/dist/sandboxWire.js +1 -1
- package/dist/sealedKeyCapability.d.ts +17 -0
- package/dist/sealedKeyCapability.js +42 -0
- package/dist/seatContract.d.ts +2 -1
- package/dist/seatContract.js +5 -21
- package/dist/subagent/engineCompactWire.d.ts +13 -2
- package/dist/subagent/engineCompactWire.js +48 -37
- package/dist/subagent/engineDelegatedPrompt.d.ts +9 -1
- package/dist/subagent/engineDelegatedPrompt.js +16 -16
- package/dist/subagent/engineRowStopGate.d.ts +2 -2
- package/dist/subagent/engineRowStopGate.js +4 -4
- package/dist/subagent/engineSubagentOutput.d.ts +8 -0
- package/dist/subagent/engineSubagentOutput.js +37 -18
- package/dist/subagent/engineSubagentResume.d.ts +11 -2
- package/dist/subagent/engineSubagentResume.js +28 -14
- package/dist/subagent/engineSubagentSteer.d.ts +10 -1
- package/dist/subagent/engineSubagentSteer.js +16 -11
- package/dist/subagent/engineSubagentTail.d.ts +10 -1
- package/dist/subagent/engineSubagentTail.js +35 -17
- package/dist/subagent/engineTaskHandleWire.d.ts +13 -0
- package/dist/subagent/engineTaskHandleWire.js +41 -20
- package/dist/systemReminderTag.d.ts +5 -0
- package/dist/systemReminderTag.js +20 -9
- package/dist/taskRequestWords.d.ts +5 -0
- package/dist/taskRequestWords.js +4 -0
- package/dist/wireErrorTriage.d.ts +1 -0
- package/dist/wireErrorTriage.js +3 -1
- package/dist/wireRefusalCopy.d.ts +10 -0
- package/dist/wireRefusalCopy.js +62 -2
- package/docs/INTEGRATION-CLIENTS.md +1128 -22
- package/package.json +1 -1
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { settleWithinDeadline } from './abortableSleep.js';
|
|
2
|
+
import { makeEngineWireClient } from './engineWireSdk.js';
|
|
3
|
+
import { engineWireTargetFor } from './engineWireTarget.js';
|
|
4
|
+
export const INJECTED_WIRE_SETTLE_MS = 60_000;
|
|
5
|
+
export function engineWireFor(wire, sessionKey, usable) {
|
|
6
|
+
if (wire !== undefined) {
|
|
7
|
+
let client;
|
|
8
|
+
let capsBaseUrl;
|
|
9
|
+
try {
|
|
10
|
+
if (wire === null || typeof wire !== 'object')
|
|
11
|
+
return { kind: 'injected-unusable' };
|
|
12
|
+
client = wire.client;
|
|
13
|
+
capsBaseUrl = wire.capsBaseUrl;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return { kind: 'injected-unusable' };
|
|
17
|
+
}
|
|
18
|
+
if (client === null || typeof client !== 'object')
|
|
19
|
+
return { kind: 'injected-unusable' };
|
|
20
|
+
const candidate = client;
|
|
21
|
+
if (!usable(candidate))
|
|
22
|
+
return { kind: 'injected-unusable' };
|
|
23
|
+
return { kind: 'injected', client: candidate, capsBaseUrl: typeof capsBaseUrl === 'string' && capsBaseUrl !== '' ? capsBaseUrl : undefined };
|
|
24
|
+
}
|
|
25
|
+
const installed = engineWireTargetFor(sessionKey);
|
|
26
|
+
if (!installed)
|
|
27
|
+
return { kind: 'no-target' };
|
|
28
|
+
const target = Object.freeze({
|
|
29
|
+
baseUrl: installed.baseUrl,
|
|
30
|
+
...(installed.token !== undefined ? { token: installed.token } : {}),
|
|
31
|
+
...(installed.principal !== undefined ? { principal: installed.principal } : {}),
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
kind: 'target',
|
|
35
|
+
target,
|
|
36
|
+
make: (opts) => makeEngineWireClient({
|
|
37
|
+
baseUrl: target.baseUrl,
|
|
38
|
+
...(target.token ? { token: target.token } : {}),
|
|
39
|
+
principal: target.principal,
|
|
40
|
+
...(opts?.timeoutMs !== undefined ? { timeoutMs: opts.timeoutMs } : {}),
|
|
41
|
+
...(opts?.maxRetries !== undefined ? { maxRetries: opts.maxRetries } : {}),
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export function clientHasVerbs(client, verbs) {
|
|
46
|
+
try {
|
|
47
|
+
if (client === null || typeof client !== 'object')
|
|
48
|
+
return false;
|
|
49
|
+
for (const path of verbs) {
|
|
50
|
+
let cur = client;
|
|
51
|
+
for (const seg of path) {
|
|
52
|
+
if (cur === null || (typeof cur !== 'object' && typeof cur !== 'function'))
|
|
53
|
+
return false;
|
|
54
|
+
cur = cur[seg];
|
|
55
|
+
}
|
|
56
|
+
if (typeof cur !== 'function')
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function callerSignalOf(signal) {
|
|
66
|
+
return signal === null ? undefined : signal;
|
|
67
|
+
}
|
|
68
|
+
function quietlyRemoveAbortListener(signal, listener) {
|
|
69
|
+
try {
|
|
70
|
+
signal.removeEventListener('abort', listener);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export function linkedAbortSignal(caller, deadline) {
|
|
76
|
+
const from = callerSignalOf(caller);
|
|
77
|
+
if (from === undefined)
|
|
78
|
+
return { signal: deadline, dispose: () => { } };
|
|
79
|
+
if (typeof AbortSignal.any === 'function')
|
|
80
|
+
return { signal: AbortSignal.any([from, deadline]), dispose: () => { } };
|
|
81
|
+
const ac = new AbortController();
|
|
82
|
+
if (from.aborted || deadline.aborted) {
|
|
83
|
+
ac.abort();
|
|
84
|
+
return { signal: ac.signal, dispose: () => { } };
|
|
85
|
+
}
|
|
86
|
+
const onAbort = () => ac.abort();
|
|
87
|
+
from.addEventListener('abort', onAbort, { once: true });
|
|
88
|
+
deadline.addEventListener('abort', onAbort, { once: true });
|
|
89
|
+
return {
|
|
90
|
+
signal: ac.signal,
|
|
91
|
+
dispose: () => {
|
|
92
|
+
quietlyRemoveAbortListener(from, onAbort);
|
|
93
|
+
quietlyRemoveAbortListener(deadline, onAbort);
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
export function injectedDeadlineDetail(ms) {
|
|
98
|
+
const within = ms === undefined ? 'the time limit this client allows' : `${ms} ms`;
|
|
99
|
+
return `no answer from the engine within ${within} — the request was abandoned (it may still have been received)`;
|
|
100
|
+
}
|
|
101
|
+
const NO_ANSWER_BRAND = Symbol.for('@sema-agent/client-core:engine-wire-no-answer');
|
|
102
|
+
const CANCELLED_BRAND = Symbol.for('@sema-agent/client-core:engine-wire-cancelled');
|
|
103
|
+
function branded(e, brand) {
|
|
104
|
+
return Object.prototype.hasOwnProperty.call(e, brand) && e[brand] === true;
|
|
105
|
+
}
|
|
106
|
+
export class EngineWireNoAnswerError extends Error {
|
|
107
|
+
constructor(message) {
|
|
108
|
+
super(message);
|
|
109
|
+
this.name = 'EngineWireNoAnswerError';
|
|
110
|
+
Object.defineProperty(this, NO_ANSWER_BRAND, { value: true, enumerable: false });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
export function cancelledWaitDetail() {
|
|
114
|
+
return 'no answer from the engine — the wait was cancelled after the request was sent (cancelling stops only the wait, not the request: it may still have been received)';
|
|
115
|
+
}
|
|
116
|
+
export class EngineWireCancelledError extends Error {
|
|
117
|
+
constructor() {
|
|
118
|
+
super(cancelledWaitDetail());
|
|
119
|
+
this.name = 'EngineWireCancelledError';
|
|
120
|
+
Object.defineProperty(this, CANCELLED_BRAND, { value: true, enumerable: false });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const NOT_SENT_MARK = Symbol.for('@sema-agent/client-core:engine-wire-not-sent');
|
|
124
|
+
function markNotSent(error) {
|
|
125
|
+
try {
|
|
126
|
+
if (error !== null && (typeof error === 'object' || typeof error === 'function') && Object.isExtensible(error)) {
|
|
127
|
+
Object.defineProperty(error, NOT_SENT_MARK, { value: true, enumerable: false, configurable: true, writable: false });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
}
|
|
132
|
+
return error;
|
|
133
|
+
}
|
|
134
|
+
function clearNotSent(error) {
|
|
135
|
+
try {
|
|
136
|
+
if (error !== null && (typeof error === 'object' || typeof error === 'function') && Object.prototype.hasOwnProperty.call(error, NOT_SENT_MARK)) {
|
|
137
|
+
delete error[NOT_SENT_MARK];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
}
|
|
142
|
+
return error;
|
|
143
|
+
}
|
|
144
|
+
function markedNotSent(e) {
|
|
145
|
+
return Object.prototype.hasOwnProperty.call(e, NOT_SENT_MARK) && e[NOT_SENT_MARK] === true;
|
|
146
|
+
}
|
|
147
|
+
export function connectionLostDetail() {
|
|
148
|
+
return 'no answer from the engine — the connection failed before an answer came back (the request may still have been received)';
|
|
149
|
+
}
|
|
150
|
+
function isPreSendCode(code, syscall) {
|
|
151
|
+
switch (code) {
|
|
152
|
+
case 'ECONNREFUSED':
|
|
153
|
+
case 'ENOTFOUND':
|
|
154
|
+
case 'EAI_AGAIN':
|
|
155
|
+
case 'UND_ERR_CONNECT_TIMEOUT':
|
|
156
|
+
case 'ERR_INVALID_URL':
|
|
157
|
+
case 'ERR_INVALID_CHAR':
|
|
158
|
+
case 'ERR_HTTP_INVALID_HEADER_VALUE':
|
|
159
|
+
case 'ERR_INVALID_ARG_TYPE':
|
|
160
|
+
case 'ERR_TLS_CERT_ALTNAME_FORMAT':
|
|
161
|
+
case 'ERR_TLS_CERT_ALTNAME_INVALID':
|
|
162
|
+
case 'ERR_TLS_DH_PARAM_SIZE':
|
|
163
|
+
case 'ERR_TLS_HANDSHAKE_TIMEOUT':
|
|
164
|
+
case 'ERR_TLS_INVALID_CONTEXT':
|
|
165
|
+
case 'ERR_TLS_INVALID_PROTOCOL_METHOD':
|
|
166
|
+
case 'ERR_TLS_INVALID_PROTOCOL_VERSION':
|
|
167
|
+
case 'ERR_TLS_PROTOCOL_VERSION_CONFLICT':
|
|
168
|
+
case 'CERT_CHAIN_TOO_LONG':
|
|
169
|
+
case 'CERT_HAS_EXPIRED':
|
|
170
|
+
case 'CERT_NOT_YET_VALID':
|
|
171
|
+
case 'CERT_REJECTED':
|
|
172
|
+
case 'CERT_REVOKED':
|
|
173
|
+
case 'CERT_SIGNATURE_FAILURE':
|
|
174
|
+
case 'CERT_UNTRUSTED':
|
|
175
|
+
case 'CRL_HAS_EXPIRED':
|
|
176
|
+
case 'CRL_NOT_YET_VALID':
|
|
177
|
+
case 'CRL_SIGNATURE_FAILURE':
|
|
178
|
+
case 'DEPTH_ZERO_SELF_SIGNED_CERT':
|
|
179
|
+
case 'ERROR_IN_CERT_NOT_AFTER_FIELD':
|
|
180
|
+
case 'ERROR_IN_CERT_NOT_BEFORE_FIELD':
|
|
181
|
+
case 'ERROR_IN_CRL_LAST_UPDATE_FIELD':
|
|
182
|
+
case 'ERROR_IN_CRL_NEXT_UPDATE_FIELD':
|
|
183
|
+
case 'HOSTNAME_MISMATCH':
|
|
184
|
+
case 'INVALID_CA':
|
|
185
|
+
case 'INVALID_PURPOSE':
|
|
186
|
+
case 'PATH_LENGTH_EXCEEDED':
|
|
187
|
+
case 'SELF_SIGNED_CERT_IN_CHAIN':
|
|
188
|
+
case 'UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY':
|
|
189
|
+
case 'UNABLE_TO_DECRYPT_CERT_SIGNATURE':
|
|
190
|
+
case 'UNABLE_TO_DECRYPT_CRL_SIGNATURE':
|
|
191
|
+
case 'UNABLE_TO_GET_CRL':
|
|
192
|
+
case 'UNABLE_TO_GET_ISSUER_CERT':
|
|
193
|
+
case 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY':
|
|
194
|
+
case 'UNABLE_TO_VERIFY_LEAF_SIGNATURE':
|
|
195
|
+
return true;
|
|
196
|
+
case 'EHOSTUNREACH':
|
|
197
|
+
case 'ENETUNREACH':
|
|
198
|
+
case 'ETIMEDOUT':
|
|
199
|
+
return syscall === 'connect';
|
|
200
|
+
default:
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function allAttemptsFailedBeforeSend(errors) {
|
|
205
|
+
if (!Array.isArray(errors) || errors.length === 0 || errors.length > 16)
|
|
206
|
+
return false;
|
|
207
|
+
return errors.every((x) => x !== null && typeof x === 'object' && isPreSendCode(x.code, x.syscall));
|
|
208
|
+
}
|
|
209
|
+
function failedBeforeSend(e) {
|
|
210
|
+
let cur = e;
|
|
211
|
+
for (let depth = 0; depth < 4 && cur !== null && typeof cur === 'object'; depth++) {
|
|
212
|
+
const o = cur;
|
|
213
|
+
if (isPreSendCode(o.code, o.syscall))
|
|
214
|
+
return true;
|
|
215
|
+
if (allAttemptsFailedBeforeSend(o.errors))
|
|
216
|
+
return true;
|
|
217
|
+
cur = cur.cause;
|
|
218
|
+
}
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
export function noAnswerKindOf(e) {
|
|
222
|
+
try {
|
|
223
|
+
if (e === null || typeof e !== 'object')
|
|
224
|
+
return null;
|
|
225
|
+
if (e instanceof EngineWireNoAnswerError || branded(e, NO_ANSWER_BRAND))
|
|
226
|
+
return 'deadline';
|
|
227
|
+
if (e instanceof EngineWireCancelledError || branded(e, CANCELLED_BRAND))
|
|
228
|
+
return 'cancelled';
|
|
229
|
+
if (markedNotSent(e))
|
|
230
|
+
return null;
|
|
231
|
+
const name = e.name;
|
|
232
|
+
if (name === 'TimeoutError')
|
|
233
|
+
return 'time-limit';
|
|
234
|
+
if ((e instanceof TypeError || name === 'TypeError') && !failedBeforeSend(e))
|
|
235
|
+
return 'connection-lost';
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
export function noAnswerDetailFrom(e) {
|
|
243
|
+
const kind = noAnswerKindOf(e);
|
|
244
|
+
if (kind === 'deadline') {
|
|
245
|
+
try {
|
|
246
|
+
return e.message;
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
return injectedDeadlineDetail();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (kind === 'time-limit')
|
|
253
|
+
return injectedDeadlineDetail();
|
|
254
|
+
if (kind === 'connection-lost')
|
|
255
|
+
return connectionLostDetail();
|
|
256
|
+
if (kind === 'cancelled')
|
|
257
|
+
return cancelledWaitDetail();
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
function signalAborted(signal) {
|
|
261
|
+
try {
|
|
262
|
+
return signal !== undefined && signal !== null && signal.aborted === true;
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function abortedBeforeSendError() {
|
|
269
|
+
const e = new Error('This operation was aborted');
|
|
270
|
+
e.name = 'AbortError';
|
|
271
|
+
return e;
|
|
272
|
+
}
|
|
273
|
+
function answeredByEngine(e) {
|
|
274
|
+
try {
|
|
275
|
+
if (e === null || typeof e !== 'object')
|
|
276
|
+
return false;
|
|
277
|
+
const o = e;
|
|
278
|
+
return typeof o.status === 'number' || typeof o.errorCode === 'string';
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const SETTLED_BY_PACKAGE_BRAND = Symbol.for('@sema-agent/client-core:engine-wire-settled');
|
|
285
|
+
function settledByPackage(value) {
|
|
286
|
+
try {
|
|
287
|
+
return value !== null && typeof value === 'object' && branded(value, SETTLED_BY_PACKAGE_BRAND);
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function abortReasonIfAborted(signal) {
|
|
294
|
+
try {
|
|
295
|
+
return signal !== undefined && signal.aborted === true ? { value: signal.reason } : undefined;
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
return undefined;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
export async function sendOnce(signal, run) {
|
|
302
|
+
const callerSignal = callerSignalOf(signal);
|
|
303
|
+
const abortedBefore = signalAborted(callerSignal);
|
|
304
|
+
const reasonBefore = abortedBefore ? abortReasonIfAborted(callerSignal) : undefined;
|
|
305
|
+
let returned;
|
|
306
|
+
try {
|
|
307
|
+
returned = run();
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
throw markNotSent(error);
|
|
311
|
+
}
|
|
312
|
+
const innerSettled = settledByPackage(returned);
|
|
313
|
+
try {
|
|
314
|
+
return await Promise.resolve(returned);
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
if (!innerSettled)
|
|
318
|
+
clearNotSent(error);
|
|
319
|
+
if (abortedBefore) {
|
|
320
|
+
if (reasonBefore !== undefined && error === reasonBefore.value && !answeredByEngine(error))
|
|
321
|
+
throw markNotSent(error);
|
|
322
|
+
throw error;
|
|
323
|
+
}
|
|
324
|
+
if (signalAborted(callerSignal) &&
|
|
325
|
+
!answeredByEngine(error) &&
|
|
326
|
+
noAnswerKindOf(error) !== 'deadline' &&
|
|
327
|
+
noAnswerKindOf(error) !== 'cancelled' &&
|
|
328
|
+
!provablyNotSent(error)) {
|
|
329
|
+
throw new EngineWireCancelledError();
|
|
330
|
+
}
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function provablyNotSent(e) {
|
|
335
|
+
try {
|
|
336
|
+
return e !== null && typeof e === 'object' && (markedNotSent(e) || failedBeforeSend(e));
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
export function settleInjected(ms, signal, run) {
|
|
343
|
+
const settled = settleInjectedOnce(ms, signal, run);
|
|
344
|
+
Object.defineProperty(settled, SETTLED_BY_PACKAGE_BRAND, { value: true, enumerable: false });
|
|
345
|
+
return settled;
|
|
346
|
+
}
|
|
347
|
+
async function settleInjectedOnce(ms, signal, run) {
|
|
348
|
+
const callerSignal = callerSignalOf(signal);
|
|
349
|
+
if (signalAborted(callerSignal))
|
|
350
|
+
throw abortedBeforeSendError();
|
|
351
|
+
let captured;
|
|
352
|
+
let cancelled = false;
|
|
353
|
+
let detach = () => { };
|
|
354
|
+
let unlink = () => { };
|
|
355
|
+
const got = await settleWithinDeadline(ms, (deadline) => {
|
|
356
|
+
let pending;
|
|
357
|
+
try {
|
|
358
|
+
const linked = linkedAbortSignal(callerSignal, deadline);
|
|
359
|
+
unlink = linked.dispose;
|
|
360
|
+
pending = Promise.resolve(run(linked.signal));
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
captured = { error: markNotSent(error) };
|
|
364
|
+
throw error;
|
|
365
|
+
}
|
|
366
|
+
const verb = pending.catch((error) => {
|
|
367
|
+
captured = { error: clearNotSent(error) };
|
|
368
|
+
throw error;
|
|
369
|
+
});
|
|
370
|
+
if (callerSignal === undefined)
|
|
371
|
+
return verb;
|
|
372
|
+
return new Promise((resolve, reject) => {
|
|
373
|
+
const onAbort = () => {
|
|
374
|
+
cancelled = true;
|
|
375
|
+
reject(new EngineWireCancelledError());
|
|
376
|
+
};
|
|
377
|
+
try {
|
|
378
|
+
callerSignal.addEventListener('abort', onAbort, { once: true });
|
|
379
|
+
detach = () => quietlyRemoveAbortListener(callerSignal, onAbort);
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
}
|
|
383
|
+
if (signalAborted(callerSignal))
|
|
384
|
+
onAbort();
|
|
385
|
+
verb.then(resolve, reject);
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
detach();
|
|
389
|
+
unlink();
|
|
390
|
+
if (got.kind === 'value')
|
|
391
|
+
return got.value;
|
|
392
|
+
if (got.kind === 'deadline')
|
|
393
|
+
throw new EngineWireNoAnswerError(injectedDeadlineDetail(ms));
|
|
394
|
+
if (cancelled)
|
|
395
|
+
throw new EngineWireCancelledError();
|
|
396
|
+
if (captured !== undefined)
|
|
397
|
+
throw captured.error;
|
|
398
|
+
throw new Error(got.detail);
|
|
399
|
+
}
|
package/dist/engineWireSdk.d.ts
CHANGED
|
@@ -6,11 +6,17 @@ export type WireAuthTokenSource = string | (() => string | undefined);
|
|
|
6
6
|
export declare function isLoopbackWireUrl(url: string): boolean;
|
|
7
7
|
export declare function resolveWireAuth(baseUrl: string | undefined, token?: string): WireAuthToken;
|
|
8
8
|
export declare function wireAuthTokenFor(baseUrl: string, token?: string): WireAuthToken;
|
|
9
|
+
export type EngineProbeClient = Pick<AgentClient, 'capabilities' | 'scenarioCapabilities'>;
|
|
10
|
+
export interface EngineWireInjection<C> {
|
|
11
|
+
client: C;
|
|
12
|
+
capsBaseUrl?: string;
|
|
13
|
+
}
|
|
9
14
|
export type EngineProbeOpts = {
|
|
10
15
|
fetchImpl?: typeof fetch;
|
|
11
16
|
timeoutMs?: number;
|
|
12
17
|
authToken?: WireAuthTokenSource | undefined;
|
|
13
18
|
principal?: string | undefined;
|
|
19
|
+
client?: EngineProbeClient;
|
|
14
20
|
};
|
|
15
21
|
export type EngineWireClientConfig = {
|
|
16
22
|
baseUrl: string;
|
|
@@ -6,13 +6,16 @@ export type FileHistoryCaptureReading = {
|
|
|
6
6
|
kind: 'present';
|
|
7
7
|
word: string;
|
|
8
8
|
};
|
|
9
|
-
export type FileHistoryCaptureMode = 'off' | 'on-always' | 'unknown';
|
|
9
|
+
export type FileHistoryCaptureMode = 'off' | 'on-always' | 'on-optional' | 'unknown';
|
|
10
10
|
export declare function projectFileHistoryCaptureCapability(caps: unknown): FileHistoryCaptureReading | undefined;
|
|
11
11
|
export declare function noteEngineCapsForFileHistoryCapture(baseUrl: string, caps: unknown, opts?: {
|
|
12
12
|
generation?: number;
|
|
13
13
|
}): void;
|
|
14
14
|
export declare function observedFileHistoryCapture(baseUrl?: string | undefined): FileHistoryCaptureReading;
|
|
15
15
|
export declare function fileHistoryCaptureMode(reading: FileHistoryCaptureReading): FileHistoryCaptureMode;
|
|
16
|
+
export declare function fileHistoryDeclarationField(reading: FileHistoryCaptureReading, captureOff: boolean): {
|
|
17
|
+
fileHistory: 'disabled';
|
|
18
|
+
} | Record<string, never>;
|
|
16
19
|
export declare function fileHistoryCaptureDoctorDetail(reading: FileHistoryCaptureReading): string;
|
|
17
20
|
export declare function forgetFileHistoryCaptureReading(baseUrl: string | undefined): void;
|
|
18
21
|
export declare function __resetFileHistoryCaptureReadingsForTests(): void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { capForDisplay } from './fleetTaskDesc.js';
|
|
2
2
|
import { engineWireTarget } from './engineWireTarget.js';
|
|
3
3
|
import { createEngineCapReader } from './engineCapReader.js';
|
|
4
|
+
import { FILE_HISTORY_DISABLED } from './request/taskRequest.js';
|
|
4
5
|
export function projectFileHistoryCaptureCapability(caps) {
|
|
5
6
|
if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
|
|
6
7
|
return undefined;
|
|
@@ -25,29 +26,62 @@ export function observedFileHistoryCapture(baseUrl = engineWireTarget()?.baseUrl
|
|
|
25
26
|
return reader.observed(baseUrl);
|
|
26
27
|
}
|
|
27
28
|
export function fileHistoryCaptureMode(reading) {
|
|
28
|
-
if (reading
|
|
29
|
+
if (typeof reading !== 'object' || reading === null)
|
|
29
30
|
return 'unknown';
|
|
30
|
-
|
|
31
|
+
let kind;
|
|
32
|
+
let word;
|
|
33
|
+
try {
|
|
34
|
+
kind = reading.kind;
|
|
35
|
+
word = kind === 'present' ? reading.word : undefined;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return 'unknown';
|
|
39
|
+
}
|
|
40
|
+
if (kind !== 'present')
|
|
41
|
+
return 'unknown';
|
|
42
|
+
if (word === 'off')
|
|
31
43
|
return 'off';
|
|
32
|
-
if (
|
|
44
|
+
if (word === 'on-optional')
|
|
45
|
+
return 'on-optional';
|
|
46
|
+
if (word === 'on-always')
|
|
33
47
|
return 'on-always';
|
|
34
48
|
return 'unknown';
|
|
35
49
|
}
|
|
50
|
+
export function fileHistoryDeclarationField(reading, captureOff) {
|
|
51
|
+
return captureOff === true && fileHistoryCaptureMode(reading) === 'on-optional' ? { fileHistory: FILE_HISTORY_DISABLED } : {};
|
|
52
|
+
}
|
|
36
53
|
const WORD_DETAIL_MAX = 40;
|
|
37
54
|
export function fileHistoryCaptureDoctorDetail(reading) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
55
|
+
const unobserved = 'file history capture not observed — the engine reports it on /v1/capabilities; this process has no usable capabilities reading cached for it, so whether this deployment captures file history is unknown';
|
|
56
|
+
if (typeof reading !== 'object' || reading === null)
|
|
57
|
+
return unobserved;
|
|
58
|
+
let kind;
|
|
59
|
+
let word;
|
|
60
|
+
try {
|
|
61
|
+
kind = reading.kind;
|
|
62
|
+
word = kind === 'present' ? reading.word : undefined;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return unobserved;
|
|
66
|
+
}
|
|
67
|
+
switch (kind) {
|
|
41
68
|
case 'not_reported':
|
|
42
69
|
return 'file history capture not reported by this engine — only newer engines advertise it; this does not say whether file history is captured here';
|
|
43
70
|
case 'present':
|
|
44
|
-
if (
|
|
71
|
+
if (typeof word !== 'string' || word.length === 0)
|
|
72
|
+
return unobserved;
|
|
73
|
+
if (word === 'off') {
|
|
45
74
|
return 'file history capture off on this deployment — the engine takes no snapshots of the files it changes; whether code can be rewound here is answered separately by the rewind readings';
|
|
46
75
|
}
|
|
47
|
-
if (
|
|
76
|
+
if (word === 'on-optional') {
|
|
77
|
+
return 'file history capture on — the engine snapshots files before changing them, and a session on this deployment can opt out of capture for its own runs';
|
|
78
|
+
}
|
|
79
|
+
if (word === 'on-always') {
|
|
48
80
|
return 'file history capture always on — the engine snapshots files before changing them in every session, and it cannot be turned off for a single session here';
|
|
49
81
|
}
|
|
50
|
-
return `file history capture reported as "${capForDisplay(
|
|
82
|
+
return `file history capture reported as "${capForDisplay(word, WORD_DETAIL_MAX)}" — a mode this client does not know yet, so whether it captures is shown as unknown`;
|
|
83
|
+
default:
|
|
84
|
+
return unobserved;
|
|
51
85
|
}
|
|
52
86
|
}
|
|
53
87
|
export function forgetFileHistoryCaptureReading(baseUrl) {
|
package/dist/gateVocabulary.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DeniedBy } from '@sema-agent/sdk';
|
|
2
|
+
import type { APPROVAL_MANDATE_WORDS } from './hitl/toolApprovalWire.js';
|
|
2
3
|
export declare const CC_TOOL_DENIAL_KINDS: readonly ["user-rejected", "permission-rule", "automode-blocked", "automode-unavailable", "automode-parsing-error", "interrupted", "cancelled"];
|
|
3
4
|
export type CcToolDenialKind = (typeof CC_TOOL_DENIAL_KINDS)[number];
|
|
4
5
|
export declare function isCcToolDenialKind(v: unknown): v is CcToolDenialKind;
|
|
@@ -7,14 +8,12 @@ export declare function ccToolDenialKindForSettledBy(settledBy: unknown): CcTool
|
|
|
7
8
|
export declare const GATE_DENIED_BY_WORDS: readonly DeniedBy[];
|
|
8
9
|
export declare function isGateDeniedByWord(v: unknown): v is DeniedBy;
|
|
9
10
|
export declare function gateDeniedByDetail(deniedBy: unknown): string;
|
|
10
|
-
export declare const ASK_ORIGIN_WORDS: readonly string[];
|
|
11
11
|
export declare function askOriginDetail(origin: unknown, message?: unknown): string;
|
|
12
12
|
export declare const RULE_STORE_UNREADABLE_KINDS: readonly ["store", "call"];
|
|
13
13
|
export type RuleStoreUnreadableKind = (typeof RULE_STORE_UNREADABLE_KINDS)[number];
|
|
14
14
|
export declare function isRuleStoreUnreadableKind(v: unknown): v is RuleStoreUnreadableKind;
|
|
15
15
|
export declare function ruleStoreUnreadableDetail(kind: RuleStoreUnreadableKind): string;
|
|
16
16
|
export declare function mandatedApprovalDetail(): string;
|
|
17
|
-
export declare const APPROVAL_MANDATE_WORDS: readonly ["operator_always", "tool_marks", "probe_mandate", "probe_unanswered", "write_protection", "write_protection_unresolved"];
|
|
18
17
|
export type ApprovalMandateWord = (typeof APPROVAL_MANDATE_WORDS)[number];
|
|
19
18
|
export declare function isApprovalMandateWord(v: unknown): v is ApprovalMandateWord;
|
|
20
19
|
export declare function approvalMandateDetail(word: ApprovalMandateWord): string;
|
package/dist/gateVocabulary.js
CHANGED
|
@@ -54,19 +54,6 @@ export function gateDeniedByDetail(deniedBy) {
|
|
|
54
54
|
const word = typeof deniedBy === 'string' && deniedBy.length > 0 ? deniedBy : '(none)';
|
|
55
55
|
return `denied by a layer this build does not know (${word}) — this build does not know this layer name: a newer engine may have added it, or the record may be damaged; this client cannot tell which`;
|
|
56
56
|
}
|
|
57
|
-
export const ASK_ORIGIN_WORDS = Object.freeze([
|
|
58
|
-
'content_question',
|
|
59
|
-
'ancestor_marked',
|
|
60
|
-
'org_unavailable',
|
|
61
|
-
'org_rule',
|
|
62
|
-
'rule_store_unavailable',
|
|
63
|
-
'hook',
|
|
64
|
-
'ask_rule',
|
|
65
|
-
'denial_limit_fallback',
|
|
66
|
-
'shell_gate_tighten',
|
|
67
|
-
'safety_tighten',
|
|
68
|
-
'policy',
|
|
69
|
-
]);
|
|
70
57
|
const ASK_ORIGIN_SENTENCES = Object.freeze({
|
|
71
58
|
content_question: 'the tool itself asked you a question',
|
|
72
59
|
ancestor_marked: 'an ancestor marked this call (an inherited approver-unavailable float, or a durable mandate): it must reach the park with no synchronous decision-maker in between',
|
|
@@ -118,17 +105,8 @@ export function ruleStoreUnreadableDetail(kind) {
|
|
|
118
105
|
export function mandatedApprovalDetail() {
|
|
119
106
|
return 'no saved allow rule and no remembered answer can retire this question; each call is settled on its own — by you here, by a hook, or by an automatic check the deployment runs — and an answer covers only that call';
|
|
120
107
|
}
|
|
121
|
-
export const APPROVAL_MANDATE_WORDS = Object.freeze([
|
|
122
|
-
'operator_always',
|
|
123
|
-
'tool_marks',
|
|
124
|
-
'probe_mandate',
|
|
125
|
-
'probe_unanswered',
|
|
126
|
-
'write_protection',
|
|
127
|
-
'write_protection_unresolved',
|
|
128
|
-
]);
|
|
129
108
|
const _mandateWordsPin = true;
|
|
130
109
|
void _mandateWordsPin;
|
|
131
|
-
const APPROVAL_MANDATE_SET = new Set(APPROVAL_MANDATE_WORDS);
|
|
132
110
|
export function isApprovalMandateWord(v) {
|
|
133
111
|
return APPROVAL_MANDATE_SET.has(v);
|
|
134
112
|
}
|
|
@@ -140,6 +118,7 @@ const APPROVAL_MANDATE_SENTENCES = Object.freeze({
|
|
|
140
118
|
write_protection: "this change lands on a protected location (the agent's own configuration), which is confirmed one change at a time",
|
|
141
119
|
write_protection_unresolved: 'the protected-location check could not tell where this change lands, so whether it touches a protected location is unknown',
|
|
142
120
|
});
|
|
121
|
+
const APPROVAL_MANDATE_SET = new Set(Object.keys(APPROVAL_MANDATE_SENTENCES));
|
|
143
122
|
export function approvalMandateDetail(word) {
|
|
144
123
|
if (typeof word === 'string' && Object.hasOwn(APPROVAL_MANDATE_SENTENCES, word)) {
|
|
145
124
|
return APPROVAL_MANDATE_SENTENCES[word];
|