@indra.ai/deva 1.0.35 → 1.1.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 CHANGED
@@ -9,20 +9,29 @@ The Deva module is a JavaScript library for building multi-agent systems that ca
9
9
 
10
10
  ## Functions
11
11
 
12
- - Dynamic Agent Loading - The Deva module allows for dynamic agent loading, which means that agents can be loaded and unloaded on the fly as needed. This provides scalability for the multi-agent system, as agents can be added or removed as demand changes.
12
+ Here are some insights about the code you shared:
13
13
 
14
- - Talk/Listen events - The module uses talk/listen events for agent broadcasting. This means that agents can communicate with each other by sending messages through the event pipeline. This allows for real-time communication and coordination between agents.
14
+ 1. Class Structure: The code follows an object-oriented programming approach by defining a `Deva` class. This allows for encapsulation of properties and methods related to the agent.
15
15
 
16
- - Question, Answer - The main function of the Deva module is to handle questions and answers between agents. When an agent has a question, it can send it to another agent using the "question" function. The receiving agent can then process the question and send an answer back using the "answer" function.
16
+ 2. State Management: The `Deva` class has a state management system represented by the `_state` property and the `_states` object. It allows the agent to transition between different states and perform actions based on the current state.
17
17
 
18
- - Ask feature - The Deva module includes an "ask" feature that allows one agent to ask another agent a question directly. This is useful for agents that need to communicate with each other in a targeted way.
18
+ 3. Event System: The code utilizes an event system by extending the `EventEmitter` class and creating an `events` object. This enables communication and collaboration between different components of the agent and other entities in the system.
19
19
 
20
- - State Management - The module includes state management to initiate and track agent processes at different load, process, and exist states. This allows for better tracking and management of agent processes, and helps ensure that the system is running smoothly.
20
+ 4. Modularity and Inheritance: The code demonstrates modularity by separating functionalities into different objects such as `config`, `lib`, `methods`, and `listeners`. It also showcases inheritance by assigning inherited properties to child Deva instances.
21
21
 
22
- - Error Management - The Deva module includes robust error management to handle unexpected errors or exceptions that may occur during the execution of agent processes. This helps ensure that the system is reliable and stable.
22
+ 5. Error Handling: The code includes an error handling mechanism through the `error` method. It allows for uniform error reporting and the execution of custom error handling logic.
23
23
 
24
- - Unifies data-packets - The Deva module unifies data-packets across the architecture, allowing for consistent data exchange between agents regardless of the platform or service they are using. This helps ensure that data is consistent and accurate throughout the system.
24
+ 6. Promises: Promises are used in several asynchronous operations, such as initializing the agent, loading Deva models, and handling method calls. Promises ensure that the code can handle asynchronous operations in a structured and controlled manner.
25
25
 
26
+ 7. Event-driven Architecture: The code follows an event-driven architecture where different events trigger specific actions or callbacks. This enables loose coupling and flexibility in the agent's behavior and interactions with other components.
27
+
28
+ 8. Extensibility: The code provides hooks for custom logic through methods like `onInit`, `onStart`, `onStop`, `onEnter`, `onExit`, and `onDone`. These allow developers to extend the functionality of the agent by adding custom code at specific stages of its lifecycle.
29
+
30
+ 9. Messaging and Communication: The `talk` and `listen` methods facilitate messaging and communication between agents. Agents can ask questions (`ask` method) and receive responses, enabling interaction and collaboration.
31
+
32
+ 10. Utility Functions: The code includes utility functions like generating unique IDs (`uid` method), hashing data (`hash` method), and handling event listeners (`listen`, `once`, `ignore` methods).
33
+
34
+ Overall, the code demonstrates the implementation of a flexible and extensible agent framework with state management, event-driven architecture, and various functionalities for communication, error handling, and lifecycle management.
26
35
 
27
36
  ## Uses
28
37
 
@@ -3,7 +3,11 @@
3
3
  // file LICENSE.md or http://www.opensource.org/licenses/mit-license.php.
4
4
  const Deva = require('../index');
5
5
  const HelloWorld = new Deva({
6
+ client: {
7
+ id: 100,
8
+ },
6
9
  agent: {
10
+ id: 101,
7
11
  key: 'hello',
8
12
  name: 'Hello World',
9
13
  description: 'The most over complex Hello World in the Universe',
@@ -32,30 +36,36 @@ const HelloWorld = new Deva({
32
36
  vars: {
33
37
  hello: 'Hello World'
34
38
  },
35
- listeners: {},
39
+ listeners: {
40
+ '101:state'(st) {
41
+ console.log(`current state: ${st}`);
42
+ }
43
+ },
36
44
  deva: {},
37
45
  modules: {},
38
46
  func: {
39
- hello() {
40
- return this.agent.translate(this.vars.hello);
47
+ state(packet) {
48
+ const ret = `${this._state} ${this.uid(true)} ${this.uid()} ${this.hash(JSON.stringify(packet), 'sha256')}`;
49
+ return Promise.resolve(ret);
41
50
  }
42
51
  },
43
52
  methods: {
44
- hello() {
45
- return this.func.hello();
53
+ state(packet) {
54
+ return this.func.state(packet);
46
55
  }
47
56
  },
57
+ onError(e, packet) {
58
+ console.log('ERROR\n\n', e, packet);
59
+ }
60
+ });
48
61
 
49
- onStart() {
50
- console.log(this.methods.hello());
51
- },
52
-
53
- onStop() {},
54
- onEnter() {},
55
- onExit() {},
56
- onDone() {},
57
- onInit() {
58
- this.start();
59
- },
62
+ HelloWorld.init().then(done => {
63
+ return HelloWorld.question('/state how are you')
64
+ }).then(answer => {
65
+ console.log('ANSWER', answer.a.text);
60
66
  });
61
- HelloWorld.init();
67
+
68
+
69
+ // HelloWorld.question('/hello hello there').then(hello => {
70
+ // console.log('hello', hello);
71
+ // });
package/index.js CHANGED
@@ -2,13 +2,40 @@
2
2
  // Distributed under the MIT software license, see the accompanying
3
3
  // file LICENSE.md or http://www.opensource.org/licenses/mit-license.php.
4
4
  const {EventEmitter} = require('events');
5
+ const { createHash, randomUUID } = require('crypto');
6
+
5
7
  class Deva {
6
8
  constructor(opts) {
7
9
  opts = opts || {};
8
10
  this._uid = this.uid(); // the unique id assigned to the agent at load
9
- this.state = 'offline'; // current state of agent.
10
- this.active = false; // the active/birth date.
11
+ this._state = 'OFFLINE'; // current state of agent.
12
+ this._states = { // The available states to work with.
13
+ offline: 'OFFLINE',
14
+ init: 'INIT',
15
+ start: 'START',
16
+ stop: 'STOP',
17
+ enter: 'ENTER',
18
+ exit: 'EXIT',
19
+ done: 'DONE',
20
+ wait: 'WAITING',
21
+ data: 'DATA',
22
+ ask: 'ASK',
23
+ question: 'QUESTION',
24
+ answer: 'ANSWER',
25
+ talk: 'TALK',
26
+ listen: 'LISTEN',
27
+ error: 'ERROR',
28
+ story: 'STORY',
29
+ development: 'DEVELOPMENT',
30
+ security: 'SECURITY',
31
+ support: 'SUPPORT',
32
+ services: 'SERVICES',
33
+ systems: 'SYSTEMS',
34
+ solutions: 'SOLUTIONS',
35
+ };
36
+ this._active = false; // the active/birth date.
11
37
  this.security = false; // inherited Security features.
38
+ this.support = false; // inherited Support features.
12
39
  this.config = opts.config || {}; // local Config Object
13
40
  this.events = opts.events || new EventEmitter({}); // Event Bus
14
41
  this.lib = opts.lib || {}; // used for loading library functions
@@ -26,49 +53,44 @@ class Deva {
26
53
  if (!this[opt]) this[opt] = opts[opt]; // set any remaining opts to this.
27
54
  }
28
55
 
29
- this.cmdChr = '!';
56
+ this.cmdChr = '/';
30
57
  this.askChr = '#';
31
58
  this.inherit = ["events", "config", "lib", "security", "client"];
32
59
  this.bind = ["listeners", "methods", "func", "lib", "security", "agent", "client"];
33
- this.states = {
34
- offline: 'OFFLINE',
35
- init: 'INITIALIZE',
36
- start: 'START',
37
- stop: 'STOP',
38
- enter: 'ENTER',
39
- exit: 'EXIT',
40
- done: 'DONE',
41
- wait: 'WAITING',
42
- ask: 'ASK',
43
- question: 'QUESTION',
44
- answer: 'ANSWER',
45
- error: 'ERROR',
46
- security: 'SECURITY',
47
- medic: 'MEDICAL',
48
- };
49
60
  this.messages = {
50
61
  offline: 'AGENT OFFLINE',
51
62
  loaded: 'DEVAS LOADED',
52
63
  stopped: 'DEVAS STOPPED',
53
64
  notext: 'NO TEXT',
65
+ notfound: 'NOT FOUND',
54
66
  }
55
67
  }
56
68
 
57
69
  // set the state of the agent with the passed value to match the valid keys.
58
70
  // this will also talk a global state event with the agent data and state.
59
71
  // then security can watch all the glorious state change events.
60
- set _state(st) {
61
- this.state = this.states[st];
62
- this.talk(`state`,{
63
- uid: this.uid(),
64
- agent: this.agent,
65
- state: this.state,
66
- created: Date.now(),
67
- });
68
- this.prompt(this.state);
72
+
73
+ /**************
74
+ func: state
75
+ params:
76
+ - st: The state flag to set for the Deva that matches to this._states
77
+ describe
78
+ ***************/
79
+ state(st) {
80
+ this._state = this._states[st];
81
+ this.talk(`${this.agent.id}:state`, this._state);
69
82
  }
83
+
70
84
  // Called from the init function to bind the elements defined in the this.bind variable.
71
85
  // the assign bind ensures that the *this* scope is available to child elements/functions.
86
+
87
+ /**************
88
+ func: _assignBind
89
+ params: none
90
+ describe:
91
+ The assign bind function will bind the translate functions and parse functions
92
+ of the agent and bind their functionality to the state machine.
93
+ ***************/
72
94
  _assignBind() {
73
95
  return new Promise((resolve, reject) => {
74
96
  try {
@@ -95,13 +117,18 @@ class Deva {
95
117
  });
96
118
  }
97
119
 
98
- // Called from the init function to assign the listeners to various states.
99
- // when the listener fires it will call the associated named function.
120
+ /**************
121
+ func: _assignListeners
122
+ params: none
123
+ describe:
124
+ Assign listeners will take the this.lisners objects and assign the appropriate
125
+ lisnter values for the event bus.
126
+ ***************/
100
127
  _assignListeners() {
101
128
  return new Promise((resolve, reject) => {
102
129
  try {
103
130
  // set the default listeners for the states of the agent.
104
- for (let state in this.states) {
131
+ for (let state in this._states) {
105
132
  this.events.on(`${this.agent.key}:${state}`, packet => {
106
133
  return this[state](packet);
107
134
  })
@@ -124,6 +151,13 @@ class Deva {
124
151
 
125
152
  // Some elements will inherit the data of the parent. this object will loop over
126
153
  // any children data that theis deva has and assign the inherited information.
154
+ /**************
155
+ func: _assignInherit
156
+ params: none
157
+ describe:
158
+ The assign inherit will make sure the Devas in the current Deva have all the
159
+ inherited properties all setup to collaborate efficiently.
160
+ ***************/
127
161
  _assignInherit() {
128
162
  return new Promise((resolve, reject) => {
129
163
  try {
@@ -143,11 +177,25 @@ class Deva {
143
177
  }
144
178
 
145
179
  // General handler for when a method is NOT found from a user command.
180
+ /**************
181
+ func: _methodNotFound
182
+ params:
183
+ - packet: The packet to relay when a method is not found.
184
+ describe:
185
+ The _methodNotFound function allows for additional security by firing
186
+ a specfici program functon every single time a interaction happens wehre a
187
+ method is not located. This assits in security and support by identifying
188
+ troubls or users who may be attemptng to explit features.
189
+
190
+ Then we talk a security event that watches all methods and return the packet.
191
+
192
+ This will return a not found text string preventing any furhter processing.
193
+ ***************/
146
194
  _methodNotFound(packet) {
147
195
  packet.a = {
148
196
  agent: this.agent || false,
149
197
  client: this.client || false,
150
- text: `${packet.q.meta.method} is NOT a valid method.`,
198
+ text: `${packet.q.meta.method} ${this.messages.notfound}`,
151
199
  meta: {
152
200
  key: this.agent.key,
153
201
  method: packet.q.meta.method,
@@ -161,64 +209,123 @@ class Deva {
161
209
  // quite oftne have to key their transactions. This will provide all agents
162
210
  // with the same key generator which can also be modified to link into a remote
163
211
  // generator or some other solution if needed.
164
- uid() {
212
+
213
+ /**************
214
+ func: uid
215
+ params:
216
+ - guid: This is a true false flag for generating a guid.
217
+ describe:
218
+ The uid function can create two types of id for you.
219
+ 1. random GUID - this is good for when you need a uinique record id returned
220
+ 2. transport id - The transport id is a number generated to provide a
221
+ numerical number used for transporting records to places
222
+ like social networks, email, other networks where informaton
223
+ is shared.
224
+ ***************/
225
+ uid(guid=false) {
226
+ if (guid) return randomUUID()
165
227
  const min = Math.floor(Date.now() - (Date.now() / Math.PI));
166
228
  const max = Math.floor(Date.now() + (Date.now() * Math.PI));
167
229
  return Math.floor(Math.random() * (max - min)) + min;
168
230
  }
169
231
 
170
- // The talk interface binds to the events emitter to allow agents to perform a
171
- // this.talk(*) feature.
232
+ /**************
233
+ func: talk
234
+ params:
235
+ - evt: The event the Deva is speaking to listen back for on a once event.
236
+ - resource: The payload resource to send with the talk event.
237
+ describe:
238
+ The talk event allows agents to broadcast events that other Deva can listen
239
+ to and make a response. talk events can be then returned with a talk even id
240
+ to create seamless collaboration between Devas.
241
+ ***************/
172
242
  talk(evt, resource=false) {
173
243
  return this.events.emit(evt, resource);
174
244
  }
175
245
 
176
- // the listen interface binds to the event emitter to allow agents to listen
177
- // this.listen(*) feature.
246
+ /**************
247
+ func: listen
248
+ params:
249
+ - evt: The vent label to listen for
250
+ - callback: The callback function to run when the event fires.
251
+ describe:
252
+ ***************/
178
253
  listen(evt, callback) {
179
254
  return this.events.on(evt, callback);
180
255
  }
181
256
 
182
- // Instances where listening for only one unique keyed event is required
183
- // this interface is provided for the this.once(*) feature.
257
+ /**************
258
+ func: once
259
+ params:
260
+ - evt: The event to listen to for a once call. These event are handy
261
+ when waiting for a key response one time.
262
+ - callback: The callback functoin to run when the event fires.
263
+ describe:
264
+ ***************/
184
265
  once(evt, callback) {
185
266
  return this.events.once(evt, callback);
186
267
  }
187
268
 
188
- // where an agent needs to ignore events or remove a lisatener this interface
189
- // serves the this.ignore(*) feature.
269
+ /**************
270
+ func: ignore
271
+ params:
272
+ - evt: The event you'd like to ignore.
273
+ - callback: a callback function to execute after removing the event from listerns.
274
+ describe:
275
+ The ignore function allow the removal of events that are in the existing devas lister group.
276
+ ***************/
190
277
  ignore(evt, callback) {
191
278
  return this.events.removeListener(evt, callback);
192
279
  }
193
280
 
194
- // Used when loading a Deva dynamically into the current set.
195
- load(opts) {
196
- this.devas[opts.key] = opts;
281
+ /**************
282
+ func: load
283
+ params:
284
+ -deva: The Deva model to load.
285
+ describe:
286
+ This function will enable fast loading of Deva into a system.
287
+ ***************/
288
+ load(deva) {
289
+ this.devas[deva.key] = deva;
197
290
  // inherit the data to the new deva.
198
291
  this.inherit.forEach(inherit => {
199
- this.devas[agent][inherit] = this[inherit];
292
+ this.devas[deva.key][inherit] = this[inherit];
200
293
  });
201
-
202
294
  return Promise.resolve();
203
295
  }
204
296
 
205
- // Used when unloading a deva dynamically from the set.
206
- unload(agent) {
207
- delete this.devas[agent];
208
- return Promise.resolve();
209
- }
210
297
 
211
- // Askign a question to another deva in the set besides itself. If the question
212
- // interface detects the action is to ask another deva a question with
213
- // this.askChr variable match. Then an answer packet is generated and the
214
- // deva is asked to process the question asked and return it's proper data set
215
- // from the requested method.
216
- // this is an event function that relies on talk/listen
298
+ /**************
299
+ func: unload
300
+ params:
301
+ - deva: The deva key to unload
302
+ describe: Unload a currently loaded Deva.
303
+ ***************/
304
+ unload(deva) {
305
+ delete this.devas[deva];
306
+ return Promise.resolve(`unload:${deva} `);
307
+ }
217
308
 
309
+ /**************
310
+ func: ask
311
+ params: packet
312
+ describe:
313
+ The ask function gives each agent the ability to ask question to other agents
314
+ in the system. When a question is asked the Agent with the question if it
315
+ detect an ask event it will trigger. Then if an Agent with the matching ask
316
+ event is listening they will respond. The question function uses this to
317
+ create integrated communication between itself and other Deva in it's library.
318
+
319
+ It can also be used in a custom manner to broadcast ask events inside other coe aswell.
320
+
321
+ When the talk has an answer it will respond with a talk event that has the packet id
322
+ so the event is specific to the talk.
323
+ ***************/
218
324
  ask(packet) {
219
325
  if (!this.active) return Promise.resolve(this.messages.offline);
220
326
 
221
- this._state = this.states.ask;
327
+ this.state('ask');
328
+
222
329
  packet.a = {
223
330
  agent: this.agent || false,
224
331
  client: this.client || false,
@@ -252,38 +359,43 @@ class Deva {
252
359
  else {
253
360
  packet.a.text = result;
254
361
  }
255
- // talk back to the once event with the ask key.
256
362
  this.talk(`${this.agent.key}:ask:${packet.id}`, packet);
363
+ this.state('wait');
257
364
  }).catch(err => {
258
- this._state = this.states.error;
259
- // If the ask method fails then a reject error is returned from the this.error
260
- // interface.
261
365
  this.talk(`${this.agent.key}:ask:${packet.id}`, {error:err.toString()});
262
366
  return this.error(err, packet);
263
367
  })
264
368
  }
265
369
  catch (e) {
266
- this._state = this.states.error;
267
- // if any error is caught in the processing of the ask then it returns and
268
- // executes the this.error(*) interface.
269
370
  this.talk(`${this.agent.key}:ask:${packet.id}`, {error:e.toString()});
270
371
  return this.error(e, packet)
271
372
  }
272
373
  // now when we ask the meta params[0] should be the method
273
374
  }
274
375
 
275
- // general question interface.
276
- // accepts two arguments a *TEXT* and *DATA* object.
277
- // if the question being asked is a simple text command then
278
- // this.question('#*agent.key *method* *text*')
279
- // if the question is a data object
280
- // this.question('#*agent.key* *method* *properties*', {*data*});
376
+ /**************
377
+ func: question
378
+ example: this.question('#*agent.key *method* *text*')
379
+ example: this.question('#*agent.key* *method* *properties*', {*data*})
380
+ params:
381
+ = TEXT: The text string is the question to process in the current state.
382
+ - DATA: The data is a data array or object that also can be passed to the question.
383
+ describe:
384
+ ***************/
281
385
  question(TEXT=false, DATA=false) {
282
- this._state = this.states.question;
283
- const id = this.uid();
386
+ if (!this.active) return Promise.resolve(this.messages.offline);
387
+
388
+ this.state('question'); // set the state to question.
389
+
390
+ const id = this.uid(); // generate a unique transport id for the question.
284
391
  const t_split = TEXT.split(' ');
392
+
393
+ // check to see if the string is an #ask string to talk to the other Deva.
285
394
  const isAsk = t_split[0].startsWith(this.askChr) ? t_split[0].substring(1) : false;
395
+
396
+ // check to see if the string is a command string to run a local method.
286
397
  const isCmd = t_split[0].startsWith(this.cmdChr) ? t_split[0].substring(1) : false;
398
+
287
399
  // Format the packet for return on the request.
288
400
  const orig = TEXT;
289
401
  const data = DATA;
@@ -336,11 +448,11 @@ class Deva {
336
448
  created: Date.now(),
337
449
  }
338
450
 
339
- // if is a command then we format another way
340
- // if the user asks a question to another deva '#' then issue the talk/once
341
- // event combination.
451
+ // hash the packet and insert the hash into the packet meta object.
452
+ packet.q.meta.hash = this.hash(JSON.stringify(packet.q));
453
+
454
+ // If a question to another Deva with '#' then trigger events
342
455
  if (isAsk) {
343
- this._state = this.states.ask;
344
456
  this.talk(`${isAsk}:ask`, packet);
345
457
  this.once(`${isAsk}:ask:${packet.id}`, answer => {
346
458
  return resolve(answer);
@@ -350,6 +462,9 @@ class Deva {
350
462
  else {
351
463
  if (typeof this.methods[method] !== 'function') return resolve(this._methodNotFound(packet));
352
464
  this.methods[method](packet).then(result => {
465
+
466
+ this.state('answer');
467
+
353
468
  const text = typeof result === 'object' ? result.text : result;
354
469
  const html = typeof result === 'object' ? result.html : result;
355
470
  const data = typeof result === 'object' ? result.data : false;
@@ -365,7 +480,13 @@ class Deva {
365
480
  data,
366
481
  created: Date.now(),
367
482
  };
368
- this._state = this.states.answer;
483
+ // create a hash for the answer and insert into answer meta.
484
+ packet.a.meta.hash = this.hash(JSON.stringify(packet.a));
485
+
486
+ // create a hash for entire packet and insert into packet
487
+ packet.hash = this.hash(JSON.stringify(packet));
488
+
489
+ this.state('wait');
369
490
  return resolve(packet);
370
491
  }).catch(err => {
371
492
  return this.error(err, packet);
@@ -378,15 +499,23 @@ class Deva {
378
499
  });
379
500
  }
380
501
 
381
-
382
- // The main init interface where the chain begins.
383
- // a set of options is passed into the init function which is the configuration
384
- // object. from this opts object the system is built. After the opts object is processed
385
- // the inherit is assigned and then bind then listners then
386
- // opts: The options object containing the necessary vaules to build a Deva.
502
+ /**************
503
+ func: init
504
+ params: none
505
+ describe:
506
+ The main init interface where the chain begins. Where the states fire for
507
+ each process of setting:
508
+ 1. Set the Max listeners to control event memory buffer.
509
+ 2. Assign the Interited Properties
510
+ 3. Assign binding functions and methods to 'this' scoe.
511
+ 4. Assign any listeners for additional functionality.
512
+ 5. run the onInit custom function if preset or the system start function.
513
+ 6. The system start function will create a chain reaction of states that load.
514
+ 7. If there is an error the init function rejects the call.
515
+ ***************/
387
516
  init() {
517
+ this.active = Date.now();
388
518
  // set client
389
- this._state = this.states.init;
390
519
  return new Promise((resolve, reject) => {
391
520
  this.events.setMaxListeners(this.maxListeners);
392
521
  this._assignInherit().then(() => {
@@ -394,7 +523,8 @@ class Deva {
394
523
  }).then(() => {
395
524
  return this._assignListeners();
396
525
  }).then(() => {
397
- return this.onInit ? this.onInit() : this.start();
526
+ this.state('init');
527
+ return this.onInit && typeof this.onInit === 'function' ? this.onInit() : this.start();
398
528
  }).then(started => {
399
529
  return resolve(started)
400
530
  }).catch(err => {
@@ -408,100 +538,145 @@ class Deva {
408
538
  // e: is the error to pass into the interface.
409
539
  // packet: the packet that caused the error.
410
540
  error(err,packet=false,reject=false) {
411
- this._state = 'error';
412
- // broadcast a global uniform error event.
413
- this.talk('error', {
414
- id: this.uid(),
415
- agent: this.agent,
416
- client: this.client,
417
- error: err.toString('utf8'),
418
- data: packet,
419
- created: Date.now(),
420
- });
421
- // call the onError if there is a logcal one.
422
- // if there is no local error return a promise reject.
541
+ this.state('error');
542
+ console.error(err)
423
543
  if (this.onError) return this.onError(err, packet, reject);
424
544
  return reject ? reject(err) : false;
425
545
  }
426
546
 
427
- // start the deva then return the 'onStart' function.
547
+ /**************
548
+ func: start
549
+ params: none
550
+ describe:
551
+ The start function begins the process by setting the state to start setting
552
+ the active to the current datetime and then checking for a custom onStart
553
+ function or running the system enter function.
554
+ ***************/
428
555
  start() {
429
- if (this.active) return;
430
- this._state = 'start';
431
- this.active = Date.now();
432
- return this.onStart ? this.onStart() : this.enter();
556
+ if (!this.active) return;
557
+ this.state('start');
558
+ return this.onStart && typeof this.onStart === 'function' ? this.onStart() : this.enter();
433
559
  }
434
560
 
435
- // stop teh deva then return the onStop function.
561
+ /**************
562
+ func: stop
563
+ params: none
564
+ describe:
565
+ The stop function will stop the Deva by setting the active status to false,
566
+ and the state to stop. From here it will check for a custom onStop function
567
+ for anything to run, or run the system exit function.
568
+
569
+ If the deva is offline it will return the offline message.
570
+ ***************/
436
571
  stop() {
437
572
  if (!this.active) return Promise.resolve(this.messages.offline);
573
+ this.state('stop');
438
574
  this.active = false;
439
- this._state = 'stop';
440
- return this.onStop ? this.onStop() : this.exit();
575
+ return this.onStop && typeof this.onStop === 'function' ? this.onStop() : this.exit();
441
576
  }
442
577
 
443
- // enter the deva then return the onEnter function.
578
+ /**************
579
+ func: enter
580
+ params: none
581
+ describe:
582
+ The ener function will check the actie status of the Deva and set it to
583
+ offline or enter.
584
+
585
+ If the Deva is offline it will return the offline message.
586
+ ***************/
444
587
  enter() {
445
588
  if (!this.active) return Promise.resolve(this.messages.offline);
446
- this._state = 'enter';
447
- return this.onEnter ? this.onEnter() : this.done(this.state)
589
+ this.state('enter');
590
+ return this.onEnter && typeof this.onEnter === 'function' ? this.onEnter() : this.done(this.state)
448
591
  }
449
592
 
450
- // exit the deva then return the onExit function.
593
+ /**************
594
+ func: exit
595
+ params: none
596
+ describe:
597
+ The exit state function is triggered when the Deva is exiting it's online
598
+ status and setting the state to exit for things like security check.
599
+
600
+ The return will check for a custom onExit function or run the system done
601
+ function.
602
+
603
+ If the deva is offline it will return the offline message.
604
+ ***************/
451
605
  exit() {
452
606
  if (!this.active) return Promise.resolve(this.messages.offline);
453
- this._state = 'exit';
454
- return this.onExit ? this.onExit() : this.done(this.state)
607
+ this.state('exit');
608
+ this.active = false;
609
+ return this.onExit && typeof this.onExit === 'function' ? this.onExit() : Promise.resolve(this._state)
455
610
  }
456
611
 
457
- // set the deva as done then return the oDone function.
612
+ /**************
613
+ func: done
614
+ params:
615
+ - msg: The done message
616
+ describe:
617
+ When the done function is triggered the system will also set the state
618
+ of hte Deva to done.
619
+
620
+ If the deva is offline it will return the offline message.
621
+ ***************/
458
622
  done(msg=false) {
459
623
  if (!this.active) return Promise.resolve(this.messages.offline);
460
- this._state = 'done';
461
- msg = msg ? msg : this.state;
462
- return this.onDone ? this.onDone() : Promise.resolve({msg,agent:this.agent})
624
+ this.state('done');
625
+ msg = msg ? msg : this._state;
626
+ return this.onDone && typeof this.onDone === 'function' ? this.onDone() : Promise.resolve(this._state)
463
627
  }
464
628
 
465
- // interface to return the status of the current deva with the time/date requested.
466
- status(addtl=false) {
629
+ /**************
630
+ func: status
631
+ params:
632
+ - addto: The addto is any additonal string to append to the end of hte call.
633
+ describe:
634
+ The status function provides an easy way to get the current status of a Deva
635
+ and append custom status messages that may pertain to any custom status call.
636
+
637
+ If the deva is offline it will return the offline message.
638
+ ***************/
639
+ status(addto=false) {
467
640
  if (!this.active) return Promise.resolve(this.messages.offline);
468
641
  const id = this.uid();
469
642
  const dateFormat = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeStyle: 'medium' }).format(this.active);
470
643
  let text = `${this.agent.name} is ONLINE since ${dateFormat}`;
471
- if (addtl) text = text + `\n${addtl}`;
644
+ if (addto) text = text + `\n${addto}`;
472
645
  return Promise.resolve({text});
473
646
  }
474
647
 
475
- // prompt emitter
648
+ /**************
649
+ func: prompt
650
+ params:
651
+ - text: The text string to send to the prompt.
652
+ describe:-
653
+ The prompt function is used to broadcasat a global prompt event with a string. Thsi is handy when passing events between a cli and user interface for example.
654
+ ***************/
476
655
  prompt(text) {
477
- this.talk('prompt', {text, agent:this.agent});
656
+ return this.talk('prompt', {text, agent:this.agent});
478
657
  }
479
658
 
480
- // hash builder
481
- hash(packet) {
482
- if (!this.vars.hash) this.vars.hash = '0x';
483
- // setup basic hashing
484
- // what type of hash depends on param 1
485
- return new Promise((resolve, reject) => {
486
- if (!packet) return reject('NO PACKET');
487
- const params = packet.q.text.split(' ');
488
- const hashType = params[0] ? params[0] : 'view';
489
- switch (hashType) {
490
- case 'clear':
491
- this.vars.hash = '0x';
492
- break;
493
- case 'add':
494
- this.vars.hash = `${this.vars.hash}${params[1]}`;
495
- break;
496
- }
497
- return resolve({
498
- text:this.vars.hash,
499
- html:`<div class="hash">${this.vars.hash}</div>`
500
- });
501
- });
659
+ /**************
660
+ func: hash
661
+ params:
662
+ - texts: The text string to create a hash value for.
663
+ - algo: The hashing algorithm to use for hashing. md5, sha256, or sha512
664
+
665
+ describe:
666
+ The hash algorithm will take a string of text and produce a hash.
667
+ ***************/
668
+ hash(text, algo='md5') {
669
+ const the_hash = createHash(algo);
670
+ the_hash.update(text);
671
+ return the_hash.digest('hex');
502
672
  }
503
- // startDevas interface is to initialize devas that this deva is a parent of.
504
- // This feature allows a Deva to be a parent of a parent of a parent etc....
673
+
674
+ /**************
675
+ func: startDevas
676
+ params: none
677
+ describe:
678
+ Start Devas will initialize the Deva agents inside this curent Deva.
679
+ ***************/
505
680
  startDevas() {
506
681
  return new Promise((resolve, reject) => {
507
682
  const devas = [];
@@ -513,6 +688,12 @@ class Deva {
513
688
  }).catch(reject);
514
689
  });
515
690
  }
691
+ /**************
692
+ func: stpDevas
693
+ params: none
694
+ describe:
695
+ stopDevas will stop all the devas running in the current Deva.
696
+ ***************/
516
697
  stopDevas() {
517
698
  return new Promise((resolve, reject) => {
518
699
  const devas = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indra.ai/deva",
3
- "version": "1.0.35",
3
+ "version": "1.1.1",
4
4
  "description": "The Deva Core",
5
5
  "main": "index.js",
6
6
  "scripts": {