@switchbot/openapi-cli 3.2.1 → 3.3.0
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 +3 -1
- package/dist/index.js +57419 -170
- package/package.json +9 -5
- package/dist/api/client.d.ts +0 -31
- package/dist/api/client.js +0 -236
- package/dist/api/client.js.map +0 -1
- package/dist/auth.d.ts +0 -1
- package/dist/auth.js +0 -21
- package/dist/auth.js.map +0 -1
- package/dist/commands/agent-bootstrap.d.ts +0 -10
- package/dist/commands/agent-bootstrap.js +0 -200
- package/dist/commands/agent-bootstrap.js.map +0 -1
- package/dist/commands/auth.d.ts +0 -18
- package/dist/commands/auth.js +0 -355
- package/dist/commands/auth.js.map +0 -1
- package/dist/commands/batch.d.ts +0 -2
- package/dist/commands/batch.js +0 -414
- package/dist/commands/batch.js.map +0 -1
- package/dist/commands/cache.d.ts +0 -2
- package/dist/commands/cache.js +0 -127
- package/dist/commands/cache.js.map +0 -1
- package/dist/commands/capabilities.d.ts +0 -31
- package/dist/commands/capabilities.js +0 -383
- package/dist/commands/capabilities.js.map +0 -1
- package/dist/commands/catalog.d.ts +0 -2
- package/dist/commands/catalog.js +0 -360
- package/dist/commands/catalog.js.map +0 -1
- package/dist/commands/completion.d.ts +0 -2
- package/dist/commands/completion.js +0 -386
- package/dist/commands/completion.js.map +0 -1
- package/dist/commands/config.d.ts +0 -21
- package/dist/commands/config.js +0 -377
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/daemon.d.ts +0 -2
- package/dist/commands/daemon.js +0 -411
- package/dist/commands/daemon.js.map +0 -1
- package/dist/commands/device-meta.d.ts +0 -2
- package/dist/commands/device-meta.js +0 -160
- package/dist/commands/device-meta.js.map +0 -1
- package/dist/commands/devices.d.ts +0 -2
- package/dist/commands/devices.js +0 -949
- package/dist/commands/devices.js.map +0 -1
- package/dist/commands/doctor.d.ts +0 -3
- package/dist/commands/doctor.js +0 -1016
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/events.d.ts +0 -31
- package/dist/commands/events.js +0 -564
- package/dist/commands/events.js.map +0 -1
- package/dist/commands/expand.d.ts +0 -2
- package/dist/commands/expand.js +0 -131
- package/dist/commands/expand.js.map +0 -1
- package/dist/commands/explain.d.ts +0 -2
- package/dist/commands/explain.js +0 -140
- package/dist/commands/explain.js.map +0 -1
- package/dist/commands/health.d.ts +0 -8
- package/dist/commands/health.js +0 -114
- package/dist/commands/health.js.map +0 -1
- package/dist/commands/history.d.ts +0 -2
- package/dist/commands/history.js +0 -321
- package/dist/commands/history.js.map +0 -1
- package/dist/commands/identity.d.ts +0 -45
- package/dist/commands/identity.js +0 -60
- package/dist/commands/identity.js.map +0 -1
- package/dist/commands/install.d.ts +0 -20
- package/dist/commands/install.js +0 -247
- package/dist/commands/install.js.map +0 -1
- package/dist/commands/mcp.d.ts +0 -14
- package/dist/commands/mcp.js +0 -2018
- package/dist/commands/mcp.js.map +0 -1
- package/dist/commands/plan.d.ts +0 -51
- package/dist/commands/plan.js +0 -654
- package/dist/commands/plan.js.map +0 -1
- package/dist/commands/policy.d.ts +0 -24
- package/dist/commands/policy.js +0 -587
- package/dist/commands/policy.js.map +0 -1
- package/dist/commands/quota.d.ts +0 -2
- package/dist/commands/quota.js +0 -79
- package/dist/commands/quota.js.map +0 -1
- package/dist/commands/rules.d.ts +0 -2
- package/dist/commands/rules.js +0 -876
- package/dist/commands/rules.js.map +0 -1
- package/dist/commands/scenes.d.ts +0 -2
- package/dist/commands/scenes.js +0 -265
- package/dist/commands/scenes.js.map +0 -1
- package/dist/commands/schema.d.ts +0 -2
- package/dist/commands/schema.js +0 -185
- package/dist/commands/schema.js.map +0 -1
- package/dist/commands/status-sync.d.ts +0 -2
- package/dist/commands/status-sync.js +0 -132
- package/dist/commands/status-sync.js.map +0 -1
- package/dist/commands/uninstall.d.ts +0 -20
- package/dist/commands/uninstall.js +0 -238
- package/dist/commands/uninstall.js.map +0 -1
- package/dist/commands/upgrade-check.d.ts +0 -2
- package/dist/commands/upgrade-check.js +0 -107
- package/dist/commands/upgrade-check.js.map +0 -1
- package/dist/commands/watch.d.ts +0 -2
- package/dist/commands/watch.js +0 -195
- package/dist/commands/watch.js.map +0 -1
- package/dist/commands/webhook.d.ts +0 -2
- package/dist/commands/webhook.js +0 -183
- package/dist/commands/webhook.js.map +0 -1
- package/dist/config.d.ts +0 -57
- package/dist/config.js +0 -259
- package/dist/config.js.map +0 -1
- package/dist/credentials/backends/file.d.ts +0 -18
- package/dist/credentials/backends/file.js +0 -102
- package/dist/credentials/backends/file.js.map +0 -1
- package/dist/credentials/backends/linux.d.ts +0 -16
- package/dist/credentials/backends/linux.js +0 -130
- package/dist/credentials/backends/linux.js.map +0 -1
- package/dist/credentials/backends/macos.d.ts +0 -18
- package/dist/credentials/backends/macos.js +0 -130
- package/dist/credentials/backends/macos.js.map +0 -1
- package/dist/credentials/backends/windows.d.ts +0 -23
- package/dist/credentials/backends/windows.js +0 -216
- package/dist/credentials/backends/windows.js.map +0 -1
- package/dist/credentials/keychain.d.ts +0 -83
- package/dist/credentials/keychain.js +0 -89
- package/dist/credentials/keychain.js.map +0 -1
- package/dist/credentials/prime.d.ts +0 -32
- package/dist/credentials/prime.js +0 -53
- package/dist/credentials/prime.js.map +0 -1
- package/dist/devices/cache.d.ts +0 -79
- package/dist/devices/cache.js +0 -294
- package/dist/devices/cache.js.map +0 -1
- package/dist/devices/catalog.d.ts +0 -138
- package/dist/devices/catalog.js +0 -768
- package/dist/devices/catalog.js.map +0 -1
- package/dist/devices/device-meta.d.ts +0 -15
- package/dist/devices/device-meta.js +0 -57
- package/dist/devices/device-meta.js.map +0 -1
- package/dist/devices/history-agg.d.ts +0 -37
- package/dist/devices/history-agg.js +0 -139
- package/dist/devices/history-agg.js.map +0 -1
- package/dist/devices/history-query.d.ts +0 -45
- package/dist/devices/history-query.js +0 -182
- package/dist/devices/history-query.js.map +0 -1
- package/dist/devices/param-validator.d.ts +0 -40
- package/dist/devices/param-validator.js +0 -434
- package/dist/devices/param-validator.js.map +0 -1
- package/dist/devices/resources.d.ts +0 -74
- package/dist/devices/resources.js +0 -271
- package/dist/devices/resources.js.map +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js.map +0 -1
- package/dist/install/default-steps.d.ts +0 -66
- package/dist/install/default-steps.js +0 -258
- package/dist/install/default-steps.js.map +0 -1
- package/dist/install/preflight.d.ts +0 -60
- package/dist/install/preflight.js +0 -213
- package/dist/install/preflight.js.map +0 -1
- package/dist/install/steps.d.ts +0 -61
- package/dist/install/steps.js +0 -68
- package/dist/install/steps.js.map +0 -1
- package/dist/lib/command-keywords.d.ts +0 -5
- package/dist/lib/command-keywords.js +0 -18
- package/dist/lib/command-keywords.js.map +0 -1
- package/dist/lib/daemon-state.d.ts +0 -24
- package/dist/lib/daemon-state.js +0 -47
- package/dist/lib/daemon-state.js.map +0 -1
- package/dist/lib/destructive-mode.d.ts +0 -2
- package/dist/lib/destructive-mode.js +0 -13
- package/dist/lib/destructive-mode.js.map +0 -1
- package/dist/lib/devices.d.ts +0 -151
- package/dist/lib/devices.js +0 -383
- package/dist/lib/devices.js.map +0 -1
- package/dist/lib/idempotency.d.ts +0 -46
- package/dist/lib/idempotency.js +0 -107
- package/dist/lib/idempotency.js.map +0 -1
- package/dist/lib/plan-store.d.ts +0 -19
- package/dist/lib/plan-store.js +0 -69
- package/dist/lib/plan-store.js.map +0 -1
- package/dist/lib/request-context.d.ts +0 -7
- package/dist/lib/request-context.js +0 -13
- package/dist/lib/request-context.js.map +0 -1
- package/dist/lib/scenes.d.ts +0 -7
- package/dist/lib/scenes.js +0 -11
- package/dist/lib/scenes.js.map +0 -1
- package/dist/logger.d.ts +0 -4
- package/dist/logger.js +0 -17
- package/dist/logger.js.map +0 -1
- package/dist/mcp/device-history.d.ts +0 -36
- package/dist/mcp/device-history.js +0 -146
- package/dist/mcp/device-history.js.map +0 -1
- package/dist/mcp/events-subscription.d.ts +0 -45
- package/dist/mcp/events-subscription.js +0 -214
- package/dist/mcp/events-subscription.js.map +0 -1
- package/dist/mqtt/client.d.ts +0 -25
- package/dist/mqtt/client.js +0 -181
- package/dist/mqtt/client.js.map +0 -1
- package/dist/mqtt/credential.d.ts +0 -16
- package/dist/mqtt/credential.js +0 -31
- package/dist/mqtt/credential.js.map +0 -1
- package/dist/policy/add-rule.d.ts +0 -21
- package/dist/policy/add-rule.js +0 -125
- package/dist/policy/add-rule.js.map +0 -1
- package/dist/policy/diff.d.ts +0 -21
- package/dist/policy/diff.js +0 -92
- package/dist/policy/diff.js.map +0 -1
- package/dist/policy/format.d.ts +0 -6
- package/dist/policy/format.js +0 -58
- package/dist/policy/format.js.map +0 -1
- package/dist/policy/load.d.ts +0 -32
- package/dist/policy/load.js +0 -62
- package/dist/policy/load.js.map +0 -1
- package/dist/policy/migrate.d.ts +0 -21
- package/dist/policy/migrate.js +0 -68
- package/dist/policy/migrate.js.map +0 -1
- package/dist/policy/schema.d.ts +0 -5
- package/dist/policy/schema.js +0 -19
- package/dist/policy/schema.js.map +0 -1
- package/dist/policy/validate.d.ts +0 -19
- package/dist/policy/validate.js +0 -263
- package/dist/policy/validate.js.map +0 -1
- package/dist/rules/action.d.ts +0 -65
- package/dist/rules/action.js +0 -217
- package/dist/rules/action.js.map +0 -1
- package/dist/rules/audit-query.d.ts +0 -51
- package/dist/rules/audit-query.js +0 -90
- package/dist/rules/audit-query.js.map +0 -1
- package/dist/rules/conflict-analyzer.d.ts +0 -57
- package/dist/rules/conflict-analyzer.js +0 -215
- package/dist/rules/conflict-analyzer.js.map +0 -1
- package/dist/rules/cron-scheduler.d.ts +0 -62
- package/dist/rules/cron-scheduler.js +0 -187
- package/dist/rules/cron-scheduler.js.map +0 -1
- package/dist/rules/destructive.d.ts +0 -20
- package/dist/rules/destructive.js +0 -53
- package/dist/rules/destructive.js.map +0 -1
- package/dist/rules/engine.d.ts +0 -193
- package/dist/rules/engine.js +0 -758
- package/dist/rules/engine.js.map +0 -1
- package/dist/rules/matcher.d.ts +0 -56
- package/dist/rules/matcher.js +0 -231
- package/dist/rules/matcher.js.map +0 -1
- package/dist/rules/pid-file.d.ts +0 -43
- package/dist/rules/pid-file.js +0 -96
- package/dist/rules/pid-file.js.map +0 -1
- package/dist/rules/quiet-hours.d.ts +0 -26
- package/dist/rules/quiet-hours.js +0 -46
- package/dist/rules/quiet-hours.js.map +0 -1
- package/dist/rules/suggest.d.ts +0 -20
- package/dist/rules/suggest.js +0 -96
- package/dist/rules/suggest.js.map +0 -1
- package/dist/rules/throttle.d.ts +0 -61
- package/dist/rules/throttle.js +0 -117
- package/dist/rules/throttle.js.map +0 -1
- package/dist/rules/types.d.ts +0 -117
- package/dist/rules/types.js +0 -35
- package/dist/rules/types.js.map +0 -1
- package/dist/rules/webhook-listener.d.ts +0 -63
- package/dist/rules/webhook-listener.js +0 -224
- package/dist/rules/webhook-listener.js.map +0 -1
- package/dist/rules/webhook-token.d.ts +0 -50
- package/dist/rules/webhook-token.js +0 -91
- package/dist/rules/webhook-token.js.map +0 -1
- package/dist/schema/field-aliases.d.ts +0 -34
- package/dist/schema/field-aliases.js +0 -132
- package/dist/schema/field-aliases.js.map +0 -1
- package/dist/sinks/dispatcher.d.ts +0 -7
- package/dist/sinks/dispatcher.js +0 -13
- package/dist/sinks/dispatcher.js.map +0 -1
- package/dist/sinks/file.d.ts +0 -6
- package/dist/sinks/file.js +0 -20
- package/dist/sinks/file.js.map +0 -1
- package/dist/sinks/format.d.ts +0 -20
- package/dist/sinks/format.js +0 -57
- package/dist/sinks/format.js.map +0 -1
- package/dist/sinks/homeassistant.d.ts +0 -18
- package/dist/sinks/homeassistant.js +0 -45
- package/dist/sinks/homeassistant.js.map +0 -1
- package/dist/sinks/openclaw.d.ts +0 -13
- package/dist/sinks/openclaw.js +0 -34
- package/dist/sinks/openclaw.js.map +0 -1
- package/dist/sinks/stdout.d.ts +0 -4
- package/dist/sinks/stdout.js +0 -6
- package/dist/sinks/stdout.js.map +0 -1
- package/dist/sinks/telegram.d.ts +0 -11
- package/dist/sinks/telegram.js +0 -29
- package/dist/sinks/telegram.js.map +0 -1
- package/dist/sinks/types.d.ts +0 -13
- package/dist/sinks/types.js +0 -2
- package/dist/sinks/types.js.map +0 -1
- package/dist/sinks/webhook.d.ts +0 -6
- package/dist/sinks/webhook.js +0 -23
- package/dist/sinks/webhook.js.map +0 -1
- package/dist/status-sync/manager.d.ts +0 -48
- package/dist/status-sync/manager.js +0 -269
- package/dist/status-sync/manager.js.map +0 -1
- package/dist/utils/arg-parsers.d.ts +0 -16
- package/dist/utils/arg-parsers.js +0 -67
- package/dist/utils/arg-parsers.js.map +0 -1
- package/dist/utils/audit.d.ts +0 -69
- package/dist/utils/audit.js +0 -122
- package/dist/utils/audit.js.map +0 -1
- package/dist/utils/filter.d.ts +0 -81
- package/dist/utils/filter.js +0 -190
- package/dist/utils/filter.js.map +0 -1
- package/dist/utils/flags.d.ts +0 -72
- package/dist/utils/flags.js +0 -187
- package/dist/utils/flags.js.map +0 -1
- package/dist/utils/format.d.ts +0 -9
- package/dist/utils/format.js +0 -118
- package/dist/utils/format.js.map +0 -1
- package/dist/utils/health.d.ts +0 -48
- package/dist/utils/health.js +0 -102
- package/dist/utils/health.js.map +0 -1
- package/dist/utils/help-json.d.ts +0 -39
- package/dist/utils/help-json.js +0 -55
- package/dist/utils/help-json.js.map +0 -1
- package/dist/utils/name-resolver.d.ts +0 -26
- package/dist/utils/name-resolver.js +0 -138
- package/dist/utils/name-resolver.js.map +0 -1
- package/dist/utils/output.d.ts +0 -73
- package/dist/utils/output.js +0 -405
- package/dist/utils/output.js.map +0 -1
- package/dist/utils/quota.d.ts +0 -61
- package/dist/utils/quota.js +0 -228
- package/dist/utils/quota.js.map +0 -1
- package/dist/utils/redact.d.ts +0 -23
- package/dist/utils/redact.js +0 -69
- package/dist/utils/redact.js.map +0 -1
- package/dist/utils/retry.d.ts +0 -72
- package/dist/utils/retry.js +0 -141
- package/dist/utils/retry.js.map +0 -1
- package/dist/utils/string.d.ts +0 -2
- package/dist/utils/string.js +0 -23
- package/dist/utils/string.js.map +0 -1
- package/dist/version.d.ts +0 -2
- package/dist/version.js +0 -5
- package/dist/version.js.map +0 -1
package/dist/commands/batch.js
DELETED
|
@@ -1,414 +0,0 @@
|
|
|
1
|
-
import { intArg, enumArg, stringArg } from '../utils/arg-parsers.js';
|
|
2
|
-
import { printJson, isJsonMode, handleError, buildErrorPayload, UsageError, exitWithError } from '../utils/output.js';
|
|
3
|
-
import { fetchDeviceList, executeCommand, isDestructiveCommand, buildHubLocationMap, } from '../lib/devices.js';
|
|
4
|
-
import { createClient } from '../api/client.js';
|
|
5
|
-
import { parseFilter, applyFilter, FilterSyntaxError } from '../utils/filter.js';
|
|
6
|
-
import { isDryRun } from '../utils/flags.js';
|
|
7
|
-
import { DryRunSignal } from '../api/client.js';
|
|
8
|
-
import { getCachedTypeMap, getCachedDevice, loadStatusCache } from '../devices/cache.js';
|
|
9
|
-
import { allowsDirectDestructiveExecution, destructiveExecutionHint } from '../lib/destructive-mode.js';
|
|
10
|
-
const DEFAULT_CONCURRENCY = 5;
|
|
11
|
-
const COMMAND_TYPES = ['command', 'customize'];
|
|
12
|
-
/**
|
|
13
|
-
* Run `task(x)` for every element with at most `concurrency` running at once.
|
|
14
|
-
* `staggerMs`: when > 0, delay each task start by this fixed interval (replaces
|
|
15
|
-
* the default 20-60ms jitter). Useful for rate-limited endpoints.
|
|
16
|
-
*/
|
|
17
|
-
async function runPool(items, concurrency, staggerMs, task) {
|
|
18
|
-
const results = new Array(items.length);
|
|
19
|
-
let cursor = 0;
|
|
20
|
-
const workers = [];
|
|
21
|
-
const width = Math.max(1, Math.min(concurrency, items.length));
|
|
22
|
-
for (let w = 0; w < width; w++) {
|
|
23
|
-
workers.push((async () => {
|
|
24
|
-
while (cursor < items.length) {
|
|
25
|
-
const idx = cursor++;
|
|
26
|
-
results[idx] = await task(items[idx]);
|
|
27
|
-
// Fixed stagger wins over random jitter when set; else keep the
|
|
28
|
-
// default polite spacing so we don't hammer the endpoint.
|
|
29
|
-
const delay = staggerMs > 0 ? staggerMs : 20 + Math.random() * 40;
|
|
30
|
-
await new Promise((r) => setTimeout(r, delay));
|
|
31
|
-
}
|
|
32
|
-
})());
|
|
33
|
-
}
|
|
34
|
-
await Promise.all(workers);
|
|
35
|
-
return results;
|
|
36
|
-
}
|
|
37
|
-
async function resolveTargetIds(options, getClient) {
|
|
38
|
-
const explicit = [];
|
|
39
|
-
if (options.ids) {
|
|
40
|
-
for (const id of options.ids.split(',').map((s) => s.trim()).filter(Boolean)) {
|
|
41
|
-
explicit.push(id);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (options.readStdin) {
|
|
45
|
-
const chunks = [];
|
|
46
|
-
for await (const chunk of process.stdin)
|
|
47
|
-
chunks.push(chunk);
|
|
48
|
-
const raw = Buffer.concat(chunks).toString('utf-8');
|
|
49
|
-
for (const line of raw.split(/\r?\n/)) {
|
|
50
|
-
const id = line.trim();
|
|
51
|
-
if (id)
|
|
52
|
-
explicit.push(id);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
const hasFilter = Boolean(options.filter);
|
|
56
|
-
if (explicit.length === 0 && !hasFilter) {
|
|
57
|
-
throw new Error('No target devices supplied — provide --ids, --filter, or pass "-" to read deviceIds from stdin.');
|
|
58
|
-
}
|
|
59
|
-
const typeMap = getCachedTypeMap(explicit);
|
|
60
|
-
let ids;
|
|
61
|
-
if (hasFilter) {
|
|
62
|
-
const body = await fetchDeviceList(getClient?.());
|
|
63
|
-
const hubLoc = buildHubLocationMap(body.deviceList);
|
|
64
|
-
for (const d of body.deviceList)
|
|
65
|
-
if (d.deviceType)
|
|
66
|
-
typeMap.set(d.deviceId, d.deviceType);
|
|
67
|
-
for (const ir of body.infraredRemoteList)
|
|
68
|
-
typeMap.set(ir.deviceId, ir.remoteType);
|
|
69
|
-
const clauses = parseFilter(options.filter);
|
|
70
|
-
const matched = applyFilter(clauses, body.deviceList, body.infraredRemoteList, hubLoc);
|
|
71
|
-
const filteredIds = new Set(matched.map((m) => m.deviceId));
|
|
72
|
-
ids =
|
|
73
|
-
explicit.length > 0 ? explicit.filter((id) => filteredIds.has(id)) : [...filteredIds];
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
ids = explicit;
|
|
77
|
-
const missingTypeInfo = ids.some((id) => !typeMap.has(id));
|
|
78
|
-
if (missingTypeInfo) {
|
|
79
|
-
const body = await fetchDeviceList(getClient?.());
|
|
80
|
-
for (const d of body.deviceList)
|
|
81
|
-
if (d.deviceType)
|
|
82
|
-
typeMap.set(d.deviceId, d.deviceType);
|
|
83
|
-
for (const ir of body.infraredRemoteList)
|
|
84
|
-
typeMap.set(ir.deviceId, ir.remoteType);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return { ids, typeMap };
|
|
88
|
-
}
|
|
89
|
-
export function registerBatchCommand(devices) {
|
|
90
|
-
devices
|
|
91
|
-
.command('batch')
|
|
92
|
-
.description('Send the same command to many devices in one run (filter- or stdin-driven)')
|
|
93
|
-
.argument('<command>', 'Command name, e.g. turnOn, turnOff, setBrightness')
|
|
94
|
-
.argument('[parameter]', 'Command parameter (same rules as `devices command`; omit for no-arg)')
|
|
95
|
-
.option('--filter <expr>', 'Target devices matching a filter, e.g. type=Bot,family=Home', stringArg('--filter'))
|
|
96
|
-
.option('--ids <csv>', 'Explicit comma-separated list of deviceIds', stringArg('--ids'))
|
|
97
|
-
.option('--concurrency <n>', 'Max parallel in-flight requests (default 5)', intArg('--concurrency', { min: 1 }), '5')
|
|
98
|
-
.option('--max-concurrent <n>', 'Alias for --concurrency; takes priority when set', intArg('--max-concurrent', { min: 1 }))
|
|
99
|
-
.option('--stagger <ms>', 'Fixed delay between task starts in ms (default 0 = random 20-60ms jitter)', intArg('--stagger', { min: 0 }), '0')
|
|
100
|
-
.option('--plan', '[DEPRECATED, use --emit-plan] With --dry-run: emit a plan JSON document instead of executing anything')
|
|
101
|
-
.option('--emit-plan', 'With --dry-run: emit a plan JSON document instead of executing anything')
|
|
102
|
-
.option('--yes', 'Allow destructive commands only from an explicit dev profile')
|
|
103
|
-
.option('--type <commandType>', '"command" (default) or "customize" for user-defined IR buttons', enumArg('--type', COMMAND_TYPES), 'command')
|
|
104
|
-
.option('--stdin', 'Read deviceIds from stdin, one per line (same as trailing "-")')
|
|
105
|
-
.option('--idempotency-key-prefix <prefix>', 'Client-supplied prefix for idempotency keys (key per device: <prefix>-<deviceId>). process-local 60s window; cache is per Node process (MCP session, batch run, plan run). Independent CLI invocations do not share cache.', stringArg('--idempotency-key-prefix'))
|
|
106
|
-
.option('--idempotency-key <prefix>', 'Alias for --idempotency-key-prefix.', stringArg('--idempotency-key'))
|
|
107
|
-
.option('--skip-offline', 'Skip devices whose cached status is offline (no API call; cache miss → send as usual).')
|
|
108
|
-
.addHelpText('after', `
|
|
109
|
-
Targets are resolved in this priority order:
|
|
110
|
-
1. --ids when present (explicit deviceIds)
|
|
111
|
-
2. stdin when --stdin / "-" (one deviceId per line)
|
|
112
|
-
3. --filter (matches the account's device list)
|
|
113
|
-
You can combine explicit ids with --filter to intersect them.
|
|
114
|
-
|
|
115
|
-
Filter grammar:
|
|
116
|
-
key=value exact match
|
|
117
|
-
key~=value case-insensitive substring match
|
|
118
|
-
clauses are comma-separated AND
|
|
119
|
-
|
|
120
|
-
Supported keys: type, family, room, category (category: physical | ir)
|
|
121
|
-
|
|
122
|
-
Output:
|
|
123
|
-
Human mode: one status line per device, summary at the end.
|
|
124
|
-
--json: {succeeded[], failed[{deviceId,error}], summary:{total,ok,failed,skipped,durationMs,maxConcurrent,staggerMs}}
|
|
125
|
-
Each step includes startedAt / finishedAt / durationMs / replayed (when cached).
|
|
126
|
-
|
|
127
|
-
Concurrency & pacing:
|
|
128
|
-
--max-concurrent <n> Upper bound on in-flight requests (alias for --concurrency).
|
|
129
|
-
--stagger <ms> Fixed delay between task starts; default 0 uses random 20-60ms jitter.
|
|
130
|
-
|
|
131
|
-
Planning:
|
|
132
|
-
--dry-run --emit-plan Print the plan JSON without executing anything. Useful
|
|
133
|
-
for agents that want to show the user what will run.
|
|
134
|
-
(--plan is the deprecated alias, removed in v3.0.)
|
|
135
|
-
|
|
136
|
-
Safety:
|
|
137
|
-
Destructive commands (Smart Lock unlock, Garage Door Opener turnOn/turnOff,
|
|
138
|
-
Keypad createKey/deleteKey) are blocked by default. Use the reviewed plan
|
|
139
|
-
flow instead of direct execution.
|
|
140
|
-
--dry-run intercepts every POST and reports the intended calls without
|
|
141
|
-
hitting the API.
|
|
142
|
-
|
|
143
|
-
Examples:
|
|
144
|
-
$ switchbot devices batch turnOff --filter 'type~=Light,family=home'
|
|
145
|
-
$ switchbot devices batch turnOn --ids ID1,ID2,ID3
|
|
146
|
-
$ switchbot devices list --format=id --filter 'type=Bot' | switchbot devices batch toggle -
|
|
147
|
-
$ switchbot devices batch unlock --filter 'type=Smart Lock' --dry-run --emit-plan
|
|
148
|
-
`)
|
|
149
|
-
.action(async (cmd, parameter, options, commandObj) => {
|
|
150
|
-
// Trailing "-" sentinel selects stdin mode.
|
|
151
|
-
const extra = commandObj.args ?? [];
|
|
152
|
-
const readStdin = Boolean(options.stdin) || extra.includes('-');
|
|
153
|
-
// P12: --plan is deprecated in favor of --emit-plan. Reject both
|
|
154
|
-
// together (conflicting) and warn when only the old flag is used.
|
|
155
|
-
if (options.plan && options.emitPlan) {
|
|
156
|
-
handleError(new UsageError('Use --emit-plan; --plan is deprecated and cannot be combined with --emit-plan.'));
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
if (options.plan && !options.emitPlan) {
|
|
160
|
-
// Warning goes to stderr so it cannot corrupt --json output on stdout.
|
|
161
|
-
console.error('[WARN] --plan is deprecated; use --emit-plan. Will be removed in v3.0.');
|
|
162
|
-
}
|
|
163
|
-
const emitPlan = Boolean(options.emitPlan || options.plan);
|
|
164
|
-
// Accept --idempotency-key as alias; reject when both forms are supplied.
|
|
165
|
-
if (options.idempotencyKey !== undefined && options.idempotencyKeyPrefix !== undefined) {
|
|
166
|
-
handleError(new UsageError('Use either --idempotency-key or --idempotency-key-prefix, not both.'));
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
if (options.idempotencyKey !== undefined && options.idempotencyKeyPrefix === undefined) {
|
|
170
|
-
options.idempotencyKeyPrefix = options.idempotencyKey;
|
|
171
|
-
}
|
|
172
|
-
let client;
|
|
173
|
-
const getClient = () => (client ??= createClient());
|
|
174
|
-
let resolved;
|
|
175
|
-
try {
|
|
176
|
-
resolved = await resolveTargetIds({
|
|
177
|
-
filter: options.filter,
|
|
178
|
-
ids: options.ids,
|
|
179
|
-
readStdin,
|
|
180
|
-
}, getClient);
|
|
181
|
-
}
|
|
182
|
-
catch (error) {
|
|
183
|
-
if (error instanceof FilterSyntaxError) {
|
|
184
|
-
exitWithError(`Error: ${error.message}`);
|
|
185
|
-
}
|
|
186
|
-
if (error instanceof Error && error.message.startsWith('No target devices')) {
|
|
187
|
-
exitWithError(`Error: ${error.message}`);
|
|
188
|
-
}
|
|
189
|
-
handleError(error);
|
|
190
|
-
}
|
|
191
|
-
if (resolved.ids.length === 0) {
|
|
192
|
-
const out = {
|
|
193
|
-
succeeded: [],
|
|
194
|
-
failed: [],
|
|
195
|
-
summary: { total: 0, ok: 0, failed: 0, skipped: 0, durationMs: 0, unverifiableCount: 0 },
|
|
196
|
-
};
|
|
197
|
-
if (isJsonMode())
|
|
198
|
-
printJson(out);
|
|
199
|
-
else
|
|
200
|
-
console.log('No devices matched — nothing to do.');
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
const effectiveType = (options.type === 'customize' ? 'customize' : 'command');
|
|
204
|
-
// --skip-offline: preflight using the status cache (no network). Cache
|
|
205
|
-
// miss = send as usual; only definite "offline" cached entries skip.
|
|
206
|
-
const preSkipped = [];
|
|
207
|
-
if (options.skipOffline && resolved.ids.length > 0) {
|
|
208
|
-
const statusCache = loadStatusCache();
|
|
209
|
-
const kept = [];
|
|
210
|
-
for (const id of resolved.ids) {
|
|
211
|
-
const entry = statusCache.entries[id];
|
|
212
|
-
const online = entry?.body?.onlineStatus;
|
|
213
|
-
if (online === 'offline') {
|
|
214
|
-
preSkipped.push({ deviceId: id, reason: 'offline' });
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
kept.push(id);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
resolved = { ...resolved, ids: kept };
|
|
221
|
-
}
|
|
222
|
-
// Pre-flight: identify destructive targets before spending API calls.
|
|
223
|
-
const blockedForDestructive = [];
|
|
224
|
-
for (const id of resolved.ids) {
|
|
225
|
-
const t = resolved.typeMap.get(id);
|
|
226
|
-
if (isDestructiveCommand(t, cmd, effectiveType) && !options.yes) {
|
|
227
|
-
blockedForDestructive.push({
|
|
228
|
-
deviceId: id,
|
|
229
|
-
reason: `destructive command "${cmd}" on ${t ?? 'unknown'} requires --yes`,
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
if (blockedForDestructive.length > 0 && !options.yes) {
|
|
234
|
-
const deviceIds = blockedForDestructive.map((b) => b.deviceId);
|
|
235
|
-
exitWithError({
|
|
236
|
-
code: 2,
|
|
237
|
-
kind: 'guard',
|
|
238
|
-
message: `Refusing to run destructive command "${cmd}" on ${blockedForDestructive.length} device(s) without --yes: ${deviceIds.join(', ')}`,
|
|
239
|
-
hint: 'Re-issue the call with --yes only from an explicit dev profile, or use the reviewed plan flow.',
|
|
240
|
-
context: { command: cmd, deviceIds },
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
if (blockedForDestructive.length > 0 && options.yes && !allowsDirectDestructiveExecution()) {
|
|
244
|
-
exitWithError({
|
|
245
|
-
code: 2,
|
|
246
|
-
kind: 'guard',
|
|
247
|
-
message: `Direct destructive execution is disabled for batch command "${cmd}".`,
|
|
248
|
-
hint: destructiveExecutionHint(),
|
|
249
|
-
context: {
|
|
250
|
-
command: cmd,
|
|
251
|
-
blockedCount: blockedForDestructive.length,
|
|
252
|
-
deviceIds: blockedForDestructive.map((item) => item.deviceId),
|
|
253
|
-
requiredWorkflow: 'plan-approval',
|
|
254
|
-
},
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
// parameter may be a JSON object string; mirror the single-command action.
|
|
258
|
-
let parsedParam = parameter ?? 'default';
|
|
259
|
-
if (parameter) {
|
|
260
|
-
try {
|
|
261
|
-
parsedParam = JSON.parse(parameter);
|
|
262
|
-
}
|
|
263
|
-
catch {
|
|
264
|
-
// keep as string
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
const maxConcurrentRaw = options.maxConcurrent ?? options.concurrency;
|
|
268
|
-
const concurrency = Math.max(1, Number.parseInt(maxConcurrentRaw, 10) || DEFAULT_CONCURRENCY);
|
|
269
|
-
const staggerMs = Math.max(0, Number.parseInt(options.stagger, 10) || 0);
|
|
270
|
-
const dryRun = isDryRun();
|
|
271
|
-
// --dry-run --emit-plan (or legacy --plan): emit a plan document and return without executing.
|
|
272
|
-
if (dryRun && emitPlan) {
|
|
273
|
-
const steps = resolved.ids.map((id) => ({
|
|
274
|
-
deviceId: id,
|
|
275
|
-
command: cmd,
|
|
276
|
-
parameter: parsedParam,
|
|
277
|
-
type: effectiveType,
|
|
278
|
-
idempotencyKey: options.idempotencyKeyPrefix
|
|
279
|
-
? `${options.idempotencyKeyPrefix}-${id}`
|
|
280
|
-
: undefined,
|
|
281
|
-
}));
|
|
282
|
-
const planDoc = {
|
|
283
|
-
schemaVersion: '1.1',
|
|
284
|
-
dryRun: true,
|
|
285
|
-
plan: {
|
|
286
|
-
command: cmd,
|
|
287
|
-
parameter: parsedParam,
|
|
288
|
-
type: effectiveType,
|
|
289
|
-
maxConcurrent: concurrency,
|
|
290
|
-
staggerMs,
|
|
291
|
-
stepCount: steps.length,
|
|
292
|
-
steps,
|
|
293
|
-
},
|
|
294
|
-
};
|
|
295
|
-
if (isJsonMode()) {
|
|
296
|
-
printJson(planDoc);
|
|
297
|
-
}
|
|
298
|
-
else {
|
|
299
|
-
console.log(`Plan: ${steps.length} step(s), command=${cmd}, maxConcurrent=${concurrency}, staggerMs=${staggerMs}`);
|
|
300
|
-
for (const s of steps)
|
|
301
|
-
console.log(` → ${s.deviceId} ${s.type} ${s.command}`);
|
|
302
|
-
}
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
const startedAt = Date.now();
|
|
306
|
-
const outcomes = await runPool(resolved.ids, concurrency, staggerMs, async (id) => {
|
|
307
|
-
const stepStart = Date.now();
|
|
308
|
-
const startedIso = new Date(stepStart).toISOString();
|
|
309
|
-
try {
|
|
310
|
-
const idempotencyKey = options.idempotencyKeyPrefix
|
|
311
|
-
? `${options.idempotencyKeyPrefix}-${id}`
|
|
312
|
-
: undefined;
|
|
313
|
-
const result = await executeCommand(id, cmd, parsedParam, effectiveType, getClient(), {
|
|
314
|
-
idempotencyKey,
|
|
315
|
-
});
|
|
316
|
-
const finishedIso = new Date().toISOString();
|
|
317
|
-
const durationMs = Date.now() - stepStart;
|
|
318
|
-
const replayed = typeof result === 'object' && result !== null && result.replayed === true;
|
|
319
|
-
if (!isJsonMode()) {
|
|
320
|
-
console.log(`✓ ${id}: ${cmd}${replayed ? ' (replayed)' : ''}`);
|
|
321
|
-
}
|
|
322
|
-
return {
|
|
323
|
-
ok: true,
|
|
324
|
-
deviceId: id,
|
|
325
|
-
result,
|
|
326
|
-
startedAt: startedIso,
|
|
327
|
-
finishedAt: finishedIso,
|
|
328
|
-
durationMs,
|
|
329
|
-
replayed,
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
catch (err) {
|
|
333
|
-
// --dry-run uses DryRunSignal to short-circuit; surface that as a
|
|
334
|
-
// "skipped" outcome, not a failure.
|
|
335
|
-
if (err instanceof DryRunSignal) {
|
|
336
|
-
return {
|
|
337
|
-
ok: 'dry-run',
|
|
338
|
-
deviceId: id,
|
|
339
|
-
startedAt: startedIso,
|
|
340
|
-
finishedAt: new Date().toISOString(),
|
|
341
|
-
durationMs: Date.now() - stepStart,
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
const errorPayload = buildErrorPayload(err);
|
|
345
|
-
if (!isJsonMode()) {
|
|
346
|
-
console.error(`✗ ${id}: ${errorPayload.message}`);
|
|
347
|
-
}
|
|
348
|
-
return {
|
|
349
|
-
ok: false,
|
|
350
|
-
deviceId: id,
|
|
351
|
-
error: errorPayload,
|
|
352
|
-
startedAt: startedIso,
|
|
353
|
-
finishedAt: new Date().toISOString(),
|
|
354
|
-
durationMs: Date.now() - stepStart,
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
const succeeded = outcomes.filter((o) => o.ok === true);
|
|
359
|
-
const failed = outcomes.filter((o) => o.ok === false);
|
|
360
|
-
const dryRunned = outcomes.filter((o) => o.ok === 'dry-run');
|
|
361
|
-
const result = {
|
|
362
|
-
succeeded: succeeded.map((s) => {
|
|
363
|
-
const isIr = getCachedDevice(s.deviceId)?.category === 'ir';
|
|
364
|
-
const entry = {
|
|
365
|
-
deviceId: s.deviceId,
|
|
366
|
-
result: s.result,
|
|
367
|
-
startedAt: s.startedAt,
|
|
368
|
-
finishedAt: s.finishedAt,
|
|
369
|
-
durationMs: s.durationMs,
|
|
370
|
-
replayed: s.replayed,
|
|
371
|
-
};
|
|
372
|
-
if (isIr) {
|
|
373
|
-
entry.subKind = 'ir-no-feedback';
|
|
374
|
-
entry.verification = {
|
|
375
|
-
verifiable: false,
|
|
376
|
-
reason: 'IR transmission is unidirectional; no receipt acknowledgment is possible.',
|
|
377
|
-
suggestedFollowup: 'Confirm visible change manually or via a paired state sensor.',
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
return entry;
|
|
381
|
-
}),
|
|
382
|
-
failed: failed.map((f) => ({
|
|
383
|
-
deviceId: f.deviceId,
|
|
384
|
-
error: f.error,
|
|
385
|
-
startedAt: f.startedAt,
|
|
386
|
-
finishedAt: f.finishedAt,
|
|
387
|
-
durationMs: f.durationMs,
|
|
388
|
-
})),
|
|
389
|
-
...(preSkipped.length > 0 ? { skipped: preSkipped } : {}),
|
|
390
|
-
summary: {
|
|
391
|
-
total: resolved.ids.length + preSkipped.length,
|
|
392
|
-
ok: succeeded.length,
|
|
393
|
-
failed: failed.length,
|
|
394
|
-
skipped: dryRunned.length + preSkipped.length,
|
|
395
|
-
durationMs: Date.now() - startedAt,
|
|
396
|
-
unverifiableCount: succeeded.filter((s) => getCachedDevice(s.deviceId)?.category === 'ir').length,
|
|
397
|
-
schemaVersion: '1.1',
|
|
398
|
-
maxConcurrent: concurrency,
|
|
399
|
-
staggerMs,
|
|
400
|
-
...(dryRun ? { dryRun: true } : {}),
|
|
401
|
-
},
|
|
402
|
-
};
|
|
403
|
-
if (isJsonMode()) {
|
|
404
|
-
printJson(result);
|
|
405
|
-
}
|
|
406
|
-
else {
|
|
407
|
-
console.log(`\nSummary: ${result.summary.ok} ok, ${result.summary.failed} failed, ${result.summary.skipped} skipped (${result.summary.durationMs}ms)`);
|
|
408
|
-
}
|
|
409
|
-
// Non-zero exit when anything failed so scripts can react.
|
|
410
|
-
if (failed.length > 0)
|
|
411
|
-
process.exit(1);
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
//# sourceMappingURL=batch.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/commands/batch.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/cache.d.ts
DELETED
package/dist/commands/cache.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { enumArg } from '../utils/arg-parsers.js';
|
|
2
|
-
import { printJson, isJsonMode, handleError, UsageError } from '../utils/output.js';
|
|
3
|
-
import { clearCache, clearStatusCache, describeCache, loadStatusCache, } from '../devices/cache.js';
|
|
4
|
-
function formatAge(ms) {
|
|
5
|
-
if (ms === undefined)
|
|
6
|
-
return '—';
|
|
7
|
-
if (ms < 1000)
|
|
8
|
-
return `${ms}ms`;
|
|
9
|
-
const s = Math.floor(ms / 1000);
|
|
10
|
-
if (s < 60)
|
|
11
|
-
return `${s}s`;
|
|
12
|
-
const m = Math.floor(s / 60);
|
|
13
|
-
if (m < 60)
|
|
14
|
-
return `${m}m ${s % 60}s`;
|
|
15
|
-
const h = Math.floor(m / 60);
|
|
16
|
-
return `${h}h ${m % 60}m`;
|
|
17
|
-
}
|
|
18
|
-
export function registerCacheCommand(program) {
|
|
19
|
-
const CACHE_KEYS = ['list', 'status', 'all'];
|
|
20
|
-
const cache = program
|
|
21
|
-
.command('cache')
|
|
22
|
-
.description('Inspect and manage the local SwitchBot CLI caches')
|
|
23
|
-
.addHelpText('after', `
|
|
24
|
-
Two caches live at ~/.switchbot/:
|
|
25
|
-
devices.json List of known deviceIds + metadata. Refreshed by every
|
|
26
|
-
'devices list' call. Drives command validation and
|
|
27
|
-
helpful hints — keep around even if you don't use TTL.
|
|
28
|
-
status.json Per-device status bodies keyed by deviceId. Only written
|
|
29
|
-
when a status TTL is enabled (via --cache <duration>).
|
|
30
|
-
|
|
31
|
-
Cache modes (global flag, apply to any read):
|
|
32
|
-
--cache off | --no-cache disable cache reads
|
|
33
|
-
--cache auto (default) list cache on (1h TTL), status cache off
|
|
34
|
-
--cache 5m | --cache 1h enable both with the given TTL
|
|
35
|
-
|
|
36
|
-
Subcommands:
|
|
37
|
-
show Show ages, entry counts, and file locations
|
|
38
|
-
clear Delete cache files (specify --key to scope)
|
|
39
|
-
|
|
40
|
-
Examples:
|
|
41
|
-
$ switchbot cache show
|
|
42
|
-
$ switchbot --json cache show
|
|
43
|
-
$ switchbot cache clear # removes devices.json + status.json
|
|
44
|
-
$ switchbot cache clear --key status # removes only status.json
|
|
45
|
-
$ switchbot cache clear --key list # removes only devices.json
|
|
46
|
-
`);
|
|
47
|
-
cache
|
|
48
|
-
.command('show')
|
|
49
|
-
.alias('status')
|
|
50
|
-
.description('Summarize the cache files (paths, ages, entry counts)')
|
|
51
|
-
.addHelpText('after', `
|
|
52
|
-
Cache TTL is computed from the 'lastUpdated' field inside the JSON, not the file mtime.
|
|
53
|
-
touch does not invalidate; use 'cache clear' to force a refresh.
|
|
54
|
-
`)
|
|
55
|
-
.action(() => {
|
|
56
|
-
const summary = describeCache();
|
|
57
|
-
if (isJsonMode()) {
|
|
58
|
-
const statusCache = loadStatusCache();
|
|
59
|
-
printJson({
|
|
60
|
-
list: summary.list,
|
|
61
|
-
status: {
|
|
62
|
-
...summary.status,
|
|
63
|
-
entries: Object.fromEntries(Object.entries(statusCache.entries).map(([id, e]) => [id, { fetchedAt: e.fetchedAt }])),
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
console.log('Device list cache (devices.json):');
|
|
69
|
-
console.log(` Path: ${summary.list.path}`);
|
|
70
|
-
console.log(` Exists: ${summary.list.exists ? 'yes' : 'no'}`);
|
|
71
|
-
if (summary.list.exists) {
|
|
72
|
-
console.log(` Last update: ${summary.list.lastUpdated ?? '—'}`);
|
|
73
|
-
console.log(` Age: ${formatAge(summary.list.ageMs)}`);
|
|
74
|
-
console.log(` Devices: ${summary.list.deviceCount ?? 0}`);
|
|
75
|
-
}
|
|
76
|
-
console.log('\nStatus cache (status.json):');
|
|
77
|
-
console.log(` Path: ${summary.status.path}`);
|
|
78
|
-
console.log(` Exists: ${summary.status.exists ? 'yes' : 'no'}`);
|
|
79
|
-
console.log(` Entries: ${summary.status.entryCount}`);
|
|
80
|
-
if (summary.status.entryCount > 0) {
|
|
81
|
-
console.log(` Oldest: ${summary.status.oldestFetchedAt ?? '—'}`);
|
|
82
|
-
console.log(` Newest: ${summary.status.newestFetchedAt ?? '—'}`);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
cache
|
|
86
|
-
.command('clear')
|
|
87
|
-
.description('Delete cache files')
|
|
88
|
-
.option('--key <which>', 'Which cache to clear: "list" | "status" | "all" (default)', enumArg('--key', CACHE_KEYS), 'all')
|
|
89
|
-
.option('--status', 'Shorthand for --key status')
|
|
90
|
-
.option('--list', 'Shorthand for --key list')
|
|
91
|
-
.action((options) => {
|
|
92
|
-
try {
|
|
93
|
-
if (options.status && options.list) {
|
|
94
|
-
throw new UsageError('--status and --list are mutually exclusive.');
|
|
95
|
-
}
|
|
96
|
-
if ((options.status || options.list) && options.key !== 'all') {
|
|
97
|
-
throw new UsageError('--status / --list cannot be combined with --key.');
|
|
98
|
-
}
|
|
99
|
-
let key = options.key;
|
|
100
|
-
if (options.status)
|
|
101
|
-
key = 'status';
|
|
102
|
-
if (options.list)
|
|
103
|
-
key = 'list';
|
|
104
|
-
if (!['list', 'status', 'all'].includes(key)) {
|
|
105
|
-
throw new UsageError(`Unknown --key "${key}". Expected: list, status, all.`);
|
|
106
|
-
}
|
|
107
|
-
const cleared = [];
|
|
108
|
-
if (key === 'list' || key === 'all') {
|
|
109
|
-
clearCache();
|
|
110
|
-
cleared.push('list');
|
|
111
|
-
}
|
|
112
|
-
if (key === 'status' || key === 'all') {
|
|
113
|
-
clearStatusCache();
|
|
114
|
-
cleared.push('status');
|
|
115
|
-
}
|
|
116
|
-
if (isJsonMode()) {
|
|
117
|
-
printJson({ cleared });
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
console.log(`Cleared: ${cleared.join(', ')}`);
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
handleError(error);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
//# sourceMappingURL=cache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/commands/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
export type AgentSafetyTier = 'read' | 'action' | 'destructive';
|
|
3
|
-
export type Verifiability = 'local' | 'deviceConfirmed' | 'deviceDependent' | 'none';
|
|
4
|
-
export type RiskLevel = 'low' | 'medium' | 'high';
|
|
5
|
-
export type IdempotencyHint = 'safe' | 'caution' | 'non-idempotent';
|
|
6
|
-
export type RecommendedMode = 'direct' | 'plan' | 'review-before-execute';
|
|
7
|
-
interface CommandMeta {
|
|
8
|
-
mutating: boolean;
|
|
9
|
-
consumesQuota: boolean;
|
|
10
|
-
idempotencySupported: boolean;
|
|
11
|
-
agentSafetyTier: AgentSafetyTier;
|
|
12
|
-
verifiability: Verifiability;
|
|
13
|
-
typicalLatencyMs: number;
|
|
14
|
-
}
|
|
15
|
-
export declare const COMMAND_META: Record<string, CommandMeta>;
|
|
16
|
-
export interface CompactLeaf {
|
|
17
|
-
name: string;
|
|
18
|
-
mutating: boolean;
|
|
19
|
-
consumesQuota: boolean;
|
|
20
|
-
idempotencySupported: boolean;
|
|
21
|
-
agentSafetyTier: AgentSafetyTier;
|
|
22
|
-
verifiability: Verifiability;
|
|
23
|
-
typicalLatencyMs: number;
|
|
24
|
-
riskLevel: RiskLevel;
|
|
25
|
-
requiresConfirmation: boolean;
|
|
26
|
-
supportsDryRun: boolean;
|
|
27
|
-
idempotencyHint: IdempotencyHint;
|
|
28
|
-
recommendedMode: RecommendedMode;
|
|
29
|
-
}
|
|
30
|
-
export declare function registerCapabilitiesCommand(program: Command): void;
|
|
31
|
-
export {};
|