hlamingo — помощник «где что лежит»
Веб-помощник для домашнего склада: помнит, в какой коробке и в каком месте лежит вещь, и находит её по названию, тегам и маркировке. Открывается с телефона, интеллект — локальная Ollama. Основное: - структурный ввод «место → ёмкость → предмет» и кнопки Положить / Забрать / Переместить / Удалить; - иерархия мест (Гараж → Стеллаж А → Полка 2), ёмкости с кодом «буква+цифра», состояние «на руках» для взятых вещей; - поиск по словам с учётом русских окончаний, теги от модели расширяют словарь предмета, смысловой поиск — вспомогательный (замеры в search.py); - фото к вещам и коробкам: съёмка и выбор из галереи; - правка и удаление всех сущностей, удаление коробки не теряет её содержимое; - работает и без Ollama: отключаются только разбор фраз, теги и поиск по смыслу. Данные (data/, static/photos/) и локальный конфиг (.env) в репозиторий не попадают. Тесты работают только в песочнице: путь к данным берётся из окружения, tests/guard.py отказывается запускаться на живых данных. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+189
@@ -0,0 +1,189 @@
|
||||
@echo off
|
||||
rem ============================================================
|
||||
rem hlamingo installer
|
||||
rem
|
||||
rem Downloads the app and sets up everything needed to run it.
|
||||
rem Put this file in an empty folder and double-click it.
|
||||
rem
|
||||
rem ASCII only: cmd.exe reads .cmd in the system codepage, so Cyrillic here
|
||||
rem would turn into garbage and break the script. Russian text is printed
|
||||
rem from Python instead.
|
||||
rem ============================================================
|
||||
setlocal
|
||||
chcp 65001 >nul
|
||||
cls
|
||||
|
||||
set REPO_WEB=https://git.08h.ru/alex/hlamingo
|
||||
set REPO_GIT=https://git.08h.ru/alex/hlamingo.git
|
||||
set BRANCH=main
|
||||
set TARGET=hlamingo
|
||||
|
||||
echo ========================================
|
||||
echo hlamingo - installer
|
||||
echo ========================================
|
||||
echo.
|
||||
echo Source: %REPO_WEB%
|
||||
echo Target: %CD%\%TARGET%
|
||||
echo.
|
||||
|
||||
cd /d "%~dp0"
|
||||
|
||||
rem ---------- 1. Python ----------
|
||||
where python >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Python not found in PATH.
|
||||
echo.
|
||||
echo Install Python 3.9 or newer from https://www.python.org/downloads/
|
||||
echo IMPORTANT: check "Add python.exe to PATH" in the installer.
|
||||
echo Then run this file again.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
for /f "delims=" %%v in ('python -c "import sys;print(sys.version.split()[0])"') do set PYVER=%%v
|
||||
echo [1/4] Python %PYVER% found.
|
||||
|
||||
rem ---------- 2. Download ----------
|
||||
if exist "%TARGET%\hlamingo\app.py" goto :update
|
||||
|
||||
where git >nul 2>&1
|
||||
if errorlevel 1 goto :download_zip
|
||||
|
||||
echo [2/4] Cloning with git...
|
||||
git clone --branch %BRANCH% "%REPO_GIT%" "%TARGET%"
|
||||
if errorlevel 1 (
|
||||
echo git clone failed, falling back to zip download.
|
||||
goto :download_zip
|
||||
)
|
||||
goto :setup
|
||||
|
||||
:download_zip
|
||||
echo [2/4] Downloading archive (git not available or clone failed)...
|
||||
rem PowerShell does the work: no curl/tar dependency on older Windows.
|
||||
rem Проверяем, что скачался именно архив: сервер, требующий входа, отдаёт
|
||||
rem HTML-страницу логина с кодом 200, и распаковка падала бы невнятно.
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
|
||||
"$ErrorActionPreference='Stop';" ^
|
||||
"$url='%REPO_WEB%/archive/%BRANCH%.zip';" ^
|
||||
"$zip=Join-Path $env:TEMP 'hlamingo-src.zip';" ^
|
||||
"$tmp=Join-Path $env:TEMP 'hlamingo-unpack';" ^
|
||||
"Write-Host (' ' + $url);" ^
|
||||
"Invoke-WebRequest -Uri $url -OutFile $zip -UseBasicParsing -MaximumRedirection 0 -ErrorAction SilentlyContinue;" ^
|
||||
"if (-not (Test-Path $zip)) { throw 'server returned nothing' }" ^
|
||||
"$head=[IO.File]::ReadAllBytes($zip) | Select-Object -First 2;" ^
|
||||
"if ($head[0] -ne 0x50 -or $head[1] -ne 0x4B) { Remove-Item $zip -Force; throw 'the server sent a web page instead of an archive - the repository is private or requires signing in' }" ^
|
||||
"if (Test-Path $tmp) { Remove-Item -Recurse -Force $tmp }" ^
|
||||
"Expand-Archive -Path $zip -DestinationPath $tmp -Force;" ^
|
||||
"$root=Get-ChildItem $tmp -Directory | Select-Object -First 1;" ^
|
||||
"if (-not $root) { throw 'archive looks empty' }" ^
|
||||
"Move-Item $root.FullName (Join-Path (Get-Location) '%TARGET%');" ^
|
||||
"Remove-Item -Recurse -Force $tmp, $zip"
|
||||
if errorlevel 1 (
|
||||
echo.
|
||||
echo [ERROR] Download failed.
|
||||
echo.
|
||||
echo Possible reasons:
|
||||
echo - %REPO_WEB% is not reachable from this computer;
|
||||
echo - the repository is private, or the server requires signing in
|
||||
echo to view anything. In that case download the project manually
|
||||
echo and run setup.cmd inside it.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
goto :setup
|
||||
|
||||
:update
|
||||
echo [2/4] Already downloaded - updating.
|
||||
where git >nul 2>&1
|
||||
if not errorlevel 1 (
|
||||
if exist "%TARGET%\.git" (
|
||||
pushd "%TARGET%"
|
||||
git pull --ff-only
|
||||
popd
|
||||
)
|
||||
)
|
||||
|
||||
rem ---------- 3. venv and dependencies ----------
|
||||
:setup
|
||||
if not exist "%TARGET%\requirements.txt" (
|
||||
echo [ERROR] Download looks incomplete: requirements.txt is missing.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
pushd "%TARGET%"
|
||||
|
||||
echo [3/4] Creating virtual environment and installing dependencies...
|
||||
if not exist "venv" python -m venv venv
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Could not create venv.
|
||||
popd
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
venv\Scripts\python.exe -m pip install --upgrade pip --quiet
|
||||
venv\Scripts\python.exe -m pip install -r requirements.txt --quiet
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Dependency installation failed.
|
||||
popd
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
rem ---------- 4. Ollama address ----------
|
||||
echo.
|
||||
echo [4/4] Where is Ollama running?
|
||||
echo Enter to accept the default (this computer).
|
||||
echo Otherwise type the address of the machine on your network,
|
||||
echo for example: http://192.168.1.50:11434
|
||||
echo.
|
||||
set OLLAMA_ADDR=
|
||||
set /p OLLAMA_ADDR="Ollama URL [http://localhost:11434]: "
|
||||
if "%OLLAMA_ADDR%"=="" set OLLAMA_ADDR=http://localhost:11434
|
||||
|
||||
rem Локальный конфиг делаем из образца: рядом с адресом Ollama человек увидит
|
||||
rem и остальные настройки с пояснениями, а не одну голую строку.
|
||||
if exist ".env" (
|
||||
echo .env already exists - left as is. Edit it by hand if needed.
|
||||
) else (
|
||||
rem -Encoding UTF8 обязателен: без него PowerShell 5.1 читает файл в
|
||||
rem системной кодировке, и русские пояснения превращаются в кракозябры.
|
||||
powershell -NoProfile -Command ^
|
||||
"$src = if (Test-Path '.env.example') { Get-Content '.env.example' -Encoding UTF8 } else { @('OLLAMA_HOST=') };" ^
|
||||
"$out = $src -replace '^\s*#?\s*OLLAMA_HOST=.*', 'OLLAMA_HOST=%OLLAMA_ADDR%';" ^
|
||||
"if (-not ($out -match '^OLLAMA_HOST=')) { $out += 'OLLAMA_HOST=%OLLAMA_ADDR%' }" ^
|
||||
"Set-Content -Path '.env' -Value $out -Encoding UTF8"
|
||||
if errorlevel 1 (
|
||||
> .env echo OLLAMA_HOST=%OLLAMA_ADDR%
|
||||
)
|
||||
echo Saved to .env ^(OLLAMA_HOST=%OLLAMA_ADDR%^)
|
||||
)
|
||||
|
||||
rem Check whether Ollama actually answers, and report in plain language.
|
||||
venv\Scripts\python.exe -c "from hlamingo import ollama, config; ok=ollama.check(); print((' Ollama ' + config.OLLAMA_HOST + (' отвечает.' if ok else ' НЕ отвечает — приложение будет работать, но без разбора фраз и поиска по смыслу.')))"
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo Done.
|
||||
echo ========================================
|
||||
echo.
|
||||
echo Start the app: %CD%\start.cmd
|
||||
echo Run tests: %CD%\tests\run.cmd
|
||||
echo.
|
||||
echo A shortcut named "hlamingo" is on your Desktop.
|
||||
powershell -NoProfile -Command ^
|
||||
"$s=(New-Object -ComObject WScript.Shell).CreateShortcut([IO.Path]::Combine([Environment]::GetFolderPath('Desktop'),'hlamingo.lnk'));" ^
|
||||
"$s.TargetPath=(Join-Path (Get-Location) 'start.cmd');" ^
|
||||
"$s.WorkingDirectory=(Get-Location).Path;" ^
|
||||
"$s.Description='hlamingo - where my stuff is';" ^
|
||||
"$s.Save()" 2>nul
|
||||
|
||||
popd
|
||||
echo.
|
||||
set RUNNOW=
|
||||
set /p RUNNOW="Start it now? [Y/n]: "
|
||||
if /i "%RUNNOW%"=="n" goto :end
|
||||
pushd "%TARGET%"
|
||||
call start.cmd
|
||||
popd
|
||||
|
||||
:end
|
||||
endlocal
|
||||
Reference in New Issue
Block a user