electron-updater in the shell (packaged builds only; dev never updates). Checks at startup + every 24h, downloads silently, and the renderer shows a Restart banner once the update is staged (it installs on quit either way). Manual "Check for Updates..." under the app menu answers via dialog. Every updater event routes through the shell log and is caught - the updater can never take the app down (verified live: a feed failure logs three lines and the app runs on). LH_UPDATE_FEED overrides the baked GitHub feed with a generic local server - the pre-release drill: serve latest-mac.yml + zip + blockmap from localhost and a real installed copy updates itself, no release, no public repo. The asar allow-list re-includes electron-updater + its 16-package runtime tree explicitly (gitignore last-match-wins; asar verified at 2.1 MB). The banner rides the preload bridge (onUpdateStatus/installUpdate) and renders nothing in the browser. window.lh typing centralized in sidebar.tsx's declaration.
85 lines
2.7 KiB
JSON
85 lines
2.7 KiB
JSON
{
|
|
"name": "learnharness",
|
|
"version": "0.2.0",
|
|
"license": "AGPL-3.0-only",
|
|
"description": "A standalone learning harness: a teacher agent (AI SDK) with quiz/ask interactions, session artifacts, and a derived knowledge graph of what the learner knows.",
|
|
"type": "module",
|
|
"private": true,
|
|
"main": "electron/main.cjs",
|
|
"scripts": {
|
|
"dev": "next dev",
|
|
"build": "next build",
|
|
"start": "next start",
|
|
"test": "NODE_ENV=test tsx --test tests/*.test.ts tests/*.test.tsx",
|
|
"lint": "eslint .",
|
|
"typecheck": "tsc --noEmit",
|
|
"desktop:dev": "concurrently -k \"next dev\" \"LH_DEV_URL=http://localhost:3000 electron .\"",
|
|
"dev:fresh": "bash scripts/dev-fresh.sh",
|
|
"desktop:dist": "rm -rf dist .next/standalone && next build && node scripts/build-server.mjs && node scripts/smoke-server.mjs && APPLE_KEYCHAIN_PROFILE=LH_NOTARY APPLE_TEAM_ID=JS6XN22HY6 electron-builder --mac --arm64"
|
|
},
|
|
"dependencies": {
|
|
"@earendil-works/pi-agent-core": "1.0.2",
|
|
"@earendil-works/pi-ai": "1.0.2",
|
|
"@mozilla/readability": "^0.6.0",
|
|
"@radix-ui/react-use-controllable-state": "^1.2.6",
|
|
"@rive-app/react-webgl2": "^4.32.1",
|
|
"@streamdown/cjk": "^1.0.3",
|
|
"@streamdown/code": "^1.1.1",
|
|
"@streamdown/math": "^1.0.2",
|
|
"@streamdown/mermaid": "^1.0.2",
|
|
"@xyflow/react": "^12.11.3",
|
|
"ansi-to-react": "^6.2.6",
|
|
"class-variance-authority": "^0.7.1",
|
|
"clsx": "^2.1.1",
|
|
"cmdk": "^1.1.1",
|
|
"d3-force": "^3.0.0",
|
|
"d3-selection": "^3.0.0",
|
|
"d3-shape": "^3.2.0",
|
|
"d3-zoom": "^3.0.0",
|
|
"dagre-d3-es": "7.0.14",
|
|
"electron-updater": "^6.8.9",
|
|
"embla-carousel-react": "^8.6.0",
|
|
"katex": "^0.16.47",
|
|
"linkedom": "^0.18.13",
|
|
"lucide-react": "^1.33.0",
|
|
"media-chrome": "^4.19.2",
|
|
"mermaid": "^11.17.0",
|
|
"motion": "^13.1.1",
|
|
"nanoid": "^6.0.1",
|
|
"next": "^16.3.2",
|
|
"next-themes": "^0.4.6",
|
|
"pdfjs-dist": "^6.3.289",
|
|
"puppeteer-core": "^25.8.0",
|
|
"radix-ui": "^1.6.7",
|
|
"react": "^19.2.8",
|
|
"react-dom": "^19.2.8",
|
|
"react-jsx-parser": "^2.4.1",
|
|
"remark-breaks": "^4.0.0",
|
|
"streamdown": "^2.5.0",
|
|
"tailwind-merge": "^3.6.0",
|
|
"tokenlens": "^1.3.1",
|
|
"turndown": "^7.2.4",
|
|
"typebox": "^1.3.27",
|
|
"use-stick-to-bottom": "^1.1.6",
|
|
"zod": "^4.4.3"
|
|
},
|
|
"devDependencies": {
|
|
"@next/eslint-plugin-next": "^16.3.3",
|
|
"@tailwindcss/postcss": "^4.3.3",
|
|
"@types/node": "^24.0.0",
|
|
"@types/react": "^19.2.18",
|
|
"@types/react-dom": "^19.2.4",
|
|
"@types/turndown": "^5.0.6",
|
|
"@typescript-eslint/parser": "^8.68.0",
|
|
"concurrently": "^10.0.5",
|
|
"electron": "^44.4.1",
|
|
"electron-builder": "^26.15.3",
|
|
"eslint": "^9.39.5",
|
|
"eslint-import-resolver-typescript": "^4.4.5",
|
|
"eslint-plugin-import": "^2.32.0",
|
|
"tailwindcss": "^4.3.3",
|
|
"tsx": "^4.19.0",
|
|
"typescript": "^5.6.0"
|
|
}
|
|
}
|