Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions packages/dsh-web/src/client.css
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,30 @@
white-space: nowrap;
}

.guionai-web__tool-details {
display: flex;
flex-wrap: wrap;
gap: 6px 14px;
margin: 0;
color: var(--dsw-alias-label-tertiary);
font-size: 12px;
line-height: 18px;
}

.guionai-web__tool-details div {
display: flex;
gap: 4px;
}

.guionai-web__tool-details dt::after {
content: ":";
}

.guionai-web__tool-details dd {
margin: 0;
color: var(--dsw-alias-label-secondary);
}

.guionai-web__tool-body {
display: grid;
gap: 8px;
Expand Down
47 changes: 47 additions & 0 deletions packages/dsh-web/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ export function apply(ctx: ClientContext): void {
{
name: "tool.call.toolview",
key,
...(key === "web_fetch" ? { priority: -1 } : {}),
inject: () => ({}),
} as never,
((props: ToolCallViewProps) =>
Expand Down Expand Up @@ -358,6 +359,7 @@ function WebResearchToolCard({
? "Find documentation"
: "Fetch documentation";
const summary = toolSummary(name, args);
const details = name === "web_fetch" ? fetchDetails(args) : [];

return createElement(
"section",
Expand All @@ -383,6 +385,20 @@ function WebResearchToolCard({
summary
? createElement("p", { className: "guionai-web__tool-summary" }, summary)
: null,
details.length > 0
? createElement(
"dl",
{ className: "guionai-web__tool-details" },
...details.map((detail) =>
createElement(
"div",
{ key: detail.label },
createElement("dt", null, detail.label),
createElement("dd", null, detail.value),
),
),
)
: null,
running
? null
: error
Expand Down Expand Up @@ -539,6 +555,37 @@ function toolSummary(
}
}

export function fetchDetails(
args: Record<string, unknown>,
): Array<{ label: string; value: string }> {
const browserRendered = args.render === "agent-browser";
const details = [
{
label: "Backend",
value: browserRendered ? "Browser rendered" : "Direct fetch",
},
];
if (browserRendered && typeof args.waitMs === "number") {
details.push({ label: "Wait", value: formatWait(args.waitMs) });
}
details.push({ label: "Result", value: fetchResultMode(args) });
return details;
}

function formatWait(waitMs: number): string {
return waitMs >= 1_000 && waitMs % 1_000 === 0
? `${waitMs / 1_000} s`
: `${waitMs} ms`;
}

function fetchResultMode(args: Record<string, unknown>): string {
if (typeof args.section_id === "string" && args.section_id !== "")
return `Section: ${args.section_id}`;
if (args.tree === true) return "Heading tree";
if (args.full === true) return "Full document";
return "Adaptive document";
}

function excerpt(output: string): string {
const compact = output.replace(/\s+/g, " ").trim();
return compact.length <= 360 ? compact : `${compact.slice(0, 357)}…`;
Expand Down
53 changes: 45 additions & 8 deletions packages/dsh-web/test/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
apply,
decodeSettings,
describeCredentialStatus,
fetchDetails,
persistProviderSelection,
removeCredential,
writeCredential,
Expand Down Expand Up @@ -50,8 +51,32 @@ function fakeApi(overrides: Record<string, unknown> = {}) {
}

describe("DSH settings client credential surface", () => {
it("registers dedicated views for fetch, links, and docs without replacing search views", () => {
const registrations: Array<{ key: string }> = [];
it("labels the fetch backend, wait, and retrieval mode from its request", () => {
expect(
fetchDetails({
render: "agent-browser",
waitMs: 2_000,
section_id: "installation",
}),
).toEqual([
{ label: "Backend", value: "Browser rendered" },
{ label: "Wait", value: "2 s" },
{ label: "Result", value: "Section: installation" },
]);
expect(fetchDetails({ tree: true })).toEqual([
{ label: "Backend", value: "Direct fetch" },
{ label: "Result", value: "Heading tree" },
]);
expect(fetchDetails({ full: true })).toEqual([
{ label: "Backend", value: "Direct fetch" },
{ label: "Result", value: "Full document" },
]);
});

it("shadows the host fetch view and registers dedicated views for links and docs", () => {
const registrations: Array<{ key: string; priority?: number }> = [
{ key: "web_fetch", priority: 0 },
];
const ctx = {
effect: () => undefined,
get: () => ({ api: {} }),
Expand All @@ -68,18 +93,30 @@ describe("DSH settings client credential surface", () => {
// Exhaust the generator so every keyed registration is observed.
}
},
register: (spec: { key: string }) => {
register: (spec: { key: string; priority?: number }) => {
if (
registrations.some(
(registration) =>
registration.key === spec.key &&
(registration.priority ?? 0) === (spec.priority ?? 0),
)
) {
throw new Error(`duplicate keyed slot entry: ${spec.key}`);
}
registrations.push(spec);
return spec;
},
},
};
apply(ctx as any);
expect(registrations.map((registration) => registration.key)).toEqual([
SETTINGS_NAMESPACE,
"web_fetch",
"web_links",
"web_docs",
expect(
registrations.map(({ key, priority }) => ({ key, priority })),
).toEqual([
{ key: "web_fetch", priority: 0 },
{ key: SETTINGS_NAMESPACE },
{ key: "web_fetch", priority: -1 },
{ key: "web_links" },
{ key: "web_docs" },
]);
});

Expand Down
Loading