@pixelbyte-software/pixcode 1.48.4 โ†’ 1.48.6

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.
@@ -14,7 +14,6 @@ const settingsMainTabs = read('src/components/settings/view/SettingsMainTabs.tsx
14
14
  const settingsTypes = read('src/components/settings/types/types.ts');
15
15
  const settingsController = read('src/components/settings/hooks/useSettingsController.ts');
16
16
  const app = read('src/App.tsx');
17
- const orchestration = read('src/components/orchestration/OrchestrationPage.tsx');
18
17
  const serverIndex = read('server/index.js');
19
18
  const hermesRoutes = read('server/modules/orchestration/hermes/hermes.routes.ts');
20
19
  const shellTerminal = read('src/components/shell/hooks/useShellTerminal.ts');
@@ -34,19 +33,32 @@ assert.doesNotMatch(appearanceTab, /workbenchLayout|WorkbenchLayoutPreference|on
34
33
 
35
34
  assert.match(workbench, /useState<ActivityPanel>\('projects'\)/, 'Workbench should open on the Projects panel.');
36
35
  assert.match(workbench, /WorkbenchWorkspaceTabs|WORKBENCH_WORKSPACE_TABS_STORAGE_KEY/, 'Workbench should expose persistent top workspace tabs.');
36
+ assert.match(workbench, /workspaceTabStripRef/, 'Workbench workspace tabs should scroll instead of overflowing the viewport.');
37
+ assert.match(workbench, /onToggleCliPanel/, 'Workbench workspace tab bar should expose a right CLI panel collapse toggle.');
37
38
  assert.match(workbench, /WorkspaceTabContextMenu/, 'Workbench workspace tabs should use right-click actions.');
38
39
  assert.doesNotMatch(workbench, /\.\.\.currentTabs\.filter\(\(tab\) => tab\.id !== tabId\)/, 'Workspace selection should not reorder tabs.');
39
40
  assert.match(workbench, /openEditorTabs|activeEditorPath/, 'Workbench editor should keep a Monaco-style tab set.');
41
+ assert.match(workbench, /WORKBENCH_EDITOR_STATE_STORAGE_KEY/, 'Workbench editor should persist open tabs per workspace.');
42
+ assert.match(workbench, /readWorkbenchEditorState/, 'Workbench editor should restore open tabs when switching back to a workspace.');
43
+ assert.doesNotMatch(
44
+ workbench,
45
+ /useEffect\(\(\) => \{\s*setOpenEditorTabs\(\[\]\);\s*setActiveEditorPath\(null\);\s*setSplitEditorFile\(null\);[\s\S]*?\}, \[selectedProject\?\.name\]\);/,
46
+ 'Workbench editor must not clear every open tab when the selected workspace changes.',
47
+ );
40
48
  assert.doesNotMatch(workbench, /<ChatInterface/, 'Right workbench panel should not render the chat composer.');
41
49
  assert.match(workbench, /WorkbenchCliPanel/, 'Right workbench panel should render the CLI terminal panel.');
42
50
  assert.match(workbench, /setIsTerminalOpen\(true\)/, 'CLI picker should give way to a full-height terminal after the user starts a provider.');
43
51
  assert.match(workbench, /onClose=\{closeTerminal\}/, 'Closing the workbench terminal should return to the CLI picker.');
44
52
  assert.match(workbench, /WorkbenchCliPanelToolbar/, 'CLI terminal should keep history and new-session actions visible.');
45
53
  assert.match(workbench, /WORKBENCH_CLI_STATE_STORAGE_KEY/, 'CLI terminal should remember per-project open state across workspace switches.');
54
+ assert.match(workbench, /function WorkbenchBottomTerminal/, 'Terminal activity should render as a bottom plain-shell panel.');
55
+ assert.match(workbench, /isPlainShell/, 'Bottom terminal should open the selected project folder without starting the selected AI CLI.');
56
+ assert.match(workbench, /startHermesAgent/, 'Right CLI panel should launch Hermes Agent in the active project.');
46
57
  assert.match(workbench, /openNewCliSessionPicker/, 'CLI terminal plus should return to provider selection before starting a fresh session.');
47
58
  assert.match(workbench, /terminateCurrentCliSession\(selectedProvider\)/, 'CLI terminal plus should terminate the existing provider PTY before showing selection.');
48
59
  assert.match(workbench, /forceNewSession=\{terminalLaunch\.forceNewSession\}/, 'Fresh CLI sessions should bypass the cached default PTY.');
49
60
  assert.match(serverIndex, /\/api\/shell\/sessions\/terminate/, 'Backend should expose an authenticated endpoint to terminate cached provider PTYs immediately.');
61
+ assert.match(serverIndex, /isPlainShell && !initialCommand/, 'Backend should spawn an interactive plain shell when no terminal command is provided.');
50
62
  assert.doesNotMatch(shellTerminal, /new WebglAddon\(\)/, 'Workbench terminal should use the stable xterm renderer.');
51
63
  assert.match(workbench, /setActivityPanel\('explorer'\)/, 'Selecting a project should return the side panel to Explorer.');
52
64
  assert.match(gitPanelHeader, /compact/, 'Workbench Source Control should have compact icon-only controls.');
@@ -63,8 +75,8 @@ assert.doesNotMatch(settingsMainTabs, /id: 'tasks'/, 'Settings main tabs should
63
75
  assert.doesNotMatch(settingsTypes, /'tasks'/, 'Settings tab type should not include tasks.');
64
76
  assert.doesNotMatch(settingsController, /'tasks'/, 'Settings controller should not treat tasks as a known tab.');
65
77
 
66
- assert.match(orchestration, /Hermes/, 'Orchestration page should present Hermes as the control agent.');
67
- assert.doesNotMatch(orchestration, /A2A|a2a/, 'Orchestration page should not present A2A terminology.');
78
+ assert.doesNotMatch(workbench, /<OrchestrationPage/, 'Workbench should not expose the old orchestration page.');
79
+ assert.doesNotMatch(workbench, /tabs\.orchestration/, 'Workbench menus should not route users into orchestration.');
68
80
  assert.match(serverIndex, /app\.use\('\/hermes', createHermesTaskRouter\(\)\)/, 'Internal task router should be mounted behind Hermes.');
69
81
  assert.doesNotMatch(serverIndex, /app\.use\('\/a2a'/, 'Server should not expose the old A2A route.');
70
82
  assert.match(hermesRoutes, /createHermesRouter/, 'Hermes should have a dedicated orchestration API router.');
@@ -102,12 +102,30 @@ assert.match(
102
102
  'Workspace add button should center its plus icon instead of rendering an off-center bare icon.',
103
103
  );
104
104
 
105
+ assert.match(
106
+ workspaceTabsSource,
107
+ /workspaceTabStripRef/,
108
+ 'Workspace tabs should use a scrollable strip like editor tabs.',
109
+ );
110
+
111
+ assert.match(
112
+ workspaceTabsSource,
113
+ /scrollWorkspaceTabs/,
114
+ 'Workspace tabs should expose left/right scroll controls when the tab row overflows.',
115
+ );
116
+
105
117
  assert.match(
106
118
  workspaceTabsSource,
107
119
  /border-r border-border/,
108
120
  'Workspace add button should read as part of the tab strip instead of a floating bare button.',
109
121
  );
110
122
 
123
+ assert.match(
124
+ workspaceTabsSource,
125
+ /onToggleCliPanel/,
126
+ 'Workspace tab bar should expose a right-panel toggle at the end of the strip.',
127
+ );
128
+
111
129
  assert.match(
112
130
  workbench,
113
131
  /WORKBENCH_WORKSPACE_TABS_STORAGE_KEY/,
@@ -126,6 +144,18 @@ assert.match(
126
144
  'Editor tabs should have a scrollable strip instead of shrinking every tab.',
127
145
  );
128
146
 
147
+ assert.match(
148
+ workbench,
149
+ /WORKBENCH_EDITOR_STATE_STORAGE_KEY/,
150
+ 'Editor tabs should keep separate persisted state for each workspace.',
151
+ );
152
+
153
+ assert.doesNotMatch(
154
+ workbench,
155
+ /useEffect\(\(\) => \{\s*setOpenEditorTabs\(\[\]\);\s*setActiveEditorPath\(null\);\s*setSplitEditorFile\(null\);[\s\S]*?\}, \[selectedProject\?\.name\]\);/,
156
+ 'Editor tabs should not be wiped by the selected-project change effect.',
157
+ );
158
+
129
159
  assert.match(
130
160
  workbench,
131
161
  /handleEditorTabContextMenu/,
@@ -208,6 +238,24 @@ assert.match(
208
238
  'Right CLI terminal should keep compact History and New Session actions visible while the terminal is open.',
209
239
  );
210
240
 
241
+ assert.match(
242
+ workbench,
243
+ /function WorkbenchBottomTerminal/,
244
+ 'Terminal activity should open a VS Code-style bottom terminal instead of the provider CLI picker.',
245
+ );
246
+
247
+ assert.match(
248
+ workbench,
249
+ /isPlainShell/,
250
+ 'Workbench bottom terminal should run a plain shell in the selected project directory.',
251
+ );
252
+
253
+ assert.match(
254
+ workbench,
255
+ /startHermesAgent/,
256
+ 'Right CLI panel should offer Hermes Agent as a project-scoped control agent.',
257
+ );
258
+
211
259
  assert.match(
212
260
  workbench,
213
261
  /onNewSession=\{openNewCliSessionPicker\}/,
package/server/index.js CHANGED
@@ -2092,7 +2092,7 @@ function handleShellConnection(ws) {
2092
2092
  const provider = data.provider || 'claude';
2093
2093
  const initialCommand = data.initialCommand;
2094
2094
  const isPlainShell = data.isPlainShell || (!!initialCommand && !hasSession) || provider === 'plain-shell';
2095
- const forceNewSession = Boolean(data.forceNewSession && !isPlainShell);
2095
+ const forceNewSession = Boolean(data.forceNewSession);
2096
2096
  urlDetectionBuffer = '';
2097
2097
  announcedAuthUrls.clear();
2098
2098
 
@@ -2129,9 +2129,16 @@ function handleShellConnection(ws) {
2129
2129
  terminatePtySession(ptySessionKey, oldSession, 'fresh login');
2130
2130
  }
2131
2131
  } else if (forceNewSession) {
2132
- const killedSessions = killProviderPtySessions(projectPath, provider);
2133
- if (killedSessions > 0) {
2134
- console.log(`๐Ÿงน Fresh ${provider} session requested; terminated ${killedSessions} cached PTY session(s).`);
2132
+ if (isPlainShell) {
2133
+ const oldSession = ptySessionsMap.get(ptySessionKey);
2134
+ if (oldSession) {
2135
+ terminatePtySession(ptySessionKey, oldSession, 'fresh plain shell session');
2136
+ }
2137
+ } else {
2138
+ const killedSessions = killProviderPtySessions(projectPath, provider);
2139
+ if (killedSessions > 0) {
2140
+ console.log(`๐Ÿงน Fresh ${provider} session requested; terminated ${killedSessions} cached PTY session(s).`);
2141
+ }
2135
2142
  }
2136
2143
  }
2137
2144
 
@@ -2213,8 +2220,8 @@ function handleShellConnection(ws) {
2213
2220
  // Build shell command โ€” use cwd for project path (never interpolate into shell string)
2214
2221
  let shellCommand;
2215
2222
  if (isPlainShell) {
2216
- // Plain shell mode - run the initial command in the project directory
2217
- shellCommand = initialCommand;
2223
+ // Plain shell mode without an initial command must stay interactive.
2224
+ shellCommand = initialCommand || null;
2218
2225
  } else if (provider === 'cursor') {
2219
2226
  if (hasSession && sessionId) {
2220
2227
  shellCommand = `cursor-agent --resume="${sessionId}"`;
@@ -2311,11 +2318,13 @@ function handleShellConnection(ws) {
2311
2318
  }
2312
2319
  }
2313
2320
 
2314
- console.log('๐Ÿ”ง Executing shell command:', shellCommand);
2321
+ console.log('๐Ÿ”ง Executing shell command:', shellCommand || 'interactive shell');
2315
2322
 
2316
2323
  // Use appropriate shell based on platform
2317
2324
  const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash';
2318
- const shellArgs = os.platform() === 'win32' ? ['-Command', shellCommand] : ['-c', shellCommand];
2325
+ const shellArgs = isPlainShell && !initialCommand
2326
+ ? (os.platform() === 'win32' ? ['-NoLogo'] : ['-l'])
2327
+ : (os.platform() === 'win32' ? ['-Command', shellCommand] : ['-c', shellCommand]);
2319
2328
 
2320
2329
  // Use terminal dimensions from client if provided, otherwise use defaults
2321
2330
  const termCols = data.cols || 80;