agent-hustle-demo 1.0.1

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 (60) hide show
  1. package/README.md +429 -0
  2. package/dist/HustleChat-BC9wvWVA.d.ts +90 -0
  3. package/dist/HustleChat-BcrKkkyn.d.cts +90 -0
  4. package/dist/browser/hustle-react.js +14854 -0
  5. package/dist/browser/hustle-react.js.map +1 -0
  6. package/dist/components/index.cjs +3141 -0
  7. package/dist/components/index.cjs.map +1 -0
  8. package/dist/components/index.d.cts +20 -0
  9. package/dist/components/index.d.ts +20 -0
  10. package/dist/components/index.js +3112 -0
  11. package/dist/components/index.js.map +1 -0
  12. package/dist/hooks/index.cjs +845 -0
  13. package/dist/hooks/index.cjs.map +1 -0
  14. package/dist/hooks/index.d.cts +6 -0
  15. package/dist/hooks/index.d.ts +6 -0
  16. package/dist/hooks/index.js +838 -0
  17. package/dist/hooks/index.js.map +1 -0
  18. package/dist/hustle-Kj0X8qXC.d.cts +193 -0
  19. package/dist/hustle-Kj0X8qXC.d.ts +193 -0
  20. package/dist/index-ChUsRBwL.d.ts +152 -0
  21. package/dist/index-DE1N7C3W.d.cts +152 -0
  22. package/dist/index-DuPFrMZy.d.cts +214 -0
  23. package/dist/index-kFIdHjNw.d.ts +214 -0
  24. package/dist/index.cjs +3746 -0
  25. package/dist/index.cjs.map +1 -0
  26. package/dist/index.d.cts +271 -0
  27. package/dist/index.d.ts +271 -0
  28. package/dist/index.js +3697 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/providers/index.cjs +844 -0
  31. package/dist/providers/index.cjs.map +1 -0
  32. package/dist/providers/index.d.cts +5 -0
  33. package/dist/providers/index.d.ts +5 -0
  34. package/dist/providers/index.js +838 -0
  35. package/dist/providers/index.js.map +1 -0
  36. package/package.json +80 -0
  37. package/src/components/AuthStatus.tsx +352 -0
  38. package/src/components/ConnectButton.tsx +421 -0
  39. package/src/components/HustleChat.tsx +1273 -0
  40. package/src/components/MarkdownContent.tsx +431 -0
  41. package/src/components/index.ts +15 -0
  42. package/src/hooks/index.ts +40 -0
  43. package/src/hooks/useEmblemAuth.ts +27 -0
  44. package/src/hooks/useHustle.ts +36 -0
  45. package/src/hooks/usePlugins.ts +135 -0
  46. package/src/index.ts +142 -0
  47. package/src/plugins/index.ts +48 -0
  48. package/src/plugins/migrateFun.ts +211 -0
  49. package/src/plugins/predictionMarket.ts +411 -0
  50. package/src/providers/EmblemAuthProvider.tsx +319 -0
  51. package/src/providers/HustleProvider.tsx +540 -0
  52. package/src/providers/index.ts +6 -0
  53. package/src/styles/index.ts +2 -0
  54. package/src/styles/tokens.ts +447 -0
  55. package/src/types/auth.ts +85 -0
  56. package/src/types/hustle.ts +217 -0
  57. package/src/types/index.ts +49 -0
  58. package/src/types/plugin.ts +180 -0
  59. package/src/utils/index.ts +122 -0
  60. package/src/utils/pluginRegistry.ts +375 -0
@@ -0,0 +1,447 @@
1
+ /**
2
+ * Design Tokens for Hustle React Components
3
+ *
4
+ * These tokens use CSS Custom Properties (CSS Variables) for easy theming.
5
+ * Override any variable in your CSS to customize the theme:
6
+ *
7
+ * @example
8
+ * ```css
9
+ * :root {
10
+ * --hustle-color-bg-primary: #ffffff;
11
+ * --hustle-color-text-primary: #1a1a1a;
12
+ * }
13
+ * ```
14
+ */
15
+
16
+ // ============================================================================
17
+ // Default Token Values
18
+ // ============================================================================
19
+ const defaults = {
20
+ colors: {
21
+ // Backgrounds
22
+ bgPrimary: '#0b0d10',
23
+ bgSecondary: '#12161b',
24
+ bgTertiary: '#1a1f25',
25
+ bgHover: '#252b33',
26
+ bgOverlay: 'rgba(0, 0, 0, 0.7)',
27
+
28
+ // Borders
29
+ borderPrimary: '#222b35',
30
+ borderSecondary: '#333',
31
+ borderHover: '#444',
32
+
33
+ // Text
34
+ textPrimary: '#e6eef8',
35
+ textSecondary: '#8892a4',
36
+ textTertiary: '#6b7280',
37
+ textInverse: '#fff',
38
+
39
+ // Accent - Primary (blue)
40
+ accentPrimary: '#4c9aff',
41
+ accentPrimaryHover: '#7bb6ff',
42
+ accentPrimaryBg: 'rgba(76, 154, 255, 0.1)',
43
+
44
+ // Accent - Success (green)
45
+ accentSuccess: '#10b981',
46
+ accentSuccessHover: '#34d399',
47
+ accentSuccessBg: 'rgba(16, 185, 129, 0.1)',
48
+
49
+ // Accent - Warning (yellow/orange)
50
+ accentWarning: '#f59e0b',
51
+ accentWarningBg: 'rgba(245, 158, 11, 0.1)',
52
+
53
+ // Accent - Error (red)
54
+ accentError: '#dc2626',
55
+ accentErrorHover: '#ef4444',
56
+ accentErrorBg: 'rgba(239, 68, 68, 0.1)',
57
+
58
+ // Messages
59
+ msgUser: '#1e3a5f',
60
+ msgAssistant: '#1a2633',
61
+ },
62
+
63
+ typography: {
64
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
65
+ fontFamilyMono: '"SF Mono", Monaco, monospace',
66
+ fontSizeXs: '11px',
67
+ fontSizeSm: '13px',
68
+ fontSizeMd: '14px',
69
+ fontSizeLg: '16px',
70
+ fontSizeXl: '18px',
71
+ fontWeightNormal: '400',
72
+ fontWeightMedium: '500',
73
+ fontWeightSemibold: '600',
74
+ lineHeightTight: '1.3',
75
+ lineHeightNormal: '1.5',
76
+ lineHeightRelaxed: '1.7',
77
+ },
78
+
79
+ spacing: {
80
+ xs: '4px',
81
+ sm: '8px',
82
+ md: '12px',
83
+ lg: '16px',
84
+ xl: '20px',
85
+ xxl: '24px',
86
+ },
87
+
88
+ radius: {
89
+ sm: '4px',
90
+ md: '6px',
91
+ lg: '8px',
92
+ xl: '12px',
93
+ pill: '20px',
94
+ full: '50%',
95
+ },
96
+
97
+ shadows: {
98
+ sm: '0 2px 8px rgba(0,0,0,0.2)',
99
+ md: '0 4px 16px rgba(0,0,0,0.3)',
100
+ lg: '0 8px 32px rgba(0,0,0,0.4)',
101
+ xl: '0 16px 48px rgba(0,0,0,0.5)',
102
+ },
103
+
104
+ // Glow effects (for enhanced themes)
105
+ glows: {
106
+ primary: 'rgba(76, 154, 255, 0.4)',
107
+ success: 'rgba(16, 185, 129, 0.4)',
108
+ error: 'rgba(239, 68, 68, 0.4)',
109
+ ambient: 'rgba(76, 154, 255, 0.08)',
110
+ },
111
+
112
+ transitions: {
113
+ fast: '0.15s ease',
114
+ normal: '0.2s ease',
115
+ slow: '0.3s ease',
116
+ },
117
+
118
+ zIndex: {
119
+ dropdown: '100',
120
+ modal: '1000',
121
+ fullscreen: '1000',
122
+ modalOverFullscreen: '10000',
123
+ },
124
+ };
125
+
126
+ // ============================================================================
127
+ // CSS Variable Name Generator
128
+ // ============================================================================
129
+ function toVarName(category: string, key: string): string {
130
+ // Convert camelCase to kebab-case
131
+ const kebab = key.replace(/([A-Z])/g, '-$1').toLowerCase();
132
+ return `--hustle-${category}-${kebab}`;
133
+ }
134
+
135
+ // ============================================================================
136
+ // CSS Variables Stylesheet (inject this once in your app)
137
+ // ============================================================================
138
+ function generateCSSVariables(): string {
139
+ const lines: string[] = [':root {'];
140
+
141
+ // Colors
142
+ for (const [key, value] of Object.entries(defaults.colors)) {
143
+ lines.push(` ${toVarName('color', key)}: ${value};`);
144
+ }
145
+
146
+ // Typography
147
+ for (const [key, value] of Object.entries(defaults.typography)) {
148
+ lines.push(` ${toVarName('font', key)}: ${value};`);
149
+ }
150
+
151
+ // Spacing
152
+ for (const [key, value] of Object.entries(defaults.spacing)) {
153
+ lines.push(` ${toVarName('space', key)}: ${value};`);
154
+ }
155
+
156
+ // Radius
157
+ for (const [key, value] of Object.entries(defaults.radius)) {
158
+ lines.push(` ${toVarName('radius', key)}: ${value};`);
159
+ }
160
+
161
+ // Shadows
162
+ for (const [key, value] of Object.entries(defaults.shadows)) {
163
+ lines.push(` ${toVarName('shadow', key)}: ${value};`);
164
+ }
165
+
166
+ // Glows
167
+ for (const [key, value] of Object.entries(defaults.glows)) {
168
+ lines.push(` ${toVarName('glow', key)}: ${value};`);
169
+ }
170
+
171
+ // Transitions
172
+ for (const [key, value] of Object.entries(defaults.transitions)) {
173
+ lines.push(` ${toVarName('transition', key)}: ${value};`);
174
+ }
175
+
176
+ // Z-Index
177
+ for (const [key, value] of Object.entries(defaults.zIndex)) {
178
+ lines.push(` ${toVarName('z', key)}: ${value};`);
179
+ }
180
+
181
+ lines.push('}');
182
+ return lines.join('\n');
183
+ }
184
+
185
+ /**
186
+ * CSS Variables stylesheet - inject this in your app's <head> or include in your CSS
187
+ * Contains all default token values as CSS custom properties
188
+ */
189
+ export const cssVariables = generateCSSVariables();
190
+
191
+ // ============================================================================
192
+ // Token Accessors (use CSS var() with fallback to default)
193
+ // ============================================================================
194
+ function createColorTokens() {
195
+ const result: Record<string, string> = {};
196
+ for (const [key, defaultValue] of Object.entries(defaults.colors)) {
197
+ result[key] = `var(${toVarName('color', key)}, ${defaultValue})`;
198
+ }
199
+ return result as typeof defaults.colors;
200
+ }
201
+
202
+ function createTypographyTokens() {
203
+ const result: Record<string, string | number> = {};
204
+ for (const [key, defaultValue] of Object.entries(defaults.typography)) {
205
+ result[key] = `var(${toVarName('font', key)}, ${defaultValue})`;
206
+ }
207
+ return result as unknown as {
208
+ fontFamily: string;
209
+ fontFamilyMono: string;
210
+ fontSizeXs: string;
211
+ fontSizeSm: string;
212
+ fontSizeMd: string;
213
+ fontSizeLg: string;
214
+ fontSizeXl: string;
215
+ fontWeightNormal: number;
216
+ fontWeightMedium: number;
217
+ fontWeightSemibold: number;
218
+ lineHeightTight: number;
219
+ lineHeightNormal: number;
220
+ lineHeightRelaxed: number;
221
+ };
222
+ }
223
+
224
+ function createSpacingTokens() {
225
+ const result: Record<string, string> = {};
226
+ for (const [key, defaultValue] of Object.entries(defaults.spacing)) {
227
+ result[key] = `var(${toVarName('space', key)}, ${defaultValue})`;
228
+ }
229
+ return result as typeof defaults.spacing;
230
+ }
231
+
232
+ function createRadiusTokens() {
233
+ const result: Record<string, string> = {};
234
+ for (const [key, defaultValue] of Object.entries(defaults.radius)) {
235
+ result[key] = `var(${toVarName('radius', key)}, ${defaultValue})`;
236
+ }
237
+ return result as typeof defaults.radius;
238
+ }
239
+
240
+ function createShadowTokens() {
241
+ const result: Record<string, string> = {};
242
+ for (const [key, defaultValue] of Object.entries(defaults.shadows)) {
243
+ result[key] = `var(${toVarName('shadow', key)}, ${defaultValue})`;
244
+ }
245
+ return result as typeof defaults.shadows;
246
+ }
247
+
248
+ function createGlowTokens() {
249
+ const result: Record<string, string> = {};
250
+ for (const [key, defaultValue] of Object.entries(defaults.glows)) {
251
+ result[key] = `var(${toVarName('glow', key)}, ${defaultValue})`;
252
+ }
253
+ return result as typeof defaults.glows;
254
+ }
255
+
256
+ function createTransitionTokens() {
257
+ const result: Record<string, string> = {};
258
+ for (const [key, defaultValue] of Object.entries(defaults.transitions)) {
259
+ result[key] = `var(${toVarName('transition', key)}, ${defaultValue})`;
260
+ }
261
+ return result as typeof defaults.transitions;
262
+ }
263
+
264
+ function createZIndexTokens() {
265
+ const result: Record<string, number> = {};
266
+ for (const [key, defaultValue] of Object.entries(defaults.zIndex)) {
267
+ // z-index needs to be a number for React inline styles
268
+ // We keep the default value as number, CSS var override still works
269
+ result[key] = parseInt(defaultValue, 10);
270
+ }
271
+ return result as { dropdown: number; modal: number; fullscreen: number; modalOverFullscreen: number };
272
+ }
273
+
274
+ // ============================================================================
275
+ // Exported Tokens (use these in components)
276
+ // ============================================================================
277
+ export const tokens = {
278
+ colors: createColorTokens(),
279
+ typography: createTypographyTokens(),
280
+ spacing: createSpacingTokens(),
281
+ radius: createRadiusTokens(),
282
+ shadows: createShadowTokens(),
283
+ glows: createGlowTokens(),
284
+ transitions: createTransitionTokens(),
285
+ zIndex: createZIndexTokens(),
286
+ };
287
+
288
+ export type Tokens = typeof tokens;
289
+
290
+ /**
291
+ * Raw default values (without CSS var() wrapper)
292
+ * Use this if you need the actual values, not CSS variable references
293
+ */
294
+ export const defaultTokens = defaults;
295
+
296
+ // ============================================================================
297
+ // Helper Functions
298
+ // ============================================================================
299
+
300
+ /**
301
+ * Get a token value by path (e.g., 'colors.bgPrimary')
302
+ */
303
+ export function getTokenValue(path: string): string | number | undefined {
304
+ const parts = path.split('.');
305
+ let current: unknown = tokens;
306
+
307
+ for (const part of parts) {
308
+ if (current && typeof current === 'object' && part in current) {
309
+ current = (current as Record<string, unknown>)[part];
310
+ } else {
311
+ return undefined;
312
+ }
313
+ }
314
+
315
+ return current as string | number | undefined;
316
+ }
317
+
318
+ /**
319
+ * Create a themed style object
320
+ */
321
+ export function createStyle(mapping: Record<string, string>): React.CSSProperties {
322
+ const result: Record<string, unknown> = {};
323
+
324
+ for (const [cssProp, tokenPath] of Object.entries(mapping)) {
325
+ const value = getTokenValue(tokenPath);
326
+ if (value !== undefined) {
327
+ result[cssProp] = value;
328
+ }
329
+ }
330
+
331
+ return result as React.CSSProperties;
332
+ }
333
+
334
+ // ============================================================================
335
+ // Common Style Presets
336
+ // ============================================================================
337
+ export const presets = {
338
+ base: {
339
+ fontFamily: tokens.typography.fontFamily,
340
+ fontSize: tokens.typography.fontSizeMd,
341
+ lineHeight: tokens.typography.lineHeightNormal,
342
+ color: tokens.colors.textPrimary,
343
+ } as React.CSSProperties,
344
+
345
+ card: {
346
+ background: tokens.colors.bgSecondary,
347
+ border: `1px solid ${tokens.colors.borderPrimary}`,
348
+ borderRadius: tokens.radius.xl,
349
+ } as React.CSSProperties,
350
+
351
+ input: {
352
+ background: tokens.colors.bgTertiary,
353
+ border: `1px solid ${tokens.colors.borderSecondary}`,
354
+ borderRadius: tokens.radius.lg,
355
+ color: tokens.colors.textPrimary,
356
+ fontSize: tokens.typography.fontSizeMd,
357
+ padding: `${tokens.spacing.md} ${tokens.spacing.lg}`,
358
+ outline: 'none',
359
+ transition: `border-color ${tokens.transitions.normal}`,
360
+ } as React.CSSProperties,
361
+
362
+ button: {
363
+ display: 'inline-flex',
364
+ alignItems: 'center',
365
+ justifyContent: 'center',
366
+ gap: tokens.spacing.sm,
367
+ padding: `${tokens.spacing.sm} ${tokens.spacing.lg}`,
368
+ borderRadius: tokens.radius.lg,
369
+ fontSize: tokens.typography.fontSizeMd,
370
+ fontWeight: tokens.typography.fontWeightMedium,
371
+ cursor: 'pointer',
372
+ transition: `all ${tokens.transitions.normal}`,
373
+ border: `1px solid ${tokens.colors.borderSecondary}`,
374
+ outline: 'none',
375
+ } as React.CSSProperties,
376
+
377
+ buttonPrimary: {
378
+ background: tokens.colors.accentPrimary,
379
+ color: tokens.colors.textInverse,
380
+ borderColor: tokens.colors.accentPrimary,
381
+ } as React.CSSProperties,
382
+
383
+ buttonSecondary: {
384
+ background: tokens.colors.bgTertiary,
385
+ color: tokens.colors.textPrimary,
386
+ borderColor: tokens.colors.borderSecondary,
387
+ } as React.CSSProperties,
388
+
389
+ buttonIcon: {
390
+ width: '36px',
391
+ height: '36px',
392
+ padding: 0,
393
+ // background inherited from global button styles
394
+ color: tokens.colors.textSecondary,
395
+ } as React.CSSProperties,
396
+
397
+ mono: {
398
+ fontFamily: tokens.typography.fontFamilyMono,
399
+ fontSize: tokens.typography.fontSizeSm,
400
+ } as React.CSSProperties,
401
+
402
+ label: {
403
+ display: 'block',
404
+ fontSize: tokens.typography.fontSizeXs,
405
+ color: tokens.colors.textTertiary,
406
+ marginBottom: tokens.spacing.xs,
407
+ } as React.CSSProperties,
408
+ };
409
+
410
+ // ============================================================================
411
+ // Animation Keyframes
412
+ // ============================================================================
413
+
414
+ /**
415
+ * Animation keyframes only (no CSS variable defaults)
416
+ * Use this in components to avoid overriding consumer theme customizations
417
+ */
418
+ export const animations = `
419
+ @keyframes hustle-spin {
420
+ to { transform: rotate(360deg); }
421
+ }
422
+ @keyframes hustle-pulse {
423
+ 0%, 100% { opacity: 1; }
424
+ 50% { opacity: 0.5; }
425
+ }
426
+ @keyframes hustle-glow {
427
+ 0%, 100% {
428
+ opacity: 1;
429
+ text-shadow: 0 0 4px ${defaults.colors.accentPrimaryBg};
430
+ }
431
+ 50% {
432
+ opacity: 0.6;
433
+ text-shadow: 0 0 8px ${defaults.colors.accentPrimary};
434
+ }
435
+ }
436
+ `;
437
+
438
+ /**
439
+ * @deprecated Use `animations` instead. This includes CSS variable defaults
440
+ * which can override consumer theme customizations.
441
+ */
442
+ export const keyframes = `
443
+ ${cssVariables}
444
+ ${animations}
445
+ `;
446
+
447
+ export default tokens;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Auth Types for Emblem Auth SDK integration
3
+ * These types mirror the EmblemAuthSDK types for use in React components
4
+ */
5
+
6
+ import type { EmblemAuthSDK } from 'emblem-auth-sdk';
7
+
8
+ /**
9
+ * User information from the authenticated session
10
+ */
11
+ export interface AuthUser {
12
+ identifier: string;
13
+ vaultId: string;
14
+ evmAddress?: string;
15
+ solanaAddress?: string;
16
+ }
17
+
18
+ /**
19
+ * Authenticated session returned by the Auth SDK
20
+ */
21
+ export interface AuthSession {
22
+ user: AuthUser;
23
+ authToken: string;
24
+ refreshToken?: string;
25
+ expiresAt: number;
26
+ appId: string;
27
+ scope?: string;
28
+ }
29
+
30
+ /**
31
+ * Vault information retrieved after authentication
32
+ */
33
+ export interface VaultInfo {
34
+ vaultId: string;
35
+ evmAddress?: string;
36
+ solanaAddress?: string;
37
+ hederaAccountId?: string;
38
+ createdAt?: string;
39
+ metadata?: Record<string, unknown>;
40
+ }
41
+
42
+ /**
43
+ * Configuration options for EmblemAuthProvider
44
+ */
45
+ export interface EmblemAuthConfig {
46
+ /** Application ID registered with Emblem */
47
+ appId: string;
48
+ /** API endpoint URL (defaults to production) */
49
+ apiUrl?: string;
50
+ /** Auth modal URL (defaults to production) */
51
+ modalUrl?: string;
52
+ /** Enable debug logging */
53
+ debug?: boolean;
54
+ }
55
+
56
+ /**
57
+ * Context value exposed by EmblemAuthProvider
58
+ */
59
+ export interface EmblemAuthContextValue {
60
+ // State
61
+ session: AuthSession | null;
62
+ isAuthenticated: boolean;
63
+ isLoading: boolean;
64
+ error: Error | null;
65
+ vaultInfo: VaultInfo | null;
66
+
67
+ // Derived from session
68
+ vaultId: string | null;
69
+ walletAddress: string | null;
70
+
71
+ // Actions
72
+ openAuthModal: () => Promise<void>;
73
+ logout: () => void;
74
+ refreshSession: () => Promise<AuthSession | null>;
75
+
76
+ // For Hustle integration (internal use)
77
+ authSDK: EmblemAuthSDK | null;
78
+ }
79
+
80
+ /**
81
+ * Props for EmblemAuthProvider component
82
+ */
83
+ export interface EmblemAuthProviderProps extends EmblemAuthConfig {
84
+ children: React.ReactNode;
85
+ }