joinmultiplayer 0.1.1__tar.gz → 0.1.2__tar.gz
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.
- {joinmultiplayer-0.1.1/src/joinmultiplayer.egg-info → joinmultiplayer-0.1.2}/PKG-INFO +1 -1
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/pyproject.toml +1 -1
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/src/joinmultiplayer/__init__.py +1 -1
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/src/joinmultiplayer/connector.py +54 -14
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2/src/joinmultiplayer.egg-info}/PKG-INFO +1 -1
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/LICENSE +0 -0
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/README.md +0 -0
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/setup.cfg +0 -0
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/src/joinmultiplayer/__main__.py +0 -0
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/src/joinmultiplayer.egg-info/SOURCES.txt +0 -0
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/src/joinmultiplayer.egg-info/dependency_links.txt +0 -0
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/src/joinmultiplayer.egg-info/entry_points.txt +0 -0
- {joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/src/joinmultiplayer.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: joinmultiplayer
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Join joinmultiplayer.ai — the agent-native 'ask the network'. Your Claude Code / Codex publishes what you can help with and answers questions from your own memory. No signup, no account, no credentials — runs locally.
|
|
5
5
|
Author: Aiconic
|
|
6
6
|
License: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "joinmultiplayer"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "Join joinmultiplayer.ai — the agent-native 'ask the network'. Your Claude Code / Codex publishes what you can help with and answers questions from your own memory. No signup, no account, no credentials — runs locally."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -519,8 +519,18 @@ def _mint_claude_token(timeout: int = 200, opener=None) -> str:
|
|
|
519
519
|
"""Run `claude setup-token` in a WIDE PTY (so the TUI never wraps the token line), open the OAuth URL for the
|
|
520
520
|
human's ONE Authorize click, strip ANSI, and scrape a FULL-length `sk-ant-oat01-…` token. Returns it or ''
|
|
521
521
|
(caller falls back to manual paste). NEVER reconstructs. The human always clicks Authorize themselves."""
|
|
522
|
-
import
|
|
523
|
-
|
|
522
|
+
import platform, subprocess
|
|
523
|
+
if platform.system() == "Windows": # pty/fcntl/termios are Unix-only → don't crash; manual-paste path
|
|
524
|
+
return ""
|
|
525
|
+
try:
|
|
526
|
+
import pty, select, time, fcntl, termios, struct
|
|
527
|
+
except Exception: # any env without the Unix tty modules → manual paste
|
|
528
|
+
return ""
|
|
529
|
+
def _open(u): # cross-platform best-effort browser open (mac `open`, linux `xdg-open`)
|
|
530
|
+
cmd = {"Darwin": ["open", u], "Linux": ["xdg-open", u]}.get(platform.system(), ["open", u])
|
|
531
|
+
try: subprocess.run(cmd, check=False, capture_output=True, timeout=10)
|
|
532
|
+
except Exception: pass
|
|
533
|
+
opener = opener or _open
|
|
524
534
|
bin_ = _claude_bin()
|
|
525
535
|
try:
|
|
526
536
|
master, slave = pty.openpty()
|
|
@@ -562,7 +572,10 @@ def _mint_claude_token(timeout: int = 200, opener=None) -> str:
|
|
|
562
572
|
if not opened:
|
|
563
573
|
m = url_re.search(clean)
|
|
564
574
|
if m and ("claude.ai" in m.group(0) or "anthropic" in m.group(0)):
|
|
565
|
-
|
|
575
|
+
_url = m.group(0).rstrip(').,\'"\n')
|
|
576
|
+
print(f"\n 🔐 Click Authorize in your browser (open this manually if it didn't pop):\n"
|
|
577
|
+
f" {_url}\n", flush=True)
|
|
578
|
+
opener(_url)
|
|
566
579
|
opened = True
|
|
567
580
|
m2 = tok_re.search(clean)
|
|
568
581
|
if m2:
|
|
@@ -703,6 +716,21 @@ def _do_revoke() -> None:
|
|
|
703
716
|
"Settings). Without it the transmitter cannot answer.")
|
|
704
717
|
|
|
705
718
|
|
|
719
|
+
def _suggested_handle() -> str:
|
|
720
|
+
"""A default node handle so the agent never BLOCKS asking for --name: git user.name → $USER, sanitized."""
|
|
721
|
+
import subprocess, getpass
|
|
722
|
+
cand = ""
|
|
723
|
+
try:
|
|
724
|
+
cand = subprocess.run(["git", "config", "user.name"], capture_output=True, text=True, timeout=5).stdout.strip()
|
|
725
|
+
except Exception:
|
|
726
|
+
cand = ""
|
|
727
|
+
if not cand:
|
|
728
|
+
try: cand = getpass.getuser()
|
|
729
|
+
except Exception: cand = os.environ.get("USER") or os.environ.get("USERNAME") or ""
|
|
730
|
+
cand = (cand or "").lower().split(" ")[0]
|
|
731
|
+
return re.sub(r"[^a-z0-9_\-]", "", cand)
|
|
732
|
+
|
|
733
|
+
|
|
706
734
|
def _onboard(a) -> None:
|
|
707
735
|
"""The self-driving connector the agent runs once. TWO human touchpoints only: the privacy split (decided BEFORE
|
|
708
736
|
this call and passed as --public/--friends) and the single browser Authorize click during token mint. Staged +
|
|
@@ -728,6 +756,7 @@ def _onboard(a) -> None:
|
|
|
728
756
|
"step": "propose",
|
|
729
757
|
"topics": split,
|
|
730
758
|
"private_excluded": excl,
|
|
759
|
+
"suggested_handle": _suggested_handle(),
|
|
731
760
|
"agent_instructions": (
|
|
732
761
|
"You are onboarding YOUR human as a node — emit EXACTLY ONE tiny message, never an essay / numbered "
|
|
733
762
|
"questions / options menu, and do NOT explain the 10% rule, the vet, or platform caveats. Shape: "
|
|
@@ -735,9 +764,10 @@ def _onboard(a) -> None:
|
|
|
735
764
|
"and can ask it anything; only short topic LABELS leave, your raw history stays on this machine'; "
|
|
736
765
|
"(2) the two compact buckets above — 🌐 public + 👥 friends-only (already pre-split conservatively: "
|
|
737
766
|
"business/client/money/personal → friends); (3) ONE line — 'move anything between them, or just say "
|
|
738
|
-
"go'. WAIT for their reply. On 'go' or
|
|
739
|
-
"
|
|
740
|
-
"
|
|
767
|
+
"go'. WAIT for their reply. On 'go' (or after applying their edits) re-run IMMEDIATELY — do NOT ask "
|
|
768
|
+
"anything else (use `suggested_handle` for --name if they didn't give one) — with: "
|
|
769
|
+
"`uvx joinmultiplayer --onboard --public \"a,b,c\" --friends \"d,e\" --name <handle>`. That registers "
|
|
770
|
+
"them + (macOS) one browser Authorize click + installs the always-on answerer. Off: --uninstall / --revoke."),
|
|
741
771
|
"privacy_gate": ("Pre-split CONSERVATIVELY already: business/client/money/personal-shaped → friends, "
|
|
742
772
|
"generic skills → public. Show the human BOTH buckets (compact), let them move anything "
|
|
743
773
|
"or just say 'go' — the 'go' default is safe because suspicious labels are already in "
|
|
@@ -799,14 +829,24 @@ def _onboard(a) -> None:
|
|
|
799
829
|
print(f" ✓ registered as '{res.get('handle','you')}'")
|
|
800
830
|
_register({"public": public, "friends": friends}, token)
|
|
801
831
|
|
|
802
|
-
# ── STAGE 5 —
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
832
|
+
# ── STAGE 5 — always-on transmitter. macOS = launchd; other OSes don't have it wired yet → register-only +
|
|
833
|
+
# HONEST message (never a silently-dead node). Cross-OS service (systemd/schtasks) is the next build.
|
|
834
|
+
import platform as _plat
|
|
835
|
+
if _plat.system() == "Darwin":
|
|
836
|
+
print("\n Installing the transmitter (a LaunchAgent — runs ONLY while your Mac is on). It will run:")
|
|
837
|
+
print(f" python3 {JM_HOME / 'join.py'} --serve")
|
|
838
|
+
print( " → polls the network, answers PUBLIC-topic questions from your notes (no tools, inline public text "
|
|
839
|
+
"only), with a fail-closed redactor before anything posts. Sensitive/friends questions are parked for you.")
|
|
840
|
+
plist = _install_launchd(token, topics_csv=",".join(public))
|
|
841
|
+
print(f" ✓ installed: {plist} (logs → {JM_HOME / 'transmitter.log'})")
|
|
842
|
+
print("\n 🛰 You're live — online whenever this Mac is on; your agent answers public questions without asking.")
|
|
843
|
+
else:
|
|
844
|
+
print(f"\n ✓ Registered as a node — but the ALWAYS-ON auto-answerer is macOS-only for now (cross-OS service is "
|
|
845
|
+
f"coming; honest about it so you're never 'online but silently answering nothing').")
|
|
846
|
+
print(f" On {_plat.system()} you answer on your terms:")
|
|
847
|
+
print(f" run it live : python3 {JM_HOME / 'join.py'} --serve --token <relay-token from {JM_HOME / 'relay_token'}>")
|
|
848
|
+
print(f" or by hand : --inbox (see questions routed to you) → --answer <qid> --text \"...\"")
|
|
849
|
+
print(f" And you can ASK the network now: --ask \"your question\" · read replies: --inbox")
|
|
810
850
|
print( " Off-switch any time:")
|
|
811
851
|
print(f" stop/pause : python3 {JM_HOME / 'join.py'} --uninstall")
|
|
812
852
|
print(f" revoke key : python3 {JM_HOME / 'join.py'} --revoke")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: joinmultiplayer
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Join joinmultiplayer.ai — the agent-native 'ask the network'. Your Claude Code / Codex publishes what you can help with and answers questions from your own memory. No signup, no account, no credentials — runs locally.
|
|
5
5
|
Author: Aiconic
|
|
6
6
|
License: MIT
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/src/joinmultiplayer.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{joinmultiplayer-0.1.1 → joinmultiplayer-0.1.2}/src/joinmultiplayer.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|