@pillar-ai/sdk 0.1.13 → 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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -44
  3. package/dist/actions/types.d.ts +39 -3
  4. package/dist/api/client.d.ts +119 -16
  5. package/dist/api/mcp-client.d.ts +137 -87
  6. package/dist/cli/sync.js +72 -13
  7. package/dist/components/DebugPanel/DebugPanel.d.ts +25 -0
  8. package/dist/components/DebugPanel/index.d.ts +2 -0
  9. package/dist/components/DevTools/index.d.ts +5 -0
  10. package/dist/components/DevTools/styles.d.ts +5 -0
  11. package/dist/components/PagePilot/PagePilotBanner.d.ts +7 -0
  12. package/dist/components/PagePilot/PagePilotManager.d.ts +42 -0
  13. package/dist/components/PagePilot/index.d.ts +7 -0
  14. package/dist/components/PagePilot/styles.d.ts +6 -0
  15. package/dist/components/Panel/Header.d.ts +3 -5
  16. package/dist/components/Panel/HistoryDropdown.d.ts +10 -0
  17. package/dist/components/Panel/PanelContent.d.ts +1 -2
  18. package/dist/components/Panel/TaskButton.d.ts +4 -14
  19. package/dist/components/Panel/UnifiedChatInput.d.ts +5 -1
  20. package/dist/components/Panel/styles.d.ts +2 -2
  21. package/dist/components/Plan/InlinePlanView.d.ts +1 -1
  22. package/dist/components/Plan/PlanDocument.d.ts +18 -0
  23. package/dist/components/Plan/PlanStepItem.d.ts +1 -1
  24. package/dist/components/Plan/PlanView.d.ts +1 -1
  25. package/dist/components/Plan/index.d.ts +1 -0
  26. package/dist/components/Progress/ProgressGroup.d.ts +20 -0
  27. package/dist/components/Progress/ProgressRow.d.ts +9 -2
  28. package/dist/components/Progress/ProgressStack.d.ts +24 -0
  29. package/dist/components/Progress/ReasoningDisclosure.d.ts +16 -0
  30. package/dist/components/Progress/index.d.ts +2 -0
  31. package/dist/components/Views/HomeView.d.ts +3 -0
  32. package/dist/components/Views/ResumePrompt.d.ts +22 -0
  33. package/dist/components/Views/index.d.ts +1 -0
  34. package/dist/components/index.d.ts +1 -0
  35. package/dist/components/shared/icons.d.ts +24 -0
  36. package/dist/components/shared/index.d.ts +1 -0
  37. package/dist/core/Pillar.d.ts +325 -70
  38. package/dist/core/config.d.ts +133 -4
  39. package/dist/core/events.d.ts +55 -70
  40. package/dist/core/plan-executor.d.ts +29 -0
  41. package/dist/core/plan.d.ts +6 -0
  42. package/dist/hooks/index.d.ts +5 -0
  43. package/dist/hooks/useDebouncedValue.d.ts +22 -0
  44. package/dist/hooks/useInlineCard.d.ts +35 -0
  45. package/dist/hooks/usePillarInstance.d.ts +30 -0
  46. package/dist/index.d.ts +11 -9
  47. package/dist/pillar.esm.js +1 -1
  48. package/dist/store/chat.d.ts +185 -25
  49. package/dist/store/index.d.ts +2 -0
  50. package/dist/store/pagePilot.d.ts +56 -0
  51. package/dist/store/session-persistence.d.ts +62 -0
  52. package/dist/store/suggestions.d.ts +58 -0
  53. package/dist/types/dom-scanner.d.ts +50 -0
  54. package/dist/types/index.d.ts +1 -0
  55. package/dist/types/user-context.d.ts +32 -1
  56. package/dist/utils/debug.d.ts +150 -0
  57. package/dist/utils/dom-scanner.d.ts +70 -0
  58. package/dist/utils/markdown-components.d.ts +53 -0
  59. package/dist/utils/preact-markdown.d.ts +17 -0
  60. package/dist/utils/route-observer.d.ts +67 -0
  61. package/package.json +1 -1
  62. package/src/actions/types.ts +43 -2
  63. package/dist/utils/markdown.d.ts +0 -9
@@ -6,8 +6,8 @@
6
6
  */
7
7
  import type { TaskButtonData } from '../components/Panel/TaskButton';
8
8
  import type { ResolvedConfig } from '../core/config';
9
- import type { ExecutionPlan } from '../core/plan';
10
9
  import type { UserContextItem } from '../types/user-context';
10
+ import { type LogEntry } from '../utils/debug';
11
11
  import type { ArticleSummary } from './client';
12
12
  /** MCP Tool result content */
13
13
  interface ToolResultContent {
@@ -23,7 +23,8 @@ export interface ToolResult {
23
23
  structuredContent?: {
24
24
  sources?: ArticleSummary[];
25
25
  actions?: ActionData[];
26
- plan?: ExecutionPlan;
26
+ /** Registered actions for dynamic action tools (persisted across turns) */
27
+ registered_actions?: Record<string, unknown>[];
27
28
  };
28
29
  _meta?: {
29
30
  conversation_id?: string;
@@ -45,6 +46,38 @@ export interface ActionData {
45
46
  score: number;
46
47
  data: Record<string, unknown>;
47
48
  }
49
+ /** Action request from agent (unified for all action execution) */
50
+ export interface ActionRequest {
51
+ /** Action name to execute */
52
+ action_name: string;
53
+ /** Parameters for the action */
54
+ parameters: Record<string, unknown>;
55
+ /** Full action definition (optional, for handler lookup) */
56
+ action?: ActionData;
57
+ /** Unique ID for this specific tool invocation (for result correlation) */
58
+ tool_call_id?: string;
59
+ }
60
+ /** Token usage data from the agentic loop (sent after each LLM iteration) */
61
+ export interface TokenUsage {
62
+ /** Input tokens for this iteration */
63
+ prompt_tokens: number;
64
+ /** Output tokens for this iteration */
65
+ completion_tokens: number;
66
+ /** Cumulative prompt tokens across all iterations */
67
+ total_prompt_tokens: number;
68
+ /** Cumulative completion tokens across all iterations */
69
+ total_completion_tokens: number;
70
+ /** Current total tokens in context */
71
+ total_used: number;
72
+ /** Maximum context window for the model */
73
+ context_window: number;
74
+ /** Current context occupancy percentage (0-100) */
75
+ occupancy_pct: number;
76
+ /** Name of the model in use */
77
+ model_name: string;
78
+ /** Current iteration number (0-indexed) */
79
+ iteration: number;
80
+ }
48
81
  /** Streaming callbacks for tool calls */
49
82
  export interface StreamCallbacks {
50
83
  /** Called for each text token */
@@ -53,29 +86,36 @@ export interface StreamCallbacks {
53
86
  onSources?: (sources: ArticleSummary[]) => void;
54
87
  /** Called when actions are available */
55
88
  onActions?: (actions: ActionData[]) => void;
56
- /** Called when a plan is created (from plan.created event) */
57
- onPlan?: (plan: ExecutionPlan) => void;
89
+ /** Called when registered actions are received (for dynamic action tools) */
90
+ onRegisteredActions?: (actions: Record<string, unknown>[]) => void;
58
91
  /** Called on error */
59
92
  onError?: (error: string) => void;
93
+ /** Called when conversation_started event is received (confirms conversation tracking) */
94
+ onConversationStarted?: (conversationId: string, assistantMessageId?: string) => void;
60
95
  /** Called when stream is complete */
61
96
  onComplete?: (conversationId?: string, queryLogId?: string) => void;
62
- /** Called for progress updates (search, query, generating, etc.) */
97
+ /** Called for progress updates (search, query, generating, thinking, etc.) */
63
98
  onProgress?: (progress: {
64
99
  kind: string;
65
- message?: string;
100
+ id?: string;
101
+ label?: string;
102
+ status?: 'active' | 'done' | 'error';
103
+ text?: string;
104
+ children?: Array<{
105
+ id: string;
106
+ label: string;
107
+ url?: string;
108
+ }>;
109
+ metadata?: Record<string, unknown>;
66
110
  progress_id?: string;
67
- metadata?: {
68
- sources?: Array<{
69
- title: string;
70
- url: string;
71
- score?: number;
72
- }>;
73
- result_count?: number;
74
- query?: string;
75
- action_name?: string;
76
- no_sources_used?: boolean;
77
- };
111
+ message?: string;
78
112
  }) => void;
113
+ /** Called immediately with the request ID (for cancellation support) */
114
+ onRequestId?: (requestId: number) => void;
115
+ /** Called when agent requests action execution (unified handler) */
116
+ onActionRequest?: (request: ActionRequest) => Promise<void>;
117
+ /** Called when token usage is updated (after each LLM iteration) */
118
+ onTokenUsage?: (usage: TokenUsage) => void;
79
119
  }
80
120
  /** Image for chat requests (from upload-image endpoint) */
81
121
  export interface ChatImage {
@@ -92,7 +132,27 @@ export interface ImageUploadResponse {
92
132
  export declare class MCPClient {
93
133
  private config;
94
134
  private requestId;
135
+ private _externalUserId;
95
136
  constructor(config: ResolvedConfig);
137
+ /**
138
+ * Set the external user ID for authenticated users.
139
+ * Enables cross-device conversation history.
140
+ */
141
+ setExternalUserId(userId: string): void;
142
+ /**
143
+ * Get or create a persistent visitor ID.
144
+ * Stored in localStorage to persist across sessions.
145
+ */
146
+ private getVisitorId;
147
+ /**
148
+ * Get or create a session ID for MCP request correlation.
149
+ * Stored in sessionStorage to persist only for the current browser session.
150
+ */
151
+ private getSessionId;
152
+ /**
153
+ * Get the current page URL for analytics tracking.
154
+ */
155
+ private getPageUrl;
96
156
  private get baseUrl();
97
157
  private get headers();
98
158
  private nextId;
@@ -132,104 +192,94 @@ export declare class MCPClient {
132
192
  articleSlug?: string;
133
193
  userContext?: UserContextItem[];
134
194
  images?: ChatImage[];
195
+ history?: Array<{
196
+ role: 'user' | 'assistant';
197
+ content: string;
198
+ }>;
199
+ /** Registered actions from previous turns (for dynamic action tools) */
200
+ registeredActions?: Record<string, unknown>[];
135
201
  signal?: AbortSignal;
202
+ /** Conversation ID - generated client-side, always provided */
203
+ conversationId?: string;
136
204
  }): Promise<ToolResult>;
137
205
  /**
138
- * Continue plan execution after receiving step result.
206
+ * Cancel an active streaming request.
139
207
  *
140
- * Called by the SDK after executing a step that has
141
- * requires_result_feedback=true. The server analyzes the result
142
- * and updates subsequent steps if needed.
208
+ * Sends a notifications/cancel JSON-RPC request to the backend, which
209
+ * signals the StreamRegistry to stop the LLM stream and cease billing.
143
210
  *
144
- * @param planId - UUID of the plan
145
- * @param stepId - UUID of the completed step
146
- * @param result - Step execution result
147
- * @returns Updated plan with all steps
211
+ * @param requestId - The JSON-RPC request ID of the stream to cancel
148
212
  */
149
- continuePlan(planId: string, stepId: string, result: unknown): Promise<{
150
- plan: ExecutionPlan;
151
- }>;
213
+ cancelStream(requestId: number | string): Promise<void>;
152
214
  /**
153
- * Cancel an in-progress plan.
215
+ * Send action result back to the agent.
154
216
  *
155
- * Marks the plan as cancelled and skips any pending steps.
217
+ * Called after executing a query action (returns_data=true).
218
+ * The result is sent to the agent for further reasoning in the ReAct loop.
156
219
  *
157
- * @param planId - UUID of the plan to cancel
158
- * @returns Updated plan with cancelled status
220
+ * @param actionName - The name of the action that was executed
221
+ * @param result - The result data to send back to the agent
222
+ * @param toolCallId - Unique ID for this specific tool invocation (for result correlation)
223
+ * @returns Promise that resolves when the result is delivered, or rejects on error
159
224
  */
160
- cancelPlan(planId: string): Promise<{
161
- plan: ExecutionPlan;
162
- }>;
225
+ sendActionResult(actionName: string, result: unknown, toolCallId?: string): Promise<void>;
163
226
  /**
164
- * Get current state of a plan.
227
+ * Send a client-side log to the server for debugging.
165
228
  *
166
- * Returns the plan and all its steps with current statuses.
229
+ * Logs are correlated with agent sessions via the MCP session ID.
230
+ * Use this to forward important SDK events to server logs.
167
231
  *
168
- * @param planId - UUID of the plan
169
- * @returns Plan with all steps
232
+ * @param level - Log level: 'log', 'warn', or 'error'
233
+ * @param message - The log message
234
+ * @param data - Optional additional data to include
170
235
  */
171
- getPlan(planId: string): Promise<{
172
- plan: ExecutionPlan;
173
- }>;
236
+ sendLog(level: 'log' | 'warn' | 'error', message: string, data?: unknown): Promise<void>;
174
237
  /**
175
- * Start a plan that was waiting for user confirmation.
238
+ * Send a batch of client-side logs to the server.
176
239
  *
177
- * For plans with auto_execute=false, the user must explicitly
178
- * start execution by calling this method.
240
+ * Logs are buffered and sent periodically (every 5 seconds by default)
241
+ * to reduce network requests. This method is called by the debug module.
179
242
  *
180
- * @param planId - UUID of the plan to start
181
- * @returns Updated plan with executing status
243
+ * @param logs - Array of log entries to send
182
244
  */
183
- startPlan(planId: string): Promise<{
184
- plan: ExecutionPlan;
185
- }>;
245
+ sendLogBatch(logs: LogEntry[]): void;
186
246
  /**
187
- * Retry a failed step.
188
- *
189
- * Increments the retry count and resets the step to ready status.
190
- * Only works if the step is retriable and hasn't exceeded max_retries.
247
+ * Check if a conversation has a resumable interrupted session.
191
248
  *
192
- * @param planId - UUID of the plan
193
- * @param stepId - UUID of the step to retry
194
- * @returns Updated plan with step reset to ready
249
+ * @param conversationId - The conversation UUID to check
250
+ * @returns Session status with resumption details, or null if not resumable
195
251
  */
196
- retryStep(planId: string, stepId: string): Promise<{
197
- plan: ExecutionPlan;
198
- }>;
252
+ getConversationStatus(conversationId: string): Promise<ConversationStatus | null>;
199
253
  /**
200
- * Mark a step as failed.
254
+ * Resume an interrupted conversation.
201
255
  *
202
- * Records the error and determines if the plan should also fail
203
- * (if step is not retriable or out of retries).
256
+ * Returns a streaming response that continues the conversation
257
+ * from where it was interrupted.
204
258
  *
205
- * @param planId - UUID of the plan
206
- * @param stepId - UUID of the failed step
207
- * @param errorMessage - Optional error message
208
- * @returns Updated plan with failed step
259
+ * @param conversationId - The conversation to resume
260
+ * @param userContext - Optional current page context (highlighted text, DOM snapshot, etc.)
261
+ * @param callbacks - Streaming callbacks
209
262
  */
210
- failStep(planId: string, stepId: string, errorMessage?: string): Promise<{
211
- plan: ExecutionPlan;
212
- }>;
263
+ resumeConversation(conversationId: string, userContext: UserContextItem[] | undefined, callbacks: StreamCallbacks): Promise<void>;
213
264
  /**
214
- * Skip a step and advance to the next one.
215
- *
216
- * @param planId - UUID of the plan
217
- * @param stepId - UUID of the step to skip
218
- * @returns Updated plan with skipped step and next step ready
265
+ * Handle events from the resume stream.
219
266
  */
220
- skipStep(planId: string, stepId: string): Promise<{
221
- plan: ExecutionPlan;
267
+ private handleResumeStreamEvent;
268
+ }
269
+ /**
270
+ * Conversation status for session resumption.
271
+ */
272
+ export interface ConversationStatus {
273
+ resumable: boolean;
274
+ message_id?: string;
275
+ elapsed_ms?: number;
276
+ user_message?: string;
277
+ partial_response?: string;
278
+ summary?: string;
279
+ accomplished?: Array<{
280
+ action: string;
281
+ result_summary: string;
222
282
  }>;
223
- /**
224
- * Send action result back to the agent.
225
- *
226
- * Called after executing a query action (returns_data=true).
227
- * The result is sent to the agent for further reasoning in the ReAct loop.
228
- *
229
- * @param actionName - The name of the action that was executed
230
- * @param result - The result data to send back to the agent
231
- */
232
- sendActionResult(actionName: string, result: unknown): void;
233
283
  }
234
284
  /**
235
285
  * Convert ActionData from MCP response to TaskButtonData for UI rendering.
package/dist/cli/sync.js CHANGED
@@ -64,9 +64,32 @@ async function loadActions(actionsPath) {
64
64
  const tempDir = path.dirname(absolutePath);
65
65
  const tempFile = path.join(tempDir, `.pillar-sync-temp-${Date.now()}.mjs`);
66
66
  const importPath = absolutePath.replace(/\\/g, "/");
67
- const extractScript = `import actions from '${importPath}';
68
- const result = actions.default || actions;
69
- console.log(JSON.stringify(result));`;
67
+ const extractScript = `import * as module from '${importPath}';
68
+
69
+ // Resolve actions - tsx may wrap all exports in module.default
70
+ function resolveActions(mod) {
71
+ // Direct named export
72
+ if (mod.actions && typeof mod.actions === 'object' && !mod.actions.default) {
73
+ return mod.actions;
74
+ }
75
+ // Default export is the actions object directly
76
+ if (mod.default && typeof mod.default === 'object') {
77
+ // Check if default is a module namespace (has nested default or actions)
78
+ if (mod.default.default && typeof mod.default.default === 'object') {
79
+ return mod.default.default;
80
+ }
81
+ if (mod.default.actions && typeof mod.default.actions === 'object') {
82
+ return mod.default.actions;
83
+ }
84
+ // default is the actions object itself
85
+ return mod.default;
86
+ }
87
+ return null;
88
+ }
89
+
90
+ const actions = resolveActions(module);
91
+ const agentGuidance = module.agentGuidance || module.default?.agentGuidance;
92
+ console.log(JSON.stringify({ actions, agentGuidance }));`;
70
93
  fs.writeFileSync(tempFile, extractScript, "utf-8");
71
94
  try {
72
95
  const result = execSync(`npx tsx "${tempFile}"`, {
@@ -74,13 +97,15 @@ console.log(JSON.stringify(result));`;
74
97
  cwd: process.cwd(),
75
98
  stdio: ["pipe", "pipe", "pipe"]
76
99
  });
77
- const actions = JSON.parse(result.trim());
100
+ const parsed = JSON.parse(result.trim());
101
+ const actions = parsed.actions;
102
+ const agentGuidance = parsed.agentGuidance;
78
103
  if (!actions || typeof actions !== "object") {
79
104
  throw new Error(
80
105
  'Actions file must export an actions object as default or named export "actions"'
81
106
  );
82
107
  }
83
- return actions;
108
+ return { actions, agentGuidance };
84
109
  } finally {
85
110
  if (fs.existsSync(tempFile)) {
86
111
  fs.unlinkSync(tempFile);
@@ -97,19 +122,37 @@ console.log(JSON.stringify(result));`;
97
122
  }
98
123
  const fileUrl = pathToFileURL(absolutePath).href;
99
124
  try {
125
+ let resolveActions2 = function(mod) {
126
+ if (mod.actions && typeof mod.actions === "object" && !mod.actions.default) {
127
+ return mod.actions;
128
+ }
129
+ if (mod.default && typeof mod.default === "object") {
130
+ const defaultExport = mod.default;
131
+ if (defaultExport.default && typeof defaultExport.default === "object") {
132
+ return defaultExport.default;
133
+ }
134
+ if (defaultExport.actions && typeof defaultExport.actions === "object") {
135
+ return defaultExport.actions;
136
+ }
137
+ return defaultExport;
138
+ }
139
+ return null;
140
+ };
141
+ var resolveActions = resolveActions2;
100
142
  const module = await import(fileUrl);
101
- const actions = module.default || module.actions;
143
+ const actions = resolveActions2(module);
144
+ const agentGuidance = module.agentGuidance || module.default?.agentGuidance;
102
145
  if (!actions || typeof actions !== "object") {
103
146
  throw new Error(
104
147
  'Actions file must export an actions object as default or named export "actions"'
105
148
  );
106
149
  }
107
- return actions;
150
+ return { actions, agentGuidance };
108
151
  } catch (error) {
109
152
  throw error;
110
153
  }
111
154
  }
112
- function buildManifest(actions, platform, version, gitSha) {
155
+ function buildManifest(actions, platform, version, gitSha, agentGuidance) {
113
156
  const entries = [];
114
157
  for (const [name, definition] of Object.entries(actions)) {
115
158
  const entry = {
@@ -127,23 +170,32 @@ function buildManifest(actions, platform, version, gitSha) {
127
170
  entry.auto_run = definition.autoRun;
128
171
  if (definition.autoComplete)
129
172
  entry.auto_complete = definition.autoComplete;
130
- if (definition.returns)
173
+ if (definition.returns !== void 0) {
131
174
  entry.returns_data = definition.returns;
175
+ } else if (definition.type === "query") {
176
+ entry.returns_data = true;
177
+ }
132
178
  if (definition.dataSchema)
133
179
  entry.data_schema = definition.dataSchema;
134
180
  if (definition.defaultData)
135
181
  entry.default_data = definition.defaultData;
136
182
  if (definition.requiredContext)
137
183
  entry.required_context = definition.requiredContext;
184
+ if (definition.parameterExamples?.length)
185
+ entry.parameter_examples = definition.parameterExamples;
138
186
  entries.push(entry);
139
187
  }
140
- return {
188
+ const manifest = {
141
189
  platform,
142
190
  version,
143
191
  gitSha,
144
192
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
145
193
  actions: entries
146
194
  };
195
+ if (agentGuidance) {
196
+ manifest.agentGuidance = agentGuidance;
197
+ }
198
+ return manifest;
147
199
  }
148
200
  async function pollStatus(statusUrl, secret, maxWaitSeconds = 300) {
149
201
  const startTime = Date.now();
@@ -241,15 +293,19 @@ async function main() {
241
293
  process.exit(1);
242
294
  }
243
295
  console.log(`[pillar-sync] Loading actions from: ${actionsPath}`);
244
- let actions;
296
+ let loadedModule;
245
297
  try {
246
- actions = await loadActions(actionsPath);
298
+ loadedModule = await loadActions(actionsPath);
247
299
  } catch (error) {
248
300
  console.error(`[pillar-sync] Failed to load actions:`, error);
249
301
  process.exit(1);
250
302
  }
303
+ const { actions, agentGuidance } = loadedModule;
251
304
  const actionCount = Object.keys(actions).length;
252
305
  console.log(`[pillar-sync] Found ${actionCount} actions`);
306
+ if (agentGuidance) {
307
+ console.log(`[pillar-sync] Found agent guidance (${agentGuidance.length} chars)`);
308
+ }
253
309
  if (actionCount === 0) {
254
310
  console.warn("[pillar-sync] No actions found. Nothing to sync.");
255
311
  process.exit(0);
@@ -260,7 +316,7 @@ async function main() {
260
316
  console.log(`[pillar-sync] Platform: ${platform}`);
261
317
  console.log(`[pillar-sync] Version: ${version}`);
262
318
  console.log(`[pillar-sync] Git SHA: ${gitSha || "not available"}`);
263
- const manifest = buildManifest(actions, platform, version, gitSha);
319
+ const manifest = buildManifest(actions, platform, version, gitSha, agentGuidance);
264
320
  if (process.env.PILLAR_DEBUG) {
265
321
  const manifestPath = path.join(process.cwd(), "actions-manifest.json");
266
322
  fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
@@ -273,6 +329,9 @@ async function main() {
273
329
  git_sha: gitSha,
274
330
  actions: manifest.actions
275
331
  };
332
+ if (agentGuidance) {
333
+ requestBody.agent_guidance = agentGuidance;
334
+ }
276
335
  const syncUrl = `${apiUrl}/api/admin/configs/${slug}/actions/sync/?async=true`;
277
336
  console.log(`[pillar-sync] POST ${syncUrl}`);
278
337
  try {
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Debug Panel Component
3
+ *
4
+ * Shows real-time SDK event timeline for debugging.
5
+ * Only rendered when debug: true is passed to Pillar.init()
6
+ *
7
+ * Features:
8
+ * - Source filtering (sdk, handler, network, server)
9
+ * - Text search filter
10
+ * - Color-coded log levels
11
+ * - Export to JSON
12
+ * - Drag to resize height
13
+ * - Auto-scroll to bottom on new logs
14
+ */
15
+ interface DebugPanelProps {
16
+ /** Whether the panel is expanded */
17
+ expanded?: boolean;
18
+ /** Callback when panel is toggled */
19
+ onToggle?: () => void;
20
+ }
21
+ /**
22
+ * Debug Panel Component
23
+ */
24
+ export declare function DebugPanel({ expanded, onToggle }: DebugPanelProps): import("preact").JSX.Element;
25
+ export default DebugPanel;
@@ -0,0 +1,2 @@
1
+ export { DebugPanel } from './DebugPanel';
2
+ export { default } from './DebugPanel';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * DevTools Components
3
+ * Development tools for debugging and previewing Pillar SDK features
4
+ */
5
+ export { DEVTOOLS_STYLES } from './styles';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * DevTools CSS Styles
3
+ * Styles for the DOM Scanner preview panel
4
+ */
5
+ export declare const DEVTOOLS_STYLES = "\n/* Pillar DevTools Styles */\n.pillar-devtools-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 99998;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n box-sizing: border-box;\n}\n\n.pillar-devtools-panel {\n background: #1e1e2e;\n border-radius: 12px;\n box-shadow: 0 20px 50px rgba(0, 0, 0, 0.4);\n max-width: 800px;\n width: 100%;\n max-height: 80vh;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n color: #e0e0e0;\n}\n\n.pillar-devtools-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid #2d2d3d;\n background: #252535;\n}\n\n.pillar-devtools-title {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 0;\n font-size: 15px;\n font-weight: 600;\n color: #ffffff;\n}\n\n.pillar-devtools-badge {\n padding: 3px 8px;\n background: #6366f1;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.pillar-devtools-close {\n padding: 6px;\n background: transparent;\n border: none;\n border-radius: 6px;\n color: #9090a0;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n}\n\n.pillar-devtools-close:hover {\n background: #3d3d4d;\n color: #ffffff;\n}\n\n.pillar-devtools-stats {\n display: flex;\n gap: 16px;\n padding: 12px 20px;\n border-bottom: 1px solid #2d2d3d;\n background: #1a1a2a;\n flex-wrap: wrap;\n}\n\n.pillar-devtools-stat {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.pillar-devtools-stat-value {\n font-weight: 600;\n color: #8b5cf6;\n}\n\n.pillar-devtools-stat-label {\n color: #9090a0;\n}\n\n.pillar-devtools-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px 20px;\n}\n\n.pillar-devtools-tree {\n font-family: 'SF Mono', Monaco, 'Inconsolata', 'Fira Code', monospace;\n font-size: 12px;\n line-height: 1.6;\n}\n\n.pillar-devtools-node {\n margin-left: 16px;\n position: relative;\n}\n\n.pillar-devtools-node::before {\n content: '';\n position: absolute;\n left: -12px;\n top: 0;\n bottom: 0;\n width: 1px;\n background: #3d3d4d;\n}\n\n.pillar-devtools-node-root {\n margin-left: 0;\n}\n\n.pillar-devtools-node-root::before {\n display: none;\n}\n\n.pillar-devtools-node-header {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n padding: 3px 0;\n cursor: pointer;\n border-radius: 4px;\n transition: background 0.1s;\n}\n\n.pillar-devtools-node-header:hover {\n background: rgba(139, 92, 246, 0.1);\n}\n\n.pillar-devtools-toggle {\n width: 16px;\n height: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #6d6d7d;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.pillar-devtools-toggle svg {\n transition: transform 0.15s;\n}\n\n.pillar-devtools-toggle--expanded svg {\n transform: rotate(90deg);\n}\n\n.pillar-devtools-tag {\n color: #f472b6;\n}\n\n.pillar-devtools-attr-name {\n color: #a78bfa;\n}\n\n.pillar-devtools-attr-value {\n color: #34d399;\n}\n\n.pillar-devtools-interactable {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n background: #6366f1;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n color: #ffffff;\n margin-left: 6px;\n}\n\n.pillar-devtools-text {\n color: #94a3b8;\n font-style: italic;\n max-width: 400px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.pillar-devtools-children {\n display: none;\n}\n\n.pillar-devtools-children--expanded {\n display: block;\n}\n\n.pillar-devtools-footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 16px 20px;\n border-top: 1px solid #2d2d3d;\n background: #252535;\n}\n\n.pillar-devtools-footer-info {\n font-size: 12px;\n color: #9090a0;\n}\n\n.pillar-devtools-actions {\n display: flex;\n gap: 10px;\n}\n\n.pillar-devtools-btn {\n padding: 8px 16px;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s, transform 0.1s;\n border: none;\n}\n\n.pillar-devtools-btn:active {\n transform: scale(0.98);\n}\n\n.pillar-devtools-btn--secondary {\n background: #3d3d4d;\n color: #e0e0e0;\n}\n\n.pillar-devtools-btn--secondary:hover {\n background: #4d4d5d;\n}\n\n.pillar-devtools-btn--primary {\n background: #6366f1;\n color: #ffffff;\n}\n\n.pillar-devtools-btn--primary:hover {\n background: #4f46e5;\n}\n";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Page Pilot Banner Component
3
+ * Shows "Page being piloted by Agent" with stop button during interact_with_page actions.
4
+ * When a destructive action is detected, shows a confirmation variant with Allow/Deny buttons.
5
+ */
6
+ import { h } from 'preact';
7
+ export declare function PagePilotBanner(): h.JSX.Element | null;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Page Pilot Manager
3
+ * Manages the "Page being piloted by Agent" banner, rendering it outside Shadow DOM
4
+ * so it appears above all other content on the page.
5
+ */
6
+ export declare class PagePilotManager {
7
+ private container;
8
+ private stylesInjected;
9
+ private unsubscribe;
10
+ private themeObserver;
11
+ private primaryColor;
12
+ /**
13
+ * Detect the current theme from the document
14
+ * Checks for .dark class (next-themes) or data-theme attribute
15
+ */
16
+ private detectThemeFromDOM;
17
+ /**
18
+ * Apply theme mode to container element
19
+ */
20
+ private applyTheme;
21
+ /**
22
+ * Set up observer to watch for theme changes on documentElement
23
+ */
24
+ private setupThemeObserver;
25
+ /**
26
+ * Initialize the page pilot manager
27
+ * @param primaryColor - Optional primary color from theme config to override the default
28
+ */
29
+ init(primaryColor?: string): void;
30
+ /**
31
+ * Update the primary color used by the banner
32
+ */
33
+ setPrimaryColor(color: string): void;
34
+ /**
35
+ * Destroy the page pilot manager
36
+ */
37
+ destroy(): void;
38
+ /**
39
+ * Render the banner component
40
+ */
41
+ private render;
42
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Page Pilot Components
3
+ * Banner and manager for displaying "Page being piloted by Agent" indicator
4
+ */
5
+ export { PagePilotBanner } from './PagePilotBanner';
6
+ export { PagePilotManager } from './PagePilotManager';
7
+ export { PAGE_PILOT_STYLES } from './styles';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Page Pilot Banner CSS Styles
3
+ * Injected into the document head (outside Shadow DOM)
4
+ * Uses the same CSS variables as the Pillar panel for consistent theming
5
+ */
6
+ export declare const PAGE_PILOT_STYLES = "\n/* Pillar Page Pilot Banner Styles */\n\n/* Define CSS variables at the container level (same as panel) */\n#pillar-page-pilot-container {\n /* Core colors - Light mode (default) */\n --pillar-primary: #2563eb;\n --pillar-primary-hover: #1d4ed8;\n --pillar-bg: #ffffff;\n --pillar-bg-secondary: #f9fafb;\n --pillar-text: #1a1a1a;\n --pillar-text-secondary: #374151;\n --pillar-border: #e5e7eb;\n --pillar-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);\n --pillar-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n --pillar-radius-lg: 8px;\n --pillar-radius-md: 6px;\n --pillar-transition-fast: 0.15s ease;\n}\n\n/* Dark mode - Auto-detect from system preference */\n@media (prefers-color-scheme: dark) {\n #pillar-page-pilot-container:not([data-theme=\"light\"]) {\n --pillar-primary: #3b82f6;\n --pillar-primary-hover: #60a5fa;\n --pillar-bg: #1a1a1a;\n --pillar-bg-secondary: #262626;\n --pillar-text: #f5f5f5;\n --pillar-text-secondary: #e5e5e5;\n --pillar-border: #404040;\n --pillar-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4);\n }\n}\n\n/* Dark mode - Manual override via html class or data attribute */\nhtml.dark #pillar-page-pilot-container,\n[data-theme=\"dark\"] #pillar-page-pilot-container,\n#pillar-page-pilot-container[data-theme=\"dark\"] {\n --pillar-primary: #3b82f6;\n --pillar-primary-hover: #60a5fa;\n --pillar-bg: #1a1a1a;\n --pillar-bg-secondary: #262626;\n --pillar-text: #f5f5f5;\n --pillar-text-secondary: #e5e5e5;\n --pillar-border: #404040;\n --pillar-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4);\n}\n\n@keyframes pillar-pulse {\n 0%, 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.6;\n transform: scale(1.1);\n }\n}\n\n@keyframes pillar-banner-fade-in {\n from {\n opacity: 0;\n transform: translateY(-100%);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n._pillar-page-pilot-banner {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n z-index: 99999;\n font-family: var(--pillar-font-family);\n display: flex;\n justify-content: center;\n pointer-events: none;\n animation: pillar-banner-fade-in 0.2s ease-out;\n}\n\n/* Viewport outline \u2014 3px border on left, right, bottom; top handled by tab shape */\n._pillar-page-pilot-banner::before {\n content: '';\n position: fixed;\n inset: 0;\n border: 3px solid var(--pillar-primary);\n border-top: none;\n pointer-events: none;\n z-index: 99998;\n}\n\n/* Top border segments on either side of the tab */\n._pillar-page-pilot-banner::after {\n content: '';\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 3px;\n background: var(--pillar-primary);\n pointer-events: none;\n z-index: 99997;\n}\n\n._pillar-page-pilot-banner__content {\n position: relative;\n z-index: 99999;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 6px 20px;\n background: var(--pillar-primary);\n color: #ffffff;\n border-bottom-left-radius: var(--pillar-radius-lg);\n border-bottom-right-radius: var(--pillar-radius-lg);\n pointer-events: auto;\n}\n\n._pillar-page-pilot-banner__indicator {\n width: 8px;\n height: 8px;\n background: #ffffff;\n border-radius: 50%;\n animation: pillar-pulse 1.5s ease-in-out infinite;\n flex-shrink: 0;\n}\n\n._pillar-page-pilot-banner__text {\n font-size: 13px;\n font-weight: 500;\n color: #ffffff;\n white-space: nowrap;\n}\n\n._pillar-page-pilot-banner__stop {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 10px;\n margin-left: 4px;\n font-family: inherit;\n font-size: 12px;\n font-weight: 500;\n color: #ffffff;\n background: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: var(--pillar-radius-md);\n cursor: pointer;\n transition: all var(--pillar-transition-fast);\n}\n\n._pillar-page-pilot-banner__stop:hover {\n background: rgba(255, 255, 255, 0.25);\n border-color: rgba(255, 255, 255, 0.5);\n}\n\n._pillar-page-pilot-banner__stop:active {\n transform: scale(0.97);\n}\n\n._pillar-page-pilot-banner__stop-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n}\n\n._pillar-page-pilot-banner__stop-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* Confirmation variant \u2014 amber/warning theme */\n._pillar-page-pilot-banner--confirm ._pillar-page-pilot-banner__content {\n background: #d97706;\n}\n\n._pillar-page-pilot-banner--confirm::before {\n border-color: #d97706;\n}\n\n._pillar-page-pilot-banner--confirm::after {\n background: #d97706;\n}\n\n._pillar-page-pilot-banner__warning-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n}\n\n._pillar-page-pilot-banner__warning-icon svg {\n width: 100%;\n height: 100%;\n}\n\n._pillar-page-pilot-banner__deny {\n display: flex;\n align-items: center;\n padding: 5px 12px;\n margin-left: 4px;\n font-family: inherit;\n font-size: 12px;\n font-weight: 500;\n color: #ffffff;\n background: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: var(--pillar-radius-md);\n cursor: pointer;\n transition: all var(--pillar-transition-fast);\n}\n\n._pillar-page-pilot-banner__deny:hover {\n background: rgba(255, 255, 255, 0.25);\n border-color: rgba(255, 255, 255, 0.5);\n}\n\n._pillar-page-pilot-banner__deny:active {\n transform: scale(0.97);\n}\n\n._pillar-page-pilot-banner__allow {\n display: flex;\n align-items: center;\n padding: 5px 12px;\n font-family: inherit;\n font-size: 12px;\n font-weight: 600;\n color: #d97706;\n background: #ffffff;\n border: 1px solid rgba(255, 255, 255, 0.8);\n border-radius: var(--pillar-radius-md);\n cursor: pointer;\n transition: all var(--pillar-transition-fast);\n}\n\n._pillar-page-pilot-banner__allow:hover {\n background: #fef3c7;\n}\n\n._pillar-page-pilot-banner__allow:active {\n transform: scale(0.97);\n}\n";
@@ -1,14 +1,12 @@
1
1
  /**
2
2
  * Panel Header Component
3
- * Navigation header with back, home, and close buttons
3
+ * Navigation header with back, home, history, and close buttons
4
4
  */
5
- import { h } from 'preact';
6
- import { type ViewType } from '../../store/router';
5
+ import { type ViewType } from "../../store/router";
7
6
  interface HeaderProps {
8
7
  currentView: ViewType;
9
- customTitle?: string;
10
8
  /** Hide back and home navigation buttons */
11
9
  hideNavigation?: boolean;
12
10
  }
13
- export declare function Header({ currentView, customTitle, hideNavigation }: HeaderProps): h.JSX.Element;
11
+ export declare function Header({ currentView, hideNavigation }: HeaderProps): import("preact").JSX.Element;
14
12
  export {};
@@ -0,0 +1,10 @@
1
+ /**
2
+ * History Dropdown Component
3
+ * Shows a list of past conversations grouped by day (like Cursor).
4
+ */
5
+ import { h } from 'preact';
6
+ interface HistoryDropdownProps {
7
+ onSelectConversation: (conversationId: string) => void;
8
+ }
9
+ export declare function HistoryDropdown({ onSelectConversation }: HistoryDropdownProps): h.JSX.Element;
10
+ export {};
@@ -2,5 +2,4 @@
2
2
  * Panel Content Component
3
3
  * Main panel layout with header, content, and chat input
4
4
  */
5
- import { h } from 'preact';
6
- export declare function PanelContent(): h.JSX.Element;
5
+ export declare function PanelContent(): import("preact").JSX.Element;