@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/agent-loader.js CHANGED
@@ -1132,9 +1132,9 @@ ${J2}${i.trimStart()}`), r2 = 3 + (0, import_node_util.stripVTControlCharacters)
1132
1132
  });
1133
1133
 
1134
1134
  // src/agent/loader.ts
1135
- var import_node_fs = require("node:fs");
1135
+ var import_node_fs2 = require("node:fs");
1136
1136
  var import_node_url = require("node:url");
1137
- var import_node_path3 = require("node:path");
1137
+ var import_node_path4 = require("node:path");
1138
1138
  var import_picocolors4 = __toESM(require_picocolors());
1139
1139
 
1140
1140
  // src/agent/envStore.ts
@@ -1235,9 +1235,29 @@ var AgentEnvStore = class {
1235
1235
  }
1236
1236
  };
1237
1237
 
1238
+ // src/agent/packagedExtensions.ts
1239
+ var import_node_fs = require("node:fs");
1240
+ var import_node_path2 = require("node:path");
1241
+ var SERVER_ONLY_PACKAGED_EXTENSION_NAMES = /* @__PURE__ */ new Set(["docyrus-web-browser"]);
1242
+ function isPackagedExtensionEntry(entryName, isDirectory) {
1243
+ return isDirectory || entryName.endsWith(".ts") || entryName.endsWith(".js");
1244
+ }
1245
+ function getPackagedExtensionName(entryName) {
1246
+ return entryName.replace(/\.(ts|js)$/u, "");
1247
+ }
1248
+ function resolvePackagedExtensionPaths(resourceRoot, runtime = "terminal") {
1249
+ const extensionsRoot = (0, import_node_path2.join)(resourceRoot, "extensions");
1250
+ if (!(0, import_node_fs.existsSync)(extensionsRoot)) {
1251
+ return [];
1252
+ }
1253
+ return (0, import_node_fs.readdirSync)(extensionsRoot, {
1254
+ withFileTypes: true
1255
+ }).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));
1256
+ }
1257
+
1238
1258
  // src/agent/modelsConfig.ts
1239
1259
  var import_promises2 = require("node:fs/promises");
1240
- var import_node_path2 = require("node:path");
1260
+ var import_node_path3 = require("node:path");
1241
1261
  function createDefaultState2() {
1242
1262
  return {
1243
1263
  providers: {}
@@ -1261,7 +1281,7 @@ async function readModelsConfig(filePath) {
1261
1281
  }
1262
1282
  }
1263
1283
  async function writeModelsConfig(filePath, state) {
1264
- const directory = (0, import_node_path2.dirname)(filePath);
1284
+ const directory = (0, import_node_path3.dirname)(filePath);
1265
1285
  await (0, import_promises2.mkdir)(directory, {
1266
1286
  recursive: true,
1267
1287
  mode: 448
@@ -1316,7 +1336,7 @@ function createCustomOpenAiProviderConfig(params) {
1316
1336
  function createAzureProviderConfig(params) {
1317
1337
  const providerConfig = {
1318
1338
  baseUrl: params.baseUrl,
1319
- apiKey: "env:AZURE_OPENAI_API_KEY"
1339
+ apiKey: "AZURE_OPENAI_API_KEY"
1320
1340
  };
1321
1341
  if (params.useCustomModel) {
1322
1342
  providerConfig.api = "azure-openai-responses";
@@ -1345,6 +1365,22 @@ function trimOrUndefined(value) {
1345
1365
  const trimmed = value?.trim();
1346
1366
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
1347
1367
  }
1368
+ function normalizeAzureBaseUrl(baseUrl) {
1369
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
1370
+ try {
1371
+ const url = new URL(trimmed);
1372
+ url.search = "";
1373
+ url.hash = "";
1374
+ if (url.pathname.endsWith("/openai/v1")) {
1375
+ url.pathname = url.pathname.slice(0, -3);
1376
+ } else if (url.pathname.endsWith("/openai/responses")) {
1377
+ url.pathname = url.pathname.slice(0, -10);
1378
+ }
1379
+ return url.toString().replace(/\/+$/, "");
1380
+ } catch {
1381
+ return trimmed.replace(/\/openai\/v1$/i, "/openai").replace(/\/openai\/responses$/i, "/openai");
1382
+ }
1383
+ }
1348
1384
  async function saveGenericApiKey(params) {
1349
1385
  params.authStorage.set(params.providerId, {
1350
1386
  type: "api_key",
@@ -1371,6 +1407,7 @@ async function saveCustomOpenAiConfig(params) {
1371
1407
  async function saveAzureConfig(params) {
1372
1408
  const modelId = params.modelId.trim();
1373
1409
  const useCustomModel = params.useCustomModel ?? false;
1410
+ const normalizedBaseUrl = normalizeAzureBaseUrl(params.baseUrl);
1374
1411
  params.authStorage.set("azure-openai-responses", {
1375
1412
  type: "api_key",
1376
1413
  key: params.apiKey.trim()
@@ -1395,7 +1432,7 @@ async function saveAzureConfig(params) {
1395
1432
  }
1396
1433
  await params.envStore.setMany(envValues);
1397
1434
  await upsertModelsProvider(params.modelsJsonPath, "azure-openai-responses", createAzureProviderConfig({
1398
- baseUrl: params.baseUrl.trim(),
1435
+ baseUrl: normalizedBaseUrl,
1399
1436
  modelId,
1400
1437
  useCustomModel
1401
1438
  }));
@@ -1659,7 +1696,7 @@ function getProviderFormFields(params) {
1659
1696
  title: "Azure OpenAI base URL",
1660
1697
  required: true,
1661
1698
  component: "text",
1662
- placeholder: "https://my-resource.openai.azure.com/openai/v1",
1699
+ placeholder: "https://my-resource.openai.azure.com/openai",
1663
1700
  dependsOn: { field: "configMode", equals: "base-url" }
1664
1701
  },
1665
1702
  {
@@ -1688,8 +1725,8 @@ function getProviderFormFields(params) {
1688
1725
  name: "apiVersion",
1689
1726
  title: "API version",
1690
1727
  component: "text",
1691
- defaultValue: "2025-03-01-preview",
1692
- placeholder: "2025-03-01-preview"
1728
+ defaultValue: "2025-04-01-preview",
1729
+ placeholder: "2025-04-01-preview"
1693
1730
  }
1694
1731
  ];
1695
1732
  case "amazon-bedrock":
@@ -1763,9 +1800,14 @@ function getProviderFormFields(params) {
1763
1800
  }
1764
1801
  }
1765
1802
  async function refreshSessionAfterCredentialChange(params) {
1803
+ await params.envStore?.hydrateProcessEnv(process.env);
1766
1804
  params.modelRegistry.refresh();
1767
1805
  const availableModels = params.modelRegistry.getAvailable();
1768
1806
  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;
1807
+ if (preferredModel) {
1808
+ await params.session.setModel(preferredModel);
1809
+ return;
1810
+ }
1769
1811
  const currentModel = params.session.model;
1770
1812
  const currentModelStillAvailable = currentModel ? availableModels.some((model) => model.provider === currentModel.provider && model.id === currentModel.id) : false;
1771
1813
  if (currentModel && !currentModelStillAvailable) {
@@ -1854,11 +1896,12 @@ async function showInput(mode, title, placeholder) {
1854
1896
  });
1855
1897
  });
1856
1898
  }
1857
- async function refreshAfterCredentialChange(mode, preferredProviderId, preferredModelId) {
1899
+ async function refreshAfterCredentialChange(mode, envStore, preferredProviderId, preferredModelId) {
1858
1900
  const modeAny = modeAsAny(mode);
1859
1901
  await refreshSessionAfterCredentialChange({
1860
1902
  session: modeAny.session,
1861
1903
  modelRegistry: modeAny.session.modelRegistry,
1904
+ envStore,
1862
1905
  preferredProviderId,
1863
1906
  preferredModelId
1864
1907
  });
@@ -1896,7 +1939,7 @@ async function runApiKeyProviderFlow(mode, dependencies, provider) {
1896
1939
  apiKey,
1897
1940
  modelId
1898
1941
  });
1899
- await refreshAfterCredentialChange(mode, "custom-openai", modelId);
1942
+ await refreshAfterCredentialChange(mode, dependencies.envStore, "custom-openai", modelId);
1900
1943
  modeAny.showStatus(`Configured ${provider.label}`);
1901
1944
  return;
1902
1945
  }
@@ -1929,7 +1972,7 @@ async function runApiKeyProviderFlow(mode, dependencies, provider) {
1929
1972
  } else {
1930
1973
  const resourceName = await showInput(mode, resourceNameField?.title || "Azure resource name", resourceNameField?.placeholder);
1931
1974
  if (resourceName) {
1932
- baseUrl = `https://${resourceName}.openai.azure.com/openai/v1`;
1975
+ baseUrl = `https://${resourceName}.openai.azure.com/openai`;
1933
1976
  }
1934
1977
  }
1935
1978
  if (!baseUrl) {
@@ -1954,7 +1997,7 @@ async function runApiKeyProviderFlow(mode, dependencies, provider) {
1954
1997
  apiVersion,
1955
1998
  useCustomModel: !builtInModelIds.has(modelId)
1956
1999
  });
1957
- await refreshAfterCredentialChange(mode, "azure-openai-responses", modelId);
2000
+ await refreshAfterCredentialChange(mode, dependencies.envStore, "azure-openai-responses", modelId);
1958
2001
  modeAny.showStatus(`Configured ${provider.label}`);
1959
2002
  return;
1960
2003
  }
@@ -2017,7 +2060,7 @@ async function runApiKeyProviderFlow(mode, dependencies, provider) {
2017
2060
  secretAccessKey,
2018
2061
  sessionToken
2019
2062
  });
2020
- await refreshAfterCredentialChange(mode, "amazon-bedrock", modelId);
2063
+ await refreshAfterCredentialChange(mode, dependencies.envStore, "amazon-bedrock", modelId);
2021
2064
  modeAny.showStatus(`Configured ${provider.label}`);
2022
2065
  return;
2023
2066
  }
@@ -2032,7 +2075,7 @@ async function runApiKeyProviderFlow(mode, dependencies, provider) {
2032
2075
  providerId: provider.id,
2033
2076
  apiKey
2034
2077
  });
2035
- await refreshAfterCredentialChange(mode, provider.id);
2078
+ await refreshAfterCredentialChange(mode, dependencies.envStore, provider.id);
2036
2079
  modeAny.showStatus(`Configured ${provider.label}`);
2037
2080
  }
2038
2081
  }
@@ -2091,7 +2134,7 @@ async function handleInteractiveLogout(mode, dependencies) {
2091
2134
  ...dependencies,
2092
2135
  providerId
2093
2136
  });
2094
- await refreshAfterCredentialChange(mode);
2137
+ await refreshAfterCredentialChange(mode, dependencies.envStore);
2095
2138
  modeAny.showStatus(`Removed ${getProviderLabel(providerId)}`);
2096
2139
  } catch (error) {
2097
2140
  modeAny.showError(`Failed to remove ${getProviderLabel(providerId)}: ${error instanceof Error ? error.message : String(error)}`);
@@ -2307,7 +2350,7 @@ async function runAzureFlow(clack, pico, dependencies) {
2307
2350
  if (configMode === "base-url") {
2308
2351
  const baseUrlInput = await clack.text({
2309
2352
  message: "Azure OpenAI base URL:",
2310
- placeholder: "https://my-resource.openai.azure.com/openai/v1",
2353
+ placeholder: "https://my-resource.openai.azure.com/openai",
2311
2354
  validate: (value) => value?.trim() ? void 0 : "Base URL is required"
2312
2355
  });
2313
2356
  if (clack.isCancel(baseUrlInput) || !baseUrlInput) {
@@ -2323,7 +2366,7 @@ async function runAzureFlow(clack, pico, dependencies) {
2323
2366
  if (clack.isCancel(resourceName) || !resourceName) {
2324
2367
  return false;
2325
2368
  }
2326
- baseUrl = `https://${String(resourceName).trim()}.openai.azure.com/openai/v1`;
2369
+ baseUrl = `https://${String(resourceName).trim()}.openai.azure.com/openai`;
2327
2370
  }
2328
2371
  const modelId = await clack.text({
2329
2372
  message: "Model ID to use:",
@@ -2342,7 +2385,7 @@ async function runAzureFlow(clack, pico, dependencies) {
2342
2385
  }
2343
2386
  const apiVersion = await clack.text({
2344
2387
  message: `API version ${pico.dim("(leave blank to use pi's default)")}:`,
2345
- placeholder: "2025-03-01-preview"
2388
+ placeholder: "2025-04-01-preview"
2346
2389
  });
2347
2390
  if (clack.isCancel(apiVersion)) {
2348
2391
  return false;
@@ -2591,31 +2634,22 @@ function readLoaderRequest() {
2591
2634
  }
2592
2635
  async function loadPiExports() {
2593
2636
  const piPackageDir = readRequiredEnv("PI_PACKAGE_DIR");
2594
- const moduleUrl = (0, import_node_url.pathToFileURL)((0, import_node_path3.join)(piPackageDir, "dist", "index.js")).href;
2637
+ const moduleUrl = (0, import_node_url.pathToFileURL)((0, import_node_path4.join)(piPackageDir, "dist", "index.js")).href;
2595
2638
  return await import(moduleUrl);
2596
2639
  }
2597
2640
  function resolvePackagedPiResourceRoot() {
2598
2641
  const candidates = [
2599
- (0, import_node_path3.resolve)(process.cwd(), "apps/api-cli/resources/pi-agent"),
2600
- (0, import_node_path3.resolve)(__dirname, "../resources/pi-agent"),
2601
- (0, import_node_path3.resolve)(__dirname, "resources/pi-agent"),
2602
- (0, import_node_path3.resolve)(process.cwd(), "dist/apps/api-cli/resources/pi-agent")
2642
+ (0, import_node_path4.resolve)(process.cwd(), "apps/api-cli/resources/pi-agent"),
2643
+ (0, import_node_path4.resolve)(__dirname, "../resources/pi-agent"),
2644
+ (0, import_node_path4.resolve)(__dirname, "resources/pi-agent"),
2645
+ (0, import_node_path4.resolve)(process.cwd(), "dist/apps/api-cli/resources/pi-agent")
2603
2646
  ];
2604
- const resolved = candidates.find((candidate) => (0, import_node_fs.existsSync)(candidate));
2647
+ const resolved = candidates.find((candidate) => (0, import_node_fs2.existsSync)(candidate));
2605
2648
  if (!resolved) {
2606
2649
  throw new Error(`Unable to locate pi agent resources. Checked: ${candidates.join(", ")}`);
2607
2650
  }
2608
2651
  return resolved;
2609
2652
  }
2610
- function resolvePackagedExtensionPaths(resourceRoot) {
2611
- const extensionsRoot = (0, import_node_path3.join)(resourceRoot, "extensions");
2612
- if (!(0, import_node_fs.existsSync)(extensionsRoot)) {
2613
- return [];
2614
- }
2615
- return (0, import_node_fs.readdirSync)(extensionsRoot, {
2616
- withFileTypes: true
2617
- }).filter((entry) => entry.isDirectory() || entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js"))).map((entry) => (0, import_node_path3.join)(extensionsRoot, entry.name)).sort((left, right) => left.localeCompare(right));
2618
- }
2619
2653
  function setProcessArgValue(flag, value) {
2620
2654
  const existingIndex = process.argv.indexOf(flag);
2621
2655
  if (existingIndex >= 0) {
@@ -2752,17 +2786,17 @@ async function main() {
2752
2786
  const agentDir = readRequiredEnv("PI_CODING_AGENT_DIR");
2753
2787
  const version = process.env.DOCYRUS_PI_VERSION || "dev";
2754
2788
  const resourceRoot = resolvePackagedPiResourceRoot();
2755
- const packagedExtensionPaths = resolvePackagedExtensionPaths(resourceRoot);
2756
- const mcpConfigPath = (0, import_node_path3.join)(agentDir, "mcp.json");
2789
+ const packagedExtensionPaths = resolvePackagedExtensionPaths(resourceRoot, "terminal");
2790
+ const mcpConfigPath = (0, import_node_path4.join)(agentDir, "mcp.json");
2757
2791
  const hasPackagedMcpAdapter = packagedExtensionPaths.some((extensionPath) => extensionPath.includes("pi-mcp-adapter"));
2758
- const envStore = new AgentEnvStore((0, import_node_path3.join)(agentDir, "env.json"));
2792
+ const envStore = new AgentEnvStore((0, import_node_path4.join)(agentDir, "env.json"));
2759
2793
  await envStore.hydrateProcessEnv(process.env);
2760
2794
  if (hasPackagedMcpAdapter) {
2761
2795
  setProcessArgValue("--mcp-config", mcpConfigPath);
2762
2796
  }
2763
- const authStorage = pi.AuthStorage.create((0, import_node_path3.join)(agentDir, "auth.json"));
2797
+ const authStorage = pi.AuthStorage.create((0, import_node_path4.join)(agentDir, "auth.json"));
2764
2798
  const settingsManager = pi.SettingsManager.create(cwd, agentDir);
2765
- const modelsJsonPath = (0, import_node_path3.join)(agentDir, "models.json");
2799
+ const modelsJsonPath = (0, import_node_path4.join)(agentDir, "models.json");
2766
2800
  const initialModelRegistry = new pi.ModelRegistry(authStorage, modelsJsonPath);
2767
2801
  const isPrintMode = Boolean(request.print) || !process.stdin.isTTY;
2768
2802
  const isInteractive = process.stdin.isTTY && !isPrintMode;
@@ -2826,7 +2860,7 @@ async function main() {
2826
2860
  agentDir,
2827
2861
  settingsManager,
2828
2862
  additionalExtensionPaths: packagedExtensionPaths,
2829
- systemPrompt: (0, import_node_path3.join)(
2863
+ systemPrompt: (0, import_node_path4.join)(
2830
2864
  resourceRoot,
2831
2865
  "prompts",
2832
2866
  request.profile === "agent" ? "agent-system.md" : "coder-system.md"