vibecore 0.3.0b1__py3-none-any.whl → 0.3.1__py3-none-any.whl

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.

Potentially problematic release.


This version of vibecore might be problematic. Click here for more details.

@@ -483,6 +483,118 @@ class MCPToolMessage(BaseToolMessage):
483
483
  )
484
484
 
485
485
 
486
+ class RichToolMessage(BaseToolMessage):
487
+ """A widget to display rich (json/markdown) custom tool execution messages."""
488
+
489
+ SQL_QUERY_KEY = "query"
490
+ tool_name: reactive[str] = reactive("")
491
+ arguments: reactive[str] = reactive("")
492
+
493
+ def __init__(
494
+ self,
495
+ tool_name: str,
496
+ arguments: str,
497
+ output: str = "",
498
+ status: MessageStatus = MessageStatus.EXECUTING,
499
+ **kwargs,
500
+ ) -> None:
501
+ """
502
+ Construct an RichToolMessage.
503
+
504
+ Args:
505
+ tool_name: The name of the tool being called.
506
+ arguments: JSON string of tool arguments.
507
+ output: The output from the tool (optional, can be set later).
508
+ status: The status of execution.
509
+ **kwargs: Additional keyword arguments for Widget.
510
+ """
511
+ super().__init__(status=status, **kwargs)
512
+ self.tool_name = tool_name
513
+ self.arguments = arguments
514
+ self.output = output
515
+
516
+ def _prettify_json_output(self, output: str) -> tuple[bool, str]:
517
+ """Try to prettify JSON output.
518
+
519
+ Args:
520
+ output: The raw output string.
521
+
522
+ Returns:
523
+ A tuple of (is_json, formatted_output).
524
+ """
525
+ if not output or not output.strip():
526
+ return False, output
527
+
528
+ try:
529
+ # Try to parse as JSON
530
+ json_obj = json.loads(output)
531
+ # Pretty print with 2-space indentation
532
+ formatted = json.dumps(json_obj, indent=2, ensure_ascii=False)
533
+ return True, formatted
534
+ except (json.JSONDecodeError, TypeError, ValueError):
535
+ # Not valid JSON, return as-is
536
+ return False, output
537
+
538
+ def on_button_pressed(self, event: Button.Pressed) -> None:
539
+ """Handle button press events."""
540
+ if event.button.has_class("copy-button"):
541
+ arg_dict = json.loads(self.arguments)
542
+ if self.SQL_QUERY_KEY in arg_dict:
543
+ # XXX(serialx): Special case for SQL queries
544
+ query = arg_dict[self.SQL_QUERY_KEY]
545
+ self.app.copy_to_clipboard(query)
546
+
547
+ def compose(self) -> ComposeResult:
548
+ """Create child widgets for the rich tool message."""
549
+ # Header line showing MCP server and tool
550
+ # Access the actual values, not the reactive descriptors
551
+ yield MessageHeader("⏺", self.tool_name, status=self.status)
552
+
553
+ # Arguments display (if any)
554
+ if self.arguments and self.arguments != "{}":
555
+ with Horizontal(classes="rich-arguments"):
556
+ yield Static("└─", classes="rich-arguments-prefix")
557
+ with Vertical(classes="rich-arguments-content"):
558
+ # Truncate arguments if too long
559
+ max_args_length = 100
560
+ arg_dict = json.loads(self.arguments)
561
+ if self.SQL_QUERY_KEY in arg_dict:
562
+ # XXX(serialx): Special case for SQL queries
563
+ query = arg_dict[self.SQL_QUERY_KEY]
564
+ yield Button("Copy", classes="copy-button", variant="primary")
565
+ yield ExpandableMarkdown(query, language="sql", truncated_lines=8, classes="rich-output-sql")
566
+ del arg_dict[self.SQL_QUERY_KEY]
567
+
568
+ display_args = arg_dict[:max_args_length] + "…" if len(arg_dict) > max_args_length else arg_dict
569
+ yield Static(f"Args: {display_args}", classes="rich-arguments-text")
570
+
571
+ # Output - check if it's JSON and prettify if so
572
+ if self.output:
573
+ try:
574
+ json_output = json.loads(self.output)
575
+ except json.JSONDecodeError:
576
+ json_output = None
577
+ if json_output:
578
+ assert json_output.get("type") == "text", "Expected JSON output type to be 'text'"
579
+ is_json, processed_output = self._prettify_json_output(json_output.get("text", ""))
580
+ else:
581
+ # output should always be a JSON string, but if not, treat it as plain text
582
+ is_json, processed_output = False, self.output
583
+ with Horizontal(classes="tool-output"):
584
+ yield Static("└─", classes="tool-output-prefix")
585
+ with Vertical(classes="tool-output-content"):
586
+ if is_json:
587
+ # Use ExpandableMarkdown for JSON with syntax highlighting
588
+ yield ExpandableMarkdown(
589
+ processed_output, language="json", truncated_lines=8, classes="rich-output-json"
590
+ )
591
+ else:
592
+ # Use ExpandableMarkdown for non-JSON content (renders as markdown without code block)
593
+ yield ExpandableMarkdown(
594
+ processed_output, language="", truncated_lines=5, classes="rich-output-markdown"
595
+ )
596
+
597
+
486
598
  class WebSearchToolMessage(BaseToolMessage):
487
599
  """A widget to display web search results."""
488
600
 
@@ -288,6 +288,75 @@ MCPToolMessage {
288
288
  }
289
289
  }
290
290
 
291
+ RichToolMessage {
292
+ Horizontal.rich-arguments {
293
+ height: auto;
294
+ layers: main button;
295
+
296
+ .copy-button {
297
+ layer: button;
298
+ dock: right;
299
+ height: 1;
300
+ width: 8;
301
+ min-width: 8;
302
+ margin: 0;
303
+ padding: 0;
304
+ background: $secondary;
305
+ color: $text;
306
+ border: none;
307
+
308
+ &:hover {
309
+ background: $secondary-lighten-1;
310
+ }
311
+
312
+ &:focus {
313
+ background: $secondary-lighten-1;
314
+ text-style: bold;
315
+ }
316
+ }
317
+
318
+ &> .rich-arguments-prefix {
319
+ height: 1;
320
+ width: 5;
321
+ padding-left: 2;
322
+ padding-right: 1;
323
+ color: $text-muted;
324
+ }
325
+
326
+ &> Vertical.rich-arguments-content {
327
+ height: auto;
328
+ width: 1fr;
329
+
330
+ .rich-arguments-label {
331
+ color: $text-muted;
332
+ # margin-bottom: 1;
333
+ }
334
+
335
+ .rich-arguments-text {
336
+ color: $text-muted;
337
+ text-overflow: ellipsis;
338
+ }
339
+ }
340
+ }
341
+
342
+ Horizontal.tool-output {
343
+ height: auto;
344
+
345
+ &> .tool-output-prefix {
346
+ height: 1;
347
+ width: 5;
348
+ padding-left: 2;
349
+ padding-right: 1;
350
+ color: $text-muted;
351
+ }
352
+
353
+ &> Vertical.tool-output-content {
354
+ height: auto;
355
+ width: 1fr;
356
+ }
357
+ }
358
+ }
359
+
291
360
  WebSearchToolMessage {
292
361
  Horizontal.tool-output {
293
362
  height: auto;
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibecore
3
- Version: 0.3.0b1
3
+ Version: 0.3.1
4
4
  Summary: Build your own AI-powered automation tools in the terminal with this extensible agent framework
5
5
  Project-URL: Homepage, https://github.com/serialx/vibecore
6
6
  Project-URL: Repository, https://github.com/serialx/vibecore
@@ -29,6 +29,7 @@ Classifier: Typing :: Typed
29
29
  Requires-Python: >=3.11
30
30
  Requires-Dist: ddgs>=9.5.4
31
31
  Requires-Dist: html2text>=2024.2.26
32
+ Requires-Dist: httpx>=0.24.0
32
33
  Requires-Dist: litellm>=1.72.4
33
34
  Requires-Dist: openai-agents[litellm]>=0.2.2
34
35
  Requires-Dist: pydantic-settings>=2.10.1
@@ -1,21 +1,31 @@
1
1
  vibecore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- vibecore/cli.py,sha256=JspCzt8jlPur35yil7i6Whiw_u33DYeRldx4G-36ueo,4166
2
+ vibecore/cli.py,sha256=HU2cjvEDzMWlauoArUItBlTpsVAdgVuKFMLshtaqvUE,7119
3
3
  vibecore/context.py,sha256=JUVkZpmKGUSlcchrHpxu-oSO8D21GDgHT1BXDzZDTeQ,844
4
4
  vibecore/flow.py,sha256=ZaKzMsz4YBvgelVzJOIHnTJzMWTmvkfvudwW_hllq6U,3384
5
5
  vibecore/main.py,sha256=MIn7Mpg_xO_20c6Mju8PgY-MmVCTER9cepHd5YFbtYs,20175
6
6
  vibecore/main.tcss,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  vibecore/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- vibecore/settings.py,sha256=u6kWIMdd5IoLE_SJYqPChR1du8bJ3ZhuCHQQvsUy_cY,6041
8
+ vibecore/settings.py,sha256=PwivzoJ-xyJu-Mmnv4E6G_E8up4GNvvz9_j4ttj-GUw,7063
9
9
  vibecore/agents/default.py,sha256=wxeP3Hsq9MVBChyMF_sNkVHCtFFXgy5ghDIxy9eH_fQ,2287
10
10
  vibecore/agents/prompts.py,sha256=0oO9QzcytIbzgZcKJQjWD9fSRNQqBqqK5ku0fcYZZrA,324
11
11
  vibecore/agents/task.py,sha256=cdhZDzKDA8eHHNYPhogFIKBms3oVAMvYeiBB2GqYNuE,1898
12
+ vibecore/auth/__init__.py,sha256=lFxAcdjXpmCjU2tWBnej3fyUqJKSc41qHLF8929nMRM,451
13
+ vibecore/auth/config.py,sha256=xEuChq61dygaDGhpOA9kK3VSximL42Usd-xBOY2XMpw,1650
14
+ vibecore/auth/interceptor.py,sha256=KsMbnTi8DDVDnwiC1YT4APjcpvpIVQK3kMSS28wizNs,5127
15
+ vibecore/auth/manager.py,sha256=xGhE8BUwmiAmT7zQWIqqYGD_3d1qdkBt9b-AslWIHJM,5980
16
+ vibecore/auth/models.py,sha256=5dw_p2s2AMSCp_NqXxF_3gsb4dvauEMturK23t9tRA0,1083
17
+ vibecore/auth/oauth_flow.py,sha256=LV8zQbNbkBRmMObsuvvc61PUQHypKyx4wByNd7PJzTc,4274
18
+ vibecore/auth/pkce.py,sha256=YMQxddItPqUyy1pkKfYPNWIahWhIUVWL7vPFsQQvb7M,956
19
+ vibecore/auth/storage.py,sha256=dWSDi4thRHHrSTJmAOInOdArTGQ_t0EdWHrk4Am8LWg,3495
20
+ vibecore/auth/token_manager.py,sha256=Dwd0EkbBVeoIef7K6RW4QzaS7-6HAM-or0Ra4M1xddg,4611
12
21
  vibecore/handlers/__init__.py,sha256=pFogA2n3GeIi4lmlUEU5jFprNNOaA6AWRR8Wc9X-P4Y,148
13
- vibecore/handlers/stream_handler.py,sha256=N3fs7jO9QcjSClSyglrwJQ3ky08F70xS8j5m-aYNkyM,10336
22
+ vibecore/handlers/stream_handler.py,sha256=e4VJOJcH84QmgKkGjOedwd85EZWmmvipmJpGuDBSPhA,11069
14
23
  vibecore/mcp/__init__.py,sha256=sl2_8pWjPx4TotO0ZojunVA6Jn6yOhbTQNbQG9-C-Jc,199
15
24
  vibecore/mcp/manager.py,sha256=RRpoFUiQjSg0-h9M7sF3odaSM7LURwrxVlaae5Yml3M,5644
16
25
  vibecore/mcp/server_wrapper.py,sha256=CkTyqZzmy7oeciSml0Q915orho_U2XcHoqhDVMOq7nY,3989
17
26
  vibecore/models/__init__.py,sha256=-vF0e_S5p7VdBM_TZuDI6oWFHcPecdX5KRjUzifHBow,116
18
27
  vibecore/models/anthropic.py,sha256=X48qj73cQ2jiChtoeMZYfLrkWTGABQZLEOPeU17hzuU,9750
28
+ vibecore/models/anthropic_auth.py,sha256=_hRGbPHTs6IrkSc5mDI7mshdOZYCyqu82HX9WdQIb8Y,8856
19
29
  vibecore/prompts/common_system_prompt.txt,sha256=L-YlOfTJSQLtVg6d0r9lcD5FrgOLzoSWjGzVfQjcDBg,4916
20
30
  vibecore/session/__init__.py,sha256=FXbtw8DZVBw8e3qCA2cQharMzozblhwA0yU4U0JRSkM,121
21
31
  vibecore/session/file_lock.py,sha256=vCuDdfaOGDeVpTjJP6yBJx7onIT7JkkAeAuWAtuLJb8,3739
@@ -65,11 +75,11 @@ vibecore/widgets/info.py,sha256=hXtsRUOE13oHbIm9FNe1GCUX_FCht28pgT9SQWeJ69I,1567
65
75
  vibecore/widgets/info.tcss,sha256=v30IqNt1two-ezIcm18ZEInKRKcRkAW-h-UH2r8QzSo,201
66
76
  vibecore/widgets/messages.py,sha256=az4fJtdk3ItSoFZBG_adRDUHdTLttIV8F23E8LOb-mg,8156
67
77
  vibecore/widgets/messages.tcss,sha256=WtBbjf5LgFkUhzhVlxJB7NMbagWladJawDizvDm7hBE,1271
68
- vibecore/widgets/tool_message_factory.py,sha256=FMwavKMRNT8ik9RgcL37WuM19Ln-c5wuFmS0A2CkikM,5377
69
- vibecore/widgets/tool_messages.py,sha256=PKmPigeOlccowo0uLpgIPzsmmE-zkichzuXIS6hWsbQ,24501
70
- vibecore/widgets/tool_messages.tcss,sha256=mcFY58FE1AcfEvEiA_Yb7sMpIniTIC_IjDvv8M7vWOA,6924
71
- vibecore-0.3.0b1.dist-info/METADATA,sha256=PYHen54ZzyRC9-8d6NA9GNxiV24aexWU8kPaQiiuJCk,18066
72
- vibecore-0.3.0b1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
73
- vibecore-0.3.0b1.dist-info/entry_points.txt,sha256=YldTakc3dNelboaWXtzCcnM5MXvU2_6pVOjc2xPjDTY,47
74
- vibecore-0.3.0b1.dist-info/licenses/LICENSE,sha256=KXxxifvrcreHrZ4aOYgP-vA8DRHHueW389KKOeEbtjc,1069
75
- vibecore-0.3.0b1.dist-info/RECORD,,
78
+ vibecore/widgets/tool_message_factory.py,sha256=yrZorT4HKo5b6rWUc0dgQle7q7cvLyq8JllE772RZS0,5730
79
+ vibecore/widgets/tool_messages.py,sha256=hJOolN3iLTAjqfotfH1elXqsdDo1r_UHjsyRVH0GAeo,29415
80
+ vibecore/widgets/tool_messages.tcss,sha256=gdChmHClURqn_sD9GkcOGQcQVYvUUl75mLUYp85sKz8,8442
81
+ vibecore-0.3.1.dist-info/METADATA,sha256=wCQB7NKn35T0W3onSrpV1FNX13zHzO-VEn0WqU6ZIlw,18093
82
+ vibecore-0.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
83
+ vibecore-0.3.1.dist-info/entry_points.txt,sha256=i9mOKvpz07ciV_YYisxNCYZ53_Crjkn9mciiQ3aA6QM,51
84
+ vibecore-0.3.1.dist-info/licenses/LICENSE,sha256=KXxxifvrcreHrZ4aOYgP-vA8DRHHueW389KKOeEbtjc,1069
85
+ vibecore-0.3.1.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ vibecore = vibecore.cli:cli_main
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- vibecore = vibecore.cli:main