@workglow/test-contract 0.6.1

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.
Files changed (149) hide show
  1. package/README.md +232 -0
  2. package/dist/ai-provider/assertions/capabilityHonesty.d.ts +7 -0
  3. package/dist/ai-provider/assertions/dispose.d.ts +7 -0
  4. package/dist/ai-provider/assertions/inferAdvertisesRegistered.d.ts +15 -0
  5. package/dist/ai-provider/assertions/inferServesInferred.d.ts +20 -0
  6. package/dist/ai-provider/assertions/pricingMatchesModality.d.ts +36 -0
  7. package/dist/ai-provider/assertions/registryCoverage.d.ts +13 -0
  8. package/dist/ai-provider/assertions/sessionReuse.d.ts +7 -0
  9. package/dist/ai-provider/assertions/signalHonoring.d.ts +7 -0
  10. package/dist/ai-provider/assertions/structuredGeneration.d.ts +7 -0
  11. package/dist/ai-provider/assertions/textGenerationSmoke.d.ts +7 -0
  12. package/dist/ai-provider/assertions/toolCallAccumulator.d.ts +7 -0
  13. package/dist/ai-provider/assertions/toolCallMultiTurn.d.ts +7 -0
  14. package/dist/ai-provider/assertions/usageNormalization.d.ts +61 -0
  15. package/dist/ai-provider/fixtures.d.ts +8 -0
  16. package/dist/ai-provider/runAiProviderConformance.d.ts +7 -0
  17. package/dist/ai-provider/types.d.ts +75 -0
  18. package/dist/ai-provider.d.ts +25 -0
  19. package/dist/ai-provider.js +876 -0
  20. package/dist/ai-provider.js.map +26 -0
  21. package/dist/browser-context/ConformanceMockContext.d.ts +54 -0
  22. package/dist/browser-context/assertions/ariaRoundTrip.d.ts +7 -0
  23. package/dist/browser-context/assertions/capabilityHonesty.d.ts +7 -0
  24. package/dist/browser-context/assertions/itExpectFail.d.ts +8 -0
  25. package/dist/browser-context/assertions/networkIntrospection.d.ts +7 -0
  26. package/dist/browser-context/assertions/tabsLifecycle.d.ts +7 -0
  27. package/dist/browser-context/fixtures.d.ts +8 -0
  28. package/dist/browser-context/runIBrowserContextConformance.d.ts +7 -0
  29. package/dist/browser-context/types.d.ts +48 -0
  30. package/dist/browser-context.d.ts +18 -0
  31. package/dist/browser-context.js +567 -0
  32. package/dist/browser-context.js.map +17 -0
  33. package/dist/creditExhaustedSkip.d.ts +39 -0
  34. package/dist/creditExhaustedSkip.js +163 -0
  35. package/dist/creditExhaustedSkip.js.map +10 -0
  36. package/dist/entitlement-profile/assertions/denialShape.d.ts +13 -0
  37. package/dist/entitlement-profile/assertions/dispose.d.ts +16 -0
  38. package/dist/entitlement-profile/assertions/hierarchyHonoring.d.ts +11 -0
  39. package/dist/entitlement-profile/assertions/optionalNeverDenied.d.ts +11 -0
  40. package/dist/entitlement-profile/assertions/requestEntitlementShape.d.ts +12 -0
  41. package/dist/entitlement-profile/assertions/resourceScoping.d.ts +16 -0
  42. package/dist/entitlement-profile/assertions/subscribeGrant.d.ts +11 -0
  43. package/dist/entitlement-profile/assertions/subscribeReload.d.ts +11 -0
  44. package/dist/entitlement-profile/assertions/subscribeRevocation.d.ts +12 -0
  45. package/dist/entitlement-profile/assertions/surfaceCoverage.d.ts +7 -0
  46. package/dist/entitlement-profile/assertions/unsubscribeIdempotent.d.ts +7 -0
  47. package/dist/entitlement-profile/fixtures.d.ts +21 -0
  48. package/dist/entitlement-profile/runEntitlementProfileConformance.d.ts +7 -0
  49. package/dist/entitlement-profile/types.d.ts +45 -0
  50. package/dist/entitlement-profile.d.ts +23 -0
  51. package/dist/entitlement-profile.js +436 -0
  52. package/dist/entitlement-profile.js.map +22 -0
  53. package/dist/human-connector/MockHumanConnector.d.ts +29 -0
  54. package/dist/human-connector/assertions/abort.d.ts +7 -0
  55. package/dist/human-connector/assertions/capabilityHonesty.d.ts +7 -0
  56. package/dist/human-connector/assertions/concurrentIsolation.d.ts +7 -0
  57. package/dist/human-connector/assertions/multiTurnFollowUp.d.ts +7 -0
  58. package/dist/human-connector/assertions/notifyDisplayFastResolve.d.ts +7 -0
  59. package/dist/human-connector/assertions/roundtrip.d.ts +7 -0
  60. package/dist/human-connector/fixtures.d.ts +8 -0
  61. package/dist/human-connector/runHumanConnectorConformance.d.ts +9 -0
  62. package/dist/human-connector/types.d.ts +91 -0
  63. package/dist/human-connector.d.ts +19 -0
  64. package/dist/human-connector.js +843 -0
  65. package/dist/human-connector.js.map +20 -0
  66. package/dist/itExpectFail.d.ts +15 -0
  67. package/dist/itExpectFail.js +180 -0
  68. package/dist/itExpectFail.js.map +11 -0
  69. package/dist/storage-migrations/assertions/appliesAndRecords.d.ts +7 -0
  70. package/dist/storage-migrations/assertions/concurrentRunsSerialize.d.ts +18 -0
  71. package/dist/storage-migrations/assertions/ensureBookkeepingIdempotent.d.ts +7 -0
  72. package/dist/storage-migrations/assertions/failedMigrationLeavesNoPartialSchema.d.ts +14 -0
  73. package/dist/storage-migrations/assertions/failedMigrationNotRecorded.d.ts +7 -0
  74. package/dist/storage-migrations/assertions/idempotentRun.d.ts +7 -0
  75. package/dist/storage-migrations/assertions/incrementalApplication.d.ts +7 -0
  76. package/dist/storage-migrations/runMigrationRunnerContract.d.ts +9 -0
  77. package/dist/storage-migrations/types.d.ts +78 -0
  78. package/dist/storage-migrations.d.ts +18 -0
  79. package/dist/storage-migrations.js +473 -0
  80. package/dist/storage-migrations.js.map +20 -0
  81. package/dist/tabular-migrations/assertions/addAndDropIndex.d.ts +7 -0
  82. package/dist/tabular-migrations/assertions/addColumn.d.ts +7 -0
  83. package/dist/tabular-migrations/assertions/backfill.d.ts +7 -0
  84. package/dist/tabular-migrations/assertions/dropColumn.d.ts +7 -0
  85. package/dist/tabular-migrations/assertions/failedMigrationNotRecorded.d.ts +7 -0
  86. package/dist/tabular-migrations/assertions/freshDbFastPath.d.ts +7 -0
  87. package/dist/tabular-migrations/assertions/incrementalApplication.d.ts +7 -0
  88. package/dist/tabular-migrations/assertions/renameColumn.d.ts +7 -0
  89. package/dist/tabular-migrations/runTabularMigrationContract.d.ts +8 -0
  90. package/dist/tabular-migrations/types.d.ts +28 -0
  91. package/dist/tabular-migrations.d.ts +19 -0
  92. package/dist/tabular-migrations.js +257 -0
  93. package/dist/tabular-migrations.js.map +18 -0
  94. package/dist/tabular-storage/assertions/countMatchesQuery.d.ts +7 -0
  95. package/dist/tabular-storage/assertions/guardParity.d.ts +25 -0
  96. package/dist/tabular-storage/assertions/inListCriterion.d.ts +14 -0
  97. package/dist/tabular-storage/assertions/joinBoundedLeftRead.d.ts +29 -0
  98. package/dist/tabular-storage/assertions/joinPushdown.d.ts +13 -0
  99. package/dist/tabular-storage/assertions/notInListCriterion.d.ts +15 -0
  100. package/dist/tabular-storage/assertions/strategyParity.d.ts +31 -0
  101. package/dist/tabular-storage/assertions/subscribeToChanges.d.ts +21 -0
  102. package/dist/tabular-storage/assertions/vectorColumnFormat.d.ts +7 -0
  103. package/dist/tabular-storage/assertions/withConnectionTransaction.d.ts +7 -0
  104. package/dist/tabular-storage/assertions/withTransactionRollback.d.ts +7 -0
  105. package/dist/tabular-storage/fixtures.d.ts +33 -0
  106. package/dist/tabular-storage/joinFixtures.d.ts +66 -0
  107. package/dist/tabular-storage/runTabularJoinContract.d.ts +24 -0
  108. package/dist/tabular-storage/runTabularStorageContract.d.ts +9 -0
  109. package/dist/tabular-storage/types.d.ts +102 -0
  110. package/dist/tabular-storage.d.ts +25 -0
  111. package/dist/tabular-storage.js +1477 -0
  112. package/dist/tabular-storage.js.map +27 -0
  113. package/dist/vector-storage/assertions/dimensionValidation.d.ts +17 -0
  114. package/dist/vector-storage/assertions/legacyEncoding.d.ts +16 -0
  115. package/dist/vector-storage/assertions/metadataFilter.d.ts +16 -0
  116. package/dist/vector-storage/assertions/searchOptions.d.ts +16 -0
  117. package/dist/vector-storage/assertions/shared.d.ts +23 -0
  118. package/dist/vector-storage/assertions/similarityRanking.d.ts +18 -0
  119. package/dist/vector-storage/assertions/similaritySearchEvent.d.ts +16 -0
  120. package/dist/vector-storage/assertions/vectorRoundTrip.d.ts +17 -0
  121. package/dist/vector-storage/runVectorStorageContract.d.ts +20 -0
  122. package/dist/vector-storage/types.d.ts +87 -0
  123. package/dist/vector-storage.d.ts +19 -0
  124. package/dist/vector-storage.js +412 -0
  125. package/dist/vector-storage.js.map +21 -0
  126. package/dist/web-search/assertions/capabilityAgreement.d.ts +23 -0
  127. package/dist/web-search/assertions/credentialNaming.d.ts +21 -0
  128. package/dist/web-search/assertions/dateFiltering.d.ts +22 -0
  129. package/dist/web-search/assertions/domainNormalization.d.ts +24 -0
  130. package/dist/web-search/assertions/maxResultsCeiling.d.ts +22 -0
  131. package/dist/web-search/assertions/reportedQuery.d.ts +18 -0
  132. package/dist/web-search/assertions/signalThreading.d.ts +20 -0
  133. package/dist/web-search/fixtures.d.ts +40 -0
  134. package/dist/web-search/runWebSearchProviderConformance.d.ts +24 -0
  135. package/dist/web-search/types.d.ts +79 -0
  136. package/dist/web-search.d.ts +19 -0
  137. package/dist/web-search.js +560 -0
  138. package/dist/web-search.js.map +18 -0
  139. package/dist/worker-proxy/assertions/backlogOrdering.d.ts +7 -0
  140. package/dist/worker-proxy/assertions/disposeTerminatesWorker.d.ts +8 -0
  141. package/dist/worker-proxy/assertions/errorPropagation.d.ts +7 -0
  142. package/dist/worker-proxy/assertions/providerCallHelpers.d.ts +23 -0
  143. package/dist/worker-proxy/browserOnlyStub.d.ts +7 -0
  144. package/dist/worker-proxy/runWorkerProxyBoundary.d.ts +7 -0
  145. package/dist/worker-proxy/types.d.ts +47 -0
  146. package/dist/worker-proxy.d.ts +16 -0
  147. package/dist/worker-proxy.js +389 -0
  148. package/dist/worker-proxy.js.map +17 -0
  149. package/package.json +120 -0
@@ -0,0 +1,26 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/ai-provider/fixtures.ts", "../src/ai-provider/runAiProviderConformance.ts", "../src/ai-provider/assertions/capabilityHonesty.ts", "../src/creditExhaustedSkip.ts", "../src/ai-provider/assertions/dispose.ts", "../src/ai-provider/assertions/registryCoverage.ts", "../src/ai-provider/assertions/sessionReuse.ts", "../src/itExpectFail.ts", "../src/ai-provider/assertions/signalHonoring.ts", "../src/ai-provider/assertions/structuredGeneration.ts", "../src/ai-provider/assertions/textGenerationSmoke.ts", "../src/ai-provider/assertions/toolCallAccumulator.ts", "../src/ai-provider/assertions/toolCallMultiTurn.ts", "../src/ai-provider/assertions/inferAdvertisesRegistered.ts", "../src/ai-provider/assertions/inferServesInferred.ts", "../src/ai-provider/assertions/pricingMatchesModality.ts", "../src/ai-provider/assertions/usageNormalization.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { JsonSchema } from \"@workglow/util/schema\";\nimport type { ConformanceFixture } from \"./types\";\n\nexport const DEFAULT_CONFORMANCE_FIXTURE: ConformanceFixture = {\n textPrompt: \"Say hello in one short sentence.\",\n weatherTool: {\n name: \"get_weather\",\n description: \"Get the current weather for a given city.\",\n inputSchema: {\n type: \"object\",\n properties: {\n location: { type: \"string\", description: \"City name, e.g. San Francisco\" },\n },\n required: [\"location\"],\n } as const satisfies JsonSchema,\n },\n weatherToolPrompt: \"What is the weather in San Francisco?\",\n multiTurnTranscript: [\n { role: \"user\", text: \"What is the weather in Tokyo?\" },\n { role: \"assistant\", text: \"Let me check.\" },\n { role: \"tool\", text: '{\"temperature\":22,\"conditions\":\"sunny\"}' },\n ],\n structuredSchema: {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n age: { type: \"number\" },\n },\n required: [\"name\", \"age\"],\n additionalProperties: false,\n } as const satisfies JsonSchema,\n structuredPrompt:\n \"Generate a JSON object with a person's name and age. Use name 'Alice' and age 30.\",\n maxTokens: 100,\n abortGraceMs: 50,\n};\n\nexport function resolveFixture(\n override: Partial<ConformanceFixture> | undefined\n): ConformanceFixture {\n if (!override) return DEFAULT_CONFORMANCE_FIXTURE;\n return { ...DEFAULT_CONFORMANCE_FIXTURE, ...override };\n}\n",
6
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { afterAll, beforeAll, describe } from \"vitest\";\n\nimport { capabilityHonestyBlock } from \"./assertions/capabilityHonesty\";\nimport { disposeBlock } from \"./assertions/dispose\";\nimport { registryCoverageBlock } from \"./assertions/registryCoverage\";\nimport { sessionReuseBlock } from \"./assertions/sessionReuse\";\nimport { signalHonoringBlock } from \"./assertions/signalHonoring\";\nimport { structuredGenerationBlock } from \"./assertions/structuredGeneration\";\nimport { textGenerationSmokeBlock } from \"./assertions/textGenerationSmoke\";\nimport { toolCallAccumulatorBlock } from \"./assertions/toolCallAccumulator\";\nimport { toolCallMultiTurnBlock } from \"./assertions/toolCallMultiTurn\";\nimport { resolveFixture } from \"./fixtures\";\nimport type { AiProviderConformanceOpts, ConformanceHandle } from \"./types\";\n\nexport function runAiProviderConformance(opts: AiProviderConformanceOpts): void {\n // Capability invariants: a positive capability claim must be backed by a\n // model the conformance suite can exercise. Without these, a true capability\n // would silently pass when no model is wired up, defeating the whole point\n // of capabilityHonestyBlock's positive assertions.\n const requiredModels: ReadonlyArray<readonly [boolean, string, string]> = [\n [opts.capabilities.streaming, \"streaming\", \"textGeneration\"],\n [opts.capabilities.tools, \"tools\", \"toolCalling\"],\n [opts.capabilities.structured, \"structured\", \"structured\"],\n [opts.capabilities.embeddings, \"embeddings\", \"embeddings\"],\n ];\n for (const [claimed, capabilityKey, modelKey] of requiredModels) {\n if (claimed && !opts.models[modelKey as keyof typeof opts.models]) {\n throw new Error(\n `AiProvider conformance \"${opts.name}\": capabilities.${capabilityKey} is true but models.${modelKey} is not set. ` +\n `Either provide a model id or set capabilities.${capabilityKey} to false.`\n );\n }\n }\n\n describe.skipIf(opts.skip)(`AiProvider conformance: ${opts.name}`, () => {\n let handle: ConformanceHandle | undefined;\n const getHandle = (): ConformanceHandle => {\n if (!handle) throw new Error(\"conformance handle not initialized\");\n return handle;\n };\n\n beforeAll(async () => {\n handle = await opts.factory();\n await handle.register();\n }, opts.timeout);\n\n afterAll(async () => {\n if (handle) await handle.dispose();\n });\n\n const fixture = resolveFixture(opts.fixture);\n\n registryCoverageBlock(opts);\n textGenerationSmokeBlock(opts, fixture);\n signalHonoringBlock(opts, fixture);\n toolCallAccumulatorBlock(opts, fixture);\n toolCallMultiTurnBlock(opts, fixture);\n structuredGenerationBlock(opts, fixture);\n sessionReuseBlock(opts, fixture, getHandle);\n capabilityHonestyBlock(opts);\n // dispose runs last; it calls handle.dispose() which must be idempotent.\n disposeBlock(opts, getHandle);\n });\n}\n",
7
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability } from \"@workglow/ai\";\nimport { getAiProviderRegistry, getGlobalModelRepository, textEmbedding } from \"@workglow/ai\";\nimport { describe, expect } from \"vitest\";\n\nimport { it } from \"../../creditExhaustedSkip\";\n\nimport type { AiProviderConformanceOpts } from \"../types\";\n\nconst TEXT_GENERATION: readonly Capability[] = [\"text.generation\"];\nconst TOOL_USE: readonly Capability[] = [\"text.generation\", \"tool-use\"];\nconst STRUCTURED: readonly Capability[] = [\"text.generation\", \"json-mode\"];\nconst TEXT_EMBEDDING: readonly Capability[] = [\"text.embedding\"];\n\nexport function capabilityHonestyBlock(opts: AiProviderConformanceOpts): void {\n describe(\"Capability honesty\", () => {\n // ------------------------------------------------------------------\n // Negative direction: declared false → no run/stream function exists.\n // ------------------------------------------------------------------\n\n it.skipIf(opts.capabilities.streaming || !opts.models.textGeneration)(\n \"declares streaming=false → registry has no stream function\",\n async () => {\n const registry = getAiProviderRegistry();\n const model = await getGlobalModelRepository().findByName(opts.models.textGeneration!);\n expect(model).toBeDefined();\n const fn = registry.getRunFnFor(model!.provider, TEXT_GENERATION);\n expect(fn).toBeUndefined();\n },\n opts.timeout\n );\n\n it.skipIf(opts.capabilities.tools || !opts.models.textGeneration)(\n \"declares tools=false → registry rejects ToolCallingTask lookup\",\n async () => {\n const registry = getAiProviderRegistry();\n const model = await getGlobalModelRepository().findByName(opts.models.textGeneration!);\n expect(model).toBeDefined();\n const fn = registry.getRunFnFor(model!.provider, TOOL_USE);\n expect(fn).toBeUndefined();\n },\n opts.timeout\n );\n\n it.skipIf(opts.capabilities.embeddings || !opts.models.textGeneration)(\n \"declares embeddings=false → registry rejects TextEmbeddingTask lookup\",\n async () => {\n const registry = getAiProviderRegistry();\n const model = await getGlobalModelRepository().findByName(opts.models.textGeneration!);\n expect(model).toBeDefined();\n const fn = registry.getRunFnFor(model!.provider, TEXT_EMBEDDING);\n expect(fn).toBeUndefined();\n },\n opts.timeout\n );\n\n it.skipIf(opts.capabilities.structured || !opts.models.textGeneration)(\n \"declares structured=false → registry rejects StructuredGenerationTask lookup\",\n async () => {\n const registry = getAiProviderRegistry();\n const model = await getGlobalModelRepository().findByName(opts.models.textGeneration!);\n expect(model).toBeDefined();\n const fn = registry.getRunFnFor(model!.provider, STRUCTURED);\n expect(fn).toBeUndefined();\n },\n opts.timeout\n );\n\n // ------------------------------------------------------------------\n // Positive direction: declared true → the wiring actually exists.\n // Calling a capability \"supported\" without testing it was the\n // original sin these blocks exist to prevent.\n // ------------------------------------------------------------------\n\n it.skipIf(!opts.capabilities.streaming || !opts.models.textGeneration)(\n \"declares streaming=true → registry has a stream function\",\n async () => {\n const registry = getAiProviderRegistry();\n const model = await getGlobalModelRepository().findByName(opts.models.textGeneration!);\n expect(model).toBeDefined();\n const fn = registry.getRunFnFor(model!.provider, TEXT_GENERATION);\n expect(fn).toBeDefined();\n },\n opts.timeout\n );\n\n it.skipIf(!opts.capabilities.tools || !opts.models.toolCalling)(\n \"declares tools=true → registry has a ToolCallingTask run function\",\n async () => {\n const registry = getAiProviderRegistry();\n const model = await getGlobalModelRepository().findByName(opts.models.toolCalling!);\n expect(model).toBeDefined();\n const fn = registry.getRunFnFor(model!.provider, TOOL_USE);\n expect(fn).toBeDefined();\n },\n opts.timeout\n );\n\n it.skipIf(!opts.capabilities.structured || !opts.models.structured)(\n \"declares structured=true → registry has a StructuredGenerationTask run function\",\n async () => {\n const registry = getAiProviderRegistry();\n const model = await getGlobalModelRepository().findByName(opts.models.structured!);\n expect(model).toBeDefined();\n const fn = registry.getRunFnFor(model!.provider, STRUCTURED);\n expect(fn).toBeDefined();\n },\n opts.timeout\n );\n\n it.skipIf(!opts.capabilities.embeddings || !opts.models.embeddings)(\n \"declares embeddings=true → registry has a run function and produces a finite vector\",\n async () => {\n const registry = getAiProviderRegistry();\n const model = await getGlobalModelRepository().findByName(opts.models.embeddings!);\n expect(model).toBeDefined();\n const fn = registry.getRunFnFor(model!.provider, TEXT_EMBEDDING);\n expect(fn).toBeDefined();\n\n const result = await textEmbedding({\n model: opts.models.embeddings!,\n text: \"hello\",\n });\n\n const vector = result.vector;\n // TextEmbeddingTaskOutput.vector is TypedArraySchema — accept any\n // typed-array view (Float32Array, Float64Array, etc.). DataView is\n // explicitly excluded since it's not a numeric typed array.\n const isTypedArray = ArrayBuffer.isView(vector) && !(vector instanceof DataView);\n expect(isTypedArray, \"vector must be a numeric typed array\").toBe(true);\n const values = Array.from(vector as ArrayLike<number>);\n expect(values.length).toBeGreaterThan(0);\n for (const v of values) {\n expect(Number.isFinite(v)).toBe(true);\n }\n },\n opts.timeout\n );\n });\n}\n",
8
+ "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { it as vitestIt } from \"vitest\";\n\n/**\n * Live provider tests treat \"the account is out of credits\" as a billing\n * condition rather than a product bug. A key being present is not the same as\n * the account being able to pay; HuggingFace / OpenRouter 402s, Anthropic's\n * credit-balance error, DeepSeek's `Insufficient Balance`, and OpenAI's\n * `insufficient_quota` are all billing.\n *\n * Rate limits (429 + `rate_limit_exceeded`) are NOT this: those are transient\n * and the existing retry policy handles them.\n *\n * Where it skips and where it fails is a deliberate split\n * ({@link creditExhaustionSkipsTest}): on CI it skips for every provider,\n * because a red build tells a reviewer nothing they can act on; locally it\n * fails, because the developer running the suite is the one who can top the\n * account up. `WORKGLOW_CREDIT_EXHAUSTED_SKIP=1` forces the skip locally\n * (and `=0` forces the failure on CI).\n */\n\nconst BILLING_CODES = new Set([\n \"insufficient_quota\",\n \"billing_hard_limit_reached\",\n \"insufficient_credits\",\n \"insufficient_balance\",\n]);\n\nconst CREDIT_MESSAGE =\n /insufficient credits|not enough credits|no credits remaining|out of credits|insufficient[\\s_-]balance|balance is (?:too low|insufficient)|exceeded[\\s\\S]{0,80}credits|monthly included credits|payment required|exceeded your current quota|check your plan and billing|billing_hard_limit/i;\n\n/**\n * A 402 that survives only as text. `classifyProviderError` rebuilds the error\n * as a `PermanentJobError` carrying the message and no `cause`, so by the time\n * a live test sees a DeepSeek billing failure the numeric `status` is gone and\n * the OpenAI-SDK message shape (`402 Insufficient Balance`) is all that is\n * left. Anchored to an HTTP-shaped position — start of a line, or after a\n * summary line's colon — so prose that merely contains the number\n * (\"Item 402(c)\") is not scavenged as a status.\n */\nconst HTTP_402_MESSAGE =\n /\\bHTTP\\/?\\d?(?:\\.\\d)?\\s*402\\b|\\bstatus(?:\\s*code)?\\s*[:=]\\s*402\\b|\\berror code:?\\s*402\\b|(?:^|:\\s+)402\\s+[a-z]/im;\n\nexport function isCreditExhaustedError(err: unknown): boolean {\n const seen = new Set<unknown>();\n let current: unknown = err;\n while (current !== undefined && current !== null && !seen.has(current)) {\n seen.add(current);\n if (matchesCreditExhaustion(current)) return true;\n current = causeOf(current);\n }\n return false;\n}\n\nfunction matchesCreditExhaustion(err: unknown): boolean {\n if (typeof err === \"string\") return messageLooksLikeCreditExhaustion(err);\n\n if (!err || typeof err !== \"object\") return false;\n\n const rec = err as Record<string, unknown>;\n const status = numericStatus(rec);\n if (status === 402) return true;\n\n const code = stringish(rec.code) ?? stringish(nested(rec.error, \"code\"));\n const type = stringish(rec.type) ?? stringish(nested(rec.error, \"type\"));\n if (code && BILLING_CODES.has(code)) return true;\n if (type && BILLING_CODES.has(type)) return true;\n\n const message = [\n stringish(rec.message),\n stringish(nested(rec.error, \"message\")),\n stringifyUnknown(err),\n ]\n .filter((part): part is string => typeof part === \"string\")\n .join(\"\\n\");\n return messageLooksLikeCreditExhaustion(message);\n}\n\nfunction messageLooksLikeCreditExhaustion(message: string): boolean {\n return CREDIT_MESSAGE.test(message) || HTTP_402_MESSAGE.test(message);\n}\n\nfunction numericStatus(rec: Record<string, unknown>): number | undefined {\n for (const key of [\"status\", \"statusCode\"] as const) {\n const value = rec[key];\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n }\n const nestedStatus = nested(rec.error, \"status\");\n if (typeof nestedStatus === \"number\" && Number.isFinite(nestedStatus)) return nestedStatus;\n return undefined;\n}\n\nfunction nested(value: unknown, key: string): unknown {\n if (!value || typeof value !== \"object\") return undefined;\n return (value as Record<string, unknown>)[key];\n}\n\nfunction stringish(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction stringifyUnknown(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nfunction causeOf(err: unknown): unknown {\n if (!err || typeof err !== \"object\") return undefined;\n return (err as { cause?: unknown }).cause;\n}\n\nexport function creditSkipNote(err: unknown): string {\n const message = err instanceof Error ? err.message : String(err);\n return `skipped: provider out of credits (${message})`;\n}\n\nconst SKIP_OVERRIDE_ENV = \"WORKGLOW_CREDIT_EXHAUSTED_SKIP\";\n\nfunction isTruthyFlag(value: string): boolean {\n return !/^(?:0|false|off|no)$/i.test(value.trim());\n}\n\n/**\n * Whether a billing failure skips the test or fails it.\n *\n * CI skips: nobody watching a build can top an account up, and one exhausted\n * key would otherwise turn every provider suite red for a change that touched\n * none of them — so the leniency is provider-agnostic by construction, keyed on\n * the environment rather than on which vendor ran out.\n *\n * Locally it fails, loudly, because the developer running the suite IS the\n * person who can act on it — and a silently green local run is how an\n * exhausted account goes unnoticed until CI is the only thing exercising the\n * provider at all.\n *\n * `WORKGLOW_CREDIT_EXHAUSTED_SKIP` overrides in both directions.\n */\nexport function creditExhaustionSkipsTest(\n env: Record<string, string | undefined> = process.env\n): boolean {\n const override = env[SKIP_OVERRIDE_ENV];\n if (override !== undefined && override.trim() !== \"\") return isTruthyFlag(override);\n for (const key of [\"CI\", \"GITHUB_ACTIONS\"] as const) {\n const value = env[key];\n if (value !== undefined && value.trim() !== \"\" && isTruthyFlag(value)) return true;\n }\n return false;\n}\n\n/**\n * The local-failure path. Rethrows the provider's own error unchanged — its\n * identity and stack are what makes the failure diagnosable — after one line\n * saying why it was not skipped and how to skip it.\n */\nfunction reportLocalCreditFailure(err: unknown): void {\n const message = err instanceof Error ? err.message : String(err);\n console.error(\n `provider out of credits (${message})\\n` +\n ` Failing because this is not CI. Top the account up, or set ${SKIP_OVERRIDE_ENV}=1 to skip instead.`\n );\n}\n\nexport async function runWithCreditSkip<T>(\n ctx: { skip: (note?: string) => void },\n fn: () => Promise<T> | T\n): Promise<T> {\n try {\n return await fn();\n } catch (err) {\n if (isCreditExhaustedError(err)) {\n if (!creditExhaustionSkipsTest()) {\n reportLocalCreditFailure(err);\n throw err;\n }\n ctx.skip(creditSkipNote(err));\n // vitest's skip() is `never` (throws). Mocks used in unit tests return.\n return undefined as T;\n }\n throw err;\n }\n}\n\n/**\n * Wraps one test body. This is the seam every conformance assertion actually\n * runs through (the exported {@link it} proxies each callback through it), so\n * the CI-skips / locally-fails policy is applied here rather than at each\n * call site.\n */\nexport function wrapTestBodyForCreditSkip(\n fn: (...args: never[]) => unknown\n): (...args: never[]) => unknown {\n return async function wrapped(this: unknown, ...args: never[]): Promise<unknown> {\n try {\n return await fn.apply(this, args);\n } catch (err) {\n if (!isCreditExhaustedError(err)) throw err;\n if (!creditExhaustionSkipsTest()) {\n reportLocalCreditFailure(err);\n throw err;\n }\n const ctx = args[0] as { skip?: (note?: string) => void } | undefined;\n if (ctx && typeof ctx.skip === \"function\") {\n ctx.skip(creditSkipNote(err));\n return undefined;\n }\n // bun:test has no TestContext.skip; passing is \"don't fail the test\".\n console.warn(creditSkipNote(err));\n return undefined;\n }\n };\n}\n\nfunction wrapCallable(fn: CallableFunction): CallableFunction {\n return new Proxy(fn, {\n apply(target, thisArg, argArray: unknown[]) {\n const wrapped = argArray.map((arg) =>\n typeof arg === \"function\" ? wrapTestBodyForCreditSkip(arg as never) : arg\n );\n const result = Reflect.apply(target, thisArg, wrapped);\n return typeof result === \"function\" ? wrapCallable(result) : result;\n },\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === \"function\") {\n return wrapCallable((value as CallableFunction).bind(target));\n }\n return value;\n },\n });\n}\n\n/**\n * Drop-in `it` for live provider tests: a credit/billing error skips the test on\n * CI and fails it locally (see {@link creditExhaustionSkipsTest}).\n */\nexport const it = wrapCallable(vitestIt) as typeof vitestIt;\n",
9
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { getLogger } from \"@workglow/util\";\nimport { describe, expect } from \"vitest\";\n\nimport { it } from \"../../creditExhaustedSkip\";\n\nimport type { AiProviderConformanceOpts, ConformanceHandle } from \"../types\";\n\nexport function disposeBlock(\n opts: AiProviderConformanceOpts,\n getHandle: () => ConformanceHandle\n): void {\n describe(\"Dispose\", () => {\n it(\n \"release resources observable via inspect()\",\n async () => {\n const handle = getHandle();\n const before = handle.inspect();\n if (!before.sessionMap && (!before.disposables || before.disposables.length === 0)) {\n getLogger().warn(\n `[conformance] ${opts.name} exposes no inspect() handles; dispose assertion skipped`\n );\n return;\n }\n await handle.dispose();\n const after = handle.inspect();\n if (after.sessionMap) {\n expect(after.sessionMap.size).toBe(0);\n }\n if (after.disposables) {\n for (const d of after.disposables) {\n expect(d.alive).toBe(false);\n }\n }\n },\n opts.timeout\n );\n });\n}\n",
10
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability } from \"@workglow/ai\";\nimport { getAiProviderRegistry, getGlobalModelRepository } from \"@workglow/ai\";\nimport { describe, expect } from \"vitest\";\n\nimport { it } from \"../../creditExhaustedSkip\";\n\nimport type { AiProviderConformanceOpts } from \"../types\";\n\n/**\n * Capability-set conformance: every model in `opts.models` must be backed by\n * a registry entry whose `serves` superset covers the model's declared\n * `capabilities`. Each capability is also probed individually to confirm the\n * provider can dispatch the bare capability via `getRunFnFor`.\n */\nexport function registryCoverageBlock(opts: AiProviderConformanceOpts): void {\n describe(\"Registry coverage\", () => {\n it(\n \"resolves a run function for every capability advertised by the provider's models\",\n async () => {\n const candidateModelIds = [\n opts.models.textGeneration,\n opts.models.toolCalling,\n opts.models.structured,\n opts.models.embeddings,\n ].filter((id): id is string => typeof id === \"string\");\n expect(\n candidateModelIds.length,\n \"registryCoverageBlock requires at least one model id in opts.models\"\n ).toBeGreaterThan(0);\n\n const registry = getAiProviderRegistry();\n const repo = getGlobalModelRepository();\n\n const seenProviders = new Set<string>();\n const seenCapabilities = new Set<string>();\n\n for (const modelId of candidateModelIds) {\n const model = await repo.findByName(modelId);\n expect(model, `model \"${modelId}\" not found in repository`).toBeDefined();\n const providerKey = model!.provider;\n\n const provider = registry.getProvider(providerKey);\n expect(provider, `provider \"${providerKey}\" not registered`).toBeDefined();\n\n const capabilities = (model!.capabilities ?? []) as readonly Capability[];\n expect(\n capabilities.length,\n `model \"${modelId}\" advertises zero capabilities`\n ).toBeGreaterThan(0);\n seenProviders.add(providerKey);\n\n for (const capability of capabilities) {\n seenCapabilities.add(`${providerKey}::${capability}`);\n const runFn = registry.getRunFnFor(providerKey, [capability]);\n expect(\n runFn,\n `provider \"${providerKey}\" advertises capability \"${capability}\" via model \"${modelId}\" but the registry has no matching run function`\n ).toBeDefined();\n }\n }\n\n expect(seenProviders.size, \"no providers reached during coverage walk\").toBeGreaterThan(0);\n expect(\n seenCapabilities.size,\n \"no capabilities reached during coverage walk\"\n ).toBeGreaterThan(0);\n },\n opts.timeout\n );\n });\n}\n",
11
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability } from \"@workglow/ai\";\nimport { accumulatingEmit, getAiProviderRegistry, getGlobalModelRepository } from \"@workglow/ai\";\nimport type { TaskOutput } from \"@workglow/task-graph\";\nimport { getLogger } from \"@workglow/util\";\nimport { beforeAll, describe, expect } from \"vitest\";\n\nimport { it } from \"../../creditExhaustedSkip\";\nimport { itExpectFail } from \"../../itExpectFail\";\nimport type { AiProviderConformanceOpts, ConformanceFixture, ConformanceHandle } from \"../types\";\n\nconst TEXT_GENERATION: readonly Capability[] = [\"text.generation\"];\n\nexport function sessionReuseBlock(\n opts: AiProviderConformanceOpts,\n fixture: ConformanceFixture,\n getHandle: () => ConformanceHandle\n): void {\n const enabled = opts.capabilities.sessions && !!opts.models.textGeneration;\n const expectFails = new Set(opts.expectedFailures ?? []);\n const itImpl = expectFails.has(\"session.reuse\") ? itExpectFail : it;\n describe.skipIf(!enabled)(\"Session reuse\", () => {\n beforeAll(async () => {\n await getHandle().releaseTransients?.();\n });\n itImpl(\n \"two invocations with the same sessionId yield exactly one session-map entry\",\n async () => {\n const handle = getHandle();\n const map = handle.inspect().sessionMap;\n if (!map) {\n getLogger().warn(\n `[conformance] ${opts.name} declares sessions=true but inspect().sessionMap is undefined; skipping`\n );\n return;\n }\n const sizeBefore = map.size;\n\n const registry = getAiProviderRegistry();\n const model = await getGlobalModelRepository().findByName(opts.models.textGeneration!);\n expect(model).toBeDefined();\n const runFn = registry.getRunFnFor(model!.provider, TEXT_GENERATION);\n expect(\n runFn,\n `provider \"${model!.provider}\" has no run-fn for [\"text.generation\"]`\n ).toBeDefined();\n\n const sessionId = `conformance-${Date.now()}`;\n {\n const { emit } = accumulatingEmit<TaskOutput>();\n await runFn!(\n { prompt: fixture.textPrompt, maxTokens: fixture.maxTokens },\n model!,\n new AbortController().signal,\n emit,\n undefined,\n { sessionId }\n );\n }\n {\n const { emit } = accumulatingEmit<TaskOutput>();\n await runFn!(\n { prompt: fixture.textPrompt, maxTokens: fixture.maxTokens },\n model!,\n new AbortController().signal,\n emit,\n undefined,\n { sessionId }\n );\n }\n\n const newEntries = map.size - sizeBefore;\n expect(newEntries).toBe(1);\n },\n opts.timeout\n );\n });\n}\n",
12
+ "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { isCreditExhaustedError, it } from \"./creditExhaustedSkip\";\n\ntype ItFn = (name: string, fn: () => Promise<void> | void, timeout?: number) => void;\n\n/**\n * Cross-runner polyfill for `it.fails`. Vitest exposes it natively; bun's\n * native `bun test` runner does not. Under bun we wrap the body in a\n * try/catch and assert that it threw — so a passing-when-expected-fail\n * test still surfaces as a CI failure (signalling \"remove from\n * expectedFailures\").\n */\nexport const itExpectFail: ItFn = (name, fn, timeout) => {\n const native = (it as unknown as { fails?: ItFn }).fails;\n if (typeof native === \"function\") {\n native(name, fn, timeout);\n return;\n }\n it(\n `${name} [expected-fail]`,\n async () => {\n let passed = false;\n try {\n await fn();\n passed = true;\n } catch (err) {\n // Billing exhaustion is not the adapter bug this marker records.\n if (isCreditExhaustedError(err)) throw err;\n // expected; the test was supposed to fail\n }\n if (passed) {\n throw new Error(\n `Test \"${name}\" was marked as expected-fail but passed. Remove its name from opts.expectedFailures.`\n );\n }\n },\n timeout\n );\n};\n",
13
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability } from \"@workglow/ai\";\nimport { accumulatingEmit, getAiProviderRegistry, getGlobalModelRepository } from \"@workglow/ai\";\nimport type { StreamEvent, TaskOutput } from \"@workglow/task-graph\";\nimport { describe, expect } from \"vitest\";\n\nimport { it } from \"../../creditExhaustedSkip\";\nimport { itExpectFail } from \"../../itExpectFail\";\nimport type { AiProviderConformanceOpts, ConformanceFixture } from \"../types\";\n\nconst TEXT_GENERATION: readonly Capability[] = [\"text.generation\"];\n\nfunction isAbortError(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n const e = err as { name?: string; message?: string };\n return e.name === \"AbortError\" || /abort/i.test(e.message ?? \"\");\n}\n\nexport function signalHonoringBlock(\n opts: AiProviderConformanceOpts,\n fixture: ConformanceFixture\n): void {\n const expectFails = new Set(opts.expectedFailures ?? []);\n const itNonStreaming = expectFails.has(\"signal.nonStreaming\") ? itExpectFail : it;\n const skipMid = !opts.capabilities.abortMidStream;\n const itMidStream = expectFails.has(\"signal.midStream\") ? itExpectFail : it;\n\n describe.skipIf(!opts.models.textGeneration)(\"Signal honoring\", () => {\n itNonStreaming(\n \"run-fn rejects with AbortError when aborted before invocation\",\n async () => {\n const registry = getAiProviderRegistry();\n const repo = getGlobalModelRepository();\n const model = await repo.findByName(opts.models.textGeneration!);\n expect(model).toBeDefined();\n const runFn = registry.getRunFnFor(model!.provider, TEXT_GENERATION);\n expect(\n runFn,\n `provider \"${model!.provider}\" has no run-fn for [\"text.generation\"]`\n ).toBeDefined();\n const ac = new AbortController();\n ac.abort();\n\n let caught: unknown;\n try {\n const { emit } = accumulatingEmit<TaskOutput>();\n await runFn!(\n { prompt: fixture.textPrompt, maxTokens: fixture.maxTokens },\n model!,\n ac.signal,\n emit,\n undefined,\n undefined\n );\n } catch (err) {\n caught = err;\n }\n expect(caught).toBeDefined();\n expect(isAbortError(caught)).toBe(true);\n },\n opts.timeout\n );\n\n if (!skipMid) {\n itMidStream(\n \"streaming run-fn terminates within abortGraceMs * 4 when aborted mid-stream\",\n async () => {\n const registry = getAiProviderRegistry();\n const repo = getGlobalModelRepository();\n const model = await repo.findByName(opts.models.textGeneration!);\n expect(model).toBeDefined();\n const streamFn = registry.getRunFnFor(model!.provider, TEXT_GENERATION);\n if (!streamFn) return; // capability mismatch — covered by capabilityHonesty\n const ac = new AbortController();\n const start = Date.now();\n setTimeout(() => ac.abort(), fixture.abortGraceMs);\n\n try {\n const emit = (_e: StreamEvent<TaskOutput>): void => {};\n await streamFn(\n { prompt: fixture.textPrompt, maxTokens: fixture.maxTokens },\n model!,\n ac.signal,\n emit,\n undefined,\n undefined\n );\n } catch (err) {\n if (!isAbortError(err)) throw err;\n }\n const elapsed = Date.now() - start;\n expect(elapsed).toBeLessThan(fixture.abortGraceMs * 4 + 2000);\n },\n opts.timeout\n );\n }\n });\n}\n",
14
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { structuredGeneration } from \"@workglow/ai\";\nimport { describe, expect } from \"vitest\";\n\nimport { it } from \"../../creditExhaustedSkip\";\n\nimport type { AiProviderConformanceOpts, ConformanceFixture } from \"../types\";\n\nexport function structuredGenerationBlock(\n opts: AiProviderConformanceOpts,\n fixture: ConformanceFixture\n): void {\n const enabled = opts.capabilities.structured && !!opts.models.structured;\n describe.skipIf(!enabled)(\"Structured generation\", () => {\n it(\n \"produces an object that contains the schema's required fields\",\n async () => {\n const result = await structuredGeneration({\n model: opts.models.structured!,\n prompt: fixture.structuredPrompt,\n outputSchema: fixture.structuredSchema as { [x: string]: unknown },\n maxTokens: fixture.maxTokens,\n });\n expect(result).toBeDefined();\n expect(result.object).toBeDefined();\n expect(typeof result.object).toBe(\"object\");\n expect(result.object).toHaveProperty(\"name\");\n expect(result.object).toHaveProperty(\"age\");\n },\n opts.timeout\n );\n });\n}\n",
15
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability } from \"@workglow/ai\";\nimport { getAiProviderRegistry, getGlobalModelRepository, textGeneration } from \"@workglow/ai\";\nimport type { StreamEvent, TaskOutput } from \"@workglow/task-graph\";\nimport { describe, expect } from \"vitest\";\n\nimport { it } from \"../../creditExhaustedSkip\";\n\nimport type { AiProviderConformanceOpts, ConformanceFixture } from \"../types\";\n\nconst TEXT_GENERATION: readonly Capability[] = [\"text.generation\"];\n\nexport function textGenerationSmokeBlock(\n opts: AiProviderConformanceOpts,\n fixture: ConformanceFixture\n): void {\n describe.skipIf(!opts.models.textGeneration)(\"TextGeneration smoke\", () => {\n it(\n \"task-level textGeneration() returns non-empty text\",\n async () => {\n const result = await textGeneration({\n model: opts.models.textGeneration!,\n prompt: fixture.textPrompt,\n maxTokens: fixture.maxTokens,\n });\n expect(result).toBeDefined();\n expect(typeof result.text).toBe(\"string\");\n expect(result.text.length).toBeGreaterThan(0);\n },\n opts.timeout\n );\n\n it.skipIf(!opts.capabilities.streaming)(\n \"streaming yields ≥1 text-delta and exactly one finish, with no event after finish\",\n async () => {\n const registry = getAiProviderRegistry();\n const model = await getGlobalModelRepository().findByName(opts.models.textGeneration!);\n expect(model).toBeDefined();\n const streamFn = registry.getRunFnFor(model!.provider, TEXT_GENERATION);\n expect(streamFn).toBeDefined();\n\n let textDeltaCount = 0;\n let finishCount = 0;\n let sawEventAfterFinish = false;\n const emit = (ev: StreamEvent<TaskOutput>): void => {\n if (finishCount > 0) {\n sawEventAfterFinish = true;\n }\n const e = ev as { type: string };\n if (e.type === \"text-delta\") textDeltaCount += 1;\n if (e.type === \"finish\") finishCount += 1;\n };\n await streamFn!(\n { prompt: fixture.textPrompt, maxTokens: fixture.maxTokens },\n model!,\n new AbortController().signal,\n emit,\n undefined,\n undefined\n );\n\n expect(textDeltaCount).toBeGreaterThanOrEqual(1);\n expect(finishCount).toBe(1);\n expect(sawEventAfterFinish).toBe(false);\n },\n opts.timeout\n );\n });\n}\n",
16
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { ToolCalls, ToolDefinition } from \"@workglow/ai\";\nimport { toolCalling } from \"@workglow/ai\";\nimport { parsePartialJson } from \"@workglow/util/schema\";\nimport { describe, expect } from \"vitest\";\n\nimport { it } from \"../../creditExhaustedSkip\";\n\nimport type { AiProviderConformanceOpts, ConformanceFixture } from \"../types\";\n\nexport function toolCallAccumulatorBlock(\n opts: AiProviderConformanceOpts,\n fixture: ConformanceFixture\n): void {\n const enabled = opts.capabilities.tools && !!opts.models.toolCalling;\n describe.skipIf(!enabled)(\"Tool-call accumulator\", () => {\n it(\n \"produces ≥1 call with non-empty id, expected name, and parsable final args\",\n async () => {\n // NOTE: This test only inspects the *final* tool-call result. Validating\n // intermediate stream-delta stability (id constant across object-deltas,\n // parsePartialJson at every intermediate step) requires driving the\n // streamFn directly and is tracked as a follow-up enhancement.\n const tool: ToolDefinition = {\n name: fixture.weatherTool.name,\n description: fixture.weatherTool.description,\n inputSchema: fixture.weatherTool.inputSchema,\n };\n const result = await toolCalling({\n model: opts.models.toolCalling!,\n prompt: fixture.weatherToolPrompt,\n tools: [tool],\n toolChoice: \"required\",\n maxTokens: fixture.maxTokens,\n messages: undefined,\n });\n const calls: ToolCalls = result.toolCalls;\n expect(calls.length).toBeGreaterThan(0);\n const call = calls[0];\n expect(call.name).toBe(fixture.weatherTool.name);\n expect(call.id).toBeTruthy();\n expect(call.input).toBeDefined();\n\n // Final args, when serialized, must round-trip through parsePartialJson.\n const serialized = typeof call.input === \"string\" ? call.input : JSON.stringify(call.input);\n const parsed = parsePartialJson(serialized);\n expect(parsed).toBeDefined();\n },\n opts.timeout\n );\n\n it(\n \"produces no tool calls with toolChoice none\",\n async () => {\n const tool: ToolDefinition = {\n name: fixture.weatherTool.name,\n description: fixture.weatherTool.description,\n inputSchema: fixture.weatherTool.inputSchema,\n };\n const result = await toolCalling({\n model: opts.models.toolCalling!,\n prompt: fixture.weatherToolPrompt,\n tools: [tool],\n toolChoice: \"none\",\n maxTokens: fixture.maxTokens,\n messages: undefined,\n });\n expect(result).toBeDefined();\n expect(typeof result.text).toBe(\"string\");\n expect(result.text.length).toBeGreaterThan(0);\n expect(result.toolCalls).toHaveLength(0);\n },\n opts.timeout\n );\n });\n}\n",
17
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { ToolCalls, ToolDefinition } from \"@workglow/ai\";\nimport { Workflow } from \"@workglow/task-graph\";\nimport { describe, expect } from \"vitest\";\n\nimport { it } from \"../../creditExhaustedSkip\";\n\nimport type { AiProviderConformanceOpts, ConformanceFixture } from \"../types\";\n\nexport function toolCallMultiTurnBlock(\n opts: AiProviderConformanceOpts,\n fixture: ConformanceFixture\n): void {\n const enabled = opts.capabilities.tools && !!opts.models.toolCalling;\n describe.skipIf(!enabled)(\"Tool-call multi-turn\", () => {\n it(\n \"second turn returns non-empty text after a tool result is provided\",\n async () => {\n const tool: ToolDefinition = {\n name: fixture.weatherTool.name,\n description: fixture.weatherTool.description,\n inputSchema: fixture.weatherTool.inputSchema,\n };\n const wf1 = new Workflow();\n wf1.toolCalling({\n model: opts.models.toolCalling!,\n prompt: fixture.multiTurnTranscript[0].text,\n tools: [tool],\n toolChoice: \"auto\",\n maxTokens: fixture.maxTokens,\n });\n const r1 = (await wf1.run()) as { text: string; toolCalls: ToolCalls };\n if (!r1.toolCalls || r1.toolCalls.length === 0) return; // small models may skip the call\n const call = r1.toolCalls[0];\n\n const wf2 = new Workflow();\n wf2.toolCalling({\n model: opts.models.toolCalling!,\n prompt: fixture.multiTurnTranscript[0].text,\n tools: [tool],\n toolChoice: \"auto\",\n maxTokens: fixture.maxTokens,\n messages: [\n {\n role: \"user\",\n content: [{ type: \"text\", text: fixture.multiTurnTranscript[0].text }],\n },\n {\n role: \"assistant\",\n content: [\n { type: \"text\", text: r1.text || fixture.multiTurnTranscript[1].text },\n {\n type: \"tool_use\",\n id: call.id,\n name: call.name,\n input: call.input,\n // Round-trip the opaque provider signature (e.g. Gemini's\n // thoughtSignature) — thinking models reject a replayed tool\n // call whose signature was dropped.\n providerSignature: call.providerSignature,\n },\n ],\n },\n {\n role: \"tool\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: call.id,\n content: [{ type: \"text\" as const, text: fixture.multiTurnTranscript[2].text }],\n is_error: undefined,\n },\n ],\n },\n ],\n });\n const r2 = (await wf2.run()) as { text: string };\n expect(typeof r2.text).toBe(\"string\");\n expect(r2.text.length).toBeGreaterThan(0);\n },\n opts.timeout\n );\n });\n}\n",
18
+ "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { expect } from \"vitest\";\n\n/**\n * A registered run-fn capability that `inferCapabilities` never returns is\n * unreachable for any model whose record was populated by inference — the\n * path the catalog exists to serve.\n *\n * The inferred sets are unioned across the provider's fixtures, so this\n * answers \"is this capability reachable at all\" and says nothing about any one\n * model; {@link assertInferServesInferred} is the per-model direction.\n */\nexport function assertInferAdvertisesRegistered(\n name: string,\n registered: readonly (readonly string[])[],\n inferred: readonly (readonly string[])[]\n): void {\n const registeredCaps = new Set(registered.flat());\n const inferredCaps = new Set(inferred.flat());\n const missing = [...registeredCaps].filter((cap) => !inferredCaps.has(cap)).sort();\n expect(\n missing,\n `${name} registers capabilities that inferCapabilities never returns: ${missing.join(\", \")}`\n ).toEqual([]);\n}\n",
19
+ "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { expect } from \"vitest\";\n\n/** One fixture model id paired with the capabilities `inferCapabilities` returns for it. */\nexport interface InferredForModel {\n readonly id: string;\n readonly capabilities: readonly string[];\n}\n\n/**\n * `vision-input` says how a model accepts input rather than a call the provider\n * can be asked to run. The other modifiers ride along inside a generation\n * run-fn's `serves` (`[\"text.generation\", \"tool-use\"]`), but nothing registers\n * `vision-input`, so it annotates the record and is never a lookup key.\n */\nconst MARKER_CAPABILITIES: ReadonlySet<string> = new Set([\"vision-input\"]);\n\n/**\n * Capabilities whose run-fn acts on a chat session, and only the generative\n * run-fns ever open one. `serves` is registered per provider rather than per\n * model, so the subset check alone cannot see that a model without\n * `text.generation` has no session to warm or free.\n */\nconst SESSION_CAPABILITIES: ReadonlySet<string> = new Set([\"cache.checkpoint\", \"session.dispose\"]);\n\n/**\n * The per-model direction of {@link assertInferAdvertisesRegistered}: that one\n * unions the inferred sets across a provider's fixtures, which answers \"is this\n * capability reachable at all\" and passes a branch that advertises a capability\n * no run-fn can serve *for that model*. Such a model clears\n * `modelMeetsRequires` during selection and fails inside the provider instead,\n * with the capability message it would have gotten replaced by whatever the\n * provider throws.\n */\nexport function assertInferServesInferred(\n name: string,\n registered: readonly (readonly string[])[],\n inferred: readonly InferredForModel[]\n): void {\n const unservable: string[] = [];\n for (const { id, capabilities } of inferred) {\n const inferredSet = new Set(capabilities);\n for (const capability of capabilities) {\n if (MARKER_CAPABILITIES.has(capability)) continue;\n const servable = registered.some(\n (serves) => serves.includes(capability) && serves.every((cap) => inferredSet.has(cap))\n );\n if (!servable) {\n unservable.push(`${id}: ${capability} — no run-fn serves it within this model's set`);\n } else if (SESSION_CAPABILITIES.has(capability) && !inferredSet.has(\"text.generation\")) {\n unservable.push(`${id}: ${capability} — no session without text.generation`);\n }\n }\n }\n expect(\n unservable,\n `${name} infers capabilities it cannot serve for that model:\\n ${unservable.join(\"\\n \")}`\n ).toEqual([]);\n}\n",
20
+ "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { ModelPricing } from \"@workglow/ai\";\nimport { expect } from \"vitest\";\n\n/** One fixture model, its inferred capabilities, and the card its provider returns. */\nexport interface PricedModel {\n readonly id: string;\n readonly capabilities: readonly string[];\n readonly pricing: ModelPricing | undefined;\n}\n\n/**\n * Capabilities billed by something other than a token.\n *\n * An image is billed per image, speech per character or per second. A card\n * carrying `input`/`output` per-1M-token rates for one of these is not an\n * approximation of the real price — it is a different unit, and arithmetic on\n * it produces a number with no meaning that renders beside real costs.\n */\nconst NOT_TOKEN_BILLED: ReadonlySet<string> = new Set([\n \"image.generation\",\n \"audio.speech\",\n \"audio.transcription\",\n]);\n\n/** Whether a card quotes a per-token rate at all. */\nfunction quotesTokenRate(pricing: ModelPricing | undefined): boolean {\n if (pricing === undefined) return false;\n return (\n typeof pricing.input === \"number\" ||\n typeof pricing.output === \"number\" ||\n typeof pricing.cached === \"number\"\n );\n}\n\n/**\n * A provider must not quote a per-token rate for a model its own inference says\n * is not billed per token.\n *\n * This is the direction that catches a real fabricated number, and it is a hard\n * assertion because there is no legitimate case for it: `grok-2-image-1212`\n * resolved `grok-2`'s per-1M-token card through the pricing table's substring\n * walk, and `gemini-2.5-flash-image-preview` took `gemini-2.5-flash`'s the same\n * way. Both are image models by the provider's own catalogue.\n *\n * A free card is exempt: `input: 0` on a local model says \"this costs nothing\",\n * which is true whatever the billing unit, and is how every local provider\n * answers.\n */\nexport function assertPricingMatchesModality(\n name: string,\n models: readonly PricedModel[],\n namedByTable: readonly string[] = []\n): void {\n const named = new Set(namedByTable);\n const fabricated: string[] = [];\n for (const { id, capabilities, pricing } of models) {\n if (!capabilities.some((capability) => NOT_TOKEN_BILLED.has(capability))) continue;\n if (!quotesTokenRate(pricing)) continue;\n // A card the provider's table names outright is a deliberate rate, not a\n // borrowed one. Recorded per provider rather than inferred, so adding an\n // image model to a table is a decision someone writes down.\n if (named.has(id)) continue;\n const free = (pricing?.input ?? 0) === 0 && (pricing?.output ?? 0) === 0;\n if (free) continue;\n const billed = capabilities.filter((capability) => NOT_TOKEN_BILLED.has(capability));\n fabricated.push(\n `${id}: ${billed.join(\", \")} but priced ` +\n `input=${String(pricing?.input)} output=${String(pricing?.output)} per 1M tokens`\n );\n }\n\n expect(fabricated, `${name} borrows a per-token rate for a model not billed per token`).toEqual(\n []\n );\n\n // The recorded set must stay honest too: an id that stopped being priced, or\n // stopped being an image model, should leave it rather than sit there\n // exempting nothing.\n const stale = namedByTable.filter(\n (id) =>\n !models.some(\n ({ id: modelId, capabilities, pricing }) =>\n modelId === id &&\n capabilities.some((capability) => NOT_TOKEN_BILLED.has(capability)) &&\n quotesTokenRate(pricing)\n )\n );\n expect(\n stale,\n `${name}: recorded as deliberately priced but no longer is: ${stale.join(\", \")}`\n ).toEqual([]);\n}\n\n/**\n * The weaker direction: a token-billed model SHOULD carry a card.\n *\n * A ratchet rather than an assertion, deliberately. Real gaps exist today —\n * `gemini-embedding-001` among them — and a hard assert would redden the build\n * on a known one and get disabled, which costs more than the gap. Recording the\n * set means it cannot grow while it shrinks deliberately.\n */\nexport function assertPricedGapDoesNotGrow(\n name: string,\n models: readonly PricedModel[],\n knownUnpriced: readonly string[]\n): void {\n const unpriced = models\n .filter(\n ({ capabilities, pricing }) =>\n capabilities.length > 0 &&\n !capabilities.some((capability) => NOT_TOKEN_BILLED.has(capability)) &&\n pricing === undefined\n )\n .map(({ id }) => id)\n .sort();\n\n const known = new Set(knownUnpriced);\n expect(\n unpriced.filter((id) => !known.has(id)),\n `${name} has a token-billed model with no rate card that was not recorded`\n ).toEqual([]);\n\n // Not a failure — a prompt to shrink the recorded set once a gap is closed.\n const closed = knownUnpriced.filter((id) => !unpriced.includes(id));\n expect(closed, `${name}: now priced — drop from the recorded set: ${closed.join(\", \")}`).toEqual(\n []\n );\n}\n",
21
+ "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Usage } from \"@workglow/ai\";\nimport { describe, expect } from \"vitest\";\n\nimport { it } from \"../../creditExhaustedSkip\";\n\n/**\n * Shared contract for every provider's usage normalization.\n *\n * Each provider reads token counts off a different terminal frame, but they all\n * have to land in {@link Usage} under one rule: **`undefined` means the provider\n * did not report this figure, and never means zero.** Collapsing \"not reported\"\n * to `0` silently understates spend — a model that billed no cached tokens and\n * a model that says nothing about caching are different facts.\n *\n * A provider registers its mapper here rather than re-litigating the rule in its\n * own suite, so a new provider inherits the same guarantees.\n */\n\n/** The full set of normalized counters, used to check untouched slots. */\nconst USAGE_COUNTER_FIELDS = [\n \"input\",\n \"output\",\n \"cached\",\n \"cacheWrite\",\n \"reasoning\",\n \"total\",\n] as const;\n\ntype UsageCounterField = (typeof USAGE_COUNTER_FIELDS)[number];\n\nexport interface UsageNormalizationCase {\n /** What this frame represents, e.g. \"a cache-hit completion\". */\n readonly name: string;\n /** The provider-shaped payload handed to the mapper. */\n readonly frame: unknown;\n /** The exact expected result — compared with `toEqual`, so extra keys fail. */\n readonly expected: Usage | undefined;\n}\n\nexport interface UsageNormalizationOpts {\n /** Provider name, used in test titles. */\n readonly provider: string;\n /** The provider's own mapper from a raw frame to {@link Usage}. */\n readonly mapUsage: (raw: unknown) => Usage | undefined;\n /** Provider-specific frames and their expected mappings. */\n readonly cases: readonly UsageNormalizationCase[];\n /**\n * A minimal real frame reporting only `sparseReports`. Every counter outside\n * that set must come back `undefined` — this is the zero-vs-absent guard.\n */\n readonly sparseFrame: unknown;\n /** Counters the sparse frame actually reports. */\n readonly sparseReports: readonly UsageCounterField[];\n /**\n * A frame in which the provider genuinely reports `0` for `sparseReports`.\n * Proves the mapper does not discard a real zero along with the absent ones.\n */\n readonly zeroFrame: unknown;\n}\n\n/** Assert a mapped {@link Usage} carries only numbers and `undefined`. */\nexport function assertUsageShape(usage: Usage): void {\n for (const field of USAGE_COUNTER_FIELDS) {\n const value = usage[field];\n if (value === undefined) continue;\n expect(typeof value, `${field} must be a number when reported`).toBe(\"number\");\n expect(Number.isFinite(value as number), `${field} must be finite`).toBe(true);\n }\n if (usage.extra !== undefined) {\n for (const [key, value] of Object.entries(usage.extra)) {\n expect([\"number\", \"string\"], `extra.${key} must be a number or string`).toContain(\n typeof value\n );\n }\n }\n}\n\n/**\n * Assert the field relationships every provider's mapper must produce.\n *\n * The sum check only runs when the provider states a `total` — it is the\n * provider's own arithmetic, so it is the one place the normalization can be\n * checked against an external authority rather than against itself.\n */\nexport function assertUsageDisjointness(usage: Usage): void {\n if (usage.reasoning !== undefined && usage.output !== undefined) {\n expect(\n usage.reasoning <= usage.output,\n `reasoning (${usage.reasoning}) is a subset of output (${usage.output})`\n ).toBe(true);\n }\n if (usage.total === undefined) return;\n const parts = [usage.input, usage.cached, usage.cacheWrite, usage.output];\n if (parts.every((part) => part === undefined)) return;\n const sum = parts.reduce<number>((acc, part) => acc + (part ?? 0), 0);\n expect(sum, `input + cached + cacheWrite + output must equal the provider's stated total`).toBe(\n usage.total\n );\n}\n\nexport function usageNormalizationBlock(opts: UsageNormalizationOpts): void {\n describe(`${opts.provider} usage normalization contract`, () => {\n it(\"reports nothing when the provider sent no usage payload\", () => {\n for (const empty of [undefined, null, {}, \"usage\", 42]) {\n expect(opts.mapUsage(empty), `mapped ${JSON.stringify(empty) ?? \"undefined\"}`).toBe(\n undefined\n );\n }\n });\n\n it(\"leaves counters the provider did not report as undefined, never 0\", () => {\n const usage = opts.mapUsage(opts.sparseFrame);\n expect(usage, \"a frame with real counters must map to a Usage\").toBeDefined();\n const reported = new Set<UsageCounterField>(opts.sparseReports);\n for (const field of USAGE_COUNTER_FIELDS) {\n if (reported.has(field)) {\n expect(usage![field], `${field} was reported and must survive`).toBeTypeOf(\"number\");\n } else {\n // The whole point: an unreported counter is absent, not zero.\n expect(usage![field], `${field} was not reported and must be undefined`).toBe(undefined);\n }\n }\n });\n\n it(\"preserves a genuinely reported zero rather than dropping it\", () => {\n const usage = opts.mapUsage(opts.zeroFrame);\n expect(usage, \"a frame reporting 0 still reported something\").toBeDefined();\n for (const field of opts.sparseReports) {\n expect(usage![field], `${field} reported 0 and must stay 0`).toBe(0);\n }\n });\n\n it(\"maps only numbers and undefined into the normalized shape\", () => {\n for (const testCase of opts.cases) {\n const usage = opts.mapUsage(testCase.frame);\n if (usage) assertUsageShape(usage);\n }\n const sparse = opts.mapUsage(opts.sparseFrame);\n if (sparse) assertUsageShape(sparse);\n });\n\n it(\"keeps input/cached/cacheWrite disjoint and reasoning inside output\", () => {\n for (const testCase of opts.cases) {\n const usage = opts.mapUsage(testCase.frame);\n if (usage) assertUsageDisjointness(usage);\n }\n const sparse = opts.mapUsage(opts.sparseFrame);\n if (sparse) assertUsageDisjointness(sparse);\n });\n\n for (const testCase of opts.cases) {\n it(`maps ${testCase.name}`, () => {\n expect(opts.mapUsage(testCase.frame)).toEqual(testCase.expected);\n });\n }\n });\n}\n"
22
+ ],
23
+ "mappings": "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",
24
+ "debugId": "A13FF2AAA5D2709B64756E2164756E21",
25
+ "names": []
26
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { AccessibilityTree, AriaRole, BrowserConnectOptions, ClickOptions, DialogAction, DialogInfo, DownloadOptions, DownloadResult, ElementRef, IBrowserContext, NavigateOptions, ScreenshotOptions, SnapshotOptions, TabInfo, WaitOptions } from "@workglow/browser-control/task";
7
+ export declare class ConformanceMockContext implements IBrowserContext {
8
+ private connected;
9
+ private nextTabSeq;
10
+ private nextRefSeq;
11
+ private pages;
12
+ private activeTabId;
13
+ /** ref → { tabId, name } produced by snapshot(). */
14
+ private refMap;
15
+ connect(_options?: BrowserConnectOptions): Promise<void>;
16
+ disconnect(): Promise<void>;
17
+ isConnected(): boolean;
18
+ private makePage;
19
+ private active;
20
+ navigate(url: string, _options?: NavigateOptions): Promise<void>;
21
+ goBack(_options?: NavigateOptions): Promise<void>;
22
+ goForward(_options?: NavigateOptions): Promise<void>;
23
+ reload(_options?: NavigateOptions): Promise<void>;
24
+ currentUrl(): Promise<string>;
25
+ title(): Promise<string>;
26
+ snapshot(_options?: SnapshotOptions): Promise<AccessibilityTree>;
27
+ click(ref: ElementRef, _options?: ClickOptions): Promise<void>;
28
+ fill(_ref: ElementRef, _value: string, _options?: WaitOptions): Promise<void>;
29
+ selectOption(_ref: ElementRef, _values: string | readonly string[], _options?: WaitOptions): Promise<void>;
30
+ hover(_ref: ElementRef, _options?: WaitOptions): Promise<void>;
31
+ clickByRole(role: AriaRole, name: string, _options?: ClickOptions): Promise<void>;
32
+ fillByLabel(_label: string, _value: string, _options?: WaitOptions): Promise<void>;
33
+ content(): Promise<string>;
34
+ innerHTML(_ref: ElementRef): Promise<string>;
35
+ textContent(ref: ElementRef): Promise<string | null>;
36
+ attribute(ref: ElementRef, name: string): Promise<string | null>;
37
+ querySelector(selector: string): Promise<ElementRef | null>;
38
+ querySelectorAll(_selector: string): Promise<readonly ElementRef[]>;
39
+ evaluate<T>(expression: string): Promise<T>;
40
+ screenshot(_options?: ScreenshotOptions): Promise<Buffer>;
41
+ pressKey(_key: string, _options?: WaitOptions): Promise<void>;
42
+ type(_text: string, _options?: WaitOptions): Promise<void>;
43
+ scroll(_x: number, _y: number, _ref?: ElementRef): Promise<void>;
44
+ uploadFile(_ref: ElementRef, _paths: string | readonly string[]): Promise<void>;
45
+ download(trigger: () => Promise<void>, _options?: DownloadOptions): Promise<DownloadResult>;
46
+ onDialog(_handler: (info: DialogInfo) => DialogAction | Promise<DialogAction>): void;
47
+ tabs(): Promise<readonly TabInfo[]>;
48
+ switchTab(tabId: string): Promise<void>;
49
+ newTab(url?: string): Promise<TabInfo>;
50
+ closeTab(tabId: string): Promise<void>;
51
+ waitForNavigation(_options?: NavigateOptions): Promise<void>;
52
+ waitForSelector(_selector: string, _options?: WaitOptions): Promise<ElementRef>;
53
+ waitForIdle(_options?: WaitOptions): Promise<void>;
54
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { BrowserContextFixture, IBrowserContextConformanceOpts } from "../types";
7
+ export declare function ariaRoundTripBlock(opts: IBrowserContextConformanceOpts, fixture: BrowserContextFixture): void;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { BrowserContextFixture, IBrowserContextConformanceOpts } from "../types";
7
+ export declare function capabilityHonestyBlock(opts: IBrowserContextConformanceOpts, fixture: BrowserContextFixture): void;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ type ItFn = (name: string, fn: () => Promise<void> | void, timeout?: number) => void;
7
+ export declare const itExpectFail: ItFn;
8
+ export {};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { BrowserContextFixture, IBrowserContextConformanceOpts } from "../types";
7
+ export declare function networkIntrospectionBlock(opts: IBrowserContextConformanceOpts, fixture: BrowserContextFixture): void;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { BrowserContextFixture, IBrowserContextConformanceOpts } from "../types";
7
+ export declare function tabsLifecycleBlock(opts: IBrowserContextConformanceOpts, fixture: BrowserContextFixture): void;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { BrowserContextFixture } from "./types";
7
+ export declare const DEFAULT_FIXTURE: BrowserContextFixture;
8
+ export declare function resolveFixture(override: Partial<BrowserContextFixture> | undefined): BrowserContextFixture;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { IBrowserContextConformanceOpts } from "./types";
7
+ export declare function runIBrowserContextConformance(opts: IBrowserContextConformanceOpts): void;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { IBrowserContext } from "@workglow/browser-control/task";
7
+ export interface IBrowserContextConformanceOpts {
8
+ readonly name: string;
9
+ readonly skip?: boolean;
10
+ readonly timeout: number;
11
+ readonly factory: () => Promise<BrowserContextHandle>;
12
+ readonly capabilities: BrowserContextCapabilities;
13
+ readonly fixture?: Partial<BrowserContextFixture>;
14
+ /**
15
+ * Names of conformance assertions currently broken in this adapter; each
16
+ * named assertion is wrapped in `it.fails` instead of `it`. Remove the
17
+ * entry once the adapter bug is fixed.
18
+ *
19
+ * Known names:
20
+ * "tabs.concurrentCloseStable"
21
+ * "aria.colonInName"
22
+ * "capability.networkRequests.undefinedWhenFalse"
23
+ * "capability.consoleMessages.undefinedWhenFalse"
24
+ */
25
+ readonly expectedFailures?: ReadonlyArray<string>;
26
+ }
27
+ export interface BrowserContextHandle {
28
+ /** Construct and connect a fresh context. Called per top-level block. */
29
+ readonly create: () => Promise<IBrowserContext>;
30
+ /** Disconnect and release resources for a context returned by create(). */
31
+ readonly dispose: (ctx: IBrowserContext) => Promise<void>;
32
+ }
33
+ export interface BrowserContextCapabilities {
34
+ /** false for single-view backends (e.g. BunWebView). */
35
+ readonly multipleTabs: boolean;
36
+ /** Optional method honesty + positive test. */
37
+ readonly networkRequests: boolean;
38
+ /** Optional method honesty + positive test. */
39
+ readonly consoleMessages: boolean;
40
+ /** Every backend should be true; flag exists for hygiene/symmetry. */
41
+ readonly ariaSnapshot: boolean;
42
+ }
43
+ export interface BrowserContextFixture {
44
+ readonly pageUrl: string;
45
+ readonly networkMarkerUrl: string;
46
+ readonly consoleMarker: string;
47
+ readonly ariaEdgeCaseNames: ReadonlyArray<string>;
48
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Steven Roussey <sroussey@gmail.com>
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Conformance suite for `IBrowserContext` — tab lifecycle, ARIA round trip and
8
+ * network introspection, over every browser backend.
9
+ */
10
+ export * from "./browser-context/ConformanceMockContext";
11
+ export * from "./browser-context/fixtures";
12
+ export * from "./browser-context/runIBrowserContextConformance";
13
+ export * from "./browser-context/types";
14
+ export * from "./browser-context/assertions/ariaRoundTrip";
15
+ export * from "./browser-context/assertions/capabilityHonesty";
16
+ export * from "./browser-context/assertions/itExpectFail";
17
+ export * from "./browser-context/assertions/networkIntrospection";
18
+ export * from "./browser-context/assertions/tabsLifecycle";