Compare commits

...
17 Commits
Author SHA1 Message Date
LogiFlow 35437e2d51 chore: version 2.0.0.1 et télémétrie sans fausses valeurs (#8)
chore: version 2.0.0.1 (schéma correctif à quatre chiffres) et télémétrie sans fausses valeurs
2026-09-03 17:43:37 +02:00
Claude e2c67a5770 chore: hotfix versioning 2.0.0.1 and honest telemetry placeholders when the bridge is missing
- Version numbers gain a fourth hotfix component (2.0.0.1); the workflow maps it to the
  Windows file build number.
- The system panel shows dashes instead of 0% until real measurements arrive from the
  main process.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y
2026-09-03 15:43:19 +00:00
LogiFlow 050ae20773 fix: modèle Hermes par défaut et repli sans outils client (v2.0.2) (#7)
fix: modèle Hermes par défaut et repli sans outils client (v2.0.2)
2026-09-03 17:40:44 +02:00
Claude 2a471e11a4 fix: default Hermes model from /v1/models and retry chat completions without client tools on HTTP 400 (v2.0.2)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y
2026-09-03 15:40:21 +00:00
LogiFlow b5357c5abd fix: charger le pont Electron dans l'application installée (v2.0.1) (#6)
fix: charger le pont Electron dans l'application installée (v2.0.1)
2026-09-03 17:38:58 +02:00
Claude c73114eb0d fix: bundle the Electron preload so the sandboxed bridge loads in packaged builds (v2.0.1)
The preload script imported ../shared/ipc at runtime; sandboxed preloads cannot
require local modules, so window.eveflow was never exposed in the installed app
and every request fell back to browser fetch (Failed to fetch, LOCALHOST metrics).
Main and preload are now bundled with esbuild into single files in dist-electron/.

Also: explicit error banner when the bridge is missing inside Electron, and a more
precise connection test message (transport path, capabilities status).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y
2026-09-03 15:38:36 +00:00
LogiFlow e3d5ead652 ci: release automatique sur master quand la version n'est pas encore taguée (#5)
ci: release automatique sur master quand la version de package.json n'est pas encore taguée
2026-09-03 15:56:51 +02:00
Claude eec6d62c20 ci: release automatically when master carries an unreleased package.json version
On push to master the workflow now checks whether tag v<version> exists and,
if not, creates the tag and the GitHub release with the Windows installer.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y
2026-09-03 13:56:32 +00:00
LogiFlow 8ee34b9932 ci: publier la release Windows depuis un lancement manuel du workflow (#4)
ci: publier la release Windows depuis un lancement manuel du workflow
2026-09-03 15:55:56 +02:00
Claude acc50da44b ci: publish a GitHub release from workflow_dispatch using the package.json version
Tag pushes are not possible from every environment; a manual run of the
workflow now creates the v<version> tag and release itself.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y
2026-09-03 13:55:17 +00:00
LogiFlow 3690dedeb3 feat!: EveFlow 2.0.0 — HUD vocal JARVIS pour Hermes Agent (#3)
feat!: refonte complète — HUD vocal JARVIS pour Hermes Agent (v2.0.0)
2026-09-03 15:53:32 +02:00
Claude 127a2083a1 feat!: rebuild EveFlow as a JARVIS-style voice HUD for Hermes Agent (v2.0.0)
Complete rewrite of the application:

- Toolchain: Electron 44, Vite 8, React 19, TypeScript 5.9, Zustand, Vitest;
  main process rewritten in TypeScript (electron/), typed IPC contract (shared/),
  sandboxed renderer with webSecurity on and an HTTP/SSE proxy in the main process.
- Voice: AudioWorklet microphone capture at 16 kHz with adaptive energy VAD and
  auto-stop, WAV encoder, OpenAI-compatible STT, TTS queue with sentence-level
  streaming, prefetch and Web Audio playback feeding an analyser; hands-free mode,
  global push-to-talk hotkey, system-voice fallback.
- Hermes: full API client (capabilities, health, models, skills, toolsets,
  sessions, jobs) with automatic transport selection: runs API (SSE lifecycle,
  approvals, steer, stop) > sessions stream > chat completions with local tools;
  tolerant event normalisation; webhook receiver hardened (secret, size limit).
- UI: JARVIS arc-reactor core on Canvas 2D reacting to the real audio signal,
  holographic HUD layout (transcript, core, Hermes ops panel with tools/crons/
  skills/sessions/link tabs, telemetry), settings drawer, approval modals,
  compact floating widget, four themes, tray icon and global shortcuts.
- Removed the 3D Eve robot, three.js and legacy assets; migrated 1.x settings.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y
2026-09-03 13:40:59 +00:00
Michael 5217eee53a fix: downsample audio to 16kHz to prevent ASR 500 error, add permission check handler, and render errors in compact view (v1.0.8) 2026-06-08 20:44:31 +02:00
Michael 221bb7062c 1.0.7 2026-06-08 20:38:05 +02:00
Michael 57690962e1 fix: implement direct WAV recording to resolve transcription API media decoding errors 2026-06-08 20:37:57 +02:00
Michael cf52a610d4 1.0.6 2026-06-08 19:44:33 +02:00
Michael 3a52cf3ae0 fix: update default STT model to Qwen/Qwen3-ASR-0.6B and implement auto-migration of old values 2026-06-08 19:44:21 +02:00
240 changed files with 11589 additions and 85974 deletions

No files matched your search

+46 -27
View File
@@ -1,59 +1,78 @@
name: Windows EXE
name: Build
on:
push:
branches:
- main
- master
tags:
- "v*"
branches: [main, master]
tags: ["v*"]
pull_request:
workflow_dispatch:
permissions:
contents: write
jobs:
check:
name: Typecheck & tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run typecheck
- run: npm test
- run: npm run build:renderer
build-windows:
name: Build Windows installer
needs: check
if: github.event_name != 'pull_request'
runs-on: windows-latest
env:
CSC_IDENTITY_AUTO_DISCOVERY: "false"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: npm
- name: Install dependencies
run: npm ci
- name: Build app
run: npm run build
- name: Build Windows EXE
- run: npm ci
- name: Read version
id: ver
shell: bash
run: |
version=$(node -p "require('./package.json').version")
echo "version=$version" >> "$GITHUB_OUTPUT"
# Fourth component (hotfix number, e.g. 2.0.0.1) becomes the Windows file build number.
echo "build=$(echo "$version" | cut -d. -f4)" >> "$GITHUB_OUTPUT"
if git ls-remote --exit-code --tags origin "refs/tags/v$version" >/dev/null 2>&1; then
echo "released=true" >> "$GITHUB_OUTPUT"
else
echo "released=false" >> "$GITHUB_OUTPUT"
fi
- run: npm run build
- name: Package Windows EXE
run: npx electron-builder --win --publish never
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Windows artifact
uses: actions/upload-artifact@v4
BUILD_NUMBER: ${{ steps.ver.outputs.build }}
- uses: actions/upload-artifact@v4
with:
name: EveFlow-Windows-${{ github.ref_name }}
name: EveFlow-Windows-v${{ steps.ver.outputs.version }}
path: |
out/*.exe
out/*.exe.blockmap
out/latest.yml
if-no-files-found: error
- name: Publish GitHub release
if: startsWith(github.ref, 'refs/tags/v')
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/master' && steps.ver.outputs.released == 'false')
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.ver.outputs.version }}
name: EveFlow ${{ steps.ver.outputs.version }}
generate_release_notes: true
files: |
out/*.exe
out/*.exe.blockmap
+2
View File
@@ -1,6 +1,8 @@
node_modules/
dist/
dist-electron/
out/
.env
.env.local
*.log
.vite/
-72
View File
@@ -1,72 +0,0 @@
# Blender 4.5.5 LTS MTL File: 'None'
# www.blender.org
newmtl ArmLight
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_4a4a505db864ac4a_14.png
map_d tex1_128x128_m_2f869d05e999c94a_0.png
newmtl Eve
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_16x16_m_60d58f4141724929_14.png
newmtl Eye
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_32x32_m_cad406fa8385be70_14.png
map_d tex1_32x32_m_c8162c34352a09e2_0.png
newmtl HeadGun
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_128x128_m_87b2e2053969c2c1_14.png
newmtl Lights
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_b3ab82716f6eb03b_14.png
map_d tex1_128x128_e0ee4f7cd514a91a_0.png
newmtl UpperBody
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_7149b995a42d2f50_14.png
map_d tex1_128x128_m_164b500fe0940dee_0.png
newmtl Visor
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_499edc885bc97572_14.png
map_d tex1_128x128_m_f2552de8e9085d25_0.png
-16262
View File
File diff suppressed because it is too large. Load diff
-72
View File
@@ -1,72 +0,0 @@
# Blender 4.5.5 LTS MTL File: 'None'
# www.blender.org
newmtl ArmLight
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_4a4a505db864ac4a_14.png
map_d tex1_128x128_m_2f869d05e999c94a_0.png
newmtl Eve
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_16x16_m_60d58f4141724929_14.png
newmtl Eye
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_32x32_m_cad406fa8385be70_14.png
map_d tex1_32x32_m_c8162c34352a09e2_0.png
newmtl HeadGun
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_128x128_m_87b2e2053969c2c1_14.png
newmtl Lights
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_b3ab82716f6eb03b_14.png
map_d tex1_128x128_e0ee4f7cd514a91a_0.png
newmtl UpperBody
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_7149b995a42d2f50_14.png
map_d tex1_128x128_m_164b500fe0940dee_0.png
newmtl Visor
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_499edc885bc97572_14.png
map_d tex1_128x128_m_f2552de8e9085d25_0.png
-16262
View File
File diff suppressed because it is too large. Load diff
-12
View File
@@ -1,12 +0,0 @@
# Blender 4.5.5 LTS MTL File: 'None'
# www.blender.org
newmtl EVE_Diver
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_256x256_m_7f667e040dcfe4ee_14.png
-897
View File
@@ -1,897 +0,0 @@
# Blender 4.5.5 LTS
# www.blender.org
mtllib EVE_Diver.mtl
o EVE_Diver
v -0.452637 10.603516 0.262695
v -0.391113 11.027832 0.227050
v -0.453613 10.603516 -0.260255
v -0.392090 11.027832 -0.225098
v -0.000977 11.027832 -0.452149
v -0.000977 10.603516 -0.522950
v 0.452637 10.603516 -0.262696
v 0.391113 11.027832 -0.227052
v 0.453613 10.603516 0.260253
v 0.392090 11.027832 0.225097
v 0.000977 11.027832 0.452148
v 0.000977 10.603516 0.522948
v -0.452637 10.603516 0.262695
v -0.391113 11.027832 0.227050
v -0.391113 11.027832 0.227050
v -0.558594 11.027832 0.324218
v -0.392090 11.027832 -0.225098
v -0.560059 11.027832 -0.321778
v -0.001465 11.027832 -0.645997
v -0.000977 11.027832 -0.452149
v 0.558594 11.027832 -0.324220
v 0.391113 11.027832 -0.227052
v 0.392090 11.027832 0.225097
v 0.560059 11.027832 0.321777
v 0.000977 11.027832 0.452148
v 0.001465 11.027832 0.645995
v -0.391113 11.027832 0.227050
v -0.558594 11.027832 0.324218
v -0.646484 10.603516 0.374999
v -0.647949 10.603516 -0.372071
v -0.558594 11.027832 0.324218
v -0.560059 11.027832 -0.321778
v -0.001465 10.603516 -0.747559
v -0.001465 11.027832 -0.645997
v 0.646484 10.603516 -0.375001
v 0.558594 11.027832 -0.324220
v 0.647949 10.603516 0.372070
v 0.560059 11.027832 0.321777
v 0.001465 10.603516 0.747558
v 0.001465 11.027832 0.645995
v -0.646484 10.603516 0.374999
v -0.558594 11.027832 0.324218
v 0.679199 7.251953 2.741210
v 0.545410 7.251953 2.741210
v 0.679199 9.599609 2.741210
v 0.545410 9.599609 2.741210
v 0.545410 7.251953 2.741210
v 0.545410 7.104004 2.485351
v 0.545410 9.599609 2.741210
v 0.545410 9.747559 2.485351
v 0.679199 7.251953 2.741210
v 0.679199 9.599609 2.741210
v 0.679199 7.104004 2.485351
v 0.679199 9.747559 2.485351
v -0.551758 7.251953 2.741210
v -0.685547 7.251953 2.741210
v -0.551758 9.599609 2.741210
v -0.685547 9.599609 2.741210
v -0.685547 7.251953 2.741210
v -0.685547 7.104004 2.485351
v -0.685547 9.599609 2.741210
v -0.685547 9.747559 2.485351
v -0.551758 7.251953 2.741210
v -0.551758 9.599609 2.741210
v -0.551758 7.104004 2.485351
v -0.551758 9.747559 2.485351
v -2.088867 7.956543 2.741210
v -2.088867 8.090332 2.741210
v 2.083496 7.956543 2.741210
v 2.083496 8.090332 2.741210
v -2.088867 8.090332 2.741210
v -2.236816 8.090332 2.485351
v 2.083496 8.090332 2.741210
v 2.230957 8.090332 2.485351
v -2.236816 7.956543 2.485351
v -2.088867 7.956543 2.741210
v 2.230957 7.956543 2.485351
v 2.083496 7.956543 2.741210
v -1.899902 8.792969 2.741210
v -1.899902 8.926758 2.741210
v 1.867676 8.792969 2.741210
v 1.867676 8.926758 2.741210
v -2.043457 8.926758 2.485351
v 2.011719 8.926758 2.485351
v -1.899902 8.926758 2.741210
v 1.867676 8.926758 2.741210
v -2.043457 8.792969 2.485351
v -1.899902 8.792969 2.741210
v 2.011719 8.792969 2.485351
v 1.867676 8.792969 2.741210
v 0.258789 11.023438 0.413085
v 0.208984 11.023438 0.413085
v 0.258789 11.023438 -0.433106
v 0.208984 11.023438 -0.433106
v 0.208984 11.023438 0.413085
v 0.208984 10.927734 0.468261
v 0.208984 11.023438 -0.433106
v 0.208984 10.927734 -0.488282
v 0.258789 10.927734 0.468261
v 0.258789 11.023438 0.413085
v 0.258789 10.927734 -0.488282
v 0.258789 11.023438 -0.433106
v -0.208984 11.023438 0.413085
v -0.258789 11.023438 0.413085
v -0.208984 11.023438 -0.433106
v -0.258789 11.023438 -0.433106
v -0.258789 11.023438 0.413085
v -0.258789 10.927734 0.468261
v -0.258789 11.023438 -0.433106
v -0.258789 10.927734 -0.488282
v -0.208984 10.927734 0.468261
v -0.208984 11.023438 0.413085
v -0.208984 10.927734 -0.488282
v -0.208984 11.023438 -0.433106
v -0.423340 11.023438 0.249023
v -0.423340 11.023438 0.198730
v 0.423340 11.023438 0.249023
v 0.423340 11.023438 0.198730
v -0.423340 11.023438 0.198730
v -0.478516 10.927734 0.198730
v 0.423340 11.023438 0.198730
v 0.478516 10.927734 0.198730
v -0.478516 10.927734 0.249023
v -0.423340 11.023438 0.249023
v 0.478516 10.927734 0.249023
v 0.423340 11.023438 0.249023
v -0.423340 11.023438 -0.218751
v -0.423340 11.023438 -0.269044
v 0.423340 11.023438 -0.218751
v 0.423340 11.023438 -0.269044
v -0.423340 11.023438 -0.269044
v -0.478516 10.927734 -0.269044
v 0.423340 11.023438 -0.269044
v 0.478516 10.927734 -0.269044
v -0.478516 10.927734 -0.218751
v -0.423340 11.023438 -0.218751
v 0.478516 10.927734 -0.218751
v 0.423340 11.023438 -0.218751
v -2.616699 9.216797 -0.743653
v -2.589355 9.301758 -0.743653
v -2.616699 9.216797 0.763671
v -2.589355 9.301758 0.763671
v -2.427246 9.249023 -0.842286
v -2.427246 9.249023 0.862304
v -2.589355 9.301758 -0.743653
v -2.589355 9.301758 0.763671
v -2.454590 9.164062 -0.842286
v -2.616699 9.216797 -0.743653
v -2.454590 9.164062 0.862304
v -2.616699 9.216797 0.763671
v -2.498535 9.580078 -0.451661
v -2.498535 9.580078 -0.362305
v -2.965820 8.145996 -0.451661
v -2.965820 8.145996 -0.362305
v -2.498535 9.580078 -0.362305
v -2.306152 9.620605 -0.362305
v -2.965820 8.145996 -0.362305
v -2.834473 7.999512 -0.362305
v -2.498535 9.580078 -0.451661
v -2.965820 8.145996 -0.451661
v -2.306152 9.620605 -0.451661
v -2.834473 7.999512 -0.451661
v -2.498535 9.580078 0.381835
v -2.498535 9.580078 0.471191
v -2.965820 8.145996 0.381835
v -2.965820 8.145996 0.471191
v -2.498535 9.580078 0.471191
v -2.306152 9.620605 0.471191
v -2.965820 8.145996 0.471191
v -2.834473 7.999512 0.471191
v -2.498535 9.580078 0.381835
v -2.965820 8.145996 0.381835
v -2.306152 9.620605 0.381835
v -2.834473 7.999512 0.381835
v -2.875488 8.423828 -0.743653
v -2.847656 8.508789 -0.743653
v -2.875488 8.423828 0.763671
v -2.847656 8.508789 0.763671
v -2.685547 8.456055 -0.842286
v -2.685547 8.456055 0.862304
v -2.847656 8.508789 -0.743653
v -2.847656 8.508789 0.763671
v -2.713379 8.371094 -0.842286
v -2.875488 8.423828 -0.743653
v -2.713379 8.371094 0.862304
v -2.875488 8.423828 0.763671
v -2.073242 9.500488 -0.000001
v -2.496582 9.638184 -0.000001
v -2.203613 9.099609 0.729980
v -2.626953 9.237305 0.729980
v -2.464844 8.297363 0.729980
v -2.888672 8.435547 0.729980
v -3.019043 8.034668 -0.000001
v -2.595703 7.896484 -0.000001
v -2.464844 8.297363 -0.729981
v -2.888672 8.435547 -0.729981
v -2.626953 9.237305 -0.729981
v -2.203613 9.099609 -0.729981
v -2.496582 9.638184 -0.000001
v -2.073242 9.500488 -0.000001
v -2.384277 9.981934 -0.000001
v -2.571289 9.409180 1.042968
v -2.496582 9.638184 -0.000001
v -2.626953 9.237305 0.729980
v -2.944336 8.263672 1.042968
v -2.888672 8.435547 0.729980
v -3.019043 8.034668 -0.000001
v -3.130859 7.690918 -0.000001
v -2.944336 8.263672 -1.042969
v -2.888672 8.435547 -0.729981
v -2.626953 9.237305 -0.729981
v -2.571289 9.409180 -1.042969
v -2.496582 9.638184 -0.000001
v -2.384277 9.981934 -0.000001
v -2.384277 9.981934 -0.000001
v -1.960938 9.843750 -0.000001
v -2.571289 9.409180 1.042968
v -2.147949 9.270996 1.042968
v -2.944336 8.263672 1.042968
v -2.520996 8.125977 1.042968
v -3.130859 7.690918 -0.000001
v -2.707520 7.553223 -0.000001
v -2.520996 8.125977 -1.042969
v -2.944336 8.263672 -1.042969
v -2.147949 9.270996 -1.042969
v -2.571289 9.409180 -1.042969
v -1.960938 9.843750 -0.000001
v -2.384277 9.981934 -0.000001
v -0.002441 7.286621 2.763183
v 1.350586 7.427246 2.763183
v -0.002930 6.862793 2.763183
v 1.464355 7.033203 2.763183
v 1.913086 7.782227 2.763183
v 2.230957 7.576660 2.763183
v 2.329590 8.142578 2.763183
v 1.983398 8.178223 2.763183
v 1.899902 9.187988 2.763183
v 1.656738 8.949707 2.763183
v 0.970215 9.465332 2.763183
v 1.095703 9.812988 2.763183
v -0.011230 9.631836 2.763183
v -0.012695 10.007324 2.763183
v -1.093262 9.817383 2.763183
v -0.974609 9.467285 2.763183
v -1.904297 9.189941 2.763183
v -1.662109 8.950195 2.763183
v -2.018066 8.201172 2.763183
v -2.361328 8.206543 2.763183
v -1.955566 7.784668 2.763183
v -2.265137 7.564453 2.763183
v -1.471191 7.021484 2.763183
v -1.362793 7.415527 2.763183
v -0.002930 6.862793 2.763183
v -0.002441 7.286621 2.763183
v -0.002441 7.286621 2.763183
v -0.002441 7.286621 2.636718
v 1.350586 7.427246 2.763183
v 1.350586 7.427246 2.296386
v 1.913086 7.782227 2.763183
v 1.913086 7.782227 1.984374
v 1.983398 8.178223 2.763183
v 1.983398 8.178223 1.858886
v 1.656738 8.949707 1.864745
v 1.656738 8.949707 2.763183
v 0.970215 9.465332 1.988769
v 0.970215 9.465332 2.763183
v -0.011230 9.631836 2.031738
v -0.011230 9.631836 2.763183
v -0.974609 9.467285 2.763183
v -0.974609 9.467285 1.987792
v -1.662109 8.950195 2.763183
v -1.662109 8.950195 1.864745
v -2.018066 8.201172 2.763183
v -2.018066 8.201172 1.840820
v -1.955566 7.784668 1.954101
v -1.955566 7.784668 2.763183
v -1.362793 7.415527 2.291015
v -1.362793 7.415527 2.763183
v -0.002441 7.286621 2.636718
v -0.002441 7.286621 2.763183
v -0.002930 6.862793 2.763183
v 1.464355 7.033203 2.763183
v -0.002930 6.862793 2.444824
v 1.464355 7.033203 2.053710
v 2.230957 7.576660 2.763183
v 2.230957 7.576660 1.608886
v 2.329590 8.142578 2.763183
v 2.329590 8.142578 1.434081
v 1.899902 9.187988 1.435058
v 1.899902 9.187988 2.763183
v 1.095703 9.812988 1.594726
v 1.095703 9.812988 2.763183
v -0.012695 10.007324 1.650390
v -0.012695 10.007324 2.763183
v -1.093262 9.817383 2.763183
v -1.093262 9.817383 1.594238
v -1.904297 9.189941 2.763183
v -1.904297 9.189941 1.434081
v -2.361328 8.206543 2.763183
v -2.361328 8.206543 1.407226
v -2.265137 7.564453 1.582031
v -2.265137 7.564453 2.763183
v -1.471191 7.021484 2.047363
v -1.471191 7.021484 2.763183
v -0.002930 6.862793 2.444824
v -0.002930 6.862793 2.763183
v 2.621582 9.216797 0.743652
v 2.594238 9.301758 0.743652
v 2.621582 9.216797 -0.763673
v 2.594238 9.301758 -0.763673
v 2.432129 9.249023 0.842284
v 2.432129 9.249023 -0.862305
v 2.594238 9.301758 0.743652
v 2.594238 9.301758 -0.763673
v 2.459473 9.164062 0.842284
v 2.621582 9.216797 0.743652
v 2.459473 9.164062 -0.862305
v 2.621582 9.216797 -0.763673
v 2.503418 9.580078 0.451659
v 2.503418 9.580078 0.362304
v 2.970703 8.145996 0.451660
v 2.970703 8.145996 0.362304
v 2.503418 9.580078 0.362304
v 2.311035 9.620605 0.362304
v 2.970703 8.145996 0.362304
v 2.839355 7.999512 0.362304
v 2.503418 9.580078 0.451659
v 2.970703 8.145996 0.451660
v 2.311035 9.620605 0.451659
v 2.839355 7.999512 0.451660
v 2.503418 9.580078 -0.381837
v 2.503418 9.580078 -0.471192
v 2.970703 8.145996 -0.381837
v 2.970703 8.145996 -0.471192
v 2.503418 9.580078 -0.471192
v 2.311035 9.620605 -0.471192
v 2.970703 8.145996 -0.471192
v 2.839355 7.999512 -0.471192
v 2.503418 9.580078 -0.381837
v 2.970703 8.145996 -0.381837
v 2.311035 9.620605 -0.381837
v 2.839355 7.999512 -0.381837
v 2.880371 8.423828 0.743652
v 2.852539 8.508789 0.743652
v 2.880371 8.423828 -0.763673
v 2.852539 8.508789 -0.763673
v 2.690430 8.456055 0.842285
v 2.690430 8.456055 -0.862305
v 2.852539 8.508789 0.743652
v 2.852539 8.508789 -0.763673
v 2.718262 8.371094 0.842285
v 2.880371 8.423828 0.743652
v 2.718262 8.371094 -0.862305
v 2.880371 8.423828 -0.763673
v 2.073242 9.500488 -0.000001
v 2.496582 9.638184 -0.000001
v 2.203613 9.099609 -0.729981
v 2.626953 9.237305 -0.729981
v 2.464844 8.297363 -0.729981
v 2.888672 8.435547 -0.729981
v 3.019043 8.034668 -0.000001
v 2.595703 7.896484 -0.000001
v 2.464844 8.297363 0.729980
v 2.888672 8.435547 0.729980
v 2.626953 9.237305 0.729980
v 2.203613 9.099609 0.729980
v 2.496582 9.638184 -0.000001
v 2.073242 9.500488 -0.000001
v 2.384277 9.981934 -0.000001
v 2.571289 9.409180 -1.042969
v 2.496582 9.638184 -0.000001
v 2.626953 9.237305 -0.729981
v 2.944336 8.263672 -1.042969
v 2.888672 8.435547 -0.729981
v 3.019043 8.034668 -0.000001
v 3.130859 7.690918 -0.000001
v 2.944336 8.263672 1.042968
v 2.888672 8.435547 0.729980
v 2.626953 9.237305 0.729980
v 2.571289 9.409180 1.042968
v 2.496582 9.638184 -0.000001
v 2.384277 9.981934 -0.000001
v 2.384277 9.981934 -0.000001
v 1.960938 9.843750 -0.000001
v 2.571289 9.409180 -1.042969
v 2.147949 9.270996 -1.042969
v 2.944336 8.263672 -1.042969
v 2.520996 8.125977 -1.042969
v 3.130859 7.690918 -0.000001
v 2.707520 7.553223 -0.000001
v 2.520996 8.125977 1.042968
v 2.944336 8.263672 1.042968
v 2.147949 9.270996 1.042968
v 2.571289 9.409180 1.042968
v 1.960938 9.843750 -0.000001
v 2.384277 9.981934 -0.000001
vn 0.8519 -0.1656 -0.4969
vn 0.8573 -0.1652 0.4876
vn -0.1499 0.4734 0.8680
vn -0.3068 0.9518 -0.0000
vn -0.0000 -0.1657 0.9862
vn -0.8519 -0.1656 0.4969
vn -0.8518 -0.1656 0.4969
vn -0.8573 -0.1652 -0.4876
vn 0.1499 -0.4734 0.8680
vn -0.0000 -0.1657 -0.9862
vn 0.8518 -0.1656 -0.4969
vn -0.0000 1.0000 -0.0000
vn 0.3068 -0.9518 -0.0000
vn -0.8424 0.2283 0.4881
vn -0.8456 0.2292 -0.4821
vn 0.1500 -0.4735 -0.8680
vn -0.0000 0.2277 -0.9737
vn -0.0000 0.2278 -0.9737
vn 0.8424 0.2283 -0.4881
vn 0.8456 0.2292 0.4821
vn -0.0000 0.2277 0.9737
vn -0.0000 0.2278 0.9737
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.9518 0.3067 -0.0000
vn 0.3068 0.9518 -0.0000
vn 0.3067 0.9518 -0.0000
vn -0.3068 -0.9518 -0.0000
vn -0.3067 -0.9518 -0.0000
vn -0.9518 0.3068 -0.0000
vn -0.3093 -0.9510 -0.0000
vn -0.1499 -0.4734 -0.8680
vn 0.1499 0.4734 -0.8680
vn -0.1499 0.4734 -0.8680
vn 0.1499 0.4734 0.8680
vn -0.1499 -0.4734 0.8680
vn 0.9518 0.3068 -0.0000
vn -0.1500 -0.4735 0.8680
vn -0.3233 0.9463 -0.0000
vn -0.8284 0.5601 -0.0000
vn -0.9939 -0.1104 -0.0000
vn -0.7885 -0.6150 -0.0001
vn -0.7884 -0.6152 -0.0000
vn -0.3930 -0.9196 -0.0000
vn -0.0001 -1.0000 -0.0000
vn 0.3930 -0.9196 -0.0000
vn 0.3930 -0.9195 -0.0000
vn 0.7746 -0.6325 -0.0000
vn 0.7747 -0.6324 -0.0000
vn 0.9899 -0.1414 -0.0000
vn 0.9900 -0.1414 -0.0000
vn 0.8345 0.5510 -0.0000
vn 0.8344 0.5511 -0.0000
vn 0.3162 0.9487 -0.0000
vn 0.3163 0.9487 -0.0000
vn 0.3537 -0.9354 -0.0000
vn 0.1499 -0.4734 -0.8680
vn 0.3093 -0.9510 -0.0000
vn 0.8440 -0.5363 -0.0000
vn 0.9947 0.1026 -0.0000
vn 0.7953 0.6063 -0.0000
vn 0.7953 0.6062 -0.0000
vn 0.4025 0.9154 -0.0000
vn -0.0003 1.0000 -0.0000
vn -0.0002 1.0000 -0.0000
vn -0.4025 0.9154 -0.0000
vn -0.7817 0.6236 -0.0000
vn -0.7816 0.6237 -0.0000
vn -0.9899 0.1414 -0.0000
vn -0.8498 -0.5271 -0.0000
vn -0.8498 -0.5272 -0.0000
vn -0.3468 -0.9379 -0.0000
vn -0.3464 -0.9381 -0.0000
vn 0.9518 0.3067 -0.0000
vn -0.3067 0.9518 -0.0000
vn 0.3067 -0.9518 -0.0000
vt 0.669678 0.523682
vt 0.706604 0.486755
vt 0.679138 0.533142
vt 0.716064 0.496216
vt 0.935120 0.295105
vt 0.984192 0.245972
vt 0.992126 0.253906
vt 0.765320 0.447021
vt 0.755859 0.437500
vt 0.942993 0.302979
vt 0.805054 0.388306
vt 0.814575 0.397766
vt 0.854309 0.339050
vt 0.863770 0.348511
vt 0.886047 0.344177
vt 0.913025 0.299316
vt 0.903503 0.289795
vt 0.893921 0.352051
vt 0.952759 0.240601
vt 0.962280 0.250061
vt 0.688660 0.542664
vt 0.725586 0.505737
vt 0.836914 0.393250
vt 0.774780 0.456482
vt 0.824036 0.407227
vt 0.844849 0.401184
vt 0.873291 0.358032
vt 0.922485 0.308777
vt 0.971741 0.259583
vt 0.698120 0.552124
vt 0.735046 0.515198
vt 0.795776 0.450256
vt 0.784302 0.466003
vt 0.833557 0.416748
vt 0.882751 0.367493
vt 0.932007 0.318298
vt 0.981201 0.269043
vt 0.680115 0.534973
vt 0.974792 0.240295
vt 0.687317 0.542236
vt 0.982056 0.247498
vt 0.686523 0.552673
vt 0.992615 0.246643
vt 0.669617 0.535767
vt 0.975647 0.229736
vt 0.687134 0.541992
vt 0.981812 0.247253
vt 0.669067 0.535217
vt 0.975098 0.229187
vt 0.680359 0.535095
vt 0.975037 0.240417
vt 0.687012 0.541687
vt 0.981689 0.247070
vt 0.683594 0.533508
vt 0.970947 0.246094
vt 0.690063 0.539978
vt 0.977417 0.252563
vt 0.686218 0.551758
vt 0.989258 0.248718
vt 0.671753 0.537354
vt 0.974792 0.234314
vt 0.971130 0.267822
vt 0.698792 0.540161
vt 0.960083 0.256714
vt 0.687683 0.529053
vt 0.963684 0.239807
vt 0.670776 0.532715
vt 0.988037 0.264160
vt 0.695129 0.557068
vt 0.673828 0.524658
vt 0.722961 0.475586
vt 0.681763 0.532593
vt 0.730835 0.483521
vt 0.772034 0.426514
vt 0.779907 0.434448
vt 0.787842 0.442322
vt 0.829041 0.385315
vt 0.821106 0.377441
vt 0.746704 0.499329
vt 0.870178 0.328308
vt 0.878113 0.336243
vt 0.738770 0.491394
vt 0.927185 0.287170
vt 0.919312 0.279236
vt 0.976257 0.238098
vt 0.968384 0.230164
vt 0.689697 0.540527
vt 0.697571 0.548401
vt 0.705444 0.554871
vt 0.695496 0.544800
vt 0.731445 0.528870
vt 0.721497 0.518799
vt 0.757446 0.502869
vt 0.747498 0.492737
vt 0.764832 0.475403
vt 0.774780 0.485535
vt 0.790894 0.449402
vt 0.800842 0.459534
vt 0.826843 0.433472
vt 0.816895 0.423401
vt 0.852844 0.407471
vt 0.842896 0.397400
vt 0.868896 0.371399
vt 0.878845 0.381470
vt 0.894897 0.345337
vt 0.904846 0.355469
vt 0.930847 0.329468
vt 0.920959 0.319336
vt 0.948242 0.312073
vt 0.938293 0.302002
vt 0.964294 0.276001
vt 0.974243 0.286072
vt 0.990295 0.250000
vt 1.000244 0.260071
vt 0.696533 0.546326
vt 0.722595 0.520264
vt 0.748596 0.494263
vt 0.765991 0.476868
vt 0.791992 0.450867
vt 0.818054 0.424805
vt 0.844055 0.398804
vt 0.870117 0.372742
vt 0.896179 0.346741
vt 0.922180 0.320679
vt 0.939514 0.303345
vt 0.965576 0.277283
vt 0.991638 0.251282
vt 0.661072 0.510559
vt 0.687134 0.484497
vt 0.713135 0.458496
vt 0.730530 0.441101
vt 0.756531 0.415100
vt 0.782593 0.389038
vt 0.808594 0.363037
vt 0.834656 0.336975
vt 0.860657 0.310913
vt 0.886719 0.284912
vt 0.904053 0.267578
vt 0.930115 0.241516
vt 0.956116 0.215454
s 1
usemtl EVE_Diver
f 1/1/1 3/2/2 2/3/1
f 2/3/1 3/2/2 4/4/2
f 394/5/3 396/6/4 395/7/4
f 4/4/2 3/2/2 5/8/5
f 3/2/2 6/9/5 5/8/5
f 393/10/3 394/5/3 395/7/4
f 6/9/5 7/11/6 5/8/5
f 5/8/5 7/11/6 8/12/7
f 7/11/6 9/13/8 8/12/7
f 8/12/7 9/13/8 10/14/8
f 392/15/9 394/5/3 393/10/3
f 10/14/8 9/13/8 11/16/10
f 9/13/8 12/17/10 11/16/10
f 391/18/9 392/15/9 393/10/3
f 12/17/10 13/19/1 11/16/10
f 11/16/10 13/19/1 14/20/11
f 15/3/12 17/4/12 16/21/12
f 16/21/12 17/4/12 18/22/12
f 389/23/13 392/15/9 391/18/9
f 18/22/12 17/4/12 19/24/12
f 17/4/12 20/8/12 19/24/12
f 19/24/12 20/8/12 21/25/12
f 20/8/12 22/12/12 21/25/12
f 390/26/13 389/23/13 391/18/9
f 22/12/12 23/14/12 21/25/12
f 21/25/12 23/14/12 24/27/12
f 23/14/12 25/16/12 24/27/12
f 24/27/12 25/16/12 26/28/12
f 25/16/12 27/20/12 26/28/12
f 26/28/12 27/20/12 28/29/12
f 29/30/14 31/21/14 30/31/15
f 388/32/16 389/23/13 390/26/13
f 31/21/14 32/22/15 30/31/15
f 30/31/15 32/22/15 33/33/17
f 32/22/15 34/24/18 33/33/17
f 33/33/17 34/24/18 35/34/19
f 34/24/18 36/25/19 35/34/19
f 35/34/19 36/25/19 37/35/20
f 36/25/19 38/27/20 37/35/20
f 37/35/20 38/27/20 39/36/21
f 38/27/20 40/28/22 39/36/21
f 39/36/21 40/28/22 41/37/14
f 40/28/22 42/29/14 41/37/14
f 43/38/23 45/39/23 44/40/23
f 44/40/23 45/39/23 46/41/23
f 47/40/24 49/41/24 48/42/24
f 48/42/24 49/41/24 50/43/24
f 51/38/25 53/44/25 52/39/25
f 52/39/25 53/44/25 54/45/25
f 55/38/23 57/39/23 56/46/23
f 56/46/23 57/39/23 58/47/23
f 59/46/24 61/47/24 60/42/24
f 60/42/24 61/47/24 62/43/24
f 63/38/25 65/48/25 64/39/25
f 64/39/25 65/48/25 66/49/25
f 67/50/23 69/51/23 68/52/23
f 68/52/23 69/51/23 70/53/23
f 71/52/12 73/53/12 72/42/12
f 72/42/12 73/53/12 74/43/12
f 75/48/26 77/49/26 76/50/26
f 76/50/26 77/49/26 78/51/26
f 79/50/23 81/51/23 80/52/23
f 80/52/23 81/51/23 82/53/23
f 83/42/12 85/52/12 84/43/12
f 84/43/12 85/52/12 86/53/12
f 87/48/26 89/49/26 88/50/26
f 88/50/26 89/49/26 90/51/26
f 91/54/12 93/55/12 92/56/12
f 92/56/12 93/55/12 94/57/12
f 95/56/24 97/57/24 96/58/24
f 96/58/24 97/57/24 98/59/24
f 99/60/25 101/61/25 100/54/25
f 100/54/25 101/61/25 102/55/25
f 103/54/12 105/55/12 104/56/12
f 104/56/12 105/55/12 106/57/12
f 107/56/24 109/57/24 108/58/24
f 108/58/24 109/57/24 110/59/24
f 111/60/25 113/61/25 112/54/25
f 112/54/25 113/61/25 114/55/25
f 115/54/12 117/55/12 116/56/12
f 116/56/12 117/55/12 118/57/12
f 119/56/27 121/57/27 120/58/27
f 120/58/27 121/57/27 122/59/27
f 123/60/23 125/61/23 124/54/23
f 124/54/23 125/61/23 126/55/23
f 127/54/12 129/55/12 128/56/12
f 128/56/12 129/55/12 130/57/12
f 131/56/27 133/57/27 132/58/27
f 132/58/27 133/57/27 134/59/27
f 135/60/23 137/61/23 136/54/23
f 136/54/23 137/61/23 138/55/23
f 139/62/28 141/63/28 140/64/28
f 140/64/28 141/63/28 142/65/28
f 143/66/29 145/64/30 144/67/29
f 144/67/29 145/64/30 146/65/30
f 147/68/31 149/69/31 148/62/32
f 148/62/32 149/69/31 150/63/32
f 151/62/33 153/63/33 152/64/33
f 152/64/33 153/63/33 154/65/33
f 155/64/23 157/65/23 156/66/23
f 156/66/23 157/65/23 158/67/23
f 159/62/27 161/68/27 160/63/27
f 160/63/27 161/68/27 162/69/27
f 163/62/33 165/63/33 164/64/33
f 164/64/33 165/63/33 166/65/33
f 167/64/23 169/65/23 168/66/23
f 168/66/23 169/65/23 170/67/23
f 171/62/27 173/68/27 172/63/27
f 172/63/27 173/68/27 174/69/27
f 175/62/33 177/63/33 176/64/33
f 176/64/33 177/63/33 178/65/33
f 179/66/29 181/64/30 180/67/30
f 180/67/30 181/64/30 182/65/30
f 183/68/31 185/69/32 184/62/32
f 184/62/32 185/69/32 186/63/32
f 187/70/34 189/71/35 188/72/31
f 188/72/31 189/71/35 190/73/35
f 189/71/35 191/74/36 190/73/35
f 190/73/35 191/74/36 192/75/36
f 387/76/16 389/23/13 388/32/16
f 192/75/36 191/74/36 193/77/29
f 191/74/36 194/78/29 193/77/29
f 386/79/37 387/76/16 388/32/16
f 194/78/29 195/80/38 193/77/29
f 193/77/29 195/80/38 196/81/38
f 385/82/37 387/76/16 386/79/37
f 196/81/38 195/80/38 197/83/39
f 195/80/38 198/84/39 197/83/39
f 197/83/39 198/84/39 199/85/34
f 198/84/39 200/86/31 199/85/34
f 201/87/33 203/72/33 202/82/33
f 384/88/4 385/82/37 386/79/37
f 203/72/33 204/73/33 202/82/33
f 202/82/33 204/73/33 205/76/33
f 204/73/33 206/75/33 205/76/33
f 383/87/4 385/82/37 384/88/4
f 206/75/33 207/77/33 205/76/33
f 205/76/33 207/77/33 208/23/33
f 380/5/40 381/85/40 382/6/40
f 208/23/33 207/77/33 209/15/33
f 207/77/33 210/81/33 209/15/33
f 379/83/40 381/85/40 380/5/40
f 210/81/33 211/83/33 209/15/33
f 209/15/33 211/83/33 212/5/33
f 211/83/33 213/85/33 212/5/33
f 212/5/33 213/85/33 214/6/33
f 215/87/29 217/82/38 216/88/29
f 216/88/29 217/82/38 218/79/38
f 217/82/38 219/76/41 218/79/38
f 218/79/38 219/76/41 220/32/41
f 219/76/41 221/23/31 220/32/41
f 220/32/41 221/23/31 222/26/31
f 377/15/40 379/83/40 380/5/40
f 222/26/31 221/23/31 223/18/35
f 221/23/31 224/15/35 223/18/35
f 223/18/35 224/15/35 225/10/36
f 224/15/35 226/5/36 225/10/36
f 225/10/36 226/5/36 227/7/29
f 226/5/36 228/6/29 227/7/29
f 229/89/23 231/90/23 230/91/23
f 378/81/40 379/83/40 377/15/40
f 231/90/23 232/92/23 230/91/23
f 230/91/23 232/92/23 233/93/23
f 232/92/23 234/94/23 233/93/23
f 375/77/40 378/81/40 377/15/40
f 234/94/23 235/95/23 233/93/23
f 233/93/23 235/95/23 236/96/23
f 235/95/23 237/97/23 236/96/23
f 236/96/23 237/97/23 238/98/23
f 376/23/40 375/77/40 377/15/40
f 238/98/23 237/97/23 239/99/23
f 237/97/23 240/100/23 239/99/23
f 239/99/23 240/100/23 241/101/23
f 240/100/23 242/102/23 241/101/23
f 373/76/40 375/77/40 376/23/40
f 242/102/23 243/103/23 241/101/23
f 241/101/23 243/103/23 244/104/23
f 243/103/23 245/105/23 244/104/23
f 244/104/23 245/105/23 246/106/23
f 374/75/40 375/77/40 373/76/40
f 246/106/23 245/105/23 247/107/23
f 245/105/23 248/108/23 247/107/23
f 247/107/23 248/108/23 249/109/23
f 248/108/23 250/110/23 249/109/23
f 372/73/40 374/75/40 373/76/40
f 250/110/23 251/111/23 249/109/23
f 249/109/23 251/111/23 252/112/23
f 251/111/23 253/113/23 252/112/23
f 252/112/23 253/113/23 254/114/23
f 255/89/12 257/91/42 256/115/12
f 256/115/12 257/91/42 258/116/42
f 257/91/42 259/93/43 258/116/42
f 258/116/42 259/93/43 260/117/43
f 259/93/43 261/96/44 260/117/43
f 260/117/43 261/96/44 262/118/44
f 370/82/40 372/73/40 373/76/40
f 262/118/44 261/96/44 263/119/45
f 261/96/44 264/98/46 263/119/45
f 263/119/45 264/98/46 265/120/47
f 264/98/46 266/99/47 265/120/47
f 265/120/47 266/99/47 267/121/48
f 266/99/47 268/101/26 267/121/48
f 371/72/40 372/73/40 370/82/40
f 268/101/26 269/104/49 267/121/48
f 267/121/48 269/104/49 270/122/50
f 269/104/49 271/106/51 270/122/50
f 270/122/50 271/106/51 272/123/52
f 271/106/51 273/107/53 272/123/52
f 272/123/52 273/107/53 274/124/54
f 369/87/40 371/72/40 370/82/40
f 274/124/54 273/107/53 275/125/55
f 273/107/53 276/109/56 275/125/55
f 275/125/55 276/109/56 277/126/57
f 276/109/56 278/112/58 277/126/57
f 277/126/57 278/112/58 279/127/12
f 278/112/58 280/114/12 279/127/12
f 281/90/26 283/128/26 282/92/59
f 366/84/60 368/86/13 367/85/61
f 283/128/26 284/129/59 282/92/59
f 282/92/59 284/129/59 285/94/62
f 284/129/59 286/130/62 285/94/62
f 285/94/62 286/130/62 287/95/63
f 286/130/62 288/131/63 287/95/63
f 365/83/60 366/84/60 367/85/61
f 288/131/63 289/132/64 287/95/63
f 287/95/63 289/132/64 290/97/65
f 289/132/64 291/133/66 290/97/65
f 290/97/65 291/133/66 292/100/66
f 291/133/66 293/134/67 292/100/66
f 292/100/66 293/134/67 294/102/68
f 363/80/37 366/84/60 365/83/60
f 294/102/68 293/134/67 295/103/69
f 293/134/67 296/135/69 295/103/69
f 295/103/69 296/135/69 297/105/70
f 296/135/69 298/136/71 297/105/70
f 297/105/70 298/136/71 299/108/72
f 298/136/71 300/137/72 299/108/72
f 364/81/37 363/80/37 365/83/60
f 300/137/72 301/138/73 299/108/72
f 299/108/72 301/138/73 302/110/74
f 301/138/73 303/139/75 302/110/74
f 302/110/74 303/139/75 304/111/76
f 303/139/75 305/140/26 304/111/76
f 304/111/76 305/140/26 306/113/26
f 307/62/77 309/63/77 308/64/77
f 308/64/77 309/63/77 310/65/77
f 311/66/4 313/64/78 312/67/78
f 312/67/78 313/64/78 314/65/4
f 315/68/13 317/69/79 316/62/79
f 316/62/79 317/69/79 318/63/13
f 319/62/40 321/63/40 320/64/40
f 320/64/40 321/63/40 322/65/40
f 323/64/27 325/65/27 324/66/27
f 324/66/27 325/65/27 326/67/27
f 327/62/23 329/68/23 328/63/23
f 328/63/23 329/68/23 330/69/23
f 331/62/40 333/63/40 332/64/40
f 332/64/40 333/63/40 334/65/40
f 335/64/27 337/65/27 336/66/27
f 336/66/27 337/65/27 338/67/27
f 339/62/23 341/68/23 340/63/23
f 340/63/23 341/68/23 342/69/23
f 343/62/40 345/63/40 344/64/77
f 344/64/77 345/63/40 346/65/40
f 347/66/4 349/64/78 348/67/78
f 348/67/78 349/64/78 350/65/78
f 351/68/13 353/69/79 352/62/79
f 352/62/79 353/69/79 354/63/79
f 355/70/61 357/71/9 356/72/13
f 356/72/13 357/71/9 358/73/9
f 357/71/9 359/74/3 358/73/9
f 358/73/9 359/74/3 360/75/3
f 361/77/4 363/80/37 364/81/37
f 360/75/3 359/74/3 361/77/4
f 359/74/3 362/78/4 361/77/4
f 362/78/4 363/80/37 361/77/4
-12
View File
@@ -1,12 +0,0 @@
# Blender 4.5.5 LTS MTL File: 'None'
# www.blender.org
newmtl EVE_Xmas
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_f5b8cc0e1394df76_14.png
map_d tex1_128x128_m_47fba0aeb06eb3d7_0.png
File diff suppressed because it is too large. Load diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

-12
View File
@@ -1,12 +0,0 @@
# Blender 4.5.5 LTS MTL File: 'None'
# www.blender.org
newmtl EVE_Diver
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_256x256_m_7f667e040dcfe4ee_14.png
-897
View File
@@ -1,897 +0,0 @@
# Blender 4.5.5 LTS
# www.blender.org
mtllib EVE_Diver.mtl
o EVE_Diver
v -0.452637 10.603516 0.262695
v -0.391113 11.027832 0.227050
v -0.453613 10.603516 -0.260255
v -0.392090 11.027832 -0.225098
v -0.000977 11.027832 -0.452149
v -0.000977 10.603516 -0.522950
v 0.452637 10.603516 -0.262696
v 0.391113 11.027832 -0.227052
v 0.453613 10.603516 0.260253
v 0.392090 11.027832 0.225097
v 0.000977 11.027832 0.452148
v 0.000977 10.603516 0.522948
v -0.452637 10.603516 0.262695
v -0.391113 11.027832 0.227050
v -0.391113 11.027832 0.227050
v -0.558594 11.027832 0.324218
v -0.392090 11.027832 -0.225098
v -0.560059 11.027832 -0.321778
v -0.001465 11.027832 -0.645997
v -0.000977 11.027832 -0.452149
v 0.558594 11.027832 -0.324220
v 0.391113 11.027832 -0.227052
v 0.392090 11.027832 0.225097
v 0.560059 11.027832 0.321777
v 0.000977 11.027832 0.452148
v 0.001465 11.027832 0.645995
v -0.391113 11.027832 0.227050
v -0.558594 11.027832 0.324218
v -0.646484 10.603516 0.374999
v -0.647949 10.603516 -0.372071
v -0.558594 11.027832 0.324218
v -0.560059 11.027832 -0.321778
v -0.001465 10.603516 -0.747559
v -0.001465 11.027832 -0.645997
v 0.646484 10.603516 -0.375001
v 0.558594 11.027832 -0.324220
v 0.647949 10.603516 0.372070
v 0.560059 11.027832 0.321777
v 0.001465 10.603516 0.747558
v 0.001465 11.027832 0.645995
v -0.646484 10.603516 0.374999
v -0.558594 11.027832 0.324218
v 0.679199 7.251953 2.741210
v 0.545410 7.251953 2.741210
v 0.679199 9.599609 2.741210
v 0.545410 9.599609 2.741210
v 0.545410 7.251953 2.741210
v 0.545410 7.104004 2.485351
v 0.545410 9.599609 2.741210
v 0.545410 9.747559 2.485351
v 0.679199 7.251953 2.741210
v 0.679199 9.599609 2.741210
v 0.679199 7.104004 2.485351
v 0.679199 9.747559 2.485351
v -0.551758 7.251953 2.741210
v -0.685547 7.251953 2.741210
v -0.551758 9.599609 2.741210
v -0.685547 9.599609 2.741210
v -0.685547 7.251953 2.741210
v -0.685547 7.104004 2.485351
v -0.685547 9.599609 2.741210
v -0.685547 9.747559 2.485351
v -0.551758 7.251953 2.741210
v -0.551758 9.599609 2.741210
v -0.551758 7.104004 2.485351
v -0.551758 9.747559 2.485351
v -2.088867 7.956543 2.741210
v -2.088867 8.090332 2.741210
v 2.083496 7.956543 2.741210
v 2.083496 8.090332 2.741210
v -2.088867 8.090332 2.741210
v -2.236816 8.090332 2.485351
v 2.083496 8.090332 2.741210
v 2.230957 8.090332 2.485351
v -2.236816 7.956543 2.485351
v -2.088867 7.956543 2.741210
v 2.230957 7.956543 2.485351
v 2.083496 7.956543 2.741210
v -1.899902 8.792969 2.741210
v -1.899902 8.926758 2.741210
v 1.867676 8.792969 2.741210
v 1.867676 8.926758 2.741210
v -2.043457 8.926758 2.485351
v 2.011719 8.926758 2.485351
v -1.899902 8.926758 2.741210
v 1.867676 8.926758 2.741210
v -2.043457 8.792969 2.485351
v -1.899902 8.792969 2.741210
v 2.011719 8.792969 2.485351
v 1.867676 8.792969 2.741210
v 0.258789 11.023438 0.413085
v 0.208984 11.023438 0.413085
v 0.258789 11.023438 -0.433106
v 0.208984 11.023438 -0.433106
v 0.208984 11.023438 0.413085
v 0.208984 10.927734 0.468261
v 0.208984 11.023438 -0.433106
v 0.208984 10.927734 -0.488282
v 0.258789 10.927734 0.468261
v 0.258789 11.023438 0.413085
v 0.258789 10.927734 -0.488282
v 0.258789 11.023438 -0.433106
v -0.208984 11.023438 0.413085
v -0.258789 11.023438 0.413085
v -0.208984 11.023438 -0.433106
v -0.258789 11.023438 -0.433106
v -0.258789 11.023438 0.413085
v -0.258789 10.927734 0.468261
v -0.258789 11.023438 -0.433106
v -0.258789 10.927734 -0.488282
v -0.208984 10.927734 0.468261
v -0.208984 11.023438 0.413085
v -0.208984 10.927734 -0.488282
v -0.208984 11.023438 -0.433106
v -0.423340 11.023438 0.249023
v -0.423340 11.023438 0.198730
v 0.423340 11.023438 0.249023
v 0.423340 11.023438 0.198730
v -0.423340 11.023438 0.198730
v -0.478516 10.927734 0.198730
v 0.423340 11.023438 0.198730
v 0.478516 10.927734 0.198730
v -0.478516 10.927734 0.249023
v -0.423340 11.023438 0.249023
v 0.478516 10.927734 0.249023
v 0.423340 11.023438 0.249023
v -0.423340 11.023438 -0.218751
v -0.423340 11.023438 -0.269044
v 0.423340 11.023438 -0.218751
v 0.423340 11.023438 -0.269044
v -0.423340 11.023438 -0.269044
v -0.478516 10.927734 -0.269044
v 0.423340 11.023438 -0.269044
v 0.478516 10.927734 -0.269044
v -0.478516 10.927734 -0.218751
v -0.423340 11.023438 -0.218751
v 0.478516 10.927734 -0.218751
v 0.423340 11.023438 -0.218751
v -2.616699 9.216797 -0.743653
v -2.589355 9.301758 -0.743653
v -2.616699 9.216797 0.763671
v -2.589355 9.301758 0.763671
v -2.427246 9.249023 -0.842286
v -2.427246 9.249023 0.862304
v -2.589355 9.301758 -0.743653
v -2.589355 9.301758 0.763671
v -2.454590 9.164062 -0.842286
v -2.616699 9.216797 -0.743653
v -2.454590 9.164062 0.862304
v -2.616699 9.216797 0.763671
v -2.498535 9.580078 -0.451661
v -2.498535 9.580078 -0.362305
v -2.965820 8.145996 -0.451661
v -2.965820 8.145996 -0.362305
v -2.498535 9.580078 -0.362305
v -2.306152 9.620605 -0.362305
v -2.965820 8.145996 -0.362305
v -2.834473 7.999512 -0.362305
v -2.498535 9.580078 -0.451661
v -2.965820 8.145996 -0.451661
v -2.306152 9.620605 -0.451661
v -2.834473 7.999512 -0.451661
v -2.498535 9.580078 0.381835
v -2.498535 9.580078 0.471191
v -2.965820 8.145996 0.381835
v -2.965820 8.145996 0.471191
v -2.498535 9.580078 0.471191
v -2.306152 9.620605 0.471191
v -2.965820 8.145996 0.471191
v -2.834473 7.999512 0.471191
v -2.498535 9.580078 0.381835
v -2.965820 8.145996 0.381835
v -2.306152 9.620605 0.381835
v -2.834473 7.999512 0.381835
v -2.875488 8.423828 -0.743653
v -2.847656 8.508789 -0.743653
v -2.875488 8.423828 0.763671
v -2.847656 8.508789 0.763671
v -2.685547 8.456055 -0.842286
v -2.685547 8.456055 0.862304
v -2.847656 8.508789 -0.743653
v -2.847656 8.508789 0.763671
v -2.713379 8.371094 -0.842286
v -2.875488 8.423828 -0.743653
v -2.713379 8.371094 0.862304
v -2.875488 8.423828 0.763671
v -2.073242 9.500488 -0.000001
v -2.496582 9.638184 -0.000001
v -2.203613 9.099609 0.729980
v -2.626953 9.237305 0.729980
v -2.464844 8.297363 0.729980
v -2.888672 8.435547 0.729980
v -3.019043 8.034668 -0.000001
v -2.595703 7.896484 -0.000001
v -2.464844 8.297363 -0.729981
v -2.888672 8.435547 -0.729981
v -2.626953 9.237305 -0.729981
v -2.203613 9.099609 -0.729981
v -2.496582 9.638184 -0.000001
v -2.073242 9.500488 -0.000001
v -2.384277 9.981934 -0.000001
v -2.571289 9.409180 1.042968
v -2.496582 9.638184 -0.000001
v -2.626953 9.237305 0.729980
v -2.944336 8.263672 1.042968
v -2.888672 8.435547 0.729980
v -3.019043 8.034668 -0.000001
v -3.130859 7.690918 -0.000001
v -2.944336 8.263672 -1.042969
v -2.888672 8.435547 -0.729981
v -2.626953 9.237305 -0.729981
v -2.571289 9.409180 -1.042969
v -2.496582 9.638184 -0.000001
v -2.384277 9.981934 -0.000001
v -2.384277 9.981934 -0.000001
v -1.960938 9.843750 -0.000001
v -2.571289 9.409180 1.042968
v -2.147949 9.270996 1.042968
v -2.944336 8.263672 1.042968
v -2.520996 8.125977 1.042968
v -3.130859 7.690918 -0.000001
v -2.707520 7.553223 -0.000001
v -2.520996 8.125977 -1.042969
v -2.944336 8.263672 -1.042969
v -2.147949 9.270996 -1.042969
v -2.571289 9.409180 -1.042969
v -1.960938 9.843750 -0.000001
v -2.384277 9.981934 -0.000001
v -0.002441 7.286621 2.763183
v 1.350586 7.427246 2.763183
v -0.002930 6.862793 2.763183
v 1.464355 7.033203 2.763183
v 1.913086 7.782227 2.763183
v 2.230957 7.576660 2.763183
v 2.329590 8.142578 2.763183
v 1.983398 8.178223 2.763183
v 1.899902 9.187988 2.763183
v 1.656738 8.949707 2.763183
v 0.970215 9.465332 2.763183
v 1.095703 9.812988 2.763183
v -0.011230 9.631836 2.763183
v -0.012695 10.007324 2.763183
v -1.093262 9.817383 2.763183
v -0.974609 9.467285 2.763183
v -1.904297 9.189941 2.763183
v -1.662109 8.950195 2.763183
v -2.018066 8.201172 2.763183
v -2.361328 8.206543 2.763183
v -1.955566 7.784668 2.763183
v -2.265137 7.564453 2.763183
v -1.471191 7.021484 2.763183
v -1.362793 7.415527 2.763183
v -0.002930 6.862793 2.763183
v -0.002441 7.286621 2.763183
v -0.002441 7.286621 2.763183
v -0.002441 7.286621 2.636718
v 1.350586 7.427246 2.763183
v 1.350586 7.427246 2.296386
v 1.913086 7.782227 2.763183
v 1.913086 7.782227 1.984374
v 1.983398 8.178223 2.763183
v 1.983398 8.178223 1.858886
v 1.656738 8.949707 1.864745
v 1.656738 8.949707 2.763183
v 0.970215 9.465332 1.988769
v 0.970215 9.465332 2.763183
v -0.011230 9.631836 2.031738
v -0.011230 9.631836 2.763183
v -0.974609 9.467285 2.763183
v -0.974609 9.467285 1.987792
v -1.662109 8.950195 2.763183
v -1.662109 8.950195 1.864745
v -2.018066 8.201172 2.763183
v -2.018066 8.201172 1.840820
v -1.955566 7.784668 1.954101
v -1.955566 7.784668 2.763183
v -1.362793 7.415527 2.291015
v -1.362793 7.415527 2.763183
v -0.002441 7.286621 2.636718
v -0.002441 7.286621 2.763183
v -0.002930 6.862793 2.763183
v 1.464355 7.033203 2.763183
v -0.002930 6.862793 2.444824
v 1.464355 7.033203 2.053710
v 2.230957 7.576660 2.763183
v 2.230957 7.576660 1.608886
v 2.329590 8.142578 2.763183
v 2.329590 8.142578 1.434081
v 1.899902 9.187988 1.435058
v 1.899902 9.187988 2.763183
v 1.095703 9.812988 1.594726
v 1.095703 9.812988 2.763183
v -0.012695 10.007324 1.650390
v -0.012695 10.007324 2.763183
v -1.093262 9.817383 2.763183
v -1.093262 9.817383 1.594238
v -1.904297 9.189941 2.763183
v -1.904297 9.189941 1.434081
v -2.361328 8.206543 2.763183
v -2.361328 8.206543 1.407226
v -2.265137 7.564453 1.582031
v -2.265137 7.564453 2.763183
v -1.471191 7.021484 2.047363
v -1.471191 7.021484 2.763183
v -0.002930 6.862793 2.444824
v -0.002930 6.862793 2.763183
v 2.621582 9.216797 0.743652
v 2.594238 9.301758 0.743652
v 2.621582 9.216797 -0.763673
v 2.594238 9.301758 -0.763673
v 2.432129 9.249023 0.842284
v 2.432129 9.249023 -0.862305
v 2.594238 9.301758 0.743652
v 2.594238 9.301758 -0.763673
v 2.459473 9.164062 0.842284
v 2.621582 9.216797 0.743652
v 2.459473 9.164062 -0.862305
v 2.621582 9.216797 -0.763673
v 2.503418 9.580078 0.451659
v 2.503418 9.580078 0.362304
v 2.970703 8.145996 0.451660
v 2.970703 8.145996 0.362304
v 2.503418 9.580078 0.362304
v 2.311035 9.620605 0.362304
v 2.970703 8.145996 0.362304
v 2.839355 7.999512 0.362304
v 2.503418 9.580078 0.451659
v 2.970703 8.145996 0.451660
v 2.311035 9.620605 0.451659
v 2.839355 7.999512 0.451660
v 2.503418 9.580078 -0.381837
v 2.503418 9.580078 -0.471192
v 2.970703 8.145996 -0.381837
v 2.970703 8.145996 -0.471192
v 2.503418 9.580078 -0.471192
v 2.311035 9.620605 -0.471192
v 2.970703 8.145996 -0.471192
v 2.839355 7.999512 -0.471192
v 2.503418 9.580078 -0.381837
v 2.970703 8.145996 -0.381837
v 2.311035 9.620605 -0.381837
v 2.839355 7.999512 -0.381837
v 2.880371 8.423828 0.743652
v 2.852539 8.508789 0.743652
v 2.880371 8.423828 -0.763673
v 2.852539 8.508789 -0.763673
v 2.690430 8.456055 0.842285
v 2.690430 8.456055 -0.862305
v 2.852539 8.508789 0.743652
v 2.852539 8.508789 -0.763673
v 2.718262 8.371094 0.842285
v 2.880371 8.423828 0.743652
v 2.718262 8.371094 -0.862305
v 2.880371 8.423828 -0.763673
v 2.073242 9.500488 -0.000001
v 2.496582 9.638184 -0.000001
v 2.203613 9.099609 -0.729981
v 2.626953 9.237305 -0.729981
v 2.464844 8.297363 -0.729981
v 2.888672 8.435547 -0.729981
v 3.019043 8.034668 -0.000001
v 2.595703 7.896484 -0.000001
v 2.464844 8.297363 0.729980
v 2.888672 8.435547 0.729980
v 2.626953 9.237305 0.729980
v 2.203613 9.099609 0.729980
v 2.496582 9.638184 -0.000001
v 2.073242 9.500488 -0.000001
v 2.384277 9.981934 -0.000001
v 2.571289 9.409180 -1.042969
v 2.496582 9.638184 -0.000001
v 2.626953 9.237305 -0.729981
v 2.944336 8.263672 -1.042969
v 2.888672 8.435547 -0.729981
v 3.019043 8.034668 -0.000001
v 3.130859 7.690918 -0.000001
v 2.944336 8.263672 1.042968
v 2.888672 8.435547 0.729980
v 2.626953 9.237305 0.729980
v 2.571289 9.409180 1.042968
v 2.496582 9.638184 -0.000001
v 2.384277 9.981934 -0.000001
v 2.384277 9.981934 -0.000001
v 1.960938 9.843750 -0.000001
v 2.571289 9.409180 -1.042969
v 2.147949 9.270996 -1.042969
v 2.944336 8.263672 -1.042969
v 2.520996 8.125977 -1.042969
v 3.130859 7.690918 -0.000001
v 2.707520 7.553223 -0.000001
v 2.520996 8.125977 1.042968
v 2.944336 8.263672 1.042968
v 2.147949 9.270996 1.042968
v 2.571289 9.409180 1.042968
v 1.960938 9.843750 -0.000001
v 2.384277 9.981934 -0.000001
vn 0.8519 -0.1656 -0.4969
vn 0.8573 -0.1652 0.4876
vn -0.1499 0.4734 0.8680
vn -0.3068 0.9518 -0.0000
vn -0.0000 -0.1657 0.9862
vn -0.8519 -0.1656 0.4969
vn -0.8518 -0.1656 0.4969
vn -0.8573 -0.1652 -0.4876
vn 0.1499 -0.4734 0.8680
vn -0.0000 -0.1657 -0.9862
vn 0.8518 -0.1656 -0.4969
vn -0.0000 1.0000 -0.0000
vn 0.3068 -0.9518 -0.0000
vn -0.8424 0.2283 0.4881
vn -0.8456 0.2292 -0.4821
vn 0.1500 -0.4735 -0.8680
vn -0.0000 0.2277 -0.9737
vn -0.0000 0.2278 -0.9737
vn 0.8424 0.2283 -0.4881
vn 0.8456 0.2292 0.4821
vn -0.0000 0.2277 0.9737
vn -0.0000 0.2278 0.9737
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.9518 0.3067 -0.0000
vn 0.3068 0.9518 -0.0000
vn 0.3067 0.9518 -0.0000
vn -0.3068 -0.9518 -0.0000
vn -0.3067 -0.9518 -0.0000
vn -0.9518 0.3068 -0.0000
vn -0.3093 -0.9510 -0.0000
vn -0.1499 -0.4734 -0.8680
vn 0.1499 0.4734 -0.8680
vn -0.1499 0.4734 -0.8680
vn 0.1499 0.4734 0.8680
vn -0.1499 -0.4734 0.8680
vn 0.9518 0.3068 -0.0000
vn -0.1500 -0.4735 0.8680
vn -0.3233 0.9463 -0.0000
vn -0.8284 0.5601 -0.0000
vn -0.9939 -0.1104 -0.0000
vn -0.7885 -0.6150 -0.0001
vn -0.7884 -0.6152 -0.0000
vn -0.3930 -0.9196 -0.0000
vn -0.0001 -1.0000 -0.0000
vn 0.3930 -0.9196 -0.0000
vn 0.3930 -0.9195 -0.0000
vn 0.7746 -0.6325 -0.0000
vn 0.7747 -0.6324 -0.0000
vn 0.9899 -0.1414 -0.0000
vn 0.9900 -0.1414 -0.0000
vn 0.8345 0.5510 -0.0000
vn 0.8344 0.5511 -0.0000
vn 0.3162 0.9487 -0.0000
vn 0.3163 0.9487 -0.0000
vn 0.3537 -0.9354 -0.0000
vn 0.1499 -0.4734 -0.8680
vn 0.3093 -0.9510 -0.0000
vn 0.8440 -0.5363 -0.0000
vn 0.9947 0.1026 -0.0000
vn 0.7953 0.6063 -0.0000
vn 0.7953 0.6062 -0.0000
vn 0.4025 0.9154 -0.0000
vn -0.0003 1.0000 -0.0000
vn -0.0002 1.0000 -0.0000
vn -0.4025 0.9154 -0.0000
vn -0.7817 0.6236 -0.0000
vn -0.7816 0.6237 -0.0000
vn -0.9899 0.1414 -0.0000
vn -0.8498 -0.5271 -0.0000
vn -0.8498 -0.5272 -0.0000
vn -0.3468 -0.9379 -0.0000
vn -0.3464 -0.9381 -0.0000
vn 0.9518 0.3067 -0.0000
vn -0.3067 0.9518 -0.0000
vn 0.3067 -0.9518 -0.0000
vt 0.669678 0.523682
vt 0.706604 0.486755
vt 0.679138 0.533142
vt 0.716064 0.496216
vt 0.935120 0.295105
vt 0.984192 0.245972
vt 0.992126 0.253906
vt 0.765320 0.447021
vt 0.755859 0.437500
vt 0.942993 0.302979
vt 0.805054 0.388306
vt 0.814575 0.397766
vt 0.854309 0.339050
vt 0.863770 0.348511
vt 0.886047 0.344177
vt 0.913025 0.299316
vt 0.903503 0.289795
vt 0.893921 0.352051
vt 0.952759 0.240601
vt 0.962280 0.250061
vt 0.688660 0.542664
vt 0.725586 0.505737
vt 0.836914 0.393250
vt 0.774780 0.456482
vt 0.824036 0.407227
vt 0.844849 0.401184
vt 0.873291 0.358032
vt 0.922485 0.308777
vt 0.971741 0.259583
vt 0.698120 0.552124
vt 0.735046 0.515198
vt 0.795776 0.450256
vt 0.784302 0.466003
vt 0.833557 0.416748
vt 0.882751 0.367493
vt 0.932007 0.318298
vt 0.981201 0.269043
vt 0.680115 0.534973
vt 0.974792 0.240295
vt 0.687317 0.542236
vt 0.982056 0.247498
vt 0.686523 0.552673
vt 0.992615 0.246643
vt 0.669617 0.535767
vt 0.975647 0.229736
vt 0.687134 0.541992
vt 0.981812 0.247253
vt 0.669067 0.535217
vt 0.975098 0.229187
vt 0.680359 0.535095
vt 0.975037 0.240417
vt 0.687012 0.541687
vt 0.981689 0.247070
vt 0.683594 0.533508
vt 0.970947 0.246094
vt 0.690063 0.539978
vt 0.977417 0.252563
vt 0.686218 0.551758
vt 0.989258 0.248718
vt 0.671753 0.537354
vt 0.974792 0.234314
vt 0.971130 0.267822
vt 0.698792 0.540161
vt 0.960083 0.256714
vt 0.687683 0.529053
vt 0.963684 0.239807
vt 0.670776 0.532715
vt 0.988037 0.264160
vt 0.695129 0.557068
vt 0.673828 0.524658
vt 0.722961 0.475586
vt 0.681763 0.532593
vt 0.730835 0.483521
vt 0.772034 0.426514
vt 0.779907 0.434448
vt 0.787842 0.442322
vt 0.829041 0.385315
vt 0.821106 0.377441
vt 0.746704 0.499329
vt 0.870178 0.328308
vt 0.878113 0.336243
vt 0.738770 0.491394
vt 0.927185 0.287170
vt 0.919312 0.279236
vt 0.976257 0.238098
vt 0.968384 0.230164
vt 0.689697 0.540527
vt 0.697571 0.548401
vt 0.705444 0.554871
vt 0.695496 0.544800
vt 0.731445 0.528870
vt 0.721497 0.518799
vt 0.757446 0.502869
vt 0.747498 0.492737
vt 0.764832 0.475403
vt 0.774780 0.485535
vt 0.790894 0.449402
vt 0.800842 0.459534
vt 0.826843 0.433472
vt 0.816895 0.423401
vt 0.852844 0.407471
vt 0.842896 0.397400
vt 0.868896 0.371399
vt 0.878845 0.381470
vt 0.894897 0.345337
vt 0.904846 0.355469
vt 0.930847 0.329468
vt 0.920959 0.319336
vt 0.948242 0.312073
vt 0.938293 0.302002
vt 0.964294 0.276001
vt 0.974243 0.286072
vt 0.990295 0.250000
vt 1.000244 0.260071
vt 0.696533 0.546326
vt 0.722595 0.520264
vt 0.748596 0.494263
vt 0.765991 0.476868
vt 0.791992 0.450867
vt 0.818054 0.424805
vt 0.844055 0.398804
vt 0.870117 0.372742
vt 0.896179 0.346741
vt 0.922180 0.320679
vt 0.939514 0.303345
vt 0.965576 0.277283
vt 0.991638 0.251282
vt 0.661072 0.510559
vt 0.687134 0.484497
vt 0.713135 0.458496
vt 0.730530 0.441101
vt 0.756531 0.415100
vt 0.782593 0.389038
vt 0.808594 0.363037
vt 0.834656 0.336975
vt 0.860657 0.310913
vt 0.886719 0.284912
vt 0.904053 0.267578
vt 0.930115 0.241516
vt 0.956116 0.215454
s 1
usemtl EVE_Diver
f 1/1/1 3/2/2 2/3/1
f 2/3/1 3/2/2 4/4/2
f 394/5/3 396/6/4 395/7/4
f 4/4/2 3/2/2 5/8/5
f 3/2/2 6/9/5 5/8/5
f 393/10/3 394/5/3 395/7/4
f 6/9/5 7/11/6 5/8/5
f 5/8/5 7/11/6 8/12/7
f 7/11/6 9/13/8 8/12/7
f 8/12/7 9/13/8 10/14/8
f 392/15/9 394/5/3 393/10/3
f 10/14/8 9/13/8 11/16/10
f 9/13/8 12/17/10 11/16/10
f 391/18/9 392/15/9 393/10/3
f 12/17/10 13/19/1 11/16/10
f 11/16/10 13/19/1 14/20/11
f 15/3/12 17/4/12 16/21/12
f 16/21/12 17/4/12 18/22/12
f 389/23/13 392/15/9 391/18/9
f 18/22/12 17/4/12 19/24/12
f 17/4/12 20/8/12 19/24/12
f 19/24/12 20/8/12 21/25/12
f 20/8/12 22/12/12 21/25/12
f 390/26/13 389/23/13 391/18/9
f 22/12/12 23/14/12 21/25/12
f 21/25/12 23/14/12 24/27/12
f 23/14/12 25/16/12 24/27/12
f 24/27/12 25/16/12 26/28/12
f 25/16/12 27/20/12 26/28/12
f 26/28/12 27/20/12 28/29/12
f 29/30/14 31/21/14 30/31/15
f 388/32/16 389/23/13 390/26/13
f 31/21/14 32/22/15 30/31/15
f 30/31/15 32/22/15 33/33/17
f 32/22/15 34/24/18 33/33/17
f 33/33/17 34/24/18 35/34/19
f 34/24/18 36/25/19 35/34/19
f 35/34/19 36/25/19 37/35/20
f 36/25/19 38/27/20 37/35/20
f 37/35/20 38/27/20 39/36/21
f 38/27/20 40/28/22 39/36/21
f 39/36/21 40/28/22 41/37/14
f 40/28/22 42/29/14 41/37/14
f 43/38/23 45/39/23 44/40/23
f 44/40/23 45/39/23 46/41/23
f 47/40/24 49/41/24 48/42/24
f 48/42/24 49/41/24 50/43/24
f 51/38/25 53/44/25 52/39/25
f 52/39/25 53/44/25 54/45/25
f 55/38/23 57/39/23 56/46/23
f 56/46/23 57/39/23 58/47/23
f 59/46/24 61/47/24 60/42/24
f 60/42/24 61/47/24 62/43/24
f 63/38/25 65/48/25 64/39/25
f 64/39/25 65/48/25 66/49/25
f 67/50/23 69/51/23 68/52/23
f 68/52/23 69/51/23 70/53/23
f 71/52/12 73/53/12 72/42/12
f 72/42/12 73/53/12 74/43/12
f 75/48/26 77/49/26 76/50/26
f 76/50/26 77/49/26 78/51/26
f 79/50/23 81/51/23 80/52/23
f 80/52/23 81/51/23 82/53/23
f 83/42/12 85/52/12 84/43/12
f 84/43/12 85/52/12 86/53/12
f 87/48/26 89/49/26 88/50/26
f 88/50/26 89/49/26 90/51/26
f 91/54/12 93/55/12 92/56/12
f 92/56/12 93/55/12 94/57/12
f 95/56/24 97/57/24 96/58/24
f 96/58/24 97/57/24 98/59/24
f 99/60/25 101/61/25 100/54/25
f 100/54/25 101/61/25 102/55/25
f 103/54/12 105/55/12 104/56/12
f 104/56/12 105/55/12 106/57/12
f 107/56/24 109/57/24 108/58/24
f 108/58/24 109/57/24 110/59/24
f 111/60/25 113/61/25 112/54/25
f 112/54/25 113/61/25 114/55/25
f 115/54/12 117/55/12 116/56/12
f 116/56/12 117/55/12 118/57/12
f 119/56/27 121/57/27 120/58/27
f 120/58/27 121/57/27 122/59/27
f 123/60/23 125/61/23 124/54/23
f 124/54/23 125/61/23 126/55/23
f 127/54/12 129/55/12 128/56/12
f 128/56/12 129/55/12 130/57/12
f 131/56/27 133/57/27 132/58/27
f 132/58/27 133/57/27 134/59/27
f 135/60/23 137/61/23 136/54/23
f 136/54/23 137/61/23 138/55/23
f 139/62/28 141/63/28 140/64/28
f 140/64/28 141/63/28 142/65/28
f 143/66/29 145/64/30 144/67/29
f 144/67/29 145/64/30 146/65/30
f 147/68/31 149/69/31 148/62/32
f 148/62/32 149/69/31 150/63/32
f 151/62/33 153/63/33 152/64/33
f 152/64/33 153/63/33 154/65/33
f 155/64/23 157/65/23 156/66/23
f 156/66/23 157/65/23 158/67/23
f 159/62/27 161/68/27 160/63/27
f 160/63/27 161/68/27 162/69/27
f 163/62/33 165/63/33 164/64/33
f 164/64/33 165/63/33 166/65/33
f 167/64/23 169/65/23 168/66/23
f 168/66/23 169/65/23 170/67/23
f 171/62/27 173/68/27 172/63/27
f 172/63/27 173/68/27 174/69/27
f 175/62/33 177/63/33 176/64/33
f 176/64/33 177/63/33 178/65/33
f 179/66/29 181/64/30 180/67/30
f 180/67/30 181/64/30 182/65/30
f 183/68/31 185/69/32 184/62/32
f 184/62/32 185/69/32 186/63/32
f 187/70/34 189/71/35 188/72/31
f 188/72/31 189/71/35 190/73/35
f 189/71/35 191/74/36 190/73/35
f 190/73/35 191/74/36 192/75/36
f 387/76/16 389/23/13 388/32/16
f 192/75/36 191/74/36 193/77/29
f 191/74/36 194/78/29 193/77/29
f 386/79/37 387/76/16 388/32/16
f 194/78/29 195/80/38 193/77/29
f 193/77/29 195/80/38 196/81/38
f 385/82/37 387/76/16 386/79/37
f 196/81/38 195/80/38 197/83/39
f 195/80/38 198/84/39 197/83/39
f 197/83/39 198/84/39 199/85/34
f 198/84/39 200/86/31 199/85/34
f 201/87/33 203/72/33 202/82/33
f 384/88/4 385/82/37 386/79/37
f 203/72/33 204/73/33 202/82/33
f 202/82/33 204/73/33 205/76/33
f 204/73/33 206/75/33 205/76/33
f 383/87/4 385/82/37 384/88/4
f 206/75/33 207/77/33 205/76/33
f 205/76/33 207/77/33 208/23/33
f 380/5/40 381/85/40 382/6/40
f 208/23/33 207/77/33 209/15/33
f 207/77/33 210/81/33 209/15/33
f 379/83/40 381/85/40 380/5/40
f 210/81/33 211/83/33 209/15/33
f 209/15/33 211/83/33 212/5/33
f 211/83/33 213/85/33 212/5/33
f 212/5/33 213/85/33 214/6/33
f 215/87/29 217/82/38 216/88/29
f 216/88/29 217/82/38 218/79/38
f 217/82/38 219/76/41 218/79/38
f 218/79/38 219/76/41 220/32/41
f 219/76/41 221/23/31 220/32/41
f 220/32/41 221/23/31 222/26/31
f 377/15/40 379/83/40 380/5/40
f 222/26/31 221/23/31 223/18/35
f 221/23/31 224/15/35 223/18/35
f 223/18/35 224/15/35 225/10/36
f 224/15/35 226/5/36 225/10/36
f 225/10/36 226/5/36 227/7/29
f 226/5/36 228/6/29 227/7/29
f 229/89/23 231/90/23 230/91/23
f 378/81/40 379/83/40 377/15/40
f 231/90/23 232/92/23 230/91/23
f 230/91/23 232/92/23 233/93/23
f 232/92/23 234/94/23 233/93/23
f 375/77/40 378/81/40 377/15/40
f 234/94/23 235/95/23 233/93/23
f 233/93/23 235/95/23 236/96/23
f 235/95/23 237/97/23 236/96/23
f 236/96/23 237/97/23 238/98/23
f 376/23/40 375/77/40 377/15/40
f 238/98/23 237/97/23 239/99/23
f 237/97/23 240/100/23 239/99/23
f 239/99/23 240/100/23 241/101/23
f 240/100/23 242/102/23 241/101/23
f 373/76/40 375/77/40 376/23/40
f 242/102/23 243/103/23 241/101/23
f 241/101/23 243/103/23 244/104/23
f 243/103/23 245/105/23 244/104/23
f 244/104/23 245/105/23 246/106/23
f 374/75/40 375/77/40 373/76/40
f 246/106/23 245/105/23 247/107/23
f 245/105/23 248/108/23 247/107/23
f 247/107/23 248/108/23 249/109/23
f 248/108/23 250/110/23 249/109/23
f 372/73/40 374/75/40 373/76/40
f 250/110/23 251/111/23 249/109/23
f 249/109/23 251/111/23 252/112/23
f 251/111/23 253/113/23 252/112/23
f 252/112/23 253/113/23 254/114/23
f 255/89/12 257/91/42 256/115/12
f 256/115/12 257/91/42 258/116/42
f 257/91/42 259/93/43 258/116/42
f 258/116/42 259/93/43 260/117/43
f 259/93/43 261/96/44 260/117/43
f 260/117/43 261/96/44 262/118/44
f 370/82/40 372/73/40 373/76/40
f 262/118/44 261/96/44 263/119/45
f 261/96/44 264/98/46 263/119/45
f 263/119/45 264/98/46 265/120/47
f 264/98/46 266/99/47 265/120/47
f 265/120/47 266/99/47 267/121/48
f 266/99/47 268/101/26 267/121/48
f 371/72/40 372/73/40 370/82/40
f 268/101/26 269/104/49 267/121/48
f 267/121/48 269/104/49 270/122/50
f 269/104/49 271/106/51 270/122/50
f 270/122/50 271/106/51 272/123/52
f 271/106/51 273/107/53 272/123/52
f 272/123/52 273/107/53 274/124/54
f 369/87/40 371/72/40 370/82/40
f 274/124/54 273/107/53 275/125/55
f 273/107/53 276/109/56 275/125/55
f 275/125/55 276/109/56 277/126/57
f 276/109/56 278/112/58 277/126/57
f 277/126/57 278/112/58 279/127/12
f 278/112/58 280/114/12 279/127/12
f 281/90/26 283/128/26 282/92/59
f 366/84/60 368/86/13 367/85/61
f 283/128/26 284/129/59 282/92/59
f 282/92/59 284/129/59 285/94/62
f 284/129/59 286/130/62 285/94/62
f 285/94/62 286/130/62 287/95/63
f 286/130/62 288/131/63 287/95/63
f 365/83/60 366/84/60 367/85/61
f 288/131/63 289/132/64 287/95/63
f 287/95/63 289/132/64 290/97/65
f 289/132/64 291/133/66 290/97/65
f 290/97/65 291/133/66 292/100/66
f 291/133/66 293/134/67 292/100/66
f 292/100/66 293/134/67 294/102/68
f 363/80/37 366/84/60 365/83/60
f 294/102/68 293/134/67 295/103/69
f 293/134/67 296/135/69 295/103/69
f 295/103/69 296/135/69 297/105/70
f 296/135/69 298/136/71 297/105/70
f 297/105/70 298/136/71 299/108/72
f 298/136/71 300/137/72 299/108/72
f 364/81/37 363/80/37 365/83/60
f 300/137/72 301/138/73 299/108/72
f 299/108/72 301/138/73 302/110/74
f 301/138/73 303/139/75 302/110/74
f 302/110/74 303/139/75 304/111/76
f 303/139/75 305/140/26 304/111/76
f 304/111/76 305/140/26 306/113/26
f 307/62/77 309/63/77 308/64/77
f 308/64/77 309/63/77 310/65/77
f 311/66/4 313/64/78 312/67/78
f 312/67/78 313/64/78 314/65/4
f 315/68/13 317/69/79 316/62/79
f 316/62/79 317/69/79 318/63/13
f 319/62/40 321/63/40 320/64/40
f 320/64/40 321/63/40 322/65/40
f 323/64/27 325/65/27 324/66/27
f 324/66/27 325/65/27 326/67/27
f 327/62/23 329/68/23 328/63/23
f 328/63/23 329/68/23 330/69/23
f 331/62/40 333/63/40 332/64/40
f 332/64/40 333/63/40 334/65/40
f 335/64/27 337/65/27 336/66/27
f 336/66/27 337/65/27 338/67/27
f 339/62/23 341/68/23 340/63/23
f 340/63/23 341/68/23 342/69/23
f 343/62/40 345/63/40 344/64/77
f 344/64/77 345/63/40 346/65/40
f 347/66/4 349/64/78 348/67/78
f 348/67/78 349/64/78 350/65/78
f 351/68/13 353/69/79 352/62/79
f 352/62/79 353/69/79 354/63/79
f 355/70/61 357/71/9 356/72/13
f 356/72/13 357/71/9 358/73/9
f 357/71/9 359/74/3 358/73/9
f 358/73/9 359/74/3 360/75/3
f 361/77/4 363/80/37 364/81/37
f 360/75/3 359/74/3 361/77/4
f 359/74/3 362/78/4 361/77/4
f 362/78/4 363/80/37 361/77/4
-12
View File
@@ -1,12 +0,0 @@
# Blender 4.5.5 LTS MTL File: 'None'
# www.blender.org
newmtl EVE_Xmas
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_f5b8cc0e1394df76_14.png
map_d tex1_128x128_m_47fba0aeb06eb3d7_0.png
File diff suppressed because it is too large. Load diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

+85 -57
View File
@@ -1,83 +1,111 @@
# 🚀 EveFlow — Compagnon de Bureau Rétro-Futuriste 3D
# EveFlow 2 — Interface vocale JARVIS pour Hermes Agent
[![Windows Version](https://img.shields.io/badge/OS-Windows-blue.svg?style=flat-square&logo=windows)](https://github.com/R0m1k3/EveFlow)
[![Version](https://img.shields.io/badge/version-1.0.5-brightgreen.svg?style=flat-square)](https://github.com/R0m1k3/EveFlow/releases/tag/v1.0.5)
[![Build](https://img.shields.io/github/actions/workflow/status/R0m1k3/EveFlow/windows-release.yml?style=flat-square)](https://github.com/R0m1k3/EveFlow/actions)
[![Version](https://img.shields.io/badge/version-2.0.0-brightgreen.svg?style=flat-square)](https://github.com/R0m1k3/EveFlow/releases)
[![License](https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square)](LICENSE)
**EveFlow** est un compagnon de bureau Windows immersif haut de gamme, combinant une esthétique cyberpunk rétro-futuriste soignée et des technologies d'intelligence artificielle avancées. Il intègre un assistant virtuel en 3D nommé **Eve**, animé en temps réel avec des expressions émotionnelles dynamiques et synchronisé avec des services de synthèse vocale (TTS/STT) locaux et des architectures multi-agents.
**EveFlow** est un compagnon de bureau Windows qui transforme [Hermes Agent](https://hermes-agent.nousresearch.com/) en assistant vocal à la JARVIS : un noyau holographique réactif au son, une conversation en streaming, les outils, sous-agents, approbations, crons, skills et sessions d'Hermes pilotés depuis un seul HUD.
La version 2 est une réécriture complète : plus de robot 3D, un pipeline vocal fiable (AudioWorklet + détection d'activité vocale), un client Hermes qui exploite l'API serveur complète (runs SSE, sessions, jobs, capabilities) et une architecture Electron sécurisée (sandbox, `webSecurity` actif, réseau proxifié par le processus principal).
---
## 📸 Aperçu de l'Interface
## Fonctionnalités
Découvrez le cockpit de contrôle immersif et le mode widget compact d'EveFlow :
### Noyau JARVIS
* Arc reactor rendu en Canvas 2D : anneaux gradués, arcs segmentés et spectre radial calculé sur le **vrai signal audio** (voix synthétisée ou microphone).
* États visuels : veille, écoute, analyse (outils en cours), transmission, attention (approbation), anomalie, succès.
* Quatre thèmes (arc cyan, gold, crimson, emerald), mode animations réduites.
* Mode compact flottant toujours au premier plan, opacité réglable.
### Voix
* **Capture micro** via AudioWorklet à 16 kHz, sans monitoring du micro dans les haut-parleurs, avec annulation d'écho et réduction de bruit.
* **Détection d'activité vocale** (seuil adaptatif, sensibilité et silence de fin réglables) : l'enregistrement s'arrête tout seul quand vous avez fini de parler.
* **Mains libres** : le micro se réactive après chaque réponse.
* **STT** : n'importe quelle API `/v1/audio/transcriptions` compatible OpenAI (Qwen3-ASR, Whisper, Speaches, faster-whisper-server, LocalAI, OpenAI). Repli sur la reconnaissance Chromium.
* **TTS** : API `/v1/audio/speech` compatible OpenAI (Kokoro, Piper, OpenAI…), voix système Windows ou Google Translate. Lecture phrase par phrase pendant le streaming, préchargement du segment suivant, coupure instantanée.
* Raccourcis globaux : `Ctrl+Shift+Espace` (micro), `Ctrl+Shift+J` (afficher/masquer), `Ctrl+Shift+Échap` (couper la voix).
### Hermes, toute la puissance
* Découverte automatique via `GET /v1/capabilities` et `GET /health/detailed`, choix du transport le plus riche :
1. **Runs API** (`POST /v1/runs` + `GET /v1/runs/{id}/events`) : deltas, outils, sous-agents, `approval.request`, `run.completed`, arrêt (`/stop`) et injection de consignes en cours de run (`/steer`).
2. **Sessions API** (`/api/sessions/{id}/chat/stream`) : mémoire côté serveur, fork, suppression, relecture de l'historique.
3. **Chat completions** OpenAI (`/v1/chat/completions`) avec `hermes.tool.progress`, continuité de session (`X-Hermes-Session-Id`) et outils EveFlow côté client (état du HUD, fichiers partagés, notifications).
* Mémoire longue durée via `X-Hermes-Session-Key`.
* **Approbations** d'outils affichées dans le HUD : une fois, pour la session, toujours, refuser.
* **Crons** : création en langage naturel (`every 1h`, `weekdays at 9am`, `in 30m`, expression cron), pause/reprise, exécution immédiate, édition, historique des résultats lus à voix haute.
* **Skills et toolsets** exposés par le serveur, **sessions** navigables.
* **Webhook local** (`POST http://<pc>:7842/eveflow/hook`) pour recevoir les livraisons de crons, le miroir Telegram ou n'importe quel script, avec secret optionnel.
* Images inline (URL, data URL, fichiers du dossier partagé `Documents/EveFlow_Shared`).
### Système
* Télémétrie réelle : charge CPU, mémoire, fréquence, FPS, uptime.
* Journal sur disque (`%APPDATA%/eveflow/eveflow.log`), icône de zone de notification, instance unique.
---
## ✨ Fonctionnalités Clés
## Stack
* **🤖 Avatar 3D Eve Interactif** : Un modèle 3D animé sous WebGL avec des shaders personnalisés pour ses yeux LED. Ses expressions (joie, tristesse, réflexion, colère, surprise, neutre), son clignotement de paupières et ses mouvements de bras s'adaptent de manière organique selon le contexte et la parole.
* **🌌 Interface Transparent Glassmorphic Premium** : Fenêtre sans bordure avec un effet de verre dépoli haut de gamme, s'intégrant magnifiquement à votre bureau Windows sans perturber votre espace de travail.
* **🔄 Deux Modes d'Affichage Dynamiques** :
* **Mode Cockpit** : Interface complète de discussion avec panneau de commande, historique des messages, affichage des logs et télémétrie matérielle avancée.
* **Mode Flottant (Widget)** : Une carte compacte translucide toujours au premier plan, plaçant l'avatar d'Eve directement dans le coin de votre écran pour une compagnie discrète.
* **🔌 Serveur Webhook Intégré (Hermes)** : Port d'écoute webhook local (`7842`) permettant la réception d'événements et de notifications poussés en temps réel par des agents tiers (comme Telegram ou des scripts d'automatisation).
* **🖥️ Télémétrie CPU en Temps Réel** : Suivi des performances de votre ordinateur (fréquence CPU et température thermique calculée selon la charge réelle) directement intégré sous forme d'afficheurs analogiques virtuels futuristes.
* **🔒 Sécurité Zero Trust** : Isolation du contexte Chromium activée (`contextIsolation`), interdiction de l'intégration directe de Node dans le renderer et vérification stricte des extensions de fichiers lors des opérations de lecture/écriture de fichiers partagés via IPC.
* Electron 44 (sandbox, contextIsolation, `webSecurity` actif, proxy HTTP en streaming dans le main process)
* React 19 + Vite 8 + TypeScript 5.9 + Zustand
* Canvas 2D, Web Audio (AudioWorklet, AnalyserNode)
* Vitest pour les tests unitaires (SSE, VAD, WAV, normalisation d'événements Hermes)
```
electron/ processus principal (fenêtre, tray, raccourcis, IPC, webhook, proxy HTTP)
shared/ contrat IPC + normalisation des pushs webhook (main + renderer)
src/lib transport, SSE, persistance, utilitaires texte
src/services hermes/ (client, événements, outils locaux) voice/ (capture, VAD, STT, TTS)
src/state stores Zustand (settings, chat, hermes, voice)
src/components hud/ chat/ panels/ settings/ compact/
tests/ vitest
```
---
## 🛠️ Stack Technique
## Prérequis côté Hermes
* **Framework Applicatif** : [Electron](https://www.electronjs.org/) (Zéro Trust)
* **Frontend** : [React](https://react.dev/) + [Vite](https://vitejs.dev/) + [TypeScript](https://www.typescriptlang.org/)
* **Moteur 3D** : [Three.js](https://threejs.org/) via [@react-three/fiber](https://github.com/pmndrs/react-three-fiber) et [@react-three/drei](https://github.com/pmndrs/drei)
* **Serveur Webhook** : Node.js `http` (Port `7842`)
Activez le serveur API dans la configuration Hermes (`~/.hermes/config.yaml`) ou via l'environnement :
```
API_SERVER_ENABLED=true
API_SERVER_PORT=8642
API_SERVER_KEY=<votre clé>
```
Puis lancez `hermes gateway`. Renseignez l'URL (`http://<hôte>:8642`) et la clé dans **Paramètres → Hermes** et cliquez **Tester la liaison**. Le transport choisi apparaît dans la barre supérieure.
Pour recevoir les résultats de crons ou le miroir d'autres canaux dans EveFlow, faites pointer une livraison Hermes (script, webhook, `deliver`) vers `http://<ip-du-pc>:7842/eveflow/hook` avec un JSON tel que :
```json
{ "role": "assistant", "text": "Rapport terminé", "source": "telegram" }
{ "event": "run.completed", "input": "question", "output": "réponse" }
{ "event": "job.completed", "job": { "name": "Rapport" }, "output": "…", "status": "ok" }
```
---
## 🚀 Installation & Lancement en Développement
## Développement
### Prérequis
* [Node.js](https://nodejs.org/) (Version 20 recommandée)
* [Git](https://git-scm.com/)
```bash
npm install
npm start # Vite + Electron (rechargement à chaud du renderer)
npm test # tests unitaires
npm run typecheck # renderer + main process
```
### Étapes d'installation
1. **Cloner le dépôt** :
```bash
git clone https://github.com/R0m1k3/EveFlow.git
cd EveFlow
```
2. **Installer les dépendances** :
```bash
npm install
```
3. **Lancer l'application en mode développement** :
```bash
npm start
```
*Cette commande démarre le serveur de développement Vite à l'adresse `http://localhost:5173` puis lance Electron en mode connecté.*
Sans Electron, `npm run dev` puis `http://127.0.0.1:5173/` (ou `?mode=compact`) permet de travailler l'interface dans un navigateur ; les appels réseau passent alors directement par `fetch` (CORS requis côté serveur).
## Packaging Windows
```bash
npm run dist
```
L'installateur NSIS est produit dans `out/`. Le workflow GitHub Actions construit l'exécutable sur chaque tag `v*`.
---
## 📦 Compilation & Packaging (Production)
## Licence
Pour générer l'exécutable d'installation Windows (`.exe`) autonome :
1. **Compiler le bundle frontend** :
```bash
npm run build
```
2. **Générer le package d'installation Windows** :
```bash
npm run dist
```
*L'exécutable d'installation NSIS (`EveFlow Setup 1.0.5.exe`) et la build décompressée seront générés dans le dossier `./out/`.*
---
## 📜 Licence
Ce projet est sous licence MIT. Consultez le fichier [LICENSE](LICENSE) pour plus de détails.
MIT.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

+113
View File
@@ -0,0 +1,113 @@
import { app, ipcMain, shell } from 'electron';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { IPC } from '../../shared/ipc';
import { log } from '../logger';
const READABLE_EXT: Record<string, string> = {
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.webp': 'image/webp',
'.svg': 'image/svg+xml',
'.bmp': 'image/bmp',
'.txt': 'text/plain',
'.log': 'text/plain',
'.csv': 'text/csv',
'.json': 'application/json',
'.md': 'text/markdown',
'.xml': 'application/xml',
'.html': 'text/html'
};
const FORBIDDEN_EXT = new Set([
'.exe', '.bat', '.cmd', '.ps1', '.vbs', '.msi', '.scr', '.pif', '.reg', '.sh',
'.com', '.hta', '.vbe', '.wsf', '.lnk', '.jar', '.dll', '.js', '.jse'
]);
export function getSharedDirectory(): string {
const candidates = [
path.join(os.homedir(), 'Documents', 'EveFlow_Shared'),
path.join(app.getPath('userData'), 'shared')
];
for (const dir of candidates) {
try {
fs.mkdirSync(dir, { recursive: true });
return dir;
} catch {
/* try next candidate */
}
}
return app.getPath('temp');
}
function normalizeSafe(filePath: string): string {
if (!filePath || typeof filePath !== 'string') throw new Error('Chemin invalide');
const normalized = path.normalize(filePath);
if (normalized.split(/[\\/]/).includes('..')) throw new Error('Traversee de repertoire refusee');
return normalized;
}
function isInsideAllowedRoots(target: string): boolean {
const roots = [getSharedDirectory(), os.homedir(), app.getPath('temp')];
const resolved = path.resolve(target);
return roots.some((root) => resolved.startsWith(path.resolve(root)));
}
function stripFileScheme(value: string): string {
let out = value.replace(/^file:\/\//, '');
// file:///C:/x -> /C:/x on Windows-style paths
if (/^\/[a-zA-Z]:/.test(out)) out = out.slice(1);
return decodeURIComponent(out);
}
export function registerFilesIpc(): void {
ipcMain.handle(IPC.readLocalFile, async (_e, filePath: string) => {
const target = normalizeSafe(stripFileScheme(filePath));
const ext = path.extname(target).toLowerCase();
const mime = READABLE_EXT[ext];
if (!mime) throw new Error(`Type de fichier non autorise : ${ext || '(aucune extension)'}`);
if (!isInsideAllowedRoots(target)) throw new Error('Chemin hors des dossiers autorises');
const stat = await fs.promises.stat(target);
if (stat.size > 25 * 1024 * 1024) throw new Error('Fichier trop volumineux (25 Mo max)');
const content = await fs.promises.readFile(target);
return `data:${mime};base64,${content.toString('base64')}`;
});
ipcMain.handle(IPC.writeSharedFile, async (_e, filename: string, content: string, isBase64 = false) => {
if (!filename || typeof filename !== 'string') throw new Error('Nom de fichier invalide');
const safeName = path.basename(filename);
if (safeName !== filename || safeName.startsWith('.') || /[<>:"|?*]/.test(safeName)) {
throw new Error('Nom de fichier non securise');
}
const ext = path.extname(safeName).toLowerCase();
if (FORBIDDEN_EXT.has(ext)) throw new Error(`Extension interdite : ${ext}`);
const target = path.join(getSharedDirectory(), safeName);
if (isBase64) {
const payload = content.replace(/^data:[^;]+;base64,/, '');
await fs.promises.writeFile(target, Buffer.from(payload, 'base64'));
} else {
await fs.promises.writeFile(target, content, 'utf8');
}
log('INFO', 'files', `shared file written: ${target}`);
return { path: target, url: `file:///${target.replace(/\\/g, '/')}` };
});
ipcMain.handle(IPC.openPath, async (_e, filePath: string) => {
const target = normalizeSafe(stripFileScheme(filePath));
const ext = path.extname(target).toLowerCase();
if (FORBIDDEN_EXT.has(ext)) throw new Error(`Ouverture refusee pour ${ext}`);
if (!fs.existsSync(target)) throw new Error('Fichier introuvable');
const result = await shell.openPath(target);
if (result) throw new Error(result);
return true;
});
ipcMain.handle(IPC.showInFolder, async (_e, filePath: string) => {
const target = normalizeSafe(stripFileScheme(filePath));
shell.showItemInFolder(target);
return true;
});
}
+159
View File
@@ -0,0 +1,159 @@
/**
* HTTP proxy: the renderer never talks to the network directly (webSecurity stays ON).
* Every request to Hermes / STT / TTS endpoints flows through here, which also removes
* CORS and mixed-content restrictions for LAN services served over plain HTTP.
*/
import { ipcMain, type WebContents } from 'electron';
import {
IPC,
type HttpProxyRequest,
type HttpProxyResponse,
type HttpStreamStart,
type HttpStreamEvent
} from '../../shared/ipc';
import { log } from '../logger';
const activeStreams = new Map<string, AbortController>();
function assertUrl(url: string): URL {
let parsed: URL;
try {
parsed = new URL(url);
} catch {
throw new Error(`URL invalide : ${url}`);
}
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
throw new Error(`Protocole non autorise : ${parsed.protocol}`);
}
return parsed;
}
function buildInit(req: HttpProxyRequest, signal: AbortSignal): RequestInit {
const headers: Record<string, string> = { ...(req.headers ?? {}) };
let body: RequestInit['body'];
if (req.multipart) {
const form = new FormData();
for (const [k, v] of Object.entries(req.multipart.fields)) form.append(k, v);
const file = req.multipart.file;
const bytes = new Uint8Array(file.data);
form.append(req.multipart.fileField ?? 'file', new Blob([bytes], { type: file.type }), file.name);
body = form;
for (const key of Object.keys(headers)) {
if (key.toLowerCase() === 'content-type') delete headers[key];
}
} else if (req.body !== undefined) {
body = req.body;
}
return { method: req.method ?? 'GET', headers, body, signal };
}
function headersToObject(headers: Headers): Record<string, string> {
const out: Record<string, string> = {};
headers.forEach((v, k) => {
out[k.toLowerCase()] = v;
});
return out;
}
export async function proxyFetch(req: HttpProxyRequest): Promise<HttpProxyResponse> {
assertUrl(req.url);
const controller = new AbortController();
const timeoutMs = req.timeoutMs ?? 60_000;
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(req.url, buildInit(req, controller.signal));
const base = {
ok: response.ok,
status: response.status,
statusText: response.statusText,
headers: headersToObject(response.headers)
};
if (req.responseType === 'binary') {
return { ...base, binary: new Uint8Array(await response.arrayBuffer()) };
}
return { ...base, text: await response.text() };
} catch (err) {
const e = err as Error;
if (e.name === 'AbortError') throw new Error(`Delai depasse (${Math.round(timeoutMs / 1000)}s) : ${req.url}`);
throw new Error(e.message || String(err));
} finally {
clearTimeout(timer);
}
}
async function startStream(sender: WebContents, id: string, req: HttpProxyRequest): Promise<HttpStreamStart> {
assertUrl(req.url);
const controller = new AbortController();
activeStreams.set(id, controller);
const send = (event: HttpStreamEvent) => {
if (!sender.isDestroyed()) sender.send(IPC.httpStreamEvent, event);
};
let response: Response;
try {
response = await fetch(req.url, buildInit(req, controller.signal));
} catch (err) {
activeStreams.delete(id);
throw new Error((err as Error).message || String(err));
}
const start: HttpStreamStart = {
id,
ok: response.ok,
status: response.status,
statusText: response.statusText,
headers: headersToObject(response.headers)
};
const pump = async () => {
try {
if (!response.body) {
send({ id, type: 'end' });
return;
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
// Hermes runs can be long, but a totally silent stream is abandoned after the idle timeout.
const idleMs = req.timeoutMs ?? 10 * 60_000;
for (;;) {
let idleTimer: ReturnType<typeof setTimeout> | undefined;
const idle = new Promise<never>((_, reject) => {
idleTimer = setTimeout(() => reject(new Error('Flux silencieux (timeout)')), idleMs);
});
const { done, value } = await Promise.race([reader.read(), idle]);
if (idleTimer) clearTimeout(idleTimer);
if (done) break;
send({ id, type: 'chunk', text: decoder.decode(value, { stream: true }) });
}
const tail = decoder.decode();
if (tail) send({ id, type: 'chunk', text: tail });
send({ id, type: 'end' });
} catch (err) {
const e = err as Error;
if (e.name === 'AbortError') send({ id, type: 'end' });
else send({ id, type: 'error', message: e.message || String(err) });
} finally {
activeStreams.delete(id);
}
};
void pump();
return start;
}
export function abortAllStreams(): void {
for (const controller of activeStreams.values()) controller.abort();
activeStreams.clear();
}
export function registerHttpIpc(): void {
ipcMain.handle(IPC.httpFetch, (_e, req: HttpProxyRequest) => proxyFetch(req));
ipcMain.handle(IPC.httpStreamStart, (event, id: string, req: HttpProxyRequest) => startStream(event.sender, id, req));
ipcMain.on(IPC.httpStreamAbort, (_e, id: string) => {
const controller = activeStreams.get(id);
if (controller) {
controller.abort();
activeStreams.delete(id);
log('DEBUG', 'http', `stream ${id} aborted by renderer`);
}
});
}
+54
View File
@@ -0,0 +1,54 @@
import { app, ipcMain } from 'electron';
import fs from 'node:fs';
import path from 'node:path';
import { IPC } from '../../shared/ipc';
type StoreData = Record<string, unknown>;
let cache: StoreData | null = null;
function storePath(): string {
return path.join(app.getPath('userData'), 'userdata.json');
}
function load(): StoreData {
if (cache) return cache;
try {
cache = JSON.parse(fs.readFileSync(storePath(), 'utf8')) as StoreData;
} catch {
cache = {};
}
return cache;
}
function persist(): void {
const target = storePath();
const tmp = target + '.tmp';
fs.writeFileSync(tmp, JSON.stringify(cache ?? {}, null, 2), 'utf8');
fs.renameSync(tmp, target);
}
export function storeGet<T = unknown>(key: string): T | null {
const data = load();
return (data[key] as T) ?? null;
}
export function storeSet(key: string, value: unknown): void {
const data = load();
data[key] = value;
persist();
}
export function registerStoreIpc(): void {
ipcMain.handle(IPC.storeGet, (_e, key: string) => storeGet(key));
ipcMain.handle(IPC.storeSet, (_e, key: string, value: unknown) => {
storeSet(key, value);
return true;
});
ipcMain.handle(IPC.storeDelete, (_e, key: string) => {
const data = load();
delete data[key];
persist();
return true;
});
}
+51
View File
@@ -0,0 +1,51 @@
import { ipcMain } from 'electron';
import os from 'node:os';
import { IPC, type SystemMetrics } from '../../shared/ipc';
interface CpuSnapshot {
idle: number;
total: number;
}
function snapshot(): CpuSnapshot {
let idle = 0;
let total = 0;
for (const cpu of os.cpus()) {
const t = cpu.times;
idle += t.idle;
total += t.user + t.nice + t.sys + t.idle + t.irq;
}
return { idle, total };
}
let last = snapshot();
function cpuLoadPct(): number {
const now = snapshot();
const idleDiff = now.idle - last.idle;
const totalDiff = now.total - last.total;
last = now;
if (totalDiff <= 0) return 0;
return Math.max(0, Math.min(100, 100 * (1 - idleDiff / totalDiff)));
}
export function collectMetrics(): SystemMetrics {
const cpus = os.cpus();
const totalMem = os.totalmem();
const freeMem = os.freemem();
return {
hostname: os.hostname().toUpperCase(),
platform: `${os.platform()} ${os.release()}`,
cpuModel: cpus[0]?.model?.trim() ?? 'CPU',
cpuCores: cpus.length,
cpuLoad: Math.round(cpuLoadPct() * 10) / 10,
cpuFreqMhz: cpus[0]?.speed ?? 0,
memUsedPct: totalMem > 0 ? Math.round(((totalMem - freeMem) / totalMem) * 1000) / 10 : 0,
memTotalGb: Math.round((totalMem / 1024 ** 3) * 10) / 10,
uptimeSec: Math.round(os.uptime())
};
}
export function registerTelemetryIpc(): void {
ipcMain.handle(IPC.metrics, () => collectMetrics());
}
+45
View File
@@ -0,0 +1,45 @@
import { app } from 'electron';
import fs from 'node:fs';
import path from 'node:path';
import type { LogEntry } from '../shared/ipc';
const MAX_LOG_BYTES = 5 * 1024 * 1024;
export function getLogPath(): string {
return path.join(app.getPath('userData'), 'eveflow.log');
}
export function writeLog(entry: LogEntry): void {
try {
const logPath = getLogPath();
const data = entry.data !== undefined ? ' | ' + safeJson(entry.data) : '';
const line = `[${entry.ts}] [${entry.level}] [${entry.tag}] ${entry.message}${data}\n`;
try {
const stat = fs.statSync(logPath);
if (stat.size > MAX_LOG_BYTES) fs.renameSync(logPath, logPath + '.old');
} catch {
/* first start: file does not exist yet */
}
fs.appendFileSync(logPath, line, 'utf8');
} catch (err) {
console.error('[logger] cannot write log file:', (err as Error).message);
}
}
export function log(level: LogEntry['level'], tag: string, message: string, data?: unknown): void {
const entry: LogEntry = { ts: new Date().toISOString(), level, tag, message, data };
const consoleLine = `[${tag}] ${message}`;
if (level === 'ERROR') console.error(consoleLine, data ?? '');
else if (level === 'WARN') console.warn(consoleLine, data ?? '');
else console.log(consoleLine, data ?? '');
writeLog(entry);
}
function safeJson(value: unknown): string {
try {
const text = JSON.stringify(value);
return text.length > 4000 ? text.slice(0, 4000) + '...' : text;
} catch {
return String(value);
}
}
+170
View File
@@ -0,0 +1,170 @@
import { app, BrowserWindow, globalShortcut, ipcMain, Menu, nativeImage, session, systemPreferences, Tray } from 'electron';
import path from 'node:path';
import { IPC, type AppInfo, type HotkeyEvent, type LogEntry, type WindowMode } from '../shared/ipc';
import { getLogPath, log, writeLog } from './logger';
import { registerStoreIpc, storeGet } from './ipc/store';
import { abortAllStreams, registerHttpIpc } from './ipc/http';
import { registerTelemetryIpc } from './ipc/telemetry';
import { getSharedDirectory, registerFilesIpc } from './ipc/files';
import { createMainWindow, getMainWindow, getWindowMode, setWindowMode, toggleWindowVisibility } from './window';
import { getWebhookStatus, startWebhookServer, stopWebhookServer } from './webhook';
// Audio playback must never be blocked behind a user gesture (TTS starts on incoming events).
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
let tray: Tray | null = null;
// -- Single instance --------------------------------------------------------
if (!app.requestSingleInstanceLock()) {
app.quit();
} else {
app.on('second-instance', () => {
const win = getMainWindow();
if (win) {
if (win.isMinimized()) win.restore();
win.show();
win.focus();
}
});
}
interface WebhookSettings {
enabled?: boolean;
port?: number;
secret?: string;
}
function readWebhookSettings(): WebhookSettings {
const saved = storeGet<WebhookSettings>('webhook');
return { enabled: true, port: 7842, secret: '', ...(saved ?? {}) };
}
async function bootWebhook(): Promise<void> {
const settings = readWebhookSettings();
if (settings.enabled === false) {
await stopWebhookServer();
return;
}
await startWebhookServer(getMainWindow, { port: Number(settings.port) || 7842, secret: settings.secret || undefined });
}
function sendHotkey(event: HotkeyEvent): void {
const win = getMainWindow();
if (win && !win.isDestroyed()) win.webContents.send(IPC.hotkey, event);
}
function registerShortcuts(): void {
const bindings: Array<[string, () => void]> = [
['CommandOrControl+Shift+Space', () => {
const win = getMainWindow();
if (win && !win.isVisible()) win.show();
sendHotkey('ptt-toggle');
}],
['CommandOrControl+Shift+J', () => toggleWindowVisibility()],
['CommandOrControl+Shift+Escape', () => sendHotkey('stop-speaking')]
];
for (const [accelerator, handler] of bindings) {
try {
if (!globalShortcut.register(accelerator, handler)) log('WARN', 'hotkey', `cannot register ${accelerator}`);
} catch (err) {
log('WARN', 'hotkey', `cannot register ${accelerator}: ${(err as Error).message}`);
}
}
}
function createTray(): void {
try {
const iconPath = app.isPackaged
? path.join(process.resourcesPath, 'icon.png')
: path.join(__dirname, '..', 'build', 'icon.png');
let image = nativeImage.createFromPath(iconPath);
if (image.isEmpty()) image = nativeImage.createEmpty();
else image = image.resize({ width: 16, height: 16 });
tray = new Tray(image);
tray.setToolTip('EveFlow - JARVIS HUD');
const rebuildMenu = () => {
const mode = getWindowMode();
tray?.setContextMenu(Menu.buildFromTemplate([
{ label: 'Afficher / masquer', click: () => toggleWindowVisibility() },
{ label: mode === 'compact' ? 'Mode HUD complet' : 'Mode compact flottant', click: () => setWindowMode(mode === 'compact' ? 'hud' : 'compact') },
{ label: 'Micro (Ctrl+Shift+Espace)', click: () => sendHotkey('ptt-toggle') },
{ type: 'separator' },
{ label: 'Quitter', click: () => app.quit() }
]));
};
rebuildMenu();
tray.on('click', () => toggleWindowVisibility());
ipcMain.on(IPC.windowSetMode, () => setTimeout(rebuildMenu, 0));
} catch (err) {
log('WARN', 'tray', `tray unavailable: ${(err as Error).message}`);
}
}
function configureSession(): void {
const ses = session.defaultSession;
ses.setPermissionRequestHandler((_wc, permission, callback) => {
callback(permission === 'media' || permission === 'notifications' || permission === 'clipboard-read');
});
ses.setPermissionCheckHandler((_wc, permission) => permission === 'media' || permission === 'notifications' || permission === 'clipboard-read');
if (process.platform === 'darwin') {
systemPreferences.askForMediaAccess('microphone').then((granted) => {
log('INFO', 'audio', `microphone access ${granted ? 'granted' : 'denied'}`);
}).catch(() => undefined);
}
}
function registerCoreIpc(): void {
ipcMain.on(IPC.windowControl, (_e, action: 'minimize' | 'maximize' | 'close' | 'hide') => {
const win = getMainWindow();
if (!win) return;
switch (action) {
case 'minimize': win.minimize(); break;
case 'maximize': win.isMaximized() ? win.unmaximize() : win.maximize(); break;
case 'hide': win.hide(); break;
case 'close': win.close(); break;
}
});
ipcMain.on(IPC.windowSetMode, (_e, mode: WindowMode) => setWindowMode(mode === 'compact' ? 'compact' : 'hud'));
ipcMain.on(IPC.log, (_e, entry: LogEntry) => writeLog(entry));
ipcMain.handle(IPC.appInfo, (): AppInfo => ({
version: app.getVersion(),
platform: process.platform,
isPackaged: app.isPackaged,
userDataPath: app.getPath('userData'),
sharedDir: getSharedDirectory(),
logPath: getLogPath()
}));
ipcMain.handle(IPC.webhookStatus, () => getWebhookStatus());
ipcMain.handle(IPC.webhookRestart, async () => {
await bootWebhook();
return getWebhookStatus();
});
}
app.whenReady().then(async () => {
log('INFO', 'app', `EveFlow ${app.getVersion()} starting (electron ${process.versions.electron}, chrome ${process.versions.chrome})`);
configureSession();
registerStoreIpc();
registerHttpIpc();
registerTelemetryIpc();
registerFilesIpc();
registerCoreIpc();
createMainWindow();
createTray();
registerShortcuts();
await bootWebhook();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createMainWindow();
});
});
app.on('will-quit', () => {
globalShortcut.unregisterAll();
abortAllStreams();
void stopWebhookServer();
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
+63
View File
@@ -0,0 +1,63 @@
import { contextBridge, ipcRenderer } from 'electron';
import {
IPC,
type AppInfo,
type HermesPushEvent,
type HotkeyEvent,
type HttpProxyRequest,
type HttpProxyResponse,
type HttpStreamEvent,
type HttpStreamStart,
type LogEntry,
type SystemMetrics,
type WebhookStatus,
type WindowMode
} from '../shared/ipc';
import type { EveFlowBridge, Unsubscribe } from '../shared/bridge';
function subscribe<T>(channel: string, callback: (payload: T) => void): Unsubscribe {
const listener = (_event: Electron.IpcRendererEvent, payload: T) => callback(payload);
ipcRenderer.on(channel, listener);
return () => ipcRenderer.removeListener(channel, listener);
}
const api: EveFlowBridge = {
window: {
control: (action: 'minimize' | 'maximize' | 'close' | 'hide') => ipcRenderer.send(IPC.windowControl, action),
setMode: (mode: WindowMode) => ipcRenderer.send(IPC.windowSetMode, mode),
onModeChanged: (cb: (mode: WindowMode) => void) => subscribe<WindowMode>(IPC.windowModeChanged, cb)
},
log: (entry: LogEntry) => ipcRenderer.send(IPC.log, entry),
store: {
get: <T = unknown>(key: string) => ipcRenderer.invoke(IPC.storeGet, key) as Promise<T | null>,
set: (key: string, value: unknown) => ipcRenderer.invoke(IPC.storeSet, key, value) as Promise<boolean>,
delete: (key: string) => ipcRenderer.invoke(IPC.storeDelete, key) as Promise<boolean>
},
http: {
fetch: (req: HttpProxyRequest) => ipcRenderer.invoke(IPC.httpFetch, req) as Promise<HttpProxyResponse>,
streamStart: (id: string, req: HttpProxyRequest) => ipcRenderer.invoke(IPC.httpStreamStart, id, req) as Promise<HttpStreamStart>,
streamAbort: (id: string) => ipcRenderer.send(IPC.httpStreamAbort, id),
onStreamEvent: (cb: (event: HttpStreamEvent) => void) => subscribe<HttpStreamEvent>(IPC.httpStreamEvent, cb)
},
system: {
metrics: () => ipcRenderer.invoke(IPC.metrics) as Promise<SystemMetrics>,
appInfo: () => ipcRenderer.invoke(IPC.appInfo) as Promise<AppInfo>
},
files: {
readLocal: (filePath: string) => ipcRenderer.invoke(IPC.readLocalFile, filePath) as Promise<string>,
writeShared: (filename: string, content: string, isBase64 = false) =>
ipcRenderer.invoke(IPC.writeSharedFile, filename, content, isBase64) as Promise<{ path: string; url: string }>,
openPath: (filePath: string) => ipcRenderer.invoke(IPC.openPath, filePath) as Promise<boolean>,
showInFolder: (filePath: string) => ipcRenderer.invoke(IPC.showInFolder, filePath) as Promise<boolean>
},
hermes: {
onPush: (cb: (event: HermesPushEvent) => void) => subscribe<HermesPushEvent>(IPC.hermesPush, cb),
webhookStatus: () => ipcRenderer.invoke(IPC.webhookStatus) as Promise<WebhookStatus>,
webhookRestart: () => ipcRenderer.invoke(IPC.webhookRestart) as Promise<WebhookStatus>
},
hotkeys: {
on: (cb: (event: HotkeyEvent) => void) => subscribe<HotkeyEvent>(IPC.hotkey, cb)
}
};
contextBridge.exposeInMainWorld('eveflow', api);
+114
View File
@@ -0,0 +1,114 @@
/**
* Local webhook server: Hermes (cron deliveries, gateway mirrors, scripts) pushes JSON here
* and EveFlow displays / speaks the result. POST /eveflow/hook, GET /health.
*/
import http from 'node:http';
import { timingSafeEqual } from 'node:crypto';
import type { BrowserWindow } from 'electron';
import { IPC, type WebhookStatus } from '../shared/ipc';
import { normalizeHermesPush } from '../shared/hermesPush';
import { log } from './logger';
export const WEBHOOK_PATH = '/eveflow/hook';
const MAX_BODY_BYTES = 2 * 1024 * 1024;
export interface WebhookOptions {
port: number;
secret?: string;
host?: string;
}
let server: http.Server | null = null;
let status: WebhookStatus = { listening: false, port: 7842, path: WEBHOOK_PATH, secretConfigured: false };
function secretMatches(provided: string | undefined, expected: string): boolean {
if (!provided) return false;
const a = Buffer.from(provided);
const b = Buffer.from(expected);
return a.length === b.length && timingSafeEqual(a, b);
}
export function getWebhookStatus(): WebhookStatus {
return status;
}
export function stopWebhookServer(): Promise<void> {
return new Promise((resolve) => {
if (!server) return resolve();
server.close(() => resolve());
server = null;
status = { ...status, listening: false };
});
}
export async function startWebhookServer(getWindow: () => BrowserWindow | null, options: WebhookOptions): Promise<WebhookStatus> {
await stopWebhookServer();
const { port, secret } = options;
const host = options.host ?? '0.0.0.0';
server = http.createServer((req, res) => {
const json = (code: number, payload: unknown) => {
res.writeHead(code, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
res.end(JSON.stringify(payload));
};
if (req.method === 'GET' && (req.url === '/health' || req.url === '/')) {
return json(200, { ok: true, app: 'eveflow', path: WEBHOOK_PATH });
}
if (req.method !== 'POST' || !req.url?.startsWith(WEBHOOK_PATH)) {
return json(404, { error: 'Not Found' });
}
if (secret) {
const auth = req.headers.authorization?.replace(/^Bearer\s+/i, '');
const custom = req.headers['x-eveflow-secret'];
const provided = typeof custom === 'string' ? custom : auth;
if (!secretMatches(provided, secret)) {
log('WARN', 'webhook', `rejected push from ${req.socket.remoteAddress}: bad secret`);
return json(401, { error: 'Unauthorized' });
}
}
let body = '';
let tooLarge = false;
req.on('data', (chunk: Buffer) => {
if (tooLarge) return;
body += chunk.toString('utf8');
if (body.length > MAX_BODY_BYTES) {
tooLarge = true;
json(413, { error: 'Payload too large' });
req.destroy();
}
});
req.on('end', () => {
if (tooLarge) return;
try {
const raw: unknown = body.trim() ? JSON.parse(body) : {};
const events = normalizeHermesPush(raw);
log('INFO', 'webhook', `${events.length} event(s) from ${events[0]?.source ?? '?'} (${req.socket.remoteAddress})`);
const win = getWindow();
if (win && !win.isDestroyed()) {
for (const event of events) win.webContents.send(IPC.hermesPush, event);
}
json(200, { ok: true, events: events.length });
} catch (err) {
log('WARN', 'webhook', `invalid JSON payload: ${(err as Error).message}`);
json(400, { error: 'Invalid JSON' });
}
});
});
return new Promise((resolve) => {
server!.once('error', (err: NodeJS.ErrnoException) => {
log('ERROR', 'webhook', `server error: ${err.message}`);
status = { listening: false, port, path: WEBHOOK_PATH, secretConfigured: !!secret, error: err.message };
server = null;
resolve(status);
});
server!.listen(port, host, () => {
log('INFO', 'webhook', `listening on http://${host}:${port}${WEBHOOK_PATH}`);
status = { listening: true, port, path: WEBHOOK_PATH, secretConfigured: !!secret };
resolve(status);
});
});
}
+143
View File
@@ -0,0 +1,143 @@
import { app, BrowserWindow, screen, shell } from 'electron';
import fs from 'node:fs';
import path from 'node:path';
import { IPC, type WindowMode } from '../shared/ipc';
import { log } from './logger';
const HUD_SIZE = { width: 1320, height: 860, minWidth: 980, minHeight: 640 };
const COMPACT_SIZE = { width: 380, height: 620, minWidth: 320, minHeight: 420 };
let mainWindow: BrowserWindow | null = null;
let currentMode: WindowMode = 'hud';
let hudBounds: Electron.Rectangle | null = null;
export function getMainWindow(): BrowserWindow | null {
return mainWindow;
}
export function getWindowMode(): WindowMode {
return currentMode;
}
function fallbackHtml(reason: string): string {
return `<!doctype html><html><body style="margin:0;font-family:Segoe UI,Arial,sans-serif;background:#03070d;color:#9fe9ff;display:flex;align-items:center;justify-content:center;height:100vh">
<div style="max-width:560px;padding:28px;border:1px solid #1d5c70;border-radius:14px;background:#061018">
<h1 style="margin:0 0 12px;font-size:20px;letter-spacing:.08em">EVEFLOW - INTERFACE INDISPONIBLE</h1>
<p style="line-height:1.5">${reason}</p><p>Lancez <code>npm run build</code> puis relancez l'application.</p></div></body></html>`;
}
async function loadRenderer(win: BrowserWindow): Promise<void> {
const devUrl = process.env.VITE_DEV_SERVER_URL;
if (devUrl && !app.isPackaged) {
try {
await win.loadURL(devUrl);
win.webContents.openDevTools({ mode: 'detach' });
return;
} catch (err) {
log('WARN', 'window', `dev server unreachable (${(err as Error).message}), loading built bundle`);
}
}
const builtIndex = path.join(__dirname, '..', 'dist', 'index.html');
if (fs.existsSync(builtIndex)) {
await win.loadFile(builtIndex);
return;
}
await win.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(fallbackHtml('Le bundle dist/index.html est introuvable.')));
}
export function createMainWindow(): BrowserWindow {
const win = new BrowserWindow({
...HUD_SIZE,
frame: false,
transparent: true,
backgroundColor: '#00000000',
hasShadow: true,
show: false,
title: 'EveFlow',
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false,
sandbox: true,
webSecurity: true,
allowRunningInsecureContent: false,
backgroundThrottling: false,
spellcheck: false
}
});
mainWindow = win;
win.once('ready-to-show', () => {
setTimeout(() => {
if (!win.isDestroyed()) win.show();
}, 60);
});
win.webContents.setWindowOpenHandler(({ url }) => {
if (/^https?:\/\//i.test(url)) void shell.openExternal(url);
return { action: 'deny' };
});
win.webContents.on('will-navigate', (event, url) => {
if (!url.startsWith('file://') && !url.startsWith(process.env.VITE_DEV_SERVER_URL ?? 'http://127.0.0.1:5173')) {
event.preventDefault();
void shell.openExternal(url);
}
});
win.on('closed', () => {
mainWindow = null;
});
loadRenderer(win).catch((err) => {
log('ERROR', 'window', `renderer load failed: ${(err as Error).message}`);
void win.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(fallbackHtml("Une erreur inattendue a interrompu le chargement de l'interface.")));
});
return win;
}
export function setWindowMode(mode: WindowMode): void {
const win = mainWindow;
if (!win || win.isDestroyed()) return;
if (mode === currentMode) {
win.webContents.send(IPC.windowModeChanged, mode);
return;
}
if (mode === 'compact') {
hudBounds = win.getBounds();
const display = screen.getDisplayMatching(win.getBounds());
const area = display.workArea;
win.setMinimumSize(COMPACT_SIZE.minWidth, COMPACT_SIZE.minHeight);
win.setBounds({
x: area.x + area.width - COMPACT_SIZE.width - 24,
y: area.y + area.height - COMPACT_SIZE.height - 24,
width: COMPACT_SIZE.width,
height: COMPACT_SIZE.height
}, true);
win.setAlwaysOnTop(true, 'floating');
win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
} else {
win.setAlwaysOnTop(false);
win.setVisibleOnAllWorkspaces(false);
win.setMinimumSize(HUD_SIZE.minWidth, HUD_SIZE.minHeight);
if (hudBounds) win.setBounds(hudBounds, true);
else {
win.setSize(HUD_SIZE.width, HUD_SIZE.height, true);
win.center();
}
}
currentMode = mode;
win.webContents.send(IPC.windowModeChanged, mode);
}
export function toggleWindowVisibility(): void {
const win = mainWindow;
if (!win || win.isDestroyed()) return;
if (win.isVisible() && win.isFocused()) {
win.hide();
} else {
win.show();
win.focus();
}
}
+4 -3
View File
@@ -2,10 +2,11 @@
<html lang="fr">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🤖</text></svg>" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="EveFlow - Assistant IA compagnon 3D rétro-futuriste." />
<title>EveFlow Companion</title>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data: blob: http: https:; media-src 'self' blob: data:; connect-src 'self' http: https: ws: wss: blob: data:; worker-src 'self' blob:;" />
<meta name="description" content="EveFlow — interface vocale JARVIS pour Hermes Agent." />
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Ccircle cx='32' cy='32' r='26' fill='none' stroke='%2334e4ff' stroke-width='4'/%3E%3Ccircle cx='32' cy='32' r='10' fill='%2334e4ff'/%3E%3C/svg%3E" />
<title>EveFlow</title>
</head>
<body>
<div id="root"></div>
-755
View File
@@ -1,755 +0,0 @@
const { app, BrowserWindow, ipcMain, session } = require('electron');
const path = require('path');
const fs = require('fs');
const os = require('os');
// Autoriser le chargement de fichiers locaux via fetch sous le protocole file://
app.commandLine.appendSwitch('disable-web-security');
app.commandLine.appendSwitch('allow-file-access-from-files');
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
let mainWindow;
// ── Single Instance Lock ───────────────────────────────────────────────────
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
process.exit(0);
}
app.on('second-instance', () => {
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
});
// ── Logging Setup ───────────────────────────────────────────────────────────
function getLogPath() {
const userDataDir = app.getPath('userData');
return path.join(userDataDir, 'eveflow.log');
}
function writeLogEntry(entry) {
try {
const logPath = getLogPath();
const line = `[${entry.ts}] [${entry.level}] [${entry.tag}] ${entry.message}` +
(entry.data !== undefined ? ' | ' + JSON.stringify(entry.data) : '') + '\n';
// Rotation simple : si le fichier dépasse 5 Mo, on le renomme et on repart
try {
const stat = fs.statSync(logPath);
if (stat.size > 5 * 1024 * 1024) {
fs.renameSync(logPath, logPath + '.old');
}
} catch { /* fichier inexistant — normal au premier démarrage */ }
fs.appendFileSync(logPath, line, 'utf8');
} catch (err) {
console.error('[main] Impossible d\'écrire dans le log:', err.message);
}
}
// ── Webhook Server (Hermes → EveFlow push events) ──────────────────────────
const http = require('http');
const WEBHOOK_PORT = 7842;
let webhookServer = null;
// Normalize any Hermes push payload into an array of { type, role, text, source } events.
// Handles multiple formats so EveFlow mirrors both sides of Telegram conversations.
function normalizeHermesEvents(raw) {
const src = raw.platform || raw.source || 'webhook';
const collectImages = (obj) => {
const images = [];
const push = (value) => {
if (!value) return;
if (typeof value === 'string') images.push(value);
else if (typeof value === 'object') push(value.url || value.href || value.path || value.file || value.file_url || value.media_url);
};
for (const key of ['image', 'image_url', 'photo', 'media', 'url', 'file', 'file_url', 'media_url']) {
push(obj?.[key]);
}
for (const key of ['images', 'photos', 'media_urls', 'attachments', 'files']) {
const value = obj?.[key];
if (Array.isArray(value)) value.forEach(push);
else push(value);
}
return [...new Set(images)];
};
const withImages = (event, obj) => {
const images = collectImages(obj);
return images.length ? { ...event, images } : event;
};
// Format A — { type:'message', payload:{ text, role?, platform? } }
if (raw.type === 'message' && raw.payload?.text) {
return [withImages({
type: 'message',
role: raw.payload.role || 'assistant',
text: raw.payload.text,
source: raw.payload.platform || src
}, raw.payload)];
}
// Format B — run completed: { event:'run.completed', input?, output, platform? }
if ((raw.event === 'run.completed' || raw.type === 'run.completed') && raw.output) {
const events = [];
if (raw.input) events.push({ type: 'message', role: 'user', text: raw.input, source: src });
events.push(withImages({ type: 'message', role: 'assistant', text: raw.output, source: src }, raw));
return events;
}
// Format C — direct: { role, text, source? }
if (raw.role && raw.text) {
return [withImages({ type: 'message', role: raw.role, text: raw.text, source: src }, raw)];
}
// Format D — legacy: { type:'user_message'|'assistant_message', text }
if (raw.text && raw.type) {
const role = raw.type.includes('user') ? 'user' : 'assistant';
return [withImages({ type: 'message', role, text: raw.text, source: src }, raw)];
}
// Passthrough — let renderer decide
return [raw];
}
function startWebhookServer() {
webhookServer = http.createServer((req, res) => {
// Only accept POST /eveflow/hook
if (req.method !== 'POST' || req.url !== '/eveflow/hook') {
res.writeHead(404, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Not Found' }));
return;
}
let body = '';
req.on('data', chunk => { body += chunk; });
req.on('end', () => {
try {
const raw = JSON.parse(body);
const events = normalizeHermesEvents(raw);
console.log(`[EveFlow Webhook] ${events.length} event(s) from ${events[0]?.source || '?'}`);
writeLogEntry({
ts: new Date().toISOString(),
level: 'INFO',
tag: 'Webhook',
message: `${events.length} event(s) received`,
data: events
});
// Forward each normalized event to the renderer
if (mainWindow && !mainWindow.isDestroyed()) {
for (const event of events) {
mainWindow.webContents.send('hermes-push', event);
}
}
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ ok: true, events: events.length }));
} catch (err) {
console.error('[EveFlow Webhook] Parse error:', err.message);
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Invalid JSON' }));
}
});
});
webhookServer.listen(WEBHOOK_PORT, '0.0.0.0', () => {
console.log(`[EveFlow] Webhook server listening on http://0.0.0.0:${WEBHOOK_PORT}/eveflow/hook`);
});
webhookServer.on('error', (err) => {
console.error(`[EveFlow] Webhook server error: ${err.message}`);
});
}
function stopWebhookServer() {
if (webhookServer) {
webhookServer.close();
webhookServer = null;
}
}
function loadFallbackPage(reason) {
const html = `
<html>
<body style="margin:0;font-family:Arial,sans-serif;background:#f4f8fc;color:#0f172a;display:flex;align-items:center;justify-content:center;height:100vh;">
<div style="max-width:560px;padding:28px;border:2px solid #0f172a;background:white;border-radius:18px;">
<h1 style="margin:0 0 12px;font-size:22px;">EveFlow n'a pas pu charger l'interface</h1>
<p style="line-height:1.5;">${reason}</p>
<p style="line-height:1.5;">Lance <code>npm run build</code>, puis relance l'application.</p>
</div>
</body>
</html>
`;
return mainWindow.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(html)}`);
}
function loadBuiltApp() {
const builtIndex = path.join(__dirname, 'dist', 'index.html');
if (fs.existsSync(builtIndex)) {
return mainWindow.loadFile(builtIndex);
}
return loadFallbackPage("Le serveur Vite est indisponible et le dossier dist/index.html n'existe pas.");
}
async function loadApp() {
const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged;
if (!isDev) {
await loadBuiltApp();
return;
}
const devServerUrl = process.env.VITE_DEV_SERVER_URL || 'http://localhost:5173';
try {
await mainWindow.loadURL(devServerUrl);
} catch (error) {
console.error(`Impossible de charger ${devServerUrl}; bascule sur le build local.`, error);
await loadBuiltApp();
}
}
function createWindow() {
mainWindow = new BrowserWindow({
width: 1120,
height: 860,
minWidth: 900,
minHeight: 680,
frame: false, // Supprime la barre de titre classique pour un style rétro-futuriste personnalisé
transparent: true, // Permet la transparence (fond de fenêtre transparent)
backgroundColor: '#00000000', // Fond transparent
hasShadow: true,
show: false, // Cache la fenêtre au démarrage pour éviter les problèmes visuels de DWM
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true, // Sécurité Zero Trust active
nodeIntegration: false,
webSecurity: false, // Permet les requêtes HTTP vers API locales/LAN
allowRunningInsecureContent: true, // Autorise HTTP depuis le renderer (API locales)
backgroundThrottling: false, // Empêche Chromium de suspendre les processus audio/TTS en arrière-plan
},
});
mainWindow.once('ready-to-show', () => {
// Petit délai de sécurité (80ms) pour garantir la synchronisation DWM sous Windows
setTimeout(() => {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.show();
}
}, 80);
});
loadApp().catch((error) => {
console.error("Echec du chargement de l'application.", error);
loadFallbackPage("Une erreur inattendue a interrompu le chargement de l'interface.");
});
mainWindow.on('closed', () => {
mainWindow = null;
});
}
app.whenReady().then(() => {
// Configurer l'intercepteur de requêtes pour Google TTS pour contourner le blocage HTTP 403 (User-Agent Electron)
session.defaultSession.webRequest.onBeforeSendHeaders(
{ urls: ['https://translate.google.com/*'] },
(details, callback) => {
details.requestHeaders['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36';
details.requestHeaders['Referer'] = 'https://translate.google.com/';
callback({ cancel: false, requestHeaders: details.requestHeaders });
}
);
// Autoriser l'accès aux périphériques de capture (microphone) sous Electron
session.defaultSession.setPermissionRequestHandler((webContents, permission, callback) => {
if (permission === 'media') {
return callback(true);
}
callback(false);
});
startWebhookServer();
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
app.on('window-all-closed', () => {
stopWebhookServer();
if (process.platform !== 'darwin') {
app.quit();
}
});
// IPC Handler pour le contrôle de la fenêtre (Header personnalisé)
ipcMain.on('window-control', (event, action) => {
if (!mainWindow) return;
switch (action) {
case 'minimize':
mainWindow.minimize();
break;
case 'maximize':
if (mainWindow.isMaximized()) {
mainWindow.unmaximize();
} else {
mainWindow.maximize();
}
break;
case 'close':
mainWindow.close();
break;
}
});
// IPC Handler pour basculer en mode flottant compact transparent (Eve Widget)
ipcMain.on('set-window-mode', (event, mode) => {
if (!mainWindow) return;
if (mode === 'floating') {
// Mode flottant compact : 300x600
mainWindow.setResizable(true);
mainWindow.setMinimumSize(250, 350);
mainWindow.setSize(300, 600);
mainWindow.setAlwaysOnTop(true, 'screen-saver');
// Positionner dans le coin inférieur droit de l'écran principal
const { screen } = require('electron');
const primaryDisplay = screen.getPrimaryDisplay();
const { width, height } = primaryDisplay.workAreaSize;
mainWindow.setPosition(width - 320, height - 620);
event.reply('window-mode-changed', 'floating');
} else {
// Mode normal : chat complet
mainWindow.setAlwaysOnTop(false);
mainWindow.setMinimumSize(900, 680);
mainWindow.setSize(1120, 860);
mainWindow.center();
event.reply('window-mode-changed', 'normal');
}
});
// IPC Handler pour ouvrir/fermer le cockpit sans ecraser Eve.
ipcMain.on('set-cockpit-mode', (_event, isOpen) => {
if (!mainWindow) return;
if (mainWindow.isMaximized()) return;
const { screen } = require('electron');
const display = screen.getDisplayMatching(mainWindow.getBounds());
const workArea = display.workArea;
const bounds = mainWindow.getBounds();
const targetWidth = isOpen ? 1460 : 1120;
const nextWidth = Math.min(targetWidth, Math.max(900, workArea.width - 40));
const nextHeight = Math.min(Math.max(bounds.height, 820), workArea.height - 40);
const nextX = Math.min(bounds.x, workArea.x + workArea.width - nextWidth - 20);
const nextY = Math.min(bounds.y, workArea.y + workArea.height - nextHeight - 20);
mainWindow.setMinimumSize(isOpen ? 1180 : 900, 680);
mainWindow.setBounds({
x: Math.max(workArea.x + 20, nextX),
y: Math.max(workArea.y + 20, nextY),
width: nextWidth,
height: nextHeight
}, true);
});
// ── IPC Handler : écriture des logs du renderer vers disque ─────────────────
ipcMain.on('write-log', (event, entry) => {
writeLogEntry(entry);
});
// ── IPC Handler : store persistant (indépendant de l'origine HTTP/file://) ──
// Lit/écrit C:\Users\...\AppData\Roaming\eveflow\userdata.json
function getStorePath() {
return path.join(app.getPath('userData'), 'userdata.json');
}
function readStoreFile() {
try {
const raw = fs.readFileSync(getStorePath(), 'utf8');
return JSON.parse(raw);
} catch {
return {};
}
}
function writeStoreFile(data) {
try {
fs.writeFileSync(getStorePath(), JSON.stringify(data, null, 2), 'utf8');
} catch (err) {
console.error('[EveFlow] Impossible d\'écrire userdata.json:', err.message);
}
}
ipcMain.handle('store-get', (_event, key) => {
const store = readStoreFile();
return store[key] ?? null;
});
ipcMain.handle('store-set', (_event, key, value) => {
const store = readStoreFile();
store[key] = value;
writeStoreFile(store);
return true;
});
// Handler de lecture de fichiers locaux sécurisé (Zéro Trust)
// Retourne une Data URL (base64) pour contourner les restrictions CORS de Chromium
ipcMain.handle('read-local-file', async (_event, filePath) => {
try {
if (!filePath || typeof filePath !== 'string') {
throw new Error("Chemin invalide");
}
// Normalisation du chemin
const normalizedPath = path.normalize(filePath);
// Prévention des attaques par traversée de répertoires
if (normalizedPath.includes('..')) {
throw new Error("Accès interdit (tentative de traversée de répertoires)");
}
// Validation des extensions de fichiers (Zéro Trust)
const ext = path.extname(normalizedPath).toLowerCase();
const allowedExtensions = [
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.bmp',
'.txt', '.csv', '.json', '.md', '.log', '.xml'
];
if (!allowedExtensions.includes(ext)) {
throw new Error(`Type de fichier non autorisé : ${ext}`);
}
// Vérifier l'existence du fichier
if (!fs.existsSync(normalizedPath)) {
throw new Error("Fichier introuvable");
}
// Mappage des types MIME
let mimeType = 'application/octet-stream';
if (ext === '.png') mimeType = 'image/png';
else if (ext === '.jpg' || ext === '.jpeg') mimeType = 'image/jpeg';
else if (ext === '.gif') mimeType = 'image/gif';
else if (ext === '.webp') mimeType = 'image/webp';
else if (ext === '.svg') mimeType = 'image/svg+xml';
else if (ext === '.txt' || ext === '.log') mimeType = 'text/plain';
else if (ext === '.csv') mimeType = 'text/csv';
else if (ext === '.json') mimeType = 'application/json';
else if (ext === '.md') mimeType = 'text/markdown';
// Lecture du fichier sur le disque
const content = fs.readFileSync(normalizedPath);
const base64 = content.toString('base64');
return `data:${mimeType};base64,${base64}`;
} catch (err) {
console.error(`[main] Erreur de lecture de fichier local (${filePath}) :`, err.message);
writeLogEntry({
ts: new Date().toISOString(),
level: 'ERROR',
tag: 'IPC-File',
message: `Échec de lecture du fichier: ${filePath} - ${err.message}`
});
throw err;
}
});
// Handler pour charger une image distante via Node.js (contourne CORS et les restrictions du navigateur Electron)
// Retourne une Data URL base64 pour un affichage garanti sans flickering ni erreur CORS
ipcMain.handle('fetch-remote-image', async (_event, url, extraHeaders = {}) => {
const https = require('https');
const http = require('http');
writeLogEntry({ ts: new Date().toISOString(), level: 'INFO', tag: 'IPC-Image', message: `fetch-remote-image: ${url}` });
return new Promise((resolve, reject) => {
try {
if (!url || typeof url !== 'string' || (!url.startsWith('http://') && !url.startsWith('https://'))) {
const err = `URL invalide : ${url}`;
writeLogEntry({ ts: new Date().toISOString(), level: 'ERROR', tag: 'IPC-Image', message: err });
reject(new Error(err));
return;
}
const client = url.startsWith('https://') ? https : http;
let timeoutId;
let isSettled = false;
const settleReject = (err) => {
if (isSettled) return;
isSettled = true;
clearTimeout(timeoutId);
reject(err);
};
const settleResolve = (value) => {
if (isSettled) return;
isSettled = true;
clearTimeout(timeoutId);
resolve(value);
};
const req = client.get(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'image/*, */*',
...extraHeaders,
},
}, (res) => {
writeLogEntry({ ts: new Date().toISOString(), level: 'INFO', tag: 'IPC-Image', message: `HTTP ${res.statusCode} — Content-Type: ${res.headers['content-type']} — URL: ${url}` });
// Gérer les redirects HTTP 301/302
if ((res.statusCode === 301 || res.statusCode === 302) && res.headers.location) {
writeLogEntry({ ts: new Date().toISOString(), level: 'INFO', tag: 'IPC-Image', message: `Redirect → ${res.headers.location}` });
// Suivre le redirect récursivement
const newUrl = res.headers.location;
const newClient = newUrl.startsWith('https://') ? https : http;
newClient.get(newUrl, { headers: { 'User-Agent': 'Mozilla/5.0', 'Accept': 'image/*' } }, (res2) => {
if (res2.statusCode !== 200) { reject(new Error(`HTTP ${res2.statusCode} après redirect`)); return; }
const chunks2 = [];
res2.on('data', c => chunks2.push(c));
res2.on('end', () => {
const buf = Buffer.concat(chunks2);
const ct = ((res2.headers['content-type'] || 'image/jpeg').split(';')[0]).trim();
settleResolve(`data:${ct};base64,${buf.toString('base64')}`);
});
}).on('error', settleReject);
return;
}
if (res.statusCode !== 200) {
const err = `HTTP ${res.statusCode} pour ${url}`;
writeLogEntry({ ts: new Date().toISOString(), level: 'ERROR', tag: 'IPC-Image', message: err });
res.resume();
settleReject(new Error(err));
return;
}
const chunks = [];
res.on('data', chunk => chunks.push(chunk));
res.on('end', () => {
try {
const buf = Buffer.concat(chunks);
const ct = ((res.headers['content-type'] || 'image/jpeg').split(';')[0]).trim();
const dataUrl = `data:${ct};base64,${buf.toString('base64')}`;
writeLogEntry({ ts: new Date().toISOString(), level: 'INFO', tag: 'IPC-Image', message: `Image chargée OK — ${buf.length} octets — ${ct}` });
settleResolve(dataUrl);
} catch (e) {
settleReject(e);
}
});
res.on('error', settleReject);
});
timeoutId = setTimeout(() => {
req.destroy();
const err = `Timeout (12s) pour ${url}`;
writeLogEntry({ ts: new Date().toISOString(), level: 'ERROR', tag: 'IPC-Image', message: err });
settleReject(new Error(err));
}, 12000);
req.on('error', (err) => {
writeLogEntry({ ts: new Date().toISOString(), level: 'ERROR', tag: 'IPC-Image', message: `Erreur réseau: ${err.message} — ${url}` });
settleReject(err);
});
} catch (err) {
writeLogEntry({ ts: new Date().toISOString(), level: 'ERROR', tag: 'IPC-Image', message: `Exception: ${err.message}` });
reject(err);
}
});
});
// ── CPU Telemetry Helper ───────────────────────────────────────────────────
function getCpuLoad() {
const cpus = os.cpus();
if (!cpus || cpus.length === 0) return { idle: 0, total: 0 };
let user = 0, nice = 0, sys = 0, idle = 0, irq = 0;
for (const cpu of cpus) {
user += cpu.times.user;
nice += cpu.times.nice;
sys += cpu.times.sys;
idle += cpu.times.idle;
irq += cpu.times.irq;
}
const total = user + nice + sys + idle + irq;
return { idle, total };
}
let lastCpuStats = getCpuLoad();
function getRealCpuPercentage() {
const current = getCpuLoad();
const idleDiff = current.idle - lastCpuStats.idle;
const totalDiff = current.total - lastCpuStats.total;
lastCpuStats = current;
if (totalDiff === 0) return 0;
return Math.max(0, Math.min(100, 100 * (1 - idleDiff / totalDiff)));
}
ipcMain.handle('get-system-metrics', async () => {
try {
const hostname = os.hostname().toUpperCase();
const cpus = os.cpus();
const baseFreq = (cpus && cpus.length > 0) ? cpus[0].speed : 2400; // fallback to 2.4 GHz
// Measure actual CPU percentage since last check
const cpuLoad = getRealCpuPercentage();
// 1. Dynamic frequency: baseline frequency with small jitter + load boost
const jitter = (Math.random() - 0.5) * 12; // dynamic fluctuation
const dynamicFreq = Math.round(baseFreq * (1.0 + (cpuLoad / 100) * 0.15) + jitter);
// 2. Dynamic temperature matching load: baseline of 35.8°C + load increase + thermal noise
const thermalNoise = (Math.random() - 0.5) * 0.6;
const cpuTemp = parseFloat((35.8 + (cpuLoad * 0.38) + thermalNoise).toFixed(1));
return {
hostname,
cpuFreq: dynamicFreq,
cpuTemp
};
} catch (err) {
console.error('[main] Erreur lors de la télémétrie:', err.message);
return {
hostname: 'UNKNOWN_HOST',
cpuFreq: 2400,
cpuTemp: 37.0
};
}
});
// ── Shared Directory Resolution ─────────────────────────────────────────────
function getSharedDirectory() {
try {
const docsDir = path.join(os.homedir(), 'Documents', 'EveFlow_Shared');
if (!fs.existsSync(docsDir)) {
fs.mkdirSync(docsDir, { recursive: true });
}
return docsDir;
} catch (err) {
console.warn('[main] Impossible de créer EveFlow_Shared dans Documents, bascule vers appData:', err.message);
const fallbackDir = path.join(app.getPath('userData'), 'shared');
if (!fs.existsSync(fallbackDir)) {
fs.mkdirSync(fallbackDir, { recursive: true });
}
return fallbackDir;
}
}
// ── IPC Handler : Écriture de fichier partagé sécurisé ──────────────────────
ipcMain.handle('write-shared-file', async (_event, filename, content, isBase64 = false) => {
try {
if (!filename || typeof filename !== 'string') {
throw new Error("Nom de fichier invalide");
}
// Assainissement Zero Trust du nom de fichier
const sanitizedFilename = path.basename(filename);
if (sanitizedFilename.includes('..') || sanitizedFilename !== filename) {
throw new Error("Nom de fichier non sécurisé (tentative de traversée de répertoire)");
}
// Validation stricte des extensions interdites (Zero Trust)
const ext = path.extname(sanitizedFilename).toLowerCase();
const forbiddenExtensions = [
'.exe', '.bat', '.cmd', '.ps1', '.vbs', '.msi', '.scr', '.pif', '.reg', '.sh',
'.com', '.hta', '.vbe', '.wsf', '.lnk'
];
if (forbiddenExtensions.includes(ext)) {
throw new Error(`Extension de fichier interdite pour des raisons de sécurité : ${ext}`);
}
const sharedDir = getSharedDirectory();
const targetPath = path.join(sharedDir, sanitizedFilename);
if (isBase64) {
const base64Data = content.replace(/^data:image\/\w+;base64,/, "");
fs.writeFileSync(targetPath, Buffer.from(base64Data, 'base64'));
} else {
fs.writeFileSync(targetPath, content, 'utf8');
}
writeLogEntry({
ts: new Date().toISOString(),
level: 'INFO',
tag: 'IPC-FileWrite',
message: `Fichier partagé écrit avec succès : ${targetPath}`
});
// Retourner au format d'URL de fichier local exploitable par Chromium
return `file:///${targetPath.replace(/\\/g, '/')}`;
} catch (err) {
console.error('[main] Erreur write-shared-file:', err.message);
writeLogEntry({
ts: new Date().toISOString(),
level: 'ERROR',
tag: 'IPC-FileWrite',
message: `Échec d'écriture de fichier partagé (${filename}) : ${err.message}`
});
throw err;
}
});
// ── IPC Handler : Ouverture sécurisée de fichier local par l'OS ─────────────
ipcMain.handle('open-local-file', async (_event, filePath) => {
try {
if (!filePath || typeof filePath !== 'string') {
throw new Error("Chemin de fichier invalide");
}
const normalizedPath = path.normalize(filePath);
if (normalizedPath.includes('..')) {
throw new Error("Accès interdit (tentative de traversée de répertoires)");
}
// Validation de sécurité stricte contre l'exécution de binaires/scripts arbitraires
const ext = path.extname(normalizedPath).toLowerCase();
const forbiddenExtensions = [
'.exe', '.bat', '.cmd', '.ps1', '.vbs', '.msi', '.scr', '.pif', '.reg', '.sh',
'.com', '.hta', '.vbe', '.wsf', '.lnk', '.js', '.jar'
];
if (forbiddenExtensions.includes(ext)) {
throw new Error(`Ouverture refusée pour des raisons de sécurité : l'exécution directe de scripts ou exécutables (${ext}) est désactivée.`);
}
if (!fs.existsSync(normalizedPath)) {
throw new Error("Le fichier spécifié n'existe pas sur le disque.");
}
const { shell } = require('electron');
await shell.openPath(normalizedPath);
writeLogEntry({
ts: new Date().toISOString(),
level: 'INFO',
tag: 'IPC-FileOpen',
message: `Fichier ouvert avec succès via l'OS : ${normalizedPath}`
});
return { success: true };
} catch (err) {
console.error('[main] Erreur open-local-file:', err.message);
writeLogEntry({
ts: new Date().toISOString(),
level: 'ERROR',
tag: 'IPC-FileOpen',
message: `Échec d'ouverture de fichier (${filePath}) : ${err.message}`
});
throw err;
}
});
// Afficher le chemin du log au démarrage pour faciliter le débogage
app.whenReady().then(() => {
console.log(`[EveFlow] Log file: ${getLogPath()}`);
});
+2432 -2789
View File
File diff suppressed because it is too large. Load diff
+48 -30
View File
@@ -1,31 +1,41 @@
{
"name": "eveflow",
"version": "1.0.5",
"description": "Retro-futuristic Windows companion with 3D Eve bot, local TTS/STT, and multi-agent connectivity",
"main": "main.js",
"version": "2.0.0.1",
"description": "JARVIS-style desktop HUD for Hermes Agent: voice, streaming runs, scheduled jobs, skills and telemetry",
"main": "dist-electron/main.js",
"private": true,
"license": "MIT",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"dev": "vite --host 127.0.0.1 --port 5173 --strictPort",
"build": "npm run typecheck && npm run build:renderer && npm run build:electron",
"build:renderer": "vite build",
"build:electron": "node scripts/build-electron.mjs",
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.electron.json --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"electron": "electron .",
"start": "concurrently -k \"npm run dev -- --host 127.0.0.1 --port 5173 --strictPort\" \"wait-on http://localhost:5173 && npm run electron\"",
"dist": "electron-builder --win"
"start": "npm run build:electron && concurrently -k -s first \"npm run dev\" \"wait-on http://127.0.0.1:5173 && cross-env NODE_ENV=development VITE_DEV_SERVER_URL=http://127.0.0.1:5173 electron .\"",
"preview": "vite preview",
"dist": "npm run build && electron-builder --win --publish never",
"typecheck:electron": "tsc -p tsconfig.electron.json --noEmit"
},
"build": {
"appId": "com.romik3.eveflow",
"productName": "EveFlow",
"copyright": "Copyright © 2026 R0m1k3",
"asar": false,
"asar": true,
"directories": {
"output": "out"
"output": "out",
"buildResources": "build"
},
"files": [
"main.js",
"preload.js",
"dist/**/*"
"dist-electron/**/*",
"dist/**/*",
"package.json"
],
"win": {
"target": "nsis",
"icon": "build/icon.png",
"requestedExecutionLevel": "asInvoker",
"signAndEditExecutable": false,
"verifyUpdateCodeSignature": false
@@ -36,28 +46,36 @@
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "EveFlow"
}
},
"extraResources": [
{
"from": "build/icon.png",
"to": "icon.png"
}
]
},
"dependencies": {
"@react-three/drei": "^9.105.0",
"@react-three/fiber": "^8.16.0",
"lucide-react": "^0.379.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"lucide-react": "^1.40.0",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-markdown": "^10.1.0",
"remark-gfm": "^4.0.1",
"three": "^0.163.0"
"zustand": "^5.0.15"
},
"devDependencies": {
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.1",
"@types/three": "^0.163.0",
"@vitejs/plugin-react": "^4.2.1",
"concurrently": "^8.2.2",
"electron": "^30.0.1",
"electron-builder": "^26.8.1",
"typescript": "^5.4.2",
"vite": "^5.2.2",
"wait-on": "^7.2.0"
"@types/node": "^24.0.0",
"@types/react": "^19.2.18",
"@types/react-dom": "^19.2.0",
"@vitejs/plugin-react": "^6.1.1",
"concurrently": "^10.0.5",
"cross-env": "^10.0.0",
"electron": "^44.1.1",
"electron-builder": "^26.15.3",
"esbuild": "^0.28.2",
"jsdom": "^30.0.1",
"typescript": "^5.9.3",
"vite": "^8.2.2",
"vitest": "^5.0.0",
"wait-on": "^9.1.0"
}
}
-34
View File
@@ -1,34 +0,0 @@
const { contextBridge, ipcRenderer } = require('electron');
// Exposition sécurisée via contextBridge (Zéro Trust contextIsolation)
contextBridge.exposeInMainWorld('electronAPI', {
windowControl: (action) => ipcRenderer.send('window-control', action),
setWindowMode: (mode) => ipcRenderer.send('set-window-mode', mode),
setCockpitMode: (isOpen) => ipcRenderer.send('set-cockpit-mode', isOpen),
onWindowModeChanged: (callback) => {
const subscription = (event, mode) => callback(mode);
ipcRenderer.on('window-mode-changed', subscription);
return () => ipcRenderer.removeListener('window-mode-changed', subscription);
},
// Logging : envoie une entrée structurée vers le processus principal pour écriture disque
writeLog: (entry) => ipcRenderer.send('write-log', entry),
// Webhook : abonnement aux events pushés par Hermes
onHermesPush: (callback) => {
const subscription = (event, data) => callback(data);
ipcRenderer.on('hermes-push', subscription);
return () => ipcRenderer.removeListener('hermes-push', subscription);
},
// Store persistant fichier — indépendant de l'origine HTTP/file://
storeGet: (key) => ipcRenderer.invoke('store-get', key),
storeSet: (key, value) => ipcRenderer.invoke('store-set', key, value),
// Lecture de fichier local sécurisée
readLocalFile: (filePath) => ipcRenderer.invoke('read-local-file', filePath),
// Télémétrie réelle système
getSystemMetrics: () => ipcRenderer.invoke('get-system-metrics'),
// Écriture de fichier partagé
writeSharedFile: (filename, content, isBase64) => ipcRenderer.invoke('write-shared-file', filename, content, isBase64),
// Ouverture de fichier local
openLocalFile: (filePath) => ipcRenderer.invoke('open-local-file', filePath),
// Chargement d'une image distante via Node.js (contourne CORS \u2014 retourne une Data URL base64)
fetchRemoteImage: (url, extraHeaders = {}) => ipcRenderer.invoke('fetch-remote-image', url, extraHeaders),
});
-72
View File
@@ -1,72 +0,0 @@
# Blender 4.5.5 LTS MTL File: 'None'
# www.blender.org
newmtl ArmLight
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_4a4a505db864ac4a_14.png
map_d tex1_128x128_m_2f869d05e999c94a_0.png
newmtl Eve
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_16x16_m_60d58f4141724929_14.png
newmtl Eye
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_32x32_m_cad406fa8385be70_14.png
map_d tex1_32x32_m_c8162c34352a09e2_0.png
newmtl HeadGun
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_128x128_m_87b2e2053969c2c1_14.png
newmtl Lights
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_b3ab82716f6eb03b_14.png
map_d tex1_128x128_e0ee4f7cd514a91a_0.png
newmtl UpperBody
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_7149b995a42d2f50_14.png
map_d tex1_128x128_m_164b500fe0940dee_0.png
newmtl Visor
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_499edc885bc97572_14.png
map_d tex1_128x128_m_f2552de8e9085d25_0.png
-16262
View File
File diff suppressed because it is too large. Load diff
-72
View File
@@ -1,72 +0,0 @@
# Blender 4.5.5 LTS MTL File: 'None'
# www.blender.org
newmtl ArmLight
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_4a4a505db864ac4a_14.png
map_d tex1_128x128_m_2f869d05e999c94a_0.png
newmtl Eve
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_16x16_m_60d58f4141724929_14.png
newmtl Eye
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_32x32_m_cad406fa8385be70_14.png
map_d tex1_32x32_m_c8162c34352a09e2_0.png
newmtl HeadGun
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_128x128_m_87b2e2053969c2c1_14.png
newmtl Lights
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_b3ab82716f6eb03b_14.png
map_d tex1_128x128_e0ee4f7cd514a91a_0.png
newmtl UpperBody
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_7149b995a42d2f50_14.png
map_d tex1_128x128_m_164b500fe0940dee_0.png
newmtl Visor
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_499edc885bc97572_14.png
map_d tex1_128x128_m_f2552de8e9085d25_0.png
-16262
View File
File diff suppressed because it is too large. Load diff
-12
View File
@@ -1,12 +0,0 @@
# Blender 4.5.5 LTS MTL File: 'None'
# www.blender.org
newmtl EVE_Diver
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 1
map_Kd tex1_256x256_m_7f667e040dcfe4ee_14.png
-897
View File
@@ -1,897 +0,0 @@
# Blender 4.5.5 LTS
# www.blender.org
mtllib EVE_Diver.mtl
o EVE_Diver
v -0.452637 10.603516 0.262695
v -0.391113 11.027832 0.227050
v -0.453613 10.603516 -0.260255
v -0.392090 11.027832 -0.225098
v -0.000977 11.027832 -0.452149
v -0.000977 10.603516 -0.522950
v 0.452637 10.603516 -0.262696
v 0.391113 11.027832 -0.227052
v 0.453613 10.603516 0.260253
v 0.392090 11.027832 0.225097
v 0.000977 11.027832 0.452148
v 0.000977 10.603516 0.522948
v -0.452637 10.603516 0.262695
v -0.391113 11.027832 0.227050
v -0.391113 11.027832 0.227050
v -0.558594 11.027832 0.324218
v -0.392090 11.027832 -0.225098
v -0.560059 11.027832 -0.321778
v -0.001465 11.027832 -0.645997
v -0.000977 11.027832 -0.452149
v 0.558594 11.027832 -0.324220
v 0.391113 11.027832 -0.227052
v 0.392090 11.027832 0.225097
v 0.560059 11.027832 0.321777
v 0.000977 11.027832 0.452148
v 0.001465 11.027832 0.645995
v -0.391113 11.027832 0.227050
v -0.558594 11.027832 0.324218
v -0.646484 10.603516 0.374999
v -0.647949 10.603516 -0.372071
v -0.558594 11.027832 0.324218
v -0.560059 11.027832 -0.321778
v -0.001465 10.603516 -0.747559
v -0.001465 11.027832 -0.645997
v 0.646484 10.603516 -0.375001
v 0.558594 11.027832 -0.324220
v 0.647949 10.603516 0.372070
v 0.560059 11.027832 0.321777
v 0.001465 10.603516 0.747558
v 0.001465 11.027832 0.645995
v -0.646484 10.603516 0.374999
v -0.558594 11.027832 0.324218
v 0.679199 7.251953 2.741210
v 0.545410 7.251953 2.741210
v 0.679199 9.599609 2.741210
v 0.545410 9.599609 2.741210
v 0.545410 7.251953 2.741210
v 0.545410 7.104004 2.485351
v 0.545410 9.599609 2.741210
v 0.545410 9.747559 2.485351
v 0.679199 7.251953 2.741210
v 0.679199 9.599609 2.741210
v 0.679199 7.104004 2.485351
v 0.679199 9.747559 2.485351
v -0.551758 7.251953 2.741210
v -0.685547 7.251953 2.741210
v -0.551758 9.599609 2.741210
v -0.685547 9.599609 2.741210
v -0.685547 7.251953 2.741210
v -0.685547 7.104004 2.485351
v -0.685547 9.599609 2.741210
v -0.685547 9.747559 2.485351
v -0.551758 7.251953 2.741210
v -0.551758 9.599609 2.741210
v -0.551758 7.104004 2.485351
v -0.551758 9.747559 2.485351
v -2.088867 7.956543 2.741210
v -2.088867 8.090332 2.741210
v 2.083496 7.956543 2.741210
v 2.083496 8.090332 2.741210
v -2.088867 8.090332 2.741210
v -2.236816 8.090332 2.485351
v 2.083496 8.090332 2.741210
v 2.230957 8.090332 2.485351
v -2.236816 7.956543 2.485351
v -2.088867 7.956543 2.741210
v 2.230957 7.956543 2.485351
v 2.083496 7.956543 2.741210
v -1.899902 8.792969 2.741210
v -1.899902 8.926758 2.741210
v 1.867676 8.792969 2.741210
v 1.867676 8.926758 2.741210
v -2.043457 8.926758 2.485351
v 2.011719 8.926758 2.485351
v -1.899902 8.926758 2.741210
v 1.867676 8.926758 2.741210
v -2.043457 8.792969 2.485351
v -1.899902 8.792969 2.741210
v 2.011719 8.792969 2.485351
v 1.867676 8.792969 2.741210
v 0.258789 11.023438 0.413085
v 0.208984 11.023438 0.413085
v 0.258789 11.023438 -0.433106
v 0.208984 11.023438 -0.433106
v 0.208984 11.023438 0.413085
v 0.208984 10.927734 0.468261
v 0.208984 11.023438 -0.433106
v 0.208984 10.927734 -0.488282
v 0.258789 10.927734 0.468261
v 0.258789 11.023438 0.413085
v 0.258789 10.927734 -0.488282
v 0.258789 11.023438 -0.433106
v -0.208984 11.023438 0.413085
v -0.258789 11.023438 0.413085
v -0.208984 11.023438 -0.433106
v -0.258789 11.023438 -0.433106
v -0.258789 11.023438 0.413085
v -0.258789 10.927734 0.468261
v -0.258789 11.023438 -0.433106
v -0.258789 10.927734 -0.488282
v -0.208984 10.927734 0.468261
v -0.208984 11.023438 0.413085
v -0.208984 10.927734 -0.488282
v -0.208984 11.023438 -0.433106
v -0.423340 11.023438 0.249023
v -0.423340 11.023438 0.198730
v 0.423340 11.023438 0.249023
v 0.423340 11.023438 0.198730
v -0.423340 11.023438 0.198730
v -0.478516 10.927734 0.198730
v 0.423340 11.023438 0.198730
v 0.478516 10.927734 0.198730
v -0.478516 10.927734 0.249023
v -0.423340 11.023438 0.249023
v 0.478516 10.927734 0.249023
v 0.423340 11.023438 0.249023
v -0.423340 11.023438 -0.218751
v -0.423340 11.023438 -0.269044
v 0.423340 11.023438 -0.218751
v 0.423340 11.023438 -0.269044
v -0.423340 11.023438 -0.269044
v -0.478516 10.927734 -0.269044
v 0.423340 11.023438 -0.269044
v 0.478516 10.927734 -0.269044
v -0.478516 10.927734 -0.218751
v -0.423340 11.023438 -0.218751
v 0.478516 10.927734 -0.218751
v 0.423340 11.023438 -0.218751
v -2.616699 9.216797 -0.743653
v -2.589355 9.301758 -0.743653
v -2.616699 9.216797 0.763671
v -2.589355 9.301758 0.763671
v -2.427246 9.249023 -0.842286
v -2.427246 9.249023 0.862304
v -2.589355 9.301758 -0.743653
v -2.589355 9.301758 0.763671
v -2.454590 9.164062 -0.842286
v -2.616699 9.216797 -0.743653
v -2.454590 9.164062 0.862304
v -2.616699 9.216797 0.763671
v -2.498535 9.580078 -0.451661
v -2.498535 9.580078 -0.362305
v -2.965820 8.145996 -0.451661
v -2.965820 8.145996 -0.362305
v -2.498535 9.580078 -0.362305
v -2.306152 9.620605 -0.362305
v -2.965820 8.145996 -0.362305
v -2.834473 7.999512 -0.362305
v -2.498535 9.580078 -0.451661
v -2.965820 8.145996 -0.451661
v -2.306152 9.620605 -0.451661
v -2.834473 7.999512 -0.451661
v -2.498535 9.580078 0.381835
v -2.498535 9.580078 0.471191
v -2.965820 8.145996 0.381835
v -2.965820 8.145996 0.471191
v -2.498535 9.580078 0.471191
v -2.306152 9.620605 0.471191
v -2.965820 8.145996 0.471191
v -2.834473 7.999512 0.471191
v -2.498535 9.580078 0.381835
v -2.965820 8.145996 0.381835
v -2.306152 9.620605 0.381835
v -2.834473 7.999512 0.381835
v -2.875488 8.423828 -0.743653
v -2.847656 8.508789 -0.743653
v -2.875488 8.423828 0.763671
v -2.847656 8.508789 0.763671
v -2.685547 8.456055 -0.842286
v -2.685547 8.456055 0.862304
v -2.847656 8.508789 -0.743653
v -2.847656 8.508789 0.763671
v -2.713379 8.371094 -0.842286
v -2.875488 8.423828 -0.743653
v -2.713379 8.371094 0.862304
v -2.875488 8.423828 0.763671
v -2.073242 9.500488 -0.000001
v -2.496582 9.638184 -0.000001
v -2.203613 9.099609 0.729980
v -2.626953 9.237305 0.729980
v -2.464844 8.297363 0.729980
v -2.888672 8.435547 0.729980
v -3.019043 8.034668 -0.000001
v -2.595703 7.896484 -0.000001
v -2.464844 8.297363 -0.729981
v -2.888672 8.435547 -0.729981
v -2.626953 9.237305 -0.729981
v -2.203613 9.099609 -0.729981
v -2.496582 9.638184 -0.000001
v -2.073242 9.500488 -0.000001
v -2.384277 9.981934 -0.000001
v -2.571289 9.409180 1.042968
v -2.496582 9.638184 -0.000001
v -2.626953 9.237305 0.729980
v -2.944336 8.263672 1.042968
v -2.888672 8.435547 0.729980
v -3.019043 8.034668 -0.000001
v -3.130859 7.690918 -0.000001
v -2.944336 8.263672 -1.042969
v -2.888672 8.435547 -0.729981
v -2.626953 9.237305 -0.729981
v -2.571289 9.409180 -1.042969
v -2.496582 9.638184 -0.000001
v -2.384277 9.981934 -0.000001
v -2.384277 9.981934 -0.000001
v -1.960938 9.843750 -0.000001
v -2.571289 9.409180 1.042968
v -2.147949 9.270996 1.042968
v -2.944336 8.263672 1.042968
v -2.520996 8.125977 1.042968
v -3.130859 7.690918 -0.000001
v -2.707520 7.553223 -0.000001
v -2.520996 8.125977 -1.042969
v -2.944336 8.263672 -1.042969
v -2.147949 9.270996 -1.042969
v -2.571289 9.409180 -1.042969
v -1.960938 9.843750 -0.000001
v -2.384277 9.981934 -0.000001
v -0.002441 7.286621 2.763183
v 1.350586 7.427246 2.763183
v -0.002930 6.862793 2.763183
v 1.464355 7.033203 2.763183
v 1.913086 7.782227 2.763183
v 2.230957 7.576660 2.763183
v 2.329590 8.142578 2.763183
v 1.983398 8.178223 2.763183
v 1.899902 9.187988 2.763183
v 1.656738 8.949707 2.763183
v 0.970215 9.465332 2.763183
v 1.095703 9.812988 2.763183
v -0.011230 9.631836 2.763183
v -0.012695 10.007324 2.763183
v -1.093262 9.817383 2.763183
v -0.974609 9.467285 2.763183
v -1.904297 9.189941 2.763183
v -1.662109 8.950195 2.763183
v -2.018066 8.201172 2.763183
v -2.361328 8.206543 2.763183
v -1.955566 7.784668 2.763183
v -2.265137 7.564453 2.763183
v -1.471191 7.021484 2.763183
v -1.362793 7.415527 2.763183
v -0.002930 6.862793 2.763183
v -0.002441 7.286621 2.763183
v -0.002441 7.286621 2.763183
v -0.002441 7.286621 2.636718
v 1.350586 7.427246 2.763183
v 1.350586 7.427246 2.296386
v 1.913086 7.782227 2.763183
v 1.913086 7.782227 1.984374
v 1.983398 8.178223 2.763183
v 1.983398 8.178223 1.858886
v 1.656738 8.949707 1.864745
v 1.656738 8.949707 2.763183
v 0.970215 9.465332 1.988769
v 0.970215 9.465332 2.763183
v -0.011230 9.631836 2.031738
v -0.011230 9.631836 2.763183
v -0.974609 9.467285 2.763183
v -0.974609 9.467285 1.987792
v -1.662109 8.950195 2.763183
v -1.662109 8.950195 1.864745
v -2.018066 8.201172 2.763183
v -2.018066 8.201172 1.840820
v -1.955566 7.784668 1.954101
v -1.955566 7.784668 2.763183
v -1.362793 7.415527 2.291015
v -1.362793 7.415527 2.763183
v -0.002441 7.286621 2.636718
v -0.002441 7.286621 2.763183
v -0.002930 6.862793 2.763183
v 1.464355 7.033203 2.763183
v -0.002930 6.862793 2.444824
v 1.464355 7.033203 2.053710
v 2.230957 7.576660 2.763183
v 2.230957 7.576660 1.608886
v 2.329590 8.142578 2.763183
v 2.329590 8.142578 1.434081
v 1.899902 9.187988 1.435058
v 1.899902 9.187988 2.763183
v 1.095703 9.812988 1.594726
v 1.095703 9.812988 2.763183
v -0.012695 10.007324 1.650390
v -0.012695 10.007324 2.763183
v -1.093262 9.817383 2.763183
v -1.093262 9.817383 1.594238
v -1.904297 9.189941 2.763183
v -1.904297 9.189941 1.434081
v -2.361328 8.206543 2.763183
v -2.361328 8.206543 1.407226
v -2.265137 7.564453 1.582031
v -2.265137 7.564453 2.763183
v -1.471191 7.021484 2.047363
v -1.471191 7.021484 2.763183
v -0.002930 6.862793 2.444824
v -0.002930 6.862793 2.763183
v 2.621582 9.216797 0.743652
v 2.594238 9.301758 0.743652
v 2.621582 9.216797 -0.763673
v 2.594238 9.301758 -0.763673
v 2.432129 9.249023 0.842284
v 2.432129 9.249023 -0.862305
v 2.594238 9.301758 0.743652
v 2.594238 9.301758 -0.763673
v 2.459473 9.164062 0.842284
v 2.621582 9.216797 0.743652
v 2.459473 9.164062 -0.862305
v 2.621582 9.216797 -0.763673
v 2.503418 9.580078 0.451659
v 2.503418 9.580078 0.362304
v 2.970703 8.145996 0.451660
v 2.970703 8.145996 0.362304
v 2.503418 9.580078 0.362304
v 2.311035 9.620605 0.362304
v 2.970703 8.145996 0.362304
v 2.839355 7.999512 0.362304
v 2.503418 9.580078 0.451659
v 2.970703 8.145996 0.451660
v 2.311035 9.620605 0.451659
v 2.839355 7.999512 0.451660
v 2.503418 9.580078 -0.381837
v 2.503418 9.580078 -0.471192
v 2.970703 8.145996 -0.381837
v 2.970703 8.145996 -0.471192
v 2.503418 9.580078 -0.471192
v 2.311035 9.620605 -0.471192
v 2.970703 8.145996 -0.471192
v 2.839355 7.999512 -0.471192
v 2.503418 9.580078 -0.381837
v 2.970703 8.145996 -0.381837
v 2.311035 9.620605 -0.381837
v 2.839355 7.999512 -0.381837
v 2.880371 8.423828 0.743652
v 2.852539 8.508789 0.743652
v 2.880371 8.423828 -0.763673
v 2.852539 8.508789 -0.763673
v 2.690430 8.456055 0.842285
v 2.690430 8.456055 -0.862305
v 2.852539 8.508789 0.743652
v 2.852539 8.508789 -0.763673
v 2.718262 8.371094 0.842285
v 2.880371 8.423828 0.743652
v 2.718262 8.371094 -0.862305
v 2.880371 8.423828 -0.763673
v 2.073242 9.500488 -0.000001
v 2.496582 9.638184 -0.000001
v 2.203613 9.099609 -0.729981
v 2.626953 9.237305 -0.729981
v 2.464844 8.297363 -0.729981
v 2.888672 8.435547 -0.729981
v 3.019043 8.034668 -0.000001
v 2.595703 7.896484 -0.000001
v 2.464844 8.297363 0.729980
v 2.888672 8.435547 0.729980
v 2.626953 9.237305 0.729980
v 2.203613 9.099609 0.729980
v 2.496582 9.638184 -0.000001
v 2.073242 9.500488 -0.000001
v 2.384277 9.981934 -0.000001
v 2.571289 9.409180 -1.042969
v 2.496582 9.638184 -0.000001
v 2.626953 9.237305 -0.729981
v 2.944336 8.263672 -1.042969
v 2.888672 8.435547 -0.729981
v 3.019043 8.034668 -0.000001
v 3.130859 7.690918 -0.000001
v 2.944336 8.263672 1.042968
v 2.888672 8.435547 0.729980
v 2.626953 9.237305 0.729980
v 2.571289 9.409180 1.042968
v 2.496582 9.638184 -0.000001
v 2.384277 9.981934 -0.000001
v 2.384277 9.981934 -0.000001
v 1.960938 9.843750 -0.000001
v 2.571289 9.409180 -1.042969
v 2.147949 9.270996 -1.042969
v 2.944336 8.263672 -1.042969
v 2.520996 8.125977 -1.042969
v 3.130859 7.690918 -0.000001
v 2.707520 7.553223 -0.000001
v 2.520996 8.125977 1.042968
v 2.944336 8.263672 1.042968
v 2.147949 9.270996 1.042968
v 2.571289 9.409180 1.042968
v 1.960938 9.843750 -0.000001
v 2.384277 9.981934 -0.000001
vn 0.8519 -0.1656 -0.4969
vn 0.8573 -0.1652 0.4876
vn -0.1499 0.4734 0.8680
vn -0.3068 0.9518 -0.0000
vn -0.0000 -0.1657 0.9862
vn -0.8519 -0.1656 0.4969
vn -0.8518 -0.1656 0.4969
vn -0.8573 -0.1652 -0.4876
vn 0.1499 -0.4734 0.8680
vn -0.0000 -0.1657 -0.9862
vn 0.8518 -0.1656 -0.4969
vn -0.0000 1.0000 -0.0000
vn 0.3068 -0.9518 -0.0000
vn -0.8424 0.2283 0.4881
vn -0.8456 0.2292 -0.4821
vn 0.1500 -0.4735 -0.8680
vn -0.0000 0.2277 -0.9737
vn -0.0000 0.2278 -0.9737
vn 0.8424 0.2283 -0.4881
vn 0.8456 0.2292 0.4821
vn -0.0000 0.2277 0.9737
vn -0.0000 0.2278 0.9737
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn -0.9518 0.3067 -0.0000
vn 0.3068 0.9518 -0.0000
vn 0.3067 0.9518 -0.0000
vn -0.3068 -0.9518 -0.0000
vn -0.3067 -0.9518 -0.0000
vn -0.9518 0.3068 -0.0000
vn -0.3093 -0.9510 -0.0000
vn -0.1499 -0.4734 -0.8680
vn 0.1499 0.4734 -0.8680
vn -0.1499 0.4734 -0.8680
vn 0.1499 0.4734 0.8680
vn -0.1499 -0.4734 0.8680
vn 0.9518 0.3068 -0.0000
vn -0.1500 -0.4735 0.8680
vn -0.3233 0.9463 -0.0000
vn -0.8284 0.5601 -0.0000
vn -0.9939 -0.1104 -0.0000
vn -0.7885 -0.6150 -0.0001
vn -0.7884 -0.6152 -0.0000
vn -0.3930 -0.9196 -0.0000
vn -0.0001 -1.0000 -0.0000
vn 0.3930 -0.9196 -0.0000
vn 0.3930 -0.9195 -0.0000
vn 0.7746 -0.6325 -0.0000
vn 0.7747 -0.6324 -0.0000
vn 0.9899 -0.1414 -0.0000
vn 0.9900 -0.1414 -0.0000
vn 0.8345 0.5510 -0.0000
vn 0.8344 0.5511 -0.0000
vn 0.3162 0.9487 -0.0000
vn 0.3163 0.9487 -0.0000
vn 0.3537 -0.9354 -0.0000
vn 0.1499 -0.4734 -0.8680
vn 0.3093 -0.9510 -0.0000
vn 0.8440 -0.5363 -0.0000
vn 0.9947 0.1026 -0.0000
vn 0.7953 0.6063 -0.0000
vn 0.7953 0.6062 -0.0000
vn 0.4025 0.9154 -0.0000
vn -0.0003 1.0000 -0.0000
vn -0.0002 1.0000 -0.0000
vn -0.4025 0.9154 -0.0000
vn -0.7817 0.6236 -0.0000
vn -0.7816 0.6237 -0.0000
vn -0.9899 0.1414 -0.0000
vn -0.8498 -0.5271 -0.0000
vn -0.8498 -0.5272 -0.0000
vn -0.3468 -0.9379 -0.0000
vn -0.3464 -0.9381 -0.0000
vn 0.9518 0.3067 -0.0000
vn -0.3067 0.9518 -0.0000
vn 0.3067 -0.9518 -0.0000
vt 0.669678 0.523682
vt 0.706604 0.486755
vt 0.679138 0.533142
vt 0.716064 0.496216
vt 0.935120 0.295105
vt 0.984192 0.245972
vt 0.992126 0.253906
vt 0.765320 0.447021
vt 0.755859 0.437500
vt 0.942993 0.302979
vt 0.805054 0.388306
vt 0.814575 0.397766
vt 0.854309 0.339050
vt 0.863770 0.348511
vt 0.886047 0.344177
vt 0.913025 0.299316
vt 0.903503 0.289795
vt 0.893921 0.352051
vt 0.952759 0.240601
vt 0.962280 0.250061
vt 0.688660 0.542664
vt 0.725586 0.505737
vt 0.836914 0.393250
vt 0.774780 0.456482
vt 0.824036 0.407227
vt 0.844849 0.401184
vt 0.873291 0.358032
vt 0.922485 0.308777
vt 0.971741 0.259583
vt 0.698120 0.552124
vt 0.735046 0.515198
vt 0.795776 0.450256
vt 0.784302 0.466003
vt 0.833557 0.416748
vt 0.882751 0.367493
vt 0.932007 0.318298
vt 0.981201 0.269043
vt 0.680115 0.534973
vt 0.974792 0.240295
vt 0.687317 0.542236
vt 0.982056 0.247498
vt 0.686523 0.552673
vt 0.992615 0.246643
vt 0.669617 0.535767
vt 0.975647 0.229736
vt 0.687134 0.541992
vt 0.981812 0.247253
vt 0.669067 0.535217
vt 0.975098 0.229187
vt 0.680359 0.535095
vt 0.975037 0.240417
vt 0.687012 0.541687
vt 0.981689 0.247070
vt 0.683594 0.533508
vt 0.970947 0.246094
vt 0.690063 0.539978
vt 0.977417 0.252563
vt 0.686218 0.551758
vt 0.989258 0.248718
vt 0.671753 0.537354
vt 0.974792 0.234314
vt 0.971130 0.267822
vt 0.698792 0.540161
vt 0.960083 0.256714
vt 0.687683 0.529053
vt 0.963684 0.239807
vt 0.670776 0.532715
vt 0.988037 0.264160
vt 0.695129 0.557068
vt 0.673828 0.524658
vt 0.722961 0.475586
vt 0.681763 0.532593
vt 0.730835 0.483521
vt 0.772034 0.426514
vt 0.779907 0.434448
vt 0.787842 0.442322
vt 0.829041 0.385315
vt 0.821106 0.377441
vt 0.746704 0.499329
vt 0.870178 0.328308
vt 0.878113 0.336243
vt 0.738770 0.491394
vt 0.927185 0.287170
vt 0.919312 0.279236
vt 0.976257 0.238098
vt 0.968384 0.230164
vt 0.689697 0.540527
vt 0.697571 0.548401
vt 0.705444 0.554871
vt 0.695496 0.544800
vt 0.731445 0.528870
vt 0.721497 0.518799
vt 0.757446 0.502869
vt 0.747498 0.492737
vt 0.764832 0.475403
vt 0.774780 0.485535
vt 0.790894 0.449402
vt 0.800842 0.459534
vt 0.826843 0.433472
vt 0.816895 0.423401
vt 0.852844 0.407471
vt 0.842896 0.397400
vt 0.868896 0.371399
vt 0.878845 0.381470
vt 0.894897 0.345337
vt 0.904846 0.355469
vt 0.930847 0.329468
vt 0.920959 0.319336
vt 0.948242 0.312073
vt 0.938293 0.302002
vt 0.964294 0.276001
vt 0.974243 0.286072
vt 0.990295 0.250000
vt 1.000244 0.260071
vt 0.696533 0.546326
vt 0.722595 0.520264
vt 0.748596 0.494263
vt 0.765991 0.476868
vt 0.791992 0.450867
vt 0.818054 0.424805
vt 0.844055 0.398804
vt 0.870117 0.372742
vt 0.896179 0.346741
vt 0.922180 0.320679
vt 0.939514 0.303345
vt 0.965576 0.277283
vt 0.991638 0.251282
vt 0.661072 0.510559
vt 0.687134 0.484497
vt 0.713135 0.458496
vt 0.730530 0.441101
vt 0.756531 0.415100
vt 0.782593 0.389038
vt 0.808594 0.363037
vt 0.834656 0.336975
vt 0.860657 0.310913
vt 0.886719 0.284912
vt 0.904053 0.267578
vt 0.930115 0.241516
vt 0.956116 0.215454
s 1
usemtl EVE_Diver
f 1/1/1 3/2/2 2/3/1
f 2/3/1 3/2/2 4/4/2
f 394/5/3 396/6/4 395/7/4
f 4/4/2 3/2/2 5/8/5
f 3/2/2 6/9/5 5/8/5
f 393/10/3 394/5/3 395/7/4
f 6/9/5 7/11/6 5/8/5
f 5/8/5 7/11/6 8/12/7
f 7/11/6 9/13/8 8/12/7
f 8/12/7 9/13/8 10/14/8
f 392/15/9 394/5/3 393/10/3
f 10/14/8 9/13/8 11/16/10
f 9/13/8 12/17/10 11/16/10
f 391/18/9 392/15/9 393/10/3
f 12/17/10 13/19/1 11/16/10
f 11/16/10 13/19/1 14/20/11
f 15/3/12 17/4/12 16/21/12
f 16/21/12 17/4/12 18/22/12
f 389/23/13 392/15/9 391/18/9
f 18/22/12 17/4/12 19/24/12
f 17/4/12 20/8/12 19/24/12
f 19/24/12 20/8/12 21/25/12
f 20/8/12 22/12/12 21/25/12
f 390/26/13 389/23/13 391/18/9
f 22/12/12 23/14/12 21/25/12
f 21/25/12 23/14/12 24/27/12
f 23/14/12 25/16/12 24/27/12
f 24/27/12 25/16/12 26/28/12
f 25/16/12 27/20/12 26/28/12
f 26/28/12 27/20/12 28/29/12
f 29/30/14 31/21/14 30/31/15
f 388/32/16 389/23/13 390/26/13
f 31/21/14 32/22/15 30/31/15
f 30/31/15 32/22/15 33/33/17
f 32/22/15 34/24/18 33/33/17
f 33/33/17 34/24/18 35/34/19
f 34/24/18 36/25/19 35/34/19
f 35/34/19 36/25/19 37/35/20
f 36/25/19 38/27/20 37/35/20
f 37/35/20 38/27/20 39/36/21
f 38/27/20 40/28/22 39/36/21
f 39/36/21 40/28/22 41/37/14
f 40/28/22 42/29/14 41/37/14
f 43/38/23 45/39/23 44/40/23
f 44/40/23 45/39/23 46/41/23
f 47/40/24 49/41/24 48/42/24
f 48/42/24 49/41/24 50/43/24
f 51/38/25 53/44/25 52/39/25
f 52/39/25 53/44/25 54/45/25
f 55/38/23 57/39/23 56/46/23
f 56/46/23 57/39/23 58/47/23
f 59/46/24 61/47/24 60/42/24
f 60/42/24 61/47/24 62/43/24
f 63/38/25 65/48/25 64/39/25
f 64/39/25 65/48/25 66/49/25
f 67/50/23 69/51/23 68/52/23
f 68/52/23 69/51/23 70/53/23
f 71/52/12 73/53/12 72/42/12
f 72/42/12 73/53/12 74/43/12
f 75/48/26 77/49/26 76/50/26
f 76/50/26 77/49/26 78/51/26
f 79/50/23 81/51/23 80/52/23
f 80/52/23 81/51/23 82/53/23
f 83/42/12 85/52/12 84/43/12
f 84/43/12 85/52/12 86/53/12
f 87/48/26 89/49/26 88/50/26
f 88/50/26 89/49/26 90/51/26
f 91/54/12 93/55/12 92/56/12
f 92/56/12 93/55/12 94/57/12
f 95/56/24 97/57/24 96/58/24
f 96/58/24 97/57/24 98/59/24
f 99/60/25 101/61/25 100/54/25
f 100/54/25 101/61/25 102/55/25
f 103/54/12 105/55/12 104/56/12
f 104/56/12 105/55/12 106/57/12
f 107/56/24 109/57/24 108/58/24
f 108/58/24 109/57/24 110/59/24
f 111/60/25 113/61/25 112/54/25
f 112/54/25 113/61/25 114/55/25
f 115/54/12 117/55/12 116/56/12
f 116/56/12 117/55/12 118/57/12
f 119/56/27 121/57/27 120/58/27
f 120/58/27 121/57/27 122/59/27
f 123/60/23 125/61/23 124/54/23
f 124/54/23 125/61/23 126/55/23
f 127/54/12 129/55/12 128/56/12
f 128/56/12 129/55/12 130/57/12
f 131/56/27 133/57/27 132/58/27
f 132/58/27 133/57/27 134/59/27
f 135/60/23 137/61/23 136/54/23
f 136/54/23 137/61/23 138/55/23
f 139/62/28 141/63/28 140/64/28
f 140/64/28 141/63/28 142/65/28
f 143/66/29 145/64/30 144/67/29
f 144/67/29 145/64/30 146/65/30
f 147/68/31 149/69/31 148/62/32
f 148/62/32 149/69/31 150/63/32
f 151/62/33 153/63/33 152/64/33
f 152/64/33 153/63/33 154/65/33
f 155/64/23 157/65/23 156/66/23
f 156/66/23 157/65/23 158/67/23
f 159/62/27 161/68/27 160/63/27
f 160/63/27 161/68/27 162/69/27
f 163/62/33 165/63/33 164/64/33
f 164/64/33 165/63/33 166/65/33
f 167/64/23 169/65/23 168/66/23
f 168/66/23 169/65/23 170/67/23
f 171/62/27 173/68/27 172/63/27
f 172/63/27 173/68/27 174/69/27
f 175/62/33 177/63/33 176/64/33
f 176/64/33 177/63/33 178/65/33
f 179/66/29 181/64/30 180/67/30
f 180/67/30 181/64/30 182/65/30
f 183/68/31 185/69/32 184/62/32
f 184/62/32 185/69/32 186/63/32
f 187/70/34 189/71/35 188/72/31
f 188/72/31 189/71/35 190/73/35
f 189/71/35 191/74/36 190/73/35
f 190/73/35 191/74/36 192/75/36
f 387/76/16 389/23/13 388/32/16
f 192/75/36 191/74/36 193/77/29
f 191/74/36 194/78/29 193/77/29
f 386/79/37 387/76/16 388/32/16
f 194/78/29 195/80/38 193/77/29
f 193/77/29 195/80/38 196/81/38
f 385/82/37 387/76/16 386/79/37
f 196/81/38 195/80/38 197/83/39
f 195/80/38 198/84/39 197/83/39
f 197/83/39 198/84/39 199/85/34
f 198/84/39 200/86/31 199/85/34
f 201/87/33 203/72/33 202/82/33
f 384/88/4 385/82/37 386/79/37
f 203/72/33 204/73/33 202/82/33
f 202/82/33 204/73/33 205/76/33
f 204/73/33 206/75/33 205/76/33
f 383/87/4 385/82/37 384/88/4
f 206/75/33 207/77/33 205/76/33
f 205/76/33 207/77/33 208/23/33
f 380/5/40 381/85/40 382/6/40
f 208/23/33 207/77/33 209/15/33
f 207/77/33 210/81/33 209/15/33
f 379/83/40 381/85/40 380/5/40
f 210/81/33 211/83/33 209/15/33
f 209/15/33 211/83/33 212/5/33
f 211/83/33 213/85/33 212/5/33
f 212/5/33 213/85/33 214/6/33
f 215/87/29 217/82/38 216/88/29
f 216/88/29 217/82/38 218/79/38
f 217/82/38 219/76/41 218/79/38
f 218/79/38 219/76/41 220/32/41
f 219/76/41 221/23/31 220/32/41
f 220/32/41 221/23/31 222/26/31
f 377/15/40 379/83/40 380/5/40
f 222/26/31 221/23/31 223/18/35
f 221/23/31 224/15/35 223/18/35
f 223/18/35 224/15/35 225/10/36
f 224/15/35 226/5/36 225/10/36
f 225/10/36 226/5/36 227/7/29
f 226/5/36 228/6/29 227/7/29
f 229/89/23 231/90/23 230/91/23
f 378/81/40 379/83/40 377/15/40
f 231/90/23 232/92/23 230/91/23
f 230/91/23 232/92/23 233/93/23
f 232/92/23 234/94/23 233/93/23
f 375/77/40 378/81/40 377/15/40
f 234/94/23 235/95/23 233/93/23
f 233/93/23 235/95/23 236/96/23
f 235/95/23 237/97/23 236/96/23
f 236/96/23 237/97/23 238/98/23
f 376/23/40 375/77/40 377/15/40
f 238/98/23 237/97/23 239/99/23
f 237/97/23 240/100/23 239/99/23
f 239/99/23 240/100/23 241/101/23
f 240/100/23 242/102/23 241/101/23
f 373/76/40 375/77/40 376/23/40
f 242/102/23 243/103/23 241/101/23
f 241/101/23 243/103/23 244/104/23
f 243/103/23 245/105/23 244/104/23
f 244/104/23 245/105/23 246/106/23
f 374/75/40 375/77/40 373/76/40
f 246/106/23 245/105/23 247/107/23
f 245/105/23 248/108/23 247/107/23
f 247/107/23 248/108/23 249/109/23
f 248/108/23 250/110/23 249/109/23
f 372/73/40 374/75/40 373/76/40
f 250/110/23 251/111/23 249/109/23
f 249/109/23 251/111/23 252/112/23
f 251/111/23 253/113/23 252/112/23
f 252/112/23 253/113/23 254/114/23
f 255/89/12 257/91/42 256/115/12
f 256/115/12 257/91/42 258/116/42
f 257/91/42 259/93/43 258/116/42
f 258/116/42 259/93/43 260/117/43
f 259/93/43 261/96/44 260/117/43
f 260/117/43 261/96/44 262/118/44
f 370/82/40 372/73/40 373/76/40
f 262/118/44 261/96/44 263/119/45
f 261/96/44 264/98/46 263/119/45
f 263/119/45 264/98/46 265/120/47
f 264/98/46 266/99/47 265/120/47
f 265/120/47 266/99/47 267/121/48
f 266/99/47 268/101/26 267/121/48
f 371/72/40 372/73/40 370/82/40
f 268/101/26 269/104/49 267/121/48
f 267/121/48 269/104/49 270/122/50
f 269/104/49 271/106/51 270/122/50
f 270/122/50 271/106/51 272/123/52
f 271/106/51 273/107/53 272/123/52
f 272/123/52 273/107/53 274/124/54
f 369/87/40 371/72/40 370/82/40
f 274/124/54 273/107/53 275/125/55
f 273/107/53 276/109/56 275/125/55
f 275/125/55 276/109/56 277/126/57
f 276/109/56 278/112/58 277/126/57
f 277/126/57 278/112/58 279/127/12
f 278/112/58 280/114/12 279/127/12
f 281/90/26 283/128/26 282/92/59
f 366/84/60 368/86/13 367/85/61
f 283/128/26 284/129/59 282/92/59
f 282/92/59 284/129/59 285/94/62
f 284/129/59 286/130/62 285/94/62
f 285/94/62 286/130/62 287/95/63
f 286/130/62 288/131/63 287/95/63
f 365/83/60 366/84/60 367/85/61
f 288/131/63 289/132/64 287/95/63
f 287/95/63 289/132/64 290/97/65
f 289/132/64 291/133/66 290/97/65
f 290/97/65 291/133/66 292/100/66
f 291/133/66 293/134/67 292/100/66
f 292/100/66 293/134/67 294/102/68
f 363/80/37 366/84/60 365/83/60
f 294/102/68 293/134/67 295/103/69
f 293/134/67 296/135/69 295/103/69
f 295/103/69 296/135/69 297/105/70
f 296/135/69 298/136/71 297/105/70
f 297/105/70 298/136/71 299/108/72
f 298/136/71 300/137/72 299/108/72
f 364/81/37 363/80/37 365/83/60
f 300/137/72 301/138/73 299/108/72
f 299/108/72 301/138/73 302/110/74
f 301/138/73 303/139/75 302/110/74
f 302/110/74 303/139/75 304/111/76
f 303/139/75 305/140/26 304/111/76
f 304/111/76 305/140/26 306/113/26
f 307/62/77 309/63/77 308/64/77
f 308/64/77 309/63/77 310/65/77
f 311/66/4 313/64/78 312/67/78
f 312/67/78 313/64/78 314/65/4
f 315/68/13 317/69/79 316/62/79
f 316/62/79 317/69/79 318/63/13
f 319/62/40 321/63/40 320/64/40
f 320/64/40 321/63/40 322/65/40
f 323/64/27 325/65/27 324/66/27
f 324/66/27 325/65/27 326/67/27
f 327/62/23 329/68/23 328/63/23
f 328/63/23 329/68/23 330/69/23
f 331/62/40 333/63/40 332/64/40
f 332/64/40 333/63/40 334/65/40
f 335/64/27 337/65/27 336/66/27
f 336/66/27 337/65/27 338/67/27
f 339/62/23 341/68/23 340/63/23
f 340/63/23 341/68/23 342/69/23
f 343/62/40 345/63/40 344/64/77
f 344/64/77 345/63/40 346/65/40
f 347/66/4 349/64/78 348/67/78
f 348/67/78 349/64/78 350/65/78
f 351/68/13 353/69/79 352/62/79
f 352/62/79 353/69/79 354/63/79
f 355/70/61 357/71/9 356/72/13
f 356/72/13 357/71/9 358/73/9
f 357/71/9 359/74/3 358/73/9
f 358/73/9 359/74/3 360/75/3
f 361/77/4 363/80/37 364/81/37
f 360/75/3 359/74/3 361/77/4
f 359/74/3 362/78/4 361/77/4
f 362/78/4 363/80/37 361/77/4
-12
View File
@@ -1,12 +0,0 @@
# Blender 4.5.5 LTS MTL File: 'None'
# www.blender.org
newmtl EVE_Xmas
Ns 0.000000
Ka 1.000000 1.000000 1.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
illum 1
map_Kd tex1_128x128_m_f5b8cc0e1394df76_14.png
map_d tex1_128x128_m_47fba0aeb06eb3d7_0.png
File diff suppressed because it is too large. Load diff
Loaded 100 of 240 files, more files were not shown because too many files have changed in this diff. Show more