sello 0.1.14 → 0.1.15

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/cli/sello.js CHANGED
@@ -199,6 +199,29 @@ async function devCommand(args ) {
199
199
  console.log(`Local dev log: ${logPath}`);
200
200
  console.log(`Loaded ${devLogEntryCountLabel(loadedEntries)}.`);
201
201
  });
202
+ server.on("error", (error) => {
203
+ if (isPortInUse(error)) {
204
+ console.error(`sello: port ${port} is already in use.`);
205
+ console.error("");
206
+ console.error("Try:");
207
+ console.error(` sello dev --port ${port + 1}`);
208
+ console.error("");
209
+ console.error("Or stop the process using that port:");
210
+ console.error(` lsof -nP -iTCP:${port} -sTCP:LISTEN`);
211
+ process.exitCode = 1;
212
+ return;
213
+ }
214
+
215
+ if (isListenError(error)) {
216
+ const message = error instanceof Error ? error.message : String(error);
217
+ console.error(`sello: could not start dev server on port ${port}.`);
218
+ console.error(message);
219
+ process.exitCode = 1;
220
+ return;
221
+ }
222
+
223
+ throw error;
224
+ });
202
225
  }
203
226
 
204
227
  async function emitDemoCommand(args ) {
@@ -257,14 +280,7 @@ async function callHttpDemoCommand(args ) {
257
280
  );
258
281
  const url = readFlag(args, "--url") ?? "http://localhost:8790/calendar/events";
259
282
  const title = readFlag(args, "--title") ?? "Ship Sello";
260
- const response = await fetch(url, {
261
- method: "POST",
262
- headers: {
263
- authorization: `Bearer ${state.agentToken}`,
264
- "content-type": "application/json",
265
- },
266
- body: JSON.stringify({ title }),
267
- });
283
+ const response = await fetchHttpDemo(url, state.agentToken, title);
268
284
  const responseText = await response.text();
269
285
 
270
286
  if (!response.ok) {
@@ -283,6 +299,31 @@ async function callHttpDemoCommand(args ) {
283
299
  console.log(` ${actionViewerUrl(state)}`);
284
300
  }
285
301
 
302
+ async function fetchHttpDemo(
303
+ url ,
304
+ agentToken ,
305
+ title ,
306
+ ) {
307
+ try {
308
+ return await fetch(url, {
309
+ method: "POST",
310
+ headers: {
311
+ authorization: `Bearer ${agentToken}`,
312
+ "content-type": "application/json",
313
+ },
314
+ body: JSON.stringify({ title }),
315
+ });
316
+ } catch (error) {
317
+ if (isFetchFailed(error)) {
318
+ throw new TypeError(
319
+ `could not reach the HTTP demo route at ${url}.\n\nStart it in another terminal:\n node sello-http-route.mjs`,
320
+ );
321
+ }
322
+
323
+ throw error;
324
+ }
325
+ }
326
+
286
327
  function initDemoCommand(args ) {
287
328
  const output = readFlag(args, "--output") ?? "emit-receipt.mjs";
288
329
  const force = args.includes("--force");
@@ -787,6 +828,22 @@ function isRecord(value ) {
787
828
  return typeof value === "object" && value !== null && !Array.isArray(value);
788
829
  }
789
830
 
831
+ function isPortInUse(error ) {
832
+ return (
833
+ isRecord(error) &&
834
+ error.code === "EADDRINUSE" &&
835
+ error.syscall === "listen"
836
+ );
837
+ }
838
+
839
+ function isListenError(error ) {
840
+ return isRecord(error) && error.syscall === "listen";
841
+ }
842
+
843
+ function isFetchFailed(error ) {
844
+ return error instanceof TypeError && error.message === "fetch failed";
845
+ }
846
+
790
847
  function printHelp() {
791
848
  console.log(`Usage:
792
849
  sello dev [--port 8787] [--service service-id] [--dry-run]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sello",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Reference implementation of the Sello protocol for service-signed AI agent receipts.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -200,6 +200,29 @@ async function devCommand(args: string[]): Promise<void> {
200
200
  console.log(`Local dev log: ${logPath}`);
201
201
  console.log(`Loaded ${devLogEntryCountLabel(loadedEntries)}.`);
202
202
  });
203
+ server.on("error", (error) => {
204
+ if (isPortInUse(error)) {
205
+ console.error(`sello: port ${port} is already in use.`);
206
+ console.error("");
207
+ console.error("Try:");
208
+ console.error(` sello dev --port ${port + 1}`);
209
+ console.error("");
210
+ console.error("Or stop the process using that port:");
211
+ console.error(` lsof -nP -iTCP:${port} -sTCP:LISTEN`);
212
+ process.exitCode = 1;
213
+ return;
214
+ }
215
+
216
+ if (isListenError(error)) {
217
+ const message = error instanceof Error ? error.message : String(error);
218
+ console.error(`sello: could not start dev server on port ${port}.`);
219
+ console.error(message);
220
+ process.exitCode = 1;
221
+ return;
222
+ }
223
+
224
+ throw error;
225
+ });
203
226
  }
204
227
 
205
228
  async function emitDemoCommand(args: string[]): Promise<void> {
@@ -258,14 +281,7 @@ async function callHttpDemoCommand(args: string[]): Promise<void> {
258
281
  );
259
282
  const url = readFlag(args, "--url") ?? "http://localhost:8790/calendar/events";
260
283
  const title = readFlag(args, "--title") ?? "Ship Sello";
261
- const response = await fetch(url, {
262
- method: "POST",
263
- headers: {
264
- authorization: `Bearer ${state.agentToken}`,
265
- "content-type": "application/json",
266
- },
267
- body: JSON.stringify({ title }),
268
- });
284
+ const response = await fetchHttpDemo(url, state.agentToken, title);
269
285
  const responseText = await response.text();
270
286
 
271
287
  if (!response.ok) {
@@ -284,6 +300,31 @@ async function callHttpDemoCommand(args: string[]): Promise<void> {
284
300
  console.log(` ${actionViewerUrl(state)}`);
285
301
  }
286
302
 
303
+ async function fetchHttpDemo(
304
+ url: string,
305
+ agentToken: string,
306
+ title: string,
307
+ ): Promise<Response> {
308
+ try {
309
+ return await fetch(url, {
310
+ method: "POST",
311
+ headers: {
312
+ authorization: `Bearer ${agentToken}`,
313
+ "content-type": "application/json",
314
+ },
315
+ body: JSON.stringify({ title }),
316
+ });
317
+ } catch (error) {
318
+ if (isFetchFailed(error)) {
319
+ throw new TypeError(
320
+ `could not reach the HTTP demo route at ${url}.\n\nStart it in another terminal:\n node sello-http-route.mjs`,
321
+ );
322
+ }
323
+
324
+ throw error;
325
+ }
326
+ }
327
+
287
328
  function initDemoCommand(args: string[]): void {
288
329
  const output = readFlag(args, "--output") ?? "emit-receipt.mjs";
289
330
  const force = args.includes("--force");
@@ -788,6 +829,22 @@ function isRecord(value: unknown): value is Record<string, unknown> {
788
829
  return typeof value === "object" && value !== null && !Array.isArray(value);
789
830
  }
790
831
 
832
+ function isPortInUse(error: unknown): boolean {
833
+ return (
834
+ isRecord(error) &&
835
+ error.code === "EADDRINUSE" &&
836
+ error.syscall === "listen"
837
+ );
838
+ }
839
+
840
+ function isListenError(error: unknown): boolean {
841
+ return isRecord(error) && error.syscall === "listen";
842
+ }
843
+
844
+ function isFetchFailed(error: unknown): boolean {
845
+ return error instanceof TypeError && error.message === "fetch failed";
846
+ }
847
+
791
848
  function printHelp(): void {
792
849
  console.log(`Usage:
793
850
  sello dev [--port 8787] [--service service-id] [--dry-run]