Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
db2cffb
Initial vector search
rogerb831 Sep 12, 2025
2a26135
Implement SQLite vector search with conversational RAG chat
rogerb831 Sep 13, 2025
d0169d4
Add transcript filtering to chat interface
rogerb831 Sep 13, 2025
f03b2b7
Add package-lock.json to .gitignore
rogerb831 Sep 13, 2025
4b4726e
Fix packaging issues for production builds
rogerb831 Sep 14, 2025
929cbc4
Merge pull request #1 from lukasbach/main
rogerb831 Oct 10, 2025
a6fe749
Revert "Add package-lock.json to .gitignore"
rogerb831 Oct 10, 2025
7794daa
Address PR feedback: fix imports, types, and add UI invalidation
rogerb831 Oct 10, 2025
752ec99
Config fixes
rogerb831 Oct 10, 2025
f6b4ed4
Add progress tracking for vector embedding step
rogerb831 Oct 10, 2025
59c2524
feat: make microphone recording default to enabled
rogerb831 Sep 16, 2025
428fbcc
feat: add toggleable recording preferences with persistence
rogerb831 Oct 10, 2025
723139a
Add recording-specific chat tab with scoped vector search
rogerb831 Oct 14, 2025
9ea88ee
Fix dependency issues for CI pipeline compatibility
rogerb831 Nov 5, 2025
ed2a55c
Fix linting errors for CI pipeline
rogerb831 Nov 5, 2025
e76f602
Fix TypeScript errors found by typecheck
rogerb831 Nov 5, 2025
71724b5
Add ability to rerun postprocessing. MP3 fallback for Whisper process…
rogerb831 Nov 5, 2025
7376e82
Enable macOS distributable builds in CI workflows
rogerb831 Nov 5, 2025
37b8f21
Fix macOS build: remove symlinks and add multi-architecture support
rogerb831 Nov 5, 2025
d2c608d
Fix CI: use macos-15-intel for x64 builds and fix console statements
rogerb831 Nov 5, 2025
f1eb7cb
Make GitHub publisher repository dynamic based on fork
rogerb831 Nov 5, 2025
77ddd08
Fix linting error: format repository name on single line
rogerb831 Nov 5, 2025
53c6119
Fix version bump conflict: run in separate job before matrix builds
rogerb831 Nov 5, 2025
088fdd8
Bump version only after all builds succeed
rogerb831 Nov 5, 2025
bca725a
Skip version bump for non-upstream repositories
rogerb831 Nov 5, 2025
e41d30e
Revert 'Bump version only after all builds succeed' (088fdd8)
rogerb831 Nov 5, 2025
d37c443
Add macOS .icns icon generation support
rogerb831 Nov 6, 2025
b71b9d9
Fix Prettier formatting errors in forge.config.ts
rogerb831 Nov 6, 2025
d4c1d1a
Fix Prettier formatting errors in recorder state.ts
rogerb831 Nov 6, 2025
8f462e5
Merge pull request #2 from rogerb831/toggleable-recorder-checkboxes
rogerb831 Nov 6, 2025
958d55c
Merge pull request #3 from rogerb831/fix/mac-distributable
rogerb831 Nov 6, 2025
1b8198f
Merge branch 'lukasbach:main' into feature/vector-search
rogerb831 Nov 6, 2025
8855e38
Merge branch 'main' into feature/vector-search
rogerb831 Nov 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 29 additions & 13 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,33 @@ on:
workflow_dispatch:

jobs:
bump-version:
if: github.repository == 'lukasbach/pensieve'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: 'paramsinghvc/gh-action-bump-version@master'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

publish:
runs-on: windows-latest
# strategy:
# matrix:
# os:
# [
# { name: 'windows', image: 'windows-latest' },
# { name: 'macos', image: 'macos-latest' },
# ]
# runs-on: ${{ matrix.os.image }}
needs: bump-version
if: always() && (needs.bump-version.result == 'success' || needs.bump-version.result == 'skipped')
strategy:
matrix:
include:
- os: windows
image: windows-latest
arch: ""
- os: macos
image: macos-latest
arch: arm64
- os: macos
image: macos-15-intel
arch: x64
runs-on: ${{ matrix.image }}
permissions:
contents: write
deployments: write
Expand All @@ -24,10 +41,9 @@ jobs:
- run: yarn lint
- run: yarn run typecheck
- run: yarn run build:docs
- run: yarn make
- uses: 'paramsinghvc/gh-action-bump-version@master'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: yarn make ${{ matrix.arch != '' && '--arch=' || '' }}${{ matrix.arch }}
- run: yarn publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
GITHUB_REPOSITORY: ${{ github.repository }}
16 changes: 14 additions & 2 deletions .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,19 @@ on:

jobs:
test:
runs-on: windows-latest
strategy:
matrix:
include:
- os: windows
image: windows-latest
arch: ""
- os: macos
image: macos-latest
arch: arm64
- os: macos
image: macos-15-intel
arch: x64
runs-on: ${{ matrix.image }}
permissions:
contents: read
id-token: write
Expand All @@ -19,4 +31,4 @@ jobs:
- run: yarn run lint
- run: yarn run typecheck
- run: yarn run build:docs
- run: yarn run make
- run: yarn run make ${{ matrix.arch != '' && '--arch=' || '' }}${{ matrix.arch }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,5 @@ extra
dist-docs
docs/index.md
docs/images
.vscode
.vscode
vector-store/vector-store.db
124 changes: 117 additions & 7 deletions forge.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import fs from "fs-extra";
import path from "path";
import { Resvg } from "@resvg/resvg-js";
import pngToIco from "png-to-ico";
import { exec } from "child_process";
import { promisify } from "util";

const execAsync = promisify(exec);

const createIcon = async (factor: number, base = 32) => {
const source = await fs.readFile(path.join(__dirname, "./icon.svg"), "utf-8");
Expand All @@ -30,26 +34,89 @@ const createIcon = async (factor: number, base = 32) => {
);
};

const createIcns = async () => {
const extraDir = path.join(__dirname, "extra");
const iconsetDir = path.join(extraDir, "icon.iconset");
await fs.ensureDir(iconsetDir);

// macOS requires specific icon sizes in .iconset format
// Format: icon_{size}x{size}.png and icon_{size}x{size}@2x.png
const sizes = [
{ size: 16, filename: "icon_16x16.png" },
{ size: 32, filename: "icon_16x16@2x.png" }, // 32x32 for @2x
{ size: 32, filename: "icon_32x32.png" },
{ size: 64, filename: "icon_32x32@2x.png" }, // 64x64 for @2x
{ size: 128, filename: "icon_128x128.png" },
{ size: 256, filename: "icon_128x128@2x.png" }, // 256x256 for @2x
{ size: 256, filename: "icon_256x256.png" },
{ size: 512, filename: "icon_256x256@2x.png" }, // 512x512 for @2x
{ size: 512, filename: "icon_512x512.png" },
{ size: 1024, filename: "icon_512x512@2x.png" }, // 1024x1024 for @2x
];

// Generate all required icon sizes
for (const { size, filename } of sizes) {
const source = await fs.readFile(
path.join(__dirname, "./icon.svg"),
"utf-8",
);
const resvg = new Resvg(source, {
background: "transparent",
fitTo: { mode: "width", value: size },
});
const png = resvg.render();
await fs.writeFile(path.join(iconsetDir, filename), png.asPng() as any);
}

// Convert .iconset to .icns using macOS iconutil
const icnsPath = path.join(extraDir, "icon.icns");
await execAsync(`iconutil -c icns "${iconsetDir}" -o "${icnsPath}"`);

// Clean up the .iconset directory
await fs.remove(iconsetDir);
};

const config: ForgeConfig = {
packagerConfig: {
asar: {
unpack: "*.{node,dll,exe}",
unpack: "**/*.node",
unpackDir: "node_modules/sqlite3",
},
extraResource: "./extra",
icon: "./extra/icon@8x.ico",
ignore: [
/^\/src/,
/^\/docs/,
/^\/images/,
/^\/\.github/,
/^\/\.idea/,
/^\/scripts/,
/^\/vector-store/,
/^\/\.git/,
/^\/\.gitignore/,
/^\/README\.md$/,
/^\/yarn\.lock$/,
/^\/\.yarnrc\.yml$/,
/^\/package-lock\.json$/,
],
},
rebuildConfig: {
// Explicitly exclude sqlite3 to avoid node-abi check issues
// sqlite3 will use prebuilt binaries or can be rebuilt manually
// onlyModules: ["sqlite3"],
onlyModules: [],
},
rebuildConfig: {},
makers: [
new MakerSquirrel({
loadingGif: path.join(__dirname, "splash.gif"),
setupIcon: "./extra/icon@8x.ico",
setupIcon: "./extra/icon.ico",
}),
// new MakerAppX({}),
new MakerZIP({}, ["darwin"]),
new MakerRpm({}),
new MakerDeb({}),
new MakerDMG({
icon: "./extra/icon@8x.ico",
icon: "./extra/icon.icns",
}),
],
plugins: [
Expand Down Expand Up @@ -93,8 +160,11 @@ const config: ForgeConfig = {
name: "@electron-forge/publisher-github",
config: {
repository: {
owner: "lukasbach",
name: "pensieve",
owner:
process.env.GITHUB_REPOSITORY_OWNER ||
process.env.GITHUB_REPOSITORY?.split("/")[0] ||
"lukasbach",
name: process.env.GITHUB_REPOSITORY?.split("/")[1] || "pensieve",
},
prerelease: false,
draft: true,
Expand All @@ -104,6 +174,38 @@ const config: ForgeConfig = {
],

hooks: {
packageAfterPrune: async (config, buildPath) => {
// Remove problematic symlinks in nested node_modules/.bin directories that break ASAR
// These symlinks point outside the package and cause ASAR packaging to fail.
// .bin directories are only needed for development (npm/yarn scripts), not at runtime.
const removeBinSymlinks = async (dir: string) => {
try {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
// Recursively check all directories
await removeBinSymlinks(fullPath);

// If this is a .bin directory, remove it entirely
if (entry.name === ".bin") {
await fs.remove(fullPath);
}
} else if (entry.isSymbolicLink()) {
// Remove individual symlinks
await fs.unlink(fullPath);
}
}
} catch (error) {
// Ignore errors - directory might not exist or be inaccessible
}
};

const nodeModulesPath = path.join(buildPath, "node_modules");
if (await fs.pathExists(nodeModulesPath)) {
await removeBinSymlinks(nodeModulesPath);
}
},
generateAssets: async (config, platform, arch) => {
const ffmpegBase = path.join(
__dirname,
Expand Down Expand Up @@ -157,14 +259,22 @@ const config: ForgeConfig = {

// Note: For macOS and Linux, FFmpeg and Whisper will use system installations

// Generate standard PNG icons (for runtime use)
await createIcon(1);
await createIcon(2);
await createIcon(3);
await createIcon(4);
await createIcon(8);

// Generate Windows ICO file (always generate for cross-platform builds)
await pngToIco(path.join(__dirname, "extra/icon@8x.png")).then((buf) =>
fs.writeFileSync(path.join(__dirname, "extra/icon@8x.ico"), buf as any),
fs.writeFileSync(path.join(__dirname, "extra/icon.ico"), buf as any),
);

// Generate macOS ICNS file (only on macOS due to iconutil requirement)
if (platform === "darwin") {
await createIcns();
}
},
},
};
Expand Down
Loading
Loading