@agent-native/core 0.207.0-nightly-20261011124220 → 0.207.0
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/agent/production-agent.js +23 -6
- package/dist/agent/thread-data-builder.js +7 -4
- package/dist/cli/eval.js +20 -4
- package/dist/client/analytics/index.d.ts +1 -1
- package/dist/client/analytics.d.ts +12 -3
- package/dist/client/analytics.js +51 -17
- package/dist/client/onboarding/use-onboarding.d.ts +1 -0
- package/dist/client/onboarding/use-onboarding.js +19 -6
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/eval/agent-runner.js +18 -8
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/mcp/connect-route.js +9 -4
- package/dist/observability/routes.d.ts +7 -7
- package/dist/onboarding/plugin.js +15 -45
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/store.js +25 -30
- package/dist/server/agent-discovery.js +47 -53
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
- package/dist/server/builtin-agents.d.ts +2 -0
- package/dist/server/builtin-agents.js +50 -3
- package/dist/server/credential-provider.d.ts +6 -9
- package/dist/server/credential-provider.js +33 -21
- package/dist/templates/builder-code-starter/.agents/skills/adding-a-feature/SKILL.md.patch +1 -1
- package/dist/templates/builder-code-starter/AGENTS.md.patch +3 -3
- package/dist/templates/builder-code-starter/app/components/layout/Layout.tsx.patch +6 -7
- package/dist/templates/builder-code-starter/app/hooks/use-navigation-state.ts.patch +21 -28
- package/dist/templates/builder-code-starter/app/root.tsx.patch +16 -5
- package/dist/templates/builder-code-starter/template-layer.json +4 -0
- package/dist/templates/chat/.agents/skills/secrets/SKILL.md +6 -2
- package/dist/templates/chat/AGENTS.md +3 -3
- package/dist/templates/chat/CHANGELOG.md +6 -0
- package/dist/templates/chat/app/components/chat/ChatHomeRedirect.tsx +25 -0
- package/dist/templates/chat/app/components/chat/ChatRouteContent.tsx +828 -15
- package/dist/templates/chat/app/components/home/HomePage.tsx +332 -0
- package/dist/templates/chat/app/components/layout/AgentInspector.tsx +2 -4
- package/dist/templates/chat/app/components/layout/Header.tsx +1 -1
- package/dist/templates/chat/app/components/layout/Layout.tsx +5 -6
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +35 -11
- package/dist/templates/chat/app/components/ui/item.tsx +1 -0
- package/dist/templates/chat/app/components/ui/separator.tsx +1 -0
- package/dist/templates/chat/app/components/ui/skeleton.tsx +1 -0
- package/dist/templates/chat/app/hooks/use-navigation-state.ts +16 -22
- package/dist/templates/chat/app/i18n/ar-SA.ts +25 -0
- package/dist/templates/chat/app/i18n/de-DE.ts +26 -0
- package/dist/templates/chat/app/i18n/en-US.ts +25 -0
- package/dist/templates/chat/app/i18n/es-ES.ts +26 -0
- package/dist/templates/chat/app/i18n/fr-FR.ts +26 -0
- package/dist/templates/chat/app/i18n/hi-IN.ts +26 -0
- package/dist/templates/chat/app/i18n/ja-JP.ts +26 -0
- package/dist/templates/chat/app/i18n/ko-KR.ts +26 -0
- package/dist/templates/chat/app/i18n/pt-BR.ts +26 -0
- package/dist/templates/chat/app/i18n/zh-CN.ts +25 -0
- package/dist/templates/chat/app/i18n/zh-TW.ts +25 -0
- package/dist/templates/chat/app/lib/chat-paths.ts +479 -0
- package/dist/templates/chat/app/root.tsx +14 -3
- package/dist/templates/chat/app/routes/chat._index.tsx +5 -0
- package/dist/templates/chat/app/routes/home.tsx +3 -22
- package/dist/templates/chat/changelog/2026-10-10-home-handoff-recovery-capacity.md +6 -0
- package/dist/templates/default/.agents/skills/secrets/SKILL.md +6 -2
- package/dist/templates/headless/.agents/skills/secrets/SKILL.md +6 -2
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +6 -2
- package/dist/triggers/actions/manage-automation.d.ts +2 -2
- package/docs/content/deployment-environment-variables.mdx +10 -10
- package/docs/content/environment-variables.mdx +38 -6
- package/docs/content/getting-started.mdx +7 -7
- package/docs/content/multi-app-workspace.mdx +7 -3
- package/docs/content/template-chat-first-edits.mdx +46 -33
- package/package.json +4 -4
- package/src/templates/builder-code-starter/.agents/skills/adding-a-feature/SKILL.md.patch +1 -1
- package/src/templates/builder-code-starter/AGENTS.md.patch +3 -3
- package/src/templates/builder-code-starter/app/components/layout/Layout.tsx.patch +6 -7
- package/src/templates/builder-code-starter/app/hooks/use-navigation-state.ts.patch +21 -28
- package/src/templates/builder-code-starter/app/root.tsx.patch +16 -5
- package/src/templates/builder-code-starter/template-layer.json +4 -0
- package/src/templates/chat/.agents/skills/secrets/SKILL.md +6 -2
- package/src/templates/chat/AGENTS.md +3 -3
- package/src/templates/chat/CHANGELOG.md +6 -0
- package/src/templates/chat/app/components/chat/ChatHomeRedirect.tsx +25 -0
- package/src/templates/chat/app/components/chat/ChatRouteContent.tsx +828 -15
- package/src/templates/chat/app/components/home/HomePage.tsx +332 -0
- package/src/templates/chat/app/components/layout/AgentInspector.tsx +2 -4
- package/src/templates/chat/app/components/layout/Header.tsx +1 -1
- package/src/templates/chat/app/components/layout/Layout.tsx +5 -6
- package/src/templates/chat/app/components/layout/Sidebar.tsx +35 -11
- package/src/templates/chat/app/components/ui/item.tsx +1 -0
- package/src/templates/chat/app/components/ui/separator.tsx +1 -0
- package/src/templates/chat/app/components/ui/skeleton.tsx +1 -0
- package/src/templates/chat/app/hooks/use-navigation-state.ts +16 -22
- package/src/templates/chat/app/i18n/ar-SA.ts +25 -0
- package/src/templates/chat/app/i18n/de-DE.ts +26 -0
- package/src/templates/chat/app/i18n/en-US.ts +25 -0
- package/src/templates/chat/app/i18n/es-ES.ts +26 -0
- package/src/templates/chat/app/i18n/fr-FR.ts +26 -0
- package/src/templates/chat/app/i18n/hi-IN.ts +26 -0
- package/src/templates/chat/app/i18n/ja-JP.ts +26 -0
- package/src/templates/chat/app/i18n/ko-KR.ts +26 -0
- package/src/templates/chat/app/i18n/pt-BR.ts +26 -0
- package/src/templates/chat/app/i18n/zh-CN.ts +25 -0
- package/src/templates/chat/app/i18n/zh-TW.ts +25 -0
- package/src/templates/chat/app/lib/chat-paths.ts +479 -0
- package/src/templates/chat/app/root.tsx +14 -3
- package/src/templates/chat/app/routes/chat._index.tsx +5 -0
- package/src/templates/chat/app/routes/home.tsx +3 -22
- package/src/templates/chat/changelog/2026-10-10-home-handoff-recovery-capacity.md +6 -0
- package/src/templates/default/.agents/skills/secrets/SKILL.md +6 -2
- package/src/templates/headless/.agents/skills/secrets/SKILL.md +6 -2
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +6 -2
|
@@ -15,9 +15,11 @@ most apps need.
|
|
|
15
15
|
For a normal app, start with the [Agent-Native app configuration guide](/docs/agent-native-config),
|
|
16
16
|
then use [Deployment: Environment Variables](/docs/deployment-environment-variables)
|
|
17
17
|
and [Authentication](/docs/authentication) for the deliberate environment-only
|
|
18
|
-
parts.
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
parts. LLM provider keys can be app-wide fallbacks on self-hosted deployments;
|
|
19
|
+
production Hosted-workspace runtimes block that fallback. See [LLM provider
|
|
20
|
+
keys](#llm-provider-keys) for local setup, scoped keys, and deployment sharing
|
|
21
|
+
and billing. Keep user-, organization-, and workspace-scoped credentials in the
|
|
22
|
+
database-backed secret or connection store.
|
|
21
23
|
|
|
22
24
|
For committed, non-secret app defaults, use `agent-native.config.ts` first. If a
|
|
23
25
|
public config value must vary by deployment, use its deterministic
|
|
@@ -79,7 +81,7 @@ public app behavior, use the config paths above instead.
|
|
|
79
81
|
| `SECRETS_ENCRYPTION_KEY` | Legacy app-local/shared encryption fallback. | A stable encryption key; prefer the workspace key for new shared vaults. |
|
|
80
82
|
| `WORKSPACE_SECRETS_ENCRYPTION_KEY` | Stable encryption key for a workspace-shared secrets vault. | The same stable key in every app that reads the vault. |
|
|
81
83
|
| `WORKSPACE_SECRETS_ENCRYPTION_KEY_PREVIOUS` | Previous workspace key during rotation. | The old key only; remove it after migration. |
|
|
82
|
-
| `ANTHROPIC_API_KEY` |
|
|
84
|
+
| `ANTHROPIC_API_KEY` | Shared fallback for self-hosted apps, including remote databases. | An Anthropic API key; saved personal, organization, or workspace-scoped keys take precedence. |
|
|
83
85
|
| `AGENT_ENGINE` | Explicitly selects the agent engine instead of auto-detecting from provider keys. | A registered engine name such as `anthropic`, `ai-sdk:openai`, `builder`, or `codex-cli`. |
|
|
84
86
|
| `AGENT_BUILT_IN_ENGINES` | Restricts which built-in engines are registered at all, so the rest never appear in the model picker or resolve by name. | A comma-separated list of built-in engine names such as `ai-sdk:openai`; unset registers every built-in. |
|
|
85
87
|
| `AGENT_SOURCE_SWEEP_TOOL_CALL_THRESHOLD` | Read-only source/search tool calls one turn may make before the agent is told to converge and answer from what it gathered. | A positive integer; defaults to 24. Raise it for research-shaped apps that legitimately inspect many records. |
|
|
@@ -169,8 +171,38 @@ specific Google API integrations; they are not required for browser sign-in.
|
|
|
169
171
|
|
|
170
172
|
## Optional AI, search, and email fallbacks
|
|
171
173
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
### LLM provider keys {#llm-provider-keys}
|
|
175
|
+
|
|
176
|
+
For local development, put a supported provider key in the app's `.env` file
|
|
177
|
+
before starting `pnpm dev`. For example:
|
|
178
|
+
|
|
179
|
+
```dotenv
|
|
180
|
+
ANTHROPIC_API_KEY=replace-with-your-key
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
For an app-wide fallback, set a supported provider key in the server-side
|
|
184
|
+
environment of a self-hosted app. This also works with a remote PostgreSQL
|
|
185
|
+
database. Any signed-in user without a personal, organization-scoped, or
|
|
186
|
+
workspace-scoped provider key can use the deployment's provider account, and
|
|
187
|
+
usage is billed to that account. Anonymous public runs and synthetic traffic do
|
|
188
|
+
not receive this fallback. Personal, organization, and workspace-scoped keys
|
|
189
|
+
take precedence. Setting a deployment key opts in to
|
|
190
|
+
app-wide access and billing; no extra shared-key flag is needed. Production
|
|
191
|
+
Hosted-workspace runtimes block deployment provider-key fallbacks.
|
|
192
|
+
|
|
193
|
+
To keep a key scoped, select **Custom keys** in the app's LLM setup. In a
|
|
194
|
+
PostgreSQL app, a personal key stays with its user; organization scope shares a
|
|
195
|
+
key with the active organization and is available to admins. The app stores
|
|
196
|
+
these saved keys in its encrypted database-backed credential store.
|
|
197
|
+
|
|
198
|
+
To use Builder's managed provider, connect with **Use Builder.io** in the app's
|
|
199
|
+
LLM setup. This uses the Builder connection instead of a provider API key from
|
|
200
|
+
the table below.
|
|
201
|
+
|
|
202
|
+
The table below lists optional deployment-level fallbacks for self-hosted apps.
|
|
203
|
+
See the LLM guidance above for which users can use the deployment provider key
|
|
204
|
+
and how usage is billed. Production Hosted-workspace runtimes block deployment
|
|
205
|
+
provider-key fallbacks.
|
|
174
206
|
|
|
175
207
|
Every provider key below selects its engine on its own: dropping one in is
|
|
176
208
|
enough, and `AGENT_ENGINE` is only needed to pick between several.
|
|
@@ -20,8 +20,7 @@ In this guide, you'll create an agent with a chat UI and call its included
|
|
|
20
20
|
- [Node.js](https://nodejs.org) 22.22 or later
|
|
21
21
|
- [pnpm](https://pnpm.io) available on your `PATH` (run `corepack enable` in
|
|
22
22
|
the generated app if it is not)
|
|
23
|
-
-
|
|
24
|
-
or a local Ollama model
|
|
23
|
+
- Optional while setting up; required to run the agent: Builder.io, an Anthropic/OpenAI key, or local Ollama
|
|
25
24
|
|
|
26
25
|
## Create an agent
|
|
27
26
|
|
|
@@ -64,11 +63,12 @@ enter an email or password for local development.
|
|
|
64
63
|
|
|
65
64
|
</Callout>
|
|
66
65
|
|
|
67
|
-
## Connect an LLM
|
|
66
|
+
## Connect an LLM (optional) {#connect-an-llm}
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
Connect with **Use Builder.io**, add a personal or organization key through
|
|
69
|
+
**Custom keys**, or set a provider key in `.env` for local development and in
|
|
70
|
+
the deployment environment for app-wide use on self-hosted apps. See the [LLM
|
|
71
|
+
provider setup](/docs/environment-variables#llm-provider-keys).
|
|
72
72
|
|
|
73
73
|
## Run the action from the agent
|
|
74
74
|
|
|
@@ -76,7 +76,7 @@ An action is a typed function that your React UI can call from code and agents
|
|
|
76
76
|
can use as a tool. The Chat template includes a simple `hello` action so you
|
|
77
77
|
can try the pattern before writing one yourself.
|
|
78
78
|
|
|
79
|
-
In the
|
|
79
|
+
In the prompt on the **Get started** page, ask:
|
|
80
80
|
|
|
81
81
|
> Call the hello action for Alex.
|
|
82
82
|
|
|
@@ -260,7 +260,10 @@ By default every workspace can reach the hosted first-party apps (Mail, Calendar
|
|
|
260
260
|
"workspaceCore": "@my-company-platform/shared",
|
|
261
261
|
"builtinAgents": {
|
|
262
262
|
"mode": "selected",
|
|
263
|
-
"include": ["mail", "calendar"]
|
|
263
|
+
"include": ["mail", "calendar", "design"],
|
|
264
|
+
"urls": {
|
|
265
|
+
"design": "https://design.example.test"
|
|
266
|
+
}
|
|
264
267
|
}
|
|
265
268
|
}
|
|
266
269
|
}
|
|
@@ -268,10 +271,11 @@ By default every workspace can reach the hosted first-party apps (Mail, Calendar
|
|
|
268
271
|
|
|
269
272
|
- `mode`: `"all"` (default, every public first-party app), `"none"` (no built-ins), or `"selected"` (only `include`).
|
|
270
273
|
- `include`: the built-ins this workspace offers when `mode` is `"selected"`. Anything else stays unknown to the workspace.
|
|
274
|
+
- `urls` (optional): maps built-in IDs to HTTPS base URL overrides for offered built-ins without changing the offered agents. It replaces the canonical hosted URL, including in a seeded manifest that still uses that default, while custom connected remote-agent URLs and workspace-app overlays retain priority. Unknown IDs and invalid URLs fail parsing. Each value must be a trimmed absolute HTTPS URL with no credentials, query, or fragment. Local-development routing keeps priority and uses local URLs.
|
|
271
275
|
|
|
272
|
-
Unknown
|
|
276
|
+
Unknown IDs in `include` log a warning and are ignored. A standalone app can use the same key in its own `package.json`. `agent-native dev` and workspace deploys pass the value to every app as `AGENT_NATIVE_BUILTIN_AGENTS_JSON`.
|
|
273
277
|
|
|
274
|
-
This config controls the app list, agent discovery, and agent-to-agent calls. Mounted workspace apps and connected remote
|
|
278
|
+
This config controls the app list, agent discovery, and agent-to-agent calls. Mounted workspace apps and custom connected remote-agent URLs retain priority, and MCP app access stays a separate routing permission.
|
|
275
279
|
|
|
276
280
|
## Shared MCP servers {#shared-mcp}
|
|
277
281
|
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Chat: Your First Feature"
|
|
3
|
-
description: "The
|
|
3
|
+
description: "The files that render Chat's starter screens, what their real props do, and a full walkthrough of adding a feature end to end."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Your First Feature
|
|
7
7
|
|
|
8
|
-
This page is for developers extending the [Chat template](/docs/template-chat). It covers the
|
|
8
|
+
This page is for developers extending the [Chat template](/docs/template-chat). It covers the files that render the starter screens, then walks through everything the agent typically touches when you ask for a real feature.
|
|
9
9
|
|
|
10
10
|
## First code to inspect {#first-code}
|
|
11
11
|
|
|
12
12
|
- `actions/hello.ts` is the starter behavior the agent can call. Replace it or
|
|
13
13
|
add actions beside it.
|
|
14
|
-
- `app/
|
|
15
|
-
|
|
14
|
+
- `app/components/chat/ChatRouteContent.tsx` renders the full-page chat surface
|
|
15
|
+
at `/chat/<threadId>`. Adjust the empty state, composer, or message slots here.
|
|
16
|
+
- `app/components/home/HomePage.tsx` is the editable Get started landing page at
|
|
17
|
+
`/home`. `/chat` starts a new chat.
|
|
16
18
|
- `AGENTS.md` tells the built-in agent how to work inside this app.
|
|
17
19
|
|
|
18
20
|
<FileTree
|
|
@@ -32,12 +34,28 @@ This page is for developers extending the [Chat template](/docs/template-chat).
|
|
|
32
34
|
note: "standard navigation action",
|
|
33
35
|
},
|
|
34
36
|
{
|
|
35
|
-
path: "app/routes/
|
|
36
|
-
note: "
|
|
37
|
+
path: "app/routes/home.tsx",
|
|
38
|
+
note: "/home: the Get started landing page; /chat: starts a new chat",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
path: "app/routes/chat._index.tsx",
|
|
42
|
+
note: "/chat: starts a new chat and hands off to /chat/:threadId",
|
|
37
43
|
},
|
|
38
44
|
{
|
|
39
45
|
path: "app/routes/chat.$threadId.tsx",
|
|
40
|
-
note: "
|
|
46
|
+
note: "/chat/:threadId: renders ChatRouteContent for that thread",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
path: "app/components/chat/ChatRouteContent.tsx",
|
|
50
|
+
note: "the full-page chat surface; edit the empty state, composer, and message slots",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
path: "app/components/home/HomePage.tsx",
|
|
54
|
+
note: "the editable Get started home page",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
path: "app/lib/chat-paths.ts",
|
|
58
|
+
note: "Chat path helpers",
|
|
41
59
|
},
|
|
42
60
|
{
|
|
43
61
|
path: "AGENTS.md",
|
|
@@ -46,46 +64,41 @@ This page is for developers extending the [Chat template](/docs/template-chat).
|
|
|
46
64
|
]}
|
|
47
65
|
/>
|
|
48
66
|
|
|
49
|
-
The
|
|
67
|
+
The chat surface is assembled from AgentKit pieces: a transport, a thread root, and the chat view. Its copy comes from i18n keys rather than literal strings:
|
|
50
68
|
|
|
51
69
|
<AnnotatedCode
|
|
52
70
|
id="doc-block-chat4"
|
|
53
|
-
title="app/
|
|
54
|
-
filename="app/
|
|
71
|
+
title="app/components/chat/ChatRouteContent.tsx (trimmed)"
|
|
72
|
+
filename="app/components/chat/ChatRouteContent.tsx"
|
|
55
73
|
language="tsx"
|
|
56
74
|
code={
|
|
57
|
-
'import {
|
|
75
|
+
'import { createAgentNativeAgentKitTransport } from "@agent-native/core/client/agentkit-chat/transport";\nimport { useT } from "@agent-native/core/client/i18n";\nimport { AgentKitChat } from "@agent-native/toolkit/app/agentkit/react/components";\nimport { CoreAgentKitRoot } from "@agent-native/toolkit/app/chat/agentkit-chat/index";\nimport { useState } from "react";\nimport { useNavigate, useParams } from "react-router";\n\nimport { chatThreadPath } from "@/lib/chat-paths";\nimport { TAB_ID } from "@/lib/tab-id";\n\nexport default function ChatRouteContent() {\n const { threadId } = useParams();\n const navigate = useNavigate();\n const t = useT();\n const [transport] = useState(() =>\n createAgentNativeAgentKitTransport({\n browserTabId: TAB_ID,\n surface: "app",\n adapter: { textFormat: "markdown" },\n }),\n );\n if (!threadId) return null;\n\n return (\n <CoreAgentKitRoot\n transport={transport}\n threadId={threadId}\n labels={{ composerPlaceholder: t("chat.composerPlaceholder") }}\n slots={{ emptyState: ChatEmptyState }}\n onThreadForked={(thread) => navigate(chatThreadPath(thread.id))}\n >\n <AgentKitChat\n emptyComposerPlacement="center"\n composerProps={{ requireAgentEngine: true, voiceEnabled: true }}\n />\n </CoreAgentKitRoot>\n );\n}\n\nfunction ChatEmptyState() {\n const t = useT();\n return (\n <div className="agentkit-chat-empty-copy">\n <h1>{t("chat.heroTitle")}</h1>\n </div>\n );\n}'
|
|
58
76
|
}
|
|
59
77
|
annotations={[
|
|
60
78
|
{
|
|
61
|
-
lines: "
|
|
62
|
-
label: "
|
|
63
|
-
note: "
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
lines: "38",
|
|
67
|
-
label: "Tab identity",
|
|
68
|
-
note: "`TAB_ID` (`app/lib/tab-id.ts`, a random id generated once per browser tab) lets the shared chat runtime tell multiple open tabs of the same app apart, so a run started in one tab isn't mistaken for one in another.",
|
|
79
|
+
lines: "15-21",
|
|
80
|
+
label: "Transport",
|
|
81
|
+
note: "`createAgentNativeAgentKitTransport` connects the chat view to the app's agent runtime. `TAB_ID` (`app/lib/tab-id.ts`, a random id generated once per browser tab) lets the runtime tell open tabs of the same app apart, so a run started in one tab isn't mistaken for one in another.",
|
|
69
82
|
},
|
|
70
83
|
{
|
|
71
|
-
lines: "
|
|
72
|
-
label: "
|
|
73
|
-
note:
|
|
84
|
+
lines: "25-30",
|
|
85
|
+
label: "Thread root",
|
|
86
|
+
note: "`CoreAgentKitRoot` loads the thread named in `/chat/:threadId` (`chat.$threadId.tsx`). Visiting `/chat` creates a new thread id and hands off here. When a thread is forked, `chatThreadPath` moves the URL to the new thread.",
|
|
74
87
|
},
|
|
75
88
|
{
|
|
76
|
-
lines: "
|
|
77
|
-
label: "
|
|
78
|
-
note:
|
|
89
|
+
lines: "29",
|
|
90
|
+
label: "Slots",
|
|
91
|
+
note: "Slots replace parts of the chat view. The real file also passes `message`, `runFailure`, `connectionRequest`, and `footer` slots for recovery messages, MCP connection cards, and the agent footer.",
|
|
79
92
|
},
|
|
80
93
|
{
|
|
81
|
-
lines: "
|
|
82
|
-
label: "
|
|
83
|
-
note: '
|
|
94
|
+
lines: "32-35",
|
|
95
|
+
label: "Centered composer",
|
|
96
|
+
note: '`emptyComposerPlacement="center"` centers the composer until the thread has a message. `requireAgentEngine` shows the Connect AI card until a model is connected.',
|
|
84
97
|
},
|
|
85
98
|
{
|
|
86
|
-
lines: "
|
|
87
|
-
label: "
|
|
88
|
-
note:
|
|
99
|
+
lines: "40-47",
|
|
100
|
+
label: "Empty state",
|
|
101
|
+
note: "The heading above the centered composer. Its copy is `chat.heroTitle` in `app/i18n/en-US.ts`: edit the catalog to change the pitch, or add elements here.",
|
|
89
102
|
},
|
|
90
103
|
]}
|
|
91
104
|
/>
|
|
@@ -126,10 +139,10 @@ The rest of the feature follows from there:
|
|
|
126
139
|
- `actions/create-note.ts` — a `defineAction` with a Zod schema (`title`, `body`), shaped like `actions/hello.ts`.
|
|
127
140
|
- `actions/list-notes.ts` — a read-only action (`readOnly: true`, like `actions/view-screen.ts`) that queries the new table through `accessFilter`.
|
|
128
141
|
- `app/routes/notes.tsx` — a new route; the app uses file-system routing (`flatRoutes()` in `app/routes.ts`), so adding the file is enough to mount `/notes`.
|
|
129
|
-
- A
|
|
142
|
+
- A link in `app/components/layout/Sidebar.tsx`, added before `ChatThreadsSection` and pointing at `/notes`.
|
|
130
143
|
- An `AGENTS.md` addition telling the agent notes exist and which actions manage them.
|
|
131
144
|
|
|
132
|
-
A new action is callable by chat as soon as it exists — every `defineAction` is a tool by default unless it sets `agentTool: false`. It won't necessarily be in the model's very first request, though: `server/plugins/agent-chat.ts` sets `INITIAL_TOOL_NAMES = ["view-screen", "navigate", "hello"]`, which controls only which tool schemas are sent on the first turn. Everything else, including a brand-new `create-note`, stays reachable through `tool-search` and loads on demand — add a name to that list only if you want it in the model's default toolset from message one.
|
|
145
|
+
A new action is callable by chat as soon as it exists — every `defineAction` is a tool by default unless it sets `agentTool: false`. It won't necessarily be in the model's very first request, though: `server/plugins/agent-chat.ts` sets `INITIAL_TOOL_NAMES = ["view-screen", "navigate", "hello", "provider-api-request"]`, which controls only which tool schemas are sent on the first turn. Everything else, including a brand-new `create-note`, stays reachable through `tool-search` and loads on demand — add a name to that list only if you want it in the model's default toolset from message one.
|
|
133
146
|
|
|
134
147
|
## Use your own agent backend {#own-agent-backend}
|
|
135
148
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.207.0
|
|
3
|
+
"version": "0.207.0",
|
|
4
4
|
"description": "The agentic application framework for building autonomous agents with intuitive UIs",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -694,8 +694,8 @@
|
|
|
694
694
|
"yaml": "^2.9.0",
|
|
695
695
|
"yjs": "^13.6.33",
|
|
696
696
|
"zod": "^4.3.6",
|
|
697
|
-
"@agent-native/
|
|
698
|
-
"@agent-native/
|
|
697
|
+
"@agent-native/recap-cli": "^0.5.69",
|
|
698
|
+
"@agent-native/agentkit": "^0.207.0"
|
|
699
699
|
},
|
|
700
700
|
"devDependencies": {
|
|
701
701
|
"@ai-sdk/anthropic": "^3.0.71",
|
|
@@ -765,7 +765,7 @@
|
|
|
765
765
|
"xlsx": "^0.18.5"
|
|
766
766
|
},
|
|
767
767
|
"peerDependencies": {
|
|
768
|
-
"@agent-native/core-corpus": "0.
|
|
768
|
+
"@agent-native/core-corpus": ">=0.196.0",
|
|
769
769
|
"@ai-sdk/anthropic": ">=3",
|
|
770
770
|
"@ai-sdk/cohere": ">=3",
|
|
771
771
|
"@ai-sdk/google": ">=3",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
===================================================================
|
|
2
2
|
--- a/.agents/skills/adding-a-feature/SKILL.md
|
|
3
3
|
+++ b/.agents/skills/adding-a-feature/SKILL.md
|
|
4
|
-
@@ -
|
|
4
|
+
@@ -131,11 +131,12 @@
|
|
5
5
|
Instruction examples may name secret keys like `SLACK_WEBHOOK`, but must use
|
|
6
6
|
placeholders such as `${keys.SLACK_WEBHOOK}` or `<SLACK_WEBHOOK>`. Do not paste
|
|
7
7
|
real keys, internal data, or customer data into instructions as examples.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
-# Chat — Agent Guide
|
|
6
6
|
+# App — Agent Guide
|
|
7
7
|
|
|
8
|
-
-Chat is the minimal chat-first agent-native app. `/` redirects to shared sign-in
|
|
8
|
+
-Chat is the minimal chat-first agent-native app. `/` redirects to shared sign-in, then `/home`, the editable Get started page. Chat lives at `/chat`; new chats start there. Actions carry capabilities; screens exist only for durable workflows.
|
|
9
9
|
+This starter ships as a blank Agent-Native app canvas — that describes its
|
|
10
10
|
+initial state, not necessarily its current one. See `DEVELOPING.md` before
|
|
11
11
|
+making any source code change.
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
## Application state
|
|
32
32
|
|
|
33
|
-
-- `navigation` describes the view and selected ids. Chat is `chat` at `/home`; `/` opens shared sign-in/signup.
|
|
33
|
+
-- `navigation` describes the view and selected ids. Chat is `chat` at `/chat` and `/chat/<threadId>`; the Get started page is `home` at `/home`; `/` opens shared sign-in/signup.
|
|
34
34
|
+- `navigation` describes the view and selected ids. The default home view is
|
|
35
35
|
+ `home` at `/` (blank app canvas). No agent rail or chat is mounted by
|
|
36
36
|
+ default; add one only when the user asks.
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
## Building a domain app
|
|
40
40
|
|
|
41
|
-
-Choose the primary workflow and route before editing. Add a domain route under `app/routes/` and set `app.homePath` in `server/plugins/agent-native-email-branding.ts` with `defineAppConfig`.
|
|
41
|
+
-Choose the primary workflow and route before editing. Add a domain route under `app/routes/` and set `app.homePath` in `server/plugins/agent-native-email-branding.ts` with `defineAppConfig`. The default Get started page lives at `/home`, and Chat stays at `/chat`; edit `app/routes/home.tsx` when replacing that page with a domain-specific home. Add a static link in `app/components/layout/Sidebar.tsx` before `ChatThreadsSection`; `Header.tsx` uses `APP_TITLE` elsewhere. Shared sidebar and AgentInspector remain.
|
|
42
42
|
+Choose the primary workflow and route before editing. Build on the blank canvas in `app/routes/_index.tsx` or add domain routes under `app/routes/`. This starter has no Chat route, sidebar, header, or agent rail; add only the navigation the product needs. Set `app.homePath` in the existing `defineAppConfig` in `server/plugins/config.ts` as `DEVELOPING.md` describes.
|
|
43
43
|
|
|
44
44
|
-Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here; do not rewrite `README.md` or `DESIGN.md`. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow, including overlap rejection, cancellation freeing the slot, and authenticated landing. Skip production build and extra test suites.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
===================================================================
|
|
2
2
|
--- a/app/components/layout/Layout.tsx
|
|
3
3
|
+++ b/app/components/layout/Layout.tsx
|
|
4
|
-
@@ -1,
|
|
4
|
+
@@ -1,188 +1,28 @@
|
|
5
5
|
-import { useT } from "@agent-native/core/client/i18n";
|
|
6
6
|
-import { HeaderActionsProvider } from "@agent-native/toolkit/app-shell/header-actions";
|
|
7
7
|
-import {
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
- SheetTitle,
|
|
24
24
|
-} from "@/components/ui/sheet";
|
|
25
25
|
-import { APP_TITLE } from "@/lib/app-config";
|
|
26
|
+
-import { HOME_PATH, isChatPathname } from "@/lib/chat-paths";
|
|
26
27
|
-
|
|
27
28
|
-import { Sidebar } from "./Sidebar";
|
|
28
29
|
-
|
|
@@ -43,8 +44,8 @@
|
|
|
43
44
|
-
|
|
44
45
|
-function routeOwnsToolbar(pathname: string): boolean {
|
|
45
46
|
- return (
|
|
46
|
-
- pathname ===
|
|
47
|
-
- pathname
|
|
47
|
+
- pathname === HOME_PATH ||
|
|
48
|
+
- isChatPathname(pathname) ||
|
|
48
49
|
- pathname === "/database" ||
|
|
49
50
|
- pathname.startsWith("/extensions")
|
|
50
51
|
- );
|
|
@@ -66,8 +67,7 @@
|
|
|
66
67
|
- const t = useT();
|
|
67
68
|
- const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
|
|
68
69
|
- const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
|
69
|
-
- const isChatRoute =
|
|
70
|
-
- location.pathname === "/home" || location.pathname.startsWith("/chat/");
|
|
70
|
+
- const isChatRoute = isChatPathname(location.pathname);
|
|
71
71
|
- // Settings brings its own navigation, header, and agent toggle, so it
|
|
72
72
|
- // renders full width.
|
|
73
73
|
- const settingsOwnsChrome = isSettingsPathname(location.pathname);
|
|
@@ -79,8 +79,7 @@
|
|
|
79
79
|
- const chatHomeHandoffPending = isAgentChatHomeHandoffActive("chat");
|
|
80
80
|
- useAgentChatHomeHandoffLinks({
|
|
81
81
|
- storageKey: "chat",
|
|
82
|
-
- isChatPath:
|
|
83
|
-
- pathname === "/home" || pathname.startsWith("/chat/"),
|
|
82
|
+
- isChatPath: isChatPathname,
|
|
84
83
|
- requireActiveHandoff: true,
|
|
85
84
|
- });
|
|
86
85
|
-
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
===================================================================
|
|
2
2
|
--- a/app/hooks/use-navigation-state.ts
|
|
3
3
|
+++ b/app/hooks/use-navigation-state.ts
|
|
4
|
-
@@ -
|
|
4
|
+
@@ -1,85 +1,41 @@
|
|
5
|
+
import { appBasePath, appPath } from "@agent-native/core/client/api-path";
|
|
6
|
+
import { useAgentRouteState } from "@agent-native/core/client/navigation";
|
|
7
|
+
|
|
8
|
+
-import {
|
|
9
|
+
- chatThreadPath,
|
|
10
|
+
- HOME_PATH,
|
|
11
|
+
- isChatPathname,
|
|
12
|
+
- NEW_CHAT_PATH,
|
|
13
|
+
- threadIdFromPath,
|
|
14
|
+
-} from "@/lib/chat-paths";
|
|
15
|
+
import { TAB_ID } from "@/lib/tab-id";
|
|
5
16
|
|
|
6
17
|
export interface NavigationState {
|
|
7
18
|
view: string;
|
|
@@ -31,19 +42,9 @@
|
|
|
31
42
|
});
|
|
32
43
|
}
|
|
33
44
|
|
|
34
|
-
-function threadIdFromPath(pathname: string): string | null {
|
|
35
|
-
- const match = pathname.match(/^\/chat\/([^/]+)/);
|
|
36
|
-
- if (!match) return null;
|
|
37
|
-
- try {
|
|
38
|
-
- const value = decodeURIComponent(match[1]).trim();
|
|
39
|
-
- return value || null;
|
|
40
|
-
- } catch {
|
|
41
|
-
- return null;
|
|
42
|
-
- }
|
|
43
|
-
-}
|
|
44
|
-
-
|
|
45
45
|
function viewForPath(pathname: string): string {
|
|
46
|
-
- if (
|
|
46
|
+
- if (isChatPathname(pathname)) return "chat";
|
|
47
|
+
- if (pathname === HOME_PATH) return "home";
|
|
47
48
|
- if (pathname.startsWith("/database")) return "database";
|
|
48
49
|
- if (pathname.startsWith("/extensions")) return "extensions";
|
|
49
50
|
- if (pathname.startsWith("/observability")) return "observability";
|
|
@@ -60,9 +61,10 @@
|
|
|
60
61
|
function pathForView(view?: string): string {
|
|
61
62
|
switch (view) {
|
|
62
63
|
- case "chat":
|
|
63
|
-
case "home":
|
|
64
64
|
- case "ask":
|
|
65
|
-
- return
|
|
65
|
+
- return NEW_CHAT_PATH;
|
|
66
|
+
case "home":
|
|
67
|
+
- return HOME_PATH;
|
|
66
68
|
- case "database":
|
|
67
69
|
- return "/database";
|
|
68
70
|
- case "extensions":
|
|
@@ -77,29 +79,20 @@
|
|
|
77
79
|
- return "/settings/organization";
|
|
78
80
|
+ return "/";
|
|
79
81
|
default:
|
|
80
|
-
- return
|
|
82
|
+
- return HOME_PATH;
|
|
81
83
|
+ return "/";
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
-function pathForCommand(command: any): string {
|
|
87
|
+
-export function pathForCommand(command: any): string {
|
|
86
88
|
- const path = pathForView(command?.view);
|
|
87
|
-
- if (
|
|
89
|
+
- if (command?.view !== "chat" && command?.view !== "ask") return path;
|
|
88
90
|
- const threadId =
|
|
89
91
|
- typeof command?.threadId === "string" ? command.threadId.trim() : "";
|
|
90
|
-
- return threadId ?
|
|
92
|
+
- return threadId ? chatThreadPath(threadId) : path;
|
|
91
93
|
-}
|
|
92
94
|
-
|
|
93
95
|
function routerPath(path: string): string {
|
|
94
96
|
const basePath = appBasePath();
|
|
95
97
|
if (!basePath) return path;
|
|
96
98
|
if (path === basePath) return "/";
|
|
97
|
-
@@ -89,8 +43,4 @@
|
|
98
|
-
return path.slice(basePath.length) || "/";
|
|
99
|
-
}
|
|
100
|
-
return path;
|
|
101
|
-
}
|
|
102
|
-
-
|
|
103
|
-
-function isChatPath(pathname: string): boolean {
|
|
104
|
-
- return pathname === "/home" || pathname.startsWith("/chat/");
|
|
105
|
-
-}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
===================================================================
|
|
2
2
|
--- a/app/root.tsx
|
|
3
3
|
+++ b/app/root.tsx
|
|
4
|
-
@@ -1,
|
|
4
|
+
@@ -1,76 +1,50 @@
|
|
5
5
|
import { configureTracking } from "@agent-native/core/client/analytics";
|
|
6
6
|
import { appPath } from "@agent-native/core/client/api-path";
|
|
7
7
|
import { useDbSync } from "@agent-native/core/client/hooks";
|
|
@@ -33,6 +33,12 @@
|
|
|
33
33
|
import { AppToolkitProvider } from "@/components/ui/toolkit-provider";
|
|
34
34
|
import { useNavigationState } from "@/hooks/use-navigation-state";
|
|
35
35
|
-import { APP_TITLE } from "@/lib/app-config";
|
|
36
|
+
-import {
|
|
37
|
+
- HOME_PATH,
|
|
38
|
+
- isChatPathname,
|
|
39
|
+
- NEW_CHAT_PATH,
|
|
40
|
+
- threadIdFromPath,
|
|
41
|
+
-} from "@/lib/chat-paths";
|
|
36
42
|
+import { APP_NAME, APP_TITLE } from "@/lib/app-config";
|
|
37
43
|
import { TAB_ID } from "@/lib/tab-id";
|
|
38
44
|
|
|
@@ -79,7 +85,7 @@
|
|
|
79
85
|
<meta name="mobile-web-app-capable" content="yes" />
|
|
80
86
|
<meta
|
|
81
87
|
name="apple-mobile-web-app-status-bar-style"
|
|
82
|
-
@@ -
|
|
88
|
+
@@ -100,96 +74,19 @@
|
|
83
89
|
});
|
|
84
90
|
return null;
|
|
85
91
|
}
|
|
@@ -104,7 +110,7 @@
|
|
|
104
110
|
- const navigate = useNavigate();
|
|
105
111
|
- const t = useT();
|
|
106
112
|
- const location = useLocation();
|
|
107
|
-
- const isChatThread = location.pathname
|
|
113
|
+
- const isChatThread = threadIdFromPath(location.pathname) !== null;
|
|
108
114
|
- useCommandMenuShortcut(useCallback(() => setCmdkOpen(true), []));
|
|
109
115
|
- return (
|
|
110
116
|
- <>
|
|
@@ -123,8 +129,13 @@
|
|
|
123
129
|
- {t("chat.newChat")}
|
|
124
130
|
- </CommandMenu.Item>
|
|
125
131
|
- ) : null}
|
|
126
|
-
- {
|
|
127
|
-
- <CommandMenu.Item onSelect={() => navigate(
|
|
132
|
+
- {location.pathname !== HOME_PATH ? (
|
|
133
|
+
- <CommandMenu.Item onSelect={() => navigate(HOME_PATH)}>
|
|
134
|
+
- {t("navigation.home")}
|
|
135
|
+
- </CommandMenu.Item>
|
|
136
|
+
- ) : null}
|
|
137
|
+
- {!isChatPathname(location.pathname) ? (
|
|
138
|
+
- <CommandMenu.Item onSelect={() => navigate(NEW_CHAT_PATH)}>
|
|
128
139
|
- {t("navigation.chat")}
|
|
129
140
|
- </CommandMenu.Item>
|
|
130
141
|
- ) : null}
|
|
@@ -5,16 +5,20 @@
|
|
|
5
5
|
"CHANGELOG.md",
|
|
6
6
|
"actions/navigate.spec.ts",
|
|
7
7
|
"app/components/chat",
|
|
8
|
+
"app/components/home",
|
|
8
9
|
"app/components/layout/AgentInspector.test.tsx",
|
|
9
10
|
"app/components/layout/AgentInspector.tsx",
|
|
10
11
|
"app/components/layout/Header.tsx",
|
|
11
12
|
"app/components/layout/Sidebar.tsx",
|
|
12
13
|
"app/i18n",
|
|
13
14
|
"app/i18n-data.ts",
|
|
15
|
+
"app/lib/chat-paths.spec.ts",
|
|
16
|
+
"app/lib/chat-paths.ts",
|
|
14
17
|
"app/lib/sidebar-thread-state.spec.ts",
|
|
15
18
|
"app/lib/sidebar-thread-state.ts",
|
|
16
19
|
"app/routes/agent.tsx",
|
|
17
20
|
"app/routes/chat.$threadId.tsx",
|
|
21
|
+
"app/routes/chat._index.tsx",
|
|
18
22
|
"app/routes/database.tsx",
|
|
19
23
|
"app/routes/extensions.$id.$slug.tsx",
|
|
20
24
|
"app/routes/extensions.$id.tsx",
|
|
@@ -25,8 +25,12 @@ never copy a value into app code or client-visible state.
|
|
|
25
25
|
3. If the app truly needs its own API key, register it with the shared secrets
|
|
26
26
|
surface. Do not build a parallel key form or storage table.
|
|
27
27
|
4. Use deployment configuration only for a secret owned by the deployed app,
|
|
28
|
-
such as a webhook verification secret.
|
|
29
|
-
|
|
28
|
+
such as a webhook verification secret. LLM inference keys are an app-owned
|
|
29
|
+
exception: self-hosted apps may use provider keys from deployment env as a
|
|
30
|
+
shared fallback, while scoped user or organization keys take precedence.
|
|
31
|
+
Hosted-workspace deployments backed by a shared database must not share
|
|
32
|
+
those env keys across apps or tenants. This exception does not authorize
|
|
33
|
+
using env credentials to access user-owned provider data.
|
|
30
34
|
|
|
31
35
|
## Register an app-local API key
|
|
32
36
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Chat — Agent Guide
|
|
2
2
|
|
|
3
|
-
Chat is the minimal chat-first agent-native app. `/` redirects to shared sign-in
|
|
3
|
+
Chat is the minimal chat-first agent-native app. `/` redirects to shared sign-in, then `/home`, the editable Get started page. Chat lives at `/chat`; new chats start there. Actions carry capabilities; screens exist only for durable workflows.
|
|
4
4
|
|
|
5
5
|
## Skills
|
|
6
6
|
|
|
@@ -19,12 +19,12 @@ For custom branding, keep `server/plugins/agent-native-email-branding.ts` aligne
|
|
|
19
19
|
|
|
20
20
|
## Application state
|
|
21
21
|
|
|
22
|
-
- `navigation` describes the view and selected ids. Chat is `chat` at `/home`; `/` opens shared sign-in/signup.
|
|
22
|
+
- `navigation` describes the view and selected ids. Chat is `chat` at `/chat` and `/chat/<threadId>`; the Get started page is `home` at `/home`; `/` opens shared sign-in/signup.
|
|
23
23
|
- Use `navigate` when supported and `view-screen` for a fresh read of visible details; basic navigation is already in `<current-screen>`.
|
|
24
24
|
|
|
25
25
|
## Building a domain app
|
|
26
26
|
|
|
27
|
-
Choose the primary workflow and route before editing. Add a domain route under `app/routes/` and set `app.homePath` in `server/plugins/agent-native-email-branding.ts` with `defineAppConfig`.
|
|
27
|
+
Choose the primary workflow and route before editing. Add a domain route under `app/routes/` and set `app.homePath` in `server/plugins/agent-native-email-branding.ts` with `defineAppConfig`. The default Get started page lives at `/home`, and Chat stays at `/chat`; edit `app/routes/home.tsx` when replacing that page with a domain-specific home. Add a static link in `app/components/layout/Sidebar.tsx` before `ChatThreadsSection`; `Header.tsx` uses `APP_TITLE` elsewhere. Shared sidebar and AgentInspector remain.
|
|
28
28
|
|
|
29
29
|
Use `adding-a-feature` for functional parity and `frontend-design` for a user-facing screen. Keep feature guidance here; do not rewrite `README.md` or `DESIGN.md`. After all edits, run one typecheck, one doctor check, and one browser smoke of the primary workflow, including overlap rejection, cancellation freeing the slot, and authenticated landing. Skip production build and extra test suites.
|
|
30
30
|
|