relmio 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,154 @@
1
+ .assistant-wizard .safety-note {
2
+ grid-template-columns: 1.75rem minmax(0, 1fr);
3
+ column-gap: 0.75rem;
4
+ font-size: 0.875rem;
5
+ }
6
+
7
+ .assistant-wizard .safety-note::before {
8
+ grid-column: 1;
9
+ grid-row: 1 / span 2;
10
+ }
11
+
12
+ .assistant-wizard .safety-note > strong,
13
+ .assistant-wizard .safety-note > span {
14
+ grid-column: 2;
15
+ min-width: 0;
16
+ overflow-wrap: anywhere;
17
+ }
18
+
19
+ .assistant-wizard .safety-note > strong {
20
+ grid-row: 1;
21
+ line-height: 1.35;
22
+ }
23
+
24
+ .assistant-wizard .safety-note > span {
25
+ grid-row: 2;
26
+ line-height: 1.45;
27
+ }
28
+
29
+ .assistant-warning {
30
+ background: color-mix(in srgb, var(--warning, #c78515) 12%, var(--surface));
31
+ border: 1px solid color-mix(in srgb, var(--warning, #c78515) 42%, var(--border));
32
+ border-radius: var(--radius-md);
33
+ margin: 1rem 0;
34
+ padding: 1rem;
35
+ }
36
+
37
+ .assistant-warning p,
38
+ .assistant-note {
39
+ margin: 0.35rem 0 0;
40
+ }
41
+
42
+ .instance-ai-guidance {
43
+ margin: 0.25rem 0;
44
+ }
45
+
46
+ .instance-ai-guidance > p {
47
+ max-width: 68ch;
48
+ }
49
+
50
+ .prerequisite-steps {
51
+ display: grid;
52
+ gap: 0.4rem;
53
+ margin: 0.75rem 0 0;
54
+ padding-left: 1.25rem;
55
+ color: var(--text-muted);
56
+ }
57
+
58
+ .prerequisite-boundary {
59
+ margin-top: 0.75rem;
60
+ padding-top: 0.75rem;
61
+ border-top: 1px solid color-mix(in srgb, var(--warning, #c78515) 32%, var(--border));
62
+ }
63
+
64
+ .prerequisite-boundary summary {
65
+ cursor: pointer;
66
+ font-weight: 700;
67
+ }
68
+
69
+ .action-hint {
70
+ max-width: 34rem;
71
+ margin: 0 auto 0 0;
72
+ color: var(--text-muted);
73
+ font-size: 0.875rem;
74
+ }
75
+
76
+ .assistant-note {
77
+ position: relative;
78
+ padding: 0.75rem 0.875rem 0.75rem 2.25rem;
79
+ border: 1px solid var(--border);
80
+ border-radius: var(--radius-sm);
81
+ color: var(--text-muted);
82
+ background: var(--surface-muted);
83
+ line-height: 1.45;
84
+ }
85
+
86
+ .assistant-note::before {
87
+ position: absolute;
88
+ top: 1.05rem;
89
+ left: 0.9rem;
90
+ width: 0.55rem;
91
+ height: 0.55rem;
92
+ border-radius: 50%;
93
+ background: var(--border-strong);
94
+ content: "";
95
+ }
96
+
97
+ .assistant-note[data-status="enabled"] {
98
+ border-color: var(--accent-border);
99
+ color: var(--accent-copy);
100
+ background: var(--accent-soft);
101
+ }
102
+
103
+ .assistant-note[data-status="enabled"]::before {
104
+ background: var(--success);
105
+ }
106
+
107
+ .assistant-note[data-status="configured"],
108
+ .assistant-note[data-status="missing"] {
109
+ border-color: var(--warning-border);
110
+ color: var(--warning);
111
+ background: var(--warning-soft);
112
+ }
113
+
114
+ .assistant-note[data-status="configured"]::before,
115
+ .assistant-note[data-status="missing"]::before {
116
+ background: var(--warning);
117
+ }
118
+
119
+ .assistant-disclosure {
120
+ border-top: 1px solid var(--border);
121
+ margin-top: 1rem;
122
+ padding-top: 1rem;
123
+ }
124
+
125
+ .assistant-disclosure summary {
126
+ color: var(--text);
127
+ cursor: pointer;
128
+ font-weight: 700;
129
+ }
130
+
131
+ @media (max-width: 60rem),
132
+ (min-width: 961px) and (max-height: 768px) {
133
+ .assistant-wizard .steps ol {
134
+ grid-template-columns: repeat(4, minmax(0, 1fr));
135
+ }
136
+ }
137
+
138
+ @media (max-width: 40rem) {
139
+ .assistant-wizard .safety-note {
140
+ padding: 0.75rem;
141
+ }
142
+
143
+ .assistant-wizard .actions {
144
+ align-items: stretch;
145
+ }
146
+
147
+ .assistant-wizard .action-hint {
148
+ width: 100%;
149
+ }
150
+
151
+ .assistant-wizard .actions .button {
152
+ width: 100%;
153
+ }
154
+ }
@@ -0,0 +1,351 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <meta
7
+ name="description"
8
+ content="Install an isolated n8n AI Assistant sandbox and optional SearXNG companion services."
9
+ />
10
+ <title>Relmio | n8n AI Assistant</title>
11
+ <link rel="icon" href="/relmio-icon-rounded.svg" type="image/svg+xml" />
12
+ <link rel="stylesheet" href="/styles.css" />
13
+ <link rel="stylesheet" href="/assistant.css" />
14
+ <script src="/theme.js" type="module"></script>
15
+ <script src="/assistant.js" type="module"></script>
16
+ </head>
17
+ <body class="assistant-wizard" data-current-step="1">
18
+ <a class="skip-link" href="#main-content">Skip to AI Assistant setup</a>
19
+
20
+ <header class="site-header">
21
+ <div class="brand">
22
+ <img class="brand-mark" src="/relmio-icon.png" alt="" width="28" height="28" />
23
+ <span>Relmio</span>
24
+ </div>
25
+ <fieldset class="theme-picker">
26
+ <legend class="visually-hidden">Color theme</legend>
27
+ <label title="Use system appearance">
28
+ <input type="radio" name="color-theme" value="system" checked />
29
+ <span class="theme-icon theme-icon-system" aria-hidden="true"></span>
30
+ <span class="visually-hidden">System</span>
31
+ </label>
32
+ <label title="Use light appearance">
33
+ <input type="radio" name="color-theme" value="light" />
34
+ <span class="theme-icon theme-icon-light" aria-hidden="true"></span>
35
+ <span class="visually-hidden">Light</span>
36
+ </label>
37
+ <label title="Use dark appearance">
38
+ <input type="radio" name="color-theme" value="dark" />
39
+ <span class="theme-icon theme-icon-dark" aria-hidden="true"></span>
40
+ <span class="visually-hidden">Dark</span>
41
+ </label>
42
+ </fieldset>
43
+ </header>
44
+
45
+ <main id="main-content" class="shell" tabindex="-1">
46
+ <aside class="rail" aria-label="AI Assistant setup progress and safety">
47
+ <section class="intro" aria-labelledby="page-title">
48
+ <h1 id="page-title">n8n AI Assistant companion</h1>
49
+ <p class="lede">
50
+ Add an isolated sandbox and optional private SearXNG search service
51
+ without changing the existing n8n project.
52
+ </p>
53
+ </section>
54
+
55
+ <nav class="steps" aria-label="AI Assistant setup progress">
56
+ <ol>
57
+ <li data-step-marker="1" aria-current="step"><span>1</span><em>Connect</em></li>
58
+ <li data-step-marker="2"><span>2</span><em>Select n8n</em></li>
59
+ <li data-step-marker="3"><span>3</span><em>Review</em></li>
60
+ <li data-step-marker="4"><span>4</span><em>Ready</em></li>
61
+ </ol>
62
+ </nav>
63
+
64
+ <div class="toast-stack" aria-label="AI Assistant safety notices">
65
+ <aside class="toast safety-note">
66
+ <strong>Existing n8n stays untouched</strong>
67
+ <span>
68
+ No n8n Compose edit, rebuild, restart, recreate, exec, host
69
+ port, or proxy route.
70
+ </span>
71
+ </aside>
72
+ <aside class="toast safety-note backup-note">
73
+ <strong>Credential boundary</strong>
74
+ <span>
75
+ ChatGPT/Codex subscription sign-in is not an OpenAI Platform API
76
+ key. Relmio does not offer it as the compliant model provider.
77
+ </span>
78
+ </aside>
79
+ <div id="global-message" class="toast message" role="status" aria-live="polite">
80
+ <span id="global-message-text">Review the self-hosted sandbox boundary.</span>
81
+ </div>
82
+ <div id="global-error" class="toast error" role="alert" tabindex="-1" hidden>
83
+ <span id="global-error-text"></span>
84
+ </div>
85
+ </div>
86
+ </aside>
87
+
88
+ <section class="panel" data-step="1" aria-labelledby="vps-title">
89
+ <div class="panel-heading">
90
+ <h2 id="vps-title" tabindex="-1">Confirm the privileged sandbox boundary</h2>
91
+ <p>
92
+ AI Assistant is Preview. Workflows it generates require human review
93
+ before use, especially in production.
94
+ </p>
95
+ </div>
96
+
97
+ <aside class="assistant-warning" aria-label="Privileged runner warning">
98
+ <strong>Advanced/local-test only</strong>
99
+ <p>
100
+ The self-hosted runner uses privileged Docker-in-Docker and should be
101
+ treated as equivalent to host root. n8n recommends Daytona for
102
+ production sandboxing.
103
+ </p>
104
+ </aside>
105
+
106
+ <form id="vps-form">
107
+ <div class="field-grid">
108
+ <label class="field">
109
+ <span>VPS address</span>
110
+ <input id="host" name="host" inputmode="url" autocomplete="off" required />
111
+ <small>Use the hostname or IP exactly as your provider shows it.</small>
112
+ </label>
113
+ <label class="field compact">
114
+ <span>SSH port</span>
115
+ <input id="port" name="port" type="number" min="1" max="65535" value="22" required />
116
+ </label>
117
+ <label class="field compact">
118
+ <span>Username</span>
119
+ <input id="username" name="username" autocomplete="username" value="root" required />
120
+ </label>
121
+ <label class="field">
122
+ <span>VPS password</span>
123
+ <input id="password" name="password" type="password" autocomplete="current-password" disabled required />
124
+ <small>Used only for this verified SSH connection and never saved.</small>
125
+ </label>
126
+ </div>
127
+
128
+ <button id="fingerprint-button" class="button secondary" type="button">Check server identity</button>
129
+ <div id="fingerprint-box" class="fingerprint" hidden>
130
+ <span>SSH fingerprint</span>
131
+ <code id="fingerprint-value"></code>
132
+ <label class="check-row">
133
+ <input id="fingerprint-confirm" type="checkbox" />
134
+ <span>I checked this fingerprint and this is the intended VPS.</span>
135
+ </label>
136
+ </div>
137
+
138
+ <label class="check-row approval">
139
+ <input id="privileged-confirm" type="checkbox" />
140
+ <span>
141
+ I understand the runner is privileged Docker-in-Docker and this
142
+ path is for advanced local testing, not the production-recommended
143
+ Daytona sandbox.
144
+ </span>
145
+ </label>
146
+
147
+ <div class="actions">
148
+ <button id="connect-button" class="button primary" type="submit" disabled>
149
+ Connect and inspect Docker
150
+ </button>
151
+ </div>
152
+ </form>
153
+ </section>
154
+
155
+ <section class="panel" data-step="2" aria-labelledby="n8n-title" hidden>
156
+ <div class="panel-heading">
157
+ <h2 id="n8n-title" tabindex="-1">Choose the detected n8n network</h2>
158
+ <p>Discovery uses read-only Docker commands. It never executes inside n8n.</p>
159
+ </div>
160
+ <div class="version-strip" aria-label="Detected Docker versions">
161
+ <span>Docker <strong id="docker-version">Not detected</strong></span>
162
+ <span>Compose <strong id="compose-version">Not detected</strong></span>
163
+ </div>
164
+ <div class="field-grid single">
165
+ <label class="field">
166
+ <span>Running n8n container</span>
167
+ <select id="container-select"></select>
168
+ </label>
169
+ <label class="field">
170
+ <span>Existing shared Docker network</span>
171
+ <select id="network-select"></select>
172
+ <small>Only the sandbox API attaches with its private alias unless you opt in to web search.</small>
173
+ </label>
174
+ <p id="instance-ai-status" class="assistant-note" role="status">
175
+ Checking whether this n8n container enables the AI Assistant module.
176
+ </p>
177
+ <aside
178
+ id="instance-ai-guidance"
179
+ class="assistant-warning instance-ai-guidance"
180
+ aria-labelledby="instance-ai-guidance-title"
181
+ >
182
+ <strong id="instance-ai-guidance-title">Required n8n prerequisite</strong>
183
+ <p>
184
+ The existing n8n service must have
185
+ <code>N8N_ENABLED_MODULES=instance-ai</code> applied before Relmio
186
+ can continue. If it is already configured without
187
+ <code>instance-ai</code>, append <code>instance-ai</code> as a
188
+ distinct comma-delimited token while preserving existing module
189
+ entries; do not replace unknown existing values.
190
+ </p>
191
+ <ol class="prerequisite-steps">
192
+ <li>Use your existing Hostinger/deployment workflow to update the n8n service.</li>
193
+ <li>Redeploy or restart n8n, then verify that it is healthy.</li>
194
+ <li>Reconnect to Relmio and run discovery again.</li>
195
+ </ol>
196
+ <details class="prerequisite-boundary">
197
+ <summary>Why Relmio cannot apply this change</summary>
198
+ <p>
199
+ Relmio reports only this allowlisted status and never displays
200
+ the raw environment value. It will not edit the existing n8n Compose
201
+ file, image, or environment; restart or recreate n8n;
202
+ or exec into n8n.
203
+ </p>
204
+ </details>
205
+ </aside>
206
+ <label class="check-row">
207
+ <input id="include-searxng" type="checkbox" />
208
+ <span>
209
+ <strong>Optional SearXNG JSON web search</strong>
210
+ <small>Off by default. Select it only if you want a private Docker-internal web-search service for n8n’s AI Assistant.</small>
211
+ </span>
212
+ </label>
213
+ </div>
214
+ <div class="actions">
215
+ <p id="review-readiness" class="action-hint" role="status">
216
+ Relmio must verify <code>instance-ai</code> before a plan can be reviewed.
217
+ </p>
218
+ <button
219
+ id="review-button"
220
+ class="button primary"
221
+ type="button"
222
+ aria-describedby="review-readiness"
223
+ disabled
224
+ >
225
+ Review exact plan
226
+ </button>
227
+ </div>
228
+ </section>
229
+
230
+ <section class="panel" data-step="3" aria-labelledby="review-title" hidden>
231
+ <div class="panel-heading">
232
+ <h2 id="review-title" tabindex="-1">Review before installing</h2>
233
+ <p>The remote deployment starts only after this exact confirmation.</p>
234
+ </div>
235
+ <div class="review-grid">
236
+ <section aria-labelledby="will-title">
237
+ <h3 id="will-title">The wizard will</h3>
238
+ <ul class="check-list">
239
+ <li>Create <code>/docker/n8n-openai-oauth/assistant-sandbox</code></li>
240
+ <li>Start only the managed AI Assistant companion project</li>
241
+ <li>Attach sandbox API to <strong id="review-network">Not selected</strong></li>
242
+ <li id="review-instance-ai">AI Assistant prerequisite has not been reviewed</li>
243
+ <li id="review-web-search">Web search selection has not been reviewed</li>
244
+ <li>Generate separate 256-bit sandbox, runner, and private SearXNG secrets</li>
245
+ <li>Check sandbox health, expected services, and no published host port</li>
246
+ </ul>
247
+ </section>
248
+ <section aria-labelledby="wont-title">
249
+ <h3 id="wont-title">The wizard will not</h3>
250
+ <ul class="no-list">
251
+ <li>Edit, rebuild, stop, restart, recreate, or exec into n8n</li>
252
+ <li>Upload your OpenAI Platform API key or ChatGPT/Codex OAuth</li>
253
+ <li>Publish sandbox, runner, or SearXNG ports to the VPS host</li>
254
+ <li>Enable a model provider or change n8n settings automatically</li>
255
+ </ul>
256
+ </section>
257
+ </div>
258
+ <label class="check-row approval">
259
+ <input id="install-confirm" type="checkbox" />
260
+ <span>
261
+ I approve this privileged, self-hosted AI Assistant companion and
262
+ understand that AI Assistant is Preview and workflows require human review.
263
+ </span>
264
+ </label>
265
+ <div class="actions">
266
+ <button id="install-button" class="button primary" type="button" disabled>
267
+ Install the companion
268
+ </button>
269
+ </div>
270
+ </section>
271
+
272
+ <section class="panel success-panel" data-step="4" aria-labelledby="ready-title" hidden>
273
+ <div class="success-heading">
274
+ <div class="success-mark" aria-hidden="true">✓</div>
275
+ <div class="panel-heading">
276
+ <h2 id="ready-title" tabindex="-1">AI Assistant companion is ready</h2>
277
+ <p>URLs are stable generated result values; the sandbox key is shown only in this result view.</p>
278
+ </div>
279
+ </div>
280
+
281
+ <aside class="assistant-warning">
282
+ <strong>Preview with human review</strong>
283
+ <p>Review every generated workflow before activation. For production sandboxing, use Daytona as n8n recommends.</p>
284
+ </aside>
285
+
286
+ <h3>1. Sandbox dialog</h3>
287
+ <dl class="result-list">
288
+ <div><dt>Sandbox Service URL</dt><dd><code id="sandbox-url">Not installed</code></dd></div>
289
+ <div><dt>Sandbox API key</dt><dd><code id="sandbox-api-key">Shown after installation</code></dd></div>
290
+ </dl>
291
+
292
+ <h3>2. Web search dialog</h3>
293
+ <dl class="result-list">
294
+ <div><dt>SearXNG Instance URL</dt><dd><code id="searxng-url">Web search disabled</code></dd></div>
295
+ </dl>
296
+ <p id="searxng-note" class="assistant-note">Web search was disabled, so no SearXNG service or settings file was installed. Its retained private secret is never user-facing.</p>
297
+
298
+ <h3>3. Model route</h3>
299
+ <dl class="result-list">
300
+ <div><dt>Model provider</dt><dd><code>OpenAI</code></dd></div>
301
+ <div><dt>Model</dt><dd><code>Keep the current supported selection</code></dd></div>
302
+ </dl>
303
+ <p>
304
+ Enter your user-owned OpenAI Platform API key directly in n8n. Relmio
305
+ does not read, receive, or store that model key.
306
+ </p>
307
+ <p>
308
+ Keep your existing supported n8n model selection—including
309
+ <code>openai/gpt-5.6-sol</code>—while n8n continues to accept it.
310
+ Change models only if n8n rejects the current selection or you
311
+ deliberately choose another supported model.
312
+ </p>
313
+
314
+ <h3>Platform account guardrails</h3>
315
+ <aside class="assistant-warning">
316
+ <strong>No setup can guarantee an account is never flagged.</strong>
317
+ <p>
318
+ Use a dedicated OpenAI Platform project/key, store it server-side in
319
+ n8n, set project rate/spend limits and alerts, monitor usage, grant
320
+ least user access, rotate or revoke credentials as needed, require
321
+ human review, and never expose this provider path publicly.
322
+ </p>
323
+ <p>
324
+ Relmio cannot inject per-user safety identifiers or moderation into
325
+ n8n’s direct provider path.
326
+ </p>
327
+ </aside>
328
+
329
+ <details class="assistant-disclosure">
330
+ <summary>Optional Ollama-style custom endpoint</summary>
331
+ <p>
332
+ n8n’s custom/self-hosted OpenAI-compatible screen defaults to an
333
+ Ollama-style endpoint. Use this only for a separately deployed,
334
+ n8n-reachable Relmio OpenAI-compatible endpoint backed by your own
335
+ OpenAI Platform API key. This companion wizard does not create one.
336
+ </p>
337
+ <dl class="result-list">
338
+ <div><dt>Base URL</dt><dd><code>your Platform-key-backed Relmio /v1 endpoint</code></dd></div>
339
+ <div><dt>API key</dt><dd>Use that endpoint’s private Relmio client credential. It is not an OpenAI-issued API key.</dd></div>
340
+ <div><dt>Model ID</dt><dd>Use a model ID exposed by that Platform-key-backed endpoint.</dd></div>
341
+ </dl>
342
+ <p>
343
+ The existing ChatGPT/Codex OAuth VPS sidecar can be technically
344
+ compatible, but remains experimental/private/policy-uncertain. It
345
+ is not auto-selected, enabled, or presented as TOS-approved.
346
+ </p>
347
+ </details>
348
+ </section>
349
+ </main>
350
+ </body>
351
+ </html>