horizon-mcp 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -76,8 +76,8 @@ Every tool declares MCP annotations (`readOnlyHint`, `destructiveHint`, `idempot
76
76
  | `horizon_get_leaderboard_top` | Get the top leaderboard entries with each player's profile, optionally by board key |
77
77
  | `horizon_get_user_rank` | Get a user's leaderboard rank, optionally by board key |
78
78
  | `horizon_get_leaderboard_around` | Get leaderboard entries around a user's position, optionally by board key |
79
- | `horizon_save_cloud_data` | Save cloud data for a user |
80
- | `horizon_load_cloud_data` | Load cloud save data for a user |
79
+ | `horizon_save_cloud_data` | Save cloud data for a user, optionally only at an `expectedRevision` (409 on conflict) |
80
+ | `horizon_load_cloud_data` | Load cloud save data for a user, with its `revision` |
81
81
  | `horizon_get_remote_config` | Get a single remote config value by key |
82
82
  | `horizon_get_all_remote_configs` | Get all remote config values |
83
83
  | `horizon_get_localization` | Get a single localized string by key, optionally for a specific language |
@@ -52,6 +52,27 @@ describe("HorizonApiClient", () => {
52
52
  expect(options.headers["X-API-Key"]).toBe("test-key");
53
53
  expect(options.headers.Authorization).toBe("Bearer s");
54
54
  });
55
+ it("postWithHeaders returns the body and the response headers", async () => {
56
+ const fakeFetch = vi.fn().mockResolvedValue({
57
+ ok: true,
58
+ status: 200,
59
+ headers: new Headers({ "X-Cloud-Save-Revision": "5" }),
60
+ text: async () => JSON.stringify({ found: true }),
61
+ });
62
+ vi.stubGlobal("fetch", fakeFetch);
63
+ const client = new HorizonApiClient("test-key", "https://example.com");
64
+ const result = await client.postWithHeaders("/api/v1/test", { a: 1 }, { Authorization: "Bearer s" });
65
+ const [, options] = fakeFetch.mock.calls[0];
66
+ expect(options.method).toBe("POST");
67
+ expect(options.headers.Authorization).toBe("Bearer s");
68
+ expect(result.data).toEqual({ found: true });
69
+ expect(result.headers.get("x-cloud-save-revision")).toBe("5");
70
+ });
71
+ it("postWithHeaders throws HorizonApiError on a non-ok response", async () => {
72
+ vi.stubGlobal("fetch", mockFetchResponse({ error: "conflict" }, { status: 409 }));
73
+ const client = new HorizonApiClient("test-key", "https://example.com");
74
+ await expect(client.postWithHeaders("/api/v1/test", {})).rejects.toMatchObject({ status: 409 });
75
+ });
55
76
  it("GET merges extra headers such as a session", async () => {
56
77
  const fakeFetch = mockFetchResponse({ ok: true });
57
78
  vi.stubGlobal("fetch", fakeFetch);
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/api-client.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,iBAAiB,CACxB,IAAa,EACb,IAAwC;IAExC,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,GAAG,CAAC;IACnC,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC,CAAC;IAEvD,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;QAC/B,EAAE;QACF,MAAM;QACN,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;QACtB,IAAI,EAAE,KAAK,IAAI,EAAE,CACf,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAClC,CAAC,CAAC;AAC5B,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC;IAEvC,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,KAAK,GAAG,aAAa,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,gBAAgB,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAC,OAAO,CACnE,2BAA2B,CAC5B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;QACvE,MAAM,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAEjC,MAAM,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;QAEvE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9C,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAE9D,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;QACvE,MAAM,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC,CAAC;QAE3E,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;QACvE,MAAM,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC,CAAC;QAEjF,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QAC7D,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;QACvE,MAAM,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC,CAAC;QAE1E,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QACxC,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACnD,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAClE,MAAM,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAEhE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACnD,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;QACrE,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC5C,MAAM,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAE7C,MAAM,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACjE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAClE,MAAM,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAEpC,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,SAAS,GAAG,iBAAiB,CAAC,WAAW,EAAE;YAC/C,MAAM,EAAE,GAAG;YACX,EAAE,EAAE,KAAK;SACV,CAAC,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAElE,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACzD,eAAe,CAChB,CAAC;QACF,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;YAChE,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,WAAW;SAClB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,SAAS,GAAG,iBAAiB,CAAC,aAAa,EAAE;YACjD,MAAM,EAAE,GAAG;YACX,EAAE,EAAE,KAAK;SACV,CAAC,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAElE,MAAM,MAAM,CACV,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAC7C,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACnC,MAAM,MAAM,CACV,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAC7C,CAAC,OAAO,CAAC,aAAa,CAAC;YACtB,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,aAAa;SACpB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;QACtC,MAAM,SAAS,GAAG,EAAE;aACjB,EAAE,EAAE;aACJ,iBAAiB,CAAC,IAAI,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC;QACpD,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAElE,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACzE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CACzC,IAAI,QAAQ,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,CAAC,CACrF,CAAC;QACF,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,SAAS,EAAE,qBAAqB,EAAE,mBAAmB,CAAC,CAAC;QAC3F,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,qBAAqB,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QAEpF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,EAAE,CAAC,UAAU,CACX,OAAO,EACP,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,QAAQ,CAAC,kCAAkC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAC7F,CAAC;QAEF,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;QACtE,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;YAC1D,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,kCAAkC;SACzC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;QACxC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC;QACnE,MAAM,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAEjC,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,MAAM,WAAW,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAEvC,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QACnC,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,sBAAsB,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,UAAU,CAAC;QACzC,MAAM,MAAM,GAAG,sBAAsB,EAAE,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,UAAU,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,4BAA4B,CAAC;QAE5D,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;QACxC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,sBAAsB,EAAG,CAAC;QACzC,MAAM,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE1B,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QAEpD,UAAU,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,0CAA0C;IACjF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,UAAU,CAAC;QAEzC,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;QACxC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,sBAAsB,EAAG,CAAC;QACzC,MAAM,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE1B,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"api-client.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/api-client.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cloud-save.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-save.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/cloud-save.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,117 @@
1
+ import { describe, it, expect, vi, afterEach } from "vitest";
2
+ import { registerCloudSaveTools, parseRevision } from "../cloud-save.js";
3
+ vi.mock("../api-client.js", async (importOriginal) => {
4
+ const actual = await importOriginal();
5
+ return {
6
+ ...actual,
7
+ createApiClientFromEnv: vi.fn(),
8
+ };
9
+ });
10
+ import { createApiClientFromEnv, HorizonApiError } from "../api-client.js";
11
+ // Server contract checked 2026-10-10 (horizOn-Server AppCloudSaveController and
12
+ // CloudSaveService.saveCloudSave): load answers X-Cloud-Save-Revision (0 = empty slot),
13
+ // save reads a plain numeric If-Match and answers 409 with {"error": "..."} on a mismatch.
14
+ const USER_ID = "550e8400-e29b-41d4-a716-446655440000";
15
+ const mockedCreateApiClient = vi.mocked(createApiClientFromEnv);
16
+ const registeredTools = new Map();
17
+ function createMockServer() {
18
+ return {
19
+ registerTool: vi.fn((name, config, handler) => {
20
+ registeredTools.set(name, { schema: config, handler });
21
+ }),
22
+ };
23
+ }
24
+ describe("registerCloudSaveTools", () => {
25
+ afterEach(() => {
26
+ registeredTools.clear();
27
+ vi.restoreAllMocks();
28
+ });
29
+ it.each([
30
+ [{ found: true, saveData: "{\"level\":2}" }, "3", 3],
31
+ [{ found: false, saveData: null }, "0", 0],
32
+ [{ found: false, saveData: null }, null, null],
33
+ ])("load returns the revision header (%j, header %s)", async (body, header, revision) => {
34
+ registerCloudSaveTools(createMockServer());
35
+ const headers = new Headers(header === null ? {} : { "X-Cloud-Save-Revision": header });
36
+ const mockPost = vi.fn().mockResolvedValue({ data: body, headers });
37
+ mockedCreateApiClient.mockReturnValue({ postWithHeaders: mockPost });
38
+ const { handler } = registeredTools.get("horizon_load_cloud_data");
39
+ const result = await handler({ userId: USER_ID, sessionToken: "session-985" });
40
+ expect(mockPost).toHaveBeenCalledWith("/api/v1/app/cloud-save/load", { userId: USER_ID }, { Authorization: "Bearer session-985" });
41
+ expect(result.structuredContent).toEqual({ ...body, revision });
42
+ expect(JSON.parse(result.content[0].text).revision).toBe(revision);
43
+ });
44
+ it("save sends expectedRevision as If-Match and returns the new revision", async () => {
45
+ registerCloudSaveTools(createMockServer());
46
+ const mockPost = vi.fn().mockResolvedValue({ success: true, dataSizeBytes: 11, revision: 4 });
47
+ mockedCreateApiClient.mockReturnValue({ post: mockPost });
48
+ const { handler } = registeredTools.get("horizon_save_cloud_data");
49
+ const result = await handler({ userId: USER_ID, data: "{\"level\":3}", sessionToken: "session-985", expectedRevision: 3 });
50
+ expect(mockPost).toHaveBeenCalledWith("/api/v1/app/cloud-save/save", { userId: USER_ID, saveData: "{\"level\":3}" }, { Authorization: "Bearer session-985", "If-Match": "3" });
51
+ expect(JSON.parse(result.content[0].text)).toEqual({ success: true, dataSizeBytes: 11, revision: 4 });
52
+ });
53
+ it("save sends If-Match 0 for an empty slot", async () => {
54
+ registerCloudSaveTools(createMockServer());
55
+ const mockPost = vi.fn().mockResolvedValue({ success: true, dataSizeBytes: 1, revision: 1 });
56
+ mockedCreateApiClient.mockReturnValue({ post: mockPost });
57
+ const { handler } = registeredTools.get("horizon_save_cloud_data");
58
+ await handler({ userId: USER_ID, data: "x", sessionToken: "session-985", expectedRevision: 0 });
59
+ expect(mockPost.mock.calls[0][2]).toEqual({ Authorization: "Bearer session-985", "If-Match": "0" });
60
+ });
61
+ it("save without expectedRevision stays an unconditional write", async () => {
62
+ registerCloudSaveTools(createMockServer());
63
+ const mockPost = vi.fn().mockResolvedValue({ success: true, dataSizeBytes: 1, revision: 2 });
64
+ mockedCreateApiClient.mockReturnValue({ post: mockPost });
65
+ const { handler } = registeredTools.get("horizon_save_cloud_data");
66
+ await handler({ userId: USER_ID, data: "x", sessionToken: "session-985" });
67
+ expect(mockPost.mock.calls[0][2]).toEqual({ Authorization: "Bearer session-985" });
68
+ });
69
+ it("save reports a 409 as a conflict with the way forward", async () => {
70
+ registerCloudSaveTools(createMockServer());
71
+ const body = "{\"error\":\"Cloud save changed on another device (expected revision 3, current revision 4)\"}";
72
+ const mockPost = vi.fn().mockRejectedValue(new HorizonApiError(409, body));
73
+ mockedCreateApiClient.mockReturnValue({ post: mockPost });
74
+ const { handler } = registeredTools.get("horizon_save_cloud_data");
75
+ const result = await handler({ userId: USER_ID, data: "stale", sessionToken: "session-985", expectedRevision: 3 });
76
+ expect(result.isError).toBe(true);
77
+ expect(result.content[0].text).toContain("conflict (HTTP 409)");
78
+ expect(result.content[0].text).toContain("revision 3");
79
+ expect(result.content[0].text).toContain("Nothing was written");
80
+ expect(result.content[0].text).toContain("horizon_load_cloud_data");
81
+ expect(result.content[0].text).toContain(body);
82
+ });
83
+ it("validates expectedRevision as a non-negative integer and keeps it optional", () => {
84
+ registerCloudSaveTools(createMockServer());
85
+ const { schema } = registeredTools.get("horizon_save_cloud_data");
86
+ const inputSchema = schema.inputSchema;
87
+ expect(inputSchema.expectedRevision.safeParse(undefined).success).toBe(true);
88
+ expect(inputSchema.expectedRevision.safeParse(0).success).toBe(true);
89
+ expect(inputSchema.expectedRevision.safeParse(12).success).toBe(true);
90
+ expect(inputSchema.expectedRevision.safeParse(-1).success).toBe(false);
91
+ expect(inputSchema.expectedRevision.safeParse(1.5).success).toBe(false);
92
+ });
93
+ it("documents the revision flow in both tool descriptions", () => {
94
+ registerCloudSaveTools(createMockServer());
95
+ const save = registeredTools.get("horizon_save_cloud_data").schema;
96
+ const load = registeredTools.get("horizon_load_cloud_data").schema;
97
+ expect(save.description).toContain("expectedRevision");
98
+ expect(save.description).toContain("409");
99
+ expect(load.description).toContain("revision");
100
+ expect(load.description).toContain("unknown state");
101
+ });
102
+ });
103
+ describe("parseRevision", () => {
104
+ it.each([
105
+ ["0", 0],
106
+ ["7", 7],
107
+ [" 12 ", 12],
108
+ [null, null],
109
+ ["", null],
110
+ ["-1", null],
111
+ ["abc", null],
112
+ ["\"3\"", null],
113
+ ])("parses %j as %j", (value, expected) => {
114
+ expect(parseRevision(value)).toBe(expected);
115
+ });
116
+ });
117
+ //# sourceMappingURL=cloud-save.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-save.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/cloud-save.test.ts"],"names":[],"mappings":"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"}
@@ -35,6 +35,14 @@ export declare class HorizonApiClient {
35
35
  headers: Headers;
36
36
  }>;
37
37
  post<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
38
+ /**
39
+ * POST that also returns the response headers (cloud save load answers
40
+ * X-Cloud-Save-Revision). Non-ok responses throw HorizonApiError like post.
41
+ */
42
+ postWithHeaders<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<{
43
+ data: T;
44
+ headers: Headers;
45
+ }>;
38
46
  put<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
39
47
  patch<T>(path: string, body?: unknown): Promise<T>;
40
48
  delete<T>(path: string, body?: unknown): Promise<T>;
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/tools/api-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,qBAAa,eAAgB,SAAQ,KAAK;aAEtB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;gBADZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM;CAK/B;AAiBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAE3E;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAE,MAAoB;IAU7E,OAAO,CAAC,WAAW;IAOb,GAAG,CAAC,CAAC,EACT,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAsBb;;;;OAIG;IACG,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAsB7C,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAenF,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAelF,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAelD,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;CAc1D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,GAAG,IAAI,CAOhE"}
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/tools/api-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,qBAAa,eAAgB,SAAQ,KAAK;aAEtB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;gBADZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM;CAK/B;AAiBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAE3E;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAE,MAAoB;IAU7E,OAAO,CAAC,WAAW;IAOb,GAAG,CAAC,CAAC,EACT,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAsBb;;;;OAIG;IACG,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAsB7C,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAezF;;;OAGG;IACG,eAAe,CAAC,CAAC,EACrB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAenC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAelF,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAelD,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;CAc1D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,GAAG,IAAI,CAOhE"}
@@ -113,6 +113,22 @@ export class HorizonApiClient {
113
113
  }
114
114
  return parseBody(response);
115
115
  }
116
+ /**
117
+ * POST that also returns the response headers (cloud save load answers
118
+ * X-Cloud-Save-Revision). Non-ok responses throw HorizonApiError like post.
119
+ */
120
+ async postWithHeaders(path, body, headers) {
121
+ const response = await fetch(`${this.baseUrl}${path}`, {
122
+ method: "POST",
123
+ headers: { ...this.authHeaders(), ...headers },
124
+ body: body !== undefined ? JSON.stringify(body) : undefined,
125
+ });
126
+ if (!response.ok) {
127
+ const responseBody = await response.text();
128
+ throw new HorizonApiError(response.status, responseBody);
129
+ }
130
+ return { data: await parseBody(response), headers: response.headers };
131
+ }
116
132
  async put(path, body, headers) {
117
133
  const response = await fetch(`${this.baseUrl}${path}`, {
118
134
  method: "PUT",
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/tools/api-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/tools/api-client.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,8 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Revision from the load header, or null when it is missing or not a number.
4
+ * Null means unknown (for example a self-hosted simpleServer), not an empty slot.
5
+ */
6
+ export declare function parseRevision(value: string | null): number | null;
2
7
  export declare function registerCloudSaveTools(server: McpServer): void;
3
8
  //# sourceMappingURL=cloud-save.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-save.d.ts","sourceRoot":"","sources":["../../src/tools/cloud-save.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAwBpE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAmE9D"}
1
+ {"version":3,"file":"cloud-save.d.ts","sourceRoot":"","sources":["../../src/tools/cloud-save.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA2BpE;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAGjE;AAkBD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAmF9D"}
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod/v4";
2
- import { createApiClientFromEnv, sessionHeaders } from "./api-client.js";
2
+ import { createApiClientFromEnv, HorizonApiError, sessionHeaders } from "./api-client.js";
3
3
  import { noApiKeyResponse, errorResponse, jsonResponse, structuredResponse, describeTool, READ_ONLY, DESTRUCTIVE_WRITE, SESSION_REQUIRED, SESSION_ERRORS, } from "./tool-helpers.js";
4
4
  import { LOAD_CLOUD_DATA_OUTPUT } from "./output-schemas.js";
5
5
  const userIdSchema = z.string().uuid().describe("Player user ID (UUID) from horizon_signup_* or horizon_signin_*");
@@ -8,38 +8,76 @@ const sessionTokenSchema = z
8
8
  .min(1)
9
9
  .max(256)
10
10
  .describe("accessToken from horizon_signin_email or horizon_signin_anonymous for this userId; sent as a Bearer session");
11
+ /** Load response header with the save's revision (0 = empty slot, 1 = first save). */
12
+ const REVISION_HEADER = "X-Cloud-Save-Revision";
13
+ /**
14
+ * Revision from the load header, or null when it is missing or not a number.
15
+ * Null means unknown (for example a self-hosted simpleServer), not an empty slot.
16
+ */
17
+ export function parseRevision(value) {
18
+ if (value === null || !/^\s*\d+\s*$/.test(value))
19
+ return null;
20
+ return Number(value.trim());
21
+ }
22
+ /** Tool result for HTTP 409: another device saved since expectedRevision. */
23
+ function conflictResponse(expectedRevision, body) {
24
+ return {
25
+ content: [
26
+ {
27
+ type: "text",
28
+ text: `Cloud save conflict (HTTP 409): the save is no longer at revision ${expectedRevision} because another device saved first. ` +
29
+ "Nothing was written. Call horizon_load_cloud_data for the current save and revision, decide or merge, " +
30
+ `then save again with that revision as expectedRevision. Server response: ${body}`,
31
+ },
32
+ ],
33
+ isError: true,
34
+ };
35
+ }
11
36
  export function registerCloudSaveTools(server) {
12
37
  // --- Save cloud data ---
13
38
  server.registerTool("horizon_save_cloud_data", {
14
39
  title: "Save Cloud Data",
15
40
  description: describeTool({
16
41
  summary: "Stores a player's save game as one string (usually JSON) on the server, replacing the player's previous save.",
17
- use: "the game saves progress so it survives reinstalls and can be loaded on another device.",
42
+ use: "the game saves progress so it survives reinstalls and can be loaded on another device. Pass expectedRevision (the revision from horizon_load_cloud_data or the last save) so a save from another device is never overwritten silently.",
18
43
  avoid: "reading the save (use horizon_load_cloud_data) or server-owned currency that players must not edit (use Validated Actions: horizon_submit_validated and horizon_get_state).",
19
44
  requires: SESSION_REQUIRED,
20
- effects: "overwrites the player's single save slot; the old save is gone. Saving the same data again changes nothing.",
21
- returns: "{success: true, dataSizeBytes}.",
22
- errors: "403 when the data exceeds the tier limit (defaults FREE 1 KB, BASIC 5 KB, PRO 20 KB, ENTERPRISE 250 KB): shrink the save or upgrade. " +
45
+ effects: "overwrites the player's single save slot; the old save is gone. With expectedRevision it only writes while the save is still at that revision. Saving the same data again changes nothing.",
46
+ returns: "{success: true, dataSizeBytes, revision}. revision is the new revision: pass it as expectedRevision to the next save.",
47
+ errors: "409 (only with expectedRevision) when another device saved first: nothing was written, load the current save and revision, decide, then save again. " +
48
+ "403 when the data exceeds the tier limit (defaults FREE 1 KB, BASIC 5 KB, PRO 20 KB, ENTERPRISE 250 KB): shrink the save or upgrade. " +
23
49
  SESSION_ERRORS,
24
50
  }),
25
51
  inputSchema: {
26
52
  userId: userIdSchema,
27
53
  data: z.string().max(300000).describe("The complete save as a string, usually serialized JSON (max 300,000 characters; the tier limit is usually lower)"),
28
54
  sessionToken: sessionTokenSchema,
55
+ expectedRevision: z
56
+ .number()
57
+ .int()
58
+ .min(0)
59
+ .optional()
60
+ .describe("Optional. Revision the save must still have, sent as If-Match: 0 for an empty slot, else the revision from horizon_load_cloud_data or the last save. Omit for an unconditional overwrite."),
29
61
  },
30
62
  annotations: DESTRUCTIVE_WRITE,
31
- }, async ({ userId, data, sessionToken }) => {
63
+ }, async ({ userId, data, sessionToken, expectedRevision }) => {
32
64
  const client = createApiClientFromEnv();
33
65
  if (!client)
34
66
  return noApiKeyResponse();
67
+ const headers = sessionHeaders(sessionToken);
68
+ if (expectedRevision !== undefined)
69
+ headers["If-Match"] = String(expectedRevision);
35
70
  try {
36
71
  const result = await client.post("/api/v1/app/cloud-save/save", {
37
72
  userId,
38
73
  saveData: data,
39
- }, sessionHeaders(sessionToken));
74
+ }, headers);
40
75
  return jsonResponse(result);
41
76
  }
42
77
  catch (error) {
78
+ if (expectedRevision !== undefined && error instanceof HorizonApiError && error.status === 409) {
79
+ return conflictResponse(expectedRevision, error.body);
80
+ }
43
81
  return errorResponse(error);
44
82
  }
45
83
  });
@@ -52,7 +90,9 @@ export function registerCloudSaveTools(server) {
52
90
  avoid: "writing (use horizon_save_cloud_data) or balances of server-owned values (use horizon_get_state).",
53
91
  requires: SESSION_REQUIRED,
54
92
  effects: "None (read only).",
55
- returns: "{found, saveData}. found false with saveData null means the player never saved: this is normal on first start, so initialize default data.",
93
+ returns: "{found, saveData, revision}. found false with saveData null means the player never saved: this is normal on first start, so initialize default data. " +
94
+ "revision is the save's server revision (0 = empty slot, 1 after the first save): pass it as expectedRevision to horizon_save_cloud_data. " +
95
+ "revision null means the server sent none (unknown state, for example a self-hosted simpleServer), not an empty slot.",
56
96
  errors: SESSION_ERRORS,
57
97
  }),
58
98
  inputSchema: {
@@ -66,10 +106,10 @@ export function registerCloudSaveTools(server) {
66
106
  if (!client)
67
107
  return noApiKeyResponse();
68
108
  try {
69
- const result = await client.post("/api/v1/app/cloud-save/load", {
109
+ const { data, headers } = await client.postWithHeaders("/api/v1/app/cloud-save/load", {
70
110
  userId,
71
111
  }, sessionHeaders(sessionToken));
72
- return structuredResponse(result);
112
+ return structuredResponse({ ...data, revision: parseRevision(headers.get(REVISION_HEADER)) });
73
113
  }
74
114
  catch (error) {
75
115
  return errorResponse(error);
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-save.js","sourceRoot":"","sources":["../../src/tools/cloud-save.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,GACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,iEAAiE,CAAC,CAAC;AAEnH,MAAM,kBAAkB,GAAG,CAAC;KACzB,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,GAAG,CAAC;KACR,QAAQ,CAAC,6GAA6G,CAAC,CAAC;AAE3H,MAAM,UAAU,sBAAsB,CAAC,MAAiB;IACtD,0BAA0B;IAC1B,MAAM,CAAC,YAAY,CAAC,yBAAyB,EAAE;QAC7C,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,YAAY,CAAC;YACxB,OAAO,EAAE,+GAA+G;YACxH,GAAG,EAAE,wFAAwF;YAC7F,KAAK,EAAE,6KAA6K;YACpL,QAAQ,EAAE,gBAAgB;YAC1B,OAAO,EAAE,6GAA6G;YACtH,OAAO,EAAE,iCAAiC;YAC1C,MAAM,EACJ,uIAAuI;gBACvI,cAAc;SACjB,CAAC;QACF,WAAW,EAAE;YACX,MAAM,EAAE,YAAY;YACpB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,kHAAkH,CAAC;YACzJ,YAAY,EAAE,kBAAkB;SACjC;QACD,WAAW,EAAE,iBAAiB;KAC/B,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QAC1C,MAAM,MAAM,GAAG,sBAAsB,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM;YAAE,OAAO,gBAAgB,EAAE,CAAC;QAEvC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE;gBAC9D,MAAM;gBACN,QAAQ,EAAE,IAAI;aACf,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;YACjC,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,0BAA0B;IAC1B,MAAM,CAAC,YAAY,CAAC,yBAAyB,EAAE;QAC7C,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,YAAY,CAAC;YACxB,OAAO,EAAE,0EAA0E;YACnF,GAAG,EAAE,8EAA8E;YACnF,KAAK,EAAE,mGAAmG;YAC1G,QAAQ,EAAE,gBAAgB;YAC1B,OAAO,EAAE,mBAAmB;YAC5B,OAAO,EAAE,4IAA4I;YACrJ,MAAM,EAAE,cAAc;SACvB,CAAC;QACF,WAAW,EAAE;YACX,MAAM,EAAE,YAAY;YACpB,YAAY,EAAE,kBAAkB;SACjC;QACD,YAAY,EAAE,sBAAsB;QACpC,WAAW,EAAE,SAAS;KACvB,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE;QACpC,MAAM,MAAM,GAAG,sBAAsB,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM;YAAE,OAAO,gBAAgB,EAAE,CAAC;QAEvC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE;gBAC9D,MAAM;aACP,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;YACjC,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"cloud-save.js","sourceRoot":"","sources":["../../src/tools/cloud-save.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"output-schemas.d.ts","sourceRoot":"","sources":["../../src/tools/output-schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK;;kBAMzC;AAeD,eAAO,MAAM,sBAAsB;;iBAGjC,CAAC;AAEH,eAAO,MAAM,iBAAiB;;iBAK5B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;iBAcnC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;iBAErC,CAAC;AAEH,eAAO,MAAM,gBAAgB;;iBAK3B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;iBAGjC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;iBAI/B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;iBAGpC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;iBAK9B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;iBAInC,CAAC;AAEH,eAAO,MAAM,6BAA6B;;iBAGxC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;iBAEpC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;iBAkBhC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;iBAa9B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;iBAU9B,CAAC"}
1
+ {"version":3,"file":"output-schemas.d.ts","sourceRoot":"","sources":["../../src/tools/output-schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK;;kBAMzC;AAeD,eAAO,MAAM,sBAAsB;;iBAGjC,CAAC;AAEH,eAAO,MAAM,iBAAiB;;iBAK5B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;iBAcnC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;iBAErC,CAAC;AAEH,eAAO,MAAM,gBAAgB;;iBAK3B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;iBAIjC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;iBAI/B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;iBAGpC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;iBAK9B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;iBAInC,CAAC;AAEH,eAAO,MAAM,6BAA6B;;iBAGxC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;iBAEpC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;iBAkBhC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;iBAa9B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;iBAU9B,CAAC"}
@@ -66,6 +66,7 @@ export const USER_RANK_OUTPUT = lenientObject({
66
66
  export const LOAD_CLOUD_DATA_OUTPUT = lenientObject({
67
67
  found: z.boolean().describe("false when the player never saved"),
68
68
  saveData: z.string().describe("The stored save string, null when found is false"),
69
+ revision: z.number().describe("Server revision (0 = empty slot), to pass as expectedRevision when saving. Null when unknown"),
69
70
  });
70
71
  export const REMOTE_CONFIG_OUTPUT = lenientObject({
71
72
  configKey: z.string().describe("The requested key"),
@@ -1 +1 @@
1
- {"version":3,"file":"output-schemas.js","sourceRoot":"","sources":["../../src/tools/output-schemas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"output-schemas.js","sourceRoot":"","sources":["../../src/tools/output-schemas.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "horizon-mcp",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "MCP server for horizOn Backend-as-a-Service: documentation, live API tools, and workflow prompts for Godot, Unity, and Unreal Engine integration.",
5
5
  "mcpName": "io.github.ProjectMakersDE/horizon-mcp",
6
6
  "type": "module",
@@ -323,6 +323,8 @@ Get entries around a user's rank.
323
323
 
324
324
  Save data to the cloud (JSON mode). Replaces the previous save. Requires `Authorization: Bearer <accessToken>` of the same user.
325
325
 
326
+ Optional header `If-Match: <revision>` (a plain number, not quoted): the save is only written while the stored save is still at that revision. Use `0` for an empty slot, otherwise the revision from load or from the last save. Without `If-Match` the save overwrites unconditionally.
327
+
326
328
  **Request:**
327
329
  ```json
328
330
  {
@@ -335,13 +337,14 @@ Save data to the cloud (JSON mode). Replaces the previous save. Requires `Author
335
337
  ```json
336
338
  {
337
339
  "success": true,
338
- "dataSizeBytes": "number"
340
+ "dataSizeBytes": "number",
341
+ "revision": "number (new revision, 1 after the first save)"
339
342
  }
340
343
  ```
341
344
 
342
- **Binary mode:** `POST /api/v1/app/cloud-save/save?userId={userId}` with `Content-Type: application/octet-stream`.
345
+ **Binary mode:** `POST /api/v1/app/cloud-save/save?userId={userId}` with `Content-Type: application/octet-stream`. `If-Match` and the response are the same as in JSON mode.
343
346
 
344
- **Status Codes:** `200` success, `403` exceeds tier size limit.
347
+ **Status Codes:** `200` success, `403` exceeds tier size limit, `409` the save changed since the `If-Match` revision (another device saved first: nothing was written, load again and decide).
345
348
 
346
349
  **Tier limits (defaults):** FREE=1KB, BASIC=5KB, PRO=20KB, ENTERPRISE=250KB.
347
350
 
@@ -366,7 +369,9 @@ Load data from the cloud (JSON mode). Requires `Authorization: Bearer <accessTok
366
369
  }
367
370
  ```
368
371
 
369
- **Binary mode:** `GET /api/v1/app/cloud-save/load?userId={userId}` with `Accept: application/octet-stream`.
372
+ **Response header:** `X-Cloud-Save-Revision: <revision>`, `0` for an empty slot. Send it back as `If-Match` on the next save. A missing header means the revision is unknown (for example a self-hosted simpleServer), not an empty slot. Browsers can read it: CORS exposes it for `/api/v1/app/**`.
373
+
374
+ **Binary mode:** `POST /api/v1/app/cloud-save/load` with `Content-Type: application/json`, `Accept: application/octet-stream` and the same JSON body. The response is raw bytes (`200`) or an empty body (`204`) when no save exists, both with `X-Cloud-Save-Revision`.
370
375
 
371
376
  ---
372
377
 
@@ -31,7 +31,8 @@ The MCP tools require this token in their `sessionToken` input.
31
31
 
32
32
  **`POST /api/v1/app/cloud-save/save`**
33
33
 
34
- Saves user data to the cloud. Overwrites any existing save.
34
+ Saves user data to the cloud. Overwrites any existing save, unless the request sends
35
+ `If-Match: <revision>` (see [Saving From Several Devices](#saving-from-several-devices)).
35
36
 
36
37
  **Request Body (JSON mode):**
37
38
 
@@ -45,10 +46,13 @@ Saves user data to the cloud. Overwrites any existing save.
45
46
  ```json
46
47
  {
47
48
  "success": true,
48
- "dataSizeBytes": 256
49
+ "dataSizeBytes": 256,
50
+ "revision": 4
49
51
  }
50
52
  ```
51
53
 
54
+ `revision` is the new revision of the save (1 after the first save).
55
+
52
56
  **Binary mode:** `POST /api/v1/app/cloud-save/save?userId={userId}` with `Content-Type: application/octet-stream` and raw bytes in the body.
53
57
 
54
58
  ---
@@ -83,9 +87,32 @@ If no save data exists:
83
87
  }
84
88
  ```
85
89
 
90
+ Every load response carries the header `X-Cloud-Save-Revision`: the save's revision, `0`
91
+ for an empty slot.
92
+
86
93
  **Binary mode:** `POST /api/v1/app/cloud-save/load` with `Content-Type: application/json`,
87
94
  `Accept: application/octet-stream` and JSON body `{"userId":"<player-uuid>"}`.
88
- The response is raw bytes (`200`) or an empty body (`204`) when no save exists.
95
+ The response is raw bytes (`200`) or an empty body (`204`) when no save exists, both with
96
+ `X-Cloud-Save-Revision`.
97
+
98
+ ## Saving From Several Devices
99
+
100
+ A plain save overwrites whatever is stored, so two devices of the same player overwrite each
101
+ other silently. The revision prevents that:
102
+
103
+ 1. **Load** and keep the revision: `X-Cloud-Save-Revision` (REST), `revision` of
104
+ `horizon_load_cloud_data` (MCP), `Revision` of `LoadSnapshot()` / `LoadBytesSnapshot()`
105
+ (Unity). `0` means the slot is empty.
106
+ 2. **Save with that revision**: header `If-Match: <revision>` (a plain number), `expectedRevision`
107
+ of `horizon_save_cloud_data`, or `Save(data, revision)` / `SaveBytes(data, revision)` in
108
+ Unity. Keep the new `revision` from the response for the next save.
109
+ 3. **On `409`** another device saved first. Nothing was written. Load again, merge or let the
110
+ player choose, then save with the new revision. Never retry the old data blindly.
111
+
112
+ A load without the revision header (for example on a self-hosted simpleServer) leaves the
113
+ revision unknown. Treat that as unknown, not as an empty slot: the server cannot detect
114
+ conflicts then. The Godot and Unreal SDKs do not send the revision yet: their saves overwrite
115
+ unconditionally.
89
116
 
90
117
  ## Code Examples
91
118
 
@@ -153,6 +180,17 @@ string json = await CloudSaveManager.Instance.Load();
153
180
  byte[] data = GetBinaryData();
154
181
  await CloudSaveManager.Instance.SaveBytes(data);
155
182
  byte[] loadedBytes = await CloudSaveManager.Instance.LoadBytes();
183
+
184
+ // Several devices: load with revision, save only if nothing changed meanwhile
185
+ var snapshot = await CloudSaveManager.Instance.LoadSnapshot();
186
+ if (snapshot.IsSuccess && snapshot.HasRevision)
187
+ {
188
+ var result = await CloudSaveManager.Instance.Save("{\"level\": 6}", snapshot.Revision.Value);
189
+ if (result.IsConflict)
190
+ {
191
+ // Another device saved first: load again and decide, nothing was written
192
+ }
193
+ }
156
194
  ```
157
195
 
158
196
  ### REST (cURL)
@@ -165,12 +203,20 @@ curl -X POST https://horizon.pm/api/v1/app/cloud-save/save \
165
203
  -H "Content-Type: application/json" \
166
204
  -d '{"userId": "user123", "saveData": "{\"level\":5,\"coins\":1000}"}'
167
205
 
168
- # Load data (JSON mode)
169
- curl -X POST https://horizon.pm/api/v1/app/cloud-save/load \
206
+ # Load data (JSON mode), -i shows the X-Cloud-Save-Revision header
207
+ curl -i -X POST https://horizon.pm/api/v1/app/cloud-save/load \
170
208
  -H "X-API-Key: YOUR_API_KEY" \
171
209
  -H "Authorization: Bearer ACCESS_TOKEN_FROM_SIGNIN" \
172
210
  -H "Content-Type: application/json" \
173
211
  -d '{"userId": "user123"}'
212
+
213
+ # Save only if the save is still at revision 3 (409 otherwise)
214
+ curl -X POST https://horizon.pm/api/v1/app/cloud-save/save \
215
+ -H "X-API-Key: YOUR_API_KEY" \
216
+ -H "Authorization: Bearer ACCESS_TOKEN_FROM_SIGNIN" \
217
+ -H "Content-Type: application/json" \
218
+ -H "If-Match: 3" \
219
+ -d '{"userId": "user123", "saveData": "{\"level\":6}"}'
174
220
  ```
175
221
 
176
222
  ## Best Practices
@@ -187,4 +233,5 @@ curl -X POST https://horizon.pm/api/v1/app/cloud-save/load \
187
233
  | 401 | Invalid API key | Check `X-API-Key` header |
188
234
  | 401 | Missing, invalid or expired player session | Sign in again and send the Bearer session |
189
235
  | 403 | Save exceeds tier limit | Reduce data size or upgrade tier |
236
+ | 409 | Save changed since the `If-Match` revision | Load again, decide, save with the new revision |
190
237
  | 429 | Rate limit exceeded | Batch saves, save less frequently |