Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions packages/extension/src/background_script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { PopupAutoClose } from "@/services/popupAutoClose"
import {
isSearchCommand,
isPageActionCommand,
isAiPromptCommand,
findMatchingPageRule,
} from "@/lib/utils"
import { execute } from "@/action/background"
Expand Down Expand Up @@ -161,6 +162,7 @@ const commandFuncs = {
const params = JSON.parse(param.command)
const isSearch = isSearchCommand(params)
const isPageAction = isPageActionCommand(params)
const isAiPrompt = isAiPromptCommand(params)
const sourceType = (params as { sourceType?: unknown }).sourceType
const sourceId = (params as { sourceId?: unknown }).sourceId
const normalizedSourceType = Object.values(COMMAND_SOURCE_TYPE).includes(
Expand All @@ -185,17 +187,27 @@ const commandFuncs = {
spaceEncoding: params.spaceEncoding,
popupOption: PopupOption,
}
: isPageAction
: isAiPrompt
? {
id: params.id,
title: params.title,
iconUrl: params.iconUrl,
...sourceInfo,
openMode: params.openMode,
pageActionOption: params.pageActionOption,
aiPromptOption: params.aiPromptOption,
popupOption: PopupOption,
}
: null
: isPageAction
? {
id: params.id,
title: params.title,
iconUrl: params.iconUrl,
...sourceInfo,
openMode: params.openMode,
pageActionOption: params.pageActionOption,
popupOption: PopupOption,
}
: null

if (!cmd) {
console.error("invalid command", param.command)
Expand Down
65 changes: 65 additions & 0 deletions packages/extension/src/components/commandHub/DownloadButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,71 @@ export const DownloadButton = (): JSX.Element => {
return () => clearTimeout(timer)
}, [open])

/**
* External postMessage API for adding/deleting commands from the Hub.
*
* This content script listens for messages from the Hub page (origin must match HUB_URL).
* The message object must have the following shape:
*
* --- AddCommand ---
* {
* action: "AddCommand",
* command: string // JSON-stringified command object (see below)
* }
*
* The `command` field is a JSON string representing a SearchCommand, an AiPromptCommand, or a PageActionCommand.
*
* SearchCommand (openMode is one of "popup" | "tab" | "window" | "backgroundTab" | "sidePanel"):
* {
* id: string, // Unique command identifier
* title: string, // Display name of the command
* searchUrl: string, // Search URL template (%s is replaced with selected text)
* iconUrl: string, // URL of the command icon
* openMode: string, // How to open the result: "popup" | "tab" | "window" | "backgroundTab" | "sidePanel"
* openModeSecondary?: string, // Secondary open mode (optional)
* spaceEncoding?: string, // Space encoding in URL: "plus" | "percent" (optional)
* sourceType?: string, // Origin of the command: "default" | "selfCreated" | "hubCommunity" | "unknown" (optional)
* sourceId?: string // Identifier of the source (optional)
* }
*
* AiPromptCommand (openMode is "aiPrompt"):
* {
* id: string, // Unique command identifier
* title: string, // Display name of the command
* iconUrl: string, // URL of the command icon
* openMode: "aiPrompt", // Must be "aiPrompt" for AI prompt commands
* aiPromptOption: {
* serviceId: string, // ID of the AI service to use (see hub/public/data/ai-services.json)
* prompt: string, // Prompt text sent to the AI service (supports variable placeholders)
* openMode: string // How to open the AI service result: "popup" | "tab" | "window" | etc.
* },
* sourceType?: string, // Origin of the command: "default" | "selfCreated" | "hubCommunity" | "unknown" (optional)
* sourceId?: string // Identifier of the source (optional)
* }
*
* PageActionCommand (openMode is "pageAction"):
* {
* id: string, // Unique command identifier
* title: string, // Display name of the command
* iconUrl: string, // URL of the command icon
* openMode: "pageAction", // Must be "pageAction" for page action commands
* pageActionOption: {
* startUrl: string, // URL to open when executing the page action
* pageUrl?: string, // URL pattern for command enablement (currentTab mode only, optional)
* openMode: string, // How to open the page: "none" | "popup" | "tab" | "backgroundTab" | "window" | "currentTab"
* steps: Array<PageActionStep>, // Sequence of automation steps to execute
* userVariables?: Array<{ name: string, value: string }> // User-defined variables (optional)
* },
* sourceType?: string, // Origin of the command: "default" | "selfCreated" | "hubCommunity" | "unknown" (optional)
* sourceId?: string // Identifier of the source (optional)
* }
*
* --- DeleteCommand ---
* {
* action: "DeleteCommand",
* id: string // ID of the command to remove
* }
*/
useEffect(() => {
const hubOrigin = new URL(HUB_URL).origin
const handleMessage = (event: MessageEvent) => {
Expand Down