@agent-native/dispatch 0.11.5 → 0.11.7
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 +57 -120
- package/dist/actions/create-vault-secret.d.ts.map +1 -1
- package/dist/actions/create-vault-secret.js +5 -0
- package/dist/actions/create-vault-secret.js.map +1 -1
- package/dist/actions/navigate.d.ts +2 -0
- package/dist/actions/navigate.d.ts.map +1 -1
- package/dist/actions/navigate.js +15 -4
- package/dist/actions/navigate.js.map +1 -1
- package/dist/actions/update-vault-secret.d.ts.map +1 -1
- package/dist/actions/update-vault-secret.js +3 -0
- package/dist/actions/update-vault-secret.js.map +1 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +26 -4
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/hooks/use-navigation-state.d.ts +1 -0
- package/dist/hooks/use-navigation-state.d.ts.map +1 -1
- package/dist/hooks/use-navigation-state.js +23 -3
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +1 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/pages/chat.d.ts.map +1 -1
- package/dist/routes/pages/chat.js +51 -3
- package/dist/routes/pages/chat.js.map +1 -1
- package/package.json +2 -2
- package/src/actions/create-vault-secret.ts +5 -0
- package/src/actions/navigate.ts +13 -4
- package/src/actions/update-vault-secret.ts +3 -0
- package/src/components/layout/Layout.tsx +31 -4
- package/src/hooks/use-navigation-state.ts +25 -4
- package/src/routes/index.ts +1 -0
- package/src/routes/pages/chat.tsx +59 -1
package/README.md
CHANGED
|
@@ -1,33 +1,8 @@
|
|
|
1
1
|
# Agent-Native
|
|
2
2
|
|
|
3
|
-
### Open-source framework for agentic applications you own.
|
|
4
|
-
|
|
5
|
-
Don't choose between rich user interfaces and autonomous agents. Every Agent-Native app is both.
|
|
6
|
-
|
|
7
|
-
## Agents and UIs — Fully Connected
|
|
8
|
-
|
|
9
|
-
The agent and the UI are equal citizens of the same system. Every action works both ways — click it or ask for it.
|
|
10
|
-
|
|
11
|
-

|
|
12
|
-
|
|
13
|
-
- **Everything syncs** — Agent and UI share one database and one state. Changes from either side show up instantly on the other.
|
|
14
|
-
- **Real-time multiplayer** — Humans and agents collaborate in the same document simultaneously: CRDT merging, live presence (cursors, selection rings, who's on which slide), and the agent as a first-class peer editor. Works on any SQL database and any host, including serverless.
|
|
15
|
-
- **Context-aware** — The agent knows what you're looking at. Select text, hit Cmd+I, and tell it what to do.
|
|
16
|
-
- **Per-user workspace** — Skills, memory, instructions, sub-agents, and MCP servers — SQL-backed, customizable per user. Claude-Code-level flexibility, SaaS-grade economics.
|
|
17
|
-
- **Agents call agents** — Tag another agent from any app. They discover each other over A2A and take action across your stack.
|
|
18
|
-
- **Reusable integrations** — Connect a provider once in Dispatch, keep secret values in the vault, then grant apps like Brain, Analytics, Mail, and Dispatch access to the shared account metadata and credential refs.
|
|
19
|
-
- **Three shapes** — Build the same agent as a headless API, a rich chat experience, or a full application where agent and UI stay in sync.
|
|
20
|
-
- **Apps that improve themselves** — Your apps get better on their own. The agent can add features, fix bugs, and refine the UI over time.
|
|
21
|
-
- **Any database, any host** — Any SQL database Drizzle supports. Any hosting target Nitro supports. No lock-in.
|
|
22
|
-
- **Bring the agent surface you need** — MCP-compatible hosts can call your apps, coding agents can install skills, native chat renders reusable app outputs, and BYO agent runtimes can stream into the Agent-Native chat shell.
|
|
23
|
-
|
|
24
3
|
## The framework for agent-native apps
|
|
25
4
|
|
|
26
|
-
Agent-Native is an open-source framework for building robust agents that
|
|
27
|
-
|
|
28
|
-
It gives you primitives for product-grade agentic software: shared actions, SQL-backed state, identity, tools, skills, jobs, observability, and UI surfaces that all work together.
|
|
29
|
-
|
|
30
|
-
Backend agnostic: bring your own database, hosting provider, model stack, and app code.
|
|
5
|
+
Agent-Native is an open-source framework for building robust agents that act inside real apps, not just chat next to them. It gives you primitives for product-grade agentic software: shared actions, SQL-backed state, identity, tools, skills, jobs, observability, and UI surfaces that all work together. Bring your own database, hosting provider, model stack, and app code.
|
|
31
6
|
|
|
32
7
|
```ts
|
|
33
8
|
// One action powers UI, agent, HTTP, MCP, A2A, and CLI.
|
|
@@ -42,58 +17,51 @@ export default defineAction({
|
|
|
42
17
|
});
|
|
43
18
|
```
|
|
44
19
|
|
|
45
|
-
- **Actions
|
|
46
|
-
- **Agent runtime
|
|
47
|
-
- **Backend agnostic
|
|
20
|
+
- **Actions**: Define work once. Use it from UI, agent, API, MCP, A2A, and CLI.
|
|
21
|
+
- **Agent runtime**: Chat, tools, skills, memory, jobs, observability, and handoffs ship together.
|
|
22
|
+
- **Backend agnostic**: Plug in any Drizzle-supported SQL database and Nitro-compatible host.
|
|
48
23
|
|
|
49
|
-
##
|
|
50
|
-
|
|
51
|
-
Agent-Native primitives let you choose how much UI to put around an agent without rebuilding the agent contract:
|
|
52
|
-
|
|
53
|
-
| Shape | What you ship | Same primitives underneath |
|
|
54
|
-
| ------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
55
|
-
| **Headless** | Call the agent and actions from code, CLI, HTTP, MCP, or A2A. | `defineAction`, auth, skills, memory, jobs, observability |
|
|
56
|
-
| **Rich chat** | A standalone or embedded chat with native tables, charts, approvals, setup flows, and tool results. | Shared chat runtime, BYO runtime adapters, action-declared native renderers |
|
|
57
|
-
| **Whole app** | A full SaaS/product UI where chat can start central, move to the sidebar, and stay synced with app state. | SQL state, actions, context awareness, deep links, live sync |
|
|
24
|
+
## Templates
|
|
58
25
|
|
|
59
|
-
|
|
26
|
+
Start with a full featured template. Each one is a complete, 100% free and open-source SaaS app: cloneable, not scaffolded, except you own the code and can customize everything.
|
|
60
27
|
|
|
61
|
-
|
|
28
|
+
<table>
|
|
29
|
+
<tr>
|
|
30
|
+
<td width="33%" align="center" valign="top">
|
|
62
31
|
|
|
63
|
-
|
|
32
|
+
**Clips**
|
|
64
33
|
|
|
65
|
-
|
|
34
|
+
<a href="https://agent-native.com/templates/clips"><img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F189ebd9b2f2b4f0ead3b33138d4e4c10?format=webp&width=800" alt="Clips template" width="100%" /></a>
|
|
66
35
|
|
|
67
|
-
|
|
36
|
+
**Agent-Native Loom + Jam**
|
|
68
37
|
|
|
69
|
-
|
|
70
|
-
npx @agent-native/core@latest skills add visual-plan
|
|
71
|
-
```
|
|
38
|
+
Record your screen with auto-transcripts and captured browser debug logs, share a link, and let an agent read the transcript, see timestamped frames, and fix the bug.
|
|
72
39
|
|
|
73
|
-
|
|
40
|
+
</td>
|
|
41
|
+
<td width="33%" align="center" valign="top">
|
|
74
42
|
|
|
75
|
-
|
|
76
|
-
- **`/visual-recap`** — after changes land, it turns a PR or git diff into a high-altitude visual recap: schema, API, and file changes rendered as grounded before/after blocks with a shareable review link, instead of scrolling a raw diff.
|
|
43
|
+
**Plans**
|
|
77
44
|
|
|
78
|
-
|
|
45
|
+
<a href="https://agent-native.com/templates/plan"><img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fb6f4213ac7cc42eeb10c12e8ccda8936?format=webp&width=800" alt="Plans template" width="100%" /></a>
|
|
79
46
|
|
|
80
|
-
|
|
47
|
+
**Visual plan mode for coding agents**
|
|
81
48
|
|
|
82
|
-
|
|
49
|
+
Install `/visual-plan` and `/visual-recap` so your coding agent can plan before it builds and recap changes after they land. High-level code reviews with diagrams, wireframes, annotations, and review links.
|
|
83
50
|
|
|
84
|
-
|
|
85
|
-
<tr>
|
|
51
|
+
</td>
|
|
86
52
|
<td width="33%" align="center" valign="top">
|
|
87
53
|
|
|
88
|
-
**
|
|
54
|
+
**Design**
|
|
89
55
|
|
|
90
|
-
<a href="https://agent-native.com/templates/
|
|
56
|
+
<a href="https://agent-native.com/templates/design"><img src="https://cdn.builder.io/api/v1/image/assets%2F348da13fcd8b414c87de9066196f7266%2F961bedb713a94463b834c1f2f4643bcf?format=webp&width=800" alt="Design template" width="100%" /></a>
|
|
91
57
|
|
|
92
|
-
**Agent-Native
|
|
58
|
+
**Agent-Native design prototyping**
|
|
93
59
|
|
|
94
|
-
|
|
60
|
+
Generate interactive HTML prototypes, compare variants, refine controls, and export the result.
|
|
95
61
|
|
|
96
62
|
</td>
|
|
63
|
+
</tr>
|
|
64
|
+
<tr>
|
|
97
65
|
<td width="33%" align="center" valign="top">
|
|
98
66
|
|
|
99
67
|
**Content**
|
|
@@ -107,19 +75,6 @@ Edit local Markdown/MDX files, generate rich interactive custom blocks, and draf
|
|
|
107
75
|
</td>
|
|
108
76
|
<td width="33%" align="center" valign="top">
|
|
109
77
|
|
|
110
|
-
**Plans**
|
|
111
|
-
|
|
112
|
-
<a href="https://agent-native.com/templates/plan"><img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fb6f4213ac7cc42eeb10c12e8ccda8936?format=webp&width=800" alt="Plans template" width="100%" /></a>
|
|
113
|
-
|
|
114
|
-
**Visual plan mode for coding agents**
|
|
115
|
-
|
|
116
|
-
Install `/visual-plan` and `/visual-recap` so your coding agent can plan before it builds and recap changes after they land — high-level code reviews with diagrams, wireframes, annotations, and review links.
|
|
117
|
-
|
|
118
|
-
</td>
|
|
119
|
-
</tr>
|
|
120
|
-
<tr>
|
|
121
|
-
<td width="33%" align="center" valign="top">
|
|
122
|
-
|
|
123
78
|
**Slides**
|
|
124
79
|
|
|
125
80
|
<a href="https://agent-native.com/templates/slides"><img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F2c09b451d40c4a74a89a38d69170c2d8?format=webp&width=800" alt="Slides template" width="100%" /></a>
|
|
@@ -137,79 +92,61 @@ Generate and edit React-based presentations via prompt or point-and-click.
|
|
|
137
92
|
|
|
138
93
|
**Agent-Native Amplitude, Mixpanel**
|
|
139
94
|
|
|
140
|
-
Connect analytics data sources, prompt for real charts, and build reusable dashboards.
|
|
141
|
-
|
|
142
|
-
</td>
|
|
143
|
-
<td width="33%" align="center" valign="top">
|
|
144
|
-
|
|
145
|
-
**Clips**
|
|
146
|
-
|
|
147
|
-
<a href="https://agent-native.com/templates/clips"><img src="https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F678be5a501a14ab8a508e5f7bc92c468?format=webp&width=800" alt="Clips template" width="100%" /></a>
|
|
148
|
-
|
|
149
|
-
**Agent-Native Loom**
|
|
150
|
-
|
|
151
|
-
Record your screen with auto-transcripts, shareable links, and an agent that summarizes, captions, and edits clips on demand.
|
|
95
|
+
Connect analytics data sources, prompt for real charts, and build reusable dashboards.
|
|
152
96
|
|
|
153
97
|
</td>
|
|
154
98
|
</tr>
|
|
155
99
|
</table>
|
|
156
100
|
|
|
157
|
-
Every template is a complete cloneable SaaS — fork it, customize it with the agent, own it. Try them with example data before connecting your own sources.
|
|
158
|
-
|
|
159
101
|
View the full template gallery at **[agent-native.com/templates](https://agent-native.com/templates)**.
|
|
160
102
|
|
|
161
|
-
##
|
|
103
|
+
## Agents and UIs, Fully Connected
|
|
162
104
|
|
|
163
|
-
|
|
105
|
+
The agent and the UI are equal citizens of one system. Every action works both ways: click it or ask for it.
|
|
164
106
|
|
|
165
|
-
|
|
166
|
-
npx @agent-native/core@latest create my-platform
|
|
167
|
-
cd my-platform
|
|
168
|
-
pnpm install
|
|
169
|
-
pnpm dev
|
|
170
|
-
```
|
|
107
|
+

|
|
171
108
|
|
|
172
|
-
|
|
109
|
+
- **Everything syncs**: One database, one state. Changes from either side show up instantly on the other.
|
|
110
|
+
- **Real-time multiplayer**: Humans and agents edit the same document together, with the agent as a first-class peer.
|
|
111
|
+
- **Context-aware**: The agent knows what you're looking at. Select text, hit Cmd+I, and tell it what to do.
|
|
112
|
+
- **Agents call agents**: Tag another agent from any app and they coordinate over A2A.
|
|
113
|
+
- **Self-improving**: The agent can add features, fix bugs, and refine the UI over time.
|
|
173
114
|
|
|
174
|
-
|
|
115
|
+
## Try it with a skill
|
|
116
|
+
|
|
117
|
+
Don't want to scaffold a whole app yet? Add visual planning and PR recaps to Claude Code, Codex, Cursor, Pi, OpenCode, GitHub Copilot / VS Code, and similar agents with one command:
|
|
175
118
|
|
|
176
119
|
```bash
|
|
177
|
-
npx @agent-native/core@latest
|
|
120
|
+
npx @agent-native/core@latest skills add visual-plan
|
|
178
121
|
```
|
|
179
122
|
|
|
180
|
-
|
|
123
|
+

|
|
181
124
|
|
|
182
|
-
|
|
125
|
+
You get two slash commands:
|
|
183
126
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
├── package.json # declares `agent-native.workspaceCore`
|
|
187
|
-
├── pnpm-workspace.yaml
|
|
188
|
-
├── .env # shared secrets: ANTHROPIC_API_KEY, BUILDER_PRIVATE_KEY, A2A_SECRET, ...
|
|
189
|
-
├── packages/
|
|
190
|
-
│ └── shared/ # optional shared custom code
|
|
191
|
-
└── apps/
|
|
192
|
-
├── mail/
|
|
193
|
-
├── calendar/
|
|
194
|
-
└── forms/
|
|
195
|
-
```
|
|
127
|
+
- **`/visual-plan`**: before the agent writes code, it opens a structured, reviewable plan with inline diagrams, UI wireframes, file-by-file implementation maps, and annotations you can comment on and approve.
|
|
128
|
+
- **`/visual-recap`**: after changes land, it turns a PR or git diff into a high-altitude visual recap with a shareable review link instead of a raw diff.
|
|
196
129
|
|
|
197
|
-
|
|
130
|
+
See the **[Skills Guide](https://agent-native.com/docs/skills-guide#app-backed-skills)** for more.
|
|
198
131
|
|
|
199
|
-
|
|
200
|
-
npx @agent-native/core@latest add-app notes --template content
|
|
201
|
-
```
|
|
132
|
+
## Quick Start
|
|
202
133
|
|
|
203
|
-
|
|
134
|
+
One command to start a new project locally.
|
|
204
135
|
|
|
205
136
|
```bash
|
|
206
|
-
npx @agent-native/core@latest
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
137
|
+
npx @agent-native/core@latest create my-app
|
|
138
|
+
cd my-app
|
|
139
|
+
pnpm install
|
|
140
|
+
pnpm dev
|
|
210
141
|
```
|
|
211
142
|
|
|
212
|
-
|
|
143
|
+
`create` first asks how you want to start:
|
|
144
|
+
|
|
145
|
+
- **Full template(s)**: clone one or more complete apps into a workspace. Pick Mail + Calendar + Forms and you get all three wired up and sharing auth.
|
|
146
|
+
- **Chat**: a single app with a minimal chat UI and the browser shell already wired, the simplest way to get a UI.
|
|
147
|
+
- **Headless**: a single action-first app with no UI shell. The CLI walks you through calling your first action and agent, and you can add a UI later.
|
|
148
|
+
|
|
149
|
+
Prefer flags? `create my-app --template mail`, `--headless`, or `--standalone` skip the prompt.
|
|
213
150
|
|
|
214
151
|
## The Best of Both Worlds
|
|
215
152
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-vault-secret.d.ts","sourceRoot":"","sources":["../../src/actions/create-vault-secret.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAIA,
|
|
1
|
+
{"version":3,"file":"create-vault-secret.d.ts","sourceRoot":"","sources":["../../src/actions/create-vault-secret.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAIA,wBAsBG"}
|
|
@@ -16,6 +16,11 @@ export default defineAction({
|
|
|
16
16
|
.describe("Provider grouping tag, e.g. google, sendgrid, slack"),
|
|
17
17
|
description: z.string().optional().describe("Optional description"),
|
|
18
18
|
}),
|
|
19
|
+
// This action's whole purpose is to carry a secret `value`. The vault owns
|
|
20
|
+
// secret storage; the audit log must record THAT a secret was created — never
|
|
21
|
+
// the value. Opt out of input capture so the trail can't become a second
|
|
22
|
+
// durable credential store.
|
|
23
|
+
audit: { recordInputs: false },
|
|
19
24
|
run: async (args) => createSecret(args),
|
|
20
25
|
});
|
|
21
26
|
//# sourceMappingURL=create-vault-secret.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-vault-secret.js","sourceRoot":"","sources":["../../src/actions/create-vault-secret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,8LAA8L;IAChM,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CAAC,kDAAkD,CAAC;QAC/D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QACrD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,sCAAsC,CAAC;QACxE,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,qDAAqD,CAAC;QAClE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;KACpE,CAAC;IACF,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC;CACxC,CAAC,CAAC","sourcesContent":["import { defineAction } from \"@agent-native/core\";\nimport { z } from \"zod\";\nimport { createSecret } from \"../server/lib/vault-store.js\";\n\nexport default defineAction({\n description:\n \"Store a secret in the workspace vault. Admin only. Existing credential keys are updated. By default, saved vault keys are available to every workspace app; manual mode uses per-app grants.\",\n schema: z.object({\n credentialKey: z\n .string()\n .min(1)\n .describe(\"Environment variable name, e.g. GOOGLE_CLIENT_ID\"),\n value: z.string().min(1).describe(\"The secret value\"),\n name: z.string().min(1).describe(\"Human-readable label for this secret\"),\n provider: z\n .string()\n .optional()\n .describe(\"Provider grouping tag, e.g. google, sendgrid, slack\"),\n description: z.string().optional().describe(\"Optional description\"),\n }),\n run: async (args) => createSecret(args),\n});\n"]}
|
|
1
|
+
{"version":3,"file":"create-vault-secret.js","sourceRoot":"","sources":["../../src/actions/create-vault-secret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,8LAA8L;IAChM,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CAAC,kDAAkD,CAAC;QAC/D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QACrD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,sCAAsC,CAAC;QACxE,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,qDAAqD,CAAC;QAClE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;KACpE,CAAC;IACF,2EAA2E;IAC3E,8EAA8E;IAC9E,yEAAyE;IACzE,4BAA4B;IAC5B,KAAK,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE;IAC9B,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC;CACxC,CAAC,CAAC","sourcesContent":["import { defineAction } from \"@agent-native/core\";\nimport { z } from \"zod\";\nimport { createSecret } from \"../server/lib/vault-store.js\";\n\nexport default defineAction({\n description:\n \"Store a secret in the workspace vault. Admin only. Existing credential keys are updated. By default, saved vault keys are available to every workspace app; manual mode uses per-app grants.\",\n schema: z.object({\n credentialKey: z\n .string()\n .min(1)\n .describe(\"Environment variable name, e.g. GOOGLE_CLIENT_ID\"),\n value: z.string().min(1).describe(\"The secret value\"),\n name: z.string().min(1).describe(\"Human-readable label for this secret\"),\n provider: z\n .string()\n .optional()\n .describe(\"Provider grouping tag, e.g. google, sendgrid, slack\"),\n description: z.string().optional().describe(\"Optional description\"),\n }),\n // This action's whole purpose is to carry a secret `value`. The vault owns\n // secret storage; the audit log must record THAT a secret was created — never\n // the value. Opt out of input capture so the trail can't become a second\n // durable credential store.\n audit: { recordInputs: false },\n run: async (args) => createSecret(args),\n});\n"]}
|
|
@@ -12,10 +12,12 @@
|
|
|
12
12
|
* Options:
|
|
13
13
|
* --view View name to navigate to
|
|
14
14
|
* --path URL path to navigate to
|
|
15
|
+
* --threadId Chat thread ID to open on the chat route
|
|
15
16
|
*/
|
|
16
17
|
declare const _default: import("@agent-native/core").ActionDefinition<{
|
|
17
18
|
view?: string | undefined;
|
|
18
19
|
path?: string | undefined;
|
|
20
|
+
threadId?: string | undefined;
|
|
19
21
|
}, string>;
|
|
20
22
|
export default _default;
|
|
21
23
|
//# sourceMappingURL=navigate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigate.d.ts","sourceRoot":"","sources":["../../src/actions/navigate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"navigate.d.ts","sourceRoot":"","sources":["../../src/actions/navigate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;;;;;;AAMH,wBA+BG"}
|
package/dist/actions/navigate.js
CHANGED
|
@@ -12,31 +12,42 @@
|
|
|
12
12
|
* Options:
|
|
13
13
|
* --view View name to navigate to
|
|
14
14
|
* --path URL path to navigate to
|
|
15
|
+
* --threadId Chat thread ID to open on the chat route
|
|
15
16
|
*/
|
|
16
17
|
import { defineAction } from "@agent-native/core";
|
|
17
18
|
import { z } from "zod";
|
|
18
19
|
import { writeAppState } from "@agent-native/core/application-state";
|
|
19
20
|
export default defineAction({
|
|
20
|
-
description: "Navigate the UI to a specific view or path. Writes a navigate command to application state which the UI reads and auto-deletes.",
|
|
21
|
+
description: "Navigate the UI to a specific view or path. Use threadId to open a specific chat thread on the chat route. Writes a navigate command to application state which the UI reads and auto-deletes.",
|
|
21
22
|
schema: z.object({
|
|
22
23
|
view: z
|
|
23
24
|
.string()
|
|
24
25
|
.optional()
|
|
25
26
|
.describe("Named dispatch view to navigate to. Built-in views include chat, overview, apps, metrics, new-app, vault, integrations, messaging, workspace, agents, destinations, identities, approvals, audit, thread-debug, dreams, and team. Generated Dispatch extension tabs can also use their nav item id."),
|
|
26
27
|
path: z.string().optional().describe("URL path to navigate to"),
|
|
28
|
+
threadId: z
|
|
29
|
+
.string()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Chat thread ID to open on the chat route"),
|
|
27
32
|
}),
|
|
28
33
|
http: false,
|
|
29
34
|
run: async (args) => {
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
const threadId = args.threadId?.trim();
|
|
36
|
+
if (!args.view && !args.path && !threadId) {
|
|
37
|
+
return "Error: At least --view, --path, or --threadId is required.";
|
|
32
38
|
}
|
|
33
39
|
const nav = {};
|
|
40
|
+
// A thread id without an explicit view implies the chat surface.
|
|
34
41
|
if (args.view)
|
|
35
42
|
nav.view = args.view;
|
|
43
|
+
else if (threadId)
|
|
44
|
+
nav.view = "chat";
|
|
36
45
|
if (args.path)
|
|
37
46
|
nav.path = args.path;
|
|
47
|
+
if (threadId)
|
|
48
|
+
nav.threadId = threadId;
|
|
38
49
|
await writeAppState("navigate", nav);
|
|
39
|
-
return `Navigating to ${args.view || args.path}`;
|
|
50
|
+
return `Navigating to ${args.view || args.path || `chat thread ${threadId}`}`;
|
|
40
51
|
},
|
|
41
52
|
});
|
|
42
53
|
//# sourceMappingURL=navigate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigate.js","sourceRoot":"","sources":["../../src/actions/navigate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"navigate.js","sourceRoot":"","sources":["../../src/actions/navigate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAErE,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,gMAAgM;IAClM,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,qSAAqS,CACtS;QACH,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QAC/D,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,0CAA0C,CAAC;KACxD,CAAC;IACF,IAAI,EAAE,KAAK;IACX,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1C,OAAO,4DAA4D,CAAC;QACtE,CAAC;QACD,MAAM,GAAG,GAA2B,EAAE,CAAC;QACvC,iEAAiE;QACjE,IAAI,IAAI,CAAC,IAAI;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;aAC/B,IAAI,QAAQ;YAAE,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC;QACrC,IAAI,IAAI,CAAC,IAAI;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACpC,IAAI,QAAQ;YAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACtC,MAAM,aAAa,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACrC,OAAO,iBAAiB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,eAAe,QAAQ,EAAE,EAAE,CAAC;IAChF,CAAC;CACF,CAAC,CAAC","sourcesContent":["/**\n * Navigate the UI to a view.\n *\n * Writes a navigate command to application state which the UI reads and auto-deletes.\n *\n * Usage:\n * pnpm action navigate --view=overview\n * pnpm action navigate --view=dreams\n * pnpm action navigate --view=<custom-dispatch-extension-id>\n * pnpm action navigate --path=/some/route\n *\n * Options:\n * --view View name to navigate to\n * --path URL path to navigate to\n * --threadId Chat thread ID to open on the chat route\n */\n\nimport { defineAction } from \"@agent-native/core\";\nimport { z } from \"zod\";\nimport { writeAppState } from \"@agent-native/core/application-state\";\n\nexport default defineAction({\n description:\n \"Navigate the UI to a specific view or path. Use threadId to open a specific chat thread on the chat route. Writes a navigate command to application state which the UI reads and auto-deletes.\",\n schema: z.object({\n view: z\n .string()\n .optional()\n .describe(\n \"Named dispatch view to navigate to. Built-in views include chat, overview, apps, metrics, new-app, vault, integrations, messaging, workspace, agents, destinations, identities, approvals, audit, thread-debug, dreams, and team. Generated Dispatch extension tabs can also use their nav item id.\",\n ),\n path: z.string().optional().describe(\"URL path to navigate to\"),\n threadId: z\n .string()\n .optional()\n .describe(\"Chat thread ID to open on the chat route\"),\n }),\n http: false,\n run: async (args) => {\n const threadId = args.threadId?.trim();\n if (!args.view && !args.path && !threadId) {\n return \"Error: At least --view, --path, or --threadId is required.\";\n }\n const nav: Record<string, string> = {};\n // A thread id without an explicit view implies the chat surface.\n if (args.view) nav.view = args.view;\n else if (threadId) nav.view = \"chat\";\n if (args.path) nav.path = args.path;\n if (threadId) nav.threadId = threadId;\n await writeAppState(\"navigate\", nav);\n return `Navigating to ${args.view || args.path || `chat thread ${threadId}`}`;\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-vault-secret.d.ts","sourceRoot":"","sources":["../../src/actions/update-vault-secret.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAIA,
|
|
1
|
+
{"version":3,"file":"update-vault-secret.d.ts","sourceRoot":"","sources":["../../src/actions/update-vault-secret.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAIA,wBA2CG"}
|
|
@@ -35,6 +35,9 @@ export default defineAction({
|
|
|
35
35
|
name !== undefined ||
|
|
36
36
|
provider !== undefined ||
|
|
37
37
|
description !== undefined, "At least one secret field must be updated"),
|
|
38
|
+
// Carries a secret `value`. Record THAT the secret changed, never the value —
|
|
39
|
+
// keep the audit trail from becoming a second credential store.
|
|
40
|
+
audit: { recordInputs: false },
|
|
38
41
|
run: async (args) => updateSecret(args.id, args),
|
|
39
42
|
});
|
|
40
43
|
//# sourceMappingURL=update-vault-secret.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-vault-secret.js","sourceRoot":"","sources":["../../src/actions/update-vault-secret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,uGAAuG;IACzG,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC3C,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CAAC,kDAAkD,CAAC;QAC/D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAChE,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CAAC,sCAAsC,CAAC;QACnD,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,qDAAqD,CAAC;QAClE,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,sBAAsB,CAAC;KACpC,CAAC;SACD,MAAM,CACL,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE,CACxD,aAAa,KAAK,SAAS;QAC3B,KAAK,KAAK,SAAS;QACnB,IAAI,KAAK,SAAS;QAClB,QAAQ,KAAK,SAAS;QACtB,WAAW,KAAK,SAAS,EAC3B,2CAA2C,CAC5C;IACH,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC;CACjD,CAAC,CAAC","sourcesContent":["import { defineAction } from \"@agent-native/core\";\nimport { z } from \"zod\";\nimport { updateSecret } from \"../server/lib/vault-store.js\";\n\nexport default defineAction({\n description:\n \"Update an existing vault secret's label, credential key, value, provider, or description. Admin only.\",\n schema: z\n .object({\n id: z.string().min(1).describe(\"Secret ID\"),\n credentialKey: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\"Environment variable name, e.g. GOOGLE_CLIENT_ID\"),\n value: z.string().min(1).optional().describe(\"New secret value\"),\n name: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\"Human-readable label for this secret\"),\n provider: z\n .string()\n .nullable()\n .optional()\n .describe(\"Provider grouping tag, e.g. google, sendgrid, slack\"),\n description: z\n .string()\n .nullable()\n .optional()\n .describe(\"Optional description\"),\n })\n .refine(\n ({ credentialKey, value, name, provider, description }) =>\n credentialKey !== undefined ||\n value !== undefined ||\n name !== undefined ||\n provider !== undefined ||\n description !== undefined,\n \"At least one secret field must be updated\",\n ),\n run: async (args) => updateSecret(args.id, args),\n});\n"]}
|
|
1
|
+
{"version":3,"file":"update-vault-secret.js","sourceRoot":"","sources":["../../src/actions/update-vault-secret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,uGAAuG;IACzG,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC3C,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CAAC,kDAAkD,CAAC;QAC/D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAChE,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CAAC,sCAAsC,CAAC;QACnD,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,qDAAqD,CAAC;QAClE,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,sBAAsB,CAAC;KACpC,CAAC;SACD,MAAM,CACL,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE,CACxD,aAAa,KAAK,SAAS;QAC3B,KAAK,KAAK,SAAS;QACnB,IAAI,KAAK,SAAS;QAClB,QAAQ,KAAK,SAAS;QACtB,WAAW,KAAK,SAAS,EAC3B,2CAA2C,CAC5C;IACH,8EAA8E;IAC9E,gEAAgE;IAChE,KAAK,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE;IAC9B,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC;CACjD,CAAC,CAAC","sourcesContent":["import { defineAction } from \"@agent-native/core\";\nimport { z } from \"zod\";\nimport { updateSecret } from \"../server/lib/vault-store.js\";\n\nexport default defineAction({\n description:\n \"Update an existing vault secret's label, credential key, value, provider, or description. Admin only.\",\n schema: z\n .object({\n id: z.string().min(1).describe(\"Secret ID\"),\n credentialKey: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\"Environment variable name, e.g. GOOGLE_CLIENT_ID\"),\n value: z.string().min(1).optional().describe(\"New secret value\"),\n name: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\"Human-readable label for this secret\"),\n provider: z\n .string()\n .nullable()\n .optional()\n .describe(\"Provider grouping tag, e.g. google, sendgrid, slack\"),\n description: z\n .string()\n .nullable()\n .optional()\n .describe(\"Optional description\"),\n })\n .refine(\n ({ credentialKey, value, name, provider, description }) =>\n credentialKey !== undefined ||\n value !== undefined ||\n name !== undefined ||\n provider !== undefined ||\n description !== undefined,\n \"At least one secret field must be updated\",\n ),\n // Carries a secret `value`. Record THAT the secret changed, never the value —\n // keep the audit trail from becoming a second credential store.\n audit: { recordInputs: false },\n run: async (args) => updateSecret(args.id, args),\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAElB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AA6Df,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,YAAY,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,mFAAmF;IACnF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,gEAAgE;IAChE,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,uBAAuB;IACtC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACtC,kFAAkF;IAClF,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B;
|
|
1
|
+
{"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAElB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AA6Df,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,YAAY,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,mFAAmF;IACnF,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,gEAAgE;IAChE,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,uBAAuB;IACtC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACtC,kFAAkF;IAClF,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/B;AA8cD,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,UAAU,GACX,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,2CA6IA;AAED,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,2CAgGA"}
|
|
@@ -190,6 +190,21 @@ function dispatchNavLinkTarget(path) {
|
|
|
190
190
|
const routerHasBasename = pathname === basePath || pathname.startsWith(`${basePath}/`);
|
|
191
191
|
return routerHasBasename ? path : appPath(path);
|
|
192
192
|
}
|
|
193
|
+
function chatThreadPath(threadId) {
|
|
194
|
+
return `/chat/${encodeURIComponent(threadId)}`;
|
|
195
|
+
}
|
|
196
|
+
function threadIdFromPath(pathname) {
|
|
197
|
+
const match = pathname.match(/^\/chat\/([^/]+)/);
|
|
198
|
+
if (!match)
|
|
199
|
+
return null;
|
|
200
|
+
try {
|
|
201
|
+
const value = decodeURIComponent(match[1]).trim();
|
|
202
|
+
return value || null;
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
193
208
|
function formatThreadAge(updatedAt) {
|
|
194
209
|
const diffMs = Math.max(0, Date.now() - updatedAt);
|
|
195
210
|
const minutes = Math.floor(diffMs / 60_000);
|
|
@@ -220,6 +235,7 @@ function threadUpdatedAt(thread) {
|
|
|
220
235
|
}
|
|
221
236
|
function DispatchChatsSection({ onNavigate }) {
|
|
222
237
|
const navigate = useNavigate();
|
|
238
|
+
const location = useLocation();
|
|
223
239
|
const { threads, activeThreadId, createThread, switchThread, renameThread, refreshThreads, } = useChatThreads(undefined, "dispatch", undefined, { autoCreate: false });
|
|
224
240
|
const [renamingThreadId, setRenamingThreadId] = useState(null);
|
|
225
241
|
const [renameDraft, setRenameDraft] = useState("");
|
|
@@ -255,7 +271,7 @@ function DispatchChatsSection({ onNavigate }) {
|
|
|
255
271
|
}, [renamingThreadId]);
|
|
256
272
|
function openThread(threadId, options) {
|
|
257
273
|
switchThread(threadId);
|
|
258
|
-
navigateWithAgentChatViewTransition(navigate, dispatchNavLinkTarget("/chat"));
|
|
274
|
+
navigateWithAgentChatViewTransition(navigate, dispatchNavLinkTarget(options?.isNew ? "/chat" : chatThreadPath(threadId)));
|
|
259
275
|
onNavigate?.();
|
|
260
276
|
window.requestAnimationFrame(() => {
|
|
261
277
|
window.dispatchEvent(new CustomEvent("agent-chat:open-thread", {
|
|
@@ -297,7 +313,10 @@ function DispatchChatsSection({ onNavigate }) {
|
|
|
297
313
|
void commitRenameThread();
|
|
298
314
|
}
|
|
299
315
|
return (_jsxs("div", { className: "mt-2 border-l border-sidebar-border/70 pl-3", children: [_jsxs("div", { className: "mb-1 flex h-7 items-center gap-2 pr-1", children: [_jsx("div", { className: "min-w-0 flex-1 text-xs font-medium text-sidebar-foreground/70", children: "Chats" }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: handleNewChat, className: "flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-sidebar-foreground/65 transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", "aria-label": "New Dispatch chat", children: _jsx(IconPlus, { className: "size-3.5" }) }) }), _jsx(TooltipContent, { children: "New chat" })] })] }), _jsx("div", { className: "grid gap-0.5", children: visibleThreads.length > 0 ? (visibleThreads.map((thread) => {
|
|
300
|
-
const
|
|
316
|
+
const localPathname = localDispatchPath(location.pathname);
|
|
317
|
+
const isActive = thread.id ===
|
|
318
|
+
(threadIdFromPath(localPathname) ??
|
|
319
|
+
(localPathname === "/chat" ? null : activeThreadId));
|
|
301
320
|
const isRenaming = thread.id === renamingThreadId;
|
|
302
321
|
return (_jsx("div", { className: cn("group flex h-8 min-w-0 items-center rounded-md text-sm transition-colors", isActive
|
|
303
322
|
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
@@ -360,13 +379,16 @@ export function Layout({ children, extensions, }) {
|
|
|
360
379
|
const navigate = useNavigate();
|
|
361
380
|
const [mobileOpen, setMobileOpen] = useState(false);
|
|
362
381
|
const localPathname = localDispatchPath(location.pathname);
|
|
363
|
-
const isChatRoute = localPathname === "/chat";
|
|
382
|
+
const isChatRoute = localPathname === "/chat" || localPathname.startsWith("/chat/");
|
|
364
383
|
const chatHomeHandoffActive = useAgentChatHomeHandoff({
|
|
365
384
|
storageKey: "dispatch",
|
|
366
385
|
activePath: localPathname,
|
|
367
386
|
enabled: !isChatRoute,
|
|
368
387
|
});
|
|
369
|
-
useAgentChatHomeHandoffLinks({
|
|
388
|
+
useAgentChatHomeHandoffLinks({
|
|
389
|
+
storageKey: "dispatch",
|
|
390
|
+
isChatPath: (pathname) => pathname === "/chat" || pathname.startsWith("/chat/"),
|
|
391
|
+
});
|
|
370
392
|
if (CHROMELESS_PATHS.some((path) => localPathname === path)) {
|
|
371
393
|
return _jsx(_Fragment, { children: children });
|
|
372
394
|
}
|