@alexkroman1/aai 0.7.7 → 0.7.9
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/dist/cli.js +2410 -2412
- package/dist/sdk/_internal_types.d.ts +2 -1
- package/dist/sdk/_internal_types.d.ts.map +1 -1
- package/dist/sdk/_internal_types.js.map +1 -1
- package/dist/sdk/protocol.d.ts +0 -7
- package/dist/sdk/protocol.d.ts.map +1 -1
- package/dist/sdk/protocol.js +0 -6
- package/dist/sdk/protocol.js.map +1 -1
- package/dist/sdk/s2s.d.ts.map +1 -1
- package/dist/sdk/s2s.js +1 -1
- package/dist/sdk/s2s.js.map +1 -1
- package/dist/sdk/server.d.ts +2 -0
- package/dist/sdk/server.d.ts.map +1 -1
- package/dist/sdk/server.js +40 -1
- package/dist/sdk/server.js.map +1 -1
- package/dist/sdk/winterc_server.d.ts.map +1 -1
- package/dist/sdk/winterc_server.js +1 -2
- package/dist/sdk/winterc_server.js.map +1 -1
- package/dist/sdk/worker_shim.d.ts.map +1 -1
- package/dist/sdk/worker_shim.js +2 -3
- package/dist/sdk/worker_shim.js.map +1 -1
- package/dist/ui/session.d.ts.map +1 -1
- package/dist/ui/session.js +0 -13
- package/dist/ui/session.js.map +1 -1
- package/package.json +5 -3
- package/templates/_shared/CLAUDE.md +192 -38
- package/templates/_shared/biome.json +32 -0
- package/templates/_shared/index.html +16 -0
- package/templates/_shared/package.json +6 -5
- package/templates/code-interpreter/client.tsx +1 -0
- package/templates/dispatch-center/client.tsx +1 -0
- package/templates/embedded-assets/client.tsx +1 -0
- package/templates/health-assistant/client.tsx +1 -0
- package/templates/infocom-adventure/client.tsx +1 -0
- package/templates/math-buddy/client.tsx +1 -0
- package/templates/memory-agent/client.tsx +1 -0
- package/templates/night-owl/client.tsx +1 -0
- package/templates/personal-finance/client.tsx +1 -0
- package/templates/simple/client.tsx +1 -0
- package/templates/smart-research/client.tsx +1 -0
- package/templates/support/client.tsx +1 -0
- package/templates/travel-concierge/client.tsx +1 -0
- package/templates/web-researcher/client.tsx +1 -0
- package/ui/styles.css +73 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# aai Voice Agent Project
|
|
2
2
|
|
|
3
|
-
You are helping a user build a voice agent using the **aai** framework.
|
|
4
|
-
or update files based on the user's description in `$ARGUMENTS`.
|
|
3
|
+
You are helping a user build a voice agent using the **aai** framework.
|
|
5
4
|
|
|
6
5
|
## Workflow
|
|
7
6
|
|
|
@@ -14,16 +13,24 @@ or update files based on the user's description in `$ARGUMENTS`.
|
|
|
14
13
|
4. **Iterate** — Make small, focused changes. Verify each change works before
|
|
15
14
|
moving on.
|
|
16
15
|
|
|
17
|
-
##
|
|
16
|
+
## Key rules
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
- Every agent lives in `agent.ts` and exports a default `defineAgent()` call
|
|
19
|
+
- Custom UI goes in `client.tsx` alongside `agent.ts`
|
|
20
|
+
- Optimize `instructions` for spoken conversation — short sentences, no visual
|
|
21
|
+
formatting, no exclamation points
|
|
22
|
+
- Never hardcode secrets — use `aai env add` and access via `ctx.env`
|
|
23
|
+
- Tool `execute` return values go into LLM context — filter and truncate large
|
|
24
|
+
API responses
|
|
25
|
+
- Agent code runs in a sandboxed worker — use `fetch` (proxied) for HTTP,
|
|
26
|
+
`ctx.env` for secrets
|
|
20
27
|
|
|
21
|
-
|
|
28
|
+
## CLI commands
|
|
22
29
|
|
|
23
30
|
```sh
|
|
24
|
-
aai
|
|
25
|
-
aai
|
|
26
|
-
aai
|
|
31
|
+
aai init # Scaffold a new agent (uses simple template)
|
|
32
|
+
aai init -t <template> # Scaffold from a specific template
|
|
33
|
+
aai dev # Start local dev server
|
|
27
34
|
aai deploy # Bundle and deploy to production
|
|
28
35
|
aai deploy -y # Deploy without prompts
|
|
29
36
|
aai deploy --dry-run # Validate and bundle without deploying
|
|
@@ -33,29 +40,10 @@ aai env ls # List environment variable names
|
|
|
33
40
|
aai env pull # Pull env var names into .env for local dev
|
|
34
41
|
```
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
## Templates
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
After scaffolding with `aai new`, deploy from the project directory:
|
|
41
|
-
|
|
42
|
-
```sh
|
|
43
|
-
cd my-agent
|
|
44
|
-
aai deploy # Bundle, check, and deploy
|
|
45
|
-
aai deploy -y # Skip confirmation prompts
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
The CLI auto-detects the server URL. When running via `aai-dev` (the local
|
|
49
|
-
monorepo dev wrapper), it targets `http://localhost:3100` automatically.
|
|
50
|
-
|
|
51
|
-
### Start from a template
|
|
52
|
-
|
|
53
|
-
Before writing an agent from scratch, **choose the closest template** and
|
|
54
|
-
scaffold with `aai new -t <template_name>`. Ask the user which template fits, or
|
|
55
|
-
recommend one based on their description. Fall back to `simple` if nothing else
|
|
56
|
-
fits.
|
|
57
|
-
|
|
58
|
-
Templates are in `templates/` relative to the CLI source:
|
|
45
|
+
Before writing an agent from scratch, choose the closest template and scaffold
|
|
46
|
+
with `aai init -t <template_name>`.
|
|
59
47
|
|
|
60
48
|
| Template | Description |
|
|
61
49
|
| ------------------- | ---------------------------------------------------------------------------------- |
|
|
@@ -75,7 +63,7 @@ Templates are in `templates/` relative to the CLI source:
|
|
|
75
63
|
| `support` | RAG-powered support agent using vector_search (AssemblyAI docs example) |
|
|
76
64
|
| `terminal` | STT-only mode for voice-driven kubectl commands |
|
|
77
65
|
|
|
78
|
-
|
|
66
|
+
## Minimal agent
|
|
79
67
|
|
|
80
68
|
Every agent lives in `agent.ts` and exports a default `defineAgent()` call:
|
|
81
69
|
|
|
@@ -104,9 +92,9 @@ import { z } from "zod"; // Tools with typed params (included in package.json)
|
|
|
104
92
|
defineAgent({
|
|
105
93
|
// Core
|
|
106
94
|
name: string; // Required: display name
|
|
107
|
-
instructions?: string; // System prompt (voice
|
|
108
|
-
greeting?: string; // Spoken on connect
|
|
109
|
-
voice?: Voice; // Cartesia voice UUID (default: Sarah)
|
|
95
|
+
instructions?: string; // System prompt (default: general voice assistant)
|
|
96
|
+
greeting?: string; // Spoken on connect (default: "Hey, how can I help you?")
|
|
97
|
+
voice?: Voice; // Cartesia voice UUID (default: Sarah 694f9389...)
|
|
110
98
|
|
|
111
99
|
// Speech
|
|
112
100
|
sttPrompt?: string; // STT guidance for jargon, names, acronyms
|
|
@@ -118,8 +106,6 @@ defineAgent({
|
|
|
118
106
|
activeTools?: string[]; // Default active tools per turn (subset of all tools)
|
|
119
107
|
maxSteps?: number | ((ctx: HookContext) => number);
|
|
120
108
|
|
|
121
|
-
// Environment
|
|
122
|
-
|
|
123
109
|
// State
|
|
124
110
|
state?: () => S; // Factory for per-session state
|
|
125
111
|
|
|
@@ -407,6 +393,42 @@ onBeforeStep: (stepNumber, ctx) => {
|
|
|
407
393
|
},
|
|
408
394
|
```
|
|
409
395
|
|
|
396
|
+
### Tool choice
|
|
397
|
+
|
|
398
|
+
Control when the LLM uses tools:
|
|
399
|
+
|
|
400
|
+
```ts
|
|
401
|
+
toolChoice: "auto", // Default — LLM decides when to use tools
|
|
402
|
+
toolChoice: "required", // Force a tool call every step (useful for research pipelines)
|
|
403
|
+
toolChoice: "none", // Disable all tool use
|
|
404
|
+
toolChoice: { type: "tool", toolName: "search" }, // Force a specific tool
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Phase-based tool filtering
|
|
408
|
+
|
|
409
|
+
Combine `state`, `onBeforeStep`, and `activeTools` for multi-phase workflows:
|
|
410
|
+
|
|
411
|
+
```ts
|
|
412
|
+
state: () => ({ phase: "gather" as "gather" | "analyze" | "respond" }),
|
|
413
|
+
onBeforeStep: (_step, ctx) => {
|
|
414
|
+
const state = ctx.state as { phase: string };
|
|
415
|
+
if (state.phase === "gather") return { activeTools: ["web_search", "advance"] };
|
|
416
|
+
if (state.phase === "analyze") return { activeTools: ["summarize", "advance"] };
|
|
417
|
+
return { activeTools: [] }; // respond phase — LLM speaks freely
|
|
418
|
+
},
|
|
419
|
+
tools: {
|
|
420
|
+
advance: {
|
|
421
|
+
description: "Move to the next phase",
|
|
422
|
+
execute: (_args, ctx) => {
|
|
423
|
+
const state = ctx.state as { phase: string };
|
|
424
|
+
if (state.phase === "gather") state.phase = "analyze";
|
|
425
|
+
else if (state.phase === "analyze") state.phase = "respond";
|
|
426
|
+
return { phase: state.phase };
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
```
|
|
431
|
+
|
|
410
432
|
### Static `activeTools`
|
|
411
433
|
|
|
412
434
|
Restrict which tools the LLM can use by default, without writing a hook:
|
|
@@ -472,6 +494,7 @@ Add `client.tsx` alongside `agent.ts`. Define a Preact component and call
|
|
|
472
494
|
`mount()` to render it. Use JSX syntax:
|
|
473
495
|
|
|
474
496
|
```tsx
|
|
497
|
+
import "aai/ui/styles.css";
|
|
475
498
|
import { mount, useSession } from "aai/ui";
|
|
476
499
|
|
|
477
500
|
function App() {
|
|
@@ -497,6 +520,8 @@ mount(App);
|
|
|
497
520
|
|
|
498
521
|
**Rules:**
|
|
499
522
|
|
|
523
|
+
- Always import `"aai/ui/styles.css"` at the top — without it, default styles
|
|
524
|
+
won't load
|
|
500
525
|
- Call `mount(YourComponent)` at the end of the file
|
|
501
526
|
- Use `.tsx` file extension for JSX syntax
|
|
502
527
|
- Import hooks from `preact/hooks` (`useEffect`, `useRef`, `useState`, etc.)
|
|
@@ -561,6 +586,7 @@ data lives on `session` (a `VoiceSession`); UI-only controls are top-level.
|
|
|
561
586
|
### Showing tool calls in custom UI
|
|
562
587
|
|
|
563
588
|
```tsx
|
|
589
|
+
import "aai/ui/styles.css";
|
|
564
590
|
import { mount, ToolCallBlock, useSession } from "aai/ui";
|
|
565
591
|
|
|
566
592
|
function App() {
|
|
@@ -590,6 +616,7 @@ mount(App);
|
|
|
590
616
|
### Reacting to agent state
|
|
591
617
|
|
|
592
618
|
```tsx
|
|
619
|
+
import "aai/ui/styles.css";
|
|
593
620
|
import { useEffect } from "preact/hooks";
|
|
594
621
|
import { mount, StateIndicator, useSession } from "aai/ui";
|
|
595
622
|
|
|
@@ -646,6 +673,92 @@ function App() {
|
|
|
646
673
|
- `--color-aai-surface`, `--color-aai-border`
|
|
647
674
|
- `--color-aai-state-{state}` — color for each `AgentState` value
|
|
648
675
|
|
|
676
|
+
## Self-hosting with `createServer()`
|
|
677
|
+
|
|
678
|
+
Agents can run anywhere (Node, Deno, Docker) without the managed platform:
|
|
679
|
+
|
|
680
|
+
```ts
|
|
681
|
+
import { defineAgent } from "aai";
|
|
682
|
+
import { createServer } from "aai/server";
|
|
683
|
+
|
|
684
|
+
const agent = defineAgent({
|
|
685
|
+
name: "My Agent",
|
|
686
|
+
instructions: "You are a helpful assistant.",
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
const server = createServer(agent, {
|
|
690
|
+
port: 3000, // default: 3000
|
|
691
|
+
staticDir: "public", // optional: serve static files
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
server.listen();
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
Run with `node --experimental-strip-types server.ts` or bundle with your
|
|
698
|
+
preferred tool. The server handles WebSocket connections, STT/TTS, and the
|
|
699
|
+
agentic loop. Set `ASSEMBLYAI_API_KEY` as an environment variable.
|
|
700
|
+
|
|
701
|
+
## Useful free API endpoints
|
|
702
|
+
|
|
703
|
+
These public APIs require no auth and work well in voice agents:
|
|
704
|
+
|
|
705
|
+
```text
|
|
706
|
+
Weather (Open-Meteo):
|
|
707
|
+
Geocode: https://geocoding-api.open-meteo.com/v1/search?name={city}&count=1&language=en
|
|
708
|
+
Forecast: https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&daily=temperature_2m_max,temperature_2m_min,precipitation_sum,weathercode&timezone=auto&forecast_days=7
|
|
709
|
+
|
|
710
|
+
Currency (ExchangeRate):
|
|
711
|
+
Rates: https://open.er-api.com/v6/latest/{CODE} → { rates: { USD: 1.0, EUR: 0.85, ... } }
|
|
712
|
+
|
|
713
|
+
Crypto (CoinGecko):
|
|
714
|
+
Price: https://api.coingecko.com/api/v3/simple/price?ids={coin}&vs_currencies={cur}&include_24hr_change=true
|
|
715
|
+
|
|
716
|
+
Drug info (FDA):
|
|
717
|
+
Label: https://api.fda.gov/drug/label.json?search=openfda.generic_name:"{name}"&limit=1
|
|
718
|
+
|
|
719
|
+
Drug interactions (RxNorm):
|
|
720
|
+
RxCUI: https://rxnav.nlm.nih.gov/REST/rxcui.json?name={name}
|
|
721
|
+
Interactions: https://rxnav.nlm.nih.gov/REST/interaction/list.json?rxcuis={id1}+{id2}
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
Use `fetch_json` builtin tool or `fetch` in custom tools to call these.
|
|
725
|
+
|
|
726
|
+
## Partial custom UI with `ChatView`
|
|
727
|
+
|
|
728
|
+
For a custom start screen that transitions to the default chat interface:
|
|
729
|
+
|
|
730
|
+
```tsx
|
|
731
|
+
import "aai/ui/styles.css";
|
|
732
|
+
import { ChatView, mount, useSession } from "aai/ui";
|
|
733
|
+
|
|
734
|
+
function MyAgent() {
|
|
735
|
+
const { started, start } = useSession();
|
|
736
|
+
|
|
737
|
+
if (!started.value) {
|
|
738
|
+
return (
|
|
739
|
+
<div class="flex items-center justify-center h-screen bg-aai-bg">
|
|
740
|
+
<div class="flex flex-col items-center gap-6">
|
|
741
|
+
<h1 class="text-xl text-aai-text">My Agent</h1>
|
|
742
|
+
<button
|
|
743
|
+
class="px-8 py-3 rounded-aai bg-aai-primary text-white border-none cursor-pointer"
|
|
744
|
+
onClick={start}
|
|
745
|
+
>
|
|
746
|
+
Start
|
|
747
|
+
</button>
|
|
748
|
+
</div>
|
|
749
|
+
</div>
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
return <ChatView />;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
mount(MyAgent);
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
This gives you full control over the start screen while reusing the built-in
|
|
760
|
+
chat UI once the session begins.
|
|
761
|
+
|
|
649
762
|
## Project structure
|
|
650
763
|
|
|
651
764
|
After scaffolding, your project directory looks like:
|
|
@@ -661,12 +774,53 @@ my-agent/
|
|
|
661
774
|
.env # Local dev secrets (gitignored)
|
|
662
775
|
.gitignore # Ignores node_modules/, .aai/, .env, etc.
|
|
663
776
|
README.md # Getting started guide
|
|
664
|
-
CLAUDE.md # Agent API reference (
|
|
777
|
+
CLAUDE.md # Agent API reference (always loaded by Claude Code)
|
|
665
778
|
.aai/ # Build output (managed by CLI, gitignored)
|
|
666
779
|
project.json # Deploy target (slug, server URL)
|
|
667
780
|
build/ # Bundle output
|
|
668
781
|
```
|
|
669
782
|
|
|
783
|
+
## Instructions patterns from templates
|
|
784
|
+
|
|
785
|
+
Good instructions tell the LLM what it is, how to behave, and when to use each
|
|
786
|
+
tool. Study these patterns:
|
|
787
|
+
|
|
788
|
+
**Code execution agent** — force tool use for anything computational:
|
|
789
|
+
```
|
|
790
|
+
You MUST use the run_code tool for ANY question involving math, counting,
|
|
791
|
+
string manipulation, or data processing. NEVER do mental math or estimate.
|
|
792
|
+
Use console.log() to output intermediate steps.
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
**Research agent** — search before answering:
|
|
796
|
+
```
|
|
797
|
+
Search first. Never guess or rely on memory for factual questions.
|
|
798
|
+
Use visit_webpage when search snippets aren't detailed enough.
|
|
799
|
+
For complex questions, search multiple times with different queries.
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
**FAQ/support agent** — stay grounded in knowledge:
|
|
803
|
+
```
|
|
804
|
+
Always use vector_search to find relevant documentation before answering.
|
|
805
|
+
Base your answers strictly on the retrieved documentation — don't guess.
|
|
806
|
+
If search results aren't relevant, say the docs don't cover that topic.
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
**API-calling agent** — tell the LLM which endpoints to use:
|
|
810
|
+
```
|
|
811
|
+
API endpoints (use fetch_json):
|
|
812
|
+
- Currency rates: https://open.er-api.com/v6/latest/{CODE}
|
|
813
|
+
Returns { rates: { USD: 1.0, EUR: 0.85, ... } }
|
|
814
|
+
- Weather: https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}...
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
**Game/interactive agent** — establish world rules and voice style:
|
|
818
|
+
```
|
|
819
|
+
You ARE the game. Maintain world state, describe rooms, handle puzzles.
|
|
820
|
+
Keep descriptions to two to four sentences. No visual formatting.
|
|
821
|
+
Use directional words naturally: "To the north you see..." not "N: forest"
|
|
822
|
+
```
|
|
823
|
+
|
|
670
824
|
## Common pitfalls
|
|
671
825
|
|
|
672
826
|
- **Writing `instructions` with visual formatting** — Bullets, bold, numbered
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.4.7/schema.json",
|
|
3
|
+
"files": {
|
|
4
|
+
"includes": ["**"],
|
|
5
|
+
"ignores": ["node_modules", "dist", ".aai"]
|
|
6
|
+
},
|
|
7
|
+
"linter": {
|
|
8
|
+
"enabled": true,
|
|
9
|
+
"rules": {
|
|
10
|
+
"recommended": true,
|
|
11
|
+
"correctness": {
|
|
12
|
+
"noUnusedImports": "error",
|
|
13
|
+
"noUnusedVariables": "error"
|
|
14
|
+
},
|
|
15
|
+
"a11y": {
|
|
16
|
+
"recommended": false
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"formatter": {
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"indentStyle": "space",
|
|
23
|
+
"indentWidth": 2,
|
|
24
|
+
"lineWidth": 100
|
|
25
|
+
},
|
|
26
|
+
"javascript": {
|
|
27
|
+
"formatter": {
|
|
28
|
+
"quoteStyle": "double",
|
|
29
|
+
"semicolons": "always"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta
|
|
6
|
+
name="viewport"
|
|
7
|
+
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
|
|
8
|
+
/>
|
|
9
|
+
<title>aai</title>
|
|
10
|
+
<link rel="icon" href="data:," />
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<main id="app"></main>
|
|
14
|
+
<script type="module" src="./client.tsx"></script>
|
|
15
|
+
</body>
|
|
16
|
+
</html>
|
|
@@ -3,15 +3,16 @@
|
|
|
3
3
|
"scripts": {
|
|
4
4
|
"dev": "aai dev",
|
|
5
5
|
"build": "aai deploy --dry-run",
|
|
6
|
-
"deploy": "aai deploy"
|
|
6
|
+
"deploy": "aai deploy",
|
|
7
|
+
"lint": "biome check .",
|
|
8
|
+
"lint:fix": "biome check --write ."
|
|
7
9
|
},
|
|
8
10
|
"dependencies": {
|
|
9
|
-
"@alexkroman1/aai": "*"
|
|
10
|
-
"preact": "^10",
|
|
11
|
-
"@preact/signals": "^2",
|
|
12
|
-
"zod": "^4"
|
|
11
|
+
"@alexkroman1/aai": "*"
|
|
13
12
|
},
|
|
14
13
|
"devDependencies": {
|
|
14
|
+
"@biomejs/biome": "^2",
|
|
15
|
+
"@types/node": "^22",
|
|
15
16
|
"typescript": "^5"
|
|
16
17
|
}
|
|
17
18
|
}
|
package/ui/styles.css
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap");
|
|
2
|
+
@import "tailwindcss";
|
|
3
|
+
@source "./";
|
|
4
|
+
|
|
5
|
+
@theme {
|
|
6
|
+
--color-aai-bg: #101010;
|
|
7
|
+
--color-aai-surface: #151515;
|
|
8
|
+
--color-aai-surface-faint: rgba(255, 255, 255, 0.031);
|
|
9
|
+
--color-aai-surface-hover: rgba(255, 255, 255, 0.059);
|
|
10
|
+
--color-aai-border: #282828;
|
|
11
|
+
--color-aai-primary: #fab283;
|
|
12
|
+
--color-aai-text: rgba(255, 255, 255, 0.936);
|
|
13
|
+
--color-aai-text-secondary: rgba(255, 255, 255, 0.618);
|
|
14
|
+
--color-aai-text-muted: rgba(255, 255, 255, 0.284);
|
|
15
|
+
--color-aai-text-dim: rgba(255, 255, 255, 0.422);
|
|
16
|
+
--color-aai-error: #e06c75;
|
|
17
|
+
--color-aai-ring: #56b6c2;
|
|
18
|
+
--color-aai-state-disconnected: rgba(255, 255, 255, 0.422);
|
|
19
|
+
--color-aai-state-connecting: rgba(255, 255, 255, 0.422);
|
|
20
|
+
--color-aai-state-ready: #7fd88f;
|
|
21
|
+
--color-aai-state-listening: #56b6c2;
|
|
22
|
+
--color-aai-state-thinking: #f5a742;
|
|
23
|
+
--color-aai-state-speaking: #e06c75;
|
|
24
|
+
--color-aai-state-error: #e06c75;
|
|
25
|
+
--radius-aai: 6px;
|
|
26
|
+
--font-aai: "Inter", system-ui, -apple-system, sans-serif;
|
|
27
|
+
--font-aai-mono: "IBM Plex Mono", monospace;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@layer base {
|
|
31
|
+
html,
|
|
32
|
+
body {
|
|
33
|
+
margin: 0;
|
|
34
|
+
padding: 0;
|
|
35
|
+
background: var(--color-aai-bg);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@keyframes aai-bounce {
|
|
40
|
+
0%,
|
|
41
|
+
80%,
|
|
42
|
+
100% {
|
|
43
|
+
opacity: 0.3;
|
|
44
|
+
transform: scale(0.8);
|
|
45
|
+
}
|
|
46
|
+
40% {
|
|
47
|
+
opacity: 1;
|
|
48
|
+
transform: scale(1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@keyframes aai-shimmer {
|
|
53
|
+
0% {
|
|
54
|
+
background-position: -200% 0;
|
|
55
|
+
}
|
|
56
|
+
100% {
|
|
57
|
+
background-position: 200% 0;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.tool-shimmer {
|
|
62
|
+
background: linear-gradient(
|
|
63
|
+
90deg,
|
|
64
|
+
var(--color-aai-text) 25%,
|
|
65
|
+
var(--color-aai-text-dim) 50%,
|
|
66
|
+
var(--color-aai-text) 75%
|
|
67
|
+
);
|
|
68
|
+
background-size: 200% 100%;
|
|
69
|
+
-webkit-background-clip: text;
|
|
70
|
+
background-clip: text;
|
|
71
|
+
-webkit-text-fill-color: transparent;
|
|
72
|
+
animation: aai-shimmer 2s ease-in-out infinite;
|
|
73
|
+
}
|