prompt_objects 0.4.0 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/CLAUDE.md +112 -44
- data/README.md +5 -0
- data/frontend/index.html +5 -1
- data/frontend/src/App.tsx +70 -78
- data/frontend/src/canvas/CanvasView.tsx +5 -5
- data/frontend/src/canvas/constants.ts +31 -31
- data/frontend/src/canvas/inspector/InspectorPanel.tsx +4 -4
- data/frontend/src/canvas/inspector/POInspector.tsx +35 -35
- data/frontend/src/canvas/inspector/ToolCallInspector.tsx +13 -13
- data/frontend/src/canvas/nodes/PONode.ts +2 -2
- data/frontend/src/components/ContextMenu.tsx +5 -4
- data/frontend/src/components/Inspector.tsx +232 -0
- data/frontend/src/components/MarkdownMessage.tsx +22 -20
- data/frontend/src/components/MethodList.tsx +90 -0
- data/frontend/src/components/ModelSelector.tsx +13 -14
- data/frontend/src/components/NotificationPanel.tsx +29 -33
- data/frontend/src/components/ObjectList.tsx +78 -0
- data/frontend/src/components/PaneSlot.tsx +30 -0
- data/frontend/src/components/SourcePane.tsx +202 -0
- data/frontend/src/components/SystemBar.tsx +74 -0
- data/frontend/src/components/Transcript.tsx +76 -0
- data/frontend/src/components/UsagePanel.tsx +27 -27
- data/frontend/src/components/Workspace.tsx +260 -0
- data/frontend/src/components/index.ts +10 -9
- data/frontend/src/hooks/useResize.ts +55 -0
- data/frontend/src/hooks/useWebSocket.ts +28 -0
- data/frontend/src/index.css +28 -10
- data/frontend/src/store/index.ts +4 -0
- data/frontend/src/types/index.ts +2 -0
- data/frontend/tailwind.config.js +28 -9
- data/lib/prompt_objects/capability.rb +23 -1
- data/lib/prompt_objects/connectors/mcp.rb +2 -16
- data/lib/prompt_objects/llm/openai_adapter.rb +22 -0
- data/lib/prompt_objects/mcp/tools/inspect_po.rb +1 -31
- data/lib/prompt_objects/mcp/tools/list_prompt_objects.rb +1 -6
- data/lib/prompt_objects/prompt_object.rb +126 -0
- data/lib/prompt_objects/server/api/routes.rb +3 -48
- data/lib/prompt_objects/server/public/assets/{index-xvyeb-5Z.js → index-D1myxE0l.js} +211 -211
- data/lib/prompt_objects/server/public/assets/index-DdCcwC-Z.css +1 -0
- data/lib/prompt_objects/server/public/index.html +7 -3
- data/lib/prompt_objects/server/websocket_handler.rb +23 -100
- data/lib/prompt_objects/server.rb +6 -62
- data/prompt_objects.gemspec +1 -1
- data/templates/arc-agi-1/primitives/find_objects.rb +1 -1
- data/templates/arc-agi-1/primitives/grid_diff.rb +2 -2
- data/templates/arc-agi-1/primitives/grid_info.rb +1 -1
- data/templates/arc-agi-1/primitives/grid_transform.rb +1 -1
- data/templates/arc-agi-1/primitives/render_grid.rb +1 -0
- data/templates/arc-agi-1/primitives/test_solution.rb +3 -0
- metadata +12 -13
- data/frontend/src/components/CapabilitiesPanel.tsx +0 -141
- data/frontend/src/components/ChatPanel.tsx +0 -296
- data/frontend/src/components/Dashboard.tsx +0 -83
- data/frontend/src/components/Header.tsx +0 -153
- data/frontend/src/components/MessageBus.tsx +0 -56
- data/frontend/src/components/POCard.tsx +0 -56
- data/frontend/src/components/PODetail.tsx +0 -124
- data/frontend/src/components/PromptPanel.tsx +0 -156
- data/frontend/src/components/SessionsPanel.tsx +0 -174
- data/frontend/src/components/ThreadsSidebar.tsx +0 -163
- data/lib/prompt_objects/server/public/assets/index-6y64NXFy.css +0 -1
|
@@ -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-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
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-
|
|
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:
|
|
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|
|
|
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|
|
|
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|
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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|
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
data/prompt_objects.gemspec
CHANGED
|
@@ -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],
|
|
@@ -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.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Werner
|
|
@@ -231,22 +231,21 @@ files:
|
|
|
231
231
|
- frontend/src/canvas/nodes/PONode.ts
|
|
232
232
|
- frontend/src/canvas/nodes/ToolCallNode.ts
|
|
233
233
|
- frontend/src/canvas/types.ts
|
|
234
|
-
- frontend/src/components/CapabilitiesPanel.tsx
|
|
235
|
-
- frontend/src/components/ChatPanel.tsx
|
|
236
234
|
- frontend/src/components/ContextMenu.tsx
|
|
237
|
-
- frontend/src/components/
|
|
238
|
-
- frontend/src/components/Header.tsx
|
|
235
|
+
- frontend/src/components/Inspector.tsx
|
|
239
236
|
- frontend/src/components/MarkdownMessage.tsx
|
|
240
|
-
- frontend/src/components/
|
|
237
|
+
- frontend/src/components/MethodList.tsx
|
|
241
238
|
- frontend/src/components/ModelSelector.tsx
|
|
242
239
|
- frontend/src/components/NotificationPanel.tsx
|
|
243
|
-
- frontend/src/components/
|
|
244
|
-
- frontend/src/components/
|
|
245
|
-
- frontend/src/components/
|
|
246
|
-
- frontend/src/components/
|
|
247
|
-
- frontend/src/components/
|
|
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
|
|
248
245
|
- frontend/src/components/UsagePanel.tsx
|
|
246
|
+
- frontend/src/components/Workspace.tsx
|
|
249
247
|
- frontend/src/components/index.ts
|
|
248
|
+
- frontend/src/hooks/useResize.ts
|
|
250
249
|
- frontend/src/hooks/useWebSocket.ts
|
|
251
250
|
- frontend/src/index.css
|
|
252
251
|
- frontend/src/main.tsx
|
|
@@ -293,8 +292,8 @@ files:
|
|
|
293
292
|
- lib/prompt_objects/server/api/routes.rb
|
|
294
293
|
- lib/prompt_objects/server/app.rb
|
|
295
294
|
- lib/prompt_objects/server/file_watcher.rb
|
|
296
|
-
- lib/prompt_objects/server/public/assets/index-
|
|
297
|
-
- lib/prompt_objects/server/public/assets/index-
|
|
295
|
+
- lib/prompt_objects/server/public/assets/index-D1myxE0l.js
|
|
296
|
+
- lib/prompt_objects/server/public/assets/index-DdCcwC-Z.css
|
|
298
297
|
- lib/prompt_objects/server/public/index.html
|
|
299
298
|
- lib/prompt_objects/server/websocket_handler.rb
|
|
300
299
|
- lib/prompt_objects/session/store.rb
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react'
|
|
2
|
-
import type { PromptObject, CapabilityInfo } from '../types'
|
|
3
|
-
|
|
4
|
-
interface CapabilitiesPanelProps {
|
|
5
|
-
po: PromptObject
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function CapabilitiesPanel({ po }: CapabilitiesPanelProps) {
|
|
9
|
-
const capabilities = po.capabilities || []
|
|
10
|
-
const universalCapabilities = po.universal_capabilities || []
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<div className="h-full overflow-auto p-4">
|
|
14
|
-
{/* Declared Capabilities */}
|
|
15
|
-
<div className="mb-6">
|
|
16
|
-
<h3 className="text-lg font-medium text-white mb-3">
|
|
17
|
-
Declared Capabilities
|
|
18
|
-
<span className="ml-2 text-sm text-gray-500">({capabilities.length})</span>
|
|
19
|
-
</h3>
|
|
20
|
-
|
|
21
|
-
{capabilities.length === 0 ? (
|
|
22
|
-
<div className="text-gray-500 text-sm py-4 px-3 bg-po-bg rounded-lg border border-po-border">
|
|
23
|
-
No capabilities declared. This PO can only use universal capabilities.
|
|
24
|
-
</div>
|
|
25
|
-
) : (
|
|
26
|
-
<div className="space-y-1">
|
|
27
|
-
{capabilities.map((cap) => (
|
|
28
|
-
<CapabilityItem key={cap.name} capability={cap} accent />
|
|
29
|
-
))}
|
|
30
|
-
</div>
|
|
31
|
-
)}
|
|
32
|
-
</div>
|
|
33
|
-
|
|
34
|
-
{/* Universal Capabilities */}
|
|
35
|
-
<div>
|
|
36
|
-
<h3 className="text-lg font-medium text-white mb-3">
|
|
37
|
-
Universal Capabilities
|
|
38
|
-
<span className="ml-2 text-sm text-gray-500">({universalCapabilities.length})</span>
|
|
39
|
-
</h3>
|
|
40
|
-
<p className="text-xs text-gray-500 mb-3">
|
|
41
|
-
Available to all Prompt Objects automatically.
|
|
42
|
-
</p>
|
|
43
|
-
|
|
44
|
-
<div className="space-y-1">
|
|
45
|
-
{universalCapabilities.map((cap) => (
|
|
46
|
-
<CapabilityItem key={cap.name} capability={cap} />
|
|
47
|
-
))}
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
interface CapabilityItemProps {
|
|
55
|
-
capability: CapabilityInfo
|
|
56
|
-
accent?: boolean // Use accent color for name (for declared caps)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function CapabilityItem({ capability, accent }: CapabilityItemProps) {
|
|
60
|
-
const [expanded, setExpanded] = useState(false)
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<div className="bg-po-bg border border-po-border rounded-lg overflow-hidden">
|
|
64
|
-
<button
|
|
65
|
-
onClick={() => setExpanded(!expanded)}
|
|
66
|
-
className="w-full px-3 py-2 flex items-center justify-between hover:bg-po-surface transition-colors"
|
|
67
|
-
>
|
|
68
|
-
<span className={`font-mono text-sm ${accent ? 'text-po-accent' : 'text-gray-300'}`}>
|
|
69
|
-
{capability.name}
|
|
70
|
-
</span>
|
|
71
|
-
<span className="text-gray-500 text-xs">{expanded ? '▼' : '▶'}</span>
|
|
72
|
-
</button>
|
|
73
|
-
{expanded && (
|
|
74
|
-
<div className="px-3 py-2 border-t border-po-border bg-po-surface space-y-3">
|
|
75
|
-
<p className="text-xs text-gray-400">{capability.description}</p>
|
|
76
|
-
|
|
77
|
-
{capability.parameters && (
|
|
78
|
-
<ParametersDisplay parameters={capability.parameters} />
|
|
79
|
-
)}
|
|
80
|
-
</div>
|
|
81
|
-
)}
|
|
82
|
-
</div>
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
interface ParametersDisplayProps {
|
|
87
|
-
parameters: Record<string, unknown>
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function ParametersDisplay({ parameters }: ParametersDisplayProps) {
|
|
91
|
-
const properties = (parameters.properties as Record<string, unknown>) || {}
|
|
92
|
-
const required = (parameters.required as string[]) || []
|
|
93
|
-
|
|
94
|
-
const propertyNames = Object.keys(properties)
|
|
95
|
-
|
|
96
|
-
if (propertyNames.length === 0) {
|
|
97
|
-
return null
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return (
|
|
101
|
-
<div>
|
|
102
|
-
<div className="text-xs text-gray-500 mb-2 font-medium">Parameters</div>
|
|
103
|
-
<div className="space-y-2">
|
|
104
|
-
{propertyNames.map((propName) => {
|
|
105
|
-
const prop = properties[propName] as Record<string, unknown>
|
|
106
|
-
const isRequired = required.includes(propName)
|
|
107
|
-
|
|
108
|
-
const propType = prop.type ? String(prop.type) : null
|
|
109
|
-
const propDescription = prop.description ? String(prop.description) : null
|
|
110
|
-
const propEnum = prop.enum as string[] | undefined
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<div key={propName} className="bg-po-bg rounded p-2">
|
|
114
|
-
<div className="flex items-center gap-2">
|
|
115
|
-
<span className="font-mono text-xs text-po-accent">{propName}</span>
|
|
116
|
-
{propType && (
|
|
117
|
-
<span className="text-xs text-gray-600">({propType})</span>
|
|
118
|
-
)}
|
|
119
|
-
{isRequired && (
|
|
120
|
-
<span className="text-xs text-red-400">required</span>
|
|
121
|
-
)}
|
|
122
|
-
</div>
|
|
123
|
-
{propDescription && (
|
|
124
|
-
<p className="text-xs text-gray-500 mt-1">{propDescription}</p>
|
|
125
|
-
)}
|
|
126
|
-
{propEnum && propEnum.length > 0 && (
|
|
127
|
-
<div className="mt-1 flex flex-wrap gap-1">
|
|
128
|
-
{propEnum.map((val) => (
|
|
129
|
-
<span key={val} className="text-xs bg-po-surface px-1.5 py-0.5 rounded text-gray-400">
|
|
130
|
-
{val}
|
|
131
|
-
</span>
|
|
132
|
-
))}
|
|
133
|
-
</div>
|
|
134
|
-
)}
|
|
135
|
-
</div>
|
|
136
|
-
)
|
|
137
|
-
})}
|
|
138
|
-
</div>
|
|
139
|
-
</div>
|
|
140
|
-
)
|
|
141
|
-
}
|