@orchestration-ai/sdk 0.1.0 → 0.3.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.
Files changed (46) hide show
  1. package/README.md +280 -207
  2. package/dist/cjs/app-builder.d.ts +39 -0
  3. package/dist/cjs/app-builder.d.ts.map +1 -0
  4. package/dist/cjs/app-builder.js +589 -0
  5. package/dist/cjs/app-builder.js.map +1 -0
  6. package/dist/cjs/oauth-utils.d.ts +41 -0
  7. package/dist/cjs/oauth-utils.d.ts.map +1 -0
  8. package/dist/cjs/oauth-utils.js +194 -0
  9. package/dist/cjs/oauth-utils.js.map +1 -0
  10. package/dist/cjs/services.d.ts +33 -0
  11. package/dist/cjs/services.d.ts.map +1 -0
  12. package/dist/cjs/services.js +121 -0
  13. package/dist/cjs/services.js.map +1 -0
  14. package/dist/cjs/shared-types.d.ts +66 -0
  15. package/dist/cjs/shared-types.d.ts.map +1 -0
  16. package/dist/cjs/shared-types.js +30 -0
  17. package/dist/cjs/shared-types.js.map +1 -0
  18. package/dist/cjs/types.gen.d.ts +28 -0
  19. package/dist/cjs/types.gen.d.ts.map +1 -1
  20. package/dist/esm/app-builder.d.ts +39 -0
  21. package/dist/esm/app-builder.d.ts.map +1 -0
  22. package/dist/esm/app-builder.js +547 -0
  23. package/dist/esm/app-builder.js.map +1 -0
  24. package/dist/esm/oauth-utils.d.ts +41 -0
  25. package/dist/esm/oauth-utils.d.ts.map +1 -0
  26. package/dist/esm/oauth-utils.js +184 -0
  27. package/dist/esm/oauth-utils.js.map +1 -0
  28. package/dist/esm/services.d.ts +33 -0
  29. package/dist/esm/services.d.ts.map +1 -0
  30. package/dist/esm/services.js +104 -0
  31. package/dist/esm/services.js.map +1 -0
  32. package/dist/esm/shared-types.d.ts +66 -0
  33. package/dist/esm/shared-types.d.ts.map +1 -0
  34. package/dist/esm/shared-types.js +25 -0
  35. package/dist/esm/shared-types.js.map +1 -0
  36. package/dist/esm/types.gen.d.ts +28 -0
  37. package/dist/esm/types.gen.d.ts.map +1 -1
  38. package/package.json +73 -10
  39. package/dist/cjs/index.d.ts +0 -3
  40. package/dist/cjs/index.d.ts.map +0 -1
  41. package/dist/cjs/index.js +0 -72
  42. package/dist/cjs/index.js.map +0 -1
  43. package/dist/esm/index.d.ts +0 -3
  44. package/dist/esm/index.d.ts.map +0 -1
  45. package/dist/esm/index.js +0 -3
  46. package/dist/esm/index.js.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @orchestration-ai/sdk
2
2
 
3
- TypeScript SDK for [Orchestration AI](https://orchestration-ai.com) The Operating System for AI-Powered Businesses.
3
+ TypeScript SDK for [Orchestration AI](https://orchestration-ai.com) - The Operating System for AI-Powered Businesses.
4
4
 
5
5
  Works in both **Node.js** and the **browser** using the same package.
6
6
 
@@ -10,306 +10,379 @@ Works in both **Node.js** and the **browser** using the same package.
10
10
  npm install @orchestration-ai/sdk
11
11
  ```
12
12
 
13
- ## Quick Start
13
+ ## Building Applications
14
14
 
15
- The SDK exports a pre-configured `client` with the correct base URL. Just import and use:
15
+ The SDK provides everything you need to build Orchestration AI applications that expose services and tools to agents.
16
16
 
17
- ```typescript
18
- import { client } from '@orchestration-ai/sdk/client.gen';
19
- import { workspaceFind } from '@orchestration-ai/sdk';
17
+ ### Quick Start - Define an Application
20
18
 
21
- const response = await workspaceFind();
22
- console.log(response.data);
19
+ ```typescript
20
+ import { createApp, defineService } from '@orchestration-ai/sdk/app-builder';
21
+
22
+ createApp()
23
+ .permissions([
24
+ { permission_name: "role_agent_reader", justification: "Read agent context." },
25
+ { permission_name: "role_agent_writer", justification: "Register endpoints." },
26
+ ])
27
+ .service(defineService({
28
+ unique_name: "my-service",
29
+ service_name: "My Service",
30
+ service_description: "Does useful things for agents.",
31
+ defaultSettings: [
32
+ { setting_name: "API_KEY", setting_description: "External API key", setting_type: "Secret", text_value: "" },
33
+ ],
34
+ description: [
35
+ {
36
+ path: "do_thing",
37
+ method: "POST",
38
+ description: "Performs an action.",
39
+ parameters: {
40
+ input: { type: "string", optional: false, description: "The input value." },
41
+ },
42
+ },
43
+ ],
44
+ tools: {
45
+ do_thing: async (body, context, engineClient, apiClient) => {
46
+ // body is the request payload
47
+ // context contains the agent identity
48
+ // engineClient is for engine calls (sendMessages, getContext)
49
+ // apiClient is for API calls (settingFindByAgent, endpointCreate, etc.)
50
+ return { result: `Processed: ${body.input}` };
51
+ },
52
+ },
53
+ }))
54
+ .listen(3001);
23
55
  ```
24
56
 
25
- ## Authentication
57
+ Visit `http://localhost:3001/explore` to see your services and test tools interactively.
26
58
 
27
- ### Node.js (Server-Side)
59
+ ### Application Structure
60
+
61
+ An application consists of:
62
+
63
+ - **Permissions** - Roles the app requires (granted on installation)
64
+ - **Services** - Each service exposes tools that agents can call
65
+
66
+ ### Service Definition
28
67
 
29
- For server-to-server authentication, use the **client_credentials** OAuth flow. The SDK manages token acquisition and refresh automatically:
68
+ Each service has:
69
+
70
+ | Field | Description |
71
+ |-------|-------------|
72
+ | `unique_name` | URL-safe identifier |
73
+ | `service_name` | Human-readable name |
74
+ | `service_description` | What the service does |
75
+ | `defaultSettings` | Settings created when the service is installed |
76
+ | `description` | Static array or dynamic function returning tool descriptions |
77
+ | `touch` | Called when the service's context may have changed |
78
+ | `tools` | Handler functions for each tool |
79
+
80
+ ### Handler Signatures
81
+
82
+ All handlers receive the engine client and API client:
30
83
 
31
84
  ```typescript
32
- import { client } from '@orchestration-ai/sdk/client.gen';
33
- import { setupClientCredentials, workspaceFind } from '@orchestration-ai/sdk';
85
+ // Tool handler
86
+ (body: any, context: Context, engineClient: Client, apiClient: Client) => unknown | Promise<unknown>
34
87
 
35
- // Setup once — tokens are fetched and refreshed automatically
36
- setupClientCredentials(client, {
37
- client_id: 'your-client-id',
38
- client_secret: 'your-client-secret',
39
- scope: 'role_admin', // any supported role as scope
40
- });
88
+ // Touch handler
89
+ (context: Context, engineClient: Client, apiClient: Client) => void | Promise<void>
41
90
 
42
- // All requests are now authenticated
43
- const workspaces = await workspaceFind();
91
+ // Description handler (dynamic)
92
+ (context: Context, engineClient: Client, apiClient: Client) => ServiceDescription | Promise<ServiceDescription>
44
93
  ```
45
94
 
46
- The SDK will:
47
- - Automatically obtain an access token via `client_credentials` on the first request
48
- - Re-fetch the token when it expires (with a 30s buffer)
49
- - Retry once on 401 responses with a fresh token
50
- - Deduplicate concurrent token requests
95
+ ### Two Clients
51
96
 
52
- The `scope` parameter accepts any supported role (e.g. `role_admin`, `role_workspace_writer`, `role_agent_reader`). See [Roles & Permissions](#roles--permissions) for the full list.
97
+ The app-builder provides two pre-configured clients to every handler:
53
98
 
54
- ### Browser (Client-Side)
99
+ | Client | Purpose | Auth |
100
+ |--------|---------|------|
101
+ | `engineClient` | Internal engine calls (`sendMessages`, `getContext`) | Bearer access key |
102
+ | `apiClient` | Public API calls (`settingFindByAgent`, `endpointCreate`, `linkCreate`) | OAuth client_credentials |
103
+
104
+ ### Static vs Dynamic Descriptions
55
105
 
56
- Browser apps should never expose a `client_secret`. The SDK provides utilities to manage the OAuth redirect flow and token storage. Token acquisition and refresh should be handled by your backend.
106
+ **Static** - TypeScript enforces that `tools` keys match the `path` values in `description`:
57
107
 
58
108
  ```typescript
59
- import { client } from '@orchestration-ai/sdk/client.gen';
60
- import {
61
- setupBrowserAuth,
62
- initiateLogin,
63
- parseLoginRedirect,
64
- saveLogin,
65
- getCurrentLogin,
66
- isLoginExpired,
67
- logout,
68
- } from '@orchestration-ai/sdk';
69
-
70
- // Attach stored tokens to all requests automatically
71
- // Optionally provide a refresh callback for automatic token renewal
72
- setupBrowserAuth(client, {
73
- onRefreshToken: async () => {
74
- // Call your backend to refresh the token
75
- const response = await fetch('/api/auth/refresh');
76
- if (!response.ok) return null;
77
- return response.json(); // must return OAuthTokens shape
109
+ import { defineService } from '@orchestration-ai/sdk/app-builder';
110
+
111
+ export const myService = defineService({
112
+ unique_name: "calculator",
113
+ service_name: "Calculator",
114
+ service_description: "Math operations.",
115
+ description: [
116
+ { path: "add", method: "POST", description: "Adds two numbers.", parameters: { a: { type: "number", optional: false, description: "First number" }, b: { type: "number", optional: false, description: "Second number" } } },
117
+ ],
118
+ tools: {
119
+ add: (body) => ({ result: body.a + body.b }),
120
+ // TypeScript error if you add a tool not in description, or miss one
121
+ },
122
+ });
123
+ ```
124
+
125
+ **Dynamic** - When the description depends on context/settings:
126
+
127
+ ```typescript
128
+ import { defineServiceWithDynamicDescription } from '@orchestration-ai/sdk/app-builder';
129
+
130
+ export const myService = defineServiceWithDynamicDescription({
131
+ unique_name: "conditional",
132
+ service_name: "Conditional Service",
133
+ service_description: "Tools depend on settings.",
134
+ description: async (context, engineClient, apiClient) => {
135
+ const { data } = await settingFindByAgent({ client: apiClient, path: { ... } });
136
+ // Return different tools based on settings
137
+ return [...];
138
+ },
139
+ tools: {
140
+ tool_a: (body, context) => { ... },
141
+ tool_b: (body, context) => { ... },
78
142
  },
79
143
  });
80
144
  ```
81
145
 
82
- #### OAuth Login Flow
146
+ ### Touch Handler
83
147
 
84
- **Step 1: Initiate login (redirects the browser)**
148
+ Called by the engine when a service's context may have changed. Use it to register endpoints or links:
85
149
 
86
150
  ```typescript
87
- import { client } from '@orchestration-ai/sdk/client.gen';
88
- import { initiateLogin } from '@orchestration-ai/sdk';
89
-
90
- function handleLoginClick() {
91
- initiateLogin(client.getConfig().baseURL, {
92
- client_id: 'your-client-id',
93
- redirect_uri: 'https://your-app.com/callback',
94
- scope: 'role_admin', // any supported role as scope
95
- }, 'optional-state-value');
151
+ touch: async (context, engineClient, apiClient) => {
152
+ await endpointCreate({
153
+ client: apiClient,
154
+ path: {
155
+ workspaceId: context.identity.workspaceId,
156
+ orchestrationId: context.identity.orchestrationId,
157
+ agentId: context.identity.agentId,
158
+ },
159
+ body: {
160
+ description: "Webhook for receiving events.",
161
+ endpoint: `https://my-app.com/webhook/${context.identity.layerId}`,
162
+ },
163
+ });
96
164
  }
97
165
  ```
98
166
 
99
- This redirects the user to the Orchestration AI login page.
167
+ ### Settings
100
168
 
101
- **Step 2: Handle the redirect callback**
169
+ Three types of settings:
170
+
171
+ | Type | Use Case |
172
+ |------|----------|
173
+ | `Text` | General configuration values |
174
+ | `Boolean` | Feature flags, toggles |
175
+ | `Secret` | API keys, passwords (treated securely by the engine) |
102
176
 
103
- On your callback page (e.g. `/callback`), parse the redirect result and exchange the code via your backend:
177
+ Utility functions for reading settings:
104
178
 
105
179
  ```typescript
106
- import { parseLoginRedirect, saveLogin } from '@orchestration-ai/sdk';
180
+ import { getBooleanSetting, getTextSetting, getSecretSetting } from '@orchestration-ai/sdk/services';
107
181
 
108
- const result = parseLoginRedirect();
182
+ const enabled = getBooleanSetting(settings, "FEATURE_ENABLED");
183
+ const host = getTextSetting(settings, "SMTP_HOST");
184
+ const apiKey = getSecretSetting(settings, "API_KEY");
185
+ ```
109
186
 
110
- if (result.granted) {
111
- // Send the code to your backend to exchange for tokens securely
112
- // IMPORTANT: pass the same redirect_uri used in initiateLogin
113
- const tokens = await fetch('/api/auth/exchange', {
114
- method: 'POST',
115
- body: JSON.stringify({
116
- code: result.code,
117
- redirect_uri: 'https://your-app.com/callback',
118
- }),
119
- }).then(r => r.json());
187
+ ### Sending Messages to Agents
120
188
 
121
- // Save the tokens setupBrowserAuth will attach them to future requests
122
- saveLogin(tokens);
123
- } else {
124
- console.error('Login denied:', result.error, result.error_description);
125
- }
189
+ Use the engine client to send messages:
190
+
191
+ ```typescript
192
+ import { sendMessages } from '@orchestration-ai/sdk/services';
193
+
194
+ const response = await sendMessages(
195
+ agentId,
196
+ layerIndex,
197
+ [{ message: "Hello from my service" }],
198
+ context.identity.layerId,
199
+ engineClient
200
+ );
126
201
  ```
127
202
 
128
- #### Token Refresh
203
+ ### Getting Agent Context
204
+
205
+ ```typescript
206
+ import { getContext } from '@orchestration-ai/sdk/services';
207
+
208
+ const context = await getContext(layerId, engineClient);
209
+ // context.identity.agentId, .layerId, .orchestrationId, .workspaceId, etc.
210
+ ```
129
211
 
130
- If you provided `onRefreshToken` to `setupBrowserAuth`, token refresh is handled automatically — both proactively when the token is about to expire and reactively on 401 responses.
212
+ ### Custom Endpoints
131
213
 
132
- If you prefer to handle refresh manually:
214
+ Access the underlying Express app and HTTP server for custom routes or WebSockets:
133
215
 
134
216
  ```typescript
135
- import { isLoginExpired, saveLogin, logout } from '@orchestration-ai/sdk';
136
-
137
- if (isLoginExpired()) {
138
- const response = await fetch('/api/auth/refresh');
139
- if (response.ok) {
140
- saveLogin(await response.json());
141
- } else {
142
- logout();
143
- }
144
- }
217
+ const app = createApp().service(myService);
218
+
219
+ // Custom route
220
+ app.expressApp.post("/custom/:id", (req, res) => { ... });
221
+
222
+ // WebSocket
223
+ import { Server } from "socket.io";
224
+ const io = new Server(app.httpServer, { path: "/ws" });
225
+ io.on("connection", (socket) => { ... });
226
+
227
+ app.listen(3001);
145
228
  ```
146
229
 
147
- #### Logout
230
+ ### Explore Page
148
231
 
149
- ```typescript
150
- import { logout } from '@orchestration-ai/sdk';
232
+ The `/explore` endpoint renders an interactive page showing all services, tools, and permissions. You can test tools directly from the browser.
233
+
234
+ Disable in production:
151
235
 
152
- logout(); // Clears stored tokens from localStorage
236
+ ```typescript
237
+ createApp({ explore: false }).service(...).listen(3001);
153
238
  ```
154
239
 
155
- ## API Usage Examples
240
+ ## Client Factories
156
241
 
157
- ### Workspaces
242
+ ### createEngineClient
243
+
244
+ For calling engine internal endpoints:
158
245
 
159
246
  ```typescript
160
- import { workspaceFind, workspaceCreate, workspaceFindById } from '@orchestration-ai/sdk';
247
+ import { createEngineClient } from '@orchestration-ai/sdk/services';
161
248
 
162
- // List workspaces
163
- const { data } = await workspaceFind({ query: { limit: 10, offset: 0 } });
249
+ // Production (default URL)
250
+ const client = createEngineClient(accessKey);
164
251
 
165
- // Create a workspace
166
- const { data: workspace } = await workspaceCreate({
167
- body: { workspace_name: 'My Workspace' },
168
- });
252
+ // Custom URL
253
+ const client = createEngineClient("https://my-engine.com", accessKey);
169
254
 
170
- // Get a workspace by ID
171
- const { data: ws } = await workspaceFindById({ path: { id: 'workspace-id' } });
255
+ // Nullable URL (falls back to production)
256
+ const client = createEngineClient(process.env.ENGINE_URL ?? null, accessKey);
172
257
  ```
173
258
 
174
- ### Orchestrations
259
+ ### createApplicationClient
260
+
261
+ For calling another OAI application's services:
175
262
 
176
263
  ```typescript
177
- import {
178
- orchestrationFindByWorkspace,
179
- orchestrationCreate,
180
- } from '@orchestration-ai/sdk';
181
-
182
- // List orchestrations in a workspace
183
- const { data } = await orchestrationFindByWorkspace({
184
- path: { workspaceId: 'workspace-id' },
185
- });
264
+ import { createApplicationClient, listServices, callServiceTool } from '@orchestration-ai/sdk/services';
186
265
 
187
- // Create an orchestration
188
- const { data: orch } = await orchestrationCreate({
189
- path: { workspaceId: 'workspace-id' },
190
- body: {
191
- orchestration_name: 'My Orchestration',
192
- orchestration_description: 'Handles customer support',
193
- },
194
- });
266
+ const client = createApplicationClient(application, layerId);
267
+ const services = await listServices(client);
268
+ const result = await callServiceTool("service-name", "tool-path", client, { body: { key: "value" } });
195
269
  ```
196
270
 
197
- ### Agents
271
+ ### createApiClient
272
+
273
+ For making authenticated API calls with OAuth:
198
274
 
199
275
  ```typescript
200
- import { agentFindByOrchestration, agentCreate } from '@orchestration-ai/sdk';
276
+ import { createApiClient } from '@orchestration-ai/sdk/services';
277
+ import { setupClientCredentials } from '@orchestration-ai/sdk/oauth-utils';
201
278
 
202
- // List agents
203
- const { data } = await agentFindByOrchestration({
204
- path: { workspaceId: 'ws-id', orchestrationId: 'orch-id' },
279
+ const apiClient = createApiClient();
280
+ setupClientCredentials(apiClient, {
281
+ client_id: accessKey,
282
+ client_secret: `${accessKey}:${workspaceOwnerId}`,
205
283
  });
206
284
 
207
- // Create an agent
208
- const { data: agent } = await agentCreate({
209
- path: { workspaceId: 'ws-id', orchestrationId: 'orch-id' },
210
- body: {
211
- agent_name: 'Support Agent',
212
- agent_description: 'Handles tier 1 support tickets',
213
- },
285
+ // Now use with sdk.gen functions
286
+ await settingFindByAgent({ client: apiClient, path: { ... } });
287
+ ```
288
+
289
+ ## Authentication
290
+
291
+ ### Node.js (Server-Side)
292
+
293
+ For server-to-server authentication, use the **client_credentials** OAuth flow:
294
+
295
+ ```typescript
296
+ import { client } from '@orchestration-ai/sdk/client.gen';
297
+ import { setupClientCredentials } from '@orchestration-ai/sdk/oauth-utils';
298
+
299
+ setupClientCredentials(client, {
300
+ client_id: 'your-client-id',
301
+ client_secret: 'your-client-secret',
302
+ scope: 'role_admin',
214
303
  });
215
304
  ```
216
305
 
217
- ### Error Handling
306
+ The SDK automatically obtains and refreshes tokens.
307
+
308
+ ### Browser (Client-Side)
218
309
 
219
310
  ```typescript
220
- import { workspaceFind } from '@orchestration-ai/sdk';
311
+ import { client } from '@orchestration-ai/sdk/client.gen';
312
+ import { setupBrowserAuth, initiateLogin, parseLoginRedirect, saveLogin, logout } from '@orchestration-ai/sdk/oauth-utils';
313
+
314
+ setupBrowserAuth(client, {
315
+ onRefreshToken: async () => {
316
+ const response = await fetch('/api/auth/refresh');
317
+ return response.ok ? response.json() : null;
318
+ },
319
+ });
221
320
 
222
- const response = await workspaceFind();
321
+ // Initiate login
322
+ initiateLogin(client.getConfig().baseURL, {
323
+ client_id: 'your-client-id',
324
+ redirect_uri: 'https://your-app.com/callback',
325
+ });
223
326
 
224
- if (response.error) {
225
- console.error('Request failed:', response.error);
226
- } else {
227
- console.log('Workspaces:', response.data);
327
+ // Handle callback
328
+ const result = parseLoginRedirect();
329
+ if (result.granted) {
330
+ const tokens = await fetch('/api/auth/exchange', {
331
+ method: 'POST',
332
+ body: JSON.stringify({ code: result.code, redirect_uri: '...' }),
333
+ }).then(r => r.json());
334
+ saveLogin(tokens);
228
335
  }
229
336
  ```
230
337
 
231
- ### Using throwOnError
338
+ ## API Usage Examples
232
339
 
233
340
  ```typescript
234
- import { workspaceFind } from '@orchestration-ai/sdk';
341
+ import { workspaceFind, orchestrationCreate, agentCreate } from '@orchestration-ai/sdk/sdk.gen';
235
342
 
236
- try {
237
- const response = await workspaceFind({ throwOnError: true });
238
- console.log('Workspaces:', response.data);
239
- } catch (error) {
240
- console.error('Request failed:', error);
241
- }
343
+ // List workspaces
344
+ const { data } = await workspaceFind();
345
+
346
+ // Create an orchestration
347
+ const { data: orch } = await orchestrationCreate({
348
+ path: { workspaceId: 'ws-id' },
349
+ body: { orchestration_name: 'My Orchestration', orchestration_description: '...' },
350
+ });
351
+
352
+ // Create an agent
353
+ const { data: agent } = await agentCreate({
354
+ path: { workspaceId: 'ws-id', orchestrationId: 'orch-id' },
355
+ body: { agent_name: 'Support Agent', agent_description: '...' },
356
+ });
242
357
  ```
243
358
 
244
359
  ## Roles & Permissions
245
360
 
246
- Access control uses a hierarchical role system. Higher-level roles inherit all permissions from their children.
361
+ Applications declare permissions using Casbin role names:
247
362
 
248
- ### Top-Level Roles
363
+ | Role | Description |
364
+ |------|-------------|
365
+ | `role_admin` | Full access to everything |
366
+ | `role_workspace_admin` | Full workspace + orchestration + agent access |
367
+ | `role_agent_reader` | Read agent data |
368
+ | `role_agent_writer` | Read + create + update agents |
369
+ | `role_agent_admin` | Full agent CRUD |
370
+ | `role_service_reader` | Read services |
249
371
 
250
- | Role | Inherits |
251
- |------|----------|
252
- | `role_admin` | `role_workspace_admin`, `role_application_admin`, `role_access_admin`, `role_llm_keys_admin`, `role_llm_reader`, `role_llm_lister`, `role_service_reader`, `role_service_lister`, `role_day_pass_transaction_lister` |
372
+ See the full hierarchy in the [Roles & Permissions](#roles-hierarchy) section below.
253
373
 
254
- ### Admin Roles
374
+ ### Roles Hierarchy
255
375
 
256
376
  | Role | Inherits |
257
377
  |------|----------|
378
+ | `role_admin` | All admin roles + `role_llm_reader`, `role_llm_lister`, `role_service_reader`, `role_service_lister`, `role_day_pass_transaction_lister` |
258
379
  | `role_workspace_admin` | `role_workspace_writer`, `role_workspace_lister`, `role_workspace_deleter`, `role_orchestration_admin` |
259
380
  | `role_orchestration_admin` | `role_orchestration_writer`, `role_orchestration_lister`, `role_orchestration_deleter`, `role_agent_admin` |
260
381
  | `role_agent_admin` | `role_agent_writer`, `role_agent_lister`, `role_agent_deleter` |
261
382
  | `role_application_admin` | `role_application_writer`, `role_application_lister`, `role_application_deleter` |
262
383
  | `role_access_admin` | `role_access_writer`, `role_access_lister`, `role_access_deleter` |
263
- | `role_llm_keys_admin` | `role_llm_keys_writer`, `role_llm_keys_lister` |
264
-
265
- ### Writer Roles
266
-
267
- | Role | Inherits |
268
- |------|----------|
269
- | `role_workspace_writer` | `role_workspace_inserter`, `role_workspace_reader`, `role_workspace_updater` |
270
- | `role_orchestration_writer` | `role_orchestration_inserter`, `role_orchestration_reader`, `role_orchestration_updater` |
271
- | `role_agent_writer` | `role_agent_inserter`, `role_agent_reader`, `role_agent_updater` |
272
- | `role_application_writer` | `role_application_inserter`, `role_application_reader`, `role_application_updater` |
273
- | `role_access_writer` | `role_access_inserter`, `role_access_reader` |
274
- | `role_llm_keys_writer` | `role_llm_keys_inserter`, `role_llm_keys_reader`, `role_llm_keys_updater` |
275
-
276
- ### Granular Permissions
277
-
278
- Each resource has fine-grained permissions:
279
-
280
- - `*_reader` — Read a single resource by ID
281
- - `*_lister` — List/query resources
282
- - `*_inserter` — Create new resources
283
- - `*_updater` — Update existing resources
284
- - `*_deleter` — Delete resources
285
384
 
286
- ### Example: Granting Access
287
-
288
- ```typescript
289
- import { accessCreate } from '@orchestration-ai/sdk';
290
-
291
- // Grant a user full admin access to a workspace
292
- await accessCreate({
293
- body: {
294
- resource_id: 'workspace-id',
295
- principal_id: 'user-uid',
296
- principal_name: 'Jane Doe',
297
- principal_email: 'jane@example.com',
298
- role: 'role_admin',
299
- },
300
- });
301
-
302
- // Grant read-only access to orchestrations
303
- await accessCreate({
304
- body: {
305
- resource_id: 'workspace-id',
306
- principal_id: 'user-uid',
307
- principal_name: 'Viewer',
308
- principal_email: 'viewer@example.com',
309
- role: 'role_orchestration_reader',
310
- },
311
- });
312
- ```
385
+ Writer roles inherit inserter + reader + updater. Each resource has `_reader`, `_lister`, `_inserter`, `_updater`, `_deleter` granular permissions.
313
386
 
314
387
  ## License
315
388
 
@@ -0,0 +1,39 @@
1
+ import express from "express";
2
+ import { type Server as HttpServer } from "node:http";
3
+ import type { Client } from "./client";
4
+ import type { Context, Permission, ServiceDescription, Setting } from "./shared-types";
5
+ export type ToolHandler = (body: any, context: Context, engineClient: Client, apiClient: Client) => unknown | Promise<unknown>;
6
+ export type TouchHandler = (context: Context, engineClient: Client, apiClient: Client) => void | Promise<void>;
7
+ export type DescriptionHandler = (context: Context, engineClient: Client, apiClient: Client) => ServiceDescription | Promise<ServiceDescription>;
8
+ type ExtractPaths<T extends ServiceDescription> = T[number]["path"];
9
+ export type ServiceDefinition<TDesc extends ServiceDescription | DescriptionHandler = ServiceDescription | DescriptionHandler> = {
10
+ unique_name: string;
11
+ service_name: string;
12
+ service_description: string;
13
+ defaultSettings?: Setting[];
14
+ description: TDesc;
15
+ touch?: TouchHandler;
16
+ tools?: TDesc extends ServiceDescription ? Record<ExtractPaths<TDesc>, ToolHandler> : Record<string, ToolHandler>;
17
+ };
18
+ export declare function defineService<const TDesc extends ServiceDescription>(definition: ServiceDefinition<TDesc>): ServiceDefinition<TDesc>;
19
+ export declare function defineServiceWithDynamicDescription(definition: ServiceDefinition<DescriptionHandler>): ServiceDefinition<DescriptionHandler>;
20
+ export type AppConfig = {
21
+ port?: number | string;
22
+ permissions?: Permission[];
23
+ engineUrl?: string;
24
+ accessKey?: string;
25
+ /** Set to false to disable the /explore page. Defaults to true. */
26
+ explore?: boolean;
27
+ };
28
+ export type OaiApp = {
29
+ service: (definition: ServiceDefinition<any>) => OaiApp;
30
+ permissions: (permissions: Permission[]) => OaiApp;
31
+ listen: (port?: number | string) => HttpServer;
32
+ expressApp: express.Application;
33
+ httpServer: HttpServer;
34
+ };
35
+ export type { Client } from "./client";
36
+ export type { Context, Permission, ServiceDescription, Setting } from "./shared-types";
37
+ export { getBooleanSetting, getTextSetting, getSecretSetting } from "./shared-types";
38
+ export declare function createApp(config?: AppConfig): OaiApp;
39
+ //# sourceMappingURL=app-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-builder.d.ts","sourceRoot":"","sources":["../../typescript/app-builder.ts"],"names":[],"mappings":"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"}