@agent-native/core 0.63.0 → 0.63.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/code-agent-executor.js +1 -1
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/create.js +1 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +1 -1
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/client/chat/index.d.ts +2 -1
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +2 -1
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/chat-view-transition.d.ts +17 -0
- package/dist/client/chat-view-transition.d.ts.map +1 -1
- package/dist/client/chat-view-transition.js +46 -0
- package/dist/client/chat-view-transition.js.map +1 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.d.ts +27 -0
- package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -0
- package/dist/client/use-agent-chat-home-handoff.js +120 -0
- package/dist/client/use-agent-chat-home-handoff.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/styles/agent-native.css +2 -6
- package/dist/templates/workspace-root/README.md +4 -4
- package/docs/content/actions.md +32 -42
- package/docs/content/agent-surfaces.md +105 -84
- package/docs/content/agent-teams.md +2 -14
- package/docs/content/agent-web-surfaces.md +4 -4
- package/docs/content/authentication.md +40 -24
- package/docs/content/automations.md +18 -36
- package/docs/content/blueprint-installer.md +3 -0
- package/docs/content/cli-adapters.md +24 -168
- package/docs/content/client.md +11 -77
- package/docs/content/cloneable-saas.md +1 -1
- package/docs/content/code-agents-ui.md +43 -0
- package/docs/content/components.md +10 -23
- package/docs/content/context-awareness.md +3 -3
- package/docs/content/creating-templates.md +20 -18
- package/docs/content/database.md +1 -1
- package/docs/content/deployment.md +5 -37
- package/docs/content/dispatch.md +17 -28
- package/docs/content/drop-in-agent.md +24 -111
- package/docs/content/durable-resume.md +4 -0
- package/docs/content/embedding-sdk.md +141 -135
- package/docs/content/evals.md +3 -3
- package/docs/content/extensions.md +1 -1
- package/docs/content/external-agents.md +34 -60
- package/docs/content/faq.md +5 -5
- package/docs/content/frames.md +13 -4
- package/docs/content/getting-started.md +96 -142
- package/docs/content/harness-agents.md +24 -7
- package/docs/content/human-approval.md +1 -1
- package/docs/content/key-concepts.md +14 -99
- package/docs/content/local-file-mode.md +2 -2
- package/docs/content/mcp-apps.md +9 -2
- package/docs/content/mcp-clients.md +8 -3
- package/docs/content/mcp-protocol.md +11 -29
- package/docs/content/messaging.md +1 -1
- package/docs/content/migration-workbench.md +14 -175
- package/docs/content/multi-app-workspace.md +1 -1
- package/docs/content/multi-tenancy.md +18 -47
- package/docs/content/native-chat-ui.md +15 -12
- package/docs/content/observability.md +16 -4
- package/docs/content/observational-memory.md +1 -1
- package/docs/content/pure-agent-apps.md +17 -124
- package/docs/content/real-time-collaboration.md +14 -14
- package/docs/content/routing.md +71 -0
- package/docs/content/sandbox-adapters.md +78 -4
- package/docs/content/security.md +59 -39
- package/docs/content/server.md +16 -8
- package/docs/content/sharing.md +1 -6
- package/docs/content/skills-guide.md +3 -1
- package/docs/content/template-analytics.md +1 -1
- package/docs/content/template-assets.md +12 -3
- package/docs/content/template-brain.md +64 -72
- package/docs/content/template-chat.md +32 -4
- package/docs/content/template-clips.md +35 -4
- package/docs/content/template-design.md +19 -3
- package/docs/content/template-dispatch.md +9 -0
- package/docs/content/template-forms.md +15 -10
- package/docs/content/template-plan.md +7 -0
- package/docs/content/template-slides.md +14 -14
- package/docs/content/template-videos.md +10 -12
- package/docs/content/tracking.md +66 -55
- package/docs/content/using-your-agent.md +6 -16
- package/docs/content/what-is-agent-native.md +5 -11
- package/docs/content/workspace-management.md +2 -2
- package/docs/content/workspace.md +20 -160
- package/package.json +1 -1
- package/src/templates/workspace-root/README.md +4 -4
|
@@ -7,7 +7,7 @@ description: "Event-triggered and scheduled automations with natural-language co
|
|
|
7
7
|
|
|
8
8
|
An **automation** is a rule: _when X happens, do Y_ — described in natural language. The agent executes the instructions, so automations have access to every action, tool, and MCP server the agent can use in an interactive chat.
|
|
9
9
|
|
|
10
|
-
Automations extend [recurring jobs](/docs/recurring-jobs) with **event triggers**, **natural-language conditions**, and **outbound HTTP** via the `web-request` tool. They
|
|
10
|
+
Automations extend [recurring jobs](/docs/recurring-jobs) with **event triggers**, **natural-language conditions**, and **outbound HTTP** via the `web-request` tool. They use the same `jobs/<name>.md` file format, storage, and "create three ways" workflow as recurring jobs — see [Recurring Jobs](/docs/recurring-jobs#job-file) for the shared format. This page covers only what's new for event-driven automations.
|
|
11
11
|
|
|
12
12
|
## Two trigger types {#trigger-types}
|
|
13
13
|
|
|
@@ -30,17 +30,10 @@ The agent discovers available events, confirms the plan, and writes the automati
|
|
|
30
30
|
|
|
31
31
|
Automations appear in the settings panel. Users can view, enable/disable, and delete them there.
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
The third path — writing the `jobs/<name>.md` file by hand via `resourcePut` — works exactly as it does for [recurring jobs](/docs/recurring-jobs#creating). For an event-driven automation you add the event-trigger frontmatter below to that same file. An event-triggered job sets `schedule: ""` and supplies `triggerType: event`, an `event` name, and an optional `condition`:
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
```ts
|
|
38
|
-
import { resourcePut } from "@agent-native/core/resources";
|
|
39
|
-
|
|
40
|
-
await resourcePut(
|
|
41
|
-
ownerEmail,
|
|
42
|
-
"jobs/slack-on-builder-booking.md",
|
|
43
|
-
`---
|
|
35
|
+
```yaml
|
|
36
|
+
---
|
|
44
37
|
schedule: ""
|
|
45
38
|
enabled: true
|
|
46
39
|
triggerType: event
|
|
@@ -48,36 +41,25 @@ event: calendar.booking.created
|
|
|
48
41
|
condition: "attendee email ends with @builder.io"
|
|
49
42
|
mode: agentic
|
|
50
43
|
domain: calendar
|
|
51
|
-
createdBy: steve@builder.io
|
|
52
44
|
runAs: creator
|
|
53
45
|
---
|
|
54
|
-
|
|
55
46
|
Send a Slack message to #sales with the booking details.
|
|
56
|
-
Use the web-request tool to POST to
|
|
57
|
-
);
|
|
47
|
+
Use the web-request tool to POST to ${keys.SLACK_WEBHOOK}.
|
|
58
48
|
```
|
|
59
49
|
|
|
60
|
-
##
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
| `mode` | `"agentic"` \| `"deterministic"` | `"agentic"` | Full agent loop. (`"deterministic"` is reserved but not yet implemented — automations that set it are skipped. Use `"agentic"` for all current automations.) |
|
|
74
|
-
| `domain` | string | _(optional)_ | Grouping tag (mail, calendar, clips, etc.) |
|
|
75
|
-
| `createdBy` | email | _(auto)_ | Owner email |
|
|
76
|
-
| `orgId` | string | _(auto)_ | Org scope; inherited from the creator's active org |
|
|
77
|
-
| `runAs` | `"creator"` \| `"shared"` | `"creator"` | Whose API key and permissions to use |
|
|
78
|
-
| `lastRun` | ISO timestamp | _(managed)_ | Written by the dispatcher after each run |
|
|
79
|
-
| `lastStatus` | `"success"` \| `"error"` \| `"running"` \| `"skipped"` | _(managed)_ | Latest outcome |
|
|
80
|
-
| `lastError` | string | _(managed)_ | Error message if the last run failed |
|
|
50
|
+
## Automation frontmatter {#frontmatter}
|
|
51
|
+
|
|
52
|
+
Automations share every field in the [recurring-jobs frontmatter table](/docs/recurring-jobs#frontmatter). These additional fields control event triggers, conditions, and the execution mode:
|
|
53
|
+
|
|
54
|
+
| Field | Type | Default | Description |
|
|
55
|
+
| ------------- | -------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
56
|
+
| `triggerType` | `"schedule"` \| `"event"` | `"schedule"` | How the automation fires |
|
|
57
|
+
| `event` | string | _(optional)_ | Event name to subscribe to (event triggers only) |
|
|
58
|
+
| `condition` | string | _(optional)_ | Natural-language condition evaluated before dispatch |
|
|
59
|
+
| `mode` | `"agentic"` \| `"deterministic"` | `"agentic"` | Full agent loop. (`"deterministic"` is reserved but not yet implemented — automations that set it are skipped. Use `"agentic"` for all current automations.) |
|
|
60
|
+
| `domain` | string | _(optional)_ | Grouping tag (mail, calendar, clips, etc.) |
|
|
61
|
+
|
|
62
|
+
For an event trigger, `schedule` is `""` (empty); for a schedule trigger it carries the cron expression. The dispatcher also writes the same managed `lastRun` / `lastStatus` / `lastError` fields the scheduler does, plus a `"skipped"` status when a condition evaluates to false.
|
|
81
63
|
|
|
82
64
|
## The event bus {#event-bus}
|
|
83
65
|
|
|
@@ -5,6 +5,9 @@ description: "agent-native add prints a curated Markdown integration recipe to s
|
|
|
5
5
|
|
|
6
6
|
# Blueprint Installer
|
|
7
7
|
|
|
8
|
+
> **Who is this for:** host authors and integrators adding a provider, channel,
|
|
9
|
+
> sandbox backend, or action to a repo by piping a recipe into their coding agent.
|
|
10
|
+
|
|
8
11
|
`agent-native add` is **not** a dumb scaffolder that writes files for you. It emits a curated Markdown _integration blueprint_ to stdout. You pipe that blueprint into your own coding agent (Claude Code, Codex, …), which applies the changes against the live repo with full context.
|
|
9
12
|
|
|
10
13
|
This fits the agent-applies-changes, filesystem-first house style: the framework supplies the recipe (the canonical files to touch, the rules to honor, the verification step), and the coding agent does the editing.
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "CLI Adapters"
|
|
3
|
-
description: "
|
|
3
|
+
description: "Give the agent structured access to any CLI tool (gh, ffmpeg, stripe) through a standard adapter interface — one of the two adapter seams covered in the Adapters guide."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# CLI Adapters
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
> **Where this fits:** CLI adapters are one of two adapter seams in the
|
|
9
|
+
> framework. The canonical guide is [Adapters](/docs/sandbox-adapters), which
|
|
10
|
+
> covers both this seam and the `run-code` sandbox seam — including the shared
|
|
11
|
+
> edge/serverless constraint. This page is the quick reference for the CLI side.
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Agents are great at running CLI commands. But without structure, every script reinvents how to invoke a CLI, check if it's installed, and parse its output.
|
|
13
|
-
|
|
14
|
-
CLI adapters solve this with a small interface — similar to file sync adapters but for command-line tools. Each adapter wraps a single CLI (`gh`, `ffmpeg`, `stripe`, `aws`) and provides:
|
|
15
|
-
|
|
16
|
-
- **Discovery** — the agent can list what CLIs are available and what they do
|
|
17
|
-
- **Availability checks** — is the CLI installed?
|
|
18
|
-
- **Consistent execution** — stdout, stderr, and exit code in a standard format
|
|
13
|
+
A CLI adapter wraps a single command-line tool (`gh`, `ffmpeg`, `stripe`, `aws`) so the agent can discover it, check whether it's installed, and run it with a consistent stdout/stderr/exit-code result. Without this seam, every script reinvents how to invoke a CLI and parse its output.
|
|
19
14
|
|
|
20
15
|
## The interface {#the-interface}
|
|
21
16
|
|
|
@@ -40,7 +35,7 @@ interface CliResult {
|
|
|
40
35
|
|
|
41
36
|
## ShellCliAdapter {#shell-adapter}
|
|
42
37
|
|
|
43
|
-
For most CLIs
|
|
38
|
+
For most CLIs you don't need a custom class — `ShellCliAdapter` wraps any binary with sensible defaults:
|
|
44
39
|
|
|
45
40
|
```ts
|
|
46
41
|
import { ShellCliAdapter } from "@agent-native/core/adapters/cli";
|
|
@@ -54,177 +49,37 @@ const ffmpeg = new ShellCliAdapter({
|
|
|
54
49
|
command: "ffmpeg",
|
|
55
50
|
description: "Audio/video processing and transcoding",
|
|
56
51
|
timeoutMs: 120_000, // 2 min for long encodes
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const stripe = new ShellCliAdapter({
|
|
60
|
-
command: "stripe",
|
|
61
|
-
description: "Stripe CLI — manage payments, webhooks, and customers",
|
|
62
52
|
env: { STRIPE_API_KEY: process.env.STRIPE_SECRET_KEY! },
|
|
63
53
|
});
|
|
64
54
|
```
|
|
65
55
|
|
|
66
|
-
|
|
56
|
+
Options: `command` (required), `description` (required), `name` (defaults to `command`), `env` (merged with `process.env`), `cwd` (defaults to `process.cwd()`), and `timeoutMs` (default `30000`).
|
|
67
57
|
|
|
68
|
-
|
|
69
|
-
| ------------- | ------ | --------------------------------------------------- |
|
|
70
|
-
| `command` | string | Binary name or path (required) |
|
|
71
|
-
| `description` | string | What the CLI does — shown to the agent (required) |
|
|
72
|
-
| `name` | string | Display name (defaults to `command`) |
|
|
73
|
-
| `env` | Record | Extra environment variables merged with process.env |
|
|
74
|
-
| `cwd` | string | Working directory (defaults to process.cwd()) |
|
|
75
|
-
| `timeoutMs` | number | Execution timeout (default: 30000) |
|
|
58
|
+
For custom auth, output parsing, or pre/post processing, implement `CliAdapter` directly instead of using `ShellCliAdapter`.
|
|
76
59
|
|
|
77
60
|
## Registry {#registry}
|
|
78
61
|
|
|
79
|
-
|
|
62
|
+
`CliRegistry` collects adapters so the agent can discover what's available at runtime:
|
|
80
63
|
|
|
81
64
|
```ts
|
|
82
65
|
import { CliRegistry, ShellCliAdapter } from "@agent-native/core/adapters/cli";
|
|
83
66
|
|
|
84
67
|
const cliRegistry = new CliRegistry();
|
|
85
|
-
|
|
86
68
|
cliRegistry.register(
|
|
87
|
-
new ShellCliAdapter({
|
|
88
|
-
command: "gh",
|
|
89
|
-
description: "GitHub CLI — manage repos, PRs, issues, and releases",
|
|
90
|
-
}),
|
|
69
|
+
new ShellCliAdapter({ command: "gh", description: "GitHub CLI" }),
|
|
91
70
|
);
|
|
92
71
|
|
|
93
|
-
cliRegistry.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
description: "Audio/video processing and transcoding",
|
|
97
|
-
}),
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
// List all registered CLIs
|
|
101
|
-
cliRegistry.list();
|
|
102
|
-
// → [{ name: "gh", ... }, { name: "ffmpeg", ... }]
|
|
103
|
-
|
|
104
|
-
// List only installed CLIs
|
|
105
|
-
await cliRegistry.listAvailable();
|
|
106
|
-
// → [{ name: "gh", ... }] (if ffmpeg isn't installed)
|
|
72
|
+
cliRegistry.list(); // all registered
|
|
73
|
+
await cliRegistry.listAvailable(); // only installed
|
|
74
|
+
await cliRegistry.describe(); // [{ name, description, available }] for discovery
|
|
107
75
|
|
|
108
|
-
// Get a full summary for agent discovery
|
|
109
|
-
await cliRegistry.describe();
|
|
110
|
-
// → [{ name: "gh", description: "...", available: true },
|
|
111
|
-
// { name: "ffmpeg", description: "...", available: false }]
|
|
112
|
-
|
|
113
|
-
// Execute a command
|
|
114
76
|
const gh = cliRegistry.get("gh");
|
|
115
77
|
const result = await gh?.execute(["pr", "list", "--json", "title,url"]);
|
|
116
|
-
console.log(result?.stdout);
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
## Custom adapters {#custom-adapter}
|
|
120
|
-
|
|
121
|
-
When you need more than `ShellCliAdapter` provides — custom auth, output parsing, or pre/post processing — implement `CliAdapter` directly:
|
|
122
|
-
|
|
123
|
-
```ts
|
|
124
|
-
import type { CliAdapter, CliResult } from "@agent-native/core/adapters/cli";
|
|
125
|
-
import { execFile } from "node:child_process";
|
|
126
|
-
|
|
127
|
-
export class DockerAdapter implements CliAdapter {
|
|
128
|
-
name = "docker";
|
|
129
|
-
description =
|
|
130
|
-
"Docker container management — build, run, and manage containers";
|
|
131
|
-
|
|
132
|
-
async isAvailable(): Promise<boolean> {
|
|
133
|
-
try {
|
|
134
|
-
const result = await this.execute([
|
|
135
|
-
"info",
|
|
136
|
-
"--format",
|
|
137
|
-
"{{.ServerVersion}}",
|
|
138
|
-
]);
|
|
139
|
-
return result.exitCode === 0;
|
|
140
|
-
} catch {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
async execute(args: string[]): Promise<CliResult> {
|
|
146
|
-
return new Promise((resolve) => {
|
|
147
|
-
execFile(
|
|
148
|
-
"docker",
|
|
149
|
-
args,
|
|
150
|
-
{
|
|
151
|
-
timeout: 60_000,
|
|
152
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
153
|
-
encoding: "utf-8",
|
|
154
|
-
},
|
|
155
|
-
(error, stdout, stderr) => {
|
|
156
|
-
resolve({
|
|
157
|
-
stdout: stdout ?? "",
|
|
158
|
-
stderr: stderr ?? "",
|
|
159
|
-
exitCode: (error as any)?.code ?? 0,
|
|
160
|
-
});
|
|
161
|
-
},
|
|
162
|
-
);
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
> [!WARNING]
|
|
169
|
-
> **Edge and Serverless Compatibility:**
|
|
170
|
-
> CLI adapters (both `ShellCliAdapter` and custom adapters using `node:child_process`) rely on Node.js-specific system bindings (`child_process.execFile` or `child_process.spawn`).
|
|
171
|
-
> These APIs **do not exist** on edge/worker runtimes (e.g., Cloudflare Workers, Netlify Edge Functions). If you deploy your server routes to these edge presets, executing CLI adapters will throw runtime exceptions. Always ensure CLI adapter endpoints and tasks run in standard Node.js environments (like traditional server containers or serverless Node functions).
|
|
172
|
-
|
|
173
|
-
## Server route {#server-route}
|
|
174
|
-
|
|
175
|
-
Expose the registry to the UI via an API route so actions and components can discover and invoke CLIs:
|
|
176
|
-
|
|
177
|
-
`createServer()` returns an H3 `{ app, router }`. Mount routes on `router` with H3 handlers (`defineEventHandler`, `readBody`, `getRouterParam`):
|
|
178
|
-
|
|
179
|
-
```ts
|
|
180
|
-
// server/index.ts
|
|
181
|
-
import { createServer } from "@agent-native/core";
|
|
182
|
-
import { CliRegistry, ShellCliAdapter } from "@agent-native/core/adapters/cli";
|
|
183
|
-
import {
|
|
184
|
-
defineEventHandler,
|
|
185
|
-
readBody,
|
|
186
|
-
getRouterParam,
|
|
187
|
-
setResponseStatus,
|
|
188
|
-
} from "h3";
|
|
189
|
-
|
|
190
|
-
const { router } = createServer();
|
|
191
|
-
const cliRegistry = new CliRegistry();
|
|
192
|
-
|
|
193
|
-
cliRegistry.register(
|
|
194
|
-
new ShellCliAdapter({
|
|
195
|
-
command: "gh",
|
|
196
|
-
description: "GitHub CLI",
|
|
197
|
-
}),
|
|
198
|
-
);
|
|
199
|
-
|
|
200
|
-
// Discovery endpoint — agent can query this
|
|
201
|
-
router.get(
|
|
202
|
-
"/api/cli",
|
|
203
|
-
defineEventHandler(async () => {
|
|
204
|
-
return await cliRegistry.describe();
|
|
205
|
-
}),
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
// Execution endpoint
|
|
209
|
-
router.post(
|
|
210
|
-
"/api/cli/:name",
|
|
211
|
-
defineEventHandler(async (event) => {
|
|
212
|
-
const name = getRouterParam(event, "name");
|
|
213
|
-
const adapter = name ? cliRegistry.get(name) : undefined;
|
|
214
|
-
if (!adapter) {
|
|
215
|
-
setResponseStatus(event, 404);
|
|
216
|
-
return { error: "CLI not found" };
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const { args } = await readBody(event);
|
|
220
|
-
return await adapter.execute(args ?? []);
|
|
221
|
-
}),
|
|
222
|
-
);
|
|
223
78
|
```
|
|
224
79
|
|
|
225
80
|
## Using from actions {#from-actions}
|
|
226
81
|
|
|
227
|
-
|
|
82
|
+
Wrap a CLI call in `defineAction` to expose it on the action surface — `defineAction` is required when the code runs inside the server action surface; use an adapter directly in a `scripts/` file otherwise. Never call `process.exit` in an action; throw an error instead.
|
|
228
83
|
|
|
229
84
|
```ts
|
|
230
85
|
// actions/list-prs.ts
|
|
@@ -232,10 +87,7 @@ import { defineAction } from "@agent-native/core/action";
|
|
|
232
87
|
import { ShellCliAdapter } from "@agent-native/core/adapters/cli";
|
|
233
88
|
import { z } from "zod";
|
|
234
89
|
|
|
235
|
-
const gh = new ShellCliAdapter({
|
|
236
|
-
command: "gh",
|
|
237
|
-
description: "GitHub CLI",
|
|
238
|
-
});
|
|
90
|
+
const gh = new ShellCliAdapter({ command: "gh", description: "GitHub CLI" });
|
|
239
91
|
|
|
240
92
|
export default defineAction({
|
|
241
93
|
description: "List open pull requests via the GitHub CLI.",
|
|
@@ -244,7 +96,6 @@ export default defineAction({
|
|
|
244
96
|
if (!(await gh.isAvailable())) {
|
|
245
97
|
throw new Error("GitHub CLI not installed. Run: brew install gh");
|
|
246
98
|
}
|
|
247
|
-
|
|
248
99
|
const result = await gh.execute([
|
|
249
100
|
"pr",
|
|
250
101
|
"list",
|
|
@@ -253,14 +104,19 @@ export default defineAction({
|
|
|
253
104
|
"--limit",
|
|
254
105
|
"10",
|
|
255
106
|
]);
|
|
256
|
-
|
|
257
107
|
if (result.exitCode !== 0) {
|
|
258
108
|
throw new Error(result.stderr || "gh pr list failed");
|
|
259
109
|
}
|
|
260
|
-
|
|
261
110
|
return JSON.parse(result.stdout);
|
|
262
111
|
},
|
|
263
112
|
});
|
|
264
113
|
```
|
|
265
114
|
|
|
266
|
-
|
|
115
|
+
## Edge and serverless {#edge-serverless}
|
|
116
|
+
|
|
117
|
+
CLI adapters use `node:child_process`, which does not exist on edge/worker runtimes (Cloudflare Workers, Netlify Edge Functions). Run CLI adapter endpoints and tasks in a standard Node.js environment. This constraint is shared with the sandbox seam — see the full discussion in [Adapters](/docs/sandbox-adapters#edge-serverless).
|
|
118
|
+
|
|
119
|
+
## What's next
|
|
120
|
+
|
|
121
|
+
- [**Adapters**](/docs/sandbox-adapters) — the canonical guide to both adapter seams.
|
|
122
|
+
- [**Actions**](/docs/actions) — the action surface CLI adapters are usually wrapped in.
|
package/docs/content/client.md
CHANGED
|
@@ -9,21 +9,7 @@ description: "React hooks and utilities for agent-native apps: sendToAgentChat,
|
|
|
9
9
|
|
|
10
10
|
These client/React APIs are exported from both `@agent-native/core` and `@agent-native/core/client`. Import them from `@agent-native/core/client` (the browser entry) for clarity and correct bundling, since the bare `@agent-native/core` root resolves to the Node build by default.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Agent-native apps use **React Router v7** with file-based routing via `flatRoutes()` from `@react-router/fs-routes`. Every file in `app/routes/` becomes a URL. Templates use the dot-notation convention — dots separate URL segments inside a single filename.
|
|
15
|
-
|
|
16
|
-
### File → URL mapping
|
|
17
|
-
|
|
18
|
-
| File | URL | Notes |
|
|
19
|
-
| --------------------- | ------------------ | -------------------------------------- |
|
|
20
|
-
| `_index.tsx` | `/` | Index route |
|
|
21
|
-
| `settings.tsx` | `/settings` | Simple page |
|
|
22
|
-
| `inbox.$threadId.tsx` | `/inbox/:threadId` | Dot = `/`, `$` = dynamic param |
|
|
23
|
-
| `_app.tsx` | (no URL segment) | Pathless layout — prefix with `_` |
|
|
24
|
-
| `inbox/route.tsx` | `/inbox` | Folder form — `route.tsx` is the index |
|
|
25
|
-
|
|
26
|
-
Prefix a segment with `$` for a dynamic param. Prefix with `_` to make it a pathless layout route (no URL segment). Templates use `flatRoutes()` — the dot-notation file above is primary; the nested-folder form `inbox/route.tsx` also works.
|
|
12
|
+
For file-based routing — adding pages, dynamic params, and navigation — see [Routing](/docs/routing).
|
|
27
13
|
|
|
28
14
|
## Fetching and Mutating Data {#fetching-mutating}
|
|
29
15
|
|
|
@@ -47,70 +33,9 @@ mutate({ name: "Alice", company: "Acme" });
|
|
|
47
33
|
await callAction("archive-lead", { leadId });
|
|
48
34
|
```
|
|
49
35
|
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
### Adding a new page
|
|
53
|
-
|
|
54
|
-
Create the file and export a default component:
|
|
55
|
-
|
|
56
|
-
```tsx
|
|
57
|
-
// app/routes/settings.tsx
|
|
58
|
-
export function meta() {
|
|
59
|
-
return [{ title: "Settings" }];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export default function SettingsPage() {
|
|
63
|
-
return <div>Settings</div>;
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
That's it — React Router picks it up automatically, no registration needed.
|
|
68
|
-
|
|
69
|
-
### Dynamic params
|
|
70
|
-
|
|
71
|
-
```tsx
|
|
72
|
-
// app/routes/inbox/$threadId.tsx
|
|
73
|
-
import { useParams } from "react-router";
|
|
74
|
-
|
|
75
|
-
export default function ThreadPage() {
|
|
76
|
-
const { threadId } = useParams();
|
|
77
|
-
return <div>Thread: {threadId}</div>;
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Navigation
|
|
82
|
-
|
|
83
|
-
Use `<Link>` for client-side navigation and `useNavigate()` for programmatic navigation:
|
|
84
|
-
|
|
85
|
-
```tsx
|
|
86
|
-
import { Link, useNavigate } from "react-router";
|
|
87
|
-
|
|
88
|
-
// In JSX
|
|
89
|
-
<Link to="/settings">Settings</Link>;
|
|
90
|
-
|
|
91
|
-
// Programmatic
|
|
92
|
-
const navigate = useNavigate();
|
|
93
|
-
navigate(`/inbox/${threadId}`);
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
36
|
## sendToAgentChat(opts) {#sendtoagentchat}
|
|
99
37
|
|
|
100
|
-
Send a message to the agent chat via postMessage
|
|
101
|
-
|
|
102
|
-
When the app route is running inside an MCP App embed created with `embedApp()`,
|
|
103
|
-
auto-submitted messages (`submit` omitted or `true`) are forwarded to the MCP
|
|
104
|
-
App host bridge, which asks the containing host to add hidden context and send
|
|
105
|
-
the visible user turn. `context` is sent as model context before the visible
|
|
106
|
-
message, so it stays model-visible without being posted as user-facing chat or
|
|
107
|
-
concatenated into the host's visible prompt.
|
|
108
|
-
`submit: false` keeps the local prefill/review behavior because MCP Apps do not
|
|
109
|
-
define a standard draft-prefill API.
|
|
110
|
-
|
|
111
|
-
Internally this is the submitted-chat path sometimes surfaced as
|
|
112
|
-
`agentNative.submitChat`; app code should call `sendToAgentChat()` rather than
|
|
113
|
-
posting that event directly.
|
|
38
|
+
Send a message to the agent chat via postMessage — the common way to delegate an AI task from a UI interaction. Pass `context` for hidden model context and `submit: true` to send immediately, or `submit: false` to prefill a draft the user reviews first.
|
|
114
39
|
|
|
115
40
|
```ts
|
|
116
41
|
import { sendToAgentChat } from "@agent-native/core/client";
|
|
@@ -130,6 +55,15 @@ sendToAgentChat({
|
|
|
130
55
|
});
|
|
131
56
|
```
|
|
132
57
|
|
|
58
|
+
Inside an MCP App embed created with `embedApp()`, auto-submitted messages
|
|
59
|
+
(`submit` omitted or `true`) are forwarded to the MCP App host bridge, which
|
|
60
|
+
asks the containing host to add hidden context and send the visible user turn.
|
|
61
|
+
`context` stays model-visible without being posted as user-facing chat.
|
|
62
|
+
`submit: false` keeps the local prefill/review behavior because MCP Apps do not
|
|
63
|
+
define a standard draft-prefill API. Internally this is the submitted-chat path
|
|
64
|
+
sometimes surfaced as `agentNative.submitChat`; app code should call
|
|
65
|
+
`sendToAgentChat()` rather than posting that event directly.
|
|
66
|
+
|
|
133
67
|
### Silent background sends {#background-send}
|
|
134
68
|
|
|
135
69
|
Use `background: true` when a UI action should kick off real agent work without
|
|
@@ -77,7 +77,7 @@ Not ready to scaffold? You can add agent-native superpowers to a coding agent yo
|
|
|
77
77
|
|
|
78
78
|
## Building on this
|
|
79
79
|
|
|
80
|
-
- [**Getting Started**](/docs/getting-started) — create a minimal chat app or headless
|
|
80
|
+
- [**Getting Started**](/docs/getting-started) — create a minimal chat app or headless agent
|
|
81
81
|
- [**Messaging the agent**](/docs/messaging) — how users (and you) talk to the agent that ships with each template
|
|
82
82
|
- [**Multi-App Workspace**](/docs/multi-app-workspace) — bundle several templates into one workspace that shares auth, brand, and agent
|
|
83
83
|
- [**Dispatch**](/docs/template-dispatch) — the workspace control plane template
|
|
@@ -5,6 +5,18 @@ description: "Build and customize Agent-Native Code surfaces with the shared UI
|
|
|
5
5
|
|
|
6
6
|
# Agent-Native Code UI
|
|
7
7
|
|
|
8
|
+
> **Who is this for:** host authors building or customizing a coding-workspace
|
|
9
|
+
> surface (CLI, Desktop, or a browser template) on the shared Code UI package.
|
|
10
|
+
|
|
11
|
+
## Which coding doc do I want? {#which-doc}
|
|
12
|
+
|
|
13
|
+
| You want to… | Use |
|
|
14
|
+
| -------------------------------------------------------------------------- | -------------------------------------- |
|
|
15
|
+
| Render a Claude-Code/Codex-style **coding workspace UI** | **Agent-Native Code UI** (this page) |
|
|
16
|
+
| Run Claude Code / Codex / Pi **as the agent**, with their own loop + tools | [Harness Agents](/docs/harness-agents) |
|
|
17
|
+
| Swap the backend that runs the agent's **`run-code` tool** | [Adapters](/docs/sandbox-adapters) |
|
|
18
|
+
| Wrap a CLI tool (`gh`, `ffmpeg`) for the agent to call | [Adapters](/docs/sandbox-adapters) |
|
|
19
|
+
|
|
8
20
|
Agent-Native Code is the Agent-Native coding surface: a local Claude Code/Codex-style workspace for coding sessions, slash commands, migrations, audits, transcripts, run controls, and follow-ups. A bare `npx @agent-native/core@latest` command opens this workspace; `npx @agent-native/core@latest code` is the explicit subcommand for the same experience.
|
|
9
21
|
|
|
10
22
|
There are three layers:
|
|
@@ -62,6 +74,24 @@ Desktop uses the shared UI but keeps privileged capabilities in Electron:
|
|
|
62
74
|
|
|
63
75
|
That separation matters. The UI can be reused by templates, but native process control should stay in Desktop or CLI.
|
|
64
76
|
|
|
77
|
+
## Codex CLI Auth {#codex-cli-auth}
|
|
78
|
+
|
|
79
|
+
Agent-Native Code can use a local Codex CLI login instead of an OpenAI API key.
|
|
80
|
+
Install the Codex CLI on your `PATH`, sign in once, then restart Desktop or the
|
|
81
|
+
Code UI if it was already open:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install -g @openai/codex@latest
|
|
85
|
+
codex login
|
|
86
|
+
codex login status
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Desktop and the CLI read `codex login status` and run `codex exec`, so they
|
|
90
|
+
reuse whatever ChatGPT subscription or API-key auth your installed Codex CLI
|
|
91
|
+
reports. This is separate from the `@ai-sdk/harness-codex` package used by
|
|
92
|
+
[Harness Agents](/docs/harness-agents); the harness adapter does not add a
|
|
93
|
+
separate Agent-Native OAuth flow.
|
|
94
|
+
|
|
65
95
|
## Browser Host
|
|
66
96
|
|
|
67
97
|
The old hidden `code` template has been removed. To build a browser-hosted Code surface, create a normal app and mount the shared UI package with a host implementation:
|
|
@@ -252,6 +282,19 @@ available when needed.
|
|
|
252
282
|
|
|
253
283
|
Agent-Native Code treats migration as a capability, not a separate app category. `/migrate` can be a built-in goal, a project command, or a custom instruction pack on top of the same host contract.
|
|
254
284
|
|
|
285
|
+
### Migrating to Agent-Native with `/migrate` {#migrate}
|
|
286
|
+
|
|
287
|
+
`/migrate` is the built-in goal for moving an existing app, URL, or described product into Agent-Native. It is a slash goal in the Code workspace — not a separate template to scaffold and not a one-off product — so it shares the same session store, transcript, run controls, and Desktop hub as every other Code session, and you can resume, attach to, inspect, and stop it the same way.
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
npx @agent-native/core@latest code /migrate ./my-next-app --out ../migrated-app
|
|
291
|
+
npx @agent-native/core@latest code /migrate https://example.com --describe "marketing site plus dashboard"
|
|
292
|
+
npx @agent-native/core@latest code /migrate --describe "A Rails admin app with reports and CSV imports" --emit
|
|
293
|
+
npx @agent-native/core@latest migrate ./my-next-app --out ../migrated-app # shortcut into the same goal
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Local source paths are read-only; generated output must live outside the source tree. Use `--emit <dir>` to write a portable migration dossier (`AGENTS.md`, `MIGRATION_PLAYBOOK.md`, assessment, and an `ir.json` inventory when available) and hand it to another coding agent instead of opening the internal run surface. `/migrate` reuses the framework's normal credentials system — there is no migration-specific key store. The `@agent-native/migrate` package exposes a reusable engine (`createMigrationRun`, `discoverMigration`, `planMigration`, source/target adapters) for custom workflows.
|
|
297
|
+
|
|
255
298
|
Project-specific commands live in:
|
|
256
299
|
|
|
257
300
|
```text
|
|
@@ -49,9 +49,11 @@ so bundlers choose the browser-safe entry.
|
|
|
49
49
|
`AgentChatRuntime` is the BYO-agent contract for the standard chat shell. Pass
|
|
50
50
|
`runtime` to `<AssistantChat>` when an external agent should power the
|
|
51
51
|
conversation while Agent-Native keeps the composer, transcript, tool cards, and
|
|
52
|
-
native widget rendering.
|
|
53
|
-
|
|
54
|
-
[
|
|
52
|
+
native widget rendering. The connectors above are the API surface; the runtime
|
|
53
|
+
contract and event shapes are taught in
|
|
54
|
+
[Native Chat UI — BYO agent runtimes](/docs/native-chat-ui#byo-agent-runtimes).
|
|
55
|
+
If you are choosing between headless agents, rich chat, embedded sidecar, and
|
|
56
|
+
full app shapes, see [Agent Surfaces](/docs/agent-surfaces).
|
|
55
57
|
|
|
56
58
|
The shortest custom route is still a pre-wired surface:
|
|
57
59
|
|
|
@@ -85,26 +87,11 @@ function CustomChat({ projectSlug }: { projectSlug: string }) {
|
|
|
85
87
|
}
|
|
86
88
|
```
|
|
87
89
|
|
|
88
|
-
For a bring-your-own agent endpoint
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
createOpenAIAgentsChatRuntime,
|
|
94
|
-
} from "@agent-native/core/client/chat";
|
|
95
|
-
|
|
96
|
-
const runtime = createOpenAIAgentsChatRuntime({
|
|
97
|
-
endpoint: "/api/my-agent/chat",
|
|
98
|
-
label: "My agent",
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
export function MyAgentChat() {
|
|
102
|
-
return <AssistantChat runtime={runtime} />;
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Use `createHttpAgentChatRuntime()` instead when your endpoint already emits
|
|
107
|
-
Agent-Native normalized events.
|
|
90
|
+
For a bring-your-own agent endpoint, build an `AgentChatRuntime` with one of the
|
|
91
|
+
connectors above and pass it to `<AssistantChat runtime={...} />`. See
|
|
92
|
+
[Native Chat UI — BYO agent runtimes](/docs/native-chat-ui#byo-agent-runtimes)
|
|
93
|
+
for the connector usage, the normalized event stream, and when to reach for
|
|
94
|
+
`createHttpAgentChatRuntime()` versus a protocol-specific connector.
|
|
108
95
|
|
|
109
96
|
## Chat Field And Composer {#composer}
|
|
110
97
|
|
|
@@ -13,7 +13,7 @@ How the agent knows what the user is looking at -- and how the agent can control
|
|
|
13
13
|
|
|
14
14
|
Without context awareness, the agent is blind. It asks "which email?" when the user is staring at one. It cannot act on the current selection, cannot provide relevant suggestions, and cannot modify what the user sees. With context awareness, the user can click a row, highlight a paragraph, select a slide element, or press Cmd+I, then say "summarize this" and the agent already knows what "this" means.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
To understand what to put in which surface (AGENTS.md vs. skills vs. application_state), see [Writing Agent Instructions — The four surfaces the agent sees](/docs/writing-agent-instructions#four-surfaces).
|
|
17
17
|
|
|
18
18
|
Six patterns solve this:
|
|
19
19
|
|
|
@@ -76,7 +76,7 @@ const navigation = await readAppState("navigation");
|
|
|
76
76
|
|
|
77
77
|
`AgentPanel` automatically syncs the current React Router URL into the `__url__` application-state key. The built-in agent includes it in every turn as a `<current-url>` block:
|
|
78
78
|
|
|
79
|
-
```
|
|
79
|
+
```text
|
|
80
80
|
<current-url>
|
|
81
81
|
pathname: /adhoc/revenue
|
|
82
82
|
search: ?f_region=west&q=renewal
|
|
@@ -88,7 +88,7 @@ searchParams:
|
|
|
88
88
|
|
|
89
89
|
This is the canonical layer for shareable filter state. If the user can copy a URL and come back to the same filtered list, the filter belongs in the query string. The agent can change those filters with the built-in `set-search-params` tool:
|
|
90
90
|
|
|
91
|
-
```
|
|
91
|
+
```text
|
|
92
92
|
set-search-params({ "params": { "f_region": "east", "q": null } })
|
|
93
93
|
```
|
|
94
94
|
|