@clinebot/core 0.0.28 → 0.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/ClineCore.d.ts +28 -2
- package/dist/ClineCore.d.ts.map +1 -1
- package/dist/account/cline-account-service.d.ts +1 -1
- package/dist/account/cline-account-service.d.ts.map +1 -1
- package/dist/account/index.d.ts +1 -1
- package/dist/account/index.d.ts.map +1 -1
- package/dist/account/types.d.ts +5 -0
- package/dist/account/types.d.ts.map +1 -1
- package/dist/auth/bounded-ttl-cache.d.ts +14 -0
- package/dist/auth/bounded-ttl-cache.d.ts.map +1 -0
- package/dist/auth/cline.d.ts +27 -2
- package/dist/auth/cline.d.ts.map +1 -1
- package/dist/auth/oca.d.ts.map +1 -1
- package/dist/chat/chat-schema.d.ts +11 -11
- package/dist/extensions/config/agent-config-loader.d.ts.map +1 -0
- package/dist/{agents → extensions/config}/agent-config-parser.d.ts +2 -2
- package/dist/extensions/config/agent-config-parser.d.ts.map +1 -0
- package/dist/{agents → extensions/config}/hooks-config-loader.d.ts +1 -1
- package/dist/extensions/config/hooks-config-loader.d.ts.map +1 -0
- package/dist/{agents → extensions/config}/index.d.ts +2 -4
- package/dist/extensions/config/index.d.ts.map +1 -0
- package/dist/{runtime/commands.d.ts → extensions/config/runtime-commands.d.ts} +2 -3
- package/dist/extensions/config/runtime-commands.d.ts.map +1 -0
- package/dist/extensions/config/unified-config-file-watcher.d.ts.map +1 -0
- package/dist/extensions/config/user-instruction-config-loader.d.ts.map +1 -0
- package/dist/extensions/context/agentic-compaction.d.ts +13 -0
- package/dist/extensions/context/agentic-compaction.d.ts.map +1 -0
- package/dist/extensions/context/basic-compaction.d.ts +9 -0
- package/dist/extensions/context/basic-compaction.d.ts.map +1 -0
- package/dist/extensions/context/compaction-shared.d.ts +60 -0
- package/dist/extensions/context/compaction-shared.d.ts.map +1 -0
- package/dist/extensions/context/compaction.d.ts +20 -0
- package/dist/extensions/context/compaction.d.ts.map +1 -0
- package/dist/extensions/index.d.ts +5 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/mcp/client.d.ts +3 -0
- package/dist/extensions/mcp/client.d.ts.map +1 -0
- package/dist/extensions/mcp/config-loader.d.ts.map +1 -0
- package/dist/extensions/mcp/index.d.ts +9 -0
- package/dist/extensions/mcp/index.d.ts.map +1 -0
- package/dist/{mcp → extensions/mcp}/manager.d.ts +1 -2
- package/dist/extensions/mcp/manager.d.ts.map +1 -0
- package/dist/extensions/mcp/name-transform.d.ts +3 -0
- package/dist/extensions/mcp/name-transform.d.ts.map +1 -0
- package/dist/extensions/mcp/policies.d.ts +15 -0
- package/dist/extensions/mcp/policies.d.ts.map +1 -0
- package/dist/extensions/mcp/tools.d.ts +4 -0
- package/dist/extensions/mcp/tools.d.ts.map +1 -0
- package/dist/{mcp → extensions/mcp}/types.d.ts +29 -1
- package/dist/extensions/mcp/types.d.ts.map +1 -0
- package/dist/{agents → extensions/plugin}/plugin-config-loader.d.ts +1 -1
- package/dist/extensions/plugin/plugin-config-loader.d.ts.map +1 -0
- package/dist/{agents → extensions/plugin}/plugin-loader.d.ts +1 -1
- package/dist/extensions/plugin/plugin-loader.d.ts.map +1 -0
- package/dist/extensions/plugin/plugin-module-import.d.ts +5 -0
- package/dist/extensions/plugin/plugin-module-import.d.ts.map +1 -0
- package/dist/{agents → extensions/plugin}/plugin-sandbox.d.ts +1 -1
- package/dist/extensions/plugin/plugin-sandbox.d.ts.map +1 -0
- package/dist/extensions/plugin-sandbox-bootstrap.js +485 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/persistent.d.ts +64 -0
- package/dist/hooks/persistent.d.ts.map +1 -0
- package/dist/hooks/subprocess-runner.d.ts +22 -0
- package/dist/hooks/subprocess-runner.d.ts.map +1 -0
- package/dist/hooks/subprocess.d.ts +189 -0
- package/dist/hooks/subprocess.d.ts.map +1 -0
- package/dist/index.d.ts +22 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +560 -447
- package/dist/prompt/default-system.d.ts +2 -0
- package/dist/prompt/default-system.d.ts.map +1 -0
- package/dist/providers/local-provider-service.d.ts +1 -1
- package/dist/providers/local-provider-service.d.ts.map +1 -1
- package/dist/runtime/checkpoint-hooks.d.ts +21 -0
- package/dist/runtime/checkpoint-hooks.d.ts.map +1 -0
- package/dist/runtime/hook-file-hooks.d.ts +1 -1
- package/dist/runtime/hook-file-hooks.d.ts.map +1 -1
- package/dist/runtime/rules.d.ts +1 -1
- package/dist/runtime/rules.d.ts.map +1 -1
- package/dist/runtime/runtime-builder.d.ts +1 -1
- package/dist/runtime/runtime-builder.d.ts.map +1 -1
- package/dist/runtime/session-runtime.d.ts +25 -5
- package/dist/runtime/session-runtime.d.ts.map +1 -1
- package/dist/runtime/subprocess-sandbox.d.ts.map +1 -0
- package/dist/runtime/team-runtime-registry.d.ts +1 -1
- package/dist/runtime/team-runtime-registry.d.ts.map +1 -1
- package/dist/runtime/tool-approval.d.ts +1 -1
- package/dist/session/default-session-manager.d.ts +4 -3
- package/dist/session/default-session-manager.d.ts.map +1 -1
- package/dist/session/file-session-service.d.ts +1 -1
- package/dist/session/file-session-service.d.ts.map +1 -1
- package/dist/session/{unified-session-persistence-service.d.ts → persistence-service.d.ts} +11 -42
- package/dist/session/persistence-service.d.ts.map +1 -0
- package/dist/session/rpc-session-service.d.ts +1 -1
- package/dist/session/rpc-session-service.d.ts.map +1 -1
- package/dist/session/session-agent-events.d.ts +1 -1
- package/dist/session/session-artifacts.d.ts.map +1 -1
- package/dist/session/session-config-builder.d.ts.map +1 -1
- package/dist/session/session-graph.d.ts +1 -1
- package/dist/session/session-graph.d.ts.map +1 -1
- package/dist/session/session-host.d.ts.map +1 -1
- package/dist/session/session-manager.d.ts +6 -5
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manifest.d.ts +1 -1
- package/dist/session/session-service.d.ts +3 -2
- package/dist/session/session-service.d.ts.map +1 -1
- package/dist/session/session-team-coordination.d.ts +2 -1
- package/dist/session/session-team-coordination.d.ts.map +1 -1
- package/dist/session/utils/helpers.d.ts +51 -3
- package/dist/session/utils/helpers.d.ts.map +1 -1
- package/dist/session/utils/types.d.ts +41 -7
- package/dist/session/utils/types.d.ts.map +1 -1
- package/dist/session/workspace-manager.d.ts +1 -2
- package/dist/session/workspace-manager.d.ts.map +1 -1
- package/dist/session/workspace-manifest.d.ts +1 -22
- package/dist/session/workspace-manifest.d.ts.map +1 -1
- package/dist/storage/file-team-store.d.ts +2 -1
- package/dist/storage/file-team-store.d.ts.map +1 -1
- package/dist/storage/sqlite-team-store.d.ts +4 -1
- package/dist/storage/sqlite-team-store.d.ts.map +1 -1
- package/dist/storage/team-store.d.ts.map +1 -1
- package/dist/team/delegated-agent.d.ts +44 -0
- package/dist/team/delegated-agent.d.ts.map +1 -0
- package/dist/team/index.d.ts +1 -0
- package/dist/team/index.d.ts.map +1 -1
- package/dist/team/multi-agent.d.ts +229 -0
- package/dist/team/multi-agent.d.ts.map +1 -0
- package/dist/team/projections.d.ts +2 -2
- package/dist/team/projections.d.ts.map +1 -1
- package/dist/team/runtime.d.ts +5 -0
- package/dist/team/runtime.d.ts.map +1 -0
- package/dist/team/spawn-agent-tool.d.ts +85 -0
- package/dist/team/spawn-agent-tool.d.ts.map +1 -0
- package/dist/team/subagent-prompts.d.ts +4 -0
- package/dist/team/subagent-prompts.d.ts.map +1 -0
- package/dist/team/team-tools.d.ts +35 -0
- package/dist/team/team-tools.d.ts.map +1 -0
- package/dist/telemetry/OpenTelemetryProvider.d.ts +11 -1
- package/dist/telemetry/OpenTelemetryProvider.d.ts.map +1 -1
- package/dist/telemetry/{LoggerTelemetryAdapter.d.ts → TelemetryLoggerSink.d.ts} +10 -4
- package/dist/telemetry/TelemetryLoggerSink.d.ts.map +1 -0
- package/dist/telemetry/TelemetryService.d.ts.map +1 -1
- package/dist/telemetry/index.js +15 -28
- package/dist/tools/definitions.d.ts +4 -3
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/index.d.ts +5 -5
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/model-tool-routing.d.ts.map +1 -1
- package/dist/tools/presets.d.ts +26 -0
- package/dist/tools/presets.d.ts.map +1 -1
- package/dist/tools/schemas.d.ts +8 -0
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/types.d.ts +23 -2
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/types/config.d.ts +47 -3
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/events.d.ts +1 -1
- package/dist/types/provider-settings.d.ts +1 -1
- package/dist/types/provider-settings.d.ts.map +1 -1
- package/dist/types/storage.d.ts +2 -1
- package/dist/types/storage.d.ts.map +1 -1
- package/dist/types.d.ts +7 -16
- package/dist/types.d.ts.map +1 -1
- package/package.json +15 -12
- package/src/ClineCore.test.ts +150 -0
- package/src/ClineCore.ts +114 -8
- package/src/account/cline-account-service.test.ts +84 -0
- package/src/account/cline-account-service.ts +2 -2
- package/src/account/index.ts +1 -0
- package/src/account/types.ts +6 -0
- package/src/auth/bounded-ttl-cache.test.ts +38 -0
- package/src/auth/bounded-ttl-cache.ts +53 -0
- package/src/auth/cline.test.ts +173 -36
- package/src/auth/cline.ts +395 -93
- package/src/auth/oca.test.ts +125 -0
- package/src/auth/oca.ts +17 -4
- package/src/{agents → extensions/config}/agent-config-loader.test.ts +1 -1
- package/src/{agents → extensions/config}/agent-config-parser.ts +2 -2
- package/src/{agents → extensions/config}/hooks-config-loader.ts +1 -1
- package/src/{agents → extensions/config}/index.ts +7 -11
- package/src/{runtime/commands.test.ts → extensions/config/runtime-commands.test.ts} +20 -3
- package/src/{runtime/commands.ts → extensions/config/runtime-commands.ts} +1 -8
- package/src/{agents → extensions/config}/unified-config-file-watcher.ts +15 -2
- package/src/{agents → extensions/config}/user-instruction-config-loader.test.ts +90 -2
- package/src/{agents → extensions/config}/user-instruction-config-loader.ts +126 -12
- package/src/extensions/context/agentic-compaction.ts +119 -0
- package/src/extensions/context/basic-compaction.ts +275 -0
- package/src/extensions/context/compaction-shared.ts +458 -0
- package/src/extensions/context/compaction.test.ts +477 -0
- package/src/extensions/context/compaction.ts +203 -0
- package/src/extensions/index.ts +12 -0
- package/src/extensions/mcp/client.ts +420 -0
- package/src/{mcp → extensions/mcp}/index.ts +16 -0
- package/src/{mcp → extensions/mcp}/manager.test.ts +1 -2
- package/src/{mcp → extensions/mcp}/manager.ts +3 -5
- package/src/extensions/mcp/name-transform.ts +33 -0
- package/src/extensions/mcp/policies.ts +47 -0
- package/src/extensions/mcp/tools.ts +47 -0
- package/src/{mcp → extensions/mcp}/types.ts +35 -7
- package/src/{agents → extensions/plugin}/plugin-config-loader.test.ts +18 -13
- package/src/{agents → extensions/plugin}/plugin-config-loader.ts +1 -1
- package/src/{agents → extensions/plugin}/plugin-loader.test.ts +41 -4
- package/src/extensions/plugin/plugin-loader.ts +106 -0
- package/src/extensions/plugin/plugin-module-import.ts +278 -0
- package/src/{agents → extensions/plugin}/plugin-sandbox-bootstrap.ts +30 -92
- package/src/{agents → extensions/plugin}/plugin-sandbox.test.ts +60 -3
- package/src/{agents → extensions/plugin}/plugin-sandbox.ts +146 -56
- package/src/hooks/index.ts +25 -0
- package/src/hooks/persistent.ts +661 -0
- package/src/hooks/subprocess-runner.ts +196 -0
- package/src/hooks/subprocess.ts +669 -0
- package/src/index.ts +200 -118
- package/src/prompt/default-system.ts +21 -0
- package/src/providers/local-provider-registry.ts +1 -1
- package/src/providers/local-provider-service.test.ts +23 -2
- package/src/providers/local-provider-service.ts +2 -2
- package/src/runtime/checkpoint-hooks.test.ts +167 -0
- package/src/runtime/checkpoint-hooks.ts +186 -0
- package/src/runtime/hook-file-hooks.test.ts +40 -1
- package/src/runtime/hook-file-hooks.ts +35 -16
- package/src/runtime/index.ts +4 -19
- package/src/runtime/rules.ts +4 -1
- package/src/runtime/runtime-builder.team-persistence.test.ts +3 -6
- package/src/runtime/runtime-builder.test.ts +266 -160
- package/src/runtime/runtime-builder.ts +120 -47
- package/src/runtime/runtime-parity.test.ts +22 -22
- package/src/runtime/session-runtime.ts +36 -6
- package/src/runtime/{sandbox/subprocess-sandbox.ts → subprocess-sandbox.ts} +24 -3
- package/src/runtime/team-runtime-registry.ts +1 -4
- package/src/runtime/tool-approval.ts +1 -1
- package/src/session/default-session-manager.e2e.test.ts +2 -2
- package/src/session/default-session-manager.test.ts +553 -9
- package/src/session/default-session-manager.ts +140 -46
- package/src/session/file-session-service.ts +3 -3
- package/src/session/index.ts +6 -6
- package/src/session/persistence-service.test.ts +212 -0
- package/src/session/{unified-session-persistence-service.ts → persistence-service.ts} +106 -172
- package/src/session/rpc-session-service.ts +3 -3
- package/src/session/runtime-oauth-token-manager.ts +1 -1
- package/src/session/session-agent-events.ts +1 -1
- package/src/session/session-artifacts.ts +32 -4
- package/src/session/session-config-builder.ts +22 -9
- package/src/session/session-graph.ts +1 -1
- package/src/session/session-host.ts +19 -11
- package/src/session/session-manager.ts +11 -6
- package/src/session/session-service.team-persistence.test.ts +1 -1
- package/src/session/session-service.ts +6 -9
- package/src/session/session-team-coordination.ts +7 -3
- package/src/session/session-telemetry.ts +1 -1
- package/src/session/utils/helpers.test.ts +160 -0
- package/src/session/utils/helpers.ts +289 -42
- package/src/session/utils/types.ts +47 -7
- package/src/session/workspace-manager.ts +5 -3
- package/src/session/workspace-manifest.ts +3 -49
- package/src/storage/file-team-store.ts +2 -5
- package/src/storage/provider-settings-legacy-migration.ts +2 -2
- package/src/storage/provider-settings-manager.test.ts +1 -1
- package/src/storage/sqlite-team-store.ts +212 -125
- package/src/storage/team-store.ts +1 -5
- package/src/team/delegated-agent.ts +131 -0
- package/src/team/index.ts +1 -0
- package/src/team/multi-agent.lifecycle.test.ts +201 -0
- package/src/team/multi-agent.ts +1666 -0
- package/src/team/projections.ts +2 -4
- package/src/team/runtime.ts +54 -0
- package/src/team/spawn-agent-tool.test.ts +387 -0
- package/src/team/spawn-agent-tool.ts +207 -0
- package/src/team/subagent-prompts.ts +41 -0
- package/src/team/team-tools.test.ts +802 -0
- package/src/team/team-tools.ts +792 -0
- package/src/telemetry/OpenTelemetryProvider.test.ts +25 -3
- package/src/telemetry/OpenTelemetryProvider.ts +108 -18
- package/src/telemetry/TelemetryLoggerSink.test.ts +42 -0
- package/src/telemetry/{LoggerTelemetryAdapter.ts → TelemetryLoggerSink.ts} +21 -14
- package/src/telemetry/TelemetryService.test.ts +7 -7
- package/src/telemetry/TelemetryService.ts +2 -4
- package/src/tools/definitions.test.ts +76 -0
- package/src/tools/definitions.ts +41 -2
- package/src/tools/executors/apply-patch.ts +1 -1
- package/src/tools/executors/editor.ts +1 -1
- package/src/tools/executors/file-read.ts +1 -1
- package/src/tools/executors/search.ts +1 -1
- package/src/tools/executors/web-fetch.ts +1 -1
- package/src/tools/index.ts +6 -1
- package/src/tools/model-tool-routing.ts +2 -0
- package/src/tools/presets.test.ts +8 -0
- package/src/tools/presets.ts +40 -2
- package/src/tools/schemas.ts +19 -0
- package/src/tools/types.ts +31 -2
- package/src/types/config.ts +61 -7
- package/src/types/events.ts +1 -1
- package/src/types/index.ts +0 -1
- package/src/types/provider-settings.ts +1 -1
- package/src/types/storage.ts +2 -5
- package/src/types.ts +32 -44
- package/dist/agents/agent-config-loader.d.ts.map +0 -1
- package/dist/agents/agent-config-parser.d.ts.map +0 -1
- package/dist/agents/hooks-config-loader.d.ts.map +0 -1
- package/dist/agents/index.d.ts.map +0 -1
- package/dist/agents/plugin-config-loader.d.ts.map +0 -1
- package/dist/agents/plugin-loader.d.ts.map +0 -1
- package/dist/agents/plugin-sandbox-bootstrap.js +0 -446
- package/dist/agents/plugin-sandbox.d.ts.map +0 -1
- package/dist/agents/unified-config-file-watcher.d.ts.map +0 -1
- package/dist/agents/user-instruction-config-loader.d.ts.map +0 -1
- package/dist/mcp/config-loader.d.ts.map +0 -1
- package/dist/mcp/index.d.ts +0 -5
- package/dist/mcp/index.d.ts.map +0 -1
- package/dist/mcp/manager.d.ts.map +0 -1
- package/dist/mcp/types.d.ts.map +0 -1
- package/dist/runtime/commands.d.ts.map +0 -1
- package/dist/runtime/sandbox/subprocess-sandbox.d.ts.map +0 -1
- package/dist/runtime/skills.d.ts +0 -14
- package/dist/runtime/skills.d.ts.map +0 -1
- package/dist/runtime/workflows.d.ts +0 -14
- package/dist/runtime/workflows.d.ts.map +0 -1
- package/dist/session/unified-session-persistence-service.d.ts.map +0 -1
- package/dist/telemetry/LoggerTelemetryAdapter.d.ts.map +0 -1
- package/dist/types/workspace.d.ts +0 -8
- package/dist/types/workspace.d.ts.map +0 -1
- package/src/agents/plugin-loader.ts +0 -175
- package/src/runtime/skills.ts +0 -44
- package/src/runtime/workflows.test.ts +0 -119
- package/src/runtime/workflows.ts +0 -45
- package/src/session/unified-session-persistence-service.test.ts +0 -85
- package/src/telemetry/LoggerTelemetryAdapter.test.ts +0 -42
- package/src/types/workspace.ts +0 -7
- /package/dist/{agents → extensions/config}/agent-config-loader.d.ts +0 -0
- /package/dist/{agents → extensions/config}/unified-config-file-watcher.d.ts +0 -0
- /package/dist/{agents → extensions/config}/user-instruction-config-loader.d.ts +0 -0
- /package/dist/{mcp → extensions/mcp}/config-loader.d.ts +0 -0
- /package/dist/runtime/{sandbox/subprocess-sandbox.d.ts → subprocess-sandbox.d.ts} +0 -0
- /package/src/{agents → extensions/config}/agent-config-loader.ts +0 -0
- /package/src/{agents → extensions/config}/hooks-config-loader.test.ts +0 -0
- /package/src/{agents → extensions/config}/unified-config-file-watcher.test.ts +0 -0
- /package/src/{mcp → extensions/mcp}/config-loader.test.ts +0 -0
- /package/src/{mcp → extensions/mcp}/config-loader.ts +0 -0
package/src/auth/oca.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
captureAuthSucceeded,
|
|
8
8
|
identifyAccount,
|
|
9
9
|
} from "../telemetry/core-events";
|
|
10
|
+
import { BoundedTtlCache } from "./bounded-ttl-cache";
|
|
10
11
|
import { startLocalOAuthServer } from "./server";
|
|
11
12
|
import type {
|
|
12
13
|
OAuthCredentials,
|
|
@@ -113,7 +114,14 @@ const OCA_CONFIG_DEFAULTS: OcaOAuthConfig = {
|
|
|
113
114
|
};
|
|
114
115
|
|
|
115
116
|
const OCA_FLOW_STATE = new Map<string, OcaAuthFlowState>();
|
|
116
|
-
|
|
117
|
+
/** OpenID discovery documents change rarely; bound memory in long-lived processes. */
|
|
118
|
+
const DISCOVERY_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
119
|
+
const DISCOVERY_ERROR_FALLBACK_TTL_MS = 5 * 60 * 1000;
|
|
120
|
+
const DISCOVERY_CACHE_MAX_ENTRIES = 32;
|
|
121
|
+
const discoveryEndpointCache = new BoundedTtlCache(
|
|
122
|
+
DISCOVERY_CACHE_TTL_MS,
|
|
123
|
+
DISCOVERY_CACHE_MAX_ENTRIES,
|
|
124
|
+
);
|
|
117
125
|
|
|
118
126
|
function resolveMode(mode?: OcaMode | (() => OcaMode)): OcaMode {
|
|
119
127
|
if (typeof mode === "function") {
|
|
@@ -219,7 +227,7 @@ async function discoverTokenEndpoint(
|
|
|
219
227
|
requestTimeoutMs: number,
|
|
220
228
|
): Promise<string> {
|
|
221
229
|
const normalizedIdcsUrl = normalizeBaseUrl(idcsUrl);
|
|
222
|
-
const cached =
|
|
230
|
+
const cached = discoveryEndpointCache.get(normalizedIdcsUrl);
|
|
223
231
|
if (cached) {
|
|
224
232
|
return cached;
|
|
225
233
|
}
|
|
@@ -232,14 +240,19 @@ async function discoverTokenEndpoint(
|
|
|
232
240
|
|
|
233
241
|
if (!response.ok) {
|
|
234
242
|
const fallback = `${normalizedIdcsUrl}/oauth2/v1/token`;
|
|
235
|
-
|
|
243
|
+
discoveryEndpointCache.set(
|
|
244
|
+
normalizedIdcsUrl,
|
|
245
|
+
fallback,
|
|
246
|
+
Date.now(),
|
|
247
|
+
DISCOVERY_ERROR_FALLBACK_TTL_MS,
|
|
248
|
+
);
|
|
236
249
|
return fallback;
|
|
237
250
|
}
|
|
238
251
|
|
|
239
252
|
const discovery = (await response.json()) as OcaDiscoveryDocument;
|
|
240
253
|
const endpoint =
|
|
241
254
|
discovery.token_endpoint || `${normalizedIdcsUrl}/oauth2/v1/token`;
|
|
242
|
-
|
|
255
|
+
discoveryEndpointCache.set(normalizedIdcsUrl, endpoint);
|
|
243
256
|
return endpoint;
|
|
244
257
|
}
|
|
245
258
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import type { Tool, ToolContext } from "@clinebot/
|
|
4
|
+
import type { Tool, ToolContext } from "@clinebot/shared";
|
|
5
5
|
import { afterEach, describe, expect, it } from "vitest";
|
|
6
6
|
import {
|
|
7
7
|
AGENT_CONFIG_DIRECTORY_NAME,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { AgentConfig, Tool } from "@clinebot/
|
|
1
|
+
import type { AgentConfig, Tool } from "@clinebot/shared";
|
|
2
2
|
import YAML from "yaml";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import { ALL_DEFAULT_TOOL_NAMES, type DefaultToolName } from "
|
|
4
|
+
import { ALL_DEFAULT_TOOL_NAMES, type DefaultToolName } from "../../tools";
|
|
5
5
|
|
|
6
6
|
const AgentConfigFrontmatterSchema = z.object({
|
|
7
7
|
name: z.string().trim().min(1),
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { existsSync, readdirSync } from "node:fs";
|
|
2
2
|
import { basename, extname, join } from "node:path";
|
|
3
|
-
import type { HookEventName } from "@clinebot/agents";
|
|
4
3
|
import {
|
|
5
4
|
HOOKS_CONFIG_DIRECTORY_NAME,
|
|
6
5
|
resolveDocumentsHooksDirectoryPath,
|
|
7
6
|
resolveHooksConfigSearchPaths as resolveHooksConfigSearchPathsFromShared,
|
|
8
7
|
} from "@clinebot/shared/storage";
|
|
8
|
+
import type { HookEventName } from "../../hooks";
|
|
9
9
|
|
|
10
10
|
export { HOOKS_CONFIG_DIRECTORY_NAME, resolveDocumentsHooksDirectoryPath };
|
|
11
11
|
|
|
@@ -30,18 +30,14 @@ export {
|
|
|
30
30
|
resolveHooksConfigSearchPaths,
|
|
31
31
|
toHookConfigFileName,
|
|
32
32
|
} from "./hooks-config-loader";
|
|
33
|
-
export type {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
resolveAndLoadAgentPlugins,
|
|
38
|
-
resolvePluginConfigSearchPaths,
|
|
39
|
-
} from "./plugin-config-loader";
|
|
40
|
-
export type { LoadAgentPluginFromPathOptions } from "./plugin-loader";
|
|
33
|
+
export type {
|
|
34
|
+
AvailableRuntimeCommand,
|
|
35
|
+
RuntimeCommandKind,
|
|
36
|
+
} from "./runtime-commands";
|
|
41
37
|
export {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
} from "./
|
|
38
|
+
listAvailableRuntimeCommandsFromWatcher,
|
|
39
|
+
resolveRuntimeSlashCommandFromWatcher,
|
|
40
|
+
} from "./runtime-commands";
|
|
45
41
|
export type {
|
|
46
42
|
UnifiedConfigDefinition,
|
|
47
43
|
UnifiedConfigFileCandidate,
|
|
@@ -2,11 +2,11 @@ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
-
import { createUserInstructionConfigWatcher } from "../agents";
|
|
6
5
|
import {
|
|
7
6
|
listAvailableRuntimeCommandsFromWatcher,
|
|
8
7
|
resolveRuntimeSlashCommandFromWatcher,
|
|
9
|
-
} from "./commands";
|
|
8
|
+
} from "./runtime-commands";
|
|
9
|
+
import { createUserInstructionConfigWatcher } from "./user-instruction-config-loader";
|
|
10
10
|
|
|
11
11
|
describe("runtime command registry", () => {
|
|
12
12
|
const tempRoots: string[] = [];
|
|
@@ -61,7 +61,7 @@ Run the release workflow.`,
|
|
|
61
61
|
}
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
it("expands
|
|
64
|
+
it("expands slash commands with workflow precedence and ignores disabled entries", async () => {
|
|
65
65
|
const tempRoot = await mkdtemp(join(tmpdir(), "core-runtime-commands-"));
|
|
66
66
|
tempRoots.push(tempRoot);
|
|
67
67
|
const skillDir = join(tempRoot, "skills", "ship");
|
|
@@ -76,6 +76,14 @@ name: ship
|
|
|
76
76
|
---
|
|
77
77
|
Run the ship workflow.`,
|
|
78
78
|
);
|
|
79
|
+
await writeFile(
|
|
80
|
+
join(workflowsDir, "disabled.md"),
|
|
81
|
+
`---
|
|
82
|
+
name: disabled
|
|
83
|
+
disabled: true
|
|
84
|
+
---
|
|
85
|
+
Do not run this workflow.`,
|
|
86
|
+
);
|
|
79
87
|
|
|
80
88
|
const watcher = createUserInstructionConfigWatcher({
|
|
81
89
|
skills: { directories: [join(tempRoot, "skills")] },
|
|
@@ -91,6 +99,15 @@ Run the ship workflow.`,
|
|
|
91
99
|
expect(resolveRuntimeSlashCommandFromWatcher("/ship now", watcher)).toBe(
|
|
92
100
|
"Run the ship workflow. now",
|
|
93
101
|
);
|
|
102
|
+
expect(resolveRuntimeSlashCommandFromWatcher("/disabled", watcher)).toBe(
|
|
103
|
+
"/disabled",
|
|
104
|
+
);
|
|
105
|
+
expect(resolveRuntimeSlashCommandFromWatcher("/missing", watcher)).toBe(
|
|
106
|
+
"/missing",
|
|
107
|
+
);
|
|
108
|
+
expect(
|
|
109
|
+
resolveRuntimeSlashCommandFromWatcher("please run /ship", watcher),
|
|
110
|
+
).toBe("please run /ship");
|
|
94
111
|
} finally {
|
|
95
112
|
watcher.stop();
|
|
96
113
|
}
|
|
@@ -2,7 +2,7 @@ import type {
|
|
|
2
2
|
SkillConfig,
|
|
3
3
|
UserInstructionConfigWatcher,
|
|
4
4
|
WorkflowConfig,
|
|
5
|
-
} from "
|
|
5
|
+
} from "./user-instruction-config-loader";
|
|
6
6
|
|
|
7
7
|
export type RuntimeCommandKind = "skill" | "workflow";
|
|
8
8
|
|
|
@@ -74,10 +74,3 @@ export function resolveRuntimeSlashCommandFromWatcher(
|
|
|
74
74
|
);
|
|
75
75
|
return matched ? `${matched.instructions}${remainder}` : input;
|
|
76
76
|
}
|
|
77
|
-
|
|
78
|
-
export function listAvailableRuntimeCommandsForKindFromWatcher(
|
|
79
|
-
watcher: UserInstructionConfigWatcher,
|
|
80
|
-
kind: RuntimeCommandKind,
|
|
81
|
-
): AvailableRuntimeCommand[] {
|
|
82
|
-
return listCommandsForKind(watcher, kind);
|
|
83
|
-
}
|
|
@@ -84,6 +84,13 @@ function isMissingDirectoryError(error: unknown): boolean {
|
|
|
84
84
|
return isErrnoException(error) && error.code === "ENOENT";
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
function isInaccessibleDirectoryError(error: unknown): boolean {
|
|
88
|
+
return (
|
|
89
|
+
isErrnoException(error) &&
|
|
90
|
+
(error.code === "EACCES" || error.code === "EPERM")
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
87
94
|
export class UnifiedConfigFileWatcher<
|
|
88
95
|
TType extends string = string,
|
|
89
96
|
TItem = unknown,
|
|
@@ -289,7 +296,10 @@ export class UnifiedConfigFileWatcher<
|
|
|
289
296
|
}
|
|
290
297
|
});
|
|
291
298
|
} catch (error) {
|
|
292
|
-
if (
|
|
299
|
+
if (
|
|
300
|
+
!isMissingDirectoryError(error) &&
|
|
301
|
+
!isInaccessibleDirectoryError(error)
|
|
302
|
+
) {
|
|
293
303
|
const types = desiredTypesByDirectory.get(directoryPath);
|
|
294
304
|
if (!types) {
|
|
295
305
|
continue;
|
|
@@ -474,7 +484,10 @@ export class UnifiedConfigFileWatcher<
|
|
|
474
484
|
}))
|
|
475
485
|
.sort((a, b) => a.fileName.localeCompare(b.fileName));
|
|
476
486
|
} catch (error) {
|
|
477
|
-
if (
|
|
487
|
+
if (
|
|
488
|
+
isMissingDirectoryError(error) ||
|
|
489
|
+
isInaccessibleDirectoryError(error)
|
|
490
|
+
) {
|
|
478
491
|
return [];
|
|
479
492
|
}
|
|
480
493
|
throw error;
|
|
@@ -3,7 +3,10 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { afterEach, describe, expect, it } from "vitest";
|
|
5
5
|
import {
|
|
6
|
+
createRulesConfigDefinition,
|
|
7
|
+
createSkillsConfigDefinition,
|
|
6
8
|
createUserInstructionConfigWatcher,
|
|
9
|
+
createWorkflowsConfigDefinition,
|
|
7
10
|
parseRuleConfigFromMarkdown,
|
|
8
11
|
parseSkillConfigFromMarkdown,
|
|
9
12
|
parseWorkflowConfigFromMarkdown,
|
|
@@ -48,18 +51,34 @@ describe("user instruction config loader", () => {
|
|
|
48
51
|
expect.arrayContaining([
|
|
49
52
|
join(workspacePath, ".clinerules", "skills"),
|
|
50
53
|
join(workspacePath, ".cline", "skills"),
|
|
51
|
-
join(workspacePath, ".claude", "skills"),
|
|
52
54
|
join(workspacePath, ".agents", "skills"),
|
|
53
55
|
]),
|
|
54
56
|
);
|
|
55
57
|
expect(resolveRulesConfigSearchPaths(workspacePath)).toEqual(
|
|
56
|
-
expect.arrayContaining([
|
|
58
|
+
expect.arrayContaining([
|
|
59
|
+
join(workspacePath, "AGENTS.md"),
|
|
60
|
+
join(workspacePath, ".clinerules"),
|
|
61
|
+
join(workspacePath, ".cline", "rules"),
|
|
62
|
+
]),
|
|
57
63
|
);
|
|
58
64
|
expect(resolveWorkflowsConfigSearchPaths(workspacePath)).toEqual(
|
|
59
65
|
expect.arrayContaining([join(workspacePath, ".clinerules", "workflows")]),
|
|
60
66
|
);
|
|
61
67
|
});
|
|
62
68
|
|
|
69
|
+
it("discovers managed plugin instruction roots from workspace .cline manifests", () => {
|
|
70
|
+
const workspacePath = "/repo/demo";
|
|
71
|
+
expect(
|
|
72
|
+
createSkillsConfigDefinition({ workspacePath }).directories,
|
|
73
|
+
).toContain(join(workspacePath, ".cline"));
|
|
74
|
+
expect(
|
|
75
|
+
createRulesConfigDefinition({ workspacePath }).directories,
|
|
76
|
+
).toContain(join(workspacePath, ".cline"));
|
|
77
|
+
expect(
|
|
78
|
+
createWorkflowsConfigDefinition({ workspacePath }).directories,
|
|
79
|
+
).toContain(join(workspacePath, ".cline"));
|
|
80
|
+
});
|
|
81
|
+
|
|
63
82
|
it("parses markdown frontmatter for skill, rule, and workflow configs", () => {
|
|
64
83
|
const skill = parseSkillConfigFromMarkdown(
|
|
65
84
|
`---
|
|
@@ -155,4 +174,73 @@ Escalation runbook`,
|
|
|
155
174
|
watcher.stop();
|
|
156
175
|
}
|
|
157
176
|
});
|
|
177
|
+
|
|
178
|
+
it("loads enterprise-style managed rules, workflows, and skills through the default workspace watcher", async () => {
|
|
179
|
+
const tempRoot = await mkdtemp(
|
|
180
|
+
join(tmpdir(), "core-user-instructions-managed-"),
|
|
181
|
+
);
|
|
182
|
+
tempRoots.push(tempRoot);
|
|
183
|
+
|
|
184
|
+
const pluginRoot = join(tempRoot, ".cline", "enterprise");
|
|
185
|
+
await mkdir(join(pluginRoot, "workflows"), { recursive: true });
|
|
186
|
+
await mkdir(join(pluginRoot, "skills", "security-review"), {
|
|
187
|
+
recursive: true,
|
|
188
|
+
});
|
|
189
|
+
await writeFile(
|
|
190
|
+
join(pluginRoot, "managed.json"),
|
|
191
|
+
JSON.stringify({ source: "enterprise", version: "1", files: [] }),
|
|
192
|
+
);
|
|
193
|
+
await writeFile(
|
|
194
|
+
join(pluginRoot, "rules.md"),
|
|
195
|
+
`---
|
|
196
|
+
name: enterprise-policy
|
|
197
|
+
---
|
|
198
|
+
Follow enterprise policy.`,
|
|
199
|
+
);
|
|
200
|
+
await writeFile(
|
|
201
|
+
join(pluginRoot, "workflows", "triage.md"),
|
|
202
|
+
`---
|
|
203
|
+
name: triage
|
|
204
|
+
---
|
|
205
|
+
Follow the triage workflow.`,
|
|
206
|
+
);
|
|
207
|
+
await writeFile(
|
|
208
|
+
join(pluginRoot, "skills", "security-review", "SKILL.md"),
|
|
209
|
+
`---
|
|
210
|
+
name: security-review
|
|
211
|
+
---
|
|
212
|
+
Use the security review checklist.`,
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
const watcher = createUserInstructionConfigWatcher({
|
|
216
|
+
skills: { workspacePath: tempRoot },
|
|
217
|
+
rules: { workspacePath: tempRoot },
|
|
218
|
+
workflows: { workspacePath: tempRoot },
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
await watcher.start();
|
|
223
|
+
const rules = watcher.getSnapshot("rule");
|
|
224
|
+
const workflows = watcher.getSnapshot("workflow");
|
|
225
|
+
const skills = watcher.getSnapshot("skill");
|
|
226
|
+
|
|
227
|
+
expect(
|
|
228
|
+
[...rules.values()].some((rule) =>
|
|
229
|
+
rule.item.instructions.includes("enterprise policy"),
|
|
230
|
+
),
|
|
231
|
+
).toBe(true);
|
|
232
|
+
expect(
|
|
233
|
+
[...workflows.values()].some((workflow) =>
|
|
234
|
+
workflow.item.instructions.includes("triage workflow"),
|
|
235
|
+
),
|
|
236
|
+
).toBe(true);
|
|
237
|
+
expect(
|
|
238
|
+
[...skills.values()].some((skill) =>
|
|
239
|
+
skill.item.instructions.includes("security review checklist"),
|
|
240
|
+
),
|
|
241
|
+
).toBe(true);
|
|
242
|
+
} finally {
|
|
243
|
+
watcher.stop();
|
|
244
|
+
}
|
|
245
|
+
});
|
|
158
246
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readdir, stat } from "node:fs/promises";
|
|
1
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
2
2
|
import { basename, dirname, extname, join } from "node:path";
|
|
3
3
|
import {
|
|
4
4
|
RULES_CONFIG_DIRECTORY_NAME,
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
} from "./unified-config-file-watcher";
|
|
20
20
|
|
|
21
21
|
const SKILL_FILE_NAME = "SKILL.md";
|
|
22
|
+
const MANAGED_PLUGIN_MANIFEST_FILE_NAME = "managed.json";
|
|
22
23
|
|
|
23
24
|
const MARKDOWN_EXTENSIONS = new Set([".md", ".markdown", ".txt"]);
|
|
24
25
|
|
|
@@ -97,10 +98,57 @@ function normalizeName(name: string): string {
|
|
|
97
98
|
return name.trim().toLowerCase();
|
|
98
99
|
}
|
|
99
100
|
|
|
101
|
+
function isIgnorableDirectoryError(error: unknown): boolean {
|
|
102
|
+
const nodeError = error as NodeJS.ErrnoException;
|
|
103
|
+
return (
|
|
104
|
+
nodeError?.code === "ENOENT" ||
|
|
105
|
+
nodeError?.code === "EACCES" ||
|
|
106
|
+
nodeError?.code === "EPERM"
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
100
110
|
function isMarkdownFile(fileName: string): boolean {
|
|
101
111
|
return MARKDOWN_EXTENSIONS.has(extname(fileName).toLowerCase());
|
|
102
112
|
}
|
|
103
113
|
|
|
114
|
+
async function discoverManagedPluginRoots(
|
|
115
|
+
clineDirectoryPath: string,
|
|
116
|
+
): Promise<string[]> {
|
|
117
|
+
try {
|
|
118
|
+
const entries = await readdir(clineDirectoryPath, { withFileTypes: true });
|
|
119
|
+
const pluginRoots: string[] = [];
|
|
120
|
+
for (const entry of entries) {
|
|
121
|
+
if (!entry.isDirectory()) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const pluginRoot = join(clineDirectoryPath, entry.name);
|
|
125
|
+
const manifestPath = join(pluginRoot, MANAGED_PLUGIN_MANIFEST_FILE_NAME);
|
|
126
|
+
try {
|
|
127
|
+
const content = await readFile(manifestPath, "utf8");
|
|
128
|
+
const parsed = JSON.parse(content) as unknown;
|
|
129
|
+
if (parsed && typeof parsed === "object") {
|
|
130
|
+
pluginRoots.push(pluginRoot);
|
|
131
|
+
}
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (isIgnorableDirectoryError(error)) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const nodeError = error as NodeJS.ErrnoException;
|
|
137
|
+
if (nodeError?.name === "SyntaxError") {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return pluginRoots.sort((a, b) => a.localeCompare(b));
|
|
144
|
+
} catch (error) {
|
|
145
|
+
if (isIgnorableDirectoryError(error)) {
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
104
152
|
function parseMarkdownFrontmatter(
|
|
105
153
|
content: string,
|
|
106
154
|
): ParseMarkdownFrontmatterResult {
|
|
@@ -267,6 +315,16 @@ export function resolveWorkflowsConfigSearchPaths(
|
|
|
267
315
|
async function discoverSkillFiles(
|
|
268
316
|
directoryPath: string,
|
|
269
317
|
): Promise<ReadonlyArray<UnifiedConfigFileCandidate>> {
|
|
318
|
+
if (basename(directoryPath) === ".cline") {
|
|
319
|
+
const pluginRoots = await discoverManagedPluginRoots(directoryPath);
|
|
320
|
+
const nestedCandidates = await Promise.all(
|
|
321
|
+
pluginRoots.map((pluginRoot) =>
|
|
322
|
+
discoverSkillFiles(join(pluginRoot, SKILLS_CONFIG_DIRECTORY_NAME)),
|
|
323
|
+
),
|
|
324
|
+
);
|
|
325
|
+
return nestedCandidates.flat();
|
|
326
|
+
}
|
|
327
|
+
|
|
270
328
|
try {
|
|
271
329
|
const entries = await readdir(directoryPath, { withFileTypes: true });
|
|
272
330
|
const candidates: UnifiedConfigFileCandidate[] = [];
|
|
@@ -289,8 +347,7 @@ async function discoverSkillFiles(
|
|
|
289
347
|
}
|
|
290
348
|
return candidates;
|
|
291
349
|
} catch (error) {
|
|
292
|
-
|
|
293
|
-
if (nodeError.code === "ENOENT") {
|
|
350
|
+
if (isIgnorableDirectoryError(error)) {
|
|
294
351
|
return [];
|
|
295
352
|
}
|
|
296
353
|
throw error;
|
|
@@ -300,6 +357,16 @@ async function discoverSkillFiles(
|
|
|
300
357
|
async function discoverRulesLikeFiles(
|
|
301
358
|
directoryPath: string,
|
|
302
359
|
): Promise<ReadonlyArray<UnifiedConfigFileCandidate>> {
|
|
360
|
+
if (basename(directoryPath) === ".cline") {
|
|
361
|
+
const pluginRoots = await discoverManagedPluginRoots(directoryPath);
|
|
362
|
+
const nestedCandidates = await Promise.all(
|
|
363
|
+
pluginRoots.map((pluginRoot) =>
|
|
364
|
+
discoverRulesLikeFiles(join(pluginRoot, "rules.md")),
|
|
365
|
+
),
|
|
366
|
+
);
|
|
367
|
+
return nestedCandidates.flat();
|
|
368
|
+
}
|
|
369
|
+
|
|
303
370
|
try {
|
|
304
371
|
const entryStat = await stat(directoryPath);
|
|
305
372
|
if (entryStat.isFile()) {
|
|
@@ -312,40 +379,81 @@ async function discoverRulesLikeFiles(
|
|
|
312
379
|
];
|
|
313
380
|
}
|
|
314
381
|
} catch (error) {
|
|
315
|
-
|
|
316
|
-
if (nodeError.code !== "ENOENT") {
|
|
382
|
+
if (!isIgnorableDirectoryError(error)) {
|
|
317
383
|
throw error;
|
|
318
384
|
}
|
|
319
385
|
}
|
|
320
386
|
|
|
321
387
|
try {
|
|
322
388
|
const entries = await readdir(directoryPath, { withFileTypes: true });
|
|
323
|
-
|
|
389
|
+
const candidates = entries
|
|
324
390
|
.filter((entry) => entry.isFile() && isMarkdownFile(entry.name))
|
|
325
391
|
.map((entry) => ({
|
|
326
392
|
directoryPath,
|
|
327
393
|
fileName: entry.name,
|
|
328
394
|
filePath: join(directoryPath, entry.name),
|
|
329
395
|
}));
|
|
396
|
+
|
|
397
|
+
// Special case: if this is a workspace root directory, also check for AGENTS.md
|
|
398
|
+
const agentsPath = join(directoryPath, "AGENTS.md");
|
|
399
|
+
try {
|
|
400
|
+
const agentsStat = await stat(agentsPath);
|
|
401
|
+
if (agentsStat.isFile()) {
|
|
402
|
+
// Check if AGENTS.md is not already in the candidates
|
|
403
|
+
const alreadyIncluded = candidates.some(
|
|
404
|
+
(c) => c.fileName === "AGENTS.md",
|
|
405
|
+
);
|
|
406
|
+
if (!alreadyIncluded) {
|
|
407
|
+
candidates.push({
|
|
408
|
+
directoryPath,
|
|
409
|
+
fileName: "AGENTS.md",
|
|
410
|
+
filePath: agentsPath,
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
} catch {
|
|
415
|
+
// AGENTS.md doesn't exist or is not accessible, which is fine
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return candidates;
|
|
330
419
|
} catch (error) {
|
|
331
|
-
|
|
332
|
-
if (nodeError.code === "ENOENT") {
|
|
420
|
+
if (isIgnorableDirectoryError(error)) {
|
|
333
421
|
return [];
|
|
334
422
|
}
|
|
335
423
|
throw error;
|
|
336
424
|
}
|
|
337
425
|
}
|
|
338
426
|
|
|
427
|
+
async function discoverManagedWorkflowFiles(
|
|
428
|
+
directoryPath: string,
|
|
429
|
+
): Promise<ReadonlyArray<UnifiedConfigFileCandidate>> {
|
|
430
|
+
if (basename(directoryPath) === ".cline") {
|
|
431
|
+
const pluginRoots = await discoverManagedPluginRoots(directoryPath);
|
|
432
|
+
const nestedCandidates = await Promise.all(
|
|
433
|
+
pluginRoots.map((pluginRoot) =>
|
|
434
|
+
discoverRulesLikeFiles(
|
|
435
|
+
join(pluginRoot, WORKFLOWS_CONFIG_DIRECTORY_NAME),
|
|
436
|
+
),
|
|
437
|
+
),
|
|
438
|
+
);
|
|
439
|
+
return nestedCandidates.flat();
|
|
440
|
+
}
|
|
441
|
+
return discoverRulesLikeFiles(directoryPath);
|
|
442
|
+
}
|
|
443
|
+
|
|
339
444
|
export function createSkillsConfigDefinition(
|
|
340
445
|
options?: CreateSkillsConfigDefinitionOptions,
|
|
341
446
|
): UnifiedConfigDefinition<"skill", SkillConfig> {
|
|
342
447
|
const directories =
|
|
343
448
|
options?.directories ??
|
|
344
449
|
resolveSkillsConfigSearchPaths(options?.workspacePath);
|
|
450
|
+
const managedRoot = options?.workspacePath
|
|
451
|
+
? join(options.workspacePath, ".cline")
|
|
452
|
+
: undefined;
|
|
345
453
|
|
|
346
454
|
return {
|
|
347
455
|
type: "skill",
|
|
348
|
-
directories,
|
|
456
|
+
directories: managedRoot ? [...directories, managedRoot] : directories,
|
|
349
457
|
discoverFiles: discoverSkillFiles,
|
|
350
458
|
includeFile: (fileName) => fileName === SKILL_FILE_NAME,
|
|
351
459
|
parseFile: (context) =>
|
|
@@ -363,10 +471,13 @@ export function createRulesConfigDefinition(
|
|
|
363
471
|
const directories =
|
|
364
472
|
options?.directories ??
|
|
365
473
|
resolveRulesConfigSearchPaths(options?.workspacePath);
|
|
474
|
+
const managedRoot = options?.workspacePath
|
|
475
|
+
? join(options.workspacePath, ".cline")
|
|
476
|
+
: undefined;
|
|
366
477
|
|
|
367
478
|
return {
|
|
368
479
|
type: "rule",
|
|
369
|
-
directories,
|
|
480
|
+
directories: managedRoot ? [...directories, managedRoot] : directories,
|
|
370
481
|
discoverFiles: discoverRulesLikeFiles,
|
|
371
482
|
includeFile: (fileName, filePath) =>
|
|
372
483
|
fileName === ".clinerules" ||
|
|
@@ -387,11 +498,14 @@ export function createWorkflowsConfigDefinition(
|
|
|
387
498
|
const directories =
|
|
388
499
|
options?.directories ??
|
|
389
500
|
resolveWorkflowsConfigSearchPaths(options?.workspacePath);
|
|
501
|
+
const managedRoot = options?.workspacePath
|
|
502
|
+
? join(options.workspacePath, ".cline")
|
|
503
|
+
: undefined;
|
|
390
504
|
|
|
391
505
|
return {
|
|
392
506
|
type: "workflow",
|
|
393
|
-
directories,
|
|
394
|
-
discoverFiles:
|
|
507
|
+
directories: managedRoot ? [...directories, managedRoot] : directories,
|
|
508
|
+
discoverFiles: discoverManagedWorkflowFiles,
|
|
395
509
|
includeFile: (fileName) => isMarkdownFile(fileName),
|
|
396
510
|
parseFile: (context) =>
|
|
397
511
|
parseWorkflowConfigFromMarkdown(
|