mirror of
https://github.com/qwibitai/nanoclaw.git
synced 2026-06-04 10:14:47 +08:00
9486d56b01
- Move all v1 files (index, router, container-runner, db, ipc, types, logger, channels/registry, and all utilities) to src/v1/ as a fully self-contained archive with no shared dependencies - Rename v2 files to remove -v2 suffix (index-v2.ts → index.ts, etc.) - Update all imports across v2 source, tests, and setup files - Migrate shared utilities (config, env, container-runtime, mount-security, timezone, group-folder) from pino logger to v2 log module - Migrate setup/ files from logger to log with argument order swap - Container agent-runner: move v1 entry to v1/, rename v2 to index.ts - Update setup skill to offer all 13 v2 channels - Install all Chat SDK adapter packages - dist/index.js now runs v2; dist/v1/index.js runs v1 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
/**
|
|
* Step: timezone — Detect, validate, and persist the user's timezone.
|
|
* Writes TZ to .env if a valid IANA timezone is resolved.
|
|
* Emits NEEDS_USER_INPUT=true when autodetection fails.
|
|
*/
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
import { isValidTimezone } from '../src/timezone.js';
|
|
import { log } from '../src/log.js';
|
|
import { emitStatus } from './status.js';
|
|
|
|
export async function run(args: string[]): Promise<void> {
|
|
const projectRoot = process.cwd();
|
|
const envFile = path.join(projectRoot, '.env');
|
|
|
|
// Check what's already in .env
|
|
let envFileTz: string | undefined;
|
|
if (fs.existsSync(envFile)) {
|
|
const content = fs.readFileSync(envFile, 'utf-8');
|
|
const match = content.match(/^TZ=(.+)$/m);
|
|
if (match) envFileTz = match[1].trim().replace(/^["']|["']$/g, '');
|
|
}
|
|
|
|
const systemTz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
const envTz = process.env.TZ;
|
|
|
|
// Accept --tz flag from CLI (used when setup skill collects from user)
|
|
const tzFlagIdx = args.indexOf('--tz');
|
|
const userTz = tzFlagIdx !== -1 ? args[tzFlagIdx + 1] : undefined;
|
|
|
|
// Resolve: user-provided > .env > process.env > system autodetect
|
|
let resolvedTz: string | undefined;
|
|
for (const candidate of [userTz, envFileTz, envTz, systemTz]) {
|
|
if (candidate && isValidTimezone(candidate)) {
|
|
resolvedTz = candidate;
|
|
break;
|
|
}
|
|
}
|
|
|
|
const needsUserInput = !resolvedTz;
|
|
|
|
if (resolvedTz && resolvedTz !== envFileTz) {
|
|
// Write/update TZ in .env
|
|
if (fs.existsSync(envFile)) {
|
|
let content = fs.readFileSync(envFile, 'utf-8');
|
|
if (/^TZ=/m.test(content)) {
|
|
content = content.replace(/^TZ=.*$/m, `TZ=${resolvedTz}`);
|
|
} else {
|
|
content = content.trimEnd() + `\nTZ=${resolvedTz}\n`;
|
|
}
|
|
fs.writeFileSync(envFile, content);
|
|
} else {
|
|
fs.writeFileSync(envFile, `TZ=${resolvedTz}\n`);
|
|
}
|
|
log.info('Set TZ in .env', { timezone: resolvedTz });
|
|
}
|
|
|
|
emitStatus('TIMEZONE', {
|
|
SYSTEM_TZ: systemTz || 'unknown',
|
|
ENV_TZ: envTz || 'unset',
|
|
ENV_FILE_TZ: envFileTz || 'unset',
|
|
RESOLVED_TZ: resolvedTz || 'none',
|
|
NEEDS_USER_INPUT: needsUserInput,
|
|
STATUS: needsUserInput ? 'needs_input' : 'success',
|
|
});
|
|
}
|