@olane/o-login 0.7.3
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 +893 -0
- package/dist/src/agents.tool.d.ts +12 -0
- package/dist/src/agents.tool.d.ts.map +1 -0
- package/dist/src/agents.tool.js +20 -0
- package/dist/src/ai-agent.tool.d.ts +6 -0
- package/dist/src/ai-agent.tool.d.ts.map +1 -0
- package/dist/src/ai-agent.tool.js +10 -0
- package/dist/src/ai-login.tool.d.ts +6 -0
- package/dist/src/ai-login.tool.d.ts.map +1 -0
- package/dist/src/ai-login.tool.js +10 -0
- package/dist/src/base-agent.tool.d.ts +14 -0
- package/dist/src/base-agent.tool.d.ts.map +1 -0
- package/dist/src/base-agent.tool.js +38 -0
- package/dist/src/base-login.tool.d.ts +14 -0
- package/dist/src/base-login.tool.d.ts.map +1 -0
- package/dist/src/base-login.tool.js +38 -0
- package/dist/src/human-agent.tool.d.ts +6 -0
- package/dist/src/human-agent.tool.d.ts.map +1 -0
- package/dist/src/human-agent.tool.js +10 -0
- package/dist/src/human-login.tool.d.ts +6 -0
- package/dist/src/human-login.tool.d.ts.map +1 -0
- package/dist/src/human-login.tool.js +10 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +4 -0
- package/dist/src/interfaces/agent.config.d.ts +7 -0
- package/dist/src/interfaces/agent.config.d.ts.map +1 -0
- package/dist/src/interfaces/agent.config.js +1 -0
- package/dist/src/interfaces/login.config.d.ts +7 -0
- package/dist/src/interfaces/login.config.d.ts.map +1 -0
- package/dist/src/interfaces/login.config.js +1 -0
- package/dist/src/login.tool.d.ts +12 -0
- package/dist/src/login.tool.d.ts.map +1 -0
- package/dist/src/login.tool.js +20 -0
- package/dist/src/methods/agent.methods.d.ts +5 -0
- package/dist/src/methods/agent.methods.d.ts.map +1 -0
- package/dist/src/methods/agent.methods.js +30 -0
- package/dist/src/methods/login.methods.d.ts +5 -0
- package/dist/src/methods/login.methods.d.ts.map +1 -0
- package/dist/src/methods/login.methods.js +30 -0
- package/dist/src/o-agent.d.ts +1 -0
- package/dist/src/o-agent.d.ts.map +1 -0
- package/dist/src/o-agent.js +1 -0
- package/dist/src/o-login.d.ts +1 -0
- package/dist/src/o-login.d.ts.map +1 -0
- package/dist/src/o-login.js +1 -0
- package/dist/test/ai.spec.d.ts +2 -0
- package/dist/test/ai.spec.d.ts.map +1 -0
- package/dist/test/ai.spec.js +19 -0
- package/package.json +69 -0
package/README.md
ADDED
|
@@ -0,0 +1,893 @@
|
|
|
1
|
+
# @olane/o-login
|
|
2
|
+
|
|
3
|
+
**Login interface for agents to connect to Olane OS.**
|
|
4
|
+
|
|
5
|
+
`o-login` enables both human and AI agents to authenticate and interact with Olane OS by registering themselves as addressable nodes on the network. Once logged in, agents can receive intents, answer questions, and process streamed data.
|
|
6
|
+
|
|
7
|
+
**TL;DR**: Use `oHumanLoginTool` for human agents or `oAILoginTool` for AI agents. Provide callback functions to handle intents, questions, and streams.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Quick Start {#quick-start}
|
|
12
|
+
|
|
13
|
+
### Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @olane/o-login
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Minimal Example: Human Agent Login
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { oHumanLoginTool } from '@olane/o-login';
|
|
23
|
+
|
|
24
|
+
// Create a human agent login
|
|
25
|
+
const humanAgent = new oHumanLoginTool({
|
|
26
|
+
respond: async (intent: string) => {
|
|
27
|
+
// Handle intents sent to this agent
|
|
28
|
+
console.log('Received intent:', intent);
|
|
29
|
+
return 'Intent resolved successfully';
|
|
30
|
+
},
|
|
31
|
+
answer: async (question: string) => {
|
|
32
|
+
// Answer questions sent to this agent
|
|
33
|
+
console.log('Received question:', question);
|
|
34
|
+
return 'Here is my answer';
|
|
35
|
+
},
|
|
36
|
+
receiveStream: async (data: any) => {
|
|
37
|
+
// Handle streamed data
|
|
38
|
+
console.log('Received stream:', data);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Start the agent
|
|
43
|
+
await humanAgent.start();
|
|
44
|
+
|
|
45
|
+
// Now reachable at o://human
|
|
46
|
+
console.log('Human agent is online at:', humanAgent.address.toString());
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Minimal Example: AI Agent Login
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { oAILoginTool } from '@olane/o-login';
|
|
53
|
+
|
|
54
|
+
// Create an AI agent login
|
|
55
|
+
const aiAgent = new oAILoginTool({
|
|
56
|
+
respond: async (intent: string) => {
|
|
57
|
+
// AI processes the intent
|
|
58
|
+
const result = await processWithAI(intent);
|
|
59
|
+
return result;
|
|
60
|
+
},
|
|
61
|
+
answer: async (question: string) => {
|
|
62
|
+
// AI answers the question
|
|
63
|
+
const answer = await aiAnswers(question);
|
|
64
|
+
return answer;
|
|
65
|
+
},
|
|
66
|
+
receiveStream: async (data: any) => {
|
|
67
|
+
// AI processes streamed data
|
|
68
|
+
await processStream(data);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Start the AI agent
|
|
73
|
+
await aiAgent.start();
|
|
74
|
+
|
|
75
|
+
// Now reachable at o://ai
|
|
76
|
+
console.log('AI agent is online at:', aiAgent.address.toString());
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## How It Works {#how-it-works}
|
|
82
|
+
|
|
83
|
+
When you create and start a login tool, you're registering an **agent node** on Olane OS. This node:
|
|
84
|
+
|
|
85
|
+
1. **Becomes addressable** - Gets an `o://` address (default: `o://human` or `o://ai`)
|
|
86
|
+
2. **Exposes tools** - Three built-in tools: `intent`, `question`, and `receive_stream`
|
|
87
|
+
3. **Handles requests** - Routes incoming requests to your callback functions
|
|
88
|
+
4. **Maintains connection** - Stays online and responsive until stopped
|
|
89
|
+
|
|
90
|
+
**Visual Flow**:
|
|
91
|
+
```
|
|
92
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
93
|
+
│ Other Nodes/Agents │
|
|
94
|
+
│ (anywhere on Olane OS) │
|
|
95
|
+
└──────────────────┬──────────────────────────────────────────┘
|
|
96
|
+
│
|
|
97
|
+
│ Send intent/question/stream
|
|
98
|
+
⬇
|
|
99
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
100
|
+
│ o-login Node (o://human or o://ai) │
|
|
101
|
+
│ │
|
|
102
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │
|
|
103
|
+
│ │ _tool_intent│ │_tool_question│ │_tool_receive_ │ │
|
|
104
|
+
│ │ │ │ │ │ stream │ │
|
|
105
|
+
│ └──────┬──────┘ └──────┬───────┘ └──────┬───────┘ │
|
|
106
|
+
│ │ │ │ │
|
|
107
|
+
│ ⬇ ⬇ ⬇ │
|
|
108
|
+
│ ┌──────────────────────────────────────────────────┐ │
|
|
109
|
+
│ │ Your Callback Functions │ │
|
|
110
|
+
│ │ • respond(intent) │ │
|
|
111
|
+
│ │ • answer(question) │ │
|
|
112
|
+
│ │ • receiveStream(data) │ │
|
|
113
|
+
│ └──────────────────────────────────────────────────┘ │
|
|
114
|
+
└─────────────────────────────────────────────────────────────┘
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## API Reference {#api-reference}
|
|
120
|
+
|
|
121
|
+
### `oHumanLoginTool`
|
|
122
|
+
|
|
123
|
+
Creates a login node for human agents.
|
|
124
|
+
|
|
125
|
+
**Constructor**:
|
|
126
|
+
```typescript
|
|
127
|
+
new oHumanLoginTool(config: oLoginConfig)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Parameters**:
|
|
131
|
+
- `config` (object, required): Configuration object
|
|
132
|
+
- `respond` (function, required): Async function to handle intents
|
|
133
|
+
- **Signature**: `(intent: string) => Promise<string>`
|
|
134
|
+
- **Returns**: Resolution message
|
|
135
|
+
- `answer` (function, required): Async function to answer questions
|
|
136
|
+
- **Signature**: `(question: string) => Promise<string>`
|
|
137
|
+
- **Returns**: Answer string
|
|
138
|
+
- `receiveStream` (function, required): Async function to handle streams
|
|
139
|
+
- **Signature**: `(data: any) => Promise<any>`
|
|
140
|
+
- **Returns**: Processing result (optional)
|
|
141
|
+
- `address` (oNodeAddress, optional): Custom address (default: `o://human`)
|
|
142
|
+
- `leader` (oAddress, optional): Leader node address for network registration
|
|
143
|
+
- `parent` (oAddress, optional): Parent node address
|
|
144
|
+
|
|
145
|
+
**Example**:
|
|
146
|
+
```typescript
|
|
147
|
+
const humanAgent = new oHumanLoginTool({
|
|
148
|
+
// Custom address
|
|
149
|
+
address: new oNodeAddress('o://team/alice'),
|
|
150
|
+
|
|
151
|
+
// Handle intents
|
|
152
|
+
respond: async (intent: string) => {
|
|
153
|
+
if (intent.includes('approve')) {
|
|
154
|
+
return 'Request approved';
|
|
155
|
+
}
|
|
156
|
+
return 'Request pending review';
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
// Answer questions
|
|
160
|
+
answer: async (question: string) => {
|
|
161
|
+
return `Human response to: ${question}`;
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
// Handle streamed data
|
|
165
|
+
receiveStream: async (data: any) => {
|
|
166
|
+
console.log('Processing stream chunk:', data);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
await humanAgent.start();
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### `oAILoginTool`
|
|
176
|
+
|
|
177
|
+
Creates a login node for AI agents.
|
|
178
|
+
|
|
179
|
+
**Constructor**:
|
|
180
|
+
```typescript
|
|
181
|
+
new oAILoginTool(config: oLoginConfig)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Parameters**:
|
|
185
|
+
Same as `oHumanLoginTool`, but with default address `o://ai`.
|
|
186
|
+
|
|
187
|
+
**Example**:
|
|
188
|
+
```typescript
|
|
189
|
+
import { oAILoginTool } from '@olane/o-login';
|
|
190
|
+
import OpenAI from 'openai';
|
|
191
|
+
|
|
192
|
+
const openai = new OpenAI();
|
|
193
|
+
|
|
194
|
+
const aiAgent = new oAILoginTool({
|
|
195
|
+
// AI processes intents
|
|
196
|
+
respond: async (intent: string) => {
|
|
197
|
+
const completion = await openai.chat.completions.create({
|
|
198
|
+
model: 'gpt-4',
|
|
199
|
+
messages: [{ role: 'user', content: intent }]
|
|
200
|
+
});
|
|
201
|
+
return completion.choices[0].message.content;
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
// AI answers questions
|
|
205
|
+
answer: async (question: string) => {
|
|
206
|
+
const completion = await openai.chat.completions.create({
|
|
207
|
+
model: 'gpt-4',
|
|
208
|
+
messages: [{ role: 'user', content: question }]
|
|
209
|
+
});
|
|
210
|
+
return completion.choices[0].message.content;
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
// AI processes streams
|
|
214
|
+
receiveStream: async (data: any) => {
|
|
215
|
+
// Process incoming data
|
|
216
|
+
await processDataWithAI(data);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
await aiAgent.start();
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### `oLoginTool` (Base Class)
|
|
226
|
+
|
|
227
|
+
Base class for all login tools. Extends `oLaneTool` from `@olane/o-lane`.
|
|
228
|
+
|
|
229
|
+
You can extend this directly for custom agent types:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import { oLoginTool } from '@olane/o-login';
|
|
233
|
+
import { oNodeAddress } from '@olane/o-node';
|
|
234
|
+
|
|
235
|
+
class CustomAgentLogin extends oLoginTool {
|
|
236
|
+
constructor() {
|
|
237
|
+
super({
|
|
238
|
+
address: new oNodeAddress('o://custom-agent'),
|
|
239
|
+
respond: async (intent: string) => {
|
|
240
|
+
// Custom intent handling
|
|
241
|
+
return 'Custom response';
|
|
242
|
+
},
|
|
243
|
+
answer: async (question: string) => {
|
|
244
|
+
// Custom question handling
|
|
245
|
+
return 'Custom answer';
|
|
246
|
+
},
|
|
247
|
+
receiveStream: async (data: any) => {
|
|
248
|
+
// Custom stream handling
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Built-in Tools {#built-in-tools}
|
|
258
|
+
|
|
259
|
+
Every login node exposes three tools:
|
|
260
|
+
|
|
261
|
+
### `_tool_intent`
|
|
262
|
+
|
|
263
|
+
Handles intent-based requests.
|
|
264
|
+
|
|
265
|
+
**Parameters**:
|
|
266
|
+
- `intent` (string, required): The intent to resolve
|
|
267
|
+
|
|
268
|
+
**Returns**:
|
|
269
|
+
```typescript
|
|
270
|
+
{
|
|
271
|
+
success: boolean;
|
|
272
|
+
resolution: string;
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Example Usage** (from another node):
|
|
277
|
+
```typescript
|
|
278
|
+
// Another node sends an intent to the human agent
|
|
279
|
+
const result = await humanAgent.use({
|
|
280
|
+
method: 'intent',
|
|
281
|
+
params: {
|
|
282
|
+
intent: 'Please approve the budget request for Q4'
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
console.log(result.resolution);
|
|
287
|
+
// "Request approved" (based on your respond callback)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
### `_tool_question`
|
|
293
|
+
|
|
294
|
+
Handles question-answer requests.
|
|
295
|
+
|
|
296
|
+
**Parameters**:
|
|
297
|
+
- `question` (string, required): The question to answer
|
|
298
|
+
|
|
299
|
+
**Returns**:
|
|
300
|
+
```typescript
|
|
301
|
+
{
|
|
302
|
+
success: boolean;
|
|
303
|
+
answer: string;
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Example Usage** (from another node):
|
|
308
|
+
```typescript
|
|
309
|
+
// Another node asks a question
|
|
310
|
+
const result = await aiAgent.use({
|
|
311
|
+
method: 'question',
|
|
312
|
+
params: {
|
|
313
|
+
question: 'What is the capital of France?'
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
console.log(result.answer);
|
|
318
|
+
// "Paris" (based on your answer callback)
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
### `_tool_receive_stream`
|
|
324
|
+
|
|
325
|
+
Handles streamed data.
|
|
326
|
+
|
|
327
|
+
**Parameters**:
|
|
328
|
+
- `data` (any, required): The data to process
|
|
329
|
+
|
|
330
|
+
**Returns**:
|
|
331
|
+
```typescript
|
|
332
|
+
{
|
|
333
|
+
success: boolean;
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Example Usage** (from another node):
|
|
338
|
+
```typescript
|
|
339
|
+
// Another node streams data
|
|
340
|
+
await humanAgent.use({
|
|
341
|
+
method: 'receive_stream',
|
|
342
|
+
params: {
|
|
343
|
+
data: { type: 'notification', message: 'System update available' }
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Common Use Cases {#common-use-cases}
|
|
351
|
+
|
|
352
|
+
### Use Case 1: Human-in-the-Loop Approval System
|
|
353
|
+
|
|
354
|
+
Create a human agent that approves or rejects automated actions.
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
import { oHumanLoginTool } from '@olane/o-login';
|
|
358
|
+
import readline from 'readline';
|
|
359
|
+
|
|
360
|
+
const rl = readline.createInterface({
|
|
361
|
+
input: process.stdin,
|
|
362
|
+
output: process.stdout
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
const humanApprover = new oHumanLoginTool({
|
|
366
|
+
address: new oNodeAddress('o://approvals/human'),
|
|
367
|
+
|
|
368
|
+
respond: async (intent: string) => {
|
|
369
|
+
// Prompt human for approval
|
|
370
|
+
return new Promise((resolve) => {
|
|
371
|
+
rl.question(`Approve this action? "${intent}" (y/n): `, (answer) => {
|
|
372
|
+
if (answer.toLowerCase() === 'y') {
|
|
373
|
+
resolve('Approved by human operator');
|
|
374
|
+
} else {
|
|
375
|
+
resolve('Rejected by human operator');
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
},
|
|
380
|
+
|
|
381
|
+
answer: async (question: string) => {
|
|
382
|
+
return new Promise((resolve) => {
|
|
383
|
+
rl.question(`${question}\nYour answer: `, resolve);
|
|
384
|
+
});
|
|
385
|
+
},
|
|
386
|
+
|
|
387
|
+
receiveStream: async (data: any) => {
|
|
388
|
+
console.log('[Human Dashboard] Received:', data);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
await humanApprover.start();
|
|
393
|
+
console.log('Human approver is online. Awaiting approval requests...');
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
### Use Case 2: AI Assistant with Context
|
|
399
|
+
|
|
400
|
+
Create an AI agent that maintains conversation context.
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
import { oAILoginTool } from '@olane/o-login';
|
|
404
|
+
import OpenAI from 'openai';
|
|
405
|
+
|
|
406
|
+
const openai = new OpenAI();
|
|
407
|
+
const conversationHistory: any[] = [];
|
|
408
|
+
|
|
409
|
+
const aiAssistant = new oAILoginTool({
|
|
410
|
+
address: new oNodeAddress('o://ai/assistant'),
|
|
411
|
+
|
|
412
|
+
respond: async (intent: string) => {
|
|
413
|
+
// Add to conversation history
|
|
414
|
+
conversationHistory.push({
|
|
415
|
+
role: 'user',
|
|
416
|
+
content: intent
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
// Get AI response with context
|
|
420
|
+
const completion = await openai.chat.completions.create({
|
|
421
|
+
model: 'gpt-4',
|
|
422
|
+
messages: conversationHistory
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
const response = completion.choices[0].message.content;
|
|
426
|
+
|
|
427
|
+
// Store AI response in history
|
|
428
|
+
conversationHistory.push({
|
|
429
|
+
role: 'assistant',
|
|
430
|
+
content: response
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
return response;
|
|
434
|
+
},
|
|
435
|
+
|
|
436
|
+
answer: async (question: string) => {
|
|
437
|
+
// Similar to respond, but for direct questions
|
|
438
|
+
conversationHistory.push({
|
|
439
|
+
role: 'user',
|
|
440
|
+
content: question
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
const completion = await openai.chat.completions.create({
|
|
444
|
+
model: 'gpt-4',
|
|
445
|
+
messages: conversationHistory
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
return completion.choices[0].message.content;
|
|
449
|
+
},
|
|
450
|
+
|
|
451
|
+
receiveStream: async (data: any) => {
|
|
452
|
+
// Process streamed data (e.g., document chunks)
|
|
453
|
+
conversationHistory.push({
|
|
454
|
+
role: 'system',
|
|
455
|
+
content: `Context data received: ${JSON.stringify(data)}`
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
await aiAssistant.start();
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
### Use Case 3: Multi-Agent System
|
|
466
|
+
|
|
467
|
+
Create both human and AI agents working together.
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
import { oHumanLoginTool, oAILoginTool } from '@olane/o-login';
|
|
471
|
+
import { oNodeAddress } from '@olane/o-node';
|
|
472
|
+
|
|
473
|
+
// AI agent handles routine questions
|
|
474
|
+
const aiSupport = new oAILoginTool({
|
|
475
|
+
address: new oNodeAddress('o://support/ai'),
|
|
476
|
+
|
|
477
|
+
respond: async (intent: string) => {
|
|
478
|
+
// Check if AI can handle this
|
|
479
|
+
if (intent.includes('complex') || intent.includes('escalate')) {
|
|
480
|
+
// Forward to human
|
|
481
|
+
const humanResult = await humanSupport.use({
|
|
482
|
+
method: 'intent',
|
|
483
|
+
params: { intent }
|
|
484
|
+
});
|
|
485
|
+
return `Escalated to human: ${humanResult.resolution}`;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// AI handles routine intents
|
|
489
|
+
return 'AI resolved the routine request';
|
|
490
|
+
},
|
|
491
|
+
|
|
492
|
+
answer: async (question: string) => {
|
|
493
|
+
return 'AI answer to routine question';
|
|
494
|
+
},
|
|
495
|
+
|
|
496
|
+
receiveStream: async (data: any) => {
|
|
497
|
+
console.log('[AI] Processing:', data);
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// Human agent handles escalations
|
|
502
|
+
const humanSupport = new oHumanLoginTool({
|
|
503
|
+
address: new oNodeAddress('o://support/human'),
|
|
504
|
+
|
|
505
|
+
respond: async (intent: string) => {
|
|
506
|
+
console.log('[Human] Handling escalated request:', intent);
|
|
507
|
+
// Human decides on action
|
|
508
|
+
return 'Human resolved complex request';
|
|
509
|
+
},
|
|
510
|
+
|
|
511
|
+
answer: async (question: string) => {
|
|
512
|
+
console.log('[Human] Answering complex question:', question);
|
|
513
|
+
return 'Human answer to complex question';
|
|
514
|
+
},
|
|
515
|
+
|
|
516
|
+
receiveStream: async (data: any) => {
|
|
517
|
+
console.log('[Human] Reviewing:', data);
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
// Start both agents
|
|
522
|
+
await aiSupport.start();
|
|
523
|
+
await humanSupport.start();
|
|
524
|
+
|
|
525
|
+
console.log('Multi-agent support system is online');
|
|
526
|
+
console.log('AI Support:', aiSupport.address.toString());
|
|
527
|
+
console.log('Human Support:', humanSupport.address.toString());
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## Integration with Other Nodes {#integration}
|
|
533
|
+
|
|
534
|
+
Login nodes can interact with any other node on Olane OS.
|
|
535
|
+
|
|
536
|
+
### Example: Agent Receives Work from Another Node
|
|
537
|
+
|
|
538
|
+
```typescript
|
|
539
|
+
import { oHumanLoginTool } from '@olane/o-login';
|
|
540
|
+
import { oLaneTool } from '@olane/o-lane';
|
|
541
|
+
import { oNodeAddress } from '@olane/o-node';
|
|
542
|
+
|
|
543
|
+
// Create a task processor node
|
|
544
|
+
const taskProcessor = new oLaneTool({
|
|
545
|
+
address: new oNodeAddress('o://tasks/processor')
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
// Create human agent that receives tasks
|
|
549
|
+
const humanWorker = new oHumanLoginTool({
|
|
550
|
+
address: new oNodeAddress('o://workers/human'),
|
|
551
|
+
|
|
552
|
+
respond: async (intent: string) => {
|
|
553
|
+
console.log('New task:', intent);
|
|
554
|
+
// Process the task
|
|
555
|
+
return 'Task completed';
|
|
556
|
+
},
|
|
557
|
+
|
|
558
|
+
answer: async (question: string) => {
|
|
559
|
+
return 'Status: Working';
|
|
560
|
+
},
|
|
561
|
+
|
|
562
|
+
receiveStream: async (data: any) => {
|
|
563
|
+
console.log('Task update:', data);
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
await taskProcessor.start();
|
|
568
|
+
await humanWorker.start();
|
|
569
|
+
|
|
570
|
+
// Task processor sends work to human
|
|
571
|
+
const result = await humanWorker.use({
|
|
572
|
+
method: 'intent',
|
|
573
|
+
params: {
|
|
574
|
+
intent: 'Review and approve the financial report'
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
console.log('Result:', result.resolution);
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
## Advanced Configuration {#advanced-configuration}
|
|
584
|
+
|
|
585
|
+
### Custom Address
|
|
586
|
+
|
|
587
|
+
Override the default address:
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
const agent = new oHumanLoginTool({
|
|
591
|
+
address: new oNodeAddress('o://company/team/alice'),
|
|
592
|
+
respond: async (intent) => 'resolved',
|
|
593
|
+
answer: async (question) => 'answered',
|
|
594
|
+
receiveStream: async (data) => {}
|
|
595
|
+
});
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### Network Registration with Leader
|
|
599
|
+
|
|
600
|
+
Connect to a leader node for service discovery:
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
import { oAddress } from '@olane/o-core';
|
|
604
|
+
|
|
605
|
+
const agent = new oHumanLoginTool({
|
|
606
|
+
leader: new oAddress('o://network/leader'),
|
|
607
|
+
respond: async (intent) => 'resolved',
|
|
608
|
+
answer: async (question) => 'answered',
|
|
609
|
+
receiveStream: async (data) => {}
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
await agent.start();
|
|
613
|
+
|
|
614
|
+
// Now discoverable by other nodes through the leader
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### Hierarchical Agents
|
|
618
|
+
|
|
619
|
+
Create agent hierarchies:
|
|
620
|
+
|
|
621
|
+
```typescript
|
|
622
|
+
// Parent agent
|
|
623
|
+
const parentAgent = new oHumanLoginTool({
|
|
624
|
+
address: new oNodeAddress('o://team/manager'),
|
|
625
|
+
respond: async (intent) => 'Manager approved',
|
|
626
|
+
answer: async (question) => 'Manager answered',
|
|
627
|
+
receiveStream: async (data) => {}
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
await parentAgent.start();
|
|
631
|
+
|
|
632
|
+
// Child agent
|
|
633
|
+
const childAgent = new oAILoginTool({
|
|
634
|
+
address: new oNodeAddress('o://team/assistant'),
|
|
635
|
+
parent: parentAgent.address,
|
|
636
|
+
respond: async (intent) => {
|
|
637
|
+
// Escalate to parent if needed
|
|
638
|
+
if (intent.includes('urgent')) {
|
|
639
|
+
const result = await parentAgent.use({
|
|
640
|
+
method: 'intent',
|
|
641
|
+
params: { intent }
|
|
642
|
+
});
|
|
643
|
+
return result.resolution;
|
|
644
|
+
}
|
|
645
|
+
return 'Assistant handled';
|
|
646
|
+
},
|
|
647
|
+
answer: async (question) => 'Assistant answered',
|
|
648
|
+
receiveStream: async (data) => {}
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
await childAgent.start();
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
---
|
|
655
|
+
|
|
656
|
+
## Lifecycle Management {#lifecycle}
|
|
657
|
+
|
|
658
|
+
### Starting an Agent
|
|
659
|
+
|
|
660
|
+
```typescript
|
|
661
|
+
const agent = new oHumanLoginTool({
|
|
662
|
+
respond: async (intent) => 'resolved',
|
|
663
|
+
answer: async (question) => 'answered',
|
|
664
|
+
receiveStream: async (data) => {}
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
// Start the agent (becomes addressable)
|
|
668
|
+
await agent.start();
|
|
669
|
+
console.log('Agent online at:', agent.address.toString());
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
### Stopping an Agent
|
|
673
|
+
|
|
674
|
+
```typescript
|
|
675
|
+
// Gracefully stop the agent
|
|
676
|
+
await agent.stop();
|
|
677
|
+
console.log('Agent offline');
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### Error Handling
|
|
681
|
+
|
|
682
|
+
```typescript
|
|
683
|
+
const agent = new oHumanLoginTool({
|
|
684
|
+
respond: async (intent: string) => {
|
|
685
|
+
try {
|
|
686
|
+
// Your logic
|
|
687
|
+
return 'Success';
|
|
688
|
+
} catch (error) {
|
|
689
|
+
console.error('Error handling intent:', error);
|
|
690
|
+
return 'Failed to process intent';
|
|
691
|
+
}
|
|
692
|
+
},
|
|
693
|
+
|
|
694
|
+
answer: async (question: string) => {
|
|
695
|
+
try {
|
|
696
|
+
// Your logic
|
|
697
|
+
return 'Answer';
|
|
698
|
+
} catch (error) {
|
|
699
|
+
console.error('Error answering question:', error);
|
|
700
|
+
return 'Failed to answer question';
|
|
701
|
+
}
|
|
702
|
+
},
|
|
703
|
+
|
|
704
|
+
receiveStream: async (data: any) => {
|
|
705
|
+
try {
|
|
706
|
+
// Your logic
|
|
707
|
+
} catch (error) {
|
|
708
|
+
console.error('Error processing stream:', error);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
---
|
|
715
|
+
|
|
716
|
+
## Troubleshooting {#troubleshooting}
|
|
717
|
+
|
|
718
|
+
### Error: "Address already in use"
|
|
719
|
+
|
|
720
|
+
**Cause**: Another agent is already using the default address (`o://human` or `o://ai`).
|
|
721
|
+
|
|
722
|
+
**Solution**: Provide a custom address:
|
|
723
|
+
```typescript
|
|
724
|
+
const agent = new oHumanLoginTool({
|
|
725
|
+
address: new oNodeAddress('o://team/alice'),
|
|
726
|
+
// ... other config
|
|
727
|
+
});
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
---
|
|
731
|
+
|
|
732
|
+
### Error: "Cannot connect to leader"
|
|
733
|
+
|
|
734
|
+
**Cause**: Leader node is not reachable or not running.
|
|
735
|
+
|
|
736
|
+
**Solution**:
|
|
737
|
+
1. Verify leader is running
|
|
738
|
+
2. Check leader address is correct
|
|
739
|
+
3. Or start without leader for local-only operation:
|
|
740
|
+
```typescript
|
|
741
|
+
const agent = new oHumanLoginTool({
|
|
742
|
+
leader: null, // No leader needed for local testing
|
|
743
|
+
// ... other config
|
|
744
|
+
});
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
---
|
|
748
|
+
|
|
749
|
+
### Callback Function Not Called
|
|
750
|
+
|
|
751
|
+
**Cause**: Request is using wrong method name or parameters.
|
|
752
|
+
|
|
753
|
+
**Solution**: Verify the calling code uses correct method names:
|
|
754
|
+
- Use `method: 'intent'` (not `respond`)
|
|
755
|
+
- Use `method: 'question'` (not `answer`)
|
|
756
|
+
- Use `method: 'receive_stream'` (not `receiveStream`)
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
### TypeScript Type Errors
|
|
761
|
+
|
|
762
|
+
**Cause**: Missing peer dependencies.
|
|
763
|
+
|
|
764
|
+
**Solution**: Install all peer dependencies:
|
|
765
|
+
```bash
|
|
766
|
+
npm install @olane/o-core @olane/o-config @olane/o-protocol @olane/o-tool @olane/o-lane @olane/o-node
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
## Comparison: Human vs AI Login {#comparison}
|
|
772
|
+
|
|
773
|
+
| Aspect | `oHumanLoginTool` | `oAILoginTool` |
|
|
774
|
+
|--------|-------------------|----------------|
|
|
775
|
+
| **Default Address** | `o://human` | `o://ai` |
|
|
776
|
+
| **Use Case** | Human approval, oversight, decision-making | Automated processing, AI reasoning |
|
|
777
|
+
| **Response Time** | Slower (human input required) | Faster (automated) |
|
|
778
|
+
| **Context Handling** | Can interpret nuance | Requires context management |
|
|
779
|
+
| **Best For** | Approvals, complex decisions | Routine questions, data processing |
|
|
780
|
+
|
|
781
|
+
---
|
|
782
|
+
|
|
783
|
+
## Architecture {#architecture}
|
|
784
|
+
|
|
785
|
+
`o-login` nodes are **complex nodes** that use the `o-lane` capability loop for intent processing.
|
|
786
|
+
|
|
787
|
+
```
|
|
788
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
789
|
+
│ o-login (extends oLaneTool) │
|
|
790
|
+
│ │
|
|
791
|
+
│ Capabilities: │
|
|
792
|
+
│ • Intent-driven interaction (via o-lane) │
|
|
793
|
+
│ • Addressable node (via o-node) │
|
|
794
|
+
│ • Tool discovery (via o-tool) │
|
|
795
|
+
│ • Network registration (via o-leader) │
|
|
796
|
+
│ │
|
|
797
|
+
│ Three exposed tools: │
|
|
798
|
+
│ • _tool_intent │
|
|
799
|
+
│ • _tool_question │
|
|
800
|
+
│ • _tool_receive_stream │
|
|
801
|
+
└─────────────────────────────────────────────────────────────┘
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
**Related Concepts**:
|
|
805
|
+
- [Tools, Nodes, and Applications](/docs/concepts/tools-nodes-applications)
|
|
806
|
+
- [Human in the Loop](/docs/agents/human-in-the-loop)
|
|
807
|
+
- [Complex Nodes](/docs/concepts/nodes/complex-nodes)
|
|
808
|
+
|
|
809
|
+
---
|
|
810
|
+
|
|
811
|
+
## TypeScript Support {#typescript}
|
|
812
|
+
|
|
813
|
+
Full TypeScript definitions included:
|
|
814
|
+
|
|
815
|
+
```typescript
|
|
816
|
+
import { oLoginConfig } from '@olane/o-login';
|
|
817
|
+
|
|
818
|
+
// Config interface
|
|
819
|
+
interface oLoginConfig extends oNodeConfig {
|
|
820
|
+
respond: (intent: string) => Promise<string>;
|
|
821
|
+
answer: (intent: string) => Promise<string>;
|
|
822
|
+
receiveStream: (data: any) => Promise<any>;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// Type-safe usage
|
|
826
|
+
const config: oLoginConfig = {
|
|
827
|
+
respond: async (intent: string): Promise<string> => {
|
|
828
|
+
return 'resolved';
|
|
829
|
+
},
|
|
830
|
+
answer: async (question: string): Promise<string> => {
|
|
831
|
+
return 'answered';
|
|
832
|
+
},
|
|
833
|
+
receiveStream: async (data: any): Promise<any> => {
|
|
834
|
+
console.log(data);
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
---
|
|
840
|
+
|
|
841
|
+
## Related Packages {#related-packages}
|
|
842
|
+
|
|
843
|
+
- [`@olane/o-core`](../o-core) - Core primitives and base classes
|
|
844
|
+
- [`@olane/o-node`](../o-node) - Network-connected nodes with P2P
|
|
845
|
+
- [`@olane/o-tool`](../o-tool) - Tool augmentation system
|
|
846
|
+
- [`@olane/o-lane`](../o-lane) - Intent processing and capability loops
|
|
847
|
+
- [`@olane/o-leader`](../o-leader) - Service discovery and network coordination
|
|
848
|
+
|
|
849
|
+
---
|
|
850
|
+
|
|
851
|
+
## Next Steps {#next-steps}
|
|
852
|
+
|
|
853
|
+
**Learn More:**
|
|
854
|
+
- [Human in the Loop Patterns](https://olane.com/docs/agents/human-in-the-loop) - Understand the conceptual patterns
|
|
855
|
+
- [Package Reference](https://olane.com/docs/packages/o-login) - Complete API documentation
|
|
856
|
+
- [Working with Agents](https://olane.com/docs/agents/overview) - Agent integration guide
|
|
857
|
+
- [Complex Nodes](https://olane.com/docs/concepts/nodes/complex-nodes) - Understanding intent-driven nodes
|
|
858
|
+
|
|
859
|
+
**Build an Agent System:**
|
|
860
|
+
1. Create AI agent for routine tasks
|
|
861
|
+
2. Create human agent for escalations
|
|
862
|
+
3. Implement escalation logic
|
|
863
|
+
4. Connect to existing nodes
|
|
864
|
+
|
|
865
|
+
**Integrate with Your App:**
|
|
866
|
+
1. Install `@olane/o-login`
|
|
867
|
+
2. Create agent login for your app
|
|
868
|
+
3. Handle intents and questions
|
|
869
|
+
4. Connect to Olane OS network
|
|
870
|
+
|
|
871
|
+
---
|
|
872
|
+
|
|
873
|
+
## Documentation {#documentation}
|
|
874
|
+
|
|
875
|
+
- [Full Documentation](https://olane.com/docs)
|
|
876
|
+
- [Human in the Loop Guide](https://olane.com/docs/agents/human-in-the-loop)
|
|
877
|
+
- [Package Reference](https://olane.com/docs/packages/o-login)
|
|
878
|
+
- [Olane OS Overview](../../README.md)
|
|
879
|
+
|
|
880
|
+
## Support {#support}
|
|
881
|
+
|
|
882
|
+
- [GitHub Issues](https://github.com/olane-labs/olane/issues)
|
|
883
|
+
- [Community Forum](https://olane.com/community)
|
|
884
|
+
- [Email Support](mailto:support@olane.com)
|
|
885
|
+
|
|
886
|
+
## License
|
|
887
|
+
|
|
888
|
+
ISC © Olane Inc.
|
|
889
|
+
|
|
890
|
+
---
|
|
891
|
+
|
|
892
|
+
**Part of the Olane OS ecosystem** - An agentic operating system where AI agents are the intelligent users, and you build the specialized tool nodes they use.
|
|
893
|
+
|