Compare commits

...

4 Commits

Author SHA1 Message Date
RaymondCho 79cc9f26c9 The plugin is published as jopilgue/aindrive, under its publisher's name (#7)
CI / checks (push) Successful in 4m59s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 14:08:45 +00:00
RaymondCho b7c251314a The README shows what a drive looks like while its machine is offline (#6)
CI / checks (push) Successful in 39s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:12:20 +00:00
RaymondCho a76a8fa680 The README shows how a connected drive looks in Memona (#4)
CI / checks (push) Successful in 39s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 14:34:02 +00:00
RaymondCho 8fea308580 Tests use the README's example drive id instead of a real drive's (#5)
CI / checks (push) Successful in 38s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 14:28:47 +00:00
9 changed files with 29 additions and 15 deletions
+17 -3
View File
@@ -21,15 +21,27 @@ copy it; aindrive shows it only once.
| Server URL | The drive's MCP server URL, for example `https://aindrive.ainetwork.ai/mcp/d/AbCdEf123456`. The drive's own page address, `…/d/AbCdEf123456`, works too, as does a self-hosted server. |
| Access token | The `aind_pat_…` token, stored as a secret |
Saving the connection checks the address and the token. It does not need the
machine that shares the drive to be online, but its files only answer while
that machine runs aindrive; until then they report the folder unavailable.
![The connection form](https://git.capsulizers.com/commons/memona-plugin-aindrive/raw/branch/main/images/connection-form.png)
Saving the connection checks the address and the token. With a wrong token the
connection shows as **Disconnected**:
![A connected drive and one with a wrong token](https://git.capsulizers.com/commons/memona-plugin-aindrive/raw/branch/main/images/connections.png)
The check does not need the machine that shares the drive to be online, but its
files only answer while that machine runs aindrive. Until then the connection
stays **Connected** and the plugin reports the drive unavailable, which Memona
shows as a folder that cannot be read:
![The drive's folder while its machine is offline](https://git.capsulizers.com/commons/memona-plugin-aindrive/raw/branch/main/images/offline-folder.png)
## What works
Browsing folders, and reading, saving and deleting files. A token generated
as **Read only** opens the drive read-only.
![A drive's PAGE.md opened in Memona](https://git.capsulizers.com/commons/memona-plugin-aindrive/raw/branch/main/images/drive-page.png)
aindrive reads a file whole, at most 8 MiB at a time, so a larger file is
refused as unsupported rather than cut short. A read is checked against the
size the drive reported a moment before, so a file that changes in between is
@@ -41,6 +53,8 @@ writes under one lock, so a file someone changed since is reported as a
conflict instead of being overwritten. A save into a folder that does not
exist yet creates that folder, as aindrive does.
![A file changed on the drive's machine while it was open in Memona](https://git.capsulizers.com/commons/memona-plugin-aindrive/raw/branch/main/images/changed-elsewhere.png)
Deleting takes one file. A folder is refused: aindrive deletes a folder with
everything in it, and leaves some entries, such as `.git`, out of every
listing, so a folder cannot be shown to be empty first.
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
{
"schemaVersion": 2,
"id": "memona/aindrive",
"id": "jopilgue/aindrive",
"name": "aindrive",
"version": "0.1.0",
"apiVersion": "0.1.0",
+9 -9
View File
@@ -70,26 +70,26 @@ mod tests {
#[tokio::test]
async fn the_mcp_panel_url_is_used_as_given() {
assert_eq!(
endpoint("https://aindrive.ainetwork.ai/mcp/d/KQHGpl8hFXq8"),
Ok("https://aindrive.ainetwork.ai/mcp/d/KQHGpl8hFXq8".to_owned())
endpoint("https://aindrive.ainetwork.ai/mcp/d/AbCdEf123456"),
Ok("https://aindrive.ainetwork.ai/mcp/d/AbCdEf123456".to_owned())
);
assert_eq!(
endpoint(" https://aindrive.ainetwork.ai/mcp/d/KQHGpl8hFXq8/ \n"),
Ok("https://aindrive.ainetwork.ai/mcp/d/KQHGpl8hFXq8".to_owned())
endpoint(" https://aindrive.ainetwork.ai/mcp/d/AbCdEf123456/ \n"),
Ok("https://aindrive.ainetwork.ai/mcp/d/AbCdEf123456".to_owned())
);
}
#[tokio::test]
async fn a_drive_page_address_finds_the_same_endpoint() {
for page in [
"https://aindrive.ainetwork.ai/d/KQHGpl8hFXq8",
"https://aindrive.ainetwork.ai/d/KQHGpl8hFXq8?path=notes",
"https://aindrive.ainetwork.ai/d/KQHGpl8hFXq8/notes/today.md",
"https://aindrive.ainetwork.ai/d/KQHGpl8hFXq8/manage#members",
"https://aindrive.ainetwork.ai/d/AbCdEf123456",
"https://aindrive.ainetwork.ai/d/AbCdEf123456?path=notes",
"https://aindrive.ainetwork.ai/d/AbCdEf123456/notes/today.md",
"https://aindrive.ainetwork.ai/d/AbCdEf123456/manage#members",
] {
assert_eq!(
endpoint(page),
Ok("https://aindrive.ainetwork.ai/mcp/d/KQHGpl8hFXq8".to_owned()),
Ok("https://aindrive.ainetwork.ai/mcp/d/AbCdEf123456".to_owned()),
"{page}"
);
}
+2 -2
View File
@@ -8,13 +8,13 @@ use crate::sdk::{
};
use std::collections::BTreeMap;
const ENDPOINT: &str = "https://aindrive.ainetwork.ai/mcp/d/KQHGpl8hFXq8";
const ENDPOINT: &str = "https://aindrive.ainetwork.ai/mcp/d/AbCdEf123456";
fn config() -> Vec<(String, Setting)> {
vec![
(
"url".to_owned(),
Setting::Text("https://aindrive.ainetwork.ai/d/KQHGpl8hFXq8".to_owned()),
Setting::Text("https://aindrive.ainetwork.ai/d/AbCdEf123456".to_owned()),
),
(
"token".to_owned(),