@agent-native/core 0.161.16 → 0.161.20
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/analytics/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/analytics/AGENTS.md +1 -0
- package/corpus/templates/analytics/server/plugins/auth.ts +4 -0
- package/corpus/templates/assets/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/assets/AGENTS.md +1 -0
- package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/brain/AGENTS.md +1 -0
- package/corpus/templates/calendar/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/calendar/AGENTS.md +1 -0
- package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/chat/AGENTS.md +4 -0
- package/corpus/templates/chat/vitest.config.ts +12 -7
- package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/clips/AGENTS.md +1 -0
- package/corpus/templates/clips/app/components/player/video-player.tsx +4 -0
- package/corpus/templates/clips/app/hooks/use-playback-position.ts +10 -2
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +1 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +26 -25
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +1 -0
- package/corpus/templates/clips/changelog/2026-08-18-clips-no-longer-opens-welcome-window-on-first-launch.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-18-clips-now-recovers-interrupted-uploads-and-reliably-restarts.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-18-meeting-notifications-no-longer-show-decorative-left-side-lines.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-18-pending-recording-files-now-use-a-clips-prefixed-name.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/updater.ts +21 -1
- package/corpus/templates/clips/desktop/src/main.tsx +0 -3
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +0 -4
- package/corpus/templates/clips/desktop/src/shared/config.ts +0 -1
- package/corpus/templates/clips/desktop/src/styles.css +0 -136
- package/corpus/templates/clips/desktop/src-tauri/capabilities/default.json +0 -1
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +0 -45
- package/corpus/templates/clips/desktop/src-tauri/src/config.rs +1 -4
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +3 -11
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +63 -8
- package/corpus/templates/clips/desktop/src-tauri/src/util.rs +98 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +54 -20
- package/corpus/templates/content/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/content/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/content/AGENTS.md +1 -0
- package/corpus/templates/crm/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/crm/AGENTS.md +1 -0
- package/corpus/templates/design/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/design/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/design/AGENTS.md +1 -0
- package/corpus/templates/design/app/global.css +6 -0
- package/corpus/templates/design/app/i18n-data.ts +11 -0
- package/corpus/templates/design/app/lib/agent-chat.ts +9 -8
- package/corpus/templates/design/app/root.tsx +1 -1
- package/corpus/templates/design/changelog/2026-08-18-design-chat-context-stays-out-of-the-composer.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/dispatch/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/dispatch/AGENTS.md +5 -5
- package/corpus/templates/factory/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/factory/AGENTS.md +1 -0
- package/corpus/templates/forms/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/forms/AGENTS.md +1 -0
- package/corpus/templates/macros/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/macros/AGENTS.md +1 -0
- package/corpus/templates/mail/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/mail/AGENTS.md +1 -0
- package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/plan/AGENTS.md +1 -0
- package/corpus/templates/slides/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/slides/AGENTS.md +2 -1
- package/corpus/templates/tasks/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +29 -2
- package/corpus/templates/tasks/AGENTS.md +1 -0
- package/dist/action.d.ts +1 -0
- package/dist/action.js +44 -2
- package/dist/agent/production-agent.js +28 -5
- package/dist/client/chat/run-recovery.js +1 -1
- package/dist/client/route-state.js +17 -13
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.d.ts +6 -0
- package/dist/server/auth.js +23 -5
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/templates/chat/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/dist/templates/chat/.agents/skills/secrets/SKILL.md +29 -2
- package/dist/templates/chat/AGENTS.md +4 -0
- package/dist/templates/chat/vitest.config.ts +12 -7
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/dist/templates/default/.agents/skills/secrets/SKILL.md +29 -2
- package/dist/templates/default/AGENTS.md +4 -0
- package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/dist/templates/headless/.agents/skills/secrets/SKILL.md +29 -2
- package/dist/templates/headless/AGENTS.md +4 -0
- package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +29 -2
- package/dist/templates/workspace-core/AGENTS.md +4 -0
- package/dist/templates/workspace-root/AGENTS.md +9 -0
- package/docs/content/deployment.mdx +70 -0
- package/docs/content/faq.mdx +1 -1
- package/package.json +1 -1
- package/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/src/templates/chat/.agents/skills/secrets/SKILL.md +29 -2
- package/src/templates/chat/AGENTS.md +4 -0
- package/src/templates/chat/vitest.config.ts +12 -7
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/src/templates/default/.agents/skills/secrets/SKILL.md +29 -2
- package/src/templates/default/AGENTS.md +4 -0
- package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/src/templates/headless/.agents/skills/secrets/SKILL.md +29 -2
- package/src/templates/headless/AGENTS.md +4 -0
- package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +10 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +24 -0
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +29 -2
- package/src/templates/workspace-core/AGENTS.md +4 -0
- package/src/templates/workspace-root/AGENTS.md +9 -0
- package/corpus/templates/clips/desktop/src/overlays/onboarding.tsx +0 -314
|
@@ -152,6 +152,30 @@ preference, notification preference, or usage/billing surface, register it as a
|
|
|
152
152
|
settings tab or app settings panel first. Only add sidebar UI when it is needed
|
|
153
153
|
in the moment of agent use.
|
|
154
154
|
|
|
155
|
+
## Integration Setup Preflight
|
|
156
|
+
|
|
157
|
+
Before building any setup, settings, credential, OAuth, or connection surface,
|
|
158
|
+
search the workspace/provider connection catalog first. If the provider already
|
|
159
|
+
has a reusable connection, use its catalog, app grant, and scoped credential
|
|
160
|
+
resolver rather than registering a parallel secret. Only then classify fields
|
|
161
|
+
that still need app-local setup by lifecycle and scope:
|
|
162
|
+
|
|
163
|
+
| Need | Default primitive |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| Deploy- or app-level configuration | Runtime configuration or deployment env vars |
|
|
166
|
+
| Existing workspace/provider connection | Workspace-connection catalog/grant plus `resolveWorkspaceConnectionCredential(s)ForApp` |
|
|
167
|
+
| App-local API/service key with no reusable connection | `registerRequiredSecret({ kind: "api-key" })` and the vault |
|
|
168
|
+
| Authorization-code or refresh-token flow | `kind: "oauth"` with `@agent-native/core/oauth-tokens` |
|
|
169
|
+
| Account, customer, or other non-secret identifiers | Scoped connection metadata or app data |
|
|
170
|
+
| Provider-specific prerequisites, sequencing, or health | A thin app-local guide over the shared primitives |
|
|
171
|
+
|
|
172
|
+
Do not register every provider field as a generic secret, mark every field as
|
|
173
|
+
required, or create a second credential-management surface. One logical
|
|
174
|
+
connection should normally produce one onboarding outcome. A custom setup page
|
|
175
|
+
is appropriate only when it adds domain-specific guidance or readiness checks;
|
|
176
|
+
it should link to or call the shared settings, OAuth, and action surfaces rather
|
|
177
|
+
than duplicating their storage or transport.
|
|
178
|
+
|
|
155
179
|
## Reusable Kits
|
|
156
180
|
|
|
157
181
|
- **Settings kit**: a searchable settings page with account, workspace, AI
|
|
@@ -3,8 +3,8 @@ name: secrets
|
|
|
3
3
|
description: >-
|
|
4
4
|
Declaratively register API keys and service credentials a template needs so
|
|
5
5
|
they appear in the agent sidebar settings UI and the onboarding checklist.
|
|
6
|
-
Use
|
|
7
|
-
|
|
6
|
+
Use before adding any third-party credential or setup UI so API keys, OAuth
|
|
7
|
+
connections, and scoped configuration use the correct shared primitive.
|
|
8
8
|
scope: dev
|
|
9
9
|
metadata:
|
|
10
10
|
internal: true
|
|
@@ -24,6 +24,33 @@ encrypted `app_secrets` vault, `saveCredential` / `resolveCredential`, OAuth, or
|
|
|
24
24
|
`${keys.NAME}` substitution. Examples must use obvious placeholders such as
|
|
25
25
|
`<OPENAI_API_KEY>` or `${keys.SLACK_WEBHOOK}`, not real-looking copied values.
|
|
26
26
|
|
|
27
|
+
## Credential Modeling Preflight
|
|
28
|
+
|
|
29
|
+
Before registering a provider's fields, inspect the workspace/provider connection
|
|
30
|
+
catalog first. If a reusable connection exists, use its app grant and scoped
|
|
31
|
+
`resolveWorkspaceConnectionCredential(s)ForApp` path instead of registering a
|
|
32
|
+
parallel secret. Only classify fields for app-local setup when no reusable
|
|
33
|
+
connection exists:
|
|
34
|
+
|
|
35
|
+
- **API or service key** - register it as `kind: "api-key"` with the narrowest
|
|
36
|
+
correct `scope`, a human label, a description, a docs link, and a validator.
|
|
37
|
+
- **OAuth authorization or refresh token** - use the OAuth token store and
|
|
38
|
+
register a `kind: "oauth"` entry so the shared UI renders Connect and the
|
|
39
|
+
runtime owns status, refresh, and reauthorization.
|
|
40
|
+
- **Deploy- or app-level configuration** - use deployment/runtime
|
|
41
|
+
configuration, not a per-user secret row.
|
|
42
|
+
- **Account, customer, manager, or other non-secret identifier** - store it as
|
|
43
|
+
scoped connection metadata or app data, not as a masked secret field.
|
|
44
|
+
|
|
45
|
+
`required: true` is for a logical setup requirement. If a provider needs
|
|
46
|
+
several values, do not automatically create one required checklist item per
|
|
47
|
+
field; use one composite onboarding step or a registered connection readiness
|
|
48
|
+
check.
|
|
49
|
+
|
|
50
|
+
Custom setup UI is allowed for provider-specific prerequisites, ordering, or
|
|
51
|
+
health checks, but it must delegate credential storage and connection state to
|
|
52
|
+
the shared vault/OAuth/settings surfaces.
|
|
53
|
+
|
|
27
54
|
## When to use
|
|
28
55
|
|
|
29
56
|
Use this for any external credential your template needs: API keys, service
|
|
@@ -56,6 +56,7 @@ Read the relevant skill before deeper work:
|
|
|
56
56
|
- Never hardcode API keys, tokens, webhook URLs, signing secrets, private
|
|
57
57
|
Builder/internal data, customer data, or credential-looking literals. Use
|
|
58
58
|
secrets/OAuth/runtime configuration and obvious placeholders in examples.
|
|
59
|
+
- For external integrations, inspect the workspace/provider connection catalog first; reuse its scoped resolver.
|
|
59
60
|
|
|
60
61
|
## Action Map
|
|
61
62
|
|
|
@@ -76,6 +76,16 @@ Builder/internal data, or customer data in the action, UI, seed data, fixtures,
|
|
|
76
76
|
docs, prompts, or generated extension/app content. Register required secrets,
|
|
77
77
|
use OAuth helpers, or read scoped values from the vault/credential store.
|
|
78
78
|
|
|
79
|
+
Before writing custom setup or credential UI, perform the shared-primitive
|
|
80
|
+
preflight from `agent-native-toolkit`: inspect the workspace/provider connection
|
|
81
|
+
catalog first, then settings, secrets/vault, OAuth, onboarding, and provider API
|
|
82
|
+
support. Reuse an existing connection's app grant and scoped credential
|
|
83
|
+
resolver; only use app-local vault or OAuth primitives when no reusable
|
|
84
|
+
connection exists. Keep any wizard thin and provider-specific - it may explain
|
|
85
|
+
prerequisites, ordering, or readiness, but must not become a second vault or
|
|
86
|
+
custom credential transport. Do not mark each field `required` by reflex;
|
|
87
|
+
model onboarding around the logical connection outcome.
|
|
88
|
+
|
|
79
89
|
If the feature involves attachments, images, recordings, screenshots, exports,
|
|
80
90
|
or other file-like payloads, design the upload path in the same change:
|
|
81
91
|
provider upload first, then URL/id/blob handle in SQL. Do not add base64/binary
|
|
@@ -152,6 +152,30 @@ preference, notification preference, or usage/billing surface, register it as a
|
|
|
152
152
|
settings tab or app settings panel first. Only add sidebar UI when it is needed
|
|
153
153
|
in the moment of agent use.
|
|
154
154
|
|
|
155
|
+
## Integration Setup Preflight
|
|
156
|
+
|
|
157
|
+
Before building any setup, settings, credential, OAuth, or connection surface,
|
|
158
|
+
search the workspace/provider connection catalog first. If the provider already
|
|
159
|
+
has a reusable connection, use its catalog, app grant, and scoped credential
|
|
160
|
+
resolver rather than registering a parallel secret. Only then classify fields
|
|
161
|
+
that still need app-local setup by lifecycle and scope:
|
|
162
|
+
|
|
163
|
+
| Need | Default primitive |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| Deploy- or app-level configuration | Runtime configuration or deployment env vars |
|
|
166
|
+
| Existing workspace/provider connection | Workspace-connection catalog/grant plus `resolveWorkspaceConnectionCredential(s)ForApp` |
|
|
167
|
+
| App-local API/service key with no reusable connection | `registerRequiredSecret({ kind: "api-key" })` and the vault |
|
|
168
|
+
| Authorization-code or refresh-token flow | `kind: "oauth"` with `@agent-native/core/oauth-tokens` |
|
|
169
|
+
| Account, customer, or other non-secret identifiers | Scoped connection metadata or app data |
|
|
170
|
+
| Provider-specific prerequisites, sequencing, or health | A thin app-local guide over the shared primitives |
|
|
171
|
+
|
|
172
|
+
Do not register every provider field as a generic secret, mark every field as
|
|
173
|
+
required, or create a second credential-management surface. One logical
|
|
174
|
+
connection should normally produce one onboarding outcome. A custom setup page
|
|
175
|
+
is appropriate only when it adds domain-specific guidance or readiness checks;
|
|
176
|
+
it should link to or call the shared settings, OAuth, and action surfaces rather
|
|
177
|
+
than duplicating their storage or transport.
|
|
178
|
+
|
|
155
179
|
## Reusable Kits
|
|
156
180
|
|
|
157
181
|
- **Settings kit**: a searchable settings page with account, workspace, AI
|
|
@@ -3,8 +3,8 @@ name: secrets
|
|
|
3
3
|
description: >-
|
|
4
4
|
Declaratively register API keys and service credentials a template needs so
|
|
5
5
|
they appear in the agent sidebar settings UI and the onboarding checklist.
|
|
6
|
-
Use
|
|
7
|
-
|
|
6
|
+
Use before adding any third-party credential or setup UI so API keys, OAuth
|
|
7
|
+
connections, and scoped configuration use the correct shared primitive.
|
|
8
8
|
scope: dev
|
|
9
9
|
metadata:
|
|
10
10
|
internal: true
|
|
@@ -24,6 +24,33 @@ encrypted `app_secrets` vault, `saveCredential` / `resolveCredential`, OAuth, or
|
|
|
24
24
|
`${keys.NAME}` substitution. Examples must use obvious placeholders such as
|
|
25
25
|
`<OPENAI_API_KEY>` or `${keys.SLACK_WEBHOOK}`, not real-looking copied values.
|
|
26
26
|
|
|
27
|
+
## Credential Modeling Preflight
|
|
28
|
+
|
|
29
|
+
Before registering a provider's fields, inspect the workspace/provider connection
|
|
30
|
+
catalog first. If a reusable connection exists, use its app grant and scoped
|
|
31
|
+
`resolveWorkspaceConnectionCredential(s)ForApp` path instead of registering a
|
|
32
|
+
parallel secret. Only classify fields for app-local setup when no reusable
|
|
33
|
+
connection exists:
|
|
34
|
+
|
|
35
|
+
- **API or service key** - register it as `kind: "api-key"` with the narrowest
|
|
36
|
+
correct `scope`, a human label, a description, a docs link, and a validator.
|
|
37
|
+
- **OAuth authorization or refresh token** - use the OAuth token store and
|
|
38
|
+
register a `kind: "oauth"` entry so the shared UI renders Connect and the
|
|
39
|
+
runtime owns status, refresh, and reauthorization.
|
|
40
|
+
- **Deploy- or app-level configuration** - use deployment/runtime
|
|
41
|
+
configuration, not a per-user secret row.
|
|
42
|
+
- **Account, customer, manager, or other non-secret identifier** - store it as
|
|
43
|
+
scoped connection metadata or app data, not as a masked secret field.
|
|
44
|
+
|
|
45
|
+
`required: true` is for a logical setup requirement. If a provider needs
|
|
46
|
+
several values, do not automatically create one required checklist item per
|
|
47
|
+
field; use one composite onboarding step or a registered connection readiness
|
|
48
|
+
check.
|
|
49
|
+
|
|
50
|
+
Custom setup UI is allowed for provider-specific prerequisites, ordering, or
|
|
51
|
+
health checks, but it must delegate credential storage and connection state to
|
|
52
|
+
the shared vault/OAuth/settings surfaces.
|
|
53
|
+
|
|
27
54
|
## When to use
|
|
28
55
|
|
|
29
56
|
Use this for any external credential your template needs: API keys, service
|
|
@@ -36,6 +36,7 @@ generating or editing a plan.
|
|
|
36
36
|
- Never hardcode API keys, tokens, webhook URLs, signing secrets, private
|
|
37
37
|
Builder/internal data, customer data, or credential-looking literals. Use
|
|
38
38
|
secrets/OAuth/runtime configuration and obvious placeholders in examples.
|
|
39
|
+
- For external integrations, inspect the workspace/provider connection catalog first; reuse its scoped resolver.
|
|
39
40
|
- Use `view-screen` or application state when the active page/selection is
|
|
40
41
|
unclear.
|
|
41
42
|
- Default to structured visual artifacts over long Markdown. Text is one block
|
|
@@ -76,6 +76,16 @@ Builder/internal data, or customer data in the action, UI, seed data, fixtures,
|
|
|
76
76
|
docs, prompts, or generated extension/app content. Register required secrets,
|
|
77
77
|
use OAuth helpers, or read scoped values from the vault/credential store.
|
|
78
78
|
|
|
79
|
+
Before writing custom setup or credential UI, perform the shared-primitive
|
|
80
|
+
preflight from `agent-native-toolkit`: inspect the workspace/provider connection
|
|
81
|
+
catalog first, then settings, secrets/vault, OAuth, onboarding, and provider API
|
|
82
|
+
support. Reuse an existing connection's app grant and scoped credential
|
|
83
|
+
resolver; only use app-local vault or OAuth primitives when no reusable
|
|
84
|
+
connection exists. Keep any wizard thin and provider-specific - it may explain
|
|
85
|
+
prerequisites, ordering, or readiness, but must not become a second vault or
|
|
86
|
+
custom credential transport. Do not mark each field `required` by reflex;
|
|
87
|
+
model onboarding around the logical connection outcome.
|
|
88
|
+
|
|
79
89
|
If the feature involves attachments, images, recordings, screenshots, exports,
|
|
80
90
|
or other file-like payloads, design the upload path in the same change:
|
|
81
91
|
provider upload first, then URL/id/blob handle in SQL. Do not add base64/binary
|
|
@@ -152,6 +152,30 @@ preference, notification preference, or usage/billing surface, register it as a
|
|
|
152
152
|
settings tab or app settings panel first. Only add sidebar UI when it is needed
|
|
153
153
|
in the moment of agent use.
|
|
154
154
|
|
|
155
|
+
## Integration Setup Preflight
|
|
156
|
+
|
|
157
|
+
Before building any setup, settings, credential, OAuth, or connection surface,
|
|
158
|
+
search the workspace/provider connection catalog first. If the provider already
|
|
159
|
+
has a reusable connection, use its catalog, app grant, and scoped credential
|
|
160
|
+
resolver rather than registering a parallel secret. Only then classify fields
|
|
161
|
+
that still need app-local setup by lifecycle and scope:
|
|
162
|
+
|
|
163
|
+
| Need | Default primitive |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| Deploy- or app-level configuration | Runtime configuration or deployment env vars |
|
|
166
|
+
| Existing workspace/provider connection | Workspace-connection catalog/grant plus `resolveWorkspaceConnectionCredential(s)ForApp` |
|
|
167
|
+
| App-local API/service key with no reusable connection | `registerRequiredSecret({ kind: "api-key" })` and the vault |
|
|
168
|
+
| Authorization-code or refresh-token flow | `kind: "oauth"` with `@agent-native/core/oauth-tokens` |
|
|
169
|
+
| Account, customer, or other non-secret identifiers | Scoped connection metadata or app data |
|
|
170
|
+
| Provider-specific prerequisites, sequencing, or health | A thin app-local guide over the shared primitives |
|
|
171
|
+
|
|
172
|
+
Do not register every provider field as a generic secret, mark every field as
|
|
173
|
+
required, or create a second credential-management surface. One logical
|
|
174
|
+
connection should normally produce one onboarding outcome. A custom setup page
|
|
175
|
+
is appropriate only when it adds domain-specific guidance or readiness checks;
|
|
176
|
+
it should link to or call the shared settings, OAuth, and action surfaces rather
|
|
177
|
+
than duplicating their storage or transport.
|
|
178
|
+
|
|
155
179
|
## Reusable Kits
|
|
156
180
|
|
|
157
181
|
- **Settings kit**: a searchable settings page with account, workspace, AI
|
|
@@ -3,8 +3,8 @@ name: secrets
|
|
|
3
3
|
description: >-
|
|
4
4
|
Declaratively register API keys and service credentials a template needs so
|
|
5
5
|
they appear in the agent sidebar settings UI and the onboarding checklist.
|
|
6
|
-
Use
|
|
7
|
-
|
|
6
|
+
Use before adding any third-party credential or setup UI so API keys, OAuth
|
|
7
|
+
connections, and scoped configuration use the correct shared primitive.
|
|
8
8
|
scope: dev
|
|
9
9
|
metadata:
|
|
10
10
|
internal: true
|
|
@@ -24,6 +24,33 @@ encrypted `app_secrets` vault, `saveCredential` / `resolveCredential`, OAuth, or
|
|
|
24
24
|
`${keys.NAME}` substitution. Examples must use obvious placeholders such as
|
|
25
25
|
`<OPENAI_API_KEY>` or `${keys.SLACK_WEBHOOK}`, not real-looking copied values.
|
|
26
26
|
|
|
27
|
+
## Credential Modeling Preflight
|
|
28
|
+
|
|
29
|
+
Before registering a provider's fields, inspect the workspace/provider connection
|
|
30
|
+
catalog first. If a reusable connection exists, use its app grant and scoped
|
|
31
|
+
`resolveWorkspaceConnectionCredential(s)ForApp` path instead of registering a
|
|
32
|
+
parallel secret. Only classify fields for app-local setup when no reusable
|
|
33
|
+
connection exists:
|
|
34
|
+
|
|
35
|
+
- **API or service key** - register it as `kind: "api-key"` with the narrowest
|
|
36
|
+
correct `scope`, a human label, a description, a docs link, and a validator.
|
|
37
|
+
- **OAuth authorization or refresh token** - use the OAuth token store and
|
|
38
|
+
register a `kind: "oauth"` entry so the shared UI renders Connect and the
|
|
39
|
+
runtime owns status, refresh, and reauthorization.
|
|
40
|
+
- **Deploy- or app-level configuration** - use deployment/runtime
|
|
41
|
+
configuration, not a per-user secret row.
|
|
42
|
+
- **Account, customer, manager, or other non-secret identifier** - store it as
|
|
43
|
+
scoped connection metadata or app data, not as a masked secret field.
|
|
44
|
+
|
|
45
|
+
`required: true` is for a logical setup requirement. If a provider needs
|
|
46
|
+
several values, do not automatically create one required checklist item per
|
|
47
|
+
field; use one composite onboarding step or a registered connection readiness
|
|
48
|
+
check.
|
|
49
|
+
|
|
50
|
+
Custom setup UI is allowed for provider-specific prerequisites, ordering, or
|
|
51
|
+
health checks, but it must delegate credential storage and connection state to
|
|
52
|
+
the shared vault/OAuth/settings surfaces.
|
|
53
|
+
|
|
27
54
|
## When to use
|
|
28
55
|
|
|
29
56
|
Use this for any external credential your template needs: API keys, service
|
|
@@ -23,6 +23,7 @@ Read the relevant skill before deeper work:
|
|
|
23
23
|
resources; persist only URLs, ids, or handles.
|
|
24
24
|
- Never hardcode secrets or private/customer data; use vault/OAuth/runtime
|
|
25
25
|
configuration and fake placeholders in examples.
|
|
26
|
+
- For external integrations, inspect the workspace/provider connection catalog first; reuse its scoped resolver.
|
|
26
27
|
- Use actions for deck lifecycle, slide edits, imports, exports, images, design
|
|
27
28
|
systems, and sharing. Do not write deck/slide rows directly. Read the action
|
|
28
29
|
schema if a parameter is unclear.
|
|
@@ -44,7 +45,7 @@ Read the relevant skill before deeper work:
|
|
|
44
45
|
within tolerance; hold Cmd/Ctrl to bypass snapping. With 2+ compatible
|
|
45
46
|
selected objects, use the contextual toolbar to align to selection bounds;
|
|
46
47
|
distribute only when 3+ objects are selected.
|
|
47
|
-
- Follow linked design-system tokens
|
|
48
|
+
- Follow linked design-system tokens.
|
|
48
49
|
- Import/export actions are shortcuts, not capability limits. For exact Google
|
|
49
50
|
Drive API needs, use `provider-api-catalog`, `provider-api-docs`, and
|
|
50
51
|
`provider-api-request`; auth comes from the user's Google Docs OAuth. Stage
|
|
@@ -76,6 +76,16 @@ Builder/internal data, or customer data in the action, UI, seed data, fixtures,
|
|
|
76
76
|
docs, prompts, or generated extension/app content. Register required secrets,
|
|
77
77
|
use OAuth helpers, or read scoped values from the vault/credential store.
|
|
78
78
|
|
|
79
|
+
Before writing custom setup or credential UI, perform the shared-primitive
|
|
80
|
+
preflight from `agent-native-toolkit`: inspect the workspace/provider connection
|
|
81
|
+
catalog first, then settings, secrets/vault, OAuth, onboarding, and provider API
|
|
82
|
+
support. Reuse an existing connection's app grant and scoped credential
|
|
83
|
+
resolver; only use app-local vault or OAuth primitives when no reusable
|
|
84
|
+
connection exists. Keep any wizard thin and provider-specific - it may explain
|
|
85
|
+
prerequisites, ordering, or readiness, but must not become a second vault or
|
|
86
|
+
custom credential transport. Do not mark each field `required` by reflex;
|
|
87
|
+
model onboarding around the logical connection outcome.
|
|
88
|
+
|
|
79
89
|
If the feature involves attachments, images, recordings, screenshots, exports,
|
|
80
90
|
or other file-like payloads, design the upload path in the same change:
|
|
81
91
|
provider upload first, then URL/id/blob handle in SQL. Do not add base64/binary
|
|
@@ -152,6 +152,30 @@ preference, notification preference, or usage/billing surface, register it as a
|
|
|
152
152
|
settings tab or app settings panel first. Only add sidebar UI when it is needed
|
|
153
153
|
in the moment of agent use.
|
|
154
154
|
|
|
155
|
+
## Integration Setup Preflight
|
|
156
|
+
|
|
157
|
+
Before building any setup, settings, credential, OAuth, or connection surface,
|
|
158
|
+
search the workspace/provider connection catalog first. If the provider already
|
|
159
|
+
has a reusable connection, use its catalog, app grant, and scoped credential
|
|
160
|
+
resolver rather than registering a parallel secret. Only then classify fields
|
|
161
|
+
that still need app-local setup by lifecycle and scope:
|
|
162
|
+
|
|
163
|
+
| Need | Default primitive |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| Deploy- or app-level configuration | Runtime configuration or deployment env vars |
|
|
166
|
+
| Existing workspace/provider connection | Workspace-connection catalog/grant plus `resolveWorkspaceConnectionCredential(s)ForApp` |
|
|
167
|
+
| App-local API/service key with no reusable connection | `registerRequiredSecret({ kind: "api-key" })` and the vault |
|
|
168
|
+
| Authorization-code or refresh-token flow | `kind: "oauth"` with `@agent-native/core/oauth-tokens` |
|
|
169
|
+
| Account, customer, or other non-secret identifiers | Scoped connection metadata or app data |
|
|
170
|
+
| Provider-specific prerequisites, sequencing, or health | A thin app-local guide over the shared primitives |
|
|
171
|
+
|
|
172
|
+
Do not register every provider field as a generic secret, mark every field as
|
|
173
|
+
required, or create a second credential-management surface. One logical
|
|
174
|
+
connection should normally produce one onboarding outcome. A custom setup page
|
|
175
|
+
is appropriate only when it adds domain-specific guidance or readiness checks;
|
|
176
|
+
it should link to or call the shared settings, OAuth, and action surfaces rather
|
|
177
|
+
than duplicating their storage or transport.
|
|
178
|
+
|
|
155
179
|
## Reusable Kits
|
|
156
180
|
|
|
157
181
|
- **Settings kit**: a searchable settings page with account, workspace, AI
|
|
@@ -3,8 +3,8 @@ name: secrets
|
|
|
3
3
|
description: >-
|
|
4
4
|
Declaratively register API keys and service credentials a template needs so
|
|
5
5
|
they appear in the agent sidebar settings UI and the onboarding checklist.
|
|
6
|
-
Use
|
|
7
|
-
|
|
6
|
+
Use before adding any third-party credential or setup UI so API keys, OAuth
|
|
7
|
+
connections, and scoped configuration use the correct shared primitive.
|
|
8
8
|
scope: dev
|
|
9
9
|
metadata:
|
|
10
10
|
internal: true
|
|
@@ -24,6 +24,33 @@ encrypted `app_secrets` vault, `saveCredential` / `resolveCredential`, OAuth, or
|
|
|
24
24
|
`${keys.NAME}` substitution. Examples must use obvious placeholders such as
|
|
25
25
|
`<OPENAI_API_KEY>` or `${keys.SLACK_WEBHOOK}`, not real-looking copied values.
|
|
26
26
|
|
|
27
|
+
## Credential Modeling Preflight
|
|
28
|
+
|
|
29
|
+
Before registering a provider's fields, inspect the workspace/provider connection
|
|
30
|
+
catalog first. If a reusable connection exists, use its app grant and scoped
|
|
31
|
+
`resolveWorkspaceConnectionCredential(s)ForApp` path instead of registering a
|
|
32
|
+
parallel secret. Only classify fields for app-local setup when no reusable
|
|
33
|
+
connection exists:
|
|
34
|
+
|
|
35
|
+
- **API or service key** - register it as `kind: "api-key"` with the narrowest
|
|
36
|
+
correct `scope`, a human label, a description, a docs link, and a validator.
|
|
37
|
+
- **OAuth authorization or refresh token** - use the OAuth token store and
|
|
38
|
+
register a `kind: "oauth"` entry so the shared UI renders Connect and the
|
|
39
|
+
runtime owns status, refresh, and reauthorization.
|
|
40
|
+
- **Deploy- or app-level configuration** - use deployment/runtime
|
|
41
|
+
configuration, not a per-user secret row.
|
|
42
|
+
- **Account, customer, manager, or other non-secret identifier** - store it as
|
|
43
|
+
scoped connection metadata or app data, not as a masked secret field.
|
|
44
|
+
|
|
45
|
+
`required: true` is for a logical setup requirement. If a provider needs
|
|
46
|
+
several values, do not automatically create one required checklist item per
|
|
47
|
+
field; use one composite onboarding step or a registered connection readiness
|
|
48
|
+
check.
|
|
49
|
+
|
|
50
|
+
Custom setup UI is allowed for provider-specific prerequisites, ordering, or
|
|
51
|
+
health checks, but it must delegate credential storage and connection state to
|
|
52
|
+
the shared vault/OAuth/settings surfaces.
|
|
53
|
+
|
|
27
54
|
## When to use
|
|
28
55
|
|
|
29
56
|
Use this for any external credential your template needs: API keys, service
|
|
@@ -14,6 +14,7 @@ Read the matching skill before acting. This file is the always-on layer; the ski
|
|
|
14
14
|
## Core Rules
|
|
15
15
|
|
|
16
16
|
- Never hardcode API keys, tokens, webhook URLs, signing secrets, private Builder/internal data, customer data, or credential-looking literals. Use secrets/OAuth/runtime configuration and obvious placeholders in examples.
|
|
17
|
+
- For external integrations, inspect the workspace/provider connection catalog first; reuse its scoped resolver.
|
|
17
18
|
- Follow the root framework contract: data in SQL, actions first, application state for navigation/selection, and shared agent chat for AI work.
|
|
18
19
|
- Do not use `db-query` for normal task operations.
|
|
19
20
|
- Call `view-screen` first when the user's visible task context matters (especially on `/tasks`).
|
package/dist/action.d.ts
CHANGED
|
@@ -706,6 +706,7 @@ export interface ActionDefinition<TInput, TReturn> {
|
|
|
706
706
|
*/
|
|
707
707
|
export declare function defineAction<TSchema extends StandardSchemaV1, TReturn, TOutputSchema extends StandardSchemaV1 | undefined = undefined>(options: DefineActionWithSchema<TSchema, TReturn, TOutputSchema>): ActionDefinition<StandardSchemaV1.InferInput<TSchema>, TReturn>;
|
|
708
708
|
export declare function defineAction<TParams extends Record<string, ParameterSchema> | undefined, TReturn>(options: DefineActionWithParams<TParams, TReturn>): ActionDefinition<InferParams<TParams>, TReturn>;
|
|
709
|
+
export declare function stripUnsupportedSchemaKeywords<T>(node: T): T;
|
|
709
710
|
/**
|
|
710
711
|
* Compact signature of an action's parameters, e.g.
|
|
711
712
|
* `{ deckId*: string, operation*: "edit"|"replace", slideId?: string }` where
|
package/dist/action.js
CHANGED
|
@@ -393,11 +393,53 @@ const TYPE_SUBSTITUTE_KEYS = [
|
|
|
393
393
|
"$ref",
|
|
394
394
|
"not",
|
|
395
395
|
];
|
|
396
|
-
|
|
396
|
+
/**
|
|
397
|
+
* `format` values OpenAI's function-schema validator accepts. Anything else --
|
|
398
|
+
* `uri` from `z.string().url()`, `binary`, `regex`, … -- is answered with
|
|
399
|
+
* "'<x>' is not a valid format" and a 400 for the WHOLE request.
|
|
400
|
+
*
|
|
401
|
+
* Dropping an unknown format only widens what the schema accepts, and the
|
|
402
|
+
* action's own zod schema still validates the value server-side, so nothing is
|
|
403
|
+
* actually loosened. Kept as an allowlist rather than a denylist: a new format
|
|
404
|
+
* we have not heard of should degrade to "unconstrained", not to a 400 that
|
|
405
|
+
* takes every other tool in the payload down with it.
|
|
406
|
+
*/
|
|
407
|
+
const PROVIDER_SUPPORTED_FORMATS = new Set([
|
|
408
|
+
"date-time",
|
|
409
|
+
"time",
|
|
410
|
+
"date",
|
|
411
|
+
"duration",
|
|
412
|
+
"email",
|
|
413
|
+
"hostname",
|
|
414
|
+
"ipv4",
|
|
415
|
+
"ipv6",
|
|
416
|
+
"uuid",
|
|
417
|
+
]);
|
|
418
|
+
/**
|
|
419
|
+
* Keywords that only ever CONSTRAIN a value and that OpenAI's validator rejects
|
|
420
|
+
* outright. Removing a constraint can never make a previously-valid document
|
|
421
|
+
* invalid, so this is safe in a way that rewriting structure would not be.
|
|
422
|
+
*/
|
|
423
|
+
const PROVIDER_REJECTED_KEYWORDS = [
|
|
424
|
+
"propertyNames",
|
|
425
|
+
"patternProperties",
|
|
426
|
+
"dependentSchemas",
|
|
427
|
+
"dependentRequired",
|
|
428
|
+
"if",
|
|
429
|
+
"then",
|
|
430
|
+
"else",
|
|
431
|
+
"not",
|
|
432
|
+
];
|
|
433
|
+
export function stripUnsupportedSchemaKeywords(node) {
|
|
397
434
|
if (!node || typeof node !== "object" || Array.isArray(node))
|
|
398
435
|
return node;
|
|
399
436
|
const obj = node;
|
|
400
|
-
|
|
437
|
+
for (const keyword of PROVIDER_REJECTED_KEYWORDS)
|
|
438
|
+
delete obj[keyword];
|
|
439
|
+
if (typeof obj.format === "string" &&
|
|
440
|
+
!PROVIDER_SUPPORTED_FORMATS.has(obj.format)) {
|
|
441
|
+
delete obj.format;
|
|
442
|
+
}
|
|
401
443
|
for (const key of SUBSCHEMA_VALUE_KEYS) {
|
|
402
444
|
// `items`/`additionalItems` may also be an array of subschemas.
|
|
403
445
|
const value = obj[key];
|
|
@@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import Ajv from "ajv";
|
|
3
3
|
import { defineEventHandler, getHeader, setResponseHeader, setResponseStatus, getMethod, } from "h3";
|
|
4
4
|
import { parseA2AAgentActivityPart } from "../a2a/activity.js";
|
|
5
|
-
import { describeToolParameterSignature, isAgentActionStopError, } from "../action.js";
|
|
5
|
+
import { describeToolParameterSignature, isAgentActionStopError, stripUnsupportedSchemaKeywords, } from "../action.js";
|
|
6
6
|
import { readAppState } from "../application-state/script-helpers.js";
|
|
7
7
|
import { isReadOnlyShellCommand } from "../coding-tools/index.js";
|
|
8
8
|
import { getDbExec, isTransientDatabaseError } from "../db/client.js";
|
|
@@ -2385,18 +2385,41 @@ function extractToolSearchResultNamesFromMessages(messages) {
|
|
|
2385
2385
|
}
|
|
2386
2386
|
return names;
|
|
2387
2387
|
}
|
|
2388
|
+
/**
|
|
2389
|
+
* Every tool the model is offered passes through here -- `defineAction`
|
|
2390
|
+
* schemas, the hand-written ones in extensions/mcp/context tools, and whatever
|
|
2391
|
+
* a third-party MCP server advertises. `defineAction` sanitizes at
|
|
2392
|
+
* construction; nothing else did, so `extension-data-set` shipped a `data`
|
|
2393
|
+
* property carrying a description and no `type`, and OpenAI 400'd the whole
|
|
2394
|
+
* request -- every tool in the payload, not just that one. Sanitizing here is
|
|
2395
|
+
* what makes that unrepresentable rather than a thing each definition site has
|
|
2396
|
+
* to remember.
|
|
2397
|
+
*
|
|
2398
|
+
* Cloned first: the hand-written schemas are module constants, so rewriting in
|
|
2399
|
+
* place would mutate shared state on first use.
|
|
2400
|
+
*/
|
|
2388
2401
|
function normalizeToolInputSchema(schema) {
|
|
2389
2402
|
if (!schema)
|
|
2390
2403
|
return { type: "object", properties: {} };
|
|
2391
2404
|
if (schema.type !== "object")
|
|
2392
2405
|
return null;
|
|
2406
|
+
let cloned;
|
|
2407
|
+
try {
|
|
2408
|
+
cloned = JSON.parse(JSON.stringify(schema));
|
|
2409
|
+
}
|
|
2410
|
+
catch {
|
|
2411
|
+
// A schema that will not round-trip cannot be safely rewritten, and
|
|
2412
|
+
// shipping it unsanitized is how this class of 400 reaches the provider.
|
|
2413
|
+
return null;
|
|
2414
|
+
}
|
|
2415
|
+
const safe = stripUnsupportedSchemaKeywords(cloned);
|
|
2393
2416
|
return {
|
|
2394
|
-
...
|
|
2417
|
+
...safe,
|
|
2395
2418
|
type: "object",
|
|
2396
|
-
properties:
|
|
2397
|
-
?
|
|
2419
|
+
properties: safe.properties && typeof safe.properties === "object"
|
|
2420
|
+
? safe.properties
|
|
2398
2421
|
: {},
|
|
2399
|
-
required: Array.isArray(
|
|
2422
|
+
required: Array.isArray(safe.required) ? safe.required : [],
|
|
2400
2423
|
};
|
|
2401
2424
|
}
|
|
2402
2425
|
function stringifyToolInput(input) {
|
|
@@ -158,7 +158,7 @@ export function BuilderSetupContent({ onConnected, layout = "default", }) {
|
|
|
158
158
|
return (_jsxs("div", { className: cn("agent-builder-setup-content", sidebarLayout && "agent-builder-setup-card--sidebar"), children: [_jsxs("div", { className: cn("agent-builder-setup-card__content flex flex-col sm:flex-row sm:items-center sm:justify-between", sidebarLayout ? "gap-2" : "gap-3"), children: [_jsxs("div", { className: "agent-builder-setup-card__copy min-w-0", children: [_jsx("h3", { className: "text-[13px] font-medium text-foreground", children: t("agentPanel.connectAi", { defaultValue: "Connect AI" }) }), _jsx("p", { className: "mt-0.5 text-[11px] leading-relaxed text-muted-foreground", children: t("agentPanel.builderOrOwnKeys", {
|
|
159
159
|
defaultValue: "Choose Builder.io or custom keys.",
|
|
160
160
|
}) })] }), _jsxs("div", { className: cn("agent-builder-setup-card__actions flex shrink-0", sidebarLayout
|
|
161
|
-
? "flex-
|
|
161
|
+
? "flex-row items-center gap-1"
|
|
162
162
|
: "flex-nowrap items-center gap-2"), children: [_jsx(BuilderConnectCta, { variant: "compact", onConnected: onConnected }), _jsx("button", { type: "button", onClick: () => setKeyOpen((open) => !open), className: cn("agent-builder-setup-card__key-button inline-flex shrink-0 items-center whitespace-nowrap rounded-md text-[11px] font-medium", sidebarLayout
|
|
163
163
|
? "h-7 border-0 bg-transparent px-0 text-muted-foreground hover:bg-transparent hover:text-foreground"
|
|
164
164
|
: "h-8 border border-border bg-background px-3 text-foreground hover:bg-accent"), "aria-expanded": keyOpen, children: t("agentPanel.addOwnKeys", {
|
|
@@ -58,19 +58,24 @@ function shallowEqualNavigationState(left, right) {
|
|
|
58
58
|
}
|
|
59
59
|
return true;
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Dedup token for the navigation write. Unserializable state falls back to the
|
|
63
|
+
* state's own identity, never a fresh symbol: the caller's `navigationKeys` is
|
|
64
|
+
* usually a new array each render, so a symbol recomputed here would never
|
|
65
|
+
* match the last one and every re-render would issue another failing write.
|
|
66
|
+
* Identity still lets a genuinely different state reach the write path.
|
|
67
|
+
*/
|
|
68
|
+
function navigationWriteDedupToken(keys, state) {
|
|
62
69
|
try {
|
|
63
|
-
const serialized = JSON.stringify(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
: Symbol("unserializable navigation state");
|
|
70
|
+
const serialized = JSON.stringify({ keys, state });
|
|
71
|
+
if (typeof serialized === "string")
|
|
72
|
+
return serialized;
|
|
67
73
|
}
|
|
68
74
|
catch {
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
// and surface its real error instead of being silently deduplicated.
|
|
72
|
-
return Symbol("unserializable navigation state");
|
|
75
|
+
// coercion-ok: deferred, not dropped — the write below still rejects with
|
|
76
|
+
// this error and reports it through `onError`.
|
|
73
77
|
}
|
|
78
|
+
return state;
|
|
74
79
|
}
|
|
75
80
|
function resolveAgentChatViewTransitionOption(option, command, path) {
|
|
76
81
|
const resolved = typeof option === "function" ? option(command, path) : option;
|
|
@@ -92,16 +97,15 @@ export function useSemanticNavigationState(options) {
|
|
|
92
97
|
const commandKeys = useMemo(() => uniqueKeys(options.commandKeys ?? ["navigate"]), [options.commandKeys]);
|
|
93
98
|
const commandQueryKey = useMemo(() => options.commandQueryKey ?? ["navigate-command"], [options.commandQueryKey]);
|
|
94
99
|
const navigationState = options.state ?? null;
|
|
95
|
-
const navigationWriteDedup = useMemo(() =>
|
|
96
|
-
keys: navigationKeys,
|
|
97
|
-
state: navigationState,
|
|
98
|
-
}), [navigationKeys, navigationState]);
|
|
100
|
+
const navigationWriteDedup = useMemo(() => navigationWriteDedupToken(navigationKeys, navigationState), [navigationKeys, navigationState]);
|
|
99
101
|
const getCommandDedupKeyRef = useRef(options.getCommandDedupKey);
|
|
100
102
|
const onCommandRef = useRef(options.onCommand);
|
|
101
103
|
const onErrorRef = useRef(options.onError);
|
|
102
104
|
getCommandDedupKeyRef.current = options.getCommandDedupKey;
|
|
103
105
|
onCommandRef.current = options.onCommand;
|
|
104
106
|
onErrorRef.current = options.onError;
|
|
107
|
+
// `null` is safe as "never written": a null state serializes to a string, so
|
|
108
|
+
// the token itself is never null.
|
|
105
109
|
const lastNavigationWriteRef = useRef(null);
|
|
106
110
|
useEffect(() => {
|
|
107
111
|
if (!enabled)
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
ok?: undefined;
|
|
17
16
|
error: string;
|
|
17
|
+
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|