@x-code-cli/core 0.2.10 → 0.3.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/dist/agent/compression.d.ts +12 -2
- package/dist/agent/compression.d.ts.map +1 -1
- package/dist/agent/compression.js +51 -2
- package/dist/agent/compression.js.map +1 -1
- package/dist/agent/file-ingest.js +2 -2
- package/dist/agent/file-ingest.js.map +1 -1
- package/dist/agent/loop-state.d.ts +3 -2
- package/dist/agent/loop-state.d.ts.map +1 -1
- package/dist/agent/loop-state.js.map +1 -1
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +134 -5
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/memory-extractor.js +5 -5
- package/dist/agent/memory-extractor.js.map +1 -1
- package/dist/agent/plan-storage.js +1 -1
- package/dist/agent/plan-storage.js.map +1 -1
- package/dist/agent/sub-agents/index.d.ts +2 -1
- package/dist/agent/sub-agents/index.d.ts.map +1 -1
- package/dist/agent/sub-agents/index.js +1 -1
- package/dist/agent/sub-agents/index.js.map +1 -1
- package/dist/agent/sub-agents/loader.d.ts +13 -3
- package/dist/agent/sub-agents/loader.d.ts.map +1 -1
- package/dist/agent/sub-agents/loader.js +36 -9
- package/dist/agent/sub-agents/loader.js.map +1 -1
- package/dist/agent/sub-agents/registry.d.ts +18 -1
- package/dist/agent/sub-agents/registry.d.ts.map +1 -1
- package/dist/agent/sub-agents/registry.js +38 -5
- package/dist/agent/sub-agents/registry.js.map +1 -1
- package/dist/agent/sub-agents/runner.d.ts.map +1 -1
- package/dist/agent/sub-agents/runner.js +45 -1
- package/dist/agent/sub-agents/runner.js.map +1 -1
- package/dist/agent/sub-agents/types.d.ts +4 -1
- package/dist/agent/sub-agents/types.d.ts.map +1 -1
- package/dist/agent/system-prompt.d.ts +21 -0
- package/dist/agent/system-prompt.d.ts.map +1 -1
- package/dist/agent/system-prompt.js +68 -2
- package/dist/agent/system-prompt.js.map +1 -1
- package/dist/agent/tool-execution.d.ts.map +1 -1
- package/dist/agent/tool-execution.js +220 -1
- package/dist/agent/tool-execution.js.map +1 -1
- package/dist/commands/index.d.ts +6 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +3 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/loader.d.ts +19 -0
- package/dist/commands/loader.d.ts.map +1 -0
- package/dist/commands/loader.js +109 -0
- package/dist/commands/loader.js.map +1 -0
- package/dist/commands/registry.d.ts +44 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +102 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/types.d.ts +23 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +26 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +12 -10
- package/dist/config/index.js.map +1 -1
- package/dist/hooks/bus.d.ts +54 -0
- package/dist/hooks/bus.d.ts.map +1 -0
- package/dist/hooks/bus.js +165 -0
- package/dist/hooks/bus.js.map +1 -0
- package/dist/hooks/config-schema.d.ts +854 -0
- package/dist/hooks/config-schema.d.ts.map +1 -0
- package/dist/hooks/config-schema.js +79 -0
- package/dist/hooks/config-schema.js.map +1 -0
- package/dist/hooks/executor.d.ts +16 -0
- package/dist/hooks/executor.d.ts.map +1 -0
- package/dist/hooks/executor.js +183 -0
- package/dist/hooks/executor.js.map +1 -0
- package/dist/hooks/index.d.ts +10 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +6 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/registry.d.ts +23 -0
- package/dist/hooks/registry.d.ts.map +1 -0
- package/dist/hooks/registry.js +49 -0
- package/dist/hooks/registry.js.map +1 -0
- package/dist/hooks/types.d.ts +165 -0
- package/dist/hooks/types.d.ts.map +1 -0
- package/dist/hooks/types.js +25 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/hooks/variables.d.ts +22 -0
- package/dist/hooks/variables.d.ts.map +1 -0
- package/dist/hooks/variables.js +80 -0
- package/dist/hooks/variables.js.map +1 -0
- package/dist/index.d.ts +57 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -2
- package/dist/index.js.map +1 -1
- package/dist/knowledge/auto-memory.d.ts +1 -1
- package/dist/knowledge/auto-memory.d.ts.map +1 -1
- package/dist/knowledge/auto-memory.js +10 -10
- package/dist/knowledge/auto-memory.js.map +1 -1
- package/dist/knowledge/loader.js +12 -12
- package/dist/knowledge/loader.js.map +1 -1
- package/dist/mcp/arg-parser.d.ts +49 -0
- package/dist/mcp/arg-parser.d.ts.map +1 -0
- package/dist/mcp/arg-parser.js +357 -0
- package/dist/mcp/arg-parser.js.map +1 -0
- package/dist/mcp/client.d.ts +73 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +376 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/config-schema.d.ts +64 -0
- package/dist/mcp/config-schema.d.ts.map +1 -0
- package/dist/mcp/config-schema.js +86 -0
- package/dist/mcp/config-schema.js.map +1 -0
- package/dist/mcp/config-writer.d.ts +41 -0
- package/dist/mcp/config-writer.d.ts.map +1 -0
- package/dist/mcp/config-writer.js +138 -0
- package/dist/mcp/config-writer.js.map +1 -0
- package/dist/mcp/env-safety.d.ts +12 -0
- package/dist/mcp/env-safety.d.ts.map +1 -0
- package/dist/mcp/env-safety.js +80 -0
- package/dist/mcp/env-safety.js.map +1 -0
- package/dist/mcp/expand-env.d.ts +14 -0
- package/dist/mcp/expand-env.d.ts.map +1 -0
- package/dist/mcp/expand-env.js +52 -0
- package/dist/mcp/expand-env.js.map +1 -0
- package/dist/mcp/loader.d.ts +81 -0
- package/dist/mcp/loader.d.ts.map +1 -0
- package/dist/mcp/loader.js +223 -0
- package/dist/mcp/loader.js.map +1 -0
- package/dist/mcp/name-mangling.d.ts +11 -0
- package/dist/mcp/name-mangling.d.ts.map +1 -0
- package/dist/mcp/name-mangling.js +82 -0
- package/dist/mcp/name-mangling.js.map +1 -0
- package/dist/mcp/oauth/callback-server.d.ts +25 -0
- package/dist/mcp/oauth/callback-server.d.ts.map +1 -0
- package/dist/mcp/oauth/callback-server.js +118 -0
- package/dist/mcp/oauth/callback-server.js.map +1 -0
- package/dist/mcp/oauth/provider.d.ts +80 -0
- package/dist/mcp/oauth/provider.d.ts.map +1 -0
- package/dist/mcp/oauth/provider.js +292 -0
- package/dist/mcp/oauth/provider.js.map +1 -0
- package/dist/mcp/oauth/token-storage.d.ts +42 -0
- package/dist/mcp/oauth/token-storage.d.ts.map +1 -0
- package/dist/mcp/oauth/token-storage.js +121 -0
- package/dist/mcp/oauth/token-storage.js.map +1 -0
- package/dist/mcp/permissions.d.ts +28 -0
- package/dist/mcp/permissions.d.ts.map +1 -0
- package/dist/mcp/permissions.js +105 -0
- package/dist/mcp/permissions.js.map +1 -0
- package/dist/mcp/registry.d.ts +150 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +334 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/resources.d.ts +7 -0
- package/dist/mcp/resources.d.ts.map +1 -0
- package/dist/mcp/resources.js +40 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/tool-bridge.d.ts +16 -0
- package/dist/mcp/tool-bridge.d.ts.map +1 -0
- package/dist/mcp/tool-bridge.js +56 -0
- package/dist/mcp/tool-bridge.js.map +1 -0
- package/dist/mcp/trust.d.ts +31 -0
- package/dist/mcp/trust.d.ts.map +1 -0
- package/dist/mcp/trust.js +103 -0
- package/dist/mcp/trust.js.map +1 -0
- package/dist/mcp/types.d.ts +73 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +13 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/permissions/index.d.ts +1 -1
- package/dist/permissions/index.d.ts.map +1 -1
- package/dist/permissions/index.js +10 -4
- package/dist/permissions/index.js.map +1 -1
- package/dist/permissions/session-store.d.ts +79 -17
- package/dist/permissions/session-store.d.ts.map +1 -1
- package/dist/permissions/session-store.js +298 -38
- package/dist/permissions/session-store.js.map +1 -1
- package/dist/plugins/consent.d.ts +87 -0
- package/dist/plugins/consent.d.ts.map +1 -0
- package/dist/plugins/consent.js +181 -0
- package/dist/plugins/consent.js.map +1 -0
- package/dist/plugins/enable-state.d.ts +34 -0
- package/dist/plugins/enable-state.d.ts.map +1 -0
- package/dist/plugins/enable-state.js +159 -0
- package/dist/plugins/enable-state.js.map +1 -0
- package/dist/plugins/installer.d.ts +64 -0
- package/dist/plugins/installer.d.ts.map +1 -0
- package/dist/plugins/installer.js +416 -0
- package/dist/plugins/installer.js.map +1 -0
- package/dist/plugins/integration.d.ts +91 -0
- package/dist/plugins/integration.d.ts.map +1 -0
- package/dist/plugins/integration.js +233 -0
- package/dist/plugins/integration.js.map +1 -0
- package/dist/plugins/loader.d.ts +69 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +243 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/manifest.d.ts +23 -0
- package/dist/plugins/manifest.d.ts.map +1 -0
- package/dist/plugins/manifest.js +143 -0
- package/dist/plugins/manifest.js.map +1 -0
- package/dist/plugins/marketplace.d.ts +103 -0
- package/dist/plugins/marketplace.d.ts.map +1 -0
- package/dist/plugins/marketplace.js +532 -0
- package/dist/plugins/marketplace.js.map +1 -0
- package/dist/plugins/paths.d.ts +44 -0
- package/dist/plugins/paths.d.ts.map +1 -0
- package/dist/plugins/paths.js +89 -0
- package/dist/plugins/paths.js.map +1 -0
- package/dist/plugins/refresh.d.ts +61 -0
- package/dist/plugins/refresh.d.ts.map +1 -0
- package/dist/plugins/refresh.js +98 -0
- package/dist/plugins/refresh.js.map +1 -0
- package/dist/plugins/registry.d.ts +40 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +80 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/plugins/types.d.ts +225 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +16 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/plugins/user-config.d.ts +22 -0
- package/dist/plugins/user-config.d.ts.map +1 -0
- package/dist/plugins/user-config.js +96 -0
- package/dist/plugins/user-config.js.map +1 -0
- package/dist/skills/loader.d.ts +19 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +197 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/registry.d.ts +74 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js +136 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/skills/settings.d.ts +13 -0
- package/dist/skills/settings.d.ts.map +1 -0
- package/dist/skills/settings.js +100 -0
- package/dist/skills/settings.js.map +1 -0
- package/dist/tools/activate-skill.d.ts +5 -0
- package/dist/tools/activate-skill.d.ts.map +1 -0
- package/dist/tools/activate-skill.js +33 -0
- package/dist/tools/activate-skill.js.map +1 -0
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/shell-utils.d.ts.map +1 -1
- package/dist/tools/shell-utils.js +157 -6
- package/dist/tools/shell-utils.js.map +1 -1
- package/dist/tools/todo-write.d.ts +1 -1
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +2 -1
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/types/index.d.ts +46 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils.d.ts +23 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +76 -20
- package/dist/utils.js.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +47 -0
- package/dist/version.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// @x-code-cli/core — Install-time consent preview
|
|
2
|
+
//
|
|
3
|
+
// Before a plugin's contents are committed to the cache, the installer
|
|
4
|
+
// builds a `ConsentPreview` summarising what the plugin will contribute
|
|
5
|
+
// (hooks, MCP servers, scopes etc.) and hands it to the caller-supplied
|
|
6
|
+
// consent callback. If the callback returns false, the install aborts
|
|
7
|
+
// and the temp dir is cleaned up.
|
|
8
|
+
//
|
|
9
|
+
// The preview is built from the already-parsed manifest, so all the
|
|
10
|
+
// validation work has already happened — by the time we ask the user
|
|
11
|
+
// "do you accept?" we know the plugin parses cleanly and what it will
|
|
12
|
+
// touch on their system.
|
|
13
|
+
//
|
|
14
|
+
// What it intentionally does NOT include:
|
|
15
|
+
//
|
|
16
|
+
// - Skill / agent / command counts (they're hidden inside subdirs;
|
|
17
|
+
// scanning them just to build a preview would slow every install,
|
|
18
|
+
// and the preview is meant to be a glance, not an audit).
|
|
19
|
+
// - LICENSE file contents — surfaced as a name only; readers should
|
|
20
|
+
// follow the homepage / source URL to read the actual terms.
|
|
21
|
+
//
|
|
22
|
+
// What it DOES include — the things with real security blast radius:
|
|
23
|
+
// hooks (arbitrary shell), MCP servers (arbitrary subprocesses), and
|
|
24
|
+
// source (so the user knows whether it came from a trusted marketplace
|
|
25
|
+
// or a random GitHub repo).
|
|
26
|
+
import fs from 'node:fs/promises';
|
|
27
|
+
import path from 'node:path';
|
|
28
|
+
import { parseHookConfig } from '../hooks/config-schema.js';
|
|
29
|
+
import { parseServersBlock } from '../mcp/config-schema.js';
|
|
30
|
+
import { extractMcpServersBlock } from './integration.js';
|
|
31
|
+
/** Stat the plugin root for the conventional contribution files / dirs
|
|
32
|
+
* the loader's `resolveContributions` will pick up at runtime. The
|
|
33
|
+
* consent UI uses this so "Will contribute" doesn't lie when a plugin
|
|
34
|
+
* drops `skills/`, `.mcp.json`, etc. at root without naming them in
|
|
35
|
+
* the manifest. Safe to call on any directory — every probe is a
|
|
36
|
+
* best-effort stat / read and missing or unreadable files just count
|
|
37
|
+
* as "absent". */
|
|
38
|
+
export async function probePluginRoot(rootDir) {
|
|
39
|
+
const [hasSkillsDir, hasAgentsDir, hasCommandsDir] = await Promise.all([
|
|
40
|
+
isDir(path.join(rootDir, 'skills')),
|
|
41
|
+
isDir(path.join(rootDir, 'agents')),
|
|
42
|
+
isDir(path.join(rootDir, 'commands')),
|
|
43
|
+
]);
|
|
44
|
+
let rootMcpServerNames = [];
|
|
45
|
+
let hasRootMcpFile = false;
|
|
46
|
+
for (const conv of ['.mcp.json', 'mcp.json']) {
|
|
47
|
+
const p = path.join(rootDir, conv);
|
|
48
|
+
if (!(await isFile(p)))
|
|
49
|
+
continue;
|
|
50
|
+
hasRootMcpFile = true;
|
|
51
|
+
try {
|
|
52
|
+
const raw = await fs.readFile(p, 'utf-8');
|
|
53
|
+
const parsed = JSON.parse(raw);
|
|
54
|
+
const block = extractMcpServersBlock(parsed);
|
|
55
|
+
const { servers } = parseServersBlock(block);
|
|
56
|
+
rootMcpServerNames = Object.keys(servers);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// parse errors are deliberately swallowed — they'll surface
|
|
60
|
+
// with a precise message at load time. The consent preview
|
|
61
|
+
// just needs to know the file exists.
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
let rootHookEvents = [];
|
|
66
|
+
let hasRootHooksFile = false;
|
|
67
|
+
const hooksPath = path.join(rootDir, 'hooks', 'hooks.json');
|
|
68
|
+
if (await isFile(hooksPath)) {
|
|
69
|
+
hasRootHooksFile = true;
|
|
70
|
+
try {
|
|
71
|
+
const raw = await fs.readFile(hooksPath, 'utf-8');
|
|
72
|
+
const parsed = JSON.parse(raw);
|
|
73
|
+
const cfg = parseHookConfig(parsed, rootDir);
|
|
74
|
+
rootHookEvents = Object.keys(cfg);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Same reasoning as the mcp probe — load-time errors win.
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
hasSkillsDir,
|
|
82
|
+
hasAgentsDir,
|
|
83
|
+
hasCommandsDir,
|
|
84
|
+
rootMcpServerNames,
|
|
85
|
+
hasRootMcpFile,
|
|
86
|
+
rootHookEvents,
|
|
87
|
+
hasRootHooksFile,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
async function isDir(p) {
|
|
91
|
+
try {
|
|
92
|
+
const s = await fs.stat(p);
|
|
93
|
+
return s.isDirectory();
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function isFile(p) {
|
|
100
|
+
try {
|
|
101
|
+
const s = await fs.stat(p);
|
|
102
|
+
return s.isFile();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/** Build a `ConsentPreview` from a parsed manifest. The hook + mcp
|
|
109
|
+
* fields are inspected only for the inline shape; path-form
|
|
110
|
+
* contributions are surfaced as `has*` booleans so the consent UI can
|
|
111
|
+
* warn "this plugin contributes MCP servers" even when their names
|
|
112
|
+
* aren't yet known.
|
|
113
|
+
*
|
|
114
|
+
* When `input.rootProbe` is present, conventional root-level
|
|
115
|
+
* contributions (an undeclared `.mcp.json`, `hooks/hooks.json`,
|
|
116
|
+
* `skills/`, etc.) are merged in too — the loader will pick those up
|
|
117
|
+
* at runtime, so the consent UI needs to know about them now. */
|
|
118
|
+
export function buildConsentPreview(input) {
|
|
119
|
+
const m = input.manifest;
|
|
120
|
+
const probe = input.rootProbe;
|
|
121
|
+
let hookEvents = [];
|
|
122
|
+
let hasPathHooks = false;
|
|
123
|
+
if (m.hooks !== undefined) {
|
|
124
|
+
if (typeof m.hooks === 'string') {
|
|
125
|
+
hasPathHooks = true;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
try {
|
|
129
|
+
const cfg = parseHookConfig(m.hooks, input.pluginId);
|
|
130
|
+
hookEvents = Object.keys(cfg);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
// Don't fail consent on hook parse errors — the install path
|
|
134
|
+
// will surface them properly. Just leave hookEvents empty so
|
|
135
|
+
// the preview doesn't lie about what's registered.
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else if (probe?.hasRootHooksFile) {
|
|
140
|
+
hookEvents = probe.rootHookEvents;
|
|
141
|
+
hasPathHooks = true;
|
|
142
|
+
}
|
|
143
|
+
let inlineMcpServerNames = [];
|
|
144
|
+
let hasPathMcpServers = false;
|
|
145
|
+
if (m.mcpServers !== undefined) {
|
|
146
|
+
if (typeof m.mcpServers === 'string') {
|
|
147
|
+
hasPathMcpServers = true;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
const { servers } = parseServersBlock(m.mcpServers);
|
|
151
|
+
inlineMcpServerNames = Object.keys(servers);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else if (probe?.hasRootMcpFile) {
|
|
155
|
+
// Convention-discovered `.mcp.json` at the plugin root — same blast
|
|
156
|
+
// radius as a manifest-declared path entry. Surface names when we
|
|
157
|
+
// were able to parse them; otherwise just flag the file's presence.
|
|
158
|
+
inlineMcpServerNames = probe.rootMcpServerNames;
|
|
159
|
+
hasPathMcpServers = true;
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
pluginId: input.pluginId,
|
|
163
|
+
version: m.version,
|
|
164
|
+
description: m.description,
|
|
165
|
+
source: input.source,
|
|
166
|
+
marketplace: input.marketplace,
|
|
167
|
+
verified: input.verified ?? false,
|
|
168
|
+
fromReservedMarketplace: input.fromReservedMarketplace ?? false,
|
|
169
|
+
hookEvents,
|
|
170
|
+
inlineMcpServerNames,
|
|
171
|
+
hasSkillsDir: !!m.skills || !!probe?.hasSkillsDir,
|
|
172
|
+
hasAgentsDir: !!m.agents || !!probe?.hasAgentsDir,
|
|
173
|
+
hasCommandsDir: !!m.commands || !!probe?.hasCommandsDir,
|
|
174
|
+
hasPathMcpServers,
|
|
175
|
+
hasPathHooks,
|
|
176
|
+
author: m.author?.name,
|
|
177
|
+
license: m.license,
|
|
178
|
+
homepage: m.homepage,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=consent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent.js","sourceRoot":"","sources":["../../src/plugins/consent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { PluginScope } from './types.js';
|
|
2
|
+
export declare function settingsPathForScope(scope: PluginScope, cwd?: string): string;
|
|
3
|
+
/** Resolved per-plugin enable state, plus which scope decided it (for
|
|
4
|
+
* `/plugin doctor`). When `decidedBy` is `undefined`, no scope mentioned
|
|
5
|
+
* the plugin and the default applied. */
|
|
6
|
+
export interface ResolvedEnableState {
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
decidedBy: PluginScope | undefined;
|
|
9
|
+
}
|
|
10
|
+
export declare class EnableState {
|
|
11
|
+
private readonly perScope;
|
|
12
|
+
private constructor();
|
|
13
|
+
/** Load both settings files and build a snapshot. The snapshot is
|
|
14
|
+
* intentionally immutable from this point — callers re-load via
|
|
15
|
+
* `EnableState.load()` after settings.json writes. `cwd` defaults to
|
|
16
|
+
* `process.cwd()` and controls where the `'project'` scope file is
|
|
17
|
+
* read from. */
|
|
18
|
+
static load(cwd?: string): Promise<EnableState>;
|
|
19
|
+
/** Effective enabled state for one plugin id. */
|
|
20
|
+
resolve(pluginId: string): ResolvedEnableState;
|
|
21
|
+
/** Raw map for one scope — used by `/plugin list` to show the per-scope
|
|
22
|
+
* flags alongside the effective state. */
|
|
23
|
+
scopeEntries(scope: PluginScope): Record<string, boolean>;
|
|
24
|
+
}
|
|
25
|
+
/** Write a single plugin's enable flag in the chosen scope. Read-modify-
|
|
26
|
+
* write so unrelated fields in settings.json (e.g. `disabledSkills` from
|
|
27
|
+
* the skill subsystem) aren't clobbered. Returns whether the file
|
|
28
|
+
* actually changed (so callers can render an accurate
|
|
29
|
+
* "already enabled" vs "enabled" message). */
|
|
30
|
+
export declare function setPluginEnabled(pluginId: string, scope: PluginScope, enabled: boolean, cwd?: string): Promise<'changed' | 'noop'>;
|
|
31
|
+
/** Remove a plugin's entry from a scope's enabledPlugins (used by
|
|
32
|
+
* `/plugin uninstall` to keep settings.json tidy). */
|
|
33
|
+
export declare function clearPluginEntry(pluginId: string, scope: PluginScope, cwd?: string): Promise<'changed' | 'noop'>;
|
|
34
|
+
//# sourceMappingURL=enable-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enable-state.d.ts","sourceRoot":"","sources":["../../src/plugins/enable-state.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAc7C,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CAG5F;AA2BD;;0CAE0C;AAC1C,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,WAAW,GAAG,SAAS,CAAA;CACnC;AAED,qBAAa,WAAW;IACF,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAA7C,OAAO;IAEP;;;;qBAIiB;WACJ,IAAI,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,WAAW,CAAC;IASpE,iDAAiD;IACjD,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB;IAU9C;+CAC2C;IAC3C,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAG1D;AAID;;;;+CAI+C;AAC/C,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,OAAO,EAChB,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,CAwB7B;AAED;uDACuD;AACvD,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,WAAW,EAClB,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,CA+B7B"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// @x-code-cli/core — Plugin enable/disable state
|
|
2
|
+
//
|
|
3
|
+
// Reads the per-scope `enabledPlugins` map from settings.json files and
|
|
4
|
+
// resolves the effective enabled state for each plugin id.
|
|
5
|
+
//
|
|
6
|
+
// Two-scope model, mirroring mcp + skill subsystems:
|
|
7
|
+
//
|
|
8
|
+
// user ~/.x-code/settings.json
|
|
9
|
+
// project <cwd>/.x-code/settings.local.json (gitignored)
|
|
10
|
+
//
|
|
11
|
+
// `'project'` reading a `.local.json` file is a slight naming quirk we
|
|
12
|
+
// inherit from skills — it's a per-user override for one repo, not a
|
|
13
|
+
// team-shared file. A separate team-shared scope (committed) can be
|
|
14
|
+
// added later without touching the existing two.
|
|
15
|
+
//
|
|
16
|
+
// Map shape: `{ "name@marketplace": true | false }` — true = enabled,
|
|
17
|
+
// false = explicitly disabled, missing = use the project-wide default
|
|
18
|
+
// (currently `true`, i.e. default-enable).
|
|
19
|
+
//
|
|
20
|
+
// Precedence: project > user. An explicit value in a higher-priority
|
|
21
|
+
// scope wins; a missing entry falls through.
|
|
22
|
+
import fs from 'node:fs/promises';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
import { XCODE_DIR, userXcodeDir } from '../utils.js';
|
|
25
|
+
/** Highest precedence first. The first scope with an explicit entry wins. */
|
|
26
|
+
const SCOPE_PRECEDENCE = ['project', 'user'];
|
|
27
|
+
/** Default enabled state when no scope mentions the plugin. We default
|
|
28
|
+
* to ENABLED so newly-installed plugins work out-of-the-box; users who
|
|
29
|
+
* want opt-in behaviour can flip individual plugins off explicitly. */
|
|
30
|
+
const DEFAULT_ENABLED = true;
|
|
31
|
+
export function settingsPathForScope(scope, cwd = process.cwd()) {
|
|
32
|
+
if (scope === 'user')
|
|
33
|
+
return path.join(userXcodeDir(), 'settings.json');
|
|
34
|
+
return path.join(cwd, XCODE_DIR, 'settings.local.json');
|
|
35
|
+
}
|
|
36
|
+
async function readSettings(scope, cwd) {
|
|
37
|
+
const file = settingsPathForScope(scope, cwd);
|
|
38
|
+
try {
|
|
39
|
+
const raw = await fs.readFile(file, 'utf-8');
|
|
40
|
+
const parsed = JSON.parse(raw);
|
|
41
|
+
if (!parsed || typeof parsed !== 'object')
|
|
42
|
+
return {};
|
|
43
|
+
const obj = parsed;
|
|
44
|
+
if (obj.enabledPlugins && typeof obj.enabledPlugins === 'object' && !Array.isArray(obj.enabledPlugins)) {
|
|
45
|
+
// Coerce values to boolean defensively — settings.json may have been
|
|
46
|
+
// hand-edited and the wrong type here shouldn't crash the loader.
|
|
47
|
+
const out = {};
|
|
48
|
+
for (const [k, v] of Object.entries(obj.enabledPlugins)) {
|
|
49
|
+
if (typeof v === 'boolean')
|
|
50
|
+
out[k] = v;
|
|
51
|
+
}
|
|
52
|
+
return { enabledPlugins: out };
|
|
53
|
+
}
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
if (err.code === 'ENOENT')
|
|
58
|
+
return {};
|
|
59
|
+
// Malformed JSON: ignore + return empty so a broken settings file never
|
|
60
|
+
// blocks startup. The user can fix the file and re-launch.
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export class EnableState {
|
|
65
|
+
perScope;
|
|
66
|
+
constructor(perScope) {
|
|
67
|
+
this.perScope = perScope;
|
|
68
|
+
}
|
|
69
|
+
/** Load both settings files and build a snapshot. The snapshot is
|
|
70
|
+
* intentionally immutable from this point — callers re-load via
|
|
71
|
+
* `EnableState.load()` after settings.json writes. `cwd` defaults to
|
|
72
|
+
* `process.cwd()` and controls where the `'project'` scope file is
|
|
73
|
+
* read from. */
|
|
74
|
+
static async load(cwd = process.cwd()) {
|
|
75
|
+
const map = new Map();
|
|
76
|
+
for (const scope of SCOPE_PRECEDENCE) {
|
|
77
|
+
const s = await readSettings(scope, cwd);
|
|
78
|
+
map.set(scope, s.enabledPlugins ?? {});
|
|
79
|
+
}
|
|
80
|
+
return new EnableState(map);
|
|
81
|
+
}
|
|
82
|
+
/** Effective enabled state for one plugin id. */
|
|
83
|
+
resolve(pluginId) {
|
|
84
|
+
for (const scope of SCOPE_PRECEDENCE) {
|
|
85
|
+
const table = this.perScope.get(scope) ?? {};
|
|
86
|
+
if (pluginId in table) {
|
|
87
|
+
return { enabled: table[pluginId], decidedBy: scope };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { enabled: DEFAULT_ENABLED, decidedBy: undefined };
|
|
91
|
+
}
|
|
92
|
+
/** Raw map for one scope — used by `/plugin list` to show the per-scope
|
|
93
|
+
* flags alongside the effective state. */
|
|
94
|
+
scopeEntries(scope) {
|
|
95
|
+
return { ...(this.perScope.get(scope) ?? {}) };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// ── Mutating writes (used by /plugin enable|disable|install) ────────────
|
|
99
|
+
/** Write a single plugin's enable flag in the chosen scope. Read-modify-
|
|
100
|
+
* write so unrelated fields in settings.json (e.g. `disabledSkills` from
|
|
101
|
+
* the skill subsystem) aren't clobbered. Returns whether the file
|
|
102
|
+
* actually changed (so callers can render an accurate
|
|
103
|
+
* "already enabled" vs "enabled" message). */
|
|
104
|
+
export async function setPluginEnabled(pluginId, scope, enabled, cwd = process.cwd()) {
|
|
105
|
+
const file = settingsPathForScope(scope, cwd);
|
|
106
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
107
|
+
let existing = {};
|
|
108
|
+
try {
|
|
109
|
+
const raw = await fs.readFile(file, 'utf-8');
|
|
110
|
+
const parsed = JSON.parse(raw);
|
|
111
|
+
if (parsed && typeof parsed === 'object')
|
|
112
|
+
existing = parsed;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// first write — file may not exist yet
|
|
116
|
+
}
|
|
117
|
+
const currentMap = existing.enabledPlugins && typeof existing.enabledPlugins === 'object' && !Array.isArray(existing.enabledPlugins)
|
|
118
|
+
? { ...existing.enabledPlugins }
|
|
119
|
+
: {};
|
|
120
|
+
if (currentMap[pluginId] === enabled)
|
|
121
|
+
return 'noop';
|
|
122
|
+
currentMap[pluginId] = enabled;
|
|
123
|
+
existing.enabledPlugins = currentMap;
|
|
124
|
+
await fs.writeFile(file, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
|
|
125
|
+
return 'changed';
|
|
126
|
+
}
|
|
127
|
+
/** Remove a plugin's entry from a scope's enabledPlugins (used by
|
|
128
|
+
* `/plugin uninstall` to keep settings.json tidy). */
|
|
129
|
+
export async function clearPluginEntry(pluginId, scope, cwd = process.cwd()) {
|
|
130
|
+
const file = settingsPathForScope(scope, cwd);
|
|
131
|
+
let existing = {};
|
|
132
|
+
try {
|
|
133
|
+
const raw = await fs.readFile(file, 'utf-8');
|
|
134
|
+
const parsed = JSON.parse(raw);
|
|
135
|
+
if (parsed && typeof parsed === 'object')
|
|
136
|
+
existing = parsed;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return 'noop';
|
|
140
|
+
}
|
|
141
|
+
if (!existing.enabledPlugins ||
|
|
142
|
+
typeof existing.enabledPlugins !== 'object' ||
|
|
143
|
+
Array.isArray(existing.enabledPlugins)) {
|
|
144
|
+
return 'noop';
|
|
145
|
+
}
|
|
146
|
+
const map = { ...existing.enabledPlugins };
|
|
147
|
+
if (!(pluginId in map))
|
|
148
|
+
return 'noop';
|
|
149
|
+
delete map[pluginId];
|
|
150
|
+
if (Object.keys(map).length === 0) {
|
|
151
|
+
delete existing.enabledPlugins;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
existing.enabledPlugins = map;
|
|
155
|
+
}
|
|
156
|
+
await fs.writeFile(file, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
|
|
157
|
+
return 'changed';
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=enable-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enable-state.js","sourceRoot":"","sources":["../../src/plugins/enable-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type ConsentPreview } from './consent.js';
|
|
2
|
+
import type { InstalledPluginRecord, ManifestFormat, PluginManifest, PluginScope, PluginSource } from './types.js';
|
|
3
|
+
import { type UserConfigValue } from './user-config.js';
|
|
4
|
+
export interface InstallRequest {
|
|
5
|
+
source: PluginSource;
|
|
6
|
+
/** Marketplace this plugin belongs to. Use `"local"` for direct
|
|
7
|
+
* git/local installs that aren't associated with a subscribed
|
|
8
|
+
* marketplace — the resulting plugin id will be `<name>@local`. */
|
|
9
|
+
marketplace: string;
|
|
10
|
+
/** Scope where the install is recorded (which settings.json's
|
|
11
|
+
* `enabledPlugins` map will mention it). Defaults to `'user'`. */
|
|
12
|
+
scope?: PluginScope;
|
|
13
|
+
/** If set, the installer aborts when the manifest's `name` field
|
|
14
|
+
* doesn't match — used by the marketplace install path to catch
|
|
15
|
+
* spoofed entries. */
|
|
16
|
+
expectedName?: string;
|
|
17
|
+
/** Whether the marketplace listing marked this plugin as verified.
|
|
18
|
+
* Surfaced to the consent callback so users know whether the listing
|
|
19
|
+
* came with curator endorsement. Pure metadata — we don't grant
|
|
20
|
+
* extra trust based on the flag. */
|
|
21
|
+
verified?: boolean;
|
|
22
|
+
/** Called after manifest parse but BEFORE the temp dir is moved to
|
|
23
|
+
* the cache. Return false to abort the install — the temp dir is
|
|
24
|
+
* cleaned up and the cache is untouched. Absent ⇒ install proceeds
|
|
25
|
+
* without prompting (used by tests + the `--yes` CLI flag). */
|
|
26
|
+
consent?: (preview: ConsentPreview) => Promise<boolean> | boolean;
|
|
27
|
+
/** Called AFTER consent passes when the manifest declares `userConfig`.
|
|
28
|
+
* The caller (a CLI / TUI handler) collects values for each field —
|
|
29
|
+
* typically by prompting the user one field at a time, masking input
|
|
30
|
+
* for `sensitive: true` fields — and resolves to a `{ key: value }`
|
|
31
|
+
* map that gets persisted via user-config.ts. Returning `null`
|
|
32
|
+
* aborts the install (treat it like consent denial). Absent ⇒ we
|
|
33
|
+
* skip the prompt; non-sensitive fields fall back to manifest
|
|
34
|
+
* defaults, sensitive fields are simply unset (the plugin's hooks /
|
|
35
|
+
* MCP entries will see empty env vars, which is the same as today). */
|
|
36
|
+
userConfigPrompt?: (fields: PluginManifest['userConfig']) => Promise<Record<string, UserConfigValue> | null>;
|
|
37
|
+
signal?: AbortSignal;
|
|
38
|
+
}
|
|
39
|
+
export interface InstallResult {
|
|
40
|
+
pluginId: string;
|
|
41
|
+
rootDir: string;
|
|
42
|
+
manifest: PluginManifest;
|
|
43
|
+
manifestFormat: ManifestFormat;
|
|
44
|
+
record: InstalledPluginRecord;
|
|
45
|
+
}
|
|
46
|
+
export declare class InstallError extends Error {
|
|
47
|
+
constructor(message: string);
|
|
48
|
+
}
|
|
49
|
+
export declare function installPlugin(req: InstallRequest): Promise<InstallResult>;
|
|
50
|
+
export declare function listInstalledPlugins(): Promise<InstalledPluginRecord[]>;
|
|
51
|
+
export declare function findInstalledPlugin(id: string): Promise<InstalledPluginRecord | undefined>;
|
|
52
|
+
export interface UninstallResult {
|
|
53
|
+
/** Versions that were removed from cache. Empty if the plugin wasn't
|
|
54
|
+
* cached. */
|
|
55
|
+
removedVersions: string[];
|
|
56
|
+
/** Whether the installed_plugins.json record was removed. */
|
|
57
|
+
removedRecord: boolean;
|
|
58
|
+
}
|
|
59
|
+
/** Remove all cached versions of a plugin + drop its
|
|
60
|
+
* installed_plugins.json record. Leaves the data dir
|
|
61
|
+
* (`~/.x-code/plugins/data/<id>/`) intact so the user doesn't lose
|
|
62
|
+
* state if they reinstall later. */
|
|
63
|
+
export declare function uninstallPlugin(id: string): Promise<UninstallResult>;
|
|
64
|
+
//# sourceMappingURL=installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/plugins/installer.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAE,KAAK,cAAc,EAAwC,MAAM,cAAc,CAAA;AAIxF,OAAO,KAAK,EACV,qBAAqB,EAErB,cAAc,EACd,cAAc,EACd,WAAW,EACX,YAAY,EACb,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,KAAK,eAAe,EAAuB,MAAM,kBAAkB,CAAA;AAE5E,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,YAAY,CAAA;IACpB;;wEAEoE;IACpE,WAAW,EAAE,MAAM,CAAA;IACnB;uEACmE;IACnE,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB;;2BAEuB;IACvB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;yCAGqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;oEAGgE;IAChE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;IACjE;;;;;;;;4EAQwE;IACxE,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC,YAAY,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,IAAI,CAAC,CAAA;IAC5G,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,cAAc,CAAA;IACxB,cAAc,EAAE,cAAc,CAAA;IAC9B,MAAM,EAAE,qBAAqB,CAAA;CAC9B;AAED,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA6I/E;AA0ND,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAG7E;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAGhG;AAID,MAAM,WAAW,eAAe;IAC9B;kBACc;IACd,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,6DAA6D;IAC7D,aAAa,EAAE,OAAO,CAAA;CACvB;AAED;;;qCAGqC;AACrC,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAyB1E"}
|