notte-sdk 1.9.6 → 1.10.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/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # notte-sdk
2
2
 
3
- > TypeScript SDK for Notte - Cloud-hosted browser sessions with LLM-powered web agents
3
+ > TypeScript SDK for Notte - Cloud-hosted browser sessions and automation
4
4
 
5
- The official TypeScript SDK for Notte API, providing cloud-hosted browser sessions with precise control, LLM-powered web agents for automated tasks, serverless functions, and secure credential management.
5
+ The official TypeScript SDK for Notte API, providing cloud-hosted browser sessions with precise control, serverless functions, and secure credential management.
6
6
 
7
7
  ## Contributing
8
8
 
@@ -23,12 +23,31 @@ npm pack --dry-run
23
23
  ```
24
24
 
25
25
  `npm run build` compiles the checked-in client without contacting the API.
26
- To update the generated client, run `npm run generate:staging`, review the diff,
27
- and commit it. `npm run check:staging` checks for drift without editing your files.
26
+ `npm run generate` uses `../openapi/openapi.json`, the committed snapshot shared
27
+ with Python, and ignores `NOTTE_API_URL` (which configures runtime API calls).
28
+ Run `npm run docs:generate` afterward and commit the generated changes.
29
+ `npm run check:generated` regenerates in a temporary directory and checks the
30
+ TypeScript reference without editing your files or contacting staging.
31
+
32
+ To deliberately refresh the snapshot and regenerate **both SDKs** and the TypeScript
33
+ reference, install dependencies with `uvx uv@latest sync --all-packages --all-extras`
34
+ at the repo root and `npm ci` here, then run from the repo root:
35
+
36
+ ```bash
37
+ make openapi-refresh # staging
38
+ make openapi-refresh OPENAPI_URL=https://api.notte.cc # production
39
+ ```
40
+
41
+ Review and commit the snapshot and all generated diffs together. If a generator
42
+ rejects the new contract, resolve the reported incompatibility before committing.
43
+ The scheduled `openapi-bump.yml` workflow proposes this same combined refresh as
44
+ one PR for manual review in `nottelabs/notte`; if a generator fails, the PR is a draft
45
+ with the error in its body and the run fails. It is repository-guarded and does not
46
+ run in `nottelabs/notte-v2`. There is no separate live Node generation check.
28
47
 
29
48
  ### Generated resource methods
30
49
 
31
- The SDK generates client-bound methods for `sessions`, `agents`, `functions`,
50
+ The SDK generates client-bound methods for `sessions`, `functions`,
32
51
  `vaults`, `personas`, and `profiles` from the checked-in OpenAPI-derived types
33
52
  and operations. No per-call client or `throwOnError` is needed:
34
53
 
@@ -47,12 +66,12 @@ example `client.sessions.createPayment(sessionId, body, undefined, { headers: {
47
66
  Keep the same idempotency key when retrying the same payment request. The SDK
48
67
  binds `x-notte-api-key` automatically; callers cannot override it through typed headers.
49
68
  Methods return the API response body and throw the client's typed API errors.
50
- The five existing `list()` methods still return arrays for compatibility;
69
+ The four existing `list()` methods still return arrays for compatibility;
51
70
  the newly added `profiles.list()` returns the API pagination response.
52
71
 
53
72
  These are API operations, not lifecycle helpers: they do not poll for completion,
54
73
  decrypt credentials, or manage cleanup. Continue using `Session().use()`,
55
- `Agent().run()`, `Function().run()`, and `Vault()` for those behaviors. Existing
74
+ `Function().run()` and `Vault()` for those behaviors. Existing
56
75
  standalone generated exports remain supported.
57
76
 
58
77
  `npm run generate` refreshes this layer too. Use `npm run resources:generate`
@@ -69,15 +88,20 @@ npx vitest run test/function-create-run.integration.test.ts
69
88
 
70
89
  This test creates its own function and deletes it afterward. Other live suites
71
90
  may require pre-existing fixtures; see [test documentation](test/README.md).
72
- The `node sdk cicd` workflow runs on every PR touching `node-sdk/`:
91
+ The `node sdk cicd` workflow runs on PRs touching `node-sdk/`, the OpenAPI snapshot,
92
+ or the generated TypeScript reference:
73
93
 
74
94
  - `tests` runs unit tests, local HTTP integration tests, type checks, and package
75
95
  checks on Node.js 22 and 24, including for fork PRs.
76
- - `integration-tests` runs the isolated live function lifecycle tests against
96
+ - `integration-tests` runs the complete live integration suite against
77
97
  staging on same-repository PRs. Fork PRs skip this credentialed job.
78
98
 
79
- Both jobs also run on main pushes and manual workflow runs on main. API drift
80
- checks remain limited to main pushes and manual workflow runs on main.
99
+ - `generated` checks the client, proxy patterns, resources and TypeScript reference
100
+ against the committed snapshot, including on fork PRs.
101
+
102
+ These jobs also run on main pushes and manual workflow runs (live integration
103
+ requires main for manual runs). Staging contract drift is handled only by the
104
+ scheduled snapshot refresh PR, so it cannot break unrelated PR generation checks.
81
105
 
82
106
  ### Releases
83
107
 
@@ -109,6 +133,10 @@ API URLs must use HTTPS, except HTTP loopback addresses for local development.
109
133
 
110
134
  ## Features
111
135
 
136
+ Since 1.10 the SDK has no high-level agent API, matching Python. Releases up to
137
+ 1.9 keep agent support. Generated low-level agent endpoints and schemas remain tied
138
+ to the API specification; they are not exposed through client resources.
139
+
112
140
  ### Server-side proxy security
113
141
 
114
142
  `createNotteProxy` from `notte-sdk/next` requires an `authenticate` callback at
@@ -116,15 +144,12 @@ runtime. Without one, requests return 401 even when a server API key is configur
116
144
  The callback must verify caller identity and authorize access to requested
117
145
  resources. Returning a user-specific Notte API key isolates accounts; returning
118
146
  void uses the shared server key and requires application-level ownership checks.
119
- An endpoint allowlist is not a substitute for authorization. Relative HTTP proxy
120
- clients poll agent status for completion because they cannot use backend WebSockets.
147
+ An endpoint allowlist is not a substitute for authorization.
121
148
 
122
149
  - 🌐 **Cloud Browser Sessions** - Access remote browsers with full control
123
- - 🤖 **LLM-Powered Agents** - Intelligent web automation with natural language
124
150
  - 🔒 **Secret Vaults** - Enterprise-grade credential management with end-to-end encryption
125
151
  - 👤 **Digital Personas** - Complete identities with email, SMS, and 2FA for automated account creation
126
152
  - 🎯 **Session Management** - Context managers for reliable resource cleanup
127
- - 📡 **Real-time Updates** - WebSocket support for live agent monitoring
128
153
  - 📝 **Type Safety** - Full TypeScript support with generated types
129
154
  - ⚡ **Serverless Functions** - Run pre-built automation workflows with simple API calls
130
155
  - 🔍 **Web Search, Secrets and Usage** - Search the web, manage workspace secrets and read billing usage
@@ -155,30 +180,6 @@ await notte.Session({ idle_timeout_minutes: 5 }).use(async (session) => {
155
180
  });
156
181
  ```
157
182
 
158
- ### Agent Automation
159
-
160
- ```typescript
161
- import { NotteClient } from 'notte-sdk';
162
-
163
- const notte = new NotteClient();
164
-
165
- // Run an agent task with live updates
166
- await notte.Session().use(async (session) => {
167
- const agent = notte.Agent({ session, max_steps: 10 });
168
-
169
- const response = await agent.run({
170
- task: "Find the best Italian restaurant in San Francisco and book a table for 2 at 7pm today",
171
- updateHandler: (update) => {
172
- // Receive real-time updates via WebSocket
173
- console.log(`[${update.type}]`, update.data);
174
- }
175
- });
176
-
177
- console.log(`Agent completed: ${response.success ? 'Success' : 'Failed'}`);
178
- console.log(`Answer: ${response.answer}`);
179
- });
180
- ```
181
-
182
183
  ## Core Classes
183
184
 
184
185
  ### NotteClient
@@ -198,9 +199,6 @@ const notte = new NotteClient({
198
199
  // Create sessions
199
200
  const session = notte.Session({ idle_timeout_minutes: 5, max_duration_minutes: 30 });
200
201
 
201
- // Create agents
202
- const agent = notte.Agent({ session, max_steps: 15 });
203
-
204
202
  // Create vaults
205
203
  const vault = notte.Vault({ name: 'My Vault' });
206
204
 
@@ -215,12 +213,11 @@ await notte.healthCheck();
215
213
 
216
214
  Every resource has a `list()` namespace, mirroring `client.sessions.list()` and
217
215
  friends in Python. Options are the generated query parameters of the matching
218
- endpoint (`SessionListOptions`, `AgentListOptions`, `VaultListOptions`,
216
+ endpoint (`SessionListOptions`, `VaultListOptions`,
219
217
  `FunctionListOptions`, `PersonaListOptions`).
220
218
 
221
219
  ```typescript
222
220
  const sessions = await notte.sessions.list({ only_active: true });
223
- const agents = await notte.agents.list({ page_size: 10 });
224
221
  const vaults = await notte.vaults.list();
225
222
  const functions = await notte.functions.list();
226
223
  const personas = await notte.personas.list({ only_active: true });
@@ -368,79 +365,6 @@ await session.downloadReplay('./session.mp4');
368
365
  - `storage` - The `RemoteFileStorage` attached with the `storage` option
369
366
  - `client.sessions.list(options?)` - List sessions
370
367
 
371
- ### Agent
372
-
373
- Executes tasks using LLM-powered web automation.
374
-
375
- ```typescript
376
- import { NotteClient } from 'notte-sdk';
377
-
378
- const notte = new NotteClient();
379
-
380
- await notte.Session().use(async (session) => {
381
- const agent = notte.Agent({
382
- session,
383
- max_steps: 10
384
- });
385
-
386
- // Non-blocking: start agent and get its ID
387
- await agent.start({ task: "Navigate to Google and search for 'TypeScript'" });
388
- console.log('Agent started:', agent.agentId);
389
-
390
- // Check agent status
391
- const status = await agent.status();
392
- console.log('Agent status:', status);
393
-
394
- // Blocking: run agent and wait for completion with live updates
395
- const response = await agent.run({
396
- task: "Find the latest TypeScript documentation",
397
- updateHandler: (update) => {
398
- if (update.type === 'step') {
399
- console.log(`Step update:`, update.data);
400
- } else if (update.type === 'completion') {
401
- console.log(`Completed:`, update.data);
402
- }
403
- }
404
- });
405
-
406
- console.log('Final result:', response);
407
- });
408
- ```
409
-
410
- #### Agent Methods
411
-
412
- - `start(request)` - Start agent with `{ task, url?, ... }` (non-blocking)
413
- - `run(request)` - Start agent and wait for completion (blocking); pass `updateHandler` for live updates
414
- - `status()` - Get agent status
415
- - `stop()` - Stop the agent
416
- - `agentId` - The agent ID (read-only property, available after `start()` / `run()`)
417
- - `sessionId` - The session ID the agent runs in (read-only property)
418
- - `hasStarted()` - Whether `start()`/`run()` was called on this instance (local check)
419
- - `isActive()` - Whether the agent is still active on the server (fetches the status)
420
- - `isRunning()` - Deprecated alias of `hasStarted()`; it does not contact the API
421
-
422
- #### Structured answers with Zod
423
-
424
- Both `agent.start()` and `agent.run()` accept a Zod schema as `response_format`.
425
- The SDK converts it to JSON Schema before calling the API. On `run()`, the final
426
- `answer` is validated against the schema and typed accordingly.
427
-
428
- ```typescript
429
- import { z } from 'zod';
430
-
431
- const Answer = z.object({ title: z.string(), summary: z.string() });
432
-
433
- await notte.Session().use(async (session) => {
434
- const agent = notte.Agent({ session, max_steps: 5 });
435
- const result = await agent.run({
436
- task: 'Go to notte.cc and return the page title and summary',
437
- response_format: Answer,
438
- });
439
- // result.answer is typed as { title: string; summary: string } and validated
440
- console.log(result.answer.title);
441
- });
442
- ```
443
-
444
368
  ### Secret Vaults
445
369
 
446
370
  Manage credentials securely with enterprise-grade encryption.
@@ -464,19 +388,6 @@ await vault.addCredentials('https://github.com/', {
464
388
  const strongPassword = vault.generatePassword(20, true); // 20 chars with special chars
465
389
  const simplePassword = vault.generatePassword(12, false); // 12 chars, no special chars
466
390
 
467
- // Use with agents for automatic credential management
468
- await notte.Session().use(async (session) => {
469
- const agent = notte.Agent({
470
- session,
471
- vault_id: vault.vaultId // Agent will use vault for authentication
472
- });
473
-
474
- const result = await agent.run({
475
- task: "Login to GitHub and create a new repository",
476
- url: "https://github.com/login"
477
- });
478
- });
479
-
480
391
  // Access existing vault
481
392
  const existingVault = notte.Vault({ vault_id: 'vault-abc-123' });
482
393
  const credentials = await existingVault.listCredentials();
@@ -536,19 +447,6 @@ const smsMessages = await persona.sms({
536
447
  });
537
448
  console.log(`Received ${smsMessages.length} SMS messages`);
538
449
 
539
- // Use with agents for automated account creation
540
- await notte.Session().use(async (session) => {
541
- const agent = notte.Agent({
542
- session,
543
- vault_id: persona.vault.vaultId // Agent will use persona's vault
544
- });
545
-
546
- const result = await agent.run({
547
- task: `Create an account on GitHub using the persona credentials`
548
- });
549
- console.log(`Account created: ${result.success}`);
550
- });
551
-
552
450
  // Access existing persona
553
451
  const existingPersona = notte.Persona({ persona_id: 'persona-abc-123' });
554
452
  const personaEmails = await existingPersona.emails();
@@ -589,7 +487,6 @@ const sms = await persona.sms(options);
589
487
 
590
488
  - **Complete Digital Identity** - Unique email address
591
489
  - **2FA Support** - Receive and read SMS verification codes automatically
592
- - **Automated Account Creation** - Seamless integration with agents for signup flows
593
490
  - **Vault Integration** - Optional secure credential storage
594
491
  - **Email Management** - Full email reading capabilities
595
492
  - **Message Tracking** - Mark messages as read/unread automatically
@@ -787,7 +684,7 @@ await notte.Session({ storage }).use(async (session) => {
787
684
  const uploaded = await storage.upload('./invoice.pdf');
788
685
  fileId = uploaded.id;
789
686
 
790
- // ... let the session / an agent download something ...
687
+ // ... download a file through the session ...
791
688
 
792
689
  const downloads = await storage.list({ source: 'session_download' });
793
690
  for (const file of downloads.files) {
@@ -874,15 +771,6 @@ const session = notte.Session({
874
771
  });
875
772
  ```
876
773
 
877
- ### Agent Configuration
878
-
879
- ```typescript
880
- const agent = notte.Agent({
881
- session: session,
882
- max_steps: 20, // Maximum steps for agent (default: 10)
883
- });
884
- ```
885
-
886
774
  ### Error Handling
887
775
 
888
776
  Every error thrown by the SDK extends `NotteError`, mirroring `notte_sdk.errors`
@@ -898,12 +786,7 @@ import { NotteAPIError, NotteError, NotteTimeoutError } from 'notte-sdk';
898
786
 
899
787
  try {
900
788
  await notte.Session().use(async (session) => {
901
- const agent = notte.Agent({ session });
902
- const response = await agent.run({ task: "Complete a complex task" });
903
-
904
- if (!response.success) {
905
- console.error('Agent failed:', response.answer);
906
- }
789
+ await session.execute({ type: "goto", url: "https://example.com" });
907
790
  });
908
791
  } catch (error) {
909
792
  if (error instanceof NotteAPIError) {
@@ -947,29 +830,6 @@ const start = retry(() => notte.Session().start(), {
947
830
  await start();
948
831
  ```
949
832
 
950
- ### WebSocket Updates
951
-
952
- The `agent.run()` method provides real-time updates via WebSocket through the
953
- `updateHandler` option:
954
-
955
- ```typescript
956
- const response = await agent.run({
957
- task: "Your task",
958
- updateHandler: (update) => {
959
- switch (update.type) {
960
- case 'step':
961
- console.log('Step:', update.data);
962
- break;
963
- case 'completion':
964
- console.log('Task completed:', update.data);
965
- break;
966
- default:
967
- console.log('Update:', update);
968
- }
969
- }
970
- });
971
- ```
972
-
973
833
  ### Legacy API Support
974
834
 
975
835
  For backward compatibility, you can still use the legacy client creation:
@@ -1006,12 +866,6 @@ notte = NotteClient()
1006
866
  with notte.Session(idle_timeout_minutes=2) as session:
1007
867
  status = session.status()
1008
868
  print(status)
1009
-
1010
- # Agent usage
1011
- with notte.Session() as session:
1012
- agent = notte.Agent(session=session, max_steps=10)
1013
- response = agent.run(task="Find the best italian restaurant in SF")
1014
- print(f"Agent completed: {response.success}, answer: {response.answer}")
1015
869
  ```
1016
870
 
1017
871
  ### TypeScript
@@ -1025,13 +879,6 @@ await notte.Session({ idle_timeout_minutes: 2 }).use(async (session) => {
1025
879
  const status = await session.status();
1026
880
  console.log(status);
1027
881
  });
1028
-
1029
- // Agent usage
1030
- await notte.Session().use(async (session) => {
1031
- const agent = notte.Agent({ session, max_steps: 10 });
1032
- const response = await agent.run({ task: "Find the best italian restaurant in SF" });
1033
- console.log(`Agent completed: ${response.success}, answer: ${response.answer}`);
1034
- });
1035
882
  ```
1036
883
 
1037
884
  ## Development
@@ -1086,15 +933,13 @@ This will fetch the latest API specification and update the generated client cod
1086
933
  The SDK is built with full TypeScript support:
1087
934
 
1088
935
  ```typescript
1089
- import { NotteClient, type SessionResponse, type LegacyAgentStatusResponse } from 'notte-sdk';
936
+ import { NotteClient, type SessionResponse } from 'notte-sdk';
1090
937
 
1091
938
  const notte = new NotteClient();
1092
939
 
1093
940
  // All types are properly inferred
1094
941
  await notte.Session().use(async (session) => {
1095
942
  const status: SessionResponse = await session.status();
1096
- const agent = notte.Agent({ session });
1097
- const response: LegacyAgentStatusResponse = await agent.run({ task: "task" });
1098
943
  });
1099
944
  ```
1100
945
 
@@ -1111,10 +956,6 @@ import type {
1111
956
  SessionOptions,
1112
957
  SessionResponse,
1113
958
  SessionListOptions,
1114
- AgentConstructor,
1115
- AgentRunRequest,
1116
- AgentUpdateHandler,
1117
- AgentListOptions,
1118
959
  VaultConstructor,
1119
960
  VaultListOptions,
1120
961
  CredentialsDictInput,