prompt_objects 0.3.1 → 0.5.0

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/CLAUDE.md +112 -44
  4. data/Gemfile.lock +31 -29
  5. data/README.md +5 -0
  6. data/frontend/index.html +5 -1
  7. data/frontend/package-lock.json +123 -0
  8. data/frontend/package.json +4 -0
  9. data/frontend/src/App.tsx +70 -71
  10. data/frontend/src/canvas/CanvasView.tsx +113 -0
  11. data/frontend/src/canvas/ForceLayout.ts +115 -0
  12. data/frontend/src/canvas/SceneManager.ts +587 -0
  13. data/frontend/src/canvas/canvasStore.ts +47 -0
  14. data/frontend/src/canvas/constants.ts +95 -0
  15. data/frontend/src/canvas/controls/CameraControls.ts +98 -0
  16. data/frontend/src/canvas/edges/MessageArc.ts +149 -0
  17. data/frontend/src/canvas/inspector/InspectorPanel.tsx +31 -0
  18. data/frontend/src/canvas/inspector/POInspector.tsx +262 -0
  19. data/frontend/src/canvas/inspector/ToolCallInspector.tsx +67 -0
  20. data/frontend/src/canvas/nodes/PONode.ts +249 -0
  21. data/frontend/src/canvas/nodes/ToolCallNode.ts +116 -0
  22. data/frontend/src/canvas/types.ts +24 -0
  23. data/frontend/src/components/ContextMenu.tsx +5 -4
  24. data/frontend/src/components/Inspector.tsx +232 -0
  25. data/frontend/src/components/MarkdownMessage.tsx +22 -20
  26. data/frontend/src/components/MethodList.tsx +90 -0
  27. data/frontend/src/components/ModelSelector.tsx +13 -14
  28. data/frontend/src/components/NotificationPanel.tsx +29 -33
  29. data/frontend/src/components/ObjectList.tsx +78 -0
  30. data/frontend/src/components/PaneSlot.tsx +30 -0
  31. data/frontend/src/components/SourcePane.tsx +202 -0
  32. data/frontend/src/components/SystemBar.tsx +74 -0
  33. data/frontend/src/components/Transcript.tsx +76 -0
  34. data/frontend/src/components/UsagePanel.tsx +27 -27
  35. data/frontend/src/components/Workspace.tsx +260 -0
  36. data/frontend/src/components/index.ts +10 -9
  37. data/frontend/src/hooks/useResize.ts +55 -0
  38. data/frontend/src/hooks/useWebSocket.ts +274 -189
  39. data/frontend/src/index.css +69 -3
  40. data/frontend/src/store/index.ts +23 -0
  41. data/frontend/src/types/index.ts +5 -0
  42. data/frontend/tailwind.config.js +28 -9
  43. data/lib/prompt_objects/capability.rb +23 -1
  44. data/lib/prompt_objects/connectors/mcp.rb +5 -22
  45. data/lib/prompt_objects/environment.rb +8 -0
  46. data/lib/prompt_objects/llm/openai_adapter.rb +22 -0
  47. data/lib/prompt_objects/mcp/tools/get_pending_requests.rb +1 -2
  48. data/lib/prompt_objects/mcp/tools/inspect_po.rb +1 -31
  49. data/lib/prompt_objects/mcp/tools/list_prompt_objects.rb +2 -8
  50. data/lib/prompt_objects/primitives/list_files.rb +1 -2
  51. data/lib/prompt_objects/prompt_object.rb +150 -6
  52. data/lib/prompt_objects/server/api/routes.rb +3 -48
  53. data/lib/prompt_objects/server/app.rb +9 -0
  54. data/lib/prompt_objects/server/public/assets/index-D1myxE0l.js +4345 -0
  55. data/lib/prompt_objects/server/public/assets/index-DdCcwC-Z.css +1 -0
  56. data/lib/prompt_objects/server/public/index.html +7 -3
  57. data/lib/prompt_objects/server/websocket_handler.rb +23 -100
  58. data/lib/prompt_objects/server.rb +6 -62
  59. data/prompt_objects.gemspec +1 -1
  60. data/templates/arc-agi-1/primitives/find_objects.rb +1 -1
  61. data/templates/arc-agi-1/primitives/grid_diff.rb +2 -2
  62. data/templates/arc-agi-1/primitives/grid_info.rb +1 -1
  63. data/templates/arc-agi-1/primitives/grid_transform.rb +1 -1
  64. data/templates/arc-agi-1/primitives/render_grid.rb +1 -0
  65. data/templates/arc-agi-1/primitives/test_solution.rb +3 -0
  66. metadata +26 -14
  67. data/frontend/src/components/CapabilitiesPanel.tsx +0 -141
  68. data/frontend/src/components/ChatPanel.tsx +0 -288
  69. data/frontend/src/components/Dashboard.tsx +0 -83
  70. data/frontend/src/components/Header.tsx +0 -141
  71. data/frontend/src/components/MessageBus.tsx +0 -56
  72. data/frontend/src/components/POCard.tsx +0 -56
  73. data/frontend/src/components/PODetail.tsx +0 -124
  74. data/frontend/src/components/PromptPanel.tsx +0 -156
  75. data/frontend/src/components/SessionsPanel.tsx +0 -174
  76. data/frontend/src/components/ThreadsSidebar.tsx +0 -163
  77. data/lib/prompt_objects/server/public/assets/index-Bkme6COu.css +0 -1
  78. data/lib/prompt_objects/server/public/assets/index-CQ7lVDF_.js +0 -77
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:Geist Mono,IBM Plex Mono,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.bottom-3{bottom:.75rem}.bottom-4{bottom:1rem}.left-3{left:.75rem}.right-0{right:0}.right-4{right:1rem}.top-0{top:0}.top-3{top:.75rem}.top-full{top:100%}.z-10{z-index:10}.z-50{z-index:50}.my-0\.5{margin-top:.125rem;margin-bottom:.125rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.ml-0\.5{margin-left:.125rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1\.5{height:.375rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-40{height:10rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-32{max-height:8rem}.max-h-48{max-height:12rem}.max-h-64{max-height:16rem}.max-h-\[60vh\]{max-height:60vh}.max-h-\[80vh\]{max-height:80vh}.w-1\.5{width:.375rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-56{width:14rem}.w-60{width:15rem}.w-80{width:20rem}.w-96{width:24rem}.w-\[400px\]{width:400px}.w-full{width:100%}.min-w-\[140px\]{min-width:140px}.min-w-full{min-width:100%}.max-w-\[60px\]{max-width:60px}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.resize{resize:both}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-b{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-b-0{border-bottom-width:0px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-po-accent{--tw-border-opacity: 1;border-color:rgb(212 149 42 / var(--tw-border-opacity, 1))}.border-po-border{--tw-border-opacity: 1;border-color:rgb(61 58 55 / var(--tw-border-opacity, 1))}.border-po-status-calling{--tw-border-opacity: 1;border-color:rgb(59 154 110 / var(--tw-border-opacity, 1))}.border-po-warning{--tw-border-opacity: 1;border-color:rgb(212 149 42 / var(--tw-border-opacity, 1))}.border-po-warning\/30{border-color:#d4952a4d}.border-transparent{border-color:transparent}.bg-black\/50{background-color:#00000080}.bg-po-accent{--tw-bg-opacity: 1;background-color:rgb(212 149 42 / var(--tw-bg-opacity, 1))}.bg-po-accent-wash{background-color:#d4952a14}.bg-po-bg{--tw-bg-opacity: 1;background-color:rgb(26 25 24 / var(--tw-bg-opacity, 1))}.bg-po-error{--tw-bg-opacity: 1;background-color:rgb(196 92 74 / var(--tw-bg-opacity, 1))}.bg-po-status-active{--tw-bg-opacity: 1;background-color:rgb(212 149 42 / var(--tw-bg-opacity, 1))}.bg-po-status-calling{--tw-bg-opacity: 1;background-color:rgb(59 154 110 / var(--tw-bg-opacity, 1))}.bg-po-status-idle{--tw-bg-opacity: 1;background-color:rgb(120 114 106 / var(--tw-bg-opacity, 1))}.bg-po-success{--tw-bg-opacity: 1;background-color:rgb(59 154 110 / var(--tw-bg-opacity, 1))}.bg-po-surface{--tw-bg-opacity: 1;background-color:rgb(34 33 32 / var(--tw-bg-opacity, 1))}.bg-po-surface-2{--tw-bg-opacity: 1;background-color:rgb(44 42 40 / var(--tw-bg-opacity, 1))}.bg-po-surface-2\/80{background-color:#2c2a28cc}.bg-po-text-ghost{--tw-bg-opacity: 1;background-color:rgb(82 78 72 / var(--tw-bg-opacity, 1))}.bg-po-warning{--tw-bg-opacity: 1;background-color:rgb(212 149 42 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-1\.5{padding-bottom:.375rem}.pb-2{padding-bottom:.5rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-\[4\.5rem\]{padding-left:4.5rem}.text-left{text-align:left}.text-center{text-align:center}.align-text-bottom{vertical-align:text-bottom}.font-mono{font-family:Geist Mono,IBM Plex Mono,monospace}.font-ui{font-family:Geist,system-ui,sans-serif}.text-2xs{font-size:11px;line-height:15px}.text-\[0\.9em\]{font-size:.9em}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.uppercase{text-transform:uppercase}.normal-case{text-transform:none}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.tracking-wider{letter-spacing:.05em}.text-po-accent{--tw-text-opacity: 1;color:rgb(212 149 42 / var(--tw-text-opacity, 1))}.text-po-bg{--tw-text-opacity: 1;color:rgb(26 25 24 / var(--tw-text-opacity, 1))}.text-po-error{--tw-text-opacity: 1;color:rgb(196 92 74 / var(--tw-text-opacity, 1))}.text-po-status-active{--tw-text-opacity: 1;color:rgb(212 149 42 / var(--tw-text-opacity, 1))}.text-po-status-calling{--tw-text-opacity: 1;color:rgb(59 154 110 / var(--tw-text-opacity, 1))}.text-po-status-delegated{--tw-text-opacity: 1;color:rgb(90 143 194 / var(--tw-text-opacity, 1))}.text-po-success{--tw-text-opacity: 1;color:rgb(59 154 110 / var(--tw-text-opacity, 1))}.text-po-text-ghost{--tw-text-opacity: 1;color:rgb(82 78 72 / var(--tw-text-opacity, 1))}.text-po-text-primary{--tw-text-opacity: 1;color:rgb(232 226 218 / var(--tw-text-opacity, 1))}.text-po-text-secondary{--tw-text-opacity: 1;color:rgb(168 162 154 / var(--tw-text-opacity, 1))}.text-po-text-tertiary{--tw-text-opacity: 1;color:rgb(120 114 106 / var(--tw-text-opacity, 1))}.text-po-warning{--tw-text-opacity: 1;color:rgb(212 149 42 / var(--tw-text-opacity, 1))}.placeholder-po-text-ghost::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(82 78 72 / var(--tw-placeholder-opacity, 1))}.placeholder-po-text-ghost::placeholder{--tw-placeholder-opacity: 1;color:rgb(82 78 72 / var(--tw-placeholder-opacity, 1))}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_5px_rgba\(212\,149\,42\,0\.6\)\]{--tw-shadow: 0 0 5px rgba(212,149,42,.6);--tw-shadow-colored: 0 0 5px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_5px_rgba\(59\,154\,110\,0\.6\)\]{--tw-shadow: 0 0 5px rgba(59,154,110,.6);--tw-shadow-colored: 0 0 5px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_6px_rgba\(212\,149\,42\,0\.7\)\]{--tw-shadow: 0 0 6px rgba(212,149,42,.7);--tw-shadow-colored: 0 0 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_6px_rgba\(59\,154\,110\,0\.7\)\]{--tw-shadow: 0 0 6px rgba(59,154,110,.7);--tw-shadow-colored: 0 0 6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur{--tw-backdrop-blur: blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-150{transition-duration:.15s}html{color-scheme:dark;font-size:14px}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{--tw-bg-opacity: 1;background-color:rgb(26 25 24 / var(--tw-bg-opacity, 1))}::-webkit-scrollbar-thumb{border-radius:9999px;--tw-bg-opacity: 1;background-color:rgb(61 58 55 / var(--tw-bg-opacity, 1))}::-webkit-scrollbar-thumb:hover{--tw-bg-opacity: 1;background-color:rgb(92 87 82 / var(--tw-bg-opacity, 1))}::-moz-selection{background:#d4952a4d}::selection{background:#d4952a4d}.resize-handle{width:.25rem;cursor:col-resize;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.resize-handle:hover{background-color:#d4952a4d}.resize-handle:active{background-color:#d4952a80}.resize-handle-h{height:.25rem;cursor:row-resize;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.resize-handle-h:hover{background-color:#d4952a4d}.resize-handle-h:active{background-color:#d4952a80}.canvas-node-label{text-align:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.canvas-node-name{display:block;color:#e8e2da;font-size:12px;font-weight:500;font-family:Geist Mono,IBM Plex Mono,monospace;text-shadow:0 1px 4px rgba(0,0,0,.8)}.canvas-node-status{display:block;color:#78726a;font-size:10px;font-family:Geist Mono,IBM Plex Mono,monospace;text-shadow:0 1px 4px rgba(0,0,0,.8)}.canvas-node-badge{display:flex;align-items:center;justify-content:center;width:20px;height:20px;background:#d4952a;color:#1a1918;font-size:10px;font-weight:700;border-radius:50%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;box-shadow:0 0 8px #d4952a99}.canvas-toolcall-label{color:#3b9a6e;font-size:10px;font-family:Geist Mono,IBM Plex Mono,monospace;text-align:center;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;text-shadow:0 1px 4px rgba(0,0,0,.8)}.first\:mt-0:first-child{margin-top:0}.last\:mb-0:last-child{margin-bottom:0}.hover\:border-po-accent:hover{--tw-border-opacity: 1;border-color:rgb(212 149 42 / var(--tw-border-opacity, 1))}.hover\:border-po-border-focus:hover{--tw-border-opacity: 1;border-color:rgb(92 87 82 / var(--tw-border-opacity, 1))}.hover\:bg-po-accent-muted:hover{--tw-bg-opacity: 1;background-color:rgb(154 109 32 / var(--tw-bg-opacity, 1))}.hover\:bg-po-surface-2:hover{--tw-bg-opacity: 1;background-color:rgb(44 42 40 / var(--tw-bg-opacity, 1))}.hover\:bg-po-surface-3:hover{--tw-bg-opacity: 1;background-color:rgb(54 52 50 / var(--tw-bg-opacity, 1))}.hover\:text-po-accent:hover{--tw-text-opacity: 1;color:rgb(212 149 42 / var(--tw-text-opacity, 1))}.hover\:text-po-text-primary:hover{--tw-text-opacity: 1;color:rgb(232 226 218 / var(--tw-text-opacity, 1))}.hover\:text-po-text-secondary:hover{--tw-text-opacity: 1;color:rgb(168 162 154 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.focus\:border-po-accent:focus{--tw-border-opacity: 1;border-color:rgb(212 149 42 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:640px){.sm\:inline{display:inline}}
@@ -4,11 +4,15 @@
4
4
  <meta charset="UTF-8" />
5
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
8
+ <link href="https://cdn.jsdelivr.net/fontsource/fonts/geist@latest/latin-400-normal.woff2" as="font" type="font/woff2" crossorigin />
9
+ <link href="https://cdn.jsdelivr.net/npm/geist@1/dist/fonts/geist-sans/style.css" rel="stylesheet" />
10
+ <link href="https://cdn.jsdelivr.net/npm/geist@1/dist/fonts/geist-mono/style.css" rel="stylesheet" />
7
11
  <title>PromptObjects</title>
8
- <script type="module" crossorigin src="/assets/index-CQ7lVDF_.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-Bkme6COu.css">
12
+ <script type="module" crossorigin src="/assets/index-D1myxE0l.js"></script>
13
+ <link rel="stylesheet" crossorigin href="/assets/index-DdCcwC-Z.css">
10
14
  </head>
11
- <body class="bg-po-bg text-gray-100">
15
+ <body class="bg-po-bg text-po-text-primary font-ui">
12
16
  <div id="root"></div>
13
17
  </body>
14
18
  </html>
@@ -156,7 +156,7 @@ module PromptObjects
156
156
  type: "po_state",
157
157
  payload: {
158
158
  name: po.name,
159
- state: po_state_hash(po).merge(status: "idle")
159
+ state: po.to_state_hash(registry: @runtime.registry).merge(status: "idle")
160
160
  }
161
161
  )
162
162
  end
@@ -269,7 +269,7 @@ module PromptObjects
269
269
  type: "po_state",
270
270
  payload: {
271
271
  name: po_name,
272
- state: { sessions: po.list_sessions.map { |s| session_summary(s) } }
272
+ state: { sessions: po.list_sessions.map { |s| PromptObject.serialize_session(s) } }
273
273
  }
274
274
  )
275
275
  end
@@ -311,7 +311,7 @@ module PromptObjects
311
311
  payload: {
312
312
  target: po_obj.name,
313
313
  session_id: session_id,
314
- messages: history.map { |m| message_to_hash(m) }
314
+ messages: history.map { |m| PromptObject.serialize_message(m) }
315
315
  }
316
316
  )
317
317
  }
@@ -350,11 +350,24 @@ module PromptObjects
350
350
  type: "po_state",
351
351
  payload: {
352
352
  name: po_name,
353
- state: { sessions: po.list_sessions.map { |s| session_summary(s) } }
353
+ state: { sessions: po.list_sessions.map { |s| PromptObject.serialize_session(s) } }
354
354
  }
355
355
  )
356
356
  rescue => e
357
357
  send_error("Error from #{po_name}: #{e.message}")
358
+
359
+ # Broadcast rich error context for diagnostics
360
+ llm_config = @runtime.llm_config
361
+ send_message(
362
+ type: "llm_error",
363
+ payload: {
364
+ po_name: po_name,
365
+ provider: llm_config[:provider],
366
+ model: llm_config[:model],
367
+ error: e.message,
368
+ error_class: e.class.name
369
+ }
370
+ )
358
371
  ensure
359
372
  # Clean up the callback
360
373
  po.on_history_updated = nil
@@ -425,7 +438,7 @@ module PromptObjects
425
438
  # Also send updated PO state
426
439
  send_message(
427
440
  type: "po_state",
428
- payload: { name: po_name, state: po_state_hash(po) }
441
+ payload: { name: po_name, state: po.to_state_hash(registry: @runtime.registry) }
429
442
  )
430
443
  end
431
444
 
@@ -445,7 +458,7 @@ module PromptObjects
445
458
  # Send updated PO state with new session's messages
446
459
  send_message(
447
460
  type: "po_state",
448
- payload: { name: po_name, state: po_state_hash(po) }
461
+ payload: { name: po_name, state: po.to_state_hash(registry: @runtime.registry) }
449
462
  )
450
463
  else
451
464
  send_error("Could not switch to session: #{session_id}")
@@ -475,7 +488,7 @@ module PromptObjects
475
488
  # Also send updated PO state
476
489
  send_message(
477
490
  type: "po_state",
478
- payload: { name: po_name, state: po_state_hash(po) }
491
+ payload: { name: po_name, state: po.to_state_hash(registry: @runtime.registry) }
479
492
  )
480
493
  end
481
494
 
@@ -501,7 +514,7 @@ module PromptObjects
501
514
  info = LLM::Factory.provider_info(provider)
502
515
  {
503
516
  name: provider,
504
- models: info[:models],
517
+ models: LLM::Factory.models_for(provider),
505
518
  default_model: info[:default_model],
506
519
  available: LLM::Factory.available_providers[provider]
507
520
  }
@@ -632,71 +645,12 @@ module PromptObjects
632
645
  send_message(type: "error", payload: { message: message })
633
646
  end
634
647
 
635
- def po_state_hash(po)
636
- {
637
- status: po.instance_variable_get(:@state) || "idle",
638
- description: po.description,
639
- capabilities: declared_capabilities_info(po),
640
- universal_capabilities: universal_capabilities_info,
641
- current_session: current_session_hash(po),
642
- sessions: po.list_sessions.map { |s| session_summary(s) },
643
- # Include full prompt for inspection
644
- prompt: po.body,
645
- config: po.config
646
- }
647
- end
648
-
649
- def declared_capabilities_info(po)
650
- declared = po.config["capabilities"] || []
651
- declared.map do |name|
652
- cap = @runtime.registry.get(name)
653
- {
654
- name: name,
655
- description: cap&.description || "Capability not found",
656
- parameters: cap&.parameters
657
- }
658
- end
659
- end
660
-
661
- def universal_capabilities_info
662
- UNIVERSAL_CAPABILITIES.map do |name|
663
- cap = @runtime.registry.get(name)
664
- {
665
- name: name,
666
- description: cap&.description || "Universal capability",
667
- parameters: cap&.parameters
668
- }
669
- end
670
- end
671
-
672
- def current_session_hash(po)
673
- return nil unless po.session_id
674
-
675
- {
676
- id: po.session_id,
677
- messages: po.history.map { |m| message_to_hash(m) }
678
- }
679
- end
680
-
681
648
  # Get messages for a specific session (may not be current session)
682
649
  def session_messages(po, session_id)
683
650
  return [] unless @runtime.session_store
684
651
 
685
652
  messages = @runtime.session_store.get_messages(session_id)
686
- messages.map { |m| message_to_hash(m) }
687
- end
688
-
689
- def session_summary(session)
690
- {
691
- id: session[:id],
692
- name: session[:name],
693
- message_count: session[:message_count] || 0,
694
- updated_at: session[:updated_at]&.iso8601,
695
- # Thread fields
696
- parent_session_id: session[:parent_session_id],
697
- parent_po: session[:parent_po],
698
- thread_type: session[:thread_type] || "root"
699
- }
653
+ messages.map { |m| PromptObject.serialize_message(m) }
700
654
  end
701
655
 
702
656
  # Recursively serialize a thread tree for JSON
@@ -704,42 +658,11 @@ module PromptObjects
704
658
  return nil unless tree
705
659
 
706
660
  {
707
- session: session_summary(tree[:session]),
661
+ session: PromptObject.serialize_session(tree[:session]),
708
662
  children: (tree[:children] || []).map { |child| serialize_thread_tree(child) }
709
663
  }
710
664
  end
711
665
 
712
- def message_to_hash(msg)
713
- case msg[:role]
714
- when :user
715
- # In-memory messages use :from, SQLite-loaded messages use :from_po
716
- from = msg[:from] || msg[:from_po]
717
- { role: "user", content: msg[:content], from: from }
718
- when :assistant
719
- hash = { role: "assistant", content: msg[:content] }
720
- if msg[:tool_calls]
721
- hash[:tool_calls] = msg[:tool_calls].map do |tc|
722
- # Handle both ToolCall objects and Hashes (from DB with symbol or string keys)
723
- if tc.is_a?(LLM::ToolCall)
724
- { id: tc.id, name: tc.name, arguments: tc.arguments }
725
- else
726
- tc_id = tc[:id] || tc["id"]
727
- tc_name = tc[:name] || tc["name"]
728
- tc_args = tc[:arguments] || tc["arguments"] || {}
729
- { id: tc_id, name: tc_name, arguments: tc_args }
730
- end
731
- end
732
- end
733
- hash
734
- when :tool
735
- # In-memory messages use :results, SQLite-loaded messages use :tool_results
736
- results = msg[:results] || msg[:tool_results]
737
- { role: "tool", results: results }
738
- else
739
- { role: msg[:role].to_s, content: msg[:content] }
740
- end
741
- end
742
-
743
666
  def request_to_hash(request)
744
667
  {
745
668
  id: request.id,
@@ -40,7 +40,7 @@ module PromptObjects
40
40
  type: "po_added",
41
41
  payload: {
42
42
  name: po.name,
43
- state: po_state_hash(po)
43
+ state: po.to_state_hash(registry: runtime.registry)
44
44
  }
45
45
  )
46
46
  puts "Broadcast: PO registered - #{po.name}"
@@ -53,7 +53,7 @@ module PromptObjects
53
53
  type: "po_modified",
54
54
  payload: {
55
55
  name: po.name,
56
- state: po_state_hash(po)
56
+ state: po.to_state_hash(registry: runtime.registry)
57
57
  }
58
58
  )
59
59
  puts "Broadcast: PO modified (programmatic) - #{po.name}"
@@ -64,7 +64,7 @@ module PromptObjects
64
64
  if env_path
65
65
  file_watcher = FileWatcher.new(runtime: runtime, env_path: env_path)
66
66
  file_watcher.subscribe do |event, data|
67
- handle_file_event(app, event, data)
67
+ handle_file_event(app, event, data, runtime: runtime)
68
68
  end
69
69
  file_watcher.start
70
70
  end
@@ -140,7 +140,7 @@ module PromptObjects
140
140
  end
141
141
 
142
142
  # Handle file change events and broadcast to connected clients.
143
- def self.handle_file_event(app, event, data)
143
+ def self.handle_file_event(app, event, data, runtime: nil)
144
144
  case event
145
145
  when :po_added
146
146
  po = data
@@ -148,7 +148,7 @@ module PromptObjects
148
148
  type: "po_added",
149
149
  payload: {
150
150
  name: po.name,
151
- state: po_state_hash(po)
151
+ state: po.to_state_hash(registry: runtime&.registry)
152
152
  }
153
153
  )
154
154
  puts "Broadcast: PO added - #{po.name}"
@@ -159,7 +159,7 @@ module PromptObjects
159
159
  type: "po_modified",
160
160
  payload: {
161
161
  name: po.name,
162
- state: po_state_hash(po)
162
+ state: po.to_state_hash(registry: runtime&.registry)
163
163
  }
164
164
  )
165
165
  puts "Broadcast: PO modified - #{po.name}"
@@ -173,61 +173,5 @@ module PromptObjects
173
173
  end
174
174
  end
175
175
 
176
- # Helper to convert PO to state hash for broadcasting.
177
- def self.po_state_hash(po)
178
- {
179
- status: po.instance_variable_get(:@state) || "idle",
180
- description: po.description,
181
- capabilities: po.config["capabilities"] || [],
182
- current_session: current_session_hash(po),
183
- sessions: po.list_sessions.map do |s|
184
- {
185
- id: s[:id],
186
- name: s[:name],
187
- message_count: s[:message_count] || 0,
188
- updated_at: s[:updated_at]&.iso8601,
189
- # Thread fields
190
- parent_session_id: s[:parent_session_id],
191
- parent_po: s[:parent_po],
192
- thread_type: s[:thread_type] || "root"
193
- }
194
- end,
195
- prompt: po.body,
196
- config: po.config
197
- }
198
- end
199
-
200
- # Helper to get current session data for a PO.
201
- def self.current_session_hash(po)
202
- return nil unless po.session_id
203
-
204
- {
205
- id: po.session_id,
206
- messages: po.history.map { |m| message_to_hash(m) }
207
- }
208
- end
209
-
210
- # Helper to convert a message to JSON-serializable hash.
211
- def self.message_to_hash(msg)
212
- case msg[:role]
213
- when :user
214
- { role: "user", content: msg[:content], from: msg[:from] }
215
- when :assistant
216
- hash = { role: "assistant", content: msg[:content] }
217
- if msg[:tool_calls]
218
- hash[:tool_calls] = msg[:tool_calls].map do |tc|
219
- tc_id = tc.respond_to?(:id) ? tc.id : (tc[:id] || tc["id"])
220
- tc_name = tc.respond_to?(:name) ? tc.name : (tc[:name] || tc["name"])
221
- tc_args = tc.respond_to?(:arguments) ? tc.arguments : (tc[:arguments] || tc["arguments"] || {})
222
- { id: tc_id, name: tc_name, arguments: tc_args }
223
- end
224
- end
225
- hash
226
- when :tool
227
- { role: "tool", results: msg[:results] }
228
- else
229
- { role: msg[:role].to_s, content: msg[:content] }
230
- end
231
- end
232
176
  end
233
177
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "prompt_objects"
5
- spec.version = "0.3.1"
5
+ spec.version = "0.5.0"
6
6
  spec.authors = ["Scott Werner"]
7
7
  spec.email = ["scott@sublayer.com"]
8
8
 
@@ -15,7 +15,7 @@ module PromptObjects
15
15
  {
16
16
  type: "object",
17
17
  properties: {
18
- grid: { type: "array", description: "2D array of integers" },
18
+ grid: { type: "array", items: { type: "array", items: { type: "integer" } }, description: "2D array of integers" },
19
19
  background: { type: "integer", description: "Background color to ignore (default: 0)" }
20
20
  },
21
21
  required: ["grid"]
@@ -15,8 +15,8 @@ module PromptObjects
15
15
  {
16
16
  type: "object",
17
17
  properties: {
18
- grid_a: { type: "array", description: "First grid (2D array)" },
19
- grid_b: { type: "array", description: "Second grid (2D array)" }
18
+ grid_a: { type: "array", items: { type: "array", items: { type: "integer" } }, description: "First grid (2D array)" },
19
+ grid_b: { type: "array", items: { type: "array", items: { type: "integer" } }, description: "Second grid (2D array)" }
20
20
  },
21
21
  required: ["grid_a", "grid_b"]
22
22
  }
@@ -15,7 +15,7 @@ module PromptObjects
15
15
  {
16
16
  type: "object",
17
17
  properties: {
18
- grid: { type: "array", description: "2D array of integers" }
18
+ grid: { type: "array", items: { type: "array", items: { type: "integer" } }, description: "2D array of integers" }
19
19
  },
20
20
  required: ["grid"]
21
21
  }
@@ -15,7 +15,7 @@ module PromptObjects
15
15
  {
16
16
  type: "object",
17
17
  properties: {
18
- grid: { type: "array", description: "2D array of integers" },
18
+ grid: { type: "array", items: { type: "array", items: { type: "integer" } }, description: "2D array of integers" },
19
19
  operation: {
20
20
  type: "string",
21
21
  enum: %w[rotate_90 rotate_180 rotate_270 flip_h flip_v transpose],
@@ -27,6 +27,7 @@ module PromptObjects
27
27
  properties: {
28
28
  grid: {
29
29
  type: "array",
30
+ items: { type: "array", items: { type: "integer" } },
30
31
  description: "2D array of integers 0-9"
31
32
  },
32
33
  label: {
@@ -21,14 +21,17 @@ module PromptObjects
21
21
  },
22
22
  grid: {
23
23
  type: "array",
24
+ items: { type: "array", items: { type: "integer" } },
24
25
  description: "A grid to compare directly against expected output (for quick checks)"
25
26
  },
26
27
  expected: {
27
28
  type: "array",
29
+ items: { type: "array", items: { type: "integer" } },
28
30
  description: "Expected output grid (used with 'grid' parameter)"
29
31
  },
30
32
  train: {
31
33
  type: "array",
34
+ items: { type: "object" },
32
35
  description: "Training pairs array (used with 'primitive_name'). Each element has 'input' and 'output' grids."
33
36
  }
34
37
  },
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prompt_objects
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Werner
@@ -218,22 +218,34 @@ files:
218
218
  - frontend/package.json
219
219
  - frontend/postcss.config.js
220
220
  - frontend/src/App.tsx
221
- - frontend/src/components/CapabilitiesPanel.tsx
222
- - frontend/src/components/ChatPanel.tsx
221
+ - frontend/src/canvas/CanvasView.tsx
222
+ - frontend/src/canvas/ForceLayout.ts
223
+ - frontend/src/canvas/SceneManager.ts
224
+ - frontend/src/canvas/canvasStore.ts
225
+ - frontend/src/canvas/constants.ts
226
+ - frontend/src/canvas/controls/CameraControls.ts
227
+ - frontend/src/canvas/edges/MessageArc.ts
228
+ - frontend/src/canvas/inspector/InspectorPanel.tsx
229
+ - frontend/src/canvas/inspector/POInspector.tsx
230
+ - frontend/src/canvas/inspector/ToolCallInspector.tsx
231
+ - frontend/src/canvas/nodes/PONode.ts
232
+ - frontend/src/canvas/nodes/ToolCallNode.ts
233
+ - frontend/src/canvas/types.ts
223
234
  - frontend/src/components/ContextMenu.tsx
224
- - frontend/src/components/Dashboard.tsx
225
- - frontend/src/components/Header.tsx
235
+ - frontend/src/components/Inspector.tsx
226
236
  - frontend/src/components/MarkdownMessage.tsx
227
- - frontend/src/components/MessageBus.tsx
237
+ - frontend/src/components/MethodList.tsx
228
238
  - frontend/src/components/ModelSelector.tsx
229
239
  - frontend/src/components/NotificationPanel.tsx
230
- - frontend/src/components/POCard.tsx
231
- - frontend/src/components/PODetail.tsx
232
- - frontend/src/components/PromptPanel.tsx
233
- - frontend/src/components/SessionsPanel.tsx
234
- - frontend/src/components/ThreadsSidebar.tsx
240
+ - frontend/src/components/ObjectList.tsx
241
+ - frontend/src/components/PaneSlot.tsx
242
+ - frontend/src/components/SourcePane.tsx
243
+ - frontend/src/components/SystemBar.tsx
244
+ - frontend/src/components/Transcript.tsx
235
245
  - frontend/src/components/UsagePanel.tsx
246
+ - frontend/src/components/Workspace.tsx
236
247
  - frontend/src/components/index.ts
248
+ - frontend/src/hooks/useResize.ts
237
249
  - frontend/src/hooks/useWebSocket.ts
238
250
  - frontend/src/index.css
239
251
  - frontend/src/main.tsx
@@ -280,8 +292,8 @@ files:
280
292
  - lib/prompt_objects/server/api/routes.rb
281
293
  - lib/prompt_objects/server/app.rb
282
294
  - lib/prompt_objects/server/file_watcher.rb
283
- - lib/prompt_objects/server/public/assets/index-Bkme6COu.css
284
- - lib/prompt_objects/server/public/assets/index-CQ7lVDF_.js
295
+ - lib/prompt_objects/server/public/assets/index-D1myxE0l.js
296
+ - lib/prompt_objects/server/public/assets/index-DdCcwC-Z.css
285
297
  - lib/prompt_objects/server/public/index.html
286
298
  - lib/prompt_objects/server/websocket_handler.rb
287
299
  - lib/prompt_objects/session/store.rb
@@ -358,7 +370,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
358
370
  - !ruby/object:Gem::Version
359
371
  version: '0'
360
372
  requirements: []
361
- rubygems_version: 3.7.2
373
+ rubygems_version: 4.0.3
362
374
  specification_version: 4
363
375
  summary: LLM-backed entities as first-class autonomous objects
364
376
  test_files: []