@alfe.ai/openclaw-identity 0.0.2 → 0.0.4
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/dist/plugin.cjs +46 -105
- package/dist/plugin.js +46 -105
- package/package.json +3 -2
package/dist/plugin.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
let _alfe_ai_config = require("@alfe.ai/config");
|
|
2
|
+
let _alfe_ai_agent_api_client = require("@alfe.ai/agent-api-client");
|
|
2
3
|
let _sinclair_typebox = require("@sinclair/typebox");
|
|
3
4
|
//#region src/plugin.ts
|
|
4
5
|
/**
|
|
@@ -12,27 +13,9 @@ let _sinclair_typebox = require("@sinclair/typebox");
|
|
|
12
13
|
* - before_tool_call → enforce permissions from cached policy
|
|
13
14
|
* - after_tool_call → log tool execution audit
|
|
14
15
|
*
|
|
15
|
-
* All data access via
|
|
16
|
+
* All data access via AgentApiClient (/agent/identity/* routes).
|
|
16
17
|
* Uses the agent's own API key (from ~/.alfe/config.toml) for authentication.
|
|
17
18
|
*/
|
|
18
|
-
function createHttpClient(apiUrl, apiKey) {
|
|
19
|
-
async function request(method, path, body) {
|
|
20
|
-
const res = await fetch(`${apiUrl}${path}`, {
|
|
21
|
-
method,
|
|
22
|
-
headers: {
|
|
23
|
-
Authorization: `Bearer ${apiKey}`,
|
|
24
|
-
"Content-Type": "application/json"
|
|
25
|
-
},
|
|
26
|
-
...body ? { body: JSON.stringify(body) } : {}
|
|
27
|
-
});
|
|
28
|
-
if (!res.ok) {
|
|
29
|
-
const text = await res.text().catch(() => "");
|
|
30
|
-
throw new Error(`Identity API ${method} ${path}: ${String(res.status)} ${text}`);
|
|
31
|
-
}
|
|
32
|
-
return (await res.json()).data;
|
|
33
|
-
}
|
|
34
|
-
return { request };
|
|
35
|
-
}
|
|
36
19
|
const CACHE_TTL_MS = 6e4;
|
|
37
20
|
const sessionCache = /* @__PURE__ */ new Map();
|
|
38
21
|
function getCached(key) {
|
|
@@ -91,17 +74,17 @@ const plugin = {
|
|
|
91
74
|
activate(api) {
|
|
92
75
|
const log = api.logger;
|
|
93
76
|
log.info("Alfe Identity plugin activating...");
|
|
94
|
-
let
|
|
95
|
-
let apiKey;
|
|
77
|
+
let client;
|
|
96
78
|
try {
|
|
97
79
|
const config = (0, _alfe_ai_config.resolveConfig)();
|
|
98
|
-
|
|
99
|
-
|
|
80
|
+
client = new _alfe_ai_agent_api_client.AgentApiClient({
|
|
81
|
+
apiKey: config.apiKey,
|
|
82
|
+
apiUrl: config.apiUrl
|
|
83
|
+
});
|
|
100
84
|
} catch (err) {
|
|
101
85
|
log.error(`Identity plugin: failed to resolve config — ${err instanceof Error ? err.message : String(err)}`);
|
|
102
86
|
return;
|
|
103
87
|
}
|
|
104
|
-
const http = createHttpClient(apiUrl, apiKey);
|
|
105
88
|
const identityToolNames = /* @__PURE__ */ new Set();
|
|
106
89
|
const tools = [
|
|
107
90
|
defineTool({
|
|
@@ -109,54 +92,45 @@ const plugin = {
|
|
|
109
92
|
description: "Look up full identity context by platform and ID — returns profile, notes, tags, platforms, and recent changelog",
|
|
110
93
|
parameters: _sinclair_typebox.Type.Object({
|
|
111
94
|
platform: _sinclair_typebox.Type.String({ description: "Platform name (discord, slack, chat, sms, whatsapp, etc.)" }),
|
|
112
|
-
platformId: _sinclair_typebox.Type.String({ description: "Platform-specific user identifier" })
|
|
113
|
-
tenantId: _sinclair_typebox.Type.String()
|
|
95
|
+
platformId: _sinclair_typebox.Type.String({ description: "Platform-specific user identifier" })
|
|
114
96
|
}),
|
|
115
97
|
handler: async (params) => {
|
|
116
|
-
const result = await
|
|
98
|
+
const result = await client.resolveIdentity({
|
|
117
99
|
platform: params.platform,
|
|
118
|
-
platformId: params.platformId
|
|
119
|
-
tenantId: params.tenantId,
|
|
120
|
-
agentId: "plugin"
|
|
100
|
+
platformId: params.platformId
|
|
121
101
|
});
|
|
122
102
|
if (!result.identityId) return { found: false };
|
|
123
|
-
return
|
|
103
|
+
return client.getIdentityContext(result.identityId);
|
|
124
104
|
}
|
|
125
105
|
}),
|
|
126
106
|
defineTool({
|
|
127
107
|
name: "lookup_identity",
|
|
128
108
|
description: "Search identities by name, email, phone, tag, or platform. Returns multiple matches.",
|
|
129
109
|
parameters: _sinclair_typebox.Type.Object({
|
|
130
|
-
tenantId: _sinclair_typebox.Type.String(),
|
|
131
110
|
query: _sinclair_typebox.Type.Optional(_sinclair_typebox.Type.String({ description: "Text search query" })),
|
|
132
111
|
status: _sinclair_typebox.Type.Optional(_sinclair_typebox.Type.String()),
|
|
133
112
|
tag: _sinclair_typebox.Type.Optional(_sinclair_typebox.Type.String()),
|
|
134
113
|
platform: _sinclair_typebox.Type.Optional(_sinclair_typebox.Type.String())
|
|
135
114
|
}),
|
|
136
|
-
handler:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return http.request("GET", `/internal/identity/search?${qs.toString()}`);
|
|
143
|
-
}
|
|
115
|
+
handler: (params) => client.searchIdentities({
|
|
116
|
+
q: params.query,
|
|
117
|
+
status: params.status,
|
|
118
|
+
tag: params.tag,
|
|
119
|
+
platform: params.platform
|
|
120
|
+
})
|
|
144
121
|
}),
|
|
145
122
|
defineTool({
|
|
146
123
|
name: "create_identity",
|
|
147
124
|
description: "Create a new identity record with profile fields",
|
|
148
125
|
parameters: _sinclair_typebox.Type.Object({
|
|
149
|
-
tenantId: _sinclair_typebox.Type.String(),
|
|
150
126
|
platform: _sinclair_typebox.Type.String(),
|
|
151
127
|
platformId: _sinclair_typebox.Type.String(),
|
|
152
128
|
displayName: _sinclair_typebox.Type.Optional(_sinclair_typebox.Type.String())
|
|
153
129
|
}),
|
|
154
|
-
handler: (params) =>
|
|
130
|
+
handler: (params) => client.resolveIdentity({
|
|
155
131
|
platform: params.platform,
|
|
156
132
|
platformId: params.platformId,
|
|
157
|
-
displayName: params.displayName
|
|
158
|
-
tenantId: params.tenantId,
|
|
159
|
-
agentId: "plugin"
|
|
133
|
+
displayName: params.displayName
|
|
160
134
|
})
|
|
161
135
|
}),
|
|
162
136
|
defineTool({
|
|
@@ -164,11 +138,9 @@ const plugin = {
|
|
|
164
138
|
description: "Merge two identity records — transfers notes, tags, aliases, platforms to survivor",
|
|
165
139
|
parameters: _sinclair_typebox.Type.Object({
|
|
166
140
|
survivorId: _sinclair_typebox.Type.String({ description: "Identity to keep" }),
|
|
167
|
-
mergedId: _sinclair_typebox.Type.String({ description: "Identity to merge into survivor" })
|
|
168
|
-
tenantId: _sinclair_typebox.Type.String()
|
|
141
|
+
mergedId: _sinclair_typebox.Type.String({ description: "Identity to merge into survivor" })
|
|
169
142
|
}),
|
|
170
|
-
handler: (params) =>
|
|
171
|
-
tenantId: params.tenantId,
|
|
143
|
+
handler: (params) => client.mergeIdentities(params.survivorId, {
|
|
172
144
|
mergedId: params.mergedId,
|
|
173
145
|
changedBy: {
|
|
174
146
|
type: "agent",
|
|
@@ -179,17 +151,11 @@ const plugin = {
|
|
|
179
151
|
defineTool({
|
|
180
152
|
name: "unmerge_identities",
|
|
181
153
|
description: "Reverse a merge — restore previously merged identity",
|
|
182
|
-
parameters: _sinclair_typebox.Type.Object({
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
tenantId: params.tenantId,
|
|
188
|
-
changedBy: {
|
|
189
|
-
type: "agent",
|
|
190
|
-
id: "plugin"
|
|
191
|
-
}
|
|
192
|
-
})
|
|
154
|
+
parameters: _sinclair_typebox.Type.Object({ mergedId: _sinclair_typebox.Type.String({ description: "Identity that was merged (has mergedInto pointer)" }) }),
|
|
155
|
+
handler: (params) => client.unmergeIdentity(params.mergedId, { changedBy: {
|
|
156
|
+
type: "agent",
|
|
157
|
+
id: "plugin"
|
|
158
|
+
} })
|
|
193
159
|
}),
|
|
194
160
|
defineTool({
|
|
195
161
|
name: "link_platform",
|
|
@@ -197,14 +163,11 @@ const plugin = {
|
|
|
197
163
|
parameters: _sinclair_typebox.Type.Object({
|
|
198
164
|
identityId: _sinclair_typebox.Type.String(),
|
|
199
165
|
platform: _sinclair_typebox.Type.String(),
|
|
200
|
-
platformId: _sinclair_typebox.Type.String()
|
|
201
|
-
tenantId: _sinclair_typebox.Type.String()
|
|
166
|
+
platformId: _sinclair_typebox.Type.String()
|
|
202
167
|
}),
|
|
203
|
-
handler: (params) =>
|
|
168
|
+
handler: (params) => client.resolveIdentity({
|
|
204
169
|
platform: params.platform,
|
|
205
|
-
platformId: params.platformId
|
|
206
|
-
tenantId: params.tenantId,
|
|
207
|
-
agentId: "plugin"
|
|
170
|
+
platformId: params.platformId
|
|
208
171
|
})
|
|
209
172
|
}),
|
|
210
173
|
defineTool({
|
|
@@ -212,12 +175,10 @@ const plugin = {
|
|
|
212
175
|
description: "Add an observation or note about a contact",
|
|
213
176
|
parameters: _sinclair_typebox.Type.Object({
|
|
214
177
|
identityId: _sinclair_typebox.Type.String(),
|
|
215
|
-
tenantId: _sinclair_typebox.Type.String(),
|
|
216
178
|
content: _sinclair_typebox.Type.String(),
|
|
217
179
|
category: _sinclair_typebox.Type.Optional(_sinclair_typebox.Type.String({ description: "observation, preference, relationship, context, or warning" }))
|
|
218
180
|
}),
|
|
219
|
-
handler: (params) =>
|
|
220
|
-
tenantId: params.tenantId,
|
|
181
|
+
handler: (params) => client.addIdentityNote(params.identityId, {
|
|
221
182
|
content: params.content,
|
|
222
183
|
category: params.category,
|
|
223
184
|
changedBy: {
|
|
@@ -231,12 +192,10 @@ const plugin = {
|
|
|
231
192
|
description: "Add or remove a tag on an identity",
|
|
232
193
|
parameters: _sinclair_typebox.Type.Object({
|
|
233
194
|
identityId: _sinclair_typebox.Type.String(),
|
|
234
|
-
tenantId: _sinclair_typebox.Type.String(),
|
|
235
195
|
tag: _sinclair_typebox.Type.String(),
|
|
236
196
|
action: _sinclair_typebox.Type.String({ description: "'add' or 'remove'" })
|
|
237
197
|
}),
|
|
238
|
-
handler: (params) =>
|
|
239
|
-
tenantId: params.tenantId,
|
|
198
|
+
handler: (params) => client.tagIdentity(params.identityId, {
|
|
240
199
|
tag: params.tag,
|
|
241
200
|
action: params.action,
|
|
242
201
|
changedBy: {
|
|
@@ -250,25 +209,18 @@ const plugin = {
|
|
|
250
209
|
description: "Get full changelog for an identity — all versions, diffs, who changed what",
|
|
251
210
|
parameters: _sinclair_typebox.Type.Object({
|
|
252
211
|
identityId: _sinclair_typebox.Type.String(),
|
|
253
|
-
tenantId: _sinclair_typebox.Type.String(),
|
|
254
212
|
limit: _sinclair_typebox.Type.Optional(_sinclair_typebox.Type.Number())
|
|
255
213
|
}),
|
|
256
|
-
handler:
|
|
257
|
-
const qs = new URLSearchParams({ tenantId: params.tenantId });
|
|
258
|
-
if (params.limit) qs.set("limit", String(Number(params.limit)));
|
|
259
|
-
return http.request("GET", `/internal/identity/${encodeURIComponent(params.identityId)}/changelog?${qs.toString()}`);
|
|
260
|
-
}
|
|
214
|
+
handler: (params) => client.getIdentityChangelog(params.identityId, { limit: params.limit })
|
|
261
215
|
}),
|
|
262
216
|
defineTool({
|
|
263
217
|
name: "rollback_identity",
|
|
264
218
|
description: "Revert an identity to a previous version",
|
|
265
219
|
parameters: _sinclair_typebox.Type.Object({
|
|
266
220
|
identityId: _sinclair_typebox.Type.String(),
|
|
267
|
-
tenantId: _sinclair_typebox.Type.String(),
|
|
268
221
|
targetVersion: _sinclair_typebox.Type.Number()
|
|
269
222
|
}),
|
|
270
|
-
handler: (params) =>
|
|
271
|
-
tenantId: params.tenantId,
|
|
223
|
+
handler: (params) => client.rollbackIdentity(params.identityId, {
|
|
272
224
|
targetVersion: params.targetVersion,
|
|
273
225
|
changedBy: {
|
|
274
226
|
type: "agent",
|
|
@@ -282,14 +234,12 @@ const plugin = {
|
|
|
282
234
|
parameters: _sinclair_typebox.Type.Object({
|
|
283
235
|
platform: _sinclair_typebox.Type.String(),
|
|
284
236
|
senderId: _sinclair_typebox.Type.String(),
|
|
285
|
-
channelId: _sinclair_typebox.Type.Optional(_sinclair_typebox.Type.String())
|
|
286
|
-
tenantId: _sinclair_typebox.Type.String()
|
|
237
|
+
channelId: _sinclair_typebox.Type.Optional(_sinclair_typebox.Type.String())
|
|
287
238
|
}),
|
|
288
|
-
handler: (params) =>
|
|
239
|
+
handler: (params) => client.enforcePolicy({
|
|
289
240
|
platform: params.platform,
|
|
290
241
|
senderId: params.senderId,
|
|
291
|
-
channelId: params.channelId
|
|
292
|
-
tenantId: params.tenantId
|
|
242
|
+
channelId: params.channelId
|
|
293
243
|
})
|
|
294
244
|
}),
|
|
295
245
|
defineTool({
|
|
@@ -298,14 +248,12 @@ const plugin = {
|
|
|
298
248
|
parameters: _sinclair_typebox.Type.Object({
|
|
299
249
|
platform: _sinclair_typebox.Type.String(),
|
|
300
250
|
senderId: _sinclair_typebox.Type.String(),
|
|
301
|
-
toolName: _sinclair_typebox.Type.String()
|
|
302
|
-
tenantId: _sinclair_typebox.Type.String()
|
|
251
|
+
toolName: _sinclair_typebox.Type.String()
|
|
303
252
|
}),
|
|
304
|
-
handler: (params) =>
|
|
253
|
+
handler: (params) => client.checkToolPermission({
|
|
305
254
|
platform: params.platform,
|
|
306
255
|
senderId: params.senderId,
|
|
307
|
-
toolName: params.toolName
|
|
308
|
-
tenantId: params.tenantId
|
|
256
|
+
toolName: params.toolName
|
|
309
257
|
})
|
|
310
258
|
})
|
|
311
259
|
];
|
|
@@ -330,19 +278,14 @@ const plugin = {
|
|
|
330
278
|
return;
|
|
331
279
|
}
|
|
332
280
|
try {
|
|
333
|
-
const
|
|
334
|
-
const agentId = ctx.agentId ?? "";
|
|
335
|
-
const resolveResult = await http.request("POST", "/internal/identity/resolve", {
|
|
281
|
+
const resolveResult = await client.resolveIdentity({
|
|
336
282
|
platform,
|
|
337
|
-
platformId: senderId
|
|
338
|
-
tenantId,
|
|
339
|
-
agentId
|
|
283
|
+
platformId: senderId
|
|
340
284
|
});
|
|
341
285
|
setCached(cacheKey, {
|
|
342
|
-
...await
|
|
286
|
+
...await client.enforcePolicy({
|
|
343
287
|
platform,
|
|
344
|
-
senderId
|
|
345
|
-
tenantId
|
|
288
|
+
senderId
|
|
346
289
|
}),
|
|
347
290
|
accessAllowed: resolveResult.accessAllowed
|
|
348
291
|
});
|
|
@@ -381,17 +324,15 @@ const plugin = {
|
|
|
381
324
|
}, { priority: 100 });
|
|
382
325
|
api.on("after_tool_call", async (...args) => {
|
|
383
326
|
const event = args[0];
|
|
384
|
-
const
|
|
385
|
-
const sessionKey = ctx.sessionKey;
|
|
327
|
+
const sessionKey = args[1].sessionKey;
|
|
386
328
|
if (!sessionKey) return;
|
|
387
329
|
const perms = getCached(sessionKey);
|
|
388
330
|
if (!perms?.identityId) return;
|
|
389
331
|
try {
|
|
390
|
-
await
|
|
332
|
+
await client.checkToolPermission({
|
|
391
333
|
platform: "tool_audit",
|
|
392
334
|
senderId: perms.identityId,
|
|
393
|
-
toolName: event.toolName
|
|
394
|
-
tenantId: ctx.tenantId ?? ""
|
|
335
|
+
toolName: event.toolName
|
|
395
336
|
});
|
|
396
337
|
} catch (e) {
|
|
397
338
|
log.error(`Audit logging failed: ${e.message}`);
|
package/dist/plugin.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveConfig } from "@alfe.ai/config";
|
|
2
|
+
import { AgentApiClient } from "@alfe.ai/agent-api-client";
|
|
2
3
|
import { Type } from "@sinclair/typebox";
|
|
3
4
|
//#region src/plugin.ts
|
|
4
5
|
/**
|
|
@@ -12,27 +13,9 @@ import { Type } from "@sinclair/typebox";
|
|
|
12
13
|
* - before_tool_call → enforce permissions from cached policy
|
|
13
14
|
* - after_tool_call → log tool execution audit
|
|
14
15
|
*
|
|
15
|
-
* All data access via
|
|
16
|
+
* All data access via AgentApiClient (/agent/identity/* routes).
|
|
16
17
|
* Uses the agent's own API key (from ~/.alfe/config.toml) for authentication.
|
|
17
18
|
*/
|
|
18
|
-
function createHttpClient(apiUrl, apiKey) {
|
|
19
|
-
async function request(method, path, body) {
|
|
20
|
-
const res = await fetch(`${apiUrl}${path}`, {
|
|
21
|
-
method,
|
|
22
|
-
headers: {
|
|
23
|
-
Authorization: `Bearer ${apiKey}`,
|
|
24
|
-
"Content-Type": "application/json"
|
|
25
|
-
},
|
|
26
|
-
...body ? { body: JSON.stringify(body) } : {}
|
|
27
|
-
});
|
|
28
|
-
if (!res.ok) {
|
|
29
|
-
const text = await res.text().catch(() => "");
|
|
30
|
-
throw new Error(`Identity API ${method} ${path}: ${String(res.status)} ${text}`);
|
|
31
|
-
}
|
|
32
|
-
return (await res.json()).data;
|
|
33
|
-
}
|
|
34
|
-
return { request };
|
|
35
|
-
}
|
|
36
19
|
const CACHE_TTL_MS = 6e4;
|
|
37
20
|
const sessionCache = /* @__PURE__ */ new Map();
|
|
38
21
|
function getCached(key) {
|
|
@@ -91,17 +74,17 @@ const plugin = {
|
|
|
91
74
|
activate(api) {
|
|
92
75
|
const log = api.logger;
|
|
93
76
|
log.info("Alfe Identity plugin activating...");
|
|
94
|
-
let
|
|
95
|
-
let apiKey;
|
|
77
|
+
let client;
|
|
96
78
|
try {
|
|
97
79
|
const config = resolveConfig();
|
|
98
|
-
|
|
99
|
-
|
|
80
|
+
client = new AgentApiClient({
|
|
81
|
+
apiKey: config.apiKey,
|
|
82
|
+
apiUrl: config.apiUrl
|
|
83
|
+
});
|
|
100
84
|
} catch (err) {
|
|
101
85
|
log.error(`Identity plugin: failed to resolve config — ${err instanceof Error ? err.message : String(err)}`);
|
|
102
86
|
return;
|
|
103
87
|
}
|
|
104
|
-
const http = createHttpClient(apiUrl, apiKey);
|
|
105
88
|
const identityToolNames = /* @__PURE__ */ new Set();
|
|
106
89
|
const tools = [
|
|
107
90
|
defineTool({
|
|
@@ -109,54 +92,45 @@ const plugin = {
|
|
|
109
92
|
description: "Look up full identity context by platform and ID — returns profile, notes, tags, platforms, and recent changelog",
|
|
110
93
|
parameters: Type.Object({
|
|
111
94
|
platform: Type.String({ description: "Platform name (discord, slack, chat, sms, whatsapp, etc.)" }),
|
|
112
|
-
platformId: Type.String({ description: "Platform-specific user identifier" })
|
|
113
|
-
tenantId: Type.String()
|
|
95
|
+
platformId: Type.String({ description: "Platform-specific user identifier" })
|
|
114
96
|
}),
|
|
115
97
|
handler: async (params) => {
|
|
116
|
-
const result = await
|
|
98
|
+
const result = await client.resolveIdentity({
|
|
117
99
|
platform: params.platform,
|
|
118
|
-
platformId: params.platformId
|
|
119
|
-
tenantId: params.tenantId,
|
|
120
|
-
agentId: "plugin"
|
|
100
|
+
platformId: params.platformId
|
|
121
101
|
});
|
|
122
102
|
if (!result.identityId) return { found: false };
|
|
123
|
-
return
|
|
103
|
+
return client.getIdentityContext(result.identityId);
|
|
124
104
|
}
|
|
125
105
|
}),
|
|
126
106
|
defineTool({
|
|
127
107
|
name: "lookup_identity",
|
|
128
108
|
description: "Search identities by name, email, phone, tag, or platform. Returns multiple matches.",
|
|
129
109
|
parameters: Type.Object({
|
|
130
|
-
tenantId: Type.String(),
|
|
131
110
|
query: Type.Optional(Type.String({ description: "Text search query" })),
|
|
132
111
|
status: Type.Optional(Type.String()),
|
|
133
112
|
tag: Type.Optional(Type.String()),
|
|
134
113
|
platform: Type.Optional(Type.String())
|
|
135
114
|
}),
|
|
136
|
-
handler:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return http.request("GET", `/internal/identity/search?${qs.toString()}`);
|
|
143
|
-
}
|
|
115
|
+
handler: (params) => client.searchIdentities({
|
|
116
|
+
q: params.query,
|
|
117
|
+
status: params.status,
|
|
118
|
+
tag: params.tag,
|
|
119
|
+
platform: params.platform
|
|
120
|
+
})
|
|
144
121
|
}),
|
|
145
122
|
defineTool({
|
|
146
123
|
name: "create_identity",
|
|
147
124
|
description: "Create a new identity record with profile fields",
|
|
148
125
|
parameters: Type.Object({
|
|
149
|
-
tenantId: Type.String(),
|
|
150
126
|
platform: Type.String(),
|
|
151
127
|
platformId: Type.String(),
|
|
152
128
|
displayName: Type.Optional(Type.String())
|
|
153
129
|
}),
|
|
154
|
-
handler: (params) =>
|
|
130
|
+
handler: (params) => client.resolveIdentity({
|
|
155
131
|
platform: params.platform,
|
|
156
132
|
platformId: params.platformId,
|
|
157
|
-
displayName: params.displayName
|
|
158
|
-
tenantId: params.tenantId,
|
|
159
|
-
agentId: "plugin"
|
|
133
|
+
displayName: params.displayName
|
|
160
134
|
})
|
|
161
135
|
}),
|
|
162
136
|
defineTool({
|
|
@@ -164,11 +138,9 @@ const plugin = {
|
|
|
164
138
|
description: "Merge two identity records — transfers notes, tags, aliases, platforms to survivor",
|
|
165
139
|
parameters: Type.Object({
|
|
166
140
|
survivorId: Type.String({ description: "Identity to keep" }),
|
|
167
|
-
mergedId: Type.String({ description: "Identity to merge into survivor" })
|
|
168
|
-
tenantId: Type.String()
|
|
141
|
+
mergedId: Type.String({ description: "Identity to merge into survivor" })
|
|
169
142
|
}),
|
|
170
|
-
handler: (params) =>
|
|
171
|
-
tenantId: params.tenantId,
|
|
143
|
+
handler: (params) => client.mergeIdentities(params.survivorId, {
|
|
172
144
|
mergedId: params.mergedId,
|
|
173
145
|
changedBy: {
|
|
174
146
|
type: "agent",
|
|
@@ -179,17 +151,11 @@ const plugin = {
|
|
|
179
151
|
defineTool({
|
|
180
152
|
name: "unmerge_identities",
|
|
181
153
|
description: "Reverse a merge — restore previously merged identity",
|
|
182
|
-
parameters: Type.Object({
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
tenantId: params.tenantId,
|
|
188
|
-
changedBy: {
|
|
189
|
-
type: "agent",
|
|
190
|
-
id: "plugin"
|
|
191
|
-
}
|
|
192
|
-
})
|
|
154
|
+
parameters: Type.Object({ mergedId: Type.String({ description: "Identity that was merged (has mergedInto pointer)" }) }),
|
|
155
|
+
handler: (params) => client.unmergeIdentity(params.mergedId, { changedBy: {
|
|
156
|
+
type: "agent",
|
|
157
|
+
id: "plugin"
|
|
158
|
+
} })
|
|
193
159
|
}),
|
|
194
160
|
defineTool({
|
|
195
161
|
name: "link_platform",
|
|
@@ -197,14 +163,11 @@ const plugin = {
|
|
|
197
163
|
parameters: Type.Object({
|
|
198
164
|
identityId: Type.String(),
|
|
199
165
|
platform: Type.String(),
|
|
200
|
-
platformId: Type.String()
|
|
201
|
-
tenantId: Type.String()
|
|
166
|
+
platformId: Type.String()
|
|
202
167
|
}),
|
|
203
|
-
handler: (params) =>
|
|
168
|
+
handler: (params) => client.resolveIdentity({
|
|
204
169
|
platform: params.platform,
|
|
205
|
-
platformId: params.platformId
|
|
206
|
-
tenantId: params.tenantId,
|
|
207
|
-
agentId: "plugin"
|
|
170
|
+
platformId: params.platformId
|
|
208
171
|
})
|
|
209
172
|
}),
|
|
210
173
|
defineTool({
|
|
@@ -212,12 +175,10 @@ const plugin = {
|
|
|
212
175
|
description: "Add an observation or note about a contact",
|
|
213
176
|
parameters: Type.Object({
|
|
214
177
|
identityId: Type.String(),
|
|
215
|
-
tenantId: Type.String(),
|
|
216
178
|
content: Type.String(),
|
|
217
179
|
category: Type.Optional(Type.String({ description: "observation, preference, relationship, context, or warning" }))
|
|
218
180
|
}),
|
|
219
|
-
handler: (params) =>
|
|
220
|
-
tenantId: params.tenantId,
|
|
181
|
+
handler: (params) => client.addIdentityNote(params.identityId, {
|
|
221
182
|
content: params.content,
|
|
222
183
|
category: params.category,
|
|
223
184
|
changedBy: {
|
|
@@ -231,12 +192,10 @@ const plugin = {
|
|
|
231
192
|
description: "Add or remove a tag on an identity",
|
|
232
193
|
parameters: Type.Object({
|
|
233
194
|
identityId: Type.String(),
|
|
234
|
-
tenantId: Type.String(),
|
|
235
195
|
tag: Type.String(),
|
|
236
196
|
action: Type.String({ description: "'add' or 'remove'" })
|
|
237
197
|
}),
|
|
238
|
-
handler: (params) =>
|
|
239
|
-
tenantId: params.tenantId,
|
|
198
|
+
handler: (params) => client.tagIdentity(params.identityId, {
|
|
240
199
|
tag: params.tag,
|
|
241
200
|
action: params.action,
|
|
242
201
|
changedBy: {
|
|
@@ -250,25 +209,18 @@ const plugin = {
|
|
|
250
209
|
description: "Get full changelog for an identity — all versions, diffs, who changed what",
|
|
251
210
|
parameters: Type.Object({
|
|
252
211
|
identityId: Type.String(),
|
|
253
|
-
tenantId: Type.String(),
|
|
254
212
|
limit: Type.Optional(Type.Number())
|
|
255
213
|
}),
|
|
256
|
-
handler:
|
|
257
|
-
const qs = new URLSearchParams({ tenantId: params.tenantId });
|
|
258
|
-
if (params.limit) qs.set("limit", String(Number(params.limit)));
|
|
259
|
-
return http.request("GET", `/internal/identity/${encodeURIComponent(params.identityId)}/changelog?${qs.toString()}`);
|
|
260
|
-
}
|
|
214
|
+
handler: (params) => client.getIdentityChangelog(params.identityId, { limit: params.limit })
|
|
261
215
|
}),
|
|
262
216
|
defineTool({
|
|
263
217
|
name: "rollback_identity",
|
|
264
218
|
description: "Revert an identity to a previous version",
|
|
265
219
|
parameters: Type.Object({
|
|
266
220
|
identityId: Type.String(),
|
|
267
|
-
tenantId: Type.String(),
|
|
268
221
|
targetVersion: Type.Number()
|
|
269
222
|
}),
|
|
270
|
-
handler: (params) =>
|
|
271
|
-
tenantId: params.tenantId,
|
|
223
|
+
handler: (params) => client.rollbackIdentity(params.identityId, {
|
|
272
224
|
targetVersion: params.targetVersion,
|
|
273
225
|
changedBy: {
|
|
274
226
|
type: "agent",
|
|
@@ -282,14 +234,12 @@ const plugin = {
|
|
|
282
234
|
parameters: Type.Object({
|
|
283
235
|
platform: Type.String(),
|
|
284
236
|
senderId: Type.String(),
|
|
285
|
-
channelId: Type.Optional(Type.String())
|
|
286
|
-
tenantId: Type.String()
|
|
237
|
+
channelId: Type.Optional(Type.String())
|
|
287
238
|
}),
|
|
288
|
-
handler: (params) =>
|
|
239
|
+
handler: (params) => client.enforcePolicy({
|
|
289
240
|
platform: params.platform,
|
|
290
241
|
senderId: params.senderId,
|
|
291
|
-
channelId: params.channelId
|
|
292
|
-
tenantId: params.tenantId
|
|
242
|
+
channelId: params.channelId
|
|
293
243
|
})
|
|
294
244
|
}),
|
|
295
245
|
defineTool({
|
|
@@ -298,14 +248,12 @@ const plugin = {
|
|
|
298
248
|
parameters: Type.Object({
|
|
299
249
|
platform: Type.String(),
|
|
300
250
|
senderId: Type.String(),
|
|
301
|
-
toolName: Type.String()
|
|
302
|
-
tenantId: Type.String()
|
|
251
|
+
toolName: Type.String()
|
|
303
252
|
}),
|
|
304
|
-
handler: (params) =>
|
|
253
|
+
handler: (params) => client.checkToolPermission({
|
|
305
254
|
platform: params.platform,
|
|
306
255
|
senderId: params.senderId,
|
|
307
|
-
toolName: params.toolName
|
|
308
|
-
tenantId: params.tenantId
|
|
256
|
+
toolName: params.toolName
|
|
309
257
|
})
|
|
310
258
|
})
|
|
311
259
|
];
|
|
@@ -330,19 +278,14 @@ const plugin = {
|
|
|
330
278
|
return;
|
|
331
279
|
}
|
|
332
280
|
try {
|
|
333
|
-
const
|
|
334
|
-
const agentId = ctx.agentId ?? "";
|
|
335
|
-
const resolveResult = await http.request("POST", "/internal/identity/resolve", {
|
|
281
|
+
const resolveResult = await client.resolveIdentity({
|
|
336
282
|
platform,
|
|
337
|
-
platformId: senderId
|
|
338
|
-
tenantId,
|
|
339
|
-
agentId
|
|
283
|
+
platformId: senderId
|
|
340
284
|
});
|
|
341
285
|
setCached(cacheKey, {
|
|
342
|
-
...await
|
|
286
|
+
...await client.enforcePolicy({
|
|
343
287
|
platform,
|
|
344
|
-
senderId
|
|
345
|
-
tenantId
|
|
288
|
+
senderId
|
|
346
289
|
}),
|
|
347
290
|
accessAllowed: resolveResult.accessAllowed
|
|
348
291
|
});
|
|
@@ -381,17 +324,15 @@ const plugin = {
|
|
|
381
324
|
}, { priority: 100 });
|
|
382
325
|
api.on("after_tool_call", async (...args) => {
|
|
383
326
|
const event = args[0];
|
|
384
|
-
const
|
|
385
|
-
const sessionKey = ctx.sessionKey;
|
|
327
|
+
const sessionKey = args[1].sessionKey;
|
|
386
328
|
if (!sessionKey) return;
|
|
387
329
|
const perms = getCached(sessionKey);
|
|
388
330
|
if (!perms?.identityId) return;
|
|
389
331
|
try {
|
|
390
|
-
await
|
|
332
|
+
await client.checkToolPermission({
|
|
391
333
|
platform: "tool_audit",
|
|
392
334
|
senderId: perms.identityId,
|
|
393
|
-
toolName: event.toolName
|
|
394
|
-
tenantId: ctx.tenantId ?? ""
|
|
335
|
+
toolName: event.toolName
|
|
395
336
|
});
|
|
396
337
|
} catch (e) {
|
|
397
338
|
log.error(`Audit logging failed: ${e.message}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfe.ai/openclaw-identity",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "OpenClaw identity plugin — identity resolution, access gating, permission enforcement",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/plugin.js",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@sinclair/typebox": "^0.34.48",
|
|
31
|
-
"@alfe.ai/
|
|
31
|
+
"@alfe.ai/agent-api-client": "0.0.9",
|
|
32
|
+
"@alfe.ai/config": "0.0.8"
|
|
32
33
|
},
|
|
33
34
|
"license": "UNLICENSED",
|
|
34
35
|
"scripts": {
|