Skip to content

Commit de68623

Browse files
committed
docs: document sdk runtime helper contracts
1 parent 848f39e commit de68623

5 files changed

Lines changed: 41 additions & 0 deletions

File tree

src/plugin-sdk/file-lock.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import { shouldRemoveDeadOwnerOrExpiredLock } from "../infra/stale-lock-file.js";
99
import { getProcessStartTime } from "../shared/pid-alive.js";
1010

11+
/** Retry and stale-recovery policy for acquiring a filesystem lock. */
1112
export type FileLockOptions = {
1213
/** Retry policy used while waiting for another process or re-entrant holder to release. */
1314
retries: {
@@ -21,23 +22,28 @@ export type FileLockOptions = {
2122
stale: number;
2223
};
2324

25+
/** Live file-lock handle returned after successful acquisition. */
2426
export type FileLockHandle = {
2527
/** Absolute path to the `.lock` sidecar held for this file path. */
2628
lockPath: string;
2729
/** Releases one held reference; callers must await it before assuming peers can proceed. */
2830
release: () => Promise<void>;
2931
};
3032

33+
/** Stable error code used when lock acquisition retries are exhausted. */
3134
export const FILE_LOCK_TIMEOUT_ERROR_CODE = "file_lock_timeout";
35+
/** Stable error code used when stale lock recovery cannot proceed safely. */
3236
export const FILE_LOCK_STALE_ERROR_CODE = "file_lock_stale";
3337

38+
/** Typed error thrown when a lock cannot be acquired before timeout. */
3439
export type FileLockTimeoutError = Error & {
3540
/** Stable error discriminator for lock acquisition timeout handling. */
3641
code: typeof FILE_LOCK_TIMEOUT_ERROR_CODE;
3742
/** Lock sidecar path that could not be acquired before retries were exhausted. */
3843
lockPath: string;
3944
};
4045

46+
/** Typed error thrown when a stale lock sidecar cannot be reclaimed safely. */
4147
export type FileLockStaleError = Error & {
4248
/** Stable error discriminator for stale-lock reclaim failures. */
4349
code: typeof FILE_LOCK_STALE_ERROR_CODE;
@@ -76,10 +82,12 @@ function normalizeLockError(err: unknown): never {
7682
throw err;
7783
}
7884

85+
/** Reset process-local file-lock state for tests that isolate lock managers. */
7986
export function resetFileLockStateForTest(): void {
8087
resetFileLockManagerForTest(FILE_LOCK_MANAGER_KEY, FILE_LOCK_MANAGER_KEY);
8188
}
8289

90+
/** Wait for process-local file-lock state to drain before test teardown. */
8391
export async function drainFileLockStateForTest(): Promise<void> {
8492
await drainFileLockManagerForTest(FILE_LOCK_MANAGER_KEY, FILE_LOCK_MANAGER_KEY);
8593
}

src/plugin-sdk/gateway-method-runtime.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { dispatchGatewayMethodInProcessRaw } from "../gateway/server-plugins.js";
33
import { getPluginRuntimeGatewayRequestScope } from "../plugins/runtime/gateway-request-scope.js";
44

5+
/** Error envelope returned by in-process Gateway method dispatch. */
56
export type GatewayMethodDispatchError = {
67
/** Stable machine-readable error code returned by the Gateway method. */
78
code: string;
@@ -15,6 +16,7 @@ export type GatewayMethodDispatchError = {
1516
retryAfterMs?: number;
1617
};
1718

19+
/** Response envelope returned to plugins after dispatching a Gateway method. */
1820
export type GatewayMethodDispatchResponse = {
1921
/** True when the Gateway method completed and `payload` contains its result. */
2022
ok: boolean;
@@ -26,6 +28,7 @@ export type GatewayMethodDispatchResponse = {
2628
meta?: Record<string, unknown>;
2729
};
2830

31+
/** Dispatch controls for plugin-initiated Gateway method calls. */
2932
export type GatewayMethodDispatchOptions = {
3033
/** Wait for the Gateway's final response instead of returning the first response frame. */
3134
expectFinal?: boolean;

src/plugin-sdk/provider-selection-runtime.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
// Provider selection runtime helpers resolve plugin/provider choices from config and CLI input.
22
import { normalizeOptionalString } from "../../packages/normalization-core/src/string-coerce.js";
33

4+
/** Provider descriptor fields needed for explicit or automatic selection. */
45
export type AutoSelectableProvider = {
56
/** Provider id used for explicit config lookup and selected result metadata. */
67
id: string;
78
/** Lower values win when no explicit provider is configured. */
89
autoSelectOrder?: number;
910
};
1011

12+
/** Provider selection result before capability-specific configuration checks run. */
1113
export type ProviderSelection<TProvider> = {
1214
/** Normalized explicit provider id, when the caller supplied one. */
1315
configuredProviderId?: string;
@@ -17,6 +19,7 @@ export type ProviderSelection<TProvider> = {
1719
provider: TProvider | undefined;
1820
};
1921

22+
/** Final provider resolution result including capability-specific config. */
2023
export type ResolvedConfiguredProvider<TProvider, TConfig> =
2124
| {
2225
/** Provider exists and passed the capability-specific configuration check. */
@@ -39,6 +42,7 @@ export type ResolvedConfiguredProvider<TProvider, TConfig> =
3942
provider?: TProvider;
4043
};
4144

45+
/** Select an explicit provider when configured, otherwise the lowest-order auto provider. */
4246
export function selectConfiguredOrAutoProvider<TProvider extends AutoSelectableProvider>(params: {
4347
/** Optional explicit provider id from config or user input. */
4448
configuredProviderId?: string;
@@ -67,6 +71,7 @@ export function selectConfiguredOrAutoProvider<TProvider extends AutoSelectableP
6771
};
6872
}
6973

74+
/** Merge canonical provider config with selected-provider override config. */
7075
export function resolveProviderRawConfig(params: {
7176
/** Canonical provider id whose default config should be read first. */
7277
providerId: string;
@@ -87,6 +92,7 @@ export function resolveProviderRawConfig(params: {
8792
};
8893
}
8994

95+
/** Resolve a configured or auto-selected provider that passes capability config checks. */
9096
export function resolveConfiguredCapabilityProvider<
9197
TConfig,
9298
TFullConfig,

src/plugin-sdk/provider-stream-shared.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ import { streamSimple } from "../llm/stream.js";
1515
import { createAssistantMessageEventStream } from "../llm/utils/event-stream.js";
1616
import type { ProviderWrapStreamFnContext } from "./plugin-entry.js";
1717

18+
/** Optional provider stream decorator factory used by shared provider wrappers. */
1819
export type ProviderStreamWrapperFactory =
1920
/** Wrapper factory that can decorate, replace, or omit a provider stream function. */
2021
((streamFn: StreamFn | undefined) => StreamFn | undefined) | null | undefined | false;
2122

23+
/** Compose stream wrapper factories from left to right around a base stream function. */
2224
export function composeProviderStreamWrappers(
2325
/** Base provider stream function to pass through the wrapper chain. */
2426
baseStreamFn: StreamFn | undefined,
@@ -235,6 +237,7 @@ export function defaultToolStreamExtraParams(
235237
};
236238
}
237239

240+
/** Wrap a provider stream so callers can patch the outbound provider payload once. */
238241
export function createPayloadPatchStreamWrapper(
239242
/** Provider stream function whose outbound payload should be patched. */
240243
baseStreamFn: StreamFn | undefined,

src/plugin-sdk/qa-channel-protocol.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
// QA channel protocol helpers validate synthetic channel messages used by QA plugins.
22
import { isRecord } from "../../packages/normalization-core/src/record-coerce.js";
33

4+
/** Conversation shape supported by the synthetic QA channel bus. */
45
export type QaBusConversationKind = "direct" | "channel" | "group";
56

7+
/** Addressable conversation used by QA bus messages and thread state. */
68
export type QaBusConversation = {
79
id: string;
810
kind: QaBusConversationKind;
911
title?: string;
1012
};
1113

14+
/** Media/file attachment fixture accepted by QA bus message APIs. */
1215
export type QaBusAttachment = {
1316
id: string;
1417
kind: "image" | "video" | "audio" | "file";
@@ -24,11 +27,13 @@ export type QaBusAttachment = {
2427
transcript?: string;
2528
};
2629

30+
/** Tool-call fixture attached to QA messages for agent-runtime tests. */
2731
export type QaBusToolCall = {
2832
name: string;
2933
arguments?: Record<string, unknown>;
3034
};
3135

36+
/** Stored QA bus message after defaults, reactions, and account ids are normalized. */
3237
export type QaBusMessage = {
3338
id: string;
3439
accountId: string;
@@ -52,6 +57,7 @@ export type QaBusMessage = {
5257
}>;
5358
};
5459

60+
/** Synthetic thread record created inside a QA bus conversation. */
5561
export type QaBusThread = {
5662
id: string;
5763
accountId: string;
@@ -61,6 +67,7 @@ export type QaBusThread = {
6167
createdBy: string;
6268
};
6369

70+
/** Ordered event emitted by QA bus polling and state snapshots. */
6471
export type QaBusEvent =
6572
| { cursor: number; kind: "inbound-message"; accountId: string; message: QaBusMessage }
6673
| { cursor: number; kind: "outbound-message"; accountId: string; message: QaBusMessage }
@@ -76,6 +83,7 @@ export type QaBusEvent =
7683
senderId: string;
7784
};
7885

86+
/** Input for injecting an inbound message from a synthetic user/channel. */
7987
export type QaBusInboundMessageInput = {
8088
accountId?: string;
8189
conversation: QaBusConversation;
@@ -90,6 +98,7 @@ export type QaBusInboundMessageInput = {
9098
toolCalls?: QaBusToolCall[];
9199
};
92100

101+
/** Input for recording an outbound message sent by an OpenClaw runtime. */
93102
export type QaBusOutboundMessageInput = {
94103
accountId?: string;
95104
to: string;
@@ -103,6 +112,7 @@ export type QaBusOutboundMessageInput = {
103112
toolCalls?: QaBusToolCall[];
104113
};
105114

115+
/** Input for creating a synthetic QA bus thread. */
106116
export type QaBusCreateThreadInput = {
107117
accountId?: string;
108118
conversationId: string;
@@ -111,6 +121,7 @@ export type QaBusCreateThreadInput = {
111121
timestamp?: number;
112122
};
113123

124+
/** Input for adding a reaction event to an existing QA bus message. */
114125
export type QaBusReactToMessageInput = {
115126
accountId?: string;
116127
messageId: string;
@@ -119,19 +130,22 @@ export type QaBusReactToMessageInput = {
119130
timestamp?: number;
120131
};
121132

133+
/** Input for editing an existing QA bus message. */
122134
export type QaBusEditMessageInput = {
123135
accountId?: string;
124136
messageId: string;
125137
text: string;
126138
timestamp?: number;
127139
};
128140

141+
/** Input for marking an existing QA bus message as deleted. */
129142
export type QaBusDeleteMessageInput = {
130143
accountId?: string;
131144
messageId: string;
132145
timestamp?: number;
133146
};
134147

148+
/** Search filter accepted by QA bus message lookup helpers. */
135149
export type QaBusSearchMessagesInput = {
136150
accountId?: string;
137151
query?: string;
@@ -140,23 +154,27 @@ export type QaBusSearchMessagesInput = {
140154
limit?: number;
141155
};
142156

157+
/** Lookup key for reading one QA bus message. */
143158
export type QaBusReadMessageInput = {
144159
accountId?: string;
145160
messageId: string;
146161
};
147162

163+
/** Cursor and timeout options used by QA bus polling. */
148164
export type QaBusPollInput = {
149165
accountId?: string;
150166
cursor?: number;
151167
timeoutMs?: number;
152168
limit?: number;
153169
};
154170

171+
/** Poll response containing the next cursor and ordered events. */
155172
export type QaBusPollResult = {
156173
cursor: number;
157174
events: QaBusEvent[];
158175
};
159176

177+
/** Complete QA bus state snapshot exposed to tests and diagnostics. */
160178
export type QaBusStateSnapshot = {
161179
cursor: number;
162180
conversations: QaBusConversation[];
@@ -212,6 +230,7 @@ function sanitizeQaBusToolCallValue(value: unknown, depth: number, key?: string)
212230
return undefined;
213231
}
214232

233+
/** Sanitize arbitrary tool-call arguments before storing them in QA bus messages. */
215234
export function sanitizeQaBusToolCallArguments(
216235
value: unknown,
217236
): Record<string, unknown> | undefined {
@@ -222,6 +241,7 @@ export function sanitizeQaBusToolCallArguments(
222241
return isRecord(sanitized) ? sanitized : undefined;
223242
}
224243

244+
/** Normalize and redact a bounded list of tool calls from untrusted QA input. */
225245
export function sanitizeQaBusToolCalls(value: unknown): QaBusToolCall[] | undefined {
226246
if (!Array.isArray(value)) {
227247
return undefined;
@@ -245,6 +265,7 @@ export function sanitizeQaBusToolCalls(value: unknown): QaBusToolCall[] | undefi
245265
return sanitized.length > 0 ? sanitized : undefined;
246266
}
247267

268+
/** Predicate input used by QA helpers that wait for bus events or messages. */
248269
export type QaBusWaitForInput =
249270
| {
250271
timeoutMs?: number;

0 commit comments

Comments
 (0)