@supportbridge/sdk 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/LICENSE +13 -0
  3. package/README.md +326 -0
  4. package/SECURITY.md +26 -0
  5. package/dist/agent.d.ts +9 -0
  6. package/dist/agent.d.ts.map +1 -0
  7. package/dist/agent.js +73 -0
  8. package/dist/agent.js.map +1 -0
  9. package/dist/client.d.ts +68 -0
  10. package/dist/client.d.ts.map +1 -0
  11. package/dist/client.js +254 -0
  12. package/dist/client.js.map +1 -0
  13. package/dist/context.d.ts +4 -0
  14. package/dist/context.d.ts.map +1 -0
  15. package/dist/context.js +9 -0
  16. package/dist/context.js.map +1 -0
  17. package/dist/control-plane.d.ts +37 -0
  18. package/dist/control-plane.d.ts.map +1 -0
  19. package/dist/control-plane.js +43 -0
  20. package/dist/control-plane.js.map +1 -0
  21. package/dist/doctor.d.ts +17 -0
  22. package/dist/doctor.d.ts.map +1 -0
  23. package/dist/doctor.js +49 -0
  24. package/dist/doctor.js.map +1 -0
  25. package/dist/index.d.ts +30 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +16 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/install.d.ts +42 -0
  30. package/dist/install.d.ts.map +1 -0
  31. package/dist/install.js +215 -0
  32. package/dist/install.js.map +1 -0
  33. package/dist/mcp-app.d.ts +50 -0
  34. package/dist/mcp-app.d.ts.map +1 -0
  35. package/dist/mcp-app.js +44 -0
  36. package/dist/mcp-app.js.map +1 -0
  37. package/dist/mcp.d.ts +44 -0
  38. package/dist/mcp.d.ts.map +1 -0
  39. package/dist/mcp.js +117 -0
  40. package/dist/mcp.js.map +1 -0
  41. package/dist/offer-app.d.ts +41 -0
  42. package/dist/offer-app.d.ts.map +1 -0
  43. package/dist/offer-app.js +21 -0
  44. package/dist/offer-app.js.map +1 -0
  45. package/dist/policy-app.d.ts +41 -0
  46. package/dist/policy-app.d.ts.map +1 -0
  47. package/dist/policy-app.js +49 -0
  48. package/dist/policy-app.js.map +1 -0
  49. package/dist/policy-store.d.ts +79 -0
  50. package/dist/policy-store.d.ts.map +1 -0
  51. package/dist/policy-store.js +137 -0
  52. package/dist/policy-store.js.map +1 -0
  53. package/dist/policy.d.ts +226 -0
  54. package/dist/policy.d.ts.map +1 -0
  55. package/dist/policy.js +420 -0
  56. package/dist/policy.js.map +1 -0
  57. package/dist/sanitize.d.ts +9 -0
  58. package/dist/sanitize.d.ts.map +1 -0
  59. package/dist/sanitize.js +83 -0
  60. package/dist/sanitize.js.map +1 -0
  61. package/dist/state.d.ts +31 -0
  62. package/dist/state.d.ts.map +1 -0
  63. package/dist/state.js +29 -0
  64. package/dist/state.js.map +1 -0
  65. package/dist/transport.d.ts +57 -0
  66. package/dist/transport.d.ts.map +1 -0
  67. package/dist/transport.js +132 -0
  68. package/dist/transport.js.map +1 -0
  69. package/dist/triggers.d.ts +19 -0
  70. package/dist/triggers.d.ts.map +1 -0
  71. package/dist/triggers.js +132 -0
  72. package/dist/triggers.js.map +1 -0
  73. package/dist/types.d.ts +221 -0
  74. package/dist/types.d.ts.map +1 -0
  75. package/dist/types.js +2 -0
  76. package/dist/types.js.map +1 -0
  77. package/docs/policy-engine.md +47 -0
  78. package/docs/telemetry-contract.md +29 -0
  79. package/package.json +53 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,73 @@
1
+ # Changelog
2
+
3
+ ## 0.8.1
4
+
5
+ - Versioned the embedded chat resource URI so MCP hosts refresh the redesigned UI instead of reusing a cached pre-0.8 chat document.
6
+
7
+ ## 0.8.0
8
+
9
+ - Redesigned the embedded support chat with distinct customer/support messages, representative identity, compact mode, quieter system activity, unread indicators, multiline composing, delivery feedback, and responsive styling.
10
+ - Replaced technical Slack identifiers in the customer-facing header with human-readable presence and conversation status.
11
+ - Added explicit close and reopen states, including a control-plane reopen endpoint and MCP App tool.
12
+ - Improved ticket-detail privacy by moving the conversation identifier into an optional details menu.
13
+
14
+ ## 0.7.0
15
+
16
+ - Added `require_acknowledgement`, a non-blocking policy action that returns business data while appending a visible, consent-safe assistance offer.
17
+ - Added explicit pending offer metadata and control-plane lifecycle persistence for pending, presented, accepted, declined, and expired offers.
18
+ - Added the acknowledgement action to the dashboard and natural-language policy compiler.
19
+ - Preserved the existing metadata-only offer and blocking decision modes for backward compatibility.
20
+ - Added optional Slack notifications for new live-help chats and new customer messages in existing chats.
21
+
22
+ ## 0.6.0
23
+
24
+ - Added representative availability as a control-plane policy eligibility condition.
25
+ - Added the mock Sarah representative with Available, Away, and Offline dashboard presence.
26
+ - Added `request_assistance` for accepted sales and customer-success assistance offers.
27
+ - Automatically assigns accepted assistance requests to the policy's representative.
28
+
29
+ # 0.5.0
30
+
31
+ - Added the canonical SupportBridge policy schema, approved field/action registries, deterministic validation and evaluation, nested Boolean conditions, explanations, conflict analysis, decision traces, dry runs, event-loop prevention, and idempotent action execution.
32
+ - Added a vendor-neutral NLP provider contract and deterministic fake compiler for local development and tests.
33
+ - Added approval, immutable version, disable, rollback, diff, test-case, and audit lifecycle primitives.
34
+ - Added the embedded Claude policy-builder MCP App with AI/manual authoring modes, canonical preview, validation, and read-only simulation.
35
+
36
+ ## 0.4.0
37
+
38
+ - Ported the MCP App lifecycle, metadata, session shape, and UI behavior from the known-working `ballyhoogroup/supportbridge` connector.
39
+ - Added the proven `open_support_chat`, `support_get_messages`, `support_send_message`, and `support_end_session` contract.
40
+ - Added preferred-frame resource metadata and the working inline display capability handshake.
41
+ - Added a compatibility fixture and conformance assertions to prevent drift from the working connector.
42
+ - Connected the proven chat lifecycle to the external multi-tenant control plane.
43
+
44
+ ## 0.3.1
45
+
46
+ - Added a model-visible, MCP-App-linked `talk_to_support` tool.
47
+ - Added reopening of an existing ticket by ID so a missing or scrolled-away widget can be rendered again.
48
+ - Ensured new and reopened chats return the state required by the embedded app.
49
+
50
+ ## 0.3.0
51
+
52
+ - Added one-call installation for the official TypeScript MCP SDK.
53
+ - Added automatic support-tool, MCP App resource, chat-handler, policy-sync, and shutdown registration.
54
+ - Added a single shared identity resolver and automatic recent-tool ticket briefs.
55
+ - Added installation capability telemetry, dashboard connection status, and `supportbridge doctor`.
56
+
57
+ ## 0.2.0
58
+
59
+ - Added a portable MCP App resource for embedded SupportBridge live chat.
60
+ - Added ticket creation to `accept_support_offer` when a control-plane client is supplied.
61
+ - Added app-only chat refresh and message handlers with a text fallback for non-App hosts.
62
+
63
+ ## 0.1.0
64
+
65
+ - Added framework-neutral tool-call instrumentation and MCP result adaptation.
66
+ - Added sanitized, bounded telemetry with buffered HTTP delivery.
67
+ - Added argument-match and repeated-failure support triggers.
68
+ - Added blocking support offers with accept, dismiss, and reset state.
69
+ - Added optional agent and model spans with async trace propagation.
70
+ - Added pluggable telemetry transports and trigger-state stores.
71
+ - Added remote policy synchronization and support-chat control-plane client.
72
+ - Added a tenant-scoped vendor control plane with Live Streams, Visitor 360, chat, and policy management.
73
+
package/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2026 SupportBridge
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,326 @@
1
+ # SupportBridge SDK
2
+
3
+ `@supportbridge/sdk` is the external, production-oriented SDK for adding tool-call telemetry, optional agent telemetry, configurable support triggers, deterministic operational policies, and MCP-compatible support experiences to software-company MCP servers.
4
+
5
+ This package is independent from the internal SupportBridge demo. It does not import the demo server, dashboard, database, or test-user implementation.
6
+
7
+ ## What the first release provides
8
+
9
+ - Framework-neutral MCP tool instrumentation
10
+ - Tool name, timing, outcome, request correlation, sanitized arguments, and bounded result summaries
11
+ - Optional agent-run and model-call spans
12
+ - Async-local trace propagation from agent runs into MCP tool events
13
+ - Immediate or non-blocking support-offer triggers
14
+ - Repeated-failure triggers
15
+ - Per-user, per-workspace, per-trace, or always-on trigger scopes
16
+ - Accept, dismiss, and explicit reset decisions
17
+ - Default secret redaction and payload-size limits
18
+ - Batched asynchronous HTTP delivery with bounded retries
19
+ - Queue overflow protection and fail-open behavior
20
+ - Pluggable telemetry transport and trigger-state storage
21
+ - Canonical, versioned policy schema with nested AND/OR/NOT conditions
22
+ - Approved field and action registries with tenant-reference validation
23
+ - Deterministic evaluation, traces, dry runs, conflict detection, and idempotent execution
24
+ - Vendor-neutral natural-language compiler interface and deterministic local fake provider
25
+ - Approval, immutable-version, rollback, and audit lifecycle primitives
26
+ - An interactive MCP policy-builder app for Claude
27
+
28
+ ## Install
29
+
30
+ During local development:
31
+
32
+ ```bash
33
+ npm install ./supportbridge-sdk
34
+ ```
35
+
36
+ After publishing:
37
+
38
+ ```bash
39
+ npm install @supportbridge/sdk
40
+ ```
41
+
42
+ Node.js 20 or newer is required.
43
+
44
+ ## Recommended one-call MCP installation
45
+
46
+ For the official TypeScript MCP SDK, one call installs remote policy synchronization, support decisions, the UI-linked `talk_to_support` tool, the embedded chat app, app-only chat handlers, capability reporting, and graceful shutdown behavior:
47
+
48
+ ```ts
49
+ import { SupportBridge } from "@supportbridge/sdk";
50
+
51
+ const support = SupportBridge.install(server, {
52
+ source: "acme-mcp",
53
+ apiKey: process.env.SUPPORTBRIDGE_API_KEY!,
54
+ identify: context => ({
55
+ userId: context.authInfo.subject,
56
+ workspaceId: context.authInfo.workspaceId,
57
+ traits: { customer: context.authInfo.organizationName }
58
+ })
59
+ });
60
+ ```
61
+
62
+ Use the returned installer to wrap each business tool while keeping the same identity resolver:
63
+
64
+ ```ts
65
+ server.tool(
66
+ "search_companies",
67
+ searchSchema,
68
+ support.instrumentTool("search_companies", searchCompanies)
69
+ );
70
+ ```
71
+
72
+ The wrapper captures bounded telemetry, enforces downloaded support triggers before execution, and retains recent sanitized failures for automatic ticket context. The installation also registers `open_policy_builder` and its embedded interactive app. No support tools or UI resources need to be registered manually.
73
+
74
+ ## Deterministic policy engine
75
+
76
+ Natural language is never executable. A `PolicyNlpProvider` can propose a `CanonicalPolicy`, then deterministic code validates approved fields, operators, events, action parameters, and workspace-scoped references before simulation or publication.
77
+
78
+ ```ts
79
+ import {
80
+ FakePolicyNlpProvider,
81
+ PolicyEngine,
82
+ PolicyRegistry,
83
+ validatePolicy
84
+ } from "@supportbridge/sdk";
85
+
86
+ const provider = new FakePolicyNlpProvider();
87
+ const draft = await provider.compile({
88
+ prompt: "Route urgent enterprise billing conversations to Finance.",
89
+ workspaceId: "acme",
90
+ actorId: "admin_123",
91
+ references: { financeTeamId: "team_finance" }
92
+ });
93
+
94
+ const registry = new PolicyRegistry();
95
+ const validation = validatePolicy(draft.policy, { registry });
96
+ if (!validation.valid) throw new Error("Review the validation errors");
97
+
98
+ const decision = new PolicyEngine(registry).evaluate(
99
+ [{ ...draft.policy, enabled: true, state: "dry_run" }],
100
+ { type: "conversation.created" },
101
+ { customer: { plan: "enterprise" }, conversation: { priority: "urgent" }, message: { classification: "billing" } },
102
+ { now: new Date(), eventId: "evt_1", correlationId: "corr_1", workspaceId: "acme" }
103
+ );
104
+ ```
105
+
106
+ Evaluation produces a decision plan; it never performs actions. Pass a plan to `executeDecisionPlan` with your authorized executor and durable `IdempotencyStore`. See [the policy engine guide](docs/policy-engine.md) for registries, lifecycle, simulations, and production adapters.
107
+
108
+ If the embedded widget is missing or has scrolled out of view, the model calls `open_support_chat` with the existing `session_id`. Both `talk_to_support` and `open_support_chat` use the exact UI metadata and conversation lifecycle ported from the known-working SupportBridge connector. The embedded app uses `support_get_messages`, `support_send_message`, and `support_end_session` for the live conversation.
109
+
110
+ Availability-gated sales and customer-success policies can assign an offer to a representative in the control plane. Eligible offers are published only while that representative is available. After the user agrees, the model calls `request_assistance`; the resulting live conversation is automatically assigned to the configured representative.
111
+
112
+ Verify an installation with:
113
+
114
+ ```bash
115
+ npx supportbridge doctor
116
+ ```
117
+
118
+ Set `SUPPORTBRIDGE_URL` and `SUPPORTBRIDGE_API_KEY` first. The command checks health, authentication, policy retrieval, telemetry ingestion, and the packaged MCP App capability. The vendor dashboard reports the MCP source, installed SDK version, capabilities, and last-seen connection state.
119
+
120
+ ## Capture an MCP tool
121
+
122
+ ```ts
123
+ import { SupportBridgeClient, instrumentMcpTool } from "@supportbridge/sdk";
124
+
125
+ const supportbridge = new SupportBridgeClient({
126
+ source: "acme-mcp",
127
+ endpoint: "https://api.supportbridge.example",
128
+ apiKey: process.env.SUPPORTBRIDGE_API_KEY!,
129
+ triggers: [{
130
+ id: "climate-tech-concierge",
131
+ kind: "argument_match",
132
+ toolName: "list_companies",
133
+ path: "industry",
134
+ operator: "equals",
135
+ value: "Climate Tech",
136
+ action: "block_and_offer",
137
+ oncePer: "user"
138
+ }]
139
+ });
140
+
141
+ const listCompanies = instrumentMcpTool(
142
+ supportbridge,
143
+ "list_companies",
144
+ async args => ({
145
+ content: [{ type: "text", text: "Company results" }],
146
+ structuredContent: { count: 12 }
147
+ }),
148
+ {
149
+ identify: (_args, context) => ({
150
+ userId: context.auth.subject,
151
+ workspaceId: context.auth.workspaceId
152
+ })
153
+ }
154
+ );
155
+ ```
156
+
157
+ When the blocking trigger matches, the vendor handler is not executed. The MCP result contains:
158
+
159
+ ```json
160
+ {
161
+ "isError": true,
162
+ "structuredContent": {
163
+ "support_available": true,
164
+ "support_offer_blocking": true,
165
+ "support_trigger_id": "climate-tech-concierge",
166
+ "accept_tool": "accept_support_offer",
167
+ "decline_tool": "dismiss_support_offer",
168
+ "retry_original_request_after_response": true
169
+ }
170
+ }
171
+ ```
172
+
173
+ For a visible offer that does not withhold the business result, use `action: "require_acknowledgement"`. The SDK preserves the original `content` and `structuredContent`, appends a transparent `LIVE ASSISTANCE AVAILABLE` content block, and includes pending offer state plus the consent-gated accept and decline tool names. This is the recommended cross-host mode when an ordinary metadata-only offer may be omitted by the model.
174
+
175
+ Register the handlers returned by `supportDecisionTools` as MCP tools. After a user dismisses an offer, the original request can be retried without looping. Call `resetSupport` to make that trigger eligible again.
176
+
177
+ ## Embedded support chat (MCP App)
178
+
179
+ `accept_support_offer` can create a durable ticket and open an inline chat in hosts that support the MCP Apps extension. Create the app kit and attach its metadata to the registered accept tool:
180
+
181
+ ```ts
182
+ import {
183
+ createSupportChatApp,
184
+ supportDecisionTools
185
+ } from "@supportbridge/sdk";
186
+
187
+ const supportApp = createSupportChatApp(controlPlane);
188
+ const decisions = supportDecisionTools(
189
+ supportbridge,
190
+ context => identifyUser(context),
191
+ { controlPlane, appMeta: supportApp.toolMeta }
192
+ );
193
+ ```
194
+
195
+ The MCP server must register these pieces using its framework:
196
+
197
+ - `accept_support_offer`, with `supportApp.toolMeta` on the **tool definition**.
198
+ - `dismiss_support_offer` as a normal model-visible tool.
199
+ - `get_support_chat` and `send_support_message` from `supportApp.tools`, with app-only visibility.
200
+ - A resource at `supportApp.resourceUri` whose read callback returns `supportApp.resourceContents()` and whose MIME type is `supportApp.mimeType`.
201
+
202
+ For the official TypeScript MCP Apps SDK, use `registerAppTool` and `registerAppResource` from `@modelcontextprotocol/ext-apps/server`. The critical registration shape is:
203
+
204
+ ```ts
205
+ registerAppTool(server, "accept_support_offer", {
206
+ description: "Open the human support conversation after the user consents.",
207
+ inputSchema: acceptSchema,
208
+ _meta: supportApp.toolMeta
209
+ }, decisions.accept_support_offer);
210
+
211
+ registerAppTool(server, "get_support_chat", {
212
+ inputSchema: getChatSchema,
213
+ _meta: { ui: { resourceUri: supportApp.resourceUri, visibility: ["app"] } }
214
+ }, supportApp.tools.get_support_chat);
215
+
216
+ registerAppTool(server, "send_support_message", {
217
+ inputSchema: sendMessageSchema,
218
+ _meta: { ui: { resourceUri: supportApp.resourceUri, visibility: ["app"] } }
219
+ }, supportApp.tools.send_support_message);
220
+
221
+ registerAppResource(server, "SupportBridge chat", supportApp.resourceUri, {
222
+ mimeType: supportApp.mimeType,
223
+ _meta: supportApp.resourceMeta
224
+ }, async () => supportApp.resourceContents());
225
+ ```
226
+
227
+ The HTML uses the standard `text/html;profile=mcp-app` resource type and MCP Apps JSON-RPC bridge. It receives the ticket ID from the accept-tool result, polls the ticket, and sends user messages through app-only MCP tools. Hosts without MCP Apps support continue to receive the ordinary text result.
228
+
229
+ ## Direct tool instrumentation
230
+
231
+ For frameworks with custom middleware:
232
+
233
+ ```ts
234
+ const result = await supportbridge.instrumentTool(
235
+ {
236
+ toolName: "search_companies",
237
+ arguments: { query: "fintech" },
238
+ identity: { userId: "user_34892", workspaceId: "acme" }
239
+ },
240
+ () => searchCompanies("fintech")
241
+ );
242
+ ```
243
+
244
+ The return value is discriminated by `kind`:
245
+
246
+ - `result`: the vendor tool executed and `value` contains its result.
247
+ - `support_offer`: execution was paused and `offer` contains the support decision payload.
248
+
249
+ ## Agent telemetry
250
+
251
+ ```ts
252
+ import { traceAgentRun } from "@supportbridge/sdk";
253
+
254
+ await traceAgentRun(
255
+ supportbridge,
256
+ {
257
+ agentName: "research-agent",
258
+ identity: { userId: "user_34892", workspaceId: "acme" }
259
+ },
260
+ async span => {
261
+ const startedAt = performance.now();
262
+ const response = await callYourModel();
263
+ span.recordModelCall({
264
+ provider: "your-provider",
265
+ model: "your-model",
266
+ startedAt,
267
+ inputTokens: response.usage.input,
268
+ outputTokens: response.usage.output
269
+ });
270
+ return response;
271
+ }
272
+ );
273
+ ```
274
+
275
+ Tool calls made inside `traceAgentRun` automatically inherit its trace and run identifiers through `AsyncLocalStorage`.
276
+
277
+ ## Privacy defaults
278
+
279
+ The SDK captures sanitized tool arguments and bounded result summaries. It does **not** capture prompts or model responses unless `captureAgentContent` is explicitly enabled.
280
+
281
+ Recognized credential fields are replaced with `[REDACTED]`. Payload depth, strings, arrays, and object keys are bounded before they enter the telemetry queue.
282
+
283
+ ```ts
284
+ privacy: {
285
+ captureToolArguments: true,
286
+ captureToolResponses: true,
287
+ captureAgentContent: false,
288
+ sensitiveKeys: ["customer_access_code"],
289
+ maxStringLength: 1000
290
+ }
291
+ ```
292
+
293
+ Software companies should still document telemetry collection, obtain any required consent, and avoid sending regulated or unnecessary data.
294
+
295
+ ## Reliability model
296
+
297
+ Telemetry is delivered outside the tool execution path. Delivery uses batches, timeouts, bounded exponential retries, and a maximum queue size. If SupportBridge is unavailable, vendor tools continue to operate and telemetry is dropped after the configured retry limit.
298
+
299
+ Call `flush()` before short-lived processes exit and `close()` during graceful shutdown:
300
+
301
+ ```ts
302
+ process.once("SIGTERM", () => void supportbridge.close());
303
+ ```
304
+
305
+ ## Trigger-state storage
306
+
307
+ The default `MemoryTriggerStateStore` is appropriate for local development and a single process. Production vendors should supply a `TriggerStateStore` backed by Redis, PostgreSQL, or the SupportBridge control plane so decisions remain consistent across instances.
308
+
309
+ ## Development
310
+
311
+ From this directory:
312
+
313
+ ```bash
314
+ npm run check
315
+ npm test
316
+ npm run build
317
+ ```
318
+
319
+ The package intentionally has no runtime dependency on a particular MCP or agent framework. Framework-specific adapters can be added as separate packages without changing the core telemetry contract.
320
+
321
+ See [the telemetry contract](docs/telemetry-contract.md) for backend ingestion details and [the security guide](SECURITY.md) before a production deployment.
322
+
323
+ ## Hosted control plane
324
+
325
+ The repository also contains the first vendor-facing control plane in [`control-plane`](control-plane). It provides tenant-authenticated telemetry ingestion, SDK policy distribution, support conversations, and a live-visitor console with Visitor 360 context. See its [deployment and integration guide](control-plane/README.md).
326
+
package/SECURITY.md ADDED
@@ -0,0 +1,26 @@
1
+ # Security and privacy
2
+
3
+ SupportBridge telemetry may contain customer context. Integrators are responsible for choosing what they collect and for meeting their own disclosure, consent, retention, and regulatory obligations.
4
+
5
+ ## Safe defaults
6
+
7
+ - Prompt and model-response capture is disabled by default.
8
+ - Common credential fields and bearer tokens are redacted before queueing.
9
+ - Strings, arrays, object keys, and nesting depth are bounded.
10
+ - Telemetry delivery is fail-open and never intentionally exposes the configured API key in an event.
11
+ - The SDK has no runtime dependencies.
12
+
13
+ Redaction is defense in depth, not a substitute for minimizing data at the integration boundary. Do not pass credentials or regulated data in tool arguments when it is avoidable. Add product-specific field names to `privacy.sensitiveKeys`.
14
+
15
+ ## Deployment recommendations
16
+
17
+ - Send telemetry only to a TLS endpoint you control or trust.
18
+ - Load the SupportBridge API key from a secret manager and rotate it regularly.
19
+ - Use a durable `TriggerStateStore` in multi-instance deployments.
20
+ - Apply least-privilege access and retention controls to the telemetry backend.
21
+ - Review custom result summarizers; they run before the SDK sanitizer.
22
+ - Call `close()` during graceful shutdown to flush queued events.
23
+
24
+ ## Reporting a vulnerability
25
+
26
+ Do not include secrets, customer data, or exploit details in a public issue. Contact the package maintainer through the private security channel configured for the SupportBridge project. A public reporting address will be added before registry publication.
@@ -0,0 +1,9 @@
1
+ import type { SupportBridgeClient } from "./client.js";
2
+ import type { AgentRunOptions, ModelCallOptions } from "./types.js";
3
+ export interface AgentRunSpan {
4
+ readonly traceId: string;
5
+ readonly runId: string;
6
+ recordModelCall(options: ModelCallOptions): void;
7
+ }
8
+ export declare function traceAgentRun<T>(client: SupportBridgeClient, options: AgentRunOptions, operation: (span: AgentRunSpan) => Promise<T> | T): Promise<T>;
9
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAiB,eAAe,EAAkB,gBAAgB,EAAgB,MAAM,YAAY,CAAC;AAEjH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAClD;AAED,wBAAsB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAmC3J"}
package/dist/agent.js ADDED
@@ -0,0 +1,73 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { currentTraceContext, runWithTrace } from "./context.js";
3
+ import { errorDetails, sanitize, sanitizeText } from "./sanitize.js";
4
+ export async function traceAgentRun(client, options, operation) {
5
+ const parent = currentTraceContext();
6
+ const traceId = options.traceId ?? parent?.traceId ?? randomUUID();
7
+ const runId = options.runId ?? randomUUID();
8
+ const spanId = randomUUID();
9
+ const startedAt = performance.now();
10
+ const identity = options.identity ?? parent?.identity;
11
+ const context = {
12
+ traceId, runId, parentSpanId: spanId,
13
+ ...(identity ? { identity } : {})
14
+ };
15
+ const started = {
16
+ ...eventBase(client, options, traceId, runId, spanId), type: "agent_run", agentName: options.agentName, phase: "started"
17
+ };
18
+ client.recordTelemetry(started);
19
+ const span = {
20
+ traceId, runId,
21
+ recordModelCall: model => recordModelCall(client, model, context, spanId)
22
+ };
23
+ try {
24
+ const result = await runWithTrace(context, () => operation(span));
25
+ client.recordTelemetry({
26
+ ...eventBase(client, options, traceId, runId, spanId), type: "agent_run", agentName: options.agentName,
27
+ phase: "completed", outcome: "success", durationMs: elapsed(startedAt)
28
+ });
29
+ return result;
30
+ }
31
+ catch (error) {
32
+ const details = errorDetails(error);
33
+ client.recordTelemetry({
34
+ ...eventBase(client, options, traceId, runId, spanId), type: "agent_run", agentName: options.agentName,
35
+ phase: "completed", outcome: "error", durationMs: elapsed(startedAt),
36
+ ...(details.errorCode ? { errorCode: details.errorCode } : {}), errorMessage: details.errorMessage
37
+ });
38
+ throw error;
39
+ }
40
+ }
41
+ function recordModelCall(client, options, context, parentSpanId) {
42
+ const details = options.error ? errorDetails(options.error) : undefined;
43
+ const outcome = details ? (/timeout|timed out/i.test(details.errorMessage) ? "timeout" : "error") : "success";
44
+ const event = {
45
+ ...client.baseEvent({
46
+ ...(context.identity ? { identity: context.identity } : {}), traceId: context.traceId,
47
+ ...(context.runId ? { runId: context.runId } : {}), spanId: randomUUID(), parentSpanId
48
+ }),
49
+ type: "model_call", provider: options.provider, model: options.model, outcome,
50
+ durationMs: elapsed(options.startedAt ?? performance.now()),
51
+ ...(options.inputTokens !== undefined ? { inputTokens: options.inputTokens } : {}),
52
+ ...(options.outputTokens !== undefined ? { outputTokens: options.outputTokens } : {}),
53
+ ...(options.costUsd !== undefined ? { costUsd: options.costUsd } : {}),
54
+ ...(client.privacy.captureAgentContent && options.prompt !== undefined ? { prompt: sanitize(options.prompt, client.privacy) } : {}),
55
+ ...(client.privacy.captureAgentContent && options.response !== undefined ? { response: sanitize(options.response, client.privacy) } : {}),
56
+ ...(details?.errorCode ? { errorCode: details.errorCode } : {}),
57
+ ...(details?.errorMessage ? { errorMessage: sanitizeText(details.errorMessage, client.privacy) } : {}),
58
+ ...(options.attributes ? { attributes: sanitize(options.attributes, client.privacy) } : {})
59
+ };
60
+ client.recordTelemetry(event);
61
+ }
62
+ function eventBase(client, options, traceId, runId, spanId) {
63
+ return {
64
+ ...client.baseEvent({
65
+ ...(options.identity ? { identity: options.identity } : {}), traceId, runId, spanId
66
+ }),
67
+ ...(options.attributes ? { attributes: sanitize(options.attributes, client.privacy) } : {})
68
+ };
69
+ }
70
+ function elapsed(startedAt) {
71
+ return Math.max(0, Math.round((performance.now() - startedAt) * 100) / 100);
72
+ }
73
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import { type TriggerStateStore } from "./state.js";
2
+ import { TriggerEngine } from "./triggers.js";
3
+ import { type BufferedTransportOptions, type HttpTransportOptions, type TelemetryTransport } from "./transport.js";
4
+ import type { InstrumentedToolResult, JsonValue, PrivacyOptions, ResolvedPrivacyOptions, SupportBrief, SupportDecision, SupportIdentity, SupportOffer, SupportTrigger, TelemetryEvent, TelemetryEventBase, ToolInvocation, ToolOutcome } from "./types.js";
5
+ import type { PolicyDecisionPlan, PolicyEvaluationContext } from "./policy.js";
6
+ export interface SupportBridgeClientOptions {
7
+ source: string;
8
+ environment?: string;
9
+ serviceVersion?: string;
10
+ endpoint?: string;
11
+ apiKey?: string;
12
+ transport?: TelemetryTransport;
13
+ http?: Omit<HttpTransportOptions, "endpoint" | "apiKey">;
14
+ buffer?: BufferedTransportOptions;
15
+ privacy?: PrivacyOptions;
16
+ triggers?: SupportTrigger[];
17
+ triggerState?: TriggerStateStore;
18
+ summarizeResult?: (result: unknown) => unknown;
19
+ }
20
+ export interface InstrumentToolOptions<TResult> {
21
+ summarizeResult?: (result: TResult) => unknown;
22
+ classifyResult?: (result: TResult) => ToolOutcome;
23
+ }
24
+ export declare class SupportBridgeToolError extends Error {
25
+ readonly supportOffer?: SupportOffer;
26
+ readonly original: unknown;
27
+ constructor(original: unknown, supportOffer?: SupportOffer);
28
+ }
29
+ export declare class SupportBridgeClient {
30
+ readonly privacy: ResolvedPrivacyOptions;
31
+ readonly triggers: TriggerEngine;
32
+ private readonly delivery;
33
+ private readonly source;
34
+ private readonly environment;
35
+ private readonly serviceVersion;
36
+ private readonly defaultSummarizer;
37
+ private readonly recentTools;
38
+ constructor(options: SupportBridgeClientOptions);
39
+ instrumentTool<TArguments, TResult>(invocation: ToolInvocation<TArguments>, handler: () => Promise<TResult> | TResult, options?: InstrumentToolOptions<TResult>): Promise<InstrumentedToolResult<TResult>>;
40
+ wrapTool<TArguments, TResult>(toolName: string, handler: (args: TArguments) => Promise<TResult> | TResult, identify: (args: TArguments) => SupportIdentity | undefined, options?: InstrumentToolOptions<TResult>): (args: TArguments) => Promise<InstrumentedToolResult<TResult>>;
41
+ decideSupport(triggerId: string, identity: SupportIdentity | undefined, decision: SupportDecision, traceId?: string): Promise<void>;
42
+ resetSupport(triggerId: string, identity: SupportIdentity | undefined, traceId?: string): Promise<void>;
43
+ markSupportPresented(triggerId: string, identity: SupportIdentity | undefined, traceId?: string): void;
44
+ markSupportExpired(triggerId: string, identity: SupportIdentity | undefined, traceId?: string): void;
45
+ replaceTriggers(triggers: readonly SupportTrigger[]): void;
46
+ recordTelemetry(event: TelemetryEvent): void;
47
+ recordDiagnostic(code: "installation_verified" | "doctor_check", message: string, capabilities?: Record<string, JsonValue>): void;
48
+ recordPolicyEvaluation(plan: PolicyDecisionPlan, context: PolicyEvaluationContext, identity?: SupportIdentity): void;
49
+ buildSupportBrief(identity: SupportIdentity, fallbackIssue?: string): SupportBrief;
50
+ flush(): Promise<void>;
51
+ close(): Promise<void>;
52
+ get pendingTelemetryCount(): number;
53
+ baseEvent(fields?: {
54
+ identity?: SupportIdentity;
55
+ traceId?: string;
56
+ runId?: string;
57
+ spanId?: string;
58
+ parentSpanId?: string;
59
+ }): TelemetryEventBase;
60
+ private normalizeInvocation;
61
+ private captureTool;
62
+ private captureSupportDecision;
63
+ private eventBase;
64
+ private summarize;
65
+ private telemetryIdentity;
66
+ private telemetryAttributes;
67
+ }
68
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}