52
return true;
53
}
55
>
/**
56
>
* A per-session registry of the tools contributed by each active client,
57
>
* keyed by `clientId` and kept in insertion order. Backs the multi-active-client
58
>
* tool model shared by the agent-host providers (Copilot, Claude, Codex):
59
>
* each provider stores one of these per session and exposes the
60
>
* {@link merged} view to its SDK while routing tool calls back to the
61
>
* {@link ownerOf | owning client}.
62
>
*
63
>
* Deduplication of {@link merged} is by tool `name`, first-inserted-client
64
>
* wins, so the merged order and the owner of any given tool name are
65
>
* deterministic regardless of how many clients contribute it.
66
>
*/
67
>
export class ActiveClientToolSet {
68
private readonly _byClient = new Map<string, readonly ToolDefinition[]>();
70
>
/** Number of clients currently contributing tools. */
71
>
get size(): number {
72
return this._byClient.size;
73
}
75
>
/** Whether `clientId` currently contributes tools. */
76
>
has(clientId: string): boolean {
77
return this._byClient.has(clientId);
78
}
80
>
/** The client ids currently contributing tools, in insertion order. */
81
>
clientIds(): IterableIterator<string> {
82
return this._byClient.keys();
83
}
85
>
/** This client's contributed tools, or an empty array when absent. */
86
>
get(clientId: string): readonly ToolDefinition[] {
87
return this._byClient.get(clientId) ?? [];
88
}
90
>
/**
91
>
* Replace `clientId`'s contributed tools (full replacement). A new
92
>
* `clientId` is appended after existing ones; re-setting an existing
93
>
* `clientId` keeps its insertion position so merged ordering and tool
94
>
* ownership stay stable across updates.
95
>
*/
96
>
set(clientId: string, tools: readonly ToolDefinition[]): void {
97
this._byClient.set(clientId, tools);
98
}
100
>
/** Remove `clientId`'s contribution. Returns whether anything was removed. */
101
>
delete(clientId: string): boolean {
102
return this._byClient.delete(clientId);
103
}
105
>
/**
106
>
* The union of every client's tools, deduplicated by `name` with the
107
>
* first-inserted contributor winning. Order follows client insertion
108
>
* order, then per-client tool order.
109
>
*/
110
>
merged(): readonly ToolDefinition[] {
111
const seen = new Set<string>();
112
const result: ToolDefinition[] = [];