@agent-native/dispatch 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/actions/create-pylon-ticket.d.ts +3 -0
- package/dist/actions/create-pylon-ticket.d.ts.map +1 -0
- package/dist/actions/create-pylon-ticket.js +94 -0
- package/dist/actions/create-pylon-ticket.js.map +1 -0
- package/dist/actions/create-vault-grant.js +1 -1
- package/dist/actions/create-vault-grant.js.map +1 -1
- package/dist/actions/create-vault-secret.d.ts.map +1 -1
- package/dist/actions/create-vault-secret.js +4 -3
- package/dist/actions/create-vault-secret.js.map +1 -1
- package/dist/actions/get-vault-access-settings.d.ts +3 -0
- package/dist/actions/get-vault-access-settings.d.ts.map +1 -0
- package/dist/actions/get-vault-access-settings.js +10 -0
- package/dist/actions/get-vault-access-settings.js.map +1 -0
- package/dist/actions/grant-vault-secrets-to-app.js +1 -1
- package/dist/actions/grant-vault-secrets-to-app.js.map +1 -1
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +8 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/list-integrations-catalog.js +1 -1
- package/dist/actions/list-integrations-catalog.js.map +1 -1
- package/dist/actions/list-vault-grants.js +1 -1
- package/dist/actions/list-vault-grants.js.map +1 -1
- package/dist/actions/list-workspace-apps.d.ts.map +1 -1
- package/dist/actions/list-workspace-apps.js +5 -1
- package/dist/actions/list-workspace-apps.js.map +1 -1
- package/dist/actions/set-vault-access-settings.d.ts +3 -0
- package/dist/actions/set-vault-access-settings.d.ts.map +1 -0
- package/dist/actions/set-vault-access-settings.js +13 -0
- package/dist/actions/set-vault-access-settings.js.map +1 -0
- package/dist/actions/start-workspace-app-creation.d.ts.map +1 -1
- package/dist/actions/start-workspace-app-creation.js +6 -0
- package/dist/actions/start-workspace-app-creation.js.map +1 -1
- package/dist/actions/sync-vault-to-app.js +1 -1
- package/dist/actions/sync-vault-to-app.js.map +1 -1
- package/dist/actions/update-workspace-app-metadata.d.ts +3 -0
- package/dist/actions/update-workspace-app-metadata.d.ts.map +1 -0
- package/dist/actions/update-workspace-app-metadata.js +30 -0
- package/dist/actions/update-workspace-app-metadata.js.map +1 -0
- package/dist/actions/view-screen.d.ts.map +1 -1
- package/dist/actions/view-screen.js +4 -2
- package/dist/actions/view-screen.js.map +1 -1
- package/dist/components/app-keys-popover.d.ts.map +1 -1
- package/dist/components/app-keys-popover.js +17 -5
- package/dist/components/app-keys-popover.js.map +1 -1
- package/dist/components/create-app-popover.d.ts.map +1 -1
- package/dist/components/create-app-popover.js +38 -14
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/dispatch-shell.d.ts +4 -4
- package/dist/components/dispatch-shell.d.ts.map +1 -1
- package/dist/components/dispatch-shell.js +6 -6
- package/dist/components/dispatch-shell.js.map +1 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +10 -3
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/messaging-setup-panel.d.ts.map +1 -1
- package/dist/components/messaging-setup-panel.js +2 -2
- package/dist/components/messaging-setup-panel.js.map +1 -1
- package/dist/components/workspace-app-card.d.ts.map +1 -1
- package/dist/components/workspace-app-card.js +41 -2
- package/dist/components/workspace-app-card.js.map +1 -1
- package/dist/hooks/use-navigation-state.js +12 -5
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/lib/catch-all-target.d.ts +2 -0
- package/dist/lib/catch-all-target.d.ts.map +1 -0
- package/dist/lib/catch-all-target.js +95 -0
- package/dist/lib/catch-all-target.js.map +1 -0
- package/dist/lib/workspace-apps.d.ts +9 -0
- package/dist/lib/workspace-apps.d.ts.map +1 -1
- package/dist/lib/workspace-apps.js.map +1 -1
- package/dist/routes/pages/$appId.d.ts +2 -24
- package/dist/routes/pages/$appId.d.ts.map +1 -1
- package/dist/routes/pages/$appId.js +42 -8
- package/dist/routes/pages/$appId.js.map +1 -1
- package/dist/routes/pages/approval.d.ts.map +1 -1
- package/dist/routes/pages/approval.js +2 -1
- package/dist/routes/pages/approval.js.map +1 -1
- package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
- package/dist/routes/pages/apps.$appId.js +2 -1
- package/dist/routes/pages/apps.$appId.js.map +1 -1
- package/dist/routes/pages/integrations.d.ts.map +1 -1
- package/dist/routes/pages/integrations.js +20 -15
- package/dist/routes/pages/integrations.js.map +1 -1
- package/dist/routes/pages/new-app.js +1 -1
- package/dist/routes/pages/new-app.js.map +1 -1
- package/dist/routes/pages/overview.d.ts.map +1 -1
- package/dist/routes/pages/overview.js +14 -1
- package/dist/routes/pages/overview.js.map +1 -1
- package/dist/routes/pages/vault.d.ts.map +1 -1
- package/dist/routes/pages/vault.js +25 -6
- package/dist/routes/pages/vault.js.map +1 -1
- package/dist/routes/pages/workspace.d.ts.map +1 -1
- package/dist/routes/pages/workspace.js +5 -3
- package/dist/routes/pages/workspace.js.map +1 -1
- package/dist/server/lib/app-creation-store.d.ts +13 -0
- package/dist/server/lib/app-creation-store.d.ts.map +1 -1
- package/dist/server/lib/app-creation-store.js +295 -9
- package/dist/server/lib/app-creation-store.js.map +1 -1
- package/dist/server/lib/env-config.d.ts.map +1 -1
- package/dist/server/lib/env-config.js +5 -0
- package/dist/server/lib/env-config.js.map +1 -1
- package/dist/server/lib/onboarding-steps.d.ts +12 -0
- package/dist/server/lib/onboarding-steps.d.ts.map +1 -0
- package/dist/server/lib/onboarding-steps.js +47 -0
- package/dist/server/lib/onboarding-steps.js.map +1 -0
- package/dist/server/lib/vault-store.d.ts +55 -0
- package/dist/server/lib/vault-store.d.ts.map +1 -1
- package/dist/server/lib/vault-store.js +210 -41
- package/dist/server/lib/vault-store.js.map +1 -1
- package/dist/server/plugins/agent-chat.d.ts.map +1 -1
- package/dist/server/plugins/agent-chat.js +2 -1
- package/dist/server/plugins/agent-chat.js.map +1 -1
- package/dist/server/plugins/core-routes.d.ts.map +1 -1
- package/dist/server/plugins/core-routes.js +4 -0
- package/dist/server/plugins/core-routes.js.map +1 -1
- package/dist/server/plugins/integrations.js +2 -2
- package/dist/server/plugins/integrations.js.map +1 -1
- package/package.json +13 -11
- package/src/actions/create-pylon-ticket.ts +109 -0
- package/src/actions/create-vault-grant.ts +1 -1
- package/src/actions/create-vault-secret.ts +4 -3
- package/src/actions/get-vault-access-settings.ts +11 -0
- package/src/actions/grant-vault-secrets-to-app.ts +1 -1
- package/src/actions/index.ts +8 -0
- package/src/actions/list-integrations-catalog.ts +1 -1
- package/src/actions/list-vault-grants.ts +1 -1
- package/src/actions/list-workspace-apps.ts +5 -1
- package/src/actions/set-vault-access-settings.ts +16 -0
- package/src/actions/start-workspace-app-creation.ts +8 -0
- package/src/actions/sync-vault-to-app.ts +1 -1
- package/src/actions/update-workspace-app-metadata.ts +32 -0
- package/src/actions/view-screen.ts +4 -1
- package/src/components/app-keys-popover.tsx +38 -8
- package/src/components/create-app-popover.tsx +47 -14
- package/src/components/dispatch-shell.tsx +16 -15
- package/src/components/layout/Layout.tsx +11 -5
- package/src/components/messaging-setup-panel.tsx +54 -39
- package/src/components/workspace-app-card.tsx +102 -0
- package/src/hooks/use-navigation-state.ts +10 -4
- package/src/lib/catch-all-target.spec.ts +218 -0
- package/src/lib/catch-all-target.ts +99 -0
- package/src/lib/workspace-apps.ts +9 -0
- package/src/routes/pages/$appId.tsx +45 -7
- package/src/routes/pages/approval.tsx +33 -3
- package/src/routes/pages/apps.$appId.tsx +6 -1
- package/src/routes/pages/integrations.tsx +57 -18
- package/src/routes/pages/new-app.tsx +1 -1
- package/src/routes/pages/overview.tsx +69 -29
- package/src/routes/pages/vault.tsx +101 -21
- package/src/routes/pages/workspace.tsx +21 -3
- package/src/server/lib/app-creation-store.spec.ts +61 -2
- package/src/server/lib/app-creation-store.ts +386 -11
- package/src/server/lib/env-config.ts +5 -0
- package/src/server/lib/onboarding-steps.ts +49 -0
- package/src/server/lib/vault-store.spec.ts +69 -0
- package/src/server/lib/vault-store.ts +266 -49
- package/src/server/plugins/agent-chat.ts +2 -1
- package/src/server/plugins/core-routes.ts +5 -0
- package/src/server/plugins/integrations.ts +2 -2
|
@@ -10,7 +10,7 @@ import { defineAction } from "@agent-native/core";
|
|
|
10
10
|
import { readAppState } from "@agent-native/core/application-state";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
import { listOverview } from "../server/lib/dispatch-store.js";
|
|
13
|
-
import { listVaultOverview, listSecrets, listGrants, listRequests, } from "../server/lib/vault-store.js";
|
|
13
|
+
import { listVaultOverview, listSecrets, listGrants, listRequests, getVaultAccessSettings, } from "../server/lib/vault-store.js";
|
|
14
14
|
import { listWorkspaceApps } from "../server/lib/app-creation-store.js";
|
|
15
15
|
import { listDispatchUsageMetrics } from "../server/lib/usage-metrics-store.js";
|
|
16
16
|
import { listWorkspaceResourceOptions } from "../server/lib/workspace-resources-store.js";
|
|
@@ -65,11 +65,13 @@ export default defineAction({
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
if (navigation?.view === "vault" || navigation?.view === "new-app") {
|
|
68
|
-
const [secrets, grants, requests] = await Promise.all([
|
|
68
|
+
const [secrets, grants, requests, access] = await Promise.all([
|
|
69
69
|
listSecrets(),
|
|
70
70
|
listGrants(),
|
|
71
71
|
listRequests({ status: "pending" }),
|
|
72
|
+
getVaultAccessSettings(),
|
|
72
73
|
]);
|
|
74
|
+
screen.vaultAccessMode = access.mode;
|
|
73
75
|
screen.vaultSecrets = secrets.map((s) => ({
|
|
74
76
|
id: s.id,
|
|
75
77
|
name: s.name,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-screen.js","sourceRoot":"","sources":["../../src/actions/view-screen.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,YAAY,
|
|
1
|
+
{"version":3,"file":"view-screen.js","sourceRoot":"","sources":["../../src/actions/view-screen.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * See what the user is currently looking at on screen.\n *\n * Reads and returns the current navigation state from application state.\n *\n * Usage:\n * pnpm action view-screen\n */\n\nimport { defineAction } from \"@agent-native/core\";\nimport { readAppState } from \"@agent-native/core/application-state\";\nimport { z } from \"zod\";\nimport { listOverview } from \"../server/lib/dispatch-store.js\";\nimport {\n listVaultOverview,\n listSecrets,\n listGrants,\n listRequests,\n getVaultAccessSettings,\n} from \"../server/lib/vault-store.js\";\nimport { listWorkspaceApps } from \"../server/lib/app-creation-store.js\";\nimport { listDispatchUsageMetrics } from \"../server/lib/usage-metrics-store.js\";\nimport { listWorkspaceResourceOptions } from \"../server/lib/workspace-resources-store.js\";\nimport {\n getAgentThreadDebug,\n listThreadDebugSources,\n searchAgentThreads,\n} from \"../server/lib/thread-debug-store.js\";\n\nexport default defineAction({\n description:\n \"See what the user is currently looking at in the dispatch UI, including navigation state and a compact operational summary.\",\n schema: z.object({}),\n http: false,\n run: async () => {\n const [navigation, overview, vaultOverview] = await Promise.all([\n readAppState(\"navigation\"),\n listOverview(),\n listVaultOverview(),\n ]);\n\n const screen: Record<string, unknown> = {\n counts: { ...overview.counts, ...vaultOverview },\n approvalPolicy: overview.settings,\n };\n if (navigation) screen.navigation = navigation;\n if (navigation?.view === \"overview\") {\n screen.recentAudit = overview.recentAudit.slice(0, 5);\n screen.recentApprovals = overview.recentApprovals.slice(0, 5);\n }\n if (navigation?.view === \"destinations\") {\n screen.recentDestinations = overview.recentDestinations;\n }\n if (\n navigation?.view === \"overview\" ||\n navigation?.view === \"metrics\" ||\n navigation?.view === \"apps\" ||\n navigation?.view === \"new-app\"\n ) {\n screen.workspaceApps = await listWorkspaceApps({\n includeAgentCards: true,\n });\n }\n if (navigation?.view === \"metrics\") {\n try {\n const metrics = await listDispatchUsageMetrics({ sinceDays: 30 });\n screen.usageMetrics = {\n billing: metrics.billing,\n totals: metrics.totals,\n byApp: metrics.byApp.slice(0, 8),\n byUser: metrics.byUser.slice(0, 8),\n appAccess: metrics.appAccess\n .filter((app) => !app.isDispatch)\n .slice(0, 8),\n };\n } catch (error) {\n screen.usageMetricsError =\n error instanceof Error ? error.message : String(error);\n }\n }\n if (navigation?.view === \"vault\" || navigation?.view === \"new-app\") {\n const [secrets, grants, requests, access] = await Promise.all([\n listSecrets(),\n listGrants(),\n listRequests({ status: \"pending\" }),\n getVaultAccessSettings(),\n ]);\n screen.vaultAccessMode = access.mode;\n screen.vaultSecrets = secrets.map((s) => ({\n id: s.id,\n name: s.name,\n credentialKey: s.credentialKey,\n provider: s.provider,\n }));\n screen.vaultActiveGrants = grants\n .filter((g) => g.status === \"active\")\n .map((g) => ({ secretId: g.secretId, appId: g.appId }));\n screen.vaultPendingRequests = requests;\n }\n if (navigation?.view === \"workspace\" || navigation?.view === \"new-app\") {\n screen.workspaceResources = await listWorkspaceResourceOptions();\n }\n if (navigation?.view === \"thread-debug\") {\n try {\n const nav = navigation as Record<string, any>;\n screen.threadDebugSources = await listThreadDebugSources();\n if (nav.query) {\n screen.threadDebugResults = await searchAgentThreads({\n sourceId: nav.sourceId,\n query: nav.query,\n ownerEmail: nav.ownerEmail,\n limit: 10,\n });\n }\n if (nav.threadId) {\n const detail = await getAgentThreadDebug({\n sourceId: nav.sourceId,\n threadId: nav.threadId,\n ownerEmail: nav.ownerEmail,\n maxRuns: 5,\n maxEvents: 80,\n maxTraceSpans: 50,\n });\n screen.threadDebugSelection = {\n source: detail.source,\n thread: detail.thread,\n messageCount: detail.messages.length,\n runCount: detail.runs.length,\n debug: detail.debug,\n debugRuns: (detail as any).debugRuns?.slice(-5) ?? [],\n messages: detail.messages.slice(-6),\n };\n }\n } catch (error) {\n screen.threadDebugError =\n error instanceof Error ? error.message : String(error);\n }\n }\n\n if (Object.keys(screen).length === 0) {\n return \"No application state found. Is the app running?\";\n }\n return JSON.stringify(screen, null, 2);\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-keys-popover.d.ts","sourceRoot":"","sources":["../../src/components/app-keys-popover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"app-keys-popover.d.ts","sourceRoot":"","sources":["../../src/components/app-keys-popover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAgC1D,UAAU,mBAAmB;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC5C;AAED,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,OAAO,EACP,OAAO,EACP,KAAa,EACb,IAAe,GAChB,EAAE,mBAAmB,2CAiCrB"}
|
|
@@ -5,6 +5,7 @@ import { IconCheck, IconLoader2, IconRefresh, IconSettings, } from "@tabler/icon
|
|
|
5
5
|
import { toast } from "sonner";
|
|
6
6
|
import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
|
|
7
7
|
import { Button } from "../components/ui/button.js";
|
|
8
|
+
import { Skeleton } from "../components/ui/skeleton.js";
|
|
8
9
|
export function AppKeysPopover({ appId, appName, trigger, align = "end", side = "bottom", }) {
|
|
9
10
|
const [open, setOpen] = useState(false);
|
|
10
11
|
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: trigger ?? (_jsx("button", { type: "button", "aria-label": `Manage keys for ${appName}`, onClick: (event) => {
|
|
@@ -17,6 +18,8 @@ export function AppKeysPopover({ appId, appName, trigger, align = "end", side =
|
|
|
17
18
|
function AppKeysPanel({ appId, appName }) {
|
|
18
19
|
const { data: secrets = [], isLoading: secretsLoading } = useActionQuery("list-vault-secret-options", {});
|
|
19
20
|
const { data: grants = [], isLoading: grantsLoading, refetch: refetchGrants, } = useActionQuery("list-vault-grants", { appId });
|
|
21
|
+
const { data: accessSettings, isLoading: accessLoading } = useActionQuery("get-vault-access-settings", {});
|
|
22
|
+
const accessMode = accessSettings?.mode === "manual" ? "manual" : "all-apps";
|
|
20
23
|
const grantBySecretId = useMemo(() => {
|
|
21
24
|
const map = new Map();
|
|
22
25
|
for (const grant of grants) {
|
|
@@ -55,10 +58,13 @@ function AppKeysPanel({ appId, appName }) {
|
|
|
55
58
|
},
|
|
56
59
|
onError: (err) => toast.error(`Sync failed: ${String(err)}`),
|
|
57
60
|
});
|
|
58
|
-
const isLoading = secretsLoading || grantsLoading;
|
|
61
|
+
const isLoading = secretsLoading || grantsLoading || accessLoading;
|
|
59
62
|
const grantedCount = grantBySecretId.size;
|
|
60
63
|
const typedSecrets = secrets;
|
|
64
|
+
const allApps = accessMode !== "manual";
|
|
61
65
|
const toggleSecret = (secret) => {
|
|
66
|
+
if (allApps)
|
|
67
|
+
return;
|
|
62
68
|
if (pendingSecretIds.has(secret.id))
|
|
63
69
|
return;
|
|
64
70
|
const existing = grantBySecretId.get(secret.id);
|
|
@@ -71,14 +77,20 @@ function AppKeysPanel({ appId, appName }) {
|
|
|
71
77
|
grantMutation.mutate({ secretId: secret.id, appId }, { onSettled });
|
|
72
78
|
}
|
|
73
79
|
};
|
|
74
|
-
return (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-1", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("p", { className: "truncate text-sm font-semibold text-foreground", children: ["Keys for ", appName] }),
|
|
75
|
-
|
|
80
|
+
return (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-1", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs("p", { className: "truncate text-sm font-semibold text-foreground", children: ["Keys for ", appName] }), _jsx("p", { className: "text-[11px] text-muted-foreground", children: allApps
|
|
81
|
+
? `${typedSecrets.length} available`
|
|
82
|
+
: `${grantedCount} of ${typedSecrets.length} granted` })] }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", disabled: syncMutation.isPending ||
|
|
83
|
+
typedSecrets.length === 0 ||
|
|
84
|
+
(!allApps && grantedCount === 0), onClick: () => syncMutation.mutate({ appId }), className: "h-7 px-2", children: [syncMutation.isPending ? (_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" })) : (_jsx(IconRefresh, { className: "h-3 w-3" })), _jsx("span", { className: "ml-1 text-xs", children: "Sync" })] })] }), _jsx("div", { className: "max-h-[320px] space-y-1.5 overflow-y-auto rounded-md border border-border bg-card p-1.5", children: isLoading ? (_jsx("div", { className: "space-y-1.5 p-1.5", children: Array.from({ length: 3 }).map((_, index) => (_jsxs("div", { className: "flex items-start gap-3 rounded-md px-2.5 py-2", children: [_jsx(Skeleton, { className: "mt-0.5 h-4 w-4 shrink-0 rounded" }), _jsxs("div", { className: "flex-1 space-y-1.5", children: [_jsx(Skeleton, { className: "h-3 w-1/2" }), _jsx(Skeleton, { className: "h-3 w-3/4" })] })] }, index))) })) : typedSecrets.length === 0 ? (_jsx("p", { className: "rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground", children: "No vault keys yet. Add one from the Vault page." })) : (typedSecrets.map((secret) => {
|
|
85
|
+
const granted = allApps || grantBySecretId.has(secret.id);
|
|
76
86
|
const pending = pendingSecretIds.has(secret.id);
|
|
77
|
-
return (_jsxs("button", { type: "button", "aria-pressed": granted, disabled: pending, onClick: () => toggleSecret(secret), className: `flex w-full items-start gap-3 rounded-md px-2.5 py-2 text-left text-sm disabled:cursor-not-allowed disabled:opacity-60 ${pending ? "" : "cursor-pointer"} ${granted
|
|
87
|
+
return (_jsxs("button", { type: "button", "aria-pressed": granted, disabled: pending || allApps, onClick: () => toggleSecret(secret), className: `flex w-full items-start gap-3 rounded-md px-2.5 py-2 text-left text-sm disabled:cursor-not-allowed disabled:opacity-60 ${pending || allApps ? "" : "cursor-pointer"} ${granted
|
|
78
88
|
? "border border-primary/45 bg-primary/5"
|
|
79
89
|
: "border border-transparent hover:border-muted-foreground/30 hover:bg-accent/35"}`, children: [_jsx("span", { className: `mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border ${granted
|
|
80
90
|
? "border-primary/60 bg-primary/10 text-primary"
|
|
81
|
-
: "border-muted-foreground/35 text-transparent"}`, children: granted ? _jsx(IconCheck, { className: "h-3 w-3" }) : null }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block truncate font-medium", children: secret.credentialKey }), _jsx("span", { className: "block truncate text-xs text-muted-foreground/70", children:
|
|
91
|
+
: "border-muted-foreground/35 text-transparent"}`, children: granted ? _jsx(IconCheck, { className: "h-3 w-3" }) : null }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block truncate font-medium", children: secret.credentialKey }), _jsx("span", { className: "block truncate text-xs text-muted-foreground/70", children: allApps
|
|
92
|
+
? "Available to this app"
|
|
93
|
+
: secret.provider || secret.name || "Vault secret" })] })] }, secret.id));
|
|
82
94
|
})) })] }));
|
|
83
95
|
}
|
|
84
96
|
//# sourceMappingURL=app-keys-popover.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-keys-popover.js","sourceRoot":"","sources":["../../src/components/app-keys-popover.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,YAAY,GACb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/B,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAyBhD,MAAM,UAAU,cAAc,CAAC,EAC7B,KAAK,EACL,OAAO,EACP,OAAO,EACP,KAAK,GAAG,KAAK,EACb,IAAI,GAAG,QAAQ,GACK;IACpB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExC,OAAO,CACL,MAAC,OAAO,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,aACxC,KAAC,cAAc,IAAC,OAAO,kBACpB,OAAO,IAAI,CACV,iBACE,IAAI,EAAC,QAAQ,gBACD,mBAAmB,OAAO,EAAE,EACxC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;wBACjB,2DAA2D;wBAC3D,6DAA6D;wBAC7D,mBAAmB;wBACnB,KAAK,CAAC,eAAe,EAAE,CAAC;oBAC1B,CAAC,EACD,SAAS,EAAC,oLAAoL,YAE9L,KAAC,YAAY,IAAC,IAAI,EAAE,EAAE,GAAI,GACnB,CACV,GACc,EACjB,KAAC,cAAc,IACb,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,CAAC,EACb,SAAS,EAAC,UAAU,EACpB,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE,YAE1C,IAAI,CAAC,CAAC,CAAC,KAAC,YAAY,IAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAI,CAAC,CAAC,CAAC,IAAI,GAChD,IACT,CACX,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAsC;IAC1E,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,cAAc,CACtE,2BAA2B,EAC3B,EAAE,CACH,CAAC;IACF,MAAM,EACJ,IAAI,EAAE,MAAM,GAAG,EAAE,EACjB,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,aAAa,GACvB,GAAG,cAAc,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAEnD,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,EAAE;QACnC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAsB,CAAC;QAC1C,KAAK,MAAM,KAAK,IAAI,MAAsB,EAAE,CAAC;YAC3C,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ;gBAAE,SAAS;YACxD,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,wEAAwE;IACxE,sEAAsE;IACtE,oEAAoE;IACpE,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CACtD,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAChB,CAAC;IACF,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,OAAgB,EAAE,EAAE,CACzD,mBAAmB,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,OAAO;YAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;;YAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEL,MAAM,aAAa,GAAG,iBAAiB,CAAC,oBAAoB,EAAE;QAC5D,SAAS,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE;QAChC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;KACjE,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,iBAAiB,CAAC,oBAAoB,EAAE;QAC7D,SAAS,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE;QAChC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,qBAAqB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;KAClE,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,iBAAiB,CAAC,mBAAmB,EAAE;QAC1D,SAAS,EAAE,CAAC,MAAW,EAAE,EAAE;YACzB,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC;YACnC,KAAK,CAAC,OAAO,CACX,MAAM,GAAG,CAAC;gBACR,CAAC,CAAC,UAAU,MAAM,OAAO,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,OAAO,EAAE;gBAChE,CAAC,CAAC,GAAG,OAAO,gBAAgB,CAC/B,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;KAC7D,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,cAAc,IAAI,aAAa,CAAC;IAClD,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC;IAC1C,MAAM,YAAY,GAAG,OAAwB,CAAC;IAE9C,MAAM,YAAY,GAAG,CAAC,MAAmB,EAAE,EAAE;QAC3C,IAAI,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,OAAO;QAC5C,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAChD,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC7B,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACtD,IAAI,QAAQ,EAAE,CAAC;YACb,cAAc,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QACjE,CAAC;aAAM,CAAC;YACN,aAAa,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QACtE,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,qBAAqB,aAClC,eAAK,SAAS,EAAC,8CAA8C,aAC3D,eAAK,SAAS,EAAC,SAAS,aACtB,aAAG,SAAS,EAAC,gDAAgD,0BACjD,OAAO,IACf,EACJ,aAAG,SAAS,EAAC,mCAAmC,aAC7C,YAAY,UAAM,YAAY,CAAC,MAAM,gBACpC,IACA,EACN,MAAC,MAAM,IACL,IAAI,EAAC,QAAQ,EACb,OAAO,EAAC,SAAS,EACjB,IAAI,EAAC,IAAI,EACT,QAAQ,EAAE,YAAY,CAAC,SAAS,IAAI,YAAY,KAAK,CAAC,EACtD,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAC7C,SAAS,EAAC,UAAU,aAEnB,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,CACxB,KAAC,WAAW,IAAC,SAAS,EAAC,sBAAsB,GAAG,CACjD,CAAC,CAAC,CAAC,CACF,KAAC,WAAW,IAAC,SAAS,EAAC,SAAS,GAAG,CACpC,EACD,eAAM,SAAS,EAAC,cAAc,qBAAY,IACnC,IACL,EAEN,cAAK,SAAS,EAAC,yFAAyF,YACrG,SAAS,CAAC,CAAC,CAAC,CACX,YAAG,SAAS,EAAC,yCAAyC,8BAAa,CACpE,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAC9B,YAAG,SAAS,EAAC,uFAAuF,gEAEhG,CACL,CAAC,CAAC,CAAC,CACF,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;oBAC1B,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBAC/C,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBAChD,OAAO,CACL,kBAEE,IAAI,EAAC,QAAQ,kBACC,OAAO,EACrB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EACnC,SAAS,EAAE,0HACT,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBACjB,IACE,OAAO;4BACL,CAAC,CAAC,uCAAuC;4BACzC,CAAC,CAAC,+EACN,EAAE,aAEF,eACE,SAAS,EAAE,2EACT,OAAO;oCACL,CAAC,CAAC,8CAA8C;oCAChD,CAAC,CAAC,6CACN,EAAE,YAED,OAAO,CAAC,CAAC,CAAC,KAAC,SAAS,IAAC,SAAS,EAAC,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,GAC9C,EACP,gBAAM,SAAS,EAAC,gBAAgB,aAC9B,eAAM,SAAS,EAAC,4BAA4B,YACzC,MAAM,CAAC,aAAa,GAChB,EACP,eAAM,SAAS,EAAC,iDAAiD,YAC9D,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,IAAI,cAAc,GAC5C,IACF,KA7BF,MAAM,CAAC,EAAE,CA8BP,CACV,CAAC;gBACJ,CAAC,CAAC,CACH,GACG,IACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { useActionMutation, useActionQuery } from \"@agent-native/core/client\";\nimport {\n IconCheck,\n IconLoader2,\n IconRefresh,\n IconSettings,\n} from \"@tabler/icons-react\";\nimport { toast } from \"sonner\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { Button } from \"@/components/ui/button\";\n\ninterface VaultSecret {\n id: string;\n name?: string | null;\n credentialKey: string;\n provider?: string | null;\n description?: string | null;\n}\n\ninterface VaultGrant {\n id: string;\n secretId: string;\n appId: string;\n status?: string | null;\n}\n\ninterface AppKeysPopoverProps {\n appId: string;\n appName: string;\n trigger?: ReactNode;\n align?: \"start\" | \"center\" | \"end\";\n side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n}\n\nexport function AppKeysPopover({\n appId,\n appName,\n trigger,\n align = \"end\",\n side = \"bottom\",\n}: AppKeysPopoverProps) {\n const [open, setOpen] = useState(false);\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n {trigger ?? (\n <button\n type=\"button\"\n aria-label={`Manage keys for ${appName}`}\n onClick={(event) => {\n // Keep parent card click handlers from also firing. Do not\n // preventDefault here: Radix uses the same click to open the\n // popover trigger.\n event.stopPropagation();\n }}\n className=\"flex h-7 w-7 cursor-pointer items-center justify-center rounded-md border border-transparent text-muted-foreground/70 hover:border-border hover:bg-accent/40 hover:text-foreground\"\n >\n <IconSettings size={14} />\n </button>\n )}\n </PopoverTrigger>\n <PopoverContent\n align={align}\n side={side}\n sideOffset={6}\n className=\"w-80 p-3\"\n onClick={(event) => event.stopPropagation()}\n >\n {open ? <AppKeysPanel appId={appId} appName={appName} /> : null}\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction AppKeysPanel({ appId, appName }: { appId: string; appName: string }) {\n const { data: secrets = [], isLoading: secretsLoading } = useActionQuery(\n \"list-vault-secret-options\",\n {},\n );\n const {\n data: grants = [],\n isLoading: grantsLoading,\n refetch: refetchGrants,\n } = useActionQuery(\"list-vault-grants\", { appId });\n\n const grantBySecretId = useMemo(() => {\n const map = new Map<string, VaultGrant>();\n for (const grant of grants as VaultGrant[]) {\n if (grant.status && grant.status !== \"active\") continue;\n map.set(grant.secretId, grant);\n }\n return map;\n }, [grants]);\n\n // Track per-secret pending state so a fast double-click on the same row\n // can't queue two `create-vault-grant` requests (which would silently\n // create duplicate active grants — a later revoke only clears one).\n const [pendingSecretIds, setPendingSecretIds] = useState<Set<string>>(\n () => new Set(),\n );\n const markPending = (secretId: string, pending: boolean) =>\n setPendingSecretIds((prev) => {\n const next = new Set(prev);\n if (pending) next.add(secretId);\n else next.delete(secretId);\n return next;\n });\n\n const grantMutation = useActionMutation(\"create-vault-grant\", {\n onSuccess: () => refetchGrants(),\n onError: (err) => toast.error(`Could not grant: ${String(err)}`),\n });\n\n const revokeMutation = useActionMutation(\"revoke-vault-grant\", {\n onSuccess: () => refetchGrants(),\n onError: (err) => toast.error(`Could not revoke: ${String(err)}`),\n });\n\n const syncMutation = useActionMutation(\"sync-vault-to-app\", {\n onSuccess: (result: any) => {\n const synced = result?.synced ?? 0;\n toast.success(\n synced > 0\n ? `Synced ${synced} key${synced === 1 ? \"\" : \"s\"} to ${appName}`\n : `${appName} is up to date`,\n );\n },\n onError: (err) => toast.error(`Sync failed: ${String(err)}`),\n });\n\n const isLoading = secretsLoading || grantsLoading;\n const grantedCount = grantBySecretId.size;\n const typedSecrets = secrets as VaultSecret[];\n\n const toggleSecret = (secret: VaultSecret) => {\n if (pendingSecretIds.has(secret.id)) return;\n const existing = grantBySecretId.get(secret.id);\n markPending(secret.id, true);\n const onSettled = () => markPending(secret.id, false);\n if (existing) {\n revokeMutation.mutate({ grantId: existing.id }, { onSettled });\n } else {\n grantMutation.mutate({ secretId: secret.id, appId }, { onSettled });\n }\n };\n\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex items-center justify-between gap-2 px-1\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-semibold text-foreground\">\n Keys for {appName}\n </p>\n <p className=\"text-[11px] text-muted-foreground\">\n {grantedCount} of {typedSecrets.length} granted\n </p>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={syncMutation.isPending || grantedCount === 0}\n onClick={() => syncMutation.mutate({ appId })}\n className=\"h-7 px-2\"\n >\n {syncMutation.isPending ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : (\n <IconRefresh className=\"h-3 w-3\" />\n )}\n <span className=\"ml-1 text-xs\">Sync</span>\n </Button>\n </div>\n\n <div className=\"max-h-[320px] space-y-1.5 overflow-y-auto rounded-md border border-border bg-card p-1.5\">\n {isLoading ? (\n <p className=\"px-3 py-3 text-xs text-muted-foreground\">Loading…</p>\n ) : typedSecrets.length === 0 ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n No vault keys yet. Add one from the Vault page.\n </p>\n ) : (\n typedSecrets.map((secret) => {\n const granted = grantBySecretId.has(secret.id);\n const pending = pendingSecretIds.has(secret.id);\n return (\n <button\n key={secret.id}\n type=\"button\"\n aria-pressed={granted}\n disabled={pending}\n onClick={() => toggleSecret(secret)}\n className={`flex w-full items-start gap-3 rounded-md px-2.5 py-2 text-left text-sm disabled:cursor-not-allowed disabled:opacity-60 ${\n pending ? \"\" : \"cursor-pointer\"\n } ${\n granted\n ? \"border border-primary/45 bg-primary/5\"\n : \"border border-transparent hover:border-muted-foreground/30 hover:bg-accent/35\"\n }`}\n >\n <span\n className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border ${\n granted\n ? \"border-primary/60 bg-primary/10 text-primary\"\n : \"border-muted-foreground/35 text-transparent\"\n }`}\n >\n {granted ? <IconCheck className=\"h-3 w-3\" /> : null}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium\">\n {secret.credentialKey}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground/70\">\n {secret.provider || secret.name || \"Vault secret\"}\n </span>\n </span>\n </button>\n );\n })\n )}\n </div>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"app-keys-popover.js","sourceRoot":"","sources":["../../src/components/app-keys-popover.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { useActionMutation, useActionQuery } from \"@agent-native/core/client\";\nimport {\n IconCheck,\n IconLoader2,\n IconRefresh,\n IconSettings,\n} from \"@tabler/icons-react\";\nimport { toast } from \"sonner\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { Button } from \"@/components/ui/button\";\nimport { Skeleton } from \"@/components/ui/skeleton\";\n\ninterface VaultSecret {\n id: string;\n name?: string | null;\n credentialKey: string;\n provider?: string | null;\n description?: string | null;\n}\n\ninterface VaultGrant {\n id: string;\n secretId: string;\n appId: string;\n status?: string | null;\n}\n\ninterface AppKeysPopoverProps {\n appId: string;\n appName: string;\n trigger?: ReactNode;\n align?: \"start\" | \"center\" | \"end\";\n side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n}\n\nexport function AppKeysPopover({\n appId,\n appName,\n trigger,\n align = \"end\",\n side = \"bottom\",\n}: AppKeysPopoverProps) {\n const [open, setOpen] = useState(false);\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n {trigger ?? (\n <button\n type=\"button\"\n aria-label={`Manage keys for ${appName}`}\n onClick={(event) => {\n // Keep parent card click handlers from also firing. Do not\n // preventDefault here: Radix uses the same click to open the\n // popover trigger.\n event.stopPropagation();\n }}\n className=\"flex h-7 w-7 cursor-pointer items-center justify-center rounded-md border border-transparent text-muted-foreground/70 hover:border-border hover:bg-accent/40 hover:text-foreground\"\n >\n <IconSettings size={14} />\n </button>\n )}\n </PopoverTrigger>\n <PopoverContent\n align={align}\n side={side}\n sideOffset={6}\n className=\"w-80 p-3\"\n onClick={(event) => event.stopPropagation()}\n >\n {open ? <AppKeysPanel appId={appId} appName={appName} /> : null}\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction AppKeysPanel({ appId, appName }: { appId: string; appName: string }) {\n const { data: secrets = [], isLoading: secretsLoading } = useActionQuery(\n \"list-vault-secret-options\",\n {},\n );\n const {\n data: grants = [],\n isLoading: grantsLoading,\n refetch: refetchGrants,\n } = useActionQuery(\"list-vault-grants\", { appId });\n const { data: accessSettings, isLoading: accessLoading } = useActionQuery(\n \"get-vault-access-settings\",\n {},\n );\n const accessMode =\n (accessSettings as any)?.mode === \"manual\" ? \"manual\" : \"all-apps\";\n\n const grantBySecretId = useMemo(() => {\n const map = new Map<string, VaultGrant>();\n for (const grant of grants as VaultGrant[]) {\n if (grant.status && grant.status !== \"active\") continue;\n map.set(grant.secretId, grant);\n }\n return map;\n }, [grants]);\n\n // Track per-secret pending state so a fast double-click on the same row\n // can't queue two `create-vault-grant` requests (which would silently\n // create duplicate active grants — a later revoke only clears one).\n const [pendingSecretIds, setPendingSecretIds] = useState<Set<string>>(\n () => new Set(),\n );\n const markPending = (secretId: string, pending: boolean) =>\n setPendingSecretIds((prev) => {\n const next = new Set(prev);\n if (pending) next.add(secretId);\n else next.delete(secretId);\n return next;\n });\n\n const grantMutation = useActionMutation(\"create-vault-grant\", {\n onSuccess: () => refetchGrants(),\n onError: (err) => toast.error(`Could not grant: ${String(err)}`),\n });\n\n const revokeMutation = useActionMutation(\"revoke-vault-grant\", {\n onSuccess: () => refetchGrants(),\n onError: (err) => toast.error(`Could not revoke: ${String(err)}`),\n });\n\n const syncMutation = useActionMutation(\"sync-vault-to-app\", {\n onSuccess: (result: any) => {\n const synced = result?.synced ?? 0;\n toast.success(\n synced > 0\n ? `Synced ${synced} key${synced === 1 ? \"\" : \"s\"} to ${appName}`\n : `${appName} is up to date`,\n );\n },\n onError: (err) => toast.error(`Sync failed: ${String(err)}`),\n });\n\n const isLoading = secretsLoading || grantsLoading || accessLoading;\n const grantedCount = grantBySecretId.size;\n const typedSecrets = secrets as VaultSecret[];\n const allApps = accessMode !== \"manual\";\n\n const toggleSecret = (secret: VaultSecret) => {\n if (allApps) return;\n if (pendingSecretIds.has(secret.id)) return;\n const existing = grantBySecretId.get(secret.id);\n markPending(secret.id, true);\n const onSettled = () => markPending(secret.id, false);\n if (existing) {\n revokeMutation.mutate({ grantId: existing.id }, { onSettled });\n } else {\n grantMutation.mutate({ secretId: secret.id, appId }, { onSettled });\n }\n };\n\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex items-center justify-between gap-2 px-1\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-semibold text-foreground\">\n Keys for {appName}\n </p>\n <p className=\"text-[11px] text-muted-foreground\">\n {allApps\n ? `${typedSecrets.length} available`\n : `${grantedCount} of ${typedSecrets.length} granted`}\n </p>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={\n syncMutation.isPending ||\n typedSecrets.length === 0 ||\n (!allApps && grantedCount === 0)\n }\n onClick={() => syncMutation.mutate({ appId })}\n className=\"h-7 px-2\"\n >\n {syncMutation.isPending ? (\n <IconLoader2 className=\"h-3 w-3 animate-spin\" />\n ) : (\n <IconRefresh className=\"h-3 w-3\" />\n )}\n <span className=\"ml-1 text-xs\">Sync</span>\n </Button>\n </div>\n\n <div className=\"max-h-[320px] space-y-1.5 overflow-y-auto rounded-md border border-border bg-card p-1.5\">\n {isLoading ? (\n <div className=\"space-y-1.5 p-1.5\">\n {Array.from({ length: 3 }).map((_, index) => (\n <div\n key={index}\n className=\"flex items-start gap-3 rounded-md px-2.5 py-2\"\n >\n <Skeleton className=\"mt-0.5 h-4 w-4 shrink-0 rounded\" />\n <div className=\"flex-1 space-y-1.5\">\n <Skeleton className=\"h-3 w-1/2\" />\n <Skeleton className=\"h-3 w-3/4\" />\n </div>\n </div>\n ))}\n </div>\n ) : typedSecrets.length === 0 ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n No vault keys yet. Add one from the Vault page.\n </p>\n ) : (\n typedSecrets.map((secret) => {\n const granted = allApps || grantBySecretId.has(secret.id);\n const pending = pendingSecretIds.has(secret.id);\n return (\n <button\n key={secret.id}\n type=\"button\"\n aria-pressed={granted}\n disabled={pending || allApps}\n onClick={() => toggleSecret(secret)}\n className={`flex w-full items-start gap-3 rounded-md px-2.5 py-2 text-left text-sm disabled:cursor-not-allowed disabled:opacity-60 ${\n pending || allApps ? \"\" : \"cursor-pointer\"\n } ${\n granted\n ? \"border border-primary/45 bg-primary/5\"\n : \"border border-transparent hover:border-muted-foreground/30 hover:bg-accent/35\"\n }`}\n >\n <span\n className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border ${\n granted\n ? \"border-primary/60 bg-primary/10 text-primary\"\n : \"border-muted-foreground/35 text-transparent\"\n }`}\n >\n {granted ? <IconCheck className=\"h-3 w-3\" /> : null}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium\">\n {secret.credentialKey}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground/70\">\n {allApps\n ? \"Available to this app\"\n : secret.provider || secret.name || \"Vault secret\"}\n </span>\n </span>\n </button>\n );\n })\n )}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-app-popover.d.ts","sourceRoot":"","sources":["../../src/components/create-app-popover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"create-app-popover.d.ts","sourceRoot":"","sources":["../../src/components/create-app-popover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAgDrE,UAAU,qBAAqB;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;CACpC;AAyGD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,SAAc,GACf,EAAE;IACD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CAyYA;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,KAAgB,GACjB,EAAE,qBAAqB,2CA0BvB"}
|
|
@@ -22,9 +22,11 @@ function titleFromPrompt(prompt) {
|
|
|
22
22
|
}
|
|
23
23
|
function buildAppCreationPrompt(input) {
|
|
24
24
|
const keyList = input.selectedKeys.join(", ");
|
|
25
|
-
const grantRequest =
|
|
26
|
-
? `
|
|
27
|
-
:
|
|
25
|
+
const grantRequest = input.vaultAccessMode === "all-apps"
|
|
26
|
+
? `Dispatch vault access: all saved vault keys are available to every workspace app by default. No per-app vault grants are needed.`
|
|
27
|
+
: keyList
|
|
28
|
+
? `Requested Dispatch vault key grants for this app: ${keyList}`
|
|
29
|
+
: `Requested Dispatch vault key grants for this app: none`;
|
|
28
30
|
const resourceList = input.selectedResources.length
|
|
29
31
|
? input.selectedResources
|
|
30
32
|
.map((resource) => `- ${resource.name} (${resource.kind}, ${resource.path})`)
|
|
@@ -36,6 +38,7 @@ function buildAppCreationPrompt(input) {
|
|
|
36
38
|
``,
|
|
37
39
|
`Suggested app name: ${input.appId} (you may adjust the slug if it conflicts)`,
|
|
38
40
|
`User prompt: ${input.prompt.trim()}`,
|
|
41
|
+
`Generate a concise one-sentence app description from the user prompt before coding; save it in apps/${input.appId}/package.json "description" so Dispatch and A2A can describe the app.`,
|
|
39
42
|
`If the user mentions a product or company such as Granola, Loom, Superhuman, Linear, or Notion, treat it as product inspiration unless they explicitly ask to connect to that service. Do not invent or require third-party API keys like GRANOLA_API_KEY just because a product is named.`,
|
|
40
43
|
grantRequest,
|
|
41
44
|
`Requested Dispatch workspace resources for this app:\n${resourceList}`,
|
|
@@ -50,18 +53,20 @@ function buildAppCreationPrompt(input) {
|
|
|
50
53
|
`Do not clone first-party templates, create wrapper apps, or scaffold child apps/routes for Mail, Calendar, Analytics, etc. inside apps/${input.appId} just so this app can access them. If the request is a cross-app dashboard or overview, build only the new dashboard/overview app and delegate to the existing apps for domain work.`,
|
|
51
54
|
`Only create another first-party app copy when the user explicitly asks for a customized fork/copy of that app; otherwise keep using the hosted/shared app so improvements to the base template keep flowing to users.`,
|
|
52
55
|
`Do not satisfy this by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app.`,
|
|
53
|
-
|
|
54
|
-
? `
|
|
55
|
-
:
|
|
56
|
+
input.vaultAccessMode === "all-apps"
|
|
57
|
+
? `Do not create per-app Dispatch vault grants unless the workspace switches vault access to manual or the user explicitly asks for manual grants.`
|
|
58
|
+
: keyList
|
|
59
|
+
? `After the app exists, grant the selected Dispatch vault keys to appId "${input.appId}" and sync them once the app server is available. Treat these as requested grants, not active grants before creation succeeds.`
|
|
60
|
+
: `Do not grant any Dispatch vault keys unless the user asks later.`,
|
|
56
61
|
input.selectedResources.length
|
|
57
62
|
? `After the app exists, grant the selected Dispatch workspace resources to appId "${input.appId}" and sync them once the app server is available. Add a short note to apps/${input.appId}/AGENTS.md telling the app agent to read relevant shared resources under context/ or the selected resource paths before doing GTM/domain work.`
|
|
58
63
|
: `Do not grant any Dispatch workspace resources unless the user asks later.`,
|
|
59
64
|
``,
|
|
60
65
|
`App readiness requirements before handing off:`,
|
|
61
|
-
`- Ensure apps/${input.appId}/package.json exists; Dispatch discovers workspace apps from apps/<app-id>/package.json, not a separate app registry.`,
|
|
66
|
+
`- Ensure apps/${input.appId}/package.json exists with displayName/name and a concise description; Dispatch discovers workspace apps from apps/<app-id>/package.json, not a separate app registry.`,
|
|
62
67
|
`- Update the app manifest/package/deploy metadata needed by the existing workspace deployment model.`,
|
|
63
68
|
`- Ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() so /${input.appId} hydrates correctly.`,
|
|
64
|
-
`- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment.`,
|
|
69
|
+
`- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment. Every sibling workspace app is available over A2A by default through call-agent, with names and descriptions from the workspace app registry.`,
|
|
65
70
|
`When it is ready, start or update the workspace dev server and navigate the user to the absolute path /${input.appId} on the workspace origin. Do not prefix with /dispatch/, /apps/, /workspace/, or any other Dispatch tab — the new app is mounted at the workspace root, not under Dispatch. If you have a navigate tool available, pass /${input.appId} verbatim; if you only have a window.location-style escape hatch, set it to /${input.appId}.`,
|
|
66
71
|
].join("\n");
|
|
67
72
|
}
|
|
@@ -98,6 +103,7 @@ export function CreateAppFlow({ onClose, className = "", }) {
|
|
|
98
103
|
const [selectedResourceIds, setSelectedResourceIds] = useState([]);
|
|
99
104
|
const [secrets, setSecrets] = useState([]);
|
|
100
105
|
const [resources, setResources] = useState([]);
|
|
106
|
+
const [vaultAccessMode, setVaultAccessMode] = useState("all-apps");
|
|
101
107
|
const [secretsError, setSecretsError] = useState(null);
|
|
102
108
|
const [resourcesError, setResourcesError] = useState(null);
|
|
103
109
|
const [statusMessage, setStatusMessage] = useState(null);
|
|
@@ -121,6 +127,17 @@ export function CreateAppFlow({ onClose, className = "", }) {
|
|
|
121
127
|
setSecrets([]);
|
|
122
128
|
setSecretsError(err?.message || "Could not load Dispatch keys");
|
|
123
129
|
});
|
|
130
|
+
fetchJson(actionUrl(basePath, "get-vault-access-settings"))
|
|
131
|
+
.then((data) => {
|
|
132
|
+
if (cancelled)
|
|
133
|
+
return;
|
|
134
|
+
setVaultAccessMode(data?.mode === "manual" ? "manual" : "all-apps");
|
|
135
|
+
})
|
|
136
|
+
.catch(() => {
|
|
137
|
+
if (cancelled)
|
|
138
|
+
return;
|
|
139
|
+
setVaultAccessMode("manual");
|
|
140
|
+
});
|
|
124
141
|
fetchJson(actionUrl(basePath, "list-workspace-resource-options"))
|
|
125
142
|
.then((data) => {
|
|
126
143
|
if (cancelled)
|
|
@@ -140,9 +157,11 @@ export function CreateAppFlow({ onClose, className = "", }) {
|
|
|
140
157
|
}, [basePath]);
|
|
141
158
|
const selectedSecrets = useMemo(() => secrets.filter((s) => selectedSecretIds.includes(s.id)), [secrets, selectedSecretIds]);
|
|
142
159
|
const selectedResources = useMemo(() => resources.filter((r) => selectedResourceIds.includes(r.id)), [resources, selectedResourceIds]);
|
|
143
|
-
const selectedSecretLabel =
|
|
144
|
-
? "
|
|
145
|
-
:
|
|
160
|
+
const selectedSecretLabel = vaultAccessMode === "all-apps"
|
|
161
|
+
? "all keys"
|
|
162
|
+
: selectedSecretIds.length === 0
|
|
163
|
+
? "no keys"
|
|
164
|
+
: `${selectedSecretIds.length} key${selectedSecretIds.length === 1 ? "" : "s"}`;
|
|
146
165
|
const selectedResourceLabel = selectedResourceIds.length === 0
|
|
147
166
|
? "no resources"
|
|
148
167
|
: `${selectedResourceIds.length} resource${selectedResourceIds.length === 1 ? "" : "s"}`;
|
|
@@ -166,8 +185,11 @@ export function CreateAppFlow({ onClose, className = "", }) {
|
|
|
166
185
|
const message = buildAppCreationPrompt({
|
|
167
186
|
appId,
|
|
168
187
|
prompt: trimmed,
|
|
169
|
-
selectedKeys:
|
|
188
|
+
selectedKeys: vaultAccessMode === "manual"
|
|
189
|
+
? selectedSecrets.map((s) => s.credentialKey)
|
|
190
|
+
: [],
|
|
170
191
|
selectedResources,
|
|
192
|
+
vaultAccessMode,
|
|
171
193
|
});
|
|
172
194
|
setIsSubmitting(true);
|
|
173
195
|
setStatusMessage(null);
|
|
@@ -190,7 +212,9 @@ export function CreateAppFlow({ onClose, className = "", }) {
|
|
|
190
212
|
body: JSON.stringify({
|
|
191
213
|
prompt: trimmed,
|
|
192
214
|
appId,
|
|
193
|
-
secretIds: selectedSecretIds.length > 0
|
|
215
|
+
secretIds: vaultAccessMode === "manual" && selectedSecretIds.length > 0
|
|
216
|
+
? selectedSecretIds
|
|
217
|
+
: [],
|
|
194
218
|
resourceIds: selectedResourceIds.length > 0 ? selectedResourceIds : [],
|
|
195
219
|
}),
|
|
196
220
|
});
|
|
@@ -215,7 +239,7 @@ export function CreateAppFlow({ onClose, className = "", }) {
|
|
|
215
239
|
return (_jsxs("div", { className: `flex flex-col gap-3 ${className}`, children: [step === "prompt" ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-1", children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: "Create app" }), _jsxs("button", { type: "button", onClick: () => setStep("access"), className: "inline-flex cursor-pointer items-center gap-1 rounded-md border border-border bg-background/40 px-2 py-1 text-[11px] text-muted-foreground hover:text-foreground hover:bg-accent/50", children: [_jsx(IconKey, { size: 11 }), selectedAccessLabel] })] }), _jsx(PromptComposer, { autoFocus: true, disabled: isSubmitting, placeholder: "Describe the app your teammate should be able to use...", draftScope: "dispatch:create-app", preserveDraftOnSubmit: true, onSubmit: (text) => {
|
|
216
240
|
setPrompt(text);
|
|
217
241
|
submit(text);
|
|
218
|
-
} })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-1", children: [_jsxs("button", { type: "button", onClick: () => setStep("prompt"), className: "inline-flex cursor-pointer items-center gap-1 text-xs text-muted-foreground hover:text-foreground", children: [_jsx(IconArrowLeft, { size: 12 }), "Back"] }), _jsx("span", { className: "text-[11px] text-muted-foreground/70", children: selectedAccessLabel })] }), _jsxs("div", { className: "max-h-[180px] space-y-2 overflow-y-auto rounded-md border border-border bg-card p-2", children: [_jsxs("div", { className: "flex items-center gap-1.5 px-1 pb-1 text-[11px] font-medium text-muted-foreground", children: [_jsx(IconKey, { size: 12 }), "Dispatch keys"] }), secretsError ? (_jsx("p", { className: "rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground", children: secretsError })) : secrets.length === 0 ? (_jsx("p", { className: "rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground", children: "No Dispatch vault keys found yet." })) : (secrets.map((secret) => {
|
|
242
|
+
} })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-1", children: [_jsxs("button", { type: "button", onClick: () => setStep("prompt"), className: "inline-flex cursor-pointer items-center gap-1 text-xs text-muted-foreground hover:text-foreground", children: [_jsx(IconArrowLeft, { size: 12 }), "Back"] }), _jsx("span", { className: "text-[11px] text-muted-foreground/70", children: selectedAccessLabel })] }), _jsxs("div", { className: "max-h-[180px] space-y-2 overflow-y-auto rounded-md border border-border bg-card p-2", children: [_jsxs("div", { className: "flex items-center gap-1.5 px-1 pb-1 text-[11px] font-medium text-muted-foreground", children: [_jsx(IconKey, { size: 12 }), "Dispatch keys"] }), vaultAccessMode === "all-apps" ? (_jsx("p", { className: "rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground", children: "Every saved Dispatch vault key is available to new apps." })) : secretsError ? (_jsx("p", { className: "rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground", children: secretsError })) : secrets.length === 0 ? (_jsx("p", { className: "rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground", children: "No Dispatch vault keys found yet." })) : (secrets.map((secret) => {
|
|
219
243
|
const selected = selectedSecretIds.includes(secret.id);
|
|
220
244
|
return (_jsxs("div", { className: `group rounded-md border text-sm ${selected
|
|
221
245
|
? "border-primary/45 bg-primary/5"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-app-popover.js","sourceRoot":"","sources":["../../src/components/create-app-popover.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport {\n PromptComposer,\n agentNativePath,\n appBasePath,\n isInBuilderFrame,\n sendToAgentChat,\n useDevMode,\n} from \"@agent-native/core/client\";\nimport { getWorkspaceAppIdValidationError } from \"@agent-native/core/shared\";\nimport {\n IconArrowLeft,\n IconArrowUpRight,\n IconBook,\n IconCheck,\n IconChevronDown,\n IconFileText,\n IconKey,\n IconLoader2,\n IconPlus,\n} from \"@tabler/icons-react\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { Button } from \"@/components/ui/button\";\n\ninterface VaultSecretOption {\n id: string;\n name: string;\n credentialKey: string;\n provider?: string | null;\n description?: string | null;\n}\n\ninterface WorkspaceResourceOption {\n id: string;\n kind: \"skill\" | \"instruction\" | \"agent\" | \"knowledge\";\n name: string;\n description?: string | null;\n path: string;\n scope: \"all\" | \"selected\";\n updatedAt?: number;\n}\n\ninterface CreateAppPopoverProps {\n /**\n * Custom trigger element. Defaults to a dashed-border tile that matches the\n * apps grid empty state.\n */\n trigger?: ReactNode;\n /**\n * Override the popover alignment. Defaults to \"center\" with a 10px offset.\n */\n align?: \"start\" | \"center\" | \"end\";\n}\n\nfunction slugify(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/^[^a-z]+/, \"\")\n .slice(0, 48);\n}\n\nfunction titleFromPrompt(prompt: string): string {\n const cleaned = prompt\n .replace(/\\b(build|create|make|an?|the|app|tool|dashboard)\\b/gi, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n return slugify(cleaned || \"new-app\") || \"new-app\";\n}\n\nfunction buildAppCreationPrompt(input: {\n appId: string;\n prompt: string;\n selectedKeys: string[];\n selectedResources: WorkspaceResourceOption[];\n}): string {\n const keyList = input.selectedKeys.join(\", \");\n const grantRequest = keyList\n ? `Requested Dispatch vault key grants for this app: ${keyList}`\n : `Requested Dispatch vault key grants for this app: none`;\n const resourceList = input.selectedResources.length\n ? input.selectedResources\n .map(\n (resource) =>\n `- ${resource.name} (${resource.kind}, ${resource.path})`,\n )\n .join(\"\\n\")\n : \"none\";\n\n return [\n `Create a new agent-native app in this workspace.`,\n `This is a new workspace app request, not a feature request for the current app.`,\n ``,\n `Suggested app name: ${input.appId} (you may adjust the slug if it conflicts)`,\n `User prompt: ${input.prompt.trim()}`,\n `If the user mentions a product or company such as Granola, Loom, Superhuman, Linear, or Notion, treat it as product inspiration unless they explicitly ask to connect to that service. Do not invent or require third-party API keys like GRANOLA_API_KEY just because a product is named.`,\n grantRequest,\n `Requested Dispatch workspace resources for this app:\\n${resourceList}`,\n ``,\n `Pick a starter template that fits the user's prompt — analytics, calendar, content, design, dispatch, forms, mail, slides, clips, or starter when none of the others fit.`,\n `Use the workspace app layout: create it under apps/${input.appId}, mount it at /${input.appId}, keep it on the shared workspace database/hosting model, and avoid table-name collisions by namespacing any new domain tables to the app.`,\n `Important routing rule: from outside the app, link to /${input.appId}; inside apps/${input.appId}, React Router routes are app-local. Use <Link to=\"/review\"> and navigate(\"/review\"), not \"/${input.appId}/review\"; APP_BASE_PATH supplies the mounted prefix, and hardcoding it causes doubled URLs like /${input.appId}/${input.appId}/review.`,\n `Prefer useActionQuery/useActionMutation for actions. If you must raw-fetch framework endpoints, wrap them with agentNativePath(\"/_agent-native/actions/<name>\") so mounted apps call the right URL.`,\n `Use relative workspace links like /${input.appId}. Do not hardcode localhost, 127.0.0.1, 8080, 8100, or any dev port; the active workspace gateway/browser origin owns the port.`,\n `Use the framework/template UI stack: shadcn/ui components and @tabler/icons-react. Do not add lucide-react or another icon library for standard UI.`,\n `Existing first-party apps are neighbors, not implementation details for this app. If the user's prompt mentions Mail, Calendar, Analytics, Dispatch, or other templates, treat them as existing hosted/connected apps that this app can link to or call through A2A/default connected agents. For example, Mail, Calendar, and Analytics already exist at https://mail.agent-native.com, https://calendar.agent-native.com, and https://analytics.agent-native.com.`,\n `Do not clone first-party templates, create wrapper apps, or scaffold child apps/routes for Mail, Calendar, Analytics, etc. inside apps/${input.appId} just so this app can access them. If the request is a cross-app dashboard or overview, build only the new dashboard/overview app and delegate to the existing apps for domain work.`,\n `Only create another first-party app copy when the user explicitly asks for a customized fork/copy of that app; otherwise keep using the hosted/shared app so improvements to the base template keep flowing to users.`,\n `Do not satisfy this by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app.`,\n keyList\n ? `After the app exists, grant the selected Dispatch vault keys to appId \"${input.appId}\" and sync them once the app server is available. Treat these as requested grants, not active grants before creation succeeds.`\n : `Do not grant any Dispatch vault keys unless the user asks later.`,\n input.selectedResources.length\n ? `After the app exists, grant the selected Dispatch workspace resources to appId \"${input.appId}\" and sync them once the app server is available. Add a short note to apps/${input.appId}/AGENTS.md telling the app agent to read relevant shared resources under context/ or the selected resource paths before doing GTM/domain work.`\n : `Do not grant any Dispatch workspace resources unless the user asks later.`,\n ``,\n `App readiness requirements before handing off:`,\n `- Ensure apps/${input.appId}/package.json exists; Dispatch discovers workspace apps from apps/<app-id>/package.json, not a separate app registry.`,\n `- Update the app manifest/package/deploy metadata needed by the existing workspace deployment model.`,\n `- Ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() so /${input.appId} hydrates correctly.`,\n `- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment.`,\n `When it is ready, start or update the workspace dev server and navigate the user to the absolute path /${input.appId} on the workspace origin. Do not prefix with /dispatch/, /apps/, /workspace/, or any other Dispatch tab — the new app is mounted at the workspace root, not under Dispatch. If you have a navigate tool available, pass /${input.appId} verbatim; if you only have a window.location-style escape hatch, set it to /${input.appId}.`,\n ].join(\"\\n\");\n}\n\nasync function fetchJson(url: string, init?: RequestInit): Promise<any> {\n const res = await fetch(url, init);\n const data = await res.json().catch(() => null);\n if (!res.ok) {\n throw new Error(\n data?.error || data?.message || `Request failed ${res.status}`,\n );\n }\n return data;\n}\n\nfunction defaultDispatchBasePath(): string | null {\n const base = appBasePath();\n if (base === \"/dispatch\") return null;\n return null;\n}\n\nfunction actionUrl(basePath: string | null, action: string): string {\n const path = `/_agent-native/actions/${action}`;\n if (basePath === null) return agentNativePath(path);\n const normalized = basePath.replace(/\\/+$/, \"\");\n return `${normalized}${path}`;\n}\n\n/**\n * Inline two-step app-creation flow: prompt → optional access picker → submit.\n * Used both in the popover form and in the dedicated `/new-app` page so the\n * same UX shows up everywhere a teammate kicks off a new workspace app.\n */\nexport function CreateAppFlow({\n onClose,\n className = \"\",\n}: {\n onClose?: () => void;\n className?: string;\n}) {\n const [step, setStep] = useState<\"prompt\" | \"access\">(\"prompt\");\n const [prompt, setPrompt] = useState(\"\");\n const [selectedSecretIds, setSelectedSecretIds] = useState<string[]>([]);\n const [selectedResourceIds, setSelectedResourceIds] = useState<string[]>([]);\n const [secrets, setSecrets] = useState<VaultSecretOption[]>([]);\n const [resources, setResources] = useState<WorkspaceResourceOption[]>([]);\n const [secretsError, setSecretsError] = useState<string | null>(null);\n const [resourcesError, setResourcesError] = useState<string | null>(null);\n const [statusMessage, setStatusMessage] = useState<string | null>(null);\n const [branchUrl, setBranchUrl] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const { isDevMode } = useDevMode();\n\n const basePath = useMemo(() => defaultDispatchBasePath(), []);\n\n // Fetch access options eagerly so step 2 has them ready immediately.\n useEffect(() => {\n let cancelled = false;\n fetchJson(actionUrl(basePath, \"list-vault-secret-options\"))\n .then((data) => {\n if (cancelled) return;\n setSecrets(Array.isArray(data) ? data : []);\n setSecretsError(null);\n })\n .catch((err) => {\n if (cancelled) return;\n setSecrets([]);\n setSecretsError(err?.message || \"Could not load Dispatch keys\");\n });\n fetchJson(actionUrl(basePath, \"list-workspace-resource-options\"))\n .then((data) => {\n if (cancelled) return;\n setResources(Array.isArray(data) ? data : []);\n setResourcesError(null);\n })\n .catch((err) => {\n if (cancelled) return;\n setResources([]);\n setResourcesError(err?.message || \"Could not load Dispatch resources\");\n });\n return () => {\n cancelled = true;\n };\n }, [basePath]);\n\n const selectedSecrets = useMemo(\n () => secrets.filter((s) => selectedSecretIds.includes(s.id)),\n [secrets, selectedSecretIds],\n );\n const selectedResources = useMemo(\n () => resources.filter((r) => selectedResourceIds.includes(r.id)),\n [resources, selectedResourceIds],\n );\n const selectedSecretLabel =\n selectedSecretIds.length === 0\n ? \"no keys\"\n : `${selectedSecretIds.length} key${selectedSecretIds.length === 1 ? \"\" : \"s\"}`;\n const selectedResourceLabel =\n selectedResourceIds.length === 0\n ? \"no resources\"\n : `${selectedResourceIds.length} resource${selectedResourceIds.length === 1 ? \"\" : \"s\"}`;\n const selectedAccessLabel = [selectedSecretLabel, selectedResourceLabel].join(\n \" · \",\n );\n\n function toggleSecret(id: string) {\n setSelectedSecretIds((cur) =>\n cur.includes(id) ? cur.filter((x) => x !== id) : [...cur, id],\n );\n }\n\n function toggleResource(id: string) {\n setSelectedResourceIds((cur) =>\n cur.includes(id) ? cur.filter((x) => x !== id) : [...cur, id],\n );\n }\n\n async function submit(rawPrompt: string) {\n const trimmed = rawPrompt.trim();\n if (!trimmed || isSubmitting) return;\n const appId = titleFromPrompt(trimmed);\n const validationError = getWorkspaceAppIdValidationError(appId);\n if (validationError) {\n setStatusMessage(validationError);\n return;\n }\n\n const message = buildAppCreationPrompt({\n appId,\n prompt: trimmed,\n selectedKeys: selectedSecrets.map((s) => s.credentialKey),\n selectedResources,\n });\n setIsSubmitting(true);\n setStatusMessage(null);\n setBranchUrl(null);\n\n try {\n if (isInBuilderFrame()) {\n sendToAgentChat({ message, submit: true, type: \"code\" });\n setStatusMessage(\"Sent to Builder chat.\");\n onClose?.();\n } else if (isDevMode) {\n sendToAgentChat({ message, submit: true, type: \"code\", newTab: true });\n setStatusMessage(\"Sent to the local agent.\");\n onClose?.();\n } else {\n const result = await fetchJson(\n actionUrl(basePath, \"start-workspace-app-creation\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n prompt: trimmed,\n appId,\n secretIds: selectedSecretIds.length > 0 ? selectedSecretIds : [],\n resourceIds:\n selectedResourceIds.length > 0 ? selectedResourceIds : [],\n }),\n },\n );\n if (result?.mode === \"builder\") {\n setBranchUrl(result?.url || null);\n setStatusMessage(\"Builder branch created.\");\n } else {\n setStatusMessage(\n result?.message ||\n \"Builder app creation is coming soon. Open this workspace in Builder to create an app from this prompt.\",\n );\n }\n }\n } catch (err: any) {\n setStatusMessage(err?.message || \"Could not start the new app flow.\");\n } finally {\n setIsSubmitting(false);\n }\n }\n\n const submitWithSelectedAccess = () => submit(prompt);\n\n return (\n <div className={`flex flex-col gap-3 ${className}`}>\n {step === \"prompt\" ? (\n <>\n <div className=\"flex items-center justify-between gap-2 px-1\">\n <p className=\"text-sm font-semibold text-foreground\">Create app</p>\n <button\n type=\"button\"\n onClick={() => setStep(\"access\")}\n className=\"inline-flex cursor-pointer items-center gap-1 rounded-md border border-border bg-background/40 px-2 py-1 text-[11px] text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n >\n <IconKey size={11} />\n {selectedAccessLabel}\n </button>\n </div>\n <PromptComposer\n autoFocus\n disabled={isSubmitting}\n placeholder=\"Describe the app your teammate should be able to use...\"\n draftScope=\"dispatch:create-app\"\n preserveDraftOnSubmit\n onSubmit={(text) => {\n setPrompt(text);\n submit(text);\n }}\n />\n </>\n ) : (\n <>\n <div className=\"flex items-center justify-between gap-2 px-1\">\n <button\n type=\"button\"\n onClick={() => setStep(\"prompt\")}\n className=\"inline-flex cursor-pointer items-center gap-1 text-xs text-muted-foreground hover:text-foreground\"\n >\n <IconArrowLeft size={12} />\n Back\n </button>\n <span className=\"text-[11px] text-muted-foreground/70\">\n {selectedAccessLabel}\n </span>\n </div>\n <div className=\"max-h-[180px] space-y-2 overflow-y-auto rounded-md border border-border bg-card p-2\">\n <div className=\"flex items-center gap-1.5 px-1 pb-1 text-[11px] font-medium text-muted-foreground\">\n <IconKey size={12} />\n Dispatch keys\n </div>\n {secretsError ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n {secretsError}\n </p>\n ) : secrets.length === 0 ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n No Dispatch vault keys found yet.\n </p>\n ) : (\n secrets.map((secret) => {\n const selected = selectedSecretIds.includes(secret.id);\n return (\n <div\n key={secret.id}\n className={`group rounded-md border text-sm ${\n selected\n ? \"border-primary/45 bg-primary/5\"\n : \"border-border hover:border-muted-foreground/40 hover:bg-accent/35\"\n }`}\n >\n <button\n type=\"button\"\n aria-pressed={selected}\n onClick={() => toggleSecret(secret.id)}\n className=\"flex w-full cursor-pointer items-start gap-3 rounded-md px-3 py-2 text-left\"\n >\n <span\n className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border ${\n selected\n ? \"border-primary/60 bg-primary/10 text-primary\"\n : \"border-muted-foreground/35 text-transparent\"\n }`}\n >\n {selected ? <IconCheck className=\"h-3 w-3\" /> : null}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium\">\n {secret.credentialKey}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground/70\">\n {selected\n ? \"Will be requested for this app\"\n : \"Click to request\"}\n </span>\n </span>\n </button>\n {(secret.provider || secret.name) && (\n <details className=\"group/details border-t border-border/60 px-3 py-1.5 text-xs text-muted-foreground/75\">\n <summary className=\"flex cursor-pointer list-none items-center gap-1.5 text-[11px] hover:text-muted-foreground [&::-webkit-details-marker]:hidden\">\n <IconChevronDown className=\"h-3 w-3 transition-transform group-open/details:rotate-180\" />\n Details\n </summary>\n <div className=\"mt-1.5 space-y-1 pb-0.5 pl-4\">\n <div className=\"truncate\">\n Provider: {secret.provider || \"Not specified\"}\n </div>\n <div className=\"truncate\">Name: {secret.name}</div>\n </div>\n </details>\n )}\n </div>\n );\n })\n )}\n </div>\n <div className=\"max-h-[180px] space-y-2 overflow-y-auto rounded-md border border-border bg-card p-2\">\n <div className=\"flex items-center gap-1.5 px-1 pb-1 text-[11px] font-medium text-muted-foreground\">\n <IconBook size={12} />\n Resource packs\n </div>\n {resourcesError ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n {resourcesError}\n </p>\n ) : resources.length === 0 ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n No Dispatch resource packs found yet.\n </p>\n ) : (\n resources.map((resource) => {\n const selected = selectedResourceIds.includes(resource.id);\n return (\n <div\n key={resource.id}\n className={`group rounded-md border text-sm ${\n selected\n ? \"border-primary/45 bg-primary/5\"\n : \"border-border hover:border-muted-foreground/40 hover:bg-accent/35\"\n }`}\n >\n <button\n type=\"button\"\n aria-pressed={selected}\n onClick={() => toggleResource(resource.id)}\n className=\"flex w-full cursor-pointer items-start gap-3 rounded-md px-3 py-2 text-left\"\n >\n <span\n className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border ${\n selected\n ? \"border-primary/60 bg-primary/10 text-primary\"\n : \"border-muted-foreground/35 text-transparent\"\n }`}\n >\n {selected ? <IconCheck className=\"h-3 w-3\" /> : null}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <IconFileText className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground/70\" />\n <span className=\"block truncate font-medium\">\n {resource.name}\n </span>\n </span>\n <span className=\"block truncate text-xs text-muted-foreground/70\">\n {resource.kind} · {resource.path}\n </span>\n </span>\n </button>\n <details className=\"group/details border-t border-border/60 px-3 py-1.5 text-xs text-muted-foreground/75\">\n <summary className=\"flex cursor-pointer list-none items-center gap-1.5 text-[11px] hover:text-muted-foreground [&::-webkit-details-marker]:hidden\">\n <IconChevronDown className=\"h-3 w-3 transition-transform group-open/details:rotate-180\" />\n Details\n </summary>\n <div className=\"mt-1.5 space-y-1 pb-0.5 pl-4\">\n <div className=\"truncate\">\n Scope:{\" \"}\n {resource.scope === \"all\"\n ? \"All apps\"\n : \"Selected apps\"}\n </div>\n {resource.description ? (\n <div className=\"line-clamp-2\">\n {resource.description}\n </div>\n ) : null}\n </div>\n </details>\n </div>\n );\n })\n )}\n </div>\n <div className=\"flex items-center justify-end gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={submitWithSelectedAccess}\n disabled={!prompt.trim() || isSubmitting}\n >\n {isSubmitting ? (\n <IconLoader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <IconPlus className=\"h-3.5 w-3.5\" />\n )}\n Create app\n </Button>\n </div>\n {!prompt.trim() ? (\n <p className=\"px-1 text-[11px] text-muted-foreground/70\">\n Add a prompt on the previous step before creating the app.\n </p>\n ) : null}\n </>\n )}\n\n {statusMessage ? (\n <div className=\"rounded-md border border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground\">\n {statusMessage}\n {branchUrl ? (\n <a\n href={branchUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"ml-2 inline-flex items-center gap-1 font-medium text-foreground underline\"\n >\n Open branch <IconArrowUpRight className=\"h-3 w-3\" />\n </a>\n ) : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nexport function CreateAppPopover({\n trigger,\n align = \"center\",\n}: CreateAppPopoverProps) {\n const [open, setOpen] = useState(false);\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n {trigger ?? (\n <button\n type=\"button\"\n className=\"flex min-h-32 cursor-pointer items-center justify-center rounded-lg border border-dashed bg-card p-4 text-sm font-medium text-muted-foreground transition hover:border-foreground/30 hover:text-foreground\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <IconPlus size={16} />\n Create app\n </span>\n </button>\n )}\n </PopoverTrigger>\n <PopoverContent\n align={align}\n sideOffset={10}\n className=\"w-[calc(100vw-2rem)] rounded-xl p-3 shadow-xl sm:w-[460px]\"\n >\n <CreateAppFlow onClose={() => setOpen(false)} />\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create-app-popover.js","sourceRoot":"","sources":["../../src/components/create-app-popover.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport {\n PromptComposer,\n agentNativePath,\n appBasePath,\n isInBuilderFrame,\n sendToAgentChat,\n useDevMode,\n} from \"@agent-native/core/client\";\nimport { getWorkspaceAppIdValidationError } from \"@agent-native/core/shared\";\nimport {\n IconArrowLeft,\n IconArrowUpRight,\n IconBook,\n IconCheck,\n IconChevronDown,\n IconFileText,\n IconKey,\n IconLoader2,\n IconPlus,\n} from \"@tabler/icons-react\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { Button } from \"@/components/ui/button\";\n\ninterface VaultSecretOption {\n id: string;\n name: string;\n credentialKey: string;\n provider?: string | null;\n description?: string | null;\n}\n\ninterface WorkspaceResourceOption {\n id: string;\n kind: \"skill\" | \"instruction\" | \"agent\" | \"knowledge\";\n name: string;\n description?: string | null;\n path: string;\n scope: \"all\" | \"selected\";\n updatedAt?: number;\n}\n\ntype VaultAccessMode = \"all-apps\" | \"manual\";\n\ninterface CreateAppPopoverProps {\n /**\n * Custom trigger element. Defaults to a dashed-border tile that matches the\n * apps grid empty state.\n */\n trigger?: ReactNode;\n /**\n * Override the popover alignment. Defaults to \"center\" with a 10px offset.\n */\n align?: \"start\" | \"center\" | \"end\";\n}\n\nfunction slugify(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/^[^a-z]+/, \"\")\n .slice(0, 48);\n}\n\nfunction titleFromPrompt(prompt: string): string {\n const cleaned = prompt\n .replace(/\\b(build|create|make|an?|the|app|tool|dashboard)\\b/gi, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n return slugify(cleaned || \"new-app\") || \"new-app\";\n}\n\nfunction buildAppCreationPrompt(input: {\n appId: string;\n prompt: string;\n selectedKeys: string[];\n selectedResources: WorkspaceResourceOption[];\n vaultAccessMode: VaultAccessMode;\n}): string {\n const keyList = input.selectedKeys.join(\", \");\n const grantRequest =\n input.vaultAccessMode === \"all-apps\"\n ? `Dispatch vault access: all saved vault keys are available to every workspace app by default. No per-app vault grants are needed.`\n : keyList\n ? `Requested Dispatch vault key grants for this app: ${keyList}`\n : `Requested Dispatch vault key grants for this app: none`;\n const resourceList = input.selectedResources.length\n ? input.selectedResources\n .map(\n (resource) =>\n `- ${resource.name} (${resource.kind}, ${resource.path})`,\n )\n .join(\"\\n\")\n : \"none\";\n\n return [\n `Create a new agent-native app in this workspace.`,\n `This is a new workspace app request, not a feature request for the current app.`,\n ``,\n `Suggested app name: ${input.appId} (you may adjust the slug if it conflicts)`,\n `User prompt: ${input.prompt.trim()}`,\n `Generate a concise one-sentence app description from the user prompt before coding; save it in apps/${input.appId}/package.json \"description\" so Dispatch and A2A can describe the app.`,\n `If the user mentions a product or company such as Granola, Loom, Superhuman, Linear, or Notion, treat it as product inspiration unless they explicitly ask to connect to that service. Do not invent or require third-party API keys like GRANOLA_API_KEY just because a product is named.`,\n grantRequest,\n `Requested Dispatch workspace resources for this app:\\n${resourceList}`,\n ``,\n `Pick a starter template that fits the user's prompt — analytics, calendar, content, design, dispatch, forms, mail, slides, clips, or starter when none of the others fit.`,\n `Use the workspace app layout: create it under apps/${input.appId}, mount it at /${input.appId}, keep it on the shared workspace database/hosting model, and avoid table-name collisions by namespacing any new domain tables to the app.`,\n `Important routing rule: from outside the app, link to /${input.appId}; inside apps/${input.appId}, React Router routes are app-local. Use <Link to=\"/review\"> and navigate(\"/review\"), not \"/${input.appId}/review\"; APP_BASE_PATH supplies the mounted prefix, and hardcoding it causes doubled URLs like /${input.appId}/${input.appId}/review.`,\n `Prefer useActionQuery/useActionMutation for actions. If you must raw-fetch framework endpoints, wrap them with agentNativePath(\"/_agent-native/actions/<name>\") so mounted apps call the right URL.`,\n `Use relative workspace links like /${input.appId}. Do not hardcode localhost, 127.0.0.1, 8080, 8100, or any dev port; the active workspace gateway/browser origin owns the port.`,\n `Use the framework/template UI stack: shadcn/ui components and @tabler/icons-react. Do not add lucide-react or another icon library for standard UI.`,\n `Existing first-party apps are neighbors, not implementation details for this app. If the user's prompt mentions Mail, Calendar, Analytics, Dispatch, or other templates, treat them as existing hosted/connected apps that this app can link to or call through A2A/default connected agents. For example, Mail, Calendar, and Analytics already exist at https://mail.agent-native.com, https://calendar.agent-native.com, and https://analytics.agent-native.com.`,\n `Do not clone first-party templates, create wrapper apps, or scaffold child apps/routes for Mail, Calendar, Analytics, etc. inside apps/${input.appId} just so this app can access them. If the request is a cross-app dashboard or overview, build only the new dashboard/overview app and delegate to the existing apps for domain work.`,\n `Only create another first-party app copy when the user explicitly asks for a customized fork/copy of that app; otherwise keep using the hosted/shared app so improvements to the base template keep flowing to users.`,\n `Do not satisfy this by adding a route, page, component, or file inside apps/starter or another existing app unless the user explicitly asks to modify that existing app.`,\n input.vaultAccessMode === \"all-apps\"\n ? `Do not create per-app Dispatch vault grants unless the workspace switches vault access to manual or the user explicitly asks for manual grants.`\n : keyList\n ? `After the app exists, grant the selected Dispatch vault keys to appId \"${input.appId}\" and sync them once the app server is available. Treat these as requested grants, not active grants before creation succeeds.`\n : `Do not grant any Dispatch vault keys unless the user asks later.`,\n input.selectedResources.length\n ? `After the app exists, grant the selected Dispatch workspace resources to appId \"${input.appId}\" and sync them once the app server is available. Add a short note to apps/${input.appId}/AGENTS.md telling the app agent to read relevant shared resources under context/ or the selected resource paths before doing GTM/domain work.`\n : `Do not grant any Dispatch workspace resources unless the user asks later.`,\n ``,\n `App readiness requirements before handing off:`,\n `- Ensure apps/${input.appId}/package.json exists with displayName/name and a concise description; Dispatch discovers workspace apps from apps/<app-id>/package.json, not a separate app registry.`,\n `- Update the app manifest/package/deploy metadata needed by the existing workspace deployment model.`,\n `- Ensure the React Router client entry preserves APP_BASE_PATH/VITE_APP_BASE_PATH via appBasePath() so /${input.appId} hydrates correctly.`,\n `- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment. Every sibling workspace app is available over A2A by default through call-agent, with names and descriptions from the workspace app registry.`,\n `When it is ready, start or update the workspace dev server and navigate the user to the absolute path /${input.appId} on the workspace origin. Do not prefix with /dispatch/, /apps/, /workspace/, or any other Dispatch tab — the new app is mounted at the workspace root, not under Dispatch. If you have a navigate tool available, pass /${input.appId} verbatim; if you only have a window.location-style escape hatch, set it to /${input.appId}.`,\n ].join(\"\\n\");\n}\n\nasync function fetchJson(url: string, init?: RequestInit): Promise<any> {\n const res = await fetch(url, init);\n const data = await res.json().catch(() => null);\n if (!res.ok) {\n throw new Error(\n data?.error || data?.message || `Request failed ${res.status}`,\n );\n }\n return data;\n}\n\nfunction defaultDispatchBasePath(): string | null {\n const base = appBasePath();\n if (base === \"/dispatch\") return null;\n return null;\n}\n\nfunction actionUrl(basePath: string | null, action: string): string {\n const path = `/_agent-native/actions/${action}`;\n if (basePath === null) return agentNativePath(path);\n const normalized = basePath.replace(/\\/+$/, \"\");\n return `${normalized}${path}`;\n}\n\n/**\n * Inline two-step app-creation flow: prompt → optional access picker → submit.\n * Used both in the popover form and in the dedicated `/new-app` page so the\n * same UX shows up everywhere a teammate kicks off a new workspace app.\n */\nexport function CreateAppFlow({\n onClose,\n className = \"\",\n}: {\n onClose?: () => void;\n className?: string;\n}) {\n const [step, setStep] = useState<\"prompt\" | \"access\">(\"prompt\");\n const [prompt, setPrompt] = useState(\"\");\n const [selectedSecretIds, setSelectedSecretIds] = useState<string[]>([]);\n const [selectedResourceIds, setSelectedResourceIds] = useState<string[]>([]);\n const [secrets, setSecrets] = useState<VaultSecretOption[]>([]);\n const [resources, setResources] = useState<WorkspaceResourceOption[]>([]);\n const [vaultAccessMode, setVaultAccessMode] =\n useState<VaultAccessMode>(\"all-apps\");\n const [secretsError, setSecretsError] = useState<string | null>(null);\n const [resourcesError, setResourcesError] = useState<string | null>(null);\n const [statusMessage, setStatusMessage] = useState<string | null>(null);\n const [branchUrl, setBranchUrl] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const { isDevMode } = useDevMode();\n\n const basePath = useMemo(() => defaultDispatchBasePath(), []);\n\n // Fetch access options eagerly so step 2 has them ready immediately.\n useEffect(() => {\n let cancelled = false;\n fetchJson(actionUrl(basePath, \"list-vault-secret-options\"))\n .then((data) => {\n if (cancelled) return;\n setSecrets(Array.isArray(data) ? data : []);\n setSecretsError(null);\n })\n .catch((err) => {\n if (cancelled) return;\n setSecrets([]);\n setSecretsError(err?.message || \"Could not load Dispatch keys\");\n });\n fetchJson(actionUrl(basePath, \"get-vault-access-settings\"))\n .then((data) => {\n if (cancelled) return;\n setVaultAccessMode(data?.mode === \"manual\" ? \"manual\" : \"all-apps\");\n })\n .catch(() => {\n if (cancelled) return;\n setVaultAccessMode(\"manual\");\n });\n fetchJson(actionUrl(basePath, \"list-workspace-resource-options\"))\n .then((data) => {\n if (cancelled) return;\n setResources(Array.isArray(data) ? data : []);\n setResourcesError(null);\n })\n .catch((err) => {\n if (cancelled) return;\n setResources([]);\n setResourcesError(err?.message || \"Could not load Dispatch resources\");\n });\n return () => {\n cancelled = true;\n };\n }, [basePath]);\n\n const selectedSecrets = useMemo(\n () => secrets.filter((s) => selectedSecretIds.includes(s.id)),\n [secrets, selectedSecretIds],\n );\n const selectedResources = useMemo(\n () => resources.filter((r) => selectedResourceIds.includes(r.id)),\n [resources, selectedResourceIds],\n );\n const selectedSecretLabel =\n vaultAccessMode === \"all-apps\"\n ? \"all keys\"\n : selectedSecretIds.length === 0\n ? \"no keys\"\n : `${selectedSecretIds.length} key${selectedSecretIds.length === 1 ? \"\" : \"s\"}`;\n const selectedResourceLabel =\n selectedResourceIds.length === 0\n ? \"no resources\"\n : `${selectedResourceIds.length} resource${selectedResourceIds.length === 1 ? \"\" : \"s\"}`;\n const selectedAccessLabel = [selectedSecretLabel, selectedResourceLabel].join(\n \" · \",\n );\n\n function toggleSecret(id: string) {\n setSelectedSecretIds((cur) =>\n cur.includes(id) ? cur.filter((x) => x !== id) : [...cur, id],\n );\n }\n\n function toggleResource(id: string) {\n setSelectedResourceIds((cur) =>\n cur.includes(id) ? cur.filter((x) => x !== id) : [...cur, id],\n );\n }\n\n async function submit(rawPrompt: string) {\n const trimmed = rawPrompt.trim();\n if (!trimmed || isSubmitting) return;\n const appId = titleFromPrompt(trimmed);\n const validationError = getWorkspaceAppIdValidationError(appId);\n if (validationError) {\n setStatusMessage(validationError);\n return;\n }\n\n const message = buildAppCreationPrompt({\n appId,\n prompt: trimmed,\n selectedKeys:\n vaultAccessMode === \"manual\"\n ? selectedSecrets.map((s) => s.credentialKey)\n : [],\n selectedResources,\n vaultAccessMode,\n });\n setIsSubmitting(true);\n setStatusMessage(null);\n setBranchUrl(null);\n\n try {\n if (isInBuilderFrame()) {\n sendToAgentChat({ message, submit: true, type: \"code\" });\n setStatusMessage(\"Sent to Builder chat.\");\n onClose?.();\n } else if (isDevMode) {\n sendToAgentChat({ message, submit: true, type: \"code\", newTab: true });\n setStatusMessage(\"Sent to the local agent.\");\n onClose?.();\n } else {\n const result = await fetchJson(\n actionUrl(basePath, \"start-workspace-app-creation\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n prompt: trimmed,\n appId,\n secretIds:\n vaultAccessMode === \"manual\" && selectedSecretIds.length > 0\n ? selectedSecretIds\n : [],\n resourceIds:\n selectedResourceIds.length > 0 ? selectedResourceIds : [],\n }),\n },\n );\n if (result?.mode === \"builder\") {\n setBranchUrl(result?.url || null);\n setStatusMessage(\"Builder branch created.\");\n } else {\n setStatusMessage(\n result?.message ||\n \"Builder app creation is coming soon. Open this workspace in Builder to create an app from this prompt.\",\n );\n }\n }\n } catch (err: any) {\n setStatusMessage(err?.message || \"Could not start the new app flow.\");\n } finally {\n setIsSubmitting(false);\n }\n }\n\n const submitWithSelectedAccess = () => submit(prompt);\n\n return (\n <div className={`flex flex-col gap-3 ${className}`}>\n {step === \"prompt\" ? (\n <>\n <div className=\"flex items-center justify-between gap-2 px-1\">\n <p className=\"text-sm font-semibold text-foreground\">Create app</p>\n <button\n type=\"button\"\n onClick={() => setStep(\"access\")}\n className=\"inline-flex cursor-pointer items-center gap-1 rounded-md border border-border bg-background/40 px-2 py-1 text-[11px] text-muted-foreground hover:text-foreground hover:bg-accent/50\"\n >\n <IconKey size={11} />\n {selectedAccessLabel}\n </button>\n </div>\n <PromptComposer\n autoFocus\n disabled={isSubmitting}\n placeholder=\"Describe the app your teammate should be able to use...\"\n draftScope=\"dispatch:create-app\"\n preserveDraftOnSubmit\n onSubmit={(text) => {\n setPrompt(text);\n submit(text);\n }}\n />\n </>\n ) : (\n <>\n <div className=\"flex items-center justify-between gap-2 px-1\">\n <button\n type=\"button\"\n onClick={() => setStep(\"prompt\")}\n className=\"inline-flex cursor-pointer items-center gap-1 text-xs text-muted-foreground hover:text-foreground\"\n >\n <IconArrowLeft size={12} />\n Back\n </button>\n <span className=\"text-[11px] text-muted-foreground/70\">\n {selectedAccessLabel}\n </span>\n </div>\n <div className=\"max-h-[180px] space-y-2 overflow-y-auto rounded-md border border-border bg-card p-2\">\n <div className=\"flex items-center gap-1.5 px-1 pb-1 text-[11px] font-medium text-muted-foreground\">\n <IconKey size={12} />\n Dispatch keys\n </div>\n {vaultAccessMode === \"all-apps\" ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n Every saved Dispatch vault key is available to new apps.\n </p>\n ) : secretsError ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n {secretsError}\n </p>\n ) : secrets.length === 0 ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n No Dispatch vault keys found yet.\n </p>\n ) : (\n secrets.map((secret) => {\n const selected = selectedSecretIds.includes(secret.id);\n return (\n <div\n key={secret.id}\n className={`group rounded-md border text-sm ${\n selected\n ? \"border-primary/45 bg-primary/5\"\n : \"border-border hover:border-muted-foreground/40 hover:bg-accent/35\"\n }`}\n >\n <button\n type=\"button\"\n aria-pressed={selected}\n onClick={() => toggleSecret(secret.id)}\n className=\"flex w-full cursor-pointer items-start gap-3 rounded-md px-3 py-2 text-left\"\n >\n <span\n className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border ${\n selected\n ? \"border-primary/60 bg-primary/10 text-primary\"\n : \"border-muted-foreground/35 text-transparent\"\n }`}\n >\n {selected ? <IconCheck className=\"h-3 w-3\" /> : null}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium\">\n {secret.credentialKey}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground/70\">\n {selected\n ? \"Will be requested for this app\"\n : \"Click to request\"}\n </span>\n </span>\n </button>\n {(secret.provider || secret.name) && (\n <details className=\"group/details border-t border-border/60 px-3 py-1.5 text-xs text-muted-foreground/75\">\n <summary className=\"flex cursor-pointer list-none items-center gap-1.5 text-[11px] hover:text-muted-foreground [&::-webkit-details-marker]:hidden\">\n <IconChevronDown className=\"h-3 w-3 transition-transform group-open/details:rotate-180\" />\n Details\n </summary>\n <div className=\"mt-1.5 space-y-1 pb-0.5 pl-4\">\n <div className=\"truncate\">\n Provider: {secret.provider || \"Not specified\"}\n </div>\n <div className=\"truncate\">Name: {secret.name}</div>\n </div>\n </details>\n )}\n </div>\n );\n })\n )}\n </div>\n <div className=\"max-h-[180px] space-y-2 overflow-y-auto rounded-md border border-border bg-card p-2\">\n <div className=\"flex items-center gap-1.5 px-1 pb-1 text-[11px] font-medium text-muted-foreground\">\n <IconBook size={12} />\n Resource packs\n </div>\n {resourcesError ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n {resourcesError}\n </p>\n ) : resources.length === 0 ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n No Dispatch resource packs found yet.\n </p>\n ) : (\n resources.map((resource) => {\n const selected = selectedResourceIds.includes(resource.id);\n return (\n <div\n key={resource.id}\n className={`group rounded-md border text-sm ${\n selected\n ? \"border-primary/45 bg-primary/5\"\n : \"border-border hover:border-muted-foreground/40 hover:bg-accent/35\"\n }`}\n >\n <button\n type=\"button\"\n aria-pressed={selected}\n onClick={() => toggleResource(resource.id)}\n className=\"flex w-full cursor-pointer items-start gap-3 rounded-md px-3 py-2 text-left\"\n >\n <span\n className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border ${\n selected\n ? \"border-primary/60 bg-primary/10 text-primary\"\n : \"border-muted-foreground/35 text-transparent\"\n }`}\n >\n {selected ? <IconCheck className=\"h-3 w-3\" /> : null}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <IconFileText className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground/70\" />\n <span className=\"block truncate font-medium\">\n {resource.name}\n </span>\n </span>\n <span className=\"block truncate text-xs text-muted-foreground/70\">\n {resource.kind} · {resource.path}\n </span>\n </span>\n </button>\n <details className=\"group/details border-t border-border/60 px-3 py-1.5 text-xs text-muted-foreground/75\">\n <summary className=\"flex cursor-pointer list-none items-center gap-1.5 text-[11px] hover:text-muted-foreground [&::-webkit-details-marker]:hidden\">\n <IconChevronDown className=\"h-3 w-3 transition-transform group-open/details:rotate-180\" />\n Details\n </summary>\n <div className=\"mt-1.5 space-y-1 pb-0.5 pl-4\">\n <div className=\"truncate\">\n Scope:{\" \"}\n {resource.scope === \"all\"\n ? \"All apps\"\n : \"Selected apps\"}\n </div>\n {resource.description ? (\n <div className=\"line-clamp-2\">\n {resource.description}\n </div>\n ) : null}\n </div>\n </details>\n </div>\n );\n })\n )}\n </div>\n <div className=\"flex items-center justify-end gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={submitWithSelectedAccess}\n disabled={!prompt.trim() || isSubmitting}\n >\n {isSubmitting ? (\n <IconLoader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <IconPlus className=\"h-3.5 w-3.5\" />\n )}\n Create app\n </Button>\n </div>\n {!prompt.trim() ? (\n <p className=\"px-1 text-[11px] text-muted-foreground/70\">\n Add a prompt on the previous step before creating the app.\n </p>\n ) : null}\n </>\n )}\n\n {statusMessage ? (\n <div className=\"rounded-md border border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground\">\n {statusMessage}\n {branchUrl ? (\n <a\n href={branchUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"ml-2 inline-flex items-center gap-1 font-medium text-foreground underline\"\n >\n Open branch <IconArrowUpRight className=\"h-3 w-3\" />\n </a>\n ) : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nexport function CreateAppPopover({\n trigger,\n align = \"center\",\n}: CreateAppPopoverProps) {\n const [open, setOpen] = useState(false);\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n {trigger ?? (\n <button\n type=\"button\"\n className=\"flex min-h-32 cursor-pointer items-center justify-center rounded-lg border border-dashed bg-card p-4 text-sm font-medium text-muted-foreground transition hover:border-foreground/30 hover:text-foreground\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <IconPlus size={16} />\n Create app\n </span>\n </button>\n )}\n </PopoverTrigger>\n <PopoverContent\n align={align}\n sideOffset={10}\n className=\"w-[calc(100vw-2rem)] rounded-xl p-3 shadow-xl sm:w-[460px]\"\n >\n <CreateAppFlow onClose={() => setOpen(false)} />\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
/**
|
|
3
|
-
* DispatchShell renders the per-page title (with optional
|
|
4
|
-
* into the global header via the HeaderActions store.
|
|
5
|
-
* (sidebar, AgentSidebar, header bar with AgentToggleButton)
|
|
6
|
-
* `Layout` mounted in `root.tsx`.
|
|
3
|
+
* DispatchShell renders the per-page title (with an optional click-to-open
|
|
4
|
+
* description popover) into the global header via the HeaderActions store.
|
|
5
|
+
* The actual chrome (sidebar, AgentSidebar, header bar with AgentToggleButton)
|
|
6
|
+
* is provided by `Layout` mounted in `root.tsx`.
|
|
7
7
|
*/
|
|
8
8
|
export declare function DispatchShell({ title, description, children, }: {
|
|
9
9
|
title: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch-shell.d.ts","sourceRoot":"","sources":["../../src/components/dispatch-shell.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB,
|
|
1
|
+
{"version":3,"file":"dispatch-shell.d.ts","sourceRoot":"","sources":["../../src/components/dispatch-shell.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,WAAW,EACX,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CA8BA"}
|