@myrialabs/clopen 0.0.8 → 0.1.1

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.
Files changed (49) hide show
  1. package/backend/index.ts +9 -0
  2. package/backend/lib/chat/stream-manager.ts +130 -10
  3. package/backend/lib/database/queries/message-queries.ts +47 -0
  4. package/backend/lib/engine/adapters/claude/stream.ts +65 -1
  5. package/backend/lib/engine/adapters/opencode/message-converter.ts +35 -77
  6. package/backend/lib/engine/types.ts +6 -0
  7. package/backend/lib/files/file-operations.ts +2 -2
  8. package/backend/lib/files/file-reading.ts +2 -2
  9. package/backend/lib/files/path-browsing.ts +2 -2
  10. package/backend/lib/terminal/pty-session-manager.ts +1 -1
  11. package/backend/lib/terminal/shell-utils.ts +4 -4
  12. package/backend/ws/chat/background.ts +3 -0
  13. package/backend/ws/chat/stream.ts +43 -1
  14. package/bin/clopen.ts +10 -0
  15. package/bun.lock +259 -381
  16. package/frontend/lib/components/chat/ChatInterface.svelte +8 -1
  17. package/frontend/lib/components/chat/formatters/MessageFormatter.svelte +20 -0
  18. package/frontend/lib/components/chat/formatters/TextMessage.svelte +3 -15
  19. package/frontend/lib/components/chat/formatters/Tools.svelte +15 -8
  20. package/frontend/lib/components/chat/input/ChatInput.svelte +70 -21
  21. package/frontend/lib/components/chat/input/components/LoadingIndicator.svelte +23 -11
  22. package/frontend/lib/components/chat/input/composables/use-chat-actions.svelte.ts +1 -1
  23. package/frontend/lib/components/chat/message/ChatMessage.svelte +13 -1
  24. package/frontend/lib/components/chat/message/ChatMessages.svelte +2 -2
  25. package/frontend/lib/components/chat/message/DateSeparator.svelte +1 -1
  26. package/frontend/lib/components/chat/message/MessageBubble.svelte +2 -2
  27. package/frontend/lib/components/chat/message/MessageHeader.svelte +14 -12
  28. package/frontend/lib/components/chat/tools/AgentTool.svelte +95 -0
  29. package/frontend/lib/components/chat/tools/AskUserQuestionTool.svelte +396 -0
  30. package/frontend/lib/components/chat/tools/BashTool.svelte +9 -4
  31. package/frontend/lib/components/chat/tools/EnterPlanModeTool.svelte +24 -0
  32. package/frontend/lib/components/chat/tools/ExitPlanModeTool.svelte +4 -7
  33. package/frontend/lib/components/chat/tools/{KillShellTool.svelte → TaskStopTool.svelte} +6 -6
  34. package/frontend/lib/components/chat/tools/index.ts +5 -2
  35. package/frontend/lib/components/checkpoint/TimelineModal.svelte +7 -2
  36. package/frontend/lib/components/history/HistoryModal.svelte +13 -5
  37. package/frontend/lib/components/workspace/DesktopNavigator.svelte +2 -1
  38. package/frontend/lib/components/workspace/MobileNavigator.svelte +2 -1
  39. package/frontend/lib/services/chat/chat.service.ts +146 -12
  40. package/frontend/lib/stores/core/app.svelte.ts +77 -0
  41. package/frontend/lib/utils/chat/message-grouper.ts +94 -12
  42. package/frontend/lib/utils/chat/message-processor.ts +37 -4
  43. package/frontend/lib/utils/chat/tool-handler.ts +96 -5
  44. package/package.json +4 -4
  45. package/shared/constants/engines.ts +1 -1
  46. package/shared/types/database/schema.ts +1 -0
  47. package/shared/types/messaging/index.ts +15 -13
  48. package/shared/types/messaging/tool.ts +185 -361
  49. package/shared/utils/message-formatter.ts +1 -0
@@ -82,6 +82,7 @@ export const backgroundHandler = createRouter()
82
82
  processId: t.String(),
83
83
  messages: t.Array(t.Any()),
84
84
  currentPartialText: t.Optional(t.String()),
85
+ currentReasoningText: t.Optional(t.String()),
85
86
  error: t.Optional(t.String()),
86
87
  startedAt: t.String(),
87
88
  completedAt: t.Optional(t.String())
@@ -106,6 +107,7 @@ export const backgroundHandler = createRouter()
106
107
  processId: '',
107
108
  messages: [],
108
109
  currentPartialText: undefined,
110
+ currentReasoningText: undefined,
109
111
  error: undefined,
110
112
  startedAt: new Date().toISOString(),
111
113
  completedAt: new Date().toISOString()
@@ -122,6 +124,7 @@ export const backgroundHandler = createRouter()
122
124
  processId: streamState.processId,
123
125
  messages,
124
126
  currentPartialText: streamState.currentPartialText,
127
+ currentReasoningText: streamState.currentReasoningText,
125
128
  error: streamState.error,
126
129
  startedAt: streamState.startedAt.toISOString(),
127
130
  completedAt: streamState.completedAt?.toISOString()
@@ -13,7 +13,7 @@ import { streamManager, type StreamEvent } from '../../lib/chat/stream-manager';
13
13
  import { debug } from '$shared/utils/logger';
14
14
  import { ws } from '$backend/lib/utils/ws';
15
15
  import { broadcastPresence } from '../projects/status';
16
- import { sessionQueries } from '../../lib/database/queries';
16
+ import { sessionQueries, messageQueries } from '../../lib/database/queries';
17
17
 
18
18
  // ============================================================================
19
19
  // Global stream lifecycle handler (module-level, not per-connection)
@@ -28,6 +28,15 @@ streamManager.on('stream:lifecycle', (event: { status: string; streamId: string;
28
28
 
29
29
  debug.log('chat', `Stream lifecycle: ${status} for project ${projectId} session ${chatSessionId}`);
30
30
 
31
+ // Mark any tool_use blocks that never got a tool_result as interrupted (persisted to DB)
32
+ if (chatSessionId) {
33
+ try {
34
+ messageQueries.markInterruptedMessages(chatSessionId);
35
+ } catch (err) {
36
+ debug.error('chat', 'Failed to mark interrupted messages:', err);
37
+ }
38
+ }
39
+
31
40
  // Notify all project members (cross-project notification for sound + push)
32
41
  ws.emit.projectMembers(projectId, 'chat:stream-finished', {
33
42
  projectId,
@@ -360,6 +369,39 @@ export const streamHandler = createRouter()
360
369
  }
361
370
  })
362
371
 
372
+ // Handle AskUserQuestion answer from user
373
+ .on('chat:ask-user-answer', {
374
+ data: t.Object({
375
+ chatSessionId: t.String(),
376
+ toolUseId: t.String(),
377
+ answers: t.Record(t.String(), t.String())
378
+ })
379
+ }, async ({ data, conn }) => {
380
+ const projectId = ws.getProjectId(conn);
381
+
382
+ try {
383
+ debug.log('chat', 'WS chat:ask-user-answer received:', {
384
+ chatSessionId: data.chatSessionId,
385
+ toolUseId: data.toolUseId,
386
+ answers: data.answers
387
+ });
388
+
389
+ const success = streamManager.resolveUserAnswer(
390
+ data.chatSessionId,
391
+ projectId,
392
+ data.toolUseId,
393
+ data.answers
394
+ );
395
+
396
+ if (!success) {
397
+ debug.warn('chat', 'Failed to resolve user answer for stream');
398
+ }
399
+ } catch (error) {
400
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
401
+ debug.error('chat', 'WS chat:ask-user-answer error:', errorMessage);
402
+ }
403
+ })
404
+
363
405
  // Cancel stream
364
406
  .on('chat:cancel', {
365
407
  data: t.Object({
package/bin/clopen.ts CHANGED
@@ -1,5 +1,15 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
+ // Runtime guard — Bun only, reject Node.js and Deno
4
+ if (typeof globalThis.Bun === 'undefined') {
5
+ console.error('\x1b[31mError: Clopen requires Bun runtime.\x1b[0m');
6
+ console.error('Node.js and Deno are not supported.');
7
+ console.error('');
8
+ console.error('Install Bun: https://bun.sh');
9
+ console.error('Then run: bun clopen');
10
+ process.exit(1);
11
+ }
12
+
3
13
  /**
4
14
  * Clopen CLI Entry Point
5
15
  *