@aion0/forge 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,7 @@ export default function LoginPage() {
12
12
 
13
13
  useEffect(() => {
14
14
  const host = window.location.hostname;
15
- setIsRemote(!['localhost', '127.0.0.1'].includes(host));
15
+ setIsRemote(host.endsWith('.trycloudflare.com'));
16
16
  // Restore theme
17
17
  const saved = localStorage.getItem('forge-theme');
18
18
  if (saved === 'light') document.documentElement.setAttribute('data-theme', 'light');
@@ -70,6 +70,40 @@ const PID_FILE = join(DATA_DIR, 'forge.pid');
70
70
  const LOG_FILE = join(DATA_DIR, 'forge.log');
71
71
 
72
72
  process.chdir(ROOT);
73
+
74
+ // ── Migrate old layout (~/.forge/*) to new (~/.forge/data/*) ──
75
+ if (!getArg('--dir')) {
76
+ const oldSettings = join(homedir(), '.forge', 'settings.yaml');
77
+ const newSettings = join(DATA_DIR, 'settings.yaml');
78
+ if (existsSync(oldSettings) && !existsSync(newSettings)) {
79
+ console.log('[forge] Migrating data from ~/.forge/ to ~/.forge/data/...');
80
+ mkdirSync(DATA_DIR, { recursive: true });
81
+ const migrateFiles = ['settings.yaml', '.encrypt-key', '.env.local', 'session-code.json', 'terminal-state.json', 'tunnel-state.json', 'preview.json', 'forge.pid', 'forge.log'];
82
+ for (const f of migrateFiles) {
83
+ const src = join(homedir(), '.forge', f);
84
+ const dest = join(DATA_DIR, f);
85
+ if (existsSync(src) && !existsSync(dest)) {
86
+ try { const { copyFileSync } = await import('node:fs'); copyFileSync(src, dest); console.log(` ${f}`); } catch {}
87
+ }
88
+ }
89
+ // data.db → workflow.db
90
+ const oldDb = join(homedir(), '.forge', 'data.db');
91
+ const newDb = join(DATA_DIR, 'workflow.db');
92
+ if (existsSync(oldDb) && !existsSync(newDb)) {
93
+ try { const { copyFileSync } = await import('node:fs'); copyFileSync(oldDb, newDb); console.log(' data.db → workflow.db'); } catch {}
94
+ }
95
+ // Migrate directories
96
+ for (const d of ['flows', 'pipelines']) {
97
+ const src = join(homedir(), '.forge', d);
98
+ const dest = join(DATA_DIR, d);
99
+ if (existsSync(src) && !existsSync(dest)) {
100
+ try { const { renameSync } = await import('node:fs'); renameSync(src, dest); console.log(` ${d}/`); } catch {}
101
+ }
102
+ }
103
+ console.log('[forge] Migration complete.');
104
+ }
105
+ }
106
+
73
107
  mkdirSync(DATA_DIR, { recursive: true });
74
108
 
75
109
  // ── Load <data-dir>/.env.local ──
package/lib/dirs.ts CHANGED
@@ -9,6 +9,7 @@
9
9
 
10
10
  import { homedir } from 'node:os';
11
11
  import { join } from 'node:path';
12
+ import { existsSync, mkdirSync, renameSync, copyFileSync } from 'node:fs';
12
13
 
13
14
  /** Shared config directory — only binaries, fixed at ~/.forge/ */
14
15
  export function getConfigDir(): string {
@@ -20,6 +21,70 @@ export function getDataDir(): string {
20
21
  return process.env.FORGE_DATA_DIR || join(getConfigDir(), 'data');
21
22
  }
22
23
 
24
+ // ─── Migration from old layout (~/.forge/*) to new (~/.forge/data/*) ───
25
+
26
+ const MIGRATE_FILES = [
27
+ 'settings.yaml',
28
+ '.encrypt-key',
29
+ '.env.local',
30
+ 'session-code.json',
31
+ 'terminal-state.json',
32
+ 'tunnel-state.json',
33
+ 'preview.json',
34
+ 'forge.pid',
35
+ 'forge.log',
36
+ ];
37
+ const MIGRATE_DIRS = ['flows', 'pipelines'];
38
+
39
+ let migrated = false;
40
+
41
+ /** Migrate old ~/.forge/ flat layout to ~/.forge/data/ if needed */
42
+ export function migrateDataDir(): void {
43
+ if (migrated) return;
44
+ migrated = true;
45
+
46
+ // Only migrate default data dir, not custom --dir
47
+ if (process.env.FORGE_DATA_DIR) return;
48
+
49
+ const configDir = getConfigDir();
50
+ const dataDir = join(configDir, 'data');
51
+
52
+ // Check if old layout exists (settings.yaml in root, not in data/)
53
+ const oldSettings = join(configDir, 'settings.yaml');
54
+ const newSettings = join(dataDir, 'settings.yaml');
55
+ if (!existsSync(oldSettings) || existsSync(newSettings)) return;
56
+
57
+ console.log('[forge] Migrating data from ~/.forge/ to ~/.forge/data/...');
58
+ if (!existsSync(dataDir)) mkdirSync(dataDir, { recursive: true });
59
+
60
+ // Migrate files
61
+ for (const file of MIGRATE_FILES) {
62
+ const src = join(configDir, file);
63
+ const dest = join(dataDir, file);
64
+ if (existsSync(src) && !existsSync(dest)) {
65
+ try { copyFileSync(src, dest); console.log(` ${file}`); } catch {}
66
+ }
67
+ }
68
+
69
+ // Migrate old data.db → data/workflow.db
70
+ const oldDb = join(configDir, 'data.db');
71
+ const newDb = join(dataDir, 'workflow.db');
72
+ if (existsSync(oldDb) && !existsSync(newDb)) {
73
+ try { copyFileSync(oldDb, newDb); console.log(' data.db → workflow.db'); } catch {}
74
+ }
75
+
76
+ // Migrate directories
77
+ for (const dir of MIGRATE_DIRS) {
78
+ const src = join(configDir, dir);
79
+ const dest = join(dataDir, dir);
80
+ if (existsSync(src) && !existsSync(dest)) {
81
+ try { renameSync(src, dest); console.log(` ${dir}/`); } catch {}
82
+ }
83
+ }
84
+
85
+ console.log('[forge] Migration complete. Old files kept as backup.');
86
+ }
87
+
23
88
  /** Claude Code home directory — skills, commands, sessions */
24
89
  export function getClaudeDir(): string {
25
90
  // Env var takes precedence
package/lib/init.ts CHANGED
@@ -64,6 +64,9 @@ export function ensureInitialized() {
64
64
  if (gInit[initKey]) return;
65
65
  gInit[initKey] = true;
66
66
 
67
+ // Migrate old data layout (~/.forge/* → ~/.forge/data/*) on first run
68
+ try { const { migrateDataDir } = require('./dirs'); migrateDataDir(); } catch {}
69
+
67
70
  // Migrate plaintext secrets on startup
68
71
  migrateSecrets();
69
72
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {