// Copyright (c) Microsoft. All rights reserved.
///
/// Static HTML pages served by the sample application.
///
internal static class Pages
{
// ═══════════════════════════════════════════════════════════════════════
// Homepage
// ═══════════════════════════════════════════════════════════════════════
internal const string Home = """
Foundry Responses Hosting — Demos
🚀 Foundry Responses Hosting
Agent-framework agents hosted via the Azure AI Responses Server SDK.
Each demo registers a different agent and serves it through POST /responses.
All demos share the same /responses endpoint.
The model field in the request selects which agent handles it.
""";
// ═══════════════════════════════════════════════════════════════════════
// Tool Demo
// ═══════════════════════════════════════════════════════════════════════
internal const string ToolDemo = """
Tool Demo — Foundry Responses Hosting
← Back to demos
🔧 Tool Demo
Agent with local tools (time, weather) + Microsoft Learn MCP (docs search)
🕐 Time in Tokyo
🌤️ Weather in Seattle
📚 Azure Functions docs
📚 Agent Framework
""";
// ═══════════════════════════════════════════════════════════════════════
// Workflow Demo
// ═══════════════════════════════════════════════════════════════════════
internal const string WorkflowDemo = """
Workflow Demo — Foundry Responses Hosting
← Back to demos
🔀 Workflow Demo — Agent Handoffs
A triage agent routes your question to a specialist (Code Expert or Creative Writer)
👤 User → 🔀 Triage → 💻 Code Expert / ✍️ Creative Writer
💻 Reverse linked list
✍️ Cloud haiku
💻 Async vs threads
✍️ AI painter story
""";
// ═══════════════════════════════════════════════════════════════════════
// SSE Validator Script (shared by all demo pages)
// ═══════════════════════════════════════════════════════════════════════
internal const string ValidationScript = """
// SseValidator - inline SSE stream validation for Foundry Responses demos
// Captures events during streaming and validates against the API behaviour contract.
(function() {
const style = document.createElement('style');
style.textContent = `
.sse-val { margin: .4rem 0 .6rem; padding: .3rem .5rem; font-size: .75rem; color: #aaa; border-top: 1px dashed #e8e8e8; }
.val-ok { color: #7ab88a; }
.val-err { color: #d47272; font-weight: 500; }
.val-issues { margin: .2rem 0; }
.val-issue { color: #c06060; font-size: .72rem; padding: .1rem 0; }
.val-issue b { color: #b04040; }
.val-at { color: #ccc; font-size: .68rem; }
.val-log summary { cursor: pointer; color: #bbb; font-size: .72rem; }
.val-log-items { max-height: 120px; overflow-y: auto; font-size: .7rem; background: #fafafa;
padding: .3rem; border-radius: 3px; margin-top: .15rem;
font-family: 'Cascadia Code', 'Fira Code', monospace; }
.val-i { color: #ccc; display: inline-block; width: 1.8rem; text-align: right; margin-right: .3rem; }
.val-t { color: #8ab4d0; }
`;
document.head.appendChild(style);
})();
class SseValidator {
constructor() { this.events = []; }
reset() { this.events = []; }
capture(eventType, data) { this.events.push({ eventType, data }); }
async validate() {
const resp = await fetch('/api/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ events: this.events })
});
return await resp.json();
}
renderElement(result) {
const el = document.createElement('div');
el.className = 'sse-val';
const n = result.eventCount;
const ok = result.isValid;
const vs = result.violations || [];
const esc = s => String(s).replace(/&/g,'&').replace(//g,'>');
let h = ok
? `${n} events — all rules passed ✅ `
: `${n} events — ${vs.length} violation(s) `;
if (vs.length) {
h += '';
vs.forEach(v => {
h += `
[${esc(v.ruleId)}] ${esc(v.message)} #${v.eventIndex}
`;
});
h += '
';
}
h += `Event log (${this.events.length}) `;
this.events.forEach((e, i) => {
h += `
${i} ${esc(e.eventType)}
`;
});
h += '
';
el.innerHTML = h;
return el;
}
}
""";
}