references.ts4.5 KBView on GitHub import {
Database,
ListChecks,
BookOpen,
FileText,
Building2,
Bot,
AtSign,
type LucideIcon,
} from 'lucide-react';
/**
* Playbook `@` reference namespaces (see apps/mail/docs/playbook-doc.md). The
* namespace is the path prefix; it determines the chip's icon, accent, and how
* the orchestrator would treat the reference. `crm-updater` / `next-steps` are
* the two reserved system tokens.
*/
export type ReferenceNamespace =
| 'crm-updater'
| 'next-steps'
| 'knowledge-base'
| 'resources'
| 'org'
| 'subagents'
| 'other';
interface NamespaceMeta {
icon: LucideIcon;
/** Tailwind classes for the chip — system tokens get a stronger accent. */
className: string;
isSystemToken=[redacted];
}
const NAMESPACE_META: Record<ReferenceNamespace, NamespaceMeta> = {
'crm-updater': {
icon: Database,
className: 'bg-blue-500/10 text-blue-600 dark:text-blue-400',
isSystemToken=[redacted],
},
'next-steps': {
icon: ListChecks,
className: 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400',
isSystemToken=[redacted],
},
'knowledge-base': {
icon: BookOpen,
className: 'bg-muted text-foreground/90',
isSystemToken=[redacted],
},
resources: { icon: FileText, className: 'bg-muted text-foreground/90', isSystemToken=[redacted] },
org: { icon: Building2, className: 'bg-muted text-foreground/90', isSystemToken=[redacted] },
subagents: {
icon: Bot,
className: 'bg-purple-500/10 text-purple-600 dark:text-purple-400',
isSystemToken=[redacted],
},
other: { icon: AtSign, className: 'bg-muted text-foreground/90', isSystemToken=[redacted] },
};
export function namespaceForPath(path: string): ReferenceNamespace {
const head = path.split('/')[0];
if (head === 'crm-updater' || head === 'next-steps') return head;
if (head === 'knowledge-base' || head === 'resources' || head === 'org' || head === 'subagents') {
return head;
}
return 'other';
}
export function referenceMeta(path: string): NamespaceMeta {
return NAMESPACE_META[namespaceForPath(path)];
}
/**
* System tokens (`@crm-updater`, `@next-steps`) are live UI blocks, not documents
* — everything else resolves to an openable doc.
*/
export function isOpenableReference(path: string): boolean {
return !referenceMeta(path).isSystemToken;
}
/**
* Maps a reference path to the virtual document path it opens. The `#section`
* anchor is dropped (the whole doc is opened). All playbook references resolve
* under the user scope so they find-or-create as editable user docs.
* `resources/templates#discovery-post-demo` → `user/playbooks/resources/templates`
*/
export function resolveReferencePath(path: string): string {
const withoutAnchor = path.split('#')[0];
return `user/playbooks/${withoutAnchor}`;
}
/** The `@…` label shown in the chip, trimmed of any `#section` anchor for brevity. */
export function referenceLabel(path: string): string {
return `@${path}`;
}
export interface ReferenceOption {
path: string;
/** Short human description shown in the `@` menu. */
description: string;
/**
* The document this path resolves to, when the caller knows it.
*
* Absent for the system tokens (`@crm-updater`, `@next-steps` — live UI blocks, not
* documents) and for the static {@link REFERENCE_OPTIONS} fallbacks, which are paths
* nobody has resolved. A `<ref>` is addressed by id, so only an option that carries one
* can become a `triggerRef` panel when picked inside a trigger.
*/
documentId?: string;
}
/** Canonical options surfaced by the `@` menu, in display order. */
export const REFERENCE_OPTIONS: ReferenceOption[] = [
{ path: 'crm-updater', description: 'System token · manage conversation fields' },
{ path: 'next-steps', description: 'System token · manage tasks & next step' },
{ path: 'knowledge-base', description: 'On-demand reference corpus' },
{ path: 'knowledge-base/company-background', description: 'Company background doc' },
{ path: 'resources/overall-goal', description: 'Always-loaded AOP goal' },
{ path: 'resources/email-style', description: 'Email style guide' },
{ path: 'resources/templates', description: 'Template library (by anchor)' },
{ path: 'resources/coaching-framework', description: 'Coaching framework' },
{ path: 'resources/discovery-guide', description: 'Discovery guide' },
{ path: 'org/deals-playbook', description: 'Org-level Deals playbook' },
{ path: 'subagents/bant-coach', description: 'Custom subagent' },
{ path: 'subagents/notify-solutions-engineer', description: 'Custom subagent' },
];