Skip to content

Commit b8abcae

Browse files
dimavrem22claude
andcommitted
Suppress the expected tunnel intake idle-cap warnings
The tunnel server idle-caps parked intake slots on a timer, and the SDK's runtime reports each one via bare console.warn ("/_system/intake slot=N -> status=408 reason=intake-idle-cap") — on a healthy gateway that one line repeats forever and buries real warnings. openTransport now installs a narrow console.warn filter before connect(): a call is dropped only when its first argument is a string containing all three markers; everything else (401s, disconnects, non-string args) passes through to the original warn unchanged. A Symbol.for tag makes the install idempotent, so gateway restarts within one process never stack wrappers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent f56b4ca commit b8abcae

2 files changed

Lines changed: 101 additions & 2 deletions

File tree

src/gateway/transport.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,33 @@ export interface Transport {
1717
// loudly instead of leaving a gateway that 403s all inbound traffic.
1818
const TUNNEL_CONNECT_TIMEOUT_MS = 15_000;
1919

20+
// The tunnel server idle-caps parked intake slots on a timer, and the SDK
21+
// reports each one via bare console.warn — on a healthy gateway that one
22+
// line repeats forever and buries real warnings. A warn call is dropped only
23+
// when its first argument contains all three markers.
24+
const IDLE_CAP_WARNING_MARKERS = ["/_system/intake slot=", "status=408", "reason=intake-idle-cap"];
25+
26+
// Tags the wrapped console.warn so repeat installs (gateway restarts within
27+
// one process) recognize it and no-op instead of stacking wrappers.
28+
const WARN_FILTER_TAG = Symbol.for("inkbox.tunnelWarnFilter");
29+
30+
// Replace console.warn with a filter that drops the expected idle-cap line
31+
// and forwards everything else — 401s, disconnects, non-string args — to the
32+
// original warn unchanged (fail-open). Idempotent.
33+
export function installTunnelWarnFilter(): void {
34+
const original = console.warn as typeof console.warn & { [WARN_FILTER_TAG]?: true };
35+
if (original[WARN_FILTER_TAG]) return;
36+
const filtered = ((...args: unknown[]) => {
37+
const first = args[0];
38+
if (typeof first === "string" && IDLE_CAP_WARNING_MARKERS.every((m) => first.includes(m))) {
39+
return;
40+
}
41+
original(...args);
42+
}) as typeof console.warn & { [WARN_FILTER_TAG]?: true };
43+
filtered[WARN_FILTER_TAG] = true;
44+
console.warn = filtered;
45+
}
46+
2047
// Bring up the inbound transport: either the Inkbox tunnel (forwarding to the
2148
// local webhook server) or a caller-provided public URL. `ownsProcess` is
2249
// false when running inside a host we don't control (in-plugin mode), which
@@ -43,6 +70,10 @@ export async function openTransport(opts: {
4370
);
4471
}
4572

73+
// Must be in place before connect(): the SDK's runtime starts warning as
74+
// soon as the data plane parks its intake slots.
75+
installTunnelWarnFilter();
76+
4677
const client = await opts.inkbox.getClient();
4778
let onConnected: () => void = () => {};
4879
const connected = new Promise<void>((resolve) => {

tests/gateway/transport.test.ts

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
// The tunnel listener returned by connect() is inert until wait() drives its
22
// data plane — openTransport must start it and gate on "connected".
3-
import { beforeEach, describe, expect, it, vi } from "vitest";
3+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
44

55
const connectMock = vi.fn();
66
vi.mock("@inkbox/sdk/tunnels/connect", () => ({
77
connect: (...args: unknown[]) => connectMock(...args),
88
}));
99

1010
import { defaultGatewayConfig } from "../../src/config.js";
11-
import { openTransport } from "../../src/gateway/transport.js";
11+
import { installTunnelWarnFilter, openTransport } from "../../src/gateway/transport.js";
1212

1313
const logger = { info: vi.fn(), warn: vi.fn(), error: vi.fn() };
1414

@@ -142,3 +142,71 @@ describe("openTransport tunnel driving", () => {
142142
expect(connectMock).not.toHaveBeenCalled();
143143
});
144144
});
145+
146+
describe("installTunnelWarnFilter", () => {
147+
const savedWarn = console.warn;
148+
let sink: ReturnType<typeof vi.fn>;
149+
150+
beforeEach(() => {
151+
// A fresh, untagged spy stands in as the "original" console.warn, so the
152+
// filter wraps it and every passthrough is observable.
153+
sink = vi.fn();
154+
console.warn = sink;
155+
installTunnelWarnFilter();
156+
});
157+
158+
afterEach(() => {
159+
console.warn = savedWarn;
160+
});
161+
162+
it("suppresses the expected intake idle-cap warning", () => {
163+
console.warn("/_system/intake slot=2 -> status=408 reason=intake-idle-cap");
164+
expect(sink).not.toHaveBeenCalled();
165+
});
166+
167+
it("keeps 401 warnings visible", () => {
168+
const line = "/_system/intake slot=2 -> status=401 reason=owner-token-invalid";
169+
console.warn(line);
170+
expect(sink).toHaveBeenCalledWith(line);
171+
});
172+
173+
it("keeps status=408 with a different reason visible", () => {
174+
console.warn("/_system/intake slot=2 -> status=408 reason=intake-superseded");
175+
expect(sink).toHaveBeenCalledTimes(1);
176+
});
177+
178+
it("keeps unrelated warnings, extra args included, visible", () => {
179+
const err = new Error("boom");
180+
console.warn("tunnel runtime: h2 session error", err);
181+
expect(sink).toHaveBeenCalledWith("tunnel runtime: h2 session error", err);
182+
});
183+
184+
it("passes a non-string first argument through even if it mentions the markers", () => {
185+
const err = new Error("/_system/intake slot=2 -> status=408 reason=intake-idle-cap");
186+
console.warn(err);
187+
expect(sink).toHaveBeenCalledWith(err);
188+
});
189+
190+
it("is idempotent: a second install keeps the same wrapper and a single layer", () => {
191+
const wrapped = console.warn;
192+
installTunnelWarnFilter();
193+
expect(console.warn).toBe(wrapped);
194+
console.warn("still one layer");
195+
expect(sink).toHaveBeenCalledTimes(1);
196+
});
197+
198+
it("is installed by openTransport before the tunnel connects", async () => {
199+
const listener = makeListener();
200+
const opts = makeOpts(listener);
201+
// Undo the beforeEach install: openTransport must wrap the bare spy itself.
202+
console.warn = sink;
203+
204+
const pending = openTransport(opts);
205+
await new Promise((r) => setTimeout(r, 0));
206+
(connectMock.mock.calls[0][1] as { onStatus: (s: string) => void }).onStatus("connected");
207+
await pending;
208+
209+
console.warn("/_system/intake slot=0 -> status=408 reason=intake-idle-cap");
210+
expect(sink).not.toHaveBeenCalled();
211+
});
212+
});

0 commit comments

Comments
 (0)