@web42/w42 0.1.3 → 0.1.8

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/README.md CHANGED
@@ -1,73 +1,101 @@
1
1
  # @web42/cli
2
2
 
3
- CLI for the Web42 Agent Marketplace - push, install, and remix OpenClaw agent packages.
3
+ CLI for the Web42 Agent Network authenticate, publish, discover, and interact with A2A agents.
4
4
 
5
5
  ## Installation
6
6
 
7
- To install the CLI globally, run:
8
-
9
- ```
7
+ ```bash
10
8
  npm install -g @web42/cli
11
9
  ```
12
10
 
13
11
  ## Authentication
14
12
 
15
- Authenticate with the marketplace by running:
13
+ ```bash
14
+ web42 auth login # Sign in via GitHub OAuth
15
+ web42 auth logout # Sign out
16
+ web42 auth whoami # Show current user
17
+ ```
18
+
19
+ ## Commands
16
20
 
21
+ ### `web42 search <query>`
22
+
23
+ Search the network for agents.
24
+
25
+ ```bash
26
+ web42 search "data analysis"
27
+ web42 search "image processing" --limit 20
17
28
  ```
18
- web42 login
29
+
30
+ | Option | Description |
31
+ |---|---|
32
+ | `-l, --limit <number>` | Max results to show (default: 10) |
33
+
34
+ ---
35
+
36
+ ### `web42 send <agent> <message>`
37
+
38
+ Send a message to an A2A agent. `<agent>` can be a slug (`@user/agent`) or a direct URL (`http://localhost:3001`).
39
+
40
+ ```bash
41
+ web42 send @alice/summarizer "Summarize this document"
42
+ web42 send http://localhost:3001 "Hello"
19
43
  ```
20
44
 
21
- ## Supported Platforms
45
+ | Option | Description |
46
+ |---|---|
47
+ | `--new` | Start a new conversation (clears saved context) |
48
+ | `--context <id>` | Use a specific context ID |
49
+ | `--task-id <id>` | Reply to a specific task (e.g. one in `input-required` state) |
22
50
 
23
- | Platform | Status |
24
- |-----------|--------------|
25
- | openclaw | Fully Supported |
26
- | claude | Fully Supported |
51
+ ---
27
52
 
28
- ## CLI Commands Reference
53
+ ### `web42 serve`
29
54
 
30
- ### General Commands
55
+ Start a local A2A server for your agent, bridging to an OpenClaw gateway.
31
56
 
32
- | Command | Description |
33
- |--------------|-----------------------------------------|
34
- | `web42 install <agent>` | Install an agent package from the marketplace |
35
- | `web42 push` | Push your agent package to the marketplace |
36
- | `web42 pull` | Pull the latest agent state from the marketplace |
37
- | `web42 list` | List installed agents |
38
- | `web42 update <agent>` | Update an installed agent to the latest version |
39
- | `web42 uninstall <agent>` | Uninstall an agent |
40
- | `web42 search <query>` | Search the marketplace for agents |
41
- | `web42 remix <agent>` | Remix an agent package to your account |
42
- | `web42 sync` | Check sync status between local workspace and the marketplace |
57
+ ```bash
58
+ web42 serve
59
+ web42 serve --port 3001 --url https://my-agent.ngrok.io --verbose
60
+ ```
43
61
 
44
- ### Claude-Specific Examples
62
+ | Option | Description |
63
+ |---|---|
64
+ | `--port <port>` | Port to listen on (default: 4000) |
65
+ | `--url <url>` | Public URL for registration and AgentCard (e.g. from ngrok) |
66
+ | `--openclaw-port <port>` | OpenClaw gateway port (default: 18789) |
67
+ | `--openclaw-token <token>` | OpenClaw gateway auth token (or `OPENCLAW_GATEWAY_TOKEN`) |
68
+ | `--openclaw-agent <id>` | OpenClaw agent ID to target (default: `main`) |
69
+ | `--client-id <id>` | Developer app client ID (or `W42_CLIENT_ID`) |
70
+ | `--client-secret <secret>` | Developer app client secret (or `W42_CLIENT_SECRET`) |
71
+ | `--visibility <vis>` | Marketplace visibility: `public` or `private` |
72
+ | `--verbose` | Enable verbose request/response logging |
45
73
 
46
- - **Initialize a Project:**
47
- ```
48
- web42 init
49
- ```
74
+ ---
50
75
 
51
- - **Pack an Agent:**
52
- ```
53
- web42 pack --agent <name>
54
- ```
76
+ ### `web42 register <url>`
55
77
 
56
- - **Push an Agent:**
57
- ```
58
- web42 push --agent <name>
59
- ```
78
+ Register an agent with the Web42 Network. The URL must serve `/.well-known/agent-card.json`.
60
79
 
61
- - **Install an Agent Globally:**
62
- ```
63
- web42 claude install @user/agent
64
- ```
80
+ ```bash
81
+ web42 register https://my-agent.example.com
82
+ web42 register https://my-agent.example.com --visibility private --tags "nlp,summarization"
83
+ ```
84
+
85
+ | Option | Description |
86
+ |---|---|
87
+ | `--price <cents>` | Price in cents (default: 0 = free) |
88
+ | `--license <license>` | License (e.g. `MIT`, `Apache-2.0`) |
89
+ | `--visibility <vis>` | `public` or `private` (default: `public`) |
90
+ | `--tags <tags>` | Comma-separated tags |
91
+ | `--categories <cats>` | Comma-separated categories |
65
92
 
66
- - **Install an Agent Locally:**
67
- ```
68
- web42 claude install -g @user/agent
69
- ```
93
+ ---
70
94
 
71
- ## Versioning
95
+ ## Environment variables
72
96
 
73
- Version `0.2.0` introduces Claude Code support.
97
+ ```bash
98
+ W42_CLIENT_ID=your-client-id
99
+ W42_CLIENT_SECRET=your-client-secret
100
+ OPENCLAW_GATEWAY_TOKEN=your-openclaw-token
101
+ ```
@@ -5,22 +5,13 @@ import { requireAuth } from "../utils/config.js";
5
5
  export const registerCommand = new Command("register")
6
6
  .description("Register an agent with the Web42 Network")
7
7
  .argument("<url>", "Public URL of the running agent (must serve /.well-known/agent-card.json)")
8
- .option("--price <cents>", "Price in cents (default: 0 = free)")
9
- .option("--license <license>", "License (e.g. MIT, Apache-2.0)")
10
- .option("--visibility <vis>", "Visibility: public or private", "public")
11
- .option("--tags <tags>", "Comma-separated tags")
8
+ .option("--tags <tags>", "Comma-separated discovery tags")
12
9
  .option("--categories <cats>", "Comma-separated categories")
13
10
  .action(async (url, opts) => {
14
11
  const config = requireAuth();
15
12
  const web42ApiUrl = config.apiUrl ?? "http://localhost:3000";
16
13
  const spinner = ora("Registering agent...").start();
17
14
  const body = { url };
18
- if (opts.price !== undefined)
19
- body.price_cents = parseInt(opts.price, 10);
20
- if (opts.license)
21
- body.license = opts.license;
22
- if (opts.visibility)
23
- body.visibility = opts.visibility;
24
15
  if (opts.tags)
25
16
  body.tags = opts.tags.split(",").map((t) => t.trim());
26
17
  if (opts.categories)
@@ -1,18 +1,41 @@
1
- import { Command } from "commander";
1
+ import { ClientFactory, ClientFactoryOptions, JsonRpcTransportFactory, } from "@a2a-js/sdk/client";
2
2
  import chalk from "chalk";
3
+ import { Command } from "commander";
3
4
  import ora from "ora";
4
5
  import { v4 as uuidv4 } from "uuid";
5
- import { requireAuth, setConfigValue, getConfigValue } from "../utils/config.js";
6
6
  import { apiPost } from "../utils/api.js";
7
+ import { getConfigValue, requireAuth, setConfigValue } from "../utils/config.js";
7
8
  function isUrl(s) {
8
9
  return s.startsWith("http://") || s.startsWith("https://");
9
10
  }
11
+ function printPart(part) {
12
+ if (part.kind === "text") {
13
+ if (part.text)
14
+ process.stdout.write(part.text);
15
+ }
16
+ else if (part.kind === "file") {
17
+ const f = part.file;
18
+ const label = [f.name, f.mimeType].filter(Boolean).join(" ");
19
+ process.stdout.write(`\n[file${label ? `: ${label}` : ""}]\n`);
20
+ if ("uri" in f) {
21
+ process.stdout.write(f.uri + "\n");
22
+ }
23
+ else {
24
+ process.stdout.write(`<${f.bytes.length} base64 chars>\n`);
25
+ }
26
+ }
27
+ else if (part.kind === "data") {
28
+ process.stdout.write("\n" + JSON.stringify(part.data, null, 2) + "\n");
29
+ }
30
+ }
10
31
  function getCachedToken(slug) {
11
32
  const raw = getConfigValue(`agentTokens.${slug}`);
12
33
  if (!raw)
13
34
  return null;
14
35
  try {
15
- const cached = typeof raw === "string" ? JSON.parse(raw) : raw;
36
+ const cached = typeof raw === "string"
37
+ ? JSON.parse(raw)
38
+ : raw;
16
39
  if (new Date(cached.expiresAt) <= new Date())
17
40
  return null;
18
41
  return cached;
@@ -27,6 +50,7 @@ export const sendCommand = new Command("send")
27
50
  .argument("<message>", "Message to send")
28
51
  .option("--new", "Start a new conversation (clears saved context)")
29
52
  .option("--context <id>", "Use a specific context ID")
53
+ .option("--task-id <id>", "Reply to a specific task (e.g. one in input-required state)")
30
54
  .action(async (rawAgent, userMessage, opts) => {
31
55
  // Normalize slug: @user/name → @user~name (DB format)
32
56
  const agent = rawAgent.includes("/") && !isUrl(rawAgent)
@@ -37,10 +61,30 @@ export const sendCommand = new Command("send")
37
61
  let bearerToken;
38
62
  let agentKey;
39
63
  if (isUrl(agent)) {
40
- // Direct URL mode — local development, no handshake needed
41
64
  agentUrl = agent;
42
- bearerToken = config.token;
43
65
  agentKey = new URL(agent).host.replace(/[.:]/g, "-");
66
+ const cached = getCachedToken(agentKey);
67
+ if (cached) {
68
+ bearerToken = cached.token;
69
+ }
70
+ else {
71
+ const spinner = ora("Getting auth token...").start();
72
+ try {
73
+ const res = await apiPost("/api/auth/token", {});
74
+ bearerToken = res.token;
75
+ setConfigValue(`agentTokens.${agentKey}`, JSON.stringify({
76
+ token: res.token,
77
+ agentUrl,
78
+ expiresAt: res.expiresAt,
79
+ }));
80
+ spinner.stop();
81
+ }
82
+ catch (err) {
83
+ spinner.fail("Failed to get auth token");
84
+ console.error(chalk.red(String(err)));
85
+ process.exit(1);
86
+ }
87
+ }
44
88
  }
45
89
  else {
46
90
  // Slug mode — handshake with Web42 Network platform
@@ -85,20 +129,6 @@ export const sendCommand = new Command("send")
85
129
  contextId = getConfigValue(contextKey) ?? uuidv4();
86
130
  }
87
131
  setConfigValue(contextKey, contextId);
88
- // Dynamically import @a2a-js/sdk client
89
- let ClientFactory;
90
- let JsonRpcTransportFactory;
91
- let ClientFactoryOptions;
92
- try {
93
- const clientModule = await import("@a2a-js/sdk/client");
94
- ClientFactory = clientModule.ClientFactory;
95
- JsonRpcTransportFactory = clientModule.JsonRpcTransportFactory;
96
- ClientFactoryOptions = clientModule.ClientFactoryOptions;
97
- }
98
- catch {
99
- console.error(chalk.red("Failed to load @a2a-js/sdk. Run: pnpm add @a2a-js/sdk"));
100
- process.exit(1);
101
- }
102
132
  const bearerInterceptor = {
103
133
  before: async (args) => {
104
134
  if (!args.options)
@@ -119,8 +149,7 @@ export const sendCommand = new Command("send")
119
149
  interceptors: [bearerInterceptor],
120
150
  },
121
151
  }));
122
- const a2aBaseUrl = new URL(agentUrl).origin;
123
- client = await factory.createFromUrl(a2aBaseUrl);
152
+ client = await factory.createFromUrl(agentUrl);
124
153
  connectSpinner.stop();
125
154
  }
126
155
  catch {
@@ -136,22 +165,67 @@ export const sendCommand = new Command("send")
136
165
  parts: [{ kind: "text", text: userMessage }],
137
166
  kind: "message",
138
167
  contextId,
168
+ ...(opts.taskId ? { taskId: opts.taskId } : {}),
139
169
  },
140
170
  });
141
171
  for await (const event of stream) {
142
- if (event.kind === "artifact-update") {
143
- const artifact = event.artifact;
144
- const text = (artifact.parts ?? [])
145
- .filter((p) => p.kind === "text")
146
- .map((p) => p.text ?? "")
147
- .join("");
148
- if (text)
149
- process.stdout.write(text);
172
+ if (event.kind === "message" && event.role === "agent") {
173
+ for (const part of event.parts)
174
+ printPart(part);
175
+ }
176
+ else if (event.kind === "artifact-update") {
177
+ // When append is true we're receiving streaming chunks — write inline.
178
+ // When it's a new artifact (append falsy), separate from prior output.
179
+ if (!event.append)
180
+ process.stdout.write("\n");
181
+ for (const part of event.artifact.parts ?? [])
182
+ printPart(part);
150
183
  }
151
- if (event.kind === "status-update") {
152
- const update = event;
153
- if (update.status?.state === "failed") {
154
- console.error(chalk.red("\nAgent returned an error."));
184
+ else if (event.kind === "status-update") {
185
+ if (event.status?.message) {
186
+ for (const part of event.status.message.parts ?? [])
187
+ printPart(part);
188
+ }
189
+ const state = event.status?.state;
190
+ if (state === "input-required") {
191
+ process.stdout.write("\n");
192
+ console.log(chalk.yellow(`[task ${event.taskId} is awaiting input — reply with --task-id ${event.taskId}]`));
193
+ }
194
+ else if (state === "auth-required") {
195
+ console.error(chalk.red("\nAgent requires authentication."));
196
+ process.exit(1);
197
+ }
198
+ else if (state === "failed" ||
199
+ state === "canceled" ||
200
+ state === "rejected") {
201
+ console.error(chalk.red(`\nAgent ${state}.`));
202
+ process.exit(1);
203
+ }
204
+ }
205
+ else if (event.kind === "task") {
206
+ // Non-streaming fallback: server returned the full task object.
207
+ // Print accumulated artifacts and handle terminal state.
208
+ const task = event;
209
+ for (const artifact of task.artifacts ?? []) {
210
+ process.stdout.write("\n");
211
+ for (const part of artifact.parts ?? [])
212
+ printPart(part);
213
+ }
214
+ if (task.status?.message) {
215
+ for (const part of task.status.message.parts ?? [])
216
+ printPart(part);
217
+ }
218
+ const taskState = task.status?.state;
219
+ if (taskState === "input-required") {
220
+ process.stdout.write("\n");
221
+ console.log(chalk.yellow(`[task ${task.id} is awaiting input — reply with --task-id ${task.id}]`));
222
+ }
223
+ else if (taskState === "auth-required") {
224
+ console.error(chalk.red("\nAgent requires authentication."));
225
+ process.exit(1);
226
+ }
227
+ else if (taskState === "failed" || taskState === "canceled" || taskState === "rejected") {
228
+ console.error(chalk.red(`\nAgent ${taskState}.`));
155
229
  process.exit(1);
156
230
  }
157
231
  }
@@ -1,13 +1,11 @@
1
1
  import { existsSync, readFileSync } from "fs";
2
2
  import { join } from "path";
3
- import { Command } from "commander";
3
+ import { Web42Client, createA2AServer, } from "@web42/auth";
4
4
  import chalk from "chalk";
5
+ import { Command } from "commander";
5
6
  import ora from "ora";
6
- import express from "express";
7
- import { agentCardHandler, jsonRpcHandler, } from "@a2a-js/sdk/server/express";
8
- import { DefaultRequestHandler, InMemoryTaskStore, } from "@a2a-js/sdk/server";
9
7
  import { printBanner } from "../utils/banner.js";
10
- import { requireAuth, getConfig } from "../utils/config.js";
8
+ import { getConfig, requireAuth } from "../utils/config.js";
11
9
  class OpenClawAgentExecutor {
12
10
  opts;
13
11
  verbose;
@@ -17,8 +15,7 @@ class OpenClawAgentExecutor {
17
15
  }
18
16
  async execute(requestContext, eventBus) {
19
17
  const { taskId, contextId, userMessage } = requestContext;
20
- const userText = userMessage.parts
21
- .find((p) => p.kind === "text")?.text ?? "";
18
+ const userText = userMessage.parts.find((p) => p.kind === "text")?.text ?? "";
22
19
  if (this.verbose) {
23
20
  console.log(chalk.gray(`[verbose] → OpenClaw request: agent=${this.opts.openClawAgent} session=${contextId} port=${this.opts.openClawPort}`));
24
21
  console.log(chalk.gray(`[verbose] → message text: "${userText.slice(0, 100)}"`));
@@ -35,7 +32,7 @@ class OpenClawAgentExecutor {
35
32
  },
36
33
  body: JSON.stringify({
37
34
  model: "openclaw",
38
- stream: true,
35
+ stream: false,
39
36
  messages: [{ role: "user", content: userText }],
40
37
  }),
41
38
  });
@@ -54,53 +51,15 @@ class OpenClawAgentExecutor {
54
51
  }
55
52
  throw new Error(`OpenClaw error: ${response.status} ${response.statusText}`);
56
53
  }
57
- const reader = response.body.getReader();
58
- const decoder = new TextDecoder();
59
- let buffer = "";
60
- let tokenCount = 0;
61
- while (true) {
62
- const { done, value } = await reader.read();
63
- if (done)
64
- break;
65
- buffer += decoder.decode(value, { stream: true });
66
- const lines = buffer.split("\n");
67
- buffer = lines.pop() ?? "";
68
- for (const line of lines) {
69
- if (!line.startsWith("data: "))
70
- continue;
71
- const data = line.slice(6).trim();
72
- if (data === "[DONE]")
73
- continue;
74
- try {
75
- const chunk = JSON.parse(data);
76
- const token = chunk.choices?.[0]?.delta?.content;
77
- if (token) {
78
- tokenCount++;
79
- eventBus.publish({
80
- kind: "artifact-update",
81
- taskId,
82
- contextId,
83
- artifact: {
84
- artifactId: "response",
85
- parts: [{ kind: "text", text: token }],
86
- },
87
- });
88
- }
89
- }
90
- catch {
91
- // ignore malformed SSE lines
92
- }
93
- }
94
- }
95
- if (this.verbose) {
96
- console.log(chalk.gray(`[verbose] ← stream complete: ${tokenCount} tokens received`));
97
- }
54
+ const data = (await response.json());
55
+ const text = data.choices?.[0]?.message?.content ?? "";
98
56
  eventBus.publish({
99
- kind: "status-update",
100
- taskId,
57
+ kind: "message",
58
+ messageId: crypto.randomUUID(),
59
+ role: "agent",
60
+ parts: [{ kind: "text", text }],
101
61
  contextId,
102
- status: { state: "completed", timestamp: new Date().toISOString() },
103
- final: true,
62
+ taskId,
104
63
  });
105
64
  eventBus.finished();
106
65
  }
@@ -117,10 +76,14 @@ async function publishLiveUrl({ apiUrl, token, slug, a2aUrl, enabled, gatewaySta
117
76
  Authorization: `Bearer ${token}`,
118
77
  "Content-Type": "application/json",
119
78
  },
120
- body: JSON.stringify({ a2a_url: a2aUrl, a2a_enabled: enabled, gateway_status: gatewayStatus }),
79
+ body: JSON.stringify({
80
+ a2a_url: a2aUrl,
81
+ a2a_enabled: enabled,
82
+ gateway_status: gatewayStatus,
83
+ }),
121
84
  });
122
85
  if (!res.ok) {
123
- const errBody = await res.json().catch(() => ({}));
86
+ const errBody = (await res.json().catch(() => ({})));
124
87
  console.warn(chalk.yellow(` Could not register URL with marketplace: ${errBody.error ?? res.status}`));
125
88
  }
126
89
  else {
@@ -195,71 +158,42 @@ export const serveCommand = new Command("serve")
195
158
  process.exit(1);
196
159
  }
197
160
  const spinner = ora("Starting A2A server...").start();
198
- // 3. Build AgentCard from local file + overrides
199
- const agentCard = {
200
- name: agentName,
201
- description: cardData.description ?? "",
202
- protocolVersion: cardData.protocolVersion ?? "0.3.0",
203
- version: cardData.version ?? "1.0.0",
204
- url: `${publicUrl ?? `http://localhost:${port}`}/a2a/jsonrpc`,
205
- skills: cardData.skills ?? [],
206
- capabilities: {
207
- streaming: true,
208
- pushNotifications: false,
209
- ...(cardData.capabilities ?? {}),
210
- },
211
- defaultInputModes: cardData.defaultInputModes ?? ["text"],
212
- defaultOutputModes: cardData.defaultOutputModes ?? ["text"],
213
- securitySchemes: {
214
- W42Bearer: { type: "http", scheme: "bearer" },
215
- },
216
- security: [{ W42Bearer: [] }],
217
- };
218
- // 4. Start Express server
219
- const app = express();
220
- // Auth: validate caller's Bearer token via Web42 introspection with Basic auth
221
- const basicAuth = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`;
222
- const userBuilder = async (req) => {
223
- const callerToken = req.headers.authorization?.split(" ")[1];
224
- if (!callerToken)
225
- throw new Error("Missing token");
226
- if (verbose) {
227
- console.log(chalk.gray(`[verbose] Introspecting token ${callerToken.slice(0, 8)}...`));
228
- }
229
- const res = await fetch(`${web42ApiUrl}/api/auth/introspect`, {
230
- method: "POST",
231
- headers: {
232
- Authorization: basicAuth,
233
- "Content-Type": "application/x-www-form-urlencoded",
234
- },
235
- body: new URLSearchParams({ token: callerToken }),
236
- });
237
- if (!res.ok)
238
- throw new Error("Introspect call failed");
239
- const result = (await res.json());
240
- if (verbose) {
241
- console.log(chalk.gray(`[verbose] active=${result.active} sub=${result.sub ?? "(none)"}`));
242
- }
243
- if (!result.active)
244
- throw new Error("Unauthorized");
245
- return {
246
- get isAuthenticated() { return true; },
247
- get userName() { return result.sub ?? ""; },
248
- };
249
- };
161
+ const web42Client = new Web42Client({
162
+ baseUrl: web42ApiUrl,
163
+ clientId,
164
+ clientSecret,
165
+ });
250
166
  const executor = new OpenClawAgentExecutor({
251
167
  openClawPort,
252
168
  openClawToken,
253
169
  openClawAgent,
254
170
  verbose,
255
171
  });
256
- const requestHandler = new DefaultRequestHandler(agentCard, new InMemoryTaskStore(), executor);
257
- // 5. Mount A2A SDK handlers
258
- app.use("/.well-known/agent-card.json", agentCardHandler({ agentCardProvider: requestHandler }));
259
- app.use("/a2a/jsonrpc", jsonRpcHandler({ requestHandler, userBuilder }));
260
- const a2aUrl = `${publicUrl ?? `http://localhost:${port}`}/a2a/jsonrpc`;
261
- // 6. Start listening, then register
262
- app.listen(port, async () => {
172
+ const { listen } = createA2AServer({
173
+ web42: web42Client,
174
+ card: {
175
+ name: agentName,
176
+ description: cardData.description ?? "",
177
+ version: cardData.version ?? "1.0.0",
178
+ skills: cardData.skills ?? [],
179
+ capabilities: {
180
+ streaming: true,
181
+ pushNotifications: false,
182
+ ...(cardData.capabilities ?? {}),
183
+ },
184
+ defaultInputModes: cardData.defaultInputModes ?? [
185
+ "text",
186
+ ],
187
+ defaultOutputModes: cardData.defaultOutputModes ?? [
188
+ "text",
189
+ ],
190
+ },
191
+ executor,
192
+ port,
193
+ baseUrl: publicUrl ?? `http://localhost:${port}`,
194
+ });
195
+ const a2aUrl = publicUrl ?? `http://localhost:${port}`;
196
+ listen(async () => {
263
197
  spinner.stop();
264
198
  printBanner();
265
199
  console.log(chalk.green(` Agent "${agentName}" is live`));
@@ -281,7 +215,10 @@ export const serveCommand = new Command("serve")
281
215
  Authorization: `Bearer ${token}`,
282
216
  "Content-Type": "application/json",
283
217
  },
284
- body: JSON.stringify({ url: registrationUrl, visibility: opts.visibility }),
218
+ body: JSON.stringify({
219
+ url: registrationUrl,
220
+ visibility: opts.visibility,
221
+ }),
285
222
  });
286
223
  if (regRes.ok) {
287
224
  const regData = (await regRes.json());
@@ -289,7 +226,7 @@ export const serveCommand = new Command("serve")
289
226
  console.log(chalk.dim(` Registered with marketplace (slug: ${registeredSlug})`));
290
227
  }
291
228
  else {
292
- const errBody = await regRes.json().catch(() => ({}));
229
+ const errBody = (await regRes.json().catch(() => ({})));
293
230
  console.warn(chalk.yellow(` Could not register with marketplace: ${errBody.error ?? regRes.status}`));
294
231
  }
295
232
  }
@@ -311,7 +248,7 @@ export const serveCommand = new Command("serve")
311
248
  console.log(chalk.yellow(" No --url provided. Registered localhost URL is not publicly reachable."));
312
249
  }
313
250
  console.log(chalk.dim("\nWaiting for requests... (Ctrl+C to stop)\n"));
314
- // 7. Graceful shutdown
251
+ // Graceful shutdown
315
252
  process.on("SIGINT", async () => {
316
253
  console.log(chalk.dim("\nShutting down..."));
317
254
  if (registeredSlug) {
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const CLI_VERSION = "0.1.3";
1
+ export declare const CLI_VERSION = "0.1.8";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = "0.1.3";
1
+ export const CLI_VERSION = "0.1.8";
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@web42/w42",
3
- "version": "0.1.3",
3
+ "version": "0.1.8",
4
4
  "description": "CLI for the Web42 Agent Network — discover, register, and communicate with A2A agents",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "w42": "./dist/index.js"
8
8
  },
9
9
  "scripts": {
10
- "embed-skills": "npx tsx scripts/embed-skills.ts",
11
- "build": "npm run embed-skills && tsc",
12
- "build:binary": "bash scripts/sync-version.sh && npm run embed-skills && bash scripts/build-binaries.sh",
10
+ "build": "tsc",
11
+ "build:binary": "bash scripts/sync-version.sh && bash scripts/build-binaries.sh",
13
12
  "dev": "tsc --watch",
14
13
  "start": "node dist/index.js"
15
14
  },
16
15
  "dependencies": {
17
16
  "@a2a-js/sdk": "^0.3.13",
17
+ "@web42/auth": "workspace:*",
18
18
  "chalk": "^5.3.0",
19
19
  "commander": "^12.1.0",
20
20
  "conf": "^13.0.1",
@@ -39,8 +39,7 @@
39
39
  },
40
40
  "files": [
41
41
  "dist/**/*.js",
42
- "dist/**/*.d.ts",
43
- "skills/**"
42
+ "dist/**/*.d.ts"
44
43
  ],
45
44
  "keywords": [
46
45
  "web42",
@@ -1,9 +0,0 @@
1
- export interface EmbeddedFile {
2
- path: string;
3
- content: string;
4
- }
5
- export interface EmbeddedSkill {
6
- name: string;
7
- files: EmbeddedFile[];
8
- }
9
- export declare const EMBEDDED_SKILLS: EmbeddedSkill[];