@aion0/forge 0.1.9 → 0.2.0
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.
- package/CLAUDE.md +44 -0
- package/app/api/code/route.ts +160 -0
- package/app/api/docs/route.ts +85 -0
- package/app/api/docs/sessions/route.ts +54 -0
- package/app/api/terminal-cwd/route.ts +19 -0
- package/components/CodeViewer.tsx +474 -0
- package/components/Dashboard.tsx +34 -14
- package/components/DocTerminal.tsx +168 -0
- package/components/DocsViewer.tsx +254 -0
- package/components/MarkdownContent.tsx +24 -8
- package/components/SettingsModal.tsx +55 -0
- package/components/WebTerminal.tsx +32 -7
- package/lib/settings.ts +2 -0
- package/lib/telegram-bot.ts +469 -49
- package/lib/terminal-standalone.ts +35 -3
- package/next-env.d.ts +1 -1
- package/package.json +2 -1
|
@@ -28,7 +28,7 @@ import { WebSocketServer, WebSocket } from 'ws';
|
|
|
28
28
|
import * as pty from 'node-pty';
|
|
29
29
|
import { execSync } from 'node:child_process';
|
|
30
30
|
import { homedir } from 'node:os';
|
|
31
|
-
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
31
|
+
import { readFileSync, writeFileSync, mkdirSync, readdirSync } from 'node:fs';
|
|
32
32
|
import { join } from 'node:path';
|
|
33
33
|
|
|
34
34
|
const PORT = Number(process.env.TERMINAL_PORT) || 3001;
|
|
@@ -116,6 +116,19 @@ function listTmuxSessions(): { name: string; created: string; attached: boolean;
|
|
|
116
116
|
|
|
117
117
|
const MAX_SESSIONS = 10;
|
|
118
118
|
|
|
119
|
+
function getDefaultCwd(): string {
|
|
120
|
+
try {
|
|
121
|
+
const settingsPath = join(homedir(), '.forge', 'settings.yaml');
|
|
122
|
+
const raw = readFileSync(settingsPath, 'utf-8');
|
|
123
|
+
const match = raw.match(/projectRoots:\s*\n((?:\s+-\s+.+\n?)*)/);
|
|
124
|
+
if (match) {
|
|
125
|
+
const first = match[1].split('\n').map(l => l.replace(/^\s+-\s+/, '').trim()).filter(Boolean)[0];
|
|
126
|
+
if (first) return first.replace(/^~/, homedir());
|
|
127
|
+
}
|
|
128
|
+
} catch {}
|
|
129
|
+
return homedir();
|
|
130
|
+
}
|
|
131
|
+
|
|
119
132
|
function createTmuxSession(cols: number, rows: number): string {
|
|
120
133
|
// Auto-cleanup: if too many sessions, kill the oldest idle ones
|
|
121
134
|
const existing = listTmuxSessions();
|
|
@@ -132,7 +145,7 @@ function createTmuxSession(cols: number, rows: number): string {
|
|
|
132
145
|
const id = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
|
|
133
146
|
const name = `${SESSION_PREFIX}${id}`;
|
|
134
147
|
execSync(`${TMUX} new-session -d -s ${name} -x ${cols} -y ${rows}`, {
|
|
135
|
-
cwd:
|
|
148
|
+
cwd: getDefaultCwd(),
|
|
136
149
|
env: { ...process.env, TERM: 'xterm-256color' },
|
|
137
150
|
});
|
|
138
151
|
// Enable mouse scrolling and set large scrollback buffer
|
|
@@ -305,7 +318,26 @@ wss.on('connection', (ws: WebSocket) => {
|
|
|
305
318
|
const cols = parsed.cols || 120;
|
|
306
319
|
const rows = parsed.rows || 30;
|
|
307
320
|
try {
|
|
308
|
-
|
|
321
|
+
// Support fixed session name (e.g. mw-docs-claude)
|
|
322
|
+
let name: string;
|
|
323
|
+
if (parsed.sessionName && parsed.sessionName.startsWith(SESSION_PREFIX)) {
|
|
324
|
+
// Create with fixed name if it doesn't exist, otherwise attach
|
|
325
|
+
if (tmuxSessionExists(parsed.sessionName)) {
|
|
326
|
+
attachToTmux(parsed.sessionName, cols, rows);
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
name = parsed.sessionName;
|
|
330
|
+
execSync(`${TMUX} new-session -d -s ${name} -x ${cols} -y ${rows}`, {
|
|
331
|
+
cwd: homedir(),
|
|
332
|
+
env: { ...process.env, TERM: 'xterm-256color' },
|
|
333
|
+
});
|
|
334
|
+
try {
|
|
335
|
+
execSync(`${TMUX} set-option -t ${name} mouse on 2>/dev/null`);
|
|
336
|
+
execSync(`${TMUX} set-option -t ${name} history-limit 50000 2>/dev/null`);
|
|
337
|
+
} catch {}
|
|
338
|
+
} else {
|
|
339
|
+
name = createTmuxSession(cols, rows);
|
|
340
|
+
}
|
|
309
341
|
createdAt.set(ws, { session: name, time: Date.now() });
|
|
310
342
|
attachToTmux(name, cols, rows);
|
|
311
343
|
} catch (e: unknown) {
|
package/next-env.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="next" />
|
|
2
2
|
/// <reference types="next/image-types/global" />
|
|
3
|
-
import "./.next/types/routes.d.ts";
|
|
3
|
+
import "./.next/dev/types/routes.d.ts";
|
|
4
4
|
|
|
5
5
|
// NOTE: This file should not be edited
|
|
6
6
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aion0/forge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"react": "^19.2.4",
|
|
43
43
|
"react-dom": "^19.2.4",
|
|
44
44
|
"react-markdown": "^10.1.0",
|
|
45
|
+
"remark-gfm": "^4.0.1",
|
|
45
46
|
"ws": "^8.19.0",
|
|
46
47
|
"yaml": "^2.8.2"
|
|
47
48
|
},
|