relmio 0.2.6 → 0.2.8

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/src/ui/index.html CHANGED
@@ -5,501 +5,456 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <meta
7
7
  name="description"
8
- content="Relmio verifies a self-hosted n8n VPS and installs a separate private OpenAI-compatible sidecar only after review."
8
+ content="Relmio connects compatible AI clients to a private ChatGPT/Codex OAuth sidecar, starting with self-hosted n8n."
9
9
  />
10
- <title>Relmio | Private n8n setup</title>
10
+ <title>Relmio | n8n Setup</title>
11
11
  <link
12
12
  rel="icon"
13
13
  href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cpath fill='%23137c74' d='M7 8h19l31 24H41L26 20v10L7 17Z'/%3E%3Cpath fill='%2312211f' d='M7 47l19-13v10l15-12h16L26 56H7Z'/%3E%3C/svg%3E"
14
14
  />
15
15
  <link rel="stylesheet" href="/styles.css" />
16
+ <script src="/theme.js" type="module"></script>
16
17
  <script src="/app.js" type="module"></script>
17
18
  </head>
18
19
  <body>
19
- <!--
20
- THESIS: Relmio makes an invisible relay legible as a verified route, refusing the generic setup card and progress bar.
21
- OWN-WORLD: Warm paper surfaces, midnight ink, relay teal, graphite seams, and precise signal spines form a compact Patchbay Ledger.
22
- STORY: Verify the local sign-in, confirm the host, inspect n8n, review every write, then complete the private route.
23
- FIRST VIEWPORT: A persistent route rail occupies the left while one dominant gate and its current safety boundary occupy the right.
24
- FORM: Signal Spine adapted for operation, first of three approved compositions, from candidate 5 and seed c4426c7c.
25
- FINISH: unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, and DESIGN.md
26
- -->
27
- <a class="skip-link" href="#main-content">Skip to the current gate</a>
20
+ <a class="skip-link" href="#main-content">Skip to setup</a>
28
21
 
29
22
  <header class="site-header">
30
- <a class="brand" href="#main-content" aria-label="Relmio setup home">
23
+ <div class="brand">
31
24
  <svg
32
25
  class="brand-mark"
33
26
  viewBox="0 0 64 64"
34
27
  aria-hidden="true"
35
28
  focusable="false"
36
29
  >
37
- <path class="brand-signal" d="M7 8h19l31 24H41L26 20v10L7 17Z" />
38
- <path class="brand-ink" d="M7 47l19-13v10l15-12h16L26 56H7Z" />
30
+ <path fill="#137c74" d="M7 8h19l31 24H41L26 20v10L7 17Z" />
31
+ <path fill="#12211f" d="M7 47l19-13v10l15-12h16L26 56H7Z" />
39
32
  </svg>
40
33
  <span>Relmio</span>
41
- </a>
42
- <span class="local-badge">
43
- <i aria-hidden="true"></i>
44
- Runs only on this computer
45
- </span>
34
+ </div>
35
+ <div class="header-actions">
36
+ <fieldset class="theme-picker">
37
+ <legend class="visually-hidden">Color theme</legend>
38
+ <label title="Use system appearance">
39
+ <input type="radio" name="color-theme" value="system" checked />
40
+ <span class="theme-icon theme-icon-system" aria-hidden="true"></span>
41
+ <span class="visually-hidden">System</span>
42
+ </label>
43
+ <label title="Use light appearance">
44
+ <input type="radio" name="color-theme" value="light" />
45
+ <span class="theme-icon theme-icon-light" aria-hidden="true"></span>
46
+ <span class="visually-hidden">Light</span>
47
+ </label>
48
+ <label title="Use dark appearance">
49
+ <input type="radio" name="color-theme" value="dark" />
50
+ <span class="theme-icon theme-icon-dark" aria-hidden="true"></span>
51
+ <span class="visually-hidden">Dark</span>
52
+ </label>
53
+ </fieldset>
54
+ <span class="local-badge">Runs only on this computer</span>
55
+ </div>
46
56
  </header>
47
57
 
48
- <main id="main-content" class="wizard-shell">
49
- <section class="wizard-intro" aria-labelledby="page-title">
50
- <h1 id="page-title">Five gates. One private sidecar.</h1>
51
- <p>
52
- Verify each boundary in order. Relmio leaves your existing n8n
53
- deployment untouched.
58
+ <main id="main-content" class="shell">
59
+ <section class="intro" aria-labelledby="page-title">
60
+ <p class="eyebrow">Guided VPS setup</p>
61
+ <h1 id="page-title">Connect n8n without changing n8n</h1>
62
+ <p class="lede">
63
+ This wizard installs one separate Docker sidecar. Your existing n8n
64
+ image, Compose file, container, and workflows stay untouched.
54
65
  </p>
55
- <section class="intro-ledger" aria-label="Setup boundaries">
56
- <span>
57
- <strong>Back up first</strong>
58
- <small>Export your n8n workflows before connecting.</small>
59
- </span>
60
- <span>
61
- <strong>No public port</strong>
62
- <small>The sidecar stays on the private Docker network.</small>
63
- </span>
64
- <span>
65
- <strong>You approve writes</strong>
66
- <small>The exact remote plan appears before installation.</small>
67
- </span>
68
- </section>
69
66
  </section>
70
67
 
71
- <section class="wizard-layout">
72
- <aside class="route-rail" aria-labelledby="route-title">
73
- <header>
74
- <h2 id="route-title">Your private route</h2>
75
- <p>Each verified gate extends the signal to the sidecar.</p>
76
- </header>
77
-
78
- <nav class="steps" aria-label="Setup progress">
79
- <ol>
80
- <li data-step-marker="1" aria-current="step">
81
- <span class="step-index">1</span>
82
- <span class="step-copy">
83
- <strong>Sign in</strong>
84
- <small>Local credential</small>
85
- </span>
86
- </li>
87
- <li data-step-marker="2">
88
- <span class="step-index">2</span>
89
- <span class="step-copy">
90
- <strong>Verify VPS</strong>
91
- <small>SSH fingerprint</small>
92
- </span>
93
- </li>
94
- <li data-step-marker="3">
95
- <span class="step-index">3</span>
96
- <span class="step-copy">
97
- <strong>Select n8n</strong>
98
- <small>Read-only discovery</small>
99
- </span>
100
- </li>
101
- <li data-step-marker="4">
102
- <span class="step-index">4</span>
103
- <span class="step-copy">
104
- <strong>Review plan</strong>
105
- <small>Every remote write</small>
106
- </span>
107
- </li>
108
- <li data-step-marker="5">
109
- <span class="step-index">5</span>
110
- <span class="step-copy">
111
- <strong>Complete</strong>
112
- <small>Private endpoint</small>
113
- </span>
114
- </li>
115
- </ol>
116
- </nav>
117
-
118
- <section class="rail-boundary" aria-label="Current safety model">
119
- <strong>Sidecar-only guarantee</strong>
120
- <p>
121
- No n8n restart. No n8n rebuild. No host port 10531. The wizard
122
- writes only under <code>/docker/n8n-openai-oauth</code>.
123
- </p>
124
- </section>
125
- </aside>
126
-
127
- <section class="work-column" aria-label="Current setup gate">
128
- <section class="status-dock" aria-label="Wizard status">
129
- <p id="preview-badge" class="preview-badge" hidden>
130
- <strong>Sanitized preview</strong>
131
- <span>Sample data only. No live sign-in or VPS writes.</span>
132
- </p>
133
- <p id="global-message" class="message" role="status" aria-live="polite">
134
- Checking your local sign-in…
68
+ <aside class="safety-note" aria-label="Safety guarantee">
69
+ <strong>Sidecar-only guarantee</strong>
70
+ <span>
71
+ No n8n restart. No n8n rebuild. No public port. You approve the exact
72
+ plan before anything is written.
73
+ </span>
74
+ </aside>
75
+
76
+ <aside class="safety-note backup-note" aria-label="Backup reminder">
77
+ <strong>Back up first</strong>
78
+ <span>
79
+ Export your n8n workflows before connecting. This wizard uses
80
+ sidecar-only commands, but it still writes to your VPS.
81
+ </span>
82
+ </aside>
83
+
84
+ <nav class="steps" aria-label="Setup progress">
85
+ <ol>
86
+ <li data-step-marker="1" aria-current="step">
87
+ <span>1</span><em>Sign in</em>
88
+ </li>
89
+ <li data-step-marker="2"><span>2</span><em>VPS</em></li>
90
+ <li data-step-marker="3"><span>3</span><em>n8n</em></li>
91
+ <li data-step-marker="4"><span>4</span><em>Review</em></li>
92
+ <li data-step-marker="5"><span>5</span><em>Done</em></li>
93
+ </ol>
94
+ </nav>
95
+
96
+ <div id="global-message" class="message" role="status" aria-live="polite">
97
+ Checking your local sign-in…
98
+ </div>
99
+ <div id="global-error" class="error" role="alert" tabindex="-1" hidden></div>
100
+
101
+ <section class="panel" data-step="1" aria-labelledby="signin-title">
102
+ <div class="panel-heading">
103
+ <span class="step-kicker">Step 1 of 5</span>
104
+ <h2 id="signin-title" tabindex="-1">Use your local ChatGPT sign-in</h2>
105
+ <p>
106
+ The OAuth credential stays on this computer until you approve its
107
+ encrypted SSH upload to your VPS.
108
+ </p>
109
+ </div>
110
+
111
+ <div class="status-row">
112
+ <span id="auth-indicator" class="status-dot" aria-hidden="true"></span>
113
+ <div>
114
+ <strong id="auth-title">Checking…</strong>
115
+ <p id="auth-detail">Looking for your local Codex credential.</p>
116
+ <p id="auth-updated" class="credential-time" hidden>
117
+ Credential updated
118
+ <time id="auth-updated-time"></time>
119
+ (local time).
135
120
  </p>
136
- <p id="global-error" class="error" role="alert" tabindex="-1" hidden></p>
137
- </section>
121
+ </div>
122
+ </div>
123
+
124
+ <div class="actions">
125
+ <button id="login-button" class="button secondary" type="button">
126
+ Sign in with ChatGPT
127
+ </button>
128
+ <a
129
+ id="login-link"
130
+ class="button secondary"
131
+ target="_blank"
132
+ rel="noopener noreferrer"
133
+ hidden
134
+ >
135
+ Open fresh ChatGPT sign-in
136
+ </a>
137
+ <button id="signin-next" class="button primary" type="button" disabled>
138
+ Continue to VPS
139
+ </button>
140
+ </div>
141
+ </section>
138
142
 
139
- <section class="panel" data-step="1" aria-labelledby="signin-title">
140
- <header class="panel-heading">
141
- <h2 id="signin-title" tabindex="-1">Use your local ChatGPT sign-in</h2>
142
- <span>Gate 1 of 5</span>
143
- <p>
144
- The OAuth credential stays on this computer until you approve
145
- its encrypted SSH upload to your VPS.
146
- </p>
147
- </header>
148
-
149
- <section class="status-row" aria-label="Local sign-in status">
150
- <span id="auth-indicator" class="status-dot" aria-hidden="true"></span>
151
- <span>
152
- <strong id="auth-title">Checking…</strong>
153
- <p id="auth-detail">Looking for your local Codex credential.</p>
154
- <p id="auth-updated" class="credential-time" hidden>
155
- Credential updated
156
- <time id="auth-updated-time"></time>
157
- (local time).
158
- </p>
159
- </span>
160
- </section>
143
+ <section class="panel" data-step="2" aria-labelledby="vps-title" hidden>
144
+ <div class="panel-heading">
145
+ <span class="step-kicker">Step 2 of 5</span>
146
+ <h2 id="vps-title" tabindex="-1">Connect to your VPS</h2>
147
+ <p>
148
+ Copy the address exactly from Hostinger. Your password is used only
149
+ for this live SSH connection and is never saved.
150
+ </p>
151
+ </div>
152
+
153
+ <form id="vps-form">
154
+ <div class="field-grid">
155
+ <label class="field">
156
+ <span>VPS address</span>
157
+ <input
158
+ id="host"
159
+ name="host"
160
+ inputmode="url"
161
+ autocomplete="off"
162
+ placeholder="your-vps-ip-or-hostname"
163
+ required
164
+ />
165
+ <small>Use the full IP address. Do not add <code>ssh root@</code>.</small>
166
+ </label>
161
167
 
162
- <footer class="actions">
163
- <button id="login-button" class="button secondary" type="button">
164
- Sign in with ChatGPT
165
- </button>
166
- <a
167
- id="login-link"
168
- class="button secondary"
169
- target="_blank"
170
- rel="noopener noreferrer"
171
- hidden
172
- >
173
- Open fresh ChatGPT sign-in
174
- </a>
175
- <button id="signin-next" class="button primary" type="button" disabled>
176
- Continue to VPS
177
- </button>
178
- </footer>
179
- </section>
168
+ <label class="field compact">
169
+ <span>SSH port</span>
170
+ <input
171
+ id="port"
172
+ name="port"
173
+ type="number"
174
+ min="1"
175
+ max="65535"
176
+ value="22"
177
+ required
178
+ />
179
+ </label>
180
180
 
181
- <section class="panel" data-step="2" aria-labelledby="vps-title" hidden>
182
- <header class="panel-heading">
183
- <h2 id="vps-title" tabindex="-1">Verify the VPS before sending a password</h2>
184
- <span>Gate 2 of 5</span>
185
- <p>
186
- Copy the address exactly from Hostinger or your VPS provider.
187
- Your password is used only for this live SSH connection and is
188
- never saved.
189
- </p>
190
- </header>
191
-
192
- <form id="vps-form">
193
- <section class="field-grid">
194
- <label class="field">
195
- <span>VPS address</span>
196
- <input
197
- id="host"
198
- name="host"
199
- inputmode="url"
200
- autocomplete="off"
201
- placeholder="your-vps-ip-or-hostname"
202
- required
203
- />
204
- <small>Use the full IP address. Do not add <code>ssh root@</code>.</small>
205
- </label>
206
-
207
- <label class="field compact">
208
- <span>SSH port</span>
209
- <input
210
- id="port"
211
- name="port"
212
- type="number"
213
- min="1"
214
- max="65535"
215
- value="22"
216
- required
217
- />
218
- </label>
219
-
220
- <label class="field compact">
221
- <span>Username</span>
222
- <input
223
- id="username"
224
- name="username"
225
- autocomplete="username"
226
- value="root"
227
- required
228
- />
229
- <small>The guided setup currently expects the VPS root account.</small>
230
- </label>
231
-
232
- <label class="field">
233
- <span>VPS password</span>
234
- <input
235
- id="password"
236
- name="password"
237
- type="password"
238
- autocomplete="current-password"
239
- disabled
240
- required
241
- />
242
- <small>
243
- This unlocks after host confirmation, then clears as soon
244
- as the connection attempt finishes.
245
- </small>
246
- </label>
247
- </section>
248
-
249
- <button id="fingerprint-button" class="button secondary" type="button">
250
- Check server identity
251
- </button>
181
+ <label class="field compact">
182
+ <span>Username</span>
183
+ <input
184
+ id="username"
185
+ name="username"
186
+ autocomplete="username"
187
+ value="root"
188
+ required
189
+ />
190
+ <small>
191
+ The current guided setup expects the VPS root account.
192
+ </small>
193
+ </label>
252
194
 
253
- <section id="fingerprint-box" class="fingerprint" hidden>
254
- <span>SSH fingerprint</span>
255
- <code id="fingerprint-value"></code>
256
- <label class="check-row">
257
- <input id="fingerprint-confirm" type="checkbox" />
258
- <span>
259
- This is the VPS I intended to connect to. I checked the
260
- address carefully.
261
- </span>
262
- </label>
263
- </section>
264
-
265
- <footer class="actions">
266
- <button class="button ghost back-button" data-back="1" type="button">
267
- Back
268
- </button>
269
- <button id="connect-button" class="button primary" type="submit" disabled>
270
- Connect and inspect Docker
271
- </button>
272
- </footer>
273
- </form>
274
- </section>
195
+ <label class="field">
196
+ <span>VPS password</span>
197
+ <input
198
+ id="password"
199
+ name="password"
200
+ type="password"
201
+ autocomplete="current-password"
202
+ disabled
203
+ required
204
+ />
205
+ <small>
206
+ This unlocks after you confirm the server identity, then clears
207
+ immediately after connecting.
208
+ </small>
209
+ </label>
210
+ </div>
275
211
 
276
- <section class="panel" data-step="3" aria-labelledby="n8n-title" hidden>
277
- <header class="panel-heading">
278
- <h2 id="n8n-title" tabindex="-1">Choose the detected n8n route</h2>
279
- <span>Gate 3 of 5</span>
280
- <p>
281
- Discovery uses read-only Docker commands and does not execute
282
- anything inside n8n.
283
- </p>
284
- </header>
285
-
286
- <section class="version-strip" aria-label="Detected Docker versions">
287
- <span>Docker <strong id="docker-version">Pending</strong></span>
288
- <span>Compose <strong id="compose-version">Pending</strong></span>
289
- </section>
290
-
291
- <section class="field-grid single">
292
- <label class="field">
293
- <span>Running n8n container</span>
294
- <select id="container-select"></select>
295
- </label>
296
-
297
- <label class="field">
298
- <span>Shared Docker network</span>
299
- <select id="network-select"></select>
300
- <small>The sidecar joins this network. n8n itself is not changed.</small>
301
- </label>
302
- </section>
303
-
304
- <footer class="actions">
305
- <button class="button ghost back-button" data-back="2" type="button">
306
- Back
307
- </button>
308
- <button id="review-button" class="button primary" type="button">
309
- Review the exact plan
310
- </button>
311
- </footer>
312
- </section>
212
+ <button id="fingerprint-button" class="button secondary" type="button">
213
+ Check server identity
214
+ </button>
313
215
 
314
- <section class="panel" data-step="4" aria-labelledby="review-title" hidden>
315
- <header class="panel-heading">
316
- <h2 id="review-title" tabindex="-1">Review every remote write</h2>
317
- <span>Gate 4 of 5</span>
318
- <p>The VPS has not changed. Confirm the sidecar-only plan below.</p>
319
- </header>
320
-
321
- <section class="review-grid">
322
- <section aria-labelledby="will-title">
323
- <h3 id="will-title">The wizard will</h3>
324
- <ul class="check-list">
325
- <li>Create or update <code>/docker/n8n-openai-oauth</code></li>
326
- <li>Build and start only the <code>openai-oauth</code> sidecar</li>
327
- <li>Attach the sidecar to <strong id="review-network">Pending</strong></li>
328
- <li>
329
- Use the private hostname
330
- <code id="review-endpoint">n8n-openai-oauth</code>
331
- </li>
332
- <li>Upload the OAuth file with owner-only permissions</li>
333
- </ul>
334
- </section>
335
- <section aria-labelledby="wont-title">
336
- <h3 id="wont-title">The wizard will not</h3>
337
- <ul class="no-list">
338
- <li>Edit or rebuild the n8n image</li>
339
- <li>Stop, restart, or recreate n8n</li>
340
- <li>Publish port <code>10531</code></li>
341
- <li>Create a Traefik route</li>
342
- </ul>
343
- </section>
344
- </section>
345
-
346
- <label class="check-row approval">
347
- <input id="install-confirm" type="checkbox" />
216
+ <div id="fingerprint-box" class="fingerprint" hidden>
217
+ <span>SSH fingerprint</span>
218
+ <code id="fingerprint-value"></code>
219
+ <label class="check-row">
220
+ <input id="fingerprint-confirm" type="checkbox" />
348
221
  <span>
349
- I approve this sidecar-only installation and understand
350
- <code>openai-oauth</code> is an unofficial project.
222
+ This is the VPS I intended to connect to. I checked the address
223
+ carefully.
351
224
  </span>
352
225
  </label>
226
+ </div>
353
227
 
354
- <footer class="actions">
355
- <button class="button ghost back-button" data-back="3" type="button">
356
- Back
357
- </button>
358
- <button id="install-button" class="button primary" type="button" disabled>
359
- Install the sidecar
360
- </button>
361
- </footer>
362
- </section>
363
-
364
- <section class="panel success-panel" data-step="5" aria-labelledby="done-title" hidden>
365
- <svg
366
- class="success-mark"
367
- viewBox="0 0 32 32"
368
- aria-hidden="true"
369
- focusable="false"
370
- >
371
- <circle cx="16" cy="16" r="14"></circle>
372
- <path d="m9.5 16.5 4 4 9-10"></path>
373
- </svg>
374
- <header class="panel-heading">
375
- <h2 id="done-title" tabindex="-1">The private route is ready</h2>
376
- <span>Gate 5 of 5</span>
377
- <p>
378
- Copy the OpenAI credential values first, then use the node
379
- recipe that matches your n8n workflow.
380
- </p>
381
- </header>
382
-
383
- <h3>1. OpenAI credential</h3>
384
- <dl class="result-list">
385
- <div>
386
- <dt>Base URL</dt>
387
- <dd class="result-value">
388
- <code id="result-url">http://n8n-openai-oauth:10531/v1</code>
389
- <button
390
- class="button secondary copy-value"
391
- type="button"
392
- data-copy-target="result-url"
393
- data-copy-label="Base URL"
394
- aria-label="Copy Base URL"
395
- >
396
- Copy
397
- </button>
398
- </dd>
399
- </div>
400
- <div>
401
- <dt>API key</dt>
402
- <dd class="result-value">
403
- <code id="result-key">local-only</code>
404
- <button
405
- class="button secondary copy-value"
406
- type="button"
407
- data-copy-target="result-key"
408
- data-copy-label="API key"
409
- aria-label="Copy API key"
410
- >
411
- Copy
412
- </button>
413
- </dd>
414
- </div>
415
- <div>
416
- <dt>Organization ID</dt>
417
- <dd>Leave empty</dd>
418
- </div>
419
- <div>
420
- <dt>Custom header</dt>
421
- <dd><strong>Off</strong></dd>
422
- </div>
423
- </dl>
424
-
425
- <button id="copy-settings" class="button secondary" type="button">
426
- Copy credential settings
228
+ <div class="actions">
229
+ <button class="button ghost back-button" data-back="1" type="button">
230
+ Back
427
231
  </button>
232
+ <button id="connect-button" class="button primary" type="submit" disabled>
233
+ Connect and inspect Docker
234
+ </button>
235
+ </div>
236
+ </form>
237
+ </section>
428
238
 
429
- <section class="model-box">
430
- <h3>2. OpenAI Chat Model: AI Agent or Basic LLM Chain</h3>
431
- <dl class="result-list">
432
- <div>
433
- <dt>Model ID</dt>
434
- <dd class="result-value">
435
- <code id="result-model">Pending</code>
436
- <button
437
- class="button secondary copy-value"
438
- type="button"
439
- data-copy-target="result-model"
440
- data-copy-label="model ID"
441
- aria-label="Copy model ID"
442
- >
443
- Copy
444
- </button>
445
- </dd>
446
- </div>
447
- <div>
448
- <dt>Responses API</dt>
449
- <dd><strong>On</strong> for Chat Model node version 1.3</dd>
450
- </div>
451
- </dl>
452
- <p>All models detected: <span id="result-models">Pending</span></p>
453
- <p>
454
- If the Responses API switch is absent, keep the node's default
455
- Chat Completions behavior. The bridge supports that route too.
456
- </p>
457
- </section>
458
-
459
- <section class="model-box">
460
- <h3>3. HTTP Request node</h3>
461
- <dl class="result-list">
462
- <div>
463
- <dt>Method</dt>
464
- <dd><code>POST</code></dd>
465
- </div>
466
- <div>
467
- <dt>URL</dt>
468
- <dd class="result-value">
469
- <code id="result-http-url">http://n8n-openai-oauth:10531/v1/responses</code>
470
- <button
471
- class="button secondary copy-value"
472
- type="button"
473
- data-copy-target="result-http-url"
474
- data-copy-label="HTTP endpoint"
475
- aria-label="Copy HTTP endpoint"
476
- >
477
- Copy
478
- </button>
479
- </dd>
480
- </div>
481
- <div>
482
- <dt>Authentication</dt>
483
- <dd>None</dd>
484
- </div>
485
- </dl>
486
- </section>
487
-
488
- <p class="final-note">
489
- The README includes complete AI Agent, Basic LLM Chain, JSON, and
490
- importable cURL examples. Start with no built-in tools. You can
491
- now return to Terminal and press Control+C to close this local
492
- wizard; the VPS sidecar will keep running.
493
- </p>
239
+ <section class="panel" data-step="3" aria-labelledby="n8n-title" hidden>
240
+ <div class="panel-heading">
241
+ <span class="step-kicker">Step 3 of 5</span>
242
+ <h2 id="n8n-title" tabindex="-1">Choose the detected n8n</h2>
243
+ <p>
244
+ Discovery uses read-only Docker commands. It does not execute
245
+ anything inside n8n.
246
+ </p>
247
+ </div>
248
+
249
+ <div class="version-strip" aria-label="Detected Docker versions">
250
+ <span>Docker <strong id="docker-version">Not detected</strong></span>
251
+ <span>Compose <strong id="compose-version">Not detected</strong></span>
252
+ </div>
253
+
254
+ <div class="field-grid single">
255
+ <label class="field">
256
+ <span>Running n8n container</span>
257
+ <select id="container-select"></select>
258
+ </label>
259
+
260
+ <label class="field">
261
+ <span>Shared Docker network</span>
262
+ <select id="network-select"></select>
263
+ <small>The sidecar joins this network; n8n itself is not changed.</small>
264
+ </label>
265
+ </div>
266
+
267
+ <div class="actions">
268
+ <button class="button ghost back-button" data-back="2" type="button">
269
+ Back
270
+ </button>
271
+ <button id="review-button" class="button primary" type="button">
272
+ Review the exact plan
273
+ </button>
274
+ </div>
275
+ </section>
276
+
277
+ <section class="panel" data-step="4" aria-labelledby="review-title" hidden>
278
+ <div class="panel-heading">
279
+ <span class="step-kicker">Step 4 of 5</span>
280
+ <h2 id="review-title" tabindex="-1">Review before installing</h2>
281
+ <p>No existing n8n files or containers will be changed.</p>
282
+ </div>
283
+
284
+ <div class="review-grid">
285
+ <section aria-labelledby="will-title">
286
+ <h3 id="will-title">The wizard will</h3>
287
+ <ul class="check-list">
288
+ <li>Create or update <code>/docker/n8n-openai-oauth</code></li>
289
+ <li>Build and start only the <code>openai-oauth</code> sidecar</li>
290
+ <li>Attach the sidecar to <strong id="review-network">Not selected</strong></li>
291
+ <li>
292
+ Use the private hostname
293
+ <code id="review-endpoint">n8n-openai-oauth</code>
294
+ </li>
295
+ <li>Upload the OAuth file with owner-only permissions</li>
296
+ </ul>
297
+ </section>
298
+ <section aria-labelledby="wont-title">
299
+ <h3 id="wont-title">The wizard will not</h3>
300
+ <ul class="no-list">
301
+ <li>Edit or rebuild the n8n image</li>
302
+ <li>Stop, restart, or recreate n8n</li>
303
+ <li>Publish port <code>10531</code></li>
304
+ <li>Create a Traefik route</li>
305
+ </ul>
494
306
  </section>
495
- </section>
307
+ </div>
308
+
309
+ <label class="check-row approval">
310
+ <input id="install-confirm" type="checkbox" />
311
+ <span>
312
+ I approve this sidecar-only installation and understand
313
+ <code>openai-oauth</code> is an unofficial project.
314
+ </span>
315
+ </label>
316
+
317
+ <div class="actions">
318
+ <button class="button ghost back-button" data-back="3" type="button">
319
+ Back
320
+ </button>
321
+ <button id="install-button" class="button primary" type="button" disabled>
322
+ Install the sidecar
323
+ </button>
324
+ </div>
325
+ </section>
326
+
327
+ <section class="panel success-panel" data-step="5" aria-labelledby="done-title" hidden>
328
+ <div class="success-mark" aria-hidden="true">✓</div>
329
+ <div class="panel-heading">
330
+ <span class="step-kicker">Step 5 of 5</span>
331
+ <h2 id="done-title" tabindex="-1">The private bridge is ready</h2>
332
+ <p>
333
+ Copy the OpenAI credential values first, then use one of the node
334
+ recipes below.
335
+ </p>
336
+ </div>
337
+
338
+ <h3>1. OpenAI credential</h3>
339
+ <dl class="result-list">
340
+ <div>
341
+ <dt>Base URL</dt>
342
+ <dd class="result-value">
343
+ <code id="result-url">http://n8n-openai-oauth:10531/v1</code>
344
+ <button
345
+ class="button secondary copy-value"
346
+ type="button"
347
+ data-copy-target="result-url"
348
+ data-copy-label="Base URL"
349
+ aria-label="Copy Base URL"
350
+ >
351
+ Copy
352
+ </button>
353
+ </dd>
354
+ </div>
355
+ <div>
356
+ <dt>API key</dt>
357
+ <dd class="result-value">
358
+ <code id="result-key">local-only</code>
359
+ <button
360
+ class="button secondary copy-value"
361
+ type="button"
362
+ data-copy-target="result-key"
363
+ data-copy-label="API key"
364
+ aria-label="Copy API key"
365
+ >
366
+ Copy
367
+ </button>
368
+ </dd>
369
+ </div>
370
+ <div>
371
+ <dt>Organization ID</dt>
372
+ <dd>Leave empty</dd>
373
+ </div>
374
+ <div>
375
+ <dt>Custom header</dt>
376
+ <dd><strong>Off</strong></dd>
377
+ </div>
378
+ </dl>
379
+
380
+ <button id="copy-settings" class="button secondary" type="button">
381
+ Copy credential settings
382
+ </button>
383
+
384
+ <div class="model-box">
385
+ <h3>2. OpenAI Chat Model for AI Agent or Basic LLM Chain</h3>
386
+ <dl class="result-list">
387
+ <div>
388
+ <dt>Model ID</dt>
389
+ <dd class="result-value">
390
+ <code id="result-model">Not detected</code>
391
+ <button
392
+ class="button secondary copy-value"
393
+ type="button"
394
+ data-copy-target="result-model"
395
+ data-copy-label="model ID"
396
+ aria-label="Copy model ID"
397
+ >
398
+ Copy
399
+ </button>
400
+ </dd>
401
+ </div>
402
+ <div>
403
+ <dt>Responses API</dt>
404
+ <dd><strong>On</strong> for Chat Model node version 1.3</dd>
405
+ </div>
406
+ </dl>
407
+ <p>All models detected: <span id="result-models">Not detected</span></p>
408
+ <p>
409
+ If the Responses API switch is absent, keep the node's default
410
+ Chat Completions behavior; the bridge supports that route too.
411
+ </p>
412
+ </div>
413
+
414
+ <div class="model-box">
415
+ <h3>3. HTTP Request node</h3>
416
+ <dl class="result-list">
417
+ <div>
418
+ <dt>Method</dt>
419
+ <dd><code>POST</code></dd>
420
+ </div>
421
+ <div>
422
+ <dt>URL</dt>
423
+ <dd class="result-value">
424
+ <code id="result-http-url">
425
+ http://n8n-openai-oauth:10531/v1/responses
426
+ </code>
427
+ <button
428
+ class="button secondary copy-value"
429
+ type="button"
430
+ data-copy-target="result-http-url"
431
+ data-copy-label="HTTP endpoint"
432
+ aria-label="Copy HTTP endpoint"
433
+ >
434
+ Copy
435
+ </button>
436
+ </dd>
437
+ </div>
438
+ <div>
439
+ <dt>Authentication</dt>
440
+ <dd>None</dd>
441
+ </div>
442
+ </dl>
443
+ </div>
444
+
445
+ <p class="final-note">
446
+ The README includes complete AI Agent, Basic LLM Chain, JSON, and
447
+ importable cURL examples. Start with no built-in tools. You can now
448
+ return to Terminal and press Control+C to close this local wizard;
449
+ the VPS sidecar will keep running.
450
+ </p>
496
451
  </section>
497
452
  </main>
498
453
 
499
- <footer class="site-footer">
454
+ <footer>
500
455
  <p>
501
456
  Personal and experimental use only. Keep your OAuth credential private
502
- and follow OpenAI's terms and usage policies.
457
+ and follow OpenAIs terms and usage policies.
503
458
  </p>
504
459
  </footer>
505
460
  </body>