@operor/provider-mock 0.1.0
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/dist/index.d.ts +45 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/package.json +20 -0
- package/src/MockProvider.ts +103 -0
- package/src/index.ts +2 -0
- package/tsdown.config.ts +10 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import EventEmitter from "eventemitter3";
|
|
2
|
+
import { MessageProvider, OutgoingMessage } from "@operor/core";
|
|
3
|
+
|
|
4
|
+
//#region src/MockProvider.d.ts
|
|
5
|
+
interface MockProviderOptions {
|
|
6
|
+
/** Suppress console output. Messages are still captured in sentMessages/receivedMessages. */
|
|
7
|
+
quiet?: boolean;
|
|
8
|
+
/** Label prefix for log lines (e.g. "order-test"). Defaults to "mock". */
|
|
9
|
+
label?: string;
|
|
10
|
+
}
|
|
11
|
+
interface CapturedMessage {
|
|
12
|
+
direction: 'in' | 'out';
|
|
13
|
+
from: string;
|
|
14
|
+
to?: string;
|
|
15
|
+
text: string;
|
|
16
|
+
timestamp: number;
|
|
17
|
+
}
|
|
18
|
+
declare class MockProvider extends EventEmitter implements MessageProvider {
|
|
19
|
+
readonly name = "mock";
|
|
20
|
+
readonly sentMessages: CapturedMessage[];
|
|
21
|
+
readonly receivedMessages: CapturedMessage[];
|
|
22
|
+
private isConnected;
|
|
23
|
+
private messageQueue;
|
|
24
|
+
private quiet;
|
|
25
|
+
private label;
|
|
26
|
+
constructor(options?: MockProviderOptions);
|
|
27
|
+
connect(): Promise<void>;
|
|
28
|
+
disconnect(): Promise<void>;
|
|
29
|
+
sendMessage(to: string, message: OutgoingMessage): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Simulate receiving a message (for testing)
|
|
32
|
+
*/
|
|
33
|
+
simulateIncomingMessage(from: string, text: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get connection status
|
|
36
|
+
*/
|
|
37
|
+
isActive(): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Dump full conversation transcript (useful for debugging failed tests).
|
|
40
|
+
*/
|
|
41
|
+
dumpTranscript(): string;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { type CapturedMessage, MockProvider, type MockProviderOptions };
|
|
45
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/MockProvider.ts"],"mappings":";;;;UAGiB,mBAAA;;EAEf,KAAA;EAFkC;EAIlC,KAAA;AAAA;AAAA,UAGe,eAAA;EACf,SAAA;EACA,IAAA;EACA,EAAA;EACA,IAAA;EACA,SAAA;AAAA;AAAA,cAGW,YAAA,SAAqB,YAAA,YAAwB,eAAA;EAAA,SACxC,IAAA;EAAA,SACA,YAAA,EAAc,eAAA;EAAA,SACd,gBAAA,EAAkB,eAAA;EAAA,QAC1B,WAAA;EAAA,QACA,YAAA;EAAA,QACA,KAAA;EAAA,QACA,KAAA;cAEI,OAAA,GAAU,mBAAA;EAMhB,OAAA,CAAA,GAAW,OAAA;EAKX,UAAA,CAAA,GAAc,OAAA;EAKd,WAAA,CAAY,EAAA,UAAY,OAAA,EAAS,eAAA,GAAkB,OAAA;EALrC;;;EAqBpB,uBAAA,CAAwB,IAAA,UAAc,IAAA;EAzCkB;;;EAoExD,QAAA,CAAA;EApEwD;;;EA2ExD,cAAA,CAAA;AAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import EventEmitter from "eventemitter3";
|
|
2
|
+
|
|
3
|
+
//#region src/MockProvider.ts
|
|
4
|
+
var MockProvider = class extends EventEmitter {
|
|
5
|
+
name = "mock";
|
|
6
|
+
sentMessages = [];
|
|
7
|
+
receivedMessages = [];
|
|
8
|
+
isConnected = false;
|
|
9
|
+
messageQueue = [];
|
|
10
|
+
quiet;
|
|
11
|
+
label;
|
|
12
|
+
constructor(options) {
|
|
13
|
+
super();
|
|
14
|
+
this.quiet = options?.quiet ?? false;
|
|
15
|
+
this.label = options?.label ?? "mock";
|
|
16
|
+
}
|
|
17
|
+
async connect() {
|
|
18
|
+
this.isConnected = true;
|
|
19
|
+
if (!this.quiet) console.log(`[${this.label}] connected`);
|
|
20
|
+
}
|
|
21
|
+
async disconnect() {
|
|
22
|
+
this.isConnected = false;
|
|
23
|
+
if (!this.quiet) console.log(`[${this.label}] disconnected`);
|
|
24
|
+
}
|
|
25
|
+
async sendMessage(to, message) {
|
|
26
|
+
if (!this.isConnected) throw new Error("Provider not connected");
|
|
27
|
+
this.sentMessages.push({
|
|
28
|
+
direction: "out",
|
|
29
|
+
from: "agent",
|
|
30
|
+
to,
|
|
31
|
+
text: message.text,
|
|
32
|
+
timestamp: Date.now()
|
|
33
|
+
});
|
|
34
|
+
if (!this.quiet) {
|
|
35
|
+
const preview = message.text.length > 120 ? message.text.slice(0, 120) + "..." : message.text;
|
|
36
|
+
console.log(`[${this.label}] 📤 → ${to}: ${preview}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Simulate receiving a message (for testing)
|
|
41
|
+
*/
|
|
42
|
+
simulateIncomingMessage(from, text) {
|
|
43
|
+
if (!this.isConnected) throw new Error("Provider not connected");
|
|
44
|
+
const message = {
|
|
45
|
+
id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
46
|
+
from,
|
|
47
|
+
text,
|
|
48
|
+
timestamp: Date.now(),
|
|
49
|
+
channel: "whatsapp",
|
|
50
|
+
provider: this.name
|
|
51
|
+
};
|
|
52
|
+
this.receivedMessages.push({
|
|
53
|
+
direction: "in",
|
|
54
|
+
from,
|
|
55
|
+
text,
|
|
56
|
+
timestamp: Date.now()
|
|
57
|
+
});
|
|
58
|
+
if (!this.quiet) {
|
|
59
|
+
const preview = text.length > 120 ? text.slice(0, 120) + "..." : text;
|
|
60
|
+
console.log(`[${this.label}] 📥 ← ${from}: ${preview}`);
|
|
61
|
+
}
|
|
62
|
+
this.emit("message", message);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get connection status
|
|
66
|
+
*/
|
|
67
|
+
isActive() {
|
|
68
|
+
return this.isConnected;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Dump full conversation transcript (useful for debugging failed tests).
|
|
72
|
+
*/
|
|
73
|
+
dumpTranscript() {
|
|
74
|
+
return [...this.sentMessages, ...this.receivedMessages].sort((a, b) => a.timestamp - b.timestamp).map((m) => {
|
|
75
|
+
return `${m.direction === "in" ? "📥 ←" : "📤 →"} ${m.direction === "in" ? m.from : m.to}: ${m.text}`;
|
|
76
|
+
}).join("\n");
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
81
|
+
export { MockProvider };
|
|
82
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/MockProvider.ts"],"sourcesContent":["import EventEmitter from 'eventemitter3';\nimport type { MessageProvider, IncomingMessage, OutgoingMessage } from '@operor/core';\n\nexport interface MockProviderOptions {\n /** Suppress console output. Messages are still captured in sentMessages/receivedMessages. */\n quiet?: boolean;\n /** Label prefix for log lines (e.g. \"order-test\"). Defaults to \"mock\". */\n label?: string;\n}\n\nexport interface CapturedMessage {\n direction: 'in' | 'out';\n from: string;\n to?: string;\n text: string;\n timestamp: number;\n}\n\nexport class MockProvider extends EventEmitter implements MessageProvider {\n public readonly name = 'mock';\n public readonly sentMessages: CapturedMessage[] = [];\n public readonly receivedMessages: CapturedMessage[] = [];\n private isConnected = false;\n private messageQueue: IncomingMessage[] = [];\n private quiet: boolean;\n private label: string;\n\n constructor(options?: MockProviderOptions) {\n super();\n this.quiet = options?.quiet ?? false;\n this.label = options?.label ?? 'mock';\n }\n\n async connect(): Promise<void> {\n this.isConnected = true;\n if (!this.quiet) console.log(`[${this.label}] connected`);\n }\n\n async disconnect(): Promise<void> {\n this.isConnected = false;\n if (!this.quiet) console.log(`[${this.label}] disconnected`);\n }\n\n async sendMessage(to: string, message: OutgoingMessage): Promise<void> {\n if (!this.isConnected) {\n throw new Error('Provider not connected');\n }\n\n this.sentMessages.push({ direction: 'out', from: 'agent', to, text: message.text, timestamp: Date.now() });\n\n if (!this.quiet) {\n const preview = message.text.length > 120 ? message.text.slice(0, 120) + '...' : message.text;\n console.log(`[${this.label}] 📤 → ${to}: ${preview}`);\n }\n }\n\n /**\n * Simulate receiving a message (for testing)\n */\n simulateIncomingMessage(from: string, text: string): void {\n if (!this.isConnected) {\n throw new Error('Provider not connected');\n }\n\n const message: IncomingMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n from,\n text,\n timestamp: Date.now(),\n channel: 'whatsapp',\n provider: this.name,\n };\n\n this.receivedMessages.push({ direction: 'in', from, text, timestamp: Date.now() });\n\n if (!this.quiet) {\n const preview = text.length > 120 ? text.slice(0, 120) + '...' : text;\n console.log(`[${this.label}] 📥 ← ${from}: ${preview}`);\n }\n\n this.emit('message', message);\n }\n\n /**\n * Get connection status\n */\n isActive(): boolean {\n return this.isConnected;\n }\n\n /**\n * Dump full conversation transcript (useful for debugging failed tests).\n */\n dumpTranscript(): string {\n const all = [...this.sentMessages, ...this.receivedMessages]\n .sort((a, b) => a.timestamp - b.timestamp);\n return all.map((m) => {\n const arrow = m.direction === 'in' ? '📥 ←' : '📤 →';\n const who = m.direction === 'in' ? m.from : m.to;\n return `${arrow} ${who}: ${m.text}`;\n }).join('\\n');\n }\n}\n"],"mappings":";;;AAkBA,IAAa,eAAb,cAAkC,aAAwC;CACxE,AAAgB,OAAO;CACvB,AAAgB,eAAkC,EAAE;CACpD,AAAgB,mBAAsC,EAAE;CACxD,AAAQ,cAAc;CACtB,AAAQ,eAAkC,EAAE;CAC5C,AAAQ;CACR,AAAQ;CAER,YAAY,SAA+B;AACzC,SAAO;AACP,OAAK,QAAQ,SAAS,SAAS;AAC/B,OAAK,QAAQ,SAAS,SAAS;;CAGjC,MAAM,UAAyB;AAC7B,OAAK,cAAc;AACnB,MAAI,CAAC,KAAK,MAAO,SAAQ,IAAI,IAAI,KAAK,MAAM,aAAa;;CAG3D,MAAM,aAA4B;AAChC,OAAK,cAAc;AACnB,MAAI,CAAC,KAAK,MAAO,SAAQ,IAAI,IAAI,KAAK,MAAM,gBAAgB;;CAG9D,MAAM,YAAY,IAAY,SAAyC;AACrE,MAAI,CAAC,KAAK,YACR,OAAM,IAAI,MAAM,yBAAyB;AAG3C,OAAK,aAAa,KAAK;GAAE,WAAW;GAAO,MAAM;GAAS;GAAI,MAAM,QAAQ;GAAM,WAAW,KAAK,KAAK;GAAE,CAAC;AAE1G,MAAI,CAAC,KAAK,OAAO;GACf,MAAM,UAAU,QAAQ,KAAK,SAAS,MAAM,QAAQ,KAAK,MAAM,GAAG,IAAI,GAAG,QAAQ,QAAQ;AACzF,WAAQ,IAAI,IAAI,KAAK,MAAM,SAAS,GAAG,IAAI,UAAU;;;;;;CAOzD,wBAAwB,MAAc,MAAoB;AACxD,MAAI,CAAC,KAAK,YACR,OAAM,IAAI,MAAM,yBAAyB;EAG3C,MAAM,UAA2B;GAC/B,IAAI,OAAO,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,OAAO,GAAG,EAAE;GAChE;GACA;GACA,WAAW,KAAK,KAAK;GACrB,SAAS;GACT,UAAU,KAAK;GAChB;AAED,OAAK,iBAAiB,KAAK;GAAE,WAAW;GAAM;GAAM;GAAM,WAAW,KAAK,KAAK;GAAE,CAAC;AAElF,MAAI,CAAC,KAAK,OAAO;GACf,MAAM,UAAU,KAAK,SAAS,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,QAAQ;AACjE,WAAQ,IAAI,IAAI,KAAK,MAAM,SAAS,KAAK,IAAI,UAAU;;AAGzD,OAAK,KAAK,WAAW,QAAQ;;;;;CAM/B,WAAoB;AAClB,SAAO,KAAK;;;;;CAMd,iBAAyB;AAGvB,SAFY,CAAC,GAAG,KAAK,cAAc,GAAG,KAAK,iBAAiB,CACzD,MAAM,GAAG,MAAM,EAAE,YAAY,EAAE,UAAU,CACjC,KAAK,MAAM;AAGpB,UAAO,GAFO,EAAE,cAAc,OAAO,SAAS,OAE9B,GADJ,EAAE,cAAc,OAAO,EAAE,OAAO,EAAE,GACvB,IAAI,EAAE;IAC7B,CAAC,KAAK,KAAK"}
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@operor/provider-mock",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Mock provider for Agent OS testing",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"eventemitter3": "^5.0.1",
|
|
10
|
+
"@operor/core": "0.1.0"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"tsdown": "^0.20.3",
|
|
14
|
+
"typescript": "^5.3.3"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsdown",
|
|
18
|
+
"dev": "tsdown --watch"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import EventEmitter from 'eventemitter3';
|
|
2
|
+
import type { MessageProvider, IncomingMessage, OutgoingMessage } from '@operor/core';
|
|
3
|
+
|
|
4
|
+
export interface MockProviderOptions {
|
|
5
|
+
/** Suppress console output. Messages are still captured in sentMessages/receivedMessages. */
|
|
6
|
+
quiet?: boolean;
|
|
7
|
+
/** Label prefix for log lines (e.g. "order-test"). Defaults to "mock". */
|
|
8
|
+
label?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface CapturedMessage {
|
|
12
|
+
direction: 'in' | 'out';
|
|
13
|
+
from: string;
|
|
14
|
+
to?: string;
|
|
15
|
+
text: string;
|
|
16
|
+
timestamp: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class MockProvider extends EventEmitter implements MessageProvider {
|
|
20
|
+
public readonly name = 'mock';
|
|
21
|
+
public readonly sentMessages: CapturedMessage[] = [];
|
|
22
|
+
public readonly receivedMessages: CapturedMessage[] = [];
|
|
23
|
+
private isConnected = false;
|
|
24
|
+
private messageQueue: IncomingMessage[] = [];
|
|
25
|
+
private quiet: boolean;
|
|
26
|
+
private label: string;
|
|
27
|
+
|
|
28
|
+
constructor(options?: MockProviderOptions) {
|
|
29
|
+
super();
|
|
30
|
+
this.quiet = options?.quiet ?? false;
|
|
31
|
+
this.label = options?.label ?? 'mock';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async connect(): Promise<void> {
|
|
35
|
+
this.isConnected = true;
|
|
36
|
+
if (!this.quiet) console.log(`[${this.label}] connected`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async disconnect(): Promise<void> {
|
|
40
|
+
this.isConnected = false;
|
|
41
|
+
if (!this.quiet) console.log(`[${this.label}] disconnected`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async sendMessage(to: string, message: OutgoingMessage): Promise<void> {
|
|
45
|
+
if (!this.isConnected) {
|
|
46
|
+
throw new Error('Provider not connected');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
this.sentMessages.push({ direction: 'out', from: 'agent', to, text: message.text, timestamp: Date.now() });
|
|
50
|
+
|
|
51
|
+
if (!this.quiet) {
|
|
52
|
+
const preview = message.text.length > 120 ? message.text.slice(0, 120) + '...' : message.text;
|
|
53
|
+
console.log(`[${this.label}] 📤 → ${to}: ${preview}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Simulate receiving a message (for testing)
|
|
59
|
+
*/
|
|
60
|
+
simulateIncomingMessage(from: string, text: string): void {
|
|
61
|
+
if (!this.isConnected) {
|
|
62
|
+
throw new Error('Provider not connected');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const message: IncomingMessage = {
|
|
66
|
+
id: `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
67
|
+
from,
|
|
68
|
+
text,
|
|
69
|
+
timestamp: Date.now(),
|
|
70
|
+
channel: 'whatsapp',
|
|
71
|
+
provider: this.name,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
this.receivedMessages.push({ direction: 'in', from, text, timestamp: Date.now() });
|
|
75
|
+
|
|
76
|
+
if (!this.quiet) {
|
|
77
|
+
const preview = text.length > 120 ? text.slice(0, 120) + '...' : text;
|
|
78
|
+
console.log(`[${this.label}] 📥 ← ${from}: ${preview}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.emit('message', message);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get connection status
|
|
86
|
+
*/
|
|
87
|
+
isActive(): boolean {
|
|
88
|
+
return this.isConnected;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Dump full conversation transcript (useful for debugging failed tests).
|
|
93
|
+
*/
|
|
94
|
+
dumpTranscript(): string {
|
|
95
|
+
const all = [...this.sentMessages, ...this.receivedMessages]
|
|
96
|
+
.sort((a, b) => a.timestamp - b.timestamp);
|
|
97
|
+
return all.map((m) => {
|
|
98
|
+
const arrow = m.direction === 'in' ? '📥 ←' : '📤 →';
|
|
99
|
+
const who = m.direction === 'in' ? m.from : m.to;
|
|
100
|
+
return `${arrow} ${who}: ${m.text}`;
|
|
101
|
+
}).join('\n');
|
|
102
|
+
}
|
|
103
|
+
}
|
package/src/index.ts
ADDED