@agent-native/core 0.228.2-nightly-20261113032548 → 0.228.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application-state/handlers.d.ts +2 -2
- package/dist/cli/skills-content/an-skill.d.ts +1 -1
- package/dist/cli/skills-content/an-skill.js +16 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db/schema-snapshot.generated.js +2 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/file-upload/builder-gateway.d.ts +42 -0
- package/dist/file-upload/builder-gateway.js +185 -0
- package/dist/file-upload/builder.js +8 -11
- package/dist/file-upload/index.d.ts +1 -0
- package/dist/file-upload/index.js +1 -0
- package/dist/framework-package-versions.json +11 -11
- package/dist/identity/rekey.js +2 -0
- package/dist/mcp/embed-app.js +259 -3
- package/dist/mcp/oauth-route.js +7 -0
- package/dist/mcp/screen-memory-stdio.d.ts +3 -3
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +5 -5
- package/dist/org/index.d.ts +1 -1
- package/dist/secrets/api-keys.js +8 -7
- package/dist/secrets/index.d.ts +2 -1
- package/dist/secrets/index.js +2 -1
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/secrets/routes.js +7 -8
- package/dist/secrets/schema.d.ts +51 -0
- package/dist/secrets/schema.js +3 -0
- package/dist/secrets/storage.d.ts +83 -1
- package/dist/secrets/storage.js +194 -6
- package/dist/secrets/usage.js +2 -4
- package/dist/secrets/vault-managed.d.ts +17 -0
- package/dist/secrets/vault-managed.js +19 -0
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/builder-signup-experiment.d.ts +4 -4
- package/dist/server/credential-provider.js +7 -7
- package/dist/server/first-touch-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +11 -0
- package/docs/content/security.mdx +1 -1
- package/docs/content/template-dispatch-developers.mdx +7 -7
- package/docs/content/template-dispatch-reference.mdx +16 -10
- package/package.json +4 -4
- package/src/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +11 -0
|
@@ -17,7 +17,7 @@ This page is for engineers extending Dispatch or customizing the template: how t
|
|
|
17
17
|
filename="packages/dispatch/src/server/lib/vault-store.ts"
|
|
18
18
|
language="ts"
|
|
19
19
|
code={
|
|
20
|
-
'export async function approveRequest(\n requestId: string,\n secretValue: string,\n secretName?: string,\n ctx: VaultCtx = requireVaultCtx(),\n) {\n await assertCanManageVault();\n const db = getDb();\n const request = await getRequestForTenant(requestId, ctx);\n if (!request) throw new Error("Request not found");\n\n const timestamp = now();\n const reviewer = ctx.ownerEmail;\n const staleApplyingBefore = timestamp - 5 * 60 * 1000;\n\n // Fence the transition on the current status — scoped to caller\'s tenant —\n // so a concurrent approve can\'t both win: only the caller that flips\n // pending -> applying proceeds to create the secret/grant. A crashed worker\n // leaves an applying row behind, so a later reviewer may reclaim a lease\n // that has been idle for five minutes. See\n // claimAgentTeamRun in packages/core/src/server/agent-teams-run-queue.ts\n // for the same pattern.\n const claimed = await db\n .update(schema.vaultRequests)\n .set({\n status: "applying",\n updatedAt: timestamp,\n })\n .where(\n and(\n eq(schema.vaultRequests.id, requestId),\n tenantScope(schema.vaultRequests, ctx),\n or(\n eq(schema.vaultRequests.status, "pending"),\n and(\n eq(schema.vaultRequests.status, "applying"),\n sql`${schema.vaultRequests.updatedAt} < ${staleApplyingBefore}`,\n ),\n ),\n ),\n )\n .returning();\n\n
|
|
20
|
+
'export async function approveRequest(\n requestId: string,\n secretValue: string,\n secretName?: string,\n ctx: VaultCtx = requireVaultCtx(),\n) {\n await assertCanManageVault();\n const db = getDb();\n const request = await getRequestForTenant(requestId, ctx);\n if (!request) throw new Error("Request not found");\n\n const timestamp = now();\n const reviewer = ctx.ownerEmail;\n const staleApplyingBefore = timestamp - 5 * 60 * 1000;\n\n // Fence the transition on the current status — scoped to caller\'s tenant —\n // so a concurrent approve can\'t both win: only the caller that flips\n // pending -> applying proceeds to create the secret/grant. A crashed worker\n // leaves an applying row behind, so a later reviewer may reclaim a lease\n // that has been idle for five minutes. See\n // claimAgentTeamRun in packages/core/src/server/agent-teams-run-queue.ts\n // for the same pattern.\n const claimed = await db\n .update(schema.vaultRequests)\n .set({\n status: "applying",\n updatedAt: timestamp,\n })\n .where(\n and(\n eq(schema.vaultRequests.id, requestId),\n tenantScope(schema.vaultRequests, ctx),\n or(\n eq(schema.vaultRequests.status, "pending"),\n and(\n eq(schema.vaultRequests.status, "applying"),\n sql`${schema.vaultRequests.updatedAt} < ${staleApplyingBefore}`,\n ),\n ),\n ),\n )\n .returning();\n\n const claimedRequest = claimed.at(0);\n if (!claimedRequest) {\n const current = await getRequestForTenant(requestId, ctx);\n if (current?.status === "applying") {\n throw new Error("Vault request is already being applied");\n }\n return current;\n }\n\n // Secret + grant must land in the REQUEST\'s tenant, not the approver\'s\n // (the approver may be acting on behalf of another user in the same org).\n const requestCtx = ctxForRow(claimedRequest);\n\n try {\n // A key that already exists in the scope is only granted: the approver\'s\n // value never overwrites a row, whether the Vault or an app wrote it.\n let secretId = (await listScopeSecrets(requestCtx)).find(\n (row) => row.credentialKey === claimedRequest.credentialKey,\n )?.id;\n\n if (!secretId) {\n secretId = (\n await createSecret(\n {\n credentialKey: claimedRequest.credentialKey,\n value: secretValue,\n name: secretName || claimedRequest.credentialKey,\n },\n requestCtx,\n )\n ).id;\n }\n\n await createGrant(secretId, claimedRequest.appId, requestCtx);\n } catch (error) {\n await db\n .update(schema.vaultRequests)\n .set({ status: "pending", updatedAt: now() })\n .where(\n and(\n eq(schema.vaultRequests.id, requestId),\n tenantScope(schema.vaultRequests, ctx),\n eq(schema.vaultRequests.status, "applying"),\n ),\n );\n throw error;\n }\n\n await db\n .update(schema.vaultRequests)\n .set({\n status: "approved",\n reviewedBy: reviewer,\n reviewedAt: timestamp,\n updatedAt: now(),\n })\n .where(\n and(\n eq(schema.vaultRequests.id, requestId),\n tenantScope(schema.vaultRequests, ctx),\n eq(schema.vaultRequests.status, "applying"),\n ),\n );\n\n await recordVaultAudit({\n action: "request.approved",\n credentialKey: claimedRequest.credentialKey,\n appId: claimedRequest.appId,\n summary: `Approved ${claimedRequest.credentialKey} for ${claimedRequest.appId} (requested by ${claimedRequest.requestedBy})`,\n metadata: { requestId, reviewer },\n });\n\n return getRequestForTenant(requestId, ctx);\n}'
|
|
21
21
|
}
|
|
22
22
|
annotations={[
|
|
23
23
|
{
|
|
@@ -26,22 +26,22 @@ This page is for engineers extending Dispatch or customizing the template: how t
|
|
|
26
26
|
note: "The claim only succeeds if the row is still pending, or stuck applying for over five minutes. Two simultaneous approvals can't both win: only one caller's update actually matches a row and returns it.",
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
|
-
lines: "44-
|
|
29
|
+
lines: "44-51",
|
|
30
30
|
label: "Losing the race isn't an error",
|
|
31
31
|
note: "If the claim matched nothing, the request is either already mid-flight elsewhere (throw) or was already resolved by the time this call ran (just return its current state).",
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
lines: "
|
|
35
|
-
label: "
|
|
36
|
-
note: "A second request for the same credential key
|
|
34
|
+
lines: "58-77",
|
|
35
|
+
label: "Grant an existing key instead of overwriting it",
|
|
36
|
+
note: "A key that already exists in the scope is only granted, so a second request for the same credential key reuses it and the approver's value never replaces a row, whether the Vault or an app wrote it.",
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
|
-
lines: "
|
|
39
|
+
lines: "78-90",
|
|
40
40
|
label: "Roll back the lock on failure",
|
|
41
41
|
note: "If creating the secret or grant throws, the request goes back to pending instead of staying stuck in applying, which is what makes the five-minute stale-lease reclaim above necessary in the first place.",
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
|
-
lines: "
|
|
44
|
+
lines: "92-106",
|
|
45
45
|
label: "Finalize only from the lock this call holds",
|
|
46
46
|
note: "The final flip to approved is still scoped to status = applying, so it can only apply the transition this specific call claimed.",
|
|
47
47
|
},
|
|
@@ -136,21 +136,26 @@ Dispatch ships close to a hundred actions. Most of the UI-facing ones are alread
|
|
|
136
136
|
id="doc-block-dispatch11"
|
|
137
137
|
title="Secrets vault schema"
|
|
138
138
|
summary={
|
|
139
|
-
"A
|
|
139
|
+
"A key is stored once, encrypted, as a row of the credential store (app_secrets, owned by @agent-native/core). A grant gives a named app access to it by key name. A request plus review gates sensitive access before a grant exists. The audit log records who changed which key, when. The grant, request, and audit tables are defined in @agent-native/dispatch (packages/dispatch/src/db/schema.ts)."
|
|
140
140
|
}
|
|
141
141
|
entities={[
|
|
142
142
|
{
|
|
143
143
|
id: "secrets",
|
|
144
|
-
name: "
|
|
145
|
-
note: "Stored
|
|
144
|
+
name: "app_secrets",
|
|
145
|
+
note: "Stored credentials, encrypted",
|
|
146
146
|
fields: [
|
|
147
147
|
{ name: "id", type: "text", pk: true },
|
|
148
|
-
{
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
{
|
|
149
|
+
name: "scope",
|
|
150
|
+
type: "text",
|
|
151
|
+
note: "org, or workspace for a solo vault",
|
|
152
|
+
},
|
|
153
|
+
{ name: "scope_id", type: "text" },
|
|
154
|
+
{ name: "key", type: "text", note: "credential key" },
|
|
155
|
+
{ name: "encrypted_value", type: "text", note: "ciphertext only" },
|
|
156
|
+
{ name: "label", type: "text", nullable: true },
|
|
153
157
|
{ name: "provider", type: "text", nullable: true },
|
|
158
|
+
{ name: "created_by", type: "text", nullable: true },
|
|
154
159
|
],
|
|
155
160
|
},
|
|
156
161
|
{
|
|
@@ -159,7 +164,8 @@ Dispatch ships close to a hundred actions. Most of the UI-facing ones are alread
|
|
|
159
164
|
note: "Per-app access grant",
|
|
160
165
|
fields: [
|
|
161
166
|
{ name: "id", type: "text", pk: true },
|
|
162
|
-
{ name: "secret_id", type: "text", fk: "
|
|
167
|
+
{ name: "secret_id", type: "text", fk: "app_secrets.id" },
|
|
168
|
+
{ name: "credential_key", type: "text", nullable: true },
|
|
163
169
|
{ name: "app_id", type: "text" },
|
|
164
170
|
{ name: "granted_by", type: "text" },
|
|
165
171
|
{ name: "status", type: "text" },
|
|
@@ -187,7 +193,7 @@ Dispatch ships close to a hundred actions. Most of the UI-facing ones are alread
|
|
|
187
193
|
{
|
|
188
194
|
name: "secret_id",
|
|
189
195
|
type: "text",
|
|
190
|
-
fk: "
|
|
196
|
+
fk: "app_secrets.id",
|
|
191
197
|
nullable: true,
|
|
192
198
|
},
|
|
193
199
|
{ name: "app_id", type: "text", nullable: true },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.228.2
|
|
3
|
+
"version": "0.228.2",
|
|
4
4
|
"description": "The agentic application framework for building autonomous agents with intuitive UIs",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -771,8 +771,8 @@
|
|
|
771
771
|
"yaml": "^2.9.0",
|
|
772
772
|
"yjs": "^13.6.33",
|
|
773
773
|
"zod": "^4.3.6",
|
|
774
|
-
"@agent-native/agentkit": "^0.228.2
|
|
775
|
-
"@agent-native/recap-cli": "^0.5.
|
|
774
|
+
"@agent-native/agentkit": "^0.228.2",
|
|
775
|
+
"@agent-native/recap-cli": "^0.5.103"
|
|
776
776
|
},
|
|
777
777
|
"devDependencies": {
|
|
778
778
|
"@ai-sdk/anthropic": "^3.0.71",
|
|
@@ -845,7 +845,7 @@
|
|
|
845
845
|
"xlsx": "^0.18.5"
|
|
846
846
|
},
|
|
847
847
|
"peerDependencies": {
|
|
848
|
-
"@agent-native/core-corpus": "0.
|
|
848
|
+
"@agent-native/core-corpus": ">=0.196.0",
|
|
849
849
|
"@ai-sdk/anthropic": ">=3",
|
|
850
850
|
"@ai-sdk/cohere": ">=3",
|
|
851
851
|
"@ai-sdk/google": ">=3",
|
package/src/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md
CHANGED
|
@@ -120,6 +120,17 @@ resource CSP should include the exact origins of apps granted through Dispatch,
|
|
|
120
120
|
not broad sources like `https:`. This lets Claude's transplant path fetch the
|
|
121
121
|
signed target app HTML while keeping the connector's resource surface narrow.
|
|
122
122
|
|
|
123
|
+
Side panel and app tools: every `embedApp()` resource sets
|
|
124
|
+
`_meta.ui.preferredDisplayMode: "fullscreen"`, so Claude opens the app in its
|
|
125
|
+
side panel beside the chat (other hosts ignore the field). The shell declares
|
|
126
|
+
`availableDisplayModes` and `tools` in `ui/initialize` and answers the host's
|
|
127
|
+
`tools/list` / `tools/call` on the open view: `read_view` returns the page's
|
|
128
|
+
path, title, selection and visible text, `navigate_view` moves the open app to
|
|
129
|
+
another same-origin path in place, and any page tools the app registered through
|
|
130
|
+
WebMCP are passed through. Prefer these over a new `open_app` call when the user
|
|
131
|
+
asks to change what the open panel shows, since each new UI tool call opens a
|
|
132
|
+
new view.
|
|
133
|
+
|
|
123
134
|
Host sizing rule: the MCP resource shell owns a bounded inline height and the
|
|
124
135
|
embedded route should scroll internally. `embedApp({ height })` defaults to a
|
|
125
136
|
`560px` shell, clamps to `320-900px`, and subtracts `44px` for the wrapper bar
|