arkclaw-webchat-cli 0.2.0__tar.gz → 0.3.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.
Files changed (25) hide show
  1. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/PKG-INFO +27 -14
  2. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/README.md +26 -13
  3. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/pyproject.toml +1 -1
  4. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/cli.py +14 -0
  5. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/config.py +39 -0
  6. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/flows.py +78 -18
  7. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/.gitignore +0 -0
  8. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/__init__.py +0 -0
  9. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/attachments.py +0 -0
  10. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/control.py +0 -0
  11. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/core.py +0 -0
  12. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/doctor.py +0 -0
  13. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/errors.py +0 -0
  14. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/identity.py +0 -0
  15. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/oauth.py +0 -0
  16. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/output.py +0 -0
  17. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/policy.py +0 -0
  18. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/providers.py +0 -0
  19. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/secrets_store.py +0 -0
  20. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/sts.py +0 -0
  21. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/transport/__init__.py +0 -0
  22. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/transport/a2a.py +0 -0
  23. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/transport/base.py +0 -0
  24. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/transport/openclaw.py +0 -0
  25. {arkclaw_webchat_cli-0.2.0 → arkclaw_webchat_cli-0.3.0}/src/ee_claw/update.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arkclaw-webchat-cli
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: CLI to chat with an ArkClaw EE space's Claw over enterprise SSO — zero permanent AK/SK.
5
5
  Author: ArkClaw Team
6
6
  Keywords: arkclaw,cli,ee,openclaw,sso,sts
@@ -29,9 +29,10 @@ own SSO identity, no passwords, no permanent keys.** Works the same for a human
29
29
  at a prompt and for another agent/script (`--json` + exit codes).
30
30
 
31
31
  ```bash
32
- arkclaw login https://your-space.arkclaw-enterprise-bj.volceapi.com # browser SSO, once
33
- arkclaw agents # list the claws you can chat
34
- arkclaw chat ci-xxxxxxxx # talk to one
32
+ arkclaw init # one-time interactive setup (asks only what it can't auto-detect)
33
+ arkclaw login # browser SSO
34
+ arkclaw agents # list the claws you can chat
35
+ arkclaw chat ci-xxxxxxxx
35
36
  ```
36
37
 
37
38
  ---
@@ -68,8 +69,13 @@ uv venv && uv pip install -e .
68
69
  ## Quick start
69
70
 
70
71
  ```bash
71
- # 1. log in to your space (a browser opens; sign in with SSO)
72
- arkclaw login https://your-space.arkclaw-enterprise-bj.volceapi.com
72
+ # 0. one-time setup interactive. Asks for your space address and (only if the
73
+ # space doesn't already publish them) the CLI client + STS role. Saved to
74
+ # ~/.arkclaw/defaults.json so you never type them again.
75
+ arkclaw init
76
+
77
+ # 1. log in (a browser opens; sign in with SSO)
78
+ arkclaw login
73
79
 
74
80
  # 2. see which claws you can talk to
75
81
  arkclaw agents
@@ -80,9 +86,10 @@ arkclaw chat ci-xxxxxxxx
80
86
  arkclaw chat ci-xxxxxxxx -m "用一句话介绍你自己"
81
87
  ```
82
88
 
83
- `login` figures out the rest from the address (your identity pool, region). If
84
- your space hasn't published auto-discovery yet, you may need to point it at the
85
- STS role oncesee **[Configuration](#configuration)**.
89
+ `arkclaw init` resolves everything it can from the address (identity pool,
90
+ region) and only prompts for what's missing. Once your space publishes
91
+ auto-discovery, `init` asks for nothing but the address and you can even skip
92
+ straight to `arkclaw login https://your-space...`. See **[Configuration](#configuration)**.
86
93
 
87
94
  ---
88
95
 
@@ -90,7 +97,8 @@ STS role once — see **[Configuration](#configuration)**.
90
97
 
91
98
  | Command | What it does |
92
99
  |---|---|
93
- | `arkclaw login <space-url>` | Browser SSO login. `--transport a2a --endpoint <url>` for an agent endpoint. `--clawid ci-...` sets a default claw (otherwise the last one you opened in the browser). Bare `arkclaw login` re-logs into the previous space. |
100
+ | `arkclaw init [address]` | One-time interactive setup. Saves the address + (only what isn't auto-discovered) the CLI client and STS role to `~/.arkclaw/defaults.json`, so later commands need no env/flags. |
101
+ | `arkclaw login [space-url]` | Browser SSO login. Uses `init` defaults if you omit the URL. `--transport a2a --endpoint <url>` for an agent endpoint. `--clawid ci-...` sets a default claw. Bare `arkclaw login` re-logs into the previous space. |
94
102
  | `arkclaw agents` | List the claws/agents you can chat with. |
95
103
  | `arkclaw chat [TARGET] [MSG]` | Chat. `TARGET` = a claw id (`ci-...`), an agent name (from `agents`), or a profile. With `MSG` → one-shot; without → interactive REPL. `-f` attach files, `-o` write the reply, `--session NAME` name the conversation, `--approve-all` auto-approve tool runs. |
96
104
  | `arkclaw <name>` | Shortcut: `arkclaw 答疑助手` ≡ `arkclaw chat 答疑助手`. |
@@ -161,9 +169,14 @@ arkclaw ls --clawid ci-other # a different claw
161
169
  ## Configuration
162
170
 
163
171
  `login` resolves config in this order: **explicit flag → `ARKCLAW_*` env →
164
- the space's published discovery → derived from the address**. You normally only
165
- type the address. Until your platform publishes auto-discovery, a deployment may
166
- supply these (non-secret) via env:
172
+ the space's published discovery → `arkclaw init` defaults derived from the
173
+ address**. You normally only type the address.
174
+
175
+ **The easy way — `arkclaw init`** asks once (interactively) for whatever the
176
+ space doesn't yet auto-publish, and saves it. After that, just `arkclaw login`.
177
+
178
+ **The env way** (scripts/CI, or instead of `init`) — supply the same non-secret
179
+ values via env:
167
180
 
168
181
  | Env | Purpose |
169
182
  |---|---|
@@ -171,7 +184,7 @@ supply these (non-secret) via env:
171
184
  | `ARKCLAW_ROLE_TRN` | STS role that mints the ChatToken (openclaw). |
172
185
  | `ARKCLAW_REGION` / `ARKCLAW_SPACE_ID` | Override region / space (usually auto). |
173
186
 
174
- Other config: `~/.arkclaw/session.json` (routing, 0600), `~/.arkclaw/cmdpolicy.json` (tool-approval allow/deny), OS keychain (tokens).
187
+ Other config: `~/.arkclaw/defaults.json` (`init` answers, 0600), `~/.arkclaw/session.json` (routing, 0600), `~/.arkclaw/cmdpolicy.json` (tool-approval allow/deny), OS keychain (tokens).
175
188
 
176
189
  > **Escape hatch (admin/test):** `arkclaw login <url> --transport openclaw --static-creds` uses `VOLCENGINE_ACCESS_KEY`/`SECRET_KEY` from the env instead of SSO — convenient for CI, but it's account-level keys, not identity-through.
177
190
 
@@ -5,9 +5,10 @@ own SSO identity, no passwords, no permanent keys.** Works the same for a human
5
5
  at a prompt and for another agent/script (`--json` + exit codes).
6
6
 
7
7
  ```bash
8
- arkclaw login https://your-space.arkclaw-enterprise-bj.volceapi.com # browser SSO, once
9
- arkclaw agents # list the claws you can chat
10
- arkclaw chat ci-xxxxxxxx # talk to one
8
+ arkclaw init # one-time interactive setup (asks only what it can't auto-detect)
9
+ arkclaw login # browser SSO
10
+ arkclaw agents # list the claws you can chat
11
+ arkclaw chat ci-xxxxxxxx
11
12
  ```
12
13
 
13
14
  ---
@@ -44,8 +45,13 @@ uv venv && uv pip install -e .
44
45
  ## Quick start
45
46
 
46
47
  ```bash
47
- # 1. log in to your space (a browser opens; sign in with SSO)
48
- arkclaw login https://your-space.arkclaw-enterprise-bj.volceapi.com
48
+ # 0. one-time setup interactive. Asks for your space address and (only if the
49
+ # space doesn't already publish them) the CLI client + STS role. Saved to
50
+ # ~/.arkclaw/defaults.json so you never type them again.
51
+ arkclaw init
52
+
53
+ # 1. log in (a browser opens; sign in with SSO)
54
+ arkclaw login
49
55
 
50
56
  # 2. see which claws you can talk to
51
57
  arkclaw agents
@@ -56,9 +62,10 @@ arkclaw chat ci-xxxxxxxx
56
62
  arkclaw chat ci-xxxxxxxx -m "用一句话介绍你自己"
57
63
  ```
58
64
 
59
- `login` figures out the rest from the address (your identity pool, region). If
60
- your space hasn't published auto-discovery yet, you may need to point it at the
61
- STS role oncesee **[Configuration](#configuration)**.
65
+ `arkclaw init` resolves everything it can from the address (identity pool,
66
+ region) and only prompts for what's missing. Once your space publishes
67
+ auto-discovery, `init` asks for nothing but the address and you can even skip
68
+ straight to `arkclaw login https://your-space...`. See **[Configuration](#configuration)**.
62
69
 
63
70
  ---
64
71
 
@@ -66,7 +73,8 @@ STS role once — see **[Configuration](#configuration)**.
66
73
 
67
74
  | Command | What it does |
68
75
  |---|---|
69
- | `arkclaw login <space-url>` | Browser SSO login. `--transport a2a --endpoint <url>` for an agent endpoint. `--clawid ci-...` sets a default claw (otherwise the last one you opened in the browser). Bare `arkclaw login` re-logs into the previous space. |
76
+ | `arkclaw init [address]` | One-time interactive setup. Saves the address + (only what isn't auto-discovered) the CLI client and STS role to `~/.arkclaw/defaults.json`, so later commands need no env/flags. |
77
+ | `arkclaw login [space-url]` | Browser SSO login. Uses `init` defaults if you omit the URL. `--transport a2a --endpoint <url>` for an agent endpoint. `--clawid ci-...` sets a default claw. Bare `arkclaw login` re-logs into the previous space. |
70
78
  | `arkclaw agents` | List the claws/agents you can chat with. |
71
79
  | `arkclaw chat [TARGET] [MSG]` | Chat. `TARGET` = a claw id (`ci-...`), an agent name (from `agents`), or a profile. With `MSG` → one-shot; without → interactive REPL. `-f` attach files, `-o` write the reply, `--session NAME` name the conversation, `--approve-all` auto-approve tool runs. |
72
80
  | `arkclaw <name>` | Shortcut: `arkclaw 答疑助手` ≡ `arkclaw chat 答疑助手`. |
@@ -137,9 +145,14 @@ arkclaw ls --clawid ci-other # a different claw
137
145
  ## Configuration
138
146
 
139
147
  `login` resolves config in this order: **explicit flag → `ARKCLAW_*` env →
140
- the space's published discovery → derived from the address**. You normally only
141
- type the address. Until your platform publishes auto-discovery, a deployment may
142
- supply these (non-secret) via env:
148
+ the space's published discovery → `arkclaw init` defaults derived from the
149
+ address**. You normally only type the address.
150
+
151
+ **The easy way — `arkclaw init`** asks once (interactively) for whatever the
152
+ space doesn't yet auto-publish, and saves it. After that, just `arkclaw login`.
153
+
154
+ **The env way** (scripts/CI, or instead of `init`) — supply the same non-secret
155
+ values via env:
143
156
 
144
157
  | Env | Purpose |
145
158
  |---|---|
@@ -147,7 +160,7 @@ supply these (non-secret) via env:
147
160
  | `ARKCLAW_ROLE_TRN` | STS role that mints the ChatToken (openclaw). |
148
161
  | `ARKCLAW_REGION` / `ARKCLAW_SPACE_ID` | Override region / space (usually auto). |
149
162
 
150
- Other config: `~/.arkclaw/session.json` (routing, 0600), `~/.arkclaw/cmdpolicy.json` (tool-approval allow/deny), OS keychain (tokens).
163
+ Other config: `~/.arkclaw/defaults.json` (`init` answers, 0600), `~/.arkclaw/session.json` (routing, 0600), `~/.arkclaw/cmdpolicy.json` (tool-approval allow/deny), OS keychain (tokens).
151
164
 
152
165
  > **Escape hatch (admin/test):** `arkclaw login <url> --transport openclaw --static-creds` uses `VOLCENGINE_ACCESS_KEY`/`SECRET_KEY` from the env instead of SSO — convenient for CI, but it's account-level keys, not identity-through.
153
166
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arkclaw-webchat-cli"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "CLI to chat with an ArkClaw EE space's Claw over enterprise SSO — zero permanent AK/SK."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -47,6 +47,20 @@ def _run(emitter: Emitter, fn: Callable[[], Any]) -> None:
47
47
  raise typer.Exit(emitter.ok(data))
48
48
 
49
49
 
50
+ @app.command()
51
+ def init(
52
+ address: str | None = typer.Argument(
53
+ None, metavar="[ADDRESS]", help="Space login URL; omit to be prompted."
54
+ ),
55
+ json_mode: bool = _json_opt(),
56
+ ) -> None:
57
+ """One-time interactive setup: capture the login address + (only what isn't
58
+ auto-discovered) the CLI client and STS role, so later `arkclaw login`
59
+ needs no env vars or flags. Run this once, then `arkclaw login`."""
60
+ emitter = Emitter(json_mode=json_mode)
61
+ _run(emitter, lambda: flows.do_init(emitter, address))
62
+
63
+
50
64
  @app.command()
51
65
  def login(
52
66
  address: str | None = typer.Argument(
@@ -176,6 +176,45 @@ def list_agent_names() -> list[str]:
176
176
  return sorted(_load_agents())
177
177
 
178
178
 
179
+ # --- init defaults ------------------------------------------------------------
180
+ # What `arkclaw init` captures once (interactively) so later `arkclaw login`
181
+ # needs no env/flags: the address + the non-secret bits a platform-published
182
+ # /.well-known/arkclaw-cli would otherwise supply. Explicit, user-set — NOT the
183
+ # auto-learned cache. A live well-known still overrides these at login time.
184
+
185
+ _DEFAULTS_FILE = "defaults.json"
186
+ _DEFAULT_KEYS = (
187
+ "address", "issuer", "client_id", "transport", "region",
188
+ "role_trn", "provider_trn", "endpoint", "space_id", "clawid",
189
+ )
190
+
191
+
192
+ def _defaults_path() -> pathlib.Path:
193
+ return pathlib.Path.home() / ".arkclaw" / _DEFAULTS_FILE
194
+
195
+
196
+ def load_defaults() -> dict[str, object]:
197
+ """`arkclaw init` config (empty dict if none). Non-secret only."""
198
+ path = _defaults_path()
199
+ if not path.exists():
200
+ return {}
201
+ try:
202
+ data = json.loads(path.read_text())
203
+ except ValueError:
204
+ return {}
205
+ return {k: v for k, v in data.items() if k in _DEFAULT_KEYS and v} if isinstance(data, dict) else {}
206
+
207
+
208
+ def save_defaults(values: dict[str, object]) -> None:
209
+ """Persist `arkclaw init` answers (whitelisted, non-None, non-secret)."""
210
+ keep = {k: v for k, v in values.items() if k in _DEFAULT_KEYS and v}
211
+ _dir()
212
+ fd = os.open(_defaults_path(), os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
213
+ with os.fdopen(fd, "w") as f:
214
+ f.write(json.dumps(keep, ensure_ascii=False))
215
+ os.chmod(_defaults_path(), 0o600)
216
+
217
+
179
218
  # --- Profiles (multi-pool / multi-claw) ---------------------------------------
180
219
  # A profile is a named snapshot of the non-secret session config. Tokens are
181
220
  # keyed by space host in the secret store, so switching profiles reattaches to
@@ -105,6 +105,63 @@ def _is_userpool_address(host: str) -> bool:
105
105
  return ".userpool.auth.id." in host or host.startswith("userpool-")
106
106
 
107
107
 
108
+ def do_init(emitter: Emitter, address: str | None = None) -> dict[str, Any]:
109
+ """``arkclaw init``: one-time interactive setup. Captures the login address
110
+ plus the bits not yet auto-discoverable (the CLI's OAuth client, the STS
111
+ role) so that afterwards ``arkclaw login`` needs no env vars or flags.
112
+ Anything the space already self-describes (issuer, region, and — once the
113
+ platform publishes it — client_id/role) is auto-filled and not asked."""
114
+ if emitter.json or not sys.stdin.isatty():
115
+ raise ValidationError(
116
+ "arkclaw init 是交互式的,需要终端。",
117
+ hint="在终端直接运行 `arkclaw init`;脚本里改用 env(ARKCLAW_CLIENT_ID/ROLE_TRN)+ flags。",
118
+ )
119
+
120
+ def ask(label: str, default: str | None = None, *, required: bool = False) -> str | None:
121
+ suffix = f" [{default}]" if default else ""
122
+ while True:
123
+ ans = input(f" {label}{suffix}: ").strip() or (default or "")
124
+ if ans or not required:
125
+ return ans or None
126
+ emitter.line(" (必填)")
127
+
128
+ emitter.line("arkclaw init —— 一次性配置(能自动发现的不会问你)\n")
129
+ address = address or ask("空间登录地址 (https://…)", required=True)
130
+ base, host = _normalize(str(address))
131
+ disc = discover_cli_config(base) or {}
132
+ issuer = disc.get("issuer") or (f"https://{host}" if _is_userpool_address(host) else None)
133
+ region = disc.get("region") or derive_region(base)
134
+ if issuer:
135
+ emitter.line(" ✓ 自动发现身份池 issuer")
136
+ if region:
137
+ emitter.line(f" ✓ 区域: {region}")
138
+
139
+ # User-facing name is "webchat" (the ChatToken/wss path); internally it's
140
+ # the "openclaw" transport. "a2a" is unchanged.
141
+ disc_t = str(disc.get("transport") or "")
142
+ transport_in = ask("传输方式 (webchat/a2a)", default=("a2a" if disc_t == "a2a" else "webchat")) or "webchat"
143
+ transport = "a2a" if transport_in.lower() == "a2a" else "openclaw"
144
+ client_id = disc.get("client_id") or ask(
145
+ "CLI client_id(public OAuth 客户端,问管理员;平台发布发现后免此项)", required=True
146
+ )
147
+ role_trn: object = None
148
+ endpoint: object = None
149
+ if transport == "openclaw":
150
+ role_trn = disc.get("role_trn") or ask("STS role TRN (trn:iam::<账号>:role/<名字>)", required=True)
151
+ else:
152
+ endpoint = disc.get("endpoint") or ask("A2A endpoint (https://…)", required=True)
153
+ clawid = disc.get("clawid") or ask("默认 claw id (ci-…,可留空,登录后用 arkclaw agents 选)")
154
+
155
+ saved = {
156
+ "address": base, "issuer": issuer, "client_id": client_id, "transport": transport,
157
+ "region": region, "role_trn": role_trn, "provider_trn": disc.get("provider_trn"),
158
+ "endpoint": endpoint, "space_id": disc.get("space_id"), "clawid": clawid,
159
+ }
160
+ config_mod.save_defaults(saved)
161
+ emitter.line("\n✓ 配置已存到 ~/.arkclaw/defaults.json。现在运行: arkclaw login")
162
+ return {k: v for k, v in saved.items() if v}
163
+
164
+
108
165
  def do_login(
109
166
  url: str | None,
110
167
  emitter: Emitter,
@@ -138,31 +195,34 @@ def do_login(
138
195
  A bare ``arkclaw login`` (no URL) re-logs into the previous space,
139
196
  inheriting every non-secret setting from the last login.
140
197
  """
198
+ defaults = config_mod.load_defaults() # what `arkclaw init` captured, if any
141
199
  if not url:
142
200
  prev = config_mod.load_config()
143
- if not prev or not (prev.url or prev.space):
201
+ if prev and (prev.url or prev.space):
202
+ url = prev.url or f"https://{prev.space}"
203
+ emitter.line(f"↻ 重新登录上次的空间: {url}({prev.transport})")
204
+ transport = transport or prev.transport
205
+ endpoint = endpoint or prev.endpoint
206
+ region = region or prev.region
207
+ role_trn = role_trn or prev.role_trn
208
+ provider_trn = provider_trn or prev.provider_trn
209
+ issuer = issuer or prev.issuer
210
+ client_id = client_id or prev.client_id
211
+ clawid = clawid or prev.claw
212
+ elif defaults.get("address"):
213
+ url = str(defaults["address"])
214
+ emitter.line(f"↻ 用 arkclaw init 的配置登录: {url}")
215
+ else:
144
216
  raise ValidationError(
145
217
  "缺少空间地址(首次登录必填)。",
146
- hint="例: arkclaw login https://<space-url> [--transport a2a];"
147
- "之后裸 `arkclaw login` 即可续登上次的空间。",
218
+ hint="先跑 `arkclaw init` 配置一次,或 `arkclaw login https://<space-url>`。",
148
219
  )
149
- url = prev.url or f"https://{prev.space}"
150
- emitter.line(f"↻ 重新登录上次的空间: {url}({prev.transport})")
151
- transport = transport or prev.transport
152
- endpoint = endpoint or prev.endpoint
153
- region = region or prev.region
154
- role_trn = role_trn or prev.role_trn
155
- provider_trn = provider_trn or prev.provider_trn
156
- issuer = issuer or prev.issuer
157
- client_id = client_id or prev.client_id
158
- clawid = clawid or prev.claw
159
220
  base, host = _normalize(url)
160
221
 
161
- # The space self-describes via GET /.well-known/arkclaw-cli (non-secret:
162
- # issuer/client_id/transport/region/space_id/role_trn/provider_trn/clawid).
163
- # When the platform publishes it, the user gives ONLY the address — every
164
- # field below resolves from it. Order: explicit flag > env > well-known.
165
- disc = discover_cli_config(base) or {}
222
+ # Resolution: explicit flag > env > the space's published
223
+ # /.well-known/arkclaw-cli > `arkclaw init` defaults > derived. The live
224
+ # well-known overrides init defaults; nothing is hardcoded per space.
225
+ disc = {**defaults, **(discover_cli_config(base) or {})}
166
226
  transport = transport or str(disc.get("transport") or "") or "openclaw"
167
227
  clawid = clawid or disc.get("clawid") # type: ignore[assignment]
168
228
  region = (