@pheem49/mint 1.5.5 → 1.6.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 (222) hide show
  1. package/.codex +0 -0
  2. package/.github/FUNDING.yml +2 -0
  3. package/.github/workflows/ci.yml +45 -0
  4. package/.github/workflows/release.yml +79 -0
  5. package/Cargo.lock +5792 -0
  6. package/Cargo.toml +32 -0
  7. package/README.md +387 -353
  8. package/assets/icon.png +0 -0
  9. package/bin/mint +0 -0
  10. package/crates/mint-cli/Cargo.toml +23 -0
  11. package/crates/mint-cli/src/agent.rs +851 -0
  12. package/crates/mint-cli/src/gmail.rs +216 -0
  13. package/crates/mint-cli/src/image.rs +142 -0
  14. package/crates/mint-cli/src/main.rs +2837 -0
  15. package/crates/mint-cli/src/mcp.rs +63 -0
  16. package/crates/mint-cli/src/onboard.rs +1149 -0
  17. package/crates/mint-cli/src/setup.rs +390 -0
  18. package/crates/mint-cli/src/skills.rs +8 -0
  19. package/crates/mint-cli/src/updater.rs +279 -0
  20. package/crates/mint-core/Cargo.toml +22 -0
  21. package/crates/mint-core/src/agent_loop.rs +94 -0
  22. package/crates/mint-core/src/api_server.rs +991 -0
  23. package/crates/mint-core/src/channels.rs +248 -0
  24. package/crates/mint-core/src/chat.rs +895 -0
  25. package/crates/mint-core/src/code_tools.rs +729 -0
  26. package/crates/mint-core/src/config.rs +368 -0
  27. package/crates/mint-core/src/files.rs +159 -0
  28. package/crates/mint-core/src/knowledge.rs +541 -0
  29. package/crates/mint-core/src/lib.rs +84 -0
  30. package/crates/mint-core/src/mcp.rs +273 -0
  31. package/crates/mint-core/src/memory.rs +673 -0
  32. package/crates/mint-core/src/orchestration.rs +2157 -0
  33. package/crates/mint-core/src/pictures.rs +314 -0
  34. package/crates/mint-core/src/plugins.rs +727 -0
  35. package/crates/mint-core/src/safety.rs +416 -0
  36. package/crates/mint-core/src/semantic.rs +254 -0
  37. package/crates/mint-core/src/shell.rs +317 -0
  38. package/crates/mint-core/src/skills.rs +71 -0
  39. package/crates/mint-core/src/symbols.rs +157 -0
  40. package/crates/mint-core/src/tasks.rs +308 -0
  41. package/crates/mint-core/src/tts.rs +92 -0
  42. package/crates/mint-core/src/weather.rs +93 -0
  43. package/crates/mint-core/src/web_search.rs +200 -0
  44. package/crates/mint-core/src/workflows.rs +81 -0
  45. package/crates/mint-core/tests/mcp_stdio.rs +45 -0
  46. package/crates/mint-core/tests/memory_persistence.rs +172 -0
  47. package/crates/mint-core/tests/pictures_storage.rs +14 -0
  48. package/crates/mint-core/tests/task_lifecycle.rs +87 -0
  49. package/package.json +35 -99
  50. package/src/bin/index.js +16 -0
  51. package/src/renderer/index-web.html +17 -0
  52. package/src/renderer/index.html +17 -0
  53. package/src/renderer/public/Live2DCubismCore.js +9 -0
  54. package/src/renderer/public/assets/icon.png +0 -0
  55. package/src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.model3.json +36 -0
  56. package/src/renderer/src/App.tsx +33 -0
  57. package/src/renderer/src/calculator.ts +47 -0
  58. package/src/renderer/src/components/ChatPanel.tsx +1598 -0
  59. package/src/renderer/src/components/DashboardSidebar.tsx +358 -0
  60. package/src/renderer/src/components/Live2DStage.tsx +374 -0
  61. package/src/renderer/src/components/MintDashboard.tsx +950 -0
  62. package/src/renderer/src/components/ModelPanel.tsx +154 -0
  63. package/src/renderer/src/components/PicturesLibrary.tsx +46 -0
  64. package/src/renderer/src/components/ProactiveGlow.tsx +19 -0
  65. package/src/renderer/src/components/ScreenPicker.tsx +579 -0
  66. package/src/renderer/src/components/SettingsWindow.tsx +1467 -0
  67. package/src/renderer/src/components/SpotlightWindow.tsx +280 -0
  68. package/src/renderer/src/components/WidgetWindow.tsx +36 -0
  69. package/src/renderer/src/components/WorkspacePanel.tsx +268 -0
  70. package/src/{UI → renderer/src/css}/settings.css +69 -16
  71. package/src/renderer/src/css/spotlight.css +113 -0
  72. package/src/renderer/src/css/styles.css +3722 -0
  73. package/src/renderer/src/css/widget.css +185 -0
  74. package/src/renderer/src/env.d.ts +116 -0
  75. package/src/renderer/src/index.css +379 -0
  76. package/src/renderer/src/main.tsx +13 -0
  77. package/src/renderer/src/tauri.ts +996 -0
  78. package/src/renderer/src-web/App.tsx +25 -0
  79. package/src/renderer/src-web/calculator.ts +47 -0
  80. package/src/renderer/src-web/components/ChatPanel.tsx +1662 -0
  81. package/src/renderer/src-web/components/DashboardSidebar.tsx +242 -0
  82. package/src/renderer/src-web/components/MintDashboard.tsx +763 -0
  83. package/src/renderer/src-web/components/PicturesLibrary.tsx +73 -0
  84. package/src/renderer/src-web/components/SettingsWindow.tsx +1500 -0
  85. package/src/renderer/src-web/css/settings.css +1100 -0
  86. package/src/{UI → renderer/src-web/css}/spotlight.css +4 -4
  87. package/src/{UI → renderer/src-web/css}/styles.css +1055 -159
  88. package/src/{UI → renderer/src-web/css}/widget.css +2 -2
  89. package/src/renderer/src-web/env.d.ts +107 -0
  90. package/src/renderer/src-web/index.css +379 -0
  91. package/src/renderer/src-web/main.tsx +13 -0
  92. package/src/renderer/src-web/tauri.ts +983 -0
  93. package/tsconfig.json +30 -0
  94. package/vite.config.ts +33 -0
  95. package/vite.config.web.ts +51 -0
  96. package/GUIDE_TH.md +0 -125
  97. package/assets/Agent_Mint.png +0 -0
  98. package/assets/CLI_Screen.png +0 -0
  99. package/assets/Settings.png +0 -0
  100. package/benchmark_ai.js +0 -71
  101. package/install.ps1 +0 -64
  102. package/install.sh +0 -54
  103. package/main.js +0 -139
  104. package/mint-cli-logic.js +0 -3
  105. package/mint-cli.js +0 -410
  106. package/models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.model3.json +0 -47
  107. package/models/Shiroko_Model/Shiroko//342/232/241/351/253/230/344/272/256/342/232/241/344/275/277/347/224/250/346/225/231/347/250/213/344/270/216/346/263/250/346/204/217/344/272/213/351/241/271.txt +0 -23
  108. package/preload-picker.js +0 -11
  109. package/preload-settings.js +0 -11
  110. package/preload.js +0 -41
  111. package/scripts/install_linux_desktop_entry.js +0 -48
  112. package/src/AI_Brain/Gemini_API.js +0 -813
  113. package/src/AI_Brain/agent_orchestrator.js +0 -73
  114. package/src/AI_Brain/autonomous_brain.js +0 -179
  115. package/src/AI_Brain/behavior_memory.js +0 -135
  116. package/src/AI_Brain/headless_agent.js +0 -143
  117. package/src/AI_Brain/knowledge_base.js +0 -349
  118. package/src/AI_Brain/memory_store.js +0 -662
  119. package/src/AI_Brain/proactive_engine.js +0 -172
  120. package/src/AI_Brain/provider_adapter.js +0 -365
  121. package/src/Automation_Layer/browser_automation.js +0 -149
  122. package/src/Automation_Layer/file_operations.js +0 -286
  123. package/src/Automation_Layer/open_app.js +0 -85
  124. package/src/Automation_Layer/open_website.js +0 -38
  125. package/src/CLI/approval_handler.js +0 -47
  126. package/src/CLI/chat_router.js +0 -247
  127. package/src/CLI/chat_ui.js +0 -1159
  128. package/src/CLI/cli_colors.js +0 -115
  129. package/src/CLI/cli_formatters.js +0 -94
  130. package/src/CLI/code_agent.js +0 -1667
  131. package/src/CLI/code_session_memory.js +0 -62
  132. package/src/CLI/gmail_auth.js +0 -210
  133. package/src/CLI/image_input.js +0 -90
  134. package/src/CLI/intent_detectors.js +0 -181
  135. package/src/CLI/interactive_chat.js +0 -658
  136. package/src/CLI/list_features.js +0 -64
  137. package/src/CLI/onboarding.js +0 -416
  138. package/src/CLI/repo_summarizer.js +0 -282
  139. package/src/CLI/semantic_code_search.js +0 -312
  140. package/src/CLI/skill_manager.js +0 -41
  141. package/src/CLI/slash_command_handler.js +0 -418
  142. package/src/CLI/symbol_indexer.js +0 -231
  143. package/src/CLI/updater.js +0 -230
  144. package/src/CLI/workspace_manager.js +0 -90
  145. package/src/Channels/brave_search_bridge.js +0 -35
  146. package/src/Channels/discord_bridge.js +0 -66
  147. package/src/Channels/google_search_bridge.js +0 -38
  148. package/src/Channels/line_bridge.js +0 -60
  149. package/src/Channels/slack_bridge.js +0 -48
  150. package/src/Channels/telegram_bridge.js +0 -41
  151. package/src/Channels/whatsapp_bridge.js +0 -57
  152. package/src/Command_Parser/parser.js +0 -45
  153. package/src/Plugins/dev_tools.js +0 -41
  154. package/src/Plugins/discord.js +0 -20
  155. package/src/Plugins/docker.js +0 -47
  156. package/src/Plugins/gmail.js +0 -251
  157. package/src/Plugins/google_calendar.js +0 -252
  158. package/src/Plugins/mcp_manager.js +0 -95
  159. package/src/Plugins/notion.js +0 -256
  160. package/src/Plugins/obsidian.js +0 -54
  161. package/src/Plugins/plugin_manager.js +0 -81
  162. package/src/Plugins/spotify.js +0 -173
  163. package/src/Plugins/system_metrics.js +0 -31
  164. package/src/Plugins/system_monitor.js +0 -72
  165. package/src/System/action_executor.js +0 -178
  166. package/src/System/bridge_manager.js +0 -76
  167. package/src/System/chat_history_manager.js +0 -83
  168. package/src/System/config_manager.js +0 -194
  169. package/src/System/custom_workflows.js +0 -163
  170. package/src/System/daemon_manager.js +0 -67
  171. package/src/System/google_tts_urls.js +0 -51
  172. package/src/System/granular_automation.js +0 -157
  173. package/src/System/ipc_handlers.js +0 -332
  174. package/src/System/notifications.js +0 -23
  175. package/src/System/optional_require.js +0 -23
  176. package/src/System/picture_store.js +0 -109
  177. package/src/System/proactive_loop.js +0 -153
  178. package/src/System/safety_manager.js +0 -273
  179. package/src/System/sandbox_runner.js +0 -182
  180. package/src/System/screen_capture.js +0 -175
  181. package/src/System/smart_context.js +0 -227
  182. package/src/System/system_automation.js +0 -162
  183. package/src/System/system_events.js +0 -79
  184. package/src/System/system_info.js +0 -125
  185. package/src/System/task_manager.js +0 -222
  186. package/src/System/tool_registry.js +0 -293
  187. package/src/System/window_manager.js +0 -220
  188. package/src/UI/floating.css +0 -80
  189. package/src/UI/floating.html +0 -17
  190. package/src/UI/floating.js +0 -67
  191. package/src/UI/live2d_manager.js +0 -600
  192. package/src/UI/preload-floating.js +0 -7
  193. package/src/UI/preload-spotlight.js +0 -11
  194. package/src/UI/preload-widget.js +0 -5
  195. package/src/UI/proactive-glow.html +0 -42
  196. package/src/UI/renderer.js +0 -2127
  197. package/src/UI/screenPicker.html +0 -214
  198. package/src/UI/screenPicker.js +0 -262
  199. package/src/UI/settings.html +0 -577
  200. package/src/UI/settings.js +0 -770
  201. package/src/UI/spotlight.html +0 -23
  202. package/src/UI/spotlight.js +0 -185
  203. package/src/UI/widget.html +0 -29
  204. package/src/UI/widget.js +0 -10
  205. /package/{models → src/renderer/public/models}/Shiroko_Model/Shiroko/Shiroko_Core/72d86db84cfa9730b894c241fd24c0db.png +0 -0
  206. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/233/264/350/243/231.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/apron.exp3.json} +0 -0
  207. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/214/253/345/222/252/346/273/244/351/225/234.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/catfilter.exp3.json} +0 -0
  208. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/202/271/344/270/200/344/270/213.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/click.exp3.json} +0 -0
  209. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/dazed.exp3.json} +0 -0
  210. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//345/221/206/347/214/253/347/234/274/347/217/240/346/221/207/346/231/203.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/dazedeyes.exp3.json} +0 -0
  211. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//347/234/274/351/225/234.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/glasses.exp3.json} +0 -0
  212. /package/{models → src/renderer/public/models}/Shiroko_Model/Shiroko/Shiroko_Core/items_pinned_to_model.json +0 -0
  213. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//346/213/277/347/254/224.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/pen.exp3.json} +0 -0
  214. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//346/213/215/347/205/247.exp3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/photo.exp3.json} +0 -0
  215. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_00.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_00.png} +0 -0
  216. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_01.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_01.png} +0 -0
  217. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_02.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_02.png} +0 -0
  218. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.4096/texture_03.png" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.4096/texture_03.png} +0 -0
  219. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.cdi3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.cdi3.json} +0 -0
  220. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.moc3" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.moc3} +0 -0
  221. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.physics3.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.physics3.json} +0 -0
  222. /package/{models/Shiroko_Model/Shiroko/Shiroko_Core//351/235/242/351/245/2740.vtube.json" → src/renderer/public/models/Shiroko_Model/Shiroko/Shiroko_Core/shiroko.vtube.json} +0 -0
@@ -1,600 +0,0 @@
1
- /**
2
- * Live2DManager - Encapsulates Live2D model loading, fitting, and lip-sync logic.
3
- */
4
- window.Live2DManager = {
5
- app: null,
6
- model: null,
7
- resizeObserver: null,
8
- lipSyncInterval: null,
9
- expIndex: 0,
10
- interactionEnabled: true,
11
- interactionStorageKey: 'mint-model-interaction-enabled',
12
- accessoryStorageKey: 'mint-live2d-accessories',
13
- activeAccessories: {},
14
- accessoryOrder: ['glasses', 'pen', 'cat'],
15
- accessoryParams: {
16
- glasses: { paramId: 'Param96', label: 'Glasses' },
17
- pen: { paramId: 'Param68', label: 'Pen' },
18
- cat: { paramId: 'Param54', label: 'Cat Filter' }
19
- },
20
- pointerTrackingEnabled: true,
21
- zoomMultiplier: 1,
22
- interactionZoneOrigin: { x: 0.5, y: 0.58 },
23
- fitModelToMount: null,
24
- pointerTrackingFrame: null,
25
- pointerTracking: {
26
- targetX: 0,
27
- targetY: 0,
28
- currentX: 0,
29
- currentY: 0,
30
- lastMoveAt: 0
31
- },
32
- pointerTrackingConfig: {
33
- focusX: 0.35,
34
- focusY: 0.35,
35
- rangeX: 0.35,
36
- rangeY: 0.35,
37
- smoothing: 0.18
38
- },
39
- baseModelPosition: null,
40
- lastInteractionAt: 0,
41
- expressionToastTimeout: null,
42
- expressionParamIds: [
43
- 'Param54',
44
- 'Param55',
45
- 'Param68',
46
- 'Param76',
47
- 'Param91',
48
- 'Param93',
49
- 'Param94',
50
- 'Param96',
51
- 'ParamAngleY',
52
- 'ParamAngleZ',
53
- 'ParamEyeBallX',
54
- 'ParamEyeBallY',
55
- 'ParamMouthForm',
56
- 'ParamMouthOpenY'
57
- ],
58
- expressionNames: [
59
- { id: null, label: 'Normal' },
60
- { id: 'Apron', label: 'Apron' },
61
- { id: 'Dazed', label: 'Dazed' },
62
- { id: 'Photo', label: 'Photo' },
63
- { id: 'Glasses', label: 'Glasses' },
64
- { id: 'Pen', label: 'Writing' },
65
- { id: 'Click', label: 'Blush' },
66
- { id: 'CatFilter', label: 'Cat Ears' },
67
- { id: 'DazedEyes', label: 'Dazed Eyes' }
68
- ],
69
-
70
- async loadModel(mountEl, statusEl, shellEl) {
71
- this.statusEl = statusEl; // Store for later use
72
- this.interactionEnabled = this.getSavedInteractionEnabled();
73
- this.activeAccessories = this.getSavedAccessories();
74
- if (!mountEl) return;
75
- if (statusEl) {
76
- statusEl.classList.remove('is-error');
77
- statusEl.innerHTML = `
78
- <div class="loader-dots">
79
- <span></span><span></span><span></span>
80
- </div>
81
- <div style="font-size: 0.7rem; opacity: 0.8; letter-spacing: 0.05em;">SYNCHRONIZING MINT...</div>
82
- `;
83
- }
84
- if (!window.PIXI || !window.PIXI.live2d) {
85
- const message = 'Live2D runtime is not available.';
86
- console.error(message);
87
- if (statusEl) {
88
- statusEl.classList.add('is-error');
89
- statusEl.textContent = message;
90
- }
91
- return;
92
- }
93
-
94
- try {
95
- window.PIXI.live2d.Live2DModel.registerTicker(window.PIXI.Ticker);
96
-
97
- this.app = new window.PIXI.Application({
98
- autoDensity: true,
99
- antialias: true,
100
- backgroundAlpha: 0,
101
- resizeTo: mountEl,
102
- resolution: window.devicePixelRatio || 1
103
- });
104
-
105
- mountEl.prepend(this.app.view);
106
-
107
- const modelUrl = new URL('../../models/Shiroko_Model/Shiroko/Shiroko_Core/%E9%9D%A2%E9%A5%BC0.model3.json', window.location.href).href;
108
- this.model = await window.PIXI.live2d.Live2DModel.from(modelUrl, {
109
- autoInteract: false
110
- });
111
- this.expressionToastEl = document.getElementById('expression-toast');
112
-
113
- this.model.anchor.set(0.5, 0.5);
114
- this.app.stage.addChild(this.model);
115
-
116
- // -- Interaction Setup --
117
- this.setInteractionEnabled(this.interactionEnabled);
118
- this.setupPointerTracking(mountEl);
119
- this.applyAccessories();
120
-
121
- // Tap Interaction. This model does not define Cubism HitAreas, so use
122
- // normalized model coordinates to provide stable region reactions.
123
- this.model.on('pointertap', (e) => this.handleModelTap(e));
124
- this.model.on('hit', (hitAreaNames) => {
125
- console.log(`[Live2D] Runtime hit detected: ${hitAreaNames}`);
126
- });
127
-
128
- const fitModel = () => {
129
- if (!this.model || !mountEl) return;
130
- const mountWidth = mountEl.clientWidth || 460;
131
- const mountHeight = mountEl.clientHeight || 620;
132
- this.app.renderer.resize(mountWidth, mountHeight);
133
-
134
- const internal = this.model.internalModel || {};
135
- const modelWidth = internal.width || internal.originalWidth || this.model.width || 1;
136
- const modelHeight = internal.height || internal.originalHeight || this.model.height || 1;
137
- const widthScale = mountWidth / Math.max(modelWidth, 1);
138
- const heightScale = mountHeight / Math.max(modelHeight, 1);
139
-
140
- // Reduced zoom to 2.0 as requested
141
- const scale = Math.min(widthScale, heightScale) * 1.85 * this.zoomMultiplier;
142
-
143
- this.model.scale.set(scale);
144
- // Adjusted Y offset to 1.0 as requested
145
- this.baseModelPosition = {
146
- x: mountWidth / 2,
147
- y: mountHeight / 2 + mountHeight * 0.55
148
- };
149
- this.applyModelFollowOffset();
150
- };
151
- this.fitModelToMount = fitModel;
152
-
153
- requestAnimationFrame(() => {
154
- fitModel();
155
- requestAnimationFrame(fitModel);
156
- });
157
- this.resizeObserver = new ResizeObserver(fitModel);
158
- this.resizeObserver.observe(mountEl);
159
-
160
- shellEl?.classList.add('is-live2d-ready');
161
- if (statusEl) statusEl.textContent = '';
162
- this.model.motion('Idle', 0).catch(() => {});
163
- } catch (error) {
164
- console.error('Failed to load Live2D model:', error);
165
- shellEl?.classList.remove('is-live2d-ready');
166
- if (statusEl) {
167
- statusEl.classList.add('is-error');
168
- statusEl.textContent = `Live2D failed: ${error && error.message ? error.message : String(error)}`;
169
- }
170
- }
171
- },
172
-
173
- showStatus(text, duration = 2000) {
174
- if (!this.statusEl) return;
175
- this.statusEl.textContent = text;
176
- this.statusEl.style.opacity = '1';
177
-
178
- if (this.statusTimeout) clearTimeout(this.statusTimeout);
179
- this.statusTimeout = setTimeout(() => {
180
- this.statusEl.style.opacity = '0';
181
- setTimeout(() => {
182
- if (this.statusEl.style.opacity === '0') this.statusEl.textContent = '';
183
- }, 500);
184
- }, duration);
185
- },
186
-
187
- handleModelTap(event) {
188
- if (!this.model || !this.interactionEnabled) return;
189
-
190
- const now = Date.now();
191
- if (now - this.lastInteractionAt < 3000) return;
192
-
193
- const region = this.getInteractionRegion(event);
194
- if (!region) return;
195
- this.lastInteractionAt = now;
196
- const expressionId = region.expression || 'Click';
197
-
198
- console.log(`[Live2D] Interaction: ${region.id}`, region);
199
- this.applyExpression(expressionId);
200
- this.showStatus(region.label, 2500);
201
-
202
- window.dispatchEvent(new CustomEvent('live2d-model-interaction', {
203
- detail: {
204
- region: region.id,
205
- label: region.label,
206
- prompt: region.prompt
207
- }
208
- }));
209
-
210
- setTimeout(() => {
211
- const currentIdx = this.expIndex === 0 ? 0 : this.expIndex;
212
- const prevExp = this.expressionNames[currentIdx]?.id;
213
- this.applyExpression(prevExp);
214
- }, 2000);
215
- },
216
-
217
- getInteractionRegion(event) {
218
- try {
219
- const point = this.getPointerViewportPoint(event);
220
- if (!point) return null;
221
- const { x, y } = this.toInteractionZonePoint(point);
222
-
223
- if (this.isPointInZone(x, y, 0.36, 0.375, 0.28, 0.12)) {
224
- return {
225
- id: 'face',
226
- label: 'Cat Ears',
227
- expression: 'CatFilter',
228
- prompt: 'The user poked Mint model on the cheek. Reply briefly, shyly or with a light tease. Use the same language as the user’s recent conversation; do not switch to Thai unless the user has been speaking Thai.'
229
- };
230
- }
231
-
232
- if (this.isPointInZone(x, y, 0.34, 0.205, 0.32, 0.155)) {
233
- return {
234
- id: 'head',
235
- label: 'Head Pat',
236
- expression: 'Dazed',
237
- prompt: 'The user patted Mint model on the head. Reply briefly in a cute, slightly shy way. Use the same language as the user’s recent conversation; do not switch to Thai unless the user has been speaking Thai.'
238
- };
239
- }
240
-
241
- const isLeftHand = this.isPointInZone(x, y, 0.14, 0.70, 0.22, 0.16);
242
- const isRightHand = this.isPointInZone(x, y, 0.65, 0.69, 0.23, 0.17);
243
- if (isLeftHand || isRightHand) {
244
- return {
245
- id: isLeftHand ? 'left-hand' : 'right-hand',
246
- label: 'Hand Tap',
247
- expression: 'Pen',
248
- prompt: 'The user tapped Mint model’s hand. Reply briefly as if ready to help or take a request. Use the same language as the user’s recent conversation; do not switch to Thai unless the user has been speaking Thai.'
249
- };
250
- }
251
-
252
- if (this.isPointInZone(x, y, 0.34, 0.74, 0.30, 0.24)) {
253
- return {
254
- id: 'lower-body',
255
- label: 'Careful',
256
- expression: 'Photo',
257
- prompt: 'The user touched the lower body area of Mint model. Reply briefly in a shy, playful way, similar to “hehe~ what are you playing at, that makes me blush,” then gently invite the user back to chatting or work. Use the same language as the user’s recent conversation; do not switch to Thai unless the user has been speaking Thai.'
258
- };
259
- }
260
-
261
- if (this.isPointInZone(x, y, 0.36, 0.53, 0.29, 0.145)) {
262
- return {
263
- id: 'body',
264
- label: 'Shoulder Tap',
265
- expression: 'Click',
266
- prompt: 'The user tapped Mint model’s body or shoulder. Reply briefly as if turning toward the user and asking what they need help with. Use the same language as the user’s recent conversation; do not switch to Thai unless the user has been speaking Thai.'
267
- };
268
- }
269
-
270
- return null;
271
- } catch (error) {
272
- console.error('[Live2D] Failed to resolve interaction region:', error);
273
- return null;
274
- }
275
- },
276
-
277
- getPointerViewportPoint(event) {
278
- const originalEvent = event?.data?.originalEvent;
279
- const rect = this.app?.view?.getBoundingClientRect?.();
280
- if (originalEvent && rect) {
281
- return {
282
- x: (originalEvent.clientX - rect.left) / Math.max(rect.width, 1),
283
- y: (originalEvent.clientY - rect.top) / Math.max(rect.height, 1)
284
- };
285
- }
286
-
287
- const globalPoint = event?.data?.global;
288
- const screen = this.app?.screen;
289
- if (!globalPoint || !screen) return null;
290
- return {
291
- x: globalPoint.x / Math.max(screen.width, 1),
292
- y: globalPoint.y / Math.max(screen.height, 1)
293
- };
294
- },
295
-
296
- isPointInZone(x, y, left, top, width, height) {
297
- return x >= left && x <= left + width && y >= top && y <= top + height;
298
- },
299
-
300
- toInteractionZonePoint(point) {
301
- const scale = this.zoomMultiplier || 1;
302
- if (Math.abs(scale - 1) < 0.001) return point;
303
-
304
- const origin = this.interactionZoneOrigin;
305
- return {
306
- x: origin.x + (point.x - origin.x) / scale,
307
- y: origin.y + (point.y - origin.y) / scale
308
- };
309
- },
310
-
311
- cycleExpression() {
312
- if (!this.model) return;
313
- this.expIndex = (this.expIndex + 1) % this.expressionNames.length;
314
- const nextExp = this.expressionNames[this.expIndex];
315
-
316
- console.log(`[Live2D] Triggering expression: ${nextExp.id} (${nextExp.label})`);
317
- this.applyExpression(nextExp.id);
318
-
319
- this.showStatus(nextExp.label);
320
- this.showExpressionToast(`Expression: ${nextExp.label}`);
321
- },
322
-
323
- setInteractionEnabled(isEnabled, persist = false) {
324
- this.interactionEnabled = Boolean(isEnabled);
325
- if (persist) {
326
- this.saveInteractionEnabled(this.interactionEnabled);
327
- }
328
- if (!this.model) return;
329
-
330
- this.model.interactive = this.interactionEnabled;
331
- this.model.buttonMode = this.interactionEnabled;
332
- },
333
-
334
- setPointerTrackingEnabled(isEnabled) {
335
- this.pointerTrackingEnabled = Boolean(isEnabled);
336
- if (this.pointerTrackingEnabled) return;
337
-
338
- this.resetPointerTrackingTarget();
339
- this.pointerTracking.currentX = 0;
340
- this.pointerTracking.currentY = 0;
341
- this.applyModelFollowOffset();
342
- },
343
-
344
- setZoomMultiplier(multiplier) {
345
- const value = Number(multiplier);
346
- this.zoomMultiplier = this.clamp(Number.isFinite(value) ? value : 1, 0.78, 1.28);
347
- document.documentElement.style.setProperty('--model-zone-scale', String(this.zoomMultiplier));
348
- if (typeof this.fitModelToMount === 'function') {
349
- this.fitModelToMount();
350
- }
351
- },
352
-
353
- getSavedInteractionEnabled() {
354
- try {
355
- return localStorage.getItem(this.interactionStorageKey) !== 'false';
356
- } catch (_) {
357
- return true;
358
- }
359
- },
360
-
361
- saveInteractionEnabled(isEnabled) {
362
- try {
363
- localStorage.setItem(this.interactionStorageKey, String(Boolean(isEnabled)));
364
- } catch (_) {}
365
- },
366
-
367
- setupPointerTracking(mountEl) {
368
- if (!mountEl) return;
369
-
370
- window.addEventListener('mousemove', (event) => this.updatePointerTrackingTarget(event, mountEl));
371
-
372
- if (!this.pointerTrackingFrame) {
373
- this.pointerTrackingFrame = () => this.updatePointerTracking();
374
- this.app?.ticker?.add(this.pointerTrackingFrame);
375
- }
376
- },
377
-
378
- updatePointerTrackingTarget(event, mountEl) {
379
- if (!this.pointerTrackingEnabled || !mountEl) return;
380
-
381
- const rect = {
382
- left: 0,
383
- top: 0,
384
- width: window.innerWidth || mountEl.getBoundingClientRect().width,
385
- height: window.innerHeight || mountEl.getBoundingClientRect().height
386
- };
387
- const config = this.pointerTrackingConfig;
388
- const centerX = rect.left + rect.width * config.focusX;
389
- const centerY = rect.top + rect.height * config.focusY;
390
- const rangeX = Math.max(rect.width * config.rangeX, 1);
391
- const rangeY = Math.max(rect.height * config.rangeY, 1);
392
-
393
- this.pointerTracking.targetX = this.clamp((event.clientX - centerX) / rangeX, -1, 1);
394
- this.pointerTracking.targetY = this.clamp((event.clientY - centerY) / rangeY, -1, 1);
395
- this.pointerTracking.lastMoveAt = performance.now();
396
- },
397
-
398
- resetPointerTrackingTarget() {
399
- this.pointerTracking.targetX = 0;
400
- this.pointerTracking.targetY = 0;
401
- },
402
-
403
- updatePointerTracking() {
404
- if (!this.model || !this.pointerTrackingEnabled) return;
405
-
406
- const tracking = this.pointerTracking;
407
- const smoothing = this.pointerTrackingConfig.smoothing;
408
- tracking.currentX += (tracking.targetX - tracking.currentX) * smoothing;
409
- tracking.currentY += (tracking.targetY - tracking.currentY) * smoothing;
410
-
411
- const x = tracking.currentX;
412
- const y = tracking.currentY;
413
- const core = this.model?.internalModel?.coreModel;
414
- if (!core) return;
415
-
416
- this.setLive2DParam(core, 'ParamAngleX', x * 18);
417
- this.setLive2DParam(core, 'ParamAngleY', -y * 14);
418
- this.setLive2DParam(core, 'ParamAngleZ', -x * 5);
419
- this.setLive2DParam(core, 'ParamEyeBallX', x * 1.45);
420
- this.setLive2DParam(core, 'ParamEyeBallY', -y * 1.35);
421
- this.setLive2DParam(core, 'Param49', x * 7);
422
- this.setLive2DParam(core, 'Param51', -y * 5);
423
- this.setLive2DParam(core, 'Param50', -x * 3);
424
- this.applyModelFollowOffset();
425
- },
426
-
427
- applyModelFollowOffset() {
428
- if (!this.model || !this.baseModelPosition) return;
429
-
430
- const x = this.pointerTracking.currentX || 0;
431
- const y = this.pointerTracking.currentY || 0;
432
- this.model.position.set(
433
- this.baseModelPosition.x + x * 22,
434
- this.baseModelPosition.y + y * 16
435
- );
436
- },
437
-
438
- setLive2DParam(core, id, value) {
439
- try {
440
- core.setParameterValueById(id, value);
441
- } catch (_) {}
442
- },
443
-
444
- clamp(value, min, max) {
445
- return Math.max(min, Math.min(max, value));
446
- },
447
-
448
- showExpressionToast(text, duration = 1600) {
449
- const toast = this.expressionToastEl || document.getElementById('expression-toast');
450
- if (!toast) return;
451
-
452
- this.expressionToastEl = toast;
453
- toast.textContent = text;
454
- toast.classList.add('is-visible');
455
-
456
- if (this.expressionToastTimeout) clearTimeout(this.expressionToastTimeout);
457
- this.expressionToastTimeout = setTimeout(() => {
458
- toast.classList.remove('is-visible');
459
- }, duration);
460
- },
461
-
462
- applyExpression(expressionId) {
463
- if (!this.model) return;
464
-
465
- this.resetExpressionParams();
466
- if (!expressionId) {
467
- this.clearExpressionState();
468
- return;
469
- }
470
-
471
- try {
472
- this.model.expression(expressionId);
473
- requestAnimationFrame(() => this.applyAccessories());
474
- } catch (error) {
475
- console.error(`[Live2D] Failed to apply expression: ${expressionId}`, error);
476
- }
477
- },
478
-
479
- resetExpressionParams() {
480
- const core = this.model?.internalModel?.coreModel;
481
- if (!core) return;
482
-
483
- this.expressionParamIds.forEach(id => {
484
- try { core.setParameterValueById(id, 0); } catch (_) {}
485
- });
486
- },
487
-
488
- clearExpressionState() {
489
- const expressionManager =
490
- this.model?.internalModel?.motionManager?.expressionManager ||
491
- this.model?.internalModel?.expressionManager;
492
-
493
- try {
494
- if (expressionManager?.defaultExpression) {
495
- expressionManager.currentExpression = expressionManager.defaultExpression;
496
- expressionManager.reserveExpressionIndex = -1;
497
- expressionManager.resetExpression();
498
- } else {
499
- this.model.expression(null);
500
- }
501
- } catch (error) {
502
- console.error('[Live2D] Failed to clear expression state:', error);
503
- }
504
-
505
- this.resetExpressionParams();
506
- requestAnimationFrame(() => {
507
- this.resetExpressionParams();
508
- this.applyAccessories();
509
- });
510
- },
511
-
512
- setAccessory(accessoryId, isEnabled, persist = false) {
513
- if (!this.accessoryParams[accessoryId]) return;
514
-
515
- this.activeAccessories[accessoryId] = Boolean(isEnabled);
516
- if (persist) {
517
- this.saveAccessories();
518
- }
519
- this.applyAccessory(accessoryId);
520
- },
521
-
522
- setExclusiveAccessory(accessoryId, persist = false) {
523
- const nextAccessoryId = this.accessoryParams[accessoryId] ? accessoryId : null;
524
- Object.keys(this.accessoryParams).forEach(id => {
525
- this.activeAccessories[id] = id === nextAccessoryId;
526
- });
527
- if (persist) {
528
- this.saveAccessories();
529
- }
530
- this.applyAccessories();
531
- return nextAccessoryId;
532
- },
533
-
534
- getActiveAccessoryId() {
535
- return this.accessoryOrder.find(id => this.activeAccessories[id]) || null;
536
- },
537
-
538
- applyAccessories() {
539
- Object.keys(this.accessoryParams).forEach(accessoryId => {
540
- this.applyAccessory(accessoryId);
541
- });
542
- },
543
-
544
- applyAccessory(accessoryId) {
545
- const accessory = this.accessoryParams[accessoryId];
546
- const core = this.model?.internalModel?.coreModel;
547
- if (!accessory || !core) return;
548
-
549
- this.setLive2DParam(core, accessory.paramId, this.activeAccessories[accessoryId] ? 1 : 0);
550
- },
551
-
552
- getSavedAccessories() {
553
- try {
554
- return JSON.parse(localStorage.getItem(this.accessoryStorageKey) || '{}') || {};
555
- } catch (_) {
556
- return {};
557
- }
558
- },
559
-
560
- saveAccessories() {
561
- try {
562
- localStorage.setItem(this.accessoryStorageKey, JSON.stringify(this.activeAccessories));
563
- } catch (_) {}
564
- },
565
-
566
- startLipSync() {
567
- if (!this.model || this.lipSyncInterval) return;
568
-
569
- this.model.motion('Speak', 0).catch(() => {});
570
-
571
- this.lipSyncInterval = setInterval(() => {
572
- if (!this.model) return;
573
- const value = Math.random() * 0.8;
574
- if (this.model.internalModel && this.model.internalModel.coreModel) {
575
- const core = this.model.internalModel.coreModel;
576
- const mouthIds = ['ParamMouthOpenY', 'ParamMouthOpen', 'PARAM_MOUTH_OPEN_Y'];
577
- mouthIds.forEach(id => {
578
- try { core.setParameterValueById(id, value); } catch(e) {}
579
- });
580
- }
581
- }, 80);
582
- },
583
-
584
- stopLipSync() {
585
- if (this.lipSyncInterval) {
586
- clearInterval(this.lipSyncInterval);
587
- this.lipSyncInterval = null;
588
- }
589
- if (this.model) {
590
- if (this.model.internalModel && this.model.internalModel.coreModel) {
591
- const core = this.model.internalModel.coreModel;
592
- const mouthIds = ['ParamMouthOpenY', 'ParamMouthOpen', 'PARAM_MOUTH_OPEN_Y'];
593
- mouthIds.forEach(id => {
594
- try { core.setParameterValueById(id, 0); } catch(e) {}
595
- });
596
- }
597
- this.model.motion('Idle', 0).catch(() => {});
598
- }
599
- }
600
- };
@@ -1,7 +0,0 @@
1
- const { contextBridge, ipcRenderer } = require('electron');
2
-
3
- contextBridge.exposeInMainWorld('floating', {
4
- onNotify: (callback) => ipcRenderer.on('floating-notify', (_event, count) => callback(count)),
5
- openMain: () => ipcRenderer.send('floating-click'),
6
- dragMove: (x, y) => ipcRenderer.send('floating-drag-move', x, y)
7
- });
@@ -1,11 +0,0 @@
1
- const { contextBridge, ipcRenderer } = require('electron');
2
-
3
- contextBridge.exposeInMainWorld('spotlightAPI', {
4
- submit: (query) => ipcRenderer.send('spotlight-submit', query),
5
- executeAction: (action) => ipcRenderer.invoke('spotlight-action', action),
6
- close: () => ipcRenderer.send('spotlight-close'),
7
- hide: () => ipcRenderer.send('spotlight-hide'),
8
- resize: (width, height) => ipcRenderer.send('spotlight-resize', width, height),
9
- getSettings: () => ipcRenderer.invoke('get-settings'),
10
- onSettingsChanged: (callback) => ipcRenderer.on('settings-changed', (event, config) => callback(config))
11
- });
@@ -1,5 +0,0 @@
1
- const { contextBridge, ipcRenderer } = require('electron');
2
-
3
- contextBridge.exposeInMainWorld('widgetAPI', {
4
- onStateChange: (callback) => ipcRenderer.on('widget-state', (event, state) => callback(state))
5
- });
@@ -1,42 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Proactive Glow</title>
7
- <style>
8
- body, html {
9
- margin: 0;
10
- padding: 0;
11
- width: 100vw;
12
- height: 100vh;
13
- overflow: hidden;
14
- background: transparent;
15
- pointer-events: none;
16
- }
17
-
18
- .vision-glow {
19
- position: absolute;
20
- inset: 0;
21
- pointer-events: none;
22
- box-shadow: inset 0 0 120px rgba(139, 92, 246, 0.35);
23
- z-index: 100;
24
- animation: vision-pulse 3s ease-in-out infinite alternate;
25
- }
26
-
27
- @keyframes vision-pulse {
28
- from {
29
- box-shadow: inset 0 0 60px rgba(139, 92, 246, 0.15);
30
- opacity: 0.4;
31
- }
32
- to {
33
- box-shadow: inset 0 0 180px rgba(139, 92, 246, 0.45);
34
- opacity: 1;
35
- }
36
- }
37
- </style>
38
- </head>
39
- <body>
40
- <div class="vision-glow"></div>
41
- </body>
42
- </html>