diff --git a/vscode/media/command-deck/command-deck.js b/vscode/media/command-deck/command-deck.js index 23feeec0..8ed0cd0b 100644 --- a/vscode/media/command-deck/command-deck.js +++ b/vscode/media/command-deck/command-deck.js @@ -133,7 +133,6 @@ class CommandDeck { this.ref.innerHTML = textContent.substring(0, atIndex) + textContent.substring(atIndex + 1); } if (option?.name.startsWith('@')) { - console.log('agents options', option?.metadata); activeAgentAttach.style = "color: #497BEF; !important"; agentName = option?.metadata.display_name; diff --git a/vscode/media/onboarding/onboarding.js b/vscode/media/onboarding/onboarding.js index 1b64c84c..138bf32c 100644 --- a/vscode/media/onboarding/onboarding.js +++ b/vscode/media/onboarding/onboarding.js @@ -1047,7 +1047,6 @@ function handleSubmit(event) { } else { matchingItems = getAgents().filter(item => { - console.log('name', item); return item.search?.toLowerCase().startsWith(query.toLowerCase()); }); } diff --git a/vscode/src/providers/chat_view_provider.ts b/vscode/src/providers/chat_view_provider.ts index 8776b72c..dc8eb504 100644 --- a/vscode/src/providers/chat_view_provider.ts +++ b/vscode/src/providers/chat_view_provider.ts @@ -174,7 +174,6 @@ export class FlutterGPTViewProvider implements vscode.WebviewViewProvider { // StorageManager.instance.deleteAgents(); webviewView.onDidChangeVisibility(() => { - console.log("webview", webviewView.visible); if (webviewView.visible && this._view) { this._view?.webview.postMessage({ type: "focusChatInput" }); } @@ -454,6 +453,7 @@ export class FlutterGPTViewProvider implements vscode.WebviewViewProvider { private: false, }; try { + console.log(JSON.stringify(data)); const modelResponse = await makeHttpRequest<{ response: string, references: Array }>({ url: "https://api.commanddash.dev/v2/ai/agent/answer", method: "post", @@ -468,19 +468,15 @@ export class FlutterGPTViewProvider implements vscode.WebviewViewProvider { value: this._publicConversationHistory, }); } catch (error) { - this._publicConversationHistory.push({ - [this._activeAgent]: { - role: "error", - text: - error instanceof Error - ? (error as Error).message - : (error as any).toString(), - }, - }); - this._view?.webview.postMessage({ - type: "displayMessages", - value: this._publicConversationHistory, - }); + // this._publicConversationHistory.push({ + // [this._activeAgent]: { + // role: "error", + // text: + // error instanceof Error + // ? (error as Error).message + // : (error as any).toString(), + // }, + // }); } finally { this?._view?.webview?.postMessage({ type: "hideLoadingIndicator" }); } @@ -730,19 +726,15 @@ export class FlutterGPTViewProvider implements vscode.WebviewViewProvider { } catch (error) { console.error(error); logError("command-deck-conversation-error", error); - this._publicConversationHistory.push({ - [this._activeAgent]: { - role: "error", - text: - error instanceof Error - ? (error as Error).message - : (error as any).toString(), - }, - }); - this._view?.webview.postMessage({ - type: "displayMessages", - value: this._publicConversationHistory, - }); + // this._publicConversationHistory.push({ + // [this._activeAgent]: { + // role: "error", + // text: + // error instanceof Error + // ? (error as Error).message + // : (error as any).toString(), + // }, + // }); } finally { this._view?.webview.postMessage({ type: "hideLoadingIndicator" }); this._view?.webview.postMessage({ diff --git a/web/src/lib/components/CreateAgentDialog.svelte b/web/src/lib/components/CreateAgentDialog.svelte index a709b2a1..884bd846 100644 --- a/web/src/lib/components/CreateAgentDialog.svelte +++ b/web/src/lib/components/CreateAgentDialog.svelte @@ -1,133 +1,356 @@ {#if showModal} -
-
-
-

Create Agent with URL

- -
- -
- {#each platforms as platform} - - {/each} -
+
+
+
+

Create Agent with URL

+
+ +
+
-
-
- {#if selectedPlatform === 'github'} - - {:else} - p.id === selectedPlatform).icon} - alt={selectedPlatform} - class="w-5 h-5" - /> - {/if} -
- p.id === selectedPlatform).placeholder} - class="w-full pl-10 pr-3 py-2 bg-gray-800 border border-gray-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 text-gray-100 placeholder-gray-500" +
+ {#each platforms as platform} + + {:else} + {platform.label} + {/if}
+ {platform.label} + + {/each} +
- +
+
+ {#if selectedPlatform === "github"} + + {:else} + p.id === selectedPlatform).icon} + alt={selectedPlatform} + class="w-5 h-5" + /> + {/if}
+ p.id === selectedPlatform) + .placeholder} + class="w-full pl-10 pr-3 py-2 bg-gray-800 border border-gray-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 text-gray-100 placeholder-gray-500" + /> +
+ {#if accessToken && !isRepoAccessible } + + {/if} + {#if !isRepoAccessible && !accessToken} + + {:else} + + {/if}
+
{/if} \ No newline at end of file + .selected { + transform: scale(1.1); + } + .selected span { + color: #60a5fa; /* blue-400 */ + font-weight: bold; + } + diff --git a/web/src/lib/components/PrivateAgentDialog.svelte b/web/src/lib/components/PrivateAgentDialog.svelte new file mode 100644 index 00000000..13ab2813 --- /dev/null +++ b/web/src/lib/components/PrivateAgentDialog.svelte @@ -0,0 +1,445 @@ + + +{#if showPrivateModal} +
+ +
+

Create New Agent

+

+ Create and share your own AI Code Agents. +

+ {#if isLoading} +
+

Creating agent...

+
+ {:else} +
+
+ + + + +
+
+ + Add Data Sources + +
+
+ + +
+ {#if !isRepoAccessible} + + {/if} + +
+ +
+ {#if !!accessToken && !!refreshToken} + + + {:else} + + {/if} +
+
+
+ {/if} +
+
+
+{/if} \ No newline at end of file diff --git a/web/src/lib/components/icons/IconInternet.svelte b/web/src/lib/components/icons/IconInternet.svelte new file mode 100644 index 00000000..c05abaac --- /dev/null +++ b/web/src/lib/components/icons/IconInternet.svelte @@ -0,0 +1,28 @@ + + + diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte index 1168849c..664dac2b 100644 --- a/web/src/routes/+page.svelte +++ b/web/src/routes/+page.svelte @@ -1,249 +1,260 @@ - CommandDash - Marketplace - - - - + CommandDash - Marketplace + + + +
-
-
-
-
-

AI Agents for Libraries

-
-

- Personalized answers from expert agents at your command -

-
+
+
+
+
+

AI Agents for Libraries

+
+

+ Personalized answers from expert agents at your command +

+
+ +
+
+
+ + search(e.currentTarget.value)} + /> +
+
+ {#if loading} +
+
+ Loading results +
+
+
+ {:else if searchValue} +
+

Search Results

+
+ {#each filteredAgents as agent} + {/each}
-
-
- - search(e.currentTarget.value)} - /> -
-
- {#if loading} -
-
- Loading results -
-
-
- {:else} - {#if searchValue} -
-

Search Results

-
- {#each filteredAgents as agent} - - {/each} -
-
- {:else} - {#each Object.keys(sections) as section} -
-

{section}

-
- {#each sections[section] as agent, index} - - - {/each} -
-
- {/each} - {/if} - {/if} -
+ + {/each} +
+
+ {/each} + {/if} +
{ - showModal = false; - }} + bind:showModal + onClose={() => { + showModal = false; + }} + onPrivateAgent={() => { + showModal = false; + showPrivateModal = true; + }} +/> + { + showPrivateModal = false; + }} /> \ No newline at end of file + .promoted-card { + border: 2px solid #1e90ff; /* Blue border */ + background-color: #e6f7ff; /* Light blue background */ + } + + .promoted-indicator { + position: absolute; + top: 0; + right: 0; + background-color: #1e90ff; /* Blue background */ + color: #fff; /* White text */ + padding: 0.2em 0.5em; + font-size: 0.75em; + font-weight: bold; + border-bottom-left-radius: 0.5em; + } + + .promoted-text { + color: #003366; /* Dark blue text */ + text-shadow: 0.5px 0.5px 1px rgba(0, 0, 0, 0.1); /* Subtle text shadow */ + } + diff --git a/web/src/routes/agent/+page.svelte b/web/src/routes/agent/+page.svelte index 59bf392c..de385fd0 100644 --- a/web/src/routes/agent/+page.svelte +++ b/web/src/routes/agent/+page.svelte @@ -12,6 +12,7 @@ let currentAgentDetails: Agent; let errorMessage: string = "Something went wrong"; let agentDataSources: Array = []; + let accessToken: string | null = ""; const limit: number = 10; @@ -19,10 +20,13 @@ onMount(async () => { loading = true; + accessToken = localStorage.getItem("accessToken"); + const githubRef: string = $page.url.searchParams.get("github") || ""; const npmRef: string = $page.url.searchParams.get("npm") || ""; const pypiRef: string = $page.url.searchParams.get("pypi") || ""; const pubRef: string = $page.url.searchParams.get("pub") || ""; + const passcode: string = $page.url.searchParams.get("passcode") || ""; let referrer = ""; let referrer_kind = ""; @@ -71,18 +75,28 @@ name: "AgentPage", }); - const response = await fetch( + const headers = { + "Content-Type": "application/json", + }; + if (!!accessToken && accessToken.length > 0) { + headers.Authorization = "Bearer " + accessToken; + } + + const response = await apiRequest( "https://api.commanddash.dev/agent/get-latest-agent", { method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ referrer, referrer_kind }), + headers: headers, + body: JSON.stringify({ + referrer: referrer, + kind: referrer_kind, + passcode: passcode + }), }, ); const _response = await response.json(); + if (!response.ok) { loading = false; errorMessage = _response.message; @@ -90,8 +104,25 @@ throw pageError(response.status, _response.message); } + if (_response.passcode) { + const currentUrl = new URL(window.location.href); + const passcodeParam = `passcode=${_response.passcode}`; + + // Check if the passcode parameter already exists + if (!currentUrl.searchParams.has('passcode')) { + // Check if there are already query parameters + if (currentUrl.search) { + currentUrl.search += `&${passcodeParam}`; + } else { + currentUrl.search = `?${passcodeParam}`; + } + + window.history.replaceState({}, "", currentUrl); + } +} + currentAgentDetails = _response as Agent; - agentDataSources = extractUris(currentAgentDetails?.data_sources) + agentDataSources = extractUris(currentAgentDetails?.data_sources); loading = false; // Track custom event for agent details loaded appInsights.trackEvent({ @@ -104,6 +135,64 @@ }); }); + async function apiRequest(url: string, options: RequestInit) { + try { + const accessToken = localStorage.getItem("accessToken"); + const response = await fetch(url, { + ...options, + headers: { + ...options.headers, + }, + }); + + if (response.status === 401) { + const refreshed = await refreshAccessToken(); + if (refreshed) { + // Retry the request with the refreshed token + options.headers = { + ...options.headers, + Authorization: `Bearer ${accessToken}`, // use updated token + }; + return await fetch(url, options); + } + } + + return response; + } catch (error) { + throw error; + } + } + + async function refreshAccessToken() { + try { + const refreshToken = localStorage.getItem("refreshToken"); + + const response = await fetch( + "https://api.commanddash.dev/account/github/refresh", + { + method: "POST", + headers: { + Authorization: `Bearer ${refreshToken}`, + }, + }, + ); + const _response = await response.json(); + if (response.ok) { + accessToken = _response.access_token; + if (accessToken?.length === 0) { + localStorage.setItem("accessToken", accessToken); + } + return true; + } else { + console.error("Failed to refresh token"); + return false; + } + } catch (error) { + console.error("refreshAccessToken: error", error); + return false; + } + } + const extractUris = ( data: { id: string; uri: { type: string; uri: string }[] }[], ): { type: string; uri: string }[] => { @@ -122,7 +211,6 @@ }); return result; }; - {#if currentAgentDetails} @@ -136,7 +224,7 @@ agentLogo={currentAgentDetails?.metadata?.avatar_id} agentIsDataSourceIndexed={currentAgentDetails.data_sources_indexed} agentId={currentAgentDetails?.name} - agentDataSources={agentDataSources} + {agentDataSources} /> {/if} @@ -147,4 +235,4 @@

Error:

{errorMessage}

-{/if} \ No newline at end of file +{/if} diff --git a/web/src/routes/agent/[id]/+page.svelte b/web/src/routes/agent/[id]/+page.svelte index 3032ad54..cded9bb9 100644 --- a/web/src/routes/agent/[id]/+page.svelte +++ b/web/src/routes/agent/[id]/+page.svelte @@ -1,93 +1,176 @@ {#if currentAgentDetails} - + {/if} {#if loading} - + {:else if !loading && !currentAgentDetails} -
-

{errorStatus}

-

{errorMessage}

-
+
+

{errorStatus}

+

{errorMessage}

+
{/if}