@sema-agent/client-core 0.107.0 → 0.109.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 +239 -0
- package/README.md +54 -36
- package/dist/adapt/arms.js +23 -8
- package/dist/adapt/textStream.d.ts +2 -0
- package/dist/adapt/textStream.js +37 -16
- package/dist/adapter/activeRunSelfHeal.d.ts +2 -0
- package/dist/adapter/activeRunSelfHeal.js +21 -4
- package/dist/adapter/downstream/eventToSdkMessage.js +2 -1
- package/dist/agentSession/engineAgentRegistryRead.js +2 -0
- package/dist/bashExitReading.d.ts +12 -0
- package/dist/bashExitReading.js +44 -0
- package/dist/checkpointRowVerdict.d.ts +6 -1
- package/dist/checkpointRowVerdict.js +30 -2
- package/dist/cloudConfigWireCaps.d.ts +10 -0
- package/dist/cloudConfigWireCaps.js +33 -0
- package/dist/compensations.js +1 -1
- package/dist/coreValuePorts.d.ts +17 -1
- package/dist/coreValuePorts.js +5 -0
- package/dist/decideReceipt.js +2 -1
- package/dist/engineAgentAbsence.d.ts +2 -0
- package/dist/engineAgentAbsence.js +28 -0
- package/dist/engineErrorCodes.d.ts +9 -0
- package/dist/engineErrorCodes.js +9 -0
- package/dist/engineHealthFacts.d.ts +17 -0
- package/dist/engineHealthFacts.js +42 -3
- package/dist/engineNoticeCodes.d.ts +147 -1
- package/dist/engineNoticeCodes.js +694 -57
- package/dist/engineTargetSeat.js +1 -0
- package/dist/errorSupplementRoles.js +6 -1
- package/dist/eventLeg.js +1 -1
- package/dist/executionLaneWords.js +2 -1
- package/dist/fleetTaskDesc.js +3 -3
- package/dist/gateOutcome.d.ts +10 -1
- package/dist/gateOutcome.js +48 -1
- package/dist/generated/engineFactTables.d.ts +2 -0
- package/dist/generated/engineFactTables.js +11 -0
- package/dist/generated/engineNoticeTables.js +6 -0
- package/dist/generated/settingsSchemaFns.d.ts +4 -2
- package/dist/generated/settingsSchemaFns.js +9 -3
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
- package/dist/generated/settingsSchemaMcpRequestEntry.js +9 -18
- package/dist/generated/settingsSchemaReservedMemberName.d.ts +1 -0
- package/dist/generated/settingsSchemaReservedMemberName.js +7 -0
- package/dist/generated/settingsSchemaTables.d.ts +2 -0
- package/dist/generated/settingsSchemaTables.js +10 -0
- package/dist/generated/settingsSchemaWireName.d.ts +1 -0
- package/dist/generated/settingsSchemaWireName.js +8 -0
- package/dist/headlessReconnectWire.js +12 -7
- package/dist/hitl/approvalAskers.d.ts +13 -0
- package/dist/hitl/approvalAskers.js +79 -0
- package/dist/hitl/approvalCardReasons.js +22 -4
- package/dist/hitl/approvalRequestFrameReading.d.ts +14 -0
- package/dist/hitl/approvalRequestFrameReading.js +79 -0
- package/dist/hitl/approvalResolution.d.ts +3 -0
- package/dist/hitl/approvalResolution.js +22 -4
- package/dist/hitl/approvalsFeed.js +4 -13
- package/dist/hitl/askParkRowRouting.js +10 -3
- package/dist/hitl/automaticAnswerVerdict.d.ts +5 -2
- package/dist/hitl/automaticAnswerVerdict.js +16 -2
- package/dist/hitl/decisionConflict.d.ts +2 -1
- package/dist/hitl/decisionConflict.js +4 -1
- package/dist/hitl/decisionRefusal.d.ts +1 -0
- package/dist/hitl/decisionRefusal.js +5 -2
- package/dist/hitl/decisionSend.js +2 -6
- package/dist/hitl/frameRouter.d.ts +3 -2
- package/dist/hitl/frameRouter.js +37 -7
- package/dist/hitl/gateLedger.d.ts +2 -0
- package/dist/hitl/gateLedger.js +3 -1
- package/dist/hitl/hitlBridge.d.ts +4 -0
- package/dist/hitl/hitlBridge.js +11 -8
- package/dist/hitl/livePendingAsk.js +17 -16
- package/dist/hitl/localAllowRule.js +2 -1
- package/dist/hitl/noAllowCause.d.ts +1 -1
- package/dist/hitl/noAllowCause.js +4 -2
- package/dist/hitl/parkExpiryJudgements.js +26 -1
- package/dist/hitl/parkOwnership.d.ts +2 -0
- package/dist/hitl/parkOwnership.js +48 -8
- package/dist/hitl/parkResolver.js +39 -30
- package/dist/hitl/parkRowBirthWait.d.ts +2 -0
- package/dist/hitl/parkRowBirthWait.js +8 -1
- package/dist/hitl/parkedUnresumable.d.ts +13 -0
- package/dist/hitl/parkedUnresumable.js +80 -0
- package/dist/hitl/permissionRuleScope.d.ts +4 -0
- package/dist/hitl/permissionRuleScope.js +31 -0
- package/dist/hitl/persistedRulesWire.d.ts +7 -1
- package/dist/hitl/persistedRulesWire.js +25 -8
- package/dist/hitl/planReviewWire.js +12 -16
- package/dist/hitl/policyDenyCause.d.ts +3 -0
- package/dist/hitl/policyDenyCause.js +16 -0
- package/dist/hitl/sessionAllowRoute.js +5 -4
- package/dist/hitl/sessionPolicyDeliverable.js +1 -1
- package/dist/hitl/standingRows.d.ts +1 -5
- package/dist/hitl/standingRows.js +15 -14
- package/dist/hitl/toolApprovalWire.d.ts +16 -4
- package/dist/hitl/toolApprovalWire.js +57 -17
- package/dist/hooksReaderGenerations.d.ts +1 -0
- package/dist/hooksReaderGenerations.js +12 -0
- package/dist/hooksWireCaps.js +12 -7
- package/dist/hostSettingsSource.js +2 -0
- package/dist/i18n/messages.en.d.ts +206 -1
- package/dist/i18n/messages.en.js +209 -4
- package/dist/i18n/messages.zh.js +214 -4
- package/dist/index.d.ts +35 -8
- package/dist/index.js +20 -5
- package/dist/liveModelCatalog.d.ts +4 -2
- package/dist/liveModelCatalog.js +164 -26
- package/dist/localEngineJudge.d.ts +75 -0
- package/dist/localEngineJudge.js +242 -0
- package/dist/localEngineOccupancy.d.ts +88 -0
- package/dist/localEngineOccupancy.js +269 -0
- package/dist/localEngineSeatReading.d.ts +29 -0
- package/dist/localEngineSeatReading.js +294 -0
- package/dist/localEngineSpawn.d.ts +113 -0
- package/dist/localEngineSpawn.js +486 -0
- package/dist/localEngineStep.d.ts +286 -0
- package/dist/localEngineStep.js +1086 -0
- package/dist/localEngineStopLadder.d.ts +29 -0
- package/dist/localEngineStopLadder.js +139 -0
- package/dist/localEngineSwapCard.d.ts +43 -0
- package/dist/localEngineSwapCard.js +205 -0
- package/dist/localEngineTiming.d.ts +8 -0
- package/dist/localEngineTiming.js +8 -0
- package/dist/mcpReconnect.js +12 -5
- package/dist/mcpWireCaps.js +2 -2
- package/dist/memoryEntriesWire.d.ts +1 -1
- package/dist/memoryEntriesWire.js +5 -0
- package/dist/model/catalogDefault.d.ts +25 -0
- package/dist/model/catalogDefault.js +44 -0
- package/dist/noticePresentation.d.ts +2 -0
- package/dist/noticePresentation.js +79 -1
- package/dist/ownKey.d.ts +10 -0
- package/dist/ownKey.js +15 -1
- package/dist/permissionWireCaps.d.ts +1 -0
- package/dist/permissionWireCaps.js +11 -0
- package/dist/pluginHooksWire.d.ts +5 -3
- package/dist/pluginHooksWire.js +116 -7
- package/dist/queuedDelivery.d.ts +1 -0
- package/dist/queuedDelivery.js +12 -0
- package/dist/resultFrameKeys.js +4 -2
- package/dist/resumeRefusalCopy.js +15 -8
- package/dist/ruleReadings.js +1 -1
- package/dist/runPermissionModeSwitch.d.ts +2 -1
- package/dist/runPermissionModeSwitch.js +16 -6
- package/dist/seam.d.ts +13 -2
- package/dist/seam.js +8 -1
- package/dist/seatContract.d.ts +103 -12
- package/dist/seatContract.js +344 -14
- package/dist/sessionBackground.js +2 -0
- package/dist/sessionEngine.d.ts +2 -1
- package/dist/sessionEngine.js +5 -0
- package/dist/settingsHooksSalvage.d.ts +5 -0
- package/dist/settingsHooksSalvage.js +54 -0
- package/dist/subagentContentStore.d.ts +12 -0
- package/dist/subagentContentStore.js +73 -12
- package/dist/supportFloor.js +2 -0
- package/dist/taskNotificationAdmission.d.ts +19 -0
- package/dist/taskNotificationAdmission.js +84 -0
- package/dist/toolResult.js +20 -6
- package/dist/webSearchWireCaps.js +9 -4
- package/dist/wireFailureShape.d.ts +20 -0
- package/dist/wireFailureShape.js +37 -6
- package/dist/wireRefusalCopy.d.ts +23 -2
- package/dist/wireRefusalCopy.js +93 -4
- package/docs/INTEGRATION-CLIENTS.md +1959 -15
- package/package.json +4 -4
|
@@ -69,6 +69,14 @@ function pickCut(src, limit, floor, boundary) {
|
|
|
69
69
|
return clause;
|
|
70
70
|
return word >= floor ? word : -1;
|
|
71
71
|
}
|
|
72
|
+
export function pairSafeCut(text, cut) {
|
|
73
|
+
if (cut <= 0 || cut >= text.length || text.charAt(cut) !== '\\' || text.charAt(cut - 1) !== '\\')
|
|
74
|
+
return cut;
|
|
75
|
+
let start = cut - 1;
|
|
76
|
+
while (start > 0 && text.charAt(start - 1) === '\\')
|
|
77
|
+
start--;
|
|
78
|
+
return (cut - start) % 2 === 1 ? cut - 1 : cut;
|
|
79
|
+
}
|
|
72
80
|
export function cutForDisplay(text, budget, opts) {
|
|
73
81
|
const src = typeof text === 'string' ? text : (guardedRead(() => String(text ?? '')) ?? '');
|
|
74
82
|
if (typeof budget !== 'number' || !Number.isFinite(budget))
|
|
@@ -83,9 +91,79 @@ export function cutForDisplay(text, budget, opts) {
|
|
|
83
91
|
const head = capDisplay(src, room, 'escape');
|
|
84
92
|
const floor = Math.ceil(head.length / CUT_KEEP_DIVISOR);
|
|
85
93
|
const at = pickCut(src, head.length, floor, boundary);
|
|
86
|
-
const kept = (at === -1 ? head :
|
|
94
|
+
const kept = src.slice(0, pairSafeCut(src, at === -1 ? head.length : at)).trimEnd();
|
|
87
95
|
return { shown: `${kept}${mark}`, truncated: true };
|
|
88
96
|
}
|
|
97
|
+
const ELISION_MARK = '…';
|
|
98
|
+
const ELISION_MIN_ROOM = 8;
|
|
99
|
+
const ELISION_SOFT_BACKOFF = 24;
|
|
100
|
+
const CLUSTER_EXTENDER = /^[\p{M}︀-️\u{1F3FB}-\u{1F3FF}\u{E0020}-\u{E007F}]/u;
|
|
101
|
+
const REGIONAL_INDICATOR = /^[\u{1F1E6}-\u{1F1FF}]$/u;
|
|
102
|
+
const RTL_LETTER = /^[\p{Script=Arabic}\p{Script=Hebrew}\p{Script=Syriac}\p{Script=Thaana}\p{Script=Nko}\p{Script=Samaritan}\p{Script=Mandaic}]$/u;
|
|
103
|
+
function codePointBefore(text, i) {
|
|
104
|
+
return text.slice(Math.max(0, i - 2), i).match(/[\s\S]$/u)?.[0] ?? '';
|
|
105
|
+
}
|
|
106
|
+
function codePointAfter(text, i) {
|
|
107
|
+
const cp = i < text.length ? text.codePointAt(i) : undefined;
|
|
108
|
+
return cp === undefined ? '' : String.fromCodePoint(cp);
|
|
109
|
+
}
|
|
110
|
+
function hardSafeBoundary(text, i) {
|
|
111
|
+
return i <= 0 || i >= text.length || (capDisplay(text, i, 'escape').length === i && pairSafeCut(text, i) === i);
|
|
112
|
+
}
|
|
113
|
+
function calmBoundary(text, i) {
|
|
114
|
+
const before = codePointBefore(text, i);
|
|
115
|
+
const after = codePointAfter(text, i);
|
|
116
|
+
if (before === '' || after === '')
|
|
117
|
+
return true;
|
|
118
|
+
if (before === '' || CLUSTER_EXTENDER.test(after))
|
|
119
|
+
return false;
|
|
120
|
+
if (RTL_LETTER.test(before) || RTL_LETTER.test(after))
|
|
121
|
+
return false;
|
|
122
|
+
if (REGIONAL_INDICATOR.test(before) && REGIONAL_INDICATOR.test(after)) {
|
|
123
|
+
let run = 0;
|
|
124
|
+
for (let j = i; j > 0;) {
|
|
125
|
+
const cp = codePointBefore(text, j);
|
|
126
|
+
if (!REGIONAL_INDICATOR.test(cp))
|
|
127
|
+
break;
|
|
128
|
+
run++;
|
|
129
|
+
j -= cp.length;
|
|
130
|
+
}
|
|
131
|
+
return run % 2 === 0;
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
function settleOnCalm(text, at, step) {
|
|
136
|
+
for (let k = 0; k <= ELISION_SOFT_BACKOFF; k++) {
|
|
137
|
+
const i = at + step * k;
|
|
138
|
+
if (i < 0 || i > text.length)
|
|
139
|
+
break;
|
|
140
|
+
if (hardSafeBoundary(text, i) && calmBoundary(text, i))
|
|
141
|
+
return i;
|
|
142
|
+
}
|
|
143
|
+
return at;
|
|
144
|
+
}
|
|
145
|
+
export function elideMiddleForDisplay(text, budget) {
|
|
146
|
+
const src = typeof text === 'string' ? text : (guardedRead(() => String(text ?? '')) ?? '');
|
|
147
|
+
if (typeof budget !== 'number' || !Number.isFinite(budget))
|
|
148
|
+
return src;
|
|
149
|
+
const limit = Math.max(0, Math.floor(budget));
|
|
150
|
+
if (src.length <= limit)
|
|
151
|
+
return src;
|
|
152
|
+
const room = limit - ELISION_MARK.length;
|
|
153
|
+
if (room < ELISION_MIN_ROOM)
|
|
154
|
+
return cutForDisplay(src, limit).shown;
|
|
155
|
+
const headRoom = Math.ceil(room / 2);
|
|
156
|
+
const tailRoom = room - headRoom;
|
|
157
|
+
let head = headRoom;
|
|
158
|
+
while (head > 0 && !hardSafeBoundary(src, head))
|
|
159
|
+
head--;
|
|
160
|
+
let tail = src.length - tailRoom;
|
|
161
|
+
while (tail < src.length && !hardSafeBoundary(src, tail))
|
|
162
|
+
tail++;
|
|
163
|
+
head = settleOnCalm(src, head, -1);
|
|
164
|
+
tail = settleOnCalm(src, tail, 1);
|
|
165
|
+
return `${src.slice(0, head).trimEnd()}${ELISION_MARK}${src.slice(tail)}`;
|
|
166
|
+
}
|
|
89
167
|
export const NOTICE_SEAT_CLASS = Object.freeze({
|
|
90
168
|
user: Object.freeze({ present: 'persistent+hint', unknown: 'persistent+hint', absent: 'persistent' }),
|
|
91
169
|
operator: Object.freeze({ present: 'transient', unknown: 'transient', absent: 'diagnostic' }),
|
package/dist/ownKey.d.ts
CHANGED
|
@@ -32,8 +32,18 @@ export interface HumanInputAttachmentView {
|
|
|
32
32
|
kind?: string;
|
|
33
33
|
outcome: string;
|
|
34
34
|
label?: string;
|
|
35
|
+
declinedBy?: HumanInputAttachmentDeclinedByView;
|
|
36
|
+
}
|
|
37
|
+
export interface HumanInputAttachmentDeclinedByView {
|
|
38
|
+
kind: 'extension';
|
|
39
|
+
name: string;
|
|
35
40
|
}
|
|
36
41
|
export declare function humanInputAttachmentsOf(frame: {} | null | undefined): HumanInputAttachmentView[] | undefined;
|
|
42
|
+
export interface HumanInputAuthorKeys {
|
|
43
|
+
author?: string;
|
|
44
|
+
extension?: string;
|
|
45
|
+
}
|
|
46
|
+
export declare function humanInputAuthorKeys(frame: {} | null | undefined): HumanInputAuthorKeys;
|
|
37
47
|
export declare function markMcpSectionDroppedNamedRows(rows: object, dropped: ReadonlyMap<string, number>): void;
|
|
38
48
|
export declare function mcpSectionDroppedNamedRowsOf(rows: object | null | undefined, name: string): number;
|
|
39
49
|
export interface PromptManifestSectionRow {
|
package/dist/ownKey.js
CHANGED
|
@@ -175,7 +175,14 @@ export function humanInputAttachmentsOf(frame) {
|
|
|
175
175
|
return undefined;
|
|
176
176
|
const kind = readOwnDataNonEmptyString(r, 'kind');
|
|
177
177
|
const label = readOwnDataNonEmptyString(r, 'label');
|
|
178
|
-
|
|
178
|
+
const declinedBy = guardedRead(() => {
|
|
179
|
+
const d = readOwnDataValue(r, 'declinedBy');
|
|
180
|
+
if (typeof d !== 'object' || d === null || Array.isArray(d))
|
|
181
|
+
return undefined;
|
|
182
|
+
const name = readOwnDataNonEmptyString(d, 'name');
|
|
183
|
+
return readOwnDataValue(d, 'kind') === 'extension' && name !== undefined ? { kind: 'extension', name } : undefined;
|
|
184
|
+
});
|
|
185
|
+
return { ordinal, ...(kind !== undefined ? { kind } : {}), outcome, ...(label !== undefined ? { label } : {}), ...(declinedBy !== undefined ? { declinedBy } : {}) };
|
|
179
186
|
});
|
|
180
187
|
if (row !== undefined)
|
|
181
188
|
appendOwnElement(rows, row);
|
|
@@ -186,6 +193,13 @@ export function humanInputAttachmentsOf(frame) {
|
|
|
186
193
|
return undefined;
|
|
187
194
|
}
|
|
188
195
|
}
|
|
196
|
+
export function humanInputAuthorKeys(frame) {
|
|
197
|
+
if (typeof frame !== 'object' || frame === null || Array.isArray(frame))
|
|
198
|
+
return {};
|
|
199
|
+
const author = guardedRead(() => readOwnDataNonEmptyString(frame, 'author'));
|
|
200
|
+
const extension = guardedRead(() => readOwnDataNonEmptyString(frame, 'extension'));
|
|
201
|
+
return { ...(author !== undefined ? { author } : {}), ...(extension !== undefined ? { extension } : {}) };
|
|
202
|
+
}
|
|
189
203
|
const DROPPED_NAMED_ROWS = Symbol.for('@sema-agent/client-core/mcpSectionDroppedNamedRows');
|
|
190
204
|
export function markMcpSectionDroppedNamedRows(rows, dropped) {
|
|
191
205
|
if (dropped.size === 0)
|
|
@@ -4,6 +4,7 @@ export type { PermissionMode };
|
|
|
4
4
|
export interface PermissionModeField {
|
|
5
5
|
permissionMode?: PermissionMode;
|
|
6
6
|
}
|
|
7
|
+
export declare function permissionModeTitle(word: string): string | undefined;
|
|
7
8
|
export declare function permissionModeField(mode: string | undefined, opts?: {
|
|
8
9
|
stampDefault?: boolean;
|
|
9
10
|
permissionModes?: PermissionModesReading | undefined;
|
|
@@ -2,6 +2,17 @@ import { PERMISSION_MODE_WORDS } from './taskRequestWords.js';
|
|
|
2
2
|
import { permissionModeAdmitted } from './permissionModesCapability.js';
|
|
3
3
|
const _permissionModePin = true;
|
|
4
4
|
void _permissionModePin;
|
|
5
|
+
const PERMISSION_MODE_TITLES = {
|
|
6
|
+
default: 'Manual',
|
|
7
|
+
acceptEdits: 'Accept edits',
|
|
8
|
+
plan: 'Plan',
|
|
9
|
+
auto: 'Auto',
|
|
10
|
+
bypassPermissions: 'Bypass Permissions',
|
|
11
|
+
dontAsk: "Don't Ask",
|
|
12
|
+
};
|
|
13
|
+
export function permissionModeTitle(word) {
|
|
14
|
+
return typeof word === 'string' && Object.hasOwn(PERMISSION_MODE_TITLES, word) ? PERMISSION_MODE_TITLES[word] : undefined;
|
|
15
|
+
}
|
|
5
16
|
const BIT_GATED_MODE = 'dontAsk';
|
|
6
17
|
const KNOWN = new Set(PERMISSION_MODE_WORDS.filter((w) => w !== BIT_GATED_MODE));
|
|
7
18
|
export function permissionModeField(mode, opts) {
|
|
@@ -8,11 +8,11 @@ export declare const ENGINE_FIRED_HOOK_EVENTS: readonly ["PreToolUse", "PostTool
|
|
|
8
8
|
export type EngineFiredHookEvent = (typeof ENGINE_FIRED_HOOK_EVENTS)[number];
|
|
9
9
|
export declare const PLUGIN_HOOK_DISPOSITIONS: readonly ["engine", "shell", "not_run"];
|
|
10
10
|
export type PluginHookDisposition = (typeof PLUGIN_HOOK_DISPOSITIONS)[number];
|
|
11
|
-
export declare const PLUGIN_HOOK_REASONS: readonly ["projected", "shell_event", "no_executor", "engine_not_local", "engine_locality_unknown", "engine_capability_absent", "engine_capability_unknown", "not_command", "sensitive_options", "engine_limit", "shell_form_user_config", "user_config_unset", "malformed_entry", "engine_hooks_off", "engine_hooks_unknown", "engine_type_skipped", "engine_llm_limit", "engine_unconfirmed", "engine_elsewhere", "hooks_module", "scope_unsupported", "source_incomplete", "compaction_local_fallback"];
|
|
11
|
+
export declare const PLUGIN_HOOK_REASONS: readonly ["projected", "shell_event", "no_executor", "engine_not_local", "engine_locality_unknown", "engine_capability_absent", "engine_capability_unknown", "not_command", "sensitive_options", "engine_limit", "shell_form_user_config", "user_config_unset", "malformed_entry", "engine_hooks_off", "engine_hooks_unknown", "engine_type_skipped", "engine_llm_limit", "engine_unconfirmed", "engine_elsewhere", "hooks_module", "scope_unsupported", "source_incomplete", "compaction_local_fallback", "key_not_read", "source_not_authored"];
|
|
12
12
|
export type PluginHookReason = (typeof PLUGIN_HOOK_REASONS)[number];
|
|
13
13
|
export declare const PLUGIN_HOOK_EXCLUSION_REASONS: readonly ["workspace_untrusted", "governance_unreadable", "policy_disable_all", "startup_mode", "managed_plugins_only", "prompt_not_user_authored"];
|
|
14
14
|
export type PluginHookExclusionReason = (typeof PLUGIN_HOOK_EXCLUSION_REASONS)[number];
|
|
15
|
-
export declare const SETTINGS_HOOK_DROP_REASONS: readonly ["exec_form_unsupported", "mcp_tool_unsupported"];
|
|
15
|
+
export declare const SETTINGS_HOOK_DROP_REASONS: readonly ["exec_form_unsupported", "mcp_tool_unsupported", "key_not_read", "source_not_authored"];
|
|
16
16
|
export type SettingsHookDropReason = (typeof SETTINGS_HOOK_DROP_REASONS)[number];
|
|
17
17
|
export type HookSettingsSource = 'policySettings' | 'userSettings' | 'projectSettings' | 'localSettings' | 'flagSettings';
|
|
18
18
|
export interface PluginHookKey {
|
|
@@ -36,6 +36,7 @@ export interface SettingsHookDrop {
|
|
|
36
36
|
readonly hookIndex: number;
|
|
37
37
|
readonly reason: SettingsHookDropReason;
|
|
38
38
|
readonly notRun: boolean;
|
|
39
|
+
readonly unreadKeys?: readonly (readonly (string | number)[])[];
|
|
39
40
|
}
|
|
40
41
|
export interface SettingsHookVerdict {
|
|
41
42
|
readonly source: HookSettingsSource;
|
|
@@ -147,6 +148,7 @@ export interface PluginHookDecisionInput {
|
|
|
147
148
|
readonly promptAuthoredByUser: boolean;
|
|
148
149
|
readonly occupied: ReadonlyMap<string, EventOccupancy>;
|
|
149
150
|
readonly suppressedLocally?: ReadonlySet<string>;
|
|
151
|
+
readonly readerNotRead: readonly string[];
|
|
150
152
|
}
|
|
151
153
|
export interface PluginHookDecision {
|
|
152
154
|
readonly verdicts: readonly PluginHookVerdict[];
|
|
@@ -166,7 +168,7 @@ export declare function decideSessionHooks(input: SessionHookDecisionInput): {
|
|
|
166
168
|
readonly verdicts: readonly SessionHookVerdict[];
|
|
167
169
|
readonly unreadable: number;
|
|
168
170
|
};
|
|
169
|
-
export declare function filterSettingsHookGroups(source: HookSettingsSource, event: string, groups: readonly WireHookGroup[], execFormCapable: boolean, shellRunsType: (type: string | undefined) => boolean, judge: SettingsHookJudge, mask?: HooksSalvageMask): SettingsHookFilterResult;
|
|
171
|
+
export declare function filterSettingsHookGroups(source: HookSettingsSource, event: string, groups: readonly WireHookGroup[], execFormCapable: boolean, shellRunsType: (type: string | undefined) => boolean, judge: SettingsHookJudge, readerNotRead: readonly string[], mask?: HooksSalvageMask): SettingsHookFilterResult;
|
|
170
172
|
export interface SettingsHookFilterResult {
|
|
171
173
|
readonly groups: WireHookGroup[];
|
|
172
174
|
readonly drops: SettingsHookDrop[];
|
package/dist/pluginHooksWire.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { displayUntrusted } from './displayUntrusted.js';
|
|
2
|
-
import { appendOwnElement } from './ownKey.js';
|
|
2
|
+
import { appendOwnElement, readOwnDataValue } from './ownKey.js';
|
|
3
3
|
import { msg, renderMessage } from './i18n/translate.js';
|
|
4
4
|
import { SETTINGS_ENGINE_OWNED_HOOK_EVENTS } from './generated/settingsSchemaTables.js';
|
|
5
|
-
import { HOOK_SETTINGS_SOURCE_TEXT, hooksSalvageMaskOf, salvageSettingsHooksEntries, } from './settingsHooksSalvage.js';
|
|
5
|
+
import { HOOK_SETTINGS_SOURCE_TEXT, hooksEntryUnreadKeys, hooksGroupAuthoredSource, hooksGroupUnreadKeys, hooksKeyCoordinateText, hooksSalvageMaskOf, salvageSettingsHooksEntries, } from './settingsHooksSalvage.js';
|
|
6
6
|
export const ENGINE_FIRED_HOOK_EVENTS = SETTINGS_ENGINE_OWNED_HOOK_EVENTS;
|
|
7
7
|
export const PLUGIN_HOOK_DISPOSITIONS = ['engine', 'shell', 'not_run'];
|
|
8
8
|
export const PLUGIN_HOOK_REASONS = [
|
|
@@ -29,6 +29,8 @@ export const PLUGIN_HOOK_REASONS = [
|
|
|
29
29
|
'scope_unsupported',
|
|
30
30
|
'source_incomplete',
|
|
31
31
|
'compaction_local_fallback',
|
|
32
|
+
'key_not_read',
|
|
33
|
+
'source_not_authored',
|
|
32
34
|
];
|
|
33
35
|
export const PLUGIN_HOOK_EXCLUSION_REASONS = [
|
|
34
36
|
'workspace_untrusted',
|
|
@@ -38,7 +40,7 @@ export const PLUGIN_HOOK_EXCLUSION_REASONS = [
|
|
|
38
40
|
'managed_plugins_only',
|
|
39
41
|
'prompt_not_user_authored',
|
|
40
42
|
];
|
|
41
|
-
export const SETTINGS_HOOK_DROP_REASONS = ['exec_form_unsupported', 'mcp_tool_unsupported'];
|
|
43
|
+
export const SETTINGS_HOOK_DROP_REASONS = ['exec_form_unsupported', 'mcp_tool_unsupported', 'key_not_read', 'source_not_authored'];
|
|
42
44
|
export function hooksWirePlanShapeOf(v) {
|
|
43
45
|
try {
|
|
44
46
|
if (typeof v !== 'object' || v === null || Array.isArray(v))
|
|
@@ -257,7 +259,9 @@ export function decidePluginHooks(input) {
|
|
|
257
259
|
unreadable++;
|
|
258
260
|
return;
|
|
259
261
|
}
|
|
260
|
-
;
|
|
262
|
+
const authored = hooksGroupAuthoredSource(group);
|
|
263
|
+
const groupUnread = authored === 'unreadable' ? undefined : hooksGroupUnreadKeys(event, group);
|
|
264
|
+
const groupSourceAuthored = authored === 'unreadable' || (authored === 'present' && groupUnread !== undefined);
|
|
261
265
|
group.hooks.forEach((entry, hookIndex) => {
|
|
262
266
|
const key = { pluginId, pluginName, event, groupIndex, hookIndex };
|
|
263
267
|
if (input.exclusion !== undefined) {
|
|
@@ -317,6 +321,15 @@ export function decidePluginHooks(input) {
|
|
|
317
321
|
appendOwnElement(verdicts, { ...key, disposition: ex.disposition, reason: ex.reason });
|
|
318
322
|
return;
|
|
319
323
|
}
|
|
324
|
+
const entryUnread = isRecord(entry) ? hooksEntryUnreadKeys(event, entry, input.readerNotRead) : undefined;
|
|
325
|
+
if (groupSourceAuthored && (authored === 'unreadable' || entryUnread !== undefined)) {
|
|
326
|
+
appendOwnElement(verdicts, { ...key, ...fallback(event, entryType, 'source_not_authored') });
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (entryUnread !== undefined && ((groupUnread?.length ?? 0) > 0 || entryUnread.length > 0)) {
|
|
330
|
+
appendOwnElement(verdicts, { ...key, ...fallback(event, entryType, 'key_not_read') });
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
320
333
|
const plugin = { name: src.name, root: src.root, dataDir: src.dataDir };
|
|
321
334
|
const options = projectedOptions(src.options);
|
|
322
335
|
if (options !== undefined)
|
|
@@ -454,7 +467,18 @@ function carriesArgs(entry) {
|
|
|
454
467
|
}
|
|
455
468
|
return true;
|
|
456
469
|
}
|
|
457
|
-
|
|
470
|
+
function unreadKeyPathsOf(event, groupIndex, hookIndex, groupUnread, entryUnread) {
|
|
471
|
+
if (entryUnread === undefined)
|
|
472
|
+
return Object.freeze([]);
|
|
473
|
+
const out = [];
|
|
474
|
+
for (const k of groupUnread)
|
|
475
|
+
appendOwnElement(out, Object.freeze(['hooks', event, groupIndex, k]));
|
|
476
|
+
for (const k of entryUnread)
|
|
477
|
+
if (k !== 'plugin')
|
|
478
|
+
appendOwnElement(out, Object.freeze(['hooks', event, groupIndex, 'hooks', hookIndex, k]));
|
|
479
|
+
return Object.freeze(out);
|
|
480
|
+
}
|
|
481
|
+
export function filterSettingsHookGroups(source, event, groups, execFormCapable, shellRunsType, judge, readerNotRead, mask) {
|
|
458
482
|
const drops = [];
|
|
459
483
|
const verdicts = [];
|
|
460
484
|
const excluded = [];
|
|
@@ -470,20 +494,35 @@ export function filterSettingsHookGroups(source, event, groups, execFormCapable,
|
|
|
470
494
|
}
|
|
471
495
|
const kept = [];
|
|
472
496
|
let changed = false;
|
|
497
|
+
const authored = hooksGroupAuthoredSource(group);
|
|
498
|
+
const groupUnread = authored === 'unreadable' ? undefined : hooksGroupUnreadKeys(event, group);
|
|
499
|
+
const groupSourceAuthored = authored === 'unreadable' || (authored === 'present' && groupUnread !== undefined);
|
|
473
500
|
group.hooks.forEach((entry, hookIndex) => {
|
|
474
501
|
if (mask !== undefined && mask.entryDropped(event, groupIndex, hookIndex)) {
|
|
475
502
|
changed = true;
|
|
476
503
|
return;
|
|
477
504
|
}
|
|
478
|
-
const
|
|
505
|
+
const earlier = !isRecord(entry)
|
|
479
506
|
? undefined
|
|
480
507
|
: entry.type === 'mcp_tool'
|
|
481
508
|
? 'mcp_tool_unsupported'
|
|
482
509
|
: entry.type === 'command' && carriesArgs(entry) && !execFormCapable
|
|
483
510
|
? 'exec_form_unsupported'
|
|
484
511
|
: undefined;
|
|
512
|
+
const entryUnread = earlier === undefined && isRecord(entry) ? hooksEntryUnreadKeys(event, entry, readerNotRead) : undefined;
|
|
513
|
+
const sourceNotAuthored = earlier === undefined && groupSourceAuthored && (authored === 'unreadable' || entryUnread !== undefined);
|
|
514
|
+
const unreadKeys = earlier === undefined && !sourceNotAuthored ? unreadKeyPathsOf(event, groupIndex, hookIndex, groupUnread ?? [], entryUnread) : [];
|
|
515
|
+
const reason = earlier ?? (sourceNotAuthored ? 'source_not_authored' : unreadKeys.length > 0 ? 'key_not_read' : undefined);
|
|
485
516
|
if (reason !== undefined) {
|
|
486
|
-
appendOwnElement(drops, {
|
|
517
|
+
appendOwnElement(drops, {
|
|
518
|
+
source,
|
|
519
|
+
event,
|
|
520
|
+
groupIndex,
|
|
521
|
+
hookIndex,
|
|
522
|
+
reason,
|
|
523
|
+
notRun: engineEvent && !shellRunsType(isRecord(entry) && typeof entry.type === 'string' ? entry.type : undefined),
|
|
524
|
+
...(reason === 'key_not_read' ? { unreadKeys } : {}),
|
|
525
|
+
});
|
|
487
526
|
changed = true;
|
|
488
527
|
return;
|
|
489
528
|
}
|
|
@@ -510,6 +549,8 @@ export function filterSettingsHookGroups(source, event, groups, execFormCapable,
|
|
|
510
549
|
}
|
|
511
550
|
appendOwnElement(kept, entry);
|
|
512
551
|
});
|
|
552
|
+
if (((groupUnread?.length ?? 0) > 0 || groupSourceAuthored) && kept.length === 0)
|
|
553
|
+
changed = true;
|
|
513
554
|
if (!changed)
|
|
514
555
|
appendOwnElement(out, group);
|
|
515
556
|
else if (kept.length > 0)
|
|
@@ -832,10 +873,14 @@ const REASON_TEXT = {
|
|
|
832
873
|
scope_unsupported: 'hooks registered for a skill, an agent or by the host application are not sent to the engine, and this client does not run this event',
|
|
833
874
|
source_incomplete: 'the plugin was reported without its id, name, root folder or data folder',
|
|
834
875
|
compaction_local_fallback: renderMessage(msg('config.hooks.plan.reason.compactionLocalFallback')),
|
|
876
|
+
key_not_read: renderMessage(msg('config.hooks.plan.reason.keyNotRead')),
|
|
877
|
+
source_not_authored: renderMessage(msg('config.hooks.plan.reason.sourceNotAuthored')),
|
|
835
878
|
};
|
|
836
879
|
const DROP_TEXT = {
|
|
837
880
|
exec_form_unsupported: 'exec-form hooks (with "args") are sent to the engine only once it reports support for them',
|
|
838
881
|
mcp_tool_unsupported: 'MCP tool hooks are not supported by the engine',
|
|
882
|
+
key_not_read: REASON_TEXT.key_not_read,
|
|
883
|
+
source_not_authored: REASON_TEXT.source_not_authored,
|
|
839
884
|
};
|
|
840
885
|
const SOURCE_TEXT = HOOK_SETTINGS_SOURCE_TEXT;
|
|
841
886
|
export function pluginHookReasonText(reason) {
|
|
@@ -898,8 +943,52 @@ function capNoticeLabel(s) {
|
|
|
898
943
|
}
|
|
899
944
|
return `${s.slice(0, end)}…`;
|
|
900
945
|
}
|
|
946
|
+
const KEY_NOT_READ_SHOWN = 3;
|
|
947
|
+
function unreadPathsOfRow(d) {
|
|
948
|
+
const raw = d.unreadKeys;
|
|
949
|
+
if (!Array.isArray(raw))
|
|
950
|
+
return [];
|
|
951
|
+
return raw.filter((p) => Array.isArray(p) && p.length > 0 && p.every((x) => typeof x === 'string' || typeof x === 'number'));
|
|
952
|
+
}
|
|
953
|
+
function namedPathsOfRow(d) {
|
|
954
|
+
switch (d.reason) {
|
|
955
|
+
case 'key_not_read':
|
|
956
|
+
return unreadPathsOfRow(d);
|
|
957
|
+
case 'source_not_authored':
|
|
958
|
+
return typeof d.event === 'string' && Number.isInteger(d.groupIndex) && d.groupIndex >= 0 ? [['hooks', d.event, d.groupIndex, 'source']] : [];
|
|
959
|
+
case 'exec_form_unsupported':
|
|
960
|
+
case 'mcp_tool_unsupported':
|
|
961
|
+
return [];
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
function namedCoordinatesText(coordinates) {
|
|
965
|
+
const shown = coordinates.slice(0, KEY_NOT_READ_SHOWN).join(', ');
|
|
966
|
+
return coordinates.length > KEY_NOT_READ_SHOWN ? renderMessage(msg('config.hooks.plan.keyNotRead.more', { shown, rest: coordinates.length - KEY_NOT_READ_SHOWN })) : shown;
|
|
967
|
+
}
|
|
968
|
+
function keyNotReadLine(source, row) {
|
|
969
|
+
const events = row.events.map((e) => noticeLabel(e)).join(', ');
|
|
970
|
+
const hooks = `${row.count} ${events} ${row.count === 1 ? 'hook' : 'hooks'}`;
|
|
971
|
+
const coordinates = namedCoordinatesText(row.coordinates);
|
|
972
|
+
const line = renderMessage(msg(row.coordinates.length === 1 ? 'config.hooks.plan.keyNotRead.oneKey' : 'config.hooks.plan.keyNotRead.manyKeys', { layer: SOURCE_TEXT[source], hooks, coordinates }));
|
|
973
|
+
return row.onFailure ? renderMessage(msg('config.hooks.plan.keyNotRead.withOnFailure', { line })) : line;
|
|
974
|
+
}
|
|
975
|
+
function sourceNotAuthoredLine(source, row) {
|
|
976
|
+
const events = row.events.map((e) => noticeLabel(e)).join(', ');
|
|
977
|
+
const hooks = `${row.count} ${events} ${row.count === 1 ? 'hook' : 'hooks'}`;
|
|
978
|
+
const coordinates = namedCoordinatesText(row.coordinates);
|
|
979
|
+
return renderMessage(msg(row.coordinates.length === 1 ? 'config.hooks.plan.sourceNotAuthored.oneKey' : 'config.hooks.plan.sourceNotAuthored.manyKeys', { layer: SOURCE_TEXT[source], hooks, coordinates }));
|
|
980
|
+
}
|
|
901
981
|
export function hooksNotRunNotice(plan) {
|
|
902
982
|
const lines = [];
|
|
983
|
+
let closedBy;
|
|
984
|
+
try {
|
|
985
|
+
closedBy = isRecord(plan) ? readOwnDataValue(plan, 'closedBy') : undefined;
|
|
986
|
+
}
|
|
987
|
+
catch {
|
|
988
|
+
closedBy = undefined;
|
|
989
|
+
}
|
|
990
|
+
if (closedBy === 'policy_disable_all')
|
|
991
|
+
appendOwnElement(lines, renderMessage(msg('config.hooks.plan.disableAllHooks')));
|
|
903
992
|
const byPlugin = new Map();
|
|
904
993
|
for (const v of plan.verdicts) {
|
|
905
994
|
if (v.disposition !== 'not_run')
|
|
@@ -916,9 +1005,27 @@ export function hooksNotRunNotice(plan) {
|
|
|
916
1005
|
appendOwnElement(lines, `Plugin "${noticeLabel(row.name) || '(unnamed)'}": ${events} ${row.count === 1 ? 'hook' : 'hooks'} will not run — ${pluginHookReasonText(row.reason)}.`);
|
|
917
1006
|
}
|
|
918
1007
|
const bySource = new Map();
|
|
1008
|
+
const namedBySource = new Map();
|
|
919
1009
|
for (const d of plan.settingsDropped) {
|
|
920
1010
|
if (!d.notRun)
|
|
921
1011
|
continue;
|
|
1012
|
+
const named = d.reason === 'key_not_read' || d.reason === 'source_not_authored' ? namedPathsOfRow(d) : [];
|
|
1013
|
+
if (named.length > 0 && (d.reason === 'key_not_read' || d.reason === 'source_not_authored')) {
|
|
1014
|
+
const nk = `${d.source}\u0000${d.reason}`;
|
|
1015
|
+
const row = namedBySource.get(nk) ?? { source: d.source, reason: d.reason, events: [], count: 0, coordinates: [], onFailure: false };
|
|
1016
|
+
if (!row.events.includes(d.event))
|
|
1017
|
+
appendOwnElement(row.events, d.event);
|
|
1018
|
+
row.count++;
|
|
1019
|
+
for (const path of named) {
|
|
1020
|
+
const c = hooksKeyCoordinateText(path);
|
|
1021
|
+
if (!row.coordinates.includes(c))
|
|
1022
|
+
appendOwnElement(row.coordinates, c);
|
|
1023
|
+
if (d.reason === 'key_not_read' && path[path.length - 1] === 'onFailure')
|
|
1024
|
+
row.onFailure = true;
|
|
1025
|
+
}
|
|
1026
|
+
namedBySource.set(nk, row);
|
|
1027
|
+
continue;
|
|
1028
|
+
}
|
|
922
1029
|
const k = `${d.source}\u0000${d.reason}`;
|
|
923
1030
|
const row = bySource.get(k) ?? { source: d.source, reason: d.reason, events: [], count: 0 };
|
|
924
1031
|
if (!row.events.includes(d.event))
|
|
@@ -930,6 +1037,8 @@ export function hooksNotRunNotice(plan) {
|
|
|
930
1037
|
const events = row.events.map((e) => noticeLabel(e)).join(', ');
|
|
931
1038
|
appendOwnElement(lines, `${SOURCE_TEXT[row.source]}: ${events} ${row.count === 1 ? 'hook' : 'hooks'} will not run — ${settingsHookDropText(row.reason)}.`);
|
|
932
1039
|
}
|
|
1040
|
+
for (const row of namedBySource.values())
|
|
1041
|
+
appendOwnElement(lines, row.reason === 'key_not_read' ? keyNotReadLine(row.source, row) : sourceNotAuthoredLine(row.source, row));
|
|
933
1042
|
const settingsVerdicts = plan.settingsVerdicts;
|
|
934
1043
|
const byVerdict = new Map();
|
|
935
1044
|
for (const raw of Array.isArray(settingsVerdicts) ? settingsVerdicts : []) {
|
package/dist/queuedDelivery.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface QueueEntry {
|
|
|
15
15
|
readonly intentKey?: string;
|
|
16
16
|
readonly screening?: 'pending' | 'result';
|
|
17
17
|
readonly upsExecutor?: 'shell' | 'engine' | 'unknown' | 'none';
|
|
18
|
+
readonly _sema_task_notification?: {} | null | undefined;
|
|
18
19
|
}
|
|
19
20
|
export type QueuedHoldReason = 'barrier' | 'share_incomplete' | 'not_steerable' | 'in_flight' | 'attempted' | 'no_run';
|
|
20
21
|
export interface QueuedDeliveryPlan {
|
package/dist/queuedDelivery.js
CHANGED
|
@@ -3,6 +3,7 @@ import { imageVisionOf } from './liveModelCatalog.js';
|
|
|
3
3
|
import { userPromptSubmitExecutorOf } from './pluginHooksWire.js';
|
|
4
4
|
import { observedUserAttachmentSeat } from './userAttachmentSeat.js';
|
|
5
5
|
import { guardedRead, readOwnDataValue } from './ownKey.js';
|
|
6
|
+
import { taskNotificationOf } from './notifications.js';
|
|
6
7
|
const own = (o, key) => guardedRead(() => readOwnDataValue(o, key));
|
|
7
8
|
const str = (o, key) => {
|
|
8
9
|
const v = own(o, key);
|
|
@@ -43,6 +44,8 @@ export function batchCompatible(head, follower, plan) {
|
|
|
43
44
|
return false;
|
|
44
45
|
if (typeof head !== 'object' || head === null || typeof follower !== 'object' || follower === null)
|
|
45
46
|
return false;
|
|
47
|
+
if (carriesCompletionIdentity(head) || carriesCompletionIdentity(follower))
|
|
48
|
+
return false;
|
|
46
49
|
const executor = userPromptSubmitExecutorOf(plan);
|
|
47
50
|
if (executor === 'engine' || executor === 'unknown')
|
|
48
51
|
return false;
|
|
@@ -84,6 +87,15 @@ export function batchCompatible(head, follower, plan) {
|
|
|
84
87
|
return false;
|
|
85
88
|
}
|
|
86
89
|
}
|
|
90
|
+
function carriesCompletionIdentity(e) {
|
|
91
|
+
const slot = peek(e, '_sema_task_notification');
|
|
92
|
+
if (slot === undefined || slot === null)
|
|
93
|
+
return false;
|
|
94
|
+
if (slot === UNREADABLE)
|
|
95
|
+
return true;
|
|
96
|
+
const fact = taskNotificationOf({ _sema_task_notification: slot });
|
|
97
|
+
return fact === undefined || fact.completionId !== undefined;
|
|
98
|
+
}
|
|
87
99
|
function upsExecutorWordOk(v) {
|
|
88
100
|
return v === undefined || v === 'shell' || v === 'engine' || v === 'unknown' || v === 'none';
|
|
89
101
|
}
|
package/dist/resultFrameKeys.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFrameStringKey, readFrameTrueMark } from './ownKey.js';
|
|
1
|
+
import { guardedRead, readFrameStringKey, readFrameTrueMark, readOwnDataValue } from './ownKey.js';
|
|
2
2
|
export function resultErrorCodeOf(frame) {
|
|
3
3
|
return readFrameStringKey(frame, '_sema_error_code');
|
|
4
4
|
}
|
|
@@ -12,5 +12,7 @@ export function resultParkFailedReasonOf(frame) {
|
|
|
12
12
|
return readFrameStringKey(frame, '_sema_park_failed_reason');
|
|
13
13
|
}
|
|
14
14
|
export function resultErrorCodeInTextOf(frame) {
|
|
15
|
-
|
|
15
|
+
if (!readFrameTrueMark(frame, '_sema_error_code_in_text'))
|
|
16
|
+
return undefined;
|
|
17
|
+
return guardedRead(() => (Array.isArray(readOwnDataValue(frame, 'errors')) ? true : undefined));
|
|
16
18
|
}
|
|
@@ -2,21 +2,27 @@ import { msg, renderMessage } from './i18n/translate.js';
|
|
|
2
2
|
import { readBlockedBy, readErrorNumber, readErrorString, readThrownSlot } from './wireFailureShape.js';
|
|
3
3
|
import { guardedRead, ownDataField, readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
|
|
4
4
|
import { CORE_RESUME_STARTUP_CAUSES } from './generated/engineFactTables.js';
|
|
5
|
-
import { RESUME_CONTEXT_UNAVAILABLE, RESUME_PLACEMENT_MISMATCH, RESUME_PREFLIGHT_REJECTED, RESUME_POLICY_FOLD_CODE, PARKED_RESUME_STARTUP_FAILED, isStatusDerivedCoarseCode, RESUME_SESSION_NOT_FOUND, REQUEST_FIELD_CONFLICT, CHECKPOINT_UNSUPPORTED_VERSION, CHECKPOINT_WALLTIME_AXIS_RETIRED, CHECKPOINT_CONFIG_REFUSED, isRefusedParkCode, refusalSaysStillPending, refusalRetriableReading, } from './engineErrorCodes.js';
|
|
5
|
+
import { RESUME_CONTEXT_UNAVAILABLE, RESUME_PLACEMENT_MISMATCH, RESUME_PREFLIGHT_REJECTED, RESUME_PRINCIPAL_MISMATCH, RESUME_COMPOSITION_MISMATCH, RESUME_PARENT_CONSTRAINT_MISSING, RESUME_PARENT_CONSTRAINT_MISMATCH, RESUME_CONSTRAINT_UNPROJECTABLE, RESUME_POLICY_FOLD_CODE, PARKED_RESUME_STARTUP_FAILED, isStatusDerivedCoarseCode, RESUME_SESSION_NOT_FOUND, REQUEST_FIELD_CONFLICT, CHECKPOINT_UNSUPPORTED_VERSION, CHECKPOINT_WALLTIME_AXIS_RETIRED, CHECKPOINT_CONFIG_REFUSED, isRefusedParkCode, refusalSaysStillPending, refusalRetriableReading, } from './engineErrorCodes.js';
|
|
6
6
|
import { capForDisplay } from './fleetTaskDesc.js';
|
|
7
7
|
import { engineVersionTier } from './supportFloor.js';
|
|
8
8
|
import { resumeRetryLaterFromError } from './wireErrorTriage.js';
|
|
9
|
-
|
|
10
|
-
RESUME_PLACEMENT_MISMATCH,
|
|
11
|
-
RESUME_PREFLIGHT_REJECTED,
|
|
12
|
-
]
|
|
9
|
+
const REFUSAL_COPY_KEYS = Object.freeze({
|
|
10
|
+
[RESUME_PLACEMENT_MISMATCH]: 'resume.refusal.placementMismatch',
|
|
11
|
+
[RESUME_PREFLIGHT_REJECTED]: null,
|
|
12
|
+
[RESUME_PRINCIPAL_MISMATCH]: 'resume.refusal.principalMismatch',
|
|
13
|
+
[RESUME_COMPOSITION_MISMATCH]: 'resume.refusal.compositionMismatch',
|
|
14
|
+
[RESUME_PARENT_CONSTRAINT_MISSING]: 'resume.refusal.parentConstraintMissing',
|
|
15
|
+
[RESUME_PARENT_CONSTRAINT_MISMATCH]: 'resume.refusal.parentConstraintMismatch',
|
|
16
|
+
[RESUME_CONSTRAINT_UNPROJECTABLE]: 'resume.refusal.constraintUnprojectable',
|
|
17
|
+
});
|
|
18
|
+
export const RESUME_REFUSAL_CODES = Object.freeze(Object.keys(REFUSAL_COPY_KEYS));
|
|
13
19
|
export function resumeRefusalFromError(err) {
|
|
14
20
|
if (typeof err !== 'object' || err === null)
|
|
15
21
|
return null;
|
|
16
22
|
const code = guardedRead(() => ownDataField(err, 'errorCode'));
|
|
17
23
|
if (typeof code !== 'string' || !RESUME_REFUSAL_CODES.includes(code))
|
|
18
24
|
return null;
|
|
19
|
-
if (code
|
|
25
|
+
if (code !== RESUME_PREFLIGHT_REJECTED) {
|
|
20
26
|
return { code, waitable: false };
|
|
21
27
|
}
|
|
22
28
|
const timed = resumeRetryLaterFromError(err);
|
|
@@ -29,8 +35,9 @@ export function resumeRefusalFromError(err) {
|
|
|
29
35
|
};
|
|
30
36
|
}
|
|
31
37
|
export function resumeRefusalContent(detail, lang) {
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
const copyKey = typeof detail.code === 'string' && Object.hasOwn(REFUSAL_COPY_KEYS, detail.code) ? REFUSAL_COPY_KEYS[detail.code] : null;
|
|
39
|
+
if (copyKey !== null && copyKey !== undefined)
|
|
40
|
+
return renderMessage(msg(copyKey, { safe: msg('resume.refusal.untouched') }), lang);
|
|
34
41
|
return renderMessage(msg(detail.waitable ? 'resume.refusal.preflightWaitable' : 'resume.refusal.preflightNoWait'), lang);
|
|
35
42
|
}
|
|
36
43
|
export function resumePolicyBlockFromError(err) {
|
package/dist/ruleReadings.js
CHANGED
|
@@ -122,7 +122,7 @@ export function ruleNearMissSentence(rows, lang) {
|
|
|
122
122
|
const named = shown
|
|
123
123
|
.map((it) => renderMessage(msg('rules.refusal.item', {
|
|
124
124
|
rule: `"${capForDisplay(it.rule, NEAR_MISS_RULE_MAX)}"`,
|
|
125
|
-
reason: renderMessage(msg('rules.nearMiss.reason', { mounted:
|
|
125
|
+
reason: renderMessage(msg('rules.nearMiss.reason', { mounted: displayUntrusted(it.mounted, { max: NEAR_MISS_NAME_MAX, escapeBackslashes: 'auto' }) }), lang),
|
|
126
126
|
}), lang))
|
|
127
127
|
.join(separator);
|
|
128
128
|
const rest = items.length - shown.length;
|
|
@@ -2,7 +2,7 @@ import type { UiLanguage } from './env/uiLanguage.js';
|
|
|
2
2
|
import { type PermissionModeReceiptView } from './adapter/downstream/wiringManifestView.js';
|
|
3
3
|
import { SDK_PERMISSION_MODE_ADMISSION_FOLDS, SDK_PERMISSION_MODE_PERSIST_MISSES } from './generated/sdkFactTables.js';
|
|
4
4
|
import { type PermissionModeWriteReading } from './permissionModeWriteCapability.js';
|
|
5
|
-
import type
|
|
5
|
+
import { type PermissionMode } from './permissionWireCaps.js';
|
|
6
6
|
export type { PermissionModeReceiptView };
|
|
7
7
|
type AdmissionFold = (typeof SDK_PERMISSION_MODE_ADMISSION_FOLDS)[number];
|
|
8
8
|
type PersistMiss = (typeof SDK_PERMISSION_MODE_PERSIST_MISSES)[number];
|
|
@@ -40,6 +40,7 @@ export type RunPermissionModeSwitchOutcome = {
|
|
|
40
40
|
readonly status?: number;
|
|
41
41
|
} | {
|
|
42
42
|
readonly kind: 'unavailable';
|
|
43
|
+
readonly code?: string;
|
|
43
44
|
};
|
|
44
45
|
export interface RunPermissionModeSwitchRuns {
|
|
45
46
|
setPermissionMode(taskId: string, mode: PermissionMode, opts?: {
|
|
@@ -3,8 +3,9 @@ import { readPermissionModeReceiptSegment } from './adapter/downstream/wiringMan
|
|
|
3
3
|
import { displayUntrusted } from './displayUntrusted.js';
|
|
4
4
|
import { SDK_PERMISSION_MODE_ADMISSION_FOLDS, SDK_PERMISSION_MODE_PERSIST_MISSES } from './generated/sdkFactTables.js';
|
|
5
5
|
import { msg, renderMessage } from './i18n/translate.js';
|
|
6
|
-
import { ownDataField } from './ownKey.js';
|
|
6
|
+
import { ownDataField, readOwnDataValue } from './ownKey.js';
|
|
7
7
|
import { permissionModeWriteAvailable } from './permissionModeWriteCapability.js';
|
|
8
|
+
import { permissionModeTitle } from './permissionWireCaps.js';
|
|
8
9
|
import { isDisplayableWireCode } from './wireFailureShape.js';
|
|
9
10
|
export const PERMISSION_MODE_SWITCH_RESULT_KEYS = Object.freeze(['taskId', 'sessionId', 'status', 'permissionMode', 'admission', 'persisted', 'persistMiss']);
|
|
10
11
|
const NOT_RUNNING_CODE = 'steering.not_running';
|
|
@@ -19,7 +20,9 @@ function guardedSlot(o, key) {
|
|
|
19
20
|
return undefined;
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
|
-
const unavailable = () => Object.freeze({ kind: 'unavailable' });
|
|
23
|
+
const unavailable = (code) => Object.freeze(code !== undefined ? { kind: 'unavailable', code } : { kind: 'unavailable' });
|
|
24
|
+
const RUN_STORE_REQUIRED_CODE = 'capability.run_store_required';
|
|
25
|
+
const CHECKPOINT_STORE_REQUIRED_CODE = 'capability.checkpoint_store_required';
|
|
23
26
|
const unreadableAnswer = () => Object.freeze({ kind: 'unconfirmed', why: 'unreadable-answer' });
|
|
24
27
|
function admissionOf(raw) {
|
|
25
28
|
if (raw === null || typeof raw !== 'object' || Array.isArray(raw))
|
|
@@ -72,7 +75,7 @@ function switchOutcomeOf(taskId, sent, body) {
|
|
|
72
75
|
function failureOutcomeOf(e) {
|
|
73
76
|
const v = atMostOnceVerdictOf(e);
|
|
74
77
|
if (v.status === 501)
|
|
75
|
-
return unavailable();
|
|
78
|
+
return unavailable(v.code);
|
|
76
79
|
if (v.delivery === 'rejected' && v.status !== undefined) {
|
|
77
80
|
if (v.status === 404)
|
|
78
81
|
return Object.freeze({ kind: 'not-found' });
|
|
@@ -110,7 +113,8 @@ export async function setRunPermissionMode(runs, taskId, mode, opts = {}) {
|
|
|
110
113
|
export function runPermissionModeSwitchLine(outcome, lang) {
|
|
111
114
|
switch (outcome.kind) {
|
|
112
115
|
case 'switched': {
|
|
113
|
-
const
|
|
116
|
+
const effective = outcome.permissionMode.effective;
|
|
117
|
+
const mode = permissionModeTitle(effective) ?? displayUntrusted(effective, { max: 64 });
|
|
114
118
|
const reason = outcome.admission !== undefined
|
|
115
119
|
? msg(outcome.admission.foldedBy === 'entry_floor' ? 'session.permissionModeSwitch.reason.entryFloor' : 'session.permissionModeSwitch.reason.disableAutoMode')
|
|
116
120
|
: outcome.permissionMode.foldedBy !== undefined
|
|
@@ -129,7 +133,13 @@ export function runPermissionModeSwitchLine(outcome, lang) {
|
|
|
129
133
|
: renderMessage(msg('session.permissionModeSwitch.refused', { status: String(outcome.status) }), lang);
|
|
130
134
|
case 'unconfirmed':
|
|
131
135
|
return renderMessage(msg('session.permissionModeSwitch.unconfirmed'), lang);
|
|
132
|
-
case 'unavailable':
|
|
133
|
-
|
|
136
|
+
case 'unavailable': {
|
|
137
|
+
const code = readOwnDataValue(outcome, 'code');
|
|
138
|
+
return renderMessage(msg(code === RUN_STORE_REQUIRED_CODE
|
|
139
|
+
? 'session.permissionModeSwitch.unavailableRunStore'
|
|
140
|
+
: code === CHECKPOINT_STORE_REQUIRED_CODE
|
|
141
|
+
? 'session.permissionModeSwitch.unavailableCheckpointStore'
|
|
142
|
+
: 'session.permissionModeSwitch.unavailable'), lang);
|
|
143
|
+
}
|
|
134
144
|
}
|
|
135
145
|
}
|