lua-cli 3.23.2 → 3.25.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
@@ -1146,6 +1146,9 @@ function isDesktopFileCommandName(value) {
1146
1146
  function isDesktopFileSessionId(value) {
1147
1147
  return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
1148
1148
  }
1149
+ function isImplicitModelSelectionSource(source) {
1150
+ return source !== void 0 && IMPLICIT_MODEL_SELECTION_SOURCES.includes(source);
1151
+ }
1149
1152
  function resolveRequireToolApproval(rules) {
1150
1153
  const raw = rules?.requireToolApproval ?? rules?.requireApproval;
1151
1154
  if (raw === void 0 || raw === null) return void 0;
@@ -1173,7 +1176,7 @@ function normalizeLuaJobExecutionTimeoutSeconds(timeout) {
1173
1176
  }
1174
1177
  return Math.min(Math.max(timeout, LUA_JOB_MIN_TIMEOUT_SECONDS), LUA_JOB_MAX_TIMEOUT_SECONDS);
1175
1178
  }
1176
- var __defProp2, __name2, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_MCP_SEND_TOOL_SUFFIX, MCP_TOOL_READ_VERB_RE, MCP_DRAFT_CREATE_VERBS, NON_INTERACTIVE_CHANNELS, RICH_PARTS_MESSAGE_ID_PREFIX, SCREENSHOT_MESSAGE_ID_PREFIX, BROWSER_COMMANDS, BROWSER_COMMAND_NAMES, DESKTOP_FILE_COMMANDS, DESKTOP_FILE_COMMAND_SET, REASONING_EFFORT_VALUES, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, AGENT_LOG_SOURCES, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema, LUA_JOB_DEFAULT_TIMEOUT_SECONDS, LUA_JOB_MIN_TIMEOUT_SECONDS, LUA_JOB_MAX_TIMEOUT_SECONDS;
1179
+ var __defProp2, __name2, REVIEWABLE_ACTION_EXECUTE_TOOL_ALLOWLIST, REVIEWABLE_MCP_SEND_TOOL_SUFFIX, MCP_TOOL_READ_VERB_RE, MCP_DRAFT_CREATE_VERBS, NON_INTERACTIVE_CHANNELS, RICH_PARTS_MESSAGE_ID_PREFIX, SCREENSHOT_MESSAGE_ID_PREFIX, BROWSER_COMMANDS, BROWSER_COMMAND_NAMES, DESKTOP_FILE_COMMANDS, DESKTOP_FILE_COMMAND_SET, REASONING_EFFORT_VALUES, IMPLICIT_MODEL_SELECTION_SOURCES, AGENT_NAME_TOKEN, DEFAULT_PERSONA_GUIDE, AGENT_LOG_SOURCES, VoiceNameSchema, PluginProviderSchema, RealtimeProviderSchema, PluginClassSchema, ModelDescriptorSchema, InferenceModelSchema, PluginModelSchema, RealtimeModelSchema, LuaVoiceModelSchema, TurnDetectionSchema, InterruptionSchema, BuiltinAudioClipSchema, AudioConfigSchema, BackgroundAudioEntrySchema, BackgroundAudioSchema, LuaVoiceConfigInnerSchema, LuaVoiceConfigSchema, LuaVoiceRefSchema, LUA_JOB_DEFAULT_TIMEOUT_SECONDS, LUA_JOB_MIN_TIMEOUT_SECONDS, LUA_JOB_MAX_TIMEOUT_SECONDS;
1177
1180
  var init_dist = __esm({
1178
1181
  "../shared-types/dist/index.mjs"() {
1179
1182
  "use strict";
@@ -1487,6 +1490,12 @@ var init_dist = __esm({
1487
1490
  "high",
1488
1491
  "max"
1489
1492
  ];
1493
+ IMPLICIT_MODEL_SELECTION_SOURCES = [
1494
+ "workspace-default",
1495
+ "platform-default"
1496
+ ];
1497
+ __name(isImplicitModelSelectionSource, "isImplicitModelSelectionSource");
1498
+ __name2(isImplicitModelSelectionSource, "isImplicitModelSelectionSource");
1490
1499
  __name(resolveRequireToolApproval, "resolveRequireToolApproval");
1491
1500
  __name2(resolveRequireToolApproval, "resolveRequireToolApproval");
1492
1501
  AGENT_NAME_TOKEN = "[Your Agent Name]";
@@ -7588,7 +7597,8 @@ var init_agent_plugin = __esm({
7588
7597
  const isDefaultExport = classDecl.isDefaultExport();
7589
7598
  const exportName = isDefaultExport ? "default" : className;
7590
7599
  const name = readStringMember(classDecl, "name") ?? deriveNameFromClassName(className);
7591
- const baseDescription = readStringMember(classDecl, "description") ?? "";
7600
+ const routingDescription = readStringMember(classDecl, "description");
7601
+ const baseDescription = routingDescription ?? "";
7592
7602
  const personaHit = findClassMember(classDecl, "persona", "property");
7593
7603
  let persona = "";
7594
7604
  if (personaHit && Node13.isPropertyDeclaration(personaHit.node)) {
@@ -7639,6 +7649,7 @@ var init_agent_plugin = __esm({
7639
7649
  metadata: {
7640
7650
  pattern: "class-definition",
7641
7651
  persona,
7652
+ routingDescription,
7642
7653
  model,
7643
7654
  hasModelResolver,
7644
7655
  modelSettings,
@@ -7671,6 +7682,7 @@ var init_agent_plugin = __esm({
7671
7682
  "voice",
7672
7683
  "text"
7673
7684
  ]) ?? "";
7685
+ const routingDescription = extractStringProperty(config, "description");
7674
7686
  const { model, hasModelResolver } = this.extractModelInfo(config);
7675
7687
  const modelSettings = this.extractModelSettings(config);
7676
7688
  const batching = this.extractBatchingInfo(config);
@@ -7688,6 +7700,7 @@ var init_agent_plugin = __esm({
7688
7700
  metadata: {
7689
7701
  pattern,
7690
7702
  persona,
7703
+ routingDescription,
7691
7704
  model,
7692
7705
  hasModelResolver,
7693
7706
  modelSettings,
@@ -7873,6 +7886,7 @@ var init_agent_plugin = __esm({
7873
7886
  return {
7874
7887
  ...this.baseManifestFields(compiled),
7875
7888
  persona: agentMeta.persona,
7889
+ routingDescription: agentMeta.routingDescription,
7876
7890
  model: agentMeta.model,
7877
7891
  hasModelResolver: agentMeta.hasModelResolver || void 0,
7878
7892
  modelSettings: agentMeta.modelSettings,
@@ -12890,17 +12904,42 @@ var init_custom_data_api_service = __esm({
12890
12904
  this.agentId = agentId;
12891
12905
  }
12892
12906
  /**
12907
+ * Lists the agent's data collections with entry counts, timestamps, and —
12908
+ * when declared — managed index status (fields, pending/building/ready/
12909
+ * failed/rejected, error reason). The place to diagnose index declarations.
12910
+ * @returns Promise resolving to the collections listing
12911
+ */
12912
+ async collections() {
12913
+ const response = await this.httpGet(`/developer/agents/${this.agentId}/custom-data`, {
12914
+ Authorization: `Bearer ${this.apiKey}`
12915
+ });
12916
+ if (response.success && response.data) {
12917
+ return response.data;
12918
+ }
12919
+ throw new Error(response.error?.message || "Failed to list custom data collections");
12920
+ }
12921
+ /**
12893
12922
  * Creates a new custom data entry in a specified collection
12894
12923
  * @param collectionName - The name of the collection to create the entry in
12895
12924
  * @param data - The data object to store in the entry
12896
- * @param searchText - Optional text to be used for semantic search indexing
12925
+ * @param optionsOrSearchText - Either a searchText string (legacy form) or an
12926
+ * options object: `searchText` for semantic search indexing, and `index` to
12927
+ * declare data fields this agent filters on (e.g. `['business_id']` or
12928
+ * compounds like `[['country', 'business_id']]`). Declared fields get
12929
+ * agent-scoped database indexes maintained by the platform: created when
12930
+ * first declared, removed automatically ~14 days after the code stops
12931
+ * declaring them. Declaring on every write is the intended, idempotent use.
12897
12932
  * @returns Promise resolving to a DataEntryInstance representing the created entry
12898
12933
  * @throws Error if the entry creation fails or the API request is unsuccessful
12899
12934
  */
12900
- async create(collectionName, data, searchText) {
12935
+ async create(collectionName, data, optionsOrSearchText) {
12936
+ const options = typeof optionsOrSearchText === "string" ? {
12937
+ searchText: optionsOrSearchText
12938
+ } : optionsOrSearchText ?? {};
12901
12939
  const response = await this.httpPost(`/developer/agents/${this.agentId}/custom-data/${collectionName}`, {
12902
12940
  data,
12903
- searchText
12941
+ searchText: options.searchText,
12942
+ index: options.index
12904
12943
  }, {
12905
12944
  Authorization: `Bearer ${this.apiKey}`
12906
12945
  });
@@ -12953,14 +12992,19 @@ var init_custom_data_api_service = __esm({
12953
12992
  * @param collectionName - The name of the collection containing the entry
12954
12993
  * @param entryId - The unique identifier of the entry to update
12955
12994
  * @param data - The data object to update
12956
- * @param searchText - Optional text to be used for semantic search indexing
12995
+ * @param optionsOrSearchText - searchText string (legacy) or { searchText?, index? };
12996
+ * `index` refreshes this agent's index declarations (same semantics as create)
12957
12997
  * @returns Promise resolving to an UpdateCustomDataResponse with the updated entry details
12958
12998
  * @throws Error if the entry is not found or the update fails
12959
12999
  */
12960
- async update(collectionName, entryId, data, searchText) {
13000
+ async update(collectionName, entryId, data, optionsOrSearchText) {
13001
+ const options = typeof optionsOrSearchText === "string" ? {
13002
+ searchText: optionsOrSearchText
13003
+ } : optionsOrSearchText ?? {};
12961
13004
  const response = await this.httpPut(`/developer/agents/${this.agentId}/custom-data/${collectionName}/${entryId}`, {
12962
13005
  data,
12963
- searchText
13006
+ searchText: options.searchText,
13007
+ index: options.index
12964
13008
  }, {
12965
13009
  Authorization: `Bearer ${this.apiKey}`
12966
13010
  });
@@ -13648,6 +13692,31 @@ var init_channels_send_api_service = __esm({
13648
13692
  }
13649
13693
  });
13650
13694
 
13695
+ // src/api/inbox-push.api.service.ts
13696
+ var InboxPushApiService;
13697
+ var init_inbox_push_api_service = __esm({
13698
+ "src/api/inbox-push.api.service.ts"() {
13699
+ "use strict";
13700
+ init_http_client();
13701
+ InboxPushApiService = class extends HttpClient {
13702
+ static {
13703
+ __name(this, "InboxPushApiService");
13704
+ }
13705
+ apiKey;
13706
+ agentId;
13707
+ constructor(baseUrl, apiKey, agentId) {
13708
+ super(baseUrl), this.apiKey = apiKey, this.agentId = agentId;
13709
+ }
13710
+ /** POST /developer/agents/:agentId/inbox/push */
13711
+ async push(input) {
13712
+ return this.httpPost(`/developer/agents/${this.agentId}/inbox/push`, input, {
13713
+ Authorization: `Bearer ${this.apiKey}`
13714
+ });
13715
+ }
13716
+ };
13717
+ }
13718
+ });
13719
+
13651
13720
  // src/api/directory.api.service.ts
13652
13721
  var DirectoryApiService;
13653
13722
  var init_directory_api_service = __esm({
@@ -13783,6 +13852,7 @@ __export(lazy_instances_exports, {
13783
13852
  getDeveloperInstance: () => getDeveloperInstance,
13784
13853
  getDeviceInstance: () => getDeviceInstance,
13785
13854
  getDirectoryInstance: () => getDirectoryInstance,
13855
+ getInboxPushInstance: () => getInboxPushInstance,
13786
13856
  getJobInstance: () => getJobInstance,
13787
13857
  getOrderInstance: () => getOrderInstance,
13788
13858
  getProductsInstance: () => getProductsInstance,
@@ -13890,6 +13960,13 @@ async function getVoiceInstance() {
13890
13960
  }
13891
13961
  return _voiceInstance;
13892
13962
  }
13963
+ async function getInboxPushInstance() {
13964
+ if (!_inboxPushInstance) {
13965
+ const creds = await getCredentials();
13966
+ _inboxPushInstance = new InboxPushApiService(BASE_URLS.API, creds.apiKey, creds.agentId);
13967
+ }
13968
+ return _inboxPushInstance;
13969
+ }
13893
13970
  async function getChannelsSendInstance() {
13894
13971
  if (!_channelsSendInstance) {
13895
13972
  const creds = await getCredentials();
@@ -13921,7 +13998,7 @@ function clearAllInstances() {
13921
13998
  _channelsSendInstance = null;
13922
13999
  _directoryInstance = null;
13923
14000
  }
13924
- var _userInstance, _dataInstance, _productsInstance, _basketsInstance, _orderInstance, _webhookInstance, _jobInstance, _aiInstance, _agentsInstance, _whatsAppTemplatesInstance, _cdnInstance, _developerInstance, _voiceInstance, _channelsSendInstance, _directoryInstance, _deviceInstance;
14001
+ var _userInstance, _dataInstance, _productsInstance, _basketsInstance, _orderInstance, _webhookInstance, _jobInstance, _aiInstance, _agentsInstance, _whatsAppTemplatesInstance, _cdnInstance, _developerInstance, _voiceInstance, _channelsSendInstance, _directoryInstance, _deviceInstance, _inboxPushInstance;
13925
14002
  var init_lazy_instances = __esm({
13926
14003
  "src/api/lazy-instances.ts"() {
13927
14004
  "use strict";
@@ -13941,6 +14018,7 @@ var init_lazy_instances = __esm({
13941
14018
  init_developer_api_service();
13942
14019
  init_voice_api_service();
13943
14020
  init_channels_send_api_service();
14021
+ init_inbox_push_api_service();
13944
14022
  init_directory_api_service();
13945
14023
  _userInstance = null;
13946
14024
  _dataInstance = null;
@@ -13972,6 +14050,8 @@ var init_lazy_instances = __esm({
13972
14050
  __name(getDeviceInstance, "getDeviceInstance");
13973
14051
  __name(getDeveloperInstance, "getDeveloperInstance");
13974
14052
  __name(getVoiceInstance, "getVoiceInstance");
14053
+ _inboxPushInstance = null;
14054
+ __name(getInboxPushInstance, "getInboxPushInstance");
13975
14055
  __name(getChannelsSendInstance, "getChannelsSendInstance");
13976
14056
  __name(getDirectoryInstance, "getDirectoryInstance");
13977
14057
  __name(clearAllInstances, "clearAllInstances");
@@ -16939,6 +17019,29 @@ var AgentHandler = class {
16939
17019
  async pushAgentConfig(apiKey, agentId, manifest) {
16940
17020
  const result = {};
16941
17021
  const agent = getPrimitivesByKind(manifest, PrimitiveKind.AGENT)[0];
17022
+ if (agent?.routingDescription !== void 0) {
17023
+ writeProgress("\n\u{1F9ED} Pushing routing description...");
17024
+ try {
17025
+ const success2 = await this.pushDescription({
17026
+ apiKey,
17027
+ agentId
17028
+ }, agent.routingDescription);
17029
+ result.description = {
17030
+ success: success2
17031
+ };
17032
+ if (success2) {
17033
+ writeSuccess(agent.routingDescription ? " \u2705 Routing description pushed" : " \u2705 Routing description cleared");
17034
+ } else {
17035
+ console.error(" \u274C Failed to push routing description");
17036
+ }
17037
+ } catch (error) {
17038
+ if (AuthenticationError.isAuthenticationError(error)) throw error;
17039
+ console.error(` \u274C Failed to push routing description: ${error.message}`);
17040
+ result.description = {
17041
+ success: false
17042
+ };
17043
+ }
17044
+ }
16942
17045
  const persona = agent?.persona;
16943
17046
  if (hasPersonaTextContent(persona)) {
16944
17047
  writeProgress("\n\u{1F319} Pushing persona...");
@@ -17163,6 +17266,13 @@ var AgentHandler = class {
17163
17266
  });
17164
17267
  return result.success;
17165
17268
  }
17269
+ async pushDescription(ctx, description) {
17270
+ const agentApi = new AgentApi(BASE_URLS.API, ctx.apiKey);
17271
+ const result = await agentApi.updateAgent(ctx.agentId, {
17272
+ description
17273
+ });
17274
+ return result.success;
17275
+ }
17166
17276
  async pushPersona(ctx, persona) {
17167
17277
  const personaApi = new PersonaApi(BASE_URLS.API, ctx.apiKey, ctx.agentId);
17168
17278
  const result = await personaApi.createVersion(persona);
@@ -20723,6 +20833,14 @@ var DEFAULT_BLOCK_CIDRS = [
20723
20833
  "fe80::/10",
20724
20834
  "fc00::/7"
20725
20835
  ];
20836
+ var HOSTNAME_NON_OVERRIDABLE_CIDRS = [
20837
+ "127.0.0.0/8",
20838
+ "169.254.0.0/16",
20839
+ "0.0.0.0/8",
20840
+ "::1/128",
20841
+ "fe80::/10",
20842
+ "fd00:ec2::254/128"
20843
+ ];
20726
20844
  function ipv4ToInt(ip) {
20727
20845
  const parts = ip.split(".").map(Number);
20728
20846
  if (parts.length !== 4 || parts.some((n) => Number.isNaN(n) || n < 0 || n > 255)) {
@@ -20824,24 +20942,50 @@ function ipInCidr(ip, cidrs) {
20824
20942
  }
20825
20943
  __name(ipInCidr, "ipInCidr");
20826
20944
  __name4(ipInCidr, "ipInCidr");
20945
+ function normalizeHostname(hostname) {
20946
+ return stripBrackets(hostname.trim()).toLowerCase().replace(/\.$/, "");
20947
+ }
20948
+ __name(normalizeHostname, "normalizeHostname");
20949
+ __name4(normalizeHostname, "normalizeHostname");
20950
+ function parseAllowedHostname(value) {
20951
+ const hostname = normalizeHostname(value);
20952
+ if (!hostname || net.isIP(hostname) || /[\s*/:\\?#]/.test(hostname)) {
20953
+ throw new Error(`Invalid sandbox egress hostname allowlist entry: ${JSON.stringify(value)}. Use an exact hostname without a wildcard, URL, port, or IP literal.`);
20954
+ }
20955
+ return hostname;
20956
+ }
20957
+ __name(parseAllowedHostname, "parseAllowedHostname");
20958
+ __name4(parseAllowedHostname, "parseAllowedHostname");
20827
20959
  function compile2(opts) {
20828
20960
  return {
20829
20961
  blockCidrs: DEFAULT_BLOCK_CIDRS.map(parseCidr),
20830
20962
  allowCidrs: (opts.extraAllowedCidrs ?? []).map(parseCidr),
20963
+ allowHostnames: new Set((opts.extraAllowedHostnames ?? []).map(parseAllowedHostname)),
20964
+ hostnameNonOverridableCidrs: HOSTNAME_NON_OVERRIDABLE_CIDRS.map(parseCidr),
20831
20965
  mode: opts.mode,
20832
20966
  onEvent: opts.onSecurityEvent
20833
20967
  };
20834
20968
  }
20835
20969
  __name(compile2, "compile");
20836
20970
  __name4(compile2, "compile");
20837
- function checkAddress(address, guard) {
20838
- if (ipInCidr(address, guard.allowCidrs)) return null;
20971
+ function isAllowedHostname(hostname, guard) {
20972
+ return !net.isIP(hostname) && guard.allowHostnames.has(normalizeHostname(hostname));
20973
+ }
20974
+ __name(isAllowedHostname, "isAllowedHostname");
20975
+ __name4(isAllowedHostname, "isAllowedHostname");
20976
+ function checkAddress(address, guard, allowedByHostname = false) {
20977
+ const v4 = ipv4MappedFromIpv6(address);
20978
+ if (ipInCidr(address, guard.allowCidrs) || v4 !== null && ipInCidr(v4, guard.allowCidrs)) return null;
20979
+ if (allowedByHostname) {
20980
+ if (ipInCidr(address, guard.hostnameNonOverridableCidrs) || v4 !== null && ipInCidr(v4, guard.hostnameNonOverridableCidrs)) {
20981
+ return `address ${address} is protected from sandbox hostname allowances`;
20982
+ }
20983
+ return null;
20984
+ }
20839
20985
  if (ipInCidr(address, guard.blockCidrs)) {
20840
20986
  return `address ${address} is in the sandbox egress block list`;
20841
20987
  }
20842
- const v4 = ipv4MappedFromIpv6(address);
20843
20988
  if (v4) {
20844
- if (ipInCidr(v4, guard.allowCidrs)) return null;
20845
20989
  if (ipInCidr(v4, guard.blockCidrs)) {
20846
20990
  return `address ${address} (IPv4-mapped: ${v4}) is in the sandbox egress block list`;
20847
20991
  }
@@ -20866,8 +21010,9 @@ async function resolveAndCheck(hostname, guard) {
20866
21010
  } catch {
20867
21011
  return null;
20868
21012
  }
21013
+ const allowedByHostname = isAllowedHostname(hostname, guard);
20869
21014
  for (const { address } of addresses) {
20870
- const reason = checkAddress(address, guard);
21015
+ const reason = checkAddress(address, guard, allowedByHostname);
20871
21016
  if (reason) return {
20872
21017
  reason,
20873
21018
  address
@@ -20978,8 +21123,9 @@ function buildBlockingLookup(guard, target) {
20978
21123
  }, (err, addresses) => {
20979
21124
  if (err) return cb(err);
20980
21125
  const list = addresses;
21126
+ const allowedByHostname = isAllowedHostname(hostname, guard);
20981
21127
  for (const { address } of list) {
20982
- const reason = checkAddress(address, guard);
21128
+ const reason = checkAddress(address, guard, allowedByHostname);
20983
21129
  if (reason) {
20984
21130
  emit(guard, target, reason, address);
20985
21131
  if (guard.mode === "enforce") {
@@ -21275,6 +21421,7 @@ function createBaseSandboxContext(opts) {
21275
21421
  const egressOpts = {
21276
21422
  mode: egressMode,
21277
21423
  extraAllowedCidrs: opts.egressExtraAllowedCidrs,
21424
+ extraAllowedHostnames: opts.egressExtraAllowedHostnames,
21278
21425
  onSecurityEvent: onSecurityEvent ? (evt) => onSecurityEvent(evt) : void 0
21279
21426
  };
21280
21427
  const wrappedModuleCache = /* @__PURE__ */ new Map();
@@ -21338,6 +21485,13 @@ function resolveExtraAllowedCidrs() {
21338
21485
  }
21339
21486
  __name(resolveExtraAllowedCidrs, "resolveExtraAllowedCidrs");
21340
21487
  __name4(resolveExtraAllowedCidrs, "resolveExtraAllowedCidrs");
21488
+ function resolveExtraAllowedHostnames() {
21489
+ const csv = process.env.LUA_ALLOWED_EGRESS_HOSTNAMES;
21490
+ if (!csv) return [];
21491
+ return csv.split(",").map((s) => s.trim()).filter(Boolean);
21492
+ }
21493
+ __name(resolveExtraAllowedHostnames, "resolveExtraAllowedHostnames");
21494
+ __name4(resolveExtraAllowedHostnames, "resolveExtraAllowedHostnames");
21341
21495
  function wrapBundleAsCjsModule(source) {
21342
21496
  return "(function(module, exports, require) {\n" + source + "\n})(module, module.exports, require);";
21343
21497
  }
@@ -21571,6 +21725,12 @@ function resolveExtraAllowedCidrs2() {
21571
21725
  return csv.split(",").map((s) => s.trim()).filter(Boolean);
21572
21726
  }
21573
21727
  __name(resolveExtraAllowedCidrs2, "resolveExtraAllowedCidrs");
21728
+ function resolveExtraAllowedHostnames2() {
21729
+ const csv = process.env.LUA_ALLOWED_EGRESS_HOSTNAMES;
21730
+ if (!csv) return [];
21731
+ return csv.split(",").map((s) => s.trim()).filter(Boolean);
21732
+ }
21733
+ __name(resolveExtraAllowedHostnames2, "resolveExtraAllowedHostnames");
21574
21734
  function defaultSecurityEventLogger(evt) {
21575
21735
  console.warn("[sandbox]", JSON.stringify(evt));
21576
21736
  }
@@ -21759,6 +21919,7 @@ function createSandbox(options) {
21759
21919
  requireMode: resolveRequireMode(),
21760
21920
  egressMode: resolveEgressMode(),
21761
21921
  egressExtraAllowedCidrs: resolveExtraAllowedCidrs2(),
21922
+ egressExtraAllowedHostnames: resolveExtraAllowedHostnames2(),
21762
21923
  onSecurityEvent: defaultSecurityEventLogger
21763
21924
  });
21764
21925
  }