@wipal/agent-team 1.2.0 → 1.2.1

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/ui/agents.html +126 -51
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipal/agent-team",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "CLI tool to add AI agent teams to existing projects with specialized roles, skills, and workflows (v2.1 with OpenFang patterns)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -26,7 +26,7 @@
26
26
 
27
27
  <!-- Add Agent Button -->
28
28
  <div class="actions-bar">
29
- <button class="btn btn-primary" @click="showAddModal = true">
29
+ <button class="btn btn-primary" @click="openAddModal()">
30
30
  ➕ Add New Agent
31
31
  </button>
32
32
  </div>
@@ -49,42 +49,55 @@
49
49
  </div>
50
50
 
51
51
  <div class="modal-body">
52
- <!-- Step 1: Basic Info -->
52
+ <!-- Step 1: Agent Name -->
53
53
  <div class="form-group">
54
- <label>Agent Name</label>
54
+ <label>Agent Name *</label>
55
55
  <input type="text" x-model="newAgent.name" placeholder="my-agent"
56
56
  class="input" pattern="[a-z0-9-]+">
57
57
  <small class="hint">Use lowercase letters, numbers, and hyphens</small>
58
58
  </div>
59
59
 
60
- <!-- Step 2: Select Role -->
60
+ <!-- Step 2: Select Role (Dropdown) -->
61
61
  <div class="form-group">
62
- <label>Role</label>
63
- <div class="role-selector" hx-get="/api/agents/meta/roles" hx-trigger="load">
64
- <div class="loading">Loading roles...</div>
65
- </div>
62
+ <label>Role *</label>
63
+ <select x-model="newAgent.role" class="input" @change="onRoleChange()" :disabled="loadingRoles">
64
+ <option value="">-- Select Role --</option>
65
+ <template x-for="role in roles" :key="role.name">
66
+ <option :value="role.name" x-text="role.name"></option>
67
+ </template>
68
+ </select>
69
+ <small class="hint" x-show="selectedRoleDescription" x-text="selectedRoleDescription"></small>
66
70
  </div>
67
71
 
68
- <!-- Step 3: Select Variants (shown when role selected) -->
69
- <div x-show="newAgent.role" x-cloak class="variants-section">
70
- <h3>Select Variants</h3>
71
- <div id="variants-container"
72
- hx-get="/api/agents/meta/variants/"
73
- :hx-get="'/api/agents/meta/variants/' + newAgent.role"
74
- hx-trigger="roleSelected from:body">
75
- <div class="loading">Loading variants...</div>
76
- </div>
72
+ <!-- Step 3: Select Variants (Dropdowns) -->
73
+ <div x-show="newAgent.role && Object.keys(variantCategories).length > 0" x-cloak class="variants-section">
74
+ <h3>Select Variants (Optional)</h3>
75
+ <template x-for="(category, key) in variantCategories" :key="key">
76
+ <div class="form-group">
77
+ <label x-text="category.label"></label>
78
+ <select class="input" @change="selectVariant(key, $event.target.value)">
79
+ <option value="">-- Select --</option>
80
+ <template x-for="option in category.options" :key="option.value">
81
+ <option :value="option.value"
82
+ :selected="newAgent.variants[key] === option.value"
83
+ x-text="option.label"></option>
84
+ </template>
85
+ </select>
86
+ </div>
87
+ </template>
77
88
  </div>
78
89
 
79
90
  <!-- Step 4: Preview Skills -->
80
91
  <div x-show="newAgent.role" x-cloak class="skills-preview">
81
92
  <h3>Skills Preview</h3>
82
- <div id="skills-preview"
83
- hx-post="/api/agents/preview-skills"
84
- hx-include="[name='variants']"
85
- hx-vals='{"role": newAgent.role}'
86
- hx-trigger="load, change from:.variant-checkbox">
87
- <div class="loading">Calculating skills...</div>
93
+ <div x-show="loadingSkills" class="loading">Calculating skills...</div>
94
+ <div x-show="!loadingSkills && previewSkills.length > 0" class="skills-list">
95
+ <template x-for="skill in previewSkills" :key="skill">
96
+ <span class="skill-tag" x-text="skill"></span>
97
+ </template>
98
+ </div>
99
+ <div x-show="!loadingSkills && previewSkills.length === 0" class="hint">
100
+ Select variants to see included skills
88
101
  </div>
89
102
  </div>
90
103
  </div>
@@ -92,8 +105,9 @@
92
105
  <div class="modal-footer">
93
106
  <button class="btn btn-secondary" @click="showAddModal = false">Cancel</button>
94
107
  <button class="btn btn-primary" @click="createAgent()"
95
- :disabled="!newAgent.name || !newAgent.role">
96
- Create Agent
108
+ :disabled="!newAgent.name || !newAgent.role || creating">
109
+ <span x-show="!creating">Create Agent</span>
110
+ <span x-show="creating">Creating...</span>
97
111
  </button>
98
112
  </div>
99
113
  </div>
@@ -104,27 +118,102 @@
104
118
  function agentApp() {
105
119
  return {
106
120
  showAddModal: false,
121
+ loadingRoles: false,
122
+ loadingSkills: false,
123
+ creating: false,
124
+ roles: [],
125
+ variantCategories: {},
126
+ previewSkills: [],
107
127
  newAgent: {
108
128
  name: '',
109
129
  role: '',
110
130
  variants: {}
111
131
  },
112
132
 
113
- selectRole(role) {
114
- this.newAgent.role = role;
115
- // Trigger variant loading
116
- htmx.trigger(document.body, 'roleSelected', { role });
133
+ get selectedRoleDescription() {
134
+ const role = this.roles.find(r => r.name === this.newAgent.role);
135
+ return role ? role.description : '';
117
136
  },
118
137
 
119
- toggleVariant(category, value) {
120
- if (this.newAgent.variants[category] === value) {
121
- delete this.newAgent.variants[category];
122
- } else {
138
+ async openAddModal() {
139
+ this.showAddModal = true;
140
+ await this.loadRoles();
141
+ },
142
+
143
+ async loadRoles() {
144
+ if (this.roles.length > 0) return; // Already loaded
145
+
146
+ this.loadingRoles = true;
147
+ try {
148
+ const response = await fetch('/api/agents/meta/roles');
149
+ this.roles = await response.json();
150
+ } catch (error) {
151
+ console.error('Failed to load roles:', error);
152
+ } finally {
153
+ this.loadingRoles = false;
154
+ }
155
+ },
156
+
157
+ async onRoleChange() {
158
+ // Reset variants and skills
159
+ this.newAgent.variants = {};
160
+ this.previewSkills = [];
161
+ this.variantCategories = {};
162
+
163
+ if (!this.newAgent.role) return;
164
+
165
+ // Load variants for selected role
166
+ await this.loadVariants(this.newAgent.role);
167
+ // Load skills preview
168
+ await this.loadSkillsPreview();
169
+ },
170
+
171
+ async loadVariants(role) {
172
+ try {
173
+ const response = await fetch(`/api/agents/meta/variants/${role}`);
174
+ const data = await response.json();
175
+ this.variantCategories = data.categories || data;
176
+ } catch (error) {
177
+ console.error('Failed to load variants:', error);
178
+ }
179
+ },
180
+
181
+ async selectVariant(category, value) {
182
+ if (value) {
123
183
  this.newAgent.variants[category] = value;
184
+ } else {
185
+ delete this.newAgent.variants[category];
186
+ }
187
+ // Update skills preview
188
+ await this.loadSkillsPreview();
189
+ },
190
+
191
+ async loadSkillsPreview() {
192
+ if (!this.newAgent.role) return;
193
+
194
+ this.loadingSkills = true;
195
+ try {
196
+ const response = await fetch('/api/agents/preview-skills', {
197
+ method: 'POST',
198
+ headers: { 'Content-Type': 'application/json' },
199
+ body: JSON.stringify({
200
+ role: this.newAgent.role,
201
+ variants: this.newAgent.variants
202
+ })
203
+ });
204
+ const data = await response.json();
205
+ this.previewSkills = data.skills || data.core?.concat(data.role || []) || [];
206
+ } catch (error) {
207
+ console.error('Failed to load skills preview:', error);
208
+ } finally {
209
+ this.loadingSkills = false;
124
210
  }
125
211
  },
126
212
 
127
213
  async createAgent() {
214
+ if (!this.newAgent.name || !this.newAgent.role) return;
215
+
216
+ this.creating = true;
128
217
  try {
129
218
  const response = await fetch('/api/agents', {
130
219
  method: 'POST',
@@ -143,32 +232,18 @@
143
232
  }
144
233
  } catch (error) {
145
234
  alert('Error creating agent: ' + error.message);
235
+ } finally {
236
+ this.creating = false;
146
237
  }
147
238
  },
148
239
 
149
240
  resetForm() {
150
241
  this.newAgent = { name: '', role: '', variants: {} };
242
+ this.variantCategories = {};
243
+ this.previewSkills = [];
151
244
  }
152
245
  }
153
246
  }
154
-
155
- // Transform role list to radio buttons
156
- document.body.addEventListener('htmx:beforeSwap', function(evt) {
157
- if (evt.detail.pathInfo.requestPath.includes('/meta/roles')) {
158
- try {
159
- const roles = JSON.parse(evt.detail.xhr.response);
160
- evt.detail.xhr.response = roles.map(r => `
161
- <label class="role-option" :class="{'selected': newAgent.role === '${r.name}'}">
162
- <input type="radio" name="role" value="${r.name}" @click="selectRole('${r.name}')">
163
- <div class="role-info">
164
- <strong>${r.name}</strong>
165
- <p>${r.description}</p>
166
- </div>
167
- </label>
168
- `).join('');
169
- } catch (e) {}
170
- }
171
- });
172
247
  </script>
173
248
  </body>
174
249
  </html>