buckyos 0.7.116 → 0.7.119
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/cli/README.md +14 -10
- package/cli/core/argv.ts +0 -4
- package/cli/core/auth.ts +104 -20
- package/cli/core/config.ts +0 -38
- package/cli/core/development_mode.ts +103 -0
- package/cli/core/identity.ts +39 -31
- package/cli/core/registry.ts +0 -2
- package/cli/dist/cli.mjs +320 -230
- package/cli/dist/cli.mjs.map +1 -1
- package/cli/runtime/host.ts +8 -10
- package/cli/version.ts +1 -1
- package/dist/browser.cjs +1 -1
- package/dist/browser.mjs +59 -58
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +59 -58
- package/dist/namelib.d.ts +4 -0
- package/dist/namelib.d.ts.map +1 -1
- package/dist/ndm_proxy-68354a89.js +13 -0
- package/dist/ndm_proxy-68354a89.js.map +1 -0
- package/dist/{ndm_proxy-a719bc58.mjs → ndm_proxy-c00bc561.mjs} +75 -58
- package/dist/ndm_proxy-c00bc561.mjs.map +1 -0
- package/dist/ndn_types-859bbd48.js +2 -0
- package/dist/ndn_types-859bbd48.js.map +1 -0
- package/dist/{ndn_types-ca94286b.mjs → ndn_types-f6c08d20.mjs} +43 -7
- package/dist/ndn_types-f6c08d20.mjs.map +1 -0
- package/dist/node.cjs +1 -1
- package/dist/node.mjs +59 -58
- package/dist/provision.cjs +1 -1
- package/dist/provision.mjs +1 -1
- package/dist/sn_client.d.ts +16 -0
- package/dist/sn_client.d.ts.map +1 -1
- package/dist/task_mgr_client.d.ts +10 -0
- package/dist/task_mgr_client.d.ts.map +1 -1
- package/dist/{tus_client-f1532e14.mjs → tus_client-573066b3.mjs} +2 -2
- package/dist/{tus_client-f1532e14.mjs.map → tus_client-573066b3.mjs.map} +1 -1
- package/dist/{tus_client-32d016c4.js → tus_client-83ad0f4f.js} +2 -2
- package/dist/{tus_client-32d016c4.js.map → tus_client-83ad0f4f.js.map} +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/ndm_proxy-36879436.js +0 -13
- package/dist/ndm_proxy-36879436.js.map +0 -1
- package/dist/ndm_proxy-a719bc58.mjs.map +0 -1
- package/dist/ndn_types-c4672b04.js +0 -2
- package/dist/ndn_types-c4672b04.js.map +0 -1
- package/dist/ndn_types-ca94286b.mjs.map +0 -1
package/cli/dist/cli.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import process from "node:process";
|
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import * as nodePath from "node:path";
|
|
4
4
|
import { resolve as resolve$5, dirname as dirname$3 } from "node:path";
|
|
5
|
-
import {
|
|
5
|
+
import { BuckyOSSDK, RuntimeType, buckyos, namelib, VerifyHubClient, createAppInstanceId, parseSessionTokenClaims, ndn, ndm_proxy } from "buckyos/node";
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
7
7
|
import { readFile, writeFile, readdir, stat, lstat, realpath, mkdtemp, rename, rm, mkdir, chmod, symlink, copyFile, open } from "node:fs/promises";
|
|
8
8
|
import { createReadStream, createWriteStream } from "node:fs";
|
|
@@ -94,8 +94,6 @@ const STRING_GLOBALS = /* @__PURE__ */ new Map([
|
|
|
94
94
|
["zone", "zone"],
|
|
95
95
|
["endpoint", "endpoint"],
|
|
96
96
|
["identity", "identity"],
|
|
97
|
-
["identity-root", "identityRoot"],
|
|
98
|
-
["security-root", "securityRoot"],
|
|
99
97
|
["session-token", "sessionToken"],
|
|
100
98
|
["session-token-file", "sessionTokenFile"],
|
|
101
99
|
["output", "output"],
|
|
@@ -485,8 +483,6 @@ const TOOL_ENVIRONMENT_NAMES = [
|
|
|
485
483
|
"BUCKYOS_TOOL_ENDPOINT",
|
|
486
484
|
"BUCKYOS_TOOL_IDENTITY",
|
|
487
485
|
"BUCKYOS_TOOL_OUTPUT",
|
|
488
|
-
"BUCKYOS_IDENTITY_ROOT",
|
|
489
|
-
"BUCKYOS_SECURITY_ROOT",
|
|
490
486
|
"BUCKYOS_APPCLIENT_SESSION_TOKEN",
|
|
491
487
|
"BUCKYOS_ROOT",
|
|
492
488
|
"SOURCE_DATE_EPOCH"
|
|
@@ -499,14 +495,16 @@ function buildDistributionPolicy(options) {
|
|
|
499
495
|
const configRoot = path.resolve(
|
|
500
496
|
environment2.BUCKYOS_TOOL_CONFIG_DIR ?? path.join(homeDir, ".buckyos_tool")
|
|
501
497
|
);
|
|
502
|
-
const readPaths = /* @__PURE__ */ new Set([
|
|
498
|
+
const readPaths = /* @__PURE__ */ new Set([
|
|
499
|
+
path.resolve(packageRoot2),
|
|
500
|
+
path.resolve(cwd),
|
|
501
|
+
configRoot,
|
|
502
|
+
path.resolve(path.join(homeDir, ".buckyos")),
|
|
503
|
+
path.resolve(path.join(homeDir, ".buckycli"))
|
|
504
|
+
]);
|
|
503
505
|
const writePaths = /* @__PURE__ */ new Set([path.resolve(cwd), configRoot]);
|
|
504
506
|
if (options.distribution === "system")
|
|
505
507
|
readPaths.add(buckyosRoot);
|
|
506
|
-
if (environment2.BUCKYOS_IDENTITY_ROOT && environment2.BUCKYOS_SECURITY_ROOT) {
|
|
507
|
-
readPaths.add(path.resolve(environment2.BUCKYOS_IDENTITY_ROOT));
|
|
508
|
-
readPaths.add(path.resolve(environment2.BUCKYOS_SECURITY_ROOT));
|
|
509
|
-
}
|
|
510
508
|
const parsed = collectArgumentPaths(argv);
|
|
511
509
|
for (const candidate of parsed.read)
|
|
512
510
|
readPaths.add(resolveInputPath(candidate, cwd, path));
|
|
@@ -603,7 +601,7 @@ function collectArgumentPaths(argv) {
|
|
|
603
601
|
write.push(value);
|
|
604
602
|
} else if (name === "allow-read") {
|
|
605
603
|
read.push(value);
|
|
606
|
-
} else if (["input", "session-token-file", "
|
|
604
|
+
} else if (["input", "session-token-file", "pikg"].includes(name)) {
|
|
607
605
|
if (value !== "-")
|
|
608
606
|
read.push(value);
|
|
609
607
|
} else if (name === "source" && module === "pikg") {
|
|
@@ -686,8 +684,6 @@ const ENVIRONMENT_NAMES = [
|
|
|
686
684
|
"BUCKYOS_TOOL_ENDPOINT",
|
|
687
685
|
"BUCKYOS_TOOL_IDENTITY",
|
|
688
686
|
"BUCKYOS_TOOL_OUTPUT",
|
|
689
|
-
"BUCKYOS_IDENTITY_ROOT",
|
|
690
|
-
"BUCKYOS_SECURITY_ROOT",
|
|
691
687
|
"BUCKYOS_APPCLIENT_SESSION_TOKEN",
|
|
692
688
|
"BUCKYOS_ROOT"
|
|
693
689
|
];
|
|
@@ -830,34 +826,6 @@ async function resolveConfig(explicit, environment2 = readEnvironment(), options
|
|
|
830
826
|
void 0,
|
|
831
827
|
sources
|
|
832
828
|
);
|
|
833
|
-
const identityRoot = select(
|
|
834
|
-
"identity_root",
|
|
835
|
-
explicit.identityRoot,
|
|
836
|
-
environment2.BUCKYOS_IDENTITY_ROOT,
|
|
837
|
-
void 0,
|
|
838
|
-
void 0,
|
|
839
|
-
sources
|
|
840
|
-
);
|
|
841
|
-
const securityRoot = select(
|
|
842
|
-
"security_root",
|
|
843
|
-
explicit.securityRoot,
|
|
844
|
-
environment2.BUCKYOS_SECURITY_ROOT,
|
|
845
|
-
void 0,
|
|
846
|
-
void 0,
|
|
847
|
-
sources
|
|
848
|
-
);
|
|
849
|
-
if (!!explicit.identityRoot !== !!explicit.securityRoot) {
|
|
850
|
-
throw new UsageError(
|
|
851
|
-
"IDENTITY_ROOT_PAIR_REQUIRED",
|
|
852
|
-
"--identity-root and --security-root must be provided together"
|
|
853
|
-
);
|
|
854
|
-
}
|
|
855
|
-
if (!!environment2.BUCKYOS_IDENTITY_ROOT !== !!environment2.BUCKYOS_SECURITY_ROOT && !explicit.identityRoot) {
|
|
856
|
-
throw new UsageError(
|
|
857
|
-
"IDENTITY_ROOT_PAIR_REQUIRED",
|
|
858
|
-
"BUCKYOS_IDENTITY_ROOT and BUCKYOS_SECURITY_ROOT must be provided together"
|
|
859
|
-
);
|
|
860
|
-
}
|
|
861
829
|
let output;
|
|
862
830
|
if (options.interactive && explicit.output === void 0) {
|
|
863
831
|
output = "table";
|
|
@@ -890,8 +858,6 @@ async function resolveConfig(explicit, environment2 = readEnvironment(), options
|
|
|
890
858
|
zone,
|
|
891
859
|
endpoint,
|
|
892
860
|
identity,
|
|
893
|
-
identityRoot,
|
|
894
|
-
securityRoot,
|
|
895
861
|
sessionToken,
|
|
896
862
|
sessionTokenFile: explicit.sessionTokenFile,
|
|
897
863
|
output,
|
|
@@ -925,8 +891,6 @@ function localResolvedConfig(explicit, environment2 = readEnvironment(), options
|
|
|
925
891
|
zone: explicit.zone ?? environment2.BUCKYOS_TOOL_ZONE,
|
|
926
892
|
endpoint: explicit.endpoint ?? environment2.BUCKYOS_TOOL_ENDPOINT,
|
|
927
893
|
identity: explicit.identity ?? environment2.BUCKYOS_TOOL_IDENTITY,
|
|
928
|
-
identityRoot: explicit.identityRoot ?? environment2.BUCKYOS_IDENTITY_ROOT,
|
|
929
|
-
securityRoot: explicit.securityRoot ?? environment2.BUCKYOS_SECURITY_ROOT,
|
|
930
894
|
sessionToken: explicit.sessionToken ?? environment2.BUCKYOS_APPCLIENT_SESSION_TOKEN,
|
|
931
895
|
sessionTokenFile: explicit.sessionTokenFile,
|
|
932
896
|
output,
|
|
@@ -1091,6 +1055,196 @@ function redactUrl(value) {
|
|
|
1091
1055
|
function configValueError(message) {
|
|
1092
1056
|
return new ToolError("INVALID_CONFIG_VALUE", message, 2);
|
|
1093
1057
|
}
|
|
1058
|
+
class BuckyOSRuntimeAdapter {
|
|
1059
|
+
#sdk = new BuckyOSSDK("node");
|
|
1060
|
+
async initialize(config, session) {
|
|
1061
|
+
const authenticated = session.current();
|
|
1062
|
+
const zoneHost = resolveZoneHost(config);
|
|
1063
|
+
const initialize = this.#sdk.initBuckyOS;
|
|
1064
|
+
await initialize.call(this.#sdk, authenticated.principal.appId, {
|
|
1065
|
+
appId: authenticated.principal.appId,
|
|
1066
|
+
ownerUserId: authenticated.principal.id,
|
|
1067
|
+
runtimeType: RuntimeType.AppClient,
|
|
1068
|
+
zoneHost,
|
|
1069
|
+
defaultProtocol: config.defaultProtocol,
|
|
1070
|
+
sessionToken: authenticated.token,
|
|
1071
|
+
privateKeySearchPaths: [],
|
|
1072
|
+
autoRenew: false,
|
|
1073
|
+
verifyHubServiceUrl: resolveServiceUrl(config, "verify-hub")
|
|
1074
|
+
});
|
|
1075
|
+
return {
|
|
1076
|
+
zone: config.zone ?? zoneHost,
|
|
1077
|
+
endpoint: config.endpoint ?? `${config.defaultProtocol}${zoneHost}`,
|
|
1078
|
+
defaultProtocol: config.defaultProtocol
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
class BuckyOSServiceClientRegistry {
|
|
1083
|
+
#config;
|
|
1084
|
+
#session;
|
|
1085
|
+
#clients = /* @__PURE__ */ new Map();
|
|
1086
|
+
constructor(config, session) {
|
|
1087
|
+
this.#config = config;
|
|
1088
|
+
this.#session = session;
|
|
1089
|
+
}
|
|
1090
|
+
async call(service, method, params, options) {
|
|
1091
|
+
let client = this.#clients.get(service);
|
|
1092
|
+
if (!client) {
|
|
1093
|
+
const RpcClient = buckyos.kRPCClient;
|
|
1094
|
+
client = new RpcClient(resolveServiceUrl(this.#config, service), null, null, {
|
|
1095
|
+
sessionTokenProvider: async () => (await this.#session.ensureValid()).token
|
|
1096
|
+
});
|
|
1097
|
+
this.#clients.set(service, client);
|
|
1098
|
+
}
|
|
1099
|
+
const request = client.call(method, params, { traceId: options.traceId });
|
|
1100
|
+
return await withDeadline(request, options.timeoutMs, options.signal);
|
|
1101
|
+
}
|
|
1102
|
+
async createEventReader(pattern, signal) {
|
|
1103
|
+
return await buckyos.createEventReader(pattern, { keepaliveMs: 5e3, signal });
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
class InteractiveSession {
|
|
1107
|
+
constructor(authentication, clients, connection) {
|
|
1108
|
+
this.authentication = authentication;
|
|
1109
|
+
this.clients = clients;
|
|
1110
|
+
this.connection = connection;
|
|
1111
|
+
this.startedAt = Date.now();
|
|
1112
|
+
}
|
|
1113
|
+
static async create(config, authentication, runtime = new BuckyOSRuntimeAdapter(), clients) {
|
|
1114
|
+
await authentication.connect();
|
|
1115
|
+
const connection = await runtime.initialize(config, authentication);
|
|
1116
|
+
return new InteractiveSession(
|
|
1117
|
+
authentication,
|
|
1118
|
+
clients ?? new BuckyOSServiceClientRegistry(config, authentication),
|
|
1119
|
+
connection
|
|
1120
|
+
);
|
|
1121
|
+
}
|
|
1122
|
+
async reconnect() {
|
|
1123
|
+
await this.authentication.reconnect();
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
function resolveServiceUrl(config, service) {
|
|
1127
|
+
if (config.endpoint) {
|
|
1128
|
+
const endpoint = new URL(config.endpoint);
|
|
1129
|
+
const marker = endpoint.pathname.indexOf("/kapi/");
|
|
1130
|
+
if (marker >= 0)
|
|
1131
|
+
endpoint.pathname = `${endpoint.pathname.slice(0, marker)}/kapi/${service}`;
|
|
1132
|
+
else if (endpoint.pathname.endsWith("/kapi")) {
|
|
1133
|
+
endpoint.pathname = `${endpoint.pathname}/${service}`;
|
|
1134
|
+
} else
|
|
1135
|
+
endpoint.pathname = `${endpoint.pathname.replace(/\/$/, "")}/kapi/${service}`;
|
|
1136
|
+
endpoint.search = "";
|
|
1137
|
+
endpoint.hash = "";
|
|
1138
|
+
return endpoint.toString().replace(/\/$/, "");
|
|
1139
|
+
}
|
|
1140
|
+
const host2 = resolveZoneHost(config);
|
|
1141
|
+
return `${config.defaultProtocol}${host2}/kapi/${service}`;
|
|
1142
|
+
}
|
|
1143
|
+
function resolveZoneHost(config) {
|
|
1144
|
+
if (config.zone) {
|
|
1145
|
+
try {
|
|
1146
|
+
return namelib.DID.fromStr(config.zone).toRawHostName();
|
|
1147
|
+
} catch {
|
|
1148
|
+
throw new UsageError("INVALID_ZONE", `invalid zone host or DID: ${config.zone}`);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
if (config.endpoint)
|
|
1152
|
+
return new URL(config.endpoint).host;
|
|
1153
|
+
throw new UsageError("CONNECTION_REQUIRED", "an endpoint or zone is required for online commands");
|
|
1154
|
+
}
|
|
1155
|
+
async function withDeadline(promise, timeoutMs, signal) {
|
|
1156
|
+
if (signal?.aborted)
|
|
1157
|
+
throw new ToolError("CANCELED", "operation canceled", 8);
|
|
1158
|
+
let timer;
|
|
1159
|
+
let abortHandler;
|
|
1160
|
+
const guards = [
|
|
1161
|
+
new Promise((_, reject) => {
|
|
1162
|
+
timer = setTimeout(
|
|
1163
|
+
() => reject(new ToolError("TIMEOUT", "operation timed out", 8, true)),
|
|
1164
|
+
timeoutMs
|
|
1165
|
+
);
|
|
1166
|
+
})
|
|
1167
|
+
];
|
|
1168
|
+
if (signal) {
|
|
1169
|
+
guards.push(
|
|
1170
|
+
new Promise((_, reject) => {
|
|
1171
|
+
abortHandler = () => reject(new ToolError("CANCELED", "operation canceled", 8));
|
|
1172
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
1173
|
+
})
|
|
1174
|
+
);
|
|
1175
|
+
}
|
|
1176
|
+
try {
|
|
1177
|
+
return await Promise.race([promise, ...guards]);
|
|
1178
|
+
} finally {
|
|
1179
|
+
if (timer !== void 0)
|
|
1180
|
+
clearTimeout(timer);
|
|
1181
|
+
if (signal && abortHandler)
|
|
1182
|
+
signal.removeEventListener("abort", abortHandler);
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
const BUCKYOS_DEV_CONFIG_SCHEMA_VERSION = 1;
|
|
1186
|
+
async function readTargetDevelopmentMode(config) {
|
|
1187
|
+
try {
|
|
1188
|
+
const url = resolveServiceUrl(config, "control-panel");
|
|
1189
|
+
const client = new buckyos.kRPCClient(url);
|
|
1190
|
+
const value = await withTimeout(
|
|
1191
|
+
client.call("system.dev_mode.get", {}),
|
|
1192
|
+
config.timeoutMs
|
|
1193
|
+
);
|
|
1194
|
+
const parsed = parseBuckyOSDevConfig(value);
|
|
1195
|
+
return parsed.enabled ? { state: "enabled", config: parsed } : { state: "disabled", config: parsed };
|
|
1196
|
+
} catch (error) {
|
|
1197
|
+
return {
|
|
1198
|
+
state: "unavailable",
|
|
1199
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
function parseBuckyOSDevConfig(value) {
|
|
1204
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1205
|
+
throw new Error("BuckyOSDevConfig must be an object");
|
|
1206
|
+
}
|
|
1207
|
+
const config = value;
|
|
1208
|
+
const keys = Object.keys(config).sort();
|
|
1209
|
+
const expectedKeys = ["enabled", "enabled_at", "enabled_by", "schema_version"];
|
|
1210
|
+
if (JSON.stringify(keys) !== JSON.stringify(expectedKeys)) {
|
|
1211
|
+
throw new Error("BuckyOSDevConfig contains missing or unsupported fields");
|
|
1212
|
+
}
|
|
1213
|
+
if (config.schema_version !== BUCKYOS_DEV_CONFIG_SCHEMA_VERSION) {
|
|
1214
|
+
throw new Error(`unsupported BuckyOSDevConfig schema_version ${String(config.schema_version)}`);
|
|
1215
|
+
}
|
|
1216
|
+
if (typeof config.enabled !== "boolean") {
|
|
1217
|
+
throw new Error("BuckyOSDevConfig enabled must be a boolean");
|
|
1218
|
+
}
|
|
1219
|
+
const enabledAt = config.enabled_at;
|
|
1220
|
+
const enabledBy = config.enabled_by;
|
|
1221
|
+
const hasAuditFields = Number.isSafeInteger(enabledAt) && enabledAt > 0 && typeof enabledBy === "string" && enabledBy.trim().length > 0;
|
|
1222
|
+
const hasNoAuditFields = enabledAt === null && enabledBy === null;
|
|
1223
|
+
if (!hasAuditFields && !hasNoAuditFields) {
|
|
1224
|
+
throw new Error("BuckyOSDevConfig enabled_at and enabled_by must be valid and present together");
|
|
1225
|
+
}
|
|
1226
|
+
if (config.enabled && !hasAuditFields) {
|
|
1227
|
+
throw new Error("enabled BuckyOSDevConfig requires enable audit fields");
|
|
1228
|
+
}
|
|
1229
|
+
return {
|
|
1230
|
+
schema_version: 1,
|
|
1231
|
+
enabled: config.enabled,
|
|
1232
|
+
enabled_at: enabledAt,
|
|
1233
|
+
enabled_by: enabledBy
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1236
|
+
async function withTimeout(promise, timeoutMs) {
|
|
1237
|
+
let timer;
|
|
1238
|
+
const timeout = new Promise((_, reject) => {
|
|
1239
|
+
timer = setTimeout(() => reject(new Error("developer-mode lookup timed out")), timeoutMs);
|
|
1240
|
+
});
|
|
1241
|
+
try {
|
|
1242
|
+
return await Promise.race([promise, timeout]);
|
|
1243
|
+
} finally {
|
|
1244
|
+
if (timer !== void 0)
|
|
1245
|
+
clearTimeout(timer);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1094
1248
|
const join$2 = (...parts) => getHost().path.join(...parts);
|
|
1095
1249
|
const LOCAL_NODE_GATEWAY_ENDPOINT = "http://127.0.0.1:3180";
|
|
1096
1250
|
const IDENTITY_CANDIDATE_LIMIT = 8;
|
|
@@ -1174,45 +1328,38 @@ async function readCurrentDeviceIdentity(environment2 = readEnvironment()) {
|
|
|
1174
1328
|
securityRoot: join$2(buckyosRoot, "security")
|
|
1175
1329
|
};
|
|
1176
1330
|
}
|
|
1177
|
-
function identityRootPairs(config, environment2 = readEnvironment()) {
|
|
1331
|
+
function identityRootPairs(config, environment2 = readEnvironment(), options = {}) {
|
|
1332
|
+
const device = config.implicitDeviceIdentity;
|
|
1333
|
+
if (device) {
|
|
1334
|
+
return [{
|
|
1335
|
+
publicRoot: device.publicRoot,
|
|
1336
|
+
securityRoot: device.securityRoot,
|
|
1337
|
+
source: "current-device"
|
|
1338
|
+
}];
|
|
1339
|
+
}
|
|
1340
|
+
const home = environment2.HOME ?? environment2.USERPROFILE ?? getHost().homeDir();
|
|
1178
1341
|
const pairs = [];
|
|
1179
|
-
if (
|
|
1342
|
+
if (options.includeOperations ?? true) {
|
|
1180
1343
|
pairs.push({
|
|
1181
|
-
publicRoot:
|
|
1182
|
-
securityRoot:
|
|
1183
|
-
source: "
|
|
1344
|
+
publicRoot: join$2(home, ".buckyos", "local", "identity"),
|
|
1345
|
+
securityRoot: join$2(home, ".buckyos", "security"),
|
|
1346
|
+
source: "buckyos-home"
|
|
1184
1347
|
});
|
|
1185
1348
|
}
|
|
1186
|
-
|
|
1187
|
-
publicRoot: join$2(config.configDir, "local", "identity"),
|
|
1188
|
-
securityRoot: join$2(config.configDir, "security"),
|
|
1189
|
-
source: "tool"
|
|
1190
|
-
});
|
|
1191
|
-
if (environment2.BUCKYOS_IDENTITY_ROOT && environment2.BUCKYOS_SECURITY_ROOT) {
|
|
1192
|
-
const duplicate = config.identityRoot === environment2.BUCKYOS_IDENTITY_ROOT && config.securityRoot === environment2.BUCKYOS_SECURITY_ROOT;
|
|
1193
|
-
if (!duplicate) {
|
|
1194
|
-
pairs.push({
|
|
1195
|
-
publicRoot: environment2.BUCKYOS_IDENTITY_ROOT,
|
|
1196
|
-
securityRoot: environment2.BUCKYOS_SECURITY_ROOT,
|
|
1197
|
-
source: "environment"
|
|
1198
|
-
});
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
if (getHost().policy.distribution === "system") {
|
|
1202
|
-
const buckyosRoot = environment2.BUCKYOS_ROOT ?? defaultBuckyOSRoot(environment2);
|
|
1349
|
+
if (options.includeDeveloper ?? false) {
|
|
1203
1350
|
pairs.push({
|
|
1204
|
-
publicRoot: join$2(
|
|
1205
|
-
securityRoot: join$2(
|
|
1206
|
-
source: "
|
|
1351
|
+
publicRoot: join$2(home, ".buckycli", "local", "identity"),
|
|
1352
|
+
securityRoot: join$2(home, ".buckycli", "security"),
|
|
1353
|
+
source: "buckycli-home"
|
|
1207
1354
|
});
|
|
1208
1355
|
}
|
|
1209
1356
|
return deduplicatePairs(pairs);
|
|
1210
1357
|
}
|
|
1211
|
-
async function resolveIdentityMaterial(selectedIdentity, config, environment2 = readEnvironment()) {
|
|
1358
|
+
async function resolveIdentityMaterial(selectedIdentity, config, environment2 = readEnvironment(), options = {}) {
|
|
1212
1359
|
const selected = selectedIdentity.trim();
|
|
1213
1360
|
if (!selected)
|
|
1214
1361
|
throw new UsageError("IDENTITY_REQUIRED", "identity is empty");
|
|
1215
|
-
for (const roots of identityRootPairs(config, environment2)) {
|
|
1362
|
+
for (const roots of identityRootPairs(config, environment2, options)) {
|
|
1216
1363
|
for (const directory of await candidateDirectories(roots.publicRoot, selected)) {
|
|
1217
1364
|
const material = await loadIdentityMaterial(roots, directory, selected);
|
|
1218
1365
|
if (material)
|
|
@@ -1225,11 +1372,11 @@ async function resolveIdentityMaterial(selectedIdentity, config, environment2 =
|
|
|
1225
1372
|
EXIT_AUTH
|
|
1226
1373
|
);
|
|
1227
1374
|
}
|
|
1228
|
-
async function scanIdentityCandidates(config, environment2 = readEnvironment()) {
|
|
1375
|
+
async function scanIdentityCandidates(config, environment2 = readEnvironment(), options = {}) {
|
|
1229
1376
|
const candidates = [];
|
|
1230
1377
|
const skipped = [];
|
|
1231
1378
|
const seen = /* @__PURE__ */ new Set();
|
|
1232
|
-
const roots = identityRootPairs(config, environment2);
|
|
1379
|
+
const roots = identityRootPairs(config, environment2, options);
|
|
1233
1380
|
for (const pair of roots) {
|
|
1234
1381
|
let directories;
|
|
1235
1382
|
try {
|
|
@@ -1283,16 +1430,18 @@ async function scanIdentityCandidates(config, environment2 = readEnvironment())
|
|
|
1283
1430
|
break;
|
|
1284
1431
|
}
|
|
1285
1432
|
return {
|
|
1286
|
-
order: Object.freeze(
|
|
1433
|
+
order: Object.freeze(roots.map((pair) => pair.source)),
|
|
1287
1434
|
limit: IDENTITY_CANDIDATE_LIMIT,
|
|
1288
1435
|
candidates,
|
|
1289
1436
|
skipped
|
|
1290
1437
|
};
|
|
1291
1438
|
}
|
|
1292
|
-
async function identityCandidateView(config, environment2 = readEnvironment()) {
|
|
1439
|
+
async function identityCandidateView(config, environment2 = readEnvironment(), developerModeEnabled = false) {
|
|
1293
1440
|
if (config.identity) {
|
|
1294
1441
|
try {
|
|
1295
|
-
const material = await resolveIdentityMaterial(config.identity, config, environment2
|
|
1442
|
+
const material = await resolveIdentityMaterial(config.identity, config, environment2, {
|
|
1443
|
+
includeDeveloper: developerModeEnabled
|
|
1444
|
+
});
|
|
1296
1445
|
return {
|
|
1297
1446
|
mode: "explicit",
|
|
1298
1447
|
order: [material.did],
|
|
@@ -1317,7 +1466,9 @@ async function identityCandidateView(config, environment2 = readEnvironment()) {
|
|
|
1317
1466
|
};
|
|
1318
1467
|
}
|
|
1319
1468
|
}
|
|
1320
|
-
const scan = await scanIdentityCandidates(config, environment2
|
|
1469
|
+
const scan = await scanIdentityCandidates(config, environment2, {
|
|
1470
|
+
includeDeveloper: developerModeEnabled
|
|
1471
|
+
});
|
|
1321
1472
|
return {
|
|
1322
1473
|
mode: "search",
|
|
1323
1474
|
order: scan.order,
|
|
@@ -1353,7 +1504,8 @@ async function loadIdentityMaterial(roots, directory, selected) {
|
|
|
1353
1504
|
securityRoot: roots.securityRoot,
|
|
1354
1505
|
documentPath,
|
|
1355
1506
|
privateKeyPath,
|
|
1356
|
-
privateKeyPem
|
|
1507
|
+
privateKeyPem,
|
|
1508
|
+
source: roots.source
|
|
1357
1509
|
};
|
|
1358
1510
|
} catch (error) {
|
|
1359
1511
|
if (!isHostError(error, "NotFound"))
|
|
@@ -1438,133 +1590,6 @@ function deduplicatePairs(pairs) {
|
|
|
1438
1590
|
return true;
|
|
1439
1591
|
});
|
|
1440
1592
|
}
|
|
1441
|
-
class BuckyOSRuntimeAdapter {
|
|
1442
|
-
#sdk = new BuckyOSSDK("node");
|
|
1443
|
-
async initialize(config, session) {
|
|
1444
|
-
const authenticated = session.current();
|
|
1445
|
-
const zoneHost = resolveZoneHost(config);
|
|
1446
|
-
const initialize = this.#sdk.initBuckyOS;
|
|
1447
|
-
await initialize.call(this.#sdk, authenticated.principal.appId, {
|
|
1448
|
-
appId: authenticated.principal.appId,
|
|
1449
|
-
ownerUserId: authenticated.principal.id,
|
|
1450
|
-
runtimeType: RuntimeType.AppClient,
|
|
1451
|
-
zoneHost,
|
|
1452
|
-
defaultProtocol: config.defaultProtocol,
|
|
1453
|
-
sessionToken: authenticated.token,
|
|
1454
|
-
privateKeySearchPaths: [],
|
|
1455
|
-
autoRenew: false,
|
|
1456
|
-
verifyHubServiceUrl: resolveServiceUrl(config, "verify-hub")
|
|
1457
|
-
});
|
|
1458
|
-
return {
|
|
1459
|
-
zone: config.zone ?? zoneHost,
|
|
1460
|
-
endpoint: config.endpoint ?? `${config.defaultProtocol}${zoneHost}`,
|
|
1461
|
-
defaultProtocol: config.defaultProtocol
|
|
1462
|
-
};
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
class BuckyOSServiceClientRegistry {
|
|
1466
|
-
#config;
|
|
1467
|
-
#session;
|
|
1468
|
-
#clients = /* @__PURE__ */ new Map();
|
|
1469
|
-
constructor(config, session) {
|
|
1470
|
-
this.#config = config;
|
|
1471
|
-
this.#session = session;
|
|
1472
|
-
}
|
|
1473
|
-
async call(service, method, params, options) {
|
|
1474
|
-
let client = this.#clients.get(service);
|
|
1475
|
-
if (!client) {
|
|
1476
|
-
const RpcClient = buckyos.kRPCClient;
|
|
1477
|
-
client = new RpcClient(resolveServiceUrl(this.#config, service), null, null, {
|
|
1478
|
-
sessionTokenProvider: async () => (await this.#session.ensureValid()).token
|
|
1479
|
-
});
|
|
1480
|
-
this.#clients.set(service, client);
|
|
1481
|
-
}
|
|
1482
|
-
const request = client.call(method, params, { traceId: options.traceId });
|
|
1483
|
-
return await withDeadline(request, options.timeoutMs, options.signal);
|
|
1484
|
-
}
|
|
1485
|
-
async createEventReader(pattern, signal) {
|
|
1486
|
-
return await buckyos.createEventReader(pattern, { keepaliveMs: 5e3, signal });
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
class InteractiveSession {
|
|
1490
|
-
constructor(authentication, clients, connection) {
|
|
1491
|
-
this.authentication = authentication;
|
|
1492
|
-
this.clients = clients;
|
|
1493
|
-
this.connection = connection;
|
|
1494
|
-
this.startedAt = Date.now();
|
|
1495
|
-
}
|
|
1496
|
-
static async create(config, authentication, runtime = new BuckyOSRuntimeAdapter(), clients) {
|
|
1497
|
-
await authentication.connect();
|
|
1498
|
-
const connection = await runtime.initialize(config, authentication);
|
|
1499
|
-
return new InteractiveSession(
|
|
1500
|
-
authentication,
|
|
1501
|
-
clients ?? new BuckyOSServiceClientRegistry(config, authentication),
|
|
1502
|
-
connection
|
|
1503
|
-
);
|
|
1504
|
-
}
|
|
1505
|
-
async reconnect() {
|
|
1506
|
-
await this.authentication.reconnect();
|
|
1507
|
-
}
|
|
1508
|
-
}
|
|
1509
|
-
function resolveServiceUrl(config, service) {
|
|
1510
|
-
if (config.endpoint) {
|
|
1511
|
-
const endpoint = new URL(config.endpoint);
|
|
1512
|
-
const marker = endpoint.pathname.indexOf("/kapi/");
|
|
1513
|
-
if (marker >= 0)
|
|
1514
|
-
endpoint.pathname = `${endpoint.pathname.slice(0, marker)}/kapi/${service}`;
|
|
1515
|
-
else if (endpoint.pathname.endsWith("/kapi")) {
|
|
1516
|
-
endpoint.pathname = `${endpoint.pathname}/${service}`;
|
|
1517
|
-
} else
|
|
1518
|
-
endpoint.pathname = `${endpoint.pathname.replace(/\/$/, "")}/kapi/${service}`;
|
|
1519
|
-
endpoint.search = "";
|
|
1520
|
-
endpoint.hash = "";
|
|
1521
|
-
return endpoint.toString().replace(/\/$/, "");
|
|
1522
|
-
}
|
|
1523
|
-
const host2 = resolveZoneHost(config);
|
|
1524
|
-
return `${config.defaultProtocol}${host2}/kapi/${service}`;
|
|
1525
|
-
}
|
|
1526
|
-
function resolveZoneHost(config) {
|
|
1527
|
-
if (config.zone) {
|
|
1528
|
-
try {
|
|
1529
|
-
return namelib.DID.fromStr(config.zone).toRawHostName();
|
|
1530
|
-
} catch {
|
|
1531
|
-
throw new UsageError("INVALID_ZONE", `invalid zone host or DID: ${config.zone}`);
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
if (config.endpoint)
|
|
1535
|
-
return new URL(config.endpoint).host;
|
|
1536
|
-
throw new UsageError("CONNECTION_REQUIRED", "an endpoint or zone is required for online commands");
|
|
1537
|
-
}
|
|
1538
|
-
async function withDeadline(promise, timeoutMs, signal) {
|
|
1539
|
-
if (signal?.aborted)
|
|
1540
|
-
throw new ToolError("CANCELED", "operation canceled", 8);
|
|
1541
|
-
let timer;
|
|
1542
|
-
let abortHandler;
|
|
1543
|
-
const guards = [
|
|
1544
|
-
new Promise((_, reject) => {
|
|
1545
|
-
timer = setTimeout(
|
|
1546
|
-
() => reject(new ToolError("TIMEOUT", "operation timed out", 8, true)),
|
|
1547
|
-
timeoutMs
|
|
1548
|
-
);
|
|
1549
|
-
})
|
|
1550
|
-
];
|
|
1551
|
-
if (signal) {
|
|
1552
|
-
guards.push(
|
|
1553
|
-
new Promise((_, reject) => {
|
|
1554
|
-
abortHandler = () => reject(new ToolError("CANCELED", "operation canceled", 8));
|
|
1555
|
-
signal.addEventListener("abort", abortHandler, { once: true });
|
|
1556
|
-
})
|
|
1557
|
-
);
|
|
1558
|
-
}
|
|
1559
|
-
try {
|
|
1560
|
-
return await Promise.race([promise, ...guards]);
|
|
1561
|
-
} finally {
|
|
1562
|
-
if (timer !== void 0)
|
|
1563
|
-
clearTimeout(timer);
|
|
1564
|
-
if (signal && abortHandler)
|
|
1565
|
-
signal.removeEventListener("abort", abortHandler);
|
|
1566
|
-
}
|
|
1567
|
-
}
|
|
1568
1593
|
const LOGIN_APP_ID = "buckycli";
|
|
1569
1594
|
const LOGIN_TOKEN_TTL_SECONDS = 10 * 60;
|
|
1570
1595
|
class AuthenticationSession {
|
|
@@ -1575,15 +1600,18 @@ class AuthenticationSession {
|
|
|
1575
1600
|
this.#transport = dependencies.transport ?? new SdkAuthenticationTransport();
|
|
1576
1601
|
this.#readPassword = dependencies.readPassword ?? readSecret;
|
|
1577
1602
|
this.#readUsername = dependencies.readUsername ?? readVisible;
|
|
1603
|
+
this.#readDevelopmentMode = dependencies.readDevelopmentMode ?? readTargetDevelopmentMode;
|
|
1578
1604
|
this.#now = dependencies.now ?? Date.now;
|
|
1579
1605
|
}
|
|
1580
1606
|
#environment;
|
|
1581
1607
|
#transport;
|
|
1582
1608
|
#readPassword;
|
|
1583
1609
|
#readUsername;
|
|
1610
|
+
#readDevelopmentMode;
|
|
1584
1611
|
#now;
|
|
1585
1612
|
#session;
|
|
1586
1613
|
#acceptedIdentity;
|
|
1614
|
+
#developmentMode;
|
|
1587
1615
|
#identityAttempts;
|
|
1588
1616
|
async connect() {
|
|
1589
1617
|
if (this.#session)
|
|
@@ -1631,6 +1659,7 @@ class AuthenticationSession {
|
|
|
1631
1659
|
renewable: session.renewable,
|
|
1632
1660
|
expires_at: expiresAt ?? null,
|
|
1633
1661
|
remaining_seconds: remainingSeconds,
|
|
1662
|
+
developer_mode: this.#developmentMode?.state ?? null,
|
|
1634
1663
|
identity_attempts: this.#identityAttempts
|
|
1635
1664
|
};
|
|
1636
1665
|
}
|
|
@@ -1658,34 +1687,39 @@ class AuthenticationSession {
|
|
|
1658
1687
|
const injected = this.#environment.BUCKYOS_APPCLIENT_SESSION_TOKEN?.trim();
|
|
1659
1688
|
if (injected)
|
|
1660
1689
|
return externalSession(injected, "environment", this.#now());
|
|
1661
|
-
if (this.#acceptedIdentity)
|
|
1690
|
+
if (this.#acceptedIdentity) {
|
|
1691
|
+
if (this.#acceptedIdentity.source === "buckycli-home") {
|
|
1692
|
+
await this.#requireDeveloperIdentityAccess();
|
|
1693
|
+
}
|
|
1662
1694
|
return await this.#loginWithIdentity(this.#acceptedIdentity);
|
|
1695
|
+
}
|
|
1663
1696
|
if (this.config.identity) {
|
|
1664
|
-
const material = await
|
|
1665
|
-
this.config.identity,
|
|
1666
|
-
this.config,
|
|
1667
|
-
this.#environment
|
|
1668
|
-
);
|
|
1697
|
+
const material = await this.#resolveExplicitIdentity(this.config.identity);
|
|
1669
1698
|
const session = await this.#loginWithIdentity(material);
|
|
1670
1699
|
this.#acceptedIdentity = material;
|
|
1671
1700
|
return session;
|
|
1672
1701
|
}
|
|
1673
|
-
const candidates = await scanIdentityCandidates(this.config, this.#environment);
|
|
1674
1702
|
this.#identityAttempts = [];
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1703
|
+
const operations = await scanIdentityCandidates(this.config, this.#environment);
|
|
1704
|
+
const operationsSession = await this.#tryIdentityCandidates(operations.candidates);
|
|
1705
|
+
if (operationsSession)
|
|
1706
|
+
return operationsSession;
|
|
1707
|
+
const developmentMode = await this.#checkDevelopmentMode();
|
|
1708
|
+
if (developmentMode.state === "enabled" && operations.candidates.length < IDENTITY_CANDIDATE_LIMIT) {
|
|
1709
|
+
const operationsDids = new Set(
|
|
1710
|
+
operations.candidates.map((candidate) => candidate.material.did)
|
|
1711
|
+
);
|
|
1712
|
+
const developer = await scanIdentityCandidates(this.config, this.#environment, {
|
|
1713
|
+
includeOperations: false,
|
|
1714
|
+
includeDeveloper: true
|
|
1715
|
+
});
|
|
1716
|
+
const remaining = IDENTITY_CANDIDATE_LIMIT - operations.candidates.length;
|
|
1717
|
+
const candidates = developer.candidates.filter(
|
|
1718
|
+
(candidate) => !operationsDids.has(candidate.material.did)
|
|
1719
|
+
).slice(0, remaining);
|
|
1720
|
+
const developerSession = await this.#tryIdentityCandidates(candidates);
|
|
1721
|
+
if (developerSession)
|
|
1722
|
+
return developerSession;
|
|
1689
1723
|
}
|
|
1690
1724
|
if (this.#identityAttempts.length > 0) {
|
|
1691
1725
|
throw new ToolError(
|
|
@@ -1716,6 +1750,40 @@ class AuthenticationSession {
|
|
|
1716
1750
|
);
|
|
1717
1751
|
return authenticatedSession(token, "password", true, this.#now());
|
|
1718
1752
|
}
|
|
1753
|
+
async #resolveExplicitIdentity(selectedIdentity) {
|
|
1754
|
+
if (this.config.implicitDeviceIdentity) {
|
|
1755
|
+
return await resolveIdentityMaterial(selectedIdentity, this.config, this.#environment);
|
|
1756
|
+
}
|
|
1757
|
+
try {
|
|
1758
|
+
return await resolveIdentityMaterial(selectedIdentity, this.config, this.#environment);
|
|
1759
|
+
} catch (error) {
|
|
1760
|
+
if (!(error instanceof ToolError) || error.code !== "IDENTITY_NOT_FOUND")
|
|
1761
|
+
throw error;
|
|
1762
|
+
}
|
|
1763
|
+
await this.#requireDeveloperIdentityAccess();
|
|
1764
|
+
return await resolveIdentityMaterial(selectedIdentity, this.config, this.#environment, {
|
|
1765
|
+
includeOperations: false,
|
|
1766
|
+
includeDeveloper: true
|
|
1767
|
+
});
|
|
1768
|
+
}
|
|
1769
|
+
async #tryIdentityCandidates(candidates) {
|
|
1770
|
+
for (const candidate of candidates) {
|
|
1771
|
+
try {
|
|
1772
|
+
const session = await this.#loginWithIdentity(candidate.material);
|
|
1773
|
+
this.#acceptedIdentity = candidate.material;
|
|
1774
|
+
return session;
|
|
1775
|
+
} catch (error) {
|
|
1776
|
+
if (!isIdentityRejection(error))
|
|
1777
|
+
throw error;
|
|
1778
|
+
this.#identityAttempts.push({
|
|
1779
|
+
identity: candidate.material.did,
|
|
1780
|
+
code: error.code,
|
|
1781
|
+
message: sanitizeMessage(error.message)
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
return void 0;
|
|
1786
|
+
}
|
|
1719
1787
|
async #loginWithIdentity(material) {
|
|
1720
1788
|
const loginJwt = await createLoginJwt(
|
|
1721
1789
|
material.subject,
|
|
@@ -1731,6 +1799,30 @@ class AuthenticationSession {
|
|
|
1731
1799
|
);
|
|
1732
1800
|
return authenticatedSession(token, "identity", true, this.#now());
|
|
1733
1801
|
}
|
|
1802
|
+
async #checkDevelopmentMode() {
|
|
1803
|
+
this.#developmentMode = await this.#readDevelopmentMode(this.config);
|
|
1804
|
+
return this.#developmentMode;
|
|
1805
|
+
}
|
|
1806
|
+
async #requireDeveloperIdentityAccess() {
|
|
1807
|
+
const decision = await this.#checkDevelopmentMode();
|
|
1808
|
+
if (decision.state === "enabled")
|
|
1809
|
+
return;
|
|
1810
|
+
this.#acceptedIdentity = void 0;
|
|
1811
|
+
if (decision.state === "disabled") {
|
|
1812
|
+
throw new ToolError(
|
|
1813
|
+
"DEVELOPER_IDENTITY_DISABLED",
|
|
1814
|
+
"the target Zone has developer mode disabled; local developer identities are unavailable",
|
|
1815
|
+
EXIT_AUTH
|
|
1816
|
+
);
|
|
1817
|
+
}
|
|
1818
|
+
throw new ToolError(
|
|
1819
|
+
"DEVELOPER_MODE_UNAVAILABLE",
|
|
1820
|
+
"the target Zone developer-mode configuration could not be verified",
|
|
1821
|
+
EXIT_AUTH,
|
|
1822
|
+
true,
|
|
1823
|
+
{ reason: sanitizeMessage(decision.reason) }
|
|
1824
|
+
);
|
|
1825
|
+
}
|
|
1734
1826
|
}
|
|
1735
1827
|
function isIdentityRejection(error) {
|
|
1736
1828
|
return error instanceof ToolError && IDENTITY_REJECTION_CODES.includes(error.code);
|
|
@@ -2005,8 +2097,6 @@ const GLOBAL_OPTIONS = [
|
|
|
2005
2097
|
{ name: "zone", property: "zone", type: "string", scope: "session" },
|
|
2006
2098
|
{ name: "endpoint", property: "endpoint", type: "string", scope: "session" },
|
|
2007
2099
|
{ name: "identity", property: "identity", type: "string", scope: "session" },
|
|
2008
|
-
{ name: "identity-root", property: "identityRoot", type: "string", scope: "session" },
|
|
2009
|
-
{ name: "security-root", property: "securityRoot", type: "string", scope: "session" },
|
|
2010
2100
|
{
|
|
2011
2101
|
name: "session-token",
|
|
2012
2102
|
property: "sessionToken",
|
|
@@ -4758,7 +4848,7 @@ function invalid(stage, message, entry) {
|
|
|
4758
4848
|
function stableJsonDigest(value) {
|
|
4759
4849
|
return sha256Bytes(new TextEncoder().encode(ndn.toCanonicalJsonString(value)));
|
|
4760
4850
|
}
|
|
4761
|
-
const PACKAGE_VERSION = "0.7.
|
|
4851
|
+
const PACKAGE_VERSION = "0.7.119";
|
|
4762
4852
|
const TOOL_VERSION = PACKAGE_VERSION;
|
|
4763
4853
|
const SDK_VERSION = PACKAGE_VERSION;
|
|
4764
4854
|
const PROTOCOL_VERSION = "1";
|