overai 1.4.27 → 1.4.29
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 +54 -1
- package/dist/a2a/adapters/overai.d.ts +21 -0
- package/dist/a2a/adapters/overai.js +94 -0
- package/dist/a2a/channel.d.ts +23 -0
- package/dist/a2a/channel.js +52 -0
- package/dist/a2a/index.d.ts +4 -0
- package/dist/a2a/index.js +20 -0
- package/dist/a2a/messages.d.ts +69 -0
- package/dist/a2a/messages.js +7 -0
- package/dist/a2a/state.d.ts +9 -0
- package/dist/a2a/state.js +46 -0
- package/package.json +12 -1
package/README.md
CHANGED
|
@@ -4,12 +4,16 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://www.npmjs.com/package/overai)
|
|
6
6
|
|
|
7
|
-

|
|
8
8
|
|
|
9
9
|
**OverAI** is the comprehensive, production-ready AI Agents framework designed for **Builders, Entrepreneurs, and Enterprise Developers**.
|
|
10
10
|
|
|
11
11
|
Unlike other frameworks that stop at "Hello World", OverAI provides the full stack needed to **Build, Deploy, and Monetize** AI solutions. From simple automation scripts to full-fledged AI SaaS platforms with billing, API keys, and workflow integrations.
|
|
12
12
|
|
|
13
|
+
## 📣 Join the Community
|
|
14
|
+
|
|
15
|
+
Follow this link to join the WhatsApp group: [Join the WhatsApp Community](https://chat.whatsapp.com/JbXwPg47gJ56Fi9lnAeHy9)
|
|
16
|
+
|
|
13
17
|
## 🚀 Why Choose OverAI?
|
|
14
18
|
|
|
15
19
|
### 💼 For Entrepreneurs & SaaS Builders
|
|
@@ -322,6 +326,55 @@ Support for the MCP standard allows your agents to safely access local files, da
|
|
|
322
326
|
|
|
323
327
|
---
|
|
324
328
|
|
|
329
|
+
## 🤝 A2A (Agent‑to‑Agent) Optionnel
|
|
330
|
+
|
|
331
|
+
OverAI fournit une couche A2A optionnelle pour la négociation et la coordination entre agents, activable à la demande et sans modifier vos agents existants.
|
|
332
|
+
|
|
333
|
+
- Activer la couche A2A par variable d’environnement:
|
|
334
|
+
```bash
|
|
335
|
+
export OVERAI_A2A_ENABLED=true
|
|
336
|
+
```
|
|
337
|
+
- Imports publics:
|
|
338
|
+
```typescript
|
|
339
|
+
import { Agent, Router } from 'overai';
|
|
340
|
+
import { ChannelManager, OverAIAdapter } from 'overai/a2a';
|
|
341
|
+
```
|
|
342
|
+
- Exemple minimal:
|
|
343
|
+
```typescript
|
|
344
|
+
const cm = new ChannelManager(); // activé si OVERAI_A2A_ENABLED=true
|
|
345
|
+
const writer = new Agent({ instructions: 'Tu rédiges des fiches produit' });
|
|
346
|
+
const seo = new Agent({ instructions: 'Tu optimises SEO' });
|
|
347
|
+
|
|
348
|
+
const router = new Router({
|
|
349
|
+
writer: { agent: writer, keywords: ['rédige', 'fiche'] },
|
|
350
|
+
seo: { agent: seo, keywords: ['seo', 'métadonnées', 'balises'] }
|
|
351
|
+
}, { default: 'writer' });
|
|
352
|
+
|
|
353
|
+
const a2a = new OverAIAdapter({
|
|
354
|
+
channel: cm,
|
|
355
|
+
agents: { writer, seo },
|
|
356
|
+
router
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
cm.openChannel('ch-1', ['writer', 'seo']);
|
|
360
|
+
await a2a.handle({
|
|
361
|
+
type: 'propose',
|
|
362
|
+
channelId: 'ch-1',
|
|
363
|
+
from: 'writer',
|
|
364
|
+
to: 'seo',
|
|
365
|
+
timestamp: Date.now(),
|
|
366
|
+
taskId: 'task-123',
|
|
367
|
+
proposal: {
|
|
368
|
+
goal: 'Optimiser la fiche produit pour SEO',
|
|
369
|
+
steps: ['mots-clés', 'meta', 'FAQ', 'JSON-LD']
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Cette couche est facultative et isolée: si OVERAI_A2A_ENABLED n’est pas défini à true, le module reste inactif et vos agents fonctionnent comme d’habitude.
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
325
378
|
## 🛠️ Development
|
|
326
379
|
|
|
327
380
|
To contribute or modify the framework:
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { A2AMessage } from '../messages';
|
|
2
|
+
import { ChannelManager } from '../channel';
|
|
3
|
+
import { Agent } from '../../agent/simple';
|
|
4
|
+
import { Router } from '../../agent/router';
|
|
5
|
+
export interface OverAIAdapterConfig {
|
|
6
|
+
channel: ChannelManager;
|
|
7
|
+
agents: Record<string, Agent>;
|
|
8
|
+
router?: Router;
|
|
9
|
+
}
|
|
10
|
+
export declare class OverAIAdapter {
|
|
11
|
+
private channel;
|
|
12
|
+
private agents;
|
|
13
|
+
private router?;
|
|
14
|
+
private machines;
|
|
15
|
+
constructor(config: OverAIAdapterConfig);
|
|
16
|
+
private getMachine;
|
|
17
|
+
handle(message: A2AMessage): Promise<void>;
|
|
18
|
+
private onPropose;
|
|
19
|
+
private onHandoff;
|
|
20
|
+
private onCommit;
|
|
21
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OverAIAdapter = void 0;
|
|
4
|
+
const state_1 = require("../state");
|
|
5
|
+
class OverAIAdapter {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.machines = new Map();
|
|
8
|
+
this.channel = config.channel;
|
|
9
|
+
this.agents = config.agents;
|
|
10
|
+
this.router = config.router;
|
|
11
|
+
}
|
|
12
|
+
getMachine(channelId) {
|
|
13
|
+
let m = this.machines.get(channelId);
|
|
14
|
+
if (!m) {
|
|
15
|
+
m = new state_1.NegotiationStateMachine();
|
|
16
|
+
this.machines.set(channelId, m);
|
|
17
|
+
}
|
|
18
|
+
return m;
|
|
19
|
+
}
|
|
20
|
+
async handle(message) {
|
|
21
|
+
const machine = this.getMachine(message.channelId);
|
|
22
|
+
machine.apply(message);
|
|
23
|
+
this.channel.send(message);
|
|
24
|
+
switch (message.type) {
|
|
25
|
+
case 'propose':
|
|
26
|
+
await this.onPropose(message);
|
|
27
|
+
break;
|
|
28
|
+
case 'handoff':
|
|
29
|
+
await this.onHandoff(message);
|
|
30
|
+
break;
|
|
31
|
+
case 'commit':
|
|
32
|
+
await this.onCommit(message);
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
// control messages handled by state machine only
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async onPropose(msg) {
|
|
40
|
+
const target = msg.to && this.agents[msg.to];
|
|
41
|
+
const prompt = `Objectif: ${msg.proposal.goal}\n` +
|
|
42
|
+
`Étapes: ${(msg.proposal.steps || []).join(' | ')}\n` +
|
|
43
|
+
`Contraintes: ${(msg.proposal.constraints || []).join(' | ')}\n` +
|
|
44
|
+
`Ressources: ${JSON.stringify(msg.proposal.resources || {})}`;
|
|
45
|
+
if (target) {
|
|
46
|
+
const out = await target.start(prompt);
|
|
47
|
+
const commit = {
|
|
48
|
+
type: 'commit',
|
|
49
|
+
channelId: msg.channelId,
|
|
50
|
+
from: msg.to,
|
|
51
|
+
to: msg.from,
|
|
52
|
+
timestamp: Date.now(),
|
|
53
|
+
taskId: msg.taskId,
|
|
54
|
+
result: { success: true, output: out }
|
|
55
|
+
};
|
|
56
|
+
await this.handle(commit);
|
|
57
|
+
}
|
|
58
|
+
else if (this.router) {
|
|
59
|
+
const result = await this.router.chat(prompt);
|
|
60
|
+
const commit = {
|
|
61
|
+
type: 'commit',
|
|
62
|
+
channelId: msg.channelId,
|
|
63
|
+
from: 'router',
|
|
64
|
+
to: msg.from,
|
|
65
|
+
timestamp: Date.now(),
|
|
66
|
+
taskId: msg.taskId,
|
|
67
|
+
result: { success: true, output: result }
|
|
68
|
+
};
|
|
69
|
+
await this.handle(commit);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async onHandoff(msg) {
|
|
73
|
+
const next = this.agents[msg.nextAgent];
|
|
74
|
+
if (!next)
|
|
75
|
+
return;
|
|
76
|
+
const ctx = msg.context || {};
|
|
77
|
+
const prompt = `Reprise (handoff) avec contexte: ${JSON.stringify(ctx)}`;
|
|
78
|
+
const out = await next.start(prompt);
|
|
79
|
+
const commit = {
|
|
80
|
+
type: 'commit',
|
|
81
|
+
channelId: msg.channelId,
|
|
82
|
+
from: msg.nextAgent,
|
|
83
|
+
to: msg.from,
|
|
84
|
+
timestamp: Date.now(),
|
|
85
|
+
taskId: msg.taskId,
|
|
86
|
+
result: { success: true, output: out }
|
|
87
|
+
};
|
|
88
|
+
await this.handle(commit);
|
|
89
|
+
}
|
|
90
|
+
async onCommit(_msg) {
|
|
91
|
+
// noop: already audited by channel + state machine
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.OverAIAdapter = OverAIAdapter;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { A2AMessage, AgentId, ChannelId } from './messages';
|
|
2
|
+
export interface ChannelRecord {
|
|
3
|
+
id: ChannelId;
|
|
4
|
+
participants: Set<AgentId>;
|
|
5
|
+
audit: A2AMessage[];
|
|
6
|
+
createdAt: number;
|
|
7
|
+
metadata?: Record<string, any>;
|
|
8
|
+
}
|
|
9
|
+
export declare class ChannelManager {
|
|
10
|
+
private channels;
|
|
11
|
+
private agents;
|
|
12
|
+
private enabled;
|
|
13
|
+
static isEnabledEnv(): boolean;
|
|
14
|
+
constructor(enabled?: boolean);
|
|
15
|
+
isEnabled(): boolean;
|
|
16
|
+
registerAgent(agentId: AgentId): void;
|
|
17
|
+
hasAgent(agentId: AgentId): boolean;
|
|
18
|
+
openChannel(id: ChannelId, participants: AgentId[], metadata?: Record<string, any>): ChannelRecord;
|
|
19
|
+
getChannel(id: ChannelId): ChannelRecord | undefined;
|
|
20
|
+
closeChannel(id: ChannelId): boolean;
|
|
21
|
+
send(message: A2AMessage): void;
|
|
22
|
+
getAudit(id: ChannelId): A2AMessage[];
|
|
23
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChannelManager = void 0;
|
|
4
|
+
class ChannelManager {
|
|
5
|
+
static isEnabledEnv() {
|
|
6
|
+
const flag = process.env.OVERAI_A2A_ENABLED;
|
|
7
|
+
return String(flag).toLowerCase() === 'true';
|
|
8
|
+
}
|
|
9
|
+
constructor(enabled = ChannelManager.isEnabledEnv()) {
|
|
10
|
+
this.channels = new Map();
|
|
11
|
+
this.agents = new Set();
|
|
12
|
+
this.enabled = enabled;
|
|
13
|
+
}
|
|
14
|
+
isEnabled() {
|
|
15
|
+
return this.enabled;
|
|
16
|
+
}
|
|
17
|
+
registerAgent(agentId) {
|
|
18
|
+
this.agents.add(agentId);
|
|
19
|
+
}
|
|
20
|
+
hasAgent(agentId) {
|
|
21
|
+
return this.agents.has(agentId);
|
|
22
|
+
}
|
|
23
|
+
openChannel(id, participants, metadata) {
|
|
24
|
+
const record = {
|
|
25
|
+
id,
|
|
26
|
+
participants: new Set(participants),
|
|
27
|
+
audit: [],
|
|
28
|
+
createdAt: Date.now(),
|
|
29
|
+
metadata
|
|
30
|
+
};
|
|
31
|
+
this.channels.set(id, record);
|
|
32
|
+
return record;
|
|
33
|
+
}
|
|
34
|
+
getChannel(id) {
|
|
35
|
+
return this.channels.get(id);
|
|
36
|
+
}
|
|
37
|
+
closeChannel(id) {
|
|
38
|
+
return this.channels.delete(id);
|
|
39
|
+
}
|
|
40
|
+
send(message) {
|
|
41
|
+
const channel = this.channels.get(message.channelId);
|
|
42
|
+
if (!channel) {
|
|
43
|
+
throw new Error(`Channel not found: ${message.channelId}`);
|
|
44
|
+
}
|
|
45
|
+
channel.audit.push(message);
|
|
46
|
+
}
|
|
47
|
+
getAudit(id) {
|
|
48
|
+
const channel = this.channels.get(id);
|
|
49
|
+
return channel ? [...channel.audit] : [];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.ChannelManager = ChannelManager;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./messages"), exports);
|
|
18
|
+
__exportStar(require("./channel"), exports);
|
|
19
|
+
__exportStar(require("./state"), exports);
|
|
20
|
+
__exportStar(require("./adapters/overai"), exports);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A2A-like Message Schema (optional layer)
|
|
3
|
+
*
|
|
4
|
+
* Defines normalized message types for agent-to-agent negotiation and coordination.
|
|
5
|
+
*/
|
|
6
|
+
export type AgentId = string;
|
|
7
|
+
export type ChannelId = string;
|
|
8
|
+
export type TaskId = string;
|
|
9
|
+
export interface BaseMessage {
|
|
10
|
+
type: 'propose' | 'accept' | 'reject' | 'revise' | 'handoff' | 'commit' | 'status' | 'error';
|
|
11
|
+
channelId: ChannelId;
|
|
12
|
+
from: AgentId;
|
|
13
|
+
to?: AgentId;
|
|
14
|
+
taskId?: TaskId;
|
|
15
|
+
correlationId?: string;
|
|
16
|
+
timestamp: number;
|
|
17
|
+
metadata?: Record<string, any>;
|
|
18
|
+
}
|
|
19
|
+
export interface ProposeMessage extends BaseMessage {
|
|
20
|
+
type: 'propose';
|
|
21
|
+
proposal: {
|
|
22
|
+
goal: string;
|
|
23
|
+
steps?: string[];
|
|
24
|
+
constraints?: string[];
|
|
25
|
+
resources?: Record<string, any>;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface AcceptMessage extends BaseMessage {
|
|
29
|
+
type: 'accept';
|
|
30
|
+
acceptedProposalId?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface RejectMessage extends BaseMessage {
|
|
33
|
+
type: 'reject';
|
|
34
|
+
reason?: string;
|
|
35
|
+
suggestedRevision?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface ReviseMessage extends BaseMessage {
|
|
38
|
+
type: 'revise';
|
|
39
|
+
revision: {
|
|
40
|
+
changes: string[];
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export interface HandoffMessage extends BaseMessage {
|
|
44
|
+
type: 'handoff';
|
|
45
|
+
nextAgent: AgentId;
|
|
46
|
+
context?: Record<string, any>;
|
|
47
|
+
}
|
|
48
|
+
export interface CommitMessage extends BaseMessage {
|
|
49
|
+
type: 'commit';
|
|
50
|
+
result?: {
|
|
51
|
+
success: boolean;
|
|
52
|
+
output?: any;
|
|
53
|
+
logs?: string[];
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export interface StatusMessage extends BaseMessage {
|
|
57
|
+
type: 'status';
|
|
58
|
+
status: 'pending' | 'negotiating' | 'in_progress' | 'blocked' | 'completed' | 'failed';
|
|
59
|
+
details?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface ErrorMessage extends BaseMessage {
|
|
62
|
+
type: 'error';
|
|
63
|
+
error: {
|
|
64
|
+
code: string;
|
|
65
|
+
message: string;
|
|
66
|
+
details?: Record<string, any>;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export type A2AMessage = ProposeMessage | AcceptMessage | RejectMessage | ReviseMessage | HandoffMessage | CommitMessage | StatusMessage | ErrorMessage;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { A2AMessage } from './messages';
|
|
2
|
+
export type NegotiationState = 'idle' | 'proposed' | 'accepted' | 'rejected' | 'revising' | 'handoff' | 'committed' | 'failed';
|
|
3
|
+
export declare class NegotiationStateMachine {
|
|
4
|
+
private state;
|
|
5
|
+
private history;
|
|
6
|
+
getState(): NegotiationState;
|
|
7
|
+
getHistory(): A2AMessage[];
|
|
8
|
+
apply(message: A2AMessage): NegotiationState;
|
|
9
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NegotiationStateMachine = void 0;
|
|
4
|
+
class NegotiationStateMachine {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.state = 'idle';
|
|
7
|
+
this.history = [];
|
|
8
|
+
}
|
|
9
|
+
getState() {
|
|
10
|
+
return this.state;
|
|
11
|
+
}
|
|
12
|
+
getHistory() {
|
|
13
|
+
return [...this.history];
|
|
14
|
+
}
|
|
15
|
+
apply(message) {
|
|
16
|
+
this.history.push(message);
|
|
17
|
+
switch (message.type) {
|
|
18
|
+
case 'propose':
|
|
19
|
+
this.state = 'proposed';
|
|
20
|
+
break;
|
|
21
|
+
case 'accept':
|
|
22
|
+
this.state = 'accepted';
|
|
23
|
+
break;
|
|
24
|
+
case 'reject':
|
|
25
|
+
this.state = 'rejected';
|
|
26
|
+
break;
|
|
27
|
+
case 'revise':
|
|
28
|
+
this.state = 'revising';
|
|
29
|
+
break;
|
|
30
|
+
case 'handoff':
|
|
31
|
+
this.state = 'handoff';
|
|
32
|
+
break;
|
|
33
|
+
case 'commit':
|
|
34
|
+
this.state = 'committed';
|
|
35
|
+
break;
|
|
36
|
+
case 'error':
|
|
37
|
+
this.state = 'failed';
|
|
38
|
+
break;
|
|
39
|
+
default:
|
|
40
|
+
// status messages do not change state directly
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
return this.state;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.NegotiationStateMachine = NegotiationStateMachine;
|
package/package.json
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "overai",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.29",
|
|
4
4
|
"description": "OverAI TypeScript AI Agents Framework - Build, Deploy, and Monetize AI Agents in Minutes",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./a2a": {
|
|
13
|
+
"types": "./dist/a2a/index.d.ts",
|
|
14
|
+
"default": "./dist/a2a/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"readmeFilename": "README.md",
|
|
7
18
|
"files": [
|
|
8
19
|
"dist",
|
|
9
20
|
"images",
|