chore: better welcome messgae, throw on config parse error
add instructions for gateway mode, change config order, and don't hard-code the config path, pull it from the default config
This commit is contained in:
@@ -5,13 +5,19 @@ import pc from 'picocolors';
|
|||||||
import { ConfigSchema, type Config } from '../config/types.ts';
|
import { ConfigSchema, type Config } from '../config/types.ts';
|
||||||
import { ensureWorkspace, resolvePath, checkWorkspaceEmpty, syncTemplates } from './utils.ts';
|
import { ensureWorkspace, resolvePath, checkWorkspaceEmpty, syncTemplates } from './utils.ts';
|
||||||
|
|
||||||
|
function logCreated(item: string) {
|
||||||
|
console.info(pc.green(` ✓ Created ${item}`));
|
||||||
|
}
|
||||||
|
|
||||||
export function onboardCommand(program: Command): void {
|
export function onboardCommand(program: Command): void {
|
||||||
program
|
program
|
||||||
.command('onboard [path]')
|
.command('onboard [path]')
|
||||||
.description('Initialize a new nanobot workspace with config and templates')
|
.description('Initialize a new nanobot workspace with config and templates')
|
||||||
.action(async (rawPath?: string) => {
|
.action(async (rawPath?: string) => {
|
||||||
try {
|
try {
|
||||||
const targetPath = resolvePath(rawPath ?? '~/.config/nanobot');
|
const defaultConfig: Config = ConfigSchema.parse({});
|
||||||
|
|
||||||
|
const targetPath = resolvePath(rawPath ?? defaultConfig.agent.workspacePath);
|
||||||
const configPath = join(targetPath, 'config.json');
|
const configPath = join(targetPath, 'config.json');
|
||||||
|
|
||||||
console.info(pc.blue('Initializing nanobot workspace...'));
|
console.info(pc.blue('Initializing nanobot workspace...'));
|
||||||
@@ -21,18 +27,17 @@ export function onboardCommand(program: Command): void {
|
|||||||
checkWorkspaceEmpty(targetPath);
|
checkWorkspaceEmpty(targetPath);
|
||||||
|
|
||||||
// Create workspace directory
|
// Create workspace directory
|
||||||
ensureWorkspace(targetPath);
|
ensureWorkspace(targetPath, true);
|
||||||
console.info(pc.green('✓ Created workspace directory'));
|
logCreated('workspace directory')
|
||||||
|
|
||||||
// Write default config
|
// Write default config
|
||||||
const defaultConfig: Config = ConfigSchema.parse({});
|
|
||||||
writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2), 'utf8');
|
writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2), 'utf8');
|
||||||
console.info(pc.green('✓ Created config.json'));
|
logCreated('config.json')
|
||||||
|
|
||||||
// Sync templates
|
// Sync templates
|
||||||
const createdFiles = syncTemplates(targetPath);
|
const createdFiles = syncTemplates(targetPath);
|
||||||
for (const file of createdFiles) {
|
for (const file of createdFiles) {
|
||||||
console.info(pc.dim(` Created ${file}`));
|
logCreated(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.info();
|
console.info();
|
||||||
@@ -40,10 +45,13 @@ export function onboardCommand(program: Command): void {
|
|||||||
console.info();
|
console.info();
|
||||||
console.info(pc.bold('Next steps:'));
|
console.info(pc.bold('Next steps:'));
|
||||||
console.info(` 1. Edit ${pc.cyan(configPath)} to add your API keys`);
|
console.info(` 1. Edit ${pc.cyan(configPath)} to add your API keys`);
|
||||||
console.info(` 2. Customize ${pc.cyan(join(targetPath, 'USER.md'))} with your preferences`);
|
console.info(` 2. Customize ${pc.cyan(join(targetPath, 'USER.md'))} and ${pc.cyan(join(targetPath, 'SOUL.md'))} with your preferences`);
|
||||||
console.info(` 3. Start chatting: ${pc.cyan('bun run nanobot agent')}`);
|
console.info(` 3. Start chatting: ${pc.cyan('bun run nanobot agent')}`);
|
||||||
console.info();
|
console.info();
|
||||||
console.info(pc.dim('For Mattermost integration, configure the channels.mattermost section in config.json'));
|
console.info(` -- For gateway mode:`);
|
||||||
|
console.info(` 1. Edit ${pc.cyan(configPath)} to add your channel config (Mattermost)`);
|
||||||
|
console.info(` 2. Connect your agent: ${pc.cyan('bun run nanobot gateway')}`);
|
||||||
|
console.info();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(pc.red(String(err)));
|
console.error(pc.red(String(err)));
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ export function loadConfig(configPath?: string): Config {
|
|||||||
let json: unknown;
|
let json: unknown;
|
||||||
try {
|
try {
|
||||||
json = JSON.parse(raw);
|
json = JSON.parse(raw);
|
||||||
} catch {
|
} catch(error) {
|
||||||
console.error(`Failed to parse config at ${path}`);
|
console.error(`Failed to parse config at ${path}`);
|
||||||
return ConfigSchema.parse({});
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply NANOBOT_ env var overrides before validation
|
// Apply NANOBOT_ env var overrides before validation
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ export type HeartbeatConfig = z.infer<typeof HeartbeatConfigSchema>;
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export const ConfigSchema = z.object({
|
export const ConfigSchema = z.object({
|
||||||
|
providers: ProvidersConfigSchema.default(() => ({})),
|
||||||
agent: AgentConfigSchema.default(() => ({
|
agent: AgentConfigSchema.default(() => ({
|
||||||
model: 'anthropic/claude-sonnet-4-5',
|
model: 'anthropic/claude-sonnet-4-5',
|
||||||
workspacePath: '~/.config/nanobot',
|
workspacePath: '~/.config/nanobot',
|
||||||
@@ -120,13 +121,12 @@ export const ConfigSchema = z.object({
|
|||||||
temperature: 0.7,
|
temperature: 0.7,
|
||||||
maxToolIterations: 40,
|
maxToolIterations: 40,
|
||||||
})),
|
})),
|
||||||
providers: ProvidersConfigSchema.default(() => ({})),
|
heartbeat: HeartbeatConfigSchema.default(() => ({ enabled: false, intervalMinutes: 30 })),
|
||||||
channels: ChannelsConfigSchema.default(() => ({ sendProgress: true, sendToolHints: true })),
|
channels: ChannelsConfigSchema.default(() => ({ sendProgress: true, sendToolHints: true })),
|
||||||
tools: ToolsConfigSchema.default(() => ({
|
tools: ToolsConfigSchema.default(() => ({
|
||||||
exec: { timeout: 120, denyPatterns: [], restrictToWorkspace: false },
|
exec: { timeout: 120, denyPatterns: [], restrictToWorkspace: false },
|
||||||
web: {},
|
web: {},
|
||||||
restrictToWorkspace: false,
|
restrictToWorkspace: false,
|
||||||
})),
|
})),
|
||||||
heartbeat: HeartbeatConfigSchema.default(() => ({ enabled: false, intervalMinutes: 30 })),
|
|
||||||
});
|
});
|
||||||
export type Config = z.infer<typeof ConfigSchema>;
|
export type Config = z.infer<typeof ConfigSchema>;
|
||||||
|
|||||||
Reference in New Issue
Block a user