@sodikinnaa/smart-report-plugin 2100.11.0 → 2100.11.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 +15 -0
- package/dist/index.js +41 -2
- package/dist/openclaw.cjs +13 -5
- package/openclaw.cjs +14 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +6 -6
- package/scripts/test-loader.js +16 -0
- package/src/index.ts +44 -2
- package/tsconfig.json +3 -3
- package/scripts/audit-sync.js +0 -71
- package/test/api.test.js +0 -36
- package/test/simple.test.js +0 -1
- package/tsconfig.cjs.json +0 -9
package/README.md
CHANGED
|
@@ -9,8 +9,23 @@ openclaw plugins install @sodikinnaa/smart-report-plugin
|
|
|
9
9
|
|
|
10
10
|
# 2. Aktivasi Token
|
|
11
11
|
openclaw smart-auth YOUR_SECRET_TOKEN
|
|
12
|
+
|
|
13
|
+
# 3. Cek status semua fungsi MCP
|
|
14
|
+
openclaw smart-status
|
|
12
15
|
```
|
|
13
16
|
|
|
17
|
+
## ✅ Command Tambahan
|
|
18
|
+
- `openclaw smart-auth <token>` → menyimpan dan validasi token Smart Report.
|
|
19
|
+
- `openclaw smart-status` → health-check semua fungsi MCP utama:
|
|
20
|
+
- `company/info`
|
|
21
|
+
- `smartreport/dashboard`
|
|
22
|
+
- `employees/list`
|
|
23
|
+
- `reports/list`
|
|
24
|
+
- `divisions/list`
|
|
25
|
+
- `guides/list`
|
|
26
|
+
- `analyze_performance`
|
|
27
|
+
|
|
28
|
+
|
|
14
29
|
## 📖 Dokumentasi Lengkap
|
|
15
30
|
Kami telah menyediakan panduan langkah-demi-langkah untuk pengguna teknis maupun non-teknis:
|
|
16
31
|
* [**Panduan Pengguna (User Guide)**](docs/USER_GUIDE.md) - Prasyarat, Instalasi, Tooling, dan Troubleshooting.
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ async function callMcp(api, method, params = {}) {
|
|
|
36
36
|
const plugin = {
|
|
37
37
|
id: PLUGIN_ID,
|
|
38
38
|
name: "Smart Report Integration",
|
|
39
|
-
version: "2100.11.
|
|
39
|
+
version: "2100.11.2",
|
|
40
40
|
register(api) {
|
|
41
41
|
// 1. CLI Commands
|
|
42
42
|
api.registerCli(({ program }) => {
|
|
@@ -62,7 +62,46 @@ const plugin = {
|
|
|
62
62
|
process.exit(1);
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
|
-
|
|
65
|
+
program
|
|
66
|
+
.command('smart-status')
|
|
67
|
+
.description('Check Smart Report MCP connectivity and core functions status')
|
|
68
|
+
.action(async () => {
|
|
69
|
+
const checks = [];
|
|
70
|
+
const runCheck = async (name, fn) => {
|
|
71
|
+
try {
|
|
72
|
+
const result = await fn();
|
|
73
|
+
const detail = Array.isArray(result)
|
|
74
|
+
? `OK (items=${result.length})`
|
|
75
|
+
: 'OK';
|
|
76
|
+
checks.push({ name, status: '✅', detail });
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
checks.push({ name, status: '❌', detail: err?.message || 'Unknown error' });
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
await runCheck('auth/company-info', async () => callMcp(api, 'company/info', {}));
|
|
83
|
+
await runCheck('dashboard', async () => callMcp(api, 'smartreport/dashboard', { mode: 'compact' }));
|
|
84
|
+
await runCheck('employees/list', async () => callMcp(api, 'employees/list', {}));
|
|
85
|
+
await runCheck('reports/list', async () => callMcp(api, 'reports/list', { per_page: 5 }));
|
|
86
|
+
await runCheck('divisions/list', async () => callMcp(api, 'divisions/list', {}));
|
|
87
|
+
await runCheck('guides/list', async () => callMcp(api, 'guides/list', {}));
|
|
88
|
+
await runCheck('analyze_performance', async () => callMcp(api, 'analyze_performance', {}));
|
|
89
|
+
console.log('\n📊 Smart Report MCP Status');
|
|
90
|
+
console.log('----------------------------------------');
|
|
91
|
+
for (const c of checks) {
|
|
92
|
+
console.log(`${c.status} ${c.name} -> ${c.detail}`);
|
|
93
|
+
}
|
|
94
|
+
const failed = checks.filter(c => c.status === '❌').length;
|
|
95
|
+
console.log('----------------------------------------');
|
|
96
|
+
if (failed === 0) {
|
|
97
|
+
console.log('✅ All MCP function checks passed.');
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
console.log(`⚠️ ${failed} check(s) failed.`);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}, { commands: ['smart-auth', 'smart-status'] });
|
|
66
105
|
// 2. Resources
|
|
67
106
|
api.registerResource({
|
|
68
107
|
uri: 'smartreport://reports',
|
package/dist/openclaw.cjs
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
const
|
|
2
|
-
const plugin = m.default || m;
|
|
1
|
+
const mod = require('./dist/index.js');
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const register =
|
|
4
|
+
mod.register ||
|
|
5
|
+
mod.activate ||
|
|
6
|
+
(mod.default && (mod.default.register || mod.default.activate));
|
|
7
|
+
|
|
8
|
+
if (typeof register !== 'function') {
|
|
9
|
+
throw new Error('smart-report-plugin: register/activate export not found');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = register;
|
|
13
|
+
module.exports.register = register;
|
|
14
|
+
module.exports.activate = register;
|
package/openclaw.cjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const mod = require('./dist/index.js');
|
|
2
|
+
|
|
3
|
+
const register =
|
|
4
|
+
mod.register ||
|
|
5
|
+
mod.activate ||
|
|
6
|
+
(mod.default && (mod.default.register || mod.default.activate));
|
|
7
|
+
|
|
8
|
+
if (typeof register !== 'function') {
|
|
9
|
+
throw new Error('smart-report-plugin: register/activate export not found');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = register;
|
|
13
|
+
module.exports.register = register;
|
|
14
|
+
module.exports.activate = register;
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "smart-report-plugin",
|
|
3
3
|
"name": "Smart Report Integration",
|
|
4
|
-
"version": "2100.11.
|
|
4
|
+
"version": "2100.11.2",
|
|
5
5
|
"description": "Integration plugin for Smart Report and AI Analytics with Daily Dashboard and Dynamic Guides",
|
|
6
6
|
"entrypoint": "./dist/openclaw.cjs",
|
|
7
7
|
"skills": [
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sodikinnaa/smart-report-plugin",
|
|
3
|
-
"version": "2100.11.
|
|
3
|
+
"version": "2100.11.2",
|
|
4
4
|
"description": "OpenClaw plugin for Smart Report system integration with Daily Dashboard",
|
|
5
|
-
"main": "./dist/
|
|
6
|
-
"
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
5
|
+
"main": "./dist/openclaw.cjs",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
8
7
|
"scripts": {
|
|
9
|
-
"build": "tsc &&
|
|
10
|
-
"test": "node
|
|
8
|
+
"build": "tsc && cp ./openclaw.cjs ./dist/openclaw.cjs",
|
|
9
|
+
"test": "node scripts/test-loader.js",
|
|
11
10
|
"publish": "npm publish --access public"
|
|
12
11
|
},
|
|
13
12
|
"keywords": [
|
|
@@ -23,6 +22,7 @@
|
|
|
23
22
|
]
|
|
24
23
|
},
|
|
25
24
|
"devDependencies": {
|
|
25
|
+
"@types/node": "^25.3.3",
|
|
26
26
|
"typescript": "^5.0.0"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// CI Gate Simulation
|
|
2
|
+
try {
|
|
3
|
+
const plugin = require('../dist/index.js');
|
|
4
|
+
console.log('Loading plugin:', Object.keys(plugin));
|
|
5
|
+
|
|
6
|
+
if (typeof plugin.register !== 'function' && typeof plugin.activate !== 'function') {
|
|
7
|
+
console.error('❌ CI Gate Failed: plugin export missing register/activate');
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
console.log('✅ CI Gate Passed: plugin exports register/activate correctly');
|
|
12
|
+
process.exit(0);
|
|
13
|
+
} catch (err) {
|
|
14
|
+
console.error('❌ CI Gate Failed with Exception:', err.message);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -37,7 +37,7 @@ async function callMcp(api: any, method: string, params: any = {}) {
|
|
|
37
37
|
const plugin: any = {
|
|
38
38
|
id: PLUGIN_ID,
|
|
39
39
|
name: "Smart Report Integration",
|
|
40
|
-
version: "2100.11.
|
|
40
|
+
version: "2100.11.2",
|
|
41
41
|
|
|
42
42
|
register(api: any) {
|
|
43
43
|
// 1. CLI Commands
|
|
@@ -65,7 +65,49 @@ const plugin: any = {
|
|
|
65
65
|
process.exit(1);
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
|
-
|
|
68
|
+
|
|
69
|
+
program
|
|
70
|
+
.command('smart-status')
|
|
71
|
+
.description('Check Smart Report MCP connectivity and core functions status')
|
|
72
|
+
.action(async () => {
|
|
73
|
+
const checks: Array<{ name: string; status: string; detail: string }> = [];
|
|
74
|
+
|
|
75
|
+
const runCheck = async (name: string, fn: () => Promise<any>) => {
|
|
76
|
+
try {
|
|
77
|
+
const result = await fn();
|
|
78
|
+
const detail = Array.isArray(result)
|
|
79
|
+
? `OK (items=${result.length})`
|
|
80
|
+
: 'OK';
|
|
81
|
+
checks.push({ name, status: '✅', detail });
|
|
82
|
+
} catch (err: any) {
|
|
83
|
+
checks.push({ name, status: '❌', detail: err?.message || 'Unknown error' });
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
await runCheck('auth/company-info', async () => callMcp(api, 'company/info', {}));
|
|
88
|
+
await runCheck('dashboard', async () => callMcp(api, 'smartreport/dashboard', { mode: 'compact' }));
|
|
89
|
+
await runCheck('employees/list', async () => callMcp(api, 'employees/list', {}));
|
|
90
|
+
await runCheck('reports/list', async () => callMcp(api, 'reports/list', { per_page: 5 }));
|
|
91
|
+
await runCheck('divisions/list', async () => callMcp(api, 'divisions/list', {}));
|
|
92
|
+
await runCheck('guides/list', async () => callMcp(api, 'guides/list', {}));
|
|
93
|
+
await runCheck('analyze_performance', async () => callMcp(api, 'analyze_performance', {}));
|
|
94
|
+
|
|
95
|
+
console.log('\n📊 Smart Report MCP Status');
|
|
96
|
+
console.log('----------------------------------------');
|
|
97
|
+
for (const c of checks) {
|
|
98
|
+
console.log(`${c.status} ${c.name} -> ${c.detail}`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const failed = checks.filter(c => c.status === '❌').length;
|
|
102
|
+
console.log('----------------------------------------');
|
|
103
|
+
if (failed === 0) {
|
|
104
|
+
console.log('✅ All MCP function checks passed.');
|
|
105
|
+
} else {
|
|
106
|
+
console.log(`⚠️ ${failed} check(s) failed.`);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}, { commands: ['smart-auth', 'smart-status'] });
|
|
69
111
|
|
|
70
112
|
// 2. Resources
|
|
71
113
|
api.registerResource({
|
package/tsconfig.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"target": "
|
|
3
|
+
"target": "ES2022",
|
|
4
4
|
"module": "CommonJS",
|
|
5
|
-
"lib": ["
|
|
5
|
+
"lib": ["ES2022", "DOM"],
|
|
6
6
|
"declaration": true,
|
|
7
7
|
"outDir": "./dist",
|
|
8
8
|
"strict": true,
|
|
9
9
|
"esModuleInterop": true,
|
|
10
10
|
"skipLibCheck": true,
|
|
11
11
|
"forceConsistentCasingInFileNames": true,
|
|
12
|
-
"moduleResolution": "
|
|
12
|
+
"moduleResolution": "node"
|
|
13
13
|
},
|
|
14
14
|
"include": ["src/**/*"]
|
|
15
15
|
}
|
package/scripts/audit-sync.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
|
|
6
|
-
const pluginPath = process.argv[2] || '.';
|
|
7
|
-
const packageJsonPath = path.join(pluginPath, 'package.json');
|
|
8
|
-
const openclawJsonPath = path.join(pluginPath, 'openclaw.plugin.json');
|
|
9
|
-
const distIndexPath = path.join(pluginPath, 'dist/index.js');
|
|
10
|
-
|
|
11
|
-
console.log('🔍 Starting Plugin Sync & Audit...');
|
|
12
|
-
|
|
13
|
-
// 1. Read package.json
|
|
14
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
15
|
-
console.error('❌ package.json not found');
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
19
|
-
const version = pkg.version;
|
|
20
|
-
|
|
21
|
-
// 2. Sync openclaw.plugin.json
|
|
22
|
-
if (fs.existsSync(openclawJsonPath)) {
|
|
23
|
-
const pluginJson = JSON.parse(fs.readFileSync(openclawJsonPath, 'utf8'));
|
|
24
|
-
if (pluginJson.version !== version) {
|
|
25
|
-
console.log(`⚠️ Syncing openclaw.plugin.json version: ${pluginJson.version} -> ${version}`);
|
|
26
|
-
pluginJson.version = version;
|
|
27
|
-
fs.writeFileSync(openclawJsonPath, JSON.stringify(pluginJson, null, 2));
|
|
28
|
-
} else {
|
|
29
|
-
console.log(`✅ openclaw.plugin.json version matches: ${version}`);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// 3. Verify dist/index.js (Loader Contract)
|
|
34
|
-
if (fs.existsSync(distIndexPath)) {
|
|
35
|
-
const content = fs.readFileSync(distIndexPath, 'utf8');
|
|
36
|
-
const hasRegister = content.includes('export function register') || content.includes('export const register') || content.includes('exports.register');
|
|
37
|
-
const hasActivate = content.includes('export function activate') || content.includes('export const activate') || content.includes('exports.activate');
|
|
38
|
-
const hasVersionMatch = content.includes(`version: "${version}"`) || content.includes(`version: '${version}'`);
|
|
39
|
-
|
|
40
|
-
if (!hasRegister || !hasActivate) {
|
|
41
|
-
console.error('❌ Loader Contract Violation: Missing register or activate export in dist/index.js');
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// 4. Entrypoint verification
|
|
46
|
-
const pluginJsonPath = path.join(pluginPath, 'openclaw.plugin.json');
|
|
47
|
-
if (fs.existsSync(pluginJsonPath)) {
|
|
48
|
-
const pluginJson = JSON.parse(fs.readFileSync(pluginJsonPath, 'utf8'));
|
|
49
|
-
if (!pluginJson.entrypoint || !pluginJson.entrypoint.startsWith('./')) {
|
|
50
|
-
console.error('❌ Manifest Violation: "entrypoint" must exist and start with "./" (e.g., "./dist/index.js")');
|
|
51
|
-
process.exit(1);
|
|
52
|
-
}
|
|
53
|
-
if (pluginJson.main) {
|
|
54
|
-
console.error('❌ Manifest Violation: "main" field detected in openclaw.plugin.json. Use "entrypoint" only for OpenClaw manifests to avoid loader confusion.');
|
|
55
|
-
process.exit(1);
|
|
56
|
-
}
|
|
57
|
-
console.log('✅ Manifest: valid entrypoint found and no "main" field.');
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
console.log('✅ Loader Contract: register/activate exports found.');
|
|
61
|
-
|
|
62
|
-
if (!hasVersionMatch) {
|
|
63
|
-
console.error(`❌ Internal version in dist/index.js out of sync! Build target: ${version}`);
|
|
64
|
-
process.exit(1);
|
|
65
|
-
}
|
|
66
|
-
console.log(`✅ Internal build version matches: ${version}`);
|
|
67
|
-
} else {
|
|
68
|
-
console.warn('⚠️ dist/index.js not found. Run build first.');
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
console.log('🚀 Audit Completed Successfully.');
|
package/test/api.test.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import axios from 'axios';
|
|
3
|
-
|
|
4
|
-
const API_BASE = 'https://smartreport.siapdigital.my.id/api/mcp';
|
|
5
|
-
const token = 'Wkr4v8TjpoXGPt4arv8EcBuXYpZaSDX8P0WL4dwPcanNRUAfNUrHF33j081lII30';
|
|
6
|
-
|
|
7
|
-
async function testApi() {
|
|
8
|
-
try {
|
|
9
|
-
console.log('Testing Smart Report API with provided token...');
|
|
10
|
-
const response = await axios.post(API_BASE, {
|
|
11
|
-
jsonrpc: '2.0',
|
|
12
|
-
method: 'guides/list',
|
|
13
|
-
params: {},
|
|
14
|
-
id: Date.now()
|
|
15
|
-
}, {
|
|
16
|
-
headers: {
|
|
17
|
-
'Authorization': `Bearer ${token}`,
|
|
18
|
-
'Content-Type': 'application/json',
|
|
19
|
-
'Accept': 'application/json'
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
if (response.data.error) {
|
|
24
|
-
console.error('❌ API Error:', response.data.error.message);
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
console.log('✅ API Success! Found', response.data.result.length, 'guides.');
|
|
29
|
-
process.exit(0);
|
|
30
|
-
} catch (err) {
|
|
31
|
-
console.error('❌ Connection Error:', err.message);
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
testApi();
|
package/test/simple.test.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
console.log('Dummy test passed');
|