toga-ai 1.0.640 → 1.0.641
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/knowledge/2.0/apps/ai-bdr/INDEX.md +3 -2
- package/knowledge/2.0/apps/ai-bdr/features/campaign-chat-handoff.md +32 -6
- package/knowledge/2.0/apps/ai-bdr/features/landing-chat-drawer.md +176 -0
- package/knowledge/2.0/apps/ai-bdr/features/security-landing-page.md +46 -13
- package/knowledge/2.0/apps/toga-blox/features/talos-assistant.md +18 -2
- package/knowledge/INDEX.md +1 -1
- package/package.json +1 -1
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
| [AI-BDR Architecture](architecture.md) | **AI-BDR** is TOGA's outbound AI sales-development representative. | ai-bdr/README.md, ai-bdr/requirements.txt, ai-bdr/.env.example, ai-bdr/docs/client-onboarding-sop.md, ai-bdr/docs/vapi-firstmessage-timing-fix.md, ai-bdr/docs/vapi-inbound-callback-assistant-request.md, ai-bdr/docs/vapi-voicemail-iphone-screening.md, ai-bdr/vapi/templates/system-prompt.template.md, ai-bdr/vapi/templates/assistant.template.json, ai-bdr/prompts/archive/prompt-may-15.txt, ai-bdr/prompts/campaigns/healthcare-2026-03-18.md, ai-bdr/prompts/campaigns/healthcare-v2-2026-03-25.md, ai-bdr/scripts/update_assistant.py, ai-bdr/scripts/update_system_prompt.py, ai-bdr/scripts/update_structured_output.py, ai-bdr/scripts/update_call_summary_context.py, ai-bdr/scripts/fix_booking_guardrails.py, ai-bdr/scripts/get_assistant.py |
|
|
6
6
|
| [BDR Web Funnel — Full Implementation Plan](features/bdr-web-funnel-plan.md) | > **Execution status (2026-07-16):** PLAN **Phases 0–5 are BUILT and QA'd**, Phase 6 > was **mostly already built** (the `info` contract was implemented at comm | bdr/PLAN.md, bdr/mockup/app.jsx, bdr/mockup/screens.jsx, bdr/mockup/components.jsx |
|
|
7
7
|
| [Call Orchestration — PHP Worker ↔ Vapi (the integration seam)](features/call-orchestration.md) | The **PHP worker** is the orchestrator; **Vapi** is the actor. | ai-bdr/docs/client-onboarding-sop.md, ai-bdr/docs/vapi-firstmessage-timing-fix.md, ai-bdr/docs/vapi-inbound-callback-assistant-request.md, ai-bdr/docs/vapi-voicemail-iphone-screening.md, ai-bdr/scripts/update_structured_output.py |
|
|
8
|
-
| [AI-BDR Campaign Chat — Backend Contract + Frontend Widget Handoff](features/campaign-chat-handoff.md) | The consolidated backend + frontend handoff for the **AI-BDR campaign chat** — a grounded AI-BDR chat widget for landing pages, powered by the Talos backend at | ai-bdr-campaign-handoff.md |
|
|
8
|
+
| [AI-BDR Campaign Chat — Backend Contract + Frontend Widget Handoff](features/campaign-chat-handoff.md) | The consolidated backend + frontend handoff for the **AI-BDR campaign chat** — a grounded AI-BDR chat widget for landing pages, powered by the Talos backend at | ai-bdr-campaign-handoff.md, bdr/src/lib/talosChat.ts |
|
|
9
|
+
| [Talos Chat Drawer on /landing (first campaign-chat consumer)](features/landing-chat-drawer.md) | The **right-anchored chat drawer on `/landing`**, wired to the **real** Talos campaign-chat backend at `https://api.togaiq.com`. | bdr/src/components/ChatPanel.tsx, bdr/src/components/ChatMarkdown.tsx, bdr/src/lib/talosChat.ts, bdr/src/content/security.ts, bdr/src/flow/screens/SecurityLanding.tsx, bdr/src/app/security.css, bdr/test/talosChat.test.ts, bdr/test/chatMarkdown.test.ts |
|
|
9
10
|
| [Live Call Status — Vapi call API → funnel Success screen lifecycle](features/live-call-status.md) | The BDR funnel's Success screen shows the **real** state of the call it just requested — dialing / ringing / answered-and-talking / ended / not-answered — inste | bdr/src/server/vapiCall.ts, bdr/src/server/callStatus.ts, bdr/src/server/statusToken.ts, bdr/src/server/callbackService.ts, bdr/src/server/workerDialer.ts, bdr/src/lib/callStatus.ts, bdr/src/app/api/call-status/route.ts, bdr/src/app/api/call-now/route.ts, bdr/src/flow/useCallStatusViewModel.ts, bdr/src/flow/callStatusApi.ts, bdr/src/flow/screens/Success.tsx, bdr/src/content/schema.ts, bdr/src/content/default.ts, bdr/src/proxy.ts |
|
|
10
|
-
| [Cybersecurity Landing Page (/landing — the site's current main page)](features/security-landing-page.md) | A single-page **cybersecurity services marketing landing page** at **`/landing`** in the `bdr` repo — and, as of 2026-08-24, **the site's main page**: `/` **307 | bdr/src/app/landing/page.tsx, bdr/src/app/security.css, bdr/src/flow/screens/SecurityLanding.tsx, bdr/src/content/security.ts, bdr/src/components/LogoSymbol.tsx, bdr/src/components/AssistantMark.tsx, bdr/src/components/Ico.tsx, bdr/src/components/Particles.tsx, bdr/next.config.ts, bdr/eslint.config.mjs |
|
|
11
|
+
| [Cybersecurity Landing Page (/landing — the site's current main page)](features/security-landing-page.md) | A single-page **cybersecurity services marketing landing page** at **`/landing`** in the `bdr` repo — and, as of 2026-08-24, **the site's main page**: `/` **307 | bdr/src/app/landing/page.tsx, bdr/src/app/security.css, bdr/src/flow/screens/SecurityLanding.tsx, bdr/src/content/security.ts, bdr/src/components/LogoSymbol.tsx, bdr/src/components/AssistantMark.tsx, bdr/src/components/Ico.tsx, bdr/src/components/Particles.tsx, bdr/src/components/ChatPanel.tsx, bdr/src/components/ChatMarkdown.tsx, bdr/src/lib/talosChat.ts, bdr/next.config.ts, bdr/eslint.config.mjs |
|
|
11
12
|
| [Vapi Integration — Assistants, Tools, Structured Output](features/vapi-integration.md) | Everything inside Vapi: the three assistants, the three shared tools, the shared structured-output schema, the Liquid-templated system prompt, and the Python sc | ai-bdr/vapi/templates/assistant.template.json, ai-bdr/vapi/templates/system-prompt.template.md, ai-bdr/prompts/archive/prompt-may-15.txt, ai-bdr/prompts/campaigns/healthcare-2026-03-18.md, ai-bdr/prompts/campaigns/healthcare-v2-2026-03-25.md, ai-bdr/prompts/templates/campaign-template.md, ai-bdr/scripts/update_assistant.py, ai-bdr/scripts/update_system_prompt.py, ai-bdr/scripts/update_structured_output.py, ai-bdr/scripts/update_call_summary_context.py, ai-bdr/scripts/fix_booking_guardrails.py, ai-bdr/scripts/get_assistant.py, ai-bdr/docs/vapi-firstmessage-timing-fix.md, ai-bdr/docs/vapi-voicemail-iphone-screening.md |
|
|
12
13
|
| [Web Funnel — Built Next.js App (structure, stack, how to run)](features/web-funnel-app.md) | > **READ FIRST (2026-08-24) — the funnel is currently UNREACHABLE.** `/` now > **307-redirects to `/landing`**, the new cybersecurity landing page > ([security- | bdr/PLAN.md, bdr/next.config.ts, bdr/.gitignore, bdr/src/server/hubspot.ts, bdr/src/server/leadSink.ts, bdr/src/server/callbackService.ts, bdr/src/server/workerDialer.ts, bdr/src/server/mailer.ts, bdr/src/server/statusToken.ts, bdr/src/server/vapiCall.ts, bdr/src/server/callStatus.ts, bdr/src/lib/summaryText.ts, bdr/src/lib/emailFormat.ts, bdr/src/lib/callStatus.ts, bdr/src/app/api/share-summary/route.ts, bdr/src/app/api/call-status/route.ts, bdr/src/flow/shareSummaryApi.ts, bdr/src/flow/callStatusApi.ts, bdr/src/flow/useCallStatusViewModel.ts, bdr/src/flow/screens/Success.tsx, bdr/src/flow/screens/CallNow.tsx, bdr/src/flow/screens/Schedule.tsx, bdr/src/flow/screens/CallSummary.tsx, bdr/src/content/schema.ts, bdr/src/content/default.ts, bdr/test/togaEnrichment.test.ts, bdr/test/fastDial.test.ts, bdr/eslint.config.mjs, bdr/amplify.yml, bdr/src/app, bdr/src/app/layout.tsx, bdr/src/app/page.tsx, bdr/src/app/studio.css, bdr/src/lib/resolveCampaignId.ts, bdr/src/lib/scheduleSlots.ts, bdr/src/lib/formatPhone.ts, bdr/src/lib/analytics.ts, bdr/src/lib/rateLimit.ts, bdr/src/lib/clientIp.ts, bdr/src/proxy.ts, bdr/.env.example, bdr/src/components/GoogleAnalytics.tsx, bdr/src/components/RichText.tsx, bdr/src/content, bdr/src/components, bdr/src/flow, bdr/src/server, bdr/src/server/toga.ts, bdr/src/app/api, bdr/test, bdr/test/togaPrimaryPhone.test.ts, bdr/public, bdr/mockup/styles.css |
|
|
13
14
|
| [Web Funnel — Next.js UI + Config-Driven Campaign Content](features/web-funnel-content-model.md) | > **Status note (RESOLVED 2026-07-16):** the content **contract** below (schema, > provider seam, adapters) is BUILT and QA'd (PLAN Phases 0–5). | bdr/src/content/schema.ts, bdr/src/content/provider.ts, bdr/src/content/useCampaign.ts, bdr/src/content/default.ts, bdr/src/lib/resolveCampaignId.ts, bdr/src/server/leadSink.ts, bdr/src/server/callbackService.ts, bdr/src/app/api/call-now/route.ts, bdr/src/app/api/call-later/route.ts, bdr/src/app/api/contact/route.ts |
|
|
@@ -6,11 +6,13 @@ project: AI-BDR
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-08-
|
|
9
|
+
updated: 2026-08-25
|
|
10
10
|
owners: [tcox]
|
|
11
11
|
files:
|
|
12
12
|
- ai-bdr-campaign-handoff.md
|
|
13
|
+
- bdr/src/lib/talosChat.ts
|
|
13
14
|
related:
|
|
15
|
+
- landing-chat-drawer.md
|
|
14
16
|
- security-landing-page.md
|
|
15
17
|
- web-funnel-app.md
|
|
16
18
|
- ../architecture.md
|
|
@@ -34,11 +36,20 @@ architecture deep-dive in `docs/ai-bdr-campaign-chat-architecture.md`). This
|
|
|
34
36
|
knowledge doc distills the contract and records the load-bearing decisions and
|
|
35
37
|
gotchas — the source handoff carries the full copy-paste implementation code.
|
|
36
38
|
|
|
37
|
-
**
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
**The first consumer now exists.** As of 2026-08-24 the `bdr` cybersecurity landing page
|
|
40
|
+
ships a chat drawer against this contract, grounded in the "External Pen Testing"
|
|
41
|
+
campaign — the same offer the landing sells. It lives in `bdr/src/lib/talosChat.ts`
|
|
42
|
+
(adapter) + `ChatPanel.tsx` / `ChatMarkdown.tsx`, and is documented in
|
|
43
|
+
[landing-chat-drawer.md](landing-chat-drawer.md). Read that doc before building the
|
|
44
|
+
**second** consumer; it is the worked example of this contract.
|
|
45
|
+
|
|
46
|
+
**It was NOT built on assistant-ui.** The *Frontend build* section below still describes
|
|
47
|
+
the handoff's original `@assistant-ui/react` + `useLocalRuntime` recipe, which remains a
|
|
48
|
+
valid path. BDR deliberately went a different way: a hand-rolled drawer plus a
|
|
49
|
+
**blox-shaped adapter** (`onSend(text) => Promise<TalosResponse>`, matching
|
|
50
|
+
`@agilant/toga-blox`'s `TalosAdapter` seam), so the shell can later be swapped for blox's
|
|
51
|
+
shared `TalosPanel` without rewriting the backend layer. Treat assistant-ui as one
|
|
52
|
+
option, not the house standard.
|
|
42
53
|
|
|
43
54
|
## Design decision (settled — do not re-litigate)
|
|
44
55
|
|
|
@@ -158,6 +169,14 @@ from `data`.
|
|
|
158
169
|
|
|
159
170
|
## Gotchas
|
|
160
171
|
|
|
172
|
+
- **Every consumer domain must be allowlisted by the Talos backend owner** — the
|
|
173
|
+
origin/UA gate on `talos-session` / `talos-chat` / `campaign` is per-origin, so
|
|
174
|
+
`localhost:3000`, each sandbox host (e.g. `bdr.dev.sandbox.togatech.com`), and the
|
|
175
|
+
production domain each need adding **before** the widget can answer live. Budget this
|
|
176
|
+
as a real dependency on someone else, not a config flag you own. A well-built consumer
|
|
177
|
+
degrades silently here (BDR's does), which makes "it works on my machine"
|
|
178
|
+
indistinguishable from "the backend refused us" unless you check for a live-only
|
|
179
|
+
signal such as backend-chosen `suggestions`.
|
|
161
180
|
- **Presigned deck-image URLs EXPIRE (~7 days).** `image_url` is a presigned S3
|
|
162
181
|
URL because `CAMPAIGN_ASSET_CDN_BASE_URL` is currently unset — do not cache
|
|
163
182
|
long-term; re-fetch the campaign read on page load / image error. Once the
|
|
@@ -181,6 +200,13 @@ from `data`.
|
|
|
181
200
|
internal-only** now that campaign traffic rides the same path.
|
|
182
201
|
|
|
183
202
|
## Change history
|
|
203
|
+
- 2026-08-24 — First consumer built and shipped into the `bdr` working tree: the
|
|
204
|
+
`/landing` chat drawer ([landing-chat-drawer.md](landing-chat-drawer.md)), grounded in
|
|
205
|
+
the "External Pen Testing" campaign. Recorded that it deliberately did **not** use the
|
|
206
|
+
handoff's assistant-ui recipe, using a blox-`TalosAdapter`-shaped seam instead so the
|
|
207
|
+
shell can be swapped for blox's shared `TalosPanel` later. Added the per-origin
|
|
208
|
+
allowlist gotcha — every consumer domain needs the Talos backend owner to allowlist it,
|
|
209
|
+
and a graceful consumer hides that failure. (tcox)
|
|
184
210
|
- 2026-08-24 — Initial doc: captured the consolidated AI-BDR campaign chat
|
|
185
211
|
handoff (backend contract at api.togaiq.com + frontend widget spec on
|
|
186
212
|
assistant-ui). Markdown + structured-data format settled over XML tags;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Talos Chat Drawer on /landing (first campaign-chat consumer)
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: ai-bdr
|
|
5
|
+
project: AI-BDR
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-08-25
|
|
10
|
+
owners: [tcox]
|
|
11
|
+
files:
|
|
12
|
+
- bdr/src/components/ChatPanel.tsx
|
|
13
|
+
- bdr/src/components/ChatMarkdown.tsx
|
|
14
|
+
- bdr/src/lib/talosChat.ts
|
|
15
|
+
- bdr/src/content/security.ts
|
|
16
|
+
- bdr/src/flow/screens/SecurityLanding.tsx
|
|
17
|
+
- bdr/src/app/security.css
|
|
18
|
+
- bdr/test/talosChat.test.ts
|
|
19
|
+
- bdr/test/chatMarkdown.test.ts
|
|
20
|
+
related:
|
|
21
|
+
- security-landing-page.md
|
|
22
|
+
- campaign-chat-handoff.md
|
|
23
|
+
- web-funnel-app.md
|
|
24
|
+
- ../../toga-blox/features/talos-assistant.md
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## What this is
|
|
28
|
+
|
|
29
|
+
The **right-anchored chat drawer on `/landing`**, wired to the **real** Talos
|
|
30
|
+
campaign-chat backend at `https://api.togaiq.com`. It is the **first live consumer**
|
|
31
|
+
of the contract in [campaign-chat-handoff.md](campaign-chat-handoff.md), grounded in
|
|
32
|
+
campaign `43fdf2b6-7a5d-4e85-be6b-911f42aa787f` ("External Pen Testing") — the same
|
|
33
|
+
offer the landing page sells.
|
|
34
|
+
|
|
35
|
+
It opens from **both** entry points that were previously inert: the header CTA
|
|
36
|
+
("Ask Alex Anything") and the hero "Learn more" button.
|
|
37
|
+
|
|
38
|
+
Three pieces, deliberately separated:
|
|
39
|
+
|
|
40
|
+
| File | Role | Disposable? |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `components/ChatPanel.tsx` | Drawer **shell** (scrim, header, message list, chips, composer) | **Yes** — planned replacement by blox `TalosPanel` |
|
|
43
|
+
| `lib/talosChat.ts` | Backend **adapter** (session, message shaping, fallback) | No — the durable piece |
|
|
44
|
+
| `components/ChatMarkdown.tsx` | Safe markdown **renderer** for the reply | No — portable as-is |
|
|
45
|
+
|
|
46
|
+
## How it works
|
|
47
|
+
|
|
48
|
+
1. **Fingerprint.** `getFingerprint()` returns a per-browser 64-lowercase-hex id
|
|
49
|
+
persisted in `localStorage` under `talos_fp` (32 random bytes), with an in-memory
|
|
50
|
+
fallback when storage is unavailable.
|
|
51
|
+
2. **Session token.** `POST /api/ai/talos-session` mints a ~15-min JWT bound to that
|
|
52
|
+
fingerprint. It is cached in the adapter and re-minted **exactly once** on a 401;
|
|
53
|
+
a second 401 falls through to the scripted fallback rather than looping.
|
|
54
|
+
3. **Turn.** Non-streaming `POST /api/ai/talos-chat` with `Bearer <token>`,
|
|
55
|
+
`campaign_id`, and the shaped `messages` array.
|
|
56
|
+
4. **Render.** `message` goes through `ChatMarkdown`; `suggestions` become quick-reply
|
|
57
|
+
chips whose text is sent as the next user message.
|
|
58
|
+
|
|
59
|
+
**Message-shape enforcement lives in `buildApiMessages()`**, not in the UI. The backend
|
|
60
|
+
requires alternating `user`/`assistant`, starting **and** ending with `user`, max 30 —
|
|
61
|
+
so the builder drops the canned greeting, merges consecutive same-role turns, and
|
|
62
|
+
trims from the front to the cap while preserving alternation. The visible transcript
|
|
63
|
+
and the wire transcript are deliberately not the same list.
|
|
64
|
+
|
|
65
|
+
**Adapter seam:** `createTalosChatAdapter(options)` returns a `TalosAdapter` whose only
|
|
66
|
+
method is `onSend(text) => Promise<TalosResponse>` — intentionally the same shape as
|
|
67
|
+
blox's `TalosAdapter` (see *Bridge to blox* below).
|
|
68
|
+
|
|
69
|
+
Base URL resolution: `options.baseUrl ?? process.env.NEXT_PUBLIC_TALOS_API_BASE ??
|
|
70
|
+
"https://api.togaiq.com"`.
|
|
71
|
+
|
|
72
|
+
## Offline fallback (the drawer never dead-ends)
|
|
73
|
+
|
|
74
|
+
When the backend is unreachable — offline, **origin not allowlisted**, 5xx, timeout —
|
|
75
|
+
the adapter answers from the mockup's scripted `askAlex` answers, which now live as
|
|
76
|
+
**data** in `src/content/security.ts` under the `talos.fallback` group (not hardcoded
|
|
77
|
+
in the adapter).
|
|
78
|
+
|
|
79
|
+
- Fallback replies are flagged `offline: true` and carry **no** suggestion chips.
|
|
80
|
+
- **That is how you tell live from fallback in the UI:** live replies carry
|
|
81
|
+
backend-chosen chips; fallback replies have none.
|
|
82
|
+
- Alternation is preserved across a fallback turn, so a later live turn is still a
|
|
83
|
+
valid request (covered by a test).
|
|
84
|
+
|
|
85
|
+
## Safety
|
|
86
|
+
|
|
87
|
+
- `ChatMarkdown` supports only paragraphs, `- ` bullets, and `**bold**`. It emits
|
|
88
|
+
**only** text nodes plus `p` / `ul` / `li` / `strong`. **No HTML parsing, no links,
|
|
89
|
+
no `dangerouslySetInnerHTML`** — html-looking content stays literal text (tested).
|
|
90
|
+
An unclosed `**` stays literal.
|
|
91
|
+
- Only rendered fields (`message`, `suggestions`, `cta`, `cited_slides`) are mapped
|
|
92
|
+
into the response type by `toTalosResponse()`. The backend's **silent
|
|
93
|
+
lead/qualification fields are never read** — deliberate, per the handoff.
|
|
94
|
+
|
|
95
|
+
## Deliberate deviations from the mockup drawer
|
|
96
|
+
|
|
97
|
+
- **"Call me now" is NOT rendered.** Its destination is the parked studio call screen,
|
|
98
|
+
unreachable from this page. The standing drawer action is **"Book a meeting"** →
|
|
99
|
+
the same Calendly href as the page's primary CTA.
|
|
100
|
+
- **`cta` and `cited_slides` are captured and typed but not rendered yet.** Both are
|
|
101
|
+
clean follow-ups; `cited_slides` additionally needs `GET /api/ai/campaign/{id}` plus
|
|
102
|
+
presigned-URL freshness handling (those URLs expire ~7 days — see the handoff).
|
|
103
|
+
|
|
104
|
+
## Bridge to blox (TRUE-80692 — "bridge now, blox later")
|
|
105
|
+
|
|
106
|
+
blox ships a shared Talos component
|
|
107
|
+
([talos-assistant.md](../../toga-blox/features/talos-assistant.md), apeterson,
|
|
108
|
+
2026-08-20). BDR does **not** use it yet, for two blox-side reasons, both unscheduled:
|
|
109
|
+
|
|
110
|
+
- blox is **not published to npm** for this component (toga25-supply consumes it via a
|
|
111
|
+
local symlink; BDR cannot symlink a Next app dependency the same way), and
|
|
112
|
+
- blox **peers cap React at ^18**, while BDR is on **React 19.2.4**.
|
|
113
|
+
|
|
114
|
+
So the decision: build the shell now, swap it later.
|
|
115
|
+
|
|
116
|
+
- `ChatPanel.tsx` is **deliberately disposable** — expect it to be deleted and replaced
|
|
117
|
+
by blox `TalosPanel`.
|
|
118
|
+
- `talosChat.ts` **deliberately mirrors blox's `TalosAdapter` seam**
|
|
119
|
+
(`onSend(text) => Promise<TalosResponse>`), so the swap is a **re-wire, not a rebuild**.
|
|
120
|
+
- `talosChat.ts` is the candidate implementation for blox's deferred *"real `onSend`
|
|
121
|
+
backend adapter"* ticket — contribute it upstream when that ticket is picked up
|
|
122
|
+
(mention to apeterson). The one env-ism to fix on the way: the
|
|
123
|
+
`process.env.NEXT_PUBLIC_TALOS_API_BASE` default is Next-specific; blox consumers are
|
|
124
|
+
Vite, so it becomes a **required `baseUrl` option**.
|
|
125
|
+
- `ChatMarkdown.tsx` is portable as-is; it would need `className` → `--talos-*`
|
|
126
|
+
tokenization.
|
|
127
|
+
- **Design caveat:** blox `TalosPanel`'s spacing/density is not yet tokenized (its
|
|
128
|
+
documented theming ceiling), so even fully themed it will **not** match the security
|
|
129
|
+
mockup drawer pixel-for-pixel. Accept that at swap time or fund the spacing-token pass.
|
|
130
|
+
|
|
131
|
+
## Styling
|
|
132
|
+
|
|
133
|
+
The `.chatveil` / `.chatpanel` block is ported from the mockup's `styles.css`
|
|
134
|
+
(1177–1220) into `security.css` and is **scoped under `.security-shell`** like every
|
|
135
|
+
other landing rule. `z-index: 120`, width `min(400px, 92vw)`, reduced-motion respected.
|
|
136
|
+
`.chatmd-p` / `.chatmd-list` carry the reply rhythm. Escape and scrim click close the
|
|
137
|
+
drawer; focus moves into the composer on open and is restored to the opener on close.
|
|
138
|
+
|
|
139
|
+
## Gotchas
|
|
140
|
+
|
|
141
|
+
- **`api.togaiq.com` chat endpoints are origin/UA-gated.** `localhost:3000`,
|
|
142
|
+
`bdr.dev.sandbox.togatech.com`, and the eventual production domain **must be
|
|
143
|
+
allowlisted by the Talos backend owner**. Until they are, the drawer silently answers
|
|
144
|
+
from the scripted fallback and looks like it works. Check for suggestion chips before
|
|
145
|
+
concluding the backend is live.
|
|
146
|
+
- **Do not "fix" the transcript by sending the visible message list.** The greeting and
|
|
147
|
+
any merged/trimmed turns would break the strict alternating shape and return a 422.
|
|
148
|
+
- **The chat is fully client-side**, which is why `/landing` still builds as a
|
|
149
|
+
**prerendered static** route. Adding a server call here changes that.
|
|
150
|
+
- **`/landing` is not rate-limited** (`src/proxy.ts` matches only `/` and the five API
|
|
151
|
+
routes). The drawer talks to a third-party origin, not a BDR API route, so the
|
|
152
|
+
limiter still does not apply — but the abuse surface now exists on the page.
|
|
153
|
+
|
|
154
|
+
## How to work on it
|
|
155
|
+
|
|
156
|
+
- 30 new Vitest tests across `test/talosChat.test.ts` and `test/chatMarkdown.test.ts`
|
|
157
|
+
(message-shape rules including the 30-cap alternation, 401 re-mint-once, fallback on
|
|
158
|
+
network error and on 5xx, alternation preserved across a fallback turn, adapter
|
|
159
|
+
reset, markdown safety). Suite **367/367 green**; `tsc`, `eslint` (incl. the
|
|
160
|
+
no-em-dash rule), and `next build` all clean as of 2026-08-24.
|
|
161
|
+
- **Nothing is committed** — the drawer lives in the `bdr` working tree only, awaiting
|
|
162
|
+
the developer's branch/commit go-ahead.
|
|
163
|
+
|
|
164
|
+
## Change history
|
|
165
|
+
- 2026-08-24 — Initial doc. BUILT the `/landing` Talos chat drawer wired to the real
|
|
166
|
+
campaign-chat backend: `ChatPanel.tsx` (right-anchored drawer ported from the security
|
|
167
|
+
mockup), `lib/talosChat.ts` (fingerprint + 15-min session token + message-shape
|
|
168
|
+
enforcement + scripted offline fallback), `ChatMarkdown.tsx` (link-free, HTML-free
|
|
169
|
+
markdown subset), the `.chatveil`/`.chatpanel` CSS block, and the `talos` content group.
|
|
170
|
+
Both previously-inert entry points (header CTA "Ask Alex Anything", hero "Learn more")
|
|
171
|
+
now open it. DECIDED "bridge now, blox later" for TRUE-80692 — blox is unpublished and
|
|
172
|
+
React-18-capped, so the shell is disposable while the adapter mirrors blox's
|
|
173
|
+
`TalosAdapter` seam for a later re-wire. DECIDED not to render the mockup's "Call me
|
|
174
|
+
now" (parked studio destination) and to defer `cta`/`cited_slides` rendering. Recorded
|
|
175
|
+
the origin/UA allowlist dependency as the reason the drawer may silently answer from
|
|
176
|
+
fallback. 30 new tests, 367/367 green. Uncommitted at capture. (tcox)
|
|
@@ -6,7 +6,7 @@ project: AI-BDR
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-08-
|
|
9
|
+
updated: 2026-08-25
|
|
10
10
|
owners: [tcox]
|
|
11
11
|
files:
|
|
12
12
|
- bdr/src/app/landing/page.tsx
|
|
@@ -17,9 +17,14 @@ files:
|
|
|
17
17
|
- bdr/src/components/AssistantMark.tsx
|
|
18
18
|
- bdr/src/components/Ico.tsx
|
|
19
19
|
- bdr/src/components/Particles.tsx
|
|
20
|
+
- bdr/src/components/ChatPanel.tsx
|
|
21
|
+
- bdr/src/components/ChatMarkdown.tsx
|
|
22
|
+
- bdr/src/lib/talosChat.ts
|
|
20
23
|
- bdr/next.config.ts
|
|
21
24
|
- bdr/eslint.config.mjs
|
|
22
25
|
related:
|
|
26
|
+
- landing-chat-drawer.md
|
|
27
|
+
- campaign-chat-handoff.md
|
|
23
28
|
- web-funnel-app.md
|
|
24
29
|
- web-funnel-content-model.md
|
|
25
30
|
- ../architecture.md
|
|
@@ -39,8 +44,11 @@ mockup: `BDR/AI BDR - Security/` (a React 18 UMD + in-browser Babel prototype
|
|
|
39
44
|
**`Capabilities` screen**; because `src/flow/screens/Capabilities.tsx` already exists as a
|
|
40
45
|
studio screen, it was ported under the name **`SecurityLanding`**.
|
|
41
46
|
|
|
42
|
-
**Status
|
|
43
|
-
|
|
47
|
+
**Status (updated 2026-08-24): one live backend, nothing else.** The page now carries a
|
|
48
|
+
**Talos chat drawer wired to the real campaign-chat backend** — see
|
|
49
|
+
[landing-chat-drawer.md](landing-chat-drawer.md), which owns that subject. Everything
|
|
50
|
+
else is still UI only: no form, no lead capture, no Toga/HubSpot call, no analytics
|
|
51
|
+
events of its own.
|
|
44
52
|
|
|
45
53
|
## Page structure
|
|
46
54
|
|
|
@@ -129,8 +137,25 @@ does not define or defines differently.
|
|
|
129
137
|
**CAVEAT: that URL is a placeholder carried over from the mockup** (the mockup's own
|
|
130
138
|
comment says "replace with the real TOGA Calendly link") and the slug's liveness has
|
|
131
139
|
**not** been verified. Confirm it before pointing traffic at the page.
|
|
132
|
-
- **"Learn more"** and the header CTA **"Ask
|
|
133
|
-
mockup
|
|
140
|
+
- **"Learn more"** and the header CTA (**"Ask Alex Anything"** — renamed 2026-08-24 from
|
|
141
|
+
the mockup's "Ask Me Anything") both **open the Talos chat drawer** as of 2026-08-24.
|
|
142
|
+
Neither is inert any more. The drawer, its backend adapter, and its offline fallback
|
|
143
|
+
are documented in [landing-chat-drawer.md](landing-chat-drawer.md).
|
|
144
|
+
|
|
145
|
+
## Responsive / mobile pass (original work, not ported)
|
|
146
|
+
|
|
147
|
+
The mockup ships **no** landing-specific mobile CSS below its 900px hero-stack and 760px
|
|
148
|
+
stats/matters breakpoints, so the phone treatment below ~760px was **designed here**, not
|
|
149
|
+
ported. All of it is scoped under `.security-shell`.
|
|
150
|
+
|
|
151
|
+
- **`@media (max-width: 560px)`** — hero title re-clamped to `clamp(29px, 8.4vw, 35px)`;
|
|
152
|
+
the two hero CTAs stack **full-width** at `height: 54px`; value-tile padding `20px`;
|
|
153
|
+
matters-card / stat padding trimmed; stat figure `23px`; section spacing tightened.
|
|
154
|
+
**`.lp-value-motes` inset pulled in from `-42px/-34px` to `-30px/-10px`** — at
|
|
155
|
+
full-width the mote spill poked past the viewport edge and opened **horizontal
|
|
156
|
+
scroll** on phones. Do not widen it back without re-checking on a real device.
|
|
157
|
+
- **`@media (max-width: 420px)`** — **`.wordmark-tech` is hidden** (the letterspaced
|
|
158
|
+
"TECHNOLOGY" suffix and the header pill cannot share a ~360px topbar); stats gap `12px`.
|
|
134
159
|
|
|
135
160
|
## How to work on it
|
|
136
161
|
|
|
@@ -142,13 +167,15 @@ does not define or defines differently.
|
|
|
142
167
|
|
|
143
168
|
## Known gaps / pending work
|
|
144
169
|
|
|
145
|
-
- **
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
- **Calendly URL unverified** (above).
|
|
170
|
+
- **Calendly URL unverified** (above) — still the top open item, and now also the
|
|
171
|
+
drawer's "Book a meeting" destination, so a bad slug breaks two paths.
|
|
172
|
+
- **Chat drawer's origin allowlist is not done** — `api.togaiq.com` is origin/UA gated,
|
|
173
|
+
so until localhost / sandbox / prod domains are allowlisted the drawer silently answers
|
|
174
|
+
from its scripted fallback (see [landing-chat-drawer.md](landing-chat-drawer.md)).
|
|
151
175
|
- No form, no lead capture, no landing-specific analytics.
|
|
176
|
+
- ~~Mobile pass pending~~ — **done 2026-08-24** (see *Responsive / mobile pass* above).
|
|
177
|
+
- ~~Chat drawer not ported~~ — **done 2026-08-24**, and wired to the real backend rather
|
|
178
|
+
than re-creating the mockup's scripted-only behavior.
|
|
152
179
|
|
|
153
180
|
## Gotchas
|
|
154
181
|
|
|
@@ -182,6 +209,14 @@ does not define or defines differently.
|
|
|
182
209
|
the page gains a form or reads a query param.
|
|
183
210
|
|
|
184
211
|
## Change history
|
|
212
|
+
- 2026-08-24 — Closed both of the doc's open gaps. BUILT the **mobile pass** as original
|
|
213
|
+
work (560px and 420px breakpoints under `.security-shell`; the `.lp-value-motes` inset
|
|
214
|
+
was pulled in to kill horizontal scroll, and `.wordmark-tech` is hidden under 420px) —
|
|
215
|
+
the mockup had no landing-specific mobile CSS to port. BUILT the **Talos chat drawer**,
|
|
216
|
+
wired to the real campaign-chat backend, opened by both previously-inert entry points
|
|
217
|
+
(header CTA, now "Ask Alex Anything", and hero "Learn more"); the drawer is its own
|
|
218
|
+
subject in [landing-chat-drawer.md](landing-chat-drawer.md). Page remains prerendered
|
|
219
|
+
static (chat is fully client-side); still no form, lead capture, or analytics. (tcox)
|
|
185
220
|
- 2026-08-24 — Initial doc. BUILT the cybersecurity landing page at `/landing`, ported
|
|
186
221
|
pixel-faithfully from the new `BDR/AI BDR - Security/` mockup (its `Capabilities` screen,
|
|
187
222
|
renamed `SecurityLanding` to avoid the studio-screen collision) and made it the site's
|
|
@@ -198,5 +233,3 @@ does not define or defines differently.
|
|
|
198
233
|
(chat drawer not ported), and that the mobile pass is pending because the mockup has no
|
|
199
234
|
landing-specific mobile CSS. tsc + lint + build clean, `/landing` prerendered static,
|
|
200
235
|
`GET /` → 307 verified. All work uncommitted in the working tree at capture. (tcox)
|
|
201
|
-
</content>
|
|
202
|
-
</invoke>
|
|
@@ -6,8 +6,8 @@ project: TOGa Blox
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-08-
|
|
10
|
-
owners: [apeterson]
|
|
9
|
+
updated: 2026-08-25
|
|
10
|
+
owners: [apeterson, tcox]
|
|
11
11
|
files:
|
|
12
12
|
- toga-blox/src/components/Talos/TalosLauncher.tsx
|
|
13
13
|
- toga-blox/src/components/Talos/TalosPanel.tsx
|
|
@@ -23,6 +23,7 @@ related:
|
|
|
23
23
|
- ../architecture.md
|
|
24
24
|
- ../workflows/dynamic-publish-pipeline.md
|
|
25
25
|
- ../../toga25-supply/features/talos-integration.md
|
|
26
|
+
- ../../ai-bdr/features/landing-chat-drawer.md
|
|
26
27
|
---
|
|
27
28
|
|
|
28
29
|
## Summary
|
|
@@ -77,10 +78,25 @@ Open questions were handed to the UX/UI team.
|
|
|
77
78
|
## Gotchas
|
|
78
79
|
|
|
79
80
|
- The real chat backend is a later ticket — `onSend` is stubbed; do not assume live responses.
|
|
81
|
+
**A working candidate implementation already exists outside blox:** `bdr/src/lib/talosChat.ts`
|
|
82
|
+
was written against the same `onSend(text) => Promise<TalosResponse>` seam and talks to the
|
|
83
|
+
live Talos campaign-chat backend (session token, fingerprint, strict message shaping, offline
|
|
84
|
+
fallback) — see
|
|
85
|
+
[AI-BDR landing chat drawer](../../ai-bdr/features/landing-chat-drawer.md). Consider
|
|
86
|
+
upstreaming it when the adapter ticket is picked up; the only env-ism to change is its
|
|
87
|
+
Next-specific `process.env.NEXT_PUBLIC_TALOS_API_BASE` default, which becomes a required
|
|
88
|
+
`baseUrl` option for Vite consumers.
|
|
89
|
+
- **BDR cannot consume blox Talos today** — blox is unpublished for this component and its peers
|
|
90
|
+
cap React at `^18`, while `bdr` is on React 19.2.4. That is why BDR hand-rolled a disposable
|
|
91
|
+
panel shell instead of waiting; both blockers are blox-side and unscheduled.
|
|
80
92
|
- blox `dist` is gitignored (shipped via publish, not the branch). Other consumers only get
|
|
81
93
|
Talos after blox is **published** per the `_sandbox-dev` dist-tag workflow — see
|
|
82
94
|
[Dynamic npm Publish Pipeline](../workflows/dynamic-publish-pipeline.md). toga25-supply
|
|
83
95
|
currently consumes it via a local symlink.
|
|
84
96
|
|
|
85
97
|
## Change history
|
|
98
|
+
- 2026-08-24 — Cross-reference only (no blox code change): recorded that `bdr` built a live
|
|
99
|
+
backend adapter against this component's `onSend` seam (`bdr/src/lib/talosChat.ts`) as a
|
|
100
|
+
candidate for the deferred real-backend ticket, and that BDR cannot consume blox Talos yet
|
|
101
|
+
(unpublished + React `^18` peer cap vs BDR's React 19). (tcox)
|
|
86
102
|
- 2026-08-20 — Built Talos shared AI-assistant component (launcher + docked/expanded chat panel): pure-UI + injected `TalosAdapter`, controlled open/expanded/width, fully `--talos-*` tokenized styling with typed `TalosTheme` overrides, stub adapter. Two adversarial review passes hardened it (removed a `window.dispatchEvent("resize")` side channel and a hardcoded initials literal; moved resize into an effect with cleanup + rAF throttle + keyboard `role="separator"`; SSR-safe portal guard; memoized message/handlers; restored the attach button + 11px card radius). Documented the spacing/density theming ceiling as future work (apeterson).
|
package/knowledge/INDEX.md
CHANGED
|
@@ -28,7 +28,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
28
28
|
- **toga2-hub** (TOGa Hub) — 2 doc(s) → [2.0/apps/toga2-hub/INDEX.md](2.0/apps/toga2-hub/INDEX.md)
|
|
29
29
|
- **talos** (TOGa IQ) — 7 doc(s) → [2.0/apps/talos/INDEX.md](2.0/apps/talos/INDEX.md)
|
|
30
30
|
- **voice-to-voice** (TOGa Voice) — 4 doc(s) → [2.0/apps/voice-to-voice/INDEX.md](2.0/apps/voice-to-voice/INDEX.md)
|
|
31
|
-
- **ai-bdr** (AI-BDR) —
|
|
31
|
+
- **ai-bdr** (AI-BDR) — 12 doc(s) → [2.0/apps/ai-bdr/INDEX.md](2.0/apps/ai-bdr/INDEX.md)
|
|
32
32
|
- **toga2-commerce** (TOGa Commerce) — 19 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
|
|
33
33
|
- **toga25-supply** (TOGa 2.5 Supply) — 12 doc(s) → [2.0/apps/toga25-supply/INDEX.md](2.0/apps/toga25-supply/INDEX.md)
|
|
34
34
|
- **toga-blox** (TOGa Blox) — 10 doc(s) → [2.0/apps/toga-blox/INDEX.md](2.0/apps/toga-blox/INDEX.md)
|
package/package.json
CHANGED