Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 1x 40x 40x 1x 49x 49x 28x 28x 21x 21x 1x 1x 64x 64x 64x 64x 1x 1x 64x 1x 113x 113x 113x 113x 81x 81x 32x 32x 32x 32x 113x 113x 113x 1x 3x 3x 3x 1x 1x 2x 2x 2x | export function removeTrailingSlash(url: string): string {
return url.replace(/\/$/, '');
}
export function removeEndingPath(url: string): string {
// https://example-eastus2.services.ai.azure.com/models -> https://example-eastus2.services.ai.azure.com
// Only remove the ending path if there's actually a path after the domain
const urlParts = url.match(/^(https?:\/\/[^/]+)(\/.*)?$/);
if (urlParts?.[2]) {
return urlParts[1] + urlParts[2].replace(/\/[^/]+$/, '');
}
return url;
}
/**
* Matches gateway paths that name the agent and skill in the URL, for example
* `/v1/agents/my-agent/skills/my-skill/chat/completions`.
*/
const AGENT_SKILL_PATH_PATTERN =
/^\/v1\/agents\/([^/]+)\/skills\/([^/]+)(\/.*)?$/;
export interface AgentSkillPathScope {
agent_name: string;
skill_name: string;
/** The path with the `/agents/:agent_name/skills/:skill_name` segment removed. */
pathname: string;
}
function decodePathSegment(segment: string): string {
try {
return decodeURIComponent(segment);
} catch {
// Malformed percent-encoding: keep the raw segment so the lookup fails with
// an "agent not found" error instead of a decoding crash.
return segment;
}
}
/**
* Reads the agent and skill names out of a path-scoped gateway URL.
*
* Returns `null` when the path is not scoped, in which case the names are
* expected in the `sa-config` header instead.
*/
export function parseAgentSkillPath(
pathname: string,
): AgentSkillPathScope | null {
const match = AGENT_SKILL_PATH_PATTERN.exec(pathname);
if (!match) {
return null;
}
const [, agentName, skillName, rest] = match;
return {
agent_name: decodePathSegment(agentName),
skill_name: decodePathSegment(skillName),
pathname: `/v1${rest ?? ''}`,
};
}
/**
* Rewrites a path-scoped gateway URL to its canonical form so that route
* matching and logging treat both request styles the same way.
*
* `/v1/agents/my-agent/skills/my-skill/chat/completions` -> `/v1/chat/completions`
*/
export function stripAgentSkillPath(urlString: string): string {
const url = new URL(urlString);
const scope = parseAgentSkillPath(url.pathname);
if (!scope) {
return urlString;
}
url.pathname = scope.pathname;
return url.toString();
}
|