@olane/os 0.7.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.
- package/README.md +947 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +2 -0
- package/dist/src/network/config/default.config.d.ts +3 -0
- package/dist/src/network/config/default.config.d.ts.map +1 -0
- package/dist/src/network/config/default.config.js +32 -0
- package/dist/src/network/index.d.ts +5 -0
- package/dist/src/network/index.d.ts.map +1 -0
- package/dist/src/network/index.js +4 -0
- package/dist/src/network/interfaces/network-status.enum.d.ts +7 -0
- package/dist/src/network/interfaces/network-status.enum.d.ts.map +1 -0
- package/dist/src/network/interfaces/network-status.enum.js +7 -0
- package/dist/src/network/interfaces/network.interface.d.ts +18 -0
- package/dist/src/network/interfaces/network.interface.d.ts.map +1 -0
- package/dist/src/network/interfaces/network.interface.js +1 -0
- package/dist/src/network/o-network.d.ts +34 -0
- package/dist/src/network/o-network.d.ts.map +1 -0
- package/dist/src/network/o-network.js +247 -0
- package/dist/src/o-olane-os/config/default.config.d.ts +3 -0
- package/dist/src/o-olane-os/config/default.config.d.ts.map +1 -0
- package/dist/src/o-olane-os/config/default.config.js +32 -0
- package/dist/src/o-olane-os/enum/o-os.status-enum.d.ts +7 -0
- package/dist/src/o-olane-os/enum/o-os.status-enum.d.ts.map +1 -0
- package/dist/src/o-olane-os/enum/o-os.status-enum.js +7 -0
- package/dist/src/o-olane-os/index.d.ts +5 -0
- package/dist/src/o-olane-os/index.d.ts.map +1 -0
- package/dist/src/o-olane-os/index.js +4 -0
- package/dist/src/o-olane-os/interfaces/o-os.config.d.ts +18 -0
- package/dist/src/o-olane-os/interfaces/o-os.config.d.ts.map +1 -0
- package/dist/src/o-olane-os/interfaces/o-os.config.js +1 -0
- package/dist/src/o-olane-os/o-os.d.ts +32 -0
- package/dist/src/o-olane-os/o-os.d.ts.map +1 -0
- package/dist/src/o-olane-os/o-os.js +207 -0
- package/dist/src/utils/config.d.ts +35 -0
- package/dist/src/utils/config.d.ts.map +1 -0
- package/dist/src/utils/config.js +82 -0
- package/dist/test/basic/basic-usage.spec.d.ts +1 -0
- package/dist/test/basic/basic-usage.spec.d.ts.map +1 -0
- package/dist/test/basic/basic-usage.spec.js +115 -0
- package/dist/test/basic/resolvers.spec.d.ts +1 -0
- package/dist/test/basic/resolvers.spec.d.ts.map +1 -0
- package/dist/test/basic/resolvers.spec.js +36 -0
- package/dist/test/benchmarks/benchmark.spec.d.ts +2 -0
- package/dist/test/benchmarks/benchmark.spec.d.ts.map +1 -0
- package/dist/test/benchmarks/benchmark.spec.js +65 -0
- package/dist/test/benchmarks/github/github.test-cases.d.ts +3 -0
- package/dist/test/benchmarks/github/github.test-cases.d.ts.map +1 -0
- package/dist/test/benchmarks/github/github.test-cases.js +236 -0
- package/dist/test/benchmarks/interfaces/test-case.interface.d.ts +10 -0
- package/dist/test/benchmarks/interfaces/test-case.interface.d.ts.map +1 -0
- package/dist/test/benchmarks/interfaces/test-case.interface.js +1 -0
- package/dist/test/local-mcp.spec.d.ts +1 -0
- package/dist/test/local-mcp.spec.d.ts.map +1 -0
- package/dist/test/local-mcp.spec.js +155 -0
- package/dist/test/utils/default.network.d.ts +3 -0
- package/dist/test/utils/default.network.d.ts.map +1 -0
- package/dist/test/utils/default.network.js +33 -0
- package/dist/test/utils/mcp-repo.d.ts +2 -0
- package/dist/test/utils/mcp-repo.d.ts.map +1 -0
- package/dist/test/utils/mcp-repo.js +5 -0
- package/dist/test/utils/models.d.ts +9 -0
- package/dist/test/utils/models.d.ts.map +1 -0
- package/dist/test/utils/models.js +8 -0
- package/dist/test/utils/os.default.d.ts +3 -0
- package/dist/test/utils/os.default.d.ts.map +1 -0
- package/dist/test/utils/os.default.js +33 -0
- package/package.json +79 -0
package/README.md
ADDED
|
@@ -0,0 +1,947 @@
|
|
|
1
|
+
# @olane/os
|
|
2
|
+
|
|
3
|
+
**Address**: `o://os` (system-level)
|
|
4
|
+
**Type**: Runtime System
|
|
5
|
+
**Domain**: Operating System / Infrastructure
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
`@olane/os` is the runtime system for Olane OS - the agentic operating system where agents (human or AI) are the users, tools are the applications, and Olane packages provide the infrastructure. OlaneOS manages the lifecycle, coordination, and execution of tools, nodes, and applications in a distributed environment.
|
|
10
|
+
|
|
11
|
+
Think of OlaneOS as the orchestration layer that:
|
|
12
|
+
- Starts and manages leader nodes for discovery and coordination
|
|
13
|
+
- Launches and supervises worker nodes containing tools
|
|
14
|
+
- Routes requests between agents and nodes
|
|
15
|
+
- Maintains system configuration and state
|
|
16
|
+
- Provides graceful lifecycle management (start, stop, restart)
|
|
17
|
+
|
|
18
|
+
## What You'll Learn
|
|
19
|
+
|
|
20
|
+
- How to create and start an Olane OS instance
|
|
21
|
+
- How to configure leaders and nodes in your OS
|
|
22
|
+
- How to manage OS instance lifecycle
|
|
23
|
+
- How to route requests to nodes
|
|
24
|
+
- How to persist and manage configuration
|
|
25
|
+
|
|
26
|
+
## Prerequisites
|
|
27
|
+
|
|
28
|
+
- Node.js 20+
|
|
29
|
+
- Basic understanding of the [Three-Layer Model](../../docs/understanding/three-layer-model.mdx)
|
|
30
|
+
- Familiarity with [Tools, Nodes, and Applications](../../docs/TOOL_NODE_APPLICATION_DISTINCTION.md)
|
|
31
|
+
|
|
32
|
+
**Time estimate**: 15-20 minutes
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install @olane/os
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Peer Dependencies
|
|
41
|
+
|
|
42
|
+
OlaneOS requires the following peer dependencies:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install @olane/o-core @olane/o-config @olane/o-protocol \
|
|
46
|
+
@olane/o-tool @olane/o-tools-common @olane/o-tool-registry \
|
|
47
|
+
@olane/o-intelligence @olane/o-leader @olane/o-lane @olane/o-storage
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
### Basic OS Instance
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { OlaneOS } from '@olane/os';
|
|
56
|
+
import { NodeType, oAddress } from '@olane/o-core';
|
|
57
|
+
|
|
58
|
+
// Create OS instance
|
|
59
|
+
const os = new OlaneOS({
|
|
60
|
+
nodes: [
|
|
61
|
+
{
|
|
62
|
+
type: NodeType.LEADER,
|
|
63
|
+
address: new oAddress('o://leader'),
|
|
64
|
+
leader: null,
|
|
65
|
+
parent: null,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
type: NodeType.NODE,
|
|
69
|
+
address: new oAddress('o://node'),
|
|
70
|
+
leader: null,
|
|
71
|
+
parent: null,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Start the OS
|
|
77
|
+
await os.start();
|
|
78
|
+
|
|
79
|
+
// Use a node via the OS
|
|
80
|
+
const result = await os.use(
|
|
81
|
+
new oAddress('o://node'),
|
|
82
|
+
{
|
|
83
|
+
method: 'some_tool',
|
|
84
|
+
params: { /* ... */ }
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// Stop the OS gracefully
|
|
89
|
+
await os.stop();
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Expected Output
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
OS instance started...
|
|
96
|
+
Root leader at: o://leader
|
|
97
|
+
Nodes: 1 worker node(s)
|
|
98
|
+
Status: RUNNING
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Architecture
|
|
102
|
+
|
|
103
|
+
### System Components
|
|
104
|
+
|
|
105
|
+
OlaneOS manages three primary components:
|
|
106
|
+
|
|
107
|
+
| Component | Type | Purpose | Address Pattern |
|
|
108
|
+
|-----------|------|---------|-----------------|
|
|
109
|
+
| **Root Leader** | oLeaderNode | Discovery, coordination, registry | `o://leader` |
|
|
110
|
+
| **Leaders** | oLeaderNode[] | Load-balanced leader instances | `o://leader/*` |
|
|
111
|
+
| **Nodes** | oLaneTool[] | Worker nodes with tools | `o://*` |
|
|
112
|
+
|
|
113
|
+
### Architecture Diagram
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
┌─────────────────────────────────────────────────────────┐
|
|
117
|
+
│ Layer 1: USERS (Agents) │
|
|
118
|
+
│ ✓ Humans (via CLI, web, API) │
|
|
119
|
+
│ ✓ AI (GPT-4, Claude, Gemini) │
|
|
120
|
+
└─────────────────────────────────────────────────────────┘
|
|
121
|
+
⬇ sends requests
|
|
122
|
+
┌─────────────────────────────────────────────────────────┐
|
|
123
|
+
│ OlaneOS Runtime │
|
|
124
|
+
│ │
|
|
125
|
+
│ ┌───────────────────────────────────────────────┐ │
|
|
126
|
+
│ │ Entry Point Router (round-robin) │ │
|
|
127
|
+
│ └───────────────────────────────────────────────┘ │
|
|
128
|
+
│ ⬇ │
|
|
129
|
+
│ ┌────────────────┐ ┌────────────────────────┐ │
|
|
130
|
+
│ │ Root Leader │──────│ Node 1 (oLaneTool) │ │
|
|
131
|
+
│ │ o://leader │ │ • Tools: [A, B, C] │ │
|
|
132
|
+
│ │ • Discovery │ │ • Capabilities │ │
|
|
133
|
+
│ │ • Registry │ └────────────────────────┘ │
|
|
134
|
+
│ │ • Coordination│ │
|
|
135
|
+
│ └────────────────┘ ┌────────────────────────┐ │
|
|
136
|
+
│ │ │ Node 2 (oLaneTool) │ │
|
|
137
|
+
│ └────────────────│ • Tools: [D, E, F] │ │
|
|
138
|
+
│ │ • Capabilities │ │
|
|
139
|
+
│ └────────────────────────┘ │
|
|
140
|
+
└─────────────────────────────────────────────────────────┘
|
|
141
|
+
⬇ manages
|
|
142
|
+
┌─────────────────────────────────────────────────────────┐
|
|
143
|
+
│ Layer 3: INFRASTRUCTURE (Olane OS) │
|
|
144
|
+
│ • Network discovery (libp2p) │
|
|
145
|
+
│ • Message routing │
|
|
146
|
+
│ • Configuration persistence │
|
|
147
|
+
└─────────────────────────────────────────────────────────┘
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Core Concepts
|
|
151
|
+
|
|
152
|
+
### OS Instance Lifecycle
|
|
153
|
+
|
|
154
|
+
OlaneOS follows a clear lifecycle with four states:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
enum OlaneOSSystemStatus {
|
|
158
|
+
STARTING = 'starting', // Initializing configuration and nodes
|
|
159
|
+
RUNNING = 'running', // Operational and accepting requests
|
|
160
|
+
STOPPING = 'stopping', // Gracefully shutting down nodes
|
|
161
|
+
STOPPED = 'stopped' // Fully stopped
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### Lifecycle Flow
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
STOPPED → start() → STARTING → [initialize] → RUNNING
|
|
169
|
+
⬆ │
|
|
170
|
+
│ │
|
|
171
|
+
└───────── stop() ← STOPPING ← [shutdown] ────┘
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Entry Point Routing
|
|
175
|
+
|
|
176
|
+
OlaneOS uses round-robin routing to distribute requests across nodes:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// Requests are automatically load-balanced
|
|
180
|
+
const result1 = await os.use(address, params); // → Node 1
|
|
181
|
+
const result2 = await os.use(address, params); // → Node 2
|
|
182
|
+
const result3 = await os.use(address, params); // → Node 1
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
This provides:
|
|
186
|
+
- **Load distribution** across worker nodes
|
|
187
|
+
- **Fault tolerance** if nodes fail
|
|
188
|
+
- **Scalability** by adding more node instances
|
|
189
|
+
|
|
190
|
+
### Configuration Management
|
|
191
|
+
|
|
192
|
+
OlaneOS supports two configuration approaches:
|
|
193
|
+
|
|
194
|
+
**1. Programmatic Configuration** (ephemeral)
|
|
195
|
+
```typescript
|
|
196
|
+
const os = new OlaneOS({
|
|
197
|
+
nodes: [/* node configs */],
|
|
198
|
+
lanes: [/* saved plans */],
|
|
199
|
+
noIndexNetwork: false
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**2. File-Based Configuration** (persistent)
|
|
204
|
+
```typescript
|
|
205
|
+
const os = new OlaneOS({
|
|
206
|
+
configFilePath: '/path/to/config.json'
|
|
207
|
+
});
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Configuration files follow this structure:
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"name": "my-olane-os",
|
|
215
|
+
"version": "0.0.1",
|
|
216
|
+
"description": "My Olane OS instance",
|
|
217
|
+
"port": 4999,
|
|
218
|
+
"oNetworkConfig": {
|
|
219
|
+
"nodes": [
|
|
220
|
+
{
|
|
221
|
+
"type": "leader",
|
|
222
|
+
"address": { "value": "o://leader" },
|
|
223
|
+
"network": {
|
|
224
|
+
"listeners": ["/ip4/0.0.0.0/tcp/4999"]
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"type": "node",
|
|
229
|
+
"address": { "value": "o://my-node" }
|
|
230
|
+
}
|
|
231
|
+
],
|
|
232
|
+
"lanes": [],
|
|
233
|
+
"noIndexNetwork": false
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Configuration Reference
|
|
239
|
+
|
|
240
|
+
### OlaneOSConfig Interface
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
interface OlaneOSConfig {
|
|
244
|
+
// Path to persistent configuration file
|
|
245
|
+
configFilePath?: string;
|
|
246
|
+
|
|
247
|
+
// Network metadata
|
|
248
|
+
network?: {
|
|
249
|
+
name?: string;
|
|
250
|
+
version?: string;
|
|
251
|
+
description?: string;
|
|
252
|
+
icon?: string;
|
|
253
|
+
website?: string;
|
|
254
|
+
networkId?: string;
|
|
255
|
+
port?: number;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// Node configurations to start
|
|
259
|
+
nodes?: oNodeConfig[];
|
|
260
|
+
|
|
261
|
+
// Saved plans/lanes to run on startup
|
|
262
|
+
lanes?: string[];
|
|
263
|
+
|
|
264
|
+
// Skip network indexing on startup
|
|
265
|
+
noIndexNetwork?: boolean;
|
|
266
|
+
|
|
267
|
+
// In-progress operations
|
|
268
|
+
inProgress?: string[];
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Node Configuration
|
|
273
|
+
|
|
274
|
+
Each node in the `nodes` array follows the `oNodeConfig` interface:
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
{
|
|
278
|
+
type: NodeType.LEADER | NodeType.NODE,
|
|
279
|
+
address: oAddress,
|
|
280
|
+
leader: oAddress | null,
|
|
281
|
+
parent: oAddress | null,
|
|
282
|
+
network?: {
|
|
283
|
+
listeners?: string[] // libp2p listener addresses
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## API Reference
|
|
289
|
+
|
|
290
|
+
### OlaneOS Class
|
|
291
|
+
|
|
292
|
+
#### Constructor
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
constructor(config: OlaneOSConfig)
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Creates a new OlaneOS instance with the specified configuration.
|
|
299
|
+
|
|
300
|
+
**Parameters**:
|
|
301
|
+
- `config` - Configuration object or file path
|
|
302
|
+
|
|
303
|
+
**Example**:
|
|
304
|
+
```typescript
|
|
305
|
+
const os = new OlaneOS({
|
|
306
|
+
configFilePath: './config.json'
|
|
307
|
+
});
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### start()
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
async start(): Promise<{ peerId: string; transports: oTransport[] }>
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Starts the OS instance, initializes configuration, launches all nodes, and runs saved plans.
|
|
317
|
+
|
|
318
|
+
**Returns**:
|
|
319
|
+
```typescript
|
|
320
|
+
{
|
|
321
|
+
peerId: string, // Peer ID of root leader
|
|
322
|
+
transports: oTransport[] // Active network transports
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
**Lifecycle**:
|
|
327
|
+
1. Load configuration from file (if specified)
|
|
328
|
+
2. Start leader nodes
|
|
329
|
+
3. Start worker nodes
|
|
330
|
+
4. Run saved plans/lanes
|
|
331
|
+
5. Index network (unless `noIndexNetwork: true`)
|
|
332
|
+
6. Set status to `RUNNING`
|
|
333
|
+
|
|
334
|
+
**Example**:
|
|
335
|
+
```typescript
|
|
336
|
+
const { peerId, transports } = await os.start();
|
|
337
|
+
console.log(`OS started with peer ID: ${peerId}`);
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
#### stop()
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
async stop(): Promise<void>
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Gracefully stops all nodes in the OS instance.
|
|
347
|
+
|
|
348
|
+
**Lifecycle**:
|
|
349
|
+
1. Set status to `STOPPING`
|
|
350
|
+
2. Stop all worker nodes in parallel
|
|
351
|
+
3. Stop all leader nodes in parallel
|
|
352
|
+
4. Stop root leader
|
|
353
|
+
5. Set status to `STOPPED`
|
|
354
|
+
|
|
355
|
+
**Example**:
|
|
356
|
+
```typescript
|
|
357
|
+
await os.stop();
|
|
358
|
+
console.log('OS stopped successfully');
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### restart()
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
async restart(): Promise<void>
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
Restarts the OS instance by stopping and starting again.
|
|
368
|
+
|
|
369
|
+
**Example**:
|
|
370
|
+
```typescript
|
|
371
|
+
await os.restart();
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### use()
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
async use(address: oAddress, params: any): Promise<any>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Routes a request to a node via the entry point router.
|
|
381
|
+
|
|
382
|
+
**Parameters**:
|
|
383
|
+
- `address` - Target node address (e.g., `o://node/tool`)
|
|
384
|
+
- `params` - Request parameters including method and params
|
|
385
|
+
|
|
386
|
+
**Returns**: Result from the target node
|
|
387
|
+
|
|
388
|
+
**Example**:
|
|
389
|
+
```typescript
|
|
390
|
+
const result = await os.use(
|
|
391
|
+
new oAddress('o://financial-analyst'),
|
|
392
|
+
{
|
|
393
|
+
method: 'intent',
|
|
394
|
+
params: {
|
|
395
|
+
intent: 'Analyze Q4 revenue trends'
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
);
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
#### addNode()
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
async addNode(node: oLaneTool | oLeaderNode): Promise<void>
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Dynamically adds a node to a running OS instance.
|
|
408
|
+
|
|
409
|
+
**Requirements**:
|
|
410
|
+
- OS must be in `RUNNING` status
|
|
411
|
+
- At least one existing node must be present
|
|
412
|
+
|
|
413
|
+
**Example**:
|
|
414
|
+
```typescript
|
|
415
|
+
import { oLaneTool } from '@olane/o-lane';
|
|
416
|
+
|
|
417
|
+
const newNode = new oLaneTool({
|
|
418
|
+
address: new oAddress('o://new-node'),
|
|
419
|
+
leader: os.rootLeader?.address
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
await os.addNode(newNode);
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
#### addLeader()
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
addLeader(leader: oLeaderNode): void
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Adds a leader node to the OS instance. First leader added becomes the root leader.
|
|
432
|
+
|
|
433
|
+
**Example**:
|
|
434
|
+
```typescript
|
|
435
|
+
import { oLeaderNode } from '@olane/o-leader';
|
|
436
|
+
|
|
437
|
+
const leader = new oLeaderNode({
|
|
438
|
+
address: new oAddress('o://leader'),
|
|
439
|
+
leader: null,
|
|
440
|
+
parent: null
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
os.addLeader(leader);
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Properties
|
|
447
|
+
|
|
448
|
+
#### status
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
readonly status: OlaneOSSystemStatus
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
Current status of the OS instance.
|
|
455
|
+
|
|
456
|
+
**Values**:
|
|
457
|
+
- `STARTING` - Initialization in progress
|
|
458
|
+
- `RUNNING` - Operational
|
|
459
|
+
- `STOPPING` - Shutdown in progress
|
|
460
|
+
- `STOPPED` - Not running
|
|
461
|
+
|
|
462
|
+
#### rootLeader
|
|
463
|
+
|
|
464
|
+
```typescript
|
|
465
|
+
readonly rootLeader: oLeaderNode | null
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Reference to the root leader node (provides discovery and coordination).
|
|
469
|
+
|
|
470
|
+
**Example**:
|
|
471
|
+
```typescript
|
|
472
|
+
if (os.rootLeader) {
|
|
473
|
+
console.log(`Root leader: ${os.rootLeader.address.toString()}`);
|
|
474
|
+
console.log(`Peer ID: ${os.rootLeader.peerId.toString()}`);
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Configuration Manager
|
|
479
|
+
|
|
480
|
+
### ConfigManager Class
|
|
481
|
+
|
|
482
|
+
Static utility class for managing OS instance configurations.
|
|
483
|
+
|
|
484
|
+
#### initialize()
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
static async initialize(): Promise<void>
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Ensures config directories exist and creates default config file if needed.
|
|
491
|
+
|
|
492
|
+
#### getConfig()
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
static async getConfig(): Promise<CLIConfig>
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
Retrieves the CLI configuration.
|
|
499
|
+
|
|
500
|
+
#### saveOSConfig()
|
|
501
|
+
|
|
502
|
+
```typescript
|
|
503
|
+
static async saveOSConfig(config: OlaneOSInstanceConfig): Promise<void>
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
Persists an OS instance configuration to disk.
|
|
507
|
+
|
|
508
|
+
**Example**:
|
|
509
|
+
```typescript
|
|
510
|
+
import { ConfigManager } from '@olane/os';
|
|
511
|
+
|
|
512
|
+
await ConfigManager.saveOSConfig({
|
|
513
|
+
name: 'production-os',
|
|
514
|
+
version: '1.0.0',
|
|
515
|
+
description: 'Production OS instance',
|
|
516
|
+
port: 4999,
|
|
517
|
+
status: OlaneOSSystemStatus.STOPPED,
|
|
518
|
+
oNetworkConfig: {
|
|
519
|
+
nodes: [/* ... */]
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
#### getOSConfig()
|
|
525
|
+
|
|
526
|
+
```typescript
|
|
527
|
+
static async getOSConfig(name: string): Promise<OlaneOSInstanceConfig | null>
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
Loads an OS instance configuration by name.
|
|
531
|
+
|
|
532
|
+
**Example**:
|
|
533
|
+
```typescript
|
|
534
|
+
const config = await ConfigManager.getOSConfig('production-os');
|
|
535
|
+
if (config) {
|
|
536
|
+
console.log(`Found OS: ${config.name}`);
|
|
537
|
+
}
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
#### listOSInstances()
|
|
541
|
+
|
|
542
|
+
```typescript
|
|
543
|
+
static async listOSInstances(): Promise<OlaneOSInstanceConfig[]>
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
Lists all saved OS instance configurations.
|
|
547
|
+
|
|
548
|
+
**Example**:
|
|
549
|
+
```typescript
|
|
550
|
+
const instances = await ConfigManager.listOSInstances();
|
|
551
|
+
instances.forEach(instance => {
|
|
552
|
+
console.log(`${instance.name} - ${instance.status}`);
|
|
553
|
+
});
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
#### deleteOSInstance()
|
|
557
|
+
|
|
558
|
+
```typescript
|
|
559
|
+
static async deleteOSInstance(name: string): Promise<void>
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
Deletes a saved OS instance configuration.
|
|
563
|
+
|
|
564
|
+
## Use Cases
|
|
565
|
+
|
|
566
|
+
### Use Case 1: Development Environment
|
|
567
|
+
|
|
568
|
+
Create a local development OS instance for testing nodes and tools.
|
|
569
|
+
|
|
570
|
+
```typescript
|
|
571
|
+
import { OlaneOS } from '@olane/os';
|
|
572
|
+
import { NodeType, oAddress, setupGracefulShutdown } from '@olane/o-core';
|
|
573
|
+
|
|
574
|
+
const devOS = new OlaneOS({
|
|
575
|
+
network: {
|
|
576
|
+
name: 'dev-environment',
|
|
577
|
+
port: 4999
|
|
578
|
+
},
|
|
579
|
+
nodes: [
|
|
580
|
+
{
|
|
581
|
+
type: NodeType.LEADER,
|
|
582
|
+
address: new oAddress('o://leader'),
|
|
583
|
+
leader: null,
|
|
584
|
+
parent: null,
|
|
585
|
+
network: {
|
|
586
|
+
listeners: ['/ip4/127.0.0.1/tcp/4999']
|
|
587
|
+
}
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
type: NodeType.NODE,
|
|
591
|
+
address: new oAddress('o://dev-node'),
|
|
592
|
+
leader: null,
|
|
593
|
+
parent: null
|
|
594
|
+
}
|
|
595
|
+
],
|
|
596
|
+
noIndexNetwork: true // Skip indexing for faster startup
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
// Graceful shutdown on Ctrl+C
|
|
600
|
+
setupGracefulShutdown(
|
|
601
|
+
async () => {
|
|
602
|
+
console.log('Shutting down dev environment...');
|
|
603
|
+
await devOS.stop();
|
|
604
|
+
},
|
|
605
|
+
{ timeout: 30000 }
|
|
606
|
+
);
|
|
607
|
+
|
|
608
|
+
await devOS.start();
|
|
609
|
+
console.log('Development OS ready!');
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
### Use Case 2: Production Multi-Node System
|
|
613
|
+
|
|
614
|
+
Deploy a production OS with multiple worker nodes and persistent configuration.
|
|
615
|
+
|
|
616
|
+
```typescript
|
|
617
|
+
import { OlaneOS, ConfigManager } from '@olane/os';
|
|
618
|
+
import { NodeType, oAddress } from '@olane/o-core';
|
|
619
|
+
|
|
620
|
+
// Save production configuration
|
|
621
|
+
await ConfigManager.saveOSConfig({
|
|
622
|
+
name: 'production-os',
|
|
623
|
+
version: '1.0.0',
|
|
624
|
+
description: 'Production CRM application',
|
|
625
|
+
port: 5000,
|
|
626
|
+
status: OlaneOSSystemStatus.STOPPED,
|
|
627
|
+
oNetworkConfig: {
|
|
628
|
+
configFilePath: '/etc/olane/production-config.json',
|
|
629
|
+
network: {
|
|
630
|
+
name: 'production-crm',
|
|
631
|
+
port: 5000,
|
|
632
|
+
networkId: 'prod-001'
|
|
633
|
+
},
|
|
634
|
+
nodes: [
|
|
635
|
+
{
|
|
636
|
+
type: NodeType.LEADER,
|
|
637
|
+
address: new oAddress('o://leader'),
|
|
638
|
+
network: {
|
|
639
|
+
listeners: ['/ip4/0.0.0.0/tcp/5000']
|
|
640
|
+
}
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
type: NodeType.NODE,
|
|
644
|
+
address: new oAddress('o://crm/customers')
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
type: NodeType.NODE,
|
|
648
|
+
address: new oAddress('o://crm/sales')
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
type: NodeType.NODE,
|
|
652
|
+
address: new oAddress('o://crm/analytics')
|
|
653
|
+
}
|
|
654
|
+
]
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
// Load and start from saved config
|
|
659
|
+
const config = await ConfigManager.getOSConfig('production-os');
|
|
660
|
+
const prodOS = new OlaneOS(config!.oNetworkConfig!);
|
|
661
|
+
await prodOS.start();
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### Use Case 3: Dynamic Node Addition
|
|
665
|
+
|
|
666
|
+
Add nodes to a running OS instance without restart.
|
|
667
|
+
|
|
668
|
+
```typescript
|
|
669
|
+
import { OlaneOS } from '@olane/os';
|
|
670
|
+
import { oLaneTool } from '@olane/o-lane';
|
|
671
|
+
import { oAddress } from '@olane/o-core';
|
|
672
|
+
|
|
673
|
+
// Start minimal OS
|
|
674
|
+
const os = new OlaneOS({
|
|
675
|
+
nodes: [
|
|
676
|
+
{ type: NodeType.LEADER, address: new oAddress('o://leader') },
|
|
677
|
+
{ type: NodeType.NODE, address: new oAddress('o://base') }
|
|
678
|
+
]
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
await os.start();
|
|
682
|
+
|
|
683
|
+
// Later, add new capability dynamically
|
|
684
|
+
const newNode = new oLaneTool({
|
|
685
|
+
address: new oAddress('o://new-capability'),
|
|
686
|
+
leader: os.rootLeader?.address,
|
|
687
|
+
parent: os.rootLeader?.address
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
await os.addNode(newNode);
|
|
691
|
+
console.log('New capability added without restart!');
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
### Use Case 4: Saved Plans Execution
|
|
695
|
+
|
|
696
|
+
Automatically run saved plans/lanes on OS startup.
|
|
697
|
+
|
|
698
|
+
```typescript
|
|
699
|
+
import { OlaneOS } from '@olane/os';
|
|
700
|
+
|
|
701
|
+
const os = new OlaneOS({
|
|
702
|
+
configFilePath: './config.json',
|
|
703
|
+
lanes: [
|
|
704
|
+
'o://monitor/system-health', // Auto-runs on startup
|
|
705
|
+
'o://backup/daily-snapshot' // Auto-runs on startup
|
|
706
|
+
]
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
await os.start();
|
|
710
|
+
// Saved plans execute automatically during startup
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
## Advanced Usage
|
|
714
|
+
|
|
715
|
+
### Custom Entry Point Selection
|
|
716
|
+
|
|
717
|
+
Override the default round-robin routing:
|
|
718
|
+
|
|
719
|
+
```typescript
|
|
720
|
+
class CustomOS extends OlaneOS {
|
|
721
|
+
entryNode() {
|
|
722
|
+
// Custom routing logic (e.g., based on load, region, etc.)
|
|
723
|
+
return this.selectOptimalNode();
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
private selectOptimalNode() {
|
|
727
|
+
// Your custom selection algorithm
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
### Monitoring OS Health
|
|
733
|
+
|
|
734
|
+
```typescript
|
|
735
|
+
import { OlaneOS, OlaneOSSystemStatus } from '@olane/os';
|
|
736
|
+
|
|
737
|
+
const os = new OlaneOS(config);
|
|
738
|
+
await os.start();
|
|
739
|
+
|
|
740
|
+
// Monitor status
|
|
741
|
+
setInterval(() => {
|
|
742
|
+
console.log(`OS Status: ${os.status}`);
|
|
743
|
+
console.log(`Root Leader: ${os.rootLeader?.peerId}`);
|
|
744
|
+
console.log(`Active Transports: ${os.rootLeader?.transports.length}`);
|
|
745
|
+
}, 5000);
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
### Multi-Instance Management
|
|
749
|
+
|
|
750
|
+
```typescript
|
|
751
|
+
import { ConfigManager } from '@olane/os';
|
|
752
|
+
|
|
753
|
+
// List all OS instances
|
|
754
|
+
const instances = await ConfigManager.listOSInstances();
|
|
755
|
+
|
|
756
|
+
// Start specific instance
|
|
757
|
+
const targetInstance = instances.find(i => i.name === 'staging-os');
|
|
758
|
+
if (targetInstance) {
|
|
759
|
+
const os = new OlaneOS(targetInstance.oNetworkConfig!);
|
|
760
|
+
await os.start();
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// Clean up old instances
|
|
764
|
+
for (const instance of instances) {
|
|
765
|
+
if (instance.status === OlaneOSSystemStatus.STOPPED) {
|
|
766
|
+
await ConfigManager.deleteOSInstance(instance.name);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
## Best Practices
|
|
772
|
+
|
|
773
|
+
### 1. Always Use Graceful Shutdown
|
|
774
|
+
|
|
775
|
+
```typescript
|
|
776
|
+
import { setupGracefulShutdown } from '@olane/o-core';
|
|
777
|
+
|
|
778
|
+
setupGracefulShutdown(
|
|
779
|
+
async () => {
|
|
780
|
+
await os.stop();
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
timeout: 30000,
|
|
784
|
+
onTimeout: () => {
|
|
785
|
+
console.error('Forced shutdown after timeout');
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
);
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
### 2. Persist Critical Configurations
|
|
792
|
+
|
|
793
|
+
```typescript
|
|
794
|
+
// Use file-based config for production
|
|
795
|
+
const os = new OlaneOS({
|
|
796
|
+
configFilePath: process.env.OLANE_CONFIG_PATH || './config.json'
|
|
797
|
+
});
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
### 3. Monitor OS Lifecycle
|
|
801
|
+
|
|
802
|
+
```typescript
|
|
803
|
+
const os = new OlaneOS(config);
|
|
804
|
+
|
|
805
|
+
// Before starting
|
|
806
|
+
console.log('Initial status:', os.status); // STOPPED
|
|
807
|
+
|
|
808
|
+
await os.start();
|
|
809
|
+
console.log('After start:', os.status); // RUNNING
|
|
810
|
+
|
|
811
|
+
await os.stop();
|
|
812
|
+
console.log('After stop:', os.status); // STOPPED
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
### 4. Handle Startup Errors
|
|
816
|
+
|
|
817
|
+
```typescript
|
|
818
|
+
try {
|
|
819
|
+
await os.start();
|
|
820
|
+
} catch (error) {
|
|
821
|
+
console.error('Failed to start OS:', error);
|
|
822
|
+
|
|
823
|
+
// Attempt cleanup
|
|
824
|
+
if (os.status !== OlaneOSSystemStatus.STOPPED) {
|
|
825
|
+
await os.stop();
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
process.exit(1);
|
|
829
|
+
}
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
### 5. Use Network Indexing Appropriately
|
|
833
|
+
|
|
834
|
+
```typescript
|
|
835
|
+
// Development: Skip indexing for faster startup
|
|
836
|
+
const devOS = new OlaneOS({
|
|
837
|
+
noIndexNetwork: true,
|
|
838
|
+
nodes: [/* ... */]
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
// Production: Enable indexing for discovery
|
|
842
|
+
const prodOS = new OlaneOS({
|
|
843
|
+
noIndexNetwork: false, // Indexes all nodes on startup
|
|
844
|
+
nodes: [/* ... */]
|
|
845
|
+
});
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
## Troubleshooting
|
|
849
|
+
|
|
850
|
+
### Issue: OS fails to start
|
|
851
|
+
|
|
852
|
+
**Symptom**: Error "No nodes found in config"
|
|
853
|
+
|
|
854
|
+
**Solution**: Ensure your configuration includes at least one leader and one worker node:
|
|
855
|
+
|
|
856
|
+
```typescript
|
|
857
|
+
const os = new OlaneOS({
|
|
858
|
+
nodes: [
|
|
859
|
+
{
|
|
860
|
+
type: NodeType.LEADER,
|
|
861
|
+
address: new oAddress('o://leader')
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
type: NodeType.NODE,
|
|
865
|
+
address: new oAddress('o://worker')
|
|
866
|
+
}
|
|
867
|
+
]
|
|
868
|
+
});
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
### Issue: Cannot add node to running OS
|
|
872
|
+
|
|
873
|
+
**Symptom**: Error "OS instance is not running"
|
|
874
|
+
|
|
875
|
+
**Solution**: Ensure OS has started before adding nodes:
|
|
876
|
+
|
|
877
|
+
```typescript
|
|
878
|
+
await os.start();
|
|
879
|
+
// Wait for RUNNING status
|
|
880
|
+
while (os.status !== OlaneOSSystemStatus.RUNNING) {
|
|
881
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
882
|
+
}
|
|
883
|
+
// Now safe to add nodes
|
|
884
|
+
await os.addNode(newNode);
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
### Issue: Config file not loading
|
|
888
|
+
|
|
889
|
+
**Symptom**: Warning "No config file path provided, using default config"
|
|
890
|
+
|
|
891
|
+
**Solution**: Verify the config file path exists and is accessible:
|
|
892
|
+
|
|
893
|
+
```typescript
|
|
894
|
+
import fs from 'fs-extra';
|
|
895
|
+
|
|
896
|
+
const configPath = './config.json';
|
|
897
|
+
await fs.ensureFile(configPath);
|
|
898
|
+
|
|
899
|
+
const os = new OlaneOS({
|
|
900
|
+
configFilePath: configPath
|
|
901
|
+
});
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
### Issue: Port already in use
|
|
905
|
+
|
|
906
|
+
**Symptom**: Error binding to network port
|
|
907
|
+
|
|
908
|
+
**Solution**: Change the port in your configuration:
|
|
909
|
+
|
|
910
|
+
```typescript
|
|
911
|
+
const os = new OlaneOS({
|
|
912
|
+
network: {
|
|
913
|
+
port: 5000 // Use different port
|
|
914
|
+
},
|
|
915
|
+
nodes: [
|
|
916
|
+
{
|
|
917
|
+
type: NodeType.LEADER,
|
|
918
|
+
network: {
|
|
919
|
+
listeners: ['/ip4/0.0.0.0/tcp/5000']
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
]
|
|
923
|
+
});
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
## Related Documentation
|
|
927
|
+
|
|
928
|
+
- [Three-Layer Model](../../docs/understanding/three-layer-model.mdx) - Understanding the Olane OS architecture
|
|
929
|
+
- [Tools, Nodes, and Applications](../../docs/TOOL_NODE_APPLICATION_DISTINCTION.md) - Terminology and patterns
|
|
930
|
+
- [@olane/o-leader](../o-leader/README.md) - Leader node for discovery and coordination
|
|
931
|
+
- [@olane/o-lane](../o-lane/README.md) - Complex nodes with autonomous execution
|
|
932
|
+
- [@olane/o-node](../o-node/README.md) - Simple node implementation
|
|
933
|
+
|
|
934
|
+
## Contributing
|
|
935
|
+
|
|
936
|
+
We welcome contributions! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.
|
|
937
|
+
|
|
938
|
+
## License
|
|
939
|
+
|
|
940
|
+
ISC © oLane Inc.
|
|
941
|
+
|
|
942
|
+
---
|
|
943
|
+
|
|
944
|
+
**Package Version**: 0.6.12
|
|
945
|
+
**Last Updated**: October 1, 2025
|
|
946
|
+
**Status**: Active development
|
|
947
|
+
|