Files
hermes-agent/apps/shared/src/index.ts
T
Teknium aff19d0251 feat(desktop): multi-source agents end-to-end — sockets, roster, SDK, fan-out updates
Phases 3-5 of the multi-connection campaign in one PR (per Teknium), on top
of the registry (#86679) and composite-key backend routing (#86839). Agents
from every registered connection are now usable side by side.

Renderer socket registry (phase 3):
- backendScopeKey moves to apps/shared (@hermes/shared) so main-process pool
  keys and renderer socket keys derive from ONE rule; the electron module
  keeps a byte-identical twin (tsconfig project boundaries) pinned by a
  cross-copy contract test.
- store/gateway secondaries are scope-keyed: entries carry (connectionId,
  profile); registry-scoped entries dial through getConnectionFor +
  getGatewayWsUrlFor (fresh per-connect OAuth tickets against the right
  host); events keep the bare profile plus a connectionId tag; touch/idle
  keepalive uses the scope key; pruning keeps entries whose PROFILE has live
  work. New ensureGatewayForAgent/openGatewayForAgent fall through to the
  profile path for local/null sources — single-source behavior byte-identical.

Union roster + plugin SDK (phases 3+4, the Bot Mode door):
- hermes:agents:roster enumerates every connection's /api/profiles
  concurrently (eager REST, lazy sockets; unreachable sources report per-row;
  undialed ssh boxes stay connect-on-demand) and flattens through
  buildAgentRoster — the @name-device duplicate-handle rule applied once
  across all sources, pure + tested.
- SDK: host.connections(), host.agents(), host.warmAgent(),
  host.ensureAgent() — feature-detected so plugins degrade cleanly on older
  Desktop builds.

Fan-out updates (phase 5):
- hermes:connections:update-all dispatches hermes update to every eligible
  source in parallel: local via the app's own applyUpdates pipeline,
  remote/ssh via the backend's own POST /api/hermes/update; cloud skipped as
  platform-managed (updateEligibility, pure + tested); per-connection result
  rows so one dead box can't wedge the batch. Settings → Connections gains
  the "Update all instances" button (shown with 2+ connections).

Also: getJsonForBackend/postJsonForBackend helpers with the token/OAuth-cookie
auth split; docs section updated from "staged rollout" to live behavior.

Tests: +4 pure cases (cross-copy contract, roster handles, unreachable
sources, update eligibility); FULL desktop suite 5115 passed; tsc renderer +
electron + shared clean; eslint clean.
2026-08-15 03:11:32 -07:00

79 lines
1.8 KiB
TypeScript

export {
backendScopeKey,
backendScopePrefix,
LOCAL_CONNECTION_ID
} from './backend-scope'
export {
BILLING_REFUSAL_POLICY,
type BillingRecovery,
type BillingRefusalPolicy,
refusalPolicy
} from './billing-policy'
export type {
BillingAutoReload,
BillingBlock,
BillingCardInfo,
BillingChargeResponse,
BillingChargeStatusResponse,
BillingErrorPayload,
BillingMonthlyCap,
BillingMutationResponse,
BillingPaymentMethod,
BillingRefusalCode,
BillingStateResponse,
ChargeFailureReason,
KnownBillingRefusalCode,
KnownChargeFailureReason,
SubscriptionPreviewResponse,
SubscriptionStateResponse,
SubscriptionTierOption,
SubscriptionUpgradeResponse,
UsageBarData,
UsageModelData
} from './billing-types'
export {
driveChargeSettlement,
SETTLEMENT_MAX_RETRY_AFTER_MS,
SETTLEMENT_POLL_CAP_MS,
SETTLEMENT_POLL_INTERVAL_MS,
type SettlementDeps,
type SettlementOutcome
} from './charge-settlement'
export {
createCronTriggerController,
type CronTriggerController,
type CronTriggerRunResult
} from './cron-trigger-controller'
export {
type ConnectionState,
type GatewayClientOptions,
type GatewayEvent,
type GatewayEventName,
type GatewayRequestId,
type JsonRpcFrame,
JsonRpcGatewayClient,
type WebSocketLike
} from './json-rpc-gateway'
export { skillInvocationText } from './skill-scaffold'
export {
type HermesSkin,
SKIN_BRANDING_TOKENS,
SKIN_COLOR_TOKENS,
type SkinBranding,
type SkinBrandingToken,
type SkinColors,
type SkinColorToken
} from './skin'
export {
buildHermesWebSocketUrl,
type GatewayAuthMode,
GatewayReauthRequiredError,
type GatewayWsConnection,
type GatewayWsUrlResult,
type HermesWebSocketUrlOptions,
isGatewayReauthRequired,
resolveGatewayWsUrl,
type ResolveGatewayWsUrlDeps,
type WebSocketAuthParam
} from './websocket-url'