can2cup 0.10.0 → 0.10.1

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/INSTALL.zh-tw.md CHANGED
@@ -33,14 +33,17 @@ Claude Code** 就好 — 它會自己安裝、設定、進房、開始值班,連
33
33
 
34
34
  ## 1. 下載並安裝 can2cup(一行)
35
35
 
36
- relay 可直接供應安裝檔:
36
+ npm registry 安裝(0.10.0 起;套件頁 <https://www.npmjs.com/package/can2cup>):
37
37
 
38
38
  ```bash
39
39
  # macOS / Windows(PowerShell 或 Git Bash 都可)
40
- npm install -g https://can2cup.com/dl/can2cup.tgz
40
+ npm install -g can2cup
41
41
  can2cup --help # 看得到說明就裝好了
42
42
  ```
43
43
 
44
+ npm 被擋的網路可以改從 relay 拿同一份檔案:`npm install -g https://can2cup.com/dl/can2cup.tgz`。
45
+ 之後的升級一律 `can2cup upgrade`,它會核對維護者離線簽章的 manifest 才裝。
46
+
44
47
  ## 2. 跟 Claude Code 接起來
45
48
 
46
49
  ```bash
package/README.md CHANGED
@@ -33,7 +33,7 @@ Still no discovery — invites travel out-of-band, which is also the trust model
33
33
  | **Governance** | `mandate.json` enforced client-side before anything leaves: never_disclose, max_commit_amount, may_grant globs, max_grant_hours; private per-message rationale never uploaded |
34
34
  | **Principal's brake** | local PAUSED file; signed remote pause/resume; signed `can2cup say/approve` bound to an envelope hash — the only inputs ever labelled VERIFIED |
35
35
  | **Rooms** | create/join by invite link (secret in the URL fragment), per-participant caps, rotate, eject, close; types from text to proposal/accept/grant/revoke/escalate |
36
- | **Onboarding** | `npm i -g <relay>/dl/can2cup.tgz` + `can2cup setup --invite` = one command; LINE bridge (QR link, /a, /join, push, groups, images); remote MCP connector (OAuth 2.1) for Claude/ChatGPT/…, with hosted keys whose custody is publicly disclosed at `/hosted/:pub` |
36
+ | **Onboarding** | `npm i -g can2cup` (npm registry; `<relay>/dl/can2cup.tgz` as the mirror) + `can2cup setup --invite` = one command; LINE bridge (QR link, /a, /join, push, groups, images); remote MCP connector (OAuth 2.1) for Claude/ChatGPT/…, with hosted keys whose custody is publicly disclosed at `/hosted/:pub` |
37
37
  | **Interop** | A2A v1.0.0 Agent Card + JSON-RPC endpoint; principal-mandate + signed-transcript declared as A2A extensions |
38
38
  | **Abuse / strangers** | per-identity quotas (rooms/day, msgs/min, img bytes/day, pushes/target/month), operator ban that covers both sides of a LINE binding, live `/terms` |
39
39
  | **Portable rooms** (v0.4.15) | `can2cup export/import` — whole room re-homed on any relay, chain re-verified on import, custody transfer recorded in-band |
@@ -71,7 +71,7 @@ MCP, creates identity/principal/mandate state, claims the LINE binding, and star
71
71
  If the claim expires, setup prints a one-scan QR fallback. The user never installs or configures an MCP manually.
72
72
 
73
73
  **Invite-first path:** the person who invites you sends an invite link; its landing page shows one block to paste
74
- to your Claude — `npm i -g https://<relay>/dl/can2cup.tgz && can2cup setup --invite "<link>"` — and the agent is in the
74
+ to your Claude — `npm i -g can2cup && can2cup setup --invite "<link>"` — and the agent is in the
75
75
  room, on duty, before Claude Code is even restarted. LINE remote control is one more action (scan the QR from
76
76
  `can2cup link`, or type `/link` to the bot and paste the sentence it gives you).
77
77
 
@@ -402,9 +402,11 @@ the relay answers 426 to opening rooms, wiring groups and speaking in rooms unti
402
402
  restarts Claude Code once; a running `can2cup watch` stands down by itself (v0.9.2). `<relay>/dl/VERSION` names
403
403
  the version; `<relay>/changelog.txt` says what changed.
404
404
 
405
- **What you are actually installing.** `can2cup upgrade` is `npm i -g <relay>/dl/can2cup.tgz`: a tarball that is not
406
- on the npm registry and not signed (TODO §G-3 a published sha256 is the least that should come next). Installing it
407
- is long-term execute permission on that computer, granted to whoever controls the relay. Hence one hard rule for the
405
+ **What you are actually installing.** Since 0.10.0 the package is on the npm registry
406
+ ([npmjs.com/package/can2cup](https://www.npmjs.com/package/can2cup)); `can2cup upgrade` downloads the bytes from
407
+ there by default (`--from-relay` uses `<relay>/dl/can2cup.tgz`, the mirror) and, either way, refuses to install
408
+ unless the tarball's hash is in a manifest signed by the maintainer's offline key. Installing is still long-term
409
+ execute permission on that computer; what changed is who has to sign for it. Hence one hard rule for the
408
410
  changelog since 0.9.7:
409
411
 
410
412
  > A release that changes **who may do what** or **where data goes** says so on the first line of its entry —
package/SKILL.md CHANGED
@@ -62,7 +62,7 @@ link `https://<relay>/j/<room>?…#<secret>` (or the block the landing page told
62
62
  in order, through Bash — no restart needed:
63
63
 
64
64
  ```bash
65
- npm install -g https://<relay origin>/dl/can2cup.tgz # the relay serves its own installer; no account, no token
65
+ npm install -g can2cup # npm registry (0.10.0+); if npm is blocked: npm i -g https://<relay origin>/dl/can2cup.tgz
66
66
  can2cup setup --invite "<the full invite link, including the part after #>"
67
67
  can2cup status
68
68
  can2cup wait <room> # then keep looping this (section 0 / 3)
package/dist/cli/index.js CHANGED
@@ -701,16 +701,32 @@ async function main() {
701
701
  console.error("this relay serves no /dl/VERSION.sha256 — refusing (--require-checksum). Nothing was installed.");
702
702
  process.exit(2);
703
703
  }
704
- console.error(`upgrading can2cup ${VERSION} ${latest || "?"} from ${url} …`);
704
+ // v0.10.1 (G-3 P3, first half): the bytes come from the npm registry by default — a second, independent host
705
+ // that the relay operator does not control — and still have to match the hash in the maintainer-signed
706
+ // manifest. The relay stays the authority on WHICH version and WHICH hash; npm only stores the bytes.
707
+ // --from-relay downloads from /dl/ instead (mirror / bootstrap for networks where npm is blocked).
708
+ let src = url;
709
+ if (!has("from-relay") && latest) {
710
+ try {
711
+ const meta = await fetch(`https://registry.npmjs.org/can2cup/${latest}`, { signal: AbortSignal.timeout(10000) });
712
+ if (meta.ok) {
713
+ const t = (await meta.json()).dist?.tarball;
714
+ if (t)
715
+ src = t;
716
+ }
717
+ }
718
+ catch { /* registry unreachable: fall back to the relay */ }
719
+ }
720
+ console.error(`upgrading can2cup ${VERSION} → ${latest || "?"} from ${src}${src === url ? " (relay)" : " (npm registry)"} …`);
705
721
  let buf;
706
722
  try {
707
- const r = await fetch(url, { signal: AbortSignal.timeout(60000) });
723
+ const r = await fetch(src, { signal: AbortSignal.timeout(60000) });
708
724
  if (!r.ok)
709
725
  throw new Error(`HTTP ${r.status}`);
710
726
  buf = Buffer.from(await r.arrayBuffer());
711
727
  }
712
728
  catch (e) {
713
- console.error(`could not download ${url}: ${e instanceof Error ? e.message : e}. Nothing was installed.`);
729
+ console.error(`could not download ${src}: ${e instanceof Error ? e.message : e}. Nothing was installed.${src !== url ? " Try can2cup upgrade --from-relay" : ""}`);
714
730
  process.exit(1);
715
731
  }
716
732
  const actual = createHash("sha256").update(buf).digest("hex");
@@ -1378,7 +1394,7 @@ async function doctor() {
1378
1394
  else if (latest === VERSION)
1379
1395
  ok(`can2cup ${VERSION} (latest)`);
1380
1396
  else
1381
- warn(`can2cup ${VERSION}, relay serves ${latest}`, `can2cup upgrade (= npm i -g ${DEFAULT_RELAY}/dl/can2cup.tgz; if npm says EEXIST for an old \`parley\` command: npm rm -g parley first)`);
1397
+ warn(`can2cup ${VERSION}, relay serves ${latest}`, `can2cup upgrade (downloads can2cup@${latest} from the npm registry, checks it against the signed manifest, installs; --from-relay uses ${DEFAULT_RELAY}/dl/can2cup.tgz)`);
1382
1398
  // 3. identity / mcp / skill
1383
1399
  const hasId = fs.existsSync(path.join(HOME, "identity.json"));
1384
1400
  if (hasId)
package/package.json CHANGED
@@ -1,55 +1,56 @@
1
- {
2
- "name": "can2cup",
3
- "version": "0.10.0",
4
- "description": "can2cup 傳聲罐罐 — a tin can, a paper cup, one string: signed rooms where two people's AI agents talk under their principals' mandates.",
5
- "type": "module",
6
- "homepage": "https://can2cup.com",
7
- "repository": { "type": "git", "url": "git+https://github.com/ccqqder/can2cup.git" },
8
- "bugs": { "url": "https://can2cup.com/guide/#faq" },
9
- "keywords": ["mcp", "agent", "a2a", "line", "ed25519", "claude-code", "can2cup", "傳聲罐罐"],
10
- "engines": { "node": ">=18" },
11
- "publishConfig": { "access": "public" },
12
- "bin": {
13
- "can2cup": "dist/cli/index.js",
14
- "can2cup-mcp": "dist/mcp/index.js",
15
- "can2can": "dist/cli/index.js",
16
- "parley": "dist/cli/index.js"
17
- },
18
- "scripts": {
19
- "build": "tsc -p tsconfig.json",
20
- "check:relay": "tsc -p tsconfig.relay.json --noEmit",
21
- "dev:relay": "wrangler dev --local-upstream 127.0.0.1 --upstream-protocol http",
22
- "deploy:relay": "wrangler deploy",
23
- "release:relay": "node scripts/routes-check.mjs && node scripts/stage-tarball.mjs && node scripts/release-sign.mjs && wrangler deploy",
24
- "release:key": "node scripts/release-key.mjs",
25
- "check:routes": "node scripts/routes-check.mjs",
26
- "smoke": "node dist/scripts/smoke.js",
27
- "view": "node dist/viewer/index.js",
28
- "pack": "npm run build && npm pack"
29
- },
30
- "license": "Apache-2.0",
31
- "dependencies": {
32
- "@modelcontextprotocol/sdk": "^1.30.0",
33
- "@noble/ed25519": "^3.1.0",
34
- "@noble/hashes": "^2.3.0",
35
- "hono": "^4.13.2",
36
- "qrcode": "^1.5.4",
37
- "zod": "^4.4.3"
38
- },
39
- "devDependencies": {
40
- "@cloudflare/workers-types": "^5.20260818.1",
41
- "@types/node": "^26.2.0",
42
- "@types/qrcode": "^1.5.6",
43
- "typescript": "^5.9.3",
44
- "wrangler": "^4.123.0"
45
- },
46
- "files": [
47
- "dist",
48
- "!dist/scripts",
49
- "README.md",
50
- "SKILL.md",
51
- "INSTALL.zh-tw.md",
52
- "LICENSE",
53
- "NOTICE"
54
- ]
55
- }
1
+ {
2
+ "name": "can2cup",
3
+ "version": "0.10.1",
4
+ "description": "can2cup 傳聲罐罐 — a tin can, a paper cup, one string: signed rooms where two people's AI agents talk under their principals' mandates.",
5
+ "type": "module",
6
+ "homepage": "https://can2cup.com",
7
+ "repository": { "type": "git", "url": "git+https://github.com/ccqqder/can2cup.git" },
8
+ "bugs": { "url": "https://can2cup.com/guide/#faq" },
9
+ "keywords": ["mcp", "agent", "a2a", "line", "ed25519", "claude-code", "can2cup", "傳聲罐罐"],
10
+ "engines": { "node": ">=18" },
11
+ "publishConfig": { "access": "public" },
12
+ "bin": {
13
+ "can2cup": "dist/cli/index.js",
14
+ "can2cup-mcp": "dist/mcp/index.js",
15
+ "can2can": "dist/cli/index.js",
16
+ "parley": "dist/cli/index.js"
17
+ },
18
+ "scripts": {
19
+ "build": "tsc -p tsconfig.json",
20
+ "check:relay": "tsc -p tsconfig.relay.json --noEmit",
21
+ "dev:relay": "wrangler dev --local-upstream 127.0.0.1 --upstream-protocol http",
22
+ "deploy:relay": "wrangler deploy",
23
+ "release:relay": "node scripts/routes-check.mjs && node scripts/stage-tarball.mjs && node scripts/release-sign.mjs && wrangler deploy",
24
+ "release:key": "node scripts/release-key.mjs",
25
+ "release:npm": "node scripts/release-npm.mjs",
26
+ "check:routes": "node scripts/routes-check.mjs",
27
+ "smoke": "node dist/scripts/smoke.js",
28
+ "view": "node dist/viewer/index.js",
29
+ "pack": "npm run build && npm pack"
30
+ },
31
+ "license": "Apache-2.0",
32
+ "dependencies": {
33
+ "@modelcontextprotocol/sdk": "^1.30.0",
34
+ "@noble/ed25519": "^3.1.0",
35
+ "@noble/hashes": "^2.3.0",
36
+ "hono": "^4.13.2",
37
+ "qrcode": "^1.5.4",
38
+ "zod": "^4.4.3"
39
+ },
40
+ "devDependencies": {
41
+ "@cloudflare/workers-types": "^5.20260818.1",
42
+ "@types/node": "^26.2.0",
43
+ "@types/qrcode": "^1.5.6",
44
+ "typescript": "^5.9.3",
45
+ "wrangler": "^4.123.0"
46
+ },
47
+ "files": [
48
+ "dist",
49
+ "!dist/scripts",
50
+ "README.md",
51
+ "SKILL.md",
52
+ "INSTALL.zh-tw.md",
53
+ "LICENSE",
54
+ "NOTICE"
55
+ ]
56
+ }