2026-06-02 11:52:17 -05:00
|
|
|
import { dispatchFor } from "@/lib/dispatch";
|
2026-06-02 11:36:21 -05:00
|
|
|
import { isTauri } from "@/lib/platform";
|
|
|
|
|
|
|
|
|
|
export { isTauri } from "@/lib/platform";
|
feat(desktop): auto-discover Honcho instances on localhost (#1)
* feat(desktop): auto-discover Honcho instances on localhost
First-launch and on-demand discovery of running Honcho instances on
127.0.0.1:8000-8100. Desktop-only — the browser can't port-scan due to
CORS, so the scan runs in the Tauri Rust shell.
- New Rust command `discover_honcho_instances(start_port?, end_port?)`
in src-tauri/src/discover.rs: parallel TCP probe of each port with
150ms connect timeout + 250ms total request budget, looking for a
/health endpoint returning `{"status":"ok"}`.
- New TS helper `discoverHonchoInstances()` in src/lib/discovery.ts:
detects Tauri runtime; web build degrades to an empty result.
- `suggestNameForInstance()` fetches the first workspace and derives a
friendly name from its id ("neo-personal" -> "Neo"). Used to seed the
Name field for each discovered instance.
- `DiscoveredInstances` component: list of found instances with
editable suggested names + per-row checkbox + "Add N instances"
button. Rows are pre-checked by default and filter out already-
configured baseUrls.
- Wired into `InstancesManager`:
- First launch (no instances): renders above the connection-type
chooser with autoRun=true. User sees results immediately.
- With instances: adds a "Discover instances" button to the list
view that opens the discovery flow on demand.
- Both paths gate on `isTauri()`; the web build keeps its existing
behaviour unchanged.
Adds tokio (with net + io-util + time + rt + macros) and futures to
the Tauri shell to get async TCP + join_all.
Tests:
- deriveNameFromWorkspaceId handles hyphenated, multi-segment, and
no-hyphen ids
* test(desktop): add probe tests including live Hermes stack integration
- rejects_inverted_port_range
- ignores_ports_with_no_listener
- finds_live_hermes_stacks (#[ignore]d; opt-in with --ignored)
The ignored test exercises discover_honcho_instances against ports
8000-8010, expecting exactly [8001, 8002, 8003, 8004, 8005]. Verified
locally — the probe finds all 5 stacks in <10ms.
---------
Co-authored-by: Agents <agents@Jarviss-Mac-mini.local>
2026-05-24 17:01:14 +01:00
|
|
|
|
|
|
|
|
export interface DiscoveredInstance {
|
|
|
|
|
port: number;
|
|
|
|
|
base_url: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Probe localhost ports for running Honcho instances. Desktop-only — the web
|
|
|
|
|
* build can't port-scan due to CORS, so this returns an empty list when not
|
|
|
|
|
* running inside Tauri.
|
|
|
|
|
*/
|
|
|
|
|
export async function discoverHonchoInstances(): Promise<DiscoveredInstance[]> {
|
|
|
|
|
if (!isTauri()) return [];
|
|
|
|
|
const { invoke } = await import("@tauri-apps/api/core");
|
|
|
|
|
return invoke<DiscoveredInstance[]>("discover_honcho_instances");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Derive a friendly agent name from a workspace ID. Honcho workspaces follow
|
|
|
|
|
* the convention `<agent>-<camp>` (e.g. "neo-personal", "jeeves-codewalnut"),
|
|
|
|
|
* so we take the prefix and capitalize it. Falls back to the full ID if no
|
|
|
|
|
* hyphen is present.
|
|
|
|
|
*/
|
|
|
|
|
export function deriveNameFromWorkspaceId(workspaceId: string): string {
|
|
|
|
|
const first = workspaceId.split("-")[0] || workspaceId;
|
|
|
|
|
return first.charAt(0).toUpperCase() + first.slice(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Probe a discovered instance for its first workspace and derive a suggested
|
|
|
|
|
* name from it. Returns `null` if the instance has no workspaces or the
|
|
|
|
|
* request fails.
|
|
|
|
|
*/
|
|
|
|
|
export async function suggestNameForInstance(baseUrl: string): Promise<string | null> {
|
|
|
|
|
try {
|
2026-06-02 11:52:17 -05:00
|
|
|
const { baseUrl: base, headers, fetch } = dispatchFor({ baseUrl });
|
|
|
|
|
const res = await fetch(`${base}/v3/workspaces/list?page=1&page_size=1`, {
|
feat(desktop): auto-discover Honcho instances on localhost (#1)
* feat(desktop): auto-discover Honcho instances on localhost
First-launch and on-demand discovery of running Honcho instances on
127.0.0.1:8000-8100. Desktop-only — the browser can't port-scan due to
CORS, so the scan runs in the Tauri Rust shell.
- New Rust command `discover_honcho_instances(start_port?, end_port?)`
in src-tauri/src/discover.rs: parallel TCP probe of each port with
150ms connect timeout + 250ms total request budget, looking for a
/health endpoint returning `{"status":"ok"}`.
- New TS helper `discoverHonchoInstances()` in src/lib/discovery.ts:
detects Tauri runtime; web build degrades to an empty result.
- `suggestNameForInstance()` fetches the first workspace and derives a
friendly name from its id ("neo-personal" -> "Neo"). Used to seed the
Name field for each discovered instance.
- `DiscoveredInstances` component: list of found instances with
editable suggested names + per-row checkbox + "Add N instances"
button. Rows are pre-checked by default and filter out already-
configured baseUrls.
- Wired into `InstancesManager`:
- First launch (no instances): renders above the connection-type
chooser with autoRun=true. User sees results immediately.
- With instances: adds a "Discover instances" button to the list
view that opens the discovery flow on demand.
- Both paths gate on `isTauri()`; the web build keeps its existing
behaviour unchanged.
Adds tokio (with net + io-util + time + rt + macros) and futures to
the Tauri shell to get async TCP + join_all.
Tests:
- deriveNameFromWorkspaceId handles hyphenated, multi-segment, and
no-hyphen ids
* test(desktop): add probe tests including live Hermes stack integration
- rejects_inverted_port_range
- ignores_ports_with_no_listener
- finds_live_hermes_stacks (#[ignore]d; opt-in with --ignored)
The ignored test exercises discover_honcho_instances against ports
8000-8010, expecting exactly [8001, 8002, 8003, 8004, 8005]. Verified
locally — the probe finds all 5 stacks in <10ms.
---------
Co-authored-by: Agents <agents@Jarviss-Mac-mini.local>
2026-05-24 17:01:14 +01:00
|
|
|
method: "POST",
|
2026-06-02 11:52:17 -05:00
|
|
|
headers,
|
feat(desktop): auto-discover Honcho instances on localhost (#1)
* feat(desktop): auto-discover Honcho instances on localhost
First-launch and on-demand discovery of running Honcho instances on
127.0.0.1:8000-8100. Desktop-only — the browser can't port-scan due to
CORS, so the scan runs in the Tauri Rust shell.
- New Rust command `discover_honcho_instances(start_port?, end_port?)`
in src-tauri/src/discover.rs: parallel TCP probe of each port with
150ms connect timeout + 250ms total request budget, looking for a
/health endpoint returning `{"status":"ok"}`.
- New TS helper `discoverHonchoInstances()` in src/lib/discovery.ts:
detects Tauri runtime; web build degrades to an empty result.
- `suggestNameForInstance()` fetches the first workspace and derives a
friendly name from its id ("neo-personal" -> "Neo"). Used to seed the
Name field for each discovered instance.
- `DiscoveredInstances` component: list of found instances with
editable suggested names + per-row checkbox + "Add N instances"
button. Rows are pre-checked by default and filter out already-
configured baseUrls.
- Wired into `InstancesManager`:
- First launch (no instances): renders above the connection-type
chooser with autoRun=true. User sees results immediately.
- With instances: adds a "Discover instances" button to the list
view that opens the discovery flow on demand.
- Both paths gate on `isTauri()`; the web build keeps its existing
behaviour unchanged.
Adds tokio (with net + io-util + time + rt + macros) and futures to
the Tauri shell to get async TCP + join_all.
Tests:
- deriveNameFromWorkspaceId handles hyphenated, multi-segment, and
no-hyphen ids
* test(desktop): add probe tests including live Hermes stack integration
- rejects_inverted_port_range
- ignores_ports_with_no_listener
- finds_live_hermes_stacks (#[ignore]d; opt-in with --ignored)
The ignored test exercises discover_honcho_instances against ports
8000-8010, expecting exactly [8001, 8002, 8003, 8004, 8005]. Verified
locally — the probe finds all 5 stacks in <10ms.
---------
Co-authored-by: Agents <agents@Jarviss-Mac-mini.local>
2026-05-24 17:01:14 +01:00
|
|
|
body: JSON.stringify({}),
|
|
|
|
|
signal: AbortSignal.timeout(2000),
|
|
|
|
|
});
|
|
|
|
|
if (!res.ok) return null;
|
|
|
|
|
const data = (await res.json()) as { items?: Array<{ id?: string }> };
|
|
|
|
|
const wsId = data.items?.[0]?.id;
|
|
|
|
|
if (typeof wsId === "string" && wsId.length > 0) {
|
|
|
|
|
return deriveNameFromWorkspaceId(wsId);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
} catch {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|