@cortexkit/aft-bridge 0.42.0 → 0.43.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Subconscious (subc) transport — the daemon-backed alternative to the standalone
3
+ * NDJSON {@link BinaryBridge}. Implements the SAME {@link AftProjectTransport} /
4
+ * {@link AftTransportPool} interfaces the plugins consume, so the entire tool /
5
+ * hoisting / permission / UI surface stays transport-agnostic: only the ONE
6
+ * construction site (BridgePool vs SubcTransportPool) differs.
7
+ *
8
+ * Standalone model: one `aft` child process per project root, session passed
9
+ * per call. Subc model: ONE {@link SubcClient} per process (one authenticated
10
+ * daemon connection), and a route opened+cached per `(project_root, harness,
11
+ * session)` triple — exactly subc's {@link BindIdentity}. So the "pool" here is a
12
+ * route cache over a single client, not N child processes.
13
+ *
14
+ * This module is S2 of B-FINAL: the tool-call route only. The bg_events idle-wake
15
+ * subscription (S3) and the config gate that selects this transport (S4) build on
16
+ * top of it. subc-client is a build-time path dependency bundled into the
17
+ * published plugin dist; it is never a published runtime dependency.
18
+ */
19
+ import { type BindIdentity, type RequestOptions, type RouteTarget } from "@cortexkit/subc-client";
20
+ import type { StatusSnapshot } from "./bridge.js";
21
+ import { type StatusBarCounts } from "./status-bar.js";
22
+ import type { AftProjectTransport, AftTransportOptions, AftTransportPool, ToolCallArguments, ToolCallOptions, ToolCallResult } from "./transport.js";
23
+ /** A held-open event subscription — the slice of subc-client's Subscription we use. */
24
+ export interface SubcSubscriptionLike {
25
+ /** Cancel the subscription (sends Cancel; idempotent); the provider unwinds with StreamEnd. */
26
+ unsubscribe(): void;
27
+ /** Resolves on StreamEnd (intentional close); REJECTS on Error / route GOODBYE / socket drop. */
28
+ readonly closed: Promise<void>;
29
+ }
30
+ /**
31
+ * The minimal slice of {@link SubcClient} this transport depends on. Declared
32
+ * structurally so a test can inject a fake client through the pool's `connect`
33
+ * seam without standing up a daemon; the real `SubcClient` satisfies it.
34
+ */
35
+ export interface SubcClientLike {
36
+ routeOpen(target: RouteTarget, identity: BindIdentity): Promise<number>;
37
+ request(routeChannel: number, body: unknown, opts?: RequestOptions): Promise<unknown>;
38
+ subscribe(routeChannel: number, body: unknown, onEvent: (event: Uint8Array) => void): SubcSubscriptionLike;
39
+ closeRouteChannel(channel: number, opts?: {
40
+ drain?: boolean;
41
+ }): Promise<void>;
42
+ close(): void;
43
+ }
44
+ export interface SubcTransportPoolOptions {
45
+ /** Absolute path to the subc connection file (user-tier `subc.connection_file`). */
46
+ connectionFile: string;
47
+ /** Harness identity carried in every BindIdentity ("opencode" | "pi" | …). */
48
+ harness: string;
49
+ /** Handshake timeout forwarded to SubcClient.connect. */
50
+ handshakeTimeoutMs?: number;
51
+ /**
52
+ * Connection factory seam. Defaults to the real `SubcClient.connect`. Tests
53
+ * inject a fake to exercise route caching / Rd reconnect without a daemon.
54
+ */
55
+ connect?: (opts: {
56
+ connectionFile: string;
57
+ handshakeTimeoutMs?: number;
58
+ }) => Promise<SubcClientLike>;
59
+ /**
60
+ * Called when an idle bg-completion WAKE arrives for `(projectRoot, session)`
61
+ * (a `{op:"bg_events"}` StreamData nudge), AND immediately after each
62
+ * (re)subscribe (the durable-outbox replay trigger). The nudge carries NO
63
+ * payload — the handler MUST force a DRAIN (bash_drain_completions) to fetch
64
+ * the actual completions. When set, the transport opens a dedicated bg_events
65
+ * subscription per session and drives its reconnect independently of tool
66
+ * calls (so an idle agent whose socket drops is still resubscribed + drained).
67
+ * Absent ⇒ no bg subscriptions are opened.
68
+ */
69
+ onBgEventsNudge?: (projectRoot: string, session: string) => void;
70
+ /** Test seam: backoff sleeper for the bg resubscribe loop (default real timer). */
71
+ bgBackoffSleep?: (ms: number) => Promise<void>;
72
+ }
73
+ /**
74
+ * One project root's view onto the shared subc client. Holds per-root status
75
+ * caches (mirroring BinaryBridge) and routes every call through the pool's single
76
+ * client, opening+caching a route per `(root, harness, session)`.
77
+ */
78
+ declare class SubcTransport implements AftProjectTransport {
79
+ private readonly pool;
80
+ private readonly projectRoot;
81
+ private lastStatusBar;
82
+ private cachedStatus;
83
+ constructor(pool: SubcTransportPool, projectRoot: string);
84
+ getCwd(): string;
85
+ getStatusBar(): StatusBarCounts | undefined;
86
+ getCachedStatus(): StatusSnapshot | null;
87
+ cacheStatusSnapshot(snapshot: StatusSnapshot): void;
88
+ private captureStatusBar;
89
+ private identityFor;
90
+ toolCall(sessionId: string | undefined, name: string, rawArgs?: ToolCallArguments, options?: ToolCallOptions): Promise<ToolCallResult>;
91
+ /**
92
+ * Lifecycle / native-command path. Over subc there is no separate "native
93
+ * command" channel — every command rides the tool_provider route as a
94
+ * `{name, arguments}` Request and the module's gate decides validity (the 21
95
+ * core tools plus the `bash_drain_completions` / `bash_ack_completions` plumbing
96
+ * allowlist). The bind session is taken from `params.session_id` so a
97
+ * session-scoped command (drain/ack) reaches the matching route — the module
98
+ * re-injects the BIND session over any body session, so the route identity is
99
+ * what scopes it. `configure` is satisfied locally (binding is the configure).
100
+ */
101
+ send(command: string, params?: Record<string, unknown>, options?: AftTransportOptions): Promise<Record<string, unknown>>;
102
+ private splitOptions;
103
+ }
104
+ /**
105
+ * Route cache over one authenticated subc client. Implements {@link AftTransportPool}
106
+ * so it drops into the plugin in place of {@link BridgePool} behind the shared
107
+ * interface. One client per process; routes keyed by `(root, harness, session)`.
108
+ */
109
+ export declare class SubcTransportPool implements AftTransportPool {
110
+ readonly harness: string;
111
+ private readonly connectionFile;
112
+ private readonly handshakeTimeoutMs?;
113
+ private readonly connectFn;
114
+ private readonly onBgEventsNudge?;
115
+ private readonly bgBackoffSleep;
116
+ private client;
117
+ /** Single-flight guard so concurrent first calls share one connect. */
118
+ private connecting;
119
+ /** Per-session lifecycle records keyed by a string built from root, harness, and session. */
120
+ private readonly sessions;
121
+ /**
122
+ * Consecutive NON-transient transport throws on the current client with no
123
+ * success in between. Resets to 0 on any successful request. Trips a client drop
124
+ * at {@link MAX_CONSECUTIVE_TRANSPORT_FAILURES} to recover a half-open socket
125
+ * whose timeouts never classify transient (B-#4).
126
+ */
127
+ private transportFailures;
128
+ /** Per-root transport facades returned by getBridge/getActiveBridgeForRoot. */
129
+ private readonly transports;
130
+ private shuttingDown;
131
+ constructor(options: SubcTransportPoolOptions);
132
+ /**
133
+ * Fail-loud presence check (memory: present-but-unconnectable must never silently
134
+ * downgrade to standalone). Returns false only when the file is genuinely absent.
135
+ */
136
+ static connectionAvailable(connectionFile: string): Promise<boolean>;
137
+ getBridge(projectRoot: string): SubcTransport;
138
+ getActiveBridgeForRoot(projectRoot: string): SubcTransport | null;
139
+ toolCall(projectRoot: string, runtime: {
140
+ sessionID?: string;
141
+ }, name: string, rawArgs?: ToolCallArguments, options?: ToolCallOptions): Promise<ToolCallResult>;
142
+ private getOrCreateSession;
143
+ private isCurrentSession;
144
+ private deleteSessionIfEmpty;
145
+ /**
146
+ * Open-or-reuse a route for `identity` and send `body` as a data-plane Request.
147
+ * Rd reconnect (mutation-safe by construction — NEVER auto-retries): on a
148
+ * transport-level {@link SubcCallError} the cached channel is discarded and the
149
+ * dead client cleared so the NEXT call re-establishes, but the failed call is
150
+ * surfaced to the agent unchanged (identical to a standalone bridge death). Only
151
+ * `SubcClient.request` transport failures throw here; a tool-level error comes
152
+ * back as a normal reply with `success:false` and is returned, not thrown.
153
+ */
154
+ routeRequest(identity: BindIdentity, body: Record<string, unknown>, timeoutMs?: number, onProgress?: RequestOptions["onProgress"]): Promise<unknown>;
155
+ private ensureClient;
156
+ /**
157
+ * Resolve the route channel for `identity`, returning BOTH the channel and the
158
+ * `RouteEntry` token that owns it. The route-entry token is the route-cache
159
+ * ownership guard: stale request failures can clear only the route they used,
160
+ * never a successor route in the same still-open session.
161
+ */
162
+ private routeChannel;
163
+ /**
164
+ * Open the dedicated bg_events subscription for `identity` once. Idempotent —
165
+ * a second call for the same identity is a no-op (one sub per session, the
166
+ * duplicate-sub guard from Oracle #2). No-op when no nudge handler is wired,
167
+ * during shutdown, or after the session has been closed.
168
+ */
169
+ private ensureBgSubscription;
170
+ /** Drop a dead client so the next call reconnects; preserves session records. */
171
+ private dropClient;
172
+ /** No-op over subc: config is read locally by AFT (wire tiers are ignored). */
173
+ setConfigureOverride(_key: string, _value: unknown): void;
174
+ /** No-op over subc: the daemon supervises the binary, not the plugin. */
175
+ replaceBinary(path: string): Promise<string>;
176
+ shutdown(): Promise<void>;
177
+ /**
178
+ * Tear down a single session's bg subscription (and tool route) — the
179
+ * per-session close hook (Oracle #5). Idempotent. Wired to OpenCode session-end
180
+ * / Pi equivalent in S4; until then, shutdown() covers teardown.
181
+ */
182
+ closeSession(projectRoot: string, session: string): Promise<void>;
183
+ }
184
+ export {};
185
+ //# sourceMappingURL=subc-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subc-transport.d.ts","sourceRoot":"","sources":["../src/subc-transport.ts"],"names":[],"mappings":"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"}