@kolisachint/hoocode-agent 0.4.121 → 0.4.122
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 +2 -0
- package/dist/core/extensions/plugins/formats/shared.d.ts +16 -3
- package/dist/core/extensions/plugins/formats/shared.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/shared.js +26 -10
- package/dist/core/extensions/plugins/formats/shared.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -24,7 +24,8 @@ export interface RawManifest {
|
|
|
24
24
|
hooks?: PluginHooksConfig | {
|
|
25
25
|
hooks?: PluginHooksConfig;
|
|
26
26
|
};
|
|
27
|
-
|
|
27
|
+
/** Inline server map, or a path (Claude Code form, e.g. `"./.mcp.json"`) relative to the plugin root. */
|
|
28
|
+
mcpServers?: Record<string, unknown> | string;
|
|
28
29
|
/** Native-only. */
|
|
29
30
|
providers?: unknown;
|
|
30
31
|
}
|
|
@@ -40,8 +41,20 @@ export declare function resolveCapabilityDir(root: string, override: unknown, co
|
|
|
40
41
|
export declare function parseAuthor(author: RawManifest["author"]): string | undefined;
|
|
41
42
|
/** Accept either `{ hooks: {...} }` or a bare event map, falling back to `hooks/hooks.json`. */
|
|
42
43
|
export declare function normalizeHooks(raw: RawManifest["hooks"], root: string): PluginHooksConfig | undefined;
|
|
43
|
-
/**
|
|
44
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Resolve inline `mcpServers`, a manifest-supplied file path, or a `.mcp.json`
|
|
46
|
+
* file at `root`.
|
|
47
|
+
*
|
|
48
|
+
* `raw` may be:
|
|
49
|
+
* - a string path (Claude Code form: `"mcpServers": "./.mcp.json"`), resolved
|
|
50
|
+
* relative to the plugin root and read as a server file;
|
|
51
|
+
* - an inline server map (returned as-is);
|
|
52
|
+
* - undefined, falling back to `<root>/<mcpFileName>`.
|
|
53
|
+
*
|
|
54
|
+
* Server files use `{ mcpServers }` (Claude/native) or `{ servers }` (Code/Copilot);
|
|
55
|
+
* both keys are accepted.
|
|
56
|
+
*/
|
|
57
|
+
export declare function normalizeMcp(raw: Record<string, unknown> | string | undefined, root: string, mcpFileName?: string): Record<string, unknown> | undefined;
|
|
45
58
|
/** Serialize a small set of frontmatter fields to YAML. Values are strings only. */
|
|
46
59
|
export declare function emitFrontmatter(fields: Record<string, string | undefined>): string;
|
|
47
60
|
/** A markdown capability file: frontmatter block + body. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/plugins/formats/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,8FAA8F;AAC9F,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,gIAAgI;IAChI,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,iBAAiB,GAAG;QAAE,KAAK,CAAC,EAAE,iBAAiB,CAAA;KAAE,CAAC;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/plugins/formats/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,8FAA8F;AAC9F,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,gIAAgI;IAChI,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,iBAAiB,GAAG;QAAE,KAAK,CAAC,EAAE,iBAAiB,CAAA;KAAE,CAAC;IAC1D,yGAAyG;IACzG,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;IAC9C,mBAAmB;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAMlD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG1E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQ9G;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,GAAG,MAAM,GAAG,SAAS,CAE7E;AAED,gGAAgG;AAChG,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAmBrG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC3B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,EACjD,IAAI,EAAE,MAAM,EACZ,WAAW,SAAc,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAOrC;AAcD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,CAUlF;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7F;AAED,sFAAsF;AACtF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE/C;AAED,kGAAkG;AAClG,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWpF;AAED,+EAA+E;AAC/E,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMzC","sourcesContent":["/**\n * Shared, format-agnostic helpers used by the plugin format adapters.\n *\n * Kept deliberately free of any runtime dependency on `../manifest.js` (it only\n * imports *types* from there) so the adapter registry can be wired without a\n * module cycle: `manifest.ts → formats/index.ts → formats/<adapter>.ts →\n * shared.ts`, with the back-reference to manifest types erased at compile time.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { PluginHooksConfig } from \"../manifest.js\";\nimport type { AuthoredHook } from \"./types.js\";\n\n/** Raw manifest shape accepted by the `plugin.json`-style formats (agents/claude/copilot). */\nexport interface RawManifest {\n\tname?: string;\n\tversion?: string;\n\tdescription?: string;\n\tauthor?: string | { name?: string };\n\t/** Optional capability-dir override(s): a path (or list of paths) relative to the plugin root, e.g. `\"skills\": \"./skills/\"`. */\n\tskills?: unknown;\n\tcommands?: unknown;\n\tagents?: unknown;\n\tthemes?: unknown;\n\thooks?: PluginHooksConfig | { hooks?: PluginHooksConfig };\n\t/** Inline server map, or a path (Claude Code form, e.g. `\"./.mcp.json\"`) relative to the plugin root. */\n\tmcpServers?: Record<string, unknown> | string;\n\t/** Native-only. */\n\tproviders?: unknown;\n}\n\nexport function readJson<T>(file: string): T | null {\n\ttry {\n\t\treturn JSON.parse(fs.readFileSync(file, \"utf8\")) as T;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function dirIfExists(root: string, name: string): string | undefined {\n\tconst p = path.join(root, name);\n\treturn fs.existsSync(p) && fs.statSync(p).isDirectory() ? p : undefined;\n}\n\n/**\n * Resolve a capability directory: an explicit manifest override — a path (or\n * list of paths, first existing wins) relative to the plugin root, e.g.\n * `\"skills\": \"./skills/\"` — beats the conventional directory.\n */\nexport function resolveCapabilityDir(root: string, override: unknown, conventional: string): string | undefined {\n\tconst candidates = Array.isArray(override) ? override : [override];\n\tfor (const c of candidates) {\n\t\tif (typeof c !== \"string\" || !c.trim()) continue;\n\t\tconst p = path.resolve(root, c.trim());\n\t\tif (fs.existsSync(p) && fs.statSync(p).isDirectory()) return p;\n\t}\n\treturn dirIfExists(root, conventional);\n}\n\n/** Coerce an author field (string or `{ name }`) to a plain string. */\nexport function parseAuthor(author: RawManifest[\"author\"]): string | undefined {\n\treturn typeof author === \"string\" ? author : author?.name;\n}\n\n/** Accept either `{ hooks: {...} }` or a bare event map, falling back to `hooks/hooks.json`. */\nexport function normalizeHooks(raw: RawManifest[\"hooks\"], root: string): PluginHooksConfig | undefined {\n\tlet config: PluginHooksConfig | undefined;\n\tif (raw && typeof raw === \"object\") {\n\t\tconfig = \"hooks\" in raw && raw.hooks ? (raw.hooks as PluginHooksConfig) : (raw as PluginHooksConfig);\n\t}\n\t// Fall back to the conventional hooks/hooks.json file.\n\tif (!config) {\n\t\tconst hooksFile = path.join(root, \"hooks\", \"hooks.json\");\n\t\tif (fs.existsSync(hooksFile)) {\n\t\t\tconst fileRaw = readJson<RawManifest[\"hooks\"]>(hooksFile);\n\t\t\tif (fileRaw && typeof fileRaw === \"object\") {\n\t\t\t\tconfig =\n\t\t\t\t\t\"hooks\" in fileRaw && fileRaw.hooks\n\t\t\t\t\t\t? (fileRaw.hooks as PluginHooksConfig)\n\t\t\t\t\t\t: (fileRaw as PluginHooksConfig);\n\t\t\t}\n\t\t}\n\t}\n\treturn config && Object.keys(config).length > 0 ? config : undefined;\n}\n\n/**\n * Resolve inline `mcpServers`, a manifest-supplied file path, or a `.mcp.json`\n * file at `root`.\n *\n * `raw` may be:\n * - a string path (Claude Code form: `\"mcpServers\": \"./.mcp.json\"`), resolved\n * relative to the plugin root and read as a server file;\n * - an inline server map (returned as-is);\n * - undefined, falling back to `<root>/<mcpFileName>`.\n *\n * Server files use `{ mcpServers }` (Claude/native) or `{ servers }` (Code/Copilot);\n * both keys are accepted.\n */\nexport function normalizeMcp(\n\traw: Record<string, unknown> | string | undefined,\n\troot: string,\n\tmcpFileName = \".mcp.json\",\n): Record<string, unknown> | undefined {\n\t// Claude Code form: a path to a server file, relative to the plugin root.\n\tif (typeof raw === \"string\") {\n\t\treturn raw.trim() ? readMcpFile(path.resolve(root, raw.trim())) : undefined;\n\t}\n\tif (raw && Object.keys(raw).length > 0) return raw;\n\treturn readMcpFile(path.join(root, mcpFileName));\n}\n\n/** Read a server file, accepting both `{ mcpServers }` and `{ servers }` keys. */\nfunction readMcpFile(mcpFile: string): Record<string, unknown> | undefined {\n\tif (!fs.existsSync(mcpFile)) return undefined;\n\tconst fileRaw = readJson<{ mcpServers?: Record<string, unknown>; servers?: Record<string, unknown> }>(mcpFile);\n\tconst servers = fileRaw?.mcpServers ?? fileRaw?.servers;\n\treturn servers && Object.keys(servers).length > 0 ? servers : undefined;\n}\n\n// ============================================================================\n// Emit helpers (used by the writer / scaffolding half of each adapter)\n// ============================================================================\n\n/** Serialize a small set of frontmatter fields to YAML. Values are strings only. */\nexport function emitFrontmatter(fields: Record<string, string | undefined>): string {\n\tconst lines: string[] = [\"---\"];\n\tfor (const [key, value] of Object.entries(fields)) {\n\t\tif (value === undefined || value === \"\") continue;\n\t\t// Quote values that could be misparsed as YAML (contain a colon-space or start punctuation).\n\t\tconst needsQuote = /[:#]|^[\\s>|@`&*!%]/.test(value) || value.includes(\"\\n\");\n\t\tlines.push(`${key}: ${needsQuote ? JSON.stringify(value) : value}`);\n\t}\n\tlines.push(\"---\");\n\treturn lines.join(\"\\n\");\n}\n\n/** A markdown capability file: frontmatter block + body. */\nexport function emitMarkdown(fields: Record<string, string | undefined>, body: string): string {\n\treturn `${emitFrontmatter(fields)}\\n\\n${body.trimEnd()}\\n`;\n}\n\n/** Pretty-print a JSON manifest with a trailing newline (matches repo convention). */\nexport function emitJson(value: unknown): string {\n\treturn `${JSON.stringify(value, null, 2)}\\n`;\n}\n\n/** Convert authored hooks into the on-disk `hooks.json` event-map shape shared by all formats. */\nexport function authoredHooksToConfig(hooks: AuthoredHook[]): Record<string, unknown> {\n\tconst byEvent: Record<string, Array<{ matcher?: string; hooks: unknown[] }>> = {};\n\tfor (const h of hooks) {\n\t\tconst group = byEvent[h.event] ?? [];\n\t\tbyEvent[h.event] = group;\n\t\tgroup.push({\n\t\t\t...(h.matcher ? { matcher: h.matcher } : {}),\n\t\t\thooks: [{ type: \"command\", command: h.command, ...(h.timeout ? { timeout: h.timeout } : {}) }],\n\t\t});\n\t}\n\treturn byEvent;\n}\n\n/** Slug-safe filename component (no path separators, conservative charset). */\nexport function slug(name: string): string {\n\treturn name\n\t\t.trim()\n\t\t.replace(/[^a-zA-Z0-9._-]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\")\n\t\t.slice(0, 80);\n}\n"]}
|
|
@@ -61,19 +61,35 @@ export function normalizeHooks(raw, root) {
|
|
|
61
61
|
}
|
|
62
62
|
return config && Object.keys(config).length > 0 ? config : undefined;
|
|
63
63
|
}
|
|
64
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Resolve inline `mcpServers`, a manifest-supplied file path, or a `.mcp.json`
|
|
66
|
+
* file at `root`.
|
|
67
|
+
*
|
|
68
|
+
* `raw` may be:
|
|
69
|
+
* - a string path (Claude Code form: `"mcpServers": "./.mcp.json"`), resolved
|
|
70
|
+
* relative to the plugin root and read as a server file;
|
|
71
|
+
* - an inline server map (returned as-is);
|
|
72
|
+
* - undefined, falling back to `<root>/<mcpFileName>`.
|
|
73
|
+
*
|
|
74
|
+
* Server files use `{ mcpServers }` (Claude/native) or `{ servers }` (Code/Copilot);
|
|
75
|
+
* both keys are accepted.
|
|
76
|
+
*/
|
|
65
77
|
export function normalizeMcp(raw, root, mcpFileName = ".mcp.json") {
|
|
78
|
+
// Claude Code form: a path to a server file, relative to the plugin root.
|
|
79
|
+
if (typeof raw === "string") {
|
|
80
|
+
return raw.trim() ? readMcpFile(path.resolve(root, raw.trim())) : undefined;
|
|
81
|
+
}
|
|
66
82
|
if (raw && Object.keys(raw).length > 0)
|
|
67
83
|
return raw;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return undefined;
|
|
84
|
+
return readMcpFile(path.join(root, mcpFileName));
|
|
85
|
+
}
|
|
86
|
+
/** Read a server file, accepting both `{ mcpServers }` and `{ servers }` keys. */
|
|
87
|
+
function readMcpFile(mcpFile) {
|
|
88
|
+
if (!fs.existsSync(mcpFile))
|
|
89
|
+
return undefined;
|
|
90
|
+
const fileRaw = readJson(mcpFile);
|
|
91
|
+
const servers = fileRaw?.mcpServers ?? fileRaw?.servers;
|
|
92
|
+
return servers && Object.keys(servers).length > 0 ? servers : undefined;
|
|
77
93
|
}
|
|
78
94
|
// ============================================================================
|
|
79
95
|
// Emit helpers (used by the writer / scaffolding half of each adapter)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../../../src/core/extensions/plugins/formats/shared.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared, format-agnostic helpers used by the plugin format adapters.\n *\n * Kept deliberately free of any runtime dependency on `../manifest.js` (it only\n * imports *types* from there) so the adapter registry can be wired without a\n * module cycle: `manifest.ts → formats/index.ts → formats/<adapter>.ts →\n * shared.ts`, with the back-reference to manifest types erased at compile time.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { PluginHooksConfig } from \"../manifest.js\";\nimport type { AuthoredHook } from \"./types.js\";\n\n/** Raw manifest shape accepted by the `plugin.json`-style formats (agents/claude/copilot). */\nexport interface RawManifest {\n\tname?: string;\n\tversion?: string;\n\tdescription?: string;\n\tauthor?: string | { name?: string };\n\t/** Optional capability-dir override(s): a path (or list of paths) relative to the plugin root, e.g. `\"skills\": \"./skills/\"`. */\n\tskills?: unknown;\n\tcommands?: unknown;\n\tagents?: unknown;\n\tthemes?: unknown;\n\thooks?: PluginHooksConfig | { hooks?: PluginHooksConfig };\n\tmcpServers?: Record<string, unknown>;\n\t/** Native-only. */\n\tproviders?: unknown;\n}\n\nexport function readJson<T>(file: string): T | null {\n\ttry {\n\t\treturn JSON.parse(fs.readFileSync(file, \"utf8\")) as T;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function dirIfExists(root: string, name: string): string | undefined {\n\tconst p = path.join(root, name);\n\treturn fs.existsSync(p) && fs.statSync(p).isDirectory() ? p : undefined;\n}\n\n/**\n * Resolve a capability directory: an explicit manifest override — a path (or\n * list of paths, first existing wins) relative to the plugin root, e.g.\n * `\"skills\": \"./skills/\"` — beats the conventional directory.\n */\nexport function resolveCapabilityDir(root: string, override: unknown, conventional: string): string | undefined {\n\tconst candidates = Array.isArray(override) ? override : [override];\n\tfor (const c of candidates) {\n\t\tif (typeof c !== \"string\" || !c.trim()) continue;\n\t\tconst p = path.resolve(root, c.trim());\n\t\tif (fs.existsSync(p) && fs.statSync(p).isDirectory()) return p;\n\t}\n\treturn dirIfExists(root, conventional);\n}\n\n/** Coerce an author field (string or `{ name }`) to a plain string. */\nexport function parseAuthor(author: RawManifest[\"author\"]): string | undefined {\n\treturn typeof author === \"string\" ? author : author?.name;\n}\n\n/** Accept either `{ hooks: {...} }` or a bare event map, falling back to `hooks/hooks.json`. */\nexport function normalizeHooks(raw: RawManifest[\"hooks\"], root: string): PluginHooksConfig | undefined {\n\tlet config: PluginHooksConfig | undefined;\n\tif (raw && typeof raw === \"object\") {\n\t\tconfig = \"hooks\" in raw && raw.hooks ? (raw.hooks as PluginHooksConfig) : (raw as PluginHooksConfig);\n\t}\n\t// Fall back to the conventional hooks/hooks.json file.\n\tif (!config) {\n\t\tconst hooksFile = path.join(root, \"hooks\", \"hooks.json\");\n\t\tif (fs.existsSync(hooksFile)) {\n\t\t\tconst fileRaw = readJson<RawManifest[\"hooks\"]>(hooksFile);\n\t\t\tif (fileRaw && typeof fileRaw === \"object\") {\n\t\t\t\tconfig =\n\t\t\t\t\t\"hooks\" in fileRaw && fileRaw.hooks\n\t\t\t\t\t\t? (fileRaw.hooks as PluginHooksConfig)\n\t\t\t\t\t\t: (fileRaw as PluginHooksConfig);\n\t\t\t}\n\t\t}\n\t}\n\treturn config && Object.keys(config).length > 0 ? config : undefined;\n}\n\n/** Read inline `mcpServers`, falling back to a `.mcp.json` file at `root`. */\nexport function normalizeMcp(\n\traw: Record<string, unknown> | undefined,\n\troot: string,\n\tmcpFileName = \".mcp.json\",\n): Record<string, unknown> | undefined {\n\tif (raw && Object.keys(raw).length > 0) return raw;\n\tconst mcpFile = path.join(root, mcpFileName);\n\tif (fs.existsSync(mcpFile)) {\n\t\t// VS Code / Copilot use `{ servers }`; Claude/native use `{ mcpServers }`. Accept both.\n\t\tconst fileRaw = readJson<{ mcpServers?: Record<string, unknown>; servers?: Record<string, unknown> }>(mcpFile);\n\t\tconst servers = fileRaw?.mcpServers ?? fileRaw?.servers;\n\t\tif (servers && Object.keys(servers).length > 0) return servers;\n\t}\n\treturn undefined;\n}\n\n// ============================================================================\n// Emit helpers (used by the writer / scaffolding half of each adapter)\n// ============================================================================\n\n/** Serialize a small set of frontmatter fields to YAML. Values are strings only. */\nexport function emitFrontmatter(fields: Record<string, string | undefined>): string {\n\tconst lines: string[] = [\"---\"];\n\tfor (const [key, value] of Object.entries(fields)) {\n\t\tif (value === undefined || value === \"\") continue;\n\t\t// Quote values that could be misparsed as YAML (contain a colon-space or start punctuation).\n\t\tconst needsQuote = /[:#]|^[\\s>|@`&*!%]/.test(value) || value.includes(\"\\n\");\n\t\tlines.push(`${key}: ${needsQuote ? JSON.stringify(value) : value}`);\n\t}\n\tlines.push(\"---\");\n\treturn lines.join(\"\\n\");\n}\n\n/** A markdown capability file: frontmatter block + body. */\nexport function emitMarkdown(fields: Record<string, string | undefined>, body: string): string {\n\treturn `${emitFrontmatter(fields)}\\n\\n${body.trimEnd()}\\n`;\n}\n\n/** Pretty-print a JSON manifest with a trailing newline (matches repo convention). */\nexport function emitJson(value: unknown): string {\n\treturn `${JSON.stringify(value, null, 2)}\\n`;\n}\n\n/** Convert authored hooks into the on-disk `hooks.json` event-map shape shared by all formats. */\nexport function authoredHooksToConfig(hooks: AuthoredHook[]): Record<string, unknown> {\n\tconst byEvent: Record<string, Array<{ matcher?: string; hooks: unknown[] }>> = {};\n\tfor (const h of hooks) {\n\t\tconst group = byEvent[h.event] ?? [];\n\t\tbyEvent[h.event] = group;\n\t\tgroup.push({\n\t\t\t...(h.matcher ? { matcher: h.matcher } : {}),\n\t\t\thooks: [{ type: \"command\", command: h.command, ...(h.timeout ? { timeout: h.timeout } : {}) }],\n\t\t});\n\t}\n\treturn byEvent;\n}\n\n/** Slug-safe filename component (no path separators, conservative charset). */\nexport function slug(name: string): string {\n\treturn name\n\t\t.trim()\n\t\t.replace(/[^a-zA-Z0-9._-]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\")\n\t\t.slice(0, 80);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../../../src/core/extensions/plugins/formats/shared.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared, format-agnostic helpers used by the plugin format adapters.\n *\n * Kept deliberately free of any runtime dependency on `../manifest.js` (it only\n * imports *types* from there) so the adapter registry can be wired without a\n * module cycle: `manifest.ts → formats/index.ts → formats/<adapter>.ts →\n * shared.ts`, with the back-reference to manifest types erased at compile time.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { PluginHooksConfig } from \"../manifest.js\";\nimport type { AuthoredHook } from \"./types.js\";\n\n/** Raw manifest shape accepted by the `plugin.json`-style formats (agents/claude/copilot). */\nexport interface RawManifest {\n\tname?: string;\n\tversion?: string;\n\tdescription?: string;\n\tauthor?: string | { name?: string };\n\t/** Optional capability-dir override(s): a path (or list of paths) relative to the plugin root, e.g. `\"skills\": \"./skills/\"`. */\n\tskills?: unknown;\n\tcommands?: unknown;\n\tagents?: unknown;\n\tthemes?: unknown;\n\thooks?: PluginHooksConfig | { hooks?: PluginHooksConfig };\n\t/** Inline server map, or a path (Claude Code form, e.g. `\"./.mcp.json\"`) relative to the plugin root. */\n\tmcpServers?: Record<string, unknown> | string;\n\t/** Native-only. */\n\tproviders?: unknown;\n}\n\nexport function readJson<T>(file: string): T | null {\n\ttry {\n\t\treturn JSON.parse(fs.readFileSync(file, \"utf8\")) as T;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function dirIfExists(root: string, name: string): string | undefined {\n\tconst p = path.join(root, name);\n\treturn fs.existsSync(p) && fs.statSync(p).isDirectory() ? p : undefined;\n}\n\n/**\n * Resolve a capability directory: an explicit manifest override — a path (or\n * list of paths, first existing wins) relative to the plugin root, e.g.\n * `\"skills\": \"./skills/\"` — beats the conventional directory.\n */\nexport function resolveCapabilityDir(root: string, override: unknown, conventional: string): string | undefined {\n\tconst candidates = Array.isArray(override) ? override : [override];\n\tfor (const c of candidates) {\n\t\tif (typeof c !== \"string\" || !c.trim()) continue;\n\t\tconst p = path.resolve(root, c.trim());\n\t\tif (fs.existsSync(p) && fs.statSync(p).isDirectory()) return p;\n\t}\n\treturn dirIfExists(root, conventional);\n}\n\n/** Coerce an author field (string or `{ name }`) to a plain string. */\nexport function parseAuthor(author: RawManifest[\"author\"]): string | undefined {\n\treturn typeof author === \"string\" ? author : author?.name;\n}\n\n/** Accept either `{ hooks: {...} }` or a bare event map, falling back to `hooks/hooks.json`. */\nexport function normalizeHooks(raw: RawManifest[\"hooks\"], root: string): PluginHooksConfig | undefined {\n\tlet config: PluginHooksConfig | undefined;\n\tif (raw && typeof raw === \"object\") {\n\t\tconfig = \"hooks\" in raw && raw.hooks ? (raw.hooks as PluginHooksConfig) : (raw as PluginHooksConfig);\n\t}\n\t// Fall back to the conventional hooks/hooks.json file.\n\tif (!config) {\n\t\tconst hooksFile = path.join(root, \"hooks\", \"hooks.json\");\n\t\tif (fs.existsSync(hooksFile)) {\n\t\t\tconst fileRaw = readJson<RawManifest[\"hooks\"]>(hooksFile);\n\t\t\tif (fileRaw && typeof fileRaw === \"object\") {\n\t\t\t\tconfig =\n\t\t\t\t\t\"hooks\" in fileRaw && fileRaw.hooks\n\t\t\t\t\t\t? (fileRaw.hooks as PluginHooksConfig)\n\t\t\t\t\t\t: (fileRaw as PluginHooksConfig);\n\t\t\t}\n\t\t}\n\t}\n\treturn config && Object.keys(config).length > 0 ? config : undefined;\n}\n\n/**\n * Resolve inline `mcpServers`, a manifest-supplied file path, or a `.mcp.json`\n * file at `root`.\n *\n * `raw` may be:\n * - a string path (Claude Code form: `\"mcpServers\": \"./.mcp.json\"`), resolved\n * relative to the plugin root and read as a server file;\n * - an inline server map (returned as-is);\n * - undefined, falling back to `<root>/<mcpFileName>`.\n *\n * Server files use `{ mcpServers }` (Claude/native) or `{ servers }` (Code/Copilot);\n * both keys are accepted.\n */\nexport function normalizeMcp(\n\traw: Record<string, unknown> | string | undefined,\n\troot: string,\n\tmcpFileName = \".mcp.json\",\n): Record<string, unknown> | undefined {\n\t// Claude Code form: a path to a server file, relative to the plugin root.\n\tif (typeof raw === \"string\") {\n\t\treturn raw.trim() ? readMcpFile(path.resolve(root, raw.trim())) : undefined;\n\t}\n\tif (raw && Object.keys(raw).length > 0) return raw;\n\treturn readMcpFile(path.join(root, mcpFileName));\n}\n\n/** Read a server file, accepting both `{ mcpServers }` and `{ servers }` keys. */\nfunction readMcpFile(mcpFile: string): Record<string, unknown> | undefined {\n\tif (!fs.existsSync(mcpFile)) return undefined;\n\tconst fileRaw = readJson<{ mcpServers?: Record<string, unknown>; servers?: Record<string, unknown> }>(mcpFile);\n\tconst servers = fileRaw?.mcpServers ?? fileRaw?.servers;\n\treturn servers && Object.keys(servers).length > 0 ? servers : undefined;\n}\n\n// ============================================================================\n// Emit helpers (used by the writer / scaffolding half of each adapter)\n// ============================================================================\n\n/** Serialize a small set of frontmatter fields to YAML. Values are strings only. */\nexport function emitFrontmatter(fields: Record<string, string | undefined>): string {\n\tconst lines: string[] = [\"---\"];\n\tfor (const [key, value] of Object.entries(fields)) {\n\t\tif (value === undefined || value === \"\") continue;\n\t\t// Quote values that could be misparsed as YAML (contain a colon-space or start punctuation).\n\t\tconst needsQuote = /[:#]|^[\\s>|@`&*!%]/.test(value) || value.includes(\"\\n\");\n\t\tlines.push(`${key}: ${needsQuote ? JSON.stringify(value) : value}`);\n\t}\n\tlines.push(\"---\");\n\treturn lines.join(\"\\n\");\n}\n\n/** A markdown capability file: frontmatter block + body. */\nexport function emitMarkdown(fields: Record<string, string | undefined>, body: string): string {\n\treturn `${emitFrontmatter(fields)}\\n\\n${body.trimEnd()}\\n`;\n}\n\n/** Pretty-print a JSON manifest with a trailing newline (matches repo convention). */\nexport function emitJson(value: unknown): string {\n\treturn `${JSON.stringify(value, null, 2)}\\n`;\n}\n\n/** Convert authored hooks into the on-disk `hooks.json` event-map shape shared by all formats. */\nexport function authoredHooksToConfig(hooks: AuthoredHook[]): Record<string, unknown> {\n\tconst byEvent: Record<string, Array<{ matcher?: string; hooks: unknown[] }>> = {};\n\tfor (const h of hooks) {\n\t\tconst group = byEvent[h.event] ?? [];\n\t\tbyEvent[h.event] = group;\n\t\tgroup.push({\n\t\t\t...(h.matcher ? { matcher: h.matcher } : {}),\n\t\t\thooks: [{ type: \"command\", command: h.command, ...(h.timeout ? { timeout: h.timeout } : {}) }],\n\t\t});\n\t}\n\treturn byEvent;\n}\n\n/** Slug-safe filename component (no path separators, conservative charset). */\nexport function slug(name: string): string {\n\treturn name\n\t\t.trim()\n\t\t.replace(/[^a-zA-Z0-9._-]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\")\n\t\t.slice(0, 80);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolisachint/hoocode-agent",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.122",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"hoocodeConfig": {
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"prepublishOnly": "npm run clean && npm run build"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@kolisachint/hoocode-agent-core": "^0.4.
|
|
49
|
-
"@kolisachint/hoocode-ai": "^0.4.
|
|
50
|
-
"@kolisachint/hoocode-tui": "^0.4.
|
|
48
|
+
"@kolisachint/hoocode-agent-core": "^0.4.122",
|
|
49
|
+
"@kolisachint/hoocode-ai": "^0.4.122",
|
|
50
|
+
"@kolisachint/hoocode-tui": "^0.4.122",
|
|
51
51
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
|
52
52
|
"chalk": "^5.5.0",
|
|
53
53
|
"cli-highlight": "^2.1.11",
|