@pheem49/mint 1.6.3 → 1.7.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 (63) hide show
  1. package/Cargo.lock +3 -3
  2. package/Cargo.toml +1 -1
  3. package/README.md +82 -21
  4. package/assets/Mint_CLI.png +0 -0
  5. package/assets/Mint_Desktop.png +0 -0
  6. package/assets/Mint_Web.png +0 -0
  7. package/assets/Mint_WorkSpace.png +0 -0
  8. package/assets/Setting.png +0 -0
  9. package/assets/bridges.svg +4 -0
  10. package/assets/chat.svg +3 -0
  11. package/assets/code.svg +4 -0
  12. package/assets/features.svg +3 -0
  13. package/assets/imagegen.svg +5 -0
  14. package/assets/live2d.svg +6 -0
  15. package/assets/memory.svg +5 -0
  16. package/assets/screencapture.svg +4 -0
  17. package/assets/setup.svg +3 -0
  18. package/assets/tools.svg +4 -0
  19. package/bin/mint +0 -0
  20. package/crates/mint-cli/src/agent.rs +47 -15
  21. package/crates/mint-cli/src/main.rs +534 -7
  22. package/crates/mint-cli/src/onboard.rs +134 -1
  23. package/crates/mint-cli/src/setup.rs +173 -32
  24. package/crates/mint-core/src/api_server.rs +147 -3
  25. package/crates/mint-core/src/config.rs +22 -3
  26. package/crates/mint-core/src/image_gen.rs +895 -0
  27. package/crates/mint-core/src/lib.rs +4 -0
  28. package/crates/mint-core/src/memory.rs +27 -1
  29. package/crates/mint-core/src/orchestration.rs +1 -1
  30. package/crates/mint-core/src/plugins.rs +32 -0
  31. package/crates/mint-core/tests/memory_persistence.rs +28 -0
  32. package/package.json +1 -1
  33. package/src/bin/index.js +0 -0
  34. package/src/renderer/src/agentProgress.ts +39 -0
  35. package/src/renderer/src/components/ChatPanel.tsx +547 -47
  36. package/src/renderer/src/components/DashboardSidebar.tsx +12 -4
  37. package/src/renderer/src/components/ImageStudioPanel.tsx +638 -0
  38. package/src/renderer/src/components/MintDashboard.tsx +84 -31
  39. package/src/renderer/src/components/ModelPanel.tsx +2 -2
  40. package/src/renderer/src/components/PicturesLibrary.tsx +5 -1
  41. package/src/renderer/src/components/SettingsWindow.tsx +29 -20
  42. package/src/renderer/src/components/SpotlightWindow.tsx +8 -8
  43. package/src/renderer/src/components/WorkspacePanel.tsx +1 -1
  44. package/src/renderer/src/css/image-studio.css +722 -0
  45. package/src/renderer/src/css/settings.css +13 -3
  46. package/src/renderer/src/css/styles.css +245 -43
  47. package/src/renderer/src/index.css +152 -0
  48. package/src/renderer/src/tauri.ts +148 -0
  49. package/src/renderer/src-web/App.tsx +16 -1
  50. package/src/renderer/src-web/agentProgress.ts +39 -0
  51. package/src/renderer/src-web/components/ChatPanel.tsx +568 -46
  52. package/src/renderer/src-web/components/DashboardSidebar.tsx +10 -2
  53. package/src/renderer/src-web/components/ImageStudioPanel.tsx +638 -0
  54. package/src/renderer/src-web/components/MintDashboard.tsx +65 -19
  55. package/src/renderer/src-web/components/PicturesLibrary.tsx +5 -1
  56. package/src/renderer/src-web/components/SettingsWindow.tsx +29 -20
  57. package/src/renderer/src-web/css/image-studio.css +722 -0
  58. package/src/renderer/src-web/css/settings.css +14 -4
  59. package/src/renderer/src-web/css/styles.css +292 -44
  60. package/src/renderer/src-web/index.css +152 -0
  61. package/src/renderer/src-web/tauri.ts +149 -0
  62. package/src-tauri/src/lib.rs +65 -5
  63. package/src-tauri/tauri.conf.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { type ChangeEvent, type FormEvent, useEffect, useRef, useState } from 'react'
2
+ import { mergeActivitySnapshots, trimAgentProgress } from '../agentProgress'
2
3
  import {
3
4
  clearChatHistory,
4
5
  deleteChatSession,
@@ -8,6 +9,7 @@ import {
8
9
  listChatSessions,
9
10
  listSavedPictures,
10
11
  selectWorkspaceDirectory,
12
+ saveInteractionAgentActivity,
11
13
  streamChatMessage,
12
14
  submitToolApproval,
13
15
  listen,
@@ -21,37 +23,38 @@ import {
21
23
  } from '../tauri'
22
24
  import ChatPanel from './ChatPanel'
23
25
  import DashboardSidebar, { type DashboardView } from './DashboardSidebar'
26
+ import ImageStudioPanel from './ImageStudioPanel'
24
27
  import ModelPanel from './ModelPanel'
25
28
  import type { ModelInteraction } from './ModelPanel'
26
29
  import PicturesLibrary from './PicturesLibrary'
27
30
  import WorkspacePanel from './WorkspacePanel'
28
31
 
29
32
  const EXPRESSIONS = [
30
- "ปกติ (Default)",
31
- "呆猫 (Dumb Cat)",
32
- "呆猫眼珠摇晃 (Dumb Cat Eye Roll)",
33
- "拍照 (Take Photo)",
34
- "点一下 (Poke)",
35
- "猫咪滤镜 (Cat Filter)",
33
+ "Default",
34
+ "Dumb Cat",
35
+ "Dumb Cat Eye Roll",
36
+ "Take Photo",
37
+ "Poke",
38
+ "Cat Filter",
36
39
  ]
37
40
 
38
41
  const ACCESSORIES = [
39
- "ปกติ (None)",
40
- "ผ้ากันเปื้อน (Apron)",
41
- "แว่นตา (Glasses)",
42
- "ท่าถือปากกา (Hold Pen)",
42
+ "None",
43
+ "Apron",
44
+ "Glasses",
45
+ "Hold Pen",
43
46
  ]
44
47
 
45
48
  const DEFAULT_CONFIG = {
46
49
  theme: 'dark',
47
- accentColor: '#4f83e6',
50
+ accentColor: '#10b981',
48
51
  systemTextColor: '#f8fafc',
49
52
  customBgStart: '#0f172a',
50
53
  customBgEnd: '#1e1b4b',
51
54
  customPanelBg: '#1e293b',
52
55
  glassBlur: 'blur(16px)',
53
56
  fontFamily: "'Outfit', sans-serif",
54
- fontSize: '15px',
57
+ fontSize: '18px',
55
58
  }
56
59
 
57
60
  const LAST_WORKSPACE_PATH_KEY = 'mint:last-workspace-path'
@@ -77,7 +80,7 @@ function activeConversationId() {
77
80
  const MOCK_WELCOME_INTERACTION = {
78
81
  id: -1,
79
82
  userText: '',
80
- aiText: `มิ้นท์กำลังรอสแตนด์บายเตรียมพร้อมช่วยคุณทีมอยู่เลยค่ะ! ✨ แล้วก็แอบนั่งจัดระเบียบข้อมูลนิดๆ หน่อยๆ ให้พร้อมใช้ด้วยค่ะ 😊💖\n\nแต่พอคุณทีมทักมา มิ้นท์ก็วางมือจากทุกอย่างมาคุยกับคุณทีมก่อนเลยนะคะค้าา! ช่วงนี้มีอะไรให้มิ้นท์ช่วยดูแล หรืออยากชวนคุยเรื่องไหนเป็นพิเศษไหมคะ มิ้นท์พร้อมมว๊ากกกค่ะ! 🚀🎯`,
83
+ aiText: `Hi there! I'm Mint, your AI assistant! 🎯✨ I'm here and ready to help you with whatever you need. I've been organizing some background data to make things smoother for you. 💖\n\nBut the moment you start chatting with me, I'll put everything aside and focus on you! Is there something I can help you with today, or would you like to chat about something special? Let's do this! 🚀💪`,
81
84
  provider: 'gemini',
82
85
  model: 'gemini-3-flash-preview',
83
86
  createdAt: new Date().toISOString(),
@@ -187,7 +190,7 @@ const applyThemeStyles = (cfg: any) => {
187
190
  document.documentElement.style.setProperty('--text-main', systemTextColor)
188
191
  document.documentElement.style.setProperty('--glass-blur', cfg.glassBlur || 'blur(16px)')
189
192
  document.body.style.fontFamily = cfg.fontFamily || "'Outfit', sans-serif"
190
- document.documentElement.style.fontSize = cfg.fontSize || '15px'
193
+ document.documentElement.style.fontSize = cfg.fontSize || '18px'
191
194
 
192
195
  if (theme === 'custom') {
193
196
  if (cfg.customBgStart && cfg.customBgEnd) {
@@ -232,8 +235,11 @@ export default function MintDashboard() {
232
235
  const [sendingImageCount, setSendingImageCount] = useState(0)
233
236
  const [streamedReply, setStreamedReply] = useState('')
234
237
  const [streamedResponse, setStreamedResponse] = useState<ChatResponse | null>(null)
238
+ const [streamingConversationId, setStreamingConversationId] = useState<string | null>(null)
235
239
  const [agentProgress, setAgentProgress] = useState<AgentProgress[]>([])
236
240
  const [agentActivitySnapshots, setAgentActivitySnapshots] = useState<Record<string, AgentProgress[]>>({})
241
+ const [thinkingExpanded, setThinkingExpanded] = useState<Record<string, boolean>>({})
242
+ const liveThinkingOpenRef = useRef(true)
237
243
  const [imageAttachments, setImageAttachments] = useState<Array<{ dataUri: string; name: string; previewDataUri?: string }>>([])
238
244
  const [documentAttachment, setDocumentAttachment] = useState<DocumentAttachment | null>(null)
239
245
  const [pendingApproval, setPendingApproval] = useState<any | null>(null)
@@ -263,7 +269,9 @@ export default function MintDashboard() {
263
269
 
264
270
  async function refreshHistory() {
265
271
  const history = await getRecentInteractions(50, conversationId)
266
- setInteractions(history.reverse())
272
+ const reversed = history.reverse()
273
+ setInteractions(reversed)
274
+ setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, reversed))
267
275
  }
268
276
 
269
277
  async function refreshChatSessions(nextActiveId = conversationId) {
@@ -285,8 +293,15 @@ export default function MintDashboard() {
285
293
  )
286
294
  }
287
295
 
296
+ const [picturesRefreshing, setPicturesRefreshing] = useState(false)
297
+
288
298
  async function refreshPictures() {
289
- setPictures(await listSavedPictures())
299
+ setPicturesRefreshing(true)
300
+ try {
301
+ setPictures(await listSavedPictures())
302
+ } finally {
303
+ setPicturesRefreshing(false)
304
+ }
290
305
  }
291
306
 
292
307
  useEffect(() => {
@@ -342,7 +357,7 @@ export default function MintDashboard() {
342
357
  }, [])
343
358
 
344
359
  useEffect(() => {
345
- if (view === 'pictures') refreshPictures().catch((reason: unknown) => setError(errorMessage(reason)))
360
+ if (view === 'pictures' || view === 'imagine') refreshPictures().catch((reason: unknown) => setError(errorMessage(reason)))
346
361
  }, [view])
347
362
 
348
363
  useEffect(() => {
@@ -444,12 +459,15 @@ export default function MintDashboard() {
444
459
  const outgoingImage = outgoingImages.map((img) => img.dataUri).join(' ')
445
460
  const outgoingImageCount = outgoingImages.length
446
461
  setSending(true)
462
+ setStreamingConversationId(conversationId)
447
463
  setSendingMessage(promptText)
448
464
  setSendingImageCount(outgoingImageCount)
449
465
  setError('')
450
466
  setStreamedReply('')
451
467
  setStreamedResponse(null)
452
468
  setAgentProgress([])
469
+ liveThinkingOpenRef.current = true
470
+ setThinkingExpanded((current) => ({ ...current, live: true }))
453
471
  const progressSnapshot: AgentProgress[] = []
454
472
  if (options.clearComposer) {
455
473
  setMessage('')
@@ -466,7 +484,7 @@ export default function MintDashboard() {
466
484
  options.systemInstruction ?? '',
467
485
  (progress) => {
468
486
  progressSnapshot.push(progress)
469
- setAgentProgress((current) => [...current, progress].slice(-24))
487
+ setAgentProgress((current) => trimAgentProgress([...current, progress]))
470
488
  },
471
489
  outgoingDocument,
472
490
  workspacePath || null,
@@ -474,18 +492,33 @@ export default function MintDashboard() {
474
492
  )
475
493
  setStreamedResponse(response)
476
494
  const history = (await getRecentInteractions(50, conversationId)).reverse()
495
+ let enrichedHistory = history
477
496
  if (progressSnapshot.length > 0) {
478
497
  const newestInteraction = [...history]
479
498
  .reverse()
480
499
  .find((interaction) => interaction.aiText === response.text || interaction.userText === promptText) ?? history[history.length - 1]
481
500
  if (newestInteraction?.id != null) {
501
+ const interactionKey = String(newestInteraction.id)
502
+ enrichedHistory = history.map((interaction) =>
503
+ interaction.id === newestInteraction.id
504
+ ? { ...interaction, agentActivity: progressSnapshot }
505
+ : interaction,
506
+ )
482
507
  setAgentActivitySnapshots((current) => ({
483
508
  ...current,
484
- [String(newestInteraction.id)]: progressSnapshot.slice(),
509
+ [interactionKey]: progressSnapshot.slice(),
485
510
  }))
511
+ if (liveThinkingOpenRef.current) {
512
+ setThinkingExpanded((current) => ({
513
+ ...current,
514
+ [interactionKey]: true,
515
+ }))
516
+ }
517
+ await saveInteractionAgentActivity(newestInteraction.id, progressSnapshot)
486
518
  }
487
519
  }
488
- setInteractions(history)
520
+ setInteractions(enrichedHistory)
521
+ setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, enrichedHistory))
489
522
  await refreshChatSessions()
490
523
  await refreshPictures()
491
524
  setStreamedReply('')
@@ -494,6 +527,7 @@ export default function MintDashboard() {
494
527
  setError(errorMessage(reason))
495
528
  } finally {
496
529
  setSending(false)
530
+ setStreamingConversationId(null)
497
531
  setSendingMessage('')
498
532
  setSendingImageCount(0)
499
533
  }
@@ -515,7 +549,7 @@ export default function MintDashboard() {
515
549
  }
516
550
 
517
551
  async function sendVoiceMessage(transcript: string, audioDataUri?: string | null) {
518
- const promptText = transcript.trim() || 'ข้อความเสียง'
552
+ const promptText = transcript.trim() || 'Voice message'
519
553
  if (!promptText || sending) return
520
554
  await sendPrompt(promptText, {
521
555
  audioDataUri,
@@ -677,6 +711,11 @@ export default function MintDashboard() {
677
711
  }
678
712
  }
679
713
 
714
+ function handleThinkingExpandedChange(key: string, open: boolean) {
715
+ if (key === 'live') liveThinkingOpenRef.current = open
716
+ setThinkingExpanded((current) => ({ ...current, [key]: open }))
717
+ }
718
+
680
719
  async function selectConversation(id: string) {
681
720
  if (id === conversationId) {
682
721
  setView('chat')
@@ -692,7 +731,9 @@ export default function MintDashboard() {
692
731
  setDocumentAttachment(null)
693
732
  setAgentProgress([])
694
733
  const history = await getRecentInteractions(50, id)
695
- setInteractions(history.reverse())
734
+ const reversed = history.reverse()
735
+ setInteractions(reversed)
736
+ setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, reversed))
696
737
  }
697
738
 
698
739
  async function deleteConversation(id: string) {
@@ -713,7 +754,9 @@ export default function MintDashboard() {
713
754
  setConversationId(nextActive)
714
755
  setAgentProgress([])
715
756
  const history = await getRecentInteractions(50, nextActive)
716
- setInteractions(history.reverse())
757
+ const reversed = history.reverse()
758
+ setInteractions(reversed)
759
+ setAgentActivitySnapshots((current) => mergeActivitySnapshots(current, reversed))
717
760
  }
718
761
 
719
762
  await refreshChatSessions(nextActive)
@@ -887,17 +930,19 @@ export default function MintDashboard() {
887
930
  />
888
931
  <ChatPanel
889
932
  interactions={interactions}
890
- sending={sending}
891
- sendingMessage={sendingMessage}
892
- sendingImageCount={sendingImageCount}
893
- streamedReply={streamedReply}
894
- streamedResponse={streamedResponse}
895
- agentProgress={agentProgress}
933
+ sending={sending && streamingConversationId === conversationId}
934
+ sendingMessage={streamingConversationId === conversationId ? sendingMessage : ''}
935
+ sendingImageCount={streamingConversationId === conversationId ? sendingImageCount : 0}
936
+ streamedReply={streamingConversationId === conversationId ? streamedReply : ''}
937
+ streamedResponse={streamingConversationId === conversationId ? streamedResponse : null}
938
+ agentProgress={streamingConversationId === conversationId ? agentProgress : []}
896
939
  agentActivitySnapshots={agentActivitySnapshots}
940
+ thinkingExpanded={thinkingExpanded}
941
+ onThinkingExpandedChange={handleThinkingExpandedChange}
897
942
  message={message}
898
943
  imageAttachments={imageAttachments}
899
944
  documentName={documentAttachment?.filename ?? ''}
900
- pendingApproval={pendingApproval}
945
+ pendingApproval={streamingConversationId === conversationId ? pendingApproval : null}
901
946
  smartContext={smartContext}
902
947
  agentMode={agentMode}
903
948
  status={status}
@@ -926,7 +971,15 @@ export default function MintDashboard() {
926
971
  onApproval={handleApproval}
927
972
  />
928
973
  </main>
929
- <PicturesLibrary view={view} pictures={pictures} onSetView={setView} />
974
+ <PicturesLibrary view={view} pictures={pictures} onSetView={setView} onRefreshPictures={refreshPictures} />
975
+ <ImageStudioPanel
976
+ view={view}
977
+ onRefreshPictures={refreshPictures}
978
+ onSendToChat={(_url, imgPrompt) => {
979
+ setView('chat')
980
+ setMessage(imgPrompt)
981
+ }}
982
+ />
930
983
  </div>
931
984
  <div className={`startup-loading ${startupReady ? 'is-hidden' : ''}`} aria-live="polite" aria-busy={!startupReady}>
932
985
  <div className="startup-loading-content">
@@ -98,13 +98,13 @@ export default function ModelPanel({
98
98
  </svg>
99
99
  </button>
100
100
  <div className="layout-preset-group">
101
- <button className={`layout-preset-btn ${layoutPreset === 'chat-wide' ? 'is-active' : ''}`} onClick={() => onChangeLayoutPreset('chat-wide')} title="ขยายหน้าต่างแชท (ย่อโมเดล)">
101
+ <button className={`layout-preset-btn ${layoutPreset === 'chat-wide' ? 'is-active' : ''}`} onClick={() => onChangeLayoutPreset('chat-wide')} title="Expand chat panel (minimize model)">
102
102
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
103
103
  <rect x="3" y="3" width="18" height="18" rx="2" />
104
104
  <path d="M9 3v18" />
105
105
  </svg>
106
106
  </button>
107
- <button className={`layout-preset-btn ${layoutPreset === 'model-wide' ? 'is-active' : ''}`} onClick={() => onChangeLayoutPreset('model-wide')} title="ขยายหน้าต่างโมเดล (ย่อแชท)">
107
+ <button className={`layout-preset-btn ${layoutPreset === 'model-wide' ? 'is-active' : ''}`} onClick={() => onChangeLayoutPreset('model-wide')} title="Expand model panel (minimize chat)">
108
108
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
109
109
  <rect x="3" y="3" width="18" height="18" rx="2" />
110
110
  <path d="M15 3v18" />
@@ -5,9 +5,10 @@ interface PicturesLibraryProps {
5
5
  view: DashboardView
6
6
  pictures: PictureEntry[]
7
7
  onSetView: (view: DashboardView) => void
8
+ onRefreshPictures?: () => Promise<void>
8
9
  }
9
10
 
10
- export default function PicturesLibrary({ view, pictures, onSetView }: PicturesLibraryProps) {
11
+ export default function PicturesLibrary({ view, pictures, onSetView, onRefreshPictures }: PicturesLibraryProps) {
11
12
  if (view !== 'pictures') return null
12
13
 
13
14
  return (
@@ -16,6 +17,9 @@ export default function PicturesLibrary({ view, pictures, onSetView }: PicturesL
16
17
  <div><span className="pictures-kicker">Gallery</span><h2>Saved Pictures</h2></div>
17
18
  <div className="pictures-header-actions">
18
19
  <button className="pictures-close-btn" onClick={() => onSetView('chat')}>Close Gallery</button>
20
+ <button type="button" className="picture-refresh-btn" title="Refresh" onClick={() => onRefreshPictures?.()}>
21
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.13-3.36L23 10"/><path d="M20.49 15a9 9 0 0 1-14.13 3.36L1 14"/></svg>
22
+ </button>
19
23
  <button type="button" className="picture-folder-btn" disabled={pictures.length === 0} onClick={() => window.settingsApi?.openFolder(pictures[0]?.path || '')}>
20
24
  Open Folder
21
25
  </button>
@@ -3,14 +3,14 @@ import { getProfileValue, setProfileValue } from '../tauri'
3
3
 
4
4
  const DEFAULT_CONFIG = {
5
5
  theme: 'dark',
6
- accentColor: '#4f83e6',
6
+ accentColor: '#10b981',
7
7
  systemTextColor: '#f8fafc',
8
8
  customBgStart: '#0f172a',
9
9
  customBgEnd: '#1e1b4b',
10
10
  customPanelBg: '#1e293b',
11
11
  glassBlur: 'blur(16px)',
12
12
  fontFamily: "'Outfit', sans-serif",
13
- fontSize: '15px',
13
+ fontSize: '18px',
14
14
  apiKey: '',
15
15
  aiProvider: 'gemini',
16
16
  geminiModel: 'gemini-2.5-flash',
@@ -143,6 +143,8 @@ const OLLAMA_MODELS = [
143
143
  'qwen2.5:latest'
144
144
  ]
145
145
 
146
+
147
+
146
148
  export default function SettingsWindow() {
147
149
  const [activeTab, setActiveTab] = useState<TabType>('sect-general')
148
150
  const [config, setConfig] = useState(DEFAULT_CONFIG)
@@ -169,6 +171,8 @@ export default function SettingsWindow() {
169
171
  const [updateMessage, setUpdateMessage] = useState('')
170
172
  const [updateAvailable, setUpdateAvailable] = useState(false)
171
173
 
174
+
175
+
172
176
  // Load settings on mount
173
177
  useEffect(() => {
174
178
  async function loadSettings() {
@@ -942,24 +946,28 @@ export default function SettingsWindow() {
942
946
  <div className="form-grid single">
943
947
  <div className="setting-row">
944
948
  <label>Your Name / Nickname</label>
945
- <input
946
- type="text"
947
- value={userName}
948
- onChange={(e) => setUserName(e.target.value)}
949
- placeholder="e.g. Pheem, Jane"
950
- />
951
- <p className="hint">Used by the assistant to address you in conversation.</p>
949
+ <div className="memory-field-container">
950
+ <input
951
+ type="text"
952
+ value={userName}
953
+ onChange={(e) => setUserName(e.target.value)}
954
+ placeholder="e.g. Pheem, Jane"
955
+ />
956
+ <p className="hint">Used by the assistant to address you in conversation.</p>
957
+ </div>
952
958
  </div>
953
959
 
954
960
  <div className="setting-row">
955
961
  <label>Custom Instructions & Preferences</label>
956
- <textarea
957
- value={userPreferences}
958
- onChange={(e) => setUserPreferences(e.target.value)}
959
- placeholder="e.g. Explain coding concepts step-by-step. Prefer TypeScript. Talk in Thai. Keep explanations concise."
960
- style={{ minHeight: '150px', resize: 'vertical' }}
961
- />
962
- <p className="hint">Preferences, guidelines, or persona instructions for the assistant.</p>
962
+ <div className="memory-field-container">
963
+ <textarea
964
+ value={userPreferences}
965
+ onChange={(e) => setUserPreferences(e.target.value)}
966
+ placeholder="e.g. Explain coding concepts step-by-step. Prefer TypeScript. Talk in Thai. Keep explanations concise."
967
+ style={{ minHeight: '150px', resize: 'vertical' }}
968
+ />
969
+ <p className="hint">Preferences, guidelines, or persona instructions for the assistant.</p>
970
+ </div>
963
971
  </div>
964
972
  </div>
965
973
  </section>
@@ -1342,10 +1350,11 @@ export default function SettingsWindow() {
1342
1350
  <div className="setting-row">
1343
1351
  <label>Font Size</label>
1344
1352
  <select value={config.fontSize} onChange={(e) => updateField('fontSize', e.target.value)}>
1345
- <option value="14px">Small</option>
1346
- <option value="15px">Medium (Default)</option>
1347
- <option value="16px">Large</option>
1348
- <option value="17px">Extra Large</option>
1353
+ <option value="16px">Small</option>
1354
+ <option value="18px">Medium (Default)</option>
1355
+ <option value="22px">Large</option>
1356
+ <option value="26px">Extra Large</option>
1357
+ <option value="30px">Extra Extra Large</option>
1349
1358
  </select>
1350
1359
  </div>
1351
1360
  </div>
@@ -2,14 +2,14 @@ import React, { useState, useEffect, useRef } from 'react'
2
2
  import { evaluateArithmetic } from '../calculator'
3
3
 
4
4
  const COMMANDS = [
5
- { label: 'Open YouTube', desc: 'เปิดเว็บไซต์ YouTube', icon: '📺', action: { type: 'open_url', target: 'https://youtube.com' } },
6
- { label: 'Open Facebook', desc: 'เปิดเว็บไซต์ Facebook', icon: '📘', action: { type: 'open_url', target: 'https://facebook.com' } },
7
- { label: 'Open Instagram', desc: 'เปิดเว็บไซต์ Instagram', icon: '📸', action: { type: 'open_url', target: 'https://instagram.com' } },
8
- { label: 'Open GitHub', desc: 'เปิดเว็บไซต์ GitHub', icon: '🐙', action: { type: 'open_url', target: 'https://github.com' } },
9
- { label: 'System Info', desc: 'ดูข้อมูลระบบ', icon: '💻', action: { type: 'chat', query: 'ขอข้อมูลระบบหน่อย' } },
10
- { label: 'Weather', desc: 'เช็คสภาพอากาศ', icon: '🌤️', action: { type: 'chat', query: 'อากาศที่กรุงเทพเป็นยังไง' } },
11
- { label: 'Open Spotify', desc: 'เปิดโปรแกรม Spotify', icon: '🎵', action: { type: 'open_app', target: 'spotify' } },
12
- { label: 'Open VS Code', desc: 'เปิดโปรแกรม VS Code', icon: '💻', action: { type: 'open_app', target: 'code' } },
5
+ { label: 'Open YouTube', desc: 'Open YouTube website', icon: '📺', action: { type: 'open_url', target: 'https://youtube.com' } },
6
+ { label: 'Open Facebook', desc: 'Open Facebook website', icon: '📘', action: { type: 'open_url', target: 'https://facebook.com' } },
7
+ { label: 'Open Instagram', desc: 'Open Instagram website', icon: '📸', action: { type: 'open_url', target: 'https://instagram.com' } },
8
+ { label: 'Open GitHub', desc: 'Open GitHub website', icon: '🐙', action: { type: 'open_url', target: 'https://github.com' } },
9
+ { label: 'System Info', desc: 'Show system information', icon: '💻', action: { type: 'chat', query: 'Show me system information' } },
10
+ { label: 'Weather', desc: 'Check the weather', icon: '🌤️', action: { type: 'chat', query: 'What is the current weather' } },
11
+ { label: 'Open Spotify', desc: 'Open Spotify app', icon: '🎵', action: { type: 'open_app', target: 'spotify' } },
12
+ { label: 'Open VS Code', desc: 'Open VS Code app', icon: '💻', action: { type: 'open_app', target: 'code' } },
13
13
  ]
14
14
 
15
15
  function getCommandIcon(iconName: string) {
@@ -221,7 +221,7 @@ export default function WorkspacePanel({ agentMode, sending, workspacePath, onEn
221
221
 
222
222
  const startWorkspacePrompt = () => {
223
223
  onEnableAgentMode()
224
- onSetMessage('ดู workspace นี้แล้วช่วยวางแผนงานต่อไปให้หน่อย')
224
+ onSetMessage('Review this workspace and help plan next steps')
225
225
  }
226
226
 
227
227
  return (