@airstore/sdk 0.1.3 → 0.1.6

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 (140) hide show
  1. package/README.md +214 -237
  2. package/dist/cjs/airstore.js +42 -21
  3. package/dist/cjs/airstore.js.map +1 -1
  4. package/dist/cjs/index.js +33 -1
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/cjs/resources/access-log.js +3 -55
  7. package/dist/cjs/resources/access-log.js.map +1 -1
  8. package/dist/cjs/resources/agents.js +59 -0
  9. package/dist/cjs/resources/agents.js.map +1 -0
  10. package/dist/cjs/resources/channels.js +50 -0
  11. package/dist/cjs/resources/channels.js.map +1 -0
  12. package/dist/cjs/resources/connections.js +6 -37
  13. package/dist/cjs/resources/connections.js.map +1 -1
  14. package/dist/cjs/resources/filesystem.js +5 -53
  15. package/dist/cjs/resources/filesystem.js.map +1 -1
  16. package/dist/cjs/resources/helpers.js +52 -0
  17. package/dist/cjs/resources/helpers.js.map +1 -0
  18. package/dist/cjs/resources/hooks.js +98 -0
  19. package/dist/cjs/resources/hooks.js.map +1 -0
  20. package/dist/cjs/resources/index.js +11 -1
  21. package/dist/cjs/resources/index.js.map +1 -1
  22. package/dist/cjs/resources/members.js +3 -33
  23. package/dist/cjs/resources/members.js.map +1 -1
  24. package/dist/cjs/resources/oauth.js +4 -39
  25. package/dist/cjs/resources/oauth.js.map +1 -1
  26. package/dist/cjs/resources/runs.js +90 -0
  27. package/dist/cjs/resources/runs.js.map +1 -0
  28. package/dist/cjs/resources/tasks.js +137 -0
  29. package/dist/cjs/resources/tasks.js.map +1 -0
  30. package/dist/cjs/resources/tokens.js +5 -36
  31. package/dist/cjs/resources/tokens.js.map +1 -1
  32. package/dist/cjs/resources/views.js +5 -40
  33. package/dist/cjs/resources/views.js.map +1 -1
  34. package/dist/cjs/resources/workspaces.js +6 -48
  35. package/dist/cjs/resources/workspaces.js.map +1 -1
  36. package/dist/cjs/types/agents.js +3 -0
  37. package/dist/cjs/types/agents.js.map +1 -0
  38. package/dist/cjs/types/channels.js +3 -0
  39. package/dist/cjs/types/channels.js.map +1 -0
  40. package/dist/cjs/types/hooks.js +3 -0
  41. package/dist/cjs/types/hooks.js.map +1 -0
  42. package/dist/cjs/types/index.js +5 -0
  43. package/dist/cjs/types/index.js.map +1 -1
  44. package/dist/cjs/types/runs.js +3 -0
  45. package/dist/cjs/types/runs.js.map +1 -0
  46. package/dist/cjs/types/tasks.js +23 -0
  47. package/dist/cjs/types/tasks.js.map +1 -0
  48. package/dist/esm/airstore.js +42 -21
  49. package/dist/esm/airstore.js.map +1 -1
  50. package/dist/esm/index.js +7 -0
  51. package/dist/esm/index.js.map +1 -1
  52. package/dist/esm/resources/access-log.js +3 -55
  53. package/dist/esm/resources/access-log.js.map +1 -1
  54. package/dist/esm/resources/agents.js +55 -0
  55. package/dist/esm/resources/agents.js.map +1 -0
  56. package/dist/esm/resources/channels.js +46 -0
  57. package/dist/esm/resources/channels.js.map +1 -0
  58. package/dist/esm/resources/connections.js +6 -37
  59. package/dist/esm/resources/connections.js.map +1 -1
  60. package/dist/esm/resources/filesystem.js +5 -53
  61. package/dist/esm/resources/filesystem.js.map +1 -1
  62. package/dist/esm/resources/helpers.js +47 -0
  63. package/dist/esm/resources/helpers.js.map +1 -0
  64. package/dist/esm/resources/hooks.js +94 -0
  65. package/dist/esm/resources/hooks.js.map +1 -0
  66. package/dist/esm/resources/index.js +5 -0
  67. package/dist/esm/resources/index.js.map +1 -1
  68. package/dist/esm/resources/members.js +3 -33
  69. package/dist/esm/resources/members.js.map +1 -1
  70. package/dist/esm/resources/oauth.js +4 -39
  71. package/dist/esm/resources/oauth.js.map +1 -1
  72. package/dist/esm/resources/runs.js +86 -0
  73. package/dist/esm/resources/runs.js.map +1 -0
  74. package/dist/esm/resources/tasks.js +133 -0
  75. package/dist/esm/resources/tasks.js.map +1 -0
  76. package/dist/esm/resources/tokens.js +5 -36
  77. package/dist/esm/resources/tokens.js.map +1 -1
  78. package/dist/esm/resources/views.js +5 -40
  79. package/dist/esm/resources/views.js.map +1 -1
  80. package/dist/esm/resources/workspaces.js +6 -48
  81. package/dist/esm/resources/workspaces.js.map +1 -1
  82. package/dist/esm/types/agents.js +2 -0
  83. package/dist/esm/types/agents.js.map +1 -0
  84. package/dist/esm/types/channels.js +2 -0
  85. package/dist/esm/types/channels.js.map +1 -0
  86. package/dist/esm/types/hooks.js +2 -0
  87. package/dist/esm/types/hooks.js.map +1 -0
  88. package/dist/esm/types/index.js +5 -0
  89. package/dist/esm/types/index.js.map +1 -1
  90. package/dist/esm/types/runs.js +2 -0
  91. package/dist/esm/types/runs.js.map +1 -0
  92. package/dist/esm/types/tasks.js +20 -0
  93. package/dist/esm/types/tasks.js.map +1 -0
  94. package/dist/types/airstore.d.ts +37 -21
  95. package/dist/types/airstore.d.ts.map +1 -1
  96. package/dist/types/index.d.ts +11 -0
  97. package/dist/types/index.d.ts.map +1 -1
  98. package/dist/types/resources/access-log.d.ts +3 -55
  99. package/dist/types/resources/access-log.d.ts.map +1 -1
  100. package/dist/types/resources/agents.d.ts +25 -0
  101. package/dist/types/resources/agents.d.ts.map +1 -0
  102. package/dist/types/resources/channels.d.ts +21 -0
  103. package/dist/types/resources/channels.d.ts.map +1 -0
  104. package/dist/types/resources/connections.d.ts +6 -37
  105. package/dist/types/resources/connections.d.ts.map +1 -1
  106. package/dist/types/resources/filesystem.d.ts +5 -53
  107. package/dist/types/resources/filesystem.d.ts.map +1 -1
  108. package/dist/types/resources/helpers.d.ts +5 -0
  109. package/dist/types/resources/helpers.d.ts.map +1 -0
  110. package/dist/types/resources/hooks.d.ts +23 -0
  111. package/dist/types/resources/hooks.d.ts.map +1 -0
  112. package/dist/types/resources/index.d.ts +5 -0
  113. package/dist/types/resources/index.d.ts.map +1 -1
  114. package/dist/types/resources/members.d.ts +3 -33
  115. package/dist/types/resources/members.d.ts.map +1 -1
  116. package/dist/types/resources/oauth.d.ts +4 -39
  117. package/dist/types/resources/oauth.d.ts.map +1 -1
  118. package/dist/types/resources/runs.d.ts +25 -0
  119. package/dist/types/resources/runs.d.ts.map +1 -0
  120. package/dist/types/resources/tasks.d.ts +46 -0
  121. package/dist/types/resources/tasks.d.ts.map +1 -0
  122. package/dist/types/resources/tokens.d.ts +5 -36
  123. package/dist/types/resources/tokens.d.ts.map +1 -1
  124. package/dist/types/resources/views.d.ts +5 -40
  125. package/dist/types/resources/views.d.ts.map +1 -1
  126. package/dist/types/resources/workspaces.d.ts +6 -48
  127. package/dist/types/resources/workspaces.d.ts.map +1 -1
  128. package/dist/types/types/agents.d.ts +40 -0
  129. package/dist/types/types/agents.d.ts.map +1 -0
  130. package/dist/types/types/channels.d.ts +20 -0
  131. package/dist/types/types/channels.d.ts.map +1 -0
  132. package/dist/types/types/hooks.d.ts +57 -0
  133. package/dist/types/types/hooks.d.ts.map +1 -0
  134. package/dist/types/types/index.d.ts +5 -0
  135. package/dist/types/types/index.d.ts.map +1 -1
  136. package/dist/types/types/runs.d.ts +64 -0
  137. package/dist/types/types/runs.d.ts.map +1 -0
  138. package/dist/types/types/tasks.d.ts +205 -0
  139. package/dist/types/types/tasks.d.ts.map +1 -0
  140. package/package.json +8 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @airstore/sdk
2
2
 
3
- Official TypeScript SDK for the [Airstore](https://airstore.ai) API. Provision workspaces, manage connections, configure source views, and generate mount tokens — all from your backend.
3
+ Official TypeScript SDK for the [Airstore](https://airstore.ai) API. Create workspaces, connect data sources, run agents, and observe everything — all from your backend.
4
4
 
5
5
  ## Installation
6
6
 
@@ -13,322 +13,293 @@ npm install @airstore/sdk
13
13
  ```typescript
14
14
  import Airstore from '@airstore/sdk';
15
15
 
16
- const airstore = new Airstore({
17
- apiKey: 'org_...', // or set AIRSTORE_API_KEY env var
18
- });
19
-
20
- const workspace = await airstore.workspaces.create({ name: 'user-123' });
21
- console.log(workspace.external_id);
22
- ```
23
-
24
- ## Full Provisioning Flow
16
+ const airstore = new Airstore({ apiKey: process.env.AIRSTORE_API_KEY });
25
17
 
26
- This is the typical flow when a new user signs up on your platform:
18
+ // Create a workspace
19
+ const ws = await airstore.workspaces.create({ name: 'user-123' });
27
20
 
28
- ```typescript
29
- import Airstore from '@airstore/sdk';
21
+ // Create an agent
22
+ const agent = await airstore.agents.create(ws.external_id, {
23
+ agentKey: 'support-agent',
24
+ name: 'Support Agent',
25
+ runner: 'claude_code',
26
+ config: { model: 'claude-sonnet-4-6' },
27
+ });
30
28
 
31
- const airstore = new Airstore({ apiKey: process.env.AIRSTORE_API_KEY });
29
+ // Submit a task
30
+ const { task, run_id } = await airstore.tasks.create(ws.external_id, {
31
+ message: 'Summarize recent support tickets',
32
+ agentId: agent.id,
33
+ });
32
34
 
33
- async function provisionUser(
34
- userId: string,
35
- gmailTokens: { accessToken: string; refreshToken: string },
36
- ) {
37
- // 1. Create a workspace
38
- const ws = await airstore.workspaces.create({ name: `user-${userId}` });
39
-
40
- // 2. Add a member (so we can create a scoped token)
41
- const member = await airstore.members.create(ws.external_id, {
42
- email: `${userId}@internal`,
43
- name: userId,
44
- role: 'member',
45
- });
46
-
47
- // 3. Connect Gmail with existing OAuth tokens
48
- await airstore.connections.create(ws.external_id, {
49
- integrationType: 'gmail',
50
- accessToken: gmailTokens.accessToken,
51
- refreshToken: gmailTokens.refreshToken,
52
- });
53
-
54
- // 4. Set up source views for what the agent should see
55
- await airstore.views.create(ws.external_id, {
56
- integration: 'gmail',
57
- name: 'Recent Emails',
58
- guidance: 'Last 7 days of emails from the inbox',
59
- outputFormat: 'folder',
60
- });
61
-
62
- // 5. Generate a mount token for the user's VM
63
- const token = await airstore.tokens.create(ws.external_id, {
64
- email: `${userId}@internal`,
65
- name: 'vm-mount',
66
- });
67
-
68
- // 6. Pass this to the VM:
69
- // airstore start --token <token.token>
70
- return {
71
- workspaceId: ws.external_id,
72
- mountToken: token.token,
73
- };
74
- }
35
+ // Poll for logs and events
36
+ const batch = await airstore.tasks.streamEvents(ws.external_id, task.id);
37
+ console.log(batch.logs);
75
38
  ```
76
39
 
77
40
  ## Configuration
78
41
 
79
42
  ```typescript
80
43
  const airstore = new Airstore({
81
- // Required org token or cluster admin token
82
- apiKey: 'org_...',
83
-
84
- // Override the base URL (default: https://api.airstore.ai/api/v1)
85
- baseURL: 'https://api.airstore.ai/api/v1',
86
-
87
- // Request timeout in ms (default: 60000)
88
- timeout: 30_000,
89
-
90
- // Max retries for 429/5xx errors (default: 2)
91
- maxRetries: 3,
92
-
93
- // Default headers for every request
94
- defaultHeaders: { 'X-Custom-Header': 'value' },
44
+ apiKey: 'org_...', // or set AIRSTORE_API_KEY env var
45
+ baseURL: 'https://api.airstore.ai/api/v1', // or AIRSTORE_BASE_URL
46
+ timeout: 30_000, // request timeout in ms (default: 60000)
47
+ maxRetries: 3, // retries for 429/5xx (default: 2)
95
48
  });
96
49
  ```
97
50
 
98
- ### Environment Variables
99
-
100
- | Variable | Description |
101
- |---|---|
102
- | `AIRSTORE_API_KEY` | Default API key if not passed to constructor |
103
- | `AIRSTORE_BASE_URL` | Default base URL if not passed to constructor |
104
-
105
51
  ## API Reference
106
52
 
107
- ### Workspaces
53
+ ### Agents
108
54
 
109
55
  ```typescript
110
56
  // Create
111
- const ws = await airstore.workspaces.create({ name: 'my-workspace' });
57
+ const agent = await airstore.agents.create(wsId, {
58
+ agentKey: 'my-agent',
59
+ name: 'My Agent',
60
+ runner: 'claude_code',
61
+ config: { model: 'claude-sonnet-4-6', system_prompt: 'You are helpful.' },
62
+ });
112
63
 
113
- // List all (org tokens only see their tenant's workspaces)
114
- const workspaces = await airstore.workspaces.list();
64
+ // List
65
+ const agents = await airstore.agents.list(wsId);
115
66
 
116
- // Retrieve by ID
117
- const ws = await airstore.workspaces.retrieve('ws_abc123');
67
+ // Retrieve
68
+ const a = await airstore.agents.retrieve(wsId, agentId);
118
69
 
119
- // Delete
120
- await airstore.workspaces.del('ws_abc123');
70
+ // Update
71
+ await airstore.agents.update(wsId, agentId, { name: 'Renamed Agent' });
72
+
73
+ // Delete (also removes bound hooks)
74
+ await airstore.agents.delete(wsId, agentId);
121
75
  ```
122
76
 
123
- ### Connections
77
+ ### Tasks
124
78
 
125
79
  ```typescript
126
- // Create with existing OAuth tokens
127
- const conn = await airstore.connections.create('ws_abc123', {
128
- integrationType: 'gmail',
129
- accessToken: '...',
130
- refreshToken: '...',
80
+ // Create a task (returns accepted response with task + run_id)
81
+ const { task, run_id } = await airstore.tasks.create(wsId, {
82
+ message: 'Do something',
83
+ agentId: agent.id,
84
+ idempotencyKey: 'unique-key', // optional, server generates if omitted
85
+ sessionId: 'session-abc', // optional, groups related tasks
86
+ timeoutMs: 120_000, // optional
87
+ policy: { // optional execution policy
88
+ host: 'sandbox',
89
+ security: 'allowlist',
90
+ runtimeType: 'gvisor',
91
+ workspaceAccess: 'rw',
92
+ },
131
93
  });
132
94
 
133
- // Create with API key
134
- const conn = await airstore.connections.create('ws_abc123', {
135
- integrationType: 'github',
136
- apiKey: 'ghp_...',
95
+ // List with filters
96
+ const page = await airstore.tasks.list(wsId, {
97
+ state: ['running', 'idle'],
98
+ agentId: agent.id,
99
+ limit: 20,
137
100
  });
138
101
 
139
- // List
140
- const connections = await airstore.connections.list('ws_abc123');
102
+ // Retrieve
103
+ const t = await airstore.tasks.retrieve(wsId, taskId);
141
104
 
142
- // Delete
143
- await airstore.connections.del('ws_abc123', 'conn_abc123');
144
- ```
105
+ // Cancel a running task
106
+ await airstore.tasks.cancel(wsId, taskId);
145
107
 
146
- ### Source Views
108
+ // Archive a completed/idle task
109
+ await airstore.tasks.archive(wsId, taskId);
110
+ ```
147
111
 
148
- Source views come in two modes: **smart** (LLM-inferred from natural language) and **query** (structured per-integration filters).
112
+ ### Log Streaming & Events
149
113
 
150
114
  ```typescript
151
- // Smart mode describe what you want in natural language
152
- const view = await airstore.views.create('ws_abc123', {
153
- integration: 'gmail',
154
- name: 'Important Emails',
155
- guidance: 'Emails marked as important from the last month',
156
- outputFormat: 'folder', // or 'file'
157
- });
115
+ // Fetch logs for a task (cursor-based for incremental reads)
116
+ const logs = await airstore.tasks.listLogs(wsId, taskId);
158
117
 
159
- // Query mode auto-detected when filter is provided
160
- const view2 = await airstore.views.create('ws_abc123', {
161
- integration: 'gmail',
162
- name: 'Unread from boss',
163
- filter: { from: 'boss@company.com', is_unread: true },
164
- });
118
+ // Composite event stream: task/run state + logs + run events in one call
119
+ let logCursor = 0;
120
+ let eventCursor = 0;
165
121
 
166
- // Query mode with GitHub content types
167
- const prView = await airstore.views.create('ws_abc123', {
168
- integration: 'github',
169
- name: 'Open PRs',
170
- filter: {
171
- repo: 'acme/api',
172
- type: 'prs',
173
- state: 'open',
174
- content_type: 'diff', // 'markdown' | 'diff' | 'json' | 'raw'
175
- },
122
+ const batch = await airstore.tasks.streamEvents(wsId, taskId, {
123
+ logCursor,
124
+ runEventCursor: eventCursor,
176
125
  });
177
126
 
178
- // List all
179
- const views = await airstore.views.list('ws_abc123');
127
+ // Use next cursors for subsequent polls
128
+ logCursor = batch.next_log_cursor;
129
+ eventCursor = batch.next_run_event_cursor;
130
+ ```
180
131
 
181
- // Retrieve by path
182
- const found = await airstore.views.retrieve('ws_abc123', '/sources/gmail/Important Emails');
132
+ ### Runs
183
133
 
184
- // Update
185
- const updated = await airstore.views.update('ws_abc123', 'view_abc', {
186
- guidance: 'Updated guidance text',
187
- });
134
+ ```typescript
135
+ // List runs
136
+ const runs = await airstore.runs.list(wsId, { status: 'running' });
188
137
 
189
- // Sync re-execute the query and refresh cached files
190
- const result = await airstore.views.sync('ws_abc123', 'view_abc');
191
- console.log(`${result.results_count} total, ${result.new_results} new`);
138
+ // Retrieve a run
139
+ const run = await airstore.runs.retrieve(wsId, runId);
192
140
 
193
- // Delete
194
- await airstore.views.del('ws_abc123', 'view_abc');
141
+ // List snapshots (intermediate state)
142
+ const snapshots = await airstore.runs.listSnapshots(wsId, runId);
143
+
144
+ // List execution events
145
+ const events = await airstore.runs.listEvents(wsId, runId);
146
+
147
+ // Cancel
148
+ await airstore.runs.cancel(wsId, runId);
195
149
  ```
196
150
 
197
- #### Per-integration filter fields
151
+ ### Channels (Follow-Up Messages)
198
152
 
199
- Each integration accepts a typed filter object:
153
+ ```typescript
154
+ // Send a new task to an agent via direct channel
155
+ await airstore.channels.sendDirectAgentMessage(wsId, agentId, {
156
+ message: 'What about the billing tickets?',
157
+ });
200
158
 
201
- | Integration | Key fields |
202
- |---|---|
203
- | `gmail` | `from`, `to`, `subject`, `label`, `newer_than`, `older_than`, `has_attachment`, `is_unread`, `is_starred` |
204
- | `github` | `repo` (required), `type`, `state`, `label`, `author`, `content_type` |
205
- | `gdrive` | `name_contains`, `mime_type`, `shared_with_me`, `starred`, `modified_after`, `modified_before`, `folder_id` |
206
- | `notion` | `search` |
207
- | `slack` | `channel`, `from`, `after`, `before`, `has_link`, `has_reaction` |
208
- | `linear` | `type`, `team`, `state`, `assignee`, `priority`, `label` |
209
- | `posthog` | `type`, `query`, `project_id` |
210
- | `web` | `mode`, `url`, `query`, `include_paths` |
159
+ // Send follow-up input to an active run
160
+ await airstore.channels.sendDirectRunMessage(wsId, runId, {
161
+ message: 'Focus on the last 24 hours',
162
+ taskId: task.id,
163
+ queueMode: 'steer', // 'queue' | 'followup' | 'steer' | 'interrupt'
164
+ });
165
+ ```
211
166
 
212
- ### Tokens
167
+ ### Scheduled Tasks (Cron)
213
168
 
214
169
  ```typescript
215
- // Create a workspace-scoped token (for CLI mounting)
216
- const token = await airstore.tokens.create('ws_abc123', {
217
- email: 'agent@internal',
218
- name: 'vm-mount',
219
- expiresIn: 86400, // optional, seconds
170
+ // Create a schedule
171
+ const schedule = await airstore.tasks.createSchedule(wsId, {
172
+ agentId: agent.id,
173
+ cronExpr: '0 9 * * 1-5', // every weekday at 9am
174
+ timezone: 'America/New_York',
175
+ prompt: 'Summarize overnight support tickets',
220
176
  });
221
- console.log(token.token); // raw value — only shown once
222
177
 
223
- // List tokens (values are never returned)
224
- const tokens = await airstore.tokens.list('ws_abc123');
178
+ // List schedules
179
+ const schedules = await airstore.tasks.listSchedules(wsId);
225
180
 
226
- // Revoke
227
- await airstore.tokens.revoke('ws_abc123', 'tok_abc123');
181
+ // Update (pause, change cron, etc.)
182
+ await airstore.tasks.updateSchedule(wsId, schedule.external_id, {
183
+ active: false,
184
+ });
185
+
186
+ // Delete
187
+ await airstore.tasks.deleteSchedule(wsId, schedule.external_id);
228
188
  ```
229
189
 
230
- ### Members
190
+ ### Hooks (File-System Triggers)
231
191
 
232
192
  ```typescript
233
- // Add a member
234
- const member = await airstore.members.create('ws_abc123', {
235
- email: 'user@example.com',
236
- name: 'Jane Doe',
237
- role: 'member', // 'admin' | 'member' | 'viewer'
193
+ // Create a hook on a source view folder
194
+ const hook = await airstore.hooks.create(wsId, {
195
+ path: '/sources/gmail/Recent Emails',
196
+ prompt: 'Triage this email and draft a reply',
197
+ eventTypes: ['create'],
198
+ agentName: 'Email Triager',
238
199
  });
239
200
 
240
- // List
241
- const members = await airstore.members.list('ws_abc123');
242
-
243
- // Remove
244
- await airstore.members.del('ws_abc123', 'mem_abc123');
201
+ // List / Retrieve / Update / Delete
202
+ const hooks = await airstore.hooks.list(wsId);
203
+ await airstore.hooks.update(wsId, hookId, { active: false });
204
+ await airstore.hooks.delete(wsId, hookId);
245
205
  ```
246
206
 
247
- ### OAuth Sessions
207
+ ### Workspaces
208
+
209
+ ```typescript
210
+ const ws = await airstore.workspaces.create({ name: 'my-workspace' });
211
+ const workspaces = await airstore.workspaces.list();
212
+ const ws2 = await airstore.workspaces.retrieve(wsId);
213
+ await airstore.workspaces.del(wsId);
214
+ ```
248
215
 
249
- For interactive connection setup where users authorize via browser redirect:
216
+ ### Connections
250
217
 
251
218
  ```typescript
252
- // Create an OAuth session
253
- const session = await airstore.oauth.createSession({
219
+ // OAuth tokens
220
+ await airstore.connections.create(wsId, {
254
221
  integrationType: 'gmail',
255
- returnTo: 'https://myapp.com/callback',
222
+ accessToken: '...',
223
+ refreshToken: '...',
256
224
  });
257
- console.log(session.authorize_url); // redirect user here
258
-
259
- // Check status
260
- const status = await airstore.oauth.getSession(session.session_id);
261
225
 
262
- // Or poll until completion (default: 5 min timeout, 2s interval)
263
- const completed = await airstore.oauth.poll(session.session_id, {
264
- timeout: 120_000,
265
- interval: 3_000,
226
+ // API key
227
+ await airstore.connections.create(wsId, {
228
+ integrationType: 'github',
229
+ apiKey: 'ghp_...',
266
230
  });
267
- console.log(completed.connection_id);
268
- ```
269
231
 
270
- ### Filesystem
232
+ const connections = await airstore.connections.list(wsId);
233
+ await airstore.connections.del(wsId, connectionId);
234
+ ```
271
235
 
272
- Read-only access to the virtual filesystem:
236
+ ### Source Views
273
237
 
274
238
  ```typescript
275
- // List directory contents
276
- const entries = await airstore.fs.list('ws_abc123', { path: '/' });
277
-
278
- // Read file contents
279
- const content = await airstore.fs.read('ws_abc123', {
280
- path: '/sources/gmail/inbox/email.txt',
239
+ // Smart mode (LLM-inferred)
240
+ const view = await airstore.views.create(wsId, {
241
+ integration: 'gmail',
242
+ name: 'Important Emails',
243
+ guidance: 'Emails marked as important from the last month',
281
244
  });
282
245
 
283
- // Get directory tree
284
- const tree = await airstore.fs.tree('ws_abc123', {
285
- path: '/',
286
- maxKeys: 100,
246
+ // Query mode (structured filter)
247
+ const view2 = await airstore.views.create(wsId, {
248
+ integration: 'github',
249
+ name: 'Open PRs',
250
+ filter: { repo: 'acme/api', type: 'prs', state: 'open' },
287
251
  });
288
252
 
289
- // Stat a file
290
- const meta = await airstore.fs.stat('ws_abc123', '/sources/gmail/inbox/email.txt');
253
+ // Sync, update, delete
254
+ await airstore.views.sync(wsId, viewId);
255
+ await airstore.views.update(wsId, viewId, { guidance: 'Updated' });
256
+ await airstore.views.del(wsId, viewId);
291
257
  ```
292
258
 
293
- ## Per-Request Options
294
-
295
- Every method accepts an optional last argument for per-request overrides:
259
+ ### Tokens, Members, OAuth
296
260
 
297
261
  ```typescript
298
- const ws = await airstore.workspaces.list({
299
- timeout: 10_000,
300
- maxRetries: 5,
301
- signal: controller.signal,
302
- headers: { 'X-Trace-Id': 'abc' },
262
+ // Tokens (for CLI mounting)
263
+ const token = await airstore.tokens.create(wsId, {
264
+ email: 'agent@internal', name: 'vm-mount',
265
+ });
266
+
267
+ // Members
268
+ const member = await airstore.members.create(wsId, {
269
+ email: 'user@example.com', name: 'Jane', role: 'member',
303
270
  });
271
+
272
+ // Interactive OAuth
273
+ const session = await airstore.oauth.createSession({
274
+ integrationType: 'gmail',
275
+ returnTo: 'https://myapp.com/callback',
276
+ });
277
+ const completed = await airstore.oauth.poll(session.session_id);
304
278
  ```
305
279
 
306
- ## Error Handling
280
+ ### Filesystem
307
281
 
308
- The SDK throws typed errors for easy programmatic handling:
282
+ ```typescript
283
+ const entries = await airstore.fs.list(wsId, { path: '/' });
284
+ const content = await airstore.fs.read(wsId, { path: '/sources/gmail/email.txt' });
285
+ const tree = await airstore.fs.tree(wsId, { path: '/', maxKeys: 100 });
286
+ const meta = await airstore.fs.stat(wsId, '/sources/gmail/email.txt');
287
+ ```
288
+
289
+ ## Error Handling
309
290
 
310
291
  ```typescript
311
- import {
312
- AuthenticationError,
313
- NotFoundError,
314
- RateLimitError,
315
- } from '@airstore/sdk';
292
+ import { NotFoundError, RateLimitError, AuthenticationError } from '@airstore/sdk';
316
293
 
317
294
  try {
318
295
  await airstore.workspaces.retrieve('ws_nonexistent');
319
296
  } catch (err) {
320
- if (err instanceof NotFoundError) {
321
- console.log('Workspace not found');
322
- } else if (err instanceof AuthenticationError) {
323
- console.log('Invalid API key');
324
- } else if (err instanceof RateLimitError) {
325
- console.log('Rate limited, retry after:', err.headers.get('retry-after'));
326
- }
297
+ if (err instanceof NotFoundError) console.log('Not found');
298
+ if (err instanceof RateLimitError) console.log('Rate limited');
299
+ if (err instanceof AuthenticationError) console.log('Bad API key');
327
300
  }
328
301
  ```
329
302
 
330
- ### Error Hierarchy
331
-
332
303
  | Class | Status | Description |
333
304
  |---|---|---|
334
305
  | `AirstoreError` | — | Base error for all SDK errors |
@@ -343,37 +314,43 @@ try {
343
314
  | `APIConnectionError` | — | Network failure |
344
315
  | `APIConnectionTimeoutError` | — | Request timed out |
345
316
 
346
- ## Response Metadata
317
+ ## Per-Request Options
347
318
 
348
- Every response object includes a non-enumerable `lastResponse` property:
319
+ Every method accepts an optional last argument for per-request overrides:
349
320
 
350
321
  ```typescript
351
- const ws = await airstore.workspaces.create({ name: 'test' });
352
- console.log(ws.lastResponse.statusCode); // 200
353
- console.log(ws.lastResponse.requestId); // 'req_abc123'
354
- console.log(ws.lastResponse.headers); // Headers object
322
+ await airstore.workspaces.list({
323
+ timeout: 10_000,
324
+ maxRetries: 5,
325
+ signal: controller.signal,
326
+ headers: { 'X-Trace-Id': 'abc' },
327
+ });
355
328
  ```
356
329
 
357
- ## Automatic Retries
330
+ ## Response Metadata
331
+
332
+ Every response includes a non-enumerable `lastResponse` property:
358
333
 
359
- The SDK automatically retries on transient errors (408, 409, 429, 500, 502, 503, 504) with exponential backoff and jitter. The `Retry-After` header is respected when present.
334
+ ```typescript
335
+ const ws = await airstore.workspaces.create({ name: 'test' });
336
+ ws.lastResponse.statusCode; // 200
337
+ ws.lastResponse.requestId; // 'req_abc123'
338
+ ```
360
339
 
361
340
  ## Raw Requests
362
341
 
363
- For endpoints not yet covered by the SDK, use the escape hatch:
342
+ For endpoints not yet covered by the SDK:
364
343
 
365
344
  ```typescript
366
345
  const response = await airstore.rawRequest('POST', '/some/new/endpoint', {
367
346
  body: { key: 'value' },
368
- timeout: 5_000,
369
347
  });
370
- const data = await response.json();
371
348
  ```
372
349
 
373
350
  ## Requirements
374
351
 
375
352
  - Node.js 18+ (uses native `fetch`)
376
- - TypeScript 5.0+ (for type-only imports)
353
+ - TypeScript 5.0+
377
354
  - Zero runtime dependencies
378
355
 
379
356
  ## License