@carrierllc/mcp 0.8.0 → 0.9.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.js CHANGED
@@ -37,7 +37,7 @@ import {
37
37
  subscriberIdParams,
38
38
  usageOverPeriodParams,
39
39
  verifyStorefront
40
- } from "./chunk-JROD4YAU.js";
40
+ } from "./chunk-VACB3Z5V.js";
41
41
  import "./chunk-SHKKVIIA.js";
42
42
 
43
43
  // src/index.ts
@@ -69,11 +69,11 @@ var OcsClient = class {
69
69
  async call(method, params = {}) {
70
70
  await acquireEndpointSlot(this.token, method, "interactive");
71
71
  const url = `${this.baseUrl}/v1?token=${this.token}`;
72
- const body = JSON.stringify({ [method]: params });
72
+ const body2 = JSON.stringify({ [method]: params });
73
73
  const res = await fetch(url, {
74
74
  method: "POST",
75
75
  headers: { "Content-Type": "application/json" },
76
- body
76
+ body: body2
77
77
  });
78
78
  if (!res.ok) {
79
79
  throw new OcsApiError(res.status, `HTTP ${res.status} ${res.statusText}`, method);
@@ -109,6 +109,17 @@ function getBillingPrimary(env) {
109
109
  const raw = env.BILLING_PRIMARY;
110
110
  return raw === "clerk" ? "clerk" : "stripe";
111
111
  }
112
+ function platformOrgId(env) {
113
+ const raw = env.CARRIER_PLATFORM_ORG_ID;
114
+ if (typeof raw !== "string") return null;
115
+ const trimmed = raw.trim();
116
+ return trimmed.length > 0 ? trimmed : null;
117
+ }
118
+ function isPlatformOperator(env, orgId) {
119
+ const platform = platformOrgId(env);
120
+ if (!platform) return false;
121
+ return Boolean(orgId) && orgId === platform;
122
+ }
112
123
  async function checkCallQuota(env, sub, tier) {
113
124
  const limit = TIER_CALL_LIMITS[tier];
114
125
  const resetAt = firstDayNextMonth();
@@ -155,7 +166,7 @@ async function pushStripeUsageRecord(env, sub, quantity) {
155
166
  if (!env.CARRIER_USERS) return;
156
167
  const subItemId = await env.CARRIER_USERS.get(`stripe_sub_item_id:${sub}`);
157
168
  if (!subItemId) return;
158
- const body = new URLSearchParams({
169
+ const body2 = new URLSearchParams({
159
170
  quantity: String(quantity),
160
171
  timestamp: String(Math.floor(Date.now() / 1e3)),
161
172
  action: "increment"
@@ -168,7 +179,7 @@ async function pushStripeUsageRecord(env, sub, quantity) {
168
179
  Authorization: `Bearer ${stripeKey}`,
169
180
  "Content-Type": "application/x-www-form-urlencoded"
170
181
  },
171
- body: body.toString()
182
+ body: body2.toString()
172
183
  }
173
184
  );
174
185
  }
@@ -589,8 +600,8 @@ function wrapHandler(toolName, ocsMethod, requiredScope, ctx, handler) {
589
600
  };
590
601
  }
591
602
  async function ocsCall(env, token2, method, params = {}) {
592
- const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token2);
593
- const result2 = await client.call(method, params);
603
+ const client2 = new OcsClient(env.CARRIER_OCS_BASE_URL, token2);
604
+ const result2 = await client2.call(method, params);
594
605
  return {
595
606
  content: [{ type: "text", text: JSON.stringify(result2, null, 2) }]
596
607
  };
@@ -598,14 +609,14 @@ async function ocsCall(env, token2, method, params = {}) {
598
609
  async function resolveSubscriberByIccid(env, token2, iccid, cache) {
599
610
  const hit = cache.get(iccid);
600
611
  if (hit) return hit;
601
- const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token2);
602
- const record = await client.call("getSingleSubscriber", { iccid });
612
+ const client2 = new OcsClient(env.CARRIER_OCS_BASE_URL, token2);
613
+ const record = await client2.call("getSingleSubscriber", { iccid });
603
614
  cache.set(iccid, record);
604
615
  return record;
605
616
  }
606
617
  async function getDefaultResellerId(env, token2) {
607
- const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token2);
608
- const info = await client.call("getResellerInfo", {});
618
+ const client2 = new OcsClient(env.CARRIER_OCS_BASE_URL, token2);
619
+ const info = await client2.call("getResellerInfo", {});
609
620
  const id = info?.id;
610
621
  if (typeof id !== "number") {
611
622
  throw new Error("Could not determine resellerId from getResellerInfo");
@@ -809,8 +820,8 @@ function registerAllTools(server2, ctx) {
809
820
  ctx,
810
821
  async (args, token2) => {
811
822
  const params = buildListSubscriberParams(args);
812
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
813
- const raw = await client.call("listSubscriber", params);
823
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
824
+ const raw = await client2.call("listSubscriber", params);
814
825
  const payload = applySubscriberFilters(raw, args);
815
826
  return {
816
827
  content: [{ type: "text", text: JSON.stringify(payload, null, 2) }]
@@ -3286,8 +3297,8 @@ var ocsAppMethods = ocsSpec.v1_app_methods;
3286
3297
  // src/intelligence.ts
3287
3298
  async function safeCall(env, token2, method, params = {}) {
3288
3299
  try {
3289
- const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token2);
3290
- const data = await client.call(method, params);
3300
+ const client2 = new OcsClient(env.CARRIER_OCS_BASE_URL, token2);
3301
+ const data = await client2.call(method, params);
3291
3302
  return { data, error: null };
3292
3303
  } catch (err7) {
3293
3304
  return { data: null, error: err7 instanceof Error ? err7.message : String(err7) };
@@ -4304,8 +4315,8 @@ function registerAllBacklogTools(server2, ctx) {
4304
4315
  ctx,
4305
4316
  async ({ iccid, phone_number, phone_type }, token2) => {
4306
4317
  const ocsMethod = phone_type === "fake" ? "affectSubscriberFakePhoneNumber" : "affectSubscriberRealPhoneNumber";
4307
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4308
- const result2 = await client.call(ocsMethod, { subscriber: iccid, phoneNumber: phone_number });
4318
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4319
+ const result2 = await client2.call(ocsMethod, { subscriber: iccid, phoneNumber: phone_number });
4309
4320
  return {
4310
4321
  content: [{ type: "text", text: JSON.stringify(result2, null, 2) }]
4311
4322
  };
@@ -4342,11 +4353,11 @@ function registerAllBacklogTools(server2, ctx) {
4342
4353
  cell_id,
4343
4354
  signal_strength
4344
4355
  }, token2) => {
4345
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4356
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4346
4357
  const params = { radioType: radio_type, mcc, mnc, lac };
4347
4358
  if (cell_id !== void 0) params.cellId = cell_id;
4348
4359
  if (signal_strength !== void 0) params.signalStrength = signal_strength;
4349
- const result2 = await client.call("getSubscriberLocationByCellId", params);
4360
+ const result2 = await client2.call("getSubscriberLocationByCellId", params);
4350
4361
  return {
4351
4362
  content: [{ type: "text", text: JSON.stringify(result2, null, 2) }]
4352
4363
  };
@@ -4370,16 +4381,16 @@ function registerAllBacklogTools(server2, ctx) {
4370
4381
  ctx,
4371
4382
  async ({ resellerId }, token2) => {
4372
4383
  const id = resellerId ?? await (async () => {
4373
- const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4374
- const info = await client2.call("getResellerInfo", {});
4384
+ const client3 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4385
+ const info = await client3.call("getResellerInfo", {});
4375
4386
  const resolvedId = info?.id;
4376
4387
  if (typeof resolvedId !== "number") {
4377
4388
  throw new Error("Could not determine resellerId from getResellerInfo");
4378
4389
  }
4379
4390
  return resolvedId;
4380
4391
  })();
4381
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4382
- const result2 = await client.call("listDetailedDestinationList", id);
4392
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4393
+ const result2 = await client2.call("listDetailedDestinationList", id);
4383
4394
  return {
4384
4395
  content: [{ type: "text", text: JSON.stringify(result2, null, 2) }]
4385
4396
  };
@@ -4404,8 +4415,8 @@ function registerAllBacklogTools(server2, ctx) {
4404
4415
  BACKLOG_TOOL_SCOPES["modify_subscriber_mobile_plan"],
4405
4416
  ctx,
4406
4417
  async ({ iccid, mobile_plan_id }, token2) => {
4407
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4408
- const result2 = await client.call(
4418
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4419
+ const result2 = await client2.call(
4409
4420
  "modifySubscriberMobilePlan",
4410
4421
  { subscriber: iccid, mobilePlanId: mobile_plan_id }
4411
4422
  );
@@ -4438,8 +4449,8 @@ function registerAllBacklogTools(server2, ctx) {
4438
4449
  const params = { subscriber: iccid, packageId: package_id };
4439
4450
  if (start_date !== void 0) params.startDate = start_date;
4440
4451
  if (end_date !== void 0) params.endDate = end_date;
4441
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4442
- const result2 = await client.call(
4452
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4453
+ const result2 = await client2.call(
4443
4454
  "modifySubscriberPrepaidPackageActivePeriod",
4444
4455
  params
4445
4456
  );
@@ -4467,8 +4478,8 @@ function registerAllBacklogTools(server2, ctx) {
4467
4478
  BACKLOG_TOOL_SCOPES["modify_subscriber_voip_plan"],
4468
4479
  ctx,
4469
4480
  async ({ iccid, voip_plan_id }, token2) => {
4470
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4471
- const result2 = await client.call(
4481
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4482
+ const result2 = await client2.call(
4472
4483
  "modifySubscriberVoipPlan",
4473
4484
  { subscriber: iccid, voipPlanId: voip_plan_id }
4474
4485
  );
@@ -4498,8 +4509,8 @@ function registerAllBacklogTools(server2, ctx) {
4498
4509
  const cache = /* @__PURE__ */ new Map();
4499
4510
  const sub = await resolveSubscriberByIccid(ctx.env, token2, iccid, cache);
4500
4511
  const subscriberId = sub.id ?? sub.subscriberId ?? iccid;
4501
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4502
- const result2 = await client.call(
4512
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4513
+ const result2 = await client2.call(
4503
4514
  "pushSteeringToSubs",
4504
4515
  { subscriber: subscriberId }
4505
4516
  );
@@ -4526,8 +4537,8 @@ function registerAllBacklogTools(server2, ctx) {
4526
4537
  BACKLOG_TOOL_SCOPES["reset_subscriber_gz_counter"],
4527
4538
  ctx,
4528
4539
  async ({ iccid }, token2) => {
4529
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4530
- const result2 = await client.call("resetSubsGzCounter", { subscriber: iccid });
4540
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4541
+ const result2 = await client2.call("resetSubsGzCounter", { subscriber: iccid });
4531
4542
  return {
4532
4543
  content: [{ type: "text", text: JSON.stringify(result2, null, 2) }]
4533
4544
  };
@@ -4550,14 +4561,14 @@ function registerAllBacklogTools(server2, ctx) {
4550
4561
  BACKLOG_TOOL_SCOPES["carrier_webhook_config"],
4551
4562
  ctx,
4552
4563
  async ({ reseller_id }, token2) => {
4553
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4564
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4554
4565
  let resellerId = reseller_id;
4555
4566
  if (resellerId === void 0) {
4556
4567
  resellerId = await getDefaultResellerId(ctx.env, token2);
4557
4568
  }
4558
4569
  const params = {};
4559
4570
  if (resellerId !== void 0) params.id = resellerId;
4560
- const raw = await client.call("getResellerInfo", params);
4571
+ const raw = await client2.call("getResellerInfo", params);
4561
4572
  const traffic = raw.trafficInfo ?? {};
4562
4573
  const notification = raw.notificationInfo ?? {};
4563
4574
  const result2 = {
@@ -4592,12 +4603,12 @@ function registerAllBacklogTools(server2, ctx) {
4592
4603
  BACKLOG_TOOL_SCOPES["list_subscriber_voip_tariff"],
4593
4604
  ctx,
4594
4605
  async ({ reseller_id }, token2) => {
4595
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4606
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4596
4607
  const params = {};
4597
4608
  if (reseller_id !== void 0) {
4598
4609
  params.resellerId = reseller_id;
4599
4610
  }
4600
- const result2 = await client.call("listSubscriberVoipTariff", params);
4611
+ const result2 = await client2.call("listSubscriberVoipTariff", params);
4601
4612
  return {
4602
4613
  content: [{ type: "text", text: JSON.stringify(result2, null, 2) }]
4603
4614
  };
@@ -4622,8 +4633,8 @@ function registerAllBacklogTools(server2, ctx) {
4622
4633
  BACKLOG_TOOL_SCOPES["list_voip_tariff_rule"],
4623
4634
  ctx,
4624
4635
  async ({ voip_plan_id }, token2) => {
4625
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4626
- const result2 = await client.call("listVoipTariffRule", voip_plan_id);
4636
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4637
+ const result2 = await client2.call("listVoipTariffRule", voip_plan_id);
4627
4638
  return {
4628
4639
  content: [{ type: "text", text: JSON.stringify(result2, null, 2) }]
4629
4640
  };
@@ -4651,8 +4662,8 @@ function registerAllBacklogTools(server2, ctx) {
4651
4662
  location_zone_id,
4652
4663
  network_profile_id
4653
4664
  }, token2) => {
4654
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4655
- const result2 = await client.call("changeNetworkProfileOfLocationZone", {
4665
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
4666
+ const result2 = await client2.call("changeNetworkProfileOfLocationZone", {
4656
4667
  locationZoneId: location_zone_id,
4657
4668
  networkProfileId: network_profile_id
4658
4669
  });
@@ -4664,8 +4675,197 @@ function registerAllBacklogTools(server2, ctx) {
4664
4675
  );
4665
4676
  }
4666
4677
 
4667
- // src/tools-carrier-ask.ts
4678
+ // ../../packages/carrier-ai/dist/index.js
4668
4679
  import { AwsClient } from "aws4fetch";
4680
+ var AI_TIER_POLICY = {
4681
+ free: { limit: 5, window: "day" },
4682
+ pro: { limit: 1e3, window: "month" },
4683
+ enterprise: { limit: 1e4, window: "month" },
4684
+ // Finite, deliberately. This was `Infinity` when the tier was introduced in
4685
+ // #762, and Infinity breaks in two ways that both hide themselves:
4686
+ //
4687
+ // 1. JSON.stringify(Infinity) is "null". The quota endpoint returned
4688
+ // {"limit":null,"remaining":null} and the console badge rendered
4689
+ // "1 of null used". That is the whole reason this was investigated.
4690
+ // 2. An infinite allowance is unmetered Bedrock. A staff account could
4691
+ // spend without bound and nothing would refuse it or show a number.
4692
+ //
4693
+ // 100,000 is roughly $580 of Haiku at the measured $0.0058/call. Nobody on
4694
+ // staff will reach it by using the product, and a runaway loop stops.
4695
+ superadmin: { limit: 1e5, window: "month" }
4696
+ };
4697
+ for (const [tier, policy] of Object.entries(AI_TIER_POLICY)) {
4698
+ if (!Number.isFinite(policy.limit) || policy.limit <= 0) {
4699
+ throw new Error(
4700
+ `AI_TIER_POLICY.${tier}.limit must be a positive finite number, got ${policy.limit}. A non-finite limit serialises to null in JSON and leaves spend unmetered.`
4701
+ );
4702
+ }
4703
+ }
4704
+ var PRELUDE_BYTES = 12;
4705
+ var MESSAGE_CRC_BYTES = 4;
4706
+ var MIN_FRAME_BYTES = PRELUDE_BYTES + MESSAGE_CRC_BYTES;
4707
+ var MAX_FRAME_BYTES = 16 * 1024 * 1024;
4708
+ var MAX_ENTRIES = 16;
4709
+ var MAX_KEY_LEN = 256;
4710
+ var MAX_VALUE_LEN = 256;
4711
+ var ALLOWED = /[^a-zA-Z0-9\s:_@$#=/+,\-.]/g;
4712
+ function clean(value, max) {
4713
+ return value.replace(ALLOWED, "").slice(0, max);
4714
+ }
4715
+ var REQUEST_METADATA_HEADER = "X-Amzn-Bedrock-Request-Metadata";
4716
+ function requestMetadata(attr2) {
4717
+ const out = {};
4718
+ const pairs = [
4719
+ ["product", "carrier"],
4720
+ ["org", attr2.orgId],
4721
+ ["subaccount", attr2.subAccountId],
4722
+ ["surface", attr2.surface],
4723
+ ["tier", attr2.tier]
4724
+ ];
4725
+ for (const [k, v] of pairs) {
4726
+ if (v === void 0 || v === "") continue;
4727
+ const key = clean(k, MAX_KEY_LEN);
4728
+ const value = clean(v, MAX_VALUE_LEN);
4729
+ if (key && value && Object.keys(out).length < MAX_ENTRIES) out[key] = value;
4730
+ }
4731
+ return Object.keys(out).length > 0 ? out : null;
4732
+ }
4733
+ var ZERO_USAGE = {
4734
+ inputTokens: 0,
4735
+ outputTokens: 0,
4736
+ cacheReadTokens: 0,
4737
+ cacheWriteTokens: 0
4738
+ };
4739
+ function extractUsage(payload) {
4740
+ if (!payload || typeof payload !== "object") return ZERO_USAGE;
4741
+ const root = payload;
4742
+ const holder = root.usage ?? root.message?.usage;
4743
+ if (!holder) return ZERO_USAGE;
4744
+ const num = (v) => {
4745
+ const n = Number(v);
4746
+ return Number.isFinite(n) && n > 0 ? n : 0;
4747
+ };
4748
+ return {
4749
+ inputTokens: num(holder.input_tokens),
4750
+ outputTokens: num(holder.output_tokens),
4751
+ cacheReadTokens: num(holder.cache_read_input_tokens),
4752
+ cacheWriteTokens: num(holder.cache_creation_input_tokens)
4753
+ };
4754
+ }
4755
+ var HAIKU_RATES = {
4756
+ inputPerMTok: 1,
4757
+ outputPerMTok: 5,
4758
+ cacheReadPerMTok: 0.1,
4759
+ cacheWritePerMTok: 1.25,
4760
+ asOf: "2026-08-22"
4761
+ };
4762
+ function estimateCostUsd(u, rates = HAIKU_RATES) {
4763
+ const perTok = (mtok) => mtok / 1e6;
4764
+ return u.inputTokens * perTok(rates.inputPerMTok) + u.outputTokens * perTok(rates.outputPerMTok) + u.cacheReadTokens * perTok(rates.cacheReadPerMTok) + u.cacheWriteTokens * perTok(rates.cacheWritePerMTok);
4765
+ }
4766
+ var DEFAULT_BEDROCK_REGION = "us-east-1";
4767
+ var DEFAULT_MODEL_ID = "us.anthropic.claude-haiku-4-5-20251001-v1:0";
4768
+ var BEDROCK_TIMEOUT_MS = 3e4;
4769
+ var BedrockRateLimitError = class extends Error {
4770
+ isRateLimit = true;
4771
+ /**
4772
+ * The raw `retry-after` header, when Bedrock sent one. Callers surface it as
4773
+ * the delay they tell the user to wait; without it they have to guess.
4774
+ */
4775
+ retryAfter;
4776
+ constructor(message, retryAfter = null) {
4777
+ super(message);
4778
+ this.name = "BedrockRateLimitError";
4779
+ this.retryAfter = retryAfter;
4780
+ }
4781
+ };
4782
+ var BedrockError = class extends Error {
4783
+ constructor(message, status) {
4784
+ super(message);
4785
+ this.status = status;
4786
+ this.name = "BedrockError";
4787
+ }
4788
+ status;
4789
+ };
4790
+ function client(creds) {
4791
+ const region = creds.region ?? DEFAULT_BEDROCK_REGION;
4792
+ return {
4793
+ aws: new AwsClient({
4794
+ accessKeyId: creds.accessKeyId,
4795
+ secretAccessKey: creds.secretAccessKey,
4796
+ ...creds.sessionToken ? { sessionToken: creds.sessionToken } : {},
4797
+ region,
4798
+ service: "bedrock"
4799
+ }),
4800
+ region,
4801
+ modelId: creds.modelId ?? DEFAULT_MODEL_ID
4802
+ };
4803
+ }
4804
+ function body(req) {
4805
+ return {
4806
+ anthropic_version: "bedrock-2023-05-31",
4807
+ max_tokens: req.maxTokens,
4808
+ ...req.temperature !== void 0 ? { temperature: req.temperature } : {},
4809
+ system: [{ type: "text", text: req.system, cache_control: { type: "ephemeral" } }],
4810
+ messages: req.messages.map((m) => ({ role: m.role, content: m.content })),
4811
+ ...req.tools ? { tools: req.tools, tool_choice: { type: "any" } } : {}
4812
+ };
4813
+ }
4814
+ function headersFor(req, accept) {
4815
+ const headers = {
4816
+ "Content-Type": "application/json",
4817
+ Accept: accept
4818
+ };
4819
+ const meta = req.attribution ? requestMetadata(req.attribution) : null;
4820
+ if (meta) headers[REQUEST_METADATA_HEADER] = JSON.stringify(meta);
4821
+ return headers;
4822
+ }
4823
+ function reportUsage(req, usage) {
4824
+ if (!req.onUsage) return;
4825
+ try {
4826
+ req.onUsage(usage);
4827
+ } catch {
4828
+ }
4829
+ }
4830
+ async function fail(resp) {
4831
+ const text = await resp.text().catch(() => "");
4832
+ if (resp.status === 429 || /throttl/i.test(text)) {
4833
+ throw new BedrockRateLimitError(
4834
+ text || "Bedrock throttled the request",
4835
+ resp.headers.get("retry-after")
4836
+ );
4837
+ }
4838
+ throw new BedrockError(text || `Bedrock returned HTTP ${resp.status}`, resp.status);
4839
+ }
4840
+ async function invokeTool(creds, req, signal) {
4841
+ const { aws, region, modelId } = client(creds);
4842
+ const controller = new AbortController();
4843
+ const timer = setTimeout(() => controller.abort(), req.timeoutMs ?? BEDROCK_TIMEOUT_MS);
4844
+ const onAbort = () => controller.abort();
4845
+ signal?.addEventListener("abort", onAbort, { once: true });
4846
+ try {
4847
+ const headers = headersFor(req, "application/json");
4848
+ const resp = await aws.fetch(
4849
+ `https://bedrock-runtime.${region}.amazonaws.com/model/${encodeURIComponent(modelId)}/invoke`,
4850
+ {
4851
+ method: "POST",
4852
+ headers,
4853
+ body: JSON.stringify(body(req)),
4854
+ signal: controller.signal
4855
+ }
4856
+ );
4857
+ if (!resp.ok) await fail(resp);
4858
+ const json = await resp.json();
4859
+ reportUsage(req, extractUsage(json));
4860
+ const block = json.content?.find((b) => b.type === "tool_use");
4861
+ return block?.name ? { name: block.name, input: block.input ?? {} } : null;
4862
+ } finally {
4863
+ clearTimeout(timer);
4864
+ signal?.removeEventListener("abort", onAbort);
4865
+ }
4866
+ }
4867
+
4868
+ // src/tools-carrier-ask.ts
4669
4869
  import { z as z11 } from "zod";
4670
4870
 
4671
4871
  // src/tools-ui-agent.ts
@@ -4711,7 +4911,7 @@ var MANUS_API_BASE = "https://api.manus.ai/v2";
4711
4911
 
4712
4912
  // src/tools-ui-agent.ts
4713
4913
  async function createManusTask(apiKey, prompt, title, outputSchema) {
4714
- const body = {
4914
+ const body2 = {
4715
4915
  message: { content: prompt },
4716
4916
  agent_profile: "manus-1.6-lite",
4717
4917
  hide_in_task_list: true,
@@ -4719,7 +4919,7 @@ async function createManusTask(apiKey, prompt, title, outputSchema) {
4719
4919
  title
4720
4920
  };
4721
4921
  if (outputSchema) {
4722
- body.structured_output_schema = outputSchema;
4922
+ body2.structured_output_schema = outputSchema;
4723
4923
  }
4724
4924
  const res = await fetch(`${MANUS_API_BASE}/task.create`, {
4725
4925
  method: "POST",
@@ -4727,7 +4927,7 @@ async function createManusTask(apiKey, prompt, title, outputSchema) {
4727
4927
  "x-manus-api-key": apiKey,
4728
4928
  "Content-Type": "application/json"
4729
4929
  },
4730
- body: JSON.stringify(body)
4930
+ body: JSON.stringify(body2)
4731
4931
  });
4732
4932
  return await res.json();
4733
4933
  }
@@ -5252,14 +5452,14 @@ async function withFallback(fn, keys) {
5252
5452
  true
5253
5453
  );
5254
5454
  }
5255
- async function manusPost(path, apiKey, body) {
5455
+ async function manusPost(path, apiKey, body2) {
5256
5456
  const res = await fetch(`${MANUS_API_BASE2}/${path}`, {
5257
5457
  method: "POST",
5258
5458
  headers: {
5259
5459
  "x-manus-api-key": apiKey,
5260
5460
  "Content-Type": "application/json"
5261
5461
  },
5262
- body: JSON.stringify(body)
5462
+ body: JSON.stringify(body2)
5263
5463
  });
5264
5464
  const data = await res.json();
5265
5465
  return { _httpStatus: res.status, data, key_used: "primary" };
@@ -5269,14 +5469,14 @@ async function sendMessage(keys, taskId, content, opts) {
5269
5469
  if (opts?.connectors?.length) message.connectors = opts.connectors;
5270
5470
  if (opts?.enableSkills?.length) message.enable_skills = opts.enableSkills;
5271
5471
  if (opts?.forceSkills?.length) message.force_skills = opts.forceSkills;
5272
- const body = {
5472
+ const body2 = {
5273
5473
  task_id: taskId,
5274
5474
  message
5275
5475
  };
5276
- if (opts?.agentProfile) body.agent_profile = opts.agentProfile;
5277
- if (opts?.outputSchema) body.structured_output_schema = opts.outputSchema;
5476
+ if (opts?.agentProfile) body2.agent_profile = opts.agentProfile;
5477
+ if (opts?.outputSchema) body2.structured_output_schema = opts.outputSchema;
5278
5478
  return withFallback(
5279
- (apiKey) => manusPost("task.sendMessage", apiKey, body),
5479
+ (apiKey) => manusPost("task.sendMessage", apiKey, body2),
5280
5480
  keys
5281
5481
  );
5282
5482
  }
@@ -5601,7 +5801,7 @@ function validateCron(cron) {
5601
5801
  return minuteFieldViolatesFiveMinuteRule(minuteField ?? "", cron);
5602
5802
  }
5603
5803
  async function createSchedule(apiKey, params) {
5604
- const body = {
5804
+ const body2 = {
5605
5805
  name: params.name,
5606
5806
  cron: params.cron,
5607
5807
  prompt_template: params.prompt_template,
@@ -5615,7 +5815,7 @@ async function createSchedule(apiKey, params) {
5615
5815
  "x-manus-api-key": apiKey,
5616
5816
  "Content-Type": "application/json"
5617
5817
  },
5618
- body: JSON.stringify(body)
5818
+ body: JSON.stringify(body2)
5619
5819
  });
5620
5820
  if (!res.ok) {
5621
5821
  throw new ManusScheduleError(
@@ -6245,19 +6445,33 @@ function registerScheduleAndUsageTools(server2, ctx) {
6245
6445
  import { z as z7 } from "zod";
6246
6446
  import * as Sentry2 from "@sentry/cloudflare";
6247
6447
 
6448
+ // src/audit-schema.ts
6449
+ var MARKER_INDEX = 11;
6450
+ var SCHEMA_GENERIC = "v1-generic";
6451
+ var SCHEMA_CARRIER_ASK = "v1-carrier-ask";
6452
+ function withSchemaMarker(blobs, marker) {
6453
+ const out = [...blobs];
6454
+ while (out.length < MARKER_INDEX) out.push("");
6455
+ out.push(marker);
6456
+ return out;
6457
+ }
6458
+
6248
6459
  // src/audit.ts
6249
6460
  function writeAudit(env, row) {
6250
6461
  env.AUDIT_LOG.writeDataPoint({
6251
- blobs: [
6252
- row.tool_name,
6253
- row.ocs_method,
6254
- row.status,
6255
- row.dry_run ? "1" : "0",
6256
- row.sub,
6257
- row.manus_task_id ?? "",
6258
- row.manus_profile ?? "",
6259
- row.manus_key_used ?? ""
6260
- ],
6462
+ blobs: withSchemaMarker(
6463
+ [
6464
+ row.tool_name,
6465
+ row.ocs_method,
6466
+ row.status,
6467
+ row.dry_run ? "1" : "0",
6468
+ row.sub,
6469
+ row.manus_task_id ?? "",
6470
+ row.manus_profile ?? "",
6471
+ row.manus_key_used ?? ""
6472
+ ],
6473
+ SCHEMA_GENERIC
6474
+ ),
6261
6475
  doubles: [row.duration_ms, row.ocs_status_code ?? 0],
6262
6476
  indexes: [String(row.reseller_id)]
6263
6477
  });
@@ -6396,14 +6610,14 @@ function resolveConfig(env) {
6396
6610
  async function atlasFetch(env, path, init) {
6397
6611
  const { baseUrl: baseUrl2, key } = resolveConfig(env);
6398
6612
  const headers = { "X-Carrier-Internal-Key": key };
6399
- let body;
6613
+ let body2;
6400
6614
  if (init.body !== void 0) {
6401
6615
  headers["Content-Type"] = "application/json";
6402
- body = JSON.stringify(init.body);
6616
+ body2 = JSON.stringify(init.body);
6403
6617
  }
6404
6618
  let res;
6405
6619
  try {
6406
- res = await fetch(`${baseUrl2}${path}`, { method: init.method, headers, body });
6620
+ res = await fetch(`${baseUrl2}${path}`, { method: init.method, headers, body: body2 });
6407
6621
  } catch (e) {
6408
6622
  throw new WalletClientError(
6409
6623
  `ATLAS wallet request failed: ${e instanceof Error ? e.message : "network error"}`,
@@ -6564,7 +6778,7 @@ async function runAutoTopup(env, args) {
6564
6778
  return { charged: false, creditedCents: 0, reason: "no_payment_method" };
6565
6779
  }
6566
6780
  const bonusCents = bonusCentsFor(pack);
6567
- const body = new URLSearchParams({
6781
+ const body2 = new URLSearchParams({
6568
6782
  amount: String(pack.eurCents),
6569
6783
  currency: "eur",
6570
6784
  customer: customerId,
@@ -6581,7 +6795,7 @@ async function runAutoTopup(env, args) {
6581
6795
  const resp = await stripePostForm(
6582
6796
  stripeKey,
6583
6797
  "/v1/payment_intents",
6584
- body
6798
+ body2
6585
6799
  );
6586
6800
  if (!resp.ok) {
6587
6801
  return {
@@ -6855,6 +7069,13 @@ function registerStripeConnectTools(server2, ctx) {
6855
7069
  annotations: annotationsFor("stripe_connect_status", "read")
6856
7070
  },
6857
7071
  async ({ operator_id }) => {
7072
+ if (operator_id !== void 0 && operator_id !== operatorId) {
7073
+ if (!isPlatformOperator(env, props2.org_id)) {
7074
+ return err2(
7075
+ "operator_id may only be overridden by Carrier's own organization. Omit it to read your own Stripe Connect status."
7076
+ );
7077
+ }
7078
+ }
6858
7079
  const opId = operator_id ?? operatorId;
6859
7080
  const opKvKey = operator_id ? `stripe_account:${operator_id}` : kvKey;
6860
7081
  const start = Date.now();
@@ -7593,7 +7814,7 @@ async function triggerBillingThreshold(env, sub, amountCents) {
7593
7814
  if (!stripeKey) return;
7594
7815
  const customerId = await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`);
7595
7816
  if (!customerId) return;
7596
- const body = new URLSearchParams({
7817
+ const body2 = new URLSearchParams({
7597
7818
  customer: customerId,
7598
7819
  amount: String(Math.round(amountCents)),
7599
7820
  currency: "usd",
@@ -7605,7 +7826,7 @@ async function triggerBillingThreshold(env, sub, amountCents) {
7605
7826
  Authorization: `Bearer ${stripeKey}`,
7606
7827
  "Content-Type": "application/x-www-form-urlencoded"
7607
7828
  },
7608
- body: body.toString()
7829
+ body: body2.toString()
7609
7830
  });
7610
7831
  if (!resp.ok) return;
7611
7832
  const invoiceBody = new URLSearchParams({
@@ -7629,7 +7850,7 @@ async function pushOverageToStripe(env, sub, quantity, ratePerCredit) {
7629
7850
  if (!stripeKey) return;
7630
7851
  const subItemId = await env.CARRIER_USERS.get(`stripe_sub_item_id:${sub}`);
7631
7852
  if (!subItemId) return;
7632
- const body = new URLSearchParams({
7853
+ const body2 = new URLSearchParams({
7633
7854
  quantity: String(quantity),
7634
7855
  timestamp: String(Math.floor(Date.now() / 1e3)),
7635
7856
  action: "increment"
@@ -7642,7 +7863,7 @@ async function pushOverageToStripe(env, sub, quantity, ratePerCredit) {
7642
7863
  Authorization: `Bearer ${stripeKey}`,
7643
7864
  "Content-Type": "application/x-www-form-urlencoded"
7644
7865
  },
7645
- body: body.toString()
7866
+ body: body2.toString()
7646
7867
  }
7647
7868
  );
7648
7869
  await env.CARRIER_USERS.put(
@@ -9316,37 +9537,9 @@ function routerTools() {
9316
9537
  var ROUTER_SYSTEM_PROMPT = `You are a carrier fleet operations router. Your job is to map a user's natural-language intent to exactly ONE tool from the Carrier MCP tool registry.
9317
9538
 
9318
9539
  ${ROUTER_RULES}`;
9319
- var DEFAULT_REGION = "us-east-1";
9320
- var DEFAULT_MODEL_ID = "us.anthropic.claude-haiku-4-5-20251001-v1:0";
9321
- async function callBedrock(env, payload) {
9322
- const region = env.AWS_REGION ?? DEFAULT_REGION;
9323
- const modelId = env.BEDROCK_MODEL_ID ?? DEFAULT_MODEL_ID;
9324
- const aws = new AwsClient({
9325
- accessKeyId: env.AWS_ACCESS_KEY_ID,
9326
- secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
9327
- region,
9328
- service: "bedrock"
9329
- });
9330
- const url = `https://bedrock-runtime.${region}.amazonaws.com/model/${encodeURIComponent(modelId)}/invoke`;
9331
- const resp = await aws.fetch(url, {
9332
- method: "POST",
9333
- headers: { "Content-Type": "application/json", Accept: "application/json" },
9334
- body: JSON.stringify(payload)
9335
- });
9336
- if (!resp.ok) {
9337
- const body = await resp.text();
9338
- if (resp.status === 429) {
9339
- const retryAfter = resp.headers.get("retry-after");
9340
- const err7 = new Error(`Bedrock rate limit: ${body}`);
9341
- err7.isRateLimit = true;
9342
- err7.retryAfter = retryAfter;
9343
- throw err7;
9344
- }
9345
- throw new Error(`Bedrock invoke failed: ${resp.status} ${body}`);
9346
- }
9347
- return await resp.json();
9348
- }
9349
- async function _routeIntent(intent, context, env) {
9540
+ var ROUTER_TIMEOUT_MS = 12e3;
9541
+ async function _routeIntent(intent, context, env, opts = {}) {
9542
+ const { attribution, onUsage } = opts;
9350
9543
  if (env.CARRIER_ASK_ENABLED !== "true" || !env.AWS_ACCESS_KEY_ID || !env.AWS_SECRET_ACCESS_KEY) {
9351
9544
  return {
9352
9545
  match: "routing_pending",
@@ -9362,26 +9555,32 @@ async function _routeIntent(intent, context, env) {
9362
9555
 
9363
9556
  Pre-resolved context: ${JSON.stringify(definedContext)}` : "";
9364
9557
  const userMessage = `${intent}${contextNote}`;
9365
- const payload = {
9366
- anthropic_version: "bedrock-2023-05-31",
9367
- max_tokens: 512,
9368
- system: ROUTER_SYSTEM_PROMPT,
9369
- messages: [{ role: "user", content: userMessage }],
9370
- tools: routerTools(),
9371
- tool_choice: { type: "any" }
9372
- };
9373
- let response;
9558
+ const routerToolList = routerTools();
9559
+ const tools = routerToolList.map(
9560
+ (tool, idx) => idx === routerToolList.length - 1 ? { ...tool, cache_control: { type: "ephemeral" } } : tool
9561
+ );
9562
+ let toolCall;
9374
9563
  try {
9375
- response = await callBedrock({
9376
- AWS_ACCESS_KEY_ID: env.AWS_ACCESS_KEY_ID,
9377
- AWS_SECRET_ACCESS_KEY: env.AWS_SECRET_ACCESS_KEY,
9378
- AWS_REGION: env.AWS_REGION,
9379
- BEDROCK_MODEL_ID: env.BEDROCK_MODEL_ID
9380
- }, payload);
9564
+ toolCall = await invokeTool(
9565
+ {
9566
+ accessKeyId: env.AWS_ACCESS_KEY_ID,
9567
+ secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
9568
+ ...env.AWS_REGION ? { region: env.AWS_REGION } : {},
9569
+ ...env.BEDROCK_MODEL_ID ? { modelId: env.BEDROCK_MODEL_ID } : {}
9570
+ },
9571
+ {
9572
+ system: ROUTER_SYSTEM_PROMPT,
9573
+ messages: [{ role: "user", content: userMessage }],
9574
+ maxTokens: 512,
9575
+ tools,
9576
+ timeoutMs: ROUTER_TIMEOUT_MS,
9577
+ ...attribution ? { attribution } : {},
9578
+ ...onUsage ? { onUsage } : {}
9579
+ }
9580
+ );
9381
9581
  } catch (err7) {
9382
- if (err7 instanceof Error && err7.isRateLimit) {
9383
- const retryAfter = err7.retryAfter;
9384
- const parsedSeconds = retryAfter ? parseInt(retryAfter, 10) : 60;
9582
+ if (err7 instanceof BedrockRateLimitError) {
9583
+ const parsedSeconds = err7.retryAfter ? parseInt(err7.retryAfter, 10) : 60;
9385
9584
  return {
9386
9585
  match: "rate_limited",
9387
9586
  retry_after_seconds: Number.isFinite(parsedSeconds) ? parsedSeconds : 60,
@@ -9390,17 +9589,14 @@ Pre-resolved context: ${JSON.stringify(definedContext)}` : "";
9390
9589
  }
9391
9590
  throw err7;
9392
9591
  }
9393
- const toolUseBlock = response.content.find(
9394
- (block) => block.type === "tool_use"
9395
- );
9396
- if (!toolUseBlock) {
9592
+ if (!toolCall) {
9397
9593
  return {
9398
9594
  match: "none",
9399
9595
  closest: [],
9400
9596
  suggestion: "Could not determine the right tool for this intent. Try rephrasing or use carrier_ask_describe to explore available tools."
9401
9597
  };
9402
9598
  }
9403
- const { name: resolvedTool, input } = toolUseBlock;
9599
+ const { name: resolvedTool, input } = toolCall;
9404
9600
  const resolvedParams = input ?? {};
9405
9601
  if (resolvedTool === "carrier_clarify") {
9406
9602
  const candidates = resolvedParams.candidates ?? [];
@@ -9443,23 +9639,47 @@ Pre-resolved context: ${JSON.stringify(definedContext)}` : "";
9443
9639
  function writeCarrierAskAudit(env, row) {
9444
9640
  try {
9445
9641
  env.AUDIT_LOG.writeDataPoint({
9446
- blobs: [
9447
- "carrier_ask",
9448
- // blob[0] tool_name
9449
- row.resolved_tool,
9450
- // blob[1] resolved tool (or "none")
9451
- row.status,
9452
- // blob[2] ok | error
9453
- row.match,
9454
- // blob[3] match type
9455
- row.intent_hash,
9456
- // blob[4] SHA-256 of intent
9457
- row.confirm_token_state,
9458
- // blob[5] confirm token state
9459
- row.sub
9460
- // blob[6] user subject
9642
+ // The marker at blob[11] is what separates these rows from writeAudit's,
9643
+ // which writes a different layout to this same dataset — its blob[4] is
9644
+ // `sub` where this one's is an intent hash. Filter on it before reading
9645
+ // any other position.
9646
+ blobs: withSchemaMarker(
9647
+ [
9648
+ "carrier_ask",
9649
+ // blob[0] tool_name
9650
+ row.resolved_tool,
9651
+ // blob[1] resolved tool (or "none")
9652
+ row.status,
9653
+ // blob[2] ok | error
9654
+ row.match,
9655
+ // blob[3] match type
9656
+ row.intent_hash,
9657
+ // blob[4] SHA-256 of intent
9658
+ row.confirm_token_state,
9659
+ // blob[5] confirm token state
9660
+ row.sub,
9661
+ // blob[6] user subject
9662
+ // Appended, never reordered: blob positions are the query contract and
9663
+ // an existing dashboard reading blob[3] must keep reading match.
9664
+ row.model_id,
9665
+ // blob[7] model id, or "none"
9666
+ row.tier
9667
+ // blob[8] tier at call time
9668
+ ],
9669
+ SCHEMA_CARRIER_ASK
9670
+ ),
9671
+ // Same rule for doubles. latency stays at [0].
9672
+ doubles: [
9673
+ row.latency_ms,
9674
+ row.usage.inputTokens,
9675
+ row.usage.outputTokens,
9676
+ row.usage.cacheReadTokens,
9677
+ row.usage.cacheWriteTokens,
9678
+ // An estimate from a rate card we maintain, not a billed figure. It is
9679
+ // here so a per-tenant cost query is one SQL statement rather than a
9680
+ // join against a rate table that lives in another package.
9681
+ estimateCostUsd(row.usage)
9461
9682
  ],
9462
- doubles: [row.latency_ms],
9463
9683
  indexes: [String(row.reseller_id)]
9464
9684
  });
9465
9685
  } catch {
@@ -9505,7 +9725,10 @@ function registerAllCarrierAskTools(server2, ctx) {
9505
9725
  status: "error",
9506
9726
  latency_ms: Date.now() - start,
9507
9727
  sub: ctx.props.sub,
9508
- reseller_id: ctx.props.reseller_id
9728
+ reseller_id: ctx.props.reseller_id,
9729
+ model_id: "none",
9730
+ tier: ctx.props.tier,
9731
+ usage: ZERO_USAGE
9509
9732
  });
9510
9733
  return {
9511
9734
  content: [
@@ -9543,7 +9766,10 @@ function registerAllCarrierAskTools(server2, ctx) {
9543
9766
  status: "ok",
9544
9767
  latency_ms: Date.now() - start,
9545
9768
  sub: ctx.props.sub,
9546
- reseller_id: ctx.props.reseller_id
9769
+ reseller_id: ctx.props.reseller_id,
9770
+ model_id: "none",
9771
+ tier: ctx.props.tier,
9772
+ usage: ZERO_USAGE
9547
9773
  });
9548
9774
  return {
9549
9775
  content: [
@@ -9560,8 +9786,21 @@ function registerAllCarrierAskTools(server2, ctx) {
9560
9786
  };
9561
9787
  }
9562
9788
  let route;
9789
+ let routeUsage = ZERO_USAGE;
9790
+ let modelRan = false;
9563
9791
  try {
9564
- route = await _routeIntent(intent, context, ctx.env);
9792
+ route = await _routeIntent(intent, context, ctx.env, {
9793
+ attribution: {
9794
+ ...ctx.props.org_id ? { orgId: ctx.props.org_id } : {},
9795
+ ...ctx.props.reseller_id ? { subAccountId: String(ctx.props.reseller_id) } : {},
9796
+ surface: "carrier_ask",
9797
+ tier: ctx.props.tier
9798
+ },
9799
+ onUsage: (u) => {
9800
+ routeUsage = u;
9801
+ modelRan = true;
9802
+ }
9803
+ });
9565
9804
  } catch (err7) {
9566
9805
  writeCarrierAskAudit(ctx.env, {
9567
9806
  intent_hash: intentHash,
@@ -9571,7 +9810,14 @@ function registerAllCarrierAskTools(server2, ctx) {
9571
9810
  status: "error",
9572
9811
  latency_ms: Date.now() - start,
9573
9812
  sub: ctx.props.sub,
9574
- reseller_id: ctx.props.reseller_id
9813
+ reseller_id: ctx.props.reseller_id,
9814
+ model_id: modelRan ? ctx.env.BEDROCK_MODEL_ID ?? DEFAULT_MODEL_ID : "none",
9815
+ tier: ctx.props.tier,
9816
+ // Not ZERO_USAGE: a call can throw AFTER the model answered, and
9817
+ // those tokens were billed regardless. Recording zero here is how
9818
+ // measured spend drifts below real spend in exactly the rows used
9819
+ // to check it.
9820
+ usage: routeUsage
9575
9821
  });
9576
9822
  return {
9577
9823
  content: [
@@ -9608,7 +9854,10 @@ function registerAllCarrierAskTools(server2, ctx) {
9608
9854
  status: "ok",
9609
9855
  latency_ms: Date.now() - start,
9610
9856
  sub: ctx.props.sub,
9611
- reseller_id: ctx.props.reseller_id
9857
+ reseller_id: ctx.props.reseller_id,
9858
+ model_id: modelRan ? ctx.env.BEDROCK_MODEL_ID ?? DEFAULT_MODEL_ID : "none",
9859
+ tier: ctx.props.tier,
9860
+ usage: routeUsage
9612
9861
  });
9613
9862
  return {
9614
9863
  content: [
@@ -10150,22 +10399,22 @@ function toFleetInput(raw) {
10150
10399
 
10151
10400
  // src/apps/fleet-health-app.ts
10152
10401
  var FLEET_APP_RESOURCE_URI = "ui://fleet-health-dashboard";
10153
- async function safeCall2(client, method, params) {
10402
+ async function safeCall2(client2, method, params) {
10154
10403
  try {
10155
- return { data: await client.call(method, params), error: null };
10404
+ return { data: await client2.call(method, params), error: null };
10156
10405
  } catch (err7) {
10157
10406
  return { data: null, error: err7 instanceof Error ? err7.message : String(err7) };
10158
10407
  }
10159
10408
  }
10160
10409
  async function loadFleet(ctx, accountId) {
10161
10410
  const token2 = await ctx.getUserToken(ctx.props.sub);
10162
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
10411
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
10163
10412
  const resellerId = await getDefaultResellerId(ctx.env, token2).catch(() => void 0);
10164
10413
  const statusParams = accountId !== void 0 ? { accountId } : resellerId !== void 0 ? { resellerId } : {};
10165
10414
  const accountParams = resellerId !== void 0 ? { resellerId } : {};
10166
10415
  const [status, accounts] = await Promise.all([
10167
- safeCall2(client, "esimStatusPerAccount", statusParams),
10168
- safeCall2(client, "listResellerAccount", accountParams)
10416
+ safeCall2(client2, "esimStatusPerAccount", statusParams),
10417
+ safeCall2(client2, "listResellerAccount", accountParams)
10169
10418
  ]);
10170
10419
  return toFleetInput({
10171
10420
  status: status.data,
@@ -10311,9 +10560,9 @@ async function deleteWizardSession(env, sub, wizardId) {
10311
10560
  }
10312
10561
 
10313
10562
  // src/apps/provisioning-wizard.ts
10314
- async function safeCallWithToken(client, _token, method, params = {}) {
10563
+ async function safeCallWithToken(client2, _token, method, params = {}) {
10315
10564
  try {
10316
- return { data: await client.call(method, params), error: null };
10565
+ return { data: await client2.call(method, params), error: null };
10317
10566
  } catch (err7) {
10318
10567
  return {
10319
10568
  data: null,
@@ -10380,11 +10629,11 @@ function registerProvisioningWizard(server2, ctx) {
10380
10629
  },
10381
10630
  async ({ step, wizardId, subscriber_iccid, package_template_id }) => {
10382
10631
  const token2 = await ctx.getUserToken(ctx.props.sub);
10383
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
10632
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
10384
10633
  if (step === "init") {
10385
10634
  const newWizardId = generateWizardId();
10386
10635
  const subscribersResult = await safeCallWithToken(
10387
- client,
10636
+ client2,
10388
10637
  token2,
10389
10638
  "listResellerAccount",
10390
10639
  {}
@@ -10462,7 +10711,7 @@ function registerProvisioningWizard(server2, ctx) {
10462
10711
  }
10463
10712
  const resellerIdForTemplates = await getDefaultResellerId(ctx.env, token2);
10464
10713
  const packagesResult = await safeCallWithToken(
10465
- client,
10714
+ client2,
10466
10715
  token2,
10467
10716
  "listPrepaidPackageTemplate",
10468
10717
  { resellerId: resellerIdForTemplates }
@@ -10529,7 +10778,7 @@ function registerProvisioningWizard(server2, ctx) {
10529
10778
  };
10530
10779
  }
10531
10780
  const previewResult = await safeCallWithToken(
10532
- client,
10781
+ client2,
10533
10782
  token2,
10534
10783
  "listPrepaidPackageTemplate",
10535
10784
  {}
@@ -10601,7 +10850,7 @@ function registerProvisioningWizard(server2, ctx) {
10601
10850
  };
10602
10851
  }
10603
10852
  const subRecord = await safeCallWithToken(
10604
- client,
10853
+ client2,
10605
10854
  token2,
10606
10855
  "getSingleSubscriber",
10607
10856
  { iccid: session.subscriber_iccid }
@@ -10630,7 +10879,7 @@ function registerProvisioningWizard(server2, ctx) {
10630
10879
  };
10631
10880
  }
10632
10881
  const result2 = await safeCallWithToken(
10633
- client,
10882
+ client2,
10634
10883
  token2,
10635
10884
  "affectPackageToSubscriber",
10636
10885
  {
@@ -10674,9 +10923,9 @@ import {
10674
10923
  registerAppResource as registerAppResource3,
10675
10924
  RESOURCE_MIME_TYPE as RESOURCE_MIME_TYPE3
10676
10925
  } from "@modelcontextprotocol/ext-apps/server";
10677
- async function safeCallWithToken2(client, _token, method, params = {}) {
10926
+ async function safeCallWithToken2(client2, _token, method, params = {}) {
10678
10927
  try {
10679
- return { data: await client.call(method, params), error: null };
10928
+ return { data: await client2.call(method, params), error: null };
10680
10929
  } catch (err7) {
10681
10930
  return {
10682
10931
  data: null,
@@ -10740,10 +10989,10 @@ function registerBalanceTopupApp(server2, ctx) {
10740
10989
  ctx,
10741
10990
  async ({ iccid, delta, preview }) => {
10742
10991
  const token2 = await ctx.getUserToken(ctx.props.sub);
10743
- const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
10992
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
10744
10993
  if (preview === true) {
10745
10994
  const result2 = await safeCallWithToken2(
10746
- client,
10995
+ client2,
10747
10996
  token2,
10748
10997
  "getSingleSubscriber",
10749
10998
  { iccid }
@@ -10768,7 +11017,7 @@ function registerBalanceTopupApp(server2, ctx) {
10768
11017
  };
10769
11018
  }
10770
11019
  const execResult = await safeCallWithToken2(
10771
- client,
11020
+ client2,
10772
11021
  token2,
10773
11022
  // CAR-78: subscriber top-up uses modifySubscriberBalance with { subscriber, amount }
10774
11023
  // (delta). modifyAccountBalance is account-level and expects { accountId, amount, mode }.