@gajae-code/coding-agent 0.16.7 → 0.17.1
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/CHANGELOG.md +180 -1
- package/dist/types/capability/fs.d.ts +37 -4
- package/dist/types/capability/index.d.ts +19 -0
- package/dist/types/capability/types.d.ts +9 -0
- package/dist/types/cli/doctor/args.d.ts +36 -0
- package/dist/types/cli/doctor/checks.d.ts +18 -0
- package/dist/types/cli/doctor/config-repairs.d.ts +38 -0
- package/dist/types/cli/doctor/context.d.ts +89 -0
- package/dist/types/cli/doctor/files.d.ts +27 -0
- package/dist/types/cli/doctor/ids.d.ts +20 -0
- package/dist/types/cli/doctor/install-repairs.d.ts +94 -0
- package/dist/types/cli/doctor/journal.d.ts +43 -0
- package/dist/types/cli/doctor/managed-link.d.ts +39 -0
- package/dist/types/cli/doctor/native-probe.d.ts +2 -0
- package/dist/types/cli/doctor/permission-repairs.d.ts +25 -0
- package/dist/types/cli/doctor/plugin-quarantine.d.ts +77 -0
- package/dist/types/cli/doctor/plugin-restore.d.ts +40 -0
- package/dist/types/cli/doctor/plugin-targets.d.ts +11 -0
- package/dist/types/cli/doctor/probe-client.d.ts +9 -0
- package/dist/types/cli/doctor/probe-types.d.ts +18 -0
- package/dist/types/cli/doctor/probe.d.ts +3 -0
- package/dist/types/cli/doctor/projection-probe.d.ts +2 -0
- package/dist/types/cli/doctor/repairs.d.ts +28 -0
- package/dist/types/cli/doctor/report.d.ts +27 -0
- package/dist/types/cli/doctor/runner.d.ts +4 -0
- package/dist/types/cli/doctor/safety.d.ts +10 -0
- package/dist/types/cli/doctor/service-repairs.d.ts +8 -0
- package/dist/types/cli/doctor/service-targets.d.ts +41 -0
- package/dist/types/cli/doctor/types.d.ts +145 -0
- package/dist/types/cli/doctor-cli.d.ts +7 -0
- package/dist/types/cli/doctor-supervisor.d.ts +121 -0
- package/dist/types/cli/doctor-worker.d.ts +29 -0
- package/dist/types/cli/install-activation.d.ts +158 -0
- package/dist/types/cli/macos-community-app.d.ts +41 -0
- package/dist/types/cli/mcp-cli.d.ts +0 -11
- package/dist/types/cli/update-cli.d.ts +41 -4
- package/dist/types/cli-main.d.ts +174 -0
- package/dist/types/cli.d.ts +1 -171
- package/dist/types/commands/doctor.d.ts +7 -0
- package/dist/types/commands/sdk.d.ts +17 -8
- package/dist/types/config/autorouting-tier-map.d.ts +19 -0
- package/dist/types/config/file-lock.d.ts +27 -3
- package/dist/types/config/model-preset-registry.d.ts +1 -0
- package/dist/types/config/model-registry.d.ts +12 -5
- package/dist/types/config/model-resolver.d.ts +16 -3
- package/dist/types/config/models-config-schema.d.ts +2 -0
- package/dist/types/config/settings-schema.d.ts +1 -1
- package/dist/types/coordinator-mcp/question-gate-codec.d.ts +1 -1
- package/dist/types/coordinator-mcp/session-reaper.d.ts +15 -5
- package/dist/types/cursor.d.ts +9 -9
- package/dist/types/discovery/agents-md.d.ts +6 -1
- package/dist/types/discovery/helpers.d.ts +36 -7
- package/dist/types/discovery/index.d.ts +1 -1
- package/dist/types/discovery/mcp-json.d.ts +2 -0
- package/dist/types/extensibility/extensions/loader.d.ts +22 -1
- package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +14 -1
- package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -1
- package/dist/types/extensibility/gjc-plugins/types.d.ts +25 -0
- package/dist/types/extensibility/plugins/manager.d.ts +33 -4
- package/dist/types/extensibility/plugins/marketplace/cache.d.ts +6 -0
- package/dist/types/extensibility/plugins/marketplace/manager.d.ts +186 -0
- package/dist/types/extensibility/plugins/marketplace/registry.d.ts +27 -0
- package/dist/types/extensibility/plugins/marketplace/source-resolver.d.ts +16 -1
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +16 -3
- package/dist/types/gjc-runtime/autoresearch-runtime.d.ts +6 -0
- package/dist/types/gjc-runtime/launch-worktree.d.ts +53 -0
- package/dist/types/gjc-runtime/session-layout.d.ts +8 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +15 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +13 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +6 -0
- package/dist/types/main.d.ts +19 -1
- package/dist/types/modes/acp/acp-agent.d.ts +40 -0
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +2 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/runtime-mcp/config-writer.d.ts +47 -0
- package/dist/types/runtime-mcp/policy-json-edit.d.ts +60 -0
- package/dist/types/runtime-mcp/startup-policy.d.ts +4 -0
- package/dist/types/runtime-mcp/types.d.ts +2 -2
- package/dist/types/sdk/acp/adapter.d.ts +5 -1
- package/dist/types/sdk/broker/broker.d.ts +51 -0
- package/dist/types/sdk/broker/daemon-entry.d.ts +39 -0
- package/dist/types/sdk/broker/discovery.d.ts +38 -0
- package/dist/types/sdk/broker/doctor-restart.d.ts +79 -0
- package/dist/types/sdk/broker/endpoint-authority.d.ts +7 -0
- package/dist/types/sdk/broker/ensure.d.ts +14 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +2 -0
- package/dist/types/sdk/broker/process-incarnation.d.ts +50 -0
- package/dist/types/sdk/broker/runtime.d.ts +26 -0
- package/dist/types/sdk/broker/session-index.d.ts +13 -4
- package/dist/types/sdk/broker/worktree-occupancy.d.ts +14 -0
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +16 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +101 -6
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +16 -0
- package/dist/types/sdk/bus/daemon-startup-exclusion.d.ts +43 -0
- package/dist/types/sdk/bus/doctor-daemon-restart-client.d.ts +51 -0
- package/dist/types/sdk/bus/doctor-daemon-restart.d.ts +39 -0
- package/dist/types/sdk/bus/index.d.ts +2 -0
- package/dist/types/sdk/bus/notification-service.d.ts +3 -0
- package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +11 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -0
- package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +1 -0
- package/dist/types/sdk/bus/telegram-daemon.d.ts +36 -5
- package/dist/types/sdk/cli/session-cli.d.ts +1 -0
- package/dist/types/sdk/host/session-runtime.d.ts +4 -0
- package/dist/types/sdk/host/surface-policy.d.ts +3 -1
- package/dist/types/sdk/lifecycle/service.d.ts +44 -10
- package/dist/types/sdk/prompt-deadline-lease.d.ts +6 -3
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -2
- package/dist/types/sdk/prompt-failure.d.ts +47 -0
- package/dist/types/sdk/prompt-status.d.ts +19 -0
- package/dist/types/sdk/router/session-router.d.ts +3 -4
- package/dist/types/sdk/service-artifact-paths.d.ts +16 -0
- package/dist/types/sdk/session-authority.d.ts +9 -0
- package/dist/types/sdk/session.d.ts +3 -1
- package/dist/types/session/agent-session.d.ts +1 -1
- package/dist/types/session/blob-store.d.ts +1 -1
- package/dist/types/session/fallback-chain-controller.d.ts +3 -6
- package/dist/types/session/internal/managed-session-scope.d.ts +44 -0
- package/dist/types/session/primary-control-surface.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +6 -0
- package/dist/types/system-prompt.d.ts +6 -0
- package/dist/types/tools/ask.d.ts +25 -0
- package/dist/types/tools/image-gen.d.ts +0 -4
- package/dist/types/tools/skill-discovery.d.ts +7 -5
- package/dist/types/tools/ultragoal-ask-guard.d.ts +7 -4
- package/dist/types/utils/changelog.d.ts +0 -9
- package/dist/types/utils/mupdf-wasm.d.ts +1 -0
- package/package.json +9 -8
- package/scripts/compile-args.ts +8 -4
- package/src/capability/fs.ts +395 -17
- package/src/capability/index.ts +273 -10
- package/src/capability/types.ts +9 -0
- package/src/cli/customize-doctor.ts +18 -12
- package/src/cli/doctor/args.ts +236 -0
- package/src/cli/doctor/checks.ts +431 -0
- package/src/cli/doctor/config-repairs.ts +517 -0
- package/src/cli/doctor/context.ts +149 -0
- package/src/cli/doctor/files.ts +149 -0
- package/src/cli/doctor/ids.ts +115 -0
- package/src/cli/doctor/install-repairs.ts +335 -0
- package/src/cli/doctor/journal.ts +423 -0
- package/src/cli/doctor/managed-link.ts +514 -0
- package/src/cli/doctor/native-probe.ts +13 -0
- package/src/cli/doctor/permission-repairs.ts +242 -0
- package/src/cli/doctor/plugin-quarantine.ts +377 -0
- package/src/cli/doctor/plugin-restore.ts +59 -0
- package/src/cli/doctor/plugin-targets.ts +373 -0
- package/src/cli/doctor/probe-client.ts +195 -0
- package/src/cli/doctor/probe-types.ts +21 -0
- package/src/cli/doctor/probe.ts +42 -0
- package/src/cli/doctor/projection-probe.ts +249 -0
- package/src/cli/doctor/repairs.ts +1157 -0
- package/src/cli/doctor/report.ts +176 -0
- package/src/cli/doctor/runner.ts +342 -0
- package/src/cli/doctor/safety.ts +40 -0
- package/src/cli/doctor/service-repairs.ts +452 -0
- package/src/cli/doctor/service-targets.ts +274 -0
- package/src/cli/doctor/types.ts +164 -0
- package/src/cli/doctor-cli.ts +62 -0
- package/src/cli/doctor-supervisor.ts +571 -0
- package/src/cli/doctor-worker.ts +181 -0
- package/src/cli/install-activation.ts +666 -0
- package/src/cli/macos-community-app.ts +1449 -0
- package/src/cli/mcp-cli.ts +11 -21
- package/src/cli/nofile-limit.ts +5 -1
- package/src/cli/plugin-cli.ts +6 -1
- package/src/cli/update-cli.ts +362 -264
- package/src/cli-main.ts +517 -0
- package/src/cli.ts +64 -433
- package/src/commands/autoresearch.ts +11 -5
- package/src/commands/completion.ts +1 -1
- package/src/commands/doctor.ts +13 -0
- package/src/commands/sdk.ts +58 -10
- package/src/commands/ultragoal.ts +11 -5
- package/src/config/autorouting-tier-map.ts +7 -0
- package/src/config/file-lock.ts +736 -71
- package/src/config/mcp-schema.json +3 -3
- package/src/config/model-preset-registry.ts +1 -0
- package/src/config/model-registry.ts +80 -27
- package/src/config/model-resolver.ts +33 -4
- package/src/config/models-config-schema.ts +2 -0
- package/src/config/settings-schema.ts +6 -2
- package/src/coordinator-mcp/question-gate-codec.ts +1 -0
- package/src/coordinator-mcp/server.ts +534 -51
- package/src/coordinator-mcp/session-reaper.ts +64 -8
- package/src/cursor.ts +223 -53
- package/src/discovery/agents-md.ts +74 -8
- package/src/discovery/agents.ts +32 -7
- package/src/discovery/builtin.ts +184 -75
- package/src/discovery/claude-plugins.ts +85 -17
- package/src/discovery/cline.ts +38 -10
- package/src/discovery/cursor.ts +19 -6
- package/src/discovery/gemini.ts +62 -22
- package/src/discovery/github.ts +13 -3
- package/src/discovery/helpers.ts +483 -89
- package/src/discovery/index.ts +1 -0
- package/src/discovery/mcp-json.ts +36 -10
- package/src/discovery/opencode.ts +36 -19
- package/src/discovery/ssh.ts +11 -8
- package/src/discovery/windsurf.ts +12 -3
- package/src/exec/bash-executor.ts +10 -3
- package/src/exec/isolated-shell.ts +15 -2
- package/src/extensibility/extensions/loader.ts +88 -26
- package/src/extensibility/gjc-plugins/lifecycle.ts +189 -0
- package/src/extensibility/gjc-plugins/paths.ts +4 -1
- package/src/extensibility/gjc-plugins/types.ts +27 -0
- package/src/extensibility/plugins/manager.ts +200 -22
- package/src/extensibility/plugins/marketplace/cache.ts +55 -2
- package/src/extensibility/plugins/marketplace/manager.ts +1262 -162
- package/src/extensibility/plugins/marketplace/registry.ts +153 -0
- package/src/extensibility/plugins/marketplace/source-resolver.ts +116 -10
- package/src/extensibility/runtime-skill-discovery.ts +61 -9
- package/src/extensibility/skill-management.ts +7 -1
- package/src/gjc-runtime/autoresearch-runtime.ts +10 -1
- package/src/gjc-runtime/launch-worktree.test.ts +248 -0
- package/src/gjc-runtime/launch-worktree.ts +275 -38
- package/src/gjc-runtime/repository-binding.ts +26 -1
- package/src/gjc-runtime/session-layout.ts +10 -0
- package/src/gjc-runtime/session-state-lock.ts +330 -23
- package/src/gjc-runtime/session-state-sidecar.ts +328 -80
- package/src/gjc-runtime/ultragoal-runtime.ts +10 -1
- package/src/harness-control-plane/session-lease.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +28 -26
- package/src/main.ts +150 -29
- package/src/memories/index.ts +24 -2
- package/src/modes/acp/acp-agent.ts +522 -68
- package/src/modes/components/agent-dashboard.ts +3 -1
- package/src/modes/components/model-selector.ts +28 -19
- package/src/modes/components/plugin-settings.ts +2 -1
- package/src/modes/controllers/selector-controller.ts +15 -9
- package/src/modes/interactive-mode.ts +21 -3
- package/src/prompts/system/system-prompt.md +5 -1
- package/src/prompts/tools/browser.md +1 -1
- package/src/prompts/tools/move-session.md +4 -0
- package/src/prompts/tools/read.md +2 -1
- package/src/prompts/tools/skill-discovery.md +6 -5
- package/src/prompts/tools/task.md +1 -0
- package/src/runtime-mcp/config-writer.ts +228 -0
- package/src/runtime-mcp/oauth-discovery.ts +114 -14
- package/src/runtime-mcp/policy-json-edit.ts +129 -0
- package/src/runtime-mcp/startup-policy.ts +14 -0
- package/src/runtime-mcp/types.ts +2 -2
- package/src/sdk/acp/adapter.ts +27 -12
- package/src/sdk/broker/broker.ts +273 -44
- package/src/sdk/broker/daemon-entry.ts +119 -0
- package/src/sdk/broker/discovery.ts +173 -20
- package/src/sdk/broker/doctor-restart.ts +206 -0
- package/src/sdk/broker/endpoint-authority.ts +36 -0
- package/src/sdk/broker/ensure.ts +49 -14
- package/src/sdk/broker/lifecycle.ts +174 -42
- package/src/sdk/broker/process-incarnation.ts +86 -2
- package/src/sdk/broker/runtime.ts +145 -21
- package/src/sdk/broker/session-index.ts +136 -22
- package/src/sdk/broker/spawn-substrate.ts +4 -1
- package/src/sdk/broker/transport.ts +5 -0
- package/src/sdk/broker/worktree-occupancy.ts +21 -1
- package/src/sdk/bus/chat-daemon-cli.ts +63 -0
- package/src/sdk/bus/chat-daemon-control.ts +260 -64
- package/src/sdk/bus/chat-daemon-runtime.ts +141 -25
- package/src/sdk/bus/daemon-startup-exclusion.ts +119 -0
- package/src/sdk/bus/doctor-daemon-restart-client.ts +291 -0
- package/src/sdk/bus/doctor-daemon-restart.ts +92 -0
- package/src/sdk/bus/index.ts +252 -51
- package/src/sdk/bus/kind-aware-reconciliation.ts +76 -41
- package/src/sdk/bus/notification-service.ts +21 -3
- package/src/sdk/bus/reconciliation-store.ts +17 -11
- package/src/sdk/bus/telegram-daemon-cli.ts +91 -5
- package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
- package/src/sdk/bus/telegram-daemon-control.ts +47 -0
- package/src/sdk/bus/telegram-daemon-owner-registry.ts +1 -1
- package/src/sdk/bus/telegram-daemon.ts +178 -13
- package/src/sdk/cli/session-cli.ts +100 -12
- package/src/sdk/host/host.ts +2 -7
- package/src/sdk/host/session-runtime.test.ts +329 -8
- package/src/sdk/host/session-runtime.ts +202 -50
- package/src/sdk/host/surface-policy.ts +8 -1
- package/src/sdk/lifecycle/service.ts +199 -22
- package/src/sdk/mcp/server.ts +1 -1
- package/src/sdk/prompt-deadline-lease.ts +12 -4
- package/src/sdk/prompt-deadline-manager.ts +5 -7
- package/src/sdk/prompt-failure.ts +148 -0
- package/src/sdk/prompt-status.ts +30 -1
- package/src/sdk/prompt-watchdog.ts +11 -3
- package/src/sdk/protocol/operation-inventory.generated.json +18 -0
- package/src/sdk/protocol/operation-registry.ts +20 -8
- package/src/sdk/router/session-router.ts +8 -3
- package/src/sdk/service-artifact-paths.ts +26 -0
- package/src/sdk/session-authority.ts +10 -0
- package/src/sdk/session.ts +361 -194
- package/src/session/agent-session.ts +398 -93
- package/src/session/blob-store.ts +9 -9
- package/src/session/fallback-chain-controller.ts +3 -7
- package/src/session/internal/managed-session-scope.ts +445 -29
- package/src/session/internal/managed-session-storage.ts +38 -6
- package/src/session/primary-control-surface.ts +12 -0
- package/src/session/session-manager.ts +11 -3
- package/src/session/session-storage.ts +1 -1
- package/src/session-import/codex.ts +6 -1
- package/src/session-import/redact.ts +7 -0
- package/src/skill-state/workflow-mutation-guard.ts +645 -39
- package/src/slash-commands/builtin-registry.ts +7 -3
- package/src/system-prompt.ts +8 -0
- package/src/task/executor.ts +36 -3
- package/src/task/types.ts +27 -5
- package/src/tools/ask.ts +114 -34
- package/src/tools/browser/actions.ts +2 -2
- package/src/tools/browser/tab-worker.ts +11 -8
- package/src/tools/descriptors.ts +6 -1
- package/src/tools/fetch.ts +7 -2
- package/src/tools/image-gen.ts +33 -34
- package/src/tools/read.ts +78 -32
- package/src/tools/skill-discovery.ts +17 -7
- package/src/tools/tool-catalog.generated.ts +8 -8
- package/src/tools/ultragoal-ask-guard.ts +16 -26
- package/src/utils/changelog.ts +7 -1
- package/src/utils/git.ts +3 -1
- package/src/utils/markit.ts +24 -2
- package/src/utils/mupdf-wasm.ts +26 -0
- package/src/web/search/providers/openai-compatible.ts +191 -14
|
@@ -16,7 +16,9 @@ import type { LoadContext, LoadResult } from "../capability/types";
|
|
|
16
16
|
import { rootContainsGjcManifest } from "../extensibility/gjc-plugins";
|
|
17
17
|
import {
|
|
18
18
|
type ClaudePluginRoot,
|
|
19
|
+
canonicalizePathWithinHome,
|
|
19
20
|
createSourceMeta,
|
|
21
|
+
getReadOptionsForContainment,
|
|
20
22
|
invalidateClaudePluginRoots,
|
|
21
23
|
listClaudePluginRoots,
|
|
22
24
|
loadFilesFromDir,
|
|
@@ -40,9 +42,20 @@ interface ResolvedPluginDir {
|
|
|
40
42
|
warning?: string;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
async function readPluginManifest(
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
async function readPluginManifest(
|
|
46
|
+
root: ClaudePluginRoot,
|
|
47
|
+
ctx: Pick<LoadContext, "home" | "isolatedHome" | "userAgentDir" | "homeIdentity" | "userAgentIdentity">,
|
|
48
|
+
): Promise<ClaudePluginManifest | null> {
|
|
49
|
+
const manifestPath = await canonicalizePathWithinHome(
|
|
50
|
+
ctx,
|
|
51
|
+
path.join(root.path, ".claude-plugin", "plugin.json"),
|
|
52
|
+
root.path,
|
|
53
|
+
root.scope,
|
|
54
|
+
);
|
|
55
|
+
if (!manifestPath) return null;
|
|
56
|
+
const readOptions = await getReadOptionsForContainment(ctx, root.scope, root.path);
|
|
57
|
+
if (ctx.isolatedHome && !readOptions) return null;
|
|
58
|
+
const raw = await readFile(manifestPath, readOptions);
|
|
46
59
|
if (raw === null) return null;
|
|
47
60
|
|
|
48
61
|
try {
|
|
@@ -60,11 +73,12 @@ function isWithinPluginRoot(rootPath: string, targetPath: string): boolean {
|
|
|
60
73
|
}
|
|
61
74
|
|
|
62
75
|
async function resolvePluginDir(
|
|
76
|
+
ctx: Pick<LoadContext, "home" | "isolatedHome" | "userAgentDir" | "homeIdentity" | "userAgentIdentity">,
|
|
63
77
|
root: ClaudePluginRoot,
|
|
64
78
|
manifestKeys: ReadonlyArray<keyof ClaudePluginManifest>,
|
|
65
79
|
fallback: string,
|
|
66
80
|
): Promise<ResolvedPluginDir> {
|
|
67
|
-
const manifest = await readPluginManifest(root);
|
|
81
|
+
const manifest = await readPluginManifest(root, ctx);
|
|
68
82
|
const fallbackDir = path.join(root.path, fallback);
|
|
69
83
|
|
|
70
84
|
let configured: string | undefined;
|
|
@@ -84,7 +98,8 @@ async function resolvePluginDir(
|
|
|
84
98
|
|
|
85
99
|
const resolved = path.resolve(root.path, configured);
|
|
86
100
|
if (isWithinPluginRoot(root.path, resolved)) {
|
|
87
|
-
|
|
101
|
+
const canonical = await canonicalizePathWithinHome(ctx, resolved, root.path, root.scope);
|
|
102
|
+
if (canonical) return { dir: canonical };
|
|
88
103
|
}
|
|
89
104
|
|
|
90
105
|
return {
|
|
@@ -96,16 +111,27 @@ async function resolvePluginDir(
|
|
|
96
111
|
async function listNonGjcPluginRoots(
|
|
97
112
|
home: string,
|
|
98
113
|
cwd: string,
|
|
114
|
+
isolatedHome: boolean,
|
|
115
|
+
homeIdentity?: LoadContext["homeIdentity"],
|
|
99
116
|
allowedLevels: ReadonlySet<"user" | "project"> = new Set(["user", "project"]),
|
|
100
117
|
): Promise<{ roots: ClaudePluginRoot[]; warnings: string[] }> {
|
|
101
|
-
await invalidateClaudePluginRoots(home, cwd);
|
|
102
|
-
const { roots, warnings } = await listClaudePluginRoots(home, cwd);
|
|
118
|
+
await invalidateClaudePluginRoots(home, cwd, isolatedHome);
|
|
119
|
+
const { roots, warnings } = await listClaudePluginRoots(home, cwd, isolatedHome, homeIdentity);
|
|
103
120
|
const filteredRoots: ClaudePluginRoot[] = [];
|
|
104
121
|
const filteredWarnings = allowedLevels.size === 2 ? [...warnings] : [];
|
|
105
122
|
|
|
106
123
|
for (const root of roots) {
|
|
107
124
|
if (!allowedLevels.has(root.scope)) continue;
|
|
108
|
-
|
|
125
|
+
const manifestReadOptions = isolatedHome
|
|
126
|
+
? {
|
|
127
|
+
isolatedHome: true,
|
|
128
|
+
home,
|
|
129
|
+
homeIdentity,
|
|
130
|
+
scope: "project" as const,
|
|
131
|
+
bypassCache: true,
|
|
132
|
+
}
|
|
133
|
+
: undefined;
|
|
134
|
+
if (await rootContainsGjcManifest(root.path, manifestReadOptions)) {
|
|
109
135
|
filteredWarnings.push(`[claude-plugins] Skipping gajae-code plugin root (binding-only): ${root.path}`);
|
|
110
136
|
continue;
|
|
111
137
|
}
|
|
@@ -126,17 +152,25 @@ export async function loadMarketplaceSkills(
|
|
|
126
152
|
const items: Skill[] = [];
|
|
127
153
|
const warnings: string[] = [];
|
|
128
154
|
|
|
129
|
-
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(
|
|
155
|
+
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(
|
|
156
|
+
ctx.home,
|
|
157
|
+
ctx.cwd,
|
|
158
|
+
ctx.isolatedHome ?? false,
|
|
159
|
+
ctx.homeIdentity,
|
|
160
|
+
allowedLevels,
|
|
161
|
+
);
|
|
130
162
|
warnings.push(...rootWarnings);
|
|
131
163
|
|
|
132
164
|
const results = await Promise.all(
|
|
133
165
|
roots.map(async root => {
|
|
134
|
-
const { dir: skillsDir, warning } = await resolvePluginDir(root, ["skills"], "skills");
|
|
166
|
+
const { dir: skillsDir, warning } = await resolvePluginDir(ctx, root, ["skills"], "skills");
|
|
135
167
|
const result = await scanSkillsFromDir(ctx, {
|
|
136
168
|
dir: skillsDir,
|
|
137
169
|
providerId: PROVIDER_ID,
|
|
138
170
|
level: root.scope,
|
|
139
171
|
requireDescription: true,
|
|
172
|
+
containmentRoot: root.path,
|
|
173
|
+
scope: root.scope,
|
|
140
174
|
});
|
|
141
175
|
return { root, result, warning };
|
|
142
176
|
}),
|
|
@@ -162,14 +196,26 @@ async function loadSlashCommands(ctx: LoadContext): Promise<LoadResult<SlashComm
|
|
|
162
196
|
const items: SlashCommand[] = [];
|
|
163
197
|
const warnings: string[] = [];
|
|
164
198
|
|
|
165
|
-
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(
|
|
199
|
+
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(
|
|
200
|
+
ctx.home,
|
|
201
|
+
ctx.cwd,
|
|
202
|
+
ctx.isolatedHome ?? false,
|
|
203
|
+
ctx.homeIdentity,
|
|
204
|
+
);
|
|
166
205
|
warnings.push(...rootWarnings);
|
|
167
206
|
|
|
168
207
|
const results = await Promise.all(
|
|
169
208
|
roots.map(async root => {
|
|
170
|
-
const { dir: commandsDir, warning } = await resolvePluginDir(
|
|
209
|
+
const { dir: commandsDir, warning } = await resolvePluginDir(
|
|
210
|
+
ctx,
|
|
211
|
+
root,
|
|
212
|
+
["commands", "slash-commands"],
|
|
213
|
+
"commands",
|
|
214
|
+
);
|
|
171
215
|
const result = await loadFilesFromDir<SlashCommand>(ctx, commandsDir, PROVIDER_ID, root.scope, {
|
|
172
216
|
extensions: ["md"],
|
|
217
|
+
containmentRoot: root.path,
|
|
218
|
+
scope: root.scope,
|
|
173
219
|
transform: (name, content, filePath, source) => {
|
|
174
220
|
const cmdName = name.replace(/\.md$/, "");
|
|
175
221
|
return {
|
|
@@ -202,7 +248,12 @@ async function loadHooks(ctx: LoadContext): Promise<LoadResult<Hook>> {
|
|
|
202
248
|
const items: Hook[] = [];
|
|
203
249
|
const warnings: string[] = [];
|
|
204
250
|
|
|
205
|
-
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(
|
|
251
|
+
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(
|
|
252
|
+
ctx.home,
|
|
253
|
+
ctx.cwd,
|
|
254
|
+
ctx.isolatedHome ?? false,
|
|
255
|
+
ctx.homeIdentity,
|
|
256
|
+
);
|
|
206
257
|
warnings.push(...rootWarnings);
|
|
207
258
|
|
|
208
259
|
const hookTypes = ["pre", "post"] as const;
|
|
@@ -218,6 +269,8 @@ async function loadHooks(ctx: LoadContext): Promise<LoadResult<Hook>> {
|
|
|
218
269
|
loadTasks.map(async ({ root, hookType }) => {
|
|
219
270
|
const hooksDir = path.join(root.path, "hooks", hookType);
|
|
220
271
|
return loadFilesFromDir<Hook>(ctx, hooksDir, PROVIDER_ID, root.scope, {
|
|
272
|
+
containmentRoot: root.path,
|
|
273
|
+
scope: root.scope,
|
|
221
274
|
transform: (name, _content, filePath, source) => {
|
|
222
275
|
const toolName = name.replace(/\.(sh|bash|zsh|fish)$/, "");
|
|
223
276
|
return {
|
|
@@ -249,13 +302,20 @@ async function loadTools(ctx: LoadContext): Promise<LoadResult<CustomTool>> {
|
|
|
249
302
|
const items: CustomTool[] = [];
|
|
250
303
|
const warnings: string[] = [];
|
|
251
304
|
|
|
252
|
-
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(
|
|
305
|
+
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(
|
|
306
|
+
ctx.home,
|
|
307
|
+
ctx.cwd,
|
|
308
|
+
ctx.isolatedHome ?? false,
|
|
309
|
+
ctx.homeIdentity,
|
|
310
|
+
);
|
|
253
311
|
warnings.push(...rootWarnings);
|
|
254
312
|
|
|
255
313
|
const results = await Promise.all(
|
|
256
314
|
roots.map(async root => {
|
|
257
315
|
const toolsDir = path.join(root.path, "tools");
|
|
258
316
|
return loadFilesFromDir<CustomTool>(ctx, toolsDir, PROVIDER_ID, root.scope, {
|
|
317
|
+
containmentRoot: root.path,
|
|
318
|
+
scope: root.scope,
|
|
259
319
|
transform: (name, _content, filePath, source) => {
|
|
260
320
|
const toolName = name.replace(/\.(ts|js|sh|bash|py)$/, "");
|
|
261
321
|
return {
|
|
@@ -286,12 +346,20 @@ async function loadMCPServers(ctx: LoadContext): Promise<LoadResult<MCPServer>>
|
|
|
286
346
|
const items: MCPServer[] = [];
|
|
287
347
|
const warnings: string[] = [];
|
|
288
348
|
|
|
289
|
-
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(
|
|
349
|
+
const { roots, warnings: rootWarnings } = await listNonGjcPluginRoots(
|
|
350
|
+
ctx.home,
|
|
351
|
+
ctx.cwd,
|
|
352
|
+
ctx.isolatedHome ?? false,
|
|
353
|
+
ctx.homeIdentity,
|
|
354
|
+
);
|
|
290
355
|
warnings.push(...rootWarnings);
|
|
291
356
|
|
|
292
357
|
for (const root of roots) {
|
|
293
|
-
const mcpPath = path.join(root.path, ".mcp.json");
|
|
294
|
-
|
|
358
|
+
const mcpPath = await canonicalizePathWithinHome(ctx, path.join(root.path, ".mcp.json"), root.path, root.scope);
|
|
359
|
+
if (!mcpPath) continue;
|
|
360
|
+
const readOptions = await getReadOptionsForContainment(ctx, root.scope, root.path);
|
|
361
|
+
if (ctx.isolatedHome && !readOptions) continue;
|
|
362
|
+
const raw = await readFile(mcpPath, readOptions);
|
|
295
363
|
if (raw === null) continue; // file absent — skip silently
|
|
296
364
|
|
|
297
365
|
let parsed: unknown;
|
package/src/discovery/cline.ts
CHANGED
|
@@ -6,21 +6,38 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import * as path from "node:path";
|
|
8
8
|
import { registerProvider } from "../capability";
|
|
9
|
-
import { readDirEntries, readFile } from "../capability/fs";
|
|
9
|
+
import { type ReadFileOptions, readDirEntries, readFile } from "../capability/fs";
|
|
10
10
|
import type { Rule } from "../capability/rule";
|
|
11
11
|
import { ruleCapability } from "../capability/rule";
|
|
12
12
|
import type { LoadContext, LoadResult } from "../capability/types";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
buildRuleFromMarkdown,
|
|
15
|
+
canonicalizePathWithinHome,
|
|
16
|
+
createSourceMeta,
|
|
17
|
+
getReadOptions,
|
|
18
|
+
loadFilesFromDir,
|
|
19
|
+
} from "./helpers";
|
|
14
20
|
|
|
15
21
|
const PROVIDER_ID = "cline";
|
|
16
22
|
const DISPLAY_NAME = "Cline";
|
|
17
23
|
const PRIORITY = 40;
|
|
18
24
|
|
|
19
|
-
async function findClinerules(
|
|
25
|
+
async function findClinerules(
|
|
26
|
+
startDir: string,
|
|
27
|
+
stopAt: string,
|
|
28
|
+
readOptions?: ReadFileOptions,
|
|
29
|
+
): Promise<{ path: string; isDir: boolean } | null> {
|
|
20
30
|
let current = path.resolve(startDir);
|
|
31
|
+
const resolvedStop = path.resolve(stopAt);
|
|
32
|
+
const relativeStop = path.relative(resolvedStop, current);
|
|
33
|
+
const effectiveStop =
|
|
34
|
+
relativeStop === "" ||
|
|
35
|
+
(relativeStop !== ".." && !relativeStop.startsWith(`..${path.sep}`) && !path.isAbsolute(relativeStop))
|
|
36
|
+
? resolvedStop
|
|
37
|
+
: current;
|
|
21
38
|
|
|
22
39
|
while (true) {
|
|
23
|
-
const entries = await readDirEntries(current);
|
|
40
|
+
const entries = await readDirEntries(current, readOptions);
|
|
24
41
|
const entry = entries.find(e => e.name === ".clinerules");
|
|
25
42
|
if (entry) {
|
|
26
43
|
return {
|
|
@@ -29,7 +46,7 @@ async function findClinerules(startDir: string): Promise<{ path: string; isDir:
|
|
|
29
46
|
};
|
|
30
47
|
}
|
|
31
48
|
const parent = path.dirname(current);
|
|
32
|
-
if (parent === current) return null;
|
|
49
|
+
if (current === effectiveStop || parent === current) return null;
|
|
33
50
|
current = parent;
|
|
34
51
|
}
|
|
35
52
|
}
|
|
@@ -42,7 +59,13 @@ async function loadRules(ctx: LoadContext): Promise<LoadResult<Rule>> {
|
|
|
42
59
|
const warnings: string[] = [];
|
|
43
60
|
|
|
44
61
|
// Project-level only (Cline uses root-level .clinerules)
|
|
45
|
-
const
|
|
62
|
+
const homeRelative = path.relative(ctx.home, ctx.cwd);
|
|
63
|
+
const cwdIsWithinHome =
|
|
64
|
+
homeRelative === "" ||
|
|
65
|
+
(homeRelative !== ".." && !homeRelative.startsWith(`..${path.sep}`) && !path.isAbsolute(homeRelative));
|
|
66
|
+
const stopDirectory = ctx.repoRoot ?? (ctx.isolatedHome || cwdIsWithinHome ? ctx.home : path.parse(ctx.cwd).root);
|
|
67
|
+
const readOptions = getReadOptions(ctx, "project");
|
|
68
|
+
const found = await findClinerules(ctx.cwd, stopDirectory, readOptions);
|
|
46
69
|
if (!found) {
|
|
47
70
|
return { items, warnings };
|
|
48
71
|
}
|
|
@@ -60,14 +83,19 @@ async function loadRules(ctx: LoadContext): Promise<LoadResult<Rule>> {
|
|
|
60
83
|
if (result.warnings) warnings.push(...result.warnings);
|
|
61
84
|
} else {
|
|
62
85
|
// Single file format
|
|
63
|
-
const
|
|
86
|
+
const filePath = await canonicalizePathWithinHome(ctx, found.path, undefined, "project");
|
|
87
|
+
if (!filePath) {
|
|
88
|
+
warnings.push(`Refusing to read .clinerules outside the supplied home at ${found.path}`);
|
|
89
|
+
return { items, warnings };
|
|
90
|
+
}
|
|
91
|
+
const content = await readFile(filePath, readOptions);
|
|
64
92
|
if (content === null) {
|
|
65
|
-
warnings.push(`Failed to read .clinerules at ${
|
|
93
|
+
warnings.push(`Failed to read .clinerules at ${filePath}`);
|
|
66
94
|
return { items, warnings };
|
|
67
95
|
}
|
|
68
96
|
|
|
69
|
-
const source = createSourceMeta(PROVIDER_ID,
|
|
70
|
-
items.push(buildRuleFromMarkdown("clinerules.md", content,
|
|
97
|
+
const source = createSourceMeta(PROVIDER_ID, filePath, "project");
|
|
98
|
+
items.push(buildRuleFromMarkdown("clinerules.md", content, filePath, source, { ruleName: "clinerules" }));
|
|
71
99
|
}
|
|
72
100
|
|
|
73
101
|
return { items, warnings };
|
package/src/discovery/cursor.ts
CHANGED
|
@@ -25,7 +25,15 @@ import { ruleCapability } from "../capability/rule";
|
|
|
25
25
|
import type { Settings } from "../capability/settings";
|
|
26
26
|
import { settingsCapability } from "../capability/settings";
|
|
27
27
|
import type { LoadContext, LoadResult, SourceMeta } from "../capability/types";
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
buildRuleFromMarkdown,
|
|
30
|
+
canonicalizePathWithinHome,
|
|
31
|
+
createSourceMeta,
|
|
32
|
+
getProjectPath,
|
|
33
|
+
getReadOptions,
|
|
34
|
+
getUserPath,
|
|
35
|
+
loadFilesFromDir,
|
|
36
|
+
} from "./helpers";
|
|
29
37
|
|
|
30
38
|
const PROVIDER_ID = "cursor";
|
|
31
39
|
const DISPLAY_NAME = "Cursor";
|
|
@@ -79,15 +87,20 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
79
87
|
const items: Settings[] = [];
|
|
80
88
|
const warnings: string[] = [];
|
|
81
89
|
|
|
82
|
-
const
|
|
90
|
+
const rawUserPath = getUserPath(ctx, "cursor", "settings.json");
|
|
91
|
+
const rawProjectPath = getProjectPath(ctx, "cursor", "settings.json");
|
|
83
92
|
|
|
84
|
-
const [
|
|
85
|
-
|
|
86
|
-
|
|
93
|
+
const [userPath, projectPath] = await Promise.all([
|
|
94
|
+
rawUserPath ? canonicalizePathWithinHome(ctx, rawUserPath, undefined, "user") : Promise.resolve(null),
|
|
95
|
+
rawProjectPath ? canonicalizePathWithinHome(ctx, rawProjectPath, undefined, "project") : Promise.resolve(null),
|
|
87
96
|
]);
|
|
88
97
|
|
|
89
|
-
const
|
|
98
|
+
const userContentPromise = userPath ? readFile(userPath, getReadOptions(ctx, "user")) : Promise.resolve(null);
|
|
99
|
+
const projectContentPromise = projectPath
|
|
100
|
+
? readFile(projectPath, getReadOptions(ctx, "project"))
|
|
101
|
+
: Promise.resolve(null);
|
|
90
102
|
|
|
103
|
+
const userContent = await userContentPromise;
|
|
91
104
|
if (userContent && userPath) {
|
|
92
105
|
const parsed = tryParseJson<Record<string, unknown>>(userContent);
|
|
93
106
|
if (parsed) {
|
package/src/discovery/gemini.ts
CHANGED
|
@@ -30,9 +30,11 @@ import type { LoadContext, LoadResult } from "../capability/types";
|
|
|
30
30
|
import {
|
|
31
31
|
buildExtensionModuleItems,
|
|
32
32
|
calculateDepth,
|
|
33
|
+
canonicalizePathWithinHome,
|
|
33
34
|
createSourceMeta,
|
|
34
35
|
discoverExtensionModulePaths,
|
|
35
36
|
getProjectPath,
|
|
37
|
+
getReadOptions,
|
|
36
38
|
getUserPath,
|
|
37
39
|
} from "./helpers";
|
|
38
40
|
|
|
@@ -49,9 +51,12 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
|
|
|
49
51
|
const warnings: string[] = [];
|
|
50
52
|
|
|
51
53
|
// User-level: ~/.gemini/GEMINI.md
|
|
52
|
-
const
|
|
54
|
+
const rawUserGeminiMd = getUserPath(ctx, "gemini", "GEMINI.md");
|
|
55
|
+
const userGeminiMd = rawUserGeminiMd
|
|
56
|
+
? await canonicalizePathWithinHome(ctx, rawUserGeminiMd, undefined, "user")
|
|
57
|
+
: null;
|
|
53
58
|
if (userGeminiMd) {
|
|
54
|
-
const content = await readFile(userGeminiMd);
|
|
59
|
+
const content = await readFile(userGeminiMd, getReadOptions(ctx, "user"));
|
|
55
60
|
if (content) {
|
|
56
61
|
items.push({
|
|
57
62
|
path: userGeminiMd,
|
|
@@ -63,9 +68,12 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
|
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
// Project-level: .gemini/GEMINI.md
|
|
66
|
-
const
|
|
71
|
+
const rawProjectGeminiMd = getProjectPath(ctx, "gemini", "GEMINI.md");
|
|
72
|
+
const projectGeminiMd = rawProjectGeminiMd
|
|
73
|
+
? await canonicalizePathWithinHome(ctx, rawProjectGeminiMd, undefined, "project")
|
|
74
|
+
: null;
|
|
67
75
|
if (projectGeminiMd) {
|
|
68
|
-
const content = await readFile(projectGeminiMd);
|
|
76
|
+
const content = await readFile(projectGeminiMd, getReadOptions(ctx, "project"));
|
|
69
77
|
if (content) {
|
|
70
78
|
const projectBase = getProjectPath(ctx, "gemini", "");
|
|
71
79
|
const depth = projectBase ? calculateDepth(ctx.cwd, projectBase, path.sep) : 0;
|
|
@@ -94,7 +102,7 @@ async function loadExtensions(ctx: LoadContext): Promise<LoadResult<Extension>>
|
|
|
94
102
|
// User-level: ~/.gemini/extensions/*/gemini-extension.json
|
|
95
103
|
const userExtPath = getUserPath(ctx, "gemini", "extensions");
|
|
96
104
|
if (userExtPath) {
|
|
97
|
-
const result = await loadExtensionsFromDir(userExtPath, "user");
|
|
105
|
+
const result = await loadExtensionsFromDir(ctx, userExtPath, "user");
|
|
98
106
|
items.push(...result.items);
|
|
99
107
|
if (result.warnings) warnings.push(...result.warnings);
|
|
100
108
|
}
|
|
@@ -102,7 +110,7 @@ async function loadExtensions(ctx: LoadContext): Promise<LoadResult<Extension>>
|
|
|
102
110
|
// Project-level: .gemini/extensions/*/gemini-extension.json
|
|
103
111
|
const projectExtPath = getProjectPath(ctx, "gemini", "extensions");
|
|
104
112
|
if (projectExtPath) {
|
|
105
|
-
const result = await loadExtensionsFromDir(projectExtPath, "project");
|
|
113
|
+
const result = await loadExtensionsFromDir(ctx, projectExtPath, "project");
|
|
106
114
|
items.push(...result.items);
|
|
107
115
|
if (result.warnings) warnings.push(...result.warnings);
|
|
108
116
|
}
|
|
@@ -110,15 +118,35 @@ async function loadExtensions(ctx: LoadContext): Promise<LoadResult<Extension>>
|
|
|
110
118
|
return { items, warnings };
|
|
111
119
|
}
|
|
112
120
|
|
|
113
|
-
async function loadExtensionsFromDir(
|
|
114
|
-
|
|
121
|
+
async function loadExtensionsFromDir(
|
|
122
|
+
ctx: LoadContext,
|
|
123
|
+
extensionsDir: string,
|
|
124
|
+
level: "user" | "project",
|
|
125
|
+
): Promise<LoadResult<Extension>> {
|
|
126
|
+
const scope = level === "user" ? "user" : "project";
|
|
127
|
+
const readOptions = getReadOptions(ctx, scope);
|
|
128
|
+
const canonicalExtensionsDir = await canonicalizePathWithinHome(ctx, extensionsDir, undefined, scope);
|
|
129
|
+
if (!canonicalExtensionsDir) return { items: [], warnings: [] };
|
|
130
|
+
const entries = await readDirEntries(canonicalExtensionsDir, readOptions);
|
|
115
131
|
const dirEntries = entries.filter(entry => entry.isDirectory());
|
|
116
132
|
|
|
117
133
|
const results = await Promise.all(
|
|
118
134
|
dirEntries.map(async entry => {
|
|
119
|
-
const extPath =
|
|
120
|
-
|
|
121
|
-
|
|
135
|
+
const extPath = await canonicalizePathWithinHome(
|
|
136
|
+
ctx,
|
|
137
|
+
path.join(canonicalExtensionsDir, entry.name),
|
|
138
|
+
undefined,
|
|
139
|
+
scope,
|
|
140
|
+
);
|
|
141
|
+
if (!extPath) return { entry, extPath: null, manifestPath: null, content: null };
|
|
142
|
+
const manifestPath = await canonicalizePathWithinHome(
|
|
143
|
+
ctx,
|
|
144
|
+
path.join(extPath, "gemini-extension.json"),
|
|
145
|
+
undefined,
|
|
146
|
+
scope,
|
|
147
|
+
);
|
|
148
|
+
if (!manifestPath) return { entry, extPath, manifestPath: null, content: null };
|
|
149
|
+
const content = await readFile(manifestPath, readOptions);
|
|
122
150
|
return { entry, extPath, manifestPath, content };
|
|
123
151
|
}),
|
|
124
152
|
);
|
|
@@ -127,7 +155,7 @@ async function loadExtensionsFromDir(extensionsDir: string, level: "user" | "pro
|
|
|
127
155
|
const warnings: string[] = [];
|
|
128
156
|
|
|
129
157
|
for (const { entry, extPath, manifestPath, content } of results) {
|
|
130
|
-
if (!content) continue;
|
|
158
|
+
if (!content || !extPath || !manifestPath) continue;
|
|
131
159
|
|
|
132
160
|
const manifest = tryParseJson<ExtensionManifest>(content);
|
|
133
161
|
if (!manifest) {
|
|
@@ -156,8 +184,10 @@ async function loadExtensionModules(ctx: LoadContext): Promise<LoadResult<Extens
|
|
|
156
184
|
const projectExtensionsDir = getProjectPath(ctx, "gemini", "extensions");
|
|
157
185
|
|
|
158
186
|
const [userPaths, projectPaths] = await Promise.all([
|
|
159
|
-
userExtensionsDir ? discoverExtensionModulePaths(ctx, userExtensionsDir) : Promise.resolve([]),
|
|
160
|
-
projectExtensionsDir
|
|
187
|
+
userExtensionsDir ? discoverExtensionModulePaths(ctx, userExtensionsDir, { scope: "user" }) : Promise.resolve([]),
|
|
188
|
+
projectExtensionsDir
|
|
189
|
+
? discoverExtensionModulePaths(ctx, projectExtensionsDir, { scope: "project" })
|
|
190
|
+
: Promise.resolve([]),
|
|
161
191
|
]);
|
|
162
192
|
|
|
163
193
|
const items = buildExtensionModuleItems(PROVIDER_ID, userPaths, projectPaths);
|
|
@@ -174,9 +204,10 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
174
204
|
const warnings: string[] = [];
|
|
175
205
|
|
|
176
206
|
// User-level: ~/.gemini/settings.json
|
|
177
|
-
const
|
|
207
|
+
const rawUserPath = getUserPath(ctx, "gemini", "settings.json");
|
|
208
|
+
const userPath = rawUserPath ? await canonicalizePathWithinHome(ctx, rawUserPath, undefined, "user") : null;
|
|
178
209
|
if (userPath) {
|
|
179
|
-
const content = await readFile(userPath);
|
|
210
|
+
const content = await readFile(userPath, getReadOptions(ctx, "user"));
|
|
180
211
|
if (content) {
|
|
181
212
|
const parsed = tryParseJson<Record<string, unknown>>(content);
|
|
182
213
|
if (parsed) {
|
|
@@ -193,9 +224,12 @@ async function loadSettings(ctx: LoadContext): Promise<LoadResult<Settings>> {
|
|
|
193
224
|
}
|
|
194
225
|
|
|
195
226
|
// Project-level: .gemini/settings.json
|
|
196
|
-
const
|
|
227
|
+
const rawProjectPath = getProjectPath(ctx, "gemini", "settings.json");
|
|
228
|
+
const projectPath = rawProjectPath
|
|
229
|
+
? await canonicalizePathWithinHome(ctx, rawProjectPath, undefined, "project")
|
|
230
|
+
: null;
|
|
197
231
|
if (projectPath) {
|
|
198
|
-
const content = await readFile(projectPath);
|
|
232
|
+
const content = await readFile(projectPath, getReadOptions(ctx, "project"));
|
|
199
233
|
if (content) {
|
|
200
234
|
const parsed = tryParseJson<Record<string, unknown>>(content);
|
|
201
235
|
if (parsed) {
|
|
@@ -234,9 +268,12 @@ async function loadSystemPrompt(ctx: LoadContext): Promise<LoadResult<SystemProm
|
|
|
234
268
|
const items: SystemPrompt[] = [];
|
|
235
269
|
|
|
236
270
|
// User-level: ~/.gemini/system.md
|
|
237
|
-
const
|
|
271
|
+
const rawUserSystemMd = getUserPath(ctx, "gemini", "system.md");
|
|
272
|
+
const userSystemMd = rawUserSystemMd
|
|
273
|
+
? await canonicalizePathWithinHome(ctx, rawUserSystemMd, undefined, "user")
|
|
274
|
+
: null;
|
|
238
275
|
if (userSystemMd) {
|
|
239
|
-
const content = await readFile(userSystemMd);
|
|
276
|
+
const content = await readFile(userSystemMd, getReadOptions(ctx, "user"));
|
|
240
277
|
if (content) {
|
|
241
278
|
items.push({
|
|
242
279
|
path: userSystemMd,
|
|
@@ -248,9 +285,12 @@ async function loadSystemPrompt(ctx: LoadContext): Promise<LoadResult<SystemProm
|
|
|
248
285
|
}
|
|
249
286
|
|
|
250
287
|
// Project-level: .gemini/system.md
|
|
251
|
-
const
|
|
288
|
+
const rawProjectSystemMd = getProjectPath(ctx, "gemini", "system.md");
|
|
289
|
+
const projectSystemMd = rawProjectSystemMd
|
|
290
|
+
? await canonicalizePathWithinHome(ctx, rawProjectSystemMd, undefined, "project")
|
|
291
|
+
: null;
|
|
252
292
|
if (projectSystemMd) {
|
|
253
|
-
const content = await readFile(projectSystemMd);
|
|
293
|
+
const content = await readFile(projectSystemMd, getReadOptions(ctx, "project"));
|
|
254
294
|
if (content) {
|
|
255
295
|
items.push({
|
|
256
296
|
path: projectSystemMd,
|
package/src/discovery/github.ts
CHANGED
|
@@ -19,7 +19,14 @@ import { readFile } from "../capability/fs";
|
|
|
19
19
|
import { type Instruction, instructionCapability } from "../capability/instruction";
|
|
20
20
|
import type { LoadContext, LoadResult, SourceMeta } from "../capability/types";
|
|
21
21
|
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
calculateDepth,
|
|
24
|
+
canonicalizePathWithinHome,
|
|
25
|
+
createSourceMeta,
|
|
26
|
+
getProjectPath,
|
|
27
|
+
getReadOptions,
|
|
28
|
+
loadFilesFromDir,
|
|
29
|
+
} from "./helpers";
|
|
23
30
|
|
|
24
31
|
const PROVIDER_ID = "github";
|
|
25
32
|
const DISPLAY_NAME = "GitHub Copilot";
|
|
@@ -33,9 +40,12 @@ async function loadContextFiles(ctx: LoadContext): Promise<LoadResult<ContextFil
|
|
|
33
40
|
const items: ContextFile[] = [];
|
|
34
41
|
const warnings: string[] = [];
|
|
35
42
|
|
|
36
|
-
const
|
|
43
|
+
const rawCopilotInstructionsPath = getProjectPath(ctx, "github", "copilot-instructions.md");
|
|
44
|
+
const copilotInstructionsPath = rawCopilotInstructionsPath
|
|
45
|
+
? await canonicalizePathWithinHome(ctx, rawCopilotInstructionsPath, undefined, "project")
|
|
46
|
+
: null;
|
|
37
47
|
if (copilotInstructionsPath) {
|
|
38
|
-
const content = await readFile(copilotInstructionsPath);
|
|
48
|
+
const content = await readFile(copilotInstructionsPath, getReadOptions(ctx, "project"));
|
|
39
49
|
if (content) {
|
|
40
50
|
const fileDir = path.dirname(copilotInstructionsPath);
|
|
41
51
|
const depth = calculateDepth(ctx.cwd, fileDir, path.sep);
|