@iblai/data-layer 1.22.0 → 1.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -39082,13 +39082,13 @@ const SPEND_CAPS_REDUCER_PATH = 'spendCapsApiSlice';
39082
39082
  * provider rate limit, which also uses status 429.
39083
39083
  */
39084
39084
  const SPEND_CAP_EXCEEDED_ERROR_CODE = 'spend_cap_exceeded';
39085
- const encodePathSegment$2 = (value) => encodeURIComponent(value);
39086
- const tenantSpendCapPath = (org) => `/api/ai-mentor/orgs/${encodePathSegment$2(org)}/spend-caps/tenant/`;
39087
- const agentSpendCapPath = (org, mentorId) => `/api/ai-mentor/orgs/${encodePathSegment$2(org)}/agents/${encodePathSegment$2(mentorId)}/spend-cap/`;
39088
- const agentUserSpendCapsPath = (org, mentorId) => `/api/ai-mentor/orgs/${encodePathSegment$2(org)}/agents/${encodePathSegment$2(mentorId)}/spend-caps/users/`;
39089
- const userSpendCapPath = (org, mentorId, username) => `${agentUserSpendCapsPath(org, mentorId)}${encodePathSegment$2(username)}/`;
39090
- const spendCapStatusPath = (org, userId) => `/api/ai-mentor/orgs/${encodePathSegment$2(org)}/spend-caps/status/${encodePathSegment$2(userId)}/`;
39091
- const agentSpendCapsListPath = (org) => `/api/ai-mentor/orgs/${encodePathSegment$2(org)}/spend-caps/agents/`;
39085
+ const encodePathSegment$3 = (value) => encodeURIComponent(value);
39086
+ const tenantSpendCapPath = (org) => `/api/ai-mentor/orgs/${encodePathSegment$3(org)}/spend-caps/tenant/`;
39087
+ const agentSpendCapPath = (org, mentorId) => `/api/ai-mentor/orgs/${encodePathSegment$3(org)}/agents/${encodePathSegment$3(mentorId)}/spend-cap/`;
39088
+ const agentUserSpendCapsPath = (org, mentorId) => `/api/ai-mentor/orgs/${encodePathSegment$3(org)}/agents/${encodePathSegment$3(mentorId)}/spend-caps/users/`;
39089
+ const userSpendCapPath = (org, mentorId, username) => `${agentUserSpendCapsPath(org, mentorId)}${encodePathSegment$3(username)}/`;
39090
+ const spendCapStatusPath = (org, userId) => `/api/ai-mentor/orgs/${encodePathSegment$3(org)}/spend-caps/status/${encodePathSegment$3(userId)}/`;
39091
+ const agentSpendCapsListPath = (org) => `/api/ai-mentor/orgs/${encodePathSegment$3(org)}/spend-caps/agents/`;
39092
39092
  const SPEND_CAPS_ENDPOINTS = {
39093
39093
  GET_TENANT_SPEND_CAP: {
39094
39094
  service: exports.SERVICES.DM,
@@ -39782,7 +39782,7 @@ const buildEndpointFromDmServiceLegacy = (serviceFn, options) => buildEndpointFr
39782
39782
  const API_TOKENS_PATH = '/api/core/platform/api-tokens/';
39783
39783
  /**
39784
39784
  * Normalizes a `getApiKeys` result: the endpoint returns a bare array unless
39785
- * `pageSize` is sent, in which case it returns a DRF page envelope.
39785
+ * `pageSize` is sent, in which case it returns a `{count, next_page, previous_page, results}` envelope.
39786
39786
  */
39787
39787
  function unwrapApiTokenList(response) {
39788
39788
  var _a, _b;
@@ -39832,7 +39832,10 @@ const apiKeysApiSlice = react.createApi({
39832
39832
  if (args.pageSize !== undefined)
39833
39833
  queryParams.set('page_size', String(args.pageSize));
39834
39834
  return requestApiToken(`${API_TOKENS_PATH}?${queryParams.toString()}`, { method: 'GET' }, 'Failed to fetch API keys');
39835
- }),
39835
+ },
39836
+ // An out-of-range page is a 404 "Invalid page." — fail fast so the
39837
+ // caller can step back instead of waiting out the retry backoff.
39838
+ { expectedErrorStatuses: [404] }),
39836
39839
  providesTags: ['apiKeys'],
39837
39840
  }),
39838
39841
  /** Detail read — the only GET that returns the token's policies and groups. */
@@ -46576,11 +46579,11 @@ const VERCEL_SPA = 'vercel';
46576
46579
  // platform-wide listing, which is why "add a domain" can only offer the caller's
46577
46580
  // own deployed apps.
46578
46581
  const HOSTING_REDUCER_PATH = 'hostingApiSlice';
46579
- const encodePathSegment$1 = (value) => encodeURIComponent(value);
46580
- const userHostingPath = (org, username) => `/api/ai-mentor/orgs/${encodePathSegment$1(org)}/users/${encodePathSegment$1(username)}/providers/vercel/hosting`;
46582
+ const encodePathSegment$2 = (value) => encodeURIComponent(value);
46583
+ const userHostingPath = (org, username) => `/api/ai-mentor/orgs/${encodePathSegment$2(org)}/users/${encodePathSegment$2(username)}/providers/vercel/hosting`;
46581
46584
  const hostingProjectsPath = (org, username) => `${userHostingPath(org, username)}/deployment/`;
46582
46585
  const hostingProjectDomainsPath = (org, username) => `${userHostingPath(org, username)}/dns/`;
46583
- const hostingDomainPath = (org, domainId) => `/api/ai-mentor/orgs/${encodePathSegment$1(org)}/providers/vercel/hosting/domains/${domainId}/`;
46586
+ const hostingDomainPath = (org, domainId) => `/api/ai-mentor/orgs/${encodePathSegment$2(org)}/providers/vercel/hosting/domains/${domainId}/`;
46584
46587
  const HOSTING_ENDPOINTS = {
46585
46588
  GET_HOSTING_PROJECTS: {
46586
46589
  service: exports.SERVICES.DM,
@@ -47421,8 +47424,8 @@ exports.recommendationPromptTypeEnum = void 0;
47421
47424
  recommendationPromptTypeEnum["catalog"] = "catalog";
47422
47425
  })(exports.recommendationPromptTypeEnum || (exports.recommendationPromptTypeEnum = {}));
47423
47426
 
47424
- const encodePathSegment = (value) => encodeURIComponent(value);
47425
- const periodicAgentsListPath = ({ org, userId }) => `/api/ai-mentor/orgs/${encodePathSegment(org)}/users/${encodePathSegment(userId)}/periodic-agents/`;
47427
+ const encodePathSegment$1 = (value) => encodeURIComponent(value);
47428
+ const periodicAgentsListPath = ({ org, userId }) => `/api/ai-mentor/orgs/${encodePathSegment$1(org)}/users/${encodePathSegment$1(userId)}/periodic-agents/`;
47426
47429
  const periodicAgentsListParams = ({ enabled, mentorId, ordering, page, pageSize, parentMentorId, parentSessionId, previousAgent, previousAgentStatus, search, status, title, username, startDate, endDate, }) => ({
47427
47430
  enabled,
47428
47431
  mentor_id: mentorId,
@@ -49115,6 +49118,357 @@ function useUserLlmTraceObservations(scope, options) {
49115
49118
  return useUserLlmUsageObservations(base && traceId ? { ...base, resource: 'observations', trace_id: traceId, limit } : null, options);
49116
49119
  }
49117
49120
 
49121
+ // Backend contract: the Virtual Machine Shell network features on iblai-dm-pro.
49122
+ // An agent with `enable_virtual_machine` runs its `execute` tool in an isolated
49123
+ // per-chat-run Linux VM that has no network by default. Two org-level records,
49124
+ // both under /api/ai-account/orgs/{org}/, decide what the VM can reach and
49125
+ // which credentials it can use:
49126
+ // 1. Network policies — virtual-machine-network-policy/ — named, reusable
49127
+ // `host:port` allowlists an agent binds under the `custom` egress profile.
49128
+ // 2. VM secrets — virtual-machine-secret/ — API keys the VM can use but never
49129
+ // read; the real value is swapped in on the wire, only for HTTPS requests to
49130
+ // the secret's own hosts.
49131
+ // Both are bound to an agent through the mentor-settings endpoint
49132
+ // (`virtual_machine_egress`, `virtual_machine_network_policy_id`,
49133
+ // `virtual_machine_secret_ids`) — see ./types.ts.
49134
+ const VIRTUAL_MACHINE_REDUCER_PATH = 'virtualMachineApiSlice';
49135
+ const VIRTUAL_MACHINE_QUERY_KEYS = {
49136
+ NETWORK_POLICIES: 'VirtualMachineNetworkPolicies',
49137
+ SECRETS: 'VirtualMachineSecrets',
49138
+ };
49139
+ const encodePathSegment = (value) => encodeURIComponent(value);
49140
+ const VIRTUAL_MACHINE_ENDPOINTS = {
49141
+ /** GET (list) / POST (create) / PATCH (update by `id`) / DELETE (by `id`). */
49142
+ NETWORK_POLICIES: {
49143
+ service: exports.SERVICES.DM,
49144
+ path: (org) => `/api/ai-account/orgs/${encodePathSegment(org)}/virtual-machine-network-policy/`,
49145
+ },
49146
+ /** GET (list) / POST (create) / PATCH (update by `env_var`) / DELETE (by `env_var`). */
49147
+ SECRETS: {
49148
+ service: exports.SERVICES.DM,
49149
+ path: (org) => `/api/ai-account/orgs/${encodePathSegment(org)}/virtual-machine-secret/`,
49150
+ },
49151
+ };
49152
+ /**
49153
+ * RBAC permission names the backend checks on each endpoint. Listed for
49154
+ * reference — the UI gates on the list call's 403 rather than on these.
49155
+ */
49156
+ const VIRTUAL_MACHINE_PERMISSIONS = {
49157
+ NETWORK_POLICIES: {
49158
+ LIST: 'Ibl.Mentor/VirtualMachineNetworkPolicies/list',
49159
+ WRITE: 'Ibl.Mentor/VirtualMachineNetworkPolicies/write',
49160
+ DELETE: 'Ibl.Mentor/VirtualMachineNetworkPolicies/delete',
49161
+ },
49162
+ SECRETS: {
49163
+ LIST: 'Ibl.Mentor/VirtualMachineSecrets/list',
49164
+ WRITE: 'Ibl.Mentor/VirtualMachineSecrets/write',
49165
+ DELETE: 'Ibl.Mentor/VirtualMachineSecrets/delete',
49166
+ },
49167
+ };
49168
+ /** Egress profiles, in the order the UI lists them. `none` is the default. */
49169
+ const VIRTUAL_MACHINE_EGRESS_PROFILES = ['none', 'registries', 'public', 'custom'];
49170
+ /**
49171
+ * Fast client-side check for a `host:port` entry. The backend is authoritative
49172
+ * (it also rejects wildcards, schemes, paths and the reserved hosts below), so
49173
+ * its message is always surfaced when it disagrees.
49174
+ */
49175
+ const VIRTUAL_MACHINE_HOST_PORT_PATTERN = /^[a-z0-9]([a-z0-9.-]*[a-z0-9])?:\d{1,5}$/i;
49176
+ /** Hostnames the backend refuses in any allowlist. */
49177
+ const VIRTUAL_MACHINE_REJECTED_HOSTS = [
49178
+ 'localhost',
49179
+ 'metadata',
49180
+ 'metadata.google.internal',
49181
+ 'instance-data',
49182
+ 'instance-data.ec2.internal',
49183
+ ];
49184
+ /** Hostname suffixes the backend refuses in any allowlist. */
49185
+ const VIRTUAL_MACHINE_REJECTED_HOST_SUFFIXES = [
49186
+ '.local',
49187
+ '.internal',
49188
+ '.localhost',
49189
+ ];
49190
+ /** `env_var` of a VM secret: a POSIX-style environment variable name. */
49191
+ const VIRTUAL_MACHINE_ENV_VAR_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
49192
+ /** A network policy holds between 1 and 100 hosts. */
49193
+ const VIRTUAL_MACHINE_MAX_POLICY_HOSTS = 100;
49194
+ /** An agent may bind at most 20 VM secrets. */
49195
+ const VIRTUAL_MACHINE_MAX_SECRETS_PER_MENTOR = 20;
49196
+ /** A pasted secret value must be at least this long. */
49197
+ const VIRTUAL_MACHINE_SECRET_VALUE_MIN_LENGTH = 8;
49198
+ /**
49199
+ * Default VM runtime billing: charged to the chatting user's credits, prorated
49200
+ * per second. The rate is configurable per org, so the UI presents these as
49201
+ * the default rather than the org's actual rate.
49202
+ */
49203
+ const VIRTUAL_MACHINE_DEFAULT_BILLING = {
49204
+ usd: 1,
49205
+ minutes: 10,
49206
+ };
49207
+
49208
+ /**
49209
+ * Virtual Machine Shell network policies and secrets
49210
+ * (`/api/ai-account/orgs/{org}/virtual-machine-network-policy/` and
49211
+ * `/api/ai-account/orgs/{org}/virtual-machine-secret/`).
49212
+ *
49213
+ * Hand-written: these endpoints are newer than the pinned `@iblai/iblai-api`
49214
+ * release. Records are keyed in the body (PATCH) or the query string (DELETE),
49215
+ * never in the URL. A 403 on either list means the caller lacks the matching
49216
+ * `Ibl.Mentor/VirtualMachine…/list` permission — hosts hide the pages then.
49217
+ */
49218
+ const virtualMachineApiSlice = react.createApi({
49219
+ reducerPath: VIRTUAL_MACHINE_REDUCER_PATH,
49220
+ tagTypes: [VIRTUAL_MACHINE_QUERY_KEYS.NETWORK_POLICIES, VIRTUAL_MACHINE_QUERY_KEYS.SECRETS],
49221
+ baseQuery: iblFetchBaseQuery,
49222
+ endpoints: (builder) => ({
49223
+ // ── Network policies ────────────────────────────────────────────────
49224
+ listVirtualMachineNetworkPolicies: builder.query({
49225
+ query: ({ org }) => ({
49226
+ url: VIRTUAL_MACHINE_ENDPOINTS.NETWORK_POLICIES.path(org),
49227
+ service: VIRTUAL_MACHINE_ENDPOINTS.NETWORK_POLICIES.service,
49228
+ }),
49229
+ providesTags: [VIRTUAL_MACHINE_QUERY_KEYS.NETWORK_POLICIES],
49230
+ }),
49231
+ createVirtualMachineNetworkPolicy: builder.mutation({
49232
+ query: ({ org, body }) => ({
49233
+ url: VIRTUAL_MACHINE_ENDPOINTS.NETWORK_POLICIES.path(org),
49234
+ service: VIRTUAL_MACHINE_ENDPOINTS.NETWORK_POLICIES.service,
49235
+ method: 'POST',
49236
+ body,
49237
+ }),
49238
+ invalidatesTags: [VIRTUAL_MACHINE_QUERY_KEYS.NETWORK_POLICIES],
49239
+ }),
49240
+ // `body.id` names the policy; `allowed_hosts` replaces the whole list.
49241
+ updateVirtualMachineNetworkPolicy: builder.mutation({
49242
+ query: ({ org, body }) => ({
49243
+ url: VIRTUAL_MACHINE_ENDPOINTS.NETWORK_POLICIES.path(org),
49244
+ service: VIRTUAL_MACHINE_ENDPOINTS.NETWORK_POLICIES.service,
49245
+ method: 'PATCH',
49246
+ body,
49247
+ }),
49248
+ invalidatesTags: [VIRTUAL_MACHINE_QUERY_KEYS.NETWORK_POLICIES],
49249
+ }),
49250
+ // 400 when an agent still uses the policy — the message names the agents.
49251
+ deleteVirtualMachineNetworkPolicy: builder.mutation({
49252
+ query: ({ org, id }) => ({
49253
+ url: VIRTUAL_MACHINE_ENDPOINTS.NETWORK_POLICIES.path(org),
49254
+ service: VIRTUAL_MACHINE_ENDPOINTS.NETWORK_POLICIES.service,
49255
+ method: 'DELETE',
49256
+ params: { id },
49257
+ }),
49258
+ invalidatesTags: [VIRTUAL_MACHINE_QUERY_KEYS.NETWORK_POLICIES],
49259
+ }),
49260
+ // ── VM secrets ──────────────────────────────────────────────────────
49261
+ listVirtualMachineSecrets: builder.query({
49262
+ query: ({ org }) => ({
49263
+ url: VIRTUAL_MACHINE_ENDPOINTS.SECRETS.path(org),
49264
+ service: VIRTUAL_MACHINE_ENDPOINTS.SECRETS.service,
49265
+ }),
49266
+ providesTags: [VIRTUAL_MACHINE_QUERY_KEYS.SECRETS],
49267
+ }),
49268
+ // Either `value` or `source_credential_id` + `source_field`, never both.
49269
+ createVirtualMachineSecret: builder.mutation({
49270
+ query: ({ org, body }) => ({
49271
+ url: VIRTUAL_MACHINE_ENDPOINTS.SECRETS.path(org),
49272
+ service: VIRTUAL_MACHINE_ENDPOINTS.SECRETS.service,
49273
+ method: 'POST',
49274
+ body,
49275
+ }),
49276
+ invalidatesTags: [VIRTUAL_MACHINE_QUERY_KEYS.SECRETS],
49277
+ }),
49278
+ // `body.env_var` names the secret and cannot change.
49279
+ updateVirtualMachineSecret: builder.mutation({
49280
+ query: ({ org, body }) => ({
49281
+ url: VIRTUAL_MACHINE_ENDPOINTS.SECRETS.path(org),
49282
+ service: VIRTUAL_MACHINE_ENDPOINTS.SECRETS.service,
49283
+ method: 'PATCH',
49284
+ body,
49285
+ }),
49286
+ invalidatesTags: [VIRTUAL_MACHINE_QUERY_KEYS.SECRETS],
49287
+ }),
49288
+ // Also unbinds the secret from every agent that uses it.
49289
+ deleteVirtualMachineSecret: builder.mutation({
49290
+ query: ({ org, envVar }) => ({
49291
+ url: VIRTUAL_MACHINE_ENDPOINTS.SECRETS.path(org),
49292
+ service: VIRTUAL_MACHINE_ENDPOINTS.SECRETS.service,
49293
+ method: 'DELETE',
49294
+ params: { env_var: envVar },
49295
+ }),
49296
+ invalidatesTags: [VIRTUAL_MACHINE_QUERY_KEYS.SECRETS],
49297
+ }),
49298
+ }),
49299
+ });
49300
+ const { useListVirtualMachineNetworkPoliciesQuery, useLazyListVirtualMachineNetworkPoliciesQuery, useCreateVirtualMachineNetworkPolicyMutation, useUpdateVirtualMachineNetworkPolicyMutation, useDeleteVirtualMachineNetworkPolicyMutation, useListVirtualMachineSecretsQuery, useLazyListVirtualMachineSecretsQuery, useCreateVirtualMachineSecretMutation, useUpdateVirtualMachineSecretMutation, useDeleteVirtualMachineSecretMutation, } = virtualMachineApiSlice;
49301
+
49302
+ /**
49303
+ * Normalise a `host:port` entry the way the backend stores it: trimmed and
49304
+ * lowercased.
49305
+ */
49306
+ function normalizeHostPort(value) {
49307
+ return value.trim().toLowerCase();
49308
+ }
49309
+ /** Split a pasted or typed string into candidate `host:port` entries. */
49310
+ function splitHostPortInput(value) {
49311
+ return value
49312
+ .split(/[\s,;]+/)
49313
+ .map(normalizeHostPort)
49314
+ .filter((entry) => entry.length > 0);
49315
+ }
49316
+ const IPV4_PATTERN = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
49317
+ /** Whether the host part is an IPv4 literal (the `host:port` grammar admits no IPv6). */
49318
+ function isIpAddressHost(host) {
49319
+ return IPV4_PATTERN.test(host);
49320
+ }
49321
+ /**
49322
+ * IPv4 literals the backend refuses even where IPs are allowed: loopback,
49323
+ * link-local, multicast, reserved and the unspecified address.
49324
+ */
49325
+ function isRejectedIpAddress(host) {
49326
+ const match = IPV4_PATTERN.exec(host);
49327
+ if (!match)
49328
+ return false;
49329
+ const octets = match.slice(1, 5).map(Number);
49330
+ if (octets.some((octet) => octet > 255))
49331
+ return true;
49332
+ const [first, second] = octets;
49333
+ if (first === 0)
49334
+ return true; // unspecified / "this" network
49335
+ if (first === 127)
49336
+ return true; // loopback
49337
+ if (first === 169 && second === 254)
49338
+ return true; // link-local
49339
+ if (first >= 224)
49340
+ return true; // multicast (224–239) and reserved (240+)
49341
+ return false;
49342
+ }
49343
+ /** Whether the backend refuses this hostname outright (localhost, metadata, `.internal`, …). */
49344
+ function isRejectedHostname(host) {
49345
+ const lowered = host.toLowerCase();
49346
+ if (VIRTUAL_MACHINE_REJECTED_HOSTS.includes(lowered))
49347
+ return true;
49348
+ return VIRTUAL_MACHINE_REJECTED_HOST_SUFFIXES.some((suffix) => lowered.endsWith(suffix));
49349
+ }
49350
+ /**
49351
+ * Client-side check of one `host:port` entry, returning why it fails or `null`
49352
+ * when it looks valid. Network policies accept IP addresses; VM secrets do
49353
+ * not (`allowIpAddresses: false`, the default). The backend remains
49354
+ * authoritative, so always show its message when it rejects an entry.
49355
+ */
49356
+ function validateHostPort(value, options = {}) {
49357
+ const entry = normalizeHostPort(value);
49358
+ if (!VIRTUAL_MACHINE_HOST_PORT_PATTERN.test(entry))
49359
+ return 'format';
49360
+ const separator = entry.lastIndexOf(':');
49361
+ const host = entry.slice(0, separator);
49362
+ const port = Number(entry.slice(separator + 1));
49363
+ if (port < 1 || port > 65535)
49364
+ return 'port';
49365
+ if (isRejectedHostname(host))
49366
+ return 'rejected_host';
49367
+ if (isIpAddressHost(host)) {
49368
+ if (!options.allowIpAddresses)
49369
+ return 'ip_not_allowed';
49370
+ if (isRejectedIpAddress(host))
49371
+ return 'rejected_host';
49372
+ }
49373
+ return null;
49374
+ }
49375
+ /** Convenience wrapper around {@link validateHostPort}. */
49376
+ function isValidHostPort(value, options = {}) {
49377
+ return validateHostPort(value, options) === null;
49378
+ }
49379
+ /** HTTP status of an RTK Query error, if it carries one. */
49380
+ function getVirtualMachineErrorStatus(error) {
49381
+ const status = error === null || error === void 0 ? void 0 : error.status;
49382
+ return typeof status === 'number' ? status : undefined;
49383
+ }
49384
+ function toMessages(value) {
49385
+ if (typeof value === 'string')
49386
+ return [value];
49387
+ if (Array.isArray(value))
49388
+ return value.filter((item) => typeof item === 'string');
49389
+ return [];
49390
+ }
49391
+ /**
49392
+ * Normalise a virtual-machine endpoint error for display. Every 400 has the
49393
+ * form `{ error }`, where `error` is either a plain string (shown as a
49394
+ * form-level message) or an object of field → messages (shown next to the
49395
+ * matching field). `non_field_errors` is folded into the form-level message.
49396
+ * Other shapes (`detail`, a bare string body) fall back to a message too.
49397
+ */
49398
+ function getVirtualMachineApiError(error) {
49399
+ const status = getVirtualMachineErrorStatus(error);
49400
+ const data = error === null || error === void 0 ? void 0 : error.data;
49401
+ const fieldErrors = {};
49402
+ let message = null;
49403
+ if (typeof data === 'string') {
49404
+ message = data;
49405
+ }
49406
+ else if (data && typeof data === 'object') {
49407
+ const body = data;
49408
+ if (typeof body.error === 'string') {
49409
+ message = body.error;
49410
+ }
49411
+ else if (body.error && typeof body.error === 'object') {
49412
+ for (const [field, messages] of Object.entries(body.error)) {
49413
+ const list = toMessages(messages);
49414
+ if (list.length === 0)
49415
+ continue;
49416
+ if (field === 'non_field_errors') {
49417
+ message = list.join(' ');
49418
+ }
49419
+ else {
49420
+ fieldErrors[field] = list;
49421
+ }
49422
+ }
49423
+ }
49424
+ else if (typeof body.detail === 'string') {
49425
+ message = body.detail;
49426
+ }
49427
+ else if (typeof body.message === 'string') {
49428
+ message = body.message;
49429
+ }
49430
+ }
49431
+ return { status, message, fieldErrors };
49432
+ }
49433
+ /**
49434
+ * Agent ids named by the "bound to mentors" delete error, e.g.
49435
+ * `"This network policy is bound to mentors; move them off it first: ['<uuid>', '<uuid>']"`.
49436
+ */
49437
+ function extractBoundMentorIds(message) {
49438
+ if (!message)
49439
+ return [];
49440
+ const listStart = message.indexOf('[');
49441
+ const listEnd = message.lastIndexOf(']');
49442
+ if (listStart === -1 || listEnd <= listStart)
49443
+ return [];
49444
+ const ids = [];
49445
+ const quoted = /['"]([^'"]+)['"]/g;
49446
+ let match;
49447
+ const list = message.slice(listStart + 1, listEnd);
49448
+ while ((match = quoted.exec(list)) !== null) {
49449
+ ids.push(match[1]);
49450
+ }
49451
+ return ids;
49452
+ }
49453
+ /** Whether an egress profile lets the VM reach hosts at all (and so may carry secrets). */
49454
+ function isVirtualMachineEgressNetworked(egress) {
49455
+ return egress === 'public' || egress === 'custom';
49456
+ }
49457
+ /**
49458
+ * Under the `custom` profile every host a bound secret is sent to must be in
49459
+ * the network policy. Returns, per secret, the hosts the policy is missing.
49460
+ */
49461
+ function findUncoveredSecretHosts(secrets, allowedHosts) {
49462
+ const allowed = new Set(allowedHosts.map(normalizeHostPort));
49463
+ const uncovered = [];
49464
+ for (const secret of secrets) {
49465
+ const hosts = secret.allow_hosts.map(normalizeHostPort).filter((host) => !allowed.has(host));
49466
+ if (hosts.length > 0)
49467
+ uncovered.push({ envVar: secret.env_var, hosts });
49468
+ }
49469
+ return uncovered;
49470
+ }
49471
+
49118
49472
  const mentorReducer = {
49119
49473
  [mentorApiSlice.reducerPath]: mentorApiSlice.reducer,
49120
49474
  [tenantApiSlice.reducerPath]: tenantApiSlice.reducer,
@@ -49178,6 +49532,7 @@ const mentorReducer = {
49178
49532
  [gradingApiSlice.reducerPath]: gradingApiSlice.reducer,
49179
49533
  [spendCapsApiSlice.reducerPath]: spendCapsApiSlice.reducer,
49180
49534
  [userChatHistoryApiSlice.reducerPath]: userChatHistoryApiSlice.reducer,
49535
+ [virtualMachineApiSlice.reducerPath]: virtualMachineApiSlice.reducer,
49181
49536
  [userLlmUsageApiSlice.reducerPath]: userLlmUsageApiSlice.reducer,
49182
49537
  };
49183
49538
  const mentorMiddleware = [
@@ -49243,6 +49598,7 @@ const mentorMiddleware = [
49243
49598
  gradingApiSlice.middleware,
49244
49599
  spendCapsApiSlice.middleware,
49245
49600
  userChatHistoryApiSlice.middleware,
49601
+ virtualMachineApiSlice.middleware,
49246
49602
  userLlmUsageApiSlice.middleware,
49247
49603
  ];
49248
49604
 
@@ -49291,6 +49647,7 @@ const skillsReducer = {
49291
49647
  [chatPrivacyApiSlice.reducerPath]: chatPrivacyApiSlice.reducer,
49292
49648
  [agentSkillsApiSlice.reducerPath]: agentSkillsApiSlice.reducer,
49293
49649
  [userChatHistoryApiSlice.reducerPath]: userChatHistoryApiSlice.reducer,
49650
+ [virtualMachineApiSlice.reducerPath]: virtualMachineApiSlice.reducer,
49294
49651
  [chatApiSlice.reducerPath]: chatApiSlice.reducer,
49295
49652
  [userLlmUsageApiSlice.reducerPath]: userLlmUsageApiSlice.reducer,
49296
49653
  };
@@ -49339,6 +49696,7 @@ const skillsMiddleware = [
49339
49696
  chatPrivacyApiSlice.middleware,
49340
49697
  agentSkillsApiSlice.middleware,
49341
49698
  userChatHistoryApiSlice.middleware,
49699
+ virtualMachineApiSlice.middleware,
49342
49700
  chatApiSlice.middleware,
49343
49701
  userLlmUsageApiSlice.middleware,
49344
49702
  ];
@@ -49465,6 +49823,19 @@ exports.USER_LLM_USAGE_REDUCER_PATH = USER_LLM_USAGE_REDUCER_PATH;
49465
49823
  exports.USER_PROGRESS_DATA_POINTS = USER_PROGRESS_DATA_POINTS;
49466
49824
  exports.USER_PROGRESS_SUMMARY_TYPE = USER_PROGRESS_SUMMARY_TYPE;
49467
49825
  exports.VERCEL_SPA = VERCEL_SPA;
49826
+ exports.VIRTUAL_MACHINE_DEFAULT_BILLING = VIRTUAL_MACHINE_DEFAULT_BILLING;
49827
+ exports.VIRTUAL_MACHINE_EGRESS_PROFILES = VIRTUAL_MACHINE_EGRESS_PROFILES;
49828
+ exports.VIRTUAL_MACHINE_ENDPOINTS = VIRTUAL_MACHINE_ENDPOINTS;
49829
+ exports.VIRTUAL_MACHINE_ENV_VAR_PATTERN = VIRTUAL_MACHINE_ENV_VAR_PATTERN;
49830
+ exports.VIRTUAL_MACHINE_HOST_PORT_PATTERN = VIRTUAL_MACHINE_HOST_PORT_PATTERN;
49831
+ exports.VIRTUAL_MACHINE_MAX_POLICY_HOSTS = VIRTUAL_MACHINE_MAX_POLICY_HOSTS;
49832
+ exports.VIRTUAL_MACHINE_MAX_SECRETS_PER_MENTOR = VIRTUAL_MACHINE_MAX_SECRETS_PER_MENTOR;
49833
+ exports.VIRTUAL_MACHINE_PERMISSIONS = VIRTUAL_MACHINE_PERMISSIONS;
49834
+ exports.VIRTUAL_MACHINE_QUERY_KEYS = VIRTUAL_MACHINE_QUERY_KEYS;
49835
+ exports.VIRTUAL_MACHINE_REDUCER_PATH = VIRTUAL_MACHINE_REDUCER_PATH;
49836
+ exports.VIRTUAL_MACHINE_REJECTED_HOSTS = VIRTUAL_MACHINE_REJECTED_HOSTS;
49837
+ exports.VIRTUAL_MACHINE_REJECTED_HOST_SUFFIXES = VIRTUAL_MACHINE_REJECTED_HOST_SUFFIXES;
49838
+ exports.VIRTUAL_MACHINE_SECRET_VALUE_MIN_LENGTH = VIRTUAL_MACHINE_SECRET_VALUE_MIN_LENGTH;
49468
49839
  exports.WATCHED_GROUPS_ENDPOINTS = WATCHED_GROUPS_ENDPOINTS;
49469
49840
  exports.WATCHED_GROUPS_QUERY_KEYS = WATCHED_GROUPS_QUERY_KEYS;
49470
49841
  exports.WATCHED_GROUPS_REDUCER_PATH = WATCHED_GROUPS_REDUCER_PATH;
@@ -49516,6 +49887,7 @@ exports.edxProctoringApiSlice = edxProctoringApiSlice;
49516
49887
  exports.edxSsoApiSlice = edxSsoApiSlice;
49517
49888
  exports.evalTotalPages = evalTotalPages;
49518
49889
  exports.evaluationsApiSlice = evaluationsApiSlice;
49890
+ exports.extractBoundMentorIds = extractBoundMentorIds;
49519
49891
  exports.fakeBaseQueryWithLogging = fakeBaseQueryWithLogging;
49520
49892
  exports.featureTags = featureTags;
49521
49893
  exports.fetchLearnerCompletion = fetchLearnerCompletion;
@@ -49525,20 +49897,28 @@ exports.filterGlobalUserRoles = filterGlobalUserRoles;
49525
49897
  exports.filterOrgUserRoles = filterOrgUserRoles;
49526
49898
  exports.filterSlashSkills = filterSlashSkills;
49527
49899
  exports.findResumeBlock = findResumeBlock;
49900
+ exports.findUncoveredSecretHosts = findUncoveredSecretHosts;
49528
49901
  exports.flattenOutline = flattenOutline;
49529
49902
  exports.getNextRecentMessagesPageParam = getNextRecentMessagesPageParam;
49530
49903
  exports.getSections = getSections;
49531
49904
  exports.getSpendCapExceededError = getSpendCapExceededError;
49532
49905
  exports.getUserRoleScope = getUserRoleScope;
49906
+ exports.getVirtualMachineApiError = getVirtualMachineApiError;
49907
+ exports.getVirtualMachineErrorStatus = getVirtualMachineErrorStatus;
49533
49908
  exports.gradingApiSlice = gradingApiSlice;
49534
49909
  exports.hostingApiSlice = hostingApiSlice;
49535
49910
  exports.iblFakeBaseQuery = iblFakeBaseQuery;
49536
49911
  exports.initializeDataLayer = initializeDataLayer;
49537
49912
  exports.isBaseAgentMentor = isBaseAgentMentor;
49913
+ exports.isIpAddressHost = isIpAddressHost;
49538
49914
  exports.isPoliciesResponse = isPoliciesResponse;
49539
49915
  exports.isPrivacyBlockedError = isPrivacyBlockedError;
49916
+ exports.isRejectedHostname = isRejectedHostname;
49917
+ exports.isRejectedIpAddress = isRejectedIpAddress;
49540
49918
  exports.isSpendCapExceededErrorBody = isSpendCapExceededErrorBody;
49541
49919
  exports.isUserLlmUsageEmpty = isUserLlmUsageEmpty;
49920
+ exports.isValidHostPort = isValidHostPort;
49921
+ exports.isVirtualMachineEgressNetworked = isVirtualMachineEgressNetworked;
49542
49922
  exports.llmsApiSlice = llmsApiSlice;
49543
49923
  exports.mcpApiSlice = mcpApiSlice;
49544
49924
  exports.memoryApiSlice = memoryApiSlice;
@@ -49551,6 +49931,7 @@ exports.mentorReducer = mentorReducer;
49551
49931
  exports.moderationLogsApiReducer = moderationLogsApiReducer;
49552
49932
  exports.moderationLogsApiSlice = moderationLogsApiSlice;
49553
49933
  exports.monetizationApiSlice = monetizationApiSlice;
49934
+ exports.normalizeHostPort = normalizeHostPort;
49554
49935
  exports.normalizeLearnerCompletionError = normalizeLearnerCompletionError;
49555
49936
  exports.normalizeOutline = normalizeOutline;
49556
49937
  exports.normalizeUserLlmUsageError = normalizeUserLlmUsageError;
@@ -49573,6 +49954,7 @@ exports.skillsApiSlice = skillsApiSlice;
49573
49954
  exports.skillsMiddleware = skillsMiddleware;
49574
49955
  exports.skillsReducer = skillsReducer;
49575
49956
  exports.spendCapsApiSlice = spendCapsApiSlice;
49957
+ exports.splitHostPortInput = splitHostPortInput;
49576
49958
  exports.stripeApiSlice = stripeApiSlice;
49577
49959
  exports.studioAuthoringApiSlice = studioAuthoringApiSlice;
49578
49960
  exports.supportTicketsApiSlice = supportTicketsApiSlice;
@@ -49680,6 +50062,8 @@ exports.useCreateUserInstitutionMutation = useCreateUserInstitutionMutation;
49680
50062
  exports.useCreateUserInvitationMutation = useCreateUserInvitationMutation;
49681
50063
  exports.useCreateUserProjectMutation = useCreateUserProjectMutation;
49682
50064
  exports.useCreateUserResumeMutation = useCreateUserResumeMutation;
50065
+ exports.useCreateVirtualMachineNetworkPolicyMutation = useCreateVirtualMachineNetworkPolicyMutation;
50066
+ exports.useCreateVirtualMachineSecretMutation = useCreateVirtualMachineSecretMutation;
49683
50067
  exports.useCreateWatchedGroupMutation = useCreateWatchedGroupMutation;
49684
50068
  exports.useCreateWorkflowMutation = useCreateWorkflowMutation;
49685
50069
  exports.useDeactivateWorkflowMutation = useDeactivateWorkflowMutation;
@@ -49738,6 +50122,8 @@ exports.useDeleteUserEducationMutation = useDeleteUserEducationMutation;
49738
50122
  exports.useDeleteUserExperienceMutation = useDeleteUserExperienceMutation;
49739
50123
  exports.useDeleteUserProjectMutation = useDeleteUserProjectMutation;
49740
50124
  exports.useDeleteUserSpendCapMutation = useDeleteUserSpendCapMutation;
50125
+ exports.useDeleteVirtualMachineNetworkPolicyMutation = useDeleteVirtualMachineNetworkPolicyMutation;
50126
+ exports.useDeleteVirtualMachineSecretMutation = useDeleteVirtualMachineSecretMutation;
49741
50127
  exports.useDeleteWatchedGroupMutation = useDeleteWatchedGroupMutation;
49742
50128
  exports.useDeleteWatcherMutation = useDeleteWatcherMutation;
49743
50129
  exports.useDeleteWorkflowMutation = useDeleteWorkflowMutation;
@@ -50264,6 +50650,8 @@ exports.useLazyListOwnApplicationsQuery = useLazyListOwnApplicationsQuery;
50264
50650
  exports.useLazyListPaywallsQuery = useLazyListPaywallsQuery;
50265
50651
  exports.useLazyListPricesQuery = useLazyListPricesQuery;
50266
50652
  exports.useLazyListSubscribersQuery = useLazyListSubscribersQuery;
50653
+ exports.useLazyListVirtualMachineNetworkPoliciesQuery = useLazyListVirtualMachineNetworkPoliciesQuery;
50654
+ exports.useLazyListVirtualMachineSecretsQuery = useLazyListVirtualMachineSecretsQuery;
50267
50655
  exports.useLazyPlatformUserGroupsQuery = useLazyPlatformUserGroupsQuery;
50268
50656
  exports.useLazyPlatformUsersQuery = useLazyPlatformUsersQuery;
50269
50657
  exports.useLazyRefreshJwtTokenQuery = useLazyRefreshJwtTokenQuery;
@@ -50289,6 +50677,8 @@ exports.useListOwnApplicationsQuery = useListOwnApplicationsQuery;
50289
50677
  exports.useListPaywallsQuery = useListPaywallsQuery;
50290
50678
  exports.useListPricesQuery = useListPricesQuery;
50291
50679
  exports.useListSubscribersQuery = useListSubscribersQuery;
50680
+ exports.useListVirtualMachineNetworkPoliciesQuery = useListVirtualMachineNetworkPoliciesQuery;
50681
+ exports.useListVirtualMachineSecretsQuery = useListVirtualMachineSecretsQuery;
50292
50682
  exports.useMarkAllAsReadMutation = useMarkAllAsReadMutation;
50293
50683
  exports.useOauthFindMutation = useOauthFindMutation;
50294
50684
  exports.useOverrideGradeResultMutation = useOverrideGradeResultMutation;
@@ -50405,6 +50795,8 @@ exports.useUpdateUserProjectMutation = useUpdateUserProjectMutation;
50405
50795
  exports.useUpdateUserRoleMutation = useUpdateUserRoleMutation;
50406
50796
  exports.useUpdateUserStatusMutation = useUpdateUserStatusMutation;
50407
50797
  exports.useUpdateUserTrialStatusMutation = useUpdateUserTrialStatusMutation;
50798
+ exports.useUpdateVirtualMachineNetworkPolicyMutation = useUpdateVirtualMachineNetworkPolicyMutation;
50799
+ exports.useUpdateVirtualMachineSecretMutation = useUpdateVirtualMachineSecretMutation;
50408
50800
  exports.useUpdateWatchedGroupMutation = useUpdateWatchedGroupMutation;
50409
50801
  exports.useUpdateWatcherMutation = useUpdateWatcherMutation;
50410
50802
  exports.useUpdateWorkflowMutation = useUpdateWorkflowMutation;
@@ -50437,8 +50829,10 @@ exports.userApiSlice = userApiSlice;
50437
50829
  exports.userChatHistoryApiSlice = userChatHistoryApiSlice;
50438
50830
  exports.userInvitationsApiSlice = userInvitationsApiSlice;
50439
50831
  exports.userLlmUsageApiSlice = userLlmUsageApiSlice;
50832
+ exports.validateHostPort = validateHostPort;
50440
50833
  exports.validateLearnerCompletionArgs = validateLearnerCompletionArgs;
50441
50834
  exports.validateUserLlmUsageParams = validateUserLlmUsageParams;
50835
+ exports.virtualMachineApiSlice = virtualMachineApiSlice;
50442
50836
  exports.watchedGroupsApiSlice = watchedGroupsApiSlice;
50443
50837
  exports.workflowsApiSlice = workflowsApiSlice;
50444
50838
  //# sourceMappingURL=index.js.map