@gholl-studio/pier-connector 0.3.20 → 0.3.22

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.20",
4
+ "version": "0.3.22",
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
@@ -7,21 +7,22 @@ import type { InboundMessage } from './types.js';
7
7
  import { truncate } from './job-handler.js';
8
8
 
9
9
  export async function handleInbound(
10
- runtime: any, // Using context-aware runtime from gateway
10
+ ctx: any, // Gateway Context
11
11
  inbound: InboundMessage,
12
12
  jobId: string,
13
13
  robot: any,
14
14
  pierPlugin: any
15
15
  ) {
16
- const logger = runtime.log || console;
16
+ const logger = ctx.log || console;
17
+ const channelRuntime = ctx.channelRuntime;
17
18
 
18
- if (!runtime.reply) {
19
- console.error(`[pier-connector][${robot.accountId}] SDK Error: runtime.reply is not available.`);
19
+ if (!channelRuntime?.reply) {
20
+ console.error(`[pier-connector][${robot.accountId}] SDK Error: channelRuntime.reply is not available.`);
20
21
  return;
21
22
  }
22
23
 
23
24
  // 1. Resolve Account-Scoped Configuration
24
- const rootConfig = runtime.cfg || {};
25
+ const rootConfig = ctx.cfg || {};
25
26
  const accountScopedCfg = {
26
27
  ...rootConfig,
27
28
  channels: {
@@ -31,7 +32,7 @@ export async function handleInbound(
31
32
  };
32
33
 
33
34
  // 2. Resolve Agent Route
34
- const route = runtime.routing.resolveAgentRoute({
35
+ const route = channelRuntime.routing.resolveAgentRoute({
35
36
  cfg: accountScopedCfg,
36
37
  channel: 'pier',
37
38
  accountId: robot.accountId,
@@ -72,7 +73,7 @@ export async function handleInbound(
72
73
  }
73
74
 
74
75
  // 3. Finalize Context
75
- const ctxPayload = runtime.reply.finalizeInboundContext({
76
+ const ctxPayload = channelRuntime.reply.finalizeInboundContext({
76
77
  Body: inbound.body,
77
78
  BodyForAgent: inbound.body,
78
79
  RawBody: inbound.body,
@@ -102,7 +103,7 @@ export async function handleInbound(
102
103
  });
103
104
 
104
105
  // 4. Create Dispatcher
105
- const { dispatcher, markDispatchIdle } = runtime.reply.createReplyDispatcherWithTyping({
106
+ const { dispatcher, markDispatchIdle } = channelRuntime.reply.createReplyDispatcherWithTyping({
106
107
  deliver: async (payload: any, info: any) => {
107
108
  const currentMeta = robot.activeNodeJobs.get(jobId);
108
109
  const resAgent = payload.agentId || finalAgentId;
@@ -126,10 +127,10 @@ export async function handleInbound(
126
127
  });
127
128
 
128
129
  // 5. Session Recording
129
- if (runtime.session?.recordSessionMetaFromInbound) {
130
+ if (channelRuntime.session?.recordSessionMetaFromInbound) {
130
131
  try {
131
- const storePath = runtime.session.resolveStorePath(dynamicSessionKey);
132
- await runtime.session.recordSessionMetaFromInbound({
132
+ const storePath = channelRuntime.session.resolveStorePath(dynamicSessionKey);
133
+ await channelRuntime.session.recordSessionMetaFromInbound({
133
134
  storePath, sessionKey: dynamicSessionKey, ctx: ctxPayload
134
135
  });
135
136
  } catch (err: any) {
@@ -139,7 +140,7 @@ export async function handleInbound(
139
140
 
140
141
  // 6. Dispatch
141
142
  try {
142
- await runtime.reply.dispatchReplyFromConfig({
143
+ await channelRuntime.reply.dispatchReplyFromConfig({
143
144
  ctx: ctxPayload,
144
145
  cfg: accountScopedCfg,
145
146
  dispatcher,
package/src/index.ts CHANGED
@@ -141,51 +141,83 @@ 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, async (inbound, jobId) => {
151
- // Pass the context-aware runtime and the plugin instance
152
- await handleInbound(ctx.runtime, inbound, jobId, robot, pierPlugin);
171
+ // Use ctx as the runtime provider as it contains .channelRuntime, .log, etc.
172
+ const robot = new PierRobot(config, ctx as any, async (inbound, jobId) => {
173
+ // Pass the context containing channelRuntime
174
+ await handleInbound(ctx, inbound, jobId, robot, pierPlugin);
153
175
  });
154
176
  instances.set(ctx.accountId, robot);
155
177
 
156
178
  try {
179
+ (robot as any).lastStartAt = Date.now();
157
180
  await robot.start();
181
+
158
182
  ctx.setStatus({
159
183
  ...ctx.getStatus(),
160
184
  running: true,
161
- lastStartAt: Date.now()
185
+ connected: true,
186
+ lastStartAt: (robot as any).lastStartAt
162
187
  } as any);
163
188
 
164
- // Keep the account active until the abort signal is received
189
+ // IMPORTANT: Keep startAccount promise active for the lifetime of the connection.
190
+ // If this promise resolves, the Gateway will auto-restart the account.
165
191
  await new Promise<void>((resolve) => {
166
192
  ctx.abortSignal.addEventListener('abort', () => {
167
193
  resolve();
168
194
  }, { once: true });
195
+
196
+ if (ctx.abortSignal.aborted) resolve();
169
197
  });
198
+
199
+ console.log(`[pier-connector][${ctx.accountId}] Account signal aborted. Stopping...`);
170
200
  } catch (err: any) {
201
+ (robot as any).lastError = err.message;
171
202
  ctx.setStatus({
172
203
  ...ctx.getStatus(),
173
204
  running: false,
174
205
  lastError: err.message
175
206
  } as any);
176
- throw err; // Re-throw to signal failure to Gateway
207
+ throw err;
177
208
  }
178
209
  },
179
210
  stopAccount: async (ctx) => {
180
211
  const robot = instances.get(ctx.accountId);
181
212
  if (robot) {
213
+ (robot as any).lastStopAt = Date.now();
182
214
  await robot.stop();
183
215
  instances.delete(ctx.accountId);
184
216
  }
185
217
  ctx.setStatus({
186
218
  ...ctx.getStatus(),
187
219
  running: false,
188
- lastStopAt: Date.now()
220
+ lastStopAt: (robot as any).lastStopAt
189
221
  } as any);
190
222
  }
191
223
  }
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,