34
);
35
readonly merged: IObservable<readonly ToolDefinition[]> = this._merged;
37
>
/** Replace `clientId`'s contributed tools (full replacement). */
38
>
setTools(clientId: string, tools: readonly ToolDefinition[]): void {
39
this._toolSet.set(clientId, tools);
40
this._merged.set(this._toolSet.merged(), undefined);
41
}
43
>
/** This client's contributed tools (empty when absent). */
44
>
getTools(clientId: string): readonly ToolDefinition[] {
45
return this._toolSet.get(clientId);
46
}
48
>
/** Remove a client's tool contribution. */
49
>
removeClient(clientId: string): void {
50
if (this._toolSet.delete(clientId)) {
51
this._merged.set(this._toolSet.merged(), undefined);
52
}
53
}
55
>
/** The `clientId` that owns the tool named `toolName`, or `undefined`. */
56
>
ownerOf(toolName: string, preferredClientId?: string): string | undefined {
57
return this._toolSet.ownerOf(toolName, preferredClientId);
58
}
60
>
61
>
/**
62
>
* Tracks "has {@link SessionClientToolsModel.merged} changed since the
63
>
* last successful {@link consume}?". Subscribes to the model's observable
64
>
* and flips a private dirty bit on every change; {@link consume} captures
65
>
* the current merged snapshot and clears the bit — preserving the C6 pin
66
>
* invariant from the previous `ClientToolDiff` implementation: a `setTools`
67
>
* call that races the in-flight builder re-flips the bit via the autorun, so
68
>
* the next sendMessage detects the stale set and triggers another rebind.
69
>
*
70
>
* On builder throw the bit is left set — the SDK is still running with
71
>
* the previous snapshot, so the next sendMessage should retry.
72
>
*/
73
>
export class SessionClientToolsDiff extends Disposable {
74
>
75
>
readonly model: SessionClientToolsModel = new SessionClientToolsModel();
76
>
77
>
private _dirty = false;
78
>
// `autorun` invokes its callback once at registration for dependency
79
>
// tracking. Skip that initial run so a brand-new diff doesn't report
80
>
// dirty before any `setTools` has happened.
81
>
private _ignoreNextFire = true;
82
>
// Structural tool snapshot last marked applied (via {@link consume}).
83
>
private _lastAppliedTools: readonly ToolDefinition[] = [];
84
>
85
>
constructor() {
86
super();
87
this._register(autorun(reader => {