@oasisomniverse/web6-api 1.0.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 +177 -0
- package/docs/README.md +24 -0
- package/docs/modules/Completion.md +124 -0
- package/docs/modules/HolonicBraid.md +137 -0
- package/docs/modules/HolonicMemory.md +268 -0
- package/docs/modules/Images.md +77 -0
- package/docs/modules/Orchestrator.md +173 -0
- package/docs/modules/ReasoningNetwork.md +254 -0
- package/index.d.ts +52 -0
- package/index.js +3 -0
- package/index.mjs +4 -0
- package/package.json +112 -0
- package/src/core/httpClient.js +110 -0
- package/src/core/routeHelper.js +85 -0
- package/src/core/tokenStore.js +52 -0
- package/src/core/types.d.ts +18 -0
- package/src/index.js +45 -0
- package/src/modules/Completion.d.ts +12 -0
- package/src/modules/Completion.js +25 -0
- package/src/modules/HolonicBraid.d.ts +12 -0
- package/src/modules/HolonicBraid.js +25 -0
- package/src/modules/HolonicMemory.d.ts +21 -0
- package/src/modules/HolonicMemory.js +31 -0
- package/src/modules/Images.d.ts +9 -0
- package/src/modules/Images.js +23 -0
- package/src/modules/Orchestrator.d.ts +15 -0
- package/src/modules/Orchestrator.js +27 -0
- package/src/modules/ReasoningNetwork.d.ts +18 -0
- package/src/modules/ReasoningNetwork.js +29 -0
- package/src/modules/index.js +25 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# ReasoningNetwork — `web6.reasoningNetwork`
|
|
2
|
+
|
|
3
|
+
Source controller: [`ReasoningNetworkController.cs`](https://github.com/NextGenSoftwareUK/OASIS2/blob/main/WEB6/NextGenSoftware.OASIS.Web6.WebAPI/Controllers/ReasoningNetworkController.cs)
|
|
4
|
+
Route prefix: `v1/reasoning-network`
|
|
5
|
+
4 operation(s).
|
|
6
|
+
|
|
7
|
+
Every method takes a single args object: any key matching a `{token}` in the route is substituted into the URL; everything else becomes the query string (GET/DELETE) or JSON body (POST/PUT). Every call resolves to the standard OASIS envelope:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
{
|
|
11
|
+
isError: boolean;
|
|
12
|
+
isWarning: boolean;
|
|
13
|
+
message: string;
|
|
14
|
+
errorCode?: string;
|
|
15
|
+
result: T; // see each endpoint's Response section below
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Operations
|
|
20
|
+
|
|
21
|
+
### `dispatch`
|
|
22
|
+
|
|
23
|
+
Dispatches a problem to the reasoning network. The controller agent scores eligible agents, picks Serial/Parallel/Decomposed execution, runs loop detection, assembles the final Mermaid plan and updates every involved agent's score via EMA before returning.
|
|
24
|
+
|
|
25
|
+
**POST** `v1/reasoning-network/dispatch`
|
|
26
|
+
|
|
27
|
+
**Request**
|
|
28
|
+
|
|
29
|
+
Body type: `DispatchRequest`
|
|
30
|
+
|
|
31
|
+
| Field | Type |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `Problem` | `string` |
|
|
34
|
+
| `TaskType` | `string` |
|
|
35
|
+
| `Mode` | `DispatchMode` |
|
|
36
|
+
| `EligibleAgentIds` | `List<Guid>` |
|
|
37
|
+
| `AvatarId` | `Guid` |
|
|
38
|
+
|
|
39
|
+
**Response**
|
|
40
|
+
|
|
41
|
+
Standard `OASISResult` envelope (see top of this page) with:
|
|
42
|
+
|
|
43
|
+
`result` type: `DispatchResult`
|
|
44
|
+
|
|
45
|
+
| Field | Type |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `SessionId` | `Guid` |
|
|
48
|
+
| `ModeUsed` | `DispatchMode` |
|
|
49
|
+
| `AgentPlans` | `List<AgentExecutionPlan>` |
|
|
50
|
+
| `FinalMermaidPlan` | `string` |
|
|
51
|
+
| `WinningAgentId` | `Guid` |
|
|
52
|
+
| `HolonicBraidGraphId` | `Guid` |
|
|
53
|
+
| `TotalLatencyMs` | `long` |
|
|
54
|
+
|
|
55
|
+
**Example**
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
const { isError, message, result } = await web6.reasoningNetwork.dispatch({
|
|
59
|
+
problem: "example string",
|
|
60
|
+
taskType: "example string",
|
|
61
|
+
mode: { },
|
|
62
|
+
eligibleAgentIds: ["3fa85f64-5717-4562-b3fc-2c963f66afa6"],
|
|
63
|
+
avatarId: "3fa85f64-5717-4562-b3fc-2c963f66afa6"
|
|
64
|
+
});
|
|
65
|
+
if (isError) throw new Error(message);
|
|
66
|
+
console.log(result);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Example response:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"isError": false,
|
|
74
|
+
"message": "",
|
|
75
|
+
"result": { "SessionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "ModeUsed": { }, "AgentPlans": [{ "AgentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "AgentName": "example string", "CompositeScoreAtDispatch": 1.0, "MermaidDiagram": "example string", "Stalled": true, "LoopDetected": true, "LatencyMs": 1 }], "FinalMermaidPlan": "example string", "WinningAgentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "HolonicBraidGraphId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "TotalLatencyMs": 1 }
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
### `getAgents`
|
|
82
|
+
|
|
83
|
+
Lists every reasoning agent currently registered with FAHRN, with its live composite scoring metadata.
|
|
84
|
+
|
|
85
|
+
**GET** `v1/reasoning-network/agents`
|
|
86
|
+
|
|
87
|
+
**Request**
|
|
88
|
+
|
|
89
|
+
No request body.
|
|
90
|
+
|
|
91
|
+
**Response**
|
|
92
|
+
|
|
93
|
+
Standard `OASISResult` envelope (see top of this page) with:
|
|
94
|
+
|
|
95
|
+
`result` type: `ReasoningAgentMetadata` (array)
|
|
96
|
+
|
|
97
|
+
| Field | Type |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| `Id` | `Guid` |
|
|
100
|
+
| `AgentName` | `string` |
|
|
101
|
+
| `Provider` | `AIProviderType` |
|
|
102
|
+
| `Model` | `string` |
|
|
103
|
+
| `CategoryScores` | `Dictionary<string, double>` |
|
|
104
|
+
| `SpeedScore` | `double` |
|
|
105
|
+
| `CostScore` | `double` |
|
|
106
|
+
| `LoopDetectionScore` | `double` |
|
|
107
|
+
| `FailureRate` | `double` |
|
|
108
|
+
| `TasksCompleted` | `int` |
|
|
109
|
+
| `LastUpdatedUtc` | `DateTime` |
|
|
110
|
+
|
|
111
|
+
**Example**
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
const { isError, message, result } = await web6.reasoningNetwork.getAgents({});
|
|
115
|
+
if (isError) throw new Error(message);
|
|
116
|
+
console.log(result);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Example response:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"isError": false,
|
|
124
|
+
"message": "",
|
|
125
|
+
"result": [{ "Id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "AgentName": "example string", "Provider": { }, "Model": "example string", "CategoryScores": { "<string>": 1.0 }, "SpeedScore": 1.0, "CostScore": 1.0, "LoopDetectionScore": 1.0, "FailureRate": 1.0, "TasksCompleted": 1, "LastUpdatedUtc": "2026-01-01T00:00:00Z" }]
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### `registerAgent`
|
|
132
|
+
|
|
133
|
+
Registers a new reasoning agent (e.g. a specific provider/model) with the network.
|
|
134
|
+
|
|
135
|
+
**POST** `v1/reasoning-network/agents`
|
|
136
|
+
|
|
137
|
+
**Request**
|
|
138
|
+
|
|
139
|
+
Body type: `ReasoningAgentMetadata`
|
|
140
|
+
|
|
141
|
+
| Field | Type |
|
|
142
|
+
| --- | --- |
|
|
143
|
+
| `Id` | `Guid` |
|
|
144
|
+
| `AgentName` | `string` |
|
|
145
|
+
| `Provider` | `AIProviderType` |
|
|
146
|
+
| `Model` | `string` |
|
|
147
|
+
| `CategoryScores` | `Dictionary<string, double>` |
|
|
148
|
+
| `SpeedScore` | `double` |
|
|
149
|
+
| `CostScore` | `double` |
|
|
150
|
+
| `LoopDetectionScore` | `double` |
|
|
151
|
+
| `FailureRate` | `double` |
|
|
152
|
+
| `TasksCompleted` | `int` |
|
|
153
|
+
| `LastUpdatedUtc` | `DateTime` |
|
|
154
|
+
|
|
155
|
+
**Response**
|
|
156
|
+
|
|
157
|
+
Standard `OASISResult` envelope (see top of this page) with:
|
|
158
|
+
|
|
159
|
+
`result` type: `ReasoningAgentMetadata`
|
|
160
|
+
|
|
161
|
+
| Field | Type |
|
|
162
|
+
| --- | --- |
|
|
163
|
+
| `Id` | `Guid` |
|
|
164
|
+
| `AgentName` | `string` |
|
|
165
|
+
| `Provider` | `AIProviderType` |
|
|
166
|
+
| `Model` | `string` |
|
|
167
|
+
| `CategoryScores` | `Dictionary<string, double>` |
|
|
168
|
+
| `SpeedScore` | `double` |
|
|
169
|
+
| `CostScore` | `double` |
|
|
170
|
+
| `LoopDetectionScore` | `double` |
|
|
171
|
+
| `FailureRate` | `double` |
|
|
172
|
+
| `TasksCompleted` | `int` |
|
|
173
|
+
| `LastUpdatedUtc` | `DateTime` |
|
|
174
|
+
|
|
175
|
+
**Example**
|
|
176
|
+
|
|
177
|
+
```js
|
|
178
|
+
const { isError, message, result } = await web6.reasoningNetwork.registerAgent({
|
|
179
|
+
id: "3fa85f64-5717-4562-b3fc-2c963f66afa6",
|
|
180
|
+
agentName: "example string",
|
|
181
|
+
provider: { },
|
|
182
|
+
model: "example string",
|
|
183
|
+
categoryScores: { "<string>": 1.0 },
|
|
184
|
+
speedScore: 1.0,
|
|
185
|
+
costScore: 1.0,
|
|
186
|
+
loopDetectionScore: 1.0,
|
|
187
|
+
failureRate: 1.0,
|
|
188
|
+
tasksCompleted: 1,
|
|
189
|
+
lastUpdatedUtc: "2026-01-01T00:00:00Z"
|
|
190
|
+
});
|
|
191
|
+
if (isError) throw new Error(message);
|
|
192
|
+
console.log(result);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Example response:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"isError": false,
|
|
200
|
+
"message": "",
|
|
201
|
+
"result": { "Id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "AgentName": "example string", "Provider": { }, "Model": "example string", "CategoryScores": { "<string>": 1.0 }, "SpeedScore": 1.0, "CostScore": 1.0, "LoopDetectionScore": 1.0, "FailureRate": 1.0, "TasksCompleted": 1, "LastUpdatedUtc": "2026-01-01T00:00:00Z" }
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
### `seedOpenServAgents`
|
|
208
|
+
|
|
209
|
+
Seeds FAHRN with one reasoning agent per model in the OpenServ SERV catalog (skips any AgentName already registered), so the network can immediately score/route/braid across every OpenServ-reachable model (OpenAI, Anthropic, Google, xAI, Qwen, DeepSeek) behind a single SERV_API_KEY. Safe to call repeatedly. POST https://api.web6.oasisomniverse.one/v1/reasoning-network/agents/seed-openserv
|
|
210
|
+
|
|
211
|
+
**POST** `v1/reasoning-network/agents/seed-openserv`
|
|
212
|
+
|
|
213
|
+
**Request**
|
|
214
|
+
|
|
215
|
+
No request body.
|
|
216
|
+
|
|
217
|
+
**Response**
|
|
218
|
+
|
|
219
|
+
Standard `OASISResult` envelope (see top of this page) with:
|
|
220
|
+
|
|
221
|
+
`result` type: `ReasoningAgentMetadata` (array)
|
|
222
|
+
|
|
223
|
+
| Field | Type |
|
|
224
|
+
| --- | --- |
|
|
225
|
+
| `Id` | `Guid` |
|
|
226
|
+
| `AgentName` | `string` |
|
|
227
|
+
| `Provider` | `AIProviderType` |
|
|
228
|
+
| `Model` | `string` |
|
|
229
|
+
| `CategoryScores` | `Dictionary<string, double>` |
|
|
230
|
+
| `SpeedScore` | `double` |
|
|
231
|
+
| `CostScore` | `double` |
|
|
232
|
+
| `LoopDetectionScore` | `double` |
|
|
233
|
+
| `FailureRate` | `double` |
|
|
234
|
+
| `TasksCompleted` | `int` |
|
|
235
|
+
| `LastUpdatedUtc` | `DateTime` |
|
|
236
|
+
|
|
237
|
+
**Example**
|
|
238
|
+
|
|
239
|
+
```js
|
|
240
|
+
const { isError, message, result } = await web6.reasoningNetwork.seedOpenServAgents({});
|
|
241
|
+
if (isError) throw new Error(message);
|
|
242
|
+
console.log(result);
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Example response:
|
|
246
|
+
|
|
247
|
+
```json
|
|
248
|
+
{
|
|
249
|
+
"isError": false,
|
|
250
|
+
"message": "",
|
|
251
|
+
"result": [{ "Id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "AgentName": "example string", "Provider": { }, "Model": "example string", "CategoryScores": { "<string>": 1.0 }, "SpeedScore": 1.0, "CostScore": 1.0, "LoopDetectionScore": 1.0, "FailureRate": 1.0, "TasksCompleted": 1, "LastUpdatedUtc": "2026-01-01T00:00:00Z" }]
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/generate-types.js - do not hand-edit.
|
|
2
|
+
import type { OASISResponse, OASISSession } from './src/core/types';
|
|
3
|
+
import type { CompletionModule } from './src/modules/Completion';
|
|
4
|
+
import type { HolonicBraidModule } from './src/modules/HolonicBraid';
|
|
5
|
+
import type { HolonicMemoryModule } from './src/modules/HolonicMemory';
|
|
6
|
+
import type { ImagesModule } from './src/modules/Images';
|
|
7
|
+
import type { OrchestratorModule } from './src/modules/Orchestrator';
|
|
8
|
+
import type { ReasoningNetworkModule } from './src/modules/ReasoningNetwork';
|
|
9
|
+
|
|
10
|
+
export type { OASISResponse, OASISSession };
|
|
11
|
+
|
|
12
|
+
export interface Web6ClientOptions {
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
persistSession?: boolean;
|
|
15
|
+
fetchImpl?: typeof fetch;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export declare class HttpClient {
|
|
19
|
+
constructor(options?: { baseUrl?: string; tokenStore?: unknown; fetchImpl?: typeof fetch });
|
|
20
|
+
setBaseUrl(baseUrl: string): void;
|
|
21
|
+
request(verb: 'GET' | 'POST' | 'PUT' | 'DELETE', path: string, options?: Record<string, any>): Promise<OASISResponse>;
|
|
22
|
+
get(path: string, options?: Record<string, any>): Promise<OASISResponse>;
|
|
23
|
+
post(path: string, options?: Record<string, any>): Promise<OASISResponse>;
|
|
24
|
+
put(path: string, options?: Record<string, any>): Promise<OASISResponse>;
|
|
25
|
+
delete(path: string, options?: Record<string, any>): Promise<OASISResponse>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export declare class TokenStore {
|
|
29
|
+
constructor(options?: { persist?: boolean });
|
|
30
|
+
getSession(): OASISSession | null;
|
|
31
|
+
getToken(): string | null;
|
|
32
|
+
setSession(session: OASISSession | null): void;
|
|
33
|
+
clear(): void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export declare const DEFAULT_BASE_URL: string;
|
|
37
|
+
|
|
38
|
+
export declare class Web6Client {
|
|
39
|
+
constructor(options?: Web6ClientOptions);
|
|
40
|
+
readonly http: HttpClient;
|
|
41
|
+
readonly tokenStore: TokenStore;
|
|
42
|
+
readonly completion: CompletionModule;
|
|
43
|
+
readonly holonicBraid: HolonicBraidModule;
|
|
44
|
+
readonly holonicMemory: HolonicMemoryModule;
|
|
45
|
+
readonly images: ImagesModule;
|
|
46
|
+
readonly orchestrator: OrchestratorModule;
|
|
47
|
+
readonly reasoningNetwork: ReasoningNetworkModule;
|
|
48
|
+
setBaseUrl(baseUrl: string): void;
|
|
49
|
+
setToken(jwtToken: string, sessionExtras?: Partial<OASISSession>): void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default Web6Client;
|
package/index.js
ADDED
package/index.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oasisomniverse/web6-api",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"publishConfig": { "access": "public" },
|
|
5
|
+
"description": "Isomorphic (Node + browser) JavaScript/TypeScript-friendly client for the WEB6 OASIS AI Layer API - full coverage of the OASIS2 WEB6 WebAPI (unified AI completion/chat across every provider, image generation, the Holonic BRAID fractal memory hierarchy and shared reasoning-graph library, multi-agent orchestrator adapters for MCP/A2A/LangChain/AutoGen/CrewAI/Semantic Kernel, and FAHRN - the Fractal Adaptive Holonic Reasoning Network for agent scoring/routing/dispatch).",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"module": "index.mjs",
|
|
8
|
+
"types": "index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./index.d.ts",
|
|
12
|
+
"import": "./index.mjs",
|
|
13
|
+
"require": "./index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"index.js",
|
|
21
|
+
"index.mjs",
|
|
22
|
+
"index.d.ts",
|
|
23
|
+
"src",
|
|
24
|
+
"docs"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"generate": "node scripts/generate-modules.js",
|
|
28
|
+
"docs": "node scripts/generate-docs.js",
|
|
29
|
+
"types": "node scripts/generate-types.js",
|
|
30
|
+
"test": "node --test test"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/NextGenSoftwareUK/OASIS-API-Javascript-Package-WEB6.git"
|
|
35
|
+
},
|
|
36
|
+
"author": "NextGen Software Ltd",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"keywords": [
|
|
39
|
+
"WEB6 AI Layer API",
|
|
40
|
+
"WEB6 WebAPI",
|
|
41
|
+
"OASIS AI Layer",
|
|
42
|
+
"AI Completion",
|
|
43
|
+
"Chat Completion",
|
|
44
|
+
"Multi-Provider AI Routing",
|
|
45
|
+
"AI Dispatch",
|
|
46
|
+
"Image Generation",
|
|
47
|
+
"StabilityAI",
|
|
48
|
+
"OpenAI",
|
|
49
|
+
"Anthropic",
|
|
50
|
+
"Google Gemini",
|
|
51
|
+
"xAI Grok",
|
|
52
|
+
"Qwen",
|
|
53
|
+
"DeepSeek",
|
|
54
|
+
"OpenServ",
|
|
55
|
+
"Holonic BRAID",
|
|
56
|
+
"Holonic Memory",
|
|
57
|
+
"Fractal Memory Hierarchy",
|
|
58
|
+
"Membrane Rules",
|
|
59
|
+
"Reasoning Graph",
|
|
60
|
+
"Mermaid",
|
|
61
|
+
"FAHRN",
|
|
62
|
+
"Fractal Adaptive Holonic Reasoning Network",
|
|
63
|
+
"Reasoning Agents",
|
|
64
|
+
"Agent Orchestration",
|
|
65
|
+
"MCP",
|
|
66
|
+
"A2A",
|
|
67
|
+
"LangChain",
|
|
68
|
+
"AutoGen",
|
|
69
|
+
"CrewAI",
|
|
70
|
+
"Semantic Kernel",
|
|
71
|
+
"OASIS API",
|
|
72
|
+
"Avatar API",
|
|
73
|
+
"WEB 3",
|
|
74
|
+
"WEB 4",
|
|
75
|
+
"WEB 5",
|
|
76
|
+
"WEB 6",
|
|
77
|
+
"Blockchain",
|
|
78
|
+
"Interoperable",
|
|
79
|
+
"Future-Prove",
|
|
80
|
+
"Metaverse",
|
|
81
|
+
"Aggregation",
|
|
82
|
+
"HOT-Swappable-Architecture",
|
|
83
|
+
"P2P",
|
|
84
|
+
"Decentralised",
|
|
85
|
+
"Distributed",
|
|
86
|
+
"Interoprability",
|
|
87
|
+
"Abstraction-Layer",
|
|
88
|
+
"Multi-Network",
|
|
89
|
+
"Multi-Chain",
|
|
90
|
+
"Bridging",
|
|
91
|
+
"Network-Of-Networks",
|
|
92
|
+
"SSO",
|
|
93
|
+
"Auto-FailOver",
|
|
94
|
+
"Auto-LoadBalancing",
|
|
95
|
+
"Auto-Replication",
|
|
96
|
+
"Auto-Sync",
|
|
97
|
+
"Offline-Support",
|
|
98
|
+
"Write-Once-Deploy-Everywhere",
|
|
99
|
+
"Triple-Level-Quantum-Resistant-Encryption",
|
|
100
|
+
"Quantum",
|
|
101
|
+
"Encryption",
|
|
102
|
+
"Intelligent-Key-Management",
|
|
103
|
+
"Zero-Lag",
|
|
104
|
+
"Zero-Downtime",
|
|
105
|
+
"Agent-Centric",
|
|
106
|
+
"AI/Machine-Learning-Over-All-Of-World's-Aggregated-Data",
|
|
107
|
+
"HTTP-REST/gRPC/GraphQL/CLI/Native-Endpoints",
|
|
108
|
+
"Best-Of-All-Worlds",
|
|
109
|
+
"GOD-Protocol/API",
|
|
110
|
+
"More Coming..."
|
|
111
|
+
]
|
|
112
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_BASE_URL = 'https://api.web6.oasisomniverse.one';
|
|
4
|
+
|
|
5
|
+
function buildQueryString(query) {
|
|
6
|
+
const entries = Object.entries(query || {}).filter(([, v]) => v !== undefined && v !== null);
|
|
7
|
+
if (!entries.length) return '';
|
|
8
|
+
const params = new URLSearchParams();
|
|
9
|
+
for (const [key, value] of entries) {
|
|
10
|
+
params.set(key, typeof value === 'object' ? JSON.stringify(value) : String(value));
|
|
11
|
+
}
|
|
12
|
+
return `?${params.toString()}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Thin isomorphic HTTP client around the global fetch API (Node 18+, all modern browsers).
|
|
17
|
+
* Every WEB6 AI Layer API call ultimately goes through `request()` below - there are no mocked
|
|
18
|
+
* or stubbed responses anywhere in this SDK.
|
|
19
|
+
*/
|
|
20
|
+
class HttpClient {
|
|
21
|
+
constructor({ baseUrl = DEFAULT_BASE_URL, tokenStore, fetchImpl = globalThis.fetch } = {}) {
|
|
22
|
+
if (!fetchImpl) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
'No global fetch implementation found. Use Node 18+, a modern browser, or pass { fetchImpl } explicitly.'
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
this.baseUrl = baseUrl.replace(/\/+$/, '');
|
|
28
|
+
this.tokenStore = tokenStore;
|
|
29
|
+
this.fetchImpl = fetchImpl;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
setBaseUrl(baseUrl) {
|
|
33
|
+
this.baseUrl = baseUrl.replace(/\/+$/, '');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {string} verb GET | POST | PUT | DELETE
|
|
38
|
+
* @param {string} path e.g. "v1/complete"
|
|
39
|
+
* @param {object} [options]
|
|
40
|
+
* @param {object} [options.query] query string params (GET/DELETE)
|
|
41
|
+
* @param {object} [options.body] JSON body (POST/PUT/DELETE)
|
|
42
|
+
* @param {boolean} [options.auth] attach Authorization: Bearer <token> (default true)
|
|
43
|
+
* @param {string} [options.token] override token for this single request
|
|
44
|
+
*/
|
|
45
|
+
async request(verb, path, { query, body, auth = true, token } = {}) {
|
|
46
|
+
const url = `${this.baseUrl}/${path.replace(/^\/+/, '')}${buildQueryString(query)}`;
|
|
47
|
+
const headers = {
|
|
48
|
+
'Content-Type': 'application/json',
|
|
49
|
+
Accept: 'application/json'
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const bearer = token || (auth ? this.tokenStore?.getToken() : null);
|
|
53
|
+
if (bearer) headers.Authorization = `Bearer ${bearer}`;
|
|
54
|
+
|
|
55
|
+
const init = { method: verb, headers };
|
|
56
|
+
if (body !== undefined && verb !== 'GET') init.body = JSON.stringify(body);
|
|
57
|
+
|
|
58
|
+
let res;
|
|
59
|
+
try {
|
|
60
|
+
res = await this.fetchImpl(url, init);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
return { isError: true, message: `Network error calling ${url}: ${err.message}`, exception: err };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const text = await res.text();
|
|
66
|
+
let json;
|
|
67
|
+
try {
|
|
68
|
+
json = text ? JSON.parse(text) : null;
|
|
69
|
+
} catch {
|
|
70
|
+
json = null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
const message =
|
|
75
|
+
json?.result?.message || json?.message || json?.title || `Request failed with status ${res.status}`;
|
|
76
|
+
return { isError: true, message, statusCode: res.status, raw: json };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// OASIS responses are typically { isError, message, result: { isError, message, result: <payload> } }.
|
|
80
|
+
// We surface the innermost payload as `.result` while keeping the full envelope available as `.raw`.
|
|
81
|
+
const inner = json?.result !== undefined ? json.result : json;
|
|
82
|
+
const payload = inner?.result !== undefined ? inner.result : inner;
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
isError: Boolean(inner?.isError || json?.isError),
|
|
86
|
+
message: inner?.message || json?.message || null,
|
|
87
|
+
result: payload,
|
|
88
|
+
raw: json,
|
|
89
|
+
statusCode: res.status
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get(path, options) {
|
|
94
|
+
return this.request('GET', path, options);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
post(path, options) {
|
|
98
|
+
return this.request('POST', path, options);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
put(path, options) {
|
|
102
|
+
return this.request('PUT', path, options);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
delete(path, options) {
|
|
106
|
+
return this.request('DELETE', path, options);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module.exports = { HttpClient, DEFAULT_BASE_URL };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const TOKEN_PATTERN = /\{(\w+)(?::\w+)?\}/g;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a route template like "get-by-id/{id}" against an args object,
|
|
7
|
+
* substituting path tokens and returning the resolved path plus whatever
|
|
8
|
+
* args were *not* consumed as path tokens (these become the query/body).
|
|
9
|
+
*/
|
|
10
|
+
function resolveRoute(routeTemplate, args = {}) {
|
|
11
|
+
const consumed = new Set();
|
|
12
|
+
const path = routeTemplate.replace(TOKEN_PATTERN, (match, name) => {
|
|
13
|
+
const key = Object.keys(args).find((k) => k.toLowerCase() === name.toLowerCase());
|
|
14
|
+
consumed.add(key);
|
|
15
|
+
const value = key !== undefined ? args[key] : undefined;
|
|
16
|
+
if (value === undefined) {
|
|
17
|
+
throw new Error(`Missing required route parameter "${name}" for route "${routeTemplate}"`);
|
|
18
|
+
}
|
|
19
|
+
return encodeURIComponent(value);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const rest = {};
|
|
23
|
+
for (const [key, value] of Object.entries(args)) {
|
|
24
|
+
if (!consumed.has(key)) rest[key] = value;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return { path, rest };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function takeKey(obj, name) {
|
|
31
|
+
const matchKey = Object.keys(obj).find((k) => k.toLowerCase() === name.toLowerCase());
|
|
32
|
+
if (matchKey === undefined) return { found: false, value: undefined };
|
|
33
|
+
const value = obj[matchKey];
|
|
34
|
+
delete obj[matchKey];
|
|
35
|
+
return { found: true, value };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Builds a bound method for a single WEB6 endpoint operation.
|
|
40
|
+
* @param {import('./httpClient').HttpClient} http
|
|
41
|
+
* @param {string} routePrefix e.g. "api/avatar"
|
|
42
|
+
* @param {string} verb GET | POST | PUT | DELETE
|
|
43
|
+
* @param {string} route route template relative to routePrefix, e.g. "get-by-id/{id}"
|
|
44
|
+
* @param {object} [opts]
|
|
45
|
+
* @param {string[]} [opts.query] arg names that ASP.NET binds from the query
|
|
46
|
+
* string on this action regardless of HTTP verb (e.g. `[FromQuery]` flags
|
|
47
|
+
* mixed into an otherwise-body-bound POST/PUT action). Always sent as query.
|
|
48
|
+
* @param {string} [opts.bodyParam] when the action's entire request body is a
|
|
49
|
+
* single `[FromBody]` parameter (primitive or object), the JSON body is
|
|
50
|
+
* that arg's value directly rather than the leftover-args object wrapped
|
|
51
|
+
* around it.
|
|
52
|
+
*/
|
|
53
|
+
function makeOperation(http, routePrefix, verb, route, opts = {}) {
|
|
54
|
+
const declaredQueryKeys = opts.query || [];
|
|
55
|
+
const bodyParam = opts.bodyParam;
|
|
56
|
+
|
|
57
|
+
return async function operation(args = {}) {
|
|
58
|
+
const { path, rest } = resolveRoute(route, args);
|
|
59
|
+
const fullPath = path ? `${routePrefix}/${path}` : routePrefix;
|
|
60
|
+
|
|
61
|
+
const query = {};
|
|
62
|
+
for (const key of declaredQueryKeys) {
|
|
63
|
+
const { found, value } = takeKey(rest, key);
|
|
64
|
+
if (found) query[key] = value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let body;
|
|
68
|
+
if (bodyParam) {
|
|
69
|
+
const { found, value } = takeKey(rest, bodyParam);
|
|
70
|
+
if (found) body = value;
|
|
71
|
+
// Any args left over that we don't recognize still get sent (as query)
|
|
72
|
+
// rather than silently dropped.
|
|
73
|
+
Object.assign(query, rest);
|
|
74
|
+
} else if (verb === 'GET' || verb === 'DELETE') {
|
|
75
|
+
Object.assign(query, rest);
|
|
76
|
+
} else {
|
|
77
|
+
body = Object.keys(rest).length ? rest : undefined;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const hasQuery = Object.keys(query).length > 0;
|
|
81
|
+
return http.request(verb, fullPath, { query: hasQuery ? query : undefined, body });
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = { resolveRoute, makeOperation };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const hasLocalStorage = typeof globalThis.localStorage !== 'undefined';
|
|
4
|
+
const STORAGE_KEY = 'oasis_session';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Holds the current JWT/avatar session for the SDK.
|
|
8
|
+
* In the browser it persists to localStorage by default; in Node (or when
|
|
9
|
+
* persistence is disabled) it simply lives in memory for the lifetime of
|
|
10
|
+
* the client instance. Callers can always set/get/clear explicitly.
|
|
11
|
+
*/
|
|
12
|
+
class TokenStore {
|
|
13
|
+
constructor({ persist = hasLocalStorage } = {}) {
|
|
14
|
+
this.persist = persist;
|
|
15
|
+
this._session = null;
|
|
16
|
+
|
|
17
|
+
if (this.persist) {
|
|
18
|
+
try {
|
|
19
|
+
const raw = globalThis.localStorage.getItem(STORAGE_KEY);
|
|
20
|
+
if (raw) this._session = JSON.parse(raw);
|
|
21
|
+
} catch {
|
|
22
|
+
this._session = null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
getSession() {
|
|
28
|
+
return this._session;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getToken() {
|
|
32
|
+
return this._session?.jwtToken || this._session?.token || null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setSession(session) {
|
|
36
|
+
this._session = session || null;
|
|
37
|
+
if (this.persist) {
|
|
38
|
+
try {
|
|
39
|
+
if (session) globalThis.localStorage.setItem(STORAGE_KEY, JSON.stringify(session));
|
|
40
|
+
else globalThis.localStorage.removeItem(STORAGE_KEY);
|
|
41
|
+
} catch {
|
|
42
|
+
// Storage unavailable (e.g. private browsing) - in-memory session still works.
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
clear() {
|
|
48
|
+
this.setSession(null);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = { TokenStore };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/generate-types.js - do not hand-edit.
|
|
2
|
+
export interface OASISResponse<T = any> {
|
|
3
|
+
isError: boolean;
|
|
4
|
+
message: string | null;
|
|
5
|
+
result: T;
|
|
6
|
+
raw: any;
|
|
7
|
+
statusCode: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface OASISSession {
|
|
11
|
+
avatarId: string;
|
|
12
|
+
username: string;
|
|
13
|
+
email: string;
|
|
14
|
+
firstName?: string;
|
|
15
|
+
lastName?: string;
|
|
16
|
+
jwtToken: string;
|
|
17
|
+
refreshToken?: string;
|
|
18
|
+
}
|