Commit Graph
82 Commits
Author SHA1 Message Date
chenchenandClaude Opus 4.7 c0363be850 feat(resources): slice 3 — persist mcp JWT, proxy, list bindings
Backend:

  1. Extend SavedProvider schema with optional mcpAuth field
     (accessToken / refreshToken / accessExpiresAt / refreshExpiresAt /
     managerLoginUrl / userId / channelId). Wired through
     CreateProviderInput and UpdateProviderInput so providerService
     persists tokens to providers.json.

  2. handleLoginWithCredentials (Path A) now decodes the JWT exp claim
     of both tokens (no signature verification — issuer just authed us)
     and stores the resulting mcpAuth object on the saved provider.
     Documented TTL (24h access / 7d refresh) used as fallback if exp
     claim missing.

  3. New handler api/heicode-resources.ts — proxy for the local server
     route /api/heicode-resources/{*path}. It:
       - Reads mcpAuth from the active provider (401 if missing)
       - Refreshes the access token if < 60s from expiry by calling
         <managerLoginUrl>/api/auth/refresh; persists the new pair
         back to providers.json before forwarding
       - Returns 401 if refresh token is also expired (re-login needed)
       - Forwards request to <managerLoginUrl>/api/resources or
         /api/resource-grants with Authorization: Bearer <accessToken>
       - Passes status + body through

  4. router.ts: register case 'heicode-resources'.

  5. errorHandler: add ApiError.unauthorized(401) and badGateway(502)
     factories used by the proxy.

Desktop:

  6. New api/heicodeResources.ts client + types (ResourceBinding,
     ResourceGrant, etc. mirroring mcp-server contract). Slice 3 only
     exposes listBindings + getBinding.

  7. New stores/resourceStore.ts (zustand) with bindings, isLoading,
     hasFetched, error + fetchBindings action.

  8. pages/ResourceBindings.tsx upgraded from shell to a real list:
       - Auto-fetches on mount
       - Shows loading skeleton, error banner with dismiss, empty state,
         or a 5-column table (Name / Type / External ref / Status /
         Permission scope)
       - Refresh button in the header
       - Footer note about CRUD coming in slice 4

  9. i18n: 14 new keys (common.dismiss + resources.refresh / refreshing
     / col.* / error.title / footer.cruComingSoon) in both zh + en.

E2E behaviour after install: log in via 55@55.com / By@123456., open
Resources tab — local server proxies to apimtaiji and lists whatever
ResourceBindings the user has on mcp-server. New test account 55@55.com
has 0 bindings, so empty state shows up.

Slice 4 next: Create / Edit / Delete binding modals + Grants UI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 18:04:59 +08:00
chenchenandClaude Opus 4.7 d1db2c1501 feat(resources): add Resources tab shell aligned with Heicode full-stack vision
Per docs/vision-heicode-full-stack-agentic-dev.md and plan.md P1, Heicode
is a full-stack agentic dev platform — not a chat-only client. cc-haha
needs a "Resources" entry where users bind Git repos / SK / project docs
/ cloud accounts and grant them to sub-agents.

mcp-server team has the P1 9 endpoints live (POST/GET/PUT/DELETE
/api/resources, POST/GET/DELETE /api/resource-grants — see
Heicode-接口契约文档.md §2-§3). cc-haha has not consumed them yet.

This commit ships slice 2 (page shell):
  - tabStore: new TabType 'resources' + RESOURCES_TAB_ID export
  - Sidebar: new nav entry between 'scheduled' and 'terminal' (link icon)
  - ContentRouter: route 'resources' tab to <ResourceBindings />
  - pages/ResourceBindings.tsx: header + "coming soon" placeholder card
  - i18n: sidebar.resources + resources.* keys (zh + en)

Slice 3 (next): persist mcp-server JWT in provider record so the local
Bun server can proxy /api/heicode-resources/* to apimtaiji with a fresh
Authorization Bearer header. Refresh logic on the 24h boundary.

Slice 4 (next): actual Bindings list + Create/Delete + Grants list +
Create/Revoke modals.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 17:39:02 +08:00
chenchenandClaude Opus 4.7 86bad2323f feat(login): align desktop credentials login with upstream Heicode design
Per heicode.md / heicode-runtime-auth-newapi-secret-design.md /
Heicode-登录接口对接文档.md, identity is owned by the Manager
(mcp-server), NewAPI is just the model gateway. The previous local
flow hit NewAPI's /api/user/login directly, which deviates from the
documented design — that endpoint is the legacy upstream NewAPI password
login that the current production web frontend already bypasses.

New flow inside POST /api/heicode-auth/login-with-credentials:

  1. POST <managerLoginUrl>/api/auth/login (mcp-server)
       Body: {email, password, role: "user"}
       → 200 {success, data{token, refreshToken, user{id, channelId,
                                                       role, email,
                                                       name}}}

  2. POST <baseUrl>/api/user/session/from-agnet (heicode 后端)
       Body: {access_token, refresh_token}
       → 200 + Set-Cookie: session=...
       JIT-syncs the local NewAPI user from the Agnet identity:
       users.group becomes the channelId returned by mcp-server,
       which matches NewAPI's abilities/channel routing model.

  3. GET <baseUrl>/heicode/oauth/authorize?... (heicode 后端)
       Headers: Cookie + New-Api-User
       redirect: 'manual' to capture the 302 Location header
       → token=sk-XXXX is parsed out and handed to the existing
         loginAndActivate pipeline (which probes /v1/models and
         persists the active provider).

Provider preset gains an optional managerLoginUrl field (default
https://apimtaiji.azure-api.net/api/mcp for taijiaicloud), with an
env override HEICODE_TAIJIAICLOUD_MANAGER_LOGIN_URL for dev.

End-to-end verified locally with the documented test account
55@55.com / By@123456.: each step returns 200, /heicode/oauth/authorize
mints a sk- token tied to channelId 6e6fc470-76f8-4bb1-8ea4-625dc5b12bc6,
and /v1/models returns the full live model catalogue under that channel.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:28:21 +08:00
chenchenandClaude Opus 4.7 f70d80ca4c Revert "fix(agnet): preserve root admin's group during Agnet session sync"
This reverts commit 992a965. After re-reading the upstream Heicode
design docs (heicode.md, heicode-runtime-auth-newapi-secret-design.md,
plan.md), it is clear that:

  1. users.group = channelId is the correct upstream behaviour. Agnet's
     /me is the source of truth for which NewAPI channel a user belongs
     to. Forking that logic in NewAPI to special-case role>=root breaks
     the documented "Manager owns identity, NewAPI is just the model
     gateway" boundary.

  2. The empty-abilities symptom isn't a NewAPI fork bug. It's that
     chenchen was created by raw SQL INSERT into NewAPI's users table —
     a path that doesn't exist in the design. Real users get their
     channelId from Manager (mcp-server) at login, and ability rows for
     that channelId are provisioned out-of-band by platform operations
     when the channel goes live.

  3. Patching NewAPI to silently keep an admin's hand-edited group hides
     the real provisioning gap and pollutes the upstream sync logic for
     every future user.

Restoring upstream behaviour. Out-of-band fixes (whether to
provision abilities, route mcp-server logins, etc.) belong elsewhere.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:15:17 +08:00
chenchenandClaude Opus 4.7 992a965cd9 fix(agnet): preserve root admin's group during Agnet session sync
syncLocalUserFromAgnet rewrites users.group with the channelId returned
by Agnet's /me on every web /sign-in. That's correct for normal users —
their channel membership is owned by the Agnet identity service. But
platform administrators (RoleRootUser) are provisioned out-of-band:
operators set their group to "default" (or whichever billing tier)
manually, and their NewAPI abilities exist there.

When a root admin logs in via the web, Agnet returns a stub channelId
that has no abilities rows. The current code overwrites users.group
with that stub, and the next /v1/models call returns an empty list —
the desktop client then falls back to providerPresets.defaultModels,
hiding the real model catalogue from the operator.

Add a role guard so the rewrite only fires for users below root. Root
admins keep whatever group an operator set in the DB.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:03:40 +08:00
chenchenandClaude Opus 4.7 f82042f83b chore(branding): replace Claude-style icon with Heicode H mark
User-supplied screenshot of the Heicode H circuit logo (heicode-logo.png
at repo root) was background-removed via flood-fill from the image
borders, edge-feathered with a 0.7px Gaussian on the alpha channel, and
upscaled to 1024x1024 as the master.

Replaced everywhere the icon is referenced:
  src-tauri/icons/
    32x32.png, 128x128.png, 128x128@2x.png  — Tauri build inputs
    icon.ico  — multi-res 16/24/32/48/64/128/256 (Windows installer +
                taskbar)
    icon.icns — multi-res 16/32/64/128/256/512/1024 (macOS bundle)
    Square*.png + StoreLogo.png — Windows store sizes (kept in sync)
  public/app-icon.png — splash icon shown by HeicodeLoginPage,
                        ActiveSession.tsx, EmptySession.tsx,
                        Settings.tsx (1024x1024)

The H mark sits on transparent alpha now; on dark window chrome it
appears as the floating logo without a white card. Source resolution
(273x276) means 16/24px renderings are slightly soft; adequate for
taskbar/tray and crisp at 32px+.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 14:26:39 +08:00
chenchenandClaude Opus 4.7 c12e19b1ce feat: email+password login (path B from original design doc)
Per docs/integration/Heicode-登录接口对接文档.md, the original Heicode
desktop is supposed to take email+password directly, hand them to the
Manager (POST /api/user/login), and use the resulting session to
acquire an LLM access token. The previous flow opened a system browser
and redirected through /heicode/oauth/authorize, which works but
deviates from the design and forces an extra round trip.

This commit adds the documented in-process flow as the primary login
path while keeping browser OAuth as a fallback link:

  POST /api/heicode-auth/login-with-credentials
    1. POST <baseUrl>/api/user/login (username + password)
    2. Capture Set-Cookie from the response
    3. GET <baseUrl>/heicode/oauth/authorize?... with that cookie and
       redirect: 'manual'
    4. Parse Location: ...?token=sk-XXXX, hand it to loginAndActivate

The whole chain stays inside the local cc-haha server — no browser is
opened, no token leaves the user's machine.

UI changes:
  - ProviderLoginCard now shows email + password fields as the primary
    form, with the existing "or via browser" OAuth path demoted to a
    small link below.
  - Added store action loginWithCredentials and matching API client
    method.
  - i18n keys: login.creds.{email,password,submit,submitting} +
    login.oauth.altLink (zh + en).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 14:08:54 +08:00
chenchenandClaude Opus 4.7 4665f88921 feat: route Heicode desktop login through code.xinghanlab.com Manager
Three concrete pieces:

1. Provider preset taijiaicloud now points at https://code.xinghanlab.com
   instead of the old api.taijiaicloud.com. Together with the stock
   resolveOAuthConfig fallback (<baseUrl>/heicode/oauth/authorize), this
   flips oauthEnabled on for the login card and turns the existing
   browser-redirect bridge into the default flow. Card name + promo
   updated to reflect that this is "log in via Heicode Manager".

2. loginAndActivate softens its model probe. /v1/models is best-effort:
   only hard 401/403 auth failures abort login. 5xx / panics / empty
   lists fall back to preset.defaultModels so the user lands inside the
   app even if the gateway transiently misbehaves; they can re-pick
   models from Settings later.

3. heicode_oauth.go fallback page: /login → /sign-in (matches the
   actual SPA route), title/copy de-branded from "HeiCode/新 API 控制台"
   to plain "Heicode 控制台".

Also picks up the prior unstaged Windows polish: WindowControls (min/
max/close + drag region) on the login screen, ProviderLoginCard +
globals.css refinements that landed in earlier MSI builds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:55:57 +08:00
chenchenandClaude Opus 4.7 7ec7778c18 fix: enforce Heicode-only login and remove ClawdRouter enum residue
Backend listLoginProviders() was iterating ['taijiaicloud','clawdrouter']
and throwing 500 because clawdrouter preset was already removed from
providerPresets.json. Narrowing SUPPORTED_LOGIN_PROVIDER_IDS and the two
Zod enums to ['taijiaicloud'] only, plus tightening the desktop
HeicodeProviderId type to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 20:56:33 +08:00
chenchen eba6478913 更新登录 2026-05-05 20:44:24 +08:00
gongzhiyongandOmX bf134dec86 Make Agnet runs submit resource-scoped work safely
Manager now exposes a Resource Grant manifest and the Agnet control-plane response carries runtime state, agent instances, and permission_manifest so frontend runs can submit bounded resource grants without plaintext credentials.

Constraint: Manager remains the user console while NewAPI stays independent and OpenBao is referenced through secret_ref only.

Rejected: platform-side high-risk approval | client approval is the product boundary; Agnet only validates approval evidence.

Confidence: medium

Scope-risk: moderate

Directive: Do not mix child Agnet runtime model selection with NewAPI billing or expose OpenBao as a public route.

Tested: git diff --check; jq empty locale JSON; go vet ./controller ./model ./router; go test -count=1 ./controller ./model ./router

Not-tested: frontend typecheck/build because local node_modules tooling is absent and user requested builds happen on the VM.

Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-04 18:55:53 +08:00
gongzhiyong ba02ae5be7 feat: align manager agnet boundaries
- add Manager user_context, NewAPI billing_context, and Agnet agent_runtime deployment fields

- move resource binding/grant scope toward user-owned binding_scope and secret_ref-only paths

- document OpenBao internal access and unified heicode.xinghanlab.com routing boundaries

- fix Manager session user id preservation after external auth login
2026-05-04 09:28:03 +08:00
gongzhiyongandOmX 5fb432f7c8 docs: clarify auth billing and secret boundaries
Document Manager user reuse, NewAPI billing mapping, OpenBao short-lived credential injection, and Agnet-owned model configuration.

Tested: git diff --check

Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-04 08:46:05 +08:00
gongzhiyongandOmX d9eb7dcd74 feat: wire resource secrets to OpenBao
Manager needs a platform-owned secret handoff path so resource bindings can keep only vault references while OpenBao stores tenant-scoped credential payloads.

Tested: go test ./controller ./model ./router && go vet ./controller ./model ./router
Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-03 23:41:55 +08:00
gongzhiyong a7588e1bc8 chore: remove plaintext postgres retry credentials 2026-05-03 21:49:55 +08:00
gongzhiyong 50bf3de6f0 agnet: add deployment logs metrics readiness endpoints 2026-05-03 21:48:26 +08:00
gongzhiyong fb61f385fb deploy: make azure vm deploy helper executable 2026-05-03 21:17:34 +08:00
gongzhiyong e7b1fd81ec Merge commit 'd39e462ff2de4f82765159a18159f3f00c7f434f' 2026-05-03 20:50:46 +08:00
gongzhiyong f182610793 Merge commit '18a7b316a1da1fb16817387c586ba3db1ca84b1c' 2026-05-03 20:50:45 +08:00
gongzhiyong 36eb0159bc Merge commit '91617b5d64fcf528a34befea1d7a9168efe070c6' 2026-05-03 20:50:44 +08:00
gongzhiyongandOmX 18a7b316a1 Validate focused docs and backend checks
Worker 3 completed the assigned validation pass without source edits, recording backend pass evidence plus environment and contract findings for leader integration.

Tested: go vet ./controller ./model ./router; go test focused resource and Agnet grant cases; go test ./controller ./model ./router; git diff --check; focused docs secret scan.

Not-tested: frontend tsc/eslint require bun or full web dependencies; live Agnet curl checks require credentials and service URL.

Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-03 18:11:48 +08:00
gongzhiyong 91617b5d64 docs: tighten Agnet secret placeholders 2026-05-03 18:09:41 +08:00
gongzhiyong 660670d2fc docs: add azure deploy guardrails 2026-05-03 18:09:07 +08:00
gongzhiyong 0d7491c9a1 omx(team): auto-checkpoint worker-5 [unknown] 2026-05-03 18:09:04 +08:00
gongzhiyong b4413cc230 omx(team): merge worker-1 2026-05-03 18:09:01 +08:00
gongzhiyong d39e462ff2 docs: add azure deploy guardrails 2026-05-03 18:08:15 +08:00
gongzhiyong 6a3e918787 docs: complete Agnet platform contract 2026-05-03 18:05:45 +08:00
gongzhiyong aba1ce28df docs: add daily work summary 2026-05-02 23:49:18 +08:00
gongzhiyong ab71d5b72b docs: add agnet platform request contract 2026-05-02 23:42:51 +08:00
gongzhiyong 57a86ce060 Merge commit '8878d4040c9f4c1a94184ed7a9755e9d7f73a745' 2026-05-02 23:42:18 +08:00
gongzhiyong 8878d4040c task: implement P1 manager resource model 2026-05-02 23:36:33 +08:00
gongzhiyong 24405519a9 omx(team): auto-checkpoint worker-1 [1] 2026-05-02 23:32:00 +08:00
gongzhiyong 05182f0277 task: implement manager resource grants 2026-05-02 23:30:23 +08:00
gongzhiyong 5e4648e608 omx(team): auto-checkpoint worker-5 [5] 2026-05-02 23:29:39 +08:00
gongzhiyong 1aa3643278 omx(team): auto-checkpoint worker-3 [3] 2026-05-02 23:29:37 +08:00
gongzhiyong 0a01f36f1b omx(team): auto-checkpoint worker-2 [2] 2026-05-02 23:29:34 +08:00
gongzhiyong 33fa9f20a6 omx(team): auto-checkpoint worker-5 [5] 2026-05-02 23:28:40 +08:00
gongzhiyong a8be398087 omx(team): auto-checkpoint worker-4 [4] 2026-05-02 23:28:37 +08:00
gongzhiyong 30e0b0b4c6 omx(team): auto-checkpoint worker-2 [2] 2026-05-02 23:28:34 +08:00
gongzhiyong bf42bbda8a omx(team): auto-checkpoint worker-4 [4] 2026-05-02 23:26:17 +08:00
gongzhiyong f0cda510a7 omx(team): merge worker-3 2026-05-02 23:24:29 +08:00
gongzhiyong 6fa8dbcb20 omx(team): auto-checkpoint worker-3 [3] 2026-05-02 23:24:29 +08:00
gongzhiyong 912e3155fd docs: converge heicode plan entrypoint 2026-05-02 23:21:16 +08:00
gongzhiyong a19b90c858 docs: split heicode plan documents 2026-05-02 22:26:44 +08:00
gongzhiyong e08a5d4dcc docs: consolidate current heicode plan 2026-05-02 22:15:33 +08:00
gongzhiyong 72d0e095a4 docs: remove obsolete agnet plans 2026-05-02 22:11:19 +08:00
gongzhiyong f585d26fe7 docs: define saas manager agnet architecture 2026-05-02 22:07:02 +08:00
gongzhiyong 63fe529b36 feat(agnet): allow users to bind git sources 2026-05-01 20:55:58 +08:00
gongzhiyong 75bc93b47a docs(agnet): capture user deployment flow 2026-05-01 20:36:30 +08:00
xiaohei be0d102553 fix(manager): load env file in compose override 2026-05-01 11:50:13 +00:00