@sapiom/tools 0.7.0 → 0.8.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/CHANGELOG.md +35 -0
- package/README.md +10 -9
- package/dist/cjs/client.d.ts +28 -2
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +12 -0
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/content-generation/index.d.ts +64 -1
- package/dist/cjs/content-generation/index.d.ts.map +1 -1
- package/dist/cjs/content-generation/index.js +129 -5
- package/dist/cjs/content-generation/index.js.map +1 -1
- package/dist/cjs/database/errors.d.ts +16 -0
- package/dist/cjs/database/errors.d.ts.map +1 -0
- package/dist/cjs/database/errors.js +36 -0
- package/dist/cjs/database/errors.js.map +1 -0
- package/dist/cjs/database/index.d.ts +103 -0
- package/dist/cjs/database/index.d.ts.map +1 -0
- package/dist/cjs/database/index.js +120 -0
- package/dist/cjs/database/index.js.map +1 -0
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +12 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/search/index.d.ts +132 -3
- package/dist/cjs/search/index.d.ts.map +1 -1
- package/dist/cjs/search/index.js +160 -3
- package/dist/cjs/search/index.js.map +1 -1
- package/dist/cjs/stub/index.d.ts.map +1 -1
- package/dist/cjs/stub/index.js +112 -2
- package/dist/cjs/stub/index.js.map +1 -1
- package/dist/esm/client.d.ts +28 -2
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +13 -1
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/content-generation/index.d.ts +64 -1
- package/dist/esm/content-generation/index.d.ts.map +1 -1
- package/dist/esm/content-generation/index.js +126 -4
- package/dist/esm/content-generation/index.js.map +1 -1
- package/dist/esm/database/errors.d.ts +16 -0
- package/dist/esm/database/errors.d.ts.map +1 -0
- package/dist/esm/database/errors.js +31 -0
- package/dist/esm/database/errors.js.map +1 -0
- package/dist/esm/database/index.d.ts +103 -0
- package/dist/esm/database/index.d.ts.map +1 -0
- package/dist/esm/database/index.js +115 -0
- package/dist/esm/database/index.js.map +1 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/search/index.d.ts +132 -3
- package/dist/esm/search/index.d.ts.map +1 -1
- package/dist/esm/search/index.js +157 -3
- package/dist/esm/search/index.js.map +1 -1
- package/dist/esm/stub/index.d.ts.map +1 -1
- package/dist/esm/stub/index.js +112 -2
- package/dist/esm/stub/index.js.map +1 -1
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +6 -1
- package/src/content-generation/README.md +67 -0
- package/src/database/README.md +62 -0
- 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`.
|
package/src/search/README.md
CHANGED
|
@@ -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 `
|
|
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.
|