codex-channel-bgos 0.2.0
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.
- package/LICENSE +21 -0
- package/README.md +114 -0
- package/dist/adapter.d.ts +96 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +677 -0
- package/dist/adapter.js.map +1 -0
- package/dist/agent-hints.d.ts +20 -0
- package/dist/agent-hints.d.ts.map +1 -0
- package/dist/agent-hints.js +92 -0
- package/dist/agent-hints.js.map +1 -0
- package/dist/agent-identity.d.ts +36 -0
- package/dist/agent-identity.d.ts.map +1 -0
- package/dist/agent-identity.js +42 -0
- package/dist/agent-identity.js.map +1 -0
- package/dist/attachment-bridge.d.ts +64 -0
- package/dist/attachment-bridge.d.ts.map +1 -0
- package/dist/attachment-bridge.js +216 -0
- package/dist/attachment-bridge.js.map +1 -0
- package/dist/auth-mode.d.ts +34 -0
- package/dist/auth-mode.d.ts.map +1 -0
- package/dist/auth-mode.js +48 -0
- package/dist/auth-mode.js.map +1 -0
- package/dist/bgos-api.d.ts +191 -0
- package/dist/bgos-api.d.ts.map +1 -0
- package/dist/bgos-api.js +225 -0
- package/dist/bgos-api.js.map +1 -0
- package/dist/bgos-ws.d.ts +94 -0
- package/dist/bgos-ws.d.ts.map +1 -0
- package/dist/bgos-ws.js +310 -0
- package/dist/bgos-ws.js.map +1 -0
- package/dist/capabilities.d.ts +28 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +44 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/catalog-sync.d.ts +26 -0
- package/dist/catalog-sync.d.ts.map +1 -0
- package/dist/catalog-sync.js +24 -0
- package/dist/catalog-sync.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +152 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-host.d.ts +44 -0
- package/dist/codex-host.d.ts.map +1 -0
- package/dist/codex-host.js +142 -0
- package/dist/codex-host.js.map +1 -0
- package/dist/commands-sync.d.ts +24 -0
- package/dist/commands-sync.d.ts.map +1 -0
- package/dist/commands-sync.js +43 -0
- package/dist/commands-sync.js.map +1 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +36 -0
- package/dist/config.js.map +1 -0
- package/dist/default-commands.d.ts +27 -0
- package/dist/default-commands.d.ts.map +1 -0
- package/dist/default-commands.js +64 -0
- package/dist/default-commands.js.map +1 -0
- package/dist/event-mapper.d.ts +43 -0
- package/dist/event-mapper.d.ts.map +1 -0
- package/dist/event-mapper.js +127 -0
- package/dist/event-mapper.js.map +1 -0
- package/dist/heartbeat.d.ts +75 -0
- package/dist/heartbeat.d.ts.map +1 -0
- package/dist/heartbeat.js +186 -0
- package/dist/heartbeat.js.map +1 -0
- package/dist/inbound-handler.d.ts +167 -0
- package/dist/inbound-handler.d.ts.map +1 -0
- package/dist/inbound-handler.js +282 -0
- package/dist/inbound-handler.js.map +1 -0
- package/dist/inbound-input.d.ts +17 -0
- package/dist/inbound-input.d.ts.map +1 -0
- package/dist/inbound-input.js +25 -0
- package/dist/inbound-input.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/install-service.d.ts +8 -0
- package/dist/install-service.d.ts.map +1 -0
- package/dist/install-service.js +66 -0
- package/dist/install-service.js.map +1 -0
- package/dist/last-id-store.d.ts +33 -0
- package/dist/last-id-store.d.ts.map +1 -0
- package/dist/last-id-store.js +101 -0
- package/dist/last-id-store.js.map +1 -0
- package/dist/load-config.d.ts +30 -0
- package/dist/load-config.d.ts.map +1 -0
- package/dist/load-config.js +86 -0
- package/dist/load-config.js.map +1 -0
- package/dist/media-classify.d.ts +37 -0
- package/dist/media-classify.d.ts.map +1 -0
- package/dist/media-classify.js +108 -0
- package/dist/media-classify.js.map +1 -0
- package/dist/media-guard.d.ts +13 -0
- package/dist/media-guard.d.ts.map +1 -0
- package/dist/media-guard.js +159 -0
- package/dist/media-guard.js.map +1 -0
- package/dist/outbound-retry.d.ts +24 -0
- package/dist/outbound-retry.d.ts.map +1 -0
- package/dist/outbound-retry.js +75 -0
- package/dist/outbound-retry.js.map +1 -0
- package/dist/outbound.d.ts +223 -0
- package/dist/outbound.d.ts.map +1 -0
- package/dist/outbound.js +366 -0
- package/dist/outbound.js.map +1 -0
- package/dist/outbox.d.ts +16 -0
- package/dist/outbox.d.ts.map +1 -0
- package/dist/outbox.js +88 -0
- package/dist/outbox.js.map +1 -0
- package/dist/pair-cli.d.ts +44 -0
- package/dist/pair-cli.d.ts.map +1 -0
- package/dist/pair-cli.js +182 -0
- package/dist/pair-cli.js.map +1 -0
- package/dist/pending-unknown-store.d.ts +26 -0
- package/dist/pending-unknown-store.d.ts.map +1 -0
- package/dist/pending-unknown-store.js +135 -0
- package/dist/pending-unknown-store.js.map +1 -0
- package/dist/processed-ids.d.ts +36 -0
- package/dist/processed-ids.d.ts.map +1 -0
- package/dist/processed-ids.js +55 -0
- package/dist/processed-ids.js.map +1 -0
- package/dist/reply-markers.d.ts +42 -0
- package/dist/reply-markers.d.ts.map +1 -0
- package/dist/reply-markers.js +124 -0
- package/dist/reply-markers.js.map +1 -0
- package/dist/setup/supervisor.d.ts +16 -0
- package/dist/setup/supervisor.d.ts.map +1 -0
- package/dist/setup/supervisor.js +61 -0
- package/dist/setup/supervisor.js.map +1 -0
- package/dist/thread-map.d.ts +12 -0
- package/dist/thread-map.d.ts.map +1 -0
- package/dist/thread-map.js +72 -0
- package/dist/thread-map.js.map +1 -0
- package/dist/tool-progress.d.ts +103 -0
- package/dist/tool-progress.d.ts.map +1 -0
- package/dist/tool-progress.js +216 -0
- package/dist/tool-progress.js.map +1 -0
- package/dist/types.d.ts +244 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +28 -0
- package/dist/version.js.map +1 -0
- package/dist/voice-rpc.d.ts +37 -0
- package/dist/voice-rpc.d.ts.map +1 -0
- package/dist/voice-rpc.js +44 -0
- package/dist/voice-rpc.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decision D7: prefer an existing `codex login` (ChatGPT plan, zero marginal
|
|
3
|
+
* cost), fall back to OPENAI_API_KEY (metered), refuse to start with neither.
|
|
4
|
+
*
|
|
5
|
+
* Pure resolver: the daemon feeds it the observable facts (does ~/.codex/auth.json
|
|
6
|
+
* exist, is OPENAI_API_KEY set, was a mode forced) and gets back the active mode,
|
|
7
|
+
* a human label to print at startup, and, for apikey mode, the key to hand the
|
|
8
|
+
* Codex SDK (which injects it as CODEX_API_KEY). See codex-host for how chatgpt
|
|
9
|
+
* mode strips the key from the child env so the CLI uses the login instead.
|
|
10
|
+
*/
|
|
11
|
+
const NEITHER_ERROR = "No Codex credentials found. Sign in with `codex login`, or set OPENAI_API_KEY " +
|
|
12
|
+
"(for example in ~/.env), then run the command again.";
|
|
13
|
+
const NO_KEY_ERROR = "CODEX_BGOS_AUTH_MODE=apikey was requested but OPENAI_API_KEY is not set. " +
|
|
14
|
+
"Set OPENAI_API_KEY (for example in ~/.env), then run the command again.";
|
|
15
|
+
const NO_LOGIN_ERROR = "CODEX_BGOS_AUTH_MODE=chatgpt was requested but no `codex login` was found " +
|
|
16
|
+
"(~/.codex/auth.json is missing). Run `codex login` first, then run the command again.";
|
|
17
|
+
function cleanKey(raw) {
|
|
18
|
+
if (typeof raw !== "string")
|
|
19
|
+
return null;
|
|
20
|
+
const trimmed = raw.trim();
|
|
21
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
22
|
+
}
|
|
23
|
+
export function resolveAuthMode(input) {
|
|
24
|
+
const forced = input.forced ?? "auto";
|
|
25
|
+
const key = cleanKey(input.openaiKey);
|
|
26
|
+
const hasLogin = input.authJsonExists === true;
|
|
27
|
+
if (forced === "chatgpt") {
|
|
28
|
+
if (hasLogin) {
|
|
29
|
+
return { ok: true, mode: "chatgpt", label: "codex login (ChatGPT plan)" };
|
|
30
|
+
}
|
|
31
|
+
return { ok: false, error: NO_LOGIN_ERROR };
|
|
32
|
+
}
|
|
33
|
+
if (forced === "apikey") {
|
|
34
|
+
if (key) {
|
|
35
|
+
return { ok: true, mode: "apikey", apiKey: key, label: "OPENAI_API_KEY" };
|
|
36
|
+
}
|
|
37
|
+
return { ok: false, error: NO_KEY_ERROR };
|
|
38
|
+
}
|
|
39
|
+
// auto: prefer the login, then the key, then refuse.
|
|
40
|
+
if (hasLogin) {
|
|
41
|
+
return { ok: true, mode: "chatgpt", label: "codex login (ChatGPT plan)" };
|
|
42
|
+
}
|
|
43
|
+
if (key) {
|
|
44
|
+
return { ok: true, mode: "apikey", apiKey: key, label: "OPENAI_API_KEY" };
|
|
45
|
+
}
|
|
46
|
+
return { ok: false, error: NEITHER_ERROR };
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=auth-mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-mode.js","sourceRoot":"","sources":["../src/auth-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA6BH,MAAM,aAAa,GACjB,gFAAgF;IAChF,sDAAsD,CAAC;AAEzD,MAAM,YAAY,GAChB,2EAA2E;IAC3E,yEAAyE,CAAC;AAE5E,MAAM,cAAc,GAClB,4EAA4E;IAC5E,uFAAuF,CAAC;AAE1F,SAAS,QAAQ,CAAC,GAA8B;IAC9C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAgB;IAC9C,MAAM,MAAM,GAAc,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC;IACjD,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,cAAc,KAAK,IAAI,CAAC;IAE/C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC;QAC5E,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAC9C,CAAC;IAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,IAAI,GAAG,EAAE,CAAC;YACR,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC5E,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAC5C,CAAC;IAED,qDAAqD;IACrD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC;IAC5E,CAAC;IACD,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC5E,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { type AgentCatalogEntry, type BgosMessageEnvelope, type CommandManifestEntry, type InboundMessagePayload, type IntegrationPairing, type OutboundMessagePayload, type PairExchangeResponse, type PluginConfig } from "./types.js";
|
|
2
|
+
import type { VoiceRpcResultBody } from "./voice-rpc.js";
|
|
3
|
+
import type { HeartbeatDto } from "./heartbeat.js";
|
|
4
|
+
/**
|
|
5
|
+
* Thin typed wrapper around the BGOS integration endpoints. All methods
|
|
6
|
+
* attach the X-BGOS-Pairing header from cfg.pairingToken.
|
|
7
|
+
*
|
|
8
|
+
* A 401 from any request is mapped to PairingRevokedError so callers
|
|
9
|
+
* (WS client, outbound adapter) can short-circuit and let the setup
|
|
10
|
+
* wizard prompt for re-pair.
|
|
11
|
+
*/
|
|
12
|
+
export declare class BgosApi {
|
|
13
|
+
private readonly http;
|
|
14
|
+
constructor(cfg: PluginConfig);
|
|
15
|
+
/** GET /integrations/me - confirms token + touches last_seen_at.
|
|
16
|
+
* Includes assistant→agent_route bindings so the plugin can seed
|
|
17
|
+
* its dispatch map on cold start.
|
|
18
|
+
*/
|
|
19
|
+
whoami(): Promise<{
|
|
20
|
+
pairing_id: number;
|
|
21
|
+
user_id: string;
|
|
22
|
+
device_label: string;
|
|
23
|
+
integration: string;
|
|
24
|
+
assistants?: Array<{
|
|
25
|
+
assistant_id: number;
|
|
26
|
+
agent_route: string | null;
|
|
27
|
+
name: string;
|
|
28
|
+
/** Count of slash-commands currently set; lets callers decide
|
|
29
|
+
* whether to seed defaults without a second round-trip. */
|
|
30
|
+
command_count?: number;
|
|
31
|
+
}>;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Fetch the served capability canon for this channel (capability bootstrap).
|
|
35
|
+
* The backend owns the machine-readable canon and serves a per-channel
|
|
36
|
+
* payload; the daemon injects the returned `text` into the Codex agent's
|
|
37
|
+
* AGENTS.md at connect, falling back to the bundled copy when this is
|
|
38
|
+
* unreachable. GET is pairing-token authed like every other method here.
|
|
39
|
+
*
|
|
40
|
+
* `text` is header + shared core + the codex channel delta, ready to inject.
|
|
41
|
+
* Any non-2xx (including a 404 from an older backend that predates the
|
|
42
|
+
* endpoint) throws, and the caller keeps the bundled fallback.
|
|
43
|
+
*/
|
|
44
|
+
getCapabilities(channel?: string): Promise<{
|
|
45
|
+
channel: string;
|
|
46
|
+
version: string;
|
|
47
|
+
text: string;
|
|
48
|
+
core: string;
|
|
49
|
+
channelSyntax: string;
|
|
50
|
+
}>;
|
|
51
|
+
/** Pair exchange (Public; does NOT need X-BGOS-Pairing). */
|
|
52
|
+
static pairExchange(baseUrl: string, params: {
|
|
53
|
+
code: string;
|
|
54
|
+
deviceLabel: string;
|
|
55
|
+
agentCatalog?: AgentCatalogEntry[];
|
|
56
|
+
/**
|
|
57
|
+
* Channel label persisted on the pairing row. MUST be `'codex'` for
|
|
58
|
+
* Codex pairings - without it, the backend falls back to `'openclaw'`
|
|
59
|
+
* and the pairing surfaces under the OpenClaw card with assistants
|
|
60
|
+
* created as code='openclaw' (wrong UI gates, wrong slash picker).
|
|
61
|
+
*/
|
|
62
|
+
integration?: string;
|
|
63
|
+
/** Daemon version stamped on the pairing row (contract C1). */
|
|
64
|
+
daemonVersion?: string;
|
|
65
|
+
}): Promise<PairExchangeResponse>;
|
|
66
|
+
/** Plugin pushes (or updates) the agent catalog for this pairing. */
|
|
67
|
+
pushAgentCatalog(pairingId: number, agents: AgentCatalogEntry[]): Promise<void>;
|
|
68
|
+
/** Plugin replaces the slash-command manifest for a single bound assistant. */
|
|
69
|
+
putCommands(assistantId: number, commands: CommandManifestEntry[]): Promise<void>;
|
|
70
|
+
/** REST backfill after a WS reconnect. */
|
|
71
|
+
inboundSince(sinceMessageId: number): Promise<{
|
|
72
|
+
messages: InboundMessagePayload[];
|
|
73
|
+
}>;
|
|
74
|
+
/** Fetch the recent message history for a chat - used by the daemon to
|
|
75
|
+
* rebuild conversation context before dispatching to a stateless
|
|
76
|
+
* gateway. Backend returns up to 100 entries ASC by created_at. */
|
|
77
|
+
getMessages(chatId: number, userId: string): Promise<BgosMessageEnvelope[]>;
|
|
78
|
+
/**
|
|
79
|
+
* Self-resolve (or create) this assistant's primary BGOS delivery chat -
|
|
80
|
+
* the target for proactive / check-in sends when no `CODEX_BGOS_CHAT_ID`
|
|
81
|
+
* env override is set (parity root cause D). Pairing-token auth only (the
|
|
82
|
+
* pairing must own the assistant; the backend enforces this).
|
|
83
|
+
*
|
|
84
|
+
* `POST /integrations/assistants/:assistantId/primary-chat` (no body). The
|
|
85
|
+
* backend resolves the assistant's `primaryChatId`, else the newest
|
|
86
|
+
* `kind='main'` chat, else creates a fresh main chat (pinning only on a
|
|
87
|
+
* fresh create). Response is `{ chat_id: number }`.
|
|
88
|
+
*
|
|
89
|
+
* Throws on any non-2xx or a malformed response - the caller (proactive
|
|
90
|
+
* `loadTargets`) treats a throw as "skip this assistant".
|
|
91
|
+
*/
|
|
92
|
+
getOrCreatePrimaryChat(assistantId: number): Promise<number>;
|
|
93
|
+
/** Agent reply - assistant message with optional inline buttons/approval. */
|
|
94
|
+
postMessage(payload: OutboundMessagePayload): Promise<{
|
|
95
|
+
id: number;
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* Agent reply via `POST /api/v1/send-message` - the SAME wire payload as
|
|
99
|
+
* `postMessage`, but the endpoint the backend runs its peer-reply bridge
|
|
100
|
+
* (`bridgePeerReplyIfApplicable`) on. For an a2a side-thread chat that
|
|
101
|
+
* bridge stamps `peer_conversation_id` on the reply, which is what
|
|
102
|
+
* resolves the initiating peer's `wait_for_reply`. `/messages` has no
|
|
103
|
+
* such bridge, so peer replies sent there never resolve the wait - hence
|
|
104
|
+
* a dedicated method (see inbound-handler.ts; reference impl
|
|
105
|
+
* bgos-claude-plugin/server.ts uses `bgosPost('send-message', …)`).
|
|
106
|
+
*
|
|
107
|
+
* Response shape differs from `/messages`: the controller returns the
|
|
108
|
+
* created message nested under `message` (HTTP 200) rather than a bare
|
|
109
|
+
* `{ id }` (HTTP 201), so unwrap both shapes.
|
|
110
|
+
*/
|
|
111
|
+
sendMessage(payload: OutboundMessagePayload): Promise<{
|
|
112
|
+
id: number;
|
|
113
|
+
}>;
|
|
114
|
+
/**
|
|
115
|
+
* PATCH an existing message. Used by the tool_progress card flow to
|
|
116
|
+
* update a card in place - adding new tools as they fire, transitioning
|
|
117
|
+
* state running → done at end-of-turn.
|
|
118
|
+
*
|
|
119
|
+
* The backend (BGOS PR #200, deployed 2026-05-16) auto-fills userId from
|
|
120
|
+
* the authenticated principal when omitted from the body. We always omit
|
|
121
|
+
* it from this client - pairing auth on the request itself carries the
|
|
122
|
+
* identity. Returns the updated message dto.
|
|
123
|
+
*/
|
|
124
|
+
patchMessage(messageId: number, payload: {
|
|
125
|
+
text?: string;
|
|
126
|
+
toolProgress?: {
|
|
127
|
+
state: "running" | "done";
|
|
128
|
+
tools: Array<{
|
|
129
|
+
icon: string;
|
|
130
|
+
name: string;
|
|
131
|
+
args?: string;
|
|
132
|
+
status: "running" | "done" | "error";
|
|
133
|
+
}>;
|
|
134
|
+
};
|
|
135
|
+
}): Promise<{
|
|
136
|
+
id: number;
|
|
137
|
+
}>;
|
|
138
|
+
/** Request a presigned PUT for a file ≥500 KB that the agent wants to send.
|
|
139
|
+
*
|
|
140
|
+
* Route is `POST /api/v1/files/upload-url` (FileController) - NOT under
|
|
141
|
+
* `/integrations/`; the old `integrations/files/upload-url` path 404'd,
|
|
142
|
+
* silently breaking every ≥500 KB media send. The request DTO is camelCase
|
|
143
|
+
* `{ fileName, contentType, size }` and the response is `{ uploadUrl, key }`
|
|
144
|
+
* - both diverged from the snake_case shape this client used. We send the
|
|
145
|
+
* right keys and normalize the response to the `{ upload_url, s3_key }`
|
|
146
|
+
* shape `publishMediaPath` consumes. */
|
|
147
|
+
createUploadUrl(params: {
|
|
148
|
+
filename: string;
|
|
149
|
+
mimeType: string;
|
|
150
|
+
size: number;
|
|
151
|
+
}): Promise<{
|
|
152
|
+
upload_url: string;
|
|
153
|
+
s3_key: string;
|
|
154
|
+
}>;
|
|
155
|
+
/** List this pairing's active/paired state. Mostly used in setup wizard. */
|
|
156
|
+
listPairings(): Promise<IntegrationPairing[]>;
|
|
157
|
+
/**
|
|
158
|
+
* POST a liveness heartbeat (contract C1). Pairing-token auth only. The
|
|
159
|
+
* backend touches last_seen_at + records daemon_version / last_error_*.
|
|
160
|
+
* Additive: older backends 404 this route; callers must treat any failure
|
|
161
|
+
* as non-fatal (the HeartbeatController swallows it).
|
|
162
|
+
*/
|
|
163
|
+
postHeartbeat(body: HeartbeatDto): Promise<void>;
|
|
164
|
+
/**
|
|
165
|
+
* Set (or clear) an assistant's status line (contract C4). PATCHes the
|
|
166
|
+
* pairing-scoped `/integrations/assistants/:assistantId/status`. Pass an
|
|
167
|
+
* empty string to clear. Fail-open at the call site (fork throttles + never
|
|
168
|
+
* lets a status write suppress a reply).
|
|
169
|
+
*/
|
|
170
|
+
setStatus(assistantId: number, body: {
|
|
171
|
+
statusText: string | null;
|
|
172
|
+
statusEmoji?: string | null;
|
|
173
|
+
}): Promise<void>;
|
|
174
|
+
/**
|
|
175
|
+
* Swap the pairing token (and optionally base URL) in place after a token
|
|
176
|
+
* rotation, so existing references (outbound, tool-progress) keep working
|
|
177
|
+
* without a rebuild. Used by the adapter's re-pair recovery path.
|
|
178
|
+
*/
|
|
179
|
+
updateToken(token: string, baseUrl?: string): void;
|
|
180
|
+
/** ACK a voice_rpc frame - cancels the backend's 1.5 s retry-emit.
|
|
181
|
+
* Best-effort; callers must treat a failure as non-fatal. */
|
|
182
|
+
postVoiceRpcAck(rpcId: string): Promise<unknown>;
|
|
183
|
+
/** Settle a voice_rpc op (mint / consult / dispatch-accept). The backend
|
|
184
|
+
* drops results that arrive after its own per-op deadline, so callers
|
|
185
|
+
* keep their inner caps strictly under it (see voice-rpc.ts). */
|
|
186
|
+
postVoiceRpcResult(rpcId: string, body: VoiceRpcResultBody): Promise<unknown>;
|
|
187
|
+
/** Report the outcome of a detached voice dispatch - flips the durable
|
|
188
|
+
* voice_tasks row and fans `voice_task_update` to the user's devices. */
|
|
189
|
+
postVoiceTaskResult(taskId: string, body: VoiceRpcResultBody): Promise<unknown>;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=bgos-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bgos-api.d.ts","sourceRoot":"","sources":["../src/bgos-api.ts"],"names":[],"mappings":"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"}
|
package/dist/bgos-api.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { PairingRevokedError, } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Thin typed wrapper around the BGOS integration endpoints. All methods
|
|
5
|
+
* attach the X-BGOS-Pairing header from cfg.pairingToken.
|
|
6
|
+
*
|
|
7
|
+
* A 401 from any request is mapped to PairingRevokedError so callers
|
|
8
|
+
* (WS client, outbound adapter) can short-circuit and let the setup
|
|
9
|
+
* wizard prompt for re-pair.
|
|
10
|
+
*/
|
|
11
|
+
export class BgosApi {
|
|
12
|
+
http;
|
|
13
|
+
constructor(cfg) {
|
|
14
|
+
this.http = axios.create({
|
|
15
|
+
baseURL: cfg.baseUrl + "/api/v1",
|
|
16
|
+
headers: {
|
|
17
|
+
"X-BGOS-Pairing": cfg.pairingToken,
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
},
|
|
20
|
+
timeout: 30_000,
|
|
21
|
+
});
|
|
22
|
+
this.http.interceptors.response.use((r) => r, (err) => {
|
|
23
|
+
if (err?.response?.status === 401) {
|
|
24
|
+
return Promise.reject(new PairingRevokedError(err.response?.data?.message ?? "pairing rejected by BGOS"));
|
|
25
|
+
}
|
|
26
|
+
return Promise.reject(err);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** GET /integrations/me - confirms token + touches last_seen_at.
|
|
30
|
+
* Includes assistant→agent_route bindings so the plugin can seed
|
|
31
|
+
* its dispatch map on cold start.
|
|
32
|
+
*/
|
|
33
|
+
async whoami() {
|
|
34
|
+
const r = await this.http.get("integrations/me");
|
|
35
|
+
return r.data;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Fetch the served capability canon for this channel (capability bootstrap).
|
|
39
|
+
* The backend owns the machine-readable canon and serves a per-channel
|
|
40
|
+
* payload; the daemon injects the returned `text` into the Codex agent's
|
|
41
|
+
* AGENTS.md at connect, falling back to the bundled copy when this is
|
|
42
|
+
* unreachable. GET is pairing-token authed like every other method here.
|
|
43
|
+
*
|
|
44
|
+
* `text` is header + shared core + the codex channel delta, ready to inject.
|
|
45
|
+
* Any non-2xx (including a 404 from an older backend that predates the
|
|
46
|
+
* endpoint) throws, and the caller keeps the bundled fallback.
|
|
47
|
+
*/
|
|
48
|
+
async getCapabilities(channel = "codex") {
|
|
49
|
+
const r = await this.http.get("integrations/capabilities", {
|
|
50
|
+
params: { channel },
|
|
51
|
+
});
|
|
52
|
+
return r.data;
|
|
53
|
+
}
|
|
54
|
+
/** Pair exchange (Public; does NOT need X-BGOS-Pairing). */
|
|
55
|
+
static async pairExchange(baseUrl, params) {
|
|
56
|
+
const base = baseUrl.replace(/\/+$/, "") + "/api/v1";
|
|
57
|
+
const r = await axios.post(`${base}/integrations/pair-exchange`, params, {
|
|
58
|
+
timeout: 15_000,
|
|
59
|
+
});
|
|
60
|
+
return r.data;
|
|
61
|
+
}
|
|
62
|
+
/** Plugin pushes (or updates) the agent catalog for this pairing. */
|
|
63
|
+
async pushAgentCatalog(pairingId, agents) {
|
|
64
|
+
await this.http.post(`integrations/pairings/${pairingId}/agent-catalog`, {
|
|
65
|
+
agents,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** Plugin replaces the slash-command manifest for a single bound assistant. */
|
|
69
|
+
async putCommands(assistantId, commands) {
|
|
70
|
+
await this.http.put(`integrations/assistants/${assistantId}/commands`, { commands });
|
|
71
|
+
}
|
|
72
|
+
/** REST backfill after a WS reconnect. */
|
|
73
|
+
async inboundSince(sinceMessageId) {
|
|
74
|
+
const r = await this.http.get("integrations/inbound", {
|
|
75
|
+
params: { since_message_id: sinceMessageId },
|
|
76
|
+
});
|
|
77
|
+
return r.data;
|
|
78
|
+
}
|
|
79
|
+
/** Fetch the recent message history for a chat - used by the daemon to
|
|
80
|
+
* rebuild conversation context before dispatching to a stateless
|
|
81
|
+
* gateway. Backend returns up to 100 entries ASC by created_at. */
|
|
82
|
+
async getMessages(chatId, userId) {
|
|
83
|
+
const r = await this.http.get(`chats/${chatId}/messages`, {
|
|
84
|
+
params: { userId },
|
|
85
|
+
});
|
|
86
|
+
const rows = r.data?.messages;
|
|
87
|
+
return Array.isArray(rows) ? rows : [];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Self-resolve (or create) this assistant's primary BGOS delivery chat -
|
|
91
|
+
* the target for proactive / check-in sends when no `CODEX_BGOS_CHAT_ID`
|
|
92
|
+
* env override is set (parity root cause D). Pairing-token auth only (the
|
|
93
|
+
* pairing must own the assistant; the backend enforces this).
|
|
94
|
+
*
|
|
95
|
+
* `POST /integrations/assistants/:assistantId/primary-chat` (no body). The
|
|
96
|
+
* backend resolves the assistant's `primaryChatId`, else the newest
|
|
97
|
+
* `kind='main'` chat, else creates a fresh main chat (pinning only on a
|
|
98
|
+
* fresh create). Response is `{ chat_id: number }`.
|
|
99
|
+
*
|
|
100
|
+
* Throws on any non-2xx or a malformed response - the caller (proactive
|
|
101
|
+
* `loadTargets`) treats a throw as "skip this assistant".
|
|
102
|
+
*/
|
|
103
|
+
async getOrCreatePrimaryChat(assistantId) {
|
|
104
|
+
const r = await this.http.post(`integrations/assistants/${assistantId}/primary-chat`, {});
|
|
105
|
+
const chatId = r.data?.chat_id;
|
|
106
|
+
if (typeof chatId !== "number" || !Number.isFinite(chatId) || chatId <= 0) {
|
|
107
|
+
throw new Error(`primary-chat endpoint returned no chat_id for assistant ${assistantId}`);
|
|
108
|
+
}
|
|
109
|
+
return chatId;
|
|
110
|
+
}
|
|
111
|
+
/** Agent reply - assistant message with optional inline buttons/approval. */
|
|
112
|
+
async postMessage(payload) {
|
|
113
|
+
const r = await this.http.post("messages", payload);
|
|
114
|
+
return r.data;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Agent reply via `POST /api/v1/send-message` - the SAME wire payload as
|
|
118
|
+
* `postMessage`, but the endpoint the backend runs its peer-reply bridge
|
|
119
|
+
* (`bridgePeerReplyIfApplicable`) on. For an a2a side-thread chat that
|
|
120
|
+
* bridge stamps `peer_conversation_id` on the reply, which is what
|
|
121
|
+
* resolves the initiating peer's `wait_for_reply`. `/messages` has no
|
|
122
|
+
* such bridge, so peer replies sent there never resolve the wait - hence
|
|
123
|
+
* a dedicated method (see inbound-handler.ts; reference impl
|
|
124
|
+
* bgos-claude-plugin/server.ts uses `bgosPost('send-message', …)`).
|
|
125
|
+
*
|
|
126
|
+
* Response shape differs from `/messages`: the controller returns the
|
|
127
|
+
* created message nested under `message` (HTTP 200) rather than a bare
|
|
128
|
+
* `{ id }` (HTTP 201), so unwrap both shapes.
|
|
129
|
+
*/
|
|
130
|
+
async sendMessage(payload) {
|
|
131
|
+
const r = await this.http.post("send-message", payload);
|
|
132
|
+
const data = (r.data ?? {});
|
|
133
|
+
return { id: data.message?.id ?? data.id ?? 0 };
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* PATCH an existing message. Used by the tool_progress card flow to
|
|
137
|
+
* update a card in place - adding new tools as they fire, transitioning
|
|
138
|
+
* state running → done at end-of-turn.
|
|
139
|
+
*
|
|
140
|
+
* The backend (BGOS PR #200, deployed 2026-05-16) auto-fills userId from
|
|
141
|
+
* the authenticated principal when omitted from the body. We always omit
|
|
142
|
+
* it from this client - pairing auth on the request itself carries the
|
|
143
|
+
* identity. Returns the updated message dto.
|
|
144
|
+
*/
|
|
145
|
+
async patchMessage(messageId, payload) {
|
|
146
|
+
const r = await this.http.patch(`messages/${messageId}`, payload);
|
|
147
|
+
return r.data;
|
|
148
|
+
}
|
|
149
|
+
/** Request a presigned PUT for a file ≥500 KB that the agent wants to send.
|
|
150
|
+
*
|
|
151
|
+
* Route is `POST /api/v1/files/upload-url` (FileController) - NOT under
|
|
152
|
+
* `/integrations/`; the old `integrations/files/upload-url` path 404'd,
|
|
153
|
+
* silently breaking every ≥500 KB media send. The request DTO is camelCase
|
|
154
|
+
* `{ fileName, contentType, size }` and the response is `{ uploadUrl, key }`
|
|
155
|
+
* - both diverged from the snake_case shape this client used. We send the
|
|
156
|
+
* right keys and normalize the response to the `{ upload_url, s3_key }`
|
|
157
|
+
* shape `publishMediaPath` consumes. */
|
|
158
|
+
async createUploadUrl(params) {
|
|
159
|
+
const r = await this.http.post("files/upload-url", {
|
|
160
|
+
fileName: params.filename,
|
|
161
|
+
contentType: params.mimeType,
|
|
162
|
+
size: params.size,
|
|
163
|
+
});
|
|
164
|
+
return { upload_url: r.data.uploadUrl, s3_key: r.data.key };
|
|
165
|
+
}
|
|
166
|
+
/** List this pairing's active/paired state. Mostly used in setup wizard. */
|
|
167
|
+
async listPairings() {
|
|
168
|
+
const r = await this.http.get("integrations/pairings");
|
|
169
|
+
return r.data;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* POST a liveness heartbeat (contract C1). Pairing-token auth only. The
|
|
173
|
+
* backend touches last_seen_at + records daemon_version / last_error_*.
|
|
174
|
+
* Additive: older backends 404 this route; callers must treat any failure
|
|
175
|
+
* as non-fatal (the HeartbeatController swallows it).
|
|
176
|
+
*/
|
|
177
|
+
async postHeartbeat(body) {
|
|
178
|
+
await this.http.post("integrations/heartbeat", body);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Set (or clear) an assistant's status line (contract C4). PATCHes the
|
|
182
|
+
* pairing-scoped `/integrations/assistants/:assistantId/status`. Pass an
|
|
183
|
+
* empty string to clear. Fail-open at the call site (fork throttles + never
|
|
184
|
+
* lets a status write suppress a reply).
|
|
185
|
+
*/
|
|
186
|
+
async setStatus(assistantId, body) {
|
|
187
|
+
await this.http.patch(`integrations/assistants/${assistantId}/status`, body);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Swap the pairing token (and optionally base URL) in place after a token
|
|
191
|
+
* rotation, so existing references (outbound, tool-progress) keep working
|
|
192
|
+
* without a rebuild. Used by the adapter's re-pair recovery path.
|
|
193
|
+
*/
|
|
194
|
+
updateToken(token, baseUrl) {
|
|
195
|
+
const headers = this.http.defaults.headers;
|
|
196
|
+
headers.common["X-BGOS-Pairing"] = token;
|
|
197
|
+
headers["X-BGOS-Pairing"] = token;
|
|
198
|
+
if (baseUrl) {
|
|
199
|
+
this.http.defaults.baseURL = baseUrl.replace(/\/+$/, "") + "/api/v1";
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// -------------------------------------------------------------------
|
|
203
|
+
// Native voice control plane (voice_rpc - see voice-rpc.ts)
|
|
204
|
+
// -------------------------------------------------------------------
|
|
205
|
+
/** ACK a voice_rpc frame - cancels the backend's 1.5 s retry-emit.
|
|
206
|
+
* Best-effort; callers must treat a failure as non-fatal. */
|
|
207
|
+
async postVoiceRpcAck(rpcId) {
|
|
208
|
+
const r = await this.http.post(`integrations/voice-rpc/${encodeURIComponent(rpcId)}/ack`, {});
|
|
209
|
+
return r.data;
|
|
210
|
+
}
|
|
211
|
+
/** Settle a voice_rpc op (mint / consult / dispatch-accept). The backend
|
|
212
|
+
* drops results that arrive after its own per-op deadline, so callers
|
|
213
|
+
* keep their inner caps strictly under it (see voice-rpc.ts). */
|
|
214
|
+
async postVoiceRpcResult(rpcId, body) {
|
|
215
|
+
const r = await this.http.post(`integrations/voice-rpc/${encodeURIComponent(rpcId)}/result`, body);
|
|
216
|
+
return r.data;
|
|
217
|
+
}
|
|
218
|
+
/** Report the outcome of a detached voice dispatch - flips the durable
|
|
219
|
+
* voice_tasks row and fans `voice_task_update` to the user's devices. */
|
|
220
|
+
async postVoiceTaskResult(taskId, body) {
|
|
221
|
+
const r = await this.http.post(`integrations/voice-tasks/${encodeURIComponent(taskId)}/result`, body);
|
|
222
|
+
return r.data;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=bgos-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bgos-api.js","sourceRoot":"","sources":["../src/bgos-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { BgosApi } from "./bgos-api.js";
|
|
2
|
+
import { type VoiceRpcFrame } from "./voice-rpc.js";
|
|
3
|
+
import { type AssistantBoundPayload, type AssistantUnboundPayload, type CallbackResultPayload, type CommandsUpdatedPayload, type InboundClickPayload, type InboundMessagePayload, type PairReadyPayload, type PairingRevokedPayload, type PluginConfig } from "./types.js";
|
|
4
|
+
type EventMap = {
|
|
5
|
+
inbound_message: [InboundMessagePayload];
|
|
6
|
+
inbound_click: [InboundClickPayload];
|
|
7
|
+
commands_updated: [CommandsUpdatedPayload];
|
|
8
|
+
pair_ready: [PairReadyPayload];
|
|
9
|
+
assistant_bound: [AssistantBoundPayload];
|
|
10
|
+
assistant_unbound: [AssistantUnboundPayload];
|
|
11
|
+
pairing_revoked: [PairingRevokedPayload];
|
|
12
|
+
callback_result: [CallbackResultPayload];
|
|
13
|
+
voice_rpc: [VoiceRpcFrame];
|
|
14
|
+
error: [Error];
|
|
15
|
+
/** Socket (re)connected / disconnected, drives heartbeat wsConnected. */
|
|
16
|
+
connect: [];
|
|
17
|
+
disconnect: [];
|
|
18
|
+
/** Manager-level reconnect: adapter refreshes identity + backfills. */
|
|
19
|
+
reconnect: [];
|
|
20
|
+
/** Backfill outcome signals, drive heartbeat lastError (contract C3). */
|
|
21
|
+
backfill_ok: [];
|
|
22
|
+
backfill_error: [Error];
|
|
23
|
+
backfill_storm: [number];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Socket.IO client against BGOS. Handshake passes pairingToken as a query
|
|
27
|
+
* param; backend validates via bcrypt and joins the client to
|
|
28
|
+
* pairing:<id> + every assistant:<id> the pairing owns.
|
|
29
|
+
*
|
|
30
|
+
* Cursor authority is the DISK cursor (bgos_last_id): triggerBackfill reads
|
|
31
|
+
* loadLastId() at call time and the live WS path advances no cursor of its
|
|
32
|
+
* own. Dedupe + saveLastId happen in the inbound handler after the route
|
|
33
|
+
* resolves. Reconnect is handled at the Manager level (socket.io.on) because
|
|
34
|
+
* the Socket does not emit a `reconnect` reserved event in socket.io-client v4.
|
|
35
|
+
*/
|
|
36
|
+
export declare class BgosWs {
|
|
37
|
+
private cfg;
|
|
38
|
+
private readonly api;
|
|
39
|
+
private readonly emitter;
|
|
40
|
+
private socket;
|
|
41
|
+
private reconnectAttempts;
|
|
42
|
+
private manualClose;
|
|
43
|
+
private wsConnectedSince;
|
|
44
|
+
private backfillInFlight;
|
|
45
|
+
private readonly typingThrottle;
|
|
46
|
+
constructor(cfg: PluginConfig, api: BgosApi);
|
|
47
|
+
on<K extends keyof EventMap>(event: K, listener: (...args: EventMap[K]) => void): this;
|
|
48
|
+
off<K extends keyof EventMap>(event: K, listener: (...args: EventMap[K]) => void): this;
|
|
49
|
+
/** ISO timestamp of the current connection, or null when disconnected. */
|
|
50
|
+
get connectedSince(): string | null;
|
|
51
|
+
/** Swap the pairing token (and optionally base URL) for re-pair recovery.
|
|
52
|
+
* Caller reconnects (disconnect + connect) to apply it. */
|
|
53
|
+
updateToken(token: string, baseUrl?: string): void;
|
|
54
|
+
connect(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Backfill missed messages from the DISK cursor. Single-flight: concurrent
|
|
57
|
+
* calls (poll tick racing a reconnect) coalesce onto the same promise.
|
|
58
|
+
*
|
|
59
|
+
* `opts.initial` marks the boot backfill: when the disk cursor is 0 and the
|
|
60
|
+
* pairing already has history, page through it WITHOUT dispatching and seed
|
|
61
|
+
* the cursor to the newest id (cold-start guard), so a fresh install does
|
|
62
|
+
* not replay the entire history as new messages.
|
|
63
|
+
*/
|
|
64
|
+
triggerBackfill(opts?: {
|
|
65
|
+
initial?: boolean;
|
|
66
|
+
}): Promise<void>;
|
|
67
|
+
private runBackfill;
|
|
68
|
+
/**
|
|
69
|
+
* Cold-start seed: page the entire history WITHOUT dispatching, advancing
|
|
70
|
+
* the disk cursor to the newest id. Bounded iterations to guarantee
|
|
71
|
+
* termination even if the backend paginates oddly.
|
|
72
|
+
*/
|
|
73
|
+
private coldStartSeed;
|
|
74
|
+
/**
|
|
75
|
+
* Emit a client-side `typing` WS event (contract C4). Best-effort +
|
|
76
|
+
* throttled to 1 per 3s per chat. Safe on old backends: an unknown WS
|
|
77
|
+
* event is ignored server-side.
|
|
78
|
+
*/
|
|
79
|
+
emitTyping(params: {
|
|
80
|
+
chatId: number;
|
|
81
|
+
assistantId: number;
|
|
82
|
+
}): void;
|
|
83
|
+
disconnect(): void;
|
|
84
|
+
/**
|
|
85
|
+
* Translate the wire-level payload (snake_case) into our camelCase type.
|
|
86
|
+
* Backend already emits camelCase via the helper service, but defensively
|
|
87
|
+
* handle both so we don't drop messages if someone changes the emitter.
|
|
88
|
+
*/
|
|
89
|
+
private normalizeInbound;
|
|
90
|
+
/** Normalize an inbound_click WS payload (camelCase or snake_case). */
|
|
91
|
+
private normalizeInboundClick;
|
|
92
|
+
}
|
|
93
|
+
export {};
|
|
94
|
+
//# sourceMappingURL=bgos-ws.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bgos-ws.d.ts","sourceRoot":"","sources":["../src/bgos-ws.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAEpB,KAAK,QAAQ,GAAG;IACd,eAAe,EAAE,CAAC,qBAAqB,CAAC,CAAC;IACzC,aAAa,EAAE,CAAC,mBAAmB,CAAC,CAAC;IACrC,gBAAgB,EAAE,CAAC,sBAAsB,CAAC,CAAC;IAC3C,UAAU,EAAE,CAAC,gBAAgB,CAAC,CAAC;IAC/B,eAAe,EAAE,CAAC,qBAAqB,CAAC,CAAC;IACzC,iBAAiB,EAAE,CAAC,uBAAuB,CAAC,CAAC;IAC7C,eAAe,EAAE,CAAC,qBAAqB,CAAC,CAAC;IACzC,eAAe,EAAE,CAAC,qBAAqB,CAAC,CAAC;IACzC,SAAS,EAAE,CAAC,aAAa,CAAC,CAAC;IAC3B,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;IACf,yEAAyE;IACzE,OAAO,EAAE,EAAE,CAAC;IACZ,UAAU,EAAE,EAAE,CAAC;IACf,uEAAuE;IACvE,SAAS,EAAE,EAAE,CAAC;IACd,yEAAyE;IACzE,WAAW,EAAE,EAAE,CAAC;IAChB,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC;IACxB,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC;CAC1B,CAAC;AAWF;;;;;;;;;;GAUG;AACH,qBAAa,MAAM;IAUf,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,QAAQ,CAAC,GAAG;IAVtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;gBAGlD,GAAG,EAAE,YAAY,EACR,GAAG,EAAE,OAAO;IAG/B,EAAE,CAAC,CAAC,SAAS,MAAM,QAAQ,EACzB,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GACvC,IAAI;IAKP,GAAG,CAAC,CAAC,SAAS,MAAM,QAAQ,EAC1B,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GACvC,IAAI;IAKP,0EAA0E;IAC1E,IAAI,cAAc,IAAI,MAAM,GAAG,IAAI,CAElC;IAED;gEAC4D;IAC5D,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ5C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoF9B;;;;;;;;OAQG;IACH,eAAe,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAU9C,WAAW;IAmCzB;;;;OAIG;YACW,aAAa;IAoB3B;;;;OAIG;IACH,UAAU,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAejE,UAAU,IAAI,IAAI;IAOlB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAsCxB,uEAAuE;IACvE,OAAO,CAAC,qBAAqB;CA2B9B"}
|