代理程式改變了我們思考來源控制、檔案系統和持久化狀態的方式。開發人員和代理程式生成的程式碼比以往任何時候都要多,未來 5 年編寫的程式碼數量將超過所有程式設計歷史記錄,這促使系統規模發生了數量級變化來滿足此需求。在這一點上,原始碼控制平台尤其困難重重:這些平台旨在滿足人類的需求,而不是應對不眠不休、同時處理多個問題、永不疲倦的代理程式驅動的 10 倍數量變化。
我們認為有必要開發一種新的基元:分散式的版本化檔案系統,其首先是為代理程式而建置,並且能支援現今正在開發的應用程式類型。
我們稱之為 Artifacts:支援 Git 的版本化檔案系統。您可透過程式設計方式建立儲存庫,與您的代理程式、沙箱、Workers 或任何其他運算範例並排放置,並從任何常規 Git 用戶端與之連線。
是否要為每個代理程式工作階段提供儲存庫?Artifacts 能夠做到。每個沙箱執行個體呢?還是 Artifacts。是否需要透過已知良好的起點建立 10,000 個進程複製?您猜對了:同樣靠 Artifacts。Artifacts 可公開 REST API 和原生 Workers API,以便在不適合 Git 用戶端的環境中(例如任何無伺服器功能)建立儲存庫、生成憑證並提交。
付費 Workers 方案的所有開發人員都可使用 Artifacts 的私人測試版,我們的目標是在 5 月初之前將其作為公開測試版。
// Create a repo
const repo = await env.AGENT_REPOS.create(name)
// Pass back the token & remote to your agent
return { repo.remote, repo.token }
# Clone it and use it like any regular git remote
$ git clone https://x:${TOKEN}@123def456abc.artifacts.cloudflare.net/git/repo-13194.git
就是這樣。一個隨時可用,動態建立的裸機儲存庫,任何 Git 用戶端都可操作。
如果您想要從現有的 Git 儲存庫啟動一個 Artifacts 儲存庫,以便代理程式可獨立運作並推送獨立變更,您也可使用 .import() 來實現:
interface Env {
ARTIFACTS: Artifacts
}
export default {
async fetch(request: Request, env: Env) {
// Import from GitHub
const { remote, token } = await env.ARTIFACTS.import({
source: {
url: "https://github.com/cloudflare/workers-sdk",
branch: "main",
},
target: {
name: "workers-sdk",
},
})
// Get a handle to the imported repo
const repo = await env.ARTIFACTS.get("workers-sdk")
// Fork to an isolated, read-only copy
const fork = await repo.fork("workers-sdk-review", {
readOnly: true,
})
return Response.json({ remote: fork.remote, token: fork.token })
},
}
查看文件以開始使用,或者如果您想要瞭解 Artifacts 的使用方式、建置方式及其內部運作方式,請繼續閱讀。
代理程式瞭解 Git。其存在於大多數模型的訓練資料中。代理程式知道順利路徑和邊緣情況,而程式碼最佳化模型(和/或整套系統)特別擅長使用 Git。
此外,Git 的資料模型不僅適用於來源控制,還適用於您需要追蹤狀態、時間回溯和保留大量小型資料的任何事物。程式碼、設定、工作階段提示和代理程式歷程記錄:所有這些都是內容(「物件」),您通常希望以較小的區塊儲存(「提交」),並且能夠還原或以其他方式回復(「歷程記錄」)。
我們本可以發明一種全新、專屬的通訊協定…但這樣就會遇到啟動問題。AI 模型不知道,因此您必須分配技能或 CLI,或希望使用者已插入您的文件 MCP…所有這些都會增加摩擦。
但是,如果我們可以為代理程式提供一個經驗證的安全 HTTPS Git 遠端 URL,並讓其像 Git 儲存庫一樣運作,結果證明效果相當不錯。對於不支援 Git 的用戶端,例如 Cloudflare Worker、Lambda 函數或 Node.js 應用程式,我們已推出 REST API 以及(很快)推出語言特定的 SDK。這些用戶端亦可使用 isomorphic-git,但在許多情況下,更簡單的 TypeScript API 可減少所需的 API 介面。
Artifacts 的 Git API 可能會讓您認為其只是用於來源控制,但事實證明,Git API 和資料模型是一種保持狀態的強大方式,允許您對任何資料進行進程複製、時間回溯以及區分狀態。
在 Cloudflare 內部,我們將 Artifacts 用於我們的內部代理程式:自動將檔案系統的目前狀態和工作階段歷程記錄保留在每個工作階段的 Artifacts 儲存庫中。這讓我們能夠:
我們還與團隊交談過,他們希望在根本不需要 Git 通訊協定,但語義(還原、複製、差異化)為必要條件的情況下使用 Artifacts。將每個客戶的設定儲存在產品中,並希望能夠復原?Artifacts 可以很好地體現這一點。
我們樂見團隊不僅探索以 Git 為中心的使用案例,而且同樣積極探索 Artifacts 的非 Git 使用案例。
Artifacts 在 Durable Objects 之上建置。能夠建立數百萬(或數千萬)具狀態、隔離式運算執行個體,正是 Durable Objects 如今運作方式所固有的特徵;而這恰恰是我們支援每個命名空間容納數百萬個 Git 儲存庫所必需的能力。
美國職業棒球大聯盟(即時比賽扇出)、Confluence 白板以及我們自有的 Agents SDK,都在內部大規模地使用了 Durable Objects,因此,我們是在生產環境中執行一段時間的基元技術基礎上來建置此服務。
然而,我們確實需要一項能在 Cloudflare Workers 上執行的 Git 實作。其必須小巧、盡可能完整、可擴展(備註、LFS),而且高效。因此,我們使用 Zig 建置了一個,並將其編譯為 Wasm。
我們為什麼要使用 Zig?三個理由:
整個 Git 通訊協定引擎以純 Zig (無 libc)編寫,編譯為約 100KB WASM 二進位(具有最佳化空間!)。其實作了 SHA-1、zlib inflate/deflate、增量編碼/解碼、封裝剖析和完整的 Git Smart HTTP 通訊協定 — 全部從頭開始,除了標準庫之外,沒有其他外部相依項。
Zig 讓我們能夠 手動控制記憶體分配,這在 Durable Objects 等受限環境中非常重要。Zig 建置系統還讓我們能夠輕鬆地在 WASM 執行階段(生產)和原生建置(針對 libgit2 進行測試以進行正確性驗證)之間共用程式碼。
WASM 模組透過精簡回呼介面來與 JS 主機通訊:11 個主機匯入函數用於儲存操作(host_get_object、host_put_object 等),1 個用於串流輸出 (host_emit_bytes)。WASM 端可完全隔離測試。
在內部,Artifacts 還使用 R2(用於快照)和 KV(用於追蹤驗證權杖):
Artifacts 運作方式 (Workers、Durable Objects 和 WebAssembly)
Worker 充當前端,處理驗證和授權、關鍵指標(錯誤、延遲),並動態地查找每個 Artifacts 儲存庫(Durable Object)。
具體而言:
除此之外,我們還原生支援 git-notes。Artifacts 以代理程式優先的方式設計,而註釋使代理程式能夠將註釋(中繼資料)新增至 Git 物件。這包括可從儲存庫讀取/寫入而無需改變物件本身的提示、代理程式屬性和其他中繼資料。
大型儲存庫,產生大問題?認識 ArtifactFS。
大多數儲存庫並沒有那麼大,Git 在儲存方面被設計得非常高效:大多數儲存庫最多只需要幾秒鐘即可複製,而這主要取決於網路設定時間、授權和總和檢查碼。在大多數代理程式或沙箱情境中,這是可行的:只需在沙箱啟動時複製儲存庫並開始運作。
但是,多 GB 儲存庫和/或包含數百萬個物件的儲存庫呢?如何快速複製該儲存庫,而又不會阻止代理程式在數分鐘內開始工作並取用運算?
一個常用的 Web 框架(2.4GB,歷史悠久!)需要將近 2 分鐘才能複製。淺層複製更快,但不足以達到個位數秒,而且我們並不總是希望忽略歷程記錄(代理程式覺得這很有用)。
我們能否將大型儲存庫縮減至約 10-15 秒,以便我們的代理程式開始運作?嗯,是的:使用一些技巧。
作為我們發布 Artifacts 的一部分,我們對 ArtifactFS 使用開放原始碼,這是一個檔案系統驅動程式,旨在盡快裝載大型 Git 儲存庫,即時載入檔案內容而不是在初始複製時封鎖。適用於代理程式、沙箱、容器,以及其他注重啟動時間非常關鍵。如果您可將沙箱針對每個大型儲存庫的啟動時間縮短約 90-100 秒,並且每月執行 10,000 個此類沙箱工作:那就能節省 2,778 沙箱小時。
您可將 ArtifactFS 視為「非同步 Git 複製」:
ArtifactFS 執行 Git 儲存庫的無 blob 複製:其擷取檔案樹和參考,但不會擷取檔案內容。還可在沙箱啟動期間執行此操作,然後您的代理程式工具便可開始運作。
在後台,它會透過輕量級精靈同時開始下載檔案內容。
它會優先處理代理程式通常想要先操作的檔案:套件資訊清單 (package.json、go.mod)、設定檔和程式碼,並在可能的情況下降低二進位大型物件(影像、可執行檔和其他非文字檔案)的優先順序,以便代理程式在檔案本身載入時掃描檔案樹。
如果代理程式嘗試讀取時檔案尚未完全水合,則讀取會被封鎖,直至檔案完全水合。
檔案系統不會嘗試將檔案「同步」回遠端儲存庫:因為有數千或數百萬個物件,這通常會非常慢,而且因為我們使用的是 Git,所以不需要這樣做。您的代理只需要提交並推送,就像對待任何儲存庫一樣。無需學習新的 API。
重要的是,ArtifactFS 適用於任何 Git 遠端,而不僅僅是我們自己的 Artifacts。如果您從 GitHub、GitLab 或自託管 Git 基礎架構複製大型儲存庫,您仍可使用 ArtifactFS。
今天的發布只是測試版,我們已經在開發許多功能,這些功能將在接下來的幾週內推出:
擴充我們公開的可用指標。今天,我們將發布每個命名空間關鍵作業計數、儲存庫、以及每個儲存庫的儲存位元組的指標,以便讓管理數百萬個 Artifact 不再繁瑣。
支援儲存庫層級事件的事件訂閱,以便我們能夠在推送、提取、複製和進程複製時發出事件至命名空間內的任何儲存庫。此外還允許您取用事件、寫入 Webhook,並使用這些事件來通知最終使用者,在產品中驅動生命週期事件,和/或執行推送後作業(如 CI/CD)。
原生 TypeScript、Go 和 Python 用戶端 SDK,用於與 Artifacts API 互動
存放庫層級的搜尋 API 和命名空間範圍的搜尋 API,例如「尋找所有包含 package.json 檔案的儲存庫」
此外,我們還規劃了一個適用於 Workers 組建的 API,讓您能夠在任何代理程式驅動的工作流程上執行 CI/CD 任務。
我們使用 Artifacts 仍處於早期,但希望我們的定價適用於代理程式規模:擁有數百萬個儲存庫必須具有成本效益,未使用(或很少使用)的儲存庫不應成為拖累,我們的定價應符合代理程式的大規模單租用戶性質。
而且您不需要考慮某個儲存庫是否會被使用、是熱儲存庫還是冷儲存庫,和/或是否會有代理程式將其喚醒。我們會針對每個儲存庫,依您取用的儲存體和操作(例如,複製、進程複製、推送和提取)來計費。
| 單位價格 | 已內含 |
|---|
操作 | 每 1,000 次操作 0.15 美元 | 包含前 10,000(每月) |
儲存 | 每月每 GB 0.50 美元 | 包含前 1GB |
無論您有 1,000 個、100,000 個還是 1,000 萬個儲存庫,繁忙的大型儲存庫比不常用的小型儲存庫成本更高。
隨著測試版的進行,我們還將在 Workers 免費方案中納入 Artifacts(有一些公平的限制),而且如果定價發生變化,我們會在整個測試版中提供更新,並在對任何使用量計費之前提供更新。
Artifacts 推出私人測試版,我們預計公開測試版將於 5 月初推出(具體來說,是 2026 年!)。我們將在接下來的幾週內逐步允許客戶使用,如果您對私人測試版感興趣,可直接註冊。
同時,您可透過以下方式瞭解有關 Artifacts 的更多資訊:
檢視變更記錄以追蹤測試版的進度。