Compare commits
2 Commits
47c4db53af
...
b6df31fcbf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6df31fcbf | ||
|
|
14aa1c1e7f |
@@ -4,10 +4,10 @@ import pc from 'picocolors';
|
|||||||
import { AgentLoop } from '../agent/loop.ts';
|
import { AgentLoop } from '../agent/loop.ts';
|
||||||
import { MessageBus } from '../bus/queue.ts';
|
import { MessageBus } from '../bus/queue.ts';
|
||||||
import { makeProvider } from '../provider/index.ts';
|
import { makeProvider } from '../provider/index.ts';
|
||||||
|
import { loadConfig } from '../config/loader.ts';
|
||||||
import { ensureWorkspace } from './utils.ts';
|
import { ensureWorkspace } from './utils.ts';
|
||||||
import type { Config } from '../config/types.ts';
|
|
||||||
|
|
||||||
export function agentCommand(program: Command, config: Config, workspace: string): void {
|
export function agentCommand(program: Command): void {
|
||||||
program
|
program
|
||||||
.command('agent')
|
.command('agent')
|
||||||
.description('Run the agent interactively or send a single message.')
|
.description('Run the agent interactively or send a single message.')
|
||||||
@@ -15,7 +15,10 @@ export function agentCommand(program: Command, config: Config, workspace: string
|
|||||||
.option('-m, --message <text>', 'Single message to process (non-interactive)')
|
.option('-m, --message <text>', 'Single message to process (non-interactive)')
|
||||||
.option('-M, --model <model>', 'Model override')
|
.option('-M, --model <model>', 'Model override')
|
||||||
.action(async (opts: { config?: string; message?: string; model?: string }) => {
|
.action(async (opts: { config?: string; message?: string; model?: string }) => {
|
||||||
|
const config = loadConfig(opts.config);
|
||||||
|
const workspace = config.agent.workspacePath;
|
||||||
ensureWorkspace(workspace);
|
ensureWorkspace(workspace);
|
||||||
|
|
||||||
console.info(pc.magenta(`workspace path: ${workspace}`));
|
console.info(pc.magenta(`workspace path: ${workspace}`));
|
||||||
|
|
||||||
const model = opts.model ?? config.agent.model;
|
const model = opts.model ?? config.agent.model;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Command } from 'commander';
|
import { Command } from 'commander';
|
||||||
import { loadConfig, resolveWorkspacePath } from '../config/loader.ts';
|
|
||||||
import { agentCommand } from './agent.ts';
|
import { agentCommand } from './agent.ts';
|
||||||
import { gatewayCommand } from './gateway.ts';
|
import { gatewayCommand } from './gateway.ts';
|
||||||
import { onboardCommand } from './onboard.ts';
|
import { onboardCommand } from './onboard.ts';
|
||||||
@@ -10,13 +9,8 @@ export function createCli(): Command {
|
|||||||
.version('1.0.0');
|
.version('1.0.0');
|
||||||
|
|
||||||
onboardCommand(program);
|
onboardCommand(program);
|
||||||
|
gatewayCommand(program);
|
||||||
const globalOpts = program.opts();
|
agentCommand(program);
|
||||||
const config = loadConfig(globalOpts.config);
|
|
||||||
const workspace = resolveWorkspacePath(config.agent.workspacePath);
|
|
||||||
|
|
||||||
gatewayCommand(program, config, workspace);
|
|
||||||
agentCommand(program, config, workspace);
|
|
||||||
|
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,19 @@ import { MattermostChannel } from '../channels/mattermost.ts';
|
|||||||
import { CronService } from '../cron/service.ts';
|
import { CronService } from '../cron/service.ts';
|
||||||
import { HeartbeatService } from '../heartbeat/service.ts';
|
import { HeartbeatService } from '../heartbeat/service.ts';
|
||||||
import { makeProvider } from '../provider/index.ts';
|
import { makeProvider } from '../provider/index.ts';
|
||||||
|
import { loadConfig } from '../config/loader.ts';
|
||||||
import { ensureWorkspace } from './utils.ts';
|
import { ensureWorkspace } from './utils.ts';
|
||||||
|
|
||||||
import type { Config } from '../config/types.ts';
|
export function gatewayCommand(program: Command): void {
|
||||||
|
|
||||||
export function gatewayCommand(program: Command, config: Config, workspace: string): void {
|
|
||||||
program
|
program
|
||||||
.command('gateway')
|
.command('gateway')
|
||||||
.option('-c, --config <path>', 'Path to config.json')
|
.option('-c, --config <path>', 'Path to config.json')
|
||||||
.description('Start the full gateway: Mattermost channel, agent loop, cron, and heartbeat.')
|
.description('Start the full gateway: Mattermost channel, agent loop, cron, and heartbeat.')
|
||||||
.action(async (_opts: { config?: string }) => {
|
.action(async (opts: { config?: string }) => {
|
||||||
|
const config = loadConfig(opts.config);
|
||||||
|
const workspace = config.agent.workspacePath;
|
||||||
ensureWorkspace(workspace);
|
ensureWorkspace(workspace);
|
||||||
|
|
||||||
console.info(pc.magenta(`workspace path: ${workspace}`));
|
console.info(pc.magenta(`workspace path: ${workspace}`));
|
||||||
|
|
||||||
const provider = makeProvider(
|
const provider = makeProvider(
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { join } from 'node:path';
|
|||||||
import { Command } from 'commander';
|
import { Command } from 'commander';
|
||||||
import pc from 'picocolors';
|
import pc from 'picocolors';
|
||||||
import { ConfigSchema, type Config } from '../config/types.ts';
|
import { ConfigSchema, type Config } from '../config/types.ts';
|
||||||
|
import { WORKSPACE_PATH } from '../config/constants.ts'
|
||||||
import { ensureWorkspace, resolvePath, checkWorkspaceEmpty, syncTemplates } from './utils.ts';
|
import { ensureWorkspace, resolvePath, checkWorkspaceEmpty, syncTemplates } from './utils.ts';
|
||||||
|
|
||||||
function logCreated(item: string) {
|
function logCreated(item: string) {
|
||||||
@@ -15,9 +16,14 @@ export function onboardCommand(program: Command): void {
|
|||||||
.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 defaultConfig: Config = ConfigSchema.parse({});
|
const defaultConfig: Config = ConfigSchema.parse({
|
||||||
|
agent: {
|
||||||
|
provider: '',
|
||||||
|
model: '',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const targetPath = resolvePath(rawPath ?? defaultConfig.agent.workspacePath);
|
const targetPath = resolvePath(rawPath ?? WORKSPACE_PATH);
|
||||||
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...'));
|
||||||
|
|||||||
1
src/config/constants.ts
Normal file
1
src/config/constants.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const WORKSPACE_PATH = '~/.config/nanobot'
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||||
import { homedir } from 'node:os';
|
import { homedir } from 'node:os';
|
||||||
import { dirname, resolve } from 'node:path';
|
import { dirname, resolve } from 'node:path';
|
||||||
|
import pc from 'picocolors'
|
||||||
import { type Config, ConfigSchema } from './types.ts';
|
import { type Config, ConfigSchema } from './types.ts';
|
||||||
|
import { WORKSPACE_PATH } from './constants.ts'
|
||||||
|
|
||||||
const DEFAULT_CONFIG_PATH = resolve(homedir(), '.config', 'nanobot', 'config.json');
|
const DEFAULT_CONFIG_PATH = resolve(homedir(), '.config', 'nanobot', 'config.json');
|
||||||
|
|
||||||
@@ -13,7 +15,8 @@ export function loadConfig(configPath?: string): Config {
|
|||||||
const path = getConfigPath(configPath);
|
const path = getConfigPath(configPath);
|
||||||
|
|
||||||
if (!existsSync(path)) {
|
if (!existsSync(path)) {
|
||||||
return ConfigSchema.parse({});
|
console.error(pc.red(`Failed to load config from ${configPath}`));
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const raw = readFileSync(path, 'utf8');
|
const raw = readFileSync(path, 'utf8');
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import { WORKSPACE_PATH } from './constants.ts'
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Mattermost
|
// Mattermost
|
||||||
@@ -41,7 +42,7 @@ export type ChannelsConfig = z.infer<typeof ChannelsConfigSchema>;
|
|||||||
|
|
||||||
export const AgentConfigSchema = z.object({
|
export const AgentConfigSchema = z.object({
|
||||||
model: z.string().default('anthropic/claude-sonnet-4-5'),
|
model: z.string().default('anthropic/claude-sonnet-4-5'),
|
||||||
workspacePath: z.string().default('~/.config/nanobot'),
|
workspacePath: z.string().default(WORKSPACE_PATH),
|
||||||
maxTokens: z.number().int().default(4096),
|
maxTokens: z.number().int().default(4096),
|
||||||
contextWindowTokens: z.number().int().default(65536),
|
contextWindowTokens: z.number().int().default(65536),
|
||||||
temperature: z.number().default(0.7),
|
temperature: z.number().default(0.7),
|
||||||
@@ -113,14 +114,7 @@ export type HeartbeatConfig = z.infer<typeof HeartbeatConfigSchema>;
|
|||||||
|
|
||||||
export const ConfigSchema = z.object({
|
export const ConfigSchema = z.object({
|
||||||
providers: ProvidersConfigSchema.default(() => ({})),
|
providers: ProvidersConfigSchema.default(() => ({})),
|
||||||
agent: AgentConfigSchema.default(() => ({
|
agent: AgentConfigSchema,
|
||||||
model: 'anthropic/claude-sonnet-4-5',
|
|
||||||
workspacePath: '~/.config/nanobot',
|
|
||||||
maxTokens: 4096,
|
|
||||||
contextWindowTokens: 65536,
|
|
||||||
temperature: 0.7,
|
|
||||||
maxToolIterations: 40,
|
|
||||||
})),
|
|
||||||
heartbeat: HeartbeatConfigSchema.default(() => ({ enabled: false, intervalMinutes: 30 })),
|
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(() => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user