@agent-native/core 0.172.3 → 0.172.6
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/corpus/README.md +1 -1
- package/corpus/templates/calendar/actions/get-settings.ts +2 -5
- package/corpus/templates/calendar/actions/list-events.ts +21 -80
- package/corpus/templates/calendar/actions/update-settings.ts +11 -16
- package/corpus/templates/calendar/actions/view-screen.ts +25 -10
- package/corpus/templates/calendar/app/components/calendar/CommandPalette.tsx +7 -1
- package/corpus/templates/calendar/app/components/calendar/EventCard.tsx +5 -2
- package/corpus/templates/calendar/app/lib/calendar-timezone.ts +3 -18
- package/corpus/templates/calendar/app/lib/event-form-utils.ts +3 -62
- package/corpus/templates/calendar/changelog/2026-07-22-calendar-grid-local-time.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-19-the-calendar-loads-again-for-accounts-whose-saved-timezone-w.md +6 -0
- package/corpus/templates/calendar/server/handlers/settings.ts +8 -24
- package/corpus/templates/calendar/server/lib/calendar-settings.ts +58 -0
- package/corpus/templates/calendar/server/lib/find-time.ts +15 -93
- package/corpus/templates/calendar/shared/settings.ts +15 -9
- package/corpus/templates/calendar/shared/timezone.ts +127 -0
- package/corpus/templates/factory/AGENTS.md +5 -3
- package/corpus/templates/factory/actions/babysit-pull-request.ts +6 -0
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -2
- package/corpus/templates/factory/actions/save-factory-automation.ts +0 -5
- package/corpus/templates/factory/changelog/2026-08-24-slack-checking-works-for-teammate-created-factories.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-24-teammates-can-edit-and-run-factory-jobs.md +6 -0
- package/corpus/templates/factory/server/lib/factory-scope.ts +8 -0
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +1 -9
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +2 -1
- package/corpus/templates/slides/actions/list-decks.ts +79 -5
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +21 -1
- package/corpus/templates/slides/app/components/editor/ShareDialog.tsx +49 -21
- package/corpus/templates/slides/app/context/DeckContext.tsx +49 -21
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +2 -2
- package/corpus/templates/slides/app/pages/Index.tsx +11 -13
- package/corpus/templates/slides/changelog/2026-08-24-deck-previews-and-sharing-live-in-the-overflow-menu.md +5 -0
- package/dist/agent/production-agent.js +5 -1
- package/dist/agent/types.d.ts +5 -0
- package/dist/automations/service.d.ts +6 -0
- package/dist/automations/service.js +20 -0
- package/dist/client/settings/SettingsPanel.js +80 -33
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/jobs/run-now.js +2 -2
- package/dist/observability/posthog-ai.d.ts +36 -11
- package/dist/observability/posthog-ai.js +99 -30
- package/dist/observability/routes.js +9 -2
- package/dist/observability/traces.js +330 -142
- package/dist/tracking/providers.js +9 -3
- package/dist/vite/client.js +5 -2
- package/docs/content/docs-components.mdx +20 -1
- package/docs/content/observability.mdx +27 -10
- package/docs/content/template-calendar-agent.mdx +63 -26
- package/docs/content/template-calendar-developers.mdx +165 -40
- package/docs/content/template-calendar-features.mdx +276 -0
- package/docs/content/template-calendar-integrations.mdx +78 -0
- package/docs/content/template-calendar.mdx +56 -123
- package/package.json +1 -1
- package/docs/content/template-calendar-booking-links.mdx +0 -73
- package/docs/content/template-calendar-scheduling.mdx +0 -128
|
@@ -140,11 +140,16 @@ function createPostHogProvider(apiKey, host, errorTracking) {
|
|
|
140
140
|
enqueue(`${host}/i/v0/e/`, JSON.stringify({
|
|
141
141
|
api_key: apiKey,
|
|
142
142
|
event: event.name,
|
|
143
|
+
// Top level, NOT inside `properties`: PostHog reads the event time from
|
|
144
|
+
// the payload root and treats a `properties.timestamp` as an ordinary
|
|
145
|
+
// custom property, stamping the event with its ingestion time instead.
|
|
146
|
+
// An agent run emits its whole tree in one burst at the end, so that
|
|
147
|
+
// collapsed a five-minute waterfall into the 100ms it took to flush.
|
|
148
|
+
timestamp: event.timestamp,
|
|
143
149
|
properties: {
|
|
144
150
|
distinct_id: distinctId,
|
|
145
151
|
...properties,
|
|
146
152
|
...(event.sessionId ? { $session_id: event.sessionId } : {}),
|
|
147
|
-
timestamp: event.timestamp,
|
|
148
153
|
},
|
|
149
154
|
}));
|
|
150
155
|
};
|
|
@@ -176,10 +181,10 @@ function createPostHogProvider(apiKey, host, errorTracking) {
|
|
|
176
181
|
api_key: apiKey,
|
|
177
182
|
event: event.name,
|
|
178
183
|
distinct_id: distinctId,
|
|
184
|
+
timestamp: event.timestamp,
|
|
179
185
|
properties: {
|
|
180
186
|
...event.properties,
|
|
181
187
|
...(event.sessionId ? { $session_id: event.sessionId } : {}),
|
|
182
|
-
timestamp: event.timestamp,
|
|
183
188
|
},
|
|
184
189
|
}));
|
|
185
190
|
},
|
|
@@ -218,7 +223,8 @@ export function sendPostHogEvent(name, properties, distinctId) {
|
|
|
218
223
|
api_key: apiKey,
|
|
219
224
|
event: name,
|
|
220
225
|
distinct_id: distinctId,
|
|
221
|
-
|
|
226
|
+
timestamp: new Date().toISOString(),
|
|
227
|
+
properties,
|
|
222
228
|
}));
|
|
223
229
|
return true;
|
|
224
230
|
}
|
package/dist/vite/client.js
CHANGED
|
@@ -1680,6 +1680,10 @@ function virtualModuleIdFromRuntimeUrl(runtimeUrl) {
|
|
|
1680
1680
|
}
|
|
1681
1681
|
async function loadMountedEmbedRuntimeModule(server, runtimeUrl) {
|
|
1682
1682
|
const virtualId = virtualModuleIdFromRuntimeUrl(runtimeUrl);
|
|
1683
|
+
// transform import to encode virtual modules in vite as these imports don't work in the browser
|
|
1684
|
+
const result = await server.transformRequest(virtualId ?? runtimeUrl);
|
|
1685
|
+
if (typeof result?.code === "string")
|
|
1686
|
+
return result.code;
|
|
1683
1687
|
if (virtualId) {
|
|
1684
1688
|
const loaded = await server.pluginContainer?.load?.(virtualId);
|
|
1685
1689
|
if (typeof loaded === "string")
|
|
@@ -1687,8 +1691,7 @@ async function loadMountedEmbedRuntimeModule(server, runtimeUrl) {
|
|
|
1687
1691
|
if (loaded && typeof loaded.code === "string")
|
|
1688
1692
|
return loaded.code;
|
|
1689
1693
|
}
|
|
1690
|
-
|
|
1691
|
-
return result?.code ?? null;
|
|
1694
|
+
return null;
|
|
1692
1695
|
}
|
|
1693
1696
|
function serveMountedEmbedRuntimeModule(server, req, res, base) {
|
|
1694
1697
|
if (req.method !== "GET" && req.method !== "HEAD")
|
|
@@ -197,6 +197,7 @@ Each card is a `###` heading (optionally linked) followed by the description. Ca
|
|
|
197
197
|
| `plug` | integrations, connected tools |
|
|
198
198
|
| `network` | cross-app or distributed communication |
|
|
199
199
|
| `terminal` | CLI, scripts, terminal-driven workflows |
|
|
200
|
+
| `calendar` | scheduling, dates, time-based features |
|
|
200
201
|
|
|
201
202
|
The grid defaults to 3 columns. Set `columns` (1-4) on the opening tag to override it, e.g. `<Cards columns={2}>`. Below 640px the grid always collapses to a single column regardless of `columns`.
|
|
202
203
|
|
|
@@ -337,7 +338,25 @@ Define one action. The agent calls it as a tool, the UI calls it through a React
|
|
|
337
338
|
</Comparison>
|
|
338
339
|
```
|
|
339
340
|
|
|
340
|
-
Add more `###` sections to get 3 or 4 columns (max 4). The red/green label accent
|
|
341
|
+
Add more `###` sections to get 3 or 4 columns (max 4). The red/green label accent applies automatically to headings that exactly match `Before`, `Old`, `Without` (red) or `After`, `New`, `With` (green).
|
|
342
|
+
|
|
343
|
+
For any other pairing, an explicit `:color:` prefix sets a column's accent directly, the same shortcode idiom `Cards` uses for `:icon:`:
|
|
344
|
+
|
|
345
|
+
```mdx
|
|
346
|
+
<Comparison>
|
|
347
|
+
|
|
348
|
+
### :blue: You ask
|
|
349
|
+
|
|
350
|
+
"Am I free Thursday afternoon?"
|
|
351
|
+
|
|
352
|
+
### :green: What happens
|
|
353
|
+
|
|
354
|
+
The agent answers in chat. Nothing on screen changes.
|
|
355
|
+
|
|
356
|
+
</Comparison>
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
`color` accepts `blue`, `green`, `red`, or `yellow`, matching `Badge`'s color naming. Each routes through a real theme token (the site's brand blue, or the same semantic red/yellow/green used elsewhere) rather than a raw color, so it stays correct in both themes. An explicit `color` always wins over the Before/After heuristic.
|
|
341
360
|
|
|
342
361
|
---
|
|
343
362
|
|
|
@@ -297,13 +297,24 @@ All endpoints support `?since=N` (ms timestamp) and `?limit=N` query params.
|
|
|
297
297
|
When `POSTHOG_API_KEY` is set, every instrumented run is mirrored to PostHog's
|
|
298
298
|
LLM analytics as a full trace tree:
|
|
299
299
|
|
|
300
|
-
| Event | Emitted per
|
|
301
|
-
| ---------------- |
|
|
302
|
-
| `$ai_trace` | agent run
|
|
303
|
-
| `$ai_generation` | model
|
|
304
|
-
| `$ai_span` | tool call
|
|
305
|
-
|
|
306
|
-
Nodes share the run id as `$ai_trace_id`, so PostHog renders one tree per run
|
|
300
|
+
| Event | Emitted per | Carries |
|
|
301
|
+
| ---------------- | ---------------- | --------------------------------------------------------- |
|
|
302
|
+
| `$ai_trace` | agent run | Run name, totals, terminal state, run-level failure |
|
|
303
|
+
| `$ai_generation` | model round-trip | Prompt, answer, model, tokens, cost, latency, stop reason |
|
|
304
|
+
| `$ai_span` | tool call | Tool name, duration, failure class |
|
|
305
|
+
|
|
306
|
+
Nodes share the run id as `$ai_trace_id`, so PostHog renders one tree per run,
|
|
307
|
+
with each tool span under the generation that requested it. A run's tool
|
|
308
|
+
definitions are never sent: they are the same catalogue on every call, and a
|
|
309
|
+
call is identified by its name in `$ai_output_choices` and by its own span.
|
|
310
|
+
|
|
311
|
+
`$ai_is_error` means a different thing at each level, and never travels without
|
|
312
|
+
`$ai_error` and `$ai_error_type`. On a generation it is the model call itself
|
|
313
|
+
failing — a provider error, a dropped stream. On a span it is a tool that
|
|
314
|
+
crashed or returned an error. On the trace it is the run: a step budget, a
|
|
315
|
+
timeout, a no-progress cut-off, or a tool that stopped the run. A run that
|
|
316
|
+
failed after the model answered leaves its generations green, because they did
|
|
317
|
+
not fail.
|
|
307
318
|
`$ai_session_id` is the conversation thread; the browser session is sent
|
|
308
319
|
separately as `$session_id` so a trace links to its session replay.
|
|
309
320
|
|
|
@@ -337,9 +348,15 @@ to each other.
|
|
|
337
348
|
|
|
338
349
|
Thumbs, category, and free-text feedback all emit `$ai_feedback`. PostHog's LLM
|
|
339
350
|
analytics feedback view reads a `survey sent` event instead, so set
|
|
340
|
-
`POSTHOG_AI_FEEDBACK_SURVEY_ID`
|
|
341
|
-
|
|
342
|
-
is sent.
|
|
351
|
+
`POSTHOG_AI_FEEDBACK_SURVEY_ID` to the survey PostHog creates from a trace's
|
|
352
|
+
**Feedback** tab. That one id is the whole configuration; without it no survey
|
|
353
|
+
event is sent.
|
|
354
|
+
|
|
355
|
+
A thumbs vote answers the survey's first question as PostHog's choice index
|
|
356
|
+
(`1` up, `2` down) and the free text after a thumbs-down answers the follow-up
|
|
357
|
+
question, so the text never lands where the rating belongs. Both carry one
|
|
358
|
+
submission id per rated message, which is how PostHog joins them into a single
|
|
359
|
+
response, and a thumbs-down stays marked incomplete until its follow-up arrives.
|
|
343
360
|
|
|
344
361
|
## Export to external platforms {#export}
|
|
345
362
|
|
|
@@ -1,52 +1,89 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Calendar:
|
|
2
|
+
title: "Calendar: Talk to the Agent"
|
|
3
3
|
description: "What the agent sees when you're in Calendar, prompts organized by task, and when it reaches for the raw Google Calendar API instead of a canned action."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Talk to the Agent
|
|
7
7
|
|
|
8
8
|
Everything in Calendar is available to the agent through the same actions the UI uses, so anything you can click, you can also ask for in plain English. This page covers how the agent sees your screen, useful prompts by task, and where it escalates beyond the built-in actions. See [Calendar](/docs/template-calendar) for the overview.
|
|
9
9
|
|
|
10
10
|
## How the agent sees your screen
|
|
11
11
|
|
|
12
|
-
The agent always knows the current calendar view, the date range you're looking at, and the event you have selected. That's why "reschedule this" or "who's on this call" resolves correctly without you naming the event
|
|
12
|
+
The agent always knows the current calendar view, the date range you're looking at, and the event you have selected. That's why "reschedule this" or "who's on this call" resolves correctly without you naming the event. The agent already knows which one "this" refers to.
|
|
13
13
|
|
|
14
14
|
## Useful prompts by task
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Every prompt below becomes a real action against your actual calendar, the
|
|
17
|
+
same one the UI reads and writes. Here's one worked example:
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
- "Create a Zoom meeting with the design team Thursday at 10."
|
|
20
|
-
- "Set me as out of office Friday."
|
|
19
|
+
<Comparison>
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
### :blue: You ask
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
- "Am I free Thursday afternoon?"
|
|
23
|
+
"Am I free Thursday afternoon?"
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
### :green: What happens
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
This is a read-only question. The agent checks your real calendar and
|
|
28
|
+
availability rules, then answers directly in chat, for example "You're open
|
|
29
|
+
from 1 to 4pm." Nothing on your screen changes, since nothing was created or
|
|
30
|
+
moved.
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
</Comparison>
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
- "Add Brent as a required co-host on my 'Steve + Brent' link."
|
|
38
|
-
- "Pause my '30 min demo' link."
|
|
39
|
-
- "Show me this week's bookings."
|
|
34
|
+
<Cards columns={2}>
|
|
40
35
|
|
|
41
|
-
|
|
36
|
+
### Schedule
|
|
37
|
+
|
|
38
|
+
- **"Schedule a 30-minute call with Alex tomorrow at 2pm."** The event
|
|
39
|
+
appears on your calendar the moment it's created. No dialog needed.
|
|
40
|
+
- **"Create a Zoom meeting with the design team Thursday at 10."** Same as
|
|
41
|
+
above, and a Zoom link is attached automatically.
|
|
42
|
+
- **"Set me as out of office Friday."** An all-day out-of-office event shows
|
|
43
|
+
up on your calendar right away.
|
|
44
|
+
|
|
45
|
+
### Find time
|
|
46
|
+
|
|
47
|
+
- **"Find a 1-hour slot next week with Sam and Priya and book 'Planning' on
|
|
48
|
+
it."** The agent checks everyone's real availability, then the new event
|
|
49
|
+
appears on your calendar live. No dialog needed.
|
|
50
|
+
|
|
51
|
+
### Manage events
|
|
52
|
+
|
|
53
|
+
_With an event selected, "this" and "this meeting" resolve on their own._
|
|
54
|
+
|
|
55
|
+
- **"Move this event to Friday at 2pm."** The event moves on your calendar
|
|
56
|
+
grid live.
|
|
57
|
+
- **"Add Jordan to this meeting as an optional guest."** Jordan shows up in
|
|
58
|
+
the attendee list immediately.
|
|
59
|
+
- **"Accept this invite." / "Decline with a note that I'm out that day."**
|
|
60
|
+
Your RSVP updates on the event right away.
|
|
61
|
+
- **"Delete this meeting, just for me. I'm not the organizer."** The meeting
|
|
62
|
+
disappears from your calendar. Other attendees still see it on theirs.
|
|
63
|
+
|
|
64
|
+
### Booking links
|
|
65
|
+
|
|
66
|
+
- **"Create a 15-minute intro booking link with a name field."** The new
|
|
67
|
+
meeting type appears in your Booking Links list live.
|
|
68
|
+
- **"Add Brent as a required co-host on my 'Steve + Brent' link."** Brent
|
|
69
|
+
shows up as a co-host immediately, and future slots only open when you're
|
|
70
|
+
both free.
|
|
71
|
+
- **"Pause my '30 min demo' link."** The link shows as paused right away and
|
|
72
|
+
stops accepting new bookings.
|
|
73
|
+
- **"Show me this week's bookings."** A read-only question. The agent
|
|
74
|
+
answers in chat with the list.
|
|
75
|
+
|
|
76
|
+
### People and view
|
|
42
77
|
|
|
43
78
|
- "Who is jane at acme.com?"
|
|
44
79
|
- "Add Priya's calendar to my view."
|
|
45
80
|
- "Switch to day view and jump to next Monday."
|
|
46
81
|
|
|
82
|
+
</Cards>
|
|
83
|
+
|
|
47
84
|
## Group and co-host booking links
|
|
48
85
|
|
|
49
|
-
When a booking link has required co-hosts, the agent (and the UI) only offers a slot when the owner _and_ every co-host are free
|
|
86
|
+
When a booking link has required co-hosts, the agent (and the UI) only offers a slot when the owner _and_ every co-host are free. It checks all of their calendars, not just the owner's. Once someone books, the agent invites every co-host to the created Google Calendar event alongside the visitor.
|
|
50
87
|
|
|
51
88
|
<Diagram id="doc-block-calendar5" title="How a scheduling request flows" summary="Whether you click in the calendar or ask the agent, the same actions read live from Google Calendar and write back to the same view. Zoom and people search plug into the same flow.">
|
|
52
89
|
|
|
@@ -118,16 +155,16 @@ When a booking link has required co-hosts, the agent (and the UI) only offers a
|
|
|
118
155
|
|
|
119
156
|
## When the agent goes straight to the Google Calendar API
|
|
120
157
|
|
|
121
|
-
The built-in actions (`list-events`, `search-events`, `find-a-time`, and so on) cover everyday scheduling.
|
|
158
|
+
The built-in actions (`list-events`, `search-events`, `find-a-time`, and so on) cover everyday scheduling. Some requests need an exact Google Calendar endpoint, filter, or pagination mode that the actions don't expose, like scanning every event across six months for a report, or an unusual calendar-list query. For those, the agent can call the real Google Calendar API directly instead of forcing the answer through a narrower action. For large scans, it stages the results into a scratch dataset and works from a compact summary rather than dumping thousands of events into the conversation. You'll typically notice this as "let me pull that directly from Google Calendar" on requests that go beyond a normal schedule question.
|
|
122
159
|
|
|
123
160
|
## Extensions
|
|
124
161
|
|
|
125
|
-
Calendar supports Extensions
|
|
162
|
+
Calendar supports Extensions: small sandboxed widgets you or the agent can build and drop into the app. The event detail panel exposes a slot at the bottom where an extension can render, with the event's id, title, times, timezones, location, attendees, and account already available to it. See [Extensions](/docs/extensions) for how to build one.
|
|
126
163
|
|
|
127
164
|
## What's next
|
|
128
165
|
|
|
129
166
|
- [**Calendar**](/docs/template-calendar) — the overview and getting-started steps
|
|
130
|
-
- [**
|
|
131
|
-
- [**
|
|
167
|
+
- [**Features**](/docs/template-calendar-features) — views, availability, finding time, and booking links, with setup steps for each
|
|
168
|
+
- [**Calendar in a Multi-App Workspace**](/docs/template-calendar-integrations) — integration strategies and connecting to Dispatch
|
|
132
169
|
- [**Developer Guide**](/docs/template-calendar-developers) — every action, the data model, and how to extend the app
|
|
133
170
|
- [**Extensions**](/docs/extensions) — building a widget for the event-detail slot
|
|
@@ -9,15 +9,91 @@ This page is for anyone customizing the Calendar template or extending it: the q
|
|
|
9
9
|
|
|
10
10
|
## Quick start
|
|
11
11
|
|
|
12
|
+
This walks through running Calendar from nothing installed to a connected
|
|
13
|
+
Google Calendar. The commands are identical whether you're in Terminal on
|
|
14
|
+
macOS or PowerShell/Command Prompt on Windows, they're plain Node.js tooling.
|
|
15
|
+
|
|
16
|
+
<Steps>
|
|
17
|
+
|
|
18
|
+
### Create the app
|
|
19
|
+
|
|
12
20
|
```bash
|
|
13
21
|
npx @agent-native/core@latest create my-calendar --standalone --template calendar
|
|
22
|
+
cd my-calendar
|
|
23
|
+
pnpm install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This needs [Node.js](https://nodejs.org) 22 or later and
|
|
27
|
+
[pnpm](https://pnpm.io) installed first. See
|
|
28
|
+
[Getting started](/docs/getting-started) if you haven't installed either
|
|
29
|
+
yet, or don't have an LLM connection (Builder.io, an Anthropic/OpenAI key,
|
|
30
|
+
or local Ollama) set up.
|
|
31
|
+
|
|
32
|
+
### Start the dev server
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pnpm dev
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The app opens at `http://localhost:8082`. If it doesn't open automatically,
|
|
39
|
+
visit that URL in your browser. Calendar works fully with Google
|
|
40
|
+
disconnected. You'll only hit an error if you try an action that needs it
|
|
41
|
+
before connecting.
|
|
42
|
+
|
|
43
|
+
### Connect Google Calendar
|
|
44
|
+
|
|
45
|
+
In the app, open **Settings**, and on the **General** tab find the **Google
|
|
46
|
+
Calendar** card, then click **Connect Google Calendar**. This opens a setup
|
|
47
|
+
wizard:
|
|
48
|
+
|
|
49
|
+
1. **Create a Google Cloud project**, if you don't already have one to use:
|
|
50
|
+
in [Google Cloud Console](https://console.cloud.google.com/), click the
|
|
51
|
+
project dropdown near the top of the page, then **New Project**. Give it
|
|
52
|
+
any name, click **Create**, and wait for the notification that it's
|
|
53
|
+
ready. Make sure it's selected in that same dropdown before continuing.
|
|
54
|
+
2. **Enable the API**: with your project selected, go to **APIs & Services
|
|
55
|
+
→ Library**, search for "Google Calendar API," open it, and click
|
|
56
|
+
**Enable**.
|
|
57
|
+
3. **Configure the consent screen**: under **APIs & Services → OAuth
|
|
58
|
+
consent screen**, set one up ("External" is fine for development).
|
|
59
|
+
4. **Create credentials**: under **APIs & Services → Credentials**, create
|
|
60
|
+
an OAuth client ID of type "Web application," and add
|
|
61
|
+
`http://localhost:8082/_agent-native/google/callback` as an authorized
|
|
62
|
+
redirect URI (8082 is Calendar's default dev port).
|
|
63
|
+
5. **Add the credentials**: download the credentials JSON and upload it in
|
|
64
|
+
the wizard, or toggle "Paste manually" and enter the Client ID and Client
|
|
65
|
+
Secret directly.
|
|
66
|
+
|
|
67
|
+
Calendar saves these to its own secret store, not a `.env` file, so this
|
|
68
|
+
step is identical on Windows and macOS. Tokens refresh automatically once
|
|
69
|
+
connected.
|
|
70
|
+
|
|
71
|
+
### Connect Zoom (optional)
|
|
72
|
+
|
|
73
|
+
Unlike Google, Zoom has no Settings form. Create a `.env` file in the
|
|
74
|
+
project root (or add to the existing one) with:
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
ZOOM_CLIENT_ID=your-client-id
|
|
78
|
+
ZOOM_CLIENT_SECRET=your-client-secret
|
|
14
79
|
```
|
|
15
80
|
|
|
16
|
-
|
|
81
|
+
Get a Client ID and Secret from a [Zoom OAuth app](https://marketplace.zoom.us/)
|
|
82
|
+
(Zoom Marketplace → Develop → Build App → OAuth), with
|
|
83
|
+
`/_agent-native/zoom/callback` as the redirect URI, then restart `pnpm dev`
|
|
84
|
+
so it picks up the new values. Without Zoom connected, booking links can
|
|
85
|
+
still offer Google Meet, just not Zoom.
|
|
86
|
+
|
|
87
|
+
</Steps>
|
|
17
88
|
|
|
18
|
-
|
|
89
|
+
<Callout tone="warning">
|
|
19
90
|
|
|
20
|
-
|
|
91
|
+
On Windows, some editors add a hidden `.txt` extension when you save a file
|
|
92
|
+
named `.env`, leaving a `.env.txt` that Calendar never reads. In File
|
|
93
|
+
Explorer, turn on "File name extensions" (View tab) and confirm the saved
|
|
94
|
+
file is named exactly `.env`, with nothing after it.
|
|
95
|
+
|
|
96
|
+
</Callout>
|
|
21
97
|
|
|
22
98
|
<Callout tone="info">
|
|
23
99
|
|
|
@@ -29,57 +105,101 @@ To enable Zoom conferencing on booking links, set `ZOOM_CLIENT_ID` and `ZOOM_CLI
|
|
|
29
105
|
|
|
30
106
|
Every operation is a TypeScript file in `templates/calendar/actions/`, auto-mounted at `POST /_agent-native/actions/:name`.
|
|
31
107
|
|
|
32
|
-
|
|
108
|
+
### Events & guests
|
|
109
|
+
|
|
110
|
+
Event data lives in Google Calendar, never SQL.
|
|
33
111
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
112
|
+
| Action | What it does |
|
|
113
|
+
| --- | --- |
|
|
114
|
+
| `list-events` | List events in a date range |
|
|
115
|
+
| `search-events` | Search events by query |
|
|
116
|
+
| `get-event` | Read one event by id |
|
|
117
|
+
| `create-event` | Create an event, including recurrence (RRULE), working locations, and status types (`outOfOffice`, `focusTime`) |
|
|
118
|
+
| `update-event` | Update an event, including recurrence, working locations, and status types |
|
|
119
|
+
| `delete-event` | Delete an event |
|
|
120
|
+
| `manage-event-draft` | Stage an unsent invite for user review before anything is written or guests are notified |
|
|
121
|
+
| `rsvp-event` | Accept, decline, or mark tentative on an invitation |
|
|
122
|
+
| `get-attendee-timezones` | Read per-guest timezone overrides |
|
|
123
|
+
| `set-attendee-timezone` | Set a per-guest timezone override so their local time keeps showing correctly |
|
|
39
124
|
|
|
40
|
-
|
|
125
|
+
### Availability & finding time
|
|
41
126
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
127
|
+
| Action | What it does |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| `get-availability` | Read the weekly schedule, timezone, buffer, notice, and advance-window settings |
|
|
130
|
+
| `update-availability` | Update the weekly schedule, timezone, buffer, notice, and advance-window settings |
|
|
131
|
+
| `check-availability` | Find open slots for one date |
|
|
132
|
+
| `find-a-time` | Shared free-slot search across an organizer and named attendees, combining Google free/busy with local conflicts |
|
|
45
133
|
|
|
46
|
-
|
|
134
|
+
### Booking links & bookings
|
|
47
135
|
|
|
48
|
-
|
|
49
|
-
|
|
136
|
+
| Action | What it does |
|
|
137
|
+
| --- | --- |
|
|
138
|
+
| `create-booking-link` | Create a booking link |
|
|
139
|
+
| `update-booking-link` | Update a booking link |
|
|
140
|
+
| `duplicate-booking-link` | Duplicate a booking link, including co-hosts (`hosts`) |
|
|
141
|
+
| `list-booking-links` | List accessible booking links |
|
|
142
|
+
| `list-bookings` | List confirmed appointments |
|
|
50
143
|
|
|
51
|
-
|
|
144
|
+
### External calendars
|
|
52
145
|
|
|
53
|
-
-
|
|
146
|
+
Read-only ICS feeds.
|
|
54
147
|
|
|
55
|
-
|
|
148
|
+
| Action | What it does |
|
|
149
|
+
| --- | --- |
|
|
150
|
+
| `add-external-calendar` | Subscribe to a read-only ICS/webcal feed |
|
|
151
|
+
| `list-external-calendars` | List subscribed feeds |
|
|
152
|
+
| `remove-external-calendar` | Remove a subscribed feed |
|
|
153
|
+
| `update-external-calendars` | Update subscribed feeds |
|
|
56
154
|
|
|
57
|
-
|
|
58
|
-
- `get-overlay-people`, `update-overlay-people` — other people's calendars pinned into your view
|
|
155
|
+
### People & overlays
|
|
59
156
|
|
|
60
|
-
|
|
157
|
+
| Action | What it does |
|
|
158
|
+
| --- | --- |
|
|
159
|
+
| `search-people` | Search Google Contacts and the Workspace directory |
|
|
160
|
+
| `get-overlay-people` | Read the other people whose calendars are pinned into your view |
|
|
161
|
+
| `update-overlay-people` | Update the other people whose calendars are pinned into your view |
|
|
61
162
|
|
|
62
|
-
|
|
163
|
+
### Zoom
|
|
63
164
|
|
|
64
|
-
|
|
165
|
+
| Action | What it does |
|
|
166
|
+
| --- | --- |
|
|
167
|
+
| `get-zoom-status` | Read the current user's Zoom connection status. Connect and disconnect happen through `/_agent-native/zoom/*` routes, not an action, since OAuth needs the signed-in browser session |
|
|
65
168
|
|
|
66
|
-
|
|
67
|
-
- `sync-google-calendar` — forces a resync
|
|
169
|
+
### Google Calendar connection & sync
|
|
68
170
|
|
|
69
|
-
|
|
171
|
+
| Action | What it does |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| `connect-google-calendar` | Return the OAuth connect URL for the signed-in browser session |
|
|
174
|
+
| `sync-google-calendar` | Force a resync |
|
|
70
175
|
|
|
71
|
-
|
|
72
|
-
- `update-calendar-visual-preferences` — local-only display prefs (event colors, hidden weekends); never touches Google Calendar
|
|
176
|
+
### Settings & preferences
|
|
73
177
|
|
|
74
|
-
|
|
178
|
+
| Action | What it does |
|
|
179
|
+
| --- | --- |
|
|
180
|
+
| `get-settings` | Read user-level settings |
|
|
181
|
+
| `update-settings` | Update user-level settings |
|
|
182
|
+
| `update-calendar-visual-preferences` | Update local-only display preferences (event colors, hidden weekends). Never touches Google Calendar |
|
|
75
183
|
|
|
76
|
-
|
|
77
|
-
- `view-screen` — reads the current view back for the agent
|
|
184
|
+
### Navigation & UI state
|
|
78
185
|
|
|
79
|
-
|
|
186
|
+
| Action | What it does |
|
|
187
|
+
| --- | --- |
|
|
188
|
+
| `navigate` | Move the UI to a view, date, or event |
|
|
189
|
+
| `view-screen` | Read the current view back for the agent |
|
|
80
190
|
|
|
81
|
-
|
|
82
|
-
|
|
191
|
+
### Provider API escalation
|
|
192
|
+
|
|
193
|
+
The raw Google Calendar (and connected CRM) API, for when the actions above are too narrow.
|
|
194
|
+
|
|
195
|
+
| Action | What it does |
|
|
196
|
+
| --- | --- |
|
|
197
|
+
| `provider-api-catalog` | List the raw provider APIs available to call directly |
|
|
198
|
+
| `provider-api-docs` | Read documentation for a raw provider API endpoint |
|
|
199
|
+
| `provider-api-request` | Call the raw Google Calendar (or connected CRM) API directly |
|
|
200
|
+
| `list-staged-datasets` | List large scans staged for querying instead of returning raw results |
|
|
201
|
+
| `query-staged-dataset` | Query a staged dataset |
|
|
202
|
+
| `delete-staged-dataset` | Delete a staged dataset |
|
|
83
203
|
|
|
84
204
|
## Data model
|
|
85
205
|
|
|
@@ -246,7 +366,7 @@ Availability rules live in per-user settings under the `calendar-availability` k
|
|
|
246
366
|
|
|
247
367
|
## An action walked through
|
|
248
368
|
|
|
249
|
-
`create-booking-link` shows
|
|
369
|
+
`create-booking-link` shows patterns worth reusing in any action: validating input before it touches the database, enforcing a rule across two tables, safely resolving the signed-in user, and normalizing a flexible input shape once instead of in every reader.
|
|
250
370
|
|
|
251
371
|
<AnnotatedCode
|
|
252
372
|
id="doc-block-calendar8"
|
|
@@ -258,7 +378,7 @@ Availability rules live in per-user settings under the `calendar-availability` k
|
|
|
258
378
|
}
|
|
259
379
|
annotations={[
|
|
260
380
|
{
|
|
261
|
-
lines: "
|
|
381
|
+
lines: "37-41",
|
|
262
382
|
label: "Slug format is validated up front",
|
|
263
383
|
note: "The regex enforces lowercase, hyphen-separated URL slugs before anything touches the database, so a malformed slug never reaches the uniqueness check below.",
|
|
264
384
|
},
|
|
@@ -272,6 +392,11 @@ Availability rules live in per-user settings under the `calendar-availability` k
|
|
|
272
392
|
label: "A slug must be free in two tables",
|
|
273
393
|
note: "A new slug has to be unused in both `booking_links` and `booking_slug_redirects` — otherwise a fresh link could silently claim a URL an older, renamed link still forwards visitors from.",
|
|
274
394
|
},
|
|
395
|
+
{
|
|
396
|
+
lines: "94-98",
|
|
397
|
+
label: "The signed-in user is resolved once, and narrowed",
|
|
398
|
+
note: "`getRequestUserEmail()` returns `string | undefined`, since there's technically no signed-in user for an unauthenticated call. Wrapping it in an immediately-invoked function lets the action throw right there if that ever happens, so `ownerEmail` is a plain `string` for the rest of the function instead of something every later line would have to re-check.",
|
|
399
|
+
},
|
|
275
400
|
{
|
|
276
401
|
lines: "110",
|
|
277
402
|
label: "Co-host input is normalized once",
|
|
@@ -359,8 +484,8 @@ If you add a feature, remember to update all four areas: UI, action, skill or AG
|
|
|
359
484
|
## What's next
|
|
360
485
|
|
|
361
486
|
- [**Calendar**](/docs/template-calendar) — the overview and getting-started steps
|
|
362
|
-
- [**
|
|
363
|
-
- [**
|
|
364
|
-
- [**
|
|
487
|
+
- [**Features**](/docs/template-calendar-features) — the user-facing behavior these actions and this data model power
|
|
488
|
+
- [**Talk to the Agent**](/docs/template-calendar-agent) — how the agent chooses between these actions and the raw Google Calendar API
|
|
489
|
+
- [**Calendar in a Multi-App Workspace**](/docs/template-calendar-integrations) — how these actions get exposed to other apps and Dispatch
|
|
365
490
|
- [**Actions**](/docs/actions-overview) — the action system this template is built on
|
|
366
491
|
- [**Sharing**](/docs/sharing) — the share-grant model `booking_link_shares` uses
|