Skip to content

Update numpy-documentation-search extension#27290

Merged
raycastbot merged 5 commits intoraycast:mainfrom
Faria22:ext/numpy-documentation-search
Apr 21, 2026
Merged

Update numpy-documentation-search extension#27290
raycastbot merged 5 commits intoraycast:mainfrom
Faria22:ext/numpy-documentation-search

Conversation

@Faria22
Copy link
Copy Markdown
Contributor

@Faria22 Faria22 commented Apr 20, 2026

Description

Implemented a local documentation fallback flow for the Raycast extension so it no longer depends exclusively on live access to numpy.org. The command now supports two source modes, Auto and Local Docs Directory: it tries the online NumPy docs first, and if that fails and a local docs folder is configured, it falls back to the downloaded docs under that folder’s stable/ subdirectory for both inventory loading and inline detail previews. The UI was updated to replace raw connection failures with guided recovery instructions that tell users how to download, extract, and configure local docs, and the extension metadata, README, changelog, and automated tests were updated to reflect and verify the new behavior.

Screencast

image

Checklist

- feat: support local docs fallback
- chore: Updated changelog to match new readme update
- chore: Updated readme to better fit with other raycast extensions
- Pull contributions
- Merge pull request raycast#14 from Faria22/copilot/fix-compilation-issue-raycast
- fix: resolve TypeScript compilation errors for Raycast build
- Initial plan
- chore: Removed unused assest
- chore: Updated screenshots
- Merge pull request raycast#13 from Faria22/copilot/remove-ufunc-from-signature
- Merge branch \'main\' into copilot/remove-ufunc-from-signature
- Fix: Remove ufunc assignment from function signatures
- Add test fixture and test case for ufunc signature issue
- chore: Fixed changelog dates
- Initial plan
- Merge pull request raycast#11 from Faria22/copilot/update-toggle-to-use-np
- Add prefix toggle feature with np./numpy. preference (default: np.)
- Initial plan
- chore: Added screenshots
- style: changed wording from `qualified name` to `item name`
- Merge pull request raycast#9 from Faria22/copilot/remove-hash-from-url
- docs: update CHANGELOG to version 1.1.1 and add versioning guidelines to AGENTS.md
- fix: remove hash fragments from documentation URLs
- chore: Added MIT license
- Initial plan
- Merge pull request raycast#4 from Faria22/copilot/fix-item-descriptions-code-blocks
- Merge branch \'main\' into copilot/fix-item-descriptions-code-blocks
- docs: update CHANGELOG with inline code blocks fix
- Merge pull request raycast#5 from Faria22/copilot/update-agents-md-change-log
- docs: Clarify CHANGELOG.md should be updated after any changes
- Initial plan
- feat: preserve inline code blocks in parameter descriptions
- Merge pull request raycast#2 from Faria22/copilot/update-changelog-to-v1-0
- chore: update CHANGELOG.md to v1.0.0 with comprehensive feature list
- Initial plan
- Initial plan
- chore: Removed outdated planning files
- Merge pull request raycast#1 from Faria22/copilot/update-implement-plan-structure
- Final documentation style
- Revert "Use HTML line break and non-breaking spaces to force parameter description on new line"
- Use HTML line break and non-breaking spaces to force parameter description on new line
- Fix parameter rendering by splitting multi-line strings into individual array elements
- Add blank line after each parameter for proper markdown multi-line rendering
- Format parameter descriptions to match NumPy style with indented descriptions
- Updated the documentation style
- Add fullscreen documentation view with Action.Push for enhanced navigation
- Remove metadata section with signature, keep signature only in markdown
- Remove signature preference and fix private member filtering for all segments
- Implement enhanced signature presentation with floating header and private member filtering
- Initial plan
- Implementation plan
- fix: add description to signature preference
- fix: add label for signature preference
- style: enlarge detail section headings
- feat: add pinned signature preference
- docs: emphasize pushing after commits
- feat: streamline detail panel layout
- refactor: use raycast hooks for numpy docs
- chore: add debug logging for doc loading
- chore: add debug logging for doc loading
- fix: allow numpy doc details to load
- Added description to NumPy Docs command
- chore: remove legacy command stub
- docs: update contributor guidance and usage
- feat: add numpy docs search command
- Updated the extension icon
- First commit
@raycastbot raycastbot added extension fix / improvement Label for PRs with extension's fix improvements extension: numpy-documentation-search Issues related to the numpy-documentation-search extension platform: macOS platform: Windows labels Apr 20, 2026
@raycastbot
Copy link
Copy Markdown
Collaborator

raycastbot commented Apr 20, 2026

Thank you for your contribution! 🎉

🔔 @Faria22 you might want to have a look.

You can use this guide to learn how to check out the Pull Request locally in order to test it.

📋 Quick checkout commands
BRANCH="ext/numpy-documentation-search"
FORK_URL="https://github.com/Faria22/raycast-extensions.git"
EXTENSION_NAME="numpy-documentation-search"
REPO_NAME="raycast-extensions"

git clone -n --depth=1 --filter=tree:0 -b $BRANCH $FORK_URL
cd $REPO_NAME
git sparse-checkout set --no-cone "extensions/$EXTENSION_NAME"
git checkout
cd "extensions/$EXTENSION_NAME"
npm install && npm run dev

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

@raycastbot raycastbot added the OP is author The OP of the PR is the author of the extension label Apr 20, 2026
@Faria22 Faria22 marked this pull request as ready for review April 20, 2026 01:37
Copilot AI review requested due to automatic review settings April 20, 2026 01:37
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a local documentation fallback for the NumPy Documentation Search Raycast extension, allowing it to function when numpy.org is unreachable by loading a downloaded local docs bundle.

Changes:

  • Introduces a docs-source loader that can fetch inventory/details remotely with local fallback (or force local).
  • Updates command UI to show a guided recovery state + preference shortcut when live docs fail.
  • Adds vitest coverage for remote→local fallback and local detail loading.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
extensions/numpy-documentation-search/src/numpy-docs.tsx Wires new inventory/detail loading modes into the UI and adds recovery actions/markdown.
extensions/numpy-documentation-search/src/lib/inventory.ts Refactors inventory transformation to support Buffer-based parsing for local file reads.
extensions/numpy-documentation-search/src/lib/docs-source.ts Implements remote/local loaders and fallback logic for inventory and detail HTML.
extensions/numpy-documentation-search/src/hooks/useInventory.ts Replaces useFetch with custom hook to support fallback + remoteError/source metadata.
extensions/numpy-documentation-search/src/hooks/useDocDetail.ts Replaces useFetch with custom hook to support local detail loading + source metadata.
extensions/numpy-documentation-search/src/tests/docs-source.test.ts Adds tests for online fallback behavior and local detail parsing.
extensions/numpy-documentation-search/package.json Adds preferences for documentation source mode and local docs directory; updates titles.
extensions/numpy-documentation-search/README.md Documents certificate-restricted network recovery and local docs configuration.
extensions/numpy-documentation-search/CHANGELOG.md Adds release notes for the new local-docs fallback flow.
Files not reviewed (1)
  • extensions/numpy-documentation-search/package-lock.json: Language not supported

Comment on lines +152 to +155
const htmlPath = path.join(directory, item.docPath.split("#")[0] ?? item.docPath);
return parseDocDetail(await deps.readTextFileImpl(htmlPath), item);
}

Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

item.docPath originates from the inventory and is used to build a filesystem path via path.join(...). If the inventory is remote/untrusted (or becomes corrupted), a docPath containing ../ or an absolute path could escape the intended stable directory and read arbitrary local files. Consider resolving the path (e.g., path.resolve) and enforcing that the resolved path stays within directory (prefix check), and reject absolute paths / path traversal segments before reading.

Suggested change
const htmlPath = path.join(directory, item.docPath.split("#")[0] ?? item.docPath);
return parseDocDetail(await deps.readTextFileImpl(htmlPath), item);
}
const htmlPath = resolveDocPathWithinDirectory(directory, item.docPath);
return parseDocDetail(await deps.readTextFileImpl(htmlPath), item);
}
function resolveDocPathWithinDirectory(directory: string, docPath: string): string {
const relativeDocPath = docPath.split("#")[0] ?? docPath;
if (!relativeDocPath) {
throw new Error("Documentation path is empty.");
}
if (path.isAbsolute(relativeDocPath)) {
throw new Error(`Documentation path must be relative: ${docPath}`);
}
const resolvedDirectory = path.resolve(directory);
const resolvedDocPath = path.resolve(resolvedDirectory, relativeDocPath);
const relativeToDirectory = path.relative(resolvedDirectory, resolvedDocPath);
if (
relativeToDirectory === ".." ||
relativeToDirectory.startsWith(`..${path.sep}`) ||
path.isAbsolute(relativeToDirectory)
) {
throw new Error(`Documentation path escapes the docs directory: ${docPath}`);
}
return resolvedDocPath;
}

Copilot uses AI. Check for mistakes.
Comment on lines +234 to +242
function RecoveryActions({ revalidate }: { revalidate: () => void }) {
return (
<ActionPanel>
<Action title="Open Command Preferences" onAction={openCommandPreferences} />
<Action title="Retry Live Download" icon={Icon.ArrowClockwise} onAction={revalidate} />
<Action.OpenInBrowser title="Open NumPy Docs Repository" url="https://github.com/numpy/doc" />
</ActionPanel>
);
}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retry Live Download is misleading when the user has set Documentation Source to Local Docs Directory (or when the failure is a local filesystem error). revalidate will just retry the same mode, not necessarily a live download. Suggest making the label conditional (e.g., Retry / Reload Inventory) or wiring the action to explicitly retry remote loading when in the fallback UI.

Copilot uses AI. Check for mistakes.
Comment on lines +244 to +258
function buildRecoveryMarkdown(error: Error, hasLocalDocsDirectory: boolean): string {
return [
"# Unable to reach live NumPy docs",
"",
"This extension was not able to connect to `https://numpy.org/doc/stable/`.",
"",
"If you can access the internet outside of Raycast, you can download the generated NumPy docs elsewhere and point the extension at that folder.",
"",
"## Setup",
"",
"1. Download the ZIP for the generated NumPy docs from [numpy/doc](https://github.com/numpy/doc) or get it from another machine that can access `numpy.org`.",
"2. Extract the ZIP locally. The extension will look for the documentation version under the `stable` folder inside what you downloaded.",
hasLocalDocsDirectory
? "3. Open this command's preferences and verify that **Local Docs Directory** points to the downloaded docs folder."
: "3. Open this command's preferences and set **Local Docs Directory** to the downloaded docs folder.",
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This markdown always frames the problem as a network failure to numpy.org, but inventoryError can also be caused by local-mode configuration issues (e.g., missing Local Docs Directory, missing stable/objects.inv, unreadable file). Consider tailoring the recovery copy based on whether the failure is a remoteError vs a local filesystem/config error so users aren’t directed to “download docs” when they simply selected the wrong directory.

Suggested change
function buildRecoveryMarkdown(error: Error, hasLocalDocsDirectory: boolean): string {
return [
"# Unable to reach live NumPy docs",
"",
"This extension was not able to connect to `https://numpy.org/doc/stable/`.",
"",
"If you can access the internet outside of Raycast, you can download the generated NumPy docs elsewhere and point the extension at that folder.",
"",
"## Setup",
"",
"1. Download the ZIP for the generated NumPy docs from [numpy/doc](https://github.com/numpy/doc) or get it from another machine that can access `numpy.org`.",
"2. Extract the ZIP locally. The extension will look for the documentation version under the `stable` folder inside what you downloaded.",
hasLocalDocsDirectory
? "3. Open this command's preferences and verify that **Local Docs Directory** points to the downloaded docs folder."
: "3. Open this command's preferences and set **Local Docs Directory** to the downloaded docs folder.",
function isLikelyRemoteInventoryError(error: Error, hasLocalDocsDirectory: boolean): boolean {
const message = error.message.toLowerCase();
const localIndicators = [
"enoent",
"eacces",
"eperm",
"not found",
"no such file",
"objects.inv",
"local docs",
"directory",
"file",
"path",
"read",
"open",
];
const remoteIndicators = [
"fetch",
"network",
"timeout",
"timed out",
"connect",
"connection",
"dns",
"socket",
"http",
"https",
"numpy.org",
];
if (localIndicators.some((indicator) => message.includes(indicator))) {
return false;
}
if (remoteIndicators.some((indicator) => message.includes(indicator))) {
return true;
}
return !hasLocalDocsDirectory;
}
function buildRecoveryMarkdown(error: Error, hasLocalDocsDirectory: boolean): string {
const isRemoteError = isLikelyRemoteInventoryError(error, hasLocalDocsDirectory);
if (isRemoteError) {
return [
"# Unable to reach live NumPy docs",
"",
"This extension was not able to connect to `https://numpy.org/doc/stable/`.",
"",
"If you can access the internet outside of Raycast, you can download the generated NumPy docs elsewhere and point the extension at that folder.",
"",
"## Setup",
"",
"1. Download the ZIP for the generated NumPy docs from [numpy/doc](https://github.com/numpy/doc) or get it from another machine that can access `numpy.org`.",
"2. Extract the ZIP locally. The extension will look for the documentation version under the `stable` folder inside what you downloaded.",
hasLocalDocsDirectory
? "3. Open this command's preferences and verify that **Local Docs Directory** points to the downloaded docs folder."
: "3. Open this command's preferences and set **Local Docs Directory** to the downloaded docs folder.",
"",
"## Current error",
"",
`\`${error.message}\``,
].join("\n");
}
return [
"# Unable to load local NumPy docs",
"",
"This extension could not load the local NumPy documentation inventory.",
"",
"## Check your local docs setup",
"",
hasLocalDocsDirectory
? "1. Open this command's preferences and verify that **Local Docs Directory** points to the correct extracted docs folder."
: "1. Open this command's preferences and set **Local Docs Directory** to the extracted docs folder.",
"2. Confirm the selected folder contains a `stable/objects.inv` file.",
"3. Make sure Raycast can read the folder and files inside it.",

Copilot uses AI. Check for mistakes.
mkdirSync(referenceDir, { recursive: true });
writeFileSync(
path.join(referenceDir, "numpy.linspace.html"),
readFileSync(path.join(process.cwd(), "src/__tests__/fixtures/numpy.linspace.html"), "utf8"),
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using process.cwd() makes the test dependent on the runner’s working directory (often the monorepo root), which can cause failures when executed from different paths/CI setups. Prefer resolving the fixture relative to the test file location (e.g., via import.meta.url / __dirname equivalent) to make the test location-independent.

Suggested change
readFileSync(path.join(process.cwd(), "src/__tests__/fixtures/numpy.linspace.html"), "utf8"),
readFileSync(new URL("./fixtures/numpy.linspace.html", import.meta.url), "utf8"),

Copilot uses AI. Check for mistakes.
"$schema": "https://www.raycast.com/schemas/extension.json",
"name": "numpy-documentation-search",
"title": "NumPy Documentation Search",
"title": "Numpy Documentation Search",
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extension/command titles changed from NumPy to Numpy. NumPy is a proper name with specific capitalization and this change will surface in the Raycast Store and command UI. Recommend reverting these strings to NumPy for correctness and consistency with the rest of the extension text (numpy.org, README, etc.).

Copilot uses AI. Check for mistakes.
Comment on lines +21 to 22
"title": "Numpy Docs",
"subtitle": "Search through Numpy documentation",
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extension/command titles changed from NumPy to Numpy. NumPy is a proper name with specific capitalization and this change will surface in the Raycast Store and command UI. Recommend reverting these strings to NumPy for correctness and consistency with the rest of the extension text (numpy.org, README, etc.).

Copilot uses AI. Check for mistakes.
import { parseDocDetail, type DocDetail } from "./doc-detail";
import { INVENTORY_URL, transformInventoryBuffer, type InventoryItem } from "./inventory";

export type DocumentationSourceMode = "online" | "local";
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DocumentationSourceMode uses online to represent a behavior that appears to be “try remote, then fall back to local if configured” (i.e., an auto mode). Naming this mode online is likely to confuse because it still uses local docs on failure. Consider renaming the mode/value to auto (and updating the preference dropdown titles accordingly) to match the described behavior and reduce ambiguity for API consumers.

Copilot uses AI. Check for mistakes.
# NumPy Documentation Search Changelog

## [1.2.3] - 2025-10-09
## [1.3.0] - {PR_MERGE_DATE}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changelog now includes {PR_MERGE_DATE} placeholders (and replaces the previously concrete date for 1.2.3). If the repository expects released versions to have real dates, these placeholders should be replaced with actual dates before merge/release so the changelog remains accurate and user-facing.

Copilot uses AI. Check for mistakes.
Comment thread extensions/numpy-documentation-search/CHANGELOG.md Outdated
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This PR adds a local documentation fallback for the NumPy Documentation Search extension, so users on certificate-restricted networks can point the extension at downloaded local docs instead of always fetching from numpy.org. The implementation is clean, with dependency-injected loaders, proper cancellation tokens in hooks, and new tests covering the fallback paths.

  • P1 – CHANGELOG date regression: The already-released [1.2.3] entry had its real date (2025-10-09) replaced with {PR_MERGE_DATE}, which will overwrite the historical date when this PR merges. Only the new [1.3.0] entry should use the placeholder.

Confidence Score: 4/5

Safe to merge after fixing the CHANGELOG date regression on the [1.2.3] entry.

One P1 issue (retroactive date overwrite in CHANGELOG) needs to be fixed before merging; all other findings are P2 style suggestions.

CHANGELOG.md — the [1.2.3] entry must restore its original date (2025-10-09).

Important Files Changed

Filename Overview
extensions/numpy-documentation-search/CHANGELOG.md Adds v1.3.0 entry correctly, but incorrectly replaces the real date on the already-released [1.2.3] entry with {PR_MERGE_DATE}.
extensions/numpy-documentation-search/src/lib/docs-source.ts New module implementing online/local inventory and doc-detail loading with clean fallback logic and dependency injection for testability.
extensions/numpy-documentation-search/src/numpy-docs.tsx Updated UI with recovery state and local-docs support; contains a manually-defined Preferences interface that should use the auto-generated type instead.
extensions/numpy-documentation-search/src/tests/docs-source.test.ts New tests cover online→local fallback and explicit local-mode doc detail loading with temp-dir cleanup.
extensions/numpy-documentation-search/package.json Adds two new preferences (documentationSourceMode dropdown, localDocsDirectory directory picker) with correct types and descriptions.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/numpy-documentation-search/CHANGELOG.md
Line: 13

Comment:
**Previously-released entry date overwritten with placeholder**

The `[1.2.3]` entry already had a real merge date (`2025-10-09`) from a prior PR. Changing it to `{PR_MERGE_DATE}` will cause the release tooling to stamp it with this PR's merge date, permanently erasing the historical date.

```suggestion
## [1.2.3] - 2025-10-09
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/numpy-documentation-search/src/numpy-docs.tsx
Line: 11-15

Comment:
**Manually-defined `Preferences` interface should be removed**

Raycast auto-generates the `Preferences` type in `raycast-env.d.ts` from `package.json`; keeping a manual definition risks type drift when preferences change. Remove the interface and rely on the generated type instead.

```suggestion
```

**Rule Used:** What: Don't manually define `Preferences` for `get... ([source](https://app.greptile.com/review/custom-context?memory=d93fc9fb-a45d-4479-a6a4-b1b4af98ebc8))

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Rename auto mode to online" | Re-trigger Greptile

- Fall back to local documentation when remote inventory loading fails
- Load inline documentation previews from a configured local docs directory when network access is unavailable

## [1.2.3] - {PR_MERGE_DATE}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Previously-released entry date overwritten with placeholder

The [1.2.3] entry already had a real merge date (2025-10-09) from a prior PR. Changing it to {PR_MERGE_DATE} will cause the release tooling to stamp it with this PR's merge date, permanently erasing the historical date.

Suggested change
## [1.2.3] - {PR_MERGE_DATE}
## [1.2.3] - 2025-10-09
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/numpy-documentation-search/CHANGELOG.md
Line: 13

Comment:
**Previously-released entry date overwritten with placeholder**

The `[1.2.3]` entry already had a real merge date (`2025-10-09`) from a prior PR. Changing it to `{PR_MERGE_DATE}` will cause the release tooling to stamp it with this PR's merge date, permanently erasing the historical date.

```suggestion
## [1.2.3] - 2025-10-09
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread extensions/numpy-documentation-search/src/numpy-docs.tsx Outdated
@0xdhrv 0xdhrv self-assigned this Apr 21, 2026
Copy link
Copy Markdown
Contributor

@0xdhrv 0xdhrv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, approved ✅

@raycastbot raycastbot merged commit 80db725 into raycast:main Apr 21, 2026
2 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

Published to the Raycast Store:
https://raycast.com/FariaF22/numpy-documentation-search

@raycastbot
Copy link
Copy Markdown
Collaborator

🎉 🎉 🎉

We've rewarded your Raycast account with some credits. You will soon be able to exchange them for some swag.

@Faria22 Faria22 deleted the ext/numpy-documentation-search branch April 28, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extension fix / improvement Label for PRs with extension's fix improvements extension: numpy-documentation-search Issues related to the numpy-documentation-search extension OP is author The OP of the PR is the author of the extension platform: macOS platform: Windows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants