From d778277be0ffe118410116877b5a5485ccad9f21 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 dd21d361..700b238b 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 78bba7b3..d5b16f95 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 1bc09d14..85b5fb79 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 077b9efe..a378f2f6 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 28cba3af..a237a08f 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 fe80f35b..432aa7af 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 f7f500d3..d74fd3c5 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 bf8597e5..eb295424 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 6ee385c1..58d32928 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 e642025a..8aa41ca0 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 839eaccc..6462a47e 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 b85b225a..f36857db 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 f01dee65..006d35e9 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 1f936126..5ae5f1fd 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 b44fba78..f762cb52 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 48d576cf..ecc6630e 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 83b37a96..21eafe79 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 ba34cddc..d33f37b3 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 ebde632a..741f5d02 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 d2534685..84e309fc 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": {