@olane/os 0.7.12-alpha.24 → 0.7.12-alpha.26
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/dist/src/o-olane-os/config/default.config.d.ts.map +1 -1
- package/dist/test/basic/basic-usage.spec.js +21 -9
- package/package.json +12 -12
- package/dist/src/network/config/default.config.d.ts +0 -3
- package/dist/src/network/config/default.config.d.ts.map +0 -1
- package/dist/src/network/config/default.config.js +0 -32
- package/dist/src/network/index.d.ts +0 -5
- package/dist/src/network/index.d.ts.map +0 -1
- package/dist/src/network/index.js +0 -4
- package/dist/src/network/interfaces/network-status.enum.d.ts +0 -7
- package/dist/src/network/interfaces/network-status.enum.d.ts.map +0 -1
- package/dist/src/network/interfaces/network-status.enum.js +0 -7
- package/dist/src/network/interfaces/network.interface.d.ts +0 -18
- package/dist/src/network/interfaces/network.interface.d.ts.map +0 -1
- package/dist/src/network/interfaces/network.interface.js +0 -1
- package/dist/src/network/o-network.d.ts +0 -34
- package/dist/src/network/o-network.d.ts.map +0 -1
- package/dist/src/network/o-network.js +0 -247
- package/dist/test/basic/streaming-usage.spec.d.ts +0 -2
- package/dist/test/basic/streaming-usage.spec.d.ts.map +0 -1
- package/dist/test/basic/streaming-usage.spec.js +0 -314
- package/dist/test/utils/default.network.d.ts +0 -3
- package/dist/test/utils/default.network.d.ts.map +0 -1
- package/dist/test/utils/default.network.js +0 -33
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default.config.d.ts","sourceRoot":"","sources":["../../../../src/o-olane-os/config/default.config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAG7D,eAAO,MAAM,uBAAuB,
|
|
1
|
+
{"version":3,"file":"default.config.d.ts","sourceRoot":"","sources":["../../../../src/o-olane-os/config/default.config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAG7D,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,KAAG,aAmCtD,CAAC"}
|
|
@@ -40,22 +40,34 @@ describe('basic-usage @initialize', async () => {
|
|
|
40
40
|
// },
|
|
41
41
|
// });
|
|
42
42
|
// use the intelligence tool
|
|
43
|
-
await entryNode.useStream(new oNodeAddress('o://
|
|
44
|
-
method: '
|
|
43
|
+
await entryNode.useStream(new oNodeAddress('o://leader'), {
|
|
44
|
+
method: 'intent',
|
|
45
45
|
params: {
|
|
46
46
|
_isStream: true,
|
|
47
|
-
|
|
48
|
-
{
|
|
49
|
-
role: 'user',
|
|
50
|
-
content: 'What is the weather in Tokyo?',
|
|
51
|
-
},
|
|
52
|
-
],
|
|
47
|
+
intent: 'What is the official endpoint for github mcp server?',
|
|
53
48
|
},
|
|
54
49
|
}, {
|
|
55
50
|
onChunk: (chunk) => {
|
|
56
|
-
console.log('Received chunk: ', chunk.result.data);
|
|
51
|
+
console.log('Received chunk: ', JSON.stringify(chunk.result.data, null, 2));
|
|
57
52
|
},
|
|
58
53
|
});
|
|
54
|
+
// await entryNode.use(
|
|
55
|
+
// new oNodeAddress('o://intelligence'),
|
|
56
|
+
// {
|
|
57
|
+
// method: 'prompt',
|
|
58
|
+
// params: {
|
|
59
|
+
// _isStream: true,
|
|
60
|
+
// prompt: 'What is the capital of France?',
|
|
61
|
+
// },
|
|
62
|
+
// },
|
|
63
|
+
// {
|
|
64
|
+
// isStream: true,
|
|
65
|
+
// onChunk: (chunk) => {
|
|
66
|
+
// console.log('FINAL Received chunk: ', JSON.stringify(chunk, null, 2));
|
|
67
|
+
// },
|
|
68
|
+
// },
|
|
69
|
+
// );
|
|
70
|
+
// await new Promise((resolve) => setTimeout(resolve, 20_000));
|
|
59
71
|
});
|
|
60
72
|
});
|
|
61
73
|
// describe('olane network usage', async () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olane/os",
|
|
3
|
-
"version": "0.7.12-alpha.
|
|
3
|
+
"version": "0.7.12-alpha.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -57,21 +57,21 @@
|
|
|
57
57
|
"typescript": "5.4.5"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@olane/o-config": "0.7.12-alpha.
|
|
61
|
-
"@olane/o-core": "0.7.12-alpha.
|
|
62
|
-
"@olane/o-intelligence": "0.7.12-alpha.
|
|
63
|
-
"@olane/o-lane": "0.7.12-alpha.
|
|
64
|
-
"@olane/o-leader": "0.7.12-alpha.
|
|
65
|
-
"@olane/o-protocol": "0.7.12-alpha.
|
|
66
|
-
"@olane/o-storage": "0.7.12-alpha.
|
|
67
|
-
"@olane/o-tool": "0.7.12-alpha.
|
|
68
|
-
"@olane/o-tool-registry": "0.7.12-alpha.
|
|
69
|
-
"@olane/o-tools-common": "0.7.12-alpha.
|
|
60
|
+
"@olane/o-config": "0.7.12-alpha.26",
|
|
61
|
+
"@olane/o-core": "0.7.12-alpha.26",
|
|
62
|
+
"@olane/o-intelligence": "0.7.12-alpha.26",
|
|
63
|
+
"@olane/o-lane": "0.7.12-alpha.26",
|
|
64
|
+
"@olane/o-leader": "0.7.12-alpha.26",
|
|
65
|
+
"@olane/o-protocol": "0.7.12-alpha.26",
|
|
66
|
+
"@olane/o-storage": "0.7.12-alpha.26",
|
|
67
|
+
"@olane/o-tool": "0.7.12-alpha.26",
|
|
68
|
+
"@olane/o-tool-registry": "0.7.12-alpha.26",
|
|
69
|
+
"@olane/o-tools-common": "0.7.12-alpha.26",
|
|
70
70
|
"chalk": "^5.4.1",
|
|
71
71
|
"debug": "^4.4.1",
|
|
72
72
|
"dotenv": "^16.5.0",
|
|
73
73
|
"fs-extra": "^11.3.0",
|
|
74
74
|
"touch": "^3.1.1"
|
|
75
75
|
},
|
|
76
|
-
"gitHead": "
|
|
76
|
+
"gitHead": "d0436ce9eed9cad0e64561cf0428b0e791c57058"
|
|
77
77
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"default.config.d.ts","sourceRoot":"","sources":["../../../../src/network/config/default.config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAG5E,eAAO,MAAM,oBAAoB,SAAU,MAAM,KAAG,sBAiCnD,CAAC"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_NETWORKS_PATH, NodeType, oAddress } from '@olane/o-core';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
export const defaultNetworkConfig = (port) => {
|
|
4
|
-
return {
|
|
5
|
-
configFilePath: path.join(DEFAULT_NETWORKS_PATH, 'my-network', 'config.json'),
|
|
6
|
-
network: {
|
|
7
|
-
name: 'my-network-' + Math.random().toString(36).substring(2, 6),
|
|
8
|
-
version: '0.0.1',
|
|
9
|
-
description: 'my olane network',
|
|
10
|
-
port: port,
|
|
11
|
-
},
|
|
12
|
-
nodes: [
|
|
13
|
-
{
|
|
14
|
-
type: NodeType.LEADER,
|
|
15
|
-
address: new oAddress('o://leader'),
|
|
16
|
-
leader: null,
|
|
17
|
-
parent: null,
|
|
18
|
-
network: {
|
|
19
|
-
listeners: ['/ip4/0.0.0.0/tcp/' + port],
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
type: NodeType.NODE,
|
|
24
|
-
address: new oAddress('o://node'),
|
|
25
|
-
leader: null,
|
|
26
|
-
parent: null,
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
lanes: [],
|
|
30
|
-
inProgress: [],
|
|
31
|
-
};
|
|
32
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/network/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,4BAA4B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"network-status.enum.d.ts","sourceRoot":"","sources":["../../../../src/network/interfaces/network-status.enum.ts"],"names":[],"mappings":"AAAA,oBAAY,aAAa;IACvB,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,OAAO,YAAY;CACpB"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { oNodeConfig } from '@olane/o-node';
|
|
2
|
-
export interface NetworkConfigInterface {
|
|
3
|
-
configFilePath?: string;
|
|
4
|
-
network?: {
|
|
5
|
-
name?: string;
|
|
6
|
-
version?: string;
|
|
7
|
-
description?: string;
|
|
8
|
-
icon?: string;
|
|
9
|
-
website?: string;
|
|
10
|
-
networkId?: string;
|
|
11
|
-
port?: number;
|
|
12
|
-
};
|
|
13
|
-
nodes?: oNodeConfig[];
|
|
14
|
-
lanes?: string[];
|
|
15
|
-
noIndexNetwork?: boolean;
|
|
16
|
-
inProgress?: string[];
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=network.interface.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"network.interface.d.ts","sourceRoot":"","sources":["../../../../src/network/interfaces/network.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,sBAAsB;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { NetworkStatus } from './interfaces/network-status.enum.js';
|
|
2
|
-
import { NetworkConfigInterface } from './interfaces/network.interface.js';
|
|
3
|
-
import { oLeaderNode } from '@olane/o-leader';
|
|
4
|
-
import { oAddress, oTransport } from '@olane/o-core';
|
|
5
|
-
import { NodeType } from '@olane/o-core';
|
|
6
|
-
import { oLaneTool } from '@olane/o-lane';
|
|
7
|
-
type oNetworkNode = oLaneTool | oLeaderNode;
|
|
8
|
-
export declare class oNetwork {
|
|
9
|
-
private leaders;
|
|
10
|
-
private nodes;
|
|
11
|
-
rootLeader: oLeaderNode | null;
|
|
12
|
-
private logger;
|
|
13
|
-
status: NetworkStatus;
|
|
14
|
-
private config;
|
|
15
|
-
private roundRobinIndex;
|
|
16
|
-
private inFlightRequests;
|
|
17
|
-
constructor(config: NetworkConfigInterface);
|
|
18
|
-
entryNode(): oLaneTool | oLeaderNode;
|
|
19
|
-
addLeader(leader: oLeaderNode): void;
|
|
20
|
-
addNode(node: oNetworkNode): Promise<void>;
|
|
21
|
-
private loadConfig;
|
|
22
|
-
getNetworkName(): Promise<string | undefined>;
|
|
23
|
-
startNodes(type: NodeType): Promise<void>;
|
|
24
|
-
runSavedPlans(): Promise<void>;
|
|
25
|
-
use(oAddress: oAddress, params: any): Promise<import("@olane/o-core").oResponse>;
|
|
26
|
-
start(): Promise<{
|
|
27
|
-
peerId: string;
|
|
28
|
-
transports: oTransport[];
|
|
29
|
-
}>;
|
|
30
|
-
stop(): Promise<void>;
|
|
31
|
-
restart(): Promise<void>;
|
|
32
|
-
}
|
|
33
|
-
export {};
|
|
34
|
-
//# sourceMappingURL=o-network.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"o-network.d.ts","sourceRoot":"","sources":["../../../src/network/o-network.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAG3E,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAU,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI1C,KAAK,YAAY,GAAG,SAAS,GAAG,WAAW,CAAC;AAC5C,qBAAa,QAAQ;IACnB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,KAAK,CAAsB;IAC5B,UAAU,EAAE,WAAW,GAAG,IAAI,CAAQ;IAC7C,OAAO,CAAC,MAAM,CAAS;IAChB,MAAM,EAAG,aAAa,CAAC;IAC9B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,gBAAgB,CAAa;gBAEzB,MAAM,EAAE,sBAAsB;IAK1C,SAAS,IAAI,SAAS,GAAG,WAAW;IAMpC,SAAS,CAAC,MAAM,EAAE,WAAW;IAOvB,OAAO,CAAC,IAAI,EAAE,YAAY;YAiBlB,UAAU;IAwClB,cAAc;IASd,UAAU,CAAC,IAAI,EAAE,QAAQ;IA2CzB,aAAa;IAUb,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG;IAiBnC,KAAK,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC;IAgC9D,IAAI;IAiFJ,OAAO;CAKd"}
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
import { NetworkStatus } from './interfaces/network-status.enum.js';
|
|
2
|
-
import touch from 'touch';
|
|
3
|
-
import { readFile } from 'fs/promises';
|
|
4
|
-
import { oLeaderNode } from '@olane/o-leader';
|
|
5
|
-
import { Logger, oAddress } from '@olane/o-core';
|
|
6
|
-
import { NodeType } from '@olane/o-core';
|
|
7
|
-
import { initCommonTools } from '@olane/o-tools-common';
|
|
8
|
-
import { initRegistryTools } from '@olane/o-tool-registry';
|
|
9
|
-
import { ConfigManager } from '../utils/config.js';
|
|
10
|
-
import { oLaneTool } from '@olane/o-lane';
|
|
11
|
-
import { oNodeAddress } from '@olane/o-node';
|
|
12
|
-
export class oNetwork {
|
|
13
|
-
constructor(config) {
|
|
14
|
-
this.leaders = []; // clones of leader for scale
|
|
15
|
-
this.nodes = []; // clones of node for scale
|
|
16
|
-
this.rootLeader = null; // the root leader node
|
|
17
|
-
this.roundRobinIndex = 0;
|
|
18
|
-
this.inFlightRequests = [];
|
|
19
|
-
this.logger = new Logger('oNetwork');
|
|
20
|
-
this.config = config;
|
|
21
|
-
}
|
|
22
|
-
entryNode() {
|
|
23
|
-
const node = this.nodes[this.roundRobinIndex];
|
|
24
|
-
this.roundRobinIndex = (this.roundRobinIndex + 1) % this.nodes.length;
|
|
25
|
-
return node;
|
|
26
|
-
}
|
|
27
|
-
addLeader(leader) {
|
|
28
|
-
this.leaders.push(leader);
|
|
29
|
-
if (!this.rootLeader) {
|
|
30
|
-
this.rootLeader = leader;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
async addNode(node) {
|
|
34
|
-
if (this.status !== NetworkStatus.RUNNING) {
|
|
35
|
-
throw new Error('Network is not running, cannot add node');
|
|
36
|
-
}
|
|
37
|
-
// TODO: how do we handle multiple leaders?
|
|
38
|
-
// TODO: how do we handle multiple nodes?
|
|
39
|
-
if (this.nodes.length === 0) {
|
|
40
|
-
throw new Error('No non-leader nodes found, cannot add node');
|
|
41
|
-
}
|
|
42
|
-
const selection = this.entryNode();
|
|
43
|
-
selection.addChildNode(node);
|
|
44
|
-
await selection.start();
|
|
45
|
-
const parent = this.entryNode();
|
|
46
|
-
parent.addChildNode(node);
|
|
47
|
-
}
|
|
48
|
-
async loadConfig() {
|
|
49
|
-
// TODO make this a promise based function
|
|
50
|
-
if (this.config.configFilePath) {
|
|
51
|
-
try {
|
|
52
|
-
await touch(this.config.configFilePath);
|
|
53
|
-
this.logger.debug('Config file path: ' + this.config.configFilePath);
|
|
54
|
-
// let's load the config
|
|
55
|
-
const config = await readFile(this.config.configFilePath, 'utf8');
|
|
56
|
-
this.logger.debug('Config file contents: ' + config);
|
|
57
|
-
if (config?.length === 0) {
|
|
58
|
-
// no contents, let's create a new config
|
|
59
|
-
throw new Error('No config file found, cannot start network');
|
|
60
|
-
}
|
|
61
|
-
const json = JSON.parse(config);
|
|
62
|
-
this.logger.debug('Config file parsed: ' + json);
|
|
63
|
-
const networkConfig = json.oNetworkConfig;
|
|
64
|
-
this.config = {
|
|
65
|
-
...networkConfig,
|
|
66
|
-
nodes: (networkConfig.nodes || []).map((node) => ({
|
|
67
|
-
...node,
|
|
68
|
-
address: new oNodeAddress(node.address.value),
|
|
69
|
-
})),
|
|
70
|
-
network: {
|
|
71
|
-
...networkConfig.network,
|
|
72
|
-
port: networkConfig.network?.port || 4999,
|
|
73
|
-
},
|
|
74
|
-
configFilePath: this.config.configFilePath, // persist the config file path
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
catch (error) {
|
|
78
|
-
this.logger.error('Failed to initialize config folder', error);
|
|
79
|
-
throw new Error('Failed to initialize config folder');
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
this.logger.warn('No config file path provided, using default config');
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
async getNetworkName() {
|
|
87
|
-
if (this.config.configFilePath) {
|
|
88
|
-
const networkConfig = await ConfigManager.getNetworkConfigFromPath(this.config.configFilePath);
|
|
89
|
-
return networkConfig?.name;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
async startNodes(type) {
|
|
93
|
-
this.logger.debug('Starting nodes');
|
|
94
|
-
if (!this.config.nodes || this.config.nodes?.length === 0) {
|
|
95
|
-
throw new Error('No nodes found in config, cannot start network');
|
|
96
|
-
}
|
|
97
|
-
const filtered = this.config.nodes.filter((node) => node.type === type);
|
|
98
|
-
const networkName = await this.getNetworkName();
|
|
99
|
-
// check the config for any leaders
|
|
100
|
-
for (const node of filtered) {
|
|
101
|
-
if (node.type === NodeType.LEADER) {
|
|
102
|
-
this.logger.debug('Starting leader: ' + node.address.toString());
|
|
103
|
-
const leaderNode = new oLeaderNode({
|
|
104
|
-
...node,
|
|
105
|
-
networkName: networkName,
|
|
106
|
-
});
|
|
107
|
-
if (!this.rootLeader) {
|
|
108
|
-
this.rootLeader = leaderNode;
|
|
109
|
-
}
|
|
110
|
-
await leaderNode.start();
|
|
111
|
-
await initCommonTools(leaderNode);
|
|
112
|
-
this.leaders.push(leaderNode);
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
this.logger.debug('Starting non-leader node: ' + node.address.toString());
|
|
116
|
-
const commonNode = new oLaneTool({
|
|
117
|
-
...node,
|
|
118
|
-
address: node.address,
|
|
119
|
-
leader: this.rootLeader?.address || null,
|
|
120
|
-
parent: this.rootLeader?.address || null,
|
|
121
|
-
});
|
|
122
|
-
await commonNode.start();
|
|
123
|
-
this.rootLeader?.addChildNode(commonNode);
|
|
124
|
-
await initCommonTools(commonNode);
|
|
125
|
-
await initRegistryTools(commonNode);
|
|
126
|
-
this.nodes.push(commonNode);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
async runSavedPlans() {
|
|
131
|
-
const plans = Array.from(new Set(this.config?.lanes || []));
|
|
132
|
-
for (const plan of plans) {
|
|
133
|
-
this.logger.debug('Running saved plan: ' + plan);
|
|
134
|
-
await this.use(new oAddress(plan), {
|
|
135
|
-
method: 'use',
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
async use(oAddress, params) {
|
|
140
|
-
const entryNode = this.entryNode();
|
|
141
|
-
if (!entryNode) {
|
|
142
|
-
throw new Error('Entry node not found');
|
|
143
|
-
}
|
|
144
|
-
this.logger.debug('Using address: ' + oAddress.toString());
|
|
145
|
-
return entryNode.use(oAddress, params);
|
|
146
|
-
// TODO: experiment with this (the wrong way to enter the network)
|
|
147
|
-
// const leader = this.leaders.find(
|
|
148
|
-
// (leader) => leader.type === NodeType.LEADER,
|
|
149
|
-
// );
|
|
150
|
-
// if (!leader) {
|
|
151
|
-
// throw new Error('Leader not found');
|
|
152
|
-
// }
|
|
153
|
-
// return leader.use(oAddress, params);
|
|
154
|
-
}
|
|
155
|
-
async start() {
|
|
156
|
-
this.logger.debug('Starting o-network');
|
|
157
|
-
this.status = NetworkStatus.STARTING;
|
|
158
|
-
// initialize config folder
|
|
159
|
-
await this.loadConfig();
|
|
160
|
-
this.logger.debug('o-network config loaded');
|
|
161
|
-
// start leaders (and consequentially, the rest of the network)
|
|
162
|
-
await this.startNodes(NodeType.LEADER);
|
|
163
|
-
this.logger.debug('Leaders started...');
|
|
164
|
-
await this.startNodes(NodeType.NODE);
|
|
165
|
-
this.logger.debug('Nodes started...');
|
|
166
|
-
await this.runSavedPlans();
|
|
167
|
-
this.logger.debug('Saved plans run...');
|
|
168
|
-
this.logger.debug('o-network started...');
|
|
169
|
-
// index the network
|
|
170
|
-
if (!this.config.noIndexNetwork) {
|
|
171
|
-
await this.use(oAddress.leader(), {
|
|
172
|
-
method: 'index_network',
|
|
173
|
-
params: {},
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
this.status = NetworkStatus.RUNNING;
|
|
177
|
-
return {
|
|
178
|
-
peerId: this.rootLeader?.peerId.toString() || '',
|
|
179
|
-
transports: this.rootLeader?.transports || [],
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
async stop() {
|
|
183
|
-
this.logger.debug('Stopping o-network');
|
|
184
|
-
this.status = NetworkStatus.STOPPING;
|
|
185
|
-
const stopPromises = [];
|
|
186
|
-
try {
|
|
187
|
-
// Stop all common nodes first
|
|
188
|
-
if (this.nodes.length > 0) {
|
|
189
|
-
stopPromises.push(Promise.allSettled(this.nodes.map(async (node) => {
|
|
190
|
-
try {
|
|
191
|
-
await node.stop();
|
|
192
|
-
this.logger.debug(`Stopped node: ${node.address.toString()}`);
|
|
193
|
-
}
|
|
194
|
-
catch (error) {
|
|
195
|
-
this.logger.error(`Error stopping node ${node.address.toString()}:`, error);
|
|
196
|
-
}
|
|
197
|
-
})).then(() => {
|
|
198
|
-
this.nodes = [];
|
|
199
|
-
this.logger.debug('All common nodes stopped');
|
|
200
|
-
}));
|
|
201
|
-
}
|
|
202
|
-
// Stop all leader nodes
|
|
203
|
-
if (this.leaders.length > 0) {
|
|
204
|
-
stopPromises.push(Promise.allSettled(this.leaders.map(async (leader) => {
|
|
205
|
-
try {
|
|
206
|
-
await leader.stop();
|
|
207
|
-
this.logger.debug(`Stopped leader: ${leader.address.toString()}`);
|
|
208
|
-
}
|
|
209
|
-
catch (error) {
|
|
210
|
-
this.logger.error(`Error stopping leader ${leader.address.toString()}:`, error);
|
|
211
|
-
}
|
|
212
|
-
})).then(() => {
|
|
213
|
-
this.leaders = [];
|
|
214
|
-
this.logger.debug('All leader nodes stopped');
|
|
215
|
-
}));
|
|
216
|
-
}
|
|
217
|
-
// Stop root leader last
|
|
218
|
-
if (this.rootLeader) {
|
|
219
|
-
this.logger.debug('Stopping root leader...');
|
|
220
|
-
stopPromises.push(this.rootLeader
|
|
221
|
-
.stop()
|
|
222
|
-
.then(() => {
|
|
223
|
-
this.logger.debug('Root leader stopped');
|
|
224
|
-
this.rootLeader = null;
|
|
225
|
-
})
|
|
226
|
-
.catch((error) => {
|
|
227
|
-
this.logger.error('Error stopping root leader:', error);
|
|
228
|
-
}));
|
|
229
|
-
}
|
|
230
|
-
// Wait for all stop operations to complete
|
|
231
|
-
await Promise.all(stopPromises);
|
|
232
|
-
this.logger.debug('o-network stopped successfully');
|
|
233
|
-
}
|
|
234
|
-
catch (error) {
|
|
235
|
-
this.logger.error('Error while stopping o-network:', error);
|
|
236
|
-
}
|
|
237
|
-
finally {
|
|
238
|
-
this.status = NetworkStatus.STOPPED;
|
|
239
|
-
this.roundRobinIndex = 0;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
async restart() {
|
|
243
|
-
this.logger.debug('Restarting o-network');
|
|
244
|
-
await this.stop();
|
|
245
|
-
await this.start();
|
|
246
|
-
}
|
|
247
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"streaming-usage.spec.d.ts","sourceRoot":"","sources":["../../../test/basic/streaming-usage.spec.ts"],"names":[],"mappings":""}
|
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
import { oAddress } from '@olane/o-core';
|
|
2
|
-
import { expect } from 'chai';
|
|
3
|
-
import dotenv from 'dotenv';
|
|
4
|
-
import { defaultOSInstance } from '../utils/os.default.js';
|
|
5
|
-
import { OlaneOSSystemStatus } from '../../src/o-olane-os/enum/o-os.status-enum.js';
|
|
6
|
-
dotenv.config();
|
|
7
|
-
const network = defaultOSInstance;
|
|
8
|
-
describe('streaming-usage @initialize', async () => {
|
|
9
|
-
it('should be able to startup the network', async () => {
|
|
10
|
-
await network.start();
|
|
11
|
-
expect(network.status).to.equal(OlaneOSSystemStatus.RUNNING);
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
describe('intelligence provider streaming tests', () => {
|
|
15
|
-
it('should stream from Intelligence Router (default provider)', async function () {
|
|
16
|
-
const entryNode = network.entryNode();
|
|
17
|
-
let fullText = '';
|
|
18
|
-
let chunkCount = 0;
|
|
19
|
-
let lastChunk = null;
|
|
20
|
-
console.log('\n Testing Intelligence Router streaming...');
|
|
21
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://intelligence'), {
|
|
22
|
-
method: 'stream_prompt',
|
|
23
|
-
params: {
|
|
24
|
-
prompt: 'Say hello in 5 words',
|
|
25
|
-
},
|
|
26
|
-
})) {
|
|
27
|
-
chunkCount++;
|
|
28
|
-
if (chunk.text) {
|
|
29
|
-
fullText += chunk.text;
|
|
30
|
-
console.log('Chunk:', chunk.text);
|
|
31
|
-
process.stdout.write(chunk.text);
|
|
32
|
-
}
|
|
33
|
-
lastChunk = chunk;
|
|
34
|
-
}
|
|
35
|
-
console.log(`\n Received ${chunkCount} chunks`);
|
|
36
|
-
console.log(` Full response: "${fullText}"\n`);
|
|
37
|
-
expect(chunkCount).to.be.greaterThan(0);
|
|
38
|
-
expect(fullText).to.not.be.empty;
|
|
39
|
-
expect(lastChunk?.isComplete).to.be.true;
|
|
40
|
-
});
|
|
41
|
-
it('should stream from Anthropic', async function () {
|
|
42
|
-
const entryNode = network.entryNode();
|
|
43
|
-
let fullText = '';
|
|
44
|
-
let chunkCount = 0;
|
|
45
|
-
let lastChunk = null;
|
|
46
|
-
console.log('\n Testing Anthropic streaming...');
|
|
47
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://anthropic'), {
|
|
48
|
-
method: 'stream_completion',
|
|
49
|
-
params: {
|
|
50
|
-
messages: [{ role: 'user', content: 'Say hello in 5 words' }],
|
|
51
|
-
max_tokens: 50,
|
|
52
|
-
},
|
|
53
|
-
})) {
|
|
54
|
-
chunkCount++;
|
|
55
|
-
if (chunk.text) {
|
|
56
|
-
fullText += chunk.text;
|
|
57
|
-
process.stdout.write(chunk.text);
|
|
58
|
-
}
|
|
59
|
-
lastChunk = chunk;
|
|
60
|
-
}
|
|
61
|
-
console.log(`\n Received ${chunkCount} chunks`);
|
|
62
|
-
console.log(` Full response: "${fullText}"\n`);
|
|
63
|
-
expect(chunkCount).to.be.greaterThan(0);
|
|
64
|
-
expect(fullText).to.not.be.empty;
|
|
65
|
-
expect(lastChunk?.isComplete).to.be.true;
|
|
66
|
-
});
|
|
67
|
-
it('should stream from OpenAI', async function () {
|
|
68
|
-
const entryNode = network.entryNode();
|
|
69
|
-
let fullText = '';
|
|
70
|
-
let chunkCount = 0;
|
|
71
|
-
let lastChunk = null;
|
|
72
|
-
console.log('\n Testing OpenAI streaming...');
|
|
73
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://openai'), {
|
|
74
|
-
method: 'stream_completion',
|
|
75
|
-
params: {
|
|
76
|
-
messages: [{ role: 'user', content: 'Say hello in 5 words' }],
|
|
77
|
-
max_tokens: 50,
|
|
78
|
-
},
|
|
79
|
-
})) {
|
|
80
|
-
chunkCount++;
|
|
81
|
-
if (chunk.text) {
|
|
82
|
-
fullText += chunk.text;
|
|
83
|
-
process.stdout.write(chunk.text);
|
|
84
|
-
}
|
|
85
|
-
lastChunk = chunk;
|
|
86
|
-
}
|
|
87
|
-
console.log(`\n Received ${chunkCount} chunks`);
|
|
88
|
-
console.log(` Full response: "${fullText}"\n`);
|
|
89
|
-
expect(chunkCount).to.be.greaterThan(0);
|
|
90
|
-
expect(fullText).to.not.be.empty;
|
|
91
|
-
expect(lastChunk?.isComplete).to.be.true;
|
|
92
|
-
});
|
|
93
|
-
it('should stream from Ollama', async function () {
|
|
94
|
-
const entryNode = network.entryNode();
|
|
95
|
-
let fullText = '';
|
|
96
|
-
let chunkCount = 0;
|
|
97
|
-
let lastChunk = null;
|
|
98
|
-
console.log('\n Testing Ollama streaming...');
|
|
99
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://ollama'), {
|
|
100
|
-
method: 'stream_completion',
|
|
101
|
-
params: {
|
|
102
|
-
messages: [{ role: 'user', content: 'Say hello in 5 words' }],
|
|
103
|
-
model: 'llama3.2:latest', // Default model
|
|
104
|
-
},
|
|
105
|
-
})) {
|
|
106
|
-
chunkCount++;
|
|
107
|
-
if (chunk.text) {
|
|
108
|
-
fullText += chunk.text;
|
|
109
|
-
process.stdout.write(chunk.text);
|
|
110
|
-
}
|
|
111
|
-
lastChunk = chunk;
|
|
112
|
-
}
|
|
113
|
-
console.log(`\n Received ${chunkCount} chunks`);
|
|
114
|
-
console.log(` Full response: "${fullText}"\n`);
|
|
115
|
-
expect(chunkCount).to.be.greaterThan(0);
|
|
116
|
-
expect(fullText).to.not.be.empty;
|
|
117
|
-
expect(lastChunk?.isComplete).to.be.true;
|
|
118
|
-
});
|
|
119
|
-
it('should stream from Perplexity', async function () {
|
|
120
|
-
const entryNode = network.entryNode();
|
|
121
|
-
let fullText = '';
|
|
122
|
-
let chunkCount = 0;
|
|
123
|
-
let lastChunk = null;
|
|
124
|
-
console.log('\n Testing Perplexity streaming...');
|
|
125
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://perplexity'), {
|
|
126
|
-
method: 'stream_completion',
|
|
127
|
-
params: {
|
|
128
|
-
messages: [{ role: 'user', content: 'Say hello in 5 words' }],
|
|
129
|
-
max_tokens: 50,
|
|
130
|
-
},
|
|
131
|
-
})) {
|
|
132
|
-
chunkCount++;
|
|
133
|
-
if (chunk.text) {
|
|
134
|
-
fullText += chunk.text;
|
|
135
|
-
process.stdout.write(chunk.text);
|
|
136
|
-
}
|
|
137
|
-
lastChunk = chunk;
|
|
138
|
-
}
|
|
139
|
-
console.log(`\n Received ${chunkCount} chunks`);
|
|
140
|
-
console.log(` Full response: "${fullText}"\n`);
|
|
141
|
-
expect(chunkCount).to.be.greaterThan(0);
|
|
142
|
-
expect(fullText).to.not.be.empty;
|
|
143
|
-
expect(lastChunk?.isComplete).to.be.true;
|
|
144
|
-
});
|
|
145
|
-
it('should stream from Grok', async function () {
|
|
146
|
-
const entryNode = network.entryNode();
|
|
147
|
-
let fullText = '';
|
|
148
|
-
let chunkCount = 0;
|
|
149
|
-
let lastChunk = null;
|
|
150
|
-
console.log('\n Testing Grok streaming...');
|
|
151
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://grok'), {
|
|
152
|
-
method: 'stream_completion',
|
|
153
|
-
params: {
|
|
154
|
-
messages: [{ role: 'user', content: 'Say hello in 5 words' }],
|
|
155
|
-
max_tokens: 50,
|
|
156
|
-
},
|
|
157
|
-
})) {
|
|
158
|
-
chunkCount++;
|
|
159
|
-
if (chunk.text) {
|
|
160
|
-
fullText += chunk.text;
|
|
161
|
-
process.stdout.write(chunk.text);
|
|
162
|
-
}
|
|
163
|
-
lastChunk = chunk;
|
|
164
|
-
}
|
|
165
|
-
console.log(`\n Received ${chunkCount} chunks`);
|
|
166
|
-
console.log(` Full response: "${fullText}"\n`);
|
|
167
|
-
expect(chunkCount).to.be.greaterThan(0);
|
|
168
|
-
expect(fullText).to.not.be.empty;
|
|
169
|
-
expect(lastChunk?.isComplete).to.be.true;
|
|
170
|
-
});
|
|
171
|
-
it('should stream from Gemini', async function () {
|
|
172
|
-
const entryNode = network.entryNode();
|
|
173
|
-
let fullText = '';
|
|
174
|
-
let chunkCount = 0;
|
|
175
|
-
let lastChunk = null;
|
|
176
|
-
console.log('\n Testing Gemini streaming...');
|
|
177
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://gemini'), {
|
|
178
|
-
method: 'stream_completion',
|
|
179
|
-
params: {
|
|
180
|
-
messages: [{ role: 'user', content: 'Say hello in 5 words' }],
|
|
181
|
-
max_tokens: 50,
|
|
182
|
-
},
|
|
183
|
-
})) {
|
|
184
|
-
chunkCount++;
|
|
185
|
-
if (chunk.text) {
|
|
186
|
-
fullText += chunk.text;
|
|
187
|
-
process.stdout.write(chunk.text);
|
|
188
|
-
}
|
|
189
|
-
lastChunk = chunk;
|
|
190
|
-
}
|
|
191
|
-
console.log(`\n Received ${chunkCount} chunks`);
|
|
192
|
-
console.log(` Full response: "${fullText}"\n`);
|
|
193
|
-
expect(chunkCount).to.be.greaterThan(0);
|
|
194
|
-
expect(fullText).to.not.be.empty;
|
|
195
|
-
expect(lastChunk?.isComplete).to.be.true;
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
describe('multi-hop streaming tests', () => {
|
|
199
|
-
it('should stream through Intelligence Router to Anthropic (2-hop)', async function () {
|
|
200
|
-
const entryNode = network.entryNode();
|
|
201
|
-
let fullText = '';
|
|
202
|
-
let chunkCount = 0;
|
|
203
|
-
let lastChunk = null;
|
|
204
|
-
console.log('\n Testing 2-hop streaming (Intelligence Router → Anthropic)...');
|
|
205
|
-
// The intelligence router will route to a specific provider
|
|
206
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://intelligence'), {
|
|
207
|
-
method: 'stream_prompt',
|
|
208
|
-
params: {
|
|
209
|
-
prompt: 'Count to 5',
|
|
210
|
-
provider: 'anthropic', // Force routing to Anthropic
|
|
211
|
-
},
|
|
212
|
-
})) {
|
|
213
|
-
chunkCount++;
|
|
214
|
-
if (chunk.text) {
|
|
215
|
-
fullText += chunk.text;
|
|
216
|
-
process.stdout.write(chunk.text);
|
|
217
|
-
}
|
|
218
|
-
lastChunk = chunk;
|
|
219
|
-
}
|
|
220
|
-
console.log(`\n Received ${chunkCount} chunks through 2-hop routing`);
|
|
221
|
-
console.log(` Full response: "${fullText}"\n`);
|
|
222
|
-
expect(chunkCount).to.be.greaterThan(0);
|
|
223
|
-
expect(fullText).to.not.be.empty;
|
|
224
|
-
expect(lastChunk?.isComplete).to.be.true;
|
|
225
|
-
});
|
|
226
|
-
it('should stream through Intelligence Router to OpenAI (2-hop)', async function () {
|
|
227
|
-
const entryNode = network.entryNode();
|
|
228
|
-
let fullText = '';
|
|
229
|
-
let chunkCount = 0;
|
|
230
|
-
let lastChunk = null;
|
|
231
|
-
console.log('\n Testing 2-hop streaming (Intelligence Router → OpenAI)...');
|
|
232
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://intelligence'), {
|
|
233
|
-
method: 'stream_prompt',
|
|
234
|
-
params: {
|
|
235
|
-
prompt: 'Say hello',
|
|
236
|
-
provider: 'openai', // Force routing to OpenAI
|
|
237
|
-
},
|
|
238
|
-
})) {
|
|
239
|
-
chunkCount++;
|
|
240
|
-
if (chunk.text) {
|
|
241
|
-
fullText += chunk.text;
|
|
242
|
-
process.stdout.write(chunk.text);
|
|
243
|
-
}
|
|
244
|
-
lastChunk = chunk;
|
|
245
|
-
}
|
|
246
|
-
console.log(`\n Received ${chunkCount} chunks through 2-hop routing`);
|
|
247
|
-
console.log(` Full response: "${fullText}"\n`);
|
|
248
|
-
expect(chunkCount).to.be.greaterThan(0);
|
|
249
|
-
expect(fullText).to.not.be.empty;
|
|
250
|
-
expect(lastChunk?.isComplete).to.be.true;
|
|
251
|
-
});
|
|
252
|
-
it('should handle streaming with routing correctly (verify chunk order)', async function () {
|
|
253
|
-
const entryNode = network.entryNode();
|
|
254
|
-
const chunks = [];
|
|
255
|
-
console.log('\n Testing chunk ordering through routing...');
|
|
256
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://anthropic'), {
|
|
257
|
-
method: 'stream_completion',
|
|
258
|
-
params: {
|
|
259
|
-
messages: [{ role: 'user', content: 'Count: 1, 2, 3, 4, 5' }],
|
|
260
|
-
max_tokens: 50,
|
|
261
|
-
},
|
|
262
|
-
})) {
|
|
263
|
-
chunks.push(chunk);
|
|
264
|
-
if (chunk.text) {
|
|
265
|
-
process.stdout.write(chunk.text);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
console.log(`\n Received ${chunks.length} chunks\n`);
|
|
269
|
-
// Verify chunks are in order (sequence numbers should increment)
|
|
270
|
-
for (let i = 0; i < chunks.length - 1; i++) {
|
|
271
|
-
if (chunks[i].position !== undefined && chunks[i + 1].position !== undefined) {
|
|
272
|
-
expect(chunks[i + 1].position).to.be.greaterThanOrEqual(chunks[i].position);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
// Verify last chunk is marked as complete
|
|
276
|
-
const lastChunk = chunks[chunks.length - 1];
|
|
277
|
-
expect(lastChunk?.isComplete).to.be.true;
|
|
278
|
-
console.log(' ✓ Chunks are in correct order');
|
|
279
|
-
});
|
|
280
|
-
it('should handle backpressure correctly during streaming', async function () {
|
|
281
|
-
const entryNode = network.entryNode();
|
|
282
|
-
let chunkCount = 0;
|
|
283
|
-
let processingTime = 0;
|
|
284
|
-
console.log('\n Testing backpressure handling...');
|
|
285
|
-
const startTime = Date.now();
|
|
286
|
-
for await (const chunk of entryNode.useStreaming(new oAddress('o://anthropic'), {
|
|
287
|
-
method: 'stream_completion',
|
|
288
|
-
params: {
|
|
289
|
-
messages: [{ role: 'user', content: 'Write a short poem' }],
|
|
290
|
-
max_tokens: 100,
|
|
291
|
-
},
|
|
292
|
-
})) {
|
|
293
|
-
chunkCount++;
|
|
294
|
-
if (chunk.text) {
|
|
295
|
-
process.stdout.write(chunk.text);
|
|
296
|
-
}
|
|
297
|
-
// Simulate slow consumer (backpressure)
|
|
298
|
-
if (chunkCount % 5 === 0) {
|
|
299
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
processingTime = Date.now() - startTime;
|
|
303
|
-
console.log(`\n Processed ${chunkCount} chunks in ${processingTime}ms`);
|
|
304
|
-
console.log(` Average: ${(processingTime / chunkCount).toFixed(2)}ms per chunk\n`);
|
|
305
|
-
expect(chunkCount).to.be.greaterThan(0);
|
|
306
|
-
// Backpressure should work without errors
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
|
-
describe('streaming-usage @stop-network', async () => {
|
|
310
|
-
it('should be able to stop the network', async () => {
|
|
311
|
-
await network.stop();
|
|
312
|
-
expect(network.status).to.equal(OlaneOSSystemStatus.STOPPED);
|
|
313
|
-
});
|
|
314
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"default.network.d.ts","sourceRoot":"","sources":["../../../test/utils/default.network.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,eAAO,MAAM,cAAc,UAoBzB,CAAC"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { NodeType, oAddress, setupGracefulShutdown } from '@olane/o-core';
|
|
2
|
-
import { oNetwork } from '../../src/index.js';
|
|
3
|
-
export const defaultNetwork = new oNetwork({
|
|
4
|
-
// configFilePath: path.join(os.homedir(), '.olane', 'config.json'),
|
|
5
|
-
nodes: [
|
|
6
|
-
{
|
|
7
|
-
type: NodeType.LEADER,
|
|
8
|
-
address: new oAddress('o://leader'),
|
|
9
|
-
description: 'Leader for testing',
|
|
10
|
-
leader: null,
|
|
11
|
-
parent: null,
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
type: NodeType.NODE,
|
|
15
|
-
address: new oAddress('o://node'),
|
|
16
|
-
description: 'Node for testing',
|
|
17
|
-
leader: null,
|
|
18
|
-
parent: null,
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
lanes: [],
|
|
22
|
-
// noIndexNetwork: true,
|
|
23
|
-
});
|
|
24
|
-
setupGracefulShutdown(async () => {
|
|
25
|
-
console.log('Stopping o-network...');
|
|
26
|
-
await defaultNetwork.stop();
|
|
27
|
-
console.log('o-network stopped successfully');
|
|
28
|
-
}, {
|
|
29
|
-
timeout: 30000, // 30 seconds timeout
|
|
30
|
-
onTimeout: () => {
|
|
31
|
-
console.error('Shutdown timeout reached, forcing exit');
|
|
32
|
-
},
|
|
33
|
-
});
|