@volter/supercode-interchange 0.0.0-stage → 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,62 @@
1
+ import { readdir, stat } from 'node:fs/promises';
2
+ import { basename, dirname, extname, join } from 'node:path';
3
+
4
+ const absent = (error) => error.code === 'ENOENT' || error.code === 'ENOTDIR';
5
+ const order = (a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b));
6
+
7
+ export async function sourceStat(path) {
8
+ try { return await stat(path, { bigint: true }); }
9
+ catch (error) { if (absent(error)) return null; throw error; }
10
+ }
11
+
12
+ export async function sourceEntries(path) {
13
+ try { return await readdir(path); }
14
+ catch (error) { if (absent(error)) return []; throw error; }
15
+ }
16
+
17
+ async function namesFile(path) {
18
+ const info = await sourceStat(path);
19
+ return info ? info.isFile() : extname(path) !== '';
20
+ }
21
+
22
+ /** Follow a profile symlink, but never turn a refused registry or target into
23
+ * an empty selection. Dot folders have the same exclusion as native readers. */
24
+ export async function profileDirectories(root) {
25
+ if (!(await sourceStat(root))?.isDirectory()) return [];
26
+ const named = [];
27
+ for (const name of await sourceEntries(join(root, 'profiles'))) {
28
+ const path = join(root, 'profiles', name);
29
+ const info = await sourceStat(path);
30
+ if (info?.isDirectory() && !name.startsWith('.')) named.push({ profile: name, path });
31
+ }
32
+ named.sort((a, b) => order(a.profile, b.profile));
33
+ return [{ profile: 'default', path: root }, ...named];
34
+ }
35
+
36
+ export async function selectStoreFiles(harness, homes) {
37
+ const plain = (path) => ({ path, profile: null });
38
+ if (harness === 'opencode') {
39
+ if (await namesFile(homes.opencode)) return [plain(homes.opencode)];
40
+ return (await sourceEntries(homes.opencode)).filter((name) => name.startsWith('opencode') && name.endsWith('.db'))
41
+ .sort(order).map((name) => plain(join(homes.opencode, name)));
42
+ }
43
+ if (harness === 'goose') {
44
+ if (await namesFile(homes.goose)) return [plain(homes.goose)];
45
+ const direct = join(homes.goose, 'sessions.db');
46
+ return [plain((await sourceStat(direct))?.isFile() ? direct : join(homes.goose, 'sessions', 'sessions.db'))];
47
+ }
48
+ if (harness === 'hermes') {
49
+ const root = dirname(homes.hermes), name = basename(homes.hermes);
50
+ return [plain(homes.hermes), ...(await profileDirectories(root)).slice(1).map(({ path }) => plain(join(path, name)))];
51
+ }
52
+ if (harness === 'orchestrator') return (await profileDirectories(homes.orchestrator)).map(({ profile, path }) => ({ profile, path: join(path, 'state.db') }));
53
+ return [];
54
+ }
55
+
56
+ export async function storeRegistryDirectories(harness, homes) {
57
+ if (harness === 'opencode') return [await namesFile(homes.opencode) ? dirname(homes.opencode) : homes.opencode];
58
+ if (harness === 'goose') return await namesFile(homes.goose) ? [dirname(homes.goose)] : [homes.goose, join(homes.goose, 'sessions')];
59
+ if (harness === 'hermes') return [join(dirname(homes.hermes), 'profiles'), dirname(homes.hermes)];
60
+ if (harness === 'orchestrator') return [homes.orchestrator, join(homes.orchestrator, 'profiles')];
61
+ return [];
62
+ }
package/text.mjs ADDED
@@ -0,0 +1,17 @@
1
+ // Rust str::trim uses Unicode White_Space, which differs from JS trim for
2
+ // U+0085 and U+FEFF. Keep source titles/content and query boundaries consistent.
3
+ const leading = /^[\u0009-\u000d\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+/u;
4
+ const trailing = /[\u0009-\u000d\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+$/u;
5
+ export const nativeTrim = (text) => text.replace(leading, '').replace(trailing, '');
6
+
7
+ export function displayText(content) {
8
+ if (typeof content === 'string') return content;
9
+ if (!Array.isArray(content)) return null;
10
+ return nativeTrim(content.filter((part) => typeof part?.text === 'string').map((part) => part.text).join(' '));
11
+ }
12
+
13
+ export function truncateScalars(text, count) {
14
+ let end = 0, used = 0;
15
+ for (const scalar of text) { if (used++ >= count) break; end += scalar.length; }
16
+ return text.slice(0, end);
17
+ }
package/workspace.mjs ADDED
@@ -0,0 +1,104 @@
1
+ import { statSync, readdirSync, readFileSync, realpathSync } from 'node:fs';
2
+ import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
3
+
4
+ const canonical = (path) => { try { return realpathSync.native(path); } catch { return null; } };
5
+ const stat = (path) => { try { return statSync(path); } catch { return null; } };
6
+
7
+ function comparisonKey(path) {
8
+ if (process.platform !== 'win32') return path;
9
+ return path.replace(/^\\\\\?\\UNC\\/, '\\\\').replace(/^\\\\\?\\/, '').toLowerCase();
10
+ }
11
+
12
+ function keys(path) {
13
+ const real = canonical(path);
14
+ return [...new Set([...(real ? [comparisonKey(real)] : []), comparisonKey(resolve(path))])];
15
+ }
16
+
17
+ function contains(root, path) {
18
+ const part = relative(root, path);
19
+ return part === '' || (!isAbsolute(part) && part !== '..' && !part.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`));
20
+ }
21
+
22
+ /** Exact and subtree workspace semantics from the native catalog. Only
23
+ * directly linked directories widen a subtree, and never to its ancestor. */
24
+ export function workspaceScope(query) {
25
+ if (query.workspace == null) return null;
26
+ const wanted = query.workspace;
27
+ const subtree = query.workspace_subtree === true;
28
+ const roots = keys(wanted);
29
+ if (subtree) {
30
+ const own = [...roots];
31
+ let entries = [];
32
+ try { entries = readdirSync(wanted, { withFileTypes: true }); } catch { /* catalog's soft linked-folder fallback */ }
33
+ for (const entry of entries) {
34
+ const path = join(wanted, entry.name);
35
+ if (!entry.isSymbolicLink() || !stat(path)?.isDirectory()) continue;
36
+ for (const key of keys(path)) {
37
+ if (!own.some((root) => contains(key, root)) && !roots.some((root) => contains(root, key))) roots.push(key);
38
+ }
39
+ }
40
+ }
41
+ const judged = new Map();
42
+ return (descriptor) => {
43
+ const recorded = descriptor.cwd;
44
+ const harness = descriptor.locator.harness;
45
+ // These two native stores historically compare an exact cwd literally.
46
+ if (!subtree && (harness === 'hermes' || harness === 'openclaw')) return recorded === wanted;
47
+ if (typeof recorded !== 'string' || !isAbsolute(recorded)) return false;
48
+ if (judged.has(recorded)) return judged.get(recorded);
49
+ let admitted;
50
+ if (subtree) admitted = keys(recorded).some((key) => roots.some((root) => contains(root, key)));
51
+ else {
52
+ const left = canonical(recorded), right = canonical(wanted);
53
+ admitted = left != null && right != null ? left === right : resolve(recorded) === resolve(wanted);
54
+ }
55
+ judged.set(recorded, admitted);
56
+ return admitted;
57
+ };
58
+ }
59
+
60
+ function originUrl(common) {
61
+ let text;
62
+ try { text = readFileSync(join(common, 'config'), 'utf8'); } catch { return null; }
63
+ let inOrigin = false;
64
+ for (const raw of text.split(/\r?\n/)) {
65
+ const line = raw.trim();
66
+ if (line.startsWith('[')) { inOrigin = line.startsWith('[remote "origin"]'); continue; }
67
+ if (inOrigin) {
68
+ const match = /^url\s*=\s*(.+)$/.exec(line);
69
+ if (match?.[1].trim()) return match[1].trim();
70
+ }
71
+ }
72
+ return null;
73
+ }
74
+
75
+ /** Read the common-directory/remote family from Git files, without a child
76
+ * process. A non-repository path only joins that exact path. */
77
+ export function repositoryFamily(path) {
78
+ const start = canonical(path) ?? path;
79
+ for (let dir = start;; dir = dirname(dir)) {
80
+ const dotGit = join(dir, '.git');
81
+ const kind = stat(dotGit);
82
+ let common = null;
83
+ if (kind?.isDirectory()) common = canonical(dotGit) ?? dotGit;
84
+ else if (kind?.isFile()) {
85
+ let text = '';
86
+ try { text = readFileSync(dotGit, 'utf8'); } catch { /* native catalog keeps walking */ }
87
+ const pointer = text.split(/\r?\n/).map((line) => line.trim()).find((line) => line.startsWith('gitdir:'));
88
+ if (pointer) {
89
+ const target = pointer.slice(7).trim();
90
+ const gitdir = isAbsolute(target) ? target : join(dir, target);
91
+ const parent = dirname(gitdir);
92
+ common = basename(parent) === 'worktrees' ? dirname(parent) : gitdir;
93
+ common = canonical(common) ?? common;
94
+ }
95
+ }
96
+ if (common) return { identity: common, repository: true, origin: originUrl(common) };
97
+ if (dirname(dir) === dir) break;
98
+ }
99
+ return { identity: start, repository: false, origin: null };
100
+ }
101
+
102
+ export function sameRepositoryFamily(left, right) {
103
+ return left.identity === right.identity || (left.repository && right.repository && left.origin != null && left.origin === right.origin);
104
+ }