@sema-agent/client-core 0.107.0 → 0.108.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 +118 -0
- package/README.md +19 -14
- package/dist/adapter/activeRunSelfHeal.d.ts +2 -0
- package/dist/adapter/activeRunSelfHeal.js +20 -3
- package/dist/checkpointRowVerdict.d.ts +5 -0
- package/dist/checkpointRowVerdict.js +26 -0
- package/dist/cloudConfigWireCaps.d.ts +10 -0
- package/dist/cloudConfigWireCaps.js +33 -0
- package/dist/coreValuePorts.d.ts +17 -1
- package/dist/coreValuePorts.js +5 -0
- package/dist/decideReceipt.js +2 -1
- package/dist/engineErrorCodes.d.ts +5 -0
- package/dist/engineErrorCodes.js +5 -0
- package/dist/engineNoticeCodes.d.ts +19 -1
- package/dist/engineNoticeCodes.js +65 -3
- package/dist/engineTargetSeat.js +1 -0
- package/dist/errorSupplementRoles.js +2 -0
- package/dist/eventLeg.js +1 -1
- package/dist/executionLaneWords.js +2 -1
- package/dist/gateOutcome.d.ts +10 -1
- package/dist/gateOutcome.js +48 -1
- package/dist/generated/engineFactTables.d.ts +1 -0
- package/dist/generated/engineFactTables.js +5 -0
- package/dist/generated/engineNoticeTables.js +3 -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/approvalResolution.d.ts +3 -0
- package/dist/hitl/approvalResolution.js +22 -4
- package/dist/hitl/approvalsFeed.js +3 -12
- package/dist/hitl/askParkRowRouting.js +5 -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 +28 -6
- package/dist/hitl/gateLedger.d.ts +2 -0
- package/dist/hitl/gateLedger.js +3 -1
- package/dist/hitl/hitlBridge.js +2 -3
- package/dist/hitl/parkResolver.js +32 -23
- package/dist/hitl/parkRowBirthWait.d.ts +2 -0
- package/dist/hitl/parkRowBirthWait.js +8 -1
- package/dist/hitl/persistedRulesWire.d.ts +5 -1
- package/dist/hitl/persistedRulesWire.js +20 -4
- 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/sessionPolicyDeliverable.js +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +8 -2
- package/dist/hitl/toolApprovalWire.js +22 -3
- package/dist/hooksReaderGenerations.d.ts +1 -0
- package/dist/hooksReaderGenerations.js +12 -0
- package/dist/hooksWireCaps.js +8 -4
- package/dist/i18n/messages.en.d.ts +38 -1
- package/dist/i18n/messages.en.js +40 -3
- package/dist/i18n/messages.zh.js +45 -3
- package/dist/index.d.ts +6 -1
- package/dist/index.js +4 -1
- package/dist/liveModelCatalog.d.ts +4 -2
- package/dist/liveModelCatalog.js +164 -26
- package/dist/model/catalogDefault.d.ts +25 -0
- package/dist/model/catalogDefault.js +44 -0
- 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/runPermissionModeSwitch.d.ts +2 -1
- package/dist/runPermissionModeSwitch.js +16 -6
- package/dist/seatContract.d.ts +63 -10
- package/dist/seatContract.js +164 -11
- 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.js +1 -1
- package/dist/supportFloor.js +2 -0
- package/dist/taskNotificationAdmission.d.ts +19 -0
- package/dist/taskNotificationAdmission.js +84 -0
- package/dist/toolResult.js +2 -1
- package/dist/webSearchWireCaps.js +9 -4
- package/dist/wireRefusalCopy.d.ts +2 -1
- package/dist/wireRefusalCopy.js +2 -2
- package/docs/INTEGRATION-CLIENTS.md +816 -14
- package/package.json +4 -4
package/dist/seatContract.js
CHANGED
|
@@ -4,6 +4,8 @@ import { REWIND_MODES } from "./rewindWireCaps.js";
|
|
|
4
4
|
import { SETTINGS_MODEL_API_WORDS } from "./generated/settingsSchemaTables.js";
|
|
5
5
|
import { PROBE_VERDICTS } from "./modelCapabilityProbe.js";
|
|
6
6
|
import { guardedRead, ownDataField, ownDataRefusalKeyOf, ownSendableField, readOwnDataValue } from "./ownKey.js";
|
|
7
|
+
import { isPlainRecord as isJsonPlainRecord } from "./jsonFaithful.js";
|
|
8
|
+
import { displayUntrustedMarks, quoteUntrustedForSentence } from "./displayUntrusted.js";
|
|
7
9
|
import { MCP_LIVENESS_STATES } from "./mcpLiveness.js";
|
|
8
10
|
import { THINKING_LATCH_EVENTS, THINKING_LATCH_ROW_WORDS } from "./thinkingLatchWords.js";
|
|
9
11
|
import { EXECUTION_PLACEMENT_ROLES } from "./executionPlacementWords.js";
|
|
@@ -18,12 +20,7 @@ const nested = (prefix, verdict) => {
|
|
|
18
20
|
const reason = verdict.reason.startsWith(`${prefix}:`) ? verdict.reason : `${prefix}: ${verdict.reason}`;
|
|
19
21
|
return bad(reason, path);
|
|
20
22
|
};
|
|
21
|
-
const isPlainRecord = (v) =>
|
|
22
|
-
if (typeof v !== "object" || v === null || Array.isArray(v))
|
|
23
|
-
return false;
|
|
24
|
-
const proto = Object.getPrototypeOf(v);
|
|
25
|
-
return proto === null || (typeof proto === "object" && Object.getPrototypeOf(proto) === null);
|
|
26
|
-
};
|
|
23
|
+
const isPlainRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v) && isJsonPlainRecord(v);
|
|
27
24
|
const isAbsent = (v) => typeof v === "undefined";
|
|
28
25
|
const optionalString = (v) => isAbsent(v) || typeof v === "string";
|
|
29
26
|
const isFolderPath = (v) => typeof v === "string" && v.length > 0;
|
|
@@ -185,6 +182,8 @@ const R_NUM = ruleOf("finite number", (v) => typeof v === "number" && Number.isF
|
|
|
185
182
|
const R_NUM0 = ruleOf("finite non-negative number", (v) => typeof v === "number" && Number.isFinite(v) && v >= 0);
|
|
186
183
|
const R_INT0 = ruleOf("non-negative integer", (v) => typeof v === "number" && Number.isSafeInteger(v) && v >= 0);
|
|
187
184
|
const R_INT1 = ruleOf("positive integer", (v) => typeof v === "number" && Number.isSafeInteger(v) && v > 0);
|
|
185
|
+
const SESSION_ENGINE_KIND_WORDS = Object.freeze(["local", "cloud"]);
|
|
186
|
+
const R_ENGINE_LANE = oneOfRule("engine lane", SESSION_ENGINE_KIND_WORDS);
|
|
188
187
|
const keyWords = (k) => k
|
|
189
188
|
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
190
189
|
.toLowerCase()
|
|
@@ -333,6 +332,7 @@ export const HITL_RESOLUTION_OUTCOMES = [
|
|
|
333
332
|
"accept",
|
|
334
333
|
"decline",
|
|
335
334
|
"cancel",
|
|
335
|
+
"engine_unavailable",
|
|
336
336
|
];
|
|
337
337
|
export const SEAT_STREAM_DELTA_TYPE_OF_CHANNEL = Object.freeze({ text: "text_delta", thinking: "thinking_delta" });
|
|
338
338
|
export function seatStreamDeltaMessage(event, ids) {
|
|
@@ -381,7 +381,7 @@ export function readSeatStreamDelta(message) {
|
|
|
381
381
|
return Object.freeze({ kind: "malformed" });
|
|
382
382
|
}
|
|
383
383
|
}
|
|
384
|
-
export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly"]);
|
|
384
|
+
export const SEAT_CAPABILITY_NAMES = Object.freeze(["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions"]);
|
|
385
385
|
const notReported = () => Object.freeze({ kind: "not_reported" });
|
|
386
386
|
const malformedReading = () => Object.freeze({ kind: "malformed" });
|
|
387
387
|
const reported = (available) => Object.freeze({ kind: "reported", available });
|
|
@@ -460,6 +460,7 @@ const SEAT_CAPABILITY_PHRASES = Object.freeze({
|
|
|
460
460
|
thinkingLatch: Object.freeze({ action: "Switching thinking", ability: "switch thinking", support: "thinking-switch support" }),
|
|
461
461
|
computerUseSwitch: Object.freeze({ action: "Computer use", ability: "be switched", support: "switch support" }),
|
|
462
462
|
engineModeDefaultOnly: Object.freeze({ action: "Default-only engine switching", ability: "keep existing sessions on their engine", support: "default-only engine switching" }),
|
|
463
|
+
seatActions: Object.freeze({ action: "App menu actions", ability: "send actions to this window", support: "app action support" }),
|
|
463
464
|
});
|
|
464
465
|
export function seatCapabilityUnavailableDetail(name, reading) {
|
|
465
466
|
const phrase = Object.hasOwn(SEAT_CAPABILITY_PHRASES, name)
|
|
@@ -668,6 +669,7 @@ export const ENGINE_TARGET_REFUSALS = Object.freeze([
|
|
|
668
669
|
"not_configured",
|
|
669
670
|
"not_signed_in",
|
|
670
671
|
"probe_failed",
|
|
672
|
+
"cloud_unreachable",
|
|
671
673
|
"org_policy",
|
|
672
674
|
"url_refused",
|
|
673
675
|
"login_failed",
|
|
@@ -766,7 +768,7 @@ const ENGINE_TARGET_LOCAL = shapeRule("local", {
|
|
|
766
768
|
mcp: optF(SEAT_LOCAL_MCP_READING),
|
|
767
769
|
});
|
|
768
770
|
const ENGINE_TARGET_STATE = shapeRule("engine target", {
|
|
769
|
-
mode: reqF(
|
|
771
|
+
mode: reqF(R_ENGINE_LANE),
|
|
770
772
|
generation: reqF(R_INT0),
|
|
771
773
|
cloud: reqF(ENGINE_TARGET_CLOUD),
|
|
772
774
|
local: reqF(ENGINE_TARGET_LOCAL),
|
|
@@ -1064,6 +1066,119 @@ export function planSetComputerUse(request, lockedByEnv) {
|
|
|
1064
1066
|
return Object.freeze({ kind: "refused", reason: "confirmation-required" });
|
|
1065
1067
|
return Object.freeze({ kind: "apply", enabled: intent.kind === "enable" });
|
|
1066
1068
|
}
|
|
1069
|
+
export const SEAT_ACTION_NAMES = Object.freeze(["new-project", "prefill-composer"]);
|
|
1070
|
+
const SEAT_PREFILL_TEXT_MAX = 14336;
|
|
1071
|
+
const SEAT_PREFILL_CWD_MAX = 4096;
|
|
1072
|
+
const SEAT_ACTIONS_CLAIM_MAX = 16;
|
|
1073
|
+
const SEAT_ACTION_WORD_MAX = 64;
|
|
1074
|
+
const SEAT_TEXT_FACE = Object.freeze({ foldLines: false, keepLayout: "crlf", credentialUrls: false, credentialWords: false });
|
|
1075
|
+
const SEAT_PATH_FACE = Object.freeze({ foldLines: false, credentialUrls: false, credentialWords: false });
|
|
1076
|
+
const faceClean = (v, face) => displayUntrustedMarks(v, face).marks.length === 0;
|
|
1077
|
+
const R_PREFILL_TEXT = ruleOf(`prefill text (1–${SEAT_PREFILL_TEXT_MAX} chars, no control, bidi or other invisible characters)`, (v) => typeof v === "string" && v.length > 0 && v.length <= SEAT_PREFILL_TEXT_MAX && faceClean(v, SEAT_TEXT_FACE));
|
|
1078
|
+
const R_PREFILL_CWD = ruleOf(`folder path (1–${SEAT_PREFILL_CWD_MAX} chars, no control, bidi or other invisible characters)`, (v) => isFolderPath(v) && v.length <= SEAT_PREFILL_CWD_MAX && faceClean(v, SEAT_PATH_FACE));
|
|
1079
|
+
const SEAT_ACTION_ARMS = {
|
|
1080
|
+
"new-project": {},
|
|
1081
|
+
"prefill-composer": { text: reqF(R_PREFILL_TEXT), cwd: optF(R_PREFILL_CWD) },
|
|
1082
|
+
};
|
|
1083
|
+
export const checkSeatAction = seatShapeCheck(armsRule("seat action", "action", SEAT_ACTION_ARMS));
|
|
1084
|
+
const seatActionMalformed = (reason) => Object.freeze({ kind: "malformed", reason });
|
|
1085
|
+
export function readSeatAction(ev) {
|
|
1086
|
+
try {
|
|
1087
|
+
if (!isPlainRecord(ev))
|
|
1088
|
+
return seatActionMalformed("not a plain object");
|
|
1089
|
+
const name = own(ev, "action");
|
|
1090
|
+
if (typeof name !== "string")
|
|
1091
|
+
return seatActionMalformed("action must be a string");
|
|
1092
|
+
if (!inTuple(SEAT_ACTION_NAMES, name))
|
|
1093
|
+
return Object.freeze({ kind: "unknown", name: name.slice(0, SEAT_ACTION_WORD_MAX) });
|
|
1094
|
+
const verdict = checkSeatAction(ev);
|
|
1095
|
+
if (verdict !== true) {
|
|
1096
|
+
return seatActionMalformed(`${verdict.field ? `${verdict.field}: ` : ""}${verdict.reason}`);
|
|
1097
|
+
}
|
|
1098
|
+
if (name === "new-project")
|
|
1099
|
+
return Object.freeze({ kind: "action", action: Object.freeze({ action: "new-project" }) });
|
|
1100
|
+
const text = own(ev, "text");
|
|
1101
|
+
const cwd = own(ev, "cwd");
|
|
1102
|
+
if (R_PREFILL_TEXT.test(text, "text") !== true || typeof text !== "string")
|
|
1103
|
+
return seatActionMalformed("text: payload changed while being read");
|
|
1104
|
+
if (!isAbsent(cwd) && (R_PREFILL_CWD.test(cwd, "cwd") !== true || typeof cwd !== "string"))
|
|
1105
|
+
return seatActionMalformed("cwd: payload changed while being read");
|
|
1106
|
+
return Object.freeze({
|
|
1107
|
+
kind: "action",
|
|
1108
|
+
action: Object.freeze({ action: "prefill-composer", text, ...(typeof cwd === "string" ? { cwd } : {}) }),
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
catch {
|
|
1112
|
+
return seatActionMalformed("payload could not be read");
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
const quoteSeatWord = (w) => quoteUntrustedForSentence(w, SEAT_ACTION_WORD_MAX) ?? '""';
|
|
1116
|
+
const R_CLAIM_WORD = {
|
|
1117
|
+
label: "action word",
|
|
1118
|
+
test: (v, path) => typeof v === "string"
|
|
1119
|
+
? inTuple(SEAT_ACTION_NAMES, v)
|
|
1120
|
+
? true
|
|
1121
|
+
: bad(`unknown action word ${quoteSeatWord(v)} (closed set: ${SEAT_ACTION_NAMES.join("|")})`, path)
|
|
1122
|
+
: bad("bad value (action word)", path),
|
|
1123
|
+
};
|
|
1124
|
+
const claimListOnce = (v, path) => {
|
|
1125
|
+
const n = ownDataField(v, "length");
|
|
1126
|
+
if (typeof n !== "number" || !Number.isSafeInteger(n) || n < 0)
|
|
1127
|
+
return bad("bad value (action list)", path);
|
|
1128
|
+
if (n > SEAT_ACTIONS_CLAIM_MAX)
|
|
1129
|
+
return bad(`bad value (at most ${SEAT_ACTIONS_CLAIM_MAX} actions)`, path);
|
|
1130
|
+
for (const k of Reflect.ownKeys(v)) {
|
|
1131
|
+
if (typeof k === "string" && !isArraySlotKey(k, n))
|
|
1132
|
+
return bad("unknown key", pathAt(path, k));
|
|
1133
|
+
}
|
|
1134
|
+
const words = [];
|
|
1135
|
+
for (let i = 0; i < n; i += 1)
|
|
1136
|
+
words.push(own(v, String(i)));
|
|
1137
|
+
return words;
|
|
1138
|
+
};
|
|
1139
|
+
const R_CLAIM_LIST = {
|
|
1140
|
+
label: `action list (at most ${SEAT_ACTIONS_CLAIM_MAX})`,
|
|
1141
|
+
test: (v, path) => {
|
|
1142
|
+
if (!Array.isArray(v))
|
|
1143
|
+
return bad("bad value (action list)", path);
|
|
1144
|
+
const words = claimListOnce(v, path);
|
|
1145
|
+
if (!Array.isArray(words))
|
|
1146
|
+
return words;
|
|
1147
|
+
for (let i = 0; i < words.length; i += 1) {
|
|
1148
|
+
const verdict = R_CLAIM_WORD.test(words[i], `${path}[${i}]`);
|
|
1149
|
+
if (verdict !== true)
|
|
1150
|
+
return verdict;
|
|
1151
|
+
}
|
|
1152
|
+
return true;
|
|
1153
|
+
},
|
|
1154
|
+
};
|
|
1155
|
+
const checkSeatActionsClaimShape = seatShapeCheck(shapeRule("seat actions claim", { actions: reqF(R_CLAIM_LIST) }));
|
|
1156
|
+
export const checkSeatActionsClaim = seatCheck((v) => isPlainRecord(v) ? checkSeatActionsClaimShape(v) : bad("claimSeatActions request is not a plain object"));
|
|
1157
|
+
export function claimedSeatActionsOf(claim) {
|
|
1158
|
+
try {
|
|
1159
|
+
if (!isPlainRecord(claim))
|
|
1160
|
+
return Object.freeze([]);
|
|
1161
|
+
const snap = Object.create(null);
|
|
1162
|
+
for (const k of Reflect.ownKeys(claim)) {
|
|
1163
|
+
if (typeof k === "string")
|
|
1164
|
+
snap[k] = own(claim, k);
|
|
1165
|
+
}
|
|
1166
|
+
const list = snap.actions;
|
|
1167
|
+
if (Array.isArray(list)) {
|
|
1168
|
+
const words = claimListOnce(list, "actions");
|
|
1169
|
+
if (!Array.isArray(words))
|
|
1170
|
+
return Object.freeze([]);
|
|
1171
|
+
snap.actions = words;
|
|
1172
|
+
}
|
|
1173
|
+
if (checkSeatActionsClaim(snap) !== true)
|
|
1174
|
+
return Object.freeze([]);
|
|
1175
|
+
const taken = snap.actions;
|
|
1176
|
+
return Object.freeze(SEAT_ACTION_NAMES.filter((name) => taken.includes(name)));
|
|
1177
|
+
}
|
|
1178
|
+
catch {
|
|
1179
|
+
return Object.freeze([]);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1067
1182
|
const checkLocalSessionRecord = seatCheck((s) => {
|
|
1068
1183
|
if (!isPlainRecord(s))
|
|
1069
1184
|
return bad("session record is not a plain object");
|
|
@@ -1608,6 +1723,16 @@ export const checkSetThinkingLatchRequest = seatCheck((v) => isPlainRecord(v) ?
|
|
|
1608
1723
|
export function isSetThinkingLatchRequest(v) {
|
|
1609
1724
|
return checkSetThinkingLatchRequest(v) === true;
|
|
1610
1725
|
}
|
|
1726
|
+
const checkStartSessionOptionsShape = seatShapeCheck(shapeRule("start options", {
|
|
1727
|
+
model: optF(R_STR),
|
|
1728
|
+
title: optF(R_STR),
|
|
1729
|
+
cwd: optF(R_STR),
|
|
1730
|
+
excludeTools: optF(arrayRule(R_STR)),
|
|
1731
|
+
engine: optF(R_ENGINE_LANE),
|
|
1732
|
+
}));
|
|
1733
|
+
export const checkStartSessionOptions = seatCheck((v) => isAbsent(v) ? true : isPlainRecord(v) ? checkStartSessionOptionsShape(v) : bad("start options are not a plain object"));
|
|
1734
|
+
const checkSeatResourceScopeShape = seatShapeCheck(shapeRule("resource scope", { sessionId: reqF(R_NONEMPTY) }));
|
|
1735
|
+
export const checkSeatResourceScope = seatCheck((v) => isAbsent(v) ? true : isPlainRecord(v) ? checkSeatResourceScopeShape(v) : bad("resource scope is not a plain object"));
|
|
1611
1736
|
const checkSendMessageAck = seatCheck((v) => {
|
|
1612
1737
|
if (!isPlainRecord(v))
|
|
1613
1738
|
return bad("sendMessage ack is not a plain object");
|
|
@@ -1782,8 +1907,10 @@ export const LOCAL_SESSIONS_SPEC = {
|
|
|
1782
1907
|
setThinkingLatch: { kind: "invoke", check: checkOkAck },
|
|
1783
1908
|
getComputerUse: { kind: "invoke", check: checkComputerUseState },
|
|
1784
1909
|
setComputerUse: { kind: "invoke", check: checkSetComputerUseResult },
|
|
1910
|
+
claimSeatActions: { kind: "invoke", check: checkOkAck },
|
|
1785
1911
|
onEvent: { kind: "event", check: checkLocalSessionEvent },
|
|
1786
1912
|
onToolPermissionRequest: { kind: "event", check: checkToolPermissionRequest },
|
|
1913
|
+
onSeatAction: { kind: "event", check: checkSeatAction },
|
|
1787
1914
|
},
|
|
1788
1915
|
stores: {
|
|
1789
1916
|
sessionsState: { check: checkSessionsState },
|
|
@@ -1832,8 +1959,10 @@ export const SEAT_METHOD_NAMES = [
|
|
|
1832
1959
|
"setThinkingLatch",
|
|
1833
1960
|
"getComputerUse",
|
|
1834
1961
|
"setComputerUse",
|
|
1962
|
+
"claimSeatActions",
|
|
1835
1963
|
"onEvent",
|
|
1836
1964
|
"onToolPermissionRequest",
|
|
1965
|
+
"onSeatAction",
|
|
1837
1966
|
];
|
|
1838
1967
|
export const SEAT_STORE_PROPS = [
|
|
1839
1968
|
"sessionsStateStore",
|
|
@@ -1842,7 +1971,7 @@ export const SEAT_STORE_PROPS = [
|
|
|
1842
1971
|
"seatCapabilitiesStateStore",
|
|
1843
1972
|
"engineTargetStateStore",
|
|
1844
1973
|
];
|
|
1845
|
-
export const SEAT_EVENT_METHOD_NAMES = ["onEvent", "onToolPermissionRequest"];
|
|
1974
|
+
export const SEAT_EVENT_METHOD_NAMES = ["onEvent", "onToolPermissionRequest", "onSeatAction"];
|
|
1846
1975
|
export const LOCAL_SESSION_EVENT_KEYS = [
|
|
1847
1976
|
"type",
|
|
1848
1977
|
"sessionId",
|
|
@@ -1934,7 +2063,7 @@ export const TOOL_PERMISSION_DECISION_KEYS = [
|
|
|
1934
2063
|
"updatedInput",
|
|
1935
2064
|
"remember",
|
|
1936
2065
|
];
|
|
1937
|
-
export const START_SESSION_OPTION_KEYS = ["model", "title", "cwd", "excludeTools"];
|
|
2066
|
+
export const START_SESSION_OPTION_KEYS = ["model", "title", "cwd", "excludeTools", "engine"];
|
|
1938
2067
|
export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
1939
2068
|
LocalSessionRecord: {
|
|
1940
2069
|
guard: "isLocalSessionRecord",
|
|
@@ -2039,6 +2168,10 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
2039
2168
|
key: "modelPlane",
|
|
2040
2169
|
why: "诊断面(0.106.0 CC-1156;这台引擎服务的是哪张模型表 / 最近一份目录候选的结局),三态读法归 modelPlaneOf(含坏形 unreadable、表外词整位不给);出站门为它拒掉整份目录 = 选单为一行诊断整个消失。",
|
|
2041
2170
|
},
|
|
2171
|
+
{
|
|
2172
|
+
key: "aliases",
|
|
2173
|
+
why: "受理面(0.108.0 CC-944;除行名之外引擎还认的模型词),读法归 modelAcceptanceOf(缺席 = 更早的服务端,照旧判;在场而坏形 ⇒ 没找到行的词读 catalog_unreadable);出站门为它拒掉整份目录 = 选单为一份受理数据整个消失。",
|
|
2174
|
+
},
|
|
2042
2175
|
],
|
|
2043
2176
|
},
|
|
2044
2177
|
SendMessageRequest: {
|
|
@@ -2073,6 +2206,21 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
2073
2206
|
validated: ["sessionId", "event"],
|
|
2074
2207
|
unchecked: [],
|
|
2075
2208
|
},
|
|
2209
|
+
StartSessionOptions: {
|
|
2210
|
+
check: checkStartSessionOptions,
|
|
2211
|
+
validated: ["model", "title", "cwd", "excludeTools", "engine"],
|
|
2212
|
+
unchecked: [],
|
|
2213
|
+
},
|
|
2214
|
+
SeatResourceScope: {
|
|
2215
|
+
check: checkSeatResourceScope,
|
|
2216
|
+
validated: ["sessionId"],
|
|
2217
|
+
unchecked: [],
|
|
2218
|
+
},
|
|
2219
|
+
SeatActionsClaim: {
|
|
2220
|
+
check: checkSeatActionsClaim,
|
|
2221
|
+
validated: ["actions"],
|
|
2222
|
+
unchecked: [],
|
|
2223
|
+
},
|
|
2076
2224
|
ApplyModelConfigResult: {
|
|
2077
2225
|
check: checkApplyModelConfigResult,
|
|
2078
2226
|
validated: ["ok", "requiresRestart", "reason", "detail"],
|
|
@@ -2126,7 +2274,7 @@ export const SEAT_VALIDATOR_KEY_COVERAGE = {
|
|
|
2126
2274
|
},
|
|
2127
2275
|
SeatCapabilitiesState: {
|
|
2128
2276
|
check: checkSeatCapabilitiesState,
|
|
2129
|
-
validated: ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly"],
|
|
2277
|
+
validated: ["pickFolder", "rewind", "recents", "patchSession", "devices", "engineTarget", "onboard", "mcpToolToggles", "thinkingLatch", "computerUseSwitch", "engineModeDefaultOnly", "seatActions"],
|
|
2130
2278
|
unchecked: [],
|
|
2131
2279
|
},
|
|
2132
2280
|
RecentFoldersResult: {
|
|
@@ -2192,6 +2340,7 @@ export const SEAT_VALIDATOR_COVERAGE_EXEMPT = [
|
|
|
2192
2340
|
["ComputerUseState", checkComputerUseState],
|
|
2193
2341
|
["SetComputerUseResult", checkSetComputerUseResult],
|
|
2194
2342
|
["SetComputerUseRequest", checkSetComputerUseRequest],
|
|
2343
|
+
["SeatAction", checkSeatAction],
|
|
2195
2344
|
].map(([label, check]) => ({
|
|
2196
2345
|
label,
|
|
2197
2346
|
check,
|
|
@@ -2251,5 +2400,9 @@ const _seatContractPins = [
|
|
|
2251
2400
|
true, true,
|
|
2252
2401
|
true, true, true, true,
|
|
2253
2402
|
true, true,
|
|
2403
|
+
true, true, true,
|
|
2404
|
+
true, true, true, true,
|
|
2405
|
+
true, true,
|
|
2406
|
+
true, true, true, true, true, true, true,
|
|
2254
2407
|
];
|
|
2255
2408
|
void _seatContractPins;
|
package/dist/sessionEngine.d.ts
CHANGED
|
@@ -134,7 +134,7 @@ export interface SessionEngineWiring {
|
|
|
134
134
|
readonly auth: EngineTargetCloudAuth | undefined;
|
|
135
135
|
readonly explicitAddresses?: readonly string[];
|
|
136
136
|
}
|
|
137
|
-
export type SessionDispatchRefusal = 'not-wired' | 'scope-mismatch' | 'scope-unproven' | 'unresolved';
|
|
137
|
+
export type SessionDispatchRefusal = 'not-wired' | 'scope-mismatch' | 'scope-unproven' | 'unresolved' | 'session-ambiguous';
|
|
138
138
|
export type SessionDispatchDecision = {
|
|
139
139
|
readonly kind: 'self';
|
|
140
140
|
readonly wiringSnapshotId: string;
|
|
@@ -153,4 +153,5 @@ export declare function sessionEngineBindingFor(input: SessionEngineBindingInput
|
|
|
153
153
|
export declare function isSessionEngineView(v: {} | null | undefined): boolean;
|
|
154
154
|
export declare function readSessionEngine(record: SessionMapRecord | undefined): SessionEngineReading;
|
|
155
155
|
export declare function commitSessionEngine(store: SessionMapStorePort, session: SessionEngineSessionRef, request: SessionEngineCommitRequest): SessionEngineCommitResult;
|
|
156
|
+
export declare function sessionDispatchRefusedFor(refusal: SessionDispatchRefusal): SessionDispatchRefused;
|
|
156
157
|
export declare function sessionDispatchTarget(reading: SessionEngineReading, ctx: SessionEngineWiring): SessionDispatchDecision;
|
package/dist/sessionEngine.js
CHANGED
|
@@ -382,8 +382,13 @@ const REFUSAL_KEYS = {
|
|
|
382
382
|
'scope-mismatch': 'session.engine.dispatch.scopeMismatch',
|
|
383
383
|
'scope-unproven': 'session.engine.dispatch.scopeUnproven',
|
|
384
384
|
unresolved: 'session.engine.dispatch.unresolved',
|
|
385
|
+
'session-ambiguous': 'session.engine.dispatch.sessionAmbiguous',
|
|
385
386
|
};
|
|
386
387
|
const refused = (refusal) => Object.freeze({ kind: 'refused', refusal, message: msg(REFUSAL_KEYS[refusal]) });
|
|
388
|
+
export function sessionDispatchRefusedFor(refusal) {
|
|
389
|
+
const word = Object.keys(REFUSAL_KEYS).find((w) => w === refusal);
|
|
390
|
+
return refused(word ?? 'unresolved');
|
|
391
|
+
}
|
|
387
392
|
function authOf(ctx) {
|
|
388
393
|
const slot = slotReadOf(ctx, 'auth');
|
|
389
394
|
if (slot.presence === 'absent' || (slot.presence === 'present' && slot.value === undefined))
|
|
@@ -40,6 +40,11 @@ export declare function hooksSalvageMaskOf(dropped: readonly {
|
|
|
40
40
|
readonly path: readonly (string | number)[];
|
|
41
41
|
}[]): HooksSalvageMask;
|
|
42
42
|
export declare function salvageSettingsHooksEntries(doc: SettingsDocument | null | undefined): HooksSalvage;
|
|
43
|
+
export declare function hooksGroupUnreadKeys(event: string, group: object): readonly string[] | undefined;
|
|
44
|
+
export type HooksGroupAuthoredSource = 'absent' | 'present' | 'unreadable';
|
|
45
|
+
export declare function hooksGroupAuthoredSource(group: object): HooksGroupAuthoredSource;
|
|
46
|
+
export declare function hooksEntryUnreadKeys(event: string, entry: object, notRead: readonly string[]): readonly string[] | undefined;
|
|
47
|
+
export declare function hooksKeyCoordinateText(path: readonly (string | number)[]): string;
|
|
43
48
|
export declare const HOOK_SETTINGS_SOURCE_TEXT: Readonly<Record<HookSettingsSource, string>>;
|
|
44
49
|
export declare function layerNotAppliedRefusesTurn(source: HookSettingsSource): boolean;
|
|
45
50
|
export declare function settingsHooksSalvageNotice(salvage: HooksSalvage, source: HookSettingsSource, doc?: SettingsDocument | null): string | undefined;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { displayUntrusted } from './displayUntrusted.js';
|
|
2
2
|
import { msg, renderMessage } from './i18n/translate.js';
|
|
3
|
+
import { appendOwnElement } from './ownKey.js';
|
|
3
4
|
import { SETTINGS_CLASSIFY_HOOKS_CONFIG, } from './generated/settingsSchemaFns.js';
|
|
4
5
|
const _tuplePins = [true, true, true, true, true, true];
|
|
5
6
|
void _tuplePins;
|
|
@@ -110,6 +111,59 @@ export function salvageSettingsHooksEntries(doc) {
|
|
|
110
111
|
rejections: Object.freeze([]),
|
|
111
112
|
});
|
|
112
113
|
}
|
|
114
|
+
const READER_GROUP_WIRE_KEYS = ['source'];
|
|
115
|
+
const READER_COMMAND_WIRE_KEYS = ['plugin', 'args'];
|
|
116
|
+
function unreadOf(raw, carried, wireKeys, notRead) {
|
|
117
|
+
const out = [];
|
|
118
|
+
for (const k of Object.keys(raw)) {
|
|
119
|
+
if (own(raw, k) === undefined || wireKeys.includes(k))
|
|
120
|
+
continue;
|
|
121
|
+
if (Object.hasOwn(carried, k) && !notRead.includes(k))
|
|
122
|
+
continue;
|
|
123
|
+
appendOwnElement(out, k);
|
|
124
|
+
}
|
|
125
|
+
return Object.freeze(out);
|
|
126
|
+
}
|
|
127
|
+
function carriedGroupOf(event, group) {
|
|
128
|
+
const r = SETTINGS_CLASSIFY_HOOKS_CONFIG({ hooks: { [event]: [group] } });
|
|
129
|
+
if (r.outcome !== 'loaded' || !isRecord(r.hooks))
|
|
130
|
+
return undefined;
|
|
131
|
+
const groups = own(r.hooks, event);
|
|
132
|
+
const g = Array.isArray(groups) ? groups[0] : undefined;
|
|
133
|
+
return isRecord(g) ? g : undefined;
|
|
134
|
+
}
|
|
135
|
+
export function hooksGroupUnreadKeys(event, group) {
|
|
136
|
+
const raw = group;
|
|
137
|
+
const carried = carriedGroupOf(event, { ...raw, hooks: [] });
|
|
138
|
+
return carried === undefined ? undefined : unreadOf(raw, carried, READER_GROUP_WIRE_KEYS, []);
|
|
139
|
+
}
|
|
140
|
+
export function hooksGroupAuthoredSource(group) {
|
|
141
|
+
try {
|
|
142
|
+
const d = Object.getOwnPropertyDescriptor(group, READER_GROUP_WIRE_KEYS[0]);
|
|
143
|
+
if (d === undefined)
|
|
144
|
+
return 'absent';
|
|
145
|
+
if (!Object.hasOwn(d, 'value'))
|
|
146
|
+
return 'unreadable';
|
|
147
|
+
if (d.value !== undefined)
|
|
148
|
+
return 'present';
|
|
149
|
+
return Reflect.get(group, READER_GROUP_WIRE_KEYS[0]) === undefined ? 'absent' : 'unreadable';
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return 'unreadable';
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
export function hooksEntryUnreadKeys(event, entry, notRead) {
|
|
156
|
+
const raw = entry;
|
|
157
|
+
const g = carriedGroupOf(event, { hooks: [raw] });
|
|
158
|
+
const entries = g === undefined ? undefined : own(g, 'hooks');
|
|
159
|
+
const carried = Array.isArray(entries) ? entries[0] : undefined;
|
|
160
|
+
if (!isRecord(carried))
|
|
161
|
+
return undefined;
|
|
162
|
+
return unreadOf(raw, carried, own(carried, 'type') === 'command' ? READER_COMMAND_WIRE_KEYS : [], notRead);
|
|
163
|
+
}
|
|
164
|
+
export function hooksKeyCoordinateText(path) {
|
|
165
|
+
return `settings.${path.map(labelOf).join('.')}`;
|
|
166
|
+
}
|
|
113
167
|
export const HOOK_SETTINGS_SOURCE_TEXT = Object.freeze({
|
|
114
168
|
policySettings: 'Managed settings',
|
|
115
169
|
userSettings: 'User settings',
|
|
@@ -812,7 +812,7 @@ export function recordSubagentOwnerFromProgress(ev, ownerRunId, ownerSessionId,
|
|
|
812
812
|
if (typeof ev !== 'object' || ev === null)
|
|
813
813
|
return;
|
|
814
814
|
const o = ev;
|
|
815
|
-
if (o.type !== 'task_progress')
|
|
815
|
+
if (o.type !== 'task_progress' && o.type !== 'task_started')
|
|
816
816
|
return;
|
|
817
817
|
if (typeof o.taskId !== 'string' || o.taskId === '')
|
|
818
818
|
return;
|
package/dist/supportFloor.js
CHANGED
|
@@ -40,6 +40,8 @@ function judgeAgainst(version, base, floor, caller) {
|
|
|
40
40
|
const got = releaseTriple(version);
|
|
41
41
|
if (got === undefined)
|
|
42
42
|
return { need: need.text, tier: 'unknown' };
|
|
43
|
+
if (got[0] === 0)
|
|
44
|
+
return { need: need.text, tier: 'unknown' };
|
|
43
45
|
return { need: need.text, tier: compareTriple(got, need.triple) >= 0 ? 'engine' : 'legacy' };
|
|
44
46
|
}
|
|
45
47
|
export function engineVersionTier(version, floor) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RunRecord } from '@sema-agent/sdk';
|
|
2
|
+
export type TaskNotificationAdmissionVerdict = 'admitted' | 'pending' | 'not_found' | 'unreadable';
|
|
3
|
+
export type TaskNotificationAdmissionWhy = 'admitted_at' | 'turns_positive' | 'zero_turns' | 'no_turn_count' | 'key_unbound' | 'read_error' | 'record_malformed' | 'input_unrecognized';
|
|
4
|
+
export type TaskNotificationRunRecordView = RunRecord & {
|
|
5
|
+
readonly admittedAt?: string | null;
|
|
6
|
+
};
|
|
7
|
+
export type TaskNotificationReadResult = {
|
|
8
|
+
readonly kind: 'record';
|
|
9
|
+
readonly record: TaskNotificationRunRecordView;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: 'not_found';
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: 'error';
|
|
14
|
+
};
|
|
15
|
+
export interface TaskNotificationAdmission {
|
|
16
|
+
readonly verdict: TaskNotificationAdmissionVerdict;
|
|
17
|
+
readonly why: TaskNotificationAdmissionWhy;
|
|
18
|
+
}
|
|
19
|
+
export declare function taskNotificationAdmissionOf(readResult: TaskNotificationReadResult): TaskNotificationAdmission;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { guardedRead, readOwnDataValue } from './ownKey.js';
|
|
2
|
+
function verdictOfWhy(why) {
|
|
3
|
+
switch (why) {
|
|
4
|
+
case 'admitted_at':
|
|
5
|
+
case 'turns_positive':
|
|
6
|
+
return 'admitted';
|
|
7
|
+
case 'zero_turns':
|
|
8
|
+
case 'no_turn_count':
|
|
9
|
+
return 'pending';
|
|
10
|
+
case 'key_unbound':
|
|
11
|
+
return 'not_found';
|
|
12
|
+
case 'read_error':
|
|
13
|
+
case 'record_malformed':
|
|
14
|
+
case 'input_unrecognized':
|
|
15
|
+
return 'unreadable';
|
|
16
|
+
default: {
|
|
17
|
+
const unreachable = why;
|
|
18
|
+
return unreachable;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function ownData(o, key) {
|
|
23
|
+
return guardedRead(() => readOwnDataValue(o, key));
|
|
24
|
+
}
|
|
25
|
+
function isJsonObject(v) {
|
|
26
|
+
if (typeof v !== 'object' || v === null)
|
|
27
|
+
return false;
|
|
28
|
+
try {
|
|
29
|
+
return !Array.isArray(v);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function admittedAtProves(v) {
|
|
36
|
+
if (typeof v !== 'string')
|
|
37
|
+
return false;
|
|
38
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/.exec(v);
|
|
39
|
+
if (m === null)
|
|
40
|
+
return false;
|
|
41
|
+
const year = Number(m[1]);
|
|
42
|
+
const month = Number(m[2]);
|
|
43
|
+
const day = Number(m[3]);
|
|
44
|
+
const leap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
45
|
+
const daysInMonth = month === 2 ? (leap ? 29 : 28) : month === 4 || month === 6 || month === 9 || month === 11 ? 30 : 31;
|
|
46
|
+
return month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth && Number.isFinite(Date.parse(v));
|
|
47
|
+
}
|
|
48
|
+
function recordWhy(record) {
|
|
49
|
+
if (admittedAtProves(ownData(record, 'admittedAt')))
|
|
50
|
+
return 'admitted_at';
|
|
51
|
+
const result = ownData(record, 'result');
|
|
52
|
+
const stats = isJsonObject(result) ? ownData(result, 'stats') : undefined;
|
|
53
|
+
const turns = isJsonObject(stats) ? ownData(stats, 'turns') : undefined;
|
|
54
|
+
if (typeof turns === 'number' && Number.isInteger(turns)) {
|
|
55
|
+
if (turns > 0)
|
|
56
|
+
return 'turns_positive';
|
|
57
|
+
if (turns === 0)
|
|
58
|
+
return 'zero_turns';
|
|
59
|
+
}
|
|
60
|
+
return 'no_turn_count';
|
|
61
|
+
}
|
|
62
|
+
function readWhy(readResult) {
|
|
63
|
+
if (typeof readResult !== 'object' || readResult === null)
|
|
64
|
+
return 'input_unrecognized';
|
|
65
|
+
const kind = ownData(readResult, 'kind');
|
|
66
|
+
if (kind === 'not_found')
|
|
67
|
+
return 'key_unbound';
|
|
68
|
+
if (kind === 'error')
|
|
69
|
+
return 'read_error';
|
|
70
|
+
if (kind !== 'record')
|
|
71
|
+
return 'input_unrecognized';
|
|
72
|
+
const record = ownData(readResult, 'record');
|
|
73
|
+
return isJsonObject(record) ? recordWhy(record) : 'record_malformed';
|
|
74
|
+
}
|
|
75
|
+
export function taskNotificationAdmissionOf(readResult) {
|
|
76
|
+
let why;
|
|
77
|
+
try {
|
|
78
|
+
why = readWhy(readResult);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
why = 'input_unrecognized';
|
|
82
|
+
}
|
|
83
|
+
return Object.freeze({ verdict: verdictOfWhy(why), why });
|
|
84
|
+
}
|
package/dist/toolResult.js
CHANGED
|
@@ -9,11 +9,12 @@ import { displayUntrusted } from './displayUntrusted.js';
|
|
|
9
9
|
import { isCoreSemaTaskTerminal } from './terminalStatuses.js';
|
|
10
10
|
import { CORE_ENGINE_CARD_TYPES } from './generated/engineFactTables.js';
|
|
11
11
|
export const STRUCTURED_DETAIL_TYPES = frozenSet(CORE_ENGINE_CARD_TYPES);
|
|
12
|
+
const LEGACY_STRUCTURED_DETAIL_TYPE = 'task-output';
|
|
12
13
|
export function structuredDetailType(structured) {
|
|
13
14
|
if (typeof structured !== 'object' || structured === null)
|
|
14
15
|
return undefined;
|
|
15
16
|
const t = structured.type;
|
|
16
|
-
return typeof t === 'string' && STRUCTURED_DETAIL_TYPES.has(t) ? t : undefined;
|
|
17
|
+
return typeof t === 'string' && (STRUCTURED_DETAIL_TYPES.has(t) || t === LEGACY_STRUCTURED_DETAIL_TYPE) ? t : undefined;
|
|
17
18
|
}
|
|
18
19
|
const MAX_STRUCTURED_FIELD_CHARS = 1_000_000;
|
|
19
20
|
export const PROTOCOL_MARKERS = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SETTINGS_IS_HIERARCHICAL_URL } from './generated/settingsSchemaFns.js';
|
|
2
2
|
import { hostEnv } from './hostEnv.js';
|
|
3
|
+
import { msg, renderMessage } from './i18n/translate.js';
|
|
3
4
|
export const WEBSEARCH_ENV = {
|
|
4
5
|
provider: 'SEMA_WEBSEARCH_PROVIDER',
|
|
5
6
|
endpoint: 'SEMA_WEBSEARCH_ENDPOINT',
|
|
@@ -49,6 +50,9 @@ function apiKeyHeaderValue(provider, key) {
|
|
|
49
50
|
return `Bearer ${key}`;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
53
|
+
function apiKeyWayOutSentence() {
|
|
54
|
+
return renderMessage(msg('config.webSearch.apiKeyWayOut'));
|
|
55
|
+
}
|
|
52
56
|
function judgeApiKey(provider, raw) {
|
|
53
57
|
const text = judgeText(raw);
|
|
54
58
|
if (!text.ok || text.value === undefined)
|
|
@@ -215,17 +219,18 @@ function envNameOfField(field) {
|
|
|
215
219
|
export function webSearchVerdictMessage(verdict, context = 'submit') {
|
|
216
220
|
if (verdict.kind !== 'malformed')
|
|
217
221
|
return undefined;
|
|
222
|
+
const wayOut = verdict.field === 'apiKey' && verdict.issue === API_KEY_ISSUE ? ` ${apiKeyWayOutSentence()}` : '';
|
|
218
223
|
if (verdict.source === 'host') {
|
|
219
224
|
const head = `Web search is misconfigured: the API key your host supplied for webSearch is malformed; it ${verdict.issue}.`;
|
|
220
225
|
return context === 'submit'
|
|
221
|
-
? `${head} The request was not sent — the key needs replacing where your host keeps it
|
|
222
|
-
: `${head} Requests will be refused until the key is replaced where your host keeps it
|
|
226
|
+
? `${head} The request was not sent — the key needs replacing where your host keeps it.${wayOut}`
|
|
227
|
+
: `${head} Requests will be refused until the key is replaced where your host keeps it.${wayOut}`;
|
|
223
228
|
}
|
|
224
229
|
const where = verdict.source === 'env' ? envNameOfField(verdict.field) : verdict.field === 'section' ? 'the webSearch section in settings' : `webSearch.${verdict.field} in settings`;
|
|
225
230
|
const fix = verdict.source === 'env' ? 'fix it or unset the SEMA_WEBSEARCH_* variables' : 'fix it or remove the webSearch section';
|
|
226
231
|
return context === 'submit'
|
|
227
|
-
? `Web search is misconfigured: ${where} ${verdict.issue}. The request was not sent — ${fix}
|
|
228
|
-
: `Web search is misconfigured: ${where} ${verdict.issue}. Requests will be refused until you ${fix}
|
|
232
|
+
? `Web search is misconfigured: ${where} ${verdict.issue}. The request was not sent — ${fix}.${wayOut}`
|
|
233
|
+
: `Web search is misconfigured: ${where} ${verdict.issue}. Requests will be refused until you ${fix}.${wayOut}`;
|
|
229
234
|
}
|
|
230
235
|
export function webSearchEndpointForDisplay(raw) {
|
|
231
236
|
if (typeof raw !== 'string' || !SETTINGS_IS_HIERARCHICAL_URL(raw))
|
|
@@ -143,7 +143,8 @@ export interface SessionArchiveStampedDetail {
|
|
|
143
143
|
readonly code: typeof CONFLICT_SESSION_ARCHIVE_STAMPED;
|
|
144
144
|
}
|
|
145
145
|
export declare function sessionArchiveStampedFromError(err: {} | null | undefined): SessionArchiveStampedDetail | null;
|
|
146
|
-
export
|
|
146
|
+
export type SessionArchiveStampedScenario = 'fork' | 'push';
|
|
147
|
+
export declare function sessionArchiveStampedContent(lang?: UiLanguage, scenario?: SessionArchiveStampedScenario): string;
|
|
147
148
|
export interface UnsupportedRuleRefusalProblem {
|
|
148
149
|
readonly code: string;
|
|
149
150
|
readonly field?: string;
|
package/dist/wireRefusalCopy.js
CHANGED
|
@@ -812,8 +812,8 @@ export function autonomyLaneRefusalContent(lang) {
|
|
|
812
812
|
export function sessionArchiveStampedFromError(err) {
|
|
813
813
|
return effectiveWireErrorCode(err) === CONFLICT_SESSION_ARCHIVE_STAMPED ? { code: CONFLICT_SESSION_ARCHIVE_STAMPED } : null;
|
|
814
814
|
}
|
|
815
|
-
export function sessionArchiveStampedContent(lang) {
|
|
816
|
-
return renderMessage(msg('notice.wireRefusal.sessionArchiveStamped'), lang);
|
|
815
|
+
export function sessionArchiveStampedContent(lang, scenario) {
|
|
816
|
+
return renderMessage(msg(scenario === 'fork' ? 'notice.wireRefusal.sessionArchiveStamped.fork' : 'notice.wireRefusal.sessionArchiveStamped'), lang);
|
|
817
817
|
}
|
|
818
818
|
const REQUEST_UNPROCESSABLE = 'request.unprocessable';
|
|
819
819
|
const UNSUPPORTED_RULE_PROBLEMS_MAX = REFUSAL_PROBLEMS_READ_MAX;
|