@gholl-studio/pier-connector 0.3.12 → 0.3.14

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.12",
4
+ "version": "0.3.14",
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
@@ -19,62 +19,32 @@ export async function handleInbound(
19
19
  return;
20
20
  }
21
21
 
22
- // 1. Resolve Global Configuration
22
+ // 1. Resolve Account-Scoped Configuration
23
23
  const rootConfig = api.config || {};
24
24
 
25
- // 2. Resolve Agent Route via SDK
25
+ /**
26
+ * ★ Multi-Account Configuration Isolation: Build account-level ClawdbotConfig
27
+ *
28
+ * In multi-account scenarios, each account can have independent agent bindings.
29
+ * The SDK's resolveAgentRoute looks into cfg.channels.pier.
30
+ * By injecting the current robot's config here, we ensure the SDK finds
31
+ * the correct agentId for this specific account.
32
+ */
33
+ const accountScopedCfg = {
34
+ ...rootConfig,
35
+ channels: { ...rootConfig.channels, pier: robot.config }
36
+ };
37
+
38
+ // 2. Resolve Agent Route via SDK with Scoped Config
26
39
  const route = api.runtime.channel.routing.resolveAgentRoute({
27
- cfg: rootConfig,
40
+ cfg: accountScopedCfg,
28
41
  channel: 'pier',
29
42
  accountId: inbound.accountId,
30
43
  peer: { kind: 'direct', id: jobId }
31
44
  });
32
45
 
33
- // 3. Robust Routing Decision Tree
34
- let finalAgentId = null;
35
- let routingSource = 'unresolved';
36
-
37
- // A. Check explicit account-level binding in plugin local config
38
- if (robot.config.agentId && robot.config.agentId !== 'main' && robot.config.agentId !== 'default') {
39
- finalAgentId = robot.config.agentId;
40
- routingSource = 'plugin-local-config';
41
- }
42
-
43
- // B. Check Global Bindings
44
- if (!finalAgentId) {
45
- const bindings = Array.isArray(rootConfig.bindings) ? rootConfig.bindings : [];
46
- const binding = bindings.find((bi: any) =>
47
- bi.match?.channel === 'pier' &&
48
- (bi.match?.accountId === inbound.accountId || bi.match?.account === inbound.accountId)
49
- );
50
- if (binding?.agentId && binding.agentId !== 'main') {
51
- finalAgentId = binding.agentId;
52
- routingSource = 'manual-global-bindings-match';
53
- }
54
- }
55
-
56
- // C. SDK Routing Result
57
- if (!finalAgentId && route.agentId && route.agentId !== 'main' && route.agentId !== 'default') {
58
- finalAgentId = route.agentId;
59
- routingSource = 'sdk-global-bindings';
60
- }
61
-
62
- // D. Name-Matching Fallback
63
- if (!finalAgentId && inbound.accountId && inbound.accountId !== 'default' && inbound.accountId !== 'main') {
64
- const agents = (rootConfig as any).agents?.list || {};
65
- const agentExists = Array.isArray(agents) ? agents.some((a: any) => a.id === inbound.accountId) : !!agents[inbound.accountId];
66
-
67
- if (agentExists) {
68
- finalAgentId = inbound.accountId;
69
- routingSource = 'account-agent-name-match';
70
- }
71
- }
72
-
73
- // E. Ultimate Fallback
74
- if (!finalAgentId) {
75
- finalAgentId = route.agentId || 'main';
76
- routingSource = route.agentId ? 'sdk-default-fallback' : 'hardcoded-main-fallback';
77
- }
46
+ const finalAgentId = route.agentId || 'main';
47
+ const routingSource = route.agentId ? 'sdk-scoped-route' : 'sdk-default-fallback';
78
48
 
79
49
  logger.info(`[pier-connector] Routing account '${inbound.accountId}' -> agent '${finalAgentId}' (Source: ${routingSource})`);
80
50
 
@@ -109,28 +79,27 @@ export async function handleInbound(
109
79
  logger.info(`[pier-connector:trace] Finalized inbound context for job ${jobId}. Target Agent: ${finalAgentId}, Session: ${dynamicSessionKey}`);
110
80
 
111
81
  const ctxPayload = api.runtime.channel.reply.finalizeInboundContext({
112
- AgentId: finalAgentId,
113
- agentId: finalAgentId, // Redundant for compatibility
114
82
  Body: inbound.body,
115
83
  BodyForAgent: inbound.body,
116
84
  RawBody: inbound.body,
117
85
  From: inbound.senderId,
118
- To: `pier:${jobId}`,
86
+ To: `chat:${jobId}`,
119
87
  SessionKey: dynamicSessionKey,
120
88
  AccountId: inbound.accountId,
121
89
  ChatType: 'direct',
122
90
  SenderId: inbound.senderId,
91
+ SenderName: robot.accountId,
123
92
  Provider: 'pier',
124
93
  Surface: 'pier',
125
94
  OriginatingChannel: 'pier',
126
- OriginatingTo: `pier:${jobId}`,
95
+ OriginatingTo: `chat:${jobId}`,
127
96
  WasMentioned: true,
128
97
  CommandAuthorized: true,
129
98
  SystemPrompt: injectedPrompt,
130
99
  MessageId: jobId,
100
+ MessageSid: jobId,
131
101
  Metadata: {
132
102
  ...metadata,
133
- agentId: finalAgentId, // Pinning in metadata
134
103
  accountId: robot.accountId,
135
104
  pierJobId: jobId,
136
105
  routingSource: routingSource
@@ -170,7 +139,7 @@ export async function handleInbound(
170
139
  try {
171
140
  logger.info(`[pier-connector:trace] Dispatching reply to agent ${finalAgentId}...`);
172
141
  await api.runtime.channel.reply.dispatchReplyFromConfig({
173
- ctx: ctxPayload, cfg: api.config, dispatcher
142
+ ctx: ctxPayload, cfg: accountScopedCfg, dispatcher
174
143
  });
175
144
  logger.info(`[pier-connector:trace] dispatchReplyFromConfig completed for job ${jobId}`);
176
145
  } catch (err: any) {
package/src/index.ts CHANGED
@@ -117,8 +117,9 @@ const register = (api: PierPluginApi) => {
117
117
  },
118
118
  required: ['task']
119
119
  },
120
- async execute(_id, params) {
121
- const robot = instances.get(params.accountId || 'default') || instances.values().next().value;
120
+ async execute(_id, params, ctx: any) {
121
+ const accountId = params.accountId || ctx?.metadata?.accountId || ctx?.accountId || 'default';
122
+ const robot = instances.get(accountId) || instances.values().next().value;
122
123
  if (!robot || robot.connectionStatus !== 'connected') {
123
124
  return {
124
125
  content: [{ type: 'text', text: 'Robot not connected' }],
@@ -150,7 +151,7 @@ const register = (api: PierPluginApi) => {
150
151
  required: ['jobId', 'text']
151
152
  },
152
153
  async execute(_id, params, ctx: any) {
153
- const accountId = params.accountId || 'default';
154
+ const accountId = params.accountId || ctx?.metadata?.accountId || ctx?.accountId || 'default';
154
155
  const robot = instances.get(accountId) || instances.values().next().value;
155
156
  if (!robot || robot.connectionStatus !== 'connected') {
156
157
  return { content: [{ type: 'text', text: 'Error: Robot not connected' }], details: {} };
@@ -206,8 +207,8 @@ const register = (api: PierPluginApi) => {
206
207
  },
207
208
  required: ['jobId', ...Object.keys(extraParams)]
208
209
  },
209
- async execute(_id, params) {
210
- const accountId = params.accountId || 'default';
210
+ async execute(_id, params, ctx: any) {
211
+ const accountId = params.accountId || ctx?.metadata?.accountId || ctx?.accountId || 'default';
211
212
  const robot = instances.get(accountId) || instances.values().next().value;
212
213
  if (!robot || robot.connectionStatus !== 'connected') {
213
214
  return { content: [{ type: 'text', text: 'Error: Robot not connected' }], details: {} };
@@ -265,8 +266,9 @@ const register = (api: PierPluginApi) => {
265
266
  type: 'object',
266
267
  properties: { accountId: { type: 'string' } }
267
268
  },
268
- async execute(_id, params) {
269
- const robot = instances.get(params.accountId || 'default') || instances.values().next().value;
269
+ async execute(_id, params, ctx: any) {
270
+ const accountId = params.accountId || ctx?.metadata?.accountId || ctx?.accountId || 'default';
271
+ const robot = instances.get(accountId) || instances.values().next().value;
270
272
  if (!robot) return { content: [{ type: 'text', text: 'Error: Robot not found' }], details: {} };
271
273
  try {
272
274
  const profile = await robot.client.getUserProfile(robot.config.secretKey);