@spool-lab/core 0.4.0 → 0.4.12
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.
- package/dist/db/db.d.ts +19 -0
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +210 -15
- package/dist/db/db.js.map +1 -1
- package/dist/db/queries.d.ts +36 -10
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +96 -75
- package/dist/db/queries.js.map +1 -1
- package/dist/db/share-drafts.d.ts +51 -0
- package/dist/db/share-drafts.d.ts.map +1 -0
- package/dist/db/share-drafts.js +47 -0
- package/dist/db/share-drafts.js.map +1 -0
- package/dist/doctor/checks/config.d.ts +3 -0
- package/dist/doctor/checks/config.d.ts.map +1 -0
- package/dist/doctor/checks/config.js +123 -0
- package/dist/doctor/checks/config.js.map +1 -0
- package/dist/doctor/checks/db.d.ts +3 -0
- package/dist/doctor/checks/db.d.ts.map +1 -0
- package/dist/doctor/checks/db.js +225 -0
- package/dist/doctor/checks/db.js.map +1 -0
- package/dist/doctor/checks/env.d.ts +3 -0
- package/dist/doctor/checks/env.d.ts.map +1 -0
- package/dist/doctor/checks/env.js +70 -0
- package/dist/doctor/checks/env.js.map +1 -0
- package/dist/doctor/checks/index.d.ts +3 -0
- package/dist/doctor/checks/index.d.ts.map +1 -0
- package/dist/doctor/checks/index.js +13 -0
- package/dist/doctor/checks/index.js.map +1 -0
- package/dist/doctor/checks/native.d.ts +3 -0
- package/dist/doctor/checks/native.d.ts.map +1 -0
- package/dist/doctor/checks/native.js +42 -0
- package/dist/doctor/checks/native.js.map +1 -0
- package/dist/doctor/checks/versions.d.ts +3 -0
- package/dist/doctor/checks/versions.d.ts.map +1 -0
- package/dist/doctor/checks/versions.js +79 -0
- package/dist/doctor/checks/versions.js.map +1 -0
- package/dist/doctor/index.d.ts +3 -0
- package/dist/doctor/index.d.ts.map +1 -0
- package/dist/doctor/index.js +3 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/preflight.d.ts +18 -0
- package/dist/doctor/preflight.d.ts.map +1 -0
- package/dist/doctor/preflight.js +27 -0
- package/dist/doctor/preflight.js.map +1 -0
- package/dist/doctor/runner.d.ts +12 -0
- package/dist/doctor/runner.d.ts.map +1 -0
- package/dist/doctor/runner.js +37 -0
- package/dist/doctor/runner.js.map +1 -0
- package/dist/doctor/types.d.ts +27 -0
- package/dist/doctor/types.d.ts.map +1 -0
- package/dist/doctor/types.js +2 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/migrations/agent-search-cleanup.d.ts +36 -0
- package/dist/migrations/agent-search-cleanup.d.ts.map +1 -0
- package/dist/migrations/agent-search-cleanup.js +182 -0
- package/dist/migrations/agent-search-cleanup.js.map +1 -0
- package/dist/migrations/worktree-identity-upgrade.d.ts +31 -0
- package/dist/migrations/worktree-identity-upgrade.d.ts.map +1 -0
- package/dist/migrations/worktree-identity-upgrade.js +22 -0
- package/dist/migrations/worktree-identity-upgrade.js.map +1 -0
- package/dist/parsers/claude.d.ts.map +1 -1
- package/dist/parsers/claude.js +25 -12
- package/dist/parsers/claude.js.map +1 -1
- package/dist/parsers/codex.d.ts.map +1 -1
- package/dist/parsers/codex.js +32 -5
- package/dist/parsers/codex.js.map +1 -1
- package/dist/parsers/gemini.d.ts.map +1 -1
- package/dist/parsers/gemini.js +5 -5
- package/dist/parsers/gemini.js.map +1 -1
- package/dist/parsers/spool-prelude.d.ts +16 -0
- package/dist/parsers/spool-prelude.d.ts.map +1 -0
- package/dist/parsers/spool-prelude.js +21 -0
- package/dist/parsers/spool-prelude.js.map +1 -0
- package/dist/projects/display-name.d.ts +2 -0
- package/dist/projects/display-name.d.ts.map +1 -0
- package/dist/projects/display-name.js +8 -0
- package/dist/projects/display-name.js.map +1 -0
- package/dist/projects/fs.d.ts +3 -0
- package/dist/projects/fs.d.ts.map +1 -0
- package/dist/projects/fs.js +20 -0
- package/dist/projects/fs.js.map +1 -0
- package/dist/projects/groups.d.ts +4 -0
- package/dist/projects/groups.d.ts.map +1 -0
- package/dist/projects/groups.js +20 -0
- package/dist/projects/groups.js.map +1 -0
- package/dist/projects/identity-synthesizers.d.ts +22 -0
- package/dist/projects/identity-synthesizers.d.ts.map +1 -0
- package/dist/projects/identity-synthesizers.js +29 -0
- package/dist/projects/identity-synthesizers.js.map +1 -0
- package/dist/projects/identity.d.ts +16 -0
- package/dist/projects/identity.d.ts.map +1 -0
- package/dist/projects/identity.js +172 -0
- package/dist/projects/identity.js.map +1 -0
- package/dist/projects/sessions.d.ts +12 -0
- package/dist/projects/sessions.d.ts.map +1 -0
- package/dist/projects/sessions.js +47 -0
- package/dist/projects/sessions.js.map +1 -0
- package/dist/projects/worktree-resolvers.d.ts +19 -0
- package/dist/projects/worktree-resolvers.d.ts.map +1 -0
- package/dist/projects/worktree-resolvers.js +65 -0
- package/dist/projects/worktree-resolvers.js.map +1 -0
- package/dist/sync/syncer.d.ts.map +1 -1
- package/dist/sync/syncer.js +11 -3
- package/dist/sync/syncer.js.map +1 -1
- package/dist/types.d.ts +15 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/connectors/capabilities/cookies-chrome.d.ts +0 -19
- package/dist/connectors/capabilities/cookies-chrome.d.ts.map +0 -1
- package/dist/connectors/capabilities/cookies-chrome.js +0 -199
- package/dist/connectors/capabilities/cookies-chrome.js.map +0 -1
- package/dist/connectors/capabilities/exec-impl.d.ts +0 -3
- package/dist/connectors/capabilities/exec-impl.d.ts.map +0 -1
- package/dist/connectors/capabilities/exec-impl.js +0 -108
- package/dist/connectors/capabilities/exec-impl.js.map +0 -1
- package/dist/connectors/capabilities/fetch-impl.d.ts +0 -3
- package/dist/connectors/capabilities/fetch-impl.d.ts.map +0 -1
- package/dist/connectors/capabilities/fetch-impl.js +0 -4
- package/dist/connectors/capabilities/fetch-impl.js.map +0 -1
- package/dist/connectors/capabilities/index.d.ts +0 -6
- package/dist/connectors/capabilities/index.d.ts.map +0 -1
- package/dist/connectors/capabilities/index.js +0 -6
- package/dist/connectors/capabilities/index.js.map +0 -1
- package/dist/connectors/capabilities/log-impl.d.ts +0 -3
- package/dist/connectors/capabilities/log-impl.d.ts.map +0 -1
- package/dist/connectors/capabilities/log-impl.js +0 -26
- package/dist/connectors/capabilities/log-impl.js.map +0 -1
- package/dist/connectors/capabilities/sqlite-impl.d.ts +0 -3
- package/dist/connectors/capabilities/sqlite-impl.d.ts.map +0 -1
- package/dist/connectors/capabilities/sqlite-impl.js +0 -19
- package/dist/connectors/capabilities/sqlite-impl.js.map +0 -1
- package/dist/connectors/loader.d.ts +0 -47
- package/dist/connectors/loader.d.ts.map +0 -1
- package/dist/connectors/loader.js +0 -328
- package/dist/connectors/loader.js.map +0 -1
- package/dist/connectors/npm-install.d.ts +0 -26
- package/dist/connectors/npm-install.d.ts.map +0 -1
- package/dist/connectors/npm-install.js +0 -74
- package/dist/connectors/npm-install.js.map +0 -1
- package/dist/connectors/prerequisites.d.ts +0 -14
- package/dist/connectors/prerequisites.d.ts.map +0 -1
- package/dist/connectors/prerequisites.js +0 -109
- package/dist/connectors/prerequisites.js.map +0 -1
- package/dist/connectors/registry-fetch.d.ts +0 -22
- package/dist/connectors/registry-fetch.d.ts.map +0 -1
- package/dist/connectors/registry-fetch.js +0 -54
- package/dist/connectors/registry-fetch.js.map +0 -1
- package/dist/connectors/registry.d.ts +0 -23
- package/dist/connectors/registry.d.ts.map +0 -1
- package/dist/connectors/registry.js +0 -59
- package/dist/connectors/registry.js.map +0 -1
- package/dist/connectors/sync-engine.d.ts +0 -31
- package/dist/connectors/sync-engine.d.ts.map +0 -1
- package/dist/connectors/sync-engine.js +0 -604
- package/dist/connectors/sync-engine.js.map +0 -1
- package/dist/connectors/sync-scheduler.d.ts +0 -56
- package/dist/connectors/sync-scheduler.d.ts.map +0 -1
- package/dist/connectors/sync-scheduler.js +0 -238
- package/dist/connectors/sync-scheduler.js.map +0 -1
- package/dist/connectors/trust-store.d.ts +0 -13
- package/dist/connectors/trust-store.d.ts.map +0 -1
- package/dist/connectors/trust-store.js +0 -48
- package/dist/connectors/trust-store.js.map +0 -1
- package/dist/connectors/types.d.ts +0 -111
- package/dist/connectors/types.d.ts.map +0 -1
- package/dist/connectors/types.js +0 -50
- package/dist/connectors/types.js.map +0 -1
package/dist/parsers/gemini.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
|
+
import { stripSpoolSystemPrelude } from './spool-prelude.js';
|
|
4
5
|
const GEMINI_INDEXABLE_TYPES = new Set(['user', 'gemini', 'info', 'warning', 'error']);
|
|
5
6
|
export function loadGeminiSession(filePath) {
|
|
6
7
|
const raw = readFileSync(filePath, 'utf8');
|
|
@@ -74,14 +75,14 @@ function toParsedRole(type) {
|
|
|
74
75
|
}
|
|
75
76
|
function extractText(content) {
|
|
76
77
|
if (typeof content === 'string')
|
|
77
|
-
return content
|
|
78
|
+
return stripSpoolSystemPrelude(content);
|
|
78
79
|
if (content && typeof content === 'object' && !Array.isArray(content)) {
|
|
79
80
|
const text = content['text'];
|
|
80
|
-
return typeof text === 'string' ? text
|
|
81
|
+
return typeof text === 'string' ? stripSpoolSystemPrelude(text) : '';
|
|
81
82
|
}
|
|
82
83
|
if (!Array.isArray(content))
|
|
83
84
|
return '';
|
|
84
|
-
return content
|
|
85
|
+
return stripSpoolSystemPrelude(content
|
|
85
86
|
.map(item => {
|
|
86
87
|
if (typeof item === 'string')
|
|
87
88
|
return item;
|
|
@@ -91,8 +92,7 @@ function extractText(content) {
|
|
|
91
92
|
return typeof text === 'string' ? text : '';
|
|
92
93
|
})
|
|
93
94
|
.filter(Boolean)
|
|
94
|
-
.join('\n')
|
|
95
|
-
.trim();
|
|
95
|
+
.join('\n'));
|
|
96
96
|
}
|
|
97
97
|
function extractToolNames(toolCalls) {
|
|
98
98
|
if (!Array.isArray(toolCalls))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/parsers/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/parsers/gemini.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spool wraps its agent-search system instructions in this marker before
|
|
3
|
+
* sending them to ACP, so the parsers can strip them back out when indexing
|
|
4
|
+
* the on-disk JSONL. Without the marker, our system prompt would appear as
|
|
5
|
+
* the first user message in every agent-search session — polluting the
|
|
6
|
+
* derived title, the FTS index, and the session detail view.
|
|
7
|
+
*
|
|
8
|
+
* The user's actual query is sent OUTSIDE the marker block (at the end of
|
|
9
|
+
* the message text), so after stripping the prelude only the bare query
|
|
10
|
+
* remains.
|
|
11
|
+
*/
|
|
12
|
+
export declare const SPOOL_SYSTEM_PRELUDE_OPEN = "<spool-system-prelude>";
|
|
13
|
+
export declare const SPOOL_SYSTEM_PRELUDE_CLOSE = "</spool-system-prelude>";
|
|
14
|
+
export declare function wrapSpoolSystemPrelude(systemBody: string, userQuery: string): string;
|
|
15
|
+
export declare function stripSpoolSystemPrelude(text: string): string;
|
|
16
|
+
//# sourceMappingURL=spool-prelude.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spool-prelude.d.ts","sourceRoot":"","sources":["../../src/parsers/spool-prelude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,2BAA2B,CAAA;AACjE,eAAO,MAAM,0BAA0B,4BAA4B,CAAA;AAEnE,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpF;AAID,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5D"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spool wraps its agent-search system instructions in this marker before
|
|
3
|
+
* sending them to ACP, so the parsers can strip them back out when indexing
|
|
4
|
+
* the on-disk JSONL. Without the marker, our system prompt would appear as
|
|
5
|
+
* the first user message in every agent-search session — polluting the
|
|
6
|
+
* derived title, the FTS index, and the session detail view.
|
|
7
|
+
*
|
|
8
|
+
* The user's actual query is sent OUTSIDE the marker block (at the end of
|
|
9
|
+
* the message text), so after stripping the prelude only the bare query
|
|
10
|
+
* remains.
|
|
11
|
+
*/
|
|
12
|
+
export const SPOOL_SYSTEM_PRELUDE_OPEN = '<spool-system-prelude>';
|
|
13
|
+
export const SPOOL_SYSTEM_PRELUDE_CLOSE = '</spool-system-prelude>';
|
|
14
|
+
export function wrapSpoolSystemPrelude(systemBody, userQuery) {
|
|
15
|
+
return `${SPOOL_SYSTEM_PRELUDE_OPEN}\n${systemBody}\n${SPOOL_SYSTEM_PRELUDE_CLOSE}\n\n${userQuery}`;
|
|
16
|
+
}
|
|
17
|
+
const STRIP_RE = /<spool-system-prelude>[\s\S]*?<\/spool-system-prelude>/g;
|
|
18
|
+
export function stripSpoolSystemPrelude(text) {
|
|
19
|
+
return text.replace(STRIP_RE, '').trim();
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=spool-prelude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spool-prelude.js","sourceRoot":"","sources":["../../src/parsers/spool-prelude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,wBAAwB,CAAA;AACjE,MAAM,CAAC,MAAM,0BAA0B,GAAG,yBAAyB,CAAA;AAEnE,MAAM,UAAU,sBAAsB,CAAC,UAAkB,EAAE,SAAiB;IAC1E,OAAO,GAAG,yBAAyB,KAAK,UAAU,KAAK,0BAA0B,OAAO,SAAS,EAAE,CAAA;AACrG,CAAC;AAED,MAAM,QAAQ,GAAG,yDAAyD,CAAA;AAE1E,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;AAC1C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-name.d.ts","sourceRoot":"","sources":["../../src/projects/display-name.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKzD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function fallbackDisplayName(input) {
|
|
2
|
+
if (input === '/')
|
|
3
|
+
return '(root)';
|
|
4
|
+
const trimmed = input.replace(/\/+$/, '');
|
|
5
|
+
const parts = trimmed.split('/').filter(Boolean);
|
|
6
|
+
return parts[parts.length - 1] ?? trimmed;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=display-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-name.js","sourceRoot":"","sources":["../../src/projects/display-name.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,KAAK,KAAK,GAAG;QAAE,OAAO,QAAQ,CAAA;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAChD,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,OAAO,CAAA;AAC3C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/projects/fs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE/C,eAAO,MAAM,MAAM,EAAE,UAWpB,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
export const realFs = {
|
|
4
|
+
exists: existsSync,
|
|
5
|
+
readText: (p) => {
|
|
6
|
+
try {
|
|
7
|
+
return readFileSync(p, 'utf8');
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
spawn: (cmd, args, opts) => {
|
|
14
|
+
// 5s timeout: a hung `git config` (e.g. ssh-agent passphrase prompt,
|
|
15
|
+
// network-mounted repo) must not block session indexing.
|
|
16
|
+
const r = spawnSync(cmd, args, { cwd: opts.cwd, encoding: 'utf8', timeout: 5000 });
|
|
17
|
+
return { stdout: r.stdout ?? '', exitCode: r.status ?? 1 };
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=fs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/projects/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAG9C,MAAM,CAAC,MAAM,MAAM,GAAe;IAChC,MAAM,EAAE,UAAU;IAClB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;QACd,IAAI,CAAC;YAAC,OAAO,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,IAAI,CAAA;QAAC,CAAC;IAC9D,CAAC;IACD,KAAK,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QACzB,qEAAqE;QACrE,yDAAyD;QACzD,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;QAClF,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,EAAE,CAAA;IAC5D,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../../src/projects/groups.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAsC,MAAM,aAAa,CAAA;AAEnF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,YAAY,EAAE,CAyBvE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function listProjectGroups(db) {
|
|
2
|
+
const rows = db.prepare(`
|
|
3
|
+
SELECT identity_kind, identity_key, display_name, sources_csv,
|
|
4
|
+
session_count, last_session_at
|
|
5
|
+
FROM project_groups_v
|
|
6
|
+
ORDER BY
|
|
7
|
+
CASE identity_kind WHEN 'loose' THEN 1 ELSE 0 END,
|
|
8
|
+
last_session_at IS NULL,
|
|
9
|
+
last_session_at DESC
|
|
10
|
+
`).all();
|
|
11
|
+
return rows.map(r => ({
|
|
12
|
+
identityKind: r.identity_kind,
|
|
13
|
+
identityKey: r.identity_key,
|
|
14
|
+
displayName: r.display_name,
|
|
15
|
+
sources: (r.sources_csv ?? '').split(',').filter(Boolean),
|
|
16
|
+
sessionCount: r.session_count,
|
|
17
|
+
lastSessionAt: r.last_session_at,
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=groups.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groups.js","sourceRoot":"","sources":["../../src/projects/groups.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,iBAAiB,CAAC,EAAqB;IACrD,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;;GAQvB,CAAC,CAAC,GAAG,EAOJ,CAAA;IACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpB,YAAY,EAAE,CAAC,CAAC,aAAa;QAC7B,WAAW,EAAE,CAAC,CAAC,YAAY;QAC3B,WAAW,EAAE,CAAC,CAAC,YAAY;QAC3B,OAAO,EAAE,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAoB;QAC5E,YAAY,EAAE,CAAC,CAAC,aAAa;QAC7B,aAAa,EAAE,CAAC,CAAC,eAAe;KACjC,CAAC,CAAC,CAAA;AACL,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ProjectIdentity } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Collapses sessions whose cwd is a known "scratch workspace" pattern into a
|
|
4
|
+
* single synthetic project — the workspace dir itself carries no useful
|
|
5
|
+
* identity signal (no .git, no manifest), so without this each chat shows up
|
|
6
|
+
* as its own sidebar entry.
|
|
7
|
+
*
|
|
8
|
+
* Each synthesizer matches a cwd and returns a stable identity shared by all
|
|
9
|
+
* sessions in that scope. Returns null to defer to the next rule.
|
|
10
|
+
*/
|
|
11
|
+
export interface IdentitySynthesizer {
|
|
12
|
+
name: string;
|
|
13
|
+
synthesize(cwd: string): ProjectIdentity | null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Codex desktop creates one disposable workspace per non-project chat at
|
|
17
|
+
* `~/Documents/Codex/<YYYY-MM-DD>/<slug>/`. Group every such chat under a
|
|
18
|
+
* single synthetic "Codex" project so they don't litter the sidebar.
|
|
19
|
+
*/
|
|
20
|
+
export declare const codexScratchSynthesizer: IdentitySynthesizer;
|
|
21
|
+
export declare const DEFAULT_SYNTHESIZERS: readonly IdentitySynthesizer[];
|
|
22
|
+
//# sourceMappingURL=identity-synthesizers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-synthesizers.d.ts","sourceRoot":"","sources":["../../src/projects/identity-synthesizers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAOlD;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAAA;CAChD;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,mBAYrC,CAAA;AAED,eAAO,MAAM,oBAAoB,EAAE,SAAS,mBAAmB,EAE7D,CAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
// Resolved at call time so process.env.HOME overrides take effect in tests.
|
|
4
|
+
function getHome() {
|
|
5
|
+
return process.env['HOME'] || homedir();
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Codex desktop creates one disposable workspace per non-project chat at
|
|
9
|
+
* `~/Documents/Codex/<YYYY-MM-DD>/<slug>/`. Group every such chat under a
|
|
10
|
+
* single synthetic "Codex" project so they don't litter the sidebar.
|
|
11
|
+
*/
|
|
12
|
+
export const codexScratchSynthesizer = {
|
|
13
|
+
name: 'codex-scratch',
|
|
14
|
+
synthesize(cwd) {
|
|
15
|
+
const root = join(getHome(), 'Documents', 'Codex');
|
|
16
|
+
if (!cwd.startsWith(root + '/'))
|
|
17
|
+
return null;
|
|
18
|
+
return {
|
|
19
|
+
kind: 'synthetic',
|
|
20
|
+
key: 'codex:scratch',
|
|
21
|
+
displayName: 'Codex Chats',
|
|
22
|
+
displayPath: root,
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
export const DEFAULT_SYNTHESIZERS = Object.freeze([
|
|
27
|
+
codexScratchSynthesizer,
|
|
28
|
+
]);
|
|
29
|
+
//# sourceMappingURL=identity-synthesizers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-synthesizers.js","sourceRoot":"","sources":["../../src/projects/identity-synthesizers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGhC,4EAA4E;AAC5E,SAAS,OAAO;IACd,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,CAAA;AACzC,CAAC;AAgBD;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAwB;IAC1D,IAAI,EAAE,eAAe;IACrB,UAAU,CAAC,GAAW;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,CAAA;QAClD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC;YAAE,OAAO,IAAI,CAAA;QAC5C,OAAO;YACL,IAAI,EAAE,WAAW;YACjB,GAAG,EAAE,eAAe;YACpB,WAAW,EAAE,aAAa;YAC1B,WAAW,EAAE,IAAI;SAClB,CAAA;IACH,CAAC;CACF,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAmC,MAAM,CAAC,MAAM,CAAC;IAChF,uBAAuB;CACxB,CAAC,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ProjectIdentity } from '../types.js';
|
|
2
|
+
import { type WorktreeUpstreamResolver } from './worktree-resolvers.js';
|
|
3
|
+
import { type IdentitySynthesizer } from './identity-synthesizers.js';
|
|
4
|
+
export interface IdentityFs {
|
|
5
|
+
exists(path: string): boolean;
|
|
6
|
+
readText(path: string): string | null;
|
|
7
|
+
spawn(cmd: string, args: string[], opts: {
|
|
8
|
+
cwd: string;
|
|
9
|
+
}): {
|
|
10
|
+
stdout: string;
|
|
11
|
+
exitCode: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function normalizeGitRemote(url: string): string | null;
|
|
15
|
+
export declare function computeIdentity(cwd: string | null, fs: IdentityFs, resolvers?: readonly WorktreeUpstreamResolver[], synthesizers?: readonly IdentitySynthesizer[]): ProjectIdentity;
|
|
16
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/projects/identity.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAuB,MAAM,aAAa,CAAA;AAEvE,OAAO,EAAqB,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAA;AAC1F,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAE3F,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACrC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAChG;AAgBD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU7D;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,EAAE,EAAE,UAAU,EACd,SAAS,GAAE,SAAS,wBAAwB,EAAsB,EAClE,YAAY,GAAE,SAAS,mBAAmB,EAAyB,GAClE,eAAe,CA6EjB"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { dirname, join, isAbsolute, resolve } from 'node:path';
|
|
3
|
+
import { fallbackDisplayName } from './display-name.js';
|
|
4
|
+
import { DEFAULT_RESOLVERS } from './worktree-resolvers.js';
|
|
5
|
+
import { DEFAULT_SYNTHESIZERS } from './identity-synthesizers.js';
|
|
6
|
+
const MANIFESTS = [
|
|
7
|
+
'package.json', 'Cargo.toml', 'pyproject.toml',
|
|
8
|
+
'go.mod', 'Gemfile', 'pom.xml', 'build.gradle',
|
|
9
|
+
];
|
|
10
|
+
const PARSEABLE_MANIFESTS = [
|
|
11
|
+
'package.json', 'Cargo.toml', 'pyproject.toml',
|
|
12
|
+
];
|
|
13
|
+
const LOOSE_DIRS = new Set([
|
|
14
|
+
'/tmp', '/private/tmp',
|
|
15
|
+
]);
|
|
16
|
+
const LOOSE_HOME_DIRS = ['Desktop', 'Downloads', 'Documents'];
|
|
17
|
+
export function normalizeGitRemote(url) {
|
|
18
|
+
if (!url)
|
|
19
|
+
return null;
|
|
20
|
+
let s = url.trim().replace(/\.git$/, '');
|
|
21
|
+
// git@host:owner/repo → host/owner/repo
|
|
22
|
+
const sshMatch = s.match(/^[^@]+@([^:]+):(.+)$/);
|
|
23
|
+
if (sshMatch)
|
|
24
|
+
s = `${sshMatch[1]}/${sshMatch[2]}`;
|
|
25
|
+
// strip protocol + credentials
|
|
26
|
+
s = s.replace(/^[a-z]+:\/\/(?:[^@/]*@)?/i, '');
|
|
27
|
+
if (!s.includes('/'))
|
|
28
|
+
return null;
|
|
29
|
+
return s.toLowerCase();
|
|
30
|
+
}
|
|
31
|
+
export function computeIdentity(cwd, fs, resolvers = DEFAULT_RESOLVERS, synthesizers = DEFAULT_SYNTHESIZERS) {
|
|
32
|
+
if (!cwd)
|
|
33
|
+
return loose();
|
|
34
|
+
const home = homedir();
|
|
35
|
+
if (cwd === home || LOOSE_DIRS.has(cwd))
|
|
36
|
+
return loose();
|
|
37
|
+
if (LOOSE_HOME_DIRS.some(d => cwd === join(home, d)))
|
|
38
|
+
return loose();
|
|
39
|
+
// 1. git
|
|
40
|
+
const gitRoot = findGitRoot(cwd, fs);
|
|
41
|
+
if (gitRoot) {
|
|
42
|
+
const remote = fs.spawn('git', ['config', '--get', 'remote.origin.url'], { cwd: gitRoot });
|
|
43
|
+
if (remote.exitCode === 0) {
|
|
44
|
+
const norm = normalizeGitRemote(remote.stdout.trim());
|
|
45
|
+
if (norm) {
|
|
46
|
+
return {
|
|
47
|
+
kind: 'git_remote',
|
|
48
|
+
key: norm,
|
|
49
|
+
displayName: deriveDisplayName({ kind: 'git_remote', key: norm, gitRoot, fs }),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const common = fs.spawn('git', ['rev-parse', '--git-common-dir'], { cwd: gitRoot });
|
|
54
|
+
if (common.exitCode === 0) {
|
|
55
|
+
const raw = common.stdout.trim();
|
|
56
|
+
if (raw) {
|
|
57
|
+
const key = isAbsolute(raw) ? raw : resolve(gitRoot, raw);
|
|
58
|
+
return {
|
|
59
|
+
kind: 'git_common_dir',
|
|
60
|
+
key,
|
|
61
|
+
displayName: deriveDisplayName({ kind: 'git_common_dir', key, gitRoot, fs }),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// 2. manifest
|
|
67
|
+
const manifestDir = findManifestDir(cwd, fs);
|
|
68
|
+
if (manifestDir) {
|
|
69
|
+
return {
|
|
70
|
+
kind: 'manifest_path',
|
|
71
|
+
key: manifestDir,
|
|
72
|
+
displayName: deriveDisplayName({ kind: 'manifest_path', key: manifestDir, fs }),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// 3. worktree resolvers — recover identity for sessions whose cwd has been
|
|
76
|
+
// deleted (e.g. superset/git worktree torn down before Spool synced). The
|
|
77
|
+
// resolver returns the upstream main-repo path; we recurse with empty
|
|
78
|
+
// resolvers to prevent loops and to ensure the upstream goes through the
|
|
79
|
+
// normal git/manifest detection on a real, existing path.
|
|
80
|
+
if (!fs.exists(cwd) && resolvers.length > 0) {
|
|
81
|
+
for (const r of resolvers) {
|
|
82
|
+
const upstream = r.resolve(cwd);
|
|
83
|
+
if (!upstream || !fs.exists(upstream))
|
|
84
|
+
continue;
|
|
85
|
+
const id = computeIdentity(upstream, fs, [], []);
|
|
86
|
+
if (id.kind === 'git_remote' || id.kind === 'git_common_dir' || id.kind === 'manifest_path') {
|
|
87
|
+
return id;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// 4. identity synthesizers — collapse known scratch-workspace patterns
|
|
92
|
+
// (e.g. Codex desktop's per-chat temp dirs under ~/Documents/Codex/<date>/)
|
|
93
|
+
// into a single synthetic project. Only runs when no real project signal
|
|
94
|
+
// was found above; a chat that happens to live inside a real git repo or
|
|
95
|
+
// manifest still groups under that repo.
|
|
96
|
+
for (const s of synthesizers) {
|
|
97
|
+
const id = s.synthesize(cwd);
|
|
98
|
+
if (id)
|
|
99
|
+
return id;
|
|
100
|
+
}
|
|
101
|
+
// 5. path
|
|
102
|
+
return {
|
|
103
|
+
kind: 'path',
|
|
104
|
+
key: cwd,
|
|
105
|
+
displayName: fallbackDisplayName(cwd),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function loose() {
|
|
109
|
+
return { kind: 'loose', key: 'loose', displayName: 'Loose' };
|
|
110
|
+
}
|
|
111
|
+
function findGitRoot(start, fs) {
|
|
112
|
+
let cur = start;
|
|
113
|
+
while (cur && cur !== '/') {
|
|
114
|
+
if (fs.exists(join(cur, '.git')))
|
|
115
|
+
return cur;
|
|
116
|
+
const parent = dirname(cur);
|
|
117
|
+
if (parent === cur)
|
|
118
|
+
break;
|
|
119
|
+
cur = parent;
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
function findManifestDir(start, fs) {
|
|
124
|
+
let cur = start;
|
|
125
|
+
while (cur && cur !== '/') {
|
|
126
|
+
for (const m of MANIFESTS) {
|
|
127
|
+
if (fs.exists(join(cur, m)))
|
|
128
|
+
return cur;
|
|
129
|
+
}
|
|
130
|
+
const parent = dirname(cur);
|
|
131
|
+
if (parent === cur)
|
|
132
|
+
break;
|
|
133
|
+
cur = parent;
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
function deriveDisplayName(input) {
|
|
138
|
+
// Try manifest name first
|
|
139
|
+
const dir = input.gitRoot ?? (input.kind === 'manifest_path' ? input.key : null);
|
|
140
|
+
if (dir) {
|
|
141
|
+
for (const m of PARSEABLE_MANIFESTS) {
|
|
142
|
+
const p = join(dir, m);
|
|
143
|
+
if (input.fs.exists(p)) {
|
|
144
|
+
const name = parseManifestName(m, input.fs.readText(p) ?? '');
|
|
145
|
+
if (name)
|
|
146
|
+
return name;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// git remote → last segment
|
|
151
|
+
if (input.kind === 'git_remote') {
|
|
152
|
+
const parts = input.key.split('/');
|
|
153
|
+
return parts[parts.length - 1] || input.key;
|
|
154
|
+
}
|
|
155
|
+
// common-dir or path → containing dir name
|
|
156
|
+
if (input.gitRoot)
|
|
157
|
+
return fallbackDisplayName(input.gitRoot);
|
|
158
|
+
return fallbackDisplayName(input.key);
|
|
159
|
+
}
|
|
160
|
+
function parseManifestName(file, text) {
|
|
161
|
+
if (!text)
|
|
162
|
+
return null;
|
|
163
|
+
if (file === 'package.json' || file === 'Cargo.toml' || file === 'pyproject.toml') {
|
|
164
|
+
// Cheap regex: find name = "x" or "name": "x"
|
|
165
|
+
const m = text.match(/"name"\s*:\s*"([^"]+)"/) ||
|
|
166
|
+
text.match(/^\s*name\s*=\s*"([^"]+)"/m);
|
|
167
|
+
if (m && m[1])
|
|
168
|
+
return m[1];
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/projects/identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { Session, SessionSource } from '../types.js';
|
|
3
|
+
export type ProjectSessionSortOrder = 'recent' | 'oldest' | 'most_messages' | 'title';
|
|
4
|
+
export interface ListSessionsByIdentityOptions {
|
|
5
|
+
sources?: SessionSource[];
|
|
6
|
+
sortOrder?: ProjectSessionSortOrder;
|
|
7
|
+
limit?: number;
|
|
8
|
+
excludePinned?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function listSessionsByIdentity(db: Database.Database, identityKey: string, options?: ListSessionsByIdentityOptions): Session[];
|
|
11
|
+
export declare function listPinnedSessionsByIdentity(db: Database.Database, identityKey: string): Session[];
|
|
12
|
+
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/projects/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGzD,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,QAAQ,GAAG,eAAe,GAAG,OAAO,CAAA;AAErF,MAAM,WAAW,6BAA6B;IAC5C,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;IACzB,SAAS,CAAC,EAAE,uBAAuB,CAAA;IACnC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,6BAAkC,GAC1C,OAAO,EAAE,CA2BX;AAED,wBAAgB,4BAA4B,CAC1C,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,EAAE,CAQX"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { SESSION_SELECT, rowToSession } from '../db/queries.js';
|
|
2
|
+
export function listSessionsByIdentity(db, identityKey, options = {}) {
|
|
3
|
+
const { sources, sortOrder = 'recent', limit = 500, excludePinned = false } = options;
|
|
4
|
+
const conditions = ['p.identity_key = ?', 's.message_count > 0'];
|
|
5
|
+
const params = [identityKey];
|
|
6
|
+
if (sources && sources.length > 0) {
|
|
7
|
+
const placeholders = sources.map(() => '?').join(',');
|
|
8
|
+
conditions.push(`src.name IN (${placeholders})`);
|
|
9
|
+
params.push(...sources);
|
|
10
|
+
}
|
|
11
|
+
if (excludePinned) {
|
|
12
|
+
conditions.push('NOT EXISTS (SELECT 1 FROM pins WHERE pins.session_uuid = s.session_uuid)');
|
|
13
|
+
}
|
|
14
|
+
const orderBy = orderByClause(sortOrder);
|
|
15
|
+
const sql = `
|
|
16
|
+
${SESSION_SELECT}
|
|
17
|
+
WHERE ${conditions.join(' AND ')}
|
|
18
|
+
ORDER BY ${orderBy}
|
|
19
|
+
LIMIT ?
|
|
20
|
+
`;
|
|
21
|
+
params.push(limit);
|
|
22
|
+
const rows = db.prepare(sql).all(...params);
|
|
23
|
+
return rows.map(rowToSession);
|
|
24
|
+
}
|
|
25
|
+
export function listPinnedSessionsByIdentity(db, identityKey) {
|
|
26
|
+
const rows = db.prepare(`
|
|
27
|
+
${SESSION_SELECT}
|
|
28
|
+
JOIN pins ON pins.session_uuid = s.session_uuid
|
|
29
|
+
WHERE p.identity_key = ? AND s.message_count > 0
|
|
30
|
+
ORDER BY pins.pinned_at DESC
|
|
31
|
+
`).all(identityKey);
|
|
32
|
+
return rows.map(rowToSession);
|
|
33
|
+
}
|
|
34
|
+
function orderByClause(sortOrder) {
|
|
35
|
+
switch (sortOrder) {
|
|
36
|
+
case 'oldest':
|
|
37
|
+
return 's.started_at ASC';
|
|
38
|
+
case 'most_messages':
|
|
39
|
+
return 's.message_count DESC, s.started_at DESC';
|
|
40
|
+
case 'title':
|
|
41
|
+
return 'COALESCE(NULLIF(s.title, \'\'), \'\') ASC, s.started_at DESC';
|
|
42
|
+
case 'recent':
|
|
43
|
+
default:
|
|
44
|
+
return 's.started_at DESC';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/projects/sessions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAW/D,MAAM,UAAU,sBAAsB,CACpC,EAAqB,EACrB,WAAmB,EACnB,UAAyC,EAAE;IAE3C,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,QAAQ,EAAE,KAAK,GAAG,GAAG,EAAE,aAAa,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;IAErF,MAAM,UAAU,GAAa,CAAC,oBAAoB,EAAE,qBAAqB,CAAC,CAAA;IAC1E,MAAM,MAAM,GAAc,CAAC,WAAW,CAAC,CAAA;IAEvC,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACrD,UAAU,CAAC,IAAI,CAAC,gBAAgB,YAAY,GAAG,CAAC,CAAA;QAChD,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAA;IACzB,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,UAAU,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAA;IAC7F,CAAC;IAED,MAAM,OAAO,GAAG,aAAa,CAAC,SAAS,CAAC,CAAA;IACxC,MAAM,GAAG,GAAG;MACR,cAAc;YACR,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;eACrB,OAAO;;GAEnB,CAAA;IACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAElB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAmC,CAAA;IAC7E,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;AAC/B,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,EAAqB,EACrB,WAAmB;IAEnB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;MACpB,cAAc;;;;GAIjB,CAAC,CAAC,GAAG,CAAC,WAAW,CAAmC,CAAA;IACrD,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;AAC/B,CAAC;AAED,SAAS,aAAa,CAAC,SAAkC;IACvD,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,QAAQ;YACX,OAAO,kBAAkB,CAAA;QAC3B,KAAK,eAAe;YAClB,OAAO,yCAAyC,CAAA;QAClD,KAAK,OAAO;YACV,OAAO,8DAA8D,CAAA;QACvE,KAAK,QAAQ,CAAC;QACd;YACE,OAAO,mBAAmB,CAAA;IAC9B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recovers the upstream main-repo path of a worktree session whose `cwd`
|
|
3
|
+
* has already been deleted at sync time. This is the only signal that lets
|
|
4
|
+
* Spool group such sessions under their real project — Claude Code's JSONL
|
|
5
|
+
* carries `cwd` and `gitBranch` but no remote URL.
|
|
6
|
+
*
|
|
7
|
+
* Each implementation reads a worktree-tool-specific persistent store. If
|
|
8
|
+
* the store is missing or the cwd doesn't match anything, return null and
|
|
9
|
+
* the next resolver in the chain (or the existing path-kind fallback) wins.
|
|
10
|
+
*/
|
|
11
|
+
export interface WorktreeUpstreamResolver {
|
|
12
|
+
name: string;
|
|
13
|
+
resolve(cwd: string): string | null;
|
|
14
|
+
}
|
|
15
|
+
/** Test hook: reset the in-process cache so tests can stub the DB. */
|
|
16
|
+
export declare function _resetSupersetCacheForTests(): void;
|
|
17
|
+
export declare const supersetResolver: WorktreeUpstreamResolver;
|
|
18
|
+
export declare const DEFAULT_RESOLVERS: readonly WorktreeUpstreamResolver[];
|
|
19
|
+
//# sourceMappingURL=worktree-resolvers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-resolvers.d.ts","sourceRoot":"","sources":["../../src/projects/worktree-resolvers.ts"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CACpC;AAwCD,sEAAsE;AACtE,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED,eAAO,MAAM,gBAAgB,EAAE,wBAgB9B,CAAA;AAED,eAAO,MAAM,iBAAiB,EAAE,SAAS,wBAAwB,EAE/D,CAAA"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import Database from 'better-sqlite3';
|
|
5
|
+
// Resolve home at call time (not module load) so tests can redirect via
|
|
6
|
+
// process.env.HOME. node:os.homedir() reads the OS user info on POSIX and
|
|
7
|
+
// ignores HOME, hence the explicit check first.
|
|
8
|
+
function getHome() {
|
|
9
|
+
return process.env['HOME'] || homedir();
|
|
10
|
+
}
|
|
11
|
+
function supersetDbPath() { return join(getHome(), '.superset', 'local.db'); }
|
|
12
|
+
function supersetDefaultBase() { return join(getHome(), '.superset', 'worktrees'); }
|
|
13
|
+
let _supersetCache = null;
|
|
14
|
+
function loadSupersetProjects() {
|
|
15
|
+
if (_supersetCache)
|
|
16
|
+
return _supersetCache;
|
|
17
|
+
const dbPath = supersetDbPath();
|
|
18
|
+
if (!existsSync(dbPath))
|
|
19
|
+
return null;
|
|
20
|
+
let db = null;
|
|
21
|
+
try {
|
|
22
|
+
db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
|
23
|
+
const settings = db.prepare(`SELECT worktree_base_dir FROM settings WHERE id = 1`).get();
|
|
24
|
+
const globalBase = settings?.worktree_base_dir || supersetDefaultBase();
|
|
25
|
+
const projects = db.prepare(`SELECT name, main_repo_path, worktree_base_dir FROM projects`).all();
|
|
26
|
+
_supersetCache = { projects, globalBase };
|
|
27
|
+
return _supersetCache;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
try {
|
|
34
|
+
db?.close();
|
|
35
|
+
}
|
|
36
|
+
catch { /* ignore */ }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Test hook: reset the in-process cache so tests can stub the DB. */
|
|
40
|
+
export function _resetSupersetCacheForTests() {
|
|
41
|
+
_supersetCache = null;
|
|
42
|
+
}
|
|
43
|
+
export const supersetResolver = {
|
|
44
|
+
name: 'superset',
|
|
45
|
+
resolve(cwd) {
|
|
46
|
+
const data = loadSupersetProjects();
|
|
47
|
+
if (!data)
|
|
48
|
+
return null;
|
|
49
|
+
for (const p of data.projects) {
|
|
50
|
+
if (!p.main_repo_path)
|
|
51
|
+
continue;
|
|
52
|
+
const base = p.worktree_base_dir || data.globalBase;
|
|
53
|
+
// Convention enforced by superset: <base>/<project-name>/<branch>
|
|
54
|
+
const projectDir = join(base, p.name);
|
|
55
|
+
if (cwd === projectDir || cwd.startsWith(projectDir + '/')) {
|
|
56
|
+
return p.main_repo_path;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
export const DEFAULT_RESOLVERS = Object.freeze([
|
|
63
|
+
supersetResolver,
|
|
64
|
+
]);
|
|
65
|
+
//# sourceMappingURL=worktree-resolvers.js.map
|