@alfe.ai/openclaw-search 0.0.24 → 0.0.26
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/plugin.d.cts +1 -0
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.ts +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin2.cjs +72 -2
- package/dist/plugin2.js +72 -2
- package/dist/plugin2.js.map +1 -1
- package/openclaw.plugin.json +2 -1
- package/package.json +2 -2
package/dist/plugin.d.cts
CHANGED
package/dist/plugin.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.cts","names":[],"sources":["../src/plugin.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"plugin.d.cts","names":[],"sources":["../src/plugin.ts"],"mappings":";UAQU,SAAA;EAAA,MAAA,EAAA;IAMJ,IAAA,EAyCL,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAAA,IAAA;IAAA,IAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAAA,IAAA;IApCe,KAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAAA,IAAA;IAiCE,KAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAAA,IAAA;EAAS,CAAA;;;;cAtCrB;;;;gBAKU;kBAiCE"}
|
package/dist/plugin.d.ts
CHANGED
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../src/plugin.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../src/plugin.ts"],"mappings":";UAQU,SAAA;EAAA,MAAA,EAAA;IAMJ,IAAA,EAyCL,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAAA,IAAA;IAAA,IAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAAA,IAAA;IApCe,KAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAAA,IAAA;IAiCE,KAAA,EAAA,CAAA,GAAA,IAAA,EAAA,OAAA,EAAA,EAAA,GAAA,IAAA;EAAS,CAAA;;;;cAtCrB;;;;gBAKU;kBAiCE"}
|
package/dist/plugin2.cjs
CHANGED
|
@@ -3,6 +3,10 @@ let _alfe_ai_agent_api_client = require("@alfe.ai/agent-api-client");
|
|
|
3
3
|
let node_module = require("node:module");
|
|
4
4
|
//#region src/tools.ts
|
|
5
5
|
function registerTools(api, client) {
|
|
6
|
+
registerWebSearchTool(api, client);
|
|
7
|
+
registerAuxiliaryTools(api, client);
|
|
8
|
+
}
|
|
9
|
+
function registerWebSearchTool(api, client) {
|
|
6
10
|
api.registerTool({
|
|
7
11
|
name: "web_search",
|
|
8
12
|
label: "web_search",
|
|
@@ -31,6 +35,8 @@ function registerTools(api, client) {
|
|
|
31
35
|
return client.searchWeb(params);
|
|
32
36
|
}
|
|
33
37
|
});
|
|
38
|
+
}
|
|
39
|
+
function registerAuxiliaryTools(api, client) {
|
|
34
40
|
api.registerTool({
|
|
35
41
|
name: "image_search",
|
|
36
42
|
label: "image_search",
|
|
@@ -84,6 +90,62 @@ function registerTools(api, client) {
|
|
|
84
90
|
});
|
|
85
91
|
}
|
|
86
92
|
//#endregion
|
|
93
|
+
//#region src/provider.ts
|
|
94
|
+
const WEB_SEARCH_SCHEMA = {
|
|
95
|
+
type: "object",
|
|
96
|
+
properties: {
|
|
97
|
+
query: {
|
|
98
|
+
type: "string",
|
|
99
|
+
description: "The search query"
|
|
100
|
+
},
|
|
101
|
+
count: {
|
|
102
|
+
type: "number",
|
|
103
|
+
description: "Number of results to return (1-20)",
|
|
104
|
+
default: 10
|
|
105
|
+
},
|
|
106
|
+
offset: {
|
|
107
|
+
type: "number",
|
|
108
|
+
description: "Pagination offset (0-9)",
|
|
109
|
+
default: 0
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
required: ["query"]
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Web-search provider that plugs into OpenClaw's builtin `web_search` tool
|
|
116
|
+
* (OpenClaw 2026.6+ ships one; registering a plugin tool with the same name
|
|
117
|
+
* is dropped as a name conflict). Routes through the Alfe search service.
|
|
118
|
+
*
|
|
119
|
+
* The Alfe API key doubles as the provider credential: OpenClaw only
|
|
120
|
+
* auto-selects providers with a credential signal, and the key is always
|
|
121
|
+
* present on a configured agent, so the provider self-selects without any
|
|
122
|
+
* openclaw.json changes. An explicit user `provider` selection still wins.
|
|
123
|
+
*/
|
|
124
|
+
function createAlfeWebSearchProvider(client, apiKey) {
|
|
125
|
+
return {
|
|
126
|
+
id: "alfe",
|
|
127
|
+
label: "Alfe Search",
|
|
128
|
+
hint: "Managed web search routed through the Alfe platform",
|
|
129
|
+
requiresCredential: true,
|
|
130
|
+
credentialLabel: "Alfe API Key",
|
|
131
|
+
envVars: ["ALFE_API_KEY"],
|
|
132
|
+
placeholder: "alfe_...",
|
|
133
|
+
signupUrl: "https://alfe.ai",
|
|
134
|
+
autoDetectOrder: 10,
|
|
135
|
+
credentialPath: "plugins.entries.@alfe.ai/openclaw-search.config.apiKey",
|
|
136
|
+
getCredentialValue: () => apiKey,
|
|
137
|
+
setCredentialValue: () => void 0,
|
|
138
|
+
getConfiguredCredentialValue: () => apiKey,
|
|
139
|
+
createTool: () => ({
|
|
140
|
+
description: "Search the web. Returns web pages with titles, URLs, and descriptions.",
|
|
141
|
+
parameters: WEB_SEARCH_SCHEMA,
|
|
142
|
+
execute: async (args) => {
|
|
143
|
+
return await client.searchWeb(args);
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
//#endregion
|
|
87
149
|
//#region src/plugin.ts
|
|
88
150
|
const plugin = {
|
|
89
151
|
id: "@alfe.ai/openclaw-search",
|
|
@@ -93,8 +155,10 @@ const plugin = {
|
|
|
93
155
|
const log = api.logger;
|
|
94
156
|
log.info("Search plugin activating...");
|
|
95
157
|
let client;
|
|
158
|
+
let apiKey;
|
|
96
159
|
try {
|
|
97
160
|
const config = (0, _alfe_ai_config.resolveConfig)();
|
|
161
|
+
apiKey = config.apiKey;
|
|
98
162
|
client = new _alfe_ai_agent_api_client.AgentApiClient({
|
|
99
163
|
apiUrl: config.apiUrl,
|
|
100
164
|
apiKey: config.apiKey
|
|
@@ -103,8 +167,14 @@ const plugin = {
|
|
|
103
167
|
log.error(`Search plugin: failed to resolve config — ${err instanceof Error ? err.message : String(err)}`);
|
|
104
168
|
return;
|
|
105
169
|
}
|
|
106
|
-
|
|
107
|
-
|
|
170
|
+
if (typeof api.registerWebSearchProvider === "function") {
|
|
171
|
+
registerAuxiliaryTools(api, client);
|
|
172
|
+
api.registerWebSearchProvider(createAlfeWebSearchProvider(client, apiKey));
|
|
173
|
+
log.info("Search plugin activated — alfe web_search provider registered; image_search, news_search tools registered");
|
|
174
|
+
} else {
|
|
175
|
+
registerTools(api, client);
|
|
176
|
+
log.info("Search plugin activated — web_search, image_search, news_search tools registered");
|
|
177
|
+
}
|
|
108
178
|
},
|
|
109
179
|
deactivate(api) {
|
|
110
180
|
api.logger.info("Search plugin deactivating...");
|
package/dist/plugin2.js
CHANGED
|
@@ -3,6 +3,10 @@ import { resolveConfig } from "@alfe.ai/config";
|
|
|
3
3
|
import { AgentApiClient } from "@alfe.ai/agent-api-client";
|
|
4
4
|
//#region src/tools.ts
|
|
5
5
|
function registerTools(api, client) {
|
|
6
|
+
registerWebSearchTool(api, client);
|
|
7
|
+
registerAuxiliaryTools(api, client);
|
|
8
|
+
}
|
|
9
|
+
function registerWebSearchTool(api, client) {
|
|
6
10
|
api.registerTool({
|
|
7
11
|
name: "web_search",
|
|
8
12
|
label: "web_search",
|
|
@@ -31,6 +35,8 @@ function registerTools(api, client) {
|
|
|
31
35
|
return client.searchWeb(params);
|
|
32
36
|
}
|
|
33
37
|
});
|
|
38
|
+
}
|
|
39
|
+
function registerAuxiliaryTools(api, client) {
|
|
34
40
|
api.registerTool({
|
|
35
41
|
name: "image_search",
|
|
36
42
|
label: "image_search",
|
|
@@ -84,6 +90,62 @@ function registerTools(api, client) {
|
|
|
84
90
|
});
|
|
85
91
|
}
|
|
86
92
|
//#endregion
|
|
93
|
+
//#region src/provider.ts
|
|
94
|
+
const WEB_SEARCH_SCHEMA = {
|
|
95
|
+
type: "object",
|
|
96
|
+
properties: {
|
|
97
|
+
query: {
|
|
98
|
+
type: "string",
|
|
99
|
+
description: "The search query"
|
|
100
|
+
},
|
|
101
|
+
count: {
|
|
102
|
+
type: "number",
|
|
103
|
+
description: "Number of results to return (1-20)",
|
|
104
|
+
default: 10
|
|
105
|
+
},
|
|
106
|
+
offset: {
|
|
107
|
+
type: "number",
|
|
108
|
+
description: "Pagination offset (0-9)",
|
|
109
|
+
default: 0
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
required: ["query"]
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Web-search provider that plugs into OpenClaw's builtin `web_search` tool
|
|
116
|
+
* (OpenClaw 2026.6+ ships one; registering a plugin tool with the same name
|
|
117
|
+
* is dropped as a name conflict). Routes through the Alfe search service.
|
|
118
|
+
*
|
|
119
|
+
* The Alfe API key doubles as the provider credential: OpenClaw only
|
|
120
|
+
* auto-selects providers with a credential signal, and the key is always
|
|
121
|
+
* present on a configured agent, so the provider self-selects without any
|
|
122
|
+
* openclaw.json changes. An explicit user `provider` selection still wins.
|
|
123
|
+
*/
|
|
124
|
+
function createAlfeWebSearchProvider(client, apiKey) {
|
|
125
|
+
return {
|
|
126
|
+
id: "alfe",
|
|
127
|
+
label: "Alfe Search",
|
|
128
|
+
hint: "Managed web search routed through the Alfe platform",
|
|
129
|
+
requiresCredential: true,
|
|
130
|
+
credentialLabel: "Alfe API Key",
|
|
131
|
+
envVars: ["ALFE_API_KEY"],
|
|
132
|
+
placeholder: "alfe_...",
|
|
133
|
+
signupUrl: "https://alfe.ai",
|
|
134
|
+
autoDetectOrder: 10,
|
|
135
|
+
credentialPath: "plugins.entries.@alfe.ai/openclaw-search.config.apiKey",
|
|
136
|
+
getCredentialValue: () => apiKey,
|
|
137
|
+
setCredentialValue: () => void 0,
|
|
138
|
+
getConfiguredCredentialValue: () => apiKey,
|
|
139
|
+
createTool: () => ({
|
|
140
|
+
description: "Search the web. Returns web pages with titles, URLs, and descriptions.",
|
|
141
|
+
parameters: WEB_SEARCH_SCHEMA,
|
|
142
|
+
execute: async (args) => {
|
|
143
|
+
return await client.searchWeb(args);
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
//#endregion
|
|
87
149
|
//#region src/plugin.ts
|
|
88
150
|
const plugin = {
|
|
89
151
|
id: "@alfe.ai/openclaw-search",
|
|
@@ -93,8 +155,10 @@ const plugin = {
|
|
|
93
155
|
const log = api.logger;
|
|
94
156
|
log.info("Search plugin activating...");
|
|
95
157
|
let client;
|
|
158
|
+
let apiKey;
|
|
96
159
|
try {
|
|
97
160
|
const config = resolveConfig();
|
|
161
|
+
apiKey = config.apiKey;
|
|
98
162
|
client = new AgentApiClient({
|
|
99
163
|
apiUrl: config.apiUrl,
|
|
100
164
|
apiKey: config.apiKey
|
|
@@ -103,8 +167,14 @@ const plugin = {
|
|
|
103
167
|
log.error(`Search plugin: failed to resolve config — ${err instanceof Error ? err.message : String(err)}`);
|
|
104
168
|
return;
|
|
105
169
|
}
|
|
106
|
-
|
|
107
|
-
|
|
170
|
+
if (typeof api.registerWebSearchProvider === "function") {
|
|
171
|
+
registerAuxiliaryTools(api, client);
|
|
172
|
+
api.registerWebSearchProvider(createAlfeWebSearchProvider(client, apiKey));
|
|
173
|
+
log.info("Search plugin activated — alfe web_search provider registered; image_search, news_search tools registered");
|
|
174
|
+
} else {
|
|
175
|
+
registerTools(api, client);
|
|
176
|
+
log.info("Search plugin activated — web_search, image_search, news_search tools registered");
|
|
177
|
+
}
|
|
108
178
|
},
|
|
109
179
|
deactivate(api) {
|
|
110
180
|
api.logger.info("Search plugin deactivating...");
|
package/dist/plugin2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin2.js","names":[],"sources":["../src/tools.ts","../src/plugin.ts"],"sourcesContent":["import type { AgentApiClient } from \"@alfe.ai/agent-api-client\";\n\ninterface PluginApi {\n registerTool(tool: ToolDef): void;\n}\n\ninterface ToolDef {\n name: string;\n description: string;\n label: string;\n parameters: Record<string, unknown>;\n execute: (toolCallId: string, params: Record<string, unknown>) => Promise<unknown>;\n}\n\nexport function registerTools(api: PluginApi, client: AgentApiClient): void {\n // ── Web Search ──────────────────────────────────────\n\n api.registerTool({\n name: \"web_search\",\n label: \"web_search\",\n description: \"Search the web. Returns web pages with titles, URLs, and descriptions.\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query\" },\n count: { type: \"number\", description: \"Number of results to return (1-20)\", default: 10 },\n offset: { type: \"number\", description: \"Pagination offset (0-9)\", default: 0 },\n },\n required: [\"query\"],\n },\n execute: async (_id, params) => {\n return client.searchWeb(params as { query: string; count?: number; offset?: number });\n },\n });\n\n // ── Image Search ────────────────────────────────────\n\n api.registerTool({\n name: \"image_search\",\n label: \"image_search\",\n description: \"Search for images. Returns image URLs, thumbnails, and metadata.\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query\" },\n count: { type: \"number\", description: \"Number of results to return (1-20)\", default: 10 },\n },\n required: [\"query\"],\n },\n execute: async (_id, params) => {\n return client.searchImages(params as { query: string; count?: number });\n },\n });\n\n // ── News Search ─────────────────────────────────────\n\n api.registerTool({\n name: \"news_search\",\n label: \"news_search\",\n description: \"Search for news articles. Returns articles with titles, sources, and publication dates.\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query\" },\n count: { type: \"number\", description: \"Number of results to return (1-20)\", default: 10 },\n offset: { type: \"number\", description: \"Pagination offset (0-9)\", default: 0 },\n },\n required: [\"query\"],\n },\n execute: async (_id, params) => {\n return client.searchNews(params as { query: string; count?: number; freshness?: string });\n },\n });\n}\n","import { registerTools } from \"./tools.js\";\nimport { resolveConfig } from \"@alfe.ai/config\";\nimport { AgentApiClient } from \"@alfe.ai/agent-api-client\";\nimport { createRequire } from 'node:module';\nconst require = createRequire(import.meta.url);\nconst pkg = require('../package.json') as { version: string };\n\ninterface PluginApi {\n logger: { info: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; error: (...args: unknown[]) => void; debug: (...args: unknown[]) => void };\n registerTool(tool: unknown): void;\n}\n\nconst plugin = {\n id: \"@alfe.ai/openclaw-search\",\n name: \"Search\",\n version: pkg.version,\n\n activate(api: PluginApi) {\n const log = api.logger;\n\n log.info(\"Search plugin activating...\");\n\n let client: AgentApiClient;\n try {\n const config = resolveConfig();\n client = new AgentApiClient({ apiUrl: config.apiUrl, apiKey: config.apiKey });\n } catch (err) {\n log.error(`Search plugin: failed to resolve config — ${err instanceof Error ? err.message : String(err)}`);\n return;\n }\n\n // No activation guard: tools must register on EVERY activate — OpenClaw\n // 2026.5+ uses per-session registries, and registration has no side\n // effects worth deduplicating (the client is a stateless HTTP wrapper).\n registerTools(api, client);\n log.info(\"Search plugin activated — web_search, image_search, news_search tools registered\");\n },\n\n deactivate(api: PluginApi) {\n api.logger.info(\"Search plugin deactivating...\");\n },\n};\n\nexport default plugin;\n"],"mappings":";;;;AAcA,SAAgB,cAAc,KAAgB,QAA8B;AAG1E,KAAI,aAAa;EACf,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY;GACV,MAAM;GACN,YAAY;IACV,OAAO;KAAE,MAAM;KAAU,aAAa;KAAoB;IAC1D,OAAO;KAAE,MAAM;KAAU,aAAa;KAAsC,SAAS;KAAI;IACzF,QAAQ;KAAE,MAAM;KAAU,aAAa;KAA2B,SAAS;KAAG;IAC/E;GACD,UAAU,CAAC,QAAQ;GACpB;EACD,SAAS,OAAO,KAAK,WAAW;AAC9B,UAAO,OAAO,UAAU,OAA6D;;EAExF,CAAC;AAIF,KAAI,aAAa;EACf,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY;GACV,MAAM;GACN,YAAY;IACV,OAAO;KAAE,MAAM;KAAU,aAAa;KAAoB;IAC1D,OAAO;KAAE,MAAM;KAAU,aAAa;KAAsC,SAAS;KAAI;IAC1F;GACD,UAAU,CAAC,QAAQ;GACpB;EACD,SAAS,OAAO,KAAK,WAAW;AAC9B,UAAO,OAAO,aAAa,OAA4C;;EAE1E,CAAC;AAIF,KAAI,aAAa;EACf,MAAM;EACN,OAAO;EACP,aAAa;EACb,YAAY;GACV,MAAM;GACN,YAAY;IACV,OAAO;KAAE,MAAM;KAAU,aAAa;KAAoB;IAC1D,OAAO;KAAE,MAAM;KAAU,aAAa;KAAsC,SAAS;KAAI;IACzF,QAAQ;KAAE,MAAM;KAAU,aAAa;KAA2B,SAAS;KAAG;IAC/E;GACD,UAAU,CAAC,QAAQ;GACpB;EACD,SAAS,OAAO,KAAK,WAAW;AAC9B,UAAO,OAAO,WAAW,OAAgE;;EAE5F,CAAC;;;;AC5DJ,MAAM,SAAS;CACb,IAAI;CACJ,MAAM;CACN,SAXc,cAAc,OAAO,KAAK,IAAI,CAC1B,kBAAkB,CAUvB;CAEb,SAAS,KAAgB;EACvB,MAAM,MAAM,IAAI;AAEhB,MAAI,KAAK,8BAA8B;EAEvC,IAAI;AACJ,MAAI;GACF,MAAM,SAAS,eAAe;AAC9B,YAAS,IAAI,eAAe;IAAE,QAAQ,OAAO;IAAQ,QAAQ,OAAO;IAAQ,CAAC;WACtE,KAAK;AACZ,OAAI,MAAM,6CAA6C,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAAG;AAC1G;;AAMF,gBAAc,KAAK,OAAO;AAC1B,MAAI,KAAK,mFAAmF;;CAG9F,WAAW,KAAgB;AACzB,MAAI,OAAO,KAAK,gCAAgC;;CAEnD"}
|
|
1
|
+
{"version":3,"file":"plugin2.js","names":[],"sources":["../src/tools.ts","../src/provider.ts","../src/plugin.ts"],"sourcesContent":["import type { AgentApiClient } from \"@alfe.ai/agent-api-client\";\n\ninterface PluginApi {\n registerTool(tool: ToolDef): void;\n}\n\ninterface ToolDef {\n name: string;\n description: string;\n label: string;\n parameters: Record<string, unknown>;\n execute: (toolCallId: string, params: Record<string, unknown>) => Promise<unknown>;\n}\n\nexport function registerTools(api: PluginApi, client: AgentApiClient): void {\n registerWebSearchTool(api, client);\n registerAuxiliaryTools(api, client);\n}\n\n// Legacy path (OpenClaw < 2026.6): register web_search as a plugin tool.\n// On 2026.6+ the builtin web_search tool owns the name and this registration\n// would be dropped as a conflict — use createAlfeWebSearchProvider instead.\nfunction registerWebSearchTool(api: PluginApi, client: AgentApiClient): void {\n api.registerTool({\n name: \"web_search\",\n label: \"web_search\",\n description: \"Search the web. Returns web pages with titles, URLs, and descriptions.\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query\" },\n count: { type: \"number\", description: \"Number of results to return (1-20)\", default: 10 },\n offset: { type: \"number\", description: \"Pagination offset (0-9)\", default: 0 },\n },\n required: [\"query\"],\n },\n execute: async (_id, params) => {\n return client.searchWeb(params as { query: string; count?: number; offset?: number });\n },\n });\n}\n\n// image_search / news_search have no builtin counterparts, so they register\n// as plugin tools on every OpenClaw version.\nexport function registerAuxiliaryTools(api: PluginApi, client: AgentApiClient): void {\n // ── Image Search ────────────────────────────────────\n\n api.registerTool({\n name: \"image_search\",\n label: \"image_search\",\n description: \"Search for images. Returns image URLs, thumbnails, and metadata.\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query\" },\n count: { type: \"number\", description: \"Number of results to return (1-20)\", default: 10 },\n },\n required: [\"query\"],\n },\n execute: async (_id, params) => {\n return client.searchImages(params as { query: string; count?: number });\n },\n });\n\n // ── News Search ─────────────────────────────────────\n\n api.registerTool({\n name: \"news_search\",\n label: \"news_search\",\n description: \"Search for news articles. Returns articles with titles, sources, and publication dates.\",\n parameters: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query\" },\n count: { type: \"number\", description: \"Number of results to return (1-20)\", default: 10 },\n offset: { type: \"number\", description: \"Pagination offset (0-9)\", default: 0 },\n },\n required: [\"query\"],\n },\n execute: async (_id, params) => {\n return client.searchNews(params as { query: string; count?: number; freshness?: string });\n },\n });\n}\n","import type { AgentApiClient } from \"@alfe.ai/agent-api-client\";\n\n// Matches OpenClaw's WebSearchProviderPlugin contract (2026.6+). Only the\n// fields the runtime actually reads are typed here; the object is passed\n// through api.registerWebSearchProvider as-is.\nexport interface AlfeWebSearchProvider {\n id: string;\n label: string;\n hint: string;\n requiresCredential: boolean;\n credentialLabel: string;\n envVars: string[];\n placeholder: string;\n signupUrl: string;\n autoDetectOrder: number;\n credentialPath: string;\n getCredentialValue: (searchConfig?: Record<string, unknown>) => unknown;\n setCredentialValue: (searchConfigTarget: Record<string, unknown>, value: unknown) => void;\n getConfiguredCredentialValue: (config?: unknown) => unknown;\n createTool: (ctx: unknown) => {\n description: string;\n parameters: Record<string, unknown>;\n execute: (args: Record<string, unknown>) => Promise<Record<string, unknown>>;\n };\n}\n\nconst WEB_SEARCH_SCHEMA = {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query\" },\n count: { type: \"number\", description: \"Number of results to return (1-20)\", default: 10 },\n offset: { type: \"number\", description: \"Pagination offset (0-9)\", default: 0 },\n },\n required: [\"query\"],\n} as const;\n\n/**\n * Web-search provider that plugs into OpenClaw's builtin `web_search` tool\n * (OpenClaw 2026.6+ ships one; registering a plugin tool with the same name\n * is dropped as a name conflict). Routes through the Alfe search service.\n *\n * The Alfe API key doubles as the provider credential: OpenClaw only\n * auto-selects providers with a credential signal, and the key is always\n * present on a configured agent, so the provider self-selects without any\n * openclaw.json changes. An explicit user `provider` selection still wins.\n */\nexport function createAlfeWebSearchProvider(\n client: AgentApiClient,\n apiKey: string,\n): AlfeWebSearchProvider {\n return {\n id: \"alfe\",\n label: \"Alfe Search\",\n hint: \"Managed web search routed through the Alfe platform\",\n requiresCredential: true,\n credentialLabel: \"Alfe API Key\",\n envVars: [\"ALFE_API_KEY\"],\n placeholder: \"alfe_...\",\n signupUrl: \"https://alfe.ai\",\n autoDetectOrder: 10,\n credentialPath: \"plugins.entries.@alfe.ai/openclaw-search.config.apiKey\",\n getCredentialValue: () => apiKey,\n // The credential is sourced from ~/.alfe/config.toml, never written back.\n setCredentialValue: () => undefined,\n getConfiguredCredentialValue: () => apiKey,\n createTool: () => ({\n description: \"Search the web. Returns web pages with titles, URLs, and descriptions.\",\n parameters: WEB_SEARCH_SCHEMA as unknown as Record<string, unknown>,\n execute: async (args) => {\n const result = await client.searchWeb(\n args as { query: string; count?: number; offset?: number },\n );\n return result as Record<string, unknown>;\n },\n }),\n };\n}\n","import { registerAuxiliaryTools, registerTools } from \"./tools.js\";\nimport { createAlfeWebSearchProvider } from \"./provider.js\";\nimport { resolveConfig } from \"@alfe.ai/config\";\nimport { AgentApiClient } from \"@alfe.ai/agent-api-client\";\nimport { createRequire } from 'node:module';\nconst require = createRequire(import.meta.url);\nconst pkg = require('../package.json') as { version: string };\n\ninterface PluginApi {\n logger: { info: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; error: (...args: unknown[]) => void; debug: (...args: unknown[]) => void };\n registerTool(tool: unknown): void;\n registerWebSearchProvider?(provider: unknown): void;\n}\n\nconst plugin = {\n id: \"@alfe.ai/openclaw-search\",\n name: \"Search\",\n version: pkg.version,\n\n activate(api: PluginApi) {\n const log = api.logger;\n\n log.info(\"Search plugin activating...\");\n\n let client: AgentApiClient;\n let apiKey: string;\n try {\n const config = resolveConfig();\n apiKey = config.apiKey;\n client = new AgentApiClient({ apiUrl: config.apiUrl, apiKey: config.apiKey });\n } catch (err) {\n log.error(`Search plugin: failed to resolve config — ${err instanceof Error ? err.message : String(err)}`);\n return;\n }\n\n // No activation guard: tools must register on EVERY activate — OpenClaw\n // 2026.5+ uses per-session registries, and registration has no side\n // effects worth deduplicating (the client is a stateless HTTP wrapper).\n if (typeof api.registerWebSearchProvider === \"function\") {\n // OpenClaw 2026.6+ ships a builtin web_search tool that wins tool-name\n // conflicts, silently dropping a plugin tool named web_search. Plug in\n // as a provider of the builtin instead. Tools first: they must survive\n // even if provider registration ever starts throwing.\n registerAuxiliaryTools(api, client);\n api.registerWebSearchProvider(createAlfeWebSearchProvider(client, apiKey));\n log.info(\"Search plugin activated — alfe web_search provider registered; image_search, news_search tools registered\");\n } else {\n registerTools(api, client);\n log.info(\"Search plugin activated — web_search, image_search, news_search tools registered\");\n }\n },\n\n deactivate(api: PluginApi) {\n api.logger.info(\"Search plugin deactivating...\");\n },\n};\n\nexport default plugin;\n"],"mappings":"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"}
|
package/openclaw.plugin.json
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
"entry": "./dist/plugin.js",
|
|
6
6
|
"activation": { "onStartup": false },
|
|
7
7
|
"contracts": {
|
|
8
|
-
"tools": ["web_search", "image_search", "news_search"]
|
|
8
|
+
"tools": ["web_search", "image_search", "news_search"],
|
|
9
|
+
"webSearchProviders": ["alfe"]
|
|
9
10
|
},
|
|
10
11
|
"configSchema": {
|
|
11
12
|
"type": "object",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfe.ai/openclaw-search",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"description": "OpenClaw search plugin — web, image, and news search",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/plugin.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"openclaw.plugin.json"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@alfe.ai/agent-api-client": "0.
|
|
30
|
+
"@alfe.ai/agent-api-client": "0.6.0",
|
|
31
31
|
"@alfe.ai/config": "0.3.0"
|
|
32
32
|
},
|
|
33
33
|
"license": "UNLICENSED",
|