@gajae-code/coding-agent 0.16.3 → 0.16.6
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 +113 -0
- package/dist/types/capability/types.d.ts +4 -0
- package/dist/types/cli/args.d.ts +2 -2
- package/dist/types/cli/customize-doctor.d.ts +22 -0
- package/dist/types/cli/root-flags.d.ts +4 -2
- package/dist/types/cli.d.ts +1 -1
- package/dist/types/commands/launch.d.ts +1 -1
- package/dist/types/config/autorouting-tier-map.d.ts +3 -0
- package/dist/types/config/file-lock.d.ts +31 -3
- package/dist/types/config/model-registry.d.ts +4 -0
- package/dist/types/config/model-resolver.d.ts +9 -0
- package/dist/types/config/settings-schema.d.ts +29 -1
- package/dist/types/coordinator-mcp/question-state.d.ts +7 -0
- package/dist/types/coordinator-mcp/server.d.ts +7 -0
- package/dist/types/discovery/claude-plugins.d.ts +3 -1
- package/dist/types/discovery/helpers.d.ts +35 -0
- package/dist/types/exec/bash-executor.d.ts +17 -1
- package/dist/types/exec/bash-shell-guardian.d.ts +15 -0
- package/dist/types/exec/bash-shell-runtime-entry.d.ts +2 -0
- package/dist/types/exec/bash-shell-signals.d.ts +2 -0
- package/dist/types/exec/bash-shell-supervisor-entry.d.ts +1 -0
- package/dist/types/exec/bash-shell-supervisor.d.ts +10 -0
- package/dist/types/exec/bash-shell-worker-entry.d.ts +2 -0
- package/dist/types/exec/bash-shell-worker-protocol.d.ts +63 -0
- package/dist/types/exec/bash-shell-worker.d.ts +1 -0
- package/dist/types/exec/isolated-shell.d.ts +19 -0
- package/dist/types/extensibility/extensions/function-hooks-internal.d.ts +9 -0
- package/dist/types/extensibility/extensions/function-hooks.d.ts +169 -0
- package/dist/types/extensibility/extensions/index.d.ts +1 -0
- package/dist/types/extensibility/extensions/runner.d.ts +46 -6
- package/dist/types/extensibility/extensions/types.d.ts +16 -0
- package/dist/types/extensibility/extensions/wrapper.d.ts +3 -1
- package/dist/types/extensibility/gjc-plugins/constrained-hooks.d.ts +35 -2
- package/dist/types/extensibility/gjc-plugins/mcp-policy.d.ts +16 -0
- package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -0
- package/dist/types/extensibility/gjc-plugins/types.d.ts +25 -0
- package/dist/types/extensibility/hooks/types.d.ts +4 -0
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +5 -2
- package/dist/types/extensibility/shared-events.d.ts +1 -1
- package/dist/types/extensibility/skill-management.d.ts +9 -4
- package/dist/types/extensibility/skills.d.ts +2 -0
- package/dist/types/gjc-runtime/empty-delete-gc.d.ts +4 -1
- package/dist/types/gjc-runtime/linux-proc.d.ts +2 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +14 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +41 -3
- package/dist/types/gjc-runtime/ultragoal-succession.d.ts +251 -0
- package/dist/types/modes/components/assistant-message.d.ts +1 -2
- package/dist/types/modes/components/bash-execution.d.ts +1 -0
- package/dist/types/modes/components/execution-shared.d.ts +1 -0
- package/dist/types/modes/components/settings-selector.d.ts +6 -1
- package/dist/types/modes/components/status-line/command.d.ts +35 -0
- package/dist/types/modes/components/status-line/index.d.ts +1 -0
- package/dist/types/modes/components/status-line/types.d.ts +5 -0
- package/dist/types/modes/components/tool-status-header.d.ts +14 -0
- package/dist/types/modes/controllers/event-controller.d.ts +6 -0
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/types.d.ts +7 -0
- package/dist/types/runtime-mcp/client.d.ts +9 -1
- package/dist/types/runtime-mcp/manager.d.ts +7 -1
- package/dist/types/runtime-mcp/pool.d.ts +22 -3
- package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
- package/dist/types/runtime-mcp/types.d.ts +22 -0
- package/dist/types/sdk/broker/ensure.d.ts +32 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +0 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +6 -0
- package/dist/types/sdk/broker/startup-failure.d.ts +4 -1
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +12 -0
- package/dist/types/sdk/bus/chat-effect-journal.d.ts +17 -2
- package/dist/types/sdk/bus/conversation-store.d.ts +11 -0
- package/dist/types/sdk/bus/lifecycle-commands.d.ts +8 -8
- package/dist/types/sdk/bus/slack-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/slack-live-provider.d.ts +6 -0
- package/dist/types/sdk/bus/slack-provider.d.ts +12 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +8 -0
- package/dist/types/sdk/client/client.d.ts +6 -0
- package/dist/types/sdk/host/host.d.ts +3 -1
- package/dist/types/sdk/host/session-runtime.d.ts +26 -1
- package/dist/types/sdk/lifecycle/service.d.ts +1 -0
- package/dist/types/sdk/router/session-router.d.ts +10 -2
- package/dist/types/sdk/session-api-key.d.ts +26 -0
- package/dist/types/sdk/session.d.ts +5 -1
- package/dist/types/sdk/transport/serve-cli.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +11 -0
- package/dist/types/session/fallback-chain-controller.d.ts +15 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +7 -0
- package/dist/types/session/messages.d.ts +1 -0
- package/dist/types/session/session-manager.d.ts +3 -1
- package/dist/types/setup/paseo/announce.d.ts +112 -0
- package/dist/types/setup/paseo/setup-deps.d.ts +2 -1
- package/dist/types/skill-state/canonical-skills.d.ts +4 -0
- package/dist/types/system-prompt.d.ts +10 -0
- package/dist/types/task/executor.d.ts +5 -1
- package/dist/types/tools/bash.d.ts +1 -0
- package/dist/types/tools/fetch.d.ts +7 -0
- package/dist/types/tools/github-cache.d.ts +2 -1
- package/dist/types/tools/index.d.ts +10 -0
- package/dist/types/tools/path-utils.d.ts +2 -0
- package/dist/types/tools/search.d.ts +6 -0
- package/package.json +9 -7
- package/scripts/capture-status-line-custom-editor-showcase.ts +151 -0
- package/scripts/generate-sdk-operation-inventory.ts +11 -0
- package/scripts/verify-status-line-custom-editor-showcase.ts +309 -0
- package/src/capability/index.ts +14 -2
- package/src/capability/types.ts +4 -0
- package/src/cli/args.ts +20 -9
- package/src/cli/customize-doctor.ts +155 -12
- package/src/cli/root-flags.ts +5 -3
- package/src/cli.ts +22 -0
- package/src/commands/sdk.ts +74 -31
- package/src/config/autorouting-tier-map.ts +1 -0
- package/src/config/file-lock-gc.ts +40 -2
- package/src/config/file-lock.ts +379 -31
- package/src/config/model-preset-registry.ts +120 -19
- package/src/config/model-profiles.ts +40 -0
- package/src/config/model-registry.ts +73 -23
- package/src/config/model-resolver.ts +48 -0
- package/src/config/settings-schema.ts +33 -1
- package/src/config/settings.ts +1 -0
- package/src/coordinator-mcp/question-state.ts +33 -2
- package/src/coordinator-mcp/server.ts +477 -101
- package/src/crash/sanitize.ts +1 -1
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/models/catalog.ts +11 -11
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/register.ts +13 -2
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +22 -0
- package/src/discovery/builtin.ts +52 -55
- package/src/discovery/claude-plugins.ts +12 -4
- package/src/discovery/helpers.ts +307 -34
- package/src/exec/bash-executor.ts +330 -50
- package/src/exec/bash-shell-guardian.ts +388 -0
- package/src/exec/bash-shell-runtime-entry.ts +5 -0
- package/src/exec/bash-shell-signals.ts +29 -0
- package/src/exec/bash-shell-supervisor-entry.ts +3 -0
- package/src/exec/bash-shell-supervisor.ts +359 -0
- package/src/exec/bash-shell-worker-entry.ts +5 -0
- package/src/exec/bash-shell-worker-protocol.ts +36 -0
- package/src/exec/bash-shell-worker.ts +116 -0
- package/src/exec/isolated-shell.ts +393 -0
- package/src/extensibility/extensions/function-hooks-internal.ts +73 -0
- package/src/extensibility/extensions/function-hooks.ts +959 -0
- package/src/extensibility/extensions/index.ts +22 -0
- package/src/extensibility/extensions/loader.ts +53 -2
- package/src/extensibility/extensions/runner.ts +895 -264
- package/src/extensibility/extensions/types.ts +42 -0
- package/src/extensibility/extensions/wrapper.ts +56 -15
- package/src/extensibility/gjc-plugins/compiler.ts +228 -60
- package/src/extensibility/gjc-plugins/constrained-hooks.ts +321 -23
- package/src/extensibility/gjc-plugins/installer.ts +13 -12
- package/src/extensibility/gjc-plugins/mcp-policy.ts +81 -52
- package/src/extensibility/gjc-plugins/paths.ts +13 -0
- package/src/extensibility/gjc-plugins/registry.ts +113 -1
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +758 -16
- package/src/extensibility/gjc-plugins/runtime-quarantine.ts +20 -2
- package/src/extensibility/gjc-plugins/schema.ts +121 -4
- package/src/extensibility/gjc-plugins/types.ts +25 -0
- package/src/extensibility/hooks/loader.ts +133 -16
- package/src/extensibility/hooks/types.ts +28 -0
- package/src/extensibility/runtime-skill-discovery.ts +149 -190
- package/src/extensibility/shared-events.ts +1 -1
- package/src/extensibility/skill-management.ts +200 -52
- package/src/extensibility/skills.ts +73 -25
- package/src/gjc-runtime/empty-delete-gc.ts +94 -4
- package/src/gjc-runtime/gc-runtime.ts +29 -0
- package/src/gjc-runtime/linux-proc.ts +14 -0
- package/src/gjc-runtime/repository-binding.ts +1 -1
- package/src/gjc-runtime/session-state-lock.ts +143 -10
- package/src/gjc-runtime/session-state-sidecar.ts +27 -11
- package/src/gjc-runtime/state-writer.ts +30 -29
- package/src/gjc-runtime/ultragoal-runtime.ts +189 -47
- package/src/gjc-runtime/ultragoal-succession.ts +1667 -0
- package/src/gjc-runtime/workflow-manifest.generated.json +52 -1
- package/src/gjc-runtime/workflow-manifest.ts +16 -0
- package/src/harness-control-plane/session-lease.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +12 -12
- package/src/lsp/config.ts +10 -3
- package/src/lsp/index.ts +1 -1
- package/src/lsp/path-trust.ts +69 -14
- package/src/main.ts +78 -35
- package/src/modes/DESIGN.md +54 -0
- package/src/modes/acp/acp-agent.ts +16 -3
- package/src/modes/components/assistant-message.ts +22 -9
- package/src/modes/components/bash-execution.ts +4 -1
- package/src/modes/components/execution-shared.ts +4 -1
- package/src/modes/components/model-selector.ts +166 -33
- package/src/modes/components/session-observer-overlay.ts +1 -1
- package/src/modes/components/settings-selector.ts +1075 -235
- package/src/modes/components/status-line/command.ts +190 -0
- package/src/modes/components/status-line/index.ts +1 -0
- package/src/modes/components/status-line/segments.ts +32 -5
- package/src/modes/components/status-line/types.ts +5 -0
- package/src/modes/components/tool-status-header.ts +396 -22
- package/src/modes/controllers/command-controller.ts +3 -0
- package/src/modes/controllers/event-controller.ts +151 -7
- package/src/modes/controllers/extension-ui-controller.ts +1 -0
- package/src/modes/controllers/input-controller.ts +6 -3
- package/src/modes/controllers/selector-controller.ts +21 -0
- package/src/modes/interactive-mode.ts +53 -6
- package/src/modes/print-mode.ts +5 -1
- package/src/modes/prompt-action-autocomplete.ts +54 -27
- package/src/modes/runtime-init.ts +2 -0
- package/src/modes/types.ts +17 -3
- package/src/modes/utils/ui-helpers.ts +2 -0
- package/src/prompts/system/system-prompt.md +8 -0
- package/src/prompts/tools/search.md +2 -0
- package/src/prompts/tools/subagent.md +1 -0
- package/src/runtime-mcp/client.ts +60 -17
- package/src/runtime-mcp/manager.ts +189 -14
- package/src/runtime-mcp/pool.test.ts +218 -0
- package/src/runtime-mcp/pool.ts +224 -23
- package/src/runtime-mcp/transports/stdio.ts +158 -24
- package/src/runtime-mcp/types.ts +24 -0
- package/src/sdk/broker/broker.ts +124 -32
- package/src/sdk/broker/ensure.ts +248 -41
- package/src/sdk/broker/lifecycle-ledger.ts +7 -17
- package/src/sdk/broker/lifecycle.ts +56 -6
- package/src/sdk/broker/startup-failure.ts +15 -6
- package/src/sdk/bus/chat-daemon-control.ts +3 -1
- package/src/sdk/bus/chat-daemon-runtime.ts +72 -6
- package/src/sdk/bus/chat-effect-journal.ts +132 -7
- package/src/sdk/bus/conversation-store.ts +29 -0
- package/src/sdk/bus/lifecycle-commands.ts +17 -11
- package/src/sdk/bus/slack-conversation.ts +1 -0
- package/src/sdk/bus/slack-daemon.ts +478 -49
- package/src/sdk/bus/slack-live-provider.ts +12 -0
- package/src/sdk/bus/slack-provider.ts +5 -0
- package/src/sdk/bus/telegram-daemon.ts +16 -2
- package/src/sdk/bus/topic-registry.ts +19 -0
- package/src/sdk/cli/master-cli.ts +1 -1
- package/src/sdk/cli/session-cli.ts +11 -8
- package/src/sdk/client/client.ts +66 -17
- package/src/sdk/host/host.ts +29 -9
- package/src/sdk/host/query/revision-store.ts +19 -13
- package/src/sdk/host/reverse-leases.ts +7 -4
- package/src/sdk/host/session-runtime.test.ts +52 -10
- package/src/sdk/host/session-runtime.ts +383 -44
- package/src/sdk/lifecycle/service.ts +4 -0
- package/src/sdk/protocol/operation-inventory.generated.json +77 -0
- package/src/sdk/router/session-router.ts +89 -38
- package/src/sdk/session-api-key.ts +94 -0
- package/src/sdk/session.ts +228 -55
- package/src/sdk/transport/relay.ts +35 -13
- package/src/sdk/transport/serve-cli.ts +3 -3
- package/src/session/agent-session.ts +240 -90
- package/src/session/contribution-prep.ts +214 -21
- package/src/session/fallback-chain-controller.ts +38 -0
- package/src/session/internal/managed-session-storage.ts +19 -5
- package/src/session/messages.ts +5 -0
- package/src/session/session-manager.ts +29 -5
- package/src/session-import/redact.ts +5 -1
- package/src/setup/paseo/announce.ts +456 -0
- package/src/setup/paseo/setup-deps.ts +15 -3
- package/src/skill-state/canonical-skills.ts +12 -0
- package/src/skills/skills.test.ts +41 -21
- package/src/slash-commands/builtin-registry.ts +1 -0
- package/src/system-prompt.ts +29 -3
- package/src/task/executor.ts +7 -1
- package/src/task/index.ts +21 -4
- package/src/tools/bash.ts +63 -19
- package/src/tools/cron.ts +1 -1
- package/src/tools/fetch.ts +29 -1
- package/src/tools/gh.ts +26 -3
- package/src/tools/github-cache.ts +68 -16
- package/src/tools/index.ts +10 -0
- package/src/tools/job.ts +21 -4
- package/src/tools/monitor.ts +8 -2
- package/src/tools/path-utils.ts +7 -0
- package/src/tools/read.ts +14 -2
- package/src/tools/render-utils.ts +1 -3
- package/src/tools/resource-gc.ts +28 -8
- package/src/tools/search.ts +116 -58
- package/src/tools/skill-discovery.ts +5 -0
- package/src/tools/skill.ts +37 -2
- package/src/tools/subagent.ts +6 -3
- package/src/tools/tool-catalog.generated.ts +10 -3
- package/src/tools/ultragoal-ask-guard.ts +2 -2
- package/src/web/insane/bridge.ts +113 -23
- package/src/web/search/providers/perplexity.ts +102 -41
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
import * as fs from "node:fs/promises";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
getAgentDir,
|
|
5
|
+
getAgentProfileAuthority,
|
|
6
|
+
getTrustedHomeDir,
|
|
7
|
+
normalizePathForComparison,
|
|
8
|
+
} from "@gajae-code/utils";
|
|
9
|
+
import { findRepoRoot } from "../capability/fs";
|
|
5
10
|
import type { Skill as CapabilitySkill } from "../capability/skill";
|
|
6
11
|
import type { SkillsSettings } from "../config/settings-schema";
|
|
7
12
|
import { resolveSkillScopeTrust } from "../config/skill-settings-defaults";
|
|
8
13
|
import { scanClaudeProjectSkills, scanClaudeUserSkills } from "../discovery/claude";
|
|
14
|
+
import { loadMarketplaceSkills } from "../discovery/claude-plugins";
|
|
9
15
|
import { scanCodexProjectSkills, scanCodexUserSkills } from "../discovery/codex";
|
|
10
|
-
import {
|
|
11
|
-
|
|
16
|
+
import {
|
|
17
|
+
compareSkillOrder,
|
|
18
|
+
getAncestorDirs,
|
|
19
|
+
getUserSkillScanDirs,
|
|
20
|
+
SOURCE_PATHS,
|
|
21
|
+
scanSkillsFromDir,
|
|
22
|
+
} from "../discovery/helpers";
|
|
23
|
+
import {
|
|
24
|
+
getSkillFilesystemIdentity,
|
|
25
|
+
isCanonicalGjcWorkflowSkillFilesystemAlias,
|
|
26
|
+
} from "../skill-state/canonical-skills";
|
|
12
27
|
import { expandTilde } from "../tools/path-utils";
|
|
13
|
-
import type
|
|
28
|
+
import { loadSkills, type Skill } from "./skills";
|
|
14
29
|
|
|
15
30
|
export type RuntimeSkillDiscoverySource = "project" | "user";
|
|
16
31
|
|
|
@@ -40,6 +55,9 @@ export interface RuntimeSkillDiscoveryResult {
|
|
|
40
55
|
export interface DiscoverRuntimeSkillsOptions {
|
|
41
56
|
cwd: string;
|
|
42
57
|
home?: string;
|
|
58
|
+
agentDir?: string;
|
|
59
|
+
/** Resolver-owned profile classification; unlike path comparison, this survives HOME refreshes. */
|
|
60
|
+
profileAuthority?: "default" | "custom";
|
|
43
61
|
query?: string;
|
|
44
62
|
limit?: number;
|
|
45
63
|
source?: RuntimeSkillDiscoverySource | "all";
|
|
@@ -53,8 +71,6 @@ function getRuntimeHome(): string {
|
|
|
53
71
|
const DEFAULT_LIMIT = 20;
|
|
54
72
|
const MAX_LIMIT = 50;
|
|
55
73
|
const MAX_DIAGNOSTICS = 10;
|
|
56
|
-
const BUILT_IN_SKILL_NAMES = new Set<string>(CANONICAL_GJC_WORKFLOW_SKILLS);
|
|
57
|
-
|
|
58
74
|
function normalizeLimit(limit: number | undefined): number {
|
|
59
75
|
if (limit === undefined || !Number.isFinite(limit)) return DEFAULT_LIMIT;
|
|
60
76
|
return Math.max(1, Math.min(MAX_LIMIT, Math.trunc(limit)));
|
|
@@ -81,41 +97,19 @@ async function getProjectSkillDirs(
|
|
|
81
97
|
): Promise<{ scans: ProjectScanDir[]; repoRoot: string | null }> {
|
|
82
98
|
const scans: ProjectScanDir[] = [];
|
|
83
99
|
const repoRoot = await findRepoRoot(cwd);
|
|
84
|
-
const walkDirs =
|
|
85
|
-
for (const dir of walkDirs) {
|
|
100
|
+
const walkDirs = getAncestorDirs(cwd, path.resolve(repoRoot ?? cwd), home);
|
|
101
|
+
for (const { dir } of walkDirs) {
|
|
86
102
|
scans.push({ dir: path.join(dir, ".gjc", "skills"), label: "project .gjc/skills" });
|
|
87
103
|
}
|
|
88
104
|
return { scans, repoRoot };
|
|
89
105
|
}
|
|
90
106
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const dirs: string[] = [];
|
|
94
|
-
let current = path.resolve(cwd);
|
|
95
|
-
const resolvedStop = path.resolve(stop);
|
|
96
|
-
const resolvedHome = path.resolve(home);
|
|
97
|
-
while (true) {
|
|
98
|
-
if (current !== resolvedHome) {
|
|
99
|
-
dirs.push(current);
|
|
100
|
-
}
|
|
101
|
-
if (current === resolvedStop) break;
|
|
102
|
-
const parent = path.dirname(current);
|
|
103
|
-
if (parent === current) break;
|
|
104
|
-
current = parent;
|
|
105
|
-
}
|
|
106
|
-
return dirs;
|
|
107
|
+
function getUserSkillDirs(home: string, agentDir = getAgentDir(), profileAuthority?: "default" | "custom"): string[] {
|
|
108
|
+
return getUserSkillScanDirs(home, agentDir, profileAuthority);
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
function
|
|
110
|
-
|
|
111
|
-
const configuredLegacyDir = SOURCE_PATHS.native.userBase;
|
|
112
|
-
return [
|
|
113
|
-
...new Set([
|
|
114
|
-
path.join(home, canonicalUserDir, "skills"),
|
|
115
|
-
path.join(home, configuredLegacyDir, "skills"),
|
|
116
|
-
path.join(home, ".gjc", "skills"),
|
|
117
|
-
]),
|
|
118
|
-
];
|
|
111
|
+
function resolveRuntimeAgentDir(home: string, agentDir: string | undefined, homeWasInjected: boolean): string {
|
|
112
|
+
return agentDir ?? (homeWasInjected ? path.join(home, SOURCE_PATHS.native.userAgent) : getAgentDir());
|
|
119
113
|
}
|
|
120
114
|
|
|
121
115
|
/**
|
|
@@ -152,18 +146,6 @@ function getUseWhen(skill: CapabilitySkill): string[] | undefined {
|
|
|
152
146
|
return values.length > 0 ? values : undefined;
|
|
153
147
|
}
|
|
154
148
|
|
|
155
|
-
function toRuntimeSkill(skill: CapabilitySkill, source: RuntimeSkillDiscoverySource): Skill {
|
|
156
|
-
return {
|
|
157
|
-
name: skill.name,
|
|
158
|
-
description: typeof skill.frontmatter?.description === "string" ? skill.frontmatter.description : "",
|
|
159
|
-
filePath: skill.path,
|
|
160
|
-
baseDir: skill.path.replace(/[\\/]SKILL\.md$/, ""),
|
|
161
|
-
source: `runtime:${source}`,
|
|
162
|
-
hide: skill.frontmatter?.hide === true,
|
|
163
|
-
_source: { ...skill._source, providerName: "Runtime skill discovery" },
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
|
|
167
149
|
function sourceEnabled(source: RuntimeSkillDiscoverySource, policy: SkillsSettings | undefined): boolean {
|
|
168
150
|
if (policy?.enabled !== true) return false;
|
|
169
151
|
return resolveSkillScopeTrust(policy, source);
|
|
@@ -202,13 +184,13 @@ async function realPathOrSelf(filePath: string): Promise<string> {
|
|
|
202
184
|
}
|
|
203
185
|
|
|
204
186
|
interface ScanJobResult {
|
|
205
|
-
items: Array<{ skill: CapabilitySkill; source: RuntimeSkillDiscoverySource }>;
|
|
187
|
+
items: Array<{ skill: CapabilitySkill; source: RuntimeSkillDiscoverySource; providerPriority: number }>;
|
|
206
188
|
warnings: string[];
|
|
207
189
|
label: string;
|
|
208
190
|
}
|
|
209
191
|
|
|
210
192
|
function isAllowedByPolicy(skill: CapabilitySkill, policy: SkillsSettings | undefined, diagnostics: string[]): boolean {
|
|
211
|
-
if (
|
|
193
|
+
if (isCanonicalGjcWorkflowSkillFilesystemAlias(skill.name)) {
|
|
212
194
|
pushDiagnostic(
|
|
213
195
|
diagnostics,
|
|
214
196
|
`skill "${skill.name}" is a bundled GJC workflow skill and always resolves to the bundled definition; the filesystem copy at ${skill.path} is shadowed`,
|
|
@@ -234,23 +216,16 @@ function pushDiagnostic(diagnostics: string[], message: string): void {
|
|
|
234
216
|
if (diagnostics.length < MAX_DIAGNOSTICS) diagnostics.push(message);
|
|
235
217
|
}
|
|
236
218
|
|
|
237
|
-
async function
|
|
219
|
+
async function collectPluginSkills(
|
|
238
220
|
home: string,
|
|
239
221
|
cwd: string,
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
// writers already invalidate via clearPluginRootsAndCaches; this is a defensive
|
|
243
|
-
// fallback so a stale in-memory cache cannot mask a disabled/removed plugin.
|
|
244
|
-
invalidateFsCache(`${getPluginsDir(home)}/installed_plugins.json`);
|
|
222
|
+
allowedLevels: ReadonlySet<"user" | "project">,
|
|
223
|
+
): Promise<{ items: CapabilitySkill[]; warnings: string[] }> {
|
|
245
224
|
try {
|
|
246
|
-
const
|
|
247
|
-
return
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
level: root.scope,
|
|
251
|
-
}));
|
|
252
|
-
} catch {
|
|
253
|
-
return [];
|
|
225
|
+
const result = await loadMarketplaceSkills({ cwd, home, repoRoot: await findRepoRoot(cwd) }, allowedLevels);
|
|
226
|
+
return { items: result.items, warnings: result.warnings ?? [] };
|
|
227
|
+
} catch (error) {
|
|
228
|
+
return { items: [], warnings: [`marketplace skill scan failed: ${String(error)}`] };
|
|
254
229
|
}
|
|
255
230
|
}
|
|
256
231
|
|
|
@@ -287,15 +262,18 @@ async function scanProjectOrUserDir(
|
|
|
287
262
|
level: "project" | "user",
|
|
288
263
|
label: string,
|
|
289
264
|
source: RuntimeSkillDiscoverySource,
|
|
265
|
+
providerPriority: number,
|
|
266
|
+
authorityRoot?: string,
|
|
290
267
|
): Promise<ScanJobResult> {
|
|
291
268
|
const result = await scanSkillsFromDir(ctx, {
|
|
292
269
|
dir,
|
|
270
|
+
authorityRoot,
|
|
293
271
|
providerId: "runtime",
|
|
294
272
|
level,
|
|
295
273
|
requireDescription: true,
|
|
296
274
|
});
|
|
297
275
|
return {
|
|
298
|
-
items: result.items.map(skill => ({ skill, source })),
|
|
276
|
+
items: result.items.map(skill => ({ skill, source, providerPriority })),
|
|
299
277
|
warnings: result.warnings ?? [],
|
|
300
278
|
label,
|
|
301
279
|
};
|
|
@@ -304,6 +282,7 @@ async function scanProjectOrUserDir(
|
|
|
304
282
|
interface ConventionImportScan {
|
|
305
283
|
host: "Claude Code" | "Codex";
|
|
306
284
|
dir: string;
|
|
285
|
+
scope: RuntimeSkillDiscoverySource;
|
|
307
286
|
skills: CapabilitySkill[];
|
|
308
287
|
}
|
|
309
288
|
|
|
@@ -326,20 +305,20 @@ async function collectConventionImportCandidates(
|
|
|
326
305
|
if ((source === "all" || source === "project") && sourceEnabled("project", policy)) {
|
|
327
306
|
jobs.push(
|
|
328
307
|
scanClaudeProjectSkills(ctx).then(result => {
|
|
329
|
-
scans.push({ host: "Claude Code", dir: ".claude/skills", skills: result.items });
|
|
308
|
+
scans.push({ host: "Claude Code", dir: ".claude/skills", scope: "project", skills: result.items });
|
|
330
309
|
}),
|
|
331
310
|
scanCodexProjectSkills(ctx).then(result => {
|
|
332
|
-
scans.push({ host: "Codex", dir: ".codex/skills", skills: result.items });
|
|
311
|
+
scans.push({ host: "Codex", dir: ".codex/skills", scope: "project", skills: result.items });
|
|
333
312
|
}),
|
|
334
313
|
);
|
|
335
314
|
}
|
|
336
315
|
if ((source === "all" || source === "user") && sourceEnabled("user", policy)) {
|
|
337
316
|
jobs.push(
|
|
338
317
|
scanClaudeUserSkills(ctx).then(result => {
|
|
339
|
-
scans.push({ host: "Claude Code", dir: "~/.claude/skills", skills: result.items });
|
|
318
|
+
scans.push({ host: "Claude Code", dir: "~/.claude/skills", scope: "user", skills: result.items });
|
|
340
319
|
}),
|
|
341
320
|
scanCodexUserSkills(ctx).then(result => {
|
|
342
|
-
scans.push({ host: "Codex", dir: "~/.codex/skills", skills: result.items });
|
|
321
|
+
scans.push({ host: "Codex", dir: "~/.codex/skills", scope: "user", skills: result.items });
|
|
343
322
|
}),
|
|
344
323
|
);
|
|
345
324
|
}
|
|
@@ -353,10 +332,17 @@ function reportConventionImportCandidates(
|
|
|
353
332
|
seenNames: Set<string>,
|
|
354
333
|
diagnostics: string[],
|
|
355
334
|
): void {
|
|
356
|
-
|
|
335
|
+
// Project scope is reported first: the bounded diagnostic budget must not be
|
|
336
|
+
// spent on a populated user-home convention directory (hundreds of skills is
|
|
337
|
+
// ordinary) before a project convention skill is ever named.
|
|
338
|
+
const scopeRank = (scan: ConventionImportScan) => (scan.scope === "project" ? 0 : 1);
|
|
339
|
+
for (const scan of scans.sort(
|
|
340
|
+
(a, b) => scopeRank(a) - scopeRank(b) || a.host.localeCompare(b.host) || a.dir.localeCompare(b.dir),
|
|
341
|
+
)) {
|
|
357
342
|
for (const skill of scan.skills) {
|
|
358
|
-
|
|
359
|
-
seenNames.
|
|
343
|
+
const normalizedName = getSkillFilesystemIdentity(skill.name);
|
|
344
|
+
if (seenNames.has(normalizedName)) continue;
|
|
345
|
+
seenNames.add(normalizedName);
|
|
360
346
|
pushDiagnostic(
|
|
361
347
|
diagnostics,
|
|
362
348
|
`skill "${skill.name}" found at ${skill.path} (${scan.host} convention): import sources are not loaded directly; copy it into a trusted .gjc/skills directory to enable it, e.g. mkdir -p .gjc/skills/${skill.name} && cp ${skill.path} .gjc/skills/${skill.name}/SKILL.md`,
|
|
@@ -396,64 +382,73 @@ export function describeDisabledSkillScopes(
|
|
|
396
382
|
export async function discoverRuntimeSkills(
|
|
397
383
|
options: DiscoverRuntimeSkillsOptions,
|
|
398
384
|
): Promise<RuntimeSkillDiscoveryResult> {
|
|
385
|
+
const hasExplicitHome = options.home !== undefined;
|
|
399
386
|
const home = options.home ?? getRuntimeHome();
|
|
400
387
|
const source = options.source ?? "all";
|
|
401
388
|
const policy = options.policy;
|
|
402
389
|
const diagnostics: string[] = [];
|
|
390
|
+
const agentDir = resolveRuntimeAgentDir(home, options.agentDir, hasExplicitHome);
|
|
391
|
+
const profileAuthority =
|
|
392
|
+
options.profileAuthority ??
|
|
393
|
+
(!hasExplicitHome
|
|
394
|
+
? options.agentDir !== undefined &&
|
|
395
|
+
normalizePathForComparison(options.agentDir) !== normalizePathForComparison(getAgentDir())
|
|
396
|
+
? "custom"
|
|
397
|
+
: getAgentProfileAuthority()
|
|
398
|
+
: undefined);
|
|
403
399
|
const scanJobs: Array<Promise<ScanJobResult>> = [];
|
|
404
400
|
const projectDirs = await getProjectSkillDirs(options.cwd, home);
|
|
405
401
|
const projectContext = { cwd: options.cwd, home, repoRoot: projectDirs.repoRoot };
|
|
406
402
|
if ((source === "all" || source === "project") && sourceEnabled("project", policy)) {
|
|
407
403
|
for (const { dir, label } of projectDirs.scans) {
|
|
408
|
-
scanJobs.push(scanProjectOrUserDir(projectContext, dir, "project", label, "project"));
|
|
404
|
+
scanJobs.push(scanProjectOrUserDir(projectContext, dir, "project", label, "project", 100));
|
|
409
405
|
}
|
|
410
406
|
}
|
|
411
407
|
if ((source === "all" || source === "user") && sourceEnabled("user", policy)) {
|
|
412
|
-
for (const dir of getUserSkillDirs(home)) {
|
|
408
|
+
for (const dir of getUserSkillDirs(home, agentDir, profileAuthority)) {
|
|
413
409
|
scanJobs.push(
|
|
414
|
-
scanProjectOrUserDir(
|
|
410
|
+
scanProjectOrUserDir(
|
|
411
|
+
{ cwd: options.cwd, home, repoRoot: home },
|
|
412
|
+
dir,
|
|
413
|
+
"user",
|
|
414
|
+
`user ${dir}`,
|
|
415
|
+
"user",
|
|
416
|
+
100,
|
|
417
|
+
path.resolve(dir) === path.resolve(agentDir, "skills") ? agentDir : undefined,
|
|
418
|
+
),
|
|
415
419
|
);
|
|
416
420
|
}
|
|
417
421
|
}
|
|
418
422
|
if ((source === "all" || source === "user") && policy?.enabled === true) {
|
|
419
423
|
for (const dir of getCustomSkillDirs(policy, home)) {
|
|
420
424
|
scanJobs.push(
|
|
421
|
-
scanProjectOrUserDir({ cwd: options.cwd, home, repoRoot: home }, dir, "user", `custom ${dir}`, "user"),
|
|
425
|
+
scanProjectOrUserDir({ cwd: options.cwd, home, repoRoot: home }, dir, "user", `custom ${dir}`, "user", 0),
|
|
422
426
|
);
|
|
423
427
|
}
|
|
424
428
|
}
|
|
425
429
|
|
|
426
|
-
// Marketplace plugin skills
|
|
427
|
-
//
|
|
428
|
-
//
|
|
429
|
-
// namespaced as `plugin:skillName`.
|
|
430
|
+
// Marketplace plugin skills come from the same provider used to populate
|
|
431
|
+
// session.skills, so discovery, slash commands, SDK state, and exact-name
|
|
432
|
+
// invocation cannot drift on manifest paths, namespacing, or enabled roots.
|
|
430
433
|
if (policy?.enabled === true) {
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
scanJobs.push(
|
|
438
|
-
(async () => {
|
|
439
|
-
const pluginCtx = { cwd: options.cwd, home, repoRoot: home };
|
|
440
|
-
const result = await scanSkillsFromDir(pluginCtx, {
|
|
441
|
-
dir: entry.dir,
|
|
442
|
-
providerId: "plugin",
|
|
443
|
-
level: entry.level,
|
|
444
|
-
requireDescription: true,
|
|
445
|
-
});
|
|
446
|
-
for (const skill of result.items) {
|
|
447
|
-
skill.name = `${entry.pluginName}:${skill.name}`;
|
|
448
|
-
}
|
|
449
|
-
return {
|
|
450
|
-
items: result.items.map(skill => ({ skill, source: entry.level as RuntimeSkillDiscoverySource })),
|
|
451
|
-
warnings: result.warnings ?? [],
|
|
452
|
-
label,
|
|
453
|
-
};
|
|
454
|
-
})(),
|
|
455
|
-
);
|
|
434
|
+
const allowedLevels = new Set<"user" | "project">();
|
|
435
|
+
if ((source === "all" || source === "project") && sourceEnabled("project", policy)) {
|
|
436
|
+
allowedLevels.add("project");
|
|
437
|
+
}
|
|
438
|
+
if ((source === "all" || source === "user") && sourceEnabled("user", policy)) {
|
|
439
|
+
allowedLevels.add("user");
|
|
456
440
|
}
|
|
441
|
+
scanJobs.push(
|
|
442
|
+
collectPluginSkills(home, options.cwd, allowedLevels).then(result => ({
|
|
443
|
+
items: result.items.map(skill => ({
|
|
444
|
+
skill,
|
|
445
|
+
source: skill.level as RuntimeSkillDiscoverySource,
|
|
446
|
+
providerPriority: 70,
|
|
447
|
+
})),
|
|
448
|
+
warnings: result.warnings,
|
|
449
|
+
label: "marketplace plugin skills",
|
|
450
|
+
})),
|
|
451
|
+
);
|
|
457
452
|
}
|
|
458
453
|
if (policy?.enabled === true && policy.customDirectories && policy.customDirectories.length > 0) {
|
|
459
454
|
for (const dir of getCustomSkillDirs(policy, home)) {
|
|
@@ -466,6 +461,7 @@ export async function discoverRuntimeSkills(
|
|
|
466
461
|
const seenNames = new Set<string>();
|
|
467
462
|
const seenPaths = new Set<string>();
|
|
468
463
|
const candidates: RuntimeSkillDiscoveryCandidate[] = [];
|
|
464
|
+
const orderedItems: ScanJobResult["items"] = [];
|
|
469
465
|
for (const entry of settled) {
|
|
470
466
|
if ("error" in entry) {
|
|
471
467
|
pushDiagnostic(diagnostics, `skill scan failed: ${entry.error}`);
|
|
@@ -476,29 +472,34 @@ export async function discoverRuntimeSkills(
|
|
|
476
472
|
pushDiagnostic(diagnostics, `${entry.label}: ${warning}`);
|
|
477
473
|
}
|
|
478
474
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
typeof item.skill.frontmatter?.description === "string" ? item.skill.frontmatter.description : "",
|
|
496
|
-
source: item.source,
|
|
497
|
-
path: item.skill.path,
|
|
498
|
-
useWhen: getUseWhen(item.skill),
|
|
499
|
-
};
|
|
500
|
-
if (matchesQuery(candidate, options.query ?? "")) candidates.push(candidate);
|
|
475
|
+
orderedItems.push(...entry.items);
|
|
476
|
+
}
|
|
477
|
+
orderedItems.sort((a, b) => {
|
|
478
|
+
const levelOrder = { project: 0, user: 1 } as const;
|
|
479
|
+
return levelOrder[a.source] - levelOrder[b.source] || b.providerPriority - a.providerPriority;
|
|
480
|
+
});
|
|
481
|
+
for (const item of orderedItems) {
|
|
482
|
+
if (!isAllowedByPolicy(item.skill, policy, diagnostics)) continue;
|
|
483
|
+
const realPath = await realPathOrSelf(item.skill.path);
|
|
484
|
+
const normalizedName = getSkillFilesystemIdentity(item.skill.name);
|
|
485
|
+
if (seenPaths.has(realPath) || seenNames.has(normalizedName)) {
|
|
486
|
+
pushDiagnostic(
|
|
487
|
+
diagnostics,
|
|
488
|
+
`skill "${item.skill.name}" already resolved from a higher-precedence location; ignoring ${item.skill.path}`,
|
|
489
|
+
);
|
|
490
|
+
continue;
|
|
501
491
|
}
|
|
492
|
+
seenPaths.add(realPath);
|
|
493
|
+
seenNames.add(normalizedName);
|
|
494
|
+
|
|
495
|
+
const candidate: RuntimeSkillDiscoveryCandidate = {
|
|
496
|
+
name: item.skill.name,
|
|
497
|
+
description: typeof item.skill.frontmatter?.description === "string" ? item.skill.frontmatter.description : "",
|
|
498
|
+
source: item.source,
|
|
499
|
+
path: item.skill.path,
|
|
500
|
+
useWhen: getUseWhen(item.skill),
|
|
501
|
+
};
|
|
502
|
+
if (matchesQuery(candidate, options.query ?? "")) candidates.push(candidate);
|
|
502
503
|
}
|
|
503
504
|
candidates.sort((a, b) => compareSkillOrder(a.name, a.path, b.name, b.path));
|
|
504
505
|
reportConventionImportCandidates(
|
|
@@ -516,71 +517,29 @@ export async function findRuntimeSkillByName(
|
|
|
516
517
|
cwd: string,
|
|
517
518
|
name: string,
|
|
518
519
|
policy?: SkillsSettings,
|
|
519
|
-
home
|
|
520
|
+
home?: string,
|
|
521
|
+
agentDir?: string,
|
|
522
|
+
profileAuthority?: "default" | "custom",
|
|
520
523
|
): Promise<Skill | undefined> {
|
|
521
524
|
const normalized = name.trim();
|
|
522
525
|
if (!normalized) return undefined;
|
|
523
|
-
|
|
524
|
-
const
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
{ cwd, home, repoRoot: home },
|
|
543
|
-
{ dir, providerId: "runtime", level: "user", requireDescription: true },
|
|
544
|
-
).then(result => result.items.map(skill => ({ skill, source: "user" as const }))),
|
|
545
|
-
);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
if (policy?.enabled === true) {
|
|
549
|
-
for (const dir of getCustomSkillDirs(policy, home)) {
|
|
550
|
-
scanJobs.push(
|
|
551
|
-
scanSkillsFromDir(
|
|
552
|
-
{ cwd, home, repoRoot: home },
|
|
553
|
-
{ dir, providerId: "runtime", level: "user", requireDescription: true },
|
|
554
|
-
).then(result => result.items.map(skill => ({ skill, source: "user" as const }))),
|
|
555
|
-
);
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
if (policy?.enabled === true) {
|
|
559
|
-
try {
|
|
560
|
-
const pluginDirs = await collectPluginSkillDirs(home, cwd);
|
|
561
|
-
for (const entry of pluginDirs) {
|
|
562
|
-
if (!sourceEnabled(entry.level, policy)) continue;
|
|
563
|
-
scanJobs.push(
|
|
564
|
-
scanSkillsFromDir(
|
|
565
|
-
{ cwd, home, repoRoot: home },
|
|
566
|
-
{
|
|
567
|
-
dir: entry.dir,
|
|
568
|
-
providerId: "plugin",
|
|
569
|
-
level: entry.level,
|
|
570
|
-
requireDescription: true,
|
|
571
|
-
},
|
|
572
|
-
).then(result => {
|
|
573
|
-
for (const skill of result.items) skill.name = `${entry.pluginName}:${skill.name}`;
|
|
574
|
-
return result.items.map(skill => ({ skill, source: entry.level as RuntimeSkillDiscoverySource }));
|
|
575
|
-
}),
|
|
576
|
-
);
|
|
577
|
-
}
|
|
578
|
-
} catch {}
|
|
579
|
-
}
|
|
580
|
-
for (const entry of (await Promise.all(scanJobs)).flat()) {
|
|
581
|
-
if (entry.skill.name === normalized && isAllowedByPolicy(entry.skill, policy, [])) {
|
|
582
|
-
return toRuntimeSkill(entry.skill, entry.source);
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
return undefined;
|
|
526
|
+
if (isCanonicalGjcWorkflowSkillFilesystemAlias(normalized)) return undefined;
|
|
527
|
+
const hasExplicitHome = home !== undefined;
|
|
528
|
+
const resolvedHome = home ?? getRuntimeHome();
|
|
529
|
+
const resolvedAgentDir = resolveRuntimeAgentDir(resolvedHome, agentDir, hasExplicitHome);
|
|
530
|
+
const resolvedProfileAuthority =
|
|
531
|
+
profileAuthority ??
|
|
532
|
+
(!hasExplicitHome
|
|
533
|
+
? agentDir !== undefined && normalizePathForComparison(agentDir) !== normalizePathForComparison(getAgentDir())
|
|
534
|
+
? "custom"
|
|
535
|
+
: getAgentProfileAuthority()
|
|
536
|
+
: undefined);
|
|
537
|
+
const loaded = await loadSkills({
|
|
538
|
+
...policy,
|
|
539
|
+
cwd,
|
|
540
|
+
home: resolvedHome,
|
|
541
|
+
agentDir: resolvedAgentDir,
|
|
542
|
+
profileAuthority: resolvedProfileAuthority,
|
|
543
|
+
});
|
|
544
|
+
return loaded.skills.find(skill => skill.name === normalized);
|
|
586
545
|
}
|
|
@@ -188,7 +188,7 @@ export interface AgentEndEvent {
|
|
|
188
188
|
sdkRunToken?: string;
|
|
189
189
|
/** Indicates whether the loop ended normally, suspended, cancelled, or entered maintenance. */
|
|
190
190
|
stopReason?: "completed" | "paused" | "cancelled" | "maintenance";
|
|
191
|
-
/** Present for maintenance checkpoints;
|
|
191
|
+
/** Present for maintenance checkpoints; only committed maintenance outcomes are non-terminal. */
|
|
192
192
|
maintenanceOutcome?: MidRunMaintenanceOutcome;
|
|
193
193
|
}
|
|
194
194
|
|