| ... | @@ -33,6 +33,13 @@ export function MCP() { | ... | @@ -33,6 +33,13 @@ export function MCP() { |
| 33 | }; | 33 | }; |
| 34 | }); | 34 | }); |
| 35 | onCleanup(() => events?.close()); | 35 | onCleanup(() => events?.close()); |
| | 36 | const linkShale = async () => { |
| | 37 | setBusy(true); |
| | 38 | try { |
| | 39 | const result = await parseResponse(api.mcp.shale.$post({ json: { request: consent()?.scopes.includes("shale:read") ? request() || undefined : undefined } })); |
| | 40 | window.location.assign(result.redirect); |
| | 41 | } catch (error) { toast(reason(error)); setBusy(false); } |
| | 42 | }; |
| 36 | const answer = async (deny: boolean) => { | 43 | const answer = async (deny: boolean) => { |
| 37 | setBusy(true); | 44 | setBusy(true); |
| 38 | try { | 45 | try { |
| ... | @@ -52,10 +59,10 @@ export function MCP() { | ... | @@ -52,10 +59,10 @@ export function MCP() { |
| 52 | <div class="mcp-resources"><For each={details().resources}>{(resource) => | 59 | <div class="mcp-resources"><For each={details().resources}>{(resource) => |
| 53 | <Checkbox checked={picked().includes(resource.id)} onChange={(checked) => setPicked(checked ? [...picked(), resource.id] : picked().filter((item) => item !== resource.id))}>{resource.name}</Checkbox> | 60 | <Checkbox checked={picked().includes(resource.id)} onChange={(checked) => setPicked(checked ? [...picked(), resource.id] : picked().filter((item) => item !== resource.id))}>{resource.name}</Checkbox> |
| 54 | }</For></div> | 61 | }</For></div> |
| 55 | <Show when={!details().linked}><p>Link your Shale account below to choose repositories.</p></Show> | 62 | <Show when={!details().linked}><p>Link your Shale account to choose repositories.</p></Show> |
| 56 | <Show when={details().linked && !details().resources.length}><p>No resources are available to your account.</p></Show> | 63 | <Show when={details().linked && !details().resources.length}><p>No resources are available to your account.</p></Show> |
| 57 | <Show when={details().scopes.includes("offline_access")}><p class="muted">This connection can refresh access without another sign-in.</p></Show> | 64 | <Show when={details().scopes.includes("offline_access")}><p class="muted">This connection can refresh access without another sign-in.</p></Show> |
| 58 | <div class="mcp-actions"><button class="button" disabled={!picked().length || busy()} onClick={() => answer(false)}>Allow access</button> | 65 | <div class="mcp-actions"><Show when={details().linked} fallback={<button class="button" disabled={busy()} onClick={linkShale}>Link account</button>}><button class="button" disabled={!picked().length || busy()} onClick={() => answer(false)}>Allow access</button></Show> |
| 59 | <button class="button secondary" disabled={busy()} onClick={() => answer(true)}>Decline</button></div> | 66 | <button class="button secondary" disabled={busy()} onClick={() => answer(true)}>Decline</button></div> |
| 60 | </section>} | 67 | </section>} |
| 61 | </Loaded> | 68 | </Loaded> |
| ... | @@ -71,11 +78,7 @@ export function MCP() { | ... | @@ -71,11 +78,7 @@ export function MCP() { |
| 71 | <Show when={data().shale} fallback={<p>Link your Shale account to grant clients access to its repositories.</p>}> | 78 | <Show when={data().shale} fallback={<p>Link your Shale account to grant clients access to its repositories.</p>}> |
| 72 | {(shale) => <p>Account linked <Ago t={shale().linkedAt} /></p>} | 79 | {(shale) => <p>Account linked <Ago t={shale().linkedAt} /></p>} |
| 73 | </Show> | 80 | </Show> |
| 74 | <button class="button" disabled={busy()} onClick={async () => { | 81 | <button class="button" disabled={busy()} onClick={linkShale}>{data().shale ? "Relink account" : "Link account"}</button> |
| 75 | setBusy(true); | | |
| 76 | try { const result = await parseResponse(api.mcp.shale.$post({ json: { request: consent()?.scopes.includes("shale:read") ? request() || undefined : undefined } })); window.location.assign(result.redirect); } | | |
| 77 | catch (error) { toast(reason(error)); setBusy(false); } | | |
| 78 | }}>{data().shale ? "Relink account" : "Link account"}</button> | | |
| 79 | <Show when={data().shale}><button class="button secondary" disabled={busy()} onClick={async () => { | 82 | <Show when={data().shale}><button class="button secondary" disabled={busy()} onClick={async () => { |
| 80 | setBusy(true); | 83 | setBusy(true); |
| 81 | try { await parseResponse(api.mcp.shale.$delete()); await refetch(); } | 84 | try { await parseResponse(api.mcp.shale.$delete()); await refetch(); } |