@agent-native/core 0.2.8 → 0.3.2
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/README.md +59 -26
- package/dist/a2a/agent-card.d.ts +3 -0
- package/dist/a2a/agent-card.d.ts.map +1 -0
- package/dist/a2a/agent-card.js +26 -0
- package/dist/a2a/agent-card.js.map +1 -0
- package/dist/a2a/client.d.ts +25 -0
- package/dist/a2a/client.d.ts.map +1 -0
- package/dist/a2a/client.js +119 -0
- package/dist/a2a/client.js.map +1 -0
- package/dist/a2a/handlers.d.ts +4 -0
- package/dist/a2a/handlers.d.ts.map +1 -0
- package/dist/a2a/handlers.js +252 -0
- package/dist/a2a/handlers.js.map +1 -0
- package/dist/a2a/index.d.ts +4 -0
- package/dist/a2a/index.d.ts.map +1 -0
- package/dist/a2a/index.js +5 -0
- package/dist/a2a/index.js.map +1 -0
- package/dist/a2a/middleware.d.ts +3 -0
- package/dist/a2a/middleware.d.ts.map +1 -0
- package/dist/a2a/middleware.js +36 -0
- package/dist/a2a/middleware.js.map +1 -0
- package/dist/a2a/server.d.ts +4 -0
- package/dist/a2a/server.d.ts.map +1 -0
- package/dist/a2a/server.js +18 -0
- package/dist/a2a/server.js.map +1 -0
- package/dist/a2a/task-store.d.ts +10 -0
- package/dist/a2a/task-store.d.ts.map +1 -0
- package/dist/a2a/task-store.js +73 -0
- package/dist/a2a/task-store.js.map +1 -0
- package/dist/a2a/types.d.ts +109 -0
- package/dist/a2a/types.d.ts.map +1 -0
- package/dist/a2a/types.js +3 -0
- package/dist/a2a/types.js.map +1 -0
- package/dist/adapters/cli/index.d.ts +4 -0
- package/dist/adapters/cli/index.d.ts.map +1 -0
- package/dist/adapters/cli/index.js +3 -0
- package/dist/adapters/cli/index.js.map +1 -0
- package/dist/adapters/cli/registry.d.ts +33 -0
- package/dist/adapters/cli/registry.d.ts.map +1 -0
- package/dist/adapters/cli/registry.js +62 -0
- package/dist/adapters/cli/registry.js.map +1 -0
- package/dist/adapters/cli/shell-adapter.d.ts +42 -0
- package/dist/adapters/cli/shell-adapter.d.ts.map +1 -0
- package/dist/adapters/cli/shell-adapter.js +57 -0
- package/dist/adapters/cli/shell-adapter.js.map +1 -0
- package/dist/adapters/cli/types.d.ts +24 -0
- package/dist/adapters/cli/types.d.ts.map +1 -0
- package/dist/adapters/cli/types.js +2 -0
- package/dist/adapters/cli/types.js.map +1 -0
- package/dist/adapters/firestore/adapter.d.ts.map +1 -1
- package/dist/adapters/firestore/adapter.js.map +1 -1
- package/dist/adapters/neon/adapter.d.ts.map +1 -1
- package/dist/adapters/neon/adapter.js +37 -21
- package/dist/adapters/neon/adapter.js.map +1 -1
- package/dist/adapters/supabase/adapter.d.ts.map +1 -1
- package/dist/adapters/supabase/adapter.js +10 -2
- package/dist/adapters/supabase/adapter.js.map +1 -1
- package/dist/adapters/sync/file-sync.d.ts.map +1 -1
- package/dist/adapters/sync/file-sync.js.map +1 -1
- package/dist/adapters/sync/index.d.ts +2 -2
- package/dist/adapters/sync/index.d.ts.map +1 -1
- package/dist/adapters/sync/index.js +1 -1
- package/dist/adapters/sync/index.js.map +1 -1
- package/dist/adapters/sync/merge.js +1 -2
- package/dist/adapters/sync/merge.js.map +1 -1
- package/dist/adapters/sync/types.d.ts.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +15 -13
- package/dist/cli/index.js.map +1 -1
- package/dist/client/components/ApiKeySettings.d.ts +1 -1
- package/dist/client/components/ApiKeySettings.d.ts.map +1 -1
- package/dist/client/components/ApiKeySettings.js +9 -4
- package/dist/client/components/ApiKeySettings.js.map +1 -1
- package/dist/client/components/MissingKeyCard.d.ts +1 -1
- package/dist/client/components/MissingKeyCard.d.ts.map +1 -1
- package/dist/client/components/MissingKeyCard.js +1 -1
- package/dist/client/components/MissingKeyCard.js.map +1 -1
- package/dist/client/harness.d.ts +10 -0
- package/dist/client/harness.d.ts.map +1 -1
- package/dist/client/harness.js +27 -0
- package/dist/client/harness.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/use-file-watcher.d.ts.map +1 -1
- package/dist/client/use-file-watcher.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/scripts/utils.d.ts.map +1 -1
- package/dist/scripts/utils.js +3 -1
- package/dist/scripts/utils.js.map +1 -1
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +2 -1
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/missing-key.d.ts.map +1 -1
- package/dist/server/missing-key.js.map +1 -1
- package/dist/server/production.d.ts.map +1 -1
- package/dist/server/production.js.map +1 -1
- package/dist/server/sse.d.ts +1 -1
- package/dist/server/sse.d.ts.map +1 -1
- package/dist/server/sse.js.map +1 -1
- package/dist/shared/agent-chat.d.ts +18 -0
- package/dist/shared/agent-chat.d.ts.map +1 -1
- package/dist/shared/agent-chat.js +35 -0
- package/dist/shared/agent-chat.js.map +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/index.js.map +1 -1
- package/package.json +127 -125
- package/src/templates/default/.agents/skills/capture-learnings/SKILL.md +50 -0
- package/src/templates/default/.agents/skills/create-skill/SKILL.md +167 -0
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +90 -0
- package/src/templates/default/.agents/skills/files-as-database/SKILL.md +91 -0
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +69 -0
- package/src/templates/default/.agents/skills/scripts/SKILL.md +118 -0
- package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +79 -0
- package/src/templates/default/.agents/skills/sse-file-watcher/SKILL.md +95 -0
- package/src/templates/default/.claude/settings.json +86 -68
- package/src/templates/default/.prettierrc +5 -5
- package/src/templates/default/AGENTS.md +86 -69
- package/src/templates/default/client/App.tsx +56 -54
- package/src/templates/default/client/global.css +75 -72
- package/src/templates/default/client/lib/utils.ts +1 -1
- package/src/templates/default/client/vite-env.d.ts +1 -1
- package/src/templates/default/components.json +20 -20
- package/src/templates/default/index.html +14 -14
- package/src/templates/default/package.json +43 -43
- package/src/templates/default/postcss.config.js +6 -6
- package/src/templates/default/scripts/hello.ts +20 -20
- package/src/templates/default/scripts/run.ts +9 -9
- package/src/templates/default/server/index.ts +22 -18
- package/src/templates/default/server/node-build.ts +4 -4
- package/src/templates/default/shared/api.ts +6 -6
- package/src/templates/default/tailwind.config.ts +7 -7
- package/src/templates/default/tsconfig.json +3 -3
- package/src/templates/default/vite.config.server.ts +3 -3
- package/src/templates/default/vite.config.ts +3 -3
- package/tsconfig.base.json +41 -41
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-design
|
|
3
|
+
description: >-
|
|
4
|
+
Create distinctive, production-grade frontend interfaces with high design
|
|
5
|
+
quality. Use when building web components, pages, artifacts, posters, or
|
|
6
|
+
applications (websites, landing pages, dashboards, React components,
|
|
7
|
+
HTML/CSS layouts, or when styling/beautifying any web UI). Generates
|
|
8
|
+
creative, polished UI that avoids generic AI aesthetics.
|
|
9
|
+
license: Complete terms in LICENSE.txt
|
|
10
|
+
source: https://github.com/anthropics/skills/blob/main/skills/frontend-design/SKILL.md
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Frontend Design
|
|
14
|
+
|
|
15
|
+
This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
|
16
|
+
|
|
17
|
+
The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
|
|
18
|
+
|
|
19
|
+
## Design Thinking
|
|
20
|
+
|
|
21
|
+
Before coding, understand the context and commit to a BOLD aesthetic direction:
|
|
22
|
+
- **Purpose**: What problem does this interface solve? Who uses it?
|
|
23
|
+
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
|
24
|
+
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
|
25
|
+
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
|
26
|
+
|
|
27
|
+
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work — the key is intentionality, not intensity.
|
|
28
|
+
|
|
29
|
+
Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
|
|
30
|
+
- Production-grade and functional
|
|
31
|
+
- Visually striking and memorable
|
|
32
|
+
- Cohesive with a clear aesthetic point-of-view
|
|
33
|
+
- Meticulously refined in every detail
|
|
34
|
+
|
|
35
|
+
## Frontend Aesthetics Guidelines
|
|
36
|
+
|
|
37
|
+
Focus on:
|
|
38
|
+
- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
|
|
39
|
+
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
|
40
|
+
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (`animation-delay`) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
|
|
41
|
+
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
|
|
42
|
+
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
|
|
43
|
+
|
|
44
|
+
## Anti-Patterns to Avoid
|
|
45
|
+
|
|
46
|
+
NEVER use generic AI-generated aesthetics like:
|
|
47
|
+
- Overused font families (Inter, Roboto, Arial, system fonts)
|
|
48
|
+
- Clichéd color schemes (particularly purple gradients on white backgrounds)
|
|
49
|
+
- Predictable layouts and component patterns
|
|
50
|
+
- Cookie-cutter design that lacks context-specific character
|
|
51
|
+
|
|
52
|
+
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
|
|
53
|
+
|
|
54
|
+
## Implementation Notes
|
|
55
|
+
|
|
56
|
+
**Match implementation complexity to the aesthetic vision.** Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
|
|
57
|
+
|
|
58
|
+
In the agent-native framework context:
|
|
59
|
+
- Agent-native apps use React 18, Vite, TailwindCSS, and shadcn/ui
|
|
60
|
+
- Custom styles go in component CSS or Tailwind classes — never inline styles
|
|
61
|
+
- For complex visual effects, use a `<style>` tag in the component or a dedicated CSS file
|
|
62
|
+
- Fonts can be loaded from Google Fonts via `@import` in a CSS file or `<link>` in `index.html`
|
|
63
|
+
- Animation libraries: prefer CSS transitions and keyframes; use Framer Motion for complex sequences
|
|
64
|
+
- All new UI components should be placed in `client/components/`
|
|
65
|
+
|
|
66
|
+
## Related Skills
|
|
67
|
+
|
|
68
|
+
- **self-modifying-code** — The agent can edit source code to apply design changes
|
|
69
|
+
- **files-as-database** — Design configuration can be stored as JSON in `data/` for agent-editable theming
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scripts
|
|
3
|
+
description: >-
|
|
4
|
+
How to create and run agent-callable scripts in scripts/. Use when creating
|
|
5
|
+
a new script, adding an API integration, implementing a complex agent
|
|
6
|
+
operation, or running pnpm script commands.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Agent Scripts
|
|
10
|
+
|
|
11
|
+
## Rule
|
|
12
|
+
|
|
13
|
+
Complex operations the agent needs to perform are implemented as scripts in `scripts/`. The agent runs them via `pnpm script <name>`.
|
|
14
|
+
|
|
15
|
+
## Why
|
|
16
|
+
|
|
17
|
+
Scripts give the agent callable tools with structured input/output. They keep the agent's chat context clean (no massive code blocks), they're reusable, and they can be tested independently.
|
|
18
|
+
|
|
19
|
+
## How to Create a Script
|
|
20
|
+
|
|
21
|
+
Create `scripts/my-script.ts`:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import fs from "fs";
|
|
25
|
+
import { parseArgs, loadEnv, fail, agentChat } from "@agent-native/core";
|
|
26
|
+
|
|
27
|
+
export default async function myScript(args: string[]) {
|
|
28
|
+
loadEnv();
|
|
29
|
+
|
|
30
|
+
const parsed = parseArgs(args);
|
|
31
|
+
const input = parsed.input;
|
|
32
|
+
if (!input) fail("--input is required");
|
|
33
|
+
|
|
34
|
+
const outputPath = parsed.output ?? "data/result.json";
|
|
35
|
+
const raw = fs.readFileSync(input, "utf-8");
|
|
36
|
+
const data = JSON.parse(raw) as unknown;
|
|
37
|
+
|
|
38
|
+
fs.writeFileSync(outputPath, JSON.stringify(data, null, 2));
|
|
39
|
+
agentChat.submit(`Processed ${input}, result saved to ${outputPath}`);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## How to Run
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pnpm script my-script --input data/source.json --output data/result.json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Script Dispatcher
|
|
50
|
+
|
|
51
|
+
The default template uses core's `runScript()` in `scripts/run.ts`:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { runScript } from "@agent-native/core";
|
|
55
|
+
runScript();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This is the canonical approach for new apps. Script names must be lowercase with hyphens only (e.g., `my-script`).
|
|
59
|
+
|
|
60
|
+
## Guidelines
|
|
61
|
+
|
|
62
|
+
- **One script, one job.** Keep scripts focused on a single operation. The agent composes multiple script calls for complex operations.
|
|
63
|
+
- **Use `parseArgs()`** for structured argument parsing. It converts `--key value` pairs to a `Record<string, string>`.
|
|
64
|
+
- **Use `loadEnv()`** if the script needs environment variables (API keys, etc.).
|
|
65
|
+
- **Use `fail()`** for user-friendly error messages (exits with message, no stack trace).
|
|
66
|
+
- **Write results to files.** The agent and UI will pick them up via the file watcher.
|
|
67
|
+
- **Use `agentChat.submit()`** to report results or errors back to the agent chat.
|
|
68
|
+
- **Import from `@agent-native/core`** — Don't redefine `parseArgs()` or other utilities locally.
|
|
69
|
+
|
|
70
|
+
## Common Patterns
|
|
71
|
+
|
|
72
|
+
**API integration script** (e.g., image generation):
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import fs from "fs";
|
|
76
|
+
import { parseArgs, loadEnv, fail } from "@agent-native/core";
|
|
77
|
+
|
|
78
|
+
export default async function generateImage(args: string[]) {
|
|
79
|
+
loadEnv();
|
|
80
|
+
const parsed = parseArgs(args);
|
|
81
|
+
const prompt = parsed.prompt;
|
|
82
|
+
if (!prompt) fail("--prompt is required");
|
|
83
|
+
|
|
84
|
+
const outputPath = parsed.output ?? "data/generated-image.png";
|
|
85
|
+
const imageUrl = await callImageAPI(prompt);
|
|
86
|
+
const buffer = await fetch(imageUrl).then((r) => r.arrayBuffer());
|
|
87
|
+
fs.writeFileSync(outputPath, Buffer.from(buffer));
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Data processing script:**
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import fs from "fs";
|
|
95
|
+
import { parseArgs, fail } from "@agent-native/core";
|
|
96
|
+
|
|
97
|
+
export default async function transform(args: string[]) {
|
|
98
|
+
const parsed = parseArgs(args);
|
|
99
|
+
const source = parsed.source;
|
|
100
|
+
if (!source) fail("--source is required");
|
|
101
|
+
|
|
102
|
+
const data = JSON.parse(fs.readFileSync(source, "utf-8")) as unknown[];
|
|
103
|
+
const result = data.map(transformItem);
|
|
104
|
+
fs.writeFileSync(source, JSON.stringify(result, null, 2));
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Troubleshooting
|
|
109
|
+
|
|
110
|
+
- **Script not found** — Check that the filename matches the command name exactly. `pnpm script foo-bar` looks for `scripts/foo-bar.ts`.
|
|
111
|
+
- **Args not parsing** — Ensure args use `--key value` or `--key=value` format. Boolean flags use `--flag` (sets value to `"true"`).
|
|
112
|
+
- **Script runs but UI doesn't update** — Make sure results are written to a path under `data/` that the file watcher monitors.
|
|
113
|
+
|
|
114
|
+
## Related Skills
|
|
115
|
+
|
|
116
|
+
- **files-as-database** — Scripts read/write data files in `data/`
|
|
117
|
+
- **delegate-to-agent** — The agent invokes scripts via `pnpm script <name>`
|
|
118
|
+
- **sse-file-watcher** — File writes from scripts trigger SSE events to update the UI
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: self-modifying-code
|
|
3
|
+
description: >-
|
|
4
|
+
How the agent can modify the app's own source code. Use when the agent needs
|
|
5
|
+
to edit components, routes, styles, or scripts, when designing UI for agent
|
|
6
|
+
editability, or when deciding what the agent should and shouldn't modify.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Self-Modifying Code
|
|
10
|
+
|
|
11
|
+
## Rule
|
|
12
|
+
|
|
13
|
+
The agent can edit the app's own source code — components, routes, styles, scripts. This is a feature, not a bug. Design your app expecting this.
|
|
14
|
+
|
|
15
|
+
## Why
|
|
16
|
+
|
|
17
|
+
An agent-native app isn't just an app the agent can _use_ — it's an app the agent can _change_. The agent can fix bugs, add features, adjust styles, and restructure code. This makes the agent a true collaborator, not just an operator.
|
|
18
|
+
|
|
19
|
+
## Modification Taxonomy
|
|
20
|
+
|
|
21
|
+
Not all modifications are equal. Use this to decide what level of care is needed:
|
|
22
|
+
|
|
23
|
+
| Tier | What | Examples | After modifying |
|
|
24
|
+
| ------------- | --------------------- | ------------------------------------------------ | --------------------------------- |
|
|
25
|
+
| 1: Data | Files in `data/` | JSON state, generated content, markdown | Nothing — these are routine |
|
|
26
|
+
| 2: Source | App code | Components, routes, styles, scripts | Run `pnpm typecheck && pnpm lint` |
|
|
27
|
+
| 3: Config | Project config | `package.json`, `tsconfig.json`, `vite.config.*` | Ask for explicit approval first |
|
|
28
|
+
| 4: Off limits | Secrets and framework | `.env`, `@agent-native/core` internals | Never modify these |
|
|
29
|
+
|
|
30
|
+
## Git Checkpoint Pattern
|
|
31
|
+
|
|
32
|
+
Before modifying source code (Tier 2+), create a rollback point:
|
|
33
|
+
|
|
34
|
+
1. Commit or stash current state
|
|
35
|
+
2. Make the edit
|
|
36
|
+
3. Run `pnpm typecheck && pnpm lint`
|
|
37
|
+
4. If verification fails → revert with `git checkout -- <file>`
|
|
38
|
+
5. If verification passes → continue
|
|
39
|
+
|
|
40
|
+
This ensures the agent can experiment without breaking the app.
|
|
41
|
+
|
|
42
|
+
## Designing for Agent Editability
|
|
43
|
+
|
|
44
|
+
Make your app easy for the agent to understand and modify:
|
|
45
|
+
|
|
46
|
+
**Expose UI state via `data-*` attributes** so the agent knows what's selected:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
const el = document.documentElement;
|
|
50
|
+
el.dataset.currentView = view;
|
|
51
|
+
el.dataset.selectedId = selectedItem?.id || "";
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Expose richer context via `window.__appState`** for complex state:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
(window as any).__appState = {
|
|
58
|
+
selectedId: id,
|
|
59
|
+
currentLayout: layout,
|
|
60
|
+
itemCount: items.length,
|
|
61
|
+
};
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Use configuration-driven rendering** — Extract visual decisions (colors, layouts, sizes) into JSON config files in `data/`. The agent can modify the config (Tier 1) instead of the component source (Tier 2).
|
|
65
|
+
|
|
66
|
+
## Don't
|
|
67
|
+
|
|
68
|
+
- Don't modify `.env` files or files containing secrets
|
|
69
|
+
- Don't modify `@agent-native/core` package internals
|
|
70
|
+
- Don't modify `.agents/skills/` or `AGENTS.md` unless explicitly requested
|
|
71
|
+
- Don't skip the typecheck/lint step after editing source code
|
|
72
|
+
- Don't make source changes without a git checkpoint to roll back to
|
|
73
|
+
|
|
74
|
+
## Related Skills
|
|
75
|
+
|
|
76
|
+
- **files-as-database** — Tier 1 modifications (data files) are the safest and most common
|
|
77
|
+
- **scripts** — The agent can create or modify scripts to add new capabilities
|
|
78
|
+
- **delegate-to-agent** — Self-modification requests come through the agent chat
|
|
79
|
+
- **sse-file-watcher** — Source and data file edits trigger SSE events to update the UI
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sse-file-watcher
|
|
3
|
+
description: >-
|
|
4
|
+
How to keep the UI in sync with agent changes via Server-Sent Events. Use
|
|
5
|
+
when setting up real-time file sync, adding SSE to a new data directory,
|
|
6
|
+
wiring query invalidation for new data models, or debugging UI not updating.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# SSE File Watcher
|
|
10
|
+
|
|
11
|
+
## Rule
|
|
12
|
+
|
|
13
|
+
The UI stays in sync with agent changes through Server-Sent Events. When the agent writes a file, the UI updates automatically — no polling, no manual refresh.
|
|
14
|
+
|
|
15
|
+
## Why
|
|
16
|
+
|
|
17
|
+
The agent modifies files on disk, but the UI runs in the browser. SSE bridges this gap: a file watcher on the server detects changes, streams them to the browser, and React Query invalidates the relevant caches. This is what makes the "files as database" pattern feel real-time.
|
|
18
|
+
|
|
19
|
+
## How It Works
|
|
20
|
+
|
|
21
|
+
1. **Server** watches the data directory with chokidar:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { createFileWatcher, createSSEHandler } from "@agent-native/core";
|
|
25
|
+
const watcher = createFileWatcher("./data");
|
|
26
|
+
app.get("/api/events", createSSEHandler(watcher));
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
2. **Client** listens for changes and invalidates React Query caches:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { useFileWatcher } from "@agent-native/core";
|
|
33
|
+
useFileWatcher({ queryClient, queryKeys: ["files", "projects"] });
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
3. When the agent writes to `data/`, chokidar detects it, SSE pushes the event, and React Query refetches the affected queries.
|
|
37
|
+
|
|
38
|
+
## Don't
|
|
39
|
+
|
|
40
|
+
- Don't poll for changes — SSE handles it
|
|
41
|
+
- Don't create per-model `fs.watch()` instances — `createFileWatcher("./data")` watches recursively. One watcher is enough.
|
|
42
|
+
- Don't create your own EventSource connections alongside `useFileWatcher` — use the `onEvent` callback for custom handling
|
|
43
|
+
|
|
44
|
+
## Query Key Mapping
|
|
45
|
+
|
|
46
|
+
By default, `useFileWatcher` invalidates all listed query keys on every file change. For apps with multiple data models, this causes unnecessary refetches. Use path-based filtering via the `onEvent` callback:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
useFileWatcher({
|
|
50
|
+
queryClient,
|
|
51
|
+
queryKeys: [], // don't auto-invalidate everything
|
|
52
|
+
onEvent: (data) => {
|
|
53
|
+
if (data.path?.includes("projects")) {
|
|
54
|
+
queryClient.invalidateQueries({ queryKey: ["projects"] });
|
|
55
|
+
} else if (data.path?.includes("settings")) {
|
|
56
|
+
queryClient.invalidateQueries({ queryKey: ["settings"] });
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
To prevent cache thrashing during rapid agent writes, set `staleTime` on your queries:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
useQuery({
|
|
66
|
+
queryKey: ["projects"],
|
|
67
|
+
queryFn: fetchProjects,
|
|
68
|
+
staleTime: 2000, // don't refetch within 2 seconds
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Performance
|
|
73
|
+
|
|
74
|
+
When the agent writes many files rapidly (e.g., during self-modification), each write fires a chokidar event → SSE broadcast → React Query invalidation. This can cause excessive refetching.
|
|
75
|
+
|
|
76
|
+
Mitigations:
|
|
77
|
+
|
|
78
|
+
- Use `staleTime: 2000` on React Query to debounce refetches
|
|
79
|
+
- Use path-based filtering (see Query Key Mapping) to limit which queries invalidate
|
|
80
|
+
|
|
81
|
+
## Troubleshooting
|
|
82
|
+
|
|
83
|
+
| Symptom | Check |
|
|
84
|
+
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
85
|
+
| UI not updating after agent writes | Is `useFileWatcher` called with the correct `queryClient`? Are the `queryKeys` matching your `useQuery` keys? |
|
|
86
|
+
| SSE not firing | Open browser devtools → Network tab → filter by EventStream. Is `/api/events` connected? Is the server running? |
|
|
87
|
+
| Watcher not detecting changes | Is the path correct? `createFileWatcher("./data")` is relative to CWD. Check the server's working directory. |
|
|
88
|
+
| Constant reconnections | Check for server crashes in terminal output. |
|
|
89
|
+
| High CPU / event storms | The agent is writing many files rapidly. Add `staleTime` to queries and use path-based filtering. |
|
|
90
|
+
|
|
91
|
+
## Related Skills
|
|
92
|
+
|
|
93
|
+
- **files-as-database** — SSE watches the data files that store application state
|
|
94
|
+
- **scripts** — Script outputs written to `data/` trigger SSE events
|
|
95
|
+
- **self-modifying-code** — Agent code edits trigger SSE events; rapid edits can cause event storms
|
|
@@ -1,68 +1,86 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Read",
|
|
5
|
-
"Edit",
|
|
6
|
-
"Write",
|
|
7
|
-
"Glob",
|
|
8
|
-
"Grep",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"Bash(
|
|
13
|
-
"Bash(
|
|
14
|
-
"Bash(
|
|
15
|
-
"Bash(
|
|
16
|
-
"Bash(
|
|
17
|
-
"Bash(
|
|
18
|
-
"Bash(
|
|
19
|
-
"Bash(
|
|
20
|
-
"Bash(
|
|
21
|
-
"Bash(
|
|
22
|
-
"Bash(
|
|
23
|
-
"Bash(
|
|
24
|
-
"Bash(
|
|
25
|
-
"Bash(
|
|
26
|
-
"Bash(
|
|
27
|
-
"Bash(
|
|
28
|
-
"Bash(
|
|
29
|
-
"Bash(
|
|
30
|
-
"Bash(
|
|
31
|
-
"Bash(
|
|
32
|
-
"Bash(
|
|
33
|
-
"Bash(
|
|
34
|
-
"Bash(
|
|
35
|
-
"Bash(
|
|
36
|
-
"Bash(
|
|
37
|
-
"Bash(
|
|
38
|
-
"Bash(
|
|
39
|
-
"Bash(
|
|
40
|
-
"Bash(
|
|
41
|
-
"Bash(git
|
|
42
|
-
"Bash(git
|
|
43
|
-
"Bash(git
|
|
44
|
-
"Bash(git
|
|
45
|
-
"Bash(git
|
|
46
|
-
"Bash(git
|
|
47
|
-
"Bash(git
|
|
48
|
-
"Bash(git
|
|
49
|
-
"Bash(git
|
|
50
|
-
"Bash(
|
|
51
|
-
"Bash(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"Bash(
|
|
55
|
-
"Bash(
|
|
56
|
-
"Bash(git
|
|
57
|
-
"Bash(git
|
|
58
|
-
"Bash(
|
|
59
|
-
"Bash(
|
|
60
|
-
"Bash(
|
|
61
|
-
"Bash(
|
|
62
|
-
"Bash(
|
|
63
|
-
"Bash(
|
|
64
|
-
"Bash(
|
|
65
|
-
"Bash(
|
|
66
|
-
]
|
|
67
|
-
|
|
68
|
-
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Read",
|
|
5
|
+
"Edit",
|
|
6
|
+
"Write",
|
|
7
|
+
"Glob",
|
|
8
|
+
"Grep",
|
|
9
|
+
"NotebookEdit",
|
|
10
|
+
"WebFetch",
|
|
11
|
+
"WebSearch",
|
|
12
|
+
"Bash(ls *)",
|
|
13
|
+
"Bash(pwd)",
|
|
14
|
+
"Bash(echo *)",
|
|
15
|
+
"Bash(cat *)",
|
|
16
|
+
"Bash(head *)",
|
|
17
|
+
"Bash(tail *)",
|
|
18
|
+
"Bash(find *)",
|
|
19
|
+
"Bash(wc *)",
|
|
20
|
+
"Bash(sort *)",
|
|
21
|
+
"Bash(uniq *)",
|
|
22
|
+
"Bash(diff *)",
|
|
23
|
+
"Bash(which *)",
|
|
24
|
+
"Bash(env)",
|
|
25
|
+
"Bash(mkdir *)",
|
|
26
|
+
"Bash(cp *)",
|
|
27
|
+
"Bash(mv *)",
|
|
28
|
+
"Bash(touch *)",
|
|
29
|
+
"Bash(chmod *)",
|
|
30
|
+
"Bash(node *)",
|
|
31
|
+
"Bash(npx *)",
|
|
32
|
+
"Bash(npm *)",
|
|
33
|
+
"Bash(pnpm *)",
|
|
34
|
+
"Bash(yarn *)",
|
|
35
|
+
"Bash(tsx *)",
|
|
36
|
+
"Bash(tsc *)",
|
|
37
|
+
"Bash(vitest *)",
|
|
38
|
+
"Bash(jest *)",
|
|
39
|
+
"Bash(eslint *)",
|
|
40
|
+
"Bash(prettier *)",
|
|
41
|
+
"Bash(git status*)",
|
|
42
|
+
"Bash(git log *)",
|
|
43
|
+
"Bash(git diff *)",
|
|
44
|
+
"Bash(git show *)",
|
|
45
|
+
"Bash(git branch*)",
|
|
46
|
+
"Bash(git add *)",
|
|
47
|
+
"Bash(git commit *)",
|
|
48
|
+
"Bash(git checkout *)",
|
|
49
|
+
"Bash(git switch *)",
|
|
50
|
+
"Bash(git stash *)",
|
|
51
|
+
"Bash(git merge *)",
|
|
52
|
+
"Bash(git rebase *)",
|
|
53
|
+
"Bash(git pull *)",
|
|
54
|
+
"Bash(git blame *)",
|
|
55
|
+
"Bash(git rev-parse *)",
|
|
56
|
+
"Bash(git worktree *)",
|
|
57
|
+
"Bash(git remote -v)",
|
|
58
|
+
"Bash(gh *)",
|
|
59
|
+
"Bash(curl *)",
|
|
60
|
+
"Bash(grep *)",
|
|
61
|
+
"Bash(rg *)",
|
|
62
|
+
"Bash(sed *)",
|
|
63
|
+
"Bash(awk *)",
|
|
64
|
+
"Bash(jq *)",
|
|
65
|
+
"Bash(rm *)"
|
|
66
|
+
],
|
|
67
|
+
"deny": [
|
|
68
|
+
"Bash(rm -rf /)",
|
|
69
|
+
"Bash(rm -rf /*)",
|
|
70
|
+
"Bash(rm -rf ~)",
|
|
71
|
+
"Bash(rm -rf ~/*)",
|
|
72
|
+
"Bash(sudo *)",
|
|
73
|
+
"Bash(git push --force *)",
|
|
74
|
+
"Bash(git push -f *)",
|
|
75
|
+
"Bash(git reset --hard *)",
|
|
76
|
+
"Bash(git clean -f *)",
|
|
77
|
+
"Bash(dd *)",
|
|
78
|
+
"Bash(mkfs *)",
|
|
79
|
+
"Bash(kill -9 *)",
|
|
80
|
+
"Bash(killall *)",
|
|
81
|
+
"Bash(pkill *)",
|
|
82
|
+
"Bash(shutdown *)",
|
|
83
|
+
"Bash(reboot *)"
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
{
|
|
2
|
-
"tabWidth": 2,
|
|
3
|
-
"useTabs": false,
|
|
4
|
-
"trailingComma": "all"
|
|
5
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"tabWidth": 2,
|
|
3
|
+
"useTabs": false,
|
|
4
|
+
"trailingComma": "all"
|
|
5
|
+
}
|