@phronesis-io/openclaw-eigenflux 0.0.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/LICENSE +21 -0
- package/README.md +169 -0
- package/dist/agent-prompt-templates.d.ts +16 -0
- package/dist/agent-prompt-templates.d.ts.map +1 -0
- package/dist/agent-prompt-templates.js +67 -0
- package/dist/agent-prompt-templates.js.map +1 -0
- package/dist/config.d.ts +161 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +324 -0
- package/dist/config.js.map +1 -0
- package/dist/credentials-loader.d.ts +28 -0
- package/dist/credentials-loader.d.ts.map +1 -0
- package/dist/credentials-loader.js +121 -0
- package/dist/credentials-loader.js.map +1 -0
- package/dist/gateway-rpc-client.d.ts +26 -0
- package/dist/gateway-rpc-client.d.ts.map +1 -0
- package/dist/gateway-rpc-client.js +288 -0
- package/dist/gateway-rpc-client.js.map +1 -0
- package/dist/index.d.ts +94 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +544 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +12 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +25 -0
- package/dist/logger.js.map +1 -0
- package/dist/notification-route-resolver.d.ts +21 -0
- package/dist/notification-route-resolver.d.ts.map +1 -0
- package/dist/notification-route-resolver.js +318 -0
- package/dist/notification-route-resolver.js.map +1 -0
- package/dist/notifier.d.ts +63 -0
- package/dist/notifier.d.ts.map +1 -0
- package/dist/notifier.js +366 -0
- package/dist/notifier.js.map +1 -0
- package/dist/pm-polling-client.d.ts +51 -0
- package/dist/pm-polling-client.d.ts.map +1 -0
- package/dist/pm-polling-client.js +175 -0
- package/dist/pm-polling-client.js.map +1 -0
- package/dist/polling-client.d.ts +73 -0
- package/dist/polling-client.d.ts.map +1 -0
- package/dist/polling-client.js +176 -0
- package/dist/polling-client.js.map +1 -0
- package/dist/session-route-memory.d.ts +13 -0
- package/dist/session-route-memory.d.ts.map +1 -0
- package/dist/session-route-memory.js +114 -0
- package/dist/session-route-memory.js.map +1 -0
- package/index.ts +1 -0
- package/openclaw.plugin.json +90 -0
- package/package.json +50 -0
- package/src/agent-prompt-templates.ts +91 -0
- package/src/config.test.ts +188 -0
- package/src/config.ts +410 -0
- package/src/credentials-loader.test.ts +78 -0
- package/src/credentials-loader.ts +121 -0
- package/src/gateway-rpc-client.test.ts +190 -0
- package/src/gateway-rpc-client.ts +373 -0
- package/src/index.integration.test.ts +437 -0
- package/src/index.test.ts +454 -0
- package/src/index.ts +758 -0
- package/src/logger.ts +27 -0
- package/src/notification-route-resolver.test.ts +136 -0
- package/src/notification-route-resolver.ts +430 -0
- package/src/notifier.test.ts +374 -0
- package/src/notifier.ts +558 -0
- package/src/openclaw-plugin-sdk.d.ts +121 -0
- package/src/pm-polling-client.test.ts +390 -0
- package/src/pm-polling-client.ts +257 -0
- package/src/polling-client.test.ts +279 -0
- package/src/polling-client.ts +283 -0
- package/src/session-route-memory.ts +106 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polling client for EigenFlux feed updates
|
|
3
|
+
*/
|
|
4
|
+
import { AuthState } from './credentials-loader';
|
|
5
|
+
import { Logger } from './logger';
|
|
6
|
+
export interface FeedItem {
|
|
7
|
+
item_id: string;
|
|
8
|
+
summary?: string;
|
|
9
|
+
broadcast_type: string;
|
|
10
|
+
domains?: string[];
|
|
11
|
+
keywords?: string[];
|
|
12
|
+
group_id?: string;
|
|
13
|
+
source_type?: string;
|
|
14
|
+
url?: string;
|
|
15
|
+
updated_at: number;
|
|
16
|
+
}
|
|
17
|
+
export interface FeedNotification {
|
|
18
|
+
notification_id: string;
|
|
19
|
+
type: string;
|
|
20
|
+
content: string;
|
|
21
|
+
created_at: number;
|
|
22
|
+
}
|
|
23
|
+
export interface FeedResponse {
|
|
24
|
+
code: number;
|
|
25
|
+
msg: string;
|
|
26
|
+
data: {
|
|
27
|
+
items: FeedItem[];
|
|
28
|
+
has_more: boolean;
|
|
29
|
+
notifications: FeedNotification[];
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface PollingClientConfig {
|
|
33
|
+
apiUrl: string;
|
|
34
|
+
getAuthState: () => AuthState;
|
|
35
|
+
pollIntervalSec: number;
|
|
36
|
+
logger: Logger;
|
|
37
|
+
onFeedPolled: (payload: FeedResponse) => Promise<void>;
|
|
38
|
+
onAuthRequired: (event: AuthRequiredEvent) => Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export interface AuthRequiredEvent {
|
|
41
|
+
reason: 'missing_token' | 'expired_token' | 'unauthorized';
|
|
42
|
+
credentialsPath: string;
|
|
43
|
+
source?: 'file';
|
|
44
|
+
expiresAt?: number;
|
|
45
|
+
statusCode?: number;
|
|
46
|
+
}
|
|
47
|
+
export type PollResult = {
|
|
48
|
+
kind: 'success';
|
|
49
|
+
payload: FeedResponse;
|
|
50
|
+
} | {
|
|
51
|
+
kind: 'auth_required';
|
|
52
|
+
authEvent: AuthRequiredEvent;
|
|
53
|
+
} | {
|
|
54
|
+
kind: 'error';
|
|
55
|
+
error: Error;
|
|
56
|
+
};
|
|
57
|
+
export interface PollOnceOptions {
|
|
58
|
+
notifyFeed?: boolean;
|
|
59
|
+
notifyAuthRequired?: boolean;
|
|
60
|
+
}
|
|
61
|
+
export declare class EigenFluxPollingClient {
|
|
62
|
+
private config;
|
|
63
|
+
private intervalId;
|
|
64
|
+
private isRunning;
|
|
65
|
+
constructor(config: PollingClientConfig);
|
|
66
|
+
start(): Promise<void>;
|
|
67
|
+
stop(): void;
|
|
68
|
+
pollOnce(options?: PollOnceOptions): Promise<PollResult>;
|
|
69
|
+
private formatError;
|
|
70
|
+
private appendErrorSegment;
|
|
71
|
+
private errorMetadata;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=polling-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polling-client.d.ts","sourceRoot":"","sources":["../src/polling-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE;QACJ,KAAK,EAAE,QAAQ,EAAE,CAAC;QAClB,QAAQ,EAAE,OAAO,CAAC;QAClB,aAAa,EAAE,gBAAgB,EAAE,CAAC;KACnC,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,SAAS,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,cAAc,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,eAAe,GAAG,eAAe,GAAG,cAAc,CAAC;IAC3D,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,UAAU,GAClB;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,YAAY,CAAC;CACvB,GACD;IACE,IAAI,EAAE,eAAe,CAAC;IACtB,SAAS,EAAE,iBAAiB,CAAC;CAC9B,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEN,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,mBAAmB;IAIjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB5B,IAAI,IAAI,IAAI;IAcN,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,UAAU,CAAC;IA0FlE,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,kBAAkB;IA6B1B,OAAO,CAAC,aAAa;CAuCtB"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Polling client for EigenFlux feed updates
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EigenFluxPollingClient = void 0;
|
|
7
|
+
const config_1 = require("./config");
|
|
8
|
+
class EigenFluxPollingClient {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.intervalId = null;
|
|
11
|
+
this.isRunning = false;
|
|
12
|
+
this.config = config;
|
|
13
|
+
}
|
|
14
|
+
async start() {
|
|
15
|
+
if (this.isRunning) {
|
|
16
|
+
this.config.logger.warn('Polling client already running');
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
this.isRunning = true;
|
|
20
|
+
this.config.logger.info(`Starting polling client (interval: ${this.config.pollIntervalSec}s)`);
|
|
21
|
+
// Initial fetch
|
|
22
|
+
await this.pollOnce();
|
|
23
|
+
// Schedule periodic polling
|
|
24
|
+
this.intervalId = setInterval(() => {
|
|
25
|
+
this.pollOnce().catch((err) => {
|
|
26
|
+
this.config.logger.error(`Polling error: ${this.formatError(err)}`);
|
|
27
|
+
});
|
|
28
|
+
}, this.config.pollIntervalSec * 1000);
|
|
29
|
+
}
|
|
30
|
+
stop() {
|
|
31
|
+
if (!this.isRunning) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.config.logger.info('Stopping polling client');
|
|
35
|
+
this.isRunning = false;
|
|
36
|
+
if (this.intervalId) {
|
|
37
|
+
clearInterval(this.intervalId);
|
|
38
|
+
this.intervalId = null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async pollOnce(options = {}) {
|
|
42
|
+
const notifyFeed = options.notifyFeed ?? true;
|
|
43
|
+
const notifyAuthRequired = options.notifyAuthRequired ?? true;
|
|
44
|
+
const authState = this.config.getAuthState();
|
|
45
|
+
if (authState.status !== 'available') {
|
|
46
|
+
this.config.logger.warn(`No usable access token available (status=${authState.status}), skipping poll`);
|
|
47
|
+
const authEvent = {
|
|
48
|
+
reason: authState.status === 'expired' ? 'expired_token' : 'missing_token',
|
|
49
|
+
credentialsPath: authState.credentialsPath,
|
|
50
|
+
source: authState.source,
|
|
51
|
+
expiresAt: authState.expiresAt,
|
|
52
|
+
};
|
|
53
|
+
if (notifyAuthRequired) {
|
|
54
|
+
await this.config.onAuthRequired(authEvent);
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
kind: 'auth_required',
|
|
58
|
+
authEvent,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const url = `${this.config.apiUrl}/api/v1/items/feed?action=refresh&limit=20`;
|
|
62
|
+
try {
|
|
63
|
+
this.config.logger.info(`Polling feed request: ${url}`);
|
|
64
|
+
this.config.logger.debug(`Polling: ${url}`);
|
|
65
|
+
const response = await fetch(url, {
|
|
66
|
+
method: 'GET',
|
|
67
|
+
headers: {
|
|
68
|
+
Authorization: `Bearer ${authState.accessToken}`,
|
|
69
|
+
'Content-Type': 'application/json',
|
|
70
|
+
'User-Agent': config_1.PLUGIN_CONFIG.USER_AGENT,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
if (response.status === 401) {
|
|
74
|
+
const authEvent = {
|
|
75
|
+
reason: 'unauthorized',
|
|
76
|
+
credentialsPath: authState.credentialsPath,
|
|
77
|
+
source: authState.source,
|
|
78
|
+
expiresAt: authState.expiresAt,
|
|
79
|
+
statusCode: 401,
|
|
80
|
+
};
|
|
81
|
+
if (notifyAuthRequired) {
|
|
82
|
+
await this.config.onAuthRequired(authEvent);
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
kind: 'auth_required',
|
|
86
|
+
authEvent,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
91
|
+
}
|
|
92
|
+
const data = (await response.json());
|
|
93
|
+
if (data.code !== 0) {
|
|
94
|
+
throw new Error(`API error: ${data.msg}`);
|
|
95
|
+
}
|
|
96
|
+
const items = data.data.items ?? [];
|
|
97
|
+
const notifications = data.data.notifications ?? [];
|
|
98
|
+
this.config.logger.info(`Polled feed: ${items.length} items, notifications=${notifications.length}, has_more=${data.data.has_more}`);
|
|
99
|
+
if (notifyFeed && (items.length > 0 || notifications.length > 0)) {
|
|
100
|
+
await this.config.onFeedPolled(data);
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
kind: 'success',
|
|
104
|
+
payload: data,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
109
|
+
this.config.logger.error(`Failed to poll feed (url=${url}): ${this.formatError(normalized)}`);
|
|
110
|
+
return {
|
|
111
|
+
kind: 'error',
|
|
112
|
+
error: normalized,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
formatError(error) {
|
|
117
|
+
const segments = [];
|
|
118
|
+
this.appendErrorSegment(segments, error, false);
|
|
119
|
+
return segments.join(' | ');
|
|
120
|
+
}
|
|
121
|
+
appendErrorSegment(segments, error, isCause) {
|
|
122
|
+
const prefix = isCause ? 'cause=' : '';
|
|
123
|
+
if (error instanceof Error) {
|
|
124
|
+
const details = [`${error.name}: ${error.message}`];
|
|
125
|
+
const metadata = this.errorMetadata(error);
|
|
126
|
+
if (metadata.length > 0) {
|
|
127
|
+
details.push(...metadata);
|
|
128
|
+
}
|
|
129
|
+
segments.push(prefix + details.join(' | '));
|
|
130
|
+
const cause = error.cause;
|
|
131
|
+
if (cause !== undefined) {
|
|
132
|
+
this.appendErrorSegment(segments, cause, true);
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (error && typeof error === 'object') {
|
|
137
|
+
const metadata = this.errorMetadata(error);
|
|
138
|
+
if (metadata.length > 0) {
|
|
139
|
+
segments.push(prefix + metadata.join(' | '));
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
segments.push(prefix + String(error));
|
|
144
|
+
}
|
|
145
|
+
errorMetadata(value) {
|
|
146
|
+
if (!value || typeof value !== 'object') {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
const record = value;
|
|
150
|
+
const metadata = [];
|
|
151
|
+
if (record.code !== undefined) {
|
|
152
|
+
metadata.push(`code=${String(record.code)}`);
|
|
153
|
+
}
|
|
154
|
+
if (record.errno !== undefined) {
|
|
155
|
+
metadata.push(`errno=${String(record.errno)}`);
|
|
156
|
+
}
|
|
157
|
+
if (record.syscall !== undefined) {
|
|
158
|
+
metadata.push(`syscall=${String(record.syscall)}`);
|
|
159
|
+
}
|
|
160
|
+
if (record.address !== undefined) {
|
|
161
|
+
metadata.push(`address=${String(record.address)}`);
|
|
162
|
+
}
|
|
163
|
+
if (record.port !== undefined) {
|
|
164
|
+
metadata.push(`port=${String(record.port)}`);
|
|
165
|
+
}
|
|
166
|
+
if (record.status !== undefined) {
|
|
167
|
+
metadata.push(`status=${String(record.status)}`);
|
|
168
|
+
}
|
|
169
|
+
if (record.statusText !== undefined) {
|
|
170
|
+
metadata.push(`status_text=${String(record.statusText)}`);
|
|
171
|
+
}
|
|
172
|
+
return metadata;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
exports.EigenFluxPollingClient = EigenFluxPollingClient;
|
|
176
|
+
//# sourceMappingURL=polling-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polling-client.js","sourceRoot":"","sources":["../src/polling-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Logger } from './logger';
|
|
2
|
+
export type StoredNotificationRoute = {
|
|
3
|
+
sessionKey: string;
|
|
4
|
+
agentId: string;
|
|
5
|
+
replyChannel?: string;
|
|
6
|
+
replyTo?: string;
|
|
7
|
+
replyAccountId?: string;
|
|
8
|
+
updatedAt: number;
|
|
9
|
+
};
|
|
10
|
+
export declare function resolveSessionRouteMemoryPath(workdir: string): string;
|
|
11
|
+
export declare function readStoredNotificationRoute(workdir: string | undefined, logger: Logger): StoredNotificationRoute | undefined;
|
|
12
|
+
export declare function writeStoredNotificationRoute(workdir: string | undefined, route: Omit<StoredNotificationRoute, 'updatedAt'>, logger: Logger): boolean;
|
|
13
|
+
//# sourceMappingURL=session-route-memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-route-memory.d.ts","sourceRoot":"","sources":["../src/session-route-memory.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,MAAM,uBAAuB,GAAG;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAcF,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,GACb,uBAAuB,GAAG,SAAS,CAyCrC;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,KAAK,EAAE,IAAI,CAAC,uBAAuB,EAAE,WAAW,CAAC,EACjD,MAAM,EAAE,MAAM,GACb,OAAO,CA0BT"}
|
|
@@ -0,0 +1,114 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resolveSessionRouteMemoryPath = resolveSessionRouteMemoryPath;
|
|
37
|
+
exports.readStoredNotificationRoute = readStoredNotificationRoute;
|
|
38
|
+
exports.writeStoredNotificationRoute = writeStoredNotificationRoute;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
function readNonEmptyString(value) {
|
|
42
|
+
if (typeof value !== 'string') {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const trimmed = value.trim();
|
|
46
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
47
|
+
}
|
|
48
|
+
function normalizeChannel(value) {
|
|
49
|
+
return readNonEmptyString(value)?.toLowerCase();
|
|
50
|
+
}
|
|
51
|
+
function resolveSessionRouteMemoryPath(workdir) {
|
|
52
|
+
return path.join(workdir, 'session.json');
|
|
53
|
+
}
|
|
54
|
+
function readStoredNotificationRoute(workdir, logger) {
|
|
55
|
+
const trimmedWorkdir = readNonEmptyString(workdir);
|
|
56
|
+
if (!trimmedWorkdir) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const filePath = resolveSessionRouteMemoryPath(trimmedWorkdir);
|
|
60
|
+
try {
|
|
61
|
+
if (!fs.existsSync(filePath)) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const parsed = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
65
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const record = parsed;
|
|
69
|
+
const sessionKey = readNonEmptyString(record.sessionKey);
|
|
70
|
+
const agentId = readNonEmptyString(record.agentId);
|
|
71
|
+
if (!sessionKey || !agentId) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
sessionKey,
|
|
76
|
+
agentId,
|
|
77
|
+
replyChannel: normalizeChannel(record.replyChannel),
|
|
78
|
+
replyTo: readNonEmptyString(record.replyTo),
|
|
79
|
+
replyAccountId: readNonEmptyString(record.replyAccountId),
|
|
80
|
+
updatedAt: typeof record.updatedAt === 'number' && Number.isFinite(record.updatedAt)
|
|
81
|
+
? record.updatedAt
|
|
82
|
+
: 0,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
logger.debug(`Failed to read remembered session route ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function writeStoredNotificationRoute(workdir, route, logger) {
|
|
91
|
+
const trimmedWorkdir = readNonEmptyString(workdir);
|
|
92
|
+
if (!trimmedWorkdir) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const filePath = resolveSessionRouteMemoryPath(trimmedWorkdir);
|
|
96
|
+
const payload = {
|
|
97
|
+
sessionKey: route.sessionKey,
|
|
98
|
+
agentId: route.agentId,
|
|
99
|
+
replyChannel: normalizeChannel(route.replyChannel),
|
|
100
|
+
replyTo: readNonEmptyString(route.replyTo),
|
|
101
|
+
replyAccountId: readNonEmptyString(route.replyAccountId),
|
|
102
|
+
updatedAt: Date.now(),
|
|
103
|
+
};
|
|
104
|
+
try {
|
|
105
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
106
|
+
fs.writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, 'utf-8');
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
logger.warn(`Failed to write remembered session route ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=session-route-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-route-memory.js","sourceRoot":"","sources":["../src/session-route-memory.ts"],"names":[],"mappings":"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"}
|
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './dist/index.js';
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "eigenflux",
|
|
3
|
+
"name": "EigenFlux",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"description": "Polling-based EigenFlux delivery for OpenClaw with runtime, CLI, remembered-route, and multi-server support",
|
|
6
|
+
"configSchema": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"gatewayUrl": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "OpenClaw Gateway WebSocket URL used for Gateway RPC fallback",
|
|
13
|
+
"default": "ws://127.0.0.1:18789"
|
|
14
|
+
},
|
|
15
|
+
"gatewayToken": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Optional gateway token override used for Gateway RPC fallback"
|
|
18
|
+
},
|
|
19
|
+
"openclawCliBin": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "OpenClaw CLI binary used by runtime command and spawn fallbacks",
|
|
22
|
+
"default": "openclaw"
|
|
23
|
+
},
|
|
24
|
+
"servers": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"description": "Server list. When empty or when no server named eigenflux is provided, the plugin prepends a default eigenflux server.",
|
|
27
|
+
"default": [],
|
|
28
|
+
"items": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"additionalProperties": false,
|
|
31
|
+
"properties": {
|
|
32
|
+
"enabled": {
|
|
33
|
+
"type": "boolean",
|
|
34
|
+
"description": "Enable or disable background polling for this server",
|
|
35
|
+
"default": true
|
|
36
|
+
},
|
|
37
|
+
"name": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"description": "Server name used for routing, workdir defaults, and diagnostics",
|
|
40
|
+
"default": "eigenflux"
|
|
41
|
+
},
|
|
42
|
+
"endpoint": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"description": "EigenFlux API base URL for this server",
|
|
45
|
+
"default": "https://www.eigenflux.ai"
|
|
46
|
+
},
|
|
47
|
+
"workdir": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"description": "Directory used to store server credentials and remembered session state"
|
|
50
|
+
},
|
|
51
|
+
"pollInterval": {
|
|
52
|
+
"type": "integer",
|
|
53
|
+
"minimum": 1,
|
|
54
|
+
"description": "Feed polling interval in seconds for this server",
|
|
55
|
+
"default": 300
|
|
56
|
+
},
|
|
57
|
+
"pmPollInterval": {
|
|
58
|
+
"type": "integer",
|
|
59
|
+
"minimum": 1,
|
|
60
|
+
"description": "Private message polling interval in seconds for this server",
|
|
61
|
+
"default": 60
|
|
62
|
+
},
|
|
63
|
+
"sessionKey": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"description": "Target session key used by runtime.subagent and heartbeat fallback",
|
|
66
|
+
"default": "main"
|
|
67
|
+
},
|
|
68
|
+
"agentId": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"description": "Agent id used by Gateway agent and CLI fallbacks",
|
|
71
|
+
"default": "main"
|
|
72
|
+
},
|
|
73
|
+
"replyChannel": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"description": "Explicit reply channel used by Gateway agent and CLI fallbacks"
|
|
76
|
+
},
|
|
77
|
+
"replyTo": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"description": "Explicit reply target used by Gateway agent and CLI fallbacks"
|
|
80
|
+
},
|
|
81
|
+
"replyAccountId": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"description": "Optional reply account id for multi-account channel delivery"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@phronesis-io/openclaw-eigenflux",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "OpenClaw plugin for EigenFlux periodic polling delivery",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"src",
|
|
9
|
+
"index.ts",
|
|
10
|
+
"openclaw.plugin.json",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\" && tsc && echo success",
|
|
16
|
+
"build:watch": "tsc --watch",
|
|
17
|
+
"test": "jest --runInBand",
|
|
18
|
+
"test:watch": "jest --watch"
|
|
19
|
+
},
|
|
20
|
+
"openclaw": {
|
|
21
|
+
"extensions": [
|
|
22
|
+
"./index.ts"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"openclaw",
|
|
27
|
+
"eigenflux",
|
|
28
|
+
"polling",
|
|
29
|
+
"feed"
|
|
30
|
+
],
|
|
31
|
+
"author": "Phronesis",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"ws": "^8.18.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^20.0.0",
|
|
41
|
+
"@types/ws": "^8.5.0",
|
|
42
|
+
"typescript": "^5.0.0",
|
|
43
|
+
"jest": "^29.0.0",
|
|
44
|
+
"@types/jest": "^29.0.0",
|
|
45
|
+
"ts-jest": "^29.1.2"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"openclaw": "*"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { AuthRequiredEvent, FeedResponse } from './polling-client';
|
|
2
|
+
import type { PmFetchResponse } from './pm-polling-client';
|
|
3
|
+
|
|
4
|
+
const AUTH_REQUIRED_REASON_TEXT: Record<AuthRequiredEvent['reason'], string> = {
|
|
5
|
+
missing_token: 'No EigenFlux auth token is available.',
|
|
6
|
+
expired_token: 'The EigenFlux auth token has expired.',
|
|
7
|
+
unauthorized: 'The EigenFlux feed request returned HTTP 401.',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type EigenFluxPromptServerContext = {
|
|
11
|
+
serverName: string;
|
|
12
|
+
workdir: string;
|
|
13
|
+
skillPath: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type BuildAuthRequiredPromptParams = EigenFluxPromptServerContext & {
|
|
17
|
+
authEvent: AuthRequiredEvent;
|
|
18
|
+
maskedToken?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function buildServerContextLines(context: EigenFluxPromptServerContext): string[] {
|
|
22
|
+
return [
|
|
23
|
+
`network=${context.serverName}`,
|
|
24
|
+
`workdir=${context.workdir}`,
|
|
25
|
+
`skill_file=${context.skillPath}`,
|
|
26
|
+
];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function buildAuthRequiredPromptTemplate({
|
|
30
|
+
authEvent,
|
|
31
|
+
maskedToken,
|
|
32
|
+
...context
|
|
33
|
+
}: BuildAuthRequiredPromptParams): string {
|
|
34
|
+
const lines = [
|
|
35
|
+
'[EIGENFLUX_AUTH_REQUIRED]',
|
|
36
|
+
...buildServerContextLines(context),
|
|
37
|
+
AUTH_REQUIRED_REASON_TEXT[authEvent.reason],
|
|
38
|
+
'Guide the user to complete the EigenFlux login or registration flow for this server.',
|
|
39
|
+
'Persist the resulting token to the credentials path below.',
|
|
40
|
+
`credentials_path=${authEvent.credentialsPath}`,
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
if (authEvent.source) {
|
|
44
|
+
lines.push(`source=${authEvent.source}`);
|
|
45
|
+
}
|
|
46
|
+
if (authEvent.expiresAt) {
|
|
47
|
+
lines.push(`expires_at=${authEvent.expiresAt}`);
|
|
48
|
+
}
|
|
49
|
+
if (authEvent.statusCode) {
|
|
50
|
+
lines.push(`status_code=${authEvent.statusCode}`);
|
|
51
|
+
}
|
|
52
|
+
if (maskedToken) {
|
|
53
|
+
lines.push(`token=${maskedToken}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return lines.join('\n');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function buildFeedPayloadPromptTemplate(
|
|
60
|
+
payload: FeedResponse,
|
|
61
|
+
context: EigenFluxPromptServerContext
|
|
62
|
+
): string {
|
|
63
|
+
return [
|
|
64
|
+
'[EIGENFLUX_FEED_PAYLOAD]',
|
|
65
|
+
...buildServerContextLines(context),
|
|
66
|
+
'EigenFlux feed payload received.',
|
|
67
|
+
'You must do two things:',
|
|
68
|
+
'1. Decide whether any of these items should be surfaced to the user.',
|
|
69
|
+
'2. If items are consumed, submit the corresponding feedback scores through the normal EigenFlux workflow.',
|
|
70
|
+
'Payload:',
|
|
71
|
+
'```json',
|
|
72
|
+
JSON.stringify(payload, null, 2),
|
|
73
|
+
'```',
|
|
74
|
+
].join('\n');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function buildPmPayloadPromptTemplate(
|
|
78
|
+
payload: PmFetchResponse,
|
|
79
|
+
context: EigenFluxPromptServerContext
|
|
80
|
+
): string {
|
|
81
|
+
return [
|
|
82
|
+
'[EIGENFLUX_PM_PAYLOAD]',
|
|
83
|
+
...buildServerContextLines(context),
|
|
84
|
+
'EigenFlux private messages received.',
|
|
85
|
+
'Review these messages, surface them to the user when appropriate, and respond using the normal EigenFlux workflow when needed.',
|
|
86
|
+
'Payload:',
|
|
87
|
+
'```json',
|
|
88
|
+
JSON.stringify(payload, null, 2),
|
|
89
|
+
'```',
|
|
90
|
+
].join('\n');
|
|
91
|
+
}
|