pika-shared 1.4.4 → 1.4.6
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/dist/types/chatbot/chatbot-types.d.mts +180 -1
- package/dist/types/chatbot/chatbot-types.d.ts +180 -1
- package/dist/types/chatbot/chatbot-types.js +2 -0
- package/dist/types/chatbot/chatbot-types.js.map +1 -1
- package/dist/types/chatbot/chatbot-types.mjs +2 -1
- package/dist/types/chatbot/chatbot-types.mjs.map +1 -1
- package/dist/types/chatbot/webcomp-types.d.mts +170 -5
- package/dist/types/chatbot/webcomp-types.d.ts +170 -5
- package/dist/util/server-client-utils.d.mts +5 -1
- package/dist/util/server-client-utils.d.ts +5 -1
- package/dist/util/server-client-utils.js +9 -0
- package/dist/util/server-client-utils.js.map +1 -1
- package/dist/util/server-client-utils.mjs +9 -1
- package/dist/util/server-client-utils.mjs.map +1 -1
- package/dist/util/server-utils.js.map +1 -1
- package/dist/util/server-utils.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UploadStatus } from '../upload-types.mjs';
|
|
2
|
-
import { ShowToastFn, ChatUser, RecordOrUndef, UserAwsCredentials, WidgetRenderingContextType, ShareSessionState, UserPrefs, ChatAppMode, IUserWidgetDataStoreState, CustomDataUiRepresentation, ChatAppOverridableFeatures, TagDefinition, TagDefinitionWidget, ChatSession, UserDataOverrideSettings, ChatMessageForRendering, ChatApp, ChatAppActionMenu, ChatAppAction,
|
|
2
|
+
import { ShowToastFn, ChatUser, RecordOrUndef, UserAwsCredentials, WidgetRenderingContextType, ShareSessionState, UserPrefs, ChatAppMode, IUserWidgetDataStoreState, CustomDataUiRepresentation, ChatAppOverridableFeatures, TagDefinition, TagDefinitionWidget, ChatSession, UserDataOverrideSettings, ChatMessageForRendering, ChatApp, ChatAppActionMenu, ChatAppAction, WidgetInstance, WidgetMetadata, SpotlightWidgetDefinition, InvokeAgentAsComponentOptions, WidgetAction } from './chatbot-types.mjs';
|
|
3
3
|
import '@aws-sdk/client-bedrock-agent-runtime';
|
|
4
4
|
import '@aws-sdk/client-bedrock-agentcore';
|
|
5
5
|
|
|
@@ -176,6 +176,8 @@ interface IChatAppState {
|
|
|
176
176
|
readonly pageTitle: string | undefined;
|
|
177
177
|
readonly customDataForChatApp: Record<string, unknown> | undefined;
|
|
178
178
|
readonly customTitleBarActions: (ChatAppActionMenu | ChatAppAction)[];
|
|
179
|
+
readonly widgetInstances: Map<string, WidgetInstance>;
|
|
180
|
+
readonly user: ChatUser;
|
|
179
181
|
setCurrentSessionById(sessionId: string): void;
|
|
180
182
|
removeFile(s3Key: string): void;
|
|
181
183
|
startNewChatSession(): void;
|
|
@@ -186,11 +188,126 @@ interface IChatAppState {
|
|
|
186
188
|
getMessageByMessageId(messageId: string): ChatMessageForRendering | undefined;
|
|
187
189
|
uploadFiles(files: File[]): Promise<void>;
|
|
188
190
|
initializeData(): Promise<void>;
|
|
189
|
-
renderTag(tagId: string, context: 'spotlight' | 'inline' | 'dialog' | 'canvas', data?: Record<string, any
|
|
191
|
+
renderTag(tagId: string, context: 'spotlight' | 'inline' | 'dialog' | 'canvas' | 'static', data?: Record<string, any>, metadata?: WidgetMetadata): Promise<void>;
|
|
190
192
|
closeCanvas(): void;
|
|
191
193
|
closeDialog(): void;
|
|
192
194
|
setOrUpdateCustomTitleBarAction(action: ChatAppActionMenu | ChatAppAction): void;
|
|
193
195
|
removeCustomTitleBarAction(actionId: string): void;
|
|
196
|
+
getWidgetInstance(instanceId: string): WidgetInstance | undefined;
|
|
197
|
+
/**
|
|
198
|
+
* Update context for a widget. Call this when your widget's context has changed.
|
|
199
|
+
*
|
|
200
|
+
* This method will re-check your widget's `getContextForLlm()` method and update
|
|
201
|
+
* the context accordingly. Use this when:
|
|
202
|
+
* - Your widget initially had no context, but now has context to share
|
|
203
|
+
* - Your widget's context data has changed (e.g., user selected different items)
|
|
204
|
+
* - You want to change whether context should be auto-added
|
|
205
|
+
*
|
|
206
|
+
* @param instanceId - Your widget's instance ID (from getPikaContext())
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```typescript
|
|
210
|
+
* // In a Svelte widget component:
|
|
211
|
+
* let selectedCities = $state<string[]>([]);
|
|
212
|
+
*
|
|
213
|
+
* onMount(async () => {
|
|
214
|
+
* const context = await getPikaContext($host());
|
|
215
|
+
*
|
|
216
|
+
* // Update context whenever selection changes
|
|
217
|
+
* $effect(() => {
|
|
218
|
+
* if (selectedCities.length > 0) {
|
|
219
|
+
* // This triggers re-evaluation of getContextForLlm()
|
|
220
|
+
* context.chatAppState.updateWidgetContext(context.instanceId);
|
|
221
|
+
* }
|
|
222
|
+
* });
|
|
223
|
+
* });
|
|
224
|
+
*
|
|
225
|
+
* // Your getContextForLlm() method will be called again
|
|
226
|
+
* getContextForLlm() {
|
|
227
|
+
* if (selectedCities.length === 0) return undefined;
|
|
228
|
+
*
|
|
229
|
+
* return {
|
|
230
|
+
* origin: 'auto',
|
|
231
|
+
* title: 'Selected Cities',
|
|
232
|
+
* description: `User selected ${selectedCities.length} cities`,
|
|
233
|
+
* data: { cities: selectedCities },
|
|
234
|
+
* addAutomatically: true
|
|
235
|
+
* };
|
|
236
|
+
* }
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
updateWidgetContext(instanceId: string): void;
|
|
240
|
+
/**
|
|
241
|
+
* Manually register a web component as a spotlight widget. This allows components to
|
|
242
|
+
* dynamically add themselves to the spotlight area at runtime.
|
|
243
|
+
*
|
|
244
|
+
* Note: Registration is ephemeral and does not persist across page refreshes.
|
|
245
|
+
* Components must re-register themselves on each page load.
|
|
246
|
+
*
|
|
247
|
+
* @param definition - Simplified definition for the spotlight widget
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* chatAppState.manuallyRegisterSpotlightWidget({
|
|
252
|
+
* tag: 'my-widget',
|
|
253
|
+
* scope: 'my-app',
|
|
254
|
+
* tagTitle: 'My Widget',
|
|
255
|
+
* displayOrder: 0
|
|
256
|
+
* });
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
manuallyRegisterSpotlightWidget(definition: SpotlightWidgetDefinition): void;
|
|
260
|
+
/**
|
|
261
|
+
* Save a persistent spotlight instance using the Virtual Tags Pattern.
|
|
262
|
+
* Creates a new instance with its own UserWidgetDataStore (400KB limit per instance),
|
|
263
|
+
* saves the data, registers it as a spotlight widget, and renders it immediately.
|
|
264
|
+
*
|
|
265
|
+
* Use this when users save content (like charts, queries, etc.) to spotlight.
|
|
266
|
+
*
|
|
267
|
+
* @param scope - Widget scope (e.g., 'weather')
|
|
268
|
+
* @param baseTag - Base tag name (e.g., 'chart-saved')
|
|
269
|
+
* @param displayName - User-facing name for this instance
|
|
270
|
+
* @param customElementName - The custom element name (same for all instances)
|
|
271
|
+
* @param data - The data to pass to this instance
|
|
272
|
+
* @param dataKey - The key to store data under (default: 'data')
|
|
273
|
+
* @param metadata - Optional widget metadata (title, actions, icon, etc.)
|
|
274
|
+
* @returns The instance ID (UUID)
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* ```typescript
|
|
278
|
+
* const instanceId = await chatAppState.saveSpotlightInstance(
|
|
279
|
+
* 'weather',
|
|
280
|
+
* 'chart-saved',
|
|
281
|
+
* 'Q4 Revenue Chart',
|
|
282
|
+
* 'weather-chart-saved',
|
|
283
|
+
* { chartType: 'bar', data: [...] },
|
|
284
|
+
* 'chartData',
|
|
285
|
+
* {
|
|
286
|
+
* title: 'Q4 Revenue Chart',
|
|
287
|
+
* iconSvg: '<svg>...</svg>',
|
|
288
|
+
* actions: [...]
|
|
289
|
+
* }
|
|
290
|
+
* );
|
|
291
|
+
* ```
|
|
292
|
+
*/
|
|
293
|
+
saveSpotlightInstance(scope: string, baseTag: string, displayName: string, customElementName: string, data: Record<string, any>, dataKey?: string, metadata?: WidgetMetadata): Promise<string>;
|
|
294
|
+
/**
|
|
295
|
+
* Delete a saved spotlight instance.
|
|
296
|
+
* Removes from spotlight, removes from registry, and unregisters from state.
|
|
297
|
+
*
|
|
298
|
+
* Note: Instance data is currently orphaned (not deleted) but could be recovered.
|
|
299
|
+
* Future: Will add deleteAll() method to UserWidgetDataStore.
|
|
300
|
+
*
|
|
301
|
+
* @param scope - Widget scope
|
|
302
|
+
* @param baseTag - Base tag name
|
|
303
|
+
* @param instanceId - Instance UUID
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```typescript
|
|
307
|
+
* await chatAppState.deleteSpotlightInstance('weather', 'chart-saved', instanceId);
|
|
308
|
+
* ```
|
|
309
|
+
*/
|
|
310
|
+
deleteSpotlightInstance(scope: string, baseTag: string, instanceId: string): Promise<void>;
|
|
194
311
|
/**
|
|
195
312
|
* Invoke the agent directly from a web component using the 'chat-app-component' invocation mode.
|
|
196
313
|
* This allows components to make out-of-band requests to the LLM without creating user sessions.
|
|
@@ -324,6 +441,54 @@ interface IUploadInstance {
|
|
|
324
441
|
error?: string;
|
|
325
442
|
};
|
|
326
443
|
}
|
|
444
|
+
/**
|
|
445
|
+
* Callback invoked when the web component has been created and is ready.
|
|
446
|
+
* Called after the element is created but before it's added to the DOM.
|
|
447
|
+
*/
|
|
448
|
+
interface OnReadyCallback {
|
|
449
|
+
(params: {
|
|
450
|
+
/** The web component element that was created */
|
|
451
|
+
element: HTMLElement;
|
|
452
|
+
/** The unique instance ID assigned to this component */
|
|
453
|
+
instanceId: string;
|
|
454
|
+
/** The full Pika context with instanceId */
|
|
455
|
+
context: PikaWCContext;
|
|
456
|
+
}): void;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Structure for data passed to web components.
|
|
460
|
+
*
|
|
461
|
+
* Special fields that affect element initialization:
|
|
462
|
+
* - `attributes`: Set as HTML attributes (stringified) and also as properties if they exist
|
|
463
|
+
* - `properties`: Set as JavaScript properties only (not attributes)
|
|
464
|
+
* - `onReady`: Callback invoked when the component is created and ready
|
|
465
|
+
*
|
|
466
|
+
* All other fields are available through `context.dataForWidget` but not set on the element.
|
|
467
|
+
*/
|
|
468
|
+
interface DataForWidget {
|
|
469
|
+
/**
|
|
470
|
+
* HTML attributes to set on the element.
|
|
471
|
+
* Values are stringified and set via `setAttributeNS()`.
|
|
472
|
+
* If a corresponding property exists on the element, it's also set with the original value.
|
|
473
|
+
*/
|
|
474
|
+
attributes?: Record<string, any>;
|
|
475
|
+
/**
|
|
476
|
+
* JavaScript properties to set on the element (not as HTML attributes).
|
|
477
|
+
* Only properties that exist on the element will be set.
|
|
478
|
+
* Use this for complex objects, arrays, functions, etc.
|
|
479
|
+
*/
|
|
480
|
+
properties?: Record<string, any>;
|
|
481
|
+
/**
|
|
482
|
+
* Callback invoked when the web component is created and ready.
|
|
483
|
+
* Called after element creation, property/attribute setting, and context setup,
|
|
484
|
+
* but before the element is added to the DOM.
|
|
485
|
+
*
|
|
486
|
+
* Use this to get notified when the component is ready and to access the element directly.
|
|
487
|
+
*/
|
|
488
|
+
onReady?: OnReadyCallback;
|
|
489
|
+
/** Any other data available through context (not set on the element) */
|
|
490
|
+
[key: string]: any;
|
|
491
|
+
}
|
|
327
492
|
/**
|
|
328
493
|
* This is the context object that is passed to the web component when it is rendered.
|
|
329
494
|
*/
|
|
@@ -337,8 +502,8 @@ interface PikaWCContext {
|
|
|
337
502
|
* Set by injectChatAppWebComponent() and used by getWidgetMetadataAPI().
|
|
338
503
|
*/
|
|
339
504
|
instanceId: string;
|
|
340
|
-
/**
|
|
341
|
-
dataForWidget:
|
|
505
|
+
/** Data passed to the widget, available through `context.dataForWidget`. */
|
|
506
|
+
dataForWidget: DataForWidget;
|
|
342
507
|
}
|
|
343
508
|
type PikaWCContextWithoutInstanceId = Omit<PikaWCContext, 'instanceId'>;
|
|
344
509
|
type PikaWCContextRequestCallbackFn = (contextRequest: PikaWCContext) => void;
|
|
@@ -349,4 +514,4 @@ interface PikaWCContextRequestEvent extends CustomEvent<PikaWCContextRequestDeta
|
|
|
349
514
|
detail: PikaWCContextRequestDetail;
|
|
350
515
|
}
|
|
351
516
|
|
|
352
|
-
export type { IAppState, IChatAppState, IIdentityState, IUploadInstance, IUserPrefsState, IWidgetMetadataAPI, PikaWCContext, PikaWCContextRequestCallbackFn, PikaWCContextRequestDetail, PikaWCContextRequestEvent, PikaWCContextWithoutInstanceId, SidebarState, Snippet };
|
|
517
|
+
export type { DataForWidget, IAppState, IChatAppState, IIdentityState, IUploadInstance, IUserPrefsState, IWidgetMetadataAPI, OnReadyCallback, PikaWCContext, PikaWCContextRequestCallbackFn, PikaWCContextRequestDetail, PikaWCContextRequestEvent, PikaWCContextWithoutInstanceId, SidebarState, Snippet };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UploadStatus } from '../upload-types.js';
|
|
2
|
-
import { ShowToastFn, ChatUser, RecordOrUndef, UserAwsCredentials, WidgetRenderingContextType, ShareSessionState, UserPrefs, ChatAppMode, IUserWidgetDataStoreState, CustomDataUiRepresentation, ChatAppOverridableFeatures, TagDefinition, TagDefinitionWidget, ChatSession, UserDataOverrideSettings, ChatMessageForRendering, ChatApp, ChatAppActionMenu, ChatAppAction,
|
|
2
|
+
import { ShowToastFn, ChatUser, RecordOrUndef, UserAwsCredentials, WidgetRenderingContextType, ShareSessionState, UserPrefs, ChatAppMode, IUserWidgetDataStoreState, CustomDataUiRepresentation, ChatAppOverridableFeatures, TagDefinition, TagDefinitionWidget, ChatSession, UserDataOverrideSettings, ChatMessageForRendering, ChatApp, ChatAppActionMenu, ChatAppAction, WidgetInstance, WidgetMetadata, SpotlightWidgetDefinition, InvokeAgentAsComponentOptions, WidgetAction } from './chatbot-types.js';
|
|
3
3
|
import '@aws-sdk/client-bedrock-agent-runtime';
|
|
4
4
|
import '@aws-sdk/client-bedrock-agentcore';
|
|
5
5
|
|
|
@@ -176,6 +176,8 @@ interface IChatAppState {
|
|
|
176
176
|
readonly pageTitle: string | undefined;
|
|
177
177
|
readonly customDataForChatApp: Record<string, unknown> | undefined;
|
|
178
178
|
readonly customTitleBarActions: (ChatAppActionMenu | ChatAppAction)[];
|
|
179
|
+
readonly widgetInstances: Map<string, WidgetInstance>;
|
|
180
|
+
readonly user: ChatUser;
|
|
179
181
|
setCurrentSessionById(sessionId: string): void;
|
|
180
182
|
removeFile(s3Key: string): void;
|
|
181
183
|
startNewChatSession(): void;
|
|
@@ -186,11 +188,126 @@ interface IChatAppState {
|
|
|
186
188
|
getMessageByMessageId(messageId: string): ChatMessageForRendering | undefined;
|
|
187
189
|
uploadFiles(files: File[]): Promise<void>;
|
|
188
190
|
initializeData(): Promise<void>;
|
|
189
|
-
renderTag(tagId: string, context: 'spotlight' | 'inline' | 'dialog' | 'canvas', data?: Record<string, any
|
|
191
|
+
renderTag(tagId: string, context: 'spotlight' | 'inline' | 'dialog' | 'canvas' | 'static', data?: Record<string, any>, metadata?: WidgetMetadata): Promise<void>;
|
|
190
192
|
closeCanvas(): void;
|
|
191
193
|
closeDialog(): void;
|
|
192
194
|
setOrUpdateCustomTitleBarAction(action: ChatAppActionMenu | ChatAppAction): void;
|
|
193
195
|
removeCustomTitleBarAction(actionId: string): void;
|
|
196
|
+
getWidgetInstance(instanceId: string): WidgetInstance | undefined;
|
|
197
|
+
/**
|
|
198
|
+
* Update context for a widget. Call this when your widget's context has changed.
|
|
199
|
+
*
|
|
200
|
+
* This method will re-check your widget's `getContextForLlm()` method and update
|
|
201
|
+
* the context accordingly. Use this when:
|
|
202
|
+
* - Your widget initially had no context, but now has context to share
|
|
203
|
+
* - Your widget's context data has changed (e.g., user selected different items)
|
|
204
|
+
* - You want to change whether context should be auto-added
|
|
205
|
+
*
|
|
206
|
+
* @param instanceId - Your widget's instance ID (from getPikaContext())
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```typescript
|
|
210
|
+
* // In a Svelte widget component:
|
|
211
|
+
* let selectedCities = $state<string[]>([]);
|
|
212
|
+
*
|
|
213
|
+
* onMount(async () => {
|
|
214
|
+
* const context = await getPikaContext($host());
|
|
215
|
+
*
|
|
216
|
+
* // Update context whenever selection changes
|
|
217
|
+
* $effect(() => {
|
|
218
|
+
* if (selectedCities.length > 0) {
|
|
219
|
+
* // This triggers re-evaluation of getContextForLlm()
|
|
220
|
+
* context.chatAppState.updateWidgetContext(context.instanceId);
|
|
221
|
+
* }
|
|
222
|
+
* });
|
|
223
|
+
* });
|
|
224
|
+
*
|
|
225
|
+
* // Your getContextForLlm() method will be called again
|
|
226
|
+
* getContextForLlm() {
|
|
227
|
+
* if (selectedCities.length === 0) return undefined;
|
|
228
|
+
*
|
|
229
|
+
* return {
|
|
230
|
+
* origin: 'auto',
|
|
231
|
+
* title: 'Selected Cities',
|
|
232
|
+
* description: `User selected ${selectedCities.length} cities`,
|
|
233
|
+
* data: { cities: selectedCities },
|
|
234
|
+
* addAutomatically: true
|
|
235
|
+
* };
|
|
236
|
+
* }
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
updateWidgetContext(instanceId: string): void;
|
|
240
|
+
/**
|
|
241
|
+
* Manually register a web component as a spotlight widget. This allows components to
|
|
242
|
+
* dynamically add themselves to the spotlight area at runtime.
|
|
243
|
+
*
|
|
244
|
+
* Note: Registration is ephemeral and does not persist across page refreshes.
|
|
245
|
+
* Components must re-register themselves on each page load.
|
|
246
|
+
*
|
|
247
|
+
* @param definition - Simplified definition for the spotlight widget
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* chatAppState.manuallyRegisterSpotlightWidget({
|
|
252
|
+
* tag: 'my-widget',
|
|
253
|
+
* scope: 'my-app',
|
|
254
|
+
* tagTitle: 'My Widget',
|
|
255
|
+
* displayOrder: 0
|
|
256
|
+
* });
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
manuallyRegisterSpotlightWidget(definition: SpotlightWidgetDefinition): void;
|
|
260
|
+
/**
|
|
261
|
+
* Save a persistent spotlight instance using the Virtual Tags Pattern.
|
|
262
|
+
* Creates a new instance with its own UserWidgetDataStore (400KB limit per instance),
|
|
263
|
+
* saves the data, registers it as a spotlight widget, and renders it immediately.
|
|
264
|
+
*
|
|
265
|
+
* Use this when users save content (like charts, queries, etc.) to spotlight.
|
|
266
|
+
*
|
|
267
|
+
* @param scope - Widget scope (e.g., 'weather')
|
|
268
|
+
* @param baseTag - Base tag name (e.g., 'chart-saved')
|
|
269
|
+
* @param displayName - User-facing name for this instance
|
|
270
|
+
* @param customElementName - The custom element name (same for all instances)
|
|
271
|
+
* @param data - The data to pass to this instance
|
|
272
|
+
* @param dataKey - The key to store data under (default: 'data')
|
|
273
|
+
* @param metadata - Optional widget metadata (title, actions, icon, etc.)
|
|
274
|
+
* @returns The instance ID (UUID)
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* ```typescript
|
|
278
|
+
* const instanceId = await chatAppState.saveSpotlightInstance(
|
|
279
|
+
* 'weather',
|
|
280
|
+
* 'chart-saved',
|
|
281
|
+
* 'Q4 Revenue Chart',
|
|
282
|
+
* 'weather-chart-saved',
|
|
283
|
+
* { chartType: 'bar', data: [...] },
|
|
284
|
+
* 'chartData',
|
|
285
|
+
* {
|
|
286
|
+
* title: 'Q4 Revenue Chart',
|
|
287
|
+
* iconSvg: '<svg>...</svg>',
|
|
288
|
+
* actions: [...]
|
|
289
|
+
* }
|
|
290
|
+
* );
|
|
291
|
+
* ```
|
|
292
|
+
*/
|
|
293
|
+
saveSpotlightInstance(scope: string, baseTag: string, displayName: string, customElementName: string, data: Record<string, any>, dataKey?: string, metadata?: WidgetMetadata): Promise<string>;
|
|
294
|
+
/**
|
|
295
|
+
* Delete a saved spotlight instance.
|
|
296
|
+
* Removes from spotlight, removes from registry, and unregisters from state.
|
|
297
|
+
*
|
|
298
|
+
* Note: Instance data is currently orphaned (not deleted) but could be recovered.
|
|
299
|
+
* Future: Will add deleteAll() method to UserWidgetDataStore.
|
|
300
|
+
*
|
|
301
|
+
* @param scope - Widget scope
|
|
302
|
+
* @param baseTag - Base tag name
|
|
303
|
+
* @param instanceId - Instance UUID
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```typescript
|
|
307
|
+
* await chatAppState.deleteSpotlightInstance('weather', 'chart-saved', instanceId);
|
|
308
|
+
* ```
|
|
309
|
+
*/
|
|
310
|
+
deleteSpotlightInstance(scope: string, baseTag: string, instanceId: string): Promise<void>;
|
|
194
311
|
/**
|
|
195
312
|
* Invoke the agent directly from a web component using the 'chat-app-component' invocation mode.
|
|
196
313
|
* This allows components to make out-of-band requests to the LLM without creating user sessions.
|
|
@@ -324,6 +441,54 @@ interface IUploadInstance {
|
|
|
324
441
|
error?: string;
|
|
325
442
|
};
|
|
326
443
|
}
|
|
444
|
+
/**
|
|
445
|
+
* Callback invoked when the web component has been created and is ready.
|
|
446
|
+
* Called after the element is created but before it's added to the DOM.
|
|
447
|
+
*/
|
|
448
|
+
interface OnReadyCallback {
|
|
449
|
+
(params: {
|
|
450
|
+
/** The web component element that was created */
|
|
451
|
+
element: HTMLElement;
|
|
452
|
+
/** The unique instance ID assigned to this component */
|
|
453
|
+
instanceId: string;
|
|
454
|
+
/** The full Pika context with instanceId */
|
|
455
|
+
context: PikaWCContext;
|
|
456
|
+
}): void;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Structure for data passed to web components.
|
|
460
|
+
*
|
|
461
|
+
* Special fields that affect element initialization:
|
|
462
|
+
* - `attributes`: Set as HTML attributes (stringified) and also as properties if they exist
|
|
463
|
+
* - `properties`: Set as JavaScript properties only (not attributes)
|
|
464
|
+
* - `onReady`: Callback invoked when the component is created and ready
|
|
465
|
+
*
|
|
466
|
+
* All other fields are available through `context.dataForWidget` but not set on the element.
|
|
467
|
+
*/
|
|
468
|
+
interface DataForWidget {
|
|
469
|
+
/**
|
|
470
|
+
* HTML attributes to set on the element.
|
|
471
|
+
* Values are stringified and set via `setAttributeNS()`.
|
|
472
|
+
* If a corresponding property exists on the element, it's also set with the original value.
|
|
473
|
+
*/
|
|
474
|
+
attributes?: Record<string, any>;
|
|
475
|
+
/**
|
|
476
|
+
* JavaScript properties to set on the element (not as HTML attributes).
|
|
477
|
+
* Only properties that exist on the element will be set.
|
|
478
|
+
* Use this for complex objects, arrays, functions, etc.
|
|
479
|
+
*/
|
|
480
|
+
properties?: Record<string, any>;
|
|
481
|
+
/**
|
|
482
|
+
* Callback invoked when the web component is created and ready.
|
|
483
|
+
* Called after element creation, property/attribute setting, and context setup,
|
|
484
|
+
* but before the element is added to the DOM.
|
|
485
|
+
*
|
|
486
|
+
* Use this to get notified when the component is ready and to access the element directly.
|
|
487
|
+
*/
|
|
488
|
+
onReady?: OnReadyCallback;
|
|
489
|
+
/** Any other data available through context (not set on the element) */
|
|
490
|
+
[key: string]: any;
|
|
491
|
+
}
|
|
327
492
|
/**
|
|
328
493
|
* This is the context object that is passed to the web component when it is rendered.
|
|
329
494
|
*/
|
|
@@ -337,8 +502,8 @@ interface PikaWCContext {
|
|
|
337
502
|
* Set by injectChatAppWebComponent() and used by getWidgetMetadataAPI().
|
|
338
503
|
*/
|
|
339
504
|
instanceId: string;
|
|
340
|
-
/**
|
|
341
|
-
dataForWidget:
|
|
505
|
+
/** Data passed to the widget, available through `context.dataForWidget`. */
|
|
506
|
+
dataForWidget: DataForWidget;
|
|
342
507
|
}
|
|
343
508
|
type PikaWCContextWithoutInstanceId = Omit<PikaWCContext, 'instanceId'>;
|
|
344
509
|
type PikaWCContextRequestCallbackFn = (contextRequest: PikaWCContext) => void;
|
|
@@ -349,4 +514,4 @@ interface PikaWCContextRequestEvent extends CustomEvent<PikaWCContextRequestDeta
|
|
|
349
514
|
detail: PikaWCContextRequestDetail;
|
|
350
515
|
}
|
|
351
516
|
|
|
352
|
-
export type { IAppState, IChatAppState, IIdentityState, IUploadInstance, IUserPrefsState, IWidgetMetadataAPI, PikaWCContext, PikaWCContextRequestCallbackFn, PikaWCContextRequestDetail, PikaWCContextRequestEvent, PikaWCContextWithoutInstanceId, SidebarState, Snippet };
|
|
517
|
+
export type { DataForWidget, IAppState, IChatAppState, IIdentityState, IUploadInstance, IUserPrefsState, IWidgetMetadataAPI, OnReadyCallback, PikaWCContext, PikaWCContextRequestCallbackFn, PikaWCContextRequestDetail, PikaWCContextRequestEvent, PikaWCContextWithoutInstanceId, SidebarState, Snippet };
|
|
@@ -27,5 +27,9 @@ declare function parseScope(scope: string): {
|
|
|
27
27
|
scopeType: string;
|
|
28
28
|
scopeValue: string | number | Record<string, string | number>;
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Useful for simple hashing like to figure out if content has changed since last sent or something.
|
|
32
|
+
*/
|
|
33
|
+
declare function getContentHashString(content: unknown): Promise<string>;
|
|
30
34
|
|
|
31
|
-
export { constructScope, parseScope, redactData, redactValue };
|
|
35
|
+
export { constructScope, getContentHashString, parseScope, redactData, redactValue };
|
|
@@ -27,5 +27,9 @@ declare function parseScope(scope: string): {
|
|
|
27
27
|
scopeType: string;
|
|
28
28
|
scopeValue: string | number | Record<string, string | number>;
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Useful for simple hashing like to figure out if content has changed since last sent or something.
|
|
32
|
+
*/
|
|
33
|
+
declare function getContentHashString(content: unknown): Promise<string>;
|
|
30
34
|
|
|
31
|
-
export { constructScope, parseScope, redactData, redactValue };
|
|
35
|
+
export { constructScope, getContentHashString, parseScope, redactData, redactValue };
|
|
@@ -91,8 +91,17 @@ function parseScope(scope) {
|
|
|
91
91
|
}
|
|
92
92
|
throw new Error(`Unsupported scope format: ${scope}`);
|
|
93
93
|
}
|
|
94
|
+
async function getContentHashString(content) {
|
|
95
|
+
const encoder = new TextEncoder();
|
|
96
|
+
const data = encoder.encode(JSON.stringify(content));
|
|
97
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
98
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
99
|
+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
100
|
+
return hashHex;
|
|
101
|
+
}
|
|
94
102
|
|
|
95
103
|
exports.constructScope = constructScope;
|
|
104
|
+
exports.getContentHashString = getContentHashString;
|
|
96
105
|
exports.parseScope = parseScope;
|
|
97
106
|
exports.redactData = redactData;
|
|
98
107
|
exports.redactValue = redactValue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/server-client-utils.ts"],"names":[],"mappings":"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","file":"server-client-utils.js","sourcesContent":["/*\n * These are utils that are safe to use both on the server and the client.\n */\n\n/**\n * Helper function to redact sensitive data from specified attributes\n * @param data - The object containing data to redact\n * @param attributesToRedact - Single attribute name or array of attribute names to redact\n * @returns A new object with specified attributes redacted\n */\nfunction redactData(data: any, attributesToRedact: string | string[]): any {\n if (!data || typeof data !== 'object') {\n return data;\n }\n\n const attributes = Array.isArray(attributesToRedact) ? attributesToRedact : [attributesToRedact];\n const redacted = { ...data };\n\n for (const attr of attributes) {\n if (attr in redacted) {\n redacted[attr] = redactValue(redacted[attr]);\n }\n }\n\n return redacted;\n}\n\n/**\n * Recursively redacts a value based on its type\n * @param value - The value to redact\n * @returns The redacted value\n */\nfunction redactValue(value: any): any {\n if (typeof value === 'string') {\n return '[REDACTED]';\n } else if (Array.isArray(value)) {\n return value.map((item) => redactValue(item));\n } else if (value && typeof value === 'object') {\n const redactedObj: any = {};\n for (const key in value) {\n if (value.hasOwnProperty(key)) {\n redactedObj[key] = redactValue(value[key]);\n }\n }\n return redactedObj;\n }\n return value; // Return as-is for other types (numbers, booleans, null, etc.)\n}\n\n/**\n * Validates that a scope value doesn't contain the '#' character which is reserved for scope construction\n */\nfunction validateScopeValue(scopeValue: string | number | Record<string, string | number>, scopeType: string): void {\n if (typeof scopeValue === 'string' && scopeValue.includes('#')) {\n throw new Error(`Scope value cannot contain '#' character. Found in ${scopeType} scope value: ${scopeValue}`);\n }\n if (typeof scopeValue === 'object' && scopeValue !== null) {\n for (const [key, value] of Object.entries(scopeValue)) {\n if (typeof value === 'string' && value.includes('#')) {\n throw new Error(`Scope value cannot contain '#' character. Found in ${scopeType}.${key}: ${value}`);\n }\n }\n }\n}\n\n/**\n * Constructs a scope string from scopeType and scopeValue\n * @param scopeType - The type of scope (chatapp, agent, tool, entity, agent-entity)\n * @param scopeValue - The value(s) for the scope\n * @returns The constructed scope string\n */\nfunction constructScope(scopeType: string, scopeValue: string | number | Record<string, string | number>): string {\n // Validate scope value doesn't contain '#'\n validateScopeValue(scopeValue, scopeType);\n\n switch (scopeType) {\n case 'chatapp':\n case 'agent':\n case 'tool':\n case 'entity':\n return `${scopeType}#${scopeValue}`;\n case 'agent-entity':\n if (typeof scopeValue !== 'object' || scopeValue === null) {\n throw new Error('agent-entity scopeType requires an object with agent and entity properties');\n }\n\n const agentEntityValue = scopeValue as Record<string, string | number>;\n if (!('agent' in agentEntityValue) || !('entity' in agentEntityValue)) {\n throw new Error('agent-entity scopeType requires an object with both agent and entity properties');\n }\n\n return `agent#${agentEntityValue.agent}#entity#${agentEntityValue.entity}`;\n\n default:\n throw new Error(`Unsupported scopeType: ${scopeType}`);\n }\n}\n\n/**\n * Parses a scope string back into scopeType and scopeValue\n * @param scope - The scope string to parse\n * @returns Object containing scopeType and scopeValue\n */\nfunction parseScope(scope: string): { scopeType: string; scopeValue: string | number | Record<string, string | number> } {\n if (!scope || typeof scope !== 'string') {\n throw new Error('Invalid scope: must be a non-empty string');\n }\n\n const parts = scope.split('#');\n if (parts.length < 2) {\n throw new Error(`Invalid scope format: ${scope}. Expected format: scopeType#scopeValue`);\n }\n\n const [firstType, firstValue, ...remaining] = parts;\n\n // Handle compound scopes (agent-entity)\n if (remaining.length >= 2 && firstType === 'agent' && remaining[0] === 'entity') {\n return {\n scopeType: 'agent-entity',\n scopeValue: {\n agent: firstValue,\n entity: remaining[1]\n }\n };\n }\n\n // Handle simple scopes\n if (remaining.length === 0) {\n // For simple scopes, try to convert to number if it's numeric\n const numericValue = Number(firstValue);\n const scopeValue = !isNaN(numericValue) && isFinite(numericValue) ? numericValue : firstValue;\n\n return {\n scopeType: firstType,\n scopeValue: scopeValue\n };\n }\n\n throw new Error(`Unsupported scope format: ${scope}`);\n}\n\n// Export both functions\nexport { redactData, redactValue, constructScope, parseScope };\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/util/server-client-utils.ts"],"names":[],"mappings":"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","file":"server-client-utils.js","sourcesContent":["/*\n * These are utils that are safe to use both on the server and the client.\n */\n\n/**\n * Helper function to redact sensitive data from specified attributes\n * @param data - The object containing data to redact\n * @param attributesToRedact - Single attribute name or array of attribute names to redact\n * @returns A new object with specified attributes redacted\n */\nfunction redactData(data: any, attributesToRedact: string | string[]): any {\n if (!data || typeof data !== 'object') {\n return data;\n }\n\n const attributes = Array.isArray(attributesToRedact) ? attributesToRedact : [attributesToRedact];\n const redacted = { ...data };\n\n for (const attr of attributes) {\n if (attr in redacted) {\n redacted[attr] = redactValue(redacted[attr]);\n }\n }\n\n return redacted;\n}\n\n/**\n * Recursively redacts a value based on its type\n * @param value - The value to redact\n * @returns The redacted value\n */\nfunction redactValue(value: any): any {\n if (typeof value === 'string') {\n return '[REDACTED]';\n } else if (Array.isArray(value)) {\n return value.map((item) => redactValue(item));\n } else if (value && typeof value === 'object') {\n const redactedObj: any = {};\n for (const key in value) {\n if (value.hasOwnProperty(key)) {\n redactedObj[key] = redactValue(value[key]);\n }\n }\n return redactedObj;\n }\n return value; // Return as-is for other types (numbers, booleans, null, etc.)\n}\n\n/**\n * Validates that a scope value doesn't contain the '#' character which is reserved for scope construction\n */\nfunction validateScopeValue(scopeValue: string | number | Record<string, string | number>, scopeType: string): void {\n if (typeof scopeValue === 'string' && scopeValue.includes('#')) {\n throw new Error(`Scope value cannot contain '#' character. Found in ${scopeType} scope value: ${scopeValue}`);\n }\n if (typeof scopeValue === 'object' && scopeValue !== null) {\n for (const [key, value] of Object.entries(scopeValue)) {\n if (typeof value === 'string' && value.includes('#')) {\n throw new Error(`Scope value cannot contain '#' character. Found in ${scopeType}.${key}: ${value}`);\n }\n }\n }\n}\n\n/**\n * Constructs a scope string from scopeType and scopeValue\n * @param scopeType - The type of scope (chatapp, agent, tool, entity, agent-entity)\n * @param scopeValue - The value(s) for the scope\n * @returns The constructed scope string\n */\nfunction constructScope(scopeType: string, scopeValue: string | number | Record<string, string | number>): string {\n // Validate scope value doesn't contain '#'\n validateScopeValue(scopeValue, scopeType);\n\n switch (scopeType) {\n case 'chatapp':\n case 'agent':\n case 'tool':\n case 'entity':\n return `${scopeType}#${scopeValue}`;\n case 'agent-entity':\n if (typeof scopeValue !== 'object' || scopeValue === null) {\n throw new Error('agent-entity scopeType requires an object with agent and entity properties');\n }\n\n const agentEntityValue = scopeValue as Record<string, string | number>;\n if (!('agent' in agentEntityValue) || !('entity' in agentEntityValue)) {\n throw new Error('agent-entity scopeType requires an object with both agent and entity properties');\n }\n\n return `agent#${agentEntityValue.agent}#entity#${agentEntityValue.entity}`;\n\n default:\n throw new Error(`Unsupported scopeType: ${scopeType}`);\n }\n}\n\n/**\n * Parses a scope string back into scopeType and scopeValue\n * @param scope - The scope string to parse\n * @returns Object containing scopeType and scopeValue\n */\nfunction parseScope(scope: string): { scopeType: string; scopeValue: string | number | Record<string, string | number> } {\n if (!scope || typeof scope !== 'string') {\n throw new Error('Invalid scope: must be a non-empty string');\n }\n\n const parts = scope.split('#');\n if (parts.length < 2) {\n throw new Error(`Invalid scope format: ${scope}. Expected format: scopeType#scopeValue`);\n }\n\n const [firstType, firstValue, ...remaining] = parts;\n\n // Handle compound scopes (agent-entity)\n if (remaining.length >= 2 && firstType === 'agent' && remaining[0] === 'entity') {\n return {\n scopeType: 'agent-entity',\n scopeValue: {\n agent: firstValue,\n entity: remaining[1]\n }\n };\n }\n\n // Handle simple scopes\n if (remaining.length === 0) {\n // For simple scopes, try to convert to number if it's numeric\n const numericValue = Number(firstValue);\n const scopeValue = !isNaN(numericValue) && isFinite(numericValue) ? numericValue : firstValue;\n\n return {\n scopeType: firstType,\n scopeValue: scopeValue\n };\n }\n\n throw new Error(`Unsupported scope format: ${scope}`);\n}\n\n/**\n * Useful for simple hashing like to figure out if content has changed since last sent or something.\n */\nasync function getContentHashString(content: unknown): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify(content));\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n return hashHex;\n}\n\n// Export both functions\nexport { redactData, redactValue, constructScope, parseScope, getContentHashString };\n"]}
|
|
@@ -89,7 +89,15 @@ function parseScope(scope) {
|
|
|
89
89
|
}
|
|
90
90
|
throw new Error(`Unsupported scope format: ${scope}`);
|
|
91
91
|
}
|
|
92
|
+
async function getContentHashString(content) {
|
|
93
|
+
const encoder = new TextEncoder();
|
|
94
|
+
const data = encoder.encode(JSON.stringify(content));
|
|
95
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
96
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
97
|
+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
98
|
+
return hashHex;
|
|
99
|
+
}
|
|
92
100
|
|
|
93
|
-
export { constructScope, parseScope, redactData, redactValue };
|
|
101
|
+
export { constructScope, getContentHashString, parseScope, redactData, redactValue };
|
|
94
102
|
//# sourceMappingURL=server-client-utils.mjs.map
|
|
95
103
|
//# sourceMappingURL=server-client-utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/server-client-utils.ts"],"names":[],"mappings":"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","file":"server-client-utils.mjs","sourcesContent":["/*\n * These are utils that are safe to use both on the server and the client.\n */\n\n/**\n * Helper function to redact sensitive data from specified attributes\n * @param data - The object containing data to redact\n * @param attributesToRedact - Single attribute name or array of attribute names to redact\n * @returns A new object with specified attributes redacted\n */\nfunction redactData(data: any, attributesToRedact: string | string[]): any {\n if (!data || typeof data !== 'object') {\n return data;\n }\n\n const attributes = Array.isArray(attributesToRedact) ? attributesToRedact : [attributesToRedact];\n const redacted = { ...data };\n\n for (const attr of attributes) {\n if (attr in redacted) {\n redacted[attr] = redactValue(redacted[attr]);\n }\n }\n\n return redacted;\n}\n\n/**\n * Recursively redacts a value based on its type\n * @param value - The value to redact\n * @returns The redacted value\n */\nfunction redactValue(value: any): any {\n if (typeof value === 'string') {\n return '[REDACTED]';\n } else if (Array.isArray(value)) {\n return value.map((item) => redactValue(item));\n } else if (value && typeof value === 'object') {\n const redactedObj: any = {};\n for (const key in value) {\n if (value.hasOwnProperty(key)) {\n redactedObj[key] = redactValue(value[key]);\n }\n }\n return redactedObj;\n }\n return value; // Return as-is for other types (numbers, booleans, null, etc.)\n}\n\n/**\n * Validates that a scope value doesn't contain the '#' character which is reserved for scope construction\n */\nfunction validateScopeValue(scopeValue: string | number | Record<string, string | number>, scopeType: string): void {\n if (typeof scopeValue === 'string' && scopeValue.includes('#')) {\n throw new Error(`Scope value cannot contain '#' character. Found in ${scopeType} scope value: ${scopeValue}`);\n }\n if (typeof scopeValue === 'object' && scopeValue !== null) {\n for (const [key, value] of Object.entries(scopeValue)) {\n if (typeof value === 'string' && value.includes('#')) {\n throw new Error(`Scope value cannot contain '#' character. Found in ${scopeType}.${key}: ${value}`);\n }\n }\n }\n}\n\n/**\n * Constructs a scope string from scopeType and scopeValue\n * @param scopeType - The type of scope (chatapp, agent, tool, entity, agent-entity)\n * @param scopeValue - The value(s) for the scope\n * @returns The constructed scope string\n */\nfunction constructScope(scopeType: string, scopeValue: string | number | Record<string, string | number>): string {\n // Validate scope value doesn't contain '#'\n validateScopeValue(scopeValue, scopeType);\n\n switch (scopeType) {\n case 'chatapp':\n case 'agent':\n case 'tool':\n case 'entity':\n return `${scopeType}#${scopeValue}`;\n case 'agent-entity':\n if (typeof scopeValue !== 'object' || scopeValue === null) {\n throw new Error('agent-entity scopeType requires an object with agent and entity properties');\n }\n\n const agentEntityValue = scopeValue as Record<string, string | number>;\n if (!('agent' in agentEntityValue) || !('entity' in agentEntityValue)) {\n throw new Error('agent-entity scopeType requires an object with both agent and entity properties');\n }\n\n return `agent#${agentEntityValue.agent}#entity#${agentEntityValue.entity}`;\n\n default:\n throw new Error(`Unsupported scopeType: ${scopeType}`);\n }\n}\n\n/**\n * Parses a scope string back into scopeType and scopeValue\n * @param scope - The scope string to parse\n * @returns Object containing scopeType and scopeValue\n */\nfunction parseScope(scope: string): { scopeType: string; scopeValue: string | number | Record<string, string | number> } {\n if (!scope || typeof scope !== 'string') {\n throw new Error('Invalid scope: must be a non-empty string');\n }\n\n const parts = scope.split('#');\n if (parts.length < 2) {\n throw new Error(`Invalid scope format: ${scope}. Expected format: scopeType#scopeValue`);\n }\n\n const [firstType, firstValue, ...remaining] = parts;\n\n // Handle compound scopes (agent-entity)\n if (remaining.length >= 2 && firstType === 'agent' && remaining[0] === 'entity') {\n return {\n scopeType: 'agent-entity',\n scopeValue: {\n agent: firstValue,\n entity: remaining[1]\n }\n };\n }\n\n // Handle simple scopes\n if (remaining.length === 0) {\n // For simple scopes, try to convert to number if it's numeric\n const numericValue = Number(firstValue);\n const scopeValue = !isNaN(numericValue) && isFinite(numericValue) ? numericValue : firstValue;\n\n return {\n scopeType: firstType,\n scopeValue: scopeValue\n };\n }\n\n throw new Error(`Unsupported scope format: ${scope}`);\n}\n\n// Export both functions\nexport { redactData, redactValue, constructScope, parseScope };\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/util/server-client-utils.ts"],"names":[],"mappings":";AAUA,SAAS,UAAA,CAAW,MAAW,kBAAA,EAA4C;AACvE,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACnC,IAAA,OAAO,IAAA;AAAA,EACX;AAEA,EAAA,MAAM,aAAa,KAAA,CAAM,OAAA,CAAQ,kBAAkB,CAAA,GAAI,kBAAA,GAAqB,CAAC,kBAAkB,CAAA;AAC/F,EAAA,MAAM,QAAA,GAAW,EAAE,GAAG,IAAA,EAAK;AAE3B,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC3B,IAAA,IAAI,QAAQ,QAAA,EAAU;AAClB,MAAA,QAAA,CAAS,IAAI,CAAA,GAAI,WAAA,CAAY,QAAA,CAAS,IAAI,CAAC,CAAA;AAAA,IAC/C;AAAA,EACJ;AAEA,EAAA,OAAO,QAAA;AACX;AAOA,SAAS,YAAY,KAAA,EAAiB;AAClC,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC3B,IAAA,OAAO,YAAA;AAAA,EACX,CAAA,MAAA,IAAW,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC7B,IAAA,OAAO,MAAM,GAAA,CAAI,CAAC,IAAA,KAAS,WAAA,CAAY,IAAI,CAAC,CAAA;AAAA,EAChD,CAAA,MAAA,IAAW,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AAC3C,IAAA,MAAM,cAAmB,EAAC;AAC1B,IAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACrB,MAAA,IAAI,KAAA,CAAM,cAAA,CAAe,GAAG,CAAA,EAAG;AAC3B,QAAA,WAAA,CAAY,GAAG,CAAA,GAAI,WAAA,CAAY,KAAA,CAAM,GAAG,CAAC,CAAA;AAAA,MAC7C;AAAA,IACJ;AACA,IAAA,OAAO,WAAA;AAAA,EACX;AACA,EAAA,OAAO,KAAA;AACX;AAKA,SAAS,kBAAA,CAAmB,YAA+D,SAAA,EAAyB;AAChH,EAAA,IAAI,OAAO,UAAA,KAAe,QAAA,IAAY,UAAA,CAAW,QAAA,CAAS,GAAG,CAAA,EAAG;AAC5D,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mDAAA,EAAsD,SAAS,CAAA,cAAA,EAAiB,UAAU,CAAA,CAAE,CAAA;AAAA,EAChH;AACA,EAAA,IAAI,OAAO,UAAA,KAAe,QAAA,IAAY,UAAA,KAAe,IAAA,EAAM;AACvD,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AACnD,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,QAAA,CAAS,GAAG,CAAA,EAAG;AAClD,QAAA,MAAM,IAAI,MAAM,CAAA,mDAAA,EAAsD,SAAS,IAAI,GAAG,CAAA,EAAA,EAAK,KAAK,CAAA,CAAE,CAAA;AAAA,MACtG;AAAA,IACJ;AAAA,EACJ;AACJ;AAQA,SAAS,cAAA,CAAe,WAAmB,UAAA,EAAuE;AAE9G,EAAA,kBAAA,CAAmB,YAAY,SAAS,CAAA;AAExC,EAAA,QAAQ,SAAA;AAAW,IACf,KAAK,SAAA;AAAA,IACL,KAAK,OAAA;AAAA,IACL,KAAK,MAAA;AAAA,IACL,KAAK,QAAA;AACD,MAAA,OAAO,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAAA,IACrC,KAAK,cAAA;AACD,MAAA,IAAI,OAAO,UAAA,KAAe,QAAA,IAAY,UAAA,KAAe,IAAA,EAAM;AACvD,QAAA,MAAM,IAAI,MAAM,4EAA4E,CAAA;AAAA,MAChG;AAEA,MAAA,MAAM,gBAAA,GAAmB,UAAA;AACzB,MAAA,IAAI,EAAE,OAAA,IAAW,gBAAA,CAAA,IAAqB,EAAE,YAAY,gBAAA,CAAA,EAAmB;AACnE,QAAA,MAAM,IAAI,MAAM,iFAAiF,CAAA;AAAA,MACrG;AAEA,MAAA,OAAO,CAAA,MAAA,EAAS,gBAAA,CAAiB,KAAK,CAAA,QAAA,EAAW,iBAAiB,MAAM,CAAA,CAAA;AAAA,IAE5E;AACI,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,SAAS,CAAA,CAAE,CAAA;AAAA;AAEjE;AAOA,SAAS,WAAW,KAAA,EAAqG;AACrH,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACrC,IAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,EAC/D;AAEA,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA;AAC7B,EAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AAClB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,KAAK,CAAA,uCAAA,CAAyC,CAAA;AAAA,EAC3F;AAEA,EAAA,MAAM,CAAC,SAAA,EAAW,UAAA,EAAY,GAAG,SAAS,CAAA,GAAI,KAAA;AAG9C,EAAA,IAAI,SAAA,CAAU,UAAU,CAAA,IAAK,SAAA,KAAc,WAAW,SAAA,CAAU,CAAC,MAAM,QAAA,EAAU;AAC7E,IAAA,OAAO;AAAA,MACH,SAAA,EAAW,cAAA;AAAA,MACX,UAAA,EAAY;AAAA,QACR,KAAA,EAAO,UAAA;AAAA,QACP,MAAA,EAAQ,UAAU,CAAC;AAAA;AACvB,KACJ;AAAA,EACJ;AAGA,EAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAExB,IAAA,MAAM,YAAA,GAAe,OAAO,UAAU,CAAA;AACtC,IAAA,MAAM,UAAA,GAAa,CAAC,KAAA,CAAM,YAAY,KAAK,QAAA,CAAS,YAAY,IAAI,YAAA,GAAe,UAAA;AAEnF,IAAA,OAAO;AAAA,MACH,SAAA,EAAW,SAAA;AAAA,MACX;AAAA,KACJ;AAAA,EACJ;AAEA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,KAAK,CAAA,CAAE,CAAA;AACxD;AAKA,eAAe,qBAAqB,OAAA,EAAmC;AACnE,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,OAAO,OAAA,CAAQ,MAAA,CAAO,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AACnD,EAAA,MAAM,aAAa,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,IAAI,CAAA;AAC7D,EAAA,MAAM,YAAY,KAAA,CAAM,IAAA,CAAK,IAAI,UAAA,CAAW,UAAU,CAAC,CAAA;AACvD,EAAA,MAAM,OAAA,GAAU,SAAA,CAAU,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,SAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAC7E,EAAA,OAAO,OAAA;AACX","file":"server-client-utils.mjs","sourcesContent":["/*\n * These are utils that are safe to use both on the server and the client.\n */\n\n/**\n * Helper function to redact sensitive data from specified attributes\n * @param data - The object containing data to redact\n * @param attributesToRedact - Single attribute name or array of attribute names to redact\n * @returns A new object with specified attributes redacted\n */\nfunction redactData(data: any, attributesToRedact: string | string[]): any {\n if (!data || typeof data !== 'object') {\n return data;\n }\n\n const attributes = Array.isArray(attributesToRedact) ? attributesToRedact : [attributesToRedact];\n const redacted = { ...data };\n\n for (const attr of attributes) {\n if (attr in redacted) {\n redacted[attr] = redactValue(redacted[attr]);\n }\n }\n\n return redacted;\n}\n\n/**\n * Recursively redacts a value based on its type\n * @param value - The value to redact\n * @returns The redacted value\n */\nfunction redactValue(value: any): any {\n if (typeof value === 'string') {\n return '[REDACTED]';\n } else if (Array.isArray(value)) {\n return value.map((item) => redactValue(item));\n } else if (value && typeof value === 'object') {\n const redactedObj: any = {};\n for (const key in value) {\n if (value.hasOwnProperty(key)) {\n redactedObj[key] = redactValue(value[key]);\n }\n }\n return redactedObj;\n }\n return value; // Return as-is for other types (numbers, booleans, null, etc.)\n}\n\n/**\n * Validates that a scope value doesn't contain the '#' character which is reserved for scope construction\n */\nfunction validateScopeValue(scopeValue: string | number | Record<string, string | number>, scopeType: string): void {\n if (typeof scopeValue === 'string' && scopeValue.includes('#')) {\n throw new Error(`Scope value cannot contain '#' character. Found in ${scopeType} scope value: ${scopeValue}`);\n }\n if (typeof scopeValue === 'object' && scopeValue !== null) {\n for (const [key, value] of Object.entries(scopeValue)) {\n if (typeof value === 'string' && value.includes('#')) {\n throw new Error(`Scope value cannot contain '#' character. Found in ${scopeType}.${key}: ${value}`);\n }\n }\n }\n}\n\n/**\n * Constructs a scope string from scopeType and scopeValue\n * @param scopeType - The type of scope (chatapp, agent, tool, entity, agent-entity)\n * @param scopeValue - The value(s) for the scope\n * @returns The constructed scope string\n */\nfunction constructScope(scopeType: string, scopeValue: string | number | Record<string, string | number>): string {\n // Validate scope value doesn't contain '#'\n validateScopeValue(scopeValue, scopeType);\n\n switch (scopeType) {\n case 'chatapp':\n case 'agent':\n case 'tool':\n case 'entity':\n return `${scopeType}#${scopeValue}`;\n case 'agent-entity':\n if (typeof scopeValue !== 'object' || scopeValue === null) {\n throw new Error('agent-entity scopeType requires an object with agent and entity properties');\n }\n\n const agentEntityValue = scopeValue as Record<string, string | number>;\n if (!('agent' in agentEntityValue) || !('entity' in agentEntityValue)) {\n throw new Error('agent-entity scopeType requires an object with both agent and entity properties');\n }\n\n return `agent#${agentEntityValue.agent}#entity#${agentEntityValue.entity}`;\n\n default:\n throw new Error(`Unsupported scopeType: ${scopeType}`);\n }\n}\n\n/**\n * Parses a scope string back into scopeType and scopeValue\n * @param scope - The scope string to parse\n * @returns Object containing scopeType and scopeValue\n */\nfunction parseScope(scope: string): { scopeType: string; scopeValue: string | number | Record<string, string | number> } {\n if (!scope || typeof scope !== 'string') {\n throw new Error('Invalid scope: must be a non-empty string');\n }\n\n const parts = scope.split('#');\n if (parts.length < 2) {\n throw new Error(`Invalid scope format: ${scope}. Expected format: scopeType#scopeValue`);\n }\n\n const [firstType, firstValue, ...remaining] = parts;\n\n // Handle compound scopes (agent-entity)\n if (remaining.length >= 2 && firstType === 'agent' && remaining[0] === 'entity') {\n return {\n scopeType: 'agent-entity',\n scopeValue: {\n agent: firstValue,\n entity: remaining[1]\n }\n };\n }\n\n // Handle simple scopes\n if (remaining.length === 0) {\n // For simple scopes, try to convert to number if it's numeric\n const numericValue = Number(firstValue);\n const scopeValue = !isNaN(numericValue) && isFinite(numericValue) ? numericValue : firstValue;\n\n return {\n scopeType: firstType,\n scopeValue: scopeValue\n };\n }\n\n throw new Error(`Unsupported scope format: ${scope}`);\n}\n\n/**\n * Useful for simple hashing like to figure out if content has changed since last sent or something.\n */\nasync function getContentHashString(content: unknown): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify(content));\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n return hashHex;\n}\n\n// Export both functions\nexport { redactData, redactValue, constructScope, parseScope, getContentHashString };\n"]}
|