@bopen-io/clawnet-plugin 0.0.2 → 0.0.3

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/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 || "https://api.clawnet.bopen.io",
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
- for (const agent of agentResponse.agents) {
6339
- await ctx.entities.upsert({
6340
- entityType: ENTITY_TYPES.clawnetAgent,
6341
- scopeKind: "instance",
6342
- externalId: agent.slug || agent._id,
6343
- title: agent.displayName || agent.name,
6344
- status: agent.deleted ? "deleted" : "active",
6345
- data: agent
6346
- });
6347
- agentCount++;
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
- for (const skill of skillResponse.skills) {
6367
- await ctx.entities.upsert({
6368
- entityType: ENTITY_TYPES.clawnetSkill,
6369
- scopeKind: "instance",
6370
- externalId: skill.slug || skill._id,
6371
- title: skill.name,
6372
- status: "available",
6373
- data: skill
6374
- });
6375
- skillCount++;
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.clawnetSync, async (job) => {
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.clawnetAgent,
6465
+ entityType: ENTITY_TYPES.agent,
6456
6466
  limit: 200
6457
6467
  });
6458
6468
  const matchingTemplate = clawnetAgents.find((entity) => {
@@ -6484,7 +6494,7 @@ function registerDataHandlers(ctx) {
6484
6494
  ctx.data.register(DATA_KEYS.clawnetAgents, async (params) => {
6485
6495
  const { search, limit } = getListParams(params);
6486
6496
  const entities = await ctx.entities.list({
6487
- entityType: ENTITY_TYPES.clawnetAgent,
6497
+ entityType: ENTITY_TYPES.agent,
6488
6498
  limit,
6489
6499
  offset: 0
6490
6500
  });
@@ -6503,7 +6513,7 @@ function registerDataHandlers(ctx) {
6503
6513
  ctx.data.register(DATA_KEYS.clawnetSkills, async (params) => {
6504
6514
  const { search, limit } = getListParams(params);
6505
6515
  const entities = await ctx.entities.list({
6506
- entityType: ENTITY_TYPES.clawnetSkill,
6516
+ entityType: ENTITY_TYPES.skill,
6507
6517
  limit,
6508
6518
  offset: 0
6509
6519
  });
@@ -6536,7 +6546,7 @@ function registerDataHandlers(ctx) {
6536
6546
  const [paperclipAgents, clawnetEntities] = await Promise.all([
6537
6547
  ctx.agents.list({ companyId, limit: 200, offset: 0 }),
6538
6548
  ctx.entities.list({
6539
- entityType: ENTITY_TYPES.clawnetAgent,
6549
+ entityType: ENTITY_TYPES.agent,
6540
6550
  limit: 200,
6541
6551
  offset: 0
6542
6552
  })
@@ -6604,7 +6614,7 @@ function registerActionHandlers(ctx) {
6604
6614
  throw new Error(`Agent ${agentId} not found`);
6605
6615
  }
6606
6616
  const clawnetEntities = await ctx.entities.list({
6607
- entityType: ENTITY_TYPES.clawnetAgent,
6617
+ entityType: ENTITY_TYPES.agent,
6608
6618
  externalId: clawnetExternalId,
6609
6619
  limit: 1
6610
6620
  });
@@ -6637,6 +6647,27 @@ function registerActionHandlers(ctx) {
6637
6647
  templateTitle: clawnetEntities[0].title
6638
6648
  };
6639
6649
  });
6650
+ ctx.actions.register(ACTION_KEYS.validateConfig, async (_params) => {
6651
+ const config = await getConfig(ctx);
6652
+ const errors = [];
6653
+ if (config.clawnetApiUrl) {
6654
+ try {
6655
+ new URL(config.clawnetApiUrl);
6656
+ } catch {
6657
+ errors.push("Invalid API URL");
6658
+ }
6659
+ }
6660
+ if (config.clawnetApiKey) {
6661
+ try {
6662
+ await ctx.secrets.resolve(config.clawnetApiKey);
6663
+ } catch (e) {
6664
+ errors.push("API key resolution failed: " + summarizeError(e));
6665
+ }
6666
+ } else {
6667
+ errors.push("No API key configured");
6668
+ }
6669
+ return { ok: errors.length === 0, errors };
6670
+ });
6640
6671
  }
6641
6672
  function registerToolHandlers(ctx) {
6642
6673
  ctx.tools.register(
@@ -6661,7 +6692,7 @@ function registerToolHandlers(ctx) {
6661
6692
  return { error: "slug is required" };
6662
6693
  }
6663
6694
  const entities = await ctx.entities.list({
6664
- entityType: ENTITY_TYPES.clawnetAgent,
6695
+ entityType: ENTITY_TYPES.agent,
6665
6696
  externalId: slug,
6666
6697
  limit: 1
6667
6698
  });
@@ -6673,7 +6704,7 @@ function registerToolHandlers(ctx) {
6673
6704
  };
6674
6705
  }
6675
6706
  const allAgents = await ctx.entities.list({
6676
- entityType: ENTITY_TYPES.clawnetAgent,
6707
+ entityType: ENTITY_TYPES.agent,
6677
6708
  limit: 200
6678
6709
  });
6679
6710
  const term = slug.toLowerCase();
@@ -6722,7 +6753,7 @@ function registerToolHandlers(ctx) {
6722
6753
  }
6723
6754
  const resultLimit = Math.min(maxResults ?? 10, 50);
6724
6755
  const allSkills = await ctx.entities.list({
6725
- entityType: ENTITY_TYPES.clawnetSkill,
6756
+ entityType: ENTITY_TYPES.skill,
6726
6757
  limit: 200
6727
6758
  });
6728
6759
  const term = query.toLowerCase();
@@ -6762,8 +6793,8 @@ function registerToolHandlers(ctx) {
6762
6793
  },
6763
6794
  async (_params, runCtx) => {
6764
6795
  const [agents, skills, cursor, paperclipAgents] = await Promise.all([
6765
- ctx.entities.list({ entityType: ENTITY_TYPES.clawnetAgent, limit: 200 }),
6766
- ctx.entities.list({ entityType: ENTITY_TYPES.clawnetSkill, limit: 200 }),
6796
+ ctx.entities.list({ entityType: ENTITY_TYPES.agent, limit: 200 }),
6797
+ ctx.entities.list({ entityType: ENTITY_TYPES.skill, limit: 200 }),
6767
6798
  getSyncCursor(ctx),
6768
6799
  ctx.agents.list({ companyId: runCtx.companyId, limit: 200, offset: 0 })
6769
6800
  ]);
@@ -6860,6 +6891,10 @@ var plugin = definePlugin({
6860
6891
  if (url.protocol !== "https:" && url.protocol !== "http:") {
6861
6892
  errors.push("clawnetApiUrl must use http or https protocol");
6862
6893
  }
6894
+ const hostname = url.hostname;
6895
+ 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")) {
6896
+ errors.push("clawnetApiUrl must not point to a private or internal address");
6897
+ }
6863
6898
  } catch {
6864
6899
  errors.push("clawnetApiUrl is not a valid URL");
6865
6900
  }
@@ -6883,7 +6918,7 @@ var plugin = definePlugin({
6883
6918
  }
6884
6919
  }
6885
6920
  if (!typed.clawnetApiUrl) {
6886
- warnings.push("clawnetApiUrl not set; will default to https://api.clawnet.bopen.io");
6921
+ warnings.push(`clawnetApiUrl not set; will default to ${DEFAULT_CONFIG.clawnetApiUrl}`);
6887
6922
  }
6888
6923
  return {
6889
6924
  ok: errors.length === 0,