@tokenbuddy/tokenbuddy 1.0.35 → 1.0.37
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/src/buyer-store.d.ts +6 -1
- package/dist/src/buyer-store.js +43 -4
- package/dist/src/cli.js +2 -2
- package/dist/src/daemon.d.ts +12 -0
- package/dist/src/daemon.js +791 -61
- package/dist/src/doctor-diagnostics.js +1 -6
- package/dist/src/provider-install.d.ts +2 -2
- package/dist/src/provider-install.js +248 -2
- package/dist/src/seller-catalog.d.ts +21 -0
- package/dist/src/seller-catalog.js +17 -0
- package/dist/src/seller-route-planner.d.ts +4 -1
- package/dist/src/seller-route-planner.js +3 -0
- package/dist/src/seller-routing-strategy.d.ts +3 -0
- package/dist/src/terminal-detect.d.ts +1 -1
- package/dist/src/terminal-detect.js +3 -2
- package/package.json +15 -2
- package/static/ui/assets/index-Djfl9tw5.js +271 -0
- package/static/ui/assets/index-DkfztCkn.css +1 -0
- package/static/ui/index.html +2 -2
- package/dist/src/buyer-store.d.ts.map +0 -1
- package/dist/src/buyer-store.js.map +0 -1
- package/dist/src/clawtip-bootstrap.d.ts.map +0 -1
- package/dist/src/clawtip-bootstrap.js.map +0 -1
- package/dist/src/cli.d.ts.map +0 -1
- package/dist/src/cli.js.map +0 -1
- package/dist/src/credit-tracker.d.ts.map +0 -1
- package/dist/src/credit-tracker.js.map +0 -1
- package/dist/src/daemon.d.ts.map +0 -1
- package/dist/src/daemon.js.map +0 -1
- package/dist/src/doctor-clawtip-wallet.d.ts.map +0 -1
- package/dist/src/doctor-clawtip-wallet.js.map +0 -1
- package/dist/src/doctor-diagnostics.d.ts.map +0 -1
- package/dist/src/doctor-diagnostics.js.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/init-clawtip-activation.d.ts.map +0 -1
- package/dist/src/init-clawtip-activation.js.map +0 -1
- package/dist/src/init-payment-options.d.ts.map +0 -1
- package/dist/src/init-payment-options.js.map +0 -1
- package/dist/src/init-setup.d.ts.map +0 -1
- package/dist/src/init-setup.js.map +0 -1
- package/dist/src/model-index.d.ts.map +0 -1
- package/dist/src/model-index.js.map +0 -1
- package/dist/src/package-update.d.ts.map +0 -1
- package/dist/src/package-update.js.map +0 -1
- package/dist/src/prewarm-cache.d.ts.map +0 -1
- package/dist/src/prewarm-cache.js.map +0 -1
- package/dist/src/prewarm-scheduler.d.ts.map +0 -1
- package/dist/src/prewarm-scheduler.js.map +0 -1
- package/dist/src/provider-install.d.ts.map +0 -1
- package/dist/src/provider-install.js.map +0 -1
- package/dist/src/provider-routing-config.d.ts.map +0 -1
- package/dist/src/provider-routing-config.js.map +0 -1
- package/dist/src/registry-trust.d.ts.map +0 -1
- package/dist/src/registry-trust.js.map +0 -1
- package/dist/src/route-failover.d.ts.map +0 -1
- package/dist/src/route-failover.js.map +0 -1
- package/dist/src/seller-catalog.d.ts.map +0 -1
- package/dist/src/seller-catalog.js.map +0 -1
- package/dist/src/seller-concurrency-limiter.d.ts.map +0 -1
- package/dist/src/seller-concurrency-limiter.js.map +0 -1
- package/dist/src/seller-metadata-cache.d.ts.map +0 -1
- package/dist/src/seller-metadata-cache.js.map +0 -1
- package/dist/src/seller-pool.d.ts.map +0 -1
- package/dist/src/seller-pool.js.map +0 -1
- package/dist/src/seller-route-planner.d.ts.map +0 -1
- package/dist/src/seller-route-planner.js.map +0 -1
- package/dist/src/seller-routing-config.d.ts.map +0 -1
- package/dist/src/seller-routing-config.js.map +0 -1
- package/dist/src/seller-routing-strategy.d.ts.map +0 -1
- package/dist/src/seller-routing-strategy.js.map +0 -1
- package/dist/src/stream-failover.d.ts.map +0 -1
- package/dist/src/stream-failover.js.map +0 -1
- package/dist/src/tb-clawtip-proof.d.ts.map +0 -1
- package/dist/src/tb-clawtip-proof.js.map +0 -1
- package/dist/src/tb-proxyd.d.ts.map +0 -1
- package/dist/src/tb-proxyd.js.map +0 -1
- package/dist/src/terminal-detect.d.ts.map +0 -1
- package/dist/src/terminal-detect.js.map +0 -1
- package/dist/src/terminal-image.d.ts.map +0 -1
- package/dist/src/terminal-image.js.map +0 -1
- package/src/buyer-store.ts +0 -1090
- package/src/clawtip-bootstrap.ts +0 -65
- package/src/cli.ts +0 -2243
- package/src/credit-tracker.ts +0 -295
- package/src/daemon.ts +0 -5475
- package/src/doctor-clawtip-wallet.ts +0 -95
- package/src/doctor-diagnostics.ts +0 -1026
- package/src/index.ts +0 -16
- package/src/init-clawtip-activation.ts +0 -695
- package/src/init-payment-options.ts +0 -373
- package/src/init-setup.ts +0 -165
- package/src/model-index.ts +0 -278
- package/src/package-update.ts +0 -311
- package/src/prewarm-cache.ts +0 -485
- package/src/prewarm-scheduler.ts +0 -675
- package/src/provider-install.ts +0 -1006
- package/src/provider-routing-config.ts +0 -410
- package/src/registry-trust.ts +0 -51
- package/src/route-failover.ts +0 -304
- package/src/seller-catalog.ts +0 -505
- package/src/seller-concurrency-limiter.ts +0 -161
- package/src/seller-metadata-cache.ts +0 -91
- package/src/seller-pool.ts +0 -557
- package/src/seller-route-planner.ts +0 -513
- package/src/seller-routing-config.ts +0 -211
- package/src/seller-routing-strategy.ts +0 -362
- package/src/stream-failover.ts +0 -152
- package/src/tb-clawtip-proof.ts +0 -28
- package/src/tb-proxyd.ts +0 -101
- package/src/terminal-detect.ts +0 -333
- package/src/terminal-image.ts +0 -228
- package/static/ui/assets/index-0MVXD7bH.css +0 -1
- package/static/ui/assets/index-BVbeDEwq.js +0 -271
- package/static/ui/assets/index-BVbeDEwq.js.map +0 -1
- package/tests/cli-routing.test.ts +0 -363
- package/tests/control-plane-ui-endpoints.test.ts +0 -1630
- package/tests/credit-tracker.test.ts +0 -165
- package/tests/daemon-413-fallback.test.ts +0 -92
- package/tests/daemon-classify.test.ts +0 -452
- package/tests/daemon-roles.test.ts +0 -92
- package/tests/daemon-trusted-registry-cache.test.ts +0 -132
- package/tests/e2e.test.ts +0 -366
- package/tests/image-generation-e2e.test.ts +0 -230
- package/tests/model-index.test.ts +0 -198
- package/tests/package-update.test.ts +0 -147
- package/tests/prewarm-cache.test.ts +0 -296
- package/tests/prewarm-scheduler.test.ts +0 -367
- package/tests/provider-routing-config.test.ts +0 -150
- package/tests/registry-trust.test.ts +0 -28
- package/tests/route-failover.test.ts +0 -222
- package/tests/seller-catalog-413.test.ts +0 -120
- package/tests/seller-catalog-utilities.test.ts +0 -124
- package/tests/seller-concurrency-limiter.test.ts +0 -83
- package/tests/seller-metadata-cache.test.ts +0 -89
- package/tests/seller-pool.test.ts +0 -365
- package/tests/seller-route-planner.test.ts +0 -312
- package/tests/seller-routing-config.test.ts +0 -124
- package/tests/seller-routing-strategy.test.ts +0 -167
- package/tests/stream-failover.test.ts +0 -52
- package/tests/thousand-seller.test.ts +0 -151
- package/tests/tokenbuddy.test.ts +0 -4043
- package/tsconfig.json +0 -8
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CreditTracker,
|
|
3
|
-
DEFAULT_FRESH_PURCHASE_THRESHOLD,
|
|
4
|
-
DEFAULT_FRESH_PURCHASE_WINDOW_MS,
|
|
5
|
-
DEFAULT_PURCHASE_BUDGET_PER_MINUTE
|
|
6
|
-
} from "../src/credit-tracker.js";
|
|
7
|
-
|
|
8
|
-
describe("CreditTracker", () => {
|
|
9
|
-
function makeClock(start = 1_000_000): { now: number; advance: (ms: number) => void } {
|
|
10
|
-
const clock = { now: start, advance: (ms: number) => { clock.now += ms; } };
|
|
11
|
-
return clock;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
test("recordPurchase creates an entry with the supplied balance", () => {
|
|
15
|
-
const clock = makeClock();
|
|
16
|
-
const tracker = new CreditTracker({ now: () => clock.now });
|
|
17
|
-
const entry = tracker.recordPurchase("s1", 1_000_000, 1_000_000);
|
|
18
|
-
expect(entry.sellerId).toBe("s1");
|
|
19
|
-
expect(entry.lastPurchaseAmountMicros).toBe(1_000_000);
|
|
20
|
-
expect(entry.currentBalanceMicros).toBe(1_000_000);
|
|
21
|
-
expect(entry.leftoverCreditMicros).toBe(0);
|
|
22
|
-
expect(tracker.summary().purchasesInLastMinute).toBe(1);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test("recordPurchase rejects non-positive amounts", () => {
|
|
26
|
-
const tracker = new CreditTracker();
|
|
27
|
-
expect(() => tracker.recordPurchase("s1", 0, 0)).toThrow();
|
|
28
|
-
expect(() => tracker.recordPurchase("s1", -1, -1)).toThrow();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("recordSpend clamps to zero and is a no-op for unknown sellers", () => {
|
|
32
|
-
const tracker = new CreditTracker();
|
|
33
|
-
expect(tracker.recordSpend("missing", 100)).toBeUndefined();
|
|
34
|
-
tracker.recordPurchase("s1", 1_000_000, 1_000_000);
|
|
35
|
-
const updated = tracker.recordSpend("s1", 600_000);
|
|
36
|
-
expect(updated?.currentBalanceMicros).toBe(600_000);
|
|
37
|
-
const zeroed = tracker.recordSpend("s1", -10);
|
|
38
|
-
expect(zeroed?.currentBalanceMicros).toBe(0);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test("isInFreshPurchaseWindow is true only when balance ratio and time window are both satisfied", () => {
|
|
42
|
-
const clock = makeClock();
|
|
43
|
-
const tracker = new CreditTracker({ now: () => clock.now });
|
|
44
|
-
tracker.recordPurchase("s1", 1_000_000, 1_000_000);
|
|
45
|
-
|
|
46
|
-
// Right after purchase: 100% balance, well within the window.
|
|
47
|
-
expect(tracker.isInFreshPurchaseWindow("s1")).toBe(true);
|
|
48
|
-
|
|
49
|
-
// After 50% spend: ratio = 0.5, still at the default threshold.
|
|
50
|
-
tracker.recordSpend("s1", 500_000);
|
|
51
|
-
expect(tracker.isInFreshPurchaseWindow("s1")).toBe(true);
|
|
52
|
-
|
|
53
|
-
// After more spend the ratio drops below threshold.
|
|
54
|
-
tracker.recordSpend("s1", 100_000);
|
|
55
|
-
expect(tracker.isInFreshPurchaseWindow("s1")).toBe(false);
|
|
56
|
-
|
|
57
|
-
// Replenish via a new purchase and verify window restarts.
|
|
58
|
-
clock.advance(1_000);
|
|
59
|
-
tracker.recordPurchase("s1", 1_000_000, 1_000_000);
|
|
60
|
-
expect(tracker.isInFreshPurchaseWindow("s1")).toBe(true);
|
|
61
|
-
|
|
62
|
-
// Advance past the window: even a full balance no longer counts.
|
|
63
|
-
clock.advance(DEFAULT_FRESH_PURCHASE_WINDOW_MS + 1);
|
|
64
|
-
expect(tracker.isInFreshPurchaseWindow("s1")).toBe(false);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test("isInFreshPurchaseWindow returns false for sellers without any purchase", () => {
|
|
68
|
-
const tracker = new CreditTracker();
|
|
69
|
-
expect(tracker.isInFreshPurchaseWindow("never-purchased")).toBe(false);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test("canAutoPurchase enforces a per-minute budget and prunes old timestamps", () => {
|
|
73
|
-
const clock = makeClock();
|
|
74
|
-
const tracker = new CreditTracker({ now: () => clock.now });
|
|
75
|
-
|
|
76
|
-
expect(tracker.canAutoPurchase()).toBe(true);
|
|
77
|
-
tracker.recordPurchase("s1", 100, 100);
|
|
78
|
-
tracker.recordPurchase("s2", 100, 100);
|
|
79
|
-
tracker.recordPurchase("s3", 100, 100);
|
|
80
|
-
expect(tracker.canAutoPurchase()).toBe(false); // budget hit
|
|
81
|
-
|
|
82
|
-
// Advance past the 60s window: oldest timestamps fall out.
|
|
83
|
-
clock.advance(60_001);
|
|
84
|
-
expect(tracker.canAutoPurchase()).toBe(true);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test("transferLeftoverToWasted moves the current balance into the leftover bucket and tracks waste", () => {
|
|
88
|
-
const clock = makeClock();
|
|
89
|
-
const tracker = new CreditTracker({ now: () => clock.now });
|
|
90
|
-
tracker.recordPurchase("s1", 1_000_000, 800_000);
|
|
91
|
-
const wasted = tracker.transferLeftoverToWasted("s1", "failover");
|
|
92
|
-
expect(wasted).toBe(800_000);
|
|
93
|
-
const entry = tracker.getEntry("s1");
|
|
94
|
-
expect(entry?.currentBalanceMicros).toBe(0);
|
|
95
|
-
expect(entry?.leftoverCreditMicros).toBe(800_000);
|
|
96
|
-
const summary = tracker.summary();
|
|
97
|
-
expect(summary.totalWastedMicros).toBe(800_000);
|
|
98
|
-
expect(summary.wastedSinceLastDoctorRun).toBe(800_000);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test("transferLeftoverToWasted is a no-op for unknown sellers or empty balances", () => {
|
|
102
|
-
const tracker = new CreditTracker();
|
|
103
|
-
expect(tracker.transferLeftoverToWasted("missing", "x")).toBe(0);
|
|
104
|
-
tracker.recordPurchase("s1", 100, 0);
|
|
105
|
-
expect(tracker.transferLeftoverToWasted("s1", "x")).toBe(0);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
test("consumeLeftover drains the leftover bucket up to the requested amount", () => {
|
|
109
|
-
const tracker = new CreditTracker();
|
|
110
|
-
tracker.recordPurchase("s1", 1_000_000, 500_000);
|
|
111
|
-
tracker.transferLeftoverToWasted("s1", "failover");
|
|
112
|
-
expect(tracker.consumeLeftover("s1", 300_000)).toBe(300_000);
|
|
113
|
-
expect(tracker.getEntry("s1")?.leftoverCreditMicros).toBe(200_000);
|
|
114
|
-
// Requesting more than available returns only the available amount.
|
|
115
|
-
expect(tracker.consumeLeftover("s1", 999_999)).toBe(200_000);
|
|
116
|
-
expect(tracker.getEntry("s1")?.leftoverCreditMicros).toBe(0);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test("consumeLeftover is a no-op for sellers without leftover", () => {
|
|
120
|
-
const tracker = new CreditTracker();
|
|
121
|
-
expect(tracker.consumeLeftover("missing", 100)).toBe(0);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
test("summary includes per-seller entries with latest values", () => {
|
|
125
|
-
const clock = makeClock();
|
|
126
|
-
const tracker = new CreditTracker({ now: () => clock.now });
|
|
127
|
-
tracker.recordPurchase("s1", 1_000_000, 1_000_000);
|
|
128
|
-
clock.advance(1_000);
|
|
129
|
-
tracker.recordPurchase("s2", 500_000, 500_000);
|
|
130
|
-
const summary = tracker.summary();
|
|
131
|
-
expect(summary.perSeller).toHaveLength(2);
|
|
132
|
-
const s2 = summary.perSeller.find((entry) => entry.sellerId === "s2");
|
|
133
|
-
expect(s2?.currentBalanceMicros).toBe(500_000);
|
|
134
|
-
expect(s2?.lastPurchaseAt).toBe(clock.now);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
test("resetDoctorRunCounter clears the wasted-since-last-doctor counter", () => {
|
|
138
|
-
const tracker = new CreditTracker();
|
|
139
|
-
tracker.recordPurchase("s1", 1_000_000, 500_000);
|
|
140
|
-
tracker.transferLeftoverToWasted("s1", "failover");
|
|
141
|
-
expect(tracker.summary().wastedSinceLastDoctorRun).toBe(500_000);
|
|
142
|
-
tracker.resetDoctorRunCounter();
|
|
143
|
-
expect(tracker.summary().wastedSinceLastDoctorRun).toBe(0);
|
|
144
|
-
// totalWastedMicros is preserved.
|
|
145
|
-
expect(tracker.summary().totalWastedMicros).toBe(500_000);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
test("clear removes all entries and resets all counters", () => {
|
|
149
|
-
const tracker = new CreditTracker();
|
|
150
|
-
tracker.recordPurchase("s1", 100, 100);
|
|
151
|
-
tracker.transferLeftoverToWasted("s1", "failover");
|
|
152
|
-
tracker.clear();
|
|
153
|
-
const summary = tracker.summary();
|
|
154
|
-
expect(summary.totalWastedMicros).toBe(0);
|
|
155
|
-
expect(summary.wastedSinceLastDoctorRun).toBe(0);
|
|
156
|
-
expect(summary.purchasesInLastMinute).toBe(0);
|
|
157
|
-
expect(summary.perSeller).toEqual([]);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test("default constants match the v1.1 / v1.2 design", () => {
|
|
161
|
-
expect(DEFAULT_FRESH_PURCHASE_WINDOW_MS).toBe(30_000);
|
|
162
|
-
expect(DEFAULT_FRESH_PURCHASE_THRESHOLD).toBe(0.5);
|
|
163
|
-
expect(DEFAULT_PURCHASE_BUDGET_PER_MINUTE).toBe(3);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import * as http from "http";
|
|
2
|
-
import * as fs from "fs";
|
|
3
|
-
import * as path from "path";
|
|
4
|
-
import { AddressInfo } from "net";
|
|
5
|
-
import { TokenbuddyDaemon } from "../src/daemon.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* v1.2 §18.9: when the bootstrap returns 413 (registry over 1MB), the
|
|
9
|
-
* daemon must fall back to the last successfully fetched snapshot
|
|
10
|
-
* instead of failing every request. This is the buyer-side counterpart
|
|
11
|
-
* to the bootstrap's hard 1MB cap.
|
|
12
|
-
*/
|
|
13
|
-
describe("TokenbuddyDaemon registry 413 stale-fallback", () => {
|
|
14
|
-
const TEMP_DB = path.resolve(__dirname, "../../data-test/413-fallback-test.db");
|
|
15
|
-
let bootstrapServer: http.Server;
|
|
16
|
-
let bootstrapPort: number;
|
|
17
|
-
let daemon: TokenbuddyDaemon;
|
|
18
|
-
let daemonProxyPort: number;
|
|
19
|
-
|
|
20
|
-
function rmDb(): void {
|
|
21
|
-
for (const suffix of ["", "-wal", "-shm"]) {
|
|
22
|
-
const file = TEMP_DB + suffix;
|
|
23
|
-
if (fs.existsSync(file)) {
|
|
24
|
-
fs.unlinkSync(file);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
beforeAll((done) => {
|
|
30
|
-
bootstrapServer = http.createServer((_req, res) => {
|
|
31
|
-
res.setHeader("Content-Type", "application/json");
|
|
32
|
-
// Always 200 for the boot fetch. Tests that want 413 do not
|
|
33
|
-
// need to flip this server; they instead verify the catch-block
|
|
34
|
-
// in `fetchRegistry` via the dedicated unit test in
|
|
35
|
-
// `seller-catalog-413.test.ts`.
|
|
36
|
-
res.statusCode = 200;
|
|
37
|
-
res.end(JSON.stringify({
|
|
38
|
-
version: 1,
|
|
39
|
-
defaultSeller: "primary-seller",
|
|
40
|
-
sellers: [
|
|
41
|
-
{
|
|
42
|
-
id: "primary-seller",
|
|
43
|
-
url: "https://primary.example.com",
|
|
44
|
-
supportedProtocols: ["chat_completions"],
|
|
45
|
-
paymentMethods: ["mock"],
|
|
46
|
-
models: ["gpt-4o"]
|
|
47
|
-
}
|
|
48
|
-
]
|
|
49
|
-
}));
|
|
50
|
-
});
|
|
51
|
-
bootstrapServer.listen(0, "127.0.0.1", () => {
|
|
52
|
-
bootstrapPort = (bootstrapServer.address() as AddressInfo).port;
|
|
53
|
-
done();
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
afterAll((done) => {
|
|
58
|
-
bootstrapServer.close(() => done());
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
beforeEach(() => {
|
|
62
|
-
rmDb();
|
|
63
|
-
daemon = new TokenbuddyDaemon({
|
|
64
|
-
controlPort: 0,
|
|
65
|
-
proxyPort: 0,
|
|
66
|
-
dbPath: TEMP_DB,
|
|
67
|
-
sellerRegistryUrl: `http://127.0.0.1:${bootstrapPort}/registry/sellers`
|
|
68
|
-
});
|
|
69
|
-
daemon.start();
|
|
70
|
-
const proxyServer = (daemon as unknown as { proxyServer: { address(): AddressInfo } }).proxyServer;
|
|
71
|
-
daemonProxyPort = proxyServer.address().port;
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
afterEach(async () => {
|
|
75
|
-
daemon.stop();
|
|
76
|
-
// Drain any in-flight prewarm scheduler work to avoid jest
|
|
77
|
-
// open-handle warnings. The daemon's stop() is fire-and-forget.
|
|
78
|
-
await new Promise<void>((resolve) => setTimeout(resolve, 50));
|
|
79
|
-
rmDb();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test("daemon stays alive after a successful boot against the bootstrap", async () => {
|
|
83
|
-
// The buyer must surface this as a typed error so the daemon can
|
|
84
|
-
// fall back to the last-known snapshot. The fetch logic is covered
|
|
85
|
-
// by `seller-catalog-413.test.ts`; here we just assert the
|
|
86
|
-
// happy-path control plane is up.
|
|
87
|
-
const controlPort = (daemon as unknown as { controlServer: { address(): AddressInfo } }).controlServer.address().port;
|
|
88
|
-
const health = await (await fetch(`http://127.0.0.1:${controlPort}/health`)).json() as { status: string };
|
|
89
|
-
expect(health.status).toBe("ok");
|
|
90
|
-
expect(typeof daemonProxyPort).toBe("number");
|
|
91
|
-
});
|
|
92
|
-
});
|