@agent-native/core 0.4.1 → 0.4.3
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 +31 -0
- package/dist/adapters/convex/adapter.d.ts +24 -0
- package/dist/adapters/convex/adapter.d.ts.map +1 -0
- package/dist/adapters/convex/adapter.js +125 -0
- package/dist/adapters/convex/adapter.js.map +1 -0
- package/dist/adapters/convex/index.d.ts +4 -0
- package/dist/adapters/convex/index.d.ts.map +1 -0
- package/dist/adapters/convex/index.js +3 -0
- package/dist/adapters/convex/index.js.map +1 -0
- package/dist/adapters/drizzle/adapter.d.ts +36 -0
- package/dist/adapters/drizzle/adapter.d.ts.map +1 -0
- package/dist/adapters/drizzle/adapter.js +210 -0
- package/dist/adapters/drizzle/adapter.js.map +1 -0
- package/dist/adapters/drizzle/index.d.ts +3 -0
- package/dist/adapters/drizzle/index.d.ts.map +1 -0
- package/dist/adapters/drizzle/index.js +3 -0
- package/dist/adapters/drizzle/index.js.map +1 -0
- package/dist/adapters/drizzle/schema.d.ts +146 -0
- package/dist/adapters/drizzle/schema.d.ts.map +1 -0
- package/dist/adapters/drizzle/schema.js +20 -0
- package/dist/adapters/drizzle/schema.js.map +1 -0
- package/dist/adapters/firestore/adapter.d.ts +3 -2
- package/dist/adapters/firestore/adapter.d.ts.map +1 -1
- package/dist/adapters/firestore/adapter.js +23 -6
- package/dist/adapters/firestore/adapter.js.map +1 -1
- package/dist/adapters/supabase/adapter.d.ts +2 -1
- package/dist/adapters/supabase/adapter.d.ts.map +1 -1
- package/dist/adapters/supabase/adapter.js +4 -1
- package/dist/adapters/supabase/adapter.js.map +1 -1
- package/dist/adapters/sync/config.d.ts +22 -2
- package/dist/adapters/sync/config.d.ts.map +1 -1
- package/dist/adapters/sync/config.js +175 -16
- package/dist/adapters/sync/config.js.map +1 -1
- package/dist/adapters/sync/create-file-sync.d.ts +32 -0
- package/dist/adapters/sync/create-file-sync.d.ts.map +1 -0
- package/dist/adapters/sync/create-file-sync.js +218 -0
- package/dist/adapters/sync/create-file-sync.js.map +1 -0
- package/dist/adapters/sync/file-sync.d.ts +40 -6
- package/dist/adapters/sync/file-sync.d.ts.map +1 -1
- package/dist/adapters/sync/file-sync.js +442 -97
- package/dist/adapters/sync/file-sync.js.map +1 -1
- package/dist/adapters/sync/index.d.ts +3 -2
- package/dist/adapters/sync/index.d.ts.map +1 -1
- package/dist/adapters/sync/index.js +3 -1
- package/dist/adapters/sync/index.js.map +1 -1
- package/dist/adapters/sync/merge.js +3 -2
- package/dist/adapters/sync/merge.js.map +1 -1
- package/dist/adapters/sync/types.d.ts +36 -2
- package/dist/adapters/sync/types.d.ts.map +1 -1
- package/dist/adapters/sync/types.js +22 -1
- package/dist/adapters/sync/types.js.map +1 -1
- package/dist/agent/index.d.ts +3 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +2 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/production-agent.d.ts +16 -0
- package/dist/agent/production-agent.d.ts.map +1 -0
- package/dist/agent/production-agent.js +158 -0
- package/dist/agent/production-agent.js.map +1 -0
- package/dist/agent/types.d.ts +40 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +2 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/application-state/emitter.d.ts +10 -0
- package/dist/application-state/emitter.d.ts.map +1 -0
- package/dist/application-state/emitter.js +18 -0
- package/dist/application-state/emitter.js.map +1 -0
- package/dist/application-state/handlers.d.ts +20 -0
- package/dist/application-state/handlers.d.ts.map +1 -0
- package/dist/application-state/handlers.js +94 -0
- package/dist/application-state/handlers.js.map +1 -0
- package/dist/application-state/index.d.ts +5 -0
- package/dist/application-state/index.d.ts.map +1 -0
- package/dist/application-state/index.js +9 -0
- package/dist/application-state/index.js.map +1 -0
- package/dist/application-state/script-helpers.d.ts +17 -0
- package/dist/application-state/script-helpers.d.ts.map +1 -0
- package/dist/application-state/script-helpers.js +28 -0
- package/dist/application-state/script-helpers.js.map +1 -0
- package/dist/application-state/store.d.ts +9 -0
- package/dist/application-state/store.d.ts.map +1 -0
- package/dist/application-state/store.js +93 -0
- package/dist/application-state/store.js.map +1 -0
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +40 -24
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +37 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +53 -0
- package/dist/client/AgentPanel.d.ts.map +1 -0
- package/dist/client/AgentPanel.js +70 -0
- package/dist/client/AgentPanel.js.map +1 -0
- package/dist/client/AssistantChat.d.ts +27 -0
- package/dist/client/AssistantChat.d.ts.map +1 -0
- package/dist/client/AssistantChat.js +165 -0
- package/dist/client/AssistantChat.js.map +1 -0
- package/dist/client/ErrorBoundary.d.ts +4 -0
- package/dist/client/ErrorBoundary.d.ts.map +1 -0
- package/dist/client/ErrorBoundary.js +22 -0
- package/dist/client/ErrorBoundary.js.map +1 -0
- package/dist/client/MultiTabAssistantChat.d.ts +4 -0
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -0
- package/dist/client/MultiTabAssistantChat.js +125 -0
- package/dist/client/MultiTabAssistantChat.js.map +1 -0
- package/dist/client/PoweredByBadge.d.ts +14 -0
- package/dist/client/PoweredByBadge.d.ts.map +1 -0
- package/dist/client/PoweredByBadge.js +60 -0
- package/dist/client/PoweredByBadge.js.map +1 -0
- package/dist/client/ProductionAgentPanel.d.ts +6 -0
- package/dist/client/ProductionAgentPanel.d.ts.map +1 -0
- package/dist/client/ProductionAgentPanel.js +6 -0
- package/dist/client/ProductionAgentPanel.js.map +1 -0
- package/dist/client/Turnstile.d.ts +35 -0
- package/dist/client/Turnstile.d.ts.map +1 -0
- package/dist/client/Turnstile.js +77 -0
- package/dist/client/Turnstile.js.map +1 -0
- package/dist/client/agent-chat-adapter.d.ts +10 -0
- package/dist/client/agent-chat-adapter.d.ts.map +1 -0
- package/dist/client/agent-chat-adapter.js +235 -0
- package/dist/client/agent-chat-adapter.js.map +1 -0
- package/dist/client/agent-chat.d.ts +9 -1
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +11 -1
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/index.d.ts +13 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +14 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/terminal/AgentTerminal.d.ts +35 -0
- package/dist/client/terminal/AgentTerminal.d.ts.map +1 -0
- package/dist/client/terminal/AgentTerminal.js +346 -0
- package/dist/client/terminal/AgentTerminal.js.map +1 -0
- package/dist/client/terminal/index.d.ts +7 -0
- package/dist/client/terminal/index.d.ts.map +1 -0
- package/dist/client/terminal/index.js +7 -0
- package/dist/client/terminal/index.js.map +1 -0
- package/dist/client/use-agent-chat.d.ts +1 -1
- package/dist/client/use-agent-chat.d.ts.map +1 -1
- package/dist/client/use-agent-chat.js +1 -1
- package/dist/client/use-agent-chat.js.map +1 -1
- package/dist/client/use-file-sync-status.d.ts +21 -0
- package/dist/client/use-file-sync-status.d.ts.map +1 -0
- package/dist/client/use-file-sync-status.js +65 -0
- package/dist/client/use-file-sync-status.js.map +1 -0
- package/dist/client/use-session.d.ts +16 -0
- package/dist/client/use-session.d.ts.map +1 -0
- package/dist/client/use-session.js +49 -0
- package/dist/client/use-session.js.map +1 -0
- package/dist/client/useProductionAgent.d.ts +23 -0
- package/dist/client/useProductionAgent.d.ts.map +1 -0
- package/dist/client/useProductionAgent.js +137 -0
- package/dist/client/useProductionAgent.js.map +1 -0
- package/dist/db/create-get-db.d.ts +3 -0
- package/dist/db/create-get-db.d.ts.map +1 -0
- package/dist/db/create-get-db.js +18 -0
- package/dist/db/create-get-db.js.map +1 -0
- package/dist/db/index.d.ts +23 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +19 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrations.d.ts +7 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +35 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/oauth-tokens/index.d.ts +2 -0
- package/dist/oauth-tokens/index.d.ts.map +1 -0
- package/dist/oauth-tokens/index.js +2 -0
- package/dist/oauth-tokens/index.js.map +1 -0
- package/dist/oauth-tokens/store.d.ts +9 -0
- package/dist/oauth-tokens/store.d.ts.map +1 -0
- package/dist/oauth-tokens/store.js +90 -0
- package/dist/oauth-tokens/store.js.map +1 -0
- package/dist/router/index.d.ts +3 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +5 -0
- package/dist/router/index.js.map +1 -0
- package/dist/scripts/core-scripts.d.ts +10 -0
- package/dist/scripts/core-scripts.d.ts.map +1 -0
- package/dist/scripts/core-scripts.js +15 -0
- package/dist/scripts/core-scripts.js.map +1 -0
- package/dist/scripts/db/exec.d.ts +11 -0
- package/dist/scripts/db/exec.d.ts.map +1 -0
- package/dist/scripts/db/exec.js +101 -0
- package/dist/scripts/db/exec.js.map +1 -0
- package/dist/scripts/db/index.d.ts +2 -0
- package/dist/scripts/db/index.d.ts.map +1 -0
- package/dist/scripts/db/index.js +6 -0
- package/dist/scripts/db/index.js.map +1 -0
- package/dist/scripts/db/query.d.ts +10 -0
- package/dist/scripts/db/query.d.ts.map +1 -0
- package/dist/scripts/db/query.js +112 -0
- package/dist/scripts/db/query.js.map +1 -0
- package/dist/scripts/db/schema.d.ts +12 -0
- package/dist/scripts/db/schema.d.ts.map +1 -0
- package/dist/scripts/db/schema.js +140 -0
- package/dist/scripts/db/schema.js.map +1 -0
- package/dist/scripts/dev/index.d.ts +15 -0
- package/dist/scripts/dev/index.d.ts.map +1 -0
- package/dist/scripts/dev/index.js +118 -0
- package/dist/scripts/dev/index.js.map +1 -0
- package/dist/scripts/dev/list-files.d.ts +5 -0
- package/dist/scripts/dev/list-files.d.ts.map +1 -0
- package/dist/scripts/dev/list-files.js +102 -0
- package/dist/scripts/dev/list-files.js.map +1 -0
- package/dist/scripts/dev/read-file.d.ts +5 -0
- package/dist/scripts/dev/read-file.d.ts.map +1 -0
- package/dist/scripts/dev/read-file.js +68 -0
- package/dist/scripts/dev/read-file.js.map +1 -0
- package/dist/scripts/dev/search-files.d.ts +5 -0
- package/dist/scripts/dev/search-files.d.ts.map +1 -0
- package/dist/scripts/dev/search-files.js +133 -0
- package/dist/scripts/dev/search-files.js.map +1 -0
- package/dist/scripts/dev/shell.d.ts +5 -0
- package/dist/scripts/dev/shell.d.ts.map +1 -0
- package/dist/scripts/dev/shell.js +65 -0
- package/dist/scripts/dev/shell.js.map +1 -0
- package/dist/scripts/dev/write-file.d.ts +5 -0
- package/dist/scripts/dev/write-file.d.ts.map +1 -0
- package/dist/scripts/dev/write-file.js +50 -0
- package/dist/scripts/dev/write-file.js.map +1 -0
- package/dist/scripts/index.d.ts +5 -0
- package/dist/scripts/index.d.ts.map +1 -1
- package/dist/scripts/index.js +5 -0
- package/dist/scripts/index.js.map +1 -1
- package/dist/scripts/runner.d.ts +3 -0
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +53 -14
- package/dist/scripts/runner.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +43 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -0
- package/dist/server/agent-chat-plugin.js +92 -0
- package/dist/server/agent-chat-plugin.js.map +1 -0
- package/dist/server/auth-plugin.d.ts +6 -0
- package/dist/server/auth-plugin.d.ts.map +1 -0
- package/dist/server/auth-plugin.js +8 -0
- package/dist/server/auth-plugin.js.map +1 -0
- package/dist/server/auth.d.ts +75 -0
- package/dist/server/auth.d.ts.map +1 -0
- package/dist/server/auth.js +499 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/captcha.d.ts +12 -0
- package/dist/server/captcha.d.ts.map +1 -0
- package/dist/server/captcha.js +43 -0
- package/dist/server/captcha.js.map +1 -0
- package/dist/server/create-server.d.ts +20 -10
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +48 -28
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/default-watcher.d.ts +17 -0
- package/dist/server/default-watcher.d.ts.map +1 -0
- package/dist/server/default-watcher.js +37 -0
- package/dist/server/default-watcher.js.map +1 -0
- package/dist/server/file-sync-plugin.d.ts +7 -0
- package/dist/server/file-sync-plugin.d.ts.map +1 -0
- package/dist/server/file-sync-plugin.js +38 -0
- package/dist/server/file-sync-plugin.js.map +1 -0
- package/dist/server/google-auth-plugin.d.ts +22 -0
- package/dist/server/google-auth-plugin.d.ts.map +1 -0
- package/dist/server/google-auth-plugin.js +122 -0
- package/dist/server/google-auth-plugin.js.map +1 -0
- package/dist/server/index.d.ts +13 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +14 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/missing-key.d.ts +9 -5
- package/dist/server/missing-key.d.ts.map +1 -1
- package/dist/server/missing-key.js +12 -7
- package/dist/server/missing-key.js.map +1 -1
- package/dist/server/sse.d.ts +18 -8
- package/dist/server/sse.d.ts.map +1 -1
- package/dist/server/sse.js +90 -19
- package/dist/server/sse.js.map +1 -1
- package/dist/settings/handlers.d.ts +9 -0
- package/dist/settings/handlers.d.ts.map +1 -0
- package/dist/settings/handlers.js +29 -0
- package/dist/settings/handlers.js.map +1 -0
- package/dist/settings/index.d.ts +5 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +9 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/settings/script-helpers.d.ts +9 -0
- package/dist/settings/script-helpers.d.ts.map +1 -0
- package/dist/settings/script-helpers.js +16 -0
- package/dist/settings/script-helpers.js.map +1 -0
- package/dist/settings/store.d.ts +7 -0
- package/dist/settings/store.d.ts.map +1 -0
- package/dist/settings/store.js +88 -0
- package/dist/settings/store.js.map +1 -0
- package/dist/settings/user-settings.d.ts +21 -0
- package/dist/settings/user-settings.d.ts.map +1 -0
- package/dist/settings/user-settings.js +35 -0
- package/dist/settings/user-settings.js.map +1 -0
- package/dist/tailwind.preset.js +1 -1
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/terminal/cli-registry.d.ts +16 -0
- package/dist/terminal/cli-registry.d.ts.map +1 -0
- package/dist/terminal/cli-registry.js +42 -0
- package/dist/terminal/cli-registry.js.map +1 -0
- package/dist/terminal/index.d.ts +9 -0
- package/dist/terminal/index.d.ts.map +1 -0
- package/dist/terminal/index.js +9 -0
- package/dist/terminal/index.js.map +1 -0
- package/dist/terminal/pty-server.d.ts +31 -0
- package/dist/terminal/pty-server.d.ts.map +1 -0
- package/dist/terminal/pty-server.js +252 -0
- package/dist/terminal/pty-server.js.map +1 -0
- package/dist/terminal/terminal-plugin.d.ts +23 -0
- package/dist/terminal/terminal-plugin.d.ts.map +1 -0
- package/dist/terminal/terminal-plugin.js +90 -0
- package/dist/terminal/terminal-plugin.js.map +1 -0
- package/dist/vite/client.d.ts +28 -5
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +55 -16
- package/dist/vite/client.js.map +1 -1
- package/dist/vite/dev-api-server.d.ts +10 -0
- package/dist/vite/dev-api-server.d.ts.map +1 -0
- package/dist/vite/dev-api-server.js +160 -0
- package/dist/vite/dev-api-server.js.map +1 -0
- package/dist/vite/index.d.ts +2 -3
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +2 -3
- package/dist/vite/index.js.map +1 -1
- package/package.json +74 -19
- package/src/templates/default/.agents/skills/create-skill/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +3 -3
- package/src/templates/default/.agents/skills/files-as-database/SKILL.md +82 -63
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +2 -2
- package/src/templates/default/.agents/skills/scripts/SKILL.md +20 -17
- package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +2 -2
- package/src/templates/default/.agents/skills/sse-file-watcher/SKILL.md +49 -64
- package/src/templates/default/.ignore +0 -0
- package/src/templates/default/AGENTS.md +129 -28
- package/src/templates/default/_gitignore +9 -5
- package/src/templates/default/app/entry.client.tsx +4 -0
- package/src/templates/default/app/entry.server.tsx +55 -0
- package/src/templates/default/app/global.css +95 -0
- package/src/templates/default/app/root.tsx +95 -0
- package/src/templates/default/app/routes/_index.tsx +62 -0
- package/src/templates/default/app/routes.ts +4 -0
- package/src/templates/default/app/vite-env.d.ts +6 -0
- package/src/templates/default/application-state/.gitkeep +0 -0
- package/src/templates/default/components.json +1 -1
- package/src/templates/default/data/sync-config.json +1 -0
- package/src/templates/default/package.json +7 -8
- package/src/templates/default/react-router.config.ts +6 -0
- package/src/templates/default/scripts/run.ts +1 -8
- package/src/templates/default/server/plugins/agent-chat.ts +1 -0
- package/src/templates/default/server/plugins/auth.ts +1 -0
- package/src/templates/default/server/plugins/file-sync.ts +1 -0
- package/src/templates/default/server/plugins/terminal.ts +1 -0
- package/src/templates/default/server/routes/[...page].get.ts +12 -0
- package/src/templates/default/server/routes/api/events.get.ts +3 -0
- package/src/templates/default/server/routes/api/file-sync/status.get.ts +4 -0
- package/src/templates/default/server/routes/api/hello.get.ts +5 -0
- package/src/templates/default/tailwind.config.ts +1 -1
- package/src/templates/default/tsconfig.json +9 -1
- package/src/templates/default/vite.config.ts +4 -1
- package/tsconfig.base.json +5 -3
- package/dist/adapters/neon/adapter.d.ts +0 -28
- package/dist/adapters/neon/adapter.d.ts.map +0 -1
- package/dist/adapters/neon/adapter.js +0 -135
- package/dist/adapters/neon/adapter.js.map +0 -1
- package/dist/adapters/neon/index.d.ts +0 -3
- package/dist/adapters/neon/index.d.ts.map +0 -1
- package/dist/adapters/neon/index.js +0 -3
- package/dist/adapters/neon/index.js.map +0 -1
- package/dist/server/production.d.ts +0 -18
- package/dist/server/production.d.ts.map +0 -1
- package/dist/server/production.js +0 -37
- package/dist/server/production.js.map +0 -1
- package/dist/vite/express-plugin.d.ts +0 -14
- package/dist/vite/express-plugin.d.ts.map +0 -1
- package/dist/vite/express-plugin.js +0 -53
- package/dist/vite/express-plugin.js.map +0 -1
- package/dist/vite/server.d.ts +0 -21
- package/dist/vite/server.d.ts.map +0 -1
- package/dist/vite/server.js +0 -68
- package/dist/vite/server.js.map +0 -1
- package/src/templates/default/client/App.tsx +0 -56
- package/src/templates/default/client/global.css +0 -75
- package/src/templates/default/client/vite-env.d.ts +0 -1
- package/src/templates/default/index.html +0 -14
- package/src/templates/default/server/index.ts +0 -22
- package/src/templates/default/server/node-build.ts +0 -4
- package/src/templates/default/vite.config.server.ts +0 -3
- /package/src/templates/default/{client → app}/lib/utils.ts +0 -0
|
@@ -21,8 +21,9 @@ Scripts give the agent callable tools with structured input/output. They keep th
|
|
|
21
21
|
Create `scripts/my-script.ts`:
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
|
-
import fs from "fs";
|
|
25
24
|
import { parseArgs, loadEnv, fail, agentChat } from "@agent-native/core";
|
|
25
|
+
import { readSetting, writeSetting } from "@agent-native/core/settings";
|
|
26
|
+
import { readAppState, writeAppState } from "@agent-native/core/application-state";
|
|
26
27
|
|
|
27
28
|
export default async function myScript(args: string[]) {
|
|
28
29
|
loadEnv();
|
|
@@ -31,19 +32,21 @@ export default async function myScript(args: string[]) {
|
|
|
31
32
|
const input = parsed.input;
|
|
32
33
|
if (!input) fail("--input is required");
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
35
|
+
// Read/write settings (persistent config)
|
|
36
|
+
const settings = await readSetting("my-settings");
|
|
37
|
+
await writeSetting("my-settings", { ...settings, lastRun: new Date().toISOString() });
|
|
38
|
+
|
|
39
|
+
// Read/write app state (ephemeral UI state)
|
|
40
|
+
await writeAppState("processing-status", { status: "done", input });
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
agentChat.submit(`Processed ${input}, result saved to ${outputPath}`);
|
|
42
|
+
agentChat.submit(`Processed ${input}`);
|
|
40
43
|
}
|
|
41
44
|
```
|
|
42
45
|
|
|
43
46
|
## How to Run
|
|
44
47
|
|
|
45
48
|
```bash
|
|
46
|
-
pnpm script my-script --input
|
|
49
|
+
pnpm script my-script --input some-value
|
|
47
50
|
```
|
|
48
51
|
|
|
49
52
|
## Script Dispatcher
|
|
@@ -63,7 +66,7 @@ This is the canonical approach for new apps. Script names must be lowercase with
|
|
|
63
66
|
- **Use `parseArgs()`** for structured argument parsing. It converts `--key value` pairs to a `Record<string, string>`.
|
|
64
67
|
- **Use `loadEnv()`** if the script needs environment variables (API keys, etc.).
|
|
65
68
|
- **Use `fail()`** for user-friendly error messages (exits with message, no stack trace).
|
|
66
|
-
- **Write results to
|
|
69
|
+
- **Write results to the database.** Use `writeSetting()` or `writeAppState()` for structured data. The UI will pick up changes via SSE.
|
|
67
70
|
- **Use `agentChat.submit()`** to report results or errors back to the agent chat.
|
|
68
71
|
- **Import from `@agent-native/core`** — Don't redefine `parseArgs()` or other utilities locally.
|
|
69
72
|
|
|
@@ -91,17 +94,17 @@ export default async function generateImage(args: string[]) {
|
|
|
91
94
|
**Data processing script:**
|
|
92
95
|
|
|
93
96
|
```ts
|
|
94
|
-
import fs from "fs";
|
|
95
97
|
import { parseArgs, fail } from "@agent-native/core";
|
|
98
|
+
import { readSetting, writeSetting } from "@agent-native/core/settings";
|
|
96
99
|
|
|
97
100
|
export default async function transform(args: string[]) {
|
|
98
101
|
const parsed = parseArgs(args);
|
|
99
|
-
const
|
|
100
|
-
if (!
|
|
102
|
+
const key = parsed.key;
|
|
103
|
+
if (!key) fail("--key is required");
|
|
101
104
|
|
|
102
|
-
const data =
|
|
103
|
-
const result = data
|
|
104
|
-
|
|
105
|
+
const data = await readSetting(key);
|
|
106
|
+
const result = processData(data);
|
|
107
|
+
await writeSetting(key, result);
|
|
105
108
|
}
|
|
106
109
|
```
|
|
107
110
|
|
|
@@ -109,10 +112,10 @@ export default async function transform(args: string[]) {
|
|
|
109
112
|
|
|
110
113
|
- **Script not found** — Check that the filename matches the command name exactly. `pnpm script foo-bar` looks for `scripts/foo-bar.ts`.
|
|
111
114
|
- **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
|
|
115
|
+
- **Script runs but UI doesn't update** — Make sure you're using core store helpers (`writeSetting`, `writeAppState`) which emit SSE events automatically. Direct SQL writes don't emit events.
|
|
113
116
|
|
|
114
117
|
## Related Skills
|
|
115
118
|
|
|
116
|
-
- **
|
|
119
|
+
- **storing-data** — Scripts read/write data via core SQL stores and Drizzle ORM
|
|
117
120
|
- **delegate-to-agent** — The agent invokes scripts via `pnpm script <name>`
|
|
118
|
-
- **
|
|
121
|
+
- **real-time-sync** — Database writes from scripts trigger SSE events to update the UI
|
|
@@ -73,7 +73,7 @@ el.dataset.selectedId = selectedItem?.id || "";
|
|
|
73
73
|
|
|
74
74
|
## Related Skills
|
|
75
75
|
|
|
76
|
-
- **
|
|
76
|
+
- **storing-data** — Tier 1 modifications (database writes) are the safest and most common
|
|
77
77
|
- **scripts** — The agent can create or modify scripts to add new capabilities
|
|
78
78
|
- **delegate-to-agent** — Self-modification requests come through the agent chat
|
|
79
|
-
- **
|
|
79
|
+
- **real-time-sync** — Source edits and database writes trigger SSE events to update the UI
|
|
@@ -1,95 +1,80 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: real-time-sync
|
|
3
3
|
description: >-
|
|
4
|
-
How
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
How the UI stays in sync when the agent writes data. Use when wiring up
|
|
5
|
+
query invalidation, debugging UI not updating, or understanding how SSE
|
|
6
|
+
connects the agent to the browser.
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
#
|
|
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.
|
|
9
|
+
# Real-Time Sync
|
|
18
10
|
|
|
19
11
|
## How It Works
|
|
20
12
|
|
|
21
|
-
|
|
13
|
+
When the agent writes data (via scripts or server handlers), the UI updates instantly. No polling, no manual refresh.
|
|
22
14
|
|
|
23
|
-
|
|
24
|
-
import { createFileWatcher, createSSEHandler } from "@agent-native/core";
|
|
25
|
-
const watcher = createFileWatcher("./data");
|
|
26
|
-
app.get("/api/events", createSSEHandler(watcher));
|
|
27
|
-
```
|
|
15
|
+
The flow:
|
|
28
16
|
|
|
29
|
-
|
|
17
|
+
1. **Agent writes** → `writeAppState("navigate", { view: "starred" })`
|
|
18
|
+
2. **Store emits SSE event** → `{ source: "app-state", type: "change", key: "navigate" }`
|
|
19
|
+
3. **Browser receives** → `useFileWatcher()` hook gets the event
|
|
20
|
+
4. **React Query invalidates** → relevant queries refetch, UI re-renders
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
import { useFileWatcher } from "@agent-native/core";
|
|
33
|
-
useFileWatcher({ queryClient, queryKeys: ["files", "projects"] });
|
|
34
|
-
```
|
|
22
|
+
This happens automatically for all writes through `@agent-native/core/application-state` and `@agent-native/core/settings`.
|
|
35
23
|
|
|
36
|
-
|
|
24
|
+
## SSE Events
|
|
37
25
|
|
|
38
|
-
|
|
26
|
+
| Source | Emitted by | Example |
|
|
27
|
+
|--------|-----------|---------|
|
|
28
|
+
| `"app-state"` | `writeAppState`, `deleteAppState` | `{ source: "app-state", type: "change", key: "navigation" }` |
|
|
29
|
+
| `"settings"` | `putSetting`, `deleteSetting` | `{ source: "settings", type: "change", key: "mail-settings" }` |
|
|
39
30
|
|
|
40
|
-
|
|
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
|
|
31
|
+
## Client Setup
|
|
43
32
|
|
|
44
|
-
|
|
33
|
+
Every template has an SSE endpoint and a `useFileWatcher` hook in `root.tsx`:
|
|
45
34
|
|
|
46
|
-
|
|
35
|
+
```ts
|
|
36
|
+
// server/routes/api/events.get.ts
|
|
37
|
+
import { createDefaultSSEHandler } from "@agent-native/core/server";
|
|
38
|
+
export default createDefaultSSEHandler();
|
|
39
|
+
```
|
|
47
40
|
|
|
48
41
|
```ts
|
|
42
|
+
// In root.tsx
|
|
49
43
|
useFileWatcher({
|
|
50
|
-
queryClient,
|
|
51
|
-
queryKeys: [],
|
|
44
|
+
queryClient: qc,
|
|
45
|
+
queryKeys: [],
|
|
52
46
|
onEvent: (data) => {
|
|
53
|
-
if (data.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
if (data.source === "app-state") {
|
|
48
|
+
// Invalidate queries affected by app state changes
|
|
49
|
+
qc.invalidateQueries({ queryKey: ["compose-drafts"] });
|
|
50
|
+
} else if (data.source === "settings") {
|
|
51
|
+
qc.invalidateQueries({ queryKey: ["settings"] });
|
|
57
52
|
}
|
|
58
53
|
},
|
|
59
54
|
});
|
|
60
55
|
```
|
|
61
56
|
|
|
62
|
-
|
|
57
|
+
Use the `key` field to selectively invalidate — don't invalidate everything on every event.
|
|
63
58
|
|
|
64
|
-
|
|
65
|
-
useQuery({
|
|
66
|
-
queryKey: ["projects"],
|
|
67
|
-
queryFn: fetchProjects,
|
|
68
|
-
staleTime: 2000, // don't refetch within 2 seconds
|
|
69
|
-
});
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Performance
|
|
59
|
+
## For Custom Domain Data
|
|
73
60
|
|
|
74
|
-
|
|
61
|
+
If your template has Drizzle tables and you want SSE notifications after writes, emit from your handler:
|
|
75
62
|
|
|
76
|
-
|
|
63
|
+
```ts
|
|
64
|
+
import { getAppStateEmitter } from "@agent-native/core/application-state";
|
|
77
65
|
|
|
78
|
-
|
|
79
|
-
|
|
66
|
+
// After inserting a booking:
|
|
67
|
+
getAppStateEmitter().emit("app-state", {
|
|
68
|
+
source: "app-state",
|
|
69
|
+
type: "change",
|
|
70
|
+
key: "bookings-updated",
|
|
71
|
+
});
|
|
72
|
+
```
|
|
80
73
|
|
|
81
74
|
## Troubleshooting
|
|
82
75
|
|
|
83
|
-
| Symptom
|
|
84
|
-
|
|
85
|
-
| UI not updating after
|
|
86
|
-
| SSE not
|
|
87
|
-
|
|
|
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
|
|
76
|
+
| Symptom | Check |
|
|
77
|
+
|---------|-------|
|
|
78
|
+
| UI not updating after script writes | Is the script using `writeAppState`/`writeSetting`? Direct SQL writes don't emit SSE. |
|
|
79
|
+
| SSE not connected | Browser devtools → Network → EventStream. Is `/api/events` connected? |
|
|
80
|
+
| Wrong queries invalidating | Check the `onEvent` callback — filter by `data.source` and `data.key` |
|
|
File without changes
|
|
@@ -2,38 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
## Architecture
|
|
4
4
|
|
|
5
|
-
This is an **@agent-native/core** application — the AI agent and UI share state through
|
|
5
|
+
This is an **@agent-native/core** application — the AI agent and UI share state through a SQL database, with SSE for real-time sync.
|
|
6
6
|
|
|
7
7
|
### Core Principles
|
|
8
8
|
|
|
9
|
-
1. **
|
|
9
|
+
1. **Shared SQL database** — All app state lives in SQL (SQLite locally, cloud DB via `DATABASE_URL` in production). Core stores: `application_state`, `settings`, `oauth_tokens`, `sessions`.
|
|
10
10
|
2. **All AI through agent chat** — No inline LLM calls. UI delegates to the AI via `sendToAgentChat()` / `agentChat.submit()`.
|
|
11
11
|
3. **Scripts for agent operations** — `pnpm script <name>` dispatches to callable script files in `scripts/`.
|
|
12
|
-
4. **
|
|
12
|
+
4. **SSE for real-time sync** — Database writes emit events that keep the UI in sync automatically.
|
|
13
13
|
5. **Agent can update code** — The agent can modify this app's source code directly.
|
|
14
14
|
|
|
15
|
-
###
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
client/ # React frontend (Vite SPA)
|
|
19
|
-
App.tsx # Entry point
|
|
20
|
-
components/ # UI components
|
|
21
|
-
hooks/ # React hooks
|
|
22
|
-
lib/ # Utilities (cn, etc)
|
|
15
|
+
### Authentication
|
|
23
16
|
|
|
24
|
-
server/
|
|
25
|
-
index.ts # createAppServer() — routes + middleware
|
|
26
|
-
node-build.ts # Production entry point
|
|
17
|
+
Auth is automatic and environment-driven. The `server/plugins/auth.ts` plugin calls `autoMountAuth(app)` at startup.
|
|
27
18
|
|
|
28
|
-
|
|
19
|
+
- **Dev mode**: Auth is bypassed. `getSession()` returns `{ email: "local@localhost" }`. Zero friction.
|
|
20
|
+
- **Production** (`ACCESS_TOKEN` set): Auth middleware auto-mounts. Login page for unauthenticated visitors.
|
|
21
|
+
- **Production** (no token, no `AUTH_DISABLED=true`): Server refuses to start.
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
run.ts # Script dispatcher
|
|
32
|
-
*.ts # Individual scripts (pnpm script <name>)
|
|
23
|
+
Use `getSession(event)` server-side and `useSession()` client-side. See [docs/auth.md](docs/auth.md).
|
|
33
24
|
|
|
34
|
-
|
|
25
|
+
### Directory Structure
|
|
35
26
|
|
|
36
|
-
|
|
27
|
+
```
|
|
28
|
+
app/ # React frontend
|
|
29
|
+
root.tsx # HTML shell + global providers
|
|
30
|
+
entry.client.tsx # Client hydration entry
|
|
31
|
+
routes.ts # Route config — flatRoutes()
|
|
32
|
+
routes/ # File-based page routes (auto-discovered)
|
|
33
|
+
_index.tsx # / (home page)
|
|
34
|
+
components/ # UI components
|
|
35
|
+
hooks/ # React hooks
|
|
36
|
+
lib/ # Utilities (cn, etc)
|
|
37
|
+
|
|
38
|
+
server/ # Nitro API server
|
|
39
|
+
routes/
|
|
40
|
+
api/ # File-based API routes (auto-discovered)
|
|
41
|
+
[...page].get.ts # SSR catch-all (delegates to React Router)
|
|
42
|
+
plugins/ # Server plugins (startup logic)
|
|
43
|
+
lib/ # Shared server modules
|
|
44
|
+
|
|
45
|
+
shared/ # Isomorphic code (imported by both client & server)
|
|
46
|
+
|
|
47
|
+
scripts/ # Agent-callable scripts
|
|
48
|
+
run.ts # Script dispatcher
|
|
49
|
+
*.ts # Individual scripts (pnpm script <name>)
|
|
50
|
+
|
|
51
|
+
data/ # App data (SQLite DB file)
|
|
52
|
+
|
|
53
|
+
react-router.config.ts # React Router framework config
|
|
54
|
+
.agents/skills/ # Agent skills — detailed guidance for each rule
|
|
37
55
|
```
|
|
38
56
|
|
|
39
57
|
## Learnings & Preferences
|
|
@@ -55,19 +73,89 @@ Skills in `.agents/skills/` provide detailed guidance for each architectural rul
|
|
|
55
73
|
|
|
56
74
|
| Skill | When to read |
|
|
57
75
|
| --------------------- | -------------------------------------------------------------- |
|
|
58
|
-
| `
|
|
76
|
+
| `storing-data` | Before storing or reading any app state |
|
|
59
77
|
| `delegate-to-agent` | Before adding LLM calls or AI delegation |
|
|
60
78
|
| `scripts` | Before creating or modifying scripts |
|
|
61
|
-
| `
|
|
79
|
+
| `real-time-sync` | Before wiring up real-time UI sync |
|
|
62
80
|
| `self-modifying-code` | Before editing source, components, or styles |
|
|
63
81
|
| `frontend-design` | Before building or restyling any UI component, page, or layout |
|
|
64
82
|
|
|
65
83
|
The **`frontend-design`** skill (sourced from [Anthropic's skills library](https://github.com/anthropics/skills/blob/main/skills/frontend-design/SKILL.md)) enforces distinctive, production-grade aesthetics — committing to a clear visual direction and avoiding generic patterns like purple gradients, overused fonts, and cookie-cutter layouts.
|
|
66
84
|
|
|
85
|
+
### Framework Basics
|
|
86
|
+
|
|
87
|
+
**SSR-first framework, CSR-by-default content:** This app uses React Router v7 framework mode with `ssr: true`. But virtually every route renders only an SSR shell (loading spinner + meta tags). All real data fetching and rendering happens on the client via React Query hooks. Server-side data fetching is the exception — only used for public pages that need SEO/og tags.
|
|
88
|
+
|
|
89
|
+
**Adding a page:**
|
|
90
|
+
Create a file in `app/routes/`. The filename determines the URL path:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
app/routes/_index.tsx → /
|
|
94
|
+
app/routes/settings.tsx → /settings
|
|
95
|
+
app/routes/inbox.tsx → /inbox
|
|
96
|
+
app/routes/inbox.$threadId.tsx → /inbox/:threadId
|
|
97
|
+
app/routes/$id.tsx → /:id (dynamic param)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Each route file exports a default component, optional `meta()`, and optional `HydrateFallback()`:
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import MyPage from "@/pages/MyPage";
|
|
104
|
+
|
|
105
|
+
export function meta() {
|
|
106
|
+
return [{ title: "My Page" }];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function HydrateFallback() {
|
|
110
|
+
return (
|
|
111
|
+
<div className="flex items-center justify-center h-screen">
|
|
112
|
+
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-foreground" />
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export default function MyPageRoute() {
|
|
118
|
+
return <MyPage />;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Do NOT fetch data server-side** in route loaders unless the page genuinely needs SEO content or og tags based on dynamic data. The standard pattern is: SSR renders a loading spinner, client hydrates, React Query hooks fetch from `/api/*`.
|
|
123
|
+
|
|
67
124
|
### Key Patterns
|
|
68
125
|
|
|
69
126
|
**Adding an API route:**
|
|
70
|
-
|
|
127
|
+
Create a file in `server/routes/api/`. The filename determines the URL path and HTTP method:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
server/routes/api/items/index.get.ts → GET /api/items
|
|
131
|
+
server/routes/api/items/[id].get.ts → GET /api/items/:id
|
|
132
|
+
server/routes/api/items/[id].patch.ts → PATCH /api/items/:id
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Each file exports a default `defineEventHandler`.
|
|
136
|
+
|
|
137
|
+
**Adding a server plugin:**
|
|
138
|
+
Startup logic (auth, SSE, etc.) lives in `server/plugins/`. Use `defineNitroPlugin` from core:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { defineNitroPlugin } from "@agent-native/core";
|
|
142
|
+
|
|
143
|
+
export default defineNitroPlugin(async (nitroApp) => {
|
|
144
|
+
// Runs once at server startup
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Key imports from `@agent-native/core`:**
|
|
149
|
+
|
|
150
|
+
| Import | Purpose |
|
|
151
|
+
| -------------------------------------------- | -------------------------------------------------------------------------- |
|
|
152
|
+
| `defineNitroPlugin` | Define a server plugin (re-exported from Nitro) |
|
|
153
|
+
| `createDefaultSSEHandler` | Create SSE endpoint for DB change events (server) |
|
|
154
|
+
| `readAppState`, `writeAppState` | Read/write application state (from `@agent-native/core/application-state`) |
|
|
155
|
+
| `readSetting`, `writeSetting` | Read/write settings (from `@agent-native/core/settings`) |
|
|
156
|
+
| `defineEventHandler`, `readBody`, `getQuery` | H3 route handler utilities (re-exported) |
|
|
157
|
+
| `sendToAgentChat` | Send messages to agent from UI (client-side) |
|
|
158
|
+
| `agentChat` | Send messages to agent from scripts (server-side) |
|
|
71
159
|
|
|
72
160
|
**Adding a script:**
|
|
73
161
|
Create `scripts/my-script.ts` exporting `default async function(args: string[])`.
|
|
@@ -91,11 +179,24 @@ import { agentChat } from "@agent-native/core";
|
|
|
91
179
|
agentChat.submit("Generate something");
|
|
92
180
|
```
|
|
93
181
|
|
|
182
|
+
### Database (Cloud Deployment)
|
|
183
|
+
|
|
184
|
+
By default, data is stored in SQLite at `data/app.db`. For production/cloud deployment, set `DATABASE_URL` to point to a remote database (Turso, Neon, Supabase, D1).
|
|
185
|
+
|
|
186
|
+
**Environment variables:**
|
|
187
|
+
|
|
188
|
+
| Variable | Required | Description |
|
|
189
|
+
| --------------------- | ---------------- | ---------------------------------------------------------- |
|
|
190
|
+
| `DATABASE_URL` | No (has default) | Database connection string (default: `file:./data/app.db`) |
|
|
191
|
+
| `DATABASE_AUTH_TOKEN` | For remote DBs | Auth token for Turso or other remote databases |
|
|
192
|
+
|
|
94
193
|
### Tech Stack
|
|
95
194
|
|
|
96
|
-
- **Framework:** @agent-native/core
|
|
195
|
+
- **Framework:** @agent-native/core + React Router v7 (framework mode)
|
|
97
196
|
- **Frontend:** React 18, Vite, TailwindCSS, shadcn/ui
|
|
98
|
-
- **
|
|
99
|
-
- **
|
|
100
|
-
- **
|
|
101
|
-
- **
|
|
197
|
+
- **Routing:** File-based via `flatRoutes()` — SSR shell + client rendering
|
|
198
|
+
- **Backend:** Nitro (via @agent-native/core) — file-based API routing, server plugins, deploy-anywhere presets
|
|
199
|
+
- **State:** SQL-backed (SSE for real-time updates)
|
|
200
|
+
- **Build:** `pnpm build` (React Router build — client + SSR + Nitro server)
|
|
201
|
+
- **Dev:** `pnpm dev` (Vite dev server with both React Router + Nitro plugins)
|
|
202
|
+
- **Start:** `node .output/server/index.mjs` (production)
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
#
|
|
1
|
+
# React Router generated types
|
|
2
|
+
.react-router/
|
|
3
|
+
|
|
4
|
+
# Logs
|
|
2
5
|
logs
|
|
3
6
|
*.log
|
|
4
7
|
npm-debug.log*
|
|
@@ -25,9 +28,10 @@ dist-ssr
|
|
|
25
28
|
.env.*
|
|
26
29
|
!.env.example
|
|
27
30
|
|
|
28
|
-
# Data
|
|
29
|
-
data/uploads/
|
|
30
|
-
data/settings.json
|
|
31
|
+
# Data
|
|
32
|
+
data/uploads/
|
|
33
|
+
data/settings.json
|
|
34
|
+
data/.sessions.json
|
|
31
35
|
|
|
32
36
|
# Learnings (personal preferences and memory — use learnings.defaults.md for tracked defaults)
|
|
33
|
-
learnings.md
|
|
37
|
+
learnings.md
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { AppLoadContext, EntryContext } from "react-router";
|
|
2
|
+
import { ServerRouter } from "react-router";
|
|
3
|
+
import ReactDOMServer from "react-dom/server.browser";
|
|
4
|
+
const { renderToReadableStream } = ReactDOMServer;
|
|
5
|
+
import { isbot } from "isbot";
|
|
6
|
+
|
|
7
|
+
export const streamTimeout = 5_000;
|
|
8
|
+
|
|
9
|
+
export default async function handleRequest(
|
|
10
|
+
request: Request,
|
|
11
|
+
responseStatusCode: number,
|
|
12
|
+
responseHeaders: Headers,
|
|
13
|
+
routerContext: EntryContext,
|
|
14
|
+
_loadContext: AppLoadContext,
|
|
15
|
+
) {
|
|
16
|
+
if (request.method.toUpperCase() === "HEAD") {
|
|
17
|
+
return new Response(null, {
|
|
18
|
+
status: responseStatusCode,
|
|
19
|
+
headers: responseHeaders,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const userAgent = request.headers.get("user-agent");
|
|
24
|
+
const waitForAll = (userAgent && isbot(userAgent)) || routerContext.isSpaMode;
|
|
25
|
+
|
|
26
|
+
const abortController = new AbortController();
|
|
27
|
+
const timeoutId = setTimeout(() => abortController.abort(), streamTimeout);
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const body = await renderToReadableStream(
|
|
31
|
+
<ServerRouter context={routerContext} url={request.url} />,
|
|
32
|
+
{
|
|
33
|
+
signal: abortController.signal,
|
|
34
|
+
onError(error: unknown) {
|
|
35
|
+
if (!abortController.signal.aborted) {
|
|
36
|
+
responseStatusCode = 500;
|
|
37
|
+
console.error(error);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
if (waitForAll) {
|
|
44
|
+
await body.allReady;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
responseHeaders.set("Content-Type", "text/html");
|
|
48
|
+
return new Response(body, {
|
|
49
|
+
headers: responseHeaders,
|
|
50
|
+
status: responseStatusCode,
|
|
51
|
+
});
|
|
52
|
+
} finally {
|
|
53
|
+
clearTimeout(timeoutId);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap");
|
|
2
|
+
|
|
3
|
+
@tailwind base;
|
|
4
|
+
@tailwind components;
|
|
5
|
+
@tailwind utilities;
|
|
6
|
+
|
|
7
|
+
@layer base {
|
|
8
|
+
:root {
|
|
9
|
+
--background: 0 0% 100%;
|
|
10
|
+
--foreground: 220 10% 10%;
|
|
11
|
+
--card: 0 0% 100%;
|
|
12
|
+
--card-foreground: 220 10% 10%;
|
|
13
|
+
--popover: 0 0% 100%;
|
|
14
|
+
--popover-foreground: 220 10% 10%;
|
|
15
|
+
--primary: 220 10% 15%;
|
|
16
|
+
--primary-foreground: 0 0% 100%;
|
|
17
|
+
--secondary: 220 10% 95%;
|
|
18
|
+
--secondary-foreground: 220 10% 15%;
|
|
19
|
+
--muted: 220 10% 95%;
|
|
20
|
+
--muted-foreground: 220 5% 45%;
|
|
21
|
+
--accent: 220 10% 95%;
|
|
22
|
+
--accent-foreground: 220 10% 15%;
|
|
23
|
+
--destructive: 0 84% 60%;
|
|
24
|
+
--destructive-foreground: 0 0% 98%;
|
|
25
|
+
--border: 220 10% 90%;
|
|
26
|
+
--input: 220 10% 90%;
|
|
27
|
+
--ring: 220 10% 40%;
|
|
28
|
+
--radius: 0.5rem;
|
|
29
|
+
--sidebar-background: 220 10% 97%;
|
|
30
|
+
--sidebar-foreground: 220 5% 45%;
|
|
31
|
+
--sidebar-primary: 220 10% 15%;
|
|
32
|
+
--sidebar-primary-foreground: 0 0% 100%;
|
|
33
|
+
--sidebar-accent: 220 10% 95%;
|
|
34
|
+
--sidebar-accent-foreground: 220 10% 15%;
|
|
35
|
+
--sidebar-border: 220 10% 90%;
|
|
36
|
+
--sidebar-ring: 220 10% 40%;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.dark {
|
|
40
|
+
--background: 220 6% 6%;
|
|
41
|
+
--foreground: 0 0% 90%;
|
|
42
|
+
--card: 220 5% 6%;
|
|
43
|
+
--card-foreground: 0 0% 90%;
|
|
44
|
+
--popover: 220 5% 6%;
|
|
45
|
+
--popover-foreground: 0 0% 90%;
|
|
46
|
+
--primary: 0 0% 75%;
|
|
47
|
+
--primary-foreground: 220 6% 6%;
|
|
48
|
+
--secondary: 220 4% 12%;
|
|
49
|
+
--secondary-foreground: 0 0% 90%;
|
|
50
|
+
--muted: 220 4% 10%;
|
|
51
|
+
--muted-foreground: 220 4% 50%;
|
|
52
|
+
--accent: 220 4% 13%;
|
|
53
|
+
--accent-foreground: 0 0% 90%;
|
|
54
|
+
--destructive: 0 63% 51%;
|
|
55
|
+
--destructive-foreground: 0 0% 98%;
|
|
56
|
+
--border: 220 4% 14%;
|
|
57
|
+
--input: 220 4% 14%;
|
|
58
|
+
--ring: 0 0% 60%;
|
|
59
|
+
--radius: 0.5rem;
|
|
60
|
+
--sidebar-background: 220 6% 4%;
|
|
61
|
+
--sidebar-foreground: 220 4% 50%;
|
|
62
|
+
--sidebar-primary: 0 0% 75%;
|
|
63
|
+
--sidebar-primary-foreground: 220 6% 6%;
|
|
64
|
+
--sidebar-accent: 220 4% 10%;
|
|
65
|
+
--sidebar-accent-foreground: 0 0% 90%;
|
|
66
|
+
--sidebar-border: 220 4% 10%;
|
|
67
|
+
--sidebar-ring: 0 0% 60%;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@layer base {
|
|
72
|
+
* {
|
|
73
|
+
@apply border-border;
|
|
74
|
+
}
|
|
75
|
+
body {
|
|
76
|
+
@apply bg-background text-foreground;
|
|
77
|
+
font-family: "Inter", sans-serif;
|
|
78
|
+
font-feature-settings: "cv02", "cv03", "cv04", "cv11";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
::-webkit-scrollbar {
|
|
83
|
+
width: 5px;
|
|
84
|
+
height: 5px;
|
|
85
|
+
}
|
|
86
|
+
::-webkit-scrollbar-track {
|
|
87
|
+
background: transparent;
|
|
88
|
+
}
|
|
89
|
+
::-webkit-scrollbar-thumb {
|
|
90
|
+
background: hsl(var(--border));
|
|
91
|
+
border-radius: 3px;
|
|
92
|
+
}
|
|
93
|
+
::-webkit-scrollbar-thumb:hover {
|
|
94
|
+
background: hsl(var(--muted-foreground) / 0.4);
|
|
95
|
+
}
|