aranea-sdk-cli 0.3.2 → 0.3.3
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 +23 -0
- package/dist/commands/knowledge.js +98 -23
- package/dist/commands/metatron.js +19 -7
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,6 +38,29 @@ aranea-sdk metatron chat
|
|
|
38
38
|
2. **新知見発見時**: `knowledge add` でナレッジベースに追加
|
|
39
39
|
3. **デバイス登録時**: `register --dry-run` で検証後、実登録
|
|
40
40
|
|
|
41
|
+
### 🔴 特に貴重なナレッジ(必ず追加すべき)
|
|
42
|
+
|
|
43
|
+
以下の情報は一般ドキュメントでは得られない**実践的知見**です。
|
|
44
|
+
発見次第、CLIでナレッジベースに追加してください:
|
|
45
|
+
|
|
46
|
+
| カテゴリ | 追加すべき情報 | 例 |
|
|
47
|
+
|---------|--------------|-----|
|
|
48
|
+
| `incident` | ハードウェア固有の問題・解決策 | メモリ不足でクラッシュ、タイムアウトエラー |
|
|
49
|
+
| `tip` | テスト・デバッグで追い込んだパラメータ | HTTPSタイムアウト15秒必要 |
|
|
50
|
+
| `tip` | ESP32メモリ関連設定 | SSL接続に50KB必要 |
|
|
51
|
+
| `tip` | SBC (OrangePi等) のサービス起動・権限問題 | systemd設定、sudoers設定 |
|
|
52
|
+
| `incident` | ハードウェア相性問題 | 特定WiFiモジュールとの非互換 |
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# 例: インシデント対応で発見した設定値を追加
|
|
56
|
+
aranea-sdk knowledge add \
|
|
57
|
+
--title "ESP32 HTTPSタイムアウト 15秒必要" \
|
|
58
|
+
--category tip \
|
|
59
|
+
--content "ESP32でHTTPS接続する場合、最低15秒のタイムアウトが必要。初回SSL handshakeは特に時間がかかる。-11 READ_TIMEOUTエラーの原因。" \
|
|
60
|
+
--keywords "esp32,https,timeout,ssl,handshake" \
|
|
61
|
+
--device-types "aranea_ar-is04a,aranea_ar-is05a"
|
|
62
|
+
```
|
|
63
|
+
|
|
41
64
|
---
|
|
42
65
|
|
|
43
66
|
## 概要
|
|
@@ -54,10 +54,17 @@ const ora_1 = __importDefault(require("ora"));
|
|
|
54
54
|
const axios_1 = __importDefault(require("axios"));
|
|
55
55
|
const fs = __importStar(require("fs"));
|
|
56
56
|
const path = __importStar(require("path"));
|
|
57
|
+
const config_1 = require("../config");
|
|
57
58
|
// ============================================================================
|
|
58
59
|
// Config
|
|
59
60
|
// ============================================================================
|
|
60
|
-
const
|
|
61
|
+
const KNOWLEDGE_API_ENDPOINTS = {
|
|
62
|
+
production: 'https://asia-northeast1-mobesorder.cloudfunctions.net/araneaKnowledgeManagement',
|
|
63
|
+
staging: 'https://asia-northeast1-mobesorder-staging.cloudfunctions.net/araneaKnowledgeManagement',
|
|
64
|
+
};
|
|
65
|
+
function getKnowledgeApiBase(env) {
|
|
66
|
+
return KNOWLEDGE_API_ENDPOINTS[env];
|
|
67
|
+
}
|
|
61
68
|
// カテゴリ定義
|
|
62
69
|
const CATEGORIES = ['api', 'guide', 'code', 'reference', 'incident', 'tip'];
|
|
63
70
|
// ============================================================================
|
|
@@ -72,8 +79,9 @@ function getAuthToken() {
|
|
|
72
79
|
/**
|
|
73
80
|
* API呼び出し(Callable形式)
|
|
74
81
|
*/
|
|
75
|
-
async function callKnowledgeAPI(action, params, token) {
|
|
76
|
-
const
|
|
82
|
+
async function callKnowledgeAPI(action, params, token, env) {
|
|
83
|
+
const apiBase = getKnowledgeApiBase(env);
|
|
84
|
+
const response = await axios_1.default.post(apiBase, { data: { action, ...params } }, {
|
|
77
85
|
headers: {
|
|
78
86
|
'Content-Type': 'application/json',
|
|
79
87
|
Authorization: `Bearer ${token}`,
|
|
@@ -131,9 +139,12 @@ exports.knowledgeCommand
|
|
|
131
139
|
.option('--device-types <types>', '関連デバイスタイプ (カンマ区切り)')
|
|
132
140
|
.option('--status <status>', 'ステータス (draft|published)', 'draft')
|
|
133
141
|
.option('--token <token>', '認証トークン')
|
|
142
|
+
.option('-e, --endpoint <env>', '環境 (staging|production)', 'production')
|
|
134
143
|
.action(async (options) => {
|
|
135
144
|
try {
|
|
136
|
-
|
|
145
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
146
|
+
(0, config_1.warnIfProduction)(env, 'knowledge add');
|
|
147
|
+
console.log(chalk_1.default.bold(`\n=== Knowledge Add (${env}) ===\n`));
|
|
137
148
|
// 認証トークン
|
|
138
149
|
const token = options.token || getAuthToken();
|
|
139
150
|
if (!token) {
|
|
@@ -186,7 +197,7 @@ exports.knowledgeCommand
|
|
|
186
197
|
relatedDeviceTypes: deviceTypes,
|
|
187
198
|
status: options.status,
|
|
188
199
|
},
|
|
189
|
-
}, token);
|
|
200
|
+
}, token, env);
|
|
190
201
|
spinner.stop();
|
|
191
202
|
if (result.success) {
|
|
192
203
|
console.log(chalk_1.default.green('✓ ナレッジエントリを追加しました'));
|
|
@@ -194,6 +205,7 @@ exports.knowledgeCommand
|
|
|
194
205
|
console.log(` Title: ${options.title}`);
|
|
195
206
|
console.log(` Category: ${options.category}`);
|
|
196
207
|
console.log(` Status: ${options.status}`);
|
|
208
|
+
console.log(` Environment: ${env}`);
|
|
197
209
|
}
|
|
198
210
|
else {
|
|
199
211
|
console.log(chalk_1.default.red(`✗ 追加失敗: ${result.error}`));
|
|
@@ -212,9 +224,11 @@ exports.knowledgeCommand
|
|
|
212
224
|
.option('-c, --category <category>', 'カテゴリフィルタ')
|
|
213
225
|
.option('-l, --limit <limit>', '結果数', '10')
|
|
214
226
|
.option('--token <token>', '認証トークン')
|
|
227
|
+
.option('-e, --endpoint <env>', '環境 (staging|production)', 'production')
|
|
215
228
|
.action(async (options) => {
|
|
216
229
|
try {
|
|
217
|
-
|
|
230
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
231
|
+
console.log(chalk_1.default.bold(`\n=== Knowledge Search (${env}) ===\n`));
|
|
218
232
|
const token = options.token || getAuthToken();
|
|
219
233
|
if (!token) {
|
|
220
234
|
console.error(chalk_1.default.red('❌ 認証トークンが必要です'));
|
|
@@ -225,7 +239,7 @@ exports.knowledgeCommand
|
|
|
225
239
|
query: options.query,
|
|
226
240
|
category: options.category,
|
|
227
241
|
limit: parseInt(options.limit, 10),
|
|
228
|
-
}, token);
|
|
242
|
+
}, token, env);
|
|
229
243
|
spinner.stop();
|
|
230
244
|
if (result.success && result.data) {
|
|
231
245
|
const entries = Array.isArray(result.data) ? result.data : [];
|
|
@@ -254,9 +268,11 @@ exports.knowledgeCommand
|
|
|
254
268
|
.option('-s, --status <status>', 'ステータスフィルタ (draft|published|archived)')
|
|
255
269
|
.option('-l, --limit <limit>', '表示数', '20')
|
|
256
270
|
.option('--token <token>', '認証トークン')
|
|
271
|
+
.option('-e, --endpoint <env>', '環境 (staging|production)', 'production')
|
|
257
272
|
.action(async (options) => {
|
|
258
273
|
try {
|
|
259
|
-
|
|
274
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
275
|
+
console.log(chalk_1.default.bold(`\n=== Knowledge List (${env}) ===\n`));
|
|
260
276
|
const token = options.token || getAuthToken();
|
|
261
277
|
if (!token) {
|
|
262
278
|
console.error(chalk_1.default.red('❌ 認証トークンが必要です'));
|
|
@@ -267,7 +283,7 @@ exports.knowledgeCommand
|
|
|
267
283
|
category: options.category,
|
|
268
284
|
status: options.status,
|
|
269
285
|
limit: parseInt(options.limit, 10),
|
|
270
|
-
}, token);
|
|
286
|
+
}, token, env);
|
|
271
287
|
spinner.stop();
|
|
272
288
|
if (result.success && result.data) {
|
|
273
289
|
const entries = Array.isArray(result.data) ? result.data : [];
|
|
@@ -294,16 +310,18 @@ exports.knowledgeCommand
|
|
|
294
310
|
.description('ナレッジエントリを取得')
|
|
295
311
|
.requiredOption('-i, --id <id>', 'エントリID')
|
|
296
312
|
.option('--token <token>', '認証トークン')
|
|
313
|
+
.option('-e, --endpoint <env>', '環境 (staging|production)', 'production')
|
|
297
314
|
.action(async (options) => {
|
|
298
315
|
try {
|
|
299
|
-
|
|
316
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
317
|
+
console.log(chalk_1.default.bold(`\n=== Knowledge Get (${env}) ===\n`));
|
|
300
318
|
const token = options.token || getAuthToken();
|
|
301
319
|
if (!token) {
|
|
302
320
|
console.error(chalk_1.default.red('❌ 認証トークンが必要です'));
|
|
303
321
|
process.exit(1);
|
|
304
322
|
}
|
|
305
323
|
const spinner = (0, ora_1.default)('ナレッジを取得中...').start();
|
|
306
|
-
const result = await callKnowledgeAPI('get', { id: options.id }, token);
|
|
324
|
+
const result = await callKnowledgeAPI('get', { id: options.id }, token, env);
|
|
307
325
|
spinner.stop();
|
|
308
326
|
if (result.success && result.data) {
|
|
309
327
|
formatEntry(result.data, true);
|
|
@@ -323,10 +341,13 @@ exports.knowledgeCommand
|
|
|
323
341
|
.description('ナレッジエントリを削除 (アーカイブ)')
|
|
324
342
|
.requiredOption('-i, --id <id>', 'エントリID')
|
|
325
343
|
.option('--token <token>', '認証トークン')
|
|
344
|
+
.option('-e, --endpoint <env>', '環境 (staging|production)', 'production')
|
|
326
345
|
.option('-y, --yes', '確認をスキップ')
|
|
327
346
|
.action(async (options) => {
|
|
328
347
|
try {
|
|
329
|
-
|
|
348
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
349
|
+
(0, config_1.warnIfProduction)(env, 'knowledge delete');
|
|
350
|
+
console.log(chalk_1.default.bold(`\n=== Knowledge Delete (${env}) ===\n`));
|
|
330
351
|
const token = options.token || getAuthToken();
|
|
331
352
|
if (!token) {
|
|
332
353
|
console.error(chalk_1.default.red('❌ 認証トークンが必要です'));
|
|
@@ -338,7 +359,7 @@ exports.knowledgeCommand
|
|
|
338
359
|
// Note: In a real CLI, would use inquirer for confirmation
|
|
339
360
|
}
|
|
340
361
|
const spinner = (0, ora_1.default)('削除中...').start();
|
|
341
|
-
const result = await callKnowledgeAPI('delete', { id: options.id }, token);
|
|
362
|
+
const result = await callKnowledgeAPI('delete', { id: options.id }, token, env);
|
|
342
363
|
spinner.stop();
|
|
343
364
|
if (result.success) {
|
|
344
365
|
console.log(chalk_1.default.green('✓ ナレッジエントリをアーカイブしました'));
|
|
@@ -355,20 +376,74 @@ exports.knowledgeCommand
|
|
|
355
376
|
// knowledge categories
|
|
356
377
|
exports.knowledgeCommand
|
|
357
378
|
.command('categories')
|
|
358
|
-
.description('
|
|
379
|
+
.description('利用可能なカテゴリ一覧と追加すべきナレッジの例')
|
|
359
380
|
.action(() => {
|
|
360
381
|
console.log(chalk_1.default.bold('\n=== Knowledge Categories ===\n'));
|
|
361
|
-
const
|
|
362
|
-
api:
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
382
|
+
const categoryInfo = {
|
|
383
|
+
api: {
|
|
384
|
+
desc: 'API仕様・エンドポイント',
|
|
385
|
+
examples: [
|
|
386
|
+
'State Report API の仕様変更',
|
|
387
|
+
'エンドポイントURL・認証方式',
|
|
388
|
+
],
|
|
389
|
+
},
|
|
390
|
+
guide: {
|
|
391
|
+
desc: '実装ガイド・チュートリアル',
|
|
392
|
+
examples: [
|
|
393
|
+
'ESP32 State Report実装手順',
|
|
394
|
+
'OrangePi サービス設定ガイド',
|
|
395
|
+
],
|
|
396
|
+
},
|
|
397
|
+
code: {
|
|
398
|
+
desc: 'コードサンプル・スニペット',
|
|
399
|
+
examples: [
|
|
400
|
+
'Arduino HTTPS接続コード',
|
|
401
|
+
'Python MQTT受信サンプル',
|
|
402
|
+
],
|
|
403
|
+
},
|
|
404
|
+
reference: {
|
|
405
|
+
desc: 'リファレンス・仕様書',
|
|
406
|
+
examples: [
|
|
407
|
+
'スキーマ定義一覧',
|
|
408
|
+
'エラーコード一覧',
|
|
409
|
+
],
|
|
410
|
+
},
|
|
411
|
+
incident: {
|
|
412
|
+
desc: 'インシデント・トラブルシューティング',
|
|
413
|
+
examples: [
|
|
414
|
+
'⚠️ ハードウェア固有の問題・解決策',
|
|
415
|
+
'⚠️ メモリ不足・タイムアウト事例',
|
|
416
|
+
'⚠️ 相性問題・回避策',
|
|
417
|
+
],
|
|
418
|
+
},
|
|
419
|
+
tip: {
|
|
420
|
+
desc: 'Tips・ノウハウ(一般情報では得られない実践知見)',
|
|
421
|
+
examples: [
|
|
422
|
+
'⚠️ ESP32 HTTPSタイムアウト 15秒必要',
|
|
423
|
+
'⚠️ OrangePi サービス起動順序',
|
|
424
|
+
'⚠️ メモリ設定・バッファサイズの追い込み値',
|
|
425
|
+
'⚠️ ハードウェア相性・非互換情報',
|
|
426
|
+
],
|
|
427
|
+
},
|
|
368
428
|
};
|
|
369
429
|
for (const cat of CATEGORIES) {
|
|
370
|
-
|
|
430
|
+
const info = categoryInfo[cat];
|
|
431
|
+
console.log(` ${chalk_1.default.cyan(cat.padEnd(12))} ${info.desc}`);
|
|
432
|
+
for (const ex of info.examples) {
|
|
433
|
+
if (ex.startsWith('⚠️')) {
|
|
434
|
+
console.log(` ${chalk_1.default.yellow(ex)}`);
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
console.log(` ${chalk_1.default.gray('- ' + ex)}`);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
console.log('');
|
|
371
441
|
}
|
|
372
|
-
console.log('');
|
|
442
|
+
console.log(chalk_1.default.bold('📝 AIエージェント向け: 以下のナレッジは特に貴重です\n'));
|
|
443
|
+
console.log(chalk_1.default.yellow(' • インシデント対応で発見したハードウェア固有の設定値'));
|
|
444
|
+
console.log(chalk_1.default.yellow(' • テスト・デバッグで追い込んだパラメータ(タイムアウト、バッファサイズ等)'));
|
|
445
|
+
console.log(chalk_1.default.yellow(' • ESP32のメモリ関連、SBCのサービス起動・権限問題'));
|
|
446
|
+
console.log(chalk_1.default.yellow(' • ハードウェア相性問題と回避策'));
|
|
447
|
+
console.log(chalk_1.default.yellow(' • 一般的なドキュメントには載っていない実践的知見\n'));
|
|
373
448
|
});
|
|
374
449
|
exports.default = exports.knowledgeCommand;
|
|
@@ -51,10 +51,17 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
51
51
|
const ora_1 = __importDefault(require("ora"));
|
|
52
52
|
const axios_1 = __importDefault(require("axios"));
|
|
53
53
|
const readline = __importStar(require("readline"));
|
|
54
|
+
const config_1 = require("../config");
|
|
54
55
|
// ============================================================================
|
|
55
56
|
// Config
|
|
56
57
|
// ============================================================================
|
|
57
|
-
const
|
|
58
|
+
const METATRON_API_ENDPOINTS = {
|
|
59
|
+
production: 'https://asia-northeast1-mobesorder.cloudfunctions.net/araneaMetatronQuery',
|
|
60
|
+
staging: 'https://asia-northeast1-mobesorder-staging.cloudfunctions.net/araneaMetatronQuery',
|
|
61
|
+
};
|
|
62
|
+
function getMetatronApiBase(env) {
|
|
63
|
+
return METATRON_API_ENDPOINTS[env];
|
|
64
|
+
}
|
|
58
65
|
// ============================================================================
|
|
59
66
|
// Helper Functions
|
|
60
67
|
// ============================================================================
|
|
@@ -67,8 +74,9 @@ function getAuthToken() {
|
|
|
67
74
|
/**
|
|
68
75
|
* Metatron API呼び出し
|
|
69
76
|
*/
|
|
70
|
-
async function queryMetatron(query, context, token) {
|
|
71
|
-
const
|
|
77
|
+
async function queryMetatron(query, context, token, env) {
|
|
78
|
+
const apiBase = getMetatronApiBase(env);
|
|
79
|
+
const response = await axios_1.default.post(apiBase, { data: { query, context } }, {
|
|
72
80
|
headers: {
|
|
73
81
|
'Content-Type': 'application/json',
|
|
74
82
|
Authorization: `Bearer ${token}`,
|
|
@@ -110,11 +118,13 @@ exports.metatronCommand
|
|
|
110
118
|
.description('単発質問')
|
|
111
119
|
.option('--context <context>', 'コンテキスト', 'aranea_sdk_cli')
|
|
112
120
|
.option('--token <token>', '認証トークン')
|
|
121
|
+
.option('-e, --endpoint <env>', '環境 (staging|production)', 'production')
|
|
113
122
|
.option('--raw', 'JSON出力')
|
|
114
123
|
.action(async (question, options) => {
|
|
115
124
|
try {
|
|
125
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
116
126
|
if (!options.raw) {
|
|
117
|
-
console.log(chalk_1.default.bold(
|
|
127
|
+
console.log(chalk_1.default.bold(`\n=== AraneaMetatron (${env}) ===\n`));
|
|
118
128
|
console.log(chalk_1.default.gray(`Q: ${question}`));
|
|
119
129
|
}
|
|
120
130
|
const token = options.token || getAuthToken();
|
|
@@ -123,7 +133,7 @@ exports.metatronCommand
|
|
|
123
133
|
process.exit(1);
|
|
124
134
|
}
|
|
125
135
|
const spinner = options.raw ? null : (0, ora_1.default)('回答生成中...').start();
|
|
126
|
-
const result = await queryMetatron(question, options.context, token);
|
|
136
|
+
const result = await queryMetatron(question, options.context, token, env);
|
|
127
137
|
spinner?.stop();
|
|
128
138
|
if (options.raw) {
|
|
129
139
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -143,8 +153,10 @@ exports.metatronCommand
|
|
|
143
153
|
.description('対話モード (REPL)')
|
|
144
154
|
.option('--context <context>', 'コンテキスト', 'aranea_sdk_cli')
|
|
145
155
|
.option('--token <token>', '認証トークン')
|
|
156
|
+
.option('-e, --endpoint <env>', '環境 (staging|production)', 'production')
|
|
146
157
|
.action(async (options) => {
|
|
147
|
-
|
|
158
|
+
const env = (0, config_1.resolveEnvironment)(options.endpoint);
|
|
159
|
+
console.log(chalk_1.default.bold(`\n=== AraneaMetatron Chat (${env}) ===\n`));
|
|
148
160
|
console.log(chalk_1.default.gray('AraneaSDKについて質問してください。'));
|
|
149
161
|
console.log(chalk_1.default.gray('終了するには "exit" または Ctrl+C を入力\n'));
|
|
150
162
|
const token = options.token || getAuthToken();
|
|
@@ -171,7 +183,7 @@ exports.metatronCommand
|
|
|
171
183
|
const spinner = (0, ora_1.default)('').start();
|
|
172
184
|
spinner.text = '';
|
|
173
185
|
try {
|
|
174
|
-
const result = await queryMetatron(query, options.context, token);
|
|
186
|
+
const result = await queryMetatron(query, options.context, token, env);
|
|
175
187
|
spinner.stop();
|
|
176
188
|
console.log('');
|
|
177
189
|
console.log(chalk_1.default.green('Metatron:'), result.answer);
|
package/dist/index.js
CHANGED