bopodev-agent-sdk 0.1.29 → 0.1.31

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.
@@ -1,5 +1,5 @@
1
1
 
2
2
  
3
- > bopodev-agent-sdk@0.1.29 build /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopodev/packages/agent-sdk
3
+ > bopodev-agent-sdk@0.1.31 build /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopohq/packages/agent-sdk
4
4
  > tsc -p tsconfig.json --emitDeclarationOnly
5
5
 
@@ -1,4 +1,4 @@
1
1
 
2
- > bopodev-agent-sdk@0.1.28 lint /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopodev/packages/agent-sdk
2
+ > bopodev-agent-sdk@0.1.15 lint /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopohq/packages/agent-sdk
3
3
  > tsc -p tsconfig.json --noEmit
4
4
 
@@ -1,4 +1,4 @@
1
1
 
2
- > bopodev-agent-sdk@0.1.20 typecheck /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopodev/packages/agent-sdk
2
+ > bopodev-agent-sdk@0.1.30 typecheck /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopohq/packages/agent-sdk
3
3
  > tsc -p tsconfig.json --noEmit
4
4
 
@@ -0,0 +1,2 @@
1
+ import type { AgentRuntimeConfig, AdapterQuotaProbeResult } from "../../../../agent-sdk/src/types";
2
+ export declare function probeQuota(runtime?: AgentRuntimeConfig): Promise<AdapterQuotaProbeResult>;
@@ -0,0 +1 @@
1
+ export declare function formatStdoutEvent(line: string, debug: boolean): void;
@@ -0,0 +1 @@
1
+ export { formatStdoutEvent } from "./format-event";
@@ -0,0 +1,7 @@
1
+ import type { AdapterMetadata, AdapterModule } from "../../../agent-sdk/src/types";
2
+ export declare const type: "openclaw_gateway";
3
+ export declare const label = "OpenClaw Gateway";
4
+ export declare const models: readonly [];
5
+ export declare const agentConfigurationDoc = "Use when:\n- You run a self-hosted [OpenClaw](https://docs.openclaw.ai/) gateway and want Bopo heartbeats to invoke `agent` / `agent.wait` over the documented WebSocket protocol.\n\nConfigure:\n- **Command**: WebSocket URL (e.g. `ws://127.0.0.1:18789`). Alternatively set `OPENCLAW_GATEWAY_URL` in runtime environment.\n- **Runtime environment**: `OPENCLAW_GATEWAY_TOKEN` or `OPENCLAW_GATEWAY_PASSWORD` (required). Optional: `OPENCLAW_AGENT_ID`, `OPENCLAW_SESSION_KEY`, `OPENCLAW_SESSION_KEY_STRATEGY` (`issue` | `run` | `fixed`), `OPENCLAW_AGENT_WAIT_MS`, `OPENCLAW_DEVICE_PRIVATE_KEY_PEM` (stable device identity), `BOPO_OPENCLAW_DISABLE_DEVICE_AUTH=1` only if your gateway explicitly allows insecure mode.\n\nDo not use when:\n- You need a local CLI subprocess adapter \u2014 use Codex, Claude Code, or OpenCode instead.";
6
+ export declare const metadata: AdapterMetadata;
7
+ export declare const openclawGatewayAdapterModule: AdapterModule;
@@ -0,0 +1,25 @@
1
+ export declare function publicKeyRawBase64UrlFromPem(publicKeyPem: string): string;
2
+ export declare function signDevicePayload(privateKeyPem: string, payload: string): string;
3
+ export type OpenClawDeviceIdentity = {
4
+ deviceId: string;
5
+ publicKeyPem: string;
6
+ privateKeyPem: string;
7
+ };
8
+ export declare function generateEphemeralDeviceIdentity(): OpenClawDeviceIdentity;
9
+ export declare function loadDeviceIdentityFromPrivateKeyPem(privateKeyPem: string): OpenClawDeviceIdentity;
10
+ /**
11
+ * OpenClaw gateway device signing payload (v3), compatible with gateway verification.
12
+ * @see https://docs.openclaw.ai/gateway/protocol
13
+ */
14
+ export declare function buildOpenClawDeviceAuthPayloadV3(params: {
15
+ deviceId: string;
16
+ clientId: string;
17
+ clientMode: string;
18
+ role: string;
19
+ scopes: string[];
20
+ signedAtMs: number;
21
+ token?: string | null;
22
+ nonce: string;
23
+ platform?: string | null;
24
+ deviceFamily?: string | null;
25
+ }): string;
@@ -0,0 +1,2 @@
1
+ import type { HeartbeatContext, AdapterExecutionResult } from "../../../../agent-sdk/src/types";
2
+ export declare function execute(context: HeartbeatContext): Promise<AdapterExecutionResult>;
@@ -0,0 +1,56 @@
1
+ import { type ParsedOpenClawSessionUsage } from "./parse";
2
+ export declare class GatewayResponseError extends Error {
3
+ readonly gatewayCode?: string;
4
+ readonly gatewayDetails?: unknown;
5
+ constructor(message: string, gatewayCode?: string, gatewayDetails?: unknown);
6
+ }
7
+ export type OpenClawGatewayRunOptions = {
8
+ gatewayUrl: string;
9
+ token?: string | null;
10
+ password?: string | null;
11
+ devicePrivateKeyPem?: string | null;
12
+ /** When true, omit `device` on `connect` (gateway must allow disabled device auth). */
13
+ disableDeviceAuth?: boolean;
14
+ agentId?: string | null;
15
+ /** For `sessionKeyStrategy: "fixed"` — OpenClaw session key string. */
16
+ openclawSessionKey?: string | null;
17
+ sessionKeyStrategy?: "issue" | "run" | "fixed";
18
+ primaryIssueId?: string | null;
19
+ /** OpenClaw `agent.timeout` (seconds). */
20
+ agentTimeoutSec?: number | null;
21
+ model?: string | null;
22
+ message: string;
23
+ idempotencyKey: string;
24
+ connectTimeoutMs: number;
25
+ agentWaitTimeoutMs: number;
26
+ onStdoutLine: (line: string) => void;
27
+ onTranscriptEvent?: (event: {
28
+ kind: "system" | "assistant" | "thinking" | "tool_call" | "tool_result" | "result" | "stderr";
29
+ label?: string;
30
+ text?: string;
31
+ payload?: string;
32
+ signalLevel?: "high" | "medium" | "low" | "noise";
33
+ groupKey?: string;
34
+ source?: "stdout" | "stderr";
35
+ }) => void;
36
+ abortSignal?: AbortSignal;
37
+ };
38
+ export type OpenClawGatewayRunResult = {
39
+ ok: boolean;
40
+ summary: string;
41
+ runId?: string;
42
+ timedOut?: boolean;
43
+ errorMessage?: string;
44
+ tokenInput: number;
45
+ tokenOutput: number;
46
+ /** Cache / context read tokens when reported by `sessions.usage`. */
47
+ cachedInputTokens: number;
48
+ usdCost: number;
49
+ model?: string | null;
50
+ /** Resolved OpenClaw runtime model provider (e.g. anthropic), when available. */
51
+ openclawModelProvider?: string | null;
52
+ provider?: string | null;
53
+ /** Where token/model/cost metadata came from, for traces. */
54
+ openclawUsageSource?: ParsedOpenClawSessionUsage["source"] | "none";
55
+ };
56
+ export declare function runOpenClawGatewayTurn(options: OpenClawGatewayRunOptions): Promise<OpenClawGatewayRunResult>;
@@ -0,0 +1,2 @@
1
+ export { execute } from "./execute";
2
+ export { testEnvironment } from "./test";
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Parse OpenClaw gateway JSON payloads for session usage (tokens, model, cost).
3
+ * Shapes follow `sessions.list` / `sessions.usage` responses on the gateway WebSocket API.
4
+ */
5
+ export type ParsedOpenClawSessionUsage = {
6
+ tokenInput: number;
7
+ tokenOutput: number;
8
+ cachedInputTokens: number;
9
+ usdCost: number;
10
+ model: string | null;
11
+ modelProvider: string | null;
12
+ source: "sessions.list" | "sessions.usage";
13
+ };
14
+ /** Match `GatewaySessionRow` from OpenClaw `sessions.list` (search + exact key). */
15
+ export declare function extractUsageFromSessionsList(payload: unknown, exactSessionKey: string): ParsedOpenClawSessionUsage | null;
16
+ /** Match `SessionUsageEntry` from OpenClaw `sessions.usage` when `key` is scoped. */
17
+ export declare function extractUsageFromSessionsUsage(payload: unknown, exactSessionKey: string): ParsedOpenClawSessionUsage | null;
18
+ /**
19
+ * Map OpenClaw session `modelProvider` strings to Bopo `pricingProviderType` when catalog pricing should apply.
20
+ * Returns `null` when unknown so heartbeat cost logic falls back to gateway-reported USD or `openclaw_gateway` defaults.
21
+ */
22
+ export declare function mapOpenClawModelProviderToBopoPricingType(openclawProvider: string | null | undefined): string | null;
@@ -0,0 +1,2 @@
1
+ import type { AdapterEnvironmentResult, AgentRuntimeConfig } from "../../../../agent-sdk/src/types";
2
+ export declare function testEnvironment(runtime?: AgentRuntimeConfig): Promise<AdapterEnvironmentResult>;
@@ -0,0 +1,3 @@
1
+ export declare function buildAdapterConfig(values: Record<string, unknown>): {
2
+ [x: string]: unknown;
3
+ };
@@ -0,0 +1,2 @@
1
+ export { parseStdoutLine } from "./parse-stdout";
2
+ export { buildAdapterConfig } from "./build-config";
@@ -0,0 +1,6 @@
1
+ export declare function parseStdoutLine(line: string, timestampIso: string): {
2
+ kind: string;
3
+ label: string;
4
+ text: string;
5
+ timestampIso: string;
6
+ }[];
@@ -1,7 +1,11 @@
1
1
  import type { AdapterMetadata, AdapterModule } from "../../../agent-sdk/src/types";
2
2
  export declare const type: "opencode";
3
3
  export declare const label = "OpenCode";
4
- export declare const models: readonly [];
4
+ /** Shown when `opencode models` is empty (e.g. CLI missing on the API host). Discovery merges on top of this. */
5
+ export declare const models: readonly [{
6
+ readonly id: "opencode/big-pickle";
7
+ readonly label: "Big Pickle";
8
+ }];
5
9
  export declare const agentConfigurationDoc = "Use when:\n- You need OpenCode CLI execution with provider/model selection.\n- You want OpenCode session reuse.\n\nDo not use when:\n- No runtime model is configured.\n- The host cannot run OpenCode CLI.";
6
10
  export declare const metadata: AdapterMetadata;
7
11
  export declare const opencodeAdapterModule: AdapterModule;
@@ -0,0 +1,4 @@
1
+ import type { AgentProviderType, AdapterQuotaProbeResult, AgentRuntimeConfig } from "./types";
2
+ export declare function createUnsupportedQuotaProbeResult(providerType: AgentProviderType, message: string): AdapterQuotaProbeResult;
3
+ export declare function createAuthRequiredQuotaProbeResult(providerType: AgentProviderType, message: string): AdapterQuotaProbeResult;
4
+ export declare function resolveMergedEnv(runtime?: AgentRuntimeConfig): NodeJS.ProcessEnv;
@@ -79,6 +79,15 @@ export interface HeartbeatContext {
79
79
  commentBody?: string | null;
80
80
  issueIds?: string[];
81
81
  };
82
+ /** Company agents (non-terminated), sorted by name; used for delegation and task routing hints. */
83
+ teamRoster?: Array<{
84
+ id: string;
85
+ name: string;
86
+ role: string;
87
+ title?: string | null;
88
+ capabilities?: string | null;
89
+ status: string;
90
+ }>;
82
91
  }
83
92
  /**
84
93
  * Normalized usage contract produced by adapter execution.
@@ -149,9 +149,190 @@ export declare const IssueSchema: z.ZodObject<{
149
149
  assigneeAgentId: z.ZodNullable<z.ZodString>;
150
150
  labels: z.ZodDefault<z.ZodArray<z.ZodString>>;
151
151
  tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
152
+ loopId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
153
+ loopRunId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
152
154
  createdAt: z.ZodString;
153
155
  updatedAt: z.ZodString;
154
156
  }, z.core.$strip>;
157
+ export declare const WorkLoopConcurrencyPolicySchema: z.ZodEnum<{
158
+ coalesce_if_active: "coalesce_if_active";
159
+ skip_if_active: "skip_if_active";
160
+ always_enqueue: "always_enqueue";
161
+ }>;
162
+ export declare const WorkLoopCatchUpPolicySchema: z.ZodEnum<{
163
+ skip_missed: "skip_missed";
164
+ enqueue_missed_with_cap: "enqueue_missed_with_cap";
165
+ }>;
166
+ export declare const WorkLoopStatusSchema: z.ZodEnum<{
167
+ active: "active";
168
+ paused: "paused";
169
+ archived: "archived";
170
+ }>;
171
+ export declare const WorkLoopSchema: z.ZodObject<{
172
+ id: z.ZodString;
173
+ companyId: z.ZodString;
174
+ projectId: z.ZodString;
175
+ parentIssueId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
176
+ goalIds: z.ZodDefault<z.ZodArray<z.ZodString>>;
177
+ title: z.ZodString;
178
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
179
+ assigneeAgentId: z.ZodString;
180
+ priority: z.ZodString;
181
+ status: z.ZodEnum<{
182
+ active: "active";
183
+ paused: "paused";
184
+ archived: "archived";
185
+ }>;
186
+ concurrencyPolicy: z.ZodEnum<{
187
+ coalesce_if_active: "coalesce_if_active";
188
+ skip_if_active: "skip_if_active";
189
+ always_enqueue: "always_enqueue";
190
+ }>;
191
+ catchUpPolicy: z.ZodEnum<{
192
+ skip_missed: "skip_missed";
193
+ enqueue_missed_with_cap: "enqueue_missed_with_cap";
194
+ }>;
195
+ lastTriggeredAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
196
+ createdAt: z.ZodString;
197
+ updatedAt: z.ZodString;
198
+ }, z.core.$strip>;
199
+ export declare const WorkLoopTriggerSchema: z.ZodObject<{
200
+ id: z.ZodString;
201
+ companyId: z.ZodString;
202
+ workLoopId: z.ZodString;
203
+ kind: z.ZodString;
204
+ label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
205
+ enabled: z.ZodBoolean;
206
+ cronExpression: z.ZodString;
207
+ timezone: z.ZodString;
208
+ nextRunAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
209
+ lastFiredAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
210
+ lastResult: z.ZodOptional<z.ZodNullable<z.ZodString>>;
211
+ createdAt: z.ZodString;
212
+ updatedAt: z.ZodString;
213
+ }, z.core.$strip>;
214
+ export declare const WorkLoopRunSchema: z.ZodObject<{
215
+ id: z.ZodString;
216
+ companyId: z.ZodString;
217
+ workLoopId: z.ZodString;
218
+ triggerId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
219
+ source: z.ZodEnum<{
220
+ schedule: "schedule";
221
+ manual: "manual";
222
+ }>;
223
+ status: z.ZodString;
224
+ triggeredAt: z.ZodString;
225
+ idempotencyKey: z.ZodOptional<z.ZodNullable<z.ZodString>>;
226
+ linkedIssueId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
227
+ coalescedIntoRunId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
228
+ failureReason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
229
+ completedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
230
+ createdAt: z.ZodString;
231
+ updatedAt: z.ZodString;
232
+ }, z.core.$strip>;
233
+ export declare const WorkLoopCreateRequestSchema: z.ZodObject<{
234
+ projectId: z.ZodString;
235
+ parentIssueId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
236
+ goalIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
237
+ title: z.ZodString;
238
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
239
+ assigneeAgentId: z.ZodString;
240
+ priority: z.ZodOptional<z.ZodEnum<{
241
+ none: "none";
242
+ low: "low";
243
+ medium: "medium";
244
+ high: "high";
245
+ urgent: "urgent";
246
+ }>>;
247
+ status: z.ZodOptional<z.ZodEnum<{
248
+ active: "active";
249
+ paused: "paused";
250
+ archived: "archived";
251
+ }>>;
252
+ concurrencyPolicy: z.ZodOptional<z.ZodEnum<{
253
+ coalesce_if_active: "coalesce_if_active";
254
+ skip_if_active: "skip_if_active";
255
+ always_enqueue: "always_enqueue";
256
+ }>>;
257
+ catchUpPolicy: z.ZodOptional<z.ZodEnum<{
258
+ skip_missed: "skip_missed";
259
+ enqueue_missed_with_cap: "enqueue_missed_with_cap";
260
+ }>>;
261
+ }, z.core.$strip>;
262
+ export declare const WorkLoopUpdateRequestSchema: z.ZodObject<{
263
+ title: z.ZodOptional<z.ZodString>;
264
+ description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
265
+ assigneeAgentId: z.ZodOptional<z.ZodString>;
266
+ priority: z.ZodOptional<z.ZodEnum<{
267
+ none: "none";
268
+ low: "low";
269
+ medium: "medium";
270
+ high: "high";
271
+ urgent: "urgent";
272
+ }>>;
273
+ status: z.ZodOptional<z.ZodEnum<{
274
+ active: "active";
275
+ paused: "paused";
276
+ archived: "archived";
277
+ }>>;
278
+ concurrencyPolicy: z.ZodOptional<z.ZodEnum<{
279
+ coalesce_if_active: "coalesce_if_active";
280
+ skip_if_active: "skip_if_active";
281
+ always_enqueue: "always_enqueue";
282
+ }>>;
283
+ catchUpPolicy: z.ZodOptional<z.ZodEnum<{
284
+ skip_missed: "skip_missed";
285
+ enqueue_missed_with_cap: "enqueue_missed_with_cap";
286
+ }>>;
287
+ parentIssueId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
288
+ goalIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
289
+ projectId: z.ZodOptional<z.ZodString>;
290
+ }, z.core.$strip>;
291
+ export declare const WorkLoopTriggerCronCreateSchema: z.ZodObject<{
292
+ mode: z.ZodLiteral<"cron">;
293
+ cronExpression: z.ZodString;
294
+ timezone: z.ZodOptional<z.ZodString>;
295
+ label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
296
+ enabled: z.ZodOptional<z.ZodBoolean>;
297
+ }, z.core.$strip>;
298
+ export declare const WorkLoopTriggerPresetCreateSchema: z.ZodObject<{
299
+ mode: z.ZodLiteral<"preset">;
300
+ preset: z.ZodEnum<{
301
+ daily: "daily";
302
+ weekly: "weekly";
303
+ }>;
304
+ hour24: z.ZodNumber;
305
+ minute: z.ZodNumber;
306
+ dayOfWeek: z.ZodOptional<z.ZodNumber>;
307
+ timezone: z.ZodOptional<z.ZodString>;
308
+ label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
309
+ enabled: z.ZodOptional<z.ZodBoolean>;
310
+ }, z.core.$strip>;
311
+ export declare const WorkLoopTriggerCreateRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
312
+ mode: z.ZodLiteral<"cron">;
313
+ cronExpression: z.ZodString;
314
+ timezone: z.ZodOptional<z.ZodString>;
315
+ label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
316
+ enabled: z.ZodOptional<z.ZodBoolean>;
317
+ }, z.core.$strip>, z.ZodObject<{
318
+ mode: z.ZodLiteral<"preset">;
319
+ preset: z.ZodEnum<{
320
+ daily: "daily";
321
+ weekly: "weekly";
322
+ }>;
323
+ hour24: z.ZodNumber;
324
+ minute: z.ZodNumber;
325
+ dayOfWeek: z.ZodOptional<z.ZodNumber>;
326
+ timezone: z.ZodOptional<z.ZodString>;
327
+ label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
328
+ enabled: z.ZodOptional<z.ZodBoolean>;
329
+ }, z.core.$strip>], "mode">;
330
+ export declare const WorkLoopTriggerUpdateRequestSchema: z.ZodObject<{
331
+ cronExpression: z.ZodOptional<z.ZodString>;
332
+ timezone: z.ZodOptional<z.ZodString>;
333
+ label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
334
+ enabled: z.ZodOptional<z.ZodBoolean>;
335
+ }, z.core.$strip>;
155
336
  export declare const IssueAttachmentSchema: z.ZodObject<{
156
337
  id: z.ZodString;
157
338
  companyId: z.ZodString;
@@ -216,6 +397,8 @@ export declare const IssueDetailSchema: z.ZodObject<{
216
397
  assigneeAgentId: z.ZodNullable<z.ZodString>;
217
398
  labels: z.ZodDefault<z.ZodArray<z.ZodString>>;
218
399
  tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
400
+ loopId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
401
+ loopRunId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
219
402
  createdAt: z.ZodString;
220
403
  updatedAt: z.ZodString;
221
404
  attachments: z.ZodArray<z.ZodObject<{
@@ -405,6 +588,7 @@ export declare const TemplateManifestAgentSchema: z.ZodObject<{
405
588
  general: "general";
406
589
  }>>;
407
590
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
591
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
408
592
  name: z.ZodString;
409
593
  providerType: z.ZodDefault<z.ZodLazy<z.ZodEnum<{
410
594
  claude_code: "claude_code";
@@ -414,6 +598,7 @@ export declare const TemplateManifestAgentSchema: z.ZodObject<{
414
598
  gemini_cli: "gemini_cli";
415
599
  openai_api: "openai_api";
416
600
  anthropic_api: "anthropic_api";
601
+ openclaw_gateway: "openclaw_gateway";
417
602
  http: "http";
418
603
  shell: "shell";
419
604
  }>>>;
@@ -532,6 +717,7 @@ export declare const TemplateManifestSchema: z.ZodObject<{
532
717
  general: "general";
533
718
  }>>;
534
719
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
720
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
535
721
  name: z.ZodString;
536
722
  providerType: z.ZodDefault<z.ZodLazy<z.ZodEnum<{
537
723
  claude_code: "claude_code";
@@ -541,6 +727,7 @@ export declare const TemplateManifestSchema: z.ZodObject<{
541
727
  gemini_cli: "gemini_cli";
542
728
  openai_api: "openai_api";
543
729
  anthropic_api: "anthropic_api";
730
+ openclaw_gateway: "openclaw_gateway";
544
731
  http: "http";
545
732
  shell: "shell";
546
733
  }>>>;
@@ -692,6 +879,7 @@ export declare const TemplateSchema: z.ZodObject<{
692
879
  general: "general";
693
880
  }>>;
694
881
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
882
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
695
883
  name: z.ZodString;
696
884
  providerType: z.ZodDefault<z.ZodLazy<z.ZodEnum<{
697
885
  claude_code: "claude_code";
@@ -701,6 +889,7 @@ export declare const TemplateSchema: z.ZodObject<{
701
889
  gemini_cli: "gemini_cli";
702
890
  openai_api: "openai_api";
703
891
  anthropic_api: "anthropic_api";
892
+ openclaw_gateway: "openclaw_gateway";
704
893
  http: "http";
705
894
  shell: "shell";
706
895
  }>>>;
@@ -852,6 +1041,7 @@ export declare const TemplateCreateRequestSchema: z.ZodObject<{
852
1041
  general: "general";
853
1042
  }>>;
854
1043
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1044
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
855
1045
  name: z.ZodString;
856
1046
  providerType: z.ZodDefault<z.ZodLazy<z.ZodEnum<{
857
1047
  claude_code: "claude_code";
@@ -861,6 +1051,7 @@ export declare const TemplateCreateRequestSchema: z.ZodObject<{
861
1051
  gemini_cli: "gemini_cli";
862
1052
  openai_api: "openai_api";
863
1053
  anthropic_api: "anthropic_api";
1054
+ openclaw_gateway: "openclaw_gateway";
864
1055
  http: "http";
865
1056
  shell: "shell";
866
1057
  }>>>;
@@ -1010,6 +1201,7 @@ export declare const TemplateUpdateRequestSchema: z.ZodObject<{
1010
1201
  general: "general";
1011
1202
  }>>;
1012
1203
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1204
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1013
1205
  name: z.ZodString;
1014
1206
  providerType: z.ZodDefault<z.ZodLazy<z.ZodEnum<{
1015
1207
  claude_code: "claude_code";
@@ -1019,6 +1211,7 @@ export declare const TemplateUpdateRequestSchema: z.ZodObject<{
1019
1211
  gemini_cli: "gemini_cli";
1020
1212
  openai_api: "openai_api";
1021
1213
  anthropic_api: "anthropic_api";
1214
+ openclaw_gateway: "openclaw_gateway";
1022
1215
  http: "http";
1023
1216
  shell: "shell";
1024
1217
  }>>>;
@@ -1219,6 +1412,7 @@ export declare const TemplateExportSchema: z.ZodObject<{
1219
1412
  general: "general";
1220
1413
  }>>;
1221
1414
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1415
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1222
1416
  name: z.ZodString;
1223
1417
  providerType: z.ZodDefault<z.ZodLazy<z.ZodEnum<{
1224
1418
  claude_code: "claude_code";
@@ -1228,6 +1422,7 @@ export declare const TemplateExportSchema: z.ZodObject<{
1228
1422
  gemini_cli: "gemini_cli";
1229
1423
  openai_api: "openai_api";
1230
1424
  anthropic_api: "anthropic_api";
1425
+ openclaw_gateway: "openclaw_gateway";
1231
1426
  http: "http";
1232
1427
  shell: "shell";
1233
1428
  }>>>;
@@ -1381,6 +1576,7 @@ export declare const TemplateImportRequestSchema: z.ZodObject<{
1381
1576
  general: "general";
1382
1577
  }>>;
1383
1578
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1579
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1384
1580
  name: z.ZodString;
1385
1581
  providerType: z.ZodDefault<z.ZodLazy<z.ZodEnum<{
1386
1582
  claude_code: "claude_code";
@@ -1390,6 +1586,7 @@ export declare const TemplateImportRequestSchema: z.ZodObject<{
1390
1586
  gemini_cli: "gemini_cli";
1391
1587
  openai_api: "openai_api";
1392
1588
  anthropic_api: "anthropic_api";
1589
+ openclaw_gateway: "openclaw_gateway";
1393
1590
  http: "http";
1394
1591
  shell: "shell";
1395
1592
  }>>>;
@@ -1520,6 +1717,7 @@ export declare const TemplateVersionSchema: z.ZodObject<{
1520
1717
  general: "general";
1521
1718
  }>>;
1522
1719
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1720
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1523
1721
  name: z.ZodString;
1524
1722
  providerType: z.ZodDefault<z.ZodLazy<z.ZodEnum<{
1525
1723
  claude_code: "claude_code";
@@ -1529,6 +1727,7 @@ export declare const TemplateVersionSchema: z.ZodObject<{
1529
1727
  gemini_cli: "gemini_cli";
1530
1728
  openai_api: "openai_api";
1531
1729
  anthropic_api: "anthropic_api";
1730
+ openclaw_gateway: "openclaw_gateway";
1532
1731
  http: "http";
1533
1732
  shell: "shell";
1534
1733
  }>>>;
@@ -1634,6 +1833,7 @@ export declare const ProviderTypeSchema: z.ZodEnum<{
1634
1833
  gemini_cli: "gemini_cli";
1635
1834
  openai_api: "openai_api";
1636
1835
  anthropic_api: "anthropic_api";
1836
+ openclaw_gateway: "openclaw_gateway";
1637
1837
  http: "http";
1638
1838
  shell: "shell";
1639
1839
  }>;
@@ -1832,6 +2032,7 @@ export declare const RunManagerReportSchema: z.ZodObject<{
1832
2032
  gemini_cli: "gemini_cli";
1833
2033
  openai_api: "openai_api";
1834
2034
  anthropic_api: "anthropic_api";
2035
+ openclaw_gateway: "openclaw_gateway";
1835
2036
  http: "http";
1836
2037
  shell: "shell";
1837
2038
  }>;
@@ -1909,6 +2110,7 @@ export declare const RunCompletionReportSchema: z.ZodObject<{
1909
2110
  gemini_cli: "gemini_cli";
1910
2111
  openai_api: "openai_api";
1911
2112
  anthropic_api: "anthropic_api";
2113
+ openclaw_gateway: "openclaw_gateway";
1912
2114
  http: "http";
1913
2115
  shell: "shell";
1914
2116
  }>;
@@ -2165,6 +2367,7 @@ export declare const AgentCreateRequestSchema: z.ZodObject<{
2165
2367
  general: "general";
2166
2368
  }>>;
2167
2369
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2370
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2168
2371
  name: z.ZodString;
2169
2372
  providerType: z.ZodEnum<{
2170
2373
  claude_code: "claude_code";
@@ -2174,6 +2377,7 @@ export declare const AgentCreateRequestSchema: z.ZodObject<{
2174
2377
  gemini_cli: "gemini_cli";
2175
2378
  openai_api: "openai_api";
2176
2379
  anthropic_api: "anthropic_api";
2380
+ openclaw_gateway: "openclaw_gateway";
2177
2381
  http: "http";
2178
2382
  shell: "shell";
2179
2383
  }>;
@@ -2209,10 +2413,12 @@ export declare const AgentCreateRequestSchema: z.ZodObject<{
2209
2413
  gemini_cli: "gemini_cli";
2210
2414
  openai_api: "openai_api";
2211
2415
  anthropic_api: "anthropic_api";
2416
+ openclaw_gateway: "openclaw_gateway";
2212
2417
  http: "http";
2213
2418
  shell: "shell";
2214
2419
  }>>>;
2215
2420
  requestedRuntimeModel: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2421
+ requestedCapabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2216
2422
  }, z.core.$strip>>;
2217
2423
  requestApproval: z.ZodDefault<z.ZodBoolean>;
2218
2424
  runtimeConfig: z.ZodDefault<z.ZodObject<{
@@ -2257,6 +2463,7 @@ export declare const AgentUpdateRequestSchema: z.ZodObject<{
2257
2463
  general: "general";
2258
2464
  }>>>;
2259
2465
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2466
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2260
2467
  name: z.ZodOptional<z.ZodString>;
2261
2468
  providerType: z.ZodOptional<z.ZodEnum<{
2262
2469
  claude_code: "claude_code";
@@ -2266,6 +2473,7 @@ export declare const AgentUpdateRequestSchema: z.ZodObject<{
2266
2473
  gemini_cli: "gemini_cli";
2267
2474
  openai_api: "openai_api";
2268
2475
  anthropic_api: "anthropic_api";
2476
+ openclaw_gateway: "openclaw_gateway";
2269
2477
  http: "http";
2270
2478
  shell: "shell";
2271
2479
  }>>;
@@ -2322,6 +2530,7 @@ export declare const AgentSchema: z.ZodObject<{
2322
2530
  general: "general";
2323
2531
  }>>>;
2324
2532
  title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2533
+ capabilities: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2325
2534
  name: z.ZodString;
2326
2535
  providerType: z.ZodEnum<{
2327
2536
  claude_code: "claude_code";
@@ -2331,6 +2540,7 @@ export declare const AgentSchema: z.ZodObject<{
2331
2540
  gemini_cli: "gemini_cli";
2332
2541
  openai_api: "openai_api";
2333
2542
  anthropic_api: "anthropic_api";
2543
+ openclaw_gateway: "openclaw_gateway";
2334
2544
  http: "http";
2335
2545
  shell: "shell";
2336
2546
  }>;
@@ -2828,6 +3038,7 @@ export declare const OfficeOccupantSchema: z.ZodObject<{
2828
3038
  gemini_cli: "gemini_cli";
2829
3039
  openai_api: "openai_api";
2830
3040
  anthropic_api: "anthropic_api";
3041
+ openclaw_gateway: "openclaw_gateway";
2831
3042
  http: "http";
2832
3043
  shell: "shell";
2833
3044
  }>>;
@@ -2875,6 +3086,7 @@ export declare const OfficeSpaceEventSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
2875
3086
  gemini_cli: "gemini_cli";
2876
3087
  openai_api: "openai_api";
2877
3088
  anthropic_api: "anthropic_api";
3089
+ openclaw_gateway: "openclaw_gateway";
2878
3090
  http: "http";
2879
3091
  shell: "shell";
2880
3092
  }>>;
@@ -2921,6 +3133,7 @@ export declare const OfficeSpaceEventSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
2921
3133
  gemini_cli: "gemini_cli";
2922
3134
  openai_api: "openai_api";
2923
3135
  anthropic_api: "anthropic_api";
3136
+ openclaw_gateway: "openclaw_gateway";
2924
3137
  http: "http";
2925
3138
  shell: "shell";
2926
3139
  }>>;
@@ -3214,6 +3427,7 @@ export declare const RealtimeEventEnvelopeSchema: z.ZodDiscriminatedUnion<[z.Zod
3214
3427
  gemini_cli: "gemini_cli";
3215
3428
  openai_api: "openai_api";
3216
3429
  anthropic_api: "anthropic_api";
3430
+ openclaw_gateway: "openclaw_gateway";
3217
3431
  http: "http";
3218
3432
  shell: "shell";
3219
3433
  }>>;
@@ -3260,6 +3474,7 @@ export declare const RealtimeEventEnvelopeSchema: z.ZodDiscriminatedUnion<[z.Zod
3260
3474
  gemini_cli: "gemini_cli";
3261
3475
  openai_api: "openai_api";
3262
3476
  anthropic_api: "anthropic_api";
3477
+ openclaw_gateway: "openclaw_gateway";
3263
3478
  http: "http";
3264
3479
  shell: "shell";
3265
3480
  }>>;
@@ -3641,6 +3856,7 @@ export declare const RealtimeEventMessageSchema: z.ZodDiscriminatedUnion<[z.ZodO
3641
3856
  gemini_cli: "gemini_cli";
3642
3857
  openai_api: "openai_api";
3643
3858
  anthropic_api: "anthropic_api";
3859
+ openclaw_gateway: "openclaw_gateway";
3644
3860
  http: "http";
3645
3861
  shell: "shell";
3646
3862
  }>>;
@@ -3687,6 +3903,7 @@ export declare const RealtimeEventMessageSchema: z.ZodDiscriminatedUnion<[z.ZodO
3687
3903
  gemini_cli: "gemini_cli";
3688
3904
  openai_api: "openai_api";
3689
3905
  anthropic_api: "anthropic_api";
3906
+ openclaw_gateway: "openclaw_gateway";
3690
3907
  http: "http";
3691
3908
  shell: "shell";
3692
3909
  }>>;
@@ -4070,6 +4287,7 @@ export declare const RealtimeMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
4070
4287
  gemini_cli: "gemini_cli";
4071
4288
  openai_api: "openai_api";
4072
4289
  anthropic_api: "anthropic_api";
4290
+ openclaw_gateway: "openclaw_gateway";
4073
4291
  http: "http";
4074
4292
  shell: "shell";
4075
4293
  }>>;
@@ -4116,6 +4334,7 @@ export declare const RealtimeMessageSchema: z.ZodUnion<readonly [z.ZodObject<{
4116
4334
  gemini_cli: "gemini_cli";
4117
4335
  openai_api: "openai_api";
4118
4336
  anthropic_api: "anthropic_api";
4337
+ openclaw_gateway: "openclaw_gateway";
4119
4338
  http: "http";
4120
4339
  shell: "shell";
4121
4340
  }>>;
@@ -4386,6 +4605,7 @@ export declare const CostLedgerEntrySchema: z.ZodObject<{
4386
4605
  gemini_cli: "gemini_cli";
4387
4606
  openai_api: "openai_api";
4388
4607
  anthropic_api: "anthropic_api";
4608
+ openclaw_gateway: "openclaw_gateway";
4389
4609
  http: "http";
4390
4610
  shell: "shell";
4391
4611
  }>;
@@ -4668,6 +4888,7 @@ export declare const HeartbeatRunDetailSchema: z.ZodObject<{
4668
4888
  gemini_cli: "gemini_cli";
4669
4889
  openai_api: "openai_api";
4670
4890
  anthropic_api: "anthropic_api";
4891
+ openclaw_gateway: "openclaw_gateway";
4671
4892
  http: "http";
4672
4893
  shell: "shell";
4673
4894
  }>;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "bopodev-agent-sdk",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
7
7
  "types": "src/index.ts",
8
8
  "dependencies": {
9
- "bopodev-contracts": "0.1.29"
9
+ "bopodev-contracts": "0.1.31"
10
10
  },
11
11
  "scripts": {
12
12
  "build": "tsc -p tsconfig.json --emitDeclarationOnly",
package/src/adapters.ts CHANGED
@@ -686,6 +686,15 @@ const staticMetadata: AdapterMetadata[] = [
686
686
  supportsThinkingEffort: false,
687
687
  requiresRuntimeCwd: false
688
688
  },
689
+ {
690
+ providerType: "openclaw_gateway",
691
+ label: "OpenClaw Gateway",
692
+ supportsModelSelection: false,
693
+ supportsEnvironmentTest: true,
694
+ supportsWebSearch: false,
695
+ supportsThinkingEffort: false,
696
+ requiresRuntimeCwd: false
697
+ },
689
698
  {
690
699
  providerType: "http",
691
700
  label: "HTTP",
@@ -708,7 +717,7 @@ const staticMetadata: AdapterMetadata[] = [
708
717
 
709
718
  const metadataByProviderType = new Map(staticMetadata.map((entry) => [entry.providerType, entry] as const));
710
719
 
711
- const modelCatalog: Record<Exclude<AgentProviderType, "http" | "shell">, AdapterModelOption[]> = {
720
+ const modelCatalog: Record<Exclude<AgentProviderType, "http" | "shell" | "openclaw_gateway">, AdapterModelOption[]> = {
712
721
  codex: [
713
722
  { id: "gpt-5.3-codex", label: "GPT-5.3 Codex" },
714
723
  { id: "gpt-5.4", label: "GPT-5.4" },
@@ -771,7 +780,7 @@ export async function listAdapterModels(
771
780
  providerType: AgentProviderType,
772
781
  runtime?: AgentRuntimeConfig
773
782
  ): Promise<AdapterModelOption[]> {
774
- if (providerType === "http" || providerType === "shell") {
783
+ if (providerType === "http" || providerType === "shell" || providerType === "openclaw_gateway") {
775
784
  return [];
776
785
  }
777
786
  if (providerType === "cursor") {
@@ -900,7 +909,10 @@ export async function testAdapterEnvironment(
900
909
 
901
910
  function detectProviderCommandMismatch(providerType: AgentProviderType, command: string) {
902
911
  const normalized = basename(command).toLowerCase();
903
- const known: Record<Exclude<AgentProviderType, "http" | "shell" | "openai_api" | "anthropic_api">, string[]> = {
912
+ const known: Record<
913
+ Exclude<AgentProviderType, "http" | "shell" | "openai_api" | "anthropic_api" | "openclaw_gateway">,
914
+ string[]
915
+ > = {
904
916
  claude_code: ["claude", "claude.exe", "claude.cmd"],
905
917
  codex: ["codex", "codex.exe", "codex.cmd"],
906
918
  cursor: ["cursor", "cursor.exe", "cursor.cmd"],
@@ -2700,9 +2712,43 @@ function composeBootstrapPreamble(context: HeartbeatContext): string {
2700
2712
  return operating ? `${operating}${user}\n\n` : `${user}\n\n`;
2701
2713
  }
2702
2714
 
2715
+ function formatTeamRosterSection(context: HeartbeatContext): string {
2716
+ const roster = context.teamRoster;
2717
+ if (!roster?.length) {
2718
+ return "";
2719
+ }
2720
+ const mode = resolveHeartbeatPromptModeForPrompt(context);
2721
+ const isCompact = mode === "compact";
2722
+ const clipCapabilities = (raw: string | null | undefined) => {
2723
+ const t = raw?.trim();
2724
+ if (!t) {
2725
+ return null;
2726
+ }
2727
+ if (isCompact && t.length > 200) {
2728
+ return `${t.slice(0, 200)}…`;
2729
+ }
2730
+ return t;
2731
+ };
2732
+ const lines = roster.map((member) => {
2733
+ const caps = clipCapabilities(member.capabilities);
2734
+ const parts = [member.id, member.name, member.role];
2735
+ const titled = member.title?.trim();
2736
+ if (titled) {
2737
+ parts.push(`title: ${titled}`);
2738
+ }
2739
+ if (caps) {
2740
+ parts.push(`capabilities: ${caps}`);
2741
+ }
2742
+ const you = member.id === context.agentId ? " (you)" : "";
2743
+ return `- ${parts.join(" | ")}${you}`;
2744
+ });
2745
+ return ["Team roster (for delegation):", ...lines, ""].join("\n");
2746
+ }
2747
+
2703
2748
  function buildIdleMicroPrompt(context: HeartbeatContext): string {
2704
2749
  const preamble = composeBootstrapPreamble(context);
2705
- return `${preamble}Idle heartbeat (micro prompt): agent ${context.agentId} (${context.agent.name}) has no assigned issues this run. Summarize readiness in \`employee_comment\`; leave \`results\` empty unless you completed verifiable work. Use \`BOPODEV_*\` for control-plane API calls when needed.
2750
+ const rosterBlock = formatTeamRosterSection(context);
2751
+ return `${preamble}${rosterBlock}Idle heartbeat (micro prompt): agent ${context.agentId} (${context.agent.name}) has no assigned issues this run. Summarize readiness in \`employee_comment\`; leave \`results\` empty unless you completed verifiable work. Use \`BOPODEV_*\` for control-plane API calls when needed.
2706
2752
 
2707
2753
  ${HEARTBEAT_JSON_SCHEMA_FOOTER}
2708
2754
  `;
@@ -2844,6 +2890,8 @@ export function createPrompt(context: HeartbeatContext) {
2844
2890
  : "- BOPODEV_REQUEST_HEADERS_JSON is missing. Report this as blocker."
2845
2891
  ].join("\n");
2846
2892
 
2893
+ const teamRosterBlock = formatTeamRosterSection(context);
2894
+
2847
2895
  const executionDirectives = [
2848
2896
  "Execution directives:",
2849
2897
  "- You are running inside a BopoDev heartbeat for local repository work.",
@@ -2885,7 +2933,7 @@ Company:
2885
2933
  - Name: ${context.company.name}
2886
2934
  - Mission: ${context.company.mission ?? "No mission set"}
2887
2935
 
2888
- Goal context:
2936
+ ${teamRosterBlock}Goal context:
2889
2937
  Company goals:
2890
2938
  ${companyGoals}
2891
2939
  Project goals:
package/src/registry.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { dedupeModels } from "./adapters";
1
2
  import type {
2
3
  AdapterEnvironmentResult,
3
4
  AdapterMetadata,
@@ -16,6 +17,7 @@ import { openaiapiAdapterModule } from "../../adapters/openai-api/src";
16
17
  import { anthropicapiAdapterModule } from "../../adapters/anthropic-api/src";
17
18
  import { httpAdapterModule } from "../../adapters/http/src";
18
19
  import { shellAdapterModule } from "../../adapters/shell/src";
20
+ import { openclawGatewayAdapterModule } from "../../adapters/openclaw-gateway/src";
19
21
 
20
22
  const adapterModules: Record<AgentProviderType, AdapterModule> = {
21
23
  claude_code: claudecodeAdapterModule,
@@ -25,6 +27,7 @@ const adapterModules: Record<AgentProviderType, AdapterModule> = {
25
27
  gemini_cli: geminiCliAdapterModule,
26
28
  openai_api: openaiapiAdapterModule,
27
29
  anthropic_api: anthropicapiAdapterModule,
30
+ openclaw_gateway: openclawGatewayAdapterModule,
28
31
  http: httpAdapterModule,
29
32
  shell: shellAdapterModule
30
33
  };
@@ -62,6 +65,10 @@ const adapters: Record<AgentProviderType, AgentAdapter> = {
62
65
  providerType: "anthropic_api",
63
66
  execute: (context) => adapterModules.anthropic_api.server.execute(context)
64
67
  },
68
+ openclaw_gateway: {
69
+ providerType: "openclaw_gateway",
70
+ execute: (context) => adapterModules.openclaw_gateway.server.execute(context)
71
+ },
65
72
  http: {
66
73
  providerType: "http",
67
74
  execute: (context) => adapterModules.http.server.execute(context)
@@ -80,11 +87,19 @@ export async function getAdapterModels(
80
87
  providerType: AgentProviderType,
81
88
  runtime?: AgentRuntimeConfig
82
89
  ): Promise<AdapterModelOption[]> {
83
- const fromModule = await adapterModules[providerType].server.listModels?.(runtime);
84
- if (fromModule) {
85
- return fromModule;
90
+ const mod = adapterModules[providerType];
91
+ const staticModels: AdapterModelOption[] = mod.models ? [...mod.models] : [];
92
+ const listModels = mod.server.listModels;
93
+ if (!listModels) {
94
+ return staticModels;
95
+ }
96
+ const discovered = await listModels(runtime);
97
+ const disc = Array.isArray(discovered) ? discovered : [];
98
+ if (disc.length > 0) {
99
+ return dedupeModels([...disc, ...staticModels]);
86
100
  }
87
- return adapterModules[providerType].models ? [...adapterModules[providerType].models] : [];
101
+ // Empty discovery (CLI missing, auth, timeout): keep static catalog so UIs are not stuck on client-only allowlists.
102
+ return staticModels.length > 0 ? staticModels : disc;
88
103
  }
89
104
 
90
105
  export function getAdapterMetadata(): AdapterMetadata[] {
package/src/types.ts CHANGED
@@ -85,6 +85,15 @@ export interface HeartbeatContext {
85
85
  commentBody?: string | null;
86
86
  issueIds?: string[];
87
87
  };
88
+ /** Company agents (non-terminated), sorted by name; used for delegation and task routing hints. */
89
+ teamRoster?: Array<{
90
+ id: string;
91
+ name: string;
92
+ role: string;
93
+ title?: string | null;
94
+ capabilities?: string | null;
95
+ status: string;
96
+ }>;
88
97
  }
89
98
 
90
99
  /**