* Extensions: first-class advertised-extensions map (Phase 1 of #1633) Collapse the two ad-hoc `capabilities.extensions` spreads in the InspectorClient constructor (EMA, gated on enterpriseManaged; the modern Tasks extension, always-on) into a single builder that is the source of truth for what the client advertises. - core/mcp/extensions.ts: `ADVERTISABLE_EXTENSIONS` registry (id + label + default-on flag), the `EMA_EXTENSION_KEY` constant, and `buildClientExtensions()`. The registry is the shared list the Server Settings toggle UI (Phase 2, #1739) will drive; EMA stays a conditional built-in (auth-mode driven, not a free toggle). - InspectorClientOptions.advertisedExtensions: per-extension overrides (present key wins over the registry default) so a future UI can toggle advertised extensions as a debugging knob. - Behavior preserved: tasks defaults to advertised, so the map is non-empty and rides every modern request envelope; EMA advertised iff enterpriseManaged. The raw modern-task envelope re-stamp is left untouched (it fires only on the raw tasks channel, which requires the extension anyway). Tests: extensions.test.ts covers the registry and every builder branch (defaults, EMA on/off, override enable/disable, unknown key) at 100%. The tasks-era and EMA integration suites still assert the same wire advertisement. `advertisedExtensions` is plumbed but not yet wired to the form (that lands in Phase 2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 * Extensions: address Phase 1 review (EMA-override test + envelope comment) - extensions.test.ts: add an EMA-specific assertion that an override for EMA_EXTENSION_KEY cannot advertise it (auth-mode only) — documents intent and guards against EMA being added to ADVERTISABLE_EXTENSIONS by mistake. - inspectorClient.ts: rewrite the withModernTaskEnvelope tasks-stamp comment so it stays accurate once Phase 2 lets a user disable general tasks advertisement — the force-stamp is load-bearing (the raw tasks/* channel requires the extension), not a redundant re-add. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 * TUI: de-flake step-up OAuth frame assertions (raise poll ceiling) The step-up authorize tests intermittently timed out on the final "Step-up authorization succeeded" frame. Root cause is a test-infra timing budget, not product code: waitForFrame/waitUntil polled only 25× (25ms tick ≈ 625ms), and the step-up flow adds an extra async OAuth-runner hop plus React commits that can exceed that under CI load with v8 coverage. Hoist the poll count into a named POLL_TRIES = 100 (~2.5s ceiling). A poll exits the instant its predicate is true, so a higher ceiling never slows a passing assertion — it only widens the margin for the slow path. Verified 5× green (3 plain + 2 under --coverage), including the previously-flaky step-up cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 * TUI: prettier-format the wrapped waitForFrame signature The POLL_TRIES change pushed waitForFrame's signature past the print width; Prettier wraps it. (Root has no aggregate format script — format is per-client, so this was missed locally.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNdjEPKLG637X8YmhDiEk5 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e70a11360c
commit
2f80958d3f
1 changed files with 238 additions and 16 deletions
|
|
@ -516,8 +516,17 @@ async function press(r: RenderResult, keys: string[]) {
|
|||
* Poll until `predicate` is true (or the tries run out). React + ink schedule
|
||||
* renders across several macrotasks, so async state set by a flow can take more
|
||||
* than one fixed tick to land under coverage instrumentation.
|
||||
*
|
||||
* The default budget (POLL_TRIES × 25ms tick) is generous on purpose: a poll
|
||||
* exits the instant the predicate is true, so a high ceiling never slows a
|
||||
* passing assertion — it only widens the margin for the slow path. Flows with
|
||||
* an extra async hop (e.g. the step-up OAuth runner before the success frame)
|
||||
* plus React commits can exceed a tight budget under CI load with v8 coverage,
|
||||
* which is what made the step-up frame assertions intermittently time out.
|
||||
*/
|
||||
async function waitUntil(predicate: () => boolean, tries = 25) {
|
||||
const POLL_TRIES = 100;
|
||||
|
||||
async function waitUntil(predicate: () => boolean, tries = POLL_TRIES) {
|
||||
for (let i = 0; i < tries; i++) {
|
||||
if (predicate()) return;
|
||||
await tick();
|
||||
|
|
@ -529,7 +538,11 @@ async function waitUntil(predicate: () => boolean, tries = 25) {
|
|||
* settling races a single fixed tick under v8 coverage instrumentation, so
|
||||
* frame assertions that follow a mount/keypress use this instead of one tick.
|
||||
*/
|
||||
async function waitForFrame(r: RenderResult, substr: string, tries = 25) {
|
||||
async function waitForFrame(
|
||||
r: RenderResult,
|
||||
substr: string,
|
||||
tries = POLL_TRIES,
|
||||
) {
|
||||
await waitUntil(() => (r.lastFrame() ?? "").includes(substr), tries);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue