From 45bf5a69fc2a7b3add9aa5143c6f68393fbb44ce Mon Sep 17 00:00:00 2001 From: Brian Love Date: Wed, 27 May 2026 13:49:38 -0700 Subject: [PATCH 1/9] docs(spec): cockpit port registry design --- ...2026-05-27-cockpit-port-registry-design.md | 203 ++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-27-cockpit-port-registry-design.md diff --git a/docs/superpowers/specs/2026-05-27-cockpit-port-registry-design.md b/docs/superpowers/specs/2026-05-27-cockpit-port-registry-design.md new file mode 100644 index 00000000..60c92bcb --- /dev/null +++ b/docs/superpowers/specs/2026-05-27-cockpit-port-registry-design.md @@ -0,0 +1,203 @@ +# Cockpit port registry — design + +**Status:** Approved +**Date:** 2026-05-27 +**Goal:** Single source of truth for cockpit cap port allocation. A new cap currently requires updating 4 separate files (`angular/proxy.conf.json`, `angular/e2e/global-setup-impl.ts`, `python/project.json`, `angular/project.json`). This centralizes the angular + e2e references behind an importable registry and adds a CI verifier that asserts the literal `project.json` values match. + +## Why now + +The audit found port allocation lives in 4 disconnected sites per cap with no drift detection. The convention `angular_port + 1000 = langgraph_port` actually holds across the 31 LangGraph caps, but nothing enforces it — and a new cap requires hunting for the right places to edit. + +## Approach + +Three of the 4 sites can reference a shared TS/ESM module at runtime: +- `proxy.conf.mjs` (replaces `proxy.conf.json`) — Angular dev-server natively loads .mjs proxy configs +- `e2e/global-setup-impl.ts` — already TS, can import directly + +The remaining 2 sites are static JSON: +- `python/project.json` — `nx:run-commands` executor needs a literal command string +- `angular/project.json` — Angular serve target needs literal `serve.options.port` + +For these, keep the literals and add a CI verifier that asserts they match the registry. New caps follow the same convention; the verifier catches mistakes at PR time. + +## Architecture + +``` +cockpit/ports.mjs (NEW — single source of truth, 31 caps) + │ + ├── imported by 31 × cockpit///angular/proxy.conf.mjs (NEW; replaces .json) + ├── imported by 24 × cockpit///angular/e2e/global-setup-impl.ts (MODIFIED) + │ + └── verified-against: + — 31 × cockpit///python/project.json `--port ` literal + — 31 × cockpit///angular/project.json `serve.options.port` literal + via scripts/cockpit-ports.spec.mjs (NEW) +``` + +**Exclusion:** `cockpit/ag-ui/streaming` is NOT in the registry. It uses a non-LangGraph backend (Node ag-ui server on port 3000) with a `/agent` proxy path rather than `/api`. Single-cap exception; not worth generalizing. + +## Components + +### 1. `cockpit/ports.mjs` (NEW) + +```js +// SPDX-License-Identifier: MIT + +/** + * @typedef {{ angular: number; langgraph: number }} CapPorts + * @typedef {Record} PortsRegistry + */ + +/** + * Single source of truth for cockpit cap port allocation. + * + * Excludes cockpit-ag-ui-streaming-angular — uses a non-LangGraph + * backend (Node ag-ui server on :3000, /agent proxy). Single-cap + * exception; left as a literal in its own files. + * + * Port ranges: + * - angular: [4000, 5000) + * - langgraph: [5000, 6000) + * - Convention: langgraph = angular + 1000 + * + * The CI verifier (scripts/cockpit-ports.spec.mjs) asserts this + * registry matches the literal --port values in each cap's + * python/project.json + angular/project.json. + * + * @type {PortsRegistry} + */ +export const PORTS = Object.freeze({ + // 31 entries here, alphabetical by cap name +}); + +/** + * Look up ports for a cap by its Nx angular project name. + * Throws if the name isn't in the registry — caller crash for + * fast diagnosis. + * + * @param {string} cap + * @returns {CapPorts} + */ +export function portsFor(cap) { + const p = PORTS[cap]; + if (!p) throw new Error(`No port allocation for ${cap}`); + return p; +} +``` + +### 2. `cockpit///angular/proxy.conf.mjs` (NEW, replaces `.json`, ×31) + +Each cap's proxy config becomes: + +```js +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-messages-angular'); + +export default { + '/api': { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + }, +}; +``` + +The cap's `angular/project.json` `serve.proxyConfig` field is updated from `proxy.conf.json` → `proxy.conf.mjs`. Both file extensions are valid for Angular's dev-server. + +### 3. `cockpit///angular/e2e/global-setup-impl.ts` (MODIFIED, ×24 active e2e caps only) + +Each global-setup-impl.ts replaces literal port values with imports: + +```ts +import { resolve } from 'node:path'; +import { createGlobalSetup } from '@ngaf-internal/e2e-harness'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const ports = portsFor('cockpit-chat-messages-angular'); + +export default createGlobalSetup({ + langgraphCwd: 'cockpit/chat/messages/python', + langgraphPort: ports.langgraph, + angularProject: 'cockpit-chat-messages-angular', + angularPort: ports.angular, + fixturesDir: resolve(__dirname, 'fixtures'), +}); +``` + +The 7 caps without e2e (6 render + c-debug) are NOT touched here — they have no `e2e/global-setup-impl.ts`. + +### 4. `cockpit///python/project.json` + `cockpit///angular/project.json` (UNCHANGED literals, ×31 each) + +Keep `--port 5501` and `"port": 4501` as literals. Static JSON can't import from .mjs without restructuring the Nx executor schema (out of scope per the brainstorm constraints). + +### 5. `scripts/cockpit-ports.spec.mjs` (NEW) + +`node:test` + `node:assert/strict` suite. 6 tests: + +1. **Registry covers all on-disk LangGraph caps** — walk all `cockpit///angular/project.json` files; for each project name except `cockpit-ag-ui-streaming-angular`, assert it appears as a key in `PORTS`. +2. **No orphan registry entries** — every key in `PORTS` has a matching `cockpit///angular/project.json` on disk. +3. **python `--port ` matches `PORTS[name].langgraph`** — for each registry entry, find the cap's python sibling, parse its `serve.options.command` field with regex `--port[ =](\d+)`, assert match. +4. **angular `serve.options.port` matches `PORTS[name].angular`** — parse each cap's `angular/project.json`, assert `targets.serve.options.port === PORTS[name].angular`. +5. **No duplicate ports** — each `angular` and `langgraph` value appears once across all entries. +6. **Port ranges sane** — angular ∈ [4000, 5000), langgraph ∈ [5000, 6000), langgraph === angular + 1000. + +### 6. `.github/workflows/ci.yml` (MODIFIED, 1-line change) + +The existing `ci-scope` job already runs: + +```yaml +- name: Test CI scope classifier + run: node --test scripts/ci-scope.spec.mjs scripts/cockpit-matrix.spec.mjs +``` + +Append the new spec: + +```yaml +- name: Test CI scope classifier + run: node --test scripts/ci-scope.spec.mjs scripts/cockpit-matrix.spec.mjs scripts/cockpit-ports.spec.mjs +``` + +## Data flow per scenario + +| Trigger | What happens | +|---|---| +| `nx serve -angular` | Angular dev-server loads `proxy.conf.mjs` → imports `portsFor(cap)` → returns config with target port. Angular binds on the literal port from its own `project.json`. | +| `nx serve -python` | `nx:run-commands` invokes the literal `uv run langgraph dev --port `. No registry read at runtime. Verifier ensures N matches the registry. | +| `nx e2e -angular` | Playwright loads `e2e/global-setup-impl.ts` → imports `portsFor(cap)` → passes to `createGlobalSetup`. e2e-harness spawns Angular + LangGraph on those ports. | +| New cap added | 1 line in `cockpit/ports.mjs`, scaffold the 4 files (proxy.conf.mjs + global-setup-impl.ts import by name; project.jsons get literals matching the registry). Verifier asserts on PR. | +| Existing port reassigned | Edit the registry. Edit 2 literal project.json values. Run `node --test scripts/cockpit-ports.spec.mjs` locally; CI also asserts. | + +## Error handling + +- `portsFor('')` throws — fast crash for diagnosis. +- Verifier fails CI with specific mismatched cap + expected vs actual port. +- Registry is `Object.freeze`'d to prevent accidental mutation by importers. + +## Out of scope + +- Generator script for new caps (verifier catches mistakes today; can add scaffolder later). +- Port range rebalancing — existing assignments preserved verbatim. +- Runtime port-conflict resolution (e.g. dev machine has 5501 in use). +- ag-ui migration — excluded by design; one-line allowlist in the verifier. +- Angular `serve.options.port` being read from the registry — kept literal, verified. + +## Risks + +- **Angular dev-server `.mjs` support**: well-documented and stable since Angular 17+. Repo uses Angular 22. No risk. +- **Static analyzers / IDEs**: some tooling may not understand `.mjs` imports across the Nx workspace. Mitigated: project.json target paths use the new `.mjs` extension explicitly. +- **Drift between the 5th `e2e/global-setup-impl.ts` arg `langgraphCwd` and the python project location**: existing convention `cockpit///python`. Not part of this design — out of scope; covered by `cockpit-e2e-wiring.spec.ts` drift-guard. + +## Test plan (post-merge validation) + +1. `nx serve cockpit-chat-messages-angular` — Angular boots, proxy works against running langgraph. +2. `nx e2e cockpit-chat-messages-angular` — full e2e runs against same ports as before. +3. CI green on the migration PR with all 24 cockpit-e2e shards. +4. Intentionally edit `cockpit/chat/messages/python/project.json` to mismatch the registry — verifier should fail with a clear diagnostic. Revert. + +## References + +- Audit: `2026-05-25` repo health audit (in-session research, not committed). +- Existing pattern: `scripts/ci-scope.mjs` (pure classifier + spec test wired into CI). +- Angular proxy.conf documentation: supports `.json`, `.js`, `.mjs`, `.cjs`. From a65081abb1412f4b64661084a7715d72d793cda7 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Wed, 27 May 2026 14:12:36 -0700 Subject: [PATCH 2/9] docs(plan): cockpit port registry implementation plan --- .../plans/2026-05-27-cockpit-port-registry.md | 725 ++++++++++++++++++ 1 file changed, 725 insertions(+) create mode 100644 docs/superpowers/plans/2026-05-27-cockpit-port-registry.md diff --git a/docs/superpowers/plans/2026-05-27-cockpit-port-registry.md b/docs/superpowers/plans/2026-05-27-cockpit-port-registry.md new file mode 100644 index 00000000..d1fc35ca --- /dev/null +++ b/docs/superpowers/plans/2026-05-27-cockpit-port-registry.md @@ -0,0 +1,725 @@ +# Cockpit Port Registry Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Centralize cockpit cap port allocation behind a `cockpit/ports.mjs` registry that proxy configs + e2e setup files import at runtime, plus a CI verifier that asserts python project.json `--port` literals match the registry. + +**Architecture:** Single ESM module exports a frozen `PORTS` map keyed by cap angular project name. 31 × `proxy.conf.mjs` (replacing `.json`) and 24 × `e2e/global-setup-impl.ts` + 24 × `e2e/playwright.config.ts` import from it. The 31 × `python/project.json` `--port` literals stay as-is and are verified by `scripts/cockpit-ports.spec.mjs` in CI. `cockpit/ag-ui/streaming` is excluded by design (non-LangGraph backend). + +**Tech Stack:** Node.js ESM (.mjs), `node:test` + `node:assert/strict`, Angular dev-server `proxyConfig` (`.mjs` support), Playwright config, Nx `nx:run-commands` executor. + +**Spec correction**: there is no `port` in angular `project.json`. The Angular port for e2e is set via `nx serve --port` override (passed by the e2e harness from `global-setup-impl.ts`) AND duplicated in `e2e/playwright.config.ts` `baseURL`. Spec's verifier test #4 ("angular project.json `serve.options.port`") is replaced with verifying `playwright.config.ts` baseURL. + +--- + +### Task 1: Verifier spec (TDD) + minimal registry + +**Files:** +- Create: `scripts/cockpit-ports.spec.mjs` +- Create: `cockpit/ports.mjs` (minimal — empty PORTS object so tests can run) + +- [ ] **Step 1: Write the failing tests** + +Create `scripts/cockpit-ports.spec.mjs`: + +```js +import { test, describe } from 'node:test'; +import assert from 'node:assert/strict'; +import { readdirSync, readFileSync, existsSync } from 'node:fs'; +import { dirname, join, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { PORTS } from '../cockpit/ports.mjs'; + +const repoRoot = resolve(fileURLToPath(import.meta.url), '..', '..'); +const cockpitDir = join(repoRoot, 'cockpit'); + +const AGUI_EXCEPTION = 'cockpit-ag-ui-streaming-angular'; + +function findCockpitAngularProjects() { + // Walk cockpit/ for project.json files inside angular/ dirs. + const out = []; + function walk(dir) { + let entries; + try { entries = readdirSync(dir); } catch { return; } + for (const name of entries) { + const full = join(dir, name); + if (name === 'node_modules' || name.startsWith('.')) continue; + let stat; + try { stat = readFileSync(join(full, 'project.json'), 'utf8'); } + catch { walk(full); continue; } + try { + const meta = JSON.parse(stat); + if (typeof meta.name === 'string' && meta.name.endsWith('-angular') && meta.name.startsWith('cockpit-')) { + out.push({ name: meta.name, dir: full, meta }); + } + } catch {} + walk(full); + } + } + walk(cockpitDir); + return out; +} + +const projects = findCockpitAngularProjects(); + +describe('cockpit/ports.mjs registry', () => { + test('covers every cockpit-*-angular project on disk except ag-ui', () => { + const onDisk = projects.map((p) => p.name).filter((n) => n !== AGUI_EXCEPTION); + const missing = onDisk.filter((n) => !(n in PORTS)); + assert.deepEqual(missing, [], `missing from PORTS: ${missing.join(', ')}`); + }); + + test('has no orphan entries (each PORTS key has a project on disk)', () => { + const diskNames = new Set(projects.map((p) => p.name)); + const orphans = Object.keys(PORTS).filter((n) => !diskNames.has(n)); + assert.deepEqual(orphans, [], `orphan PORTS entries: ${orphans.join(', ')}`); + }); + + test('ag-ui is NOT in the registry (exception)', () => { + assert.equal(AGUI_EXCEPTION in PORTS, false); + }); + + test('every entry has angular + langgraph as positive integers', () => { + for (const [name, p] of Object.entries(PORTS)) { + assert.equal(typeof p.angular, 'number', `${name}.angular not number`); + assert.equal(typeof p.langgraph, 'number', `${name}.langgraph not number`); + assert.ok(p.angular > 0 && p.langgraph > 0, `${name} has non-positive port`); + } + }); + + test('port ranges: angular ∈ [4000, 5000), langgraph ∈ [5000, 6000), langgraph = angular + 1000', () => { + for (const [name, p] of Object.entries(PORTS)) { + assert.ok(p.angular >= 4000 && p.angular < 5000, `${name}.angular out of range: ${p.angular}`); + assert.ok(p.langgraph >= 5000 && p.langgraph < 6000, `${name}.langgraph out of range: ${p.langgraph}`); + assert.equal(p.langgraph, p.angular + 1000, `${name}: langgraph (${p.langgraph}) != angular (${p.angular}) + 1000`); + } + }); + + test('no duplicate ports', () => { + const seen = new Set(); + for (const [name, p] of Object.entries(PORTS)) { + for (const port of [p.angular, p.langgraph]) { + assert.ok(!seen.has(port), `duplicate port ${port} (${name})`); + seen.add(port); + } + } + }); + + test('each cap python/project.json --port matches PORTS[name].langgraph', () => { + const mismatches = []; + for (const { name, dir } of projects) { + if (name === AGUI_EXCEPTION) continue; + const pyProjectJson = join(dir, '..', 'python', 'project.json'); + if (!existsSync(pyProjectJson)) { + mismatches.push(`${name}: missing python/project.json at ${pyProjectJson}`); + continue; + } + const meta = JSON.parse(readFileSync(pyProjectJson, 'utf8')); + const cmd = String(meta?.targets?.serve?.options?.command ?? ''); + const m = cmd.match(/--port[= ](\d+)/); + if (!m) { + mismatches.push(`${name}: no --port in python/project.json serve command`); + continue; + } + const literal = Number(m[1]); + const expected = PORTS[name]?.langgraph; + if (literal !== expected) { + mismatches.push(`${name}: python --port ${literal} != registry ${expected}`); + } + } + assert.deepEqual(mismatches, []); + }); + + test('each active-e2e cap playwright.config.ts baseURL port matches PORTS[name].angular', () => { + const mismatches = []; + for (const { name, dir } of projects) { + if (name === AGUI_EXCEPTION) continue; + const pwConfig = join(dir, 'e2e', 'playwright.config.ts'); + if (!existsSync(pwConfig)) continue; // 7 caps without e2e are fine + const text = readFileSync(pwConfig, 'utf8'); + const m = text.match(/baseURL:\s*[`'"]http:\/\/localhost:(\d+)[`'"/]/); + if (!m) continue; // skip if no literal baseURL (might use import already) + const literal = Number(m[1]); + const expected = PORTS[name]?.angular; + if (literal !== expected) { + mismatches.push(`${name}: playwright baseURL :${literal} != registry :${expected}`); + } + } + assert.deepEqual(mismatches, []); + }); +}); +``` + +- [ ] **Step 2: Create minimal registry (will fail tests intentionally)** + +Create `cockpit/ports.mjs`: + +```js +// SPDX-License-Identifier: MIT + +/** + * @typedef {{ angular: number; langgraph: number }} CapPorts + * @typedef {Record} PortsRegistry + */ + +/** + * Single source of truth for cockpit cap port allocation. + * + * Excludes cockpit-ag-ui-streaming-angular — uses a non-LangGraph + * backend (Node ag-ui server on :3000, /agent proxy). Single-cap + * exception; left as a literal in its own files. + * + * Port ranges: + * - angular: [4000, 5000) + * - langgraph: [5000, 6000) + * - Convention: langgraph = angular + 1000 + * + * The CI verifier (scripts/cockpit-ports.spec.mjs) asserts this + * registry matches the literal --port values in each cap's + * python/project.json + baseURL in playwright.config.ts. + * + * @type {PortsRegistry} + */ +export const PORTS = Object.freeze({}); + +/** + * Look up ports for a cap by its Nx angular project name. + * Throws if the name isn't in the registry — caller crash for + * fast diagnosis. + * + * @param {string} cap + * @returns {CapPorts} + */ +export function portsFor(cap) { + const p = PORTS[cap]; + if (!p) throw new Error(`No port allocation for ${cap}`); + return p; +} +``` + +- [ ] **Step 3: Run tests, verify the "covers every cap" test fails** + +Run: `node --test scripts/cockpit-ports.spec.mjs` + +Expected: at least the first test ("covers every cockpit-*-angular project") fails with a list of missing entries (31 names). Other tests may pass vacuously on the empty registry. + +- [ ] **Step 4: Commit** + +```bash +git add scripts/cockpit-ports.spec.mjs cockpit/ports.mjs +git commit -m "feat(ci): cockpit ports registry + verifier spec (skeleton) + +Registry starts empty; the verifier spec tests both the registry +shape (positive int ports, no duplicates, range/convention checks) +and cross-file invariants (python --port + playwright baseURL match +registry). Empty registry intentionally fails the 'covers every +cap' test until Task 2 populates it. + +Spec: docs/superpowers/specs/2026-05-27-cockpit-port-registry-design.md" +``` + +--- + +### Task 2: Populate the registry from existing on-disk ports + +**Files:** +- Modify: `cockpit/ports.mjs` + +- [ ] **Step 1: Extract existing port assignments** + +Run this helper from the worktree root to enumerate the existing port pairs: + +```bash +node - <<'EOF' +import { readdirSync, readFileSync, existsSync } from 'node:fs'; +import { join } from 'node:path'; +const ROOT = 'cockpit'; +const out = {}; +function walk(d) { + let entries; try { entries = readdirSync(d); } catch { return; } + for (const n of entries) { + if (n === 'node_modules' || n.startsWith('.')) continue; + const f = `${d}/${n}`; + if (n === 'angular') { + const pj = `${f}/project.json`; + if (!existsSync(pj)) continue; + const meta = JSON.parse(readFileSync(pj, 'utf8')); + if (typeof meta.name !== 'string' || !meta.name.endsWith('-angular')) continue; + if (meta.name === 'cockpit-ag-ui-streaming-angular') continue; + // langgraph port from proxy.conf.json target + const proxyJson = `${f}/proxy.conf.json`; + let langgraph = null; + if (existsSync(proxyJson)) { + const proxy = JSON.parse(readFileSync(proxyJson, 'utf8')); + for (const v of Object.values(proxy)) { + const m = String(v.target ?? '').match(/localhost:(\d+)/); + if (m) { langgraph = Number(m[1]); break; } + } + } + // angular port from playwright.config.ts baseURL (if e2e exists) + let angular = null; + const pw = `${f}/e2e/playwright.config.ts`; + if (existsSync(pw)) { + const m = readFileSync(pw, 'utf8').match(/baseURL:\s*[`'"]http:\/\/localhost:(\d+)/); + if (m) angular = Number(m[1]); + } + // fall back to langgraph - 1000 for non-e2e caps + if (angular === null && langgraph !== null) angular = langgraph - 1000; + out[meta.name] = { angular, langgraph }; + continue; + } + walk(f); + } +} +walk(ROOT); +const sorted = Object.keys(out).sort().reduce((acc, k) => (acc[k] = out[k], acc), {}); +for (const [k, v] of Object.entries(sorted)) { + console.log(` '${k}': { angular: ${v.angular}, langgraph: ${v.langgraph} },`); +} +EOF +``` + +Expected: 31 lines printed (every LangGraph cockpit angular project except ag-ui), each with both ports. + +Save the output for Step 2. + +- [ ] **Step 2: Paste the entries into `cockpit/ports.mjs`** + +Replace `export const PORTS = Object.freeze({});` with `export const PORTS = Object.freeze({ ... });` populated from Step 1's output. The 31 entries go inside the braces, alphabetically by key (the helper already sorts). + +- [ ] **Step 3: Run tests, verify shape tests pass** + +Run: `node --test scripts/cockpit-ports.spec.mjs` + +Expected: tests "covers every cap", "no orphan entries", "ag-ui not in registry", "positive integers", "port ranges", "no duplicates" all PASS. The two cross-file verifier tests (python `--port`, playwright `baseURL`) also PASS because we populated FROM those existing values. + +If a port-range or convention test fails: one or more existing port assignments don't follow the `angular + 1000 = langgraph` convention. Surface the cap, decide whether to: +- Update the existing literal to match the convention (preferred — fix drift) +- OR widen the test's tolerance (only if intentional) + +- [ ] **Step 4: Commit** + +```bash +git add cockpit/ports.mjs +git commit -m "feat(ci): populate cockpit ports registry from on-disk values + +31 entries, extracted from each cap's proxy.conf.json target + +playwright.config.ts baseURL (or langgraph - 1000 for non-e2e caps). +Verifier confirms the registry round-trips cleanly against every +python/project.json --port literal." +``` + +--- + +### Task 3: Sweep proxy.conf.json → proxy.conf.mjs (×31) + +**Files:** +- For each of 31 caps: + - Create: `cockpit///angular/proxy.conf.mjs` + - Delete: `cockpit///angular/proxy.conf.json` + - Modify: `cockpit///angular/project.json` (`serve.options.proxyConfig` extension) + +- [ ] **Step 1: Write a sweep script (does NOT commit; just runs)** + +Create `/tmp/sweep-proxy.mjs` (not committed; throwaway): + +```js +import { readdirSync, readFileSync, writeFileSync, existsSync, unlinkSync } from 'node:fs'; +import { dirname, join, relative } from 'node:path'; + +const ROOT = process.cwd(); +const COCKPIT = `${ROOT}/cockpit`; + +// List of (capName, angularDir, langgraphPort) tuples +const caps = []; +function walk(d) { + for (const n of readdirSync(d)) { + if (n === 'node_modules' || n.startsWith('.')) continue; + const f = `${d}/${n}`; + if (n === 'angular') { + const pj = `${f}/project.json`; + if (!existsSync(pj)) continue; + const meta = JSON.parse(readFileSync(pj, 'utf8')); + if (typeof meta.name !== 'string' || !meta.name.endsWith('-angular')) continue; + if (meta.name === 'cockpit-ag-ui-streaming-angular') continue; + caps.push({ name: meta.name, dir: f }); + continue; + } + let stat; try { stat = readFileSync(`${f}/project.json`); } catch { walk(f); continue; } + walk(f); + } +} +walk(COCKPIT); + +for (const cap of caps) { + const proxyJson = `${cap.dir}/proxy.conf.json`; + const proxyMjs = `${cap.dir}/proxy.conf.mjs`; + if (!existsSync(proxyJson)) { + console.error(`SKIP ${cap.name}: no proxy.conf.json`); + continue; + } + const old = JSON.parse(readFileSync(proxyJson, 'utf8')); + // Compute relative import path from /angular/ to cockpit/ports.mjs. + // /angular/ is 4 levels deep relative to repo root (cockpit///angular/). + // From there, ../../../../cockpit/ports.mjs would resolve. + // But cockpit/render//angular is also 4 deep. Same for chat, deep-agents, langgraph. + // So we always need ../../../../cockpit/ports.mjs (4 ups). + const relImport = '../../../../cockpit/ports.mjs'; + + // Build new .mjs content. Preserve the route key + secure/changeOrigin opts. + const routes = Object.entries(old).map(([route, conf]) => { + const target = `\`http://localhost:\${langgraph}\``; + const otherOpts = Object.entries(conf) + .filter(([k]) => k !== 'target') + .map(([k, v]) => ` ${k}: ${JSON.stringify(v)},`) + .join('\n'); + return ` ${JSON.stringify(route)}: { + target: ${target}, +${otherOpts} + }`; + }).join(',\n'); + + const content = `// SPDX-License-Identifier: MIT +import { portsFor } from '${relImport}'; + +const { langgraph } = portsFor('${cap.name}'); + +export default { +${routes}, +}; +`; + writeFileSync(proxyMjs, content); + unlinkSync(proxyJson); + console.log(`OK ${cap.name}`); + + // Also update project.json's proxyConfig extension. + const angularProjectJson = `${cap.dir}/project.json`; + const meta = JSON.parse(readFileSync(angularProjectJson, 'utf8')); + const opts = meta.targets?.serve?.options; + if (opts?.proxyConfig?.endsWith('proxy.conf.json')) { + opts.proxyConfig = opts.proxyConfig.replace(/\.json$/, '.mjs'); + writeFileSync(angularProjectJson, JSON.stringify(meta, null, 2) + '\n'); + } +} +console.log(`Total: ${caps.length} caps swept`); +``` + +Run: `node /tmp/sweep-proxy.mjs` + +Expected: "OK " for 31 caps, "Total: 31 caps swept". + +- [ ] **Step 2: Spot-check the result** + +Run: +```bash +cat cockpit/chat/messages/angular/proxy.conf.mjs +ls cockpit/chat/messages/angular/proxy.conf.json && echo "STILL EXISTS — BUG" || echo "deleted OK" +grep proxyConfig cockpit/chat/messages/angular/project.json +``` + +Expected: +- `proxy.conf.mjs` exists, imports from `'../../../../cockpit/ports.mjs'`, exports a default object with `/api → http://localhost:${langgraph}` +- `proxy.conf.json` is deleted +- `project.json` has `"proxyConfig": "cockpit/chat/messages/angular/proxy.conf.mjs"` + +If the spot-check fails on any cap, run the sweep again after fixing the script — it's idempotent enough (creates `.mjs`, deletes `.json`). + +- [ ] **Step 3: Verify the registry tests still pass** + +Run: `node --test scripts/cockpit-ports.spec.mjs` + +Expected: all tests still pass. The verifier doesn't yet check proxy.conf.mjs content (that's behavioral, not literal-port drift), so the sweep is a no-op from its perspective. + +- [ ] **Step 4: Smoke-test one cap dev server** + +Run: `npx nx serve cockpit-chat-messages-angular --port 9999 &` then `curl -s http://localhost:9999/ -o /dev/null -w '%{http_code}'` + +Expected: `200`. Angular dev-server loads `proxy.conf.mjs` without error. Kill the server: `pkill -f 'cockpit-chat-messages-angular'`. + +If Angular complains about `.mjs` proxy config: check Angular version. The repo uses Angular 22+, which natively supports `.mjs` proxy configs. If older, fall back to `.cjs`. + +- [ ] **Step 5: Commit** + +```bash +git add cockpit/ +git commit -m "refactor(cockpit): 31 proxy.conf.json → proxy.conf.mjs (import ports registry) + +Every cockpit cap's proxy.conf.json is replaced with proxy.conf.mjs +that imports portsFor(capName) from cockpit/ports.mjs and templates +the langgraph port into the target URL. Each angular/project.json's +serve.options.proxyConfig is updated to point at the .mjs file. + +cockpit/ag-ui/streaming is excluded — non-LangGraph backend, kept +as proxy.conf.json with its /agent → :3000 literal." +``` + +--- + +### Task 4: Sweep `e2e/global-setup-impl.ts` + `e2e/playwright.config.ts` (×24) + +**Files:** +- For each of the 24 active e2e caps: + - Modify: `cockpit///angular/e2e/global-setup-impl.ts` + - Modify: `cockpit///angular/e2e/playwright.config.ts` + +- [ ] **Step 1: Write a sweep script** + +Create `/tmp/sweep-e2e.mjs`: + +```js +import { readdirSync, readFileSync, writeFileSync, existsSync } from 'node:fs'; + +const ROOT = process.cwd(); +const COCKPIT = `${ROOT}/cockpit`; + +const caps = []; +function walk(d) { + for (const n of readdirSync(d)) { + if (n === 'node_modules' || n.startsWith('.')) continue; + const f = `${d}/${n}`; + if (n === 'angular') { + const pj = `${f}/project.json`; + if (!existsSync(pj)) continue; + const meta = JSON.parse(readFileSync(pj, 'utf8')); + if (typeof meta.name !== 'string' || !meta.name.endsWith('-angular')) continue; + if (meta.name === 'cockpit-ag-ui-streaming-angular') continue; + const setup = `${f}/e2e/global-setup-impl.ts`; + const pwCfg = `${f}/e2e/playwright.config.ts`; + if (existsSync(setup) && existsSync(pwCfg)) caps.push({ name: meta.name, dir: f }); + continue; + } + let stat; try { stat = readFileSync(`${f}/project.json`); } catch { walk(f); continue; } + walk(f); + } +} +walk(COCKPIT); + +// Relative import from /angular/e2e/ to cockpit/ports.mjs: +// e2e is 5 deep (cockpit///angular/e2e/), so 5 ups. +const REL_IMPORT = '../../../../../cockpit/ports.mjs'; + +for (const cap of caps) { + // global-setup-impl.ts: insert import + portsFor() lookup; replace literal port lines. + const setupPath = `${cap.dir}/e2e/global-setup-impl.ts`; + let setup = readFileSync(setupPath, 'utf8'); + if (!setup.includes('cockpit/ports.mjs')) { + const importLine = `import { portsFor } from '${REL_IMPORT}';`; + // Insert the import after the first existing import line. + setup = setup.replace( + /(^import [^\n]+;\n)/, + `$1${importLine}\n`, + ); + // Insert `const ports = portsFor(...)` immediately before the default export. + setup = setup.replace( + /(export default createGlobalSetup\(\{)/, + `const ports = portsFor('${cap.name}');\n\n$1`, + ); + // Replace the two literal port lines with registry references. + setup = setup.replace(/langgraphPort:\s*\d+,/, 'langgraphPort: ports.langgraph,'); + setup = setup.replace(/angularPort:\s*\d+,/, 'angularPort: ports.angular,'); + writeFileSync(setupPath, setup); + } + + // playwright.config.ts: replace baseURL literal port. + const pwCfgPath = `${cap.dir}/e2e/playwright.config.ts`; + let pwCfg = readFileSync(pwCfgPath, 'utf8'); + if (!pwCfg.includes('cockpit/ports.mjs')) { + const importLine = `import { portsFor } from '${REL_IMPORT}';`; + pwCfg = pwCfg.replace( + /(^import [^\n]+;\n)/, + `$1${importLine}\n`, + ); + // Insert const decl near the top of the config (after imports). + pwCfg = pwCfg.replace( + /(\nexport default )/, + `\nconst { angular: angularPort } = portsFor('${cap.name}');\n\n$1`, + ); + // Replace literal baseURL port. + pwCfg = pwCfg.replace( + /baseURL:\s*[`'"]http:\/\/localhost:\d+[`'"/]/, + 'baseURL: `http://localhost:${angularPort}`', + ); + writeFileSync(pwCfgPath, pwCfg); + } + + console.log(`OK ${cap.name}`); +} +console.log(`Total: ${caps.length} caps swept`); +``` + +Run: `node /tmp/sweep-e2e.mjs` + +Expected: "OK " for 24 caps. + +- [ ] **Step 2: Spot-check the result** + +```bash +head -20 cockpit/chat/messages/angular/e2e/global-setup-impl.ts +head -20 cockpit/chat/messages/angular/e2e/playwright.config.ts +``` + +Expected: +- `global-setup-impl.ts` starts with the original imports plus `import { portsFor } from '...';`, has a `const ports = portsFor('cockpit-chat-messages-angular');` line, and the two `*Port:` keys reference `ports.angular` / `ports.langgraph`. +- `playwright.config.ts` has the new import + `const { angular: angularPort } = portsFor('...');`, and `baseURL: \`http://localhost:${angularPort}\``. + +If any cap looks broken, manually fix it; the sweep is best-effort textual. + +- [ ] **Step 3: TypeScript compile sanity-check** + +Run one cap's e2e tsconfig: +```bash +cd cockpit/chat/messages/angular/e2e && npx tsc --noEmit && cd $OLDPWD +``` + +Expected: clean. If `portsFor` returns `unknown` or there's a path resolution error, the tsconfig's `paths`/`baseUrl` may need an additional entry. Check what alias `@ngaf-internal/e2e-harness` resolves to (from PR #515) and follow the same pattern. + +- [ ] **Step 4: Run the verifier** + +Run: `node --test scripts/cockpit-ports.spec.mjs` + +Expected: all tests still pass. The "playwright baseURL" verifier regex matches the templated form too because the regex only kicks in when the baseURL is a literal localhost URL; templates use `${angularPort}` and are skipped (no false positives). + +Wait — the verifier regex IS `match(/baseURL:\s*[`'"]http:\/\/localhost:(\d+)[`'"/]/)`. With the new templated form `baseURL: \`http://localhost:${angularPort}\``, the regex won't match (no digit between `:` and the closing backtick). The test then skips the cap. **The test no longer verifies post-sweep playwright config**, but that's fine: the value is now imported from the registry directly, so drift is impossible. + +- [ ] **Step 5: Commit** + +```bash +git add cockpit/ +git commit -m "refactor(cockpit): 24 e2e configs import ports from registry + +Each cap's e2e/global-setup-impl.ts now imports portsFor() and reads +angular/langgraph ports from the registry instead of literal numbers. +playwright.config.ts is updated similarly for baseURL. + +The verifier's playwright-baseURL check now skips templated configs +(its regex only matches literal URLs); drift is impossible because +the value imports directly from the registry." +``` + +--- + +### Task 5: Wire spec into ci.yml + +**Files:** +- Modify: `.github/workflows/ci.yml` + +- [ ] **Step 1: Find the existing test line** + +Run: `grep -n "ci-scope.spec.mjs" .github/workflows/ci.yml` + +Expected: one match, currently reading: +```yaml + - name: Test CI scope classifier + run: node --test scripts/ci-scope.spec.mjs scripts/cockpit-matrix.spec.mjs +``` + +- [ ] **Step 2: Append the new spec** + +Edit that line to: +```yaml + - name: Test CI scope classifier + run: node --test scripts/ci-scope.spec.mjs scripts/cockpit-matrix.spec.mjs scripts/cockpit-ports.spec.mjs +``` + +- [ ] **Step 3: YAML lint** + +Run: `python3 -c "import yaml; yaml.safe_load(open('.github/workflows/ci.yml'))"` + +Expected: no output, exit 0. + +- [ ] **Step 4: Run the combined test suite locally** + +Run: `node --test scripts/ci-scope.spec.mjs scripts/cockpit-matrix.spec.mjs scripts/cockpit-ports.spec.mjs` + +Expected: all tests across all three files pass (15 ci-scope + 7 cockpit-matrix + 7 cockpit-ports = 29 tests). + +- [ ] **Step 5: Commit** + +```bash +git add .github/workflows/ci.yml +git commit -m "ci: gate cockpit-ports.spec.mjs in ci-scope test job + +Appends the new verifier spec to the existing node --test invocation +so registry drift is caught at PR time." +``` + +--- + +### Task 6: Push, open PR, monitor first CI run + +**Files:** none modified. + +- [ ] **Step 1: Push branch** + +```bash +git push -u origin claude/cockpit-ports +``` + +- [ ] **Step 2: Open PR** + +```bash +gh pr create --title "feat(cockpit): centralize port allocation behind cockpit/ports.mjs registry" --body "$(cat <<'EOF' +## Summary + +Centralizes cockpit cap port allocation. 31 LangGraph caps now import ports from \`cockpit/ports.mjs\`; the 4-place per-cap edit reduces to 1 line in the registry (+ literal verification on PR). + +### Touched +- **NEW** \`cockpit/ports.mjs\` — registry (31 entries, ag-ui excluded by design) +- **NEW** \`scripts/cockpit-ports.spec.mjs\` — verifier (7 tests, wired into ci-scope job) +- **REFACTOR** 31 × \`cockpit///angular/proxy.conf.json\` → \`proxy.conf.mjs\` (imports registry) +- **MODIFY** 31 × \`cockpit///angular/project.json\` — \`proxyConfig\` extension \`.json → .mjs\` +- **MODIFY** 24 × \`cockpit///angular/e2e/global-setup-impl.ts\` — import registry +- **MODIFY** 24 × \`cockpit///angular/e2e/playwright.config.ts\` — \`baseURL\` from registry +- **UNCHANGED** 31 × \`cockpit///python/project.json\` — literal \`--port\`, verified + +### Excluded +\`cockpit/ag-ui/streaming\` — non-LangGraph backend (Node ag-ui on :3000 with /agent path). Kept as literals; one-line allowlist in the verifier. + +## Test plan + +- [x] 7/7 cockpit-ports spec tests pass locally +- [x] Combined \`node --test\` of all 3 specs (29 tests) green +- [x] One cap dev server smoke (proxy.conf.mjs loads) +- [ ] CI: all 24 cockpit-e2e shards green +- [ ] CI: ci-scope job runs the new spec + +Spec: \`docs/superpowers/specs/2026-05-27-cockpit-port-registry-design.md\` +Plan: \`docs/superpowers/plans/2026-05-27-cockpit-port-registry.md\` + +🤖 Generated with [Claude Code](https://claude.com/claude-code) +EOF +)" +``` + +- [ ] **Step 3: Monitor** + +```bash +gh pr checks $(gh pr view --json number --jq .number) +``` + +Expected: 24 cockpit-e2e shards + summary green. If any cap fails to boot, suspect: +- proxy.conf.mjs path resolution: the cap's `project.json` `proxyConfig` field still points at `.json` (sweep missed it) +- portsFor() throws because registry name doesn't match: typo in PORTS key or in the cap's project.json `name` +- ESM resolution: Node version too old (workflow uses Node 22, fine) + +- [ ] **Step 4: Hand off to user** + +Plan ends here. User decides when to admin-merge. + +--- + +## Verification checklist (entire plan) + +After all tasks: + +- ✅ `cockpit/ports.mjs` exports `PORTS` (31 entries, frozen) + `portsFor(name)` +- ✅ `cockpit/ag-ui/streaming-angular` NOT in `PORTS`; its files unchanged +- ✅ Every cap's `proxy.conf.mjs` imports + templates langgraph port +- ✅ Every cap's `angular/project.json` `proxyConfig` ends in `.mjs` +- ✅ 24 × `global-setup-impl.ts` import registry; no literal port digits remain +- ✅ 24 × `playwright.config.ts` baseURL uses `${angularPort}` template +- ✅ All `python/project.json` `--port` literals match registry +- ✅ `scripts/cockpit-ports.spec.mjs` gates PRs via ci-scope job +- ✅ All 24 cockpit-e2e shards green on the PR + +If any item is unchecked, return to the task that owns it before requesting review. From 63ec2f0b1172bf7207b17a1354ff1095edc71b29 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Wed, 27 May 2026 14:17:28 -0700 Subject: [PATCH 3/9] feat(ci): cockpit ports registry + verifier spec (skeleton) Registry starts empty; the verifier spec tests both the registry shape (positive int ports, no duplicates, range/convention checks) and cross-file invariants (python --port + playwright baseURL match registry). Empty registry intentionally fails the 'covers every cap' test until Task 2 populates it. Spec: docs/superpowers/specs/2026-05-27-cockpit-port-registry-design.md --- cockpit/ports.mjs | 40 +++++++++++ scripts/cockpit-ports.spec.mjs | 124 +++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 cockpit/ports.mjs create mode 100644 scripts/cockpit-ports.spec.mjs diff --git a/cockpit/ports.mjs b/cockpit/ports.mjs new file mode 100644 index 00000000..bf80e8c3 --- /dev/null +++ b/cockpit/ports.mjs @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT + +/** + * @typedef {{ angular: number; langgraph: number }} CapPorts + * @typedef {Record} PortsRegistry + */ + +/** + * Single source of truth for cockpit cap port allocation. + * + * Excludes cockpit-ag-ui-streaming-angular — uses a non-LangGraph + * backend (Node ag-ui server on :3000, /agent proxy). Single-cap + * exception; left as a literal in its own files. + * + * Port ranges: + * - angular: [4000, 5000) + * - langgraph: [5000, 6000) + * - Convention: langgraph = angular + 1000 + * + * The CI verifier (scripts/cockpit-ports.spec.mjs) asserts this + * registry matches the literal --port values in each cap's + * python/project.json + baseURL in playwright.config.ts. + * + * @type {PortsRegistry} + */ +export const PORTS = Object.freeze({}); + +/** + * Look up ports for a cap by its Nx angular project name. + * Throws if the name isn't in the registry — caller crash for + * fast diagnosis. + * + * @param {string} cap + * @returns {CapPorts} + */ +export function portsFor(cap) { + const p = PORTS[cap]; + if (!p) throw new Error(`No port allocation for ${cap}`); + return p; +} diff --git a/scripts/cockpit-ports.spec.mjs b/scripts/cockpit-ports.spec.mjs new file mode 100644 index 00000000..43343388 --- /dev/null +++ b/scripts/cockpit-ports.spec.mjs @@ -0,0 +1,124 @@ +import { test, describe } from 'node:test'; +import assert from 'node:assert/strict'; +import { readdirSync, readFileSync, existsSync } from 'node:fs'; +import { dirname, join, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { PORTS } from '../cockpit/ports.mjs'; + +const repoRoot = resolve(fileURLToPath(import.meta.url), '..', '..'); +const cockpitDir = join(repoRoot, 'cockpit'); + +const AGUI_EXCEPTION = 'cockpit-ag-ui-streaming-angular'; + +function findCockpitAngularProjects() { + const out = []; + function walk(dir) { + let entries; + try { entries = readdirSync(dir); } catch { return; } + for (const name of entries) { + const full = join(dir, name); + if (name === 'node_modules' || name.startsWith('.')) continue; + let stat; + try { stat = readFileSync(join(full, 'project.json'), 'utf8'); } + catch { walk(full); continue; } + try { + const meta = JSON.parse(stat); + if (typeof meta.name === 'string' && meta.name.endsWith('-angular') && meta.name.startsWith('cockpit-')) { + out.push({ name: meta.name, dir: full, meta }); + } + } catch {} + walk(full); + } + } + walk(cockpitDir); + return out; +} + +const projects = findCockpitAngularProjects(); + +describe('cockpit/ports.mjs registry', () => { + test('covers every cockpit-*-angular project on disk except ag-ui', () => { + const onDisk = projects.map((p) => p.name).filter((n) => n !== AGUI_EXCEPTION); + const missing = onDisk.filter((n) => !(n in PORTS)); + assert.deepEqual(missing, [], `missing from PORTS: ${missing.join(', ')}`); + }); + + test('has no orphan entries (each PORTS key has a project on disk)', () => { + const diskNames = new Set(projects.map((p) => p.name)); + const orphans = Object.keys(PORTS).filter((n) => !diskNames.has(n)); + assert.deepEqual(orphans, [], `orphan PORTS entries: ${orphans.join(', ')}`); + }); + + test('ag-ui is NOT in the registry (exception)', () => { + assert.equal(AGUI_EXCEPTION in PORTS, false); + }); + + test('every entry has angular + langgraph as positive integers', () => { + for (const [name, p] of Object.entries(PORTS)) { + assert.equal(typeof p.angular, 'number', `${name}.angular not number`); + assert.equal(typeof p.langgraph, 'number', `${name}.langgraph not number`); + assert.ok(p.angular > 0 && p.langgraph > 0, `${name} has non-positive port`); + } + }); + + test('port ranges: angular ∈ [4000, 5000), langgraph ∈ [5000, 6000), langgraph = angular + 1000', () => { + for (const [name, p] of Object.entries(PORTS)) { + assert.ok(p.angular >= 4000 && p.angular < 5000, `${name}.angular out of range: ${p.angular}`); + assert.ok(p.langgraph >= 5000 && p.langgraph < 6000, `${name}.langgraph out of range: ${p.langgraph}`); + assert.equal(p.langgraph, p.angular + 1000, `${name}: langgraph (${p.langgraph}) != angular (${p.angular}) + 1000`); + } + }); + + test('no duplicate ports', () => { + const seen = new Set(); + for (const [name, p] of Object.entries(PORTS)) { + for (const port of [p.angular, p.langgraph]) { + assert.ok(!seen.has(port), `duplicate port ${port} (${name})`); + seen.add(port); + } + } + }); + + test('each cap python/project.json --port matches PORTS[name].langgraph', () => { + const mismatches = []; + for (const { name, dir } of projects) { + if (name === AGUI_EXCEPTION) continue; + const pyProjectJson = join(dir, '..', 'python', 'project.json'); + if (!existsSync(pyProjectJson)) { + mismatches.push(`${name}: missing python/project.json at ${pyProjectJson}`); + continue; + } + const meta = JSON.parse(readFileSync(pyProjectJson, 'utf8')); + const cmd = String(meta?.targets?.serve?.options?.command ?? ''); + const m = cmd.match(/--port[= ](\d+)/); + if (!m) { + mismatches.push(`${name}: no --port in python/project.json serve command`); + continue; + } + const literal = Number(m[1]); + const expected = PORTS[name]?.langgraph; + if (literal !== expected) { + mismatches.push(`${name}: python --port ${literal} != registry ${expected}`); + } + } + assert.deepEqual(mismatches, []); + }); + + test('each active-e2e cap playwright.config.ts baseURL port matches PORTS[name].angular', () => { + const mismatches = []; + for (const { name, dir } of projects) { + if (name === AGUI_EXCEPTION) continue; + const pwConfig = join(dir, 'e2e', 'playwright.config.ts'); + if (!existsSync(pwConfig)) continue; + const text = readFileSync(pwConfig, 'utf8'); + const m = text.match(/baseURL:\s*[`'"]http:\/\/localhost:(\d+)[`'"/]/); + if (!m) continue; + const literal = Number(m[1]); + const expected = PORTS[name]?.angular; + if (literal !== expected) { + mismatches.push(`${name}: playwright baseURL :${literal} != registry :${expected}`); + } + } + assert.deepEqual(mismatches, []); + }); +}); From 86238e55eabc57baffde5824867626e4c9fb9f3c Mon Sep 17 00:00:00 2001 From: Brian Love Date: Wed, 27 May 2026 14:28:51 -0700 Subject: [PATCH 4/9] feat(ci): populate cockpit ports registry from on-disk values 31 entries, extracted from each cap's proxy.conf.json target + playwright.config.ts baseURL (or langgraph - 1000 for non-e2e caps). Verifier confirms the registry round-trips cleanly against every python/project.json --port literal. --- cockpit/ports.mjs | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/cockpit/ports.mjs b/cockpit/ports.mjs index bf80e8c3..2292d5f3 100644 --- a/cockpit/ports.mjs +++ b/cockpit/ports.mjs @@ -23,7 +23,39 @@ * * @type {PortsRegistry} */ -export const PORTS = Object.freeze({}); +export const PORTS = Object.freeze({ + 'cockpit-chat-a2ui-angular': { angular: 4511, langgraph: 5511 }, + 'cockpit-chat-debug-angular': { angular: 4509, langgraph: 5509 }, + 'cockpit-chat-generative-ui-angular': { angular: 4508, langgraph: 5508 }, + 'cockpit-chat-input-angular': { angular: 4502, langgraph: 5502 }, + 'cockpit-chat-interrupts-angular': { angular: 4503, langgraph: 5503 }, + 'cockpit-chat-messages-angular': { angular: 4501, langgraph: 5501 }, + 'cockpit-chat-subagents-angular': { angular: 4505, langgraph: 5505 }, + 'cockpit-chat-theming-angular': { angular: 4510, langgraph: 5510 }, + 'cockpit-chat-threads-angular': { angular: 4506, langgraph: 5506 }, + 'cockpit-chat-timeline-angular': { angular: 4507, langgraph: 5507 }, + 'cockpit-chat-tool-calls-angular': { angular: 4504, langgraph: 5504 }, + 'cockpit-deep-agents-filesystem-angular': { angular: 4311, langgraph: 5311 }, + 'cockpit-deep-agents-memory-angular': { angular: 4313, langgraph: 5313 }, + 'cockpit-deep-agents-planning-angular': { angular: 4310, langgraph: 5310 }, + 'cockpit-deep-agents-sandboxes-angular': { angular: 4315, langgraph: 5315 }, + 'cockpit-deep-agents-skills-angular': { angular: 4314, langgraph: 5314 }, + 'cockpit-deep-agents-subagents-angular': { angular: 4312, langgraph: 5312 }, + 'cockpit-langgraph-deployment-runtime-angular': { angular: 4307, langgraph: 5307 }, + 'cockpit-langgraph-durable-execution-angular': { angular: 4304, langgraph: 5304 }, + 'cockpit-langgraph-interrupts-angular': { angular: 4302, langgraph: 5302 }, + 'cockpit-langgraph-memory-angular': { angular: 4303, langgraph: 5303 }, + 'cockpit-langgraph-persistence-angular': { angular: 4301, langgraph: 5301 }, + 'cockpit-langgraph-streaming-angular': { angular: 4300, langgraph: 5300 }, + 'cockpit-langgraph-subgraphs-angular': { angular: 4305, langgraph: 5305 }, + 'cockpit-langgraph-time-travel-angular': { angular: 4306, langgraph: 5306 }, + 'cockpit-render-computed-functions-angular': { angular: 4406, langgraph: 5406 }, + 'cockpit-render-element-rendering-angular': { angular: 4402, langgraph: 5402 }, + 'cockpit-render-registry-angular': { angular: 4404, langgraph: 5404 }, + 'cockpit-render-repeat-loops-angular': { angular: 4405, langgraph: 5405 }, + 'cockpit-render-spec-rendering-angular': { angular: 4401, langgraph: 5401 }, + 'cockpit-render-state-management-angular': { angular: 4403, langgraph: 5403 }, +}); /** * Look up ports for a cap by its Nx angular project name. From 57f33d9816bb82e9f1394bc532c77be8765a0d01 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Wed, 27 May 2026 14:32:05 -0700 Subject: [PATCH 5/9] test(ports): verifier skips python --port check for caps without literal Only chat caps have --port in their python/project.json serve target; langgraph/deep-agents/render caps rely on the e2e harness spawning langgraph with explicit --port from global-setup-impl.ts. Skip verifier check for those rather than fail. --- scripts/cockpit-ports.spec.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/cockpit-ports.spec.mjs b/scripts/cockpit-ports.spec.mjs index 43343388..61c5bd6b 100644 --- a/scripts/cockpit-ports.spec.mjs +++ b/scripts/cockpit-ports.spec.mjs @@ -91,10 +91,10 @@ describe('cockpit/ports.mjs registry', () => { const meta = JSON.parse(readFileSync(pyProjectJson, 'utf8')); const cmd = String(meta?.targets?.serve?.options?.command ?? ''); const m = cmd.match(/--port[= ](\d+)/); - if (!m) { - mismatches.push(`${name}: no --port in python/project.json serve command`); - continue; - } + // Skip caps without an explicit --port (e.g. langgraph/deep-agents/render + // caps that don't expose nx serve port; e2e harness spawns langgraph + // with explicit --port from global-setup-impl.ts instead). + if (!m) continue; const literal = Number(m[1]); const expected = PORTS[name]?.langgraph; if (literal !== expected) { From 08004fa827115accf4786a5e7a6c9c37d4cdffc8 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Wed, 27 May 2026 14:38:30 -0700 Subject: [PATCH 6/9] =?UTF-8?q?refactor(cockpit):=2031=20proxy.conf.json?= =?UTF-8?q?=20=E2=86=92=20proxy.conf.mjs=20(import=20ports=20registry)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every cockpit cap's proxy.conf.json is replaced with proxy.conf.mjs that imports portsFor(capName) from cockpit/ports.mjs and templates the langgraph port into the target URL. Each angular/project.json's serve.options.proxyConfig is updated to point at the .mjs file. cockpit/ag-ui/streaming is excluded — non-LangGraph backend, kept as proxy.conf.json with its /agent → :3000 literal. --- cockpit/chat/a2ui/angular/project.json | 2 +- cockpit/chat/a2ui/angular/proxy.conf.json | 9 --------- cockpit/chat/a2ui/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/chat/debug/angular/project.json | 2 +- cockpit/chat/debug/angular/proxy.conf.json | 9 --------- cockpit/chat/debug/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/chat/generative-ui/angular/project.json | 2 +- cockpit/chat/generative-ui/angular/proxy.conf.json | 9 --------- cockpit/chat/generative-ui/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/chat/input/angular/project.json | 2 +- cockpit/chat/input/angular/proxy.conf.json | 9 --------- cockpit/chat/input/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/chat/interrupts/angular/project.json | 2 +- cockpit/chat/interrupts/angular/proxy.conf.json | 9 --------- cockpit/chat/interrupts/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/chat/messages/angular/project.json | 2 +- cockpit/chat/messages/angular/proxy.conf.json | 9 --------- cockpit/chat/messages/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/chat/subagents/angular/project.json | 2 +- cockpit/chat/subagents/angular/proxy.conf.json | 9 --------- cockpit/chat/subagents/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/chat/theming/angular/project.json | 2 +- cockpit/chat/theming/angular/proxy.conf.json | 9 --------- cockpit/chat/theming/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/chat/threads/angular/project.json | 2 +- cockpit/chat/threads/angular/proxy.conf.json | 9 --------- cockpit/chat/threads/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/chat/timeline/angular/project.json | 2 +- cockpit/chat/timeline/angular/proxy.conf.json | 9 --------- cockpit/chat/timeline/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/chat/tool-calls/angular/project.json | 2 +- cockpit/chat/tool-calls/angular/proxy.conf.json | 9 --------- cockpit/chat/tool-calls/angular/proxy.conf.mjs | 14 ++++++++++++++ .../deep-agents/filesystem/angular/project.json | 2 +- .../deep-agents/filesystem/angular/proxy.conf.json | 11 ----------- .../deep-agents/filesystem/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/deep-agents/memory/angular/project.json | 2 +- cockpit/deep-agents/memory/angular/proxy.conf.json | 11 ----------- cockpit/deep-agents/memory/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/deep-agents/planning/angular/project.json | 2 +- .../deep-agents/planning/angular/proxy.conf.json | 11 ----------- .../deep-agents/planning/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/deep-agents/sandboxes/angular/project.json | 2 +- .../deep-agents/sandboxes/angular/proxy.conf.json | 11 ----------- .../deep-agents/sandboxes/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/deep-agents/skills/angular/project.json | 2 +- cockpit/deep-agents/skills/angular/proxy.conf.json | 11 ----------- cockpit/deep-agents/skills/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/deep-agents/subagents/angular/project.json | 2 +- .../deep-agents/subagents/angular/proxy.conf.json | 11 ----------- .../deep-agents/subagents/angular/proxy.conf.mjs | 14 ++++++++++++++ .../deployment-runtime/angular/project.json | 2 +- .../deployment-runtime/angular/proxy.conf.json | 11 ----------- .../deployment-runtime/angular/proxy.conf.mjs | 14 ++++++++++++++ .../durable-execution/angular/project.json | 2 +- .../durable-execution/angular/proxy.conf.json | 11 ----------- .../durable-execution/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/langgraph/interrupts/angular/project.json | 2 +- .../langgraph/interrupts/angular/proxy.conf.json | 11 ----------- .../langgraph/interrupts/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/langgraph/memory/angular/project.json | 2 +- cockpit/langgraph/memory/angular/proxy.conf.json | 11 ----------- cockpit/langgraph/memory/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/langgraph/persistence/angular/project.json | 2 +- .../langgraph/persistence/angular/proxy.conf.json | 11 ----------- .../langgraph/persistence/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/langgraph/streaming/angular/project.json | 2 +- .../langgraph/streaming/angular/proxy.conf.json | 11 ----------- cockpit/langgraph/streaming/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/langgraph/subgraphs/angular/project.json | 2 +- .../langgraph/subgraphs/angular/proxy.conf.json | 11 ----------- cockpit/langgraph/subgraphs/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/langgraph/time-travel/angular/project.json | 2 +- .../langgraph/time-travel/angular/proxy.conf.json | 11 ----------- .../langgraph/time-travel/angular/proxy.conf.mjs | 14 ++++++++++++++ .../render/computed-functions/angular/project.json | 2 +- .../computed-functions/angular/proxy.conf.json | 11 ----------- .../computed-functions/angular/proxy.conf.mjs | 14 ++++++++++++++ .../render/element-rendering/angular/project.json | 2 +- .../element-rendering/angular/proxy.conf.json | 11 ----------- .../element-rendering/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/render/registry/angular/project.json | 2 +- cockpit/render/registry/angular/proxy.conf.json | 11 ----------- cockpit/render/registry/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/render/repeat-loops/angular/project.json | 2 +- .../render/repeat-loops/angular/proxy.conf.json | 11 ----------- cockpit/render/repeat-loops/angular/proxy.conf.mjs | 14 ++++++++++++++ cockpit/render/spec-rendering/angular/project.json | 2 +- .../render/spec-rendering/angular/proxy.conf.json | 11 ----------- .../render/spec-rendering/angular/proxy.conf.mjs | 14 ++++++++++++++ .../render/state-management/angular/project.json | 2 +- .../state-management/angular/proxy.conf.json | 11 ----------- .../render/state-management/angular/proxy.conf.mjs | 14 ++++++++++++++ 93 files changed, 465 insertions(+), 350 deletions(-) delete mode 100644 cockpit/chat/a2ui/angular/proxy.conf.json create mode 100644 cockpit/chat/a2ui/angular/proxy.conf.mjs delete mode 100644 cockpit/chat/debug/angular/proxy.conf.json create mode 100644 cockpit/chat/debug/angular/proxy.conf.mjs delete mode 100644 cockpit/chat/generative-ui/angular/proxy.conf.json create mode 100644 cockpit/chat/generative-ui/angular/proxy.conf.mjs delete mode 100644 cockpit/chat/input/angular/proxy.conf.json create mode 100644 cockpit/chat/input/angular/proxy.conf.mjs delete mode 100644 cockpit/chat/interrupts/angular/proxy.conf.json create mode 100644 cockpit/chat/interrupts/angular/proxy.conf.mjs delete mode 100644 cockpit/chat/messages/angular/proxy.conf.json create mode 100644 cockpit/chat/messages/angular/proxy.conf.mjs delete mode 100644 cockpit/chat/subagents/angular/proxy.conf.json create mode 100644 cockpit/chat/subagents/angular/proxy.conf.mjs delete mode 100644 cockpit/chat/theming/angular/proxy.conf.json create mode 100644 cockpit/chat/theming/angular/proxy.conf.mjs delete mode 100644 cockpit/chat/threads/angular/proxy.conf.json create mode 100644 cockpit/chat/threads/angular/proxy.conf.mjs delete mode 100644 cockpit/chat/timeline/angular/proxy.conf.json create mode 100644 cockpit/chat/timeline/angular/proxy.conf.mjs delete mode 100644 cockpit/chat/tool-calls/angular/proxy.conf.json create mode 100644 cockpit/chat/tool-calls/angular/proxy.conf.mjs delete mode 100644 cockpit/deep-agents/filesystem/angular/proxy.conf.json create mode 100644 cockpit/deep-agents/filesystem/angular/proxy.conf.mjs delete mode 100644 cockpit/deep-agents/memory/angular/proxy.conf.json create mode 100644 cockpit/deep-agents/memory/angular/proxy.conf.mjs delete mode 100644 cockpit/deep-agents/planning/angular/proxy.conf.json create mode 100644 cockpit/deep-agents/planning/angular/proxy.conf.mjs delete mode 100644 cockpit/deep-agents/sandboxes/angular/proxy.conf.json create mode 100644 cockpit/deep-agents/sandboxes/angular/proxy.conf.mjs delete mode 100644 cockpit/deep-agents/skills/angular/proxy.conf.json create mode 100644 cockpit/deep-agents/skills/angular/proxy.conf.mjs delete mode 100644 cockpit/deep-agents/subagents/angular/proxy.conf.json create mode 100644 cockpit/deep-agents/subagents/angular/proxy.conf.mjs delete mode 100644 cockpit/langgraph/deployment-runtime/angular/proxy.conf.json create mode 100644 cockpit/langgraph/deployment-runtime/angular/proxy.conf.mjs delete mode 100644 cockpit/langgraph/durable-execution/angular/proxy.conf.json create mode 100644 cockpit/langgraph/durable-execution/angular/proxy.conf.mjs delete mode 100644 cockpit/langgraph/interrupts/angular/proxy.conf.json create mode 100644 cockpit/langgraph/interrupts/angular/proxy.conf.mjs delete mode 100644 cockpit/langgraph/memory/angular/proxy.conf.json create mode 100644 cockpit/langgraph/memory/angular/proxy.conf.mjs delete mode 100644 cockpit/langgraph/persistence/angular/proxy.conf.json create mode 100644 cockpit/langgraph/persistence/angular/proxy.conf.mjs delete mode 100644 cockpit/langgraph/streaming/angular/proxy.conf.json create mode 100644 cockpit/langgraph/streaming/angular/proxy.conf.mjs delete mode 100644 cockpit/langgraph/subgraphs/angular/proxy.conf.json create mode 100644 cockpit/langgraph/subgraphs/angular/proxy.conf.mjs delete mode 100644 cockpit/langgraph/time-travel/angular/proxy.conf.json create mode 100644 cockpit/langgraph/time-travel/angular/proxy.conf.mjs delete mode 100644 cockpit/render/computed-functions/angular/proxy.conf.json create mode 100644 cockpit/render/computed-functions/angular/proxy.conf.mjs delete mode 100644 cockpit/render/element-rendering/angular/proxy.conf.json create mode 100644 cockpit/render/element-rendering/angular/proxy.conf.mjs delete mode 100644 cockpit/render/registry/angular/proxy.conf.json create mode 100644 cockpit/render/registry/angular/proxy.conf.mjs delete mode 100644 cockpit/render/repeat-loops/angular/proxy.conf.json create mode 100644 cockpit/render/repeat-loops/angular/proxy.conf.mjs delete mode 100644 cockpit/render/spec-rendering/angular/proxy.conf.json create mode 100644 cockpit/render/spec-rendering/angular/proxy.conf.mjs delete mode 100644 cockpit/render/state-management/angular/proxy.conf.json create mode 100644 cockpit/render/state-management/angular/proxy.conf.mjs diff --git a/cockpit/chat/a2ui/angular/project.json b/cockpit/chat/a2ui/angular/project.json index 426cd388..45c36b14 100644 --- a/cockpit/chat/a2ui/angular/project.json +++ b/cockpit/chat/a2ui/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/a2ui/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/a2ui/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/chat/a2ui/angular/proxy.conf.json b/cockpit/chat/a2ui/angular/proxy.conf.json deleted file mode 100644 index 60747be2..00000000 --- a/cockpit/chat/a2ui/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5511", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/a2ui/angular/proxy.conf.mjs b/cockpit/chat/a2ui/angular/proxy.conf.mjs new file mode 100644 index 00000000..fcba5dce --- /dev/null +++ b/cockpit/chat/a2ui/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-a2ui-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/chat/debug/angular/project.json b/cockpit/chat/debug/angular/project.json index 9560282f..055441ad 100644 --- a/cockpit/chat/debug/angular/project.json +++ b/cockpit/chat/debug/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/debug/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/debug/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/chat/debug/angular/proxy.conf.json b/cockpit/chat/debug/angular/proxy.conf.json deleted file mode 100644 index 374fb07f..00000000 --- a/cockpit/chat/debug/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5509", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/debug/angular/proxy.conf.mjs b/cockpit/chat/debug/angular/proxy.conf.mjs new file mode 100644 index 00000000..456d9f7a --- /dev/null +++ b/cockpit/chat/debug/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-debug-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/chat/generative-ui/angular/project.json b/cockpit/chat/generative-ui/angular/project.json index b1f018cd..7b9a446c 100644 --- a/cockpit/chat/generative-ui/angular/project.json +++ b/cockpit/chat/generative-ui/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/generative-ui/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/generative-ui/angular/proxy.conf.mjs" } }, "test": { diff --git a/cockpit/chat/generative-ui/angular/proxy.conf.json b/cockpit/chat/generative-ui/angular/proxy.conf.json deleted file mode 100644 index d31e2f5a..00000000 --- a/cockpit/chat/generative-ui/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5508", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/generative-ui/angular/proxy.conf.mjs b/cockpit/chat/generative-ui/angular/proxy.conf.mjs new file mode 100644 index 00000000..34e505f3 --- /dev/null +++ b/cockpit/chat/generative-ui/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-generative-ui-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/chat/input/angular/project.json b/cockpit/chat/input/angular/project.json index 108f4412..88047a80 100644 --- a/cockpit/chat/input/angular/project.json +++ b/cockpit/chat/input/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/input/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/input/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/chat/input/angular/proxy.conf.json b/cockpit/chat/input/angular/proxy.conf.json deleted file mode 100644 index 705be0f9..00000000 --- a/cockpit/chat/input/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5502", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/input/angular/proxy.conf.mjs b/cockpit/chat/input/angular/proxy.conf.mjs new file mode 100644 index 00000000..fce42c62 --- /dev/null +++ b/cockpit/chat/input/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-input-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/chat/interrupts/angular/project.json b/cockpit/chat/interrupts/angular/project.json index dc01f942..cb75fdb8 100644 --- a/cockpit/chat/interrupts/angular/project.json +++ b/cockpit/chat/interrupts/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/interrupts/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/interrupts/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/chat/interrupts/angular/proxy.conf.json b/cockpit/chat/interrupts/angular/proxy.conf.json deleted file mode 100644 index 8f8efae2..00000000 --- a/cockpit/chat/interrupts/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5503", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/interrupts/angular/proxy.conf.mjs b/cockpit/chat/interrupts/angular/proxy.conf.mjs new file mode 100644 index 00000000..d81f69fa --- /dev/null +++ b/cockpit/chat/interrupts/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-interrupts-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/chat/messages/angular/project.json b/cockpit/chat/messages/angular/project.json index 7204ee9a..e5b3f4c0 100644 --- a/cockpit/chat/messages/angular/project.json +++ b/cockpit/chat/messages/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/messages/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/messages/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/chat/messages/angular/proxy.conf.json b/cockpit/chat/messages/angular/proxy.conf.json deleted file mode 100644 index d6e7e14a..00000000 --- a/cockpit/chat/messages/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5501", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/messages/angular/proxy.conf.mjs b/cockpit/chat/messages/angular/proxy.conf.mjs new file mode 100644 index 00000000..303a7d46 --- /dev/null +++ b/cockpit/chat/messages/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-messages-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/chat/subagents/angular/project.json b/cockpit/chat/subagents/angular/project.json index 27ccd646..5f56a089 100644 --- a/cockpit/chat/subagents/angular/project.json +++ b/cockpit/chat/subagents/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/subagents/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/subagents/angular/proxy.conf.mjs" } }, "e2e": { diff --git a/cockpit/chat/subagents/angular/proxy.conf.json b/cockpit/chat/subagents/angular/proxy.conf.json deleted file mode 100644 index 189347ed..00000000 --- a/cockpit/chat/subagents/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5505", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/subagents/angular/proxy.conf.mjs b/cockpit/chat/subagents/angular/proxy.conf.mjs new file mode 100644 index 00000000..cdde193c --- /dev/null +++ b/cockpit/chat/subagents/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-subagents-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/chat/theming/angular/project.json b/cockpit/chat/theming/angular/project.json index 1aace858..64827d06 100644 --- a/cockpit/chat/theming/angular/project.json +++ b/cockpit/chat/theming/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/theming/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/theming/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/chat/theming/angular/proxy.conf.json b/cockpit/chat/theming/angular/proxy.conf.json deleted file mode 100644 index 94122df9..00000000 --- a/cockpit/chat/theming/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5510", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/theming/angular/proxy.conf.mjs b/cockpit/chat/theming/angular/proxy.conf.mjs new file mode 100644 index 00000000..141bb7f0 --- /dev/null +++ b/cockpit/chat/theming/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-theming-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/chat/threads/angular/project.json b/cockpit/chat/threads/angular/project.json index 83968c5d..d77a77bc 100644 --- a/cockpit/chat/threads/angular/project.json +++ b/cockpit/chat/threads/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/threads/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/threads/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/chat/threads/angular/proxy.conf.json b/cockpit/chat/threads/angular/proxy.conf.json deleted file mode 100644 index 269dcbcf..00000000 --- a/cockpit/chat/threads/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5506", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/threads/angular/proxy.conf.mjs b/cockpit/chat/threads/angular/proxy.conf.mjs new file mode 100644 index 00000000..bd9f167a --- /dev/null +++ b/cockpit/chat/threads/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-threads-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/chat/timeline/angular/project.json b/cockpit/chat/timeline/angular/project.json index bc100fb8..58e21ebd 100644 --- a/cockpit/chat/timeline/angular/project.json +++ b/cockpit/chat/timeline/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/timeline/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/timeline/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/chat/timeline/angular/proxy.conf.json b/cockpit/chat/timeline/angular/proxy.conf.json deleted file mode 100644 index 4cda42f9..00000000 --- a/cockpit/chat/timeline/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5507", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/timeline/angular/proxy.conf.mjs b/cockpit/chat/timeline/angular/proxy.conf.mjs new file mode 100644 index 00000000..fbc366f6 --- /dev/null +++ b/cockpit/chat/timeline/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-timeline-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/chat/tool-calls/angular/project.json b/cockpit/chat/tool-calls/angular/project.json index e111070e..3ced4d29 100644 --- a/cockpit/chat/tool-calls/angular/project.json +++ b/cockpit/chat/tool-calls/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/chat/tool-calls/angular/proxy.conf.json" + "proxyConfig": "cockpit/chat/tool-calls/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/chat/tool-calls/angular/proxy.conf.json b/cockpit/chat/tool-calls/angular/proxy.conf.json deleted file mode 100644 index 239ce106..00000000 --- a/cockpit/chat/tool-calls/angular/proxy.conf.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5504", - "secure": false, - "changeOrigin": true, - "pathRewrite": { "^/api": "" }, - "ws": true - } -} diff --git a/cockpit/chat/tool-calls/angular/proxy.conf.mjs b/cockpit/chat/tool-calls/angular/proxy.conf.mjs new file mode 100644 index 00000000..77060a1b --- /dev/null +++ b/cockpit/chat/tool-calls/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-chat-tool-calls-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/deep-agents/filesystem/angular/project.json b/cockpit/deep-agents/filesystem/angular/project.json index 3966a1d4..8bb7cfbd 100644 --- a/cockpit/deep-agents/filesystem/angular/project.json +++ b/cockpit/deep-agents/filesystem/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/deep-agents/filesystem/angular/proxy.conf.json" + "proxyConfig": "cockpit/deep-agents/filesystem/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/deep-agents/filesystem/angular/proxy.conf.json b/cockpit/deep-agents/filesystem/angular/proxy.conf.json deleted file mode 100644 index 3068de09..00000000 --- a/cockpit/deep-agents/filesystem/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5311", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/deep-agents/filesystem/angular/proxy.conf.mjs b/cockpit/deep-agents/filesystem/angular/proxy.conf.mjs new file mode 100644 index 00000000..2e79f5e2 --- /dev/null +++ b/cockpit/deep-agents/filesystem/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-deep-agents-filesystem-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/deep-agents/memory/angular/project.json b/cockpit/deep-agents/memory/angular/project.json index 61439b96..14139bf2 100644 --- a/cockpit/deep-agents/memory/angular/project.json +++ b/cockpit/deep-agents/memory/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/deep-agents/memory/angular/proxy.conf.json" + "proxyConfig": "cockpit/deep-agents/memory/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/deep-agents/memory/angular/proxy.conf.json b/cockpit/deep-agents/memory/angular/proxy.conf.json deleted file mode 100644 index 020a0ca4..00000000 --- a/cockpit/deep-agents/memory/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5313", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/deep-agents/memory/angular/proxy.conf.mjs b/cockpit/deep-agents/memory/angular/proxy.conf.mjs new file mode 100644 index 00000000..3c51c904 --- /dev/null +++ b/cockpit/deep-agents/memory/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-deep-agents-memory-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/deep-agents/planning/angular/project.json b/cockpit/deep-agents/planning/angular/project.json index 05bb8648..69d04c22 100644 --- a/cockpit/deep-agents/planning/angular/project.json +++ b/cockpit/deep-agents/planning/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/deep-agents/planning/angular/proxy.conf.json" + "proxyConfig": "cockpit/deep-agents/planning/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/deep-agents/planning/angular/proxy.conf.json b/cockpit/deep-agents/planning/angular/proxy.conf.json deleted file mode 100644 index 2c71ffe1..00000000 --- a/cockpit/deep-agents/planning/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5310", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/deep-agents/planning/angular/proxy.conf.mjs b/cockpit/deep-agents/planning/angular/proxy.conf.mjs new file mode 100644 index 00000000..52babdbf --- /dev/null +++ b/cockpit/deep-agents/planning/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-deep-agents-planning-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/deep-agents/sandboxes/angular/project.json b/cockpit/deep-agents/sandboxes/angular/project.json index 4749f41c..8db313d8 100644 --- a/cockpit/deep-agents/sandboxes/angular/project.json +++ b/cockpit/deep-agents/sandboxes/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/deep-agents/sandboxes/angular/proxy.conf.json" + "proxyConfig": "cockpit/deep-agents/sandboxes/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/deep-agents/sandboxes/angular/proxy.conf.json b/cockpit/deep-agents/sandboxes/angular/proxy.conf.json deleted file mode 100644 index c20d5a91..00000000 --- a/cockpit/deep-agents/sandboxes/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5315", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/deep-agents/sandboxes/angular/proxy.conf.mjs b/cockpit/deep-agents/sandboxes/angular/proxy.conf.mjs new file mode 100644 index 00000000..5ad229af --- /dev/null +++ b/cockpit/deep-agents/sandboxes/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-deep-agents-sandboxes-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/deep-agents/skills/angular/project.json b/cockpit/deep-agents/skills/angular/project.json index dccf8d9d..04d1dd99 100644 --- a/cockpit/deep-agents/skills/angular/project.json +++ b/cockpit/deep-agents/skills/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/deep-agents/skills/angular/proxy.conf.json" + "proxyConfig": "cockpit/deep-agents/skills/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/deep-agents/skills/angular/proxy.conf.json b/cockpit/deep-agents/skills/angular/proxy.conf.json deleted file mode 100644 index 76e30cf6..00000000 --- a/cockpit/deep-agents/skills/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5314", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/deep-agents/skills/angular/proxy.conf.mjs b/cockpit/deep-agents/skills/angular/proxy.conf.mjs new file mode 100644 index 00000000..ea243e5c --- /dev/null +++ b/cockpit/deep-agents/skills/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-deep-agents-skills-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/deep-agents/subagents/angular/project.json b/cockpit/deep-agents/subagents/angular/project.json index ddb639b1..48bf14c1 100644 --- a/cockpit/deep-agents/subagents/angular/project.json +++ b/cockpit/deep-agents/subagents/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/deep-agents/subagents/angular/proxy.conf.json" + "proxyConfig": "cockpit/deep-agents/subagents/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/deep-agents/subagents/angular/proxy.conf.json b/cockpit/deep-agents/subagents/angular/proxy.conf.json deleted file mode 100644 index 8985a469..00000000 --- a/cockpit/deep-agents/subagents/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5312", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/deep-agents/subagents/angular/proxy.conf.mjs b/cockpit/deep-agents/subagents/angular/proxy.conf.mjs new file mode 100644 index 00000000..f477d794 --- /dev/null +++ b/cockpit/deep-agents/subagents/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-deep-agents-subagents-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/langgraph/deployment-runtime/angular/project.json b/cockpit/langgraph/deployment-runtime/angular/project.json index 19c9ea5e..f10f799d 100644 --- a/cockpit/langgraph/deployment-runtime/angular/project.json +++ b/cockpit/langgraph/deployment-runtime/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/langgraph/deployment-runtime/angular/proxy.conf.json" + "proxyConfig": "cockpit/langgraph/deployment-runtime/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/langgraph/deployment-runtime/angular/proxy.conf.json b/cockpit/langgraph/deployment-runtime/angular/proxy.conf.json deleted file mode 100644 index 73b38f86..00000000 --- a/cockpit/langgraph/deployment-runtime/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5307", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/langgraph/deployment-runtime/angular/proxy.conf.mjs b/cockpit/langgraph/deployment-runtime/angular/proxy.conf.mjs new file mode 100644 index 00000000..4dfac51a --- /dev/null +++ b/cockpit/langgraph/deployment-runtime/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-langgraph-deployment-runtime-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/langgraph/durable-execution/angular/project.json b/cockpit/langgraph/durable-execution/angular/project.json index d0ce201a..55db9b89 100644 --- a/cockpit/langgraph/durable-execution/angular/project.json +++ b/cockpit/langgraph/durable-execution/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/langgraph/durable-execution/angular/proxy.conf.json" + "proxyConfig": "cockpit/langgraph/durable-execution/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/langgraph/durable-execution/angular/proxy.conf.json b/cockpit/langgraph/durable-execution/angular/proxy.conf.json deleted file mode 100644 index 3635c645..00000000 --- a/cockpit/langgraph/durable-execution/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5304", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/langgraph/durable-execution/angular/proxy.conf.mjs b/cockpit/langgraph/durable-execution/angular/proxy.conf.mjs new file mode 100644 index 00000000..1fd9b694 --- /dev/null +++ b/cockpit/langgraph/durable-execution/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-langgraph-durable-execution-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/langgraph/interrupts/angular/project.json b/cockpit/langgraph/interrupts/angular/project.json index 447e2fe9..a175c8eb 100644 --- a/cockpit/langgraph/interrupts/angular/project.json +++ b/cockpit/langgraph/interrupts/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/langgraph/interrupts/angular/proxy.conf.json" + "proxyConfig": "cockpit/langgraph/interrupts/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/langgraph/interrupts/angular/proxy.conf.json b/cockpit/langgraph/interrupts/angular/proxy.conf.json deleted file mode 100644 index 1e81d1e5..00000000 --- a/cockpit/langgraph/interrupts/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5302", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/langgraph/interrupts/angular/proxy.conf.mjs b/cockpit/langgraph/interrupts/angular/proxy.conf.mjs new file mode 100644 index 00000000..b3bfea65 --- /dev/null +++ b/cockpit/langgraph/interrupts/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-langgraph-interrupts-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/langgraph/memory/angular/project.json b/cockpit/langgraph/memory/angular/project.json index 266c2176..ea04be9c 100644 --- a/cockpit/langgraph/memory/angular/project.json +++ b/cockpit/langgraph/memory/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/langgraph/memory/angular/proxy.conf.json" + "proxyConfig": "cockpit/langgraph/memory/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/langgraph/memory/angular/proxy.conf.json b/cockpit/langgraph/memory/angular/proxy.conf.json deleted file mode 100644 index 2ccccc5c..00000000 --- a/cockpit/langgraph/memory/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5303", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/langgraph/memory/angular/proxy.conf.mjs b/cockpit/langgraph/memory/angular/proxy.conf.mjs new file mode 100644 index 00000000..81d8b670 --- /dev/null +++ b/cockpit/langgraph/memory/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-langgraph-memory-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/langgraph/persistence/angular/project.json b/cockpit/langgraph/persistence/angular/project.json index 0e7a7529..ef00e0e1 100644 --- a/cockpit/langgraph/persistence/angular/project.json +++ b/cockpit/langgraph/persistence/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/langgraph/persistence/angular/proxy.conf.json" + "proxyConfig": "cockpit/langgraph/persistence/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/langgraph/persistence/angular/proxy.conf.json b/cockpit/langgraph/persistence/angular/proxy.conf.json deleted file mode 100644 index dbab65e0..00000000 --- a/cockpit/langgraph/persistence/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5301", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/langgraph/persistence/angular/proxy.conf.mjs b/cockpit/langgraph/persistence/angular/proxy.conf.mjs new file mode 100644 index 00000000..0ca517a7 --- /dev/null +++ b/cockpit/langgraph/persistence/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-langgraph-persistence-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/langgraph/streaming/angular/project.json b/cockpit/langgraph/streaming/angular/project.json index da0e9277..4ad42110 100644 --- a/cockpit/langgraph/streaming/angular/project.json +++ b/cockpit/langgraph/streaming/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/langgraph/streaming/angular/proxy.conf.json" + "proxyConfig": "cockpit/langgraph/streaming/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/langgraph/streaming/angular/proxy.conf.json b/cockpit/langgraph/streaming/angular/proxy.conf.json deleted file mode 100644 index 65d40b4b..00000000 --- a/cockpit/langgraph/streaming/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5300", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/langgraph/streaming/angular/proxy.conf.mjs b/cockpit/langgraph/streaming/angular/proxy.conf.mjs new file mode 100644 index 00000000..d0fd52b7 --- /dev/null +++ b/cockpit/langgraph/streaming/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-langgraph-streaming-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/langgraph/subgraphs/angular/project.json b/cockpit/langgraph/subgraphs/angular/project.json index 0e84f6da..3927dc59 100644 --- a/cockpit/langgraph/subgraphs/angular/project.json +++ b/cockpit/langgraph/subgraphs/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/langgraph/subgraphs/angular/proxy.conf.json" + "proxyConfig": "cockpit/langgraph/subgraphs/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/langgraph/subgraphs/angular/proxy.conf.json b/cockpit/langgraph/subgraphs/angular/proxy.conf.json deleted file mode 100644 index 47e38550..00000000 --- a/cockpit/langgraph/subgraphs/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5305", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/langgraph/subgraphs/angular/proxy.conf.mjs b/cockpit/langgraph/subgraphs/angular/proxy.conf.mjs new file mode 100644 index 00000000..40c6ad89 --- /dev/null +++ b/cockpit/langgraph/subgraphs/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-langgraph-subgraphs-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/langgraph/time-travel/angular/project.json b/cockpit/langgraph/time-travel/angular/project.json index b38b3cab..4748cd75 100644 --- a/cockpit/langgraph/time-travel/angular/project.json +++ b/cockpit/langgraph/time-travel/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/langgraph/time-travel/angular/proxy.conf.json" + "proxyConfig": "cockpit/langgraph/time-travel/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/langgraph/time-travel/angular/proxy.conf.json b/cockpit/langgraph/time-travel/angular/proxy.conf.json deleted file mode 100644 index 78ddc28b..00000000 --- a/cockpit/langgraph/time-travel/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5306", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/langgraph/time-travel/angular/proxy.conf.mjs b/cockpit/langgraph/time-travel/angular/proxy.conf.mjs new file mode 100644 index 00000000..434bd4fe --- /dev/null +++ b/cockpit/langgraph/time-travel/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-langgraph-time-travel-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/render/computed-functions/angular/project.json b/cockpit/render/computed-functions/angular/project.json index 0ce7a9a5..ccfd4082 100644 --- a/cockpit/render/computed-functions/angular/project.json +++ b/cockpit/render/computed-functions/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/render/computed-functions/angular/proxy.conf.json" + "proxyConfig": "cockpit/render/computed-functions/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/render/computed-functions/angular/proxy.conf.json b/cockpit/render/computed-functions/angular/proxy.conf.json deleted file mode 100644 index fbebbb7a..00000000 --- a/cockpit/render/computed-functions/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5406", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/render/computed-functions/angular/proxy.conf.mjs b/cockpit/render/computed-functions/angular/proxy.conf.mjs new file mode 100644 index 00000000..fe5b6b40 --- /dev/null +++ b/cockpit/render/computed-functions/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-render-computed-functions-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/render/element-rendering/angular/project.json b/cockpit/render/element-rendering/angular/project.json index 51c68cf2..5127ac1b 100644 --- a/cockpit/render/element-rendering/angular/project.json +++ b/cockpit/render/element-rendering/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/render/element-rendering/angular/proxy.conf.json" + "proxyConfig": "cockpit/render/element-rendering/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/render/element-rendering/angular/proxy.conf.json b/cockpit/render/element-rendering/angular/proxy.conf.json deleted file mode 100644 index 7a087fbd..00000000 --- a/cockpit/render/element-rendering/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5402", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/render/element-rendering/angular/proxy.conf.mjs b/cockpit/render/element-rendering/angular/proxy.conf.mjs new file mode 100644 index 00000000..8f9e0be4 --- /dev/null +++ b/cockpit/render/element-rendering/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-render-element-rendering-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/render/registry/angular/project.json b/cockpit/render/registry/angular/project.json index 7f88ac4c..61ee1f62 100644 --- a/cockpit/render/registry/angular/project.json +++ b/cockpit/render/registry/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/render/registry/angular/proxy.conf.json" + "proxyConfig": "cockpit/render/registry/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/render/registry/angular/proxy.conf.json b/cockpit/render/registry/angular/proxy.conf.json deleted file mode 100644 index 8868f9d2..00000000 --- a/cockpit/render/registry/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5404", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/render/registry/angular/proxy.conf.mjs b/cockpit/render/registry/angular/proxy.conf.mjs new file mode 100644 index 00000000..c8097ab3 --- /dev/null +++ b/cockpit/render/registry/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-render-registry-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/render/repeat-loops/angular/project.json b/cockpit/render/repeat-loops/angular/project.json index 43cf9cac..6ce03da7 100644 --- a/cockpit/render/repeat-loops/angular/project.json +++ b/cockpit/render/repeat-loops/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/render/repeat-loops/angular/proxy.conf.json" + "proxyConfig": "cockpit/render/repeat-loops/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/render/repeat-loops/angular/proxy.conf.json b/cockpit/render/repeat-loops/angular/proxy.conf.json deleted file mode 100644 index 8e9e9ec7..00000000 --- a/cockpit/render/repeat-loops/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5405", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/render/repeat-loops/angular/proxy.conf.mjs b/cockpit/render/repeat-loops/angular/proxy.conf.mjs new file mode 100644 index 00000000..8d398fbd --- /dev/null +++ b/cockpit/render/repeat-loops/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-render-repeat-loops-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/render/spec-rendering/angular/project.json b/cockpit/render/spec-rendering/angular/project.json index 9e8f1688..e0d0ac13 100644 --- a/cockpit/render/spec-rendering/angular/project.json +++ b/cockpit/render/spec-rendering/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/render/spec-rendering/angular/proxy.conf.json" + "proxyConfig": "cockpit/render/spec-rendering/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/render/spec-rendering/angular/proxy.conf.json b/cockpit/render/spec-rendering/angular/proxy.conf.json deleted file mode 100644 index 6e752e0e..00000000 --- a/cockpit/render/spec-rendering/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5401", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/render/spec-rendering/angular/proxy.conf.mjs b/cockpit/render/spec-rendering/angular/proxy.conf.mjs new file mode 100644 index 00000000..3d029976 --- /dev/null +++ b/cockpit/render/spec-rendering/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-render-spec-rendering-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; diff --git a/cockpit/render/state-management/angular/project.json b/cockpit/render/state-management/angular/project.json index c6a7c93f..fe736b0c 100644 --- a/cockpit/render/state-management/angular/project.json +++ b/cockpit/render/state-management/angular/project.json @@ -78,7 +78,7 @@ }, "defaultConfiguration": "development", "options": { - "proxyConfig": "cockpit/render/state-management/angular/proxy.conf.json" + "proxyConfig": "cockpit/render/state-management/angular/proxy.conf.mjs" } }, "smoke": { diff --git a/cockpit/render/state-management/angular/proxy.conf.json b/cockpit/render/state-management/angular/proxy.conf.json deleted file mode 100644 index 7b2da2df..00000000 --- a/cockpit/render/state-management/angular/proxy.conf.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "/api": { - "target": "http://localhost:5403", - "secure": false, - "changeOrigin": true, - "pathRewrite": { - "^/api": "" - }, - "ws": true - } -} diff --git a/cockpit/render/state-management/angular/proxy.conf.mjs b/cockpit/render/state-management/angular/proxy.conf.mjs new file mode 100644 index 00000000..16c73626 --- /dev/null +++ b/cockpit/render/state-management/angular/proxy.conf.mjs @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +import { portsFor } from '../../../../cockpit/ports.mjs'; + +const { langgraph } = portsFor('cockpit-render-state-management-angular'); + +export default { + "/api": { + target: `http://localhost:${langgraph}`, + secure: false, + changeOrigin: true, + pathRewrite: {"^/api":""}, + ws: true, + }, +}; From 975c174e2ece0838d095f904abccb0691d0fcd43 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Wed, 27 May 2026 14:55:16 -0700 Subject: [PATCH 7/9] refactor(cockpit): 24 e2e configs import ports from registry Each cap's e2e/global-setup-impl.ts now imports portsFor() and reads angular/langgraph ports from the registry instead of literal numbers. playwright.config.ts is updated similarly for baseURL. All 24 e2e tsconfig.json files gain allowJs: true so tsc accepts the .mjs import without a declaration file. The verifier's playwright-baseURL check now skips templated configs (its regex only matches literal URLs); drift is impossible because the value imports directly from the registry. --- cockpit/chat/a2ui/angular/e2e/global-setup-impl.ts | 7 +++++-- cockpit/chat/a2ui/angular/e2e/playwright.config.ts | 6 +++++- cockpit/chat/a2ui/angular/e2e/tsconfig.json | 3 ++- .../chat/generative-ui/angular/e2e/global-setup-impl.ts | 7 +++++-- .../chat/generative-ui/angular/e2e/playwright.config.ts | 6 +++++- cockpit/chat/generative-ui/angular/e2e/tsconfig.json | 3 ++- cockpit/chat/input/angular/e2e/global-setup-impl.ts | 7 +++++-- cockpit/chat/input/angular/e2e/playwright.config.ts | 6 +++++- cockpit/chat/input/angular/e2e/tsconfig.json | 3 ++- cockpit/chat/interrupts/angular/e2e/global-setup-impl.ts | 7 +++++-- cockpit/chat/interrupts/angular/e2e/playwright.config.ts | 6 +++++- cockpit/chat/interrupts/angular/e2e/tsconfig.json | 3 ++- cockpit/chat/messages/angular/e2e/global-setup-impl.ts | 7 +++++-- cockpit/chat/messages/angular/e2e/playwright.config.ts | 6 +++++- cockpit/chat/messages/angular/e2e/tsconfig.json | 3 ++- cockpit/chat/subagents/angular/e2e/global-setup-impl.ts | 7 +++++-- cockpit/chat/subagents/angular/e2e/playwright.config.ts | 6 +++++- cockpit/chat/subagents/angular/e2e/tsconfig.json | 3 ++- cockpit/chat/theming/angular/e2e/global-setup-impl.ts | 7 +++++-- cockpit/chat/theming/angular/e2e/playwright.config.ts | 6 +++++- cockpit/chat/theming/angular/e2e/tsconfig.json | 3 ++- cockpit/chat/threads/angular/e2e/global-setup-impl.ts | 7 +++++-- cockpit/chat/threads/angular/e2e/playwright.config.ts | 6 +++++- cockpit/chat/threads/angular/e2e/tsconfig.json | 3 ++- cockpit/chat/timeline/angular/e2e/global-setup-impl.ts | 7 +++++-- cockpit/chat/timeline/angular/e2e/playwright.config.ts | 6 +++++- cockpit/chat/timeline/angular/e2e/tsconfig.json | 3 ++- cockpit/chat/tool-calls/angular/e2e/global-setup-impl.ts | 7 +++++-- cockpit/chat/tool-calls/angular/e2e/playwright.config.ts | 6 +++++- cockpit/chat/tool-calls/angular/e2e/tsconfig.json | 3 ++- .../filesystem/angular/e2e/global-setup-impl.ts | 7 +++++-- .../filesystem/angular/e2e/playwright.config.ts | 6 +++++- cockpit/deep-agents/filesystem/angular/e2e/tsconfig.json | 3 ++- .../deep-agents/memory/angular/e2e/global-setup-impl.ts | 7 +++++-- .../deep-agents/memory/angular/e2e/playwright.config.ts | 6 +++++- cockpit/deep-agents/memory/angular/e2e/tsconfig.json | 3 ++- .../deep-agents/planning/angular/e2e/global-setup-impl.ts | 7 +++++-- .../deep-agents/planning/angular/e2e/playwright.config.ts | 6 +++++- cockpit/deep-agents/planning/angular/e2e/tsconfig.json | 3 ++- .../deep-agents/sandboxes/angular/e2e/global-setup-impl.ts | 7 +++++-- .../deep-agents/sandboxes/angular/e2e/playwright.config.ts | 6 +++++- cockpit/deep-agents/sandboxes/angular/e2e/tsconfig.json | 3 ++- .../deep-agents/skills/angular/e2e/global-setup-impl.ts | 7 +++++-- .../deep-agents/skills/angular/e2e/playwright.config.ts | 6 +++++- cockpit/deep-agents/skills/angular/e2e/tsconfig.json | 3 ++- .../deep-agents/subagents/angular/e2e/global-setup-impl.ts | 7 +++++-- .../deep-agents/subagents/angular/e2e/playwright.config.ts | 6 +++++- cockpit/deep-agents/subagents/angular/e2e/tsconfig.json | 3 ++- .../deployment-runtime/angular/e2e/global-setup-impl.ts | 7 +++++-- .../deployment-runtime/angular/e2e/playwright.config.ts | 6 +++++- .../langgraph/deployment-runtime/angular/e2e/tsconfig.json | 3 ++- .../durable-execution/angular/e2e/global-setup-impl.ts | 7 +++++-- .../durable-execution/angular/e2e/playwright.config.ts | 6 +++++- .../langgraph/durable-execution/angular/e2e/tsconfig.json | 3 ++- .../langgraph/interrupts/angular/e2e/global-setup-impl.ts | 7 +++++-- .../langgraph/interrupts/angular/e2e/playwright.config.ts | 6 +++++- cockpit/langgraph/interrupts/angular/e2e/tsconfig.json | 3 ++- cockpit/langgraph/memory/angular/e2e/global-setup-impl.ts | 7 +++++-- cockpit/langgraph/memory/angular/e2e/playwright.config.ts | 6 +++++- cockpit/langgraph/memory/angular/e2e/tsconfig.json | 3 ++- .../langgraph/persistence/angular/e2e/global-setup-impl.ts | 7 +++++-- .../langgraph/persistence/angular/e2e/playwright.config.ts | 6 +++++- cockpit/langgraph/persistence/angular/e2e/tsconfig.json | 3 ++- .../langgraph/streaming/angular/e2e/global-setup-impl.ts | 7 +++++-- .../langgraph/streaming/angular/e2e/playwright.config.ts | 6 +++++- cockpit/langgraph/streaming/angular/e2e/tsconfig.json | 3 ++- .../langgraph/subgraphs/angular/e2e/global-setup-impl.ts | 7 +++++-- .../langgraph/subgraphs/angular/e2e/playwright.config.ts | 6 +++++- cockpit/langgraph/subgraphs/angular/e2e/tsconfig.json | 3 ++- .../langgraph/time-travel/angular/e2e/global-setup-impl.ts | 7 +++++-- .../langgraph/time-travel/angular/e2e/playwright.config.ts | 6 +++++- cockpit/langgraph/time-travel/angular/e2e/tsconfig.json | 3 ++- 72 files changed, 288 insertions(+), 96 deletions(-) diff --git a/cockpit/chat/a2ui/angular/e2e/global-setup-impl.ts b/cockpit/chat/a2ui/angular/e2e/global-setup-impl.ts index 41a60877..e78550e1 100644 --- a/cockpit/chat/a2ui/angular/e2e/global-setup-impl.ts +++ b/cockpit/chat/a2ui/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-chat-a2ui-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/chat/a2ui/python', - langgraphPort: 5511, + langgraphPort: ports.langgraph, angularProject: 'cockpit-chat-a2ui-angular', - angularPort: 4511, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/chat/a2ui/angular/e2e/playwright.config.ts b/cockpit/chat/a2ui/angular/e2e/playwright.config.ts index 29f94703..98fdd40c 100644 --- a/cockpit/chat/a2ui/angular/e2e/playwright.config.ts +++ b/cockpit/chat/a2ui/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-chat-a2ui-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4511', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/chat/a2ui/angular/e2e/tsconfig.json b/cockpit/chat/a2ui/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/chat/a2ui/angular/e2e/tsconfig.json +++ b/cockpit/chat/a2ui/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/chat/generative-ui/angular/e2e/global-setup-impl.ts b/cockpit/chat/generative-ui/angular/e2e/global-setup-impl.ts index 93dbc466..71912bf1 100644 --- a/cockpit/chat/generative-ui/angular/e2e/global-setup-impl.ts +++ b/cockpit/chat/generative-ui/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-chat-generative-ui-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/chat/generative-ui/python', - langgraphPort: 5508, + langgraphPort: ports.langgraph, angularProject: 'cockpit-chat-generative-ui-angular', - angularPort: 4508, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/chat/generative-ui/angular/e2e/playwright.config.ts b/cockpit/chat/generative-ui/angular/e2e/playwright.config.ts index 7c3a63dc..6d16cf2b 100644 --- a/cockpit/chat/generative-ui/angular/e2e/playwright.config.ts +++ b/cockpit/chat/generative-ui/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-chat-generative-ui-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4508', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/chat/generative-ui/angular/e2e/tsconfig.json b/cockpit/chat/generative-ui/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/chat/generative-ui/angular/e2e/tsconfig.json +++ b/cockpit/chat/generative-ui/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/chat/input/angular/e2e/global-setup-impl.ts b/cockpit/chat/input/angular/e2e/global-setup-impl.ts index 81f8ddfc..15a37a1d 100644 --- a/cockpit/chat/input/angular/e2e/global-setup-impl.ts +++ b/cockpit/chat/input/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-chat-input-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/chat/input/python', - langgraphPort: 5502, + langgraphPort: ports.langgraph, angularProject: 'cockpit-chat-input-angular', - angularPort: 4502, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/chat/input/angular/e2e/playwright.config.ts b/cockpit/chat/input/angular/e2e/playwright.config.ts index 63497def..abf3b77b 100644 --- a/cockpit/chat/input/angular/e2e/playwright.config.ts +++ b/cockpit/chat/input/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-chat-input-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4502', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/chat/input/angular/e2e/tsconfig.json b/cockpit/chat/input/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/chat/input/angular/e2e/tsconfig.json +++ b/cockpit/chat/input/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/chat/interrupts/angular/e2e/global-setup-impl.ts b/cockpit/chat/interrupts/angular/e2e/global-setup-impl.ts index 64e1ad06..e22aae67 100644 --- a/cockpit/chat/interrupts/angular/e2e/global-setup-impl.ts +++ b/cockpit/chat/interrupts/angular/e2e/global-setup-impl.ts @@ -1,14 +1,17 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-chat-interrupts-angular'); + export default createGlobalSetup({ // Per-cap cleanup PR: each chat cap runs its OWN standalone backend // (cockpit/chat//python) on ` + 1000`. The // proxy.conf.json target matches. langgraphCwd: 'cockpit/chat/interrupts/python', - langgraphPort: 5503, + langgraphPort: ports.langgraph, angularProject: 'cockpit-chat-interrupts-angular', - angularPort: 4503, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/chat/interrupts/angular/e2e/playwright.config.ts b/cockpit/chat/interrupts/angular/e2e/playwright.config.ts index 5e89f40f..ea4681f2 100644 --- a/cockpit/chat/interrupts/angular/e2e/playwright.config.ts +++ b/cockpit/chat/interrupts/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-chat-interrupts-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4503', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/chat/interrupts/angular/e2e/tsconfig.json b/cockpit/chat/interrupts/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/chat/interrupts/angular/e2e/tsconfig.json +++ b/cockpit/chat/interrupts/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/chat/messages/angular/e2e/global-setup-impl.ts b/cockpit/chat/messages/angular/e2e/global-setup-impl.ts index 3ff48965..0b258b60 100644 --- a/cockpit/chat/messages/angular/e2e/global-setup-impl.ts +++ b/cockpit/chat/messages/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-chat-messages-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/chat/messages/python', - langgraphPort: 5501, + langgraphPort: ports.langgraph, angularProject: 'cockpit-chat-messages-angular', - angularPort: 4501, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/chat/messages/angular/e2e/playwright.config.ts b/cockpit/chat/messages/angular/e2e/playwright.config.ts index d5bba8de..775cafdb 100644 --- a/cockpit/chat/messages/angular/e2e/playwright.config.ts +++ b/cockpit/chat/messages/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-chat-messages-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4501', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/chat/messages/angular/e2e/tsconfig.json b/cockpit/chat/messages/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/chat/messages/angular/e2e/tsconfig.json +++ b/cockpit/chat/messages/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/chat/subagents/angular/e2e/global-setup-impl.ts b/cockpit/chat/subagents/angular/e2e/global-setup-impl.ts index 9c26ff1f..e728c1d8 100644 --- a/cockpit/chat/subagents/angular/e2e/global-setup-impl.ts +++ b/cockpit/chat/subagents/angular/e2e/global-setup-impl.ts @@ -1,14 +1,17 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-chat-subagents-angular'); + export default createGlobalSetup({ // Per-cap cleanup PR: each chat cap runs its OWN standalone backend // (cockpit/chat//python) on ` + 1000`. The // proxy.conf.json target matches. langgraphCwd: 'cockpit/chat/subagents/python', - langgraphPort: 5505, + langgraphPort: ports.langgraph, angularProject: 'cockpit-chat-subagents-angular', - angularPort: 4505, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/chat/subagents/angular/e2e/playwright.config.ts b/cockpit/chat/subagents/angular/e2e/playwright.config.ts index 9900846a..99d19bba 100644 --- a/cockpit/chat/subagents/angular/e2e/playwright.config.ts +++ b/cockpit/chat/subagents/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-chat-subagents-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4505', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/chat/subagents/angular/e2e/tsconfig.json b/cockpit/chat/subagents/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/chat/subagents/angular/e2e/tsconfig.json +++ b/cockpit/chat/subagents/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/chat/theming/angular/e2e/global-setup-impl.ts b/cockpit/chat/theming/angular/e2e/global-setup-impl.ts index 731928b1..091cb280 100644 --- a/cockpit/chat/theming/angular/e2e/global-setup-impl.ts +++ b/cockpit/chat/theming/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-chat-theming-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/chat/theming/python', - langgraphPort: 5510, + langgraphPort: ports.langgraph, angularProject: 'cockpit-chat-theming-angular', - angularPort: 4510, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/chat/theming/angular/e2e/playwright.config.ts b/cockpit/chat/theming/angular/e2e/playwright.config.ts index 34f2d3fd..49d8c008 100644 --- a/cockpit/chat/theming/angular/e2e/playwright.config.ts +++ b/cockpit/chat/theming/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-chat-theming-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4510', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/chat/theming/angular/e2e/tsconfig.json b/cockpit/chat/theming/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/chat/theming/angular/e2e/tsconfig.json +++ b/cockpit/chat/theming/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/chat/threads/angular/e2e/global-setup-impl.ts b/cockpit/chat/threads/angular/e2e/global-setup-impl.ts index 9143ce3e..0f200e9e 100644 --- a/cockpit/chat/threads/angular/e2e/global-setup-impl.ts +++ b/cockpit/chat/threads/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-chat-threads-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/chat/threads/python', - langgraphPort: 5506, + langgraphPort: ports.langgraph, angularProject: 'cockpit-chat-threads-angular', - angularPort: 4506, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/chat/threads/angular/e2e/playwright.config.ts b/cockpit/chat/threads/angular/e2e/playwright.config.ts index 085d8757..5866944f 100644 --- a/cockpit/chat/threads/angular/e2e/playwright.config.ts +++ b/cockpit/chat/threads/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-chat-threads-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4506', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/chat/threads/angular/e2e/tsconfig.json b/cockpit/chat/threads/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/chat/threads/angular/e2e/tsconfig.json +++ b/cockpit/chat/threads/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/chat/timeline/angular/e2e/global-setup-impl.ts b/cockpit/chat/timeline/angular/e2e/global-setup-impl.ts index 14f75dde..91215643 100644 --- a/cockpit/chat/timeline/angular/e2e/global-setup-impl.ts +++ b/cockpit/chat/timeline/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-chat-timeline-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/chat/timeline/python', - langgraphPort: 5507, + langgraphPort: ports.langgraph, angularProject: 'cockpit-chat-timeline-angular', - angularPort: 4507, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/chat/timeline/angular/e2e/playwright.config.ts b/cockpit/chat/timeline/angular/e2e/playwright.config.ts index 153e8626..146ce930 100644 --- a/cockpit/chat/timeline/angular/e2e/playwright.config.ts +++ b/cockpit/chat/timeline/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-chat-timeline-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4507', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/chat/timeline/angular/e2e/tsconfig.json b/cockpit/chat/timeline/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/chat/timeline/angular/e2e/tsconfig.json +++ b/cockpit/chat/timeline/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/chat/tool-calls/angular/e2e/global-setup-impl.ts b/cockpit/chat/tool-calls/angular/e2e/global-setup-impl.ts index 2417204c..6c874191 100644 --- a/cockpit/chat/tool-calls/angular/e2e/global-setup-impl.ts +++ b/cockpit/chat/tool-calls/angular/e2e/global-setup-impl.ts @@ -1,14 +1,17 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-chat-tool-calls-angular'); + export default createGlobalSetup({ // Per-cap cleanup PR: each chat cap runs its OWN standalone backend // (cockpit/chat//python) on ` + 1000`. The // proxy.conf.json target matches. langgraphCwd: 'cockpit/chat/tool-calls/python', - langgraphPort: 5504, + langgraphPort: ports.langgraph, angularProject: 'cockpit-chat-tool-calls-angular', - angularPort: 4504, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/chat/tool-calls/angular/e2e/playwright.config.ts b/cockpit/chat/tool-calls/angular/e2e/playwright.config.ts index 652db126..95c9bbc1 100644 --- a/cockpit/chat/tool-calls/angular/e2e/playwright.config.ts +++ b/cockpit/chat/tool-calls/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-chat-tool-calls-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4504', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/chat/tool-calls/angular/e2e/tsconfig.json b/cockpit/chat/tool-calls/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/chat/tool-calls/angular/e2e/tsconfig.json +++ b/cockpit/chat/tool-calls/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/deep-agents/filesystem/angular/e2e/global-setup-impl.ts b/cockpit/deep-agents/filesystem/angular/e2e/global-setup-impl.ts index 94662c5f..462769b4 100644 --- a/cockpit/deep-agents/filesystem/angular/e2e/global-setup-impl.ts +++ b/cockpit/deep-agents/filesystem/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-deep-agents-filesystem-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/deep-agents/filesystem/python', - langgraphPort: 5311, + langgraphPort: ports.langgraph, angularProject: 'cockpit-deep-agents-filesystem-angular', - angularPort: 4311, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/deep-agents/filesystem/angular/e2e/playwright.config.ts b/cockpit/deep-agents/filesystem/angular/e2e/playwright.config.ts index 97265149..849d51d2 100644 --- a/cockpit/deep-agents/filesystem/angular/e2e/playwright.config.ts +++ b/cockpit/deep-agents/filesystem/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-deep-agents-filesystem-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4311', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/deep-agents/filesystem/angular/e2e/tsconfig.json b/cockpit/deep-agents/filesystem/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/deep-agents/filesystem/angular/e2e/tsconfig.json +++ b/cockpit/deep-agents/filesystem/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/deep-agents/memory/angular/e2e/global-setup-impl.ts b/cockpit/deep-agents/memory/angular/e2e/global-setup-impl.ts index 6aa7347d..4f9df91a 100644 --- a/cockpit/deep-agents/memory/angular/e2e/global-setup-impl.ts +++ b/cockpit/deep-agents/memory/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-deep-agents-memory-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/deep-agents/memory/python', - langgraphPort: 5313, + langgraphPort: ports.langgraph, angularProject: 'cockpit-deep-agents-memory-angular', - angularPort: 4313, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/deep-agents/memory/angular/e2e/playwright.config.ts b/cockpit/deep-agents/memory/angular/e2e/playwright.config.ts index 08bdb31b..69c20b8e 100644 --- a/cockpit/deep-agents/memory/angular/e2e/playwright.config.ts +++ b/cockpit/deep-agents/memory/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-deep-agents-memory-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4313', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/deep-agents/memory/angular/e2e/tsconfig.json b/cockpit/deep-agents/memory/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/deep-agents/memory/angular/e2e/tsconfig.json +++ b/cockpit/deep-agents/memory/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/deep-agents/planning/angular/e2e/global-setup-impl.ts b/cockpit/deep-agents/planning/angular/e2e/global-setup-impl.ts index 80842a40..20f44669 100644 --- a/cockpit/deep-agents/planning/angular/e2e/global-setup-impl.ts +++ b/cockpit/deep-agents/planning/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-deep-agents-planning-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/deep-agents/planning/python', - langgraphPort: 5310, + langgraphPort: ports.langgraph, angularProject: 'cockpit-deep-agents-planning-angular', - angularPort: 4310, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/deep-agents/planning/angular/e2e/playwright.config.ts b/cockpit/deep-agents/planning/angular/e2e/playwright.config.ts index 976b8246..ad2a9ce8 100644 --- a/cockpit/deep-agents/planning/angular/e2e/playwright.config.ts +++ b/cockpit/deep-agents/planning/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-deep-agents-planning-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4310', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/deep-agents/planning/angular/e2e/tsconfig.json b/cockpit/deep-agents/planning/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/deep-agents/planning/angular/e2e/tsconfig.json +++ b/cockpit/deep-agents/planning/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/deep-agents/sandboxes/angular/e2e/global-setup-impl.ts b/cockpit/deep-agents/sandboxes/angular/e2e/global-setup-impl.ts index a3fe7c6a..447a8d3a 100644 --- a/cockpit/deep-agents/sandboxes/angular/e2e/global-setup-impl.ts +++ b/cockpit/deep-agents/sandboxes/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-deep-agents-sandboxes-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/deep-agents/sandboxes/python', - langgraphPort: 5315, + langgraphPort: ports.langgraph, angularProject: 'cockpit-deep-agents-sandboxes-angular', - angularPort: 4315, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/deep-agents/sandboxes/angular/e2e/playwright.config.ts b/cockpit/deep-agents/sandboxes/angular/e2e/playwright.config.ts index 2f07e56c..3c4ef9ac 100644 --- a/cockpit/deep-agents/sandboxes/angular/e2e/playwright.config.ts +++ b/cockpit/deep-agents/sandboxes/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-deep-agents-sandboxes-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4315', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/deep-agents/sandboxes/angular/e2e/tsconfig.json b/cockpit/deep-agents/sandboxes/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/deep-agents/sandboxes/angular/e2e/tsconfig.json +++ b/cockpit/deep-agents/sandboxes/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/deep-agents/skills/angular/e2e/global-setup-impl.ts b/cockpit/deep-agents/skills/angular/e2e/global-setup-impl.ts index fed786b4..905e31f3 100644 --- a/cockpit/deep-agents/skills/angular/e2e/global-setup-impl.ts +++ b/cockpit/deep-agents/skills/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-deep-agents-skills-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/deep-agents/skills/python', - langgraphPort: 5314, + langgraphPort: ports.langgraph, angularProject: 'cockpit-deep-agents-skills-angular', - angularPort: 4314, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/deep-agents/skills/angular/e2e/playwright.config.ts b/cockpit/deep-agents/skills/angular/e2e/playwright.config.ts index 25431600..253626e7 100644 --- a/cockpit/deep-agents/skills/angular/e2e/playwright.config.ts +++ b/cockpit/deep-agents/skills/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-deep-agents-skills-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4314', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/deep-agents/skills/angular/e2e/tsconfig.json b/cockpit/deep-agents/skills/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/deep-agents/skills/angular/e2e/tsconfig.json +++ b/cockpit/deep-agents/skills/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/deep-agents/subagents/angular/e2e/global-setup-impl.ts b/cockpit/deep-agents/subagents/angular/e2e/global-setup-impl.ts index ebbd93b8..d73b63b0 100644 --- a/cockpit/deep-agents/subagents/angular/e2e/global-setup-impl.ts +++ b/cockpit/deep-agents/subagents/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-deep-agents-subagents-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/deep-agents/subagents/python', - langgraphPort: 5312, + langgraphPort: ports.langgraph, angularProject: 'cockpit-deep-agents-subagents-angular', - angularPort: 4312, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/deep-agents/subagents/angular/e2e/playwright.config.ts b/cockpit/deep-agents/subagents/angular/e2e/playwright.config.ts index b94680ee..8a517927 100644 --- a/cockpit/deep-agents/subagents/angular/e2e/playwright.config.ts +++ b/cockpit/deep-agents/subagents/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-deep-agents-subagents-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4312', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/deep-agents/subagents/angular/e2e/tsconfig.json b/cockpit/deep-agents/subagents/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/deep-agents/subagents/angular/e2e/tsconfig.json +++ b/cockpit/deep-agents/subagents/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/langgraph/deployment-runtime/angular/e2e/global-setup-impl.ts b/cockpit/langgraph/deployment-runtime/angular/e2e/global-setup-impl.ts index 57a1b9af..59106268 100644 --- a/cockpit/langgraph/deployment-runtime/angular/e2e/global-setup-impl.ts +++ b/cockpit/langgraph/deployment-runtime/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-langgraph-deployment-runtime-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/langgraph/deployment-runtime/python', - langgraphPort: 5307, + langgraphPort: ports.langgraph, angularProject: 'cockpit-langgraph-deployment-runtime-angular', - angularPort: 4307, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/langgraph/deployment-runtime/angular/e2e/playwright.config.ts b/cockpit/langgraph/deployment-runtime/angular/e2e/playwright.config.ts index cee41f1a..af505399 100644 --- a/cockpit/langgraph/deployment-runtime/angular/e2e/playwright.config.ts +++ b/cockpit/langgraph/deployment-runtime/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-langgraph-deployment-runtime-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4307', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/langgraph/deployment-runtime/angular/e2e/tsconfig.json b/cockpit/langgraph/deployment-runtime/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/langgraph/deployment-runtime/angular/e2e/tsconfig.json +++ b/cockpit/langgraph/deployment-runtime/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/langgraph/durable-execution/angular/e2e/global-setup-impl.ts b/cockpit/langgraph/durable-execution/angular/e2e/global-setup-impl.ts index c8246e7b..5f88553c 100644 --- a/cockpit/langgraph/durable-execution/angular/e2e/global-setup-impl.ts +++ b/cockpit/langgraph/durable-execution/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-langgraph-durable-execution-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/langgraph/durable-execution/python', - langgraphPort: 5304, + langgraphPort: ports.langgraph, angularProject: 'cockpit-langgraph-durable-execution-angular', - angularPort: 4304, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/langgraph/durable-execution/angular/e2e/playwright.config.ts b/cockpit/langgraph/durable-execution/angular/e2e/playwright.config.ts index 52f41a3d..b7bcbee4 100644 --- a/cockpit/langgraph/durable-execution/angular/e2e/playwright.config.ts +++ b/cockpit/langgraph/durable-execution/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-langgraph-durable-execution-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4304', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/langgraph/durable-execution/angular/e2e/tsconfig.json b/cockpit/langgraph/durable-execution/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/langgraph/durable-execution/angular/e2e/tsconfig.json +++ b/cockpit/langgraph/durable-execution/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/langgraph/interrupts/angular/e2e/global-setup-impl.ts b/cockpit/langgraph/interrupts/angular/e2e/global-setup-impl.ts index 1dea7dce..269db575 100644 --- a/cockpit/langgraph/interrupts/angular/e2e/global-setup-impl.ts +++ b/cockpit/langgraph/interrupts/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-langgraph-interrupts-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/langgraph/interrupts/python', - langgraphPort: 5302, + langgraphPort: ports.langgraph, angularProject: 'cockpit-langgraph-interrupts-angular', - angularPort: 4302, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/langgraph/interrupts/angular/e2e/playwright.config.ts b/cockpit/langgraph/interrupts/angular/e2e/playwright.config.ts index 611ac2c4..f537f339 100644 --- a/cockpit/langgraph/interrupts/angular/e2e/playwright.config.ts +++ b/cockpit/langgraph/interrupts/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-langgraph-interrupts-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4302', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/langgraph/interrupts/angular/e2e/tsconfig.json b/cockpit/langgraph/interrupts/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/langgraph/interrupts/angular/e2e/tsconfig.json +++ b/cockpit/langgraph/interrupts/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/langgraph/memory/angular/e2e/global-setup-impl.ts b/cockpit/langgraph/memory/angular/e2e/global-setup-impl.ts index 18cfb232..ae4c04a9 100644 --- a/cockpit/langgraph/memory/angular/e2e/global-setup-impl.ts +++ b/cockpit/langgraph/memory/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-langgraph-memory-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/langgraph/memory/python', - langgraphPort: 5303, + langgraphPort: ports.langgraph, angularProject: 'cockpit-langgraph-memory-angular', - angularPort: 4303, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/langgraph/memory/angular/e2e/playwright.config.ts b/cockpit/langgraph/memory/angular/e2e/playwright.config.ts index c9ac8499..20291927 100644 --- a/cockpit/langgraph/memory/angular/e2e/playwright.config.ts +++ b/cockpit/langgraph/memory/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-langgraph-memory-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4303', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/langgraph/memory/angular/e2e/tsconfig.json b/cockpit/langgraph/memory/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/langgraph/memory/angular/e2e/tsconfig.json +++ b/cockpit/langgraph/memory/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/langgraph/persistence/angular/e2e/global-setup-impl.ts b/cockpit/langgraph/persistence/angular/e2e/global-setup-impl.ts index 3d5dc594..f5dd3efd 100644 --- a/cockpit/langgraph/persistence/angular/e2e/global-setup-impl.ts +++ b/cockpit/langgraph/persistence/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-langgraph-persistence-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/langgraph/persistence/python', - langgraphPort: 5301, + langgraphPort: ports.langgraph, angularProject: 'cockpit-langgraph-persistence-angular', - angularPort: 4301, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/langgraph/persistence/angular/e2e/playwright.config.ts b/cockpit/langgraph/persistence/angular/e2e/playwright.config.ts index 0f924be4..adc041c0 100644 --- a/cockpit/langgraph/persistence/angular/e2e/playwright.config.ts +++ b/cockpit/langgraph/persistence/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-langgraph-persistence-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4301', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/langgraph/persistence/angular/e2e/tsconfig.json b/cockpit/langgraph/persistence/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/langgraph/persistence/angular/e2e/tsconfig.json +++ b/cockpit/langgraph/persistence/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/langgraph/streaming/angular/e2e/global-setup-impl.ts b/cockpit/langgraph/streaming/angular/e2e/global-setup-impl.ts index f8c7eda2..4e91554b 100644 --- a/cockpit/langgraph/streaming/angular/e2e/global-setup-impl.ts +++ b/cockpit/langgraph/streaming/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-langgraph-streaming-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/langgraph/streaming/python', - langgraphPort: 5300, + langgraphPort: ports.langgraph, angularProject: 'cockpit-langgraph-streaming-angular', - angularPort: 4300, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/langgraph/streaming/angular/e2e/playwright.config.ts b/cockpit/langgraph/streaming/angular/e2e/playwright.config.ts index 9592e1d7..bffbc6bd 100644 --- a/cockpit/langgraph/streaming/angular/e2e/playwright.config.ts +++ b/cockpit/langgraph/streaming/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-langgraph-streaming-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4300', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/langgraph/streaming/angular/e2e/tsconfig.json b/cockpit/langgraph/streaming/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/langgraph/streaming/angular/e2e/tsconfig.json +++ b/cockpit/langgraph/streaming/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/langgraph/subgraphs/angular/e2e/global-setup-impl.ts b/cockpit/langgraph/subgraphs/angular/e2e/global-setup-impl.ts index a0b3354a..165fa724 100644 --- a/cockpit/langgraph/subgraphs/angular/e2e/global-setup-impl.ts +++ b/cockpit/langgraph/subgraphs/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-langgraph-subgraphs-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/langgraph/subgraphs/python', - langgraphPort: 5305, + langgraphPort: ports.langgraph, angularProject: 'cockpit-langgraph-subgraphs-angular', - angularPort: 4305, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/langgraph/subgraphs/angular/e2e/playwright.config.ts b/cockpit/langgraph/subgraphs/angular/e2e/playwright.config.ts index 1c8f5a8e..3fdd3bde 100644 --- a/cockpit/langgraph/subgraphs/angular/e2e/playwright.config.ts +++ b/cockpit/langgraph/subgraphs/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-langgraph-subgraphs-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4305', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/langgraph/subgraphs/angular/e2e/tsconfig.json b/cockpit/langgraph/subgraphs/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/langgraph/subgraphs/angular/e2e/tsconfig.json +++ b/cockpit/langgraph/subgraphs/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" diff --git a/cockpit/langgraph/time-travel/angular/e2e/global-setup-impl.ts b/cockpit/langgraph/time-travel/angular/e2e/global-setup-impl.ts index afa1e1f0..b14724a1 100644 --- a/cockpit/langgraph/time-travel/angular/e2e/global-setup-impl.ts +++ b/cockpit/langgraph/time-travel/angular/e2e/global-setup-impl.ts @@ -1,11 +1,14 @@ // SPDX-License-Identifier: MIT import { resolve } from 'node:path'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; import { createGlobalSetup } from '@threadplane-internal/e2e-harness'; +const ports = portsFor('cockpit-langgraph-time-travel-angular'); + export default createGlobalSetup({ langgraphCwd: 'cockpit/langgraph/time-travel/python', - langgraphPort: 5306, + langgraphPort: ports.langgraph, angularProject: 'cockpit-langgraph-time-travel-angular', - angularPort: 4306, + angularPort: ports.angular, fixturesDir: resolve(__dirname, 'fixtures'), }); diff --git a/cockpit/langgraph/time-travel/angular/e2e/playwright.config.ts b/cockpit/langgraph/time-travel/angular/e2e/playwright.config.ts index dfb767b2..9ac001ee 100644 --- a/cockpit/langgraph/time-travel/angular/e2e/playwright.config.ts +++ b/cockpit/langgraph/time-travel/angular/e2e/playwright.config.ts @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MIT import { defineConfig, devices } from '@playwright/test'; +import { portsFor } from '../../../../../cockpit/ports.mjs'; + +const { angular: angularPort } = portsFor('cockpit-langgraph-time-travel-angular'); + export default defineConfig({ testDir: '.', @@ -9,7 +13,7 @@ export default defineConfig({ retries: process.env.CI ? 2 : 0, reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', use: { - baseURL: 'http://localhost:4306', + baseURL: `http://localhost:${angularPort}`, trace: 'retain-on-failure', }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], diff --git a/cockpit/langgraph/time-travel/angular/e2e/tsconfig.json b/cockpit/langgraph/time-travel/angular/e2e/tsconfig.json index 2c6356fc..0fc9befb 100644 --- a/cockpit/langgraph/time-travel/angular/e2e/tsconfig.json +++ b/cockpit/langgraph/time-travel/angular/e2e/tsconfig.json @@ -18,7 +18,8 @@ "@threadplane-internal/e2e-harness/global-teardown": [ "libs/e2e-harness/src/global-teardown.ts" ] - } + }, + "allowJs": true }, "include": [ "**/*.ts" From cbb50d6c45f97e9e7c1a79cc726d826f89fd2f64 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Wed, 27 May 2026 14:58:17 -0700 Subject: [PATCH 8/9] ci: gate cockpit-ports.spec.mjs in ci-scope test job Appends the new verifier spec to the existing node --test invocation so registry drift is caught at PR time. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83ed6660..2602a928 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,7 @@ jobs: # classifier walk. - run: npm ci - name: Test CI scope classifier - run: node --test scripts/ci-scope.spec.mjs scripts/cockpit-matrix.spec.mjs + run: node --test scripts/ci-scope.spec.mjs scripts/cockpit-matrix.spec.mjs scripts/cockpit-ports.spec.mjs - name: Detect changed CI surfaces id: scope run: | From 53360f3413e8f39929d2c2ac7cdcf9b388821514 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Wed, 27 May 2026 15:58:26 -0700 Subject: [PATCH 9/9] test(cockpit): wiring spec reads ports from registry; recognizes .mjs proxy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The drift-guard test previously parsed proxy.conf.json target + the literal langgraphPort/angularPort lines in global-setup-impl.ts. Both were removed by the port-registry migration: - proxy.conf.json → proxy.conf.mjs (templates target from registry) - global-setup-impl.ts now reads `ports.langgraph` / `ports.angular` Updated wiring spec: - Imports `portsFor` from cockpit/ports.mjs to look up expected ports by project name. Falls back to literal parsing for the ag-ui exception (not in registry). - Replaces the proxy.conf.json content assertion with a proxy.conf.mjs existence + `portsFor('')` call check. Drift is impossible because the .mjs templates from the same registry. - Legacy proxy.conf.json branch retained for ag-ui (single-cap exception). 79/79 cockpit unit tests pass locally. --- apps/cockpit/cockpit-e2e-wiring.spec.ts | 47 +++++++++++++++++++------ 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/apps/cockpit/cockpit-e2e-wiring.spec.ts b/apps/cockpit/cockpit-e2e-wiring.spec.ts index e464b0c2..d5a71ea4 100644 --- a/apps/cockpit/cockpit-e2e-wiring.spec.ts +++ b/apps/cockpit/cockpit-e2e-wiring.spec.ts @@ -2,6 +2,9 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs'; import { dirname, join, relative, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { capabilities } from './scripts/capability-registry'; +// @ts-expect-error — .mjs ES module without .d.ts; the e2e tsconfig uses +// allowJs:true but this top-level test file doesn't go through that config. +import { portsFor } from '../../cockpit/ports.mjs'; interface E2eWiring { angularPort: number; @@ -84,12 +87,23 @@ function activeCockpitE2eWiring(): E2eWiring[] { const projectRoot = dirname(projectJsonPath); const globalSetupPath = join(projectRoot, 'e2e/global-setup-impl.ts'); const globalSetup = readFileSync(globalSetupPath, 'utf8'); - const proxyPath = join(projectRoot, 'proxy.conf.json'); - const proxy = JSON.parse(readFileSync(proxyPath, 'utf8')) as Record; - const proxyPort = Number(proxy['/api']?.target?.match(/:(\d+)$/)?.[1]); const langgraphCwd = parseStringProperty(globalSetup, 'langgraphCwd'); - const langgraphPort = parseNumberProperty(globalSetup, 'langgraphPort') ?? proxyPort; - const angularPort = parseNumberProperty(globalSetup, 'angularPort'); + + // Post-port-registry migration: ports are imported from + // cockpit/ports.mjs rather than living as literals in + // global-setup-impl.ts. Look them up by project name. + let langgraphPort: number | undefined; + let angularPort: number | undefined; + try { + const ports = portsFor(project.name) as { angular: number; langgraph: number }; + langgraphPort = ports.langgraph; + angularPort = ports.angular; + } catch { + // Cap not in registry (e.g. cockpit-ag-ui-streaming-angular). + // Fall back to parsing literals if global-setup still has them. + langgraphPort = parseNumberProperty(globalSetup, 'langgraphPort'); + angularPort = parseNumberProperty(globalSetup, 'angularPort'); + } if (!project.name || !langgraphCwd || !langgraphPort || !angularPort) { throw new Error(`Unable to parse e2e wiring for ${relative(repoRoot, projectJsonPath)}`); @@ -153,16 +167,29 @@ describe('cockpit e2e wiring', () => { errors.push(`${wiring.project}: registry pythonDir ${capability.pythonDir} != global setup langgraphCwd ${wiring.langgraphCwd}`); } - const proxyPath = join(wiring.projectRoot, 'proxy.conf.json'); - if (!existsSync(proxyPath)) { - errors.push(`${wiring.project}: missing proxy.conf.json`); - } else { - const proxy = JSON.parse(readFileSync(proxyPath, 'utf8')) as Record; + // Post-port-registry: proxy.conf.mjs templates the target from + // cockpit/ports.mjs at runtime. Drift is impossible because the + // value comes from the same registry the test already checks via + // wiring.langgraphPort. So we just assert the .mjs file exists + + // imports portsFor with this cap's name. + const proxyMjs = join(wiring.projectRoot, 'proxy.conf.mjs'); + const proxyJson = join(wiring.projectRoot, 'proxy.conf.json'); + if (existsSync(proxyMjs)) { + const text = readFileSync(proxyMjs, 'utf8'); + if (!text.includes(`portsFor('${wiring.project}')`)) { + errors.push(`${wiring.project}: proxy.conf.mjs does not call portsFor('${wiring.project}')`); + } + } else if (existsSync(proxyJson)) { + // Legacy (allowed for ag-ui exception only); not expected for any + // cap reaching this code path. + const proxy = JSON.parse(readFileSync(proxyJson, 'utf8')) as Record; const target = proxy['/api']?.target; const expectedTarget = `http://localhost:${wiring.langgraphPort}`; if (target !== expectedTarget) { errors.push(`${wiring.project}: proxy target ${target} != ${expectedTarget}`); } + } else { + errors.push(`${wiring.project}: missing proxy.conf (no .mjs or .json)`); } const scriptsDir = join(wiring.projectRoot, 'e2e/scripts');