@aion0/forge 0.2.27 → 0.2.28

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.
@@ -506,7 +506,17 @@ const WebTerminal = forwardRef<WebTerminalHandle, WebTerminalProps>(function Web
506
506
  </div>
507
507
  ))}
508
508
  <button
509
- onClick={() => setShowNewTabModal(true)}
509
+ onClick={() => {
510
+ setShowNewTabModal(true);
511
+ // Refresh projects list when opening modal
512
+ fetch('/api/projects').then(r => r.json())
513
+ .then((p: { name: string; path: string; root: string }[]) => {
514
+ if (!Array.isArray(p)) return;
515
+ setAllProjects(p);
516
+ setProjectRoots([...new Set(p.map(proj => proj.root))]);
517
+ })
518
+ .catch(() => {});
519
+ }}
510
520
  className="px-2 py-1 text-[11px] text-gray-500 hover:text-white hover:bg-[var(--term-border)]"
511
521
  title="New tab"
512
522
  >
@@ -690,7 +700,25 @@ const WebTerminal = forwardRef<WebTerminalHandle, WebTerminalProps>(function Web
690
700
  {rootProjects.map(p => (
691
701
  <button
692
702
  key={p.path}
693
- onClick={() => { addTab(p.path); setShowNewTabModal(false); setExpandedRoot(null); }}
703
+ onClick={async () => {
704
+ setShowNewTabModal(false); setExpandedRoot(null);
705
+ // Pre-check sessions before creating tab
706
+ let hasSession = false;
707
+ try {
708
+ const sRes = await fetch(`/api/claude-sessions/${encodeURIComponent(p.name)}`);
709
+ const sData = await sRes.json();
710
+ hasSession = Array.isArray(sData) ? sData.length > 0 : (Array.isArray(sData.sessions) && sData.sessions.length > 0);
711
+ } catch {}
712
+ const skipFlag = skipPermissions ? ' --dangerously-skip-permissions' : '';
713
+ const resumeFlag = hasSession ? ' --resume' : '';
714
+ const tree = makeTerminal(undefined, p.path);
715
+ const paneId = firstTerminalId(tree);
716
+ pendingCommands.set(paneId, `cd "${p.path}" && claude${resumeFlag}${skipFlag}\n`);
717
+ const tabNum = tabs.length + 1;
718
+ const newTab: TabState = { id: nextId++, label: p.name || `Terminal ${tabNum}`, tree, ratios: {}, activeId: paneId, projectPath: p.path };
719
+ setTabs(prev => [...prev, newTab]);
720
+ setActiveTabId(newTab.id);
721
+ }}
694
722
  className="w-full text-left px-3 py-1.5 rounded hover:bg-[var(--term-border)] text-[11px] text-gray-300 flex items-center gap-2 truncate"
695
723
  title={p.path}
696
724
  >
@@ -1090,13 +1118,13 @@ const MemoTerminalPane = memo(function TerminalPane({
1090
1118
  createRetries = 0;
1091
1119
  reconnectAttempts = 0;
1092
1120
  onSessionConnected(id, msg.sessionName);
1093
- // Auto-run claude --resume for project tabs on new session
1094
- if (isNewlyCreated && projectPathRef.current) {
1121
+ // Auto-run claude for project tabs (only if no pendingCommand already set)
1122
+ if (isNewlyCreated && projectPathRef.current && !pendingCommands.has(id)) {
1095
1123
  isNewlyCreated = false;
1096
1124
  setTimeout(() => {
1097
1125
  if (!disposed && ws?.readyState === WebSocket.OPEN) {
1098
1126
  const skipFlag = skipPermRef.current ? ' --dangerously-skip-permissions' : '';
1099
- ws.send(JSON.stringify({ type: 'input', data: `cd "${projectPathRef.current}" && claude --resume${skipFlag}\n` }));
1127
+ ws.send(JSON.stringify({ type: 'input', data: `cd "${projectPathRef.current}" && claude${skipFlag}\n` }));
1100
1128
  }
1101
1129
  }, 300);
1102
1130
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aion0/forge",
3
- "version": "0.2.27",
3
+ "version": "0.2.28",
4
4
  "description": "Unified AI workflow platform — multi-model task orchestration, persistent sessions, web terminal, remote access",
5
5
  "type": "module",
6
6
  "scripts": {