opensteer 0.8.11 → 0.8.12

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/dist/cli/bin.js CHANGED
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { assertProviderSupportsEngine, createOpensteerSemanticRuntime, OpensteerBrowserManager, dispatchSemanticOperation, loadEnvironment, normalizeOpensteerProviderMode, discoverLocalCdpBrowsers, inspectCdpEndpoint, resolveOpensteerRuntimeConfig, resolveOpensteerEngineName, resolveOpensteerProvider, resolveFilesystemWorkspacePath, CloudSessionProxy, FlowRecorderCollector, generateReplayScript, pathExists, readPersistedLocalBrowserSessionRecord, readPersistedCloudSessionRecord, OpensteerCloudClient, isProcessRunning } from '../chunk-33FDEOQY.js';
3
- import process2 from 'process';
2
+ import { assertProviderSupportsEngine, createOpensteerSemanticRuntime, OpensteerBrowserManager, dispatchSemanticOperation, loadEnvironment, normalizeOpensteerProviderMode, discoverLocalCdpBrowsers, inspectCdpEndpoint, resolveOpensteerRuntimeConfig, resolveOpensteerEngineName, resolveOpensteerProvider, resolveFilesystemWorkspacePath, requireCloudAppBaseUrl, CloudSessionProxy, FlowRecorderCollector, generateReplayScript, pathExists, readPersistedLocalBrowserSessionRecord, readPersistedCloudSessionRecord, OpensteerCloudClient, isProcessRunning } from '../chunk-AXTKKAPW.js';
3
+ import process3 from 'process';
4
4
  import { spawn } from 'child_process';
5
5
  import { existsSync } from 'fs';
6
6
  import path from 'path';
7
7
  import { createRequire } from 'module';
8
8
  import { fileURLToPath } from 'url';
9
9
  import { mkdir, writeFile } from 'fs/promises';
10
+ import os from 'os';
10
11
 
11
12
  // package.json
12
13
  var package_default = {
@@ -16,6 +17,7 @@ var package_default = {
16
17
  async function loadCliEnvironment(cwd) {
17
18
  loadEnvironment(cwd);
18
19
  }
20
+ var OPENSTEER_GITHUB_SOURCE = "steerlabs/opensteer";
19
21
  function createOpensteerSkillsInvocation(input) {
20
22
  const cliArgs = ["add", input.skillSourcePath];
21
23
  if (input.options.all === true) {
@@ -56,7 +58,7 @@ function resolveOpensteerSkillsCliPath() {
56
58
  }
57
59
  return cliPath;
58
60
  }
59
- function resolveOpensteerSkillSourcePath() {
61
+ function resolveOpensteerLocalSkillSourcePath() {
60
62
  let ancestor = path.dirname(fileURLToPath(import.meta.url));
61
63
  for (let index = 0; index < 6; index += 1) {
62
64
  const candidate = path.join(ancestor, "skills");
@@ -68,17 +70,32 @@ function resolveOpensteerSkillSourcePath() {
68
70
  }
69
71
  throw new Error("Unable to find the packaged Opensteer skill source directory.");
70
72
  }
73
+ async function checkOpensteerGitHubReachable() {
74
+ try {
75
+ const response = await fetch(`https://github.com/${OPENSTEER_GITHUB_SOURCE}`, {
76
+ method: "HEAD",
77
+ signal: AbortSignal.timeout(3e3),
78
+ redirect: "manual"
79
+ });
80
+ return response.status < 500;
81
+ } catch {
82
+ return false;
83
+ }
84
+ }
71
85
  async function runOpensteerSkillsInstaller(options = {}, overrideDeps = {}) {
72
86
  const deps = {
73
87
  resolveSkillsCliPath: resolveOpensteerSkillsCliPath,
74
- resolveSkillSourcePath: resolveOpensteerSkillSourcePath,
88
+ resolveLocalSkillSourcePath: resolveOpensteerLocalSkillSourcePath,
89
+ checkGitHubReachable: checkOpensteerGitHubReachable,
75
90
  spawnInvocation: spawnOpensteerSkillsInvocation,
76
91
  ...overrideDeps
77
92
  };
93
+ const useGitHub = await deps.checkGitHubReachable();
94
+ const skillSourcePath = useGitHub ? OPENSTEER_GITHUB_SOURCE : deps.resolveLocalSkillSourcePath();
78
95
  const invocation = createOpensteerSkillsInvocation({
79
96
  options,
80
97
  skillsCliPath: deps.resolveSkillsCliPath(),
81
- skillSourcePath: deps.resolveSkillSourcePath()
98
+ skillSourcePath
82
99
  });
83
100
  return deps.spawnInvocation(invocation);
84
101
  }
@@ -263,6 +280,43 @@ function formatLaneRow(input) {
263
280
  const summary = input.summary.padEnd(16, " ");
264
281
  return `${input.marker} ${provider} ${status} ${summary}${input.detail ?? ""}`.trimEnd();
265
282
  }
283
+ async function openBrowserUrl(url) {
284
+ const command = resolveOpenBrowserCommand(url);
285
+ await new Promise((resolve, reject) => {
286
+ const child = spawn(command.executable, command.args, {
287
+ detached: process3.platform !== "win32",
288
+ stdio: "ignore"
289
+ });
290
+ child.once("error", reject);
291
+ child.once("spawn", () => {
292
+ child.unref();
293
+ resolve();
294
+ });
295
+ });
296
+ }
297
+ function resolveOpenBrowserCommand(url) {
298
+ if (process3.platform === "darwin") {
299
+ return {
300
+ executable: "open",
301
+ args: [url]
302
+ };
303
+ }
304
+ if (process3.platform === "win32" || isWsl()) {
305
+ return {
306
+ executable: process3.platform === "win32" ? "cmd" : "cmd.exe",
307
+ args: ["/c", "start", "", url]
308
+ };
309
+ }
310
+ return {
311
+ executable: "xdg-open",
312
+ args: [url]
313
+ };
314
+ }
315
+ function isWsl() {
316
+ return process3.platform === "linux" && (process3.env.WSL_DISTRO_NAME !== void 0 || os.release().toLowerCase().includes("microsoft"));
317
+ }
318
+
319
+ // src/cli/record.ts
266
320
  async function runOpensteerRecordCommand(input) {
267
321
  const stdout = input.stdout ?? process.stdout;
268
322
  const stderr = input.stderr ?? process.stderr;
@@ -316,6 +370,7 @@ async function runOpensteerRecordCommand(input) {
316
370
  async function runOpensteerCloudRecordCommand(input) {
317
371
  const stdout = input.stdout ?? process.stdout;
318
372
  const stderr = input.stderr ?? process.stderr;
373
+ const cloudAppBaseUrl = requireCloudAppBaseUrl(input.cloudConfig);
319
374
  const outputPath = resolveRecordOutputPath({
320
375
  rootDir: input.rootDir,
321
376
  workspace: input.workspace,
@@ -332,6 +387,7 @@ async function runOpensteerCloudRecordCommand(input) {
332
387
  });
333
388
  const client = input.client ?? resolveCloud();
334
389
  const sleep = input.sleep ?? delay;
390
+ const openUrl = input.openUrl ?? openBrowserUrl;
335
391
  let closed = false;
336
392
  try {
337
393
  await runtime.open({
@@ -341,8 +397,13 @@ async function runOpensteerCloudRecordCommand(input) {
341
397
  ...input.context === void 0 ? {} : { context: input.context }
342
398
  });
343
399
  const sessionId = await resolveCloudRecordingSessionId(runtime);
344
- const sessionUrl = buildCloudRecordingSessionUrl(input.cloudConfig, sessionId);
400
+ const sessionUrl = buildCloudRecordingSessionUrl(cloudAppBaseUrl, sessionId);
345
401
  await client.startSessionRecording(sessionId);
402
+ await tryOpenCloudRecordingSessionUrl({
403
+ sessionUrl,
404
+ stderr,
405
+ openUrl
406
+ });
346
407
  stderr.write(
347
408
  `Recording browser actions for workspace "${input.workspace}". Open ${sessionUrl} and click "Stop recording" in the browser session toolbar when you're done.
348
409
  `
@@ -406,14 +467,18 @@ function createRecorderRuntimeAdapter(runtime) {
406
467
  }
407
468
  };
408
469
  }
409
- function buildCloudRecordingSessionUrl(cloudConfig, sessionId) {
410
- const baseUrl = cloudConfig.appBaseUrl;
411
- if (!baseUrl || baseUrl.trim().length === 0) {
412
- throw new Error(
413
- 'record with provider=cloud requires OPENSTEER_CLOUD_APP_BASE_URL or "--cloud-app-base-url".'
470
+ function buildCloudRecordingSessionUrl(appBaseUrl, sessionId) {
471
+ return `${appBaseUrl}/browsers/${encodeURIComponent(sessionId)}`;
472
+ }
473
+ async function tryOpenCloudRecordingSessionUrl(input) {
474
+ try {
475
+ await input.openUrl(input.sessionUrl);
476
+ } catch {
477
+ input.stderr.write(
478
+ `Could not automatically open the cloud browser session. Open it manually: ${input.sessionUrl}
479
+ `
414
480
  );
415
481
  }
416
- return `${baseUrl.replace(/\/+$/, "")}/browsers/${encodeURIComponent(sessionId)}`;
417
482
  }
418
483
  async function resolveCloudRecordingSessionId(runtime) {
419
484
  const info = await runtime.info();
@@ -527,7 +592,7 @@ var OPERATION_ALIASES = /* @__PURE__ */ new Map([
527
592
  ["close", "session.close"]
528
593
  ]);
529
594
  async function main() {
530
- const argv = process2.argv.slice(2);
595
+ const argv = process3.argv.slice(2);
531
596
  const bootstrapAction = resolveCliBootstrapAction(argv);
532
597
  if (bootstrapAction === "version") {
533
598
  printVersion();
@@ -537,7 +602,7 @@ async function main() {
537
602
  printHelp();
538
603
  return;
539
604
  }
540
- await loadCliEnvironment(process2.cwd());
605
+ await loadCliEnvironment(process3.cwd());
541
606
  const parsed = parseCommandLine(argv);
542
607
  if (parsed.command[0] === "browser") {
543
608
  await handleBrowserCommand(parsed);
@@ -554,7 +619,7 @@ async function main() {
554
619
  list: parsed.options.list === true
555
620
  });
556
621
  if (exitCode !== 0) {
557
- process2.exitCode = exitCode;
622
+ process3.exitCode = exitCode;
558
623
  }
559
624
  return;
560
625
  }
@@ -585,19 +650,19 @@ async function main() {
585
650
  engine: engineName,
586
651
  runtimeOptions: {
587
652
  workspace: parsed.options.workspace,
588
- rootDir: process2.cwd(),
653
+ rootDir: process3.cwd(),
589
654
  browser: "persistent",
590
655
  ...parsed.options.launch === void 0 ? {} : { launch: parsed.options.launch },
591
656
  ...parsed.options.context === void 0 ? {} : { context: parsed.options.context }
592
657
  }
593
658
  });
594
659
  const result2 = await runtime2.close();
595
- process2.stdout.write(`${JSON.stringify(result2, null, 2)}
660
+ process3.stdout.write(`${JSON.stringify(result2, null, 2)}
596
661
  `);
597
662
  return;
598
663
  }
599
664
  const manager = new OpensteerBrowserManager({
600
- rootDir: process2.cwd(),
665
+ rootDir: process3.cwd(),
601
666
  workspace: parsed.options.workspace,
602
667
  engineName,
603
668
  browser: "persistent",
@@ -605,7 +670,7 @@ async function main() {
605
670
  ...parsed.options.context === void 0 ? {} : { context: parsed.options.context }
606
671
  });
607
672
  await manager.close();
608
- process2.stdout.write(`${JSON.stringify({ closed: true }, null, 2)}
673
+ process3.stdout.write(`${JSON.stringify({ closed: true }, null, 2)}
609
674
  `);
610
675
  return;
611
676
  }
@@ -614,7 +679,7 @@ async function main() {
614
679
  engine: engineName,
615
680
  runtimeOptions: {
616
681
  workspace: parsed.options.workspace,
617
- rootDir: process2.cwd(),
682
+ rootDir: process3.cwd(),
618
683
  ...parsed.options.browser === void 0 ? {} : { browser: parsed.options.browser },
619
684
  ...parsed.options.launch === void 0 ? {} : { launch: parsed.options.launch },
620
685
  ...parsed.options.context === void 0 ? {} : { context: parsed.options.context }
@@ -633,7 +698,7 @@ async function main() {
633
698
  } finally {
634
699
  await runtime.disconnect().catch(() => void 0);
635
700
  }
636
- process2.stdout.write(`${JSON.stringify(result, null, 2)}
701
+ process3.stdout.write(`${JSON.stringify(result, null, 2)}
637
702
  `);
638
703
  }
639
704
  async function handleBrowserCommand(parsed) {
@@ -642,7 +707,7 @@ async function handleBrowserCommand(parsed) {
642
707
  const result = await discoverLocalCdpBrowsers({
643
708
  ...parsed.options.launch?.timeoutMs === void 0 ? {} : { timeoutMs: parsed.options.launch.timeoutMs }
644
709
  });
645
- process2.stdout.write(`${JSON.stringify(result, null, 2)}
710
+ process3.stdout.write(`${JSON.stringify(result, null, 2)}
646
711
  `);
647
712
  return;
648
713
  }
@@ -658,7 +723,7 @@ async function handleBrowserCommand(parsed) {
658
723
  ...parsed.options.attachHeaders === void 0 ? {} : { headers: parsed.options.attachHeaders },
659
724
  ...parsed.options.launch?.timeoutMs === void 0 ? {} : { timeoutMs: parsed.options.launch.timeoutMs }
660
725
  });
661
- process2.stdout.write(`${JSON.stringify(result, null, 2)}
726
+ process3.stdout.write(`${JSON.stringify(result, null, 2)}
662
727
  `);
663
728
  return;
664
729
  }
@@ -667,7 +732,7 @@ async function handleBrowserCommand(parsed) {
667
732
  }
668
733
  const engineName = resolveCliEngineName(parsed);
669
734
  const manager = new OpensteerBrowserManager({
670
- rootDir: process2.cwd(),
735
+ rootDir: process3.cwd(),
671
736
  workspace: parsed.options.workspace,
672
737
  engineName,
673
738
  browser: "persistent",
@@ -677,7 +742,7 @@ async function handleBrowserCommand(parsed) {
677
742
  switch (subcommand) {
678
743
  case "status": {
679
744
  const result = await manager.status();
680
- process2.stdout.write(`${JSON.stringify(result, null, 2)}
745
+ process3.stdout.write(`${JSON.stringify(result, null, 2)}
681
746
  `);
682
747
  return;
683
748
  }
@@ -690,19 +755,19 @@ async function handleBrowserCommand(parsed) {
690
755
  sourceUserDataDir,
691
756
  ...parsed.options.sourceProfileDirectory === void 0 ? {} : { sourceProfileDirectory: parsed.options.sourceProfileDirectory }
692
757
  });
693
- process2.stdout.write(`${JSON.stringify(result, null, 2)}
758
+ process3.stdout.write(`${JSON.stringify(result, null, 2)}
694
759
  `);
695
760
  return;
696
761
  }
697
762
  case "reset": {
698
763
  await manager.reset();
699
- process2.stdout.write(`${JSON.stringify({ reset: true }, null, 2)}
764
+ process3.stdout.write(`${JSON.stringify({ reset: true }, null, 2)}
700
765
  `);
701
766
  return;
702
767
  }
703
768
  case "delete": {
704
769
  await manager.delete();
705
- process2.stdout.write(`${JSON.stringify({ deleted: true }, null, 2)}
770
+ process3.stdout.write(`${JSON.stringify({ deleted: true }, null, 2)}
706
771
  `);
707
772
  return;
708
773
  }
@@ -724,7 +789,7 @@ async function handleRecordCommandEntry(parsed) {
724
789
  if (engineName !== "playwright") {
725
790
  throw new Error("record requires engine=playwright.");
726
791
  }
727
- const rootDir = process2.cwd();
792
+ const rootDir = process3.cwd();
728
793
  const recordBrowser = parsed.options.browser;
729
794
  if (provider.mode === "cloud") {
730
795
  if (typeof recordBrowser === "object") {
@@ -733,7 +798,7 @@ async function handleRecordCommandEntry(parsed) {
733
798
  const runtimeProvider = buildCliRuntimeProvider(parsed, provider.mode);
734
799
  const runtimeConfig = resolveOpensteerRuntimeConfig({
735
800
  ...runtimeProvider === void 0 ? {} : { provider: runtimeProvider },
736
- environment: process2.env
801
+ environment: process3.env
737
802
  });
738
803
  await runOpensteerCloudRecordCommand({
739
804
  cloudConfig: runtimeConfig.cloud,
@@ -1113,14 +1178,14 @@ function buildCliExplicitProvider(parsed) {
1113
1178
  function resolveCliEngineName(parsed) {
1114
1179
  return resolveOpensteerEngineName({
1115
1180
  ...parsed.options.requestedEngineName === void 0 ? {} : { requested: parsed.options.requestedEngineName },
1116
- ...process2.env.OPENSTEER_ENGINE === void 0 ? {} : { environment: process2.env.OPENSTEER_ENGINE }
1181
+ ...process3.env.OPENSTEER_ENGINE === void 0 ? {} : { environment: process3.env.OPENSTEER_ENGINE }
1117
1182
  });
1118
1183
  }
1119
1184
  function resolveCliProvider(parsed) {
1120
1185
  const explicitProvider = buildCliExplicitProvider(parsed);
1121
1186
  return resolveOpensteerProvider({
1122
1187
  ...explicitProvider === void 0 ? {} : { provider: explicitProvider },
1123
- ...process2.env.OPENSTEER_PROVIDER === void 0 ? {} : { environmentProvider: process2.env.OPENSTEER_PROVIDER }
1188
+ ...process3.env.OPENSTEER_PROVIDER === void 0 ? {} : { environmentProvider: process3.env.OPENSTEER_PROVIDER }
1124
1189
  });
1125
1190
  }
1126
1191
  function buildCliRuntimeProvider(parsed, providerMode) {
@@ -1154,20 +1219,20 @@ async function handleStatusCommand(parsed) {
1154
1219
  const runtimeProvider = buildCliRuntimeProvider(parsed, provider.mode);
1155
1220
  const runtimeConfig = resolveOpensteerRuntimeConfig({
1156
1221
  ...runtimeProvider === void 0 ? {} : { provider: runtimeProvider },
1157
- environment: process2.env
1222
+ environment: process3.env
1158
1223
  });
1159
1224
  const status = await collectOpensteerStatus({
1160
- rootDir: process2.cwd(),
1225
+ rootDir: process3.cwd(),
1161
1226
  ...parsed.options.workspace === void 0 ? {} : { workspace: parsed.options.workspace },
1162
1227
  provider,
1163
1228
  ...runtimeConfig.cloud === void 0 ? {} : { cloudConfig: runtimeConfig.cloud }
1164
1229
  });
1165
1230
  if (parsed.options.json === true) {
1166
- process2.stdout.write(`${JSON.stringify(status, null, 2)}
1231
+ process3.stdout.write(`${JSON.stringify(status, null, 2)}
1167
1232
  `);
1168
1233
  return;
1169
1234
  }
1170
- process2.stdout.write(renderOpensteerStatus(status));
1235
+ process3.stdout.write(renderOpensteerStatus(status));
1171
1236
  }
1172
1237
  function parseKeyValueList(values) {
1173
1238
  if (values === void 0 || values.length === 0) {
@@ -1252,7 +1317,7 @@ function resolveCommandLength(tokens) {
1252
1317
  return Math.min(tokens.length, 1);
1253
1318
  }
1254
1319
  function printHelp() {
1255
- process2.stdout.write(`Opensteer v2 CLI
1320
+ process3.stdout.write(`Opensteer v2 CLI
1256
1321
 
1257
1322
  Usage:
1258
1323
  opensteer open <url> --workspace <id> [--browser persistent|temporary|attach]
@@ -1303,7 +1368,7 @@ Common options:
1303
1368
  `);
1304
1369
  }
1305
1370
  function printVersion() {
1306
- process2.stdout.write(`${package_default.version}
1371
+ process3.stdout.write(`${package_default.version}
1307
1372
  `);
1308
1373
  }
1309
1374
  main().catch((error) => {
@@ -1318,9 +1383,9 @@ main().catch((error) => {
1318
1383
  message: String(error)
1319
1384
  }
1320
1385
  };
1321
- process2.stderr.write(`${JSON.stringify(payload)}
1386
+ process3.stderr.write(`${JSON.stringify(payload)}
1322
1387
  `);
1323
- process2.exitCode = 1;
1388
+ process3.exitCode = 1;
1324
1389
  });
1325
1390
  //# sourceMappingURL=bin.js.map
1326
1391
  //# sourceMappingURL=bin.js.map