opensteer 0.6.3 → 0.6.4

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.
Files changed (33) hide show
  1. package/bin/opensteer.mjs +94 -8
  2. package/dist/{browser-profile-client-DK9qa_Dj.d.cts → browser-profile-client-D6PuRefA.d.cts} +1 -1
  3. package/dist/{browser-profile-client-CaL-mwqs.d.ts → browser-profile-client-OUHaODro.d.ts} +1 -1
  4. package/dist/{chunk-SCNX4NN3.js → chunk-54KNQTOL.js} +141 -2
  5. package/dist/{chunk-FTKWQ6X3.js → chunk-6B6LOYU3.js} +1 -1
  6. package/dist/{chunk-3OMXCBPD.js → chunk-G6V2DJRN.js} +442 -591
  7. package/dist/chunk-K5CL76MG.js +81 -0
  8. package/dist/{chunk-KE35RQOJ.js → chunk-KPPOTU3D.js} +53 -144
  9. package/dist/cli/auth.cjs +53 -6
  10. package/dist/cli/auth.d.cts +1 -1
  11. package/dist/cli/auth.d.ts +1 -1
  12. package/dist/cli/auth.js +2 -2
  13. package/dist/cli/local-profile.cjs +197 -0
  14. package/dist/cli/local-profile.d.cts +18 -0
  15. package/dist/cli/local-profile.d.ts +18 -0
  16. package/dist/cli/local-profile.js +97 -0
  17. package/dist/cli/profile.cjs +2844 -2412
  18. package/dist/cli/profile.d.cts +2 -2
  19. package/dist/cli/profile.d.ts +2 -2
  20. package/dist/cli/profile.js +469 -7
  21. package/dist/cli/server.cjs +649 -204
  22. package/dist/cli/server.js +69 -16
  23. package/dist/index.cjs +578 -185
  24. package/dist/index.d.cts +7 -5
  25. package/dist/index.d.ts +7 -5
  26. package/dist/index.js +4 -3
  27. package/dist/{types-BxiRblC7.d.cts → types-BWItZPl_.d.cts} +31 -13
  28. package/dist/{types-BxiRblC7.d.ts → types-BWItZPl_.d.ts} +31 -13
  29. package/package.json +2 -2
  30. package/skills/opensteer/SKILL.md +34 -14
  31. package/skills/opensteer/references/cli-reference.md +1 -1
  32. package/skills/opensteer/references/examples.md +5 -3
  33. package/skills/opensteer/references/sdk-reference.md +16 -14
package/bin/opensteer.mjs CHANGED
@@ -27,6 +27,13 @@ const SKILLS_INSTALLER_SCRIPT = join(
27
27
  'skills-installer.js'
28
28
  )
29
29
  const PROFILE_CLI_SCRIPT = join(__dirname, '..', 'dist', 'cli', 'profile.js')
30
+ const LOCAL_PROFILE_CLI_SCRIPT = join(
31
+ __dirname,
32
+ '..',
33
+ 'dist',
34
+ 'cli',
35
+ 'local-profile.js'
36
+ )
30
37
  const AUTH_CLI_SCRIPT = join(__dirname, '..', 'dist', 'cli', 'auth.js')
31
38
  const SKILLS_HELP_TEXT = `Usage: opensteer skills <install|add> [options]
32
39
 
@@ -60,6 +67,15 @@ Commands:
60
67
 
61
68
  Run "opensteer profile --help" after building for full command details.
62
69
  `
70
+ const LOCAL_PROFILE_HELP_TEXT = `Usage: opensteer local-profile <command> [options]
71
+
72
+ Inspect local Chrome profiles for real-browser mode.
73
+
74
+ Commands:
75
+ list
76
+
77
+ Run "opensteer local-profile --help" after building for full command details.
78
+ `
63
79
  const AUTH_HELP_TEXT = `Usage: opensteer auth <command> [options]
64
80
 
65
81
  Authenticate Opensteer CLI with Opensteer Cloud.
@@ -87,6 +103,7 @@ const CLOSE_ALL_REQUEST = { id: 1, command: 'close', args: {} }
87
103
  const PING_REQUEST = { id: 1, command: 'ping', args: {} }
88
104
  const SESSION_ID_PATTERN = /^[a-zA-Z0-9_-]+$/
89
105
  const RUNTIME_SESSION_PREFIX = 'sc-'
106
+ const BOOLEAN_FLAGS = new Set(['all', 'headless', 'headed', 'json'])
90
107
 
91
108
  function getVersion() {
92
109
  try {
@@ -118,7 +135,14 @@ function parseArgs(argv) {
118
135
  if (arg.startsWith('--')) {
119
136
  const key = arg.slice(2)
120
137
  const next = args[i + 1]
121
- if (next !== undefined && !next.startsWith('--')) {
138
+ if (
139
+ BOOLEAN_FLAGS.has(key) &&
140
+ next !== undefined &&
141
+ next !== 'true' &&
142
+ next !== 'false'
143
+ ) {
144
+ flags[key] = true
145
+ } else if (next !== undefined && !next.startsWith('--')) {
122
146
  flags[key] = parseValue(next)
123
147
  i++
124
148
  } else {
@@ -334,9 +358,11 @@ function buildRequest(command, flags, positional) {
334
358
  for (const key of [
335
359
  'headless',
336
360
  'json',
337
- 'connect-url',
338
- 'channel',
339
- 'profile-dir',
361
+ 'browser',
362
+ 'profile',
363
+ 'cdp-url',
364
+ 'user-data-dir',
365
+ 'browser-path',
340
366
  'cloud-profile-id',
341
367
  'cloud-profile-reuse-if-active',
342
368
  'cursor',
@@ -348,6 +374,11 @@ function buildRequest(command, flags, positional) {
348
374
  }
349
375
 
350
376
  const args = { ...globalFlags, ...flags }
377
+ if ('headed' in flags) {
378
+ const headed = flags.headed === false ? false : Boolean(flags.headed)
379
+ args.headless = args.headless ?? !headed
380
+ delete args.headed
381
+ }
351
382
 
352
383
  switch (command) {
353
384
  case 'open':
@@ -975,6 +1006,30 @@ async function runProfileSubcommand(args) {
975
1006
  }
976
1007
  }
977
1008
 
1009
+ async function runLocalProfileSubcommand(args) {
1010
+ if (
1011
+ args.length === 0 ||
1012
+ args.includes('--help') ||
1013
+ args.includes('-h')
1014
+ ) {
1015
+ process.stdout.write(LOCAL_PROFILE_HELP_TEXT)
1016
+ return
1017
+ }
1018
+
1019
+ if (!existsSync(LOCAL_PROFILE_CLI_SCRIPT)) {
1020
+ throw new Error(
1021
+ `Local profile CLI module was not found at "${LOCAL_PROFILE_CLI_SCRIPT}". Run "npm run build" to generate dist artifacts.`
1022
+ )
1023
+ }
1024
+
1025
+ const moduleUrl = pathToFileURL(LOCAL_PROFILE_CLI_SCRIPT).href
1026
+ const { runOpensteerLocalProfileCli } = await import(moduleUrl)
1027
+ const exitCode = await runOpensteerLocalProfileCli(args)
1028
+ if (exitCode !== 0) {
1029
+ process.exit(exitCode)
1030
+ }
1031
+ }
1032
+
978
1033
  async function runAuthSubcommand(args) {
979
1034
  if (isAuthHelpRequest(args)) {
980
1035
  process.stdout.write(AUTH_HELP_TEXT)
@@ -1119,6 +1174,7 @@ Skills:
1119
1174
  skills add [options] Alias for "skills install"
1120
1175
  skills --help Show skills installer help
1121
1176
  profile <command> Manage cloud browser profiles and cookie sync
1177
+ local-profile <command> Inspect local Chrome profiles for real-browser mode
1122
1178
  auth <command> Manage cloud login credentials (login/status/logout)
1123
1179
  login Alias for "auth login"
1124
1180
  logout Alias for "auth logout"
@@ -1126,10 +1182,13 @@ Skills:
1126
1182
  Global Flags:
1127
1183
  --session <id> Logical session id (scoped by canonical cwd)
1128
1184
  --name <namespace> Selector namespace for cache storage on 'open'
1129
- --headless Launch browser in headless mode
1130
- --connect-url <url> Connect to a running browser (e.g. http://localhost:9222)
1131
- --channel <browser> Use installed browser (chrome, chrome-beta, msedge)
1132
- --profile-dir <path> Browser profile directory for logged-in sessions
1185
+ --headless Launch chromium mode in headless mode
1186
+ --browser <mode> Browser mode: chromium or real
1187
+ --profile <name> Browser profile directory name for real-browser mode
1188
+ --headed Launch real-browser mode with a visible window
1189
+ --cdp-url <url> Connect to a running browser (e.g. http://localhost:9222)
1190
+ --user-data-dir <path> Browser user-data root for real-browser mode
1191
+ --browser-path <path> Override Chrome executable path for real-browser mode
1133
1192
  --cloud-profile-id <id> Launch cloud session with a specific browser profile
1134
1193
  --cloud-profile-reuse-if-active <true|false>
1135
1194
  Reuse active cloud session for that browser profile
@@ -1151,6 +1210,10 @@ Environment:
1151
1210
  OPENSTEER_BASE_URL Override cloud control-plane base URL
1152
1211
  OPENSTEER_AUTH_SCHEME Cloud auth scheme: api-key (default) or bearer
1153
1212
  OPENSTEER_REMOTE_ANNOUNCE Cloud session announcement policy: always (default), off, tty
1213
+ OPENSTEER_BROWSER Local browser mode: chromium or real
1214
+ OPENSTEER_CDP_URL Connect to a running browser (e.g. http://localhost:9222)
1215
+ OPENSTEER_USER_DATA_DIR Browser user-data root for real-browser mode
1216
+ OPENSTEER_PROFILE_DIRECTORY Browser profile directory for real-browser mode
1154
1217
  `)
1155
1218
  }
1156
1219
 
@@ -1211,11 +1274,34 @@ async function main() {
1211
1274
  }
1212
1275
  return
1213
1276
  }
1277
+ if (rawArgs[0] === 'local-profile') {
1278
+ try {
1279
+ await runLocalProfileSubcommand(rawArgs.slice(1))
1280
+ } catch (err) {
1281
+ const message =
1282
+ err instanceof Error
1283
+ ? err.message
1284
+ : 'Failed to run local-profile command'
1285
+ process.stderr.write(`${message}\n`)
1286
+ process.exit(1)
1287
+ }
1288
+ return
1289
+ }
1214
1290
 
1215
1291
  const scopeDir = resolveScopeDir()
1216
1292
 
1217
1293
  const { command, flags, positional } = parseArgs(process.argv)
1218
1294
 
1295
+ if (
1296
+ flags['connect-url'] !== undefined ||
1297
+ flags.channel !== undefined ||
1298
+ flags['profile-dir'] !== undefined
1299
+ ) {
1300
+ error(
1301
+ '--connect-url, --channel, and --profile-dir are no longer supported. Use --cdp-url, --browser real, --profile, --user-data-dir, and --browser-path instead.'
1302
+ )
1303
+ }
1304
+
1219
1305
  if (command === 'sessions') {
1220
1306
  output({ ok: true, sessions: listSessions() })
1221
1307
  return
@@ -1,4 +1,4 @@
1
- import { O as OpensteerAuthScheme } from './types-BxiRblC7.cjs';
1
+ import { O as OpensteerAuthScheme } from './types-BWItZPl_.cjs';
2
2
 
3
3
  type ActionFailureCode = 'TARGET_NOT_FOUND' | 'TARGET_UNAVAILABLE' | 'TARGET_STALE' | 'TARGET_AMBIGUOUS' | 'BLOCKED_BY_INTERCEPTOR' | 'NOT_VISIBLE' | 'NOT_ENABLED' | 'NOT_EDITABLE' | 'INVALID_TARGET' | 'INVALID_OPTIONS' | 'ACTION_TIMEOUT' | 'UNKNOWN';
4
4
  type ActionFailureClassificationSource = 'typed_error' | 'playwright_call_log' | 'dom_probe' | 'message_heuristic' | 'unknown';
@@ -1,4 +1,4 @@
1
- import { O as OpensteerAuthScheme } from './types-BxiRblC7.js';
1
+ import { O as OpensteerAuthScheme } from './types-BWItZPl_.js';
2
2
 
3
3
  type ActionFailureCode = 'TARGET_NOT_FOUND' | 'TARGET_UNAVAILABLE' | 'TARGET_STALE' | 'TARGET_AMBIGUOUS' | 'BLOCKED_BY_INTERCEPTOR' | 'NOT_VISIBLE' | 'NOT_ENABLED' | 'NOT_EDITABLE' | 'INVALID_TARGET' | 'INVALID_OPTIONS' | 'ACTION_TIMEOUT' | 'UNKNOWN';
4
4
  type ActionFailureClassificationSource = 'typed_error' | 'playwright_call_log' | 'dom_probe' | 'message_heuristic' | 'unknown';
@@ -1,12 +1,11 @@
1
1
  import {
2
2
  DEFAULT_CLOUD_BASE_URL,
3
- createKeychainStore,
4
3
  normalizeCloudBaseUrl,
5
4
  resolveCloudSelection,
6
5
  resolveConfigWithEnv,
7
6
  selectCloudCredential,
8
7
  stripTrailingSlashes
9
- } from "./chunk-KE35RQOJ.js";
8
+ } from "./chunk-KPPOTU3D.js";
10
9
 
11
10
  // src/cli/auth.ts
12
11
  import open from "open";
@@ -80,6 +79,145 @@ import { createHash } from "crypto";
80
79
  import fs from "fs";
81
80
  import os from "os";
82
81
  import path from "path";
82
+
83
+ // src/auth/keychain-store.ts
84
+ import { spawnSync } from "child_process";
85
+ function commandExists(command) {
86
+ const result = spawnSync(command, ["--help"], {
87
+ encoding: "utf8",
88
+ stdio: "ignore"
89
+ });
90
+ return result.error == null;
91
+ }
92
+ function commandFailed(result) {
93
+ return typeof result.status === "number" && result.status !== 0;
94
+ }
95
+ function sanitizeCommandArgs(command, args) {
96
+ if (command !== "security") {
97
+ return args;
98
+ }
99
+ const sanitized = [];
100
+ for (let index = 0; index < args.length; index += 1) {
101
+ const value = args[index];
102
+ sanitized.push(value);
103
+ if (value === "-w" && index + 1 < args.length) {
104
+ sanitized.push("[REDACTED]");
105
+ index += 1;
106
+ }
107
+ }
108
+ return sanitized;
109
+ }
110
+ function buildCommandError(command, args, result) {
111
+ const stderr = typeof result.stderr === "string" && result.stderr.trim() ? result.stderr.trim() : `Command "${command}" failed with status ${String(result.status)}.`;
112
+ const sanitizedArgs = sanitizeCommandArgs(command, args);
113
+ return new Error(
114
+ [
115
+ `Unable to persist credential via ${command}.`,
116
+ `${command} ${sanitizedArgs.join(" ")}`,
117
+ stderr
118
+ ].join(" ")
119
+ );
120
+ }
121
+ function createMacosSecurityStore() {
122
+ return {
123
+ backend: "macos-security",
124
+ get(service, account) {
125
+ const result = spawnSync(
126
+ "security",
127
+ ["find-generic-password", "-s", service, "-a", account, "-w"],
128
+ { encoding: "utf8" }
129
+ );
130
+ if (commandFailed(result)) {
131
+ return null;
132
+ }
133
+ const secret = result.stdout.trim();
134
+ return secret.length ? secret : null;
135
+ },
136
+ set(service, account, secret) {
137
+ const args = [
138
+ "add-generic-password",
139
+ "-U",
140
+ "-s",
141
+ service,
142
+ "-a",
143
+ account,
144
+ "-w",
145
+ secret
146
+ ];
147
+ const result = spawnSync("security", args, { encoding: "utf8" });
148
+ if (commandFailed(result)) {
149
+ throw buildCommandError("security", args, result);
150
+ }
151
+ },
152
+ delete(service, account) {
153
+ const args = ["delete-generic-password", "-s", service, "-a", account];
154
+ const result = spawnSync("security", args, { encoding: "utf8" });
155
+ if (commandFailed(result)) {
156
+ return;
157
+ }
158
+ }
159
+ };
160
+ }
161
+ function createLinuxSecretToolStore() {
162
+ return {
163
+ backend: "linux-secret-tool",
164
+ get(service, account) {
165
+ const result = spawnSync(
166
+ "secret-tool",
167
+ ["lookup", "service", service, "account", account],
168
+ {
169
+ encoding: "utf8"
170
+ }
171
+ );
172
+ if (commandFailed(result)) {
173
+ return null;
174
+ }
175
+ const secret = result.stdout.trim();
176
+ return secret.length ? secret : null;
177
+ },
178
+ set(service, account, secret) {
179
+ const args = [
180
+ "store",
181
+ "--label",
182
+ "Opensteer CLI",
183
+ "service",
184
+ service,
185
+ "account",
186
+ account
187
+ ];
188
+ const result = spawnSync("secret-tool", args, {
189
+ encoding: "utf8",
190
+ input: secret
191
+ });
192
+ if (commandFailed(result)) {
193
+ throw buildCommandError("secret-tool", args, result);
194
+ }
195
+ },
196
+ delete(service, account) {
197
+ const args = ["clear", "service", service, "account", account];
198
+ spawnSync("secret-tool", args, {
199
+ encoding: "utf8"
200
+ });
201
+ }
202
+ };
203
+ }
204
+ function createKeychainStore() {
205
+ if (process.platform === "darwin") {
206
+ if (!commandExists("security")) {
207
+ return null;
208
+ }
209
+ return createMacosSecurityStore();
210
+ }
211
+ if (process.platform === "linux") {
212
+ if (!commandExists("secret-tool")) {
213
+ return null;
214
+ }
215
+ return createLinuxSecretToolStore();
216
+ }
217
+ return null;
218
+ }
219
+
220
+ // src/auth/machine-credential-store.ts
83
221
  var METADATA_VERSION = 2;
84
222
  var ACTIVE_TARGET_VERSION = 2;
85
223
  var KEYCHAIN_SERVICE = "com.opensteer.cli.cloud";
@@ -1100,6 +1238,7 @@ async function runOpensteerAuthCli(rawArgs, overrideDeps = {}) {
1100
1238
  }
1101
1239
 
1102
1240
  export {
1241
+ createKeychainStore,
1103
1242
  parseOpensteerAuthArgs,
1104
1243
  isCloudModeEnabledForRootDir,
1105
1244
  ensureCloudCredentialsForOpenCommand,
@@ -2,7 +2,7 @@ import {
2
2
  cloudAuthHeaders,
3
3
  normalizeCloudBaseUrl,
4
4
  parseCloudHttpError
5
- } from "./chunk-KE35RQOJ.js";
5
+ } from "./chunk-KPPOTU3D.js";
6
6
 
7
7
  // src/cloud/browser-profile-client.ts
8
8
  var BrowserProfileClient = class {