context-mode 1.0.111 → 1.0.113
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.openclaw-plugin/index.ts +3 -2
- package/.openclaw-plugin/openclaw.plugin.json +1 -1
- package/.openclaw-plugin/package.json +1 -1
- package/README.md +152 -34
- package/bin/statusline.mjs +144 -127
- package/build/adapters/base.d.ts +8 -5
- package/build/adapters/base.js +8 -18
- package/build/adapters/claude-code/index.d.ts +24 -3
- package/build/adapters/claude-code/index.js +44 -11
- package/build/adapters/codex/hooks.d.ts +10 -5
- package/build/adapters/codex/hooks.js +10 -5
- package/build/adapters/codex/index.d.ts +17 -5
- package/build/adapters/codex/index.js +337 -37
- package/build/adapters/codex/paths.d.ts +1 -0
- package/build/adapters/codex/paths.js +12 -0
- package/build/adapters/cursor/index.d.ts +6 -0
- package/build/adapters/cursor/index.js +83 -2
- package/build/adapters/detect.d.ts +1 -1
- package/build/adapters/detect.js +29 -6
- package/build/adapters/omp/index.d.ts +65 -0
- package/build/adapters/omp/index.js +182 -0
- package/build/adapters/omp/plugin.d.ts +75 -0
- package/build/adapters/omp/plugin.js +220 -0
- package/build/adapters/openclaw/mcp-tools.d.ts +54 -0
- package/build/adapters/openclaw/mcp-tools.js +198 -0
- package/build/adapters/openclaw/plugin.d.ts +130 -0
- package/build/adapters/openclaw/plugin.js +629 -0
- package/build/adapters/openclaw/workspace-router.d.ts +29 -0
- package/build/adapters/openclaw/workspace-router.js +64 -0
- package/build/adapters/opencode/plugin.d.ts +145 -0
- package/build/adapters/opencode/plugin.js +457 -0
- package/build/adapters/pi/extension.d.ts +26 -0
- package/build/adapters/pi/extension.js +552 -0
- package/build/adapters/pi/index.d.ts +57 -0
- package/build/adapters/pi/index.js +173 -0
- package/build/adapters/pi/mcp-bridge.d.ts +113 -0
- package/build/adapters/pi/mcp-bridge.js +251 -0
- package/build/adapters/types.d.ts +11 -6
- package/build/cli.js +186 -170
- package/build/db-base.d.ts +15 -2
- package/build/db-base.js +50 -5
- package/build/executor.d.ts +2 -0
- package/build/executor.js +15 -2
- package/build/runPool.d.ts +36 -0
- package/build/runPool.js +51 -0
- package/build/runtime.js +64 -5
- package/build/search/auto-memory.js +6 -4
- package/build/security.js +30 -10
- package/build/server.d.ts +23 -1
- package/build/server.js +662 -182
- package/build/session/analytics.d.ts +404 -1
- package/build/session/analytics.js +1347 -42
- package/build/session/db.d.ts +114 -5
- package/build/session/db.js +275 -27
- package/build/session/event-emit.d.ts +48 -0
- package/build/session/event-emit.js +101 -0
- package/build/session/extract.d.ts +1 -0
- package/build/session/extract.js +79 -12
- package/build/session/purge.d.ts +111 -0
- package/build/session/purge.js +138 -0
- package/build/store.d.ts +7 -0
- package/build/store.js +69 -6
- package/build/util/claude-config.d.ts +26 -0
- package/build/util/claude-config.js +91 -0
- package/build/util/hook-config.d.ts +4 -0
- package/build/util/hook-config.js +39 -0
- package/build/util/project-dir.d.ts +49 -0
- package/build/util/project-dir.js +67 -0
- package/cli.bundle.mjs +411 -208
- package/configs/antigravity/GEMINI.md +0 -3
- package/configs/claude-code/CLAUDE.md +1 -4
- package/configs/codex/AGENTS.md +1 -4
- package/configs/codex/config.toml +3 -0
- package/configs/codex/hooks.json +8 -0
- package/configs/cursor/context-mode.mdc +0 -3
- package/configs/gemini-cli/GEMINI.md +0 -3
- package/configs/jetbrains-copilot/copilot-instructions.md +0 -3
- package/configs/kilo/AGENTS.md +0 -3
- package/configs/kiro/KIRO.md +0 -3
- package/configs/omp/SYSTEM.md +85 -0
- package/configs/omp/mcp.json +7 -0
- package/configs/openclaw/AGENTS.md +0 -3
- package/configs/opencode/AGENTS.md +0 -3
- package/configs/pi/AGENTS.md +0 -3
- package/configs/qwen-code/QWEN.md +1 -4
- package/configs/vscode-copilot/copilot-instructions.md +0 -3
- package/configs/zed/AGENTS.md +0 -3
- package/hooks/codex/posttooluse.mjs +9 -2
- package/hooks/codex/precompact.mjs +69 -0
- package/hooks/codex/sessionstart.mjs +13 -9
- package/hooks/codex/stop.mjs +1 -2
- package/hooks/codex/userpromptsubmit.mjs +1 -2
- package/hooks/core/routing.mjs +237 -18
- package/hooks/cursor/afteragentresponse.mjs +1 -1
- package/hooks/cursor/hooks.json +31 -0
- package/hooks/cursor/posttooluse.mjs +1 -1
- package/hooks/cursor/sessionstart.mjs +5 -5
- package/hooks/cursor/stop.mjs +1 -1
- package/hooks/ensure-deps.mjs +12 -13
- package/hooks/gemini-cli/aftertool.mjs +1 -1
- package/hooks/gemini-cli/beforeagent.mjs +1 -1
- package/hooks/gemini-cli/precompress.mjs +3 -2
- package/hooks/gemini-cli/sessionstart.mjs +9 -9
- package/hooks/jetbrains-copilot/posttooluse.mjs +1 -1
- package/hooks/jetbrains-copilot/precompact.mjs +3 -2
- package/hooks/jetbrains-copilot/sessionstart.mjs +9 -9
- package/hooks/kiro/agentspawn.mjs +5 -5
- package/hooks/kiro/posttooluse.mjs +2 -2
- package/hooks/kiro/userpromptsubmit.mjs +1 -1
- package/hooks/posttooluse.mjs +45 -0
- package/hooks/precompact.mjs +17 -0
- package/hooks/pretooluse.mjs +23 -0
- package/hooks/routing-block.mjs +0 -12
- package/hooks/run-hook.mjs +16 -3
- package/hooks/session-db.bundle.mjs +27 -18
- package/hooks/session-extract.bundle.mjs +2 -2
- package/hooks/session-helpers.mjs +101 -64
- package/hooks/sessionstart.mjs +51 -2
- package/hooks/vscode-copilot/posttooluse.mjs +1 -1
- package/hooks/vscode-copilot/precompact.mjs +3 -2
- package/hooks/vscode-copilot/sessionstart.mjs +9 -9
- package/openclaw.plugin.json +1 -1
- package/package.json +14 -8
- package/server.bundle.mjs +349 -147
- package/start.mjs +16 -4
- package/skills/UPSTREAM-CREDITS.md +0 -51
- package/skills/context-mode-ops/SKILL.md +0 -299
- package/skills/context-mode-ops/agent-teams.md +0 -198
- package/skills/context-mode-ops/communication.md +0 -224
- package/skills/context-mode-ops/marketing.md +0 -124
- package/skills/context-mode-ops/release.md +0 -214
- package/skills/context-mode-ops/review-pr.md +0 -269
- package/skills/context-mode-ops/tdd.md +0 -329
- package/skills/context-mode-ops/triage-issue.md +0 -266
- package/skills/context-mode-ops/validation.md +0 -307
- package/skills/diagnose/SKILL.md +0 -122
- package/skills/diagnose/scripts/hitl-loop.template.sh +0 -41
- package/skills/grill-me/SKILL.md +0 -15
- package/skills/grill-with-docs/ADR-FORMAT.md +0 -47
- package/skills/grill-with-docs/CONTEXT-FORMAT.md +0 -77
- package/skills/grill-with-docs/SKILL.md +0 -93
- package/skills/improve-codebase-architecture/DEEPENING.md +0 -37
- package/skills/improve-codebase-architecture/INTERFACE-DESIGN.md +0 -44
- package/skills/improve-codebase-architecture/LANGUAGE.md +0 -53
- package/skills/improve-codebase-architecture/SKILL.md +0 -76
- package/skills/tdd/SKILL.md +0 -114
- package/skills/tdd/deep-modules.md +0 -33
- package/skills/tdd/interface-design.md +0 -31
- package/skills/tdd/mocking.md +0 -59
- package/skills/tdd/refactoring.md +0 -10
- package/skills/tdd/tests.md +0 -61
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code config directory resolver — single source of truth.
|
|
3
|
+
*
|
|
4
|
+
* Issue #460 follow-up: every Claude-aware reader (adapters, security policy
|
|
5
|
+
* loader, hook helpers) MUST agree on where global settings live. Hardcoding
|
|
6
|
+
* `~/.claude` in any one reader silently breaks `CLAUDE_CONFIG_DIR` for that
|
|
7
|
+
* code path, producing policy drift that is invisible until a user sets the
|
|
8
|
+
* env var and watches their settings get ignored.
|
|
9
|
+
*
|
|
10
|
+
* Mirrors the contract of `hooks/session-helpers.mjs::resolveConfigDir` and
|
|
11
|
+
* `ClaudeCodeAdapter.getConfigDir`:
|
|
12
|
+
* - env unset, empty string, or whitespace-only → ~/.claude
|
|
13
|
+
* - env starts with `~`, `~/`, or `~\` → expanded against homedir()
|
|
14
|
+
* - otherwise → resolved to absolute (relative paths anchor to cwd)
|
|
15
|
+
*
|
|
16
|
+
* Whitespace guard: shells that quote-pad the env value (`CLAUDE_CONFIG_DIR=" "`)
|
|
17
|
+
* would otherwise resolve to `cwd/<spaces>` — silently writing settings into
|
|
18
|
+
* the project tree. Trim before the truthy check so quote-padding falls back
|
|
19
|
+
* to `~/.claude` like a sane default.
|
|
20
|
+
*
|
|
21
|
+
* Cross-platform note: tilde regex strips a single leading `/` OR `\` so
|
|
22
|
+
* `~\Users\foo` works on Windows. `path.resolve` handles drive-letter joining.
|
|
23
|
+
*/
|
|
24
|
+
import { resolve } from "node:path";
|
|
25
|
+
import { homedir } from "node:os";
|
|
26
|
+
import { createRequire } from "node:module";
|
|
27
|
+
export function resolveClaudeConfigDir(env = process.env) {
|
|
28
|
+
const envVal = env.CLAUDE_CONFIG_DIR;
|
|
29
|
+
if (envVal && envVal.trim() !== "") {
|
|
30
|
+
if (envVal.startsWith("~")) {
|
|
31
|
+
return resolve(homedir(), envVal.replace(/^~[/\\]?/, ""));
|
|
32
|
+
}
|
|
33
|
+
return resolve(envVal);
|
|
34
|
+
}
|
|
35
|
+
return resolve(homedir(), ".claude");
|
|
36
|
+
}
|
|
37
|
+
/** Resolve the global settings.json path, honoring CLAUDE_CONFIG_DIR. */
|
|
38
|
+
export function resolveClaudeGlobalSettingsPath(env = process.env) {
|
|
39
|
+
return resolve(resolveClaudeConfigDir(env), "settings.json");
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Issue #451 round-3: cross-adapter deny-policy parity.
|
|
43
|
+
*
|
|
44
|
+
* `resolveClaudeGlobalSettingsPath` hardcodes the `.claude` segment, so
|
|
45
|
+
* non-Claude adapters (cursor, codex, qwen-code, gemini-cli, jetbrains-copilot,
|
|
46
|
+
* vscode-copilot, etc.) never had their global settings consulted by the
|
|
47
|
+
* security policy reader. This helper returns the union of:
|
|
48
|
+
*
|
|
49
|
+
* 1. The currently-detected adapter's home-rooted settings.json (when the
|
|
50
|
+
* adapter is non-claude — claude is already covered by entry 2).
|
|
51
|
+
* 2. The claude global settings.json (always — defense in depth).
|
|
52
|
+
*
|
|
53
|
+
* Lazy import of `./adapters/detect.js` keeps this file free of any direct
|
|
54
|
+
* adapter dependency: the detect module itself only `import type`s adapter
|
|
55
|
+
* types at the top level (concrete adapters are loaded dynamically inside
|
|
56
|
+
* `getAdapter()`), so a static import is safe — but we use `createRequire`
|
|
57
|
+
* to make the dependency direction crystal clear and to avoid surprising
|
|
58
|
+
* future maintainers who add eager adapter imports to detect.ts.
|
|
59
|
+
*
|
|
60
|
+
* The returned array is deduplicated and order-stable: adapter-specific path
|
|
61
|
+
* first (most specific), claude global second (fallback).
|
|
62
|
+
*/
|
|
63
|
+
export function resolveAdapterGlobalSettingsPaths(env = process.env) {
|
|
64
|
+
const paths = [];
|
|
65
|
+
// Lazy-load detect module to avoid any chance of an adapter import cycle.
|
|
66
|
+
// `detect.ts` exports pure functions — `detectPlatform` (env-driven) and
|
|
67
|
+
// `getSessionDirSegments` (sync map). Neither instantiates an adapter.
|
|
68
|
+
let detected = null;
|
|
69
|
+
let segmentsFor = null;
|
|
70
|
+
try {
|
|
71
|
+
const lazyRequire = createRequire(import.meta.url);
|
|
72
|
+
const detect = lazyRequire("../adapters/detect.js");
|
|
73
|
+
detected = detect.detectPlatform();
|
|
74
|
+
segmentsFor = detect.getSessionDirSegments;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// If detection fails for any reason, fall back to claude-only behavior.
|
|
78
|
+
}
|
|
79
|
+
if (detected && segmentsFor && detected.platform !== "claude-code") {
|
|
80
|
+
const segments = segmentsFor(detected.platform);
|
|
81
|
+
if (segments && segments.length > 0) {
|
|
82
|
+
paths.push(resolve(homedir(), ...segments, "settings.json"));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Always include claude global as fallback (defense in depth).
|
|
86
|
+
const claudePath = resolveClaudeGlobalSettingsPath(env);
|
|
87
|
+
if (!paths.includes(claudePath)) {
|
|
88
|
+
paths.push(claudePath);
|
|
89
|
+
}
|
|
90
|
+
return paths;
|
|
91
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { HookAdapter } from "../adapters/types.js";
|
|
2
|
+
export declare function getCommandsFromHookEntry(entry: unknown): string[];
|
|
3
|
+
export declare function extractHookScriptPath(command: string): string | null;
|
|
4
|
+
export declare function getHookScriptPaths(adapter: HookAdapter, pluginRoot: string): string[];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function getCommandsFromHookEntry(entry) {
|
|
2
|
+
const commands = [];
|
|
3
|
+
if (entry && typeof entry === "object") {
|
|
4
|
+
const command = entry.command;
|
|
5
|
+
if (typeof command === "string")
|
|
6
|
+
commands.push(command);
|
|
7
|
+
const hooks = entry.hooks;
|
|
8
|
+
if (Array.isArray(hooks)) {
|
|
9
|
+
for (const hook of hooks) {
|
|
10
|
+
if (hook && typeof hook === "object") {
|
|
11
|
+
const nestedCommand = hook.command;
|
|
12
|
+
if (typeof nestedCommand === "string")
|
|
13
|
+
commands.push(nestedCommand);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return commands;
|
|
19
|
+
}
|
|
20
|
+
export function extractHookScriptPath(command) {
|
|
21
|
+
const match = command.match(/(?:"([^"]+\.mjs)"|'([^']+\.mjs)'|(\S+\.mjs))/);
|
|
22
|
+
return match?.[1] ?? match?.[2] ?? match?.[3] ?? null;
|
|
23
|
+
}
|
|
24
|
+
export function getHookScriptPaths(adapter, pluginRoot) {
|
|
25
|
+
const paths = new Set();
|
|
26
|
+
const hookConfig = adapter.generateHookConfig(pluginRoot);
|
|
27
|
+
for (const entries of Object.values(hookConfig)) {
|
|
28
|
+
if (!Array.isArray(entries))
|
|
29
|
+
continue;
|
|
30
|
+
for (const entry of entries) {
|
|
31
|
+
for (const command of getCommandsFromHookEntry(entry)) {
|
|
32
|
+
const scriptPath = extractHookScriptPath(command);
|
|
33
|
+
if (scriptPath)
|
|
34
|
+
paths.add(scriptPath);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return [...paths];
|
|
39
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-dir resolution helpers — shared between `start.mjs` (the MCP entry
|
|
3
|
+
* point) and `src/server.ts getProjectDir()` (the consumer).
|
|
4
|
+
*
|
|
5
|
+
* Background: when Claude Code runs `/ctx-upgrade`, it kills + respawns the
|
|
6
|
+
* MCP server. The respawn happens with `cwd` set to the plugin install
|
|
7
|
+
* directory (`~/.claude/plugins/cache/context-mode/context-mode/<version>/`).
|
|
8
|
+
* The legacy `start.mjs` then set `CLAUDE_PROJECT_DIR = originalCwd`, which
|
|
9
|
+
* poisoned every downstream `ctx_stats` / SessionDB / hash computation —
|
|
10
|
+
* sessions silently re-rooted under the plugin install path.
|
|
11
|
+
*
|
|
12
|
+
* Defense-in-depth fix (v1.0.113):
|
|
13
|
+
* - `start.mjs` calls `isPluginInstallPath(originalCwd)` and skips the env
|
|
14
|
+
* auto-set when true (no poisoning at the source).
|
|
15
|
+
* - `getProjectDir()` calls `resolveProjectDir(...)` which rejects plugin-
|
|
16
|
+
* pathed env vars and the plugin cwd, preferring `process.env.PWD`
|
|
17
|
+
* (shell-set, survives `process.chdir`) before falling back.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Detect whether a path lives inside the Claude Code plugin install tree —
|
|
21
|
+
* specifically `<home>/.claude/plugins/cache/<plugin>/<plugin>/<version>/`
|
|
22
|
+
* or the marketplace mirror `<home>/.claude/plugins/marketplaces/...`.
|
|
23
|
+
*
|
|
24
|
+
* Cross-OS: matches both POSIX (`/`) and Windows (`\`) path separators.
|
|
25
|
+
* Independent of `home` location — we only care about the `.claude/plugins/`
|
|
26
|
+
* suffix pattern.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isPluginInstallPath(p: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Pure project-dir resolver. Mirror of the env-var chain inside
|
|
31
|
+
* `src/server.ts getProjectDir()`, but takes its inputs explicitly so the
|
|
32
|
+
* resolver can be exercised under test without process-level mutation.
|
|
33
|
+
*
|
|
34
|
+
* Resolution order:
|
|
35
|
+
* 1. Adapter-priority env vars (CLAUDE / GEMINI / VSCODE / OPENCODE / PI /
|
|
36
|
+
* IDEA / CONTEXT_MODE) — first non-empty AND non-plugin-path wins.
|
|
37
|
+
* 2. `process.env.PWD` — shell-set, NOT updated by `process.chdir()`, so
|
|
38
|
+
* it survives the `start.mjs` chdir into the plugin dir. Skipped if
|
|
39
|
+
* it too points at a plugin install path.
|
|
40
|
+
* 3. `cwd` — last resort. Returned even if it is a plugin path; the
|
|
41
|
+
* caller is responsible for rendering a graceful "no project context"
|
|
42
|
+
* message rather than panicking. Keeping the function total preserves
|
|
43
|
+
* operation of project-independent tools (sandbox execute, fetch).
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveProjectDir(opts: {
|
|
46
|
+
env: Record<string, string | undefined>;
|
|
47
|
+
cwd: string;
|
|
48
|
+
pwd: string | undefined;
|
|
49
|
+
}): string;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-dir resolution helpers — shared between `start.mjs` (the MCP entry
|
|
3
|
+
* point) and `src/server.ts getProjectDir()` (the consumer).
|
|
4
|
+
*
|
|
5
|
+
* Background: when Claude Code runs `/ctx-upgrade`, it kills + respawns the
|
|
6
|
+
* MCP server. The respawn happens with `cwd` set to the plugin install
|
|
7
|
+
* directory (`~/.claude/plugins/cache/context-mode/context-mode/<version>/`).
|
|
8
|
+
* The legacy `start.mjs` then set `CLAUDE_PROJECT_DIR = originalCwd`, which
|
|
9
|
+
* poisoned every downstream `ctx_stats` / SessionDB / hash computation —
|
|
10
|
+
* sessions silently re-rooted under the plugin install path.
|
|
11
|
+
*
|
|
12
|
+
* Defense-in-depth fix (v1.0.113):
|
|
13
|
+
* - `start.mjs` calls `isPluginInstallPath(originalCwd)` and skips the env
|
|
14
|
+
* auto-set when true (no poisoning at the source).
|
|
15
|
+
* - `getProjectDir()` calls `resolveProjectDir(...)` which rejects plugin-
|
|
16
|
+
* pathed env vars and the plugin cwd, preferring `process.env.PWD`
|
|
17
|
+
* (shell-set, survives `process.chdir`) before falling back.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Detect whether a path lives inside the Claude Code plugin install tree —
|
|
21
|
+
* specifically `<home>/.claude/plugins/cache/<plugin>/<plugin>/<version>/`
|
|
22
|
+
* or the marketplace mirror `<home>/.claude/plugins/marketplaces/...`.
|
|
23
|
+
*
|
|
24
|
+
* Cross-OS: matches both POSIX (`/`) and Windows (`\`) path separators.
|
|
25
|
+
* Independent of `home` location — we only care about the `.claude/plugins/`
|
|
26
|
+
* suffix pattern.
|
|
27
|
+
*/
|
|
28
|
+
export function isPluginInstallPath(p) {
|
|
29
|
+
if (!p)
|
|
30
|
+
return false;
|
|
31
|
+
return /[/\\]\.claude[/\\]plugins[/\\](cache|marketplaces)[/\\]/.test(p);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Pure project-dir resolver. Mirror of the env-var chain inside
|
|
35
|
+
* `src/server.ts getProjectDir()`, but takes its inputs explicitly so the
|
|
36
|
+
* resolver can be exercised under test without process-level mutation.
|
|
37
|
+
*
|
|
38
|
+
* Resolution order:
|
|
39
|
+
* 1. Adapter-priority env vars (CLAUDE / GEMINI / VSCODE / OPENCODE / PI /
|
|
40
|
+
* IDEA / CONTEXT_MODE) — first non-empty AND non-plugin-path wins.
|
|
41
|
+
* 2. `process.env.PWD` — shell-set, NOT updated by `process.chdir()`, so
|
|
42
|
+
* it survives the `start.mjs` chdir into the plugin dir. Skipped if
|
|
43
|
+
* it too points at a plugin install path.
|
|
44
|
+
* 3. `cwd` — last resort. Returned even if it is a plugin path; the
|
|
45
|
+
* caller is responsible for rendering a graceful "no project context"
|
|
46
|
+
* message rather than panicking. Keeping the function total preserves
|
|
47
|
+
* operation of project-independent tools (sandbox execute, fetch).
|
|
48
|
+
*/
|
|
49
|
+
export function resolveProjectDir(opts) {
|
|
50
|
+
const { env, cwd, pwd } = opts;
|
|
51
|
+
const candidates = [
|
|
52
|
+
env.CLAUDE_PROJECT_DIR,
|
|
53
|
+
env.GEMINI_PROJECT_DIR,
|
|
54
|
+
env.VSCODE_CWD,
|
|
55
|
+
env.OPENCODE_PROJECT_DIR,
|
|
56
|
+
env.PI_PROJECT_DIR,
|
|
57
|
+
env.IDEA_INITIAL_DIRECTORY,
|
|
58
|
+
env.CONTEXT_MODE_PROJECT_DIR,
|
|
59
|
+
];
|
|
60
|
+
for (const c of candidates) {
|
|
61
|
+
if (c && !isPluginInstallPath(c))
|
|
62
|
+
return c;
|
|
63
|
+
}
|
|
64
|
+
if (pwd && !isPluginInstallPath(pwd))
|
|
65
|
+
return pwd;
|
|
66
|
+
return cwd;
|
|
67
|
+
}
|