@mantyx/sdk 0.10.0 → 0.11.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/dist/index.cjs CHANGED
@@ -48,7 +48,6 @@ __export(index_exports, {
48
48
  defineLocalA2A: () => defineLocalA2A,
49
49
  defineLocalMcp: () => defineLocalMcp,
50
50
  defineLocalTool: () => defineLocalTool,
51
- generatePkceVerifier: () => generatePkceVerifier,
52
51
  isLocalA2ATool: () => isLocalA2ATool,
53
52
  isLocalMcpServer: () => isLocalMcpServer,
54
53
  isLocalTool: () => isLocalTool,
@@ -57,7 +56,6 @@ __export(index_exports, {
57
56
  mantyxPluginTool: () => mantyxPluginTool,
58
57
  mantyxTool: () => mantyxTool,
59
58
  parseRunOutput: () => parseRunOutput,
60
- pkceChallenge: () => pkceChallenge,
61
59
  readSseStream: () => readSseStream,
62
60
  toToolParametersWire: () => toToolParametersWire,
63
61
  zodToJsonSchema: () => zodToJsonSchema
@@ -125,6 +123,12 @@ var MantyxRunError = class extends MantyxError {
125
123
  partialText;
126
124
  /** See {@link MantyxRunErrorInit.retryable}. */
127
125
  retryable;
126
+ /** See {@link MantyxRunErrorInit.tokens}. */
127
+ tokens;
128
+ /** See {@link MantyxRunErrorInit.turns}. */
129
+ turns;
130
+ /** See {@link MantyxRunErrorInit.model}. */
131
+ model;
128
132
  constructor(runId, subtype, message, init = {}) {
129
133
  super(message, { code: subtype });
130
134
  this.name = "MantyxRunError";
@@ -134,6 +138,9 @@ var MantyxRunError = class extends MantyxError {
134
138
  this.finishReason = init.finishReason;
135
139
  this.partialText = init.partialText;
136
140
  this.retryable = init.retryable;
141
+ this.tokens = init.tokens;
142
+ this.turns = init.turns;
143
+ this.model = init.model;
137
144
  }
138
145
  };
139
146
  var MantyxParseError = class extends MantyxError {
@@ -773,6 +780,9 @@ var MantyxClient = class {
773
780
  async driveRun(runId, handlers, opts = {}) {
774
781
  const collected = [];
775
782
  let finalText = "";
783
+ let tokens;
784
+ let turns;
785
+ let modelInfo;
776
786
  for await (const ev of this.streamRunEvents(runId, handlers, opts.signal)) {
777
787
  collected.push(ev);
778
788
  if (opts.onEvent) opts.onEvent(ev);
@@ -781,25 +791,42 @@ var MantyxClient = class {
781
791
  }
782
792
  if (ev.type === "result") {
783
793
  const r = ev;
794
+ tokens = parseRunTokens(r.tokens) ?? tokens;
795
+ turns = parseRunTurns(r.turns) ?? turns;
796
+ modelInfo = parseRunModel(r.model) ?? modelInfo;
784
797
  if (r.subtype === "success") {
785
798
  finalText = typeof r.text === "string" ? r.text : "";
786
799
  } else {
787
- throw new MantyxRunError(runId, r.subtype, r.error ?? r.subtype);
800
+ const errInit = {};
801
+ if (tokens !== void 0) errInit.tokens = tokens;
802
+ if (turns !== void 0) errInit.turns = turns;
803
+ if (modelInfo !== void 0) errInit.model = modelInfo;
804
+ throw new MantyxRunError(runId, r.subtype, r.error ?? r.subtype, errInit);
788
805
  }
789
806
  } else if (ev.type === "error") {
790
807
  const e = ev;
791
808
  const subtype = e.errorClass ?? e.code ?? "error";
792
- throw new MantyxRunError(runId, subtype, e.error, {
793
- ...e.errorClass !== void 0 ? { errorClass: e.errorClass } : {},
794
- ...e.finishReason !== void 0 ? { finishReason: e.finishReason } : {},
795
- ...typeof e.partialText === "string" ? { partialText: e.partialText } : {},
796
- ...typeof e.retryable === "boolean" ? { retryable: e.retryable } : {}
797
- });
809
+ const errInit = {};
810
+ if (e.errorClass !== void 0) errInit.errorClass = e.errorClass;
811
+ if (e.finishReason !== void 0) errInit.finishReason = e.finishReason;
812
+ if (typeof e.partialText === "string") errInit.partialText = e.partialText;
813
+ if (typeof e.retryable === "boolean") errInit.retryable = e.retryable;
814
+ const errTokens = parseRunTokens(e.tokens);
815
+ if (errTokens !== void 0) errInit.tokens = errTokens;
816
+ const errTurns = parseRunTurns(e.turns);
817
+ if (errTurns !== void 0) errInit.turns = errTurns;
818
+ const errModel = parseRunModel(e.model);
819
+ if (errModel !== void 0) errInit.model = errModel;
820
+ throw new MantyxRunError(runId, subtype, e.error, errInit);
798
821
  } else if (ev.type === "cancelled") {
799
822
  throw new MantyxRunError(runId, "cancelled", "Run was cancelled");
800
823
  }
801
824
  }
802
- return { runId, text: finalText, events: collected };
825
+ const result = { runId, text: finalText, events: collected };
826
+ if (tokens !== void 0) result.tokens = tokens;
827
+ if (turns !== void 0) result.turns = turns;
828
+ if (modelInfo !== void 0) result.model = modelInfo;
829
+ return result;
803
830
  }
804
831
  async *streamRunEvents(runId, handlers, signal) {
805
832
  const url = this.absoluteUrl(`/agent-runs/${encodeURIComponent(runId)}/stream`);
@@ -1386,6 +1413,37 @@ function parseRunOutput(result, validator) {
1386
1413
  function sleep(ms) {
1387
1414
  return new Promise((r) => setTimeout(r, ms));
1388
1415
  }
1416
+ function parseRunTokens(value) {
1417
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
1418
+ const v = value;
1419
+ return {
1420
+ inputTokens: toNonNegativeInt(v.inputTokens),
1421
+ cachedTokens: toNonNegativeInt(v.cachedTokens),
1422
+ reasoningTokens: toNonNegativeInt(v.reasoningTokens),
1423
+ outputTokens: toNonNegativeInt(v.outputTokens)
1424
+ };
1425
+ }
1426
+ function parseRunTurns(value) {
1427
+ if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
1428
+ return Math.max(0, Math.trunc(value));
1429
+ }
1430
+ function parseRunModel(value) {
1431
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
1432
+ const v = value;
1433
+ const out = {
1434
+ id: typeof v.id === "string" ? v.id : "",
1435
+ provider: typeof v.provider === "string" ? v.provider : "",
1436
+ vendorModelId: typeof v.vendorModelId === "string" ? v.vendorModelId : ""
1437
+ };
1438
+ if (typeof v.reasoningEffort === "string" && v.reasoningEffort.length > 0) {
1439
+ out.reasoningEffort = v.reasoningEffort;
1440
+ }
1441
+ return out;
1442
+ }
1443
+ function toNonNegativeInt(value) {
1444
+ if (typeof value !== "number" || !Number.isFinite(value)) return 0;
1445
+ return Math.max(0, Math.trunc(value));
1446
+ }
1389
1447
  function resolveCredential(opts) {
1390
1448
  const apiKey = typeof opts.apiKey === "string" ? opts.apiKey : "";
1391
1449
  const accessToken = typeof opts.accessToken === "string" ? opts.accessToken : "";
@@ -1423,8 +1481,6 @@ function parseRequiredScopes(bodyRequired, wwwAuthenticate) {
1423
1481
  }
1424
1482
 
1425
1483
  // src/oauth.ts
1426
- var import_node_buffer = require("buffer");
1427
- var import_node_crypto = require("crypto");
1428
1484
  var DEFAULT_OAUTH_BASE_URL = "https://app.mantyx.io";
1429
1485
  var DEFAULT_REFRESH_SKEW_MS = 6e4;
1430
1486
  var MantyxOAuthError = class extends MantyxError {
@@ -1463,26 +1519,11 @@ var MantyxOAuthClient = class {
1463
1519
  this.fetchImpl = f;
1464
1520
  this.timeoutMs = opts.timeoutMs ?? 3e4;
1465
1521
  }
1466
- /**
1467
- * Swap an authorization-code + PKCE verifier for the initial
1468
- * `{access_token, refresh_token}` pair. Call this exactly once per
1469
- * sign-in after the browser/native redirect lands back on your
1470
- * `redirectUri` with a `code` parameter. Persist the returned
1471
- * `refreshToken` against the user record — it is long-lived and
1472
- * non-rotating per `docs/oauth.md` §"Token lifetimes & lifecycle".
1473
- */
1474
- async exchangeAuthorizationCode(opts) {
1475
- return this.token({
1476
- grant_type: "authorization_code",
1477
- code: opts.code,
1478
- redirect_uri: opts.redirectUri,
1479
- code_verifier: opts.codeVerifier
1480
- });
1481
- }
1482
1522
  /**
1483
1523
  * Mint a fresh access token from a stored refresh token. The
1484
- * returned `refreshToken` is identical to the input — the field is
1485
- * surfaced for symmetry with {@link exchangeAuthorizationCode} only.
1524
+ * returned `refreshToken` is identical to the input — refresh
1525
+ * tokens are persistent and non-rotating, so the field is
1526
+ * surfaced only for symmetry with the response shape.
1486
1527
  *
1487
1528
  * On `400 invalid_grant` the refresh token has been revoked (or its
1488
1529
  * grant / app was deleted); the SDK surfaces a
@@ -1500,21 +1541,6 @@ var MantyxOAuthClient = class {
1500
1541
  if (scope !== void 0) body.scope = scope;
1501
1542
  return this.token(body);
1502
1543
  }
1503
- /**
1504
- * Request a workspace-scoped access token without a user via the
1505
- * `client_credentials` grant. Available only on private OAuth apps
1506
- * that were registered with `allowsClientCredentials: true`. No
1507
- * refresh token is issued; re-call this method whenever a new
1508
- * access token is needed.
1509
- */
1510
- async clientCredentials(opts = {}) {
1511
- const body = {
1512
- grant_type: "client_credentials"
1513
- };
1514
- const scope = normalizeScope(opts.scope);
1515
- if (scope !== void 0) body.scope = scope;
1516
- return this.token(body);
1517
- }
1518
1544
  /**
1519
1545
  * Revoke an access or refresh token (RFC 7009). The server always
1520
1546
  * returns 200, even for unknown tokens. Revoking a **refresh**
@@ -1536,6 +1562,10 @@ var MantyxOAuthClient = class {
1536
1562
  * source caches the access token in-memory and refreshes
1537
1563
  * proactively when the cached value is within `refreshSkewMs` of
1538
1564
  * `expiresAt`, or eagerly when `MantyxClient` reports a 401.
1565
+ *
1566
+ * Pass `initialToken` if the calling app already has a non-expired
1567
+ * access token in hand (e.g. straight out of the sign-in flow) to
1568
+ * avoid an extra round-trip on the first request.
1539
1569
  */
1540
1570
  refreshTokenSource(opts) {
1541
1571
  if (!opts.refreshToken) {
@@ -1548,20 +1578,6 @@ var MantyxOAuthClient = class {
1548
1578
  return this.refresh({ refreshToken, scope: opts.scope });
1549
1579
  });
1550
1580
  }
1551
- /**
1552
- * Build a long-lived {@link TokenSource} backed by the
1553
- * `client_credentials` grant. On every refresh the source re-mints
1554
- * a workspace-scoped access token by calling the token endpoint
1555
- * with `grant_type=client_credentials`. Available only on private
1556
- * apps with `allowsClientCredentials: true`.
1557
- */
1558
- clientCredentialsTokenSource(opts = {}) {
1559
- const skew = opts.refreshSkewMs ?? DEFAULT_REFRESH_SKEW_MS;
1560
- const cache = { token: void 0, inflight: null };
1561
- return makeTokenSource(cache, skew, async () => {
1562
- return this.clientCredentials({ scope: opts.scope });
1563
- });
1564
- }
1565
1581
  // -------------------------------------------------------------- internals
1566
1582
  /**
1567
1583
  * POST `application/x-www-form-urlencoded` to `/api/oauth/token` and
@@ -1641,22 +1657,6 @@ var MantyxOAuthClient = class {
1641
1657
  return res;
1642
1658
  }
1643
1659
  };
1644
- function generatePkceVerifier(length = 64) {
1645
- if (length < 43 || length > 128) {
1646
- throw new MantyxError("PKCE code_verifier length must be in [43, 128]");
1647
- }
1648
- const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
1649
- const bytes = (0, import_node_crypto.randomBytes)(length);
1650
- let out = "";
1651
- for (let i = 0; i < length; i++) {
1652
- out += ALPHABET[bytes[i] % ALPHABET.length];
1653
- }
1654
- return out;
1655
- }
1656
- function pkceChallenge(verifier) {
1657
- const hash = (0, import_node_crypto.createHash)("sha256").update(verifier, "utf8").digest();
1658
- return import_node_buffer.Buffer.from(hash).toString("base64").replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
1659
- }
1660
1660
  function makeTokenSource(cache, skewMs, mint) {
1661
1661
  return async (reason = "initial") => {
1662
1662
  if (reason !== "unauthorized" && cache.token && !isExpiring(cache.token, skewMs)) {
@@ -1700,7 +1700,7 @@ function normalizeScope(scope) {
1700
1700
  }
1701
1701
 
1702
1702
  // src/version.ts
1703
- var SDK_VERSION = "0.10.0";
1703
+ var SDK_VERSION = "0.11.0";
1704
1704
  // Annotate the CommonJS export names for ESM import in node:
1705
1705
  0 && (module.exports = {
1706
1706
  AgentSession,
@@ -1721,7 +1721,6 @@ var SDK_VERSION = "0.10.0";
1721
1721
  defineLocalA2A,
1722
1722
  defineLocalMcp,
1723
1723
  defineLocalTool,
1724
- generatePkceVerifier,
1725
1724
  isLocalA2ATool,
1726
1725
  isLocalMcpServer,
1727
1726
  isLocalTool,
@@ -1730,7 +1729,6 @@ var SDK_VERSION = "0.10.0";
1730
1729
  mantyxPluginTool,
1731
1730
  mantyxTool,
1732
1731
  parseRunOutput,
1733
- pkceChallenge,
1734
1732
  readSseStream,
1735
1733
  toToolParametersWire,
1736
1734
  zodToJsonSchema