execbro 1.10.17 → 1.10.19
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/README.md +14 -3
- package/build/__tests__/unit/licenseGrace.test.d.ts +2 -0
- package/build/__tests__/unit/licenseGrace.test.d.ts.map +1 -0
- package/build/__tests__/unit/licenseGrace.test.js +62 -0
- package/build/__tests__/unit/licenseGrace.test.js.map +1 -0
- package/build/__tests__/unit/telemetryModes.test.d.ts +2 -0
- package/build/__tests__/unit/telemetryModes.test.d.ts.map +1 -0
- package/build/__tests__/unit/telemetryModes.test.js +29 -0
- package/build/__tests__/unit/telemetryModes.test.js.map +1 -0
- package/build/__tests__/unit/usageGate.test.d.ts +2 -0
- package/build/__tests__/unit/usageGate.test.d.ts.map +1 -0
- package/build/__tests__/unit/usageGate.test.js +78 -0
- package/build/__tests__/unit/usageGate.test.js.map +1 -0
- package/build/__tests__/unit/usageNotifications.test.d.ts +2 -0
- package/build/__tests__/unit/usageNotifications.test.d.ts.map +1 -0
- package/build/__tests__/unit/usageNotifications.test.js +27 -0
- package/build/__tests__/unit/usageNotifications.test.js.map +1 -0
- package/build/core/license.d.ts +9 -0
- package/build/core/license.d.ts.map +1 -1
- package/build/core/license.js +68 -4
- package/build/core/license.js.map +1 -1
- package/build/core/register.d.ts.map +1 -1
- package/build/core/register.js +19 -3
- package/build/core/register.js.map +1 -1
- package/build/core/telemetry.d.ts +22 -0
- package/build/core/telemetry.d.ts.map +1 -1
- package/build/core/telemetry.js +122 -73
- package/build/core/telemetry.js.map +1 -1
- package/build/pro/usageGate.d.ts +10 -0
- package/build/pro/usageGate.d.ts.map +1 -0
- package/build/pro/usageGate.js +75 -0
- package/build/pro/usageGate.js.map +1 -0
- package/build/pro/usageNotifications.d.ts +5 -0
- package/build/pro/usageNotifications.d.ts.map +1 -0
- package/build/pro/usageNotifications.js +88 -0
- package/build/pro/usageNotifications.js.map +1 -0
- package/build/tools/accountTools.d.ts.map +1 -1
- package/build/tools/accountTools.js +12 -1
- package/build/tools/accountTools.js.map +1 -1
- package/build/tools/metaTools.d.ts.map +1 -1
- package/build/tools/metaTools.js +28 -7
- package/build/tools/metaTools.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,12 +14,17 @@ ExecBro is the runtime bridge between your AI coding assistant and your running
|
|
|
14
14
|
|
|
15
15
|
1. [Setup ExecBro as an MCP server for your agent of choice](#setup)
|
|
16
16
|
2. [Setup UI automation helpers](docs/setup.md#ios-simulator--ui-automation-setup)
|
|
17
|
-
3. [Install the SDK
|
|
17
|
+
3. [Install the SDK in your React Native app](#install-the-sdk-recommended) — optional, but recommended for the most robust log, network, and state experience
|
|
18
|
+
4. [Authorize and link to the web dashboard](#see-your-usage--execbrocom) — optional for usage stats and session history, **required to unlock unlimited usage via ExecBro Pro**
|
|
19
|
+
5. Start your React Native app (`npm start` / `expo start`)
|
|
20
|
+
6. [Ask your AI assistant](#usage) in plain language — e.g. "Connect to the simulator and investigate what caused the error on the screen"
|
|
18
21
|
|
|
19
22
|
## See your usage — [execbro.com](https://execbro.com)
|
|
20
23
|
|
|
21
24
|
Log in at **[execbro.com](https://execbro.com)** to see your ExecBro activity rendered back to you: which tools you use most, tool **error rates**, and your **session history** — so you can spot flaky tools, track usage over time, and understand how your agent drives the app across sessions. It's built from the same anonymous telemetry described in [Telemetry & Privacy](#telemetry--privacy), tied to your installation ID.
|
|
22
25
|
|
|
26
|
+
Linking your installation here is also **required to unlock [ExecBro Pro](#pricing)** — signing in and authorizing your installation is what lets the unlimited-usage plan take effect; without it, the free tier's monthly cap applies even after subscribing.
|
|
27
|
+
|
|
23
28
|
## Features
|
|
24
29
|
|
|
25
30
|
### Runtime Interaction
|
|
@@ -123,6 +128,9 @@ See the [full tool reference](docs/tools.md) for all tools with descriptions. Ke
|
|
|
123
128
|
|
|
124
129
|
2. Just describe what you want in plain language — the agent picks the right tools. You don't need to know tool names or ask for a specific one. For example:
|
|
125
130
|
|
|
131
|
+
```
|
|
132
|
+
Connect to the simulator and investigate what caused the error on the screen
|
|
133
|
+
```
|
|
126
134
|
```
|
|
127
135
|
Check the network logs and investigate why this error is happening
|
|
128
136
|
```
|
|
@@ -189,7 +197,10 @@ See the [full tool reference](docs/tools.md) for all tools with descriptions. Ke
|
|
|
189
197
|
|
|
190
198
|
## Telemetry & Privacy
|
|
191
199
|
|
|
192
|
-
ExecBro
|
|
200
|
+
ExecBro sends two separate signals, not one:
|
|
201
|
+
|
|
202
|
+
- **Usage metering** (required, always on) — a counted tool-call signal that powers the free tier and enforces its monthly cap. This stays on whenever you're using the free tier; it cannot be disabled and still use ExecBro's free tools.
|
|
203
|
+
- **Product analytics** (optional) — tool names, success/failure, and durations, used to improve the product. **No source code, file paths, or app content is ever sent.** This is what powers your [usage dashboard](#see-your-usage--execbrocom). Disable it with `EXECBRO_TELEMETRY=false` in your MCP server config. Doing so turns off analytics only — it does **not** disable usage metering, which keeps counting tool calls against the free-tier cap regardless.
|
|
193
204
|
|
|
194
205
|
See the [Telemetry & Data Collection guide](docs/telemetry.md) for the full breakdown of what's collected, auto-registration, and how to opt out, and [PRIVACY.md](./PRIVACY.md) for the complete privacy policy.
|
|
195
206
|
|
|
@@ -205,7 +216,7 @@ See the [Telemetry & Data Collection guide](docs/telemetry.md) for the full brea
|
|
|
205
216
|
|
|
206
217
|
## Pricing
|
|
207
218
|
|
|
208
|
-
ExecBro is **free
|
|
219
|
+
ExecBro is **free to use** — every feature, fully intelligent — up to **600 tool calls per month**. That covers evaluation and everyday debugging. Heavy users can remove the cap with **ExecBro Pro** ($9/mo) for unlimited calls and every future hosted feature. See [execbro.com/pricing](https://execbro.com/pricing). Existing users get an extra month before the cap applies, with in-app notice.
|
|
209
220
|
|
|
210
221
|
## Feedback & Feature Requests
|
|
211
222
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"licenseGrace.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/licenseGrace.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { computeOfflineUsage, GRACE_WINDOW_MS } from "../../core/license.js";
|
|
3
|
+
const NOW = 1_000_000_000_000;
|
|
4
|
+
// Default monthKey matches NOW's UTC month so existing tests (which aren't
|
|
5
|
+
// exercising month-rollover behavior) don't unintentionally cross a month
|
|
6
|
+
// boundary between the cached verdict and the "now" they're evaluated at.
|
|
7
|
+
function currentMonthKeyFor(ts) {
|
|
8
|
+
const d = new Date(ts);
|
|
9
|
+
return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, "0")}`;
|
|
10
|
+
}
|
|
11
|
+
function base(over = {}) {
|
|
12
|
+
return {
|
|
13
|
+
used: 100,
|
|
14
|
+
limit: 600,
|
|
15
|
+
monthKey: currentMonthKeyFor(NOW),
|
|
16
|
+
creditsRemaining: null,
|
|
17
|
+
canUse: true,
|
|
18
|
+
capActive: true,
|
|
19
|
+
...over,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
describe("computeOfflineUsage (fail-closed after grace)", () => {
|
|
23
|
+
it("null cache stays null (fail-open when never seen)", () => {
|
|
24
|
+
expect(computeOfflineUsage(null, NOW)).toBeNull();
|
|
25
|
+
});
|
|
26
|
+
it("within grace: trusts the cached verdict, including canUse:false", () => {
|
|
27
|
+
const cached = base({ used: 700, canUse: false, verdictFreshUntil: new Date(NOW + 1000).toISOString() });
|
|
28
|
+
const out = computeOfflineUsage(cached, NOW);
|
|
29
|
+
expect(out.canUse).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
it("past grace + last-known under cap: allow", () => {
|
|
32
|
+
const cached = base({ used: 100, canUse: true, verdictFreshUntil: new Date(NOW - 1000).toISOString() });
|
|
33
|
+
expect(computeOfflineUsage(cached, NOW).canUse).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it("past grace + last-known over cap: block", () => {
|
|
36
|
+
const cached = base({ used: 650, canUse: false, verdictFreshUntil: new Date(NOW - 1000).toISOString() });
|
|
37
|
+
expect(computeOfflineUsage(cached, NOW).canUse).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
it("past grace but capActive:false (deferred user): allow", () => {
|
|
40
|
+
const cached = base({
|
|
41
|
+
used: 900,
|
|
42
|
+
capActive: false,
|
|
43
|
+
canUse: true,
|
|
44
|
+
verdictFreshUntil: new Date(NOW - 1000).toISOString(),
|
|
45
|
+
});
|
|
46
|
+
expect(computeOfflineUsage(cached, NOW).canUse).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
it("GRACE_WINDOW_MS is 72h", () => {
|
|
49
|
+
expect(GRACE_WINDOW_MS).toBe(72 * 60 * 60 * 1000);
|
|
50
|
+
});
|
|
51
|
+
it("past grace + over cap but month has rolled over: allow (monthly counter reset)", () => {
|
|
52
|
+
const cached = base({
|
|
53
|
+
used: 650,
|
|
54
|
+
canUse: false,
|
|
55
|
+
monthKey: "2026-05",
|
|
56
|
+
verdictFreshUntil: new Date(NOW - 1000).toISOString(),
|
|
57
|
+
});
|
|
58
|
+
const laterMonth = Date.UTC(2026, 5, 15); // June 2026, well past May
|
|
59
|
+
expect(computeOfflineUsage(cached, laterMonth).canUse).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=licenseGrace.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"licenseGrace.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/licenseGrace.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetryModes.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/telemetryModes.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { resolveTelemetryModes } from "../../core/telemetry.js";
|
|
3
|
+
describe("resolveTelemetryModes", () => {
|
|
4
|
+
it("normal (configured, no opt-out, not dev): both on", () => {
|
|
5
|
+
const modes = resolveTelemetryModes({ envOptOut: false, devMode: false, endpointConfigured: true });
|
|
6
|
+
expect(modes).toEqual({ telemetryEnabled: true, meteringEnabled: true });
|
|
7
|
+
});
|
|
8
|
+
it("EXECBRO_TELEMETRY opt-out: analytics off, metering stays on", () => {
|
|
9
|
+
const modes = resolveTelemetryModes({ envOptOut: true, devMode: false, endpointConfigured: true });
|
|
10
|
+
expect(modes).toEqual({ telemetryEnabled: false, meteringEnabled: true });
|
|
11
|
+
});
|
|
12
|
+
it("dev mode: both off, even if opt-out is not set", () => {
|
|
13
|
+
const modes = resolveTelemetryModes({ envOptOut: false, devMode: true, endpointConfigured: true });
|
|
14
|
+
expect(modes).toEqual({ telemetryEnabled: false, meteringEnabled: false });
|
|
15
|
+
});
|
|
16
|
+
it("dev mode wins even when combined with opt-out", () => {
|
|
17
|
+
const modes = resolveTelemetryModes({ envOptOut: true, devMode: true, endpointConfigured: true });
|
|
18
|
+
expect(modes).toEqual({ telemetryEnabled: false, meteringEnabled: false });
|
|
19
|
+
});
|
|
20
|
+
it("unconfigured endpoint (placeholder): both off", () => {
|
|
21
|
+
const modes = resolveTelemetryModes({ envOptOut: false, devMode: false, endpointConfigured: false });
|
|
22
|
+
expect(modes).toEqual({ telemetryEnabled: false, meteringEnabled: false });
|
|
23
|
+
});
|
|
24
|
+
it("unconfigured endpoint wins even when combined with opt-out", () => {
|
|
25
|
+
const modes = resolveTelemetryModes({ envOptOut: true, devMode: false, endpointConfigured: false });
|
|
26
|
+
expect(modes).toEqual({ telemetryEnabled: false, meteringEnabled: false });
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=telemetryModes.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetryModes.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/telemetryModes.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QACzD,MAAM,KAAK,GAAG,qBAAqB,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QACpG,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACnE,MAAM,KAAK,GAAG,qBAAqB,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QACnG,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACtD,MAAM,KAAK,GAAG,qBAAqB,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QACnG,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACrD,MAAM,KAAK,GAAG,qBAAqB,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QAClG,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACrD,MAAM,KAAK,GAAG,qBAAqB,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC;QACrG,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QAClE,MAAM,KAAK,GAAG,qBAAqB,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC;QACpG,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usageGate.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/usageGate.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from "@jest/globals";
|
|
2
|
+
import { freezeSessionVerdict, refreezeSessionVerdict, isToolBlocked, usageWarningLine, resetGateForTests, } from "../../pro/usageGate.js";
|
|
3
|
+
function usage(over = {}) {
|
|
4
|
+
return {
|
|
5
|
+
used: 100,
|
|
6
|
+
limit: 600,
|
|
7
|
+
monthKey: "2026-08",
|
|
8
|
+
creditsRemaining: null,
|
|
9
|
+
canUse: true,
|
|
10
|
+
capActive: true,
|
|
11
|
+
warnThreshold: 0.8,
|
|
12
|
+
resetsAt: "2026-09-01T00:00:00Z",
|
|
13
|
+
...over,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
beforeEach(() => resetGateForTests());
|
|
17
|
+
describe("session verdict freeze", () => {
|
|
18
|
+
it("under cap: nothing blocked", () => {
|
|
19
|
+
freezeSessionVerdict(usage({ used: 100, canUse: true }));
|
|
20
|
+
expect(isToolBlocked("tap").blocked).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
it("over cap: non-exempt tools blocked with a relay message", () => {
|
|
23
|
+
freezeSessionVerdict(usage({ used: 600, canUse: false }));
|
|
24
|
+
const r = isToolBlocked("tap");
|
|
25
|
+
expect(r.blocked).toBe(true);
|
|
26
|
+
expect(r.message).toMatch(/limit reached|monthly limit/i);
|
|
27
|
+
expect(r.message).toMatch(/upgrade/);
|
|
28
|
+
});
|
|
29
|
+
it("exempt tools never blocked even over cap", () => {
|
|
30
|
+
freezeSessionVerdict(usage({ used: 600, canUse: false }));
|
|
31
|
+
expect(isToolBlocked("get_license_status").blocked).toBe(false);
|
|
32
|
+
expect(isToolBlocked("activate_license").blocked).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
it("deferred user (capActive:false) never blocked", () => {
|
|
35
|
+
freezeSessionVerdict(usage({ used: 900, capActive: false, canUse: true }));
|
|
36
|
+
expect(isToolBlocked("tap").blocked).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
it("before freeze (null verdict): allow", () => {
|
|
39
|
+
expect(isToolBlocked("tap").blocked).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
it("freeze is idempotent — stays blocked", () => {
|
|
42
|
+
freezeSessionVerdict(usage({ used: 600, canUse: false }));
|
|
43
|
+
expect(isToolBlocked("tap").blocked).toBe(true);
|
|
44
|
+
freezeSessionVerdict(usage({ used: 100, canUse: true }));
|
|
45
|
+
expect(isToolBlocked("tap").blocked).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
it("freeze is idempotent — stays unblocked", () => {
|
|
48
|
+
freezeSessionVerdict(usage({ used: 100, canUse: true }));
|
|
49
|
+
expect(isToolBlocked("tap").blocked).toBe(false);
|
|
50
|
+
freezeSessionVerdict(usage({ used: 600, canUse: false }));
|
|
51
|
+
expect(isToolBlocked("tap").blocked).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
it("refreezeSessionVerdict lifts a frozen block after mid-session upgrade", () => {
|
|
54
|
+
freezeSessionVerdict(usage({ used: 600, canUse: false }));
|
|
55
|
+
expect(isToolBlocked("tap").blocked).toBe(true);
|
|
56
|
+
refreezeSessionVerdict(usage({ used: 0, canUse: true, limit: null }));
|
|
57
|
+
expect(isToolBlocked("tap").blocked).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe("warning line", () => {
|
|
61
|
+
it("below 80%: no warning", () => {
|
|
62
|
+
expect(usageWarningLine(usage({ used: 100 }))).toBeNull();
|
|
63
|
+
});
|
|
64
|
+
it("at/above 80%: warning with remaining + reset date", () => {
|
|
65
|
+
const line = usageWarningLine(usage({ used: 500 }));
|
|
66
|
+
expect(line).toMatch(/100/); // 600-500 remaining
|
|
67
|
+
expect(line).toMatch(/ExecBro/);
|
|
68
|
+
});
|
|
69
|
+
it("deferred or uncapped: no warning", () => {
|
|
70
|
+
expect(usageWarningLine(usage({ capActive: false }))).toBeNull();
|
|
71
|
+
expect(usageWarningLine(usage({ limit: null }))).toBeNull();
|
|
72
|
+
});
|
|
73
|
+
it("invalid resetsAt falls back to 'next month'", () => {
|
|
74
|
+
const line = usageWarningLine(usage({ used: 500, resetsAt: "not-a-date" }));
|
|
75
|
+
expect(line).toMatch(/next month/);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
//# sourceMappingURL=usageGate.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usageGate.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/usageGate.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usageNotifications.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/usageNotifications.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, test, expect } from "@jest/globals";
|
|
2
|
+
import { nextThreshold } from "../../pro/usageNotifications.js";
|
|
3
|
+
function usage(over = {}) {
|
|
4
|
+
return {
|
|
5
|
+
used: 0,
|
|
6
|
+
limit: 600,
|
|
7
|
+
monthKey: "2026-08",
|
|
8
|
+
creditsRemaining: null,
|
|
9
|
+
canUse: true,
|
|
10
|
+
capActive: true,
|
|
11
|
+
warnThreshold: 0.8,
|
|
12
|
+
...over,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
describe("nextThreshold", () => {
|
|
16
|
+
test("below 80% → null", () => expect(nextThreshold(usage({ used: 100 }))).toBeNull());
|
|
17
|
+
test("80–99% → 80", () => expect(nextThreshold(usage({ used: 500 }))).toBe(80));
|
|
18
|
+
test("100%+ → 100", () => expect(nextThreshold(usage({ used: 600 }))).toBe(100));
|
|
19
|
+
test("exactly 80% boundary → 80", () => expect(nextThreshold(usage({ limit: 600, used: 480 }))).toBe(80));
|
|
20
|
+
test("just below 80% boundary → null", () => expect(nextThreshold(usage({ limit: 600, used: 479 }))).toBeNull());
|
|
21
|
+
test("exactly 100% boundary → 100", () => expect(nextThreshold(usage({ limit: 600, used: 600 }))).toBe(100));
|
|
22
|
+
test("deferred/uncapped → null", () => {
|
|
23
|
+
expect(nextThreshold(usage({ capActive: false, used: 600 }))).toBeNull();
|
|
24
|
+
expect(nextThreshold(usage({ limit: null, used: 9999 }))).toBeNull();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=usageNotifications.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usageNotifications.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/usageNotifications.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAGhE,SAAS,KAAK,CAAC,OAA2B,EAAE;IACxC,OAAO;QACH,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,GAAG;QACV,QAAQ,EAAE,SAAS;QACnB,gBAAgB,EAAE,IAAI;QACtB,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,IAAI;QACf,aAAa,EAAE,GAAG;QAClB,GAAG,IAAI;KACV,CAAC;AACN,CAAC;AAED,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC3B,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvF,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACjF,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1G,IAAI,CAAC,gCAAgC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjH,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7G,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACzE,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
package/build/core/license.d.ts
CHANGED
|
@@ -18,6 +18,11 @@ export interface UsageInfo {
|
|
|
18
18
|
canUse: boolean;
|
|
19
19
|
promotionalPeriod?: boolean;
|
|
20
20
|
promotionalPeriodEndsAt?: string | null;
|
|
21
|
+
resetsAt?: string;
|
|
22
|
+
warnThreshold?: number;
|
|
23
|
+
capActive?: boolean;
|
|
24
|
+
enforcementStartsAt?: string | null;
|
|
25
|
+
verdictFreshUntil?: string;
|
|
21
26
|
}
|
|
22
27
|
export interface PlanPricing {
|
|
23
28
|
amount: number;
|
|
@@ -30,6 +35,8 @@ export interface PricingInfo {
|
|
|
30
35
|
export declare function getUsageInfo(): UsageInfo | null;
|
|
31
36
|
export declare function getPricingInfo(): PricingInfo | null;
|
|
32
37
|
export declare function formatPlanPrice(p: PlanPricing): string;
|
|
38
|
+
export declare const GRACE_WINDOW_MS: number;
|
|
39
|
+
export declare function computeOfflineUsage(cached: UsageInfo | null, now: number): UsageInfo | null;
|
|
33
40
|
interface LicenseResult {
|
|
34
41
|
status: LicenseStatus;
|
|
35
42
|
source: "cache" | "api" | "default";
|
|
@@ -40,9 +47,11 @@ interface LicenseResult {
|
|
|
40
47
|
* Returns cached result on subsequent calls.
|
|
41
48
|
*/
|
|
42
49
|
export declare function ensureLicense(): Promise<LicenseResult>;
|
|
50
|
+
export declare function refreshLicense(): Promise<LicenseResult>;
|
|
43
51
|
export declare function getLicenseStatus(): LicenseStatus;
|
|
44
52
|
export declare function incrementLocalUsage(): void;
|
|
45
53
|
export declare function getDashboardUrl(): string;
|
|
54
|
+
export declare function requestLinkToken(): Promise<string | null>;
|
|
46
55
|
export declare function resetLicense(): void;
|
|
47
56
|
export {};
|
|
48
57
|
//# sourceMappingURL=license.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../../src/core/license.ts"],"names":[],"mappings":"AA2BA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,aAAa;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,WAAW,CAAC;IAClB,aAAa,EAAE,WAAW,GAAG,QAAQ,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC;CACL;AAED,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../../src/core/license.ts"],"names":[],"mappings":"AA2BA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,aAAa;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,WAAW,CAAC;IAClB,aAAa,EAAE,WAAW,GAAG,QAAQ,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE;QACH,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC;CACL;AAED,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IACxB,GAAG,CAAC,EAAE,WAAW,CAAC;CACrB;AAwBD,wBAAgB,YAAY,IAAI,SAAS,GAAG,IAAI,CAE/C;AAED,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAEnD;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAItD;AAED,eAAO,MAAM,eAAe,QAAsB,CAAC;AAMnD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAgB3F;AAyID,UAAU,aAAa;IACnB,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC,CAKtD;AAMD,wBAAgB,cAAc,IAAI,OAAO,CAAC,aAAa,CAAC,CAGvD;AAyED,wBAAgB,gBAAgB,IAAI,aAAa,CAOhD;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAO1C;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAKD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4B/D;AAED,wBAAgB,YAAY,IAAI,IAAI,CAUnC"}
|
package/build/core/license.js
CHANGED
|
@@ -35,6 +35,30 @@ export function formatPlanPrice(p) {
|
|
|
35
35
|
const period = p.interval === "month" ? "mo" : "yr";
|
|
36
36
|
return `${symbol}${p.amount}/${period}`;
|
|
37
37
|
}
|
|
38
|
+
export const GRACE_WINDOW_MS = 72 * 60 * 60 * 1000; // 72h fail-closed grace
|
|
39
|
+
// Offline verdict resolution. Within the grace window we trust the last server
|
|
40
|
+
// verdict verbatim (including canUse:false — this is the anti-bypass reversal of
|
|
41
|
+
// the old "never load stale usage" behavior). Past the window we block only if the
|
|
42
|
+
// last-known state was over cap; deferred (capActive:false) users are never blocked.
|
|
43
|
+
export function computeOfflineUsage(cached, now) {
|
|
44
|
+
if (!cached)
|
|
45
|
+
return null;
|
|
46
|
+
const fresh = cached.verdictFreshUntil ? new Date(cached.verdictFreshUntil).getTime() : 0;
|
|
47
|
+
if (now < fresh)
|
|
48
|
+
return cached;
|
|
49
|
+
// The cap is monthly — if we've rolled into a new calendar month (UTC) since
|
|
50
|
+
// the cached verdict, the counter has reset server-side even though we can't
|
|
51
|
+
// reach the API to confirm it, so don't keep blocking on last month's usage.
|
|
52
|
+
if (cached.monthKey) {
|
|
53
|
+
const d = new Date(now);
|
|
54
|
+
const currentMonthKey = `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, "0")}`;
|
|
55
|
+
if (cached.monthKey !== currentMonthKey) {
|
|
56
|
+
return { ...cached, canUse: true };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const overCap = cached.capActive !== false && cached.limit != null && cached.used >= cached.limit;
|
|
60
|
+
return { ...cached, canUse: !overCap };
|
|
61
|
+
}
|
|
38
62
|
function readUsageCache() {
|
|
39
63
|
try {
|
|
40
64
|
if (!existsSync(USAGE_FILE))
|
|
@@ -174,6 +198,14 @@ export function ensureLicense() {
|
|
|
174
198
|
}
|
|
175
199
|
return licensePromise;
|
|
176
200
|
}
|
|
201
|
+
// Force a fresh validate, bypassing the per-process memo but WITHOUT clearing the
|
|
202
|
+
// cache first (unlike resetLicense) — so if the API is unreachable, resolveLicense()
|
|
203
|
+
// still falls back to the last-known verdict instead of dropping to free. Lets
|
|
204
|
+
// get_license_status pick up a mid-session dashboard upgrade without an MCP restart.
|
|
205
|
+
export function refreshLicense() {
|
|
206
|
+
licensePromise = resolveLicense();
|
|
207
|
+
return licensePromise;
|
|
208
|
+
}
|
|
177
209
|
async function resolveLicense() {
|
|
178
210
|
const startTime = Date.now();
|
|
179
211
|
const installationId = getInstallationId();
|
|
@@ -209,6 +241,7 @@ async function resolveLicense() {
|
|
|
209
241
|
// Parse usage info from API response
|
|
210
242
|
if (apiResponse.usage) {
|
|
211
243
|
const usageData = apiResponse.usage;
|
|
244
|
+
usageData.verdictFreshUntil = new Date(Date.now() + GRACE_WINDOW_MS).toISOString();
|
|
212
245
|
currentUsage = usageData;
|
|
213
246
|
writeUsageCache(usageData);
|
|
214
247
|
}
|
|
@@ -218,13 +251,13 @@ async function resolveLicense() {
|
|
|
218
251
|
return { status: currentStatus, source, durationMs: Date.now() - startTime };
|
|
219
252
|
}
|
|
220
253
|
// API failed — fall back to stale license cache (fail open on tier).
|
|
221
|
-
// Intentionally do NOT load stale usage.json: a stale `canUse: false` would
|
|
222
|
-
// block tools during a transient backend outage even when the user should
|
|
223
|
-
// be allowed (e.g. new month rolled over, or promo period is active).
|
|
224
|
-
// Leaving currentUsage as null makes the per-tool block in index.ts a no-op.
|
|
225
254
|
if (cache && cache.installationId === installationId) {
|
|
226
255
|
currentStatus = cache;
|
|
227
256
|
source = "cache";
|
|
257
|
+
// Fail-closed-after-grace: reuse the last usage verdict within the grace
|
|
258
|
+
// window; past it, block only if last-known over cap. (Replaces the old
|
|
259
|
+
// fail-open no-op which let anyone bypass the cap by blocking the endpoint.)
|
|
260
|
+
currentUsage = computeOfflineUsage(readUsageCache(), Date.now());
|
|
228
261
|
return { status: currentStatus, source, durationMs: Date.now() - startTime };
|
|
229
262
|
}
|
|
230
263
|
// No cache, no API — default to free
|
|
@@ -252,6 +285,37 @@ export function incrementLocalUsage() {
|
|
|
252
285
|
export function getDashboardUrl() {
|
|
253
286
|
return DASHBOARD_URL;
|
|
254
287
|
}
|
|
288
|
+
// Mints a short-lived, single-use link token bound to this installation's
|
|
289
|
+
// fingerprint, so the printed /link URL can't be redeemed by anyone who just
|
|
290
|
+
// sees it — only someone who can also prove they hold this machine's fingerprint.
|
|
291
|
+
export async function requestLinkToken() {
|
|
292
|
+
if (!VALIDATION_ENDPOINT)
|
|
293
|
+
return null;
|
|
294
|
+
try {
|
|
295
|
+
const controller = new AbortController();
|
|
296
|
+
const timeout = setTimeout(() => controller.abort(), API_TIMEOUT_MS);
|
|
297
|
+
const response = await fetch(`${VALIDATION_ENDPOINT}/api/accounts/link-token`, {
|
|
298
|
+
method: "POST",
|
|
299
|
+
headers: {
|
|
300
|
+
"Content-Type": "application/json",
|
|
301
|
+
"X-API-Key": ACCOUNTS_API_KEY,
|
|
302
|
+
},
|
|
303
|
+
body: JSON.stringify({
|
|
304
|
+
installationId: getInstallationId(),
|
|
305
|
+
fingerprint: getDeviceFingerprint(),
|
|
306
|
+
}),
|
|
307
|
+
signal: controller.signal,
|
|
308
|
+
});
|
|
309
|
+
clearTimeout(timeout);
|
|
310
|
+
if (!response.ok)
|
|
311
|
+
return null;
|
|
312
|
+
const data = (await response.json());
|
|
313
|
+
return typeof data.token === "string" ? data.token : null;
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
255
319
|
export function resetLicense() {
|
|
256
320
|
currentStatus = null;
|
|
257
321
|
licensePromise = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"license.js","sourceRoot":"","sources":["../../src/core/license.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC/C,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,+BAA+B;AACtF,MAAM,mBAAmB,GAAG,YAAY,CAAC;AACzC,MAAM,gBAAgB,GAAG,kEAAkE,CAAC;AAC5F,MAAM,cAAc,GAAG,KAAK,CAAC;AAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;AACtD,MAAM,aAAa,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"license.js","sourceRoot":"","sources":["../../src/core/license.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/core/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/core/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4CzE,eAAO,MAAM,YAAY;YAA6B,GAAG;aAAW,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC;EAAK,CAAC;AAKrG,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAMtE;AAED,wBAAgB,yBAAyB,CACrC,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,EACpC,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,GAC/C,IAAI,CA6JN"}
|
package/build/core/register.js
CHANGED
|
@@ -4,6 +4,9 @@ import { getTargetPlatform } from "./state.js";
|
|
|
4
4
|
import { UserInputError } from "./errors.js";
|
|
5
5
|
import { estimateImageTokens } from "./toolHelpers.js";
|
|
6
6
|
import { connectedApps, shouldShowFeedbackHint, markFeedbackHintShown, pushLogBox } from "./index.js";
|
|
7
|
+
import { ensureLicense, getUsageInfo } from "./license.js";
|
|
8
|
+
import { freezeSessionVerdict, isToolBlocked, usageWarningLine } from "../pro/usageGate.js";
|
|
9
|
+
import { maybeNotifyUsage, maybeNotifyDeferral } from "../pro/usageNotifications.js";
|
|
7
10
|
// Tools that do NOT require an active Metro connection — excluded from feedback hint trigger
|
|
8
11
|
const NON_METRO_TOOLS = new Set([
|
|
9
12
|
"scan_metro",
|
|
@@ -44,9 +47,18 @@ export function installToolRegistryInterceptor(server) {
|
|
|
44
47
|
export function registerToolWithTelemetry(server, toolName, config, handler, emptyResultDetector) {
|
|
45
48
|
toolRegistry.set(toolName, { config, handler });
|
|
46
49
|
server.registerTool(toolName, config, async (args) => {
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
+
// Resolve + freeze the session verdict once (session-start semantics),
|
|
51
|
+
// then gate. Cap logic lives in src/pro/ (commercial); this MIT wrapper
|
|
52
|
+
// only calls into it.
|
|
53
|
+
await ensureLicense();
|
|
54
|
+
freezeSessionVerdict(getUsageInfo());
|
|
55
|
+
const usageNow = getUsageInfo();
|
|
56
|
+
void maybeNotifyDeferral(usageNow);
|
|
57
|
+
void maybeNotifyUsage(usageNow);
|
|
58
|
+
const gate = isToolBlocked(toolName);
|
|
59
|
+
if (gate.blocked) {
|
|
60
|
+
return { content: [{ type: "text", text: gate.message }] };
|
|
61
|
+
}
|
|
50
62
|
const startTime = Date.now();
|
|
51
63
|
let success = true;
|
|
52
64
|
let errorMessage;
|
|
@@ -144,6 +156,10 @@ export function registerToolWithTelemetry(server, toolName, config, handler, emp
|
|
|
144
156
|
// Non-fatal — hint delivery failure should not affect tool execution
|
|
145
157
|
});
|
|
146
158
|
}
|
|
159
|
+
const warn = usageWarningLine(getUsageInfo());
|
|
160
|
+
if (warn && Array.isArray(result?.content)) {
|
|
161
|
+
result.content.push({ type: "text", text: warn });
|
|
162
|
+
}
|
|
147
163
|
return result;
|
|
148
164
|
}
|
|
149
165
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/core/register.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EACH,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,mBAAmB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/core/register.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EACH,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,mBAAmB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtG,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAErF,6FAA6F;AAC7F,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC5B,YAAY;IACZ,eAAe;IACf,kBAAkB;IAClB,mBAAmB;IACnB,uBAAuB;IACvB,oBAAoB;IACpB,kBAAkB;IAClB,gBAAgB;IAChB,iBAAiB;IACjB,UAAU;IACV,qBAAqB;IACrB,sBAAsB;IACtB,oBAAoB;IACpB,gBAAgB;IAChB,oBAAoB;IACpB,iBAAiB;IACjB,qBAAqB;IACrB,eAAe;CAClB,CAAC,CAAC;AAEH,iFAAiF;AACjF,kFAAkF;AAClF,oFAAoF;AACpF,uEAAuE;AACvE,uDAAuD;AACvD,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAiE,CAAC;AAErG,kFAAkF;AAClF,oFAAoF;AACpF,uEAAuE;AACvE,MAAM,UAAU,8BAA8B,CAAC,MAAiB;IAC5D,MAAM,qBAAqB,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAc,CAAC,YAAY,GAAG,CAAC,IAAY,EAAE,MAAW,EAAE,OAAY,EAAE,EAAE;QACvE,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5C,OAAO,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,yBAAyB,CACrC,MAAiB,EACjB,QAAgB,EAChB,MAAW,EACX,OAAoC,EACpC,mBAA8C;IAE9C,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAChD,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,IAAS,EAAE,EAAE;QACtD,uEAAuE;QACvE,wEAAwE;QACxE,sBAAsB;QACtB,MAAM,aAAa,EAAE,CAAC;QACtB,oBAAoB,CAAC,YAAY,EAAE,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;QAChC,KAAK,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACnC,KAAK,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,OAAQ,EAAE,CAAC,EAAE,CAAC;QACzE,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,IAAI,YAAgC,CAAC;QACrC,IAAI,YAAgC,CAAC;QACrC,IAAI,WAA+B,CAAC;QACpC,IAAI,YAAgC,CAAC;QACrC,IAAI,WAAgC,CAAC;QACrC,IAAI,UAA+B,CAAC;QACpC,IAAI,UAA8B,CAAC;QACnC,IAAI,WAA+B,CAAC;QACpC,IAAI,SAA6B,CAAC;QAClC,IAAI,eAAmC,CAAC;QACxC,IAAI,WAA+B,CAAC;QACpC,IAAI,WAA+B,CAAC;QACpC,IAAI,eAAmC,CAAC;QACxC,IAAI,mBAAuC,CAAC;QAC5C,IAAI,uBAA2C,CAAC;QAChD,IAAI,QAA4B,CAAC;QAEjC,IAAI,CAAC;YACD,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACL,qCAAqC;QACzC,CAAC;QAED,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;YACnC,qCAAqC;YACrC,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBAClB,OAAO,GAAG,KAAK,CAAC;gBAChB,iFAAiF;gBACjF,YAAY,GAAG,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,eAAe,CAAC;YACxF,CAAC;YACD,+EAA+E;YAC/E,sFAAsF;YACtF,IAAI,MAAM,EAAE,aAAa,EAAE,CAAC;gBACxB,YAAY,GAAG,MAAM,CAAC,aAAa,CAAC;YACxC,CAAC;YACD,sEAAsE;YACtE,IAAI,OAAO,IAAI,mBAAmB,EAAE,CAAC;gBACjC,IAAI,CAAC;oBACD,WAAW,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;gBAC9C,CAAC;gBAAC,MAAM,CAAC;oBACL,sDAAsD;gBAC1D,CAAC;YACL,CAAC;YACD,kEAAkE;YAClE,IAAI,MAAM,EAAE,WAAW,KAAK,SAAS;gBAAE,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC;YACvE,IAAI,MAAM,EAAE,WAAW,KAAK,SAAS;gBAAE,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC;YACvE,IAAI,MAAM,EAAE,YAAY;gBAAE,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC;YAC5D,IAAI,MAAM,EAAE,UAAU;gBAAE,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;YACtD,IAAI,MAAM,EAAE,YAAY;gBAAE,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC;YAC5D,IAAI,MAAM,EAAE,YAAY;gBAAE,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC;YAC5D,IAAI,MAAM,EAAE,gBAAgB;gBAAE,eAAe,GAAG,MAAM,CAAC,gBAAgB,CAAC;YACxE,IAAI,MAAM,EAAE,oBAAoB;gBAAE,mBAAmB,GAAG,MAAM,CAAC,oBAAoB,CAAC;YACpF,IAAI,MAAM,EAAE,wBAAwB;gBAAE,uBAAuB,GAAG,MAAM,CAAC,wBAAwB,CAAC;YAChG,IAAI,MAAM,EAAE,SAAS;gBAAE,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC;YACnD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;gBACjC,IAAI,WAAW,GAAG,CAAC,CAAC;gBACpB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBAChC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wBACxD,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBACnD,CAAC;yBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wBAChE,WAAW,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAClD,CAAC;gBACL,CAAC;gBACD,IAAI,WAAW,GAAG,CAAC;oBAAE,YAAY,GAAG,WAAW,CAAC;YACpD,CAAC;YACD,wDAAwD;YACxD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;gBACjC,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO;qBAC3B,MAAM,CAAC,CAAC,IAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;qBACxD,GAAG,CAAC,CAAC,IAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBAC9D,CAAC;YACL,CAAC;YACD,oFAAoF;YACpF,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,sBAAsB,EAAE,EAAE,CAAC;gBAC7D,qBAAqB,EAAE,CAAC;gBACxB,kDAAkD;gBAClD,UAAU,CACN,iPAAiP,EACjP,SAAS,EACT,IAAI,EACJ,QAAQ,CACX,CAAC,KAAK,CAAC,GAAG,EAAE;oBACT,qEAAqE;gBACzE,CAAC,CAAC,CAAC;YACP,CAAC;YACD,MAAM,IAAI,GAAG,gBAAgB,CAAC,YAAY,EAAE,CAAC,CAAC;YAC9C,IAAI,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;gBACzC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/D,CAAC;YACD,OAAO,MAAM,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,GAAG,KAAK,CAAC;YAChB,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtE,kEAAkE;YAClE,iEAAiE;YACjE,gEAAgE;YAChE,mEAAmE;YACnE,kDAAkD;YAClD,IAAI,CAAC,CAAC,KAAK,YAAY,cAAc,CAAC,EAAE,CAAC;gBACrC,gBAAgB,EAAE,EAAE,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,EAAE,YAAY,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;YAC7J,CAAC;YACD,MAAM,KAAK,CAAC;QAChB,CAAC;gBAAS,CAAC;YACP,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YACxC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,QAAQ,CAAC,CAAC;YAC9S,yFAAyF;YACzF,gGAAgG;YAChG,IAAI,YAAY,GAA2B,IAAI,CAAC;YAChD,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC;gBACvC,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;oBAAC,YAAY,GAAG,IAAI,CAAC;oBAAC,MAAM;gBAAC,CAAC;YACzD,CAAC;YACD,IAAI,CAAC,YAAY,EAAE,CAAC;gBAChB,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC;oBAAE,YAAY,GAAG,QAAQ,CAAC;YAChG,CAAC;YAED,gBAAgB,EAAE,EAAE,OAAO,CAAC;gBACxB,UAAU,EAAE,iBAAiB,EAAE;gBAC/B,KAAK,EAAE,QAAQ;gBACf,UAAU,EAAE;oBACR,OAAO;oBACP,QAAQ;oBACR,cAAc,EAAE,gBAAgB,EAAE;oBAClC,YAAY,EAAE,cAAc,EAAE;oBAC9B,GAAG,CAAC,YAAY,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;oBAC9D,GAAG,CAAC,YAAY,IAAI,EAAE,cAAc,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;oBACtE,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,EAAE,CAAC;oBAC7D,GAAG,CAAC,YAAY,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC;oBACpD,GAAG,CAAC,WAAW,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;oBACjD,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,CAAC;oBAC/C,GAAG,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC;oBAC5D,GAAG,CAAC,SAAS,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;oBAC3C,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;oBAC/D,GAAG,CAAC,WAAW,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;iBACpD;aACJ,CAAC,CAAC;QACP,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC;AACD,sDAAsD"}
|