@m8tes/sdk 0.1.0-alpha.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 +100 -0
- package/LICENSE +21 -0
- package/README.md +160 -0
- package/dist/chunk-UFQQNUFE.js +1083 -0
- package/dist/chunk-UFQQNUFE.js.map +1 -0
- package/dist/fixtures.cjs +297 -0
- package/dist/fixtures.cjs.map +1 -0
- package/dist/fixtures.d.cts +81 -0
- package/dist/fixtures.d.ts +81 -0
- package/dist/fixtures.js +295 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/index.cjs +1783 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +937 -0
- package/dist/index.d.ts +937 -0
- package/dist/index.js +672 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/index.cjs +1109 -0
- package/dist/protocol/index.cjs.map +1 -0
- package/dist/protocol/index.d.cts +576 -0
- package/dist/protocol/index.d.ts +576 -0
- package/dist/protocol/index.js +3 -0
- package/dist/protocol/index.js.map +1 -0
- package/package.json +64 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@m8tes/sdk`.
|
|
4
|
+
|
|
5
|
+
> **Release process** (mirrors `sdk/py`): every change to behaviour or public API
|
|
6
|
+
> lands an entry under `## [Unreleased]` in the same commit. A RELEASE then bumps
|
|
7
|
+
> `package.json` `version` (semver) and retitles that section. Entries are never
|
|
8
|
+
> skipped — without one, a consumer cannot tell what changed. Publish via the `Publish @m8tes/sdk` workflow — never `npm publish` by
|
|
9
|
+
> hand (it does not rewrite the pnpm `workspace:` protocol).
|
|
10
|
+
>
|
|
11
|
+
> While the version is a `-alpha.N` prerelease, publish with dist-tag `alpha`.
|
|
12
|
+
> The first stable release is published with `--tag latest` deliberately.
|
|
13
|
+
|
|
14
|
+
## [0.1.0-alpha.1]
|
|
15
|
+
|
|
16
|
+
Initial release. TypeScript client for the m8tes V2 API, at parity with the
|
|
17
|
+
Python SDK on the core loop.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **`M8tes` client** — `runs`, `agents` (alias `teammates`), `tasks` (+ `tasks.triggers`),
|
|
22
|
+
`users`, `apps`, `webhooks`, `settings`. Reads `M8TES_API_KEY`, or pass `apiKey`.
|
|
23
|
+
`client.http` is the escape hatch for endpoints this version does not wrap yet.
|
|
24
|
+
- **Streaming `RunStream`** — async-iterable of normalized events, plus `iterText()`,
|
|
25
|
+
`text()`, `runId`, `errors`, and `conversation` (the full accumulated
|
|
26
|
+
conversation: messages, tool calls, notices). `raiseOnError` turns a run that
|
|
27
|
+
emitted error events into a thrown `RunFailedError`, so a mid-run failure is
|
|
28
|
+
never mistaken for a successful empty run.
|
|
29
|
+
- **Typed errors** — `M8tesApiError` plus a subclass per status
|
|
30
|
+
(`ValidationError`, `AuthenticationError`, `BillingError`,
|
|
31
|
+
`PermissionDeniedError`, `NotFoundError`, `ConflictError`, `RateLimitError`,
|
|
32
|
+
`APIError`), each carrying `status`, `errorCode`, `requestId`, `docUrl`,
|
|
33
|
+
`retryAfter`, and `details`.
|
|
34
|
+
- **Automatic retries** on 429/5xx for idempotent requests only, honouring
|
|
35
|
+
`Retry-After`. A `POST` is never retried: one that timed out may already have
|
|
36
|
+
started a billable run.
|
|
37
|
+
- **Auto-paging** — every `list()` returns a `Page` you can `for await` straight
|
|
38
|
+
through; it fetches subsequent pages for you.
|
|
39
|
+
- **`verifySignature()`** — HMAC-SHA256 webhook verification with optional replay
|
|
40
|
+
protection. Needs no client and no API key, and interoperates with the Python
|
|
41
|
+
SDK (same signing scheme, pinned by a shared test vector).
|
|
42
|
+
- **`@m8tes/sdk/protocol`** — the wire protocol (event union, SSE decoder,
|
|
43
|
+
normalizer, conversation accumulator, error classes) as a browser-safe entry
|
|
44
|
+
point with no auth code. `@m8tes/react` consumes this, so there is ONE
|
|
45
|
+
implementation of the protocol rather than one per package.
|
|
46
|
+
- **`@m8tes/sdk/fixtures`** — the recorded wire scenarios both packages test
|
|
47
|
+
against, exported so you can test your own protocol consumers.
|
|
48
|
+
- **Base-URL diagnostics** — an HTML response or a 404 with no error envelope
|
|
49
|
+
produces an actionable message ("check your baseUrl includes the /api/v2
|
|
50
|
+
prefix") instead of a wall of HTML or a bare 404.
|
|
51
|
+
|
|
52
|
+
### Corrections from review (before first publish)
|
|
53
|
+
|
|
54
|
+
An adversarial Codex review plus a second live-backend pass caught these while
|
|
55
|
+
the package was still unpublished. Each was verified against the backend schema,
|
|
56
|
+
not assumed, and each is pinned by a test in `test/review-findings.test.ts`:
|
|
57
|
+
|
|
58
|
+
- **Field names are the API's own snake_case** (`user_id`, `created_at`) in params
|
|
59
|
+
and responses, matching `/docs/api-reference` and the Python SDK. This removed
|
|
60
|
+
the case-mapping layer entirely — and with it the class of bug where a key
|
|
61
|
+
rewriter silently mangled caller-defined keys.
|
|
62
|
+
- `apps.connectOauth` sends **`redirect_uri`** (not `redirect_url` — a 422) and
|
|
63
|
+
returns `{authorization_url, connection_id}`; `apps.connectComplete` requires
|
|
64
|
+
`connection_id`.
|
|
65
|
+
- `runs.get()` sends **no query parameters** — `GET /runs/{id}` declares none, so
|
|
66
|
+
passing `user_id` was a 422.
|
|
67
|
+
- `runs.cancel()` returns the updated `Run`, matching the Python SDK.
|
|
68
|
+
- `PermissionMode` is `"autonomous" | "approval" | "plan"` — the previous type
|
|
69
|
+
offered the Claude Agent SDK's names, which the API rejects.
|
|
70
|
+
- `tasks.create()` requires an owning agent; `POST /tasks/` requires `teammate_id`.
|
|
71
|
+
- Update params carry **only** what each PATCH schema accepts. Create-only fields
|
|
72
|
+
sent to PATCH return 200 and change nothing, which reads as success.
|
|
73
|
+
- Explicit `null` is expressible on update params — that is how a field is cleared.
|
|
74
|
+
- An unmapped HTTP status maps to `APIError`, matching Python's
|
|
75
|
+
`STATUS_MAP.get(status, APIError)`.
|
|
76
|
+
- Auto-pagination terminates if the cursor stops advancing instead of looping forever.
|
|
77
|
+
- An abort is observed **during** retry backoff (a `Retry-After: 3600` no longer
|
|
78
|
+
strands a cancelled caller for an hour).
|
|
79
|
+
- Constructing a client in a browser throws: the secret key would otherwise be
|
|
80
|
+
readable by every visitor.
|
|
81
|
+
|
|
82
|
+
### Notes from validating against a live backend
|
|
83
|
+
|
|
84
|
+
Two things the mocked unit suite could not have caught, both fixed before release:
|
|
85
|
+
|
|
86
|
+
- `client.settings` is in v0.1 because strict multi-tenant mode is ON by default
|
|
87
|
+
for API accounts, and the backend's 422 tells you to call
|
|
88
|
+
`client.settings.update(...)`. Without the resource, that instruction dead-ends.
|
|
89
|
+
- `apps.list()` sends only `user_id`. `GET /apps/` rejects `limit` /
|
|
90
|
+
`starting_after` with a 422 (`unknown_query_parameter`), so the endpoint is not
|
|
91
|
+
paginated and iterating one page terminates instead of looping.
|
|
92
|
+
|
|
93
|
+
### Notes
|
|
94
|
+
|
|
95
|
+
- Server-only: this package holds your secret key. To render an agent in a
|
|
96
|
+
browser use [`@m8tes/react`](https://www.npmjs.com/package/@m8tes/react).
|
|
97
|
+
- Parameters and response fields are camelCase, matching `@m8tes/react`; the
|
|
98
|
+
snake_case wire mapping happens inside the SDK. Caller-defined keys
|
|
99
|
+
(`metadata`, `answers`, `outputSchema` properties, `triggerConfig`) are passed
|
|
100
|
+
through verbatim and never rewritten.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 m8tes.ai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# @m8tes/sdk
|
|
2
|
+
|
|
3
|
+
TypeScript client for the [m8tes](https://www.m8tes.ai) API. Create agents, schedule tasks, stream runs, and verify webhooks from Node, Deno, or Bun.
|
|
4
|
+
|
|
5
|
+
> **Alpha.** Published under the `alpha` dist-tag. Method signatures may change before 1.0; the streaming wire protocol (`m8tes.stream.v2`) is semver-stable.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i @m8tes/sdk@alpha
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires Node 18+, Deno, or Bun. No dependencies. (`verifySignature` uses `node:crypto`, so edge runtimes need Node compatibility enabled.)
|
|
12
|
+
|
|
13
|
+
## Your first run
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { M8tes } from "@m8tes/sdk";
|
|
17
|
+
|
|
18
|
+
const client = new M8tes(); // reads M8TES_API_KEY
|
|
19
|
+
|
|
20
|
+
const run = client.runs.create({
|
|
21
|
+
message: "A customer asked to cancel. Draft a warm reply that offers to pause instead.",
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
for await (const chunk of run.iterText()) process.stdout.write(chunk);
|
|
25
|
+
console.log("\nrun", run.runId, "cost", run.conversation.status);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
No agent to create first: a brand-new key auto-provisions a default agent.
|
|
29
|
+
|
|
30
|
+
Get a key at [m8tes.ai/developer](https://m8tes.ai/developer).
|
|
31
|
+
|
|
32
|
+
## Multi-tenancy
|
|
33
|
+
|
|
34
|
+
`user_id` is **your** id for one of your customers. Pass it and that person's memory, run history, and tool connections stay isolated — strictly, with no fallback to account-level data.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
const run = client.runs.create({ message: "Summarize my open tickets", user_id: "customer_42" });
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Register end-users explicitly when you want per-person budgets:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
await client.users.create({ user_id: "customer_42", run_limit: 50, rate_per_minute: 5 });
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Not streaming
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
const run = await client.runs.createAsync({ message: "Prep the weekly recap" });
|
|
50
|
+
// poll, or receive a webhook
|
|
51
|
+
const done = await client.runs.get(run.id);
|
|
52
|
+
console.log(done.status, done.output);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Agents and scheduled tasks
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
const agent = await client.agents.create({
|
|
59
|
+
name: "Support Triage",
|
|
60
|
+
instructions: "Sort inbound tickets by urgency and draft first replies.",
|
|
61
|
+
tools: ["gmail"],
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const task = await client.tasks.create({
|
|
65
|
+
agent_id: agent.id,
|
|
66
|
+
instructions: "Review yesterday's tickets and post a summary.",
|
|
67
|
+
schedule: "0 9 * * 1-5", // weekday mornings
|
|
68
|
+
schedule_timezone: "Europe/Copenhagen",
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Triggers beyond cron — webhook, email, and app events:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
await client.tasks.triggers.create(task.id, { type: "app", app: "github", trigger_name: "pull_request_opened" });
|
|
76
|
+
const { url } = await client.tasks.enableWebhook(task.id);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Human-in-the-loop
|
|
80
|
+
|
|
81
|
+
When a run pauses, the stream emits an `approval-request` or `question` event. Answer it and the run resumes.
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
const run = client.runs.create({ message: "Refund order 1234", human_in_the_loop: true });
|
|
85
|
+
|
|
86
|
+
for await (const event of run) {
|
|
87
|
+
// run.runId is populated from the first event, so it's available by the time a gate arrives.
|
|
88
|
+
if (event.type === "approval-request" && run.runId) {
|
|
89
|
+
await client.runs.approve(run.runId, { request_id: event.requestId, decision: "allow" });
|
|
90
|
+
}
|
|
91
|
+
if (event.type === "question" && run.runId) {
|
|
92
|
+
const q = event.questions[0];
|
|
93
|
+
if (q) await client.runs.answer(run.runId, { answers: { [q.question]: "Yes" } });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Every snippet in this README is mirrored by a compiled file in [`examples/`](./examples), so `tsc` fails if one of them stops type-checking.
|
|
99
|
+
|
|
100
|
+
## Webhooks
|
|
101
|
+
|
|
102
|
+
Verification needs no client and no API key. Pass the **raw** body: a parsed-then-restringified object will not match.
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { verifySignature } from "@m8tes/sdk";
|
|
106
|
+
|
|
107
|
+
export async function POST(req: Request) {
|
|
108
|
+
const raw = await req.text();
|
|
109
|
+
if (!verifySignature(raw, req.headers, process.env.M8TES_WEBHOOK_SECRET!, { toleranceSeconds: 300 })) {
|
|
110
|
+
return new Response("bad signature", { status: 401 });
|
|
111
|
+
}
|
|
112
|
+
const event = JSON.parse(raw);
|
|
113
|
+
return new Response("ok");
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Errors
|
|
118
|
+
|
|
119
|
+
Every failure is a typed subclass of `M8tesApiError`, carrying `status`, `errorCode`, `requestId`, `docUrl`, and `retryAfter`.
|
|
120
|
+
|
|
121
|
+
Field names throughout are the API's own **snake_case** (`user_id`, `created_at`) — the same names as the [API reference](https://www.m8tes.ai/docs/api-reference) and the Python SDK, so nothing is renamed in transit. Things the SDK owns rather than sends — client options, method names, `RunStream`, stream events — stay camelCase.
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { BillingError, RateLimitError } from "@m8tes/sdk";
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
await client.runs.createAsync({ message: "..." });
|
|
128
|
+
} catch (err) {
|
|
129
|
+
if (err instanceof RateLimitError) await sleep((err.retryAfter ?? 1) * 1000);
|
|
130
|
+
else if (err instanceof BillingError) console.error(err.errorCode, err.docUrl);
|
|
131
|
+
else throw err;
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Retries are automatic on 429 and 5xx for idempotent requests only. A `POST` is **never** retried: one that timed out may already have started a billable run.
|
|
136
|
+
|
|
137
|
+
## Pagination
|
|
138
|
+
|
|
139
|
+
Every `list()` returns a page you can iterate straight through — it fetches the rest for you.
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
for await (const run of await client.runs.list({ user_id: "customer_42" })) {
|
|
143
|
+
console.log(run.id, run.status);
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Browser UI
|
|
148
|
+
|
|
149
|
+
This package is **server-only** — it holds your secret key. To render an agent in a browser, use [`@m8tes/react`](https://www.npmjs.com/package/@m8tes/react), which ships a `<MateChat>` component plus a locked-down server proxy so the key never reaches the client. Both packages share this one wire-protocol implementation, exported separately as the browser-safe `@m8tes/sdk/protocol`.
|
|
150
|
+
|
|
151
|
+
## Docs
|
|
152
|
+
|
|
153
|
+
- [TypeScript SDK guide](https://www.m8tes.ai/docs/typescript-sdk)
|
|
154
|
+
- [API reference](https://www.m8tes.ai/docs/api-reference)
|
|
155
|
+
- [Multi-tenancy](https://www.m8tes.ai/docs/users)
|
|
156
|
+
- [Streaming & events](https://www.m8tes.ai/docs/streaming)
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
MIT
|