forked from pingdotgg/t3code
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProviderAdapterRegistry.ts
More file actions
100 lines (91 loc) · 4.2 KB
/
Copy pathProviderAdapterRegistry.ts
File metadata and controls
100 lines (91 loc) · 4.2 KB
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* ProviderAdapterRegistry - Lookup boundary for provider adapter implementations.
*
* Maps a `ProviderInstanceId` (the new per-instance routing key) or a
* `ProviderDriverKind` (legacy single-instance-per-driver key) to the concrete
* adapter service (Codex, Claude, etc). It does not own session lifecycle
* or routing rules; `ProviderService` uses this registry together with
* `ProviderSessionDirectory`.
*
* During the driver/instance migration this tag exposes both flavours:
*
* - `getByInstance` / `listInstances` — new per-instance routing. Callers
* that already know an `instanceId` (threads, sessions, events)
* should prefer these.
* (`defaultInstanceIdForDriver(kind) === kind`), matching the pre-Slice-D
* behaviour. New code should not grow additional callers of the kind-keyed
* methods; they exist so the settings UI, WS refresh RPC, and a handful
* of legacy persisted rows can still be routed during the rollout.
*
* @module ProviderAdapterRegistry
*/
import type { ProviderDriverKind, ProviderInstanceId } from "@t3tools/contracts";
import * as Context from "effect/Context";
import type * as Effect from "effect/Effect";
import type * as PubSub from "effect/PubSub";
import type * as Scope from "effect/Scope";
import type * as Stream from "effect/Stream";
import type { ProviderAdapterError, ProviderUnsupportedError } from "../Errors.ts";
import type { ProviderAdapterShape } from "./ProviderAdapter.ts";
import type { ProviderContinuationIdentity } from "../ProviderDriver.ts";
export interface ProviderInstanceRoutingInfo {
readonly instanceId: ProviderInstanceId;
readonly driverKind: ProviderDriverKind;
readonly displayName: string | undefined;
readonly accentColor?: string | undefined;
readonly enabled: boolean;
readonly continuationIdentity: ProviderContinuationIdentity;
}
/**
* ProviderAdapterRegistryShape - Service API for adapter lookup.
*/
export interface ProviderAdapterRegistryShape {
/**
* Resolve the adapter for a specific instance id. Returns
* `ProviderUnsupportedError` if no such instance is currently registered
* (which covers "never configured" *and* "configured but the driver is
* unavailable in this build" — both surface the same failure to callers
* that expect a working adapter).
*/
readonly getByInstance: (
instanceId: ProviderInstanceId,
) => Effect.Effect<ProviderAdapterShape<ProviderAdapterError>, ProviderUnsupportedError>;
readonly getInstanceInfo: (
instanceId: ProviderInstanceId,
) => Effect.Effect<ProviderInstanceRoutingInfo, ProviderUnsupportedError>;
/**
* List all live instance ids. Excludes unavailable/shadow instances —
* callers of this method want something they can pass to `getByInstance`.
*/
readonly listInstances: () => Effect.Effect<ReadonlyArray<ProviderInstanceId>>;
/**
* Legacy: list provider kinds whose default instance is currently
* registered.
*
* @deprecated Prefer `listInstances`. Retained for migration-era call
* sites that iterate providers to build UI/metrics.
*/
readonly listProviders: () => Effect.Effect<ReadonlyArray<ProviderDriverKind>>;
/**
* Change notification stream mirroring `ProviderInstanceRegistry.streamChanges`.
* Emits one `void` tick whenever the set of live instances changes
* (instance added, removed, or rebuilt after a settings edit). Consumers
* that fan out `adapter.streamEvents` per instance — e.g. `ProviderService`'s
* runtime event bus — re-pull `listInstances` on each tick and fork new
* subscriptions for instances they haven't seen yet.
*/
readonly streamChanges: Stream.Stream<void>;
/**
* Acquire a change subscription synchronously in the caller's current fiber.
* Consumers that must avoid missing a publish between initial reconciliation
* and watcher startup should use this, then fork `Stream.fromSubscription`.
*/
readonly subscribeChanges: Effect.Effect<PubSub.Subscription<void>, never, Scope.Scope>;
}
/**
* ProviderAdapterRegistry - Service tag for provider adapter lookup.
*/
export class ProviderAdapterRegistry extends Context.Service<
ProviderAdapterRegistry,
ProviderAdapterRegistryShape
>()("t3/provider/Services/ProviderAdapterRegistry") {}