@spool-lab/connector-typeless 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ import type { SqliteDatabase } from '@spool/connector-sdk';
2
+ export declare const DEFAULT_DB_PATH: string;
3
+ export declare const PAGE_SIZE = 25;
4
+ export interface TypelessRow {
5
+ id: string;
6
+ refined_text: string | null;
7
+ edited_text: string | null;
8
+ status: string;
9
+ mode: string | null;
10
+ duration: number | null;
11
+ detected_language: string | null;
12
+ audio_local_path: string | null;
13
+ focused_app_name: string | null;
14
+ focused_app_bundle_id: string | null;
15
+ focused_app_window_title: string | null;
16
+ focused_app_window_web_url: string | null;
17
+ focused_app_window_web_domain: string | null;
18
+ focused_app_window_web_title: string | null;
19
+ created_at: string;
20
+ }
21
+ export declare function fetchTranscriptPage(db: SqliteDatabase, cursor: string | null): TypelessRow[];
22
+ //# sourceMappingURL=db-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-reader.d.ts","sourceRoot":"","sources":["../src/db-reader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAI1D,eAAO,MAAM,eAAe,QAM3B,CAAA;AAED,eAAO,MAAM,SAAS,KAAK,CAAA;AAE3B,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,0BAA0B,EAAE,MAAM,GAAG,IAAI,CAAA;IACzC,6BAA6B,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5C,4BAA4B,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3C,UAAU,EAAE,MAAM,CAAA;CACnB;AAeD,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,WAAW,EAAE,CAqBf"}
@@ -0,0 +1,33 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ export const DEFAULT_DB_PATH = join(homedir(), 'Library', 'Application Support', 'Typeless', 'typeless.db');
4
+ export const PAGE_SIZE = 25;
5
+ const SELECT_COLS = `
6
+ id, refined_text, edited_text, status, mode, duration, detected_language,
7
+ audio_local_path, focused_app_name, focused_app_bundle_id,
8
+ focused_app_window_title, focused_app_window_web_url,
9
+ focused_app_window_web_domain, focused_app_window_web_title, created_at
10
+ `;
11
+ const WHERE_TRANSCRIBED = `
12
+ status = 'transcript'
13
+ AND refined_text IS NOT NULL
14
+ AND refined_text != ''
15
+ `;
16
+ export function fetchTranscriptPage(db, cursor) {
17
+ if (cursor === null) {
18
+ return db
19
+ .prepare(`SELECT ${SELECT_COLS} FROM history
20
+ WHERE ${WHERE_TRANSCRIBED}
21
+ ORDER BY created_at DESC
22
+ LIMIT ?`)
23
+ .all(PAGE_SIZE);
24
+ }
25
+ return db
26
+ .prepare(`SELECT ${SELECT_COLS} FROM history
27
+ WHERE ${WHERE_TRANSCRIBED}
28
+ AND created_at < ?
29
+ ORDER BY created_at DESC
30
+ LIMIT ?`)
31
+ .all(cursor, PAGE_SIZE);
32
+ }
33
+ //# sourceMappingURL=db-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-reader.js","sourceRoot":"","sources":["../src/db-reader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CACjC,OAAO,EAAE,EACT,SAAS,EACT,qBAAqB,EACrB,UAAU,EACV,aAAa,CACd,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAA;AAoB3B,MAAM,WAAW,GAAG;;;;;CAKnB,CAAA;AAED,MAAM,iBAAiB,GAAG;;;;CAIzB,CAAA;AAED,MAAM,UAAU,mBAAmB,CACjC,EAAkB,EAClB,MAAqB;IAErB,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,EAAE;aACN,OAAO,CACN,UAAU,WAAW;iBACZ,iBAAiB;;iBAEjB,CACV;aACA,GAAG,CAAC,SAAS,CAAC,CAAA;IACnB,CAAC;IAED,OAAO,EAAE;SACN,OAAO,CACN,UAAU,WAAW;eACZ,iBAAiB;;;eAGjB,CACV;SACA,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;AAC3B,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Connector, ConnectorCapabilities, AuthStatus, PageResult, FetchContext } from '@spool/connector-sdk';
2
+ export default class TypelessConnector implements Connector {
3
+ private readonly caps;
4
+ readonly id = "typeless";
5
+ readonly platform = "typeless";
6
+ readonly label = "Typeless Voice";
7
+ readonly description = "Your voice transcripts from Typeless";
8
+ readonly color = "#1D1A1A";
9
+ readonly ephemeral = false;
10
+ private readonly dbPath;
11
+ constructor(caps: ConnectorCapabilities, opts?: {
12
+ dbPath?: string;
13
+ });
14
+ checkAuth(): Promise<AuthStatus>;
15
+ fetchPage(ctx: FetchContext): Promise<PageResult>;
16
+ }
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,qBAAqB,EACrB,UAAU,EACV,UAAU,EACV,YAAY,EAEb,MAAM,sBAAsB,CAAA;AAS7B,MAAM,CAAC,OAAO,OAAO,iBAAkB,YAAW,SAAS;IAWvD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAVvB,QAAQ,CAAC,EAAE,cAAa;IACxB,QAAQ,CAAC,QAAQ,cAAa;IAC9B,QAAQ,CAAC,KAAK,oBAAmB;IACjC,QAAQ,CAAC,WAAW,0CAAyC;IAC7D,QAAQ,CAAC,KAAK,aAAY;IAC1B,QAAQ,CAAC,SAAS,SAAQ;IAE1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;gBAGZ,IAAI,EAAE,qBAAqB,EAC5C,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAKtB,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC;IAehC,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC;CAmBxD"}
package/dist/index.js ADDED
@@ -0,0 +1,90 @@
1
+ import { SyncError, SyncErrorCode } from '@spool/connector-sdk';
2
+ import { fetchTranscriptPage, DEFAULT_DB_PATH, PAGE_SIZE, } from './db-reader.js';
3
+ export default class TypelessConnector {
4
+ caps;
5
+ id = 'typeless';
6
+ platform = 'typeless';
7
+ label = 'Typeless Voice';
8
+ description = 'Your voice transcripts from Typeless';
9
+ color = '#1D1A1A';
10
+ ephemeral = false;
11
+ dbPath;
12
+ constructor(caps, opts) {
13
+ this.caps = caps;
14
+ this.dbPath = opts?.dbPath ?? DEFAULT_DB_PATH;
15
+ }
16
+ async checkAuth() {
17
+ try {
18
+ const db = this.caps.sqlite.openReadonly(this.dbPath);
19
+ db.close();
20
+ return { ok: true };
21
+ }
22
+ catch (err) {
23
+ return {
24
+ ok: false,
25
+ error: SyncErrorCode.CONNECTOR_ERROR,
26
+ message: err instanceof Error ? err.message : String(err),
27
+ hint: 'Typeless not found. Install Typeless (typeless.com), record at least once, then retry.',
28
+ };
29
+ }
30
+ }
31
+ async fetchPage(ctx) {
32
+ let db = null;
33
+ try {
34
+ db = this.caps.sqlite.openReadonly(this.dbPath);
35
+ const rows = fetchTranscriptPage(db, ctx.cursor);
36
+ const items = rows.map(rowToCapturedItem);
37
+ const nextCursor = rows.length === PAGE_SIZE ? (rows[rows.length - 1]?.created_at ?? null) : null;
38
+ return { items, nextCursor };
39
+ }
40
+ catch (err) {
41
+ if (err instanceof SyncError)
42
+ throw err;
43
+ throw new SyncError(SyncErrorCode.CONNECTOR_ERROR, err instanceof Error ? err.message : String(err));
44
+ }
45
+ finally {
46
+ db?.close();
47
+ }
48
+ }
49
+ }
50
+ function rowToCapturedItem(row) {
51
+ const transcript = (row.edited_text?.trim() || row.refined_text?.trim()) ?? '';
52
+ const contextParts = [];
53
+ if (row.focused_app_name)
54
+ contextParts.push(row.focused_app_name);
55
+ if (row.focused_app_window_title)
56
+ contextParts.push(row.focused_app_window_title);
57
+ if (row.focused_app_window_web_domain)
58
+ contextParts.push(row.focused_app_window_web_domain);
59
+ if (row.focused_app_window_web_title)
60
+ contextParts.push(row.focused_app_window_web_title);
61
+ const contentText = contextParts.length > 0
62
+ ? `${transcript}\n${contextParts.join(' · ')}`
63
+ : transcript;
64
+ const title = transcript.length > 80 ? `${transcript.slice(0, 80)}…` : transcript;
65
+ const url = row.audio_local_path
66
+ ? `file://${row.audio_local_path}`
67
+ : `typeless://transcript/${row.id}`;
68
+ return {
69
+ url,
70
+ title,
71
+ contentText,
72
+ author: null,
73
+ platform: 'typeless',
74
+ platformId: row.id,
75
+ contentType: row.mode ?? 'voice_transcript',
76
+ thumbnailUrl: null,
77
+ metadata: {
78
+ duration: row.duration,
79
+ detected_language: row.detected_language,
80
+ focused_app: row.focused_app_name,
81
+ focused_app_bundle_id: row.focused_app_bundle_id,
82
+ focused_app_window_title: row.focused_app_window_title,
83
+ focused_app_window_web_url: row.focused_app_window_web_url,
84
+ focused_app_window_web_domain: row.focused_app_window_web_domain,
85
+ },
86
+ capturedAt: row.created_at,
87
+ rawJson: JSON.stringify(row),
88
+ };
89
+ }
90
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@spool-lab/connector-typeless",
3
+ "version": "0.1.0",
4
+ "description": "Your voice transcripts from Typeless for Spool",
5
+ "keywords": ["spool-connector", "typeless", "voice"],
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "files": ["dist"],
10
+ "scripts": {
11
+ "prepack": "pnpm run build",
12
+ "build": "tsc",
13
+ "clean": "rm -rf dist",
14
+ "test": "vitest run"
15
+ },
16
+ "peerDependencies": {
17
+ "@spool/connector-sdk": "workspace:^"
18
+ },
19
+ "devDependencies": {
20
+ "@spool/connector-sdk": "workspace:^",
21
+ "@types/better-sqlite3": "^7.6.13",
22
+ "@types/node": "^22.15.3",
23
+ "better-sqlite3": "^11.9.1",
24
+ "typescript": "^5.7.3",
25
+ "vitest": "^3.1.1"
26
+ },
27
+ "spool": {
28
+ "type": "connector",
29
+ "id": "typeless",
30
+ "platform": "typeless",
31
+ "label": "Typeless Voice",
32
+ "description": "Your voice transcripts from Typeless",
33
+ "color": "#1D1A1A",
34
+ "ephemeral": false,
35
+ "capabilities": ["sqlite", "log"]
36
+ }
37
+ }