neoagent 3.0.1-beta.29 → 3.0.1-beta.30
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/docs/billing.md +5 -0
- package/package.json +1 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +4 -4
- package/server/services/ai/loop/conversation_loop.js +3 -1
- package/server/services/ai/rate_limits.js +27 -23
- package/server/services/tasks/runtime.js +2 -1
package/docs/billing.md
CHANGED
|
@@ -61,6 +61,11 @@ Token limits are written directly to the user account when a subscription
|
|
|
61
61
|
becomes active or is updated via webhook. The existing rate-limit enforcement
|
|
62
62
|
in the runtime reads them with no additional configuration.
|
|
63
63
|
|
|
64
|
+
Token limits gate interactive run starts. Background task executions are not
|
|
65
|
+
blocked by the internal token admission check, so scheduled and integration
|
|
66
|
+
tasks can still run while a user is over quota. Their token usage is still
|
|
67
|
+
recorded and included in account and admin usage snapshots.
|
|
68
|
+
|
|
64
69
|
### Free plan
|
|
65
70
|
|
|
66
71
|
Create a plan with **Price = 0** to serve as the default for new users. If a
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
400b929549327d2b7624182c525fe34e
|
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"a10d8ac38de835021c8d2f920dbf50a920ccc0
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "74968846" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|
|
@@ -138719,7 +138719,7 @@ r===$&&A.b()
|
|
|
138719
138719
|
p.push(A.iU(q,A.ju(!1,new A.Y(B.vr,A.cN(new A.cA(B.jU,new A.a94(r,q),q),q,q),q),!1,B.I,!0),q,q,0,0,0,q))}r=!1
|
|
138720
138720
|
if(!s.ay)if(!s.ch){r=s.e
|
|
138721
138721
|
r===$&&A.b()
|
|
138722
|
-
r=B.b.t("
|
|
138722
|
+
r=B.b.t("mr09cv28-5adc70e").length!==0&&r.b}if(r){r=s.d
|
|
138723
138723
|
r===$&&A.b()
|
|
138724
138724
|
r=r.aD&&!r.av?84:0
|
|
138725
138725
|
s=s.e
|
|
@@ -145015,7 +145015,7 @@ $S:0}
|
|
|
145015
145015
|
A.a0g.prototype={}
|
|
145016
145016
|
A.U0.prototype={
|
|
145017
145017
|
nm(a){var s=this
|
|
145018
|
-
if(B.b.t("
|
|
145018
|
+
if(B.b.t("mr09cv28-5adc70e").length===0||s.a!=null)return
|
|
145019
145019
|
s.Bg()
|
|
145020
145020
|
s.a=A.m4(B.Td,new A.bgn(s))},
|
|
145021
145021
|
Bg(){var s=0,r=A.l(t.H),q,p=2,o=[],n=this,m,l,k,j,i,h,g,f
|
|
@@ -145033,7 +145033,7 @@ if(!t.f.b(k)){s=1
|
|
|
145033
145033
|
break}i=J.a2(k,"buildId")
|
|
145034
145034
|
h=i==null?null:B.b.t(J.p(i))
|
|
145035
145035
|
j=h==null?"":h
|
|
145036
|
-
if(J.bd(j)===0||J.f(j,"
|
|
145036
|
+
if(J.bd(j)===0||J.f(j,"mr09cv28-5adc70e")){s=1
|
|
145037
145037
|
break}n.b=!0
|
|
145038
145038
|
n.E()
|
|
145039
145039
|
p=2
|
|
@@ -145050,7 +145050,7 @@ case 2:return A.i(o.at(-1),r)}})
|
|
|
145050
145050
|
return A.k($async$Bg,r)},
|
|
145051
145051
|
vV(){var s=0,r=A.l(t.H),q,p=2,o=[],n=this,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1
|
|
145052
145052
|
var $async$vV=A.h(function(a2,a3){if(a2===1){o.push(a3)
|
|
145053
|
-
s=p}for(;;)switch(s){case 0:if(B.b.t("
|
|
145053
|
+
s=p}for(;;)switch(s){case 0:if(B.b.t("mr09cv28-5adc70e").length===0||n.c){s=1
|
|
145054
145054
|
break}n.c=!0
|
|
145055
145055
|
n.E()
|
|
145056
145056
|
p=4
|
|
@@ -571,7 +571,9 @@ async function runConversation(engine, userId, userMessage, options = {}, _model
|
|
|
571
571
|
let deliverableWorkflow = null;
|
|
572
572
|
const timelineService = app?.locals?.timelineService || null;
|
|
573
573
|
|
|
574
|
-
const { releaseReservation } = enforceRateLimits(userId
|
|
574
|
+
const { releaseReservation } = enforceRateLimits(userId, {
|
|
575
|
+
bypass: options.bypassUserRateLimits === true,
|
|
576
|
+
});
|
|
575
577
|
|
|
576
578
|
try {
|
|
577
579
|
const historyWindow = Math.max(
|
|
@@ -9,12 +9,7 @@ const _reservations = new Map();
|
|
|
9
9
|
const DEFAULT_RATE_LIMIT_4H = 2_500_000;
|
|
10
10
|
const DEFAULT_RATE_LIMIT_WEEKLY = 10_000_000;
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
// reservation that keeps concurrent run starts from collectively bypassing the
|
|
14
|
-
// per-user budget. It must NOT be the full limit — doing so would reserve the
|
|
15
|
-
// entire budget for one run and reject any second concurrent run for the same
|
|
16
|
-
// user (e.g. a scheduled task firing in the same minute as another).
|
|
17
|
-
const DEFAULT_RUN_RESERVATION_TOKENS = 500_000;
|
|
12
|
+
const MAX_RUN_RESERVATION_TOKENS = 100_000;
|
|
18
13
|
|
|
19
14
|
const WINDOWS = {
|
|
20
15
|
fourHour: {
|
|
@@ -142,7 +137,28 @@ function getRateLimitSnapshot(userId, { includeReservations = false } = {}) {
|
|
|
142
137
|
};
|
|
143
138
|
}
|
|
144
139
|
|
|
145
|
-
function
|
|
140
|
+
function noopReleaseReservation() {}
|
|
141
|
+
|
|
142
|
+
function calculateReservation(limits) {
|
|
143
|
+
const finiteLimits = [limits.fourHour, limits.weekly]
|
|
144
|
+
.filter((limit) => Number.isFinite(limit) && limit > 0);
|
|
145
|
+
if (finiteLimits.length === 0) return 1;
|
|
146
|
+
const minFiniteLimit = Math.min(...finiteLimits);
|
|
147
|
+
return Math.min(
|
|
148
|
+
MAX_RUN_RESERVATION_TOKENS,
|
|
149
|
+
Math.max(1, Math.floor(minFiniteLimit * 0.1)),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function enforceRateLimits(userId, options = {}) {
|
|
154
|
+
if (options.bypass === true) {
|
|
155
|
+
return {
|
|
156
|
+
snapshot: getRateLimitSnapshot(userId, { includeReservations: false }),
|
|
157
|
+
releaseReservation: noopReleaseReservation,
|
|
158
|
+
bypassed: true,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
146
162
|
const snapshot = getRateLimitSnapshot(userId, { includeReservations: true });
|
|
147
163
|
if (snapshot.reached.fourHour) {
|
|
148
164
|
throw new RateLimitExceededError('fourHour', snapshot);
|
|
@@ -150,23 +166,10 @@ function enforceRateLimits(userId) {
|
|
|
150
166
|
if (snapshot.reached.weekly) {
|
|
151
167
|
throw new RateLimitExceededError('weekly', snapshot);
|
|
152
168
|
}
|
|
153
|
-
// Reserve a placeholder so concurrent starts see this run as
|
|
154
|
-
//
|
|
155
|
-
// to a realistic per-run estimate — never the full limit — so concurrent runs
|
|
156
|
-
// for the same user are admitted normally and only a genuinely near-budget
|
|
157
|
-
// user gets throttled. Clamp so the reservation can never by itself exceed a
|
|
158
|
-
// (possibly small/custom) limit.
|
|
169
|
+
// Reserve a bounded placeholder so concurrent starts see this run as
|
|
170
|
+
// in-flight without letting one run consume the user's entire budget.
|
|
159
171
|
const key = String(userId);
|
|
160
|
-
const
|
|
161
|
-
const estimate = parsePositiveInteger(
|
|
162
|
-
process.env.NEOAGENT_RUN_RESERVATION_TOKENS,
|
|
163
|
-
DEFAULT_RUN_RESERVATION_TOKENS,
|
|
164
|
-
);
|
|
165
|
-
const cap = Math.min(
|
|
166
|
-
limits.fourHour == null ? Infinity : limits.fourHour,
|
|
167
|
-
limits.weekly == null ? Infinity : limits.weekly,
|
|
168
|
-
);
|
|
169
|
-
const reserve = Math.max(1, Math.min(estimate, Number.isFinite(cap) ? cap : estimate));
|
|
172
|
+
const reserve = calculateReservation(snapshot.limits);
|
|
170
173
|
_reservations.set(key, (_reservations.get(key) || 0) + reserve);
|
|
171
174
|
return { snapshot, releaseReservation: () => releaseReservation(userId, reserve) };
|
|
172
175
|
}
|
|
@@ -185,6 +188,7 @@ function releaseReservation(userId, amount) {
|
|
|
185
188
|
module.exports = {
|
|
186
189
|
DEFAULT_RATE_LIMIT_4H,
|
|
187
190
|
DEFAULT_RATE_LIMIT_WEEKLY,
|
|
191
|
+
MAX_RUN_RESERVATION_TOKENS,
|
|
188
192
|
RateLimitExceededError,
|
|
189
193
|
configuredDefaultLimits,
|
|
190
194
|
enforceRateLimits,
|
|
@@ -567,11 +567,12 @@ class TaskRuntime {
|
|
|
567
567
|
const finalPrompt = basePrompt + recoveryNote;
|
|
568
568
|
const runOptions = {
|
|
569
569
|
triggerType: task.trigger_type || 'schedule',
|
|
570
|
-
triggerSource: task.trigger_type || 'schedule',
|
|
570
|
+
triggerSource: executionMeta.triggerSource || task.trigger_type || 'schedule',
|
|
571
571
|
agentId,
|
|
572
572
|
app: this.app,
|
|
573
573
|
conversationId,
|
|
574
574
|
taskId,
|
|
575
|
+
bypassUserRateLimits: true,
|
|
575
576
|
deliveryState,
|
|
576
577
|
allowMultipleProactiveMessages: normalizedConfig.allowMultipleMessages === true || normalizedConfig.allow_multiple_messages === true,
|
|
577
578
|
stageProactiveMessages: true,
|