@pillar-ai/sdk 0.1.14 → 0.1.15

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.
@@ -2,31 +2,54 @@
2
2
  * Chat Store
3
3
  * Signal-based state for chat messages and interaction
4
4
  */
5
- import type { ArticleSummary, ChatMessage } from '../api/client';
6
- import type { ChatImage } from '../api/mcp-client';
7
- import type { TaskButtonData } from '../components/Panel/TaskButton';
8
- import type { UserContextItem } from '../types/user-context';
9
- export type { ChatImage } from '../api/mcp-client';
5
+ import type { ArticleSummary, ChatMessage, ConversationSummary, HistoryMessage } from "../api/client";
6
+ import type { ChatImage } from "../api/mcp-client";
7
+ import type { TaskButtonData } from "../components/Panel/TaskButton";
8
+ import type { UserContextItem } from "../types/user-context";
9
+ export type { ChatImage } from "../api/mcp-client";
10
10
  export interface ActionStatus {
11
- status: 'pending' | 'success' | 'failed';
11
+ status: "pending" | "success" | "failed";
12
12
  completedAt?: number;
13
13
  errorMessage?: string;
14
14
  }
15
+ /**
16
+ * A segment in an assistant message's timeline.
17
+ * Segments maintain chronological order so text and tool blocks interleave correctly.
18
+ *
19
+ * - "text": Model-generated content tokens (narration or final response)
20
+ * - "progress": A group of progress events (thinking, search, tool calls)
21
+ */
22
+ export type MessageSegment = {
23
+ type: "text";
24
+ content: string;
25
+ } | {
26
+ type: "progress";
27
+ events: ProgressEvent[];
28
+ };
15
29
  export interface StoredChatMessage extends ChatMessage {
16
30
  id?: string;
17
- feedback?: 'up' | 'down' | null;
31
+ feedback?: "up" | "down" | null;
18
32
  actions?: TaskButtonData[];
19
33
  sources?: ArticleSummary[];
20
34
  actionStatus?: Record<string, ActionStatus>;
21
35
  userContext?: UserContextItem[];
22
36
  images?: ChatImage[];
23
37
  progressEvents?: ProgressEvent[];
38
+ segments?: MessageSegment[];
24
39
  }
25
40
  export declare const messages: import("@preact/signals-core").Signal<StoredChatMessage[]>;
26
41
  export declare const conversationId: import("@preact/signals-core").Signal<string | null>;
27
42
  export declare const registeredActions: import("@preact/signals-core").Signal<Record<string, unknown>[]>;
28
43
  export declare const historyInvalidationCounter: import("@preact/signals-core").Signal<number>;
44
+ export declare const optimisticConversations: import("@preact/signals-core").Signal<ConversationSummary[]>;
45
+ /**
46
+ * Read the persisted conversation ID from localStorage (e.g. for restore on refresh).
47
+ */
48
+ export declare function getStoredConversationId(): string | null;
29
49
  export declare const isLoading: import("@preact/signals-core").Signal<boolean>;
50
+ export declare const activeRequestId: import("@preact/signals-core").Signal<number | null>;
51
+ export declare const setActiveRequestId: (id: number | null) => void;
52
+ export declare const isLoadingHistory: import("@preact/signals-core").Signal<boolean>;
30
53
  export interface InterruptedSession {
31
54
  conversationId: string;
32
55
  userMessage: string;
@@ -35,6 +58,30 @@ export interface InterruptedSession {
35
58
  elapsedMs: number;
36
59
  }
37
60
  export declare const interruptedSession: import("@preact/signals-core").Signal<InterruptedSession | null>;
61
+ export interface TokenUsageState {
62
+ /** Input tokens for the latest iteration */
63
+ promptTokens: number;
64
+ /** Output tokens for the latest iteration */
65
+ completionTokens: number;
66
+ /** Cumulative prompt tokens across all iterations */
67
+ totalPromptTokens: number;
68
+ /** Cumulative completion tokens across all iterations */
69
+ totalCompletionTokens: number;
70
+ /** Current total tokens in context */
71
+ totalUsed: number;
72
+ /** Maximum context window for the model */
73
+ contextWindow: number;
74
+ /** Current context occupancy percentage (0-100) */
75
+ occupancyPct: number;
76
+ /** Name of the model in use */
77
+ modelName: string;
78
+ /** Current iteration number (0-indexed) */
79
+ iteration: number;
80
+ }
81
+ /** Current token usage for the active streaming response */
82
+ export declare const tokenUsage: import("@preact/signals-core").Signal<TokenUsageState | null>;
83
+ export declare const updateTokenUsage: (usage: TokenUsageState) => void;
84
+ export declare const clearTokenUsage: () => void;
38
85
  export interface ProgressStatus {
39
86
  kind: string | null;
40
87
  message?: string;
@@ -59,7 +106,7 @@ export interface ProgressEvent {
59
106
  kind: string;
60
107
  id?: string;
61
108
  label?: string;
62
- status?: 'active' | 'done' | 'error';
109
+ status?: "active" | "done" | "error";
63
110
  text?: string;
64
111
  children?: ProgressChild[];
65
112
  metadata?: Record<string, unknown>;
@@ -85,6 +132,12 @@ export declare const progressEvents: import("@preact/signals-core").Signal<Progr
85
132
  * This prevents multiple rows from appearing for the same event.
86
133
  */
87
134
  export declare const addProgressEventToLastMessage: (event: ProgressEvent) => void;
135
+ /**
136
+ * Append a content token to the last assistant message's segments array.
137
+ * Creates a new text segment or appends to an existing one, while also
138
+ * updating `content` for backward compat (history persistence, feedback, etc.).
139
+ */
140
+ export declare const appendTokenToSegments: (token: string) => void;
88
141
  export declare const isExpanded: import("@preact/signals-core").Signal<boolean>;
89
142
  /**
90
143
  * @deprecated Sources are now stored per-message on `StoredChatMessage.sources`. Will be removed in v2.0.
@@ -104,7 +157,7 @@ export declare const submitPendingTrigger: import("@preact/signals-core").Signal
104
157
  export declare const focusInputTrigger: import("@preact/signals-core").Signal<number>;
105
158
  export declare const userContext: import("@preact/signals-core").Signal<UserContextItem[]>;
106
159
  export declare const pendingUserContext: import("@preact/signals-core").Signal<UserContextItem[]>;
107
- export type ImageUploadStatus = 'uploading' | 'ready' | 'error';
160
+ export type ImageUploadStatus = "uploading" | "ready" | "error";
108
161
  export interface PendingImage {
109
162
  id: string;
110
163
  file: File;
@@ -154,10 +207,24 @@ export declare const clearActions: () => void;
154
207
  export declare const setLoading: (loading: boolean) => void;
155
208
  export declare const setProgressStatus: (status: ProgressStatus) => void;
156
209
  export declare const clearProgressStatus: () => void;
210
+ /**
211
+ * Mark all active progress events on the last assistant message as "done".
212
+ * Called when the user cancels/stops streaming so thinking timers stop.
213
+ */
214
+ export declare const finalizeActiveProgressEvents: () => void;
157
215
  export declare const addProgressEvent: (event: ProgressEvent) => void;
158
216
  export declare const clearProgressEvents: () => void;
159
217
  export declare const setInterruptedSession: (session: InterruptedSession | null) => void;
160
218
  export declare const clearInterruptedSession: () => void;
219
+ /**
220
+ * Remove the last assistant message if it has no content AND no progress events.
221
+ * Used after Stop / AbortError to clean up the empty placeholder
222
+ * that was added before streaming started.
223
+ *
224
+ * If the model was thinking (progress events exist), the message is kept
225
+ * so the user can still see the thinking text that was streamed.
226
+ */
227
+ export declare const removeLastEmptyAssistantMessage: () => void;
161
228
  export declare const expandChat: () => void;
162
229
  export declare const collapseChat: () => void;
163
230
  export declare const setPrefillText: (text: string) => void;
@@ -172,12 +239,28 @@ export declare const clearUserContext: () => void;
172
239
  export declare const setPendingUserContext: (items: UserContextItem[]) => void;
173
240
  export declare const clearPendingUserContext: () => void;
174
241
  export declare const resetChat: () => void;
242
+ /**
243
+ * Start loading a conversation from history.
244
+ * Shows loading state immediately for better UX.
245
+ */
246
+ export declare const startLoadingHistory: () => void;
175
247
  /**
176
248
  * Load a conversation from history.
177
249
  * Populates the chat with messages from a previous conversation.
178
250
  */
179
- export declare const loadConversation: (id: string, historyMessages: Array<{
180
- role: "user" | "assistant";
181
- content: string;
182
- id?: string;
183
- }>) => void;
251
+ export declare const loadConversation: (id: string, historyMessages: HistoryMessage[]) => void;
252
+ /**
253
+ * Stop loading history (on error or cancellation).
254
+ */
255
+ export declare const stopLoadingHistory: () => void;
256
+ /**
257
+ * Optimistically add a new conversation to the history list.
258
+ * The conversation appears immediately in the dropdown without
259
+ * waiting for the server to confirm via listConversations.
260
+ */
261
+ export declare const addOptimisticConversation: (id: string, title: string) => void;
262
+ /**
263
+ * Select and load a conversation by ID (fetch from API, navigate to chat, load messages).
264
+ * Use from history dropdown or anywhere else in the SDK that needs to open a past conversation.
265
+ */
266
+ export declare const selectConversationById: (conversationId: string) => Promise<void>;
@@ -8,3 +8,4 @@ export * as chatStore from './chat';
8
8
  export * as contextStore from './context';
9
9
  export * as workflowStore from './workflow';
10
10
  export * as suggestionsStore from './suggestions';
11
+ export * as pagePilotStore from './pagePilot';
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Page Pilot Store
3
+ * Signal-based state for tracking when the AI agent is piloting the page
4
+ * (executing interact_with_page actions like click, type, select, etc.)
5
+ */
6
+ /** Current piloting operation type */
7
+ export type PilotOperation = 'click' | 'type' | 'select' | 'focus' | 'toggle' | null;
8
+ /** Whether page interaction is currently in progress */
9
+ export declare const isPiloting: import("@preact/signals-core").Signal<boolean>;
10
+ /** Current operation type being performed */
11
+ export declare const pilotOperation: import("@preact/signals-core").Signal<PilotOperation>;
12
+ /** Flag to indicate cancellation was requested */
13
+ export declare const isCancelled: import("@preact/signals-core").Signal<boolean>;
14
+ /** Tool call ID of the current action (for sending cancellation result) */
15
+ export declare const currentToolCallId: import("@preact/signals-core").Signal<string | null>;
16
+ /**
17
+ * Start piloting mode - called when an interact_with_page action begins
18
+ */
19
+ export declare function startPiloting(operation: PilotOperation, toolCallId?: string): void;
20
+ /**
21
+ * Stop piloting mode - called when an interact_with_page action completes
22
+ */
23
+ export declare function stopPiloting(): void;
24
+ /**
25
+ * Cancel the current piloting action - called when user clicks Stop
26
+ */
27
+ export declare function cancelPiloting(): void;
28
+ /**
29
+ * Reset cancellation flag after it's been handled
30
+ */
31
+ export declare function resetCancellation(): void;
32
+ /**
33
+ * Check if cancellation was requested
34
+ */
35
+ export declare function wasCancelled(): boolean;
36
+ /** Whether a destructive action is awaiting user confirmation */
37
+ export declare const needsConfirmation: import("@preact/signals-core").Signal<boolean>;
38
+ /** Human-readable description of the action pending confirmation */
39
+ export declare const confirmationLabel: import("@preact/signals-core").Signal<string | null>;
40
+ /** Resolver function for the confirmation promise */
41
+ export declare const confirmationResolver: import("@preact/signals-core").Signal<((confirmed: boolean) => void) | null>;
42
+ /**
43
+ * Request user confirmation for a destructive action.
44
+ * Shows a confirmation UI and returns a Promise that resolves when the user responds.
45
+ *
46
+ * @param label - Description of the action (e.g., 'Agent wants to click "Delete Account"')
47
+ * @returns Promise<boolean> - true if user confirmed, false if denied
48
+ */
49
+ export declare function requestConfirmation(label: string): Promise<boolean>;
50
+ /**
51
+ * Resolve the pending confirmation request.
52
+ * Called by the UI when the user clicks Allow or Deny.
53
+ *
54
+ * @param confirmed - Whether the user confirmed the action
55
+ */
56
+ export declare function resolveConfirmation(confirmed: boolean): void;
@@ -2,12 +2,12 @@
2
2
  * Suggestions Store
3
3
  * Signal-based state for page-aware suggested questions
4
4
  *
5
- * The backend generates a pool of 15-20 diverse suggestions.
5
+ * The backend generates a small set of suggested questions.
6
6
  * This store sorts them client-side based on page relevance
7
7
  * for instant page-aware suggestions without additional LLM calls.
8
8
  */
9
9
  import type { SuggestedQuestion } from '../api/client';
10
- /** Base suggestion pool from backend (15-20 suggestions) */
10
+ /** Base suggestion pool from backend */
11
11
  export declare const suggestionPool: import("@preact/signals-core").Signal<SuggestedQuestion[]>;
12
12
  /** Currently displayed suggestions (sorted by page relevance) */
13
13
  export declare const suggestions: import("@preact/signals-core").Signal<SuggestedQuestion[]>;
@@ -20,6 +20,10 @@ export interface ScanOptions {
20
20
  minTextLength?: number;
21
21
  /** Maximum text length before truncation (default: 500) */
22
22
  maxTextLength?: number;
23
+ /** Maximum total output length in characters (default: 50000) */
24
+ maxTotalLength?: number;
25
+ /** Maximum label length for interactable elements (default: 100) */
26
+ maxLabelLength?: number;
23
27
  /** Include element positions/coordinates (default: false) */
24
28
  includePositions?: boolean;
25
29
  }
@@ -8,6 +8,22 @@ import { type CompactScanResult, type InteractionType, type ScanOptions } from "
8
8
  * Called before scanning to remove stale refs.
9
9
  */
10
10
  export declare function clearPillarRefs(): void;
11
+ /**
12
+ * Check if an element or any of its ancestors is marked for redaction.
13
+ * Elements with `data-pillar-redact` or password inputs are redacted.
14
+ * Their text content is replaced with [REDACTED] in scan output.
15
+ */
16
+ export declare function isRedacted(el: Element): boolean;
17
+ /**
18
+ * Check if an element represents a destructive action.
19
+ * Used to gate interactions behind user confirmation.
20
+ *
21
+ * Returns true if:
22
+ * - The element has `data-pillar-destructive` attribute (explicit opt-in)
23
+ * - The element's label or text content contains destructive keywords
24
+ * - The element is a reset/submit button on a form with "delete" in its action URL
25
+ */
26
+ export declare function isDestructiveElement(el: Element): boolean;
11
27
  /**
12
28
  * Check if an element is interactable
13
29
  */
@@ -16,12 +32,22 @@ export declare function isInteractable(el: Element): boolean;
16
32
  * Determine the interaction type for an element
17
33
  */
18
34
  export declare function getInteractionType(el: Element): InteractionType;
35
+ /**
36
+ * Validate that a ref string matches the expected pillar ref format.
37
+ * Prevents CSS selector injection from malformed/malicious ref values.
38
+ *
39
+ * @param ref - Ref string to validate
40
+ * @returns true if the ref matches the expected format
41
+ */
42
+ export declare function isValidPillarRef(ref: string): boolean;
19
43
  /**
20
44
  * Build full selector from short ref ID.
21
45
  * Converts "pr-abc" to '[data-pillar-ref="pr-abc"]'
46
+ * Throws if the ref format is invalid to prevent CSS selector injection.
22
47
  *
23
48
  * @param shortRef - Short ref ID (e.g., "pr-abc")
24
49
  * @returns Full CSS selector for querySelector
50
+ * @throws Error if the ref format is invalid
25
51
  */
26
52
  export declare function buildSelectorFromRef(shortRef: string): string;
27
53
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pillar-ai/sdk",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Pillar Embedded Help SDK - Add contextual help and AI chat to your application",
5
5
  "type": "module",
6
6
  "main": "./dist/pillar.esm.js",
@@ -182,6 +182,19 @@ export interface ActionDefinition<TData = Record<string, unknown>> {
182
182
  */
183
183
  returns?: boolean;
184
184
 
185
+ /**
186
+ * Concrete examples of valid parameter objects for the AI to reference.
187
+ *
188
+ * Each example should have a `description` explaining the scenario
189
+ * and a `parameters` object matching the `dataSchema`.
190
+ * Useful for complex schemas where the AI benefits from seeing
191
+ * what a correct call looks like.
192
+ */
193
+ parameterExamples?: Array<{
194
+ description: string;
195
+ parameters: Record<string, unknown>;
196
+ }>;
197
+
185
198
  /**
186
199
  * Handler function executed when the action is triggered.
187
200
  *
@@ -216,6 +229,10 @@ export interface ActionManifestEntry {
216
229
  data_schema?: ActionDataSchema;
217
230
  default_data?: Record<string, unknown>;
218
231
  required_context?: Record<string, unknown>;
232
+ parameter_examples?: Array<{
233
+ description: string;
234
+ parameters: Record<string, unknown>;
235
+ }>;
219
236
  }
220
237
 
221
238
  /**
@@ -248,6 +265,12 @@ export interface ActionManifest {
248
265
  * Action definitions (without handlers).
249
266
  */
250
267
  actions: ActionManifestEntry[];
268
+
269
+ /**
270
+ * Custom agent guidance synced alongside actions.
271
+ * Injected into the AI agent's prompt as product_guidance.
272
+ */
273
+ agentGuidance?: string;
251
274
  }
252
275
 
253
276
  /**
@@ -314,6 +337,16 @@ export interface SyncActionDefinition<TData = Record<string, unknown>> {
314
337
  * If true, the handler's return value is sent back to the agent.
315
338
  */
316
339
  returns?: boolean;
340
+
341
+ /**
342
+ * Concrete examples of valid parameter objects for the AI to reference.
343
+ * Each example should have a `description` and a `parameters` object
344
+ * matching the `dataSchema`.
345
+ */
346
+ parameterExamples?: Array<{
347
+ description: string;
348
+ parameters: Record<string, unknown>;
349
+ }>;
317
350
  }
318
351
 
319
352
  /**