@docyrus/docyrus 0.0.20 → 0.0.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.
Files changed (65) hide show
  1. package/agent-loader.js +32 -1
  2. package/agent-loader.js.map +2 -2
  3. package/main.js +321 -70
  4. package/main.js.map +4 -4
  5. package/package.json +12 -2
  6. package/resources/chrome-tools/browser-content.js +103 -0
  7. package/resources/chrome-tools/browser-cookies.js +35 -0
  8. package/resources/chrome-tools/browser-eval.js +53 -0
  9. package/resources/chrome-tools/browser-hn-scraper.js +108 -0
  10. package/resources/chrome-tools/browser-nav.js +44 -0
  11. package/resources/chrome-tools/browser-pick.js +162 -0
  12. package/resources/chrome-tools/browser-screenshot.js +34 -0
  13. package/resources/chrome-tools/browser-start.js +86 -0
  14. package/resources/pi-agent/extensions/answer.ts +532 -0
  15. package/resources/pi-agent/extensions/context.ts +578 -0
  16. package/resources/pi-agent/extensions/control.ts +1779 -0
  17. package/resources/pi-agent/extensions/diff.ts +218 -0
  18. package/resources/pi-agent/extensions/files.ts +199 -0
  19. package/resources/pi-agent/extensions/loop.ts +446 -0
  20. package/resources/pi-agent/extensions/multi-edit.ts +835 -0
  21. package/resources/pi-agent/extensions/notify.ts +88 -0
  22. package/resources/pi-agent/extensions/pi-mcp-adapter/CHANGELOG.md +192 -0
  23. package/resources/pi-agent/extensions/pi-mcp-adapter/LICENSE +21 -0
  24. package/resources/pi-agent/extensions/pi-mcp-adapter/README.md +296 -0
  25. package/resources/pi-agent/extensions/pi-mcp-adapter/app-bridge.bundle.js +67 -0
  26. package/resources/pi-agent/extensions/pi-mcp-adapter/cli.js +108 -0
  27. package/resources/pi-agent/extensions/pi-mcp-adapter/commands.ts +211 -0
  28. package/resources/pi-agent/extensions/pi-mcp-adapter/config.ts +227 -0
  29. package/resources/pi-agent/extensions/pi-mcp-adapter/consent-manager.ts +64 -0
  30. package/resources/pi-agent/extensions/pi-mcp-adapter/direct-tools.ts +301 -0
  31. package/resources/pi-agent/extensions/pi-mcp-adapter/errors.ts +219 -0
  32. package/resources/pi-agent/extensions/pi-mcp-adapter/glimpse-ui.ts +80 -0
  33. package/resources/pi-agent/extensions/pi-mcp-adapter/host-html-template.ts +427 -0
  34. package/resources/pi-agent/extensions/pi-mcp-adapter/index.ts +232 -0
  35. package/resources/pi-agent/extensions/pi-mcp-adapter/init.ts +319 -0
  36. package/resources/pi-agent/extensions/pi-mcp-adapter/lifecycle.ts +93 -0
  37. package/resources/pi-agent/extensions/pi-mcp-adapter/logger.ts +169 -0
  38. package/resources/pi-agent/extensions/pi-mcp-adapter/mcp-panel.ts +713 -0
  39. package/resources/pi-agent/extensions/pi-mcp-adapter/metadata-cache.ts +191 -0
  40. package/resources/pi-agent/extensions/pi-mcp-adapter/npx-resolver.ts +419 -0
  41. package/resources/pi-agent/extensions/pi-mcp-adapter/oauth-handler.ts +56 -0
  42. package/resources/pi-agent/extensions/pi-mcp-adapter/package.json +85 -0
  43. package/resources/pi-agent/extensions/pi-mcp-adapter/paths.ts +29 -0
  44. package/resources/pi-agent/extensions/pi-mcp-adapter/proxy-modes.ts +635 -0
  45. package/resources/pi-agent/extensions/pi-mcp-adapter/resource-tools.ts +17 -0
  46. package/resources/pi-agent/extensions/pi-mcp-adapter/server-manager.ts +330 -0
  47. package/resources/pi-agent/extensions/pi-mcp-adapter/state.ts +41 -0
  48. package/resources/pi-agent/extensions/pi-mcp-adapter/tool-metadata.ts +144 -0
  49. package/resources/pi-agent/extensions/pi-mcp-adapter/tool-registrar.ts +46 -0
  50. package/resources/pi-agent/extensions/pi-mcp-adapter/types.ts +367 -0
  51. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-resource-handler.ts +145 -0
  52. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-server.ts +623 -0
  53. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-session.ts +384 -0
  54. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-stream-types.ts +89 -0
  55. package/resources/pi-agent/extensions/pi-mcp-adapter/utils.ts +75 -0
  56. package/resources/pi-agent/extensions/prompt-editor.ts +1315 -0
  57. package/resources/pi-agent/extensions/prompt-url-widget.ts +158 -0
  58. package/resources/pi-agent/extensions/redraws.ts +24 -0
  59. package/resources/pi-agent/extensions/review.ts +2160 -0
  60. package/resources/pi-agent/extensions/todos.ts +2076 -0
  61. package/resources/pi-agent/extensions/tps.ts +47 -0
  62. package/resources/pi-agent/extensions/whimsical.ts +474 -0
  63. package/resources/pi-agent/skills/changelog-generator/SKILL.md +425 -0
  64. package/resources/pi-agent/skills/docyrus-chrome-devtools-cli/SKILL.md +80 -0
  65. package/resources/pi-agent/skills/docyrus-platform/references/docyrus-cli-usage.md +51 -0
package/main.js CHANGED
@@ -18851,7 +18851,7 @@ var require_core3 = __commonJS({
18851
18851
  return match && match.index === 0;
18852
18852
  }
18853
18853
  var BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
18854
- function join6(regexps, separator = "|") {
18854
+ function join7(regexps, separator = "|") {
18855
18855
  let numCaptures = 0;
18856
18856
  return regexps.map((regex) => {
18857
18857
  numCaptures += 1;
@@ -19155,7 +19155,7 @@ var require_core3 = __commonJS({
19155
19155
  this.exec = () => null;
19156
19156
  }
19157
19157
  const terminators = this.regexes.map((el) => el[1]);
19158
- this.matcherRe = langRe(join6(terminators), true);
19158
+ this.matcherRe = langRe(join7(terminators), true);
19159
19159
  this.lastIndex = 0;
19160
19160
  }
19161
19161
  /** @param {string} s */
@@ -124678,7 +124678,7 @@ function buildInputSchema(args, env2, options2) {
124678
124678
  // package.json
124679
124679
  var package_default = {
124680
124680
  name: "@docyrus/docyrus",
124681
- version: "0.0.20",
124681
+ version: "0.0.21",
124682
124682
  private: false,
124683
124683
  description: "Docyrus API CLI",
124684
124684
  main: "./main.js",
@@ -124686,17 +124686,27 @@ var package_default = {
124686
124686
  docyrus: "main.js"
124687
124687
  },
124688
124688
  dependencies: {
124689
+ "@mozilla/readability": "^0.6.0",
124689
124690
  "@clack/prompts": "^0.11.0",
124691
+ "@modelcontextprotocol/ext-apps": "^1.2.2",
124692
+ "@modelcontextprotocol/sdk": "^1.25.1",
124690
124693
  "@mariozechner/pi-ai": "0.61.0",
124691
124694
  "@mariozechner/pi-coding-agent": "0.61.0",
124692
124695
  "@opentui/core": "^0.1.85",
124693
124696
  "@opentui/react": "^0.1.85",
124697
+ cheerio: "^1.1.2",
124698
+ diff: "^8.0.2",
124694
124699
  incur: "^0.1.6",
124700
+ jsdom: "^27.0.1",
124695
124701
  marked: "^15.0.12",
124696
124702
  "marked-terminal": "^7.3.0",
124697
124703
  picocolors: "^1.1.1",
124704
+ "puppeteer-core": "^24.31.0",
124698
124705
  react: "^19.1.1",
124699
- undici: "^7.16.0"
124706
+ turndown: "^7.2.2",
124707
+ "turndown-plugin-gfm": "^1.0.2",
124708
+ undici: "^7.16.0",
124709
+ zod: "^4.3.6"
124700
124710
  },
124701
124711
  devDependencies: {
124702
124712
  "@types/react": "^19.1.13"
@@ -125688,9 +125698,244 @@ function createAuthCli(dependencies) {
125688
125698
  return authCli;
125689
125699
  }
125690
125700
 
125701
+ // src/commands/chromeCommands.ts
125702
+ var import_node_child_process2 = require("node:child_process");
125703
+ var import_node_fs3 = require("node:fs");
125704
+ var import_node_path4 = require("node:path");
125705
+ function summarizeFailure(result) {
125706
+ const stderr = result.stderr?.toString().trim();
125707
+ if (stderr && stderr.length > 0) {
125708
+ return stderr;
125709
+ }
125710
+ if (typeof result.status === "number") {
125711
+ return `Chrome tool exited with code ${result.status}.`;
125712
+ }
125713
+ if (result.signal) {
125714
+ return `Chrome tool exited due to signal ${result.signal}.`;
125715
+ }
125716
+ return "Chrome tool terminated unexpectedly.";
125717
+ }
125718
+ function resolveChromeToolsResourceRoot(options2 = {}) {
125719
+ const cwd = options2.cwd ?? process.cwd();
125720
+ const dirname6 = options2.dirname ?? __dirname;
125721
+ const fileExists = options2.existsSyncFn ?? import_node_fs3.existsSync;
125722
+ const candidates = options2.candidatePaths ?? [
125723
+ (0, import_node_path4.resolve)(cwd, "apps/api-cli/resources/chrome-tools"),
125724
+ (0, import_node_path4.resolve)(dirname6, "../resources/chrome-tools"),
125725
+ (0, import_node_path4.resolve)(dirname6, "resources/chrome-tools"),
125726
+ (0, import_node_path4.resolve)(cwd, "dist/apps/api-cli/resources/chrome-tools")
125727
+ ];
125728
+ const resolved = candidates.find((candidate) => fileExists(candidate));
125729
+ if (!resolved) {
125730
+ throw new UserInputError(`Unable to locate chrome tool resources. Checked: ${candidates.join(", ")}`);
125731
+ }
125732
+ return resolved;
125733
+ }
125734
+ function resolveChromeToolScriptPath(params) {
125735
+ const scriptPath = (0, import_node_path4.join)(params.resourceRoot, params.scriptName);
125736
+ if (!(0, import_node_fs3.existsSync)(scriptPath)) {
125737
+ throw new UserInputError(`Missing chrome tool script: ${scriptPath}`);
125738
+ }
125739
+ return scriptPath;
125740
+ }
125741
+ function parseTextOutput(rawOutput) {
125742
+ return rawOutput.trimEnd();
125743
+ }
125744
+ function parseJsonOutput(rawOutput) {
125745
+ const trimmedOutput = rawOutput.trim();
125746
+ if (!trimmedOutput) {
125747
+ return [];
125748
+ }
125749
+ try {
125750
+ return JSON.parse(trimmedOutput);
125751
+ } catch (error48) {
125752
+ throw new UserInputError("Chrome tool returned invalid JSON output.", {
125753
+ cause: error48,
125754
+ rawOutput: trimmedOutput
125755
+ });
125756
+ }
125757
+ }
125758
+ function executeChromeTool(params) {
125759
+ const resolveResourceRoot = params.resolveChromeToolsResourceRootFn ?? resolveChromeToolsResourceRoot;
125760
+ const resourceRoot = resolveResourceRoot({
125761
+ cwd: params.cwd
125762
+ });
125763
+ const scriptPath = resolveChromeToolScriptPath({
125764
+ resourceRoot,
125765
+ scriptName: params.scriptName
125766
+ });
125767
+ const spawnCommand = params.spawnSyncFn ?? import_node_child_process2.spawnSync;
125768
+ const processExecPath = params.processExecPath ?? process.execPath;
125769
+ const result = spawnCommand(processExecPath, [scriptPath, ...params.args], {
125770
+ encoding: "utf8",
125771
+ cwd: params.cwd ?? process.cwd(),
125772
+ env: {
125773
+ ...process.env
125774
+ }
125775
+ });
125776
+ if (result.error) {
125777
+ throw new UserInputError(`Unable to start chrome tool '${params.scriptName}': ${result.error.message}`, {
125778
+ cause: result.error
125779
+ });
125780
+ }
125781
+ if (result.status !== 0) {
125782
+ throw new UserInputError(`Chrome tool '${params.scriptName}' failed: ${summarizeFailure(result)}`);
125783
+ }
125784
+ const stdout = result.stdout?.toString() || "";
125785
+ if (params.outputMode === "json") {
125786
+ return parseJsonOutput(stdout);
125787
+ }
125788
+ return parseTextOutput(stdout);
125789
+ }
125790
+ function createChromeCli(options2 = {}) {
125791
+ const chromeCli = Cli_exports.create("chrome", {
125792
+ description: "Chrome DevTools browser automation commands",
125793
+ env: EnvSchema
125794
+ });
125795
+ chromeCli.command("start", {
125796
+ description: "Launch Chrome with remote debugging on :9222",
125797
+ options: external_exports.object({
125798
+ profile: external_exports.boolean().optional().describe("Copy your default Chrome profile (cookies, logins)")
125799
+ }),
125800
+ run: async (context) => {
125801
+ return executeChromeTool({
125802
+ scriptName: "browser-start.js",
125803
+ args: context.options.profile ? ["--profile"] : [],
125804
+ cwd: options2.cwd,
125805
+ processExecPath: options2.processExecPath,
125806
+ spawnSyncFn: options2.spawnSyncFn,
125807
+ resolveChromeToolsResourceRootFn: options2.resolveChromeToolsResourceRootFn
125808
+ });
125809
+ }
125810
+ });
125811
+ chromeCli.command("nav", {
125812
+ description: "Navigate the current Chrome tab or open a URL in a new tab",
125813
+ args: external_exports.object({
125814
+ url: external_exports.string().min(1)
125815
+ }),
125816
+ options: external_exports.object({
125817
+ new: external_exports.boolean().optional().describe("Open the URL in a new tab"),
125818
+ reload: external_exports.boolean().optional().describe("Force a reload after navigation")
125819
+ }),
125820
+ run: async (context) => {
125821
+ const args = [context.args.url];
125822
+ if (context.options.new) {
125823
+ args.push("--new");
125824
+ }
125825
+ if (context.options.reload) {
125826
+ args.push("--reload");
125827
+ }
125828
+ return executeChromeTool({
125829
+ scriptName: "browser-nav.js",
125830
+ args,
125831
+ cwd: options2.cwd,
125832
+ processExecPath: options2.processExecPath,
125833
+ spawnSyncFn: options2.spawnSyncFn,
125834
+ resolveChromeToolsResourceRootFn: options2.resolveChromeToolsResourceRootFn
125835
+ });
125836
+ }
125837
+ });
125838
+ chromeCli.command("eval", {
125839
+ description: "Evaluate JavaScript in the active Chrome tab",
125840
+ args: external_exports.object({
125841
+ code: external_exports.string().min(1)
125842
+ }),
125843
+ run: async (context) => {
125844
+ return executeChromeTool({
125845
+ scriptName: "browser-eval.js",
125846
+ args: [context.args.code],
125847
+ cwd: options2.cwd,
125848
+ processExecPath: options2.processExecPath,
125849
+ spawnSyncFn: options2.spawnSyncFn,
125850
+ resolveChromeToolsResourceRootFn: options2.resolveChromeToolsResourceRootFn
125851
+ });
125852
+ }
125853
+ });
125854
+ chromeCli.command("screenshot", {
125855
+ description: "Capture a screenshot of the active Chrome tab",
125856
+ run: async () => {
125857
+ return executeChromeTool({
125858
+ scriptName: "browser-screenshot.js",
125859
+ args: [],
125860
+ cwd: options2.cwd,
125861
+ processExecPath: options2.processExecPath,
125862
+ spawnSyncFn: options2.spawnSyncFn,
125863
+ resolveChromeToolsResourceRootFn: options2.resolveChromeToolsResourceRootFn
125864
+ });
125865
+ }
125866
+ });
125867
+ chromeCli.command("pick", {
125868
+ description: "Interactively pick DOM elements in the active Chrome tab",
125869
+ args: external_exports.object({
125870
+ message: external_exports.string().min(1)
125871
+ }),
125872
+ run: async (context) => {
125873
+ return executeChromeTool({
125874
+ scriptName: "browser-pick.js",
125875
+ args: [context.args.message],
125876
+ cwd: options2.cwd,
125877
+ processExecPath: options2.processExecPath,
125878
+ spawnSyncFn: options2.spawnSyncFn,
125879
+ resolveChromeToolsResourceRootFn: options2.resolveChromeToolsResourceRootFn
125880
+ });
125881
+ }
125882
+ });
125883
+ chromeCli.command("cookies", {
125884
+ description: "Show cookies for the active Chrome tab",
125885
+ run: async () => {
125886
+ return executeChromeTool({
125887
+ scriptName: "browser-cookies.js",
125888
+ args: [],
125889
+ cwd: options2.cwd,
125890
+ processExecPath: options2.processExecPath,
125891
+ spawnSyncFn: options2.spawnSyncFn,
125892
+ resolveChromeToolsResourceRootFn: options2.resolveChromeToolsResourceRootFn
125893
+ });
125894
+ }
125895
+ });
125896
+ chromeCli.command("content", {
125897
+ description: "Extract readable markdown content from a URL in Chrome",
125898
+ args: external_exports.object({
125899
+ url: external_exports.string().min(1)
125900
+ }),
125901
+ run: async (context) => {
125902
+ return executeChromeTool({
125903
+ scriptName: "browser-content.js",
125904
+ args: [context.args.url],
125905
+ cwd: options2.cwd,
125906
+ processExecPath: options2.processExecPath,
125907
+ spawnSyncFn: options2.spawnSyncFn,
125908
+ resolveChromeToolsResourceRootFn: options2.resolveChromeToolsResourceRootFn
125909
+ });
125910
+ }
125911
+ });
125912
+ chromeCli.command("hn-scraper", {
125913
+ description: "Scrape Hacker News submissions as JSON",
125914
+ options: external_exports.object({
125915
+ limit: external_exports.number().int().positive().optional().describe("Maximum number of submissions to return")
125916
+ }),
125917
+ run: async (context) => {
125918
+ const args = [];
125919
+ if (context.options.limit !== void 0) {
125920
+ args.push("--limit", String(context.options.limit));
125921
+ }
125922
+ return executeChromeTool({
125923
+ scriptName: "browser-hn-scraper.js",
125924
+ args,
125925
+ outputMode: "json",
125926
+ cwd: options2.cwd,
125927
+ processExecPath: options2.processExecPath,
125928
+ spawnSyncFn: options2.spawnSyncFn,
125929
+ resolveChromeToolsResourceRootFn: options2.resolveChromeToolsResourceRootFn
125930
+ });
125931
+ }
125932
+ });
125933
+ return chromeCli;
125934
+ }
125935
+
125691
125936
  // src/services/inputReader.ts
125692
125937
  var import_promises2 = require("node:fs/promises");
125693
- var import_node_path4 = require("node:path");
125938
+ var import_node_path5 = require("node:path");
125694
125939
  async function readStdinText() {
125695
125940
  if (process.stdin.isTTY) {
125696
125941
  return "";
@@ -125793,7 +126038,7 @@ async function readDataInput(params) {
125793
126038
  cause: error48
125794
126039
  });
125795
126040
  }
125796
- const extension = (0, import_node_path4.extname)(trimmedFromFile).toLowerCase();
126041
+ const extension = (0, import_node_path5.extname)(trimmedFromFile).toLowerCase();
125797
126042
  if (extension === ".csv") {
125798
126043
  return parseCsvData(content, "--from-file");
125799
126044
  }
@@ -126591,7 +126836,7 @@ function createEnvCli(dependencies) {
126591
126836
 
126592
126837
  // src/services/studioPayload.ts
126593
126838
  var import_promises4 = require("node:fs/promises");
126594
- var import_node_path5 = require("node:path");
126839
+ var import_node_path6 = require("node:path");
126595
126840
  async function readStdinText2() {
126596
126841
  if (process.stdin.isTTY) {
126597
126842
  return "";
@@ -126622,7 +126867,7 @@ async function readStudioWriteInput(params) {
126622
126867
  throw new UserInputError("Provide either --data or --from-file, not both.");
126623
126868
  }
126624
126869
  if (trimmedFromFile) {
126625
- const extension = (0, import_node_path5.extname)(trimmedFromFile).toLowerCase();
126870
+ const extension = (0, import_node_path6.extname)(trimmedFromFile).toLowerCase();
126626
126871
  if (extension && extension !== ".json") {
126627
126872
  throw new UserInputError("Studio commands support only JSON files in --from-file.");
126628
126873
  }
@@ -127625,10 +127870,10 @@ function createStudioCli(dependencies) {
127625
127870
  }
127626
127871
 
127627
127872
  // src/commands/tuiCommand.ts
127628
- var import_node_child_process2 = require("node:child_process");
127629
- var import_node_fs3 = require("node:fs");
127630
- var import_node_path6 = require("node:path");
127631
- function summarizeFailure(result) {
127873
+ var import_node_child_process3 = require("node:child_process");
127874
+ var import_node_fs4 = require("node:fs");
127875
+ var import_node_path7 = require("node:path");
127876
+ function summarizeFailure2(result) {
127632
127877
  const stderr = result.stderr?.toString().trim();
127633
127878
  if (stderr && stderr.length > 0) {
127634
127879
  return stderr;
@@ -127644,23 +127889,23 @@ function summarizeFailure(result) {
127644
127889
  function resolveCliScriptPath() {
127645
127890
  const argvScript = process.argv[1];
127646
127891
  if (argvScript && argvScript.trim().length > 0) {
127647
- return (0, import_node_path6.isAbsolute)(argvScript) ? argvScript : (0, import_node_path6.resolve)(process.cwd(), argvScript);
127892
+ return (0, import_node_path7.isAbsolute)(argvScript) ? argvScript : (0, import_node_path7.resolve)(process.cwd(), argvScript);
127648
127893
  }
127649
127894
  return __filename;
127650
127895
  }
127651
127896
  function resolveOpenTuiEntryPath(options2 = {}) {
127652
127897
  const cwd = options2.cwd ?? process.cwd();
127653
127898
  const dirname6 = options2.dirname ?? __dirname;
127654
- const fileExists = options2.existsSyncFn ?? import_node_fs3.existsSync;
127899
+ const fileExists = options2.existsSyncFn ?? import_node_fs4.existsSync;
127655
127900
  const candidates = [
127656
127901
  // Source/dev mode in monorepo. Prefer this first so Bun resolves deps via
127657
127902
  // apps/api-cli/node_modules in workspace runs (e.g. `pnpm docyrus tui`).
127658
- (0, import_node_path6.resolve)(cwd, "apps/api-cli/src/tui/opentuiMain.tsx"),
127659
- (0, import_node_path6.resolve)(dirname6, "../tui/opentuiMain.tsx"),
127903
+ (0, import_node_path7.resolve)(cwd, "apps/api-cli/src/tui/opentuiMain.tsx"),
127904
+ (0, import_node_path7.resolve)(dirname6, "../tui/opentuiMain.tsx"),
127660
127905
  // Dist mode (bundled command runtime)
127661
- (0, import_node_path6.resolve)(dirname6, "tui.mjs"),
127662
- (0, import_node_path6.resolve)(dirname6, "../tui.mjs"),
127663
- (0, import_node_path6.resolve)(cwd, "dist/apps/api-cli/tui.mjs")
127906
+ (0, import_node_path7.resolve)(dirname6, "tui.mjs"),
127907
+ (0, import_node_path7.resolve)(dirname6, "../tui.mjs"),
127908
+ (0, import_node_path7.resolve)(cwd, "dist/apps/api-cli/tui.mjs")
127664
127909
  ];
127665
127910
  const resolved = candidates.find((candidate) => fileExists(candidate));
127666
127911
  if (!resolved) {
@@ -127671,7 +127916,7 @@ function resolveOpenTuiEntryPath(options2 = {}) {
127671
127916
  return resolved;
127672
127917
  }
127673
127918
  function ensureBunAvailable(options2 = {}) {
127674
- const spawnCommand = options2.spawnSyncFn ?? import_node_child_process2.spawnSync;
127919
+ const spawnCommand = options2.spawnSyncFn ?? import_node_child_process3.spawnSync;
127675
127920
  const result = spawnCommand("bun", ["--version"], {
127676
127921
  encoding: "utf8"
127677
127922
  });
@@ -127685,7 +127930,7 @@ function ensureBunAvailable(options2 = {}) {
127685
127930
  }
127686
127931
  }
127687
127932
  function launchOpenTuiProcess(options2) {
127688
- const spawnCommand = options2.spawnSyncFn ?? import_node_child_process2.spawnSync;
127933
+ const spawnCommand = options2.spawnSyncFn ?? import_node_child_process3.spawnSync;
127689
127934
  const result = spawnCommand("bun", [options2.entryPath], {
127690
127935
  stdio: ["inherit", "inherit", "pipe"],
127691
127936
  encoding: "utf8",
@@ -127701,7 +127946,7 @@ function launchOpenTuiProcess(options2) {
127701
127946
  }
127702
127947
  if (result.status !== 0) {
127703
127948
  throw new UserInputError(
127704
- `OpenTUI process failed: ${summarizeFailure(result)}`
127949
+ `OpenTUI process failed: ${summarizeFailure2(result)}`
127705
127950
  );
127706
127951
  }
127707
127952
  }
@@ -128446,7 +128691,7 @@ var AuthSessionService = class {
128446
128691
 
128447
128692
  // src/services/authStore.ts
128448
128693
  var import_promises5 = require("node:fs/promises");
128449
- var import_node_path7 = require("node:path");
128694
+ var import_node_path8 = require("node:path");
128450
128695
  function createEmptyState() {
128451
128696
  return {
128452
128697
  version: 2,
@@ -128521,7 +128766,7 @@ var AuthStore = class {
128521
128766
  });
128522
128767
  }
128523
128768
  const normalized = normalizeState(validated.data);
128524
- const directory = (0, import_node_path7.dirname)(this.authFilePath);
128769
+ const directory = (0, import_node_path8.dirname)(this.authFilePath);
128525
128770
  await (0, import_promises5.mkdir)(directory, {
128526
128771
  recursive: true,
128527
128772
  mode: 448
@@ -128736,7 +128981,7 @@ var AuthStore = class {
128736
128981
 
128737
128982
  // src/services/environmentConfig.ts
128738
128983
  var import_promises6 = require("node:fs/promises");
128739
- var import_node_path8 = require("node:path");
128984
+ var import_node_path9 = require("node:path");
128740
128985
  var ENVIRONMENT_ID_ALIASES = {
128741
128986
  "local-development": "dev",
128742
128987
  prod: "live"
@@ -128856,7 +129101,7 @@ var EnvironmentConfigService = class {
128856
129101
  });
128857
129102
  }
128858
129103
  const normalized = normalizeState2(validated.data);
128859
- const directory = (0, import_node_path8.dirname)(this.configFilePath);
129104
+ const directory = (0, import_node_path9.dirname)(this.configFilePath);
128860
129105
  await (0, import_promises6.mkdir)(directory, {
128861
129106
  recursive: true,
128862
129107
  mode: 448
@@ -128932,10 +129177,10 @@ var EnvironmentConfigService = class {
128932
129177
  };
128933
129178
 
128934
129179
  // src/services/piAgentLauncher.ts
128935
- var import_node_child_process3 = require("node:child_process");
128936
- var import_node_fs4 = require("node:fs");
129180
+ var import_node_child_process4 = require("node:child_process");
129181
+ var import_node_fs5 = require("node:fs");
128937
129182
  var import_promises7 = require("node:fs/promises");
128938
- var import_node_path9 = require("node:path");
129183
+ var import_node_path10 = require("node:path");
128939
129184
  var DOCYRUS_EXTERNAL_SKILL_SOURCE = "docyrus/agent-skills";
128940
129185
  var DOCYRUS_PACKAGED_PLATFORM_SKILL_NAME = "docyrus-platform";
128941
129186
  var DOCYRUS_MIGRATED_SKILL_NAMES = [
@@ -128953,7 +129198,7 @@ var DOCYRUS_EXTERNAL_SKILL_AGENT_IDS = [
128953
129198
  "windsurf"
128954
129199
  ];
128955
129200
  var DOCYRUS_EXTERNAL_SKILL_MARKER_FILE = ".docyrus-external-skills-installed.json";
128956
- function summarizeFailure2(result) {
129201
+ function summarizeFailure3(result) {
128957
129202
  const stderr = result.stderr?.toString().trim();
128958
129203
  if (stderr && stderr.length > 0) {
128959
129204
  return stderr;
@@ -128969,12 +129214,12 @@ function summarizeFailure2(result) {
128969
129214
  function resolvePackagedPiResourceRoot(options2 = {}) {
128970
129215
  const cwd = options2.cwd ?? process.cwd();
128971
129216
  const dirname6 = options2.dirname ?? __dirname;
128972
- const fileExists = options2.existsSyncFn ?? import_node_fs4.existsSync;
129217
+ const fileExists = options2.existsSyncFn ?? import_node_fs5.existsSync;
128973
129218
  const candidates = [
128974
- (0, import_node_path9.resolve)(cwd, "apps/api-cli/resources/pi-agent"),
128975
- (0, import_node_path9.resolve)(dirname6, "../resources/pi-agent"),
128976
- (0, import_node_path9.resolve)(dirname6, "resources/pi-agent"),
128977
- (0, import_node_path9.resolve)(cwd, "dist/apps/api-cli/resources/pi-agent")
129219
+ (0, import_node_path10.resolve)(cwd, "apps/api-cli/resources/pi-agent"),
129220
+ (0, import_node_path10.resolve)(dirname6, "../resources/pi-agent"),
129221
+ (0, import_node_path10.resolve)(dirname6, "resources/pi-agent"),
129222
+ (0, import_node_path10.resolve)(cwd, "dist/apps/api-cli/resources/pi-agent")
128978
129223
  ];
128979
129224
  const resolved = candidates.find((candidate) => fileExists(candidate));
128980
129225
  if (!resolved) {
@@ -128985,7 +129230,7 @@ function resolvePackagedPiResourceRoot(options2 = {}) {
128985
129230
  function resolveDocyrusPiLoaderEntryPath(options2 = {}) {
128986
129231
  const cwd = options2.cwd ?? process.cwd();
128987
129232
  const dirname6 = options2.dirname ?? __dirname;
128988
- const fileExists = options2.existsSyncFn ?? import_node_fs4.existsSync;
129233
+ const fileExists = options2.existsSyncFn ?? import_node_fs5.existsSync;
128989
129234
  const seen = /* @__PURE__ */ new Set();
128990
129235
  const candidates = options2.candidatePaths ?? [];
128991
129236
  const addCandidate = (candidate) => {
@@ -128995,23 +129240,23 @@ function resolveDocyrusPiLoaderEntryPath(options2 = {}) {
128995
129240
  }
128996
129241
  };
128997
129242
  const collectAncestorCandidates = (startDir) => {
128998
- let currentDir = (0, import_node_path9.resolve)(startDir);
129243
+ let currentDir = (0, import_node_path10.resolve)(startDir);
128999
129244
  while (true) {
129000
- addCandidate((0, import_node_path9.join)(currentDir, "dist", "apps", "api-cli", "agent-loader.js"));
129001
- addCandidate((0, import_node_path9.join)(currentDir, "agent-loader.js"));
129002
- if ((0, import_node_path9.basename)(currentDir) === "dist") {
129003
- addCandidate((0, import_node_path9.join)(currentDir, "apps", "api-cli", "agent-loader.js"));
129245
+ addCandidate((0, import_node_path10.join)(currentDir, "dist", "apps", "api-cli", "agent-loader.js"));
129246
+ addCandidate((0, import_node_path10.join)(currentDir, "agent-loader.js"));
129247
+ if ((0, import_node_path10.basename)(currentDir) === "dist") {
129248
+ addCandidate((0, import_node_path10.join)(currentDir, "apps", "api-cli", "agent-loader.js"));
129004
129249
  }
129005
- const parentDir = (0, import_node_path9.resolve)(currentDir, "..");
129250
+ const parentDir = (0, import_node_path10.resolve)(currentDir, "..");
129006
129251
  if (parentDir === currentDir) {
129007
129252
  break;
129008
129253
  }
129009
129254
  currentDir = parentDir;
129010
129255
  }
129011
129256
  };
129012
- addCandidate((0, import_node_path9.resolve)(cwd, "dist/apps/api-cli/agent-loader.js"));
129013
- addCandidate((0, import_node_path9.resolve)(dirname6, "../agent-loader.js"));
129014
- addCandidate((0, import_node_path9.resolve)(dirname6, "agent-loader.js"));
129257
+ addCandidate((0, import_node_path10.resolve)(cwd, "dist/apps/api-cli/agent-loader.js"));
129258
+ addCandidate((0, import_node_path10.resolve)(dirname6, "../agent-loader.js"));
129259
+ addCandidate((0, import_node_path10.resolve)(dirname6, "agent-loader.js"));
129015
129260
  collectAncestorCandidates(cwd);
129016
129261
  collectAncestorCandidates(dirname6);
129017
129262
  const resolved = candidates.find((candidate) => fileExists(candidate));
@@ -129023,7 +129268,7 @@ function resolveDocyrusPiLoaderEntryPath(options2 = {}) {
129023
129268
  function resolveInstalledPiPackageRootPath(options2 = {}) {
129024
129269
  const cwd = options2.cwd ?? process.cwd();
129025
129270
  const dirname6 = options2.dirname ?? __dirname;
129026
- const fileExists = options2.existsSyncFn ?? import_node_fs4.existsSync;
129271
+ const fileExists = options2.existsSyncFn ?? import_node_fs5.existsSync;
129027
129272
  const seen = /* @__PURE__ */ new Set();
129028
129273
  const candidates = options2.candidatePaths ?? [];
129029
129274
  const addCandidate = (candidate) => {
@@ -129033,27 +129278,27 @@ function resolveInstalledPiPackageRootPath(options2 = {}) {
129033
129278
  }
129034
129279
  };
129035
129280
  const collectAncestorCandidates = (startDir) => {
129036
- let currentDir = (0, import_node_path9.resolve)(startDir);
129281
+ let currentDir = (0, import_node_path10.resolve)(startDir);
129037
129282
  while (true) {
129038
- addCandidate((0, import_node_path9.join)(currentDir, "node_modules", "@mariozechner", "pi-coding-agent", "package.json"));
129039
- if ((0, import_node_path9.basename)(currentDir) === "node_modules") {
129040
- addCandidate((0, import_node_path9.join)(currentDir, "@mariozechner", "pi-coding-agent", "package.json"));
129283
+ addCandidate((0, import_node_path10.join)(currentDir, "node_modules", "@mariozechner", "pi-coding-agent", "package.json"));
129284
+ if ((0, import_node_path10.basename)(currentDir) === "node_modules") {
129285
+ addCandidate((0, import_node_path10.join)(currentDir, "@mariozechner", "pi-coding-agent", "package.json"));
129041
129286
  }
129042
- const parentDir = (0, import_node_path9.resolve)(currentDir, "..");
129287
+ const parentDir = (0, import_node_path10.resolve)(currentDir, "..");
129043
129288
  if (parentDir === currentDir) {
129044
129289
  break;
129045
129290
  }
129046
129291
  currentDir = parentDir;
129047
129292
  }
129048
129293
  };
129049
- addCandidate((0, import_node_path9.resolve)(cwd, "apps/api-cli/node_modules/@mariozechner/pi-coding-agent/package.json"));
129294
+ addCandidate((0, import_node_path10.resolve)(cwd, "apps/api-cli/node_modules/@mariozechner/pi-coding-agent/package.json"));
129050
129295
  collectAncestorCandidates(cwd);
129051
129296
  collectAncestorCandidates(dirname6);
129052
129297
  const resolvedPackageJson = candidates.find((candidate) => fileExists(candidate));
129053
129298
  if (!resolvedPackageJson) {
129054
129299
  throw new UserInputError(`Unable to locate the installed pi package root. Checked: ${candidates.join(", ")}`);
129055
129300
  }
129056
- return (0, import_node_path9.resolve)(resolvedPackageJson, "..");
129301
+ return (0, import_node_path10.resolve)(resolvedPackageJson, "..");
129057
129302
  }
129058
129303
  function createPiAgentRuntimeSkill(params) {
129059
129304
  const commandPrefix = params.scope === "global" ? "docyrus -g" : "docyrus";
@@ -129100,8 +129345,8 @@ function createPiAgentRuntimeSkill(params) {
129100
129345
  ].join("\n");
129101
129346
  }
129102
129347
  async function syncPackagedSkills(params) {
129103
- const sourceSkillsRoot = (0, import_node_path9.join)(params.resourceRoot, "skills");
129104
- const targetSkillsRoot = (0, import_node_path9.join)(params.agentRootPath, "skills");
129348
+ const sourceSkillsRoot = (0, import_node_path10.join)(params.resourceRoot, "skills");
129349
+ const targetSkillsRoot = (0, import_node_path10.join)(params.agentRootPath, "skills");
129105
129350
  await (0, import_promises7.mkdir)(targetSkillsRoot, {
129106
129351
  recursive: true,
129107
129352
  mode: 448
@@ -129110,25 +129355,25 @@ async function syncPackagedSkills(params) {
129110
129355
  withFileTypes: true
129111
129356
  });
129112
129357
  await Promise.all(DOCYRUS_MIGRATED_SKILL_NAMES.map(async (skillName) => {
129113
- await (0, import_promises7.rm)((0, import_node_path9.join)(targetSkillsRoot, skillName), {
129358
+ await (0, import_promises7.rm)((0, import_node_path10.join)(targetSkillsRoot, skillName), {
129114
129359
  recursive: true,
129115
129360
  force: true
129116
129361
  });
129117
129362
  }));
129118
129363
  await Promise.all(entries.map(async (entry) => {
129119
- await (0, import_promises7.cp)((0, import_node_path9.join)(sourceSkillsRoot, entry.name), (0, import_node_path9.join)(targetSkillsRoot, entry.name), {
129364
+ await (0, import_promises7.cp)((0, import_node_path10.join)(sourceSkillsRoot, entry.name), (0, import_node_path10.join)(targetSkillsRoot, entry.name), {
129120
129365
  recursive: true,
129121
129366
  force: true
129122
129367
  });
129123
129368
  }));
129124
129369
  }
129125
129370
  async function writeRuntimeSkill(params) {
129126
- const runtimeSkillDir = (0, import_node_path9.join)(params.agentRootPath, "skills", "docyrus-runtime-context");
129371
+ const runtimeSkillDir = (0, import_node_path10.join)(params.agentRootPath, "skills", "docyrus-runtime-context");
129127
129372
  await (0, import_promises7.mkdir)(runtimeSkillDir, {
129128
129373
  recursive: true,
129129
129374
  mode: 448
129130
129375
  });
129131
- await (0, import_promises7.writeFile)((0, import_node_path9.join)(runtimeSkillDir, "SKILL.md"), `${params.content}
129376
+ await (0, import_promises7.writeFile)((0, import_node_path10.join)(runtimeSkillDir, "SKILL.md"), `${params.content}
129132
129377
  `, {
129133
129378
  encoding: "utf8",
129134
129379
  mode: 384
@@ -129173,8 +129418,8 @@ function createPackagedDocyrusPlatformInstallArgs(params) {
129173
129418
  return args;
129174
129419
  }
129175
129420
  async function installExternalDocyrusSkillsOnce(params) {
129176
- const markerPath = (0, import_node_path9.join)(params.agentRootPath, DOCYRUS_EXTERNAL_SKILL_MARKER_FILE);
129177
- if ((0, import_node_fs4.existsSync)(markerPath)) {
129421
+ const markerPath = (0, import_node_path10.join)(params.agentRootPath, DOCYRUS_EXTERNAL_SKILL_MARKER_FILE);
129422
+ if ((0, import_node_fs5.existsSync)(markerPath)) {
129178
129423
  return;
129179
129424
  }
129180
129425
  const result = params.spawnCommand(resolveNpxCommand(), createDocyrusSkillsInstallArgs(params.scope), {
@@ -129187,7 +129432,7 @@ async function installExternalDocyrusSkillsOnce(params) {
129187
129432
  });
129188
129433
  if (result.error || result.status !== 0) {
129189
129434
  process.stderr.write(
129190
- `[docyrus] Automatic Docyrus skill install failed. Continuing without it: ${result.error?.message || summarizeFailure2(result)}
129435
+ `[docyrus] Automatic Docyrus skill install failed. Continuing without it: ${result.error?.message || summarizeFailure3(result)}
129191
129436
  `
129192
129437
  );
129193
129438
  return;
@@ -129205,11 +129450,11 @@ async function installExternalDocyrusSkillsOnce(params) {
129205
129450
  });
129206
129451
  }
129207
129452
  function resolvePackagedDocyrusPlatformSkillPath(resourceRoot) {
129208
- return (0, import_node_path9.join)(resourceRoot, "skills", DOCYRUS_PACKAGED_PLATFORM_SKILL_NAME);
129453
+ return (0, import_node_path10.join)(resourceRoot, "skills", DOCYRUS_PACKAGED_PLATFORM_SKILL_NAME);
129209
129454
  }
129210
129455
  function installPackagedDocyrusPlatformSkill(params) {
129211
129456
  const skillSourcePath = resolvePackagedDocyrusPlatformSkillPath(params.resourceRoot);
129212
- if (!(0, import_node_fs4.existsSync)(skillSourcePath)) {
129457
+ if (!(0, import_node_fs5.existsSync)(skillSourcePath)) {
129213
129458
  process.stderr.write("[docyrus] Packaged docyrus-platform skill is missing. Continuing without agent sync.\n");
129214
129459
  return;
129215
129460
  }
@@ -129230,7 +129475,7 @@ function installPackagedDocyrusPlatformSkill(params) {
129230
129475
  );
129231
129476
  if (result.error || result.status !== 0) {
129232
129477
  process.stderr.write(
129233
- `[docyrus] Automatic docyrus-platform skill sync failed. Continuing without it: ${result.error?.message || summarizeFailure2(result)}
129478
+ `[docyrus] Automatic docyrus-platform skill sync failed. Continuing without it: ${result.error?.message || summarizeFailure3(result)}
129234
129479
  `
129235
129480
  );
129236
129481
  }
@@ -129246,7 +129491,7 @@ function validatePiAgentLaunchRequest(params) {
129246
129491
  function createPiAgentLauncher(options2) {
129247
129492
  const cwd = options2.cwd ?? process.cwd();
129248
129493
  const stdinIsTTY = options2.stdinIsTTY ?? process.stdin.isTTY ?? false;
129249
- const spawnCommand = options2.spawnSyncFn ?? import_node_child_process3.spawnSync;
129494
+ const spawnCommand = options2.spawnSyncFn ?? import_node_child_process4.spawnSync;
129250
129495
  const processExecPath = options2.processExecPath ?? process.execPath;
129251
129496
  const resolveResourceRoot = options2.resolvePackagedPiResourceRootFn ?? resolvePackagedPiResourceRoot;
129252
129497
  const resolveLoaderPath = options2.resolveDocyrusPiLoaderEntryPathFn ?? resolveDocyrusPiLoaderEntryPath;
@@ -129307,14 +129552,14 @@ function createPiAgentLauncher(options2) {
129307
129552
  });
129308
129553
  }
129309
129554
  if (result.status !== 0) {
129310
- throw new UserInputError(`Docyrus pi loader failed: ${summarizeFailure2(result)}`);
129555
+ throw new UserInputError(`Docyrus pi loader failed: ${summarizeFailure3(result)}`);
129311
129556
  }
129312
129557
  };
129313
129558
  }
129314
129559
 
129315
129560
  // src/services/tenantOpenApi.ts
129316
129561
  var import_promises8 = require("node:fs/promises");
129317
- var import_node_path10 = require("node:path");
129562
+ var import_node_path11 = require("node:path");
129318
129563
  function resolveSourceUrl(tenantId, template) {
129319
129564
  return template.replace("{tenantId}", encodeURIComponent(tenantId));
129320
129565
  }
@@ -129338,7 +129583,7 @@ var TenantOpenApiService = class {
129338
129583
  }
129339
129584
  async #writeOpenApiFile(tenantId, parsedContent) {
129340
129585
  const filePath = this.getTenantOpenApiFilePath(tenantId);
129341
- await (0, import_promises8.mkdir)((0, import_node_path10.dirname)(filePath), {
129586
+ await (0, import_promises8.mkdir)((0, import_node_path11.dirname)(filePath), {
129342
129587
  recursive: true,
129343
129588
  mode: 448
129344
129589
  });
@@ -129384,7 +129629,7 @@ var TenantOpenApiService = class {
129384
129629
  throw new AuthSessionError("Tenant ID is required to resolve OpenAPI spec path.");
129385
129630
  }
129386
129631
  const rootPath = this.params?.rootPath || TENANT_OPENAPI_ROOT_PATH;
129387
- return (0, import_node_path10.join)(rootPath, normalizedTenantId, "openapi.json");
129632
+ return (0, import_node_path11.join)(rootPath, normalizedTenantId, "openapi.json");
129388
129633
  }
129389
129634
  async downloadTenantOpenApi(tenantId, options2 = {}) {
129390
129635
  const normalizedTenantId = tenantId.trim();
@@ -129447,6 +129692,9 @@ var ROOT_HELP_COMMANDS = [
129447
129692
  { command: 'ai "<prompt>"', description: "Send a prompt to the default Docyrus CLI agent" },
129448
129693
  { command: "agent [prompt]", description: "Launch the scoped Docyrus pi assistant" },
129449
129694
  { command: "coder [prompt]", description: "Launch the scoped Docyrus pi coding agent" },
129695
+ { command: "chrome start", description: "Launch Chrome with remote debugging on :9222" },
129696
+ { command: "chrome nav <url>", description: "Navigate the active Chrome tab" },
129697
+ { command: "chrome content <url>", description: "Extract readable page content as markdown" },
129450
129698
  { command: "discover api", description: "Download active tenant OpenAPI spec" },
129451
129699
  { command: "discover namespaces", description: "List namespaces from tenant OpenAPI spec" },
129452
129700
  { command: "discover path <prefix>", description: "List endpoint paths by prefix" },
@@ -129537,6 +129785,9 @@ function createDocyrusCli(params) {
129537
129785
  cli2.command(createCoderCli({
129538
129786
  launchPiAgent: piAgentLauncher
129539
129787
  }));
129788
+ cli2.command(createChromeCli({
129789
+ cwd: params?.cwd
129790
+ }));
129540
129791
  cli2.command(createDsCli({
129541
129792
  createApiClient,
129542
129793
  environmentConfigService,