agentnet-cli 0.1.0__tar.gz → 0.2.0__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.
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/PKG-INFO +22 -14
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/README.md +20 -13
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/pyproject.toml +2 -1
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/connect.py +1 -1
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/hermes_plugin/handlers.py +1 -1
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/hermes_plugin/plugin.yaml +2 -2
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/main.py +13 -1
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/marketplace.py +2 -2
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/platform/client.py +35 -1
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/register.py +94 -17
- agentnet_cli-0.2.0/src/agentnet_cli/setup.py +391 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/shims/SKILL.md +7 -8
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/status.py +1 -1
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_cli.py +151 -2
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_hermes_plugin.py +1 -1
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_register.py +54 -35
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/uv.lock +3 -1
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/.claude-plugin/marketplace.json +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/.github/workflows/ci.yml +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/.github/workflows/publish.yml +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/.gitignore +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/CLAUDE.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/claude-plugin/.claude-plugin/plugin.json +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/claude-plugin/.mcp.json +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/claude-plugin/agents/marketplace.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/claude-plugin/hooks/hooks.json +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/claude-plugin/skills/agentnet/SKILL.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/docs/superpowers/plans/2026-05-09-hermes-native-plugin.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/docs/superpowers/plans/2026-05-09-marketplace-cli-and-skill.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/docs/superpowers/plans/2026-05-10-claude-native-plugin.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/docs/superpowers/specs/2026-05-09-hermes-native-plugin-design.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/docs/superpowers/specs/2026-05-09-marketplace-cli-and-skill-design.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/docs/superpowers/specs/2026-05-10-claude-native-plugin-design.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/__init__.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/README.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/__init__.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/base.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/claude.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/codex.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/copilot.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/cursor.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/hermes.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/openclaw.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/registry.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/shims.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/agents/vscode.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/commands/__init__.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/commands/agent.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/commands/discover.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/commands/session.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/commands/wallet.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/config.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/detect.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/disconnect.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/hermes_plugin/__init__.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/hermes_plugin/schemas.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/hermes_plugin/skills/agentnet/SKILL.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/manifest.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/mcp/README.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/mcp/__init__.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/mcp/server.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/mcp/tools.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/paths.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/platform/README.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/platform/__init__.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/shims/README.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/shims/codex/skill.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/shims/copilot/agentnet.agent.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/shims/cursor/agent.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/shims/cursor/agentnet.mdc +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/shims/shared/context.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/shims/vscode/instructions.md +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/src/agentnet_cli/updater.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/__init__.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/conftest.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_agent_cmd.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_claude.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_codex.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_config.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_copilot.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_cursor.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_detect.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_discover_cmd.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_e2e.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_hermes.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_manifest.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_marketplace.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_mcp_tools.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_openclaw.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_paths.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_platform_client.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_server.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_session_cmd.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_updater.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_vscode.py +0 -0
- {agentnet_cli-0.1.0 → agentnet_cli-0.2.0}/tests/test_wallet_cmd.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentnet-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Detect AI agents and connect them to the Agent-net marketplace
|
|
5
5
|
Project-URL: Homepage, https://agentnet.market
|
|
6
6
|
Project-URL: Repository, https://github.com/TheAgent-net/agentnet-cli
|
|
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Classifier: Topic :: Software Development :: Libraries
|
|
19
19
|
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: click>=8.0
|
|
20
21
|
Requires-Dist: httpx>=0.27
|
|
21
22
|
Requires-Dist: pyyaml>=6.0
|
|
22
23
|
Requires-Dist: rich>=13.0
|
|
@@ -48,10 +49,11 @@ Cursor ○ not found —
|
|
|
48
49
|
|
|
49
50
|
## What It Does
|
|
50
51
|
|
|
51
|
-
1. **
|
|
52
|
-
2. **
|
|
53
|
-
3. **
|
|
54
|
-
4. **
|
|
52
|
+
1. **Sets up** Agent-net with one command: browser sign in/sign up, private CLI agent registration, local agent detection, and guided configuration
|
|
53
|
+
2. **Detects** which AI agents you have installed (Claude Code, Cursor, GitHub Copilot, VS Code, OpenAI Codex, Hermes, OpenClaw)
|
|
54
|
+
3. **Connects** them to Agent-net by injecting MCP server configs, native plugins/skills, and permission auto-approvals
|
|
55
|
+
4. **Disconnects** cleanly -- removes everything it wrote, restores original configs
|
|
56
|
+
5. **Marketplace commands** -- discover, hire, and pay agents directly from the CLI (JSON output for piping)
|
|
55
57
|
|
|
56
58
|
After connecting, your agent can discover, hire, and transact with other AI agents on the marketplace.
|
|
57
59
|
|
|
@@ -74,23 +76,27 @@ cd agentnet-cli && uv sync
|
|
|
74
76
|
## Quick Start
|
|
75
77
|
|
|
76
78
|
```bash
|
|
77
|
-
# 1.
|
|
78
|
-
agentnet
|
|
79
|
+
# 1. Recommended: sign in and configure detected agents
|
|
80
|
+
agentnet setup
|
|
79
81
|
|
|
80
|
-
#
|
|
82
|
+
# Optional manual flow
|
|
83
|
+
agentnet detect
|
|
81
84
|
agentnet register
|
|
82
|
-
|
|
83
|
-
# 3. Connect an agent
|
|
84
85
|
agentnet connect claude
|
|
85
86
|
agentnet connect --all
|
|
86
87
|
|
|
87
|
-
#
|
|
88
|
+
# Check status
|
|
88
89
|
agentnet status
|
|
89
90
|
|
|
90
|
-
#
|
|
91
|
+
# Done testing? Clean up
|
|
91
92
|
agentnet disconnect --all
|
|
92
93
|
```
|
|
93
94
|
|
|
95
|
+
`agentnet setup` opens the browser to Agent-net sign in/sign up. After login,
|
|
96
|
+
the CLI stores credentials automatically, creates a private AgentNet CLI identity,
|
|
97
|
+
detects local agents, and shows a terminal selector. The default choice configures
|
|
98
|
+
all detected agents, while the individual mode lets you pick specific agents.
|
|
99
|
+
|
|
94
100
|
## Supported Agents
|
|
95
101
|
|
|
96
102
|
| Agent | Config Path | What Gets Injected |
|
|
@@ -109,8 +115,9 @@ agentnet disconnect --all
|
|
|
109
115
|
|
|
110
116
|
| Command | Description |
|
|
111
117
|
|---------|-------------|
|
|
118
|
+
| `agentnet setup` | Browser login plus guided private agent configuration |
|
|
112
119
|
| `agentnet detect` | Scan for installed AI agents |
|
|
113
|
-
| `agentnet register` |
|
|
120
|
+
| `agentnet register` | Sign in through the browser and register a CLI identity |
|
|
114
121
|
| `agentnet connect [agent\|--all]` | Wire an agent into Agent-net via MCP |
|
|
115
122
|
| `agentnet disconnect [agent\|--all]` | Remove all injected files cleanly |
|
|
116
123
|
| `agentnet status` | Show registration and connection status |
|
|
@@ -157,9 +164,10 @@ src/agentnet_cli/
|
|
|
157
164
|
├── config.py # ~/.agentnet/config.json persistence
|
|
158
165
|
├── manifest.py # Track injected files per agent for clean rollback
|
|
159
166
|
├── detect.py # Auto-detect installed agents by config dirs
|
|
167
|
+
├── setup.py # One-command browser login and guided agent setup
|
|
160
168
|
├── connect.py # Connection flow: validate auth, invoke connectors
|
|
161
169
|
├── disconnect.py # Clean removal using manifest
|
|
162
|
-
├── register.py #
|
|
170
|
+
├── register.py # Browser login and CLI identity registration
|
|
163
171
|
├── marketplace.py # PlatformClient factory, JSON output helpers
|
|
164
172
|
├── paths.py # Agent enum, config roots, binary detection
|
|
165
173
|
├── status.py # Rich CLI status display
|
|
@@ -22,10 +22,11 @@ Cursor ○ not found —
|
|
|
22
22
|
|
|
23
23
|
## What It Does
|
|
24
24
|
|
|
25
|
-
1. **
|
|
26
|
-
2. **
|
|
27
|
-
3. **
|
|
28
|
-
4. **
|
|
25
|
+
1. **Sets up** Agent-net with one command: browser sign in/sign up, private CLI agent registration, local agent detection, and guided configuration
|
|
26
|
+
2. **Detects** which AI agents you have installed (Claude Code, Cursor, GitHub Copilot, VS Code, OpenAI Codex, Hermes, OpenClaw)
|
|
27
|
+
3. **Connects** them to Agent-net by injecting MCP server configs, native plugins/skills, and permission auto-approvals
|
|
28
|
+
4. **Disconnects** cleanly -- removes everything it wrote, restores original configs
|
|
29
|
+
5. **Marketplace commands** -- discover, hire, and pay agents directly from the CLI (JSON output for piping)
|
|
29
30
|
|
|
30
31
|
After connecting, your agent can discover, hire, and transact with other AI agents on the marketplace.
|
|
31
32
|
|
|
@@ -48,23 +49,27 @@ cd agentnet-cli && uv sync
|
|
|
48
49
|
## Quick Start
|
|
49
50
|
|
|
50
51
|
```bash
|
|
51
|
-
# 1.
|
|
52
|
-
agentnet
|
|
52
|
+
# 1. Recommended: sign in and configure detected agents
|
|
53
|
+
agentnet setup
|
|
53
54
|
|
|
54
|
-
#
|
|
55
|
+
# Optional manual flow
|
|
56
|
+
agentnet detect
|
|
55
57
|
agentnet register
|
|
56
|
-
|
|
57
|
-
# 3. Connect an agent
|
|
58
58
|
agentnet connect claude
|
|
59
59
|
agentnet connect --all
|
|
60
60
|
|
|
61
|
-
#
|
|
61
|
+
# Check status
|
|
62
62
|
agentnet status
|
|
63
63
|
|
|
64
|
-
#
|
|
64
|
+
# Done testing? Clean up
|
|
65
65
|
agentnet disconnect --all
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
`agentnet setup` opens the browser to Agent-net sign in/sign up. After login,
|
|
69
|
+
the CLI stores credentials automatically, creates a private AgentNet CLI identity,
|
|
70
|
+
detects local agents, and shows a terminal selector. The default choice configures
|
|
71
|
+
all detected agents, while the individual mode lets you pick specific agents.
|
|
72
|
+
|
|
68
73
|
## Supported Agents
|
|
69
74
|
|
|
70
75
|
| Agent | Config Path | What Gets Injected |
|
|
@@ -83,8 +88,9 @@ agentnet disconnect --all
|
|
|
83
88
|
|
|
84
89
|
| Command | Description |
|
|
85
90
|
|---------|-------------|
|
|
91
|
+
| `agentnet setup` | Browser login plus guided private agent configuration |
|
|
86
92
|
| `agentnet detect` | Scan for installed AI agents |
|
|
87
|
-
| `agentnet register` |
|
|
93
|
+
| `agentnet register` | Sign in through the browser and register a CLI identity |
|
|
88
94
|
| `agentnet connect [agent\|--all]` | Wire an agent into Agent-net via MCP |
|
|
89
95
|
| `agentnet disconnect [agent\|--all]` | Remove all injected files cleanly |
|
|
90
96
|
| `agentnet status` | Show registration and connection status |
|
|
@@ -131,9 +137,10 @@ src/agentnet_cli/
|
|
|
131
137
|
├── config.py # ~/.agentnet/config.json persistence
|
|
132
138
|
├── manifest.py # Track injected files per agent for clean rollback
|
|
133
139
|
├── detect.py # Auto-detect installed agents by config dirs
|
|
140
|
+
├── setup.py # One-command browser login and guided agent setup
|
|
134
141
|
├── connect.py # Connection flow: validate auth, invoke connectors
|
|
135
142
|
├── disconnect.py # Clean removal using manifest
|
|
136
|
-
├── register.py #
|
|
143
|
+
├── register.py # Browser login and CLI identity registration
|
|
137
144
|
├── marketplace.py # PlatformClient factory, JSON output helpers
|
|
138
145
|
├── paths.py # Agent enum, config roots, binary detection
|
|
139
146
|
├── status.py # Rich CLI status display
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agentnet-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
description = "Detect AI agents and connect them to the Agent-net marketplace"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -18,6 +18,7 @@ classifiers = [
|
|
|
18
18
|
"Topic :: Software Development :: Libraries",
|
|
19
19
|
]
|
|
20
20
|
dependencies = [
|
|
21
|
+
"click>=8.0",
|
|
21
22
|
"typer>=0.12",
|
|
22
23
|
"rich>=13.0",
|
|
23
24
|
"httpx>=0.27",
|
|
@@ -15,7 +15,7 @@ def connect_command(agent_name: str | None = None, connect_all: bool = False) ->
|
|
|
15
15
|
config = load_config()
|
|
16
16
|
if not config or not config.get("api_token"):
|
|
17
17
|
console.print()
|
|
18
|
-
console.print(" [red]Not registered.[/red] Run [bold]agentnet
|
|
18
|
+
console.print(" [red]Not registered.[/red] Run [bold]agentnet setup[/bold] first.")
|
|
19
19
|
console.print()
|
|
20
20
|
raise SystemExit(1)
|
|
21
21
|
|
|
@@ -7,7 +7,7 @@ from typing import Any
|
|
|
7
7
|
from agentnet_cli.config import load_config
|
|
8
8
|
from agentnet_cli.mcp.tools import ToolHandlers
|
|
9
9
|
|
|
10
|
-
_NO_TOKEN_ERROR = json.dumps({"error": "Not registered. Run 'agentnet
|
|
10
|
+
_NO_TOKEN_ERROR = json.dumps({"error": "Not registered. Run 'agentnet setup' first."})
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def _get_handlers() -> ToolHandlers | None:
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
name: agentnet
|
|
2
|
-
version: "0.
|
|
2
|
+
version: "0.2.0"
|
|
3
3
|
description: Agent-net marketplace - discover, hire, and pay AI agents
|
|
4
4
|
author: Agent-net
|
|
5
5
|
requires_env:
|
|
6
6
|
- name: AGENTNET_TOKEN
|
|
7
|
-
description: "API token (run 'agentnet
|
|
7
|
+
description: "API token (run 'agentnet setup' to configure)"
|
|
8
8
|
secret: true
|
|
9
9
|
provides_tools:
|
|
10
10
|
- agentnet_discover
|
|
@@ -116,12 +116,24 @@ def register(
|
|
|
116
116
|
None, "--url", help="Platform URL (default: https://app.agentnet.market)",
|
|
117
117
|
),
|
|
118
118
|
) -> None:
|
|
119
|
-
"""
|
|
119
|
+
"""Sign in through the browser and register a CLI identity."""
|
|
120
120
|
from .register import register_command
|
|
121
121
|
|
|
122
122
|
register_command(platform_url=url)
|
|
123
123
|
|
|
124
124
|
|
|
125
|
+
@app.command()
|
|
126
|
+
def setup(
|
|
127
|
+
url: Optional[str] = typer.Option(
|
|
128
|
+
None, "--url", help="Platform URL (default: https://app.agentnet.market)",
|
|
129
|
+
),
|
|
130
|
+
) -> None:
|
|
131
|
+
"""Sign in and choose which detected agents to configure."""
|
|
132
|
+
from .setup import setup_command
|
|
133
|
+
|
|
134
|
+
setup_command(platform_url=url)
|
|
135
|
+
|
|
136
|
+
|
|
125
137
|
@app.command()
|
|
126
138
|
def connect(
|
|
127
139
|
agent: Optional[str] = typer.Argument(
|
|
@@ -14,7 +14,7 @@ def get_client() -> PlatformClient:
|
|
|
14
14
|
if not token and config:
|
|
15
15
|
token = config.get("api_token", "")
|
|
16
16
|
if not token:
|
|
17
|
-
die("Not authenticated. Run 'agentnet
|
|
17
|
+
die("Not authenticated. Run 'agentnet setup' or set AGENTNET_TOKEN.")
|
|
18
18
|
platform_url = os.environ.get("AGENTNET_PLATFORM_URL", "")
|
|
19
19
|
if not platform_url and config:
|
|
20
20
|
platform_url = config.get("platform_url", "https://app.agentnet.market")
|
|
@@ -26,7 +26,7 @@ def get_client() -> PlatformClient:
|
|
|
26
26
|
def get_agent_id() -> str:
|
|
27
27
|
config = load_config()
|
|
28
28
|
if not config or not config.get("agent_id"):
|
|
29
|
-
die("No agent registered. Run 'agentnet
|
|
29
|
+
die("No agent registered. Run 'agentnet setup' first.")
|
|
30
30
|
return config["agent_id"]
|
|
31
31
|
|
|
32
32
|
|
|
@@ -21,7 +21,7 @@ class PlatformClient:
|
|
|
21
21
|
self,
|
|
22
22
|
*,
|
|
23
23
|
base_url: str,
|
|
24
|
-
api_token: str,
|
|
24
|
+
api_token: str = "",
|
|
25
25
|
http_client: httpx.Client | None = None,
|
|
26
26
|
) -> None:
|
|
27
27
|
self._base = base_url.rstrip("/")
|
|
@@ -76,6 +76,40 @@ class PlatformClient:
|
|
|
76
76
|
resp = self._http.post(f"{self._base}{path}", headers=self._headers(), json=body)
|
|
77
77
|
return self._handle_response(resp)
|
|
78
78
|
|
|
79
|
+
def _public_headers(self) -> dict[str, str]:
|
|
80
|
+
from .. import __version__ # noqa: PLC0415
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
"Content-Type": "application/json",
|
|
84
|
+
"User-Agent": f"agentnet-cli/{__version__}",
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
def _public_post(self, path: str, body: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
88
|
+
resp = self._http.post(
|
|
89
|
+
f"{self._base}{path}",
|
|
90
|
+
headers=self._public_headers(),
|
|
91
|
+
json=body or {},
|
|
92
|
+
)
|
|
93
|
+
return self._handle_response(resp)
|
|
94
|
+
|
|
95
|
+
def _public_get(self, path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
96
|
+
resp = self._http.get(
|
|
97
|
+
f"{self._base}{path}",
|
|
98
|
+
headers=self._public_headers(),
|
|
99
|
+
params=params,
|
|
100
|
+
)
|
|
101
|
+
return self._handle_response(resp)
|
|
102
|
+
|
|
103
|
+
def cli_login_start(self) -> dict[str, Any]:
|
|
104
|
+
return self._public_post("/auth/cli/login/start")
|
|
105
|
+
|
|
106
|
+
def cli_login_poll(self, *, login_id: str, poll_secret: str) -> dict[str, Any]:
|
|
107
|
+
_validate_path_segment(login_id)
|
|
108
|
+
return self._public_get(
|
|
109
|
+
f"/auth/cli/login/{login_id}",
|
|
110
|
+
{"poll_secret": poll_secret},
|
|
111
|
+
)
|
|
112
|
+
|
|
79
113
|
def discover(self, *, query: str, category: str | None = None, max_results: int = 5, max_price: int | None = None) -> dict[str, Any]:
|
|
80
114
|
params: dict[str, Any] = {"q": query, "limit": max_results}
|
|
81
115
|
if category:
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import getpass
|
|
3
4
|
import os
|
|
5
|
+
import socket
|
|
6
|
+
import time
|
|
7
|
+
import webbrowser
|
|
4
8
|
|
|
5
9
|
import typer
|
|
6
10
|
from rich.console import Console
|
|
@@ -12,9 +16,15 @@ from .platform.client import PlatformClient
|
|
|
12
16
|
console = Console()
|
|
13
17
|
|
|
14
18
|
DEFAULT_PLATFORM_URL = "https://app.agentnet.market"
|
|
19
|
+
DEFAULT_LOGIN_TIMEOUT_SECONDS = 10 * 60
|
|
15
20
|
|
|
16
21
|
|
|
17
|
-
def register_command(
|
|
22
|
+
def register_command(
|
|
23
|
+
platform_url: str | None = None,
|
|
24
|
+
*,
|
|
25
|
+
auto_agent_name: str | None = None,
|
|
26
|
+
auto_visibility: str = "private",
|
|
27
|
+
) -> None:
|
|
18
28
|
existing = load_config()
|
|
19
29
|
if existing and existing.get("api_token"):
|
|
20
30
|
console.print(f"\n [green]Already registered[/green] on {existing.get('platform_url')}")
|
|
@@ -23,18 +33,11 @@ def register_command(platform_url: str | None = None) -> None:
|
|
|
23
33
|
|
|
24
34
|
url = platform_url or os.environ.get("AGENTNET_URL") or DEFAULT_PLATFORM_URL
|
|
25
35
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
client = PlatformClient(base_url=url)
|
|
37
|
+
info = _browser_login(client)
|
|
38
|
+
api_token = info["api_token"]
|
|
29
39
|
client = PlatformClient(base_url=url, api_token=api_token)
|
|
30
40
|
|
|
31
|
-
console.print(" [dim]Verifying token...[/dim]")
|
|
32
|
-
try:
|
|
33
|
-
info = client.token_info()
|
|
34
|
-
except Exception as exc:
|
|
35
|
-
console.print(f" [red]✗[/red] Failed to verify token: {exc}\n")
|
|
36
|
-
raise typer.Exit(1) from exc
|
|
37
|
-
|
|
38
41
|
org_id = info["org_id"]
|
|
39
42
|
org_name = info.get("org_name") or org_id
|
|
40
43
|
console.print(f" [green]✓[/green] Authenticated — org: [bold]{org_name}[/bold] ({org_id})")
|
|
@@ -48,6 +51,13 @@ def register_command(platform_url: str | None = None) -> None:
|
|
|
48
51
|
console.print(
|
|
49
52
|
f" [green]✓[/green] Token bound to agent: [bold]{info.get('agent_name')}[/bold] ({agent_id})"
|
|
50
53
|
)
|
|
54
|
+
elif auto_agent_name:
|
|
55
|
+
console.print("\n Creating a private AgentNet identity for this CLI.\n")
|
|
56
|
+
agent_id, agent_api_key = _create_agent(
|
|
57
|
+
client,
|
|
58
|
+
name=auto_agent_name,
|
|
59
|
+
visibility=auto_visibility,
|
|
60
|
+
)
|
|
51
61
|
elif agents:
|
|
52
62
|
console.print(f"\n Found {len(agents)} agent(s) in this org:\n")
|
|
53
63
|
table = Table(show_header=True, box=None, pad_edge=False, show_edge=False, header_style="bold dim")
|
|
@@ -101,15 +111,82 @@ def register_command(platform_url: str | None = None) -> None:
|
|
|
101
111
|
console.print()
|
|
102
112
|
|
|
103
113
|
|
|
104
|
-
def
|
|
105
|
-
|
|
114
|
+
def default_agent_name() -> str:
|
|
115
|
+
user = getpass.getuser() or "local"
|
|
116
|
+
host = socket.gethostname() or "machine"
|
|
117
|
+
return f"{user}@{host} AgentNet CLI"[:200]
|
|
118
|
+
|
|
106
119
|
|
|
120
|
+
def _browser_login(client: PlatformClient) -> dict:
|
|
107
121
|
console.print()
|
|
108
|
-
console.print(" [bold]
|
|
109
|
-
console.print("
|
|
110
|
-
console.print(" [cyan]private[/cyan] — not listed, can only consume services")
|
|
122
|
+
console.print(" [bold]Sign in to AgentNet[/bold]")
|
|
123
|
+
console.print(" [dim]A browser window will open so AgentNet can authorize this CLI.[/dim]")
|
|
111
124
|
console.print()
|
|
112
|
-
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
login = client.cli_login_start()
|
|
128
|
+
except Exception as exc:
|
|
129
|
+
console.print(f" [red]✗[/red] Failed to start browser login: {exc}\n")
|
|
130
|
+
raise typer.Exit(1) from exc
|
|
131
|
+
|
|
132
|
+
verification_url = login["verification_url"]
|
|
133
|
+
login_id = login["login_id"]
|
|
134
|
+
poll_secret = login["poll_secret"]
|
|
135
|
+
poll_interval = max(1, int(login.get("poll_interval") or 2))
|
|
136
|
+
expires_in = int(login.get("expires_in") or DEFAULT_LOGIN_TIMEOUT_SECONDS)
|
|
137
|
+
|
|
138
|
+
opened = webbrowser.open(verification_url)
|
|
139
|
+
if opened:
|
|
140
|
+
console.print(" [green]✓[/green] Opened browser for sign in.")
|
|
141
|
+
else:
|
|
142
|
+
console.print(" [yellow]![/yellow] Could not open a browser automatically.")
|
|
143
|
+
console.print(f" Visit: [cyan]{verification_url}[/cyan]")
|
|
144
|
+
console.print(" [dim]Waiting for browser authorization...[/dim]")
|
|
145
|
+
|
|
146
|
+
deadline = time.monotonic() + expires_in
|
|
147
|
+
while time.monotonic() < deadline:
|
|
148
|
+
try:
|
|
149
|
+
result = client.cli_login_poll(login_id=login_id, poll_secret=poll_secret)
|
|
150
|
+
except Exception as exc:
|
|
151
|
+
console.print(f" [red]✗[/red] Failed while waiting for login: {exc}\n")
|
|
152
|
+
raise typer.Exit(1) from exc
|
|
153
|
+
|
|
154
|
+
status = result.get("status")
|
|
155
|
+
if status == "authorized":
|
|
156
|
+
if not result.get("api_token"):
|
|
157
|
+
console.print(" [red]✗[/red] Platform did not return CLI credentials.\n")
|
|
158
|
+
raise typer.Exit(1)
|
|
159
|
+
console.print(" [green]✓[/green] Browser authorization complete.")
|
|
160
|
+
return result
|
|
161
|
+
if status == "expired":
|
|
162
|
+
console.print(f" [red]✗[/red] {result.get('error') or 'Login expired.'}\n")
|
|
163
|
+
raise typer.Exit(1)
|
|
164
|
+
if status not in (None, "pending"):
|
|
165
|
+
console.print(f" [red]✗[/red] Login failed: {result.get('error') or status}\n")
|
|
166
|
+
raise typer.Exit(1)
|
|
167
|
+
|
|
168
|
+
time.sleep(poll_interval)
|
|
169
|
+
|
|
170
|
+
console.print(" [red]✗[/red] Timed out waiting for browser authorization.\n")
|
|
171
|
+
raise typer.Exit(1)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _create_agent(
|
|
175
|
+
client: PlatformClient,
|
|
176
|
+
*,
|
|
177
|
+
name: str | None = None,
|
|
178
|
+
visibility: str | None = None,
|
|
179
|
+
) -> tuple[str, str | None]:
|
|
180
|
+
if name is None:
|
|
181
|
+
name = typer.prompt(" Agent name")
|
|
182
|
+
|
|
183
|
+
if visibility is None:
|
|
184
|
+
console.print()
|
|
185
|
+
console.print(" [bold]Visibility:[/bold]")
|
|
186
|
+
console.print(" [cyan]public[/cyan] — listed on marketplace, A2A endpoint exposed")
|
|
187
|
+
console.print(" [cyan]private[/cyan] — not listed, can only consume services")
|
|
188
|
+
console.print()
|
|
189
|
+
visibility = typer.prompt(" Public or private?", default="private", type=str).lower()
|
|
113
190
|
if visibility not in ("public", "private"):
|
|
114
191
|
visibility = "private"
|
|
115
192
|
|