@docyrus/docyrus 0.0.19 → 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 (111) hide show
  1. package/agent-loader.js +37 -3
  2. package/agent-loader.js.map +2 -2
  3. package/main.js +498 -93
  4. package/main.js.map +4 -4
  5. package/package.json +14 -4
  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/prompts/coder-system.md +106 -0
  64. package/resources/pi-agent/skills/changelog-generator/SKILL.md +425 -0
  65. package/resources/pi-agent/skills/docyrus-chrome-devtools-cli/SKILL.md +80 -0
  66. package/resources/pi-agent/skills/docyrus-platform/SKILL.md +71 -0
  67. package/resources/pi-agent/skills/docyrus-platform/references/ai-capabilities.md +43 -0
  68. package/resources/pi-agent/skills/docyrus-platform/references/auth-and-multi-tenancy.md +35 -0
  69. package/resources/pi-agent/skills/docyrus-platform/references/automation-and-workflows.md +30 -0
  70. package/resources/pi-agent/skills/docyrus-platform/references/core-building-blocks.md +53 -0
  71. package/resources/pi-agent/skills/{docyrus-api-dev → docyrus-platform}/references/data-source-query-guide.md +32 -28
  72. package/resources/pi-agent/skills/docyrus-platform/references/developer-tools.md +28 -0
  73. package/resources/pi-agent/skills/docyrus-platform/references/docyrus-cli-usage.md +554 -0
  74. package/resources/pi-agent/skills/{docyrus-api-dev → docyrus-platform}/references/formula-design-guide-llm.md +15 -23
  75. package/resources/pi-agent/skills/docyrus-platform/references/integrations-and-events.md +60 -0
  76. package/resources/pi-agent/skills/docyrus-platform/references/platform-services.md +58 -0
  77. package/resources/pi-agent/skills/docyrus-platform/references/querying-and-data-operations.md +27 -0
  78. package/resources/pi-agent/prompts/coder-append-system.md +0 -19
  79. package/resources/pi-agent/skills/docyrus-ai/SKILL.md +0 -28
  80. package/resources/pi-agent/skills/docyrus-api-dev/SKILL.md +0 -161
  81. package/resources/pi-agent/skills/docyrus-api-dev/references/api-client.md +0 -349
  82. package/resources/pi-agent/skills/docyrus-api-dev/references/authentication.md +0 -238
  83. package/resources/pi-agent/skills/docyrus-api-dev/references/query-and-formulas.md +0 -592
  84. package/resources/pi-agent/skills/docyrus-api-doctor/SKILL.md +0 -70
  85. package/resources/pi-agent/skills/docyrus-api-doctor/references/checklist-details.md +0 -588
  86. package/resources/pi-agent/skills/docyrus-app-dev/SKILL.md +0 -159
  87. package/resources/pi-agent/skills/docyrus-app-dev/references/api-client-and-auth.md +0 -275
  88. package/resources/pi-agent/skills/docyrus-app-dev/references/collections-and-patterns.md +0 -352
  89. package/resources/pi-agent/skills/docyrus-app-dev/references/data-source-query-guide.md +0 -2059
  90. package/resources/pi-agent/skills/docyrus-app-dev/references/formula-design-guide-llm.md +0 -320
  91. package/resources/pi-agent/skills/docyrus-app-dev/references/query-guide.md +0 -525
  92. package/resources/pi-agent/skills/docyrus-app-ui-design/SKILL.md +0 -466
  93. package/resources/pi-agent/skills/docyrus-app-ui-design/references/component-selection-guide.md +0 -602
  94. package/resources/pi-agent/skills/docyrus-app-ui-design/references/icon-usage-guide.md +0 -463
  95. package/resources/pi-agent/skills/docyrus-app-ui-design/references/preferred-components-catalog.md +0 -242
  96. package/resources/pi-agent/skills/docyrus-apps/SKILL.md +0 -54
  97. package/resources/pi-agent/skills/docyrus-architect/SKILL.md +0 -174
  98. package/resources/pi-agent/skills/docyrus-architect/references/custom-query-guide.md +0 -410
  99. package/resources/pi-agent/skills/docyrus-architect/references/data-source-query-guide.md +0 -2059
  100. package/resources/pi-agent/skills/docyrus-architect/references/formula-design-guide-llm.md +0 -320
  101. package/resources/pi-agent/skills/docyrus-architect/references/formula-reference.md +0 -145
  102. package/resources/pi-agent/skills/docyrus-auth/SKILL.md +0 -100
  103. package/resources/pi-agent/skills/docyrus-cli-app/SKILL.md +0 -279
  104. package/resources/pi-agent/skills/docyrus-cli-app/references/cli-manifest.md +0 -532
  105. package/resources/pi-agent/skills/docyrus-cli-app/references/list-query-examples.md +0 -248
  106. package/resources/pi-agent/skills/docyrus-curl/SKILL.md +0 -32
  107. package/resources/pi-agent/skills/docyrus-discover/SKILL.md +0 -63
  108. package/resources/pi-agent/skills/docyrus-ds/SKILL.md +0 -95
  109. package/resources/pi-agent/skills/docyrus-env/SKILL.md +0 -21
  110. package/resources/pi-agent/skills/docyrus-studio/SKILL.md +0 -369
  111. package/resources/pi-agent/skills/docyrus-tui/SKILL.md +0 -15
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.19",
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",
124690
- "@mariozechner/pi-ai": "0.60.0",
124691
- "@mariozechner/pi-coding-agent": "0.60.0",
124691
+ "@modelcontextprotocol/ext-apps": "^1.2.2",
124692
+ "@modelcontextprotocol/sdk": "^1.25.1",
124693
+ "@mariozechner/pi-ai": "0.61.0",
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
  }
@@ -125956,6 +126201,20 @@ var BULK_OPERATION_LIMIT = 50;
125956
126201
  function isRecord(value) {
125957
126202
  return typeof value === "object" && value !== null && !Array.isArray(value);
125958
126203
  }
126204
+ function normalizeOptionalString(value) {
126205
+ const trimmed = value?.trim();
126206
+ return trimmed && trimmed.length > 0 ? trimmed : void 0;
126207
+ }
126208
+ function normalizeJsonLikeQueryValue(value, flag) {
126209
+ const trimmed = normalizeOptionalString(value);
126210
+ if (!trimmed) {
126211
+ return void 0;
126212
+ }
126213
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
126214
+ return JSON.stringify(parseJsonData(trimmed, flag));
126215
+ }
126216
+ return trimmed;
126217
+ }
125959
126218
  function toBulkPayload(payload, mode) {
125960
126219
  if (!Array.isArray(payload)) {
125961
126220
  return null;
@@ -126004,7 +126263,10 @@ function createDsCli(dependencies) {
126004
126263
  const apiClient = dependencies.createApiClient(apiBaseUrl);
126005
126264
  const response = await apiClient.request({
126006
126265
  method: "GET",
126007
- path: `/apps/${context.args.appSlug}/data-sources/${context.args.dataSourceSlug}`
126266
+ path: `/apps/${context.args.appSlug}/data-sources/${context.args.dataSourceSlug}`,
126267
+ query: {
126268
+ expand: "fields"
126269
+ }
126008
126270
  });
126009
126271
  return await injectContext({
126010
126272
  apiBaseUrl,
@@ -126020,31 +126282,44 @@ function createDsCli(dependencies) {
126020
126282
  dataSourceSlug: external_exports.string().min(1)
126021
126283
  }),
126022
126284
  options: external_exports.object({
126023
- columns: external_exports.string().optional(),
126024
- filters: external_exports.string().optional(),
126285
+ collapseRows: external_exports.boolean().optional().describe("Collapse rows into a single aggregated array"),
126286
+ columns: external_exports.string().optional().describe("Columns to select; comma-separated or JSON array"),
126287
+ distinctColumns: external_exports.string().optional().describe("Distinct columns; comma-separated or JSON array"),
126288
+ formulas: external_exports.string().optional().describe("JSON formulas object"),
126289
+ calculations: external_exports.string().optional().describe("JSON calculations array"),
126290
+ filters: external_exports.string().optional().describe("JSON filter group"),
126291
+ filterKeyword: external_exports.string().optional().describe("Keyword filter"),
126025
126292
  limit: external_exports.number().optional(),
126026
126293
  offset: external_exports.number().optional(),
126027
- orderBy: external_exports.string().optional(),
126028
- fullCount: external_exports.boolean().optional()
126294
+ orderBy: external_exports.string().optional().describe("Sort order string or JSON object/array"),
126295
+ groupSummaries: external_exports.boolean().optional().describe("Return per-group summaries when calculations are used"),
126296
+ fullCount: external_exports.boolean().optional(),
126297
+ expand: external_exports.string().optional().describe("Expand columns; comma-separated or JSON array"),
126298
+ pivot: external_exports.string().optional().describe("JSON pivot configuration"),
126299
+ childQueries: external_exports.string().optional().describe("JSON child query array")
126029
126300
  }),
126030
126301
  run: async (context) => {
126031
126302
  const apiBaseUrl = await dependencies.environmentConfigService.getActiveApiBaseUrl();
126032
126303
  const apiClient = dependencies.createApiClient(apiBaseUrl);
126033
- let serializedFilters;
126034
- if (context.options.filters) {
126035
- const parsedFilters = parseJsonData(context.options.filters, "--filters");
126036
- serializedFilters = JSON.stringify(parsedFilters);
126037
- }
126038
126304
  const response = await apiClient.request({
126039
126305
  method: "GET",
126040
126306
  path: `/apps/${context.args.appSlug}/data-sources/${context.args.dataSourceSlug}/items`,
126041
126307
  query: {
126042
- columns: context.options.columns,
126043
- filters: serializedFilters,
126308
+ collapseRows: context.options.collapseRows,
126309
+ columns: normalizeJsonLikeQueryValue(context.options.columns, "--columns"),
126310
+ distinctColumns: normalizeJsonLikeQueryValue(context.options.distinctColumns, "--distinctColumns"),
126311
+ formulas: normalizeJsonLikeQueryValue(context.options.formulas, "--formulas"),
126312
+ calculations: normalizeJsonLikeQueryValue(context.options.calculations, "--calculations"),
126313
+ filters: normalizeJsonLikeQueryValue(context.options.filters, "--filters"),
126314
+ filterKeyword: normalizeOptionalString(context.options.filterKeyword),
126044
126315
  limit: context.options.limit,
126045
126316
  offset: context.options.offset,
126046
- orderBy: context.options.orderBy,
126047
- fullCount: context.options.fullCount
126317
+ orderBy: normalizeJsonLikeQueryValue(context.options.orderBy, "--orderBy"),
126318
+ groupSummaries: context.options.groupSummaries,
126319
+ fullCount: context.options.fullCount,
126320
+ expand: normalizeJsonLikeQueryValue(context.options.expand, "--expand"),
126321
+ pivot: normalizeJsonLikeQueryValue(context.options.pivot, "--pivot"),
126322
+ childQueries: normalizeJsonLikeQueryValue(context.options.childQueries, "--childQueries")
126048
126323
  }
126049
126324
  });
126050
126325
  return await injectContext({
@@ -126561,7 +126836,7 @@ function createEnvCli(dependencies) {
126561
126836
 
126562
126837
  // src/services/studioPayload.ts
126563
126838
  var import_promises4 = require("node:fs/promises");
126564
- var import_node_path5 = require("node:path");
126839
+ var import_node_path6 = require("node:path");
126565
126840
  async function readStdinText2() {
126566
126841
  if (process.stdin.isTTY) {
126567
126842
  return "";
@@ -126592,7 +126867,7 @@ async function readStudioWriteInput(params) {
126592
126867
  throw new UserInputError("Provide either --data or --from-file, not both.");
126593
126868
  }
126594
126869
  if (trimmedFromFile) {
126595
- const extension = (0, import_node_path5.extname)(trimmedFromFile).toLowerCase();
126870
+ const extension = (0, import_node_path6.extname)(trimmedFromFile).toLowerCase();
126596
126871
  if (extension && extension !== ".json") {
126597
126872
  throw new UserInputError("Studio commands support only JSON files in --from-file.");
126598
126873
  }
@@ -126920,25 +127195,13 @@ function createStudioCli(dependencies) {
126920
127195
  studioCli.command("get-data-source", {
126921
127196
  description: "Get a single data source",
126922
127197
  options: external_exports.object({
126923
- appId: external_exports.string().optional().describe("App ID"),
126924
- appSlug: external_exports.string().optional().describe("App slug"),
126925
- dataSourceId: external_exports.string().optional().describe("Data source ID"),
126926
- dataSourceSlug: external_exports.string().optional().describe("Data source slug")
127198
+ dataSourceId: external_exports.string().min(1).describe("Data source ID")
126927
127199
  }),
126928
127200
  run: async (context) => {
126929
127201
  const studio = await getStudioRunContext(dependencies);
126930
- const appId = await studio.resolver.resolveAppId({
126931
- appId: context.options.appId,
126932
- appSlug: context.options.appSlug
126933
- });
126934
- const dataSourceId = await studio.resolver.resolveDataSourceId({
126935
- appId,
126936
- dataSourceId: context.options.dataSourceId,
126937
- dataSourceSlug: context.options.dataSourceSlug
126938
- });
126939
127202
  const response = await studio.apiClient.request({
126940
127203
  method: "GET",
126941
- path: `/dev/apps/${appId}/data-sources/${dataSourceId}`
127204
+ path: `/dev/data-sources/${context.options.dataSourceId}`
126942
127205
  });
126943
127206
  return await wrapStudioPayload(studio.apiBaseUrl, dependencies, response.data);
126944
127207
  }
@@ -127607,10 +127870,10 @@ function createStudioCli(dependencies) {
127607
127870
  }
127608
127871
 
127609
127872
  // src/commands/tuiCommand.ts
127610
- var import_node_child_process2 = require("node:child_process");
127611
- var import_node_fs3 = require("node:fs");
127612
- var import_node_path6 = require("node:path");
127613
- 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) {
127614
127877
  const stderr = result.stderr?.toString().trim();
127615
127878
  if (stderr && stderr.length > 0) {
127616
127879
  return stderr;
@@ -127626,23 +127889,23 @@ function summarizeFailure(result) {
127626
127889
  function resolveCliScriptPath() {
127627
127890
  const argvScript = process.argv[1];
127628
127891
  if (argvScript && argvScript.trim().length > 0) {
127629
- 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);
127630
127893
  }
127631
127894
  return __filename;
127632
127895
  }
127633
127896
  function resolveOpenTuiEntryPath(options2 = {}) {
127634
127897
  const cwd = options2.cwd ?? process.cwd();
127635
127898
  const dirname6 = options2.dirname ?? __dirname;
127636
- const fileExists = options2.existsSyncFn ?? import_node_fs3.existsSync;
127899
+ const fileExists = options2.existsSyncFn ?? import_node_fs4.existsSync;
127637
127900
  const candidates = [
127638
127901
  // Source/dev mode in monorepo. Prefer this first so Bun resolves deps via
127639
127902
  // apps/api-cli/node_modules in workspace runs (e.g. `pnpm docyrus tui`).
127640
- (0, import_node_path6.resolve)(cwd, "apps/api-cli/src/tui/opentuiMain.tsx"),
127641
- (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"),
127642
127905
  // Dist mode (bundled command runtime)
127643
- (0, import_node_path6.resolve)(dirname6, "tui.mjs"),
127644
- (0, import_node_path6.resolve)(dirname6, "../tui.mjs"),
127645
- (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")
127646
127909
  ];
127647
127910
  const resolved = candidates.find((candidate) => fileExists(candidate));
127648
127911
  if (!resolved) {
@@ -127653,7 +127916,7 @@ function resolveOpenTuiEntryPath(options2 = {}) {
127653
127916
  return resolved;
127654
127917
  }
127655
127918
  function ensureBunAvailable(options2 = {}) {
127656
- const spawnCommand = options2.spawnSyncFn ?? import_node_child_process2.spawnSync;
127919
+ const spawnCommand = options2.spawnSyncFn ?? import_node_child_process3.spawnSync;
127657
127920
  const result = spawnCommand("bun", ["--version"], {
127658
127921
  encoding: "utf8"
127659
127922
  });
@@ -127667,7 +127930,7 @@ function ensureBunAvailable(options2 = {}) {
127667
127930
  }
127668
127931
  }
127669
127932
  function launchOpenTuiProcess(options2) {
127670
- const spawnCommand = options2.spawnSyncFn ?? import_node_child_process2.spawnSync;
127933
+ const spawnCommand = options2.spawnSyncFn ?? import_node_child_process3.spawnSync;
127671
127934
  const result = spawnCommand("bun", [options2.entryPath], {
127672
127935
  stdio: ["inherit", "inherit", "pipe"],
127673
127936
  encoding: "utf8",
@@ -127683,7 +127946,7 @@ function launchOpenTuiProcess(options2) {
127683
127946
  }
127684
127947
  if (result.status !== 0) {
127685
127948
  throw new UserInputError(
127686
- `OpenTUI process failed: ${summarizeFailure(result)}`
127949
+ `OpenTUI process failed: ${summarizeFailure2(result)}`
127687
127950
  );
127688
127951
  }
127689
127952
  }
@@ -128428,7 +128691,7 @@ var AuthSessionService = class {
128428
128691
 
128429
128692
  // src/services/authStore.ts
128430
128693
  var import_promises5 = require("node:fs/promises");
128431
- var import_node_path7 = require("node:path");
128694
+ var import_node_path8 = require("node:path");
128432
128695
  function createEmptyState() {
128433
128696
  return {
128434
128697
  version: 2,
@@ -128503,7 +128766,7 @@ var AuthStore = class {
128503
128766
  });
128504
128767
  }
128505
128768
  const normalized = normalizeState(validated.data);
128506
- const directory = (0, import_node_path7.dirname)(this.authFilePath);
128769
+ const directory = (0, import_node_path8.dirname)(this.authFilePath);
128507
128770
  await (0, import_promises5.mkdir)(directory, {
128508
128771
  recursive: true,
128509
128772
  mode: 448
@@ -128718,7 +128981,7 @@ var AuthStore = class {
128718
128981
 
128719
128982
  // src/services/environmentConfig.ts
128720
128983
  var import_promises6 = require("node:fs/promises");
128721
- var import_node_path8 = require("node:path");
128984
+ var import_node_path9 = require("node:path");
128722
128985
  var ENVIRONMENT_ID_ALIASES = {
128723
128986
  "local-development": "dev",
128724
128987
  prod: "live"
@@ -128838,7 +129101,7 @@ var EnvironmentConfigService = class {
128838
129101
  });
128839
129102
  }
128840
129103
  const normalized = normalizeState2(validated.data);
128841
- const directory = (0, import_node_path8.dirname)(this.configFilePath);
129104
+ const directory = (0, import_node_path9.dirname)(this.configFilePath);
128842
129105
  await (0, import_promises6.mkdir)(directory, {
128843
129106
  recursive: true,
128844
129107
  mode: 448
@@ -128914,11 +129177,28 @@ var EnvironmentConfigService = class {
128914
129177
  };
128915
129178
 
128916
129179
  // src/services/piAgentLauncher.ts
128917
- var import_node_child_process3 = require("node:child_process");
128918
- 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");
128919
129182
  var import_promises7 = require("node:fs/promises");
128920
- var import_node_path9 = require("node:path");
128921
- function summarizeFailure2(result) {
129183
+ var import_node_path10 = require("node:path");
129184
+ var DOCYRUS_EXTERNAL_SKILL_SOURCE = "docyrus/agent-skills";
129185
+ var DOCYRUS_PACKAGED_PLATFORM_SKILL_NAME = "docyrus-platform";
129186
+ var DOCYRUS_MIGRATED_SKILL_NAMES = [
129187
+ "docyrus-app-dev",
129188
+ "docyrus-api-dev",
129189
+ "docyrus-cli-app"
129190
+ ];
129191
+ var DOCYRUS_EXTERNAL_SKILL_AGENT_IDS = [
129192
+ "pi",
129193
+ "claude-code",
129194
+ "codex",
129195
+ "github-copilot",
129196
+ "gemini-cli",
129197
+ "antigravity",
129198
+ "windsurf"
129199
+ ];
129200
+ var DOCYRUS_EXTERNAL_SKILL_MARKER_FILE = ".docyrus-external-skills-installed.json";
129201
+ function summarizeFailure3(result) {
128922
129202
  const stderr = result.stderr?.toString().trim();
128923
129203
  if (stderr && stderr.length > 0) {
128924
129204
  return stderr;
@@ -128934,12 +129214,12 @@ function summarizeFailure2(result) {
128934
129214
  function resolvePackagedPiResourceRoot(options2 = {}) {
128935
129215
  const cwd = options2.cwd ?? process.cwd();
128936
129216
  const dirname6 = options2.dirname ?? __dirname;
128937
- const fileExists = options2.existsSyncFn ?? import_node_fs4.existsSync;
129217
+ const fileExists = options2.existsSyncFn ?? import_node_fs5.existsSync;
128938
129218
  const candidates = [
128939
- (0, import_node_path9.resolve)(cwd, "apps/api-cli/resources/pi-agent"),
128940
- (0, import_node_path9.resolve)(dirname6, "../resources/pi-agent"),
128941
- (0, import_node_path9.resolve)(dirname6, "resources/pi-agent"),
128942
- (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")
128943
129223
  ];
128944
129224
  const resolved = candidates.find((candidate) => fileExists(candidate));
128945
129225
  if (!resolved) {
@@ -128950,7 +129230,7 @@ function resolvePackagedPiResourceRoot(options2 = {}) {
128950
129230
  function resolveDocyrusPiLoaderEntryPath(options2 = {}) {
128951
129231
  const cwd = options2.cwd ?? process.cwd();
128952
129232
  const dirname6 = options2.dirname ?? __dirname;
128953
- const fileExists = options2.existsSyncFn ?? import_node_fs4.existsSync;
129233
+ const fileExists = options2.existsSyncFn ?? import_node_fs5.existsSync;
128954
129234
  const seen = /* @__PURE__ */ new Set();
128955
129235
  const candidates = options2.candidatePaths ?? [];
128956
129236
  const addCandidate = (candidate) => {
@@ -128960,23 +129240,23 @@ function resolveDocyrusPiLoaderEntryPath(options2 = {}) {
128960
129240
  }
128961
129241
  };
128962
129242
  const collectAncestorCandidates = (startDir) => {
128963
- let currentDir = (0, import_node_path9.resolve)(startDir);
129243
+ let currentDir = (0, import_node_path10.resolve)(startDir);
128964
129244
  while (true) {
128965
- addCandidate((0, import_node_path9.join)(currentDir, "dist", "apps", "api-cli", "agent-loader.js"));
128966
- addCandidate((0, import_node_path9.join)(currentDir, "agent-loader.js"));
128967
- if ((0, import_node_path9.basename)(currentDir) === "dist") {
128968
- 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"));
128969
129249
  }
128970
- const parentDir = (0, import_node_path9.resolve)(currentDir, "..");
129250
+ const parentDir = (0, import_node_path10.resolve)(currentDir, "..");
128971
129251
  if (parentDir === currentDir) {
128972
129252
  break;
128973
129253
  }
128974
129254
  currentDir = parentDir;
128975
129255
  }
128976
129256
  };
128977
- addCandidate((0, import_node_path9.resolve)(cwd, "dist/apps/api-cli/agent-loader.js"));
128978
- addCandidate((0, import_node_path9.resolve)(dirname6, "../agent-loader.js"));
128979
- 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"));
128980
129260
  collectAncestorCandidates(cwd);
128981
129261
  collectAncestorCandidates(dirname6);
128982
129262
  const resolved = candidates.find((candidate) => fileExists(candidate));
@@ -128988,7 +129268,7 @@ function resolveDocyrusPiLoaderEntryPath(options2 = {}) {
128988
129268
  function resolveInstalledPiPackageRootPath(options2 = {}) {
128989
129269
  const cwd = options2.cwd ?? process.cwd();
128990
129270
  const dirname6 = options2.dirname ?? __dirname;
128991
- const fileExists = options2.existsSyncFn ?? import_node_fs4.existsSync;
129271
+ const fileExists = options2.existsSyncFn ?? import_node_fs5.existsSync;
128992
129272
  const seen = /* @__PURE__ */ new Set();
128993
129273
  const candidates = options2.candidatePaths ?? [];
128994
129274
  const addCandidate = (candidate) => {
@@ -128998,27 +129278,27 @@ function resolveInstalledPiPackageRootPath(options2 = {}) {
128998
129278
  }
128999
129279
  };
129000
129280
  const collectAncestorCandidates = (startDir) => {
129001
- let currentDir = (0, import_node_path9.resolve)(startDir);
129281
+ let currentDir = (0, import_node_path10.resolve)(startDir);
129002
129282
  while (true) {
129003
- addCandidate((0, import_node_path9.join)(currentDir, "node_modules", "@mariozechner", "pi-coding-agent", "package.json"));
129004
- if ((0, import_node_path9.basename)(currentDir) === "node_modules") {
129005
- 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"));
129006
129286
  }
129007
- const parentDir = (0, import_node_path9.resolve)(currentDir, "..");
129287
+ const parentDir = (0, import_node_path10.resolve)(currentDir, "..");
129008
129288
  if (parentDir === currentDir) {
129009
129289
  break;
129010
129290
  }
129011
129291
  currentDir = parentDir;
129012
129292
  }
129013
129293
  };
129014
- 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"));
129015
129295
  collectAncestorCandidates(cwd);
129016
129296
  collectAncestorCandidates(dirname6);
129017
129297
  const resolvedPackageJson = candidates.find((candidate) => fileExists(candidate));
129018
129298
  if (!resolvedPackageJson) {
129019
129299
  throw new UserInputError(`Unable to locate the installed pi package root. Checked: ${candidates.join(", ")}`);
129020
129300
  }
129021
- return (0, import_node_path9.resolve)(resolvedPackageJson, "..");
129301
+ return (0, import_node_path10.resolve)(resolvedPackageJson, "..");
129022
129302
  }
129023
129303
  function createPiAgentRuntimeSkill(params) {
129024
129304
  const commandPrefix = params.scope === "global" ? "docyrus -g" : "docyrus";
@@ -129065,8 +129345,8 @@ function createPiAgentRuntimeSkill(params) {
129065
129345
  ].join("\n");
129066
129346
  }
129067
129347
  async function syncPackagedSkills(params) {
129068
- const sourceSkillsRoot = (0, import_node_path9.join)(params.resourceRoot, "skills");
129069
- 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");
129070
129350
  await (0, import_promises7.mkdir)(targetSkillsRoot, {
129071
129351
  recursive: true,
129072
129352
  mode: 448
@@ -129074,25 +129354,132 @@ async function syncPackagedSkills(params) {
129074
129354
  const entries = await (0, import_promises7.readdir)(sourceSkillsRoot, {
129075
129355
  withFileTypes: true
129076
129356
  });
129357
+ await Promise.all(DOCYRUS_MIGRATED_SKILL_NAMES.map(async (skillName) => {
129358
+ await (0, import_promises7.rm)((0, import_node_path10.join)(targetSkillsRoot, skillName), {
129359
+ recursive: true,
129360
+ force: true
129361
+ });
129362
+ }));
129077
129363
  await Promise.all(entries.map(async (entry) => {
129078
- 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), {
129079
129365
  recursive: true,
129080
129366
  force: true
129081
129367
  });
129082
129368
  }));
129083
129369
  }
129084
129370
  async function writeRuntimeSkill(params) {
129085
- 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");
129086
129372
  await (0, import_promises7.mkdir)(runtimeSkillDir, {
129087
129373
  recursive: true,
129088
129374
  mode: 448
129089
129375
  });
129090
- 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}
129377
+ `, {
129378
+ encoding: "utf8",
129379
+ mode: 384
129380
+ });
129381
+ }
129382
+ function resolveNpxCommand() {
129383
+ return process.platform === "win32" ? "npx.cmd" : "npx";
129384
+ }
129385
+ function createDocyrusSkillsInstallArgs(scope) {
129386
+ const args = [
129387
+ "skills",
129388
+ "add",
129389
+ DOCYRUS_EXTERNAL_SKILL_SOURCE
129390
+ ];
129391
+ if (scope === "global") {
129392
+ args.push("--global");
129393
+ }
129394
+ args.push(
129395
+ "--skill",
129396
+ ...DOCYRUS_MIGRATED_SKILL_NAMES,
129397
+ "--agent",
129398
+ ...DOCYRUS_EXTERNAL_SKILL_AGENT_IDS,
129399
+ "--yes"
129400
+ );
129401
+ return args;
129402
+ }
129403
+ function createPackagedDocyrusPlatformInstallArgs(params) {
129404
+ const args = [
129405
+ "skills",
129406
+ "add",
129407
+ params.skillSourcePath
129408
+ ];
129409
+ if (params.scope === "global") {
129410
+ args.push("--global");
129411
+ }
129412
+ args.push(
129413
+ "--agent",
129414
+ ...DOCYRUS_EXTERNAL_SKILL_AGENT_IDS,
129415
+ "--copy",
129416
+ "--yes"
129417
+ );
129418
+ return args;
129419
+ }
129420
+ async function installExternalDocyrusSkillsOnce(params) {
129421
+ const markerPath = (0, import_node_path10.join)(params.agentRootPath, DOCYRUS_EXTERNAL_SKILL_MARKER_FILE);
129422
+ if ((0, import_node_fs5.existsSync)(markerPath)) {
129423
+ return;
129424
+ }
129425
+ const result = params.spawnCommand(resolveNpxCommand(), createDocyrusSkillsInstallArgs(params.scope), {
129426
+ stdio: ["ignore", "pipe", "pipe"],
129427
+ encoding: "utf8",
129428
+ cwd: params.cwd,
129429
+ env: {
129430
+ ...process.env
129431
+ }
129432
+ });
129433
+ if (result.error || result.status !== 0) {
129434
+ process.stderr.write(
129435
+ `[docyrus] Automatic Docyrus skill install failed. Continuing without it: ${result.error?.message || summarizeFailure3(result)}
129436
+ `
129437
+ );
129438
+ return;
129439
+ }
129440
+ await (0, import_promises7.writeFile)(markerPath, `${JSON.stringify({
129441
+ source: DOCYRUS_EXTERNAL_SKILL_SOURCE,
129442
+ skills: DOCYRUS_MIGRATED_SKILL_NAMES,
129443
+ agents: DOCYRUS_EXTERNAL_SKILL_AGENT_IDS,
129444
+ scope: params.scope,
129445
+ installedAt: (/* @__PURE__ */ new Date()).toISOString()
129446
+ }, null, 2)}
129091
129447
  `, {
129092
129448
  encoding: "utf8",
129093
129449
  mode: 384
129094
129450
  });
129095
129451
  }
129452
+ function resolvePackagedDocyrusPlatformSkillPath(resourceRoot) {
129453
+ return (0, import_node_path10.join)(resourceRoot, "skills", DOCYRUS_PACKAGED_PLATFORM_SKILL_NAME);
129454
+ }
129455
+ function installPackagedDocyrusPlatformSkill(params) {
129456
+ const skillSourcePath = resolvePackagedDocyrusPlatformSkillPath(params.resourceRoot);
129457
+ if (!(0, import_node_fs5.existsSync)(skillSourcePath)) {
129458
+ process.stderr.write("[docyrus] Packaged docyrus-platform skill is missing. Continuing without agent sync.\n");
129459
+ return;
129460
+ }
129461
+ const result = params.spawnCommand(
129462
+ resolveNpxCommand(),
129463
+ createPackagedDocyrusPlatformInstallArgs({
129464
+ scope: params.scope,
129465
+ skillSourcePath
129466
+ }),
129467
+ {
129468
+ stdio: ["ignore", "pipe", "pipe"],
129469
+ encoding: "utf8",
129470
+ cwd: params.cwd,
129471
+ env: {
129472
+ ...process.env
129473
+ }
129474
+ }
129475
+ );
129476
+ if (result.error || result.status !== 0) {
129477
+ process.stderr.write(
129478
+ `[docyrus] Automatic docyrus-platform skill sync failed. Continuing without it: ${result.error?.message || summarizeFailure3(result)}
129479
+ `
129480
+ );
129481
+ }
129482
+ }
129096
129483
  function validatePiAgentLaunchRequest(params) {
129097
129484
  if (params.request.mode && !params.request.print && params.stdinIsTTY) {
129098
129485
  throw new UserInputError("`--mode` requires `--print` when stdin is interactive.");
@@ -129104,7 +129491,7 @@ function validatePiAgentLaunchRequest(params) {
129104
129491
  function createPiAgentLauncher(options2) {
129105
129492
  const cwd = options2.cwd ?? process.cwd();
129106
129493
  const stdinIsTTY = options2.stdinIsTTY ?? process.stdin.isTTY ?? false;
129107
- const spawnCommand = options2.spawnSyncFn ?? import_node_child_process3.spawnSync;
129494
+ const spawnCommand = options2.spawnSyncFn ?? import_node_child_process4.spawnSync;
129108
129495
  const processExecPath = options2.processExecPath ?? process.execPath;
129109
129496
  const resolveResourceRoot = options2.resolvePackagedPiResourceRootFn ?? resolvePackagedPiResourceRoot;
129110
129497
  const resolveLoaderPath = options2.resolveDocyrusPiLoaderEntryPathFn ?? resolveDocyrusPiLoaderEntryPath;
@@ -129133,6 +129520,18 @@ function createPiAgentLauncher(options2) {
129133
129520
  settingsRootPath
129134
129521
  })
129135
129522
  });
129523
+ await installExternalDocyrusSkillsOnce({
129524
+ agentRootPath,
129525
+ cwd,
129526
+ scope: options2.settingsPaths.scope,
129527
+ spawnCommand
129528
+ });
129529
+ installPackagedDocyrusPlatformSkill({
129530
+ resourceRoot,
129531
+ cwd,
129532
+ scope: options2.settingsPaths.scope,
129533
+ spawnCommand
129534
+ });
129136
129535
  const loaderEntryPath = resolveLoaderPath({ cwd });
129137
129536
  const piPackageRoot = resolvePiPackageRoot({ cwd });
129138
129537
  const result = spawnCommand(processExecPath, [loaderEntryPath], {
@@ -129153,14 +129552,14 @@ function createPiAgentLauncher(options2) {
129153
129552
  });
129154
129553
  }
129155
129554
  if (result.status !== 0) {
129156
- throw new UserInputError(`Docyrus pi loader failed: ${summarizeFailure2(result)}`);
129555
+ throw new UserInputError(`Docyrus pi loader failed: ${summarizeFailure3(result)}`);
129157
129556
  }
129158
129557
  };
129159
129558
  }
129160
129559
 
129161
129560
  // src/services/tenantOpenApi.ts
129162
129561
  var import_promises8 = require("node:fs/promises");
129163
- var import_node_path10 = require("node:path");
129562
+ var import_node_path11 = require("node:path");
129164
129563
  function resolveSourceUrl(tenantId, template) {
129165
129564
  return template.replace("{tenantId}", encodeURIComponent(tenantId));
129166
129565
  }
@@ -129184,7 +129583,7 @@ var TenantOpenApiService = class {
129184
129583
  }
129185
129584
  async #writeOpenApiFile(tenantId, parsedContent) {
129186
129585
  const filePath = this.getTenantOpenApiFilePath(tenantId);
129187
- await (0, import_promises8.mkdir)((0, import_node_path10.dirname)(filePath), {
129586
+ await (0, import_promises8.mkdir)((0, import_node_path11.dirname)(filePath), {
129188
129587
  recursive: true,
129189
129588
  mode: 448
129190
129589
  });
@@ -129230,7 +129629,7 @@ var TenantOpenApiService = class {
129230
129629
  throw new AuthSessionError("Tenant ID is required to resolve OpenAPI spec path.");
129231
129630
  }
129232
129631
  const rootPath = this.params?.rootPath || TENANT_OPENAPI_ROOT_PATH;
129233
- return (0, import_node_path10.join)(rootPath, normalizedTenantId, "openapi.json");
129632
+ return (0, import_node_path11.join)(rootPath, normalizedTenantId, "openapi.json");
129234
129633
  }
129235
129634
  async downloadTenantOpenApi(tenantId, options2 = {}) {
129236
129635
  const normalizedTenantId = tenantId.trim();
@@ -129293,6 +129692,9 @@ var ROOT_HELP_COMMANDS = [
129293
129692
  { command: 'ai "<prompt>"', description: "Send a prompt to the default Docyrus CLI agent" },
129294
129693
  { command: "agent [prompt]", description: "Launch the scoped Docyrus pi assistant" },
129295
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" },
129296
129698
  { command: "discover api", description: "Download active tenant OpenAPI spec" },
129297
129699
  { command: "discover namespaces", description: "List namespaces from tenant OpenAPI spec" },
129298
129700
  { command: "discover path <prefix>", description: "List endpoint paths by prefix" },
@@ -129383,6 +129785,9 @@ function createDocyrusCli(params) {
129383
129785
  cli2.command(createCoderCli({
129384
129786
  launchPiAgent: piAgentLauncher
129385
129787
  }));
129788
+ cli2.command(createChromeCli({
129789
+ cwd: params?.cwd
129790
+ }));
129386
129791
  cli2.command(createDsCli({
129387
129792
  createApiClient,
129388
129793
  environmentConfigService,