@olane/o-node 0.8.2 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +140 -21
  2. package/package.json +7 -7
package/README.md CHANGED
@@ -81,7 +81,7 @@ The production distribution layer of Olane OS - build tool nodes that AI agents
81
81
  ## Installation
82
82
 
83
83
  ```bash
84
- npm install @olane/o-node @olane/o-core @olane/o-protocol @olane/o-config @olane/o-tool
84
+ pnpm install @olane/o-node @olane/o-core @olane/o-protocol @olane/o-config @olane/o-tool
85
85
  ```
86
86
 
87
87
  ## Quick Start
@@ -141,8 +141,14 @@ const response = await toolNode.use(
141
141
  { method: 'greet', params: { name: 'World' } }
142
142
  );
143
143
 
144
- console.log(response.result);
145
- // { message: "Hello, World! I'm a tool node that AI agents can use.", peerId: "..." }
144
+ // Responses are wrapped in a standard structure:
145
+ // response.result.success - boolean indicating success/failure
146
+ // response.result.data - the raw data returned by the tool method
147
+ // response.result.error - error message if success is false
148
+ if (response.result.success) {
149
+ console.log(response.result.data);
150
+ // { message: "Hello, World! I'm a tool node that AI agents can use.", peerId: "..." }
151
+ }
146
152
 
147
153
  await toolNode.stop();
148
154
  ```
@@ -581,6 +587,118 @@ const response = await agent1.use(agent2.address, {
581
587
 
582
588
  ## API Reference
583
589
 
590
+ ### Class Hierarchy
591
+
592
+ The o-node package provides several classes that build on each other through both inheritance and composition (mixins):
593
+
594
+ ```
595
+ oCore (from @olane/o-core)
596
+ └─ oToolBase (from @olane/o-tool) [inheritance]
597
+ └─ oNode [inheritance]
598
+ └─ oServerNode [inheritance]
599
+ └─ oNodeTool [composition via oTool mixin]
600
+ ```
601
+
602
+ `oNodeTool` is the **recommended base class** for building tool nodes. It applies the `oTool` mixin to `oServerNode`, which adds protocol handling, tool method discovery (methods prefixed with `_tool_`), and the standard request/response pipeline. Use `oServerNode` directly only when you need low-level networking without the tool layer.
603
+
604
+ ### oNodeTool Class
605
+
606
+ The primary base class for building tool nodes. Created by applying the `oTool` mixin to `oServerNode`, which adds protocol handling, `_tool_` method discovery, and the standard response wrapping pipeline.
607
+
608
+ **Import:**
609
+ ```typescript
610
+ import { oNodeTool, oNodeAddress } from '@olane/o-node';
611
+ ```
612
+
613
+ **Usage:**
614
+ ```typescript
615
+ import { oNodeTool, oNodeAddress } from '@olane/o-node';
616
+ import { oRequest } from '@olane/o-core';
617
+
618
+ class MyTool extends oNodeTool {
619
+ constructor(config: any) {
620
+ super({
621
+ ...config,
622
+ address: new oNodeAddress('o://my-tool'),
623
+ description: 'A tool node for AI agents',
624
+ });
625
+ }
626
+
627
+ // Initialize external services in this hook (not in start())
628
+ async hookInitializeFinished(): Promise<void> {
629
+ // Set up API clients, load resources, etc.
630
+ await super.hookInitializeFinished();
631
+ }
632
+
633
+ // Start background tasks in this hook
634
+ async hookStartFinished(): Promise<void> {
635
+ // Start monitoring, spawn children, etc.
636
+ await super.hookStartFinished();
637
+ }
638
+
639
+ // Methods prefixed with _tool_ are automatically discovered
640
+ async _tool_greet(request: oRequest): Promise<any> {
641
+ const { name } = request.params;
642
+ if (!name) {
643
+ throw new Error('name is required');
644
+ }
645
+ // Return raw data - base class wraps it automatically
646
+ return { message: `Hello, ${name}!` };
647
+ }
648
+
649
+ // Cleanup resources
650
+ async stop(): Promise<void> {
651
+ // Disconnect clients, clear timers, etc.
652
+ await super.stop();
653
+ }
654
+ }
655
+ ```
656
+
657
+ **Configuration** (`oNodeToolConfig`):
658
+
659
+ Extends `oNodeConfig` (with `address` optional, since it can be set in the constructor):
660
+
661
+ ```typescript
662
+ interface oNodeToolConfig extends Omit<oNodeConfig, 'address'> {}
663
+ ```
664
+
665
+ See `oNodeConfig` below for the full set of configuration options.
666
+
667
+ **Lifecycle Hooks:**
668
+
669
+ | Hook | When | Use For |
670
+ |------|------|---------|
671
+ | `hookInitializeFinished()` | After `initialize()`, before `register()` | Initialize 3rd party services |
672
+ | `hookStartFinished()` | After `register()`, fully started | Start background tasks, create children |
673
+ | `stop()` | When stopping | Cleanup resources, disconnect services |
674
+
675
+ > **Important**: Never override `start()`. It orchestrates the entire lifecycle. Use `hookInitializeFinished()` and `hookStartFinished()` instead.
676
+
677
+ **Response Structure:**
678
+
679
+ When calling tool methods via `node.use()`, responses follow the standard Olane response structure:
680
+
681
+ ```typescript
682
+ const response = await node.use(
683
+ new oNodeAddress('o://some-tool'),
684
+ { method: 'some_method', params: { ... } }
685
+ );
686
+
687
+ // response.result.success - boolean indicating success or failure
688
+ // response.result.data - the return value on success
689
+ // response.result.error - error message on failure
690
+
691
+ if (response.result.success) {
692
+ const data = response.result.data;
693
+ } else {
694
+ console.error('Error:', response.result.error);
695
+ }
696
+ ```
697
+
698
+ > **Important**: Never access `response.success` or `response.data` directly. Always use `response.result.success` and `response.result.data`.
699
+
700
+ ---
701
+
584
702
  ### oNode Class
585
703
 
586
704
  Extends `oToolBase` from `@olane/o-tool`, which extends `oCore` from `@olane/o-core`.
@@ -852,39 +970,40 @@ describe('Agent Communication', () => {
852
970
  ```typescript
853
971
  class MonitoredNode extends oServerNode {
854
972
  private healthCheckInterval?: NodeJS.Timeout;
855
-
856
- async start(): Promise<void> {
857
- await super.start();
858
-
859
- // Start health monitoring
973
+
974
+ // Use hookStartFinished() instead of overriding start()
975
+ async hookStartFinished(): Promise<void> {
976
+ // Start health monitoring after the node is fully started
860
977
  this.healthCheckInterval = setInterval(() => {
861
978
  const connections = this.p2pNode.getConnections();
862
979
  const peers = this.p2pNode.getPeers();
863
-
980
+
864
981
  console.log('Health Check:', {
865
982
  connections: connections.length,
866
983
  peers: peers.length,
867
984
  protocols: this.p2pNode.getProtocols()
868
985
  });
869
-
986
+
870
987
  // Alert if disconnected
871
988
  if (connections.length === 0 && this.leader) {
872
989
  console.warn('No active connections! Attempting reconnect...');
873
990
  this.reconnectToLeader();
874
991
  }
875
992
  }, 30000); // Every 30 seconds
993
+
994
+ await super.hookStartFinished();
876
995
  }
877
-
996
+
878
997
  async stop(): Promise<void> {
879
998
  if (this.healthCheckInterval) {
880
999
  clearInterval(this.healthCheckInterval);
881
1000
  }
882
1001
  await super.stop();
883
1002
  }
884
-
1003
+
885
1004
  private async reconnectToLeader(): Promise<void> {
886
1005
  if (!this.leader) return;
887
-
1006
+
888
1007
  try {
889
1008
  await this.register();
890
1009
  console.log('Reconnected to leader');
@@ -961,32 +1080,32 @@ const agent = new oServerNode({
961
1080
 
962
1081
  ```bash
963
1082
  # Run tests
964
- npm test
1083
+ pnpm test
965
1084
 
966
1085
  # Run tests in Node.js
967
- npm run test:node
1086
+ pnpm run test:node
968
1087
 
969
1088
  # Run tests in browser
970
- npm run test:browser
1089
+ pnpm run test:browser
971
1090
  ```
972
1091
 
973
1092
  ## Development
974
1093
 
975
1094
  ```bash
976
1095
  # Install dependencies
977
- npm install
1096
+ pnpm install
978
1097
 
979
1098
  # Build the package
980
- npm run build
1099
+ pnpm run build
981
1100
 
982
1101
  # Run in development mode with debug output
983
- npm run dev
1102
+ pnpm run dev
984
1103
 
985
1104
  # Update o-core dependency
986
- npm run update:lib
1105
+ pnpm run update:lib
987
1106
 
988
1107
  # Lint the code
989
- npm run lint
1108
+ pnpm run lint
990
1109
  ```
991
1110
 
992
1111
  ## Related Packages
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olane/o-node",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "type": "module",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -40,7 +40,7 @@
40
40
  "devDependencies": {
41
41
  "@eslint/eslintrc": "^3.3.1",
42
42
  "@eslint/js": "^9.29.0",
43
- "@olane/o-test": "0.8.2",
43
+ "@olane/o-test": "0.8.4",
44
44
  "@tsconfig/node20": "^20.1.6",
45
45
  "@types/jest": "^30.0.0",
46
46
  "@types/json5": "^2.2.0",
@@ -60,13 +60,13 @@
60
60
  "typescript": "5.4.5"
61
61
  },
62
62
  "dependencies": {
63
- "@olane/o-config": "0.8.2",
64
- "@olane/o-core": "0.8.2",
65
- "@olane/o-protocol": "0.8.2",
66
- "@olane/o-tool": "0.8.2",
63
+ "@olane/o-config": "0.8.4",
64
+ "@olane/o-core": "0.8.4",
65
+ "@olane/o-protocol": "0.8.4",
66
+ "@olane/o-tool": "0.8.4",
67
67
  "debug": "^4.4.1",
68
68
  "dotenv": "^16.5.0",
69
69
  "json5": "^2.2.3"
70
70
  },
71
- "gitHead": "9e35c874d849d051bcffe483fd2a8c2b3ecf68cc"
71
+ "gitHead": "b53623b1ad4365133911722f80d5597a72b65bf2"
72
72
  }