refactor: rename 'tier' to 'level' across the codebase
- Updated WorkerState type to use 'level' instead of 'tier'. - Modified functions related to worker state management, including parseWorkerState, emptyWorkerState, getSessionForLevel, activateWorker, and deactivateWorker to reflect the new terminology. - Adjusted health check logic to utilize 'level' instead of 'tier'. - Refactored tick and setup tools to accommodate the change from 'tier' to 'level', including model configuration and workspace scaffolding. - Updated tests to ensure consistency with the new 'level' terminology. - Revised documentation and comments to reflect the changes in terminology from 'tier' to 'level'.
This commit is contained in:
@@ -1,36 +1,20 @@
|
||||
/**
|
||||
* setup/config.ts — Plugin config writer (openclaw.json).
|
||||
*
|
||||
* Handles: model tier config, devClawAgentIds, tool restrictions, subagent cleanup.
|
||||
* Handles: model level config, devClawAgentIds, tool restrictions, subagent cleanup.
|
||||
*/
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { DEV_TIERS, QA_TIERS, tierName, type Tier } from "../tiers.js";
|
||||
import { HEARTBEAT_DEFAULTS } from "../services/heartbeat.js";
|
||||
|
||||
type ModelConfig = { dev: Record<string, string>; qa: Record<string, string> };
|
||||
|
||||
function openclawConfigPath(): string {
|
||||
return path.join(process.env.HOME ?? "/home/lauren", ".openclaw", "openclaw.json");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert flat tier map to nested role-tier structure.
|
||||
*/
|
||||
function buildRoleTierModels(models: Record<Tier, string>): { dev: Record<string, string>; qa: Record<string, string> } {
|
||||
const dev: Record<string, string> = {};
|
||||
const qa: Record<string, string> = {};
|
||||
|
||||
for (const tier of DEV_TIERS) {
|
||||
dev[tierName(tier)] = models[tier];
|
||||
}
|
||||
for (const tier of QA_TIERS) {
|
||||
qa[tierName(tier)] = models[tier];
|
||||
}
|
||||
|
||||
return { dev, qa };
|
||||
}
|
||||
|
||||
/**
|
||||
* Write DevClaw model tier config and devClawAgentIds to openclaw.json plugins section.
|
||||
* Write DevClaw model level config and devClawAgentIds to openclaw.json plugins section.
|
||||
*
|
||||
* Also configures:
|
||||
* - Tool restrictions (deny sessions_spawn, sessions_send) for DevClaw agents
|
||||
@@ -39,7 +23,7 @@ function buildRoleTierModels(models: Record<Tier, string>): { dev: Record<string
|
||||
* Read-modify-write to preserve existing config.
|
||||
*/
|
||||
export async function writePluginConfig(
|
||||
models: Record<Tier, string>,
|
||||
models: ModelConfig,
|
||||
agentId?: string,
|
||||
projectExecution?: "parallel" | "sequential",
|
||||
): Promise<void> {
|
||||
@@ -47,7 +31,7 @@ export async function writePluginConfig(
|
||||
const config = JSON.parse(await fs.readFile(configPath, "utf-8"));
|
||||
|
||||
ensurePluginStructure(config);
|
||||
config.plugins.entries.devclaw.config.models = buildRoleTierModels(models);
|
||||
config.plugins.entries.devclaw.config.models = models;
|
||||
|
||||
if (projectExecution) {
|
||||
config.plugins.entries.devclaw.config.projectExecution = projectExecution;
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
* Coordinates: agent creation → model config → workspace scaffolding.
|
||||
* Used by both the `setup` tool and the `openclaw devclaw setup` CLI command.
|
||||
*/
|
||||
import { ALL_TIERS, allDefaultModels, type Tier } from "../tiers.js";
|
||||
import { DEFAULT_MODELS } from "../tiers.js";
|
||||
import { migrateChannelBinding } from "../binding-manager.js";
|
||||
import { createAgent, resolveWorkspacePath } from "./agent.js";
|
||||
import { writePluginConfig } from "./config.js";
|
||||
import { scaffoldWorkspace } from "./workspace.js";
|
||||
|
||||
export type ModelConfig = { dev: Record<string, string>; qa: Record<string, string> };
|
||||
|
||||
export type SetupOpts = {
|
||||
/** Create a new agent with this name. Mutually exclusive with agentId. */
|
||||
newAgentName?: string;
|
||||
@@ -21,8 +23,8 @@ export type SetupOpts = {
|
||||
agentId?: string;
|
||||
/** Override workspace path (auto-detected from agent if not given). */
|
||||
workspacePath?: string;
|
||||
/** Model overrides per tier. Missing tiers use defaults. */
|
||||
models?: Partial<Record<Tier, string>>;
|
||||
/** Model overrides per role.level. Missing levels use defaults. */
|
||||
models?: { dev?: Partial<Record<string, string>>; qa?: Partial<Record<string, string>> };
|
||||
/** Plugin-level project execution mode: parallel or sequential. Default: parallel. */
|
||||
projectExecution?: "parallel" | "sequential";
|
||||
};
|
||||
@@ -31,7 +33,7 @@ export type SetupResult = {
|
||||
agentId: string;
|
||||
agentCreated: boolean;
|
||||
workspacePath: string;
|
||||
models: Record<Tier, string>;
|
||||
models: ModelConfig;
|
||||
filesWritten: string[];
|
||||
warnings: string[];
|
||||
bindingMigrated?: {
|
||||
@@ -107,14 +109,20 @@ async function tryMigrateBinding(
|
||||
}
|
||||
}
|
||||
|
||||
function buildModelConfig(overrides?: Partial<Record<Tier, string>>): Record<Tier, string> {
|
||||
const models = allDefaultModels();
|
||||
if (overrides) {
|
||||
for (const [tier, model] of Object.entries(overrides)) {
|
||||
if (model && (ALL_TIERS as readonly string[]).includes(tier)) {
|
||||
models[tier as Tier] = model;
|
||||
}
|
||||
function buildModelConfig(overrides?: SetupOpts["models"]): ModelConfig {
|
||||
const dev: Record<string, string> = { ...DEFAULT_MODELS.dev };
|
||||
const qa: Record<string, string> = { ...DEFAULT_MODELS.qa };
|
||||
|
||||
if (overrides?.dev) {
|
||||
for (const [level, model] of Object.entries(overrides.dev)) {
|
||||
if (model) dev[level] = model;
|
||||
}
|
||||
}
|
||||
return models;
|
||||
if (overrides?.qa) {
|
||||
for (const [level, model] of Object.entries(overrides.qa)) {
|
||||
if (model) qa[level] = model;
|
||||
}
|
||||
}
|
||||
|
||||
return { dev, qa };
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import path from "node:path";
|
||||
import {
|
||||
AGENTS_MD_TEMPLATE,
|
||||
HEARTBEAT_MD_TEMPLATE,
|
||||
DEFAULT_DEV_INSTRUCTIONS,
|
||||
DEFAULT_QA_INSTRUCTIONS,
|
||||
} from "../templates.js";
|
||||
|
||||
/**
|
||||
@@ -34,6 +36,20 @@ export async function scaffoldWorkspace(workspacePath: string): Promise<string[]
|
||||
filesWritten.push("projects/projects.json");
|
||||
}
|
||||
|
||||
// projects/roles/default/ (fallback role instructions)
|
||||
const defaultRolesDir = path.join(projectsDir, "roles", "default");
|
||||
await fs.mkdir(defaultRolesDir, { recursive: true });
|
||||
const devRolePath = path.join(defaultRolesDir, "dev.md");
|
||||
if (!await fileExists(devRolePath)) {
|
||||
await fs.writeFile(devRolePath, DEFAULT_DEV_INSTRUCTIONS, "utf-8");
|
||||
filesWritten.push("projects/roles/default/dev.md");
|
||||
}
|
||||
const qaRolePath = path.join(defaultRolesDir, "qa.md");
|
||||
if (!await fileExists(qaRolePath)) {
|
||||
await fs.writeFile(qaRolePath, DEFAULT_QA_INSTRUCTIONS, "utf-8");
|
||||
filesWritten.push("projects/roles/default/qa.md");
|
||||
}
|
||||
|
||||
// log/ directory (audit.log created on first write)
|
||||
const logDir = path.join(workspacePath, "log");
|
||||
await fs.mkdir(logDir, { recursive: true });
|
||||
|
||||
Reference in New Issue
Block a user