signalwire-agents 0.1.0
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/CLAUDE.md +112 -0
- package/README.md +417 -0
- package/dist/AgentBase.d.ts +481 -0
- package/dist/AgentBase.js +1155 -0
- package/dist/AgentBase.js.map +1 -0
- package/dist/AgentServer.d.ts +60 -0
- package/dist/AgentServer.js +128 -0
- package/dist/AgentServer.js.map +1 -0
- package/dist/AuthHandler.d.ts +56 -0
- package/dist/AuthHandler.js +119 -0
- package/dist/AuthHandler.js.map +1 -0
- package/dist/ConfigLoader.d.ts +68 -0
- package/dist/ConfigLoader.js +150 -0
- package/dist/ConfigLoader.js.map +1 -0
- package/dist/ContextBuilder.d.ts +431 -0
- package/dist/ContextBuilder.js +751 -0
- package/dist/ContextBuilder.js.map +1 -0
- package/dist/DataMap.d.ts +179 -0
- package/dist/DataMap.js +321 -0
- package/dist/DataMap.js.map +1 -0
- package/dist/Logger.d.ts +91 -0
- package/dist/Logger.js +191 -0
- package/dist/Logger.js.map +1 -0
- package/dist/PomBuilder.d.ts +144 -0
- package/dist/PomBuilder.js +249 -0
- package/dist/PomBuilder.js.map +1 -0
- package/dist/PromptManager.d.ts +85 -0
- package/dist/PromptManager.js +108 -0
- package/dist/PromptManager.js.map +1 -0
- package/dist/SchemaUtils.d.ts +42 -0
- package/dist/SchemaUtils.js +148 -0
- package/dist/SchemaUtils.js.map +1 -0
- package/dist/ServerlessAdapter.d.ts +100 -0
- package/dist/ServerlessAdapter.js +166 -0
- package/dist/ServerlessAdapter.js.map +1 -0
- package/dist/SessionManager.d.ts +86 -0
- package/dist/SessionManager.js +155 -0
- package/dist/SessionManager.js.map +1 -0
- package/dist/SslConfig.d.ts +77 -0
- package/dist/SslConfig.js +100 -0
- package/dist/SslConfig.js.map +1 -0
- package/dist/SwaigFunction.d.ts +88 -0
- package/dist/SwaigFunction.js +125 -0
- package/dist/SwaigFunction.js.map +1 -0
- package/dist/SwaigFunctionResult.d.ts +442 -0
- package/dist/SwaigFunctionResult.js +735 -0
- package/dist/SwaigFunctionResult.js.map +1 -0
- package/dist/SwmlBuilder.d.ts +37 -0
- package/dist/SwmlBuilder.js +55 -0
- package/dist/SwmlBuilder.js.map +1 -0
- package/dist/cli/agent-loader.d.ts +22 -0
- package/dist/cli/agent-loader.js +106 -0
- package/dist/cli/agent-loader.js.map +1 -0
- package/dist/cli/mock-data.d.ts +37 -0
- package/dist/cli/mock-data.js +79 -0
- package/dist/cli/mock-data.js.map +1 -0
- package/dist/cli/swaig-test.d.ts +32 -0
- package/dist/cli/swaig-test.js +405 -0
- package/dist/cli/swaig-test.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/prefabs/ConciergeAgent.d.ts +64 -0
- package/dist/prefabs/ConciergeAgent.js +188 -0
- package/dist/prefabs/ConciergeAgent.js.map +1 -0
- package/dist/prefabs/FAQBotAgent.d.ts +68 -0
- package/dist/prefabs/FAQBotAgent.js +206 -0
- package/dist/prefabs/FAQBotAgent.js.map +1 -0
- package/dist/prefabs/InfoGathererAgent.d.ts +73 -0
- package/dist/prefabs/InfoGathererAgent.js +202 -0
- package/dist/prefabs/InfoGathererAgent.js.map +1 -0
- package/dist/prefabs/ReceptionistAgent.d.ts +65 -0
- package/dist/prefabs/ReceptionistAgent.js +205 -0
- package/dist/prefabs/ReceptionistAgent.js.map +1 -0
- package/dist/prefabs/SurveyAgent.d.ts +84 -0
- package/dist/prefabs/SurveyAgent.js +324 -0
- package/dist/prefabs/SurveyAgent.js.map +1 -0
- package/dist/prefabs/index.d.ts +13 -0
- package/dist/prefabs/index.js +14 -0
- package/dist/prefabs/index.js.map +1 -0
- package/dist/skills/SkillBase.d.ts +134 -0
- package/dist/skills/SkillBase.js +105 -0
- package/dist/skills/SkillBase.js.map +1 -0
- package/dist/skills/SkillManager.d.ts +83 -0
- package/dist/skills/SkillManager.js +159 -0
- package/dist/skills/SkillManager.js.map +1 -0
- package/dist/skills/SkillRegistry.d.ts +105 -0
- package/dist/skills/SkillRegistry.js +195 -0
- package/dist/skills/SkillRegistry.js.map +1 -0
- package/dist/skills/builtin/api_ninjas_trivia.d.ts +35 -0
- package/dist/skills/builtin/api_ninjas_trivia.js +161 -0
- package/dist/skills/builtin/api_ninjas_trivia.js.map +1 -0
- package/dist/skills/builtin/claude_skills.d.ts +34 -0
- package/dist/skills/builtin/claude_skills.js +156 -0
- package/dist/skills/builtin/claude_skills.js.map +1 -0
- package/dist/skills/builtin/custom_skills.d.ts +59 -0
- package/dist/skills/builtin/custom_skills.js +231 -0
- package/dist/skills/builtin/custom_skills.js.map +1 -0
- package/dist/skills/builtin/datasphere.d.ts +34 -0
- package/dist/skills/builtin/datasphere.js +163 -0
- package/dist/skills/builtin/datasphere.js.map +1 -0
- package/dist/skills/builtin/datasphere_serverless.d.ts +54 -0
- package/dist/skills/builtin/datasphere_serverless.js +155 -0
- package/dist/skills/builtin/datasphere_serverless.js.map +1 -0
- package/dist/skills/builtin/datetime.d.ts +31 -0
- package/dist/skills/builtin/datetime.js +95 -0
- package/dist/skills/builtin/datetime.js.map +1 -0
- package/dist/skills/builtin/google_maps.d.ts +33 -0
- package/dist/skills/builtin/google_maps.js +233 -0
- package/dist/skills/builtin/google_maps.js.map +1 -0
- package/dist/skills/builtin/index.d.ts +28 -0
- package/dist/skills/builtin/index.js +75 -0
- package/dist/skills/builtin/index.js.map +1 -0
- package/dist/skills/builtin/info_gatherer.d.ts +52 -0
- package/dist/skills/builtin/info_gatherer.js +237 -0
- package/dist/skills/builtin/info_gatherer.js.map +1 -0
- package/dist/skills/builtin/joke.d.ts +32 -0
- package/dist/skills/builtin/joke.js +142 -0
- package/dist/skills/builtin/joke.js.map +1 -0
- package/dist/skills/builtin/math.d.ts +33 -0
- package/dist/skills/builtin/math.js +120 -0
- package/dist/skills/builtin/math.js.map +1 -0
- package/dist/skills/builtin/mcp_gateway.d.ts +35 -0
- package/dist/skills/builtin/mcp_gateway.js +85 -0
- package/dist/skills/builtin/mcp_gateway.js.map +1 -0
- package/dist/skills/builtin/native_vector_search.d.ts +44 -0
- package/dist/skills/builtin/native_vector_search.js +248 -0
- package/dist/skills/builtin/native_vector_search.js.map +1 -0
- package/dist/skills/builtin/play_background_file.d.ts +34 -0
- package/dist/skills/builtin/play_background_file.js +135 -0
- package/dist/skills/builtin/play_background_file.js.map +1 -0
- package/dist/skills/builtin/spider.d.ts +34 -0
- package/dist/skills/builtin/spider.js +164 -0
- package/dist/skills/builtin/spider.js.map +1 -0
- package/dist/skills/builtin/swml_transfer.d.ts +44 -0
- package/dist/skills/builtin/swml_transfer.js +204 -0
- package/dist/skills/builtin/swml_transfer.js.map +1 -0
- package/dist/skills/builtin/weather_api.d.ts +34 -0
- package/dist/skills/builtin/weather_api.js +136 -0
- package/dist/skills/builtin/weather_api.js.map +1 -0
- package/dist/skills/builtin/web_search.d.ts +34 -0
- package/dist/skills/builtin/web_search.js +141 -0
- package/dist/skills/builtin/web_search.js.map +1 -0
- package/dist/skills/builtin/wikipedia_search.d.ts +34 -0
- package/dist/skills/builtin/wikipedia_search.js +166 -0
- package/dist/skills/builtin/wikipedia_search.js.map +1 -0
- package/dist/skills/index.d.ts +11 -0
- package/dist/skills/index.js +10 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/types.d.ts +85 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/docs/agent-guide.md +869 -0
- package/docs/api-reference.md +2419 -0
- package/docs/architecture.md +843 -0
- package/docs/cli-guide.md +579 -0
- package/docs/configuration.md +422 -0
- package/docs/contexts-guide.md +787 -0
- package/docs/datamap-guide.md +1141 -0
- package/docs/prefabs-guide.md +830 -0
- package/docs/security.md +436 -0
- package/docs/serverless-guide.md +513 -0
- package/docs/skills-guide.md +845 -0
- package/docs/swaig-reference.md +1627 -0
- package/examples/call-flow.ts +60 -0
- package/examples/contexts-steps.ts +62 -0
- package/examples/datamap-tools.ts +52 -0
- package/examples/dynamic-config.ts +51 -0
- package/examples/multi-agent.ts +67 -0
- package/examples/pom-prompt.ts +68 -0
- package/examples/simple-agent.ts +33 -0
- package/package.json +35 -0
- package/src/AgentBase.ts +1279 -0
- package/src/AgentServer.ts +149 -0
- package/src/AuthHandler.ts +141 -0
- package/src/ConfigLoader.ts +165 -0
- package/src/ContextBuilder.ts +796 -0
- package/src/DataMap.ts +365 -0
- package/src/Logger.ts +197 -0
- package/src/PomBuilder.ts +298 -0
- package/src/PromptManager.ts +133 -0
- package/src/SchemaUtils.ts +170 -0
- package/src/ServerlessAdapter.ts +218 -0
- package/src/SessionManager.ts +161 -0
- package/src/SslConfig.ts +118 -0
- package/src/SwaigFunction.ts +168 -0
- package/src/SwaigFunctionResult.ts +864 -0
- package/src/SwmlBuilder.ts +62 -0
- package/src/cli/agent-loader.ts +122 -0
- package/src/cli/mock-data.ts +110 -0
- package/src/cli/swaig-test.ts +440 -0
- package/src/index.ts +99 -0
- package/src/prefabs/ConciergeAgent.ts +251 -0
- package/src/prefabs/FAQBotAgent.ts +263 -0
- package/src/prefabs/InfoGathererAgent.ts +276 -0
- package/src/prefabs/ReceptionistAgent.ts +277 -0
- package/src/prefabs/SurveyAgent.ts +413 -0
- package/src/prefabs/index.ts +23 -0
- package/src/skills/SkillBase.ts +184 -0
- package/src/skills/SkillManager.ts +177 -0
- package/src/skills/SkillRegistry.ts +231 -0
- package/src/skills/builtin/api_ninjas_trivia.ts +230 -0
- package/src/skills/builtin/claude_skills.ts +239 -0
- package/src/skills/builtin/custom_skills.ts +326 -0
- package/src/skills/builtin/datasphere.ts +225 -0
- package/src/skills/builtin/datasphere_serverless.ts +194 -0
- package/src/skills/builtin/datetime.ts +115 -0
- package/src/skills/builtin/google_maps.ts +347 -0
- package/src/skills/builtin/index.ts +79 -0
- package/src/skills/builtin/info_gatherer.ts +331 -0
- package/src/skills/builtin/joke.ts +180 -0
- package/src/skills/builtin/math.ts +150 -0
- package/src/skills/builtin/mcp_gateway.ts +99 -0
- package/src/skills/builtin/native_vector_search.ts +327 -0
- package/src/skills/builtin/play_background_file.ts +189 -0
- package/src/skills/builtin/spider.ts +232 -0
- package/src/skills/builtin/swml_transfer.ts +285 -0
- package/src/skills/builtin/weather_api.ts +193 -0
- package/src/skills/builtin/web_search.ts +212 -0
- package/src/skills/builtin/wikipedia_search.ts +248 -0
- package/src/skills/index.ts +12 -0
- package/src/types.ts +99 -0
- package/tests/AgentBase.test.ts +693 -0
- package/tests/AgentServer.test.ts +102 -0
- package/tests/AuthHandler.test.ts +121 -0
- package/tests/ConfigLoader.test.ts +121 -0
- package/tests/DataMap.test.ts +286 -0
- package/tests/Logger.test.ts +218 -0
- package/tests/PomBuilder.test.ts +164 -0
- package/tests/ProxyDetection.test.ts +185 -0
- package/tests/SchemaUtils.test.ts +106 -0
- package/tests/ServerlessAdapter.test.ts +200 -0
- package/tests/SessionManager.test.ts +139 -0
- package/tests/SslConfig.test.ts +97 -0
- package/tests/SwaigFunctionResult.test.ts +298 -0
- package/tests/cli/mock-data.test.ts +94 -0
- package/tests/cli/swaig-test.test.ts +96 -0
- package/tests/prefabs/prefabs.test.ts +854 -0
- package/tests/setup.ts +6 -0
- package/tests/skills/SkillBase.test.ts +118 -0
- package/tests/skills/SkillManager.test.ts +164 -0
- package/tests/skills/SkillRegistry.test.ts +124 -0
- package/tests/skills/builtin.test.ts +924 -0
- package/tsconfig.json +18 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spider Skill - Scrapes webpage content using the Spider API.
|
|
3
|
+
*
|
|
4
|
+
* Tier 3 built-in skill: requires SPIDER_API_KEY environment variable.
|
|
5
|
+
* Uses the Spider API to fetch and extract content from web pages,
|
|
6
|
+
* optionally filtering by CSS selector.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { SkillBase } from '../SkillBase.js';
|
|
10
|
+
import type {
|
|
11
|
+
SkillManifest,
|
|
12
|
+
SkillToolDefinition,
|
|
13
|
+
SkillPromptSection,
|
|
14
|
+
SkillConfig,
|
|
15
|
+
} from '../SkillBase.js';
|
|
16
|
+
import { SwaigFunctionResult } from '../../SwaigFunctionResult.js';
|
|
17
|
+
|
|
18
|
+
/** A single crawl result from the Spider API. */
|
|
19
|
+
interface SpiderResult {
|
|
20
|
+
/** Raw HTML content of the page. */
|
|
21
|
+
content?: string;
|
|
22
|
+
/** Markdown-formatted content. */
|
|
23
|
+
markdown?: string;
|
|
24
|
+
/** Plain text content. */
|
|
25
|
+
text?: string;
|
|
26
|
+
/** Resolved URL of the crawled page. */
|
|
27
|
+
url?: string;
|
|
28
|
+
/** HTTP status code of the crawl. */
|
|
29
|
+
status?: number;
|
|
30
|
+
/** Error message if the crawl failed. */
|
|
31
|
+
error?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Response from the Spider API, which may be an array, single result, or error object. */
|
|
35
|
+
type SpiderResponse = SpiderResult[] | SpiderResult | { error: string; message?: string };
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Scrapes webpage content using the Spider API.
|
|
39
|
+
*
|
|
40
|
+
* Tier 3 built-in skill. Requires the `SPIDER_API_KEY` environment variable.
|
|
41
|
+
* Extracts text, markdown, or HTML from any public URL, with optional CSS
|
|
42
|
+
* selector filtering. Supports `max_content_length` config option.
|
|
43
|
+
*/
|
|
44
|
+
export class SpiderSkill extends SkillBase {
|
|
45
|
+
/**
|
|
46
|
+
* @param config - Optional configuration; supports `max_content_length`.
|
|
47
|
+
*/
|
|
48
|
+
constructor(config?: SkillConfig) {
|
|
49
|
+
super('spider', config);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** @returns Manifest declaring SPIDER_API_KEY as required and config schema for max_content_length. */
|
|
53
|
+
getManifest(): SkillManifest {
|
|
54
|
+
return {
|
|
55
|
+
name: 'spider',
|
|
56
|
+
description:
|
|
57
|
+
'Scrapes webpage content using the Spider API. Extracts text, markdown, or HTML from any public URL.',
|
|
58
|
+
version: '1.0.0',
|
|
59
|
+
author: 'SignalWire',
|
|
60
|
+
tags: ['scraping', 'web', 'spider', 'content', 'extraction', 'external'],
|
|
61
|
+
requiredEnvVars: ['SPIDER_API_KEY'],
|
|
62
|
+
configSchema: {
|
|
63
|
+
max_content_length: {
|
|
64
|
+
type: 'number',
|
|
65
|
+
description:
|
|
66
|
+
'Maximum length of returned content in characters. Defaults to 5000.',
|
|
67
|
+
default: 5000,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** @returns A single `scrape_url` tool that extracts content from a web page. */
|
|
74
|
+
getTools(): SkillToolDefinition[] {
|
|
75
|
+
const maxContentLength = this.getConfig<number>('max_content_length', 5000);
|
|
76
|
+
|
|
77
|
+
return [
|
|
78
|
+
{
|
|
79
|
+
name: 'scrape_url',
|
|
80
|
+
description:
|
|
81
|
+
'Scrape and extract content from a web page URL. Returns the page text or markdown content.',
|
|
82
|
+
parameters: {
|
|
83
|
+
url: {
|
|
84
|
+
type: 'string',
|
|
85
|
+
description: 'The full URL of the web page to scrape (must start with http:// or https://).',
|
|
86
|
+
},
|
|
87
|
+
selector: {
|
|
88
|
+
type: 'string',
|
|
89
|
+
description:
|
|
90
|
+
'Optional CSS selector to extract specific content from the page (e.g., "article", ".main-content", "#body").',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
required: ['url'],
|
|
94
|
+
handler: async (args: Record<string, unknown>) => {
|
|
95
|
+
const url = args.url as string | undefined;
|
|
96
|
+
const selector = args.selector as string | undefined;
|
|
97
|
+
|
|
98
|
+
if (!url || typeof url !== 'string' || url.trim().length === 0) {
|
|
99
|
+
return new SwaigFunctionResult('Please provide a URL to scrape.');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const trimmedUrl = url.trim();
|
|
103
|
+
if (!trimmedUrl.startsWith('http://') && !trimmedUrl.startsWith('https://')) {
|
|
104
|
+
return new SwaigFunctionResult(
|
|
105
|
+
'Invalid URL. Please provide a full URL starting with http:// or https://.',
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const apiKey = process.env['SPIDER_API_KEY'];
|
|
110
|
+
if (!apiKey) {
|
|
111
|
+
return new SwaigFunctionResult(
|
|
112
|
+
'Spider scraping is not configured. The SPIDER_API_KEY environment variable is required.',
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const requestBody: Record<string, unknown> = {
|
|
118
|
+
url: trimmedUrl,
|
|
119
|
+
return_format: 'markdown',
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
if (selector && typeof selector === 'string' && selector.trim().length > 0) {
|
|
123
|
+
requestBody['css_selector'] = selector.trim();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const response = await fetch('https://api.spider.cloud/crawl', {
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: {
|
|
129
|
+
'Content-Type': 'application/json',
|
|
130
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
131
|
+
},
|
|
132
|
+
body: JSON.stringify(requestBody),
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
if (!response.ok) {
|
|
136
|
+
const errorText = await response.text();
|
|
137
|
+
return new SwaigFunctionResult(
|
|
138
|
+
`Spider API returned an error (HTTP ${response.status}): ${errorText.slice(0, 300)}`,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const data = (await response.json()) as SpiderResponse;
|
|
143
|
+
|
|
144
|
+
// Handle error responses
|
|
145
|
+
if (!Array.isArray(data) && 'error' in data) {
|
|
146
|
+
return new SwaigFunctionResult(
|
|
147
|
+
`Spider scraping failed: ${data.error}`,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Extract content from result
|
|
152
|
+
let content = '';
|
|
153
|
+
const result: SpiderResult = Array.isArray(data) ? data[0] : data;
|
|
154
|
+
|
|
155
|
+
if (!result) {
|
|
156
|
+
return new SwaigFunctionResult(
|
|
157
|
+
`No content could be extracted from "${trimmedUrl}".`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (result.error) {
|
|
162
|
+
return new SwaigFunctionResult(
|
|
163
|
+
`Error scraping "${trimmedUrl}": ${result.error}`,
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Prefer markdown > text > content
|
|
168
|
+
content = result.markdown ?? result.text ?? result.content ?? '';
|
|
169
|
+
|
|
170
|
+
if (content.trim().length === 0) {
|
|
171
|
+
return new SwaigFunctionResult(
|
|
172
|
+
`The page at "${trimmedUrl}" returned no extractable content.`,
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Truncate if necessary
|
|
177
|
+
let truncated = false;
|
|
178
|
+
if (content.length > maxContentLength) {
|
|
179
|
+
content = content.slice(0, maxContentLength);
|
|
180
|
+
truncated = true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const parts: string[] = [
|
|
184
|
+
`Content from ${trimmedUrl}:`,
|
|
185
|
+
'',
|
|
186
|
+
content.trim(),
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
if (truncated) {
|
|
190
|
+
parts.push('');
|
|
191
|
+
parts.push(`[Content truncated to ${maxContentLength} characters]`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return new SwaigFunctionResult(parts.join('\n'));
|
|
195
|
+
} catch (err) {
|
|
196
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
197
|
+
return new SwaigFunctionResult(
|
|
198
|
+
`Failed to scrape "${trimmedUrl}": ${message}`,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** @returns Prompt section describing web scraping capabilities and content limits. */
|
|
207
|
+
getPromptSections(): SkillPromptSection[] {
|
|
208
|
+
return [
|
|
209
|
+
{
|
|
210
|
+
title: 'Web Page Scraping',
|
|
211
|
+
body: 'You can scrape and extract content from web pages.',
|
|
212
|
+
bullets: [
|
|
213
|
+
'Use the scrape_url tool to fetch content from any public web page.',
|
|
214
|
+
'Provide a full URL starting with http:// or https://.',
|
|
215
|
+
'Optionally specify a CSS selector to extract specific parts of the page.',
|
|
216
|
+
'Content is returned as markdown text for easy reading.',
|
|
217
|
+
`Content is limited to ${this.getConfig<number>('max_content_length', 5000)} characters.`,
|
|
218
|
+
'Summarize the scraped content for the user rather than reading it verbatim.',
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Factory function for creating SpiderSkill instances.
|
|
227
|
+
* @param config - Optional skill configuration.
|
|
228
|
+
* @returns A new SpiderSkill instance.
|
|
229
|
+
*/
|
|
230
|
+
export function createSkill(config?: SkillConfig): SpiderSkill {
|
|
231
|
+
return new SpiderSkill(config);
|
|
232
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SWML Transfer Skill - Transfers calls using SWML transfer actions.
|
|
3
|
+
*
|
|
4
|
+
* Tier 2 built-in skill: no external dependencies required.
|
|
5
|
+
* Supports both direct destination transfers and named pattern-based transfers.
|
|
6
|
+
* Named patterns allow configuring a set of known transfer destinations
|
|
7
|
+
* that the AI can use by name rather than requiring raw phone numbers or SIP URIs.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { SkillBase } from '../SkillBase.js';
|
|
11
|
+
import type {
|
|
12
|
+
SkillManifest,
|
|
13
|
+
SkillToolDefinition,
|
|
14
|
+
SkillPromptSection,
|
|
15
|
+
SkillConfig,
|
|
16
|
+
} from '../SkillBase.js';
|
|
17
|
+
import { SwaigFunctionResult } from '../../SwaigFunctionResult.js';
|
|
18
|
+
|
|
19
|
+
/** A named transfer destination pattern with a friendly name and underlying address. */
|
|
20
|
+
interface TransferPattern {
|
|
21
|
+
/** Friendly name for the destination (used by the AI to refer to it). */
|
|
22
|
+
name: string;
|
|
23
|
+
/** SIP URI, phone number, or agent URL to transfer to. */
|
|
24
|
+
destination: string;
|
|
25
|
+
/** Optional human-readable description of this destination. */
|
|
26
|
+
description?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Transfers calls using SWML transfer actions.
|
|
31
|
+
*
|
|
32
|
+
* Tier 2 built-in skill with no external dependencies. Supports both direct
|
|
33
|
+
* destination transfers and named pattern-based transfers configured via the
|
|
34
|
+
* `patterns` config array. Optionally restricts to named destinations only
|
|
35
|
+
* via `allow_arbitrary`.
|
|
36
|
+
*/
|
|
37
|
+
export class SwmlTransferSkill extends SkillBase {
|
|
38
|
+
/**
|
|
39
|
+
* @param config - Optional configuration; supports `patterns`, `allow_arbitrary`, `default_message`.
|
|
40
|
+
*/
|
|
41
|
+
constructor(config?: SkillConfig) {
|
|
42
|
+
super('swml_transfer', config);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** @returns Manifest with config schema for patterns, allow_arbitrary, and default_message. */
|
|
46
|
+
getManifest(): SkillManifest {
|
|
47
|
+
return {
|
|
48
|
+
name: 'swml_transfer',
|
|
49
|
+
description:
|
|
50
|
+
'Transfers calls using SWML transfer actions. Supports direct destination transfers and named pattern-based routing.',
|
|
51
|
+
version: '1.0.0',
|
|
52
|
+
author: 'SignalWire',
|
|
53
|
+
tags: ['call-control', 'transfer', 'swml', 'routing'],
|
|
54
|
+
configSchema: {
|
|
55
|
+
patterns: {
|
|
56
|
+
type: 'array',
|
|
57
|
+
description:
|
|
58
|
+
'Array of named transfer patterns: { name, destination, description? }. When configured, the AI can transfer to named destinations.',
|
|
59
|
+
items: {
|
|
60
|
+
type: 'object',
|
|
61
|
+
properties: {
|
|
62
|
+
name: { type: 'string', description: 'Friendly name for the destination.' },
|
|
63
|
+
destination: { type: 'string', description: 'SIP URI, phone number, or agent URL.' },
|
|
64
|
+
description: { type: 'string', description: 'Optional description of this destination.' },
|
|
65
|
+
},
|
|
66
|
+
required: ['name', 'destination'],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
allow_arbitrary: {
|
|
70
|
+
type: 'boolean',
|
|
71
|
+
description:
|
|
72
|
+
'Whether to allow transfers to arbitrary destinations not in the patterns list. Defaults to true if no patterns are configured, false if patterns are configured.',
|
|
73
|
+
},
|
|
74
|
+
default_message: {
|
|
75
|
+
type: 'string',
|
|
76
|
+
description:
|
|
77
|
+
'Default message to say before transferring. Defaults to "Transferring your call now.".',
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** @returns A `transfer_call` tool, plus `list_transfer_destinations` when patterns are configured. */
|
|
84
|
+
getTools(): SkillToolDefinition[] {
|
|
85
|
+
const patterns = this.getConfig<TransferPattern[]>('patterns', []);
|
|
86
|
+
const defaultMessage = this.getConfig<string>(
|
|
87
|
+
'default_message',
|
|
88
|
+
'Transferring your call now.',
|
|
89
|
+
);
|
|
90
|
+
const allowArbitrary = this.getConfig<boolean | undefined>(
|
|
91
|
+
'allow_arbitrary',
|
|
92
|
+
undefined,
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// If patterns are defined and allow_arbitrary is not explicitly set, default to false
|
|
96
|
+
const canUseArbitrary =
|
|
97
|
+
allowArbitrary !== undefined
|
|
98
|
+
? allowArbitrary
|
|
99
|
+
: patterns.length === 0;
|
|
100
|
+
|
|
101
|
+
// Build the pattern lookup map
|
|
102
|
+
const patternMap = new Map<string, TransferPattern>();
|
|
103
|
+
for (const pattern of patterns) {
|
|
104
|
+
patternMap.set(pattern.name.toLowerCase(), pattern);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const tools: SkillToolDefinition[] = [
|
|
108
|
+
{
|
|
109
|
+
name: 'transfer_call',
|
|
110
|
+
description: this._buildTransferDescription(patterns, canUseArbitrary),
|
|
111
|
+
parameters: {
|
|
112
|
+
destination: {
|
|
113
|
+
type: 'string',
|
|
114
|
+
description: this._buildDestinationDescription(patterns, canUseArbitrary),
|
|
115
|
+
},
|
|
116
|
+
message: {
|
|
117
|
+
type: 'string',
|
|
118
|
+
description:
|
|
119
|
+
'An optional message to say to the caller before the transfer. If not provided, a default transfer message is used.',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
required: ['destination'],
|
|
123
|
+
handler: (args: Record<string, unknown>) => {
|
|
124
|
+
const destination = args.destination as string | undefined;
|
|
125
|
+
const message = (args.message as string | undefined) ?? defaultMessage;
|
|
126
|
+
|
|
127
|
+
if (
|
|
128
|
+
!destination ||
|
|
129
|
+
typeof destination !== 'string' ||
|
|
130
|
+
destination.trim().length === 0
|
|
131
|
+
) {
|
|
132
|
+
return new SwaigFunctionResult(
|
|
133
|
+
'Please specify a destination for the transfer.',
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const trimmedDest = destination.trim();
|
|
138
|
+
|
|
139
|
+
// Check if this matches a named pattern
|
|
140
|
+
const matchedPattern = patternMap.get(trimmedDest.toLowerCase());
|
|
141
|
+
|
|
142
|
+
if (matchedPattern) {
|
|
143
|
+
const result = new SwaigFunctionResult(message);
|
|
144
|
+
result.swmlTransfer(matchedPattern.destination, message);
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// No matching pattern - check if arbitrary transfers are allowed
|
|
149
|
+
if (!canUseArbitrary) {
|
|
150
|
+
const availableNames = patterns
|
|
151
|
+
.map((p) => `"${p.name}"`)
|
|
152
|
+
.join(', ');
|
|
153
|
+
return new SwaigFunctionResult(
|
|
154
|
+
`Unknown transfer destination "${trimmedDest}". Available destinations: ${availableNames}.`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Arbitrary transfer
|
|
159
|
+
const result = new SwaigFunctionResult(message);
|
|
160
|
+
result.swmlTransfer(trimmedDest, message);
|
|
161
|
+
return result;
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
// Add a list_destinations tool if patterns are configured
|
|
167
|
+
if (patterns.length > 0) {
|
|
168
|
+
tools.push({
|
|
169
|
+
name: 'list_transfer_destinations',
|
|
170
|
+
description:
|
|
171
|
+
'List all available named transfer destinations that calls can be routed to.',
|
|
172
|
+
parameters: {},
|
|
173
|
+
handler: () => {
|
|
174
|
+
const lines = patterns.map((p) => {
|
|
175
|
+
const desc = p.description ? ` - ${p.description}` : '';
|
|
176
|
+
return `${p.name}${desc}`;
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
return new SwaigFunctionResult(
|
|
180
|
+
`Available transfer destinations:\n${lines.join('\n')}`,
|
|
181
|
+
);
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return tools;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** @returns Prompt section describing call transfer capabilities and available destinations. */
|
|
190
|
+
getPromptSections(): SkillPromptSection[] {
|
|
191
|
+
const patterns = this.getConfig<TransferPattern[]>('patterns', []);
|
|
192
|
+
const allowArbitrary = this.getConfig<boolean | undefined>(
|
|
193
|
+
'allow_arbitrary',
|
|
194
|
+
undefined,
|
|
195
|
+
);
|
|
196
|
+
const canUseArbitrary =
|
|
197
|
+
allowArbitrary !== undefined
|
|
198
|
+
? allowArbitrary
|
|
199
|
+
: patterns.length === 0;
|
|
200
|
+
|
|
201
|
+
const bullets: string[] = [
|
|
202
|
+
'Use the transfer_call tool to transfer the current call to another destination.',
|
|
203
|
+
'You can optionally provide a message to say to the caller before the transfer.',
|
|
204
|
+
];
|
|
205
|
+
|
|
206
|
+
if (patterns.length > 0) {
|
|
207
|
+
const patternNames = patterns.map((p) => `"${p.name}"`).join(', ');
|
|
208
|
+
bullets.push(
|
|
209
|
+
`Named transfer destinations are available: ${patternNames}. Use these names as the destination.`,
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
for (const pattern of patterns) {
|
|
213
|
+
if (pattern.description) {
|
|
214
|
+
bullets.push(`${pattern.name}: ${pattern.description}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (canUseArbitrary) {
|
|
219
|
+
bullets.push(
|
|
220
|
+
'You can also transfer to arbitrary phone numbers or SIP URIs.',
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
bullets.push(
|
|
225
|
+
'Use list_transfer_destinations to see all available named destinations.',
|
|
226
|
+
);
|
|
227
|
+
} else {
|
|
228
|
+
bullets.push(
|
|
229
|
+
'Provide a phone number, SIP URI, or agent URL as the transfer destination.',
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return [
|
|
234
|
+
{
|
|
235
|
+
title: 'Call Transfer',
|
|
236
|
+
body: 'You can transfer the current call to another destination.',
|
|
237
|
+
bullets,
|
|
238
|
+
},
|
|
239
|
+
];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Build the tool description based on available patterns.
|
|
244
|
+
*/
|
|
245
|
+
private _buildTransferDescription(
|
|
246
|
+
patterns: TransferPattern[],
|
|
247
|
+
canUseArbitrary: boolean,
|
|
248
|
+
): string {
|
|
249
|
+
if (patterns.length === 0) {
|
|
250
|
+
return 'Transfer the current call to a specified destination (phone number, SIP URI, or agent URL).';
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const names = patterns.map((p) => `"${p.name}"`).join(', ');
|
|
254
|
+
const base = `Transfer the current call. Named destinations: ${names}.`;
|
|
255
|
+
return canUseArbitrary
|
|
256
|
+
? `${base} You may also use arbitrary phone numbers or SIP URIs.`
|
|
257
|
+
: base;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Build the destination parameter description based on available patterns.
|
|
262
|
+
*/
|
|
263
|
+
private _buildDestinationDescription(
|
|
264
|
+
patterns: TransferPattern[],
|
|
265
|
+
canUseArbitrary: boolean,
|
|
266
|
+
): string {
|
|
267
|
+
if (patterns.length === 0) {
|
|
268
|
+
return 'The transfer destination: a phone number (e.g., +15551234567), SIP URI, or agent URL.';
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const names = patterns.map((p) => `"${p.name}"`).join(', ');
|
|
272
|
+
return canUseArbitrary
|
|
273
|
+
? `A named destination (${names}) or an arbitrary phone number / SIP URI.`
|
|
274
|
+
: `One of the named destinations: ${names}.`;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Factory function for creating SwmlTransferSkill instances.
|
|
280
|
+
* @param config - Optional skill configuration.
|
|
281
|
+
* @returns A new SwmlTransferSkill instance.
|
|
282
|
+
*/
|
|
283
|
+
export function createSkill(config?: SkillConfig): SwmlTransferSkill {
|
|
284
|
+
return new SwmlTransferSkill(config);
|
|
285
|
+
}
|