@myrialabs/clopen 0.2.12 → 0.2.13

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.
@@ -43,16 +43,14 @@ class ChatService {
43
43
 
44
44
  static loadingTexts: string[] = [
45
45
  'thinking', 'processing', 'analyzing', 'calculating', 'computing',
46
- 'strategizing', 'learningpatterns', 'updatingweights', 'finetuning',
47
- 'adaptingmodels', 'trainingnetworks', 'evaluatingoptions', 'planningactions',
48
- 'executingplans', 'simulatingscenarios', 'predictingoutcomes', 'scanningenvironment',
49
- 'monitoringsignals', 'processinginputs', 'adjustingparameters', 'optimizing',
50
- 'generatingresponses', 'refininglogic', 'recognizingpatterns', 'synthesizinginformation',
51
- 'runninginference', 'validatingoutputs', 'modulatingresponse', 'updatingmemory',
52
- 'switchingcontext', 'resolvingconflicts', 'allocatingresources', 'prioritizingtasks',
53
- 'developingawareness', 'buildingstrategies', 'assessingscenarios', 'integratingdata',
54
- 'bootingreasoning', 'activatingmodules', 'triggeringaction', 'deployinglogic',
55
- 'maintainingstate', 'clearingcache', 'updating', 'reflecting', 'syncinglogic',
46
+ 'strategizing', 'learningpatterns', 'adaptingmodels', 'evaluatingoptions',
47
+ 'executingplans', 'simulatingscenarios', 'predictingoutcomes', 'planningactions',
48
+ 'processinginputs', 'optimizing', 'generatingresponses', 'refininglogic',
49
+ 'validatingoutputs', 'modulatingresponse', 'updatingmemory', 'recognizingpatterns',
50
+ 'switchingcontext', 'allocatingresources', 'prioritizingtasks',
51
+ 'developingawareness', 'buildingstrategies', 'assessingscenarios',
52
+ 'bootingreasoning', 'triggeringaction', 'deployinglogic', 'synthesizinginformation',
53
+ 'maintainingstate', 'updating', 'reflecting', 'syncinglogic',
56
54
  'connectingdots', 'compilingideas', 'brainstorming', 'schedulingtasks'
57
55
  ].map(text => text + '...');
58
56
 
@@ -262,66 +262,10 @@ class TerminalProjectManager {
262
262
  }
263
263
  }
264
264
 
265
- // Restore saved output for this session
266
- let baseOutput: any[] = [];
267
- let backgroundOutput: any[] = [];
268
-
269
- // First, restore base output from context (input/output sebelumnya)
270
- if (context.sessionOutputs.has(sessionId)) {
271
- const savedOutput = context.sessionOutputs.get(sessionId);
272
- if (savedOutput) {
273
- baseOutput = savedOutput.map(output => ({
274
- content: output.content,
275
- type: output.type as any,
276
- timestamp: output.timestamp
277
- }));
278
- // Restored base output lines for session
279
- }
280
- }
281
-
282
- // Second, get NEW output from server that was generated while we were away
283
- // We need to track when we saved the output to know what's new
284
- if (hasActiveStream && activeStreamInfo) {
285
- try {
286
- // Get the saved output count from context metadata
287
- // This tells us how much output we had when we switched away
288
- let savedOutputCount = 0;
289
- const savedMetadata = context.sessionOutputs.get(`${sessionId}-metadata`);
290
- if (savedMetadata && typeof savedMetadata === 'object' && 'outputCount' in savedMetadata) {
291
- savedOutputCount = (savedMetadata as any).outputCount || 0;
292
- } else {
293
- // Fallback: count actual output lines in baseOutput
294
- for (const line of baseOutput) {
295
- if (line.type === 'output' || line.type === 'error') {
296
- savedOutputCount++;
297
- }
298
- }
299
- }
300
-
301
- // Get only NEW output from server (skip what we already have)
302
- const data = await terminalService.getMissedOutput(
303
- sessionId,
304
- activeStreamInfo.streamId,
305
- savedOutputCount
306
- );
307
- if (data.success && data.output && data.output.length > 0) {
308
- // Convert server output to terminal lines
309
- backgroundOutput = data.output.map((content: string) => ({
310
- content: content,
311
- type: 'output',
312
- timestamp: new Date()
313
- }));
314
- debug.log('terminal', `Restored ${backgroundOutput.length} new output lines for session ${sessionId}`);
315
- }
316
- } catch (error) {
317
- debug.error('terminal', 'Failed to fetch missed output:', error);
318
- }
319
- }
320
-
321
- // Combine base output with background output from server
322
- // Base output contains previous input/output saved in context
323
- // Background output contains new output from server (if any)
324
- terminalSession.lines = [...baseOutput, ...backgroundOutput];
265
+ // Always start with empty lines.
266
+ // The create-session replay from headless xterm will provide the
267
+ // accurate current terminal state (respects clear, scrollback, etc.)
268
+ terminalSession.lines = [];
325
269
 
326
270
  // Restore command history from context (persisted) rather than manager (temporary)
327
271
  const savedCommandHistory = context.sessionCommandHistories.get(sessionId);
@@ -62,20 +62,6 @@ export class TerminalService {
62
62
  // Create unique stream ID for this connection
63
63
  const streamId = `${sessionId}-${Date.now()}`;
64
64
 
65
- // Get current output count to mark where new output starts
66
- let outputStartIndex = 0;
67
- if (typeof window !== 'undefined') {
68
- try {
69
- const terminalStoreModule = await import('$frontend/stores/features/terminal.svelte');
70
- const termSession = terminalStoreModule.terminalStore.getSession(sessionId);
71
- if (termSession && termSession.lines) {
72
- outputStartIndex = termSession.lines.length;
73
- }
74
- } catch {
75
- // Ignore error, use default 0
76
- }
77
- }
78
-
79
65
  // Setup WebSocket listeners for this session
80
66
  const listeners: Array<() => void> = [];
81
67
 
@@ -173,8 +159,7 @@ export class TerminalService {
173
159
  workingDirectory: session.workingDirectory,
174
160
  projectPath,
175
161
  cols: terminalSize?.cols || 80,
176
- rows: terminalSize?.rows || 24,
177
- outputStartIndex
162
+ rows: terminalSize?.rows || 24
178
163
  });
179
164
 
180
165
  debug.log('terminal', `✅ Terminal session created:`, response);
@@ -230,6 +215,17 @@ export class TerminalService {
230
215
  }
231
216
  }
232
217
 
218
+ /**
219
+ * Clear headless terminal on backend (sync with frontend clear)
220
+ */
221
+ async clearHeadlessTerminal(sessionId: string): Promise<void> {
222
+ try {
223
+ await ws.http('terminal:clear', { sessionId });
224
+ } catch {
225
+ // Silently handle - non-critical
226
+ }
227
+ }
228
+
233
229
  /**
234
230
  * Resize terminal for a specific session
235
231
  */
@@ -301,39 +297,34 @@ export class TerminalService {
301
297
  }
302
298
 
303
299
  /**
304
- * Get missed output for a session
300
+ * Get missed output for a session (serialized terminal state)
305
301
  */
306
302
  async getMissedOutput(
307
303
  sessionId: string,
308
- streamId?: string,
309
- fromIndex: number = 0
304
+ streamId?: string
310
305
  ): Promise<{
311
306
  success: boolean;
312
- output: string[];
313
- outputCount: number;
307
+ output: string;
314
308
  status: string;
315
309
  }> {
316
310
  try {
317
- const data = await ws.http('terminal:missed-output', { sessionId, streamId, fromIndex }, 5000);
311
+ const data = await ws.http('terminal:missed-output', { sessionId, streamId }, 5000);
318
312
  if (data.sessionId === sessionId) {
319
313
  return {
320
314
  success: true,
321
315
  output: data.output,
322
- outputCount: data.outputCount,
323
316
  status: data.status
324
317
  };
325
318
  }
326
319
  return {
327
320
  success: false,
328
- output: [],
329
- outputCount: 0,
321
+ output: '',
330
322
  status: 'invalid_session'
331
323
  };
332
324
  } catch {
333
325
  return {
334
326
  success: false,
335
- output: [],
336
- outputCount: 0,
327
+ output: '',
337
328
  status: 'timeout'
338
329
  };
339
330
  }
@@ -436,6 +436,12 @@ export async function initializeSessions() {
436
436
  setupCollaborativeListeners();
437
437
  setupEditModeListener();
438
438
 
439
+ // Skip loading if no project is active — both calls require WS project context
440
+ if (!projectState.currentProject) {
441
+ debug.log('session', 'No active project, skipping session load');
442
+ return;
443
+ }
444
+
439
445
  // Load sessions and restore edit mode in parallel
440
446
  // Both only need WS project context (already set by initializeProjects)
441
447
  await Promise.all([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myrialabs/clopen",
3
- "version": "0.2.12",
3
+ "version": "0.2.13",
4
4
  "description": "All-in-one web workspace for Claude Code & OpenCode — chat, terminal, git, browser preview, checkpoints, and real-time collaboration",
5
5
  "author": "Myria Labs",
6
6
  "license": "MIT",
@@ -77,17 +77,19 @@
77
77
  "dependencies": {
78
78
  "@anthropic-ai/claude-agent-sdk": "0.2.63",
79
79
  "@anthropic-ai/sdk": "0.78.0",
80
- "@opencode-ai/sdk": "1.2.15",
81
80
  "@elysiajs/cors": "^1.4.0",
82
81
  "@iconify-json/lucide": "^1.2.57",
83
82
  "@iconify-json/material-icon-theme": "^1.2.16",
84
83
  "@modelcontextprotocol/sdk": "^1.26.0",
85
84
  "@monaco-editor/loader": "^1.5.0",
85
+ "@opencode-ai/sdk": "1.2.15",
86
86
  "@xterm/addon-clipboard": "^0.2.0",
87
87
  "@xterm/addon-fit": "^0.11.0",
88
88
  "@xterm/addon-ligatures": "^0.10.0",
89
+ "@xterm/addon-serialize": "^0.14.0",
89
90
  "@xterm/addon-unicode11": "^0.9.0",
90
91
  "@xterm/addon-web-links": "^0.12.0",
92
+ "@xterm/headless": "^6.0.0",
91
93
  "@xterm/xterm": "^6.0.0",
92
94
  "bun-pty": "^0.4.2",
93
95
  "cloudflared": "^0.7.1",