rainskills 0.1.19 → 0.1.21
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 +34 -39
- package/SKILL.md +12 -10
- package/bin/rainskills-tools.js +114 -240
- package/bin/rainskills.js +134 -591
- package/install.sh +68 -94
- package/marketplace/rainskills/.claude-plugin/plugin.json +1 -1
- package/marketplace/rainskills/.codex-plugin/plugin.json +1 -1
- package/marketplace/rainskills/skills/rainskills/SKILL.md +13 -11
- package/package.json +2 -2
- package/rainbond-app-assistant/SKILL.md +116 -151
- package/rainbond-app-version-assistant/SKILL.md +98 -98
- package/rainbond-delivery-verifier/SKILL.md +98 -68
- package/rainbond-env-sync/SKILL.md +98 -69
- package/rainbond-fullstack-bootstrap/SKILL.md +101 -89
- package/rainbond-fullstack-bootstrap/modules/10-context-loading.md +1 -1
- package/rainbond-fullstack-troubleshooter/SKILL.md +98 -68
- package/rainbond-opensource-app-deploy/SKILL.md +102 -81
- package/rainbond-platform-installer/SKILL.md +4 -4
- package/rainbond-platform-installer/scripts/auto-update.js +0 -9
- package/rainbond-platform-installer/scripts/installed-version.js +1 -1
- package/rainbond-platform-installer/scripts/platform-installer.js +3 -89
- package/rainbond-platform-installer/scripts/runtime-state.js +14 -251
- package/rainbond-platform-installer/scripts/single-runtime.js +114 -0
- package/rainbond-platform-installer/scripts/user-message.js +3 -49
- package/rainbond-platform-installer/scripts/windows-client-config.js +0 -51
- package/rainbond-platform-installer/scripts/windows-onboarding.js +0 -3
- package/rainbond-platform-installer/scripts/windows-platform.ps1 +1 -1
- package/rainbond-platform-query/SKILL.md +103 -61
- package/rainbond-project-init/SKILL.md +102 -79
- package/rainbond-template-installer/SKILL.md +102 -80
- package/rainbond-platform-installer/scripts/environment-credentials.js +0 -225
- package/rainbond-platform-installer/scripts/environment-registry.js +0 -349
- package/rainbond-platform-installer/scripts/local-runtime-commands.js +0 -180
- package/rainbond-platform-installer/scripts/local-runtime.js +0 -58
- package/rainbond-platform-installer/scripts/runtime-context-resolver.js +0 -189
- package/rainbond-platform-installer/scripts/runtime-credentials.js +0 -163
- package/rainbond-platform-installer/scripts/runtime-intents.js +0 -386
- package/rainbond-platform-installer/scripts/runtime-operations.js +0 -597
- package/rainbond-platform-installer/scripts/windows-client-config.ps1 +0 -9
- package/rainbond-platform-installer/scripts/windows-read-user-environment.ps1 +0 -16
package/bin/rainskills-tools.js
CHANGED
|
@@ -17,8 +17,6 @@ const PROTOCOL_VERSION = "2025-03-26";
|
|
|
17
17
|
const ENDPOINT_PATH = "/console/mcp/rainskills/api/query";
|
|
18
18
|
const CLI_VERSION = "2.1.0";
|
|
19
19
|
const CONFIG_DIRECTORY = ".rainbond";
|
|
20
|
-
const CREDENTIALS_FILENAME = "credentials.env";
|
|
21
|
-
const LEGACY_CREDENTIALS_FILENAME = "mcp.env";
|
|
22
20
|
const CATALOG_FILENAME = "capabilities.json";
|
|
23
21
|
const OPERATIONS_DIRECTORY = "operations";
|
|
24
22
|
const SKILL_MANIFEST_FILENAME = "rainskills-skill-manifest.json";
|
|
@@ -76,62 +74,6 @@ class BridgeError extends Error {
|
|
|
76
74
|
}
|
|
77
75
|
}
|
|
78
76
|
|
|
79
|
-
function parseShellValue(value) {
|
|
80
|
-
let offset = 0;
|
|
81
|
-
let result = "";
|
|
82
|
-
while (offset < value.length) {
|
|
83
|
-
const quote = value[offset];
|
|
84
|
-
if (quote === "'") {
|
|
85
|
-
const end = value.indexOf("'", offset + 1);
|
|
86
|
-
if (end === -1) return null;
|
|
87
|
-
result += value.slice(offset + 1, end);
|
|
88
|
-
offset = end + 1;
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
if (quote === '"') {
|
|
92
|
-
const end = value.indexOf('"', offset + 1);
|
|
93
|
-
if (end === -1) return null;
|
|
94
|
-
result += value.slice(offset + 1, end).replace(/\\([\\"$`])/g, "$1");
|
|
95
|
-
offset = end + 1;
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
const match = value.slice(offset).match(/^[^\s'"#]+/);
|
|
99
|
-
if (!match) return null;
|
|
100
|
-
result += match[0];
|
|
101
|
-
offset += match[0].length;
|
|
102
|
-
}
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function parseEnvFile(contents) {
|
|
107
|
-
const values = {};
|
|
108
|
-
for (const line of contents.split(/\r?\n/)) {
|
|
109
|
-
const match = line.match(/^\s*(?:export\s+)?(RAINBOND_URL|RAINBOND_JWT|RAINBOND_ALLOW_INSECURE_HTTP)\s*=\s*(.*?)\s*$/);
|
|
110
|
-
if (!match) continue;
|
|
111
|
-
const parsed = parseShellValue(match[2]);
|
|
112
|
-
if (parsed !== null) values[match[1]] = parsed;
|
|
113
|
-
}
|
|
114
|
-
return values;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function readPrivateEnvFile(configPath) {
|
|
118
|
-
let stat;
|
|
119
|
-
try {
|
|
120
|
-
stat = fs.lstatSync(configPath);
|
|
121
|
-
} catch (error) {
|
|
122
|
-
if (error.code === "ENOENT") return {};
|
|
123
|
-
throw new BridgeError("unable to inspect Rainbond configuration", EXIT.CONFIG);
|
|
124
|
-
}
|
|
125
|
-
if (!stat.isFile() || stat.isSymbolicLink() || (stat.mode & 0o077) !== 0) {
|
|
126
|
-
throw new BridgeError("Rainbond configuration must be a private regular file", EXIT.CONFIG);
|
|
127
|
-
}
|
|
128
|
-
try {
|
|
129
|
-
return parseEnvFile(fs.readFileSync(configPath, "utf8"));
|
|
130
|
-
} catch (_error) {
|
|
131
|
-
throw new BridgeError("unable to read Rainbond configuration", EXIT.CONFIG);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
77
|
function requireRuntimeModule(filename) {
|
|
136
78
|
const candidates = [
|
|
137
79
|
path.resolve(__dirname, "..", "rainbond-platform-installer", "scripts", filename),
|
|
@@ -166,69 +108,25 @@ function requireRuntimeFile(...segments) {
|
|
|
166
108
|
throw new BridgeError("installed Rainskills package upload helper is incomplete", EXIT.CONFIG);
|
|
167
109
|
}
|
|
168
110
|
|
|
169
|
-
function loadOperationConfig({ homeDir, operationId, includeRuntime }) {
|
|
170
|
-
let operationStore;
|
|
171
|
-
const { createEnvironmentRegistry } = requireRuntimeModule("environment-registry.js");
|
|
172
|
-
const { createEnvironmentCredentialStore } = requireRuntimeModule("environment-credentials.js");
|
|
173
|
-
const { createRuntimeOperationStore } = requireRuntimeModule("runtime-operations.js");
|
|
174
|
-
const registry = createEnvironmentRegistry({
|
|
175
|
-
home: homeDir,
|
|
176
|
-
activeOperationIds: (environmentId) => operationStore?.activeOperationIds(environmentId) || [],
|
|
177
|
-
});
|
|
178
|
-
operationStore = createRuntimeOperationStore({ home: homeDir, registry });
|
|
179
|
-
const operation = operationStore.read(operationId);
|
|
180
|
-
if (!operation || !["active", "interrupted"].includes(operation.stage)) {
|
|
181
|
-
throw new BridgeError("protected runtime operation is missing or inactive", EXIT.CONFIG);
|
|
182
|
-
}
|
|
183
|
-
const environment = registry.get(operation.environment_id);
|
|
184
|
-
if (!environment || environment.connection_state !== "connected") {
|
|
185
|
-
throw new BridgeError("the operation environment is unavailable", EXIT.CONFIG);
|
|
186
|
-
}
|
|
187
|
-
const credential = createEnvironmentCredentialStore({ home: homeDir }).read({
|
|
188
|
-
environmentId: environment.id,
|
|
189
|
-
expectedOrigin: environment.console_origin,
|
|
190
|
-
});
|
|
191
|
-
const parsed = new URL(environment.console_origin);
|
|
192
|
-
const { INTENT_DEFINITIONS } = requireRuntimeModule("runtime-intents.js");
|
|
193
|
-
const requiredSkillId = INTENT_DEFINITIONS[operation.intent.type]?.skillId;
|
|
194
|
-
if (!requiredSkillId) {
|
|
195
|
-
throw new BridgeError("the protected runtime intent has no Skill binding", EXIT.CONFIG);
|
|
196
|
-
}
|
|
197
|
-
return {
|
|
198
|
-
baseUrl: environment.console_origin,
|
|
199
|
-
jwt: credential.token,
|
|
200
|
-
operationId: operation.operation_id,
|
|
201
|
-
environmentId: environment.id,
|
|
202
|
-
intent: operation.intent,
|
|
203
|
-
requiredSkillId,
|
|
204
|
-
operationStore,
|
|
205
|
-
...(includeRuntime ? {
|
|
206
|
-
homeDir,
|
|
207
|
-
allowInsecureHttp: parsed.protocol === "http:",
|
|
208
|
-
isInsecureHttp: parsed.protocol === "http:",
|
|
209
|
-
} : {}),
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
111
|
function loadConfig({
|
|
214
112
|
env = process.env,
|
|
215
113
|
homeDir = os.homedir(),
|
|
216
114
|
includeRuntime = false,
|
|
217
|
-
operationId,
|
|
218
115
|
} = {}) {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const
|
|
116
|
+
const hasEnvironmentOverride = env.RAINSKILLS_CREDENTIAL_SOURCE === "environment";
|
|
117
|
+
if (hasEnvironmentOverride && !(env.RAINBOND_URL && env.RAINBOND_JWT)) {
|
|
118
|
+
throw new BridgeError(
|
|
119
|
+
"RAINBOND_URL and RAINBOND_JWT must be provided together",
|
|
120
|
+
EXIT.CONFIG
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
const stored = hasEnvironmentOverride
|
|
124
|
+
? null
|
|
125
|
+
: requireRuntimeModule("single-runtime.js").createSingleRuntimeStore({ home: homeDir }).read();
|
|
126
|
+
const baseUrl = hasEnvironmentOverride ? env.RAINBOND_URL : stored?.console_origin;
|
|
127
|
+
const jwt = hasEnvironmentOverride ? env.RAINBOND_JWT : stored?.token;
|
|
230
128
|
if (!baseUrl || !jwt) {
|
|
231
|
-
throw new BridgeError("
|
|
129
|
+
throw new BridgeError("no Rainbond runtime is configured", EXIT.CONFIG);
|
|
232
130
|
}
|
|
233
131
|
|
|
234
132
|
let parsed;
|
|
@@ -241,9 +139,9 @@ function loadConfig({
|
|
|
241
139
|
parsed.password || parsed.search || parsed.hash) {
|
|
242
140
|
throw new BridgeError("RAINBOND_URL must be a safe HTTP(S) URL", EXIT.CONFIG);
|
|
243
141
|
}
|
|
244
|
-
const allowInsecureHttp =
|
|
245
|
-
|
|
246
|
-
|
|
142
|
+
const allowInsecureHttp = hasEnvironmentOverride
|
|
143
|
+
? env.RAINBOND_ALLOW_INSECURE_HTTP === "true"
|
|
144
|
+
: stored.allow_insecure_http;
|
|
247
145
|
if (parsed.protocol === "http:" && !allowInsecureHttp) {
|
|
248
146
|
throw new BridgeError(
|
|
249
147
|
"RAINBOND_URL must use HTTPS; explicitly authorize insecure HTTP during installation",
|
|
@@ -262,101 +160,31 @@ function loadConfig({
|
|
|
262
160
|
return config;
|
|
263
161
|
}
|
|
264
162
|
|
|
265
|
-
function loadEnvironmentConfig({
|
|
266
|
-
homeDir = os.homedir(),
|
|
267
|
-
environmentId,
|
|
268
|
-
} = {}) {
|
|
269
|
-
const { createEnvironmentRegistry } = requireRuntimeModule("environment-registry.js");
|
|
270
|
-
const { createEnvironmentCredentialStore } = requireRuntimeModule("environment-credentials.js");
|
|
271
|
-
const registry = createEnvironmentRegistry({ home: homeDir });
|
|
272
|
-
const snapshot = registry.read();
|
|
273
|
-
const selectedId = environmentId || snapshot.default_environment_id;
|
|
274
|
-
if (!selectedId) {
|
|
275
|
-
throw new BridgeError("no default Rainbond environment is configured", EXIT.CONFIG);
|
|
276
|
-
}
|
|
277
|
-
const environment = snapshot.environments.find((entry) => entry.id === selectedId);
|
|
278
|
-
if (!environment || environment.connection_state !== "connected") {
|
|
279
|
-
throw new BridgeError("the selected Rainbond environment is unavailable", EXIT.CONFIG);
|
|
280
|
-
}
|
|
281
|
-
let credential;
|
|
282
|
-
try {
|
|
283
|
-
credential = createEnvironmentCredentialStore({ home: homeDir }).read({
|
|
284
|
-
environmentId: environment.id,
|
|
285
|
-
expectedOrigin: environment.console_origin,
|
|
286
|
-
});
|
|
287
|
-
} catch (_error) {
|
|
288
|
-
throw new BridgeError("the selected Rainbond environment credential is unavailable", EXIT.CONFIG);
|
|
289
|
-
}
|
|
290
|
-
const parsed = new URL(environment.console_origin);
|
|
291
|
-
return {
|
|
292
|
-
baseUrl: environment.console_origin,
|
|
293
|
-
jwt: credential.token,
|
|
294
|
-
environmentId: environment.id,
|
|
295
|
-
homeDir,
|
|
296
|
-
allowInsecureHttp: parsed.protocol === "http:",
|
|
297
|
-
isInsecureHttp: parsed.protocol === "http:",
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
|
|
301
163
|
function parseCommand(args) {
|
|
302
|
-
if (args
|
|
303
|
-
|
|
304
|
-
if (!Object.hasOwn(PLATFORM_QUERY_TO_RESOURCE, toolName || "")) {
|
|
305
|
-
throw new BridgeError("platform query tool is not allowed", EXIT.USAGE);
|
|
306
|
-
}
|
|
307
|
-
let environmentId;
|
|
308
|
-
let input;
|
|
309
|
-
for (let index = 2; index < args.length; index += 2) {
|
|
310
|
-
const option = args[index];
|
|
311
|
-
const value = args[index + 1];
|
|
312
|
-
if (!value || value.startsWith("--")) {
|
|
313
|
-
throw new BridgeError("platform query option requires a value", EXIT.USAGE);
|
|
314
|
-
}
|
|
315
|
-
if (option === "--environment-id" && !environmentId && OPERATION_ID_PATTERN.test(value)) {
|
|
316
|
-
environmentId = value;
|
|
317
|
-
} else if (option === "--input" && input === undefined && value === "-") {
|
|
318
|
-
input = value;
|
|
319
|
-
} else {
|
|
320
|
-
throw new BridgeError("invalid platform query command", EXIT.USAGE);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
if (input !== "-") throw new BridgeError("platform query requires --input -", EXIT.USAGE);
|
|
324
|
-
return { command: "query", toolName, input, environmentId };
|
|
164
|
+
if (args.includes("--operation-id") || args.includes("--environment-id")) {
|
|
165
|
+
throw new BridgeError("--operation-id and --environment-id are no longer supported", EXIT.USAGE);
|
|
325
166
|
}
|
|
326
|
-
const
|
|
327
|
-
if (
|
|
328
|
-
operationIndex < 0
|
|
329
|
-
|| !OPERATION_ID_PATTERN.test(args[operationIndex + 1] || "")
|
|
330
|
-
|| args.indexOf("--operation-id", operationIndex + 1) !== -1
|
|
331
|
-
) {
|
|
332
|
-
throw new BridgeError("every tools command requires --operation-id <uuid>", EXIT.USAGE);
|
|
333
|
-
}
|
|
334
|
-
const operationId = args[operationIndex + 1];
|
|
335
|
-
const operationArgs = [
|
|
336
|
-
...args.slice(0, operationIndex),
|
|
337
|
-
...args.slice(operationIndex + 2),
|
|
338
|
-
];
|
|
339
|
-
const skillIndex = operationArgs.indexOf("--skill-id");
|
|
167
|
+
const skillIndex = args.indexOf("--skill-id");
|
|
340
168
|
if (
|
|
341
169
|
skillIndex < 0
|
|
342
|
-
|| !SKILL_ID_PATTERN.test(
|
|
343
|
-
||
|
|
170
|
+
|| !SKILL_ID_PATTERN.test(args[skillIndex + 1] || "")
|
|
171
|
+
|| args.indexOf("--skill-id", skillIndex + 1) !== -1
|
|
344
172
|
) {
|
|
345
173
|
throw new BridgeError(
|
|
346
174
|
"every tools command requires --skill-id <active-skill-id>",
|
|
347
175
|
EXIT.USAGE
|
|
348
176
|
);
|
|
349
177
|
}
|
|
350
|
-
const skillId =
|
|
178
|
+
const skillId = args[skillIndex + 1];
|
|
351
179
|
const remaining = [
|
|
352
|
-
...
|
|
353
|
-
...
|
|
180
|
+
...args.slice(0, skillIndex),
|
|
181
|
+
...args.slice(skillIndex + 2),
|
|
354
182
|
];
|
|
355
183
|
const command = remaining[0];
|
|
356
|
-
const context = {
|
|
184
|
+
const context = { skillId };
|
|
357
185
|
if (
|
|
358
186
|
command === "context"
|
|
359
|
-
&& ["resolve"
|
|
187
|
+
&& remaining[1] === "resolve"
|
|
360
188
|
&& remaining.length === 4
|
|
361
189
|
&& remaining[2] === "--input"
|
|
362
190
|
&& remaining[3] === "-"
|
|
@@ -368,6 +196,18 @@ function parseCommand(args) {
|
|
|
368
196
|
...context,
|
|
369
197
|
};
|
|
370
198
|
}
|
|
199
|
+
if (
|
|
200
|
+
command === "query"
|
|
201
|
+
&& Object.hasOwn(PLATFORM_QUERY_TO_RESOURCE, remaining[1] || "")
|
|
202
|
+
&& remaining.length === 4
|
|
203
|
+
&& remaining[2] === "--input"
|
|
204
|
+
&& remaining[3] === "-"
|
|
205
|
+
) {
|
|
206
|
+
return { command, toolName: remaining[1], input: remaining[3], ...context };
|
|
207
|
+
}
|
|
208
|
+
if (command === "query") {
|
|
209
|
+
throw new BridgeError("platform query tool is not allowed", EXIT.USAGE);
|
|
210
|
+
}
|
|
371
211
|
if (command === "status" && remaining.length === 1) return { command, ...context };
|
|
372
212
|
if (command === "list") {
|
|
373
213
|
if (remaining.length === 1) return { command, ...context };
|
|
@@ -434,11 +274,7 @@ function platformQueryIntent(toolName, argumentsValue) {
|
|
|
434
274
|
}
|
|
435
275
|
intent.app_id = String(value);
|
|
436
276
|
}
|
|
437
|
-
|
|
438
|
-
return requireRuntimeModule("runtime-intents.js").validateIntent(intent);
|
|
439
|
-
} catch (_error) {
|
|
440
|
-
throw new BridgeError("platform query intent is invalid", EXIT.USAGE);
|
|
441
|
-
}
|
|
277
|
+
return intent;
|
|
442
278
|
}
|
|
443
279
|
|
|
444
280
|
async function resolvePlatformQueryArguments(toolName, argumentsValue, config) {
|
|
@@ -602,9 +438,6 @@ function skillManifestPath(config) {
|
|
|
602
438
|
}
|
|
603
439
|
|
|
604
440
|
function loadSkillBinding(config, skillId, rootSkillId) {
|
|
605
|
-
if (skillId !== config.requiredSkillId) {
|
|
606
|
-
throw new BridgeError("Skill does not match the protected runtime operation intent", EXIT.CONFIG);
|
|
607
|
-
}
|
|
608
441
|
const target = skillManifestPath(config);
|
|
609
442
|
let manifest;
|
|
610
443
|
try {
|
|
@@ -725,7 +558,6 @@ function prepareOperation(config, toolName, operationClass, argumentsValue, skil
|
|
|
725
558
|
tool_name: toolName,
|
|
726
559
|
operation_class: operationClass,
|
|
727
560
|
arguments_digest: argumentsDigest(argumentsValue),
|
|
728
|
-
runtime_operation_id: config.operationId,
|
|
729
561
|
skill_id: skillBinding.skillId,
|
|
730
562
|
root_skill_id: skillBinding.rootSkillId,
|
|
731
563
|
skill_package_version: skillBinding.packageVersion,
|
|
@@ -752,7 +584,6 @@ function confirmOperation(
|
|
|
752
584
|
if (!record || record.status !== "awaiting_confirmation" || record.tool_name !== toolName ||
|
|
753
585
|
record.operation_class !== operationClass ||
|
|
754
586
|
record.arguments_digest !== argumentsDigest(argumentsValue) ||
|
|
755
|
-
record.runtime_operation_id !== config.operationId ||
|
|
756
587
|
record.skill_id !== skillBinding.skillId ||
|
|
757
588
|
record.root_skill_id !== skillBinding.rootSkillId ||
|
|
758
589
|
record.skill_package_version !== skillBinding.packageVersion ||
|
|
@@ -1182,28 +1013,82 @@ async function validateToolArguments(config, toolName, argumentsValue) {
|
|
|
1182
1013
|
if (validationError) throw new BridgeError(validationError, EXIT.USAGE);
|
|
1183
1014
|
}
|
|
1184
1015
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1016
|
+
function boundedContextString(value) {
|
|
1017
|
+
return typeof value === "string"
|
|
1018
|
+
&& value.length > 0
|
|
1019
|
+
&& value.length <= 128
|
|
1020
|
+
&& !/[\u0000-\u001f\u007f-\u009f]/u.test(value)
|
|
1021
|
+
? value
|
|
1022
|
+
: null;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
async function resolveStatelessContext(input, config) {
|
|
1026
|
+
const required = input?.required;
|
|
1027
|
+
if (!Array.isArray(required)
|
|
1028
|
+
|| required.some((item) => !["enterprise", "workspace"].includes(item))) {
|
|
1029
|
+
throw new BridgeError("context required dimensions are invalid", EXIT.USAGE);
|
|
1030
|
+
}
|
|
1031
|
+
const identity = await execute({
|
|
1032
|
+
command: "read",
|
|
1033
|
+
toolName: "rainbond_get_current_user",
|
|
1034
|
+
argumentsValue: {},
|
|
1035
|
+
}, config);
|
|
1036
|
+
const enterpriseId = boundedContextString(identity?.enterprise_id);
|
|
1037
|
+
if (required.includes("enterprise") && !enterpriseId) {
|
|
1038
|
+
return { state: "blocked", reason: "no-current-enterprise" };
|
|
1039
|
+
}
|
|
1040
|
+
if (!required.includes("workspace")) {
|
|
1041
|
+
return { state: "resolved", context: { enterprise_id: enterpriseId } };
|
|
1042
|
+
}
|
|
1043
|
+
const teams = await execute({
|
|
1044
|
+
command: "read",
|
|
1045
|
+
toolName: "rainbond_query_teams",
|
|
1046
|
+
argumentsValue: enterpriseId ? { enterprise_id: enterpriseId } : {},
|
|
1047
|
+
}, config);
|
|
1048
|
+
const options = [];
|
|
1049
|
+
for (const item of Array.isArray(teams?.items) ? teams.items : []) {
|
|
1050
|
+
const teamId = boundedContextString(item?.team_id || item?.tenant_id);
|
|
1051
|
+
const teamName = boundedContextString(item?.team_name || item?.tenant_name);
|
|
1052
|
+
const teamAlias = boundedContextString(item?.team_alias || item?.tenant_alias);
|
|
1053
|
+
if (!teamId || !teamName || !Array.isArray(item.region_list)) continue;
|
|
1054
|
+
for (const region of item.region_list) {
|
|
1055
|
+
const regionName = boundedContextString(region?.region_name);
|
|
1056
|
+
if (!regionName) continue;
|
|
1057
|
+
const regionLabel = boundedContextString(region.region_alias) || regionName;
|
|
1058
|
+
const workspaceLabel = teamAlias && teamAlias !== teamName
|
|
1059
|
+
? `${teamAlias}(${teamName})`
|
|
1060
|
+
: teamName;
|
|
1061
|
+
options.push({
|
|
1062
|
+
id: `${teamId}:${regionName}`,
|
|
1063
|
+
label: `${workspaceLabel} / ${regionLabel}`,
|
|
1064
|
+
team_id: teamId,
|
|
1065
|
+
team_name: teamName,
|
|
1066
|
+
region_name: regionName,
|
|
1200
1067
|
});
|
|
1068
|
+
if (options.length > 256) {
|
|
1069
|
+
throw new BridgeError("workspace candidate set is too large", EXIT.TOOL);
|
|
1070
|
+
}
|
|
1201
1071
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1072
|
+
}
|
|
1073
|
+
if (options.length === 0) return { state: "blocked", reason: "no-accessible-workspace" };
|
|
1074
|
+
if (options.length === 1) {
|
|
1075
|
+
const option = options[0];
|
|
1076
|
+
return {
|
|
1077
|
+
state: "resolved",
|
|
1078
|
+
context: {
|
|
1079
|
+
enterprise_id: enterpriseId,
|
|
1080
|
+
team_id: option.team_id,
|
|
1081
|
+
team_name: option.team_name,
|
|
1082
|
+
region_name: option.region_name,
|
|
1083
|
+
},
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
return { state: "needs-selection", dimension: "workspace-region", options };
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
async function execute(command, config) {
|
|
1090
|
+
if (command.command === "context") {
|
|
1091
|
+
return resolveStatelessContext(command.argumentsValue, config);
|
|
1207
1092
|
}
|
|
1208
1093
|
if (command.command === "package-upload") {
|
|
1209
1094
|
return executePackageUpload(command, config);
|
|
@@ -1214,8 +1099,6 @@ async function execute(command, config) {
|
|
|
1214
1099
|
return {
|
|
1215
1100
|
status: "ok",
|
|
1216
1101
|
cli_version: CLI_VERSION,
|
|
1217
|
-
operation_id: config.operationId,
|
|
1218
|
-
environment_id: config.environmentId,
|
|
1219
1102
|
tool_count: tools.length,
|
|
1220
1103
|
catalog_age_ms: cached ? Math.max(0, Math.round(cached.age)) : 0,
|
|
1221
1104
|
};
|
|
@@ -1327,7 +1210,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1327
1210
|
argumentRedactions = collectArgumentRedactions(argumentsValue);
|
|
1328
1211
|
}
|
|
1329
1212
|
if (command.command === "query") {
|
|
1330
|
-
config =
|
|
1213
|
+
config = loadConfig({ includeRuntime: true });
|
|
1331
1214
|
command.argumentsValue = await resolvePlatformQueryArguments(
|
|
1332
1215
|
command.toolName,
|
|
1333
1216
|
command.argumentsValue,
|
|
@@ -1348,14 +1231,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1348
1231
|
}
|
|
1349
1232
|
config = loadConfig({
|
|
1350
1233
|
includeRuntime: true,
|
|
1351
|
-
operationId: command.operationId,
|
|
1352
1234
|
});
|
|
1353
|
-
if (command.skillId !== config.requiredSkillId) {
|
|
1354
|
-
throw new BridgeError(
|
|
1355
|
-
"Skill does not match the protected runtime operation intent",
|
|
1356
|
-
EXIT.CONFIG
|
|
1357
|
-
);
|
|
1358
|
-
}
|
|
1359
1235
|
if (config.isInsecureHttp) {
|
|
1360
1236
|
process.stderr.write('{"warning":"using insecure HTTP transport"}\n');
|
|
1361
1237
|
}
|
|
@@ -1382,10 +1258,8 @@ module.exports = {
|
|
|
1382
1258
|
loadConfig,
|
|
1383
1259
|
executePackageUpload,
|
|
1384
1260
|
packageUploadEnvironment,
|
|
1385
|
-
parseEnvFile,
|
|
1386
1261
|
parseCommand,
|
|
1387
1262
|
platformQueryIntent,
|
|
1388
|
-
loadEnvironmentConfig,
|
|
1389
1263
|
rpcRequest,
|
|
1390
1264
|
validateSchemaValue,
|
|
1391
1265
|
validateToolArguments,
|