opensteer 0.6.0 → 0.6.2
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 +16 -1
- package/README.md +63 -0
- package/bin/opensteer.mjs +214 -3
- package/dist/browser-profile-client-CaL-mwqs.d.ts +168 -0
- package/dist/browser-profile-client-DK9qa_Dj.d.cts +168 -0
- package/dist/chunk-7RMY26CM.js +1130 -0
- package/dist/{chunk-SGZYTGY3.js → chunk-F2VDVOJO.js} +1890 -1520
- package/dist/chunk-WDRMHPWL.js +1320 -0
- package/dist/chunk-WJI7TGBQ.js +77 -0
- package/dist/cli/auth.cjs +1834 -0
- package/dist/cli/auth.d.cts +114 -0
- package/dist/cli/auth.d.ts +114 -0
- package/dist/cli/auth.js +15 -0
- package/dist/cli/profile.cjs +16222 -0
- package/dist/cli/profile.d.cts +79 -0
- package/dist/cli/profile.d.ts +79 -0
- package/dist/cli/profile.js +866 -0
- package/dist/cli/server.cjs +1816 -422
- package/dist/cli/server.js +310 -10
- package/dist/index.cjs +1772 -414
- package/dist/index.d.cts +141 -395
- package/dist/index.d.ts +141 -395
- package/dist/index.js +203 -8
- package/dist/types-BxiRblC7.d.cts +327 -0
- package/dist/types-BxiRblC7.d.ts +327 -0
- package/package.json +3 -2
- package/skills/opensteer/SKILL.md +34 -5
- package/skills/opensteer/references/cli-reference.md +10 -8
- package/skills/opensteer/references/sdk-reference.md +14 -3
package/dist/cli/server.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Opensteer
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
Opensteer
|
|
3
|
+
} from "../chunk-F2VDVOJO.js";
|
|
4
|
+
import {
|
|
5
|
+
normalizeError,
|
|
6
|
+
resolveCloudSelection,
|
|
7
|
+
resolveConfigWithEnv
|
|
8
|
+
} from "../chunk-WDRMHPWL.js";
|
|
5
9
|
import "../chunk-3H5RRIMZ.js";
|
|
6
10
|
|
|
7
11
|
// src/cli/server.ts
|
|
@@ -57,6 +61,21 @@ var commands = {
|
|
|
57
61
|
async state(opensteer) {
|
|
58
62
|
return await opensteer.state();
|
|
59
63
|
},
|
|
64
|
+
async cursor(opensteer, args) {
|
|
65
|
+
const mode = typeof args.mode === "string" ? args.mode : "status";
|
|
66
|
+
if (mode === "on") {
|
|
67
|
+
opensteer.setCursorEnabled(true);
|
|
68
|
+
} else if (mode === "off") {
|
|
69
|
+
opensteer.setCursorEnabled(false);
|
|
70
|
+
} else if (mode !== "status") {
|
|
71
|
+
throw new Error(
|
|
72
|
+
`Invalid cursor mode "${String(mode)}". Use "on", "off", or "status".`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
cursor: opensteer.getCursorState()
|
|
77
|
+
};
|
|
78
|
+
},
|
|
60
79
|
async screenshot(opensteer, args) {
|
|
61
80
|
const file = args.file || "screenshot.png";
|
|
62
81
|
const type = file.endsWith(".jpg") || file.endsWith(".jpeg") ? "jpeg" : "png";
|
|
@@ -256,10 +275,175 @@ function getCommandHandler(name) {
|
|
|
256
275
|
return commands[name];
|
|
257
276
|
}
|
|
258
277
|
|
|
278
|
+
// src/cli/cloud-profile-binding.ts
|
|
279
|
+
function normalizeCloudProfileBinding(value) {
|
|
280
|
+
if (!value) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
const profileId = typeof value.profileId === "string" ? value.profileId.trim() : "";
|
|
284
|
+
if (!profileId) {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
profileId,
|
|
289
|
+
reuseIfActive: typeof value.reuseIfActive === "boolean" ? value.reuseIfActive : void 0
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
function resolveConfiguredCloudProfileBinding(config) {
|
|
293
|
+
if (!isCloudConfigured(config)) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
return normalizeCloudProfileBinding(config.cloud.browserProfile);
|
|
297
|
+
}
|
|
298
|
+
function resolveSessionCloudProfileBinding(config, requested) {
|
|
299
|
+
if (!isCloudConfigured(config)) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
return requested ?? resolveConfiguredCloudProfileBinding(config);
|
|
303
|
+
}
|
|
304
|
+
function assertCompatibleCloudProfileBinding(sessionId, active, requested) {
|
|
305
|
+
if (!requested) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (!active) {
|
|
309
|
+
throw new Error(
|
|
310
|
+
[
|
|
311
|
+
`Session '${sessionId}' is already running without a bound cloud browser profile.`,
|
|
312
|
+
"Cloud browser profile selection only applies when the session is first opened.",
|
|
313
|
+
"Close this session or use a different --session to target another profile."
|
|
314
|
+
].join(" ")
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
if (active.profileId === requested.profileId && active.reuseIfActive === requested.reuseIfActive) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
throw new Error(
|
|
321
|
+
[
|
|
322
|
+
`Session '${sessionId}' is already bound to cloud browser profile ${formatCloudProfileBinding(active)}.`,
|
|
323
|
+
`Requested ${formatCloudProfileBinding(requested)} does not match.`,
|
|
324
|
+
"Use the same cloud profile for this session, or start a different --session."
|
|
325
|
+
].join(" ")
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
function formatCloudProfileBinding(binding) {
|
|
329
|
+
if (binding.reuseIfActive === void 0) {
|
|
330
|
+
return `'${binding.profileId}'`;
|
|
331
|
+
}
|
|
332
|
+
return `'${binding.profileId}' (reuseIfActive=${String(
|
|
333
|
+
binding.reuseIfActive
|
|
334
|
+
)})`;
|
|
335
|
+
}
|
|
336
|
+
function isCloudConfigured(config) {
|
|
337
|
+
return Boolean(
|
|
338
|
+
config.cloud && typeof config.cloud === "object" && !Array.isArray(config.cloud)
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// src/cli/open-cloud-auth.ts
|
|
343
|
+
function normalizeCliOpenCloudAuth(value) {
|
|
344
|
+
if (value == null) {
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
348
|
+
throw new Error("Invalid open request cloud auth payload.");
|
|
349
|
+
}
|
|
350
|
+
const record = value;
|
|
351
|
+
const apiKey = normalizeNonEmptyString(record.apiKey);
|
|
352
|
+
const accessToken = normalizeNonEmptyString(record.accessToken);
|
|
353
|
+
const baseUrl = normalizeNonEmptyString(record.baseUrl);
|
|
354
|
+
const authScheme = normalizeAuthScheme(record.authScheme);
|
|
355
|
+
if (!baseUrl) {
|
|
356
|
+
throw new Error("Open request cloud auth payload is missing baseUrl.");
|
|
357
|
+
}
|
|
358
|
+
if ((apiKey ? 1 : 0) + (accessToken ? 1 : 0) !== 1) {
|
|
359
|
+
throw new Error(
|
|
360
|
+
"Open request cloud auth payload must include exactly one credential."
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
if (accessToken && authScheme !== "bearer") {
|
|
364
|
+
throw new Error(
|
|
365
|
+
'Open request cloud auth payload must use authScheme "bearer" with accessToken.'
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
...apiKey ? { apiKey } : {},
|
|
370
|
+
...accessToken ? { accessToken } : {},
|
|
371
|
+
baseUrl,
|
|
372
|
+
authScheme
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function buildServerOpenConfig(options) {
|
|
376
|
+
const config = {
|
|
377
|
+
name: options.name,
|
|
378
|
+
storage: {
|
|
379
|
+
rootDir: options.scopeDir
|
|
380
|
+
},
|
|
381
|
+
cursor: {
|
|
382
|
+
enabled: options.cursorEnabled
|
|
383
|
+
},
|
|
384
|
+
browser: {
|
|
385
|
+
headless: options.headless ?? false,
|
|
386
|
+
connectUrl: options.connectUrl,
|
|
387
|
+
channel: options.channel,
|
|
388
|
+
profileDir: options.profileDir
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
if (!options.cloudAuth) {
|
|
392
|
+
return config;
|
|
393
|
+
}
|
|
394
|
+
const resolved = resolveConfigWithEnv(
|
|
395
|
+
{
|
|
396
|
+
storage: {
|
|
397
|
+
rootDir: options.scopeDir
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
env: options.env
|
|
402
|
+
}
|
|
403
|
+
);
|
|
404
|
+
const cloudSelection = resolveCloudSelection(
|
|
405
|
+
{
|
|
406
|
+
cloud: resolved.config.cloud
|
|
407
|
+
},
|
|
408
|
+
resolved.env
|
|
409
|
+
);
|
|
410
|
+
if (!cloudSelection.cloud) {
|
|
411
|
+
return config;
|
|
412
|
+
}
|
|
413
|
+
config.cloud = toOpensteerCloudOptions(options.cloudAuth);
|
|
414
|
+
return config;
|
|
415
|
+
}
|
|
416
|
+
function toOpensteerCloudOptions(auth) {
|
|
417
|
+
return {
|
|
418
|
+
...auth.apiKey ? { apiKey: auth.apiKey } : {},
|
|
419
|
+
...auth.accessToken ? { accessToken: auth.accessToken } : {},
|
|
420
|
+
baseUrl: auth.baseUrl,
|
|
421
|
+
authScheme: auth.authScheme
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
function normalizeNonEmptyString(value) {
|
|
425
|
+
if (typeof value !== "string") {
|
|
426
|
+
return void 0;
|
|
427
|
+
}
|
|
428
|
+
const trimmed = value.trim();
|
|
429
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
430
|
+
}
|
|
431
|
+
function normalizeAuthScheme(value) {
|
|
432
|
+
if (value === "api-key" || value === "bearer") {
|
|
433
|
+
return value;
|
|
434
|
+
}
|
|
435
|
+
throw new Error(
|
|
436
|
+
'Open request cloud auth payload must use authScheme "api-key" or "bearer".'
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
259
440
|
// src/cli/server.ts
|
|
260
441
|
var instance = null;
|
|
261
442
|
var launchPromise = null;
|
|
262
443
|
var selectorNamespace = null;
|
|
444
|
+
var cloudProfileBinding = null;
|
|
445
|
+
var cloudAuthOverride = null;
|
|
446
|
+
var cursorEnabledPreference = readCursorPreferenceFromEnv();
|
|
263
447
|
var requestQueue = Promise.resolve();
|
|
264
448
|
var shuttingDown = false;
|
|
265
449
|
function sanitizeNamespace(value) {
|
|
@@ -277,6 +461,36 @@ function invalidateInstance() {
|
|
|
277
461
|
instance.close().catch(() => {
|
|
278
462
|
});
|
|
279
463
|
instance = null;
|
|
464
|
+
cloudProfileBinding = null;
|
|
465
|
+
}
|
|
466
|
+
function normalizeCursorFlag(value) {
|
|
467
|
+
if (value === void 0 || value === null) {
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
if (typeof value === "boolean") {
|
|
471
|
+
return value;
|
|
472
|
+
}
|
|
473
|
+
if (typeof value === "number") {
|
|
474
|
+
if (value === 1) return true;
|
|
475
|
+
if (value === 0) return false;
|
|
476
|
+
}
|
|
477
|
+
throw new Error(
|
|
478
|
+
'--cursor must be a boolean value ("true" or "false").'
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
function readCursorPreferenceFromEnv() {
|
|
482
|
+
const value = process.env.OPENSTEER_CURSOR;
|
|
483
|
+
if (typeof value !== "string") {
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
const normalized = value.trim().toLowerCase();
|
|
487
|
+
if (normalized === "true" || normalized === "1") {
|
|
488
|
+
return true;
|
|
489
|
+
}
|
|
490
|
+
if (normalized === "false" || normalized === "0") {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
return null;
|
|
280
494
|
}
|
|
281
495
|
function attachLifecycleListeners(inst) {
|
|
282
496
|
try {
|
|
@@ -386,7 +600,26 @@ async function handleRequest(request, socket) {
|
|
|
386
600
|
const connectUrl = args["connect-url"];
|
|
387
601
|
const channel = args.channel;
|
|
388
602
|
const profileDir = args["profile-dir"];
|
|
603
|
+
const cloudProfileId = typeof args["cloud-profile-id"] === "string" ? args["cloud-profile-id"].trim() : void 0;
|
|
604
|
+
const cloudProfileReuseIfActive = typeof args["cloud-profile-reuse-if-active"] === "boolean" ? args["cloud-profile-reuse-if-active"] : void 0;
|
|
605
|
+
const requestedCloudProfileBinding = normalizeCloudProfileBinding({
|
|
606
|
+
profileId: cloudProfileId,
|
|
607
|
+
reuseIfActive: cloudProfileReuseIfActive
|
|
608
|
+
});
|
|
609
|
+
const requestedCloudAuth = normalizeCliOpenCloudAuth(
|
|
610
|
+
args["cloud-auth"]
|
|
611
|
+
);
|
|
612
|
+
if (cloudProfileReuseIfActive !== void 0 && !cloudProfileId) {
|
|
613
|
+
throw new Error(
|
|
614
|
+
"--cloud-profile-reuse-if-active requires --cloud-profile-id."
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
const requestedCursor = normalizeCursorFlag(args.cursor);
|
|
389
618
|
const requestedName = typeof args.name === "string" && args.name.trim().length > 0 ? sanitizeNamespace(args.name) : null;
|
|
619
|
+
if (requestedCursor !== null) {
|
|
620
|
+
cursorEnabledPreference = requestedCursor;
|
|
621
|
+
}
|
|
622
|
+
const effectiveCursorEnabled = cursorEnabledPreference !== null ? cursorEnabledPreference : true;
|
|
390
623
|
if (selectorNamespace && requestedName && requestedName !== selectorNamespace) {
|
|
391
624
|
sendResponse(socket, {
|
|
392
625
|
id,
|
|
@@ -410,6 +643,9 @@ async function handleRequest(request, socket) {
|
|
|
410
643
|
selectorNamespace = requestedName ?? logicalSession;
|
|
411
644
|
}
|
|
412
645
|
const activeNamespace = selectorNamespace ?? logicalSession;
|
|
646
|
+
if (requestedCloudAuth) {
|
|
647
|
+
cloudAuthOverride = requestedCloudAuth;
|
|
648
|
+
}
|
|
413
649
|
if (instance && !launchPromise) {
|
|
414
650
|
try {
|
|
415
651
|
if (instance.page.isClosed()) {
|
|
@@ -419,31 +655,59 @@ async function handleRequest(request, socket) {
|
|
|
419
655
|
invalidateInstance();
|
|
420
656
|
}
|
|
421
657
|
}
|
|
658
|
+
if (instance && !launchPromise) {
|
|
659
|
+
assertCompatibleCloudProfileBinding(
|
|
660
|
+
logicalSession,
|
|
661
|
+
cloudProfileBinding,
|
|
662
|
+
requestedCloudProfileBinding
|
|
663
|
+
);
|
|
664
|
+
}
|
|
422
665
|
if (!instance) {
|
|
423
|
-
instance = new Opensteer(
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
666
|
+
instance = new Opensteer(
|
|
667
|
+
buildServerOpenConfig({
|
|
668
|
+
scopeDir,
|
|
669
|
+
name: activeNamespace,
|
|
670
|
+
cursorEnabled: effectiveCursorEnabled,
|
|
671
|
+
headless,
|
|
427
672
|
connectUrl,
|
|
428
673
|
channel,
|
|
429
|
-
profileDir
|
|
430
|
-
|
|
431
|
-
|
|
674
|
+
profileDir,
|
|
675
|
+
cloudAuth: cloudAuthOverride
|
|
676
|
+
})
|
|
677
|
+
);
|
|
678
|
+
const nextCloudProfileBinding = resolveSessionCloudProfileBinding(
|
|
679
|
+
instance.getConfig(),
|
|
680
|
+
requestedCloudProfileBinding
|
|
681
|
+
);
|
|
682
|
+
if (requestedCloudProfileBinding && !nextCloudProfileBinding) {
|
|
683
|
+
instance = null;
|
|
684
|
+
throw new Error(
|
|
685
|
+
"--cloud-profile-id can only be used when cloud mode is enabled for this session."
|
|
686
|
+
);
|
|
687
|
+
}
|
|
432
688
|
launchPromise = instance.launch({
|
|
433
689
|
headless: headless ?? false,
|
|
690
|
+
cloudBrowserProfile: cloudProfileId ? {
|
|
691
|
+
profileId: cloudProfileId,
|
|
692
|
+
reuseIfActive: cloudProfileReuseIfActive
|
|
693
|
+
} : void 0,
|
|
434
694
|
timeout: connectUrl ? 12e4 : 3e4
|
|
435
695
|
});
|
|
436
696
|
try {
|
|
437
697
|
await launchPromise;
|
|
438
698
|
attachLifecycleListeners(instance);
|
|
699
|
+
cloudProfileBinding = nextCloudProfileBinding;
|
|
439
700
|
} catch (err) {
|
|
440
701
|
instance = null;
|
|
702
|
+
cloudProfileBinding = null;
|
|
441
703
|
throw err;
|
|
442
704
|
} finally {
|
|
443
705
|
launchPromise = null;
|
|
444
706
|
}
|
|
445
707
|
} else if (launchPromise) {
|
|
446
708
|
await launchPromise;
|
|
709
|
+
} else if (requestedCursor !== null) {
|
|
710
|
+
instance.setCursorEnabled(requestedCursor);
|
|
447
711
|
}
|
|
448
712
|
if (url) {
|
|
449
713
|
await instance.goto(url);
|
|
@@ -458,6 +722,7 @@ async function handleRequest(request, socket) {
|
|
|
458
722
|
runtimeSession: session,
|
|
459
723
|
scopeDir,
|
|
460
724
|
name: activeNamespace,
|
|
725
|
+
cursor: instance.getCursorState(),
|
|
461
726
|
cloudSessionId: instance.getCloudSessionId() ?? void 0,
|
|
462
727
|
cloudSessionUrl: instance.getCloudSessionUrl() ?? void 0
|
|
463
728
|
}
|
|
@@ -470,6 +735,41 @@ async function handleRequest(request, socket) {
|
|
|
470
735
|
}
|
|
471
736
|
return;
|
|
472
737
|
}
|
|
738
|
+
if (command === "cursor") {
|
|
739
|
+
try {
|
|
740
|
+
const mode = typeof args.mode === "string" ? args.mode : "status";
|
|
741
|
+
if (mode === "on") {
|
|
742
|
+
cursorEnabledPreference = true;
|
|
743
|
+
instance?.setCursorEnabled(true);
|
|
744
|
+
} else if (mode === "off") {
|
|
745
|
+
cursorEnabledPreference = false;
|
|
746
|
+
instance?.setCursorEnabled(false);
|
|
747
|
+
} else if (mode !== "status") {
|
|
748
|
+
throw new Error(
|
|
749
|
+
`Invalid cursor mode "${mode}". Use "on", "off", or "status".`
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
const defaultEnabled = cursorEnabledPreference !== null ? cursorEnabledPreference : true;
|
|
753
|
+
const cursor = instance ? instance.getCursorState() : {
|
|
754
|
+
enabled: defaultEnabled,
|
|
755
|
+
active: false,
|
|
756
|
+
reason: "session_not_open"
|
|
757
|
+
};
|
|
758
|
+
sendResponse(socket, {
|
|
759
|
+
id,
|
|
760
|
+
ok: true,
|
|
761
|
+
result: {
|
|
762
|
+
cursor
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
} catch (err) {
|
|
766
|
+
sendResponse(
|
|
767
|
+
socket,
|
|
768
|
+
buildErrorResponse(id, err, "Failed to update cursor mode.")
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
473
773
|
if (command === "close") {
|
|
474
774
|
try {
|
|
475
775
|
if (instance) {
|