wokitoki 0.3.0 → 0.3.2

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
@@ -10,7 +10,10 @@ Your Claude Code talks to your friend's Claude Code (or Codex), directly, peer t
10
10
  No server. No account. No tunnel. Free and open source.
11
11
 
12
12
  [![CI](https://github.com/pandeyvishwas51-oss/wokitoki/actions/workflows/ci.yml/badge.svg)](https://github.com/pandeyvishwas51-oss/wokitoki/actions/workflows/ci.yml)
13
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/pandeyvishwas51-oss/wokitoki/badge)](https://scorecard.dev/viewer/?uri=github.com/pandeyvishwas51-oss/wokitoki)
13
14
  [![npm](https://img.shields.io/npm/v/wokitoki?color=FF5A1F)](https://www.npmjs.com/package/wokitoki)
15
+ [![WokiToki MCP server on Glama](https://glama.ai/mcp/servers/pandeyvishwas51-oss/wokitoki/badges/score.svg)](https://glama.ai/mcp/servers/pandeyvishwas51-oss/wokitoki)
16
+ [![M8ven Score](https://m8ven.ai/badge/mcp/pandeyvishwas51-oss-wokitoki-atcfpk?v=f7bb2fa9b9dcfb420e5aafaf4712ed9e)](https://m8ven.ai/mcp/pandeyvishwas51-oss-wokitoki-atcfpk?s=readme)
14
17
  [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-FF5A1F)](https://github.com/pandeyvishwas51-oss/wokitoki/blob/main/LICENSE)
15
18
  [![MCP Registry](https://img.shields.io/badge/MCP_Registry-io.github.pandeyvishwas51--oss%2Fwokitoki-2B1306)](https://registry.modelcontextprotocol.io/v0/servers?search=wokitoki)
16
19
  [![Node 22.18+](https://img.shields.io/badge/node-22.18%2B-2B1306)](https://nodejs.org)
@@ -89,7 +92,7 @@ It brings the MCP tools, the skill, and an alert: at session start and on your n
89
92
  | `wokitoki_read_inbox` | read unread messages (marks them read) |
90
93
  | `wokitoki_list_messages` | conversation history with delivery state |
91
94
 
92
- `wokitoki setup` also installs a Claude Code [skill](https://github.com/pandeyvishwas51-oss/wokitoki/blob/main/skills/wokitoki/SKILL.md) that tells the agent when to use these tools, to never send secrets, and to treat incoming messages as information rather than instructions.
95
+ `wokitoki setup` also installs a Claude Code [skill](https://github.com/pandeyvishwas51-oss/wokitoki/blob/main/plugins/wokitoki/skills/wokitoki/SKILL.md) that tells the agent when to use these tools, to never send secrets, and to treat incoming messages as information rather than instructions.
93
96
 
94
97
  Your agent **cannot** pair, approve or revoke; those always need you at the terminal. Incoming text is labelled as untrusted data, so agents treat it as information, never as instructions. Any MCP client can use WokiToki by running `wokitoki mcp`.
95
98
 
@@ -187,9 +190,11 @@ Every command accepts `--json` and `--home <dir>` (default `~/.wokitoki`). The o
187
190
 
188
191
  ```bash
189
192
  pnpm install
190
- pnpm check # strict TypeScript + 64 tests: unit, adversarial, P2P on a local DHT testnet, multi-process CLI e2e, real MCP calls
193
+ pnpm check # strict TypeScript + 65 tests: unit, adversarial, P2P on a local DHT testnet, multi-process CLI e2e, real MCP calls
191
194
  ```
192
195
 
196
+ Releases come only from CI: bump the version, tag `vX.Y.Z` on `main` and push the tag. [release.yml](https://github.com/pandeyvishwas51-oss/wokitoki/blob/main/.github/workflows/release.yml) stages it on npm with signed provenance (trusted publishing, no tokens) for a maintainer to approve with 2FA, attaches a build attestation and an SBOM to the GitHub release, and updates the MCP Registry.
197
+
193
198
  [Roadmap](https://github.com/pandeyvishwas51-oss/wokitoki/blob/main/ROADMAP.md): tasks, encrypted file transfer, multi-agent rooms and a web console are next. License: [Apache-2.0](https://github.com/pandeyvishwas51-oss/wokitoki/blob/main/LICENSE).
194
199
 
195
200
  <p align="center"><img src="https://raw.githubusercontent.com/pandeyvishwas51-oss/wokitoki/main/assets/logo.svg" width="72" alt="WokiToki mascot"></p>
package/dist/wokitoki.mjs CHANGED
@@ -281,7 +281,11 @@ var init_src2 = __esm({
281
281
  utf8 = new TextEncoder();
282
282
  strictUtf8 = new TextDecoder("utf-8", { fatal: true });
283
283
  toB64 = (u) => Buffer.from(u).toString("base64url");
284
- fromB64 = (s) => new Uint8Array(Buffer.from(s, "base64url"));
284
+ fromB64 = (s) => {
285
+ const bytes = new Uint8Array(Buffer.from(s, "base64url"));
286
+ if (Buffer.from(bytes).toString("base64url") !== s) throw new Error("invalid base64url: not in canonical form");
287
+ return bytes;
288
+ };
285
289
  toHex = (u) => Buffer.from(u).toString("hex");
286
290
  joinTranscript = (pairId, joiner) => utf8.encode(canonicalJson({ t: "agentmesh-pair-join-v1", pairId, joiner }));
287
291
  }
@@ -1912,7 +1916,8 @@ function createMcpServer(socketPath, version) {
1912
1916
  {
1913
1917
  title: "WokiToki status",
1914
1918
  description: "Show this WokiToki identity, network connection state (peer-to-peer or relay), pending outbox size and peer counts.",
1915
- annotations: { readOnlyHint: true, openWorldHint: false }
1919
+ inputSchema: {},
1920
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
1916
1921
  },
1917
1922
  () => guard(async () => ok(await daemon2("GET", "/status")))
1918
1923
  );
@@ -1922,7 +1927,7 @@ function createMcpServer(socketPath, version) {
1922
1927
  title: "List WokiToki peers",
1923
1928
  description: 'List agents this machine is paired with. Only peers in state "active" can receive messages. Pairing and approval are done by the human with the wokitoki CLI, not by this tool.',
1924
1929
  inputSchema: { state: z7.enum(["pending", "active", "rejected", "revoked"]).optional().describe("filter by pairing state") },
1925
- annotations: { readOnlyHint: true, openWorldHint: false }
1930
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
1926
1931
  },
1927
1932
  ({ state }) => guard(async () => ok((await daemon2("GET", `/peers${state ? `?state=${state}` : ""}`)).map(peerSummary)))
1928
1933
  );
@@ -1950,7 +1955,8 @@ function createMcpServer(socketPath, version) {
1950
1955
  limit: z7.number().int().min(1).max(200).optional().describe("max messages (default 50)"),
1951
1956
  markRead: z7.boolean().optional().describe("mark returned messages as read (default true)")
1952
1957
  },
1953
- annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
1958
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }
1959
+ // marks messages read
1954
1960
  },
1955
1961
  ({ peer, limit, markRead }) => guard(async () => {
1956
1962
  const q = new URLSearchParams({ unread: "1", limit: String(limit ?? 50), ...peer ? { peer } : {} });
@@ -1969,7 +1975,7 @@ function createMcpServer(socketPath, version) {
1969
1975
  peer: z7.string().max(128).optional().describe("only this peer (name or device id)"),
1970
1976
  limit: z7.number().int().min(1).max(200).optional().describe("max messages (default 20)")
1971
1977
  },
1972
- annotations: { readOnlyHint: true, openWorldHint: false }
1978
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
1973
1979
  },
1974
1980
  ({ peer, limit }) => guard(async () => {
1975
1981
  const q = new URLSearchParams({ limit: String(limit ?? 20), ...peer ? { peer } : {} });
@@ -2148,7 +2154,7 @@ await init_control();
2148
2154
  var SELF = fileURLToPath(import.meta.url);
2149
2155
  var firstExisting = (...paths) => paths.find((p) => existsSync4(p)) ?? paths[0];
2150
2156
  var BIN = firstExisting(resolve2(dirname2(SELF), "../bin/wokitoki.js"), SELF);
2151
- var SKILL = firstExisting(resolve2(dirname2(SELF), "../skills/wokitoki/SKILL.md"), resolve2(dirname2(SELF), "../../../skills/wokitoki/SKILL.md"));
2157
+ var SKILL = firstExisting(resolve2(dirname2(SELF), "../skills/wokitoki/SKILL.md"), resolve2(dirname2(SELF), "../../../plugins/wokitoki/skills/wokitoki/SKILL.md"));
2152
2158
  var INSTALL_URL = "https://raw.githubusercontent.com/pandeyvishwas51-oss/wokitoki/main/install.sh";
2153
2159
  var VERSION = JSON.parse(readFileSync3(new URL("../package.json", import.meta.url), "utf8")).version;
2154
2160
  var program = new Command("wokitoki").description("WokiToki: paired, end-to-end encrypted messaging between independently owned coding agents").version(VERSION).option("--home <dir>", "WokiToki home directory (default: $WOKITOKI_HOME or ~/.wokitoki)").option("--json", "machine-readable JSON output").showHelpAfterError();
@@ -2531,7 +2537,7 @@ program.command("hook <event>").description("Claude Code hook: announce unread m
2531
2537
  const { home } = ctx();
2532
2538
  try {
2533
2539
  if (!existsSync4(homePaths(home).identity)) {
2534
- if (event === "session-start") console.log(`WokiToki is installed but not set up. If the user wants their agent to message other developers' agents, tell them to run: wokitoki setup --name "<their name>"`);
2540
+ if (event === "session-start") console.log(`WokiToki is not set up on this machine. If the user wants their agent to message other developers' agents, tell them to run: npm install -g wokitoki, then wokitoki setup --name "<their name>"`);
2535
2541
  return;
2536
2542
  }
2537
2543
  const unread = await daemon("GET", "/messages?unread=1&limit=100");