@bopen-io/clawnet-plugin 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/constants.js +4 -7
- package/dist/constants.js.map +2 -2
- package/dist/ui/index.js +12 -6
- package/dist/ui/index.js.map +2 -2
- package/dist/worker.js +133 -56
- package/dist/worker.js.map +2 -2
- package/package.json +1 -1
package/dist/worker.js
CHANGED
|
@@ -6239,8 +6239,7 @@ function createClawNetClient(config) {
|
|
|
6239
6239
|
|
|
6240
6240
|
// src/constants.ts
|
|
6241
6241
|
var JOB_KEYS = {
|
|
6242
|
-
sync: "clawnet-sync"
|
|
6243
|
-
clawnetSync: "clawnet-sync"
|
|
6242
|
+
sync: "clawnet-sync"
|
|
6244
6243
|
};
|
|
6245
6244
|
var TOOL_NAMES = {
|
|
6246
6245
|
agentLookup: "agent-lookup",
|
|
@@ -6248,14 +6247,12 @@ var TOOL_NAMES = {
|
|
|
6248
6247
|
fleetOverview: "fleet-overview"
|
|
6249
6248
|
};
|
|
6250
6249
|
var STREAM_CHANNELS = {
|
|
6251
|
-
fleetStatus: "fleet-status",
|
|
6252
|
-
syncProgress: "sync-progress"
|
|
6250
|
+
fleetStatus: "clawnet:fleet-status",
|
|
6251
|
+
syncProgress: "clawnet:sync-progress"
|
|
6253
6252
|
};
|
|
6254
6253
|
var ENTITY_TYPES = {
|
|
6255
6254
|
agent: "clawnet-agent",
|
|
6256
|
-
skill: "clawnet-skill"
|
|
6257
|
-
clawnetAgent: "clawnet-agent",
|
|
6258
|
-
clawnetSkill: "clawnet-skill"
|
|
6255
|
+
skill: "clawnet-skill"
|
|
6259
6256
|
};
|
|
6260
6257
|
var DATA_KEYS = {
|
|
6261
6258
|
clawnetAgents: "clawnet-agents",
|
|
@@ -6272,6 +6269,11 @@ var STATE_KEYS = {
|
|
|
6272
6269
|
syncCursor: "clawnet-sync-cursor",
|
|
6273
6270
|
clawnetLink: "clawnet-link"
|
|
6274
6271
|
};
|
|
6272
|
+
var DEFAULT_CONFIG = {
|
|
6273
|
+
clawnetApiUrl: "https://clawnet.sh",
|
|
6274
|
+
clawnetApiKey: "",
|
|
6275
|
+
syncIntervalMinutes: 15
|
|
6276
|
+
};
|
|
6275
6277
|
|
|
6276
6278
|
// src/worker.ts
|
|
6277
6279
|
var currentContext = null;
|
|
@@ -6317,7 +6319,7 @@ async function performSync(ctx, streamProgress) {
|
|
|
6317
6319
|
const config = await getConfig(ctx);
|
|
6318
6320
|
const apiKey = await resolveApiKey(ctx, config);
|
|
6319
6321
|
const client = createClawNetClient({
|
|
6320
|
-
baseUrl: config.clawnetApiUrl ||
|
|
6322
|
+
baseUrl: config.clawnetApiUrl || DEFAULT_CONFIG.clawnetApiUrl,
|
|
6321
6323
|
apiKey,
|
|
6322
6324
|
fetchFn: ctx.http.fetch.bind(ctx.http)
|
|
6323
6325
|
});
|
|
@@ -6333,19 +6335,23 @@ async function performSync(ctx, streamProgress) {
|
|
|
6333
6335
|
message: "Fetching agents from ClawNet registry..."
|
|
6334
6336
|
});
|
|
6335
6337
|
}
|
|
6336
|
-
const agentResponse = await client.listAgents();
|
|
6337
6338
|
let agentCount = 0;
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6339
|
+
let agentCursor;
|
|
6340
|
+
do {
|
|
6341
|
+
const agentResponse = await client.listAgents({ cursor: agentCursor });
|
|
6342
|
+
for (const agent of agentResponse.agents) {
|
|
6343
|
+
await ctx.entities.upsert({
|
|
6344
|
+
entityType: ENTITY_TYPES.agent,
|
|
6345
|
+
scopeKind: "instance",
|
|
6346
|
+
externalId: agent.slug || agent._id,
|
|
6347
|
+
title: agent.displayName || agent.name,
|
|
6348
|
+
status: agent.deleted ? "deleted" : "active",
|
|
6349
|
+
data: agent
|
|
6350
|
+
});
|
|
6351
|
+
agentCount++;
|
|
6352
|
+
}
|
|
6353
|
+
agentCursor = agentResponse.hasMore ? agentResponse.cursor : void 0;
|
|
6354
|
+
} while (agentCursor);
|
|
6349
6355
|
if (streamProgress) {
|
|
6350
6356
|
ctx.streams.emit(STREAM_CHANNELS.syncProgress, {
|
|
6351
6357
|
phase: "agents",
|
|
@@ -6361,19 +6367,23 @@ async function performSync(ctx, streamProgress) {
|
|
|
6361
6367
|
message: "Fetching skills from ClawNet registry..."
|
|
6362
6368
|
});
|
|
6363
6369
|
}
|
|
6364
|
-
const skillResponse = await client.listSkills();
|
|
6365
6370
|
let skillCount = 0;
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6371
|
+
let skillCursor;
|
|
6372
|
+
do {
|
|
6373
|
+
const skillResponse = await client.listSkills({ cursor: skillCursor });
|
|
6374
|
+
for (const skill of skillResponse.skills) {
|
|
6375
|
+
await ctx.entities.upsert({
|
|
6376
|
+
entityType: ENTITY_TYPES.skill,
|
|
6377
|
+
scopeKind: "instance",
|
|
6378
|
+
externalId: skill.slug || skill._id,
|
|
6379
|
+
title: skill.name,
|
|
6380
|
+
status: "available",
|
|
6381
|
+
data: skill
|
|
6382
|
+
});
|
|
6383
|
+
skillCount++;
|
|
6384
|
+
}
|
|
6385
|
+
skillCursor = skillResponse.hasMore ? skillResponse.cursor : void 0;
|
|
6386
|
+
} while (skillCursor);
|
|
6377
6387
|
if (streamProgress) {
|
|
6378
6388
|
ctx.streams.emit(STREAM_CHANNELS.syncProgress, {
|
|
6379
6389
|
phase: "skills",
|
|
@@ -6407,7 +6417,7 @@ async function performSync(ctx, streamProgress) {
|
|
|
6407
6417
|
return cursor;
|
|
6408
6418
|
}
|
|
6409
6419
|
function registerJobHandlers(ctx) {
|
|
6410
|
-
ctx.jobs.register(JOB_KEYS.
|
|
6420
|
+
ctx.jobs.register(JOB_KEYS.sync, async (job) => {
|
|
6411
6421
|
ctx.logger.info("Starting scheduled ClawNet sync", {
|
|
6412
6422
|
runId: job.runId,
|
|
6413
6423
|
trigger: job.trigger
|
|
@@ -6452,7 +6462,7 @@ function registerEventHandlers(ctx) {
|
|
|
6452
6462
|
const agent = await ctx.agents.get(event.entityId, event.companyId);
|
|
6453
6463
|
if (!agent) return;
|
|
6454
6464
|
const clawnetAgents = await ctx.entities.list({
|
|
6455
|
-
entityType: ENTITY_TYPES.
|
|
6465
|
+
entityType: ENTITY_TYPES.agent,
|
|
6456
6466
|
limit: 200
|
|
6457
6467
|
});
|
|
6458
6468
|
const matchingTemplate = clawnetAgents.find((entity) => {
|
|
@@ -6482,15 +6492,15 @@ function registerEventHandlers(ctx) {
|
|
|
6482
6492
|
}
|
|
6483
6493
|
function registerDataHandlers(ctx) {
|
|
6484
6494
|
ctx.data.register(DATA_KEYS.clawnetAgents, async (params) => {
|
|
6485
|
-
const { search, limit } = getListParams(params);
|
|
6486
|
-
|
|
6487
|
-
entityType: ENTITY_TYPES.
|
|
6495
|
+
const { search, page, limit } = getListParams(params);
|
|
6496
|
+
let entities = await ctx.entities.list({
|
|
6497
|
+
entityType: ENTITY_TYPES.agent,
|
|
6488
6498
|
limit,
|
|
6489
6499
|
offset: 0
|
|
6490
6500
|
});
|
|
6491
6501
|
if (search) {
|
|
6492
6502
|
const term = search.toLowerCase();
|
|
6493
|
-
|
|
6503
|
+
entities = entities.filter((entity) => {
|
|
6494
6504
|
const titleMatch = entity.title?.toLowerCase().includes(term);
|
|
6495
6505
|
const data = entity.data;
|
|
6496
6506
|
const nameMatch = typeof data.name === "string" && data.name.toLowerCase().includes(term);
|
|
@@ -6498,18 +6508,36 @@ function registerDataHandlers(ctx) {
|
|
|
6498
6508
|
return titleMatch || nameMatch || descMatch;
|
|
6499
6509
|
});
|
|
6500
6510
|
}
|
|
6501
|
-
|
|
6511
|
+
const agents = entities.map((entity) => {
|
|
6512
|
+
const d = entity.data;
|
|
6513
|
+
return {
|
|
6514
|
+
id: entity.externalId ?? entity.id,
|
|
6515
|
+
slug: d.slug ?? entity.externalId ?? "",
|
|
6516
|
+
displayName: entity.title ?? d.displayName ?? d.name ?? "",
|
|
6517
|
+
description: d.description ?? null,
|
|
6518
|
+
model: d.model ?? null,
|
|
6519
|
+
color: d.color ?? null,
|
|
6520
|
+
starCount: d.starCount ?? 0,
|
|
6521
|
+
trustScore: null,
|
|
6522
|
+
// Not yet available from ClawNet
|
|
6523
|
+
attestations: [],
|
|
6524
|
+
// Not yet available from ClawNet
|
|
6525
|
+
skills: Array.isArray(d.skills) ? d.skills : [],
|
|
6526
|
+
createdAt: entity.createdAt
|
|
6527
|
+
};
|
|
6528
|
+
});
|
|
6529
|
+
return { agents, total: agents.length, page, limit };
|
|
6502
6530
|
});
|
|
6503
6531
|
ctx.data.register(DATA_KEYS.clawnetSkills, async (params) => {
|
|
6504
6532
|
const { search, limit } = getListParams(params);
|
|
6505
|
-
|
|
6506
|
-
entityType: ENTITY_TYPES.
|
|
6533
|
+
let entities = await ctx.entities.list({
|
|
6534
|
+
entityType: ENTITY_TYPES.skill,
|
|
6507
6535
|
limit,
|
|
6508
6536
|
offset: 0
|
|
6509
6537
|
});
|
|
6510
6538
|
if (search) {
|
|
6511
6539
|
const term = search.toLowerCase();
|
|
6512
|
-
|
|
6540
|
+
entities = entities.filter((entity) => {
|
|
6513
6541
|
const titleMatch = entity.title?.toLowerCase().includes(term);
|
|
6514
6542
|
const data = entity.data;
|
|
6515
6543
|
const nameMatch = typeof data.name === "string" && data.name.toLowerCase().includes(term);
|
|
@@ -6517,7 +6545,18 @@ function registerDataHandlers(ctx) {
|
|
|
6517
6545
|
return titleMatch || nameMatch || descMatch;
|
|
6518
6546
|
});
|
|
6519
6547
|
}
|
|
6520
|
-
|
|
6548
|
+
const skills = entities.map((entity) => {
|
|
6549
|
+
const d = entity.data;
|
|
6550
|
+
return {
|
|
6551
|
+
id: entity.externalId ?? entity.id,
|
|
6552
|
+
slug: d.slug ?? entity.externalId ?? "",
|
|
6553
|
+
displayName: entity.title ?? d.displayName ?? d.name ?? "",
|
|
6554
|
+
description: d.description ?? null,
|
|
6555
|
+
category: d.category ?? null,
|
|
6556
|
+
starCount: d.starCount ?? 0
|
|
6557
|
+
};
|
|
6558
|
+
});
|
|
6559
|
+
return { skills, total: skills.length };
|
|
6521
6560
|
});
|
|
6522
6561
|
ctx.data.register(DATA_KEYS.syncStatus, async () => {
|
|
6523
6562
|
const cursor = await getSyncCursor(ctx);
|
|
@@ -6536,7 +6575,7 @@ function registerDataHandlers(ctx) {
|
|
|
6536
6575
|
const [paperclipAgents, clawnetEntities] = await Promise.all([
|
|
6537
6576
|
ctx.agents.list({ companyId, limit: 200, offset: 0 }),
|
|
6538
6577
|
ctx.entities.list({
|
|
6539
|
-
entityType: ENTITY_TYPES.
|
|
6578
|
+
entityType: ENTITY_TYPES.agent,
|
|
6540
6579
|
limit: 200,
|
|
6541
6580
|
offset: 0
|
|
6542
6581
|
})
|
|
@@ -6549,6 +6588,23 @@ function registerDataHandlers(ctx) {
|
|
|
6549
6588
|
stateKey: STATE_KEYS.clawnetLink
|
|
6550
6589
|
});
|
|
6551
6590
|
const clawnetMatch = linkState ? clawnetEntities.find((e) => e.externalId === linkState.clawnetExternalId) : null;
|
|
6591
|
+
let clawnetTemplate = null;
|
|
6592
|
+
if (clawnetMatch) {
|
|
6593
|
+
const d = clawnetMatch.data;
|
|
6594
|
+
clawnetTemplate = {
|
|
6595
|
+
id: clawnetMatch.externalId ?? clawnetMatch.id,
|
|
6596
|
+
slug: d.slug ?? clawnetMatch.externalId ?? "",
|
|
6597
|
+
displayName: clawnetMatch.title ?? d.displayName ?? d.name ?? "",
|
|
6598
|
+
description: d.description ?? null,
|
|
6599
|
+
model: d.model ?? null,
|
|
6600
|
+
color: d.color ?? null,
|
|
6601
|
+
starCount: d.starCount ?? 0,
|
|
6602
|
+
trustScore: null,
|
|
6603
|
+
attestations: [],
|
|
6604
|
+
skills: Array.isArray(d.skills) ? d.skills : [],
|
|
6605
|
+
createdAt: clawnetMatch.createdAt
|
|
6606
|
+
};
|
|
6607
|
+
}
|
|
6552
6608
|
return {
|
|
6553
6609
|
paperclipAgent: {
|
|
6554
6610
|
id: agent.id,
|
|
@@ -6557,11 +6613,7 @@ function registerDataHandlers(ctx) {
|
|
|
6557
6613
|
role: agent.role
|
|
6558
6614
|
},
|
|
6559
6615
|
clawnetLink: linkState,
|
|
6560
|
-
clawnetTemplate
|
|
6561
|
-
externalId: clawnetMatch.externalId,
|
|
6562
|
-
title: clawnetMatch.title,
|
|
6563
|
-
data: clawnetMatch.data
|
|
6564
|
-
} : null
|
|
6616
|
+
clawnetTemplate
|
|
6565
6617
|
};
|
|
6566
6618
|
})
|
|
6567
6619
|
);
|
|
@@ -6604,7 +6656,7 @@ function registerActionHandlers(ctx) {
|
|
|
6604
6656
|
throw new Error(`Agent ${agentId} not found`);
|
|
6605
6657
|
}
|
|
6606
6658
|
const clawnetEntities = await ctx.entities.list({
|
|
6607
|
-
entityType: ENTITY_TYPES.
|
|
6659
|
+
entityType: ENTITY_TYPES.agent,
|
|
6608
6660
|
externalId: clawnetExternalId,
|
|
6609
6661
|
limit: 1
|
|
6610
6662
|
});
|
|
@@ -6637,6 +6689,27 @@ function registerActionHandlers(ctx) {
|
|
|
6637
6689
|
templateTitle: clawnetEntities[0].title
|
|
6638
6690
|
};
|
|
6639
6691
|
});
|
|
6692
|
+
ctx.actions.register(ACTION_KEYS.validateConfig, async (_params) => {
|
|
6693
|
+
const config = await getConfig(ctx);
|
|
6694
|
+
const errors = [];
|
|
6695
|
+
if (config.clawnetApiUrl) {
|
|
6696
|
+
try {
|
|
6697
|
+
new URL(config.clawnetApiUrl);
|
|
6698
|
+
} catch {
|
|
6699
|
+
errors.push("Invalid API URL");
|
|
6700
|
+
}
|
|
6701
|
+
}
|
|
6702
|
+
if (config.clawnetApiKey) {
|
|
6703
|
+
try {
|
|
6704
|
+
await ctx.secrets.resolve(config.clawnetApiKey);
|
|
6705
|
+
} catch (e) {
|
|
6706
|
+
errors.push("API key resolution failed: " + summarizeError(e));
|
|
6707
|
+
}
|
|
6708
|
+
} else {
|
|
6709
|
+
errors.push("No API key configured");
|
|
6710
|
+
}
|
|
6711
|
+
return { ok: errors.length === 0, errors };
|
|
6712
|
+
});
|
|
6640
6713
|
}
|
|
6641
6714
|
function registerToolHandlers(ctx) {
|
|
6642
6715
|
ctx.tools.register(
|
|
@@ -6661,7 +6734,7 @@ function registerToolHandlers(ctx) {
|
|
|
6661
6734
|
return { error: "slug is required" };
|
|
6662
6735
|
}
|
|
6663
6736
|
const entities = await ctx.entities.list({
|
|
6664
|
-
entityType: ENTITY_TYPES.
|
|
6737
|
+
entityType: ENTITY_TYPES.agent,
|
|
6665
6738
|
externalId: slug,
|
|
6666
6739
|
limit: 1
|
|
6667
6740
|
});
|
|
@@ -6673,7 +6746,7 @@ function registerToolHandlers(ctx) {
|
|
|
6673
6746
|
};
|
|
6674
6747
|
}
|
|
6675
6748
|
const allAgents = await ctx.entities.list({
|
|
6676
|
-
entityType: ENTITY_TYPES.
|
|
6749
|
+
entityType: ENTITY_TYPES.agent,
|
|
6677
6750
|
limit: 200
|
|
6678
6751
|
});
|
|
6679
6752
|
const term = slug.toLowerCase();
|
|
@@ -6722,7 +6795,7 @@ function registerToolHandlers(ctx) {
|
|
|
6722
6795
|
}
|
|
6723
6796
|
const resultLimit = Math.min(maxResults ?? 10, 50);
|
|
6724
6797
|
const allSkills = await ctx.entities.list({
|
|
6725
|
-
entityType: ENTITY_TYPES.
|
|
6798
|
+
entityType: ENTITY_TYPES.skill,
|
|
6726
6799
|
limit: 200
|
|
6727
6800
|
});
|
|
6728
6801
|
const term = query.toLowerCase();
|
|
@@ -6762,8 +6835,8 @@ function registerToolHandlers(ctx) {
|
|
|
6762
6835
|
},
|
|
6763
6836
|
async (_params, runCtx) => {
|
|
6764
6837
|
const [agents, skills, cursor, paperclipAgents] = await Promise.all([
|
|
6765
|
-
ctx.entities.list({ entityType: ENTITY_TYPES.
|
|
6766
|
-
ctx.entities.list({ entityType: ENTITY_TYPES.
|
|
6838
|
+
ctx.entities.list({ entityType: ENTITY_TYPES.agent, limit: 200 }),
|
|
6839
|
+
ctx.entities.list({ entityType: ENTITY_TYPES.skill, limit: 200 }),
|
|
6767
6840
|
getSyncCursor(ctx),
|
|
6768
6841
|
ctx.agents.list({ companyId: runCtx.companyId, limit: 200, offset: 0 })
|
|
6769
6842
|
]);
|
|
@@ -6860,6 +6933,10 @@ var plugin = definePlugin({
|
|
|
6860
6933
|
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
6861
6934
|
errors.push("clawnetApiUrl must use http or https protocol");
|
|
6862
6935
|
}
|
|
6936
|
+
const hostname = url.hostname;
|
|
6937
|
+
if (hostname === "localhost" || hostname.startsWith("127.") || hostname.startsWith("10.") || hostname.startsWith("192.168.") || hostname.startsWith("169.254.") || /^172\.(1[6-9]|2\d|3[01])\./.test(hostname) || hostname.endsWith(".internal") || hostname.endsWith(".local")) {
|
|
6938
|
+
errors.push("clawnetApiUrl must not point to a private or internal address");
|
|
6939
|
+
}
|
|
6863
6940
|
} catch {
|
|
6864
6941
|
errors.push("clawnetApiUrl is not a valid URL");
|
|
6865
6942
|
}
|
|
@@ -6883,7 +6960,7 @@ var plugin = definePlugin({
|
|
|
6883
6960
|
}
|
|
6884
6961
|
}
|
|
6885
6962
|
if (!typed.clawnetApiUrl) {
|
|
6886
|
-
warnings.push(
|
|
6963
|
+
warnings.push(`clawnetApiUrl not set; will default to ${DEFAULT_CONFIG.clawnetApiUrl}`);
|
|
6887
6964
|
}
|
|
6888
6965
|
return {
|
|
6889
6966
|
ok: errors.length === 0,
|