@pillar-ai/sdk 0.1.21 → 0.1.22
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/actions/definitions/analytics.d.ts +18 -0
- package/dist/actions/definitions/content.d.ts +40 -0
- package/dist/actions/definitions/index.d.ts +26 -0
- package/dist/actions/definitions/navigation.d.ts +65 -0
- package/dist/actions/definitions/settings.d.ts +162 -0
- package/dist/actions/definitions/sources.d.ts +44 -0
- package/dist/actions/definitions/support.d.ts +15 -0
- package/dist/actions/definitions/team.d.ts +120 -0
- package/dist/actions/index.d.ts +1 -1
- package/dist/actions/types.d.ts +0 -89
- package/dist/api/ag-ui-adapter.d.ts +76 -0
- package/dist/api/ag-ui-bridge.d.ts +49 -0
- package/dist/api/ag-ui-client.d.ts +102 -0
- package/dist/api/ag-ui-handler.d.ts +89 -0
- package/dist/api/mcp-client.d.ts +46 -24
- package/dist/cli/sync.js +62 -43
- package/dist/components/Button/FloatingButton.d.ts +46 -0
- package/dist/components/PagePilot/styles.d.ts +1 -1
- package/dist/components/Panel/TabNavigation.d.ts +16 -0
- package/dist/components/Panel/styles.d.ts +1 -1
- package/dist/components/Progress/AGUIProgress.d.ts +15 -0
- package/dist/components/Tooltips/Tooltip.d.ts +46 -0
- package/dist/components/Tooltips/TooltipManager.d.ts +41 -0
- package/dist/components/Tooltips/index.d.ts +6 -0
- package/dist/components/Tooltips/styles.d.ts +5 -0
- package/dist/components/Views/ArticleChatView.d.ts +10 -0
- package/dist/components/Views/ArticleView.d.ts +10 -0
- package/dist/components/Views/CategoryView.d.ts +11 -0
- package/dist/components/Views/HelpCenterArticles.d.ts +17 -0
- package/dist/components/Views/SearchView.d.ts +10 -0
- package/dist/components/Views/SupportView.d.ts +15 -0
- package/dist/components/shared/ArticleCard.d.ts +17 -0
- package/dist/components/shared/CategoryCard.d.ts +17 -0
- package/dist/content/extensions/AccordionNode.d.ts +10 -0
- package/dist/content/extensions/CalloutNode.d.ts +11 -0
- package/dist/content/extensions/index.d.ts +5 -0
- package/dist/content/index.d.ts +5 -0
- package/dist/content/renderer.d.ts +24 -0
- package/dist/core/Pillar.d.ts +57 -38
- package/dist/core/config.d.ts +1 -1
- package/dist/core/events.d.ts +7 -1
- package/dist/index.d.ts +2 -2
- package/dist/pillar.esm.js +1 -1
- package/dist/store/chat.d.ts +2 -0
- package/dist/store/tooltips.d.ts +21 -0
- package/dist/tools/index.d.ts +27 -0
- package/dist/tools/registry.d.ts +106 -0
- package/dist/tools/types.d.ts +564 -0
- package/dist/utils/helpdesk.d.ts +33 -0
- package/dist/utils/markdown.d.ts +9 -0
- package/dist/utils/resilient-fetch.d.ts +25 -0
- package/package.json +3 -2
- package/src/actions/types.ts +0 -622
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AG-UI Bridge
|
|
3
|
+
*
|
|
4
|
+
* Temporary bridge that converts Phase 1's JSON-RPC wrapped AG-UI events
|
|
5
|
+
* to native AG-UI events. This allows the SDK to use AG-UI patterns while
|
|
6
|
+
* the backend still uses JSON-RPC transport.
|
|
7
|
+
*
|
|
8
|
+
* Will be removed after Phase 3 (pure AG-UI transport).
|
|
9
|
+
*/
|
|
10
|
+
import type { AGUIEvent } from '@ag-ui/core';
|
|
11
|
+
/**
|
|
12
|
+
* Unwrap an AG-UI event from a JSON-RPC notification.
|
|
13
|
+
*
|
|
14
|
+
* Phase 1 backend wraps AG-UI events like this:
|
|
15
|
+
* {
|
|
16
|
+
* "jsonrpc": "2.0",
|
|
17
|
+
* "method": "notifications/progress",
|
|
18
|
+
* "params": {
|
|
19
|
+
* "ag_ui_event": { "type": "RUN_STARTED", ... }
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* @param jsonRpcEvent - The JSON-RPC notification from the backend
|
|
24
|
+
* @returns The unwrapped AG-UI event, or null if not an AG-UI event
|
|
25
|
+
*/
|
|
26
|
+
export declare function unwrapAGUIEvent(jsonRpcEvent: unknown): AGUIEvent | null;
|
|
27
|
+
/**
|
|
28
|
+
* Check if a JSON-RPC event contains an AG-UI event.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isAGUIWrappedEvent(jsonRpcEvent: unknown): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Convert legacy MCP progress events to AG-UI events.
|
|
33
|
+
*
|
|
34
|
+
* This is for backwards compatibility during the transition.
|
|
35
|
+
* Converts old-style progress events to AG-UI events.
|
|
36
|
+
*
|
|
37
|
+
* @param legacyEvent - The legacy MCP progress event
|
|
38
|
+
* @returns An array of AG-UI events (may be multiple for some conversions)
|
|
39
|
+
*/
|
|
40
|
+
export declare function convertLegacyProgressToAGUI(legacyEvent: Record<string, unknown>): AGUIEvent[];
|
|
41
|
+
/**
|
|
42
|
+
* Process a raw SSE event and extract AG-UI events.
|
|
43
|
+
*
|
|
44
|
+
* Handles both new AG-UI wrapped events and legacy progress events.
|
|
45
|
+
*
|
|
46
|
+
* @param rawEvent - The parsed JSON from an SSE data line
|
|
47
|
+
* @returns An array of AG-UI events
|
|
48
|
+
*/
|
|
49
|
+
export declare function processSSEEvent(rawEvent: unknown): AGUIEvent[];
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AG-UI Protocol Client for Pillar SDK
|
|
3
|
+
*
|
|
4
|
+
* Implements the AG-UI specification for streaming agent interactions.
|
|
5
|
+
* Uses the @ag-ui/client HttpAgent for transport.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (C) 2025 Pillar Team
|
|
8
|
+
*/
|
|
9
|
+
import type { ResolvedConfig } from '../core/config';
|
|
10
|
+
export interface AGUIStreamCallbacks {
|
|
11
|
+
/** Called when run starts */
|
|
12
|
+
onRunStarted?: (runId: string) => void;
|
|
13
|
+
/** Called when run completes successfully */
|
|
14
|
+
onRunFinished?: () => void;
|
|
15
|
+
/** Called on error */
|
|
16
|
+
onError?: (error: Error) => void;
|
|
17
|
+
/** Called when a step starts */
|
|
18
|
+
onStepStarted?: (stepName: string) => void;
|
|
19
|
+
/** Called when a step finishes */
|
|
20
|
+
onStepFinished?: (stepName: string) => void;
|
|
21
|
+
/** Called for text message streaming */
|
|
22
|
+
onTextContent?: (messageId: string, delta: string) => void;
|
|
23
|
+
/** Called when text message completes */
|
|
24
|
+
onTextComplete?: (messageId: string, fullContent: string) => void;
|
|
25
|
+
/** Called when tool call starts (for UI display) */
|
|
26
|
+
onToolCallStart?: (toolCallId: string, toolName: string) => void;
|
|
27
|
+
/** Called with tool call arguments */
|
|
28
|
+
onToolCallArgs?: (toolCallId: string, argsJson: string) => void;
|
|
29
|
+
/** Called when tool call completes */
|
|
30
|
+
onToolCallEnd?: (toolCallId: string) => void;
|
|
31
|
+
/** Called when tool result is available */
|
|
32
|
+
onToolCallResult?: (toolCallId: string, result: string) => void;
|
|
33
|
+
/** Called for state delta events (sources, actions, plan) */
|
|
34
|
+
onStateDelta?: (delta: unknown[]) => void;
|
|
35
|
+
/** Called for state snapshots */
|
|
36
|
+
onStateSnapshot?: (state: unknown) => void;
|
|
37
|
+
}
|
|
38
|
+
export interface ClientTool {
|
|
39
|
+
name: string;
|
|
40
|
+
description: string;
|
|
41
|
+
parameters: Record<string, unknown>;
|
|
42
|
+
/** Handler function - called when agent requests this tool */
|
|
43
|
+
handler?: (args: Record<string, unknown>) => Promise<unknown>;
|
|
44
|
+
}
|
|
45
|
+
export declare class AGUIClient {
|
|
46
|
+
private config;
|
|
47
|
+
private agent;
|
|
48
|
+
private currentRunId;
|
|
49
|
+
private currentThreadId;
|
|
50
|
+
private messageAccumulators;
|
|
51
|
+
private toolArgAccumulators;
|
|
52
|
+
private toolCallNames;
|
|
53
|
+
private registeredTools;
|
|
54
|
+
constructor(config: ResolvedConfig);
|
|
55
|
+
/**
|
|
56
|
+
* Get or create a persistent thread ID for this session.
|
|
57
|
+
*/
|
|
58
|
+
private getOrCreateThreadId;
|
|
59
|
+
private getBrowserLanguage;
|
|
60
|
+
/**
|
|
61
|
+
* Register a client-side tool that can be called by the agent.
|
|
62
|
+
*/
|
|
63
|
+
registerTool(tool: ClientTool): void;
|
|
64
|
+
/**
|
|
65
|
+
* Unregister a client-side tool.
|
|
66
|
+
*/
|
|
67
|
+
unregisterTool(toolName: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* Send a message and stream the agent's response.
|
|
70
|
+
*/
|
|
71
|
+
chat(message: string, callbacks: AGUIStreamCallbacks, options?: {
|
|
72
|
+
history?: Array<{
|
|
73
|
+
role: 'user' | 'assistant';
|
|
74
|
+
content: string;
|
|
75
|
+
}>;
|
|
76
|
+
userContext?: Array<{
|
|
77
|
+
type: string;
|
|
78
|
+
[key: string]: unknown;
|
|
79
|
+
}>;
|
|
80
|
+
signal?: AbortSignal;
|
|
81
|
+
}): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Execute a client-side tool if registered.
|
|
84
|
+
*/
|
|
85
|
+
private maybeExecuteClientTool;
|
|
86
|
+
/**
|
|
87
|
+
* Send tool execution result back to the server.
|
|
88
|
+
*/
|
|
89
|
+
sendToolResult(toolCallId: string, result: unknown, error?: string): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Start a new conversation thread.
|
|
92
|
+
*/
|
|
93
|
+
newThread(): string;
|
|
94
|
+
/**
|
|
95
|
+
* Get current thread ID.
|
|
96
|
+
*/
|
|
97
|
+
get threadId(): string;
|
|
98
|
+
/**
|
|
99
|
+
* Get current run ID.
|
|
100
|
+
*/
|
|
101
|
+
get runId(): string | null;
|
|
102
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AG-UI Event Handler
|
|
3
|
+
*
|
|
4
|
+
* Processes AG-UI protocol events and maintains UI state.
|
|
5
|
+
* Replaces the complex JSON-RPC parsing in mcp-client.ts.
|
|
6
|
+
*/
|
|
7
|
+
import type { AGUIEvent } from '@ag-ui/core';
|
|
8
|
+
/** A streaming text message being accumulated */
|
|
9
|
+
export interface StreamingMessage {
|
|
10
|
+
id: string;
|
|
11
|
+
role: 'user' | 'assistant';
|
|
12
|
+
content: string;
|
|
13
|
+
complete: boolean;
|
|
14
|
+
/** Which step this message belongs to (for thinking vs response) */
|
|
15
|
+
stepName?: string;
|
|
16
|
+
}
|
|
17
|
+
/** A tool call being tracked */
|
|
18
|
+
export interface ToolCallState {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
args: string;
|
|
22
|
+
result?: unknown;
|
|
23
|
+
complete: boolean;
|
|
24
|
+
/** True if this tool executes on the client (query action) */
|
|
25
|
+
isClientSide?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** State delta data (sources, actions, plan, etc.) */
|
|
28
|
+
export interface StateDeltaData {
|
|
29
|
+
type: string;
|
|
30
|
+
data: unknown;
|
|
31
|
+
timestamp: number;
|
|
32
|
+
}
|
|
33
|
+
/** Complete AG-UI state */
|
|
34
|
+
export interface AGUIState {
|
|
35
|
+
/** Current run ID */
|
|
36
|
+
runId: string | null;
|
|
37
|
+
/** Thread ID (replaces conversation_id) */
|
|
38
|
+
threadId: string | null;
|
|
39
|
+
/** Current step name (e.g., "reasoning", "tool_execution") */
|
|
40
|
+
currentStep: string | null;
|
|
41
|
+
/** Streaming messages keyed by message ID */
|
|
42
|
+
messages: Map<string, StreamingMessage>;
|
|
43
|
+
/** Tool calls keyed by tool call ID */
|
|
44
|
+
toolCalls: Map<string, ToolCallState>;
|
|
45
|
+
/** State deltas received (sources, actions, plans) */
|
|
46
|
+
stateDeltas: StateDeltaData[];
|
|
47
|
+
/** Whether the run is complete */
|
|
48
|
+
isComplete: boolean;
|
|
49
|
+
/** Error if run failed */
|
|
50
|
+
error: Error | null;
|
|
51
|
+
}
|
|
52
|
+
export interface AGUIHandlerCallbacks {
|
|
53
|
+
/** Called whenever state changes */
|
|
54
|
+
onStateChange: (state: AGUIState) => void;
|
|
55
|
+
/** Called when an error occurs */
|
|
56
|
+
onError: (error: Error) => void;
|
|
57
|
+
/** Called when run completes successfully */
|
|
58
|
+
onComplete: () => void;
|
|
59
|
+
/** Called when a client-side tool needs execution */
|
|
60
|
+
onClientToolCall?: (toolCall: ToolCallState) => Promise<unknown>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Create an AG-UI event handler.
|
|
64
|
+
*
|
|
65
|
+
* Returns an object with a handleEvent method that processes
|
|
66
|
+
* AG-UI events and updates internal state.
|
|
67
|
+
*/
|
|
68
|
+
export declare function createAGUIHandler(callbacks: AGUIHandlerCallbacks): {
|
|
69
|
+
handleEvent: (event: AGUIEvent) => Promise<void>;
|
|
70
|
+
reset: () => void;
|
|
71
|
+
getState: () => AGUIState;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Register a tool as client-side.
|
|
75
|
+
* Called when the SDK registers an action with returns: true.
|
|
76
|
+
*/
|
|
77
|
+
export declare function registerClientSideTool(toolName: string): void;
|
|
78
|
+
/**
|
|
79
|
+
* Unregister a client-side tool.
|
|
80
|
+
*/
|
|
81
|
+
export declare function unregisterClientSideTool(toolName: string): void;
|
|
82
|
+
/**
|
|
83
|
+
* Check if a tool executes on the client side.
|
|
84
|
+
*/
|
|
85
|
+
export declare function isClientSideTool(toolName: string): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Get all registered client-side tools.
|
|
88
|
+
*/
|
|
89
|
+
export declare function getClientSideTools(): string[];
|
package/dist/api/mcp-client.d.ts
CHANGED
|
@@ -22,8 +22,12 @@ export interface ToolResult {
|
|
|
22
22
|
isError?: boolean;
|
|
23
23
|
structuredContent?: {
|
|
24
24
|
sources?: ArticleSummary[];
|
|
25
|
-
|
|
26
|
-
/**
|
|
25
|
+
tools?: ToolData[];
|
|
26
|
+
/** @deprecated Use tools instead */
|
|
27
|
+
actions?: ToolData[];
|
|
28
|
+
/** Registered tools for dynamic tool invocations (persisted across turns) */
|
|
29
|
+
registered_tools?: Record<string, unknown>[];
|
|
30
|
+
/** @deprecated Use registered_tools instead */
|
|
27
31
|
registered_actions?: Record<string, unknown>[];
|
|
28
32
|
};
|
|
29
33
|
_meta?: {
|
|
@@ -31,32 +35,36 @@ export interface ToolResult {
|
|
|
31
35
|
query_log_id?: string;
|
|
32
36
|
};
|
|
33
37
|
}
|
|
34
|
-
/**
|
|
35
|
-
export interface
|
|
38
|
+
/** Tool data from MCP server */
|
|
39
|
+
export interface ToolData {
|
|
36
40
|
id: string;
|
|
37
41
|
name: string;
|
|
38
42
|
description: string;
|
|
39
43
|
action_type: string;
|
|
40
|
-
/** If true,
|
|
44
|
+
/** If true, tool executes immediately without user clicking */
|
|
41
45
|
auto_run: boolean;
|
|
42
|
-
/** If true,
|
|
46
|
+
/** If true, tool completes without waiting for host confirmation */
|
|
43
47
|
auto_complete: boolean;
|
|
44
|
-
/** If true,
|
|
48
|
+
/** If true, tool returns data for agent reasoning */
|
|
45
49
|
returns_data: boolean;
|
|
46
50
|
score: number;
|
|
47
51
|
data: Record<string, unknown>;
|
|
48
52
|
}
|
|
49
|
-
/**
|
|
50
|
-
export
|
|
51
|
-
|
|
53
|
+
/** @deprecated Use ToolData instead */
|
|
54
|
+
export type ActionData = ToolData;
|
|
55
|
+
/** Tool request from agent (unified for all tool execution) */
|
|
56
|
+
export interface ToolRequest {
|
|
57
|
+
/** Tool name to execute */
|
|
52
58
|
action_name: string;
|
|
53
|
-
/** Parameters for the
|
|
59
|
+
/** Parameters for the tool */
|
|
54
60
|
parameters: Record<string, unknown>;
|
|
55
|
-
/** Full
|
|
56
|
-
action?:
|
|
61
|
+
/** Full tool definition (optional, for handler lookup) */
|
|
62
|
+
action?: ToolData;
|
|
57
63
|
/** Unique ID for this specific tool invocation (for result correlation) */
|
|
58
64
|
tool_call_id?: string;
|
|
59
65
|
}
|
|
66
|
+
/** @deprecated Use ToolRequest instead */
|
|
67
|
+
export type ActionRequest = ToolRequest;
|
|
60
68
|
/** Token usage data from the agentic loop (sent after each LLM iteration) */
|
|
61
69
|
export interface TokenUsage {
|
|
62
70
|
/** Input tokens for this iteration */
|
|
@@ -84,9 +92,13 @@ export interface StreamCallbacks {
|
|
|
84
92
|
onToken?: (token: string) => void;
|
|
85
93
|
/** Called when sources are available */
|
|
86
94
|
onSources?: (sources: ArticleSummary[]) => void;
|
|
87
|
-
/** Called when
|
|
88
|
-
|
|
89
|
-
/**
|
|
95
|
+
/** Called when tools are available */
|
|
96
|
+
onTools?: (tools: ToolData[]) => void;
|
|
97
|
+
/** @deprecated Use onTools instead */
|
|
98
|
+
onActions?: (actions: ToolData[]) => void;
|
|
99
|
+
/** Called when registered tools are received (for dynamic tool invocations) */
|
|
100
|
+
onRegisteredTools?: (tools: Record<string, unknown>[]) => void;
|
|
101
|
+
/** @deprecated Use onRegisteredTools instead */
|
|
90
102
|
onRegisteredActions?: (actions: Record<string, unknown>[]) => void;
|
|
91
103
|
/** Called on error */
|
|
92
104
|
onError?: (error: string) => void;
|
|
@@ -112,8 +124,10 @@ export interface StreamCallbacks {
|
|
|
112
124
|
}) => void;
|
|
113
125
|
/** Called immediately with the request ID (for cancellation support) */
|
|
114
126
|
onRequestId?: (requestId: number) => void;
|
|
115
|
-
/** Called when agent requests
|
|
116
|
-
|
|
127
|
+
/** Called when agent requests tool execution (unified handler) */
|
|
128
|
+
onToolRequest?: (request: ToolRequest) => Promise<void>;
|
|
129
|
+
/** @deprecated Use onToolRequest instead */
|
|
130
|
+
onActionRequest?: (request: ToolRequest) => Promise<void>;
|
|
117
131
|
/** Called when token usage is updated (after each LLM iteration) */
|
|
118
132
|
onTokenUsage?: (usage: TokenUsage) => void;
|
|
119
133
|
}
|
|
@@ -199,7 +213,9 @@ export declare class MCPClient {
|
|
|
199
213
|
role: 'user' | 'assistant';
|
|
200
214
|
content: string;
|
|
201
215
|
}>;
|
|
202
|
-
/** Registered
|
|
216
|
+
/** Registered tools from previous turns (for dynamic tool invocations) */
|
|
217
|
+
registeredTools?: Record<string, unknown>[];
|
|
218
|
+
/** @deprecated Use registeredTools instead */
|
|
203
219
|
registeredActions?: Record<string, unknown>[];
|
|
204
220
|
signal?: AbortSignal;
|
|
205
221
|
/** Conversation ID - generated client-side, always provided */
|
|
@@ -217,16 +233,18 @@ export declare class MCPClient {
|
|
|
217
233
|
*/
|
|
218
234
|
cancelStream(requestId: number | string): Promise<void>;
|
|
219
235
|
/**
|
|
220
|
-
* Send
|
|
236
|
+
* Send tool result back to the agent.
|
|
221
237
|
*
|
|
222
|
-
* Called after executing a query
|
|
238
|
+
* Called after executing a query tool (returns_data=true).
|
|
223
239
|
* The result is sent to the agent for further reasoning in the ReAct loop.
|
|
224
240
|
*
|
|
225
|
-
* @param
|
|
241
|
+
* @param toolName - The name of the tool that was executed
|
|
226
242
|
* @param result - The result data to send back to the agent
|
|
227
243
|
* @param toolCallId - Unique ID for this specific tool invocation (for result correlation)
|
|
228
244
|
* @returns Promise that resolves when the result is delivered, or rejects on error
|
|
229
245
|
*/
|
|
246
|
+
sendToolResult(toolName: string, result: unknown, toolCallId?: string): Promise<void>;
|
|
247
|
+
/** @deprecated Use sendToolResult instead */
|
|
230
248
|
sendActionResult(actionName: string, result: unknown, toolCallId?: string): Promise<void>;
|
|
231
249
|
/**
|
|
232
250
|
* Send a client-side log to the server for debugging.
|
|
@@ -266,10 +284,14 @@ export interface ConversationStatus {
|
|
|
266
284
|
user_message?: string;
|
|
267
285
|
partial_response?: string;
|
|
268
286
|
display_trace?: DisplayStep[];
|
|
287
|
+
registered_tools?: Record<string, unknown>[];
|
|
288
|
+
/** @deprecated Use registered_tools instead */
|
|
269
289
|
registered_actions?: Record<string, unknown>[];
|
|
270
290
|
}
|
|
271
291
|
/**
|
|
272
|
-
* Convert
|
|
292
|
+
* Convert ToolData from MCP response to TaskButtonData for UI rendering.
|
|
273
293
|
*/
|
|
274
|
-
export declare function
|
|
294
|
+
export declare function toolToTaskButton(tool: ToolData): TaskButtonData;
|
|
295
|
+
/** @deprecated Use toolToTaskButton instead */
|
|
296
|
+
export declare const actionToTaskButton: typeof toolToTaskButton;
|
|
275
297
|
export {};
|
package/dist/cli/sync.js
CHANGED
|
@@ -25,15 +25,16 @@ function parseArgs(args) {
|
|
|
25
25
|
}
|
|
26
26
|
function printUsage() {
|
|
27
27
|
console.log(`
|
|
28
|
-
Pillar
|
|
28
|
+
Pillar Tool Sync CLI
|
|
29
29
|
|
|
30
|
-
Scans for
|
|
30
|
+
Scans for usePillarTool/defineTool calls and syncs to the Pillar backend.
|
|
31
|
+
Also supports legacy usePillarAction/defineAction calls.
|
|
31
32
|
|
|
32
33
|
Usage:
|
|
33
34
|
npx pillar-sync --scan <dir> [--local]
|
|
34
35
|
|
|
35
36
|
Arguments:
|
|
36
|
-
--scan <dir> Directory to scan for
|
|
37
|
+
--scan <dir> Directory to scan for usePillarTool/defineTool calls
|
|
37
38
|
--local Use localhost:8003 as the API URL (for local development)
|
|
38
39
|
--help Show this help message
|
|
39
40
|
|
|
@@ -46,7 +47,7 @@ Environment Variables:
|
|
|
46
47
|
GIT_SHA Git commit SHA for traceability
|
|
47
48
|
|
|
48
49
|
Examples:
|
|
49
|
-
# Scan and sync
|
|
50
|
+
# Scan and sync tools
|
|
50
51
|
PILLAR_SLUG=my-app PILLAR_SECRET=xxx npx pillar-sync --scan ./src
|
|
51
52
|
|
|
52
53
|
# Local development
|
|
@@ -207,7 +208,7 @@ function evaluateNode(node, ts) {
|
|
|
207
208
|
}
|
|
208
209
|
return void 0;
|
|
209
210
|
}
|
|
210
|
-
async function
|
|
211
|
+
async function scanTools(scanDir) {
|
|
211
212
|
const absoluteDir = path.resolve(process.cwd(), scanDir);
|
|
212
213
|
if (!fs.existsSync(absoluteDir)) {
|
|
213
214
|
throw new Error(`Scan directory not found: ${absoluteDir}`);
|
|
@@ -216,19 +217,25 @@ async function scanActions(scanDir) {
|
|
|
216
217
|
try {
|
|
217
218
|
ts = await import("typescript");
|
|
218
219
|
} catch {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
try {
|
|
221
|
+
const { createRequire } = await import("module");
|
|
222
|
+
const require2 = createRequire(path.join(process.cwd(), "node_modules", "_placeholder.js"));
|
|
223
|
+
ts = require2("typescript");
|
|
224
|
+
} catch {
|
|
225
|
+
console.error("[pillar-sync] TypeScript is required for --scan mode.");
|
|
226
|
+
console.error("[pillar-sync] Install it: npm install -D typescript");
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
222
229
|
}
|
|
223
230
|
const files = globFiles(absoluteDir, [".ts", ".tsx", ".js", ".jsx", ".mjs"]);
|
|
224
231
|
console.log(`[pillar-sync] Scanning ${files.length} files in ${scanDir}`);
|
|
225
|
-
const PATTERNS = ["defineAction", "usePillarAction"];
|
|
232
|
+
const PATTERNS = ["defineTool", "usePillarTool", "defineAction", "usePillarAction"];
|
|
226
233
|
const candidateFiles = files.filter((file) => {
|
|
227
234
|
const content = fs.readFileSync(file, "utf-8");
|
|
228
235
|
return PATTERNS.some((p) => content.includes(p));
|
|
229
236
|
});
|
|
230
|
-
console.log(`[pillar-sync] Found ${candidateFiles.length} files with
|
|
231
|
-
const
|
|
237
|
+
console.log(`[pillar-sync] Found ${candidateFiles.length} files with tool definitions`);
|
|
238
|
+
const tools = [];
|
|
232
239
|
for (const filePath of candidateFiles) {
|
|
233
240
|
let visit2 = function(node) {
|
|
234
241
|
if (ts.isCallExpression(node)) {
|
|
@@ -237,18 +244,22 @@ async function scanActions(scanDir) {
|
|
|
237
244
|
if (ts.isIdentifier(callee)) {
|
|
238
245
|
isTargetCall = PATTERNS.includes(callee.text);
|
|
239
246
|
} else if (ts.isPropertyAccessExpression(callee)) {
|
|
240
|
-
isTargetCall = callee.name.text === "defineAction";
|
|
247
|
+
isTargetCall = callee.name.text === "defineTool" || callee.name.text === "defineAction";
|
|
241
248
|
}
|
|
242
249
|
if (isTargetCall && node.arguments.length > 0) {
|
|
243
250
|
const arg = node.arguments[0];
|
|
244
251
|
const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
245
252
|
const relativePath = path.relative(process.cwd(), filePath);
|
|
246
|
-
const
|
|
253
|
+
const processToolObject = (obj, line) => {
|
|
247
254
|
if (obj && typeof obj.name === "string" && typeof obj.description === "string") {
|
|
248
|
-
|
|
255
|
+
let toolType = obj.type;
|
|
256
|
+
if (toolType === "trigger_action") {
|
|
257
|
+
toolType = "trigger_tool";
|
|
258
|
+
}
|
|
259
|
+
tools.push({
|
|
249
260
|
name: obj.name,
|
|
250
261
|
description: obj.description,
|
|
251
|
-
type:
|
|
262
|
+
type: toolType,
|
|
252
263
|
inputSchema: obj.inputSchema,
|
|
253
264
|
examples: obj.examples,
|
|
254
265
|
autoRun: obj.autoRun,
|
|
@@ -259,29 +270,29 @@ async function scanActions(scanDir) {
|
|
|
259
270
|
console.log(`[pillar-sync] ${obj.name} (${relativePath}:${line})`);
|
|
260
271
|
} else if (obj) {
|
|
261
272
|
console.warn(
|
|
262
|
-
`[pillar-sync] \u26A0 Skipping
|
|
273
|
+
`[pillar-sync] \u26A0 Skipping tool at ${relativePath}:${line} \u2014 missing name or description`
|
|
263
274
|
);
|
|
264
275
|
}
|
|
265
276
|
};
|
|
266
277
|
if (ts.isObjectLiteralExpression(arg)) {
|
|
267
278
|
const obj = evaluateNode(arg, ts);
|
|
268
|
-
|
|
279
|
+
processToolObject(obj, lineNumber);
|
|
269
280
|
} else if (ts.isArrayLiteralExpression(arg)) {
|
|
270
281
|
for (const element of arg.elements) {
|
|
271
282
|
if (ts.isObjectLiteralExpression(element)) {
|
|
272
283
|
const elementLine = sourceFile.getLineAndCharacterOfPosition(element.getStart()).line + 1;
|
|
273
284
|
const obj = evaluateNode(element, ts);
|
|
274
|
-
|
|
285
|
+
processToolObject(obj, elementLine);
|
|
275
286
|
} else {
|
|
276
287
|
const elementLine = sourceFile.getLineAndCharacterOfPosition(element.getStart()).line + 1;
|
|
277
288
|
console.warn(
|
|
278
|
-
`[pillar-sync] \u26A0 Skipping
|
|
289
|
+
`[pillar-sync] \u26A0 Skipping tool at ${relativePath}:${elementLine} \u2014 array element is not an inline object literal`
|
|
279
290
|
);
|
|
280
291
|
}
|
|
281
292
|
}
|
|
282
293
|
} else {
|
|
283
294
|
console.warn(
|
|
284
|
-
`[pillar-sync] \u26A0 Skipping
|
|
295
|
+
`[pillar-sync] \u26A0 Skipping tool at ${relativePath}:${lineNumber} \u2014 argument is not an inline object literal or array (variable reference can't be resolved statically)`
|
|
285
296
|
);
|
|
286
297
|
}
|
|
287
298
|
}
|
|
@@ -300,25 +311,32 @@ async function scanActions(scanDir) {
|
|
|
300
311
|
);
|
|
301
312
|
visit2(sourceFile);
|
|
302
313
|
}
|
|
303
|
-
return
|
|
314
|
+
return tools;
|
|
315
|
+
}
|
|
316
|
+
function normalizeTypeForBackend(type) {
|
|
317
|
+
if (type === "trigger_tool") {
|
|
318
|
+
return "trigger_action";
|
|
319
|
+
}
|
|
320
|
+
return type || "trigger_action";
|
|
304
321
|
}
|
|
305
|
-
function buildManifestFromScan(
|
|
322
|
+
function buildManifestFromScan(tools, platform, version, gitSha) {
|
|
306
323
|
const entries = [];
|
|
307
|
-
for (const
|
|
324
|
+
for (const tool of tools) {
|
|
308
325
|
const entry = {
|
|
309
|
-
name:
|
|
310
|
-
description:
|
|
311
|
-
|
|
326
|
+
name: tool.name,
|
|
327
|
+
description: tool.description,
|
|
328
|
+
// Normalize trigger_tool → trigger_action for backend API compatibility
|
|
329
|
+
type: normalizeTypeForBackend(tool.type)
|
|
312
330
|
};
|
|
313
|
-
if (
|
|
314
|
-
entry.examples =
|
|
315
|
-
if (
|
|
316
|
-
entry.auto_run =
|
|
317
|
-
if (
|
|
318
|
-
entry.auto_complete =
|
|
331
|
+
if (tool.examples?.length)
|
|
332
|
+
entry.examples = tool.examples;
|
|
333
|
+
if (tool.autoRun)
|
|
334
|
+
entry.auto_run = tool.autoRun;
|
|
335
|
+
if (tool.autoComplete !== void 0)
|
|
336
|
+
entry.auto_complete = tool.autoComplete;
|
|
319
337
|
entry.returns_data = true;
|
|
320
|
-
if (
|
|
321
|
-
entry.data_schema =
|
|
338
|
+
if (tool.inputSchema)
|
|
339
|
+
entry.data_schema = tool.inputSchema;
|
|
322
340
|
entries.push(entry);
|
|
323
341
|
}
|
|
324
342
|
return {
|
|
@@ -327,6 +345,7 @@ function buildManifestFromScan(actions, platform, version, gitSha) {
|
|
|
327
345
|
gitSha,
|
|
328
346
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
329
347
|
actions: entries
|
|
348
|
+
// Keep 'actions' key for backend API compatibility
|
|
330
349
|
};
|
|
331
350
|
}
|
|
332
351
|
async function main() {
|
|
@@ -362,21 +381,21 @@ async function main() {
|
|
|
362
381
|
const platform = process.env.PILLAR_PLATFORM || "web";
|
|
363
382
|
const version = process.env.PILLAR_VERSION || getPackageVersion();
|
|
364
383
|
const gitSha = process.env.GIT_SHA || getGitSha();
|
|
365
|
-
console.log(`[pillar-sync] Scanning for
|
|
366
|
-
let
|
|
384
|
+
console.log(`[pillar-sync] Scanning for tools in: ${scanDir}`);
|
|
385
|
+
let scannedTools;
|
|
367
386
|
try {
|
|
368
|
-
|
|
387
|
+
scannedTools = await scanTools(scanDir);
|
|
369
388
|
} catch (error) {
|
|
370
|
-
console.error(`[pillar-sync] Failed to scan
|
|
389
|
+
console.error(`[pillar-sync] Failed to scan tools:`, error);
|
|
371
390
|
process.exit(1);
|
|
372
391
|
}
|
|
373
|
-
const
|
|
374
|
-
console.log(`[pillar-sync] Found ${
|
|
375
|
-
if (
|
|
376
|
-
console.warn("[pillar-sync] No
|
|
392
|
+
const toolCount = scannedTools.length;
|
|
393
|
+
console.log(`[pillar-sync] Found ${toolCount} tools`);
|
|
394
|
+
if (toolCount === 0) {
|
|
395
|
+
console.warn("[pillar-sync] No tools found. Nothing to sync.");
|
|
377
396
|
process.exit(0);
|
|
378
397
|
}
|
|
379
|
-
const manifest = buildManifestFromScan(
|
|
398
|
+
const manifest = buildManifestFromScan(scannedTools, platform, version, gitSha);
|
|
380
399
|
console.log(`[pillar-sync] Platform: ${platform}`);
|
|
381
400
|
console.log(`[pillar-sync] Version: ${version}`);
|
|
382
401
|
console.log(`[pillar-sync] Git SHA: ${gitSha || "not available"}`);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Floating Help Button Component
|
|
3
|
+
* A floating action button that opens the help panel
|
|
4
|
+
*/
|
|
5
|
+
import type { ResolvedConfig, FloatingButtonPosition } from '../../core/config';
|
|
6
|
+
/**
|
|
7
|
+
* FloatingButton class that manages the button lifecycle
|
|
8
|
+
* Uses Preact for rendering but maintains imperative control
|
|
9
|
+
*/
|
|
10
|
+
export declare class FloatingButton {
|
|
11
|
+
private config;
|
|
12
|
+
private onClick;
|
|
13
|
+
private container;
|
|
14
|
+
private stylesInjected;
|
|
15
|
+
private _isHidden;
|
|
16
|
+
constructor(config: ResolvedConfig, onClick: () => void);
|
|
17
|
+
/**
|
|
18
|
+
* Initialize the floating button
|
|
19
|
+
*/
|
|
20
|
+
init(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Set the open state (to update icon when panel opens)
|
|
23
|
+
*/
|
|
24
|
+
setOpen(_isOpen: boolean): void;
|
|
25
|
+
/**
|
|
26
|
+
* Show the button
|
|
27
|
+
*/
|
|
28
|
+
show(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Hide the button
|
|
31
|
+
*/
|
|
32
|
+
hide(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Update button position
|
|
35
|
+
*/
|
|
36
|
+
setPosition(position: FloatingButtonPosition): void;
|
|
37
|
+
/**
|
|
38
|
+
* Update button label
|
|
39
|
+
*/
|
|
40
|
+
setLabel(label: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Destroy the button
|
|
43
|
+
*/
|
|
44
|
+
destroy(): void;
|
|
45
|
+
private render;
|
|
46
|
+
}
|