clawaxis 1.0.3 → 1.2.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/index.ts +8 -15
- package/openclaw.plugin.json +10 -10
- package/package.json +3 -4
- package/src/channel.ts +14 -30
- package/src/config.ts +32 -23
- package/src/governance/hooks.ts +2 -2
- package/src/message-handler.ts +26 -56
- package/src/runtime.ts +9 -38
- package/src/socket.ts +271 -0
- package/src/sync/documents.ts +35 -24
- package/src/sync/routines.ts +5 -9
- package/src/tools/content.ts +14 -19
- package/src/tools/helpers.ts +5 -17
- package/src/tools/index.ts +2 -5
- package/src/tools/memory.ts +15 -45
- package/src/tools/routines.ts +5 -13
- package/src/tools/sync.ts +5 -11
- package/src/types.ts +2 -2
- package/src/utils.ts +24 -97
- package/src/tools/media.ts +0 -21
- package/src/websocket.ts +0 -294
package/index.ts
CHANGED
|
@@ -1,32 +1,25 @@
|
|
|
1
1
|
import { LOG_PREFIX, PLUGIN_VERSION, loadConfig } from "./src/config.js";
|
|
2
2
|
import { setRuntime } from "./src/runtime.js";
|
|
3
|
-
import { setUtilsConfig } from "./src/utils.js";
|
|
4
3
|
import { clawaxisChannel } from "./src/channel.js";
|
|
5
4
|
import { registerGovernanceHooks } from "./src/governance/hooks.js";
|
|
6
5
|
import { registerTools } from "./src/tools/index.js";
|
|
7
6
|
|
|
8
7
|
function register(api: any) {
|
|
9
8
|
console.log(`${LOG_PREFIX} ==========================================`);
|
|
10
|
-
console.log(`${LOG_PREFIX}
|
|
9
|
+
console.log(`${LOG_PREFIX} ClawAxis Plugin v${PLUGIN_VERSION} (Unix Socket)`);
|
|
11
10
|
console.log(`${LOG_PREFIX} ==========================================`);
|
|
12
11
|
|
|
13
12
|
setRuntime(api.runtime);
|
|
14
13
|
|
|
15
14
|
const config = loadConfig(api.config);
|
|
16
|
-
if (!config) {
|
|
17
|
-
console.warn(`${LOG_PREFIX} No channels.clawaxis config found (or missing relayUrl/agentToken). Plugin disabled.`);
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
setUtilsConfig(config);
|
|
22
15
|
|
|
23
|
-
console.log(`${LOG_PREFIX}
|
|
24
|
-
if (config.
|
|
25
|
-
|
|
16
|
+
if (config.mediaDomain) console.log(`${LOG_PREFIX} Media domain: ${config.mediaDomain}`);
|
|
17
|
+
if (config.agentName) console.log(`${LOG_PREFIX} Agent name: ${config.agentName}`);
|
|
18
|
+
console.log(`${LOG_PREFIX} Socket: ${config.socketPath}`);
|
|
26
19
|
|
|
27
20
|
if (typeof api.registerChannel === "function") {
|
|
28
21
|
api.registerChannel({ plugin: clawaxisChannel });
|
|
29
|
-
console.log(`${LOG_PREFIX}
|
|
22
|
+
console.log(`${LOG_PREFIX} Channel 'clawaxis' registered (socket starts via gateway.startAccount)`);
|
|
30
23
|
} else {
|
|
31
24
|
console.warn(`${LOG_PREFIX} api.registerChannel not available — channel not registered`);
|
|
32
25
|
}
|
|
@@ -34,14 +27,14 @@ function register(api: any) {
|
|
|
34
27
|
registerGovernanceHooks(api, config);
|
|
35
28
|
|
|
36
29
|
if (typeof api.registerTool === "function") {
|
|
37
|
-
registerTools(api
|
|
38
|
-
console.log(`${LOG_PREFIX}
|
|
30
|
+
registerTools(api);
|
|
31
|
+
console.log(`${LOG_PREFIX} All 9 tools registered`);
|
|
39
32
|
} else {
|
|
40
33
|
console.warn(`${LOG_PREFIX} api.registerTool not available — tools not registered`);
|
|
41
34
|
}
|
|
42
35
|
|
|
43
36
|
console.log(`${LOG_PREFIX} ==========================================`);
|
|
44
|
-
console.log(`${LOG_PREFIX}
|
|
37
|
+
console.log(`${LOG_PREFIX} ClawAxis plugin loaded`);
|
|
45
38
|
console.log(`${LOG_PREFIX} ==========================================`);
|
|
46
39
|
}
|
|
47
40
|
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "clawaxis",
|
|
3
3
|
"name": "ClawAxis",
|
|
4
|
-
"version": "1.0
|
|
5
|
-
"description": "Real-time bridge between OpenClaw agents and the ClawAxis iOS app. Channel plugin with governance, content management, and document/routine sync.",
|
|
4
|
+
"version": "2.1.0",
|
|
5
|
+
"description": "Real-time bridge between OpenClaw agents and the ClawAxis iOS app via the Connect daemon. Channel plugin with governance, content management, and document/routine sync.",
|
|
6
6
|
"channels": ["clawaxis"],
|
|
7
7
|
"configSchema": {
|
|
8
8
|
"type": "object",
|
|
9
9
|
"additionalProperties": false,
|
|
10
10
|
"properties": {
|
|
11
|
-
"
|
|
11
|
+
"socketPath": {
|
|
12
12
|
"type": "string",
|
|
13
|
-
"description": "
|
|
14
|
-
"default": "
|
|
13
|
+
"description": "Path to the Connect Unix socket",
|
|
14
|
+
"default": "~/.clawaxis/connect.sock"
|
|
15
15
|
},
|
|
16
|
-
"
|
|
16
|
+
"tokenPath": {
|
|
17
17
|
"type": "string",
|
|
18
|
-
"description": "
|
|
19
|
-
"default": "
|
|
18
|
+
"description": "Path to the local auth token file",
|
|
19
|
+
"default": "~/.clawaxis/local-token"
|
|
20
20
|
},
|
|
21
21
|
"mediaDomain": {
|
|
22
22
|
"type": "string",
|
|
@@ -80,8 +80,8 @@
|
|
|
80
80
|
"required": []
|
|
81
81
|
},
|
|
82
82
|
"uiHints": {
|
|
83
|
-
"
|
|
84
|
-
"
|
|
83
|
+
"socketPath": { "label": "Socket Path", "placeholder": "~/.clawaxis/connect.sock" },
|
|
84
|
+
"tokenPath": { "label": "Token Path", "placeholder": "~/.clawaxis/local-token" },
|
|
85
85
|
"mediaDomain": { "label": "Media Domain", "placeholder": "pub-xxxxx.r2.dev" },
|
|
86
86
|
"agentName": { "label": "Agent Name" }
|
|
87
87
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawaxis",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"files": [
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"openclaw",
|
|
14
14
|
"openclaw-plugin",
|
|
15
15
|
"clawaxis",
|
|
16
|
-
"
|
|
16
|
+
"unix-socket",
|
|
17
17
|
"mobile",
|
|
18
18
|
"channel"
|
|
19
19
|
],
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@sinclair/typebox": "^0.34.48"
|
|
33
|
-
"ws": "^8.19.0"
|
|
32
|
+
"@sinclair/typebox": "^0.34.48"
|
|
34
33
|
}
|
|
35
34
|
}
|
package/src/channel.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LOG_PREFIX, loadConfig } from "./config.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { relaySend } from "./socket.js";
|
|
3
|
+
import { createSocketService } from "./socket.js";
|
|
4
4
|
|
|
5
5
|
export const clawaxisChannel = {
|
|
6
6
|
id: "clawaxis",
|
|
@@ -26,52 +26,36 @@ export const clawaxisChannel = {
|
|
|
26
26
|
deliveryMode: "direct",
|
|
27
27
|
sendText: async () => ({ ok: true }),
|
|
28
28
|
sendMedia: async (ctx: any) => {
|
|
29
|
-
const
|
|
29
|
+
const sent = relaySend({
|
|
30
|
+
type: "message",
|
|
30
31
|
content: ctx.caption || "[media]",
|
|
31
32
|
message_type: "image",
|
|
32
33
|
});
|
|
33
|
-
return { ok:
|
|
34
|
+
return { ok: sent };
|
|
34
35
|
},
|
|
35
36
|
},
|
|
36
37
|
|
|
37
38
|
gateway: {
|
|
38
|
-
/**
|
|
39
|
-
* OpenClaw calls startAccount when the channel activates.
|
|
40
|
-
* This is the correct lifecycle hook for channel plugins —
|
|
41
|
-
* it replaces manual api.registerService() + wsService.start().
|
|
42
|
-
*
|
|
43
|
-
* ctx.account.config is pre-scoped to the channel config
|
|
44
|
-
* (relayUrl/agentToken already at top level).
|
|
45
|
-
*
|
|
46
|
-
* Returns a cleanup function that OpenClaw calls on shutdown.
|
|
47
|
-
*/
|
|
48
39
|
startAccount: async (ctx: any) => {
|
|
49
40
|
const accountId = ctx.account?.accountId || "default";
|
|
50
41
|
console.log(`${LOG_PREFIX} gateway.startAccount called for account: ${accountId}`);
|
|
51
42
|
|
|
52
|
-
const accountConfig = ctx.account?.config || ctx.config;
|
|
43
|
+
const accountConfig = ctx.account?.config || ctx.account || ctx.config;
|
|
53
44
|
const config = loadConfig(accountConfig);
|
|
54
45
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
46
|
+
console.log(`${LOG_PREFIX} Config loaded for account ${accountId}`);
|
|
47
|
+
if (config.mediaDomain) console.log(`${LOG_PREFIX} Media domain: ${config.mediaDomain}`);
|
|
48
|
+
if (config.agentName) console.log(`${LOG_PREFIX} Agent name: ${config.agentName}`);
|
|
59
49
|
|
|
60
|
-
|
|
50
|
+
const socketService = createSocketService(config);
|
|
51
|
+
await socketService.start();
|
|
61
52
|
|
|
62
|
-
console.log(`${LOG_PREFIX}
|
|
63
|
-
if (config.mediaDomain) console.log(`${LOG_PREFIX} \u2022 Media domain: ${config.mediaDomain}`);
|
|
64
|
-
if (config.agentName) console.log(`${LOG_PREFIX} \u2022 Agent name: ${config.agentName}`);
|
|
65
|
-
|
|
66
|
-
const wsService = createWebSocketService(config);
|
|
67
|
-
await wsService.start();
|
|
68
|
-
|
|
69
|
-
console.log(`${LOG_PREFIX} \u2713 Account ${accountId} started (WebSocket active)`);
|
|
53
|
+
console.log(`${LOG_PREFIX} Account ${accountId} started (socket active)`);
|
|
70
54
|
|
|
71
55
|
return async () => {
|
|
72
56
|
console.log(`${LOG_PREFIX} Stopping account ${accountId}...`);
|
|
73
|
-
await
|
|
74
|
-
console.log(`${LOG_PREFIX}
|
|
57
|
+
await socketService.stop();
|
|
58
|
+
console.log(`${LOG_PREFIX} Account ${accountId} stopped`);
|
|
75
59
|
};
|
|
76
60
|
},
|
|
77
61
|
},
|
package/src/config.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { homedir } from "node:os";
|
|
1
3
|
import type { GovernanceConfig, ClawAxisConfig } from "./types.js";
|
|
2
4
|
|
|
3
|
-
export const HEARTBEAT_MS = 60000;
|
|
4
|
-
export const PING_MS = 30000;
|
|
5
|
-
export const REAUTH_BUFFER_MS = 5000;
|
|
6
|
-
export const MAX_RECONNECT_DELAY = 60000;
|
|
7
5
|
export const LOG_PREFIX = "\u{1F99E}";
|
|
8
|
-
export const PLUGIN_VERSION = "2.
|
|
6
|
+
export const PLUGIN_VERSION = "2.1.0";
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
export const
|
|
8
|
+
export const DEFAULT_SOCKET_PATH = path.join(homedir(), ".clawaxis", "connect.sock");
|
|
9
|
+
export const DEFAULT_TOKEN_PATH = path.join(homedir(), ".clawaxis", "local-token");
|
|
12
10
|
|
|
13
11
|
export const DEFAULT_GOVERNANCE: GovernanceConfig = {
|
|
14
12
|
imageTools: [],
|
|
@@ -44,25 +42,36 @@ export const DEFAULT_GOVERNANCE: GovernanceConfig = {
|
|
|
44
42
|
/**
|
|
45
43
|
* Load and merge config from OpenClaw's config hierarchy.
|
|
46
44
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
45
|
+
* With the Unix socket transport, no secrets are required in plugin config.
|
|
46
|
+
* Auth is handled via the local token file generated by Connect.
|
|
47
|
+
*
|
|
48
|
+
* Config sources (in priority order):
|
|
49
|
+
* 1. Pre-scoped config (from gateway.startAccount)
|
|
50
|
+
* 2. channels.clawaxis (flat)
|
|
51
|
+
* 3. channels.clawaxis.accounts.default
|
|
52
|
+
* 4. plugins.entries.clawaxis-plugin.config
|
|
53
|
+
* 5. plugins.entries.clawaxis.config
|
|
52
54
|
*/
|
|
53
|
-
export function loadConfig(apiConfig: any): ClawAxisConfig
|
|
54
|
-
let cfg: any;
|
|
55
|
+
export function loadConfig(apiConfig: any): ClawAxisConfig {
|
|
56
|
+
let cfg: any = {};
|
|
55
57
|
|
|
56
|
-
if (apiConfig?.
|
|
58
|
+
if (apiConfig?.socketPath || apiConfig?.governance) {
|
|
57
59
|
cfg = apiConfig;
|
|
58
60
|
} else {
|
|
59
|
-
|
|
60
|
-
?? apiConfig?.plugins?.entries?.["clawaxis-plugin"]?.config
|
|
61
|
-
?? apiConfig?.plugins?.entries?.["clawaxis"]?.config;
|
|
62
|
-
}
|
|
61
|
+
const channelConfig = apiConfig?.channels?.clawaxis;
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
if (channelConfig && typeof channelConfig === "object") {
|
|
64
|
+
if (channelConfig.accounts?.default) {
|
|
65
|
+
cfg = channelConfig.accounts.default;
|
|
66
|
+
} else {
|
|
67
|
+
cfg = channelConfig;
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
cfg = apiConfig?.plugins?.entries?.["clawaxis-plugin"]?.config
|
|
71
|
+
?? apiConfig?.plugins?.entries?.["clawaxis"]?.config
|
|
72
|
+
?? {};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
66
75
|
|
|
67
76
|
const governance: GovernanceConfig = {
|
|
68
77
|
imageTools: cfg.governance?.imageTools || DEFAULT_GOVERNANCE.imageTools,
|
|
@@ -74,8 +83,8 @@ export function loadConfig(apiConfig: any): ClawAxisConfig | null {
|
|
|
74
83
|
};
|
|
75
84
|
|
|
76
85
|
return {
|
|
77
|
-
|
|
78
|
-
|
|
86
|
+
socketPath: cfg.socketPath || DEFAULT_SOCKET_PATH,
|
|
87
|
+
tokenPath: cfg.tokenPath || DEFAULT_TOKEN_PATH,
|
|
79
88
|
mediaDomain: cfg.mediaDomain || null,
|
|
80
89
|
agentName: apiConfig?.agents?.defaults?.name || cfg.agentName || null,
|
|
81
90
|
governance,
|
package/src/governance/hooks.ts
CHANGED
|
@@ -72,9 +72,9 @@ export function registerGovernanceHooks(api: any, config: ClawAxisConfig) {
|
|
|
72
72
|
if (ft) {
|
|
73
73
|
clearTimeout(ft);
|
|
74
74
|
setFlushTimeout(null);
|
|
75
|
-
flushLogQueue()
|
|
75
|
+
try { flushLogQueue(); } catch (err) {
|
|
76
76
|
console.error(`${LOG_PREFIX} Log flush failed:`, err);
|
|
77
|
-
}
|
|
77
|
+
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
return context;
|
package/src/message-handler.ts
CHANGED
|
@@ -1,27 +1,20 @@
|
|
|
1
|
-
import WS from "ws";
|
|
2
1
|
import { LOG_PREFIX } from "./config.js";
|
|
3
2
|
import {
|
|
4
3
|
getRuntime,
|
|
5
|
-
getWs,
|
|
6
4
|
getIsAuthenticated,
|
|
7
5
|
getAuthenticatedAgentId,
|
|
8
|
-
getLastTokenCount,
|
|
9
|
-
setLastTokenCount,
|
|
10
|
-
addSessionTokens,
|
|
11
6
|
hasProcessedMessage,
|
|
12
7
|
markMessageProcessed,
|
|
13
8
|
} from "./runtime.js";
|
|
14
|
-
import {
|
|
9
|
+
import { relaySend, socketWrite } from "./socket.js";
|
|
10
|
+
import { relayLog, getModelName, getSessionTokens } from "./utils.js";
|
|
15
11
|
|
|
16
12
|
export function sendStatusUpdate(messageId: string, status: string): void {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
status,
|
|
23
|
-
}));
|
|
24
|
-
}
|
|
13
|
+
relaySend({
|
|
14
|
+
type: "status",
|
|
15
|
+
message_id: messageId,
|
|
16
|
+
status,
|
|
17
|
+
});
|
|
25
18
|
}
|
|
26
19
|
|
|
27
20
|
export async function dispatchSystemMessage(
|
|
@@ -61,16 +54,13 @@ export async function dispatchSystemMessage(
|
|
|
61
54
|
dispatcherOptions: {
|
|
62
55
|
deliver: async (payload: any) => {
|
|
63
56
|
if (payload.text) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
tokens_used: 0,
|
|
72
|
-
}));
|
|
73
|
-
}
|
|
57
|
+
relaySend({
|
|
58
|
+
type: "reply",
|
|
59
|
+
ref_id: refId,
|
|
60
|
+
content: payload.text,
|
|
61
|
+
model_used: getModelName(),
|
|
62
|
+
tokens_used: 0,
|
|
63
|
+
});
|
|
74
64
|
}
|
|
75
65
|
},
|
|
76
66
|
onError: (err: Error) => {
|
|
@@ -82,11 +72,7 @@ export async function dispatchSystemMessage(
|
|
|
82
72
|
}
|
|
83
73
|
|
|
84
74
|
export async function handleMessage(msg: any): Promise<void> {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (ws?.readyState === WS.OPEN) {
|
|
88
|
-
ws.send(JSON.stringify({ type: "ack", id: msg.id }));
|
|
89
|
-
}
|
|
75
|
+
relaySend({ type: "ack", id: msg.id });
|
|
90
76
|
|
|
91
77
|
if (hasProcessedMessage(msg.id)) {
|
|
92
78
|
console.log(`${LOG_PREFIX} Skipping duplicate message: ${msg.id}`);
|
|
@@ -138,7 +124,7 @@ export async function handleMessage(msg: any): Promise<void> {
|
|
|
138
124
|
return;
|
|
139
125
|
}
|
|
140
126
|
|
|
141
|
-
const tokensBefore = getSessionTokens(runtime)
|
|
127
|
+
const tokensBefore = getSessionTokens(runtime);
|
|
142
128
|
|
|
143
129
|
await dispatchReply({
|
|
144
130
|
ctx: ctxPayload,
|
|
@@ -149,28 +135,15 @@ export async function handleMessage(msg: any): Promise<void> {
|
|
|
149
135
|
const tokensAfter = getSessionTokens(runtime);
|
|
150
136
|
const tokensDelta = tokensAfter > tokensBefore ? tokensAfter - tokensBefore : 0;
|
|
151
137
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
model_used: getModelName(),
|
|
162
|
-
tokens_used: tokensDelta || 0,
|
|
163
|
-
processing_time_ms: Date.now() - (msg.timestamp || new Date(msg.created_at).getTime())
|
|
164
|
-
}));
|
|
165
|
-
console.log(`${LOG_PREFIX} \u2713 Reply sent via WebSocket`);
|
|
166
|
-
} else {
|
|
167
|
-
await relayFetch("POST", "message", {
|
|
168
|
-
content: payload.text,
|
|
169
|
-
model_used: getModelName(),
|
|
170
|
-
tokens_used: tokensDelta || 0
|
|
171
|
-
});
|
|
172
|
-
console.log(`${LOG_PREFIX} \u2713 Reply sent via HTTPS`);
|
|
173
|
-
}
|
|
138
|
+
relaySend({
|
|
139
|
+
type: "reply",
|
|
140
|
+
ref_id: msg.id,
|
|
141
|
+
content: payload.text,
|
|
142
|
+
model_used: getModelName(),
|
|
143
|
+
tokens_used: tokensDelta || 0,
|
|
144
|
+
processing_time_ms: Date.now() - (msg.timestamp || new Date(msg.created_at).getTime())
|
|
145
|
+
});
|
|
146
|
+
console.log(`${LOG_PREFIX} Reply sent via socket`);
|
|
174
147
|
|
|
175
148
|
sendStatusUpdate(msg.id, "complete");
|
|
176
149
|
}
|
|
@@ -196,10 +169,7 @@ export async function handleMessage(msg: any): Promise<void> {
|
|
|
196
169
|
}
|
|
197
170
|
|
|
198
171
|
export async function handleCommand(msg: any): Promise<void> {
|
|
199
|
-
|
|
200
|
-
if (ws?.readyState === WS.OPEN) {
|
|
201
|
-
ws.send(JSON.stringify({ type: "ack", id: msg.id }));
|
|
202
|
-
}
|
|
172
|
+
relaySend({ type: "ack", id: msg.id });
|
|
203
173
|
|
|
204
174
|
console.log(`${LOG_PREFIX} Received command: ${msg.action}`);
|
|
205
175
|
|
package/src/runtime.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Socket } from "node:net";
|
|
1
2
|
import type { MemoryCacheEntry, LogEntry } from "./types.js";
|
|
2
3
|
|
|
3
4
|
let pluginRuntime: any = null;
|
|
@@ -5,54 +6,24 @@ let pluginRuntime: any = null;
|
|
|
5
6
|
export function getRuntime(): any { return pluginRuntime; }
|
|
6
7
|
export function setRuntime(r: any) { pluginRuntime = r; }
|
|
7
8
|
|
|
8
|
-
//
|
|
9
|
-
let
|
|
10
|
-
let
|
|
11
|
-
let isAuthenticated = false;
|
|
9
|
+
// Unix socket connection state
|
|
10
|
+
let socket: Socket | null = null;
|
|
11
|
+
let authenticated = false;
|
|
12
12
|
let authenticatedAgentId: string | null = null;
|
|
13
|
-
let
|
|
14
|
-
let heartbeatInterval: NodeJS.Timeout | null = null;
|
|
15
|
-
let running = true;
|
|
13
|
+
let running = false;
|
|
16
14
|
|
|
17
|
-
export function
|
|
18
|
-
export function
|
|
15
|
+
export function getSocket() { return socket; }
|
|
16
|
+
export function setSocket(s: Socket | null) { socket = s; }
|
|
19
17
|
|
|
20
|
-
export function
|
|
21
|
-
export function
|
|
22
|
-
export function incrementReconnectAttempts() { reconnectAttempts++; }
|
|
23
|
-
|
|
24
|
-
export function getIsAuthenticated() { return isAuthenticated; }
|
|
25
|
-
export function setIsAuthenticated(v: boolean) { isAuthenticated = v; }
|
|
18
|
+
export function getIsAuthenticated() { return authenticated; }
|
|
19
|
+
export function setIsAuthenticated(v: boolean) { authenticated = v; }
|
|
26
20
|
|
|
27
21
|
export function getAuthenticatedAgentId() { return authenticatedAgentId; }
|
|
28
22
|
export function setAuthenticatedAgentId(id: string | null) { authenticatedAgentId = id; }
|
|
29
23
|
|
|
30
|
-
export function getPingInterval() { return pingInterval; }
|
|
31
|
-
export function setPingInterval(t: NodeJS.Timeout | null) { pingInterval = t; }
|
|
32
|
-
|
|
33
|
-
export function getHeartbeatInterval() { return heartbeatInterval; }
|
|
34
|
-
export function setHeartbeatInterval(t: NodeJS.Timeout | null) { heartbeatInterval = t; }
|
|
35
|
-
|
|
36
24
|
export function isRunning() { return running; }
|
|
37
25
|
export function setRunning(v: boolean) { running = v; }
|
|
38
26
|
|
|
39
|
-
// Token tracking
|
|
40
|
-
let lastTokenCount = 0;
|
|
41
|
-
let sessionTokensAccumulated = 0;
|
|
42
|
-
let sessionCostAccumulated = 0;
|
|
43
|
-
let lastHeartbeatTokens = 0;
|
|
44
|
-
|
|
45
|
-
export function getLastTokenCount() { return lastTokenCount; }
|
|
46
|
-
export function setLastTokenCount(n: number) { lastTokenCount = n; }
|
|
47
|
-
|
|
48
|
-
export function getSessionTokensAccumulated() { return sessionTokensAccumulated; }
|
|
49
|
-
export function addSessionTokens(delta: number) { sessionTokensAccumulated += delta; }
|
|
50
|
-
|
|
51
|
-
export function getSessionCostAccumulated() { return sessionCostAccumulated; }
|
|
52
|
-
|
|
53
|
-
export function getLastHeartbeatTokens() { return lastHeartbeatTokens; }
|
|
54
|
-
export function setLastHeartbeatTokens(n: number) { lastHeartbeatTokens = n; }
|
|
55
|
-
|
|
56
27
|
// Message deduplication with lazy cleanup
|
|
57
28
|
const processedMessageIds = new Set<string>();
|
|
58
29
|
const MESSAGE_ID_HARD_CAP = 2000;
|