speculos-toolkit 1.2.0 → 1.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "speculos-toolkit",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "The Speculos toolkit for coding agents \u2014 deploy any frontend/backend to a live URL and build against your linked data connectors (BigQuery, Postgres, Snowflake, Salesforce, \u2026). Built for Claude Code, Codex, Cursor, and friends.",
5
5
  "bin": {
6
6
  "speculos-toolkit": "bin/speculos-toolkit.js"
package/src/client.js CHANGED
@@ -16,8 +16,8 @@ async function post(url, body, token) {
16
16
  if (!res.ok) { const e = new Error(data.error || `HTTP ${res.status}`); e.code = data.code; e.status = res.status; throw e; }
17
17
  return data;
18
18
  }
19
- async function get(url, token) {
20
- const headers = {};
19
+ async function get(url, token, extra) {
20
+ const headers = Object.assign({}, extra || {});
21
21
  if (token) headers["Authorization"] = "Bearer " + token;
22
22
  const res = await fetch(url, { headers });
23
23
  const data = await res.json().catch(() => ({}));
@@ -38,14 +38,18 @@ async function whoami(token, opts = {}) { return get(base(opts) + "/api/account/
38
38
  async function linkMachine(token, payload, opts = {}) { return post(base(opts) + "/api/account/link", payload, token); }
39
39
  async function logout(token, opts = {}) { return post(base(opts) + "/api/account/logout", {}, token); }
40
40
  // poll a backend job (owner-authenticated)
41
+ // The machine credentials travel as headers, not a query string: a query
42
+ // string is written to every access log between here and the orchestrator.
41
43
  async function backendStatus(jobId, creds = {}, opts = {}) {
42
- const qs = new URLSearchParams({ userId: creds.userId || "", userKey: creds.userKey || "" });
43
- return get(base(opts) + "/api/backend/" + encodeURIComponent(jobId) + "?" + qs.toString());
44
+ return get(base(opts) + "/api/backend/" + encodeURIComponent(jobId), null,
45
+ { "x-speculos-user-id": creds.userId || "", "x-speculos-user-key": creds.userKey || "" });
44
46
  }
45
- // upload built/static frontend
46
- async function putFrontend(payload, opts = {}) { return post(base(opts) + "/api/frontend", payload); }
47
+ // upload built/static frontend. The account token rides along so the gateway
48
+ // can file the deploy under the person, not the machine; the orchestrator
49
+ // itself authorizes on the machine credentials in the body as before.
50
+ async function putFrontend(payload, opts = {}) { return post(base(opts) + "/api/frontend", payload, opts.token); }
47
51
  // remove a deployment
48
- async function teardown(payload, opts = {}) { return post(base(opts) + "/api/teardown", payload); }
52
+ async function teardown(payload, opts = {}) { return post(base(opts) + "/api/teardown", payload, opts.token); }
49
53
  // ---- connectors (data sources linked in the dashboard) ----
50
54
  async function connectorsList(token, opts = {}) {
51
55
  return get(base(opts) + "/api/connectors" + (opts.noTools ? "?tools=0" : ""), token);
package/src/index.js CHANGED
@@ -335,6 +335,7 @@ async function cmdTeardown(root, opts) {
335
335
  if (!slug) { emit({ ok: false, error: "--slug required (or run from the project dir with a .speculos.json)" }); return 2; }
336
336
  if (!identity || !identity.userId) { emit({ ok: false, error: "no identity found (~/.speculos/identity.json) — nothing to tear down from this machine" }); return 1; }
337
337
  try {
338
+ if (identity.accountToken) opts.token = identity.accountToken;
338
339
  const r = await client.teardown({ userId: identity.userId, userKey: identity.userKey, slug }, opts);
339
340
  if (saved && saved.slug === slug) creds.remove(root);
340
341
  emit({ ok: true, ...r });