@troykelly/openclaw-projects 0.0.1
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/LICENSE +21 -0
- package/README.md +389 -0
- package/dist/api-client.d.ts +81 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +216 -0
- package/dist/api-client.js.map +1 -0
- package/dist/cli.d.ts +112 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +233 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +324 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +287 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +87 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +144 -0
- package/dist/context.js.map +1 -0
- package/dist/gateway/rpc-methods.d.ts +93 -0
- package/dist/gateway/rpc-methods.d.ts.map +1 -0
- package/dist/gateway/rpc-methods.js +145 -0
- package/dist/gateway/rpc-methods.js.map +1 -0
- package/dist/hooks.d.ts +86 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +314 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +221 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +22 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +78 -0
- package/dist/logger.js.map +1 -0
- package/dist/register-openclaw.d.ts +43 -0
- package/dist/register-openclaw.d.ts.map +1 -0
- package/dist/register-openclaw.js +1838 -0
- package/dist/register-openclaw.js.map +1 -0
- package/dist/secrets.d.ts +56 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +161 -0
- package/dist/secrets.js.map +1 -0
- package/dist/services/notification-service.d.ts +60 -0
- package/dist/services/notification-service.d.ts.map +1 -0
- package/dist/services/notification-service.js +145 -0
- package/dist/services/notification-service.js.map +1 -0
- package/dist/tools/contacts.d.ts +139 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +333 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/email-send.d.ts +71 -0
- package/dist/tools/email-send.d.ts.map +1 -0
- package/dist/tools/email-send.js +132 -0
- package/dist/tools/email-send.js.map +1 -0
- package/dist/tools/file-share.d.ts +64 -0
- package/dist/tools/file-share.d.ts.map +1 -0
- package/dist/tools/file-share.js +133 -0
- package/dist/tools/file-share.js.map +1 -0
- package/dist/tools/index.d.ts +22 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +33 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/memory-forget.d.ts +69 -0
- package/dist/tools/memory-forget.d.ts.map +1 -0
- package/dist/tools/memory-forget.js +224 -0
- package/dist/tools/memory-forget.js.map +1 -0
- package/dist/tools/memory-recall.d.ts +82 -0
- package/dist/tools/memory-recall.d.ts.map +1 -0
- package/dist/tools/memory-recall.js +161 -0
- package/dist/tools/memory-recall.js.map +1 -0
- package/dist/tools/memory-store.d.ts +80 -0
- package/dist/tools/memory-store.d.ts.map +1 -0
- package/dist/tools/memory-store.js +172 -0
- package/dist/tools/memory-store.js.map +1 -0
- package/dist/tools/message-search.d.ts +85 -0
- package/dist/tools/message-search.d.ts.map +1 -0
- package/dist/tools/message-search.js +137 -0
- package/dist/tools/message-search.js.map +1 -0
- package/dist/tools/notebooks.d.ts +155 -0
- package/dist/tools/notebooks.d.ts.map +1 -0
- package/dist/tools/notebooks.js +287 -0
- package/dist/tools/notebooks.js.map +1 -0
- package/dist/tools/notes.d.ts +272 -0
- package/dist/tools/notes.d.ts.map +1 -0
- package/dist/tools/notes.js +530 -0
- package/dist/tools/notes.js.map +1 -0
- package/dist/tools/projects.d.ts +139 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +280 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/relationships.d.ts +133 -0
- package/dist/tools/relationships.d.ts.map +1 -0
- package/dist/tools/relationships.js +281 -0
- package/dist/tools/relationships.js.map +1 -0
- package/dist/tools/sms-send.d.ts +62 -0
- package/dist/tools/sms-send.d.ts.map +1 -0
- package/dist/tools/sms-send.js +121 -0
- package/dist/tools/sms-send.js.map +1 -0
- package/dist/tools/threads.d.ts +127 -0
- package/dist/tools/threads.d.ts.map +1 -0
- package/dist/tools/threads.js +202 -0
- package/dist/tools/threads.js.map +1 -0
- package/dist/tools/todos.d.ts +142 -0
- package/dist/tools/todos.d.ts.map +1 -0
- package/dist/tools/todos.js +308 -0
- package/dist/tools/todos.js.map +1 -0
- package/dist/types/openclaw-api.d.ts +215 -0
- package/dist/types/openclaw-api.d.ts.map +1 -0
- package/dist/types/openclaw-api.js +10 -0
- package/dist/types/openclaw-api.js.map +1 -0
- package/dist/utils/zod-to-json-schema.d.ts +19 -0
- package/dist/utils/zod-to-json-schema.d.ts.map +1 -0
- package/dist/utils/zod-to-json-schema.js +132 -0
- package/dist/utils/zod-to-json-schema.js.map +1 -0
- package/openclaw.plugin.json +229 -0
- package/package.json +69 -0
- package/skills/contact-lookup/SKILL.md +30 -0
- package/skills/daily-summary/SKILL.md +23 -0
- package/skills/project-status/SKILL.md +33 -0
- package/skills/send-reminder/SKILL.md +42 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relationship management tools implementation.
|
|
3
|
+
* Provides relationship_set and relationship_query tools for OpenClaw agents.
|
|
4
|
+
* Part of Epic #486, Issue #494
|
|
5
|
+
*
|
|
6
|
+
* These tools give agents a simple interface to manage the relationship graph
|
|
7
|
+
* without needing to understand types, directionality, or inverses.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
// ==================== Shared utilities ====================
|
|
11
|
+
/**
|
|
12
|
+
* Strip HTML tags from a string.
|
|
13
|
+
* Also removes content inside script and style tags for security.
|
|
14
|
+
*/
|
|
15
|
+
function stripHtml(text) {
|
|
16
|
+
return text
|
|
17
|
+
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
|
|
18
|
+
.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, '')
|
|
19
|
+
.replace(/<[^>]*>/g, '')
|
|
20
|
+
.trim();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Sanitize text input to remove control characters.
|
|
24
|
+
*/
|
|
25
|
+
function sanitizeText(text) {
|
|
26
|
+
const sanitized = text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '');
|
|
27
|
+
return sanitized.trim();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create a sanitized error message that doesn't expose internal details.
|
|
31
|
+
*/
|
|
32
|
+
function sanitizeErrorMessage(error) {
|
|
33
|
+
if (error instanceof Error) {
|
|
34
|
+
const message = error.message
|
|
35
|
+
.replace(/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g, '[host]')
|
|
36
|
+
.replace(/:\d{2,5}\b/g, '')
|
|
37
|
+
.replace(/\b(?:localhost|internal[-\w]*)\b/gi, '[internal]');
|
|
38
|
+
if (message.includes('[internal]') || message.includes('[host]')) {
|
|
39
|
+
return 'Operation failed. Please try again.';
|
|
40
|
+
}
|
|
41
|
+
return message;
|
|
42
|
+
}
|
|
43
|
+
return 'An unexpected error occurred.';
|
|
44
|
+
}
|
|
45
|
+
// ==================== relationship_set ====================
|
|
46
|
+
/** Parameters for relationship_set tool */
|
|
47
|
+
export const RelationshipSetParamsSchema = z.object({
|
|
48
|
+
contact_a: z
|
|
49
|
+
.string()
|
|
50
|
+
.min(1, 'First contact name or ID is required')
|
|
51
|
+
.max(200, 'Contact reference must be 200 characters or less'),
|
|
52
|
+
contact_b: z
|
|
53
|
+
.string()
|
|
54
|
+
.min(1, 'Second contact name or ID is required')
|
|
55
|
+
.max(200, 'Contact reference must be 200 characters or less'),
|
|
56
|
+
relationship: z
|
|
57
|
+
.string()
|
|
58
|
+
.min(1, 'Relationship description is required')
|
|
59
|
+
.max(200, 'Relationship description must be 200 characters or less'),
|
|
60
|
+
notes: z
|
|
61
|
+
.string()
|
|
62
|
+
.max(2000, 'Notes must be 2000 characters or less')
|
|
63
|
+
.optional(),
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Creates the relationship_set tool.
|
|
67
|
+
* Records a relationship between two people, groups, or organisations.
|
|
68
|
+
* The system handles directionality and type matching automatically.
|
|
69
|
+
*/
|
|
70
|
+
export function createRelationshipSetTool(options) {
|
|
71
|
+
const { client, logger, userId } = options;
|
|
72
|
+
return {
|
|
73
|
+
name: 'relationship_set',
|
|
74
|
+
description: "Record a relationship between two people, groups, or organisations. Examples: 'Troy is Alex\\'s partner', 'Sam is a member of The Kelly Household', 'Troy works for Acme Corp'. The system handles directionality and type matching automatically.",
|
|
75
|
+
parameters: RelationshipSetParamsSchema,
|
|
76
|
+
async execute(params) {
|
|
77
|
+
// Validate parameters
|
|
78
|
+
const parseResult = RelationshipSetParamsSchema.safeParse(params);
|
|
79
|
+
if (!parseResult.success) {
|
|
80
|
+
const errorMessage = parseResult.error.errors
|
|
81
|
+
.map((e) => `${e.path.join('.')}: ${e.message}`)
|
|
82
|
+
.join(', ');
|
|
83
|
+
return { success: false, error: errorMessage };
|
|
84
|
+
}
|
|
85
|
+
const { contact_a, contact_b, relationship, notes } = parseResult.data;
|
|
86
|
+
// Sanitize inputs
|
|
87
|
+
const sanitizedContactA = stripHtml(sanitizeText(contact_a));
|
|
88
|
+
const sanitizedContactB = stripHtml(sanitizeText(contact_b));
|
|
89
|
+
const sanitizedRelationship = stripHtml(sanitizeText(relationship));
|
|
90
|
+
const sanitizedNotes = notes ? sanitizeText(notes) : undefined;
|
|
91
|
+
if (sanitizedContactA.length === 0) {
|
|
92
|
+
return { success: false, error: 'First contact reference cannot be empty after sanitization' };
|
|
93
|
+
}
|
|
94
|
+
if (sanitizedContactB.length === 0) {
|
|
95
|
+
return { success: false, error: 'Second contact reference cannot be empty after sanitization' };
|
|
96
|
+
}
|
|
97
|
+
if (sanitizedRelationship.length === 0) {
|
|
98
|
+
return { success: false, error: 'Relationship description cannot be empty after sanitization' };
|
|
99
|
+
}
|
|
100
|
+
// Log without PII
|
|
101
|
+
logger.info('relationship_set invoked', {
|
|
102
|
+
userId,
|
|
103
|
+
contactALength: sanitizedContactA.length,
|
|
104
|
+
contactBLength: sanitizedContactB.length,
|
|
105
|
+
relationshipLength: sanitizedRelationship.length,
|
|
106
|
+
hasNotes: !!sanitizedNotes,
|
|
107
|
+
});
|
|
108
|
+
try {
|
|
109
|
+
const body = {
|
|
110
|
+
contactA: sanitizedContactA,
|
|
111
|
+
contactB: sanitizedContactB,
|
|
112
|
+
relationshipType: sanitizedRelationship,
|
|
113
|
+
};
|
|
114
|
+
if (sanitizedNotes) {
|
|
115
|
+
body.notes = sanitizedNotes;
|
|
116
|
+
}
|
|
117
|
+
const response = await client.post('/api/relationships/set', body, { userId });
|
|
118
|
+
if (!response.success) {
|
|
119
|
+
logger.error('relationship_set API error', {
|
|
120
|
+
userId,
|
|
121
|
+
status: response.error.status,
|
|
122
|
+
code: response.error.code,
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
success: false,
|
|
126
|
+
error: response.error.message || 'Failed to set relationship',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const { relationship: rel, contactA: resolvedA, contactB: resolvedB, relationshipType, created } = response.data;
|
|
130
|
+
const content = created
|
|
131
|
+
? `Recorded: ${resolvedA.displayName} [${relationshipType.label}] ${resolvedB.displayName}`
|
|
132
|
+
: `Relationship already exists: ${resolvedA.displayName} [${relationshipType.label}] ${resolvedB.displayName}`;
|
|
133
|
+
logger.debug('relationship_set completed', {
|
|
134
|
+
userId,
|
|
135
|
+
relationshipId: rel.id,
|
|
136
|
+
created,
|
|
137
|
+
});
|
|
138
|
+
return {
|
|
139
|
+
success: true,
|
|
140
|
+
data: {
|
|
141
|
+
content,
|
|
142
|
+
details: {
|
|
143
|
+
relationshipId: rel.id,
|
|
144
|
+
created,
|
|
145
|
+
contactA: resolvedA,
|
|
146
|
+
contactB: resolvedB,
|
|
147
|
+
relationshipType,
|
|
148
|
+
userId,
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
logger.error('relationship_set failed', {
|
|
155
|
+
userId,
|
|
156
|
+
error: error instanceof Error ? error.message : String(error),
|
|
157
|
+
});
|
|
158
|
+
return { success: false, error: sanitizeErrorMessage(error) };
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
// ==================== relationship_query ====================
|
|
164
|
+
/** Parameters for relationship_query tool */
|
|
165
|
+
export const RelationshipQueryParamsSchema = z.object({
|
|
166
|
+
contact: z
|
|
167
|
+
.string()
|
|
168
|
+
.min(1, 'Contact name or ID is required')
|
|
169
|
+
.max(200, 'Contact reference must be 200 characters or less'),
|
|
170
|
+
type_filter: z
|
|
171
|
+
.string()
|
|
172
|
+
.max(200, 'Type filter must be 200 characters or less')
|
|
173
|
+
.optional(),
|
|
174
|
+
});
|
|
175
|
+
/**
|
|
176
|
+
* Creates the relationship_query tool.
|
|
177
|
+
* Queries a contact's relationships, returning all connections
|
|
178
|
+
* including family, partners, group memberships, and professional links.
|
|
179
|
+
* Handles directional relationships automatically.
|
|
180
|
+
*/
|
|
181
|
+
export function createRelationshipQueryTool(options) {
|
|
182
|
+
const { client, logger, userId } = options;
|
|
183
|
+
return {
|
|
184
|
+
name: 'relationship_query',
|
|
185
|
+
description: "Query a contact's relationships. Returns all relationships including family, partners, group memberships, professional connections, etc. Handles directional relationships automatically.",
|
|
186
|
+
parameters: RelationshipQueryParamsSchema,
|
|
187
|
+
async execute(params) {
|
|
188
|
+
// Validate parameters
|
|
189
|
+
const parseResult = RelationshipQueryParamsSchema.safeParse(params);
|
|
190
|
+
if (!parseResult.success) {
|
|
191
|
+
const errorMessage = parseResult.error.errors
|
|
192
|
+
.map((e) => `${e.path.join('.')}: ${e.message}`)
|
|
193
|
+
.join(', ');
|
|
194
|
+
return { success: false, error: errorMessage };
|
|
195
|
+
}
|
|
196
|
+
const { contact, type_filter } = parseResult.data;
|
|
197
|
+
// Sanitize input
|
|
198
|
+
const sanitizedContact = stripHtml(sanitizeText(contact));
|
|
199
|
+
if (sanitizedContact.length === 0) {
|
|
200
|
+
return { success: false, error: 'Contact reference cannot be empty after sanitization' };
|
|
201
|
+
}
|
|
202
|
+
// Log without PII
|
|
203
|
+
logger.info('relationship_query invoked', {
|
|
204
|
+
userId,
|
|
205
|
+
contactLength: sanitizedContact.length,
|
|
206
|
+
hasTypeFilter: !!type_filter,
|
|
207
|
+
});
|
|
208
|
+
try {
|
|
209
|
+
const queryParams = new URLSearchParams({
|
|
210
|
+
contact: sanitizedContact,
|
|
211
|
+
});
|
|
212
|
+
if (type_filter) {
|
|
213
|
+
queryParams.set('type_filter', type_filter);
|
|
214
|
+
}
|
|
215
|
+
const response = await client.get(`/api/relationships/query?${queryParams.toString()}`, { userId });
|
|
216
|
+
if (!response.success) {
|
|
217
|
+
if (response.error.code === 'NOT_FOUND') {
|
|
218
|
+
return { success: false, error: 'Contact not found.' };
|
|
219
|
+
}
|
|
220
|
+
logger.error('relationship_query API error', {
|
|
221
|
+
userId,
|
|
222
|
+
status: response.error.status,
|
|
223
|
+
code: response.error.code,
|
|
224
|
+
});
|
|
225
|
+
return {
|
|
226
|
+
success: false,
|
|
227
|
+
error: response.error.message || 'Failed to query relationships',
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const { contactId, contactName, relatedContacts } = response.data;
|
|
231
|
+
if (relatedContacts.length === 0) {
|
|
232
|
+
return {
|
|
233
|
+
success: true,
|
|
234
|
+
data: {
|
|
235
|
+
content: `No relationships found for ${contactName}.`,
|
|
236
|
+
details: {
|
|
237
|
+
contactId,
|
|
238
|
+
contactName,
|
|
239
|
+
relatedContacts: [],
|
|
240
|
+
userId,
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
// Format relationships as a readable list
|
|
246
|
+
const lines = [`Relationships for ${contactName}:`];
|
|
247
|
+
for (const rel of relatedContacts) {
|
|
248
|
+
const kindTag = rel.contactKind !== 'person' ? ` [${rel.contactKind}]` : '';
|
|
249
|
+
const notesTag = rel.notes ? ` -- ${rel.notes}` : '';
|
|
250
|
+
lines.push(`- ${rel.relationshipTypeLabel}: ${rel.contactName}${kindTag}${notesTag}`);
|
|
251
|
+
}
|
|
252
|
+
const content = lines.join('\n');
|
|
253
|
+
logger.debug('relationship_query completed', {
|
|
254
|
+
userId,
|
|
255
|
+
contactId,
|
|
256
|
+
relatedCount: relatedContacts.length,
|
|
257
|
+
});
|
|
258
|
+
return {
|
|
259
|
+
success: true,
|
|
260
|
+
data: {
|
|
261
|
+
content,
|
|
262
|
+
details: {
|
|
263
|
+
contactId,
|
|
264
|
+
contactName,
|
|
265
|
+
relatedContacts,
|
|
266
|
+
userId,
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
logger.error('relationship_query failed', {
|
|
273
|
+
userId,
|
|
274
|
+
error: error instanceof Error ? error.message : String(error),
|
|
275
|
+
});
|
|
276
|
+
return { success: false, error: sanitizeErrorMessage(error) };
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=relationships.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relationships.js","sourceRoot":"","sources":["../../src/tools/relationships.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sms_send tool implementation.
|
|
3
|
+
* Sends SMS messages via Twilio.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import type { ApiClient } from '../api-client.js';
|
|
7
|
+
import type { Logger } from '../logger.js';
|
|
8
|
+
import type { PluginConfig } from '../config.js';
|
|
9
|
+
/** Parameters for sms_send tool */
|
|
10
|
+
export declare const SmsSendParamsSchema: z.ZodObject<{
|
|
11
|
+
to: z.ZodString;
|
|
12
|
+
body: z.ZodString;
|
|
13
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
to: string;
|
|
16
|
+
body: string;
|
|
17
|
+
idempotencyKey?: string | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
to: string;
|
|
20
|
+
body: string;
|
|
21
|
+
idempotencyKey?: string | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export type SmsSendParams = z.infer<typeof SmsSendParamsSchema>;
|
|
24
|
+
/** Successful tool result */
|
|
25
|
+
export interface SmsSendSuccess {
|
|
26
|
+
success: true;
|
|
27
|
+
data: {
|
|
28
|
+
content: string;
|
|
29
|
+
details: {
|
|
30
|
+
messageId: string;
|
|
31
|
+
threadId?: string;
|
|
32
|
+
status: string;
|
|
33
|
+
userId: string;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Failed tool result */
|
|
38
|
+
export interface SmsSendFailure {
|
|
39
|
+
success: false;
|
|
40
|
+
error: string;
|
|
41
|
+
}
|
|
42
|
+
/** Tool result type */
|
|
43
|
+
export type SmsSendResult = SmsSendSuccess | SmsSendFailure;
|
|
44
|
+
/** Tool configuration */
|
|
45
|
+
export interface SmsSendToolOptions {
|
|
46
|
+
client: ApiClient;
|
|
47
|
+
logger: Logger;
|
|
48
|
+
config: PluginConfig;
|
|
49
|
+
userId: string;
|
|
50
|
+
}
|
|
51
|
+
/** Tool definition */
|
|
52
|
+
export interface SmsSendTool {
|
|
53
|
+
name: string;
|
|
54
|
+
description: string;
|
|
55
|
+
parameters: typeof SmsSendParamsSchema;
|
|
56
|
+
execute: (params: SmsSendParams) => Promise<SmsSendResult>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Creates the sms_send tool.
|
|
60
|
+
*/
|
|
61
|
+
export declare function createSmsSendTool(options: SmsSendToolOptions): SmsSendTool;
|
|
62
|
+
//# sourceMappingURL=sms-send.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sms-send.d.ts","sourceRoot":"","sources":["../../src/tools/sms-send.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAQhD,mCAAmC;AACnC,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAS9B,CAAA;AACF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAS/D,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,IAAI,CAAA;IACb,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE;YACP,SAAS,EAAE,MAAM,CAAA;YACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;YACjB,MAAM,EAAE,MAAM,CAAA;YACd,MAAM,EAAE,MAAM,CAAA;SACf,CAAA;KACF,CAAA;CACF;AAED,yBAAyB;AACzB,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,uBAAuB;AACvB,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,cAAc,CAAA;AAE3D,yBAAyB;AACzB,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,SAAS,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,sBAAsB;AACtB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,mBAAmB,CAAA;IACtC,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,aAAa,CAAC,CAAA;CAC3D;AAqBD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CA8F1E"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sms_send tool implementation.
|
|
3
|
+
* Sends SMS messages via Twilio.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
/** E.164 phone number regex */
|
|
7
|
+
const E164_REGEX = /^\+[1-9]\d{1,14}$/;
|
|
8
|
+
/** Maximum SMS body length (Twilio standard) */
|
|
9
|
+
const MAX_BODY_LENGTH = 1600;
|
|
10
|
+
/** Parameters for sms_send tool */
|
|
11
|
+
export const SmsSendParamsSchema = z.object({
|
|
12
|
+
to: z
|
|
13
|
+
.string()
|
|
14
|
+
.regex(E164_REGEX, 'Phone number must be in E.164 format (e.g., +15551234567)'),
|
|
15
|
+
body: z
|
|
16
|
+
.string()
|
|
17
|
+
.min(1, 'Message body cannot be empty')
|
|
18
|
+
.max(MAX_BODY_LENGTH, `Message body must be ${MAX_BODY_LENGTH} characters or less`),
|
|
19
|
+
idempotencyKey: z.string().optional(),
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Sanitize phone numbers from error messages for privacy.
|
|
23
|
+
*/
|
|
24
|
+
function sanitizeErrorMessage(error) {
|
|
25
|
+
if (error instanceof Error) {
|
|
26
|
+
// Remove phone numbers from error messages
|
|
27
|
+
const sanitized = error.message.replace(/\+\d{1,15}/g, '[phone]');
|
|
28
|
+
return sanitized;
|
|
29
|
+
}
|
|
30
|
+
return 'An unexpected error occurred while sending SMS.';
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Check if Twilio is configured.
|
|
34
|
+
*/
|
|
35
|
+
function isTwilioConfigured(config) {
|
|
36
|
+
return !!(config.twilioAccountSid && config.twilioAuthToken && config.twilioPhoneNumber);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Creates the sms_send tool.
|
|
40
|
+
*/
|
|
41
|
+
export function createSmsSendTool(options) {
|
|
42
|
+
const { client, logger, config, userId } = options;
|
|
43
|
+
return {
|
|
44
|
+
name: 'sms_send',
|
|
45
|
+
description: 'Send an SMS message to a phone number. Use when you need to notify someone via text message. ' +
|
|
46
|
+
'Requires the recipient phone number in E.164 format (e.g., +15551234567).',
|
|
47
|
+
parameters: SmsSendParamsSchema,
|
|
48
|
+
async execute(params) {
|
|
49
|
+
// Validate parameters
|
|
50
|
+
const parseResult = SmsSendParamsSchema.safeParse(params);
|
|
51
|
+
if (!parseResult.success) {
|
|
52
|
+
const errorMessage = parseResult.error.errors
|
|
53
|
+
.map((e) => `${e.path.join('.')}: ${e.message}`)
|
|
54
|
+
.join(', ');
|
|
55
|
+
return { success: false, error: errorMessage };
|
|
56
|
+
}
|
|
57
|
+
const { to, body, idempotencyKey } = parseResult.data;
|
|
58
|
+
// Check Twilio configuration
|
|
59
|
+
if (!isTwilioConfigured(config)) {
|
|
60
|
+
return {
|
|
61
|
+
success: false,
|
|
62
|
+
error: 'Twilio is not configured. Please configure Twilio credentials.',
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// Log invocation (without phone number for privacy)
|
|
66
|
+
logger.info('sms_send invoked', {
|
|
67
|
+
userId,
|
|
68
|
+
bodyLength: body.length,
|
|
69
|
+
hasIdempotencyKey: !!idempotencyKey,
|
|
70
|
+
});
|
|
71
|
+
try {
|
|
72
|
+
// Call API
|
|
73
|
+
const response = await client.post('/api/twilio/sms/send', {
|
|
74
|
+
to,
|
|
75
|
+
body,
|
|
76
|
+
idempotencyKey,
|
|
77
|
+
}, { userId });
|
|
78
|
+
if (!response.success) {
|
|
79
|
+
logger.error('sms_send API error', {
|
|
80
|
+
userId,
|
|
81
|
+
status: response.error.status,
|
|
82
|
+
code: response.error.code,
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
success: false,
|
|
86
|
+
error: response.error.message || 'Failed to send SMS',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const { messageId, threadId, status } = response.data;
|
|
90
|
+
logger.debug('sms_send completed', {
|
|
91
|
+
userId,
|
|
92
|
+
messageId,
|
|
93
|
+
status,
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
success: true,
|
|
97
|
+
data: {
|
|
98
|
+
content: `SMS sent successfully (ID: ${messageId}, Status: ${status})`,
|
|
99
|
+
details: {
|
|
100
|
+
messageId,
|
|
101
|
+
threadId,
|
|
102
|
+
status,
|
|
103
|
+
userId,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
logger.error('sms_send failed', {
|
|
110
|
+
userId,
|
|
111
|
+
error: error instanceof Error ? error.message : String(error),
|
|
112
|
+
});
|
|
113
|
+
return {
|
|
114
|
+
success: false,
|
|
115
|
+
error: sanitizeErrorMessage(error),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=sms-send.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sms-send.js","sourceRoot":"","sources":["../../src/tools/sms-send.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thread tools implementation.
|
|
3
|
+
* Provides thread_list and thread_get tools for viewing message threads.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import type { ApiClient } from '../api-client.js';
|
|
7
|
+
import type { Logger } from '../logger.js';
|
|
8
|
+
import type { PluginConfig } from '../config.js';
|
|
9
|
+
/** Parameters for thread_list tool */
|
|
10
|
+
export declare const ThreadListParamsSchema: z.ZodObject<{
|
|
11
|
+
channel: z.ZodOptional<z.ZodEnum<["sms", "email"]>>;
|
|
12
|
+
contactId: z.ZodOptional<z.ZodString>;
|
|
13
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
limit: number;
|
|
16
|
+
contactId?: string | undefined;
|
|
17
|
+
channel?: "email" | "sms" | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
limit?: number | undefined;
|
|
20
|
+
contactId?: string | undefined;
|
|
21
|
+
channel?: "email" | "sms" | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export type ThreadListParams = z.infer<typeof ThreadListParamsSchema>;
|
|
24
|
+
/** Thread in list response */
|
|
25
|
+
interface ThreadListItem {
|
|
26
|
+
id: string;
|
|
27
|
+
channel: string;
|
|
28
|
+
contactName?: string;
|
|
29
|
+
endpointValue: string;
|
|
30
|
+
messageCount: number;
|
|
31
|
+
lastMessageAt?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Successful tool result */
|
|
34
|
+
export interface ThreadListSuccess {
|
|
35
|
+
success: true;
|
|
36
|
+
data: {
|
|
37
|
+
content: string;
|
|
38
|
+
details: {
|
|
39
|
+
threads: ThreadListItem[];
|
|
40
|
+
total: number;
|
|
41
|
+
userId: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Failed tool result */
|
|
46
|
+
export interface ThreadListFailure {
|
|
47
|
+
success: false;
|
|
48
|
+
error: string;
|
|
49
|
+
}
|
|
50
|
+
export type ThreadListResult = ThreadListSuccess | ThreadListFailure;
|
|
51
|
+
/** Tool configuration */
|
|
52
|
+
export interface ThreadToolOptions {
|
|
53
|
+
client: ApiClient;
|
|
54
|
+
logger: Logger;
|
|
55
|
+
config: PluginConfig;
|
|
56
|
+
userId: string;
|
|
57
|
+
}
|
|
58
|
+
/** Tool definition */
|
|
59
|
+
export interface ThreadListTool {
|
|
60
|
+
name: string;
|
|
61
|
+
description: string;
|
|
62
|
+
parameters: typeof ThreadListParamsSchema;
|
|
63
|
+
execute: (params: ThreadListParams) => Promise<ThreadListResult>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Creates the thread_list tool.
|
|
67
|
+
*/
|
|
68
|
+
export declare function createThreadListTool(options: ThreadToolOptions): ThreadListTool;
|
|
69
|
+
/** Parameters for thread_get tool */
|
|
70
|
+
export declare const ThreadGetParamsSchema: z.ZodObject<{
|
|
71
|
+
threadId: z.ZodString;
|
|
72
|
+
messageLimit: z.ZodDefault<z.ZodNumber>;
|
|
73
|
+
}, "strip", z.ZodTypeAny, {
|
|
74
|
+
threadId: string;
|
|
75
|
+
messageLimit: number;
|
|
76
|
+
}, {
|
|
77
|
+
threadId: string;
|
|
78
|
+
messageLimit?: number | undefined;
|
|
79
|
+
}>;
|
|
80
|
+
export type ThreadGetParams = z.infer<typeof ThreadGetParamsSchema>;
|
|
81
|
+
/** Thread detail */
|
|
82
|
+
interface ThreadDetail {
|
|
83
|
+
id: string;
|
|
84
|
+
channel: string;
|
|
85
|
+
contactName?: string;
|
|
86
|
+
endpointValue?: string;
|
|
87
|
+
}
|
|
88
|
+
/** Message in thread */
|
|
89
|
+
interface ThreadMessage {
|
|
90
|
+
id: string;
|
|
91
|
+
direction: 'inbound' | 'outbound';
|
|
92
|
+
body: string;
|
|
93
|
+
subject?: string;
|
|
94
|
+
deliveryStatus?: string;
|
|
95
|
+
createdAt: string;
|
|
96
|
+
}
|
|
97
|
+
/** Successful tool result */
|
|
98
|
+
export interface ThreadGetSuccess {
|
|
99
|
+
success: true;
|
|
100
|
+
data: {
|
|
101
|
+
content: string;
|
|
102
|
+
details: {
|
|
103
|
+
thread: ThreadDetail;
|
|
104
|
+
messages: ThreadMessage[];
|
|
105
|
+
userId: string;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** Failed tool result */
|
|
110
|
+
export interface ThreadGetFailure {
|
|
111
|
+
success: false;
|
|
112
|
+
error: string;
|
|
113
|
+
}
|
|
114
|
+
export type ThreadGetResult = ThreadGetSuccess | ThreadGetFailure;
|
|
115
|
+
/** Tool definition */
|
|
116
|
+
export interface ThreadGetTool {
|
|
117
|
+
name: string;
|
|
118
|
+
description: string;
|
|
119
|
+
parameters: typeof ThreadGetParamsSchema;
|
|
120
|
+
execute: (params: ThreadGetParams) => Promise<ThreadGetResult>;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Creates the thread_get tool.
|
|
124
|
+
*/
|
|
125
|
+
export declare function createThreadGetTool(options: ThreadToolOptions): ThreadGetTool;
|
|
126
|
+
export {};
|
|
127
|
+
//# sourceMappingURL=threads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../src/tools/threads.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAgBhD,sCAAsC;AACtC,eAAO,MAAM,sBAAsB;;;;;;;;;;;;EASjC,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAErE,8BAA8B;AAC9B,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAQD,6BAA6B;AAC7B,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,IAAI,CAAA;IACb,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE;YACP,OAAO,EAAE,cAAc,EAAE,CAAA;YACzB,KAAK,EAAE,MAAM,CAAA;YACb,MAAM,EAAE,MAAM,CAAA;SACf,CAAA;KACF,CAAA;CACF;AAED,yBAAyB;AACzB,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,KAAK,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,CAAA;AAEpE,yBAAyB;AACzB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,SAAS,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,sBAAsB;AACtB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,sBAAsB,CAAA;IACzC,OAAO,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAA;CACjE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CA+F/E;AAMD,qCAAqC;AACrC,eAAO,MAAM,qBAAqB;;;;;;;;;EAQhC,CAAA;AACF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEnE,oBAAoB;AACpB,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAwB;AACxB,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,SAAS,GAAG,UAAU,CAAA;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;CAClB;AAQD,6BAA6B;AAC7B,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,IAAI,CAAA;IACb,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE;YACP,MAAM,EAAE,YAAY,CAAA;YACpB,QAAQ,EAAE,aAAa,EAAE,CAAA;YACzB,MAAM,EAAE,MAAM,CAAA;SACf,CAAA;KACF,CAAA;CACF;AAED,yBAAyB;AACzB,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,KAAK,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG,gBAAgB,CAAA;AAEjE,sBAAsB;AACtB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,OAAO,qBAAqB,CAAA;IACxC,OAAO,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;CAC/D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa,CA4F7E"}
|