From d626aa0810af93c6bba1470e604df0ca8f4bf702 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Thu, 21 May 2026 14:20:07 -0700 Subject: [PATCH] fix(ci): repair main test regressions --- .../content/docs/agent/api/api-docs.json | 18 ------ .../content/docs/agent/api/provide-agent.mdx | 4 +- .../agent/getting-started/installation.mdx | 1 - .../getting-started/introduction.mdx | 4 +- .../docs/licensing/guides/ci-and-offline.mdx | 7 +-- .../content/docs/licensing/guides/setup.mdx | 11 ++-- .../content/docs/render/api/api-docs.json | 18 ------ .../render/getting-started/installation.mdx | 1 - apps/website/e2e/website.spec.ts | 14 ++++- libs/ag-ui/eslint.config.mjs | 2 - libs/ag-ui/package.json | 1 - libs/langgraph/package.json | 1 - libs/langgraph/src/lib/agent.provider.spec.ts | 58 ++++--------------- libs/langgraph/src/lib/agent.provider.ts | 29 ---------- libs/render/package.json | 3 +- libs/render/src/lib/lifecycle.spec.ts | 6 -- libs/render/src/lib/provide-render.spec.ts | 23 +++----- libs/render/src/lib/provide-render.ts | 15 ----- libs/render/src/lib/render.types.ts | 13 ----- package-lock.json | 5 +- 20 files changed, 42 insertions(+), 192 deletions(-) diff --git a/apps/website/content/docs/agent/api/api-docs.json b/apps/website/content/docs/agent/api/api-docs.json index dd21d361e..700b238b4 100644 --- a/apps/website/content/docs/agent/api/api-docs.json +++ b/apps/website/content/docs/agent/api/api-docs.json @@ -733,30 +733,12 @@ "kind": "interface", "description": "Global configuration for agent instances.\nProperties set here serve as defaults that can be overridden per-call.", "properties": [ - { - "name": "__licenseEnvHint", - "type": "object", - "description": "Test-only env hint override. Not part of the stable API.", - "optional": true - }, - { - "name": "__licensePublicKey", - "type": "Uint8Array", - "description": "Test-only public-key override. Defaults to the compile-time embedded\n`LICENSE_PUBLIC_KEY`. Not part of the stable API.", - "optional": true - }, { "name": "apiUrl", "type": "string", "description": "Base URL of the LangGraph Platform API (e.g., `'http://localhost:2024'`).", "optional": true }, - { - "name": "license", - "type": "string", - "description": "Signed license token from threadplane.ai. Optional; omitted in dev.", - "optional": true - }, { "name": "transport", "type": "AgentTransport", diff --git a/apps/website/content/docs/agent/api/provide-agent.mdx b/apps/website/content/docs/agent/api/provide-agent.mdx index 78bba7b34..d5b16f953 100644 --- a/apps/website/content/docs/agent/api/provide-agent.mdx +++ b/apps/website/content/docs/agent/api/provide-agent.mdx @@ -1,6 +1,6 @@ # provideAgent() -`provideAgent()` registers global defaults for every `agent()` call in an Angular application. Call it once in `bootstrapApplication` or an `ApplicationConfig` when multiple agents share the same LangGraph API URL, transport, or license token. +`provideAgent()` registers global defaults for every `agent()` call in an Angular application. Call it once in `bootstrapApplication` or an `ApplicationConfig` when multiple agents share the same LangGraph API URL or transport. Per-call options still win over provider defaults, so you can configure the common case globally and override individual agents when needed. @@ -16,7 +16,6 @@ bootstrapApplication(AppComponent, { providers: [ provideAgent({ apiUrl: 'http://localhost:2024', - license: environment.ngafLicense, transport: environment.testMode ? new MockAgentTransport() : undefined, @@ -31,7 +30,6 @@ bootstrapApplication(AppComponent, { |--------|------|-------------| | `apiUrl` | `string` | Default LangGraph Platform API base URL. Individual `agent()` calls may override it. | | `transport` | `AgentTransport` | Optional transport instance. Defaults to `FetchStreamTransport` when omitted. | -| `license` | `string` | Optional signed license token. Development and noncommercial use can omit it. | ## Defaults and overrides diff --git a/apps/website/content/docs/agent/getting-started/installation.mdx b/apps/website/content/docs/agent/getting-started/installation.mdx index 1bc09d14a..85b5fb79f 100644 --- a/apps/website/content/docs/agent/getting-started/installation.mdx +++ b/apps/website/content/docs/agent/getting-started/installation.mdx @@ -31,7 +31,6 @@ npm install @ngaf/langgraph @ngaf/chat | Package | Version | |---------|---------| | `@ngaf/chat` | `*` | -| `@ngaf/licensing` | `*` | | `@angular/core` | `^20.0.0 \|\| ^21.0.0` | | `@langchain/core` | `^1.1.33` | | `@langchain/langgraph-sdk` | `^1.7.4` | diff --git a/apps/website/content/docs/licensing/getting-started/introduction.mdx b/apps/website/content/docs/licensing/getting-started/introduction.mdx index 077b9efea..a378f2f66 100644 --- a/apps/website/content/docs/licensing/getting-started/introduction.mdx +++ b/apps/website/content/docs/licensing/getting-started/introduction.mdx @@ -1,6 +1,6 @@ # Introduction -`@ngaf/licensing` is the shared license-check helper used by the framework packages. It verifies compact Ed25519-signed tokens offline, evaluates the result into a small status set, and emits non-blocking warnings when appropriate. +`@ngaf/licensing` is the shared license-check helper used by `@ngaf/chat` and by custom integrations that opt into the same warning behavior. It verifies compact Ed25519-signed tokens offline, evaluates the result into a small status set, and emits non-blocking warnings when appropriate. The package itself is MIT licensed. `COMMERCIAL.md` states that the libraries in this repository are free to use, modify, and distribute in commercial and noncommercial projects. The proprietary part called out there is the internal minting service, not this package. @@ -67,4 +67,4 @@ The higher-level check is designed not to block app startup: - warning output goes through `console.warn` unless a custom `warn` function is supplied; - no network request is made by the licensing check. -The code returns statuses instead of throwing for normal license states. Consumers can choose what to do with the status, but the framework packages use it as a warning and visibility mechanism, not as an app kill switch. +The code returns statuses instead of throwing for normal license states. Consumers can choose what to do with the status, and `@ngaf/chat` uses it as a warning and visibility mechanism, not as an app kill switch. diff --git a/apps/website/content/docs/licensing/guides/ci-and-offline.mdx b/apps/website/content/docs/licensing/guides/ci-and-offline.mdx index 28cba3af0..a237a08fd 100644 --- a/apps/website/content/docs/licensing/guides/ci-and-offline.mdx +++ b/apps/website/content/docs/licensing/guides/ci-and-offline.mdx @@ -12,13 +12,10 @@ For CI builds, treat the license token like any other secret: NGAF_LICENSE=... npm test ``` -Then pass it through the framework provider that owns the package you use. +Then pass it through `provideChat()`. ```ts -provideAgent({ - apiUrl: process.env['LANGGRAPH_API_URL'], - license: process.env['NGAF_LICENSE'], -}); +provideChat({ license: process.env['NGAF_LICENSE'] }); ``` If you call `runLicenseCheck()` directly, inject the current time only when you need deterministic tests: diff --git a/apps/website/content/docs/licensing/guides/setup.mdx b/apps/website/content/docs/licensing/guides/setup.mdx index fe80f35ba..432aa7afc 100644 --- a/apps/website/content/docs/licensing/guides/setup.mdx +++ b/apps/website/content/docs/licensing/guides/setup.mdx @@ -1,17 +1,14 @@ # Setup -Most applications do not import `@ngaf/licensing` directly. Framework packages call `runLicenseCheck()` from their providers when you pass a license token. +Most applications do not import `@ngaf/licensing` directly. `@ngaf/chat` calls `runLicenseCheck()` from `provideChat()` when you pass a license token. -For example, higher-level packages expose a `license` option: +For example, chat exposes a `license` option: ```ts -provideAgent({ - apiUrl: 'https://api.example.com', - license: environment.ngafLicense, -}); +provideChat({ license: environment.ngafLicense }); ``` -When no token is supplied, the licensing helper can evaluate the environment as `noncommercial` when the package passes `isNoncommercial: true`. +When no token is supplied, the licensing helper can evaluate the environment as `noncommercial` when the caller passes `isNoncommercial: true`. ## Direct use diff --git a/apps/website/content/docs/render/api/api-docs.json b/apps/website/content/docs/render/api/api-docs.json index f7f500d39..d74fd3c51 100644 --- a/apps/website/content/docs/render/api/api-docs.json +++ b/apps/website/content/docs/render/api/api-docs.json @@ -239,18 +239,6 @@ "kind": "interface", "description": "", "properties": [ - { - "name": "__licenseEnvHint", - "type": "object", - "description": "Test-only env hint override. Not part of the stable API.", - "optional": true - }, - { - "name": "__licensePublicKey", - "type": "Uint8Array", - "description": "Test-only public-key override. Defaults to the compile-time embedded\n`LICENSE_PUBLIC_KEY`. Not part of the stable API.", - "optional": true - }, { "name": "functions", "type": "Record", @@ -263,12 +251,6 @@ "description": "", "optional": true }, - { - "name": "license", - "type": "string", - "description": "Signed license token from threadplane.ai. Optional; omitted in dev.", - "optional": true - }, { "name": "registry", "type": "AngularRegistry", diff --git a/apps/website/content/docs/render/getting-started/installation.mdx b/apps/website/content/docs/render/getting-started/installation.mdx index bf8597e5a..eb295424c 100644 --- a/apps/website/content/docs/render/getting-started/installation.mdx +++ b/apps/website/content/docs/render/getting-started/installation.mdx @@ -28,7 +28,6 @@ The library requires the following peer dependencies: | `@angular/core` | `^20.0.0` or `^21.0.0` | | `@angular/common` | `^20.0.0` or `^21.0.0` | | `@json-render/core` | `^0.16.0` | -| `@ngaf/licensing` | `*` | `@angular/core` and `@angular/common` are already part of any Angular 20+ project. You only need to install `@json-render/core` as an additional dependency if your package manager does not install peer dependencies automatically. diff --git a/apps/website/e2e/website.spec.ts b/apps/website/e2e/website.spec.ts index 6ee385c18..58d32928c 100644 --- a/apps/website/e2e/website.spec.ts +++ b/apps/website/e2e/website.spec.ts @@ -28,9 +28,19 @@ test('pricing page shows plan cards', async ({ page }) => { }); test('pricing page lead form validates required fields', async ({ page }) => { + let checkoutCalled = false; + await page.route('**/api/checkout/session', async (route) => { + checkoutCalled = true; + await route.abort(); + }); + await page.goto('/pricing'); - await page.click('button[type="submit"]'); - await expect(page.locator('form').first()).toBeVisible(); + const leadForm = page.locator('#lead-form form'); + await expect(leadForm).toBeVisible(); + await leadForm.getByRole('button', { name: 'Get in touch' }).click(); + await expect(leadForm).toBeVisible(); + expect(checkoutCalled).toBe(false); + expect(await leadForm.evaluate((form) => (form as HTMLFormElement).checkValidity())).toBe(false); }); test('contact page submits a lead payload and renders success state', async ({ page }) => { diff --git a/libs/ag-ui/eslint.config.mjs b/libs/ag-ui/eslint.config.mjs index e642025aa..8aa41ca0f 100644 --- a/libs/ag-ui/eslint.config.mjs +++ b/libs/ag-ui/eslint.config.mjs @@ -14,8 +14,6 @@ export default [ 'vite', '@nx/vite', 'vitest', - // peerDeps used by later tasks (stub-only in Task 1) - '@ngaf/licensing', 'fast-json-patch', 'rxjs', ], diff --git a/libs/ag-ui/package.json b/libs/ag-ui/package.json index 839eaccc0..6462a47e9 100644 --- a/libs/ag-ui/package.json +++ b/libs/ag-ui/package.json @@ -3,7 +3,6 @@ "version": "0.0.46", "peerDependencies": { "@ngaf/chat": "*", - "@ngaf/licensing": "*", "@angular/core": "^20.0.0 || ^21.0.0", "@ag-ui/client": "*", "rxjs": "~7.8.0" diff --git a/libs/langgraph/package.json b/libs/langgraph/package.json index b85b225a5..f36857db0 100644 --- a/libs/langgraph/package.json +++ b/libs/langgraph/package.json @@ -3,7 +3,6 @@ "version": "0.0.46", "peerDependencies": { "@ngaf/chat": "*", - "@ngaf/licensing": "*", "@angular/core": "^20.0.0 || ^21.0.0", "@langchain/core": "^1.1.33", "@langchain/langgraph-sdk": "^1.7.4", diff --git a/libs/langgraph/src/lib/agent.provider.spec.ts b/libs/langgraph/src/lib/agent.provider.spec.ts index f01dee659..006d35e9b 100644 --- a/libs/langgraph/src/lib/agent.provider.spec.ts +++ b/libs/langgraph/src/lib/agent.provider.spec.ts @@ -1,19 +1,12 @@ // SPDX-License-Identifier: MIT import { beforeEach, describe, it, expect, vi } from 'vitest'; import { TestBed } from '@angular/core/testing'; -import { provideAgent, AGENT_CONFIG } from './agent.provider'; +import { provideAgent, AGENT_CONFIG, type AgentConfig } from './agent.provider'; import { MockAgentTransport } from './transport/mock-stream.transport'; -import { - signLicense, - generateKeyPair, - __resetRunLicenseCheckStateForTests, - __resetNagStateForTests, -} from '@ngaf/licensing/testing'; describe('provideAgent', () => { beforeEach(() => { - __resetRunLicenseCheckStateForTests(); - __resetNagStateForTests(); + globalThis.console.warn = vi.fn(); }); it('provides AGENT_CONFIG token', () => { @@ -33,48 +26,19 @@ describe('provideAgent', () => { expect(config.transport).toBe(transport); }); - it('runs a silent license check when a valid license is supplied', async () => { - const warn = vi.fn(); - globalThis.console.warn = warn; - const kp = await generateKeyPair(); - const token = await signLicense( - { - sub: 'cus_test', - tier: 'developer-seat', - iat: 1_700_000_000, - exp: 2_000_000_000, - seats: 1, - }, - kp.privateKey, - ); - TestBed.configureTestingModule({ - providers: [ - provideAgent({ - apiUrl: '', - license: token, - // @internal hook — verifies against the ephemeral pair so the test - // doesn't need to know/mint the production public key. - __licensePublicKey: kp.publicKey, - }), - ], - }); - TestBed.inject(AGENT_CONFIG); - // Allow microtasks from the ed25519 verify + telemetry fire-and-forget. - await new Promise((r) => setTimeout(r, 0)); - expect(warn).not.toHaveBeenCalled(); - }); + it('does not perform license checks because @ngaf/langgraph is MIT-licensed', async () => { + const warn = globalThis.console.warn as ReturnType; + const legacyLicenseConfig = { + apiUrl: '', + license: 'invalid-token', + __licenseEnvHint: { isNoncommercial: false }, + } as unknown as AgentConfig; - it('warns when license is missing and env is production-like', async () => { - const warn = vi.fn(); - globalThis.console.warn = warn; TestBed.configureTestingModule({ - providers: [ - provideAgent({ apiUrl: '', __licenseEnvHint: { isNoncommercial: false } }), - ], + providers: [provideAgent(legacyLicenseConfig)], }); TestBed.inject(AGENT_CONFIG); await new Promise((r) => setTimeout(r, 0)); - const calls = warn.mock.calls.map((c) => String(c[0])); - expect(calls.some((m) => m.includes('[threadplane] @ngaf/langgraph'))).toBe(true); + expect(warn).not.toHaveBeenCalled(); }); }); diff --git a/libs/langgraph/src/lib/agent.provider.ts b/libs/langgraph/src/lib/agent.provider.ts index 1f936126d..5ae5f1fdd 100644 --- a/libs/langgraph/src/lib/agent.provider.ts +++ b/libs/langgraph/src/lib/agent.provider.ts @@ -1,14 +1,7 @@ // SPDX-License-Identifier: MIT import { InjectionToken, Provider } from '@angular/core'; -import { - runLicenseCheck, - LICENSE_PUBLIC_KEY, - inferNoncommercial, -} from '@ngaf/licensing'; import { AgentTransport } from './agent.types'; -const PACKAGE_NAME = '@ngaf/langgraph'; - /** * Global configuration for agent instances. * Properties set here serve as defaults that can be overridden per-call. @@ -18,19 +11,6 @@ export interface AgentConfig { apiUrl?: string; /** Custom transport implementation. Defaults to {@link FetchStreamTransport}. */ transport?: AgentTransport; - /** Signed license token from threadplane.ai. Optional; omitted in dev. */ - license?: string; - /** - * @internal - * Test-only env hint override. Not part of the stable API. - */ - __licenseEnvHint?: { isNoncommercial: boolean }; - /** - * @internal - * Test-only public-key override. Defaults to the compile-time embedded - * `LICENSE_PUBLIC_KEY`. Not part of the stable API. - */ - __licensePublicKey?: Uint8Array; } export const AGENT_CONFIG = new InjectionToken('AGENT_CONFIG'); @@ -40,14 +20,5 @@ export const AGENT_CONFIG = new InjectionToken('AGENT_CONFIG'); * agent instances in the application. */ export function provideAgent(config: AgentConfig): Provider { - // Fire-and-forget license check. Never blocks DI resolution. - void runLicenseCheck({ - package: PACKAGE_NAME, - token: config.license, - publicKey: config.__licensePublicKey ?? LICENSE_PUBLIC_KEY, - isNoncommercial: - config.__licenseEnvHint?.isNoncommercial ?? inferNoncommercial(), - }); - return { provide: AGENT_CONFIG, useValue: config }; } diff --git a/libs/render/package.json b/libs/render/package.json index b44fba781..f762cb528 100644 --- a/libs/render/package.json +++ b/libs/render/package.json @@ -4,8 +4,7 @@ "peerDependencies": { "@angular/core": "^20.0.0 || ^21.0.0", "@angular/common": "^20.0.0 || ^21.0.0", - "@json-render/core": "^0.16.0", - "@ngaf/licensing": "*" + "@json-render/core": "^0.16.0" }, "license": "MIT", "repository": { diff --git a/libs/render/src/lib/lifecycle.spec.ts b/libs/render/src/lib/lifecycle.spec.ts index 48d576cf5..ecc6630e2 100644 --- a/libs/render/src/lib/lifecycle.spec.ts +++ b/libs/render/src/lib/lifecycle.spec.ts @@ -5,17 +5,11 @@ import { TestBed } from '@angular/core/testing'; import { RenderLifecycleService } from './render-lifecycle.service'; import { RENDER_LIFECYCLE } from './lifecycle'; import { provideRender } from './provide-render'; -import { - __resetRunLicenseCheckStateForTests, - __resetNagStateForTests, -} from '@ngaf/licensing/testing'; describe('RenderLifecycle', () => { let service: RenderLifecycleService; beforeEach(() => { - __resetRunLicenseCheckStateForTests(); - __resetNagStateForTests(); globalThis.console.warn = vi.fn(); TestBed.configureTestingModule({ providers: [provideRender({})], diff --git a/libs/render/src/lib/provide-render.spec.ts b/libs/render/src/lib/provide-render.spec.ts index 83b37a961..21eafe795 100644 --- a/libs/render/src/lib/provide-render.spec.ts +++ b/libs/render/src/lib/provide-render.spec.ts @@ -5,18 +5,12 @@ import { Component } from '@angular/core'; import { provideRender, RENDER_CONFIG } from './provide-render'; import { defineAngularRegistry } from './define-angular-registry'; import type { RenderConfig } from './render.types'; -import { - __resetRunLicenseCheckStateForTests, - __resetNagStateForTests, -} from '@ngaf/licensing/testing'; @Component({ selector: 'render-test-card', standalone: true, template: '
card
' }) class TestCardComponent {} describe('provideRender', () => { beforeEach(() => { - __resetRunLicenseCheckStateForTests(); - __resetNagStateForTests(); globalThis.console.warn = vi.fn(); }); @@ -40,19 +34,18 @@ describe('provideRender', () => { expect(config).toBeDefined(); }); - it('warns when license is missing in a production-like env', async () => { + it('does not perform license checks because @ngaf/render is MIT-licensed', async () => { + const legacyLicenseConfig = { + license: 'invalid-token', + __licenseEnvHint: { isNoncommercial: false }, + } as unknown as RenderConfig; + TestBed.configureTestingModule({ - providers: [ - provideRender({ __licenseEnvHint: { isNoncommercial: false } }), - ], + providers: [provideRender(legacyLicenseConfig)], }); TestBed.inject(RENDER_CONFIG); await new Promise((r) => setTimeout(r, 0)); const warn = globalThis.console.warn as ReturnType; - expect( - warn.mock.calls.some((c) => - String(c[0]).includes('[threadplane] @ngaf/render'), - ), - ).toBe(true); + expect(warn).not.toHaveBeenCalled(); }); }); diff --git a/libs/render/src/lib/provide-render.ts b/libs/render/src/lib/provide-render.ts index ba34cddc9..d33f37b38 100644 --- a/libs/render/src/lib/provide-render.ts +++ b/libs/render/src/lib/provide-render.ts @@ -1,27 +1,12 @@ // SPDX-License-Identifier: MIT import { InjectionToken, makeEnvironmentProviders } from '@angular/core'; -import { - runLicenseCheck, - LICENSE_PUBLIC_KEY, - inferNoncommercial, -} from '@ngaf/licensing'; import type { RenderConfig } from './render.types'; import { RENDER_LIFECYCLE } from './lifecycle'; import { RenderLifecycleService } from './render-lifecycle.service'; -const PACKAGE_NAME = '@ngaf/render'; - export const RENDER_CONFIG = new InjectionToken('RENDER_CONFIG'); export function provideRender(config: RenderConfig) { - void runLicenseCheck({ - package: PACKAGE_NAME, - token: config.license, - publicKey: config.__licensePublicKey ?? LICENSE_PUBLIC_KEY, - isNoncommercial: - config.__licenseEnvHint?.isNoncommercial ?? inferNoncommercial(), - }); - return makeEnvironmentProviders([ { provide: RENDER_CONFIG, useValue: config }, RenderLifecycleService, diff --git a/libs/render/src/lib/render.types.ts b/libs/render/src/lib/render.types.ts index ebde632a1..741f5d029 100644 --- a/libs/render/src/lib/render.types.ts +++ b/libs/render/src/lib/render.types.ts @@ -48,17 +48,4 @@ export interface RenderConfig { store?: StateStore; functions?: Record; handlers?: Record) => unknown | Promise>; - /** Signed license token from threadplane.ai. Optional; omitted in dev. */ - license?: string; - /** - * @internal - * Test-only env hint override. Not part of the stable API. - */ - __licenseEnvHint?: { isNoncommercial: boolean }; - /** - * @internal - * Test-only public-key override. Defaults to the compile-time embedded - * `LICENSE_PUBLIC_KEY`. Not part of the stable API. - */ - __licensePublicKey?: Uint8Array; } diff --git a/package-lock.json b/package-lock.json index d25346854..84e309fc7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -189,7 +189,6 @@ "@ag-ui/client": "*", "@angular/core": "^20.0.0 || ^21.0.0", "@ngaf/chat": "*", - "@ngaf/licensing": "*", "rxjs": "~7.8.0" } }, @@ -330,7 +329,6 @@ "@langchain/core": "^1.1.33", "@langchain/langgraph-sdk": "^1.7.4", "@ngaf/chat": "*", - "@ngaf/licensing": "*", "rxjs": "~7.8.0" } }, @@ -349,8 +347,7 @@ "peerDependencies": { "@angular/common": "^20.0.0 || ^21.0.0", "@angular/core": "^20.0.0 || ^21.0.0", - "@json-render/core": "^0.16.0", - "@ngaf/licensing": "*" + "@json-render/core": "^0.16.0" } }, "libs/telemetry": {