feat: 开源发布 — 完整 README、MIT 许可证、22+ 大模型厂商支持
- 重写 README.md:项目简介、快速开始、22+ 厂商列表、功能特性、架构说明、配置指南、FAQ、贡献指南 - 新增 MIT LICENSE - 包含全部源码与文档
This commit is contained in:
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+1
-1
@@ -166,7 +166,7 @@ export function checkBridgeMinVersion(): string | null {
|
||||
minVersion: string
|
||||
}>('tengu_bridge_min_version', { minVersion: '0.0.0' })
|
||||
if (config.minVersion && lt(MACRO.VERSION, config.minVersion)) {
|
||||
return `Your version of Claude Code (${MACRO.VERSION}) is too old for Remote Control.\nVersion ${config.minVersion} or higher is required. Run \`claude update\` to update.`
|
||||
return `Your version of 嘉陵江-code (${MACRO.VERSION}) is too old for Remote Control.\nVersion ${config.minVersion} or higher is required. Run \`jialing update\` to update.`
|
||||
}
|
||||
}
|
||||
return null
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+1
-1
@@ -147,7 +147,7 @@ export async function getEnvLessBridgeConfig(): Promise<EnvLessBridgeConfig> {
|
||||
export async function checkEnvLessBridgeMinVersion(): Promise<string | null> {
|
||||
const cfg = await getEnvLessBridgeConfig()
|
||||
if (cfg.min_version && lt(MACRO.VERSION, cfg.min_version)) {
|
||||
return `Your version of Claude Code (${MACRO.VERSION}) is too old for Remote Control.\nVersion ${cfg.min_version} or higher is required. Run \`claude update\` to update.`
|
||||
return `Your version of 嘉陵江-code (${MACRO.VERSION}) is too old for Remote Control.\nVersion ${cfg.min_version} or higher is required. Run \`jialing update\` to update.`
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+1
-1
@@ -147,7 +147,7 @@ export async function enrollTrustedDevice(): Promise<void> {
|
||||
device_id?: string
|
||||
}>(
|
||||
`${baseUrl}/api/auth/trusted_devices`,
|
||||
{ display_name: `Claude Code on ${hostname()} · ${process.platform}` },
|
||||
{ display_name: `嘉陵江-code on ${hostname()} · ${process.platform}` },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
+3
-3
@@ -165,7 +165,7 @@ function spriteColWidth(nameWidth: number): number {
|
||||
// Narrow terminals: 0 — REPL.tsx stacks the one-liner on its own row
|
||||
// (above input in fullscreen, below in scrollback), so no reservation.
|
||||
export function companionReservedColumns(terminalColumns: number, speaking: boolean): number {
|
||||
if (!feature('BUDDY')) return 0;
|
||||
if (!true) return 0;
|
||||
const companion = getCompanion();
|
||||
if (!companion || getGlobalConfig().companionMuted) return 0;
|
||||
if (terminalColumns < MIN_COLS_FOR_FULL_SPRITE) return 0;
|
||||
@@ -212,7 +212,7 @@ export function CompanionSprite(): React.ReactNode {
|
||||
return () => clearTimeout(timer);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps -- tick intentionally captured at reaction-change, not tracked
|
||||
}, [reaction, setAppState]);
|
||||
if (!feature('BUDDY')) return null;
|
||||
if (!true) return null;
|
||||
const companion = getCompanion();
|
||||
if (!companion || getGlobalConfig().companionMuted) return null;
|
||||
const color = RARITY_COLORS[companion.rarity];
|
||||
@@ -337,7 +337,7 @@ export function CompanionFloatingBubble() {
|
||||
t3 = $[4];
|
||||
}
|
||||
useEffect(t2, t3);
|
||||
if (!feature("BUDDY") || !reaction) {
|
||||
if (!true || !reaction) {
|
||||
return null;
|
||||
}
|
||||
const companion = getCompanion();
|
||||
|
||||
Regular → Executable
+49
-2
@@ -1,4 +1,7 @@
|
||||
import { getGlobalConfig } from '../utils/config.js'
|
||||
import { existsSync, readFileSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
import { homedir } from 'os'
|
||||
import { getGlobalConfig, saveGlobalConfig } from '../utils/config.js'
|
||||
import {
|
||||
type Companion,
|
||||
type CompanionBones,
|
||||
@@ -8,6 +11,7 @@ import {
|
||||
RARITY_WEIGHTS,
|
||||
type Rarity,
|
||||
SPECIES,
|
||||
type Species,
|
||||
STAT_NAMES,
|
||||
type StatName,
|
||||
} from './types.js'
|
||||
@@ -121,13 +125,56 @@ export function companionUserId(): string {
|
||||
return config.oauthAccount?.accountUuid ?? config.userID ?? 'anon'
|
||||
}
|
||||
|
||||
// ── Jialing config fallback ─────────────────────────────────────────────────
|
||||
// Read companion from ~/.jialing-code/config.json as a fallback when the
|
||||
// global claude config doesn't have it (setup wizard writes there first).
|
||||
let jialingCompanionMigrated = false
|
||||
|
||||
function tryMigrateJialingCompanion(): void {
|
||||
if (jialingCompanionMigrated) return
|
||||
jialingCompanionMigrated = true
|
||||
|
||||
try {
|
||||
const jialingConfigPath = join(homedir(), '.jialing-code', 'config.json')
|
||||
if (!existsSync(jialingConfigPath)) return
|
||||
const jialingConfig = JSON.parse(readFileSync(jialingConfigPath, 'utf-8'))
|
||||
if (!jialingConfig.companion) return
|
||||
|
||||
// Check if global config already has companion
|
||||
const globalConfig = getGlobalConfig()
|
||||
if (globalConfig.companion) return
|
||||
|
||||
// Migrate companion from jialing config to global config
|
||||
saveGlobalConfig(current => ({
|
||||
...current,
|
||||
companion: {
|
||||
name: jialingConfig.companion.name || 'Buddy',
|
||||
personality: jialingConfig.companion.personality || '',
|
||||
hatchedAt: jialingConfig.companion.hatchedAt || Date.now(),
|
||||
},
|
||||
companionSpeciesOverride: jialingConfig.companion.species,
|
||||
}))
|
||||
} catch {
|
||||
// Silent — best effort migration
|
||||
}
|
||||
}
|
||||
|
||||
// Regenerate bones from userId, merge with stored soul. Bones never persist
|
||||
// so species renames and SPECIES-array edits can't break stored companions,
|
||||
// and editing config.companion can't fake a rarity.
|
||||
export function getCompanion(): Companion | undefined {
|
||||
const stored = getGlobalConfig().companion
|
||||
// Try migrating companion from jialing config if not in global config
|
||||
tryMigrateJialingCompanion()
|
||||
|
||||
const config = getGlobalConfig()
|
||||
const stored = config.companion
|
||||
if (!stored) return undefined
|
||||
const { bones } = roll(companionUserId())
|
||||
// Allow user-chosen species override from setup wizard
|
||||
const speciesOverride = (config as any).companionSpeciesOverride
|
||||
if (speciesOverride && SPECIES.includes(speciesOverride as Species)) {
|
||||
bones.species = speciesOverride as Species
|
||||
}
|
||||
// bones last so stale bones fields in old-format configs get overridden
|
||||
return { ...stored, ...bones }
|
||||
}
|
||||
|
||||
Regular → Executable
+1
-1
@@ -15,7 +15,7 @@ When the user addresses ${name} directly (by name), its bubble will answer. Your
|
||||
export function getCompanionIntroAttachment(
|
||||
messages: Message[] | undefined,
|
||||
): Attachment[] {
|
||||
if (!feature('BUDDY')) return []
|
||||
if (!true) return []
|
||||
const companion = getCompanion()
|
||||
if (!companion || getGlobalConfig().companionMuted) return []
|
||||
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
+2
-2
@@ -50,7 +50,7 @@ export function useBuddyNotification() {
|
||||
let t1;
|
||||
if ($[0] !== addNotification || $[1] !== removeNotification) {
|
||||
t0 = () => {
|
||||
if (!feature("BUDDY")) {
|
||||
if (!true) {
|
||||
return;
|
||||
}
|
||||
const config = getGlobalConfig();
|
||||
@@ -80,7 +80,7 @@ export function findBuddyTriggerPositions(text: string): Array<{
|
||||
start: number;
|
||||
end: number;
|
||||
}> {
|
||||
if (!feature('BUDDY')) return [];
|
||||
if (!true) return [];
|
||||
const triggers: Array<{
|
||||
start: number;
|
||||
end: number;
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Regular → Executable
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user