@agent-native/core 0.228.2-nightly-20261113152307 → 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/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/collab/struct-routes.d.ts +1 -1
- package/dist/db/schema-snapshot.generated.js +2 -1
- 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/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +5 -5
- 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 +4 -4
- 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
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const AN_SKILL_MD = "---\nname: an\ndescription: >-\n Open and operate Agent-Native workspace apps through Dispatch MCP, with\n inline app surfaces, browser-session authentication, and current screen state.\nmetadata:\n visibility: exported\n---\n\n# Agent-Native Apps\n\nUse `/an <app>` to open an Agent-Native app beside the conversation and keep\nthe app's live UI and the agent's actions in the same workflow. The first\nargument is the Dispatch app id. For example, `/an slides` opens the Slides\neditor. After it opens, the user can sign in in that browser surface and ask\nfor new decks or focused edits in ordinary language.\n\n## Open the app\n\nFor a known app, call Dispatch's `open_app` with an inline surface:\n\n```json\n{\n \"app\": \"slides\",\n \"path\": \"/\",\n \"embed\": true,\n \"chrome\": \"full\"\n}\n```\n\nThe MCP App response is the preferred handoff for Claude, Claude Desktop,\nClaude Cowork, ChatGPT, ChatGPT desktop, Codex, and other compatible hosts. Keep\nthe returned open link as the fallback for a host that cannot render MCP Apps\ninline. Do not claim that a browser opened unless the host rendered the inline\nsurface or its browser tool confirmed the returned URL.\n\nIf the app name is missing or uncertain, call `list_apps` first and use the\nexact granted app id. If the requested app is not listed, explain that it must\nbe granted in Dispatch's Agents access settings. Do not invent a URL, use a\nlocalhost URL, or route around the Dispatch grant.\n\n## Work in the opened app\n\nPrefer direct app tools when the host exposes them. After opening an app, call\n`list-host-webmcp-tools` when available, then use `run-host-webmcp-tool`\nwith the exact listed name and origin. Page-local tools reflect current app\nstate and selection, so use `view-screen` before selection-dependent edits\nand read back writes.\n\nYou are the model doing the work: when the user asks for new content \u2014 a\ndesign, a deck, a form, a document \u2014 author it yourself and save it with the\napp's create/update tools. Never hand off authoring to the app's own agent\nwhen those tools exist, and never wait on an in-app question form; it answers\nback through that app's own chat, not to you.\n\nUse `ask_app` only when the host has no direct page tools, the requested\ncapability is not exposed, the task needs the app agent's interpretation or\nmulti-step specialist reasoning, or a direct call fails and needs recovery.\nDispatch's unified `/mcp` endpoint still exposes generic cross-app verbs; a\ndirect app MCP connection or page WebMCP surface is where named app actions\nappear.\n\nThe app's MCP `instructions` name its key tools (generated from the app's own\nlist); follow those names verbatim and use `tool-search` for anything else \u2014\nnever guess a tool name.\n\n1. Call `view-screen` before any selection-dependent edit and use the ids it\n returns; never guess an id from a title, index, or stale context.\n2. If `view-screen` returns a `selection` and `nextRequiredAction`, make\n that call directly with the smallest atomic change; do not regenerate a\n whole artifact for a focused edit.\n3. Read the result back with the app's matching read action and report what\n changed. A queued `ask_app_status` task is not proof an edit completed.\n\n## Authentication and host behavior\n\nThe Dispatch MCP connector identifies the calling agent, while the embedded app\nuses the user's browser session. Let the user complete sign-in in the rendered\nAgent-Native browser surface. Never request, copy, or store passwords, OAuth\ncodes, cookies, or access tokens.\n\nThe generic Agent-Native plugin registers Dispatch at\n`https://dispatch.agent-native.com/mcp` for hosts that support plugin MCP\nconfiguration. ChatGPT custom connectors use the same URL with OAuth. After\ninstalling or changing a connector, reload Claude/Cowork/ChatGPT or reconnect\nand rescan the MCP server if the new tools or inline surface are not visible.\n\n## Failure handling\n\n- If `open_app` succeeds but no inline surface appears, show its returned\n link and say that this host does not expose an embedded browser here.\n- After an app loads, check for `list-host-webmcp-tools` before delegating. If\n it is available, use the exact returned tool name and origin for direct work.\n- If `ask_app` cannot reach Slides, check that Slides is granted in\n Dispatch and that the connector is authenticated, then retry once with the\n exact app id `slides`.\n- If screen state has no deck or selection, describe that state instead of\n fabricating context. Ask the user to open a deck or select an element when\n the requested edit depends on it.\n- Treat a successful open link, a queued task, or a tool acknowledgment as\n navigation/task setup only. Confirm a write with the app's readback action.\n";
|
|
1
|
+
export declare const AN_SKILL_MD = "---\nname: an\ndescription: >-\n Open and operate Agent-Native workspace apps through Dispatch MCP, with\n inline app surfaces, browser-session authentication, and current screen state.\nmetadata:\n visibility: exported\n---\n\n# Agent-Native Apps\n\nUse `/an <app>` to open an Agent-Native app beside the conversation and keep\nthe app's live UI and the agent's actions in the same workflow. The first\nargument is the Dispatch app id. For example, `/an slides` opens the Slides\neditor. After it opens, the user can sign in in that browser surface and ask\nfor new decks or focused edits in ordinary language.\n\n## Open the app\n\nFor a known app, call Dispatch's `open_app` with an inline surface:\n\n```json\n{\n \"app\": \"slides\",\n \"path\": \"/\",\n \"embed\": true,\n \"chrome\": \"full\"\n}\n```\n\nThe MCP App response is the preferred handoff for Claude, Claude Desktop,\nClaude Cowork, ChatGPT, ChatGPT desktop, Codex, and other compatible hosts. Keep\nthe returned open link as the fallback for a host that cannot render MCP Apps\ninline. Do not claim that a browser opened unless the host rendered the inline\nsurface or its browser tool confirmed the returned URL.\n\nIf the app name is missing or uncertain, call `list_apps` first and use the\nexact granted app id. If the requested app is not listed, explain that it must\nbe granted in Dispatch's Agents access settings. Do not invent a URL, use a\nlocalhost URL, or route around the Dispatch grant.\n\n## Work in the opened app\n\nPrefer direct app tools when the host exposes them. After opening an app, call\n`list-host-webmcp-tools` when available, then use `run-host-webmcp-tool`\nwith the exact listed name and origin. Page-local tools reflect current app\nstate and selection, so use `view-screen` before selection-dependent edits\nand read back writes.\n\nYou are the model doing the work: when the user asks for new content \u2014 a\ndesign, a deck, a form, a document \u2014 author it yourself and save it with the\napp's create/update tools. Never hand off authoring to the app's own agent\nwhen those tools exist, and never wait on an in-app question form; it answers\nback through that app's own chat, not to you.\n\nUse `ask_app` only when the host has no direct page tools, the requested\ncapability is not exposed, the task needs the app agent's interpretation or\nmulti-step specialist reasoning, or a direct call fails and needs recovery.\nDispatch's unified `/mcp` endpoint still exposes generic cross-app verbs; a\ndirect app MCP connection or page WebMCP surface is where named app actions\nappear.\n\nThe app's MCP `instructions` name its key tools (generated from the app's own\nlist); follow those names verbatim and use `tool-search` for anything else \u2014\nnever guess a tool name.\n\n1. Call `view-screen` before any selection-dependent edit and use the ids it\n returns; never guess an id from a title, index, or stale context.\n2. If `view-screen` returns a `selection` and `nextRequiredAction`, make\n that call directly with the smallest atomic change; do not regenerate a\n whole artifact for a focused edit.\n3. Read the result back with the app's matching read action and report what\n changed. A queued `ask_app_status` task is not proof an edit completed.\n\n## Keep the open app in step with the chat\n\nClaude opens an embedded app in its side panel. The panel is one live app: an\nedit made through a tool shows there, and an edit the user makes by hand is in\nthe app's data the next time you read it.\n\n- To change what the open panel shows (filter a list, open a record, switch a\n week), call the view tools `read_view` and `navigate_view` on the open app\n instead of calling `open_app` again. Each new `open_app` call opens a new\n view and replaces the panel.\n- Before acting on \"this\", \"it\" or \"the one I opened\", call `read_view`;\n the user may have clicked or typed in the panel since your last turn.\n- Draft and edit with the app's own actions (create or update a draft, an\n event, a task), then read it back. Send, delete or move only when the user\n asks.\n\n## Authentication and host behavior\n\nThe Dispatch MCP connector identifies the calling agent, while the embedded app\nuses the user's browser session. Let the user complete sign-in in the rendered\nAgent-Native browser surface. Never request, copy, or store passwords, OAuth\ncodes, cookies, or access tokens.\n\nThe generic Agent-Native plugin registers Dispatch at\n`https://dispatch.agent-native.com/mcp` for hosts that support plugin MCP\nconfiguration. ChatGPT custom connectors use the same URL with OAuth. After\ninstalling or changing a connector, reload Claude/Cowork/ChatGPT or reconnect\nand rescan the MCP server if the new tools or inline surface are not visible.\n\n## Failure handling\n\n- If `open_app` succeeds but no inline surface appears, show its returned\n link and say that this host does not expose an embedded browser here.\n- After an app loads, check for `list-host-webmcp-tools` before delegating. If\n it is available, use the exact returned tool name and origin for direct work.\n- If `ask_app` cannot reach Slides, check that Slides is granted in\n Dispatch and that the connector is authenticated, then retry once with the\n exact app id `slides`.\n- If screen state has no deck or selection, describe that state instead of\n fabricating context. Ask the user to open a deck or select an element when\n the requested edit depends on it.\n- Treat a successful open link, a queued task, or a tool acknowledgment as\n navigation/task setup only. Confirm a write with the app's readback action.\n";
|
|
2
2
|
export declare const AN_COMMAND_MD = "---\ndescription: Open and operate a granted Agent-Native app through Dispatch MCP.\nargument-hint: <app> [request]\n---\n\nUse the an skill. Treat the first argument as the Agent-Native Dispatch app id.\nFor `/an slides`, call `open_app` with app `slides`, path \"/\", embed\ntrue, and chrome `full`. Keep the returned link if the host cannot render\nthe inline MCP App. Any remaining arguments are the user's request after the\napp opens:\n\n$ARGUMENTS\n";
|
|
@@ -73,6 +73,22 @@ never guess a tool name.
|
|
|
73
73
|
3. Read the result back with the app's matching read action and report what
|
|
74
74
|
changed. A queued \`ask_app_status\` task is not proof an edit completed.
|
|
75
75
|
|
|
76
|
+
## Keep the open app in step with the chat
|
|
77
|
+
|
|
78
|
+
Claude opens an embedded app in its side panel. The panel is one live app: an
|
|
79
|
+
edit made through a tool shows there, and an edit the user makes by hand is in
|
|
80
|
+
the app's data the next time you read it.
|
|
81
|
+
|
|
82
|
+
- To change what the open panel shows (filter a list, open a record, switch a
|
|
83
|
+
week), call the view tools \`read_view\` and \`navigate_view\` on the open app
|
|
84
|
+
instead of calling \`open_app\` again. Each new \`open_app\` call opens a new
|
|
85
|
+
view and replaces the panel.
|
|
86
|
+
- Before acting on "this", "it" or "the one I opened", call \`read_view\`;
|
|
87
|
+
the user may have clicked or typed in the panel since your last turn.
|
|
88
|
+
- Draft and edit with the app's own actions (create or update a draft, an
|
|
89
|
+
event, a task), then read it back. Send, delete or move only when the user
|
|
90
|
+
asks.
|
|
91
|
+
|
|
76
92
|
## Authentication and host behavior
|
|
77
93
|
|
|
78
94
|
The Dispatch MCP connector identifies the calling agent, while the embedded app
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
|
|
|
26
26
|
ok: boolean;
|
|
27
27
|
}>>;
|
|
28
28
|
export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
ok?: undefined;
|
|
30
29
|
text?: undefined;
|
|
30
|
+
ok?: undefined;
|
|
31
31
|
error: string;
|
|
32
32
|
} | {
|
|
33
33
|
error?: undefined;
|
|
@@ -13,9 +13,9 @@ export declare const postCollabPatch: import("h3").EventHandlerWithFetch<import(
|
|
|
13
13
|
ok: boolean;
|
|
14
14
|
}>>;
|
|
15
15
|
export declare const getCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
data?: undefined;
|
|
17
16
|
error: string;
|
|
18
17
|
docId?: undefined;
|
|
18
|
+
data?: undefined;
|
|
19
19
|
} | {
|
|
20
20
|
error?: undefined;
|
|
21
21
|
docId: string;
|
|
@@ -68,7 +68,7 @@ export const SCHEMA_SNAPSHOT = {
|
|
|
68
68
|
'CREATE TABLE "app_permission_overrides" (\n "org_id" text NOT NULL,\n "app_id" text NOT NULL,\n "permission" text NOT NULL,\n "roles_json" text NOT NULL,\n "updated_by" text NOT NULL,\n "updated_at" bigint NOT NULL\n);',
|
|
69
69
|
'CREATE TABLE "app_resource_change_consumers" (\n "app" text NOT NULL,\n "resource_type" text NOT NULL,\n "consumer" text NOT NULL,\n "registered_at" timestamp with time zone DEFAULT now() NOT NULL\n);',
|
|
70
70
|
'CREATE TABLE "app_resource_changes" (\n "consumer" text NOT NULL,\n "app" text NOT NULL,\n "resource_type" text NOT NULL,\n "resource_id" text NOT NULL,\n "reason" text NOT NULL,\n "seq" bigint NOT NULL,\n "changed_at" timestamp with time zone DEFAULT clock_timestamp() NOT NULL,\n "available_at" timestamp with time zone DEFAULT clock_timestamp() NOT NULL,\n "attempts" integer DEFAULT 0 NOT NULL,\n "failed_at" timestamp with time zone\n);',
|
|
71
|
-
'CREATE TABLE "app_secrets" (\n "id" text NOT NULL,\n "scope" text NOT NULL,\n "scope_id" text NOT NULL,\n "key" text NOT NULL,\n "encrypted_value" text NOT NULL,\n "shared_encrypted_value" text,\n "description" text,\n "url_allowlist" text,\n "created_at" bigint NOT NULL,\n "updated_at" bigint NOT NULL\n);',
|
|
71
|
+
'CREATE TABLE "app_secrets" (\n "id" text NOT NULL,\n "scope" text NOT NULL,\n "scope_id" text NOT NULL,\n "key" text NOT NULL,\n "encrypted_value" text NOT NULL,\n "shared_encrypted_value" text,\n "description" text,\n "url_allowlist" text,\n "created_at" bigint NOT NULL,\n "updated_at" bigint NOT NULL,\n "label" text,\n "provider" text,\n "created_by" text\n);',
|
|
72
72
|
'CREATE TABLE "application_state" (\n "session_id" text NOT NULL,\n "key" text NOT NULL,\n "value" text NOT NULL,\n "updated_at" bigint NOT NULL,\n "writer" text,\n "writer_seq" bigint\n);',
|
|
73
73
|
'CREATE TABLE "automation_runs" (\n "id" text NOT NULL,\n "owner" text NOT NULL,\n "automation" text NOT NULL,\n "path" text NOT NULL,\n "scope" text,\n "org_id" text,\n "app_id" text,\n "run_id" text,\n "thread_id" text,\n "status" text DEFAULT \'running\'::text NOT NULL,\n "started_at" bigint NOT NULL,\n "finished_at" bigint,\n "error" text,\n "error_code" text,\n "notification_email" text,\n "failure_alerted" bigint DEFAULT 0 NOT NULL,\n "failure_alert_state" text,\n "failure_alert_attempts" bigint DEFAULT 0 NOT NULL,\n "failure_alert_next_attempt_at" bigint,\n "failure_alert_claimed_at" bigint,\n "failure_alert_provider" text,\n "failure_alert_first_attempt_at" bigint,\n "failure_alert_unsubscribe_token" text,\n "claimed_at" bigint,\n "dispatch_pending" bigint DEFAULT 0 NOT NULL\n);',
|
|
74
74
|
'CREATE TABLE "automation_scheduler_health" (\n "id" text NOT NULL,\n "app_id" text DEFAULT \'default\'::text NOT NULL,\n "org_id" text,\n "last_checked_at" bigint,\n "last_dispatched_at" bigint,\n "last_error" text,\n "runtime" text,\n "updated_at" bigint NOT NULL,\n "lease_owner" text,\n "lease_expires_at" bigint\n);',
|
|
@@ -953,6 +953,7 @@ export const SCHEMA_SNAPSHOT = {
|
|
|
953
953
|
["agent_tool_approvals", "tool-revision", null],
|
|
954
954
|
["app_resource_changes", "baseline", null],
|
|
955
955
|
["app_secrets", "baseline", null],
|
|
956
|
+
["app_secrets", "vault-metadata-columns", null],
|
|
956
957
|
["application_state", "baseline", null],
|
|
957
958
|
["application_state", "indexes", null],
|
|
958
959
|
["application_state", "widen-bigint", null],
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
|
-
"@agent-native/agentkit": "0.228.2
|
|
2
|
+
"@agent-native/agentkit": "0.228.2",
|
|
3
3
|
"@agent-native/code-agents-ui": "0.1.75",
|
|
4
|
-
"@agent-native/core": "0.228.2
|
|
5
|
-
"@agent-native/core-corpus": "0.228.2
|
|
6
|
-
"@agent-native/creative-context": "0.8.
|
|
7
|
-
"@agent-native/dispatch": "0.42.7
|
|
4
|
+
"@agent-native/core": "0.228.2",
|
|
5
|
+
"@agent-native/core-corpus": "0.228.2",
|
|
6
|
+
"@agent-native/creative-context": "0.8.72",
|
|
7
|
+
"@agent-native/dispatch": "0.42.7",
|
|
8
8
|
"@agent-native/embedding": "0.2.0",
|
|
9
9
|
"@agent-native/migrate": "0.0.7",
|
|
10
|
-
"@agent-native/otel": "0.1.
|
|
11
|
-
"@agent-native/pinpoint": "0.1.
|
|
12
|
-
"@agent-native/recap-cli": "0.5.
|
|
13
|
-
"@agent-native/scheduling": "0.2.
|
|
10
|
+
"@agent-native/otel": "0.1.39",
|
|
11
|
+
"@agent-native/pinpoint": "0.1.115",
|
|
12
|
+
"@agent-native/recap-cli": "0.5.103",
|
|
13
|
+
"@agent-native/scheduling": "0.2.59",
|
|
14
14
|
"@agent-native/shared-app-config": "0.1.2",
|
|
15
|
-
"@agent-native/skills": "0.4.7
|
|
16
|
-
"@agent-native/toolkit": "0.228.2
|
|
15
|
+
"@agent-native/skills": "0.4.7",
|
|
16
|
+
"@agent-native/toolkit": "0.228.2"
|
|
17
17
|
}
|
package/dist/identity/rekey.js
CHANGED
|
@@ -239,6 +239,8 @@ export const IDENTITY_REKEY_IGNORED_COLUMNS = new Set([
|
|
|
239
239
|
"tool_history.actor_email",
|
|
240
240
|
"tool_history.owner_email",
|
|
241
241
|
"agent_resource_versions.created_by",
|
|
242
|
+
// Creator attribution on a Vault key, kept as written; the key is owned by its scope.
|
|
243
|
+
"app_secrets.created_by",
|
|
242
244
|
"agent_review_comments.created_by",
|
|
243
245
|
"agent_human_review_summaries.created_by",
|
|
244
246
|
"organizations.created_by",
|
package/dist/mcp/embed-app.js
CHANGED
|
@@ -31,6 +31,9 @@ export function embedApp(options = {}) {
|
|
|
31
31
|
return {
|
|
32
32
|
title,
|
|
33
33
|
requiresEmbedSession: true,
|
|
34
|
+
// Claude reads this from the resources/read content item and moves the
|
|
35
|
+
// view to its side panel; hosts that do not know the field ignore it.
|
|
36
|
+
_meta: { ui: { preferredDisplayMode: "fullscreen" } },
|
|
34
37
|
...(options.description ? { description: options.description } : {}),
|
|
35
38
|
html: (ctx) => {
|
|
36
39
|
const remoteBridgeFallbackEnabled = ctx.catalogMode !== "directory";
|
|
@@ -1363,6 +1366,7 @@ export function embedApp(options = {}) {
|
|
|
1363
1366
|
window.history.replaceState(window.history.state, "", localPathFromUrl(appUrl, false));
|
|
1364
1367
|
} catch {}
|
|
1365
1368
|
await mountTransplantedHtml(html, appUrl);
|
|
1369
|
+
watchPageTools();
|
|
1366
1370
|
embedSessionRefreshAttempts = 0;
|
|
1367
1371
|
notifyHostHeightRepeatedly();
|
|
1368
1372
|
}
|
|
@@ -1756,6 +1760,7 @@ export function embedApp(options = {}) {
|
|
|
1756
1760
|
${ctx.catalogMode === "directory" ? "" : 'frame.allow = "clipboard-read; clipboard-write";'}
|
|
1757
1761
|
appFrame = frame;
|
|
1758
1762
|
appFrameReady = false;
|
|
1763
|
+
notifyViewToolsChanged();
|
|
1759
1764
|
lastFrameSrc = src;
|
|
1760
1765
|
appFrameDocumentState.loadGeneration += 1;
|
|
1761
1766
|
frame.addEventListener("load", () => {
|
|
@@ -2642,6 +2647,226 @@ export function embedApp(options = {}) {
|
|
|
2642
2647
|
if (bridge && (!appFrame || openAiBridge)) syncOpenAiBridge(bridge);
|
|
2643
2648
|
}, { passive: true });
|
|
2644
2649
|
|
|
2650
|
+
// App tools: the host calls these on this open view, so a "filter it" or
|
|
2651
|
+
// "open that one" turn changes the panel in place instead of opening a new view.
|
|
2652
|
+
const readViewToolName = "read_view";
|
|
2653
|
+
const navigateViewToolName = "navigate_view";
|
|
2654
|
+
const maxViewTextChars = 6000;
|
|
2655
|
+
const maxPageTools = 60;
|
|
2656
|
+
const pageToolWaitMs = 40000;
|
|
2657
|
+
const pageToolOrigins = new Map();
|
|
2658
|
+
let pageToolWatchStarted = false;
|
|
2659
|
+
|
|
2660
|
+
function appPageToolHelper() {
|
|
2661
|
+
if (appFrame) return null;
|
|
2662
|
+
const helper = window.__agentNativeWebMcp;
|
|
2663
|
+
return helper && typeof helper.tools === "function" && typeof helper.call === "function"
|
|
2664
|
+
? helper
|
|
2665
|
+
: null;
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
function currentViewUrl() {
|
|
2669
|
+
if (appFrame) {
|
|
2670
|
+
try {
|
|
2671
|
+
return new URL(appFrame.src, window.location.href);
|
|
2672
|
+
// coercion-ok: null means "no readable view URL"; read_view and navigate_view report it as an error
|
|
2673
|
+
} catch {
|
|
2674
|
+
return null;
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
return lastFrameSrc ? new URL(window.location.href) : null;
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2680
|
+
function readViewState() {
|
|
2681
|
+
// A nested app frame is cross-origin and moves on its own, so its src is
|
|
2682
|
+
// only the launch URL; reporting it would describe the wrong page.
|
|
2683
|
+
if (appFrame) throw new Error("This host shows the app in a nested frame, so its current page can't be read.");
|
|
2684
|
+
const url = currentViewUrl();
|
|
2685
|
+
if (!url) throw new Error("No app page has loaded in this view yet.");
|
|
2686
|
+
const state = {
|
|
2687
|
+
path: localPathFromUrl(url, false),
|
|
2688
|
+
title: document.title
|
|
2689
|
+
};
|
|
2690
|
+
{
|
|
2691
|
+
const selection = typeof window.getSelection === "function"
|
|
2692
|
+
? String(window.getSelection() || "").trim()
|
|
2693
|
+
: "";
|
|
2694
|
+
if (selection) state.selectedText = selection.slice(0, maxViewTextChars);
|
|
2695
|
+
const root = document.querySelector("main") || document.body;
|
|
2696
|
+
state.visibleText = root
|
|
2697
|
+
? String(root.innerText || "").replace(/\\s+/g, " ").trim().slice(0, maxViewTextChars)
|
|
2698
|
+
: "";
|
|
2699
|
+
}
|
|
2700
|
+
return state;
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2703
|
+
function navigateView(rawPath) {
|
|
2704
|
+
const path = typeof rawPath === "string" ? rawPath.trim() : "";
|
|
2705
|
+
if (!path.startsWith("/") || path.startsWith("//")) {
|
|
2706
|
+
throw new Error("path must start with / and stay inside the open app, e.g. the path read_view returns.");
|
|
2707
|
+
}
|
|
2708
|
+
// The nested frame was launched on a session scoped to its start URL;
|
|
2709
|
+
// pointing it at a bare app route would drop that session.
|
|
2710
|
+
if (appFrame) {
|
|
2711
|
+
throw new Error("This host shows the app in a nested frame, so it can't be moved from here.");
|
|
2712
|
+
}
|
|
2713
|
+
const base = currentViewUrl();
|
|
2714
|
+
if (!base) throw new Error("No app page has loaded in this view yet.");
|
|
2715
|
+
const target = new URL(path, base);
|
|
2716
|
+
if (target.origin !== base.origin) throw new Error("path must stay inside the open app.");
|
|
2717
|
+
const nextPath = localPathFromUrl(target, false);
|
|
2718
|
+
// React Router reads the location on popstate, so a pushed entry plus a
|
|
2719
|
+
// popstate event moves the transplanted app without reloading it.
|
|
2720
|
+
const current = window.history.state;
|
|
2721
|
+
const idx = current && typeof current.idx === "number" ? current.idx + 1 : 0;
|
|
2722
|
+
window.history.pushState(
|
|
2723
|
+
{ usr: null, key: Math.random().toString(36).slice(2, 10), idx },
|
|
2724
|
+
"",
|
|
2725
|
+
nextPath
|
|
2726
|
+
);
|
|
2727
|
+
window.dispatchEvent(new PopStateEvent("popstate", { state: window.history.state }));
|
|
2728
|
+
return { path: nextPath };
|
|
2729
|
+
}
|
|
2730
|
+
|
|
2731
|
+
async function listViewTools() {
|
|
2732
|
+
// A nested cross-origin frame can be neither read nor moved from here.
|
|
2733
|
+
if (appFrame) return [];
|
|
2734
|
+
const tools = [
|
|
2735
|
+
{
|
|
2736
|
+
name: readViewToolName,
|
|
2737
|
+
title: "Read open app view",
|
|
2738
|
+
description: "Read the app page open beside the chat: its path, title, selected text and visible text. Call it before acting on what the user is looking at.",
|
|
2739
|
+
inputSchema: { type: "object", properties: {} },
|
|
2740
|
+
annotations: { readOnlyHint: true }
|
|
2741
|
+
},
|
|
2742
|
+
{
|
|
2743
|
+
name: navigateViewToolName,
|
|
2744
|
+
title: "Navigate open app view",
|
|
2745
|
+
description: "Show another page of the open app in place, such as a filtered list or one record. Pass a path in the form read_view returns.",
|
|
2746
|
+
inputSchema: {
|
|
2747
|
+
type: "object",
|
|
2748
|
+
properties: {
|
|
2749
|
+
path: {
|
|
2750
|
+
type: "string",
|
|
2751
|
+
description: "App path starting with /, in the form read_view returns, e.g. a list with a search query."
|
|
2752
|
+
}
|
|
2753
|
+
},
|
|
2754
|
+
required: ["path"]
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
];
|
|
2758
|
+
const helper = appPageToolHelper();
|
|
2759
|
+
if (!helper) return tools;
|
|
2760
|
+
pageToolOrigins.clear();
|
|
2761
|
+
try {
|
|
2762
|
+
const summaries = await helper.tools();
|
|
2763
|
+
for (const summary of (Array.isArray(summaries) ? summaries : []).slice(0, maxPageTools)) {
|
|
2764
|
+
if (!summary || typeof summary.name !== "string") continue;
|
|
2765
|
+
if (tools.some((tool) => tool.name === summary.name)) continue;
|
|
2766
|
+
const full = typeof helper.describe === "function"
|
|
2767
|
+
? await helper.describe(summary.name, summary.origin)
|
|
2768
|
+
: null;
|
|
2769
|
+
const schema = full && full.inputSchema && full.inputSchema.type === "object"
|
|
2770
|
+
? full.inputSchema
|
|
2771
|
+
: { type: "object", properties: {} };
|
|
2772
|
+
tools.push({
|
|
2773
|
+
name: summary.name,
|
|
2774
|
+
...(summary.title ? { title: summary.title } : {}),
|
|
2775
|
+
description: String((full && full.description) || summary.description || summary.name),
|
|
2776
|
+
inputSchema: schema,
|
|
2777
|
+
...(summary.readOnly ? { annotations: { readOnlyHint: true } } : {})
|
|
2778
|
+
});
|
|
2779
|
+
pageToolOrigins.set(summary.name, summary.origin);
|
|
2780
|
+
}
|
|
2781
|
+
} catch (err) {
|
|
2782
|
+
console.warn("[agent-native] page tools unavailable to the MCP host", err);
|
|
2783
|
+
}
|
|
2784
|
+
return tools;
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
async function callViewTool(params) {
|
|
2788
|
+
const record = objectValue(params);
|
|
2789
|
+
const name = typeof record.name === "string" ? record.name : "";
|
|
2790
|
+
const args = objectValue(record.arguments);
|
|
2791
|
+
try {
|
|
2792
|
+
let result;
|
|
2793
|
+
if (name === readViewToolName) {
|
|
2794
|
+
result = readViewState();
|
|
2795
|
+
} else if (name === navigateViewToolName) {
|
|
2796
|
+
result = navigateView(args.path);
|
|
2797
|
+
} else {
|
|
2798
|
+
const helper = appPageToolHelper();
|
|
2799
|
+
if (!helper) throw new Error("Unknown view tool: " + name);
|
|
2800
|
+
const origin = pageToolOrigins.get(name);
|
|
2801
|
+
const outcome = await helper.call(name, args, {
|
|
2802
|
+
waitMs: pageToolWaitMs,
|
|
2803
|
+
...(origin ? { origin } : {})
|
|
2804
|
+
});
|
|
2805
|
+
if (!outcome || outcome.state !== "done") {
|
|
2806
|
+
throw new Error("Page tool " + name + " did not finish.");
|
|
2807
|
+
}
|
|
2808
|
+
if (!outcome.ok) throw new Error(outcome.error || "Page tool " + name + " failed.");
|
|
2809
|
+
result = outcome.result;
|
|
2810
|
+
}
|
|
2811
|
+
const structured = result && typeof result === "object" && !Array.isArray(result)
|
|
2812
|
+
? result
|
|
2813
|
+
: undefined;
|
|
2814
|
+
return {
|
|
2815
|
+
content: [{
|
|
2816
|
+
type: "text",
|
|
2817
|
+
text: typeof result === "string" ? result : JSON.stringify(result === undefined ? null : result)
|
|
2818
|
+
}],
|
|
2819
|
+
...(structured ? { structuredContent: structured } : {})
|
|
2820
|
+
};
|
|
2821
|
+
} catch (err) {
|
|
2822
|
+
return {
|
|
2823
|
+
isError: true,
|
|
2824
|
+
content: [{ type: "text", text: err && err.message ? err.message : String(err) }]
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2829
|
+
function notifyViewToolsChanged() {
|
|
2830
|
+
if (app && typeof app.sendToolListChanged === "function") {
|
|
2831
|
+
try {
|
|
2832
|
+
app.sendToolListChanged();
|
|
2833
|
+
} catch (error) {
|
|
2834
|
+
console.warn("[agent-native] tools/list_changed notification failed", error);
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2839
|
+
// The app registers its WebMCP tools from module scripts that keep running
|
|
2840
|
+
// after the transplant mounts, so the first list_changed can arrive before
|
|
2841
|
+
// they exist. Re-announce when the helper appears and on every toolchange.
|
|
2842
|
+
function watchPageTools() {
|
|
2843
|
+
notifyViewToolsChanged();
|
|
2844
|
+
if (pageToolWatchStarted) return;
|
|
2845
|
+
pageToolWatchStarted = true;
|
|
2846
|
+
let timer = null;
|
|
2847
|
+
const schedule = () => {
|
|
2848
|
+
clearTimeout(timer);
|
|
2849
|
+
timer = setTimeout(notifyViewToolsChanged, 250);
|
|
2850
|
+
};
|
|
2851
|
+
let watchedContext = null;
|
|
2852
|
+
let helperSeen = false;
|
|
2853
|
+
let ticks = 0;
|
|
2854
|
+
const check = () => {
|
|
2855
|
+
const context = document.modelContext;
|
|
2856
|
+
if (context && context !== watchedContext && typeof context.addEventListener === "function") {
|
|
2857
|
+
context.addEventListener("toolchange", schedule);
|
|
2858
|
+
watchedContext = context;
|
|
2859
|
+
}
|
|
2860
|
+
if (!helperSeen && appPageToolHelper()) {
|
|
2861
|
+
helperSeen = true;
|
|
2862
|
+
schedule();
|
|
2863
|
+
}
|
|
2864
|
+
if ((helperSeen && watchedContext) || ++ticks >= 20) clearInterval(poll);
|
|
2865
|
+
};
|
|
2866
|
+
const poll = setInterval(check, 500);
|
|
2867
|
+
check();
|
|
2868
|
+
}
|
|
2869
|
+
|
|
2645
2870
|
function createNativeMcpAppsBridge() {
|
|
2646
2871
|
let rpcId = 0;
|
|
2647
2872
|
let connectPromise = null;
|
|
@@ -2745,7 +2970,10 @@ export function embedApp(options = {}) {
|
|
|
2745
2970
|
"ui/initialize",
|
|
2746
2971
|
{
|
|
2747
2972
|
appInfo: { name: "Agent-Native Embed", version: "1.0.0" },
|
|
2748
|
-
appCapabilities: {
|
|
2973
|
+
appCapabilities: {
|
|
2974
|
+
availableDisplayModes: ["inline", "fullscreen"],
|
|
2975
|
+
tools: { listChanged: true }
|
|
2976
|
+
},
|
|
2749
2977
|
protocolVersion: "2026-01-26"
|
|
2750
2978
|
},
|
|
2751
2979
|
nativeBridgeInitializeTimeoutMs
|
|
@@ -2791,17 +3019,43 @@ export function embedApp(options = {}) {
|
|
|
2791
3019
|
sendSizeChanged(params) {
|
|
2792
3020
|
rpcNotify("ui/notifications/size-changed", objectValue(params));
|
|
2793
3021
|
},
|
|
3022
|
+
sendToolListChanged() {
|
|
3023
|
+
if (connectPromise) rpcNotify("notifications/tools/list_changed", {});
|
|
3024
|
+
},
|
|
2794
3025
|
async sendMessage(params) {
|
|
2795
3026
|
await nativeApp.connect();
|
|
2796
3027
|
return await rpcRequest("ui/message", objectValue(params));
|
|
2797
3028
|
}
|
|
2798
3029
|
};
|
|
2799
3030
|
|
|
3031
|
+
async function answerHostRequest(message) {
|
|
3032
|
+
let reply;
|
|
3033
|
+
try {
|
|
3034
|
+
if (message.method === "tools/list") {
|
|
3035
|
+
reply = { result: { tools: await listViewTools() } };
|
|
3036
|
+
} else if (message.method === "tools/call") {
|
|
3037
|
+
reply = { result: await callViewTool(message.params) };
|
|
3038
|
+
} else if (message.method === "ping" || message.method === "ui/resource-teardown") {
|
|
3039
|
+
reply = { result: {} };
|
|
3040
|
+
} else {
|
|
3041
|
+
reply = { error: { code: -32601, message: "Method not found: " + message.method } };
|
|
3042
|
+
}
|
|
3043
|
+
} catch (err) {
|
|
3044
|
+
reply = { error: { code: -32603, message: err && err.message ? err.message : String(err) } };
|
|
3045
|
+
}
|
|
3046
|
+
window.parent.postMessage({ jsonrpc: "2.0", id: message.id, ...reply }, "*");
|
|
3047
|
+
}
|
|
3048
|
+
|
|
2800
3049
|
function onMessage(event) {
|
|
2801
3050
|
if (event.source !== window.parent) return;
|
|
2802
3051
|
const message = event.data;
|
|
2803
3052
|
if (!message || message.jsonrpc !== "2.0") return;
|
|
2804
|
-
|
|
3053
|
+
const hasId = typeof message.id === "number" || typeof message.id === "string";
|
|
3054
|
+
if (hasId && typeof message.method === "string") {
|
|
3055
|
+
void answerHostRequest(message);
|
|
3056
|
+
return;
|
|
3057
|
+
}
|
|
3058
|
+
if (hasId) {
|
|
2805
3059
|
settleRpcResponse(message);
|
|
2806
3060
|
return;
|
|
2807
3061
|
}
|
|
@@ -2881,9 +3135,11 @@ export function embedApp(options = {}) {
|
|
|
2881
3135
|
const { App } = await import("${MCP_APP_IMPORT}");
|
|
2882
3136
|
app = new App(
|
|
2883
3137
|
{ name: "Agent-Native Embed", version: "1.0.0" },
|
|
2884
|
-
{},
|
|
3138
|
+
{ availableDisplayModes: ["inline", "fullscreen"], tools: { listChanged: true } },
|
|
2885
3139
|
{ autoResize: false }
|
|
2886
3140
|
);
|
|
3141
|
+
app.onlisttools = async () => ({ tools: await listViewTools() });
|
|
3142
|
+
app.oncalltool = async (params) => await callViewTool(params);
|
|
2887
3143
|
appConnectPromise = null;
|
|
2888
3144
|
app.ontoolinput = (params) => {
|
|
2889
3145
|
toolInput = params.arguments || {};
|
package/dist/mcp/oauth-route.js
CHANGED
|
@@ -310,6 +310,13 @@ function protectedResourcePathFromRequest(event) {
|
|
|
310
310
|
pathname = pathname.replace(/\/+$/, "");
|
|
311
311
|
if (!pathname || pathname === "/")
|
|
312
312
|
return undefined;
|
|
313
|
+
// RFC 9728 inserts the whole resource path after the well-known segment, so
|
|
314
|
+
// a mounted app (resource /dispatch/mcp) is asked about /dispatch/mcp.
|
|
315
|
+
const issuer = getMcpOAuthIssuer(event);
|
|
316
|
+
const basePath = issuer ? new URL(issuer).pathname.replace(/\/+$/, "") : "";
|
|
317
|
+
if (basePath && pathname.startsWith(`${basePath}/`)) {
|
|
318
|
+
pathname = pathname.slice(basePath.length);
|
|
319
|
+
}
|
|
313
320
|
return ([
|
|
314
321
|
MCP_PUBLIC_ROUTE_PREFIX,
|
|
315
322
|
MCP_LEGACY_ROUTE_PREFIX,
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
2
2
|
error?: undefined;
|
|
3
|
-
ok?: undefined;
|
|
4
3
|
count: number;
|
|
5
4
|
updated?: undefined;
|
|
5
|
+
ok?: undefined;
|
|
6
6
|
} | {
|
|
7
7
|
error?: undefined;
|
|
8
|
-
ok?: undefined;
|
|
9
8
|
count?: undefined;
|
|
10
9
|
updated: number;
|
|
11
|
-
} | {
|
|
12
10
|
ok?: undefined;
|
|
11
|
+
} | {
|
|
13
12
|
count?: undefined;
|
|
14
13
|
updated?: undefined;
|
|
15
14
|
error: string;
|
|
15
|
+
ok?: undefined;
|
|
16
16
|
} | {
|
|
17
17
|
error?: undefined;
|
|
18
18
|
count?: undefined;
|
|
@@ -27,10 +27,10 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
27
27
|
thumbsUpRate: number;
|
|
28
28
|
avgEvalScore: number;
|
|
29
29
|
} | {
|
|
30
|
-
summary?: undefined;
|
|
31
30
|
ok?: undefined;
|
|
32
31
|
error: string;
|
|
33
32
|
message: string;
|
|
33
|
+
summary?: undefined;
|
|
34
34
|
spans?: undefined;
|
|
35
35
|
} | {
|
|
36
36
|
error?: undefined;
|
|
@@ -40,30 +40,30 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
40
40
|
spans: import("./types.js").TraceSpan[];
|
|
41
41
|
} | {
|
|
42
42
|
error?: undefined;
|
|
43
|
-
summary?: undefined;
|
|
44
43
|
ok?: undefined;
|
|
45
44
|
message?: undefined;
|
|
45
|
+
summary?: undefined;
|
|
46
46
|
spans?: undefined;
|
|
47
47
|
traceMissing: true;
|
|
48
48
|
id: string;
|
|
49
49
|
} | {
|
|
50
50
|
error?: undefined;
|
|
51
|
-
summary?: undefined;
|
|
52
51
|
ok?: undefined;
|
|
53
52
|
message?: undefined;
|
|
53
|
+
summary?: undefined;
|
|
54
54
|
spans?: undefined;
|
|
55
55
|
traceMissing?: undefined;
|
|
56
56
|
id: string;
|
|
57
57
|
} | {
|
|
58
|
-
summary?: undefined;
|
|
59
58
|
ok?: undefined;
|
|
60
59
|
message?: undefined;
|
|
60
|
+
summary?: undefined;
|
|
61
61
|
spans?: undefined;
|
|
62
62
|
error: any;
|
|
63
63
|
} | {
|
|
64
64
|
error?: undefined;
|
|
65
|
-
summary?: undefined;
|
|
66
65
|
message?: undefined;
|
|
66
|
+
summary?: undefined;
|
|
67
67
|
spans?: undefined;
|
|
68
68
|
ok: boolean;
|
|
69
69
|
}>>;
|
package/dist/secrets/api-keys.js
CHANGED
|
@@ -10,8 +10,9 @@ import { readOrgMemberRole } from "../server/personal-provider-key-policy.js";
|
|
|
10
10
|
import { canonicalSecretKey, secretKeyNames } from "./key-aliases.js";
|
|
11
11
|
import { resolveSecretManagedBy } from "./managed-keys.js";
|
|
12
12
|
import { getRequiredSecret, listRequiredSecrets, } from "./register.js";
|
|
13
|
-
import { deleteAppSecret, listAppSecretsForScope,
|
|
13
|
+
import { deleteAppSecret, listAppSecretsForScope, } from "./storage.js";
|
|
14
14
|
import { describeSecretUsage } from "./usage.js";
|
|
15
|
+
import { isVaultManagedSecret } from "./vault-managed.js";
|
|
15
16
|
/**
|
|
16
17
|
* The rows the resolver reads for the caller, in its precedence order:
|
|
17
18
|
* personal, the pre-organization solo row, then the organization's.
|
|
@@ -63,7 +64,7 @@ function toEntry(caller, meta, owner, manages) {
|
|
|
63
64
|
const registered = getRequiredSecret(meta.key);
|
|
64
65
|
const managedBy = resolveSecretManagedBy(meta.key);
|
|
65
66
|
const provider = providerForName(meta.key);
|
|
66
|
-
const vault = isVaultSynced(meta.scope, meta
|
|
67
|
+
const vault = isVaultSynced(meta.scope, meta);
|
|
67
68
|
const mayChange = !managedBy && !vault && (owner === "user" || manages);
|
|
68
69
|
// Replace writes through the routes' own target, so it only applies when
|
|
69
70
|
// that target is this row; otherwise it would add a second row instead.
|
|
@@ -155,9 +156,9 @@ export async function listApiKeys(caller) {
|
|
|
155
156
|
canManageOrg: manages,
|
|
156
157
|
};
|
|
157
158
|
}
|
|
158
|
-
/** Vault
|
|
159
|
-
function isVaultSynced(scope,
|
|
160
|
-
return
|
|
159
|
+
/** The Vault owns the shared rows it writes; a user's own rows never belong to it. */
|
|
160
|
+
function isVaultSynced(scope, meta) {
|
|
161
|
+
return scope !== "user" && isVaultManagedSecret(meta);
|
|
161
162
|
}
|
|
162
163
|
/**
|
|
163
164
|
* Delete one saved key row. A provider key also takes its endpoint and older
|
|
@@ -181,7 +182,7 @@ export async function deleteApiKey(caller, input) {
|
|
|
181
182
|
const row = rows.find((meta) => meta.key === input.name);
|
|
182
183
|
if (!row)
|
|
183
184
|
return { status: "not-found" };
|
|
184
|
-
if (isVaultSynced(storedScope, row
|
|
185
|
+
if (isVaultSynced(storedScope, row))
|
|
185
186
|
return { status: "vault" };
|
|
186
187
|
const provider = AGENT_PROVIDER_CATALOG.find((option) => option.id === providerForName(input.name));
|
|
187
188
|
const names = provider
|
|
@@ -198,7 +199,7 @@ export async function deleteApiKey(caller, input) {
|
|
|
198
199
|
continue;
|
|
199
200
|
// Vault owns its rows, and a managed name is never the user's to delete,
|
|
200
201
|
// even when it sits beside the key being removed.
|
|
201
|
-
if (isVaultSynced(storedScope, meta
|
|
202
|
+
if (isVaultSynced(storedScope, meta))
|
|
202
203
|
continue;
|
|
203
204
|
if (resolveSecretManagedBy(name))
|
|
204
205
|
continue;
|
package/dist/secrets/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { registerRequiredSecret, listRequiredSecrets, getRequiredSecret, registerSecretUsage, getRegisteredSecretUsage, __resetSecretsRegistry, type RegisteredSecret, type SecretUsage, type SecretManagedBy, type SecretScope, type SecretKind, type SecretValidator, type ValidatorResult, } from "./register.js";
|
|
2
|
-
export { writeAppSecret, readAppSecret, hasAppSecret, readAppSecretMeta, deleteAppSecret, getAppSecretMeta, listAppSecretsForScope,
|
|
2
|
+
export { writeAppSecret, readAppSecret, hasAppSecret, readAppSecretMeta, readAppSecretMetaById, deleteAppSecret, deleteAppSecretById, getAppSecretMeta, listAppSecretsForScope, listAppSecretSummaries, updateAppSecretById, AppSecretKeyConflictError, last4, type SecretRef, type WriteSecretArgs, type ReadSecretResult, type SecretMeta, type AppSecretSummary, type UpdateAppSecretPatch, } from "./storage.js";
|
|
3
|
+
export { VAULT_SYNC_DESCRIPTION_PREFIX, isVaultManagedSecret, } from "./vault-managed.js";
|
|
3
4
|
export { APP_SECRETS_CREATE_SQL, appSecrets } from "./schema.js";
|
|
4
5
|
export { encryptSecretValue, decryptSecretValue, isEncryptedSecretValue, } from "./crypto.js";
|
|
5
6
|
export { createListSecretsHandler, createWriteSecretHandler, createTestSecretHandler, createAdHocSecretHandler, type SecretStatusPayload, type AdHocSecretPayload, } from "./routes.js";
|
package/dist/secrets/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { registerRequiredSecret, listRequiredSecrets, getRequiredSecret, registerSecretUsage, getRegisteredSecretUsage, __resetSecretsRegistry, } from "./register.js";
|
|
2
|
-
export { writeAppSecret, readAppSecret, hasAppSecret, readAppSecretMeta, deleteAppSecret, getAppSecretMeta, listAppSecretsForScope,
|
|
2
|
+
export { writeAppSecret, readAppSecret, hasAppSecret, readAppSecretMeta, readAppSecretMetaById, deleteAppSecret, deleteAppSecretById, getAppSecretMeta, listAppSecretsForScope, listAppSecretSummaries, updateAppSecretById, AppSecretKeyConflictError, last4, } from "./storage.js";
|
|
3
|
+
export { VAULT_SYNC_DESCRIPTION_PREFIX, isVaultManagedSecret, } from "./vault-managed.js";
|
|
3
4
|
export { APP_SECRETS_CREATE_SQL, appSecrets } from "./schema.js";
|
|
4
5
|
export { encryptSecretValue, decryptSecretValue, isEncryptedSecretValue, } from "./crypto.js";
|
|
5
6
|
export { createListSecretsHandler, createWriteSecretHandler, createTestSecretHandler, createAdHocSecretHandler, } from "./routes.js";
|
package/dist/secrets/routes.d.ts
CHANGED
|
@@ -55,18 +55,18 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
|
|
|
55
55
|
errorCode: "secret_managed_elsewhere";
|
|
56
56
|
managedBy: SecretManagedBy;
|
|
57
57
|
} | {
|
|
58
|
-
errorCode?: undefined;
|
|
59
|
-
error: string;
|
|
60
58
|
ok?: undefined;
|
|
59
|
+
error: string;
|
|
60
|
+
errorCode?: undefined;
|
|
61
61
|
status?: undefined;
|
|
62
62
|
} | {
|
|
63
|
+
ok?: undefined;
|
|
63
64
|
error: string;
|
|
64
65
|
errorCode: string;
|
|
65
|
-
ok?: undefined;
|
|
66
66
|
status?: undefined;
|
|
67
67
|
} | {
|
|
68
|
-
errorCode?: undefined;
|
|
69
68
|
error?: undefined;
|
|
69
|
+
errorCode?: undefined;
|
|
70
70
|
ok: boolean;
|
|
71
71
|
status: string;
|
|
72
72
|
} | {
|