Nanny7 commited on
Commit
f98edcd
·
1 Parent(s): 5246bcd

Use custom guest registration modal

Browse files
config/minimal_ui_patch.js CHANGED
@@ -1,5 +1,4 @@
1
  (() => {
2
- // ── Prompt suggestions ──────────────────────────────────────────
3
  const MONTAIGNE_SUGGESTIONS = [
4
  {
5
  title: ['What occupies your thoughts', 'most lately?'],
@@ -27,7 +26,6 @@
27
  }
28
  ];
29
 
30
- // ── Elements to hide ────────────────────────────────────────────
31
  const HIDE_TEXT = new Set([
32
  'Settings',
33
  'Archived Chats',
@@ -39,143 +37,249 @@
39
  'Releases',
40
  'Set as default'
41
  ]);
42
-
43
  const HIDE_HREF = new Set(['/playground', '/admin']);
44
  const HIDE_ARIA = new Set(['Controls', 'Add Model', 'Remove Model', 'Voice Input', 'Voice mode']);
45
 
46
- // ── Guest upgrade constants ─────────────────────────────────────
47
- const GUEST_TOKEN_KEY = 'montaigne_guest_upgrade_token';
48
  const CHAT_COMPLETIONS_PATH = '/api/chat/completions';
49
- const GUEST_SIGNUP_NOTICE_ID = 'montaigne-guest-signup-notice';
 
 
50
 
51
  function normalize(text) {
52
  return (text || '').replace(/\s+/g, ' ').trim();
53
  }
54
 
55
- // ── Guest upgrade: CTA banner ───────────────────────────────────
56
- function showGuestBanner() {
57
- if (document.getElementById('montaigne-guest-banner')) return;
58
-
59
- const banner = document.createElement('div');
60
- banner.id = 'montaigne-guest-banner';
61
- banner.style.cssText =
62
- 'position:fixed;bottom:0;left:0;right:0;z-index:99999;' +
63
- 'background:linear-gradient(135deg,#3d2b1f,#5c3d2e);color:#f5e6d3;' +
64
- 'padding:14px 20px;display:flex;align-items:center;justify-content:center;' +
65
- 'gap:16px;font-family:Inter,system-ui,sans-serif;font-size:14px;' +
66
- 'box-shadow:0 -2px 12px rgba(0,0,0,.3);';
67
-
68
- const msg = document.createElement('span');
69
- msg.textContent =
70
- 'You\u2019ve used your 5 free messages. Create a free account to continue chatting with Montaigne.';
71
-
72
- const btn = document.createElement('a');
73
- btn.textContent = 'Create free account';
74
- btn.style.cssText =
75
- 'background:#c9a96e;color:#2b1d0e;padding:8px 18px;border-radius:6px;' +
76
- 'text-decoration:none;font-weight:600;white-space:nowrap;cursor:pointer;' +
77
- 'transition:background .15s;';
78
- btn.onmouseenter = () => (btn.style.background = '#d4b87a');
79
- btn.onmouseleave = () => (btn.style.background = '#c9a96e');
80
-
81
- const currentPath = window.location.pathname + window.location.search;
82
- const authUrl = '/auth?form=true&redirect=' + encodeURIComponent(currentPath) + '&guestUpgrade=1';
83
- btn.href = authUrl;
84
-
85
- const close = document.createElement('button');
86
- close.textContent = '\u00d7';
87
- close.style.cssText =
88
- 'background:none;border:none;color:#f5e6d3;font-size:20px;cursor:pointer;' +
89
- 'padding:0 4px;line-height:1;';
90
- close.onclick = () => banner.remove();
91
 
92
- banner.appendChild(msg);
93
- banner.appendChild(btn);
94
- banner.appendChild(close);
95
- document.body.appendChild(banner);
 
96
  }
97
 
98
- function applyGuestUpgradeAuthPrompt() {
99
- const url = new URL(window.location.href);
100
- if (url.pathname !== '/auth' || url.searchParams.get('guestUpgrade') !== '1') {
 
 
 
 
 
101
  return;
102
  }
103
-
104
- const authContainer = document.getElementById('auth-container');
105
- if (!authContainer) {
 
 
 
106
  return;
107
  }
108
 
109
- if (!document.getElementById(GUEST_SIGNUP_NOTICE_ID)) {
110
- const notice = document.createElement('div');
111
- notice.id = GUEST_SIGNUP_NOTICE_ID;
112
- notice.textContent = 'Create an account to keep this conversation and continue where you left off.';
113
- notice.style.cssText =
114
- 'margin:18px auto 14px;max-width:28rem;padding:12px 14px;border-radius:10px;' +
115
- 'background:rgba(201,169,110,.12);border:1px solid rgba(201,169,110,.35);' +
116
- 'color:inherit;font-size:14px;line-height:1.45;';
117
- const target = authContainer.querySelector('.w-full.px-10') || authContainer.firstElementChild;
118
- if (target) {
119
- target.insertBefore(notice, target.firstChild || null);
 
 
 
 
 
 
120
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  }
 
122
 
123
- if (document.documentElement.dataset.montaigneGuestSignupActivated === '1') {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  return;
125
  }
126
 
127
- const toggleButtons = Array.from(authContainer.querySelectorAll('button[type="button"]'));
128
- const signupToggle = toggleButtons.find((button) => normalize(button.textContent) === 'Sign up');
129
- if (signupToggle) {
130
- document.documentElement.dataset.montaigneGuestSignupActivated = '1';
131
- signupToggle.click();
132
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  }
134
 
135
- // ── Unified fetch patch (config + guest upgrade) ───────────────
136
  function installFetchPatch() {
137
- if (window.__montaigneFetchPatched) return;
 
 
138
  window.__montaigneFetchPatched = true;
139
 
140
  const originalFetch = window.fetch.bind(window);
141
 
142
  window.fetch = async (...args) => {
143
- // ── Outgoing request: inject guest upgrade token ──────────
144
  try {
145
  const input = args[0];
146
  const rawUrl = input instanceof Request ? input.url : String(input);
147
  const url = new URL(rawUrl, window.location.origin);
148
 
149
  if (url.pathname === CHAT_COMPLETIONS_PATH) {
150
- const storedToken = localStorage.getItem(GUEST_TOKEN_KEY);
151
- if (storedToken) {
152
- let body = args[1] && args[1].body;
153
- if (typeof body === 'string') {
154
- try {
155
- const parsed = JSON.parse(body);
156
- if (!parsed.variables) parsed.variables = {};
157
- parsed.variables.guest_upgrade_token = storedToken;
158
- args[1] = { ...args[1], body: JSON.stringify(parsed) };
159
- } catch (_) {
160
- // Body not JSON — skip injection
161
  }
 
 
 
162
  }
163
  }
164
  }
165
  } catch (_) {
166
- // URL parsing failed — proceed with original args
167
  }
168
 
169
- // ── Perform request ───────────────────────────────────────
170
  const response = await originalFetch(...args);
171
 
172
- // ── Incoming response handling ────────────────────────────
173
  try {
174
  const input = args[0];
175
  const rawUrl = input instanceof Request ? input.url : String(input);
176
  const url = new URL(rawUrl, window.location.origin);
177
 
178
- // Patch 1: inject prompt suggestions into /api/config
179
  if (url.pathname === '/api/config') {
180
  const payload = await response.clone().json();
181
  payload.default_prompt_suggestions = MONTAIGNE_SUGGESTIONS;
@@ -189,42 +293,26 @@
189
  });
190
  }
191
 
192
- // Patch 2: intercept 403 guest_limit_reached on chat completions
193
  if (url.pathname === CHAT_COMPLETIONS_PATH && response.status === 403) {
194
- const clone = response.clone();
195
- try {
196
- const body = await clone.json();
197
- const code = typeof body === 'object' ? body.code : null;
198
- const token = typeof body === 'object' ? body.guest_upgrade_token : null;
199
-
200
- if (code === 'guest_limit_reached' && token) {
201
- localStorage.setItem(GUEST_TOKEN_KEY, token);
202
- showGuestBanner();
203
- }
204
- } catch (_) {
205
- // Not JSON — fall through
206
  }
207
-
208
- // Patch 3: on successful chat response, clear consumed token
209
- } else if (
210
- url.pathname === CHAT_COMPLETIONS_PATH &&
211
- response.ok
212
- ) {
213
- localStorage.removeItem(GUEST_TOKEN_KEY);
214
- const banner = document.getElementById('montaigne-guest-banner');
215
- if (banner) banner.remove();
216
  }
217
  } catch (_) {
218
- // Swallow — never break the page
219
  }
220
 
221
  return response;
222
  };
223
  }
224
 
225
- // ── Minimal UI: hide power-user elements ───────────────────────
226
  function hide(el) {
227
- if (!el || el.dataset.montaigneHidden === '1') return;
 
 
228
  el.dataset.montaigneHidden = '1';
229
  el.style.display = 'none';
230
  }
@@ -248,8 +336,6 @@
248
  }
249
 
250
  function applyMinimalUi() {
251
- applyGuestUpgradeAuthPrompt();
252
-
253
  document
254
  .querySelectorAll('[id^="model-selector-"][id$="-button"]')
255
  .forEach(hideModelSelector);
@@ -261,7 +347,9 @@
261
  const text = normalize(el.textContent);
262
  if (text.includes("What's New") || text.includes('Release Notes')) {
263
  const closeButton = el.querySelector('button[aria-label="Close"]');
264
- if (closeButton) closeButton.click();
 
 
265
  hide(el);
266
  }
267
  });
@@ -278,7 +366,6 @@
278
  document.querySelectorAll('#temporary-chat-button').forEach(hide);
279
  }
280
 
281
- // ── Boot ───────────────────────────────────────────────────────
282
  installFetchPatch();
283
 
284
  const run = () => window.requestAnimationFrame(applyMinimalUi);
 
1
  (() => {
 
2
  const MONTAIGNE_SUGGESTIONS = [
3
  {
4
  title: ['What occupies your thoughts', 'most lately?'],
 
26
  }
27
  ];
28
 
 
29
  const HIDE_TEXT = new Set([
30
  'Settings',
31
  'Archived Chats',
 
37
  'Releases',
38
  'Set as default'
39
  ]);
 
40
  const HIDE_HREF = new Set(['/playground', '/admin']);
41
  const HIDE_ARIA = new Set(['Controls', 'Add Model', 'Remove Model', 'Voice Input', 'Voice mode']);
42
 
 
 
43
  const CHAT_COMPLETIONS_PATH = '/api/chat/completions';
44
+ const GUEST_TOKEN_KEY = 'montaigne_guest_upgrade_token';
45
+ const GUEST_CLAIM_URL_KEY = 'montaigne_guest_claim_url';
46
+ const MONTAIGNE_TOKEN_KEY = 'montaigne_access_token';
47
 
48
  function normalize(text) {
49
  return (text || '').replace(/\s+/g, ' ').trim();
50
  }
51
 
52
+ function removeGuestBanner() {
53
+ const banner = document.getElementById('montaigne-guest-banner');
54
+ if (banner) {
55
+ banner.remove();
56
+ }
57
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
+ function closeGuestModal() {
60
+ const modal = document.getElementById('montaigne-guest-modal');
61
+ if (modal) {
62
+ modal.remove();
63
+ }
64
  }
65
 
66
+ async function submitGuestClaim(form, statusEl) {
67
+ const guestUpgradeToken = localStorage.getItem(GUEST_TOKEN_KEY);
68
+ const claimUrl = localStorage.getItem(GUEST_CLAIM_URL_KEY);
69
+ const username = form.querySelector('[name="username"]').value.trim();
70
+ const password = form.querySelector('[name="password"]').value;
71
+
72
+ if (!guestUpgradeToken || !claimUrl) {
73
+ statusEl.textContent = 'This guest session can no longer be claimed. Please refresh and try again.';
74
  return;
75
  }
76
+ if (username.length < 3) {
77
+ statusEl.textContent = 'Choose a username with at least 3 characters.';
78
+ return;
79
+ }
80
+ if (password.length < 6) {
81
+ statusEl.textContent = 'Choose a password with at least 6 characters.';
82
  return;
83
  }
84
 
85
+ statusEl.textContent = 'Creating your account...';
86
+
87
+ try {
88
+ const response = await fetch(claimUrl, {
89
+ method: 'POST',
90
+ headers: {
91
+ 'Content-Type': 'application/json'
92
+ },
93
+ body: JSON.stringify({
94
+ guest_upgrade_token: guestUpgradeToken,
95
+ username,
96
+ password
97
+ })
98
+ });
99
+ const payload = await response.json();
100
+ if (!response.ok) {
101
+ throw new Error(payload.detail || 'Could not create your account.');
102
  }
103
+
104
+ localStorage.setItem(MONTAIGNE_TOKEN_KEY, payload.access_token);
105
+ localStorage.removeItem(GUEST_TOKEN_KEY);
106
+ localStorage.removeItem(GUEST_CLAIM_URL_KEY);
107
+ closeGuestModal();
108
+ removeGuestBanner();
109
+
110
+ const toast = document.createElement('div');
111
+ toast.style.cssText =
112
+ 'position:fixed;bottom:18px;left:50%;transform:translateX(-50%);z-index:100000;' +
113
+ 'background:#16311f;color:#e6f6ea;padding:10px 14px;border-radius:10px;' +
114
+ 'font:13px Inter,system-ui,sans-serif;box-shadow:0 10px 30px rgba(0,0,0,.25);';
115
+ toast.textContent = 'Account created. Send your next message to continue.';
116
+ document.body.appendChild(toast);
117
+ setTimeout(() => toast.remove(), 4000);
118
+ } catch (error) {
119
+ statusEl.textContent = error instanceof Error ? error.message : 'Could not create your account.';
120
  }
121
+ }
122
 
123
+ function openGuestModal() {
124
+ closeGuestModal();
125
+
126
+ const overlay = document.createElement('div');
127
+ overlay.id = 'montaigne-guest-modal';
128
+ overlay.style.cssText =
129
+ 'position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;' +
130
+ 'background:rgba(22,16,12,.62);padding:20px;';
131
+
132
+ const card = document.createElement('div');
133
+ card.style.cssText =
134
+ 'width:min(420px,100%);border-radius:18px;padding:22px;background:#f5ede0;color:#2b2118;' +
135
+ 'box-shadow:0 20px 60px rgba(0,0,0,.35);font:14px Inter,system-ui,sans-serif;';
136
+
137
+ const title = document.createElement('h2');
138
+ title.textContent = 'Create your account';
139
+ title.style.cssText = 'margin:0 0 8px;font:600 22px Georgia,serif;';
140
+
141
+ const intro = document.createElement('p');
142
+ intro.textContent = 'Keep this conversation and continue chatting with Montaigne.';
143
+ intro.style.cssText = 'margin:0 0 16px;line-height:1.45;color:#5b4a3c;';
144
+
145
+ const form = document.createElement('form');
146
+ form.style.cssText = 'display:grid;gap:12px;';
147
+
148
+ const username = document.createElement('input');
149
+ username.name = 'username';
150
+ username.placeholder = 'Username';
151
+ username.autocomplete = 'username';
152
+ username.style.cssText =
153
+ 'width:100%;padding:12px 14px;border:1px solid #cfb89b;border-radius:10px;background:#fffdf9;';
154
+
155
+ const password = document.createElement('input');
156
+ password.name = 'password';
157
+ password.type = 'password';
158
+ password.placeholder = 'Password';
159
+ password.autocomplete = 'new-password';
160
+ password.style.cssText = username.style.cssText;
161
+
162
+ const status = document.createElement('div');
163
+ status.style.cssText = 'min-height:18px;font-size:13px;color:#8a2f2f;';
164
+
165
+ const actions = document.createElement('div');
166
+ actions.style.cssText = 'display:flex;justify-content:flex-end;gap:10px;margin-top:4px;';
167
+
168
+ const cancel = document.createElement('button');
169
+ cancel.type = 'button';
170
+ cancel.textContent = 'Cancel';
171
+ cancel.style.cssText =
172
+ 'padding:10px 14px;border:1px solid #cfb89b;border-radius:10px;background:#fff8ef;cursor:pointer;';
173
+ cancel.onclick = () => closeGuestModal();
174
+
175
+ const submit = document.createElement('button');
176
+ submit.type = 'submit';
177
+ submit.textContent = 'Create account';
178
+ submit.style.cssText =
179
+ 'padding:10px 14px;border:none;border-radius:10px;background:#8b6243;color:#fff;cursor:pointer;font-weight:600;';
180
+
181
+ form.addEventListener('submit', async (event) => {
182
+ event.preventDefault();
183
+ await submitGuestClaim(form, status);
184
+ });
185
+
186
+ actions.appendChild(cancel);
187
+ actions.appendChild(submit);
188
+ form.appendChild(username);
189
+ form.appendChild(password);
190
+ form.appendChild(status);
191
+ form.appendChild(actions);
192
+
193
+ card.appendChild(title);
194
+ card.appendChild(intro);
195
+ card.appendChild(form);
196
+ overlay.appendChild(card);
197
+ overlay.addEventListener('click', (event) => {
198
+ if (event.target === overlay) {
199
+ closeGuestModal();
200
+ }
201
+ });
202
+ document.body.appendChild(overlay);
203
+ username.focus();
204
+ }
205
+
206
+ function showGuestBanner() {
207
+ if (document.getElementById('montaigne-guest-banner')) {
208
  return;
209
  }
210
 
211
+ const banner = document.createElement('div');
212
+ banner.id = 'montaigne-guest-banner';
213
+ banner.style.cssText =
214
+ 'position:fixed;bottom:0;left:0;right:0;z-index:99999;background:linear-gradient(135deg,#3d2b1f,#5c3d2e);' +
215
+ 'color:#f5e6d3;padding:14px 20px;display:flex;align-items:center;justify-content:center;gap:16px;' +
216
+ 'font:14px Inter,system-ui,sans-serif;box-shadow:0 -2px 12px rgba(0,0,0,.3);';
217
+
218
+ const message = document.createElement('span');
219
+ message.textContent = 'You have used your 5 free messages. Create a free account to continue chatting with Montaigne.';
220
+
221
+ const button = document.createElement('button');
222
+ button.type = 'button';
223
+ button.textContent = 'Create free account';
224
+ button.style.cssText =
225
+ 'background:#c9a96e;color:#2b1d0e;padding:8px 18px;border:none;border-radius:6px;' +
226
+ 'font-weight:600;white-space:nowrap;cursor:pointer;';
227
+ button.onclick = () => openGuestModal();
228
+
229
+ const close = document.createElement('button');
230
+ close.type = 'button';
231
+ close.textContent = 'x';
232
+ close.style.cssText =
233
+ 'background:none;border:none;color:#f5e6d3;font-size:20px;cursor:pointer;padding:0 4px;line-height:1;';
234
+ close.onclick = () => removeGuestBanner();
235
+
236
+ banner.appendChild(message);
237
+ banner.appendChild(button);
238
+ banner.appendChild(close);
239
+ document.body.appendChild(banner);
240
  }
241
 
 
242
  function installFetchPatch() {
243
+ if (window.__montaigneFetchPatched) {
244
+ return;
245
+ }
246
  window.__montaigneFetchPatched = true;
247
 
248
  const originalFetch = window.fetch.bind(window);
249
 
250
  window.fetch = async (...args) => {
 
251
  try {
252
  const input = args[0];
253
  const rawUrl = input instanceof Request ? input.url : String(input);
254
  const url = new URL(rawUrl, window.location.origin);
255
 
256
  if (url.pathname === CHAT_COMPLETIONS_PATH) {
257
+ const body = args[1] && args[1].body;
258
+ if (typeof body === 'string') {
259
+ try {
260
+ const parsed = JSON.parse(body);
261
+ parsed.variables = parsed.variables || {};
262
+ const montaigneToken = localStorage.getItem(MONTAIGNE_TOKEN_KEY);
263
+ if (montaigneToken) {
264
+ parsed.variables.montaigne_token = montaigneToken;
 
 
 
265
  }
266
+ args[1] = { ...args[1], body: JSON.stringify(parsed) };
267
+ } catch (_) {
268
+ // Ignore non-JSON payloads.
269
  }
270
  }
271
  }
272
  } catch (_) {
273
+ // Ignore URL parsing errors.
274
  }
275
 
 
276
  const response = await originalFetch(...args);
277
 
 
278
  try {
279
  const input = args[0];
280
  const rawUrl = input instanceof Request ? input.url : String(input);
281
  const url = new URL(rawUrl, window.location.origin);
282
 
 
283
  if (url.pathname === '/api/config') {
284
  const payload = await response.clone().json();
285
  payload.default_prompt_suggestions = MONTAIGNE_SUGGESTIONS;
 
293
  });
294
  }
295
 
 
296
  if (url.pathname === CHAT_COMPLETIONS_PATH && response.status === 403) {
297
+ const payload = await response.clone().json().catch(() => null);
298
+ if (payload && payload.code === 'guest_limit_reached' && payload.guest_upgrade_token && payload.claim_guest_url) {
299
+ localStorage.setItem(GUEST_TOKEN_KEY, payload.guest_upgrade_token);
300
+ localStorage.setItem(GUEST_CLAIM_URL_KEY, payload.claim_guest_url);
301
+ showGuestBanner();
 
 
 
 
 
 
 
302
  }
 
 
 
 
 
 
 
 
 
303
  }
304
  } catch (_) {
305
+ // Keep the UI resilient.
306
  }
307
 
308
  return response;
309
  };
310
  }
311
 
 
312
  function hide(el) {
313
+ if (!el || el.dataset.montaigneHidden === '1') {
314
+ return;
315
+ }
316
  el.dataset.montaigneHidden = '1';
317
  el.style.display = 'none';
318
  }
 
336
  }
337
 
338
  function applyMinimalUi() {
 
 
339
  document
340
  .querySelectorAll('[id^="model-selector-"][id$="-button"]')
341
  .forEach(hideModelSelector);
 
347
  const text = normalize(el.textContent);
348
  if (text.includes("What's New") || text.includes('Release Notes')) {
349
  const closeButton = el.querySelector('button[aria-label="Close"]');
350
+ if (closeButton) {
351
+ closeButton.click();
352
+ }
353
  hide(el);
354
  }
355
  });
 
366
  document.querySelectorAll('#temporary-chat-button').forEach(hide);
367
  }
368
 
 
369
  installFetchPatch();
370
 
371
  const run = () => window.requestAnimationFrame(applyMinimalUi);
config/ui_policy.json CHANGED
@@ -1,10 +1,6 @@
1
  {
2
  "default_models": "montaigne",
3
  "default_pinned_models": "montaigne",
4
- "ui": {
5
- "enable_signup": true,
6
- "ENABLE_LOGIN_FORM": true
7
- },
8
  "permissions": {
9
  "workspace": {
10
  "models": false,
 
1
  {
2
  "default_models": "montaigne",
3
  "default_pinned_models": "montaigne",
 
 
 
 
4
  "permissions": {
5
  "workspace": {
6
  "models": false,
docker-entrypoint.sh CHANGED
@@ -1,11 +1,6 @@
1
  #!/bin/bash
2
  set -e
3
 
4
- export WEBUI_AUTH=true
5
- export ENABLE_FORWARD_USER_INFO_HEADERS=true
6
- export ENABLE_LOGIN_FORM=true
7
- export ENABLE_SIGNUP=true
8
-
9
  SUGGESTIONS_FILE="/app/montaigne-config/prompt_suggestions.json"
10
  POLICY_FILE="/app/montaigne-config/ui_policy.json"
11
  MINIMAL_UI_PATCH_FILE="/app/montaigne-config/minimal_ui_patch.js"
@@ -54,9 +49,6 @@ def merge_config(config: dict, suggestions: list, policy: dict) -> dict:
54
  ui["prompt_suggestions"] = suggestions
55
  config["ui"] = ui
56
 
57
- if "ui" in policy:
58
- deep_update(ui, policy["ui"])
59
-
60
  # Policy fields
61
  if "default_models" in policy:
62
  config["default_models"] = policy["default_models"]
 
1
  #!/bin/bash
2
  set -e
3
 
 
 
 
 
 
4
  SUGGESTIONS_FILE="/app/montaigne-config/prompt_suggestions.json"
5
  POLICY_FILE="/app/montaigne-config/ui_policy.json"
6
  MINIMAL_UI_PATCH_FILE="/app/montaigne-config/minimal_ui_patch.js"
 
49
  ui["prompt_suggestions"] = suggestions
50
  config["ui"] = ui
51
 
 
 
 
52
  # Policy fields
53
  if "default_models" in policy:
54
  config["default_models"] = policy["default_models"]