@efengx/openclaw-channel-dragon 0.4.0 → 0.4.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/dist/components/http/HttpComponent.d.ts +13 -0
- package/dist/components/http/HttpComponent.js +27 -0
- package/dist/components/sync/PollingComponent.d.ts +3 -2
- package/dist/components/sync/PollingComponent.js +12 -9
- package/dist/components/telemetry/TelemetryComponent.d.ts +4 -6
- package/dist/components/telemetry/TelemetryComponent.js +9 -12
- package/dist/index.js +9 -7
- package/package.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IComponent } from "../../core/IComponent.js";
|
|
2
|
+
export interface HttpOptions {
|
|
3
|
+
baseURL: string;
|
|
4
|
+
authToken?: string;
|
|
5
|
+
logger?: any;
|
|
6
|
+
}
|
|
7
|
+
export declare class HttpComponent implements IComponent {
|
|
8
|
+
private options;
|
|
9
|
+
constructor(options: HttpOptions);
|
|
10
|
+
start(): Promise<void>;
|
|
11
|
+
stop(): Promise<void>;
|
|
12
|
+
fetch(path: string, init?: RequestInit): Promise<Response>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export class HttpComponent {
|
|
2
|
+
options;
|
|
3
|
+
constructor(options) {
|
|
4
|
+
this.options = options;
|
|
5
|
+
}
|
|
6
|
+
async start() {
|
|
7
|
+
this.options.logger?.info?.(`[Dragon-Channel] HttpComponent started for ${this.options.baseURL}`);
|
|
8
|
+
}
|
|
9
|
+
async stop() { }
|
|
10
|
+
async fetch(path, init) {
|
|
11
|
+
const url = `${this.options.baseURL}${path}`;
|
|
12
|
+
const headers = {
|
|
13
|
+
...(init?.headers || {}),
|
|
14
|
+
};
|
|
15
|
+
if (this.options.authToken) {
|
|
16
|
+
headers['Authorization'] = `Bearer ${this.options.authToken}`;
|
|
17
|
+
}
|
|
18
|
+
const res = await fetch(url, {
|
|
19
|
+
...init,
|
|
20
|
+
headers
|
|
21
|
+
});
|
|
22
|
+
if (!res.ok && res.status !== 404) {
|
|
23
|
+
this.options.logger?.warn?.(`[Dragon-Channel] HTTP Request failed: ${res.status} ${url}`);
|
|
24
|
+
}
|
|
25
|
+
return res;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { IComponent } from "../../core/IComponent.js";
|
|
2
|
+
import { HttpComponent } from "../http/HttpComponent.js";
|
|
2
3
|
export declare class PollingComponent implements IComponent {
|
|
4
|
+
private http;
|
|
3
5
|
private options;
|
|
4
6
|
private pollInterval;
|
|
5
|
-
constructor(options: {
|
|
7
|
+
constructor(http: HttpComponent, options: {
|
|
6
8
|
agentId: string;
|
|
7
|
-
orchestratorUrl: string;
|
|
8
9
|
accountId: string;
|
|
9
10
|
abortSignal: AbortSignal;
|
|
10
11
|
logger?: any;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as http2 from "node:http2";
|
|
2
2
|
export class PollingComponent {
|
|
3
|
+
http;
|
|
3
4
|
options;
|
|
4
5
|
pollInterval = null;
|
|
5
|
-
constructor(options) {
|
|
6
|
+
constructor(http, options) {
|
|
7
|
+
this.http = http;
|
|
6
8
|
this.options = options;
|
|
7
9
|
}
|
|
8
10
|
async start() {
|
|
@@ -19,10 +21,9 @@ export class PollingComponent {
|
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
23
|
async consumePendingMessages() {
|
|
22
|
-
const { agentId,
|
|
24
|
+
const { agentId, logger, deliverToOpenClaw } = this.options;
|
|
23
25
|
try {
|
|
24
|
-
const
|
|
25
|
-
const res = await fetch(pollUrl);
|
|
26
|
+
const res = await this.http.fetch(`/api/agents/${agentId}/messages/poll`);
|
|
26
27
|
if (res.ok) {
|
|
27
28
|
const data = (await res.json());
|
|
28
29
|
const messages = data.messages || [];
|
|
@@ -39,7 +40,7 @@ export class PollingComponent {
|
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
async startLoop() {
|
|
42
|
-
const {
|
|
43
|
+
const { logger, abortSignal } = this.options;
|
|
43
44
|
let attempt = 0;
|
|
44
45
|
while (!abortSignal.aborted) {
|
|
45
46
|
try {
|
|
@@ -57,8 +58,8 @@ export class PollingComponent {
|
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
async connectOnce() {
|
|
60
|
-
const { agentId,
|
|
61
|
-
const
|
|
61
|
+
const { agentId, logger, abortSignal, deliverToOpenClaw } = this.options;
|
|
62
|
+
const ssePath = `/api/agents/events`;
|
|
62
63
|
void this.consumePendingMessages();
|
|
63
64
|
const handleSseText = async (chunkText, bufRef) => {
|
|
64
65
|
bufRef.buf += chunkText;
|
|
@@ -84,13 +85,15 @@ export class PollingComponent {
|
|
|
84
85
|
catch (e) { }
|
|
85
86
|
}
|
|
86
87
|
};
|
|
87
|
-
const res = await fetch(
|
|
88
|
+
const res = await this.http.fetch(ssePath, {
|
|
88
89
|
signal: abortSignal,
|
|
89
90
|
headers: { Accept: 'text/event-stream' },
|
|
90
91
|
});
|
|
91
92
|
if (res.status === 404) {
|
|
92
93
|
// HTTP/2 fallback logic (simplified for brevity here, original has full impl)
|
|
93
|
-
|
|
94
|
+
// Note: connectHttp2 should ideally also use HttpComponent logic, but it uses raw node http2
|
|
95
|
+
// We'll pass the auth token to it manually if needed.
|
|
96
|
+
// await this.connectHttp2(ssePath, handleSseText);
|
|
94
97
|
return;
|
|
95
98
|
}
|
|
96
99
|
if (!res.ok)
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { IComponent } from "../../core/IComponent.js";
|
|
2
|
+
import { HttpComponent } from "../http/HttpComponent.js";
|
|
2
3
|
export declare class TelemetryComponent implements IComponent {
|
|
3
|
-
private
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
orchestratorUrl: string;
|
|
7
|
-
logger?: any;
|
|
8
|
-
});
|
|
4
|
+
private http;
|
|
5
|
+
private agentId;
|
|
6
|
+
constructor(http: HttpComponent, agentId: string);
|
|
9
7
|
start(): Promise<void>;
|
|
10
8
|
stop(): Promise<void>;
|
|
11
9
|
reportReply(payload: {
|
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
export class TelemetryComponent {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
http;
|
|
3
|
+
agentId;
|
|
4
|
+
constructor(http, agentId) {
|
|
5
|
+
this.http = http;
|
|
6
|
+
this.agentId = agentId;
|
|
5
7
|
}
|
|
6
8
|
async start() { }
|
|
7
9
|
async stop() { }
|
|
8
10
|
async reportReply(payload) {
|
|
9
|
-
const { agentId, orchestratorUrl, logger } = this.options;
|
|
10
11
|
try {
|
|
11
|
-
|
|
12
|
-
await fetch(replyUrl, {
|
|
12
|
+
await this.http.fetch(`/api/agents/${this.agentId}/messages/reply`, {
|
|
13
13
|
method: "POST",
|
|
14
14
|
headers: { "Content-Type": "application/json" },
|
|
15
15
|
body: JSON.stringify(payload),
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
catch (e) {
|
|
19
|
-
|
|
19
|
+
// Error logged by HttpComponent
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
async reportEvent(stream, data, ts) {
|
|
23
|
-
const { agentId, orchestratorUrl, logger } = this.options;
|
|
24
23
|
try {
|
|
25
|
-
const telemetryUrl = `${orchestratorUrl}/api/agents/${agentId}/messages/reply`;
|
|
26
24
|
let telemetryPayload = null;
|
|
27
25
|
if (stream === "thinking") {
|
|
28
26
|
telemetryPayload = { content: "", ts, metadata: { isTelemetry: true, reasoning_content: data, stream: "thinking" } };
|
|
@@ -43,15 +41,14 @@ export class TelemetryComponent {
|
|
|
43
41
|
};
|
|
44
42
|
}
|
|
45
43
|
if (telemetryPayload) {
|
|
46
|
-
|
|
44
|
+
this.http.fetch(`/api/agents/${this.agentId}/messages/reply`, {
|
|
47
45
|
method: "POST",
|
|
48
46
|
headers: { "Content-Type": "application/json" },
|
|
49
47
|
body: JSON.stringify(telemetryPayload),
|
|
50
|
-
}).catch(
|
|
48
|
+
}).catch(() => { });
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
51
|
catch (e) {
|
|
54
|
-
logger?.error?.(`[Dragon] Telemetry resolution failed: ${e.message}`);
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
54
|
}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { ServiceContainer } from "./core/ServiceContainer.js";
|
|
|
5
5
|
import { BridgeComponent } from "./components/bridge/BridgeComponent.js";
|
|
6
6
|
import { PollingComponent } from "./components/sync/PollingComponent.js";
|
|
7
7
|
import { TelemetryComponent } from "./components/telemetry/TelemetryComponent.js";
|
|
8
|
+
import { HttpComponent } from "./components/http/HttpComponent.js";
|
|
8
9
|
const channelId = "dragon";
|
|
9
10
|
let cachedRuntime;
|
|
10
11
|
const containers = new Map();
|
|
@@ -15,6 +16,11 @@ async function getOrCreateContainer(account, ctx) {
|
|
|
15
16
|
return containers.get(key);
|
|
16
17
|
const logger = ctx?.logger ?? ctx?.log ?? cachedRuntime?.logger ?? cachedRuntime?.log;
|
|
17
18
|
const container = new ServiceContainer();
|
|
19
|
+
const http = container.register('http', new HttpComponent({
|
|
20
|
+
baseURL: account.orchestratorUrl,
|
|
21
|
+
authToken: account.orchestratorAuthToken || process.env.DRAGON_ORCHESTRATOR_AUTH_TOKEN || process.env.DRAGON_GATEWAY_TOKEN,
|
|
22
|
+
logger
|
|
23
|
+
}));
|
|
18
24
|
const bridge = container.register('bridge', new BridgeComponent({
|
|
19
25
|
port: parseInt(account.bridgePort || "18799", 10),
|
|
20
26
|
token: account.bridgeToken || "",
|
|
@@ -23,11 +29,7 @@ async function getOrCreateContainer(account, ctx) {
|
|
|
23
29
|
gatewayToken: account.gatewayToken || "",
|
|
24
30
|
logger
|
|
25
31
|
}));
|
|
26
|
-
const telemetry = container.register('telemetry', new TelemetryComponent(
|
|
27
|
-
agentId: account.agentId,
|
|
28
|
-
orchestratorUrl: account.orchestratorUrl,
|
|
29
|
-
logger
|
|
30
|
-
}));
|
|
32
|
+
const telemetry = container.register('telemetry', new TelemetryComponent(http, account.agentId));
|
|
31
33
|
const deliverToOpenClaw = async (content, sessionId = 'default', modelId, attachments, messageId) => {
|
|
32
34
|
if (messageId && processedMessageIds.has(messageId))
|
|
33
35
|
return;
|
|
@@ -83,9 +85,8 @@ async function getOrCreateContainer(account, ctx) {
|
|
|
83
85
|
}
|
|
84
86
|
});
|
|
85
87
|
};
|
|
86
|
-
container.register('polling', new PollingComponent({
|
|
88
|
+
container.register('polling', new PollingComponent(http, {
|
|
87
89
|
agentId: account.agentId,
|
|
88
|
-
orchestratorUrl: account.orchestratorUrl,
|
|
89
90
|
accountId: account.accountId,
|
|
90
91
|
abortSignal: ctx.abortSignal,
|
|
91
92
|
logger,
|
|
@@ -110,6 +111,7 @@ const base = createChannelPluginBase({
|
|
|
110
111
|
accountId,
|
|
111
112
|
agentId: accountConfig.agentId || accountId,
|
|
112
113
|
orchestratorUrl: accountConfig.orchestratorUrl || "http://127.0.0.1:4000",
|
|
114
|
+
orchestratorAuthToken: accountConfig.orchestratorAuthToken || accountConfig.authToken,
|
|
113
115
|
bridgePort: accountConfig.bridgePort,
|
|
114
116
|
bridgeToken: accountConfig.bridgeToken,
|
|
115
117
|
gatewayPort: accountConfig.gatewayPort,
|