@forwardimpact/pathway 0.25.15 → 0.25.20
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.
- package/bin/fit-pathway.js +62 -54
- package/package.json +1 -3
- package/src/commands/agent-io.js +120 -0
- package/src/commands/agent.js +266 -349
- package/src/commands/init.js +2 -2
- package/src/commands/job.js +237 -183
- package/src/components/comparison-radar.js +118 -103
- package/src/components/progression-table.js +244 -208
- package/src/formatters/interview/markdown.js +100 -88
- package/src/formatters/job/description.js +76 -75
- package/src/formatters/job/dom.js +113 -97
- package/src/formatters/level/dom.js +87 -102
- package/src/formatters/questions/markdown.js +37 -33
- package/src/formatters/questions/shared.js +142 -75
- package/src/formatters/skill/dom.js +102 -93
- package/src/lib/comparison-radar-chart.js +256 -0
- package/src/lib/radar-utils.js +199 -0
- package/src/lib/radar.js +25 -662
- package/src/pages/agent-builder-download.js +170 -0
- package/src/pages/agent-builder-preview.js +344 -0
- package/src/pages/agent-builder.js +6 -550
- package/src/pages/progress-comparison.js +110 -0
- package/src/pages/progress.js +11 -111
- package/src/pages/self-assessment-steps.js +494 -0
- package/src/pages/self-assessment.js +54 -504
|
@@ -111,6 +111,119 @@ function getSkillCapability(skillId, skills) {
|
|
|
111
111
|
*/
|
|
112
112
|
const ROLE_TYPES = ["professionalQuestions", "managementQuestions"];
|
|
113
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Check whether skill questions should be included given the current filter
|
|
116
|
+
* @param {string} skillId
|
|
117
|
+
* @param {Array} skills
|
|
118
|
+
* @param {QuestionsFilter} filter
|
|
119
|
+
* @returns {boolean}
|
|
120
|
+
*/
|
|
121
|
+
function shouldIncludeSkill(skillId, skills, filter) {
|
|
122
|
+
if (filter.skills && !filter.skills.includes(skillId)) return false;
|
|
123
|
+
if (filter.behaviours) return false;
|
|
124
|
+
if (filter.maturity) return false;
|
|
125
|
+
if (filter.capability) {
|
|
126
|
+
const capability = getSkillCapability(skillId, skills);
|
|
127
|
+
if (capability !== filter.capability) return false;
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check whether behaviour questions should be included given the current filter
|
|
134
|
+
* @param {string} behaviourId
|
|
135
|
+
* @param {QuestionsFilter} filter
|
|
136
|
+
* @returns {boolean}
|
|
137
|
+
*/
|
|
138
|
+
function shouldIncludeBehaviour(behaviourId, filter) {
|
|
139
|
+
if (filter.behaviours && !filter.behaviours.includes(behaviourId))
|
|
140
|
+
return false;
|
|
141
|
+
if (filter.capability) return false;
|
|
142
|
+
if (filter.skills) return false;
|
|
143
|
+
if (filter.level) return false;
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Flatten skill questions from a single skill entry
|
|
149
|
+
* @param {string} skillId
|
|
150
|
+
* @param {Object} roleTypes
|
|
151
|
+
* @param {Array} skills
|
|
152
|
+
* @param {QuestionsFilter} filter
|
|
153
|
+
* @param {FlattenedQuestion[]} out
|
|
154
|
+
*/
|
|
155
|
+
function flattenSkillQuestions(skillId, roleTypes, skills, filter, out) {
|
|
156
|
+
const skillName = getSkillName(skillId, skills);
|
|
157
|
+
|
|
158
|
+
for (const roleType of ROLE_TYPES) {
|
|
159
|
+
const levels = roleTypes[roleType];
|
|
160
|
+
if (!levels) continue;
|
|
161
|
+
|
|
162
|
+
for (const [level, levelQuestions] of Object.entries(levels)) {
|
|
163
|
+
if (filter.level && level !== filter.level) continue;
|
|
164
|
+
|
|
165
|
+
for (const q of levelQuestions) {
|
|
166
|
+
out.push({
|
|
167
|
+
source: skillId,
|
|
168
|
+
sourceName: skillName,
|
|
169
|
+
sourceType: "skill",
|
|
170
|
+
level,
|
|
171
|
+
id: q.id,
|
|
172
|
+
text: q.text,
|
|
173
|
+
lookingFor: q.lookingFor || [],
|
|
174
|
+
expectedDurationMinutes: q.expectedDurationMinutes || 5,
|
|
175
|
+
followUps: q.followUps || [],
|
|
176
|
+
context: q.context || null,
|
|
177
|
+
decompositionPrompts: q.decompositionPrompts || [],
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Flatten behaviour questions from a single behaviour entry
|
|
186
|
+
* @param {string} behaviourId
|
|
187
|
+
* @param {Object} roleTypes
|
|
188
|
+
* @param {Array} behaviours
|
|
189
|
+
* @param {QuestionsFilter} filter
|
|
190
|
+
* @param {FlattenedQuestion[]} out
|
|
191
|
+
*/
|
|
192
|
+
function flattenBehaviourQuestions(
|
|
193
|
+
behaviourId,
|
|
194
|
+
roleTypes,
|
|
195
|
+
behaviours,
|
|
196
|
+
filter,
|
|
197
|
+
out,
|
|
198
|
+
) {
|
|
199
|
+
const behaviourName = getBehaviourName(behaviourId, behaviours);
|
|
200
|
+
|
|
201
|
+
for (const roleType of ROLE_TYPES) {
|
|
202
|
+
const maturities = roleTypes[roleType];
|
|
203
|
+
if (!maturities) continue;
|
|
204
|
+
|
|
205
|
+
for (const [maturity, maturityQuestions] of Object.entries(maturities)) {
|
|
206
|
+
if (filter.maturity && maturity !== filter.maturity) continue;
|
|
207
|
+
|
|
208
|
+
for (const q of maturityQuestions) {
|
|
209
|
+
out.push({
|
|
210
|
+
source: behaviourId,
|
|
211
|
+
sourceName: behaviourName,
|
|
212
|
+
sourceType: "behaviour",
|
|
213
|
+
level: maturity,
|
|
214
|
+
id: q.id,
|
|
215
|
+
text: q.text,
|
|
216
|
+
lookingFor: q.lookingFor || [],
|
|
217
|
+
expectedDurationMinutes: q.expectedDurationMinutes || 5,
|
|
218
|
+
followUps: q.followUps || [],
|
|
219
|
+
context: q.context || null,
|
|
220
|
+
simulationPrompts: q.simulationPrompts || [],
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
114
227
|
/**
|
|
115
228
|
* Flatten all questions from question bank
|
|
116
229
|
* @param {Object} questionBank
|
|
@@ -122,84 +235,43 @@ const ROLE_TYPES = ["professionalQuestions", "managementQuestions"];
|
|
|
122
235
|
export function flattenQuestions(questionBank, skills, behaviours, filter) {
|
|
123
236
|
const questions = [];
|
|
124
237
|
|
|
125
|
-
// Process skill questions
|
|
126
238
|
for (const [skillId, roleTypes] of Object.entries(
|
|
127
239
|
questionBank.skillProficiencies || {},
|
|
128
240
|
)) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (filter.skills && !filter.skills.includes(skillId)) continue;
|
|
133
|
-
if (filter.behaviours) continue;
|
|
134
|
-
if (filter.capability && capability !== filter.capability) continue;
|
|
135
|
-
if (filter.maturity) continue;
|
|
136
|
-
|
|
137
|
-
for (const roleType of ROLE_TYPES) {
|
|
138
|
-
const levels = roleTypes[roleType];
|
|
139
|
-
if (!levels) continue;
|
|
140
|
-
|
|
141
|
-
for (const [level, levelQuestions] of Object.entries(levels)) {
|
|
142
|
-
if (filter.level && level !== filter.level) continue;
|
|
143
|
-
|
|
144
|
-
for (const q of levelQuestions) {
|
|
145
|
-
questions.push({
|
|
146
|
-
source: skillId,
|
|
147
|
-
sourceName: skillName,
|
|
148
|
-
sourceType: "skill",
|
|
149
|
-
level,
|
|
150
|
-
id: q.id,
|
|
151
|
-
text: q.text,
|
|
152
|
-
lookingFor: q.lookingFor || [],
|
|
153
|
-
expectedDurationMinutes: q.expectedDurationMinutes || 5,
|
|
154
|
-
followUps: q.followUps || [],
|
|
155
|
-
context: q.context || null,
|
|
156
|
-
decompositionPrompts: q.decompositionPrompts || [],
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
241
|
+
if (!shouldIncludeSkill(skillId, skills, filter)) continue;
|
|
242
|
+
flattenSkillQuestions(skillId, roleTypes, skills, filter, questions);
|
|
161
243
|
}
|
|
162
244
|
|
|
163
|
-
// Process behaviour questions
|
|
164
245
|
for (const [behaviourId, roleTypes] of Object.entries(
|
|
165
246
|
questionBank.behaviourMaturities || {},
|
|
166
247
|
)) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const maturities = roleTypes[roleType];
|
|
176
|
-
if (!maturities) continue;
|
|
177
|
-
|
|
178
|
-
for (const [maturity, maturityQuestions] of Object.entries(maturities)) {
|
|
179
|
-
if (filter.maturity && maturity !== filter.maturity) continue;
|
|
180
|
-
|
|
181
|
-
for (const q of maturityQuestions) {
|
|
182
|
-
questions.push({
|
|
183
|
-
source: behaviourId,
|
|
184
|
-
sourceName: behaviourName,
|
|
185
|
-
sourceType: "behaviour",
|
|
186
|
-
level: maturity,
|
|
187
|
-
id: q.id,
|
|
188
|
-
text: q.text,
|
|
189
|
-
lookingFor: q.lookingFor || [],
|
|
190
|
-
expectedDurationMinutes: q.expectedDurationMinutes || 5,
|
|
191
|
-
followUps: q.followUps || [],
|
|
192
|
-
context: q.context || null,
|
|
193
|
-
simulationPrompts: q.simulationPrompts || [],
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
248
|
+
if (!shouldIncludeBehaviour(behaviourId, filter)) continue;
|
|
249
|
+
flattenBehaviourQuestions(
|
|
250
|
+
behaviourId,
|
|
251
|
+
roleTypes,
|
|
252
|
+
behaviours,
|
|
253
|
+
filter,
|
|
254
|
+
questions,
|
|
255
|
+
);
|
|
198
256
|
}
|
|
199
257
|
|
|
200
258
|
return questions;
|
|
201
259
|
}
|
|
202
260
|
|
|
261
|
+
/**
|
|
262
|
+
* Count questions across role types for a given level/maturity
|
|
263
|
+
* @param {Object} roleTypes - Role type map
|
|
264
|
+
* @param {string} levelKey - Level or maturity key
|
|
265
|
+
* @returns {number}
|
|
266
|
+
*/
|
|
267
|
+
function countQuestionsForLevel(roleTypes, levelKey) {
|
|
268
|
+
let count = 0;
|
|
269
|
+
for (const roleType of ROLE_TYPES) {
|
|
270
|
+
count += (roleTypes[roleType]?.[levelKey] || []).length;
|
|
271
|
+
}
|
|
272
|
+
return count;
|
|
273
|
+
}
|
|
274
|
+
|
|
203
275
|
/**
|
|
204
276
|
* Calculate question statistics
|
|
205
277
|
* @param {FlattenedQuestion[]} questions
|
|
@@ -222,11 +294,7 @@ export function calculateStats(questions, questionBank) {
|
|
|
222
294
|
)) {
|
|
223
295
|
skillStats[skillId] = {};
|
|
224
296
|
for (const level of SKILL_PROFICIENCIES) {
|
|
225
|
-
|
|
226
|
-
for (const roleType of ROLE_TYPES) {
|
|
227
|
-
count += (roleTypes[roleType]?.[level] || []).length;
|
|
228
|
-
}
|
|
229
|
-
skillStats[skillId][level] = count;
|
|
297
|
+
skillStats[skillId][level] = countQuestionsForLevel(roleTypes, level);
|
|
230
298
|
}
|
|
231
299
|
skillStats[skillId].total = Object.values(skillStats[skillId]).reduce(
|
|
232
300
|
(a, b) => a + b,
|
|
@@ -240,11 +308,10 @@ export function calculateStats(questions, questionBank) {
|
|
|
240
308
|
)) {
|
|
241
309
|
behaviourStats[behaviourId] = {};
|
|
242
310
|
for (const maturity of BEHAVIOUR_MATURITIES) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
behaviourStats[behaviourId][maturity] = count;
|
|
311
|
+
behaviourStats[behaviourId][maturity] = countQuestionsForLevel(
|
|
312
|
+
roleTypes,
|
|
313
|
+
maturity,
|
|
314
|
+
);
|
|
248
315
|
}
|
|
249
316
|
behaviourStats[behaviourId].total = Object.values(
|
|
250
317
|
behaviourStats[behaviourId],
|
|
@@ -37,6 +37,106 @@ import { createJsonLdScript, skillToJsonLd } from "../json-ld.js";
|
|
|
37
37
|
* @param {string} [context.agentSkillContent] - Pre-generated SKILL.md content for agent file viewer
|
|
38
38
|
* @returns {HTMLElement}
|
|
39
39
|
*/
|
|
40
|
+
/**
|
|
41
|
+
* Create the required tools section
|
|
42
|
+
* @param {Object} view
|
|
43
|
+
* @param {boolean} showBackLink
|
|
44
|
+
* @returns {HTMLElement}
|
|
45
|
+
*/
|
|
46
|
+
function createToolsSection(view, showBackLink) {
|
|
47
|
+
return div(
|
|
48
|
+
{ className: "detail-section" },
|
|
49
|
+
heading2({ className: "section-title" }, "Required Tools"),
|
|
50
|
+
table(
|
|
51
|
+
{ className: "tools-table" },
|
|
52
|
+
thead({}, tr({}, th({}, "Tool"), th({}, "Use When"))),
|
|
53
|
+
tbody(
|
|
54
|
+
{},
|
|
55
|
+
...view.toolReferences.map((tool) =>
|
|
56
|
+
tr(
|
|
57
|
+
{},
|
|
58
|
+
td(
|
|
59
|
+
{ className: "tool-name-cell" },
|
|
60
|
+
tool.simpleIcon
|
|
61
|
+
? createToolIcon(tool.simpleIcon, tool.name)
|
|
62
|
+
: null,
|
|
63
|
+
tool.url
|
|
64
|
+
? a(
|
|
65
|
+
{
|
|
66
|
+
href: tool.url,
|
|
67
|
+
target: "_blank",
|
|
68
|
+
rel: "noopener noreferrer",
|
|
69
|
+
},
|
|
70
|
+
tool.name,
|
|
71
|
+
span({ className: "external-icon" }, " ↗"),
|
|
72
|
+
)
|
|
73
|
+
: tool.name,
|
|
74
|
+
),
|
|
75
|
+
td({}, tool.useWhen),
|
|
76
|
+
),
|
|
77
|
+
),
|
|
78
|
+
),
|
|
79
|
+
),
|
|
80
|
+
showBackLink
|
|
81
|
+
? p(
|
|
82
|
+
{ className: "see-all-link" },
|
|
83
|
+
a({ href: "#/tool" }, "See all tools →"),
|
|
84
|
+
)
|
|
85
|
+
: null,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Create the related disciplines and drivers section
|
|
91
|
+
* @param {Object} view
|
|
92
|
+
* @param {boolean} showBackLink
|
|
93
|
+
* @returns {HTMLElement|null}
|
|
94
|
+
*/
|
|
95
|
+
function createRelationsSection(view, showBackLink) {
|
|
96
|
+
if (
|
|
97
|
+
view.relatedDisciplines.length === 0 &&
|
|
98
|
+
view.relatedDrivers.length === 0
|
|
99
|
+
) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
return div(
|
|
103
|
+
{ className: "detail-section" },
|
|
104
|
+
div(
|
|
105
|
+
{ className: "content-columns" },
|
|
106
|
+
view.relatedDisciplines.length > 0
|
|
107
|
+
? div(
|
|
108
|
+
{ className: "column" },
|
|
109
|
+
heading2({ className: "section-title" }, "Used in Disciplines"),
|
|
110
|
+
...view.relatedDisciplines.map((d) =>
|
|
111
|
+
div(
|
|
112
|
+
{ className: "list-item" },
|
|
113
|
+
showBackLink
|
|
114
|
+
? a({ href: `#/discipline/${d.id}` }, d.name)
|
|
115
|
+
: span({}, d.name),
|
|
116
|
+
" ",
|
|
117
|
+
span({ className: `badge badge-${d.skillType}` }, d.skillType),
|
|
118
|
+
),
|
|
119
|
+
),
|
|
120
|
+
)
|
|
121
|
+
: null,
|
|
122
|
+
view.relatedDrivers.length > 0
|
|
123
|
+
? div(
|
|
124
|
+
{ className: "column" },
|
|
125
|
+
heading2({ className: "section-title" }, "Linked to Drivers"),
|
|
126
|
+
...view.relatedDrivers.map((d) =>
|
|
127
|
+
div(
|
|
128
|
+
{ className: "list-item" },
|
|
129
|
+
showBackLink
|
|
130
|
+
? a({ href: `#/driver/${d.id}` }, d.name)
|
|
131
|
+
: span({}, d.name),
|
|
132
|
+
),
|
|
133
|
+
),
|
|
134
|
+
)
|
|
135
|
+
: null,
|
|
136
|
+
),
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
40
140
|
export function skillToDOM(
|
|
41
141
|
skill,
|
|
42
142
|
{
|
|
@@ -57,9 +157,7 @@ export function skillToDOM(
|
|
|
57
157
|
});
|
|
58
158
|
return div(
|
|
59
159
|
{ className: "detail-page skill-detail" },
|
|
60
|
-
// JSON-LD structured data
|
|
61
160
|
createJsonLdScript(skillToJsonLd(skill, { capabilities })),
|
|
62
|
-
// Header
|
|
63
161
|
div(
|
|
64
162
|
{ className: "page-header" },
|
|
65
163
|
showBackLink ? createBackLink("/skill", "← Back to Skills") : null,
|
|
@@ -88,7 +186,6 @@ export function skillToDOM(
|
|
|
88
186
|
p({ className: "page-description" }, view.description),
|
|
89
187
|
),
|
|
90
188
|
|
|
91
|
-
// Level descriptions
|
|
92
189
|
div(
|
|
93
190
|
{ className: "detail-section" },
|
|
94
191
|
heading2({ className: "section-title" }, "Level Descriptions"),
|
|
@@ -109,55 +206,8 @@ export function skillToDOM(
|
|
|
109
206
|
),
|
|
110
207
|
),
|
|
111
208
|
|
|
112
|
-
|
|
113
|
-
view.relatedDisciplines.length > 0 || view.relatedDrivers.length > 0
|
|
114
|
-
? div(
|
|
115
|
-
{ className: "detail-section" },
|
|
116
|
-
div(
|
|
117
|
-
{ className: "content-columns" },
|
|
118
|
-
// Used in Disciplines column
|
|
119
|
-
view.relatedDisciplines.length > 0
|
|
120
|
-
? div(
|
|
121
|
-
{ className: "column" },
|
|
122
|
-
heading2(
|
|
123
|
-
{ className: "section-title" },
|
|
124
|
-
"Used in Disciplines",
|
|
125
|
-
),
|
|
126
|
-
...view.relatedDisciplines.map((d) =>
|
|
127
|
-
div(
|
|
128
|
-
{ className: "list-item" },
|
|
129
|
-
showBackLink
|
|
130
|
-
? a({ href: `#/discipline/${d.id}` }, d.name)
|
|
131
|
-
: span({}, d.name),
|
|
132
|
-
" ",
|
|
133
|
-
span(
|
|
134
|
-
{ className: `badge badge-${d.skillType}` },
|
|
135
|
-
d.skillType,
|
|
136
|
-
),
|
|
137
|
-
),
|
|
138
|
-
),
|
|
139
|
-
)
|
|
140
|
-
: null,
|
|
141
|
-
// Linked to Drivers column
|
|
142
|
-
view.relatedDrivers.length > 0
|
|
143
|
-
? div(
|
|
144
|
-
{ className: "column" },
|
|
145
|
-
heading2({ className: "section-title" }, "Linked to Drivers"),
|
|
146
|
-
...view.relatedDrivers.map((d) =>
|
|
147
|
-
div(
|
|
148
|
-
{ className: "list-item" },
|
|
149
|
-
showBackLink
|
|
150
|
-
? a({ href: `#/driver/${d.id}` }, d.name)
|
|
151
|
-
: span({}, d.name),
|
|
152
|
-
),
|
|
153
|
-
),
|
|
154
|
-
)
|
|
155
|
-
: null,
|
|
156
|
-
),
|
|
157
|
-
)
|
|
158
|
-
: null,
|
|
209
|
+
createRelationsSection(view, showBackLink),
|
|
159
210
|
|
|
160
|
-
// Related tracks
|
|
161
211
|
view.relatedTracks.length > 0
|
|
162
212
|
? div(
|
|
163
213
|
{ className: "detail-section" },
|
|
@@ -180,51 +230,10 @@ export function skillToDOM(
|
|
|
180
230
|
)
|
|
181
231
|
: null,
|
|
182
232
|
|
|
183
|
-
// Required Tools
|
|
184
233
|
showToolsAndPatterns && view.toolReferences.length > 0
|
|
185
|
-
?
|
|
186
|
-
{ className: "detail-section" },
|
|
187
|
-
heading2({ className: "section-title" }, "Required Tools"),
|
|
188
|
-
table(
|
|
189
|
-
{ className: "tools-table" },
|
|
190
|
-
thead({}, tr({}, th({}, "Tool"), th({}, "Use When"))),
|
|
191
|
-
tbody(
|
|
192
|
-
{},
|
|
193
|
-
...view.toolReferences.map((tool) =>
|
|
194
|
-
tr(
|
|
195
|
-
{},
|
|
196
|
-
td(
|
|
197
|
-
{ className: "tool-name-cell" },
|
|
198
|
-
tool.simpleIcon
|
|
199
|
-
? createToolIcon(tool.simpleIcon, tool.name)
|
|
200
|
-
: null,
|
|
201
|
-
tool.url
|
|
202
|
-
? a(
|
|
203
|
-
{
|
|
204
|
-
href: tool.url,
|
|
205
|
-
target: "_blank",
|
|
206
|
-
rel: "noopener noreferrer",
|
|
207
|
-
},
|
|
208
|
-
tool.name,
|
|
209
|
-
span({ className: "external-icon" }, " ↗"),
|
|
210
|
-
)
|
|
211
|
-
: tool.name,
|
|
212
|
-
),
|
|
213
|
-
td({}, tool.useWhen),
|
|
214
|
-
),
|
|
215
|
-
),
|
|
216
|
-
),
|
|
217
|
-
),
|
|
218
|
-
showBackLink
|
|
219
|
-
? p(
|
|
220
|
-
{ className: "see-all-link" },
|
|
221
|
-
a({ href: "#/tool" }, "See all tools →"),
|
|
222
|
-
)
|
|
223
|
-
: null,
|
|
224
|
-
)
|
|
234
|
+
? createToolsSection(view, showBackLink)
|
|
225
235
|
: null,
|
|
226
236
|
|
|
227
|
-
// Agent Skill Files
|
|
228
237
|
showToolsAndPatterns &&
|
|
229
238
|
(agentSkillContent || view.implementationReference || view.installScript)
|
|
230
239
|
? div(
|