sello 0.1.8 → 0.1.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.
package/README.md CHANGED
@@ -46,6 +46,7 @@ To scaffold a small HTTP route that emits receipts:
46
46
 
47
47
  ```bash
48
48
  npx --yes sello init-http-demo
49
+ npx --yes sello call-http-demo
49
50
  ```
50
51
 
51
52
  ## Why Sello?
@@ -85,7 +86,7 @@ The implementation includes a local end-to-end demo, compact JWS token verificat
85
86
  |------|------|
86
87
  | Add Sello in a few lines | [SDK Quickstart](docs/sdk-quickstart.md) |
87
88
  | Emit your first receipt | `npx --yes sello dev`, then `npx --yes sello emit-demo` |
88
- | Wrap one HTTP route | `npx --yes sello init-http-demo` |
89
+ | Wrap one HTTP route | `npx --yes sello init-http-demo`, then `npx --yes sello call-http-demo` |
89
90
  | Try a wrapped tool locally | `node --run dev`, then `node --run example:tool` |
90
91
  | Try an MCP-style tool call | `node --run dev`, then `node --run example:mcp` |
91
92
  | See a minimal MCP integration | [examples/mcp-minimal-server.ts](examples/mcp-minimal-server.ts) |
@@ -142,7 +143,7 @@ For an MCP-shaped `tools/call` boundary, run `node --run example:mcp` instead of
142
143
 
143
144
  For a smaller production-shaped MCP example, see [examples/mcp-minimal-server.ts](examples/mcp-minimal-server.ts). It wraps one `tools/call` handler with `sello.service()` and leaves unknown tools unreceipted.
144
145
 
145
- For an installed-project bridge from demo to app, run `npx sello init-http-demo`. It writes a small dependency-free HTTP route that imports `sello`, reads the local dev config, verifies a bearer token, runs a handler, and emits a receipt.
146
+ For an installed-project bridge from demo to app, run `npx sello init-http-demo`. It writes a small dependency-free HTTP route that imports `sello`, reads the local dev config, verifies a bearer token, runs a handler, and emits a receipt. With the local log and route running, `npx sello call-http-demo` sends the demo request for you.
146
147
 
147
148
  ## The First 10 Minutes
148
149
 
package/dist/cli/sello.js CHANGED
@@ -81,6 +81,9 @@ try {
81
81
  case "emit-demo":
82
82
  await emitDemoCommand(process.argv.slice(3));
83
83
  break;
84
+ case "call-http-demo":
85
+ await callHttpDemoCommand(process.argv.slice(3));
86
+ break;
84
87
  case "init-demo":
85
88
  initDemoCommand(process.argv.slice(3));
86
89
  break;
@@ -237,6 +240,38 @@ async function emitDemoCommand(args ) {
237
240
  console.log(` ${actionViewerUrl(state)}`);
238
241
  }
239
242
 
243
+ async function callHttpDemoCommand(args ) {
244
+ const state = loadDevStateOrThrow(
245
+ "missing local Sello dev state. Run `sello dev` first, then run `sello call-http-demo` in another terminal from the same directory.",
246
+ );
247
+ const url = readFlag(args, "--url") ?? "http://localhost:8790/calendar/events";
248
+ const title = readFlag(args, "--title") ?? "Ship Sello";
249
+ const response = await fetch(url, {
250
+ method: "POST",
251
+ headers: {
252
+ authorization: `Bearer ${state.agentToken}`,
253
+ "content-type": "application/json",
254
+ },
255
+ body: JSON.stringify({ title }),
256
+ });
257
+ const responseText = await response.text();
258
+
259
+ if (!response.ok) {
260
+ throw new TypeError(
261
+ `HTTP route demo failed with HTTP ${response.status}: ${responseText.trim()}`,
262
+ );
263
+ }
264
+
265
+ console.log("Called Sello HTTP route demo.");
266
+ console.log(formatHttpDemoResponse(responseText));
267
+ console.log("");
268
+ console.log("View verified actions with:");
269
+ console.log(" sello actions");
270
+ console.log("");
271
+ console.log("Or open:");
272
+ console.log(` ${actionViewerUrl(state)}`);
273
+ }
274
+
240
275
  function initDemoCommand(args ) {
241
276
  const output = readFlag(args, "--output") ?? "emit-receipt.mjs";
242
277
  const force = args.includes("--force");
@@ -278,8 +313,7 @@ function initHttpDemoCommand(args ) {
278
313
  console.log(` node ${output}`);
279
314
  console.log("");
280
315
  console.log("Terminal 3: call the route and view the receipt");
281
- console.log(" TOKEN=$(node -e 'console.log(JSON.parse(require(\"fs\").readFileSync(\".sello/dev.json\", \"utf8\")).agentToken)')");
282
- console.log(" curl -sS -X POST http://localhost:8790/calendar/events -H \"authorization: Bearer $TOKEN\" -H \"content-type: application/json\" -d '{\"title\":\"Ship Sello\"}'");
316
+ console.log(" npx sello call-http-demo");
283
317
  console.log(" npx sello actions");
284
318
  console.log("");
285
319
  console.log("Then open http://localhost:8787/actions");
@@ -678,6 +712,7 @@ function printHelp() {
678
712
  console.log(`Usage:
679
713
  sello dev [--port 8787] [--service service-id] [--dry-run]
680
714
  sello emit-demo [--title title]
715
+ sello call-http-demo [--url http://localhost:8790/calendar/events] [--title title]
681
716
  sello init-demo [--output emit-receipt.mjs] [--force]
682
717
  sello init-http-demo [--output sello-http-route.mjs] [--force]
683
718
  sello actions [--token agent-token]
@@ -738,6 +773,14 @@ function actionViewerUrl(state ) {
738
773
  return `${endpoint.origin}/actions`;
739
774
  }
740
775
 
776
+ function formatHttpDemoResponse(responseText ) {
777
+ try {
778
+ return JSON.stringify(JSON.parse(responseText), null, 2);
779
+ } catch {
780
+ return responseText;
781
+ }
782
+ }
783
+
741
784
  function slug(value ) {
742
785
  return value
743
786
  .toLowerCase()
@@ -857,9 +900,8 @@ const server = createServer(async (request, response) => {
857
900
  server.listen(port, () => {
858
901
  console.log("Sello HTTP route demo running at http://localhost:" + port + "/calendar/events");
859
902
  console.log("");
860
- console.log("Call it with:");
861
- console.log(" TOKEN=$(node -e 'console.log(JSON.parse(require(\\\"fs\\\").readFileSync(\\\".sello/dev.json\\\", \\\"utf8\\\")).agentToken)')");
862
- console.log(" curl -sS -X POST http://localhost:" + port + "/calendar/events -H \\\"authorization: Bearer $TOKEN\\\" -H \\\"content-type: application/json\\\" -d '{\\\"title\\\":\\\"Ship Sello\\\"}'");
903
+ console.log("Call it from another terminal with:");
904
+ console.log(" npx sello call-http-demo");
863
905
  });
864
906
 
865
907
  async function readJson(request) {
@@ -41,7 +41,12 @@ To write a dependency-free HTTP route example into your project:
41
41
  npx --yes sello init-http-demo
42
42
  ```
43
43
 
44
- The route example imports `sello`, reads the local dev config, verifies a bearer token, runs one `POST /calendar/events` handler, and emits a receipt.
44
+ The route example imports `sello`, reads the local dev config, verifies a bearer token, runs one `POST /calendar/events` handler, and emits a receipt. With `npx sello dev` and the generated route running, call it with:
45
+
46
+ ```bash
47
+ npx --yes sello call-http-demo
48
+ npx --yes sello actions
49
+ ```
45
50
 
46
51
  Inside this repo, start the local log and action viewer:
47
52
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sello",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
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",
package/src/cli/sello.ts CHANGED
@@ -82,6 +82,9 @@ try {
82
82
  case "emit-demo":
83
83
  await emitDemoCommand(process.argv.slice(3));
84
84
  break;
85
+ case "call-http-demo":
86
+ await callHttpDemoCommand(process.argv.slice(3));
87
+ break;
85
88
  case "init-demo":
86
89
  initDemoCommand(process.argv.slice(3));
87
90
  break;
@@ -238,6 +241,38 @@ async function emitDemoCommand(args: string[]): Promise<void> {
238
241
  console.log(` ${actionViewerUrl(state)}`);
239
242
  }
240
243
 
244
+ async function callHttpDemoCommand(args: string[]): Promise<void> {
245
+ const state = loadDevStateOrThrow(
246
+ "missing local Sello dev state. Run `sello dev` first, then run `sello call-http-demo` in another terminal from the same directory.",
247
+ );
248
+ const url = readFlag(args, "--url") ?? "http://localhost:8790/calendar/events";
249
+ const title = readFlag(args, "--title") ?? "Ship Sello";
250
+ const response = await fetch(url, {
251
+ method: "POST",
252
+ headers: {
253
+ authorization: `Bearer ${state.agentToken}`,
254
+ "content-type": "application/json",
255
+ },
256
+ body: JSON.stringify({ title }),
257
+ });
258
+ const responseText = await response.text();
259
+
260
+ if (!response.ok) {
261
+ throw new TypeError(
262
+ `HTTP route demo failed with HTTP ${response.status}: ${responseText.trim()}`,
263
+ );
264
+ }
265
+
266
+ console.log("Called Sello HTTP route demo.");
267
+ console.log(formatHttpDemoResponse(responseText));
268
+ console.log("");
269
+ console.log("View verified actions with:");
270
+ console.log(" sello actions");
271
+ console.log("");
272
+ console.log("Or open:");
273
+ console.log(` ${actionViewerUrl(state)}`);
274
+ }
275
+
241
276
  function initDemoCommand(args: string[]): void {
242
277
  const output = readFlag(args, "--output") ?? "emit-receipt.mjs";
243
278
  const force = args.includes("--force");
@@ -279,8 +314,7 @@ function initHttpDemoCommand(args: string[]): void {
279
314
  console.log(` node ${output}`);
280
315
  console.log("");
281
316
  console.log("Terminal 3: call the route and view the receipt");
282
- console.log(" TOKEN=$(node -e 'console.log(JSON.parse(require(\"fs\").readFileSync(\".sello/dev.json\", \"utf8\")).agentToken)')");
283
- console.log(" curl -sS -X POST http://localhost:8790/calendar/events -H \"authorization: Bearer $TOKEN\" -H \"content-type: application/json\" -d '{\"title\":\"Ship Sello\"}'");
317
+ console.log(" npx sello call-http-demo");
284
318
  console.log(" npx sello actions");
285
319
  console.log("");
286
320
  console.log("Then open http://localhost:8787/actions");
@@ -679,6 +713,7 @@ function printHelp(): void {
679
713
  console.log(`Usage:
680
714
  sello dev [--port 8787] [--service service-id] [--dry-run]
681
715
  sello emit-demo [--title title]
716
+ sello call-http-demo [--url http://localhost:8790/calendar/events] [--title title]
682
717
  sello init-demo [--output emit-receipt.mjs] [--force]
683
718
  sello init-http-demo [--output sello-http-route.mjs] [--force]
684
719
  sello actions [--token agent-token]
@@ -739,6 +774,14 @@ function actionViewerUrl(state: DevState): string {
739
774
  return `${endpoint.origin}/actions`;
740
775
  }
741
776
 
777
+ function formatHttpDemoResponse(responseText: string): string {
778
+ try {
779
+ return JSON.stringify(JSON.parse(responseText), null, 2);
780
+ } catch {
781
+ return responseText;
782
+ }
783
+ }
784
+
742
785
  function slug(value: string): string {
743
786
  return value
744
787
  .toLowerCase()
@@ -858,9 +901,8 @@ const server = createServer(async (request, response) => {
858
901
  server.listen(port, () => {
859
902
  console.log("Sello HTTP route demo running at http://localhost:" + port + "/calendar/events");
860
903
  console.log("");
861
- console.log("Call it with:");
862
- console.log(" TOKEN=$(node -e 'console.log(JSON.parse(require(\\\"fs\\\").readFileSync(\\\".sello/dev.json\\\", \\\"utf8\\\")).agentToken)')");
863
- console.log(" curl -sS -X POST http://localhost:" + port + "/calendar/events -H \\\"authorization: Bearer $TOKEN\\\" -H \\\"content-type: application/json\\\" -d '{\\\"title\\\":\\\"Ship Sello\\\"}'");
904
+ console.log("Call it from another terminal with:");
905
+ console.log(" npx sello call-http-demo");
864
906
  });
865
907
 
866
908
  async function readJson(request) {