Mulai migrasi Zesdex dari Rust ke TypeScript/Bun.
- Root workspace package.json, tsconfig strict, bun.lock, gitignore fix
- Paket @zesdex/domain (apps/packages/domain):
- core: ChatMessage/Conversation/ToolCall/SseParser/repairJson/
sanitizeToolArguments/UsageStats/Store/DomainError
- auth: Session/SessionId/SessionLock/OAuth + repository & service interfaces
- cms: AppConfig/Settings/SettingsPatch/Memory/EditLog + repository &
service interfaces
- agent: TurnEvent/SessionRuntime/AgentTurnParams/AgentProgress/prompt
- subagent & workflow models
- Wire-shape JSON disamakan dengan Rust (serde rename/flatten/skip_if)
- 27 unit test Bun port dari test Rust (SseParser, repair_json, resolve_effective_model, session id)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
78 lines
2.3 KiB
TypeScript
78 lines
2.3 KiB
TypeScript
/**
|
|
* Application settings domain entity. Mirrors `settings.rs`.
|
|
*/
|
|
import type { AppConfig } from "./app_config.ts";
|
|
|
|
/** Controls how much network access the agent is permitted. */
|
|
export type InternetMode = "Off" | "ReadOnly" | "Full";
|
|
|
|
export const InternetModeLiteral = {
|
|
Off: "Off" as const,
|
|
ReadOnly: "ReadOnly" as const,
|
|
Full: "Full" as const,
|
|
} satisfies Record<string, InternetMode>;
|
|
|
|
/** Grouped boolean feature toggles. */
|
|
export interface SettingsFlags {
|
|
review_enabled: boolean;
|
|
session_archive_enabled: boolean;
|
|
}
|
|
|
|
export function newSettingsFlags(): SettingsFlags {
|
|
return { review_enabled: true, session_archive_enabled: true };
|
|
}
|
|
|
|
const DEFAULT_HIVE_MIND_NODE_TIMEOUT_MS = 600_000;
|
|
|
|
/** Top-level application settings model (serialized to `settings.json`). */
|
|
export interface Settings {
|
|
internet_mode: InternetMode;
|
|
provider: string;
|
|
model: string;
|
|
api_keys: Record<string, string>;
|
|
max_tokens?: number;
|
|
temperature?: number;
|
|
review_max_lessons_per_run: number;
|
|
adaptive_review_max_skip: number;
|
|
verify_command?: string;
|
|
verify_timeout_ms: number;
|
|
workflow_max_concurrency: number;
|
|
review_enabled: boolean;
|
|
session_archive_enabled: boolean;
|
|
hive_mind_node_timeout_ms: number;
|
|
}
|
|
|
|
export function newSettings(): Settings {
|
|
return {
|
|
internet_mode: "Off",
|
|
provider: "zen",
|
|
model: "deepseek-v4-flash-free",
|
|
api_keys: {},
|
|
max_tokens: undefined,
|
|
temperature: undefined,
|
|
review_max_lessons_per_run: 5,
|
|
adaptive_review_max_skip: 3,
|
|
verify_command: undefined,
|
|
verify_timeout_ms: 30_000,
|
|
workflow_max_concurrency: 5,
|
|
review_enabled: true,
|
|
session_archive_enabled: true,
|
|
hive_mind_node_timeout_ms: DEFAULT_HIVE_MIND_NODE_TIMEOUT_MS,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Pick the effective model name for the main agent.
|
|
*
|
|
* When `settings.provider === "claude"`, the provider's `default_model`
|
|
* (or the app-level `default_model`) wins over a possibly-stale persisted
|
|
* `settings.model`. Otherwise the user's explicit `settings.model` is used.
|
|
*/
|
|
export function resolveEffectiveModel(settings: Settings, appConfig: AppConfig): string {
|
|
if (settings.provider === "claude") {
|
|
const m = appConfig.providers["claude"]?.default_model;
|
|
if (m) return m;
|
|
return appConfig.default_model;
|
|
}
|
|
return settings.model;
|
|
} |