@hang.yang/frankcli 0.1.51 → 0.1.52

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/bundle/api.cjs CHANGED
@@ -156413,18 +156413,18 @@ var ConfluenceGetPageTool = class _ConfluenceGetPageTool extends BaseTool {
156413
156413
  config;
156414
156414
  static Name = "confluence_get_page";
156415
156415
  constructor(config2) {
156416
- super(_ConfluenceGetPageTool.Name, "ConfluenceGetPage", "Retrieves content from a Confluence page by its ID. Uses Personal Access Token from keys.json for authentication and can convert HTML content to markdown.", {
156416
+ super(_ConfluenceGetPageTool.Name, "ConfluenceGetPage", "Retrieves content from a Confluence page by its URL. and the url include confluence.rakuten-it.com, Fetches the page to resolve page ID from HTML, then retrieves content via REST API. Uses Personal Access Token from keys.json and can convert HTML to markdown.", {
156417
156417
  properties: {
156418
- page_id: {
156419
- description: "The ID of the Confluence page to retrieve",
156418
+ confluence_url: {
156419
+ description: "The full Confluence page URL (e.g. https://confluence.rakuten-it.com/confluence/pages/viewpage.action?pageId=12345). Page ID is extracted from the page.",
156420
156420
  type: import_genai18.Type.STRING
156421
156421
  },
156422
156422
  convert_to_markdown: {
156423
156423
  description: "Whether to convert HTML content to markdown format (default: true)",
156424
- type: import_genai18.Type.STRING
156424
+ type: import_genai18.Type.BOOLEAN
156425
156425
  }
156426
156426
  },
156427
- required: ["page_id"],
156427
+ required: ["confluence_url"],
156428
156428
  type: import_genai18.Type.OBJECT
156429
156429
  });
156430
156430
  this.config = config2;
@@ -156434,13 +156434,51 @@ var ConfluenceGetPageTool = class _ConfluenceGetPageTool extends BaseTool {
156434
156434
  if (errors) {
156435
156435
  return errors;
156436
156436
  }
156437
- if (!params.page_id || params.page_id.trim() === "") {
156438
- return "The 'page_id' parameter cannot be empty.";
156437
+ if (!params.confluence_url || params.confluence_url.trim() === "") {
156438
+ return "The 'confluence_url' parameter cannot be empty.";
156439
156439
  }
156440
156440
  return null;
156441
156441
  }
156442
156442
  getDescription(params) {
156443
- return `Retrieving Confluence page ${params.page_id} from ${CONFLUENCE_URL}`;
156443
+ return `Retrieving Confluence page from URL: ${params.confluence_url}`;
156444
+ }
156445
+ /**
156446
+ * Fetch the Confluence page URL (HTML) and extract page_id from <meta name="ajs-page-id" content="...">.
156447
+ * Mirrors logic in get_page_id_from_url.py.
156448
+ */
156449
+ async getPageIdFromUrl(confluenceUrl, token2, signal) {
156450
+ const controller = new AbortController();
156451
+ const timeoutId = setTimeout(() => controller.abort(), CONFLUENCE_FETCH_TIMEOUT_MS);
156452
+ try {
156453
+ const response = await fetch(confluenceUrl.trim(), {
156454
+ method: "GET",
156455
+ headers: {
156456
+ "Authorization": `Bearer ${token2}`,
156457
+ "Accept": "text/html, application/xhtml+xml, */*"
156458
+ },
156459
+ signal: signal || controller.signal
156460
+ });
156461
+ clearTimeout(timeoutId);
156462
+ if (response.status !== 200) {
156463
+ return {
156464
+ error: `Failed to fetch URL: HTTP ${response.status}. Check the URL and that your token has access to the page.`
156465
+ };
156466
+ }
156467
+ const html = await response.text();
156468
+ const metaMatch = html.match(/<meta\s+name="ajs-page-id"\s+content="([^"]*)"\s*\/?>/i) || html.match(/<meta[^>]+content="([^"]*)"[^>]+name="ajs-page-id"[^>]*>/i);
156469
+ const pageId = metaMatch ? (metaMatch[1] || "").trim() : "";
156470
+ if (!pageId) {
156471
+ return {
156472
+ error: 'Page ID not found: no <meta name="ajs-page-id" content="..."> in the response. Ensure the URL is a Confluence page view URL.'
156473
+ };
156474
+ }
156475
+ return { pageId };
156476
+ } catch (e2) {
156477
+ clearTimeout(timeoutId);
156478
+ return {
156479
+ error: `Network or parse error while fetching URL: ${getErrorMessage(e2)}. Check the URL and network.`
156480
+ };
156481
+ }
156444
156482
  }
156445
156483
  /**
156446
156484
  * Process HTML content to handle user mentions and page links
@@ -156479,15 +156517,23 @@ var ConfluenceGetPageTool = class _ConfluenceGetPageTool extends BaseTool {
156479
156517
  returnDisplay: validationError
156480
156518
  };
156481
156519
  }
156482
- const { page_id, convert_to_markdown = true } = params;
156520
+ const { confluence_url, convert_to_markdown = true } = params;
156483
156521
  const personal_access_token = this.config.getConfluenceToken();
156484
156522
  if (!personal_access_token) {
156485
156523
  return {
156486
- llmContent: "Error: Confluence Personal Access Token not found in keys.json. Please configure it first.",
156487
- returnDisplay: "Confluence token not configured"
156524
+ llmContent: `Error: ${CONFLUENCE_TOKEN_MISSING_MESSAGE}`,
156525
+ returnDisplay: CONFLUENCE_TOKEN_MISSING_MESSAGE
156488
156526
  };
156489
156527
  }
156490
156528
  try {
156529
+ const resolved = await this.getPageIdFromUrl(confluence_url, personal_access_token, signal);
156530
+ if ("error" in resolved) {
156531
+ return {
156532
+ llmContent: `Error: ${resolved.error}`,
156533
+ returnDisplay: resolved.error
156534
+ };
156535
+ }
156536
+ const page_id = resolved.pageId;
156491
156537
  const isCloud = CONFLUENCE_URL.includes(".atlassian.net");
156492
156538
  const apiUrl = `${CONFLUENCE_URL.replace(/\/$/, "")}/rest/api/content/${page_id}`;
156493
156539
  const paramsObj = new URLSearchParams({
@@ -156596,7 +156642,7 @@ ${processedContent}
156596
156642
  returnDisplay: `Retrieved Confluence page: ${title}`
156597
156643
  };
156598
156644
  } catch (error) {
156599
- const errorMessage = `Error retrieving Confluence page ${page_id}: ${getErrorMessage(error)}`;
156645
+ const errorMessage = `Error retrieving Confluence page: ${getErrorMessage(error)}`;
156600
156646
  console.error(errorMessage, error);
156601
156647
  return {
156602
156648
  llmContent: `Error: ${errorMessage}`,
@@ -156730,8 +156776,8 @@ var JiraGetIssueTool = class _JiraGetIssueTool extends BaseTool {
156730
156776
  const personal_access_token = this.config.getJiraToken();
156731
156777
  if (!personal_access_token) {
156732
156778
  return {
156733
- llmContent: "Error: Jira Personal Access Token not found in keys.json. Please configure it first.",
156734
- returnDisplay: "Jira token not configured"
156779
+ llmContent: `Error: ${JIRA_TOKEN_MISSING_MESSAGE}`,
156780
+ returnDisplay: JIRA_TOKEN_MISSING_MESSAGE
156735
156781
  };
156736
156782
  }
156737
156783
  try {
@@ -165107,6 +165153,8 @@ var DEFAULT_OTLP_ENDPOINT = "http://localhost:4317";
165107
165153
 
165108
165154
  // packages/core/dist/src/config/config.js
165109
165155
  init_models();
165156
+ var CONFLUENCE_TOKEN_MISSING_MESSAGE = "Confluence Personal Access Token not found. Set it with: frankcli set confluence token <Personal Access Tokens>. Create a token at: https://confluence.rakuten-it.com/confluence/plugins/personalaccesstokens/usertokens.action";
165157
+ var JIRA_TOKEN_MISSING_MESSAGE = "Jira Personal Access Token not found. Set it with: frankcli set jira token <Personal Access Tokens>. Create a token at: https://jira.rakuten-it.com/jira/secure/ViewProfile.jspa";
165110
165158
  var ApprovalMode;
165111
165159
  (function(ApprovalMode2) {
165112
165160
  ApprovalMode2["DEFAULT"] = "default";
@@ -165390,12 +165438,19 @@ var Config = class {
165390
165438
  return { memoryContent, fileCount };
165391
165439
  }
165392
165440
  /**
165393
- * Get Confluence Advanced Access Token from keys.json
165441
+ * Get Confluence Advanced Access Token. Checks ~/.mpdai/confluence.key first, then keys.json.
165394
165442
  * @returns The Personal Access Token or null if not found
165395
165443
  */
165396
165444
  getConfluenceToken() {
165397
165445
  try {
165398
- const keysJsonPath = (0, import_node_path7.join)((0, import_node_os3.homedir)(), ".mpdai", "keys.json");
165446
+ const mpdaiDir = (0, import_node_path7.join)((0, import_node_os3.homedir)(), ".mpdai");
165447
+ const keyFilePath = (0, import_node_path7.join)(mpdaiDir, "confluence.key");
165448
+ if ((0, import_node_fs6.existsSync)(keyFilePath)) {
165449
+ const value = (0, import_node_fs6.readFileSync)(keyFilePath, "utf-8").trim();
165450
+ if (value)
165451
+ return value;
165452
+ }
165453
+ const keysJsonPath = (0, import_node_path7.join)(mpdaiDir, "keys.json");
165399
165454
  if (!(0, import_node_fs6.existsSync)(keysJsonPath)) {
165400
165455
  return null;
165401
165456
  }
@@ -165407,17 +165462,24 @@ var Config = class {
165407
165462
  }
165408
165463
  return null;
165409
165464
  } catch (error) {
165410
- console.error("Failed to read Confluence token from keys.json:", error);
165465
+ console.error("Failed to read Confluence token:", error);
165411
165466
  return null;
165412
165467
  }
165413
165468
  }
165414
165469
  /**
165415
- * Get Jira Personal Access Token from keys.json
165470
+ * Get Jira Personal Access Token. Checks ~/.mpdai/jira.key first, then keys.json.
165416
165471
  * @returns The Personal Access Token or null if not found
165417
165472
  */
165418
165473
  getJiraToken() {
165419
165474
  try {
165420
- const keysJsonPath = (0, import_node_path7.join)((0, import_node_os3.homedir)(), ".mpdai", "keys.json");
165475
+ const mpdaiDir = (0, import_node_path7.join)((0, import_node_os3.homedir)(), ".mpdai");
165476
+ const keyFilePath = (0, import_node_path7.join)(mpdaiDir, "jira.key");
165477
+ if ((0, import_node_fs6.existsSync)(keyFilePath)) {
165478
+ const value = (0, import_node_fs6.readFileSync)(keyFilePath, "utf-8").trim();
165479
+ if (value)
165480
+ return value;
165481
+ }
165482
+ const keysJsonPath = (0, import_node_path7.join)(mpdaiDir, "keys.json");
165421
165483
  if (!(0, import_node_fs6.existsSync)(keysJsonPath)) {
165422
165484
  return null;
165423
165485
  }
@@ -165429,7 +165491,7 @@ var Config = class {
165429
165491
  }
165430
165492
  return null;
165431
165493
  } catch (error) {
165432
- console.error("Failed to read Jira token from keys.json:", error);
165494
+ console.error("Failed to read Jira token:", error);
165433
165495
  return null;
165434
165496
  }
165435
165497
  }
@@ -166401,6 +166463,7 @@ var import_path39 = __toESM(require("path"), 1);
166401
166463
  var __filename = (0, import_url4.fileURLToPath)(_importMetaUrl);
166402
166464
  var __dirname4 = import_path39.default.dirname(__filename);
166403
166465
  var packageJson;
166466
+ var packageRoot;
166404
166467
  async function getPackageJson() {
166405
166468
  if (packageJson) {
166406
166469
  return packageJson;
@@ -166410,6 +166473,7 @@ async function getPackageJson() {
166410
166473
  return;
166411
166474
  }
166412
166475
  packageJson = result.packageJson;
166476
+ packageRoot = import_path39.default.dirname(result.path);
166413
166477
  return packageJson;
166414
166478
  }
166415
166479
 
package/bundle/api.js CHANGED
@@ -27724,7 +27724,7 @@ async function createContentGeneratorConfig(model, authType) {
27724
27724
  return contentGeneratorConfig;
27725
27725
  }
27726
27726
  async function createContentGenerator(config2, sessionId2) {
27727
- const version2 = "0.1.51";
27727
+ const version2 = "0.1.52";
27728
27728
  const httpOptions = {
27729
27729
  headers: {
27730
27730
  "User-Agent": `GeminiCLI/${version2} (${process.platform}; ${process.arch})`
@@ -156409,18 +156409,18 @@ var ConfluenceGetPageTool = class _ConfluenceGetPageTool extends BaseTool {
156409
156409
  config;
156410
156410
  static Name = "confluence_get_page";
156411
156411
  constructor(config2) {
156412
- super(_ConfluenceGetPageTool.Name, "ConfluenceGetPage", "Retrieves content from a Confluence page by its ID. Uses Personal Access Token from keys.json for authentication and can convert HTML content to markdown.", {
156412
+ super(_ConfluenceGetPageTool.Name, "ConfluenceGetPage", "Retrieves content from a Confluence page by its URL. and the url include confluence.rakuten-it.com, Fetches the page to resolve page ID from HTML, then retrieves content via REST API. Uses Personal Access Token from keys.json and can convert HTML to markdown.", {
156413
156413
  properties: {
156414
- page_id: {
156415
- description: "The ID of the Confluence page to retrieve",
156414
+ confluence_url: {
156415
+ description: "The full Confluence page URL (e.g. https://confluence.rakuten-it.com/confluence/pages/viewpage.action?pageId=12345). Page ID is extracted from the page.",
156416
156416
  type: Type15.STRING
156417
156417
  },
156418
156418
  convert_to_markdown: {
156419
156419
  description: "Whether to convert HTML content to markdown format (default: true)",
156420
- type: Type15.STRING
156420
+ type: Type15.BOOLEAN
156421
156421
  }
156422
156422
  },
156423
- required: ["page_id"],
156423
+ required: ["confluence_url"],
156424
156424
  type: Type15.OBJECT
156425
156425
  });
156426
156426
  this.config = config2;
@@ -156430,13 +156430,51 @@ var ConfluenceGetPageTool = class _ConfluenceGetPageTool extends BaseTool {
156430
156430
  if (errors) {
156431
156431
  return errors;
156432
156432
  }
156433
- if (!params.page_id || params.page_id.trim() === "") {
156434
- return "The 'page_id' parameter cannot be empty.";
156433
+ if (!params.confluence_url || params.confluence_url.trim() === "") {
156434
+ return "The 'confluence_url' parameter cannot be empty.";
156435
156435
  }
156436
156436
  return null;
156437
156437
  }
156438
156438
  getDescription(params) {
156439
- return `Retrieving Confluence page ${params.page_id} from ${CONFLUENCE_URL}`;
156439
+ return `Retrieving Confluence page from URL: ${params.confluence_url}`;
156440
+ }
156441
+ /**
156442
+ * Fetch the Confluence page URL (HTML) and extract page_id from <meta name="ajs-page-id" content="...">.
156443
+ * Mirrors logic in get_page_id_from_url.py.
156444
+ */
156445
+ async getPageIdFromUrl(confluenceUrl, token2, signal) {
156446
+ const controller = new AbortController();
156447
+ const timeoutId = setTimeout(() => controller.abort(), CONFLUENCE_FETCH_TIMEOUT_MS);
156448
+ try {
156449
+ const response = await fetch(confluenceUrl.trim(), {
156450
+ method: "GET",
156451
+ headers: {
156452
+ "Authorization": `Bearer ${token2}`,
156453
+ "Accept": "text/html, application/xhtml+xml, */*"
156454
+ },
156455
+ signal: signal || controller.signal
156456
+ });
156457
+ clearTimeout(timeoutId);
156458
+ if (response.status !== 200) {
156459
+ return {
156460
+ error: `Failed to fetch URL: HTTP ${response.status}. Check the URL and that your token has access to the page.`
156461
+ };
156462
+ }
156463
+ const html = await response.text();
156464
+ const metaMatch = html.match(/<meta\s+name="ajs-page-id"\s+content="([^"]*)"\s*\/?>/i) || html.match(/<meta[^>]+content="([^"]*)"[^>]+name="ajs-page-id"[^>]*>/i);
156465
+ const pageId = metaMatch ? (metaMatch[1] || "").trim() : "";
156466
+ if (!pageId) {
156467
+ return {
156468
+ error: 'Page ID not found: no <meta name="ajs-page-id" content="..."> in the response. Ensure the URL is a Confluence page view URL.'
156469
+ };
156470
+ }
156471
+ return { pageId };
156472
+ } catch (e2) {
156473
+ clearTimeout(timeoutId);
156474
+ return {
156475
+ error: `Network or parse error while fetching URL: ${getErrorMessage(e2)}. Check the URL and network.`
156476
+ };
156477
+ }
156440
156478
  }
156441
156479
  /**
156442
156480
  * Process HTML content to handle user mentions and page links
@@ -156475,15 +156513,23 @@ var ConfluenceGetPageTool = class _ConfluenceGetPageTool extends BaseTool {
156475
156513
  returnDisplay: validationError
156476
156514
  };
156477
156515
  }
156478
- const { page_id, convert_to_markdown = true } = params;
156516
+ const { confluence_url, convert_to_markdown = true } = params;
156479
156517
  const personal_access_token = this.config.getConfluenceToken();
156480
156518
  if (!personal_access_token) {
156481
156519
  return {
156482
- llmContent: "Error: Confluence Personal Access Token not found in keys.json. Please configure it first.",
156483
- returnDisplay: "Confluence token not configured"
156520
+ llmContent: `Error: ${CONFLUENCE_TOKEN_MISSING_MESSAGE}`,
156521
+ returnDisplay: CONFLUENCE_TOKEN_MISSING_MESSAGE
156484
156522
  };
156485
156523
  }
156486
156524
  try {
156525
+ const resolved = await this.getPageIdFromUrl(confluence_url, personal_access_token, signal);
156526
+ if ("error" in resolved) {
156527
+ return {
156528
+ llmContent: `Error: ${resolved.error}`,
156529
+ returnDisplay: resolved.error
156530
+ };
156531
+ }
156532
+ const page_id = resolved.pageId;
156487
156533
  const isCloud = CONFLUENCE_URL.includes(".atlassian.net");
156488
156534
  const apiUrl = `${CONFLUENCE_URL.replace(/\/$/, "")}/rest/api/content/${page_id}`;
156489
156535
  const paramsObj = new URLSearchParams({
@@ -156592,7 +156638,7 @@ ${processedContent}
156592
156638
  returnDisplay: `Retrieved Confluence page: ${title}`
156593
156639
  };
156594
156640
  } catch (error) {
156595
- const errorMessage = `Error retrieving Confluence page ${page_id}: ${getErrorMessage(error)}`;
156641
+ const errorMessage = `Error retrieving Confluence page: ${getErrorMessage(error)}`;
156596
156642
  console.error(errorMessage, error);
156597
156643
  return {
156598
156644
  llmContent: `Error: ${errorMessage}`,
@@ -156726,8 +156772,8 @@ var JiraGetIssueTool = class _JiraGetIssueTool extends BaseTool {
156726
156772
  const personal_access_token = this.config.getJiraToken();
156727
156773
  if (!personal_access_token) {
156728
156774
  return {
156729
- llmContent: "Error: Jira Personal Access Token not found in keys.json. Please configure it first.",
156730
- returnDisplay: "Jira token not configured"
156775
+ llmContent: `Error: ${JIRA_TOKEN_MISSING_MESSAGE}`,
156776
+ returnDisplay: JIRA_TOKEN_MISSING_MESSAGE
156731
156777
  };
156732
156778
  }
156733
156779
  try {
@@ -165103,6 +165149,8 @@ var DEFAULT_OTLP_ENDPOINT = "http://localhost:4317";
165103
165149
 
165104
165150
  // packages/core/dist/src/config/config.js
165105
165151
  init_models();
165152
+ var CONFLUENCE_TOKEN_MISSING_MESSAGE = "Confluence Personal Access Token not found. Set it with: frankcli set confluence token <Personal Access Tokens>. Create a token at: https://confluence.rakuten-it.com/confluence/plugins/personalaccesstokens/usertokens.action";
165153
+ var JIRA_TOKEN_MISSING_MESSAGE = "Jira Personal Access Token not found. Set it with: frankcli set jira token <Personal Access Tokens>. Create a token at: https://jira.rakuten-it.com/jira/secure/ViewProfile.jspa";
165106
165154
  var ApprovalMode;
165107
165155
  (function(ApprovalMode2) {
165108
165156
  ApprovalMode2["DEFAULT"] = "default";
@@ -165386,12 +165434,19 @@ var Config = class {
165386
165434
  return { memoryContent, fileCount };
165387
165435
  }
165388
165436
  /**
165389
- * Get Confluence Advanced Access Token from keys.json
165437
+ * Get Confluence Advanced Access Token. Checks ~/.mpdai/confluence.key first, then keys.json.
165390
165438
  * @returns The Personal Access Token or null if not found
165391
165439
  */
165392
165440
  getConfluenceToken() {
165393
165441
  try {
165394
- const keysJsonPath = join11(homedir6(), ".mpdai", "keys.json");
165442
+ const mpdaiDir = join11(homedir6(), ".mpdai");
165443
+ const keyFilePath = join11(mpdaiDir, "confluence.key");
165444
+ if (existsSync5(keyFilePath)) {
165445
+ const value = readFileSync8(keyFilePath, "utf-8").trim();
165446
+ if (value)
165447
+ return value;
165448
+ }
165449
+ const keysJsonPath = join11(mpdaiDir, "keys.json");
165395
165450
  if (!existsSync5(keysJsonPath)) {
165396
165451
  return null;
165397
165452
  }
@@ -165403,17 +165458,24 @@ var Config = class {
165403
165458
  }
165404
165459
  return null;
165405
165460
  } catch (error) {
165406
- console.error("Failed to read Confluence token from keys.json:", error);
165461
+ console.error("Failed to read Confluence token:", error);
165407
165462
  return null;
165408
165463
  }
165409
165464
  }
165410
165465
  /**
165411
- * Get Jira Personal Access Token from keys.json
165466
+ * Get Jira Personal Access Token. Checks ~/.mpdai/jira.key first, then keys.json.
165412
165467
  * @returns The Personal Access Token or null if not found
165413
165468
  */
165414
165469
  getJiraToken() {
165415
165470
  try {
165416
- const keysJsonPath = join11(homedir6(), ".mpdai", "keys.json");
165471
+ const mpdaiDir = join11(homedir6(), ".mpdai");
165472
+ const keyFilePath = join11(mpdaiDir, "jira.key");
165473
+ if (existsSync5(keyFilePath)) {
165474
+ const value = readFileSync8(keyFilePath, "utf-8").trim();
165475
+ if (value)
165476
+ return value;
165477
+ }
165478
+ const keysJsonPath = join11(mpdaiDir, "keys.json");
165417
165479
  if (!existsSync5(keysJsonPath)) {
165418
165480
  return null;
165419
165481
  }
@@ -165425,7 +165487,7 @@ var Config = class {
165425
165487
  }
165426
165488
  return null;
165427
165489
  } catch (error) {
165428
- console.error("Failed to read Jira token from keys.json:", error);
165490
+ console.error("Failed to read Jira token:", error);
165429
165491
  return null;
165430
165492
  }
165431
165493
  }
@@ -166397,6 +166459,7 @@ import path33 from "path";
166397
166459
  var __filename = fileURLToPath7(import.meta.url);
166398
166460
  var __dirname4 = path33.dirname(__filename);
166399
166461
  var packageJson;
166462
+ var packageRoot;
166400
166463
  async function getPackageJson() {
166401
166464
  if (packageJson) {
166402
166465
  return packageJson;
@@ -166406,13 +166469,14 @@ async function getPackageJson() {
166406
166469
  return;
166407
166470
  }
166408
166471
  packageJson = result.packageJson;
166472
+ packageRoot = path33.dirname(result.path);
166409
166473
  return packageJson;
166410
166474
  }
166411
166475
 
166412
166476
  // packages/cli/src/utils/version.ts
166413
166477
  async function getCliVersion() {
166414
166478
  const pkgJson = await getPackageJson();
166415
- return "0.1.51";
166479
+ return "0.1.52";
166416
166480
  }
166417
166481
 
166418
166482
  // packages/cli/src/config/sandboxConfig.ts