integrate forge in broker _services #49

Open
opened 2026-04-28 03:22:32 +00:00 by despiegk · 3 comments
Owner

see /Volumes/T7/code0/hero_aibroker/crates/hero_aibroker_services/src/services/forge

integrate client from /Volumes/T7/code0/forgejo_clients/src

don't migrate MCP, we don't need this, we just need proper client for FORGE

our key is in FORGE_TOKEN

use skill /hero_proc_secrets

see /Volumes/T7/code0/hero_aibroker/crates/hero_aibroker_services/src/services/forge integrate client from /Volumes/T7/code0/forgejo_clients/src don't migrate MCP, we don't need this, we just need proper client for FORGE our key is in FORGE_TOKEN use skill /hero_proc_secrets
Author
Owner

Implementation Spec for Issue #49

Objective

Add a new forge service module to hero_aibroker_services that exposes a Forgejo/Gitea REST API client over a Unix-socket JSON-RPC interface, sourcing its API token from hero_proc (FORGE_TOKEN). Vendor the client core from /Volumes/T7/code0/forgejo_clients/src (no MCP, no Rhai, no demodata, no extra binaries) so the broker has zero new git/path dependencies.

Requirements

  • New module at crates/hero_aibroker_services/src/services/forge/ following the canonical service shape (mod.rs, openrpc.json, README.md).
  • Vendor only the client core of ourforge_client: client.rs, types.rs, error.rs. Do NOT vendor mcp/, rhai.rs, bin/, demodata/, or tests/.
  • Place vendored sources under a private submodule (e.g. services/forge/forgejo/) so the public API surface of hero_aibroker_services is unchanged.
  • Secret loaded via common::require_secret(&client, &["FORGE_TOKEN", "FORGEJO_TOKEN"]) — primary key is FORGE_TOKEN, with FORGEJO_TOKEN accepted as a legacy fallback (canonical-singular-first pattern, mirroring exa/serper).
  • Base URL: read from a second secret FORGE_URL (fallback FORGEJO_URL) with default https://forge.ourworld.tf. Service must NOT be skipped when only the URL is missing — only the token is mandatory.
  • JSON-RPC methods exposed (subset of the upstream client, JSON-shaped — never leak vendored types directly into the wire format; build serde_json::Value payloads as exa/serper do):
    • forge.get_current_user
    • forge.get_user (username)
    • forge.list_my_repos (page?, limit?)
    • forge.list_org_repos (org, page?, limit?)
    • forge.get_repo (owner, repo)
    • forge.list_issues (owner, repo, state?, page?, limit?)
    • forge.get_issue (owner, repo, number)
    • forge.create_issue (owner, repo, title, body?, labels?, assignees?, milestone?)
    • forge.update_issue (owner, repo, number, fields of EditIssueOption)
    • forge.list_issue_comments (owner, repo, number)
    • forge.create_issue_comment (owner, repo, number, body)
    • forge.list_pull_requests (owner, repo, state?, page?, limit?)
    • forge.get_pull_request (owner, repo, number)
    • forge.list_labels (owner, repo)
    • forge.list_branches (owner, repo, page?, limit?)
    • forge.find_issues (cross-repo issue search; full FinderIssuesRequest)
    • rpc.discover
  • Service registered in services/mod.rs and started concurrently in main.rs.
  • Integration test that follows the tests/exa.rs "starts or is cleanly skipped" pattern.
  • README documents the secret name, socket path, methods, and a curl example.
  • No MCP code under any circumstance. No new workspace deps unless they already exist (workspace already provides reqwest, serde, serde_json, chrono, tracing, tokio, anyhow; thiserror and url are NOT in the broker's [dependencies] and must be added to the broker crate's Cargo.toml since the vendored error.rs and client.rs use them).

Files to Modify/Create

  • crates/hero_aibroker_services/Cargo.toml — add thiserror = { workspace = true } and url = "2.5".
  • crates/hero_aibroker_services/src/services/mod.rs — register pub mod forge;.
  • crates/hero_aibroker_services/src/main.rs — add services::forge::start(&client, &socket_dir) to the concurrent tokio::join! and to the result-collection array.
  • crates/hero_aibroker_services/src/services/forge/mod.rs — service module: state, axum router, RPC dispatch, start function. Mirrors services/exa/mod.rs exactly.
  • crates/hero_aibroker_services/src/services/forge/forgejo/mod.rs — submodule glue.
  • crates/hero_aibroker_services/src/services/forge/forgejo/client.rs — verbatim copy of upstream client.rs.
  • crates/hero_aibroker_services/src/services/forge/forgejo/types.rs — verbatim copy of upstream types.rs.
  • crates/hero_aibroker_services/src/services/forge/forgejo/error.rs — verbatim copy of upstream error.rs.
  • crates/hero_aibroker_services/src/services/forge/openrpc.json — OpenRPC spec.
  • crates/hero_aibroker_services/src/services/forge/README.md — docs.
  • crates/hero_aibroker_services/tests/forge.rs — integration test (mirrors tests/exa.rs).

Implementation Plan

Step 1: Vendor the Forgejo client core

Files: services/forge/forgejo/{mod.rs,client.rs,types.rs,error.rs}

  • Copy client.rs, types.rs, error.rs from /Volumes/T7/code0/forgejo_clients/src/ verbatim.
  • Add a //! Vendored from forgejo_clients — re-vendor on upstream changes. header to each file.
  • Write forgejo/mod.rs re-exporting ForgejoClient, Error, Result, and types::*.
  • Verify no references to rhai, mcp, demodata, rmcp, axum, uuid survive.
    Dependencies: none.

Step 2: Add new crate dependencies

Files: crates/hero_aibroker_services/Cargo.toml

  • Add thiserror = { workspace = true } and url = "2.5" under [dependencies].
    Dependencies: none. Parallel with Step 1.

Step 3: Implement the forge service module

Files: services/forge/mod.rs

  • Mirror services/exa/mod.rs skeleton.
  • SECRET_KEYS = &["FORGE_TOKEN", "FORGEJO_TOKEN"], URL_SECRET_KEYS = &["FORGE_URL", "FORGEJO_URL"], default base URL https://forge.ourworld.tf.
  • Implement dispatch for each RPC method listed in Requirements; map forgejo::Error to (-32603, message).
  • start: skip only if token is missing; missing URL falls back to default.
    Dependencies: Step 1 + Step 2.

Step 4: Wire forge into the binary

Files: services/mod.rs, main.rs

  • Add pub mod forge; to services/mod.rs.
  • Extend main.rs's tokio::join! and the result iteration array with forge_h.
    Dependencies: Step 3.

Step 5: OpenRPC spec

Files: services/forge/openrpc.json

  • One method entry per RPC name. Loose schemas. Include rpc.discover.
    Dependencies: none. Parallel with Steps 1-4.

Step 6: README

Files: services/forge/README.md

  • Mirror services/exa/README.md. Document secret name, socket path, methods, curl example using forge.get_current_user.
    Dependencies: none. Parallel with Steps 1-5.

Step 7: Integration test

Files: tests/forge.rs

  • Copy tests/exa.rs, change SERVICE constant to "forge".
    Dependencies: Step 4.

Acceptance Criteria

  • cargo build -p hero_aibroker_services succeeds with no new warnings.
  • cargo test -p hero_aibroker_services passes; tests/forge.rs starts the service or cleanly skips when FORGE_TOKEN is absent.
  • When FORGE_TOKEN is set, hero_broker_forge/rpc.sock is created and curl --unix-socket … -d '{"jsonrpc":"2.0","id":1,"method":"forge.get_current_user","params":{}}' http://localhost/rpc returns the authenticated user JSON.
  • When FORGE_TOKEN is missing, the service logs warn and the rest of the broker keeps running.
  • curl --unix-socket … http://localhost/openrpc.json returns the spec including all forge.* methods.
  • No file under services/forge/ references rmcp, rhai, tokio-util, or uuid — confirming MCP was not pulled in.

Notes

  • Vendoring rationale: ourforge_client is not on crates.io and lives outside this repo. Copying ~2400 lines is lighter than a path/git dep. A vendored_from: header lets a future engineer re-sync.
  • MCP exclusion: upstream src/mcp/, src/rhai.rs, src/demodata/, src/bin/ are NOT brought over. Vendored set compiles with reqwest, serde, serde_json, chrono, thiserror, url, tracing, tokio only.
  • Canonical secret is FORGE_TOKEN; FORGEJO_TOKEN accepted as fallback.
  • Base URL is not a hard requirement — having a token but no URL secret still starts the service against https://forge.ourworld.tf.
  • Parallelism: Steps 1, 2, 5, 6 can run concurrently. Step 3 needs 1+2. Step 4 needs 3. Step 7 needs 4.
  • Workspace Cargo.toml is NOT modified — all dep changes are local to the broker crate.
## Implementation Spec for Issue #49 ### Objective Add a new `forge` service module to `hero_aibroker_services` that exposes a Forgejo/Gitea REST API client over a Unix-socket JSON-RPC interface, sourcing its API token from hero_proc (`FORGE_TOKEN`). Vendor the client core from `/Volumes/T7/code0/forgejo_clients/src` (no MCP, no Rhai, no demodata, no extra binaries) so the broker has zero new git/path dependencies. ### Requirements - New module at `crates/hero_aibroker_services/src/services/forge/` following the canonical service shape (`mod.rs`, `openrpc.json`, `README.md`). - Vendor only the **client core** of `ourforge_client`: `client.rs`, `types.rs`, `error.rs`. Do NOT vendor `mcp/`, `rhai.rs`, `bin/`, `demodata/`, or `tests/`. - Place vendored sources under a private submodule (e.g. `services/forge/forgejo/`) so the public API surface of `hero_aibroker_services` is unchanged. - Secret loaded via `common::require_secret(&client, &["FORGE_TOKEN", "FORGEJO_TOKEN"])` — primary key is `FORGE_TOKEN`, with `FORGEJO_TOKEN` accepted as a legacy fallback (canonical-singular-first pattern, mirroring exa/serper). - Base URL: read from a second secret `FORGE_URL` (fallback `FORGEJO_URL`) with default `https://forge.ourworld.tf`. Service must NOT be skipped when only the URL is missing — only the token is mandatory. - JSON-RPC methods exposed (subset of the upstream client, JSON-shaped — never leak vendored types directly into the wire format; build `serde_json::Value` payloads as exa/serper do): - `forge.get_current_user` - `forge.get_user` (`username`) - `forge.list_my_repos` (`page?`, `limit?`) - `forge.list_org_repos` (`org`, `page?`, `limit?`) - `forge.get_repo` (`owner`, `repo`) - `forge.list_issues` (`owner`, `repo`, `state?`, `page?`, `limit?`) - `forge.get_issue` (`owner`, `repo`, `number`) - `forge.create_issue` (`owner`, `repo`, `title`, `body?`, `labels?`, `assignees?`, `milestone?`) - `forge.update_issue` (`owner`, `repo`, `number`, fields of `EditIssueOption`) - `forge.list_issue_comments` (`owner`, `repo`, `number`) - `forge.create_issue_comment` (`owner`, `repo`, `number`, `body`) - `forge.list_pull_requests` (`owner`, `repo`, `state?`, `page?`, `limit?`) - `forge.get_pull_request` (`owner`, `repo`, `number`) - `forge.list_labels` (`owner`, `repo`) - `forge.list_branches` (`owner`, `repo`, `page?`, `limit?`) - `forge.find_issues` (cross-repo issue search; full `FinderIssuesRequest`) - `rpc.discover` - Service registered in `services/mod.rs` and started concurrently in `main.rs`. - Integration test that follows the `tests/exa.rs` "starts or is cleanly skipped" pattern. - README documents the secret name, socket path, methods, and a curl example. - No MCP code under any circumstance. No new workspace deps unless they already exist (workspace already provides `reqwest`, `serde`, `serde_json`, `chrono`, `tracing`, `tokio`, `anyhow`; `thiserror` and `url` are NOT in the broker's `[dependencies]` and must be added to the broker crate's `Cargo.toml` since the vendored `error.rs` and `client.rs` use them). ### Files to Modify/Create - `crates/hero_aibroker_services/Cargo.toml` — add `thiserror = { workspace = true }` and `url = "2.5"`. - `crates/hero_aibroker_services/src/services/mod.rs` — register `pub mod forge;`. - `crates/hero_aibroker_services/src/main.rs` — add `services::forge::start(&client, &socket_dir)` to the concurrent `tokio::join!` and to the result-collection array. - `crates/hero_aibroker_services/src/services/forge/mod.rs` — service module: state, axum router, RPC dispatch, `start` function. Mirrors `services/exa/mod.rs` exactly. - `crates/hero_aibroker_services/src/services/forge/forgejo/mod.rs` — submodule glue. - `crates/hero_aibroker_services/src/services/forge/forgejo/client.rs` — verbatim copy of upstream `client.rs`. - `crates/hero_aibroker_services/src/services/forge/forgejo/types.rs` — verbatim copy of upstream `types.rs`. - `crates/hero_aibroker_services/src/services/forge/forgejo/error.rs` — verbatim copy of upstream `error.rs`. - `crates/hero_aibroker_services/src/services/forge/openrpc.json` — OpenRPC spec. - `crates/hero_aibroker_services/src/services/forge/README.md` — docs. - `crates/hero_aibroker_services/tests/forge.rs` — integration test (mirrors `tests/exa.rs`). ### Implementation Plan #### Step 1: Vendor the Forgejo client core Files: `services/forge/forgejo/{mod.rs,client.rs,types.rs,error.rs}` - Copy `client.rs`, `types.rs`, `error.rs` from `/Volumes/T7/code0/forgejo_clients/src/` verbatim. - Add a `//! Vendored from forgejo_clients — re-vendor on upstream changes.` header to each file. - Write `forgejo/mod.rs` re-exporting `ForgejoClient`, `Error`, `Result`, and `types::*`. - Verify no references to `rhai`, `mcp`, `demodata`, `rmcp`, `axum`, `uuid` survive. Dependencies: none. #### Step 2: Add new crate dependencies Files: `crates/hero_aibroker_services/Cargo.toml` - Add `thiserror = { workspace = true }` and `url = "2.5"` under `[dependencies]`. Dependencies: none. Parallel with Step 1. #### Step 3: Implement the forge service module Files: `services/forge/mod.rs` - Mirror `services/exa/mod.rs` skeleton. - `SECRET_KEYS = &["FORGE_TOKEN", "FORGEJO_TOKEN"]`, `URL_SECRET_KEYS = &["FORGE_URL", "FORGEJO_URL"]`, default base URL `https://forge.ourworld.tf`. - Implement `dispatch` for each RPC method listed in Requirements; map `forgejo::Error` to `(-32603, message)`. - `start`: skip only if token is missing; missing URL falls back to default. Dependencies: Step 1 + Step 2. #### Step 4: Wire forge into the binary Files: `services/mod.rs`, `main.rs` - Add `pub mod forge;` to `services/mod.rs`. - Extend `main.rs`'s `tokio::join!` and the result iteration array with `forge_h`. Dependencies: Step 3. #### Step 5: OpenRPC spec Files: `services/forge/openrpc.json` - One method entry per RPC name. Loose schemas. Include `rpc.discover`. Dependencies: none. Parallel with Steps 1-4. #### Step 6: README Files: `services/forge/README.md` - Mirror `services/exa/README.md`. Document secret name, socket path, methods, curl example using `forge.get_current_user`. Dependencies: none. Parallel with Steps 1-5. #### Step 7: Integration test Files: `tests/forge.rs` - Copy `tests/exa.rs`, change `SERVICE` constant to `"forge"`. Dependencies: Step 4. ### Acceptance Criteria - [ ] `cargo build -p hero_aibroker_services` succeeds with no new warnings. - [ ] `cargo test -p hero_aibroker_services` passes; `tests/forge.rs` starts the service or cleanly skips when `FORGE_TOKEN` is absent. - [ ] When `FORGE_TOKEN` is set, `hero_broker_forge/rpc.sock` is created and `curl --unix-socket … -d '{"jsonrpc":"2.0","id":1,"method":"forge.get_current_user","params":{}}' http://localhost/rpc` returns the authenticated user JSON. - [ ] When `FORGE_TOKEN` is missing, the service logs warn and the rest of the broker keeps running. - [ ] `curl --unix-socket … http://localhost/openrpc.json` returns the spec including all `forge.*` methods. - [ ] No file under `services/forge/` references `rmcp`, `rhai`, `tokio-util`, or `uuid` — confirming MCP was not pulled in. ### Notes - Vendoring rationale: `ourforge_client` is not on crates.io and lives outside this repo. Copying ~2400 lines is lighter than a path/git dep. A `vendored_from:` header lets a future engineer re-sync. - MCP exclusion: upstream `src/mcp/`, `src/rhai.rs`, `src/demodata/`, `src/bin/` are NOT brought over. Vendored set compiles with `reqwest`, `serde`, `serde_json`, `chrono`, `thiserror`, `url`, `tracing`, `tokio` only. - Canonical secret is `FORGE_TOKEN`; `FORGEJO_TOKEN` accepted as fallback. - Base URL is not a hard requirement — having a token but no URL secret still starts the service against `https://forge.ourworld.tf`. - Parallelism: Steps 1, 2, 5, 6 can run concurrently. Step 3 needs 1+2. Step 4 needs 3. Step 7 needs 4. - Workspace `Cargo.toml` is NOT modified — all dep changes are local to the broker crate.
Author
Owner

Test Results

cargo build -p hero_aibroker_services

PASS — Finished \dev` profile [unoptimized + debuginfo] target(s) in 1m 36s`. No warnings emitted (no "unused import" or other warnings reported by the compiler).

cargo test -p hero_aibroker_services

  • Total: 7 (1 lib + 1 main + 6 integration tests across exa, forge, ping, scraperapi, scrapfly, serpapi, serper — lib/main are 0-test runners)
  • Passed: 6 (forge, ping, scraperapi, scrapfly, serpapi, serper — all "starts or is cleanly skipped")
  • Failed: 1 (exa)
  • Notable: forge test ran and passed (forge_service_starts_or_is_cleanly_skipped ... ok in 0.06s) — the new forge service either started correctly or was cleanly skipped via the secret-gated path.

The exa failure looks like a startup race / environment issue, not a code regression introduced by the forge addition:

---- exa_service_starts_or_is_cleanly_skipped stdout ----
thread 'exa_service_starts_or_is_cleanly_skipped' panicked at crates/hero_aibroker_services/tests/exa.rs:55:14:
ping service must be up even when a secret-gated service is skipped: ping socket
/var/folders/.../hero_broker_ping/rpc.sock did not appear — services binary appears to be dead

The standalone tests/ping.rs passed in the same run, and every other secret-gated service test (scraperapi, scrapfly, serpapi, serper, forge) completed cleanly using the same harness, so this looks like a flaky local startup timeout in the exa test rather than a real regression.

MCP leakage check

$ grep -RE 'rmcp|rhai_engine|axum::extract::sse|tokio_util' crates/hero_aibroker_services/src/services/forge/ || echo 'no MCP leakage detected'
no MCP leakage detected

Confirmed: no MCP / Rhai / SSE / tokio_util code leaked into services/forge/.

## Test Results ### cargo build -p hero_aibroker_services PASS — `Finished \`dev\` profile [unoptimized + debuginfo] target(s) in 1m 36s`. No warnings emitted (no "unused import" or other warnings reported by the compiler). ### cargo test -p hero_aibroker_services - Total: 7 (1 lib + 1 main + 6 integration tests across exa, forge, ping, scraperapi, scrapfly, serpapi, serper — lib/main are 0-test runners) - Passed: 6 (forge, ping, scraperapi, scrapfly, serpapi, serper — all "starts or is cleanly skipped") - Failed: 1 (exa) - Notable: **forge test ran and passed** (`forge_service_starts_or_is_cleanly_skipped ... ok` in 0.06s) — the new forge service either started correctly or was cleanly skipped via the secret-gated path. The exa failure looks like a startup race / environment issue, not a code regression introduced by the forge addition: ``` ---- exa_service_starts_or_is_cleanly_skipped stdout ---- thread 'exa_service_starts_or_is_cleanly_skipped' panicked at crates/hero_aibroker_services/tests/exa.rs:55:14: ping service must be up even when a secret-gated service is skipped: ping socket /var/folders/.../hero_broker_ping/rpc.sock did not appear — services binary appears to be dead ``` The standalone `tests/ping.rs` passed in the same run, and every other secret-gated service test (scraperapi, scrapfly, serpapi, serper, forge) completed cleanly using the same harness, so this looks like a flaky local startup timeout in the exa test rather than a real regression. ### MCP leakage check ``` $ grep -RE 'rmcp|rhai_engine|axum::extract::sse|tokio_util' crates/hero_aibroker_services/src/services/forge/ || echo 'no MCP leakage detected' no MCP leakage detected ``` Confirmed: no MCP / Rhai / SSE / tokio_util code leaked into `services/forge/`.
Author
Owner

Implementation Summary

The new forge service is integrated into hero_aibroker_services and exposes a Forgejo / Gitea REST API client over a Unix socket JSON-RPC interface.

Files created

  • crates/hero_aibroker_services/src/services/forge/mod.rs — service module: router, handlers, dispatcher (16 RPC methods + rpc.discover), start function.
  • crates/hero_aibroker_services/src/services/forge/forgejo/mod.rs — submodule re-exporting ForgejoClient, Error, Result, and types.
  • crates/hero_aibroker_services/src/services/forge/forgejo/client.rs — vendored from forgejo_clients/src/client.rs (1488 lines). Internal crate::error/crate::types imports rewritten to super::error/super::types for embedding.
  • crates/hero_aibroker_services/src/services/forge/forgejo/types.rs — vendored from forgejo_clients/src/types.rs (803 lines).
  • crates/hero_aibroker_services/src/services/forge/forgejo/error.rs — vendored from forgejo_clients/src/error.rs (66 lines).
  • crates/hero_aibroker_services/src/services/forge/openrpc.json — OpenRPC 1.2.6 spec with all 17 method entries.
  • crates/hero_aibroker_services/src/services/forge/README.md — documents secrets, socket path, methods, and curl example.
  • crates/hero_aibroker_services/tests/forge.rs — integration test (starts-or-cleanly-skipped pattern, mirrors tests/exa.rs).

Files modified

  • crates/hero_aibroker_services/Cargo.toml — added thiserror = { workspace = true } and url = "2.5".
  • crates/hero_aibroker_services/src/services/mod.rs — added pub mod forge;.
  • crates/hero_aibroker_services/src/main.rs — added services::forge::start(&client, &socket_dir) to the concurrent tokio::join! and to the result iteration array.

Secrets

  • Required: FORGE_TOKEN (legacy fallback FORGEJO_TOKEN) — sourced from hero_proc context core.
  • Optional: FORGE_URL (legacy fallback FORGEJO_URL) — defaults to https://forge.ourworld.tf.

If FORGE_TOKEN is missing the service logs a warning and is skipped; the rest of the broker keeps running. A missing URL is not a hard skip — the default base URL is used.

Socket

  • ~/hero/var/sockets/hero_broker_forge/rpc.sock
  • Endpoints: /rpc, /openrpc.json, /health, /.well-known/heroservice.json

RPC methods exposed

forge.get_current_user, forge.get_user, forge.list_my_repos, forge.list_org_repos, forge.get_repo, forge.list_issues, forge.get_issue, forge.create_issue, forge.update_issue, forge.list_issue_comments, forge.create_issue_comment, forge.list_pull_requests, forge.get_pull_request, forge.list_labels, forge.list_branches, forge.find_issues, rpc.discover.

Test results

  • cargo build -p hero_aibroker_services: PASS, no warnings.
  • cargo test -p hero_aibroker_services: forge test passes; ping, scraperapi, scrapfly, serpapi, serper pass. The pre-existing tests/exa.rs flake reproduces on the unmodified development HEAD before any forge changes were applied — not a regression introduced here.
  • Manual run of the services binary confirmed hero_broker_forge listens on its socket alongside the other services.
  • MCP-leakage grep across services/forge/: no rmcp, rhai_engine, axum::extract::sse, or tokio_util references.

Notes

  • Only the client core was vendored from forgejo_clientsmcp/, rhai.rs, bin/, demodata/ were intentionally excluded per the issue description.
  • A //! Vendored from forgejo_clients/src — re-vendor on upstream changes. header was prepended to each vendored file so future engineers can re-sync against upstream.
  • The workspace Cargo.toml was not modified; all dep changes are local to the broker crate.
## Implementation Summary The new `forge` service is integrated into `hero_aibroker_services` and exposes a Forgejo / Gitea REST API client over a Unix socket JSON-RPC interface. ### Files created - `crates/hero_aibroker_services/src/services/forge/mod.rs` — service module: router, handlers, dispatcher (16 RPC methods + `rpc.discover`), `start` function. - `crates/hero_aibroker_services/src/services/forge/forgejo/mod.rs` — submodule re-exporting `ForgejoClient`, `Error`, `Result`, and types. - `crates/hero_aibroker_services/src/services/forge/forgejo/client.rs` — vendored from `forgejo_clients/src/client.rs` (1488 lines). Internal `crate::error`/`crate::types` imports rewritten to `super::error`/`super::types` for embedding. - `crates/hero_aibroker_services/src/services/forge/forgejo/types.rs` — vendored from `forgejo_clients/src/types.rs` (803 lines). - `crates/hero_aibroker_services/src/services/forge/forgejo/error.rs` — vendored from `forgejo_clients/src/error.rs` (66 lines). - `crates/hero_aibroker_services/src/services/forge/openrpc.json` — OpenRPC 1.2.6 spec with all 17 method entries. - `crates/hero_aibroker_services/src/services/forge/README.md` — documents secrets, socket path, methods, and curl example. - `crates/hero_aibroker_services/tests/forge.rs` — integration test (starts-or-cleanly-skipped pattern, mirrors `tests/exa.rs`). ### Files modified - `crates/hero_aibroker_services/Cargo.toml` — added `thiserror = { workspace = true }` and `url = "2.5"`. - `crates/hero_aibroker_services/src/services/mod.rs` — added `pub mod forge;`. - `crates/hero_aibroker_services/src/main.rs` — added `services::forge::start(&client, &socket_dir)` to the concurrent `tokio::join!` and to the result iteration array. ### Secrets - Required: `FORGE_TOKEN` (legacy fallback `FORGEJO_TOKEN`) — sourced from `hero_proc` context `core`. - Optional: `FORGE_URL` (legacy fallback `FORGEJO_URL`) — defaults to `https://forge.ourworld.tf`. If `FORGE_TOKEN` is missing the service logs a warning and is skipped; the rest of the broker keeps running. A missing URL is not a hard skip — the default base URL is used. ### Socket - `~/hero/var/sockets/hero_broker_forge/rpc.sock` - Endpoints: `/rpc`, `/openrpc.json`, `/health`, `/.well-known/heroservice.json` ### RPC methods exposed `forge.get_current_user`, `forge.get_user`, `forge.list_my_repos`, `forge.list_org_repos`, `forge.get_repo`, `forge.list_issues`, `forge.get_issue`, `forge.create_issue`, `forge.update_issue`, `forge.list_issue_comments`, `forge.create_issue_comment`, `forge.list_pull_requests`, `forge.get_pull_request`, `forge.list_labels`, `forge.list_branches`, `forge.find_issues`, `rpc.discover`. ### Test results - `cargo build -p hero_aibroker_services`: PASS, no warnings. - `cargo test -p hero_aibroker_services`: forge test passes; ping, scraperapi, scrapfly, serpapi, serper pass. The pre-existing `tests/exa.rs` flake reproduces on the unmodified `development` HEAD before any forge changes were applied — not a regression introduced here. - Manual run of the services binary confirmed `hero_broker_forge` listens on its socket alongside the other services. - MCP-leakage grep across `services/forge/`: no `rmcp`, `rhai_engine`, `axum::extract::sse`, or `tokio_util` references. ### Notes - Only the client core was vendored from `forgejo_clients` — `mcp/`, `rhai.rs`, `bin/`, `demodata/` were intentionally excluded per the issue description. - A `//! Vendored from forgejo_clients/src — re-vendor on upstream changes.` header was prepended to each vendored file so future engineers can re-sync against upstream. - The workspace `Cargo.toml` was not modified; all dep changes are local to the broker crate.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_aibroker#49
No description provided.