assets/mcp-cards/health-card-v2.html.txt
Rama main · réplica de lectura del repositorio original.
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Chickpea health card</title>
<style>/*
* Framework-free MCP App styles.
*/
@layer base {
:root {
color-scheme: light dark;
--background: var(
--color-background-primary,
light-dark(rgb(255 255 255), rgb(24 24 24))
);
--foreground: var(
--color-text-primary,
light-dark(rgb(26 28 31), rgb(255 255 255))
);
--card: color-mix(in oklab, var(--foreground) 5%, var(--background));
--card-foreground: var(--color-text-primary, var(--foreground));
--primary: var(
--color-text-info,
light-dark(rgb(51 156 255), rgb(131 195 255))
);
--primary-foreground: var(
--color-text-inverse,
light-dark(rgb(255 255 255), rgb(13 13 13))
);
--secondary: var(
--color-background-secondary,
light-dark(rgb(255 255 255 / 96%), rgb(54 54 54 / 96%))
);
--secondary-foreground: var(--color-text-primary, var(--foreground));
--muted: color-mix(in srgb, var(--foreground) 10%, transparent);
--muted-foreground: var(
--color-text-secondary,
light-dark(rgb(26 28 31 / 49.4%), rgb(255 255 255 / 49.8%))
);
--accent: var(
--color-background-info,
light-dark(rgb(229 242 255), rgb(13 39 63))
);
--accent-foreground: var(--color-text-info, var(--primary));
--destructive: var(
--color-text-warning,
light-dark(rgb(226 85 7), rgb(255 133 73))
);
--border: var(
--color-border-secondary,
light-dark(rgb(26 28 31 / 8%), rgb(255 255 255 / 8.2%))
);
--input: var(
--color-border-primary,
light-dark(rgb(26 28 31 / 11.8%), rgb(255 255 255 / 12%))
);
--ring: var(--color-ring-primary, var(--primary));
--font-size-base: var(--font-text-md-size, 14px);
--radius: var(--border-radius-lg, 12.5px);
}
:root[data-theme="light"] {
color-scheme: light;
}
:root[data-theme="dark"] {
color-scheme: dark;
}
body {
margin: 0;
color: var(--foreground);
background: var(--background);
font-size: max(11px, var(--font-size-base));
font-weight: var(--font-weight-normal, 430);
line-height: 1.5;
}
/* MCP sandboxes can force their own font on body, so restore the host font below it. */
body,
body > * {
font-family: var(
--font-sans,
-apple-system,
system-ui,
"Segoe UI",
sans-serif
);
}
h1,
h2,
h3,
p {
margin-block: 0;
}
h1,
h2,
h3 {
font-weight: var(--font-weight-medium, 500);
line-height: 1.25;
}
h1 {
font-size: calc(var(--font-size-base) * 1.7142857143);
}
h2 {
font-size: calc(var(--font-size-base) * 1.4285714286);
}
h3 {
font-size: calc(var(--font-size-base) * 1.2857142857);
}
}
@layer components {
.cursor-interaction {
cursor: var(--cursor-interaction, pointer);
}
.card {
min-width: 0;
padding: 12px;
overflow-wrap: break-word;
border-radius: calc(var(--radius) * 1.6);
corner-shape: superellipse(1.5);
color: var(--card-foreground);
background: var(--card);
}
.btn,
.form-check-input,
.form-control,
.form-select {
box-sizing: border-box;
font: inherit;
}
.btn {
appearance: button;
display: inline-flex;
inline-size: fit-content;
max-inline-size: 100%;
min-height: 28px;
align-items: center;
justify-content: center;
gap: 4px;
margin: 0;
padding: 0 8px;
border: 1px solid var(--input);
border-radius: var(--radius);
corner-shape: superellipse(1.5);
color: var(--secondary-foreground);
background: var(--secondary);
cursor: var(--cursor-interaction, pointer);
text-align: center;
text-decoration: none;
white-space: nowrap;
user-select: none;
}
.btn:not(:disabled):hover {
background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));
}
.btn-primary {
border-color: transparent;
color: var(--primary-foreground);
background: var(--foreground);
background-clip: padding-box;
}
.btn-primary:not(:disabled):hover {
background: color-mix(in srgb, var(--foreground) 80%, transparent);
background-clip: padding-box;
}
.btn-ghost {
border-color: transparent;
color: var(--muted-foreground);
background: transparent;
}
.btn-ghost:not(:disabled):hover {
color: var(--foreground);
background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));
}
.btn:not(.btn-primary):is([aria-pressed="true"], [aria-selected="true"]) {
border-color: var(--primary);
color: var(--primary-foreground);
background: var(--primary);
}
.btn:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
.btn:disabled,
.form-check-input:disabled,
.form-control:disabled,
.form-select:disabled {
cursor: not-allowed;
opacity: 0.4;
}
.form-label {
display: block;
margin-bottom: 6px;
color: var(--foreground);
}
.form-control,
.form-select {
display: block;
width: 100%;
min-height: 28px;
padding: 0 8px;
outline: none;
border: 1px solid var(--input);
border-radius: var(--radius);
corner-shape: superellipse(1.5);
color: var(--foreground);
background: var(--secondary);
}
.form-control::placeholder {
color: var(--muted-foreground);
}
.form-select {
appearance: none;
padding-right: 32px;
background-image:
linear-gradient(45deg, transparent 50%, var(--muted-foreground) 50%),
linear-gradient(135deg, var(--muted-foreground) 50%, transparent 50%);
background-position:
calc(100% - 14px) 50%,
calc(100% - 10px) 50%;
background-repeat: no-repeat;
background-size: 4px 4px;
cursor: var(--cursor-interaction, pointer);
}
.form-select:not(:disabled):hover {
background-color: color-mix(
in srgb,
var(--foreground) 6%,
var(--secondary)
);
}
textarea.form-control {
min-height: 72px;
padding: 8px 10px;
resize: vertical;
}
.form-control:focus-visible,
.form-select:focus-visible {
border-color: var(--ring);
box-shadow: inset 0 0 0 1px var(--ring);
}
.form-check {
display: flex;
min-height: 20px;
align-items: center;
gap: 8px;
}
.form-check-input {
appearance: none;
display: grid;
width: 16px;
height: 16px;
flex: 0 0 auto;
place-items: center;
margin: 0;
border: 1px solid var(--input);
border-radius: 5px;
corner-shape: superellipse(1.5);
color: var(--primary-foreground);
background: var(--secondary);
cursor: var(--cursor-interaction, pointer);
}
.form-check-input:checked {
border-color: var(--primary);
background: var(--primary);
}
.form-check-input:checked::after {
width: 7px;
height: 4px;
border-bottom: 2px solid currentColor;
border-left: 2px solid currentColor;
content: "";
transform: translateY(-1px) rotate(-45deg);
}
.form-check-input:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
.form-check-label {
color: var(--foreground);
}
svg.lucide {
display: block;
width: 16px;
height: 16px;
flex: none;
stroke-width: 1.6;
}
.text-small {
font-size: max(11px, calc(var(--font-size-base) - 2px));
}
.text-muted {
color: var(--muted-foreground);
}
.text-destructive {
color: var(--destructive);
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
}
/*
* The Agent card in ChatGPT's own look: its type, colors and black primary
* buttons, from the host's style variables. Chickpea shows only in the avatar
* and the quote accent. Without host variables the colors fall back to the
* mockup's palette, and without a host theme to light.
*/
:root:not([data-theme]) {
color-scheme: light;
}
:root {
--cp-bg: var(--color-background-primary, light-dark(#ffffff, #181818));
--cp-fg: var(--color-text-primary, light-dark(#0d0d0d, #ededed));
/* Secondary text stays at AA contrast; the host's tertiary text does not. */
--cp-muted: var(--color-text-secondary, light-dark(#5d5d5d, #cdcdcd));
--cp-line: var(--color-border-primary, light-dark(#e5e5e5, rgb(255 255 255 / 20%)));
--cp-soft: light-dark(#f7f7f7, rgb(255 255 255 / 6%));
--cp-ok: light-dark(#1a7f37, #40c977);
--cp-warn: light-dark(#a15c00, #f0a050);
--cp-danger: #c62828;
--cp-danger-hover: #a31f1f;
--cp-accent: #e8901a;
--cp-size: var(--font-text-md-size, 14px);
}
html,
body {
background: var(--cp-bg);
color: var(--cp-fg);
}
body {
font-size: var(--cp-size);
line-height: 1.45;
}
.cp-card {
display: flex;
flex-direction: column;
gap: 0;
padding: 16px;
overflow-wrap: anywhere;
}
.cp-hdr {
display: flex;
gap: 12px;
align-items: center;
}
.cp-avatar {
flex: none;
display: block;
}
.cp-avatar svg,
.cp-avatar img {
display: block;
width: 100%;
height: 100%;
}
/* Slack's rounded square, cropped as Admin and the setup page crop it. */
.cp-avatar img {
object-fit: cover;
}
.cp-avatar-lg {
width: 44px;
height: 44px;
}
.cp-avatar-lg img {
border-radius: 12px;
}
.cp-avatar-sm {
width: 26px;
height: 26px;
}
.cp-avatar-sm img {
border-radius: 7px;
}
/* On an alert card, an Agent's picture keeps the alert art's red. */
.cp-avatar-alert img {
outline: 2px solid var(--cp-danger);
outline-offset: 1px;
}
.cp-heading {
min-width: 0;
}
.cp-title {
margin: 0;
font-size: calc(var(--cp-size) * 1.143);
font-weight: 600;
line-height: 1.25;
}
/* Focus lands here after a redraw only so the keyboard stays on the card. */
.cp-title:focus {
outline: none;
}
.cp-sub {
margin: 2px 0 0;
color: var(--cp-muted);
font-size: calc(var(--cp-size) * 0.93);
}
.cp-ok {
color: var(--cp-ok);
}
.cp-warn {
color: var(--cp-warn);
}
.cp-text {
margin: 12px 0 0;
white-space: pre-line;
}
.cp-sect {
margin: 14px 0 6px;
color: var(--cp-muted);
font-size: calc(var(--cp-size) * 0.79);
font-weight: 600;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.cp-sect + .cp-text {
margin-top: 0;
}
.cp-quote {
margin: 6px 0;
padding: 2px 0 2px 10px;
border-left: 3px solid var(--cp-accent);
white-space: pre-line;
}
.cp-note {
margin: 6px 0 0;
color: var(--cp-muted);
font-size: calc(var(--cp-size) * 0.93);
}
.cp-note.cp-warn {
color: var(--cp-warn);
}
.cp-thread {
display: flex;
flex-direction: column;
gap: 9px;
padding: 10px 12px;
border: 1px solid var(--cp-line);
border-radius: 12px;
background: var(--cp-soft);
}
.cp-msg {
display: grid;
grid-template-columns: 26px 1fr;
gap: 8px;
font-size: calc(var(--cp-size) * 0.964);
}
/* A host may pass an example's line breaks as they are; they show as written. */
.cp-said {
white-space: pre-line;
overflow-wrap: anywhere;
}
.cp-who {
font-weight: 600;
font-size: calc(var(--cp-size) * 0.93);
}
.cp-who-note {
margin-left: 4px;
color: var(--cp-muted);
font-weight: 400;
}
.cp-init {
display: grid;
width: 26px;
height: 26px;
place-items: center;
border-radius: 7px;
background: #4a6cc4;
color: #ffffff;
font-size: calc(var(--cp-size) * 0.86);
font-weight: 600;
}
.cp-facts {
display: grid;
grid-template-columns: max-content 1fr;
gap: 6px 12px;
margin: 12px 0 0;
font-size: calc(var(--cp-size) * 0.964);
}
.cp-facts dt {
color: var(--cp-muted);
}
.cp-facts dd {
margin: 0;
}
.cp-chip {
display: inline-flex;
padding: 0 9px;
border: 1px solid var(--cp-line);
border-radius: 999px;
background: var(--cp-soft);
font-size: calc(var(--cp-size) * 0.9);
}
.cp-faint {
color: var(--cp-muted);
font-size: calc(var(--cp-size) * 0.86);
}
.cp-foot {
margin: 14px 0 0;
color: var(--cp-muted);
font-size: calc(var(--cp-size) * 0.93);
}
.cp-steps {
display: flex;
flex-direction: column;
gap: 7px;
margin: 12px 0 0;
padding: 0;
list-style: none;
font-size: calc(var(--cp-size) * 0.964);
}
.cp-steps li {
display: flex;
gap: 8px;
align-items: center;
}
.cp-ic {
display: inline-grid;
flex: none;
width: 18px;
height: 18px;
box-sizing: border-box;
place-items: center;
border-radius: 50%;
font-size: 11px;
}
.cp-ic-done {
background: color-mix(in srgb, var(--cp-ok) 14%, transparent);
color: var(--cp-ok);
}
.cp-ic-now {
border: 2px solid var(--cp-accent);
border-right-color: transparent;
animation: cp-spin 0.9s linear infinite;
}
.cp-ic-todo {
border: 1.5px solid var(--cp-line);
}
.cp-ic-failed {
background: color-mix(in srgb, var(--cp-danger) 14%, transparent);
color: light-dark(var(--cp-danger), #ff8a80);
font-weight: 700;
}
@keyframes cp-spin {
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: reduce) {
.cp-ic-now {
animation: none;
}
}
.cp-acts {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
margin-top: 14px;
}
.cp-card .btn {
min-height: 34px;
padding: 0 14px;
border-radius: 999px;
font-size: calc(var(--cp-size) * 0.964);
font-weight: 600;
}
.cp-btn-primary {
border-color: transparent;
color: var(--color-text-inverse, light-dark(#ffffff, #0d0d0d));
background: var(--cp-fg);
}
.cp-btn-primary:not(:disabled):hover {
background: color-mix(in srgb, var(--cp-fg) 82%, var(--cp-bg));
}
.cp-btn-danger {
border-color: transparent;
color: #ffffff;
background: var(--cp-danger);
}
.cp-btn-danger:not(:disabled):hover {
background: var(--cp-danger-hover);
}
.cp-btn-secondary {
border-color: var(--cp-line);
color: var(--cp-fg);
background: var(--cp-bg);
}
.cp-card .btn:focus-visible {
outline: 2px solid var(--color-ring-primary, light-dark(#0169cc, #ffffff));
outline-offset: 2px;
}
.cp-acts[hidden],
.cp-error[hidden] {
display: none;
}
.cp-error {
margin: 10px 0 0;
color: light-dark(#b42318, #ff8a80);
font-size: calc(var(--cp-size) * 0.93);
}
.cp-rows {
display: flex;
flex-direction: column;
container-type: inline-size;
margin: 12px 0 0;
padding: 0;
border: 1px solid var(--cp-line);
border-radius: 14px;
list-style: none;
}
.cp-row {
display: grid;
grid-template-columns: 22px minmax(0, 1fr) auto;
gap: 10px;
align-items: center;
padding: 10px 12px;
border-top: 1px solid var(--cp-line);
font-size: calc(var(--cp-size) * 0.964);
}
.cp-row:first-child {
border-top: 0;
}
/* A narrow card puts a row's link under its words instead of squeezing them. */
@container (max-width: 520px) {
.cp-row:has(> .cp-link-go) {
grid-template-columns: 22px minmax(0, 1fr);
row-gap: 2px;
}
.cp-row > .cp-link-go {
grid-column: 2;
justify-self: start;
white-space: normal;
text-align: start;
}
}
.cp-row-detail {
color: var(--cp-muted);
font-size: calc(var(--cp-size) * 0.893);
white-space: pre-line;
}
.cp-row-detail.cp-warn {
color: var(--cp-warn);
}
.cp-tile {
display: grid;
width: 22px;
height: 22px;
place-items: center;
border-radius: 6px;
background: var(--cp-fg);
color: var(--cp-bg);
font-size: calc(var(--cp-size) * 0.86);
font-weight: 700;
}
.cp-ic-warning {
background: color-mix(in srgb, var(--cp-warn) 16%, transparent);
color: var(--cp-warn);
font-weight: 700;
}
.cp-ic-unknown {
border: 1.5px solid var(--cp-line);
color: var(--cp-muted);
font-weight: 700;
}
.cp-card .btn-sm {
min-height: 30px;
padding: 0 12px;
font-size: calc(var(--cp-size) * 0.893);
white-space: nowrap;
}
.cp-link {
padding: 4px 0;
border: 0;
background: none;
color: var(--cp-fg);
font: inherit;
font-size: calc(var(--cp-size) * 0.93);
font-weight: 600;
white-space: nowrap;
cursor: var(--cursor-interaction, pointer);
}
.cp-link-go::after {
content: " →" / "";
}
.cp-link:not(:disabled):hover {
text-decoration: underline;
}
.cp-link:disabled {
color: var(--cp-muted);
}
.cp-link:focus-visible {
border-radius: 4px;
outline: 2px solid var(--color-ring-primary, light-dark(#0169cc, #ffffff));
outline-offset: 2px;
}
</style></head>
<body><div id="card"></div><script>"use strict";(()=>{var de="2026-01-26";var R=class{constructor(t){this.appInfo=t;window.addEventListener("message",n=>{n.source===window.parent&&this.#i(n.data)}),this.on("ui/notifications/host-context-changed",n=>{let o=n,{styles:r,...i}=this.hostContext??{},c=o.theme!==void 0&&o.theme!==i.theme&&!o.styles;this.hostContext={...i,...r&&!c?{styles:r}:{},...o}})}appInfo;#r=1;#e=new Map;#n=new Map;hostContext;hostCapabilities;on(t,n){this.#n.set(t,[...this.#n.get(t)??[],n])}async connect(){let t=await this.#t("ui/initialize",{appInfo:this.appInfo,appCapabilities:{availableDisplayModes:["inline"]},protocolVersion:de});this.hostContext=t?.hostContext,this.hostCapabilities=t?.hostCapabilities,this.#o("ui/notifications/initialized",{}),new ResizeObserver(()=>this.#o("ui/notifications/size-changed",{height:Math.ceil(document.body.getBoundingClientRect().height)})).observe(document.body)}async callTool(t,n,o){return await this.#t("tools/call",{name:t,arguments:n},o)}async sendMessage(t){let n=this.hostCapabilities?.experimental?.["openai/message"]?.draft!==void 0,o=t.draft!==void 0&&n?t.draft:t.sent;M(await this.#t("ui/message",{role:"user",content:[{type:"text",text:o}],...o===t.draft?{_meta:{"openai/message":{target:"active",send:!1}}}:{}}))}async updateModelContext(t){M(await this.#t("ui/update-model-context",{content:[{type:"text",text:t}]}))}async openLink(t){if(window.openai?.openExternal)try{await window.openai.openExternal({href:t,redirectUrl:!1});return}catch{}M(await this.#t("ui/open-link",{url:t}))}#o(t,n){window.parent.postMessage({jsonrpc:"2.0",method:t,params:n},"*")}#t(t,n,o){let r=this.#r++;return new Promise((i,c)=>{let u=setTimeout(()=>{o?this.#e.set(r,{resolve:o,reject:()=>{}}):this.#e.delete(r),c(new Error(`${t} timed out`))},6e4);this.#e.set(r,{resolve:l=>{clearTimeout(u),i(l)},reject:l=>{clearTimeout(u),c(l)}}),window.parent.postMessage({jsonrpc:"2.0",id:r,method:t,params:n},"*")})}#i(t){if(!(!t||t.jsonrpc!=="2.0")){if(t.method===void 0){let n=typeof t.id=="number"?this.#e.get(t.id):void 0;if(!n)return;this.#e.delete(t.id),t.error?n.reject(t.error):n.resolve(t.result);return}for(let n of this.#n.get(t.method)??[])n(t.params);t.id!==void 0&&window.parent.postMessage({jsonrpc:"2.0",id:t.id,result:{}},"*")}}};function M(e){if(e?.isError===!0)throw new Error("The host refused it")}function le(e){document.documentElement.setAttribute("data-theme",e),document.documentElement.style.colorScheme=e}function ue(e){for(let[t,n]of Object.entries(e))n!==void 0&&document.documentElement.style.setProperty(t,n)}var z=[];function I(e){e?.theme&&le(e.theme);let t=e?.["openai/interactionCursor"],n={...e?.styles?.variables,"--cursor-interaction":typeof t=="string"&&/^[a-z-]+$/.test(t)?t:void 0};for(let o of z)n[o]===void 0&&document.documentElement.style.removeProperty(o);ue(n),z=Object.keys(n).filter(o=>n[o]!==void 0)}var F=(e,t,n)=>`<svg viewBox="0 0 44 44" aria-hidden="true" focusable="false"><rect width="44" height="44" rx="12" fill="${e}"/><path d="M22 6c-9 0-14 8-14 18v14h28V24C36 14 31 6 22 6z" fill="${t}"/><path d="M22 12c-6 0-9.5 6-9.5 13.5S16 38 22 38s9.5-5 9.5-12.5S28 12 22 12z" fill="${n}"/><circle cx="18.5" cy="26" r="1.3" fill="#3a2a1e"/><circle cx="25.5" cy="26" r="1.3" fill="#3a2a1e"/><path d="M20.5 30.2q1.5 1.2 3 0" stroke="#3a2a1e" stroke-width="1.1" fill="none" stroke-linecap="round"/></svg>`,pe={agent:F("#3a2a1e","#E8901A","#f3d9b1"),alert:F("#2a1f2e","#c2453a","#f1d3b8")},fe={done:"done",now:"in progress",todo:"to do",failed:"failed"},G={done:{glyph:"\u2713",words:"done"},now:{glyph:"",words:"in progress"},failed:{glyph:"!",words:"needs attention"},warning:{glyph:"!",words:"warning"},unknown:{glyph:"?",words:"unknown"}};function s(e,t,n){let o=document.createElement(e);return t&&(o.className=t),n!==void 0&&(o.textContent=n),o}var W=new Set;function K(e,t,n){let o=s("span",`cp-avatar cp-avatar-${t}`),r=()=>{o.innerHTML=pe[e]};if(!n||W.has(n))return r(),o;e==="alert"&&o.classList.add("cp-avatar-alert");let i=s("img");return i.alt="",i.decoding="async",i.addEventListener("error",()=>{W.add(n),r()},{once:!0}),i.src=n,o.append(i),o}function ge(e){let t=s("p","cp-sub");for(let n of e)t.append(n.tone?s("span",`cp-${n.tone}`,n.text):n.text);return t}function he(e,t,n){switch(e.kind){case"text":return s("p","cp-text",e.text);case"quote":return s("blockquote","cp-quote",e.text);case"section":return s("h3","cp-sect",e.label);case"note":return s("p",`cp-note${e.tone?` cp-${e.tone}`:""}`,e.text);case"exchange":{let o=s("div","cp-thread"),r=s("div","cp-msg"),i=s("div","cp-who","You");i.append(s("span","cp-who-note","example"));let c=s("div");c.append(i,s("div","cp-said",e.ask)),r.append(s("span","cp-init","Y"),c);let u=s("div","cp-msg"),l=s("div");return l.append(s("div","cp-who",e.agent),s("div","cp-said",e.answer)),u.append(K(t,"sm",n),l),o.append(r,u),o}case"facts":{let o=s("dl","cp-facts");for(let r of e.rows){let i=s("dd",void 0,r.value);for(let c of r.chips??[])i.append(s("span","cp-chip",c)," ");r.note&&i.append(s("span","cp-faint",r.note)),o.append(s("dt",void 0,r.label),i)}return o}case"steps":{let o=s("ul","cp-steps");for(let{label:r,state:i}of e.steps){let c=s("li"),u=s("span",`cp-ic cp-ic-${i}`,i==="done"?"\u2713":i==="failed"?"!":"");u.setAttribute("aria-hidden","true"),c.append(u,r,s("span","sr-only",` (${fe[i]})`)),o.append(c)}return o}case"rows":{let o=s("ul","cp-rows");return o.append(...e.rows.map(we)),o}}}function we(e){let t=s("li","cp-row");if(e.icon==="tile"){let r=s("span","cp-tile",e.tile??"");r.setAttribute("aria-hidden","true"),t.append(r)}else{let r=G[e.icon],i=s("span",`cp-ic cp-ic-${e.icon}`,r.glyph);i.setAttribute("aria-hidden","true"),t.append(i)}let n=s("div","cp-row-body"),o=s("div","cp-row-title",e.title);if(e.icon!=="tile"&&o.append(s("span","sr-only",` (${G[e.icon].words})`)),n.append(o),e.detail&&n.append(s("div",`cp-row-detail${e.tone?` cp-${e.tone}`:""}`,e.detail)),t.append(n),e.control){let{label:r,action:i,style:c}=e.control;t.append(J(r,i,c==="link"?"cp-link cp-link-go":c==="toggle"?"cp-link":`btn btn-sm cp-btn-${c}`))}return t}function J(e,t,n){let o=s("button",`${n} cursor-interaction`,e);return o.type="button",o.dataset.action=t,o}function X(e,t){let n=s("p","sr-only");n.setAttribute("aria-live","polite");let o=s("main","cp-card"),r=s("div","cp-content"),i=s("div","cp-acts"),c=s("p","cp-error");c.setAttribute("role","alert"),o.append(r,i,c),e.replaceChildren(n,o),o.addEventListener("click",a=>{let d=a.target?.closest("button[data-action]");d instanceof HTMLButtonElement&&!d.disabled&&t(d.dataset.action)});let u="",l="",h=new Map;return{render(a){let d=JSON.stringify(a);if(d===u)return;u=d;let m=o.contains(document.activeElement),k=a.announce??a.title;n.textContent!==k&&(n.textContent=k);let p=s("header","cp-hdr"),b=a.avatar==="none"?"agent":a.avatar,{avatarUrl:V}=a;a.avatar!=="none"&&p.append(K(a.avatar,"lg",V));let $=s("div","cp-heading"),x=s("h2","cp-title");if(x.tabIndex=-1,a.done){let w=s("span","cp-ok","\u2713 ");w.setAttribute("aria-hidden","true"),x.append(w)}x.append(a.title),$.append(x),a.subtitle&&$.append(ge(a.subtitle)),p.append($);let v=new Map,ce=a.blocks.map(w=>{let A=JSON.stringify([w,b,V]),U=!v.has(A)&&h.get(A)||he(w,b,V);return v.has(A)||v.set(A,U),U});h=v,r.replaceChildren(p,...ce,...a.foot?[s("p","cp-foot",a.foot)]:[]);let j=JSON.stringify(a.buttons);j!==l&&(l=j,i.replaceChildren(...a.buttons.map(w=>J(w.label,w.action,`btn cp-btn-${w.tone}`)))),i.hidden=a.buttons.length===0;for(let w of o.querySelectorAll("button"))w.disabled=a.busy,w.toggleAttribute("aria-busy",a.busy);c.textContent=a.error??"",c.hidden=!a.error,m&&!o.contains(document.activeElement)&&x.focus({preventScroll:!0})}}}var ye=1e3;function Q(e,t){let n=new R({name:e,version:String(2)}),o=ke(),r=o?{view:o.view,busy:!1,seq:o.seq}:t.initial,i,c=0,u=X(document.getElementById("card"),d=>l({type:"press",action:d,now:Date.now()}));function l(d){let m=t.step(r,d),k=m.state.view!==r.view;r=m.state,k&&be(r),u.render(t.present(r));for(let p of m.effects)h(p)}function h(d){switch(d.type){case"call":{let m=k=>l({type:"reply",call:d.call,result:k,now:Date.now()});n.callTool(d.call.tool,d.call.args,m).then(m,()=>l({type:"unreachable",call:d.call,now:Date.now()}));return}case"timer":clearTimeout(i),i=setTimeout(()=>l({type:"tick",now:Date.now()}),d.inMs);return;case"message":n.sendMessage(d).catch(()=>l({type:"refused",effect:d,now:Date.now()}));return;case"open":n.openLink(d.url).catch(()=>l({type:"refused",effect:d,now:Date.now()}));return;case"context":n.updateModelContext(d.text).catch(()=>{});return}}function a(){let d=Date.now();d-c<ye||r.view.kind==="waiting"||(c=d,l({type:"reread",now:d}))}n.on("ui/notifications/tool-result",d=>{o||r.view.kind!=="waiting"||(l({type:"result",result:me(d),now:Date.now()}),a())}),n.on("ui/notifications/tool-cancelled",()=>l({type:"no_result",now:Date.now()})),n.on("ui/notifications/host-context-changed",()=>I(n.hostContext)),window.addEventListener("focus",a),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&a()}),u.render(t.present(r)),n.connect().then(()=>{I(n.hostContext),o&&a()},()=>l({type:"no_result",now:Date.now()}))}function me(e){let t=window.openai?.toolResponseMetadata;return e._meta||typeof t!="object"||t===null||Array.isArray(t)?e:{...e,_meta:t}}function ke(){let t=window.openai?.widgetState?.privateContent?.card,n=t?.view;return t?.version===2&&n&&typeof n.kind=="string"?{view:n,seq:t.seq??0}:void 0}function be({view:e,seq:t}){if(e.kind==="waiting")return;let n={version:2,view:e,seq:t};Promise.resolve(window.openai?.setWidgetState?.({privateContent:{card:n}})).catch(()=>{})}var f=(e,t=[])=>({state:e,effects:t}),y=(e,t=[])=>({state:{view:e,busy:!1},effects:t}),E=(e,t)=>({type:"call",call:{tool:e,args:t}}),N=(e,t)=>({...e,effects:[{type:"context",text:t},...e.effects]});function Z(e){return(t,n)=>{let o=e(t,n.type==="result"||n.type==="reply"?{...n,result:xe(n.result)}:n),r=o.state.view===t.view?t.seq:t.seq+1;return{state:{...o.state,seq:r},effects:o.effects.map(i=>i.type==="call"?{...i,call:{...i.call,seq:r}}:i)}}}function O(e,t){return t.seq!==e.seq}function xe(e){let t=e._meta?.["chickpea/held"],n=e.structuredContent;if(!g(t)||!g(n))return e;let o=typeof t.confirmToken=="string"?t.confirmToken:void 0,r=typeof t.undoToken=="string"?t.undoToken:void 0;return{...e,structuredContent:{...n,...r?{undoToken:r}:{},...o&&g(n.confirmation)?{confirmation:{...n.confirmation,confirmToken:o}}:{}}}}var C="That did not work. Try again.",ee="Chickpea could not be reached. Try again.",T={kind:"notice",title:"Nothing to show here."};function S(e){return typeof e=="string"&&URL.parse(e)?.protocol==="https:"?e:void 0}var Y=60;function H(e,t){let n=e.length>Y?`${e.slice(0,Y-1)}\u2026`:e;return`the Agent ${JSON.stringify(n)}${t?` (@${t})`:""}`}function g(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function L(e){if(!e.isError)return;let t=g(e.structuredContent)?e.structuredContent.error:void 0;return g(t)&&typeof t.message=="string"?t.message:C}function te(e){return t=>{try{return e(t)}catch{return{busy:t.busy,error:t.error,avatar:"none",title:T.title,blocks:[],buttons:[]}}}}function P(e){return typeof e.plain=="string"&&e.plain!==""?e.plain:Ce[e.part][e.status]}var Ce={connection:{ok:"Connected.",warning:"Connected, but something needs a look.",failing:"It is not working.",unknown:"The check could not tell whether it works."},model:{ok:"It can run.",warning:"It may not run as expected.",failing:"It cannot run now.",unknown:"The check could not tell whether it can run."},slack:{ok:"Ready in Slack.",warning:"Not ready in Slack yet.",failing:"It has a problem in Slack.",unknown:"The check could not tell whether it is ready in Slack."},channel:{ok:"Answers here.",warning:"Not answering here yet.",failing:"It cannot answer here.",unknown:"The check could not tell whether it answers here."},schedule:{ok:"On schedule.",warning:"Some of its runs need a look.",failing:"Its runs are failing.",unknown:"The check could not tell whether it runs."},repository:{ok:"GitHub access is installed.",warning:"GitHub access needs a look.",failing:"It cannot reach this repository.",unknown:"The check could not tell whether it can reach this repository."},website_login:{ok:"Ready to sign in.",warning:"This login needs a look.",failing:"It cannot sign in.",unknown:"The check could not tell whether it can sign in."},admission:{ok:"A message reaches it.",warning:"A message may not reach it.",failing:"A message does not reach it.",unknown:"Slack decides when the message arrives."}};function ve(e){return e.tool==="reconnect_service"||e.tool==="connect_model_provider"||e.tool==="connect_service"&&!("custom"in e.arguments)}var ne={view:{kind:"waiting"},busy:!1,seq:0},oe=Z(Ae);function Ae(e,t){switch(t.type){case"result":return Re(t.result);case"press":return e.busy||e.view.kind!=="health"?f(e):Ee(e,e.view,t.action);case"reply":return O(e,t.call)?f(e):Se(e,t.call.tool,t.result);case"unreachable":return O(e,t.call)?f(e):t.call.tool==="get_agent"||e.view.kind!=="health"?f(e):f({view:_(e.view),busy:!1,error:ee});case"refused":return f({...e,error:C});case"no_result":return e.view.kind==="waiting"?y(T):f(e);case"tick":return f(e);case"reread":return!e.busy&&e.view.kind==="health"?f(e,[E("get_agent",{agentId:e.view.checked.agent.agentId})]):f(e)}}function Re(e){let t=L(e);return t?y({kind:"notice",title:t}):ie(e.structuredContent)?y({kind:"health",checked:e.structuredContent}):y(T)}function Ee(e,t,n){switch(n){case"show":return y({...t,open:!0});case"hide":{let{open:o,...r}=t;return y(r)}case"check_again":return t.checked.person.you?{state:{view:t,busy:!0},effects:[Te(t.checked)]}:f(e);default:{let o=Number(n.slice(4)),r=t.checked.checks[o],i=r?.fix;if(!r||!i)return f(e);if("url"in i){let c=S(i.url);return c?f(e,[{type:"open",url:c}]):f(e)}return ve(i)?{state:{view:{...t,fixing:o},busy:!0},effects:[E(i.tool,i.arguments)]}:f(e,[re(t,o)])}}}function re(e,t){let n=e.checked.checks[t];return{type:"message",sent:`Fix ${n.name} for ${e.checked.agent.name}: ${n.fix.label}.`}}function Te(e){return E("check_agent",{agentId:e.agent.agentId,...e.place.kind==="channel"&&e.place.channelId?{place:e.place.channelId}:{}})}function Se(e,t,n){let{view:o}=e;if(o.kind!=="health")return f(e);let r=L(n),i=n.structuredContent;if(t==="get_agent")return e.busy||r?f(e):_e(e,o,i);if(t==="check_agent"){if(r||!ie(i))return f({view:o,busy:!1,error:r??C});let a=i.checks.filter(({status:d})=>d==="failing"||d==="warning").length;return N(y({kind:"health",checked:i,...o.open?{open:!0}:{}}),`The person checked ${H(i.agent.name)} again from the card: ${a===0?"no problems found":`${a} ${a===1?"thing needs":"things need"} attention`}.`)}let c=!r&&g(i)&&g(i.setup)?i.setup:void 0,u=S(c?.url);if(!u||o.fixing===void 0){let a=g(i)&&typeof i.summary=="string"?i.summary:void 0;return f({view:_(o),busy:!1,error:r??a??C})}if(typeof c?.setupToken!="string")return y(_(o),[re(o,o.fixing)]);let l=[...(o.opened??[]).filter(a=>a!==o.fixing),o.fixing],h=o.checked.checks[o.fixing]?.fix;return N(y({..._(o),opened:l},[{type:"open",url:u}]),`The person opened Chickpea's page to ${h?.label??"fix it"} for ${H(o.checked.agent.name)} from the card. It changes when they finish there.`)}function _e(e,t,n){let o=g(n)&&Array.isArray(n.connections)?n.connections:void 0;if(!o)return f(e);let r=Object.fromEntries(o.map(({connectionId:u,status:l})=>[u,l]));if(!t.before)return y({...t,before:r});let c=t.checked.checks.filter(({part:u,status:l,connectionId:h})=>u==="connection"&&l!=="ok"&&h!==void 0&&t.before[h]!=="ready"&&r[h]==="ready").map(({connectionId:u})=>u).filter(u=>!t.fixed?.includes(u));return c.length?y({...t,fixed:[...t.fixed??[],...c]}):f(e)}function _({fixing:e,...t}){return t}function ie(e){return g(e)&&g(e.agent)&&typeof e.agent.name=="string"&&g(e.person)&&g(e.place)&&Array.isArray(e.checks)&&e.checks.every(t=>g(t)&&typeof t.name=="string"&&typeof t.detail=="string"&&typeof t.part=="string"&&Object.hasOwn(se,t.part)&&typeof t.status=="string"&&Object.hasOwn(D,t.status)&&Ve(t.fix))}function Ve(e){return e===void 0||g(e)&&typeof e.label=="string"&&(typeof e.url=="string"||typeof e.tool=="string"&&g(e.arguments))}var se={connection:"connections",model:"model",slack:"Slack",channel:"Channels",schedule:"schedules",repository:"repositories",website_login:"website logins",admission:"who can reach it"},D={failing:0,warning:1,unknown:2,ok:3},ae=te($e);function $e(e){let t={busy:e.busy,error:e.error},{view:n}=e;switch(n.kind){case"waiting":return{...t,avatar:"none",title:"Loading\u2026",blocks:[],buttons:[]};case"notice":return{...t,avatar:"none",title:n.title,blocks:[],buttons:[]};case"health":return{...t,...Me(n)}}}function Me(e){let{checked:t}=e,n=t.checks.map((p,b)=>({check:p,index:b,status:Ie(e,p)})),o=n.filter(({status:p})=>p==="failing"||p==="warning"),r=n.filter(({status:p})=>p==="unknown"),i=n.filter(({status:p})=>p==="ok"),c=[...o,...r].sort((p,b)=>D[p.status]-D[b.status]||p.index-b.index),u=t.agent.handle?`@${t.agent.handle}`:t.agent.name,l=[...new Set(t.checks.map(({part:p})=>se[p]))],h=c.length>0,a=[...c.map(p=>q(e,p)),...i.length?[{icon:"done",title:`${i.length} ${h?"other ":""}${i.length===1?"part looks":"parts look"} healthy`,control:e.open?{label:"Hide",action:"hide",style:"toggle"}:{label:"Show",action:"show",style:"toggle"}}]:[],...e.open?i.map(p=>q(e,p)):[]],d=o.length>0?`${o.length} ${o.length===1?"thing needs":"things need"} attention`:r.length>0?"No problems found":"Everything looks healthy",m=e.opened?.at(-1),k=m===void 0?void 0:n[m];return{avatar:n.some(({status:p})=>p==="failing")?"alert":"agent",avatarUrl:S(t.agent.avatarUrl),title:d,...k?{announce:`${d}. ${B(k.check)}: ${q(e,k).detail}`}:{},subtitle:[{text:`${u} \xB7 checked its ${Ne(l)}`}],blocks:a.length?[{kind:"rows",rows:a}]:[],buttons:t.person.you?[{label:"Check again",action:"check_again",tone:"secondary"}]:[]}}function Ie(e,t){return t.connectionId!==void 0&&e.fixed?.includes(t.connectionId)?"ok":t.status}function q(e,{check:t,index:n,status:o}){if(o==="ok")return{icon:"done",title:B(t),detail:e.fixed?.includes(t.connectionId??"")?"Connected.":P(t)};let r=e.opened?.includes(n);return{icon:r?"now":o==="failing"?"failed":o==="warning"?"warning":"unknown",title:B(t),detail:r?"Finish on the Chickpea page that opened, then come back.":P(t),...t.fix?{control:{label:t.fix.label,action:`fix:${n}`,style:"link"}}:{}}}function B(e){let{channelId:t}=e;if(e.part==="channel"&&t&&e.name===t)return"A private Channel";let n=e.part==="admission"&&t&&e.name.endsWith(`, in ${t}`)?`${e.name.slice(0,-t.length)}a private Channel`:e.name;return e.part==="admission"?`${n.charAt(0).toUpperCase()}${n.slice(1)}`:n}function Ne(e){return e.length<=2?e.join(" and "):`${e.slice(0,-1).join(", ")} and ${e.at(-1)}`}Q("chickpea-health-card",{initial:ne,step:oe,present:ae});})();
</script></body>
</html>