@nexalink/carecompass-sdk 0.4.0-beta.15 → 0.5.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.
@@ -1,13 +1,35 @@
1
1
  import React from "react";
2
- import { type CareCompassContext, type CareCompassCoreEvent, type CareCompassMessage } from "./core.js";
2
+ import { type CareCompassContext, type CareCompassCore, type CareCompassCoreEvent, type CareCompassCoreOptions, type CareCompassCoreSnapshot, type CareCompassMessage, type CareCompassSendMessageOptions } from "./core.js";
3
+ import type { CareCompassRuntimeTokenProvider } from "./client.js";
3
4
  import type { CareCompassConfig } from "./schema.js";
5
+ import type { CareCompassAuditListener, CareCompassSafetyListener } from "./compliance.js";
4
6
  export type CareCompassChatProps = {
5
7
  config: CareCompassConfig;
6
8
  initialContext?: CareCompassContext;
9
+ onAuditEvent?: CareCompassAuditListener;
7
10
  onEvent?: (event: CareCompassCoreEvent) => void;
11
+ onSafetyEvent?: CareCompassSafetyListener;
8
12
  pollIntervalMs?: number;
9
13
  renderMessage?: (message: CareCompassMessage) => React.ReactNode;
10
14
  retryLabel?: string;
15
+ runtimeTokenProvider?: CareCompassRuntimeTokenProvider;
11
16
  };
12
- export declare function CareCompassChat({ config, initialContext, onEvent, pollIntervalMs, renderMessage, retryLabel, }: CareCompassChatProps): import("react/jsx-runtime").JSX.Element;
17
+ /** Options for the headless React hook. Keep object-valued options stable with
18
+ * `useMemo` when the calling component rerenders. */
19
+ export type UseCareCompassOptions = CareCompassCoreOptions;
20
+ export type CareCompassReactController = {
21
+ core: CareCompassCore;
22
+ snapshot: CareCompassCoreSnapshot;
23
+ sendMessage: (prompt: string, options?: CareCompassSendMessageOptions) => Promise<CareCompassCoreSnapshot>;
24
+ streamMessage: CareCompassCore["streamMessage"];
25
+ retryLast: CareCompassCore["retryLast"];
26
+ reset: CareCompassCore["reset"];
27
+ setContext: CareCompassCore["setContext"];
28
+ };
29
+ /**
30
+ * React adapter for the headless CareCompass core. It owns the core lifecycle
31
+ * and subscribes React to its snapshots, leaving hosts free to render any UI.
32
+ */
33
+ export declare function useCareCompass(config: CareCompassConfig, options?: UseCareCompassOptions): CareCompassReactController;
34
+ export declare function CareCompassChat({ config, initialContext, onAuditEvent, onEvent, onSafetyEvent, pollIntervalMs, renderMessage, retryLabel, runtimeTokenProvider, }: CareCompassChatProps): React.JSX.Element;
13
35
  export declare const CareCompassEmbed: typeof CareCompassChat;
package/dist/component.js CHANGED
@@ -26,11 +26,68 @@ class CareCompassErrorBoundary extends React.Component {
26
26
  return this.props.children;
27
27
  }
28
28
  }
29
- function CareCompassChatContent({ config, initialContext, onEvent, telemetry, pollIntervalMs = 1500, renderMessage, retryLabel = "Retry", }) {
29
+ /**
30
+ * React adapter for the headless CareCompass core. It owns the core lifecycle
31
+ * and subscribes React to its snapshots, leaving hosts free to render any UI.
32
+ */
33
+ export function useCareCompass(config, options = {}) {
34
+ const { compliance, fetcher, initialContext, now, onAuditEvent, onSafetyEvent, pollIntervalMs, runtimeTokenProvider, timeoutMs, } = options;
30
35
  const core = React.useMemo(() => createCareCompassCore(config, {
36
+ compliance,
37
+ fetcher,
31
38
  initialContext,
39
+ now,
40
+ onAuditEvent,
41
+ onSafetyEvent,
32
42
  pollIntervalMs,
33
- }), [config, initialContext, pollIntervalMs]);
43
+ runtimeTokenProvider,
44
+ timeoutMs,
45
+ }), [
46
+ compliance,
47
+ config,
48
+ fetcher,
49
+ initialContext,
50
+ now,
51
+ onAuditEvent,
52
+ onSafetyEvent,
53
+ pollIntervalMs,
54
+ runtimeTokenProvider,
55
+ timeoutMs,
56
+ ]);
57
+ const [snapshot, setSnapshot] = React.useState(() => core.getSnapshot());
58
+ React.useEffect(() => {
59
+ const unsubscribe = core.subscribe(setSnapshot);
60
+ setSnapshot(core.getSnapshot());
61
+ return () => {
62
+ unsubscribe();
63
+ core.dispose();
64
+ };
65
+ }, [core]);
66
+ return React.useMemo(() => ({
67
+ core,
68
+ snapshot,
69
+ sendMessage: core.sendMessage,
70
+ streamMessage: core.streamMessage,
71
+ retryLast: core.retryLast,
72
+ reset: core.reset,
73
+ setContext: core.setContext,
74
+ }), [core, snapshot]);
75
+ }
76
+ function CareCompassChatContent({ config, initialContext, onAuditEvent, onEvent, onSafetyEvent, telemetry, pollIntervalMs = 1500, renderMessage, retryLabel = "Retry", runtimeTokenProvider, }) {
77
+ const core = React.useMemo(() => createCareCompassCore(config, {
78
+ initialContext,
79
+ onAuditEvent,
80
+ onSafetyEvent,
81
+ pollIntervalMs,
82
+ runtimeTokenProvider,
83
+ }), [
84
+ config,
85
+ initialContext,
86
+ onAuditEvent,
87
+ onSafetyEvent,
88
+ pollIntervalMs,
89
+ runtimeTokenProvider,
90
+ ]);
34
91
  const [snapshot, setSnapshot] = React.useState(() => core.getSnapshot());
35
92
  const [input, setInput] = React.useState("");
36
93
  React.useEffect(() => {
@@ -51,6 +108,7 @@ function CareCompassChatContent({ config, initialContext, onEvent, telemetry, po
51
108
  return;
52
109
  setInput("");
53
110
  try {
111
+ core.recordWidgetAction();
54
112
  for await (const coreEvent of core.streamMessage(prompt)) {
55
113
  onEvent?.(coreEvent);
56
114
  }
@@ -62,6 +120,7 @@ function CareCompassChatContent({ config, initialContext, onEvent, telemetry, po
62
120
  }
63
121
  async function retryMessage() {
64
122
  try {
123
+ core.recordWidgetAction();
65
124
  await core.retryLast();
66
125
  }
67
126
  catch {
@@ -154,10 +213,10 @@ function CareCompassChatContent({ config, initialContext, onEvent, telemetry, po
154
213
  padding: "4px 8px",
155
214
  }, type: "button", children: retryLabel })) : null] })) : null, _jsx("div", { style: { fontSize: 11, opacity: 0.7 }, children: config.labels.disclaimer })] })] }));
156
215
  }
157
- export function CareCompassChat({ config, initialContext, onEvent, pollIntervalMs = 1500, renderMessage, retryLabel, }) {
216
+ export function CareCompassChat({ config, initialContext, onAuditEvent, onEvent, onSafetyEvent, pollIntervalMs = 1500, renderMessage, retryLabel, runtimeTokenProvider, }) {
158
217
  // Telemetry is scoped to the validated public config; no per-message content
159
218
  // is passed through this component-level telemetry object.
160
219
  const telemetry = React.useMemo(() => createCareCompassTelemetry(config), [config]);
161
- return (_jsx(CareCompassErrorBoundary, { config: config, telemetry: telemetry, children: _jsx(CareCompassChatContent, { config: config, initialContext: initialContext, onEvent: onEvent, pollIntervalMs: pollIntervalMs, renderMessage: renderMessage, retryLabel: retryLabel, telemetry: telemetry }) }));
220
+ return (_jsx(CareCompassErrorBoundary, { config: config, telemetry: telemetry, children: _jsx(CareCompassChatContent, { config: config, initialContext: initialContext, onAuditEvent: onAuditEvent, onEvent: onEvent, onSafetyEvent: onSafetyEvent, pollIntervalMs: pollIntervalMs, renderMessage: renderMessage, retryLabel: retryLabel, runtimeTokenProvider: runtimeTokenProvider, telemetry: telemetry }) }));
162
221
  }
163
222
  export const CareCompassEmbed = CareCompassChat;
package/dist/core.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { type CareCompassStatusResponse } from "./client.js";
1
+ import { type CareCompassRuntimeTokenProvider, type CareCompassStatusResponse, type CareCompassWorkflowId } from "./client.js";
2
+ import { type CareCompassAuditEvent, type CareCompassAuditListener, type CareCompassComplianceRuntimeOptions, type CareCompassSafetyDecision, type CareCompassSafetyListener } from "./compliance.js";
2
3
  import type { CareCompassConfig } from "./schema.js";
3
4
  type Fetcher = typeof fetch;
4
5
  export type CareCompassContext = Record<string, unknown>;
@@ -8,15 +9,18 @@ export type CareCompassMessage = {
8
9
  text: string;
9
10
  createdAt: number;
10
11
  status: "complete" | "failed" | "pending";
12
+ retrieval?: CareCompassStatusResponse["retrieval"];
11
13
  };
12
14
  export type CareCompassLifecyclePhase = "idle" | "submitting" | "streaming" | "complete" | "error" | "disposed";
13
- export type CareCompassCoreErrorCode = "request_failed" | "timeout" | "disposed";
15
+ export type CareCompassCoreErrorCode = "request_failed" | "safety_blocked" | "timeout" | "disposed";
14
16
  export type CareCompassCoreError = {
15
17
  code: CareCompassCoreErrorCode;
16
18
  message: string;
17
19
  };
18
20
  export type CareCompassRetryMetadata = {
19
21
  prompt: string;
22
+ requestId?: string;
23
+ workflow?: CareCompassWorkflowId;
20
24
  context: CareCompassContext;
21
25
  attempts: number;
22
26
  };
@@ -55,18 +59,31 @@ export type CareCompassCoreEvent = {
55
59
  snapshot: CareCompassCoreSnapshot;
56
60
  };
57
61
  export type CareCompassCoreOptions = {
62
+ compliance?: CareCompassComplianceRuntimeOptions;
58
63
  fetcher?: Fetcher;
59
64
  initialContext?: CareCompassContext;
60
65
  now?: () => number;
66
+ onAuditEvent?: CareCompassAuditListener;
67
+ onSafetyEvent?: CareCompassSafetyListener;
61
68
  pollIntervalMs?: number;
69
+ runtimeTokenProvider?: CareCompassRuntimeTokenProvider;
62
70
  timeoutMs?: number;
63
71
  };
64
72
  export type CareCompassSendMessageOptions = {
73
+ /** Reuse this value only when retrying the same hosted submission. */
74
+ requestId?: string;
75
+ workflow?: CareCompassWorkflowId;
65
76
  context?: CareCompassContext;
66
77
  };
67
78
  export type CareCompassCore = {
79
+ exportAuditTrail: () => CareCompassAuditEvent[];
68
80
  getSnapshot: () => CareCompassCoreSnapshot;
81
+ recordSafetyDecision: (decision: Exclude<CareCompassSafetyDecision, "redacted" | "blocked">, source?: "tool_call" | "widget_action") => void;
82
+ recordToolCall: (outcome?: "completed" | "failed") => void;
83
+ recordWidgetAction: (outcome?: "recorded" | "completed") => void;
69
84
  subscribe: (listener: (snapshot: CareCompassCoreSnapshot) => void) => () => void;
85
+ subscribeAudit: (listener: CareCompassAuditListener) => () => void;
86
+ subscribeSafety: (listener: CareCompassSafetyListener) => () => void;
70
87
  setContext: (context: CareCompassContext | ((current: CareCompassContext) => CareCompassContext)) => void;
71
88
  sendMessage: (prompt: string, options?: CareCompassSendMessageOptions) => Promise<CareCompassCoreSnapshot>;
72
89
  streamMessage: (prompt: string, options?: CareCompassSendMessageOptions) => AsyncIterable<CareCompassCoreEvent>;
package/dist/core.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createCareCompassClient, } from "./client.js";
2
+ import { phiSummary, resolveCareCompassCompliancePolicy, sanitizeCareCompassValue, } from "./compliance.js";
2
3
  const sleep = (durationMs) => new Promise((resolve) => setTimeout(resolve, durationMs));
3
4
  const errorFrom = (error, code = "request_failed") => ({
4
5
  code,
@@ -11,7 +12,16 @@ export function createCareCompassCore(config, options = {}) {
11
12
  const client = createCareCompassClient(config, {
12
13
  fetcher: options.fetcher,
13
14
  now,
15
+ runtimeTokenProvider: options.runtimeTokenProvider,
14
16
  });
17
+ const compliancePolicy = resolveCareCompassCompliancePolicy(config.compliance);
18
+ const auditEvents = [];
19
+ const auditListeners = new Set();
20
+ const safetyListeners = new Set();
21
+ if (options.onAuditEvent)
22
+ auditListeners.add(options.onAuditEvent);
23
+ if (options.onSafetyEvent)
24
+ safetyListeners.add(options.onSafetyEvent);
15
25
  const listeners = new Set();
16
26
  let sequence = 0;
17
27
  let disposed = false;
@@ -30,6 +40,44 @@ export function createCareCompassCore(config, options = {}) {
30
40
  },
31
41
  ];
32
42
  const nextId = (prefix) => `${prefix}-${now()}-${++sequence}`;
43
+ const emitAudit = (type, outcome, source, matches = []) => {
44
+ if (!compliancePolicy.auditEnabled)
45
+ return;
46
+ const auditEvent = {
47
+ id: nextId("audit"),
48
+ occurredAt: now(),
49
+ outcome,
50
+ phi: phiSummary(matches),
51
+ ...(source ? { source } : {}),
52
+ type,
53
+ };
54
+ auditEvents.push(auditEvent);
55
+ for (const listener of auditListeners)
56
+ listener(auditEvent);
57
+ };
58
+ const emitSafety = (decision, source, matches = []) => {
59
+ const safetyEvent = {
60
+ decision,
61
+ occurredAt: now(),
62
+ phi: phiSummary(matches),
63
+ source,
64
+ };
65
+ for (const listener of safetyListeners)
66
+ listener(safetyEvent);
67
+ emitAudit("safety_decision", decision === "policy_sensitive" ? "recorded" : decision, source, matches);
68
+ };
69
+ const applyPhiPolicy = (value, source) => {
70
+ const sanitized = sanitizeCareCompassValue(value, source, compliancePolicy, options.compliance?.phi);
71
+ if (sanitized.matches.length === 0)
72
+ return sanitized;
73
+ const decision = compliancePolicy.phiAction === "block"
74
+ ? "blocked"
75
+ : compliancePolicy.phiAction === "redact"
76
+ ? "redacted"
77
+ : "policy_sensitive";
78
+ emitSafety(decision, source, sanitized.matches);
79
+ return sanitized;
80
+ };
33
81
  const getSnapshot = () => ({
34
82
  messages: messages.map((message) => ({ ...message })),
35
83
  phase,
@@ -40,6 +88,8 @@ export function createCareCompassCore(config, options = {}) {
40
88
  retry: retry
41
89
  ? {
42
90
  prompt: retry.prompt,
91
+ requestId: retry.requestId,
92
+ workflow: retry.workflow,
43
93
  context: { ...retry.context },
44
94
  attempts: retry.attempts,
45
95
  }
@@ -56,6 +106,7 @@ export function createCareCompassCore(config, options = {}) {
56
106
  error = coreError;
57
107
  phase = disposed ? "disposed" : "error";
58
108
  activeJobId = null;
109
+ emitAudit("error", "failed");
59
110
  notify();
60
111
  return event({ type: "error", error: coreError });
61
112
  };
@@ -72,14 +123,33 @@ export function createCareCompassCore(config, options = {}) {
72
123
  const prompt = promptInput.trim();
73
124
  if (!prompt)
74
125
  return;
75
- const requestContext = {
126
+ const protectedPrompt = applyPhiPolicy(prompt, "message");
127
+ const protectedContext = applyPhiPolicy({
76
128
  ...context,
77
129
  ...(sendOptions.context ?? {}),
78
- };
130
+ }, "context");
131
+ if (compliancePolicy.phiAction === "block" &&
132
+ (protectedPrompt.matches.length > 0 ||
133
+ protectedContext.matches.length > 0)) {
134
+ emitAudit("message", "blocked", "message", protectedPrompt.matches);
135
+ const blocked = {
136
+ code: "safety_blocked",
137
+ message: "CareCompass blocked this request because detectable PHI is not allowed in strict compliance mode.",
138
+ };
139
+ retry = null;
140
+ yield fail(blocked);
141
+ throw new Error(blocked.message);
142
+ }
143
+ const requestContext = protectedContext.value;
144
+ const protectedPromptValue = protectedPrompt.value;
145
+ const requestId = sendOptions.requestId ??
146
+ (typeof globalThis.crypto?.randomUUID === "function"
147
+ ? globalThis.crypto.randomUUID()
148
+ : nextId("request"));
79
149
  const userMessage = {
80
150
  id: nextId("user"),
81
151
  role: "user",
82
- text: prompt,
152
+ text: protectedPromptValue,
83
153
  createdAt: now(),
84
154
  status: "complete",
85
155
  };
@@ -89,12 +159,18 @@ export function createCareCompassCore(config, options = {}) {
89
159
  activeJobId = null;
90
160
  retry = null;
91
161
  notify();
162
+ emitAudit("message", protectedPrompt.matches.length > 0 &&
163
+ compliancePolicy.phiAction === "redact"
164
+ ? "redacted"
165
+ : "submitted", "message", protectedPrompt.matches);
92
166
  yield event({ type: "message_submitted", message: userMessage });
93
167
  const startedAt = now();
94
168
  let failureAlreadyCaptured = false;
95
169
  try {
96
170
  const { jobId } = await client.ask({
97
- prompt,
171
+ prompt: protectedPromptValue,
172
+ requestId,
173
+ workflow: sendOptions.workflow,
98
174
  userContext: requestContext,
99
175
  });
100
176
  activeJobId = jobId;
@@ -104,12 +180,25 @@ export function createCareCompassCore(config, options = {}) {
104
180
  const status = await client.status(jobId);
105
181
  yield event({ type: "status", jobId, status: status.status });
106
182
  if (status.status === "complete" && status.result) {
183
+ const protectedResponse = applyPhiPolicy(status.result, "response");
184
+ if (compliancePolicy.phiAction === "block" &&
185
+ protectedResponse.matches.length > 0) {
186
+ const blocked = {
187
+ code: "safety_blocked",
188
+ message: "CareCompass blocked a response because detectable PHI is not allowed in strict compliance mode.",
189
+ };
190
+ retry = null;
191
+ yield fail(blocked);
192
+ failureAlreadyCaptured = true;
193
+ throw new Error(blocked.message);
194
+ }
107
195
  const assistantMessage = {
108
196
  id: nextId("assistant"),
109
197
  role: "assistant",
110
- text: status.result,
198
+ text: protectedResponse.value,
111
199
  createdAt: now(),
112
200
  status: "complete",
201
+ retrieval: status.retrieval,
113
202
  };
114
203
  messages = [...messages, assistantMessage];
115
204
  phase = "complete";
@@ -117,6 +206,10 @@ export function createCareCompassCore(config, options = {}) {
117
206
  activeJobId = null;
118
207
  retry = null;
119
208
  notify();
209
+ emitAudit("message", protectedResponse.matches.length > 0 &&
210
+ compliancePolicy.phiAction === "redact"
211
+ ? "redacted"
212
+ : "completed", "response", protectedResponse.matches);
120
213
  yield event({
121
214
  type: "message_completed",
122
215
  message: assistantMessage,
@@ -125,7 +218,12 @@ export function createCareCompassCore(config, options = {}) {
125
218
  }
126
219
  if (status.status === "failed") {
127
220
  const failed = errorFrom(new Error(status.result ?? config.labels.errorMessage));
128
- retry = { prompt, context: requestContext, attempts: 0 };
221
+ retry = {
222
+ prompt: protectedPromptValue,
223
+ workflow: sendOptions.workflow,
224
+ context: requestContext,
225
+ attempts: 0,
226
+ };
129
227
  yield fail(failed);
130
228
  failureAlreadyCaptured = true;
131
229
  throw new Error(failed.message);
@@ -135,7 +233,13 @@ export function createCareCompassCore(config, options = {}) {
135
233
  }
136
234
  client.recordInferenceTimeout(jobId, now() - startedAt);
137
235
  const timedOut = errorFrom(new Error("CareCompass request timed out."), "timeout");
138
- retry = { prompt, context: requestContext, attempts: 0 };
236
+ retry = {
237
+ prompt: protectedPromptValue,
238
+ requestId,
239
+ workflow: sendOptions.workflow,
240
+ context: requestContext,
241
+ attempts: 0,
242
+ };
139
243
  yield fail(timedOut);
140
244
  failureAlreadyCaptured = true;
141
245
  throw new Error(timedOut.message);
@@ -143,20 +247,44 @@ export function createCareCompassCore(config, options = {}) {
143
247
  catch (caught) {
144
248
  if (failureAlreadyCaptured)
145
249
  throw caught;
146
- retry = { prompt, context: requestContext, attempts: 0 };
250
+ retry = {
251
+ prompt: protectedPromptValue,
252
+ requestId,
253
+ workflow: sendOptions.workflow,
254
+ context: requestContext,
255
+ attempts: 0,
256
+ };
147
257
  const requestError = errorFrom(caught);
148
258
  yield fail(requestError);
149
259
  throw caught instanceof Error ? caught : new Error(requestError.message);
150
260
  }
151
261
  }
152
262
  return {
263
+ exportAuditTrail: () => auditEvents.map((auditEvent) => ({
264
+ ...auditEvent,
265
+ phi: {
266
+ categories: [...auditEvent.phi.categories],
267
+ count: auditEvent.phi.count,
268
+ },
269
+ })),
153
270
  getSnapshot,
271
+ recordSafetyDecision: (decision, source = "tool_call") => emitSafety(decision, source),
272
+ recordToolCall: (outcome = "completed") => emitAudit("tool_call", outcome, "tool_call"),
273
+ recordWidgetAction: (outcome = "recorded") => emitAudit("widget_action", outcome, "widget_action"),
154
274
  subscribe: (listener) => {
155
275
  listeners.add(listener);
156
276
  return () => {
157
277
  listeners.delete(listener);
158
278
  };
159
279
  },
280
+ subscribeAudit: (listener) => {
281
+ auditListeners.add(listener);
282
+ return () => auditListeners.delete(listener);
283
+ },
284
+ subscribeSafety: (listener) => {
285
+ safetyListeners.add(listener);
286
+ return () => safetyListeners.delete(listener);
287
+ },
160
288
  setContext: (nextContext) => {
161
289
  ensureAvailable();
162
290
  context =
@@ -206,10 +334,14 @@ export function createCareCompassCore(config, options = {}) {
206
334
  phase = "disposed";
207
335
  activeJobId = null;
208
336
  listeners.clear();
337
+ auditListeners.clear();
338
+ safetyListeners.clear();
209
339
  },
210
340
  };
211
341
  async function streamRetry(retryRequest) {
212
342
  const iterator = streamMessage(retryRequest.prompt, {
343
+ requestId: retryRequest.requestId,
344
+ workflow: retryRequest.workflow,
213
345
  context: retryRequest.context,
214
346
  })[Symbol.asyncIterator]();
215
347
  while (!(await iterator.next()).done) {
package/dist/index.d.ts CHANGED
@@ -1,13 +1,19 @@
1
1
  export { createCareCompassClient } from "./client.js";
2
- export type { CareCompassAskRequest, CareCompassAskResponse, CareCompassStatusResponse, } from "./client.js";
3
- export { CareCompassChat, CareCompassEmbed } from "./component.js";
4
- export type { CareCompassChatProps } from "./component.js";
2
+ export type { CareCompassAskRequest, CareCompassAskResponse, CareCompassClientOptions, CareCompassRetrievalMetadata, CareCompassRetrievalReference, CareCompassRuntimeTokenProvider, CareCompassRuntimeTokenRequest, CareCompassStatusResponse, CareCompassWorkflowId, } from "./client.js";
3
+ export { CareCompassChat, CareCompassEmbed, useCareCompass, } from "./component.js";
4
+ export type { CareCompassChatProps, CareCompassReactController, UseCareCompassOptions, } from "./component.js";
5
5
  export { createCareCompassCore } from "./core.js";
6
6
  export type { CareCompassContext, CareCompassCore, CareCompassCoreError, CareCompassCoreErrorCode, CareCompassCoreEvent, CareCompassCoreOptions, CareCompassCoreSnapshot, CareCompassLifecyclePhase, CareCompassMessage, CareCompassRetryMetadata, CareCompassSendMessageOptions, } from "./core.js";
7
+ export { CARECOMPASS_RCM_SYNTHETIC_DEMO, createRcmCodingWorkflow, RcmCodingAssistant, } from "./rcm.js";
8
+ export type { RcmCodeRecommendation, RcmCodeSystem, RcmCodingAssistanceInput, RcmCodingAssistanceResult, RcmCodingAssistantProps, RcmCodingWorkflow, RcmCodingWorkflowOptions, RcmConfidence, RcmCustomerRules, RcmPolicyReference, RcmPolicyRetriever, RcmReviewDisposition, } from "./rcm.js";
7
9
  export { mountCareCompass } from "./mount.js";
10
+ export { CARECOMPASS_ELEMENT_TAG, defineCareCompassElement, } from "./web-component.js";
11
+ export type { CareCompassWebComponentElement } from "./web-component.js";
8
12
  export { generateCareCompassIframeSnippet, generateCareCompassSnippet, } from "./snippet.js";
9
- export { careCompassApiBaseUrlSchema, careCompassConfigSchema, createDefaultCareCompassConfig, validateCareCompassConfig, } from "./schema.js";
10
- export type { CareCompassConfig, CareCompassConfigInput, CareCompassLabels, CareCompassPromptConfig, CareCompassTheme, CareCompassValidationResult, } from "./schema.js";
13
+ export { careCompassApiBaseUrlSchema, careCompassComplianceConfigSchema, careCompassConfigSchema, careCompassFeatureFlagsSchema, careCompassModelConfigSchema, createDefaultCareCompassConfig, validateCareCompassConfig, } from "./schema.js";
14
+ export type { CareCompassComplianceConfig, CareCompassConfig, CareCompassConfigInput, CareCompassFeatureFlags, CareCompassLabels, CareCompassModelConfig, CareCompassPromptConfig, CareCompassTheme, CareCompassValidationResult, } from "./schema.js";
15
+ export { CARECOMPASS_COMPLIANCE_PRESETS, detectCareCompassPhi, redactCareCompassPhi, resolveCareCompassCompliancePolicy, } from "./compliance.js";
16
+ export type { CareCompassAuditEvent, CareCompassAuditEventType, CareCompassAuditListener, CareCompassAuditOutcome, CareCompassAuditSource, CareCompassCompliancePolicy, CareCompassCompliancePreset, CareCompassComplianceRuntimeOptions, CareCompassPhiAction, CareCompassPhiCategory, CareCompassPhiDetectionContext, CareCompassPhiDetector, CareCompassPhiHooks, CareCompassPhiMatch, CareCompassPhiRedactor, CareCompassPhiSource, CareCompassSafetyDecision, CareCompassSafetyEvent, CareCompassSafetyListener, } from "./compliance.js";
11
17
  export { CARECOMPASS_TELEMETRY_ERROR_CODES, CARECOMPASS_TELEMETRY_EVENTS, careCompassTelemetryDurationBucket, createCareCompassCliTelemetry, createCareCompassTelemetry, } from "./telemetry.js";
12
18
  export type { CareCompassTelemetry, CareCompassTelemetryCaptureOptions, CareCompassTelemetryDurationBucket, CareCompassTelemetryErrorCode, CareCompassTelemetryEvent, CareCompassTelemetryFailureCategory, } from "./telemetry.js";
13
19
  export { CARECOMPASS_COMPONENT_VERSION, CARECOMPASS_SDK_VERSION, CARECOMPASS_TELEMETRY_CONTRACT_VERSION, } from "./version.js";
package/dist/index.js CHANGED
@@ -1,8 +1,11 @@
1
1
  export { createCareCompassClient } from "./client.js";
2
- export { CareCompassChat, CareCompassEmbed } from "./component.js";
2
+ export { CareCompassChat, CareCompassEmbed, useCareCompass, } from "./component.js";
3
3
  export { createCareCompassCore } from "./core.js";
4
+ export { CARECOMPASS_RCM_SYNTHETIC_DEMO, createRcmCodingWorkflow, RcmCodingAssistant, } from "./rcm.js";
4
5
  export { mountCareCompass } from "./mount.js";
6
+ export { CARECOMPASS_ELEMENT_TAG, defineCareCompassElement, } from "./web-component.js";
5
7
  export { generateCareCompassIframeSnippet, generateCareCompassSnippet, } from "./snippet.js";
6
- export { careCompassApiBaseUrlSchema, careCompassConfigSchema, createDefaultCareCompassConfig, validateCareCompassConfig, } from "./schema.js";
8
+ export { careCompassApiBaseUrlSchema, careCompassComplianceConfigSchema, careCompassConfigSchema, careCompassFeatureFlagsSchema, careCompassModelConfigSchema, createDefaultCareCompassConfig, validateCareCompassConfig, } from "./schema.js";
9
+ export { CARECOMPASS_COMPLIANCE_PRESETS, detectCareCompassPhi, redactCareCompassPhi, resolveCareCompassCompliancePolicy, } from "./compliance.js";
7
10
  export { CARECOMPASS_TELEMETRY_ERROR_CODES, CARECOMPASS_TELEMETRY_EVENTS, careCompassTelemetryDurationBucket, createCareCompassCliTelemetry, createCareCompassTelemetry, } from "./telemetry.js";
8
11
  export { CARECOMPASS_COMPONENT_VERSION, CARECOMPASS_SDK_VERSION, CARECOMPASS_TELEMETRY_CONTRACT_VERSION, } from "./version.js";
@@ -1,3 +1,4 @@
1
+ import React from "react";
1
2
  export declare function CareCompassMarkdown({ text }: {
2
3
  text: string;
3
- }): import("react/jsx-runtime").JSX.Element;
4
+ }): React.JSX.Element;
package/dist/mount.d.ts CHANGED
@@ -1,4 +1,7 @@
1
+ import type { CareCompassRuntimeTokenProvider } from "./client.js";
1
2
  import type { CareCompassConfig } from "./schema.js";
2
- export declare function mountCareCompass(element: Element | null, config: CareCompassConfig): {
3
+ export declare function mountCareCompass(element: Element | null, config: CareCompassConfig, options?: {
4
+ runtimeTokenProvider?: CareCompassRuntimeTokenProvider;
5
+ }): {
3
6
  unmount: () => void;
4
7
  };
package/dist/mount.js CHANGED
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createRoot } from "react-dom/client";
3
3
  import { CareCompassEmbed } from "./component.js";
4
4
  import { CARECOMPASS_TELEMETRY_ERROR_CODES, CARECOMPASS_TELEMETRY_EVENTS, createCareCompassTelemetry, } from "./telemetry.js";
5
- export function mountCareCompass(element, config) {
5
+ export function mountCareCompass(element, config, options = {}) {
6
6
  if (!element) {
7
7
  // Missing mount points usually mean a copied snippet and page markup drifted
8
8
  // apart, so capture the setup error before throwing to the caller.
@@ -13,7 +13,7 @@ export function mountCareCompass(element, config) {
13
13
  throw new Error("CareCompass mount element was not found.");
14
14
  }
15
15
  const root = createRoot(element);
16
- root.render(_jsx(CareCompassEmbed, { config: config }));
16
+ root.render(_jsx(CareCompassEmbed, { config: config, runtimeTokenProvider: options.runtimeTokenProvider }));
17
17
  return {
18
18
  // Return the small React root facade so non-React hosts can clean up embeds.
19
19
  unmount: () => root.unmount(),
package/dist/rcm.d.ts ADDED
@@ -0,0 +1,93 @@
1
+ import React from "react";
2
+ import { type CareCompassCore, type CareCompassCoreOptions } from "./core.js";
3
+ import type { CareCompassAuditListener, CareCompassSafetyListener } from "./compliance.js";
4
+ import type { CareCompassConfig } from "./schema.js";
5
+ /** A narrow, structured input for coding review. Do not include direct patient identifiers. */
6
+ export type RcmCodingAssistanceInput = {
7
+ encounterId: string;
8
+ diagnosisNarrative: string;
9
+ procedureNarrative?: string;
10
+ serviceDate?: string;
11
+ placeOfService?: string;
12
+ claimContext?: {
13
+ payerName?: string;
14
+ submittedCodes?: string[];
15
+ };
16
+ };
17
+ export type RcmCodeSystem = "ICD-10-CM" | "CPT" | "HCPCS";
18
+ export type RcmConfidence = "low" | "medium" | "high";
19
+ export type RcmReviewDisposition = "review_required" | "abstain" | "escalate";
20
+ export type RcmPolicyReference = {
21
+ corpusId: string;
22
+ id: string;
23
+ title: string;
24
+ excerpt: string;
25
+ version?: string;
26
+ };
27
+ export type RcmCodeRecommendation = {
28
+ code: string;
29
+ codeSystem: RcmCodeSystem;
30
+ confidence: RcmConfidence;
31
+ rationale: string;
32
+ policyReferenceIds: string[];
33
+ };
34
+ export type RcmCodingAssistanceResult = {
35
+ disposition: RcmReviewDisposition;
36
+ humanReviewRequired: true;
37
+ recommendations: RcmCodeRecommendation[];
38
+ documentationGaps: string[];
39
+ policyReferences: RcmPolicyReference[];
40
+ rationale: string;
41
+ /** A host-facing, measurable pilot hypothesis—not a claim of realized savings. */
42
+ operationalHypothesis: {
43
+ metric: "manual_research_minutes_per_case";
44
+ target: "Measure whether assisted review reduces manual research time by 25% or more.";
45
+ };
46
+ processingTimeMs: number;
47
+ };
48
+ export type RcmCustomerRules = {
49
+ allowedCodeSystems?: RcmCodeSystem[];
50
+ escalateOnLowConfidence?: boolean;
51
+ requirePolicySupport?: boolean;
52
+ };
53
+ export type RcmPolicyRetriever = {
54
+ /** Corpus IDs are allowlisted by the embed owner; retrieval stays in the host's trusted boundary. */
55
+ approvedCorpusIds: readonly string[];
56
+ search: (request: {
57
+ input: RcmCodingAssistanceInput;
58
+ query: string;
59
+ }) => Promise<RcmPolicyReference[]>;
60
+ };
61
+ export type RcmCodingWorkflowOptions = {
62
+ core?: CareCompassCore;
63
+ coreOptions?: CareCompassCoreOptions;
64
+ customerRules?: RcmCustomerRules;
65
+ now?: () => number;
66
+ onResult?: (result: RcmCodingAssistanceResult) => void;
67
+ /**
68
+ * `hosted` delegates retrieval to the tenant-authorized CareCompass runtime.
69
+ * The browser never supplies policy text or corpus identifiers in that mode.
70
+ */
71
+ retrieval?: RcmPolicyRetriever | "hosted";
72
+ };
73
+ export type RcmCodingWorkflow = {
74
+ core: CareCompassCore;
75
+ review: (input: RcmCodingAssistanceInput) => Promise<RcmCodingAssistanceResult>;
76
+ };
77
+ /**
78
+ * Creates a narrow RCM coding-review workflow on the shared CareCompass core.
79
+ * Retrieval can run in the CareCompass tenant boundary or be injected by a
80
+ * customer that maintains its own approved, server-side retrieval boundary.
81
+ */
82
+ export declare function createRcmCodingWorkflow(config: CareCompassConfig, options?: RcmCodingWorkflowOptions): RcmCodingWorkflow;
83
+ export declare const CARECOMPASS_RCM_SYNTHETIC_DEMO: RcmCodingAssistanceInput;
84
+ export type RcmCodingAssistantProps = {
85
+ config: CareCompassConfig;
86
+ initialInput?: RcmCodingAssistanceInput;
87
+ onAuditEvent?: CareCompassAuditListener;
88
+ onResult?: (result: RcmCodingAssistanceResult) => void;
89
+ onSafetyEvent?: CareCompassSafetyListener;
90
+ workflowOptions?: Omit<RcmCodingWorkflowOptions, "core" | "coreOptions" | "onResult">;
91
+ };
92
+ /** A small branded form suitable for embedding the pilot workflow in a host app. */
93
+ export declare function RcmCodingAssistant({ config, initialInput, onAuditEvent, onResult, onSafetyEvent, workflowOptions, }: RcmCodingAssistantProps): React.JSX.Element;