@pillar-ai/sdk 0.1.19 → 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.
Files changed (53) hide show
  1. package/dist/actions/definitions/analytics.d.ts +18 -0
  2. package/dist/actions/definitions/content.d.ts +40 -0
  3. package/dist/actions/definitions/index.d.ts +26 -0
  4. package/dist/actions/definitions/navigation.d.ts +65 -0
  5. package/dist/actions/definitions/settings.d.ts +162 -0
  6. package/dist/actions/definitions/sources.d.ts +44 -0
  7. package/dist/actions/definitions/support.d.ts +15 -0
  8. package/dist/actions/definitions/team.d.ts +120 -0
  9. package/dist/api/ag-ui-adapter.d.ts +76 -0
  10. package/dist/api/ag-ui-bridge.d.ts +49 -0
  11. package/dist/api/ag-ui-client.d.ts +102 -0
  12. package/dist/api/ag-ui-handler.d.ts +89 -0
  13. package/dist/api/mcp-client.d.ts +46 -24
  14. package/dist/cli/sync.js +253 -174
  15. package/dist/components/Button/FloatingButton.d.ts +46 -0
  16. package/dist/components/PagePilot/styles.d.ts +1 -1
  17. package/dist/components/Panel/TabNavigation.d.ts +16 -0
  18. package/dist/components/Panel/styles.d.ts +1 -1
  19. package/dist/components/Progress/AGUIProgress.d.ts +15 -0
  20. package/dist/components/Progress/ErrorRow.d.ts +12 -0
  21. package/dist/components/Progress/index.d.ts +1 -0
  22. package/dist/components/Tooltips/Tooltip.d.ts +46 -0
  23. package/dist/components/Tooltips/TooltipManager.d.ts +41 -0
  24. package/dist/components/Tooltips/index.d.ts +6 -0
  25. package/dist/components/Tooltips/styles.d.ts +5 -0
  26. package/dist/components/Views/ArticleChatView.d.ts +10 -0
  27. package/dist/components/Views/ArticleView.d.ts +10 -0
  28. package/dist/components/Views/CategoryView.d.ts +11 -0
  29. package/dist/components/Views/HelpCenterArticles.d.ts +17 -0
  30. package/dist/components/Views/SearchView.d.ts +10 -0
  31. package/dist/components/Views/SupportView.d.ts +15 -0
  32. package/dist/components/shared/ArticleCard.d.ts +17 -0
  33. package/dist/components/shared/CategoryCard.d.ts +17 -0
  34. package/dist/content/extensions/AccordionNode.d.ts +10 -0
  35. package/dist/content/extensions/CalloutNode.d.ts +11 -0
  36. package/dist/content/extensions/index.d.ts +5 -0
  37. package/dist/content/index.d.ts +5 -0
  38. package/dist/content/renderer.d.ts +24 -0
  39. package/dist/core/Pillar.d.ts +85 -28
  40. package/dist/core/config.d.ts +1 -1
  41. package/dist/core/events.d.ts +7 -1
  42. package/dist/index.d.ts +2 -2
  43. package/dist/pillar.esm.js +1 -1
  44. package/dist/store/chat.d.ts +12 -0
  45. package/dist/store/tooltips.d.ts +21 -0
  46. package/dist/tools/index.d.ts +27 -0
  47. package/dist/tools/registry.d.ts +106 -0
  48. package/dist/tools/types.d.ts +564 -0
  49. package/dist/utils/helpdesk.d.ts +33 -0
  50. package/dist/utils/markdown.d.ts +9 -0
  51. package/dist/utils/resilient-fetch.d.ts +25 -0
  52. package/package.json +12 -3
  53. package/src/actions/types.ts +0 -524
package/dist/cli/sync.js CHANGED
@@ -4,7 +4,6 @@
4
4
  import * as fs from "fs";
5
5
  import * as path from "path";
6
6
  import { execSync } from "child_process";
7
- import { pathToFileURL } from "url";
8
7
  var DEFAULT_API_URL = "https://help-api.trypillar.com";
9
8
  var LOCAL_API_URL = "http://localhost:8003";
10
9
  function parseArgs(args) {
@@ -26,14 +25,16 @@ function parseArgs(args) {
26
25
  }
27
26
  function printUsage() {
28
27
  console.log(`
29
- Pillar Action Sync CLI
28
+ Pillar Tool Sync CLI
29
+
30
+ Scans for usePillarTool/defineTool calls and syncs to the Pillar backend.
31
+ Also supports legacy usePillarAction/defineAction calls.
30
32
 
31
33
  Usage:
32
- npx pillar-sync --actions <path> [--local]
34
+ npx pillar-sync --scan <dir> [--local]
33
35
 
34
36
  Arguments:
35
- --actions <path> Path to your actions definition file (required)
36
- Supports .ts, .js, .mjs files
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,157 +47,13 @@ Environment Variables:
46
47
  GIT_SHA Git commit SHA for traceability
47
48
 
48
49
  Examples:
49
- # Production
50
- PILLAR_SLUG=my-app PILLAR_SECRET=xxx npx pillar-sync --actions ./lib/actions.ts
50
+ # Scan and sync tools
51
+ PILLAR_SLUG=my-app PILLAR_SECRET=xxx npx pillar-sync --scan ./src
51
52
 
52
53
  # Local development
53
- PILLAR_SLUG=my-app PILLAR_SECRET=xxx npx pillar-sync --actions ./lib/actions.ts --local
54
+ PILLAR_SLUG=my-app PILLAR_SECRET=xxx npx pillar-sync --scan ./src --local
54
55
  `);
55
56
  }
56
- async function loadActions(actionsPath) {
57
- const absolutePath = path.resolve(process.cwd(), actionsPath);
58
- if (!fs.existsSync(absolutePath)) {
59
- throw new Error(`Actions file not found: ${absolutePath}`);
60
- }
61
- const isTypeScript = absolutePath.endsWith(".ts") || absolutePath.endsWith(".tsx");
62
- if (isTypeScript) {
63
- try {
64
- const tempDir = path.dirname(absolutePath);
65
- const tempFile = path.join(tempDir, `.pillar-sync-temp-${Date.now()}.mjs`);
66
- const importPath = absolutePath.replace(/\\/g, "/");
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 }));`;
93
- fs.writeFileSync(tempFile, extractScript, "utf-8");
94
- try {
95
- const result = execSync(`npx tsx "${tempFile}"`, {
96
- encoding: "utf-8",
97
- cwd: process.cwd(),
98
- stdio: ["pipe", "pipe", "pipe"]
99
- });
100
- const parsed = JSON.parse(result.trim());
101
- const actions = parsed.actions;
102
- const agentGuidance = parsed.agentGuidance;
103
- if (!actions || typeof actions !== "object") {
104
- throw new Error(
105
- 'Actions file must export an actions object as default or named export "actions"'
106
- );
107
- }
108
- return { actions, agentGuidance };
109
- } finally {
110
- if (fs.existsSync(tempFile)) {
111
- fs.unlinkSync(tempFile);
112
- }
113
- }
114
- } catch (error) {
115
- if (error instanceof Error && error.message.includes("tsx")) {
116
- console.error("[pillar-sync] TypeScript files require tsx.");
117
- console.error("[pillar-sync] Make sure tsx is installed: npm install -D tsx");
118
- console.error("[pillar-sync] Then run: npx pillar-sync --actions ./actions.ts");
119
- }
120
- throw error;
121
- }
122
- }
123
- const fileUrl = pathToFileURL(absolutePath).href;
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;
142
- const module = await import(fileUrl);
143
- const actions = resolveActions2(module);
144
- const agentGuidance = module.agentGuidance || module.default?.agentGuidance;
145
- if (!actions || typeof actions !== "object") {
146
- throw new Error(
147
- 'Actions file must export an actions object as default or named export "actions"'
148
- );
149
- }
150
- return { actions, agentGuidance };
151
- } catch (error) {
152
- throw error;
153
- }
154
- }
155
- function buildManifest(actions, platform, version, gitSha, agentGuidance) {
156
- const entries = [];
157
- for (const [name, definition] of Object.entries(actions)) {
158
- const entry = {
159
- name,
160
- description: definition.description,
161
- type: definition.type
162
- };
163
- if (definition.examples?.length)
164
- entry.examples = definition.examples;
165
- if (definition.path)
166
- entry.path = definition.path;
167
- if (definition.externalUrl)
168
- entry.external_url = definition.externalUrl;
169
- if (definition.autoRun)
170
- entry.auto_run = definition.autoRun;
171
- if (definition.autoComplete)
172
- entry.auto_complete = definition.autoComplete;
173
- if (definition.returns !== void 0) {
174
- entry.returns_data = definition.returns;
175
- } else if (definition.type === "query") {
176
- entry.returns_data = true;
177
- }
178
- if (definition.dataSchema)
179
- entry.data_schema = definition.dataSchema;
180
- if (definition.defaultData)
181
- entry.default_data = definition.defaultData;
182
- if (definition.requiredContext)
183
- entry.required_context = definition.requiredContext;
184
- if (definition.parameterExamples?.length)
185
- entry.parameter_examples = definition.parameterExamples;
186
- entries.push(entry);
187
- }
188
- const manifest = {
189
- platform,
190
- version,
191
- gitSha,
192
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
193
- actions: entries
194
- };
195
- if (agentGuidance) {
196
- manifest.agentGuidance = agentGuidance;
197
- }
198
- return manifest;
199
- }
200
57
  async function pollStatus(statusUrl, secret, maxWaitSeconds = 300) {
201
58
  const startTime = Date.now();
202
59
  let lastProgress = { processed: 0, total: 0 };
@@ -262,15 +119,244 @@ function getGitSha() {
262
119
  return void 0;
263
120
  }
264
121
  }
122
+ function globFiles(dir, extensions) {
123
+ const results = [];
124
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
125
+ for (const entry of entries) {
126
+ if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".next") {
127
+ continue;
128
+ }
129
+ const fullPath = path.join(dir, entry.name);
130
+ if (entry.isDirectory()) {
131
+ results.push(...globFiles(fullPath, extensions));
132
+ } else if (extensions.some((ext) => entry.name.endsWith(ext))) {
133
+ results.push(fullPath);
134
+ }
135
+ }
136
+ return results;
137
+ }
138
+ function evaluateNode(node, ts) {
139
+ const n = node;
140
+ if (ts.isStringLiteral(n)) {
141
+ return n.text;
142
+ }
143
+ if (ts.isNoSubstitutionTemplateLiteral(n)) {
144
+ return n.text;
145
+ }
146
+ if (ts.isNumericLiteral(n)) {
147
+ return Number(n.text);
148
+ }
149
+ if (n.kind === ts.SyntaxKind.TrueKeyword)
150
+ return true;
151
+ if (n.kind === ts.SyntaxKind.FalseKeyword)
152
+ return false;
153
+ if (n.kind === ts.SyntaxKind.NullKeyword)
154
+ return null;
155
+ if (ts.isPrefixUnaryExpression(n)) {
156
+ const expr = n;
157
+ if (expr.operator === ts.SyntaxKind.MinusToken) {
158
+ const operand = evaluateNode(expr.operand, ts);
159
+ if (typeof operand === "number")
160
+ return -operand;
161
+ }
162
+ }
163
+ if (ts.isArrayLiteralExpression(n)) {
164
+ const arr = n;
165
+ const result = [];
166
+ for (const elem of arr.elements) {
167
+ const val = evaluateNode(elem, ts);
168
+ if (val === void 0)
169
+ return void 0;
170
+ result.push(val);
171
+ }
172
+ return result;
173
+ }
174
+ if (ts.isObjectLiteralExpression(n)) {
175
+ const obj = n;
176
+ const result = {};
177
+ for (const prop of obj.properties) {
178
+ if (ts.isPropertyAssignment(prop)) {
179
+ const key = prop.name ? ts.isIdentifier(prop.name) ? prop.name.text : ts.isStringLiteral(prop.name) ? prop.name.text : void 0 : void 0;
180
+ if (!key)
181
+ continue;
182
+ const val = evaluateNode(prop.initializer, ts);
183
+ if (val !== void 0) {
184
+ result[key] = val;
185
+ }
186
+ }
187
+ if (ts.isShorthandPropertyAssignment(prop)) {
188
+ continue;
189
+ }
190
+ }
191
+ return result;
192
+ }
193
+ if (ts.isAsExpression(n)) {
194
+ return evaluateNode(n.expression, ts);
195
+ }
196
+ if (ts.isParenthesizedExpression(n)) {
197
+ return evaluateNode(n.expression, ts);
198
+ }
199
+ if (ts.isBinaryExpression(n)) {
200
+ const bin = n;
201
+ if (bin.operatorToken.kind === ts.SyntaxKind.PlusToken) {
202
+ const left = evaluateNode(bin.left, ts);
203
+ const right = evaluateNode(bin.right, ts);
204
+ if (typeof left === "string" && typeof right === "string") {
205
+ return left + right;
206
+ }
207
+ }
208
+ }
209
+ return void 0;
210
+ }
211
+ async function scanTools(scanDir) {
212
+ const absoluteDir = path.resolve(process.cwd(), scanDir);
213
+ if (!fs.existsSync(absoluteDir)) {
214
+ throw new Error(`Scan directory not found: ${absoluteDir}`);
215
+ }
216
+ let ts;
217
+ try {
218
+ ts = await import("typescript");
219
+ } catch {
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
+ }
229
+ }
230
+ const files = globFiles(absoluteDir, [".ts", ".tsx", ".js", ".jsx", ".mjs"]);
231
+ console.log(`[pillar-sync] Scanning ${files.length} files in ${scanDir}`);
232
+ const PATTERNS = ["defineTool", "usePillarTool", "defineAction", "usePillarAction"];
233
+ const candidateFiles = files.filter((file) => {
234
+ const content = fs.readFileSync(file, "utf-8");
235
+ return PATTERNS.some((p) => content.includes(p));
236
+ });
237
+ console.log(`[pillar-sync] Found ${candidateFiles.length} files with tool definitions`);
238
+ const tools = [];
239
+ for (const filePath of candidateFiles) {
240
+ let visit2 = function(node) {
241
+ if (ts.isCallExpression(node)) {
242
+ const callee = node.expression;
243
+ let isTargetCall = false;
244
+ if (ts.isIdentifier(callee)) {
245
+ isTargetCall = PATTERNS.includes(callee.text);
246
+ } else if (ts.isPropertyAccessExpression(callee)) {
247
+ isTargetCall = callee.name.text === "defineTool" || callee.name.text === "defineAction";
248
+ }
249
+ if (isTargetCall && node.arguments.length > 0) {
250
+ const arg = node.arguments[0];
251
+ const lineNumber = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
252
+ const relativePath = path.relative(process.cwd(), filePath);
253
+ const processToolObject = (obj, line) => {
254
+ if (obj && typeof obj.name === "string" && typeof obj.description === "string") {
255
+ let toolType = obj.type;
256
+ if (toolType === "trigger_action") {
257
+ toolType = "trigger_tool";
258
+ }
259
+ tools.push({
260
+ name: obj.name,
261
+ description: obj.description,
262
+ type: toolType,
263
+ inputSchema: obj.inputSchema,
264
+ examples: obj.examples,
265
+ autoRun: obj.autoRun,
266
+ autoComplete: obj.autoComplete,
267
+ sourceFile: relativePath,
268
+ line
269
+ });
270
+ console.log(`[pillar-sync] ${obj.name} (${relativePath}:${line})`);
271
+ } else if (obj) {
272
+ console.warn(
273
+ `[pillar-sync] \u26A0 Skipping tool at ${relativePath}:${line} \u2014 missing name or description`
274
+ );
275
+ }
276
+ };
277
+ if (ts.isObjectLiteralExpression(arg)) {
278
+ const obj = evaluateNode(arg, ts);
279
+ processToolObject(obj, lineNumber);
280
+ } else if (ts.isArrayLiteralExpression(arg)) {
281
+ for (const element of arg.elements) {
282
+ if (ts.isObjectLiteralExpression(element)) {
283
+ const elementLine = sourceFile.getLineAndCharacterOfPosition(element.getStart()).line + 1;
284
+ const obj = evaluateNode(element, ts);
285
+ processToolObject(obj, elementLine);
286
+ } else {
287
+ const elementLine = sourceFile.getLineAndCharacterOfPosition(element.getStart()).line + 1;
288
+ console.warn(
289
+ `[pillar-sync] \u26A0 Skipping tool at ${relativePath}:${elementLine} \u2014 array element is not an inline object literal`
290
+ );
291
+ }
292
+ }
293
+ } else {
294
+ console.warn(
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)`
296
+ );
297
+ }
298
+ }
299
+ }
300
+ ts.forEachChild(node, visit2);
301
+ };
302
+ var visit = visit2;
303
+ const content = fs.readFileSync(filePath, "utf-8");
304
+ const sourceFile = ts.createSourceFile(
305
+ filePath,
306
+ content,
307
+ ts.ScriptTarget.Latest,
308
+ true,
309
+ // setParentNodes
310
+ filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : filePath.endsWith(".jsx") ? ts.ScriptKind.JSX : /\.m?js$/.test(filePath) ? ts.ScriptKind.JS : ts.ScriptKind.TS
311
+ );
312
+ visit2(sourceFile);
313
+ }
314
+ return tools;
315
+ }
316
+ function normalizeTypeForBackend(type) {
317
+ if (type === "trigger_tool") {
318
+ return "trigger_action";
319
+ }
320
+ return type || "trigger_action";
321
+ }
322
+ function buildManifestFromScan(tools, platform, version, gitSha) {
323
+ const entries = [];
324
+ for (const tool of tools) {
325
+ const entry = {
326
+ name: tool.name,
327
+ description: tool.description,
328
+ // Normalize trigger_tool → trigger_action for backend API compatibility
329
+ type: normalizeTypeForBackend(tool.type)
330
+ };
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;
337
+ entry.returns_data = true;
338
+ if (tool.inputSchema)
339
+ entry.data_schema = tool.inputSchema;
340
+ entries.push(entry);
341
+ }
342
+ return {
343
+ platform,
344
+ version,
345
+ gitSha,
346
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
347
+ actions: entries
348
+ // Keep 'actions' key for backend API compatibility
349
+ };
350
+ }
265
351
  async function main() {
266
352
  const args = parseArgs(process.argv.slice(2));
267
353
  if (args.help) {
268
354
  printUsage();
269
355
  process.exit(0);
270
356
  }
271
- const actionsPath = args.actions;
272
- if (!actionsPath) {
273
- console.error("[pillar-sync] Missing required --actions argument");
357
+ const scanDir = args.scan;
358
+ if (!scanDir) {
359
+ console.error("[pillar-sync] Missing required argument: --scan <dir>");
274
360
  console.error("");
275
361
  printUsage();
276
362
  process.exit(1);
@@ -292,31 +378,27 @@ async function main() {
292
378
  console.error("Get these from the Pillar admin: Actions \u2192 Configure Sync");
293
379
  process.exit(1);
294
380
  }
295
- console.log(`[pillar-sync] Loading actions from: ${actionsPath}`);
296
- let loadedModule;
381
+ const platform = process.env.PILLAR_PLATFORM || "web";
382
+ const version = process.env.PILLAR_VERSION || getPackageVersion();
383
+ const gitSha = process.env.GIT_SHA || getGitSha();
384
+ console.log(`[pillar-sync] Scanning for tools in: ${scanDir}`);
385
+ let scannedTools;
297
386
  try {
298
- loadedModule = await loadActions(actionsPath);
387
+ scannedTools = await scanTools(scanDir);
299
388
  } catch (error) {
300
- console.error(`[pillar-sync] Failed to load actions:`, error);
389
+ console.error(`[pillar-sync] Failed to scan tools:`, error);
301
390
  process.exit(1);
302
391
  }
303
- const { actions, agentGuidance } = loadedModule;
304
- const actionCount = Object.keys(actions).length;
305
- console.log(`[pillar-sync] Found ${actionCount} actions`);
306
- if (agentGuidance) {
307
- console.log(`[pillar-sync] Found agent guidance (${agentGuidance.length} chars)`);
308
- }
309
- if (actionCount === 0) {
310
- console.warn("[pillar-sync] No actions found. Nothing to sync.");
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.");
311
396
  process.exit(0);
312
397
  }
313
- const platform = process.env.PILLAR_PLATFORM || "web";
314
- const version = process.env.PILLAR_VERSION || getPackageVersion();
315
- const gitSha = process.env.GIT_SHA || getGitSha();
398
+ const manifest = buildManifestFromScan(scannedTools, platform, version, gitSha);
316
399
  console.log(`[pillar-sync] Platform: ${platform}`);
317
400
  console.log(`[pillar-sync] Version: ${version}`);
318
401
  console.log(`[pillar-sync] Git SHA: ${gitSha || "not available"}`);
319
- const manifest = buildManifest(actions, platform, version, gitSha, agentGuidance);
320
402
  if (process.env.PILLAR_DEBUG) {
321
403
  const manifestPath = path.join(process.cwd(), "actions-manifest.json");
322
404
  fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
@@ -329,9 +411,6 @@ async function main() {
329
411
  git_sha: gitSha,
330
412
  actions: manifest.actions
331
413
  };
332
- if (agentGuidance) {
333
- requestBody.agent_guidance = agentGuidance;
334
- }
335
414
  const syncUrl = `${apiUrl}/api/admin/configs/${slug}/actions/sync/?async=true`;
336
415
  console.log(`[pillar-sync] POST ${syncUrl}`);
337
416
  try {
@@ -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
+ }
@@ -3,4 +3,4 @@
3
3
  * Injected into the document head (outside Shadow DOM)
4
4
  * Uses the same CSS variables as the Pillar panel for consistent theming
5
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";
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";
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Tab Navigation Component
3
+ * Vertical tabs on the right edge of the panel for switching between Assistant and Support
4
+ */
5
+ import { h } from 'preact';
6
+ import type { ResolvedSupportConfig } from '../../core/config';
7
+ interface TabNavigationProps {
8
+ supportConfig: ResolvedSupportConfig;
9
+ }
10
+ export declare function TabNavigation({ supportConfig }: TabNavigationProps): h.JSX.Element;
11
+ /**
12
+ * CSS Styles for Tab Navigation
13
+ * Should be appended to PANEL_STYLES
14
+ */
15
+ export declare const TAB_NAVIGATION_STYLES = "\n/* ============================================================================\n Panel Wrapper (for tab layout)\n Horizontal flex container with main content + tab nav\n ============================================================================ */\n\n._pillar-panel-wrapper {\n display: flex;\n flex-direction: row;\n height: 100%;\n overflow: hidden;\n}\n\n._pillar-panel-wrapper > ._pillar-panel-ui {\n flex: 1;\n min-width: 0;\n}\n\n.pillar-panel-wrapper {}\n\n/* ============================================================================\n Tab Navigation\n Vertical tabs on the right edge of the panel\n ============================================================================ */\n\n._pillar-tab-nav {\n display: flex;\n flex-direction: column;\n width: 48px;\n min-width: 48px;\n background: var(--pillar-bg-secondary);\n border-left: 1px solid var(--pillar-border);\n padding: var(--pillar-spacing-sm) 0;\n gap: var(--pillar-spacing-xs);\n}\n\n._pillar-tab {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 2px;\n padding: var(--pillar-spacing-sm) var(--pillar-spacing-xs);\n margin: 0 var(--pillar-spacing-xs);\n border: none;\n border-radius: var(--pillar-radius-md);\n background: transparent;\n color: var(--pillar-text-muted);\n cursor: pointer;\n transition: all var(--pillar-transition-fast);\n position: relative;\n}\n\n._pillar-tab:hover {\n background: var(--pillar-bg-tertiary);\n color: var(--pillar-text);\n}\n\n._pillar-tab--active {\n background: var(--pillar-primary-light);\n color: var(--pillar-primary);\n}\n\n._pillar-tab--active:hover {\n background: var(--pillar-primary-light-hover);\n color: var(--pillar-primary);\n}\n\n._pillar-tab-icon {\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n._pillar-tab-icon svg {\n width: 100%;\n height: 100%;\n}\n\n._pillar-tab-label {\n font-size: 9px;\n font-weight: 500;\n text-align: center;\n line-height: 1.2;\n max-width: 40px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Public override classes */\n.pillar-tab-nav {}\n.pillar-tab {}\n.pillar-tab-icon {}\n.pillar-tab-label {}\n";
16
+ export {};