@sodikinnaa/smart-report-plugin 1.0.2
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/README.md +33 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +166 -0
- package/openclaw.plugin.json +14 -0
- package/package.json +28 -0
- package/src/index.ts +135 -0
- package/tsconfig.json +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Smart Report Plugin for OpenClaw
|
|
2
|
+
|
|
3
|
+
Plugin ini mengintegrasikan ekosistem OpenClaw dengan sistem pelaporan Smart Report via protokol MCP.
|
|
4
|
+
|
|
5
|
+
## 🛠️ Fitur
|
|
6
|
+
- **CLI Auth:** Autentikasi mudah menggunakan token API.
|
|
7
|
+
- **Resources:** Akses data real-time via URI `smartreport://`.
|
|
8
|
+
- **Agent Tools:** Memungkinkan AI melakukan analisis laporan dan performa secara otonom.
|
|
9
|
+
|
|
10
|
+
## 🚀 Instalasi
|
|
11
|
+
1. Clone repositori ini ke folder `~/.openclaw/extensions/`.
|
|
12
|
+
2. Jalankan `npm install` dan `npm run build`.
|
|
13
|
+
3. Tambahkan entry di `openclaw.json`:
|
|
14
|
+
```json
|
|
15
|
+
"plugins": {
|
|
16
|
+
"allow": ["smart-report-plugin"]
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 🔑 Konfigurasi
|
|
21
|
+
Lakukan autentikasi via CLI:
|
|
22
|
+
```bash
|
|
23
|
+
openclaw smart-auth <YOUR_API_TOKEN>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 📖 URI Resources
|
|
27
|
+
- `smartreport://reports`: 10 Laporan terbaru.
|
|
28
|
+
- `smartreport://employees`: Daftar seluruh karyawan.
|
|
29
|
+
- `smartreport://debt-aging`: Analisis keterlambatan/absen.
|
|
30
|
+
|
|
31
|
+
## 🤖 AI Tools
|
|
32
|
+
- `get_list_reports`: Mengambil laporan dengan filter.
|
|
33
|
+
- `get_debt_analysis`: Analisis performa dan tugas tertunda.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function register(api: any): void;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.default = register;
|
|
40
|
+
/**
|
|
41
|
+
* Smart Report MCP Plugin for OpenClaw
|
|
42
|
+
*/
|
|
43
|
+
const axios_1 = __importDefault(require("axios"));
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const os = __importStar(require("os"));
|
|
47
|
+
const PLUGIN_ID = 'smart-report-plugin';
|
|
48
|
+
const API_BASE = 'https://smartreport.siapdigital.my.id/api/mcp';
|
|
49
|
+
function saveConfig(token) {
|
|
50
|
+
const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
|
|
51
|
+
if (fs.existsSync(configPath)) {
|
|
52
|
+
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
53
|
+
const config = JSON.parse(raw);
|
|
54
|
+
if (!config.plugins)
|
|
55
|
+
config.plugins = {};
|
|
56
|
+
if (!config.plugins.entries)
|
|
57
|
+
config.plugins.entries = {};
|
|
58
|
+
if (!config.plugins.entries[PLUGIN_ID])
|
|
59
|
+
config.plugins.entries[PLUGIN_ID] = {};
|
|
60
|
+
if (!config.plugins.entries[PLUGIN_ID].config)
|
|
61
|
+
config.plugins.entries[PLUGIN_ID].config = {};
|
|
62
|
+
config.plugins.entries[PLUGIN_ID].config.apiToken = token;
|
|
63
|
+
config.plugins.entries[PLUGIN_ID].enabled = true;
|
|
64
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function callMcp(api, method, params = {}) {
|
|
68
|
+
const config = api.config.plugins?.entries?.[PLUGIN_ID]?.config;
|
|
69
|
+
const token = config?.apiToken;
|
|
70
|
+
if (!token) {
|
|
71
|
+
throw new Error('API Token not found. Please run "openclaw smart-auth <token>" first.');
|
|
72
|
+
}
|
|
73
|
+
const response = await axios_1.default.post(API_BASE, {
|
|
74
|
+
jsonrpc: '2.0',
|
|
75
|
+
method: method,
|
|
76
|
+
params: params,
|
|
77
|
+
id: Date.now()
|
|
78
|
+
}, {
|
|
79
|
+
headers: {
|
|
80
|
+
'Authorization': `Bearer ${token}`,
|
|
81
|
+
'Content-Type': 'application/json',
|
|
82
|
+
'Accept': 'application/json'
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
if (response.data.error) {
|
|
86
|
+
throw new Error(response.data.error.message);
|
|
87
|
+
}
|
|
88
|
+
return response.data.result;
|
|
89
|
+
}
|
|
90
|
+
function register(api) {
|
|
91
|
+
// 1. CLI Commands
|
|
92
|
+
api.registerCli(({ program }) => {
|
|
93
|
+
program
|
|
94
|
+
.command('smart-auth <token>')
|
|
95
|
+
.description('Set API Token for Smart Report integration')
|
|
96
|
+
.action((token) => {
|
|
97
|
+
try {
|
|
98
|
+
saveConfig(token);
|
|
99
|
+
console.log('✅ Smart Report API Token saved successfully.');
|
|
100
|
+
process.exit(0);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
console.error('❌ Failed to save config:', err.message);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}, { commands: ['smart-auth'] });
|
|
108
|
+
// 2. Resources
|
|
109
|
+
api.registerResource({
|
|
110
|
+
uri: 'smartreport://reports',
|
|
111
|
+
name: 'Recent Reports',
|
|
112
|
+
description: 'Stream of latest submitted reports',
|
|
113
|
+
mimeType: 'application/json',
|
|
114
|
+
read: async () => {
|
|
115
|
+
const data = await callMcp(api, 'reports/list', { per_page: 10 });
|
|
116
|
+
return { content: JSON.stringify(data, null, 2) };
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
api.registerResource({
|
|
120
|
+
uri: 'smartreport://employees',
|
|
121
|
+
name: 'Employee List',
|
|
122
|
+
description: 'Complete list of active employees',
|
|
123
|
+
mimeType: 'application/json',
|
|
124
|
+
read: async () => {
|
|
125
|
+
const data = await callMcp(api, 'employees/list', {});
|
|
126
|
+
return { content: JSON.stringify(data, null, 2) };
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
api.registerResource({
|
|
130
|
+
uri: 'smartreport://debt-aging',
|
|
131
|
+
name: 'Debt Aging Analysis',
|
|
132
|
+
description: 'Analysis of pending tasks and overdue reports',
|
|
133
|
+
mimeType: 'application/json',
|
|
134
|
+
read: async () => {
|
|
135
|
+
const data = await callMcp(api, 'attendance/list_absent', { include_reason: true });
|
|
136
|
+
return { content: JSON.stringify(data, null, 2) };
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
// 3. Agent Tools
|
|
140
|
+
api.registerTool({
|
|
141
|
+
name: 'get_list_reports',
|
|
142
|
+
description: 'Retrieve reports with filters (date, employee, division).',
|
|
143
|
+
execute: async (args) => {
|
|
144
|
+
try {
|
|
145
|
+
const data = await callMcp(api, 'reports/list', args);
|
|
146
|
+
return { text: JSON.stringify(data, null, 2) };
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
return { error: err.message };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
api.registerTool({
|
|
154
|
+
name: 'get_debt_analysis',
|
|
155
|
+
description: 'Analyze pending tasks and employee performance debt.',
|
|
156
|
+
execute: async (args) => {
|
|
157
|
+
try {
|
|
158
|
+
const data = await callMcp(api, 'analyze_performance', args);
|
|
159
|
+
return { text: JSON.stringify(data, null, 2) };
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
return { error: err.message };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "smart-report-plugin",
|
|
3
|
+
"name": "Smart Report Integration",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Integration plugin for Smart Report and AI Analytics",
|
|
6
|
+
"entry": "dist/index.js",
|
|
7
|
+
"skills": ["skills/smart-report/SKILL.md"],
|
|
8
|
+
"configSchema": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
"apiToken": { "type": "string" }
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sodikinnaa/smart-report-plugin",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "OpenClaw plugin for Smart Report system integration",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"openclaw-plugin",
|
|
15
|
+
"smart-report"
|
|
16
|
+
],
|
|
17
|
+
"author": "Sodikin",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"typescript": "^5.0.0"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"axios": "^1.6.0"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Report MCP Plugin for OpenClaw
|
|
3
|
+
*/
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import * as os from 'os';
|
|
8
|
+
|
|
9
|
+
const PLUGIN_ID = 'smart-report-plugin';
|
|
10
|
+
const API_BASE = 'https://smartreport.siapdigital.my.id/api/mcp';
|
|
11
|
+
|
|
12
|
+
function saveConfig(token: string) {
|
|
13
|
+
const configPath = path.join(os.homedir(), '.openclaw', 'openclaw.json');
|
|
14
|
+
if (fs.existsSync(configPath)) {
|
|
15
|
+
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
16
|
+
const config = JSON.parse(raw);
|
|
17
|
+
if (!config.plugins) config.plugins = {};
|
|
18
|
+
if (!config.plugins.entries) config.plugins.entries = {};
|
|
19
|
+
if (!config.plugins.entries[PLUGIN_ID]) config.plugins.entries[PLUGIN_ID] = {};
|
|
20
|
+
if (!config.plugins.entries[PLUGIN_ID].config) config.plugins.entries[PLUGIN_ID].config = {};
|
|
21
|
+
|
|
22
|
+
config.plugins.entries[PLUGIN_ID].config.apiToken = token;
|
|
23
|
+
config.plugins.entries[PLUGIN_ID].enabled = true;
|
|
24
|
+
|
|
25
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function callMcp(api: any, method: string, params: any = {}) {
|
|
30
|
+
const config = (api.config as any).plugins?.entries?.[PLUGIN_ID]?.config;
|
|
31
|
+
const token = config?.apiToken;
|
|
32
|
+
|
|
33
|
+
if (!token) {
|
|
34
|
+
throw new Error('API Token not found. Please run "openclaw smart-auth <token>" first.');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const response = await axios.post(API_BASE, {
|
|
38
|
+
jsonrpc: '2.0',
|
|
39
|
+
method: method,
|
|
40
|
+
params: params,
|
|
41
|
+
id: Date.now()
|
|
42
|
+
}, {
|
|
43
|
+
headers: {
|
|
44
|
+
'Authorization': `Bearer ${token}`,
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
'Accept': 'application/json'
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (response.data.error) {
|
|
51
|
+
throw new Error(response.data.error.message);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return response.data.result;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default function register(api: any) {
|
|
58
|
+
// 1. CLI Commands
|
|
59
|
+
api.registerCli(({ program }: any) => {
|
|
60
|
+
program
|
|
61
|
+
.command('smart-auth <token>')
|
|
62
|
+
.description('Set API Token for Smart Report integration')
|
|
63
|
+
.action((token: string) => {
|
|
64
|
+
try {
|
|
65
|
+
saveConfig(token);
|
|
66
|
+
console.log('✅ Smart Report API Token saved successfully.');
|
|
67
|
+
process.exit(0);
|
|
68
|
+
} catch (err: any) {
|
|
69
|
+
console.error('❌ Failed to save config:', err.message);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}, { commands: ['smart-auth'] });
|
|
74
|
+
|
|
75
|
+
// 2. Resources
|
|
76
|
+
api.registerResource({
|
|
77
|
+
uri: 'smartreport://reports',
|
|
78
|
+
name: 'Recent Reports',
|
|
79
|
+
description: 'Stream of latest submitted reports',
|
|
80
|
+
mimeType: 'application/json',
|
|
81
|
+
read: async () => {
|
|
82
|
+
const data = await callMcp(api, 'reports/list', { per_page: 10 });
|
|
83
|
+
return { content: JSON.stringify(data, null, 2) };
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
api.registerResource({
|
|
88
|
+
uri: 'smartreport://employees',
|
|
89
|
+
name: 'Employee List',
|
|
90
|
+
description: 'Complete list of active employees',
|
|
91
|
+
mimeType: 'application/json',
|
|
92
|
+
read: async () => {
|
|
93
|
+
const data = await callMcp(api, 'employees/list', {});
|
|
94
|
+
return { content: JSON.stringify(data, null, 2) };
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
api.registerResource({
|
|
99
|
+
uri: 'smartreport://debt-aging',
|
|
100
|
+
name: 'Debt Aging Analysis',
|
|
101
|
+
description: 'Analysis of pending tasks and overdue reports',
|
|
102
|
+
mimeType: 'application/json',
|
|
103
|
+
read: async () => {
|
|
104
|
+
const data = await callMcp(api, 'attendance/list_absent', { include_reason: true });
|
|
105
|
+
return { content: JSON.stringify(data, null, 2) };
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// 3. Agent Tools
|
|
110
|
+
api.registerTool({
|
|
111
|
+
name: 'get_list_reports',
|
|
112
|
+
description: 'Retrieve reports with filters (date, employee, division).',
|
|
113
|
+
execute: async (args: any) => {
|
|
114
|
+
try {
|
|
115
|
+
const data = await callMcp(api, 'reports/list', args);
|
|
116
|
+
return { text: JSON.stringify(data, null, 2) };
|
|
117
|
+
} catch (err: any) {
|
|
118
|
+
return { error: err.message };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
api.registerTool({
|
|
124
|
+
name: 'get_debt_analysis',
|
|
125
|
+
description: 'Analyze pending tasks and employee performance debt.',
|
|
126
|
+
execute: async (args: any) => {
|
|
127
|
+
try {
|
|
128
|
+
const data = await callMcp(api, 'analyze_performance', args);
|
|
129
|
+
return { text: JSON.stringify(data, null, 2) };
|
|
130
|
+
} catch (err: any) {
|
|
131
|
+
return { error: err.message };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"lib": ["ESNext"],
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"moduleResolution": "node"
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*"]
|
|
15
|
+
}
|