feat: make urls clickable in interrupt (#165)
Some checks failed
CI / Check formatting (push) Has been cancelled
CI / Check linting (push) Has been cancelled
CI / Check README spelling (push) Has been cancelled
CI / Check code spelling (push) Has been cancelled

This commit is contained in:
Sam Crowder
2025-08-11 12:29:42 -07:00
committed by GitHub
parent 9234a380fc
commit 8b9382501e
2 changed files with 40 additions and 9 deletions

View File

@@ -86,7 +86,7 @@ function Interrupt({
)} )}
{interruptValue && {interruptValue &&
!isAgentInboxInterruptSchema(interruptValue) && !isAgentInboxInterruptSchema(interruptValue) &&
isLastMessage ? ( (isLastMessage || hasNoAIOrToolMessages) ? (
<GenericInterruptView interrupt={interruptValue} /> <GenericInterruptView interrupt={interruptValue} />
) : null} ) : null}
</> </>

View File

@@ -6,6 +6,39 @@ function isComplexValue(value: any): boolean {
return Array.isArray(value) || (typeof value === "object" && value !== null); return Array.isArray(value) || (typeof value === "object" && value !== null);
} }
function isUrl(value: any): boolean {
if (typeof value !== "string") return false;
try {
new URL(value);
return value.startsWith("http://") || value.startsWith("https://");
} catch {
return false;
}
}
function renderInterruptStateItem(value: any): React.ReactNode {
if (isComplexValue(value)) {
return (
<code className="rounded bg-gray-50 px-2 py-1 font-mono text-sm">
{JSON.stringify(value, null, 2)}
</code>
);
} else if (isUrl(value)) {
return (
<a
href={value}
target="_blank"
rel="noopener noreferrer"
className="break-all text-blue-600 underline hover:text-blue-800"
>
{value}
</a>
);
} else {
return String(value);
}
}
export function GenericInterruptView({ export function GenericInterruptView({
interrupt, interrupt,
}: { }: {
@@ -17,9 +50,13 @@ export function GenericInterruptView({
const contentLines = contentStr.split("\n"); const contentLines = contentStr.split("\n");
const shouldTruncate = contentLines.length > 4 || contentStr.length > 500; const shouldTruncate = contentLines.length > 4 || contentStr.length > 500;
// Function to truncate long string values // Function to truncate long string values (but preserve URLs)
const truncateValue = (value: any): any => { const truncateValue = (value: any): any => {
if (typeof value === "string" && value.length > 100) { if (typeof value === "string" && value.length > 100) {
// Don't truncate URLs so they remain clickable
if (isUrl(value)) {
return value;
}
return value.substring(0, 100) + "..."; return value.substring(0, 100) + "...";
} }
@@ -95,13 +132,7 @@ export function GenericInterruptView({
{key} {key}
</td> </td>
<td className="px-4 py-2 text-sm text-gray-500"> <td className="px-4 py-2 text-sm text-gray-500">
{isComplexValue(value) ? ( {renderInterruptStateItem(value)}
<code className="rounded bg-gray-50 px-2 py-1 font-mono text-sm">
{JSON.stringify(value, null, 2)}
</code>
) : (
String(value)
)}
</td> </td>
</tr> </tr>
); );