@docyrus/docyrus 0.0.31 → 0.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/server-loader.js CHANGED
@@ -690,9 +690,9 @@ var init_dist = __esm({
690
690
  });
691
691
 
692
692
  // src/server/server-loader.ts
693
- var import_node_fs = require("node:fs");
693
+ var import_node_fs2 = require("node:fs");
694
694
  var import_node_url = require("node:url");
695
- var import_node_path6 = require("node:path");
695
+ var import_node_path7 = require("node:path");
696
696
  var import_picocolors2 = __toESM(require_picocolors());
697
697
 
698
698
  // src/agent/envStore.ts
@@ -793,11 +793,31 @@ var AgentEnvStore = class {
793
793
  }
794
794
  };
795
795
 
796
+ // src/agent/packagedExtensions.ts
797
+ var import_node_fs = require("node:fs");
798
+ var import_node_path2 = require("node:path");
799
+ var SERVER_ONLY_PACKAGED_EXTENSION_NAMES = /* @__PURE__ */ new Set(["docyrus-web-browser"]);
800
+ function isPackagedExtensionEntry(entryName, isDirectory) {
801
+ return isDirectory || entryName.endsWith(".ts") || entryName.endsWith(".js");
802
+ }
803
+ function getPackagedExtensionName(entryName) {
804
+ return entryName.replace(/\.(ts|js)$/u, "");
805
+ }
806
+ function resolvePackagedExtensionPaths(resourceRoot, runtime = "terminal") {
807
+ const extensionsRoot = (0, import_node_path2.join)(resourceRoot, "extensions");
808
+ if (!(0, import_node_fs.existsSync)(extensionsRoot)) {
809
+ return [];
810
+ }
811
+ return (0, import_node_fs.readdirSync)(extensionsRoot, {
812
+ withFileTypes: true
813
+ }).filter((entry) => isPackagedExtensionEntry(entry.name, entry.isDirectory())).filter((entry) => runtime === "server" || !SERVER_ONLY_PACKAGED_EXTENSION_NAMES.has(getPackagedExtensionName(entry.name))).map((entry) => (0, import_node_path2.join)(extensionsRoot, entry.name)).sort((left, right) => left.localeCompare(right));
814
+ }
815
+
796
816
  // src/server/agentServer.ts
797
817
  var import_node_child_process = require("node:child_process");
798
818
  var import_node_crypto3 = require("node:crypto");
799
819
  var import_promises5 = require("node:fs/promises");
800
- var import_node_path5 = require("node:path");
820
+ var import_node_path6 = require("node:path");
801
821
 
802
822
  // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/compose.js
803
823
  var compose = (middleware, onError, onNotFound) => {
@@ -3105,9 +3125,122 @@ function parseAskUserResponseFromToolOutput(output) {
3105
3125
  return normalizeAskUserResponse(output);
3106
3126
  }
3107
3127
 
3128
+ // resources/pi-agent/shared/docyrusWebBrowserProtocol.ts
3129
+ var DOCYRUS_WEB_BROWSER_TAG = "docyrus_web_browser";
3130
+ var DOCYRUS_WEB_BROWSER_OPEN = `<${DOCYRUS_WEB_BROWSER_TAG}>`;
3131
+ var DOCYRUS_WEB_BROWSER_CLOSE = `</${DOCYRUS_WEB_BROWSER_TAG}>`;
3132
+ var DOCYRUS_WEB_BROWSER_RESULT_TAG = "docyrus_web_browser_result";
3133
+ var DOCYRUS_WEB_BROWSER_RESULT_OPEN = `<${DOCYRUS_WEB_BROWSER_RESULT_TAG}>`;
3134
+ var DOCYRUS_WEB_BROWSER_RESULT_CLOSE = `</${DOCYRUS_WEB_BROWSER_RESULT_TAG}>`;
3135
+ var WEB_PREVIEW_CONTEXT_TOOL = "web_preview_context";
3136
+ var WEB_PREVIEW_PLAYWRIGHT_TOOL = "web_preview_playwright";
3137
+ var DOCYRUS_WEB_BROWSER_TOOL_NAMES = [
3138
+ WEB_PREVIEW_CONTEXT_TOOL,
3139
+ WEB_PREVIEW_PLAYWRIGHT_TOOL
3140
+ ];
3141
+ var DOCYRUS_WEB_BROWSER_CLIENT_TOOLS = [
3142
+ {
3143
+ name: WEB_PREVIEW_CONTEXT_TOOL,
3144
+ description: "Inspect the current Docyrus web preview state before automation. Prefer this first when preview availability or bridge state is unknown.",
3145
+ inputSchema: {
3146
+ type: "object",
3147
+ properties: {
3148
+ includeSnapshot: { type: "boolean" }
3149
+ },
3150
+ additionalProperties: false
3151
+ }
3152
+ },
3153
+ {
3154
+ name: WEB_PREVIEW_PLAYWRIGHT_TOOL,
3155
+ description: "Run Playwright-style actions against the Docyrus web preview. Prefer structured steps over raw scripts.",
3156
+ inputSchema: {
3157
+ type: "object",
3158
+ properties: {
3159
+ script: { type: "string" },
3160
+ steps: {
3161
+ type: "array",
3162
+ items: {
3163
+ type: "object",
3164
+ properties: {
3165
+ action: { type: "string" },
3166
+ selector: { type: "string" },
3167
+ url: { type: "string" },
3168
+ value: { type: "string" },
3169
+ values: {
3170
+ type: "array",
3171
+ items: { type: "string" }
3172
+ },
3173
+ key: { type: "string" },
3174
+ attribute: { type: "string" },
3175
+ timeoutMs: { type: "number" },
3176
+ state: { type: "string" }
3177
+ },
3178
+ additionalProperties: true
3179
+ }
3180
+ },
3181
+ timeoutMs: { type: "number" },
3182
+ stopOnError: { type: "boolean" }
3183
+ },
3184
+ additionalProperties: true
3185
+ }
3186
+ }
3187
+ ];
3188
+ function hashString2(value) {
3189
+ let hash = 0;
3190
+ for (let index = 0; index < value.length; index += 1) {
3191
+ hash = (hash << 5) - hash + value.charCodeAt(index);
3192
+ hash |= 0;
3193
+ }
3194
+ return Math.abs(hash).toString(36);
3195
+ }
3196
+ function isRecord2(value) {
3197
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3198
+ }
3199
+ function isDocyrusWebBrowserToolName(value) {
3200
+ return DOCYRUS_WEB_BROWSER_TOOL_NAMES.some((toolName) => toolName === value);
3201
+ }
3202
+ function normalizeDocyrusWebBrowserToolRequest(value) {
3203
+ if (!isRecord2(value) || !isDocyrusWebBrowserToolName(value.tool)) {
3204
+ return void 0;
3205
+ }
3206
+ return {
3207
+ tool: value.tool,
3208
+ input: isRecord2(value.input) ? value.input : void 0
3209
+ };
3210
+ }
3211
+ function createDocyrusWebBrowserToolCallId(request) {
3212
+ return `docyrus_web_browser_${hashString2(JSON.stringify(request))}`;
3213
+ }
3214
+ function parseDocyrusWebBrowserRequestFromText(text) {
3215
+ const trimmed = text.trim();
3216
+ if (!trimmed.startsWith(DOCYRUS_WEB_BROWSER_OPEN) || !trimmed.endsWith(DOCYRUS_WEB_BROWSER_CLOSE)) {
3217
+ return void 0;
3218
+ }
3219
+ const body = trimmed.slice(DOCYRUS_WEB_BROWSER_OPEN.length, trimmed.length - DOCYRUS_WEB_BROWSER_CLOSE.length).trim();
3220
+ if (!body) {
3221
+ return void 0;
3222
+ }
3223
+ try {
3224
+ return normalizeDocyrusWebBrowserToolRequest(JSON.parse(body));
3225
+ } catch {
3226
+ return void 0;
3227
+ }
3228
+ }
3229
+ function formatDocyrusWebBrowserToolResponsePrompt(response) {
3230
+ return [
3231
+ "The docyrus-web-browser client tool returned a result.",
3232
+ "",
3233
+ `${DOCYRUS_WEB_BROWSER_RESULT_OPEN}`,
3234
+ JSON.stringify(response, null, 2),
3235
+ `${DOCYRUS_WEB_BROWSER_RESULT_CLOSE}`,
3236
+ "",
3237
+ "Continue the task using this result. If the tool reported an availability or bridge blocker, explain that blocker exactly and do not claim success."
3238
+ ].join("\n");
3239
+ }
3240
+
3108
3241
  // src/server/eventBridge.ts
3109
3242
  function createEventBridge(params) {
3110
- const { messageId, onChunk, onDone, onError, onAskUser } = params;
3243
+ const { messageId, onChunk, onDone, onError, onAskUser, onDocyrusWebBrowserTool } = params;
3111
3244
  const activeToolCalls = /* @__PURE__ */ new Map();
3112
3245
  let activeTextBuffer = null;
3113
3246
  function flushBufferedTextToStream(close) {
@@ -3143,6 +3276,27 @@ function createEventBridge(params) {
3143
3276
  });
3144
3277
  return true;
3145
3278
  }
3279
+ function maybeEmitDocyrusWebBrowserTool(text) {
3280
+ const request = parseDocyrusWebBrowserRequestFromText(text);
3281
+ if (!request) {
3282
+ return false;
3283
+ }
3284
+ const toolCallId = createDocyrusWebBrowserToolCallId(request);
3285
+ onDocyrusWebBrowserTool?.({ toolCallId, request });
3286
+ onChunk({ type: "tool-input-start", toolCallId, toolName: request.tool, dynamic: true });
3287
+ onChunk({
3288
+ type: "tool-input-available",
3289
+ toolCallId,
3290
+ toolName: request.tool,
3291
+ input: request.input ?? {},
3292
+ dynamic: true
3293
+ });
3294
+ return true;
3295
+ }
3296
+ function shouldKeepBufferingDynamicToolText(text) {
3297
+ const dynamicToolTags = ["<ask_user>", "<docyrus_web_browser>"];
3298
+ return dynamicToolTags.some((tag) => tag.startsWith(text) || text.startsWith(tag));
3299
+ }
3146
3300
  function handleEvent(event) {
3147
3301
  switch (event.type) {
3148
3302
  case "message_update": {
@@ -3181,7 +3335,7 @@ function createEventBridge(params) {
3181
3335
  break;
3182
3336
  }
3183
3337
  activeTextBuffer.text += assistantEvent.delta ?? "";
3184
- if ("<ask_user>".startsWith(activeTextBuffer.text) || activeTextBuffer.text.startsWith("<ask_user>")) {
3338
+ if (shouldKeepBufferingDynamicToolText(activeTextBuffer.text)) {
3185
3339
  break;
3186
3340
  }
3187
3341
  flushBufferedTextToStream(false);
@@ -3197,7 +3351,7 @@ function createEventBridge(params) {
3197
3351
  activeTextBuffer = null;
3198
3352
  break;
3199
3353
  }
3200
- if (!maybeEmitAskUser(activeTextBuffer.text)) {
3354
+ if (!maybeEmitAskUser(activeTextBuffer.text) && !maybeEmitDocyrusWebBrowserTool(activeTextBuffer.text)) {
3201
3355
  flushBufferedTextToStream(true);
3202
3356
  } else {
3203
3357
  activeTextBuffer = null;
@@ -3282,7 +3436,7 @@ function createEventBridge(params) {
3282
3436
 
3283
3437
  // src/agent/modelsConfig.ts
3284
3438
  var import_promises2 = require("node:fs/promises");
3285
- var import_node_path2 = require("node:path");
3439
+ var import_node_path3 = require("node:path");
3286
3440
  function createDefaultState2() {
3287
3441
  return {
3288
3442
  providers: {}
@@ -3306,7 +3460,7 @@ async function readModelsConfig(filePath) {
3306
3460
  }
3307
3461
  }
3308
3462
  async function writeModelsConfig(filePath, state) {
3309
- const directory = (0, import_node_path2.dirname)(filePath);
3463
+ const directory = (0, import_node_path3.dirname)(filePath);
3310
3464
  await (0, import_promises2.mkdir)(directory, {
3311
3465
  recursive: true,
3312
3466
  mode: 448
@@ -3361,7 +3515,7 @@ function createCustomOpenAiProviderConfig(params) {
3361
3515
  function createAzureProviderConfig(params) {
3362
3516
  const providerConfig = {
3363
3517
  baseUrl: params.baseUrl,
3364
- apiKey: "env:AZURE_OPENAI_API_KEY"
3518
+ apiKey: "AZURE_OPENAI_API_KEY"
3365
3519
  };
3366
3520
  if (params.useCustomModel) {
3367
3521
  providerConfig.api = "azure-openai-responses";
@@ -3390,6 +3544,22 @@ function trimOrUndefined(value) {
3390
3544
  const trimmed = value?.trim();
3391
3545
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
3392
3546
  }
3547
+ function normalizeAzureBaseUrl(baseUrl) {
3548
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
3549
+ try {
3550
+ const url = new URL(trimmed);
3551
+ url.search = "";
3552
+ url.hash = "";
3553
+ if (url.pathname.endsWith("/openai/v1")) {
3554
+ url.pathname = url.pathname.slice(0, -3);
3555
+ } else if (url.pathname.endsWith("/openai/responses")) {
3556
+ url.pathname = url.pathname.slice(0, -10);
3557
+ }
3558
+ return url.toString().replace(/\/+$/, "");
3559
+ } catch {
3560
+ return trimmed.replace(/\/openai\/v1$/i, "/openai").replace(/\/openai\/responses$/i, "/openai");
3561
+ }
3562
+ }
3393
3563
  async function saveGenericApiKey(params) {
3394
3564
  params.authStorage.set(params.providerId, {
3395
3565
  type: "api_key",
@@ -3416,6 +3586,7 @@ async function saveCustomOpenAiConfig(params) {
3416
3586
  async function saveAzureConfig(params) {
3417
3587
  const modelId = params.modelId.trim();
3418
3588
  const useCustomModel = params.useCustomModel ?? false;
3589
+ const normalizedBaseUrl = normalizeAzureBaseUrl(params.baseUrl);
3419
3590
  params.authStorage.set("azure-openai-responses", {
3420
3591
  type: "api_key",
3421
3592
  key: params.apiKey.trim()
@@ -3440,7 +3611,7 @@ async function saveAzureConfig(params) {
3440
3611
  }
3441
3612
  await params.envStore.setMany(envValues);
3442
3613
  await upsertModelsProvider(params.modelsJsonPath, "azure-openai-responses", createAzureProviderConfig({
3443
- baseUrl: params.baseUrl.trim(),
3614
+ baseUrl: normalizedBaseUrl,
3444
3615
  modelId,
3445
3616
  useCustomModel
3446
3617
  }));
@@ -3687,7 +3858,7 @@ function getProviderFormFields(params) {
3687
3858
  title: "Azure OpenAI base URL",
3688
3859
  required: true,
3689
3860
  component: "text",
3690
- placeholder: "https://my-resource.openai.azure.com/openai/v1",
3861
+ placeholder: "https://my-resource.openai.azure.com/openai",
3691
3862
  dependsOn: { field: "configMode", equals: "base-url" }
3692
3863
  },
3693
3864
  {
@@ -3716,8 +3887,8 @@ function getProviderFormFields(params) {
3716
3887
  name: "apiVersion",
3717
3888
  title: "API version",
3718
3889
  component: "text",
3719
- defaultValue: "2025-03-01-preview",
3720
- placeholder: "2025-03-01-preview"
3890
+ defaultValue: "2025-04-01-preview",
3891
+ placeholder: "2025-04-01-preview"
3721
3892
  }
3722
3893
  ];
3723
3894
  case "amazon-bedrock":
@@ -3909,7 +4080,7 @@ async function applyProviderLogin(params) {
3909
4080
  return { providerId: provider.id, preferredModelId: params.input.modelId };
3910
4081
  }
3911
4082
  case "azure-openai-responses": {
3912
- const baseUrl = params.input.baseUrl ?? (params.input.resourceName ? `https://${params.input.resourceName}.openai.azure.com/openai/v1` : void 0);
4083
+ const baseUrl = params.input.baseUrl ?? (params.input.resourceName ? `https://${params.input.resourceName}.openai.azure.com/openai` : void 0);
3913
4084
  if (!baseUrl) {
3914
4085
  throw new Error("Azure login requires either baseUrl or resourceName.");
3915
4086
  }
@@ -3949,9 +4120,14 @@ async function applyProviderLogin(params) {
3949
4120
  }
3950
4121
  }
3951
4122
  async function refreshSessionAfterCredentialChange(params) {
4123
+ await params.envStore?.hydrateProcessEnv(process.env);
3952
4124
  params.modelRegistry.refresh();
3953
4125
  const availableModels = params.modelRegistry.getAvailable();
3954
4126
  const preferredModel = params.preferredProviderId && params.preferredModelId ? availableModels.find((model) => model.provider === params.preferredProviderId && model.id === params.preferredModelId) : params.preferredProviderId ? availableModels.find((model) => model.provider === params.preferredProviderId) : void 0;
4127
+ if (preferredModel) {
4128
+ await params.session.setModel(preferredModel);
4129
+ return;
4130
+ }
3955
4131
  const currentModel = params.session.model;
3956
4132
  const currentModelStillAvailable = currentModel ? availableModels.some((model) => model.provider === currentModel.provider && model.id === currentModel.id) : false;
3957
4133
  if (currentModel && !currentModelStillAvailable) {
@@ -4132,21 +4308,21 @@ var OAuthFlowManager = class {
4132
4308
  var import_node_crypto2 = require("node:crypto");
4133
4309
  var import_promises3 = require("node:fs/promises");
4134
4310
  var import_node_os = require("node:os");
4135
- var import_node_path3 = require("node:path");
4311
+ var import_node_path4 = require("node:path");
4136
4312
  var PROJECT_CONFIG_NAME = ".pi/mcp.json";
4137
4313
  var IMPORT_PATHS = {
4138
- "cursor": (0, import_node_path3.join)((0, import_node_os.homedir)(), ".cursor", "mcp.json"),
4139
- "claude-code": (0, import_node_path3.join)((0, import_node_os.homedir)(), ".claude", "claude_desktop_config.json"),
4140
- "claude-desktop": (0, import_node_path3.join)((0, import_node_os.homedir)(), "Library", "Application Support", "Claude", "claude_desktop_config.json"),
4141
- "codex": (0, import_node_path3.join)((0, import_node_os.homedir)(), ".codex", "config.json"),
4142
- "windsurf": (0, import_node_path3.join)((0, import_node_os.homedir)(), ".windsurf", "mcp.json"),
4314
+ "cursor": (0, import_node_path4.join)((0, import_node_os.homedir)(), ".cursor", "mcp.json"),
4315
+ "claude-code": (0, import_node_path4.join)((0, import_node_os.homedir)(), ".claude", "claude_desktop_config.json"),
4316
+ "claude-desktop": (0, import_node_path4.join)((0, import_node_os.homedir)(), "Library", "Application Support", "Claude", "claude_desktop_config.json"),
4317
+ "codex": (0, import_node_path4.join)((0, import_node_os.homedir)(), ".codex", "config.json"),
4318
+ "windsurf": (0, import_node_path4.join)((0, import_node_os.homedir)(), ".windsurf", "mcp.json"),
4143
4319
  "vscode": ".vscode/mcp.json"
4144
4320
  };
4145
4321
  function getMcpConfigPath(agentDir) {
4146
- return (0, import_node_path3.join)(agentDir, "mcp.json");
4322
+ return (0, import_node_path4.join)(agentDir, "mcp.json");
4147
4323
  }
4148
4324
  function getMcpCachePath(agentDir) {
4149
- return (0, import_node_path3.join)(agentDir, "mcp-cache.json");
4325
+ return (0, import_node_path4.join)(agentDir, "mcp-cache.json");
4150
4326
  }
4151
4327
  var SERVER_NAME_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
4152
4328
  function validateServerName(name) {
@@ -4283,7 +4459,7 @@ async function loadMcpServerConfig(agentDir, cwd) {
4283
4459
  if (!importPath) {
4284
4460
  continue;
4285
4461
  }
4286
- const fullPath = importPath.startsWith(".") ? (0, import_node_path3.resolve)(cwd, importPath) : importPath;
4462
+ const fullPath = importPath.startsWith(".") ? (0, import_node_path4.resolve)(cwd, importPath) : importPath;
4287
4463
  const imported = await readJsonFile(fullPath);
4288
4464
  if (!imported) {
4289
4465
  continue;
@@ -4296,7 +4472,7 @@ async function loadMcpServerConfig(agentDir, cwd) {
4296
4472
  }
4297
4473
  }
4298
4474
  }
4299
- const projectPath = (0, import_node_path3.resolve)(cwd, PROJECT_CONFIG_NAME);
4475
+ const projectPath = (0, import_node_path4.resolve)(cwd, PROJECT_CONFIG_NAME);
4300
4476
  if (projectPath !== configPath) {
4301
4477
  const projectRaw = await readJsonFile(projectPath);
4302
4478
  if (projectRaw) {
@@ -4380,7 +4556,7 @@ async function getServerProvenance(agentDir, cwd) {
4380
4556
  if (!importPath) {
4381
4557
  continue;
4382
4558
  }
4383
- const fullPath = importPath.startsWith(".") ? (0, import_node_path3.resolve)(cwd, importPath) : importPath;
4559
+ const fullPath = importPath.startsWith(".") ? (0, import_node_path4.resolve)(cwd, importPath) : importPath;
4384
4560
  const imported = await readJsonFile(fullPath);
4385
4561
  if (!imported) {
4386
4562
  continue;
@@ -4393,7 +4569,7 @@ async function getServerProvenance(agentDir, cwd) {
4393
4569
  }
4394
4570
  }
4395
4571
  }
4396
- const projectPath = (0, import_node_path3.resolve)(cwd, PROJECT_CONFIG_NAME);
4572
+ const projectPath = (0, import_node_path4.resolve)(cwd, PROJECT_CONFIG_NAME);
4397
4573
  if (projectPath !== userPath) {
4398
4574
  const projectRaw = await readJsonFile(projectPath);
4399
4575
  if (projectRaw) {
@@ -4417,7 +4593,7 @@ async function readUserConfig(agentDir) {
4417
4593
  }
4418
4594
  async function writeUserConfig(agentDir, raw2) {
4419
4595
  const configPath = getMcpConfigPath(agentDir);
4420
- await (0, import_promises3.mkdir)((0, import_node_path3.dirname)(configPath), { recursive: true });
4596
+ await (0, import_promises3.mkdir)((0, import_node_path4.dirname)(configPath), { recursive: true });
4421
4597
  const tmpPath = `${configPath}.${process.pid}.tmp`;
4422
4598
  await (0, import_promises3.writeFile)(tmpPath, JSON.stringify(raw2, null, 2) + "\n", "utf-8");
4423
4599
  await (0, import_promises3.rename)(tmpPath, configPath);
@@ -4475,7 +4651,7 @@ function formatToolName(toolName, serverName, prefix) {
4475
4651
 
4476
4652
  // src/server/skillsService.ts
4477
4653
  var import_promises4 = require("node:fs/promises");
4478
- var import_node_path4 = require("node:path");
4654
+ var import_node_path5 = require("node:path");
4479
4655
  function parseFrontmatter(content) {
4480
4656
  const frontmatter = {};
4481
4657
  if (!content.startsWith("---")) {
@@ -4509,7 +4685,7 @@ async function dirExists(path) {
4509
4685
  }
4510
4686
  }
4511
4687
  async function listSkills(agentDir) {
4512
- const skillsDir = (0, import_node_path4.join)(agentDir, "skills");
4688
+ const skillsDir = (0, import_node_path5.join)(agentDir, "skills");
4513
4689
  let entries;
4514
4690
  try {
4515
4691
  entries = await (0, import_promises4.readdir)(skillsDir, { withFileTypes: true });
@@ -4521,8 +4697,8 @@ async function listSkills(agentDir) {
4521
4697
  if (!entry.isDirectory()) {
4522
4698
  continue;
4523
4699
  }
4524
- const skillDir = (0, import_node_path4.join)(skillsDir, entry.name);
4525
- const skillMdPath = (0, import_node_path4.join)(skillDir, "SKILL.md");
4700
+ const skillDir = (0, import_node_path5.join)(skillsDir, entry.name);
4701
+ const skillMdPath = (0, import_node_path5.join)(skillDir, "SKILL.md");
4526
4702
  let content;
4527
4703
  try {
4528
4704
  content = await (0, import_promises4.readFile)(skillMdPath, "utf-8");
@@ -4530,7 +4706,7 @@ async function listSkills(agentDir) {
4530
4706
  continue;
4531
4707
  }
4532
4708
  const parsed = parseFrontmatter(content);
4533
- const hasReferences = await dirExists((0, import_node_path4.join)(skillDir, "references"));
4709
+ const hasReferences = await dirExists((0, import_node_path5.join)(skillDir, "references"));
4534
4710
  skills.push({
4535
4711
  name: parsed.frontmatter.name || entry.name,
4536
4712
  description: parsed.frontmatter.description || null,
@@ -4543,7 +4719,7 @@ async function listSkills(agentDir) {
4543
4719
  return skills.sort((a, b) => a.name.localeCompare(b.name));
4544
4720
  }
4545
4721
  async function getSkillDetail(agentDir, skillName) {
4546
- const skillsDir = (0, import_node_path4.join)(agentDir, "skills");
4722
+ const skillsDir = (0, import_node_path5.join)(agentDir, "skills");
4547
4723
  let entries;
4548
4724
  try {
4549
4725
  entries = await (0, import_promises4.readdir)(skillsDir, { withFileTypes: true });
@@ -4554,8 +4730,8 @@ async function getSkillDetail(agentDir, skillName) {
4554
4730
  if (!entry.isDirectory()) {
4555
4731
  continue;
4556
4732
  }
4557
- const skillDir = (0, import_node_path4.join)(skillsDir, entry.name);
4558
- const skillMdPath = (0, import_node_path4.join)(skillDir, "SKILL.md");
4733
+ const skillDir = (0, import_node_path5.join)(skillsDir, entry.name);
4734
+ const skillMdPath = (0, import_node_path5.join)(skillDir, "SKILL.md");
4559
4735
  let content;
4560
4736
  try {
4561
4737
  content = await (0, import_promises4.readFile)(skillMdPath, "utf-8");
@@ -4565,7 +4741,7 @@ async function getSkillDetail(agentDir, skillName) {
4565
4741
  const parsed = parseFrontmatter(content);
4566
4742
  const fmName = parsed.frontmatter.name || entry.name;
4567
4743
  if (entry.name === skillName || fmName === skillName) {
4568
- const hasReferences = await dirExists((0, import_node_path4.join)(skillDir, "references"));
4744
+ const hasReferences = await dirExists((0, import_node_path5.join)(skillDir, "references"));
4569
4745
  return {
4570
4746
  skill: {
4571
4747
  name: fmName,
@@ -4602,7 +4778,7 @@ var BUILT_IN_TOOLS = {
4602
4778
  ]
4603
4779
  };
4604
4780
  async function listAllTools(params) {
4605
- const { profile, agentDir, cwd } = params;
4781
+ const { profile, agentDir, cwd, includeDocyrusWebBrowser } = params;
4606
4782
  const tools = [];
4607
4783
  const builtIn = BUILT_IN_TOOLS[profile] ?? BUILT_IN_TOOLS.coder;
4608
4784
  for (const tool of builtIn) {
@@ -4612,6 +4788,16 @@ async function listAllTools(params) {
4612
4788
  source: "built-in"
4613
4789
  });
4614
4790
  }
4791
+ if (includeDocyrusWebBrowser) {
4792
+ for (const tool of DOCYRUS_WEB_BROWSER_CLIENT_TOOLS) {
4793
+ tools.push({
4794
+ name: tool.name,
4795
+ description: tool.description,
4796
+ source: "built-in",
4797
+ inputSchema: tool.inputSchema
4798
+ });
4799
+ }
4800
+ }
4615
4801
  let config;
4616
4802
  let cache;
4617
4803
  try {
@@ -4661,6 +4847,13 @@ async function listAllTools(params) {
4661
4847
  function generateMessageId() {
4662
4848
  return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
4663
4849
  }
4850
+ function getLastAssistantMessage(messages) {
4851
+ if (messages.length === 0) {
4852
+ return void 0;
4853
+ }
4854
+ const lastMessage = messages[messages.length - 1];
4855
+ return lastMessage.role === "assistant" ? lastMessage : void 0;
4856
+ }
4664
4857
  function extractLastUserText(messages) {
4665
4858
  if (messages.length === 0) {
4666
4859
  return void 0;
@@ -4677,21 +4870,58 @@ function extractLastUserText(messages) {
4677
4870
  return void 0;
4678
4871
  }
4679
4872
  function extractAskUserToolResponse(messages) {
4680
- for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex -= 1) {
4681
- const message = messages[messageIndex];
4682
- if (message.role !== "assistant") {
4683
- continue;
4873
+ const message = getLastAssistantMessage(messages);
4874
+ if (!message) {
4875
+ return void 0;
4876
+ }
4877
+ for (let partIndex = message.parts.length - 1; partIndex >= 0; partIndex -= 1) {
4878
+ const part = message.parts[partIndex];
4879
+ if (part.type === "dynamic-tool" && part.toolName === "ask_user" && part.state === "output-available" && typeof part.toolCallId === "string") {
4880
+ const response = parseAskUserResponseFromToolOutput(part.output);
4881
+ if (response) {
4882
+ return {
4883
+ toolCallId: part.toolCallId,
4884
+ response
4885
+ };
4886
+ }
4684
4887
  }
4685
- for (let partIndex = message.parts.length - 1; partIndex >= 0; partIndex -= 1) {
4686
- const part = message.parts[partIndex];
4687
- if (part.type === "dynamic-tool" && part.toolName === "ask_user" && part.state === "output-available" && typeof part.toolCallId === "string") {
4688
- const response = parseAskUserResponseFromToolOutput(part.output);
4689
- if (response) {
4690
- return {
4691
- toolCallId: part.toolCallId,
4692
- response
4693
- };
4694
- }
4888
+ }
4889
+ return void 0;
4890
+ }
4891
+ function extractDocyrusWebBrowserToolResponse(messages) {
4892
+ const message = getLastAssistantMessage(messages);
4893
+ if (!message) {
4894
+ return void 0;
4895
+ }
4896
+ for (let partIndex = message.parts.length - 1; partIndex >= 0; partIndex -= 1) {
4897
+ const part = message.parts[partIndex];
4898
+ if (part.type === "dynamic-tool" && isDocyrusWebBrowserToolName(part.toolName) && typeof part.toolCallId === "string" && (part.state === "output-available" || part.state === "output-error")) {
4899
+ const errorText = typeof part.errorText === "string" ? part.errorText : typeof part.output === "string" && part.state === "output-error" ? part.output : void 0;
4900
+ return {
4901
+ toolCallId: part.toolCallId,
4902
+ toolName: part.toolName,
4903
+ output: part.state === "output-available" ? part.output : void 0,
4904
+ errorText,
4905
+ isError: part.state === "output-error"
4906
+ };
4907
+ }
4908
+ }
4909
+ return void 0;
4910
+ }
4911
+ function extractDocyrusWebBrowserToolRequest(messages, toolCallId) {
4912
+ const message = getLastAssistantMessage(messages);
4913
+ if (!message) {
4914
+ return void 0;
4915
+ }
4916
+ for (let partIndex = message.parts.length - 1; partIndex >= 0; partIndex -= 1) {
4917
+ const part = message.parts[partIndex];
4918
+ if (part.type === "dynamic-tool" && isDocyrusWebBrowserToolName(part.toolName) && part.toolCallId === toolCallId) {
4919
+ const request = normalizeDocyrusWebBrowserToolRequest({
4920
+ tool: part.toolName,
4921
+ input: part.input
4922
+ });
4923
+ if (request) {
4924
+ return request;
4695
4925
  }
4696
4926
  }
4697
4927
  }
@@ -4797,6 +5027,17 @@ function convertSessionEntriesToUIMessages(entries) {
4797
5027
  });
4798
5028
  continue;
4799
5029
  }
5030
+ const docyrusWebBrowserRequest = parseDocyrusWebBrowserRequestFromText(block.text);
5031
+ if (docyrusWebBrowserRequest) {
5032
+ parts.push({
5033
+ type: "dynamic-tool",
5034
+ toolCallId: createDocyrusWebBrowserToolCallId(docyrusWebBrowserRequest),
5035
+ toolName: docyrusWebBrowserRequest.tool,
5036
+ state: "input-available",
5037
+ input: docyrusWebBrowserRequest.input ?? {}
5038
+ });
5039
+ continue;
5040
+ }
4800
5041
  parts.push({ type: "text", text: block.text });
4801
5042
  } else if (block.type === "thinking" && typeof block.thinking === "string") {
4802
5043
  parts.push({ type: "reasoning", text: block.thinking, state: "complete" });
@@ -4841,8 +5082,8 @@ var FS_IGNORE = /* @__PURE__ */ new Set([
4841
5082
  ".svelte-kit"
4842
5083
  ]);
4843
5084
  function resolveSafePath(cwd, requestPath) {
4844
- const resolved = (0, import_node_path5.resolve)(cwd, requestPath);
4845
- const normalizedCwd = cwd.endsWith(import_node_path5.sep) ? cwd : cwd + import_node_path5.sep;
5085
+ const resolved = (0, import_node_path6.resolve)(cwd, requestPath);
5086
+ const normalizedCwd = cwd.endsWith(import_node_path6.sep) ? cwd : cwd + import_node_path6.sep;
4846
5087
  if (resolved !== cwd && !resolved.startsWith(normalizedCwd)) {
4847
5088
  throw new Error("Path escapes working directory");
4848
5089
  }
@@ -4879,8 +5120,8 @@ async function buildTree(params) {
4879
5120
  if (ignore.has(entry.name)) {
4880
5121
  continue;
4881
5122
  }
4882
- const fullPath = (0, import_node_path5.join)(dir, entry.name);
4883
- const relativePath = (0, import_node_path5.relative)(cwd, fullPath);
5123
+ const fullPath = (0, import_node_path6.join)(dir, entry.name);
5124
+ const relativePath = (0, import_node_path6.relative)(cwd, fullPath);
4884
5125
  if (entry.isDirectory()) {
4885
5126
  const children = await buildTree({
4886
5127
  dir: fullPath,
@@ -4917,8 +5158,8 @@ async function walkFiles(params) {
4917
5158
  if (ignore.has(entry.name)) {
4918
5159
  continue;
4919
5160
  }
4920
- const fullPath = (0, import_node_path5.join)(dir, entry.name);
4921
- const relativePath = (0, import_node_path5.relative)(cwd, fullPath);
5161
+ const fullPath = (0, import_node_path6.join)(dir, entry.name);
5162
+ const relativePath = (0, import_node_path6.relative)(cwd, fullPath);
4922
5163
  if (entry.isDirectory()) {
4923
5164
  await walkFiles({ dir: fullPath, cwd, pattern, ignore, maxResults, results });
4924
5165
  } else if (entry.isFile() && pattern.test(relativePath)) {
@@ -4930,6 +5171,7 @@ async function createAgentServer(params) {
4930
5171
  const { port, sessionManager, modelRegistry, authRuntime, context, onCreateSession, onResumeSession, authToken } = params;
4931
5172
  let activeSession = params.session;
4932
5173
  const pendingAskUserRequests = /* @__PURE__ */ new Map();
5174
+ const pendingDocyrusWebBrowserRequests = /* @__PURE__ */ new Map();
4933
5175
  const oauthFlowManager = new OAuthFlowManager();
4934
5176
  const app = new Hono2();
4935
5177
  function getModelIdsByProvider() {
@@ -4983,14 +5225,31 @@ async function createAgentServer(params) {
4983
5225
  }
4984
5226
  const sessionId = body.sessionId?.trim() || activeSession.id?.trim() || "active";
4985
5227
  const askUserResponse = extractAskUserToolResponse(messages);
5228
+ const docyrusWebBrowserResponse = extractDocyrusWebBrowserToolResponse(messages);
4986
5229
  const pendingAskUser = pendingAskUserRequests.get(sessionId);
4987
- const userMessage = askUserResponse ? pendingAskUser && pendingAskUser.toolCallId === askUserResponse.toolCallId ? formatAskUserResponsePrompt(askUserResponse.response) : void 0 : extractLastUserText(messages);
5230
+ const pendingDocyrusWebBrowser = pendingDocyrusWebBrowserRequests.get(sessionId);
5231
+ const pendingDocyrusWebBrowserRequest = docyrusWebBrowserResponse ? pendingDocyrusWebBrowser?.get(docyrusWebBrowserResponse.toolCallId) ?? extractDocyrusWebBrowserToolRequest(messages, docyrusWebBrowserResponse.toolCallId) : void 0;
5232
+ const userMessage = askUserResponse ? pendingAskUser && pendingAskUser.toolCallId === askUserResponse.toolCallId ? formatAskUserResponsePrompt(askUserResponse.response) : void 0 : docyrusWebBrowserResponse ? pendingDocyrusWebBrowserRequest ? formatDocyrusWebBrowserToolResponsePrompt({
5233
+ tool: docyrusWebBrowserResponse.toolName,
5234
+ request: pendingDocyrusWebBrowserRequest.input,
5235
+ status: docyrusWebBrowserResponse.isError ? "error" : "success",
5236
+ output: docyrusWebBrowserResponse.output,
5237
+ errorText: docyrusWebBrowserResponse.errorText
5238
+ }) : void 0 : extractLastUserText(messages);
4988
5239
  if (!userMessage) {
4989
- return c.json({ error: askUserResponse ? "No matching pending ask_user request found" : "No user message found" }, 400);
5240
+ return c.json({
5241
+ error: askUserResponse ? "No matching pending ask_user request found" : docyrusWebBrowserResponse ? "No matching pending docyrus-web-browser request found" : "No user message found"
5242
+ }, 400);
4990
5243
  }
4991
5244
  if (askUserResponse) {
4992
5245
  pendingAskUserRequests.delete(sessionId);
4993
5246
  }
5247
+ if (docyrusWebBrowserResponse && pendingDocyrusWebBrowser) {
5248
+ pendingDocyrusWebBrowser.delete(docyrusWebBrowserResponse.toolCallId);
5249
+ if (pendingDocyrusWebBrowser.size === 0) {
5250
+ pendingDocyrusWebBrowserRequests.delete(sessionId);
5251
+ }
5252
+ }
4994
5253
  if (activeSession.isStreaming) {
4995
5254
  await activeSession.abort();
4996
5255
  await waitForIdle(activeSession);
@@ -5012,6 +5271,11 @@ async function createAgentServer(params) {
5012
5271
  onAskUser: ({ toolCallId, request }) => {
5013
5272
  pendingAskUserRequests.set(sessionId, { toolCallId, request });
5014
5273
  },
5274
+ onDocyrusWebBrowserTool: ({ toolCallId, request }) => {
5275
+ const pendingForSession = pendingDocyrusWebBrowserRequests.get(sessionId) ?? /* @__PURE__ */ new Map();
5276
+ pendingForSession.set(toolCallId, request);
5277
+ pendingDocyrusWebBrowserRequests.set(sessionId, pendingForSession);
5278
+ },
5015
5279
  onDone: () => {
5016
5280
  writeChunk({ type: "finish-step" });
5017
5281
  writeChunk({ type: "finish" });
@@ -5194,6 +5458,7 @@ async function createAgentServer(params) {
5194
5458
  await refreshSessionAfterCredentialChange({
5195
5459
  session: activeSession,
5196
5460
  modelRegistry,
5461
+ envStore: authRuntime.envStore,
5197
5462
  preferredProviderId: result.providerId,
5198
5463
  preferredModelId: result.preferredModelId
5199
5464
  });
@@ -5225,6 +5490,7 @@ async function createAgentServer(params) {
5225
5490
  await refreshSessionAfterCredentialChange({
5226
5491
  session: activeSession,
5227
5492
  modelRegistry,
5493
+ envStore: authRuntime.envStore,
5228
5494
  preferredProviderId: providerId
5229
5495
  });
5230
5496
  }
@@ -5256,7 +5522,8 @@ async function createAgentServer(params) {
5256
5522
  modelRegistry.refresh();
5257
5523
  await refreshSessionAfterCredentialChange({
5258
5524
  session: activeSession,
5259
- modelRegistry
5525
+ modelRegistry,
5526
+ envStore: authRuntime.envStore
5260
5527
  });
5261
5528
  return c.json({
5262
5529
  ok: true,
@@ -5383,7 +5650,7 @@ async function createAgentServer(params) {
5383
5650
  }
5384
5651
  try {
5385
5652
  const resolved = resolveSafePath(context.cwd, body.path);
5386
- await (0, import_promises5.mkdir)((0, import_node_path5.join)(resolved, ".."), { recursive: true });
5653
+ await (0, import_promises5.mkdir)((0, import_node_path6.join)(resolved, ".."), { recursive: true });
5387
5654
  await (0, import_promises5.writeFile)(resolved, body.content, "utf-8");
5388
5655
  const fileStat = await (0, import_promises5.stat)(resolved);
5389
5656
  return c.json({ ok: true, path: body.path, size: fileStat.size });
@@ -5414,7 +5681,7 @@ async function createAgentServer(params) {
5414
5681
  try {
5415
5682
  const resolvedFrom = resolveSafePath(context.cwd, body.from);
5416
5683
  const resolvedTo = resolveSafePath(context.cwd, body.to);
5417
- await (0, import_promises5.mkdir)((0, import_node_path5.join)(resolvedTo, ".."), { recursive: true });
5684
+ await (0, import_promises5.mkdir)((0, import_node_path6.join)(resolvedTo, ".."), { recursive: true });
5418
5685
  await (0, import_promises5.rename)(resolvedFrom, resolvedTo);
5419
5686
  return c.json({ ok: true, from: body.from, to: body.to });
5420
5687
  } catch (error) {
@@ -5443,7 +5710,7 @@ async function createAgentServer(params) {
5443
5710
  }
5444
5711
  });
5445
5712
  const CLI_EXEC = process.env.DOCYRUS_CLI_EXECUTABLE || process.execPath;
5446
- const CLI_ENTRY = process.env.DOCYRUS_CLI_ENTRY || (0, import_node_path5.resolve)(process.argv[1] ? (0, import_node_path5.join)(process.argv[1], "..") : __dirname, "main.js");
5713
+ const CLI_ENTRY = process.env.DOCYRUS_CLI_ENTRY || (0, import_node_path6.resolve)(process.argv[1] ? (0, import_node_path6.join)(process.argv[1], "..") : __dirname, "main.js");
5447
5714
  const CLI_SCOPE = process.env.DOCYRUS_CLI_SCOPE;
5448
5715
  const CLI_TIMEOUT_MS = 3e4;
5449
5716
  function runCliCommand(args) {
@@ -5493,7 +5760,7 @@ async function createAgentServer(params) {
5493
5760
  }
5494
5761
  async function detectDevPort(cwd) {
5495
5762
  try {
5496
- const pkg = JSON.parse(await (0, import_promises5.readFile)((0, import_node_path5.join)(cwd, "package.json"), "utf-8"));
5763
+ const pkg = JSON.parse(await (0, import_promises5.readFile)((0, import_node_path6.join)(cwd, "package.json"), "utf-8"));
5497
5764
  const devScript = pkg.scripts?.dev;
5498
5765
  if (devScript) {
5499
5766
  const portFlag = devScript.match(/--port\s+(\d+)/);
@@ -5509,7 +5776,7 @@ async function createAgentServer(params) {
5509
5776
  }
5510
5777
  for (const name of ["vite.config.ts", "vite.config.mts", "vite.config.js"]) {
5511
5778
  try {
5512
- const content = await (0, import_promises5.readFile)((0, import_node_path5.join)(cwd, name), "utf-8");
5779
+ const content = await (0, import_promises5.readFile)((0, import_node_path6.join)(cwd, name), "utf-8");
5513
5780
  const portMatch = content.match(/port\s*:\s*(\d+)/);
5514
5781
  if (portMatch) {
5515
5782
  return Number(portMatch[1]);
@@ -5519,19 +5786,19 @@ async function createAgentServer(params) {
5519
5786
  }
5520
5787
  for (const name of ["next.config.ts", "next.config.mts", "next.config.js", "next.config.mjs"]) {
5521
5788
  try {
5522
- await (0, import_promises5.stat)((0, import_node_path5.join)(cwd, name));
5789
+ await (0, import_promises5.stat)((0, import_node_path6.join)(cwd, name));
5523
5790
  return 3e3;
5524
5791
  } catch {
5525
5792
  }
5526
5793
  }
5527
5794
  try {
5528
- await (0, import_promises5.stat)((0, import_node_path5.join)(cwd, "angular.json"));
5795
+ await (0, import_promises5.stat)((0, import_node_path6.join)(cwd, "angular.json"));
5529
5796
  return 4200;
5530
5797
  } catch {
5531
5798
  }
5532
5799
  for (const name of ["nuxt.config.ts", "nuxt.config.js"]) {
5533
5800
  try {
5534
- await (0, import_promises5.stat)((0, import_node_path5.join)(cwd, name));
5801
+ await (0, import_promises5.stat)((0, import_node_path6.join)(cwd, name));
5535
5802
  return 3e3;
5536
5803
  } catch {
5537
5804
  }
@@ -5561,14 +5828,14 @@ async function createAgentServer(params) {
5561
5828
  } catch {
5562
5829
  }
5563
5830
  try {
5564
- const pkg = JSON.parse(await (0, import_promises5.readFile)((0, import_node_path5.join)(cwd, "package.json"), "utf-8"));
5831
+ const pkg = JSON.parse(await (0, import_promises5.readFile)((0, import_node_path6.join)(cwd, "package.json"), "utf-8"));
5565
5832
  packageName = pkg.name ?? null;
5566
5833
  packageVersion = pkg.version ?? null;
5567
5834
  } catch {
5568
5835
  }
5569
5836
  cachedProjectInfo = {
5570
5837
  path: cwd,
5571
- folder: (0, import_node_path5.basename)(cwd),
5838
+ folder: (0, import_node_path6.basename)(cwd),
5572
5839
  repo,
5573
5840
  packageName,
5574
5841
  packageVersion
@@ -5779,7 +6046,7 @@ async function createAgentServer(params) {
5779
6046
  }
5780
6047
  if (entry.status !== "deleted") {
5781
6048
  try {
5782
- const resolved = (0, import_node_path5.resolve)(cwd, entry.path);
6049
+ const resolved = (0, import_node_path6.resolve)(cwd, entry.path);
5783
6050
  const buf = await (0, import_promises5.readFile)(resolved);
5784
6051
  if (buf.subarray(0, 8192).includes(0)) {
5785
6052
  return null;
@@ -5958,7 +6225,7 @@ async function createAgentServer(params) {
5958
6225
  });
5959
6226
  app.get("/api/skills", async (c) => {
5960
6227
  try {
5961
- const skills = await listSkills(context.agentDir);
6228
+ const skills = (await listSkills(context.agentDir)).filter((skill) => skill.name !== "docyrus-chrome-devtools-cli");
5962
6229
  return c.json({ skills });
5963
6230
  } catch (error) {
5964
6231
  const message = error instanceof Error ? error.message : String(error);
@@ -5968,6 +6235,9 @@ async function createAgentServer(params) {
5968
6235
  app.get("/api/skills/:skillName", async (c) => {
5969
6236
  const skillName = c.req.param("skillName");
5970
6237
  try {
6238
+ if (skillName === "docyrus-chrome-devtools-cli") {
6239
+ return c.json({ error: `Skill "${skillName}" not found` }, 404);
6240
+ }
5971
6241
  const result = await getSkillDetail(context.agentDir, skillName);
5972
6242
  if (!result) {
5973
6243
  return c.json({ error: `Skill "${skillName}" not found` }, 404);
@@ -5983,7 +6253,8 @@ async function createAgentServer(params) {
5983
6253
  const tools = await listAllTools({
5984
6254
  profile: context.profile,
5985
6255
  agentDir: context.agentDir,
5986
- cwd: context.cwd
6256
+ cwd: context.cwd,
6257
+ includeDocyrusWebBrowser: true
5987
6258
  });
5988
6259
  const builtInCount = tools.filter((t) => t.source === "built-in").length;
5989
6260
  const mcpCount = tools.filter((t) => t.source !== "built-in").length;
@@ -6288,31 +6559,22 @@ function readLoaderRequest() {
6288
6559
  }
6289
6560
  async function loadPiExports() {
6290
6561
  const piPackageDir = readRequiredEnv("PI_PACKAGE_DIR");
6291
- const moduleUrl = (0, import_node_url.pathToFileURL)((0, import_node_path6.join)(piPackageDir, "dist", "index.js")).href;
6562
+ const moduleUrl = (0, import_node_url.pathToFileURL)((0, import_node_path7.join)(piPackageDir, "dist", "index.js")).href;
6292
6563
  return await import(moduleUrl);
6293
6564
  }
6294
6565
  function resolvePackagedPiResourceRoot() {
6295
6566
  const candidates = [
6296
- (0, import_node_path6.resolve)(process.cwd(), "apps/api-cli/resources/pi-agent"),
6297
- (0, import_node_path6.resolve)(__dirname, "../resources/pi-agent"),
6298
- (0, import_node_path6.resolve)(__dirname, "resources/pi-agent"),
6299
- (0, import_node_path6.resolve)(process.cwd(), "dist/apps/api-cli/resources/pi-agent")
6567
+ (0, import_node_path7.resolve)(process.cwd(), "apps/api-cli/resources/pi-agent"),
6568
+ (0, import_node_path7.resolve)(__dirname, "../resources/pi-agent"),
6569
+ (0, import_node_path7.resolve)(__dirname, "resources/pi-agent"),
6570
+ (0, import_node_path7.resolve)(process.cwd(), "dist/apps/api-cli/resources/pi-agent")
6300
6571
  ];
6301
- const resolved = candidates.find((candidate) => (0, import_node_fs.existsSync)(candidate));
6572
+ const resolved = candidates.find((candidate) => (0, import_node_fs2.existsSync)(candidate));
6302
6573
  if (!resolved) {
6303
6574
  throw new Error(`Unable to locate pi agent resources. Checked: ${candidates.join(", ")}`);
6304
6575
  }
6305
6576
  return resolved;
6306
6577
  }
6307
- function resolvePackagedExtensionPaths(resourceRoot) {
6308
- const extensionsRoot = (0, import_node_path6.join)(resourceRoot, "extensions");
6309
- if (!(0, import_node_fs.existsSync)(extensionsRoot)) {
6310
- return [];
6311
- }
6312
- return (0, import_node_fs.readdirSync)(extensionsRoot, {
6313
- withFileTypes: true
6314
- }).filter((entry) => entry.isDirectory() || entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js"))).map((entry) => (0, import_node_path6.join)(extensionsRoot, entry.name)).sort((left, right) => left.localeCompare(right));
6315
- }
6316
6578
  function setProcessArgValue(flag, value) {
6317
6579
  const existingIndex = process.argv.indexOf(flag);
6318
6580
  if (existingIndex >= 0) {
@@ -6424,17 +6686,17 @@ async function main() {
6424
6686
  const agentDir = readRequiredEnv("PI_CODING_AGENT_DIR");
6425
6687
  const version = process.env.DOCYRUS_PI_VERSION || "dev";
6426
6688
  const resourceRoot = resolvePackagedPiResourceRoot();
6427
- const packagedExtensionPaths = resolvePackagedExtensionPaths(resourceRoot);
6428
- const mcpConfigPath = (0, import_node_path6.join)(agentDir, "mcp.json");
6689
+ const packagedExtensionPaths = resolvePackagedExtensionPaths(resourceRoot, "server");
6690
+ const mcpConfigPath = (0, import_node_path7.join)(agentDir, "mcp.json");
6429
6691
  const hasPackagedMcpAdapter = packagedExtensionPaths.some((extensionPath) => extensionPath.includes("pi-mcp-adapter"));
6430
- const envStore = new AgentEnvStore((0, import_node_path6.join)(agentDir, "env.json"));
6692
+ const envStore = new AgentEnvStore((0, import_node_path7.join)(agentDir, "env.json"));
6431
6693
  await envStore.hydrateProcessEnv(process.env);
6432
6694
  if (hasPackagedMcpAdapter) {
6433
6695
  setProcessArgValue("--mcp-config", mcpConfigPath);
6434
6696
  }
6435
- const authStorage = pi.AuthStorage.create((0, import_node_path6.join)(agentDir, "auth.json"));
6697
+ const authStorage = pi.AuthStorage.create((0, import_node_path7.join)(agentDir, "auth.json"));
6436
6698
  const settingsManager = pi.SettingsManager.create(cwd, agentDir);
6437
- const modelsJsonPath = (0, import_node_path6.join)(agentDir, "models.json");
6699
+ const modelsJsonPath = (0, import_node_path7.join)(agentDir, "models.json");
6438
6700
  const modelRegistry = new pi.ModelRegistry(authStorage, modelsJsonPath);
6439
6701
  const quietStartup = !request.verbose;
6440
6702
  if (quietStartup) {
@@ -6463,7 +6725,11 @@ async function main() {
6463
6725
  agentDir,
6464
6726
  settingsManager,
6465
6727
  additionalExtensionPaths: packagedExtensionPaths,
6466
- systemPrompt: (0, import_node_path6.join)(
6728
+ skillsOverride: ({ skills, diagnostics }) => ({
6729
+ skills: skills.filter((skill) => skill.name !== "docyrus-chrome-devtools-cli"),
6730
+ diagnostics
6731
+ }),
6732
+ systemPrompt: (0, import_node_path7.join)(
6467
6733
  resourceRoot,
6468
6734
  "prompts",
6469
6735
  request.profile === "agent" ? "agent-system.md" : "coder-system.md"