Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion apps/website/src/lib/analytics/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,14 @@ export type CtaId =
// MediumSwitcher derives ids from section id + medium key at runtime
| `medium_${string}`;

export type AnalyticsLibrary = 'langgraph' | 'render' | 'chat' | 'ag-ui' | 'unknown';
export type AnalyticsLibrary =
| 'langgraph'
| 'render'
| 'chat'
| 'ag-ui'
| 'deep-agents'
| 'runtimes'
| 'unknown';

export type WhitepaperId = 'overview' | 'angular' | 'render' | 'chat';

Expand Down
132 changes: 131 additions & 1 deletion apps/website/src/lib/cockpit-links.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { cockpitManifest } from '@threadplane/cockpit-registry';
import { COCKPIT_DOCS_LINKS, cockpitManifest } from '@threadplane/cockpit-registry';
import { describe, expect, it } from 'vitest';
import { findDocsPage } from './docs-config';
import {
buildCockpitHandoffProperties,
buildCockpitModeHref,
Expand All @@ -10,6 +11,54 @@ import {
describe('Docs-to-Cockpit links', () => {
it('contains the exhaustive first-iteration mapping set', () => {
expect(docsCockpitMappings).toEqual({
'deep-agents/getting-started/introduction': {
product: 'deep-agents', section: 'getting-started', topic: 'overview', page: 'overview', language: 'python',
},
'deep-agents/capabilities/planning': {
product: 'deep-agents', section: 'core-capabilities', topic: 'planning', page: 'overview', language: 'python',
},
'deep-agents/capabilities/filesystem': {
product: 'deep-agents', section: 'core-capabilities', topic: 'filesystem', page: 'overview', language: 'python',
},
'deep-agents/capabilities/subagents': {
product: 'deep-agents', section: 'core-capabilities', topic: 'subagents', page: 'overview', language: 'python',
},
'deep-agents/capabilities/memory': {
product: 'deep-agents', section: 'core-capabilities', topic: 'memory', page: 'overview', language: 'python',
},
'deep-agents/capabilities/skills': {
product: 'deep-agents', section: 'core-capabilities', topic: 'skills', page: 'overview', language: 'python',
},
'runtimes/getting-started/introduction': {
product: 'runtimes', section: 'getting-started', topic: 'overview', page: 'overview', language: 'python',
},
'runtimes/aws-strands/overview': {
product: 'runtimes', section: 'core-capabilities', topic: 'aws-strands', page: 'overview', language: 'python',
},
'runtimes/aws-strands/quickstart': {
product: 'runtimes', section: 'core-capabilities', topic: 'aws-strands', page: 'overview', language: 'python',
},
'runtimes/aws-strands/how-it-connects': {
product: 'runtimes', section: 'core-capabilities', topic: 'aws-strands', page: 'overview', language: 'python',
},
'runtimes/microsoft-agent-framework/overview': {
product: 'runtimes', section: 'core-capabilities', topic: 'microsoft-agent-framework', page: 'overview', language: 'python',
},
'runtimes/microsoft-agent-framework/quickstart': {
product: 'runtimes', section: 'core-capabilities', topic: 'microsoft-agent-framework', page: 'overview', language: 'python',
},
'runtimes/microsoft-agent-framework/how-it-connects': {
product: 'runtimes', section: 'core-capabilities', topic: 'microsoft-agent-framework', page: 'overview', language: 'python',
},
'runtimes/mastra/overview': {
product: 'runtimes', section: 'core-capabilities', topic: 'mastra', page: 'overview', language: 'python',
},
'runtimes/mastra/quickstart': {
product: 'runtimes', section: 'core-capabilities', topic: 'mastra', page: 'overview', language: 'python',
},
'runtimes/mastra/how-it-connects': {
product: 'runtimes', section: 'core-capabilities', topic: 'mastra', page: 'overview', language: 'python',
},
'langgraph/guides/streaming': {
product: 'langgraph', section: 'core-capabilities', topic: 'streaming', page: 'overview', language: 'python',
},
Expand Down Expand Up @@ -124,4 +173,85 @@ describe('Docs-to-Cockpit links', () => {
)).toBe(true);
}
});

// A typo'd key is invisible at runtime: the page just never resolves and the
// reader silently keeps the Cockpit-home fallback. Pin the keys to the real
// content tree so a typo (or a docs rename) fails here instead.
it('keys every mapping to a docs page that exists', () => {
for (const key of Object.keys(docsCockpitMappings)) {
const [library, section, slug] = key.split('/');
expect(findDocsPage(library, section, slug), key).toBeDefined();
}
});

// The two directions are separate tables in separate packages. Where the
// Cockpit side already points at a docs page, that page must point back at
// the same capability, or the round trip lands somewhere else.
it('round-trips the deep-agents and runtimes links back to their capability', () => {
const forward = Object.entries(COCKPIT_DOCS_LINKS).filter(([key]) =>
key.startsWith('deep-agents/') || key.startsWith('runtimes/'),
);
expect(forward).toHaveLength(10);

for (const [key, docsPath] of forward) {
const [product, section, topic] = key.split('/');
const [library, docsSection, slug] = docsPath.replace('/docs/', '').split('/');

expect(resolveCockpitIdentity(library, docsSection, slug), key).toEqual(
expect.objectContaining({ product, section, topic }),
);
}
});

it('reports deep-agents and runtimes as themselves, not unknown', () => {
expect(
buildCockpitHandoffProperties(
{ library: 'deep-agents', section: 'capabilities', slug: 'planning' },
'Run',
),
).toEqual({
library: 'deep-agents',
source_section: 'capabilities',
source_slug: 'planning',
destination_product: 'deep-agents',
destination_capability: 'planning',
requested_mode: 'run',
mapped: true,
});

expect(
buildCockpitHandoffProperties(
{ library: 'runtimes', section: 'mastra', slug: 'quickstart' },
'Code',
).library,
).toBe('runtimes');
});

// Every page of a runtime's docs section shares that runtime's one demo, so
// a reader on the quickstart gets the same handoff as one on the overview.
it('sends every page of a runtime section to that runtime demo', () => {
for (const slug of ['overview', 'quickstart', 'how-it-connects']) {
expect(
buildCockpitModeHref(
{ library: 'runtimes', section: 'aws-strands', slug },
'Run',
'https://cockpit.example',
),
).toBe(
'https://cockpit.example/runtimes/core-capabilities/aws-strands/overview/python?mode=run',
);
}
});

it('sends a deep-agents capability page to its capability demo', () => {
expect(
buildCockpitModeHref(
{ library: 'deep-agents', section: 'capabilities', slug: 'skills' },
'Code',
'https://cockpit.example',
),
).toBe(
'https://cockpit.example/deep-agents/core-capabilities/skills/overview/python?mode=code',
);
});
});
144 changes: 144 additions & 0 deletions apps/website/src/lib/cockpit-links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,149 @@ export interface DocsIdentity {
export const COCKPIT_ENVIRONMENT_LABEL =
process.env.NEXT_PUBLIC_COCKPIT_ENVIRONMENT_LABEL ?? 'Shared development';

/**
* Documentation page -> Cockpit capability (the reverse of
* `COCKPIT_DOCS_LINKS` in `@threadplane/cockpit-registry`).
*
* Keyed by `${library}/${section}/${slug}` — the three segments of the docs
* route, `/docs/<library>/<section>/<slug>`. Values are a full Cockpit
* identity, because the Cockpit route carries five segments; the extra two are
* fixed (`page: 'overview'`, `language: 'python'`) for every manifest entry
* today, so they are written out rather than derived.
*
* Rules for this table:
*
* - An unmapped page is not an error. `resolveCockpitIdentity` returns null and
* the control plane sends the reader to Cockpit home instead of guessing a
* URL — the five-segment formula 404s for pages that have no demo.
* - Several docs pages may share one Cockpit target. The runtimes library
* documents each runtime across three pages (overview, quickstart,
* how-it-connects) that one demo serves equally well.
* - An `introduction` maps to its product's `getting-started/overview` entry.
* Those entries are `entryKind: 'docs-only'` in the manifest, so Run mode
* lands on the product's Cockpit overview rather than a live demo — still a
* better destination than Cockpit home, and it keeps the Capability row
* truthful.
* - The spec pins this object exactly and cross-checks every target against
* `cockpitManifest`, so a Cockpit topic rename breaks the test rather than
* the link.
*/
export const docsCockpitMappings = {
'deep-agents/getting-started/introduction': {
product: 'deep-agents',
section: 'getting-started',
topic: 'overview',
page: 'overview',
language: 'python',
},
'deep-agents/capabilities/planning': {
product: 'deep-agents',
section: 'core-capabilities',
topic: 'planning',
page: 'overview',
language: 'python',
},
'deep-agents/capabilities/filesystem': {
product: 'deep-agents',
section: 'core-capabilities',
topic: 'filesystem',
page: 'overview',
language: 'python',
},
'deep-agents/capabilities/subagents': {
product: 'deep-agents',
section: 'core-capabilities',
topic: 'subagents',
page: 'overview',
language: 'python',
},
'deep-agents/capabilities/memory': {
product: 'deep-agents',
section: 'core-capabilities',
topic: 'memory',
page: 'overview',
language: 'python',
},
'deep-agents/capabilities/skills': {
product: 'deep-agents',
section: 'core-capabilities',
topic: 'skills',
page: 'overview',
language: 'python',
},
'runtimes/getting-started/introduction': {
product: 'runtimes',
section: 'getting-started',
topic: 'overview',
page: 'overview',
language: 'python',
},
'runtimes/aws-strands/overview': {
product: 'runtimes',
section: 'core-capabilities',
topic: 'aws-strands',
page: 'overview',
language: 'python',
},
'runtimes/aws-strands/quickstart': {
product: 'runtimes',
section: 'core-capabilities',
topic: 'aws-strands',
page: 'overview',
language: 'python',
},
'runtimes/aws-strands/how-it-connects': {
product: 'runtimes',
section: 'core-capabilities',
topic: 'aws-strands',
page: 'overview',
language: 'python',
},
'runtimes/microsoft-agent-framework/overview': {
product: 'runtimes',
section: 'core-capabilities',
topic: 'microsoft-agent-framework',
page: 'overview',
language: 'python',
},
'runtimes/microsoft-agent-framework/quickstart': {
product: 'runtimes',
section: 'core-capabilities',
topic: 'microsoft-agent-framework',
page: 'overview',
language: 'python',
},
'runtimes/microsoft-agent-framework/how-it-connects': {
product: 'runtimes',
section: 'core-capabilities',
topic: 'microsoft-agent-framework',
page: 'overview',
language: 'python',
},
// The Mastra demo's backend is a Node AG-UI service, but the Cockpit route
// is `python` like every other manifest entry — the language segment names
// the Cockpit lane, not the runtime.
'runtimes/mastra/overview': {
product: 'runtimes',
section: 'core-capabilities',
topic: 'mastra',
page: 'overview',
language: 'python',
},
'runtimes/mastra/quickstart': {
product: 'runtimes',
section: 'core-capabilities',
topic: 'mastra',
page: 'overview',
language: 'python',
},
'runtimes/mastra/how-it-connects': {
product: 'runtimes',
section: 'core-capabilities',
topic: 'mastra',
page: 'overview',
language: 'python',
},
'langgraph/guides/streaming': {
product: 'langgraph',
section: 'core-capabilities',
Expand Down Expand Up @@ -77,6 +219,8 @@ const toAnalyticsLibrary = (library: string): AnalyticsLibrary => {
case 'render':
case 'chat':
case 'ag-ui':
case 'deep-agents':
case 'runtimes':
return library;
default:
return 'unknown';
Expand Down
Loading