@gholl-studio/pier-connector 0.3.21 → 0.3.23

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.21",
4
+ "version": "0.3.23",
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,31 +7,28 @@ 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 accountScopedCfg = {
26
- ...rootConfig,
27
- channels: {
28
- ...rootConfig.channels,
29
- pier: robot.config
30
- }
31
- };
25
+ // 使用原始完整配置,不覆盖 channels.pier,确保 bindings 和 defaultAgent 完整可用。
26
+ // resolveAgentRoute 需要完整配置中的 bindings 才能正确匹配 channel+accountId 路由规则。
27
+ const rootConfig = ctx.cfg || {};
28
+ const accountScopedCfg = rootConfig;
32
29
 
33
30
  // 2. Resolve Agent Route
34
- const route = runtime.routing.resolveAgentRoute({
31
+ const route = channelRuntime.routing.resolveAgentRoute({
35
32
  cfg: accountScopedCfg,
36
33
  channel: 'pier',
37
34
  accountId: robot.accountId,
@@ -43,7 +40,10 @@ export async function handleInbound(
43
40
 
44
41
  logger.info(`[pier-connector] Routing account '${robot.accountId}' -> agent '${finalAgentId}' (Source: ${routingSource})`);
45
42
 
46
- const dynamicSessionKey = `pier-job-${jobId}`;
43
+ // route.sessionKey resolveAgentRoute 生成,格式为 agent/{agentId}/...,
44
+ // SDK 通过解析此 key 来确定使用哪个 agent。
45
+ // 若使用自定义字符串(如 pier-job-${jobId}),SDK 无法解析 agentId,会回落到默认 main agent。
46
+ const dynamicSessionKey = route.sessionKey;
47
47
  const metadata = robot.activeNodeJobs.get(jobId);
48
48
  let injectedPrompt = "";
49
49
 
@@ -72,13 +72,13 @@ export async function handleInbound(
72
72
  }
73
73
 
74
74
  // 3. Finalize Context
75
- const ctxPayload = runtime.reply.finalizeInboundContext({
75
+ const ctxPayload = channelRuntime.reply.finalizeInboundContext({
76
76
  Body: inbound.body,
77
77
  BodyForAgent: inbound.body,
78
78
  RawBody: inbound.body,
79
79
  From: inbound.senderId,
80
80
  To: `chat:${jobId}`,
81
- SessionKey: dynamicSessionKey,
81
+ SessionKey: route.sessionKey,
82
82
  AccountId: robot.accountId,
83
83
  ChatType: 'direct',
84
84
  SenderId: inbound.senderId,
@@ -102,7 +102,7 @@ export async function handleInbound(
102
102
  });
103
103
 
104
104
  // 4. Create Dispatcher
105
- const { dispatcher, markDispatchIdle } = runtime.reply.createReplyDispatcherWithTyping({
105
+ const { dispatcher, markDispatchIdle } = channelRuntime.reply.createReplyDispatcherWithTyping({
106
106
  deliver: async (payload: any, info: any) => {
107
107
  const currentMeta = robot.activeNodeJobs.get(jobId);
108
108
  const resAgent = payload.agentId || finalAgentId;
@@ -126,10 +126,10 @@ export async function handleInbound(
126
126
  });
127
127
 
128
128
  // 5. Session Recording
129
- if (runtime.session?.recordSessionMetaFromInbound) {
129
+ if (channelRuntime.session?.recordSessionMetaFromInbound) {
130
130
  try {
131
- const storePath = runtime.session.resolveStorePath(dynamicSessionKey);
132
- await runtime.session.recordSessionMetaFromInbound({
131
+ const storePath = channelRuntime.session.resolveStorePath(dynamicSessionKey);
132
+ await channelRuntime.session.recordSessionMetaFromInbound({
133
133
  storePath, sessionKey: dynamicSessionKey, ctx: ctxPayload
134
134
  });
135
135
  } catch (err: any) {
@@ -139,7 +139,7 @@ export async function handleInbound(
139
139
 
140
140
  // 6. Dispatch
141
141
  try {
142
- await runtime.reply.dispatchReplyFromConfig({
142
+ await channelRuntime.reply.dispatchReplyFromConfig({
143
143
  ctx: ctxPayload,
144
144
  cfg: accountScopedCfg,
145
145
  dispatcher,
package/src/index.ts CHANGED
@@ -168,9 +168,10 @@ const pierPlugin: ChannelPlugin<PierAccountConfig> = {
168
168
  gateway: {
169
169
  startAccount: async (ctx) => {
170
170
  const config = ctx.account;
171
- // ctx has .log, .runtime, .cfg, etc.
171
+ // Use ctx as the runtime provider as it contains .channelRuntime, .log, etc.
172
172
  const robot = new PierRobot(config, ctx as any, async (inbound, jobId) => {
173
- await handleInbound(ctx.runtime, inbound, jobId, robot, pierPlugin);
173
+ // Pass the context containing channelRuntime
174
+ await handleInbound(ctx, inbound, jobId, robot, pierPlugin);
174
175
  });
175
176
  instances.set(ctx.accountId, robot);
176
177
 
@@ -185,11 +186,17 @@ const pierPlugin: ChannelPlugin<PierAccountConfig> = {
185
186
  lastStartAt: (robot as any).lastStartAt
186
187
  } as any);
187
188
 
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.`);
189
+ // IMPORTANT: Keep startAccount promise active for the lifetime of the connection.
190
+ // If this promise resolves, the Gateway will auto-restart the account.
191
+ await new Promise<void>((resolve) => {
192
+ ctx.abortSignal.addEventListener('abort', () => {
193
+ resolve();
194
+ }, { once: true });
195
+
196
+ if (ctx.abortSignal.aborted) resolve();
197
+ });
198
+
199
+ console.log(`[pier-connector][${ctx.accountId}] Account signal aborted. Stopping...`);
193
200
  } catch (err: any) {
194
201
  (robot as any).lastError = err.message;
195
202
  ctx.setStatus({