Remove restart infrastructure, generalize WASM channel setup (#493)

* refactor: remove restart infrastructure and generalize Telegram-specific code

Remove the gateway restart mechanism (hot-activation works, restart won't
fix activation failures) and generalize Telegram-specific hardcoded checks
so all WASM channels get equal treatment.

Part 1 - Remove restart infrastructure:
- Remove needs_restart from ActionResponse, restart_requested from GatewayState
- Remove gateway_restart_handler, /api/gateway/restart route, exit code 75
- Remove restart overlay JS/CSS (dead code - restartGateway() never called)
- Surface actual activation errors instead of suggesting restart

Part 2 - Generalize Telegram-specific code:
- Replace telegram_owner_id: Option<i64> with generic
  wasm_channel_owner_ids: HashMap<String, i64> (backwards-compatible
  via TELEGRAM_OWNER_ID env var)
- Pairing status check now applies to all active WASM channels
- All channels get 3-step stepper in web UI, remove "coming soon" note
- Remove dead setup_telegram() code (~700 lines) - Telegram's
  capabilities.json declares required_secrets, so the generic
  setup_wasm_channel() path handles it

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* test: add Settings::set() test for wasm_channel_owner_ids

Addresses review feedback: verify that setting per-channel owner IDs
via the dotted-path Settings::set() API works correctly with the new
HashMap<String, i64> type.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* fix(web): refresh extension stepper after pairing approval

loadPairingRequests only refreshed the pairing section, not the
stepper status. Call loadExtensions() instead so the stepper updates
from "Awaiting Pairing" to "Active" immediately after approval.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
This commit is contained in:
Henry Park
2026-03-03 22:10:32 +08:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 5f841554d5
commit 78878ad7ef
16 changed files with 74 additions and 561 deletions
+9 -15
View File
@@ -49,7 +49,7 @@ struct ChannelRuntimeState {
wasm_channel_runtime: Arc<WasmChannelRuntime>,
pairing_store: Arc<PairingStore>,
wasm_channel_router: Arc<WasmChannelRouter>,
telegram_owner_id: Option<i64>,
wasm_channel_owner_ids: std::collections::HashMap<String, i64>,
}
/// Result of saving setup secrets and attempting activation.
@@ -150,14 +150,14 @@ impl ExtensionManager {
wasm_channel_runtime: Arc<WasmChannelRuntime>,
pairing_store: Arc<PairingStore>,
wasm_channel_router: Arc<WasmChannelRouter>,
telegram_owner_id: Option<i64>,
wasm_channel_owner_ids: std::collections::HashMap<String, i64>,
) {
*self.channel_runtime.write().await = Some(ChannelRuntimeState {
channel_manager,
wasm_channel_runtime,
pairing_store,
wasm_channel_router,
telegram_owner_id,
wasm_channel_owner_ids,
});
}
@@ -1872,21 +1872,18 @@ impl ExtensionManager {
channel_manager,
pairing_store,
wasm_channel_router,
telegram_owner_id,
wasm_channel_owner_ids,
) = {
let rt_guard = self.channel_runtime.read().await;
let rt = rt_guard.as_ref().ok_or_else(|| {
ExtensionError::ActivationFailed(
"WASM channel runtime not configured. Restart IronClaw to activate."
.to_string(),
)
ExtensionError::ActivationFailed("WASM channel runtime not configured".to_string())
})?;
(
Arc::clone(&rt.wasm_channel_runtime),
Arc::clone(&rt.channel_manager),
Arc::clone(&rt.pairing_store),
Arc::clone(&rt.wasm_channel_router),
rt.telegram_owner_id,
rt.wasm_channel_owner_ids.clone(),
)
};
@@ -1956,9 +1953,7 @@ impl ExtensionManager {
);
}
if channel_name == "telegram"
&& let Some(owner_id) = telegram_owner_id
{
if let Some(&owner_id) = wasm_channel_owner_ids.get(channel_name.as_str()) {
config_updates.insert("owner_id".to_string(), serde_json::json!(owner_id));
}
@@ -2527,7 +2522,7 @@ impl ExtensionManager {
tracing::warn!(
channel = name,
error = %e,
"Saved configuration but hot-activation failed, restart may be needed"
"Saved configuration but hot-activation failed"
);
self.activation_errors
.write()
@@ -2537,8 +2532,7 @@ impl ExtensionManager {
.await;
Ok(SetupResult {
message: format!(
"Configuration saved for '{}'. \
Automatic activation failed ({}), restart IronClaw to activate.",
"Configuration saved for '{}'. Activation failed: {}",
name, e
),
activated: false,