@gholl-studio/pier-connector 0.3.19 → 0.3.21

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.19",
4
+ "version": "0.3.21",
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/index.ts CHANGED
@@ -141,34 +141,76 @@ const pierPlugin: ChannelPlugin<PierAccountConfig> = {
141
141
  }
142
142
  },
143
143
 
144
+ // -------------------------------------------------------------------------
145
+ // Status Adapter
146
+ // -------------------------------------------------------------------------
147
+ status: {
148
+ buildAccountSnapshot: ({ account, cfg }) => {
149
+ const robot = instances.get(account.accountId);
150
+ return {
151
+ accountId: account.accountId,
152
+ running: !!robot,
153
+ connected: robot?.connectionStatus === 'connected',
154
+ lastStartAt: (robot as any)?.lastStartAt,
155
+ lastStopAt: (robot as any)?.lastStopAt,
156
+ lastError: (robot as any)?.lastError,
157
+ healthState: robot?.connectionStatus === 'connected' ? 'healthy' : 'degraded',
158
+ };
159
+ },
160
+ resolveAccountState: ({ configured, enabled }) => {
161
+ return configured && enabled ? 'enabled' : 'disabled';
162
+ }
163
+ },
164
+
144
165
  // -------------------------------------------------------------------------
145
166
  // Gateway Adapter
146
167
  // -------------------------------------------------------------------------
147
168
  gateway: {
148
169
  startAccount: async (ctx) => {
149
170
  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);
171
+ // ctx has .log, .runtime, .cfg, etc.
172
+ const robot = new PierRobot(config, ctx as any, async (inbound, jobId) => {
173
+ await handleInbound(ctx.runtime, inbound, jobId, robot, pierPlugin);
153
174
  });
154
175
  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);
176
+
177
+ try {
178
+ (robot as any).lastStartAt = Date.now();
179
+ await robot.start();
180
+
181
+ ctx.setStatus({
182
+ ...ctx.getStatus(),
183
+ running: true,
184
+ connected: true,
185
+ lastStartAt: (robot as any).lastStartAt
186
+ } as any);
187
+
188
+ // Note: We resolve here to signal successful startup.
189
+ // The robot stays alive in the 'instances' map.
190
+ // If OpenClaw requires a long-running promise, we can revert to keeping it alive,
191
+ // but usually, status monitoring is enough for non-standard services.
192
+ console.log(`[pier-connector][${ctx.accountId}] Startup successful and resolved.`);
193
+ } catch (err: any) {
194
+ (robot as any).lastError = err.message;
195
+ ctx.setStatus({
196
+ ...ctx.getStatus(),
197
+ running: false,
198
+ lastError: err.message
199
+ } as any);
200
+ throw err;
201
+ }
161
202
  },
162
203
  stopAccount: async (ctx) => {
163
204
  const robot = instances.get(ctx.accountId);
164
205
  if (robot) {
206
+ (robot as any).lastStopAt = Date.now();
165
207
  await robot.stop();
166
208
  instances.delete(ctx.accountId);
167
209
  }
168
210
  ctx.setStatus({
169
211
  ...ctx.getStatus(),
170
212
  running: false,
171
- lastStopAt: new Date().toISOString()
213
+ lastStopAt: (robot as any).lastStopAt
172
214
  } as any);
173
215
  }
174
216
  }
package/src/robot.ts CHANGED
@@ -38,8 +38,20 @@ export class PierRobot {
38
38
  this.config = config;
39
39
  this.accountId = config.accountId;
40
40
  this.runtime = runtime;
41
- this.logger = runtime.log || console;
42
41
  this.onInbound = onInbound;
42
+
43
+ // Robust logger wrapper
44
+ if (runtime.log && typeof runtime.log === 'object' && 'error' in runtime.log) {
45
+ this.logger = runtime.log;
46
+ } else {
47
+ this.logger = {
48
+ info: (msg: string) => (typeof runtime.log === 'function' ? runtime.log(msg) : console.log(msg)),
49
+ error: (msg: string) => (typeof runtime.error === 'function' ? runtime.error(msg) : console.error(msg)),
50
+ warn: (msg: string) => (typeof runtime.warn === 'function' ? runtime.warn(msg) : console.warn(msg)),
51
+ debug: (msg: string) => (typeof runtime.debug === 'function' ? runtime.debug(msg) : console.debug ? console.debug(msg) : console.log(msg)),
52
+ };
53
+ }
54
+
43
55
  this.client = new PierClient({
44
56
  apiUrl: config.pierApiUrl,
45
57
  natsUrl: config.natsUrl,
@@ -292,16 +304,24 @@ export class PierRobot {
292
304
  await this.setupMarketplaceConsumer(streamName, this.config.subject, durableNameMarket);
293
305
  await this.setupMarketplaceConsumer(streamName, `jobs.node.${this.config.nodeId}`, durableNameDirect);
294
306
 
307
+ if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
295
308
  this.heartbeatTimer = setInterval(() => this.heartbeat(), 60000);
296
309
  } catch (err: any) {
297
310
  this.connectionStatus = 'error';
298
311
  this.logger.error(`[pier-connector][${this.accountId}] Start failed: ${err.message}`);
312
+ throw err; // Re-throw to signal failure to Gateway
299
313
  }
300
314
  }
301
315
 
302
316
  async stop() {
303
- if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
304
- if (this.nc) await this.client.drainNats();
317
+ if (this.heartbeatTimer) {
318
+ clearInterval(this.heartbeatTimer);
319
+ this.heartbeatTimer = null;
320
+ }
321
+ if (this.nc) {
322
+ await this.client.drainNats();
323
+ this.nc = null;
324
+ }
305
325
  this.connectionStatus = 'disconnected';
306
326
  }
307
327
  }