@gholl-studio/pier-connector 0.2.49 → 0.2.51

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +58 -43
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gholl-studio/pier-connector",
3
3
  "author": "gholl",
4
- "version": "0.2.49",
4
+ "version": "0.2.51",
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.js",
package/src/index.js CHANGED
@@ -38,11 +38,15 @@ export default function register(api) {
38
38
  // ── resolve plugin config ──────────────────────────────────────────
39
39
 
40
40
  function resolveConfigs() {
41
- const rawAccounts = api.config?.channels?.['pier']?.accounts || {};
42
- const legacyCfg = api.config?.plugins?.entries?.['pier-connector']?.config || {};
41
+ const globalAccounts = api.runtime?.config?.channels?.['pier']?.accounts || {};
42
+ const pluginAccounts = api.config?.channels?.['pier']?.accounts || {};
43
+ const rawAccounts = { ...globalAccounts, ...pluginAccounts };
43
44
 
44
- // If no accounts defined, fallback to 'default' using legacy/env config
45
+ const legacyCfg = api.config?.plugins?.entries?.['pier-connector']?.config || api.config || {};
46
+
47
+ // If no accounts defined at all, fallback to 'default' using legacy/env config
45
48
  if (Object.keys(rawAccounts).length === 0) {
49
+ logger.info(`[pier-connector] No accounts found in global or plugin config. Falling back to default.`);
46
50
  return [{
47
51
  accountId: 'default',
48
52
  ...mergedCfgFrom(legacyCfg, {})
@@ -161,68 +165,77 @@ export default function register(api) {
161
165
  return;
162
166
  }
163
167
 
164
- logger.info(`[pier-connector:trace] receiveIncoming triggered. inbound.accountId='${inbound.accountId}', inbound.senderId='${inbound.senderId}'`);
168
+ logger.info(`[pier-connector:trace] receiveIncoming triggered for jobId=${jobId}. accountId='${inbound.accountId}', senderId='${inbound.senderId}'`);
165
169
 
170
+ // 1. Resolve Global Configuration
171
+ // In OpenClaw V2, we need the FULL config for routing to work, but api.runtime.config is often scoped to the plugin.
172
+ // We search for the root config and fall back to whatever is available.
173
+ const rootConfig = api.rootConfig || api.runtime?.globalConfig || api.runtime?.config || {};
174
+
175
+ // Diagnostic logging (only if we suspect it's still failing)
176
+ const bindingsCount = Array.isArray(rootConfig.bindings) ? rootConfig.bindings.length : 0;
177
+ const agentsCount = rootConfig.agents?.list ? (Array.isArray(rootConfig.agents.list) ? rootConfig.agents.list.length : Object.keys(rootConfig.agents.list).length) : 0;
178
+
179
+ logger.info(`[pier-connector:trace] Diagnostic: rootConfig source=${api.rootConfig ? 'api.rootConfig' : (api.runtime?.globalConfig ? 'globalConfig' : 'runtime.config')}, bindings=${bindingsCount}, agents=${agentsCount}`);
180
+
181
+ // 2. Resolve Agent Route via SDK
166
182
  const route = api.runtime.channel.routing.resolveAgentRoute({
167
- cfg: api.runtime.config,
183
+ cfg: rootConfig,
168
184
  channel: 'pier',
169
- account: inbound.accountId, // Fixed: parameter name should be 'account'
185
+ account: inbound.accountId,
170
186
  peer: { kind: 'direct', id: jobId }
171
187
  });
172
188
 
173
189
  logger.info(`[pier-connector:trace] resolveAgentRoute returned: route.agentId='${route?.agentId}', route.accountId='${route?.accountId}'`);
174
190
 
175
- // 1. Explicit account-level agentId from plugin config (if still used)
176
- let finalAgentId = this.config.agentId;
177
- let routingSource = 'account-config';
191
+ // 3. Robust Routing Decision Tree
192
+ let finalAgentId = null;
193
+ let routingSource = 'unresolved';
178
194
 
179
- // 2. Robust manual parse (safeguard against OpenClaw core parsing bugs)
180
- if (!finalAgentId && api.runtime?.config) {
181
- const cfg = api.runtime.config;
182
- const bs = Array.isArray(cfg.bindings) ? cfg.bindings : [];
183
- const al = Array.isArray(cfg.agents?.list) ? cfg.agents.list : [];
184
-
185
- logger.info(`[pier-connector:trace] Manual debug: bindings_count=${bs.length}, agents_count=${al.length}`);
195
+ // A. Check explicit account-level binding in plugin local config (this.config)
196
+ if (this.config.agentId && this.config.agentId !== 'main' && this.config.agentId !== 'default') {
197
+ finalAgentId = this.config.agentId;
198
+ routingSource = 'plugin-local-config';
199
+ }
186
200
 
187
- // Check bindings
188
- const manualBinding = bs.find(b =>
201
+ // B. Check Global Bindings (Manual Scan of rootConfig.bindings)
202
+ if (!finalAgentId) {
203
+ const bindings = Array.isArray(rootConfig.bindings) ? rootConfig.bindings : [];
204
+ const binding = bindings.find(b =>
189
205
  b.match?.channel === 'pier' &&
190
206
  (b.match?.accountId === inbound.accountId || b.match?.account === inbound.accountId)
191
207
  );
192
-
193
- if (manualBinding && manualBinding.agentId && manualBinding.agentId !== 'main') {
194
- finalAgentId = manualBinding.agentId;
195
- routingSource = 'manual-global-bindings';
196
- }
197
-
198
- // Check agent list for name match (account ID == agent ID)
199
- if (!finalAgentId) {
200
- const nameMatch = al.find(a => a.id === inbound.accountId);
201
- if (nameMatch) {
202
- finalAgentId = inbound.accountId;
203
- routingSource = 'manual-name-match';
204
- }
208
+ if (binding?.agentId && binding.agentId !== 'main') {
209
+ finalAgentId = binding.agentId;
210
+ routingSource = 'manual-global-bindings-match';
205
211
  }
206
212
  }
207
213
 
208
- // 3. Fallback to OpenClaw's resolveAgentRoute (only if still unresolved and not 'main')
214
+ // C. SDK Routing Result (if it actually found something non-default)
209
215
  if (!finalAgentId && route.agentId && route.agentId !== 'main' && route.agentId !== 'default') {
210
216
  finalAgentId = route.agentId;
211
217
  routingSource = 'sdk-global-bindings';
212
218
  }
213
219
 
214
- // 4. Ultimate/Aggressive default
215
- if (!finalAgentId) {
216
- if (inbound.accountId && inbound.accountId !== 'default' && inbound.accountId !== 'main') {
217
- // Critical fallback: if the account has a custom name, assume the user wants that specific agent
220
+ // D. Name-Matching Fallback (CRITICAL: account name == agent ID)
221
+ // If we see account 'sunwukong', and we have an agent 'sunwukong', route there!
222
+ if (!finalAgentId && inbound.accountId && inbound.accountId !== 'default' && inbound.accountId !== 'main') {
223
+ // Check if such an agent exists in rootConfig
224
+ const agents = rootConfig.agents?.list || {};
225
+ const agentExists = Array.isArray(agents) ? agents.some(a => a.id === inbound.accountId) : !!agents[inbound.accountId];
226
+
227
+ if (agentExists) {
218
228
  finalAgentId = inbound.accountId;
219
- routingSource = 'aggressive-account-name-match';
220
- } else {
221
- finalAgentId = route.agentId || 'main'; // Ultimate fallback
222
- routingSource = route.agentId ? 'global-bindings-fallback' : 'default-routing';
229
+ routingSource = 'account-agent-name-match';
223
230
  }
224
231
  }
225
232
 
233
+ // E. Ultimate Fallback
234
+ if (!finalAgentId) {
235
+ finalAgentId = route.agentId || 'main'; // Use SDK result or hard default 'main'
236
+ routingSource = route.agentId ? 'sdk-default-fallback' : 'hardcoded-main-fallback';
237
+ }
238
+
226
239
  logger.info(`[pier-connector] Routing account '${inbound.accountId}' -> agent '${finalAgentId}' (Source: ${routingSource})`);
227
240
 
228
241
  const dynamicSessionKey = `pier-job-${jobId}`;
@@ -236,7 +249,7 @@ export default function register(api) {
236
249
  "=========================================",
237
250
  "You are an autonomous AI worker on Pier. This job currently has NO assigned worker.",
238
251
  "1. DO NOT directly solve the user's task or output the final answer right now.",
239
- "2. You MUST USE the `pier_bid_task` tool to send a pitch/bid to the employer explaining why you are best equipped to solve this, and state your price.",
252
+ "2. You MUST USE the \`pier_bid_task\` tool to send a pitch/bid to the employer explaining why you are best equipped to solve this.",
240
253
  "3. Stop executing after submitting the bid.",
241
254
  "4. You MUST use the Job ID provided below when calling the tool.",
242
255
  `Job ID: ${jobId}`,
@@ -255,8 +268,9 @@ export default function register(api) {
255
268
  ].join('\n');
256
269
  }
257
270
 
271
+ // MsgContext uses PascalCase for keys in OpenClaw V2 SDK
258
272
  const ctxPayload = api.runtime.channel.reply.finalizeInboundContext({
259
- agentId: finalAgentId, // Lowercase agentId is the standard target identifier
273
+ agentId: finalAgentId, // Keep lowercase here as it's the target system ID
260
274
  Body: inbound.text,
261
275
  BodyForAgent: inbound.text,
262
276
  RawBody: inbound.text,
@@ -277,7 +291,8 @@ export default function register(api) {
277
291
  Metadata: {
278
292
  ...metadata,
279
293
  accountId: this.accountId,
280
- pierJobId: jobId
294
+ pierJobId: jobId,
295
+ routingSource: routingSource
281
296
  }
282
297
  });
283
298