Compare commits

...

18 commits
1.0.1 ... main

Author SHA1 Message Date
Maclean Dunkin
fe357a5f08
Enhance star history display in README
Updated star history section with responsive image support.
2026-07-07 20:04:09 -07:00
Maclean Dunkin
d5fa51277c Bump version to 1.0.6 2025-07-12 19:13:54 -07:00
Maclean Dunkin
8be0273474
Merge pull request #4 from jaspermayone-forks/jsp-better-rate-limit-handling
Add better rate limit handling
2025-07-12 22:09:03 -04:00
Jasper Mayone
8a31323212
better rate limit handling 2025-07-08 21:24:28 -04:00
Maclean Dunkin
9c90890099 Fix release workflow by removing styles.css reference 2025-05-03 17:04:10 -06:00
Maclean Dunkin
46f4e31f38 Bump version to 1.0.5 2025-05-03 17:01:56 -06:00
Maclean Dunkin
c2f724a629 vault api 2025-05-03 15:34:27 -06:00
Maclean Dunkin
bc3d17e8a1 sentence case 2025-05-03 15:30:14 -06:00
Maclean Dunkin
e0d07875df Update LICENSE 2025-05-03 15:24:35 -06:00
Maclean Dunkin
d0ca8c2557 Update limitless-lifelogs.png 2025-05-03 15:23:22 -06:00
Maclean Dunkin
cdd792fa0b
Merge pull request #1 from tralston/main
LGTM
2025-04-15 20:57:32 -06:00
Taylor Ralston
687c8a6e5f
Update main.ts 2025-04-15 11:28:02 -07:00
Taylor Ralston
9cd4f3adae
Reformat Markdown to remove double newlines 2025-04-15 11:19:06 -07:00
Maclean Dunkin
0cd1328fed update package.json & add markdown guides for cursor 2025-03-17 17:07:25 -07:00
Maclean Dunkin
dc0875395b
Add files via upload 2025-03-15 03:02:34 -06:00
Maclean Dunkin
fcf0dcf53c Bump version to 1.0.4 and update description 2025-03-14 23:57:07 -06:00
Maclean Dunkin
578064afbe Bump version to 1.0.3 2025-03-14 23:54:49 -06:00
Maclean Dunkin
078d04e11a Fix author name and bump version to 1.0.2 2025-03-14 23:53:42 -06:00
12 changed files with 2480 additions and 48 deletions

View file

@ -32,4 +32,4 @@ jobs:
gh release create "$tag" \
--title="$tag" \
--draft \
main.js manifest.json styles.css
main.js manifest.json

View file

@ -1,5 +1,3 @@
Copyright (C) 2020-2025 by Dynalist Inc.
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View file

@ -78,10 +78,16 @@ If you encounter any issues:
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=Maclean-D/obsidian-limitless-lifelogs&type=Date)](https://star-history.com/#Maclean-D/obsidian-limitless-lifelogs&Date)
<a href="https://www.star-history.com/?repos=Maclean-D%2Fobsidian-limitless-lifelogs&type=date&legend=top-left">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=Maclean-D/obsidian-limitless-lifelogs&type=date&theme=dark&legend=top-left&sealed_token=n0qnDUpZGvp6y_j0NpoDcTvohZJ0tocsgfpskhjAPGqYY0mSleeunkuQ8dm8HcZi5aCR2D_OHiD8q1Bz4pnUHiXo48HcWKIHPHFUgls95HtHhPnjnuwr5lsOOBjrenFeB0jwJjXP3aNhafiFlspD5WjXA1VVf1XqIO6Yktr2CBHPrSLgqq0YJZqhctEe" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=Maclean-D/obsidian-limitless-lifelogs&type=date&legend=top-left&sealed_token=n0qnDUpZGvp6y_j0NpoDcTvohZJ0tocsgfpskhjAPGqYY0mSleeunkuQ8dm8HcZi5aCR2D_OHiD8q1Bz4pnUHiXo48HcWKIHPHFUgls95HtHhPnjnuwr5lsOOBjrenFeB0jwJjXP3aNhafiFlspD5WjXA1VVf1XqIO6Yktr2CBHPrSLgqq0YJZqhctEe" />
<img alt="Star History Chart" src="https://api.star-history.com/chart?repos=Maclean-D/obsidian-limitless-lifelogs&type=date&legend=top-left&sealed_token=n0qnDUpZGvp6y_j0NpoDcTvohZJ0tocsgfpskhjAPGqYY0mSleeunkuQ8dm8HcZi5aCR2D_OHiD8q1Bz4pnUHiXo48HcWKIHPHFUgls95HtHhPnjnuwr5lsOOBjrenFeB0jwJjXP3aNhafiFlspD5WjXA1VVf1XqIO6Yktr2CBHPrSLgqq0YJZqhctEe" />
</picture>
</a>
## Contributors
<a href="https://github.com/Maclean-D/obsidian-limitless-lifelogs/graphs/contributors">
<img src="https://contrib.rocks/image?repo=Maclean-D/obsidian-limitless-lifelogs" />
</a>
</a>

0
buildaplugin.md Normal file
View file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 46 KiB

91
main.ts
View file

@ -33,7 +33,7 @@ export default class LimitlessLifelogsPlugin extends Plugin {
// Add command for syncing
this.addCommand({
id: 'sync-limitless-lifelogs',
name: 'Sync Limitless Lifelogs',
name: 'Sync',
callback: async () => {
await this.syncLifelogs();
}
@ -96,8 +96,8 @@ export default class LimitlessLifelogsPlugin extends Plugin {
}
private async ensureFolderExists(path: string) {
const folderExists = await this.app.vault.adapter.exists(path);
if (!folderExists) {
const folder = this.app.vault.getFolderByPath(path);
if (!folder) {
await this.app.vault.createFolder(path);
}
}
@ -105,14 +105,15 @@ export default class LimitlessLifelogsPlugin extends Plugin {
private async getLastSyncedDate(): Promise<Date | null> {
const folderPath = normalizePath(this.settings.folderPath);
try {
const files = await this.app.vault.adapter.list(folderPath);
const dates = files.files
.map(file => file.split('/').pop()?.replace('.md', ''))
.filter(date => date && /^\d{4}-\d{2}-\d{2}$/.test(date))
.map(date => new Date(date as string))
const files = this.app.vault.getFiles()
.filter(file => file.path.startsWith(folderPath + '/'))
.filter(file => file.path.endsWith('.md'))
.map(file => file.basename)
.filter(basename => /^\d{4}-\d{2}-\d{2}$/.test(basename))
.map(basename => new Date(basename))
.sort((a, b) => b.getTime() - a.getTime());
return dates.length > 0 ? dates[0] : null;
return files.length > 0 ? files[0] : null;
} catch {
return null;
}
@ -120,7 +121,9 @@ export default class LimitlessLifelogsPlugin extends Plugin {
private formatLifelogMarkdown(lifelog: any): string {
if (lifelog.markdown) {
return lifelog.markdown;
// Reformat Markdown
const reformattedMarkdown = lifelog.markdown.replaceAll('\n\n', '\n');
return reformattedMarkdown;
}
const content: string[] = [];
@ -192,7 +195,7 @@ class LimitlessLifelogsSettingTab extends PluginSettingTab {
containerEl.empty();
new Setting(containerEl)
.setName('API Key')
.setName('API key')
.setDesc('Your Limitless AI API key')
.addText(text => text
.setPlaceholder('Enter your API key')
@ -203,7 +206,7 @@ class LimitlessLifelogsSettingTab extends PluginSettingTab {
}));
new Setting(containerEl)
.setName('Folder Path')
.setName('Folder path')
.setDesc('Where to store the lifelog entries')
.addText(text => text
.setPlaceholder('Folder path')
@ -214,7 +217,7 @@ class LimitlessLifelogsSettingTab extends PluginSettingTab {
}));
new Setting(containerEl)
.setName('Start Date')
.setName('Start date')
.setDesc('Default start date for initial sync (YYYY-MM-DD)')
.addText(text => text
.setPlaceholder('YYYY-MM-DD')
@ -230,6 +233,8 @@ class LimitlessAPI {
private apiKey: string;
private baseUrl = 'https://api.limitless.ai';
private batchSize = 10;
private maxRetries = 5;
private retryDelay = 1000; // 1 second
constructor(apiKey: string) {
this.apiKey = apiKey;
@ -258,20 +263,7 @@ class LimitlessAPI {
}
try {
const response = await requestUrl({
url: `${this.baseUrl}/v1/lifelogs?${params.toString()}`,
method: 'GET',
headers: {
'X-API-Key': this.apiKey,
'Content-Type': 'application/json'
}
});
if (!response.json) {
throw new Error('Invalid response format');
}
const data = response.json;
const data = await this.makeRequest(`${this.baseUrl}/v1/lifelogs`, params);
const lifelogs = data.data?.lifelogs || [];
allLifelogs.push(...lifelogs);
@ -284,4 +276,49 @@ class LimitlessAPI {
return allLifelogs;
}
private async makeRequest(url: string, params: URLSearchParams): Promise<any> {
let retries = 0;
while (true) {
try {
const response = await requestUrl({
url: `${url}?${params.toString()}`,
method: 'GET',
headers: {
'X-API-Key': this.apiKey,
'Content-Type': 'application/json'
}
});
if (!response.json) {
throw new Error('Invalid response format');
}
return response.json;
} catch (error) {
if (error.status === 429 && retries < this.maxRetries) {
let delay = this.retryDelay * Math.pow(2, retries);
const retryAfter = error.headers?.['retry-after'];
if (retryAfter) {
const retryAfterSeconds = parseInt(retryAfter, 10);
if (!isNaN(retryAfterSeconds)) {
delay = retryAfterSeconds * 1000;
} else {
const retryAfterDate = new Date(retryAfter);
const now = new Date();
delay = retryAfterDate.getTime() - now.getTime();
}
}
new Notice(`Rate limit exceeded. Retrying in ${Math.round(delay / 1000)} seconds...`);
await new Promise(resolve => setTimeout(resolve, delay));
retries++;
} else {
console.error('Error making request:', error);
throw error;
}
}
}
}
}

View file

@ -1,10 +1,10 @@
{
"id": "limitless-lifelogs",
"name": "Limitless Lifelogs",
"version": "1.0.1",
"version": "1.0.6",
"minAppVersion": "0.15.0",
"description": "Download and sync your Limitless AI lifelog entries into Obsidian markdown files.",
"author": "Maclean Dunstan",
"description": "Sync your Limitless AI lifelog entries",
"author": "Maclean Dunkin",
"authorUrl": "https://github.com/Maclean-D",
"isDesktopOnly": false
}
}

2397
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "obsidian-limitless-lifelogs",
"version": "1.0.0",
"version": "1.0.6",
"description": "Download and sync your Limitless AI lifelog entries into Obsidian markdown files.",
"main": "main.js",
"scripts": {
@ -9,7 +9,7 @@
"version": "node version-bump.mjs && git add manifest.json versions.json"
},
"keywords": ["obsidian", "plugin", "limitless", "lifelogs"],
"author": "Your Name",
"author": "Maclean Dunkin",
"license": "MIT",
"devDependencies": {
"@types/node": "^16.11.6",

0
releaseplugin.md Normal file
View file

View file

@ -1,8 +0,0 @@
/*
This CSS file will be included with your plugin, and
available in the app when your plugin is enabled.
If your plugin does not need CSS, delete this file.
*/

View file

@ -1,3 +1,5 @@
{
"1.0.0": "0.15.0"
}
"1.0.0": "0.15.0",
"1.0.5": "0.15.0",
"1.0.6": "0.15.0"
}