4runr-os 2.10.60 → 2.10.62

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.
@@ -1 +1 @@
1
- {"version":3,"file":"sentinel-policies.d.ts","sourceRoot":"","sources":["../../../../../src/routes/sentinel-policies.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAaxE,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,eAAe,iBA4MlE"}
1
+ {"version":3,"file":"sentinel-policies.d.ts","sourceRoot":"","sources":["../../../../../src/routes/sentinel-policies.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAaxE,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,eAAe,iBAwQlE"}
@@ -130,6 +130,58 @@ export async function sentinelPolicyRoutes(fastify) {
130
130
  });
131
131
  }
132
132
  });
133
+ fastify.post('/api/sentinel/policies/custom', {
134
+ preHandler: [requireAuth, writeRateLimit],
135
+ }, async (request, reply) => {
136
+ try {
137
+ const body = (request.body || {});
138
+ const { Sentinel } = await import('@4runr/sentinel');
139
+ const sentinel = Sentinel.getInstance();
140
+ const current = sentinel.getConfig();
141
+ const num = (key, fallback) => {
142
+ const v = body[key];
143
+ if (typeof v === 'number' && Number.isFinite(v))
144
+ return v;
145
+ if (typeof v === 'string' && v.trim() !== '') {
146
+ const n = Number(v);
147
+ if (Number.isFinite(n))
148
+ return n;
149
+ }
150
+ return fallback;
151
+ };
152
+ const config = {
153
+ enabled: typeof body['enabled'] === 'boolean' ? body['enabled'] : current.enabled,
154
+ runMaxDurationMs: num('runMaxDurationMs', current.runMaxDurationMs),
155
+ runMaxTokens: num('runMaxTokens', current.runMaxTokens),
156
+ runIdleMs: num('runIdleMs', current.runIdleMs),
157
+ loopWindow: num('loopWindow', current.loopWindow),
158
+ loopMax: num('loopMax', current.loopMax),
159
+ runMaxCost: num('runMaxCost', current.runMaxCost ?? 1.0),
160
+ };
161
+ try {
162
+ sentinel.updateConfig(config);
163
+ return {
164
+ success: true,
165
+ config,
166
+ message: 'Custom Sentinel limits applied. Active until Gateway restart unless set via env.',
167
+ };
168
+ }
169
+ catch (error) {
170
+ const msg = error instanceof Error ? error.message : String(error);
171
+ return reply.status(400).send({
172
+ error: 'Invalid custom config',
173
+ details: msg,
174
+ });
175
+ }
176
+ }
177
+ catch (error) {
178
+ const msg = error instanceof Error ? error.message : String(error);
179
+ return reply.status(500).send({
180
+ error: 'Failed to apply custom config',
181
+ details: msg,
182
+ });
183
+ }
184
+ });
133
185
  fastify.get('/api/sentinel/policies/current', {
134
186
  preHandler: [requireAuth, readRateLimit],
135
187
  }, async (request, reply) => {
@@ -1 +1 @@
1
- {"version":3,"file":"sentinel-policies.js","sourceRoot":"","sources":["../../../../../src/routes/sentinel-policies.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sentinel-policies.js","sourceRoot":"","sources":["../../../../../src/routes/sentinel-policies.ts"],"names":[],"mappings":"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"}
@@ -199,15 +199,15 @@
199
199
  }
200
200
  },
201
201
  "node_modules/@aws-sdk/client-kms": {
202
- "version": "3.1057.0",
203
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-kms/-/client-kms-3.1057.0.tgz",
204
- "integrity": "sha512-S0LA7ks4eo2JpyG7UkpcNNgckYygi8H9URhG56tcD/ffYmydLPkXZeTl/Aj/BwMRe3dklMwrXTSRyknDmY2mXg==",
202
+ "version": "3.1058.0",
203
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-kms/-/client-kms-3.1058.0.tgz",
204
+ "integrity": "sha512-sZ+vpNFa7ACfV0sMPCYR4dIMN9LUH/M/7OStsTADSNzTKiRQKTt//Vsfu7ku0tHEjjVX5fOc6oSeu9LRu4tD6Q==",
205
205
  "license": "Apache-2.0",
206
206
  "dependencies": {
207
207
  "@aws-crypto/sha256-browser": "5.2.0",
208
208
  "@aws-crypto/sha256-js": "5.2.0",
209
209
  "@aws-sdk/core": "^3.974.15",
210
- "@aws-sdk/credential-provider-node": "^3.972.47",
210
+ "@aws-sdk/credential-provider-node": "^3.972.48",
211
211
  "@aws-sdk/types": "^3.973.9",
212
212
  "@smithy/core": "^3.24.5",
213
213
  "@smithy/fetch-http-handler": "^5.4.5",
@@ -220,15 +220,15 @@
220
220
  }
221
221
  },
222
222
  "node_modules/@aws-sdk/client-secrets-manager": {
223
- "version": "3.1057.0",
224
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.1057.0.tgz",
225
- "integrity": "sha512-2AsQ+7SChrQamIe68nMvMpZfXpHWnjwkcaFPFWf9E21+iTnEdIXRqC5v1P2NATrKn0BI6MaG/KlNrOhPOknk8w==",
223
+ "version": "3.1058.0",
224
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.1058.0.tgz",
225
+ "integrity": "sha512-m6u7ns0aA1dJGKVhqz7HQFEyvMu5ae67bxVmolSH3rQwHnvjRxWMCgGKWljgHI/Pd2OiRtodZlLikafjo65EPg==",
226
226
  "license": "Apache-2.0",
227
227
  "dependencies": {
228
228
  "@aws-crypto/sha256-browser": "5.2.0",
229
229
  "@aws-crypto/sha256-js": "5.2.0",
230
230
  "@aws-sdk/core": "^3.974.15",
231
- "@aws-sdk/credential-provider-node": "^3.972.47",
231
+ "@aws-sdk/credential-provider-node": "^3.972.48",
232
232
  "@aws-sdk/types": "^3.973.9",
233
233
  "@smithy/core": "^3.24.5",
234
234
  "@smithy/fetch-http-handler": "^5.4.5",
@@ -241,15 +241,15 @@
241
241
  }
242
242
  },
243
243
  "node_modules/@aws-sdk/client-ssm": {
244
- "version": "3.1057.0",
245
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1057.0.tgz",
246
- "integrity": "sha512-h+uTW2MTycbCqqBVJ6tGUuvehRX9gpvu+pL260pNd5nv0sQBDC1a9a/Ihz4rD/8KwmBrcd4ifeDV3gEoXpmnew==",
244
+ "version": "3.1058.0",
245
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1058.0.tgz",
246
+ "integrity": "sha512-xvJ0IahS3aepnIW1400dApwH3i/eJk+ggXNbNxnjHxjN8gozTFKn80HaboT/husAImv8qzJhZG/9ZeeT7o2USg==",
247
247
  "license": "Apache-2.0",
248
248
  "dependencies": {
249
249
  "@aws-crypto/sha256-browser": "5.2.0",
250
250
  "@aws-crypto/sha256-js": "5.2.0",
251
251
  "@aws-sdk/core": "^3.974.15",
252
- "@aws-sdk/credential-provider-node": "^3.972.47",
252
+ "@aws-sdk/credential-provider-node": "^3.972.48",
253
253
  "@aws-sdk/types": "^3.973.9",
254
254
  "@smithy/core": "^3.24.5",
255
255
  "@smithy/fetch-http-handler": "^5.4.5",
@@ -356,9 +356,9 @@
356
356
  }
357
357
  },
358
358
  "node_modules/@aws-sdk/credential-provider-node": {
359
- "version": "3.972.47",
360
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.47.tgz",
361
- "integrity": "sha512-HrId+C0DWA5qDIyLG64/kjUB2RNtPypxmABnIctK+TA1P1kHlOYoE/Wf5T5tKOMKgb08P7k/zNyhvfJ3lh5Oag==",
359
+ "version": "3.972.48",
360
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.48.tgz",
361
+ "integrity": "sha512-QIbtJP0olSLZ2ImEu636pP+7JJbPfaL3xSJIFXhu472CWuondCc4bGOa8OeyhOFet8z4H1D/ZFKXc39FboWwYA==",
362
362
  "license": "Apache-2.0",
363
363
  "dependencies": {
364
364
  "@aws-sdk/credential-provider-env": "^3.972.41",
@@ -2695,13 +2695,13 @@
2695
2695
  }
2696
2696
  },
2697
2697
  "node_modules/@smithy/core": {
2698
- "version": "3.24.5",
2699
- "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.24.5.tgz",
2700
- "integrity": "sha512-Kt8phUg45M15EjhYAbZ+fFikYneijLu9Liugz8ZsYz2i8j0hzGv27LWKpEHYRfvj+LyCOSijpcR/2i8RouV+cA==",
2698
+ "version": "3.24.6",
2699
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.24.6.tgz",
2700
+ "integrity": "sha512-wBXDRup6UU97VKyaiRo8AssnfStPtG0oAAfpq/bC0a1YYau8pM86YB4kM6ccoVi1mS8l/UHbn9oDM+7uozr/ug==",
2701
2701
  "license": "Apache-2.0",
2702
2702
  "dependencies": {
2703
2703
  "@aws-crypto/crc32": "5.2.0",
2704
- "@smithy/types": "^4.14.2",
2704
+ "@smithy/types": "^4.14.3",
2705
2705
  "tslib": "^2.6.2"
2706
2706
  },
2707
2707
  "engines": {
@@ -2709,13 +2709,13 @@
2709
2709
  }
2710
2710
  },
2711
2711
  "node_modules/@smithy/credential-provider-imds": {
2712
- "version": "4.3.6",
2713
- "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.6.tgz",
2714
- "integrity": "sha512-tHhdiWZfG1ZIh2YcRfPJmY2gHcBmqbAzqm3ER4TIDFYsSEqTD5tICT7cgQ/kI8LRakxp12myOYyK68XPn7MnHw==",
2712
+ "version": "4.3.7",
2713
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.7.tgz",
2714
+ "integrity": "sha512-xj8gq/bjFABAh6qWPSDCYcY3kzQIm4b561C+YnHH4zGq8rOgzQ3Shk+JGlpUxSd41UGiO6FkLdUCtNX1FAeHgg==",
2715
2715
  "license": "Apache-2.0",
2716
2716
  "dependencies": {
2717
- "@smithy/core": "^3.24.5",
2718
- "@smithy/types": "^4.14.2",
2717
+ "@smithy/core": "^3.24.6",
2718
+ "@smithy/types": "^4.14.3",
2719
2719
  "tslib": "^2.6.2"
2720
2720
  },
2721
2721
  "engines": {
@@ -2723,13 +2723,13 @@
2723
2723
  }
2724
2724
  },
2725
2725
  "node_modules/@smithy/fetch-http-handler": {
2726
- "version": "5.4.5",
2727
- "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.5.tgz",
2728
- "integrity": "sha512-SK3VMeH0fibgdTg2QeB+O4p7Yy/2E5HBOHJeC58FshkDdeuX8lOgO7PfjYfLyPLP1ch55j91cQqKBzDS0mRjSQ==",
2726
+ "version": "5.4.6",
2727
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.6.tgz",
2728
+ "integrity": "sha512-FEwEYJ1jlBKdhe9TPzfghEi1bP55ZeEImlDkEa62bBBYzUcnB6RUCyuiS2mqKt6ZVjUbBgcNhzfIctH+Hevx9g==",
2729
2729
  "license": "Apache-2.0",
2730
2730
  "dependencies": {
2731
- "@smithy/core": "^3.24.5",
2732
- "@smithy/types": "^4.14.2",
2731
+ "@smithy/core": "^3.24.6",
2732
+ "@smithy/types": "^4.14.3",
2733
2733
  "tslib": "^2.6.2"
2734
2734
  },
2735
2735
  "engines": {
@@ -2749,13 +2749,13 @@
2749
2749
  }
2750
2750
  },
2751
2751
  "node_modules/@smithy/node-http-handler": {
2752
- "version": "4.7.5",
2753
- "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.7.5.tgz",
2754
- "integrity": "sha512-3dA9TQ+ybRSZ/m0wnbZhiBy4Dezjgq1Ib/ZZrYTpJDBgpoLLU/SDzZc/g0x0MNAdOJe1wPcM+x2PBRmoOur+Sw==",
2752
+ "version": "4.7.6",
2753
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.7.6.tgz",
2754
+ "integrity": "sha512-3fya8i7GrJilQouk4cZJKdy5k8MWQBpjfXrRNaXDedH8r779tr0jcxyH3+yoTmsluc2+vF4S343yFbnvu8ExDQ==",
2755
2755
  "license": "Apache-2.0",
2756
2756
  "dependencies": {
2757
- "@smithy/core": "^3.24.5",
2758
- "@smithy/types": "^4.14.2",
2757
+ "@smithy/core": "^3.24.6",
2758
+ "@smithy/types": "^4.14.3",
2759
2759
  "tslib": "^2.6.2"
2760
2760
  },
2761
2761
  "engines": {
@@ -2763,13 +2763,13 @@
2763
2763
  }
2764
2764
  },
2765
2765
  "node_modules/@smithy/signature-v4": {
2766
- "version": "5.4.5",
2767
- "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.4.5.tgz",
2768
- "integrity": "sha512-QBJKWGqIknH0dc9LWpfH1mkdokAx6iXYN3UcQ3eY6uIEyScuoQAhfl94ge7ozUy9WgFUdE8xsvwBjaYBbWmPNA==",
2766
+ "version": "5.4.6",
2767
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.4.6.tgz",
2768
+ "integrity": "sha512-Ojg4B6oIDlIr1R86xCDJt1zJWnYa0VINmqdjfe9qxWjdRivHalZ3iSlQgVqYbW0MdpFOC5XfHEWsnbmdnpIILQ==",
2769
2769
  "license": "Apache-2.0",
2770
2770
  "dependencies": {
2771
- "@smithy/core": "^3.24.5",
2772
- "@smithy/types": "^4.14.2",
2771
+ "@smithy/core": "^3.24.6",
2772
+ "@smithy/types": "^4.14.3",
2773
2773
  "tslib": "^2.6.2"
2774
2774
  },
2775
2775
  "engines": {
@@ -2777,9 +2777,9 @@
2777
2777
  }
2778
2778
  },
2779
2779
  "node_modules/@smithy/types": {
2780
- "version": "4.14.2",
2781
- "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.2.tgz",
2782
- "integrity": "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw==",
2780
+ "version": "4.14.3",
2781
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.3.tgz",
2782
+ "integrity": "sha512-YupL0ZWmFtJexUN2cHzkvvF/b9pKrtAIfT1o7/oY/Ppu8IYeZ+lDPM5vZdQJaSeA132dJCqojjGC9NhXeF71VQ==",
2783
2783
  "license": "Apache-2.0",
2784
2784
  "dependencies": {
2785
2785
  "tslib": "^2.6.2"
@@ -191,6 +191,66 @@ export async function sentinelPolicyRoutes(fastify: FastifyInstance) {
191
191
  }
192
192
  );
193
193
 
194
+ /**
195
+ * POST /api/sentinel/policies/custom
196
+ * Apply operator-defined limits (merge with current config for omitted fields).
197
+ */
198
+ fastify.post(
199
+ '/api/sentinel/policies/custom',
200
+ {
201
+ preHandler: [requireAuth, writeRateLimit],
202
+ },
203
+ async (request: FastifyRequest, reply: FastifyReply) => {
204
+ try {
205
+ const body = (request.body || {}) as Record<string, unknown>;
206
+ const { Sentinel } = await import('@4runr/sentinel');
207
+ const sentinel = Sentinel.getInstance();
208
+ const current = sentinel.getConfig();
209
+
210
+ const num = (key: string, fallback: number): number => {
211
+ const v = body[key];
212
+ if (typeof v === 'number' && Number.isFinite(v)) return v;
213
+ if (typeof v === 'string' && v.trim() !== '') {
214
+ const n = Number(v);
215
+ if (Number.isFinite(n)) return n;
216
+ }
217
+ return fallback;
218
+ };
219
+
220
+ const config = {
221
+ enabled: typeof body['enabled'] === 'boolean' ? body['enabled'] : current.enabled,
222
+ runMaxDurationMs: num('runMaxDurationMs', current.runMaxDurationMs),
223
+ runMaxTokens: num('runMaxTokens', current.runMaxTokens),
224
+ runIdleMs: num('runIdleMs', current.runIdleMs),
225
+ loopWindow: num('loopWindow', current.loopWindow),
226
+ loopMax: num('loopMax', current.loopMax),
227
+ runMaxCost: num('runMaxCost', current.runMaxCost ?? 1.0),
228
+ };
229
+
230
+ try {
231
+ sentinel.updateConfig(config);
232
+ return {
233
+ success: true,
234
+ config,
235
+ message: 'Custom Sentinel limits applied. Active until Gateway restart unless set via env.',
236
+ };
237
+ } catch (error: unknown) {
238
+ const msg = error instanceof Error ? error.message : String(error);
239
+ return reply.status(400).send({
240
+ error: 'Invalid custom config',
241
+ details: msg,
242
+ });
243
+ }
244
+ } catch (error: unknown) {
245
+ const msg = error instanceof Error ? error.message : String(error);
246
+ return reply.status(500).send({
247
+ error: 'Failed to apply custom config',
248
+ details: msg,
249
+ });
250
+ }
251
+ }
252
+ );
253
+
194
254
  /**
195
255
  * GET /api/sentinel/policies/current
196
256
  * Get current policy configuration
@@ -1 +1 @@
1
- {"version":3,"file":"tui-handlers.d.ts","sourceRoot":"","sources":["../src/tui-handlers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQ5C,OAAO,EACL,aAAa,EAId,MAAM,qBAAqB,CAAC;AA0G7B;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,aAAa,EAAE,aAAa,GAAG,IAAI,EACnC,SAAS,EAAE,OAAO,GACjB,IAAI,CA0CN"}
1
+ {"version":3,"file":"tui-handlers.d.ts","sourceRoot":"","sources":["../src/tui-handlers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQ5C,OAAO,EACL,aAAa,EAId,MAAM,qBAAqB,CAAC;AA2G7B;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,aAAa,EAAE,aAAa,GAAG,IAAI,EACnC,SAAS,EAAE,OAAO,GACjB,IAAI,CA0CN"}
@@ -60,6 +60,7 @@ const DEDUPE_EXEMPT_COMMANDS = new Set([
60
60
  'monitoring.drill',
61
61
  'sentinel.load',
62
62
  'sentinel.apply',
63
+ 'sentinel.applyCustom',
63
64
  ]);
64
65
  function portCheckHint(port) {
65
66
  if (process.platform === 'win32') {
@@ -1320,6 +1321,49 @@ async function handleSentinelCommand(ctx, action) {
1320
1321
  }
1321
1322
  return;
1322
1323
  }
1324
+ if (action === 'applyCustom') {
1325
+ const d = ctx.data ?? {};
1326
+ const body = {};
1327
+ if (typeof d.enabled === 'boolean')
1328
+ body.enabled = d.enabled;
1329
+ for (const key of [
1330
+ 'runMaxDurationMs',
1331
+ 'runIdleMs',
1332
+ 'runMaxTokens',
1333
+ 'runMaxCost',
1334
+ 'loopWindow',
1335
+ 'loopMax',
1336
+ ]) {
1337
+ const v = d[key];
1338
+ if (typeof v === 'number' && Number.isFinite(v))
1339
+ body[key] = v;
1340
+ }
1341
+ try {
1342
+ const applyRaw = (await gc.postJson('/api/sentinel/policies/custom', body));
1343
+ const currentRaw = await gc.getJson('/api/sentinel/policies/current');
1344
+ const currentObj = currentRaw;
1345
+ const config = currentObj.config && typeof currentObj.config === 'object'
1346
+ ? currentObj.config
1347
+ : applyRaw.config && typeof applyRaw.config === 'object'
1348
+ ? applyRaw.config
1349
+ : {};
1350
+ ctx.server.sendResponse(ctx.ws, ctx.id, {
1351
+ success: true,
1352
+ data: {
1353
+ sentinelApply: true,
1354
+ custom: true,
1355
+ message: typeof applyRaw.message === 'string'
1356
+ ? applyRaw.message
1357
+ : 'Custom Sentinel limits applied.',
1358
+ current: config,
1359
+ },
1360
+ });
1361
+ }
1362
+ catch (e) {
1363
+ ctx.server.sendError(ctx.ws, ctx.id, errorMessage(e));
1364
+ }
1365
+ return;
1366
+ }
1323
1367
  ctx.server.sendError(ctx.ws, ctx.id, `Unknown sentinel action: ${action}`);
1324
1368
  }
1325
1369
  async function handleGatewayObservability(ctx) {