@sapiom/tools 0.7.0 → 0.8.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.
Files changed (62) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +10 -9
  3. package/dist/cjs/client.d.ts +28 -2
  4. package/dist/cjs/client.d.ts.map +1 -1
  5. package/dist/cjs/client.js +12 -0
  6. package/dist/cjs/client.js.map +1 -1
  7. package/dist/cjs/content-generation/index.d.ts +64 -1
  8. package/dist/cjs/content-generation/index.d.ts.map +1 -1
  9. package/dist/cjs/content-generation/index.js +129 -5
  10. package/dist/cjs/content-generation/index.js.map +1 -1
  11. package/dist/cjs/database/errors.d.ts +16 -0
  12. package/dist/cjs/database/errors.d.ts.map +1 -0
  13. package/dist/cjs/database/errors.js +36 -0
  14. package/dist/cjs/database/errors.js.map +1 -0
  15. package/dist/cjs/database/index.d.ts +101 -0
  16. package/dist/cjs/database/index.d.ts.map +1 -0
  17. package/dist/cjs/database/index.js +118 -0
  18. package/dist/cjs/database/index.js.map +1 -0
  19. package/dist/cjs/index.d.ts +5 -0
  20. package/dist/cjs/index.d.ts.map +1 -1
  21. package/dist/cjs/index.js +12 -3
  22. package/dist/cjs/index.js.map +1 -1
  23. package/dist/cjs/search/index.d.ts +132 -3
  24. package/dist/cjs/search/index.d.ts.map +1 -1
  25. package/dist/cjs/search/index.js +160 -3
  26. package/dist/cjs/search/index.js.map +1 -1
  27. package/dist/cjs/stub/index.d.ts.map +1 -1
  28. package/dist/cjs/stub/index.js +112 -2
  29. package/dist/cjs/stub/index.js.map +1 -1
  30. package/dist/esm/client.d.ts +28 -2
  31. package/dist/esm/client.d.ts.map +1 -1
  32. package/dist/esm/client.js +13 -1
  33. package/dist/esm/client.js.map +1 -1
  34. package/dist/esm/content-generation/index.d.ts +64 -1
  35. package/dist/esm/content-generation/index.d.ts.map +1 -1
  36. package/dist/esm/content-generation/index.js +126 -4
  37. package/dist/esm/content-generation/index.js.map +1 -1
  38. package/dist/esm/database/errors.d.ts +16 -0
  39. package/dist/esm/database/errors.d.ts.map +1 -0
  40. package/dist/esm/database/errors.js +31 -0
  41. package/dist/esm/database/errors.js.map +1 -0
  42. package/dist/esm/database/index.d.ts +101 -0
  43. package/dist/esm/database/index.d.ts.map +1 -0
  44. package/dist/esm/database/index.js +113 -0
  45. package/dist/esm/database/index.js.map +1 -0
  46. package/dist/esm/index.d.ts +5 -0
  47. package/dist/esm/index.d.ts.map +1 -1
  48. package/dist/esm/index.js +6 -0
  49. package/dist/esm/index.js.map +1 -1
  50. package/dist/esm/search/index.d.ts +132 -3
  51. package/dist/esm/search/index.d.ts.map +1 -1
  52. package/dist/esm/search/index.js +157 -3
  53. package/dist/esm/search/index.js.map +1 -1
  54. package/dist/esm/stub/index.d.ts.map +1 -1
  55. package/dist/esm/stub/index.js +112 -2
  56. package/dist/esm/stub/index.js.map +1 -1
  57. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  58. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  59. package/package.json +6 -1
  60. package/src/content-generation/README.md +67 -0
  61. package/src/database/README.md +62 -0
  62. package/src/search/README.md +130 -1
@@ -0,0 +1,62 @@
1
+ # database
2
+
3
+ On-demand Postgres databases. The same database capability your agents call over
4
+ MCP, callable directly from your code. You get back direct connection credentials,
5
+ so you can connect with any standard Postgres client or driver.
6
+
7
+ ```typescript
8
+ import { createClient } from "@sapiom/tools";
9
+ const sapiom = createClient({ apiKey: process.env.SAPIOM_API_KEY });
10
+
11
+ // 1. Provision a database. `duration` is required.
12
+ const db = await sapiom.database.create({
13
+ duration: "1h", // "15m" | "1h" | "4h" | "24h" | "7d"
14
+ handle: "analytics", // optional, stable key to look it up later
15
+ });
16
+
17
+ // 2. Connect with any Postgres client using the credentials.
18
+ db.connection?.connectionString; // a ready-to-use Postgres URI
19
+ db.connection?.host;
20
+ db.connection?.port;
21
+ db.connection?.username;
22
+ db.connection?.password;
23
+ db.connection?.databaseName;
24
+
25
+ // 3. Retrieve it later by id or handle, then delete it.
26
+ const again = await sapiom.database.get(db.id); // or get("analytics")
27
+ await sapiom.database.delete(db.id); // or delete("analytics")
28
+ ```
29
+
30
+ Ambient import works too: `import { database } from "@sapiom/tools"`.
31
+
32
+ ## This is a provisioning surface, not a query layer
33
+
34
+ `database` hands you connection credentials; it does not run SQL for you. You
35
+ connect with the Postgres client of your choice (`pg`, `postgres`, an ORM, `psql`,
36
+ …) using `connection.connectionString` and run your own queries.
37
+
38
+ ## Lifecycle
39
+
40
+ - A database is created with a `duration` and is **automatically removed** when it
41
+ expires — there is no long-lived state to clean up by hand. `expiresAt` tells you
42
+ when that happens.
43
+ - Right after `create`, `status` is `"active"` and `connection` carries credentials.
44
+ - `get` on a database that is still provisioning may return `connection: null` until
45
+ it is ready.
46
+
47
+ ## Looking up a database
48
+
49
+ `get` and `delete` accept either the database `id` or the `handle` you set at
50
+ creation. A `handle` is a stable, human-friendly key (`3–63` chars,
51
+ `^[a-z0-9][a-z0-9-]*[a-z0-9]$`) that is unique within your tenant — handy for
52
+ passing a database between steps or agents without carrying the id around.
53
+
54
+ ## Gotchas
55
+
56
+ - **`duration` is required.** Omitting it is rejected before any request is made.
57
+ - **`connection` can be `null`** while a database is still provisioning — guard it
58
+ (`db.connection?.connectionString`) before connecting.
59
+ - **`connectionString` is always present** on a non-null `connection`, even if the
60
+ individual component fields couldn't be parsed.
61
+ - **Failed requests throw `DatabaseHttpError`** (carries `status` + parsed `body`),
62
+ exported from `@sapiom/tools`.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Find information across the web and beyond — searching the web, reading pages,
4
4
  and looking up professional emails. More operations land in this namespace as
5
- they ship; today it offers `webSearch` and `scrape`.
5
+ they ship; today it offers `webSearch`, `scrape`, and `emailSearch`.
6
6
 
7
7
  ## `webSearch` — search the web
8
8
 
@@ -120,7 +120,136 @@ that format was requested.
120
120
  `scrape` works on HTML pages and common documents (PDF, DOCX, TXT). It is not
121
121
  meant for images, video, or archives.
122
122
 
123
+ ## `emailSearch` — work with professional emails
124
+
125
+ `emailSearch` groups three operations: `findEmail` (find a person's email),
126
+ `verifyEmail` (check an address is deliverable), and `domainSearch` (discover the
127
+ emails published at a company domain).
128
+
129
+ ### `findEmail` — find a person's email
130
+
131
+ ```typescript
132
+ import { createClient } from "@sapiom/tools";
133
+ const sapiom = createClient({ apiKey: process.env.SAPIOM_API_KEY });
134
+
135
+ const found = await sapiom.search.emailSearch.findEmail({
136
+ domain: "example.com",
137
+ firstName: "Ada",
138
+ lastName: "Lovelace",
139
+ });
140
+ found.email; // the discovered email, or null when none was found
141
+ found.score; // confidence (0–100)
142
+ ```
143
+
144
+ You must give enough to identify both the person and where they work: a `domain`
145
+ **or** `company`, **and** either a `fullName` **or** both `firstName` and
146
+ `lastName`. Calling without a valid combination throws `SearchHttpError` before
147
+ any request is made.
148
+
149
+ ```typescript
150
+ const found = await sapiom.search.emailSearch.findEmail({
151
+ company: "Example Inc",
152
+ fullName: "Ada Lovelace",
153
+ });
154
+ ```
155
+
156
+ #### Input
157
+
158
+ - `domain` — company domain, e.g. `"example.com"` (provide `domain` or `company`).
159
+ - `company` — company name (alternative to `domain`).
160
+ - `firstName` / `lastName` — the person's name (provide both, or use `fullName`).
161
+ - `fullName` — the person's full name (alternative to `firstName` + `lastName`).
162
+
163
+ #### Result
164
+
165
+ ```typescript
166
+ {
167
+ email: string | null; // null when not found
168
+ score?: number; // confidence 0–100
169
+ firstName?: string;
170
+ lastName?: string;
171
+ position?: string;
172
+ company?: string;
173
+ linkedinUrl?: string;
174
+ verification?: { status?: string; date?: string };
175
+ }
176
+ ```
177
+
178
+ ### `verifyEmail` — verify deliverability
179
+
180
+ ```typescript
181
+ const check = await sapiom.search.emailSearch.verifyEmail({
182
+ email: "ada@example.com",
183
+ });
184
+ check.status; // deliverability status
185
+ check.score; // confidence 0–100
186
+ ```
187
+
188
+ #### Input
189
+
190
+ - `email` (required) — the address to verify.
191
+
192
+ #### Result
193
+
194
+ ```typescript
195
+ {
196
+ email: string;
197
+ status?: string;
198
+ result?: string;
199
+ score?: number;
200
+ smtpCheck?: boolean;
201
+ acceptAll?: boolean; // domain accepts any address (a positive is weak)
202
+ disposable?: boolean;
203
+ webmail?: boolean;
204
+ }
205
+ ```
206
+
207
+ ### `domainSearch` — discover emails at a domain
208
+
209
+ ```typescript
210
+ const hits = await sapiom.search.emailSearch.domainSearch({
211
+ domain: "example.com",
212
+ limit: 5,
213
+ seniority: ["executive"],
214
+ department: ["engineering", "sales"],
215
+ });
216
+ hits.emails; // [{ email, type?, confidence?, firstName?, ... }, …]
217
+ hits.pattern; // the detected email pattern, e.g. "{first}.{last}"
218
+ ```
219
+
220
+ #### Input
221
+
222
+ - `domain` (required) — the company domain to search.
223
+ - `limit` — max emails to return (max 100, default 10).
224
+ - `type` — `"personal"` or `"generic"`.
225
+ - `seniority` — any of `"junior" | "senior" | "executive"`.
226
+ - `department` — one or more departments, e.g. `["engineering", "sales"]`.
227
+
228
+ #### Result
229
+
230
+ ```typescript
231
+ {
232
+ domain: string;
233
+ organization?: string;
234
+ pattern?: string;
235
+ acceptAll?: boolean;
236
+ emails: Array<{
237
+ email: string;
238
+ type?: string;
239
+ confidence?: number;
240
+ firstName?: string;
241
+ lastName?: string;
242
+ position?: string;
243
+ department?: string;
244
+ seniority?: string;
245
+ }>;
246
+ }
247
+ ```
248
+
123
249
  ## Gotchas
124
250
 
125
251
  - **Failed requests throw `SearchHttpError`** (carries `status` + parsed `body`),
126
252
  exported from `@sapiom/tools`.
253
+ - **`findEmail` validates its inputs before calling.** An under-specified lookup
254
+ (missing the org or the person) throws `SearchHttpError` immediately, with no
255
+ network round-trip.