@runpod/mcp-server 4.9.1 → 4.10.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/hosted.cjs CHANGED
@@ -436,6 +436,104 @@ function coerceScalars(value, schema, defs, depth = 0) {
436
436
 
437
437
  // src/specgen/generated/tools.gen.ts
438
438
  var generatedTools = [
439
+ {
440
+ name: "add-organization-group-member",
441
+ title: "Add organization group member",
442
+ operationId: "addOrganizationGroupMember",
443
+ description: "Add a member to a group. Adds the organization member to the group. The group and user must belong to the current organization. Adding an existing member is idempotent and returns the same no-content response.",
444
+ method: "PUT",
445
+ path: "/v2/organization/groups/{id}/members/{userId}",
446
+ params: [
447
+ {
448
+ name: "id",
449
+ location: "path"
450
+ },
451
+ {
452
+ name: "userId",
453
+ location: "path"
454
+ }
455
+ ],
456
+ hasBody: false,
457
+ annotations: {
458
+ readOnlyHint: false,
459
+ destructiveHint: false,
460
+ idempotentHint: true,
461
+ openWorldHint: true
462
+ },
463
+ inputSchema: {
464
+ type: "object",
465
+ properties: {
466
+ id: {
467
+ type: "string",
468
+ minLength: 1,
469
+ description: "Group ID."
470
+ },
471
+ userId: {
472
+ type: "string",
473
+ minLength: 1,
474
+ description: "Organization member user ID."
475
+ }
476
+ },
477
+ required: ["id", "userId"]
478
+ }
479
+ },
480
+ {
481
+ name: "attach-cost-center-resource",
482
+ title: "Attach cost center resource",
483
+ operationId: "attachCostCenterResource",
484
+ description: "Attribute a resource to a cost center. Attributes a resource to a cost center. Repeating the request is a no-op. A resource belongs to at most one cost center; one already attributed elsewhere is rejected with 409 rather than moved.",
485
+ method: "PUT",
486
+ path: "/v2/cost-centers/{id}/{resourceType}/{resourceId}",
487
+ params: [
488
+ {
489
+ name: "id",
490
+ location: "path"
491
+ },
492
+ {
493
+ name: "resourceType",
494
+ location: "path"
495
+ },
496
+ {
497
+ name: "resourceId",
498
+ location: "path"
499
+ }
500
+ ],
501
+ hasBody: false,
502
+ annotations: {
503
+ readOnlyHint: false,
504
+ destructiveHint: false,
505
+ idempotentHint: true,
506
+ openWorldHint: true
507
+ },
508
+ inputSchema: {
509
+ type: "object",
510
+ properties: {
511
+ id: {
512
+ type: "string",
513
+ minLength: 1,
514
+ description: "Cost center identifier."
515
+ },
516
+ resourceType: {
517
+ $ref: "#/$defs/ResourceType",
518
+ description: "Kind of resource.",
519
+ type: "string"
520
+ },
521
+ resourceId: {
522
+ type: "string",
523
+ minLength: 1,
524
+ description: "Resource identifier."
525
+ }
526
+ },
527
+ required: ["id", "resourceType", "resourceId"],
528
+ $defs: {
529
+ ResourceType: {
530
+ type: "string",
531
+ description: "Kind of resource a cost center or tag can be attached to.",
532
+ enum: ["POD", "CLUSTER", "SERVERLESS_ENDPOINT", "NETWORK_VOLUME"]
533
+ }
534
+ }
535
+ }
536
+ },
439
537
  {
440
538
  name: "create-cluster",
441
539
  title: "Create cluster",
@@ -534,7 +632,6 @@ var generatedTools = [
534
632
  },
535
633
  network: {
536
634
  type: "array",
537
- maxItems: 1,
538
635
  items: {
539
636
  $ref: "#/$defs/NetworkMount"
540
637
  }
@@ -556,7 +653,7 @@ var generatedTools = [
556
653
  gpuCountPerPod: {
557
654
  type: "integer",
558
655
  minimum: 1,
559
- description: "Number of GPUs on each pod. Bounded above by the GPU type's per-cloud maximum (GpuType.maxCount); the upstream rejects values beyond it.",
656
+ description: "Number of GPUs on each pod. Bounded above by the GPU type's per-cloud maximum (GpuType.maxCount); values beyond it are rejected.",
560
657
  examples: [8]
561
658
  },
562
659
  podCount: {
@@ -569,7 +666,7 @@ var generatedTools = [
569
666
  }
570
667
  },
571
668
  ClusterMounts: {
572
- description: "Storage mounts for a cluster create: `persistent` or `network`, not both. Clusters cannot mount global volumes, so `global` is rejected.",
669
+ description: "Storage mounts for a cluster create: `persistent` or one `network` volume, not both. Clusters cannot mount global volumes, so `global` is rejected.",
573
670
  "x-go-type": "BaseMounts",
574
671
  allOf: [
575
672
  {
@@ -589,6 +686,7 @@ var generatedTools = [
589
686
  },
590
687
  network: {
591
688
  type: "array",
689
+ maxItems: 1,
592
690
  items: {
593
691
  type: "object",
594
692
  properties: {
@@ -667,7 +765,7 @@ var generatedTools = [
667
765
  type: "object",
668
766
  required: ["volumeId", "path"],
669
767
  additionalProperties: false,
670
- description: "Reference to a NetworkVolume. Custom paths are honored at runtime on both GPU and CPU pods. The underlying `volumeId` is immutable post-create; the mount `path` may be changed via PATCH.",
768
+ description: "Reference to a NetworkVolume. Custom paths are honored at runtime on both GPU and CPU pods. On a pod, the volume can be mounted, moved, or unmounted after creation (see `UpdatePodMounts`).",
671
769
  properties: {
672
770
  volumeId: {
673
771
  type: "string",
@@ -690,7 +788,7 @@ var generatedTools = [
690
788
  size: {
691
789
  type: "integer",
692
790
  minimum: 10,
693
- description: "Host-local persistent storage in GB. Upstream enforces a 10 GB floor.",
791
+ description: "Host-local persistent storage in GB. Minimum 10 GB.",
694
792
  examples: [20]
695
793
  },
696
794
  path: {
@@ -703,6 +801,77 @@ var generatedTools = [
703
801
  }
704
802
  }
705
803
  },
804
+ {
805
+ name: "create-cost-center",
806
+ title: "Create cost center",
807
+ operationId: "createCostCenter",
808
+ description: "Create a cost center. Creates a cost center \u2014 a named label that groups resource spend so it can be broken out in billing. Pass `resources` to attribute resources at creation time; attaching is all-or-nothing, and a resource that already belongs to another cost center is rejected rather than moved.",
809
+ method: "POST",
810
+ path: "/v2/cost-centers",
811
+ params: [],
812
+ hasBody: true,
813
+ annotations: {
814
+ readOnlyHint: false,
815
+ destructiveHint: false,
816
+ idempotentHint: false,
817
+ openWorldHint: true
818
+ },
819
+ inputSchema: {
820
+ type: "object",
821
+ properties: {
822
+ body: {
823
+ $ref: "#/$defs/CreateCostCenterRequest",
824
+ type: "object"
825
+ }
826
+ },
827
+ required: ["body"],
828
+ $defs: {
829
+ CostCenterResource: {
830
+ type: "object",
831
+ additionalProperties: false,
832
+ required: ["id", "type"],
833
+ properties: {
834
+ id: {
835
+ type: "string",
836
+ minLength: 1,
837
+ examples: ["p9k2m4n6q8"]
838
+ },
839
+ type: {
840
+ $ref: "#/$defs/ResourceType"
841
+ }
842
+ }
843
+ },
844
+ CreateCostCenterRequest: {
845
+ type: "object",
846
+ additionalProperties: false,
847
+ required: ["value"],
848
+ properties: {
849
+ value: {
850
+ type: "string",
851
+ minLength: 1,
852
+ maxLength: 50,
853
+ pattern: "^\\s*\\S",
854
+ description: "Leading and trailing whitespace is trimmed.",
855
+ examples: ["team-ml"]
856
+ },
857
+ resources: {
858
+ type: "array",
859
+ description: "Resources to attribute to the new cost center.",
860
+ maxItems: 100,
861
+ items: {
862
+ $ref: "#/$defs/CostCenterResource"
863
+ }
864
+ }
865
+ }
866
+ },
867
+ ResourceType: {
868
+ type: "string",
869
+ description: "Kind of resource a cost center or tag can be attached to.",
870
+ enum: ["POD", "CLUSTER", "SERVERLESS_ENDPOINT", "NETWORK_VOLUME"]
871
+ }
872
+ }
873
+ }
874
+ },
706
875
  {
707
876
  name: "create-delegation",
708
877
  title: "Create ECR delegation",
@@ -1231,6 +1400,7 @@ var generatedTools = [
1231
1400
  type: "string",
1232
1401
  minLength: 1,
1233
1402
  maxLength: 191,
1403
+ pattern: "[^\\t-\\r \x85\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]",
1234
1404
  description: "Human-readable name, 1\u2013191 characters with at least one non-whitespace character. Leading and trailing whitespace is trimmed.",
1235
1405
  examples: ["training-data"]
1236
1406
  }
@@ -1306,6 +1476,169 @@ var generatedTools = [
1306
1476
  }
1307
1477
  }
1308
1478
  },
1479
+ {
1480
+ name: "create-organization-group",
1481
+ title: "Create organization group",
1482
+ operationId: "createOrganizationGroup",
1483
+ description: "Create a group in your current organization",
1484
+ method: "POST",
1485
+ path: "/v2/organization/groups",
1486
+ params: [],
1487
+ hasBody: true,
1488
+ annotations: {
1489
+ readOnlyHint: false,
1490
+ destructiveHint: false,
1491
+ idempotentHint: false,
1492
+ openWorldHint: true
1493
+ },
1494
+ inputSchema: {
1495
+ type: "object",
1496
+ properties: {
1497
+ body: {
1498
+ $ref: "#/$defs/CreateOrganizationGroupRequest",
1499
+ type: "object"
1500
+ }
1501
+ },
1502
+ required: ["body"],
1503
+ $defs: {
1504
+ CreateOrganizationGroupRequest: {
1505
+ type: "object",
1506
+ additionalProperties: false,
1507
+ required: ["name"],
1508
+ properties: {
1509
+ name: {
1510
+ type: "string",
1511
+ minLength: 1,
1512
+ maxLength: 191,
1513
+ pattern: "[^\\t-\\r \x85\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]",
1514
+ description: "Group name with at least one non-whitespace character; surrounding whitespace is trimmed.",
1515
+ examples: ["Engineering"]
1516
+ }
1517
+ }
1518
+ }
1519
+ }
1520
+ }
1521
+ },
1522
+ {
1523
+ name: "create-organization-invite",
1524
+ title: "Create organization invite",
1525
+ operationId: "createOrganizationInvite",
1526
+ description: "Invite a user to your organization. Sends an invitation to join the authenticated caller's organization and returns the pending invite; `expiresAt` is when it lapses. The invitee receives an email carrying the acceptance link, which is never returned here. Returns 409 when the address already belongs to a member or to a pending invite, or when the organization has reached its pending-invite limit; 404 when the role is unknown to the organization; and 403 when the caller does not hold every capability the role grants. Inviting requires the organization's invite-management capability, which the built-in admin role holds; other members, and callers outside an organization, receive 403, as does a caller for whom organizations are unavailable.",
1527
+ method: "POST",
1528
+ path: "/v2/organization/invites",
1529
+ params: [],
1530
+ hasBody: true,
1531
+ annotations: {
1532
+ readOnlyHint: false,
1533
+ destructiveHint: false,
1534
+ idempotentHint: false,
1535
+ openWorldHint: true
1536
+ },
1537
+ inputSchema: {
1538
+ type: "object",
1539
+ properties: {
1540
+ body: {
1541
+ $ref: "#/$defs/CreateOrganizationInviteRequest",
1542
+ type: "object"
1543
+ }
1544
+ },
1545
+ required: ["body"],
1546
+ $defs: {
1547
+ CreateOrganizationInviteRequest: {
1548
+ type: "object",
1549
+ additionalProperties: false,
1550
+ required: ["email", "role"],
1551
+ properties: {
1552
+ email: {
1553
+ type: "string",
1554
+ format: "email",
1555
+ minLength: 1,
1556
+ maxLength: 254,
1557
+ description: "Address to invite, stored lowercased. The invitee accepts by signing in with a verified account on this address.",
1558
+ examples: ["new-member@example.com"]
1559
+ },
1560
+ role: {
1561
+ $ref: "#/$defs/OrganizationRoleInput"
1562
+ }
1563
+ }
1564
+ },
1565
+ OrganizationRoleInput: {
1566
+ type: "object",
1567
+ description: "An organization role to assign, by ID.",
1568
+ additionalProperties: false,
1569
+ required: ["id"],
1570
+ properties: {
1571
+ id: {
1572
+ type: "string",
1573
+ minLength: 1,
1574
+ description: "Role ID, as reported on a member or an invite: `builtin:admin`, `builtin:dev`, `builtin:billing`, `builtin:basic`, or a custom role's own ID.",
1575
+ examples: ["builtin:dev"]
1576
+ }
1577
+ }
1578
+ }
1579
+ }
1580
+ }
1581
+ },
1582
+ {
1583
+ name: "create-organization-role",
1584
+ title: "Create organization role",
1585
+ operationId: "createOrganizationRole",
1586
+ description: "Create a custom organization role. Creates a custom role in the authenticated caller's organization and returns it. Returns 409 when the organization already has a role with this name or has reached its custom-role limit; 422 when a capability is unknown or the name is reserved; and 403 when the caller does not hold every capability the role grants. Creating roles requires the organization's role-management capability, which the built-in admin role holds; other members, and callers outside an organization, receive 403, as does a caller for whom organizations are unavailable.",
1587
+ method: "POST",
1588
+ path: "/v2/organization/roles",
1589
+ params: [],
1590
+ hasBody: true,
1591
+ annotations: {
1592
+ readOnlyHint: false,
1593
+ destructiveHint: false,
1594
+ idempotentHint: false,
1595
+ openWorldHint: true
1596
+ },
1597
+ inputSchema: {
1598
+ type: "object",
1599
+ properties: {
1600
+ body: {
1601
+ $ref: "#/$defs/CreateOrganizationRoleRequest",
1602
+ type: "object"
1603
+ }
1604
+ },
1605
+ required: ["body"],
1606
+ $defs: {
1607
+ CreateOrganizationRoleRequest: {
1608
+ type: "object",
1609
+ additionalProperties: false,
1610
+ required: ["name", "capabilities"],
1611
+ properties: {
1612
+ name: {
1613
+ $ref: "#/$defs/OrganizationRoleName"
1614
+ },
1615
+ capabilities: {
1616
+ $ref: "#/$defs/OrganizationRoleCapabilitiesInput"
1617
+ }
1618
+ }
1619
+ },
1620
+ OrganizationRoleCapabilitiesInput: {
1621
+ type: "array",
1622
+ description: "What the role grants, as `FAMILY:VERB` capabilities from `get-organization-role-capabilities`. The caller must hold every capability it lists.",
1623
+ minItems: 1,
1624
+ uniqueItems: true,
1625
+ items: {
1626
+ type: "string",
1627
+ pattern: "^[A-Z0-9_]+:[A-Z0-9_]+$"
1628
+ },
1629
+ examples: [["POD:VIEW"]]
1630
+ },
1631
+ OrganizationRoleName: {
1632
+ type: "string",
1633
+ minLength: 1,
1634
+ maxLength: 191,
1635
+ pattern: "[^\\t-\\r \x85\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]",
1636
+ description: "Display name, 1\u2013191 characters with at least one non-whitespace character. Leading and trailing whitespace is trimmed. It must be unique within the organization and cannot be a built-in role's name.",
1637
+ examples: ["Pod viewer"]
1638
+ }
1639
+ }
1640
+ }
1641
+ },
1309
1642
  {
1310
1643
  name: "create-pod",
1311
1644
  title: "Create Pod",
@@ -1426,6 +1759,7 @@ var generatedTools = [
1426
1759
  count: {
1427
1760
  type: "integer",
1428
1761
  minimum: 1,
1762
+ maximum: 1024,
1429
1763
  default: 1,
1430
1764
  description: "Number of GPUs",
1431
1765
  examples: [1]
@@ -1440,7 +1774,6 @@ var generatedTools = [
1440
1774
  },
1441
1775
  network: {
1442
1776
  type: "array",
1443
- maxItems: 1,
1444
1777
  items: {
1445
1778
  $ref: "#/$defs/NetworkMount"
1446
1779
  }
@@ -1504,12 +1837,14 @@ var generatedTools = [
1504
1837
  minRamPerGpu: {
1505
1838
  type: "integer",
1506
1839
  minimum: 1,
1840
+ maximum: 65536,
1507
1841
  description: "Minimum host system RAM in GB per requested GPU. This is a placement filter, not a resource request. The actual total allocated system RAM may be higher and is returned in gpu.memory.",
1508
1842
  examples: [8]
1509
1843
  },
1510
1844
  minVcpuCountPerGpu: {
1511
1845
  type: "integer",
1512
1846
  minimum: 1,
1847
+ maximum: 4096,
1513
1848
  description: "Minimum host vCPU count per requested GPU. This is a placement filter, not a resource request. The actual total allocated vCPU count may be higher and is returned in gpu.vcpuCount.",
1514
1849
  examples: [2]
1515
1850
  }
@@ -1600,7 +1935,7 @@ var generatedTools = [
1600
1935
  type: "object",
1601
1936
  required: ["volumeId"],
1602
1937
  additionalProperties: false,
1603
- description: "Reference to a GlobalVolume. Usage-billed, so it has no size. The underlying `volumeId` is immutable post-create; the mount `path` may be changed via PATCH.",
1938
+ description: "Reference to a GlobalVolume. Usage-billed, so it has no size. On a pod, the volume can be mounted, moved, or unmounted after creation (see `UpdatePodMounts`).",
1604
1939
  properties: {
1605
1940
  volumeId: {
1606
1941
  type: "string",
@@ -1609,7 +1944,7 @@ var generatedTools = [
1609
1944
  },
1610
1945
  path: {
1611
1946
  type: "string",
1612
- description: "Mount path inside the container. Optional on create, where a default is chosen for you; a PATCH that omits it leaves the path unchanged.",
1947
+ description: "Mount path inside the container. Optional; a default is chosen for you when omitted.",
1613
1948
  examples: ["/data"]
1614
1949
  }
1615
1950
  }
@@ -1623,10 +1958,18 @@ var generatedTools = [
1623
1958
  {
1624
1959
  type: "object",
1625
1960
  properties: {
1961
+ network: {
1962
+ type: "array",
1963
+ maxItems: 4,
1964
+ description: "Up to 4 network volumes, all in the pod's data center.",
1965
+ items: {
1966
+ $ref: "#/$defs/NetworkMount"
1967
+ }
1968
+ },
1626
1969
  global: {
1627
1970
  type: "array",
1628
1971
  maxItems: 1,
1629
- description: "At most one global volume, on GPU and CPU pods, with no data center constraint. Combinable with `network` but not with `persistent` (rejected): upstream drops a persistent disk whenever a volume is attached.",
1972
+ description: "At most one global volume, on GPU and CPU pods, with no data center constraint. Combinable with `network` but not with `persistent` (rejected): a persistent disk is dropped whenever a volume is attached. Same PATCH rules as `network`.",
1630
1973
  items: {
1631
1974
  $ref: "#/$defs/GlobalMount"
1632
1975
  }
@@ -1640,7 +1983,7 @@ var generatedTools = [
1640
1983
  type: "object",
1641
1984
  required: ["volumeId", "path"],
1642
1985
  additionalProperties: false,
1643
- description: "Reference to a NetworkVolume. Custom paths are honored at runtime on both GPU and CPU pods. The underlying `volumeId` is immutable post-create; the mount `path` may be changed via PATCH.",
1986
+ description: "Reference to a NetworkVolume. Custom paths are honored at runtime on both GPU and CPU pods. On a pod, the volume can be mounted, moved, or unmounted after creation (see `UpdatePodMounts`).",
1644
1987
  properties: {
1645
1988
  volumeId: {
1646
1989
  type: "string",
@@ -1663,7 +2006,7 @@ var generatedTools = [
1663
2006
  size: {
1664
2007
  type: "integer",
1665
2008
  minimum: 10,
1666
- description: "Host-local persistent storage in GB. Upstream enforces a 10 GB floor.",
2009
+ description: "Host-local persistent storage in GB. Minimum 10 GB.",
1667
2010
  examples: [20]
1668
2011
  },
1669
2012
  path: {
@@ -1960,7 +2303,7 @@ var generatedTools = [
1960
2303
  size: {
1961
2304
  type: "integer",
1962
2305
  minimum: 10,
1963
- description: "Host-local persistent storage in GB. Upstream enforces a 10 GB floor.",
2306
+ description: "Host-local persistent storage in GB. Minimum 10 GB.",
1964
2307
  examples: [20]
1965
2308
  },
1966
2309
  path: {
@@ -2021,13 +2364,12 @@ var generatedTools = [
2021
2364
  }
2022
2365
  },
2023
2366
  {
2024
- name: "delete-endpoint",
2025
- title: "Delete endpoint",
2026
- operationId: "deleteEndpoint",
2027
- description: "Delete a serverless endpoint permanently and immediately. Verify the id belongs to the intended endpoint (get-endpoint) before deleting; delete only endpoints your own tool calls created in this conversation, or the one the user asked you to delete by id \u2014 a name found by listing is not attribution.",
2028
- directoryDescription: "Delete a Serverless endpoint permanently and immediately.",
2367
+ name: "delete-cost-center",
2368
+ title: "Delete cost center",
2369
+ operationId: "deleteCostCenter",
2370
+ description: "Delete a cost center. Deletes a cost center. The delete fails with 409 while any resource is still attributed to the cost center; detach those resources first.",
2029
2371
  method: "DELETE",
2030
- path: "/v2/serverless/{id}",
2372
+ path: "/v2/cost-centers/{id}",
2031
2373
  params: [
2032
2374
  {
2033
2375
  name: "id",
@@ -2046,21 +2388,54 @@ var generatedTools = [
2046
2388
  properties: {
2047
2389
  id: {
2048
2390
  type: "string",
2049
- description: "Serverless endpoint identifier"
2391
+ minLength: 1,
2392
+ description: "Cost center identifier."
2050
2393
  }
2051
2394
  },
2052
2395
  required: ["id"]
2053
2396
  }
2054
2397
  },
2055
2398
  {
2056
- name: "delete-global-volume",
2057
- title: "Delete global volume",
2058
- operationId: "deleteGlobalVolume",
2059
- description: "Delete a global volume. Permanently deletes a global volume and its stored data. Fails with `409` while the volume is still mounted: terminate every pod that mounts it (stopped pods count) and detach it from every serverless endpoint first. Nothing is detached or terminated on your behalf.",
2060
- method: "DELETE",
2061
- path: "/v2/global-volumes/{id}",
2062
- params: [
2063
- {
2399
+ name: "delete-endpoint",
2400
+ title: "Delete endpoint",
2401
+ operationId: "deleteEndpoint",
2402
+ description: "Delete a serverless endpoint permanently and immediately. Verify the id belongs to the intended endpoint (get-endpoint) before deleting; delete only endpoints your own tool calls created in this conversation, or the one the user asked you to delete by id \u2014 a name found by listing is not attribution.",
2403
+ directoryDescription: "Delete a Serverless endpoint permanently and immediately.",
2404
+ method: "DELETE",
2405
+ path: "/v2/serverless/{id}",
2406
+ params: [
2407
+ {
2408
+ name: "id",
2409
+ location: "path"
2410
+ }
2411
+ ],
2412
+ hasBody: false,
2413
+ annotations: {
2414
+ readOnlyHint: false,
2415
+ destructiveHint: true,
2416
+ idempotentHint: true,
2417
+ openWorldHint: true
2418
+ },
2419
+ inputSchema: {
2420
+ type: "object",
2421
+ properties: {
2422
+ id: {
2423
+ type: "string",
2424
+ description: "Serverless endpoint identifier"
2425
+ }
2426
+ },
2427
+ required: ["id"]
2428
+ }
2429
+ },
2430
+ {
2431
+ name: "delete-global-volume",
2432
+ title: "Delete global volume",
2433
+ operationId: "deleteGlobalVolume",
2434
+ description: "Delete a global volume. Permanently deletes a global volume and its stored data. Fails with `409` while the volume is still mounted: terminate every pod that mounts it (stopped pods count) and detach it from every serverless endpoint first. Nothing is detached or terminated on your behalf.",
2435
+ method: "DELETE",
2436
+ path: "/v2/global-volumes/{id}",
2437
+ params: [
2438
+ {
2064
2439
  name: "id",
2065
2440
  location: "path"
2066
2441
  }
@@ -2114,6 +2489,131 @@ var generatedTools = [
2114
2489
  required: ["id"]
2115
2490
  }
2116
2491
  },
2492
+ {
2493
+ name: "delete-organization-group",
2494
+ title: "Delete organization group",
2495
+ operationId: "deleteOrganizationGroup",
2496
+ description: "Delete a group in your current organization. Permanently deletes the group and its group memberships. Organization members are not removed. Returns 404 when the group does not exist in your current organization, including when it has already been deleted.",
2497
+ method: "DELETE",
2498
+ path: "/v2/organization/groups/{id}",
2499
+ params: [
2500
+ {
2501
+ name: "id",
2502
+ location: "path"
2503
+ }
2504
+ ],
2505
+ hasBody: false,
2506
+ annotations: {
2507
+ readOnlyHint: false,
2508
+ destructiveHint: true,
2509
+ idempotentHint: true,
2510
+ openWorldHint: true
2511
+ },
2512
+ inputSchema: {
2513
+ type: "object",
2514
+ properties: {
2515
+ id: {
2516
+ type: "string",
2517
+ minLength: 1,
2518
+ description: "Group ID."
2519
+ }
2520
+ },
2521
+ required: ["id"]
2522
+ }
2523
+ },
2524
+ {
2525
+ name: "delete-organization-invite",
2526
+ title: "Delete organization invite",
2527
+ operationId: "deleteOrganizationInvite",
2528
+ description: "Cancel an organization invite. Cancels one invitation to the authenticated caller's organization; the invitee can no longer accept it. Returns 404 when the ID is unknown to the caller's organization: never issued, already accepted, already cancelled, or issued by another organization. An expired invite can still be cancelled. Cancelling invites requires the organization's invite-management capability, which the built-in admin role holds; other members, and callers outside an organization, receive 403, as does a caller for whom organizations are unavailable.",
2529
+ method: "DELETE",
2530
+ path: "/v2/organization/invites/{id}",
2531
+ params: [
2532
+ {
2533
+ name: "id",
2534
+ location: "path"
2535
+ }
2536
+ ],
2537
+ hasBody: false,
2538
+ annotations: {
2539
+ readOnlyHint: false,
2540
+ destructiveHint: true,
2541
+ idempotentHint: true,
2542
+ openWorldHint: true
2543
+ },
2544
+ inputSchema: {
2545
+ type: "object",
2546
+ properties: {
2547
+ id: {
2548
+ type: "string",
2549
+ description: "Invite identifier"
2550
+ }
2551
+ },
2552
+ required: ["id"]
2553
+ }
2554
+ },
2555
+ {
2556
+ name: "delete-organization-role",
2557
+ title: "Delete organization role",
2558
+ operationId: "deleteOrganizationRole",
2559
+ description: "Delete a custom organization role. Deletes a custom role from the authenticated caller's organization. Returns 409 while a member or a pending invite holds the role: reassign those members and cancel those invites first, since deleting never changes anyone's role. Expired invites do not block deletion. Returns 400 for a built-in role, which cannot be deleted; 404 when the ID is unknown, names another organization's role, or was already deleted. Deleting roles requires the organization's role-management capability, which the built-in admin role holds; other members, and callers outside an organization, receive 403, as does a caller for whom organizations are unavailable.",
2560
+ method: "DELETE",
2561
+ path: "/v2/organization/roles/{id}",
2562
+ params: [
2563
+ {
2564
+ name: "id",
2565
+ location: "path"
2566
+ }
2567
+ ],
2568
+ hasBody: false,
2569
+ annotations: {
2570
+ readOnlyHint: false,
2571
+ destructiveHint: true,
2572
+ idempotentHint: true,
2573
+ openWorldHint: true
2574
+ },
2575
+ inputSchema: {
2576
+ type: "object",
2577
+ properties: {
2578
+ id: {
2579
+ type: "string",
2580
+ description: "Role identifier"
2581
+ }
2582
+ },
2583
+ required: ["id"]
2584
+ }
2585
+ },
2586
+ {
2587
+ name: "delete-organization-user",
2588
+ title: "Delete organization user",
2589
+ operationId: "deleteOrganizationUser",
2590
+ description: "Remove an organization member. Removes one member from the authenticated caller's organization by user ID. Their group memberships end and the API keys attributed to them within the organization are revoked; the resources they created stay with the organization. Removing another member requires the organization's member-removal capability, which the built-in admin role holds; any member can remove themselves. The organization keeps at least one member with the built-in admin role, so removing the last one returns 409. A user who is not a member, including one from another organization, returns 404. A member without the capability removing someone else, a caller outside an organization, and a caller for whom organizations are unavailable receive 403.",
2591
+ method: "DELETE",
2592
+ path: "/v2/organization/users/{id}",
2593
+ params: [
2594
+ {
2595
+ name: "id",
2596
+ location: "path"
2597
+ }
2598
+ ],
2599
+ hasBody: false,
2600
+ annotations: {
2601
+ readOnlyHint: false,
2602
+ destructiveHint: true,
2603
+ idempotentHint: true,
2604
+ openWorldHint: true
2605
+ },
2606
+ inputSchema: {
2607
+ type: "object",
2608
+ properties: {
2609
+ id: {
2610
+ type: "string",
2611
+ description: "User identifier"
2612
+ }
2613
+ },
2614
+ required: ["id"]
2615
+ }
2616
+ },
2117
2617
  {
2118
2618
  name: "delete-pod",
2119
2619
  title: "Delete Pod",
@@ -2239,6 +2739,63 @@ var generatedTools = [
2239
2739
  required: ["id"]
2240
2740
  }
2241
2741
  },
2742
+ {
2743
+ name: "detach-cost-center-resource",
2744
+ title: "Detach cost center resource",
2745
+ operationId: "detachCostCenterResource",
2746
+ description: "Remove a resource from a cost center. Removes a resource's attribution to a cost center. The resource itself is untouched. Returns 404 when the cost center does not exist or the resource is not attributed to it, so repeating a DELETE that succeeded returns 404.",
2747
+ method: "DELETE",
2748
+ path: "/v2/cost-centers/{id}/{resourceType}/{resourceId}",
2749
+ params: [
2750
+ {
2751
+ name: "id",
2752
+ location: "path"
2753
+ },
2754
+ {
2755
+ name: "resourceType",
2756
+ location: "path"
2757
+ },
2758
+ {
2759
+ name: "resourceId",
2760
+ location: "path"
2761
+ }
2762
+ ],
2763
+ hasBody: false,
2764
+ annotations: {
2765
+ readOnlyHint: false,
2766
+ destructiveHint: true,
2767
+ idempotentHint: true,
2768
+ openWorldHint: true
2769
+ },
2770
+ inputSchema: {
2771
+ type: "object",
2772
+ properties: {
2773
+ id: {
2774
+ type: "string",
2775
+ minLength: 1,
2776
+ description: "Cost center identifier."
2777
+ },
2778
+ resourceType: {
2779
+ $ref: "#/$defs/ResourceType",
2780
+ description: "Kind of resource.",
2781
+ type: "string"
2782
+ },
2783
+ resourceId: {
2784
+ type: "string",
2785
+ minLength: 1,
2786
+ description: "Resource identifier."
2787
+ }
2788
+ },
2789
+ required: ["id", "resourceType", "resourceId"],
2790
+ $defs: {
2791
+ ResourceType: {
2792
+ type: "string",
2793
+ description: "Kind of resource a cost center or tag can be attached to.",
2794
+ enum: ["POD", "CLUSTER", "SERVERLESS_ENDPOINT", "NETWORK_VOLUME"]
2795
+ }
2796
+ }
2797
+ }
2798
+ },
2242
2799
  {
2243
2800
  name: "get-cluster",
2244
2801
  title: "Get cluster",
@@ -2270,6 +2827,38 @@ var generatedTools = [
2270
2827
  required: ["id"]
2271
2828
  }
2272
2829
  },
2830
+ {
2831
+ name: "get-cost-center",
2832
+ title: "Get cost center",
2833
+ operationId: "getCostCenter",
2834
+ description: "Get a cost center. Returns one cost center. Its attributed resources are listed by `GET /v2/cost-centers/{id}/resources`. Returns 404 when the cost center does not exist or is not the caller's.",
2835
+ method: "GET",
2836
+ path: "/v2/cost-centers/{id}",
2837
+ params: [
2838
+ {
2839
+ name: "id",
2840
+ location: "path"
2841
+ }
2842
+ ],
2843
+ hasBody: false,
2844
+ annotations: {
2845
+ readOnlyHint: true,
2846
+ destructiveHint: false,
2847
+ idempotentHint: true,
2848
+ openWorldHint: true
2849
+ },
2850
+ inputSchema: {
2851
+ type: "object",
2852
+ properties: {
2853
+ id: {
2854
+ type: "string",
2855
+ minLength: 1,
2856
+ description: "Cost center identifier."
2857
+ }
2858
+ },
2859
+ required: ["id"]
2860
+ }
2861
+ },
2273
2862
  {
2274
2863
  name: "get-cpu-type",
2275
2864
  title: "Get CPU type",
@@ -2425,24 +3014,249 @@ var generatedTools = [
2425
3014
  description: "Serverless endpoint identifier"
2426
3015
  }
2427
3016
  },
2428
- required: ["id"]
3017
+ required: ["id"]
3018
+ }
3019
+ },
3020
+ {
3021
+ name: "get-endpoint-build",
3022
+ title: "Get endpoint build",
3023
+ operationId: "getEndpointBuild",
3024
+ description: "Get a serverless endpoint build. Returns one of the endpoint's GitHub builds by id, regardless of age \u2014 no need to page through `GET /v2/serverless/{id}/builds` to reach it.",
3025
+ method: "GET",
3026
+ path: "/v2/serverless/{id}/builds/{buildId}",
3027
+ params: [
3028
+ {
3029
+ name: "id",
3030
+ location: "path"
3031
+ },
3032
+ {
3033
+ name: "buildId",
3034
+ location: "path"
3035
+ }
3036
+ ],
3037
+ hasBody: false,
3038
+ annotations: {
3039
+ readOnlyHint: true,
3040
+ destructiveHint: false,
3041
+ idempotentHint: true,
3042
+ openWorldHint: true
3043
+ },
3044
+ inputSchema: {
3045
+ type: "object",
3046
+ properties: {
3047
+ id: {
3048
+ type: "string",
3049
+ description: "Serverless endpoint identifier"
3050
+ },
3051
+ buildId: {
3052
+ type: "string",
3053
+ description: "GitHub build identifier (from `list-endpoint-builds` or a release's `buildId`)"
3054
+ }
3055
+ },
3056
+ required: ["id", "buildId"]
3057
+ }
3058
+ },
3059
+ {
3060
+ name: "get-endpoint-cold-start-metrics",
3061
+ title: "Get endpoint cold start metrics",
3062
+ operationId: "getEndpointColdStartMetrics",
3063
+ description: "Get serverless endpoint cold start metrics. Returns the cold start series shown on the endpoint's Metrics tab in the console. **Window.** `startTime` is inclusive and `endTime` is exclusive. Both are optional: `endTime` defaults to now and `startTime` to 24 hours before `endTime`, rounded down to the start of an `interval` bucket. An `endTime` in the future is treated as now. Metrics are kept for 90 days, so `startTime` must be within the last 90 days. **Interval.** Each record covers one `interval`-sized bucket, aligned to UTC. **Paging.** Records are oldest first, at most `limit` (default 1000) per page. Follow `pagination.nextCursor` while `pagination.hasNextPage` is true. The cursor keeps the first page's window, so `startTime`, `endTime`, and `interval` can be left out on later pages; if sent, they must match the first page or the cursor is rejected with 422. **Sparse series.** Buckets with no activity are omitted, not zero-filled, so `records` can be shorter than the number of buckets in the window, or empty. **Units.** `durationMs` is how long each cold start took, in milliseconds.",
3064
+ method: "GET",
3065
+ path: "/v2/serverless/{id}/metrics/cold-starts",
3066
+ params: [
3067
+ {
3068
+ name: "id",
3069
+ location: "path"
3070
+ },
3071
+ {
3072
+ name: "startTime",
3073
+ location: "query"
3074
+ },
3075
+ {
3076
+ name: "endTime",
3077
+ location: "query"
3078
+ },
3079
+ {
3080
+ name: "interval",
3081
+ location: "query"
3082
+ },
3083
+ {
3084
+ name: "cursor",
3085
+ location: "query"
3086
+ },
3087
+ {
3088
+ name: "limit",
3089
+ location: "query"
3090
+ }
3091
+ ],
3092
+ hasBody: false,
3093
+ annotations: {
3094
+ readOnlyHint: true,
3095
+ destructiveHint: false,
3096
+ idempotentHint: true,
3097
+ openWorldHint: true
3098
+ },
3099
+ inputSchema: {
3100
+ type: "object",
3101
+ properties: {
3102
+ id: {
3103
+ type: "string",
3104
+ description: "Serverless endpoint identifier"
3105
+ },
3106
+ startTime: {
3107
+ type: "string",
3108
+ format: "date-time",
3109
+ description: "Start of the window (RFC 3339), inclusive. Defaults to 24 hours before endTime, rounded down to the start of an interval bucket. Must be within the last 90 days."
3110
+ },
3111
+ endTime: {
3112
+ type: "string",
3113
+ format: "date-time",
3114
+ description: "End of the window (RFC 3339), exclusive. Defaults to now; a future value is treated as now."
3115
+ },
3116
+ interval: {
3117
+ $ref: "#/$defs/EndpointMetricsInterval",
3118
+ description: "Bucket size. Defaults to 1h.",
3119
+ type: "string"
3120
+ },
3121
+ cursor: {
3122
+ type: "string",
3123
+ minLength: 1,
3124
+ description: "Opaque resume cursor \u2014 pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected."
3125
+ },
3126
+ limit: {
3127
+ type: "integer",
3128
+ minimum: 1,
3129
+ maximum: 1e3,
3130
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
3131
+ }
3132
+ },
3133
+ required: ["id"],
3134
+ $defs: {
3135
+ EndpointMetricsInterval: {
3136
+ type: "string",
3137
+ enum: ["1m", "5m", "15m", "30m", "1h", "6h", "12h", "1d"],
3138
+ default: "1h",
3139
+ description: "Bucket size for endpoint metrics."
3140
+ }
3141
+ }
3142
+ }
3143
+ },
3144
+ {
3145
+ name: "get-endpoint-request-metrics",
3146
+ title: "Get endpoint request metrics",
3147
+ operationId: "getEndpointRequestMetrics",
3148
+ description: "Get serverless endpoint request metrics. Returns the request series shown on the endpoint's Metrics tab in the console. **Window.** `startTime` is inclusive and `endTime` is exclusive. Both are optional: `endTime` defaults to now and `startTime` to 24 hours before `endTime`, rounded down to the start of an `interval` bucket. An `endTime` in the future is treated as now. Metrics are kept for 90 days, so `startTime` must be within the last 90 days. **Interval.** Each record covers one `interval`-sized bucket, aligned to UTC. **Paging.** Records are oldest first, at most `limit` (default 1000) per page. Follow `pagination.nextCursor` while `pagination.hasNextPage` is true. The cursor keeps the first page's window, so `startTime`, `endTime`, and `interval` can be left out on later pages; if sent, they must match the first page or the cursor is rejected with 422. **Sparse series.** Buckets with no activity are omitted, not zero-filled, so `records` can be shorter than the number of buckets in the window, or empty. **Units.** Durations are milliseconds. `executionTimeMs` is the time a worker spent running a request; `delayTimeMs` is the time a request waited in the queue before a worker picked it up.",
3149
+ method: "GET",
3150
+ path: "/v2/serverless/{id}/metrics/requests",
3151
+ params: [
3152
+ {
3153
+ name: "id",
3154
+ location: "path"
3155
+ },
3156
+ {
3157
+ name: "startTime",
3158
+ location: "query"
3159
+ },
3160
+ {
3161
+ name: "endTime",
3162
+ location: "query"
3163
+ },
3164
+ {
3165
+ name: "interval",
3166
+ location: "query"
3167
+ },
3168
+ {
3169
+ name: "cursor",
3170
+ location: "query"
3171
+ },
3172
+ {
3173
+ name: "limit",
3174
+ location: "query"
3175
+ }
3176
+ ],
3177
+ hasBody: false,
3178
+ annotations: {
3179
+ readOnlyHint: true,
3180
+ destructiveHint: false,
3181
+ idempotentHint: true,
3182
+ openWorldHint: true
3183
+ },
3184
+ inputSchema: {
3185
+ type: "object",
3186
+ properties: {
3187
+ id: {
3188
+ type: "string",
3189
+ description: "Serverless endpoint identifier"
3190
+ },
3191
+ startTime: {
3192
+ type: "string",
3193
+ format: "date-time",
3194
+ description: "Start of the window (RFC 3339), inclusive. Defaults to 24 hours before endTime, rounded down to the start of an interval bucket. Must be within the last 90 days."
3195
+ },
3196
+ endTime: {
3197
+ type: "string",
3198
+ format: "date-time",
3199
+ description: "End of the window (RFC 3339), exclusive. Defaults to now; a future value is treated as now."
3200
+ },
3201
+ interval: {
3202
+ $ref: "#/$defs/EndpointMetricsInterval",
3203
+ description: "Bucket size. Defaults to 1h.",
3204
+ type: "string"
3205
+ },
3206
+ cursor: {
3207
+ type: "string",
3208
+ minLength: 1,
3209
+ description: "Opaque resume cursor \u2014 pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected."
3210
+ },
3211
+ limit: {
3212
+ type: "integer",
3213
+ minimum: 1,
3214
+ maximum: 1e3,
3215
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
3216
+ }
3217
+ },
3218
+ required: ["id"],
3219
+ $defs: {
3220
+ EndpointMetricsInterval: {
3221
+ type: "string",
3222
+ enum: ["1m", "5m", "15m", "30m", "1h", "6h", "12h", "1d"],
3223
+ default: "1h",
3224
+ description: "Bucket size for endpoint metrics."
3225
+ }
3226
+ }
2429
3227
  }
2430
3228
  },
2431
3229
  {
2432
- name: "get-endpoint-build",
2433
- title: "Get endpoint build",
2434
- operationId: "getEndpointBuild",
2435
- description: "Get a serverless endpoint build. Returns one of the endpoint's GitHub builds by id, regardless of age \u2014 no need to page through `GET /v2/serverless/{id}/builds` to reach it.",
3230
+ name: "get-endpoint-worker-metrics",
3231
+ title: "Get endpoint worker metrics",
3232
+ operationId: "getEndpointWorkerMetrics",
3233
+ description: "Get serverless endpoint worker metrics. Returns the worker state series shown on the endpoint's Metrics tab in the console. For the current worker list, use `GET /v2/serverless/{id}/workers`. **Window.** `startTime` is inclusive and `endTime` is exclusive. Both are optional: `endTime` defaults to now and `startTime` to 24 hours before `endTime`, rounded down to the start of an `interval` bucket. An `endTime` in the future is treated as now. Metrics are kept for 90 days, so `startTime` must be within the last 90 days. **Interval.** Each record covers one `interval`-sized bucket, aligned to UTC. **Paging.** Records are oldest first, at most `limit` (default 1000) per page. Follow `pagination.nextCursor` while `pagination.hasNextPage` is true. The cursor keeps the first page's window, so `startTime`, `endTime`, and `interval` can be left out on later pages; if sent, they must match the first page or the cursor is rejected with 422. **Sparse series.** Buckets with no activity are omitted, not zero-filled, so `records` can be shorter than the number of buckets in the window, or empty. **Snapshots.** Each record holds the last worker-count snapshot in its bucket, as point-in-time counts.",
2436
3234
  method: "GET",
2437
- path: "/v2/serverless/{id}/builds/{buildId}",
3235
+ path: "/v2/serverless/{id}/metrics/workers",
2438
3236
  params: [
2439
3237
  {
2440
3238
  name: "id",
2441
3239
  location: "path"
2442
3240
  },
2443
3241
  {
2444
- name: "buildId",
2445
- location: "path"
3242
+ name: "startTime",
3243
+ location: "query"
3244
+ },
3245
+ {
3246
+ name: "endTime",
3247
+ location: "query"
3248
+ },
3249
+ {
3250
+ name: "interval",
3251
+ location: "query"
3252
+ },
3253
+ {
3254
+ name: "cursor",
3255
+ location: "query"
3256
+ },
3257
+ {
3258
+ name: "limit",
3259
+ location: "query"
2446
3260
  }
2447
3261
  ],
2448
3262
  hasBody: false,
@@ -2459,12 +3273,42 @@ var generatedTools = [
2459
3273
  type: "string",
2460
3274
  description: "Serverless endpoint identifier"
2461
3275
  },
2462
- buildId: {
3276
+ startTime: {
2463
3277
  type: "string",
2464
- description: "GitHub build identifier (from `list-endpoint-builds` or a release's `buildId`)"
3278
+ format: "date-time",
3279
+ description: "Start of the window (RFC 3339), inclusive. Defaults to 24 hours before endTime, rounded down to the start of an interval bucket. Must be within the last 90 days."
3280
+ },
3281
+ endTime: {
3282
+ type: "string",
3283
+ format: "date-time",
3284
+ description: "End of the window (RFC 3339), exclusive. Defaults to now; a future value is treated as now."
3285
+ },
3286
+ interval: {
3287
+ $ref: "#/$defs/EndpointMetricsInterval",
3288
+ description: "Bucket size. Defaults to 1h.",
3289
+ type: "string"
3290
+ },
3291
+ cursor: {
3292
+ type: "string",
3293
+ minLength: 1,
3294
+ description: "Opaque resume cursor \u2014 pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected."
3295
+ },
3296
+ limit: {
3297
+ type: "integer",
3298
+ minimum: 1,
3299
+ maximum: 1e3,
3300
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
2465
3301
  }
2466
3302
  },
2467
- required: ["id", "buildId"]
3303
+ required: ["id"],
3304
+ $defs: {
3305
+ EndpointMetricsInterval: {
3306
+ type: "string",
3307
+ enum: ["1m", "5m", "15m", "30m", "1h", "6h", "12h", "1d"],
3308
+ default: "1h",
3309
+ description: "Bucket size for endpoint metrics."
3310
+ }
3311
+ }
2468
3312
  }
2469
3313
  },
2470
3314
  {
@@ -2579,7 +3423,7 @@ var generatedTools = [
2579
3423
  },
2580
3424
  cloud: {
2581
3425
  $ref: "#/$defs/GpuCloudFilter",
2582
- description: "Cloud type for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Supported values: SECURE, COMMUNITY. Upstream default when omitted: SECURE.",
3426
+ description: "Cloud type for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Supported values: SECURE, COMMUNITY. Default when omitted: SECURE.",
2583
3427
  type: "string"
2584
3428
  },
2585
3429
  countryCodes: {
@@ -2675,6 +3519,146 @@ var generatedTools = [
2675
3519
  properties: {}
2676
3520
  }
2677
3521
  },
3522
+ {
3523
+ name: "get-organization-group",
3524
+ title: "Get organization group",
3525
+ operationId: "getOrganizationGroup",
3526
+ description: "Get a group in your current organization. Returns the group without its members. Returns 404 when the ID is unknown or belongs to another organization, or when the caller does not belong to an organization.",
3527
+ method: "GET",
3528
+ path: "/v2/organization/groups/{id}",
3529
+ params: [
3530
+ {
3531
+ name: "id",
3532
+ location: "path"
3533
+ }
3534
+ ],
3535
+ hasBody: false,
3536
+ annotations: {
3537
+ readOnlyHint: true,
3538
+ destructiveHint: false,
3539
+ idempotentHint: true,
3540
+ openWorldHint: true
3541
+ },
3542
+ inputSchema: {
3543
+ type: "object",
3544
+ properties: {
3545
+ id: {
3546
+ type: "string",
3547
+ minLength: 1,
3548
+ description: "Group ID."
3549
+ }
3550
+ },
3551
+ required: ["id"]
3552
+ }
3553
+ },
3554
+ {
3555
+ name: "get-organization-invite",
3556
+ title: "Get organization invite",
3557
+ operationId: "getOrganizationInvite",
3558
+ description: "Get a pending organization invite. Returns one pending invitation to the authenticated caller's organization. Only unexpired invites are pending: an invite that has expired, been accepted or been revoked returns 404, as does an ID from another organization. Reading invites requires the organization's invite-management capability, which the built-in admin role holds; other members receive 403. Returns 404 when the caller does not belong to an organization, or 403 when organizations are unavailable to the caller.",
3559
+ method: "GET",
3560
+ path: "/v2/organization/invites/{id}",
3561
+ params: [
3562
+ {
3563
+ name: "id",
3564
+ location: "path"
3565
+ }
3566
+ ],
3567
+ hasBody: false,
3568
+ annotations: {
3569
+ readOnlyHint: true,
3570
+ destructiveHint: false,
3571
+ idempotentHint: true,
3572
+ openWorldHint: true
3573
+ },
3574
+ inputSchema: {
3575
+ type: "object",
3576
+ properties: {
3577
+ id: {
3578
+ type: "string",
3579
+ description: "Invite identifier"
3580
+ }
3581
+ },
3582
+ required: ["id"]
3583
+ }
3584
+ },
3585
+ {
3586
+ name: "get-organization-role",
3587
+ title: "Get organization role",
3588
+ operationId: "getOrganizationRole",
3589
+ description: "Get an organization role. Returns one role a member or invite of the authenticated caller's organization can hold: a built-in role, or one of the organization's custom roles. Returns 404 when the ID is unknown or names another organization's custom role, or when the caller does not belong to an organization; 403 when the caller may not view the organization's roles or organizations are unavailable to the caller.",
3590
+ method: "GET",
3591
+ path: "/v2/organization/roles/{id}",
3592
+ params: [
3593
+ {
3594
+ name: "id",
3595
+ location: "path"
3596
+ }
3597
+ ],
3598
+ hasBody: false,
3599
+ annotations: {
3600
+ readOnlyHint: true,
3601
+ destructiveHint: false,
3602
+ idempotentHint: true,
3603
+ openWorldHint: true
3604
+ },
3605
+ inputSchema: {
3606
+ type: "object",
3607
+ properties: {
3608
+ id: {
3609
+ type: "string",
3610
+ description: "Role identifier"
3611
+ }
3612
+ },
3613
+ required: ["id"]
3614
+ }
3615
+ },
3616
+ {
3617
+ name: "get-organization-role-capabilities",
3618
+ title: "Get organization role capabilities",
3619
+ operationId: "getOrganizationRoleCapabilities",
3620
+ description: "List grantable role capabilities. Returns the capabilities a custom role can grant, grouped by family: each capability is a family and one of its verbs, written `FAMILY:VERB`. This is the set role creation accepts, not filtered to the caller's own access; saving a role also requires the caller to hold every capability it grants. `family` and `verb` narrow the result and apply together; with neither, the whole catalog is returned. Reading the catalog requires organization membership; other callers receive 403.",
3621
+ method: "GET",
3622
+ path: "/v2/organization/roles/capabilities",
3623
+ params: [
3624
+ {
3625
+ name: "family",
3626
+ location: "query",
3627
+ explode: false
3628
+ },
3629
+ {
3630
+ name: "verb",
3631
+ location: "query",
3632
+ explode: false
3633
+ }
3634
+ ],
3635
+ hasBody: false,
3636
+ annotations: {
3637
+ readOnlyHint: true,
3638
+ destructiveHint: false,
3639
+ idempotentHint: true,
3640
+ openWorldHint: true
3641
+ },
3642
+ inputSchema: {
3643
+ type: "object",
3644
+ properties: {
3645
+ family: {
3646
+ type: "array",
3647
+ items: {
3648
+ type: "string"
3649
+ },
3650
+ description: "Only return these capability families, matched exactly. Comma-separated; a family matching any listed value is returned. An empty value is ignored."
3651
+ },
3652
+ verb: {
3653
+ type: "array",
3654
+ items: {
3655
+ type: "string"
3656
+ },
3657
+ description: "Only return these verbs, matched exactly. Comma-separated. Each family lists only the requested verbs it has, and a family with none of them is left out. An empty value is ignored."
3658
+ }
3659
+ }
3660
+ }
3661
+ },
2678
3662
  {
2679
3663
  name: "get-organization-user",
2680
3664
  title: "Get organization user",
@@ -3062,38 +4046,118 @@ var generatedTools = [
3062
4046
  description: "Length of each billing time bucket. Defaults to day.",
3063
4047
  type: "string"
3064
4048
  },
3065
- lastN: {
4049
+ lastN: {
4050
+ type: "integer",
4051
+ minimum: 1,
4052
+ description: 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket \u2014 e.g. lastN=100 with bucketSize=day is "last 100 days".'
4053
+ },
4054
+ clusterId: {
4055
+ type: "string",
4056
+ description: "Filter to a specific cluster."
4057
+ }
4058
+ },
4059
+ $defs: {
4060
+ BillingBucketSize: {
4061
+ type: "string",
4062
+ enum: ["hour", "day", "week", "month", "year"],
4063
+ default: "day",
4064
+ description: "Length of each billing time bucket.",
4065
+ examples: ["day"]
4066
+ }
4067
+ }
4068
+ }
4069
+ },
4070
+ {
4071
+ name: "list-cluster-pods",
4072
+ title: "List cluster Pods",
4073
+ operationId: "listClusterPods",
4074
+ description: "List a cluster's pods. Returns the full member pods of a cluster. The cluster summary (`GET /v2/clusters/{id}`) carries only aggregate pod counts; this endpoint returns each member as a complete Pod object.",
4075
+ method: "GET",
4076
+ path: "/v2/clusters/{id}/pods",
4077
+ params: [
4078
+ {
4079
+ name: "id",
4080
+ location: "path"
4081
+ }
4082
+ ],
4083
+ hasBody: false,
4084
+ annotations: {
4085
+ readOnlyHint: true,
4086
+ destructiveHint: false,
4087
+ idempotentHint: true,
4088
+ openWorldHint: true
4089
+ },
4090
+ inputSchema: {
4091
+ type: "object",
4092
+ properties: {
4093
+ id: {
4094
+ type: "string",
4095
+ description: "Cluster identifier"
4096
+ }
4097
+ },
4098
+ required: ["id"]
4099
+ }
4100
+ },
4101
+ {
4102
+ name: "list-clusters",
4103
+ title: "List clusters",
4104
+ operationId: "listClusters",
4105
+ description: "List clusters. Returns clusters owned by the authenticated user, cursor-paginated newest-first; an omitted `limit` defaults to 1000. Follow `pagination.nextCursor` until `hasNextPage` is false.",
4106
+ method: "GET",
4107
+ path: "/v2/clusters",
4108
+ params: [
4109
+ {
4110
+ name: "cursor",
4111
+ location: "query"
4112
+ },
4113
+ {
4114
+ name: "limit",
4115
+ location: "query"
4116
+ }
4117
+ ],
4118
+ hasBody: false,
4119
+ annotations: {
4120
+ readOnlyHint: true,
4121
+ destructiveHint: false,
4122
+ idempotentHint: true,
4123
+ openWorldHint: true
4124
+ },
4125
+ inputSchema: {
4126
+ type: "object",
4127
+ properties: {
4128
+ cursor: {
4129
+ type: "string",
4130
+ minLength: 1,
4131
+ description: "Opaque resume cursor \u2014 pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected."
4132
+ },
4133
+ limit: {
3066
4134
  type: "integer",
3067
4135
  minimum: 1,
3068
- description: 'Return the last N buckets of bucketSize, ending with the current (in-progress) bucket \u2014 e.g. lastN=100 with bucketSize=day is "last 100 days".'
3069
- },
3070
- clusterId: {
3071
- type: "string",
3072
- description: "Filter to a specific cluster."
3073
- }
3074
- },
3075
- $defs: {
3076
- BillingBucketSize: {
3077
- type: "string",
3078
- enum: ["hour", "day", "week", "month", "year"],
3079
- default: "day",
3080
- description: "Length of each billing time bucket.",
3081
- examples: ["day"]
4136
+ maximum: 1e3,
4137
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
3082
4138
  }
3083
4139
  }
3084
4140
  }
3085
4141
  },
3086
4142
  {
3087
- name: "list-cluster-pods",
3088
- title: "List cluster Pods",
3089
- operationId: "listClusterPods",
3090
- description: "List a cluster's pods. Returns the full member pods of a cluster. The cluster summary (`GET /v2/clusters/{id}`) carries only aggregate pod counts; this endpoint returns each member as a complete Pod object.",
4143
+ name: "list-cost-center-resources",
4144
+ title: "List cost center resources",
4145
+ operationId: "listCostCenterResources",
4146
+ description: "List a cost center's resources. Returns the resources attributed to one cost center, cursor-paginated; an omitted `limit` defaults to 1000. Each entry is the `{type}/{id}` pair `DELETE /v2/cost-centers/{id}/{resourceType}/{resourceId}` takes. A cost center with nothing attributed returns an empty list; one that does not exist or is not the caller's returns 404.",
3091
4147
  method: "GET",
3092
- path: "/v2/clusters/{id}/pods",
4148
+ path: "/v2/cost-centers/{id}/resources",
3093
4149
  params: [
3094
4150
  {
3095
4151
  name: "id",
3096
4152
  location: "path"
4153
+ },
4154
+ {
4155
+ name: "cursor",
4156
+ location: "query"
4157
+ },
4158
+ {
4159
+ name: "limit",
4160
+ location: "query"
3097
4161
  }
3098
4162
  ],
3099
4163
  hasBody: false,
@@ -3108,20 +4172,36 @@ var generatedTools = [
3108
4172
  properties: {
3109
4173
  id: {
3110
4174
  type: "string",
3111
- description: "Cluster identifier"
4175
+ minLength: 1,
4176
+ description: "Cost center identifier."
4177
+ },
4178
+ cursor: {
4179
+ type: "string",
4180
+ minLength: 1,
4181
+ description: "Opaque resume cursor \u2014 pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected."
4182
+ },
4183
+ limit: {
4184
+ type: "integer",
4185
+ minimum: 1,
4186
+ maximum: 1e3,
4187
+ description: "Page size, 1\u20131000. Defaults to 1000 when omitted."
3112
4188
  }
3113
4189
  },
3114
4190
  required: ["id"]
3115
4191
  }
3116
4192
  },
3117
4193
  {
3118
- name: "list-clusters",
3119
- title: "List clusters",
3120
- operationId: "listClusters",
3121
- description: "List clusters. Returns clusters owned by the authenticated user, cursor-paginated newest-first; an omitted `limit` defaults to 1000. Follow `pagination.nextCursor` until `hasNextPage` is false.",
4194
+ name: "list-cost-centers",
4195
+ title: "List cost centers",
4196
+ operationId: "listCostCenters",
4197
+ description: "List cost centers. Returns the caller's cost centers, cursor-paginated newest-first; an omitted `limit` defaults to 1000. Follow `pagination.nextCursor` until `hasNextPage` is false.",
3122
4198
  method: "GET",
3123
- path: "/v2/clusters",
4199
+ path: "/v2/cost-centers",
3124
4200
  params: [
4201
+ {
4202
+ name: "search",
4203
+ location: "query"
4204
+ },
3125
4205
  {
3126
4206
  name: "cursor",
3127
4207
  location: "query"
@@ -3141,6 +4221,11 @@ var generatedTools = [
3141
4221
  inputSchema: {
3142
4222
  type: "object",
3143
4223
  properties: {
4224
+ search: {
4225
+ type: "string",
4226
+ minLength: 1,
4227
+ description: "Case-insensitive substring match against `value`."
4228
+ },
3144
4229
  cursor: {
3145
4230
  type: "string",
3146
4231
  minLength: 1,
@@ -3685,7 +4770,7 @@ var generatedTools = [
3685
4770
  },
3686
4771
  cloud: {
3687
4772
  $ref: "#/$defs/GpuCloudFilter",
3688
- description: "Cloud type for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Supported values: SECURE, COMMUNITY. Upstream default when omitted: SECURE.",
4773
+ description: "Cloud type for availability and lowest-price calculations. Valid only with include=AVAILABILITY. Supported values: SECURE, COMMUNITY. Default when omitted: SECURE.",
3689
4774
  type: "string"
3690
4775
  },
3691
4776
  countryCodes: {
@@ -3845,6 +4930,146 @@ var generatedTools = [
3845
4930
  }
3846
4931
  }
3847
4932
  },
4933
+ {
4934
+ name: "list-organization-group-members",
4935
+ title: "List organization group members",
4936
+ operationId: "listOrganizationGroupMembers",
4937
+ description: "List members of a group. Members are ordered newest first by membership creation time, with a unique upstream tie-breaker. Returns 404 when the group does not exist in the current organization, or when the caller does not belong to an organization.",
4938
+ method: "GET",
4939
+ path: "/v2/organization/groups/{id}/members",
4940
+ params: [
4941
+ {
4942
+ name: "id",
4943
+ location: "path"
4944
+ },
4945
+ {
4946
+ name: "cursor",
4947
+ location: "query"
4948
+ },
4949
+ {
4950
+ name: "limit",
4951
+ location: "query"
4952
+ }
4953
+ ],
4954
+ hasBody: false,
4955
+ annotations: {
4956
+ readOnlyHint: true,
4957
+ destructiveHint: false,
4958
+ idempotentHint: true,
4959
+ openWorldHint: true
4960
+ },
4961
+ inputSchema: {
4962
+ type: "object",
4963
+ properties: {
4964
+ id: {
4965
+ type: "string",
4966
+ minLength: 1,
4967
+ description: "Group ID."
4968
+ },
4969
+ cursor: {
4970
+ type: "string",
4971
+ minLength: 1,
4972
+ description: "Opaque resume cursor \u2014 pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected."
4973
+ },
4974
+ limit: {
4975
+ type: "integer",
4976
+ minimum: 1,
4977
+ maximum: 100,
4978
+ description: "Page size, 1\u2013100. Defaults to 100 when omitted."
4979
+ }
4980
+ },
4981
+ required: ["id"]
4982
+ }
4983
+ },
4984
+ {
4985
+ name: "list-organization-groups",
4986
+ title: "List organization groups",
4987
+ operationId: "listOrganizationGroups",
4988
+ description: "List groups in your current organization. Returns groups without their members or roles, ordered by creation time descending and then ID descending for deterministic pagination.",
4989
+ method: "GET",
4990
+ path: "/v2/organization/groups",
4991
+ params: [
4992
+ {
4993
+ name: "name",
4994
+ location: "query"
4995
+ },
4996
+ {
4997
+ name: "cursor",
4998
+ location: "query"
4999
+ },
5000
+ {
5001
+ name: "limit",
5002
+ location: "query"
5003
+ }
5004
+ ],
5005
+ hasBody: false,
5006
+ annotations: {
5007
+ readOnlyHint: true,
5008
+ destructiveHint: false,
5009
+ idempotentHint: true,
5010
+ openWorldHint: true
5011
+ },
5012
+ inputSchema: {
5013
+ type: "object",
5014
+ properties: {
5015
+ name: {
5016
+ type: "string",
5017
+ description: "Optional case-insensitive substring of the group name. An empty value applies no filter."
5018
+ },
5019
+ cursor: {
5020
+ type: "string",
5021
+ minLength: 1,
5022
+ description: "Opaque resume cursor \u2014 pass the previous response's `pagination.nextCursor` through verbatim; omit for the first page. A cursor is only valid for the operation and parameters that issued it; a malformed or foreign cursor is rejected."
5023
+ },
5024
+ limit: {
5025
+ type: "integer",
5026
+ minimum: 1,
5027
+ maximum: 100,
5028
+ description: "Page size, 1\u2013100. Defaults to 100 when omitted."
5029
+ }
5030
+ }
5031
+ }
5032
+ },
5033
+ {
5034
+ name: "list-organization-invites",
5035
+ title: "List organization invites",
5036
+ operationId: "listOrganizationInvites",
5037
+ description: "List pending organization invites. Returns the pending invitations to the authenticated caller's organization, newest first. Only unexpired invites are pending: an invite leaves the list once it is accepted, revoked or expired. The list is complete and takes no pagination parameters, because an organization's pending invites are capped. Reading invites requires the organization's invite-management capability, which the built-in admin role holds; other members receive 403. Returns 404 when the caller does not belong to an organization, or 403 when organizations are unavailable to the caller.",
5038
+ method: "GET",
5039
+ path: "/v2/organization/invites",
5040
+ params: [],
5041
+ hasBody: false,
5042
+ annotations: {
5043
+ readOnlyHint: true,
5044
+ destructiveHint: false,
5045
+ idempotentHint: true,
5046
+ openWorldHint: true
5047
+ },
5048
+ inputSchema: {
5049
+ type: "object",
5050
+ properties: {}
5051
+ }
5052
+ },
5053
+ {
5054
+ name: "list-organization-roles",
5055
+ title: "List organization roles",
5056
+ operationId: "listOrganizationRoles",
5057
+ description: "List organization roles. Returns every role a member or invite of the authenticated caller's organization can hold: Runpod's built-in roles and the organization's custom roles, oldest first. The list is complete and takes no pagination parameters, because an organization's custom roles are capped. Returns 404 when the caller does not belong to an organization, or 403 when organizations are unavailable to the caller.",
5058
+ method: "GET",
5059
+ path: "/v2/organization/roles",
5060
+ params: [],
5061
+ hasBody: false,
5062
+ annotations: {
5063
+ readOnlyHint: true,
5064
+ destructiveHint: false,
5065
+ idempotentHint: true,
5066
+ openWorldHint: true
5067
+ },
5068
+ inputSchema: {
5069
+ type: "object",
5070
+ properties: {}
5071
+ }
5072
+ },
3848
5073
  {
3849
5074
  name: "list-organization-users",
3850
5075
  title: "List organization users",
@@ -4199,6 +5424,47 @@ var generatedTools = [
4199
5424
  }
4200
5425
  }
4201
5426
  },
5427
+ {
5428
+ name: "remove-organization-group-member",
5429
+ title: "Remove organization group member",
5430
+ operationId: "removeOrganizationGroupMember",
5431
+ description: "Remove a member from a group. Removes the organization member from the group. The group and user must belong to the current organization. Returns 404 when the membership is absent, including repeated deletion, or when the group is unknown or belongs to another organization.",
5432
+ method: "DELETE",
5433
+ path: "/v2/organization/groups/{id}/members/{userId}",
5434
+ params: [
5435
+ {
5436
+ name: "id",
5437
+ location: "path"
5438
+ },
5439
+ {
5440
+ name: "userId",
5441
+ location: "path"
5442
+ }
5443
+ ],
5444
+ hasBody: false,
5445
+ annotations: {
5446
+ readOnlyHint: false,
5447
+ destructiveHint: true,
5448
+ idempotentHint: true,
5449
+ openWorldHint: true
5450
+ },
5451
+ inputSchema: {
5452
+ type: "object",
5453
+ properties: {
5454
+ id: {
5455
+ type: "string",
5456
+ minLength: 1,
5457
+ description: "Group ID."
5458
+ },
5459
+ userId: {
5460
+ type: "string",
5461
+ minLength: 1,
5462
+ description: "Organization member user ID."
5463
+ }
5464
+ },
5465
+ required: ["id", "userId"]
5466
+ }
5467
+ },
4202
5468
  {
4203
5469
  name: "revoke-delegation",
4204
5470
  title: "Revoke ECR delegation",
@@ -4230,12 +5496,62 @@ var generatedTools = [
4230
5496
  }
4231
5497
  },
4232
5498
  {
4233
- name: "update-cluster",
4234
- title: "Update cluster",
4235
- operationId: "updateCluster",
4236
- description: "Rename a cluster. Renames a cluster. This endpoint only changes the cluster name \u2014 compute shape, type, and container configuration are fixed at creation and cannot be updated.",
5499
+ name: "update-cluster",
5500
+ title: "Update cluster",
5501
+ operationId: "updateCluster",
5502
+ description: "Rename a cluster. Renames a cluster. This endpoint only changes the cluster name \u2014 compute shape, type, and container configuration are fixed at creation and cannot be updated.",
5503
+ method: "PATCH",
5504
+ path: "/v2/clusters/{id}",
5505
+ params: [
5506
+ {
5507
+ name: "id",
5508
+ location: "path"
5509
+ }
5510
+ ],
5511
+ hasBody: true,
5512
+ annotations: {
5513
+ readOnlyHint: false,
5514
+ destructiveHint: false,
5515
+ idempotentHint: true,
5516
+ openWorldHint: true
5517
+ },
5518
+ inputSchema: {
5519
+ type: "object",
5520
+ properties: {
5521
+ id: {
5522
+ type: "string",
5523
+ description: "Cluster identifier"
5524
+ },
5525
+ body: {
5526
+ $ref: "#/$defs/UpdateClusterRequest",
5527
+ type: "object"
5528
+ }
5529
+ },
5530
+ required: ["id", "body"],
5531
+ $defs: {
5532
+ UpdateClusterRequest: {
5533
+ type: "object",
5534
+ additionalProperties: false,
5535
+ minProperties: 1,
5536
+ description: "Request body for updating a cluster. Only the cluster name can be changed \u2014 this endpoint is a rename. Compute shape, type, and container configuration are fixed at creation.",
5537
+ properties: {
5538
+ name: {
5539
+ type: "string",
5540
+ minLength: 1,
5541
+ examples: ["renamed-cluster"]
5542
+ }
5543
+ }
5544
+ }
5545
+ }
5546
+ }
5547
+ },
5548
+ {
5549
+ name: "update-cost-center",
5550
+ title: "Update cost center",
5551
+ operationId: "updateCostCenter",
5552
+ description: "Rename a cost center. Renames a cost center. Resources attributed to it are unaffected and follow the new name \u2014 the attribution is by identifier, not by name.",
4237
5553
  method: "PATCH",
4238
- path: "/v2/clusters/{id}",
5554
+ path: "/v2/cost-centers/{id}",
4239
5555
  params: [
4240
5556
  {
4241
5557
  name: "id",
@@ -4254,25 +5570,28 @@ var generatedTools = [
4254
5570
  properties: {
4255
5571
  id: {
4256
5572
  type: "string",
4257
- description: "Cluster identifier"
5573
+ minLength: 1,
5574
+ description: "Cost center identifier."
4258
5575
  },
4259
5576
  body: {
4260
- $ref: "#/$defs/UpdateClusterRequest",
5577
+ $ref: "#/$defs/UpdateCostCenterRequest",
4261
5578
  type: "object"
4262
5579
  }
4263
5580
  },
4264
5581
  required: ["id", "body"],
4265
5582
  $defs: {
4266
- UpdateClusterRequest: {
5583
+ UpdateCostCenterRequest: {
4267
5584
  type: "object",
4268
5585
  additionalProperties: false,
4269
- minProperties: 1,
4270
- description: "Request body for updating a cluster. Only the cluster name can be changed \u2014 this endpoint is a rename. Compute shape, type, and container configuration are fixed at creation.",
5586
+ required: ["value"],
4271
5587
  properties: {
4272
- name: {
5588
+ value: {
4273
5589
  type: "string",
4274
5590
  minLength: 1,
4275
- examples: ["renamed-cluster"]
5591
+ maxLength: 50,
5592
+ pattern: "^\\s*\\S",
5593
+ description: "Leading and trailing whitespace is trimmed.",
5594
+ examples: ["team-ml-eu"]
4276
5595
  }
4277
5596
  }
4278
5597
  }
@@ -4716,6 +6035,7 @@ var generatedTools = [
4716
6035
  type: "string",
4717
6036
  minLength: 1,
4718
6037
  maxLength: 191,
6038
+ pattern: "[^\\t-\\r \x85\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]",
4719
6039
  description: "New human-readable name, 1\u2013191 characters with at least one non-whitespace character. Leading and trailing whitespace is trimmed.",
4720
6040
  examples: ["renamed-volume"]
4721
6041
  }
@@ -4782,11 +6102,218 @@ var generatedTools = [
4782
6102
  }
4783
6103
  }
4784
6104
  },
6105
+ {
6106
+ name: "update-organization-group",
6107
+ title: "Update organization group",
6108
+ operationId: "updateOrganizationGroup",
6109
+ description: "Rename a group in your current organization",
6110
+ method: "PATCH",
6111
+ path: "/v2/organization/groups/{id}",
6112
+ params: [
6113
+ {
6114
+ name: "id",
6115
+ location: "path"
6116
+ }
6117
+ ],
6118
+ hasBody: true,
6119
+ annotations: {
6120
+ readOnlyHint: false,
6121
+ destructiveHint: false,
6122
+ idempotentHint: true,
6123
+ openWorldHint: true
6124
+ },
6125
+ inputSchema: {
6126
+ type: "object",
6127
+ properties: {
6128
+ id: {
6129
+ type: "string",
6130
+ minLength: 1,
6131
+ description: "Group ID."
6132
+ },
6133
+ body: {
6134
+ $ref: "#/$defs/UpdateOrganizationGroupRequest",
6135
+ type: "object"
6136
+ }
6137
+ },
6138
+ required: ["id", "body"],
6139
+ $defs: {
6140
+ UpdateOrganizationGroupRequest: {
6141
+ type: "object",
6142
+ additionalProperties: false,
6143
+ required: ["name"],
6144
+ properties: {
6145
+ name: {
6146
+ type: "string",
6147
+ minLength: 1,
6148
+ maxLength: 191,
6149
+ pattern: "[^\\t-\\r \x85\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]",
6150
+ description: "Group name with at least one non-whitespace character; surrounding whitespace is trimmed.",
6151
+ examples: ["Research"]
6152
+ }
6153
+ }
6154
+ }
6155
+ }
6156
+ }
6157
+ },
6158
+ {
6159
+ name: "update-organization-role",
6160
+ title: "Update organization role",
6161
+ operationId: "updateOrganizationRole",
6162
+ description: "Update a custom organization role. Changes a custom role's name, its capabilities, or both, and returns the role. Sent capabilities replace the whole grant set. Returns 400 for a built-in role, which cannot be changed; 404 when the ID is unknown or names another organization's role; 403 when the caller does not hold every capability the role grants, before or after the change; 409 when the organization already has a role with the new name; and 422 when a capability is unknown or the name is reserved. Updating roles requires the organization's role-management capability, which the built-in admin role holds; other members, and callers outside an organization, receive 403, as does a caller for whom organizations are unavailable.",
6163
+ method: "PATCH",
6164
+ path: "/v2/organization/roles/{id}",
6165
+ params: [
6166
+ {
6167
+ name: "id",
6168
+ location: "path"
6169
+ }
6170
+ ],
6171
+ hasBody: true,
6172
+ annotations: {
6173
+ readOnlyHint: false,
6174
+ destructiveHint: true,
6175
+ idempotentHint: true,
6176
+ openWorldHint: true
6177
+ },
6178
+ inputSchema: {
6179
+ type: "object",
6180
+ properties: {
6181
+ id: {
6182
+ type: "string",
6183
+ description: "Role identifier"
6184
+ },
6185
+ body: {
6186
+ $ref: "#/$defs/UpdateOrganizationRoleRequest",
6187
+ type: "object"
6188
+ }
6189
+ },
6190
+ required: ["id", "body"],
6191
+ $defs: {
6192
+ OrganizationRoleCapabilitiesInput: {
6193
+ type: "array",
6194
+ description: "What the role grants, as `FAMILY:VERB` capabilities from `get-organization-role-capabilities`. The caller must hold every capability it lists.",
6195
+ minItems: 1,
6196
+ uniqueItems: true,
6197
+ items: {
6198
+ type: "string",
6199
+ pattern: "^[A-Z0-9_]+:[A-Z0-9_]+$"
6200
+ },
6201
+ examples: [["POD:VIEW"]]
6202
+ },
6203
+ OrganizationRoleName: {
6204
+ type: "string",
6205
+ minLength: 1,
6206
+ maxLength: 191,
6207
+ pattern: "[^\\t-\\r \x85\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]",
6208
+ description: "Display name, 1\u2013191 characters with at least one non-whitespace character. Leading and trailing whitespace is trimmed. It must be unique within the organization and cannot be a built-in role's name.",
6209
+ examples: ["Pod viewer"]
6210
+ },
6211
+ UpdateOrganizationRoleRequest: {
6212
+ type: "object",
6213
+ additionalProperties: false,
6214
+ minProperties: 1,
6215
+ description: "The fields to change; omitted fields are unchanged. `capabilities` replaces the role's whole grant set rather than adding to it.",
6216
+ properties: {
6217
+ name: {
6218
+ $ref: "#/$defs/OrganizationRoleName"
6219
+ },
6220
+ capabilities: {
6221
+ $ref: "#/$defs/OrganizationRoleCapabilitiesInput"
6222
+ }
6223
+ }
6224
+ }
6225
+ }
6226
+ }
6227
+ },
6228
+ {
6229
+ name: "update-organization-user",
6230
+ title: "Update organization user",
6231
+ operationId: "updateOrganizationUser",
6232
+ description: "Update an organization member. Changes one member of the authenticated caller's organization by user ID: assigns a role, replaces their set of groups, or both, applied together or not at all. Send at least one field; an omitted field is left as it is, and an empty `groups` list removes the member from every group. Updating members requires the organization's member-management capability, which the built-in admin role holds; other members, and callers outside an organization, receive 403, as does a caller for whom organizations are unavailable. Returns 403 when the caller changes their own role or assigns a role granting a capability the caller lacks; 409 when the change would leave the organization without a member in the built-in admin role; and 404 when the user is not a member or the role or a group is unknown to the organization, with the detail naming which.",
6233
+ method: "PATCH",
6234
+ path: "/v2/organization/users/{id}",
6235
+ params: [
6236
+ {
6237
+ name: "id",
6238
+ location: "path"
6239
+ }
6240
+ ],
6241
+ hasBody: true,
6242
+ annotations: {
6243
+ readOnlyHint: false,
6244
+ destructiveHint: true,
6245
+ idempotentHint: true,
6246
+ openWorldHint: true
6247
+ },
6248
+ inputSchema: {
6249
+ type: "object",
6250
+ properties: {
6251
+ id: {
6252
+ type: "string",
6253
+ description: "User identifier"
6254
+ },
6255
+ body: {
6256
+ $ref: "#/$defs/UpdateOrganizationUserRequest",
6257
+ type: "object"
6258
+ }
6259
+ },
6260
+ required: ["id", "body"],
6261
+ $defs: {
6262
+ OrganizationGroupInput: {
6263
+ type: "object",
6264
+ description: "An organization group, by ID.",
6265
+ additionalProperties: false,
6266
+ required: ["id"],
6267
+ properties: {
6268
+ id: {
6269
+ type: "string",
6270
+ minLength: 1,
6271
+ description: "Group ID.",
6272
+ examples: ["group_id_abc_123"]
6273
+ }
6274
+ }
6275
+ },
6276
+ OrganizationRoleInput: {
6277
+ type: "object",
6278
+ description: "An organization role to assign, by ID.",
6279
+ additionalProperties: false,
6280
+ required: ["id"],
6281
+ properties: {
6282
+ id: {
6283
+ type: "string",
6284
+ minLength: 1,
6285
+ description: "Role ID, as reported on a member or an invite: `builtin:admin`, `builtin:dev`, `builtin:billing`, `builtin:basic`, or a custom role's own ID.",
6286
+ examples: ["builtin:dev"]
6287
+ }
6288
+ }
6289
+ },
6290
+ UpdateOrganizationUserRequest: {
6291
+ type: "object",
6292
+ description: "Changes to a member. Send `role`, `groups`, or both; an omitted field is left as it is.",
6293
+ additionalProperties: false,
6294
+ minProperties: 1,
6295
+ properties: {
6296
+ role: {
6297
+ $ref: "#/$defs/OrganizationRoleInput"
6298
+ },
6299
+ groups: {
6300
+ type: "array",
6301
+ description: "The member's groups after the change: the whole set, by ID. An empty list removes the member from every group.",
6302
+ uniqueItems: true,
6303
+ items: {
6304
+ $ref: "#/$defs/OrganizationGroupInput"
6305
+ }
6306
+ }
6307
+ }
6308
+ }
6309
+ }
6310
+ }
6311
+ },
4785
6312
  {
4786
6313
  name: "update-pod",
4787
6314
  title: "Update Pod",
4788
6315
  operationId: "updatePod",
4789
- description: "Update a pod. Partially updates a pod's configuration. This is a PATCH: only the fields present in the body are changed, and omitted fields are left untouched. Use empty values only when you explicitly mean to clear a field (for example, set `registry` to `null` or set `ports` to `[]`). See `UpdatePodRequest` for the full body. Mutable fields: `name`, `image`, `args`, `disk`, `ports`, `env`, `registry`, `mounts`, `locked`, and `globalNetworking`. Some changes apply immediately while others (e.g. `globalNetworking`) take effect on the pod's next start/restart, as noted on the individual fields. Pods that belong to a Cluster cannot be updated here \u2014 manage them through `/v2/clusters/{id}`. Returns `200` with the full updated pod.",
6316
+ description: "Update a pod. Partially updates a pod's configuration. This is a PATCH: only the fields present in the body are changed, and omitted fields are left untouched. Use empty values only when you explicitly mean to clear a field (for example, set `registry` to `null` or set `ports` to `[]`). See `UpdatePodRequest` for the full body. Mutable fields: `name`, `image`, `args`, `disk`, `ports`, `env`, `registry`, `mounts`, `locked`, and `globalNetworking`. Some changes apply immediately while others (e.g. `globalNetworking`) take effect on the pod's next start/restart, as noted on the individual fields. Volumes can be mounted, moved, or unmounted after creation through `mounts`, one entry per volume; see `UpdatePodMounts` for the rules. Pods that belong to a Cluster cannot be updated here \u2014 manage them through `/v2/clusters/{id}`. Returns `200` with the full updated pod.",
4790
6317
  method: "PATCH",
4791
6318
  path: "/v2/pods/{id}",
4792
6319
  params: [
@@ -4880,21 +6407,6 @@ var generatedTools = [
4880
6407
  }
4881
6408
  }
4882
6409
  },
4883
- BaseMounts: {
4884
- type: "object",
4885
- properties: {
4886
- persistent: {
4887
- $ref: "#/$defs/PersistentMount"
4888
- },
4889
- network: {
4890
- type: "array",
4891
- maxItems: 1,
4892
- items: {
4893
- $ref: "#/$defs/NetworkMount"
4894
- }
4895
- }
4896
- }
4897
- },
4898
6410
  ContainerConfig: {
4899
6411
  allOf: [
4900
6412
  {
@@ -4912,11 +6424,11 @@ var generatedTools = [
4912
6424
  }
4913
6425
  ]
4914
6426
  },
4915
- GlobalMount: {
6427
+ GlobalMountPatch: {
4916
6428
  type: "object",
4917
6429
  required: ["volumeId"],
4918
6430
  additionalProperties: false,
4919
- description: "Reference to a GlobalVolume. Usage-billed, so it has no size. The underlying `volumeId` is immutable post-create; the mount `path` may be changed via PATCH.",
6431
+ description: "Mounts, moves, or unmounts the pod's global volume.",
4920
6432
  properties: {
4921
6433
  volumeId: {
4922
6434
  type: "string",
@@ -4925,38 +6437,21 @@ var generatedTools = [
4925
6437
  },
4926
6438
  path: {
4927
6439
  type: "string",
4928
- description: "Mount path inside the container. Optional on create, where a default is chosen for you; a PATCH that omits it leaves the path unchanged.",
6440
+ minLength: 1,
6441
+ description: "Mount path inside the container. Optional; when mounting, a default is chosen for you if omitted.",
4929
6442
  examples: ["/data"]
4930
- }
4931
- }
4932
- },
4933
- Mounts: {
4934
- description: "Storage mounts for the pod: `persistent` (size + path) excludes both `network` and `global`; `network` (volumeId + path) and `global` (volumeId, optional path) take one entry each and can be combined. Every entry needs its full shape. On update, omit the field to leave the mounts as they are; the mount kind and a volume's volumeId cannot change, and mounts cannot be cleared.",
4935
- allOf: [
4936
- {
4937
- $ref: "#/$defs/BaseMounts"
4938
6443
  },
4939
- {
4940
- type: "object",
4941
- properties: {
4942
- global: {
4943
- type: "array",
4944
- maxItems: 1,
4945
- description: "At most one global volume, on GPU and CPU pods, with no data center constraint. Combinable with `network` but not with `persistent` (rejected): upstream drops a persistent disk whenever a volume is attached.",
4946
- items: {
4947
- $ref: "#/$defs/GlobalMount"
4948
- }
4949
- }
4950
- }
6444
+ remove: {
6445
+ type: "boolean",
6446
+ description: "Unmount the volume. Cannot be combined with `path`."
4951
6447
  }
4952
- ],
4953
- unevaluatedProperties: false
6448
+ }
4954
6449
  },
4955
- NetworkMount: {
6450
+ NetworkMountPatch: {
4956
6451
  type: "object",
4957
- required: ["volumeId", "path"],
6452
+ required: ["volumeId"],
4958
6453
  additionalProperties: false,
4959
- description: "Reference to a NetworkVolume. Custom paths are honored at runtime on both GPU and CPU pods. The underlying `volumeId` is immutable post-create; the mount `path` may be changed via PATCH.",
6454
+ description: "Mounts, moves, or unmounts one network volume. Mounting a volume the pod does not have requires `path`.",
4960
6455
  properties: {
4961
6456
  volumeId: {
4962
6457
  type: "string",
@@ -4965,27 +6460,62 @@ var generatedTools = [
4965
6460
  },
4966
6461
  path: {
4967
6462
  type: "string",
4968
- description: "Mount path inside the container. No default \u2014 must be specified explicitly.",
6463
+ minLength: 1,
6464
+ description: "Mount path inside the container. Required when mounting; optional when moving a mounted volume.",
4969
6465
  examples: ["/runpod-volume"]
6466
+ },
6467
+ remove: {
6468
+ type: "boolean",
6469
+ description: "Unmount the volume. Cannot be combined with `path`."
4970
6470
  }
4971
6471
  }
4972
6472
  },
4973
- PersistentMount: {
6473
+ PersistentMountPatch: {
4974
6474
  type: "object",
4975
- required: ["size", "path"],
4976
6475
  additionalProperties: false,
4977
- description: "Host-local persistent storage. Pinned to the pod's host machine \u2014 data does not survive a host failure. Disallowed on CPU pods. Mutually exclusive with NetworkMount. Deprecated: prefer NetworkMount for any data you cannot recreate.",
6476
+ description: "Adds the pod's volume disk, grows it, or moves it. Adding a disk requires `size`; on a pod that already has one, omitted fields are left as they are. Not available on CPU pods.",
4978
6477
  properties: {
4979
6478
  size: {
4980
6479
  type: "integer",
4981
6480
  minimum: 10,
4982
- description: "Host-local persistent storage in GB. Upstream enforces a 10 GB floor.",
4983
- examples: [20]
6481
+ description: "Volume disk size in GB. Can only grow; a smaller size than the current one is rejected.",
6482
+ examples: [50]
4984
6483
  },
4985
6484
  path: {
4986
6485
  type: "string",
4987
- description: "Mount path inside the container. May be changed via PATCH.",
6486
+ minLength: 1,
6487
+ description: "Mount path inside the container.",
4988
6488
  examples: ["/workspace"]
6489
+ },
6490
+ remove: {
6491
+ type: "boolean",
6492
+ description: "Removes the volume disk. Not supported yet: `remove: true` is rejected."
6493
+ }
6494
+ }
6495
+ },
6496
+ UpdatePodMounts: {
6497
+ type: "object",
6498
+ additionalProperties: false,
6499
+ description: "Changes to a pod's mounts. Each entry names one volume by `volumeId` and changes only that volume; volumes that are not listed, and kinds that are omitted, are left as they are. Omitting `mounts` or sending `{}` changes nothing.",
6500
+ properties: {
6501
+ persistent: {
6502
+ $ref: "#/$defs/PersistentMountPatch"
6503
+ },
6504
+ network: {
6505
+ type: "array",
6506
+ maxItems: 8,
6507
+ description: "Network volumes to mount, move, or unmount. Up to 8 entries, so a request can unmount 4 volumes and mount 4 others; the pod can still hold at most 4 afterwards.",
6508
+ items: {
6509
+ $ref: "#/$defs/NetworkMountPatch"
6510
+ }
6511
+ },
6512
+ global: {
6513
+ type: "array",
6514
+ maxItems: 2,
6515
+ description: "Global volumes to mount, move, or unmount. Up to 2 entries, so a request can swap the global volume; the pod can still hold at most 1 afterwards.",
6516
+ items: {
6517
+ $ref: "#/$defs/GlobalMountPatch"
6518
+ }
4989
6519
  }
4990
6520
  }
4991
6521
  },
@@ -5006,7 +6536,7 @@ var generatedTools = [
5006
6536
  description: "Lock the pod (true) or unlock it (false). Locked pods cannot be stopped or reset."
5007
6537
  },
5008
6538
  mounts: {
5009
- $ref: "#/$defs/Mounts"
6539
+ $ref: "#/$defs/UpdatePodMounts"
5010
6540
  },
5011
6541
  name: {
5012
6542
  type: "string",
@@ -5253,7 +6783,7 @@ var generatedTools = [
5253
6783
  size: {
5254
6784
  type: "integer",
5255
6785
  minimum: 10,
5256
- description: "Host-local persistent storage in GB. Upstream enforces a 10 GB floor.",
6786
+ description: "Host-local persistent storage in GB. Minimum 10 GB.",
5257
6787
  examples: [20]
5258
6788
  },
5259
6789
  path: {
@@ -5514,33 +7044,53 @@ var CREDENTIAL_MANAGEMENT = "Manages stored credentials; OpenAI restricts plugin
5514
7044
  var CREDENTIAL_INPUT = "Takes a secret or password as input; directories forbid collecting credentials.";
5515
7045
  var ALP = "Collects conversation-derived data beyond the task; the directory profile never serves it.";
5516
7046
  var DIRECTORY_TOOLS = {
7047
+ "add-organization-group-member": IN,
7048
+ "attach-cost-center-resource": IN,
5517
7049
  "cancel-job": IN,
5518
7050
  "create-cluster": IN,
7051
+ "create-cost-center": IN,
5519
7052
  "create-delegation": IN,
5520
7053
  "create-endpoint": IN,
5521
7054
  "create-global-volume": IN,
5522
7055
  "create-network-volume": IN,
7056
+ "create-organization-group": IN,
7057
+ "create-organization-invite": IN,
7058
+ "create-organization-role": IN,
5523
7059
  "create-pod": IN,
5524
7060
  "create-template": IN,
5525
7061
  "delete-cluster": IN,
7062
+ "delete-cost-center": IN,
5526
7063
  "delete-endpoint": IN,
5527
7064
  "delete-global-volume": IN,
5528
7065
  "delete-network-volume": IN,
7066
+ "delete-organization-group": IN,
7067
+ "delete-organization-invite": IN,
7068
+ "delete-organization-role": IN,
7069
+ "delete-organization-user": IN,
5529
7070
  "delete-pod": IN,
5530
7071
  "delete-template": IN,
5531
7072
  "deploy-hub-repo": IN,
7073
+ "detach-cost-center-resource": IN,
5532
7074
  "endpoint-health": IN,
5533
7075
  "get-capacity": IN,
5534
7076
  "get-cluster": IN,
7077
+ "get-cost-center": IN,
5535
7078
  "get-cpu-type": IN,
5536
7079
  "get-data-center": IN,
5537
7080
  "get-endpoint": IN,
5538
7081
  "get-endpoint-build": IN,
7082
+ "get-endpoint-cold-start-metrics": IN,
7083
+ "get-endpoint-request-metrics": IN,
7084
+ "get-endpoint-worker-metrics": IN,
5539
7085
  "get-global-volume": IN,
5540
7086
  "get-gpu-type": IN,
5541
7087
  "get-job-status": IN,
5542
7088
  "get-network-volume": IN,
5543
7089
  "get-organization": IN,
7090
+ "get-organization-group": IN,
7091
+ "get-organization-invite": IN,
7092
+ "get-organization-role": IN,
7093
+ "get-organization-role-capabilities": IN,
5544
7094
  "get-organization-user": IN,
5545
7095
  "get-pod": IN,
5546
7096
  "get-ssh-keys": IN,
@@ -5550,6 +7100,8 @@ var DIRECTORY_TOOLS = {
5550
7100
  "list-cluster-billing": IN,
5551
7101
  "list-cluster-pods": IN,
5552
7102
  "list-clusters": IN,
7103
+ "list-cost-center-resources": IN,
7104
+ "list-cost-centers": IN,
5553
7105
  "list-cpu-types": IN,
5554
7106
  "list-data-centers": IN,
5555
7107
  "list-delegations": IN,
@@ -5563,6 +7115,10 @@ var DIRECTORY_TOOLS = {
5563
7115
  "list-hub-repos": IN,
5564
7116
  "list-network-volume-billing": IN,
5565
7117
  "list-network-volumes": IN,
7118
+ "list-organization-group-members": IN,
7119
+ "list-organization-groups": IN,
7120
+ "list-organization-invites": IN,
7121
+ "list-organization-roles": IN,
5566
7122
  "list-organization-users": IN,
5567
7123
  "list-pod-billing": IN,
5568
7124
  "list-pods": IN,
@@ -5572,6 +7128,7 @@ var DIRECTORY_TOOLS = {
5572
7128
  "list-templates": IN,
5573
7129
  "lookup-concept": IN,
5574
7130
  "purge-endpoint-queue": IN,
7131
+ "remove-organization-group-member": IN,
5575
7132
  "retry-job": IN,
5576
7133
  "revoke-delegation": IN,
5577
7134
  "search-concepts": IN,
@@ -5581,9 +7138,13 @@ var DIRECTORY_TOOLS = {
5581
7138
  "stream-pod-logs": IN,
5582
7139
  "stream-worker-logs": IN,
5583
7140
  "update-cluster": IN,
7141
+ "update-cost-center": IN,
5584
7142
  "update-endpoint": IN,
5585
7143
  "update-global-volume": IN,
5586
7144
  "update-network-volume": IN,
7145
+ "update-organization-group": IN,
7146
+ "update-organization-role": IN,
7147
+ "update-organization-user": IN,
5587
7148
  "update-pod": IN,
5588
7149
  "update-ssh-keys": IN,
5589
7150
  "update-template": IN,
@@ -8683,6 +10244,23 @@ var listPublicEndpoints = {
8683
10244
  // src/specgen/tools/knowledge.ts
8684
10245
  var import_plugin_knowledge = require("@runpod/plugin-knowledge");
8685
10246
  var knowledge = (0, import_plugin_knowledge.loadKnowledge)();
10247
+ var hiddenRules = new Set(
10248
+ (process.env.KNOWLEDGE_HIDDEN_RULES ?? "").split(",").map((id) => id.trim()).filter(Boolean)
10249
+ );
10250
+ var concepts = knowledge.concepts.map((concept) => ({
10251
+ ...concept,
10252
+ rules: concept.rules.filter((rule) => !hiddenRules.has(rule.id))
10253
+ }));
10254
+ for (const id of hiddenRules) {
10255
+ if (!knowledge.concepts.some(
10256
+ (concept) => concept.rules.some((rule) => rule.id === id)
10257
+ ))
10258
+ console.warn("knowledge_hidden_rule_unknown", {
10259
+ id,
10260
+ plugin_version: knowledge.version
10261
+ });
10262
+ }
10263
+ var visibleRuleIds = (ids) => ids.filter((id) => !hiddenRules.has(id));
8686
10264
  var GUIDE_KINDS = ["skill", "reference", "golden-path"];
8687
10265
  var STOPWORDS = new Set(
8688
10266
  "a an and are as at be by can do does for from how i in is it my of on or the to what when why with you your".split(
@@ -8725,7 +10303,7 @@ var guideSummary = ({
8725
10303
  lanes,
8726
10304
  mcp,
8727
10305
  needs_shell,
8728
- concepts
10306
+ concepts: concepts2
8729
10307
  }) => ({
8730
10308
  id,
8731
10309
  kind,
@@ -8734,7 +10312,7 @@ var guideSummary = ({
8734
10312
  lanes,
8735
10313
  mcp,
8736
10314
  needs_shell,
8737
- concepts
10315
+ concepts: concepts2
8738
10316
  });
8739
10317
  function linkedGuides(conceptId) {
8740
10318
  const byId = new Map(knowledge.guides.map((guide) => [guide.id, guide]));
@@ -8746,19 +10324,20 @@ function linkedGuides(conceptId) {
8746
10324
  seen.add(link.from);
8747
10325
  const guide = byId.get(link.from);
8748
10326
  if (!guide) continue;
10327
+ const rules = link.rules && visibleRuleIds(link.rules);
8749
10328
  if (guide.kind === "golden-path")
8750
10329
  examples.push({ id: guide.id, title: guide.title, mcp: guide.mcp });
8751
10330
  else
8752
10331
  docs.push({
8753
10332
  id: guide.id,
8754
10333
  title: guide.title,
8755
- ...link.rules ? { rules: link.rules } : {}
10334
+ ...rules?.length ? { rules } : {}
8756
10335
  });
8757
10336
  }
8758
10337
  return { examples, docs };
8759
10338
  }
8760
10339
  var conceptIndex = /* @__PURE__ */ new Map();
8761
- for (const concept of knowledge.concepts) {
10340
+ for (const concept of concepts) {
8762
10341
  for (const key of [concept.id, concept.name, ...concept.aliases]) {
8763
10342
  if (!conceptIndex.has(key.toLowerCase()))
8764
10343
  conceptIndex.set(key.toLowerCase(), concept);
@@ -8792,7 +10371,7 @@ function resolveConcept(input) {
8792
10371
  return best && !tied ? { concept: best.concept, matchedAs: best.key } : void 0;
8793
10372
  }
8794
10373
  var ruleIndex = /* @__PURE__ */ new Map();
8795
- for (const concept of knowledge.concepts) {
10374
+ for (const concept of concepts) {
8796
10375
  for (const rule of concept.rules) ruleIndex.set(rule.id, { rule, concept });
8797
10376
  }
8798
10377
  var source = {
@@ -8911,7 +10490,7 @@ var lookupConcept = {
8911
10490
  };
8912
10491
  }
8913
10492
  const { concept, matchedAs } = resolved;
8914
- const pointedAtBy = knowledge.concepts.flatMap((other) => [
10493
+ const pointedAtBy = concepts.flatMap((other) => [
8915
10494
  ...other.is_a === concept.id ? [{ concept: other.id, type: "is_a" }] : [],
8916
10495
  ...other.part_of === concept.id ? [{ concept: other.id, type: "part_of" }] : [],
8917
10496
  ...other.relations.filter((relation) => relation.target === concept.id).map((relation) => ({ concept: other.id, type: relation.type }))
@@ -8925,6 +10504,14 @@ var lookupConcept = {
8925
10504
  ...source,
8926
10505
  ...matchedAs ? { matched_as: matchedAs } : {},
8927
10506
  ...concept,
10507
+ steps: concept.steps.map((step) => ({
10508
+ ...step,
10509
+ rules: visibleRuleIds(step.rules)
10510
+ })),
10511
+ rules: concept.rules.map((rule) => ({
10512
+ ...rule,
10513
+ see: visibleRuleIds(rule.see)
10514
+ })),
8928
10515
  pointed_at_by: pointedAtBy,
8929
10516
  linked_rules: linkedRules,
8930
10517
  ...linkedGuides(concept.id)
@@ -9183,7 +10770,7 @@ function words2(name) {
9183
10770
 
9184
10771
  // src/server.ts
9185
10772
  var SERVER_NAME = "Runpod API Server";
9186
- var SERVER_VERSION = true ? "4.9.1" : "dev";
10773
+ var SERVER_VERSION = true ? "4.10.0" : "dev";
9187
10774
 
9188
10775
  // src/specgen/analytics.ts
9189
10776
  var import_node_crypto = require("crypto");
@@ -10822,7 +12409,7 @@ async function handleMcpRequest(req, res, opts = {}) {
10822
12409
  }
10823
12410
 
10824
12411
  // src/alp/scrub.ts
10825
- var SCRUB_VERSION = 5;
12412
+ var SCRUB_VERSION = 6;
10826
12413
  var MARKER = /^["']?\[redacted:[a-z_]+\]["']?$/;
10827
12414
  var CREDENTIAL_PATTERNS = [
10828
12415
  // Runpod API keys.
@@ -11010,6 +12597,22 @@ function redactAssignments(text) {
11010
12597
  out += text.slice(copiedTo);
11011
12598
  return { text: out, redactions };
11012
12599
  }
12600
+ var EMAIL = /(?<![\p{L}\p{M}\p{N}_.%+-])([\p{L}\p{M}\p{N}_.%+-]{1,64})@((?:[\p{L}\p{M}\p{N}-]{1,63}\.){1,8}[\p{L}\p{M}]{2,63})(?![\p{L}\p{M}\p{N}])/gu;
12601
+ var RUNPOD_SSH_HOST = "ssh.runpod.io";
12602
+ function redactEmails(text) {
12603
+ let redactions = 0;
12604
+ const out = text.replace(
12605
+ EMAIL,
12606
+ (address, local, domain, offset) => {
12607
+ const next = text[offset + address.length];
12608
+ if (domain.toLowerCase() === RUNPOD_SSH_HOST || local === "git" && (next === ":" || next === "/"))
12609
+ return address;
12610
+ redactions++;
12611
+ return "[redacted:email]";
12612
+ }
12613
+ );
12614
+ return { text: out, redactions };
12615
+ }
11013
12616
  function scrub(text) {
11014
12617
  let out = text;
11015
12618
  let redactions = 0;
@@ -11017,7 +12620,8 @@ function scrub(text) {
11017
12620
  redactAnchoredCredentials,
11018
12621
  redactHeaderValues,
11019
12622
  redactQuerySecrets,
11020
- redactAssignments
12623
+ redactAssignments,
12624
+ redactEmails
11021
12625
  ]) {
11022
12626
  const result = stage(out);
11023
12627
  out = result.text;
@@ -11057,6 +12661,7 @@ var MAX_CONTENT_CHARS = 2e4;
11057
12661
  var MAX_REFERRAL_CONTENT_CHARS = 200;
11058
12662
  var MAX_FIELD_CHARS = 500;
11059
12663
  var SINK_TIMEOUT_MS3 = 5e3;
12664
+ var TOOL_NAME = /^[A-Za-z0-9_-]{1,64}$/;
11060
12665
  var ALP_SEVERITIES = ["blocked", "degraded", "cosmetic"];
11061
12666
  function notRecorded(reason) {
11062
12667
  return {
@@ -11129,7 +12734,9 @@ async function handleAlpSubmit(req, res, opts = {}) {
11129
12734
  // ("critical", "high") turns a dimension back into prose, and the loss of
11130
12735
  // one label costs less than that.
11131
12736
  severity: !referral && ALP_SEVERITIES.includes(body.severity) ? body.severity : void 0,
11132
- tool: !referral && typeof body.tool === "string" ? body.tool : void 0,
12737
+ // Same rule as severity: a free-text tool would turn a grouping key back
12738
+ // into prose, so only a value shaped like a tool name is kept.
12739
+ tool: !referral && typeof body.tool === "string" && TOOL_NAME.test(body.tool) ? body.tool : void 0,
11133
12740
  workaround: !referral && typeof body.workaround === "string" ? body.workaround : void 0,
11134
12741
  trigger: !referral && typeof body.trigger === "string" ? body.trigger : void 0,
11135
12742
  // Referral-only fields. source follows the severity rule (off-enum is
@@ -11155,7 +12762,7 @@ async function handleAlpSubmit(req, res, opts = {}) {
11155
12762
  intention: clean.intention?.slice(0, MAX_FIELD_CHARS),
11156
12763
  modelType: clean.modelType?.slice(0, MAX_FIELD_CHARS),
11157
12764
  severity: clean.severity,
11158
- tool: clean.tool?.slice(0, MAX_FIELD_CHARS),
12765
+ tool: clean.tool,
11159
12766
  // Prose fields, so they get the content cap rather than the field cap: a
11160
12767
  // workaround worth reading is a paragraph, not a label.
11161
12768
  workaround: clean.workaround?.slice(0, MAX_CONTENT_CHARS),
@@ -11187,6 +12794,14 @@ async function handleAlpSubmit(req, res, opts = {}) {
11187
12794
  return;
11188
12795
  }
11189
12796
  const sinkBody = await response.json().catch(() => null);
12797
+ if (sinkBody?.capped === true) {
12798
+ console.log(
12799
+ "alp_submit_capped",
12800
+ JSON.stringify({ route: body.route, transport: row.transport })
12801
+ );
12802
+ send(200, notRecorded("this account reached its limit for this tool"));
12803
+ return;
12804
+ }
11190
12805
  if (sinkBody?.ok !== true || typeof sinkBody.id !== "string") {
11191
12806
  console.warn("alp_sink_unrecognized", { status: response.status });
11192
12807
  send(200, notRecorded("the store did not confirm the write"));