@sema-agent/client-core 0.90.0 → 0.92.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 +365 -0
- package/README.md +48 -32
- package/dist/adapt/arms.js +13 -12
- package/dist/adapt/panelTasks.d.ts +0 -2
- package/dist/adapt/panelTasks.js +6 -26
- package/dist/adapt.js +2 -2
- package/dist/adapter/activeRunSelfHeal.d.ts +0 -2
- package/dist/adapter/activeRunSelfHeal.js +5 -27
- package/dist/adapter/downstream/eventToSdkMessage.js +4 -2
- package/dist/adapter/downstream/terminalToSdkResult.js +16 -7
- package/dist/adapter/downstream/wiringManifestView.d.ts +6 -0
- package/dist/adapter/downstream/wiringManifestView.js +16 -0
- package/dist/adapter/runStream.js +39 -20
- package/dist/askSurvivesStandingAnswer.d.ts +13 -0
- package/dist/askSurvivesStandingAnswer.js +53 -0
- package/dist/attachmentSeatCapability.d.ts +11 -0
- package/dist/attachmentSeatCapability.js +27 -0
- package/dist/attachmentsWireCaps.d.ts +9 -0
- package/dist/attachmentsWireCaps.js +74 -21
- package/dist/autoModeUnavailable.js +3 -2
- package/dist/cloudConfigWireCaps.js +5 -4
- package/dist/compensations.js +13 -17
- package/dist/controlRouter.d.ts +32 -25
- package/dist/controlRouter.js +166 -63
- package/dist/coreValuePorts.d.ts +4 -2
- package/dist/coreValuePorts.js +5 -0
- package/dist/decideFailureNote.js +7 -3
- package/dist/decideReceipt.d.ts +9 -0
- package/dist/decideReceipt.js +62 -1
- package/dist/disableSkillsWire.d.ts +1 -0
- package/dist/disableSkillsWire.js +8 -1
- package/dist/displayUntrusted.js +155 -5
- package/dist/effectiveFacts.d.ts +14 -4
- package/dist/effectiveFacts.js +45 -5
- package/dist/engineAgentAbsence.js +2 -1
- package/dist/engineCapReader.js +16 -10
- package/dist/engineCapsCache.d.ts +5 -1
- package/dist/engineCapsCache.js +69 -8
- package/dist/engineClosedSets.d.ts +2 -0
- package/dist/engineClosedSets.js +3 -0
- package/dist/engineErrorCodes.d.ts +17 -0
- package/dist/engineErrorCodes.js +47 -0
- package/dist/engineNoticeCodes.d.ts +14 -0
- package/dist/engineNoticeCodes.js +71 -0
- package/dist/executionLaneCapability.js +2 -0
- package/dist/gateOutcome.js +2 -17
- package/dist/gateVocabulary.d.ts +2 -4
- package/dist/gateVocabulary.js +3 -11
- package/dist/generated/engineFactTables.d.ts +27 -0
- package/dist/generated/engineFactTables.js +128 -0
- package/dist/generated/engineNoticeTables.js +3 -0
- package/dist/generated/settingsSchemaTables.d.ts +8 -0
- package/dist/generated/settingsSchemaTables.js +40 -0
- package/dist/hitl/allowRuleShadow.d.ts +21 -0
- package/dist/hitl/allowRuleShadow.js +167 -0
- package/dist/hitl/askClassPair.d.ts +14 -0
- package/dist/hitl/askClassPair.js +42 -0
- package/dist/hitl/askGateWire.d.ts +1 -1
- package/dist/hitl/askGateWire.js +2 -1
- package/dist/hitl/askSurvivesPosture.d.ts +5 -0
- package/dist/hitl/askSurvivesPosture.js +17 -0
- package/dist/hitl/automaticAnswerVerdict.d.ts +21 -0
- package/dist/hitl/automaticAnswerVerdict.js +143 -0
- package/dist/hitl/crashConverged.d.ts +8 -0
- package/dist/hitl/crashConverged.js +58 -1
- package/dist/hitl/crashConvergedNotice.d.ts +4 -0
- package/dist/hitl/crashConvergedNotice.js +57 -0
- package/dist/hitl/frameRouter.d.ts +2 -0
- package/dist/hitl/frameRouter.js +66 -14
- package/dist/hitl/gateLedger.d.ts +6 -0
- package/dist/hitl/gateLedger.js +34 -5
- package/dist/hitl/hitlBridge.d.ts +7 -4
- package/dist/hitl/hitlHostSurface.d.ts +2 -0
- package/dist/hitl/hitlHostSurface.js +7 -0
- package/dist/hitl/livePendingAsk.js +24 -5
- package/dist/hitl/parkResolver.d.ts +7 -2
- package/dist/hitl/parkResolver.js +21 -7
- package/dist/hitl/persistedRulesWire.d.ts +4 -1
- package/dist/hitl/persistedRulesWire.js +9 -2
- package/dist/hitl/planReviewWire.d.ts +1 -1
- package/dist/hitl/planReviewWire.js +19 -5
- package/dist/hitl/replayedApproval.d.ts +21 -0
- package/dist/hitl/replayedApproval.js +89 -0
- package/dist/hitl/sessionPolicyDeliverable.js +20 -2
- package/dist/hitl/sessionPolicyWire.d.ts +13 -0
- package/dist/hitl/sessionPolicyWire.js +75 -2
- package/dist/hitl/suspendedReopen.js +2 -2
- package/dist/hitl/toolApprovalWire.d.ts +9 -1
- package/dist/hitl/toolApprovalWire.js +40 -40
- package/dist/hookMatcherVerdict.d.ts +29 -0
- package/dist/hookMatcherVerdict.js +266 -0
- package/dist/humanTurn.d.ts +91 -0
- package/dist/humanTurn.js +252 -0
- package/dist/humanTurnRead.d.ts +105 -0
- package/dist/humanTurnRead.js +331 -0
- package/dist/index.d.ts +38 -11
- package/dist/index.js +27 -8
- package/dist/inheritEnvWire.js +4 -5
- package/dist/liveModelCatalog.d.ts +2 -0
- package/dist/liveModelCatalog.js +51 -3
- package/dist/mcpLiveness.js +2 -1
- package/dist/memoryVerbsWire.d.ts +1 -1
- package/dist/memoryVerbsWire.js +3 -0
- package/dist/model/catalog.js +2 -1
- package/dist/model/providerPresets.d.ts +3 -1
- package/dist/model/tierVocabulary.d.ts +2 -1
- package/dist/model/tierVocabulary.js +3 -8
- package/dist/peerFrames.js +2 -2
- package/dist/permissionRuleIssue.d.ts +1 -1
- package/dist/permissionRuleIssue.js +31 -9
- package/dist/permissionsAllowGrantCapability.d.ts +2 -1
- package/dist/permissionsAllowGrantCapability.js +11 -2
- package/dist/permissionsDeclaration.d.ts +29 -0
- package/dist/permissionsDeclaration.js +155 -66
- package/dist/pluginHooksWire.js +2 -11
- package/dist/promptDelivery.d.ts +11 -3
- package/dist/promptDelivery.js +164 -29
- package/dist/promptProfileWireCaps.d.ts +2 -1
- package/dist/protocolSegment.d.ts +9 -0
- package/dist/protocolSegment.js +28 -0
- package/dist/providerRejection.d.ts +1 -0
- package/dist/providerRejection.js +20 -0
- package/dist/readDenyTiers.d.ts +10 -0
- package/dist/readDenyTiers.js +29 -0
- package/dist/request/taskRequest.js +3 -17
- package/dist/resumeRefusalCopy.d.ts +11 -0
- package/dist/resumeRefusalCopy.js +61 -4
- package/dist/rewindArchiveCapability.js +4 -4
- package/dist/rewindWireCaps.d.ts +2 -1
- package/dist/rewindWireCaps.js +19 -2
- package/dist/ruleCompileVerdict.d.ts +2 -0
- package/dist/ruleCompileVerdict.js +13 -0
- package/dist/ruleRemovalConsequence.d.ts +2 -1
- package/dist/runCancelContext.d.ts +12 -0
- package/dist/runCancelContext.js +83 -1
- package/dist/seam.d.ts +2 -0
- package/dist/seam.js +1 -1
- package/dist/seatContract.d.ts +2 -1
- package/dist/sessionMemoryStatus.d.ts +2 -4
- package/dist/sessionSyncFileHistoryCapability.d.ts +18 -0
- package/dist/sessionSyncFileHistoryCapability.js +50 -0
- package/dist/skillToolListsCapability.d.ts +18 -0
- package/dist/skillToolListsCapability.js +50 -0
- package/dist/sqlEngineCapability.js +1 -8
- package/dist/steerPriorityCapability.d.ts +18 -0
- package/dist/steerPriorityCapability.js +80 -0
- package/dist/steerReceipt.d.ts +9 -0
- package/dist/steerReceipt.js +25 -0
- package/dist/subagent/engineSubagentSteer.js +2 -9
- package/dist/supportFloor.js +2 -2
- package/dist/taskRequestWords.d.ts +7 -1
- package/dist/taskRequestWords.js +18 -8
- package/dist/toolHistoryBadTurn.d.ts +1 -0
- package/dist/toolHistoryBadTurn.js +89 -0
- package/dist/toolHistoryMismatch.d.ts +2 -1
- package/dist/toolHistoryMismatch.js +19 -6
- package/dist/toolResult.d.ts +8 -0
- package/dist/toolResult.js +47 -3
- package/dist/types/engineState.d.ts +2 -12
- package/dist/userAttachmentEnvelope.d.ts +61 -0
- package/dist/userAttachmentEnvelope.js +204 -0
- package/dist/userInvokedSkillsCapability.d.ts +18 -0
- package/dist/userInvokedSkillsCapability.js +50 -0
- package/dist/wireFailureShape.d.ts +3 -0
- package/dist/wireFailureShape.js +8 -0
- package/dist/wireRefusalCopy.d.ts +6 -0
- package/dist/wireRefusalCopy.js +26 -3
- package/dist/workflowsJournalCapability.d.ts +18 -0
- package/dist/workflowsJournalCapability.js +50 -0
- package/dist/writeProtectionCapability.d.ts +2 -4
- package/docs/INTEGRATION-CLIENTS.md +1489 -16
- package/package.json +3 -3
package/dist/controlRouter.js
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { cancelConflictContent, cancelConflictFromError } from './wireRefusalCopy.js';
|
|
2
|
-
import {
|
|
2
|
+
import { steerPriorityMode } from './steerPriorityCapability.js';
|
|
3
3
|
export class ControlSafetyError extends Error {
|
|
4
4
|
code;
|
|
5
5
|
cause;
|
|
6
|
-
constructor(message, code, cause) {
|
|
6
|
+
constructor(message, code, cause, detail) {
|
|
7
7
|
super(message);
|
|
8
8
|
this.code = code;
|
|
9
9
|
this.cause = cause;
|
|
10
10
|
this.name = 'ControlSafetyError';
|
|
11
|
+
const advice = detail?.advice;
|
|
12
|
+
const status = detail?.status;
|
|
13
|
+
if (typeof advice === 'string' && advice.length > 0)
|
|
14
|
+
this.advice = advice;
|
|
15
|
+
if (typeof status === 'number')
|
|
16
|
+
this.status = status;
|
|
11
17
|
}
|
|
12
18
|
}
|
|
13
|
-
const BAND_RANK = { now: 0, next: 1, later: 2 };
|
|
14
19
|
export class ControlRouter {
|
|
15
20
|
client;
|
|
16
21
|
taskId = null;
|
|
@@ -18,8 +23,6 @@ export class ControlRouter {
|
|
|
18
23
|
jobId;
|
|
19
24
|
scenario;
|
|
20
25
|
systemPrompt;
|
|
21
|
-
queue = [];
|
|
22
|
-
seq = 0;
|
|
23
26
|
constructor(client, opts = {}) {
|
|
24
27
|
this.client = client;
|
|
25
28
|
this.sessionId = opts.sessionId;
|
|
@@ -55,70 +58,51 @@ export class ControlRouter {
|
|
|
55
58
|
}
|
|
56
59
|
async steer(text, mode, opts) {
|
|
57
60
|
if (this.taskId === null) {
|
|
58
|
-
throw
|
|
61
|
+
throw controlSafetyRefusal('not_running', 'no run in flight to steer', 'submit a turn first');
|
|
59
62
|
}
|
|
60
|
-
|
|
63
|
+
let priority;
|
|
64
|
+
let reading;
|
|
65
|
+
try {
|
|
66
|
+
priority = opts?.priority;
|
|
67
|
+
reading = opts?.steerPriority;
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
throw steerLocalRefusal('steer_input_invalid', 'unknown', e);
|
|
71
|
+
}
|
|
72
|
+
const body = steerBodyOf({ text, ...(mode !== undefined ? { mode } : {}), ...(priority !== undefined ? { priority: priority } : {}) }, (reading ?? UNOBSERVED_STEER_PRIORITY));
|
|
61
73
|
try {
|
|
62
74
|
return await this.client.runs.steer(this.taskId, body, opts?.signal !== undefined ? { signal: opts.signal } : undefined);
|
|
63
75
|
}
|
|
64
76
|
catch (e) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
throw new ControlSafetyError(`${wireCode} — ${steeringAdviceOf(e, safety) ?? 'steering refused'}`, safety, e);
|
|
77
|
+
if (typeof e === 'object' && e !== null) {
|
|
78
|
+
const refusal = steerRefusalAdviceOf(e);
|
|
79
|
+
if (refusal !== undefined)
|
|
80
|
+
throw controlSafetyRefusal(refusal.safety, steerRefusalWireLabel(e), refusal.advice, e);
|
|
70
81
|
}
|
|
71
82
|
throw e;
|
|
72
83
|
}
|
|
73
84
|
}
|
|
74
85
|
async cancel(opts) {
|
|
75
86
|
if (this.taskId === null) {
|
|
76
|
-
throw
|
|
87
|
+
throw controlSafetyRefusal('not_found', 'no run in flight to cancel');
|
|
77
88
|
}
|
|
78
89
|
try {
|
|
79
90
|
return await this.client.runs.cancel(this.taskId, opts?.signal !== undefined ? { signal: opts.signal } : undefined);
|
|
80
91
|
}
|
|
81
92
|
catch (e) {
|
|
82
93
|
if (cancelConflictFromError(e)?.kind === 'run_not_running') {
|
|
83
|
-
throw
|
|
94
|
+
throw controlSafetyRefusal('cancel_run_not_running', 'runs.cancel 409 conflict.run_not_running', cancelConflictContent({ kind: 'run_not_running' }), e);
|
|
84
95
|
}
|
|
85
96
|
if (isCancelSuspendedConflict(e)) {
|
|
86
|
-
throw
|
|
87
|
-
'check what that decision did to the run before retrying the cancel',
|
|
97
|
+
throw controlSafetyRefusal('cancel_lost_race', 'runs.cancel 409', 'the pending gate was decided or expired concurrently (lost CAS race); ' +
|
|
98
|
+
'check what that decision did to the run before retrying the cancel', e);
|
|
88
99
|
}
|
|
89
100
|
if (isNotFound(e)) {
|
|
90
|
-
throw
|
|
101
|
+
throw controlSafetyRefusal('not_found', 'runs.cancel 404', `${CANCEL_NOT_FOUND_COPY.happened} — ${CANCEL_NOT_FOUND_COPY.nextStep}`, e);
|
|
91
102
|
}
|
|
92
103
|
throw e;
|
|
93
104
|
}
|
|
94
105
|
}
|
|
95
|
-
enqueue(text, priority = 'next') {
|
|
96
|
-
const cmd = { id: this.nextId(), text, priority };
|
|
97
|
-
this.queue.push(cmd);
|
|
98
|
-
return cmd;
|
|
99
|
-
}
|
|
100
|
-
dequeue(id) {
|
|
101
|
-
const i = this.queue.findIndex((c) => c.id === id);
|
|
102
|
-
if (i < 0)
|
|
103
|
-
return false;
|
|
104
|
-
this.queue.splice(i, 1);
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
pending() {
|
|
108
|
-
return [...this.queue].sort((a, b) => BAND_RANK[a.priority] - BAND_RANK[b.priority]);
|
|
109
|
-
}
|
|
110
|
-
async drainNext(opts) {
|
|
111
|
-
const ordered = this.pending();
|
|
112
|
-
const head = ordered[0];
|
|
113
|
-
if (!head)
|
|
114
|
-
return null;
|
|
115
|
-
this.dequeue(head.id);
|
|
116
|
-
return this.submit(head.text, opts);
|
|
117
|
-
}
|
|
118
|
-
nextId() {
|
|
119
|
-
this.seq += 1;
|
|
120
|
-
return `q-${this.seq}-${uuid()}`;
|
|
121
|
-
}
|
|
122
106
|
}
|
|
123
107
|
export function errCodes(e) {
|
|
124
108
|
if (!e || typeof e !== 'object')
|
|
@@ -147,20 +131,72 @@ const STEERING_NAME_TO_SAFETY = new Map([
|
|
|
147
131
|
['SteeringAmbiguousTargetError', 'ambiguous_target'],
|
|
148
132
|
['SteeringStillRunningError', 'still_running'],
|
|
149
133
|
['SteeringLedgerUnavailableError', 'ledger_unavailable'],
|
|
134
|
+
['SteeringQueueFullError', 'queue_full'],
|
|
135
|
+
['SteeringDuplicateInputIdError', 'duplicate_input_id'],
|
|
150
136
|
['SteeringError', 'steering_other'],
|
|
151
137
|
]);
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
138
|
+
const STEERING_COPY = {
|
|
139
|
+
not_running: {
|
|
140
|
+
happened: 'that run is not accepting messages right now — it has just finished, is running on another server, or is not the active run of its session',
|
|
141
|
+
nextStep: 'check its current state and send the message to the run that is active',
|
|
142
|
+
},
|
|
143
|
+
invalid_content: {
|
|
144
|
+
happened: 'the message was refused because its text contains control markers the engine does not accept, so nothing was delivered',
|
|
145
|
+
nextStep: 'rewrite the message and send it again',
|
|
146
|
+
},
|
|
147
|
+
queue_full: {
|
|
148
|
+
happened: 'that run is paused and already holds as many waiting messages as it can, so this one was not accepted',
|
|
149
|
+
nextStep: 'send it again once the waiting messages have been delivered (when the run resumes or the session is woken)',
|
|
150
|
+
},
|
|
151
|
+
duplicate_input_id: {
|
|
152
|
+
happened: 'a different instruction was already accepted under this idempotency key, and that earlier instruction stands',
|
|
153
|
+
nextStep: 'if you changed the text, send the new text under a new key; otherwise do not resend it — a new key would deliver the same instruction twice',
|
|
154
|
+
},
|
|
155
|
+
ambiguous_target: {
|
|
156
|
+
happened: 'more than one running agent matches that target, so the message was not delivered',
|
|
157
|
+
nextStep: 'address a sub-agent by its tool-call id; a workflow agent cannot be singled out while another running agent shares its label, so send it again once only one does',
|
|
158
|
+
},
|
|
159
|
+
still_running: {
|
|
160
|
+
happened: 'that agent is still running, so it cannot be resumed',
|
|
161
|
+
nextStep: 'send it a message instead, or wait for it to finish',
|
|
162
|
+
},
|
|
163
|
+
blocked_by_hook: {
|
|
164
|
+
happened: "the message was not accepted: a prompt check on this deployment blocked it, so nothing was delivered",
|
|
165
|
+
nextStep: 'edit the message and send it again — that is not a duplicate submission',
|
|
166
|
+
},
|
|
167
|
+
ledger_unavailable: {
|
|
168
|
+
happened: 'the server could not record the message and refused it before anything reached the engine, so nothing was delivered',
|
|
169
|
+
nextStep: 'send the same text again later',
|
|
170
|
+
},
|
|
171
|
+
steering_other: {
|
|
172
|
+
happened: 'the message was refused for a reason this version does not recognise, so it did not land',
|
|
173
|
+
nextStep: 'report its error code if this keeps happening; do not guess what it means',
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
const adviceOfCopy = (c) => `${c.happened} — ${c.nextStep}`;
|
|
177
|
+
const STEERING_ADVICE = Object.freeze(Object.fromEntries(Object.entries(STEERING_COPY).map(([k, c]) => [k, adviceOfCopy(c)])));
|
|
178
|
+
const STEERING_OTHER_UNKNOWN_COPY = {
|
|
179
|
+
happened: 'the message was refused for a reason this version does not recognise, and whether it was delivered is not known',
|
|
180
|
+
nextStep: 'do not resend it as if it had certainly been dropped — check the run first, and report its error code if this keeps happening',
|
|
181
|
+
};
|
|
182
|
+
const CANCEL_NOT_FOUND_COPY = {
|
|
183
|
+
happened: 'this server has no run with that id for you — it does not exist, or it belongs to someone else',
|
|
184
|
+
nextStep: 'nothing was cancelled; refresh the run list',
|
|
185
|
+
};
|
|
186
|
+
const PRIORITY_NOT_APPLIED_COPY = {
|
|
187
|
+
advisory: {
|
|
188
|
+
happened: "this server accepts a steer priority but does not apply it — a 'now' message would not interrupt the running turn and a 'later' message would not wait",
|
|
189
|
+
nextStep: 'nothing was sent; to interrupt the turn now, send the text as an interrupt, or send it without a priority to have it delivered at the next turn boundary',
|
|
190
|
+
},
|
|
191
|
+
unknown: {
|
|
192
|
+
happened: 'whether this server applies a steer priority is not known — there is no usable capability reading for it',
|
|
193
|
+
nextStep: 'nothing was sent; wait for the capability reading and try again, or send it without a priority to have it delivered at the next turn boundary',
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
const STEER_INPUT_INVALID_COPY = {
|
|
197
|
+
happened: "the steer request could not be built — its priority must be 'now', 'next' or 'later', and its fields must be readable",
|
|
198
|
+
nextStep: 'nothing was sent; fix the request and send it again',
|
|
199
|
+
};
|
|
164
200
|
export function steeringStatusIs4xx(e) {
|
|
165
201
|
let status;
|
|
166
202
|
try {
|
|
@@ -171,10 +207,10 @@ export function steeringStatusIs4xx(e) {
|
|
|
171
207
|
}
|
|
172
208
|
return status !== undefined && status >= 400 && status < 500;
|
|
173
209
|
}
|
|
174
|
-
function
|
|
175
|
-
if (safety === 'steering_other' && !
|
|
176
|
-
return
|
|
177
|
-
return
|
|
210
|
+
function steeringCopyOf(e, safety) {
|
|
211
|
+
if (safety === 'steering_other' && !steeringStatusIs4xx(e))
|
|
212
|
+
return STEERING_OTHER_UNKNOWN_COPY;
|
|
213
|
+
return STEERING_COPY[safety];
|
|
178
214
|
}
|
|
179
215
|
const STEERING_REFUSED_BEFORE_ENGINE = new Map([['ledger_unavailable', 503]]);
|
|
180
216
|
export function steeringRefusedBeforeEngine(e) {
|
|
@@ -185,8 +221,8 @@ export function steeringRefusedBeforeEngine(e) {
|
|
|
185
221
|
const safety = steeringVerdict(e);
|
|
186
222
|
if (safety === undefined || STEERING_REFUSED_BEFORE_ENGINE.get(safety) !== status)
|
|
187
223
|
return undefined;
|
|
188
|
-
const
|
|
189
|
-
return
|
|
224
|
+
const copy = STEERING_COPY[safety];
|
|
225
|
+
return { safety, advice: STEERING_ADVICE[safety], happened: copy.happened, nextStep: copy.nextStep };
|
|
190
226
|
}
|
|
191
227
|
catch {
|
|
192
228
|
return undefined;
|
|
@@ -195,7 +231,7 @@ export function steeringRefusedBeforeEngine(e) {
|
|
|
195
231
|
function steeringSafetyOf(e, verdict) {
|
|
196
232
|
if (!STEERING_REFUSED_BEFORE_ENGINE.has(verdict))
|
|
197
233
|
return verdict;
|
|
198
|
-
const refused =
|
|
234
|
+
const refused = steeringRefusedBeforeEngine(e);
|
|
199
235
|
return refused !== undefined && refused.safety === verdict ? verdict : 'steering_other';
|
|
200
236
|
}
|
|
201
237
|
function steeringVerdict(e) {
|
|
@@ -207,6 +243,73 @@ function steeringVerdict(e) {
|
|
|
207
243
|
return STEERING_NAME_TO_SAFETY.get(name);
|
|
208
244
|
return undefined;
|
|
209
245
|
}
|
|
246
|
+
export function steerRefusalAdviceOf(e) {
|
|
247
|
+
try {
|
|
248
|
+
const verdict = steeringVerdict(e);
|
|
249
|
+
if (verdict === undefined)
|
|
250
|
+
return undefined;
|
|
251
|
+
const safety = steeringSafetyOf(e, verdict);
|
|
252
|
+
const copy = steeringCopyOf(e, safety);
|
|
253
|
+
return { safety, advice: adviceOfCopy(copy), happened: copy.happened, nextStep: copy.nextStep };
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
return undefined;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function steerRefusalWireLabel(e) {
|
|
260
|
+
try {
|
|
261
|
+
const { code, name } = errCodes(e);
|
|
262
|
+
return code ?? name ?? 'steering.<unknown>';
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return 'steering.<unknown>';
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function statusOfThrown(e) {
|
|
269
|
+
try {
|
|
270
|
+
return errCodes(e).status;
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
return undefined;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
function controlSafetyRefusal(code, head, advice, cause) {
|
|
277
|
+
const status = statusOfThrown(cause);
|
|
278
|
+
const detail = { ...(advice !== undefined ? { advice } : {}), ...(status !== undefined ? { status } : {}) };
|
|
279
|
+
return new ControlSafetyError(advice === undefined ? head : `${head} — ${advice}`, code, cause, detail);
|
|
280
|
+
}
|
|
281
|
+
export const UNOBSERVED_STEER_PRIORITY = Object.freeze({ kind: 'unobserved' });
|
|
282
|
+
function steerLocalRefusal(code, mode, cause) {
|
|
283
|
+
const copy = code === 'steer_input_invalid' ? STEER_INPUT_INVALID_COPY : PRIORITY_NOT_APPLIED_COPY[mode === 'advisory' ? 'advisory' : 'unknown'];
|
|
284
|
+
return controlSafetyRefusal(code, 'steer not sent', adviceOfCopy(copy), cause);
|
|
285
|
+
}
|
|
286
|
+
function ownInputField(input, key) {
|
|
287
|
+
return Object.hasOwn(input, key) ? input[key] : undefined;
|
|
288
|
+
}
|
|
289
|
+
export function steerBodyOf(input, reading) {
|
|
290
|
+
let text;
|
|
291
|
+
let mode;
|
|
292
|
+
let priority;
|
|
293
|
+
try {
|
|
294
|
+
if (input === null || typeof input !== 'object' || Array.isArray(input))
|
|
295
|
+
throw new TypeError('steer input is not an object');
|
|
296
|
+
text = ownInputField(input, 'text');
|
|
297
|
+
mode = ownInputField(input, 'mode');
|
|
298
|
+
priority = ownInputField(input, 'priority');
|
|
299
|
+
}
|
|
300
|
+
catch (e) {
|
|
301
|
+
throw steerLocalRefusal('steer_input_invalid', 'unknown', e);
|
|
302
|
+
}
|
|
303
|
+
const base = mode !== undefined ? { text, mode } : { text };
|
|
304
|
+
if (priority === undefined || priority === 'next')
|
|
305
|
+
return Object.freeze(base);
|
|
306
|
+
const tierMode = steerPriorityMode(reading);
|
|
307
|
+
if (priority !== 'now' && priority !== 'later')
|
|
308
|
+
throw steerLocalRefusal('steer_input_invalid', tierMode);
|
|
309
|
+
if (tierMode !== 'engine')
|
|
310
|
+
throw steerLocalRefusal('priority_not_applied', tierMode);
|
|
311
|
+
return Object.freeze({ ...base, priority });
|
|
312
|
+
}
|
|
210
313
|
function isCancelSuspendedConflict(e) {
|
|
211
314
|
const { name, status } = errCodes(e);
|
|
212
315
|
return name === 'ConflictError' || status === 409;
|
package/dist/coreValuePorts.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export interface CoreProtocolNamespaceView {
|
|
|
32
32
|
}
|
|
33
33
|
export interface PermissionRuleView {
|
|
34
34
|
rule: string;
|
|
35
|
-
behavior: 'deny' | 'ask'
|
|
35
|
+
behavior: 'deny' | 'ask';
|
|
36
36
|
source?: string;
|
|
37
37
|
}
|
|
38
38
|
export interface PermissionRuleIssueView {
|
|
@@ -59,8 +59,9 @@ export interface CoreValuePorts {
|
|
|
59
59
|
ruleToolGrammarOf: (toolName: string) => 'command' | 'path' | undefined;
|
|
60
60
|
validatePermissionRules: (rules: PermissionRuleView[], opts?: ValidatePermissionRulesOptionsView) => PermissionRuleIssueView[];
|
|
61
61
|
DISCUSSION_WORKFLOW_NAME: string;
|
|
62
|
+
mintNamespacePrefix(ns: CoreProtocolNamespaceView, peer: string): string;
|
|
62
63
|
}
|
|
63
|
-
export declare const CORE_VALUE_PORT_NAMES: readonly ["resolveAutonomousLoopPrompt", "loosenReasons", "combinePolicies", "createAllowDenyPolicy", "MCP_NAMESPACE", "RETIRED_TOOL_NAMES", "protocolOf", "ruleToolGrammarOf", "validatePermissionRules", "DISCUSSION_WORKFLOW_NAME"];
|
|
64
|
+
export declare const CORE_VALUE_PORT_NAMES: readonly ["resolveAutonomousLoopPrompt", "loosenReasons", "combinePolicies", "createAllowDenyPolicy", "MCP_NAMESPACE", "RETIRED_TOOL_NAMES", "protocolOf", "ruleToolGrammarOf", "validatePermissionRules", "DISCUSSION_WORKFLOW_NAME", "mintNamespacePrefix"];
|
|
64
65
|
export type CoreValuePortName = (typeof CORE_VALUE_PORT_NAMES)[number];
|
|
65
66
|
export declare function installCoreValuePorts(ports: Partial<CoreValuePorts> | null): () => void;
|
|
66
67
|
export declare function hasCoreValuePorts(): boolean;
|
|
@@ -76,3 +77,4 @@ export declare function protocolOf(name: string): CoreProtocolNamespaceView | un
|
|
|
76
77
|
export declare function ruleToolGrammarOf(toolName: string): 'command' | 'path' | undefined;
|
|
77
78
|
export declare function validatePermissionRules(rules: PermissionRuleView[], opts?: ValidatePermissionRulesOptionsView): PermissionRuleIssueView[] | undefined;
|
|
78
79
|
export declare function discussionWorkflowName(): string | undefined;
|
|
80
|
+
export declare function mintNamespacePrefix(ns: CoreProtocolNamespaceView, peer: string): string | undefined;
|
package/dist/coreValuePorts.js
CHANGED
|
@@ -9,6 +9,7 @@ export const CORE_VALUE_PORT_NAMES = Object.freeze([
|
|
|
9
9
|
'ruleToolGrammarOf',
|
|
10
10
|
'validatePermissionRules',
|
|
11
11
|
'DISCUSSION_WORKFLOW_NAME',
|
|
12
|
+
'mintNamespacePrefix',
|
|
12
13
|
]);
|
|
13
14
|
let installed = null;
|
|
14
15
|
export function installCoreValuePorts(ports) {
|
|
@@ -67,3 +68,7 @@ export function validatePermissionRules(rules, opts) {
|
|
|
67
68
|
export function discussionWorkflowName() {
|
|
68
69
|
return port('DISCUSSION_WORKFLOW_NAME');
|
|
69
70
|
}
|
|
71
|
+
export function mintNamespacePrefix(ns, peer) {
|
|
72
|
+
const fn = port('mintNamespacePrefix');
|
|
73
|
+
return fn === undefined ? undefined : fn(ns, peer);
|
|
74
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { corruptStoredRowContent, corruptStoredRowWhere } from './wireErrorTriage.js';
|
|
2
|
-
import { parkedResumeStartupContent, parkedResumeStartupFromError, resumePolicyBlockContent, resumePolicyBlockFromError, } from './resumeRefusalCopy.js';
|
|
3
|
-
import { decideParkMovedContent, decideParkMovedFromError } from './decideReceipt.js';
|
|
2
|
+
import { checkpointUnsupportedVersionContent, checkpointUnsupportedVersionFromError, parkedResumeStartupContent, parkedResumeStartupFromError, resumePolicyBlockContent, resumePolicyBlockFromError, } from './resumeRefusalCopy.js';
|
|
3
|
+
import { askGoneContent, askGoneFromError, decideParkMovedContent, decideParkMovedFromError } from './decideReceipt.js';
|
|
4
4
|
import { settingsPermissionBucketRefusalContent, settingsPermissionBucketRefusalFromError } from './wireRefusalCopy.js';
|
|
5
5
|
export function decideFailureNote(err, decision) {
|
|
6
6
|
const where = corruptStoredRowWhere(err);
|
|
@@ -8,9 +8,13 @@ export function decideFailureNote(err, decision) {
|
|
|
8
8
|
const startup = parkedResumeStartupFromError(err, decision);
|
|
9
9
|
const moved = decideParkMovedFromError(err);
|
|
10
10
|
const bucket = settingsPermissionBucketRefusalFromError(err);
|
|
11
|
+
const unsupported = checkpointUnsupportedVersionFromError(err);
|
|
12
|
+
const gone = askGoneFromError(err);
|
|
11
13
|
return ((where === undefined ? '' : ` — ${corruptStoredRowContent(where)}`) +
|
|
12
14
|
(fold === null ? '' : ` — ${resumePolicyBlockContent(fold)}`) +
|
|
13
15
|
(bucket === null ? '' : ` — ${settingsPermissionBucketRefusalContent(bucket)}`) +
|
|
14
16
|
(startup === null ? '' : ` — ${parkedResumeStartupContent(startup)}`) +
|
|
15
|
-
(moved === null ? '' : ` — ${decideParkMovedContent(moved)}`)
|
|
17
|
+
(moved === null ? '' : ` — ${decideParkMovedContent(moved)}`) +
|
|
18
|
+
(unsupported === null ? '' : ` — ${checkpointUnsupportedVersionContent(unsupported)}`) +
|
|
19
|
+
(gone === null ? '' : ` — ${askGoneContent(gone)}`));
|
|
16
20
|
}
|
package/dist/decideReceipt.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type GateOutcomeView } from './gateOutcome.js';
|
|
2
2
|
import { type ResumeReopenDetail } from './hitl/suspendedReopen.js';
|
|
3
|
+
import { type CrashConvergedRow } from './hitl/crashConverged.js';
|
|
3
4
|
export interface DecideReceiptView {
|
|
4
5
|
status?: string;
|
|
5
6
|
taskId?: string;
|
|
@@ -27,3 +28,11 @@ export interface DecideParkMovedDetail {
|
|
|
27
28
|
}
|
|
28
29
|
export declare function decideParkMovedFromError(e: unknown): DecideParkMovedDetail | null;
|
|
29
30
|
export declare function decideParkMovedContent(detail: Pick<DecideParkMovedDetail, 'code'>): string;
|
|
31
|
+
export interface AskGoneDetail {
|
|
32
|
+
code: 'gone.ask';
|
|
33
|
+
state?: 'VOID' | 'DENIED';
|
|
34
|
+
deniedReason?: string;
|
|
35
|
+
holderGone?: CrashConvergedRow['cause'];
|
|
36
|
+
}
|
|
37
|
+
export declare function askGoneFromError(e: unknown): AskGoneDetail | null;
|
|
38
|
+
export declare function askGoneContent(detail: AskGoneDetail): string;
|
package/dist/decideReceipt.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { gateOutcomeOf } from './gateOutcome.js';
|
|
2
2
|
import { resumeReopenFromError } from './hitl/suspendedReopen.js';
|
|
3
|
-
import { DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, isDecideParkMovedCode, } from './engineErrorCodes.js';
|
|
3
|
+
import { ASK_GONE, ASK_GONE_DENIED_WORD, DECIDE_CLAIM_LOST, DECIDE_GATE_MOVED, DECIDE_NOT_PARKED, DECIDE_WORKFLOW_HOST_UNKNOWN, DECIDE_WORKFLOW_LANE_CODES, DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED, isDecideParkMovedCode, } from './engineErrorCodes.js';
|
|
4
4
|
import { effectiveWireErrorCode } from './wireErrorTriage.js';
|
|
5
5
|
import { readErrorString } from './wireFailureShape.js';
|
|
6
|
+
import { isCrashConvergedCause } from './hitl/crashConverged.js';
|
|
6
7
|
const STATUS_RESUMING = 'resuming';
|
|
7
8
|
function str(v) {
|
|
8
9
|
return typeof v === 'string' && v.length > 0 ? v : undefined;
|
|
@@ -106,3 +107,63 @@ export function decideParkMovedContent(detail) {
|
|
|
106
107
|
const extra = code === DECIDE_CLAIM_LOST ? '; if this approval is still listed, wait a little before deciding it again' : '';
|
|
107
108
|
return `${what} · This decision was not applied — fetch the pending approvals again and decide from what is pending now${extra}`;
|
|
108
109
|
}
|
|
110
|
+
export function askGoneFromError(e) {
|
|
111
|
+
if (typeof e !== 'object' || e === null)
|
|
112
|
+
return null;
|
|
113
|
+
if (effectiveWireErrorCode(e) !== ASK_GONE)
|
|
114
|
+
return null;
|
|
115
|
+
const rawState = readErrorString(e, 'state');
|
|
116
|
+
const state = rawState === 'VOID' || rawState === 'DENIED' ? rawState : undefined;
|
|
117
|
+
const rawReason = readErrorString(e, 'deniedReason');
|
|
118
|
+
const deniedReason = rawReason === undefined || rawReason.length === 0
|
|
119
|
+
? undefined
|
|
120
|
+
: state === 'DENIED'
|
|
121
|
+
? rawReason === ASK_GONE_DENIED_WORD ? rawReason : undefined
|
|
122
|
+
: state === 'VOID' ? rawReason : undefined;
|
|
123
|
+
const holderGone = state === 'VOID' && isCrashConvergedCause(deniedReason) ? deniedReason : undefined;
|
|
124
|
+
return {
|
|
125
|
+
code: ASK_GONE,
|
|
126
|
+
...(state !== undefined ? { state } : {}),
|
|
127
|
+
...(deniedReason !== undefined ? { deniedReason } : {}),
|
|
128
|
+
...(holderGone !== undefined ? { holderGone } : {}),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export function askGoneContent(detail) {
|
|
132
|
+
let state;
|
|
133
|
+
let deniedReason;
|
|
134
|
+
let holderGone;
|
|
135
|
+
try {
|
|
136
|
+
state = detail.state;
|
|
137
|
+
deniedReason = detail.deniedReason;
|
|
138
|
+
holderGone = detail.holderGone;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
state = undefined;
|
|
142
|
+
deniedReason = undefined;
|
|
143
|
+
holderGone = undefined;
|
|
144
|
+
}
|
|
145
|
+
const st = state === 'VOID' || state === 'DENIED' ? state : undefined;
|
|
146
|
+
const safety = 'Your answer was not applied and nothing was run on it';
|
|
147
|
+
if (st === 'VOID' && (isCrashConvergedCause(holderGone) || isCrashConvergedCause(deniedReason))) {
|
|
148
|
+
return [
|
|
149
|
+
'The engine run that was waiting for this answer ended before the answer arrived',
|
|
150
|
+
safety,
|
|
151
|
+
'That run will not continue: submit the work again as a new task, and it will ask again',
|
|
152
|
+
].join(' · ');
|
|
153
|
+
}
|
|
154
|
+
if (st === 'DENIED') {
|
|
155
|
+
return ['This approval was closed without a human decision and the request was denied', safety, 'The denial stands; this approval cannot be reopened'].join(' · ');
|
|
156
|
+
}
|
|
157
|
+
if (st === 'VOID') {
|
|
158
|
+
return [
|
|
159
|
+
'This approval was withdrawn without a human decision',
|
|
160
|
+
safety,
|
|
161
|
+
'Nothing is waiting for this answer any more; if the work still needs this step, wait for it to be asked again or submit the work again',
|
|
162
|
+
].join(' · ');
|
|
163
|
+
}
|
|
164
|
+
return [
|
|
165
|
+
'This approval was closed without a human decision',
|
|
166
|
+
safety,
|
|
167
|
+
'It can no longer be decided; fetch the pending approvals again and decide from what is pending now',
|
|
168
|
+
].join(' · ');
|
|
169
|
+
}
|
|
@@ -14,4 +14,5 @@ export type DisableSkillsDeclaration = {
|
|
|
14
14
|
};
|
|
15
15
|
};
|
|
16
16
|
export declare function disableSkillsDeclaration(want: unknown, baseUrl: string | undefined): DisableSkillsDeclaration;
|
|
17
|
+
export declare function disableSkillsDeclarationSettled(want: boolean | null | undefined, baseUrl: string | undefined, withinMs: number): Promise<DisableSkillsDeclaration>;
|
|
17
18
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { engineCapState } from './engineCapsCache.js';
|
|
1
|
+
import { engineCapState, engineCapsSettled } from './engineCapsCache.js';
|
|
2
2
|
const KEY = 'disableSkills';
|
|
3
3
|
const shapeOf = (v) => {
|
|
4
4
|
try {
|
|
@@ -50,3 +50,10 @@ export function disableSkillsDeclaration(want, baseUrl) {
|
|
|
50
50
|
const cause = WITHHELD_CAUSE_OF[state];
|
|
51
51
|
return Object.freeze({ field: Object.freeze({}), withheld: Object.freeze({ cause, text: WITHHELD_TEXT[cause] }) });
|
|
52
52
|
}
|
|
53
|
+
export async function disableSkillsDeclarationSettled(want, baseUrl, withinMs) {
|
|
54
|
+
refuseBadDisableSkills(want, 'disableSkillsDeclarationSettled');
|
|
55
|
+
if (want !== true)
|
|
56
|
+
return disableSkillsDeclaration(want, baseUrl);
|
|
57
|
+
await engineCapsSettled(baseUrl, { withinMs: typeof withinMs === 'number' ? withinMs : 0 });
|
|
58
|
+
return disableSkillsDeclaration(want, baseUrl);
|
|
59
|
+
}
|