commit fe689a05773ddcb48a05627238bea612da202f8a Author: Di Date: Tue Sep 8 15:24:59 2026 +0800 发布页 + 一句话安装脚本 install.sh 放在 git 树里而不是只作 release 资产:这个 raw URL 永不变, 每发一版只改文件内容指向新 release,README 里的安装命令不用跟着换。 diff --git a/README.md b/README.md new file mode 100644 index 0000000..ad66b4c --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +# Agent for Science 科研平台 + +装上、打开、说一句你想研究什么 —— 它自己写代码、跑计算、看结果、出论文。 + +数据和计算都在**你自己的机器上**:项目是本地 git 仓库,模型 key 只存在本机。 + +--- + +## macOS 安装 + +一条命令(Apple Silicon): + +```sh +curl -fsSL https://desktop-9el2944.taile9f15e.ts.net/wangd/agent-for-science/raw/branch/main/install.sh | sh +``` + +装完会自己打开。**不会弹「无法验证开发者」** —— 那个提示只对浏览器下载的文件出现,这条路用 `curl`,系统不会拦。 + +
+想先看脚本做什么,或者手动装 + +脚本只做五件事:下载 dmg → 用 `SHA256SUMS` 核对 → 挂载 → 复制进「应用程序」→ 打开。任何一步失败就停。 + +先看再跑: + +```sh +curl -fsSL https://desktop-9el2944.taile9f15e.ts.net/wangd/agent-for-science/raw/branch/main/install.sh -o install.sh +less install.sh +sh install.sh +``` + +只想看它打算做什么、先不动手:`AFS_DRY_RUN=1 sh install.sh` + +也可以从 [Releases](https://desktop-9el2944.taile9f15e.ts.net/wangd/agent-for-science/releases) 直接下 `.dmg` 拖进「应用程序」。走浏览器下载的话,第一次打开会被系统拦(应用还没买签名证书): +**系统设置 → 隐私与安全性 → 拉到最下面「仍要打开」→ 再确认一次**。每台机器只需要这一次。 + +
+ +## Windows + +打包器已经能出便携目录和安装器,但还没在这里发布。先用 macOS 版。 + +--- + +## 装完第一件事 + +打开后它问两个问题,第二个可以跳过: + +1. **用哪个模型** —— 填提供商、地址、API key。key 加密后存在这台机器上,不发去别处。 +2. **有没有组织服务器** —— 一个人用直接跳过。 + +然后就可以新建项目、开始提问了。 + +## 更新 + +应用自己会看有没有新版本,有就在界面上出一行「有新版本 · 现在更新」。点一下,它下载、校验签名、重启自己。**更新只换程序,不碰你的项目数据。** + +发布件都带 ed25519 签名,签名对不上一律拒收。 + +## 你的东西放在哪 + +``` +~/.harness-framework/ + db.sqlite 设置与索引(仅本人可读) + project-worktrees/ 每个项目一个 git 仓库 + logs/backend.log 出问题时看这里 +``` + +卸载 = 把「应用程序」里的图标扔进废纸篓。数据留在上面那个目录,你自己决定要不要删。 + +## 系统要求 + +- macOS 13 或更新,Apple Silicon(M 系列) +- 约 1.5 GB 磁盘 +- 一个能用的模型 API key + +Python、git、LaTeX 都随包带,**不用先装任何东西**。 + +## 出问题了 + +1. 看 `~/.harness-framework/logs/backend.log` 最后几十行 +2. 应用自检: + ```sh + "/Applications/Agent for Science.app/Contents/Resources/python/bin/python3" -m app.launcher doctor + ``` + 它会印出数据根、界面、harness、git、PDF 引擎、版本、沙箱各在哪 —— 有一项是 `not found` 就是它。 +3. 还是不行,把上面两样发给我。 + +--- + +*内部试用版。发布件仓库,不含源码。* diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..41b9da0 --- /dev/null +++ b/install.sh @@ -0,0 +1,90 @@ +#!/bin/sh +# Agent for Science —— 内网安装(macOS,不经浏览器,不弹 Gatekeeper) +# +# curl -fsSL <发布目录>/install.sh | sh +# +# ## 为什么这条路不会弹「无法验证开发者」 +# +# Gatekeeper 只检查带「隔离标记」(com.apple.quarantine)的文件,而那个标记是 +# 浏览器 / 邮件 / AirDrop 在保存文件时打上去的。curl 不打。所以经这条路装的 +# 应用,系统根本不会去看它签没签 —— 这不是绕过,是 macOS 自己划的线:从哪来的 +# 文件由谁负责。内网发布目录由我们自己负责,就像共享盘拷过来一样。 +# +# 我们在最后还是会把隔离标记(若有)去掉一次。理由:万一有人先用浏览器下了 dmg +# 再手动跑这个脚本,装出来的 .app 会带着标记;那时用户看到的是四步走的系统设置。 +# +# ## 它做什么 +# +# 下载 dmg → 用发布目录里的 SHA256SUMS 核对 → 挂载 → 复制进「应用程序」(写不了就 +# 进 ~/Applications)→ 卸载 → 打开。每一步失败就停,不留半个应用。 +# +# 环境变量:AFS_RELEASE_URL(发布目录;打包器已经烧了默认值)、AFS_INSTALL_DIR、AFS_AUTH(私有仓库)、 +# AFS_DRY_RUN=1(只打印要做什么,不做)。 +set -eu + +# 下面两行由打包器整行替换(占位符只能出现在这里,别处不许提它 —— 第一版把占位符 +# 也写进了 case 的模式里,替换后要么语法错、要么把正确的地址当成"没填"拒掉)。 +DEFAULT_URL="https://desktop-9el2944.taile9f15e.ts.net/wangd/agent-for-science/releases/download/v0.3.0" +DEFAULT_DMG="Agent-for-Science-0.3.0-arm64.dmg" +BASE="${AFS_RELEASE_URL:-$DEFAULT_URL}" +DMG="$DEFAULT_DMG" +APP="Agent for Science.app" +DEST="${AFS_INSTALL_DIR:-/Applications}" +DRY="${AFS_DRY_RUN:-}" +# 私有 Forgejo 仓库的 release 资产要登录才下得到:AFS_AUTH="user:token"(只读 token 即可)。 +AUTH="${AFS_AUTH:-}" + +say() { printf '%s\n' "$*"; } +die() { printf '✗ %s\n' "$*" >&2; exit 1; } +run() { if [ -n "$DRY" ]; then say " \$ $*"; else "$@"; fi; } + +if [ -z "$BASE" ] || [ "$BASE" = "$(printf '__RELEASE''_URL__')" ]; then + die "没有发布目录地址。打包时传 --release-url,或运行前 export AFS_RELEASE_URL=http://<内网主机>/afs" +fi +[ "$(uname -s)" = "Darwin" ] || die "这个脚本只装 macOS;Windows 用 install.ps1" +[ "$(uname -m)" = "arm64" ] || die "这个包是 Apple Silicon(arm64)的,这台是 $(uname -m)" + +BASE="${BASE%/}" +WORK="$(mktemp -d "${TMPDIR:-/tmp}/afs-install.XXXXXX")" +cleanup() { + [ -d "$WORK/mnt" ] && hdiutil detach "$WORK/mnt" -quiet >/dev/null 2>&1 || true + rm -rf "$WORK" +} +trap cleanup EXIT + +say "① 下载 $DMG(curl,不会打隔离标记)" +run curl -fsSL --retry 3 ${AUTH:+-u "$AUTH"} "$BASE/$DMG" -o "$WORK/$DMG" +run curl -fsSL --retry 3 ${AUTH:+-u "$AUTH"} "$BASE/SHA256SUMS" -o "$WORK/SHA256SUMS" + +say "② 核对 SHA-256" +if [ -z "$DRY" ]; then + expected="$(grep " $DMG\$" "$WORK/SHA256SUMS" | awk '{print $1}')" + [ -n "$expected" ] || die "SHA256SUMS 里没有 $DMG 这一行" + actual="$(shasum -a 256 "$WORK/$DMG" | awk '{print $1}')" + [ "$expected" = "$actual" ] || die "校验和不对:发布目录说 $expected,下载到的是 $actual —— 不装" + say " ✓ $actual" +else + say " \$ shasum -a 256 -c(对 SHA256SUMS 里 $DMG 那一行)" +fi + +say "③ 装进 $DEST" +if [ -z "$DRY" ] && [ ! -w "$DEST" ]; then + DEST="$HOME/Applications"; mkdir -p "$DEST" + say " /Applications 写不了,改装到 $DEST" +fi +if [ -z "$DRY" ] && pgrep -x AgentForScience >/dev/null 2>&1; then + say " 应用正在运行,先退出它" + osascript -e 'tell application "Agent for Science" to quit' >/dev/null 2>&1 || true + sleep 2 +fi +run hdiutil attach "$WORK/$DMG" -nobrowse -readonly -quiet -mountpoint "$WORK/mnt" +run rm -rf "$DEST/$APP" +run ditto "$WORK/mnt/$APP" "$DEST/$APP" +run hdiutil detach "$WORK/mnt" -quiet +[ -n "$DRY" ] || rmdir "$WORK/mnt" 2>/dev/null || true + +say "④ 去掉隔离标记(若有)" +run xattr -dr com.apple.quarantine "$DEST/$APP" 2>/dev/null || true + +say "✅ 装好了:$DEST/$APP" +run open -a "$DEST/$APP"