@gholl-studio/pier-connector 0.3.18 → 0.3.19

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gholl-studio/pier-connector",
3
3
  "author": "gholl",
4
- "version": "0.3.18",
4
+ "version": "0.3.19",
5
5
  "description": "OpenClaw plugin that connects to the Pier job marketplace. Automatically fetches, executes, and reports distributed tasks for rewards.",
6
6
  "type": "module",
7
7
  "main": "src/index.ts",
package/src/inbound.ts CHANGED
@@ -3,35 +3,25 @@
3
3
  * @description Manages inbound message processing, agent routing resolution, and session context propagation.
4
4
  */
5
5
 
6
- import type { PierPluginApi, InboundMessage } from './types.js';
6
+ import type { InboundMessage } from './types.js';
7
7
  import { truncate } from './job-handler.js';
8
8
 
9
9
  export async function handleInbound(
10
- api: PierPluginApi,
10
+ runtime: any, // Using context-aware runtime from gateway
11
11
  inbound: InboundMessage,
12
12
  jobId: string,
13
- robot: any, // Avoiding circular dependency with type PierRobot
14
- pierChannel: any
13
+ robot: any,
14
+ pierPlugin: any
15
15
  ) {
16
- const logger = api.logger;
17
- if (!api.runtime?.channel?.reply) {
18
- logger.error(`[pier-connector][${robot.accountId}] SDK Error: api.runtime.channel.reply is not available.`);
16
+ const logger = runtime.log || console;
17
+
18
+ if (!runtime.reply) {
19
+ console.error(`[pier-connector][${robot.accountId}] SDK Error: runtime.reply is not available.`);
19
20
  return;
20
21
  }
21
22
 
22
- // 0. Log Online/Configured Agents
23
- const agentsList = (api.config as any)?.agents?.list || [];
24
- const agentIds = Array.isArray(agentsList) ? agentsList.map((a: any) => a.id) : Object.keys(agentsList);
25
- logger.info(`[pier-connector][${robot.accountId}] Available agents in OpenClaw: ${JSON.stringify(agentIds)}`);
26
-
27
- // 1. Resolve Account-Scoped Configuration (Flat Structure for SDK)
28
- /**
29
- * ★ Multi-Account Configuration Isolation:
30
- * SDK helpers like resolveAgentRoute expect the channel config at the top level
31
- * of cfg.channels.<channelName>. Replacing it with the robot's merged config
32
- * ensures the SDK sees the correct agentId/dmPolicy for this specific account.
33
- */
34
- const rootConfig = api.config || {};
23
+ // 1. Resolve Account-Scoped Configuration
24
+ const rootConfig = runtime.cfg || {};
35
25
  const accountScopedCfg = {
36
26
  ...rootConfig,
37
27
  channels: {
@@ -40,8 +30,8 @@ export async function handleInbound(
40
30
  }
41
31
  };
42
32
 
43
- // 2. Resolve Agent Route via SDK with Scoped Config
44
- const route = api.runtime.channel.routing.resolveAgentRoute({
33
+ // 2. Resolve Agent Route
34
+ const route = runtime.routing.resolveAgentRoute({
45
35
  cfg: accountScopedCfg,
46
36
  channel: 'pier',
47
37
  accountId: robot.accountId,
@@ -53,30 +43,6 @@ export async function handleInbound(
53
43
 
54
44
  logger.info(`[pier-connector] Routing account '${robot.accountId}' -> agent '${finalAgentId}' (Source: ${routingSource})`);
55
45
 
56
- // Debug: Check Agent Identity & Detailed Config
57
- try {
58
- const identity = (api.runtime as any).agent.resolveAgentIdentity(accountScopedCfg, finalAgentId);
59
- logger.info(`[pier-connector:debug] Identity resolution [0.3.18] for ${finalAgentId}: ${JSON.stringify(identity)}`);
60
-
61
- // Deep Config Inspection
62
- const agentsList = (accountScopedCfg as any)?.agents?.list || [];
63
- const targetedAgent = agentsList.find((a: any) => a.id === finalAgentId);
64
- if (targetedAgent) {
65
- logger.info(`[pier-connector:debug] FULL AGENT CONFIG for ${finalAgentId}: ${JSON.stringify({
66
- id: targetedAgent.id,
67
- name: targetedAgent.name,
68
- agentDir: targetedAgent.agentDir,
69
- workspace: targetedAgent.workspace,
70
- runtime: targetedAgent.runtime,
71
- model: targetedAgent.model
72
- })}`);
73
- } else {
74
- logger.warn(`[pier-connector:debug] Agent ${finalAgentId} NOT FOUND in agents.list of scoped config!`);
75
- }
76
- } catch (err: any) {
77
- logger.warn(`[pier-connector:debug] Identity resolution crash for ${finalAgentId}: ${err.message}`);
78
- }
79
-
80
46
  const dynamicSessionKey = `pier-job-${jobId}`;
81
47
  const metadata = robot.activeNodeJobs.get(jobId);
82
48
  let injectedPrompt = "";
@@ -105,19 +71,18 @@ export async function handleInbound(
105
71
  ].join('\n');
106
72
  }
107
73
 
108
- logger.info(`[pier-connector:trace] Finalized inbound context for job ${jobId}. Target Agent: ${finalAgentId}, Session: ${dynamicSessionKey}`);
109
-
110
- const ctxPayload = api.runtime.channel.reply.finalizeInboundContext({
74
+ // 3. Finalize Context
75
+ const ctxPayload = runtime.reply.finalizeInboundContext({
111
76
  Body: inbound.body,
112
77
  BodyForAgent: inbound.body,
113
78
  RawBody: inbound.body,
114
- From: inbound.senderId, // Fix: senderId already includes "pier:" prefix
79
+ From: inbound.senderId,
115
80
  To: `chat:${jobId}`,
116
81
  SessionKey: dynamicSessionKey,
117
82
  AccountId: robot.accountId,
118
83
  ChatType: 'direct',
119
84
  SenderId: inbound.senderId,
120
- SenderName: inbound.senderId, // Use senderId as name if unknown
85
+ SenderName: inbound.senderId,
121
86
  Provider: 'pier',
122
87
  Surface: 'pier',
123
88
  OriginatingChannel: 'pier',
@@ -130,27 +95,25 @@ export async function handleInbound(
130
95
  Metadata: {
131
96
  ...metadata,
132
97
  accountId: robot.accountId,
133
- agentId: finalAgentId, // Explicitly tell SDK which agent we want
98
+ agentId: finalAgentId,
134
99
  pierJobId: jobId,
135
100
  routingSource: routingSource
136
101
  }
137
102
  });
138
103
 
139
- logger.info(`[pier-connector:trace] FULL DISPATCH CONTEXT for job ${jobId}: ${JSON.stringify(ctxPayload)}`);
140
-
141
- const { dispatcher, markDispatchIdle } = api.runtime.channel.reply.createReplyDispatcherWithTyping({
104
+ // 4. Create Dispatcher
105
+ const { dispatcher, markDispatchIdle } = runtime.reply.createReplyDispatcherWithTyping({
142
106
  deliver: async (payload: any, info: any) => {
143
107
  const currentMeta = robot.activeNodeJobs.get(jobId);
144
- const rawResponder = payload.agentId || payload.btw?.agentId || payload.channelData?.agentId;
145
- const resAgent = rawResponder || finalAgentId;
108
+ const resAgent = payload.agentId || finalAgentId;
146
109
 
147
- logger.info(`[pier-connector:trace] Outbound delivery for ${jobId}. Mode: ${info?.kind}. Responder: ${resAgent} (Raw: ${rawResponder || 'none'}).`);
148
- logger.info(`[pier-connector:debug] FULL PAYLOAD: ${JSON.stringify(payload)}`);
110
+ logger.info(`[pier-connector:trace] Outbound delivery for ${jobId}. Responder: ${resAgent}.`);
149
111
 
150
112
  if (payload.text && payload.text.length > 0) {
151
- await pierChannel.outbound.sendText({
113
+ await pierPlugin.outbound.sendText({
152
114
  text: payload.text,
153
115
  to: `pier:${jobId}`,
116
+ accountId: robot.accountId,
154
117
  metadata: {
155
118
  ...currentMeta,
156
119
  accountId: robot.accountId,
@@ -162,11 +125,11 @@ export async function handleInbound(
162
125
  }
163
126
  });
164
127
 
165
- if (api.runtime.channel.session?.recordSessionMetaFromInbound) {
128
+ // 5. Session Recording
129
+ if (runtime.session?.recordSessionMetaFromInbound) {
166
130
  try {
167
- const storePath = api.runtime.channel.session.resolveStorePath(dynamicSessionKey);
168
- logger.info(`[pier-connector:trace] Recording session metadata at ${storePath}`);
169
- await api.runtime.channel.session.recordSessionMetaFromInbound({
131
+ const storePath = runtime.session.resolveStorePath(dynamicSessionKey);
132
+ await runtime.session.recordSessionMetaFromInbound({
170
133
  storePath, sessionKey: dynamicSessionKey, ctx: ctxPayload
171
134
  });
172
135
  } catch (err: any) {
@@ -174,22 +137,22 @@ export async function handleInbound(
174
137
  }
175
138
  }
176
139
 
140
+ // 6. Dispatch
177
141
  try {
178
- logger.info(`[pier-connector:trace] Dispatching reply to agent ${finalAgentId}...`);
179
- await api.runtime.channel.reply.dispatchReplyFromConfig({
142
+ await runtime.reply.dispatchReplyFromConfig({
180
143
  ctx: ctxPayload,
181
144
  cfg: accountScopedCfg,
182
145
  dispatcher,
183
146
  replyOptions: {
184
147
  onModelSelected: (mCtx: any) => {
185
- logger.info(`[pier-connector:debug] Model selected for ${jobId}: ${mCtx.provider}/${mCtx.model} (Think: ${mCtx.thinkLevel})`);
148
+ logger.info(`[pier-connector:debug] Model selected for ${jobId}: ${mCtx.provider}/${mCtx.model}`);
186
149
  }
187
150
  }
188
- } as any);
189
- logger.info(`[pier-connector:trace] dispatchReplyFromConfig completed for job ${jobId}`);
151
+ });
190
152
  } catch (err: any) {
191
153
  logger.error(`[pier-connector] ✖ Dispatch error for job ${jobId}: ${err.message}`);
192
154
  } finally {
193
- markDispatchIdle();
155
+ markDispatchIdle?.();
194
156
  }
195
157
  }
158
+
package/src/index.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * @file index.ts
3
- * @description Main entry point for the Pier Connector plugin. Orchestrates robots, tools, and channel registration.
3
+ * @description Main entry point for the Pier Connector plugin.
4
+ * Implements the standard OpenClaw ChannelPlugin interface for native multi-account support.
4
5
  */
5
6
 
6
7
  import { definePluginEntry } from 'openclaw/plugin-sdk/plugin-entry';
8
+ import type { ChannelPlugin, OpenClawConfig, PluginRuntime } from 'openclaw/plugin-sdk';
7
9
  import { protocol } from '@gholl-studio/pier-sdk';
8
10
  const { createRequestPayload } = protocol;
9
11
  import { DEFAULTS } from './config.js';
@@ -12,99 +14,174 @@ import { handleInbound } from './inbound.js';
12
14
  import { registerCli } from './cli.js';
13
15
  import type { PierAccountConfig, PierPluginApi } from './types.js';
14
16
 
15
- const register = (api: PierPluginApi) => {
16
- const logger = api.logger;
17
- const instances = new Map<string, PierRobot>();
18
- const globalStats = { received: 0, completed: 0, failed: 0 };
19
-
20
- function mergedCfgFrom(legacy: any, account: any): PierAccountConfig {
21
- const merged = { ...legacy, ...account };
22
- return {
23
- accountId: account.accountId || 'default',
24
- pierApiUrl: merged.pierApiUrl || DEFAULTS.PIER_API_URL,
25
- nodeId: merged.nodeId || DEFAULTS.NODE_ID,
26
- secretKey: merged.secretKey || DEFAULTS.SECRET_KEY,
27
- privateKey: merged.privateKey || process.env.PIER_PRIVATE_KEY || DEFAULTS.PRIVATE_KEY,
28
- natsUrl: merged.natsUrl || DEFAULTS.NATS_URL,
29
- subject: merged.subject || DEFAULTS.SUBJECT,
30
- publishSubject: merged.publishSubject || DEFAULTS.PUBLISH_SUBJECT,
31
- queueGroup: merged.queueGroup || DEFAULTS.QUEUE_GROUP,
32
- agentId: merged.agentId || DEFAULTS.AGENT_ID,
33
- walletAddress: merged.walletAddress || DEFAULTS.WALLET_ADDRESS,
34
- capabilities: merged.capabilities || ['translation', 'code-execution', 'reasoning', 'vision'],
35
- };
36
- }
17
+ // Global instances map to track active robots by account ID
18
+ const instances = new Map<string, PierRobot>();
37
19
 
38
- function resolveConfigs(): PierAccountConfig[] {
39
- const globalAccounts = (api.config as any)?.channels?.['pier']?.accounts || {};
40
- const pluginAccounts = (api.pluginConfig as any)?.accounts || {};
41
- const rawAccounts = { ...globalAccounts, ...pluginAccounts };
42
- const legacyCfg = api.pluginConfig || {};
20
+ /**
21
+ * Merges global/legacy config with account-specific overrides.
22
+ */
23
+ function mergedCfgFrom(legacy: any, account: any): PierAccountConfig {
24
+ const merged = { ...legacy, ...account };
25
+ return {
26
+ accountId: account.accountId || 'default',
27
+ pierApiUrl: merged.pierApiUrl || DEFAULTS.PIER_API_URL,
28
+ nodeId: merged.nodeId || DEFAULTS.NODE_ID,
29
+ secretKey: merged.secretKey || DEFAULTS.SECRET_KEY,
30
+ privateKey: merged.privateKey || process.env.PIER_PRIVATE_KEY || DEFAULTS.PRIVATE_KEY,
31
+ natsUrl: merged.natsUrl || DEFAULTS.NATS_URL,
32
+ subject: merged.subject || DEFAULTS.SUBJECT,
33
+ publishSubject: merged.publishSubject || DEFAULTS.PUBLISH_SUBJECT,
34
+ queueGroup: merged.queueGroup || DEFAULTS.QUEUE_GROUP,
35
+ agentId: merged.agentId || DEFAULTS.AGENT_ID,
36
+ walletAddress: merged.walletAddress || DEFAULTS.WALLET_ADDRESS,
37
+ capabilities: merged.capabilities || ['translation', 'code-execution', 'reasoning', 'vision'],
38
+ };
39
+ }
43
40
 
44
- if (Object.keys(rawAccounts).length === 0) {
45
- return [mergedCfgFrom(legacyCfg, { accountId: 'default' })];
46
- }
41
+ /**
42
+ * Resolves all configured accounts for the Pier channel.
43
+ */
44
+ function getAccountConfigs(cfg: OpenClawConfig, pluginConfig: any): PierAccountConfig[] {
45
+ const globalAccounts = (cfg as any)?.channels?.['pier']?.accounts || {};
46
+ const pluginAccounts = pluginConfig?.accounts || {};
47
+ const rawAccounts = { ...globalAccounts, ...pluginAccounts };
48
+ const legacyCfg = pluginConfig || {};
47
49
 
48
- return Object.entries(rawAccounts).map(([id, account]: [string, any]) =>
49
- mergedCfgFrom(legacyCfg, { ...account, accountId: id })
50
- );
50
+ if (Object.keys(rawAccounts).length === 0) {
51
+ return [mergedCfgFrom(legacyCfg, { accountId: 'default' })];
51
52
  }
52
53
 
53
- const pierChannel = {
54
+ return Object.entries(rawAccounts).map(([id, account]: [string, any]) =>
55
+ mergedCfgFrom(legacyCfg, { ...account, accountId: id })
56
+ );
57
+ }
58
+
59
+ const pierPlugin: ChannelPlugin<PierAccountConfig> = {
60
+ id: 'pier',
61
+
62
+ meta: {
54
63
  id: 'pier',
55
- meta: {
56
- id: 'pier',
57
- label: 'Pier',
58
- selectionLabel: 'Pier (NATS Job Marketplace)',
59
- blurb: 'Connect to the Pier distributed job marketplace.'
64
+ label: 'Pier',
65
+ selectionLabel: 'Pier (NATS Job Marketplace)',
66
+ docsPath: '/channels/pier',
67
+ blurb: 'Connect to the Pier distributed job marketplace.',
68
+ },
69
+
70
+ capabilities: {
71
+ chatTypes: ['direct'],
72
+ media: false,
73
+ reactions: false,
74
+ threads: false,
75
+ nativeCommands: true,
76
+ blockStreaming: true,
77
+ },
78
+
79
+ // -------------------------------------------------------------------------
80
+ // Config Adapter
81
+ // -------------------------------------------------------------------------
82
+ config: {
83
+ listAccountIds: (cfg) => {
84
+ const accounts = (cfg as any)?.channels?.['pier']?.accounts || {};
85
+ const ids = Object.keys(accounts);
86
+ return ids.length > 0 ? ids : ['default'];
60
87
  },
61
- outbound: {
62
- sendText: async (params: any) => {
63
- const robot = instances.get(params.metadata?.accountId || 'default') || instances.values().next().value;
64
- if (!robot || !robot.js) return;
65
-
66
- const jobId = params.metadata?.pierJobId || params.to.replace(/^pier:/, '');
67
- const subject = `chat.${jobId}`;
68
-
69
- const payload = {
70
- id: crypto.randomUUID ? crypto.randomUUID() : (Math.random().toString(36).substring(2)),
71
- job_id: jobId,
72
- sender_id: robot.config.nodeId,
73
- sender_name: robot.accountId,
74
- sender_type: 'node',
75
- content: params.text,
76
- created_at: new Date().toISOString(),
77
- auth_token: robot.config.secretKey
78
- };
88
+ resolveAccount: (cfg, accountId) => {
89
+ const accounts = (cfg as any)?.channels?.['pier']?.accounts || {};
90
+ const account = accounts[accountId || 'default'] || {};
91
+ return mergedCfgFrom((cfg as any)?.channels?.['pier'] || {}, { ...account, accountId: accountId || 'default' });
92
+ },
93
+ defaultAccountId: () => 'default'
94
+ },
79
95
 
80
- await robot.js.publish(subject, new TextEncoder().encode(JSON.stringify(payload)));
81
- }
96
+ // -------------------------------------------------------------------------
97
+ // Pairing Adapter
98
+ // -------------------------------------------------------------------------
99
+ pairing: {
100
+ idLabel: 'pierJobId',
101
+ normalizeAllowEntry: (entry) => entry.replace(/^(pier|job):/i, ''),
102
+ notifyApproval: async ({ cfg, id, accountId }) => {
103
+ // Signal received when 'openclaw pairing approve pier <id>' is run.
104
+ // Useful if we want to trigger specific onboarding or status updates.
105
+ console.log(`[pier-connector] Pairing approved for Job ${id} on account ${accountId}`);
82
106
  }
83
- };
107
+ },
84
108
 
85
- api.registerChannel(pierChannel as any);
86
-
87
- api.registerService({
88
- id: 'pier-connector',
89
- start: async () => {
90
- const configs = resolveConfigs();
91
- for (const config of configs) {
92
- const robot = new PierRobot(config, api, async (inbound, jobId) => {
93
- await handleInbound(api, inbound, jobId, robot, pierChannel);
94
- globalStats.received++;
95
- });
96
- instances.set(config.accountId, robot);
97
- await robot.start();
109
+ // -------------------------------------------------------------------------
110
+ // Outbound Adapter
111
+ // -------------------------------------------------------------------------
112
+ outbound: {
113
+ deliveryMode: 'direct',
114
+ sendText: async (ctx) => {
115
+ const robot = instances.get(ctx.accountId || 'default') || instances.values().next().value;
116
+ if (!robot || !robot.js) {
117
+ throw new Error('Robot not connected');
98
118
  }
119
+
120
+ const jobId = ctx.to.replace(/^pier:/, '');
121
+ const subject = `chat.${jobId}`;
122
+
123
+ const payload = {
124
+ id: (globalThis.crypto as any).randomUUID ? (globalThis.crypto as any).randomUUID() : (Math.random().toString(36).substring(2)),
125
+ job_id: jobId,
126
+ sender_id: robot.config.nodeId,
127
+ sender_name: robot.accountId,
128
+ sender_type: 'node',
129
+ content: ctx.text,
130
+ created_at: new Date().toISOString(),
131
+ auth_token: robot.config.secretKey
132
+ };
133
+
134
+ await robot.js.publish(subject, new TextEncoder().encode(JSON.stringify(payload)));
135
+
136
+ return {
137
+ channel: 'pier',
138
+ messageId: payload.id,
139
+ conversationId: jobId
140
+ };
141
+ }
142
+ },
143
+
144
+ // -------------------------------------------------------------------------
145
+ // Gateway Adapter
146
+ // -------------------------------------------------------------------------
147
+ gateway: {
148
+ startAccount: async (ctx) => {
149
+ const config = ctx.account;
150
+ const robot = new PierRobot(config, (ctx.runtime as any), async (inbound, jobId) => {
151
+ // Pass the context-aware runtime and the plugin instance
152
+ await handleInbound((ctx.runtime as any), inbound, jobId, robot, pierPlugin);
153
+ });
154
+ instances.set(ctx.accountId, robot);
155
+ await robot.start();
156
+ ctx.setStatus({
157
+ ...ctx.getStatus(),
158
+ running: true,
159
+ lastStartAt: new Date().toISOString()
160
+ } as any);
99
161
  },
100
- stop: async () => {
101
- for (const robot of instances.values()) {
162
+ stopAccount: async (ctx) => {
163
+ const robot = instances.get(ctx.accountId);
164
+ if (robot) {
102
165
  await robot.stop();
166
+ instances.delete(ctx.accountId);
103
167
  }
104
- instances.clear();
168
+ ctx.setStatus({
169
+ ...ctx.getStatus(),
170
+ running: false,
171
+ lastStopAt: new Date().toISOString()
172
+ } as any);
105
173
  }
106
- });
174
+ }
175
+ };
176
+
177
+ const register = (api: PierPluginApi) => {
178
+ const logger = api.logger;
179
+ const globalStats = { received: 0, completed: 0, failed: 0 };
180
+
181
+ // Register our new ChannelPlugin
182
+ api.registerChannel({ plugin: pierPlugin as any });
107
183
 
184
+ // Tools and CLI registration
108
185
  api.registerTool({
109
186
  name: 'pier_publish',
110
187
  label: 'Publish to Pier',
@@ -193,6 +270,7 @@ const register = (api: PierPluginApi) => {
193
270
  { optional: true }
194
271
  );
195
272
 
273
+ // Helper to register marketplace action tools
196
274
  const registerSystemActionTool = (name: string, label: string, description: string, action: string, extraParams: any, userRole = 'node') => {
197
275
  api.registerTool({
198
276
  name,
@@ -215,7 +293,6 @@ const register = (api: PierPluginApi) => {
215
293
  }
216
294
 
217
295
  try {
218
- const subject = `chat.${params.jobId}`;
219
296
  const { jobId: j, accountId: _, ...p } = params;
220
297
 
221
298
  if (!robot.js) {
@@ -234,7 +311,7 @@ const register = (api: PierPluginApi) => {
234
311
  action: action
235
312
  };
236
313
 
237
- await robot.js.publish(subject, new TextEncoder().encode(JSON.stringify(msgData)));
314
+ await robot.js.publish(`chat.${params.jobId}`, new TextEncoder().encode(JSON.stringify(msgData)));
238
315
  return { content: [{ type: 'text', text: `${action} executed successfully` }], details: {} };
239
316
  } catch (err: any) {
240
317
  return { content: [{ type: 'text', text: `Error: ${err.message}` }], details: {} };
@@ -279,7 +356,7 @@ const register = (api: PierPluginApi) => {
279
356
  }
280
357
  }, { optional: true });
281
358
 
282
- // Register simple status command
359
+ // Status Command
283
360
  api.registerCommand({
284
361
  name: 'pier',
285
362
  description: 'Show Pier status',
@@ -302,3 +379,4 @@ export default definePluginEntry({
302
379
  description: 'Connects OpenClaw to the Pier job marketplace.',
303
380
  register
304
381
  });
382
+
package/src/robot.ts CHANGED
@@ -25,20 +25,20 @@ export class PierRobot {
25
25
  public connectionStatus: 'disconnected' | 'connecting' | 'connected' | 'error' = 'disconnected';
26
26
  public stats = { received: 0, completed: 0, failed: 0 };
27
27
 
28
- private api: PierPluginApi;
28
+ private runtime: any;
29
29
  private logger: any;
30
30
  private heartbeatTimer: NodeJS.Timeout | null = null;
31
31
  private onInbound: (inbound: InboundMessage, jobId: string) => Promise<void>;
32
32
 
33
33
  constructor(
34
34
  config: PierAccountConfig,
35
- api: PierPluginApi,
35
+ runtime: any,
36
36
  onInbound: (inbound: InboundMessage, jobId: string) => Promise<void>
37
37
  ) {
38
38
  this.config = config;
39
39
  this.accountId = config.accountId;
40
- this.api = api;
41
- this.logger = api.logger;
40
+ this.runtime = runtime;
41
+ this.logger = runtime.log || console;
42
42
  this.onInbound = onInbound;
43
43
  this.client = new PierClient({
44
44
  apiUrl: config.pierApiUrl,
@@ -264,7 +264,7 @@ export class PierRobot {
264
264
 
265
265
  async autoRegister() {
266
266
  if (!this.config.privateKey) return;
267
- const hostName = `${(this.api as any).getRuntimeInfo?.()?.hostname ?? 'Auto'}-${this.accountId}`;
267
+ const hostName = `${this.runtime?.hostname ?? 'Auto'}-${this.accountId}`;
268
268
  const { nodeId, secretKey } = await this.client.autoRegister(this.config.privateKey, hostName);
269
269
  this.config.nodeId = nodeId;
270
270
  this.config.secretKey = secretKey;