@m8tes/sdk 0.1.0-alpha.2 → 0.1.0-alpha.3

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/CHANGELOG.md CHANGED
@@ -5,7 +5,9 @@ All notable changes to `@m8tes/sdk`.
5
5
  > **Release process** (mirrors `sdk/py`): every change to behaviour or public API
6
6
  > lands an entry under `## [Unreleased]` in the same commit. A RELEASE then bumps
7
7
  > `package.json` `version` (semver) and retitles that section. Entries are never
8
- > skipped — without one, a consumer cannot tell what changed. Publish via the `Publish @m8tes/sdk` workflow — never `npm publish` by
8
+ > skipped — without one, a consumer cannot tell what changed. A version bump
9
+ > merged to main publishes automatically (`Publish npm packages`); dry-run stays
10
+ > on the package-specific workflow. Never `npm publish` by
9
11
  > hand (it does not rewrite the pnpm `workspace:` protocol).
10
12
  >
11
13
  > While the version is a `-alpha.N` prerelease, publish with dist-tag `alpha`.
@@ -13,8 +15,34 @@ All notable changes to `@m8tes/sdk`.
13
15
 
14
16
  ## [Unreleased]
15
17
 
18
+ ## [0.1.0-alpha.3] — 2026-08-19
19
+
20
+ ### Changed
21
+
22
+ - **`runs.get` / `poll` / `wait` / `createAndWait` forward `user_id`.** Strict
23
+ multi-tenant mode requires `?user_id=` on every by-ID GET; `createAndWait`
24
+ reuses the create body's `user_id`, then falls back to the created run's
25
+ stamped `user_id` (agent-inherited scope). A wait-only `options.user_id` is
26
+ folded into the create body when params omit it; conflicting scopes are
27
+ rejected before POST. After create, poll prefers the API-stamped owner when
28
+ it differs from the request scope.
29
+ - **`runs.cancel(id, { user_id })`** — same end-user scope as get (strict mode).
30
+ - **`ApproveParams.remember` docs match persistence.** `remember: true` on allow
31
+ stores a cross-run always-allow policy (not run-only); deny+remember stays
32
+ run-scoped.
33
+
16
34
  ### Added
17
35
 
36
+ - **`Usage.unlimited_runs`.** Mirrors `GET /api/v2/usage` so clients can tell a
37
+ bypassed meter from a soft over-limit.
38
+ - **`Page.nextStartingAfter` / list envelope `next_starting_after`.** Cursor for the
39
+ next `starting_after` page when `hasMore` is true.
40
+ - **`PermissionRequest.can_remember` / `remember_default` and
41
+ `PermissionPolicy.source`.** `remember_default: false` tells a client the
42
+ Always-allow control must start unticked (force-ask floor: spend, access,
43
+ destroy); `source` names the surface that minted a standing grant
44
+ (`"run_approval"` / `"api"`; null on legacy rows).
45
+
18
46
  - **`user_id` end-user scoping on agent and task sub-resource methods.**
19
47
  `agents.enableWebhook` / `disableWebhook` / `enableEmailInbox` /
20
48
  `disableEmailInbox`, `tasks.enableWebhook` / `disableWebhook`, and the full
package/dist/index.cjs CHANGED
@@ -1298,12 +1298,14 @@ function createHttp(options = {}) {
1298
1298
  var Page = class {
1299
1299
  data;
1300
1300
  hasMore;
1301
+ nextStartingAfter;
1301
1302
  /** Fetches the next page given a cursor. Absent on a terminal page. */
1302
1303
  fetchNext;
1303
- constructor(data, hasMore, fetchNext) {
1304
+ constructor(data, hasMore, fetchNext, nextStartingAfter) {
1304
1305
  this.data = data;
1305
1306
  this.hasMore = hasMore;
1306
1307
  this.fetchNext = fetchNext;
1308
+ this.nextStartingAfter = nextStartingAfter ?? null;
1307
1309
  }
1308
1310
  /**
1309
1311
  * Auto-paging: yields every item across every page.
@@ -1321,7 +1323,10 @@ var Page = class {
1321
1323
  yield* page.data;
1322
1324
  const last = page.data.at(-1);
1323
1325
  if (!page.hasMore || !last || !page.fetchNext) return;
1324
- const cursor = typeof last.id === "number" || typeof last.id === "string" ? last.id : typeof last.name === "string" ? last.name : void 0;
1326
+ let cursor = page.nextStartingAfter === null || page.nextStartingAfter === void 0 ? void 0 : page.nextStartingAfter;
1327
+ if (cursor === void 0) {
1328
+ cursor = typeof last.id === "number" || typeof last.id === "string" ? last.id : typeof last.name === "string" ? last.name : void 0;
1329
+ }
1325
1330
  if (cursor === void 0 || seen.has(cursor)) return;
1326
1331
  seen.add(cursor);
1327
1332
  page = await page.fetchNext(cursor);
@@ -1373,7 +1378,8 @@ function createAgentsResource(http) {
1373
1378
  return new Page(
1374
1379
  res?.data ?? [],
1375
1380
  res?.has_more ?? false,
1376
- (starting_after) => fetchPage({ ...p, starting_after })
1381
+ (starting_after) => fetchPage({ ...p, starting_after }),
1382
+ res?.next_starting_after
1377
1383
  );
1378
1384
  };
1379
1385
  return fetchPage({ ...params });
@@ -1418,7 +1424,7 @@ function createAppsResource(http) {
1418
1424
  const res = await http.request("GET", "/apps/", {
1419
1425
  query: toQuery({ user_id: params.user_id })
1420
1426
  });
1421
- return new Page(res?.data ?? [], res?.has_more ?? false);
1427
+ return new Page(res?.data ?? [], res?.has_more ?? false, void 0, res?.next_starting_after);
1422
1428
  };
1423
1429
  return {
1424
1430
  list,
@@ -1468,7 +1474,8 @@ function pager(http, path) {
1468
1474
  return new Page(
1469
1475
  res?.data ?? [],
1470
1476
  res?.has_more ?? false,
1471
- (starting_after) => fetchPage({ ...p, starting_after })
1477
+ (starting_after) => fetchPage({ ...p, starting_after }),
1478
+ res?.next_starting_after
1472
1479
  );
1473
1480
  };
1474
1481
  return fetchPage;
@@ -1570,7 +1577,7 @@ function createModelsResource(http) {
1570
1577
  return {
1571
1578
  async list() {
1572
1579
  const res = await http.request("GET", "/models/");
1573
- return new Page(res?.data ?? [], res?.has_more ?? false);
1580
+ return new Page(res?.data ?? [], res?.has_more ?? false, void 0, res?.next_starting_after);
1574
1581
  }
1575
1582
  };
1576
1583
  }
@@ -2038,12 +2045,15 @@ function createRunsResource(http) {
2038
2045
  return form;
2039
2046
  };
2040
2047
  const hasFiles = (p) => (p.files?.length ?? 0) > 0;
2041
- const deps = {
2042
- get: (runId, signal) => http.request("GET", `/runs/${seg(runId)}`, { signal }),
2048
+ const pollDeps = (userId) => ({
2049
+ get: (runId, signal) => http.request("GET", `/runs/${seg(runId)}`, {
2050
+ query: toQuery({ user_id: userId }),
2051
+ signal
2052
+ }),
2043
2053
  permissions: async (runId, signal) => items(await http.request("GET", `/runs/${seg(runId)}/permissions`, { signal })),
2044
2054
  approve: (runId, params, signal) => http.request("POST", `/runs/${seg(runId)}/approve`, { body: { remember: false, ...params }, signal }),
2045
2055
  answer: (runId, params, signal) => http.request("POST", `/runs/${seg(runId)}/answer`, { body: params, signal })
2046
- };
2056
+ });
2047
2057
  const createAsync = async (params) => {
2048
2058
  const headers = idempotencyHeaders(params.idempotencyKey);
2049
2059
  return hasFiles(params) ? http.request("POST", "/runs/with-files", { form: createForm(params, false), headers }) : http.request("POST", "/runs", { body: createBody(params, false), headers });
@@ -2061,18 +2071,26 @@ function createRunsResource(http) {
2061
2071
  createAsync,
2062
2072
  async createAndWait(params, options = {}) {
2063
2073
  if (options.signal?.aborted) throw new RunWaitAbortedError();
2064
- const started = await createAsync(params);
2074
+ if (options.user_id != null && params.user_id != null && options.user_id !== params.user_id) {
2075
+ throw new ValidationError(
2076
+ `createAndWait: options.user_id (${JSON.stringify(options.user_id)}) conflicts with params.user_id (${JSON.stringify(params.user_id)}). Use one scope for create and poll.`,
2077
+ { type: "invalid_request_error", code: 0, status: 0 }
2078
+ );
2079
+ }
2080
+ const createParams = params.user_id == null && options.user_id != null ? { ...params, user_id: options.user_id } : params;
2081
+ const started = await createAsync(createParams);
2082
+ const userId = started.user_id ?? createParams.user_id ?? void 0;
2065
2083
  try {
2066
- return await waitForRun(deps, started.id, options);
2084
+ return await waitForRun(pollDeps(userId), started.id, { ...options, user_id: userId });
2067
2085
  } catch (err) {
2068
2086
  throw withRunId(err, started.id);
2069
2087
  }
2070
2088
  },
2071
- poll(runId, options) {
2072
- return pollRun(deps, runId, options);
2089
+ poll(runId, options = {}) {
2090
+ return pollRun(pollDeps(options.user_id), runId, options);
2073
2091
  },
2074
- wait(runId, options) {
2075
- return waitForRun(deps, runId, options);
2092
+ wait(runId, options = {}) {
2093
+ return waitForRun(pollDeps(options.user_id), runId, options);
2076
2094
  },
2077
2095
  // `confirm` is a QUERY param and the route takes no body (verified against
2078
2096
  // fastapi/app/routers/v2/runs.py::retry_run), so send neither.
@@ -2094,8 +2112,10 @@ function createRunsResource(http) {
2094
2112
  options
2095
2113
  );
2096
2114
  },
2097
- get(runId) {
2098
- return http.request("GET", `/runs/${seg(runId)}`);
2115
+ get(runId, params = {}) {
2116
+ return http.request("GET", `/runs/${seg(runId)}`, {
2117
+ query: toQuery({ user_id: params.user_id })
2118
+ });
2099
2119
  },
2100
2120
  async list(params = {}) {
2101
2121
  const { agent_id, teammate_id, ...rest } = params;
@@ -2107,13 +2127,16 @@ function createRunsResource(http) {
2107
2127
  return new Page(
2108
2128
  res?.data ?? [],
2109
2129
  res?.has_more ?? false,
2110
- (starting_after) => fetchPage({ ...p, starting_after })
2130
+ (starting_after) => fetchPage({ ...p, starting_after }),
2131
+ res?.next_starting_after
2111
2132
  );
2112
2133
  };
2113
2134
  return fetchPage(q);
2114
2135
  },
2115
- cancel(runId) {
2116
- return http.request("POST", `/runs/${seg(runId)}/cancel`, { body: {} });
2136
+ cancel(runId, params = {}) {
2137
+ return http.request("POST", `/runs/${seg(runId)}/cancel`, {
2138
+ query: toQuery({ user_id: params.user_id })
2139
+ });
2117
2140
  },
2118
2141
  approve(runId, params) {
2119
2142
  return http.request("POST", `/runs/${seg(runId)}/approve`, {
@@ -2204,7 +2227,8 @@ function createTasksResource(http) {
2204
2227
  return new Page(
2205
2228
  res?.data ?? [],
2206
2229
  res?.has_more ?? false,
2207
- (starting_after) => fetchPage({ ...p, starting_after })
2230
+ (starting_after) => fetchPage({ ...p, starting_after }),
2231
+ res?.next_starting_after
2208
2232
  );
2209
2233
  };
2210
2234
  return fetchPage(q);
@@ -2307,7 +2331,7 @@ function createWebhooksResource(http) {
2307
2331
  }
2308
2332
 
2309
2333
  // src/index.ts
2310
- var M8TES_SDK_VERSION = "0.1.0-alpha.2";
2334
+ var M8TES_SDK_VERSION = "0.1.0-alpha.3";
2311
2335
  var M8tes = class {
2312
2336
  runs;
2313
2337
  agents;