Skip to content

Commit

Permalink
release-app fix issue browser_url filter in search api, update SDK, f…
Browse files Browse the repository at this point in the history
…ix small UX issue obsidian
  • Loading branch information
louis030195 committed Feb 27, 2025
1 parent 2a5476e commit b371c94
Show file tree
Hide file tree
Showing 12 changed files with 294 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ exclude = ["screenpipe-app-tauri/src-tauri"]
resolver = "2"

[workspace.package]
version = "0.2.59"
version = "0.2.60"
authors = ["louis030195 <[email protected]>"]
description = ""
repository = "https://github.com/mediar-ai/screenpipe"
Expand Down
2 changes: 1 addition & 1 deletion pipes/obsidian/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "obsidian",
"version": "0.1.27",
"version": "0.1.28",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
Expand Down
10 changes: 8 additions & 2 deletions pipes/obsidian/src/components/obsidian-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,9 @@ export function ObsidianSettings() {
type="button"
onClick={testLog}
variant="outline"
disabled={testLogLoading || !pathValidation.isValid}
disabled={
testLogLoading || !pathValidation.isValid || !settings?.logModel
}
className="flex-1"
>
{testLogLoading ? (
Expand All @@ -916,7 +918,11 @@ export function ObsidianSettings() {
type="button"
onClick={testIntelligence}
variant="outline"
disabled={intelligenceLoading || !pathValidation.isValid}
disabled={
intelligenceLoading ||
!pathValidation.isValid ||
!settings?.analysisModel
}
className="flex-1"
>
<Brain className="mr-2 h-4 w-4" />
Expand Down
2 changes: 1 addition & 1 deletion screenpipe-app-tauri/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "screenpipe-app"
version = "0.38.4"
version = "0.38.5"
description = ""
authors = ["you"]
license = ""
Expand Down
2 changes: 1 addition & 1 deletion screenpipe-js/browser-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@screenpipe/browser",
"version": "0.1.34",
"version": "0.1.35",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
Expand Down
134 changes: 134 additions & 0 deletions screenpipe-js/browser-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,140 @@ class BrowserPipeImpl implements BrowserPipe {
}
}

/**
* Query Screenpipe for content based on various filters.
*
* @param params - Query parameters for filtering Screenpipe content
* @returns Promise resolving to the Screenpipe response or null
*
* @example
* // Basic search for recent browser activity on a specific website
* const githubActivity = await pipe.queryScreenpipe({
* browserUrl: "github.com",
* contentType: "ocr",
* limit: 20,
* includeFrames: true
* });
*
* @example
* // Search for specific text on a particular website with date filters
* const searchResults = await pipe.queryScreenpipe({
* q: "authentication",
* browserUrl: "auth0.com",
* appName: "Chrome",
* contentType: "ocr",
* startTime: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),
* endTime: new Date().toISOString(),
* limit: 50
* });
*
* @example
* // Build a browser extension that searches your browsing history
* document.getElementById('searchBtn').addEventListener('click', async () => {
* const domain = document.getElementById('domainInput').value;
* const resultDiv = document.getElementById('results');
* resultDiv.innerHTML = '<p>Searching...</p>';
*
* try {
* const results = await pipe.queryScreenpipe({
* browserUrl: domain,
* contentType: "ocr",
* includeFrames: true,
* limit: 10
* });
*
* if (results.data.length === 0) {
* resultDiv.innerHTML = '<p>No results found</p>';
* return;
* }
*
* let html = '<div class="results-container">';
* results.data.forEach(item => {
* if (item.type === "OCR") {
* const content = item.content;
* html += `
* <div class="result-card">
* <h3>${content.windowName || 'Unnamed Window'}</h3>
* <p>${new Date(content.timestamp).toLocaleString()}</p>
* <div class="text-content">${content.text}</div>
* ${content.frame ? `<img src="data:image/png;base64,${content.frame}" />` : ''}
* </div>
* `;
* }
* });
* html += '</div>';
* resultDiv.innerHTML = html;
* } catch (error) {
* resultDiv.innerHTML = `<p>Error: ${error.message}</p>`;
* }
* });
*
* @example
* // Create a React component that displays website visit history
* import React, { useState, useEffect } from 'react';
* import { pipe, ContentType } from '@screenpipe/browser';
*
* function WebsiteHistoryViewer({ domain }) {
* const [visits, setVisits] = useState([]);
* const [loading, setLoading] = useState(true);
* const [error, setError] = useState(null);
*
* useEffect(() => {
* async function fetchVisits() {
* try {
* setLoading(true);
* const results = await pipe.queryScreenpipe({
* browserUrl: domain,
* contentType: "ocr" as ContentType,
* includeFrames: true,
* limit: 20
* });
*
* const processedVisits = results.data
* .filter(item => item.type === "OCR")
* .map(item => ({
* id: item.content.frameId,
* title: item.content.windowName || domain,
* timestamp: new Date(item.content.timestamp),
* text: item.content.text,
* thumbnail: item.content.frame
* }));
*
* setVisits(processedVisits);
* } catch (err) {
* setError(err.message);
* } finally {
* setLoading(false);
* }
* }
*
* fetchVisits();
* }, [domain]);
*
* if (loading) return <div>Loading visit history...</div>;
* if (error) return <div>Error: {error}</div>;
* if (visits.length === 0) return <div>No visits found for {domain}</div>;
*
* return (
* <div className="visits-container">
* <h2>Recent visits to {domain}</h2>
* {visits.map(visit => (
* <div key={visit.id} className="visit-card">
* <h3>{visit.title}</h3>
* <p>{visit.timestamp.toLocaleString()}</p>
* {visit.thumbnail && (
* <img
* src={`data:image/png;base64,${visit.thumbnail}`}
* alt={`Screenshot of ${domain}`}
* />
* )}
* <div className="visit-text">{visit.text}</div>
* </div>
* ))}
* </div>
* );
* }
*/
async queryScreenpipe(
params: ScreenpipeQueryParams
): Promise<ScreenpipeResponse | null> {
Expand Down
28 changes: 28 additions & 0 deletions screenpipe-js/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,47 @@ export type ContentType =
* Parameters for querying Screenpipe.
*/
export interface ScreenpipeQueryParams {
/** Optional search query text */
q?: string;

/** Type of content to search for (default: "all") */
contentType?: ContentType;

/** Maximum number of results to return (default: 10) */
limit?: number;

/** Number of results to skip (for pagination) */
offset?: number;

/** Filter results after this ISO timestamp (e.g. "2023-01-01T00:00:00Z") */
startTime?: string;

/** Filter results before this ISO timestamp (e.g. "2023-01-01T00:00:00Z") */
endTime?: string;

/** Filter by application name (e.g. "chrome", "vscode") */
appName?: string;

/** Filter by window title */
windowName?: string;

/** Include base64-encoded screenshot frames in results */
includeFrames?: boolean;

/** Filter by minimum text length */
minLength?: number;

/** Filter by maximum text length */
maxLength?: number;

/** Filter by specific speaker IDs */
speakerIds?: number[];

/** Filter by frame name */
frameName?: string;

/** Filter by browser URL (for web content) */
browserUrl?: string;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion screenpipe-js/node-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@screenpipe/js",
"version": "1.0.15",
"version": "1.0.16",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
Expand Down
103 changes: 103 additions & 0 deletions screenpipe-js/node-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,109 @@ class NodePipe {
}
}

/**
* Query Screenpipe for content based on various filters.
*
* @param params - Query parameters for filtering Screenpipe content
* @returns Promise resolving to the Screenpipe response or null
*
* @example
* // Basic search for recent browser activity on a specific website
* const githubActivity = await pipe.queryScreenpipe({
* browserUrl: "github.com",
* contentType: "ocr",
* limit: 20,
* includeFrames: true
* });
*
* @example
* // Search for specific text on a particular website with date filters
* const searchResults = await pipe.queryScreenpipe({
* q: "authentication",
* browserUrl: "auth0.com",
* appName: "Chrome",
* contentType: "ocr",
* startTime: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),
* endTime: new Date().toISOString(),
* limit: 50
* });
*
* @example
* // Track history of visits to a specific web application
* type VisitSession = {
* timestamp: string;
* title: string;
* textContent: string;
* imageData?: string;
* };
*
* async function getAppUsageHistory(domain: string): Promise<VisitSession[]> {
* try {
* const results = await pipe.queryScreenpipe({
* browserUrl: domain,
* contentType: "ocr",
* includeFrames: true,
* limit: 100,
* startTime: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString() // last 30 days
* });
*
* return results.data
* .filter(item => item.type === "OCR")
* .map(item => {
* const ocrItem = item.content as OCRContent;
* return {
* timestamp: ocrItem.timestamp,
* title: ocrItem.windowName || '',
* textContent: ocrItem.text,
* imageData: ocrItem.frame
* };
* });
* } catch (error) {
* console.error("Failed to retrieve app usage history:", error);
* return [];
* }
* }
*
* @example
* // Combining browserUrl with speaker filters for meeting recordings in browser
* import { pipe, ContentType, ScreenpipeResponse } from '@screenpipe/js';
*
* interface MeetingData {
* url: string;
* speakerName: string;
* transcript: string;
* timestamp: string;
* }
*
* async function getMeetingTranscripts(
* meetingUrl: string,
* speakerIds: number[]
* ): Promise<MeetingData[]> {
* try {
* const results = await pipe.queryScreenpipe({
* browserUrl: meetingUrl,
* contentType: "audio" as ContentType,
* speakerIds: speakerIds,
* limit: 200
* });
*
* return results.data
* .filter(item => item.type === "Audio")
* .map(item => {
* const audioItem = item.content;
* return {
* url: meetingUrl,
* speakerName: audioItem.speaker?.name || 'Unknown',
* transcript: audioItem.transcription,
* timestamp: audioItem.timestamp
* };
* });
* } catch (error) {
* console.error(`Error fetching meeting transcripts for ${meetingUrl}:`, error);
* return [];
* }
* }
*/
public async queryScreenpipe(
params: ScreenpipeQueryParams
): Promise<ScreenpipeResponse | null> {
Expand Down
2 changes: 1 addition & 1 deletion screenpipe-server/src/bin/screenpipe-server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,7 @@ async fn main() -> anyhow::Result<()> {
let shutdown_tx_clone = shutdown_tx.clone();
tokio::spawn(async move {
// sleep for 1 seconds
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
if watch_pid(pid).await {
info!("Watched pid ({}) has stopped, initiating shutdown", pid);

Expand Down
Loading

0 comments on commit b371c94

Please sign in to comment.