@sema-agent/client-core 0.98.0 → 0.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/CHANGELOG.md +376 -0
  2. package/README.md +61 -35
  3. package/dist/adapt/arms.js +120 -55
  4. package/dist/adapt/panelTasks.d.ts +3 -2
  5. package/dist/adapt/panelTasks.js +34 -11
  6. package/dist/adapt/textStream.d.ts +1 -1
  7. package/dist/adapt/textStream.js +51 -28
  8. package/dist/adapter/activeRunSelfHeal.d.ts +11 -3
  9. package/dist/adapter/activeRunSelfHeal.js +210 -294
  10. package/dist/adapter/downstream/eventToSdkMessage.d.ts +25 -6
  11. package/dist/adapter/downstream/eventToSdkMessage.js +176 -12
  12. package/dist/adapter/downstream/terminalToSdkResult.js +10 -0
  13. package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
  14. package/dist/adapter/downstream/wiringManifestView.js +1 -0
  15. package/dist/adapter/runStream.js +82 -40
  16. package/dist/adapter/types.d.ts +2 -0
  17. package/dist/adapter/types.js +2 -1
  18. package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
  19. package/dist/agentsWireCaps.d.ts +7 -3
  20. package/dist/agentsWireCaps.js +133 -39
  21. package/dist/cloudConfigWireCaps.d.ts +10 -1
  22. package/dist/cloudConfigWireCaps.js +181 -65
  23. package/dist/compactionStatus.d.ts +34 -0
  24. package/dist/compactionStatus.js +196 -0
  25. package/dist/controlRouter.d.ts +4 -2
  26. package/dist/controlRouter.js +39 -51
  27. package/dist/coreValuePorts.d.ts +26 -1
  28. package/dist/coreValuePorts.js +10 -0
  29. package/dist/corruptSessionCopy.d.ts +2 -1
  30. package/dist/corruptSessionCopy.js +3 -3
  31. package/dist/decideFailureNote.js +3 -3
  32. package/dist/declared/supportFloorDeclared.js +1 -1
  33. package/dist/detachWire.js +3 -2
  34. package/dist/devicesFace.d.ts +34 -0
  35. package/dist/devicesFace.js +90 -0
  36. package/dist/displayUntrusted.d.ts +1 -0
  37. package/dist/displayUntrusted.js +153 -5
  38. package/dist/engineAgentPanelStore.d.ts +14 -4
  39. package/dist/engineAgentPanelStore.js +14 -0
  40. package/dist/engineCapReader.d.ts +2 -1
  41. package/dist/engineCapReader.js +7 -5
  42. package/dist/engineCapsCache.d.ts +8 -0
  43. package/dist/engineCapsCache.js +59 -6
  44. package/dist/engineCapsChange.d.ts +2 -0
  45. package/dist/engineCapsChange.js +9 -0
  46. package/dist/engineErrorCodes.d.ts +11 -2
  47. package/dist/engineErrorCodes.js +11 -12
  48. package/dist/engineRowRef.js +4 -0
  49. package/dist/engineSessionMessages.d.ts +1 -0
  50. package/dist/engineSessionMessages.js +7 -1
  51. package/dist/engineTargetSeat.d.ts +27 -0
  52. package/dist/engineTargetSeat.js +199 -0
  53. package/dist/engineToolDirectory.d.ts +3 -0
  54. package/dist/engineToolDirectory.js +4 -2
  55. package/dist/engineWireFor.js +3 -8
  56. package/dist/env/uiLanguage.d.ts +2 -1
  57. package/dist/env/uiLanguage.js +3 -2
  58. package/dist/eventLeg.d.ts +7 -5
  59. package/dist/eventLeg.js +68 -49
  60. package/dist/fileHistoryCaptureCapability.d.ts +2 -4
  61. package/dist/fileHistoryCaptureCapability.js +12 -22
  62. package/dist/fileHistoryLegNotice.d.ts +2 -1
  63. package/dist/fileHistoryLegNotice.js +3 -3
  64. package/dist/frameBinding.d.ts +3 -0
  65. package/dist/frameBinding.js +12 -0
  66. package/dist/gateOutcome.js +16 -2
  67. package/dist/gateVocabulary.d.ts +8 -7
  68. package/dist/gateVocabulary.js +71 -73
  69. package/dist/generated/engineFactTables.d.ts +18 -1
  70. package/dist/generated/engineFactTables.js +56 -0
  71. package/dist/generated/engineNoticeTables.js +12 -3
  72. package/dist/generated/settingsSchemaFns.d.ts +18 -0
  73. package/dist/generated/settingsSchemaFns.js +70 -0
  74. package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
  75. package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
  76. package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -0
  77. package/dist/generated/settingsSchemaMcpRequestEntry.js +162 -0
  78. package/dist/generated/settingsSchemaTables.d.ts +2 -0
  79. package/dist/generated/settingsSchemaTables.js +9 -0
  80. package/dist/generated/settingsSchemaTypes.d.ts +133 -0
  81. package/dist/generated/settingsSchemaTypes.js +1 -0
  82. package/dist/hitl/allowRuleShadow.d.ts +2 -1
  83. package/dist/hitl/allowRuleShadow.js +18 -15
  84. package/dist/hitl/approvalCardReasons.d.ts +3 -2
  85. package/dist/hitl/approvalCardReasons.js +29 -30
  86. package/dist/hitl/approvalHolds.d.ts +17 -0
  87. package/dist/hitl/approvalHolds.js +114 -29
  88. package/dist/hitl/askClassPair.d.ts +2 -2
  89. package/dist/hitl/askClassPair.js +16 -0
  90. package/dist/hitl/askGateWire.js +2 -1
  91. package/dist/hitl/askSettlementLine.d.ts +14 -4
  92. package/dist/hitl/askSettlementLine.js +67 -47
  93. package/dist/hitl/attributionLadder.d.ts +23 -0
  94. package/dist/hitl/attributionLadder.js +67 -0
  95. package/dist/hitl/automaticAnswerVerdict.d.ts +2 -1
  96. package/dist/hitl/automaticAnswerVerdict.js +8 -8
  97. package/dist/hitl/crashConvergedNotice.d.ts +5 -4
  98. package/dist/hitl/crashConvergedNotice.js +28 -41
  99. package/dist/hitl/decisionLedger.d.ts +55 -0
  100. package/dist/hitl/decisionLedger.js +156 -0
  101. package/dist/hitl/decisionRefusal.d.ts +1 -0
  102. package/dist/hitl/decisionRefusal.js +1 -1
  103. package/dist/hitl/decisionSend.d.ts +113 -0
  104. package/dist/hitl/decisionSend.js +579 -0
  105. package/dist/hitl/frameRouter.js +7 -8
  106. package/dist/hitl/hitlBridge.d.ts +1 -0
  107. package/dist/hitl/hitlBridge.js +21 -9
  108. package/dist/hitl/persistedRulesWire.d.ts +6 -5
  109. package/dist/hitl/persistedRulesWire.js +55 -73
  110. package/dist/hitl/planReviewWire.d.ts +5 -0
  111. package/dist/hitl/planReviewWire.js +53 -76
  112. package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
  113. package/dist/hitl/sessionPolicyDeliverable.js +49 -9
  114. package/dist/hitl/sessionPolicyWire.d.ts +2 -1
  115. package/dist/hitl/sessionPolicyWire.js +23 -24
  116. package/dist/hitl/suspendedReopen.d.ts +2 -1
  117. package/dist/hitl/suspendedReopen.js +7 -10
  118. package/dist/hitl/toolApprovalWire.d.ts +17 -5
  119. package/dist/hitl/toolApprovalWire.js +120 -147
  120. package/dist/hooksWireCaps.js +145 -56
  121. package/dist/host.d.ts +21 -0
  122. package/dist/hostTurnSettings.d.ts +110 -0
  123. package/dist/hostTurnSettings.js +692 -0
  124. package/dist/humanTurn.d.ts +15 -1
  125. package/dist/humanTurn.js +100 -12
  126. package/dist/humanTurnRead.d.ts +2 -0
  127. package/dist/humanTurnRead.js +22 -1
  128. package/dist/i18n/messages.en.d.ts +713 -0
  129. package/dist/i18n/messages.en.js +713 -0
  130. package/dist/i18n/messages.zh.js +854 -1
  131. package/dist/index.d.ts +45 -13
  132. package/dist/index.js +27 -9
  133. package/dist/inheritEnvCapability.d.ts +4 -2
  134. package/dist/inheritEnvCapability.js +12 -5
  135. package/dist/inheritEnvWire.d.ts +3 -2
  136. package/dist/inheritEnvWire.js +14 -16
  137. package/dist/injectionLaneNotice.d.ts +5 -0
  138. package/dist/injectionLaneNotice.js +46 -0
  139. package/dist/interactiveHalt.js +17 -6
  140. package/dist/liveModelCatalog.d.ts +2 -1
  141. package/dist/liveModelCatalog.js +14 -8
  142. package/dist/mcpPanel.d.ts +10 -1
  143. package/dist/mcpPanel.js +42 -13
  144. package/dist/mcpProbeCapability.d.ts +2 -1
  145. package/dist/mcpProbeCapability.js +7 -11
  146. package/dist/mcpProbeWire.d.ts +3 -1
  147. package/dist/mcpProbeWire.js +5 -0
  148. package/dist/mcpReconnect.js +2 -2
  149. package/dist/mcpToolToggles.d.ts +6 -0
  150. package/dist/mcpToolToggles.js +46 -0
  151. package/dist/mcpWireCaps.d.ts +43 -3
  152. package/dist/mcpWireCaps.js +194 -59
  153. package/dist/mcpWireTransport.d.ts +4 -0
  154. package/dist/mcpWireTransport.js +18 -0
  155. package/dist/memoryEntriesWire.js +5 -10
  156. package/dist/model/onboardJudgement.d.ts +93 -0
  157. package/dist/model/onboardJudgement.js +415 -0
  158. package/dist/model/tierVocabulary.d.ts +2 -0
  159. package/dist/model/tierVocabulary.js +17 -5
  160. package/dist/modelCapabilityProbe.d.ts +65 -0
  161. package/dist/modelCapabilityProbe.js +601 -0
  162. package/dist/modelIdentityResolvability.d.ts +5 -0
  163. package/dist/modelIdentityResolvability.js +49 -22
  164. package/dist/ownKey.d.ts +33 -0
  165. package/dist/ownKey.js +109 -0
  166. package/dist/panelReduce.d.ts +11 -1
  167. package/dist/panelReduce.js +95 -16
  168. package/dist/panelStateHolder.d.ts +1 -0
  169. package/dist/panelStateHolder.js +10 -1
  170. package/dist/permissionRuleIssue.d.ts +2 -1
  171. package/dist/permissionRuleIssue.js +23 -20
  172. package/dist/permissionRulesWriteCapability.d.ts +2 -1
  173. package/dist/permissionRulesWriteCapability.js +8 -6
  174. package/dist/pluginHooksWire.d.ts +46 -3
  175. package/dist/pluginHooksWire.js +220 -12
  176. package/dist/prepareRefusal.d.ts +8 -0
  177. package/dist/prepareRefusal.js +72 -0
  178. package/dist/printModelStatus.d.ts +63 -0
  179. package/dist/printModelStatus.js +155 -0
  180. package/dist/request/taskRequest.d.ts +16 -10
  181. package/dist/request/taskRequest.js +195 -58
  182. package/dist/resumeRefusalCopy.d.ts +14 -9
  183. package/dist/resumeRefusalCopy.js +89 -144
  184. package/dist/retryStatus.d.ts +55 -0
  185. package/dist/retryStatus.js +155 -19
  186. package/dist/ruleRefusalSentence.d.ts +4 -0
  187. package/dist/ruleRefusalSentence.js +58 -0
  188. package/dist/sandboxWire.d.ts +2 -1
  189. package/dist/sandboxWire.js +55 -21
  190. package/dist/scenarioRefusal.d.ts +10 -0
  191. package/dist/scenarioRefusal.js +111 -0
  192. package/dist/seam.d.ts +48 -9
  193. package/dist/seam.js +54 -5
  194. package/dist/seatContract.d.ts +272 -14
  195. package/dist/seatContract.js +711 -23
  196. package/dist/selfOrchestrationDenial.js +7 -19
  197. package/dist/sessionIdSegment.d.ts +6 -0
  198. package/dist/sessionIdSegment.js +24 -0
  199. package/dist/sessionMemoryStatus.js +6 -11
  200. package/dist/sessionPolicyCapability.d.ts +2 -1
  201. package/dist/sessionPolicyCapability.js +8 -6
  202. package/dist/settingsCredentialKeyPaths.d.ts +8 -0
  203. package/dist/settingsCredentialKeyPaths.js +219 -0
  204. package/dist/settingsHooksSalvage.d.ts +44 -0
  205. package/dist/settingsHooksSalvage.js +211 -0
  206. package/dist/skillToolListsCapability.d.ts +2 -1
  207. package/dist/skillToolListsCapability.js +8 -6
  208. package/dist/skillsWireCaps.d.ts +0 -3
  209. package/dist/skillsWireCaps.js +1 -2
  210. package/dist/sseIdleTriage.js +3 -2
  211. package/dist/subagent/engineSubagentResume.js +15 -9
  212. package/dist/subagentContentStore.d.ts +4 -0
  213. package/dist/subagentContentStore.js +157 -27
  214. package/dist/toolHistoryMismatch.js +3 -2
  215. package/dist/toolRoster.d.ts +3 -2
  216. package/dist/toolRoster.js +21 -20
  217. package/dist/toolsFlagNames.d.ts +8 -0
  218. package/dist/toolsFlagNames.js +110 -0
  219. package/dist/turnFailurePresentation.d.ts +12 -1
  220. package/dist/turnFailurePresentation.js +220 -15
  221. package/dist/usageAnalytics.js +6 -11
  222. package/dist/userAttachmentEnvelope.d.ts +1 -0
  223. package/dist/userAttachmentEnvelope.js +37 -7
  224. package/dist/userAttachmentSeat.d.ts +21 -0
  225. package/dist/userAttachmentSeat.js +75 -0
  226. package/dist/userInvokedSkillsCapability.d.ts +11 -1
  227. package/dist/userInvokedSkillsCapability.js +31 -7
  228. package/dist/wireErrorTriage.d.ts +7 -0
  229. package/dist/wireErrorTriage.js +23 -1
  230. package/dist/wireFailureShape.js +2 -1
  231. package/dist/wireRefusalCopy.d.ts +62 -16
  232. package/dist/wireRefusalCopy.js +307 -148
  233. package/dist/workflowsJournalCapability.d.ts +2 -1
  234. package/dist/workflowsJournalCapability.js +8 -6
  235. package/docs/INTEGRATION-CLIENTS.md +951 -42
  236. package/package.json +5 -5
@@ -1,7 +1,8 @@
1
1
  import { cancelConflictContent, cancelConflictFromError } from './wireRefusalCopy.js';
2
- import { PROTOCOL_ERROR_NAME, protocolErrorNameOf } from './wireFailureShape.js';
2
+ import { PROTOCOL_ERROR_NAME, THROWN_SLOT_UNREADABLE, protocolErrorNameOf, readThrownSlot, readThrownStatusSlot } from './wireFailureShape.js';
3
3
  import { steerPriorityMode } from './steerPriorityCapability.js';
4
4
  import { preemptReadingOfAck, preemptReadingOfError } from './preemptWire.js';
5
+ import { msg, renderMessage } from './i18n/translate.js';
5
6
  export class ControlSafetyError extends Error {
6
7
  code;
7
8
  cause;
@@ -156,10 +157,11 @@ export class ControlRouter {
156
157
  export function errCodes(e) {
157
158
  if (!e || typeof e !== 'object')
158
159
  return {};
159
- const o = e;
160
- const code = typeof o.errorCode === 'string' ? o.errorCode : undefined;
161
- const name = typeof o.name === 'string' ? o.name : undefined;
162
- const rawStatus = o.status ?? o.statusCode;
160
+ const rawCode = readThrownSlot(e, 'errorCode', 'data');
161
+ const code = typeof rawCode === 'string' ? rawCode : undefined;
162
+ const rawName = readThrownSlot(e, 'name');
163
+ const name = typeof rawName === 'string' ? rawName : undefined;
164
+ const rawStatus = readThrownStatusSlot(e);
163
165
  const status = typeof rawStatus === 'number' ? rawStatus : undefined;
164
166
  return { code, name, status };
165
167
  }
@@ -185,48 +187,32 @@ const STEERING_NAME_TO_SAFETY = {
185
187
  SteeringError: 'steering_other',
186
188
  };
187
189
  const STEERING_COPY = {
188
- not_running: {
189
- 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',
190
- nextStep: 'check its current state and send the message to the run that is active',
191
- },
192
- invalid_content: {
193
- happened: 'the message was refused because its text contains control markers the engine does not accept, so nothing was delivered',
194
- nextStep: 'rewrite the message and send it again',
195
- },
196
- queue_full: {
197
- happened: 'that run is paused and already holds as many waiting messages as it can, so this one was not accepted',
198
- nextStep: 'send it again once the waiting messages have been delivered (when the run resumes or the session is woken)',
199
- },
200
- duplicate_input_id: {
201
- happened: 'a different instruction was already accepted under this idempotency key, and that earlier instruction stands',
202
- 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',
203
- },
204
- ambiguous_target: {
205
- happened: 'more than one running agent matches that target, so the message was not delivered',
206
- 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',
207
- },
208
- still_running: {
209
- happened: 'that agent is still running, so it cannot be resumed',
210
- nextStep: 'send it a message instead, or wait for it to finish',
211
- },
212
- blocked_by_hook: {
213
- happened: "the message was not accepted: a prompt check on this deployment blocked it, so nothing was delivered",
214
- nextStep: 'edit the message and send it again — that is not a duplicate submission',
215
- },
216
- ledger_unavailable: {
217
- happened: 'the server could not record the message and refused it before anything reached the engine, so nothing was delivered',
218
- nextStep: 'send the same text again later',
219
- },
220
- steering_other: {
221
- happened: 'the message was refused for a reason this version does not recognise, so it did not land',
222
- nextStep: 'report its error code if this keeps happening; do not guess what it means',
223
- },
190
+ not_running: { happened: 'session.steerRefusal.notRunning.happened', nextStep: 'session.steerRefusal.notRunning.nextStep' },
191
+ invalid_content: { happened: 'session.steerRefusal.invalidContent.happened', nextStep: 'session.steerRefusal.invalidContent.nextStep' },
192
+ queue_full: { happened: 'session.steerRefusal.queueFull.happened', nextStep: 'session.steerRefusal.queueFull.nextStep' },
193
+ duplicate_input_id: { happened: 'session.steerRefusal.duplicateInputId.happened', nextStep: 'session.steerRefusal.duplicateInputId.nextStep' },
194
+ ambiguous_target: { happened: 'session.steerRefusal.ambiguousTarget.happened', nextStep: 'session.steerRefusal.ambiguousTarget.nextStep' },
195
+ still_running: { happened: 'session.steerRefusal.stillRunning.happened', nextStep: 'session.steerRefusal.stillRunning.nextStep' },
196
+ blocked_by_hook: { happened: 'session.steerRefusal.blockedByHook.happened', nextStep: 'session.steerRefusal.blockedByHook.nextStep' },
197
+ ledger_unavailable: { happened: 'session.steerRefusal.ledgerUnavailable.happened', nextStep: 'session.steerRefusal.ledgerUnavailable.nextStep' },
198
+ steering_other: { happened: 'session.steerRefusal.steeringOther.happened', nextStep: 'session.steerRefusal.steeringOther.nextStep' },
224
199
  };
225
- const adviceOfCopy = (c) => `${c.happened} — ${c.nextStep}`;
226
- const STEERING_ADVICE = Object.freeze(Object.fromEntries(Object.entries(STEERING_COPY).map(([k, c]) => [k, adviceOfCopy(c)])));
200
+ const adviceOfCopy = (c, lang) => renderMessage(msg('session.steerRefusal.advice', { happened: c.happened, nextStep: c.nextStep }), lang);
201
+ function hostQueueFactOf(v) {
202
+ return v === 'queued_until_turn_end' || v === 'dropped' ? v : 'unknown';
203
+ }
204
+ function renderedCopyOf(keys, lang, hostQueue) {
205
+ const happened = renderMessage(msg(keys.happened), lang);
206
+ const tableNextStep = renderMessage(msg(keys.nextStep), lang);
207
+ if (hostQueue === 'queued_until_turn_end')
208
+ return { happened, nextStep: renderMessage(msg('session.steerRefusal.hostQueue.queued'), lang) };
209
+ if (hostQueue === 'dropped')
210
+ return { happened, nextStep: renderMessage(msg('session.steerRefusal.hostQueue.dropped', { nextStep: tableNextStep }), lang) };
211
+ return { happened, nextStep: tableNextStep };
212
+ }
227
213
  const STEERING_OTHER_UNKNOWN_COPY = {
228
- happened: 'the message was refused for a reason this version does not recognise, and whether it was delivered is not known',
229
- 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',
214
+ happened: 'session.steerRefusal.steeringOtherUnknown.happened',
215
+ nextStep: 'session.steerRefusal.steeringOtherUnknown.nextStep',
230
216
  };
231
217
  const CANCEL_NOT_FOUND_COPY = {
232
218
  happened: 'this server has no run with that id for you — it does not exist, or it belongs to someone else',
@@ -262,7 +248,7 @@ function steeringCopyOf(e, safety) {
262
248
  return STEERING_COPY[safety];
263
249
  }
264
250
  const STEERING_REFUSED_BEFORE_ENGINE = new Map([['ledger_unavailable', 503]]);
265
- export function steeringRefusedBeforeEngine(e) {
251
+ export function steeringRefusedBeforeEngine(e, hostQueue, lang) {
266
252
  try {
267
253
  const { status } = errCodes(e);
268
254
  if (status === undefined)
@@ -270,8 +256,8 @@ export function steeringRefusedBeforeEngine(e) {
270
256
  const safety = steeringVerdict(e);
271
257
  if (safety === undefined || STEERING_REFUSED_BEFORE_ENGINE.get(safety) !== status)
272
258
  return undefined;
273
- const copy = STEERING_COPY[safety];
274
- return { safety, advice: STEERING_ADVICE[safety], happened: copy.happened, nextStep: copy.nextStep };
259
+ const copy = renderedCopyOf(STEERING_COPY[safety], lang, hostQueueFactOf(hostQueue));
260
+ return { safety, advice: adviceOfCopy(copy, lang), happened: copy.happened, nextStep: copy.nextStep };
275
261
  }
276
262
  catch {
277
263
  return undefined;
@@ -288,17 +274,19 @@ function steeringVerdict(e) {
288
274
  if (typeof code === 'string' && code.startsWith('steering.')) {
289
275
  return STEERING_CODE_TO_SAFETY.get(code) ?? 'steering_other';
290
276
  }
277
+ if (readThrownSlot(e, 'errorCode', 'data') === THROWN_SLOT_UNREADABLE)
278
+ return undefined;
291
279
  const protocolName = protocolErrorNameOf(e);
292
280
  return protocolName !== undefined ? STEERING_NAME_TO_SAFETY[protocolName] : undefined;
293
281
  }
294
- export function steerRefusalAdviceOf(e) {
282
+ export function steerRefusalAdviceOf(e, hostQueue, lang) {
295
283
  try {
296
284
  const verdict = steeringVerdict(e);
297
285
  if (verdict === undefined)
298
286
  return undefined;
299
287
  const safety = steeringSafetyOf(e, verdict);
300
- const copy = steeringCopyOf(e, safety);
301
- return { safety, advice: adviceOfCopy(copy), happened: copy.happened, nextStep: copy.nextStep };
288
+ const copy = renderedCopyOf(steeringCopyOf(e, safety), lang, hostQueueFactOf(hostQueue));
289
+ return { safety, advice: adviceOfCopy(copy, lang), happened: copy.happened, nextStep: copy.nextStep };
302
290
  }
303
291
  catch {
304
292
  return undefined;
@@ -97,6 +97,27 @@ export interface RuleToolNameVerdictView {
97
97
  readonly guidance?: string;
98
98
  readonly currentName?: string;
99
99
  }
100
+ export type RuleEntryReadingView = {
101
+ readonly kind: 'row';
102
+ readonly compiled: RuleEntryCompiledView;
103
+ } | {
104
+ readonly kind: 'inert';
105
+ readonly reason: string;
106
+ readonly verdict?: string;
107
+ readonly guidance?: string;
108
+ readonly currentName?: string;
109
+ readonly valueType?: string;
110
+ };
111
+ export interface RuleEntryCompiledView {
112
+ readonly kind: string;
113
+ }
114
+ export type McpToolAxesReadView = {
115
+ readonly ok: true;
116
+ readonly toolAxes?: Readonly<Record<string, object>>;
117
+ } | {
118
+ readonly ok: false;
119
+ readonly problem: string;
120
+ };
100
121
  export interface CoreValuePorts {
101
122
  resolveAutonomousLoopPrompt: (prompt: string, opts?: AutonomousLoopPromptOptionsView) => string | null;
102
123
  loosenReasons: (prior: SessionPermissionRules, next: SessionPermissionRules) => string[];
@@ -118,8 +139,10 @@ export interface CoreValuePorts {
118
139
  adjudicateRoute?(model: RouteModelView, perModelAuth?: PerModelAuthView): RouteAdjudicationView | undefined;
119
140
  }, model: RouteModelView, perModelAuth?: PerModelAuthView): RoutePairingStatusView;
120
141
  judgeRuleToolName(name: string, roster: ReadonlySet<string>): RuleToolNameVerdictView;
142
+ readRuleEntry(raw: {} | null | undefined, behavior: 'allow' | 'deny', roster?: ReadonlySet<string>): RuleEntryReadingView;
143
+ readMcpToolAxes(declared: {} | null | undefined): McpToolAxesReadView;
121
144
  }
122
- export declare const CORE_VALUE_PORT_NAMES: readonly ["resolveAutonomousLoopPrompt", "loosenReasons", "combinePolicies", "createAllowDenyPolicy", "MCP_NAMESPACE", "protocolOf", "ruleToolGrammarOf", "validatePermissionRules", "mintNamespacePrefix", "compileAllowList", "routeKeyOf", "joinRequestUrl", "resolveRouteCredential", "adjudicateModelRoute", "routePairingStatus", "judgeRuleToolName"];
145
+ export declare const CORE_VALUE_PORT_NAMES: readonly ["resolveAutonomousLoopPrompt", "loosenReasons", "combinePolicies", "createAllowDenyPolicy", "MCP_NAMESPACE", "protocolOf", "ruleToolGrammarOf", "validatePermissionRules", "mintNamespacePrefix", "compileAllowList", "routeKeyOf", "joinRequestUrl", "resolveRouteCredential", "adjudicateModelRoute", "routePairingStatus", "judgeRuleToolName", "readRuleEntry", "readMcpToolAxes"];
123
146
  export type CoreValuePortName = (typeof CORE_VALUE_PORT_NAMES)[number];
124
147
  export declare function installCoreValuePorts(ports: Partial<CoreValuePorts> | null): () => void;
125
148
  export declare function hasCoreValuePorts(): boolean;
@@ -145,3 +168,5 @@ export declare function adjudicateModelRoute(model: RouteModelView, credential:
145
168
  export declare function routePairingStatus(brain: {
146
169
  adjudicateRoute?(model: RouteModelView, perModelAuth?: PerModelAuthView): RouteAdjudicationView | undefined;
147
170
  }, model: RouteModelView, perModelAuth?: PerModelAuthView): RoutePairingStatusView | undefined;
171
+ export declare function readRuleEntry(raw: {} | null | undefined, behavior: 'allow' | 'deny', roster?: ReadonlySet<string>): RuleEntryReadingView | undefined;
172
+ export declare function readMcpToolAxes(declared: {} | null | undefined): McpToolAxesReadView | undefined;
@@ -15,6 +15,8 @@ export const CORE_VALUE_PORT_NAMES = Object.freeze([
15
15
  'adjudicateModelRoute',
16
16
  'routePairingStatus',
17
17
  'judgeRuleToolName',
18
+ 'readRuleEntry',
19
+ 'readMcpToolAxes',
18
20
  ]);
19
21
  let installed = null;
20
22
  export function installCoreValuePorts(ports) {
@@ -99,3 +101,11 @@ export function routePairingStatus(brain, model, perModelAuth) {
99
101
  const fn = port('routePairingStatus');
100
102
  return fn === undefined ? undefined : fn(brain, model, perModelAuth);
101
103
  }
104
+ export function readRuleEntry(raw, behavior, roster) {
105
+ const fn = port('readRuleEntry');
106
+ return fn === undefined ? undefined : fn(raw, behavior, roster);
107
+ }
108
+ export function readMcpToolAxes(declared) {
109
+ const fn = port('readMcpToolAxes');
110
+ return fn === undefined ? undefined : fn(declared);
111
+ }
@@ -1 +1,2 @@
1
- export declare function corruptSessionContent(): string;
1
+ import type { UiLanguage } from './env/uiLanguage.js';
2
+ export declare function corruptSessionContent(lang?: UiLanguage): string;
@@ -1,4 +1,4 @@
1
- export function corruptSessionContent() {
2
- return ("This session's saved history cannot be read — its stored log is damaged — so the engine cannot open this session. " +
3
- 'Retrying will not help: whoever operates this engine has to repair or remove that stored log. Until then, continue in a new session.');
1
+ import { msg, renderMessage } from './i18n/translate.js';
2
+ export function corruptSessionContent(lang) {
3
+ return renderMessage(msg('session.corrupt.content'), lang);
4
4
  }
@@ -1,21 +1,21 @@
1
1
  import { corruptStoredRowContent, corruptStoredRowWhere, scenarioDenyFromError, scenarioNotAllowedContent } from './wireErrorTriage.js';
2
2
  import { checkpointUnsupportedVersionContent, checkpointUnsupportedVersionFromError, parkedResumeStartupContent, parkedResumeStartupFromError, resumePolicyBlockContent, resumePolicyBlockFromError, } from './resumeRefusalCopy.js';
3
3
  import { askGoneContent, askGoneFromError, decideParkMovedContent, decideParkMovedFromError } from './decideReceipt.js';
4
- import { settingsPermissionBucketRefusalContent, settingsPermissionBucketRefusalFromError } from './wireRefusalCopy.js';
4
+ import { fieldLimitRefusalContent, fieldLimitRefusalFromError } from './wireRefusalCopy.js';
5
5
  import { DECISION_ANSWER_INVALID_CONTENT, decisionConflictOf } from './hitl/decisionConflict.js';
6
6
  export function decideFailureNote(err, decision) {
7
7
  const where = corruptStoredRowWhere(err);
8
8
  const fold = resumePolicyBlockFromError(err);
9
9
  const startup = parkedResumeStartupFromError(err, decision);
10
10
  const moved = decideParkMovedFromError(err);
11
- const bucket = settingsPermissionBucketRefusalFromError(err);
11
+ const bucket = fieldLimitRefusalFromError(err);
12
12
  const scenario = scenarioDenyFromError(err);
13
13
  const unsupported = checkpointUnsupportedVersionFromError(err);
14
14
  const gone = askGoneFromError(err);
15
15
  const answerInvalid = decisionConflictOf(err) === 'answer_invalid';
16
16
  return ((where === undefined ? '' : ` — ${corruptStoredRowContent(where)}`) +
17
17
  (fold === null ? '' : ` — ${resumePolicyBlockContent(fold)}`) +
18
- (bucket === null ? '' : ` — ${settingsPermissionBucketRefusalContent(bucket)}`) +
18
+ (bucket === null ? '' : ` — ${fieldLimitRefusalContent(bucket)}`) +
19
19
  (scenario === null ? '' : ` — ${scenarioNotAllowedContent(scenario, undefined, 'resumed_work')}`) +
20
20
  (startup === null ? '' : ` — ${parkedResumeStartupContent(startup)}`) +
21
21
  (moved === null ? '' : ` — ${decideParkMovedContent(moved)}`) +
@@ -1,5 +1,5 @@
1
1
  export const DECLARED_SUPPORT_FLOOR = Object.freeze({
2
2
  server: "7.129.1",
3
3
  core: "7.51.2",
4
- sdk: "23.0.2",
4
+ sdk: "23.1.0",
5
5
  });
@@ -1,5 +1,6 @@
1
1
  import { hostEnv } from './hostEnv.js';
2
2
  import { envFlagOff } from './envFlag.js';
3
+ import { readThrownSlot } from './wireFailureShape.js';
3
4
  import { resolveWireAuth } from './engineWireSdk.js';
4
5
  export const DETACH_HEADER = 'x-detach-on-disconnect';
5
6
  export const HEADLESS_DETACH_ENV = 'SEMA_HEADLESS_DETACH';
@@ -13,10 +14,10 @@ export async function resolveHeadlessDetach(env = hostEnv()) {
13
14
  }
14
15
  export const DETACH_DURABLE_OFF_400_ANCHOR = 'x-detach-on-disconnect requires a durable run';
15
16
  export function isDetachDurableOff400(err) {
17
+ if (readThrownSlot(err, 'status', 'data') !== 400)
18
+ return false;
16
19
  try {
17
20
  const e = err;
18
- if (e?.status !== 400)
19
- return false;
20
21
  const msg = e?.message;
21
22
  return typeof msg === 'string' && msg.includes(DETACH_DURABLE_OFF_400_ANCHOR);
22
23
  }
@@ -0,0 +1,34 @@
1
+ import { type SeatCapabilityReading } from './seatContract.js';
2
+ import { type DeviceExecutorManagementReading } from './deviceExecutorManagementCapability.js';
3
+ import type { DeviceListOutcome } from './deviceRebind.js';
4
+ import type { UiLanguage } from './env/uiLanguage.js';
5
+ export type DevicesFaceUnavailableWhy = 'host_not_wired' | 'host_not_reported' | 'host_report_unreadable' | 'lane_absent' | 'lane_unreported';
6
+ export type DevicesFace = {
7
+ readonly kind: 'unavailable';
8
+ readonly why: DevicesFaceUnavailableWhy;
9
+ } | {
10
+ readonly kind: 'probe_pending';
11
+ } | {
12
+ readonly kind: 'probe_failed';
13
+ readonly retryable: true;
14
+ readonly cause: 'transport' | 'refused' | 'unreadable';
15
+ } | {
16
+ readonly kind: 'verbs_off';
17
+ } | {
18
+ readonly kind: 'manage';
19
+ readonly probe: boolean;
20
+ };
21
+ export interface DevicesFaceInput {
22
+ readonly host: {
23
+ readonly kind: 'seat';
24
+ readonly capability: SeatCapabilityReading;
25
+ } | {
26
+ readonly kind: 'direct';
27
+ readonly sliceArmed: boolean;
28
+ };
29
+ readonly engine?: DeviceExecutorManagementReading | undefined;
30
+ readonly lastList?: DeviceListOutcome | undefined;
31
+ }
32
+ export declare function devicesFaceOf(input: DevicesFaceInput): DevicesFace;
33
+ export declare function devicesWritesAllowed(face: DevicesFace): boolean;
34
+ export declare function devicesFaceDetail(face: DevicesFace, lang?: UiLanguage): string | undefined;
@@ -0,0 +1,90 @@
1
+ import { seatCapabilityUnavailableDetail } from './seatContract.js';
2
+ import { deviceLaneOpen, deviceManagementVerbsAvailable } from './deviceExecutorManagementCapability.js';
3
+ import { ownDataField } from './ownKey.js';
4
+ import { msg, renderMessage } from './i18n/translate.js';
5
+ const freeze = (v) => Object.freeze(v);
6
+ const field = (v, key) => {
7
+ if (v === null || typeof v !== 'object')
8
+ return undefined;
9
+ try {
10
+ return ownDataField(v, key);
11
+ }
12
+ catch {
13
+ return undefined;
14
+ }
15
+ };
16
+ function hostProblem(host) {
17
+ const kind = field(host, 'kind');
18
+ if (kind === 'direct')
19
+ return field(host, 'sliceArmed') === true ? undefined : 'host_not_wired';
20
+ if (kind !== 'seat')
21
+ return 'host_report_unreadable';
22
+ const reading = field(host, 'capability');
23
+ const rk = field(reading, 'kind');
24
+ if (rk === 'reported')
25
+ return field(reading, 'available') === true ? undefined : 'host_not_wired';
26
+ if (rk === 'not_reported')
27
+ return 'host_not_reported';
28
+ return 'host_report_unreadable';
29
+ }
30
+ export function devicesFaceOf(input) {
31
+ const engineRaw = field(input, 'engine');
32
+ const engine = { kind: field(engineRaw, 'kind'), management: field(engineRaw, 'management') };
33
+ const lane = deviceLaneOpen(engine);
34
+ const listKind = field(field(input, 'lastList'), 'kind');
35
+ if (lane === 'no' || listKind === 'lane-absent')
36
+ return freeze({ kind: 'unavailable', why: 'lane_absent' });
37
+ const host = field(input, 'host');
38
+ const hostWhy = hostProblem(host);
39
+ if (hostWhy !== undefined)
40
+ return freeze({ kind: 'unavailable', why: hostWhy });
41
+ if (listKind === 'unarmed')
42
+ return freeze({ kind: 'unavailable', why: 'host_not_wired' });
43
+ if (lane === 'unknown') {
44
+ if (field(host, 'kind') === 'direct')
45
+ return freeze({ kind: 'unavailable', why: 'lane_unreported' });
46
+ if (listKind === undefined)
47
+ return freeze({ kind: 'probe_pending' });
48
+ if (listKind === 'ok')
49
+ return freeze({ kind: 'manage', probe: true });
50
+ const cause = listKind === 'transport' || listKind === 'refused' ? listKind : 'unreadable';
51
+ return freeze({ kind: 'probe_failed', retryable: true, cause });
52
+ }
53
+ const verbs = deviceManagementVerbsAvailable(engine);
54
+ if (verbs === 'no')
55
+ return freeze({ kind: 'verbs_off' });
56
+ return freeze({ kind: 'manage', probe: verbs === 'unknown' });
57
+ }
58
+ export function devicesWritesAllowed(face) {
59
+ return field(face, 'kind') === 'manage';
60
+ }
61
+ const UNWIRED = freeze({ kind: 'reported', available: false });
62
+ const NOT_REPORTED = freeze({ kind: 'not_reported' });
63
+ const MALFORMED = freeze({ kind: 'malformed' });
64
+ export function devicesFaceDetail(face, lang) {
65
+ const kind = field(face, 'kind');
66
+ if (kind === 'manage')
67
+ return undefined;
68
+ if (kind === 'probe_pending')
69
+ return renderMessage(msg('session.devices.probePending'), lang);
70
+ if (kind === 'verbs_off')
71
+ return renderMessage(msg('session.devices.verbsOff'), lang);
72
+ if (kind === 'probe_failed') {
73
+ const cause = field(face, 'cause');
74
+ if (cause === 'transport')
75
+ return renderMessage(msg('session.devices.probeFailedTransport'), lang);
76
+ if (cause === 'refused')
77
+ return renderMessage(msg('session.devices.probeFailedRefused'), lang);
78
+ return renderMessage(msg('session.devices.probeFailedUnreadable'), lang);
79
+ }
80
+ const why = kind === 'unavailable' ? field(face, 'why') : undefined;
81
+ if (why === 'lane_absent')
82
+ return renderMessage(msg('session.devices.laneAbsent'), lang);
83
+ if (why === 'lane_unreported')
84
+ return renderMessage(msg('session.devices.laneUnreported'), lang);
85
+ if (why === 'host_not_wired')
86
+ return seatCapabilityUnavailableDetail('devices', UNWIRED);
87
+ if (why === 'host_not_reported')
88
+ return seatCapabilityUnavailableDetail('devices', NOT_REPORTED);
89
+ return seatCapabilityUnavailableDetail('devices', MALFORMED);
90
+ }
@@ -44,6 +44,7 @@ export declare function credentialWashPasses(text: string, opts?: DisplayUntrust
44
44
  capped: boolean;
45
45
  };
46
46
  export declare function displayUntrusted(text: string, opts?: DisplayUntrustedOptions): string;
47
+ export declare function cleanUntrustedScalar(v: string | number | bigint | boolean | null | undefined): string;
47
48
  export declare function queryCarriesCredential(query: string): boolean;
48
49
  export declare function displayConfiguredUrl(url: string, opts?: DisplayUntrustedOptions): string;
49
50
  export declare function quoteUntrustedForSentence(text: string, max: number): string | undefined;
@@ -43,6 +43,9 @@ export function looksLikeKnownSecret(s) {
43
43
  for (let layer = 0; layer < 4; layer++) {
44
44
  if (scanForSecretLiteral(cur))
45
45
  return true;
46
+ const wide = percentBoundaryDecode(cur);
47
+ if (wide !== null && scanForSecretLiteral(wide.decoded))
48
+ return true;
46
49
  const next = percentDecodeForMatching(cur).decoded;
47
50
  if (next === cur)
48
51
  break;
@@ -301,7 +304,7 @@ function pathCandidates(src, base, path, opaqueSegments, edits, soft) {
301
304
  if (opaqueSegments) {
302
305
  let a = 0;
303
306
  let b = head.length;
304
- while (a < b && !isKeyWordChar(head.charCodeAt(a)))
307
+ while (a < b && !isKeyWordChar(head.charCodeAt(a)) && !(head.charCodeAt(a) === 0x25 && hasNonAsciiPercentEscape(head.slice(a, a + 3))))
305
308
  a++;
306
309
  while (b > a && !isKeyWordChar(head.charCodeAt(b - 1)))
307
310
  b--;
@@ -1321,10 +1324,93 @@ function percentDecodeForMatching(text) {
1321
1324
  return { decoded: chars.join(''), offsets };
1322
1325
  }
1323
1326
  const PERCENT_ESCAPE_ASCII = /%[0-7][0-9A-Fa-f]/;
1327
+ function hasNonAsciiPercentEscape(text) {
1328
+ return /%[89A-Fa-f][0-9A-Fa-f]/.test(text);
1329
+ }
1330
+ function isWellFormedUtf8(bytes) {
1331
+ for (let i = 0; i < bytes.length;) {
1332
+ const lead = bytes[i] ?? 0;
1333
+ if (lead < 0x80) {
1334
+ i += 1;
1335
+ continue;
1336
+ }
1337
+ const need = utf8TailLength(lead);
1338
+ if (need === 0)
1339
+ return false;
1340
+ for (let k = 1; k <= need; k++) {
1341
+ const c = bytes[i + k];
1342
+ const lo = k === 1 ? (lead === 0xe0 ? 0xa0 : lead === 0xf0 ? 0x90 : 0x80) : 0x80;
1343
+ const hi = k === 1 ? (lead === 0xed ? 0x9f : lead === 0xf4 ? 0x8f : 0xbf) : 0xbf;
1344
+ if (c === undefined || c < lo || c > hi)
1345
+ return false;
1346
+ }
1347
+ i += need + 1;
1348
+ }
1349
+ return true;
1350
+ }
1351
+ function utf8TailLength(lead) {
1352
+ if (lead >= 0xc2 && lead <= 0xdf)
1353
+ return 1;
1354
+ if (lead >= 0xe0 && lead <= 0xef)
1355
+ return 2;
1356
+ if (lead >= 0xf0 && lead <= 0xf4)
1357
+ return 3;
1358
+ return 0;
1359
+ }
1360
+ function percentBoundaryDecode(text) {
1361
+ if (!hasNonAsciiPercentEscape(text))
1362
+ return null;
1363
+ const chars = [];
1364
+ const from = [];
1365
+ const to = [];
1366
+ const escapeAt = (k) => text.charCodeAt(k) === 0x25 && isHexDigit(text.charAt(k + 1)) && isHexDigit(text.charAt(k + 2));
1367
+ let i = 0;
1368
+ while (i < text.length) {
1369
+ if (!escapeAt(i)) {
1370
+ chars.push(text.charAt(i));
1371
+ from.push(i);
1372
+ to.push(i + 1);
1373
+ i += 1;
1374
+ continue;
1375
+ }
1376
+ const bytes = [];
1377
+ let j = i;
1378
+ while (escapeAt(j)) {
1379
+ bytes.push(Number.parseInt(text.slice(j + 1, j + 3), 16));
1380
+ j += 3;
1381
+ }
1382
+ if (isWellFormedUtf8(bytes)) {
1383
+ for (let k = 0; k < bytes.length;) {
1384
+ const lead = bytes[k] ?? 0;
1385
+ const len = lead < 0x80 ? 1 : utf8TailLength(lead) + 1;
1386
+ let cp = len === 1 ? lead : lead & (0xff >> (len + 1));
1387
+ for (let t = 1; t < len; t++)
1388
+ cp = (cp << 6) | ((bytes[k + t] ?? 0) & 0x3f);
1389
+ const ch = String.fromCodePoint(cp);
1390
+ for (let u = 0; u < ch.length; u++) {
1391
+ chars.push(ch.charAt(u));
1392
+ from.push(i + k * 3);
1393
+ to.push(i + (k + len) * 3);
1394
+ }
1395
+ k += len;
1396
+ }
1397
+ }
1398
+ else {
1399
+ for (let k = 0; k < bytes.length; k++) {
1400
+ const b = bytes[k] ?? 0;
1401
+ chars.push(b < 0x80 ? String.fromCharCode(b) : ' ');
1402
+ from.push(i + k * 3);
1403
+ to.push(i + k * 3 + 3);
1404
+ }
1405
+ }
1406
+ i = j;
1407
+ }
1408
+ return { decoded: chars.join(''), from, to };
1409
+ }
1324
1410
  const MAX_PERCENT_VIEW_LAYERS = 3;
1325
1411
  function percentLayers(text) {
1326
1412
  const out = [];
1327
- if (!PERCENT_ESCAPE_ASCII.test(text))
1413
+ if (!PERCENT_ESCAPE_ASCII.test(text) && !hasNonAsciiPercentEscape(text))
1328
1414
  return out;
1329
1415
  let cur = text;
1330
1416
  let ps = null;
@@ -1347,6 +1433,22 @@ function percentLayers(text) {
1347
1433
  ps = nps;
1348
1434
  pe = npe;
1349
1435
  }
1436
+ const bases = [[text, null, null], ...out.map((l) => [l.text, l.ps, l.pe])];
1437
+ for (const [base, bps, bpe] of bases) {
1438
+ const wide = percentBoundaryDecode(base);
1439
+ if (wide === null)
1440
+ continue;
1441
+ const n = wide.decoded.length;
1442
+ const nps = new Int32Array(n);
1443
+ const npe = new Int32Array(n);
1444
+ for (let k = 0; k < n; k++) {
1445
+ const a = wide.from[k] ?? 0;
1446
+ const b = wide.to[k] ?? base.length;
1447
+ nps[k] = bps === null ? a : (bps[a] ?? 0);
1448
+ npe[k] = bpe === null ? b : (bpe[b - 1] ?? 0);
1449
+ }
1450
+ out.push({ text: wide.decoded, ps: nps, pe: npe });
1451
+ }
1350
1452
  return out;
1351
1453
  }
1352
1454
  function firstLabelCutInPath(path, outer = false) {
@@ -3312,7 +3414,7 @@ function proseLiteralEdits(text) {
3312
3414
  let end = i;
3313
3415
  while (end < text.length && isKeyWordChar(text.charCodeAt(end)))
3314
3416
  end++;
3315
- const escHead = i > 0 && text.charCodeAt(i - 1) === 0x25 && PERCENT_ESCAPE_ASCII.test(text.slice(i - 1, i + 2)) && i + 2 < end ? 2 : 0;
3417
+ const escHead = i > 0 && text.charCodeAt(i - 1) === 0x25 && (PERCENT_ESCAPE_ASCII.test(text.slice(i - 1, i + 2)) || hasNonAsciiPercentEscape(text.slice(i - 1, i + 2))) && i + 2 < end ? 2 : 0;
3316
3418
  const word = text.slice(i, end);
3317
3419
  if (word.startsWith('eyJ')) {
3318
3420
  let segEnd = end;
@@ -4134,11 +4236,19 @@ function collectCandidates(text, o, nested) {
4134
4236
  for (const S of surfaces) {
4135
4237
  const cands = [];
4136
4238
  const regions = [];
4239
+ const unitPos = (k) => S.dropped(k) || V.rawUnit[S.rawStart(k)] === 1;
4137
4240
  if (o.urls) {
4138
- const unitPos = (k) => S.dropped(k) || V.rawUnit[S.rawStart(k)] === 1;
4139
4241
  urlCandidates(S.text, cands, regions, unitPos, (k) => unitPos(k) || S.painted(k), o.queryByShape ?? false, o.wholeAddress === true, o.wholeAddress === true && S.decoded !== true);
4140
4242
  userinfoCandidates(S, cands, o.words);
4141
4243
  }
4244
+ else if (o.words && o.wholeAddress === true) {
4245
+ const scratch = [];
4246
+ const hostOnly = [];
4247
+ urlCandidates(S.text, scratch, hostOnly, unitPos, (k) => unitPos(k) || S.painted(k), false, true, S.decoded !== true);
4248
+ for (const r of hostOnly)
4249
+ if (r[2] === 'host')
4250
+ regions.push(r);
4251
+ }
4142
4252
  if (o.words) {
4143
4253
  editsToCandidates(pemEdits(S, (blk) => { if (S === regionSurface)
4144
4254
  pemBlocksSeen.push(pemBlockToRaw(S, blk)); }), 'pem', cands);
@@ -4663,6 +4773,9 @@ export function displayUntrusted(text, opts = {}) {
4663
4773
  const out = renderUntrusted(text, opts, null);
4664
4774
  return typeof out === 'string' ? out : out.text;
4665
4775
  }
4776
+ export function cleanUntrustedScalar(v) {
4777
+ return displayUntrusted(String(v ?? ''), { credentialUrls: false, credentialWords: false, foldLines: false });
4778
+ }
4666
4779
  const NON_SECRET_FIELD_NAMES = new Set([
4667
4780
  'deployment', 'deploymentname', 'deploymentid', 'name', 'tenant', 'tenantname', 'tenantid', 'region', 'location', 'zone',
4668
4781
  'project', 'projectname', 'projectid', 'workspace', 'workspacename', 'workspaceid', 'resource', 'resourcename', 'resourcegroup',
@@ -4775,7 +4888,42 @@ function isHighEntropyQueryValue(value) {
4775
4888
  }
4776
4889
  function isOpaqueSecretValue(value) {
4777
4890
  const core = valueCoreForJudging(value);
4778
- return core.length > 0 && (looksLikeKnownSecret(core) || isHighEntropyQueryValue(core));
4891
+ if (core.length === 0)
4892
+ return false;
4893
+ if (looksLikeKnownSecret(core) || isHighEntropyQueryValue(core))
4894
+ return true;
4895
+ if (hasNonAsciiPercentEscape(core)) {
4896
+ for (const chunk of percentByteChunks(core))
4897
+ if (chunk.length > 0 && isHighEntropyQueryValue(chunk))
4898
+ return true;
4899
+ }
4900
+ return false;
4901
+ }
4902
+ function percentByteChunks(text) {
4903
+ const escapeAt = (k) => text.charCodeAt(k) === 0x25 && isHexDigit(text.charAt(k + 1)) && isHexDigit(text.charAt(k + 2));
4904
+ const chunks = [];
4905
+ let start = 0;
4906
+ let i = 0;
4907
+ while (i < text.length) {
4908
+ if (!escapeAt(i)) {
4909
+ i += 1;
4910
+ continue;
4911
+ }
4912
+ let j = i;
4913
+ let wide = false;
4914
+ while (escapeAt(j)) {
4915
+ if (text.charCodeAt(j + 1) >= 0x38)
4916
+ wide = true;
4917
+ j += 3;
4918
+ }
4919
+ if (wide) {
4920
+ chunks.push(text.slice(start, i));
4921
+ start = j;
4922
+ }
4923
+ i = j;
4924
+ }
4925
+ chunks.push(text.slice(start));
4926
+ return chunks;
4779
4927
  }
4780
4928
  const VALUE_PIECE_SEPARATORS = new Set(['/', '\\', '?', '#', '&', '=', ';', ':', '@', ',', '+']);
4781
4929
  function hasOpaquePiece(text) {