ag-ai 0.4.4 → 0.4.5

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.
@@ -13,7 +13,7 @@ iptables-restore <<'RULES'
13
13
  :OUTPUT DROP [0:0]
14
14
  -A INPUT -i lo -j ACCEPT
15
15
  -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
16
- -A INPUT -s __GENERATION_CIDR__ -p tcp --dport __GENERATION_PORT__ -j ACCEPT
16
+ __GENERATION_INGRESS__
17
17
  -A OUTPUT -o lo -j ACCEPT
18
18
  -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
19
19
  __DNS_RULES__
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runnerStack = void 0;
7
7
  const node_fs_1 = require("node:fs");
8
+ const node_net_1 = require("node:net");
8
9
  const node_path_1 = __importDefault(require("node:path"));
9
10
  const ag_rpi_mega_1 = require("ag-rpi-mega");
10
11
  const common_1 = require("./common");
@@ -12,12 +13,14 @@ const networkInitTemplate = (0, node_fs_1.readFileSync)(node_path_1.default.join
12
13
  /** The published runtime is installed into a writable emptyDir at pod start. */
13
14
  const AG_AI_RUNTIME_DIR = '/opt/ag-ai';
14
15
  const AG_AI_BRIDGE = `${AG_AI_RUNTIME_DIR}/node_modules/ag-ai/runtime/bridge.mjs`;
15
- const networkInitScript = ({ generationCidr, generationPort, opencodePort, }) => networkInitTemplate
16
- .replaceAll('__GENERATION_CIDR__', generationCidr)
16
+ const networkInitScript = ({ generationCidrs, generationPort, opencodePort, }) => networkInitTemplate
17
+ .replaceAll('__GENERATION_INGRESS__', generationCidrs
18
+ .map((cidr) => `-A INPUT -s ${cidr} -p tcp --dport ${generationPort} -j ACCEPT`)
19
+ .join('\n'))
17
20
  .replaceAll('__GENERATION_PORT__', String(generationPort))
18
21
  .replaceAll('__OPENCODE_PORT__', String(opencodePort))
19
22
  .replaceAll('__DNS_RULES__', '-A OUTPUT -p udp --dport 53 -j ACCEPT\n-A OUTPUT -p tcp --dport 53 -j ACCEPT')
20
- .replaceAll('__GENERATION_REJECT__', `-A OUTPUT -d ${generationCidr} -j REJECT`);
23
+ .replaceAll('__GENERATION_REJECT__', generationCidrs.map((cidr) => `-A OUTPUT -d ${cidr} -j REJECT`).join('\n'));
21
24
  const healthProbe = (readiness) => ({
22
25
  exec: {
23
26
  command: [
@@ -38,6 +41,25 @@ const runnerStack = (context) => {
38
41
  const generationCidr = context.env.AG_AI_GENERATION_CIDR;
39
42
  if (!generationCidr)
40
43
  throw new Error('AG_AI_GENERATION_CIDR is required');
44
+ const clusterCidr = context.env.AG_AI_GENERATION_CLUSTER_CIDR;
45
+ const generationCidrs = [generationCidr, ...(clusterCidr ? [clusterCidr] : [])];
46
+ for (const cidr of generationCidrs) {
47
+ const [address, prefix, ...extra] = cidr.split('/');
48
+ const minimum = address.startsWith('10.')
49
+ ? 8
50
+ : address.startsWith('192.168.')
51
+ ? 16
52
+ : /^172\.(1[6-9]|2\d|3[01])\./.test(address)
53
+ ? 12
54
+ : 33;
55
+ if ((0, node_net_1.isIP)(address) !== 4 ||
56
+ extra.length ||
57
+ !/^\d{1,2}$/.test(prefix) ||
58
+ Number(prefix) < minimum ||
59
+ Number(prefix) > 32) {
60
+ throw new Error('Generation ingress requires a valid private IPv4 CIDR');
61
+ }
62
+ }
41
63
  const imageProvider = context.env.AG_AI_IMAGE_PROVIDER ?? 'openai';
42
64
  const opencodeProvider = context.env.AG_AI_OPENCODE_PROVIDER;
43
65
  const agAiPackage = context.env.AG_AI_PACKAGE;
@@ -61,7 +83,7 @@ const runnerStack = (context) => {
61
83
  preserveData: true,
62
84
  data: {
63
85
  'network-init.sh': networkInitScript({
64
- generationCidr,
86
+ generationCidrs,
65
87
  generationPort: common_1.GENERATION_PORT,
66
88
  opencodePort: common_1.OPENCODE_PORT,
67
89
  }),
@@ -138,9 +160,10 @@ const runnerStack = (context) => {
138
160
  changeNFSFilePerms: false,
139
161
  });
140
162
  const spec = deployment.spec;
141
- // oxlint-disable-next-line typescript/no-unnecessary-condition -- the SDK class type hides runtime optionality.
142
- const pod = spec?.template?.spec;
143
- if (!spec || !pod)
163
+ if (!spec)
164
+ throw new Error('runner deployment is missing its specification');
165
+ const pod = spec.template.spec;
166
+ if (!pod)
144
167
  throw new Error('runner deployment is missing its pod specification');
145
168
  // A shared store must have only one writer during rollouts.
146
169
  spec.strategy = { type: 'Recreate' };
@@ -253,7 +276,7 @@ const runnerStack = (context) => {
253
276
  spec: {
254
277
  type: 'LoadBalancer',
255
278
  loadBalancerIP: metalLbAddress,
256
- loadBalancerSourceRanges: [generationCidr],
279
+ loadBalancerSourceRanges: generationCidrs,
257
280
  externalTrafficPolicy: 'Local',
258
281
  allocateLoadBalancerNodePorts: false,
259
282
  selector: { app: common_1.RUNNER_APP },
@@ -279,7 +302,7 @@ const runnerStack = (context) => {
279
302
  policyTypes: ['Ingress'],
280
303
  ingress: [
281
304
  {
282
- from: [{ ipBlock: { cidr: generationCidr } }],
305
+ from: generationCidrs.map((cidr) => ({ ipBlock: { cidr } })),
283
306
  ports: [{ protocol: 'TCP', port: common_1.GENERATION_PORT }],
284
307
  },
285
308
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ag-ai",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "Provider-neutral AI client and cluster runtime for the rpi-mega cluster.",
5
5
  "license": "ISC",
6
6
  "author": "admin@gec.dev",