Commit Graph

2355 Commits

Author SHA1 Message Date
yushen
eb4ce85602 refactor(hub): rename Device ID to Hub ID in console layer
Rename the business-layer concept from "Device ID" to "Hub ID" for
better user comprehension. The underlying network transport layer
still uses deviceId — Hub ID is passed as the deviceId value.

- Rename device.ts → hub-identity.ts, getDeviceId → getHubId
- Storage file: ~/.super-multica/device-id → ~/.super-multica/hub-id
- Hub property: deviceId → hubId
- API response field: deviceId → hubId
- Console UI label: "Device ID" → "Hub ID"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 16:02:00 +08:00
Jiayuan
a3e9fb60eb Merge pull request #32 from multica-ai/forrestchang/cli-build-bin
feat(cli): add binary build support
2026-01-30 15:58:40 +08:00
Jiang Bohan
578c8a6534 docs(skills): add README for skills system 2026-01-30 15:53:55 +08:00
LinYushen
b66bbdde06 Merge pull request #33 from multica-ai/fix/openrouter-provider
fix(agent): add OpenRouter provider support
2026-01-30 15:51:27 +08:00
yushen
b8201293b6 fix(agent): add OpenRouter provider support and guard against unknown models
Use generic OPENROUTER_* env vars (OPENROUTER_API_KEY, OPENROUTER_BASE_URL,
OPENROUTER_MODEL) via the existing fallback mechanism instead of hardcoding
mappings to OPENAI_* vars. Also add a guard when resolveModel returns
undefined to throw a clear error instead of crashing on property access.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:50:49 +08:00
Jiang Bohan
da3bb254ec fix(skills): support nested skill directories and managed skills
- Add managed skills directory (~/.super-multica/skills/) to loader
- Change discoverSkillDirs to recursively scan up to 3 levels deep
- Skip hidden directories during scan
- Fixes skills installed via `skills add` not being discovered

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:36:31 +08:00
Jiang Bohan
ecaada1df0 feat(skills): add CLI commands for add/remove skills
Add new CLI commands:
- add <source>: Add skill from GitHub (owner/repo format)
- remove <name>: Remove installed skill
- Support for --force flag to overwrite existing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:30:00 +08:00
Jiang Bohan
aee807e95a feat(skills): add module for GitHub skill installation
Implement skill download from GitHub repositories:
- parseSource() to handle owner/repo, owner/repo/skill, and full URLs
- addSkill() with shallow clone and sparse checkout support
- removeSkill() to uninstall skills
- listInstalledSkills() for listing managed skills
- Automatic .git cleanup after clone

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:29:55 +08:00
Jiayuan
7f25378e4b feat(cli): add binary build support for interactive CLI
Add esbuild-based build script to bundle CLI tools into standalone
binaries that can be run directly with node. The built binaries
externalize dependencies to keep bundle size small and avoid
bundling issues with native modules.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:22:53 +08:00
Jiang Bohan
1105a7ac1f feat(skills): add CLI for skills management
Add skills-cli.ts with commands:
- list: Show all skills with eligibility status
- status [id]: Show detailed skill info or summary
- install <id>: Install skill dependencies

Add skills:cli script to package.json

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:15:56 +08:00
Jiang Bohan
91709ddd84 feat(skills): integrate watcher into SkillManager
Add hot reload support to SkillManager:
- startWatching/stopWatching methods
- Version-based automatic cache invalidation
- Export install and watcher functions
- listAllSkillsWithStatus and checkSkillEligibility helpers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:15:51 +08:00
Jiang Bohan
8eba6c0f4a feat(skills): add file watcher for hot reload
Implement chokidar-based file watching for skill hot reload:
- Version-based cache invalidation
- Debounced change detection
- Change listener registration with onSkillsChange
- Dynamic chokidar import (optional dependency)
- Watch skill directories with configurable paths

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:15:46 +08:00
Jiang Bohan
5853c9146a feat(skills): add install mechanism for skill dependencies
Implement install support for brew/npm/uv/go/download methods:
- buildInstallCommand for each installer type
- selectPreferredInstallSpec with configurable priority
- installSkill main function with timeout support
- Download support with archive extraction (tar.gz, zip)
- getInstallOptions for UI listing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:15:41 +08:00
Jiang Bohan
6d0ee87fdf test(skills): update eligibility tests for new context-based API
- Update checkEligibility calls to use EligibilityContext object
- Add tests for new features: anyBins, always flag, config disabled
- Add tests for bundled allowlist filtering
- Add tests for env var injection via config
- Add tests for apiKey + primaryEnv combination
- Add tests for new requires.bins/env format alongside legacy format

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:01:50 +08:00
Jiang Bohan
3d2e539127 feat(agent): integrate skills config into AgentOptions
- Add skills?: SkillsConfig to AgentOptions
- Update runner.ts to pass skills config to SkillManager
- Merge extraSkillDirs from options with config.load.extraDirs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:01:44 +08:00
Jiang Bohan
00915d7fb9 feat(skills): enhance metadata and config system for OpenClaw compatibility
- Add SkillInstallSpec type for future install mechanism support
- Add SkillRequirements type with bins, anyBins, env, config checks
- Add SkillConfig, SkillsConfig types for per-skill and global config
- Add utility functions: getSkillKey, getSkillConfig, normalizeRequirements
- Support both new (requires.bins, os) and legacy (requiresBinaries, platforms) fields
- Implement 'always' flag to skip eligibility checks
- Implement bundled skills allowlist filtering
- Implement config-based skill enable/disable
- Implement env var injection via config (apiKey + primaryEnv)
- Add listAllSkillsWithStatus() method to SkillManager
- Export new types and utility functions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 15:01:35 +08:00
LinYushen
4f50b3b399 Merge pull request #31 from multica-ai/copy-env-file
feat(gateway): add PWA mobile client
2026-01-30 15:00:59 +08:00
yushen
f3ec056b90 feat(console): redesign Hub Console UI for desktop
- Stat cards grid (Device ID, Gateway, State, Agents) with copy buttons
- Connection state badge with colored dot indicator
- Inline gateway URL form with accent Connect button
- Agent table with hover-reveal copy and delete actions
- Toast notification on clipboard copy
- Centered container layout (960px max)
- Consistent dark theme matching Multica Client branding

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:59:00 +08:00
yushen
d9ba793fee fix(gateway): extract content from payload in received messages
Display payload.content instead of raw JSON when the payload
is an object with a content field.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:46:30 +08:00
yushen
7775ba5ca9 fix(gateway): stack target fields vertically for mobile
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:43:22 +08:00
yushen
e35aa95690 chore(gateway): rename client from Geneva to Multica
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:41:48 +08:00
yushen
25d447afc6 feat(gateway): polish PWA client UI for mobile
- Move disconnect button into header as a compact X icon
- Add app logo to header and setup screen
- Truncate device ID with tap-to-copy
- Collapsible target bar with smart label summary
- Empty state illustration when no messages
- Pulsing status dot animation for live connection
- Rounded send button, chat-bubble message input
- Glassmorphism header/compose bar with backdrop blur
- Auto-open target bar when targets not set
- Auto-collapse target bar after first send

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:39:31 +08:00
yushen
0f8db7083c fix(gateway): serve PWA client under /client subpath
Move static files from / to /client to avoid conflicts with
WebSocket and existing HTTP endpoints. Update manifest, service
worker, and HTML asset references accordingly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:35:40 +08:00
yushen
5f2cc06111 fix(gateway): fix Dockerfile build and copy static assets
- Replace `pnpm build` (turbo recursion) with direct `tsc` invocation
- Copy gateway/public static assets into dist for PWA serving

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:32:01 +08:00
yushen
1ddde840de chore(gateway): use provided PNG icon for PWA
Replace generated SVG icon with the provided PNG icon across
manifest, HTML, and service worker precache.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:27:45 +08:00
yushen
566f14f8ac feat(gateway): add PWA mobile client
Add a mobile-first PWA client served from the Gateway, mirroring the
console demo client functionality with enhanced mobile UX:
- Chat-bubble style messaging UI with safe-area support
- PWA manifest, service worker, and SVG icon
- ServeStaticModule added to Gateway for static file serving

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:24:28 +08:00
Jiayuan
75fba044bd Merge pull request #30 from multica-ai/forrestchang/add-unit-tests
test: add comprehensive unit tests across the codebase
2026-01-30 14:13:10 +08:00
LinYushen
0bc5380765 Merge pull request #29 from multica-ai/agent-api-key-baseurl
feat(agent): add LLM provider config and Hub agent persistence
2026-01-30 14:08:26 +08:00
yushen
e5feb96b0b Merge remote-tracking branch 'origin/main' into agent-api-key-baseurl
# Conflicts:
#	src/shared/index.ts
2026-01-30 14:06:36 +08:00
Jiayuan
f6360c32d9 test(ssrf): expand SSRF test coverage
Add tests for createPinnedLookup, resolvePinnedHostname,
createPinnedDispatcher, and closeDispatcher functions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:01:00 +08:00
Jiayuan
44d0cef838 test(tools): add unit tests for glob and param-helpers
Add tests for:
- Glob tool pattern matching, limits, and ignore patterns
- Parameter helpers for string/number parsing and JSON results

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:00:53 +08:00
Jiayuan
5353161b1d test(skills): add unit tests for skills loader
Add tests for getProfileSkillsDir, getBundledSkillsDir, and loadAllSkills
with skill precedence, invalid files, and directory discovery.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:00:47 +08:00
Jiayuan
0f8d032b68 test(context): add unit tests for context window guard
Add tests for resolveContextWindowInfo, evaluateContextWindowGuard,
and checkContextWindow functions with various threshold scenarios.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:00:38 +08:00
yushen
c6d0476679 feat(hub): persist agent list to disk for restart recovery
Store agent records in ~/.super-multica/agents/agents.json.
Hub restores agents on startup and updates the file on create/delete.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:56:19 +08:00
Jiayuan
4201095519 test(profile): add unit tests for profile storage
Add tests for profile file storage operations including read,
write, load, and save functionality with temp directory isolation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:55:03 +08:00
Jiayuan
9345128367 test(context): add unit tests for token estimation and compaction
Add tests for:
- Token estimation and usage calculation
- Token-aware message compaction
- Count and token-based compaction strategies

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:54:57 +08:00
Jiayuan
de8ff730fb test(skills): add unit tests for parser and eligibility checker
Add tests for:
- YAML frontmatter parsing from SKILL.md files
- Skill eligibility checking (platform, binary, env requirements)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:54:50 +08:00
Jiayuan
9f5424eb5c test(web): add unit tests for SSRF, cache, and HTML utilities
Add comprehensive tests for:
- SSRF protection (isPrivateIpAddress, isBlockedHostname)
- Cache utilities (readCache, writeCache, TTL handling)
- HTML utilities (htmlToMarkdownSimple, markdownToText, truncateText)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:54:44 +08:00
Jiayuan
7215a15e37 chore: set up Vitest testing framework
Add Vitest and @vitest/coverage-v8 for unit testing. Configure
test scripts and add coverage directory to gitignore.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:54:34 +08:00
Jiayuan
a86774e7b5 chore(ci): add GitHub Actions workflow (#28) 2026-01-30 13:51:05 +08:00
Jiayuan
f74ac430a9 feat(shared): add error handling infrastructure (#27)
- Add JakartaError base class with error codes and retry semantics
- Add typed error classes for network, session, compaction, process, channel, and gateway errors
- Add withRetry utility with exponential backoff, jitter, and abort support
- Add CancellationToken with hierarchical parent-child cancellation support

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:50:49 +08:00
yushen
36e9acb35f refactor(shared): extract DATA_DIR constant to shared/paths.ts
Replace hardcoded ~/.super-multica paths across agent and hub modules
with a single DATA_DIR constant exported from shared.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:49:35 +08:00
yushen
98f3f7ed50 chore(agent): remove --env-file from agent:cli script
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:49:28 +08:00
yushen
a9dcde124b docs: add .env.example and environment configuration guide
- Add .env.example with all supported provider env vars
  (OpenAI, Anthropic, DeepSeek, Kimi, Groq, Mistral, Together, Google)
- Update README with environment setup instructions
- Document configuration priority and startup commands
- Whitelist .env.example in .gitignore

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:32:01 +08:00
yushen
0d1f48cf53 refactor(agent): rename env vars to LLM_PROVIDER and provider-specific MODEL
- AGENT_PROVIDER → LLM_PROVIDER
- AGENT_MODEL → provider-specific env vars (e.g., OPENAI_MODEL, DEEPSEEK_MODEL)
- Add resolveModelId function matching resolveApiKey/resolveBaseUrl pattern

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:20:20 +08:00
yushen
236863acd4 feat(agent): support AGENT_PROVIDER and AGENT_MODEL env vars
Add environment variable support for provider/model defaults:
- AGENT_PROVIDER: default LLM provider (fallback: kimi-coding)
- AGENT_MODEL: default model name
- Auto-load .env via tsx --env-file in agent:cli script

Priority: CLI args > env vars > session meta > defaults.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:15:11 +08:00
yushen
9858576abe feat(agent): support custom API key and base URL configuration
Add apiKey and baseUrl options to AgentOptions, with support for:
- Explicit values via CLI args (--api-key, --base-url)
- Provider-specific environment variables (e.g., OPENAI_BASE_URL)
- Generic fallback format (PROVIDER_BASE_URL)

Priority: CLI args > env vars > library defaults.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:12:24 +08:00
LinYushen
6f8c9ef383 Merge pull request #26 from multica-ai/view-recent-commits
feat(agent): add SyncAgent/AsyncAgent wrappers and integrate with Hub
2026-01-30 12:51:08 +08:00
yushen
0212b02f4e Merge remote-tracking branch 'origin/main' into view-recent-commits
# Conflicts:
#	.gitignore
2026-01-30 12:50:20 +08:00
yushen
e0615dbe69 chore: add .env to gitignore
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:48:22 +08:00