supervaizer 0.9.7__py3-none-any.whl → 0.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. supervaizer/__init__.py +11 -2
  2. supervaizer/__version__.py +1 -1
  3. supervaizer/account.py +4 -0
  4. supervaizer/account_service.py +7 -1
  5. supervaizer/admin/routes.py +46 -7
  6. supervaizer/admin/static/js/job-start-form.js +373 -0
  7. supervaizer/admin/templates/agents.html +74 -0
  8. supervaizer/admin/templates/agents_grid.html +5 -3
  9. supervaizer/admin/templates/job_start_test.html +109 -0
  10. supervaizer/admin/templates/navigation.html +11 -1
  11. supervaizer/admin/templates/supervaize_instructions.html +212 -0
  12. supervaizer/agent.py +165 -25
  13. supervaizer/case.py +46 -14
  14. supervaizer/cli.py +248 -8
  15. supervaizer/common.py +45 -4
  16. supervaizer/deploy/__init__.py +16 -0
  17. supervaizer/deploy/cli.py +296 -0
  18. supervaizer/deploy/commands/__init__.py +9 -0
  19. supervaizer/deploy/commands/clean.py +294 -0
  20. supervaizer/deploy/commands/down.py +119 -0
  21. supervaizer/deploy/commands/local.py +460 -0
  22. supervaizer/deploy/commands/plan.py +167 -0
  23. supervaizer/deploy/commands/status.py +169 -0
  24. supervaizer/deploy/commands/up.py +281 -0
  25. supervaizer/deploy/docker.py +370 -0
  26. supervaizer/deploy/driver_factory.py +42 -0
  27. supervaizer/deploy/drivers/__init__.py +39 -0
  28. supervaizer/deploy/drivers/aws_app_runner.py +607 -0
  29. supervaizer/deploy/drivers/base.py +196 -0
  30. supervaizer/deploy/drivers/cloud_run.py +570 -0
  31. supervaizer/deploy/drivers/do_app_platform.py +504 -0
  32. supervaizer/deploy/health.py +404 -0
  33. supervaizer/deploy/state.py +210 -0
  34. supervaizer/deploy/templates/Dockerfile.template +44 -0
  35. supervaizer/deploy/templates/debug_env.py +69 -0
  36. supervaizer/deploy/templates/docker-compose.yml.template +37 -0
  37. supervaizer/deploy/templates/dockerignore.template +66 -0
  38. supervaizer/deploy/templates/entrypoint.sh +20 -0
  39. supervaizer/deploy/utils.py +41 -0
  40. supervaizer/examples/{controller-template.py → controller_template.py} +5 -4
  41. supervaizer/job.py +18 -5
  42. supervaizer/job_service.py +6 -5
  43. supervaizer/parameter.py +61 -1
  44. supervaizer/protocol/__init__.py +2 -2
  45. supervaizer/protocol/a2a/routes.py +1 -1
  46. supervaizer/routes.py +262 -12
  47. supervaizer/server.py +5 -11
  48. supervaizer/utils/__init__.py +16 -0
  49. supervaizer/utils/version_check.py +56 -0
  50. {supervaizer-0.9.7.dist-info → supervaizer-0.10.0.dist-info}/METADATA +105 -34
  51. supervaizer-0.10.0.dist-info/RECORD +76 -0
  52. {supervaizer-0.9.7.dist-info → supervaizer-0.10.0.dist-info}/WHEEL +1 -1
  53. supervaizer/protocol/acp/__init__.py +0 -21
  54. supervaizer/protocol/acp/model.py +0 -198
  55. supervaizer/protocol/acp/routes.py +0 -74
  56. supervaizer-0.9.7.dist-info/RECORD +0 -50
  57. {supervaizer-0.9.7.dist-info → supervaizer-0.10.0.dist-info}/entry_points.txt +0 -0
  58. {supervaizer-0.9.7.dist-info → supervaizer-0.10.0.dist-info}/licenses/LICENSE.md +0 -0
@@ -126,6 +126,43 @@
126
126
  </div>
127
127
  </div>
128
128
 
129
+ <!-- Instructions Modal -->
130
+ <div id="instructions-modal"
131
+ class="fixed inset-0 z-50"
132
+ x-data="{ open: false, agentSlug: '', instructionsPath: 'supervaize_instructions.html' }"
133
+ x-show="open"
134
+ x-cloak
135
+ @open-instructions.window="agentSlug = $event.detail.slug; instructionsPath = $event.detail.instructionsPath || 'supervaize_instructions.html'; open = true">
136
+ <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
137
+ <div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" @click="open = false"></div>
138
+
139
+ <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-6xl sm:w-full">
140
+ <div class="bg-white px-4 pt-5 pb-4 sm:p-6">
141
+ <div class="flex items-center justify-between mb-4">
142
+ <h3 class="text-lg leading-6 font-medium text-gray-900">Supervaize Instructions</h3>
143
+ <button
144
+ @click="open = false"
145
+ class="bg-white rounded-md text-gray-400 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
146
+ >
147
+ <span class="sr-only">Close</span>
148
+ <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
149
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
150
+ </svg>
151
+ </button>
152
+ </div>
153
+ <div class="mt-4" style="height: 80vh; overflow-y: auto;">
154
+ <iframe
155
+ id="instructions-iframe"
156
+ x-bind:src="agentSlug && instructionsPath ? `/supervaizer/agents/${agentSlug}/${instructionsPath}` : ''"
157
+ class="w-full h-full border-0"
158
+ style="min-height: 600px;"
159
+ ></iframe>
160
+ </div>
161
+ </div>
162
+ </div>
163
+ </div>
164
+ </div>
165
+
129
166
  <script>
130
167
  // Handle agent modal
131
168
  document.body.addEventListener('htmx:afterRequest', function(e) {
@@ -151,6 +188,43 @@
151
188
  htmx.ajax('GET', `/admin/api/agents/${encodeURIComponent(agentSlug)}`, {target: '#agent-modal-content'});
152
189
  };
153
190
 
191
+ window.showAgentInstructions = function(agentSlug, instructionsPath) {
192
+ console.log('showAgentInstructions called with slug:', agentSlug, 'path:', instructionsPath);
193
+
194
+ if (!agentSlug || agentSlug.trim() === '') {
195
+ console.error('Agent slug is missing or empty');
196
+ return;
197
+ }
198
+
199
+ // Default instructions path if not provided
200
+ instructionsPath = instructionsPath || 'supervaize_instructions.html';
201
+
202
+ const modal = document.getElementById('instructions-modal');
203
+ if (!modal) {
204
+ console.error('Instructions modal not found');
205
+ return;
206
+ }
207
+
208
+ // Dispatch Alpine.js event to open modal (Alpine will handle iframe src reactively)
209
+ const event = new CustomEvent('open-instructions', {
210
+ detail: { slug: agentSlug, instructionsPath: instructionsPath },
211
+ bubbles: true
212
+ });
213
+ modal.dispatchEvent(event);
214
+ console.log('Dispatched open-instructions event with slug:', agentSlug, 'path:', instructionsPath);
215
+
216
+ // Also try direct Alpine.js access as fallback
217
+ if (modal._x_dataStack && modal._x_dataStack[0]) {
218
+ const alpineData = modal._x_dataStack[0];
219
+ alpineData.agentSlug = agentSlug;
220
+ alpineData.instructionsPath = instructionsPath;
221
+ alpineData.open = true;
222
+ console.log('Modal opened via direct Alpine.js access');
223
+ } else {
224
+ console.warn('Alpine.js data not available, modal may not open');
225
+ }
226
+ };
227
+
154
228
  window.editAgent = function(agentId) {
155
229
  console.log('Edit agent:', agentId);
156
230
  // Future: htmx.ajax('GET', `/admin/api/agents/${agentId}/edit`, {target: '#agent-modal-content'});
@@ -33,7 +33,7 @@
33
33
  </div>
34
34
  {% endif %}
35
35
  <div class="ml-3">
36
- <h3 class="text-lg font-medium text-gray-900">{{ agent.name }}</h3>
36
+ <h3 class="text-lg font-medium text-gray-900">{{ agent.name }} </h3>
37
37
  <p class="text-sm text-gray-500 capitalize">{{ agent.type or "conversational" }}</p>
38
38
  </div>
39
39
  </div>
@@ -56,10 +56,12 @@
56
56
  </div>
57
57
  </div>
58
58
  <div class="mt-6 flex space-x-3">
59
- <button onclick="showAgentDetails('{{ agent.slug }}')" class="flex-1 bg-blue-50 text-blue-700 hover:bg-blue-100 px-3 py-2 rounded-md text-sm font-medium transition-colors">
59
+ {% set agent_slug = agent.slug if agent.slug else (agent.api_path.replace('/agents/', '').rstrip('/') if agent.api_path and agent.api_path.startswith('/agents/') else '') %}
60
+ {% set instructions_path = agent.instructions_path if agent.instructions_path else 'supervaize_instructions.html' %}
61
+ <button onclick="showAgentInstructions('{{ agent_slug }}', '{{ instructions_path }}')" class="flex-1 bg-blue-50 text-blue-700 hover:bg-blue-100 px-3 py-2 rounded-md text-sm font-medium transition-colors">
60
62
  View
61
63
  </button>
62
- <button onclick="editAgent('{{ agent.slug }}')" class="flex-1 bg-gray-50 text-gray-700 hover:bg-gray-100 px-3 py-2 rounded-md text-sm font-medium transition-colors">
64
+ <button onclick="showAgentDetails('{{ agent_slug }}')" class="flex-1 bg-gray-50 text-gray-700 hover:bg-gray-100 px-3 py-2 rounded-md text-sm font-medium transition-colors">
63
65
  Configure
64
66
  </button>
65
67
  </div>
@@ -0,0 +1,109 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div class="max-w-4xl mx-auto">
5
+ <div class="bg-white shadow rounded-lg p-6">
6
+ <h1 class="text-2xl font-bold text-gray-900 mb-6">Job Start Form Test</h1>
7
+
8
+ <!-- Validation Errors Container -->
9
+ <div id="validation-errors" class="mb-6"></div>
10
+
11
+ <!-- Agent Parameter Errors Container -->
12
+ <div id="agent-parameter-errors" class="mb-6"></div>
13
+
14
+ <!-- Job Start Form -->
15
+ <form data-job-start method="POST" class="space-y-6">
16
+ <!-- Job Fields -->
17
+ <div class="space-y-4">
18
+ <h3 class="text-lg font-medium text-gray-900">Job Parameters</h3>
19
+
20
+ <div>
21
+ <label for="company_name" class="block text-sm font-medium text-gray-700">
22
+ Company Name *
23
+ </label>
24
+ <input
25
+ type="text"
26
+ id="company_name"
27
+ name="company_name"
28
+ required
29
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
30
+ placeholder="Enter company name"
31
+ >
32
+ </div>
33
+
34
+ <div>
35
+ <label for="max_results" class="block text-sm font-medium text-gray-700">
36
+ Max Results *
37
+ </label>
38
+ <input
39
+ type="number"
40
+ id="max_results"
41
+ name="max_results"
42
+ required
43
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
44
+ placeholder="Enter maximum results"
45
+ >
46
+ </div>
47
+
48
+ <div>
49
+ <label for="subscribe_updates" class="block text-sm font-medium text-gray-700">
50
+ Subscribe to Updates
51
+ </label>
52
+ <input
53
+ type="checkbox"
54
+ id="subscribe_updates"
55
+ name="subscribe_updates"
56
+ class="mt-1 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
57
+ >
58
+ <span class="ml-2 text-sm text-gray-600">Receive email updates about this job</span>
59
+ </div>
60
+ </div>
61
+
62
+ <!-- Hidden Fields for Testing -->
63
+ <input type="hidden" name="encrypted_agent_parameters" value="test_encrypted_params">
64
+ <input type="hidden" name="api_key" value="{{ api_key }}">
65
+
66
+ <!-- Submit Button -->
67
+ <div class="flex justify-end">
68
+ <button
69
+ type="submit"
70
+ class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
71
+ >
72
+ Start Job
73
+ </button>
74
+ </div>
75
+ </form>
76
+ </div>
77
+ </div>
78
+
79
+ <script>
80
+ // Initialize JobStartForm when the page loads
81
+ document.addEventListener('DOMContentLoaded', function() {
82
+ // Wait for JobStartForm class to be available
83
+ function waitForJobStartForm() {
84
+ if (typeof window.JobStartForm !== 'undefined') {
85
+ console.log('JobStartForm class found, initializing...');
86
+
87
+ // Initialize the form with the current agent path
88
+ const form = new JobStartForm('/test-agent');
89
+
90
+ // Set up callbacks
91
+ form.setOnJobStarted(function(jobData) {
92
+ console.log('Job started successfully:', jobData);
93
+ });
94
+
95
+ form.setOnJobError(function(error) {
96
+ console.error('Job failed:', error);
97
+ });
98
+
99
+ console.log('JobStartForm initialized successfully');
100
+ } else {
101
+ console.log('JobStartForm class not ready yet, waiting...');
102
+ setTimeout(waitForJobStartForm, 100);
103
+ }
104
+ }
105
+
106
+ waitForJobStartForm();
107
+ });
108
+ </script>
109
+ {% endblock %}
@@ -83,6 +83,14 @@
83
83
  class="absolute left-0 mt-2 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-50"
84
84
  x-cloak>
85
85
  <div class="py-1">
86
+ <a href="https://doc.supervaize.com/docs/category/supervaizer-controller" target="_blank" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors">
87
+ Supervaizer Doc
88
+ <svg class="inline ml-1 h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
89
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
90
+ </svg>
91
+ </a>
92
+ <div class="border-t border-gray-200 my-1"></div>
93
+ <div class="px-4 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wider">API Documentation</div>
86
94
  <a href="/docs" target="_blank" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors">
87
95
  Swagger API
88
96
  <svg class="inline ml-1 h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -110,7 +118,7 @@
110
118
 
111
119
  <!-- Right side -->
112
120
  <div class="flex items-center space-x-4">
113
- <span class="text-sm text-gray-500">API {{ api_version }}</span>
121
+ <span class="text-sm text-gray-500">{{ api_version }}</span>
114
122
 
115
123
  <!-- Mobile menu button -->
116
124
  <button @click="mobileMenuOpen = !mobileMenuOpen" class="sm:hidden inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100">
@@ -142,6 +150,8 @@
142
150
  <!-- Documentation section -->
143
151
  <div class="pl-3 pr-4 py-2">
144
152
  <div class="text-base font-medium text-gray-700 mb-2">Documentation</div>
153
+ <a href="https://doc.supervaize.com/docs/category/supervaizer-controller" target="_blank" class="block pl-4 py-1 text-sm text-gray-500 hover:text-gray-700">Supervaizer Controller</a>
154
+ <div class="pl-4 py-1 text-xs font-semibold text-gray-500 uppercase tracking-wider">API Documentation</div>
145
155
  <a href="/docs" target="_blank" class="block pl-4 py-1 text-sm text-gray-500 hover:text-gray-700">Swagger API</a>
146
156
  <a href="/redoc" target="_blank" class="block pl-4 py-1 text-sm text-gray-500 hover:text-gray-700">ReDoc</a>
147
157
  <a href="https://github.com/supervaize/supervaizer-controller" target="_blank" class="block pl-4 py-1 text-sm text-gray-500 hover:text-gray-700">Supervaizer GitHub</a>
@@ -0,0 +1,212 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Supervaize Instructions - {{ registration_info.name }}</title>
7
+
8
+ <!-- Tailwind CSS -->
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+
11
+ <style>
12
+ pre {
13
+ white-space: pre-wrap;
14
+ word-wrap: break-word;
15
+ }
16
+ .json-key {
17
+ color: #0369a1;
18
+ font-weight: 600;
19
+ }
20
+ .json-string {
21
+ color: #059669;
22
+ }
23
+ .json-number {
24
+ color: #dc2626;
25
+ }
26
+ .json-boolean {
27
+ color: #7c3aed;
28
+ }
29
+ .json-null {
30
+ color: #6b7280;
31
+ }
32
+ </style>
33
+ </head>
34
+ <body class="bg-gray-50 min-h-screen">
35
+ <div class="max-w-4xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
36
+ <!-- Header -->
37
+ <div class="bg-white shadow rounded-lg mb-6 p-6">
38
+ <h1 class="text-3xl font-bold text-gray-900 mb-2">{{ registration_info.name }}</h1>
39
+ {% if registration_info.description %}
40
+ <p class="text-lg text-gray-600">{{ registration_info.description }}</p>
41
+ {% endif %}
42
+ {% if registration_info.version %}
43
+ <p class="text-sm text-gray-500 mt-2">Version: {{ registration_info.version }}</p>
44
+ {% endif %}
45
+ </div>
46
+
47
+ <!-- Basic Information -->
48
+ <div class="bg-white shadow rounded-lg mb-6 p-6">
49
+ <h2 class="text-xl font-semibold text-gray-900 mb-4">Agent Information</h2>
50
+ <dl class="grid grid-cols-1 gap-4 sm:grid-cols-2">
51
+ {% if registration_info.id %}
52
+ <div>
53
+ <dt class="text-sm font-medium text-gray-500">ID</dt>
54
+ <dd class="mt-1 text-sm text-gray-900">{{ registration_info.id }}</dd>
55
+ </div>
56
+ {% endif %}
57
+ {% if registration_info.api_path %}
58
+ <div>
59
+ <dt class="text-sm font-medium text-gray-500">API Path</dt>
60
+ <dd class="mt-1 text-sm text-gray-900 font-mono">{{ registration_info.api_path }}</dd>
61
+ </div>
62
+ {% endif %}
63
+ {% if registration_info.author %}
64
+ <div>
65
+ <dt class="text-sm font-medium text-gray-500">Author</dt>
66
+ <dd class="mt-1 text-sm text-gray-900">{{ registration_info.author }}</dd>
67
+ </div>
68
+ {% endif %}
69
+ {% if registration_info.developer %}
70
+ <div>
71
+ <dt class="text-sm font-medium text-gray-500">Developer</dt>
72
+ <dd class="mt-1 text-sm text-gray-900">{{ registration_info.developer }}</dd>
73
+ </div>
74
+ {% endif %}
75
+ {% if registration_info.maintainer %}
76
+ <div>
77
+ <dt class="text-sm font-medium text-gray-500">Maintainer</dt>
78
+ <dd class="mt-1 text-sm text-gray-900">{{ registration_info.maintainer }}</dd>
79
+ </div>
80
+ {% endif %}
81
+ {% if registration_info.editor %}
82
+ <div>
83
+ <dt class="text-sm font-medium text-gray-500">Editor</dt>
84
+ <dd class="mt-1 text-sm text-gray-900">{{ registration_info.editor }}</dd>
85
+ </div>
86
+ {% endif %}
87
+ {% if registration_info.max_execution_time %}
88
+ <div>
89
+ <dt class="text-sm font-medium text-gray-500">Max Execution Time</dt>
90
+ <dd class="mt-1 text-sm text-gray-900">{{ registration_info.max_execution_time }} seconds</dd>
91
+ </div>
92
+ {% endif %}
93
+ </dl>
94
+ </div>
95
+
96
+ <!-- Tags -->
97
+ {% if registration_info.tags %}
98
+ <div class="bg-white shadow rounded-lg mb-6 p-6">
99
+ <h2 class="text-xl font-semibold text-gray-900 mb-4">Tags</h2>
100
+ <div class="flex flex-wrap gap-2">
101
+ {% for tag in registration_info.tags %}
102
+ <span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-blue-100 text-blue-800">
103
+ {{ tag }}
104
+ </span>
105
+ {% endfor %}
106
+ </div>
107
+ </div>
108
+ {% endif %}
109
+
110
+ <!-- Methods -->
111
+ {% if registration_info.methods %}
112
+ <div class="bg-white shadow rounded-lg mb-6 p-6">
113
+ <h2 class="text-xl font-semibold text-gray-900 mb-4">Available Methods</h2>
114
+ <div class="space-y-4">
115
+ {% if registration_info.methods.job_start %}
116
+ <div class="border-l-4 border-green-500 pl-4">
117
+ <h3 class="font-medium text-gray-900">Job Start</h3>
118
+ {% if registration_info.methods.job_start.description %}
119
+ <p class="text-sm text-gray-600 mt-1">{{ registration_info.methods.job_start.description }}</p>
120
+ {% endif %}
121
+ </div>
122
+ {% endif %}
123
+ {% if registration_info.methods.job_stop %}
124
+ <div class="border-l-4 border-red-500 pl-4">
125
+ <h3 class="font-medium text-gray-900">Job Stop</h3>
126
+ {% if registration_info.methods.job_stop.description %}
127
+ <p class="text-sm text-gray-600 mt-1">{{ registration_info.methods.job_stop.description }}</p>
128
+ {% endif %}
129
+ </div>
130
+ {% endif %}
131
+ {% if registration_info.methods.job_status %}
132
+ <div class="border-l-4 border-blue-500 pl-4">
133
+ <h3 class="font-medium text-gray-900">Job Status</h3>
134
+ {% if registration_info.methods.job_status.description %}
135
+ <p class="text-sm text-gray-600 mt-1">{{ registration_info.methods.job_status.description }}</p>
136
+ {% endif %}
137
+ </div>
138
+ {% endif %}
139
+ {% if registration_info.methods.chat %}
140
+ <div class="border-l-4 border-purple-500 pl-4">
141
+ <h3 class="font-medium text-gray-900">Chat</h3>
142
+ {% if registration_info.methods.chat.description %}
143
+ <p class="text-sm text-gray-600 mt-1">{{ registration_info.methods.chat.description }}</p>
144
+ {% endif %}
145
+ </div>
146
+ {% endif %}
147
+ {% if registration_info.methods.custom %}
148
+ {% for method_name, method_info in registration_info.methods.custom.items() %}
149
+ <div class="border-l-4 border-yellow-500 pl-4">
150
+ <h3 class="font-medium text-gray-900">{{ method_name }}</h3>
151
+ {% if method_info.description %}
152
+ <p class="text-sm text-gray-600 mt-1">{{ method_info.description }}</p>
153
+ {% endif %}
154
+ </div>
155
+ {% endfor %}
156
+ {% endif %}
157
+ </div>
158
+ </div>
159
+ {% endif %}
160
+ <!-- Parameters Setup -->
161
+ <div class="bg-white shadow rounded-lg mb-6 p-6">
162
+ <h2 class="text-xl font-semibold text-gray-900 mb-4">Parameters</h2>
163
+ {% if registration_info.parameters_setup %}
164
+ <div class="overflow-x-auto">
165
+ <table class="min-w-full divide-y divide-gray-200">
166
+ <thead class="bg-gray-50">
167
+ <tr>
168
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th>
169
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Description</th>
170
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th>
171
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Required</th>
172
+ </tr>
173
+ </thead>
174
+ <tbody class="bg-white divide-y divide-gray-200">
175
+ {% for param in registration_info.parameters_setup %}
176
+ <tr>
177
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">{{ param.name }}</td>
178
+ <td class="px-6 py-4 text-sm text-gray-500">{{ param.description or "-" }}</td>
179
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
180
+ {% if param.is_secret %}
181
+ <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">Secret</span>
182
+ {% else %}
183
+ <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">Standard</span>
184
+ {% endif %}
185
+ </td>
186
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
187
+ {% if param.is_required %}
188
+ <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800">Required</span>
189
+ {% else %}
190
+ <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">Optional</span>
191
+ {% endif %}
192
+ </td>
193
+ </tr>
194
+ {% endfor %}
195
+ </tbody>
196
+ </table>
197
+ </div>
198
+ {% else %}
199
+ <p class="text-sm text-gray-500">No parameters configured.</p>
200
+ {% endif %}
201
+ </div>
202
+
203
+ <!-- Custom instructions -->
204
+ <div class="bg-white shadow rounded-lg mb-6 p-6">
205
+ <h2 class="text-xl font-semibold text-gray-900 mb-4">Setup instructions</h2>
206
+ <div class="overflow-x-auto">
207
+ TBD
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </body>
212
+ </html>