@web42/cli 0.2.7 → 0.2.9

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 (58) hide show
  1. package/dist/commands/search.js +20 -15
  2. package/dist/commands/send.js +75 -41
  3. package/dist/commands/serve.d.ts +1 -1
  4. package/dist/commands/serve.js +160 -114
  5. package/dist/index.js +1 -19
  6. package/dist/version.d.ts +1 -1
  7. package/dist/version.js +1 -1
  8. package/package.json +1 -1
  9. package/dist/commands/config.d.ts +0 -2
  10. package/dist/commands/config.js +0 -27
  11. package/dist/commands/init.d.ts +0 -2
  12. package/dist/commands/init.js +0 -451
  13. package/dist/commands/install.d.ts +0 -3
  14. package/dist/commands/install.js +0 -231
  15. package/dist/commands/list.d.ts +0 -3
  16. package/dist/commands/list.js +0 -22
  17. package/dist/commands/pack.d.ts +0 -2
  18. package/dist/commands/pack.js +0 -210
  19. package/dist/commands/pull.d.ts +0 -2
  20. package/dist/commands/pull.js +0 -202
  21. package/dist/commands/push.d.ts +0 -2
  22. package/dist/commands/push.js +0 -374
  23. package/dist/commands/remix.d.ts +0 -2
  24. package/dist/commands/remix.js +0 -49
  25. package/dist/commands/sync.d.ts +0 -2
  26. package/dist/commands/sync.js +0 -98
  27. package/dist/commands/uninstall.d.ts +0 -3
  28. package/dist/commands/uninstall.js +0 -54
  29. package/dist/commands/update.d.ts +0 -3
  30. package/dist/commands/update.js +0 -59
  31. package/dist/platforms/base.d.ts +0 -82
  32. package/dist/platforms/base.js +0 -1
  33. package/dist/platforms/claude/__tests__/adapter.test.d.ts +0 -1
  34. package/dist/platforms/claude/__tests__/adapter.test.js +0 -257
  35. package/dist/platforms/claude/__tests__/security.test.d.ts +0 -1
  36. package/dist/platforms/claude/__tests__/security.test.js +0 -166
  37. package/dist/platforms/claude/adapter.d.ts +0 -34
  38. package/dist/platforms/claude/adapter.js +0 -525
  39. package/dist/platforms/claude/security.d.ts +0 -15
  40. package/dist/platforms/claude/security.js +0 -67
  41. package/dist/platforms/claude/templates.d.ts +0 -5
  42. package/dist/platforms/claude/templates.js +0 -22
  43. package/dist/platforms/openclaw/adapter.d.ts +0 -12
  44. package/dist/platforms/openclaw/adapter.js +0 -476
  45. package/dist/platforms/openclaw/templates.d.ts +0 -7
  46. package/dist/platforms/openclaw/templates.js +0 -369
  47. package/dist/platforms/registry.d.ts +0 -6
  48. package/dist/platforms/registry.js +0 -32
  49. package/dist/types/sync.d.ts +0 -74
  50. package/dist/types/sync.js +0 -7
  51. package/dist/utils/bundled-skills.d.ts +0 -6
  52. package/dist/utils/bundled-skills.js +0 -29
  53. package/dist/utils/secrets.d.ts +0 -32
  54. package/dist/utils/secrets.js +0 -118
  55. package/dist/utils/skill.d.ts +0 -6
  56. package/dist/utils/skill.js +0 -42
  57. package/dist/utils/sync.d.ts +0 -14
  58. package/dist/utils/sync.js +0 -242
@@ -2,6 +2,16 @@ import { Command } from "commander";
2
2
  import chalk from "chalk";
3
3
  import ora from "ora";
4
4
  import { apiGet } from "../utils/api.js";
5
+ function getCardName(card) {
6
+ return card?.name ?? "Untitled Agent";
7
+ }
8
+ function getCardDescription(card) {
9
+ return card?.description ?? "";
10
+ }
11
+ function getMarketplacePrice(card) {
12
+ const ext = card?.capabilities?.extensions?.find((e) => e.uri === "https://web42.ai/ext/marketplace/v1");
13
+ return ext?.params?.price_cents ?? 0;
14
+ }
5
15
  function truncate(str, max) {
6
16
  if (str.length <= max)
7
17
  return str;
@@ -10,7 +20,6 @@ function truncate(str, max) {
10
20
  export const searchCommand = new Command("search")
11
21
  .description("Search the marketplace for agents")
12
22
  .argument("<query>", "Search query")
13
- .option("-p, --platform <platform>", "Filter results by platform (e.g. openclaw)")
14
23
  .option("-l, --limit <number>", "Max results to show", "10")
15
24
  .action(async (query, opts) => {
16
25
  const spinner = ora(`Searching for "${query}"...`).start();
@@ -26,24 +35,20 @@ export const searchCommand = new Command("search")
26
35
  console.log(chalk.bold(`Found ${agents.length} agent(s) for "${query}":`));
27
36
  console.log();
28
37
  for (const agent of results) {
38
+ const name = getCardName(agent.agent_card);
39
+ const description = getCardDescription(agent.agent_card);
40
+ const priceCents = getMarketplacePrice(agent.agent_card);
29
41
  const ref = `@${agent.owner.username}/${agent.slug}`;
30
42
  const stars = agent.stars_count > 0 ? chalk.yellow(` \u2605 ${agent.stars_count}`) : "";
31
- const price = agent.price_cents > 0
32
- ? chalk.green(` $${(agent.price_cents / 100).toFixed(2)}`)
43
+ const price = priceCents > 0
44
+ ? chalk.green(` $${(priceCents / 100).toFixed(2)}`)
33
45
  : chalk.dim(" Free");
34
- console.log(` ${chalk.cyan.bold(agent.name)}${stars}${price}`);
46
+ console.log(` ${chalk.cyan.bold(name)}${stars}${price}`);
35
47
  console.log(` ${chalk.dim(ref)}`);
36
- if (agent.description) {
37
- console.log(` ${truncate(agent.description, 80)}`);
38
- }
39
- const platform = agent.manifest?.platform ?? "openclaw";
40
- if (agent.price_cents > 0) {
41
- const siteUrl = process.env.WEB42_API_URL ?? "https://web42.ai";
42
- console.log(chalk.dim(` Purchase: ${siteUrl}/${agent.owner.username}/${agent.slug}`));
43
- }
44
- else {
45
- console.log(chalk.dim(` Install: web42 ${platform} install ${ref}`));
48
+ if (description) {
49
+ console.log(` ${truncate(description, 80)}`);
46
50
  }
51
+ console.log(chalk.dim(` Send: web42 send ${agent.slug} "hello"`));
47
52
  console.log();
48
53
  }
49
54
  if (agents.length > limit) {
@@ -52,7 +57,7 @@ export const searchCommand = new Command("search")
52
57
  }
53
58
  catch (error) {
54
59
  spinner.fail("Search failed");
55
- console.error(chalk.red(error.message));
60
+ console.error(chalk.red(String(error)));
56
61
  process.exit(1);
57
62
  }
58
63
  });
@@ -3,44 +3,85 @@ import chalk from "chalk";
3
3
  import ora from "ora";
4
4
  import { v4 as uuidv4 } from "uuid";
5
5
  import { requireAuth, setConfigValue, getConfigValue } from "../utils/config.js";
6
- import { apiGet } from "../utils/api.js";
6
+ import { apiPost } from "../utils/api.js";
7
+ function isUrl(s) {
8
+ return s.startsWith("http://") || s.startsWith("https://");
9
+ }
10
+ function getCachedToken(slug) {
11
+ const raw = getConfigValue(`agentTokens.${slug}`);
12
+ if (!raw)
13
+ return null;
14
+ try {
15
+ const cached = typeof raw === "string" ? JSON.parse(raw) : raw;
16
+ if (new Date(cached.expiresAt) <= new Date())
17
+ return null;
18
+ return cached;
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
7
24
  export const sendCommand = new Command("send")
8
- .description("Send a message to a live web42 agent")
9
- .argument("<agent>", "Agent handle, e.g. @javier/gilfoyle")
25
+ .description("Send a message to an A2A agent")
26
+ .argument("<agent>", "Agent slug (e.g. my-agent) or direct URL (http://localhost:3001)")
10
27
  .argument("<message>", "Message to send")
11
28
  .option("--new", "Start a new conversation (clears saved context)")
12
- .action(async (agentHandle, userMessage, opts) => {
29
+ .option("--context <id>", "Use a specific context ID")
30
+ .action(async (agent, userMessage, opts) => {
13
31
  const config = requireAuth();
14
- // 1. Parse @user/slug
15
- const match = agentHandle.match(/^@?([\w-]+)\/([\w-]+)$/);
16
- if (!match) {
17
- console.error(chalk.red("Invalid agent handle. Expected format: @user/agent-slug"));
18
- process.exit(1);
19
- }
20
- const [, username, slug] = match;
21
- // 2. Look up agent A2A URL from marketplace
22
- const spinner = ora(`Looking up @${username}/${slug}...`).start();
23
- let a2aData;
24
- try {
25
- a2aData = await apiGet(`/api/agents/${slug}/a2a`);
32
+ let agentUrl;
33
+ let bearerToken;
34
+ let agentKey;
35
+ if (isUrl(agent)) {
36
+ // Direct URL mode — local development, no handshake needed
37
+ agentUrl = agent;
38
+ bearerToken = config.token;
39
+ agentKey = new URL(agent).host.replace(/[.:]/g, "-");
26
40
  }
27
- catch {
28
- spinner.fail(`Agent @${username}/${slug} not found`);
29
- process.exit(1);
41
+ else {
42
+ // Slug mode — handshake with Web42 platform
43
+ agentKey = agent;
44
+ const cached = getCachedToken(agent);
45
+ if (cached) {
46
+ agentUrl = cached.agentUrl;
47
+ bearerToken = cached.token;
48
+ }
49
+ else {
50
+ const spinner = ora(`Authenticating with ${agent}...`).start();
51
+ try {
52
+ const res = await apiPost("/api/auth/handshake", {
53
+ agentSlug: agent,
54
+ });
55
+ agentUrl = res.agentUrl;
56
+ bearerToken = res.token;
57
+ setConfigValue(`agentTokens.${agent}`, JSON.stringify({
58
+ token: res.token,
59
+ agentUrl: res.agentUrl,
60
+ expiresAt: res.expiresAt,
61
+ }));
62
+ spinner.succeed(`Authenticated with ${agent}`);
63
+ }
64
+ catch (err) {
65
+ spinner.fail(`Failed to authenticate with ${agent}`);
66
+ console.error(chalk.red(String(err)));
67
+ process.exit(1);
68
+ }
69
+ }
30
70
  }
31
- if (!a2aData.a2a_enabled || !a2aData.a2a_url) {
32
- spinner.fail(`@${username}/${slug} is not live. Publisher must run: web42 serve --url <url>`);
33
- process.exit(1);
71
+ // Resolve contextId
72
+ const contextKey = `context.${agentKey}`;
73
+ let contextId;
74
+ if (opts.context) {
75
+ contextId = opts.context;
34
76
  }
35
- spinner.stop();
36
- // 3. Resolve contextId — reuse existing session or start fresh
37
- const contextKey = `context.${username}.${slug}`;
38
- let contextId = getConfigValue(contextKey) ?? uuidv4();
39
- if (opts.new) {
77
+ else if (opts.new) {
40
78
  contextId = uuidv4();
41
79
  }
80
+ else {
81
+ contextId = getConfigValue(contextKey) ?? uuidv4();
82
+ }
42
83
  setConfigValue(contextKey, contextId);
43
- // 4. Dynamically import @a2a-js/sdk client (ESM)
84
+ // Dynamically import @a2a-js/sdk client
44
85
  let ClientFactory;
45
86
  let JsonRpcTransportFactory;
46
87
  let ClientFactoryOptions;
@@ -54,22 +95,18 @@ export const sendCommand = new Command("send")
54
95
  console.error(chalk.red("Failed to load @a2a-js/sdk. Run: pnpm add @a2a-js/sdk"));
55
96
  process.exit(1);
56
97
  }
57
- // 5. Bearer token interceptor
58
- const token = config.token;
59
98
  const bearerInterceptor = {
60
99
  before: async (args) => {
61
- if (!args.options) {
100
+ if (!args.options)
62
101
  args.options = {};
63
- }
64
102
  args.options.serviceParameters = {
65
103
  ...(args.options.serviceParameters ?? {}),
66
- Authorization: `Bearer ${token}`,
104
+ Authorization: `Bearer ${bearerToken}`,
67
105
  };
68
106
  },
69
107
  after: async () => { },
70
108
  };
71
- // 6. Create A2A client
72
- const connectSpinner = ora(`Connecting to @${username}/${slug}...`).start();
109
+ const connectSpinner = ora(`Connecting to ${agentKey}...`).start();
73
110
  let client;
74
111
  try {
75
112
  const factory = new ClientFactory(ClientFactoryOptions.createFrom(ClientFactoryOptions.default, {
@@ -78,18 +115,15 @@ export const sendCommand = new Command("send")
78
115
  interceptors: [bearerInterceptor],
79
116
  },
80
117
  }));
81
- // a2aData.a2a_url is the full JSON-RPC endpoint, e.g. https://foo.ngrok.dev/a2a/jsonrpc
82
- // createFromUrl needs the base URL; it will append /.well-known/agent-card.json itself
83
- const a2aBaseUrl = new URL(a2aData.a2a_url).origin;
118
+ const a2aBaseUrl = new URL(agentUrl).origin;
84
119
  client = await factory.createFromUrl(a2aBaseUrl);
85
120
  connectSpinner.stop();
86
121
  }
87
122
  catch {
88
- connectSpinner.fail(`Could not reach agent at ${a2aData.a2a_url}`);
89
- console.error(chalk.dim("Is the publisher running web42 serve? Is ngrok still active?"));
123
+ connectSpinner.fail(`Could not reach agent at ${agentUrl}`);
124
+ console.error(chalk.dim("Is the agent server running?"));
90
125
  process.exit(1);
91
126
  }
92
- // 7. Stream response to stdout
93
127
  try {
94
128
  const stream = client.sendMessageStream({
95
129
  message: {
@@ -1,2 +1,2 @@
1
- import { Command } from 'commander';
1
+ import { Command } from "commander";
2
2
  export declare const serveCommand: Command;