@nessielabs/daemon 0.4.0 → 0.5.26
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/README.md +8 -17
- package/dist/cli.js +42 -21
- package/dist/commands/auth.js +116 -0
- package/dist/commands/integrations.js +84 -0
- package/dist/commands/login.js +145 -0
- package/dist/commands/run.js +21 -6
- package/dist/commands/service.js +18 -36
- package/dist/commands/sharing.js +399 -0
- package/dist/commands/status.js +67 -0
- package/dist/commands/teams.js +64 -0
- package/dist/nera/client.js +156 -0
- package/dist/nera/process.js +78 -0
- package/dist/nera/runtimeFile.js +25 -0
- package/dist/platform/binary.js +21 -0
- package/dist/platform/openBrowser.js +14 -0
- package/dist/platform/paths.js +13 -0
- package/dist/platform/table.js +85 -0
- package/package.json +9 -5
- package/vendor/nera/darwin-arm64/nera +0 -0
- package/vendor/nera/darwin-x64/nera +0 -0
- package/vendor/nera/linux-arm64/nera +0 -0
- package/vendor/nera/linux-x64/nera +0 -0
- package/vendor/nera/win32-arm64/nera.exe +0 -0
- package/vendor/nera/win32-x64/nera.exe +0 -0
- package/vendor/proto/nessie.edge.v1.proto +475 -0
- package/dist/api/http.js +0 -44
- package/dist/auth/deviceFlow.js +0 -36
- package/dist/auth/tokens.js +0 -30
- package/dist/commands/setup.js +0 -75
- package/dist/config/endpoints.js +0 -2
- package/dist/config/paths.js +0 -19
- package/dist/config/store.js +0 -27
- package/dist/git/repoResolver.js +0 -215
- package/dist/localStore/daemonGraphStore.js +0 -494
- package/dist/localStore/messageComparison.js +0 -37
- package/dist/localStore/pushMapping.js +0 -69
- package/dist/localStore/rowTypes.js +0 -1
- package/dist/localStore/schema.js +0 -70
- package/dist/localStore/uuid.js +0 -12
- package/dist/parser/claudeCode.js +0 -202
- package/dist/parser/codex.js +0 -91
- package/dist/parser/jsonl.js +0 -24
- package/dist/parser/types.js +0 -15
- package/dist/redact/secrets.js +0 -60
- package/dist/service/process.js +0 -134
- package/dist/service/systemd.js +0 -38
- package/dist/sources/detect.js +0 -43
- package/dist/sync/batch.js +0 -50
- package/dist/sync/client.js +0 -90
- package/dist/sync/exclusions.js +0 -10
- package/dist/sync/hash.js +0 -4
- package/dist/sync/loop.js +0 -106
- package/dist/sync/scan.js +0 -245
- package/dist/sync/slices.js +0 -63
- package/dist/sync/types.js +0 -1
package/dist/config/store.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
import { hostname } from "node:os";
|
|
4
|
-
import { dirname } from "node:path";
|
|
5
|
-
import { getDaemonPaths } from "./paths.js";
|
|
6
|
-
export function createConfig(input) {
|
|
7
|
-
const deviceId = input.deviceId ?? randomUUID();
|
|
8
|
-
return {
|
|
9
|
-
deviceId,
|
|
10
|
-
deviceName: input.deviceName ?? hostname(),
|
|
11
|
-
accessToken: input.accessToken,
|
|
12
|
-
refreshToken: input.refreshToken ?? null,
|
|
13
|
-
apiKey: input.apiKey ?? null,
|
|
14
|
-
selectedSources: input.selectedSources.map((source) => ({
|
|
15
|
-
...source,
|
|
16
|
-
localId: randomUUID(),
|
|
17
|
-
stableKey: `device:${deviceId}`,
|
|
18
|
-
})),
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
export async function readConfig(paths = getDaemonPaths()) {
|
|
22
|
-
return JSON.parse(await readFile(paths.configFile, "utf8"));
|
|
23
|
-
}
|
|
24
|
-
export async function writeConfig(config, paths = getDaemonPaths()) {
|
|
25
|
-
await mkdir(dirname(paths.configFile), { recursive: true });
|
|
26
|
-
await writeFile(paths.configFile, `${JSON.stringify(config, null, 2)}\n`, { mode: 0o600 });
|
|
27
|
-
}
|
package/dist/git/repoResolver.js
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import { readFileSync, statSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
-
/** Directory levels to walk up looking for `.git` before giving up. */
|
|
5
|
-
const MAX_PARENT_TRAVERSAL = 64;
|
|
6
|
-
/**
|
|
7
|
-
* Resolves the git repository identity for a working directory by reading
|
|
8
|
-
* `.git` metadata from disk, without invoking the `git` binary.
|
|
9
|
-
*
|
|
10
|
-
* Resolution is best-effort by design: paths that are not inside a git
|
|
11
|
-
* repository, repositories without remotes, and repositories deleted since
|
|
12
|
-
* the session simply resolve to null.
|
|
13
|
-
*/
|
|
14
|
-
export class GitRepoResolver {
|
|
15
|
-
/**
|
|
16
|
-
* Memoized results per workspace path: conversations in the same directory
|
|
17
|
-
* repeat heavily within one sync run.
|
|
18
|
-
*/
|
|
19
|
-
cache = new Map();
|
|
20
|
-
resolve(workspacePath) {
|
|
21
|
-
const standardized = resolve(expandTilde(workspacePath));
|
|
22
|
-
const cached = this.cache.get(standardized);
|
|
23
|
-
if (cached !== undefined)
|
|
24
|
-
return cached;
|
|
25
|
-
const resolved = resolveUncached(standardized);
|
|
26
|
-
this.cache.set(standardized, resolved);
|
|
27
|
-
return resolved;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function expandTilde(path) {
|
|
31
|
-
if (path === "~")
|
|
32
|
-
return homedir();
|
|
33
|
-
if (path.startsWith("~/"))
|
|
34
|
-
return join(homedir(), path.slice(2));
|
|
35
|
-
return path;
|
|
36
|
-
}
|
|
37
|
-
function resolveUncached(workspacePath) {
|
|
38
|
-
let directory = workspacePath;
|
|
39
|
-
for (let level = 0; level < MAX_PARENT_TRAVERSAL; level += 1) {
|
|
40
|
-
const configPath = gitConfigPath(join(directory, ".git"));
|
|
41
|
-
if (configPath) {
|
|
42
|
-
const config = readTextFile(configPath);
|
|
43
|
-
const remoteUrl = config !== null ? remoteUrlFromGitConfig(config) : null;
|
|
44
|
-
if (remoteUrl) {
|
|
45
|
-
return { remoteUrl, repoKey: normalizedRepoKey(remoteUrl) };
|
|
46
|
-
}
|
|
47
|
-
// A repo without a remote keeps the walk going so a nested remoteless
|
|
48
|
-
// checkout attributes to its enclosing repo. Matches NessieCore's
|
|
49
|
-
// GitRepoResolver.resolveUncached, the source of truth for repo
|
|
50
|
-
// identity; both implementations must group conversations identically.
|
|
51
|
-
}
|
|
52
|
-
const parent = dirname(directory);
|
|
53
|
-
if (parent === directory)
|
|
54
|
-
return null;
|
|
55
|
-
directory = parent;
|
|
56
|
-
}
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Locate the `config` file for a `.git` entry, which is a directory for
|
|
61
|
-
* normal checkouts and a `gitdir:` pointer file for worktrees and submodules.
|
|
62
|
-
*/
|
|
63
|
-
function gitConfigPath(gitEntry) {
|
|
64
|
-
const stats = statSync(gitEntry, { throwIfNoEntry: false });
|
|
65
|
-
if (!stats)
|
|
66
|
-
return null;
|
|
67
|
-
if (stats.isDirectory()) {
|
|
68
|
-
return existingFile(join(gitEntry, "config"));
|
|
69
|
-
}
|
|
70
|
-
const pointer = readTextFile(gitEntry);
|
|
71
|
-
const gitDir = pointer !== null ? gitDirPath(pointer) : null;
|
|
72
|
-
if (!gitDir)
|
|
73
|
-
return null;
|
|
74
|
-
const resolvedGitDir = absolutePath(gitDir, dirname(gitEntry));
|
|
75
|
-
// Worktree gitdirs keep shared state (including `config`) in the main
|
|
76
|
-
// repository's git directory, referenced by a `commondir` file.
|
|
77
|
-
const commonDir = readTextFile(join(resolvedGitDir, "commondir"))?.trim();
|
|
78
|
-
if (commonDir) {
|
|
79
|
-
return existingFile(join(absolutePath(commonDir, resolvedGitDir), "config"));
|
|
80
|
-
}
|
|
81
|
-
return existingFile(join(resolvedGitDir, "config"));
|
|
82
|
-
}
|
|
83
|
-
function existingFile(path) {
|
|
84
|
-
return statSync(path, { throwIfNoEntry: false })?.isFile() ? path : null;
|
|
85
|
-
}
|
|
86
|
-
function readTextFile(path) {
|
|
87
|
-
try {
|
|
88
|
-
return readFileSync(path, "utf8");
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
export function gitDirPath(pointerContents) {
|
|
95
|
-
for (const line of pointerContents.split(/\r?\n/)) {
|
|
96
|
-
const trimmed = line.trim();
|
|
97
|
-
if (!trimmed.startsWith("gitdir:"))
|
|
98
|
-
continue;
|
|
99
|
-
const path = trimmed.slice("gitdir:".length).trim();
|
|
100
|
-
return path.length > 0 ? path : null;
|
|
101
|
-
}
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
function absolutePath(path, base) {
|
|
105
|
-
return isAbsolute(path) ? resolve(path) : resolve(base, path);
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Extract a remote URL from raw `.git/config` contents, preferring `origin`
|
|
109
|
-
* and falling back to the first remote with a URL.
|
|
110
|
-
*/
|
|
111
|
-
export function remoteUrlFromGitConfig(contents) {
|
|
112
|
-
let currentRemote = null;
|
|
113
|
-
let originUrl = null;
|
|
114
|
-
let firstUrl = null;
|
|
115
|
-
for (const line of contents.split(/\r?\n/)) {
|
|
116
|
-
const trimmed = line.trim();
|
|
117
|
-
if (trimmed.startsWith("[")) {
|
|
118
|
-
currentRemote = remoteNameFromSectionHeader(trimmed);
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
if (!currentRemote)
|
|
122
|
-
continue;
|
|
123
|
-
const url = configValue(trimmed, "url");
|
|
124
|
-
if (!url)
|
|
125
|
-
continue;
|
|
126
|
-
if (currentRemote === "origin" && originUrl === null) {
|
|
127
|
-
originUrl = url;
|
|
128
|
-
}
|
|
129
|
-
if (firstUrl === null) {
|
|
130
|
-
firstUrl = url;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return originUrl ?? firstUrl;
|
|
134
|
-
}
|
|
135
|
-
function remoteNameFromSectionHeader(header) {
|
|
136
|
-
// [remote "origin"]
|
|
137
|
-
if (!header.startsWith("[remote "))
|
|
138
|
-
return null;
|
|
139
|
-
const openQuote = header.indexOf('"');
|
|
140
|
-
const closeQuote = header.lastIndexOf('"');
|
|
141
|
-
if (openQuote === -1 || closeQuote <= openQuote)
|
|
142
|
-
return null;
|
|
143
|
-
return header.slice(openQuote + 1, closeQuote);
|
|
144
|
-
}
|
|
145
|
-
function configValue(line, key) {
|
|
146
|
-
const equals = line.indexOf("=");
|
|
147
|
-
if (equals === -1)
|
|
148
|
-
return null;
|
|
149
|
-
if (line.slice(0, equals).trim() !== key)
|
|
150
|
-
return null;
|
|
151
|
-
const value = line.slice(equals + 1).trim();
|
|
152
|
-
return value.length > 0 ? value : null;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Normalize a configured remote URL to a stable `host/path` identity so the
|
|
156
|
-
* same repository matches across protocols, credentials, machines, and
|
|
157
|
-
* clones: `git@github.com:Org/Repo.git` and `https://github.com/org/repo`
|
|
158
|
-
* both become `github.com/org/repo`.
|
|
159
|
-
*/
|
|
160
|
-
export function normalizedRepoKey(remoteUrl) {
|
|
161
|
-
let rest = remoteUrl.trim();
|
|
162
|
-
if (rest.length === 0)
|
|
163
|
-
return null;
|
|
164
|
-
const schemeEnd = rest.indexOf("://");
|
|
165
|
-
if (schemeEnd !== -1) {
|
|
166
|
-
const scheme = rest.slice(0, schemeEnd).toLowerCase();
|
|
167
|
-
// Local remotes have no cross-machine identity.
|
|
168
|
-
if (scheme === "file")
|
|
169
|
-
return null;
|
|
170
|
-
rest = rest.slice(schemeEnd + "://".length);
|
|
171
|
-
}
|
|
172
|
-
else if (rest.includes(":") && (rest.includes("@") || !rest.startsWith("/"))) {
|
|
173
|
-
// scp-like syntax: [user@]host:path
|
|
174
|
-
const colon = rest.indexOf(":");
|
|
175
|
-
const hostPart = rest.slice(0, colon);
|
|
176
|
-
const path = rest.slice(colon + 1);
|
|
177
|
-
if (hostPart.length === 0 || path.length === 0 || hostPart.includes("/"))
|
|
178
|
-
return null;
|
|
179
|
-
rest = `${hostPart}/${path}`;
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
// Bare filesystem path remote.
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
// Strip userinfo.
|
|
186
|
-
const lastAt = rest.lastIndexOf("@");
|
|
187
|
-
const firstSlash = rest.indexOf("/");
|
|
188
|
-
if (lastAt !== -1 && firstSlash !== -1 && lastAt < firstSlash) {
|
|
189
|
-
rest = rest.slice(lastAt + 1);
|
|
190
|
-
}
|
|
191
|
-
else if (rest.includes("@") && !rest.includes("/")) {
|
|
192
|
-
rest = rest.slice(rest.indexOf("@") + 1);
|
|
193
|
-
}
|
|
194
|
-
const components = rest.split("/").filter((component) => component.length > 0);
|
|
195
|
-
if (components.length < 2)
|
|
196
|
-
return null;
|
|
197
|
-
// Lowercase the host and drop any port; path case is preserved except for
|
|
198
|
-
// trailing `.git`.
|
|
199
|
-
let host = components[0].toLowerCase();
|
|
200
|
-
const portColon = host.indexOf(":");
|
|
201
|
-
if (portColon !== -1) {
|
|
202
|
-
host = host.slice(0, portColon);
|
|
203
|
-
}
|
|
204
|
-
if (!host.includes(".") && host !== "localhost")
|
|
205
|
-
return null;
|
|
206
|
-
components[0] = host;
|
|
207
|
-
let last = components[components.length - 1];
|
|
208
|
-
if (last.toLowerCase().endsWith(".git")) {
|
|
209
|
-
last = last.slice(0, -4);
|
|
210
|
-
}
|
|
211
|
-
if (last.length === 0)
|
|
212
|
-
return null;
|
|
213
|
-
components[components.length - 1] = last;
|
|
214
|
-
return components.join("/");
|
|
215
|
-
}
|