Commit Graph
623 Commits
Author SHA1 Message Date
zeekay 1ca5ccadc3 release(hanzo-tools-browser): 0.5.10 — zapd connect-or-spawn auto-start 2026-07-08 08:50:48 -07:00
zeekayandGitHub 0b45461a6f feat(browser): auto-start zapd when absent (connect-or-spawn) (#47)
The browser MCP tool no longer requires a human to have started zapd.
ZapdConsumer.connect() now dials the router and, on failure, auto-starts
the shared singleton (locate the zapd binary, spawn it detached, wait for
the socket) then dials once more — mirroring zapd's own host-mode
connect-or-spawn. No consumer-side lock: the singleton invariant lives in
zapd (advisory-lock bind), so concurrent spawns are safe. The OS unit is
the primary starter; this is the bare-machine fallback so the tool just
works.
2026-07-08 08:49:21 -07:00
zeekay f7511ac282 fix(hanzoai): 3.1.1 — guard optional ZAP import so import hanzoai works without the [zap] extra
zap.py is an httpx.BaseTransport; httpx is not a base dep (client core is urllib3).
3.1.0 imported zap.py eagerly in __init__, so `import hanzoai` crashed on missing
httpx in any clean install. Guard the import (try/except ImportError) and declare
httpx under the [zap] extra. import hanzoai now works with or without extras.
2026-07-05 19:49:03 -07:00
zeekay 3e22e2c016 release(hanzoai): 3.1.0 — opt-in ZAP-native transport 2026-07-05 19:20:31 -07:00
1f05cff4f5 feat(hanzoai): optional ZAP-native transport (opt-in, public API unchanged) (#46)
Add hanzoai.zap: an httpx.BaseTransport / AsyncBaseTransport that routes the
SAME typed client calls through hanzo_zap.CloudClient over the ZAP binary wire.
Opt in with Hanzo(http_client=hanzoai.zap_http_client(...)); default stays HTTPS.

- hanzo-zap is an optional extra [zap], imported lazily so "import hanzoai"
  still works when it (and zap-proto) are not installed.
- Public __all__ is byte-identical; new names are additive and kept out of __all__.
- Request to ZAP mapping: path to dotted method, api-key header to Bearer auth,
  body forwarded verbatim.
- Tests: back-compat lock + request-translation via mock CloudClient (no network).

Co-authored-by: hanzo-dev <[email protected]>
2026-07-05 19:18:09 -07:00
zeekay f66cbfff8a fix(workspace): complete member set — install real toolset, fix 20 integration failures
The uv workspace listed only 10 of 61 packages as members, so `uv sync`
never installed fs/shell/agent/reasoning/lsp/refactor/todo/jupyter/memory —
and hanzo-tools-core's integration suite (which asserts each imports with an
exact TOOLS count) failed 20 tests against the absent packages. Add the 9
required tool packages as members + [tool.uv.sources] workspace pins so the
real toolset installs and the suite validates live code. Honest fix — install
what the test asserts, don't weaken the assertions. Suite: 24 passed / 12
skipped (was 20 failed / 4 passed). Lock resolves clean (tree-sitter, tornado,
nbformat added). No regressions: hanzoai 3/3, browser 11/11, hanzo-mcp boots.
2026-07-05 12:11:35 -07:00
zeekay f9dc5d477f fix(workspace): pin hanzo-tools + hanzo-tools-core to on-disk source (kill PyPI shadow)
hanzo-tools-core was a [tool.uv.sources] gap: not a workspace member, so uv
resolved it from PyPI 0.3.0 — the OLD package that still ships the duplicate
hanzo_tools/core/ WITHOUT ToolImage, shadowing canonical hanzo-tools.core and
breaking 'from hanzo_tools.core import ToolImage' (browser tests: 6 fail/5 error).
Add hanzo-tools + hanzo-tools-core as workspace members AND [tool.uv.sources]
= { workspace = true } so both resolve on-disk (0.3.1 empty shim), never the
shadowing wheel. Purge the stale untracked pkg/hanzo-tools-core/hanzo_tools/
build artifact. Finishes the decomplect 8b9e82d9 started. Browser tests: 11/11 green.
2026-07-05 12:07:52 -07:00
zeekay c172ab6c49 fix(hanzoai): restore core SDK modules wiped by #45 regen — unbreaks hanzo-mcp (3.0.1)
#45 regenerated hanzoai as a pure OpenAPI client and DELETED the hand-written
core-SDK modules (config/mcp/session/protocols/…) that live in the same package
but aren't part of API generation. hanzo-mcp imports all four → the published
hanzoai 3.0.0 crashed EVERY hanzo-mcp consumer on startup ('No module named
hanzoai.protocols') → the MCP server wouldn't boot → Claude Code couldn't
reconnect. Restore the 4 self-contained modules hanzo-mcp needs (verified: zero
imports of the removed Stainless internals); they coexist with the generated
api/models client. Left agents/auth/cluster/llm_client OUT — they import the
removed ._client and need migration to the new client (separate follow-up, no
reconnect-path consumer). Bump 3.0.0→3.0.1. Boot-proven: hanzo-mcp starts,
26 tool packages / 29 tools, MCP initialize OK.
2026-07-05 09:50:51 -07:00
zeekay 86eefc092c fix(browser): route MCP register through _result_to_mcp — ToolImage→ImageContent
The browser tool's bespoke register() returned execute()'s dict RAW, so FastMCP
flat-JSON-serialized a screenshot's ToolImage (base64 inline, 250K chars) →
overflowed the agent context and wedged the run — the SAME bug main's
ImageContent converter (8b9e82d9) fixed for every OTHER tool via
BaseTool.register→_result_to_mcp, but the browser tool bypassed that path.
Now both registration paths share the one converter: nested ToolImage anywhere
in the result becomes a native MCP ImageContent block the client SEES. One way.
2026-07-05 04:29:07 -07:00
53c123a3f5 feat(hanzoai): regenerate client from unified OpenAPI spec (retire Stainless) (#45)
Replace the Stainless-generated `hanzoai` client (188 legacy LLM-gateway
endpoints) with an openapi-generator `python` (urllib3 + pydantic v2)
client built from hanzoai/openapi `hanzo.yaml` — the full unified
api.hanzo.ai/v1 surface (493 API groups, 1710 models, all /v1 products).

- scripts/generate.sh: the one-way generator; emits only pkg/hanzoai
  (other pkg/hanzo-* packages untouched).
- pyproject: deps -> urllib3 / python-dateutil / pydantic>=2 /
  typing-extensions; version 2.2.3 -> 3.0.0 (breaking surface change).
- tests/: Stainless client tests replaced with a surface smoke test.
- .github/workflows/generate.yml: regenerate on openapi spec-update.
- Base URL https://api.hanzo.ai, Bearer hk- / JWT auth.

Verified: wheel hanzoai-3.0.0 builds, installs into a clean venv, and
`import hanzoai` + product API construction succeed.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-04 20:07:32 -07:00
zeekay f3db3d33fd Merge branch 'chore/ui-rag-v1-paths'
# Conflicts:
#	pkg/hanzo-tools-browser/hanzo_tools/browser/browser_tool.py
2026-07-04 13:59:42 -07:00
zeekay 2738527a5a fix(browser): screenshots/pdf save-to-disk + return path, never inline huge base64
A full-page PNG returned as inline base64 (100K+ chars) overflows an agent's
context window and wedges the whole run — the #1 cause of 'the browser tool
hangs' (two mobile-QA agents died on 6.6MB transcripts). Both capture paths
(native-zap _extension_command + the playwright fallback) now persist to
~/.hanzo/screenshots (or a caller path) and return a compact {path,size};
base64 is inlined ONLY for a small PNG (<=40KB). Adds _save_capture + _extract_b64.
2026-07-04 12:33:52 -07:00
zeekayandHanzo Dev 1ab641d393 fix(billing): drop extraneous /api prefix — api.hanzo.ai/v1/billing
The billing tool hardcoded api.hanzo.ai/api/v1/billing (double prefix). Per
the /v1-only canonical API contract, the gateway serves everything under bare
/v1/* — never /api/. Scrub to api.hanzo.ai/v1/billing.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-03 12:31:09 -07:00
zeekayandHanzo Dev 3214c798a5 browser/zapd_consumer: self-heal a dead cached socket
connect() trusted a cached ZapClient forever; if the router restarted, every
call raised BrokenPipeError and the consumer stayed wedged. list_providers/route
now drop the dead client and reconnect once.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-03 12:31:09 -07:00
zeekay a14e44a822 feat(mcp): native MCP ImageContent — tools return images the client can SEE
HIP-0300 tools serialize results to JSON text, which flattened images into
useless base64-in-text. Add a ToolImage value type + one converter in
BaseTool.register: any ToolImage anywhere in a result becomes a real
mcp.types.ImageContent block; text-only results stay byte-for-byte JSON.
Emitters wired: fs read of image files, browser screenshots (bidi+playwright).
This gives hanzo-mcp vision parity with zai-mcp — an agent with native vision
(Claude) sees pixels directly, no per-task vision tool needed.

Also decomplect the core-package collision that caused this class of bug:
hanzo-tools-core shipped a DUPLICATE hanzo_tools/core/ that nondeterministically
shadowed canonical hanzo-tools (dropping ToolImage, the sophisticated register,
etc. — same shadow class as the 0.3.0 error-reexport gap). Finish the
'merge core into hanzo-tools' refactor: move id_tool into hanzo-tools, make
hanzo-tools-core a pure empty metapackage. Now ONE package owns hanzo_tools.core.

Versions: hanzo-tools 0.3.2, -core 0.3.1 (shim), -browser 0.5.9, -fs 0.3.4,
hanzo-mcp 0.15.12 (floors bumped). Verified: fs read PNG -> [text, image];
fs stat -> [text]; 29 tools intact; 9 tests pass.
2026-07-03 00:45:49 -07:00
zeekay 617084b1ab test(hanzo-mcp): guard every hanzo.tools entry point imports cleanly
Regression guard for the hanzo-tools 0.3.0 core re-export gap that silently
dropped fs/exec/code/git/fetch/agent, leaving hanzo-mcp with only 13 tools.
Fails loudly if any entry point stops loading or the core error contract
(ToolError/ConflictError/InvalidParamsError/NotFoundError) regresses.
2026-07-02 23:57:21 -07:00
zeekay b1caa18c7f release(hanzo-tools): 0.3.1 — ship core error-class re-exports
PyPI hanzo-tools 0.3.0 shipped a core/__init__.py that never re-exported
ToolError/ConflictError/InvalidParamsError/NotFoundError from core.unified.
Six tool packages (fs, shell, agent, code, vcs, net) import those names at
entry-point load and silently failed, so hanzo-mcp exposed only 13 tools
instead of the full axis set. The re-export fix already landed in git
(4406ef32) but 0.3.0 was never republished. Bump to 0.3.1 to ship it.

Verified: entry points 20→26 loaded, hanzo-mcp tools/list 13→29.
2026-07-02 23:55:25 -07:00
zeekay da181e9d0f fix(hanzo-mcp): 'tool list' crash on @property descriptions (v0.15.11)
DynamicToolRegistry stored getattr(tool_class, 'description'), which for a
class-level @property returns the property DESCRIPTOR (not a str). 'tool list'
then did len(config.description) → 'object of type property has no len()',
breaking the entire tool-catalog command. Add _extract_tool_description
(mirrors _extract_tool_name): resolve a @property via a cheap instance, else
coerce to str, always returns str. Plus a defensive isinstance guard in the
list display path. Regression test covers property/unevaluable-property/plain/
absent + asserts every registered entry's description is len()-safe. 2 passed.
2026-07-02 23:00:52 -07:00
zeekay 41b9dc0b21 Merge remote-tracking branch 'origin/rip/api-callers-to-v1' 2026-07-02 13:18:52 -07:00
zeekayandHanzo Dev 6ac1e43ddc rip: migrate KMS universal-auth login to canonical /v1/kms/auth/login
hanzo-kms (sync + async): /api/v1/auth/universal-auth/login →
/v1/kms/auth/login. Body already canonical {clientId,clientSecret};
TokenResponse already parses {accessToken,expiresIn,tokenType}.

Scoped per CTO ruling: ONLY endpoints with a real canonical /v1/kms/*
target are migrated. The remaining /api/v3/secrets/raw/*,
/api/v1/auth/{kubernetes-auth,aws-auth}/login and /api/v3/auth/login
have NO canonical route (or a different API shape) on the kms.hanzo.ai
server and are left intact — rewriting them would mint dead /v1 paths.
They are flagged for a separate SDK-port task. Clean break, no aliases
(org rule: one way, /v1/, never /api/).

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-02 13:16:42 -07:00
zeekay 01566be773 release: bump auth-fixed packages for publish
Ship the canonical hanzo-app client_id + /v1/iam/get-account fixes:
- hanzoai 2.2.2 → 2.2.3
- hanzo-cli 0.2.1 → 0.2.2
- hanzo 0.4.2 → 0.4.3
- hanzo-tools-auth 0.1.0 → 0.1.1
2026-06-30 22:21:53 -07:00
zeekay afb00aaed6 auth: fix get-account endpoint (bare /v1/get-account 404s)
get_user_info hit {api_base_url}/v1/get-account (api.hanzo.ai/v1/get-account),
which 404s — the account read lives on the IAM issuer at /v1/iam/get-account
(same base as mint_api_key). Response is a {status,sub,name,data,data2}
envelope; accessKey is under data (get_api_key already reads it there).
2026-06-30 17:56:31 -07:00
zeekay 43cdcd4377 auth: align all SDK packages to canonical <org>-<app> client ids
IAM seeds apps as <org>-<app> (iam cmd/iam/cli/init_apps.go:57-59):
hanzo-app, zoo-app, lux-app — AppName == ClientID. Several packages used the
inverted 'app-hanzo'/'app-hanzobot' or placeholder '*-client-id', none of which
IAM knows — device/PKCE login would fail. One value, everywhere:

- hanzoai/auth.py: login_with_pkce default -> IAM_CLIENT_ID (hanzo-app)
- hanzo-cli/auth.py: DEFAULT_APP, DEFAULT_CLIENT_ID -> hanzo-app
- hanzo/commands/auth.py: IAM_CLIENT_ID -> hanzo-app
- hanzo-tools-auth/session.py: DEFAULT_APP, DEFAULT_CLIENT_ID -> hanzo-app
- hanzo/commands/iam.py: --app default + doc example -> hanzo-app
- hanzo-cli/bot/commands.py: BOT_IAM_APP/CLIENT_ID app-hanzobot -> hanzo-bot
2026-06-30 17:23:10 -07:00
zeekay f07ff89b29 auth: fix device login + API-key flow to real hanzo.id/IAM contract
Verified against iam (controllers/token.go, user.go, init_apps.go), ai
(controllers/account.go), and login (middleware.ts) sources:

- client_id hanzo-app (canonical brand CLI/desktop/mobile app seeded with the
  device_code grant), not the unseeded hanzo-dev/app-hanzo.
- Device flow uses RFC paths hanzo.id proxies to IAM — POST /oauth/device and
  /oauth/token — form-encoded (IAM reads device-grant params via Query(), skips
  JSON), keyed off the response body so a proxy can't desync polling.
- get_user_info reads /v1/get-account (IAM Claims with accessKey inlined),
  not the nonexistent /v1/user.
- Replace fictional named-key CRUD (/v1/api-keys) with Hanzo's real single
  per-user hk- key model: get_api_key (read accessKey), mint_api_key (self via
  /v1/iam/mint-user-keys), get_or_create_api_key (read-first), revoke_api_key.

Email/SMS/Google/GitHub/web3 all work since the device flow delegates login UI
to the browser approval page (providers wired per iam wire_providers.go).
2026-06-30 17:23:10 -07:00
9ca5085925 chore(tools-ui): RAG client paths /api/* -> /v1/* (#43)
The hanzo-tools-ui docs-RAG client targets api.hanzo.ai (host already
canonicalized on main). Move the paths off the residual /api/ prefix to
top-level /v1/, matching the cloud-api route rename and the openapi
v1.0.0 lock-in (no /api/ prefix):

  /api/search-docs       -> /v1/search-docs
  /api/chat-docs         -> /v1/chat-docs
  /api/index-docs        -> /v1/index-docs
  /api/search-docs/stats -> /v1/search-docs/stats

Hard cutover, coordinated with hanzoai/cloud (productsvc + ai serve these
at /v1), universe cloud-api-v1 AUTH_PUBLIC_PATHS, hanzo-docs RAG clients,
and the openapi cloud spec.

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-30 17:06:30 -07:00
zeekay 4db9f8f78a chore(tools-ui): RAG client paths /api/* -> /v1/*
The hanzo-tools-ui docs-RAG client targets api.hanzo.ai (host already
canonicalized on main). Move the paths off the residual /api/ prefix to
top-level /v1/, matching the cloud-api route rename and the openapi
v1.0.0 lock-in (no /api/ prefix):

  /api/search-docs       -> /v1/search-docs
  /api/chat-docs         -> /v1/chat-docs
  /api/index-docs        -> /v1/index-docs
  /api/search-docs/stats -> /v1/search-docs/stats

Hard cutover, coordinated with hanzoai/cloud (productsvc + ai serve these
at /v1), universe cloud-api-v1 AUTH_PUBLIC_PATHS, hanzo-docs RAG clients,
and the openapi cloud spec.
2026-06-30 16:58:58 -07:00
6cb701adc1 Point cloud clients at canonical api.hanzo.ai front door (#42)
The cloud API now sits behind one front door (ingress -> gateway -> cloud).
api.cloud.hanzo.ai / cloud-api.hanzo.ai / functions.hanzo.ai are redundant
aliases routing to the same backend, so migrate clients to api.hanzo.ai.

- hanzo-tools-ui: HANZO_CLOUD_API default cloud-api.hanzo.ai -> api.hanzo.ai
  (docs RAG paths /api/search-docs|chat-docs|index-docs are served at /api on
  the cloud backend per AUTH_PUBLIC_PATHS; kept as-is)
- hanzo base status: Functions remote host functions.hanzo.ai ->
  api.hanzo.ai/v1/functions (the canonical gateway path)

Non-breaking: the aliases still resolve to the same backend.

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-30 16:49:00 -07:00
558f1afed6 refactor(iam): drop Casdoor branding — Hanzo IAM only (white-label) (#41)
Co-authored-by: Hanzo Dev <[email protected]>
2026-06-30 14:56:32 -07:00
a1ab42289f fix(ci): PyPI upload token-fallback for per-project scope (#40)
hanzo-iam is owned on PyPI by HANZO_AI_PYPI_TOKEN, not PYPI_TOKEN, so it 403'd.
Each upload now tries PYPI_TOKEN then falls back to HANZO_AI_PYPI_TOKEN, so any
hanzo-* package publishes regardless of which token owns its project.

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-30 14:36:47 -07:00
a1cdb92c24 fix(ci): auto-discover packages + retry PyPI uploads on 429 (#39)
The hardcoded MAIN/TOOLS package lists silently dropped hanzo-zap and the
newer packages, so tag-triggered 'publish all' never shipped them. Derive
the list from pkg/ so it can never go stale again. Also retry uploads with
backoff: PyPI 429-rate-limits rapid multi-package bursts, which dropped the
tail of a large publish (hanzo-hooks, hanzo-tools-gimp, hanzo-tools-s3).

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-30 14:04:13 -07:00
zeekay 1ae66bac7d docs(brand): add hero banner 2026-06-28 20:08:36 -07:00
zeekay 23608fe495 chore(brand): dynamic hero banner 2026-06-28 20:08:35 -07:00
zeekay e8680ed46e fix(tools): correct PyPI long_description metadata + stale tool-count tests
Packaging metadata (twine check was PASSED-with-warnings -> clean PASS):
- config/llm/mcp/vector: add missing 'readme = README.md' ([project] key);
  README files existed but were never wired into the dist metadata.
- net/plan/vcs: fill empty (0-byte) README.md files referenced by the
  readme key, so long_description is no longer missing.

Tests (hanzo-tools-core/test_all_tools.py drifted from current sources):
- browser: 1 -> 3 tools (browser, cdp, playwright after the zapd split)
- mcp_tools: 4 -> 5 tools
- required-tool total: 21 -> 23
2026-06-26 11:57:48 -07:00
zeekay e67fa9d2b6 release: hanzoai 2.2.2
Patch release carrying the HIP-0111 IAM endpoint migration in
hanzoai.resources.iam (/iam/api/get-account + /iam/api/userinfo ->
canonical /v1/iam/oauth/userinfo), already in-tree since e1a38363 but
unreleased. 2.2.1 is taken on PyPI; bump to 2.2.2 (x.x.x+1).
2026-06-26 11:57:39 -07:00
zeekayandGitHub 0b844fdd33 fix(iam): migrate userinfo/get-account to canonical /v1/iam/oauth/userinfo (HIP-0111) (#38)
Co-authored-by: Zach Kelling <[email protected]>
2026-06-24 19:16:18 -07:00
zeekay 1e8038c0c0 fix(iam): canonical /v1/iam paths, drop forbidden /api/ (HIP-0111)
hanzo-tools-iam built URLs as {base}/api/{path} — forbidden per HIP-0111
(no /api/ prefix; one way). Now {base}/v1/iam/{path}; health probe is
/v1/iam/healthz. Asserts JSON shape, not bare 200, to dodge the IAM SPA
catch-all that serves 200 text/html for unregistered paths. Adds a test
for _iam_url + IAM_BASE_URL. (Test harness wiring for this non-member
package is a separate packaging task — code verified: 0 /api/ remain.)
2026-06-24 13:50:24 -07:00
zeekay ddc00162ec refactor(s3): back hanzo-s3 with boto3 over hanzoai/s3, drop minio
hanzoai/s3 (SeaweedFS fork w/ consensus+ZAP) is the canonical object
store; the minio pip package and its branding are gone. hanzo-s3 is now
a thin native boto3 adapter exposing a stable surface (S3Client + Bucket/
Object/Stat) so the hanzo s3 CLI and s3 MCP tool are unchanged. Removed
the dead MinioAdmin re-export (no consumer) and all MinIO naming.

CLI (7) + MCP S3Tool (14) tests green; ruff clean.
2026-06-24 13:50:24 -07:00
zeekay 2a753b334d feat(cli,mcp): complete S3 control surface — hanzo s3 + s3 MCP tool
Closes the last gap in the one-way Hanzo control surface. IAM/KMS/PaaS
already had both CLI subcommands and MCP tools; S3 had neither.

- hanzo s3: buckets/mb/rb/ls/stat/rm/presign over hanzo_s3 (MinIO) client,
  creds from env (inject from KMS, never plaintext). Registered in the
  unified hanzo CLI alongside iam/kms/paas.
- hanzo-tools-s3: S3Tool MCP tool (same action-dispatch pattern as PaaSTool),
  exported via the hanzo.tools entry point; s3 added to loader prefix map.
- uv workspace: map hanzo-cli/iam/kms/s3 + tools-s3 to local sources so the
  unified CLI resolves on-disk packages (fixes hanzo_iam ImportError from a
  stale published 1.29.0 wheel shadowing local 1.30.0).

Tests: 7 CLI + 14 MCP, all green.
2026-06-24 13:50:24 -07:00
zeekay 77c94812a6 kms: use canonical KMS env + client names 2026-06-24 10:50:44 -07:00
zeekayandGitHub 49d7e66286 chore(hips): remove duplicated HIP docs — canonical is hanzoai/HIPs (#37)
No duplication: the SDK must not carry copies of governance proposals.
HIP-0300 duplicated canonical hip-0300; the rest diverge. Canonical home is
hanzoai/HIPs (git history preserves these). Forwards-only, no backcompat.
2026-06-23 17:58:19 -07:00
zeekay 178cae7914 hanzo-mcp 0.15.10: harden tool floors (shell>=0.6.5, core>=0.3.0) so the pre-ToolError core can't resolve
Root cause of dead shell-exec: stale installs froze hanzo-tools-core 0.2.0 (no ToolError)
before 0.3.0 published, shadowing hanzo_tools.core and crashing the shell package import.
Floors now exclude it; a fresh/upgraded install always lands the consistent set.
2026-06-23 11:55:07 -07:00
zeekay 6fc449825c refactor(zap): consume canonical zap-proto, drop hand-rolled wire
hanzo-tools-browser: the zapd router envelope (frame.rs mirror) is no
longer reimplemented — zapd_consumer now uses zap.frame + zap.ZapClient
(dep zap-proto>=1.2.0). The end-to-end browser command codec stays local
and untagged to match the extension's decodeCmd (frame.encode_cmd is
tagged and would corrupt it); a new test proves the byte layout.

hanzo-zap: wire.py now delegates the zero-copy codec (Message/Builder/
ObjectBuilder/object readers) to canonical zap.wire instead of a 3rd
hand-rolled copy; the hanzo cloud-service schema + handshake + frame I/O
remain as a thin layer. dep zap-proto>=1.2.0. 114 tests pass.
2026-06-21 01:29:06 -07:00
zeekay 8aa9834b61 release: hanzo-tools-browser 0.5.8 + hanzo-mcp 0.15.9 (Firefox BiDi driving) 2026-06-20 13:04:39 -07:00
zeekay 340c3197dd feat(browser): route Firefox actions through BiDi fast-path
When the firefox backend is targeted and Firefox exposes a WebDriver BiDi remote agent (--remote-debugging-port=9222), drive it directly via bidi_client (real navigation + trusted input) instead of the half-implemented extension path or a dead headless Playwright. Additive + gated: only fires for target firefox with live BiDi and a BiDi-mapped action; otherwise falls through to the existing extension/Playwright routing unchanged. Takes effect after the MCP server reloads.
2026-06-20 13:04:39 -07:00
zeekay f336aaefc2 fix(browser/bidi): drive Firefox 153 (BiDi-only) seamlessly
Firefox 129+ runs WebDriver BiDi-only by default (CDP off), so /json/version 404s and the socket is served directly at /session. Four fixes make the BiDi client actually work against it:

- probe(): fall back to a TCP check + ws://host:port/session when /json/version isn't advertised (don't open a probe WebSocket — that establishes session state and conflicts with session.new).

- websockets>=13 compat: ClientConnection dropped .closed; _ws_open() reads .state/.close_code across versions.

- session lifecycle: session.end on close() so a session never orphans (Firefox keeps one at a time, and an orphan blocks every later session.new); retry session.new once after ending.

- add create_context/close_context/get_url so automation runs in a fresh tab without disturbing the user's tabs.
2026-06-20 13:04:39 -07:00
c9845991c5 ci: run on self-hosted ARC pool (hanzo-build-linux-amd64/deploy), not GitHub-hosted (#36)
Co-authored-by: zeekay <[email protected]>
2026-06-19 20:37:59 -07:00
zooqueen 3bcb26de56 docs: tidy LLM.md content (remove heading prefix) 2026-06-19 17:46:14 -07:00
zeekay 8c4861cf24 feat(computer): ydotool/uinput backend (Linux) — avoid xdotool/XTEST crashing Tauri/WebKitGTK 2026-06-17 22:06:55 +00:00
zeekay c626805bea feat(tools): hanzo-tools-gimp (clean-room BSD-3) 2026-06-17 21:53:05 +00:00
zooqueenandHanzo Dev 8d46e34ac1 ci(publish-pypi): run on live ARC fleet (hanzo-build-linux-amd64)
External evo/spark [self-hosted,linux,amd64] fleet is offline; the in-cluster ARC
scaleset is healthy and targeted by name. Decouple from the shared test.yml gate
(also pinned to the offline fleet) for dispatch publishes.

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-16 23:09:04 -07:00