@tikoci/centrs 0.1.1 → 0.1.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/CHANGELOG.md +107 -2
- package/GLOSSARY.txt +87 -0
- package/README.md +25 -9
- package/SECURITY.md +3 -3
- package/commands/AGENTS.md +3 -2
- package/commands/api/AGENTS.md +212 -0
- package/commands/api/README.md +177 -0
- package/commands/api/examples.md +428 -0
- package/commands/btest/README.md +56 -31
- package/commands/btest/examples.md +35 -10
- package/commands/check/README.md +371 -53
- package/commands/check/examples.md +390 -0
- package/commands/devices/README.md +177 -37
- package/commands/devices/examples.md +148 -0
- package/commands/execute/README.md +48 -7
- package/commands/execute/examples.md +90 -6
- package/commands/retrieve/README.md +37 -51
- package/commands/retrieve/examples.md +40 -9
- package/commands/settings/README.md +286 -22
- package/commands/settings/examples.md +408 -0
- package/commands/terminal/README.md +6 -0
- package/commands/transfer/README.md +32 -2
- package/commands/transfer/examples.md +66 -0
- package/docs/CONSTITUTION.md +40 -15
- package/docs/MATRIX.md +69 -142
- package/docs/errors/README.md +2 -1
- package/docs/errors/cdb/empty-selection.md +19 -0
- package/docs/errors/input/incomplete-gps.md +9 -0
- package/docs/errors/input/invalid-altitude.md +9 -0
- package/docs/errors/input/invalid-bbox.md +9 -0
- package/docs/errors/input/invalid-coordinate.md +9 -0
- package/docs/errors/input/invalid-radius.md +9 -0
- package/docs/errors/internal/settings-failed.md +9 -0
- package/docs/errors/routeros/btest-connection-count-single-stream.md +22 -0
- package/docs/errors/routeros/btest-udp-tx-size-ignored.md +15 -0
- package/docs/errors/settings/consequential-value.md +26 -0
- package/docs/errors/settings/invalid-boolean.md +21 -3
- package/docs/errors/settings/invalid-format.md +18 -3
- package/docs/errors/settings/invalid-integer.md +18 -3
- package/docs/errors/settings/invalid-timeout.md +20 -3
- package/docs/errors/settings/invalid-via.md +22 -3
- package/docs/errors/settings/reserved-key.md +29 -0
- package/docs/errors/settings/skip-env-file-active.md +25 -0
- package/docs/errors/settings/unknown-key.md +25 -0
- package/docs/errors/usage/fanout-not-supported.md +16 -0
- package/docs/errors/usage/invalid-method.md +23 -0
- package/package.json +9 -9
- package/src/api-fanout.ts +454 -0
- package/src/api.ts +1627 -0
- package/src/btest.ts +61 -1
- package/src/cli/api.ts +660 -0
- package/src/cli/btest.ts +20 -2
- package/src/cli/common.ts +75 -0
- package/src/cli/devices.ts +235 -6
- package/src/cli/discover.ts +3 -1
- package/src/cli/execute.ts +107 -6
- package/src/cli/mcp.ts +8 -1
- package/src/cli/retrieve.ts +135 -90
- package/src/cli/selection.ts +200 -0
- package/src/cli/settings.ts +286 -0
- package/src/cli/terminal.ts +22 -7
- package/src/cli/transfer.ts +171 -47
- package/src/cli.ts +29 -0
- package/src/core/error-catalog.ts +69 -0
- package/src/core/fanout.ts +301 -0
- package/src/core/inspect.ts +170 -0
- package/src/devices.ts +212 -20
- package/src/discover.ts +7 -2
- package/src/execute-fanout.ts +438 -0
- package/src/execute.ts +134 -70
- package/src/index.ts +166 -9
- package/src/mcp/config.ts +12 -2
- package/src/mcp/tools.ts +137 -2
- package/src/protocols/adapter.ts +357 -9
- package/src/protocols/btest-session.ts +279 -46
- package/src/protocols/btest.ts +6 -2
- package/src/protocols/index.ts +11 -5
- package/src/protocols/native-api.ts +223 -30
- package/src/resolver/cdb.ts +10 -2
- package/src/resolver/comment-kv.ts +58 -4
- package/src/resolver/config-file.ts +136 -0
- package/src/resolver/facts.ts +78 -0
- package/src/resolver/geo.ts +453 -0
- package/src/resolver/index.ts +46 -0
- package/src/resolver/mac.ts +12 -3
- package/src/resolver/selection.ts +304 -0
- package/src/resolver/settings.ts +54 -5
- package/src/resolver/target.ts +20 -2
- package/src/retrieve-fanout.ts +232 -268
- package/src/retrieve.ts +69 -94
- package/src/settings.ts +1078 -0
- package/src/terminal.ts +11 -1
- package/src/transfer-fanout.ts +527 -0
- package/src/transfer.ts +61 -11
- package/commands/stream/README.md +0 -70
package/src/execute.ts
CHANGED
|
@@ -9,6 +9,13 @@ import type {
|
|
|
9
9
|
Warning,
|
|
10
10
|
} from "./core/envelope.ts";
|
|
11
11
|
import { buildTip } from "./core/envelope.ts";
|
|
12
|
+
import {
|
|
13
|
+
extractCompletionNames,
|
|
14
|
+
inspectChildren,
|
|
15
|
+
inspectCompletions,
|
|
16
|
+
isArgumentNode,
|
|
17
|
+
pathTokens,
|
|
18
|
+
} from "./core/inspect.ts";
|
|
12
19
|
import { mapRouterOsError } from "./core/routeros-errors.ts";
|
|
13
20
|
import { CentrsError, serializeCentrsError } from "./errors.ts";
|
|
14
21
|
import {
|
|
@@ -28,6 +35,7 @@ import {
|
|
|
28
35
|
effectiveHostCandidate,
|
|
29
36
|
isIpTransport,
|
|
30
37
|
isMacAddress,
|
|
38
|
+
loadEnvFileDefaults,
|
|
31
39
|
parseDuration,
|
|
32
40
|
parseResolvePolicy,
|
|
33
41
|
type ResolvedAuth,
|
|
@@ -132,20 +140,6 @@ export interface ResolvedExecuteRequest {
|
|
|
132
140
|
warnings: readonly Warning[];
|
|
133
141
|
}
|
|
134
142
|
|
|
135
|
-
interface InspectChildItem {
|
|
136
|
-
type?: string;
|
|
137
|
-
name?: string;
|
|
138
|
-
"node-type"?: string;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
interface InspectCompletionItem {
|
|
142
|
-
type?: string;
|
|
143
|
-
name?: string;
|
|
144
|
-
completion?: string;
|
|
145
|
-
value?: string;
|
|
146
|
-
text?: string;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
143
|
export async function execute(
|
|
150
144
|
request: ExecuteRequest,
|
|
151
145
|
env: Record<string, string | undefined> = Bun.env,
|
|
@@ -284,19 +278,29 @@ export async function runResolvedExecute(
|
|
|
284
278
|
export async function resolveExecuteRequest(
|
|
285
279
|
request: ExecuteRequest,
|
|
286
280
|
env: Record<string, string | undefined>,
|
|
281
|
+
options: {
|
|
282
|
+
cdbResolution?: CdbResolution;
|
|
283
|
+
config?: Record<string, string | undefined>;
|
|
284
|
+
} = {},
|
|
287
285
|
): Promise<ResolvedExecuteRequest> {
|
|
288
286
|
validateExecuteRequestShape(request);
|
|
289
287
|
const canonical = canonicalizeExecuteCommand(request.command);
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
288
|
+
const config = options.config ?? (await loadEnvFileDefaults(env));
|
|
289
|
+
// Fan-out passes the pre-resolved CDB record for a member (the CDB is loaded
|
|
290
|
+
// once in `expandCdbSelection`); single-target resolves it here.
|
|
291
|
+
const cdbResolution =
|
|
292
|
+
options.cdbResolution ??
|
|
293
|
+
(await resolveCdb(
|
|
294
|
+
{
|
|
295
|
+
targetInput: request.targetInput,
|
|
296
|
+
cdbFile: request.cdbFile,
|
|
297
|
+
cdbPassword: request.cdbPassword,
|
|
298
|
+
},
|
|
299
|
+
env,
|
|
300
|
+
config,
|
|
301
|
+
));
|
|
302
|
+
const via = resolveExecuteProtocol(request, env, cdbResolution, config);
|
|
303
|
+
const format = resolveFormat(request, env, config);
|
|
300
304
|
const validate = resolveBooleanSetting(
|
|
301
305
|
request.validate,
|
|
302
306
|
env,
|
|
@@ -304,18 +308,22 @@ export async function resolveExecuteRequest(
|
|
|
304
308
|
true,
|
|
305
309
|
"validate",
|
|
306
310
|
cdbResolution?.overrides.validate,
|
|
311
|
+
config,
|
|
307
312
|
);
|
|
308
313
|
const timeoutMs = resolveTimeoutSetting(
|
|
309
314
|
request.timeout,
|
|
310
315
|
env,
|
|
311
316
|
via.value,
|
|
312
317
|
cdbResolution?.overrides.timeoutMs,
|
|
318
|
+
config,
|
|
313
319
|
);
|
|
314
320
|
const maxResultsBytes = resolveOptionalIntegerSetting(
|
|
315
321
|
request.maxResultsBytes,
|
|
316
322
|
env,
|
|
317
323
|
"CENTRS_MAX_RESULTS",
|
|
318
324
|
"max-results",
|
|
325
|
+
undefined,
|
|
326
|
+
config,
|
|
319
327
|
);
|
|
320
328
|
const macResolution = isIpTransport(via.value)
|
|
321
329
|
? await resolveMacTarget({
|
|
@@ -323,7 +331,10 @@ export async function resolveExecuteRequest(
|
|
|
323
331
|
targetInput: request.targetInput,
|
|
324
332
|
cdbTarget: cdbResolution?.target,
|
|
325
333
|
env,
|
|
326
|
-
|
|
334
|
+
config,
|
|
335
|
+
policy: parseResolvePolicy(
|
|
336
|
+
request.resolve ?? env["CENTRS_RESOLVE"] ?? config["CENTRS_RESOLVE"],
|
|
337
|
+
),
|
|
327
338
|
operation: "execute",
|
|
328
339
|
})
|
|
329
340
|
: undefined;
|
|
@@ -337,6 +348,7 @@ export async function resolveExecuteRequest(
|
|
|
337
348
|
env,
|
|
338
349
|
via.value,
|
|
339
350
|
cdbResolution,
|
|
351
|
+
config,
|
|
340
352
|
);
|
|
341
353
|
const auth = resolveAuth(
|
|
342
354
|
{
|
|
@@ -346,6 +358,7 @@ export async function resolveExecuteRequest(
|
|
|
346
358
|
},
|
|
347
359
|
env,
|
|
348
360
|
cdbResolution,
|
|
361
|
+
config,
|
|
349
362
|
);
|
|
350
363
|
const insecure = resolveBooleanSetting(
|
|
351
364
|
request.insecure,
|
|
@@ -354,6 +367,7 @@ export async function resolveExecuteRequest(
|
|
|
354
367
|
false,
|
|
355
368
|
"insecure",
|
|
356
369
|
cdbResolution?.overrides.insecure,
|
|
370
|
+
config,
|
|
357
371
|
);
|
|
358
372
|
|
|
359
373
|
return {
|
|
@@ -373,6 +387,79 @@ export async function resolveExecuteRequest(
|
|
|
373
387
|
};
|
|
374
388
|
}
|
|
375
389
|
|
|
390
|
+
export interface ExecuteGlobalContext {
|
|
391
|
+
via: RouterOsProtocol;
|
|
392
|
+
write: boolean;
|
|
393
|
+
summary: ExecuteRequestSummary;
|
|
394
|
+
settings: CommonSettingsMeta;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Resolve the target-independent settings (protocol, format, validate, timeout,
|
|
399
|
+
* max-results) for a fan-out's outer `meta.operation.request` summary and its
|
|
400
|
+
* transport-aware concurrency default. No CDB record is consulted; the global
|
|
401
|
+
* `--via` (default `native-api`) decides the summary and concurrency base. Also
|
|
402
|
+
* canonicalizes the command once so write-ness is known before any target runs.
|
|
403
|
+
*/
|
|
404
|
+
export function resolveExecuteGlobalContext(
|
|
405
|
+
request: ExecuteRequest,
|
|
406
|
+
env: Record<string, string | undefined>,
|
|
407
|
+
config: Record<string, string | undefined> = {},
|
|
408
|
+
): ExecuteGlobalContext {
|
|
409
|
+
validateExecuteRequestShape(request);
|
|
410
|
+
const canonical = canonicalizeExecuteCommand(request.command);
|
|
411
|
+
const via = resolveExecuteProtocol(request, env, undefined, config);
|
|
412
|
+
const format = resolveFormat(request, env, config);
|
|
413
|
+
const validate = resolveBooleanSetting(
|
|
414
|
+
request.validate,
|
|
415
|
+
env,
|
|
416
|
+
"CENTRS_VALIDATE",
|
|
417
|
+
true,
|
|
418
|
+
"validate",
|
|
419
|
+
undefined,
|
|
420
|
+
config,
|
|
421
|
+
);
|
|
422
|
+
const timeoutMs = resolveTimeoutSetting(
|
|
423
|
+
request.timeout,
|
|
424
|
+
env,
|
|
425
|
+
via.value,
|
|
426
|
+
undefined,
|
|
427
|
+
config,
|
|
428
|
+
);
|
|
429
|
+
const maxResultsBytes = resolveOptionalIntegerSetting(
|
|
430
|
+
request.maxResultsBytes,
|
|
431
|
+
env,
|
|
432
|
+
"CENTRS_MAX_RESULTS",
|
|
433
|
+
"max-results",
|
|
434
|
+
undefined,
|
|
435
|
+
config,
|
|
436
|
+
);
|
|
437
|
+
return {
|
|
438
|
+
via: via.value,
|
|
439
|
+
write: isWriteShaped(canonical),
|
|
440
|
+
summary: {
|
|
441
|
+
command: request.command,
|
|
442
|
+
canonical,
|
|
443
|
+
write: isWriteShaped(canonical),
|
|
444
|
+
yes: request.yes ?? false,
|
|
445
|
+
validate: validate.value,
|
|
446
|
+
verbose: request.verbose ?? false,
|
|
447
|
+
timeoutMs: timeoutMs.value,
|
|
448
|
+
format: format.value,
|
|
449
|
+
maxResultsBytes: maxResultsBytes?.value,
|
|
450
|
+
},
|
|
451
|
+
settings: {
|
|
452
|
+
via: toCoreSource(via.source),
|
|
453
|
+
timeoutMs: toCoreSource(timeoutMs.source),
|
|
454
|
+
format: toCoreSource(format.source),
|
|
455
|
+
validate: toCoreSource(validate.source),
|
|
456
|
+
maxResultsBytes: maxResultsBytes
|
|
457
|
+
? toCoreSource(maxResultsBytes.source)
|
|
458
|
+
: undefined,
|
|
459
|
+
},
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
376
463
|
export function buildExecuteErrorEnvelope(
|
|
377
464
|
request: ExecuteRequest,
|
|
378
465
|
error: unknown,
|
|
@@ -735,24 +822,18 @@ async function inspectExecuteAttributes(
|
|
|
735
822
|
resolved: ResolvedExecuteRequest,
|
|
736
823
|
backend: ProtocolAdapter,
|
|
737
824
|
): Promise<string[]> {
|
|
738
|
-
const
|
|
825
|
+
const commandTokens = [
|
|
739
826
|
...pathTokens(resolved.canonical.path),
|
|
740
827
|
resolved.canonical.verb,
|
|
741
|
-
]
|
|
742
|
-
const children =
|
|
743
|
-
"child",
|
|
744
|
-
commandPath,
|
|
745
|
-
)) as InspectChildItem[];
|
|
828
|
+
];
|
|
829
|
+
const children = await inspectChildren(backend, commandTokens);
|
|
746
830
|
const childAttributes = children
|
|
747
831
|
.filter(isArgumentNode)
|
|
748
832
|
.map((child) => child.name)
|
|
749
833
|
.filter(
|
|
750
834
|
(name): name is string => typeof name === "string" && name.length > 0,
|
|
751
835
|
);
|
|
752
|
-
const completionRows =
|
|
753
|
-
"completion",
|
|
754
|
-
commandPath,
|
|
755
|
-
)) as InspectCompletionItem[];
|
|
836
|
+
const completionRows = await inspectCompletions(backend, commandTokens);
|
|
756
837
|
return [
|
|
757
838
|
...new Set([...childAttributes, ...extractCompletionNames(completionRows)]),
|
|
758
839
|
].sort();
|
|
@@ -769,16 +850,6 @@ async function runCommand(
|
|
|
769
850
|
return backend.execute({ path: "", command: "", script: resolved.command });
|
|
770
851
|
}
|
|
771
852
|
if (resolved.canonical.mode === "script") {
|
|
772
|
-
if (resolved.via.value === "native-api") {
|
|
773
|
-
throw new CentrsError({
|
|
774
|
-
code: "transport/unsupported-operation",
|
|
775
|
-
summary:
|
|
776
|
-
"The native API execute path requires a slash-prefixed RouterOS command.",
|
|
777
|
-
remediation:
|
|
778
|
-
"Use a path-shaped command such as `/system/identity/set name=x`, or pin `--via rest-api` for `/rest/execute` script mode.",
|
|
779
|
-
context: { via: resolved.via.value, command: resolved.command },
|
|
780
|
-
});
|
|
781
|
-
}
|
|
782
853
|
return backend.execute({ path: "", command: "", script: resolved.command });
|
|
783
854
|
}
|
|
784
855
|
return backend.execute({
|
|
@@ -819,7 +890,9 @@ async function assertWriteConfirmed(
|
|
|
819
890
|
});
|
|
820
891
|
}
|
|
821
892
|
|
|
822
|
-
async function promptForWriteConfirmation(
|
|
893
|
+
export async function promptForWriteConfirmation(
|
|
894
|
+
prompt: string,
|
|
895
|
+
): Promise<boolean> {
|
|
823
896
|
process.stderr.write(prompt);
|
|
824
897
|
for await (const chunk of Bun.stdin.stream()) {
|
|
825
898
|
const answer = new TextDecoder().decode(chunk).trim().toLowerCase();
|
|
@@ -832,8 +905,9 @@ function resolveExecuteProtocol(
|
|
|
832
905
|
request: ExecuteRequest,
|
|
833
906
|
env: Record<string, string | undefined>,
|
|
834
907
|
cdb?: CdbResolution,
|
|
908
|
+
config: Record<string, string | undefined> = {},
|
|
835
909
|
): ResolvedSetting<RouterOsProtocol> {
|
|
836
|
-
const defaultVia = isUnresolvedMacTarget(request, env, cdb)
|
|
910
|
+
const defaultVia = isUnresolvedMacTarget(request, env, cdb, config)
|
|
837
911
|
? "mac-telnet"
|
|
838
912
|
: "native-api";
|
|
839
913
|
const via = resolveStringSetting(
|
|
@@ -844,6 +918,7 @@ function resolveExecuteProtocol(
|
|
|
844
918
|
"via",
|
|
845
919
|
undefined,
|
|
846
920
|
cdb?.overrides.via,
|
|
921
|
+
config,
|
|
847
922
|
);
|
|
848
923
|
if (!via) {
|
|
849
924
|
throw new CentrsError({
|
|
@@ -888,8 +963,13 @@ function isUnresolvedMacTarget(
|
|
|
888
963
|
request: ExecuteRequest,
|
|
889
964
|
env: Record<string, string | undefined>,
|
|
890
965
|
cdb?: CdbResolution,
|
|
966
|
+
config: Record<string, string | undefined> = {},
|
|
891
967
|
): boolean {
|
|
892
|
-
if (
|
|
968
|
+
if (
|
|
969
|
+
request.via !== undefined ||
|
|
970
|
+
env["CENTRS_VIA"] !== undefined ||
|
|
971
|
+
config["CENTRS_VIA"] !== undefined
|
|
972
|
+
) {
|
|
893
973
|
return false;
|
|
894
974
|
}
|
|
895
975
|
// Decide the default transport from the *effective* target (host >
|
|
@@ -901,6 +981,7 @@ function isUnresolvedMacTarget(
|
|
|
901
981
|
targetInput: request.targetInput,
|
|
902
982
|
cdbTarget: cdb?.target,
|
|
903
983
|
env,
|
|
984
|
+
config,
|
|
904
985
|
});
|
|
905
986
|
return candidate ? isMacAddress(candidate) : false;
|
|
906
987
|
}
|
|
@@ -908,6 +989,7 @@ function isUnresolvedMacTarget(
|
|
|
908
989
|
function resolveFormat(
|
|
909
990
|
request: ExecuteRequest,
|
|
910
991
|
env: Record<string, string | undefined>,
|
|
992
|
+
config: Record<string, string | undefined> = {},
|
|
911
993
|
): ResolvedSetting<ExecuteOutputFormat> {
|
|
912
994
|
return resolveStringSetting(
|
|
913
995
|
request.format,
|
|
@@ -916,6 +998,8 @@ function resolveFormat(
|
|
|
916
998
|
"text",
|
|
917
999
|
"format",
|
|
918
1000
|
parseOutputFormat,
|
|
1001
|
+
undefined,
|
|
1002
|
+
config,
|
|
919
1003
|
) as ResolvedSetting<ExecuteOutputFormat>;
|
|
920
1004
|
}
|
|
921
1005
|
|
|
@@ -941,6 +1025,7 @@ function resolveTimeoutSetting(
|
|
|
941
1025
|
env: Record<string, string | undefined>,
|
|
942
1026
|
via: RouterOsProtocol,
|
|
943
1027
|
commentKv?: ResolvedSetting<number>,
|
|
1028
|
+
config: Record<string, string | undefined> = {},
|
|
944
1029
|
): ResolvedSetting<number> {
|
|
945
1030
|
const resolved = resolveStringSetting(
|
|
946
1031
|
timeout === undefined ? undefined : String(timeout),
|
|
@@ -961,6 +1046,7 @@ function resolveTimeoutSetting(
|
|
|
961
1046
|
return parsed;
|
|
962
1047
|
},
|
|
963
1048
|
commentKv,
|
|
1049
|
+
config,
|
|
964
1050
|
);
|
|
965
1051
|
if (!resolved) {
|
|
966
1052
|
throw new Error("timeout resolution produced no value");
|
|
@@ -1299,28 +1385,6 @@ function syntaxCause(error: unknown): unknown {
|
|
|
1299
1385
|
return error;
|
|
1300
1386
|
}
|
|
1301
1387
|
|
|
1302
|
-
function pathTokens(path: string): string[] {
|
|
1303
|
-
return path.split("/").filter(Boolean);
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1306
|
-
function inspectPath(tokens: readonly string[]): string {
|
|
1307
|
-
return tokens.join(",");
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
function isArgumentNode(child: InspectChildItem): boolean {
|
|
1311
|
-
return child.type === "arg" || child["node-type"] === "arg";
|
|
1312
|
-
}
|
|
1313
|
-
|
|
1314
|
-
function extractCompletionNames(
|
|
1315
|
-
rows: readonly InspectCompletionItem[],
|
|
1316
|
-
): string[] {
|
|
1317
|
-
return rows
|
|
1318
|
-
.flatMap((row) => [row.completion, row.name, row.value, row.text])
|
|
1319
|
-
.filter((value): value is string => typeof value === "string")
|
|
1320
|
-
.map((value) => value.replace(/=.*$/, "").trim())
|
|
1321
|
-
.filter((value) => value.length > 0);
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
1388
|
function parseOutputFormat(value: string): ExecuteOutputFormat {
|
|
1325
1389
|
if (executeOutputFormats.includes(value as ExecuteOutputFormat)) {
|
|
1326
1390
|
return value as ExecuteOutputFormat;
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,52 @@
|
|
|
1
1
|
export const centrsVersion = "0.1.0";
|
|
2
2
|
|
|
3
|
+
export {
|
|
4
|
+
type ApiEnvelope,
|
|
5
|
+
type ApiErrorEnvelope,
|
|
6
|
+
type ApiMethod,
|
|
7
|
+
type ApiOperationMeta,
|
|
8
|
+
type ApiOutputFormat,
|
|
9
|
+
type ApiRequest,
|
|
10
|
+
type ApiRequestSummary,
|
|
11
|
+
type ApiStreamMeta,
|
|
12
|
+
type ApiStreamStopReason,
|
|
13
|
+
type ApiStreamSummary,
|
|
14
|
+
type ApiSuccessEnvelope,
|
|
15
|
+
api,
|
|
16
|
+
apiEnvelope,
|
|
17
|
+
apiListen,
|
|
18
|
+
apiMethods,
|
|
19
|
+
apiOutputFormats,
|
|
20
|
+
apiRequestSummaryFromRequest,
|
|
21
|
+
buildApiBody,
|
|
22
|
+
buildApiErrorEnvelope,
|
|
23
|
+
buildApiErrorEnvelopeFromResolved,
|
|
24
|
+
buildApiQuery,
|
|
25
|
+
buildProtocolApiRequest,
|
|
26
|
+
isApiMutating,
|
|
27
|
+
mapMethodToVerb,
|
|
28
|
+
type NormalizedApiEndpoint,
|
|
29
|
+
normalizeApiEndpoint,
|
|
30
|
+
parseApiMethod,
|
|
31
|
+
type ResolvedApiRequest,
|
|
32
|
+
renderApiEnvelope,
|
|
33
|
+
renderApiStreamLine,
|
|
34
|
+
resolveApiRequest,
|
|
35
|
+
runResolvedApi,
|
|
36
|
+
validateApiRequestShape,
|
|
37
|
+
} from "./api.ts";
|
|
38
|
+
export {
|
|
39
|
+
type ApiFanoutData,
|
|
40
|
+
type ApiFanoutEnvelope,
|
|
41
|
+
type ApiFanoutErrorEnvelope,
|
|
42
|
+
type ApiFanoutInternals,
|
|
43
|
+
type ApiFanoutOperationMeta,
|
|
44
|
+
type ApiFanoutOptions,
|
|
45
|
+
type ApiSelectionSummary,
|
|
46
|
+
apiFanout,
|
|
47
|
+
buildApiFanoutErrorEnvelope,
|
|
48
|
+
renderApiFanoutEnvelope,
|
|
49
|
+
} from "./api-fanout.ts";
|
|
3
50
|
export {
|
|
4
51
|
BTEST_CLIENT_CSV_HEADER,
|
|
5
52
|
BTEST_SERVER_CSV_HEADER,
|
|
@@ -41,6 +88,36 @@ export {
|
|
|
41
88
|
type SettingSourceKind,
|
|
42
89
|
type Warning,
|
|
43
90
|
} from "./core/envelope.ts";
|
|
91
|
+
export {
|
|
92
|
+
buildFanoutEnvelope,
|
|
93
|
+
buildFanoutResolveFailure,
|
|
94
|
+
commonVia,
|
|
95
|
+
FANOUT_BACKOFF_BASE_MS,
|
|
96
|
+
FANOUT_CONCURRENCY_DEFAULTS,
|
|
97
|
+
FANOUT_MAX_RETRIES,
|
|
98
|
+
FANOUT_RETRYABLE_CODES,
|
|
99
|
+
fanoutExitCode,
|
|
100
|
+
isRetryableFanoutError,
|
|
101
|
+
resolveFanoutConcurrency,
|
|
102
|
+
runBoundedPool,
|
|
103
|
+
runFanout,
|
|
104
|
+
runWithRetry,
|
|
105
|
+
summarizeFanout,
|
|
106
|
+
} from "./core/fanout.ts";
|
|
107
|
+
export {
|
|
108
|
+
extractCompletionNames,
|
|
109
|
+
type InspectBackend,
|
|
110
|
+
type InspectChildItem,
|
|
111
|
+
type InspectCompletionItem,
|
|
112
|
+
type InspectRequestKind,
|
|
113
|
+
inspectChildren,
|
|
114
|
+
inspectChildrenOrEmpty,
|
|
115
|
+
inspectCompletions,
|
|
116
|
+
inspectPath,
|
|
117
|
+
isArgumentNode,
|
|
118
|
+
isCommandNode,
|
|
119
|
+
pathTokens,
|
|
120
|
+
} from "./core/inspect.ts";
|
|
44
121
|
export {
|
|
45
122
|
encodeMndpPacket,
|
|
46
123
|
MNDP_BROADCAST_ADDRESS,
|
|
@@ -115,6 +192,7 @@ export {
|
|
|
115
192
|
type DevicesShowEnvelopeData,
|
|
116
193
|
type DevicesShowItem,
|
|
117
194
|
type DevicesWarning,
|
|
195
|
+
type DevicesWhereClause,
|
|
118
196
|
defaultCdbPath,
|
|
119
197
|
devicesOutputFormats,
|
|
120
198
|
editInteractiveOnlyError,
|
|
@@ -170,6 +248,7 @@ export {
|
|
|
170
248
|
canonicalizeExecuteCommand,
|
|
171
249
|
type ExecuteEnvelope,
|
|
172
250
|
type ExecuteErrorEnvelope,
|
|
251
|
+
type ExecuteGlobalContext,
|
|
173
252
|
type ExecuteOperationMeta,
|
|
174
253
|
type ExecuteOutputFormat,
|
|
175
254
|
type ExecuteRequest,
|
|
@@ -180,16 +259,32 @@ export {
|
|
|
180
259
|
executeOutputFormats,
|
|
181
260
|
isWriteShaped,
|
|
182
261
|
renderExecuteEnvelope,
|
|
262
|
+
resolveExecuteGlobalContext,
|
|
183
263
|
resolveExecuteRequest,
|
|
184
264
|
runResolvedExecute,
|
|
185
265
|
validateExecuteRequestShape,
|
|
186
266
|
} from "./execute.ts";
|
|
187
267
|
export {
|
|
268
|
+
buildExecuteFanoutErrorEnvelope,
|
|
269
|
+
type ExecuteFanoutData,
|
|
270
|
+
type ExecuteFanoutEnvelope,
|
|
271
|
+
type ExecuteFanoutErrorEnvelope,
|
|
272
|
+
type ExecuteFanoutInternals,
|
|
273
|
+
type ExecuteFanoutOperationMeta,
|
|
274
|
+
type ExecuteFanoutOptions,
|
|
275
|
+
type ExecuteSelectionSummary,
|
|
276
|
+
executeFanout,
|
|
277
|
+
renderExecuteFanoutEnvelope,
|
|
278
|
+
} from "./execute-fanout.ts";
|
|
279
|
+
export {
|
|
280
|
+
type ApiVerb,
|
|
188
281
|
createProtocolAdapter,
|
|
189
282
|
getProtocolPlan,
|
|
190
283
|
type ProtocolAdapter,
|
|
191
284
|
type ProtocolAdapterCapabilities,
|
|
192
285
|
type ProtocolAdapterConfig,
|
|
286
|
+
type ProtocolApiRequest,
|
|
287
|
+
type ProtocolApiResult,
|
|
193
288
|
type ProtocolCapability,
|
|
194
289
|
type ProtocolExecuteRequest,
|
|
195
290
|
type ProtocolExecuteResult,
|
|
@@ -201,27 +296,48 @@ export {
|
|
|
201
296
|
type RouterOsProtocol,
|
|
202
297
|
} from "./protocols/index.ts";
|
|
203
298
|
export {
|
|
299
|
+
type AltitudeType,
|
|
204
300
|
applyCommentKv,
|
|
301
|
+
type BboxPredicate,
|
|
205
302
|
type CdbGroupExpansion,
|
|
206
303
|
type CdbGroupResolveInput,
|
|
207
304
|
type CdbGroupTarget,
|
|
208
305
|
type CdbResolution,
|
|
209
306
|
type CdbResolveInput,
|
|
307
|
+
type CdbSelectionExpansion,
|
|
308
|
+
type CdbSelectionMember,
|
|
309
|
+
type CdbSelectionResolveInput,
|
|
310
|
+
type CommentKvGeoKey,
|
|
210
311
|
type CommentKvKey,
|
|
211
312
|
type CommentKvLayer,
|
|
212
313
|
type CommentKvOverrides,
|
|
213
314
|
type CommentKvResult,
|
|
214
315
|
type CommentKvUpdate,
|
|
215
316
|
type CommentKvWarning,
|
|
317
|
+
canonicalizeGeoKey,
|
|
216
318
|
coerceCommentKv,
|
|
217
319
|
commentKvAllowlist,
|
|
320
|
+
commentKvGeoKeys,
|
|
218
321
|
commentKvReservedKeys,
|
|
322
|
+
type DeviceLocation,
|
|
219
323
|
defaultPortForScheme,
|
|
324
|
+
deviceLocation,
|
|
220
325
|
expandCdbGroup,
|
|
326
|
+
expandCdbSelection,
|
|
327
|
+
isDefaultRecordTarget,
|
|
328
|
+
type NearPredicate,
|
|
329
|
+
type ParsedGpsTuple,
|
|
330
|
+
parseAltitude,
|
|
331
|
+
parseAltitudeType,
|
|
332
|
+
parseBbox,
|
|
221
333
|
parseBoolean,
|
|
222
334
|
parseCommentKv,
|
|
223
335
|
parseDuration,
|
|
336
|
+
parseGpsTuple,
|
|
224
337
|
parseHostCandidate,
|
|
338
|
+
parseLatLon,
|
|
339
|
+
parseNear,
|
|
340
|
+
parseRawCommentFacts,
|
|
225
341
|
type ResolvedAuth,
|
|
226
342
|
type ResolvedSetting,
|
|
227
343
|
type ResolvedTarget,
|
|
@@ -235,7 +351,9 @@ export {
|
|
|
235
351
|
resolveOptionalIntegerSetting,
|
|
236
352
|
resolveStringSetting,
|
|
237
353
|
resolveTarget,
|
|
354
|
+
type SelectionWhereClause,
|
|
238
355
|
type TargetResolveInput,
|
|
356
|
+
type TargetSelection,
|
|
239
357
|
toCoreSource,
|
|
240
358
|
} from "./resolver/index.ts";
|
|
241
359
|
export {
|
|
@@ -262,22 +380,47 @@ export {
|
|
|
262
380
|
} from "./retrieve.ts";
|
|
263
381
|
export {
|
|
264
382
|
buildRetrieveFanoutErrorEnvelope,
|
|
265
|
-
isRetryableFanoutError,
|
|
266
|
-
RETRIEVE_FANOUT_BACKOFF_BASE_MS,
|
|
267
|
-
RETRIEVE_FANOUT_CONCURRENCY_DEFAULTS,
|
|
268
|
-
RETRIEVE_FANOUT_MAX_RETRIES,
|
|
269
|
-
RETRIEVE_FANOUT_RETRYABLE_CODES,
|
|
270
383
|
type RetrieveFanoutData,
|
|
271
384
|
type RetrieveFanoutEnvelope,
|
|
272
385
|
type RetrieveFanoutErrorEnvelope,
|
|
386
|
+
type RetrieveFanoutInternals,
|
|
273
387
|
type RetrieveFanoutOperationMeta,
|
|
274
|
-
type
|
|
388
|
+
type RetrieveFanoutOptions,
|
|
389
|
+
type RetrieveSelectionSummary,
|
|
275
390
|
renderRetrieveFanoutEnvelope,
|
|
276
|
-
|
|
391
|
+
retrieveFanout,
|
|
277
392
|
retrieveGroup,
|
|
278
|
-
runBoundedPool,
|
|
279
|
-
summarizeFanout,
|
|
280
393
|
} from "./retrieve-fanout.ts";
|
|
394
|
+
export {
|
|
395
|
+
buildSettingsErrorEnvelope,
|
|
396
|
+
renderSettingsEnvelope,
|
|
397
|
+
type SettingsCommand,
|
|
398
|
+
type SettingsDefaultDeviceSummary,
|
|
399
|
+
type SettingsEnvelope,
|
|
400
|
+
type SettingsErrorEnvelope,
|
|
401
|
+
type SettingsGetArgs,
|
|
402
|
+
type SettingsGetData,
|
|
403
|
+
type SettingsKeyDef,
|
|
404
|
+
type SettingsKeyEntry,
|
|
405
|
+
type SettingsOperationMeta,
|
|
406
|
+
type SettingsOutputFormat,
|
|
407
|
+
type SettingsPrintArgs,
|
|
408
|
+
type SettingsPrintData,
|
|
409
|
+
type SettingsResetArgs,
|
|
410
|
+
type SettingsResetData,
|
|
411
|
+
type SettingsSetArgs,
|
|
412
|
+
type SettingsSetData,
|
|
413
|
+
type SettingsSuccessEnvelope,
|
|
414
|
+
type SettingsUnrecognizedEntry,
|
|
415
|
+
type SettingsValue,
|
|
416
|
+
settingsGet,
|
|
417
|
+
settingsManagedKeys,
|
|
418
|
+
settingsOutputFormats,
|
|
419
|
+
settingsPrint,
|
|
420
|
+
settingsRefusedKeys,
|
|
421
|
+
settingsReset,
|
|
422
|
+
settingsSet,
|
|
423
|
+
} from "./settings.ts";
|
|
281
424
|
export {
|
|
282
425
|
buildSshTerminalArgv,
|
|
283
426
|
buildTerminalErrorEnvelope,
|
|
@@ -290,6 +433,7 @@ export {
|
|
|
290
433
|
export {
|
|
291
434
|
buildTransferErrorEnvelope,
|
|
292
435
|
FILE_READ_CHUNK_BYTES,
|
|
436
|
+
isTransferWriteVerb,
|
|
293
437
|
normalizeRemotePath,
|
|
294
438
|
REST_FILE_WRITE_CAP_BYTES,
|
|
295
439
|
renderTransferEnvelope,
|
|
@@ -312,6 +456,19 @@ export {
|
|
|
312
456
|
transferVerbs,
|
|
313
457
|
validateTransferRequestShape,
|
|
314
458
|
} from "./transfer.ts";
|
|
459
|
+
export {
|
|
460
|
+
buildTransferFanoutErrorEnvelope,
|
|
461
|
+
renderTransferFanoutEnvelope,
|
|
462
|
+
type TransferFanoutData,
|
|
463
|
+
type TransferFanoutEnvelope,
|
|
464
|
+
type TransferFanoutErrorEnvelope,
|
|
465
|
+
type TransferFanoutInternals,
|
|
466
|
+
type TransferFanoutOperationMeta,
|
|
467
|
+
type TransferFanoutOptions,
|
|
468
|
+
type TransferFanoutRequestSummary,
|
|
469
|
+
type TransferSelectionSummary,
|
|
470
|
+
transferFanout,
|
|
471
|
+
} from "./transfer-fanout.ts";
|
|
315
472
|
|
|
316
473
|
import { plannedProtocols, type RouterOsProtocol } from "./protocols/index.ts";
|
|
317
474
|
|
package/src/mcp/config.ts
CHANGED
|
@@ -46,16 +46,26 @@ export interface ResolveMcpConfigArgs {
|
|
|
46
46
|
cdbPassword?: string;
|
|
47
47
|
allowAdhocTargets?: boolean;
|
|
48
48
|
env?: Record<string, string | undefined>;
|
|
49
|
+
/**
|
|
50
|
+
* The `centrs.env` config tier (`src/resolver/config-file.ts`), loaded by
|
|
51
|
+
* the caller — `resolveMcpConfig` itself stays synchronous so it can keep
|
|
52
|
+
* serving as a default-parameter value (`server.ts`). `CENTRS_CDB_PASSWORD`
|
|
53
|
+
* deliberately never reads it, same as `resolveAuth`'s credential fields.
|
|
54
|
+
*/
|
|
55
|
+
config?: Record<string, string | undefined>;
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
export function resolveMcpConfig(
|
|
52
59
|
args: ResolveMcpConfigArgs = {},
|
|
53
60
|
): CentrsMcpConfig {
|
|
54
61
|
const env = args.env ?? Bun.env;
|
|
55
|
-
const
|
|
62
|
+
const config = args.config ?? {};
|
|
63
|
+
const explicitPath =
|
|
64
|
+
args.cdbFile ?? env[ENV_CDB_FILE] ?? config[ENV_CDB_FILE] ?? undefined;
|
|
56
65
|
const cdbFile = explicitPath ?? defaultCdbPath(env);
|
|
57
66
|
const allowAdhocTargets =
|
|
58
|
-
args.allowAdhocTargets ??
|
|
67
|
+
args.allowAdhocTargets ??
|
|
68
|
+
(env[ENV_ALLOW_ADHOC] ?? config[ENV_ALLOW_ADHOC]) === "1";
|
|
59
69
|
return {
|
|
60
70
|
cdbFile,
|
|
61
71
|
cdbFileExplicit: explicitPath !== undefined,
|