@orchestration-ai/sdk 0.2.0 → 0.4.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.
Files changed (38) hide show
  1. package/README.md +280 -208
  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/sdk.gen.d.ts +3 -1
  7. package/dist/cjs/sdk.gen.d.ts.map +1 -1
  8. package/dist/cjs/sdk.gen.js +26 -2
  9. package/dist/cjs/sdk.gen.js.map +1 -1
  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 +155 -15
  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/sdk.gen.d.ts +3 -1
  25. package/dist/esm/sdk.gen.d.ts.map +1 -1
  26. package/dist/esm/sdk.gen.js +22 -0
  27. package/dist/esm/sdk.gen.js.map +1 -1
  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 +155 -15
  37. package/dist/esm/types.gen.d.ts.map +1 -1
  38. package/package.json +35 -2
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,307 +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/sdk.gen';
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
67
+
68
+ Each service has:
28
69
 
29
- For server-to-server authentication, use the **client_credentials** OAuth flow. The SDK manages token acquisition and refresh automatically:
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 } from '@orchestration-ai/sdk/oauth-utils';
34
- import { workspaceFind } from '@orchestration-ai/sdk/sdk.gen';
85
+ // Tool handler
86
+ (body: any, context: Context, engineClient: Client, apiClient: Client) => unknown | Promise<unknown>
35
87
 
36
- // Setup once — tokens are fetched and refreshed automatically
37
- setupClientCredentials(client, {
38
- client_id: 'your-client-id',
39
- client_secret: 'your-client-secret',
40
- scope: 'role_admin', // any supported role as scope
41
- });
88
+ // Touch handler
89
+ (context: Context, engineClient: Client, apiClient: Client) => void | Promise<void>
42
90
 
43
- // All requests are now authenticated
44
- const workspaces = await workspaceFind();
91
+ // Description handler (dynamic)
92
+ (context: Context, engineClient: Client, apiClient: Client) => ServiceDescription | Promise<ServiceDescription>
45
93
  ```
46
94
 
47
- The SDK will:
48
- - Automatically obtain an access token via `client_credentials` on the first request
49
- - Re-fetch the token when it expires (with a 30s buffer)
50
- - Retry once on 401 responses with a fresh token
51
- - Deduplicate concurrent token requests
95
+ ### Two Clients
52
96
 
53
- 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:
54
98
 
55
- ### 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
56
105
 
57
- 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`:
58
107
 
59
108
  ```typescript
60
- import { client } from '@orchestration-ai/sdk/client.gen';
61
- import {
62
- setupBrowserAuth,
63
- initiateLogin,
64
- parseLoginRedirect,
65
- saveLogin,
66
- getCurrentLogin,
67
- isLoginExpired,
68
- logout,
69
- } from '@orchestration-ai/sdk/oauth-utils';
70
-
71
- // Attach stored tokens to all requests automatically
72
- // Optionally provide a refresh callback for automatic token renewal
73
- setupBrowserAuth(client, {
74
- onRefreshToken: async () => {
75
- // Call your backend to refresh the token
76
- const response = await fetch('/api/auth/refresh');
77
- if (!response.ok) return null;
78
- 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) => { ... },
79
142
  },
80
143
  });
81
144
  ```
82
145
 
83
- #### OAuth Login Flow
146
+ ### Touch Handler
84
147
 
85
- **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:
86
149
 
87
150
  ```typescript
88
- import { client } from '@orchestration-ai/sdk/client.gen';
89
- import { initiateLogin } from '@orchestration-ai/sdk/oauth-utils';
90
-
91
- function handleLoginClick() {
92
- initiateLogin(client.getConfig().baseURL, {
93
- client_id: 'your-client-id',
94
- redirect_uri: 'https://your-app.com/callback',
95
- scope: 'role_admin', // any supported role as scope
96
- }, '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
+ });
97
164
  }
98
165
  ```
99
166
 
100
- This redirects the user to the Orchestration AI login page.
167
+ ### Settings
101
168
 
102
- **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) |
103
176
 
104
- On your callback page (e.g. `/callback`), parse the redirect result and exchange the code via your backend:
177
+ Utility functions for reading settings:
105
178
 
106
179
  ```typescript
107
- import { parseLoginRedirect, saveLogin } from '@orchestration-ai/sdk/oauth-utils';
180
+ import { getBooleanSetting, getTextSetting, getSecretSetting } from '@orchestration-ai/sdk/services';
108
181
 
109
- 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
+ ```
110
186
 
111
- if (result.granted) {
112
- // Send the code to your backend to exchange for tokens securely
113
- // IMPORTANT: pass the same redirect_uri used in initiateLogin
114
- const tokens = await fetch('/api/auth/exchange', {
115
- method: 'POST',
116
- body: JSON.stringify({
117
- code: result.code,
118
- redirect_uri: 'https://your-app.com/callback',
119
- }),
120
- }).then(r => r.json());
187
+ ### Sending Messages to Agents
121
188
 
122
- // Save the tokens setupBrowserAuth will attach them to future requests
123
- saveLogin(tokens);
124
- } else {
125
- console.error('Login denied:', result.error, result.error_description);
126
- }
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
+ );
127
201
  ```
128
202
 
129
- #### 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
+ ```
130
211
 
131
- 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
132
213
 
133
- If you prefer to handle refresh manually:
214
+ Access the underlying Express app and HTTP server for custom routes or WebSockets:
134
215
 
135
216
  ```typescript
136
- import { isLoginExpired, saveLogin, logout } from '@orchestration-ai/sdk/oauth-utils';
137
-
138
- if (isLoginExpired()) {
139
- const response = await fetch('/api/auth/refresh');
140
- if (response.ok) {
141
- saveLogin(await response.json());
142
- } else {
143
- logout();
144
- }
145
- }
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);
146
228
  ```
147
229
 
148
- #### Logout
230
+ ### Explore Page
149
231
 
150
- ```typescript
151
- import { logout } from '@orchestration-ai/sdk/oauth-utils';
232
+ The `/explore` endpoint renders an interactive page showing all services, tools, and permissions. You can test tools directly from the browser.
152
233
 
153
- logout(); // Clears stored tokens from localStorage
234
+ Disable in production:
235
+
236
+ ```typescript
237
+ createApp({ explore: false }).service(...).listen(3001);
154
238
  ```
155
239
 
156
- ## API Usage Examples
240
+ ## Client Factories
241
+
242
+ ### createEngineClient
157
243
 
158
- ### Workspaces
244
+ For calling engine internal endpoints:
159
245
 
160
246
  ```typescript
161
- import { workspaceFind, workspaceCreate, workspaceFindById } from '@orchestration-ai/sdk/sdk.gen';
247
+ import { createEngineClient } from '@orchestration-ai/sdk/services';
162
248
 
163
- // List workspaces
164
- const { data } = await workspaceFind({ query: { limit: 10, offset: 0 } });
249
+ // Production (default URL)
250
+ const client = createEngineClient(accessKey);
165
251
 
166
- // Create a workspace
167
- const { data: workspace } = await workspaceCreate({
168
- body: { workspace_name: 'My Workspace' },
169
- });
252
+ // Custom URL
253
+ const client = createEngineClient("https://my-engine.com", accessKey);
170
254
 
171
- // Get a workspace by ID
172
- 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);
173
257
  ```
174
258
 
175
- ### Orchestrations
259
+ ### createApplicationClient
260
+
261
+ For calling another OAI application's services:
176
262
 
177
263
  ```typescript
178
- import {
179
- orchestrationFindByWorkspace,
180
- orchestrationCreate,
181
- } from '@orchestration-ai/sdk/sdk.gen';
182
-
183
- // List orchestrations in a workspace
184
- const { data } = await orchestrationFindByWorkspace({
185
- path: { workspaceId: 'workspace-id' },
186
- });
264
+ import { createApplicationClient, listServices, callServiceTool } from '@orchestration-ai/sdk/services';
187
265
 
188
- // Create an orchestration
189
- const { data: orch } = await orchestrationCreate({
190
- path: { workspaceId: 'workspace-id' },
191
- body: {
192
- orchestration_name: 'My Orchestration',
193
- orchestration_description: 'Handles customer support',
194
- },
195
- });
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" } });
196
269
  ```
197
270
 
198
- ### Agents
271
+ ### createApiClient
272
+
273
+ For making authenticated API calls with OAuth:
199
274
 
200
275
  ```typescript
201
- import { agentFindByOrchestration, agentCreate } from '@orchestration-ai/sdk/sdk.gen';
276
+ import { createApiClient } from '@orchestration-ai/sdk/services';
277
+ import { setupClientCredentials } from '@orchestration-ai/sdk/oauth-utils';
202
278
 
203
- // List agents
204
- const { data } = await agentFindByOrchestration({
205
- path: { workspaceId: 'ws-id', orchestrationId: 'orch-id' },
279
+ const apiClient = createApiClient();
280
+ setupClientCredentials(apiClient, {
281
+ client_id: accessKey,
282
+ client_secret: `${accessKey}:${workspaceOwnerId}`,
206
283
  });
207
284
 
208
- // Create an agent
209
- const { data: agent } = await agentCreate({
210
- path: { workspaceId: 'ws-id', orchestrationId: 'orch-id' },
211
- body: {
212
- agent_name: 'Support Agent',
213
- agent_description: 'Handles tier 1 support tickets',
214
- },
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',
215
303
  });
216
304
  ```
217
305
 
218
- ### Error Handling
306
+ The SDK automatically obtains and refreshes tokens.
307
+
308
+ ### Browser (Client-Side)
219
309
 
220
310
  ```typescript
221
- import { workspaceFind } from '@orchestration-ai/sdk/sdk.gen';
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
+ });
222
320
 
223
- 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
+ });
224
326
 
225
- if (response.error) {
226
- console.error('Request failed:', response.error);
227
- } else {
228
- 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);
229
335
  }
230
336
  ```
231
337
 
232
- ### Using throwOnError
338
+ ## API Usage Examples
233
339
 
234
340
  ```typescript
235
- import { workspaceFind } from '@orchestration-ai/sdk/sdk.gen';
341
+ import { workspaceFind, orchestrationCreate, agentCreate } from '@orchestration-ai/sdk/sdk.gen';
236
342
 
237
- try {
238
- const response = await workspaceFind({ throwOnError: true });
239
- console.log('Workspaces:', response.data);
240
- } catch (error) {
241
- console.error('Request failed:', error);
242
- }
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
+ });
243
357
  ```
244
358
 
245
359
  ## Roles & Permissions
246
360
 
247
- Access control uses a hierarchical role system. Higher-level roles inherit all permissions from their children.
361
+ Applications declare permissions using Casbin role names:
248
362
 
249
- ### 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 |
250
371
 
251
- | Role | Inherits |
252
- |------|----------|
253
- | `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.
254
373
 
255
- ### Admin Roles
374
+ ### Roles Hierarchy
256
375
 
257
376
  | Role | Inherits |
258
377
  |------|----------|
378
+ | `role_admin` | All admin roles + `role_llm_reader`, `role_llm_lister`, `role_service_reader`, `role_service_lister`, `role_day_pass_transaction_lister` |
259
379
  | `role_workspace_admin` | `role_workspace_writer`, `role_workspace_lister`, `role_workspace_deleter`, `role_orchestration_admin` |
260
380
  | `role_orchestration_admin` | `role_orchestration_writer`, `role_orchestration_lister`, `role_orchestration_deleter`, `role_agent_admin` |
261
381
  | `role_agent_admin` | `role_agent_writer`, `role_agent_lister`, `role_agent_deleter` |
262
382
  | `role_application_admin` | `role_application_writer`, `role_application_lister`, `role_application_deleter` |
263
383
  | `role_access_admin` | `role_access_writer`, `role_access_lister`, `role_access_deleter` |
264
- | `role_llm_keys_admin` | `role_llm_keys_writer`, `role_llm_keys_lister` |
265
-
266
- ### Writer Roles
267
-
268
- | Role | Inherits |
269
- |------|----------|
270
- | `role_workspace_writer` | `role_workspace_inserter`, `role_workspace_reader`, `role_workspace_updater` |
271
- | `role_orchestration_writer` | `role_orchestration_inserter`, `role_orchestration_reader`, `role_orchestration_updater` |
272
- | `role_agent_writer` | `role_agent_inserter`, `role_agent_reader`, `role_agent_updater` |
273
- | `role_application_writer` | `role_application_inserter`, `role_application_reader`, `role_application_updater` |
274
- | `role_access_writer` | `role_access_inserter`, `role_access_reader` |
275
- | `role_llm_keys_writer` | `role_llm_keys_inserter`, `role_llm_keys_reader`, `role_llm_keys_updater` |
276
-
277
- ### Granular Permissions
278
-
279
- Each resource has fine-grained permissions:
280
-
281
- - `*_reader` — Read a single resource by ID
282
- - `*_lister` — List/query resources
283
- - `*_inserter` — Create new resources
284
- - `*_updater` — Update existing resources
285
- - `*_deleter` — Delete resources
286
384
 
287
- ### Example: Granting Access
288
-
289
- ```typescript
290
- import { accessCreate } from '@orchestration-ai/sdk/sdk.gen';
291
-
292
- // Grant a user full admin access to a workspace
293
- await accessCreate({
294
- body: {
295
- resource_id: 'workspace-id',
296
- principal_id: 'user-uid',
297
- principal_name: 'Jane Doe',
298
- principal_email: 'jane@example.com',
299
- role: 'role_admin',
300
- },
301
- });
302
-
303
- // Grant read-only access to orchestrations
304
- await accessCreate({
305
- body: {
306
- resource_id: 'workspace-id',
307
- principal_id: 'user-uid',
308
- principal_name: 'Viewer',
309
- principal_email: 'viewer@example.com',
310
- role: 'role_orchestration_reader',
311
- },
312
- });
313
- ```
385
+ Writer roles inherit inserter + reader + updater. Each resource has `_reader`, `_lister`, `_inserter`, `_updater`, `_deleter` granular permissions.
314
386
 
315
387
  ## License
316
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":"AAAA,OAAO,OAAgD,MAAM,SAAS,CAAC;AACvE,OAAO,EAAgB,KAAK,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EACV,OAAO,EACP,UAAU,EACV,kBAAkB,EAClB,OAAO,EACR,MAAM,gBAAgB,CAAC;AAMxB,MAAM,MAAM,WAAW,GAAG,CACxB,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,KACd,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE/G,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,KACd,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEtD,KAAK,YAAY,CAAC,CAAC,SAAS,kBAAkB,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,MAAM,MAAM,iBAAiB,CAAC,KAAK,SAAS,kBAAkB,GAAG,kBAAkB,GAAG,kBAAkB,GAAG,kBAAkB,IAAI;IAC/H,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B,WAAW,EAAE,KAAK,CAAC;IACnB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,SAAS,kBAAkB,GACpC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,GACxC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACjC,CAAC;AAEF,wBAAgB,aAAa,CAAC,KAAK,CAAC,KAAK,SAAS,kBAAkB,EAClE,UAAU,EAAE,iBAAiB,CAAC,KAAK,CAAC,GACnC,iBAAiB,CAAC,KAAK,CAAC,CAE1B;AAED,wBAAgB,mCAAmC,CACjD,UAAU,EAAE,iBAAiB,CAAC,kBAAkB,CAAC,GAChD,iBAAiB,CAAC,kBAAkB,CAAC,CAEvC;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,OAAO,EAAE,CAAC,UAAU,EAAE,iBAAiB,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC;IACxD,WAAW,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,KAAK,MAAM,CAAC;IACnD,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,KAAK,UAAU,CAAC;IAC/C,UAAU,EAAE,OAAO,CAAC,WAAW,CAAC;IAChC,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAGF,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AA0arF,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAqJpD"}