yepanywhere 0.6.0 → 0.6.2
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/bundled/@yep-anywhere/shared/dist/app-types.d.ts +25 -0
- package/bundled/@yep-anywhere/shared/dist/app-types.d.ts.map +1 -1
- package/bundled/@yep-anywhere/shared/dist/app-types.js.map +1 -1
- package/bundled/@yep-anywhere/shared/dist/codex-schema/session.d.ts +179 -14
- package/bundled/@yep-anywhere/shared/dist/codex-schema/session.d.ts.map +1 -1
- package/bundled/@yep-anywhere/shared/dist/codex-schema/session.js +89 -0
- package/bundled/@yep-anywhere/shared/dist/codex-schema/session.js.map +1 -1
- package/bundled/@yep-anywhere/shared/dist/codex-tool-correlation.d.ts +25 -0
- package/bundled/@yep-anywhere/shared/dist/codex-tool-correlation.d.ts.map +1 -0
- package/bundled/@yep-anywhere/shared/dist/codex-tool-correlation.js +52 -0
- package/bundled/@yep-anywhere/shared/dist/codex-tool-correlation.js.map +1 -0
- package/bundled/@yep-anywhere/shared/dist/codex-web-run.d.ts +46 -0
- package/bundled/@yep-anywhere/shared/dist/codex-web-run.d.ts.map +1 -0
- package/bundled/@yep-anywhere/shared/dist/codex-web-run.js +14 -0
- package/bundled/@yep-anywhere/shared/dist/codex-web-run.js.map +1 -0
- package/bundled/@yep-anywhere/shared/dist/git-status.d.ts +29 -6
- package/bundled/@yep-anywhere/shared/dist/git-status.d.ts.map +1 -1
- package/bundled/@yep-anywhere/shared/dist/git-status.js +1 -6
- package/bundled/@yep-anywhere/shared/dist/git-status.js.map +1 -1
- package/bundled/@yep-anywhere/shared/dist/index.d.ts +7 -2
- package/bundled/@yep-anywhere/shared/dist/index.d.ts.map +1 -1
- package/bundled/@yep-anywhere/shared/dist/index.js +2 -0
- package/bundled/@yep-anywhere/shared/dist/index.js.map +1 -1
- package/bundled/@yep-anywhere/shared/dist/server-capabilities.d.ts +248 -0
- package/bundled/@yep-anywhere/shared/dist/server-capabilities.d.ts.map +1 -0
- package/bundled/@yep-anywhere/shared/dist/server-capabilities.js +251 -0
- package/bundled/@yep-anywhere/shared/dist/server-capabilities.js.map +1 -0
- package/bundled/@yep-anywhere/shared/dist/tool-display-actions.d.ts +26 -0
- package/bundled/@yep-anywhere/shared/dist/tool-display-actions.d.ts.map +1 -0
- package/bundled/@yep-anywhere/shared/dist/tool-display-actions.js +9 -0
- package/bundled/@yep-anywhere/shared/dist/tool-display-actions.js.map +1 -0
- package/bundled/@yep-anywhere/shared/package.json +1 -1
- package/client-dist/assets/de-BNhVdIq4.js +6 -0
- package/client-dist/assets/es-Csn9n24J.js +6 -0
- package/client-dist/assets/fr-DKx4tSpo.js +6 -0
- package/client-dist/assets/index-1y2h7U7U.js +582 -0
- package/client-dist/assets/index-Cn_ZDP6u.css +1 -0
- package/client-dist/assets/ja-DAkhkwQZ.js +6 -0
- package/client-dist/assets/zh-CN-B7lY0cc6.js +6 -0
- package/client-dist/index.html +2 -2
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js.map +1 -1
- package/dist/codex/codeModeExec.d.ts +30 -0
- package/dist/codex/codeModeExec.d.ts.map +1 -0
- package/dist/codex/codeModeExec.js +419 -0
- package/dist/codex/codeModeExec.js.map +1 -0
- package/dist/codex/displayActions.d.ts +48 -0
- package/dist/codex/displayActions.d.ts.map +1 -0
- package/dist/codex/displayActions.js +674 -0
- package/dist/codex/displayActions.js.map +1 -0
- package/dist/codex/normalization.d.ts +10 -7
- package/dist/codex/normalization.d.ts.map +1 -1
- package/dist/codex/normalization.js +179 -502
- package/dist/codex/normalization.js.map +1 -1
- package/dist/codex/webRun.d.ts +42 -0
- package/dist/codex/webRun.d.ts.map +1 -0
- package/dist/codex/webRun.js +199 -0
- package/dist/codex/webRun.js.map +1 -0
- package/dist/indexes/SessionIndexService.d.ts +1 -1
- package/dist/indexes/SessionIndexService.d.ts.map +1 -1
- package/dist/indexes/SessionIndexService.js +16 -4
- package/dist/indexes/SessionIndexService.js.map +1 -1
- package/dist/routes/git-status.d.ts.map +1 -1
- package/dist/routes/git-status.js +70 -0
- package/dist/routes/git-status.js.map +1 -1
- package/dist/routes/project-queue.d.ts.map +1 -1
- package/dist/routes/project-queue.js.map +1 -1
- package/dist/routes/public-shares.d.ts +1 -1
- package/dist/routes/public-shares.d.ts.map +1 -1
- package/dist/routes/public-shares.js +4 -6
- package/dist/routes/public-shares.js.map +1 -1
- package/dist/routes/session-metadata-patch.d.ts +24 -0
- package/dist/routes/session-metadata-patch.d.ts.map +1 -0
- package/dist/routes/session-metadata-patch.js +119 -0
- package/dist/routes/session-metadata-patch.js.map +1 -0
- package/dist/routes/session-project-routing.d.ts +25 -0
- package/dist/routes/session-project-routing.d.ts.map +1 -0
- package/dist/routes/session-project-routing.js +32 -0
- package/dist/routes/session-project-routing.js.map +1 -0
- package/dist/routes/session-provider-resolution.d.ts +28 -0
- package/dist/routes/session-provider-resolution.d.ts.map +1 -0
- package/dist/routes/session-provider-resolution.js +22 -0
- package/dist/routes/session-provider-resolution.js.map +1 -0
- package/dist/routes/session-queue-summaries.d.ts +21 -0
- package/dist/routes/session-queue-summaries.d.ts.map +1 -0
- package/dist/routes/session-queue-summaries.js +79 -0
- package/dist/routes/session-queue-summaries.js.map +1 -0
- package/dist/routes/session-recovered-queue.d.ts +43 -0
- package/dist/routes/session-recovered-queue.d.ts.map +1 -0
- package/dist/routes/session-recovered-queue.js +132 -0
- package/dist/routes/session-recovered-queue.js.map +1 -0
- package/dist/routes/session-thinking-options.d.ts +12 -0
- package/dist/routes/session-thinking-options.d.ts.map +1 -0
- package/dist/routes/session-thinking-options.js +7 -0
- package/dist/routes/session-thinking-options.js.map +1 -0
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +110 -409
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/settings-parsers.d.ts +37 -0
- package/dist/routes/settings-parsers.d.ts.map +1 -0
- package/dist/routes/settings-parsers.js +896 -0
- package/dist/routes/settings-parsers.js.map +1 -0
- package/dist/routes/settings.d.ts.map +1 -1
- package/dist/routes/settings.js +4 -894
- package/dist/routes/settings.js.map +1 -1
- package/dist/routes/version.d.ts +0 -2
- package/dist/routes/version.d.ts.map +1 -1
- package/dist/routes/version.js +8 -10
- package/dist/routes/version.js.map +1 -1
- package/dist/sdk/cli-detection.d.ts +15 -1
- package/dist/sdk/cli-detection.d.ts.map +1 -1
- package/dist/sdk/cli-detection.js +159 -28
- package/dist/sdk/cli-detection.js.map +1 -1
- package/dist/sdk/messageQueue.d.ts +5 -0
- package/dist/sdk/messageQueue.d.ts.map +1 -1
- package/dist/sdk/messageQueue.js +21 -0
- package/dist/sdk/messageQueue.js.map +1 -1
- package/dist/sdk/providers/codex-model-catalog.d.ts +34 -0
- package/dist/sdk/providers/codex-model-catalog.d.ts.map +1 -0
- package/dist/sdk/providers/codex-model-catalog.js +378 -0
- package/dist/sdk/providers/codex-model-catalog.js.map +1 -0
- package/dist/sdk/providers/codex-notification-guards.d.ts +15 -0
- package/dist/sdk/providers/codex-notification-guards.d.ts.map +1 -0
- package/dist/sdk/providers/codex-notification-guards.js +159 -0
- package/dist/sdk/providers/codex-notification-guards.js.map +1 -0
- package/dist/sdk/providers/codex-protocol/generated/ImageGenerationItem.d.ts +9 -0
- package/dist/sdk/providers/codex-protocol/generated/ImageGenerationItem.d.ts.map +1 -0
- package/dist/sdk/providers/codex-protocol/generated/ImageGenerationItem.js +3 -0
- package/dist/sdk/providers/codex-protocol/generated/ImageGenerationItem.js.map +1 -0
- package/dist/sdk/providers/codex-protocol/generated/MultiAgentMode.d.ts +5 -5
- package/dist/sdk/providers/codex-protocol/generated/MultiAgentMode.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/ResponseItem.d.ts +1 -0
- package/dist/sdk/providers/codex-protocol/generated/ResponseItem.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/ThreadId.d.ts +5 -0
- package/dist/sdk/providers/codex-protocol/generated/ThreadId.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/WebSearchItem.d.ts +7 -0
- package/dist/sdk/providers/codex-protocol/generated/WebSearchItem.d.ts.map +1 -0
- package/dist/sdk/providers/codex-protocol/generated/WebSearchItem.js +3 -0
- package/dist/sdk/providers/codex-protocol/generated/WebSearchItem.js.map +1 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/AskForApproval.d.ts +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/AskForApproval.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/CapabilityRootLocation.d.ts +3 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/CapabilityRootLocation.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/CodexErrorInfo.d.ts +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/CodexErrorInfo.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/McpToolCallAppContext.d.ts +3 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/McpToolCallAppContext.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/Thread.d.ts +13 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/Thread.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadExtra.d.ts +5 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadExtra.d.ts.map +1 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadExtra.js +3 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadExtra.js.map +1 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadForkParams.d.ts +7 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadForkParams.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadHistoryMode.d.ts +2 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadHistoryMode.d.ts.map +1 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadHistoryMode.js +3 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadHistoryMode.js.map +1 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadItem.d.ts +5 -13
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadItem.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadRollbackParams.d.ts +3 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadRollbackParams.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadStartParams.d.ts +10 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/ThreadStartParams.d.ts.map +1 -1
- package/dist/sdk/providers/codex-protocol/generated/v2/Turn.d.ts +3 -0
- package/dist/sdk/providers/codex-protocol/generated/v2/Turn.d.ts.map +1 -1
- package/dist/sdk/providers/codex-summary-helpers.d.ts +41 -0
- package/dist/sdk/providers/codex-summary-helpers.d.ts.map +1 -0
- package/dist/sdk/providers/codex-summary-helpers.js +207 -0
- package/dist/sdk/providers/codex-summary-helpers.js.map +1 -0
- package/dist/sdk/providers/codex.d.ts +0 -25
- package/dist/sdk/providers/codex.d.ts.map +1 -1
- package/dist/sdk/providers/codex.js +160 -703
- package/dist/sdk/providers/codex.js.map +1 -1
- package/dist/sdk/providers/opencode-models.d.ts +17 -0
- package/dist/sdk/providers/opencode-models.d.ts.map +1 -0
- package/dist/sdk/providers/opencode-models.js +83 -0
- package/dist/sdk/providers/opencode-models.js.map +1 -0
- package/dist/sdk/providers/opencode.d.ts +1 -9
- package/dist/sdk/providers/opencode.d.ts.map +1 -1
- package/dist/sdk/providers/opencode.js +1 -82
- package/dist/sdk/providers/opencode.js.map +1 -1
- package/dist/sdk/types.d.ts +3 -1
- package/dist/sdk/types.d.ts.map +1 -1
- package/dist/services/ProjectQueueService.d.ts.map +1 -1
- package/dist/services/ProjectQueueService.js +3 -1
- package/dist/services/ProjectQueueService.js.map +1 -1
- package/dist/sessions/claude-summary.d.ts.map +1 -1
- package/dist/sessions/claude-summary.js +13 -1
- package/dist/sessions/claude-summary.js.map +1 -1
- package/dist/sessions/codex-reader.d.ts +0 -2
- package/dist/sessions/codex-reader.d.ts.map +1 -1
- package/dist/sessions/codex-reader.js +46 -84
- package/dist/sessions/codex-reader.js.map +1 -1
- package/dist/sessions/codex-user-turn-provenance.d.ts +40 -0
- package/dist/sessions/codex-user-turn-provenance.d.ts.map +1 -0
- package/dist/sessions/codex-user-turn-provenance.js +165 -0
- package/dist/sessions/codex-user-turn-provenance.js.map +1 -0
- package/dist/sessions/normalization.d.ts.map +1 -1
- package/dist/sessions/normalization.js +80 -51
- package/dist/sessions/normalization.js.map +1 -1
- package/dist/sessions/pagination.d.ts +6 -0
- package/dist/sessions/pagination.d.ts.map +1 -1
- package/dist/sessions/pagination.js +42 -2
- package/dist/sessions/pagination.js.map +1 -1
- package/dist/subscriptions.d.ts.map +1 -1
- package/dist/subscriptions.js +1 -0
- package/dist/subscriptions.js.map +1 -1
- package/dist/supervisor/Process.d.ts +12 -0
- package/dist/supervisor/Process.d.ts.map +1 -1
- package/dist/supervisor/Process.js +178 -22
- package/dist/supervisor/Process.js.map +1 -1
- package/dist/supervisor/Supervisor.d.ts +5 -1
- package/dist/supervisor/Supervisor.d.ts.map +1 -1
- package/dist/supervisor/Supervisor.js +47 -0
- package/dist/supervisor/Supervisor.js.map +1 -1
- package/package.json +2 -2
- package/client-dist/assets/de-CHMDbVD5.js +0 -6
- package/client-dist/assets/es-CK8MPF_C.js +0 -6
- package/client-dist/assets/fr-49PXQiUL.js +0 -6
- package/client-dist/assets/index-B-09fVut.js +0 -557
- package/client-dist/assets/index-uJnfvD1f.css +0 -1
- package/client-dist/assets/ja-CrCGPmoH.js +0 -6
- package/client-dist/assets/zh-CN-AFJxv5ke.js +0 -6
|
@@ -0,0 +1,896 @@
|
|
|
1
|
+
import { ALL_PERMISSION_MODES, ALL_PROVIDERS, HELPER_SIDE_MODEL_CHEAPEST, HELPER_SIDE_MODEL_SAME_AS_MAIN, DEFAULT_CACHE_MISS_BILLING_SETTINGS, PROMPT_CACHE_KEEPALIVE_MODES, PROMPT_SUGGESTION_MODES, RECAP_MODES, clampRecapAfterSeconds, } from "../../bundled/@yep-anywhere/shared/dist/index.js";
|
|
2
|
+
import { normalizeFileAccess, } from "../middleware/file-access.js";
|
|
3
|
+
import { DEFAULT_SERVER_SETTINGS, DEFAULT_SPEECH_AUDIO_RETENTION_MAX_AGE_DAYS, DEFAULT_SPEECH_AUDIO_RETENTION_MAX_BYTES, } from "../services/ServerSettingsService.js";
|
|
4
|
+
import { isValidSshHostAlias, normalizeSshHostAlias, } from "../utils/sshHostAlias.js";
|
|
5
|
+
const HELPER_TARGET_ID_PATTERN = /^[A-Za-z0-9._-]{1,64}$/;
|
|
6
|
+
const MAX_HELPER_TARGETS = 20;
|
|
7
|
+
const HELPER_TARGET_MODEL_DISCOVERY_TIMEOUT_MS = 5000;
|
|
8
|
+
const SESSION_TOOLBAR_PRESENCE_CLIENT_DEFAULT_KEYS = [
|
|
9
|
+
"modeSelector",
|
|
10
|
+
"steerNow",
|
|
11
|
+
"attachments",
|
|
12
|
+
"slashMenu",
|
|
13
|
+
"thinkingToggle",
|
|
14
|
+
"renderMode",
|
|
15
|
+
"microphone",
|
|
16
|
+
"waveform",
|
|
17
|
+
"shortcutsHelp",
|
|
18
|
+
"contextUsage",
|
|
19
|
+
"btw",
|
|
20
|
+
"nudge",
|
|
21
|
+
"sessionStatus",
|
|
22
|
+
"projectQueue",
|
|
23
|
+
];
|
|
24
|
+
const TOOLBAR_CONTROL_PRESENCES = [
|
|
25
|
+
"hidden",
|
|
26
|
+
"pin",
|
|
27
|
+
"last",
|
|
28
|
+
"mid",
|
|
29
|
+
"first",
|
|
30
|
+
];
|
|
31
|
+
const CLIENT_DEFAULT_KEYS = [
|
|
32
|
+
"speech",
|
|
33
|
+
"busyComposerDefaultAction",
|
|
34
|
+
"collapsedComposerButton",
|
|
35
|
+
"sessionToolbarPresence",
|
|
36
|
+
"steerNowDefault",
|
|
37
|
+
"patientQueueDefault",
|
|
38
|
+
"projectQueueCtrlEnterEnabled",
|
|
39
|
+
"compactAtContextPercent",
|
|
40
|
+
];
|
|
41
|
+
const BUSY_COMPOSER_DEFAULT_ACTIONS = [
|
|
42
|
+
"steer",
|
|
43
|
+
"queue",
|
|
44
|
+
];
|
|
45
|
+
const COLLAPSED_COMPOSER_BUTTON_PREFERENCES = [
|
|
46
|
+
"primary",
|
|
47
|
+
"alternate",
|
|
48
|
+
"microphone",
|
|
49
|
+
];
|
|
50
|
+
const SPEECH_CLIENT_DEFAULT_KEYS = [
|
|
51
|
+
"voiceInputEnabled",
|
|
52
|
+
"speechMethod",
|
|
53
|
+
"speechSmartTurnSettings",
|
|
54
|
+
"grokSpeechAudioSettings",
|
|
55
|
+
];
|
|
56
|
+
const THINKING_MODES = [
|
|
57
|
+
"off",
|
|
58
|
+
"auto",
|
|
59
|
+
"on",
|
|
60
|
+
];
|
|
61
|
+
const EFFORT_LEVELS = [
|
|
62
|
+
"low",
|
|
63
|
+
"medium",
|
|
64
|
+
"high",
|
|
65
|
+
"xhigh",
|
|
66
|
+
"max",
|
|
67
|
+
];
|
|
68
|
+
const MAX_SPEECH_SMART_TURN_TIMEOUT_MS = 10000;
|
|
69
|
+
export function parseHostAliasList(rawHosts) {
|
|
70
|
+
const hosts = [];
|
|
71
|
+
for (const rawHost of rawHosts) {
|
|
72
|
+
if (typeof rawHost !== "string")
|
|
73
|
+
continue;
|
|
74
|
+
const host = normalizeSshHostAlias(rawHost);
|
|
75
|
+
if (!host)
|
|
76
|
+
continue;
|
|
77
|
+
if (!isValidSshHostAlias(host)) {
|
|
78
|
+
return { hosts: [], invalidHost: host };
|
|
79
|
+
}
|
|
80
|
+
hosts.push(host);
|
|
81
|
+
}
|
|
82
|
+
return { hosts };
|
|
83
|
+
}
|
|
84
|
+
export function normalizeOpenAiCompatibleBaseUrl(raw) {
|
|
85
|
+
if (typeof raw !== "string")
|
|
86
|
+
return null;
|
|
87
|
+
const trimmed = raw.trim();
|
|
88
|
+
if (!trimmed)
|
|
89
|
+
return null;
|
|
90
|
+
const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed)
|
|
91
|
+
? trimmed
|
|
92
|
+
: `http://${trimmed}`;
|
|
93
|
+
try {
|
|
94
|
+
const url = new URL(withScheme);
|
|
95
|
+
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
96
|
+
return null;
|
|
97
|
+
if (url.pathname === "" || url.pathname === "/") {
|
|
98
|
+
url.pathname = "/v1";
|
|
99
|
+
}
|
|
100
|
+
const normalized = url.toString();
|
|
101
|
+
return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Returns:
|
|
109
|
+
* - `null` when the payload is invalid
|
|
110
|
+
* - `undefined` when the setting should be cleared
|
|
111
|
+
* - an array when valid helper targets should be saved
|
|
112
|
+
*/
|
|
113
|
+
export function parseHelperTargets(raw) {
|
|
114
|
+
if (raw === undefined)
|
|
115
|
+
return null;
|
|
116
|
+
if (raw === null || raw === "")
|
|
117
|
+
return undefined;
|
|
118
|
+
if (!Array.isArray(raw) || raw.length > MAX_HELPER_TARGETS)
|
|
119
|
+
return null;
|
|
120
|
+
const seenIds = new Set();
|
|
121
|
+
const parsed = [];
|
|
122
|
+
for (const entry of raw) {
|
|
123
|
+
if (!entry || typeof entry !== "object")
|
|
124
|
+
return null;
|
|
125
|
+
const input = entry;
|
|
126
|
+
const id = typeof input.id === "string" ? input.id.trim() : "";
|
|
127
|
+
const name = typeof input.name === "string" ? input.name.trim() : "";
|
|
128
|
+
const baseUrl = normalizeOpenAiCompatibleBaseUrl(input.baseUrl);
|
|
129
|
+
const model = typeof input.model === "string" ? input.model.trim() : "";
|
|
130
|
+
if (!HELPER_TARGET_ID_PATTERN.test(id) ||
|
|
131
|
+
seenIds.has(id) ||
|
|
132
|
+
!name ||
|
|
133
|
+
name.length > 80 ||
|
|
134
|
+
input.kind !== "openai-compatible" ||
|
|
135
|
+
!baseUrl ||
|
|
136
|
+
model.length > 200) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
seenIds.add(id);
|
|
140
|
+
parsed.push({
|
|
141
|
+
id,
|
|
142
|
+
name,
|
|
143
|
+
kind: "openai-compatible",
|
|
144
|
+
baseUrl,
|
|
145
|
+
...(model ? { model } : {}),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return parsed;
|
|
149
|
+
}
|
|
150
|
+
function isRecord(value) {
|
|
151
|
+
return typeof value === "object" && value !== null;
|
|
152
|
+
}
|
|
153
|
+
function parseOptionalString(value, maxLength) {
|
|
154
|
+
if (value === undefined || value === null || value === "")
|
|
155
|
+
return undefined;
|
|
156
|
+
if (typeof value !== "string")
|
|
157
|
+
return null;
|
|
158
|
+
return value.length > 0 ? value.slice(0, maxLength) : undefined;
|
|
159
|
+
}
|
|
160
|
+
function parseProviderSessionDefaults(raw) {
|
|
161
|
+
if (raw === undefined || raw === null || raw === "")
|
|
162
|
+
return undefined;
|
|
163
|
+
if (!isRecord(raw))
|
|
164
|
+
return null;
|
|
165
|
+
const parsed = {};
|
|
166
|
+
if ("model" in raw) {
|
|
167
|
+
const model = parseOptionalString(raw.model, 200);
|
|
168
|
+
if (model === null)
|
|
169
|
+
return null;
|
|
170
|
+
if (model)
|
|
171
|
+
parsed.model = model;
|
|
172
|
+
}
|
|
173
|
+
if ("serviceTier" in raw) {
|
|
174
|
+
const serviceTier = parseOptionalString(raw.serviceTier, 64);
|
|
175
|
+
if (serviceTier === null)
|
|
176
|
+
return null;
|
|
177
|
+
if (serviceTier)
|
|
178
|
+
parsed.serviceTier = serviceTier;
|
|
179
|
+
}
|
|
180
|
+
if ("thinkingMode" in raw) {
|
|
181
|
+
if (raw.thinkingMode !== undefined &&
|
|
182
|
+
raw.thinkingMode !== null &&
|
|
183
|
+
raw.thinkingMode !== "" &&
|
|
184
|
+
!THINKING_MODES.includes(raw.thinkingMode)) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
if (typeof raw.thinkingMode === "string" && raw.thinkingMode.length > 0) {
|
|
188
|
+
parsed.thinkingMode = raw.thinkingMode;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if ("effortLevel" in raw) {
|
|
192
|
+
if (raw.effortLevel !== undefined &&
|
|
193
|
+
raw.effortLevel !== null &&
|
|
194
|
+
raw.effortLevel !== "" &&
|
|
195
|
+
!EFFORT_LEVELS.includes(raw.effortLevel)) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
if (typeof raw.effortLevel === "string" && raw.effortLevel.length > 0) {
|
|
199
|
+
parsed.effortLevel = raw.effortLevel;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if ("helperSideModel" in raw) {
|
|
203
|
+
const helperSideModel = parseOptionalString(raw.helperSideModel, 200);
|
|
204
|
+
if (helperSideModel === null)
|
|
205
|
+
return null;
|
|
206
|
+
if (helperSideModel) {
|
|
207
|
+
parsed.helperSideModel =
|
|
208
|
+
helperSideModel === HELPER_SIDE_MODEL_SAME_AS_MAIN
|
|
209
|
+
? HELPER_SIDE_MODEL_SAME_AS_MAIN
|
|
210
|
+
: helperSideModel === HELPER_SIDE_MODEL_CHEAPEST
|
|
211
|
+
? HELPER_SIDE_MODEL_CHEAPEST
|
|
212
|
+
: helperSideModel;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return Object.keys(parsed).length > 0 ? parsed : undefined;
|
|
216
|
+
}
|
|
217
|
+
const MAX_FILE_ACCESS_CUSTOM_ENTRIES = 100;
|
|
218
|
+
const MAX_FILE_ACCESS_CUSTOM_LENGTH = 1024;
|
|
219
|
+
/**
|
|
220
|
+
* Returns:
|
|
221
|
+
* - `null` when the payload is invalid
|
|
222
|
+
* - `undefined` when the setting should be cleared (reset to secure defaults)
|
|
223
|
+
* - a normalized object when valid
|
|
224
|
+
*/
|
|
225
|
+
export function parseFileAccess(raw) {
|
|
226
|
+
if (raw === undefined)
|
|
227
|
+
return null;
|
|
228
|
+
if (raw === null || raw === "")
|
|
229
|
+
return undefined;
|
|
230
|
+
if (!isRecord(raw))
|
|
231
|
+
return null;
|
|
232
|
+
const allowedKeys = new Set([
|
|
233
|
+
"projects",
|
|
234
|
+
"uploads",
|
|
235
|
+
"temp",
|
|
236
|
+
"home",
|
|
237
|
+
"custom",
|
|
238
|
+
]);
|
|
239
|
+
for (const key of Object.keys(raw)) {
|
|
240
|
+
if (!allowedKeys.has(key))
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
for (const key of ["projects", "uploads", "temp", "home"]) {
|
|
244
|
+
if (key in raw && typeof raw[key] !== "boolean")
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
if ("custom" in raw) {
|
|
248
|
+
if (!Array.isArray(raw.custom) ||
|
|
249
|
+
raw.custom.length > MAX_FILE_ACCESS_CUSTOM_ENTRIES) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
for (const entry of raw.custom) {
|
|
253
|
+
if (typeof entry !== "string" ||
|
|
254
|
+
entry.length > MAX_FILE_ACCESS_CUSTOM_LENGTH) {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return normalizeFileAccess({
|
|
260
|
+
projects: raw.projects,
|
|
261
|
+
uploads: raw.uploads,
|
|
262
|
+
temp: raw.temp,
|
|
263
|
+
home: raw.home,
|
|
264
|
+
custom: raw.custom ?? [],
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
function parseOpenAiModelsResponse(raw) {
|
|
268
|
+
if (!isRecord(raw) || !Array.isArray(raw.data))
|
|
269
|
+
return null;
|
|
270
|
+
const models = [];
|
|
271
|
+
for (const entry of raw.data) {
|
|
272
|
+
if (!isRecord(entry) || typeof entry.id !== "string" || !entry.id.trim()) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
const metadata = isRecord(entry.metadata) ? entry.metadata : undefined;
|
|
276
|
+
const rawContextWindow = typeof entry.max_model_len === "number"
|
|
277
|
+
? entry.max_model_len
|
|
278
|
+
: typeof entry.maxModelLen === "number"
|
|
279
|
+
? entry.maxModelLen
|
|
280
|
+
: typeof metadata?.max_model_len === "number"
|
|
281
|
+
? metadata.max_model_len
|
|
282
|
+
: undefined;
|
|
283
|
+
const contextWindow = rawContextWindow !== undefined && Number.isFinite(rawContextWindow)
|
|
284
|
+
? rawContextWindow
|
|
285
|
+
: undefined;
|
|
286
|
+
models.push({
|
|
287
|
+
id: entry.id,
|
|
288
|
+
name: entry.id,
|
|
289
|
+
...(contextWindow ? { contextWindow } : {}),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return models;
|
|
293
|
+
}
|
|
294
|
+
export function parseAgentContextHints(raw, current) {
|
|
295
|
+
if (raw === undefined || raw === null)
|
|
296
|
+
return {};
|
|
297
|
+
if (!isRecord(raw))
|
|
298
|
+
return null;
|
|
299
|
+
const parsed = { ...current };
|
|
300
|
+
if ("latexMathRendering" in raw) {
|
|
301
|
+
if (typeof raw.latexMathRendering !== "boolean")
|
|
302
|
+
return null;
|
|
303
|
+
parsed.latexMathRendering = raw.latexMathRendering;
|
|
304
|
+
}
|
|
305
|
+
return parsed;
|
|
306
|
+
}
|
|
307
|
+
export async function discoverOpenAiCompatibleModels(baseUrl) {
|
|
308
|
+
const controller = new AbortController();
|
|
309
|
+
const timeout = setTimeout(() => controller.abort(), HELPER_TARGET_MODEL_DISCOVERY_TIMEOUT_MS);
|
|
310
|
+
try {
|
|
311
|
+
const response = await fetch(`${baseUrl}/models`, {
|
|
312
|
+
signal: controller.signal,
|
|
313
|
+
});
|
|
314
|
+
if (!response.ok)
|
|
315
|
+
return null;
|
|
316
|
+
return parseOpenAiModelsResponse(await response.json());
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
clearTimeout(timeout);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Returns:
|
|
327
|
+
* - `null` when the payload is invalid
|
|
328
|
+
* - `undefined` when the setting should be cleared
|
|
329
|
+
* - an object when valid defaults should be saved
|
|
330
|
+
*/
|
|
331
|
+
export function parseNewSessionDefaults(raw) {
|
|
332
|
+
if (raw === undefined)
|
|
333
|
+
return null;
|
|
334
|
+
if (raw === null || raw === "")
|
|
335
|
+
return undefined;
|
|
336
|
+
if (typeof raw !== "object")
|
|
337
|
+
return null;
|
|
338
|
+
const input = raw;
|
|
339
|
+
const parsed = {};
|
|
340
|
+
if ("provider" in input) {
|
|
341
|
+
if (input.provider !== undefined &&
|
|
342
|
+
input.provider !== null &&
|
|
343
|
+
input.provider !== "" &&
|
|
344
|
+
!ALL_PROVIDERS.includes(input.provider)) {
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
if (typeof input.provider === "string" && input.provider.length > 0) {
|
|
348
|
+
parsed.provider = input.provider;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if ("model" in input) {
|
|
352
|
+
const model = parseOptionalString(input.model, 200);
|
|
353
|
+
if (model === null)
|
|
354
|
+
return null;
|
|
355
|
+
if (model)
|
|
356
|
+
parsed.model = model;
|
|
357
|
+
}
|
|
358
|
+
if ("serviceTier" in input) {
|
|
359
|
+
const serviceTier = parseOptionalString(input.serviceTier, 64);
|
|
360
|
+
if (serviceTier === null)
|
|
361
|
+
return null;
|
|
362
|
+
if (serviceTier)
|
|
363
|
+
parsed.serviceTier = serviceTier;
|
|
364
|
+
}
|
|
365
|
+
if ("permissionMode" in input) {
|
|
366
|
+
if (input.permissionMode !== undefined &&
|
|
367
|
+
input.permissionMode !== null &&
|
|
368
|
+
input.permissionMode !== "" &&
|
|
369
|
+
!ALL_PERMISSION_MODES.includes(input.permissionMode)) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
if (typeof input.permissionMode === "string" &&
|
|
373
|
+
input.permissionMode.length > 0) {
|
|
374
|
+
parsed.permissionMode = input.permissionMode;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if ("recapMode" in input) {
|
|
378
|
+
if (input.recapMode !== undefined &&
|
|
379
|
+
input.recapMode !== null &&
|
|
380
|
+
input.recapMode !== "" &&
|
|
381
|
+
!RECAP_MODES.includes(input.recapMode)) {
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
if (typeof input.recapMode === "string" && input.recapMode.length > 0) {
|
|
385
|
+
parsed.recapMode = input.recapMode;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if ("recapAfterSeconds" in input) {
|
|
389
|
+
if (input.recapAfterSeconds !== undefined &&
|
|
390
|
+
input.recapAfterSeconds !== null &&
|
|
391
|
+
input.recapAfterSeconds !== "" &&
|
|
392
|
+
(typeof input.recapAfterSeconds !== "number" ||
|
|
393
|
+
!Number.isFinite(input.recapAfterSeconds))) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
if (typeof input.recapAfterSeconds === "number" &&
|
|
397
|
+
Number.isFinite(input.recapAfterSeconds)) {
|
|
398
|
+
parsed.recapAfterSeconds = clampRecapAfterSeconds(input.recapAfterSeconds);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if ("promptSuggestionMode" in input) {
|
|
402
|
+
if (input.promptSuggestionMode !== undefined &&
|
|
403
|
+
input.promptSuggestionMode !== null &&
|
|
404
|
+
input.promptSuggestionMode !== "" &&
|
|
405
|
+
!PROMPT_SUGGESTION_MODES.includes(input.promptSuggestionMode)) {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
if (typeof input.promptSuggestionMode === "string" &&
|
|
409
|
+
input.promptSuggestionMode.length > 0) {
|
|
410
|
+
parsed.promptSuggestionMode =
|
|
411
|
+
input.promptSuggestionMode;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if ("providers" in input) {
|
|
415
|
+
if (input.providers !== undefined &&
|
|
416
|
+
input.providers !== null &&
|
|
417
|
+
input.providers !== "" &&
|
|
418
|
+
!isRecord(input.providers)) {
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
if (isRecord(input.providers)) {
|
|
422
|
+
const providers = {};
|
|
423
|
+
for (const [providerName, rawDefaults] of Object.entries(input.providers)) {
|
|
424
|
+
if (!ALL_PROVIDERS.includes(providerName)) {
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
const parsedProviderDefaults = parseProviderSessionDefaults(rawDefaults);
|
|
428
|
+
if (parsedProviderDefaults === null)
|
|
429
|
+
return null;
|
|
430
|
+
if (parsedProviderDefaults) {
|
|
431
|
+
providers[providerName] = parsedProviderDefaults;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
if (Object.keys(providers).length > 0) {
|
|
435
|
+
parsed.providers = providers;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return Object.keys(parsed).length > 0 ? parsed : undefined;
|
|
440
|
+
}
|
|
441
|
+
function parseSpeechSmartTurnClientDefault(raw) {
|
|
442
|
+
if (!isRecord(raw))
|
|
443
|
+
return null;
|
|
444
|
+
if (typeof raw.enabled !== "boolean" ||
|
|
445
|
+
typeof raw.threshold !== "number" ||
|
|
446
|
+
typeof raw.timeoutMs !== "number" ||
|
|
447
|
+
!Number.isFinite(raw.threshold) ||
|
|
448
|
+
!Number.isFinite(raw.timeoutMs) ||
|
|
449
|
+
raw.threshold < 0 ||
|
|
450
|
+
raw.threshold > 1 ||
|
|
451
|
+
raw.timeoutMs < 0 ||
|
|
452
|
+
raw.timeoutMs > MAX_SPEECH_SMART_TURN_TIMEOUT_MS) {
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
enabled: raw.enabled,
|
|
457
|
+
threshold: raw.threshold,
|
|
458
|
+
timeoutMs: Math.round(raw.timeoutMs),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
function parseGrokSpeechAudioClientDefault(raw) {
|
|
462
|
+
if (!isRecord(raw))
|
|
463
|
+
return null;
|
|
464
|
+
if (raw.uplinkMode !== "pcm16" && raw.uplinkMode !== "browser-compressed") {
|
|
465
|
+
return null;
|
|
466
|
+
}
|
|
467
|
+
return { uplinkMode: raw.uplinkMode };
|
|
468
|
+
}
|
|
469
|
+
function parseSessionToolbarPresenceClientDefaults(raw) {
|
|
470
|
+
if (raw === undefined || raw === null || raw === "")
|
|
471
|
+
return undefined;
|
|
472
|
+
if (!isRecord(raw))
|
|
473
|
+
return null;
|
|
474
|
+
const allowedKeys = new Set(SESSION_TOOLBAR_PRESENCE_CLIENT_DEFAULT_KEYS);
|
|
475
|
+
for (const key of Object.keys(raw)) {
|
|
476
|
+
if (!allowedKeys.has(key))
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
const allowedPresences = new Set(TOOLBAR_CONTROL_PRESENCES);
|
|
480
|
+
const parsed = {};
|
|
481
|
+
for (const key of SESSION_TOOLBAR_PRESENCE_CLIENT_DEFAULT_KEYS) {
|
|
482
|
+
if (!(key in raw))
|
|
483
|
+
continue;
|
|
484
|
+
const value = raw[key];
|
|
485
|
+
if (typeof value !== "string" || !allowedPresences.has(value))
|
|
486
|
+
return null;
|
|
487
|
+
parsed[key] = value;
|
|
488
|
+
}
|
|
489
|
+
return Object.keys(parsed).length > 0 ? parsed : null;
|
|
490
|
+
}
|
|
491
|
+
// Per-model compaction thresholds: each value is "compact at X% of that
|
|
492
|
+
// model's context window". Reject non-numbers (the slider only ever sends
|
|
493
|
+
// numbers), but treat out-of-range like the load path does — keep 1–99 and
|
|
494
|
+
// drop anything else (including >= 100 = "off"). An empty result clears the
|
|
495
|
+
// setting. The returned map is authoritative: the client always sends the
|
|
496
|
+
// full map, so mergeClientDefaults replaces rather than per-model merges,
|
|
497
|
+
// which is what makes turning a model "off" (dropping its key) take effect.
|
|
498
|
+
function parseCompactAtContextPercent(raw) {
|
|
499
|
+
if (raw === undefined || raw === null || raw === "")
|
|
500
|
+
return undefined;
|
|
501
|
+
if (!isRecord(raw))
|
|
502
|
+
return null;
|
|
503
|
+
const cleaned = {};
|
|
504
|
+
for (const [modelId, value] of Object.entries(raw)) {
|
|
505
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
506
|
+
return null;
|
|
507
|
+
const pct = Math.round(value);
|
|
508
|
+
if (pct > 0 && pct < 100)
|
|
509
|
+
cleaned[modelId] = pct;
|
|
510
|
+
}
|
|
511
|
+
return Object.keys(cleaned).length > 0 ? cleaned : undefined;
|
|
512
|
+
}
|
|
513
|
+
export function parseClientDefaults(raw) {
|
|
514
|
+
if (raw === undefined)
|
|
515
|
+
return null;
|
|
516
|
+
if (raw === null || raw === "")
|
|
517
|
+
return undefined;
|
|
518
|
+
if (!isRecord(raw))
|
|
519
|
+
return null;
|
|
520
|
+
const allowedKeys = new Set(CLIENT_DEFAULT_KEYS);
|
|
521
|
+
for (const key of Object.keys(raw)) {
|
|
522
|
+
if (!allowedKeys.has(key))
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
if (Object.keys(raw).length === 0)
|
|
526
|
+
return null;
|
|
527
|
+
const parsed = {};
|
|
528
|
+
if ("speech" in raw) {
|
|
529
|
+
if (raw.speech === undefined || raw.speech === null || raw.speech === "") {
|
|
530
|
+
parsed.speech = undefined;
|
|
531
|
+
}
|
|
532
|
+
else if (!isRecord(raw.speech)) {
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
const allowedSpeechKeys = new Set(SPEECH_CLIENT_DEFAULT_KEYS);
|
|
537
|
+
for (const key of Object.keys(raw.speech)) {
|
|
538
|
+
if (!allowedSpeechKeys.has(key))
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
const speech = {};
|
|
542
|
+
if ("voiceInputEnabled" in raw.speech) {
|
|
543
|
+
if (typeof raw.speech.voiceInputEnabled !== "boolean")
|
|
544
|
+
return null;
|
|
545
|
+
speech.voiceInputEnabled = raw.speech.voiceInputEnabled;
|
|
546
|
+
}
|
|
547
|
+
if ("speechMethod" in raw.speech) {
|
|
548
|
+
if (typeof raw.speech.speechMethod !== "string" ||
|
|
549
|
+
raw.speech.speechMethod.trim().length === 0) {
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
speech.speechMethod = raw.speech.speechMethod.trim().slice(0, 120);
|
|
553
|
+
}
|
|
554
|
+
if ("speechSmartTurnSettings" in raw.speech) {
|
|
555
|
+
const parsedSmartTurn = parseSpeechSmartTurnClientDefault(raw.speech.speechSmartTurnSettings);
|
|
556
|
+
if (!parsedSmartTurn)
|
|
557
|
+
return null;
|
|
558
|
+
speech.speechSmartTurnSettings = parsedSmartTurn;
|
|
559
|
+
}
|
|
560
|
+
if ("grokSpeechAudioSettings" in raw.speech) {
|
|
561
|
+
const parsedGrokAudio = parseGrokSpeechAudioClientDefault(raw.speech.grokSpeechAudioSettings);
|
|
562
|
+
if (!parsedGrokAudio)
|
|
563
|
+
return null;
|
|
564
|
+
speech.grokSpeechAudioSettings = parsedGrokAudio;
|
|
565
|
+
}
|
|
566
|
+
if (Object.keys(speech).length === 0)
|
|
567
|
+
return null;
|
|
568
|
+
parsed.speech = speech;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
if ("busyComposerDefaultAction" in raw) {
|
|
572
|
+
if (raw.busyComposerDefaultAction === undefined ||
|
|
573
|
+
raw.busyComposerDefaultAction === null) {
|
|
574
|
+
parsed.busyComposerDefaultAction = undefined;
|
|
575
|
+
}
|
|
576
|
+
else if (!BUSY_COMPOSER_DEFAULT_ACTIONS.includes(raw.busyComposerDefaultAction)) {
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
parsed.busyComposerDefaultAction =
|
|
581
|
+
raw.busyComposerDefaultAction;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
if ("collapsedComposerButton" in raw) {
|
|
585
|
+
if (raw.collapsedComposerButton === undefined ||
|
|
586
|
+
raw.collapsedComposerButton === null) {
|
|
587
|
+
parsed.collapsedComposerButton = undefined;
|
|
588
|
+
}
|
|
589
|
+
else if (!COLLAPSED_COMPOSER_BUTTON_PREFERENCES.includes(raw.collapsedComposerButton)) {
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
parsed.collapsedComposerButton =
|
|
594
|
+
raw.collapsedComposerButton;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if ("steerNowDefault" in raw) {
|
|
598
|
+
if (raw.steerNowDefault === undefined || raw.steerNowDefault === null) {
|
|
599
|
+
parsed.steerNowDefault = undefined;
|
|
600
|
+
}
|
|
601
|
+
else if (typeof raw.steerNowDefault !== "boolean") {
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
parsed.steerNowDefault = raw.steerNowDefault;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
if ("patientQueueDefault" in raw) {
|
|
609
|
+
if (raw.patientQueueDefault === undefined ||
|
|
610
|
+
raw.patientQueueDefault === null) {
|
|
611
|
+
parsed.patientQueueDefault = undefined;
|
|
612
|
+
}
|
|
613
|
+
else if (typeof raw.patientQueueDefault !== "boolean") {
|
|
614
|
+
return null;
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
parsed.patientQueueDefault = raw.patientQueueDefault;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
if ("projectQueueCtrlEnterEnabled" in raw) {
|
|
621
|
+
if (raw.projectQueueCtrlEnterEnabled === undefined ||
|
|
622
|
+
raw.projectQueueCtrlEnterEnabled === null) {
|
|
623
|
+
parsed.projectQueueCtrlEnterEnabled = undefined;
|
|
624
|
+
}
|
|
625
|
+
else if (typeof raw.projectQueueCtrlEnterEnabled !== "boolean") {
|
|
626
|
+
return null;
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
parsed.projectQueueCtrlEnterEnabled = raw.projectQueueCtrlEnterEnabled;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if ("sessionToolbarPresence" in raw) {
|
|
633
|
+
const parsedPresence = parseSessionToolbarPresenceClientDefaults(raw.sessionToolbarPresence);
|
|
634
|
+
if (parsedPresence === null)
|
|
635
|
+
return null;
|
|
636
|
+
parsed.sessionToolbarPresence = parsedPresence;
|
|
637
|
+
}
|
|
638
|
+
if ("compactAtContextPercent" in raw) {
|
|
639
|
+
const parsedCompact = parseCompactAtContextPercent(raw.compactAtContextPercent);
|
|
640
|
+
if (parsedCompact === null)
|
|
641
|
+
return null;
|
|
642
|
+
parsed.compactAtContextPercent = parsedCompact;
|
|
643
|
+
}
|
|
644
|
+
return Object.keys(parsed).length > 0 ? parsed : undefined;
|
|
645
|
+
}
|
|
646
|
+
export function mergeClientDefaults(current, update) {
|
|
647
|
+
if (!update)
|
|
648
|
+
return undefined;
|
|
649
|
+
const merged = { ...current };
|
|
650
|
+
if ("speech" in update) {
|
|
651
|
+
if (update.speech === undefined) {
|
|
652
|
+
delete merged.speech;
|
|
653
|
+
}
|
|
654
|
+
else {
|
|
655
|
+
merged.speech = {
|
|
656
|
+
...current?.speech,
|
|
657
|
+
...update.speech,
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
if ("busyComposerDefaultAction" in update) {
|
|
662
|
+
if (update.busyComposerDefaultAction === undefined) {
|
|
663
|
+
delete merged.busyComposerDefaultAction;
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
merged.busyComposerDefaultAction = update.busyComposerDefaultAction;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
if ("collapsedComposerButton" in update) {
|
|
670
|
+
if (update.collapsedComposerButton === undefined) {
|
|
671
|
+
delete merged.collapsedComposerButton;
|
|
672
|
+
}
|
|
673
|
+
else {
|
|
674
|
+
merged.collapsedComposerButton = update.collapsedComposerButton;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if ("steerNowDefault" in update) {
|
|
678
|
+
if (update.steerNowDefault === undefined) {
|
|
679
|
+
delete merged.steerNowDefault;
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
merged.steerNowDefault = update.steerNowDefault;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
if ("patientQueueDefault" in update) {
|
|
686
|
+
if (update.patientQueueDefault === undefined) {
|
|
687
|
+
delete merged.patientQueueDefault;
|
|
688
|
+
}
|
|
689
|
+
else {
|
|
690
|
+
merged.patientQueueDefault = update.patientQueueDefault;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
if ("projectQueueCtrlEnterEnabled" in update) {
|
|
694
|
+
if (update.projectQueueCtrlEnterEnabled === undefined) {
|
|
695
|
+
delete merged.projectQueueCtrlEnterEnabled;
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
merged.projectQueueCtrlEnterEnabled = update.projectQueueCtrlEnterEnabled;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
if ("sessionToolbarPresence" in update) {
|
|
702
|
+
if (update.sessionToolbarPresence === undefined) {
|
|
703
|
+
delete merged.sessionToolbarPresence;
|
|
704
|
+
}
|
|
705
|
+
else {
|
|
706
|
+
merged.sessionToolbarPresence = {
|
|
707
|
+
...current?.sessionToolbarPresence,
|
|
708
|
+
...update.sessionToolbarPresence,
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
if ("compactAtContextPercent" in update) {
|
|
713
|
+
// Replace the whole map (not a per-model merge): the client always sends
|
|
714
|
+
// the complete map, so a model dropped from it means "off" for that model.
|
|
715
|
+
if (update.compactAtContextPercent === undefined) {
|
|
716
|
+
delete merged.compactAtContextPercent;
|
|
717
|
+
}
|
|
718
|
+
else {
|
|
719
|
+
merged.compactAtContextPercent = update.compactAtContextPercent;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
723
|
+
}
|
|
724
|
+
export function parseSpeechAudioRetention(raw) {
|
|
725
|
+
if (raw === undefined || raw === null) {
|
|
726
|
+
return DEFAULT_SERVER_SETTINGS.speechAudioRetention;
|
|
727
|
+
}
|
|
728
|
+
if (!isRecord(raw))
|
|
729
|
+
return null;
|
|
730
|
+
const enabled = typeof raw.enabled === "boolean"
|
|
731
|
+
? raw.enabled
|
|
732
|
+
: DEFAULT_SERVER_SETTINGS.speechAudioRetention.enabled;
|
|
733
|
+
const maxAgeDays = raw.maxAgeDays === undefined || raw.maxAgeDays === null
|
|
734
|
+
? DEFAULT_SPEECH_AUDIO_RETENTION_MAX_AGE_DAYS
|
|
735
|
+
: raw.maxAgeDays;
|
|
736
|
+
const maxBytes = raw.maxBytes === undefined || raw.maxBytes === null
|
|
737
|
+
? DEFAULT_SPEECH_AUDIO_RETENTION_MAX_BYTES
|
|
738
|
+
: raw.maxBytes;
|
|
739
|
+
if (typeof maxAgeDays !== "number" ||
|
|
740
|
+
!Number.isInteger(maxAgeDays) ||
|
|
741
|
+
maxAgeDays < 1 ||
|
|
742
|
+
maxAgeDays > 3650) {
|
|
743
|
+
return null;
|
|
744
|
+
}
|
|
745
|
+
if (typeof maxBytes !== "number" ||
|
|
746
|
+
!Number.isInteger(maxBytes) ||
|
|
747
|
+
maxBytes < 1024 * 1024 ||
|
|
748
|
+
maxBytes > 100 * 1024 * 1024 * 1024) {
|
|
749
|
+
return null;
|
|
750
|
+
}
|
|
751
|
+
return { enabled, maxAgeDays, maxBytes };
|
|
752
|
+
}
|
|
753
|
+
export function parsePromptCacheKeepalive(raw) {
|
|
754
|
+
if (raw === undefined)
|
|
755
|
+
return null;
|
|
756
|
+
if (raw === null || raw === "")
|
|
757
|
+
return undefined;
|
|
758
|
+
if (!isRecord(raw))
|
|
759
|
+
return null;
|
|
760
|
+
const rawProviders = raw.providers;
|
|
761
|
+
if (rawProviders === undefined || rawProviders === null)
|
|
762
|
+
return {};
|
|
763
|
+
if (!isRecord(rawProviders))
|
|
764
|
+
return null;
|
|
765
|
+
const providers = {};
|
|
766
|
+
for (const [providerName, rawProviderSetting] of Object.entries(rawProviders)) {
|
|
767
|
+
if (!ALL_PROVIDERS.includes(providerName))
|
|
768
|
+
return null;
|
|
769
|
+
if (rawProviderSetting === undefined || rawProviderSetting === null) {
|
|
770
|
+
continue;
|
|
771
|
+
}
|
|
772
|
+
if (!isRecord(rawProviderSetting))
|
|
773
|
+
return null;
|
|
774
|
+
const setting = {};
|
|
775
|
+
if ("mode" in rawProviderSetting) {
|
|
776
|
+
if (typeof rawProviderSetting.mode !== "string" ||
|
|
777
|
+
!PROMPT_CACHE_KEEPALIVE_MODES.includes(rawProviderSetting.mode)) {
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
setting.mode = rawProviderSetting.mode;
|
|
781
|
+
}
|
|
782
|
+
if ("inactivityMinutes" in rawProviderSetting) {
|
|
783
|
+
const value = rawProviderSetting.inactivityMinutes;
|
|
784
|
+
if (typeof value !== "number" ||
|
|
785
|
+
!Number.isInteger(value) ||
|
|
786
|
+
value < 1 ||
|
|
787
|
+
value > 1440) {
|
|
788
|
+
return null;
|
|
789
|
+
}
|
|
790
|
+
setting.inactivityMinutes = value;
|
|
791
|
+
}
|
|
792
|
+
if (Object.keys(setting).length > 0) {
|
|
793
|
+
providers[providerName] = setting;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
return { providers };
|
|
797
|
+
}
|
|
798
|
+
export function parseCacheMissBilling(raw) {
|
|
799
|
+
if (raw === undefined)
|
|
800
|
+
return null;
|
|
801
|
+
if (raw === null || raw === "")
|
|
802
|
+
return DEFAULT_CACHE_MISS_BILLING_SETTINGS;
|
|
803
|
+
if (!isRecord(raw))
|
|
804
|
+
return null;
|
|
805
|
+
const parsed = {};
|
|
806
|
+
if ("enabled" in raw) {
|
|
807
|
+
if (raw.enabled === undefined || raw.enabled === null) {
|
|
808
|
+
parsed.enabled = DEFAULT_CACHE_MISS_BILLING_SETTINGS.enabled;
|
|
809
|
+
}
|
|
810
|
+
else if (typeof raw.enabled !== "boolean") {
|
|
811
|
+
return null;
|
|
812
|
+
}
|
|
813
|
+
else {
|
|
814
|
+
parsed.enabled = raw.enabled;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
if ("showToasts" in raw) {
|
|
818
|
+
if (raw.showToasts === undefined || raw.showToasts === null) {
|
|
819
|
+
parsed.showToasts = DEFAULT_CACHE_MISS_BILLING_SETTINGS.showToasts;
|
|
820
|
+
}
|
|
821
|
+
else if (typeof raw.showToasts !== "boolean") {
|
|
822
|
+
return null;
|
|
823
|
+
}
|
|
824
|
+
else {
|
|
825
|
+
parsed.showToasts = raw.showToasts;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
if ("freshWindowMinutes" in raw) {
|
|
829
|
+
if (raw.freshWindowMinutes === undefined ||
|
|
830
|
+
raw.freshWindowMinutes === null) {
|
|
831
|
+
parsed.freshWindowMinutes =
|
|
832
|
+
DEFAULT_CACHE_MISS_BILLING_SETTINGS.freshWindowMinutes;
|
|
833
|
+
}
|
|
834
|
+
else if (typeof raw.freshWindowMinutes !== "number" ||
|
|
835
|
+
!Number.isInteger(raw.freshWindowMinutes) ||
|
|
836
|
+
raw.freshWindowMinutes < 1 ||
|
|
837
|
+
raw.freshWindowMinutes > 1440) {
|
|
838
|
+
return null;
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
parsed.freshWindowMinutes = raw.freshWindowMinutes;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
if ("providerFreshWindowMinutes" in raw) {
|
|
845
|
+
if (raw.providerFreshWindowMinutes === undefined ||
|
|
846
|
+
raw.providerFreshWindowMinutes === null) {
|
|
847
|
+
parsed.providerFreshWindowMinutes =
|
|
848
|
+
DEFAULT_CACHE_MISS_BILLING_SETTINGS.providerFreshWindowMinutes;
|
|
849
|
+
}
|
|
850
|
+
else if (!isRecord(raw.providerFreshWindowMinutes)) {
|
|
851
|
+
return null;
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
const providerFreshWindowMinutes = {};
|
|
855
|
+
for (const [providerName, value] of Object.entries(raw.providerFreshWindowMinutes)) {
|
|
856
|
+
if (!ALL_PROVIDERS.includes(providerName)) {
|
|
857
|
+
return null;
|
|
858
|
+
}
|
|
859
|
+
if (typeof value !== "number" ||
|
|
860
|
+
!Number.isInteger(value) ||
|
|
861
|
+
value < 1 ||
|
|
862
|
+
value > 1440) {
|
|
863
|
+
return null;
|
|
864
|
+
}
|
|
865
|
+
providerFreshWindowMinutes[providerName] = value;
|
|
866
|
+
}
|
|
867
|
+
parsed.providerFreshWindowMinutes = providerFreshWindowMinutes;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
if ("minimumInputTokens" in raw) {
|
|
871
|
+
if (raw.minimumInputTokens === undefined ||
|
|
872
|
+
raw.minimumInputTokens === null) {
|
|
873
|
+
parsed.minimumInputTokens =
|
|
874
|
+
DEFAULT_CACHE_MISS_BILLING_SETTINGS.minimumInputTokens;
|
|
875
|
+
}
|
|
876
|
+
else if (typeof raw.minimumInputTokens !== "number" ||
|
|
877
|
+
!Number.isInteger(raw.minimumInputTokens) ||
|
|
878
|
+
raw.minimumInputTokens < 1 ||
|
|
879
|
+
raw.minimumInputTokens > 5_000_000) {
|
|
880
|
+
return null;
|
|
881
|
+
}
|
|
882
|
+
else {
|
|
883
|
+
parsed.minimumInputTokens = raw.minimumInputTokens;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
const result = {
|
|
887
|
+
...DEFAULT_CACHE_MISS_BILLING_SETTINGS,
|
|
888
|
+
...parsed,
|
|
889
|
+
providerFreshWindowMinutes: {
|
|
890
|
+
...DEFAULT_CACHE_MISS_BILLING_SETTINGS.providerFreshWindowMinutes,
|
|
891
|
+
...parsed.providerFreshWindowMinutes,
|
|
892
|
+
},
|
|
893
|
+
};
|
|
894
|
+
return result;
|
|
895
|
+
}
|
|
896
|
+
//# sourceMappingURL=settings-parsers.js.map
|