Skip to content

Commit d460e87

Browse files
author
JiaDe
committed
feat: example Layer 2 skills (weather-lookup, jira-query) with role-based filtering verified
1 parent 3859e8d commit d460e87

4 files changed

Lines changed: 119 additions & 0 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "jira-query",
3+
"version": "1.0.0",
4+
"description": "Query Jira issues by ID or search. Requires JIRA_API_TOKEN and JIRA_BASE_URL.",
5+
"author": "IT Team",
6+
"scope": "global",
7+
"requires": {
8+
"env": ["JIRA_API_TOKEN", "JIRA_BASE_URL"],
9+
"tools": ["web_fetch"]
10+
},
11+
"permissions": {
12+
"allowedRoles": ["engineering", "product", "management"],
13+
"blockedRoles": ["intern"]
14+
}
15+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Jira Query Skill — Example Layer 2 skill with API key injection.
4+
*
5+
* Reads JIRA_API_TOKEN and JIRA_BASE_URL from environment variables
6+
* (injected by skill_loader.py from SSM Parameter Store).
7+
*
8+
* This is a demonstration skill. Replace the mock with real Jira API calls.
9+
*/
10+
11+
const JIRA_TOKEN = process.env.JIRA_API_TOKEN;
12+
const JIRA_URL = process.env.JIRA_BASE_URL;
13+
14+
if (!JIRA_TOKEN || !JIRA_URL) {
15+
console.error('Error: JIRA_API_TOKEN and JIRA_BASE_URL environment variables required.');
16+
console.error('Ask your IT admin to configure these in the Skill Platform.');
17+
process.exit(1);
18+
}
19+
20+
async function queryIssue(issueId) {
21+
// In production: call Jira REST API
22+
// GET ${JIRA_URL}/rest/api/3/issue/${issueId}
23+
// Authorization: Basic base64(email:JIRA_TOKEN)
24+
return {
25+
key: issueId,
26+
summary: `[Mock] Issue ${issueId} summary`,
27+
status: 'In Progress',
28+
assignee: 'alice@company.com',
29+
priority: 'High',
30+
note: `Queried from ${JIRA_URL} (API key configured via SSM)`,
31+
};
32+
}
33+
34+
async function main() {
35+
const issueId = process.argv[2] || 'PROJ-123';
36+
const result = await queryIssue(issueId);
37+
console.log(JSON.stringify(result, null, 2));
38+
}
39+
40+
main();
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "weather-lookup",
3+
"version": "1.0.0",
4+
"description": "Look up current weather for a city using wttr.in (no API key needed)",
5+
"author": "Platform Team",
6+
"scope": "global",
7+
"requires": {
8+
"env": [],
9+
"tools": ["web_fetch"]
10+
},
11+
"permissions": {
12+
"allowedRoles": ["*"],
13+
"blockedRoles": []
14+
}
15+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Weather Lookup Skill — Example Layer 2 skill for OpenClaw Enterprise Platform.
4+
* Uses wttr.in free API (no API key required).
5+
*
6+
* Usage by OpenClaw: automatically invoked when user asks about weather.
7+
*/
8+
9+
const https = require('https');
10+
11+
function fetchWeather(city) {
12+
return new Promise((resolve, reject) => {
13+
const url = `https://wttr.in/${encodeURIComponent(city)}?format=j1`;
14+
https.get(url, (res) => {
15+
let data = '';
16+
res.on('data', chunk => data += chunk);
17+
res.on('end', () => {
18+
try {
19+
const json = JSON.parse(data);
20+
const current = json.current_condition?.[0] || {};
21+
resolve({
22+
city: city,
23+
temp_c: current.temp_C,
24+
temp_f: current.temp_F,
25+
condition: current.weatherDesc?.[0]?.value || 'Unknown',
26+
humidity: current.humidity,
27+
wind_kmph: current.windspeedKmph,
28+
feels_like_c: current.FeelsLikeC,
29+
});
30+
} catch (e) {
31+
reject(new Error(`Failed to parse weather data: ${e.message}`));
32+
}
33+
});
34+
}).on('error', reject);
35+
});
36+
}
37+
38+
async function main() {
39+
const city = process.argv[2] || 'Seattle';
40+
try {
41+
const weather = await fetchWeather(city);
42+
console.log(JSON.stringify(weather, null, 2));
43+
} catch (e) {
44+
console.error(`Error: ${e.message}`);
45+
process.exit(1);
46+
}
47+
}
48+
49+
main();

0 commit comments

Comments
 (0)