@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,3 +1,4 @@
1
+ import { readThrownSlot, THROWN_SLOT_UNREADABLE } from './wireFailureShape.js';
1
2
  function nonEmptyString(v) {
2
3
  return typeof v === 'string' && v !== '';
3
4
  }
@@ -216,16 +217,10 @@ export function readMemoryEraseReceipt(body) {
216
217
  return { kind: 'malformed', why: 'body_unreadable' };
217
218
  o = body;
218
219
  envelopeSeen = ['v', 'requestId', 'status', 'erased', 'notFound'].some((k) => Object.hasOwn(o, k));
219
- rawV = Object.hasOwn(o, 'v') ? o.v : undefined;
220
- rawRequestId = o.requestId;
221
- rawStatus = o.status;
222
- rawEvidence = o.evidenceCapability;
223
- rawCustody = o.custodyState;
224
- rawSelected = o.resolvedIds;
225
- rawErased = o.erased;
226
- rawNotFound = o.notFound;
227
- rawPreviously = Object.hasOwn(o, 'erasedPreviously') ? o.erasedPreviously : undefined;
228
- rawConflicts = o.conflicts;
220
+ const slots = ['v', 'requestId', 'status', 'evidenceCapability', 'custodyState', 'resolvedIds', 'erased', 'notFound', 'erasedPreviously', 'conflicts'].map((k) => readThrownSlot(o, k, 'data'));
221
+ if (slots.includes(THROWN_SLOT_UNREADABLE))
222
+ return { kind: 'malformed', why: 'body_unreadable' };
223
+ [rawV, rawRequestId, rawStatus, rawEvidence, rawCustody, rawSelected, rawErased, rawNotFound, rawPreviously, rawConflicts] = slots;
229
224
  }
230
225
  catch {
231
226
  return { kind: 'malformed', why: 'body_unreadable' };
@@ -0,0 +1,93 @@
1
+ import type { ModelApiWord } from './providerPresets.js';
2
+ import type { OnboardCatalogIssue, OnboardProbeResult, OnboardProbeVerdict, OnboardRefusal } from '../seatContract.js';
3
+ import { type ModelProbeResult } from '../modelCapabilityProbe.js';
4
+ import type { UiLanguage } from '../env/uiLanguage.js';
5
+ export declare function onboardBaseUrlProblem(url: string, lang?: UiLanguage): string | undefined;
6
+ export interface OnboardProbeTarget {
7
+ readonly baseUrl: string;
8
+ readonly api: ModelApiWord;
9
+ readonly modelId?: string | undefined;
10
+ readonly apiKey?: string | undefined;
11
+ readonly auth?: 'bearer' | 'x-api-key' | undefined;
12
+ }
13
+ export interface OnboardProbeRequestInit {
14
+ method?: string;
15
+ headers: Record<string, string>;
16
+ body?: string;
17
+ redirect: 'manual';
18
+ signal: AbortSignal;
19
+ }
20
+ export interface OnboardProbeBodyReader {
21
+ read(): Promise<{
22
+ readonly done: boolean;
23
+ readonly value?: Uint8Array | undefined;
24
+ }>;
25
+ cancel(): Promise<void>;
26
+ }
27
+ export interface OnboardProbeResponse {
28
+ readonly status: number;
29
+ readonly ok: boolean;
30
+ readonly headers: {
31
+ get(name: string): string | null;
32
+ };
33
+ readonly body?: {
34
+ getReader(): OnboardProbeBodyReader;
35
+ } | null | undefined;
36
+ text(): Promise<string>;
37
+ }
38
+ export type OnboardProbeFetch = (url: string, init: OnboardProbeRequestInit) => Promise<OnboardProbeResponse>;
39
+ export interface OnboardProbeDeps {
40
+ readonly fetchImpl?: OnboardProbeFetch | undefined;
41
+ readonly timeoutMs?: number | undefined;
42
+ readonly firstTokenMs?: number | undefined;
43
+ }
44
+ export declare function probeModelEndpoint(target: OnboardProbeTarget, deps?: OnboardProbeDeps): Promise<OnboardProbeResult>;
45
+ export type OnboardWriteVerdict = {
46
+ readonly write: true;
47
+ readonly unverified: boolean;
48
+ } | {
49
+ readonly write: false;
50
+ readonly refusal: 'probe_failed' | 'probe_unverified';
51
+ };
52
+ export declare function onboardWriteVerdict(verdict: OnboardProbeVerdict, acceptUnverified?: boolean): OnboardWriteVerdict;
53
+ export declare function keyEnvNameForEntry(entryName: string): string;
54
+ export declare function poolEntryNameOf(modelId: string, channel: string, taken: ReadonlySet<string>): string;
55
+ export interface OnboardPlanEntry {
56
+ readonly modelId: string;
57
+ readonly api: ModelApiWord;
58
+ readonly baseUrl: string;
59
+ readonly apiKey: string;
60
+ readonly providerName: string;
61
+ readonly contextWindow: number;
62
+ readonly maxTokens: number;
63
+ readonly channel: string;
64
+ }
65
+ export interface OnboardJsonObject {
66
+ readonly [key: string]: {} | null;
67
+ }
68
+ export interface OnboardWritePlanInput {
69
+ readonly modelsDoc: OnboardJsonObject | undefined;
70
+ readonly settingsEnv: OnboardJsonObject | undefined;
71
+ readonly effectiveEnv: Readonly<Record<string, string | undefined>>;
72
+ readonly entry: OnboardPlanEntry;
73
+ readonly probe: OnboardProbeResult;
74
+ readonly makeDefault: boolean;
75
+ readonly now: number;
76
+ readonly thinking?: ModelProbeResult | undefined;
77
+ readonly engineMode?: 'local' | 'cloud' | undefined;
78
+ }
79
+ export type OnboardWritePlan = {
80
+ readonly ok: true;
81
+ readonly entryName: string;
82
+ readonly keyEnv: string;
83
+ readonly updatedExisting: boolean;
84
+ readonly nextModelsDoc: OnboardJsonObject;
85
+ readonly nextSettingsEnv: OnboardJsonObject;
86
+ readonly otherIssues: readonly OnboardCatalogIssue[];
87
+ } | {
88
+ readonly ok: false;
89
+ readonly refusal: Extract<OnboardRefusal, 'input' | 'catalog_unreadable' | 'credential_unpaired' | 'engine_is_remote' | 'env_catalog_present'>;
90
+ readonly detail: string;
91
+ };
92
+ export declare function onboardWritePlan(input: OnboardWritePlanInput): OnboardWritePlan;
93
+ export declare function onboardRefusalText(refusal: OnboardRefusal, lang?: UiLanguage): string;
@@ -0,0 +1,415 @@
1
+ import { ONBOARD_REFUSALS } from '../seatContract.js';
2
+ import { joinRequestUrl, routeKeyOf } from '../coreValuePorts.js';
3
+ import { applyProbeToEntry, probeModelLiveness, probeVerdictNotice } from '../modelCapabilityProbe.js';
4
+ import { ownDataField } from '../ownKey.js';
5
+ import { msg, renderMessage } from '../i18n/translate.js';
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
+ const en = (key, params) => renderMessage(msg(key, params));
17
+ function decodeLenient(t) {
18
+ let cur = t;
19
+ for (let i = 0; i < 16; i++) {
20
+ const next = cur.replace(/(?:%[0-9A-Fa-f]{2})+/g, (m) => {
21
+ try {
22
+ return decodeURIComponent(m);
23
+ }
24
+ catch {
25
+ return m.replace(/%([0-9A-Fa-f]{2})/g, (_x, h) => String.fromCharCode(parseInt(h, 16)));
26
+ }
27
+ });
28
+ if (next === cur)
29
+ return cur;
30
+ cur = next;
31
+ }
32
+ return undefined;
33
+ }
34
+ function decodeDeep(t) {
35
+ let cur = t;
36
+ for (let i = 0; i < 16; i++) {
37
+ if (!cur.includes('%'))
38
+ return cur;
39
+ let next;
40
+ try {
41
+ next = decodeURIComponent(cur);
42
+ }
43
+ catch {
44
+ return undefined;
45
+ }
46
+ if (next === cur)
47
+ return cur;
48
+ cur = next;
49
+ }
50
+ return undefined;
51
+ }
52
+ function safeDecode(t) {
53
+ try {
54
+ return decodeURIComponent(t);
55
+ }
56
+ catch {
57
+ return t;
58
+ }
59
+ }
60
+ function carriesKey(text, key) {
61
+ if (key === undefined || key === '')
62
+ return false;
63
+ const d = decodeDeep(text);
64
+ if (d === undefined)
65
+ return true;
66
+ const k = key.toLowerCase();
67
+ return text.toLowerCase().includes(k) || d.toLowerCase().includes(k);
68
+ }
69
+ function looksLikeSecret(val) {
70
+ return /^(sk|ak|pk|rk)[-_]/i.test(val) || (val.length >= 20 && /[A-Za-z]/.test(val) && /[0-9]/.test(val) && /^[A-Za-z0-9._~+/=-]+$/.test(val));
71
+ }
72
+ function redact(text, key) {
73
+ if (key === undefined || key === '')
74
+ return text;
75
+ const out = text.split(key).join('****');
76
+ const k = key.toLowerCase();
77
+ const d = decodeLenient(out);
78
+ return d === undefined || out.toLowerCase().includes(k) || d.toLowerCase().includes(k) ? en('onboard.probe.keyEchoed') : out;
79
+ }
80
+ const capText = (text) => (text.length > 400 ? `${text.slice(0, 400)}…` : text);
81
+ export function onboardBaseUrlProblem(url, lang) {
82
+ const say = (key) => renderMessage(msg(key), lang);
83
+ if (typeof url !== 'string')
84
+ return say('onboard.baseUrl.invalid');
85
+ if (/\s/.test(url.trim()))
86
+ return say('onboard.baseUrl.spaces');
87
+ let u;
88
+ try {
89
+ u = new URL(url.trim());
90
+ }
91
+ catch {
92
+ return say('onboard.baseUrl.invalid');
93
+ }
94
+ if (u.protocol !== 'http:' && u.protocol !== 'https:')
95
+ return say('onboard.baseUrl.scheme');
96
+ if (u.username !== '' || u.password !== '')
97
+ return say('onboard.baseUrl.userinfo');
98
+ if (u.hash !== '')
99
+ return say('onboard.baseUrl.fragment');
100
+ if (u.pathname.split('/').some((seg) => /^(sk|ak|pk|rk)[-_]/i.test(safeDecode(seg))))
101
+ return say('onboard.baseUrl.pathKey');
102
+ for (const [k, val] of u.searchParams) {
103
+ if (/key|token|secret|auth|sig|pass/i.test(k))
104
+ return say('onboard.baseUrl.queryKey');
105
+ if (looksLikeSecret(val))
106
+ return say('onboard.baseUrl.queryValueKey');
107
+ }
108
+ if (decodeDeep(url.trim()) === undefined)
109
+ return say('onboard.baseUrl.encoding');
110
+ return undefined;
111
+ }
112
+ function keyHeaders(api, key, auth) {
113
+ const h = {};
114
+ if (key !== undefined && key !== '') {
115
+ if (auth !== 'x-api-key' || api !== 'anthropic-messages')
116
+ h['authorization'] = `Bearer ${key}`;
117
+ if (api === 'anthropic-messages' && auth !== 'bearer')
118
+ h['x-api-key'] = key;
119
+ }
120
+ return h;
121
+ }
122
+ class OnboardRedirect extends Error {
123
+ }
124
+ function redirectRefusal(res, url, key) {
125
+ if (res.status < 300 || res.status >= 400)
126
+ return undefined;
127
+ let where = en('onboard.probe.anotherAddress');
128
+ try {
129
+ const to = res.headers.get('location');
130
+ if (to)
131
+ where = redact(to, key) === to ? new URL(to, url).host : en('onboard.probe.anotherAddress');
132
+ }
133
+ catch {
134
+ where = en('onboard.probe.anotherAddress');
135
+ }
136
+ return en('onboard.probe.redirected', { status: res.status, where });
137
+ }
138
+ function probeDetailOf(v) {
139
+ if (v.verdict === 'ok' && v.waitedMs === undefined && v.path !== undefined && v.httpStatus !== undefined) {
140
+ return en('onboard.probe.endpointReachable', { method: v.path === '/models' ? 'GET' : 'POST', path: v.path, status: v.httpStatus });
141
+ }
142
+ const line = probeVerdictNotice(v).line;
143
+ const tail = v.apiError ?? v.cause;
144
+ const detail = tail === undefined ? line : `${line}: ${tail}`;
145
+ return v.nearModelId === undefined ? detail : en('onboard.probe.modelSuggest', { error: detail, near: v.nearModelId });
146
+ }
147
+ export async function probeModelEndpoint(target, deps) {
148
+ const apiKey = field(target, 'apiKey');
149
+ const key = typeof apiKey === 'string' ? apiKey : undefined;
150
+ const redactKey = key?.trim() || undefined;
151
+ const out = (verdict, detail) => Object.freeze({ verdict, detail: capText(redact(detail, redactKey)) });
152
+ const baseUrl = field(target, 'baseUrl');
153
+ const api = field(target, 'api');
154
+ const rawModel = field(target, 'modelId');
155
+ const modelId = typeof rawModel === 'string' && rawModel.trim() !== '' ? rawModel.trim() : undefined;
156
+ const auth = field(target, 'auth');
157
+ if (typeof baseUrl !== 'string' || (api !== 'anthropic-messages' && api !== 'openai-completions'))
158
+ return out('other', en('onboard.probe.incomplete'));
159
+ const f = (field(deps, 'fetchImpl') ?? globalThis.fetch);
160
+ if (typeof f !== 'function')
161
+ return out('unreachable', en('onboard.probe.noFetch'));
162
+ const num = (k) => {
163
+ const v = field(deps, k);
164
+ return typeof v === 'number' && Number.isFinite(v) && v > 0 ? v : undefined;
165
+ };
166
+ const timeoutMs = num('timeoutMs');
167
+ const deadlineMs = num('firstTokenMs') ?? timeoutMs ?? 15_000;
168
+ const root = baseUrl.trim();
169
+ try {
170
+ if (joinRequestUrl(root, 'models') === undefined)
171
+ return out('other', en('onboard.probe.judgeAbsent'));
172
+ }
173
+ catch {
174
+ return out('other', en('onboard.baseUrl.invalid'));
175
+ }
176
+ const secret = keyHeaders(api, key, auth === 'bearer' || auth === 'x-api-key' ? auth : undefined);
177
+ const seen = {};
178
+ const fetchWithKey = async (url, init) => {
179
+ const res = await f(url, { method: init.method, headers: { ...init.headers, ...secret }, ...(init.body !== undefined ? { body: init.body } : {}), redirect: 'manual', signal: init.signal });
180
+ const refusal = redirectRefusal(res, url, redactKey);
181
+ if (refusal !== undefined) {
182
+ if (init.method === 'POST' || api === 'openai-completions')
183
+ seen.redirected = refusal;
184
+ throw new OnboardRedirect(refusal);
185
+ }
186
+ return { status: res.status, headers: res.headers, body: res.body ?? null, text: () => res.text() };
187
+ };
188
+ const v = await probeModelLiveness({
189
+ api,
190
+ baseUrl: root,
191
+ ...(modelId !== undefined ? { modelId } : {}),
192
+ fetch: fetchWithKey,
193
+ firstTokenBudgetMs: deadlineMs,
194
+ catalogBudgetMs: timeoutMs ?? (api === 'anthropic-messages' ? 8000 : 10_000),
195
+ requestUrl: (path) => joinRequestUrl(root, path),
196
+ redact: (text) => redact(text, redactKey),
197
+ });
198
+ if (v.verdict === 'unreachable' && seen.redirected !== undefined)
199
+ return out('unreachable', seen.redirected);
200
+ return out(v.verdict, probeDetailOf(v));
201
+ }
202
+ export function onboardWriteVerdict(verdict, acceptUnverified) {
203
+ if (verdict === 'ok')
204
+ return Object.freeze({ write: true, unverified: false });
205
+ if (verdict === 'auth' || verdict === 'model' || verdict === 'shape')
206
+ return Object.freeze({ write: false, refusal: 'probe_failed' });
207
+ return acceptUnverified === true ? Object.freeze({ write: true, unverified: true }) : Object.freeze({ write: false, refusal: 'probe_unverified' });
208
+ }
209
+ const KEY_SLOT_PREFIX = 'SEMA_MODEL_KEY_';
210
+ export function keyEnvNameForEntry(entryName) {
211
+ const base = String(entryName).toUpperCase().replace(/[^A-Z0-9]+/g, '_').replace(/^_+|_+$/g, '') || 'ENTRY';
212
+ return `${KEY_SLOT_PREFIX}${base}`;
213
+ }
214
+ export function poolEntryNameOf(modelId, channel, taken) {
215
+ let name = String(modelId).toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^[._-]+/, '');
216
+ if (!name)
217
+ name = 'model';
218
+ if (name === 'default')
219
+ name = 'm-default';
220
+ let candidate = name;
221
+ if (taken.has(candidate))
222
+ candidate = `${name}-${channel}`;
223
+ for (let i = 2; taken.has(candidate); i++)
224
+ candidate = `${name}-${channel}-${i}`;
225
+ return candidate;
226
+ }
227
+ function entryCredentialIssue(m, env) {
228
+ const name = typeof m['name'] === 'string' ? m['name'] : '?';
229
+ if (m['sealedApiKey'] !== undefined && m['sealedApiKey'] !== null)
230
+ return undefined;
231
+ const keyEnv = typeof m['apiKeyEnv'] === 'string' && m['apiKeyEnv'] !== '' ? m['apiKeyEnv'] : undefined;
232
+ if (keyEnv !== undefined) {
233
+ const v = env[keyEnv];
234
+ return typeof v === 'string' && v.length > 0 ? undefined : en('onboard.catalog.keyEnvUnset', { name, keyEnv });
235
+ }
236
+ const base = typeof m['baseUrl'] === 'string' ? m['baseUrl'] : '';
237
+ if (base.trim() === '')
238
+ return undefined;
239
+ const api = typeof m['api'] === 'string' ? m['api'] : 'openai-completions';
240
+ const rootKey = api === 'anthropic-messages' ? 'ANTHROPIC_BASE_URL' : 'MODEL_GATEWAY_BASEURL';
241
+ const root = env[rootKey];
242
+ let paired;
243
+ try {
244
+ const a = routeKeyOf(base);
245
+ if (a === undefined)
246
+ return en('onboard.catalog.judgeAbsent', { name });
247
+ paired = typeof root === 'string' && root !== '' && a === routeKeyOf(root);
248
+ }
249
+ catch {
250
+ paired = false;
251
+ }
252
+ if (paired)
253
+ return undefined;
254
+ const hostOf = (u) => {
255
+ try {
256
+ return new URL(u).host;
257
+ }
258
+ catch {
259
+ return en('onboard.catalog.unparseableHost');
260
+ }
261
+ };
262
+ const rootText = typeof root === 'string' && root !== '' ? `${rootKey} (${hostOf(root)})` : en('onboard.catalog.noRoot', { rootKey });
263
+ return en('onboard.catalog.unpaired', { name, host: hostOf(base), root: rootText });
264
+ }
265
+ function migrateLegacyDefaultKey(doc) {
266
+ const legacy = doc['default'];
267
+ if (typeof legacy !== 'string' || legacy.length === 0)
268
+ return doc;
269
+ const { default: _legacy, ...rest } = doc;
270
+ void _legacy;
271
+ const prevRoles = rest['roles'];
272
+ const roles = prevRoles !== null && typeof prevRoles === 'object' && !Array.isArray(prevRoles) ? { ...prevRoles } : {};
273
+ roles['default'] = { model: legacy };
274
+ return { ...rest, roles };
275
+ }
276
+ export function onboardWritePlan(input) {
277
+ const rawKey = field(field(input, 'entry'), 'apiKey');
278
+ const planKey = typeof rawKey === 'string' && rawKey !== '' ? rawKey : undefined;
279
+ const say = (text) => redact(text, planKey);
280
+ const refuse = (refusal, detail) => Object.freeze({ ok: false, refusal, detail: say(detail) });
281
+ try {
282
+ if (input.engineMode === 'cloud')
283
+ return refuse('engine_is_remote', en('onboard.refusal.engineIsRemote'));
284
+ const rawDoc = input.modelsDoc;
285
+ if (rawDoc !== undefined && (rawDoc === null || typeof rawDoc !== 'object' || Array.isArray(rawDoc)))
286
+ return refuse('catalog_unreadable', en('onboard.plan.notObject'));
287
+ const doc = migrateLegacyDefaultKey(rawDoc === undefined ? {} : { ...rawDoc });
288
+ const rawModels = doc['models'];
289
+ if (rawModels !== undefined && !Array.isArray(rawModels))
290
+ return refuse('catalog_unreadable', en('onboard.plan.modelsNotList'));
291
+ const list = Array.isArray(rawModels) ? rawModels : [];
292
+ if (list.some((m) => m === null || typeof m !== 'object' || Array.isArray(m)))
293
+ return refuse('catalog_unreadable', en('onboard.plan.modelsItemNotObject'));
294
+ const models = list.map((m) => ({ ...m }));
295
+ const envModel = [input.effectiveEnv?.['MODEL_ID'], input.effectiveEnv?.['MODEL_CHEAP_ID']].find((v) => typeof v === 'string' && v.trim() !== '');
296
+ if (envModel !== undefined && !models.some((m) => m['enabled'] !== false)) {
297
+ return refuse('env_catalog_present', en('onboard.plan.envCatalogPresent', { model: envModel }));
298
+ }
299
+ const rawEnv = input.settingsEnv;
300
+ if (rawEnv !== undefined && (rawEnv === null || typeof rawEnv !== 'object' || Array.isArray(rawEnv)))
301
+ return refuse('catalog_unreadable', en('onboard.plan.envNotObject'));
302
+ const prevEnv = rawEnv === undefined ? {} : { ...rawEnv };
303
+ const e = input.entry;
304
+ const isShellSlot = (ref) => typeof ref === 'string' && ref.startsWith(KEY_SLOT_PREFIX) && typeof prevEnv[ref] === 'string';
305
+ const targetKey = routeKeyOf(e.baseUrl);
306
+ if (targetKey === undefined)
307
+ return refuse('credential_unpaired', en('onboard.catalog.judgeAbsent', { name: e.modelId }));
308
+ const sameTarget = (m) => m['id'] === e.modelId && m['api'] === e.api && typeof m['baseUrl'] === 'string' && routeKeyOf(m['baseUrl']) === targetKey;
309
+ const existingIdx = models.findIndex((m) => sameTarget(m) && m['enabled'] !== false && m['sealedApiKey'] === undefined && (m['apiKeyEnv'] === undefined || isShellSlot(m['apiKeyEnv'])));
310
+ const taken = new Set(models.map((m) => (typeof m['name'] === 'string' ? m['name'] : '')).filter((n) => n !== ''));
311
+ const name = existingIdx >= 0 ? String(models[existingIdx]['name']) : poolEntryNameOf(e.modelId, e.channel, taken);
312
+ const existingRef = existingIdx >= 0 ? models[existingIdx]['apiKeyEnv'] : undefined;
313
+ const sharedByOther = typeof existingRef === 'string' &&
314
+ models.some((m, i) => i !== existingIdx && typeof m['apiKeyEnv'] === 'string' && m['apiKeyEnv'].toUpperCase() === existingRef.toUpperCase());
315
+ let keyEnv;
316
+ if (isShellSlot(existingRef) && !sharedByOther) {
317
+ keyEnv = existingRef;
318
+ }
319
+ else {
320
+ const used = new Set();
321
+ for (const m of models)
322
+ if (typeof m['apiKeyEnv'] === 'string')
323
+ used.add(m['apiKeyEnv'].toUpperCase());
324
+ for (const k of Object.keys(prevEnv))
325
+ used.add(k.toUpperCase());
326
+ for (const [k, v] of Object.entries(input.effectiveEnv ?? {}))
327
+ if (typeof v === 'string')
328
+ used.add(k.toUpperCase());
329
+ const baseSlot = keyEnvNameForEntry(name);
330
+ keyEnv = baseSlot;
331
+ for (let i = 2; used.has(keyEnv.toUpperCase()); i++)
332
+ keyEnv = `${baseSlot}_${i}`;
333
+ }
334
+ if (carriesKey(name, e.apiKey) || carriesKey(keyEnv, e.apiKey))
335
+ return refuse('input', en('onboard.input.keyInFields'));
336
+ const base = existingIdx >= 0 ? models[existingIdx] : {};
337
+ let entry = {
338
+ ...base,
339
+ name,
340
+ id: e.modelId,
341
+ provider: e.api === 'anthropic-messages' ? 'anthropic' : 'gateway',
342
+ api: e.api,
343
+ baseUrl: e.baseUrl,
344
+ contextWindow: typeof base['contextWindow'] === 'number' ? base['contextWindow'] : e.contextWindow,
345
+ maxTokens: typeof base['maxTokens'] === 'number' ? base['maxTokens'] : e.maxTokens,
346
+ apiKeyEnv: keyEnv,
347
+ semaChannel: typeof base['semaChannel'] === 'string' ? base['semaChannel'] : e.channel,
348
+ semaLabel: typeof base['semaLabel'] === 'string' ? base['semaLabel'] : e.providerName,
349
+ semaProbe: input.probe.verdict,
350
+ semaProbeAt: input.now,
351
+ };
352
+ if (input.thinking !== undefined) {
353
+ const probed = applyProbeToEntry({ ...(typeof entry['reasoning'] === 'boolean' ? { reasoning: entry['reasoning'] } : {}), ...(entry['compat'] !== undefined ? { compat: entry['compat'] } : {}) }, input.thinking);
354
+ const next = { ...entry };
355
+ if (typeof probed.reasoning === 'boolean')
356
+ next['reasoning'] = probed.reasoning;
357
+ if (probed.compat !== undefined)
358
+ next['compat'] = probed.compat;
359
+ else
360
+ delete next['compat'];
361
+ entry = next;
362
+ }
363
+ const envView = { ...input.effectiveEnv, [keyEnv]: e.apiKey };
364
+ const issue = entryCredentialIssue(entry, envView);
365
+ if (issue !== undefined)
366
+ return refuse('credential_unpaired', issue);
367
+ if (existingIdx >= 0)
368
+ models[existingIdx] = entry;
369
+ else
370
+ models.push(entry);
371
+ const nextDoc = { ...doc, models };
372
+ if (input.makeDefault) {
373
+ const prevRoles = doc['roles'];
374
+ const roles = prevRoles !== null && typeof prevRoles === 'object' && !Array.isArray(prevRoles) ? { ...prevRoles } : {};
375
+ roles['default'] = { model: name };
376
+ nextDoc['roles'] = roles;
377
+ }
378
+ const otherIssues = [];
379
+ for (const m of models) {
380
+ if (m['enabled'] === false || m['name'] === name)
381
+ continue;
382
+ const other = entryCredentialIssue(m, envView);
383
+ if (other !== undefined) {
384
+ otherIssues.push(Object.freeze({ name: typeof m['name'] === 'string' ? m['name'] : '?', modelId: typeof m['id'] === 'string' ? m['id'] : '?', issue: say(other) }));
385
+ }
386
+ }
387
+ return Object.freeze({
388
+ ok: true,
389
+ entryName: name,
390
+ keyEnv,
391
+ updatedExisting: existingIdx >= 0,
392
+ nextModelsDoc: nextDoc,
393
+ nextSettingsEnv: { ...prevEnv, [keyEnv]: e.apiKey },
394
+ otherIssues: Object.freeze(otherIssues),
395
+ });
396
+ }
397
+ catch {
398
+ return refuse('input', en('onboard.refusal.input'));
399
+ }
400
+ }
401
+ const REFUSAL_KEYS = {
402
+ input: 'onboard.refusal.input',
403
+ probe_failed: 'onboard.refusal.probeFailed',
404
+ probe_unverified: 'onboard.refusal.probeUnverified',
405
+ credential_unpaired: 'onboard.refusal.credentialUnpaired',
406
+ catalog_unreadable: 'onboard.refusal.catalogUnreadable',
407
+ write_conflict: 'onboard.refusal.writeConflict',
408
+ write_failed: 'onboard.refusal.writeFailed',
409
+ engine_is_remote: 'onboard.refusal.engineIsRemote',
410
+ env_catalog_present: 'onboard.refusal.envCatalogPresent',
411
+ };
412
+ export function onboardRefusalText(refusal, lang) {
413
+ const known = ONBOARD_REFUSALS.find((w) => w === refusal) ?? 'input';
414
+ return renderMessage(msg(REFUSAL_KEYS[known]), lang);
415
+ }
@@ -1,10 +1,12 @@
1
1
  import { CORE_DEFAULT_TIER_ORDER } from '../generated/engineFactTables.js';
2
+ import type { UiLanguage } from '../env/uiLanguage.js';
2
3
  export type Tier = (typeof CORE_DEFAULT_TIER_ORDER)[number];
3
4
  export declare const TIER_ORDER: readonly Tier[];
4
5
  export declare const SURFACED_TIERS: readonly Tier[];
5
6
  export declare const CC_TIER_ALIASES: Readonly<Record<string, Tier>>;
6
7
  export declare const DEFAULT_TIER: Tier;
7
8
  export declare const TIER_BLURBS: Readonly<Record<Tier, string>>;
9
+ export declare function tierBlurb(tier: Tier, lang?: UiLanguage): string;
8
10
  export type TierGroupDef = {
9
11
  tiers: Partial<Record<Tier, string>>;
10
12
  defaultTier?: Tier;
@@ -1,15 +1,27 @@
1
1
  import { CORE_CC_MODEL_TIER_ALIASES, CORE_DEFAULT_TIER_ORDER } from '../generated/engineFactTables.js';
2
+ import { EN_MESSAGES } from '../i18n/messages.en.js';
3
+ import { msg, renderMessage } from '../i18n/translate.js';
2
4
  export const TIER_ORDER = CORE_DEFAULT_TIER_ORDER;
3
5
  export const SURFACED_TIERS = ['max', 'pro', 'flash', 'lite'];
4
6
  export const CC_TIER_ALIASES = CORE_CC_MODEL_TIER_ALIASES;
5
7
  export const DEFAULT_TIER = 'pro';
8
+ const TIER_BLURB_KEYS = Object.freeze({
9
+ ultra: 'model.tier.blurb.ultra',
10
+ max: 'model.tier.blurb.max',
11
+ pro: 'model.tier.blurb.pro',
12
+ flash: 'model.tier.blurb.flash',
13
+ lite: 'model.tier.blurb.lite',
14
+ });
6
15
  export const TIER_BLURBS = {
7
- ultra: 'reserved above max — binds when a stronger model lands',
8
- max: 'hardest problems — deep reasoning, big refactors',
9
- pro: 'everyday driving — the default tier',
10
- flash: 'fast + cheap — titles, recaps, volume work',
11
- lite: 'cheapest — bulk classification, simple lookups',
16
+ ultra: EN_MESSAGES[TIER_BLURB_KEYS.ultra],
17
+ max: EN_MESSAGES[TIER_BLURB_KEYS.max],
18
+ pro: EN_MESSAGES[TIER_BLURB_KEYS.pro],
19
+ flash: EN_MESSAGES[TIER_BLURB_KEYS.flash],
20
+ lite: EN_MESSAGES[TIER_BLURB_KEYS.lite],
12
21
  };
22
+ export function tierBlurb(tier, lang) {
23
+ return typeof tier === 'string' && Object.hasOwn(TIER_BLURB_KEYS, tier) ? renderMessage(msg(TIER_BLURB_KEYS[tier]), lang) : '';
24
+ }
13
25
  export const isTier = (v) => typeof v === 'string' && TIER_ORDER.includes(v);
14
26
  export function resolveTierBinding(def, tier) {
15
27
  const direct = def.tiers[tier];
@@ -1,3 +1,5 @@
1
+ import type { ModelApiWord } from './model/providerPresets.js';
2
+ import type { UiLanguage } from './env/uiLanguage.js';
1
3
  export interface OpenAICompletionsProbeBody {
2
4
  model: string;
3
5
  messages: ReadonlyArray<{
@@ -66,4 +68,67 @@ type ProbeWritableEntry = {
66
68
  compat?: unknown;
67
69
  };
68
70
  export declare function applyProbeToEntry<T extends ProbeWritableEntry>(entry: T, result: ModelProbeResult): T;
71
+ export declare const PROBE_VERDICTS: readonly ["ok", "auth", "unreachable", "model", "shape", "busy", "no_token", "other"];
72
+ export type ProbeVerdictWord = (typeof PROBE_VERDICTS)[number];
73
+ export type ProbeAnswerOutcome = 'error' | 'not_model' | 'ended';
74
+ export interface ProbeVerdict {
75
+ readonly verdict: ProbeVerdictWord;
76
+ readonly httpStatus?: number;
77
+ readonly waitedMs?: number;
78
+ readonly path?: string;
79
+ readonly apiError?: string;
80
+ readonly outcome?: ProbeAnswerOutcome;
81
+ readonly nearModelId?: string;
82
+ readonly cause?: string;
83
+ }
84
+ export interface LivenessFetchInit {
85
+ readonly method: 'GET' | 'POST';
86
+ readonly headers: Readonly<Record<string, string>>;
87
+ readonly body?: string;
88
+ readonly signal: AbortSignal;
89
+ }
90
+ export interface LivenessBodyReader {
91
+ read(): Promise<{
92
+ readonly done: boolean;
93
+ readonly value?: Uint8Array | undefined;
94
+ }>;
95
+ cancel(): Promise<void>;
96
+ }
97
+ export interface LivenessResponse {
98
+ readonly status: number;
99
+ readonly headers: {
100
+ get(name: string): string | null;
101
+ };
102
+ readonly body: {
103
+ getReader(): LivenessBodyReader;
104
+ } | null;
105
+ text(): Promise<string>;
106
+ }
107
+ export type LivenessFetch = (url: string, init: LivenessFetchInit) => Promise<LivenessResponse>;
108
+ export interface LivenessProbeInput {
109
+ readonly api: ModelApiWord;
110
+ readonly baseUrl: string;
111
+ readonly modelId?: string;
112
+ readonly fetch: LivenessFetch;
113
+ readonly firstTokenBudgetMs: number;
114
+ readonly catalogBudgetMs: number;
115
+ readonly signal?: AbortSignal;
116
+ readonly now?: () => number;
117
+ readonly redact?: (text: string) => string;
118
+ readonly requestUrl?: (path: string) => string;
119
+ }
120
+ export declare function probeModelLiveness(input: LivenessProbeInput): Promise<ProbeVerdict>;
121
+ export type ProbeVerdictRecourse = 'switch_model' | 'check_credentials';
122
+ export interface ProbeVerdictNotice {
123
+ readonly line: string;
124
+ readonly recourse?: ProbeVerdictRecourse;
125
+ }
126
+ export interface ProbeVerdictFacts {
127
+ readonly verdict?: string;
128
+ readonly httpStatus?: number;
129
+ readonly waitedMs?: number;
130
+ }
131
+ export declare function probeVerdictNotice(facts: ProbeVerdictFacts | null | undefined, ctx?: {
132
+ readonly modelName?: string;
133
+ }, lang?: UiLanguage): ProbeVerdictNotice;
69
134
  export {};