saico 2.7.0 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +23 -4
  2. package/package.json +1 -1
  3. package/saico.js +7 -5
package/README.md CHANGED
@@ -69,14 +69,15 @@ Saico separates construction from activation:
69
69
  const agent = new Saico({
70
70
  name: 'agent',
71
71
  prompt: 'System prompt here',
72
+ createQ: true, // message Q created on activate()
72
73
  dynamodb: { region: 'us-east-1', credentials: { accessKeyId: 'AK', secretAccessKey: 'SK' } },
73
74
  });
74
75
 
75
76
  // DB methods work before activation
76
77
  const item = await agent.dbGetItem('id', '123');
77
78
 
78
- // 2. Activate — creates internal task + optional message queue context
79
- agent.activate({ createQ: true });
79
+ // 2. Activate — creates internal task + message Q (from this.createQ)
80
+ agent.activate();
80
81
 
81
82
  // 3. Use — send messages, spawn children
82
83
  await agent.sendMessage('Do something');
@@ -86,6 +87,23 @@ await agent.recvChatMessage('User says hello');
86
87
  await agent.deactivate();
87
88
  ```
88
89
 
90
+ Subclasses can also define `this.states` (task functions) in the constructor — `activate()` picks them up automatically:
91
+
92
+ ```js
93
+ class MyAgent extends Saico {
94
+ constructor() {
95
+ super({ name: 'agent', prompt: 'You are helpful', createQ: true });
96
+ this.states = [
97
+ async function main() {
98
+ return await this.sendMessage('Starting...');
99
+ }
100
+ ];
101
+ }
102
+ }
103
+ const agent = new MyAgent();
104
+ agent.activate(); // no params needed — uses this.createQ and this.states
105
+ ```
106
+
89
107
  ### Message Orchestration
90
108
 
91
109
  When `sendMessage()` or `recvChatMessage()` is called, Saico walks the parent chain to build the full LLM payload:
@@ -177,6 +195,7 @@ new Saico({
177
195
  // AI config
178
196
  prompt: 'System prompt',
179
197
  functions: [], // OpenAI function definitions
198
+ createQ: false, // Create message Q on activate() (also settable as this.createQ)
180
199
 
181
200
  // Behavior
182
201
  isolate: false, // Stop ancestor aggregation
@@ -207,9 +226,9 @@ new Saico({
207
226
 
208
227
  ```js
209
228
  agent.activate({
210
- createQ: true, // Create message queue context
229
+ createQ: true, // Override this.createQ for this activation
211
230
  prompt: 'Extra prompt', // Appended to class-level prompt
212
- states: [], // Task state functions
231
+ states: [], // Override this.states for this activation
213
232
  taskId: 'custom-id',
214
233
  sequential_mode: true, // Process messages sequentially
215
234
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "saico",
3
- "version": "2.7.0",
3
+ "version": "2.7.1",
4
4
  "main": "index.js",
5
5
  "type": "commonjs",
6
6
  "description": "Hierarchical AI Conversation Orchestrator - Task hierarchy with conversation contexts",
package/saico.js CHANGED
@@ -37,6 +37,7 @@ class Saico {
37
37
  * @param {Array} [opt.functions] - Available AI functions
38
38
  * @param {string} [opt.key] - Redis key override (default: 'saico:<id>')
39
39
  * @param {boolean} [opt.redis=true] - Set false to skip Redis proxy
40
+ * @param {boolean} [opt.createQ] - Create message Q context on activate()
40
41
  * @param {boolean} [opt.isolate] - Isolate: don't aggregate from ancestors
41
42
  * @param {Object} [opt.dynamodb] - DynamoDB config { region, credentials: { accessKeyId, secretAccessKey }, client }
42
43
  * @param {Object} [opt.db] - Pluggable DB backend
@@ -60,6 +61,7 @@ class Saico {
60
61
  this.name = opt.name || this.constructor.name || 'saico';
61
62
  this.prompt = opt.prompt || '';
62
63
  this.functions = opt.functions || null;
64
+ this.createQ = opt.createQ || false;
63
65
 
64
66
  // Absorbed from Sid
65
67
  this.userData = opt.userData || {};
@@ -99,10 +101,10 @@ class Saico {
99
101
  * Create the internal Itask and optionally a message Q context.
100
102
  *
101
103
  * @param {Object} opts
102
- * @param {boolean} [opts.createQ] - If true, attach a message Q (Context)
104
+ * @param {boolean} [opts.createQ] - Override this.createQ for this activation
103
105
  * @param {string} [opts.prompt] - Additional prompt (appended to class-level)
104
106
  * @param {Array} [opts.functions] - Override functions
105
- * @param {Array} [opts.states] - Task state functions
107
+ * @param {Array} [opts.states] - Override this.states for this activation
106
108
  * @param {string} [opts.taskId] - Custom task ID
107
109
  * @param {number} [opts.token_limit] - Token limit for context
108
110
  * @param {number} [opts.max_depth] - Max tool call depth
@@ -119,7 +121,7 @@ class Saico {
119
121
  if (this._task)
120
122
  throw new Error('Already activated. Call deactivate() first.');
121
123
 
122
- const states = opts.states || [];
124
+ const states = opts.states || this.states || [];
123
125
 
124
126
  // Build effective prompt: class-level + activation-level
125
127
  const effectivePrompt = [this.prompt, opts.prompt].filter(Boolean).join('\n');
@@ -136,8 +138,8 @@ class Saico {
136
138
  // Store Saico reference on task for parent chain traversal
137
139
  this._task._saico = this;
138
140
 
139
- // Create message Q context if requested (only via createQ flag, NOT prompt)
140
- if (opts.createQ) {
141
+ // Create message Q context if requested (class-level or activate-level)
142
+ if (opts.createQ ?? this.createQ) {
141
143
  const functions = opts.functions || this.functions;
142
144
  const contextConfig = {
143
145
  tag: opts.tag || this._task.id,