Google宣布编程智能体Jules将于2026年底关停
来源标题:Jules Turndown
Google宣布为统一智能体编程业务,Jules将于2026年12月31日停止服务,用户须在11月11日前完成现有会话,此后至年底转为只读。用户可安装Jules Tools将账户设置、仓库、记忆及所有会话与代码补丁导出至本地,代码和PR仍保留在GitHub。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
我们写这封信是为了通知你,作为整合智能体编程工作的一部分,Jules 将于 2026 年 12 月 31 日停止服务。你可以在 2026 年 11 月 11 日之前继续完成剩余的会话。2026 年 11 月 11 日之后,我们会将 Jules 切换为只读模式,直至年底。
当初推出 Jules 时,它只是一个实验,目的是了解异步编程智能体如何帮助你处理积压任务、更快地交付。你们用它构建的东西让我们看清了智能体开发的方向,这些经验正在塑造 Google 旗下的多款产品,包括我们以智能体为先的平台 Google Antigravity。
现在,你可以将 Jules 掌握的关于你工作的全部数据导出到一个本地文件夹:账户设置、环境变量、定时任务、已连接的仓库、记忆、初始化脚本,以及每一个会话——包括其 prompt、计划、完整活动日志和代码补丁。
你的代码、分支和 pull request 本来就存放在 GitHub 上,因此会留在原处。导出内容涵盖的是保存在 Jules 内部的配置和历史记录。
要执行导出,请安装 Jules Tools 并登录:
npm install -g @google/jules jules login
然后从你的主目录打开一个 CLI 编程智能体(例如 Antigravity CLI),粘贴下面的导出 prompt。该智能体会检查你的环境、执行导出,并告诉你保存了哪些内容。
我想把所有数据从 Google Jules 导出到一个本地文件夹:设置、环境变量、定时任务、已连接的仓库、记忆、初始化脚本,以及每一个会话(prompt、计划、完整活动日志和代码补丁)。请按以下顺序操作:
- 准备工作
- 检查 Jules CLI 是否已安装(
which jules)。如果没有安装,请用npm install -g @google/jules安装。如果 npm 没有安装,请告诉我并停止。 - 检查我是否已登录:在 macOS 上运行
security find-generic-password -s jules-cli -a default(仅查元数据,不加 -w),在 Linux 上运行secret-tool lookup service jules-cli username default。如果没有对应条目,请让我自己运行! jules login。这是交互式的浏览器登录,所以不要替我运行。等我确认完成后再继续。 - 运行
jules remote list --repo。如果它返回 401 并提示 GitHub 相关问题,请告诉我前往 https://github.com/apps/google-labs-jules/installations/select_target 连接我的 GitHub 账户,并等我确认。如果我从未在 Jules 中使用过 GitHub 仓库,可以跳过这一步;导出结果只是不含仓库数据。
- 导出:将下面的脚本保存为文件,并从我的主目录运行它。然后告诉我导出了哪些内容(脚本打印的计数)以及该文件夹的完整路径。不要打印我的 access token 或 env-variables.json 中的值。
其他人已经遇到的问题:
- Jules CLI 将登录信息存储在 macOS Keychain 中(service 为 "jules-cli",account 为 "default"),格式为 "go-keyring-base64:<base64 JSON>"。脚本会对其进行解码。access token 在登录约一小时后过期;如果每次调用都返回 401,请运行任意
jules命令,或让我重新运行! jules login。 - 如果 ListSources 返回 401 "missing required authentication credential",但其他调用正常,说明我的 GitHub 账户未连接到 Jules(见第 1 步)。
- 设置、环境变量、仓库和记忆来自内部的
$rpc端点。会话来自 https://aida.googleapis.com/v1/swebot 下的 REST 端点(/tasks、/tasks/{id}、/tasks/{id}/activities),也就是 CLI 自身使用的端点。两者均未公开文档,因此如果某个调用开始返回 404/400,请告诉我是哪一个,而不是猜测修复方法。 - 仓库列表不包含初始化脚本或测试命令;脚本会从每个会话的代码输出(repoMetadata)中恢复它们。记忆返回空({})只表示没有记忆。
- API 可能返回比
jules remote list --session显示的更多会话(较旧的会话)。这是预期情况。
import base64, json, pathlib, re, subprocess, sys, urllib.error, urllib.parse, urllib.request
def get_token():
for cmd in [["security", "find-generic-password", "-s", "jules-cli", "-a", "default", "-w"],
["secret-tool", "lookup", "service", "jules-cli", "username", "default"]]:
try:
out = subprocess.check_output(cmd, stderr=subprocess.DEVNULL).decode().strip()
if out.startswith("go-keyring-base64:"):
out = base64.b64decode(out.split(":", 1)[1]).decode()
if out: return json.loads(out)["access_token"]
except Exception: pass
p = pathlib.Path.home() / ".jules/cache/oauth_creds.json"
if p.exists(): return json.loads(p.read_text())["access_token"]
sys.exit("Run `jules login` first.")
TOKEN = get_token()
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
RPC = "https://aida.googleapis.com/$rpc/language_labs.aida.swebot.proto.SweBotService"
REST = "https://aida.googleapis.com/v1/swebot"
OUT = pathlib.Path("./jules-export"); OUT.mkdir(exist_ok=True)
errors = []
def rpc(m, b=None):
req = urllib.request.Request(f"{RPC}/{m}", data=json.dumps(b or {}).encode(), headers=HEADERS, method="POST")
with urllib.request.urlopen(req, timeout=60) as r: return json.loads(r.read().decode() or "{}")
def get(path, **params):
q = ("?" + urllib.parse.urlencode(params)) if params else ""
with urllib.request.urlopen(urllib.request.Request(f"{REST}{path}{q}", headers=HEADERS), timeout=60) as r:
return json.loads(r.read().decode() or "{}")
def paged(fetch, key):
items, token = [], None
while True:
resp = fetch(token)
items += resp.get(key, [])
token = resp.get("nextPageToken")
if not token: return items
def safe(s): return re.sub(r"[^a-zA-Z0-9._-]", "_", s)
def dump(path, obj): path.parent.mkdir(parents=True, exist_ok=True); path.write_text(json.dumps(obj, indent=2))
# 账户级数据
dump(OUT / "user-settings.json", rpc("GetUserSettings"))
dump(OUT / "env-variables.json", rpc("ListEnvironmentVariables"))
dump(OUT / "scheduled-tasks.json", rpc("ListScheduledTasks"))
# 仓库(来源)及其记忆
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。