Skip to content

Commit

Permalink
version: 0.2.9
Browse files Browse the repository at this point in the history
  • Loading branch information
pinittech committed May 13, 2024
1 parent 8bee763 commit 3370f2e
Show file tree
Hide file tree
Showing 12 changed files with 889 additions and 691 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
node_modules/
dist/
*.log
data.json
data.json
generate_uuids.ts
31 changes: 26 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## Caret

Caret enables new LLM-powered workflows in Obsidian.
Caret enables you to work better in Obsidian.

Caret is a local-first, privacy preserving application. The only external network calls are to activate your license and use remote LLMs (although not required). I don't have any backend or servers for Caret, don't collect any telemetry, etc.
## Known Issues

- **Sparkle Icon**: May render context incompletely if used immediately after editing a note on Canvas. *Workaround*: Allow a brief pause (Like 1 second) before using the sparkle icon.
Expand All @@ -12,29 +14,36 @@ Caret enables new LLM-powered workflows in Obsidian.

### Step 1: Install the BRAT Plugin from TfTHacker
1. BRAT is the **Beta Reviewers Auto-update Tool**
- https://tfthacker.com/BRAT
1. https://tfthacker.com/BRAT
2. You can install this through the Community Plugins within Obsidian.

### Step 2: Install Caret
- Open up the BRAT Plugin
- Add the Personal Access Token
- Add the GitHub Personal Access Token from your confirmation email
- This enables read access to private Caret repo, which allows you to download the plugin
- PAT: `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`
- Click Add Beta Plugin
- For repo enter: `jcollingj/caret`
- You can choose whether you want to auto update the plugins or not! It might be useful while I'm rapidly iterating on this

### Step 3: Activate License:
- Go to Caret settings
- Enter the license you received in your email
- Click activate!
- Let me know if you have any issues at all with this please!

### Step 3: Configure Caret Settings
- Within your settings page open up the Caret settings
- Pick the model you want to use
- When you add API Keys you need to then reload the app for those changes to take effect. That's only for API keys. You can change the providers/models at any time without reloading.
- Note that there are a couple additional steps if you want to use ollama running locally


## Features
### Standard LLM Chat
- Like ChatGPT, but local first and the output is stored directly in your vault as markdown files. Meaning every conversation is instantly searchable and can be used as input to other Caret features.
- Open this from the chat icon added to the side bar.
- This does create a new folder `caret/chats` and stores all chats in this
- You can type `@` to bring up the at-command menu. This allows you to insert documents and use them as context
### Chat in Canvas
- Explore non-linear chats in the Obsidian canvas. Easily remix conversations by moving, linking, and unlinking nodes
- Use the node icon within the menu to add new nodes that are pre-formatted for user messages.
Expand All @@ -59,8 +68,20 @@ Caret enables new LLM-powered workflows in Obsidian.
- So if I had a property called `best_season` my code block would look like:
- ```xml
<best_season> Whats the best time visit the following location? </best_season>```
- I need to document this better!
- I'm also planning to add a view that will make creating these easier. Feel free to DM if you want to get started with this before I document it better/
### Inline Editing
- Inline editing can be used in markdown files. Either use the command pallette or CMD+J when you have text selected. That text will be used as the context. Add the prompt and then choose append or edit.
- The LLM will generate a response. This is added into your existing file. It will be formatted as a janky diff for now. So you can see what the changes would be before you apply them
- Then use the command "Apply Diffs" to apply those changes if you want them
- There is a lot of work to be done with this. For now it's just basic usage.

## What does my purchase entail?
- Your purchase of Caret is for life-time access and includes all future updates!
- I plan to maintain Caret as long as it's fun and profitable. I built Caret for myself first and continue to use it every day. Updates to Caret will be driven by my own usage and by the needs of early adopters (thank you for the support 🙏).
- I'm committed to maintaining Caret for the foreseeable future, but not forever. If at some point I decide to stop maintaining Caret I'm committed to open sourcing it.
- So to summarize: For $50 (or less), you get life-time access to Caret. If at any point I ever stop updating you and the community will have full access to the code itself. At that point anyone would be welcome to continue adding new features to it.


## Refund Policy
- If you're refund request is reasonable I'm down to refund.
5 changes: 0 additions & 5 deletions install.md

This file was deleted.

45 changes: 45 additions & 0 deletions license_hashing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
function generateConsistentSalt(): string {
// Ya ya, this is not secure in the slightest. Goal is to put up one modicum of effort towards ensuring people purchase
// And after that I would rather be focused on building and having fun
// Mind keeping this between us if possible?
// Would love if you could at least help out my work by tweeting about the plugin instead then.
const base =
"pleasebuyartisansoftwarebutalsoallgoodfriend.DMifyouneedsomething.Woudlappreciateyoukeepingthisonthedownlow";
let salt = "";
for (let i = 0; i < base.length; i++) {
const charCode = base.charCodeAt(i);
const shift = charCode % 3 === 0 ? 3 : charCode % 2 === 0 ? 1 : 2;
salt += String.fromCharCode(charCode + shift);
}
return salt;
}
export function generateHashForUUID(uuid: string): string {
const salt = generateConsistentSalt(); // Consistently generated, obfuscated salt
const combined = uuid + salt;
let hash = 0;
for (let i = 0; i < combined.length; i++) {
const char = combined.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash = hash & hash; // Convert to 32bit integer
}
return hash.toString(16); // Return hash as a hexadecimal string
}
export function validateUUIDHashPair(uuid: string, hash: string): boolean {
const generatedHash = generateHashForUUID(uuid);
console.log("Checking the generated hash");
return generatedHash === hash;
}
export async function validate_license_key(key: string) {
// ya ya I know here. This is literally a good sheet that has the license keys stored in it.
// I'm telling you this is not sophisticated anti-piracy.
// This is what can I do in 30 minutes to put up a speed bump.
const url = `https://script.google.com/macros/s/AKfycbzIOC4eyZ6ttfhONhBvrZZxYMNAqCT6K4RM-qkyGaCSsQ9yF1RJIxCGysbfMVrazeVfdg/exec?key=${key}`;
const output = await fetch(url);
console.log(output);
const json = await output.json();
console.log(json);
// Convert string values of 'status' and 'validKey' to actual boolean values
json.status = json.status === "true";
json.validKey = json.validKey === "true";
return json;
}
Loading

0 comments on commit 3370f2e

Please sign in to comment.