@flowget/ai-chat 0.1.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,473 @@
1
+ /**
2
+ * @flowget/ai-chat styles — self-contained, host-themeable.
3
+ *
4
+ * Every color / spacing / typography value reads a `--flowget-*` design token
5
+ * with a **sensible built-in fallback**, so the chat renders correctly on its
6
+ * own ("import the stylesheet once") and automatically inherits a host's theme
7
+ * (light/dark) wherever the host defines those tokens. Two package-owned knobs
8
+ * tune placement without touching the token contract:
9
+ * --fg-aichat-z — stacking order of the launcher + panel (200)
10
+ * --fg-aichat-launcher-offset — gap from the bottom-right corner (24px)
11
+ *
12
+ * See the README "Theming" section for the full overridable token list.
13
+ */
14
+
15
+ /* ── launcher (floating trigger, bottom-right) ─────────────────────── */
16
+ .fg-aichat-anchor {
17
+ position: fixed;
18
+ right: var(--fg-aichat-launcher-offset, 24px);
19
+ bottom: var(--fg-aichat-launcher-offset, 24px);
20
+ z-index: var(--fg-aichat-z, 200);
21
+ }
22
+ .fg-aichat-launcher {
23
+ display: grid;
24
+ place-items: center;
25
+ width: 48px;
26
+ height: 48px;
27
+ border: none;
28
+ border-radius: 50%;
29
+ background: var(--flowget-color-accent, #6366f1);
30
+ color: var(--flowget-color-text-inverse, #ffffff);
31
+ cursor: pointer;
32
+ box-shadow: var(--flowget-shadow-lg, 0 12px 32px -8px rgba(15, 23, 42, 0.28));
33
+ transition: transform var(--flowget-motion-fast, 140ms) ease,
34
+ box-shadow var(--flowget-motion-fast, 140ms) ease;
35
+ }
36
+ .fg-aichat-launcher:hover {
37
+ transform: translateY(-1px);
38
+ box-shadow: 0 10px 30px -8px color-mix(in srgb, var(--flowget-color-accent, #6366f1) 60%, transparent);
39
+ }
40
+ /* Both icons share one grid cell; the Radix [data-state] swaps them. */
41
+ .fg-aichat-launcher__icon {
42
+ grid-area: 1 / 1;
43
+ transition: opacity var(--flowget-motion-fast, 140ms) ease,
44
+ transform var(--flowget-motion-fast, 140ms) ease;
45
+ }
46
+ .fg-aichat-launcher[data-state="open"] .fg-aichat-launcher__icon--open,
47
+ .fg-aichat-launcher[data-state="closed"] .fg-aichat-launcher__icon--close {
48
+ opacity: 0;
49
+ transform: scale(0.4) rotate(-90deg);
50
+ }
51
+ .fg-aichat-launcher[data-state="closed"] .fg-aichat-launcher__icon--open,
52
+ .fg-aichat-launcher[data-state="open"] .fg-aichat-launcher__icon--close {
53
+ opacity: 1;
54
+ transform: none;
55
+ }
56
+
57
+ /* ── floating panel (Radix Popover content, portaled to body) ─────── */
58
+ .fg-aichat-panel {
59
+ z-index: calc(var(--fg-aichat-z, 200) - 1);
60
+ display: flex;
61
+ flex-direction: column;
62
+ width: min(400px, 94vw);
63
+ height: min(620px, 78vh);
64
+ background: var(--flowget-color-bg-elevated, #ffffff);
65
+ border: 1px solid var(--flowget-color-border, #e2e8f0);
66
+ border-radius: var(--flowget-radius-lg, 14px);
67
+ box-shadow: var(--flowget-shadow-lg, 0 12px 32px -8px rgba(15, 23, 42, 0.28));
68
+ overflow: hidden;
69
+ transform-origin: bottom right;
70
+ }
71
+ .fg-aichat-panel[data-state="open"] {
72
+ animation: fg-aichat-panel-in 140ms ease-out;
73
+ }
74
+ .fg-aichat-panel[data-state="closed"] {
75
+ animation: fg-aichat-panel-out 100ms ease-in;
76
+ }
77
+ @keyframes fg-aichat-panel-in {
78
+ from {
79
+ opacity: 0;
80
+ transform: translateY(8px) scale(0.98);
81
+ }
82
+ to {
83
+ opacity: 1;
84
+ transform: none;
85
+ }
86
+ }
87
+ @keyframes fg-aichat-panel-out {
88
+ from {
89
+ opacity: 1;
90
+ }
91
+ to {
92
+ opacity: 0;
93
+ transform: translateY(8px) scale(0.98);
94
+ }
95
+ }
96
+
97
+ /* header */
98
+ .fg-aichat-dock__head {
99
+ display: flex;
100
+ align-items: center;
101
+ justify-content: space-between;
102
+ gap: 12px;
103
+ padding: 14px 14px 14px 16px;
104
+ border-bottom: 1px solid var(--flowget-color-border, #e2e8f0);
105
+ }
106
+ .fg-aichat-dock__brand {
107
+ display: flex;
108
+ align-items: center;
109
+ gap: 10px;
110
+ min-width: 0;
111
+ }
112
+ .fg-aichat-dock__mark {
113
+ display: grid;
114
+ place-items: center;
115
+ width: 30px;
116
+ height: 30px;
117
+ border-radius: 9px;
118
+ color: var(--flowget-color-accent, #6366f1);
119
+ background: color-mix(in srgb, var(--flowget-color-accent, #6366f1) 14%, transparent);
120
+ }
121
+ .fg-aichat-dock__title {
122
+ font-size: var(--flowget-font-size-sm, 13px);
123
+ font-weight: 600;
124
+ line-height: 1.2;
125
+ }
126
+ .fg-aichat-dock__subtitle {
127
+ font-size: var(--flowget-font-size-xs, 11px);
128
+ color: var(--flowget-color-text-subtle, #64748b);
129
+ line-height: 1.3;
130
+ }
131
+
132
+ .fg-aichat-newchat {
133
+ display: inline-flex;
134
+ align-items: center;
135
+ gap: 6px;
136
+ height: 32px;
137
+ padding: 0 10px;
138
+ border: 1px solid var(--flowget-color-border, #e2e8f0);
139
+ border-radius: var(--flowget-radius-md, 9px);
140
+ background: transparent;
141
+ color: var(--flowget-color-text-subtle, #64748b);
142
+ font-family: var(--flowget-font-sans, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif);
143
+ font-size: var(--flowget-font-size-xs, 11px);
144
+ font-weight: 500;
145
+ cursor: pointer;
146
+ transition: color var(--flowget-motion-fast, 140ms) ease,
147
+ border-color var(--flowget-motion-fast, 140ms) ease,
148
+ background var(--flowget-motion-fast, 140ms) ease;
149
+ }
150
+ .fg-aichat-newchat:hover {
151
+ color: var(--flowget-color-text, #0f172a);
152
+ border-color: var(--flowget-color-border-strong, #cbd5e1);
153
+ background: var(--flowget-color-surface-strong, #f8fafc);
154
+ }
155
+
156
+ /* ── thinking indicator + errors ───────────────────────────── */
157
+ .fg-aichat-thinking {
158
+ display: inline-flex;
159
+ align-items: center;
160
+ gap: 7px;
161
+ padding: 4px 2px;
162
+ color: var(--flowget-color-text-subtle, #64748b);
163
+ font-size: var(--flowget-font-size-sm, 13px);
164
+ }
165
+ .fg-aichat-thinking__dots {
166
+ display: inline-flex;
167
+ align-items: center;
168
+ gap: 4px;
169
+ }
170
+ .fg-aichat-thinking__dots span {
171
+ width: 5px;
172
+ height: 5px;
173
+ border-radius: 50%;
174
+ background: currentColor;
175
+ animation: fg-aichat-blink 1.2s infinite ease-in-out both;
176
+ }
177
+ .fg-aichat-thinking__dots span:nth-child(2) {
178
+ animation-delay: 0.18s;
179
+ }
180
+ .fg-aichat-thinking__dots span:nth-child(3) {
181
+ animation-delay: 0.36s;
182
+ }
183
+ @keyframes fg-aichat-blink {
184
+ 0%,
185
+ 80%,
186
+ 100% {
187
+ opacity: 0.25;
188
+ }
189
+ 40% {
190
+ opacity: 1;
191
+ }
192
+ }
193
+
194
+ .fg-aichat-error {
195
+ margin-top: 6px;
196
+ padding: 8px 10px;
197
+ border-radius: var(--flowget-radius-md, 9px);
198
+ border: 1px solid color-mix(in srgb, var(--flowget-color-danger, #dc2626) 45%, transparent);
199
+ background: color-mix(in srgb, var(--flowget-color-danger, #dc2626) 10%, transparent);
200
+ color: var(--flowget-color-danger, #dc2626);
201
+ font-size: var(--flowget-font-size-sm, 13px);
202
+ line-height: 1.45;
203
+ }
204
+
205
+ /* ── thread ────────────────────────────────────────────────── */
206
+ .fg-aichat-thread {
207
+ display: flex;
208
+ flex-direction: column;
209
+ flex: 1 1 auto;
210
+ min-height: 0;
211
+ }
212
+ .fg-aichat-thread__viewport {
213
+ flex: 1 1 auto;
214
+ min-height: 0;
215
+ overflow-y: auto;
216
+ padding: 18px;
217
+ display: flex;
218
+ flex-direction: column;
219
+ gap: 14px;
220
+ }
221
+
222
+ /* empty state */
223
+ .fg-aichat-empty {
224
+ margin: auto 0;
225
+ display: flex;
226
+ flex-direction: column;
227
+ align-items: center;
228
+ text-align: center;
229
+ padding: 8px 4px;
230
+ }
231
+ .fg-aichat-empty__mark {
232
+ display: grid;
233
+ place-items: center;
234
+ width: 48px;
235
+ height: 48px;
236
+ border-radius: 14px;
237
+ color: var(--flowget-color-accent, #6366f1);
238
+ background: color-mix(in srgb, var(--flowget-color-accent, #6366f1) 12%, transparent);
239
+ margin-bottom: 14px;
240
+ }
241
+ .fg-aichat-empty__title {
242
+ margin: 0 0 6px;
243
+ font-size: var(--flowget-font-size-md, 15px);
244
+ font-weight: 600;
245
+ }
246
+ .fg-aichat-empty__hint {
247
+ margin: 0 0 16px;
248
+ max-width: 30ch;
249
+ font-size: var(--flowget-font-size-sm, 13px);
250
+ line-height: 1.5;
251
+ color: var(--flowget-color-text-subtle, #64748b);
252
+ }
253
+ .fg-aichat-empty__examples {
254
+ display: flex;
255
+ flex-direction: column;
256
+ gap: 8px;
257
+ width: 100%;
258
+ }
259
+ .fg-aichat-chip {
260
+ width: 100%;
261
+ text-align: left;
262
+ padding: 9px 12px;
263
+ border: 1px solid var(--flowget-color-border, #e2e8f0);
264
+ border-radius: var(--flowget-radius-md, 9px);
265
+ background: var(--flowget-color-bg, #ffffff);
266
+ color: var(--flowget-color-text, #0f172a);
267
+ font-family: var(--flowget-font-sans, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif);
268
+ font-size: var(--flowget-font-size-sm, 13px);
269
+ cursor: pointer;
270
+ transition: border-color var(--flowget-motion-fast, 140ms) ease,
271
+ background var(--flowget-motion-fast, 140ms) ease;
272
+ }
273
+ .fg-aichat-chip:hover {
274
+ border-color: color-mix(in srgb, var(--flowget-color-accent, #6366f1) 55%, transparent);
275
+ background: color-mix(in srgb, var(--flowget-color-accent, #6366f1) 7%, transparent);
276
+ }
277
+
278
+ /* ── messages ──────────────────────────────────────────────── */
279
+ .fg-aichat-msg--user {
280
+ display: flex;
281
+ justify-content: flex-end;
282
+ }
283
+ .fg-aichat-msg--user .fg-aichat-msg__bubble {
284
+ max-width: 86%;
285
+ padding: 9px 13px;
286
+ border-radius: 16px 16px 4px 16px;
287
+ background: var(--flowget-color-accent, #6366f1);
288
+ color: var(--flowget-color-text-inverse, #ffffff);
289
+ font-size: var(--flowget-font-size-sm, 13px);
290
+ line-height: 1.5;
291
+ white-space: pre-wrap;
292
+ word-break: break-word;
293
+ }
294
+ .fg-aichat-msg--assistant .fg-aichat-msg__body {
295
+ font-size: var(--flowget-font-size-sm, 13px);
296
+ line-height: 1.55;
297
+ color: var(--flowget-color-text, #0f172a);
298
+ white-space: pre-wrap;
299
+ word-break: break-word;
300
+ }
301
+
302
+ /* ── proposal card ─────────────────────────────────────────── */
303
+ .fg-aichat-card {
304
+ border: 1px solid var(--flowget-color-border, #e2e8f0);
305
+ border-radius: var(--flowget-radius-lg, 14px);
306
+ background: var(--flowget-color-surface-strong, #f8fafc);
307
+ padding: 14px;
308
+ }
309
+ .fg-aichat-card--drafting {
310
+ color: var(--flowget-color-text-subtle, #64748b);
311
+ font-size: var(--flowget-font-size-sm, 13px);
312
+ }
313
+ .fg-aichat-card__label {
314
+ font-size: var(--flowget-font-size-xs, 11px);
315
+ font-weight: 600;
316
+ text-transform: uppercase;
317
+ letter-spacing: 0.6px;
318
+ color: var(--flowget-color-accent, #6366f1);
319
+ margin-bottom: 6px;
320
+ }
321
+ .fg-aichat-card__summary {
322
+ margin: 0;
323
+ font-size: var(--flowget-font-size-sm, 13px);
324
+ line-height: 1.5;
325
+ color: var(--flowget-color-text, #0f172a);
326
+ }
327
+ .fg-aichat-card__meta {
328
+ margin-top: 6px;
329
+ font-family: var(--flowget-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace);
330
+ font-size: var(--flowget-font-size-xs, 11px);
331
+ color: var(--flowget-color-text-subtle, #64748b);
332
+ }
333
+ .fg-aichat-card__actions {
334
+ display: flex;
335
+ justify-content: flex-end;
336
+ gap: 8px;
337
+ margin-top: 14px;
338
+ }
339
+
340
+ /* applied confirmation — calm success: green check badge + summary */
341
+ .fg-aichat-applied {
342
+ display: flex;
343
+ align-items: center;
344
+ gap: 9px;
345
+ padding: 9px 11px;
346
+ border-radius: var(--flowget-radius-md, 9px);
347
+ border: 1px solid color-mix(in srgb, var(--flowget-color-success, #16a34a) 28%, transparent);
348
+ background: color-mix(in srgb, var(--flowget-color-success, #16a34a) 8%, var(--flowget-color-surface-strong, #f8fafc));
349
+ }
350
+ .fg-aichat-applied__badge {
351
+ display: grid;
352
+ place-items: center;
353
+ width: 20px;
354
+ height: 20px;
355
+ flex: 0 0 auto;
356
+ border-radius: 50%;
357
+ background: var(--flowget-color-success, #16a34a);
358
+ color: var(--flowget-color-text-inverse, #ffffff);
359
+ }
360
+ .fg-aichat-applied__summary {
361
+ margin: 0;
362
+ font-size: var(--flowget-font-size-sm, 13px);
363
+ line-height: 1.4;
364
+ color: var(--flowget-color-text, #0f172a);
365
+ }
366
+
367
+ /* dismissed — muted */
368
+ .fg-aichat-dismissed {
369
+ display: flex;
370
+ align-items: center;
371
+ justify-content: space-between;
372
+ gap: 10px;
373
+ padding: 9px 11px;
374
+ border-radius: var(--flowget-radius-md, 9px);
375
+ border: 1px solid var(--flowget-color-border, #e2e8f0);
376
+ opacity: 0.7;
377
+ }
378
+ .fg-aichat-dismissed__summary {
379
+ margin: 0;
380
+ font-size: var(--flowget-font-size-sm, 13px);
381
+ line-height: 1.4;
382
+ color: var(--flowget-color-text-subtle, #64748b);
383
+ }
384
+ .fg-aichat-dismissed__tag {
385
+ flex: 0 0 auto;
386
+ font-size: var(--flowget-font-size-xs, 11px);
387
+ color: var(--flowget-color-text-subtle, #64748b);
388
+ }
389
+
390
+ /* buttons */
391
+ .fg-aichat-btn {
392
+ font-family: var(--flowget-font-sans, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif);
393
+ font-size: var(--flowget-font-size-sm, 13px);
394
+ font-weight: 500;
395
+ padding: 7px 14px;
396
+ border-radius: var(--flowget-radius-md, 9px);
397
+ border: 1px solid transparent;
398
+ cursor: pointer;
399
+ transition: background var(--flowget-motion-fast, 140ms) ease,
400
+ border-color var(--flowget-motion-fast, 140ms) ease, opacity var(--flowget-motion-fast, 140ms) ease;
401
+ }
402
+ .fg-aichat-btn:disabled {
403
+ opacity: 0.55;
404
+ cursor: default;
405
+ }
406
+ .fg-aichat-btn--primary {
407
+ background: var(--flowget-color-accent, #6366f1);
408
+ color: var(--flowget-color-text-inverse, #ffffff);
409
+ }
410
+ .fg-aichat-btn--primary:hover:not(:disabled) {
411
+ background: color-mix(in srgb, var(--flowget-color-accent, #6366f1) 88%, #fff);
412
+ }
413
+ .fg-aichat-btn--ghost {
414
+ background: transparent;
415
+ border-color: var(--flowget-color-border, #e2e8f0);
416
+ color: var(--flowget-color-text-subtle, #64748b);
417
+ }
418
+ .fg-aichat-btn--ghost:hover:not(:disabled) {
419
+ color: var(--flowget-color-text, #0f172a);
420
+ border-color: var(--flowget-color-border-strong, #cbd5e1);
421
+ }
422
+
423
+ /* ── composer ──────────────────────────────────────────────── */
424
+ .fg-aichat-composer {
425
+ padding: 12px 14px 14px;
426
+ border-top: 1px solid var(--flowget-color-border, #e2e8f0);
427
+ }
428
+ .fg-aichat-composer__field {
429
+ display: flex;
430
+ align-items: flex-end;
431
+ gap: 8px;
432
+ padding: 5px 5px 5px 14px;
433
+ border: 1px solid var(--flowget-color-border, #e2e8f0);
434
+ border-radius: 22px;
435
+ background: var(--flowget-color-bg, #ffffff);
436
+ transition: border-color var(--flowget-motion-fast, 140ms) ease;
437
+ }
438
+ .fg-aichat-composer__field:focus-within {
439
+ border-color: color-mix(in srgb, var(--flowget-color-accent, #6366f1) 60%, transparent);
440
+ }
441
+ .fg-aichat-composer__input {
442
+ flex: 1 1 auto;
443
+ border: none;
444
+ outline: none;
445
+ resize: none;
446
+ max-height: 120px;
447
+ padding: 7px 0;
448
+ background: transparent;
449
+ color: var(--flowget-color-text, #0f172a);
450
+ font-family: var(--flowget-font-sans, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif);
451
+ font-size: var(--flowget-font-size-sm, 13px);
452
+ line-height: 1.4;
453
+ }
454
+ .fg-aichat-send {
455
+ display: grid;
456
+ place-items: center;
457
+ width: 34px;
458
+ height: 34px;
459
+ flex: 0 0 auto;
460
+ border: none;
461
+ border-radius: 50%;
462
+ background: var(--flowget-color-accent, #6366f1);
463
+ color: var(--flowget-color-text-inverse, #ffffff);
464
+ cursor: pointer;
465
+ transition: background var(--flowget-motion-fast, 140ms) ease, opacity var(--flowget-motion-fast, 140ms) ease;
466
+ }
467
+ .fg-aichat-send:hover {
468
+ background: color-mix(in srgb, var(--flowget-color-accent, #6366f1) 88%, #fff);
469
+ }
470
+ .fg-aichat-send--stop {
471
+ background: var(--flowget-color-surface-strong, #f8fafc);
472
+ color: var(--flowget-color-text, #0f172a);
473
+ }
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@flowget/ai-chat",
3
+ "version": "0.1.0",
4
+ "description": "Builder-agnostic AI workflow-authoring chat for Flowget — an assistant-ui chat panel (./react) + an SSE BFF helper (./server) over @flowget/ai's streaming author(). Bring your own builder via the currentGraph/applyGraph seam.",
5
+ "keywords": [
6
+ "flowget",
7
+ "workflow",
8
+ "workflow-automation",
9
+ "ai",
10
+ "assistant-ui",
11
+ "chat",
12
+ "authoring",
13
+ "react",
14
+ "sse"
15
+ ],
16
+ "homepage": "https://github.com/flowgethq/ai-chat#readme",
17
+ "bugs": "https://github.com/flowgethq/ai-chat/issues",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/flowgethq/ai-chat.git"
21
+ },
22
+ "license": "FSL-1.1-ALv2",
23
+ "type": "module",
24
+ "main": "./dist/react.cjs",
25
+ "module": "./dist/react.js",
26
+ "types": "./dist/react.d.ts",
27
+ "exports": {
28
+ "./react": {
29
+ "types": "./dist/react.d.ts",
30
+ "import": "./dist/react.js",
31
+ "require": "./dist/react.cjs"
32
+ },
33
+ "./server": {
34
+ "types": "./dist/server.d.ts",
35
+ "import": "./dist/server.js",
36
+ "require": "./dist/server.cjs"
37
+ },
38
+ "./styles.css": "./dist/styles.css",
39
+ "./package.json": "./package.json"
40
+ },
41
+ "sideEffects": [
42
+ "**/*.css"
43
+ ],
44
+ "files": [
45
+ "dist",
46
+ "CHANGELOG.md",
47
+ "LICENSE",
48
+ "README.md"
49
+ ],
50
+ "engines": {
51
+ "node": ">=18"
52
+ },
53
+ "scripts": {
54
+ "build": "tsup",
55
+ "dev": "tsup --watch",
56
+ "typecheck": "tsc --noEmit",
57
+ "lint": "eslint src",
58
+ "test": "vitest run",
59
+ "prepack": "npm run build"
60
+ },
61
+ "peerDependencies": {
62
+ "@assistant-ui/react": "^0.14.26",
63
+ "@flowget/ai": ">=0.1.0 <1.0.0",
64
+ "react": "^18.3.0 || ^19.0.0",
65
+ "react-dom": "^18.3.0 || ^19.0.0"
66
+ },
67
+ "peerDependenciesMeta": {
68
+ "@flowget/ai": {
69
+ "optional": true
70
+ }
71
+ },
72
+ "devDependencies": {
73
+ "@assistant-ui/react": "^0.14.26",
74
+ "@eslint/js": "^9.39.4",
75
+ "@flowget/ai": "^0.1.0",
76
+ "@types/node": "^22.19.21",
77
+ "@types/react": "^19.2.17",
78
+ "@types/react-dom": "^19.2.3",
79
+ "eslint": "^9.39.4",
80
+ "react": "^19.2.7",
81
+ "react-dom": "^19.2.7",
82
+ "tsup": "^8.5.1",
83
+ "typescript": "^5.9.3",
84
+ "typescript-eslint": "^8.61.0",
85
+ "vitest": "^2.1.9"
86
+ },
87
+ "publishConfig": {
88
+ "access": "public",
89
+ "registry": "https://registry.npmjs.org"
90
+ }
91
+ }