21 Commits
Author SHA1 Message Date
zeekay d2dc8189bf feat(mcp): add kai_agent_step and kai_compact tools for decision-native agent workflows
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Successful in 1m27s
Hanzo CI/CD / test-amd64 (push) Failing after 8m23s
Hanzo CI/CD / cicd (push) Skipped
CI/CD / cicd (push) Failing after 8m25s
2026-10-11 10:00:40 -07:00
zeekay bd67f73a4c feat(llm): limits, catalog search, served and paid-by, plan refusals 2026-10-04 16:15:00 -07:00
zooqueenandHanzo Dev 58ddbc51e5 Add the llm tool to the TypeScript surface: Enso, the catalog, feedback
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Failing after 59s
Hanzo CI/CD / test-amd64 (push) Successful in 1m47s
Hanzo CI/CD / cicd (push) Successful in 1m37s
CI/CD / cicd (push) Successful in 3m29s
HIP-0300 names llm among the optional tools and Python and Rust carry it,
but the TypeScript server had none, so an agent on @hanzo/mcp could ask
Kai a typed question and could not reach a model.

llm routes by action over api.hanzo.ai:
- query: POST /v1/chat/completions, model enso-auto unless named; "auto"
  lets Enso pick. max_cost and max_latency_ms ride as X-Max-Cost and
  X-Max-Latency-Ms. It returns the model that served (X-Routed-Model, else
  the body's model) and the completion id feedback takes.
- models: GET /v1/models, each model's family, class and per-million
  price as the catalog states it; family narrows to enso or kai.
- feedback: POST /v1/ai/feedback with request_id, signal and a 1-3
  rating; an envelope that says error is an error.

Co-authored-by: Hanzo Dev <[email protected]>
2026-10-04 11:23:44 -07:00
zeekay 0e11347985 Add npx, uvx and jq to the TypeScript surface
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Failing after 51s
Hanzo CI/CD / test-amd64 (push) Successful in 2m25s
Hanzo CI/CD / cicd (push) Successful in 3m55s
CI/CD / cicd (push) Successful in 6m24s
exec gains run(): an argv with no shell, waited on up to a deadline, then
left running in exec's process table. npx and uvx use it with Python's argv
and a two-minute deadline; jq passes its filter as one argv word.

@hanzo/mcp 2.4.14
2026-09-30 15:17:34 -07:00
zeekay 46b081c99e Give the TypeScript fs tool Python's contract
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
Hanzo CI/CD / cicd (push) Successful in 1m52s
CI/CD / cicd (push) Successful in 3m40s
Hanzo CI/CD / test-amd64 (push) Successful in 1m45s
publish / publish (push) Failing after 2m50s
read returns numbered lines and the full sha256 hash, write only creates,
apply_patch takes old_text and new_text under base_hash, list walks with
depth, pattern and cursor, patch takes the Rust grammar, and search_text
takes a pattern and glob. rg now runs without a shell, so a pattern is never
a shell word.

@hanzo/mcp 2.4.13
2026-09-30 15:06:58 -07:00
zeekay c58488a2a3 Add browser and cdp to the TypeScript surface, over the ZAP router
Hanzo CI/CD / test (linux-amd64) (push) Skipped
Hanzo CI/CD / test (linux-arm64) (push) Skipped
Hanzo CI/CD / test-advisory (push) Skipped
publish / publish (push) Failing after 58s
Hanzo CI/CD / test-amd64 (push) Successful in 2m5s
Hanzo CI/CD / cicd (push) Successful in 1m53s
CI/CD / cicd (push) Successful in 4m32s
src/zap.ts is a consumer seat on the unix socket of whichever process the
lock elected: zapd has no JS or wasm build, so this runtime joins as
mcp/hanzo-<pid> and never stands for router. browser and cdp carry Python's
action names, parameters and extension methods; headless Playwright covers
the core, navigation and tabs when no browser is registered. The test runs
PyPI zapd as the router in another process, with a fake extension.

@hanzo/mcp 2.4.12
2026-09-30 14:52:19 -07:00
zeekay 8d13859eb0 The kai tools steer a yes/no to a choice whose labels name the outcomes, which Kai answers better than yes and no. 2026-09-28 15:13:12 -07:00
zeekay e1f6a85d42 The kai tools cap no label or level count, since /v1/decisions caps none. 2026-09-28 14:46:36 -07:00
zeekay e33c38f0a2 The kai tools follow the frozen decision contract: instructions optional, 1 to 100 questions, 2 to 255 labels, 1 to 10 levels, and a noul's confidence. 2026-09-28 14:41:35 -07:00
zeekay 30fafe2616 kai_decide, kai_choice, kai_score and kai_noul ask Kai typed questions on /v1/decisions, in @hanzo/mcp 2.4.11 2026-09-28 14:31:22 -07:00
zeekayandHanzo Dev a0c3a2d05b grep's test reads the description the tool now carries
70a0a04 put tgrep first in the grep tool's description and left the test
holding the old words, so the suite failed on main.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 05:37:21 -07:00
zeekay c724ae360a Let the tests run again
Every suite had stopped executing. ts-jest peers on `typescript >=4.3 <7`
and this repo builds against 7, so all twenty files died inside ConfigSet
with "Cannot read properties of undefined (reading 'fileExists')" — twenty
failures, zero tests, and nothing to read them by because the push gate
deliberately runs typecheck and build rather than jest.

swc transforms instead: it strips types rather than asking the compiler
to, so it has no TypeScript version to disagree with, and `tsc --noEmit`
already answers the question ts-jest was answering twice.

Running as real ESM then exposed what the CommonJS fallback had hidden.
jest.mock does not hoist there, so a static import binds the real module
and the suite fails on `mockReturnValue is not a function` — an absent
mock reported as a broken one. The search, autogui and ui suites now
register through unstable_mockModule and import after it. One of them had
never mocked fs at all: it cast fs.promises to a mocked type and called
mockImplementation on the real module.

384 tests, twenty suites, all passing.
2026-09-01 09:42:54 -07:00
zeekayandHanzo Dev 2e72b6f1f8 fetch: search asks our own API, and says so when it cannot
`fetch:search` scraped html.duckduckgo.com and pulled results out of a regex
over `class="result__title"`. Measured 2026-08-20: that page answers HTTP 202 —
DuckDuckGo's anti-bot challenge — and the markup carries no `result__title` at
all. So the regex matched nothing and the tool returned `{results: [], count: 0}`
for EVERY query: the identical answer it gives when the web genuinely has
nothing. Blind rendered as empty, with no way for a caller to tell them apart,
which is exactly why nobody noticed.

It now asks POST /v1/websearch — the meta-search we ship — reading the base URL
and credential from the same env the tracker tool reads, so the MCP has one way
to reach cloud rather than a second one here.

The failure shape is the point:

  no credential  -> NO_CREDENTIAL, never an empty result list
  cloud refuses  -> its own words verbatim ("sign in to search the web"),
                    because a 401 and a 500 are different problems and
                    flattening both into "search failed" makes an outage
                    look like a bad query
  results        -> carries WHICH ENGINES answered, so a zero-result search
                    with engines listed is a real empty and one with none is
                    a search that did not happen

HONEST GAP: the committed test cannot run. The repo declares typescript ^7.0.2
against ts-jest ^29.4.6, which does not support TS7, so `npx jest` dies in
_resolveTsConfig on "Cannot read properties of undefined (reading 'fileExists')"
— for the pre-existing suites too (edit.test.ts: 0 tests). `tsc --noEmit` is
clean repo-wide; only the transform is dead. The eight assertions were run
against the esbuild-bundled tool instead and all pass; they execute under jest
the moment the toolchain is fixed.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-20 13:48:00 -07:00
zooqueenandHanzo Dev 6182d0d800 feat(tools): tracker_* — the shared board, so an agent can report its own work
An agent could already keep a todo list (`tasks`), but only on its own disk.
Nothing here reached the board a human looks at, so "what is this agent doing"
had no answer outside the agent. These four tools are the cloud /v1/tracker
surface — the ONE work-item primitive — as MCP tools.

They are deliberately NOT called tasks_*. Three planes are easy to braid and
cloud apps/tracker/contract.go is law about it: a tracker Issue is a work item,
hanzoai/tasks is durable async execution, and the local `tasks` tool is a
private file at ~/.hanzo/todos.json. Naming these tasks_* would have collided
with that third one and pointed callers at the plane nobody can see.

Linking a run needed no new field. An agent's run is a SESSION — "mission" is
not modeled anywhere in the fleet — and the tracker contract already defines
extRef as "a link INTO another plane", so `session` writes the anchor
`session:<id>` and hanzo.app renders that session's live status on the row.
tracker_create defaults source to agent, because the board's ?source=agent
filter is only true if agents say so.

Cloud's own refusal reaches the caller verbatim — "unknown status filter" is
worth more to an agent than a generic failure — and the org is never sent: it
is minted server-side from the bearer, and a tool that sends one is a tool
asking to be trusted about tenancy.

NOTE: the jest suite cannot RUN on main right now — TypeScript 7.0.2 is
installed and ts-jest 29.4.6 cannot read its compiler API, so all 18 suites
fail to load. That break predates this commit and is orthogonal to it (verified
on a clean origin/main checkout). These tools were verified twice: 20 jest tests
green under the TS 5 toolchain, and 11 runtime checks through the shipped
esbuild bundle under main's current dependency state.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-04 21:57:27 -07:00
1e48359e6d feat(tools): wire Hanzo code-intelligence API as MCP tools (#12)
Add code_search / code_context / code_ask / code_index — one MCP tool per
api.hanzo.ai/v1/code endpoint — so @hanzo/dev and any MCP agent gain per-org
code search, budget-packed context, and cited RAG answers.

Auth mirrors hanzo-cloud.ts exactly: the caller's Hanzo bearer from
HANZO_API_KEY (or API_KEY/API_TOKEN/HANZO_TOKEN). The org is minted
server-side from that identity (principal gate) — a client never passes an
org. Output is requested as markdown (?format=md) so the LLM reads a
token-thrifty table; a non-2xx surfaces as a clear isError string. The tools
join the canonical HIP-0300 surface (allUnifiedTools), so tools/list exposes
all four over stdio.

test: hermetic local-server suite (10 tests) asserts method/path/format=md/
Bearer, no-org-leak, and arg + auth failures. Update the two tool-list
registry tests for gimp + the four code tools, and fix a pre-existing
ts-jest rootDir error that blocked every suite importing test/setup.ts.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-10 10:05:08 -07:00
89bf02f5f7 feat(fetch): x402 Payment Required handling + first unified-tool tests (#5)
* feat(fetch): x402 Payment Required handling + first unified-tool tests

Adds HTTP 402 (x402) parsing to the unified fetch tool so AI agents can
surface payment quotes from x402-gated endpoints and replay with X-PAYMENT.

- request / fetch / head detect status === 402 and return a structured
  payment_required envelope (parsed accepts[], x402-version, www-authenticate)
- new optional 'payment' input: pre-encoded base64 string sent verbatim, or
  a JSON object that is base64-encoded into X-PAYMENT before retry
- adds the first Jest test file for the HIP-0300 unified surface
  (test/tools/unified/fetch.test.ts) covering 200, 402, payment object, and
  payment string paths against an in-process http.createServer fixture

Also fixes test/setup.ts so the existing test suite actually runs:
- imports 'jest' from @jest/globals (jest is not a global under ESM)
- ESM-safe __dirname via fileURLToPath(import.meta.url)
Net effect: 169 previously-unrunnable tests can now start; 7/7 new fetch
tests pass; remaining failures are pre-existing test bugs unrelated to this
PR (CommonJS require() in ESM mode, missing mocks, etc.).

No new dependencies, no breaking changes to fetch's existing semantics.

* test: anchor setup.ts on process.cwd() to fix Node 18/20 ESM CI

`test/setup.ts` used `fileURLToPath(import.meta.url)` to derive its own
directory, but `ts-jest`'s handling of `import.meta` inside
`setupFilesAfterEnv` is fragile across Node versions — every test suite
failed on Node 18.x and 20.x with TS1343 ("\'import.meta\' meta-property
is only allowed when \'--module\' is es2020/...\"), even though the
root tsconfig and ts-jest's transform tsconfig both set
`module: ESNext`.

Tests always run from the project root, so `path.join(process.cwd(),
'test', ...)` is a stable anchor that doesn't depend on how the setup
file is loaded.

Local: 15/16 suites pass after the fix (2 unrelated shell.test.ts timing
flakes remain).

* fix(ci): suppress TS2307 on optional jsautogui dynamic import

The Node 20 CI job was failing two test suites — test/config/
configuration.test.ts and test/integration/mcp-server.test.ts — with:

    src/autogui/adapters/jsautogui.ts:37:37 - error TS2307: Cannot find
    module 'jsautogui' or its corresponding type declarations.

while the actual jest run itself reported 326/326 tests passing in the
suites it could load. Root cause: jsautogui is in optionalDependencies
and ships native bindings that npm may skip on some platforms. When
the package (and its bundled .d.ts) isn't present, ts-jest's transform
pass fails the whole suite at type-check time even though the runtime
code path is already guarded by try/catch + AutoGUINotAvailableError.

Adds a localised `// @ts-ignore` on the single dynamic-import line,
with a comment explaining why. The runtime behaviour is unchanged —
if jsautogui isn't installed, the catch arm still throws
AutoGUINotAvailableError as before. Confirmed locally that the
previously-failing test/config/configuration.test.ts now passes both
with jsautogui present and with node_modules/jsautogui removed
(simulating the Ubuntu CI install).

No code logic changed; package.json and package-lock.json untouched.

---------

Co-authored-by: Abhishek Krishna <[email protected]>
2026-05-19 11:33:09 -07:00
zeekay ac2000708d feat: HIP-0300 unified tool architecture (TS + Rust)
Implement 13 canonical tools organized by axis:
- Core (7): fs, exec, code, git, fetch, workspace, ui
- Optional (6): think, memory, hanzo, plan, tasks, mode

Key changes:
- Add src/tools/unified/ with action-routed tool implementations
- Add Rust native tools: exec, git, fetch, code, hanzo, tasks, workspace, computer
- Refactor tool index to default to unified surface (legacy available via enableLegacy)
- Simplify tests to match new architecture (337 tests, 15 suites pass)
- Update LLM.md with HIP-0300 architecture documentation
- Remove legacy shell_tool.rs and ui_tool/ (replaced by exec_tool.rs and computer_tool/)
- Stop tracking rust/target/.rustc_info.json
2026-03-11 11:37:15 -07:00
zooqueen 339c997b8c fix: resolve CI test failures on Ubuntu
- Use seq instead of brace expansion for shell large output test (sh compat)
- Handle platform-dependent behavior in search error test (rg vs grep)
2026-02-23 20:45:16 -08:00
zooqueen 2411bc3ac5 fix: resolve TypeScript compilation errors and fix all 15 test suites
Source fixes:
- Fix MCP SDK v1.18.0 callback signatures (extra param)
- Fix searchTool default type to 'all' when unspecified
- Fix file-ops maxDepth boundary check (> to >=)
- Fix type annotations in multi-framework-tools, agent-tools
- Fix secure-tunnel config property types
- Add resetUrlHelper export for test isolation

Test fixes:
- Fix url-helper tests for actual path resolution behavior
- Fix configuration/mcp-server tests for actual tool counts
- Fix search-engine test for actual ENOENT error messages
- Fix autogui tests for actual schema (required: [])
- Fix shell tests to use script files instead of inline bash
- Fix unified-ui-tool alias test expectations
- Fix test setup: per-suite unique temp dirs prevent parallel interference
2026-02-23 20:42:19 -08:00
zeekay 075661c92e feat: Full shadcn-ui-mcp-server parity with multi-framework support v2.1.0
Major Features:
- Complete GitHub API integration for fetching UI components
- Support for 5 frameworks: Hanzo (default), React, Svelte, Vue, React Native
- 13 new MCP tools for comprehensive UI component management
- Full parity with shadcn-ui-mcp-server functionality

New Tools:
- ui_get_component - Fetch component source code
- ui_get_component_demo - Get component usage examples
- ui_get_component_metadata - Extract dependencies and registry info
- ui_list_components - List all available components
- ui_get_block - Fetch UI blocks (complex compositions)
- ui_list_blocks - List blocks with categories
- ui_get_directory_structure - Browse repository structure
- ui_set_framework - Switch between frameworks
- ui_get_framework - Get current framework
- ui_set_github_token - Configure GitHub authentication
- ui_get_rate_limit - Check API rate limit status

Framework Support:
- Hanzo UI (hanzoai/ui) - Default framework
- React/shadcn (shadcn-ui/ui)
- Svelte (huntabyte/shadcn-svelte)
- Vue (unovue/shadcn-vue)
- React Native (founded-labs/react-native-reusables)

Technical Improvements:
- GitHub API client with rate limiting and caching
- Circuit breaker pattern for resilience
- 15-minute cache TTL for API responses
- Automatic authentication detection
- Support for blocks with multiple files
- Tree view directory browsing
2025-09-18 19:33:00 -05:00
zeekay 7e0448f10e feat: implement unified MCP search with OpenAI spec compliance and CI
## Core Implementation
- Unified search engine with strategy pattern for extensible search types
- Full OpenAI MCP specification compliance for search and fetch tools
- Multi-modal search strategies: Symbol, AST, Vector, Text, and File search
- Automatic strategy selection based on query characteristics

## Security & Remote Access
- Secure ngrok tunnel integration with automatic detection
- Multi-method authentication (Bearer token, API keys, JWT)
- Post-quantum TLS configuration support
- Rate limiting and CORS protection
- Access logging and monitoring
- Only exposes files when ngrok credentials are present

## Testing & CI
- 102 tests with 85% coverage on critical paths
- GitHub Actions CI workflow for automated testing
- Node.js 18.x and 20.x compatibility testing
- Coverage reporting to Codecov
- Security audit checks

## Documentation
- Comprehensive documentation in LLM.md
- Security guide in docs/SECURITY.md
- .npmrc excluded from repository for security

This implementation provides a production-ready search system for AI tools like ChatGPT and Claude Desktop.
2025-09-14 18:11:10 -05:00