|
294 | 294 | "outputs": [], |
295 | 295 | "source": "@dataclass\nclass WaveSession:\n \"\"\"Represents a Wave collaboration session.\"\"\"\n session_id: str\n timestamp: str\n context: WaveContext\n system_prompt: str\n task: Optional[str] = None\n log_entries: List[Dict[str, Any]] = field(default_factory=list)\n \n def add_log(self, entry_type: str, content: str):\n \"\"\"Add a log entry to the session.\"\"\"\n self.log_entries.append({\n \"timestamp\": datetime.now().isoformat(),\n \"type\": entry_type,\n \"content\": content\n })\n \n def save(self, output_dir: str = \".claude/logs/sessions\"):\n \"\"\"Save the session log to a file.\"\"\"\n output_path = Path(output_dir)\n output_path.mkdir(parents=True, exist_ok=True)\n \n log_file = output_path / f\"session_{self.session_id}.json\"\n \n session_data = {\n \"session_id\": self.session_id,\n \"timestamp\": self.timestamp,\n \"task\": self.task,\n \"context\": self.context.to_dict(),\n \"system_prompt\": self.system_prompt,\n \"log_entries\": self.log_entries\n }\n \n with open(log_file, \"w\", encoding=\"utf-8\") as f:\n json.dump(session_data, f, indent=2)\n \n return str(log_file)\n\n\ndef create_wave_session(task: Optional[str] = None) -> WaveSession:\n \"\"\"\n Create a new Wave session with captured context.\n \n Args:\n task: Optional task description for the session\n \n Returns:\n WaveSession object\n \"\"\"\n ctx = get_wave_context()\n session_id = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n \n session = WaveSession(\n session_id=session_id,\n timestamp=ctx.timestamp,\n context=ctx,\n system_prompt=generate_system_prompt(ctx),\n task=task\n )\n \n session.add_log(\"session_start\", f\"Session created: {session_id}\")\n if task:\n session.add_log(\"task\", task)\n \n return session\n\n\n# Create a demo session\ndemo_session = create_wave_session(\"Explore Wave Toolkit Project Book\")\nprint(f\"\ud83d\udcdd Session Created: {demo_session.session_id}\")\nprint(f\" Task: {demo_session.task}\")\nprint(f\" Log Entries: {len(demo_session.log_entries)}\")" |
296 | 296 | }, |
| 297 | + { |
| 298 | + "cell_type": "code", |
| 299 | + "execution_count": null, |
| 300 | + "metadata": {}, |
| 301 | + "outputs": [], |
| 302 | + "source": [ |
| 303 | + "def import_traces(json_file_path: str) -> List[Dict[str, Any]]:", |
| 304 | + " \"\"\"", |
| 305 | + " Import trace data from a JSON file with proper error handling.", |
| 306 | + " ", |
| 307 | + " Handles JSON files containing trace data with required fields:", |
| 308 | + " - trace_id: Unique identifier for the trace", |
| 309 | + " - state: Current state of the trace", |
| 310 | + " - input: Input data for the trace", |
| 311 | + " - output: Output data from the trace", |
| 312 | + " ", |
| 313 | + " Args:", |
| 314 | + " json_file_path: Path to the JSON file containing trace data", |
| 315 | + " ", |
| 316 | + " Returns:", |
| 317 | + " List of trace dictionaries with validated fields", |
| 318 | + " ", |
| 319 | + " Raises:", |
| 320 | + " FileNotFoundError: If the JSON file doesn't exist", |
| 321 | + " json.JSONDecodeError: If the file contains invalid JSON", |
| 322 | + " ValueError: If required fields are missing or invalid", |
| 323 | + " ", |
| 324 | + " Example:", |
| 325 | + " >>> traces = import_traces(\"traces.json\")", |
| 326 | + " >>> for trace in traces:", |
| 327 | + " ... print(f\"Trace {trace['trace_id']}: {trace['state']}\")", |
| 328 | + " \"\"\"", |
| 329 | + " # Check if file exists", |
| 330 | + " if not Path(json_file_path).exists():", |
| 331 | + " raise FileNotFoundError(f\"Trace file not found: {json_file_path}\")", |
| 332 | + " ", |
| 333 | + " # Read and parse JSON", |
| 334 | + " try:", |
| 335 | + " with open(json_file_path, 'r', encoding='utf-8') as f:", |
| 336 | + " data = json.load(f)", |
| 337 | + " except json.JSONDecodeError as e:", |
| 338 | + " raise json.JSONDecodeError(", |
| 339 | + " f\"Invalid JSON in file {json_file_path}: {str(e)}\", ", |
| 340 | + " e.doc, ", |
| 341 | + " e.pos", |
| 342 | + " )", |
| 343 | + " ", |
| 344 | + " # Ensure data is a list", |
| 345 | + " if isinstance(data, dict):", |
| 346 | + " # If it's a single trace object, wrap it in a list", |
| 347 | + " data = [data]", |
| 348 | + " elif not isinstance(data, list):", |
| 349 | + " raise ValueError(", |
| 350 | + " f\"Expected JSON to contain a list or dict, got {type(data).__name__}\"", |
| 351 | + " )", |
| 352 | + " ", |
| 353 | + " # Required fields for trace data", |
| 354 | + " required_fields = ['trace_id', 'state', 'input', 'output']", |
| 355 | + " ", |
| 356 | + " # Validate each trace", |
| 357 | + " validated_traces = []", |
| 358 | + " errors = []", |
| 359 | + " ", |
| 360 | + " for idx, trace in enumerate(data):", |
| 361 | + " if not isinstance(trace, dict):", |
| 362 | + " errors.append(f\"Trace at index {idx} is not a dictionary: {type(trace).__name__}\")", |
| 363 | + " continue", |
| 364 | + " ", |
| 365 | + " # Check for missing required fields", |
| 366 | + " missing_fields = [field for field in required_fields if field not in trace]", |
| 367 | + " ", |
| 368 | + " if missing_fields:", |
| 369 | + " # Build a helpful error message", |
| 370 | + " error_msg = (", |
| 371 | + " f\"Trace at index {idx} is missing required fields: {', '.join(missing_fields)}. \"", |
| 372 | + " f\"Available fields: {', '.join(trace.keys()) if trace.keys() else 'none'}. \"", |
| 373 | + " f\"Required fields are: {', '.join(required_fields)}\"", |
| 374 | + " )", |
| 375 | + " errors.append(error_msg)", |
| 376 | + " continue", |
| 377 | + " ", |
| 378 | + " # Validate that required fields are not None", |
| 379 | + " none_fields = [field for field in required_fields if trace[field] is None]", |
| 380 | + " if none_fields:", |
| 381 | + " error_msg = (", |
| 382 | + " f\"Trace at index {idx} has null values for required fields: {', '.join(none_fields)}\"", |
| 383 | + " )", |
| 384 | + " errors.append(error_msg)", |
| 385 | + " continue", |
| 386 | + " ", |
| 387 | + " validated_traces.append(trace)", |
| 388 | + " ", |
| 389 | + " # If we have errors, raise a comprehensive error message", |
| 390 | + " if errors:", |
| 391 | + " error_summary = f\"Found {len(errors)} invalid trace(s) in {json_file_path}:\\n\"", |
| 392 | + " error_summary += \"\\n\".join(f\" - {err}\" for err in errors[:5]) # Show first 5 errors", |
| 393 | + " if len(errors) > 5:", |
| 394 | + " error_summary += f\"\\n ... and {len(errors) - 5} more error(s)\"", |
| 395 | + " raise ValueError(error_summary)", |
| 396 | + " ", |
| 397 | + " if not validated_traces:", |
| 398 | + " raise ValueError(f\"No valid traces found in {json_file_path}\")", |
| 399 | + " ", |
| 400 | + " return validated_traces", |
| 401 | + "", |
| 402 | + "", |
| 403 | + "# Example usage and test", |
| 404 | + "def _test_import_traces():", |
| 405 | + " \"\"\"Test the import_traces function with various scenarios.\"\"\"", |
| 406 | + " print(\"\\n\ud83e\uddea Testing import_traces function...\")", |
| 407 | + " ", |
| 408 | + " # Create test directory", |
| 409 | + " test_dir = Path(\".claude/test_traces\")", |
| 410 | + " test_dir.mkdir(parents=True, exist_ok=True)", |
| 411 | + " ", |
| 412 | + " # Test 1: Valid trace data", |
| 413 | + " valid_trace_file = test_dir / \"valid_traces.json\"", |
| 414 | + " valid_data = [", |
| 415 | + " {", |
| 416 | + " \"trace_id\": \"trace_001\",", |
| 417 | + " \"state\": \"completed\",", |
| 418 | + " \"input\": {\"query\": \"Hello\"},", |
| 419 | + " \"output\": {\"response\": \"Hi there!\"}", |
| 420 | + " },", |
| 421 | + " {", |
| 422 | + " \"trace_id\": \"trace_002\", ", |
| 423 | + " \"state\": \"pending\",", |
| 424 | + " \"input\": {\"query\": \"How are you?\"},", |
| 425 | + " \"output\": {}", |
| 426 | + " }", |
| 427 | + " ]", |
| 428 | + " with open(valid_trace_file, 'w') as f:", |
| 429 | + " json.dump(valid_data, f, indent=2)", |
| 430 | + " ", |
| 431 | + " try:", |
| 432 | + " traces = import_traces(str(valid_trace_file))", |
| 433 | + " print(f\"\u2705 Test 1 passed: Loaded {len(traces)} valid traces\")", |
| 434 | + " except Exception as e:", |
| 435 | + " print(f\"\u274c Test 1 failed: {e}\")", |
| 436 | + " ", |
| 437 | + " # Test 2: Missing required field", |
| 438 | + " invalid_trace_file = test_dir / \"invalid_traces.json\"", |
| 439 | + " invalid_data = [", |
| 440 | + " {", |
| 441 | + " \"trace_id\": \"trace_003\",", |
| 442 | + " \"state\": \"completed\",", |
| 443 | + " # Missing 'input' and 'output'", |
| 444 | + " }", |
| 445 | + " ]", |
| 446 | + " with open(invalid_trace_file, 'w') as f:", |
| 447 | + " json.dump(invalid_data, f, indent=2)", |
| 448 | + " ", |
| 449 | + " try:", |
| 450 | + " traces = import_traces(str(invalid_trace_file))", |
| 451 | + " print(f\"\u274c Test 2 failed: Should have raised ValueError for missing fields\")", |
| 452 | + " except ValueError as e:", |
| 453 | + " if \"missing required fields\" in str(e):", |
| 454 | + " print(f\"\u2705 Test 2 passed: Caught missing fields error\")", |
| 455 | + " else:", |
| 456 | + " print(f\"\u274c Test 2 failed: Wrong error message: {e}\")", |
| 457 | + " except Exception as e:", |
| 458 | + " print(f\"\u274c Test 2 failed: Unexpected error: {e}\")", |
| 459 | + " ", |
| 460 | + " # Test 3: File not found", |
| 461 | + " try:", |
| 462 | + " traces = import_traces(\"nonexistent_file.json\")", |
| 463 | + " print(f\"\u274c Test 3 failed: Should have raised FileNotFoundError\")", |
| 464 | + " except FileNotFoundError:", |
| 465 | + " print(f\"\u2705 Test 3 passed: Caught file not found error\")", |
| 466 | + " except Exception as e:", |
| 467 | + " print(f\"\u274c Test 3 failed: Unexpected error: {e}\")", |
| 468 | + " ", |
| 469 | + " # Test 4: Invalid JSON", |
| 470 | + " malformed_file = test_dir / \"malformed.json\"", |
| 471 | + " with open(malformed_file, 'w') as f:", |
| 472 | + " f.write(\"{invalid json content\")", |
| 473 | + " ", |
| 474 | + " try:", |
| 475 | + " traces = import_traces(str(malformed_file))", |
| 476 | + " print(f\"\u274c Test 4 failed: Should have raised JSONDecodeError\")", |
| 477 | + " except json.JSONDecodeError:", |
| 478 | + " print(f\"\u2705 Test 4 passed: Caught invalid JSON error\")", |
| 479 | + " except Exception as e:", |
| 480 | + " print(f\"\u274c Test 4 failed: Unexpected error: {e}\")", |
| 481 | + " ", |
| 482 | + " print(\"\\n\u2728 Testing complete!\")", |
| 483 | + "", |
| 484 | + "# Uncomment to run tests", |
| 485 | + "# _test_import_traces()", |
| 486 | + "" |
| 487 | + ] |
| 488 | + }, |
297 | 489 | { |
298 | 490 | "cell_type": "markdown", |
299 | 491 | "metadata": {}, |
|
0 commit comments