Skip to content

Commit

Permalink
sidepanel: Update the dynamic webAgent whenever the schema is saved (#…
Browse files Browse the repository at this point in the history
…800)

- Update the dynamic webAgent whenever the schema is saved
- Simplify sidepanel UI
  • Loading branch information
hillary-mutisya authored Mar 8, 2025
1 parent 9c1dbb4 commit 0c3349b
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 95 deletions.
17 changes: 17 additions & 0 deletions ts/packages/agents/browser/src/extension/serviceWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1750,11 +1750,13 @@ chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
title: "Refresh crossword agent",
id: "reInitCrosswordPage",
documentUrlPatterns: ["http://*/*", "https://*/*"],
});

chrome.contextMenus.create({
title: "Clear crossword cache",
id: "clearCrosswordPageCache",
documentUrlPatterns: ["http://*/*", "https://*/*"],
});

// Add separator
Expand All @@ -1766,6 +1768,14 @@ chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
title: "Discover page Schema",
id: "discoverPageSchema",
documentUrlPatterns: ["http://*/*", "https://*/*"],
});

chrome.contextMenus.create({
id: "sidepanel-registerAgent",
title: "Update Page Agent",
contexts: ["all"],
documentUrlPatterns: ["chrome-extension://*/sidepanel.html"],
});
});

Expand Down Expand Up @@ -1818,6 +1828,13 @@ chrome.contextMenus?.onClicked.addListener(
await chrome.sidePanel.open({ tabId: tab.id! });
break;
}
case "sidepanel-registerAgent": {
const schemaResult = await sendActionToAgent({
actionName: "registerPageDynamicAgent",
parameters: {},
});
break;
}
}
},
);
Expand Down
33 changes: 13 additions & 20 deletions ts/packages/agents/browser/src/extension/sidepanel.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@
top: 5px;
}

.toggle-button {
width: 50px;
}
.list-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
}

/* Timeline styling*/
.timeline {
border-left: 3px solid #727cf5;
Expand Down Expand Up @@ -167,24 +177,6 @@
</style>
</head>
<body class="container">
<div class="d-flex gap-2">
<button
id="trySchema"
class="btn btn-sm btn-outline-primary"
title="Try Schema"
>
<i class="bi bi-play-circle"></i> Try Page Agent
</button>

<button
id="saveSchema"
class="btn btn-sm btn-outline-primary"
title="Save Schema"
>
<i class="bi bi-floppy"></i> Save
</button>
</div>

<div class="mt-4"></div>
<div class="d-flex justify-content-between align-items-center mt-3">
<h3>Detected Actions</h3>
Expand All @@ -195,8 +187,9 @@ <h3>Detected Actions</h3>
<i class="bi bi-arrow-clockwise"></i>
</button>
</div>
<!-- Accordion for Schema -->
<div class="accordion" id="schemaAccordion"></div>
<div class="card">
<ul class="list-group list-group-flush" id="detectedSchemaItemsList"></ul>
</div>

<!-- User Defined Actions -->
<div id="userActionsContainer" class="mt-4">
Expand Down
157 changes: 82 additions & 75 deletions ts/packages/agents/browser/src/extension/sidepanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@ async function getActiveTabUrl(): Promise<string | null> {
}

async function requestSchemaUpdate(forceRefresh?: boolean) {
const schemaAccordion = document.getElementById(
"schemaAccordion",
) as HTMLDivElement;
schemaAccordion.innerHTML = "<p>Loading...</p>";
const itemsList = document.getElementById(
"detectedSchemaItemsList",
) as HTMLElement;

itemsList.innerHTML = "";

const refreshButton = document.getElementById(
"refreshDetectedActions",
) as HTMLButtonElement;
const originalHtml = refreshButton.innerHTML;

const currentSchema = await getStoredPageProperty(
launchUrl!,
Expand All @@ -40,66 +46,86 @@ async function requestSchemaUpdate(forceRefresh?: boolean) {
currentActionDefinitions === null ||
forceRefresh
) {
const response = await chrome.runtime.sendMessage({
type: "refreshSchema",
});
if (chrome.runtime.lastError) {
console.error("Error fetching schema:", chrome.runtime.lastError);
return;
refreshButton.innerHTML =
'<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>';

try {
const response = await chrome.runtime.sendMessage({
type: "refreshSchema",
});
if (chrome.runtime.lastError) {
console.error(
"Error fetching schema:",
chrome.runtime.lastError,
);
return;
}

await setStoredPageProperty(
launchUrl!,
"detectedActions",
response.schema,
);
await setStoredPageProperty(
launchUrl!,
"detectedActionDefinitions",
response.actionDefinitions,
);

renderSchemaResults(response.schema);
} finally {
refreshButton.innerHTML = originalHtml;
}

await setStoredPageProperty(
launchUrl!,
"detectedActions",
response.schema,
);
await setStoredPageProperty(
launchUrl!,
"detectedActionDefinitions",
response.actionDefinitions,
);

renderSchemaResults(response.schema);
} else {
renderSchemaResults(currentSchema);
}

registerTempSchema();
}

function renderSchemaResults(schemaActions: any) {
const schemaAccordion = document.getElementById(
"schemaAccordion",
) as HTMLDivElement;
const itemsList = document.getElementById(
"detectedSchemaItemsList",
) as HTMLElement;

if (schemaActions) {
schemaAccordion.innerHTML = "";
itemsList.innerHTML = "";

schemaActions.forEach((action: any, index: number) => {
const { actionName, parameters } = action;
const paramsText = parameters
? JSON.stringify(parameters, null, 2)
: "{}";

const accordionItem = document.createElement("div");
accordionItem.classList.add("accordion-item");

accordionItem.innerHTML = `
<h2 class="accordion-header" id="heading${index}">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
data-bs-target="#collapse${index}" aria-expanded="false" aria-controls="collapse${index}">
${actionName}
</button>
</h2>
<div id="collapse${index}" class="accordion-collapse collapse" aria-labelledby="heading${index}" data-bs-parent="#schemaAccordion">
<div class="accordion-body">
<pre><code class="language-json">${paramsText}</code></pre>
</div>
</div>
`;

schemaAccordion.appendChild(accordionItem);
const listItem = document.createElement("li");
listItem.className = "list-group-item list-item";

const nameSpan = document.createElement("span");
nameSpan.textContent = actionName;

/*
const toggleDiv = document.createElement('div');
toggleDiv.className = 'form-check form-switch';
const toggleInput = document.createElement('input');
toggleInput.className = 'form-check-input';
toggleInput.type = 'checkbox';
toggleInput.id = `toggle-${index}`;
toggleInput.checked = true;
toggleInput.addEventListener('change', () => {
// toggleOption(index);
});
toggleDiv.appendChild(toggleInput);
*/
listItem.appendChild(nameSpan);
//listItem.appendChild(toggleDiv);

itemsList.appendChild(listItem);
});
} else {
schemaAccordion.innerHTML = "<p>No schema found.</p>";
itemsList.innerHTML = "<p>No schema found.</p>";
}
}

Expand All @@ -116,33 +142,13 @@ function copySchemaToClipboard() {
}

async function registerTempSchema() {
const button = document.getElementById("trySchema") as HTMLButtonElement;
const originalContent = button.innerHTML;
const originalClass = button.className;

function showTemporaryStatus(text: string, newClass: string) {
button.innerHTML = text;
button.className = `btn btn-sm ${newClass}`;

setTimeout(() => {
button.innerHTML = originalContent;
button.className = originalClass;
button.disabled = false;
}, 5000);
}
await chrome.runtime.sendMessage({
type: "registerTempSchema",
});

button.innerHTML = `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Processing...`;
button.disabled = true;
try {
const response = await chrome.runtime.sendMessage({
type: "registerTempSchema",
});
} catch {}
if (chrome.runtime.lastError) {
console.error("Error fetching schema:", chrome.runtime.lastError);
showTemporaryStatus("✖ Failed", "btn-outline-danger");
} else {
showTemporaryStatus("✔ Succeeded", "btn-outline-success");
return;
}
}

Expand Down Expand Up @@ -237,6 +243,7 @@ async function saveUserAction() {

toggleActionForm();
await updateUserActionsUI();
registerTempSchema();
}

async function addEntryToStoredPageProperties(
Expand Down Expand Up @@ -328,6 +335,7 @@ async function clearRecordedUserAction() {
await setStoredPageProperty(launchUrl!, "authoredIntentJson", null);
// Update UI
await updateUserActionsUI();
registerTempSchema();
}

async function showUserDefinedActionsList() {
Expand Down Expand Up @@ -487,10 +495,13 @@ function renderTimelineSteps(
card.classList.add("event");
card.dataset.date = new Date(step.timestamp).toLocaleString();

// only display a subset of fields in the UI
const { boundingBox, timestamp, id, ...filteredObjet } = step;

card.innerHTML = `
<h3>${index + 1}. ${step.type}</h3>
<p>Details.</p>
<pre class="card-text"><code class="language-json">${JSON.stringify(step, null, 2)}</code></pre>
<pre class="card-text"><code class="language-json">${JSON.stringify(filteredObjet, null, 2)}</code></pre>
`;

stepsContainer.appendChild(card);
Expand Down Expand Up @@ -566,10 +577,6 @@ document.addEventListener("DOMContentLoaded", async () => {
.getElementById("refreshDetectedActions")!
.addEventListener("click", () => requestSchemaUpdate(true));

document
.getElementById("trySchema")!
.addEventListener("click", registerTempSchema);

document
.getElementById("recordAction")!
.addEventListener("click", startRecording);
Expand Down

0 comments on commit 0c3349b

Please sign in to comment.