@optima-chat/browser-cli 0.8.0 → 0.9.1

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 (2) hide show
  1. package/dist/index.js +56 -53
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -186,14 +186,6 @@ var BrowserAPI = class {
186
186
  body: JSON.stringify(body)
187
187
  });
188
188
  }
189
- async listProfiles() {
190
- return request("/api/profiles");
191
- }
192
- async deleteProfile(profileId) {
193
- return request("/api/profiles/" + encodeURIComponent(profileId), {
194
- method: "DELETE"
195
- });
196
- }
197
189
  async setZiNiaoConfig(company, username, password) {
198
190
  return request("/api/user/ziniao-config", {
199
191
  method: "PUT",
@@ -265,7 +257,14 @@ var BrowserAPI = class {
265
257
  const deadline = Date.now() + timeoutMs;
266
258
  for (; ; ) {
267
259
  const task = await request(`/api/script-tasks/${started.id}`);
268
- if (task.status === "completed") return task.output;
260
+ if (task.status === "completed") {
261
+ if (!task.output) {
262
+ throw new Error(
263
+ `recipe ${name} reported completed but returned no output (task ${started.id})`
264
+ );
265
+ }
266
+ return task.output;
267
+ }
269
268
  if (task.status === "failed" || task.status === "needs_fallback") {
270
269
  throw new Error(task.error || task.output?.error || `recipe ${task.status}`);
271
270
  }
@@ -452,20 +451,6 @@ function formatError(err) {
452
451
  function formatTabsInline(tabs) {
453
452
  return tabs.map((t) => `[${t.tab_id}] ${t.title}`).join(", ");
454
453
  }
455
- function formatProfiles(result) {
456
- if (result.profiles.length === 0) {
457
- return "No browser profiles found.";
458
- }
459
- const lines = result.profiles.map((p) => {
460
- const sizeMb = (p.size_bytes / (1024 * 1024)).toFixed(1);
461
- return ` ${p.profile_id} (${sizeMb} MB)`;
462
- });
463
- return `Browser profiles:
464
- ${lines.join("\n")}`;
465
- }
466
- function formatProfileDelete(profileId) {
467
- return `Profile '${profileId}' deleted.`;
468
- }
469
454
 
470
455
  // src/commands/lifecycle.ts
471
456
  function registerLifecycleCommands(program2) {
@@ -688,15 +673,38 @@ function registerTabCommands(program2) {
688
673
  }
689
674
 
690
675
  // src/commands/script.ts
691
- import { readFileSync as readFileSync3 } from "fs";
676
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
677
+ import { basename, dirname, resolve } from "path";
692
678
  var POLL_INTERVAL_MS = 2e3;
693
679
  var POLL_TIMEOUT_MS = 18e4;
680
+ var REQUIRED_ARG_FLAG = {
681
+ ziniao_profile_id: "--ziniao-profile <id>",
682
+ bitbrowser_profile_id: "--bitbrowser-profile <id>"
683
+ };
684
+ function formatRequiredArgs(s) {
685
+ if (!s.required_args?.length) return null;
686
+ const flags = s.required_args.map((a) => REQUIRED_ARG_FLAG[a] ?? `--param ${a}=<value>`).join(" ");
687
+ return ` requires: ${flags}`;
688
+ }
689
+ async function deliverArtifact(task, out) {
690
+ const output = task.output;
691
+ if (!output) return null;
692
+ if (output.path) return output.path;
693
+ if (!output.artifact_path) return null;
694
+ const target = resolve(out ?? `./${basename(output.filename ?? "artifact")}`);
695
+ const content = await api.fetchArtifact(output.artifact_path);
696
+ mkdirSync2(dirname(target), { recursive: true });
697
+ writeFileSync3(target, content);
698
+ return target;
699
+ }
694
700
  function formatScriptList(scripts) {
695
701
  if (scripts.length === 0) return "No scripts registered.";
696
702
  const lines = [];
697
703
  for (const s of scripts) {
698
704
  const tag = s.source ? ` [${s.source}]` : "";
699
705
  lines.push(`${s.name} \u2014 ${s.description}${tag}`);
706
+ const requires = formatRequiredArgs(s);
707
+ if (requires) lines.push(requires);
700
708
  for (let i = 0; i < s.steps.length; i++) {
701
709
  lines.push(` [${i + 1}] ${s.steps[i].id} \u2014 ${s.steps[i].description}`);
702
710
  }
@@ -787,7 +795,7 @@ function registerScriptCommands(program2) {
787
795
  process.exit(1);
788
796
  }
789
797
  });
790
- program2.command("runscript").argument("<name>", "Script name").description("Run a script (polls until complete)").option("--param <params...>", "Parameters as key=value").option("--connector <type>", "Browser connector: chrome, ziniao, or bitbrowser").option("--ziniao-profile <id>", "ZiNiao browser profile ID (with --connector ziniao)").option("--bitbrowser-profile <id>", "BitBrowser profile ID (with --connector bitbrowser)").option("--no-poll", "Return immediately without polling").action(async (name, opts) => {
798
+ program2.command("runscript").argument("<name>", "Script name").description("Run a script (polls until complete)").option("--param <params...>", "Parameters as key=value").option("--connector <type>", "Browser connector: chrome, ziniao, or bitbrowser").option("--ziniao-profile <id>", "ZiNiao browser profile ID (with --connector ziniao)").option("--bitbrowser-profile <id>", "BitBrowser profile ID (with --connector bitbrowser)").option("--out <path>", "Where to write the script's exported file (default: ./<filename>)").option("--no-poll", "Return immediately without polling").action(async (name, opts) => {
791
799
  try {
792
800
  const params = {};
793
801
  if (opts.param) {
@@ -796,6 +804,7 @@ function registerScriptCommands(program2) {
796
804
  params[k] = rest.join("=");
797
805
  }
798
806
  }
807
+ if (opts.out) params.out_path = resolve(opts.out);
799
808
  clearSessionId();
800
809
  const task = await api.runScript(name, params, opts.connector, opts.ziniaoProfile, opts.bitbrowserProfile);
801
810
  console.log(`Script started (task: ${task.id})`);
@@ -818,6 +827,18 @@ function registerScriptCommands(program2) {
818
827
  saveSessionId(result.session_id);
819
828
  }
820
829
  console.log(formatScriptTask(result));
830
+ if (result.status === "completed") {
831
+ try {
832
+ const saved = await deliverArtifact(result, opts.out);
833
+ if (saved) console.log(`Saved -> ${saved}`);
834
+ } catch (err) {
835
+ const staged = result.output?.artifact_path;
836
+ console.error(`${formatError(err)}
837
+ Script completed; only saving the file failed.`);
838
+ if (staged) console.error(`The artifact is still at ${staged}.`);
839
+ process.exit(1);
840
+ }
841
+ }
821
842
  } catch (err) {
822
843
  console.error(formatError(err));
823
844
  process.exit(1);
@@ -834,29 +855,7 @@ function registerScriptCommands(program2) {
834
855
  });
835
856
  }
836
857
  function sleep(ms) {
837
- return new Promise((resolve2) => setTimeout(resolve2, ms));
838
- }
839
-
840
- // src/commands/profile.ts
841
- function registerProfileCommands(program2) {
842
- program2.command("profiles").description("List browser profiles").action(async () => {
843
- try {
844
- const result = await api.listProfiles();
845
- console.log(formatProfiles(result));
846
- } catch (err) {
847
- console.error(formatError(err));
848
- process.exit(1);
849
- }
850
- });
851
- program2.command("delete-profile").description("Delete a named browser profile").argument("<profile-id>", "Profile ID to delete").action(async (profileId) => {
852
- try {
853
- const result = await api.deleteProfile(profileId);
854
- console.log(formatProfileDelete(result.profile_id));
855
- } catch (err) {
856
- console.error(formatError(err));
857
- process.exit(1);
858
- }
859
- });
858
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
860
859
  }
861
860
 
862
861
  // src/ziniao-doctor.ts
@@ -1033,13 +1032,18 @@ function registerZiNiaoCommands(program2) {
1033
1032
  }
1034
1033
 
1035
1034
  // src/commands/recipes.ts
1036
- import { writeFileSync as writeFileSync3 } from "fs";
1037
- import { resolve } from "path";
1035
+ import { writeFileSync as writeFileSync4 } from "fs";
1036
+ import { resolve as resolve2 } from "path";
1038
1037
  async function runExport(script, params, out, timeoutMs) {
1039
- const outPath = resolve(out);
1038
+ const outPath = resolve2(out);
1040
1039
  const result = await api.runRecipeScript(script, { ...params, out_path: outPath }, 2e3, timeoutMs);
1041
1040
  if (!result.path) {
1042
- writeFileSync3(outPath, await api.fetchArtifact(result.artifact_path));
1041
+ if (!result.artifact_path) {
1042
+ throw new Error(
1043
+ `Script ${script} finished but delivered no file \u2014 no workspace path and no staged artifact. Nothing was written to ${outPath}.`
1044
+ );
1045
+ }
1046
+ writeFileSync4(outPath, await api.fetchArtifact(result.artifact_path));
1043
1047
  }
1044
1048
  console.log(`Saved ${result.filename} -> ${outPath} (${result.size} bytes)`);
1045
1049
  }
@@ -1111,7 +1115,6 @@ registerInteractionCommands(program);
1111
1115
  registerInfoCommands(program);
1112
1116
  registerTabCommands(program);
1113
1117
  registerScriptCommands(program);
1114
- registerProfileCommands(program);
1115
1118
  registerZiNiaoCommands(program);
1116
1119
  registerRecipeCommands(program);
1117
1120
  registerBitBrowserCommands(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optima-chat/browser-cli",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {