prompt_objects 0.4.0 → 0.6.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 +33 -0
- data/CLAUDE.md +113 -44
- data/README.md +140 -14
- data/frontend/index.html +5 -1
- data/frontend/src/App.tsx +72 -79
- 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/EnvDataPane.tsx +69 -0
- data/frontend/src/components/Inspector.tsx +263 -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 +70 -0
- data/frontend/src/index.css +27 -10
- data/frontend/src/store/index.ts +36 -0
- data/frontend/src/types/index.ts +13 -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/environment.rb +15 -0
- 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 +239 -7
- data/lib/prompt_objects/server/api/routes.rb +16 -48
- data/lib/prompt_objects/server/app.rb +14 -0
- data/lib/prompt_objects/server/public/assets/{index-xvyeb-5Z.js → index-DEPawnfZ.js} +206 -206
- data/lib/prompt_objects/server/public/assets/index-oMrRce1m.css +1 -0
- data/lib/prompt_objects/server/public/index.html +7 -3
- data/lib/prompt_objects/server/websocket_handler.rb +41 -98
- data/lib/prompt_objects/server.rb +6 -62
- data/lib/prompt_objects/session/store.rb +176 -4
- data/lib/prompt_objects/universal/delete_env_data.rb +70 -0
- data/lib/prompt_objects/universal/get_env_data.rb +64 -0
- data/lib/prompt_objects/universal/list_env_data.rb +61 -0
- data/lib/prompt_objects/universal/store_env_data.rb +87 -0
- data/lib/prompt_objects/universal/update_env_data.rb +88 -0
- data/lib/prompt_objects.rb +6 -1
- data/prompt_objects.gemspec +1 -1
- data/templates/arc-agi-1/objects/observer.md +4 -0
- data/templates/arc-agi-1/objects/solver.md +10 -1
- data/templates/arc-agi-1/objects/verifier.md +4 -0
- 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
- data/tools/thread-explorer.html +27 -0
- metadata +18 -16
- data/Gemfile.lock +0 -233
- data/IMPLEMENTATION_PLAN.md +0 -1073
- data/design-doc-v2.md +0 -1232
- 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
|
@@ -1,46 +1,46 @@
|
|
|
1
1
|
// Canvas visualization constants
|
|
2
2
|
|
|
3
|
-
// Colors (hex values matching po-* palette)
|
|
3
|
+
// Colors (hex values matching warm po-* palette)
|
|
4
4
|
export const COLORS = {
|
|
5
5
|
// Node colors
|
|
6
|
-
background:
|
|
7
|
-
surface:
|
|
8
|
-
border:
|
|
9
|
-
accent:
|
|
10
|
-
accentHover:
|
|
11
|
-
success:
|
|
12
|
-
warning:
|
|
13
|
-
error:
|
|
6
|
+
background: 0x1a1918,
|
|
7
|
+
surface: 0x222120,
|
|
8
|
+
border: 0x3d3a37,
|
|
9
|
+
accent: 0xd4952a,
|
|
10
|
+
accentHover: 0xe0a940,
|
|
11
|
+
success: 0x3b9a6e,
|
|
12
|
+
warning: 0xd4952a,
|
|
13
|
+
error: 0xc45c4a,
|
|
14
14
|
|
|
15
15
|
// Status colors
|
|
16
|
-
statusIdle:
|
|
17
|
-
statusThinking:
|
|
18
|
-
statusCallingTool:
|
|
16
|
+
statusIdle: 0x78726a,
|
|
17
|
+
statusThinking: 0xd4952a,
|
|
18
|
+
statusCallingTool: 0x3b9a6e,
|
|
19
19
|
|
|
20
20
|
// Canvas-specific
|
|
21
|
-
nodeFill:
|
|
22
|
-
nodeGlow:
|
|
23
|
-
toolCallFill:
|
|
24
|
-
arcColor:
|
|
25
|
-
particleColor:
|
|
26
|
-
gridColor:
|
|
21
|
+
nodeFill: 0x222120,
|
|
22
|
+
nodeGlow: 0xd4952a,
|
|
23
|
+
toolCallFill: 0x3b9a6e,
|
|
24
|
+
arcColor: 0xd4952a,
|
|
25
|
+
particleColor: 0xe0a940,
|
|
26
|
+
gridColor: 0x222120,
|
|
27
27
|
} as const
|
|
28
28
|
|
|
29
29
|
// CSS color strings (for CSS2DRenderer elements)
|
|
30
30
|
export const CSS_COLORS = {
|
|
31
|
-
accent: '#
|
|
32
|
-
accentHover: '#
|
|
33
|
-
warning: '#
|
|
34
|
-
success: '#
|
|
35
|
-
error: '#
|
|
36
|
-
textPrimary: '#
|
|
37
|
-
textSecondary: '#
|
|
38
|
-
textMuted: '#
|
|
39
|
-
surface: '#
|
|
40
|
-
border: '#
|
|
41
|
-
statusIdle: '#
|
|
42
|
-
statusThinking: '#
|
|
43
|
-
statusCallingTool: '#
|
|
31
|
+
accent: '#d4952a',
|
|
32
|
+
accentHover: '#e0a940',
|
|
33
|
+
warning: '#d4952a',
|
|
34
|
+
success: '#3b9a6e',
|
|
35
|
+
error: '#c45c4a',
|
|
36
|
+
textPrimary: '#e8e2da',
|
|
37
|
+
textSecondary: '#a8a29a',
|
|
38
|
+
textMuted: '#78726a',
|
|
39
|
+
surface: '#222120',
|
|
40
|
+
border: '#3d3a37',
|
|
41
|
+
statusIdle: '#78726a',
|
|
42
|
+
statusThinking: '#d4952a',
|
|
43
|
+
statusCallingTool: '#3b9a6e',
|
|
44
44
|
} as const
|
|
45
45
|
|
|
46
46
|
// Node dimensions
|
|
@@ -9,14 +9,14 @@ export function InspectorPanel() {
|
|
|
9
9
|
|
|
10
10
|
return (
|
|
11
11
|
<aside className="w-80 border-l border-po-border bg-po-surface overflow-hidden flex flex-col">
|
|
12
|
-
<div className="
|
|
13
|
-
<
|
|
12
|
+
<div className="h-8 bg-po-surface-2 border-b border-po-border flex items-center px-3">
|
|
13
|
+
<span className="text-2xs font-medium text-po-text-ghost uppercase tracking-wider flex-1">Inspector</span>
|
|
14
14
|
<button
|
|
15
15
|
onClick={() => useCanvasStore.getState().selectNode(null)}
|
|
16
|
-
className="text-
|
|
16
|
+
className="text-2xs text-po-text-ghost hover:text-po-text-secondary transition-colors duration-150"
|
|
17
17
|
title="Close inspector"
|
|
18
18
|
>
|
|
19
|
-
|
|
19
|
+
{'\u2715'}
|
|
20
20
|
</button>
|
|
21
21
|
</div>
|
|
22
22
|
<div className="flex-1 overflow-auto">
|
|
@@ -7,9 +7,9 @@ interface Props {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
const statusColors: Record<string, string> = {
|
|
10
|
-
idle: 'bg-
|
|
11
|
-
thinking: 'bg-po-
|
|
12
|
-
calling_tool: 'bg-po-
|
|
10
|
+
idle: 'bg-po-status-idle',
|
|
11
|
+
thinking: 'bg-po-status-active animate-pulse',
|
|
12
|
+
calling_tool: 'bg-po-status-calling animate-pulse',
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export function POInspector({ poName }: Props) {
|
|
@@ -20,7 +20,7 @@ export function POInspector({ poName }: Props) {
|
|
|
20
20
|
|
|
21
21
|
if (!po) {
|
|
22
22
|
return (
|
|
23
|
-
<div className="p-4 text-
|
|
23
|
+
<div className="p-4 text-po-text-ghost text-xs font-mono">
|
|
24
24
|
Prompt Object "{poName}" not found.
|
|
25
25
|
</div>
|
|
26
26
|
)
|
|
@@ -31,18 +31,18 @@ export function POInspector({ poName }: Props) {
|
|
|
31
31
|
{/* Header */}
|
|
32
32
|
<div>
|
|
33
33
|
<div className="flex items-center gap-2 mb-1">
|
|
34
|
-
<h3 className="text-
|
|
34
|
+
<h3 className="text-sm font-mono font-medium text-po-text-primary">{po.name}</h3>
|
|
35
35
|
<div className={`w-2 h-2 rounded-full ${statusColors[po.status] || statusColors.idle}`} />
|
|
36
36
|
</div>
|
|
37
|
-
<p className="text-
|
|
38
|
-
<span className="inline-block mt-1 text-
|
|
37
|
+
<p className="text-xs text-po-text-secondary">{po.description}</p>
|
|
38
|
+
<span className="inline-block mt-1 text-2xs text-po-text-ghost bg-po-surface-2 px-1.5 py-0.5 rounded font-mono">
|
|
39
39
|
{po.status}
|
|
40
40
|
</span>
|
|
41
41
|
</div>
|
|
42
42
|
|
|
43
43
|
{/* Capabilities */}
|
|
44
44
|
<div>
|
|
45
|
-
<h4 className="text-
|
|
45
|
+
<h4 className="text-2xs font-medium text-po-text-ghost uppercase tracking-wider mb-2">
|
|
46
46
|
Capabilities ({po.capabilities?.length || 0})
|
|
47
47
|
</h4>
|
|
48
48
|
<div className="space-y-1">
|
|
@@ -60,12 +60,12 @@ export function POInspector({ poName }: Props) {
|
|
|
60
60
|
|
|
61
61
|
{/* Sessions */}
|
|
62
62
|
<div>
|
|
63
|
-
<h4 className="text-
|
|
63
|
+
<h4 className="text-2xs font-medium text-po-text-ghost uppercase tracking-wider mb-2">
|
|
64
64
|
Sessions ({po.sessions?.length || 0})
|
|
65
65
|
</h4>
|
|
66
66
|
{po.current_session && (
|
|
67
|
-
<div className="text-xs text-
|
|
68
|
-
Current: <span className="text-
|
|
67
|
+
<div className="text-xs text-po-text-tertiary">
|
|
68
|
+
Current: <span className="text-po-text-secondary font-mono">{po.current_session.id.slice(0, 8)}...</span>
|
|
69
69
|
<span className="ml-2">({po.current_session.messages.length} messages)</span>
|
|
70
70
|
</div>
|
|
71
71
|
)}
|
|
@@ -74,7 +74,7 @@ export function POInspector({ poName }: Props) {
|
|
|
74
74
|
{/* Notifications */}
|
|
75
75
|
{notifications.length > 0 && (
|
|
76
76
|
<div>
|
|
77
|
-
<h4 className="text-
|
|
77
|
+
<h4 className="text-2xs font-medium text-po-warning uppercase tracking-wider mb-2">
|
|
78
78
|
Pending Requests ({notifications.length})
|
|
79
79
|
</h4>
|
|
80
80
|
<div className="space-y-2">
|
|
@@ -95,9 +95,9 @@ export function POInspector({ poName }: Props) {
|
|
|
95
95
|
selectPO(poName)
|
|
96
96
|
setCurrentView('dashboard')
|
|
97
97
|
}}
|
|
98
|
-
className="text-
|
|
98
|
+
className="text-xs text-po-accent hover:underline font-mono transition-colors duration-150"
|
|
99
99
|
>
|
|
100
|
-
Open
|
|
100
|
+
Open in browser view
|
|
101
101
|
</button>
|
|
102
102
|
</div>
|
|
103
103
|
)
|
|
@@ -107,17 +107,17 @@ function CapabilityItem({ name, description }: { name: string; description: stri
|
|
|
107
107
|
const [expanded, setExpanded] = useState(false)
|
|
108
108
|
|
|
109
109
|
return (
|
|
110
|
-
<div className="bg-po-
|
|
110
|
+
<div className="bg-po-surface-2 border border-po-border rounded overflow-hidden">
|
|
111
111
|
<button
|
|
112
112
|
onClick={() => setExpanded(!expanded)}
|
|
113
|
-
className="w-full px-
|
|
113
|
+
className="w-full px-2.5 py-1.5 flex items-center justify-between hover:bg-po-surface-3 transition-colors duration-150"
|
|
114
114
|
>
|
|
115
115
|
<span className="font-mono text-xs text-po-accent">{name}</span>
|
|
116
|
-
<span className="text-
|
|
116
|
+
<span className="text-po-text-ghost text-xs">{expanded ? '\u25BC' : '\u25B8'}</span>
|
|
117
117
|
</button>
|
|
118
118
|
{expanded && (
|
|
119
|
-
<div className="px-
|
|
120
|
-
<p className="text-xs text-
|
|
119
|
+
<div className="px-2.5 py-2 border-t border-po-border bg-po-surface">
|
|
120
|
+
<p className="text-xs text-po-text-secondary">{description}</p>
|
|
121
121
|
</div>
|
|
122
122
|
)}
|
|
123
123
|
</div>
|
|
@@ -152,16 +152,16 @@ function PromptSection({ prompt, onSave }: { prompt: string; onSave: (p: string)
|
|
|
152
152
|
return (
|
|
153
153
|
<div>
|
|
154
154
|
<div className="flex items-center justify-between mb-2">
|
|
155
|
-
<h4 className="text-
|
|
155
|
+
<h4 className="text-2xs font-medium text-po-text-ghost uppercase tracking-wider">Prompt</h4>
|
|
156
156
|
<button
|
|
157
157
|
onClick={() => {
|
|
158
158
|
if (isEditing && edited !== prompt) onSave(edited)
|
|
159
159
|
setIsEditing(!isEditing)
|
|
160
160
|
}}
|
|
161
|
-
className={`text-
|
|
161
|
+
className={`text-2xs px-1.5 py-0.5 rounded transition-colors duration-150 ${
|
|
162
162
|
isEditing
|
|
163
|
-
? 'bg-po-accent text-
|
|
164
|
-
: '
|
|
163
|
+
? 'bg-po-accent text-po-bg'
|
|
164
|
+
: 'text-po-text-tertiary hover:text-po-text-primary hover:bg-po-surface-2'
|
|
165
165
|
}`}
|
|
166
166
|
>
|
|
167
167
|
{isEditing ? 'Done' : 'Edit'}
|
|
@@ -174,12 +174,12 @@ function PromptSection({ prompt, onSave }: { prompt: string; onSave: (p: string)
|
|
|
174
174
|
setEdited(e.target.value)
|
|
175
175
|
debouncedSave(e.target.value)
|
|
176
176
|
}}
|
|
177
|
-
className="w-full h-40 bg-po-bg border border-po-border rounded p-2 text-xs text-
|
|
177
|
+
className="w-full h-40 bg-po-bg border border-po-border rounded p-2 text-xs text-po-text-primary font-mono resize-none focus:outline-none focus:border-po-accent"
|
|
178
178
|
spellCheck={false}
|
|
179
179
|
/>
|
|
180
180
|
) : (
|
|
181
|
-
<div className="bg-po-
|
|
182
|
-
<pre className="text-xs text-
|
|
181
|
+
<div className="bg-po-surface-2 border border-po-border rounded p-2 max-h-32 overflow-auto">
|
|
182
|
+
<pre className="text-xs text-po-text-secondary font-mono whitespace-pre-wrap">
|
|
183
183
|
{prompt || '(no prompt)'}
|
|
184
184
|
</pre>
|
|
185
185
|
</div>
|
|
@@ -199,19 +199,19 @@ function NotificationCard({
|
|
|
199
199
|
const [showCustom, setShowCustom] = useState(false)
|
|
200
200
|
|
|
201
201
|
return (
|
|
202
|
-
<div className="bg-po-
|
|
203
|
-
<span className="text-
|
|
202
|
+
<div className="bg-po-surface-2 border border-po-border rounded p-2">
|
|
203
|
+
<span className="text-2xs font-mono bg-po-warning text-po-bg px-1.5 py-0.5 rounded font-bold">
|
|
204
204
|
{notification.type}
|
|
205
205
|
</span>
|
|
206
|
-
<p className="text-xs text-
|
|
206
|
+
<p className="text-xs text-po-text-primary mt-1.5 mb-2">{notification.message}</p>
|
|
207
207
|
|
|
208
208
|
{notification.options.length > 0 && (
|
|
209
|
-
<div className="flex flex-wrap gap-1 mb-1">
|
|
209
|
+
<div className="flex flex-wrap gap-1.5 mb-1.5">
|
|
210
210
|
{notification.options.map((opt, i) => (
|
|
211
211
|
<button
|
|
212
212
|
key={i}
|
|
213
213
|
onClick={() => onRespond(opt)}
|
|
214
|
-
className="px-2 py-
|
|
214
|
+
className="px-2 py-0.5 text-xs bg-po-surface border border-po-border rounded hover:border-po-accent hover:text-po-accent transition-colors duration-150 text-po-text-secondary"
|
|
215
215
|
>
|
|
216
216
|
{opt}
|
|
217
217
|
</button>
|
|
@@ -220,13 +220,13 @@ function NotificationCard({
|
|
|
220
220
|
)}
|
|
221
221
|
|
|
222
222
|
{showCustom ? (
|
|
223
|
-
<div className="flex gap-1 mt-1">
|
|
223
|
+
<div className="flex gap-1.5 mt-1.5">
|
|
224
224
|
<input
|
|
225
225
|
type="text"
|
|
226
226
|
value={customInput}
|
|
227
227
|
onChange={(e) => setCustomInput(e.target.value)}
|
|
228
228
|
placeholder="Custom response..."
|
|
229
|
-
className="flex-1 bg-po-
|
|
229
|
+
className="flex-1 bg-po-bg border border-po-border rounded px-2 py-1 text-xs text-po-text-primary placeholder-po-text-ghost focus:outline-none focus:border-po-accent"
|
|
230
230
|
onKeyDown={(e) => {
|
|
231
231
|
if (e.key === 'Enter' && customInput.trim()) {
|
|
232
232
|
onRespond(customInput.trim())
|
|
@@ -244,7 +244,7 @@ function NotificationCard({
|
|
|
244
244
|
setShowCustom(false)
|
|
245
245
|
}
|
|
246
246
|
}}
|
|
247
|
-
className="px-2 py-1 text-xs bg-po-accent text-
|
|
247
|
+
className="px-2 py-1 text-xs bg-po-accent text-po-bg rounded font-medium"
|
|
248
248
|
>
|
|
249
249
|
Send
|
|
250
250
|
</button>
|
|
@@ -252,7 +252,7 @@ function NotificationCard({
|
|
|
252
252
|
) : (
|
|
253
253
|
<button
|
|
254
254
|
onClick={() => setShowCustom(true)}
|
|
255
|
-
className="text-
|
|
255
|
+
className="text-2xs text-po-text-ghost hover:text-po-text-secondary transition-colors duration-150 mt-1"
|
|
256
256
|
>
|
|
257
257
|
+ Custom
|
|
258
258
|
</button>
|
|
@@ -7,7 +7,7 @@ interface Props {
|
|
|
7
7
|
const statusColors: Record<string, string> = {
|
|
8
8
|
active: 'text-po-accent',
|
|
9
9
|
completed: 'text-po-success',
|
|
10
|
-
error: 'text-
|
|
10
|
+
error: 'text-po-error',
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export function ToolCallInspector({ toolCallId }: Props) {
|
|
@@ -15,7 +15,7 @@ export function ToolCallInspector({ toolCallId }: Props) {
|
|
|
15
15
|
|
|
16
16
|
if (!toolCall) {
|
|
17
17
|
return (
|
|
18
|
-
<div className="p-4 text-
|
|
18
|
+
<div className="p-4 text-po-text-ghost text-xs font-mono">
|
|
19
19
|
Tool call not found or has expired.
|
|
20
20
|
</div>
|
|
21
21
|
)
|
|
@@ -29,23 +29,23 @@ export function ToolCallInspector({ toolCallId }: Props) {
|
|
|
29
29
|
<div className="p-4 space-y-4">
|
|
30
30
|
{/* Header */}
|
|
31
31
|
<div>
|
|
32
|
-
<h3 className="text-
|
|
32
|
+
<h3 className="text-sm font-mono font-medium text-po-text-primary">{toolCall.toolName}</h3>
|
|
33
33
|
<div className="flex items-center gap-2 mt-1">
|
|
34
|
-
<span className={`text-xs font-medium ${statusColors[toolCall.status] || ''}`}>
|
|
34
|
+
<span className={`text-xs font-mono font-medium ${statusColors[toolCall.status] || ''}`}>
|
|
35
35
|
{toolCall.status}
|
|
36
36
|
</span>
|
|
37
|
-
<span className="text-
|
|
37
|
+
<span className="text-2xs text-po-text-ghost font-mono">{duration}</span>
|
|
38
38
|
</div>
|
|
39
|
-
<div className="text-xs text-
|
|
40
|
-
Called by: <span className="text-po-accent">{toolCall.callerPO}</span>
|
|
39
|
+
<div className="text-xs text-po-text-tertiary mt-1">
|
|
40
|
+
Called by: <span className="text-po-accent font-mono">{toolCall.callerPO}</span>
|
|
41
41
|
</div>
|
|
42
42
|
</div>
|
|
43
43
|
|
|
44
44
|
{/* Parameters */}
|
|
45
45
|
<div>
|
|
46
|
-
<h4 className="text-
|
|
47
|
-
<div className="bg-po-
|
|
48
|
-
<pre className="text-xs text-
|
|
46
|
+
<h4 className="text-2xs font-medium text-po-text-ghost uppercase tracking-wider mb-2">Parameters</h4>
|
|
47
|
+
<div className="bg-po-surface-2 border border-po-border rounded p-2.5 overflow-auto max-h-48">
|
|
48
|
+
<pre className="text-xs text-po-text-secondary font-mono whitespace-pre-wrap">
|
|
49
49
|
{JSON.stringify(toolCall.params, null, 2)}
|
|
50
50
|
</pre>
|
|
51
51
|
</div>
|
|
@@ -54,9 +54,9 @@ export function ToolCallInspector({ toolCallId }: Props) {
|
|
|
54
54
|
{/* Result */}
|
|
55
55
|
{toolCall.result && (
|
|
56
56
|
<div>
|
|
57
|
-
<h4 className="text-
|
|
58
|
-
<div className="bg-po-
|
|
59
|
-
<pre className="text-xs text-
|
|
57
|
+
<h4 className="text-2xs font-medium text-po-text-ghost uppercase tracking-wider mb-2">Result</h4>
|
|
58
|
+
<div className="bg-po-surface-2 border border-po-border rounded p-2.5 overflow-auto max-h-64">
|
|
59
|
+
<pre className="text-xs text-po-text-secondary font-mono whitespace-pre-wrap">
|
|
60
60
|
{toolCall.result}
|
|
61
61
|
</pre>
|
|
62
62
|
</div>
|
|
@@ -63,8 +63,8 @@ const STATUS_CSS_COLORS: Record<POStatus, string> = {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Color for when this PO is being called by another PO (delegation)
|
|
66
|
-
const DELEGATED_COLOR =
|
|
67
|
-
const DELEGATED_CSS_COLOR = '#
|
|
66
|
+
const DELEGATED_COLOR = 0x5a8fc2 // steel blue (matches po-status-delegated)
|
|
67
|
+
const DELEGATED_CSS_COLOR = '#5a8fc2'
|
|
68
68
|
|
|
69
69
|
export class PONode {
|
|
70
70
|
readonly id: string
|
|
@@ -35,7 +35,6 @@ export function ContextMenu({ x, y, items, onClose }: ContextMenuProps) {
|
|
|
35
35
|
}
|
|
36
36
|
}, [onClose])
|
|
37
37
|
|
|
38
|
-
// Adjust position to stay within viewport
|
|
39
38
|
const adjustedStyle = {
|
|
40
39
|
top: y,
|
|
41
40
|
left: x,
|
|
@@ -44,7 +43,7 @@ export function ContextMenu({ x, y, items, onClose }: ContextMenuProps) {
|
|
|
44
43
|
return (
|
|
45
44
|
<div
|
|
46
45
|
ref={menuRef}
|
|
47
|
-
className="fixed z-50 bg-po-surface border border-po-border rounded
|
|
46
|
+
className="fixed z-50 bg-po-surface-2 border border-po-border rounded shadow-xl py-0.5 min-w-[140px]"
|
|
48
47
|
style={adjustedStyle}
|
|
49
48
|
>
|
|
50
49
|
{items.map((item, idx) => (
|
|
@@ -54,8 +53,10 @@ export function ContextMenu({ x, y, items, onClose }: ContextMenuProps) {
|
|
|
54
53
|
item.onClick()
|
|
55
54
|
onClose()
|
|
56
55
|
}}
|
|
57
|
-
className={`w-full text-left px-
|
|
58
|
-
item.danger
|
|
56
|
+
className={`w-full text-left px-2.5 py-1.5 text-xs transition-colors duration-150 flex items-center gap-1.5 ${
|
|
57
|
+
item.danger
|
|
58
|
+
? 'text-po-error hover:bg-po-surface-3'
|
|
59
|
+
: 'text-po-text-secondary hover:bg-po-surface-3 hover:text-po-text-primary'
|
|
59
60
|
}`}
|
|
60
61
|
>
|
|
61
62
|
{item.icon && <span>{item.icon}</span>}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react'
|
|
2
|
+
import { useStore, useEnvData } from '../store'
|
|
3
|
+
import type { EnvDataEntry } from '../types'
|
|
4
|
+
|
|
5
|
+
interface EnvDataPaneProps {
|
|
6
|
+
sessionId: string | undefined
|
|
7
|
+
requestEnvData: (sessionId: string) => void
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function EnvDataPane({ sessionId, requestEnvData }: EnvDataPaneProps) {
|
|
11
|
+
const sessionRootMap = useStore((s) => s.sessionRootMap)
|
|
12
|
+
const rootThreadId = sessionId ? sessionRootMap[sessionId] : undefined
|
|
13
|
+
const entries = useEnvData(rootThreadId)
|
|
14
|
+
const [expandedKey, setExpandedKey] = useState<string | null>(null)
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (sessionId) {
|
|
18
|
+
requestEnvData(sessionId)
|
|
19
|
+
}
|
|
20
|
+
}, [sessionId, requestEnvData])
|
|
21
|
+
|
|
22
|
+
if (entries.length === 0) {
|
|
23
|
+
return (
|
|
24
|
+
<div className="h-full flex items-center justify-center">
|
|
25
|
+
<span className="font-mono text-xs text-po-text-ghost">No shared data</span>
|
|
26
|
+
</div>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div className="h-full overflow-auto px-2 py-1">
|
|
32
|
+
{entries.map((entry) => (
|
|
33
|
+
<EnvDataRow
|
|
34
|
+
key={entry.key}
|
|
35
|
+
entry={entry}
|
|
36
|
+
expanded={expandedKey === entry.key}
|
|
37
|
+
onToggle={() => setExpandedKey(expandedKey === entry.key ? null : entry.key)}
|
|
38
|
+
/>
|
|
39
|
+
))}
|
|
40
|
+
</div>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function EnvDataRow({ entry, expanded, onToggle }: { entry: EnvDataEntry; expanded: boolean; onToggle: () => void }) {
|
|
45
|
+
return (
|
|
46
|
+
<div className="border-b border-po-border last:border-b-0">
|
|
47
|
+
<button
|
|
48
|
+
onClick={onToggle}
|
|
49
|
+
className="w-full text-left px-1.5 py-1.5 hover:bg-po-surface-3 transition-colors duration-150 flex items-center gap-2"
|
|
50
|
+
>
|
|
51
|
+
<span className="text-2xs text-po-text-ghost">{expanded ? '▼' : '▶'}</span>
|
|
52
|
+
<span className="font-mono text-sm text-po-accent truncate">{entry.key}</span>
|
|
53
|
+
<span className="text-xs text-po-text-ghost truncate flex-1">{entry.short_description}</span>
|
|
54
|
+
<span className="text-xs text-po-text-ghost flex-shrink-0">{entry.stored_by}</span>
|
|
55
|
+
</button>
|
|
56
|
+
{expanded && (
|
|
57
|
+
<div className="px-2 pb-2">
|
|
58
|
+
<div className="text-xs text-po-text-ghost mb-1">
|
|
59
|
+
stored by <span className="text-po-text-secondary">{entry.stored_by}</span>
|
|
60
|
+
{entry.updated_at && <> · {new Date(entry.updated_at).toLocaleTimeString()}</>}
|
|
61
|
+
</div>
|
|
62
|
+
<pre className="font-mono text-xs text-po-text-primary bg-po-surface-1 rounded p-2 overflow-auto max-h-40 whitespace-pre-wrap break-all">
|
|
63
|
+
{typeof entry.value === 'string' ? entry.value : JSON.stringify(entry.value, null, 2)}
|
|
64
|
+
</pre>
|
|
65
|
+
</div>
|
|
66
|
+
)}
|
|
67
|
+
</div>
|
|
68
|
+
)
|
|
69
|
+
}
|