dynim-react 1.0.39 → 1.0.41

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.
@@ -9,6 +9,8 @@
9
9
  import { type ReactNode } from 'react';
10
10
  import type { CodeMessage } from 'dynim-core';
11
11
  export interface DynimConfig {
12
+ /** JWT session token for authentication (avoids HTTP call on mount) */
13
+ sessionToken?: string;
12
14
  /** Function to fetch a new session when current one expires */
13
15
  getSession?: () => Promise<{
14
16
  token: string;
@@ -1 +1 @@
1
- {"version":3,"file":"DynimProvider.d.ts","sourceRoot":"","sources":["../src/DynimProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAc,EAQZ,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AASf,OAAO,KAAK,EAKV,WAAW,EAEZ,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,kCAAkC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,KAAK,IAAI,CAAC;IACzC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,qBAAqB;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,yBAAyB;IACzB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,oCAAoC;IACpC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,yDAAyD;IACzD,WAAW,EAAE,WAAW,CAAC;IACzB,2CAA2C;IAC3C,cAAc,EAAE,OAAO,CAAC;IACxB,gCAAgC;IAChC,eAAe,EAAE,OAAO,CAAC;CAC1B;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,MAAW,GACZ,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CA0WlC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C"}
1
+ {"version":3,"file":"DynimProvider.d.ts","sourceRoot":"","sources":["../src/DynimProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAc,EAQZ,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AASf,OAAO,KAAK,EAKV,WAAW,EAEZ,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,WAAW;IAC1B,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE,kCAAkC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,KAAK,IAAI,CAAC;IACzC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,qBAAqB;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,qCAAqC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,yBAAyB;IACzB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,oCAAoC;IACpC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,yDAAyD;IACzD,WAAW,EAAE,WAAW,CAAC;IACzB,2CAA2C;IAC3C,cAAc,EAAE,OAAO,CAAC;IACxB,gCAAgC;IAChC,eAAe,EAAE,OAAO,CAAC;CAC1B;AAID,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,MAAW,GACZ,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAsYlC;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C"}
@@ -88,11 +88,17 @@ export function DynimProvider({ children, config = {}, }) {
88
88
  }, []);
89
89
  // Get auth token
90
90
  const getAuthToken = useCallback(async () => {
91
+ const { sessionToken, getSession } = configRef.current;
92
+ // Fast path: static token from config (avoids HTTP call)
93
+ if (sessionToken) {
94
+ return sessionToken;
95
+ }
96
+ // Fast path: return cached token
91
97
  if (cachedTokenRef.current)
92
98
  return cachedTokenRef.current;
99
+ // Reuse in-flight promise if one exists
93
100
  if (tokenPromiseRef.current)
94
101
  return tokenPromiseRef.current;
95
- const { getSession } = configRef.current;
96
102
  if (getSession) {
97
103
  tokenPromiseRef.current = (async () => {
98
104
  try {
@@ -236,14 +242,32 @@ export function DynimProvider({ children, config = {}, }) {
236
242
  console.warn('[DynimProvider] Failed to fetch theme:', error);
237
243
  }
238
244
  }, [getAuthToken]);
239
- // Mark initial load complete immediately - no eager HTTP requests
240
- // Bundle loading happens lazily when user enters builder or when
241
- // the consuming app explicitly triggers it
245
+ // Auto-load saved bundle on mount if sessionToken is provided
246
+ // This avoids HTTP calls (getSession) while still loading saved bundles
242
247
  useEffect(() => {
243
- if (!hasAttemptedInitialLoadRef.current) {
244
- hasAttemptedInitialLoadRef.current = true;
248
+ if (hasAttemptedInitialLoadRef.current)
249
+ return;
250
+ hasAttemptedInitialLoadRef.current = true;
251
+ const { sessionToken } = configRef.current;
252
+ // No token = user not logged in, skip bundle load
253
+ if (!sessionToken) {
245
254
  setIsInitialLoadComplete(true);
255
+ return;
246
256
  }
257
+ // Load bundle with the provided token
258
+ const doInitialLoad = async () => {
259
+ try {
260
+ await loadBundleRef.current?.('/api/code/bundle');
261
+ }
262
+ catch (error) {
263
+ // Errors handled in loadBundle (404 = no bundle, etc.)
264
+ console.log('[DynimProvider] Initial bundle load:', error.message);
265
+ }
266
+ finally {
267
+ setIsInitialLoadComplete(true);
268
+ }
269
+ };
270
+ doInitialLoad();
247
271
  }, []);
248
272
  // Load saved bundle
249
273
  const loadSavedBundle = useCallback(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dynim-react",
3
- "version": "1.0.39",
3
+ "version": "1.0.41",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1,11 +0,0 @@
1
- /**
2
- * React Context for sharing chatbot state across components
3
- */
4
- import { type ReactNode } from 'react';
5
- import { type UseChatbotConfig, type UseChatbotReturn } from './useChatbot';
6
- export interface ChatProviderProps extends UseChatbotConfig {
7
- children: ReactNode;
8
- }
9
- export declare function ChatProvider({ children, ...config }: ChatProviderProps): JSX.Element;
10
- export declare function useChatContext(): UseChatbotReturn;
11
- //# sourceMappingURL=ChatContext.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ChatContext.d.ts","sourceRoot":"","sources":["../../src/builder/ChatContext.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,EAAc,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIxF,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,EAAE,iBAAiB,GAAG,GAAG,CAAC,OAAO,CAIpF;AAED,wBAAgB,cAAc,IAAI,gBAAgB,CAMjD"}
@@ -1,18 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * React Context for sharing chatbot state across components
4
- */
5
- import { createContext, useContext } from 'react';
6
- import { useChatbot } from './useChatbot';
7
- const ChatContext = createContext(null);
8
- export function ChatProvider({ children, ...config }) {
9
- const chatbot = useChatbot(config);
10
- return _jsx(ChatContext.Provider, { value: chatbot, children: children });
11
- }
12
- export function useChatContext() {
13
- const context = useContext(ChatContext);
14
- if (!context) {
15
- throw new Error('useChatContext must be used within a ChatProvider');
16
- }
17
- return context;
18
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * Chat input component
3
- */
4
- export interface ChatInputProps {
5
- className?: string;
6
- placeholder?: string;
7
- disabled?: boolean;
8
- onSubmit?: (text: string) => void;
9
- }
10
- export declare function ChatInput({ className, placeholder, disabled, onSubmit, }: ChatInputProps): JSX.Element;
11
- //# sourceMappingURL=ChatInput.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ChatInput.d.ts","sourceRoot":"","sources":["../../src/builder/ChatInput.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,SAAS,CAAC,EACxB,SAAc,EACd,WAAiC,EACjC,QAAgB,EAChB,QAAQ,GACT,EAAE,cAAc,GAAG,GAAG,CAAC,OAAO,CAuC9B"}
@@ -1,20 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * Chat input component
4
- */
5
- import { useState, useCallback } from 'react';
6
- import { useChatContext } from './ChatContext';
7
- export function ChatInput({ className = '', placeholder = 'Type a message...', disabled = false, onSubmit, }) {
8
- const { sendMessage, isLoading } = useChatContext();
9
- const [value, setValue] = useState('');
10
- const handleSubmit = useCallback((e) => {
11
- e.preventDefault();
12
- const text = value.trim();
13
- if (!text || isLoading)
14
- return;
15
- setValue('');
16
- onSubmit?.(text);
17
- sendMessage(text);
18
- }, [value, isLoading, sendMessage, onSubmit]);
19
- return (_jsxs("form", { className: `chatbot-form ${className}`, onSubmit: handleSubmit, children: [_jsx("input", { type: "text", className: "chatbot-input", placeholder: placeholder, value: value, onChange: (e) => setValue(e.target.value), disabled: disabled || isLoading, autoComplete: "off" }), _jsx("button", { type: "submit", className: "chatbot-send", disabled: disabled || isLoading || !value.trim(), children: _jsx("svg", { viewBox: "0 0 24 24", width: "20", height: "20", fill: "currentColor", children: _jsx("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) }) })] }));
20
- }
@@ -1,24 +0,0 @@
1
- /**
2
- * CodeChatPanel - Self-contained code chat UI component
3
- *
4
- * Handles all the complexity internally:
5
- * - Streaming responses with thinking/text differentiation
6
- * - Code edit display with accept/reject
7
- * - Loading states, errors
8
- *
9
- * Consuming app just drops this in and it works.
10
- */
11
- export interface CodeChatPanelProps {
12
- /** Optional placeholder text for input */
13
- placeholder?: string;
14
- /** Optional class name for the container */
15
- className?: string;
16
- /** Called when edits are saved */
17
- onSave?: () => void;
18
- /** Called when edits are abandoned */
19
- onAbandon?: () => void;
20
- /** Called on errors */
21
- onError?: (error: string) => void;
22
- }
23
- export declare function CodeChatPanel({ placeholder, className, onSave, onAbandon, onError, }: CodeChatPanelProps): JSX.Element;
24
- //# sourceMappingURL=CodeChatPanel.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"CodeChatPanel.d.ts","sourceRoot":"","sources":["../../src/builder/CodeChatPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,MAAM,WAAW,kBAAkB;IACjC,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,uBAAuB;IACvB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AA4MD,wBAAgB,aAAa,CAAC,EAC5B,WAAsD,EACtD,SAAc,EACd,MAAM,EACN,SAAS,EACT,OAAO,GACR,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CA6LlC"}
@@ -1,304 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * CodeChatPanel - Self-contained code chat UI component
4
- *
5
- * Handles all the complexity internally:
6
- * - Streaming responses with thinking/text differentiation
7
- * - Code edit display with accept/reject
8
- * - Loading states, errors
9
- *
10
- * Consuming app just drops this in and it works.
11
- */
12
- import { useState, useCallback, useRef, useEffect } from 'react';
13
- import { useDynim } from '../DynimProvider';
14
- import { themeVars } from '../theme';
15
- // Styles using CSS variables for easy theming
16
- const styles = {
17
- container: {
18
- display: 'flex',
19
- flexDirection: 'column',
20
- height: '100%',
21
- fontFamily: themeVars.fontFamily,
22
- fontSize: themeVars.fontSize,
23
- backgroundColor: themeVars.bgPrimary,
24
- borderRadius: themeVars.radiusLg,
25
- overflow: 'hidden',
26
- },
27
- messagesArea: {
28
- flex: 1,
29
- overflowY: 'auto',
30
- padding: themeVars.spacingLg,
31
- },
32
- messageBlock: {
33
- marginBottom: themeVars.spacingLg,
34
- },
35
- thinkingSection: {
36
- marginBottom: themeVars.spacingMd,
37
- },
38
- thinkingHeader: {
39
- display: 'flex',
40
- alignItems: 'center',
41
- gap: themeVars.spacingSm,
42
- padding: `${themeVars.spacingSm} ${themeVars.spacingMd}`,
43
- backgroundColor: themeVars.bgTertiary,
44
- borderRadius: themeVars.radiusMd,
45
- cursor: 'pointer',
46
- userSelect: 'none',
47
- fontSize: themeVars.fontSizeSm,
48
- color: themeVars.textSecondary,
49
- },
50
- thinkingContent: {
51
- padding: themeVars.spacingMd,
52
- backgroundColor: themeVars.bgPrimary,
53
- borderRadius: `0 0 ${themeVars.radiusMd} ${themeVars.radiusMd}`,
54
- borderLeft: `3px solid ${themeVars.border}`,
55
- marginTop: '-6px',
56
- fontSize: themeVars.fontSizeSm,
57
- color: themeVars.textSecondary,
58
- whiteSpace: 'pre-wrap',
59
- lineHeight: themeVars.lineHeight,
60
- },
61
- responseText: {
62
- padding: `${themeVars.spacingMd} ${themeVars.spacingLg}`,
63
- backgroundColor: themeVars.bgSecondary,
64
- borderRadius: themeVars.radiusLg,
65
- border: `1px solid ${themeVars.border}`,
66
- whiteSpace: 'pre-wrap',
67
- lineHeight: '1.6',
68
- color: themeVars.textPrimary,
69
- },
70
- editsSection: {
71
- marginTop: themeVars.spacingLg,
72
- },
73
- editsHeader: {
74
- display: 'flex',
75
- alignItems: 'center',
76
- justifyContent: 'space-between',
77
- marginBottom: themeVars.spacingMd,
78
- },
79
- editsTitle: {
80
- fontWeight: 600,
81
- color: themeVars.textPrimary,
82
- },
83
- editsActions: {
84
- display: 'flex',
85
- gap: themeVars.spacingSm,
86
- },
87
- editCard: {
88
- backgroundColor: themeVars.bgSecondary,
89
- border: `1px solid ${themeVars.border}`,
90
- borderRadius: themeVars.radiusMd,
91
- marginBottom: themeVars.spacingSm,
92
- overflow: 'hidden',
93
- },
94
- editHeader: {
95
- display: 'flex',
96
- alignItems: 'center',
97
- justifyContent: 'space-between',
98
- padding: `${themeVars.spacingSm} ${themeVars.spacingMd}`,
99
- backgroundColor: themeVars.bgTertiary,
100
- borderBottom: `1px solid ${themeVars.border}`,
101
- },
102
- editPath: {
103
- fontFamily: themeVars.fontFamilyMono,
104
- fontSize: themeVars.fontSizeXs,
105
- color: themeVars.textSecondary,
106
- },
107
- editType: {
108
- fontSize: '11px',
109
- padding: '2px 6px',
110
- borderRadius: '3px',
111
- fontWeight: 500,
112
- },
113
- editTypeCreate: {
114
- backgroundColor: themeVars.successBg,
115
- color: themeVars.success,
116
- },
117
- editTypeReplace: {
118
- backgroundColor: themeVars.warningBg,
119
- color: themeVars.warning,
120
- },
121
- editTypeDelete: {
122
- backgroundColor: themeVars.errorBg,
123
- color: themeVars.error,
124
- },
125
- editContent: {
126
- padding: `${themeVars.spacingSm} ${themeVars.spacingMd}`,
127
- fontFamily: themeVars.fontFamilyMono,
128
- fontSize: themeVars.fontSizeXs,
129
- maxHeight: '200px',
130
- overflowY: 'auto',
131
- },
132
- diffLine: {
133
- padding: '1px 4px',
134
- whiteSpace: 'pre',
135
- },
136
- diffAdd: {
137
- backgroundColor: themeVars.successBg,
138
- color: themeVars.success,
139
- },
140
- diffRemove: {
141
- backgroundColor: themeVars.errorBg,
142
- color: themeVars.error,
143
- },
144
- button: {
145
- padding: `6px ${themeVars.spacingMd}`,
146
- borderRadius: themeVars.radiusSm,
147
- border: 'none',
148
- cursor: 'pointer',
149
- fontSize: themeVars.fontSizeSm,
150
- fontWeight: 500,
151
- transition: 'background-color 0.2s',
152
- },
153
- buttonPrimary: {
154
- backgroundColor: themeVars.accent,
155
- color: '#fff',
156
- },
157
- buttonSecondary: {
158
- backgroundColor: themeVars.bgTertiary,
159
- color: themeVars.textPrimary,
160
- },
161
- buttonDisabled: {
162
- opacity: 0.5,
163
- cursor: 'not-allowed',
164
- },
165
- inputArea: {
166
- padding: `${themeVars.spacingMd} ${themeVars.spacingLg}`,
167
- borderTop: `1px solid ${themeVars.border}`,
168
- backgroundColor: themeVars.bgSecondary,
169
- },
170
- form: {
171
- display: 'flex',
172
- gap: themeVars.spacingSm,
173
- },
174
- input: {
175
- flex: 1,
176
- padding: `10px 14px`,
177
- borderRadius: themeVars.radiusMd,
178
- border: `1px solid ${themeVars.border}`,
179
- fontSize: themeVars.fontSize,
180
- outline: 'none',
181
- fontFamily: themeVars.fontFamily,
182
- backgroundColor: themeVars.bgSecondary,
183
- color: themeVars.textPrimary,
184
- },
185
- statusBar: {
186
- padding: `${themeVars.spacingSm} ${themeVars.spacingLg}`,
187
- fontSize: themeVars.fontSizeXs,
188
- color: themeVars.textSecondary,
189
- backgroundColor: themeVars.bgTertiary,
190
- borderTop: `1px solid ${themeVars.border}`,
191
- },
192
- streamingDot: {
193
- display: 'inline-block',
194
- width: '8px',
195
- height: '8px',
196
- borderRadius: '50%',
197
- backgroundColor: themeVars.accent,
198
- marginRight: themeVars.spacingSm,
199
- animation: 'pulse 1s infinite',
200
- },
201
- errorBar: {
202
- padding: `${themeVars.spacingMd} ${themeVars.spacingLg}`,
203
- backgroundColor: themeVars.errorBg,
204
- color: themeVars.error,
205
- borderTop: `1px solid ${themeVars.border}`,
206
- },
207
- emptyState: {
208
- display: 'flex',
209
- alignItems: 'center',
210
- justifyContent: 'center',
211
- height: '100%',
212
- color: themeVars.textMuted,
213
- fontSize: themeVars.fontSize,
214
- },
215
- };
216
- export function CodeChatPanel({ placeholder = 'Ask me to make changes to your code...', className = '', onSave, onAbandon, onError, }) {
217
- const { sendCode, saveCode, abandonCode, codeMessage } = useDynim();
218
- const [inputValue, setInputValue] = useState('');
219
- const [thinkingExpanded, setThinkingExpanded] = useState(false);
220
- const [isSaving, setIsSaving] = useState(false);
221
- const messagesRef = useRef(null);
222
- const { thinking, text, edits, status, error } = codeMessage;
223
- // Auto-scroll on new content
224
- useEffect(() => {
225
- if (messagesRef.current) {
226
- messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
227
- }
228
- }, [thinking, text, edits]);
229
- // Notify on errors
230
- useEffect(() => {
231
- if (error) {
232
- onError?.(error);
233
- }
234
- }, [error, onError]);
235
- const handleSubmit = useCallback(async (e) => {
236
- e.preventDefault();
237
- const query = inputValue.trim();
238
- if (!query || status === 'streaming')
239
- return;
240
- setInputValue('');
241
- setThinkingExpanded(false);
242
- await sendCode(query);
243
- }, [inputValue, status, sendCode]);
244
- const handleSave = useCallback(async () => {
245
- setIsSaving(true);
246
- try {
247
- await saveCode();
248
- onSave?.();
249
- }
250
- catch (err) {
251
- onError?.(err.message);
252
- }
253
- finally {
254
- setIsSaving(false);
255
- }
256
- }, [saveCode, onSave, onError]);
257
- const handleAbandon = useCallback(async () => {
258
- setIsSaving(true);
259
- try {
260
- await abandonCode();
261
- onAbandon?.();
262
- }
263
- catch (err) {
264
- onError?.(err.message);
265
- }
266
- finally {
267
- setIsSaving(false);
268
- }
269
- }, [abandonCode, onAbandon, onError]);
270
- const isStreaming = status === 'streaming';
271
- const hasContent = thinking || text || edits.length > 0;
272
- const hasEdits = edits.length > 0;
273
- return (_jsxs("div", { style: styles.container, className: className, children: [_jsx("style", { children: `
274
- @keyframes pulse {
275
- 0%, 100% { opacity: 1; }
276
- 50% { opacity: 0.4; }
277
- }
278
- ` }), _jsxs("div", { ref: messagesRef, style: styles.messagesArea, children: [!hasContent && status === 'idle' && (_jsx("div", { style: styles.emptyState, children: "Send a message to start editing code" })), hasContent && (_jsxs("div", { style: styles.messageBlock, children: [thinking && (_jsxs("div", { style: styles.thinkingSection, children: [_jsxs("div", { style: styles.thinkingHeader, onClick: () => setThinkingExpanded(!thinkingExpanded), children: [_jsx("span", { children: thinkingExpanded ? '▼' : '▶' }), _jsx("span", { children: "Thinking..." }), _jsxs("span", { style: { marginLeft: 'auto', fontSize: '11px' }, children: [thinking.length, " chars"] })] }), thinkingExpanded && (_jsx("div", { style: styles.thinkingContent, children: thinking }))] })), text && _jsx("div", { style: styles.responseText, children: text }), hasEdits && (_jsxs("div", { style: styles.editsSection, children: [_jsxs("div", { style: styles.editsHeader, children: [_jsxs("span", { style: styles.editsTitle, children: [edits.length, " file", edits.length !== 1 ? 's' : '', " changed"] }), status === 'done' && (_jsxs("div", { style: styles.editsActions, children: [_jsx("button", { style: {
279
- ...styles.button,
280
- ...styles.buttonSecondary,
281
- ...(isSaving ? styles.buttonDisabled : {}),
282
- }, onClick: handleAbandon, disabled: isSaving, children: "Reject" }), _jsx("button", { style: {
283
- ...styles.button,
284
- ...styles.buttonPrimary,
285
- ...(isSaving ? styles.buttonDisabled : {}),
286
- }, onClick: handleSave, disabled: isSaving, children: "Accept Changes" })] }))] }), edits.map((edit, index) => (_jsx(EditCard, { edit: edit }, `${edit.file_path}-${index}`)))] }))] }))] }), isStreaming && (_jsxs("div", { style: styles.statusBar, children: [_jsx("span", { style: styles.streamingDot }), "Generating response..."] })), status === 'error' && error && (_jsx("div", { style: styles.errorBar, children: error })), _jsx("div", { style: styles.inputArea, children: _jsxs("form", { style: styles.form, onSubmit: handleSubmit, children: [_jsx("input", { type: "text", style: styles.input, placeholder: placeholder, value: inputValue, onChange: (e) => setInputValue(e.target.value), disabled: isStreaming }), _jsx("button", { type: "submit", style: {
287
- ...styles.button,
288
- ...styles.buttonPrimary,
289
- ...(isStreaming || !inputValue.trim() ? styles.buttonDisabled : {}),
290
- }, disabled: isStreaming || !inputValue.trim(), children: "Send" })] }) })] }));
291
- }
292
- /** Individual edit card component */
293
- function EditCard({ edit }) {
294
- const [expanded, setExpanded] = useState(true);
295
- const typeStyle = {
296
- ...styles.editType,
297
- ...(edit.type === 'create'
298
- ? styles.editTypeCreate
299
- : edit.type === 'delete'
300
- ? styles.editTypeDelete
301
- : styles.editTypeReplace),
302
- };
303
- return (_jsxs("div", { style: styles.editCard, children: [_jsxs("div", { style: { ...styles.editHeader, cursor: 'pointer' }, onClick: () => setExpanded(!expanded), children: [_jsxs("span", { style: styles.editPath, children: [expanded ? '▼' : '▶', " ", edit.file_path] }), _jsx("span", { style: typeStyle, children: edit.type })] }), expanded && (_jsxs("div", { style: styles.editContent, children: [edit.type === 'delete' && edit.old_content && (_jsx("div", { children: edit.old_content.split('\n').map((line, i) => (_jsxs("div", { style: { ...styles.diffLine, ...styles.diffRemove }, children: ["- ", line] }, i))) })), edit.type === 'create' && edit.new_content && (_jsx("div", { children: edit.new_content.split('\n').map((line, i) => (_jsxs("div", { style: { ...styles.diffLine, ...styles.diffAdd }, children: ["+ ", line] }, i))) })), edit.type === 'replace' && (_jsxs("div", { children: [edit.old_content?.split('\n').map((line, i) => (_jsxs("div", { style: { ...styles.diffLine, ...styles.diffRemove }, children: ["- ", line] }, `old-${i}`))), edit.new_content?.split('\n').map((line, i) => (_jsxs("div", { style: { ...styles.diffLine, ...styles.diffAdd }, children: ["+ ", line] }, `new-${i}`)))] }))] }))] }));
304
- }
@@ -1,14 +0,0 @@
1
- /**
2
- * Message list component
3
- * Renders messages with optional custom renderer
4
- */
5
- import { type ReactNode } from 'react';
6
- import type { Message } from 'dynim-core';
7
- export interface MessageListProps {
8
- className?: string;
9
- renderMessage?: (message: Message) => ReactNode;
10
- showAvatars?: boolean;
11
- showTimestamps?: boolean;
12
- }
13
- export declare function MessageList({ className, renderMessage, showAvatars, showTimestamps, }: MessageListProps): JSX.Element;
14
- //# sourceMappingURL=MessageList.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/builder/MessageList.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,SAAS,CAAC;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,WAAW,CAAC,EAC1B,SAAc,EACd,aAAa,EACb,WAAkB,EAClB,cAAsB,GACvB,EAAE,gBAAgB,GAAG,GAAG,CAAC,OAAO,CA6ChC"}
@@ -1,23 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * Message list component
4
- * Renders messages with optional custom renderer
5
- */
6
- import { useRef, useEffect } from 'react';
7
- import { useChatContext } from './ChatContext';
8
- export function MessageList({ className = '', renderMessage, showAvatars = true, showTimestamps = false, }) {
9
- const { messages, isTyping } = useChatContext();
10
- const containerRef = useRef(null);
11
- // Auto-scroll to bottom on new messages
12
- useEffect(() => {
13
- if (containerRef.current) {
14
- containerRef.current.scrollTop = containerRef.current.scrollHeight;
15
- }
16
- }, [messages]);
17
- // Default message renderer
18
- const defaultRenderMessage = (message) => (_jsxs("div", { className: `chatbot-message chatbot-message--${message.role}`, children: [showAvatars && (_jsx("div", { className: "chatbot-avatar", children: message.role === 'user' ? '\u{1F464}' : '\u{1F916}' })), _jsxs("div", { className: "chatbot-bubble", children: [_jsx("div", { className: "chatbot-text", children: message.text }), showTimestamps && (_jsx("div", { className: "chatbot-time", children: new Date(message.timestamp).toLocaleTimeString([], {
19
- hour: '2-digit',
20
- minute: '2-digit',
21
- }) }))] })] }, message.id));
22
- return (_jsxs("div", { ref: containerRef, className: `chatbot-messages ${className}`, children: [messages.map((message) => renderMessage ? renderMessage(message) : defaultRenderMessage(message)), isTyping && (_jsxs("div", { className: "chatbot-typing", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }))] }));
23
- }
@@ -1,14 +0,0 @@
1
- /**
2
- * Builder React exports
3
- */
4
- export { ChatProvider, useChatContext } from './ChatContext';
5
- export type { ChatProviderProps } from './ChatContext';
6
- export { MessageList } from './MessageList';
7
- export type { MessageListProps } from './MessageList';
8
- export { ChatInput } from './ChatInput';
9
- export type { ChatInputProps } from './ChatInput';
10
- export { CodeChatPanel } from './CodeChatPanel';
11
- export type { CodeChatPanelProps } from './CodeChatPanel';
12
- export { useChatbot } from './useChatbot';
13
- export type { UseChatbotConfig, UseChatbotReturn } from './useChatbot';
14
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builder/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -1,11 +0,0 @@
1
- /**
2
- * Builder React exports
3
- */
4
- // Chat context and provider
5
- export { ChatProvider, useChatContext } from './ChatContext';
6
- // Components
7
- export { MessageList } from './MessageList';
8
- export { ChatInput } from './ChatInput';
9
- export { CodeChatPanel } from './CodeChatPanel';
10
- // Headless hook for custom UI
11
- export { useChatbot } from './useChatbot';
@@ -1,28 +0,0 @@
1
- /**
2
- * Headless hook for full UI control
3
- * Use this when you want to build your own UI
4
- *
5
- * Wraps createChatbotController from dynim-core for React usage.
6
- */
7
- import type { Message } from 'dynim-core';
8
- export interface UseChatbotConfig {
9
- /** Optional API key for direct API calls (if not using session auth) */
10
- apiKey?: string;
11
- /** Optional callback when message chunks are received */
12
- onMessage?: (data: {
13
- text?: string;
14
- content?: string;
15
- }) => void;
16
- /** Optional callback when an error occurs */
17
- onError?: (error: Error) => void;
18
- }
19
- export interface UseChatbotReturn {
20
- messages: Message[];
21
- isLoading: boolean;
22
- isTyping: boolean;
23
- error: string | null;
24
- sendMessage: (text: string) => Promise<void>;
25
- clearMessages: () => void;
26
- }
27
- export declare function useChatbot(config?: UseChatbotConfig): UseChatbotReturn;
28
- //# sourceMappingURL=useChatbot.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useChatbot.d.ts","sourceRoot":"","sources":["../../src/builder/useChatbot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,YAAY,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAChE,6CAA6C;IAC7C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,MAAM,GAAE,gBAAqB,GAAG,gBAAgB,CA4D1E"}
@@ -1,60 +0,0 @@
1
- /**
2
- * Headless hook for full UI control
3
- * Use this when you want to build your own UI
4
- *
5
- * Wraps createChatbotController from dynim-core for React usage.
6
- */
7
- import { useState, useEffect, useCallback, useRef } from 'react';
8
- import { createChatbotController } from 'dynim-core';
9
- export function useChatbot(config = {}) {
10
- const { apiKey, onMessage, onError } = config;
11
- const [messages, setMessages] = useState([]);
12
- const [isLoading, setIsLoading] = useState(false);
13
- const [isTyping, setIsTyping] = useState(false);
14
- const [error, setError] = useState(null);
15
- // Keep callbacks in refs so controller always uses latest
16
- const callbacksRef = useRef({ onMessage, onError });
17
- callbacksRef.current = { onMessage, onError };
18
- const controllerRef = useRef(null);
19
- // Initialize controller once on mount (recreate if apiKey changes)
20
- useEffect(() => {
21
- // Create chatbot controller from core (uses default /api/chat endpoint)
22
- const controller = createChatbotController({
23
- apiKey,
24
- onMessage: (data) => callbacksRef.current.onMessage?.(data),
25
- onError: (err) => callbacksRef.current.onError?.(err),
26
- });
27
- controllerRef.current = controller;
28
- // Subscribe to state changes from the controller
29
- const unsubscribe = controller.subscribe((state) => {
30
- setMessages([...state.messages]);
31
- setIsLoading(state.isLoading);
32
- setIsTyping(state.isTyping);
33
- setError(state.error);
34
- });
35
- return () => {
36
- unsubscribe();
37
- controller.destroy();
38
- };
39
- }, [apiKey]); // Recreate if apiKey changes
40
- // Send message using the controller
41
- const sendMessage = useCallback(async (text) => {
42
- const controller = controllerRef.current;
43
- if (!controller)
44
- return;
45
- await controller.sendMessage(text);
46
- }, []);
47
- // Clear messages using the controller
48
- const clearMessages = useCallback(() => {
49
- controllerRef.current?.clearMessages();
50
- setError(null); // Also clear error in React state
51
- }, []);
52
- return {
53
- messages,
54
- isLoading,
55
- isTyping,
56
- error,
57
- sendMessage,
58
- clearMessages,
59
- };
60
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Inference exports
3
- */
4
- export { createSharedContext, updateSharedContext, getSharedContext, isSharedContextReady, } from './sharedContext';
5
- export type { DynimSDKConfig, DynimGlobal } from './types';
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/inference/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
@@ -1,5 +0,0 @@
1
- /**
2
- * Inference exports
3
- */
4
- // Shared context utilities
5
- export { createSharedContext, updateSharedContext, getSharedContext, isSharedContextReady, } from './sharedContext';