elepha 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.
- package/LICENSE.md +375 -0
- package/README.md +135 -0
- package/bin/elepha.js +2 -0
- package/dist/adapters/base.js +600 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/claude-code.js +260 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.js +499 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/discriminators.js +39 -0
- package/dist/adapters/discriminators.js.map +1 -0
- package/dist/adapters/index.js +6 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/internal-command.js +3 -0
- package/dist/adapters/internal-command.js.map +1 -0
- package/dist/cli/backup-wizard.js +97 -0
- package/dist/cli/backup-wizard.js.map +1 -0
- package/dist/cli/capture-service.js +80 -0
- package/dist/cli/capture-service.js.map +1 -0
- package/dist/cli/commands/backfills.js +336 -0
- package/dist/cli/commands/backfills.js.map +1 -0
- package/dist/cli/commands/backup.js +234 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/config.js +66 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/consent.js +237 -0
- package/dist/cli/commands/consent.js.map +1 -0
- package/dist/cli/commands/daemon-control.js +76 -0
- package/dist/cli/commands/daemon-control.js.map +1 -0
- package/dist/cli/commands/doctor.js +31 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/hook.js +24 -0
- package/dist/cli/commands/hook.js.map +1 -0
- package/dist/cli/commands/import.js +611 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/init.js +19 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/inspect.js +54 -0
- package/dist/cli/commands/inspect.js.map +1 -0
- package/dist/cli/commands/install.js +49 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/internal.js +16 -0
- package/dist/cli/commands/internal.js.map +1 -0
- package/dist/cli/commands/mcp.js +12 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/projects.js +26 -0
- package/dist/cli/commands/projects.js.map +1 -0
- package/dist/cli/commands/purge.js +216 -0
- package/dist/cli/commands/purge.js.map +1 -0
- package/dist/cli/commands/reingest.js +80 -0
- package/dist/cli/commands/reingest.js.map +1 -0
- package/dist/cli/commands/rekey.js +58 -0
- package/dist/cli/commands/rekey.js.map +1 -0
- package/dist/cli/commands/restore.js +376 -0
- package/dist/cli/commands/restore.js.map +1 -0
- package/dist/cli/commands/rollup.js +130 -0
- package/dist/cli/commands/rollup.js.map +1 -0
- package/dist/cli/commands/sanitize.js +72 -0
- package/dist/cli/commands/sanitize.js.map +1 -0
- package/dist/cli/commands/segment.js +153 -0
- package/dist/cli/commands/segment.js.map +1 -0
- package/dist/cli/commands/self-update.js +26 -0
- package/dist/cli/commands/self-update.js.map +1 -0
- package/dist/cli/commands/start.js +53 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/stats.js +42 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/status.js +73 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/uninstall.js +23 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/config-wizard.js +104 -0
- package/dist/cli/config-wizard.js.map +1 -0
- package/dist/cli/destructive-op.js +32 -0
- package/dist/cli/destructive-op.js.map +1 -0
- package/dist/cli/import-wizard.js +89 -0
- package/dist/cli/import-wizard.js.map +1 -0
- package/dist/cli/index.js +74 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init-wizard.js +80 -0
- package/dist/cli/init-wizard.js.map +1 -0
- package/dist/cli/init.js +159 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/launcher-probe.js +71 -0
- package/dist/cli/launcher-probe.js.map +1 -0
- package/dist/cli/project-path.js +16 -0
- package/dist/cli/project-path.js.map +1 -0
- package/dist/cli/purge-wizard.js +200 -0
- package/dist/cli/purge-wizard.js.map +1 -0
- package/dist/cli/restore-wizard.js +101 -0
- package/dist/cli/restore-wizard.js.map +1 -0
- package/dist/cli/shared.js +128 -0
- package/dist/cli/shared.js.map +1 -0
- package/dist/cli/status.js +22 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/wordmark.js +15 -0
- package/dist/cli/wordmark.js.map +1 -0
- package/dist/config/constants.js +115 -0
- package/dist/config/constants.js.map +1 -0
- package/dist/config/env.js +168 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/memory-config.js +63 -0
- package/dist/config/memory-config.js.map +1 -0
- package/dist/config/paths.js +343 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/settings.js +132 -0
- package/dist/config/settings.js.map +1 -0
- package/dist/config/version.js +12 -0
- package/dist/config/version.js.map +1 -0
- package/dist/daemon/failure-window.js +38 -0
- package/dist/daemon/failure-window.js.map +1 -0
- package/dist/daemon/heartbeat.js +40 -0
- package/dist/daemon/heartbeat.js.map +1 -0
- package/dist/daemon/index.js +873 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/log-rotation.js +27 -0
- package/dist/daemon/log-rotation.js.map +1 -0
- package/dist/daemon/readability-guard.js +89 -0
- package/dist/daemon/readability-guard.js.map +1 -0
- package/dist/daemon/rollup-service.js +239 -0
- package/dist/daemon/rollup-service.js.map +1 -0
- package/dist/daemon/update-check.js +87 -0
- package/dist/daemon/update-check.js.map +1 -0
- package/dist/daemon/work-queue.js +28 -0
- package/dist/daemon/work-queue.js.map +1 -0
- package/dist/discovery/session-projects.js +242 -0
- package/dist/discovery/session-projects.js.map +1 -0
- package/dist/hooks/codex-trust.js +80 -0
- package/dist/hooks/codex-trust.js.map +1 -0
- package/dist/hooks/common.js +81 -0
- package/dist/hooks/common.js.map +1 -0
- package/dist/hooks/hook-log.js +38 -0
- package/dist/hooks/hook-log.js.map +1 -0
- package/dist/hooks/installer.js +200 -0
- package/dist/hooks/installer.js.map +1 -0
- package/dist/hooks/session-start.js +321 -0
- package/dist/hooks/session-start.js.map +1 -0
- package/dist/hooks/user-prompt-submit.js +248 -0
- package/dist/hooks/user-prompt-submit.js.map +1 -0
- package/dist/install/binary.js +72 -0
- package/dist/install/binary.js.map +1 -0
- package/dist/install/config-file.js +119 -0
- package/dist/install/config-file.js.map +1 -0
- package/dist/install/daemon-health.js +48 -0
- package/dist/install/daemon-health.js.map +1 -0
- package/dist/install/daemon-service.js +309 -0
- package/dist/install/daemon-service.js.map +1 -0
- package/dist/install/doctor.js +180 -0
- package/dist/install/doctor.js.map +1 -0
- package/dist/install/health-checks.js +90 -0
- package/dist/install/health-checks.js.map +1 -0
- package/dist/install/installer.js +411 -0
- package/dist/install/installer.js.map +1 -0
- package/dist/install/launchd-backend.js +261 -0
- package/dist/install/launchd-backend.js.map +1 -0
- package/dist/install/launcher.js +224 -0
- package/dist/install/launcher.js.map +1 -0
- package/dist/install/markers.js +14 -0
- package/dist/install/markers.js.map +1 -0
- package/dist/install/platform.js +29 -0
- package/dist/install/platform.js.map +1 -0
- package/dist/install/present-tools.js +16 -0
- package/dist/install/present-tools.js.map +1 -0
- package/dist/install/self-update.js +120 -0
- package/dist/install/self-update.js.map +1 -0
- package/dist/install/service-backend.js +36 -0
- package/dist/install/service-backend.js.map +1 -0
- package/dist/install/service-manifest.js +36 -0
- package/dist/install/service-manifest.js.map +1 -0
- package/dist/install/status.js +58 -0
- package/dist/install/status.js.map +1 -0
- package/dist/install/systemd-backend.js +225 -0
- package/dist/install/systemd-backend.js.map +1 -0
- package/dist/markers.js +5 -0
- package/dist/markers.js.map +1 -0
- package/dist/mcp/installer.js +131 -0
- package/dist/mcp/installer.js.map +1 -0
- package/dist/mcp/server.js +81 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/get-context.js +3 -0
- package/dist/mcp/tools/get-context.js.map +1 -0
- package/dist/mcp/tools/list-projects.js +3 -0
- package/dist/mcp/tools/list-projects.js.map +1 -0
- package/dist/mcp/tools/save-memory.js +3 -0
- package/dist/mcp/tools/save-memory.js.map +1 -0
- package/dist/mcp/tools.js +288 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/rendering/raw-turn-renderer.js +85 -0
- package/dist/rendering/raw-turn-renderer.js.map +1 -0
- package/dist/security/file-permissions.js +15 -0
- package/dist/security/file-permissions.js.map +1 -0
- package/dist/security/provider-transcript.js +74 -0
- package/dist/security/provider-transcript.js.map +1 -0
- package/dist/security/sanitize.js +210 -0
- package/dist/security/sanitize.js.map +1 -0
- package/dist/security/self-ingestion.js +47 -0
- package/dist/security/self-ingestion.js.map +1 -0
- package/dist/security/sentinel.js +19 -0
- package/dist/security/sentinel.js.map +1 -0
- package/dist/security/subprocess-allowlist.js +421 -0
- package/dist/security/subprocess-allowlist.js.map +1 -0
- package/dist/serving/instructions.js +33 -0
- package/dist/serving/instructions.js.map +1 -0
- package/dist/serving/lexical-recall.js +249 -0
- package/dist/serving/lexical-recall.js.map +1 -0
- package/dist/serving/session-reader.js +302 -0
- package/dist/serving/session-reader.js.map +1 -0
- package/dist/storage/backfill-runner.js +34 -0
- package/dist/storage/backfill-runner.js.map +1 -0
- package/dist/storage/backup.js +46 -0
- package/dist/storage/backup.js.map +1 -0
- package/dist/storage/candidate-validator.js +77 -0
- package/dist/storage/candidate-validator.js.map +1 -0
- package/dist/storage/consent-store.js +198 -0
- package/dist/storage/consent-store.js.map +1 -0
- package/dist/storage/custom-title-backfill.js +68 -0
- package/dist/storage/custom-title-backfill.js.map +1 -0
- package/dist/storage/db.js +312 -0
- package/dist/storage/db.js.map +1 -0
- package/dist/storage/external-agent-import-purge.js +182 -0
- package/dist/storage/external-agent-import-purge.js.map +1 -0
- package/dist/storage/first-prompt-search-backfill.js +76 -0
- package/dist/storage/first-prompt-search-backfill.js.map +1 -0
- package/dist/storage/first-prompt-search.js +7 -0
- package/dist/storage/first-prompt-search.js.map +1 -0
- package/dist/storage/injection-store.js +37 -0
- package/dist/storage/injection-store.js.map +1 -0
- package/dist/storage/memory-store.js +428 -0
- package/dist/storage/memory-store.js.map +1 -0
- package/dist/storage/project-resolver.js +294 -0
- package/dist/storage/project-resolver.js.map +1 -0
- package/dist/storage/project-store.js +104 -0
- package/dist/storage/project-store.js.map +1 -0
- package/dist/storage/rendered-chars-backfill.js +85 -0
- package/dist/storage/rendered-chars-backfill.js.map +1 -0
- package/dist/storage/resegmentation.js +582 -0
- package/dist/storage/resegmentation.js.map +1 -0
- package/dist/storage/rollup-store.js +246 -0
- package/dist/storage/rollup-store.js.map +1 -0
- package/dist/storage/root-commit-backfill.js +32 -0
- package/dist/storage/root-commit-backfill.js.map +1 -0
- package/dist/storage/sanitize-backfill.js +184 -0
- package/dist/storage/sanitize-backfill.js.map +1 -0
- package/dist/storage/segmentation.js +87 -0
- package/dist/storage/segmentation.js.map +1 -0
- package/dist/storage/session-fields-backfill.js +196 -0
- package/dist/storage/session-fields-backfill.js.map +1 -0
- package/dist/storage/session-read-model.js +130 -0
- package/dist/storage/session-read-model.js.map +1 -0
- package/dist/storage/session-store.js +200 -0
- package/dist/storage/session-store.js.map +1 -0
- package/dist/storage/session-title-backfill.js +75 -0
- package/dist/storage/session-title-backfill.js.map +1 -0
- package/dist/storage/session-title.js +71 -0
- package/dist/storage/session-title.js.map +1 -0
- package/dist/storage/shown-session-list-store.js +33 -0
- package/dist/storage/shown-session-list-store.js.map +1 -0
- package/dist/storage/stats.js +30 -0
- package/dist/storage/stats.js.map +1 -0
- package/dist/storage/turn-store.js +202 -0
- package/dist/storage/turn-store.js.map +1 -0
- package/dist/storage/ulid.js +17 -0
- package/dist/storage/ulid.js.map +1 -0
- package/dist/summarizer/anthropic-call.js +76 -0
- package/dist/summarizer/anthropic-call.js.map +1 -0
- package/dist/summarizer/call-log.js +120 -0
- package/dist/summarizer/call-log.js.map +1 -0
- package/dist/summarizer/haiku-provider.js +136 -0
- package/dist/summarizer/haiku-provider.js.map +1 -0
- package/dist/summarizer/pricing.js +8 -0
- package/dist/summarizer/pricing.js.map +1 -0
- package/dist/summarizer/prompt-cache.js +6 -0
- package/dist/summarizer/prompt-cache.js.map +1 -0
- package/dist/summarizer/prompt.js +47 -0
- package/dist/summarizer/prompt.js.map +1 -0
- package/dist/summarizer/provider-config.js +25 -0
- package/dist/summarizer/provider-config.js.map +1 -0
- package/dist/summarizer/rollup-prompt.js +225 -0
- package/dist/summarizer/rollup-prompt.js.map +1 -0
- package/dist/summarizer/rollup-provider.js +224 -0
- package/dist/summarizer/rollup-provider.js.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/util/error.js +5 -0
- package/dist/util/error.js.map +1 -0
- package/dist/util/fs.js +97 -0
- package/dist/util/fs.js.map +1 -0
- package/dist/util/relative-time.js +12 -0
- package/dist/util/relative-time.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// Loads the API key (and a small set of other settings) from a .env file.
|
|
2
|
+
//
|
|
3
|
+
// Deliberately NOT a general dotenv implementation, for three reasons that are
|
|
4
|
+
// specific to what elepha is:
|
|
5
|
+
//
|
|
6
|
+
// 1. NEVER FROM THE CURRENT DIRECTORY. elepha runs as a background daemon
|
|
7
|
+
// while the user works in other repositories, and `elepha` is invoked from
|
|
8
|
+
// whatever directory the user happens to be standing in. A cwd-relative
|
|
9
|
+
// .env lookup would mean any project's secrets get read into this
|
|
10
|
+
// process - a memory tool that quietly slurps other repos' credentials is
|
|
11
|
+
// precisely the trust failure the consent model exists to prevent. Paths
|
|
12
|
+
// are resolved from $HOME and from this package's own location, never from
|
|
13
|
+
// process.cwd().
|
|
14
|
+
// 2. ALLOWLISTED KEYS ONLY. A .env can set anything, including PATH,
|
|
15
|
+
// NODE_OPTIONS or ANTHROPIC_BASE_URL. Applying an arbitrary file wholesale
|
|
16
|
+
// to process.env turns a config file into an execution-environment
|
|
17
|
+
// override. Only the variables below are read; everything else in the file
|
|
18
|
+
// is ignored.
|
|
19
|
+
// 3. NO INTERPOLATION. Popular dotenv variants expand `${VAR}` and some
|
|
20
|
+
// expand `$(cmd)`. elepha's whole security posture is that stored text is
|
|
21
|
+
// never executable syntax (Rule 3); it would be absurd to hand that
|
|
22
|
+
// property away in the config loader. Values are taken literally.
|
|
23
|
+
//
|
|
24
|
+
// Explicit environment always wins: a variable already set in process.env is
|
|
25
|
+
// never overwritten, so `ANTHROPIC_API_KEY=... elepha rollup` behaves as
|
|
26
|
+
// expected and CI never picks up a developer's file.
|
|
27
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
28
|
+
import path from 'node:path';
|
|
29
|
+
import { fileURLToPath } from 'node:url';
|
|
30
|
+
import { errorMessage } from '../util/error.js';
|
|
31
|
+
import { PRIVATE_UMASK_MASK } from './constants.js';
|
|
32
|
+
import { elephaHome } from './paths.js';
|
|
33
|
+
/**
|
|
34
|
+
* The only variables read from a .env file. Adding one here is a deliberate
|
|
35
|
+
* act: it widens what a config file can change about this process.
|
|
36
|
+
*/
|
|
37
|
+
const ALLOWED_KEYS = new Set([
|
|
38
|
+
'ANTHROPIC_API_KEY',
|
|
39
|
+
'ANTHROPIC_MODEL',
|
|
40
|
+
'CLAUDE_CONFIG_DIR',
|
|
41
|
+
'CODEX_HOME',
|
|
42
|
+
'ELEPHA_CLAUDE_MCP_PATH',
|
|
43
|
+
'ELEPHA_DB_PATH',
|
|
44
|
+
'ELEPHA_HOME',
|
|
45
|
+
]);
|
|
46
|
+
/** Package root, resolved from this module's own location - not from cwd. */
|
|
47
|
+
function packageRoot() {
|
|
48
|
+
// dist/config/env.js -> dist/config -> dist -> <package root>
|
|
49
|
+
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Candidate files, most specific first. `ELEPHA_ENV_FILE` exists so the
|
|
53
|
+
* launchd plist and the CLI can be pointed at one file while the key lives in
|
|
54
|
+
* two places.
|
|
55
|
+
*
|
|
56
|
+
* An explicit ELEPHA_ENV_FILE is the ONLY candidate when set. Falling back to
|
|
57
|
+
* a different file because the named one is missing would mean the process
|
|
58
|
+
* silently ran against config the operator did not choose - the same
|
|
59
|
+
* "reads as working and isn't" shape as every other bug in this codebase's
|
|
60
|
+
* reference cases.
|
|
61
|
+
*/
|
|
62
|
+
export function envFileCandidates() {
|
|
63
|
+
const explicit = process.env.ELEPHA_ENV_FILE;
|
|
64
|
+
if (explicit) {
|
|
65
|
+
return [path.resolve(explicit)];
|
|
66
|
+
}
|
|
67
|
+
return [path.join(elephaHome(), '.env'), path.join(packageRoot(), '.env')];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Parses .env text. Supports `KEY=value`, `#` comments, blank lines, and
|
|
71
|
+
* single/double quoted values. No interpolation, no command substitution, no
|
|
72
|
+
* multi-line values - anything fancier is a config file trying to be a
|
|
73
|
+
* program.
|
|
74
|
+
*/
|
|
75
|
+
export function parseEnv(text) {
|
|
76
|
+
const out = new Map();
|
|
77
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
78
|
+
const line = rawLine.trim();
|
|
79
|
+
if (line === '' || line.startsWith('#')) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const eq = line.indexOf('=');
|
|
83
|
+
if (eq <= 0) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const key = line
|
|
87
|
+
.slice(0, eq)
|
|
88
|
+
.trim()
|
|
89
|
+
.replace(/^export\s+/, '');
|
|
90
|
+
let value = line.slice(eq + 1).trim();
|
|
91
|
+
if ((value.startsWith('"') && value.endsWith('"') && value.length >= 2) ||
|
|
92
|
+
(value.startsWith("'") && value.endsWith("'") && value.length >= 2)) {
|
|
93
|
+
value = value.slice(1, -1);
|
|
94
|
+
}
|
|
95
|
+
if (key !== '') {
|
|
96
|
+
out.set(key, value);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Applies the first existing candidate file to process.env.
|
|
103
|
+
*
|
|
104
|
+
* Returns names only, never values. Callers may log the result; nothing in it
|
|
105
|
+
* can leak a secret. (`SummarizerCallLog.sanitizeErrorMessage` is the matching
|
|
106
|
+
* guard on the other end, for keys echoed back inside API error text.)
|
|
107
|
+
*/
|
|
108
|
+
export function loadEnvFile() {
|
|
109
|
+
for (const file of envFileCandidates()) {
|
|
110
|
+
if (!existsSync(file)) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
let mode;
|
|
114
|
+
let parsed;
|
|
115
|
+
try {
|
|
116
|
+
mode = statSync(file).mode & 0o777;
|
|
117
|
+
parsed = parseEnv(readFileSync(file, 'utf8'));
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
// The file is there but unreadable. Report it and carry on
|
|
121
|
+
// unconfigured rather than crashing the CLI: `elepha status`
|
|
122
|
+
// should still work when the key file is misowned.
|
|
123
|
+
return {
|
|
124
|
+
file,
|
|
125
|
+
applied: [],
|
|
126
|
+
ignored: [],
|
|
127
|
+
tooPermissive: false,
|
|
128
|
+
error: errorMessage(err),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const applied = [];
|
|
132
|
+
const ignored = [];
|
|
133
|
+
for (const [key, value] of parsed) {
|
|
134
|
+
if (!ALLOWED_KEYS.has(key)) {
|
|
135
|
+
ignored.push(key);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
// Explicit environment wins. Never overwrite.
|
|
139
|
+
if (process.env[key] === undefined || process.env[key] === '') {
|
|
140
|
+
process.env[key] = value;
|
|
141
|
+
applied.push(key);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return { file, applied, ignored, tooPermissive: (mode & PRIVATE_UMASK_MASK) !== 0 };
|
|
145
|
+
}
|
|
146
|
+
return { applied: [], ignored: [], tooPermissive: false };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Loads and warns, for CLI entrypoints. Warnings go to stderr so they never
|
|
150
|
+
* pollute a hook's stdout (a SessionStart hook's stdout is parsed as JSON -
|
|
151
|
+
* see the Phase 2 hook design).
|
|
152
|
+
*/
|
|
153
|
+
export function loadEnvFileWithWarnings(warn = console.error) {
|
|
154
|
+
const result = loadEnvFile();
|
|
155
|
+
if (result.error && result.file) {
|
|
156
|
+
warn(`[elepha] WARNING: could not read ${result.file}: ${result.error}. Continuing without it.`);
|
|
157
|
+
}
|
|
158
|
+
if (result.tooPermissive && result.file) {
|
|
159
|
+
warn(`[elepha] WARNING: ${result.file} is readable by other users (chmod 600 it). It holds an API key.`);
|
|
160
|
+
}
|
|
161
|
+
if (result.ignored.length > 0 && result.file) {
|
|
162
|
+
// Not silent: a key that looks set but is being ignored is exactly the
|
|
163
|
+
// "reads as working and isn't" failure this codebase keeps hitting.
|
|
164
|
+
warn(`[elepha] ignored non-allowlisted variable(s) in ${result.file}: ${result.ignored.join(', ')}`);
|
|
165
|
+
}
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Hook configuration is deliberately narrow: malformed explicit config is an
|
|
2
|
+
// error, whereas an absent config keeps the documented fail-open defaults.
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { elephaConfigPath } from './paths.js';
|
|
5
|
+
export const DEFAULT_MEMORY_CONFIG = {
|
|
6
|
+
on_startup: 'notify',
|
|
7
|
+
on_clear: 'notify',
|
|
8
|
+
on_resume: 'auto',
|
|
9
|
+
on_compact: 'off',
|
|
10
|
+
captureClaudeCode: true,
|
|
11
|
+
captureCodex: true,
|
|
12
|
+
};
|
|
13
|
+
const KEYS = ['on_startup', 'on_clear', 'on_resume', 'on_compact'];
|
|
14
|
+
const MODES = new Set(['notify', 'auto', 'off', 'ask']);
|
|
15
|
+
export function readMemoryConfig(filePath = elephaConfigPath()) {
|
|
16
|
+
let raw;
|
|
17
|
+
try {
|
|
18
|
+
raw = readFileSync(filePath, 'utf8');
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (error.code === 'ENOENT') {
|
|
22
|
+
return { config: { ...DEFAULT_MEMORY_CONFIG } };
|
|
23
|
+
}
|
|
24
|
+
return { error: `cannot read memory config` };
|
|
25
|
+
}
|
|
26
|
+
let parsed;
|
|
27
|
+
try {
|
|
28
|
+
parsed = JSON.parse(raw);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return { error: 'memory config is invalid JSON' };
|
|
32
|
+
}
|
|
33
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
34
|
+
return { error: 'memory config must be an object' };
|
|
35
|
+
}
|
|
36
|
+
const memory = parsed.memory;
|
|
37
|
+
if (memory === undefined) {
|
|
38
|
+
return { config: { ...DEFAULT_MEMORY_CONFIG } };
|
|
39
|
+
}
|
|
40
|
+
if (!memory || typeof memory !== 'object' || Array.isArray(memory)) {
|
|
41
|
+
return { error: 'memory config.memory must be an object' };
|
|
42
|
+
}
|
|
43
|
+
const output = { ...DEFAULT_MEMORY_CONFIG };
|
|
44
|
+
for (const key of KEYS) {
|
|
45
|
+
const value = memory[key];
|
|
46
|
+
if (value === undefined) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (typeof value !== 'string' || !MODES.has(value)) {
|
|
50
|
+
return { error: `memory config ${key} is unsupported` };
|
|
51
|
+
}
|
|
52
|
+
output[key] = value;
|
|
53
|
+
}
|
|
54
|
+
const settings = parsed;
|
|
55
|
+
if (typeof settings['capture-claude-code'] === 'boolean') {
|
|
56
|
+
output.captureClaudeCode = settings['capture-claude-code'];
|
|
57
|
+
}
|
|
58
|
+
if (typeof settings['capture-codex'] === 'boolean') {
|
|
59
|
+
output.captureCodex = settings['capture-codex'];
|
|
60
|
+
}
|
|
61
|
+
return { config: output };
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=memory-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-config.js","sourceRoot":"","sources":["../../src/config/memory-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
// Where the watched CLIs keep their session transcripts.
|
|
2
|
+
//
|
|
3
|
+
// Both tools support relocating their config/state directory via an env var.
|
|
4
|
+
// Hardcoding ~/.claude and ~/.codex makes every user with a non-default setup
|
|
5
|
+
// silently invisible to elepha - the daemon watches a directory that never
|
|
6
|
+
// receives writes and reports RUNNING forever. Every path into either tool
|
|
7
|
+
// must resolve through here.
|
|
8
|
+
//
|
|
9
|
+
// Case handling follows platform filesystem defaults: macOS and Windows are
|
|
10
|
+
// case-insensitive, while Linux and other platforms are case-sensitive. Compare
|
|
11
|
+
// with samePath/normalizeForCompare; store the original casing. Volume-level
|
|
12
|
+
// case-sensitivity detection is deliberately out of scope.
|
|
13
|
+
import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
15
|
+
import path from 'node:path';
|
|
16
|
+
import { DEFAULT_ELEPHA_SERVICE_LABEL, REFUSED_ABSOLUTE_PROJECT_ROOTS, REFUSED_HOME_PROJECT_ROOTS, TEMPORARY_PROJECT_ROOTS, } from './constants.js';
|
|
17
|
+
export { DEFAULT_ELEPHA_SERVICE_LABEL } from './constants.js';
|
|
18
|
+
export function expandUserPath(p) {
|
|
19
|
+
if (p === '~') {
|
|
20
|
+
return homedir();
|
|
21
|
+
}
|
|
22
|
+
return p.startsWith('~/') ? path.join(homedir(), p.slice(2)) : p;
|
|
23
|
+
}
|
|
24
|
+
/** Claude Code's config root. Honors CLAUDE_CONFIG_DIR, else ~/.claude. */
|
|
25
|
+
export function claudeConfigDir() {
|
|
26
|
+
const override = process.env.CLAUDE_CONFIG_DIR?.trim();
|
|
27
|
+
return override ? path.resolve(override) : path.join(homedir(), '.claude');
|
|
28
|
+
}
|
|
29
|
+
/** Codex's home. Honors CODEX_HOME, else ~/.codex. */
|
|
30
|
+
export function codexHome() {
|
|
31
|
+
const override = process.env.CODEX_HOME?.trim();
|
|
32
|
+
return override ? path.resolve(override) : path.join(homedir(), '.codex');
|
|
33
|
+
}
|
|
34
|
+
export function claudeProjectsRoot() {
|
|
35
|
+
return path.join(claudeConfigDir(), 'projects');
|
|
36
|
+
}
|
|
37
|
+
export function codexSessionsRoot() {
|
|
38
|
+
return path.join(codexHome(), 'sessions');
|
|
39
|
+
}
|
|
40
|
+
export function providerStoreRoot(tool) {
|
|
41
|
+
if (tool === 'claude-code') {
|
|
42
|
+
return claudeProjectsRoot();
|
|
43
|
+
}
|
|
44
|
+
if (tool === 'codex') {
|
|
45
|
+
return codexSessionsRoot();
|
|
46
|
+
}
|
|
47
|
+
throw new Error(`Unsupported transcript provider: ${String(tool)}`);
|
|
48
|
+
}
|
|
49
|
+
/** elepha's own user configuration; hooks only read it and never create it. */
|
|
50
|
+
export function elephaConfigPath() {
|
|
51
|
+
return elephaPaths().config;
|
|
52
|
+
}
|
|
53
|
+
export function hookLogPath() {
|
|
54
|
+
const override = process.env.ELEPHA_HOOK_LOG_PATH?.trim();
|
|
55
|
+
if (override) {
|
|
56
|
+
return path.resolve(override);
|
|
57
|
+
}
|
|
58
|
+
return path.join(elephaLogDir(), 'hook.log');
|
|
59
|
+
}
|
|
60
|
+
export function claudeSettingsPath() {
|
|
61
|
+
return path.join(claudeConfigDir(), 'settings.json');
|
|
62
|
+
}
|
|
63
|
+
/** Claude Code's user-scoped MCP registry. Project .mcp.json is deliberately never used here. */
|
|
64
|
+
export function claudeMcpPath() {
|
|
65
|
+
const override = process.env.ELEPHA_CLAUDE_MCP_PATH?.trim();
|
|
66
|
+
if (override) {
|
|
67
|
+
return path.resolve(override);
|
|
68
|
+
}
|
|
69
|
+
return path.join(homedir(), '.claude.json');
|
|
70
|
+
}
|
|
71
|
+
export function codexConfigPath() {
|
|
72
|
+
return path.join(codexHome(), 'config.toml');
|
|
73
|
+
}
|
|
74
|
+
/** elepha-owned paths are kept together so persistent integrations never learn a Node-manager path. */
|
|
75
|
+
export function elephaHome() {
|
|
76
|
+
const override = process.env.ELEPHA_HOME?.trim();
|
|
77
|
+
if (override) {
|
|
78
|
+
return path.resolve(override);
|
|
79
|
+
}
|
|
80
|
+
return path.join(homedir(), '.elepha');
|
|
81
|
+
}
|
|
82
|
+
/** Complete elepha-owned layout for one user home. */
|
|
83
|
+
export function elephaPaths(home = homedir()) {
|
|
84
|
+
// The normal user-home layout honors ELEPHA_HOME; explicit homes are used
|
|
85
|
+
// by isolated install/test runs and retain their literal layout.
|
|
86
|
+
const root = home === homedir() ? elephaHome() : path.join(home, '.elepha');
|
|
87
|
+
const logDir = path.join(root, 'logs');
|
|
88
|
+
const serviceDir = path.join(root, 'service');
|
|
89
|
+
return {
|
|
90
|
+
home,
|
|
91
|
+
root,
|
|
92
|
+
config: path.join(root, 'config.json'),
|
|
93
|
+
launcher: path.join(root, 'bin', 'elepha'),
|
|
94
|
+
logDir,
|
|
95
|
+
serviceDir,
|
|
96
|
+
installState: path.join(serviceDir, 'install-state.json'),
|
|
97
|
+
installTransaction: path.join(serviceDir, 'install-transaction.json'),
|
|
98
|
+
launchFailure: path.join(serviceDir, 'launch-failure.json'),
|
|
99
|
+
heartbeat: path.join(root, 'daemon.heartbeat.json'),
|
|
100
|
+
updateCheckState: path.join(root, 'update-check.json'),
|
|
101
|
+
updateAvailable: path.join(root, 'update-available.json'),
|
|
102
|
+
stdout: path.join(logDir, 'daemon.stdout.log'),
|
|
103
|
+
stderr: path.join(logDir, 'daemon.stderr.log'),
|
|
104
|
+
launchAgent: path.join(home, 'Library', 'LaunchAgents', `${elephaServiceLabel()}.plist`),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/** A service label is also a LaunchAgents filename component, so keep it path-safe. */
|
|
108
|
+
export function elephaServiceLabel() {
|
|
109
|
+
const override = process.env.ELEPHA_SERVICE_LABEL?.trim();
|
|
110
|
+
if (!override) {
|
|
111
|
+
return DEFAULT_ELEPHA_SERVICE_LABEL;
|
|
112
|
+
}
|
|
113
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9.-]*$/.test(override)) {
|
|
114
|
+
throw new Error('ELEPHA_SERVICE_LABEL must contain only letters, numbers, dots, and hyphens');
|
|
115
|
+
}
|
|
116
|
+
return override;
|
|
117
|
+
}
|
|
118
|
+
export function elephaLauncherPath() {
|
|
119
|
+
return elephaPaths().launcher;
|
|
120
|
+
}
|
|
121
|
+
export function elephaLogDir() {
|
|
122
|
+
return elephaPaths().logDir;
|
|
123
|
+
}
|
|
124
|
+
export function elephaInstallTransactionPath() {
|
|
125
|
+
return elephaPaths().installTransaction;
|
|
126
|
+
}
|
|
127
|
+
export function elephaLaunchFailurePath() {
|
|
128
|
+
return elephaPaths().launchFailure;
|
|
129
|
+
}
|
|
130
|
+
export function daemonHeartbeatPath() {
|
|
131
|
+
return elephaPaths().heartbeat;
|
|
132
|
+
}
|
|
133
|
+
/** Daemon-owned cache state for the daily registry check. */
|
|
134
|
+
export function updateCheckStatePath() {
|
|
135
|
+
return elephaPaths().updateCheckState;
|
|
136
|
+
}
|
|
137
|
+
/** Hook-readable marker written only when the daemon found a newer release. */
|
|
138
|
+
export function updateAvailablePath() {
|
|
139
|
+
return elephaPaths().updateAvailable;
|
|
140
|
+
}
|
|
141
|
+
export function daemonStdoutLogPath() {
|
|
142
|
+
return elephaPaths().stdout;
|
|
143
|
+
}
|
|
144
|
+
export function daemonStderrLogPath() {
|
|
145
|
+
return elephaPaths().stderr;
|
|
146
|
+
}
|
|
147
|
+
export function daemonLaunchAgentPath(label = elephaServiceLabel()) {
|
|
148
|
+
return label === elephaServiceLabel() ? elephaPaths().launchAgent : path.join(homedir(), 'Library', 'LaunchAgents', `${label}.plist`);
|
|
149
|
+
}
|
|
150
|
+
/** Forward-slash form, for substring checks that must behave the same on Windows. */
|
|
151
|
+
export function toPosix(p) {
|
|
152
|
+
return p.split(path.sep).join('/');
|
|
153
|
+
}
|
|
154
|
+
export function normalizeForCompare(p, platform = process.platform) {
|
|
155
|
+
const normalized = toPosix(path.normalize(p));
|
|
156
|
+
const comparePlatform = typeof platform === 'string' ? platform : process.platform;
|
|
157
|
+
return comparePlatform === 'darwin' || comparePlatform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
158
|
+
}
|
|
159
|
+
export function samePath(a, b, platform = process.platform) {
|
|
160
|
+
return normalizeForCompare(a, platform) === normalizeForCompare(b, platform);
|
|
161
|
+
}
|
|
162
|
+
/** Resolves symlinks when possible; non-existent paths retain lexical resolution. */
|
|
163
|
+
export function canonicalizeExisting(p) {
|
|
164
|
+
try {
|
|
165
|
+
return realpathSync(p);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return path.resolve(p);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/** True if `child` is inside `parent` (or is `parent`), using platform-default case handling. */
|
|
172
|
+
export function isWithin(parent, child, platform = process.platform) {
|
|
173
|
+
const p = normalizeForCompare(parent, platform).replace(/\/+$/, '');
|
|
174
|
+
const c = normalizeForCompare(child, platform);
|
|
175
|
+
return c === p || c.startsWith(`${p}/`);
|
|
176
|
+
}
|
|
177
|
+
export function isWithinProviderStore(tool, sourcePath) {
|
|
178
|
+
try {
|
|
179
|
+
return isWithin(canonicalizeExisting(providerStoreRoot(tool)), canonicalizeExisting(sourcePath));
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
export function isReadableProviderSource(tool, sourcePath) {
|
|
186
|
+
return isWithinProviderStore(tool, sourcePath) && existsSync(sourcePath);
|
|
187
|
+
}
|
|
188
|
+
const XDG_USER_DIR_NAMES = ['DESKTOP', 'DOCUMENTS', 'DOWNLOAD'];
|
|
189
|
+
const WSL_WINDOWS_HOME_PATTERN = /^\/mnt\/[a-z]\/Users\/[^/]+$/;
|
|
190
|
+
let cachedLocalizedUserDirRoots;
|
|
191
|
+
let cachedRefusedRootSet;
|
|
192
|
+
function parseXdgUserDir(rawValue, home) {
|
|
193
|
+
const quoted = rawValue.match(/^"((?:[^"\\]|\\.)*)"\s*(?:#.*)?$/);
|
|
194
|
+
if (!quoted) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
let value = '';
|
|
198
|
+
for (let index = 0; index < quoted[1].length; index++) {
|
|
199
|
+
const character = quoted[1][index];
|
|
200
|
+
if (character !== '\\') {
|
|
201
|
+
value += character;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const escaped = quoted[1][++index];
|
|
205
|
+
if (escaped === undefined) {
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
value += ['$', '`', '"', '\\'].includes(escaped) ? escaped : `\\${escaped}`;
|
|
209
|
+
}
|
|
210
|
+
for (const homeVariable of ['$HOME', `\${HOME}`]) {
|
|
211
|
+
if (value === homeVariable) {
|
|
212
|
+
return home;
|
|
213
|
+
}
|
|
214
|
+
if (value.startsWith(`${homeVariable}/`)) {
|
|
215
|
+
return path.join(home, value.slice(homeVariable.length + 1));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return path.isAbsolute(value) && !value.includes('\0') ? path.normalize(value) : undefined;
|
|
219
|
+
}
|
|
220
|
+
function readLocalizedUserDirRoots(inputs) {
|
|
221
|
+
try {
|
|
222
|
+
const configuredHome = inputs.xdgConfigHome?.trim();
|
|
223
|
+
const configHome = configuredHome || path.join(inputs.home, '.config');
|
|
224
|
+
if (!path.isAbsolute(configHome)) {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
const source = readFileSync(path.join(configHome, 'user-dirs.dirs'), 'utf8');
|
|
228
|
+
const roots = new Map();
|
|
229
|
+
for (const line of source.split(/\r?\n/)) {
|
|
230
|
+
if (!/^\s*XDG_(?:DESKTOP|DOCUMENTS|DOWNLOAD)_DIR\b/.test(line)) {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
const assignment = line.match(/^\s*XDG_(DESKTOP|DOCUMENTS|DOWNLOAD)_DIR\s*=\s*(.*?)\s*$/);
|
|
234
|
+
if (!assignment) {
|
|
235
|
+
return [];
|
|
236
|
+
}
|
|
237
|
+
const root = parseXdgUserDir(assignment[2], inputs.home);
|
|
238
|
+
if (!root) {
|
|
239
|
+
return [];
|
|
240
|
+
}
|
|
241
|
+
roots.set(assignment[1], root);
|
|
242
|
+
}
|
|
243
|
+
if (!XDG_USER_DIR_NAMES.every((name) => roots.has(name))) {
|
|
244
|
+
return [];
|
|
245
|
+
}
|
|
246
|
+
return XDG_USER_DIR_NAMES.map((name) => roots.get(name));
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
return [];
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function sameRefusedRootInputs(left, right) {
|
|
253
|
+
return (left.home === right.home &&
|
|
254
|
+
left.xdgConfigHome === right.xdgConfigHome &&
|
|
255
|
+
left.claudeConfigRoot === right.claudeConfigRoot &&
|
|
256
|
+
left.codexConfigRoot === right.codexConfigRoot);
|
|
257
|
+
}
|
|
258
|
+
function localizedUserDirRoots(inputs) {
|
|
259
|
+
if (!cachedLocalizedUserDirRoots || !sameRefusedRootInputs(cachedLocalizedUserDirRoots.inputs, inputs)) {
|
|
260
|
+
cachedLocalizedUserDirRoots = { inputs, roots: readLocalizedUserDirRoots(inputs) };
|
|
261
|
+
}
|
|
262
|
+
return cachedLocalizedUserDirRoots.roots;
|
|
263
|
+
}
|
|
264
|
+
function withCanonicalForms(roots) {
|
|
265
|
+
return roots.flatMap((root) => [root, canonicalizeExisting(root)]);
|
|
266
|
+
}
|
|
267
|
+
function refusedRootSet(inputs) {
|
|
268
|
+
if (cachedRefusedRootSet && sameRefusedRootInputs(cachedRefusedRootSet.inputs, inputs)) {
|
|
269
|
+
return cachedRefusedRootSet;
|
|
270
|
+
}
|
|
271
|
+
cachedRefusedRootSet = {
|
|
272
|
+
inputs,
|
|
273
|
+
exact: withCanonicalForms([
|
|
274
|
+
...REFUSED_HOME_PROJECT_ROOTS.map((relative) => path.join(inputs.home, relative)),
|
|
275
|
+
...localizedUserDirRoots(inputs),
|
|
276
|
+
...REFUSED_ABSOLUTE_PROJECT_ROOTS,
|
|
277
|
+
]),
|
|
278
|
+
temporary: withCanonicalForms(TEMPORARY_PROJECT_ROOTS),
|
|
279
|
+
toolConfig: withCanonicalForms([inputs.claudeConfigRoot, inputs.codexConfigRoot]),
|
|
280
|
+
};
|
|
281
|
+
return cachedRefusedRootSet;
|
|
282
|
+
}
|
|
283
|
+
function isRefusedWslWindowsRoot(candidate) {
|
|
284
|
+
const normalized = toPosix(path.normalize(candidate)).replace(/\/+$/, '');
|
|
285
|
+
if (WSL_WINDOWS_HOME_PATTERN.test(normalized)) {
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
return (WSL_WINDOWS_HOME_PATTERN.test(path.posix.dirname(normalized)) &&
|
|
289
|
+
REFUSED_HOME_PROJECT_ROOTS.some((relative) => relative !== '' && path.posix.basename(normalized) === relative));
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Directories that must never become a project, regardless of what a
|
|
293
|
+
* transcript's cwd says.
|
|
294
|
+
*
|
|
295
|
+
* $HOME itself is the one that actually bit us: a Codex session run from the
|
|
296
|
+
* home directory registered `/Users/<me>` as a project and ingested personal
|
|
297
|
+
* content (medical imaging files) into memory. Purging the row is not a fix -
|
|
298
|
+
* the next session from that cwd recreates it, which is exactly what happened
|
|
299
|
+
* within hours of the purge. The refusal has to live at ingestion.
|
|
300
|
+
*
|
|
301
|
+
* Only the directory ITSELF is refused, not everything beneath it: real
|
|
302
|
+
* projects live under $HOME. `~/Documents`, `~/Desktop` and `~/Downloads` are
|
|
303
|
+
* refused as project roots for the same reason - they are document dumps, not
|
|
304
|
+
* codebases. Tool config homes are refused as whole trees because their
|
|
305
|
+
* contents are provider state, not user projects.
|
|
306
|
+
*/
|
|
307
|
+
export function isRefusedProjectRoot(projectPath) {
|
|
308
|
+
if (!projectPath.trim()) {
|
|
309
|
+
return true; // an empty cwd yields an unreachable project row
|
|
310
|
+
}
|
|
311
|
+
const canonicalProjectPath = canonicalizeExisting(projectPath);
|
|
312
|
+
const candidatePaths = [projectPath, canonicalProjectPath];
|
|
313
|
+
const roots = refusedRootSet({
|
|
314
|
+
home: homedir(),
|
|
315
|
+
xdgConfigHome: process.env.XDG_CONFIG_HOME,
|
|
316
|
+
claudeConfigRoot: claudeConfigDir(),
|
|
317
|
+
codexConfigRoot: codexHome(),
|
|
318
|
+
});
|
|
319
|
+
// Temporary trees are never durable project roots. Unlike the user-facing
|
|
320
|
+
// document directories above, refusing only their own root would let a
|
|
321
|
+
// transient checkout such as /private/tmp/.../hooktest become permanent
|
|
322
|
+
// memory merely by being one level deeper.
|
|
323
|
+
return candidatePaths.some((candidate) => roots.exact.some((root) => samePath(root, candidate)) ||
|
|
324
|
+
roots.temporary.some((root) => isWithin(root, candidate)) ||
|
|
325
|
+
roots.toolConfig.some((root) => isWithin(root, candidate)) ||
|
|
326
|
+
isRefusedWslWindowsRoot(candidate));
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* De-duplicates paths that differ only by case, keeping the first spelling
|
|
330
|
+
* seen. Used for files_touched: on macOS the same file reached via different
|
|
331
|
+
* casing must not appear twice.
|
|
332
|
+
*/
|
|
333
|
+
export function dedupePaths(paths) {
|
|
334
|
+
const seen = new Map();
|
|
335
|
+
for (const p of paths) {
|
|
336
|
+
const key = normalizeForCompare(p);
|
|
337
|
+
if (!seen.has(key)) {
|
|
338
|
+
seen.set(key, p);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return [...seen.values()];
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/config/paths.ts"],"names":[],"mappings":"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"}
|