epsimo-agent 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.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/SKILL.md +85 -0
  3. package/assets/example_asset.txt +24 -0
  4. package/epsimo/__init__.py +3 -0
  5. package/epsimo/__main__.py +4 -0
  6. package/epsimo/auth.py +143 -0
  7. package/epsimo/cli.py +586 -0
  8. package/epsimo/client.py +53 -0
  9. package/epsimo/resources/assistants.py +47 -0
  10. package/epsimo/resources/credits.py +16 -0
  11. package/epsimo/resources/db.py +31 -0
  12. package/epsimo/resources/files.py +39 -0
  13. package/epsimo/resources/projects.py +30 -0
  14. package/epsimo/resources/threads.py +83 -0
  15. package/epsimo/templates/components/AuthModal/AuthModal.module.css +39 -0
  16. package/epsimo/templates/components/AuthModal/AuthModal.tsx +138 -0
  17. package/epsimo/templates/components/BuyCredits/BuyCreditsModal.module.css +96 -0
  18. package/epsimo/templates/components/BuyCredits/BuyCreditsModal.tsx +132 -0
  19. package/epsimo/templates/components/BuyCredits/CreditsDisplay.tsx +101 -0
  20. package/epsimo/templates/components/ThreadChat/ThreadChat.module.css +551 -0
  21. package/epsimo/templates/components/ThreadChat/ThreadChat.tsx +862 -0
  22. package/epsimo/templates/components/ThreadChat/components/ToolRenderers.module.css +509 -0
  23. package/epsimo/templates/components/ThreadChat/components/ToolRenderers.tsx +322 -0
  24. package/epsimo/templates/next-mvp/app/globals.css.tmpl +20 -0
  25. package/epsimo/templates/next-mvp/app/layout.tsx.tmpl +22 -0
  26. package/epsimo/templates/next-mvp/app/page.module.css.tmpl +84 -0
  27. package/epsimo/templates/next-mvp/app/page.tsx.tmpl +43 -0
  28. package/epsimo/templates/next-mvp/epsimo.yaml.tmpl +12 -0
  29. package/epsimo/templates/next-mvp/package.json.tmpl +26 -0
  30. package/epsimo/tools/library.yaml +51 -0
  31. package/package.json +27 -0
  32. package/references/api_reference.md +34 -0
  33. package/references/virtual_db_guide.md +57 -0
  34. package/requirements.txt +2 -0
  35. package/scripts/assistant.py +165 -0
  36. package/scripts/auth.py +195 -0
  37. package/scripts/credits.py +107 -0
  38. package/scripts/debug_run.py +41 -0
  39. package/scripts/example.py +19 -0
  40. package/scripts/files.py +73 -0
  41. package/scripts/find_thread.py +55 -0
  42. package/scripts/project.py +60 -0
  43. package/scripts/run.py +75 -0
  44. package/scripts/test_all_skills.py +387 -0
  45. package/scripts/test_sdk.py +83 -0
  46. package/scripts/test_streaming.py +167 -0
  47. package/scripts/test_vdb.py +65 -0
  48. package/scripts/thread.py +77 -0
  49. package/scripts/verify_skill.py +87 -0
@@ -0,0 +1,101 @@
1
+ "use client";
2
+
3
+ import React, { useState } from 'react';
4
+ import { useAuth } from '@/contexts/AuthContext';
5
+ import { BuyCreditsModal } from './BuyCreditsModal';
6
+
7
+ interface CreditsDisplayProps {
8
+ className?: string;
9
+ variant?: 'simple' | 'full';
10
+ }
11
+
12
+ export const CreditsDisplay: React.FC<CreditsDisplayProps> = ({
13
+ className,
14
+ variant = 'simple'
15
+ }) => {
16
+ const { user, isLoading } = useAuth();
17
+ const [isModalOpen, setIsModalOpen] = useState(false);
18
+
19
+ if (isLoading || !user || user.thread_count === undefined || user.max_thread_count === undefined) {
20
+ return null; // Or a skeleton loader
21
+ }
22
+
23
+ const percentage = Math.min(100, Math.max(0, (user.thread_count / user.max_thread_count) * 100));
24
+ const isLow = user.max_thread_count - user.thread_count < 10 || percentage > 90;
25
+ const isCritical = user.thread_count >= user.max_thread_count;
26
+
27
+ return (
28
+ <>
29
+ <div
30
+ className={className}
31
+ style={{
32
+ padding: '6px 12px',
33
+ background: 'var(--background-surface-base)',
34
+ border: '1px solid var(--border-color)',
35
+ borderRadius: '20px',
36
+ fontSize: '0.8rem',
37
+ color: 'var(--text-secondary)',
38
+ display: 'flex',
39
+ alignItems: 'center',
40
+ gap: '8px',
41
+ cursor: 'pointer',
42
+ transition: 'all 0.2s ease'
43
+ }}
44
+ onClick={() => setIsModalOpen(true)}
45
+ title="Click to buy more threads"
46
+ >
47
+ <div style={{ position: 'relative', width: '16px', height: '16px' }}>
48
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ color: isCritical ? '#ef4444' : isLow ? '#f59e0b' : '#10b981' }}>
49
+ <circle cx="12" cy="12" r="10"></circle>
50
+ <path d="M12 2v20"></path>
51
+ <path d="M2 12h20"></path>
52
+ </svg>
53
+ </div>
54
+
55
+ {variant === 'full' ? (
56
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '2px' }}>
57
+ <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '0.75rem' }}>
58
+ <span>Threads Used</span>
59
+ <span style={{ fontWeight: 600, color: isCritical ? '#ef4444' : 'inherit' }}>
60
+ {user.thread_count} / {user.max_thread_count}
61
+ </span>
62
+ </div>
63
+ <div style={{ width: '100px', height: '4px', background: 'var(--border-color)', borderRadius: '2px', overflow: 'hidden' }}>
64
+ <div style={{
65
+ width: `${percentage}%`,
66
+ height: '100%',
67
+ background: isCritical ? '#ef4444' : isLow ? '#f59e0b' : '#10b981',
68
+ transition: 'width 0.3s ease'
69
+ }}></div>
70
+ </div>
71
+ </div>
72
+ ) : (
73
+ <>
74
+ <span style={{
75
+ width: '8px',
76
+ height: '8px',
77
+ borderRadius: '50%',
78
+ background: isCritical ? '#ef4444' : isLow ? '#f59e0b' : '#10b981',
79
+ display: 'none' // Replaced by icon
80
+ }}></span>
81
+ Threads: <strong style={{ color: isCritical ? '#ef4444' : 'inherit' }}>{user.thread_count}</strong> / {user.max_thread_count}
82
+ <span style={{
83
+ marginLeft: '4px',
84
+ fontSize: '0.7rem',
85
+ background: 'var(--color-primary)',
86
+ color: 'white',
87
+ padding: '1px 6px',
88
+ borderRadius: '8px',
89
+ opacity: 0.8
90
+ }}>+</span>
91
+ </>
92
+ )}
93
+ </div>
94
+
95
+ <BuyCreditsModal
96
+ isOpen={isModalOpen}
97
+ onClose={() => setIsModalOpen(false)}
98
+ />
99
+ </>
100
+ );
101
+ };
@@ -0,0 +1,551 @@
1
+ .chatContainer {
2
+ display: flex;
3
+ flex-direction: column;
4
+ height: 100%;
5
+ width: 100%;
6
+ background-color: var(--background-surface);
7
+ overflow: hidden;
8
+ position: relative;
9
+ }
10
+
11
+ .chatHeader {
12
+ display: flex;
13
+ align-items: center;
14
+ padding: var(--spacing-4) var(--spacing-6);
15
+ background-color: rgba(24, 27, 33, 0.8);
16
+ backdrop-filter: blur(8px);
17
+ border-bottom: 1px solid var(--border-color);
18
+ gap: var(--spacing-4);
19
+ z-index: 10;
20
+ }
21
+
22
+ .backBtn {
23
+ display: flex;
24
+ align-items: center;
25
+ gap: var(--spacing-2);
26
+ color: var(--text-secondary);
27
+ font-size: 0.875rem;
28
+ font-weight: 500;
29
+ transition: color 0.2s ease;
30
+ }
31
+
32
+ .backBtn:hover {
33
+ color: var(--color-primary);
34
+ }
35
+
36
+ .threadTitle {
37
+ font-size: 1rem;
38
+ font-weight: 600;
39
+ color: var(--text-primary);
40
+ flex: 1;
41
+ text-align: center;
42
+ /* Offset to center title */
43
+ }
44
+
45
+ .messageList {
46
+ flex: 1;
47
+ overflow-y: auto;
48
+ padding: var(--spacing-8) var(--spacing-6);
49
+ display: flex;
50
+ flex-direction: column;
51
+ gap: var(--spacing-8);
52
+ background-color: var(--background-base);
53
+ }
54
+
55
+ .messageWrapper {
56
+ display: flex;
57
+ gap: var(--spacing-4);
58
+ max-width: 85%;
59
+ animation: slideUp 0.4s cubic-bezier(0.16, 1, 0.3, 1);
60
+ }
61
+
62
+ @keyframes slideUp {
63
+ from {
64
+ opacity: 0;
65
+ transform: translateY(20px);
66
+ }
67
+
68
+ to {
69
+ opacity: 1;
70
+ transform: translateY(0);
71
+ }
72
+ }
73
+
74
+ .userWrapper {
75
+ align-self: flex-end;
76
+ flex-direction: row-reverse;
77
+ }
78
+
79
+ .assistantWrapper {
80
+ align-self: flex-start;
81
+ }
82
+
83
+ .avatar {
84
+ width: 36px;
85
+ height: 36px;
86
+ border-radius: var(--radius-md);
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: center;
90
+ font-size: 0.75rem;
91
+ font-weight: 600;
92
+ flex-shrink: 0;
93
+ box-shadow: var(--shadow-sm);
94
+ }
95
+
96
+ .userAvatar {
97
+ background: var(--color-primary);
98
+ color: white;
99
+ }
100
+
101
+ .assistantAvatar {
102
+ background: var(--background-surface-hover);
103
+ color: var(--color-primary);
104
+ border: 1px solid var(--border-color);
105
+ }
106
+
107
+ .messageBubble {
108
+ padding: var(--spacing-4) var(--spacing-5);
109
+ border-radius: var(--radius-lg);
110
+ font-size: 0.9375rem;
111
+ line-height: 1.6;
112
+ position: relative;
113
+ max-width: fit-content;
114
+ }
115
+
116
+ /* User Message - Primary color background, white text */
117
+ .userWrapper .messageBubble {
118
+ background-color: var(--color-primary);
119
+ color: #ffffff;
120
+ border-top-right-radius: 4px;
121
+ box-shadow: var(--shadow-md);
122
+ }
123
+
124
+ /* Assistant Message - Glassy dark background, white text */
125
+ .assistantWrapper .messageBubble {
126
+ background-color: var(--background-surface);
127
+ color: var(--text-primary);
128
+ border: 1px solid var(--border-color);
129
+ border-top-left-radius: 4px;
130
+ box-shadow: var(--shadow-sm);
131
+ padding: var(--spacing-4) var(--spacing-6);
132
+ min-width: 60px;
133
+ position: relative;
134
+ padding-right: var(--spacing-8);
135
+ /* Room for copy button */
136
+ }
137
+
138
+ /* Markdown Content Styling */
139
+ .markdownContent {
140
+ font-size: 0.9375rem;
141
+ line-height: 1.6;
142
+ }
143
+
144
+ .markdownContent p {
145
+ margin-bottom: var(--spacing-3);
146
+ }
147
+
148
+ .markdownContent p:last-child {
149
+ margin-bottom: 0;
150
+ }
151
+
152
+ .markdownContent h1,
153
+ .markdownContent h2,
154
+ .markdownContent h3 {
155
+ margin-top: var(--spacing-4);
156
+ margin-bottom: var(--spacing-2);
157
+ color: var(--text-primary);
158
+ }
159
+
160
+ .markdownContent ul,
161
+ .markdownContent ol {
162
+ margin-left: var(--spacing-6);
163
+ margin-bottom: var(--spacing-3);
164
+ }
165
+
166
+ .markdownContent li {
167
+ margin-bottom: var(--spacing-1);
168
+ }
169
+
170
+ .markdownContent code:not(pre code) {
171
+ background-color: var(--background-surface-hover);
172
+ padding: 0.2rem 0.4rem;
173
+ border-radius: 4px;
174
+ font-family: 'Monaco', 'Consolas', monospace;
175
+ font-size: 0.85rem;
176
+ color: var(--color-primary);
177
+ }
178
+
179
+ .markdownContent pre {
180
+ margin: var(--spacing-4) 0;
181
+ border-radius: 12px;
182
+ overflow: hidden;
183
+ background-color: #1a1b26 !important;
184
+ /* VS Code Tokyo Night like background */
185
+ }
186
+
187
+ .markdownContent table {
188
+ width: 100%;
189
+ border-collapse: collapse;
190
+ margin-bottom: var(--spacing-4);
191
+ font-size: 0.875rem;
192
+ }
193
+
194
+ .markdownContent th,
195
+ .markdownContent td {
196
+ padding: var(--spacing-2) var(--spacing-3);
197
+ border: 1px solid var(--border-color);
198
+ text-align: left;
199
+ }
200
+
201
+ .markdownContent th {
202
+ background-color: var(--background-surface-hover);
203
+ font-weight: 600;
204
+ }
205
+
206
+ .markdownContent blockquote {
207
+ border-left: 4px solid var(--color-primary);
208
+ padding-left: var(--spacing-4);
209
+ margin-left: 0;
210
+ color: var(--text-secondary);
211
+ font-style: italic;
212
+ margin-bottom: var(--spacing-3);
213
+ }
214
+
215
+ .typingBubble {
216
+ display: flex;
217
+ gap: 4px;
218
+ padding: 16px 20px !important;
219
+ align-items: center;
220
+ min-width: 60px;
221
+ }
222
+
223
+ .toolIndicator {
224
+ display: flex;
225
+ align-items: center;
226
+ gap: var(--spacing-3);
227
+ padding: var(--spacing-3) var(--spacing-4);
228
+ background-color: var(--background-surface);
229
+ border: 1px solid var(--border-color);
230
+ border-radius: var(--radius-md);
231
+ color: var(--text-secondary);
232
+ font-size: 0.875rem;
233
+ animation: slideUp 0.3s ease-out;
234
+ margin-left: 50px;
235
+ /* Indent to align with assistant avatar */
236
+ margin-bottom: var(--spacing-4);
237
+ width: fit-content;
238
+ }
239
+
240
+ .toolSpinner {
241
+ width: 16px;
242
+ height: 16px;
243
+ border: 2px solid var(--border-color);
244
+ border-top: 2px solid var(--color-primary);
245
+ border-radius: 50%;
246
+ animation: spin 1s linear infinite;
247
+ }
248
+
249
+ .toolText {
250
+ font-weight: 500;
251
+ }
252
+
253
+ .copyBtn {
254
+ position: absolute;
255
+ top: 8px;
256
+ right: 8px;
257
+ padding: 4px;
258
+ border-radius: var(--radius-sm);
259
+ color: var(--text-tertiary);
260
+ background: transparent;
261
+ border: none;
262
+ cursor: pointer;
263
+ opacity: 0;
264
+ transition: all 0.2s ease;
265
+ }
266
+
267
+ .messageBubble:hover .copyBtn {
268
+ opacity: 1;
269
+ }
270
+
271
+ .copyBtn:hover {
272
+ background: var(--background-surface-hover);
273
+ color: var(--color-primary);
274
+ }
275
+
276
+ .inputArea {
277
+ padding: var(--spacing-6);
278
+ background-color: var(--background-surface);
279
+ border-top: 1px solid var(--border-color);
280
+ display: flex;
281
+ justify-content: center;
282
+ z-index: 20;
283
+ }
284
+
285
+ .inputContainer {
286
+ width: 100%;
287
+ max-width: 800px;
288
+ background-color: var(--background-base);
289
+ padding: 6px;
290
+ border-radius: var(--radius-full);
291
+ display: flex;
292
+ gap: 8px;
293
+ border: 1px solid var(--border-color);
294
+ transition: all 0.3s ease;
295
+ }
296
+
297
+ .inputContainer:focus-within {
298
+ border-color: var(--color-primary);
299
+ box-shadow: var(--shadow-glow);
300
+ }
301
+
302
+ .chatInput {
303
+ flex: 1;
304
+ background: transparent !important;
305
+ border: none !important;
306
+ padding: 10px 20px !important;
307
+ color: var(--text-primary) !important;
308
+ font-size: 0.95rem !important;
309
+ }
310
+
311
+ .chatInput:focus {
312
+ box-shadow: none !important;
313
+ outline: none !important;
314
+ }
315
+
316
+ .sendBtn {
317
+ width: 40px;
318
+ height: 40px;
319
+ border-radius: var(--radius-full) !important;
320
+ padding: 0 !important;
321
+ display: flex;
322
+ align-items: center;
323
+ justify-content: center;
324
+ background-color: var(--color-primary) !important;
325
+ color: white !important;
326
+ }
327
+
328
+ .sendBtn:hover:not(:disabled) {
329
+ background-color: var(--color-primary-hover) !important;
330
+ }
331
+
332
+ .fileBtn {
333
+ width: 40px;
334
+ height: 40px;
335
+ border-radius: var(--radius-full) !important;
336
+ padding: 0 !important;
337
+ display: flex;
338
+ align-items: center;
339
+ justify-content: center;
340
+ background-color: var(--background-surface) !important;
341
+ color: var(--text-secondary) !important;
342
+ border: 1px solid var(--border-color) !important;
343
+ transition: all 0.2s ease;
344
+ }
345
+
346
+ .fileBtn:hover:not(:disabled) {
347
+ background-color: var(--background-surface-hover) !important;
348
+ color: var(--color-primary) !important;
349
+ border-color: var(--color-primary) !important;
350
+ }
351
+
352
+ .fileBtn:disabled {
353
+ opacity: 0.5;
354
+ cursor: not-allowed;
355
+ }
356
+
357
+ .uploadSpinner {
358
+ width: 16px;
359
+ height: 16px;
360
+ border: 2px solid var(--border-color);
361
+ border-top: 2px solid var(--color-primary);
362
+ border-radius: 50%;
363
+ animation: spin 1s linear infinite;
364
+ }
365
+
366
+ .uploadError {
367
+ margin-bottom: var(--spacing-3);
368
+ padding: var(--spacing-3) var(--spacing-4);
369
+ background-color: rgba(220, 38, 38, 0.1);
370
+ border: 1px solid rgba(220, 38, 38, 0.2);
371
+ border-radius: var(--radius-md);
372
+ display: flex;
373
+ align-items: center;
374
+ justify-content: space-between;
375
+ gap: var(--spacing-3);
376
+ color: #ef4444;
377
+ font-size: 0.875rem;
378
+ animation: slideDown 0.3s cubic-bezier(0.16, 1, 0.3, 1);
379
+ }
380
+
381
+ .uploadError .errorIcon {
382
+ font-size: 1rem;
383
+ margin: 0;
384
+ }
385
+
386
+ .errorClose {
387
+ background: transparent;
388
+ border: none;
389
+ color: inherit;
390
+ font-size: 1.25rem;
391
+ cursor: pointer;
392
+ padding: 0;
393
+ width: 20px;
394
+ height: 20px;
395
+ display: flex;
396
+ align-items: center;
397
+ justify-content: center;
398
+ border-radius: var(--radius-sm);
399
+ transition: background-color 0.2s ease;
400
+ }
401
+
402
+ .errorClose:hover {
403
+ background-color: rgba(220, 38, 38, 0.1);
404
+ }
405
+
406
+ .loading,
407
+ .emptyState {
408
+ display: flex;
409
+ flex-direction: column;
410
+ align-items: center;
411
+ justify-content: center;
412
+ height: 100%;
413
+ gap: var(--spacing-4);
414
+ color: var(--text-secondary);
415
+ }
416
+
417
+ .spinner {
418
+ width: 32px;
419
+ height: 32px;
420
+ border: 3px solid var(--border-color);
421
+ border-top: 3px solid var(--color-primary);
422
+ border-radius: 50%;
423
+ animation: spin 1s linear infinite;
424
+ }
425
+
426
+ .emptyIcon {
427
+ font-size: 3rem;
428
+ margin-bottom: var(--spacing-2);
429
+ }
430
+
431
+ .typingDot {
432
+ width: 6px;
433
+ height: 6px;
434
+ background-color: var(--text-secondary);
435
+ border-radius: 50%;
436
+ animation: bounce 1.4s infinite ease-in-out both;
437
+ }
438
+
439
+ .typingDot:nth-child(1) {
440
+ animation-delay: -0.32s;
441
+ }
442
+
443
+ .typingDot:nth-child(2) {
444
+ animation-delay: -0.16s;
445
+ }
446
+
447
+ @keyframes bounce {
448
+
449
+ 0%,
450
+ 80%,
451
+ 100% {
452
+ transform: scale(0);
453
+ opacity: 0.3;
454
+ }
455
+
456
+ 40% {
457
+ transform: scale(1);
458
+ opacity: 1;
459
+ }
460
+ }
461
+
462
+ @keyframes spin {
463
+ to {
464
+ transform: rotate(360deg);
465
+ }
466
+ }
467
+
468
+ @keyframes slideUp {
469
+ from {
470
+ opacity: 0;
471
+ transform: translateY(10px);
472
+ }
473
+
474
+ to {
475
+ opacity: 1;
476
+ transform: translateY(0);
477
+ }
478
+ }
479
+
480
+ .errorState {
481
+ display: flex;
482
+ flex-direction: column;
483
+ align-items: center;
484
+ justify-content: center;
485
+ height: 100%;
486
+ gap: var(--spacing-4);
487
+ color: var(--text-secondary);
488
+ text-align: center;
489
+ padding: var(--spacing-6);
490
+ }
491
+
492
+ .errorIcon {
493
+ font-size: 3rem;
494
+ margin-bottom: var(--spacing-2);
495
+ }
496
+
497
+ .retryBtn {
498
+ margin-top: var(--spacing-4);
499
+ background-color: var(--color-primary);
500
+ color: #fff;
501
+ }
502
+
503
+ .errorBanner {
504
+ margin: var(--spacing-4);
505
+ margin-bottom: var(--spacing-6);
506
+ padding: var(--spacing-3) var(--spacing-4);
507
+ background-color: rgba(220, 38, 38, 0.1);
508
+ border: 1px solid rgba(220, 38, 38, 0.2);
509
+ border-radius: var(--radius-md);
510
+ display: flex;
511
+ align-items: center;
512
+ justify-content: space-between;
513
+ gap: var(--spacing-4);
514
+ color: #ef4444;
515
+ font-size: 0.875rem;
516
+ animation: slideDown 0.3s cubic-bezier(0.16, 1, 0.3, 1);
517
+ }
518
+
519
+ .errorContent {
520
+ display: flex;
521
+ align-items: center;
522
+ gap: var(--spacing-3);
523
+ }
524
+
525
+ .errorRetry {
526
+ background: transparent;
527
+ border: 1px solid currentColor;
528
+ color: inherit;
529
+ padding: 4px 12px;
530
+ border-radius: var(--radius-sm);
531
+ font-size: 0.75rem;
532
+ font-weight: 600;
533
+ cursor: pointer;
534
+ transition: all 0.2s ease;
535
+ }
536
+
537
+ .errorRetry:hover {
538
+ background-color: rgba(220, 38, 38, 0.1);
539
+ }
540
+
541
+ @keyframes slideDown {
542
+ from {
543
+ opacity: 0;
544
+ transform: translateY(-10px);
545
+ }
546
+
547
+ to {
548
+ opacity: 1;
549
+ transform: translateY(0);
550
+ }
551
+ }