oh-my-claude-sisyphus 3.8.12 → 3.8.14
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/commands/omc-setup.md +45 -9
- package/dist/__tests__/mnemosyne/finder.test.js +44 -0
- package/dist/__tests__/mnemosyne/finder.test.js.map +1 -1
- package/dist/__tests__/omc-tools-server.test.js +15 -6
- package/dist/__tests__/omc-tools-server.test.js.map +1 -1
- package/dist/__tests__/task-continuation.test.js +5 -2
- package/dist/__tests__/task-continuation.test.js.map +1 -1
- package/dist/__tests__/tools/skills-tools.test.d.ts +2 -0
- package/dist/__tests__/tools/skills-tools.test.d.ts.map +1 -0
- package/dist/__tests__/tools/skills-tools.test.js +63 -0
- package/dist/__tests__/tools/skills-tools.test.js.map +1 -0
- package/dist/hooks/__tests__/bridge-pkill.test.d.ts +8 -0
- package/dist/hooks/__tests__/bridge-pkill.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/bridge-pkill.test.js +188 -0
- package/dist/hooks/__tests__/bridge-pkill.test.js.map +1 -0
- package/dist/hooks/bridge.d.ts.map +1 -1
- package/dist/hooks/bridge.js +17 -0
- package/dist/hooks/bridge.js.map +1 -1
- package/dist/hooks/clear-suggestions/index.d.ts.map +1 -1
- package/dist/hooks/clear-suggestions/index.js +6 -0
- package/dist/hooks/clear-suggestions/index.js.map +1 -1
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +0 -3
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/learner/bridge.d.ts +7 -2
- package/dist/hooks/learner/bridge.d.ts.map +1 -1
- package/dist/hooks/learner/bridge.js +59 -30
- package/dist/hooks/learner/bridge.js.map +1 -1
- package/dist/hooks/learner/constants.d.ts +5 -1
- package/dist/hooks/learner/constants.d.ts.map +1 -1
- package/dist/hooks/learner/constants.js +5 -1
- package/dist/hooks/learner/constants.js.map +1 -1
- package/dist/hooks/learner/finder.d.ts +4 -2
- package/dist/hooks/learner/finder.d.ts.map +1 -1
- package/dist/hooks/learner/finder.js +58 -23
- package/dist/hooks/learner/finder.js.map +1 -1
- package/dist/hooks/learner/loader.d.ts.map +1 -1
- package/dist/hooks/learner/loader.js +3 -4
- package/dist/hooks/learner/loader.js.map +1 -1
- package/dist/hooks/learner/types.d.ts +3 -1
- package/dist/hooks/learner/types.d.ts.map +1 -1
- package/dist/hooks/mode-registry/index.d.ts +7 -0
- package/dist/hooks/mode-registry/index.d.ts.map +1 -1
- package/dist/hooks/mode-registry/index.js +9 -0
- package/dist/hooks/mode-registry/index.js.map +1 -1
- package/dist/hooks/skill-bridge.cjs +50 -27
- package/dist/hooks/todo-continuation/__tests__/isUserAbort.test.d.ts +2 -0
- package/dist/hooks/todo-continuation/__tests__/isUserAbort.test.d.ts.map +1 -0
- package/dist/hooks/todo-continuation/__tests__/isUserAbort.test.js +119 -0
- package/dist/hooks/todo-continuation/__tests__/isUserAbort.test.js.map +1 -0
- package/dist/hooks/todo-continuation/index.d.ts.map +1 -1
- package/dist/hooks/todo-continuation/index.js +6 -12
- package/dist/hooks/todo-continuation/index.js.map +1 -1
- package/dist/hud/usage-api.d.ts.map +1 -1
- package/dist/hud/usage-api.js +148 -3
- package/dist/hud/usage-api.js.map +1 -1
- package/dist/mcp/omc-tools-server.d.ts +2 -1
- package/dist/mcp/omc-tools-server.d.ts.map +1 -1
- package/dist/mcp/omc-tools-server.js +7 -3
- package/dist/mcp/omc-tools-server.js.map +1 -1
- package/dist/tools/skills-tools.d.ts +75 -0
- package/dist/tools/skills-tools.d.ts.map +1 -0
- package/dist/tools/skills-tools.js +151 -0
- package/dist/tools/skills-tools.js.map +1 -0
- package/package.json +1 -1
- package/scripts/persistent-mode.mjs +7 -5
- package/scripts/post-tool-verifier.mjs +1 -36
- package/scripts/skill-injector.mjs +21 -17
- package/skills/cancel/SKILL.md +1 -1
- package/templates/hooks/persistent-mode.mjs +7 -5
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OMC Tools Server - In-process MCP server for custom tools
|
|
3
3
|
*
|
|
4
|
-
* Exposes
|
|
4
|
+
* Exposes 18 custom tools (12 LSP, 2 AST, 1 python_repl, 3 skills) via the Claude Agent SDK's
|
|
5
5
|
* createSdkMcpServer helper for use by subagents.
|
|
6
6
|
*/
|
|
7
7
|
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
8
8
|
import { lspTools } from "../tools/lsp-tools.js";
|
|
9
9
|
import { astTools } from "../tools/ast-tools.js";
|
|
10
10
|
import { pythonReplTool } from "../tools/python-repl/index.js";
|
|
11
|
+
import { skillsTools } from "../tools/skills-tools.js";
|
|
11
12
|
// Aggregate all custom tools
|
|
12
13
|
const allTools = [
|
|
13
14
|
...lspTools,
|
|
14
15
|
...astTools,
|
|
15
|
-
pythonReplTool
|
|
16
|
+
pythonReplTool,
|
|
17
|
+
...skillsTools
|
|
16
18
|
];
|
|
17
19
|
// Convert to SDK tool format
|
|
18
20
|
// The SDK's tool() expects a ZodRawShape directly (not wrapped in z.object())
|
|
@@ -35,7 +37,7 @@ export const omcToolNames = allTools.map(t => `mcp__omc-tools__${t.name}`);
|
|
|
35
37
|
* Get tool names filtered by category
|
|
36
38
|
*/
|
|
37
39
|
export function getOmcToolNames(options) {
|
|
38
|
-
const { includeLsp = true, includeAst = true, includePython = true } = options || {};
|
|
40
|
+
const { includeLsp = true, includeAst = true, includePython = true, includeSkills = true } = options || {};
|
|
39
41
|
return omcToolNames.filter(name => {
|
|
40
42
|
if (!includeLsp && name.includes('lsp_'))
|
|
41
43
|
return false;
|
|
@@ -43,6 +45,8 @@ export function getOmcToolNames(options) {
|
|
|
43
45
|
return false;
|
|
44
46
|
if (!includePython && name.includes('python_repl'))
|
|
45
47
|
return false;
|
|
48
|
+
if (!includeSkills && (name.includes('load_omc_skills') || name.includes('list_omc_skills')))
|
|
49
|
+
return false;
|
|
46
50
|
return true;
|
|
47
51
|
});
|
|
48
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"omc-tools-server.js","sourceRoot":"","sources":["../../src/mcp/omc-tools-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"omc-tools-server.js","sourceRoot":"","sources":["../../src/mcp/omc-tools-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAUvD,6BAA6B;AAC7B,MAAM,QAAQ,GAAc;IAC1B,GAAI,QAAiC;IACrC,GAAI,QAAiC;IACrC,cAAoC;IACpC,GAAI,WAAoC;CACzC,CAAC;AAEF,6BAA6B;AAC7B,8EAA8E;AAC9E,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAChC,IAAI,CACF,CAAC,CAAC,IAAI,EACN,CAAC,CAAC,WAAW,EACb,CAAC,CAAC,MAAoC,EACtC,KAAK,EAAE,IAAa,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAC/C,CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,kBAAkB,CAAC;IAC/C,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,OAAO;IAChB,KAAK,EAAE,QAAQ;CAChB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAE3E;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAK/B;IACC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,UAAU,GAAG,IAAI,EAAE,aAAa,GAAG,IAAI,EAAE,aAAa,GAAG,IAAI,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;IAE3G,OAAO,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;QAChC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;QACvD,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;QACvD,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;YAAE,OAAO,KAAK,CAAC;QACjE,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAC3G,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills Tools
|
|
3
|
+
*
|
|
4
|
+
* MCP tools for loading and listing OMC learned skills
|
|
5
|
+
* from local (.omc/skills/) and global (~/.omc/skills/) directories.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
export declare const loadLocalTool: {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
schema: {
|
|
12
|
+
projectRoot: z.ZodOptional<z.ZodString>;
|
|
13
|
+
};
|
|
14
|
+
handler: (args: {
|
|
15
|
+
projectRoot?: string;
|
|
16
|
+
}) => Promise<{
|
|
17
|
+
content: {
|
|
18
|
+
type: "text";
|
|
19
|
+
text: string;
|
|
20
|
+
}[];
|
|
21
|
+
}>;
|
|
22
|
+
};
|
|
23
|
+
export declare const loadGlobalTool: {
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
schema: {};
|
|
27
|
+
handler: (_args: Record<string, never>) => Promise<{
|
|
28
|
+
content: {
|
|
29
|
+
type: "text";
|
|
30
|
+
text: string;
|
|
31
|
+
}[];
|
|
32
|
+
}>;
|
|
33
|
+
};
|
|
34
|
+
export declare const listSkillsTool: {
|
|
35
|
+
name: string;
|
|
36
|
+
description: string;
|
|
37
|
+
schema: {
|
|
38
|
+
projectRoot: z.ZodOptional<z.ZodString>;
|
|
39
|
+
};
|
|
40
|
+
handler: (args: {
|
|
41
|
+
projectRoot?: string;
|
|
42
|
+
}) => Promise<{
|
|
43
|
+
content: {
|
|
44
|
+
type: "text";
|
|
45
|
+
text: string;
|
|
46
|
+
}[];
|
|
47
|
+
}>;
|
|
48
|
+
};
|
|
49
|
+
/** All skills tools for registration in omc-tools-server */
|
|
50
|
+
export declare const skillsTools: ({
|
|
51
|
+
name: string;
|
|
52
|
+
description: string;
|
|
53
|
+
schema: {
|
|
54
|
+
projectRoot: z.ZodOptional<z.ZodString>;
|
|
55
|
+
};
|
|
56
|
+
handler: (args: {
|
|
57
|
+
projectRoot?: string;
|
|
58
|
+
}) => Promise<{
|
|
59
|
+
content: {
|
|
60
|
+
type: "text";
|
|
61
|
+
text: string;
|
|
62
|
+
}[];
|
|
63
|
+
}>;
|
|
64
|
+
} | {
|
|
65
|
+
name: string;
|
|
66
|
+
description: string;
|
|
67
|
+
schema: {};
|
|
68
|
+
handler: (_args: Record<string, never>) => Promise<{
|
|
69
|
+
content: {
|
|
70
|
+
type: "text";
|
|
71
|
+
text: string;
|
|
72
|
+
}[];
|
|
73
|
+
}>;
|
|
74
|
+
})[];
|
|
75
|
+
//# sourceMappingURL=skills-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-tools.d.ts","sourceRoot":"","sources":["../../src/tools/skills-tools.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+FxB,eAAO,MAAM,aAAa;;;;;;oBAIF;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;CAY/C,CAAC;AAGF,eAAO,MAAM,cAAc;;;;qBAIF,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;;;;;;CAW7C,CAAC;AAGF,eAAO,MAAM,cAAc;;;;;;oBAIH;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;CA2B/C,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,WAAW;;;;;;oBAnEA;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;qBAmBvB,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;;;;;;IAgD4B,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills Tools
|
|
3
|
+
*
|
|
4
|
+
* MCP tools for loading and listing OMC learned skills
|
|
5
|
+
* from local (.omc/skills/) and global (~/.omc/skills/) directories.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { resolve, normalize, sep } from 'path';
|
|
9
|
+
import { homedir } from 'os';
|
|
10
|
+
import { loadAllSkills } from '../hooks/learner/loader.js';
|
|
11
|
+
import { MAX_SKILL_CONTENT_LENGTH } from '../hooks/learner/constants.js';
|
|
12
|
+
/** Allowed boundary directories for projectRoot validation */
|
|
13
|
+
const ALLOWED_BOUNDARIES = [process.cwd(), homedir()];
|
|
14
|
+
/** Role boundary tags that could be used for prompt injection */
|
|
15
|
+
const ROLE_BOUNDARY_PATTERN = /^<\s*\/?\s*(system|human|assistant|user|tool_use|tool_result)\b[^>]*>/i;
|
|
16
|
+
/**
|
|
17
|
+
* Validate projectRoot is within allowed directories.
|
|
18
|
+
* Prevents path traversal attacks.
|
|
19
|
+
*/
|
|
20
|
+
function validateProjectRoot(input) {
|
|
21
|
+
const normalized = normalize(resolve(input));
|
|
22
|
+
// Reject path traversal sequences in raw input
|
|
23
|
+
if (input.includes('..')) {
|
|
24
|
+
throw new Error('Invalid project root: path traversal not allowed');
|
|
25
|
+
}
|
|
26
|
+
// Positive boundary validation: resolved path must be under cwd or HOME
|
|
27
|
+
const isWithinAllowed = ALLOWED_BOUNDARIES.some(boundary => {
|
|
28
|
+
const normalizedBoundary = normalize(boundary);
|
|
29
|
+
return normalized === normalizedBoundary ||
|
|
30
|
+
normalized.startsWith(normalizedBoundary + sep);
|
|
31
|
+
});
|
|
32
|
+
if (!isWithinAllowed) {
|
|
33
|
+
throw new Error('Invalid project root: path is outside allowed directories');
|
|
34
|
+
}
|
|
35
|
+
return normalized;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Sanitize skill content to prevent prompt injection.
|
|
39
|
+
*/
|
|
40
|
+
function sanitizeSkillContent(content) {
|
|
41
|
+
// Truncate to max length
|
|
42
|
+
const truncated = content.length > MAX_SKILL_CONTENT_LENGTH
|
|
43
|
+
? content.slice(0, MAX_SKILL_CONTENT_LENGTH) + '\n[truncated]'
|
|
44
|
+
: content;
|
|
45
|
+
// Strip role boundary tags
|
|
46
|
+
return truncated
|
|
47
|
+
.split('\n')
|
|
48
|
+
.filter(line => !ROLE_BOUNDARY_PATTERN.test(line.trim()))
|
|
49
|
+
.join('\n');
|
|
50
|
+
}
|
|
51
|
+
// Schema definitions
|
|
52
|
+
const loadLocalSchema = {
|
|
53
|
+
projectRoot: z.string()
|
|
54
|
+
.max(500)
|
|
55
|
+
.optional()
|
|
56
|
+
.describe('Project root directory (defaults to cwd)'),
|
|
57
|
+
};
|
|
58
|
+
// Empty ZodRawShape: SDK expects plain object of z-types; {} means no parameters
|
|
59
|
+
const loadGlobalSchema = {};
|
|
60
|
+
const listSkillsSchema = {
|
|
61
|
+
projectRoot: z.string()
|
|
62
|
+
.max(500)
|
|
63
|
+
.optional()
|
|
64
|
+
.describe('Project root directory (defaults to cwd)'),
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Format skills into readable markdown output.
|
|
68
|
+
*/
|
|
69
|
+
function formatSkillOutput(skills) {
|
|
70
|
+
if (skills.length === 0) {
|
|
71
|
+
return 'No skills found in the searched directories.';
|
|
72
|
+
}
|
|
73
|
+
const lines = [];
|
|
74
|
+
for (const skill of skills) {
|
|
75
|
+
lines.push(`### ${skill.metadata.id}`);
|
|
76
|
+
lines.push(`- **Name:** ${skill.metadata.name}`);
|
|
77
|
+
lines.push(`- **Description:** ${skill.metadata.description}`);
|
|
78
|
+
lines.push(`- **Triggers:** ${skill.metadata.triggers.join(', ')}`);
|
|
79
|
+
if (skill.metadata.tags?.length) {
|
|
80
|
+
lines.push(`- **Tags:** ${skill.metadata.tags.join(', ')}`);
|
|
81
|
+
}
|
|
82
|
+
lines.push(`- **Scope:** ${skill.scope}`);
|
|
83
|
+
lines.push(`- **Path:** ${skill.relativePath}`);
|
|
84
|
+
lines.push('');
|
|
85
|
+
}
|
|
86
|
+
return lines.join('\n');
|
|
87
|
+
}
|
|
88
|
+
// Tool 1: load_omc_skills_local
|
|
89
|
+
export const loadLocalTool = {
|
|
90
|
+
name: 'load_omc_skills_local',
|
|
91
|
+
description: 'Load and list skills from the project-local .omc/skills/ directory. Returns skill metadata (id, name, description, triggers, tags) for all discovered project-scoped skills.',
|
|
92
|
+
schema: loadLocalSchema,
|
|
93
|
+
handler: async (args) => {
|
|
94
|
+
const projectRoot = args.projectRoot ? validateProjectRoot(args.projectRoot) : process.cwd();
|
|
95
|
+
const allSkills = loadAllSkills(projectRoot);
|
|
96
|
+
const projectSkills = allSkills.filter(s => s.scope === 'project');
|
|
97
|
+
return {
|
|
98
|
+
content: [{
|
|
99
|
+
type: 'text',
|
|
100
|
+
text: `## Project Skills (${projectSkills.length})\n\n${formatSkillOutput(projectSkills)}`,
|
|
101
|
+
}],
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
// Tool 2: load_omc_skills_global
|
|
106
|
+
export const loadGlobalTool = {
|
|
107
|
+
name: 'load_omc_skills_global',
|
|
108
|
+
description: 'Load and list skills from global user directories (~/.omc/skills/ and ~/.claude/skills/omc-learned/). Returns skill metadata for all discovered user-scoped skills.',
|
|
109
|
+
schema: loadGlobalSchema,
|
|
110
|
+
handler: async (_args) => {
|
|
111
|
+
const allSkills = loadAllSkills(null);
|
|
112
|
+
const userSkills = allSkills.filter(s => s.scope === 'user');
|
|
113
|
+
return {
|
|
114
|
+
content: [{
|
|
115
|
+
type: 'text',
|
|
116
|
+
text: `## Global User Skills (${userSkills.length})\n\n${formatSkillOutput(userSkills)}`,
|
|
117
|
+
}],
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
// Tool 3: list_omc_skills
|
|
122
|
+
export const listSkillsTool = {
|
|
123
|
+
name: 'list_omc_skills',
|
|
124
|
+
description: 'List all available skills (both project-local and global user skills). Project skills take priority over user skills with the same ID.',
|
|
125
|
+
schema: listSkillsSchema,
|
|
126
|
+
handler: async (args) => {
|
|
127
|
+
const projectRoot = args.projectRoot ? validateProjectRoot(args.projectRoot) : process.cwd();
|
|
128
|
+
const skills = loadAllSkills(projectRoot);
|
|
129
|
+
const projectSkills = skills.filter(s => s.scope === 'project');
|
|
130
|
+
const userSkills = skills.filter(s => s.scope === 'user');
|
|
131
|
+
let output = `## All Available Skills (${skills.length} total)\n\n`;
|
|
132
|
+
if (projectSkills.length > 0) {
|
|
133
|
+
output += `### Project Skills (${projectSkills.length})\n\n${formatSkillOutput(projectSkills)}\n`;
|
|
134
|
+
}
|
|
135
|
+
if (userSkills.length > 0) {
|
|
136
|
+
output += `### User Skills (${userSkills.length})\n\n${formatSkillOutput(userSkills)}`;
|
|
137
|
+
}
|
|
138
|
+
if (skills.length === 0) {
|
|
139
|
+
output = '## No Skills Found\n\nNo skill files were discovered in any searched directories.\n\nSearched:\n- Project: .omc/skills/\n- Global: ~/.omc/skills/\n- Legacy: ~/.claude/skills/omc-learned/';
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
content: [{
|
|
143
|
+
type: 'text',
|
|
144
|
+
text: output,
|
|
145
|
+
}],
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
/** All skills tools for registration in omc-tools-server */
|
|
150
|
+
export const skillsTools = [loadLocalTool, loadGlobalTool, listSkillsTool];
|
|
151
|
+
//# sourceMappingURL=skills-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-tools.js","sourceRoot":"","sources":["../../src/tools/skills-tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -155,11 +155,13 @@ function isUserAbort(data) {
|
|
|
155
155
|
if (data.user_requested || data.userRequested) return true;
|
|
156
156
|
|
|
157
157
|
const reason = (data.stop_reason || data.stopReason || '').toLowerCase();
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
];
|
|
162
|
-
|
|
158
|
+
// Exact-match patterns: short generic words that cause false positives with .includes()
|
|
159
|
+
const exactPatterns = ['aborted', 'abort', 'cancel', 'interrupt'];
|
|
160
|
+
// Substring patterns: compound words safe for .includes() matching
|
|
161
|
+
const substringPatterns = ['user_cancel', 'user_interrupt', 'ctrl_c', 'manual_stop'];
|
|
162
|
+
|
|
163
|
+
return exactPatterns.some(p => reason === p) ||
|
|
164
|
+
substringPatterns.some(p => reason.includes(p));
|
|
163
165
|
}
|
|
164
166
|
|
|
165
167
|
async function main() {
|
|
@@ -15,7 +15,6 @@ import { fileURLToPath } from 'url';
|
|
|
15
15
|
const __filename = fileURLToPath(import.meta.url);
|
|
16
16
|
const __dirname = dirname(__filename);
|
|
17
17
|
const distDir = join(__dirname, '..', 'dist', 'hooks', 'notepad');
|
|
18
|
-
const clearSuggestionsDistDir = join(__dirname, '..', 'dist', 'hooks', 'clear-suggestions');
|
|
19
18
|
|
|
20
19
|
// Try to import notepad functions (may fail if not built)
|
|
21
20
|
let setPriorityContext = null;
|
|
@@ -28,15 +27,6 @@ try {
|
|
|
28
27
|
// Notepad module not available - remember tags will be silently ignored
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
// Try to import clear suggestions functions (may fail if not built)
|
|
32
|
-
let checkClearSuggestion = null;
|
|
33
|
-
try {
|
|
34
|
-
const clearSuggestionsModule = await import(join(clearSuggestionsDistDir, 'index.js'));
|
|
35
|
-
checkClearSuggestion = clearSuggestionsModule.checkClearSuggestion;
|
|
36
|
-
} catch {
|
|
37
|
-
// Clear suggestions module not available - will be silently skipped
|
|
38
|
-
}
|
|
39
|
-
|
|
40
30
|
// State file for session tracking
|
|
41
31
|
const STATE_FILE = join(homedir(), '.claude', '.session-stats.json');
|
|
42
32
|
|
|
@@ -272,34 +262,9 @@ async function main() {
|
|
|
272
262
|
// Generate contextual message
|
|
273
263
|
const message = generateMessage(toolName, toolOutput, sessionId, toolCount);
|
|
274
264
|
|
|
275
|
-
// Check for clear suggestions (complements /compact suggestions)
|
|
276
|
-
let clearSuggestionMessage = null;
|
|
277
|
-
if (checkClearSuggestion) {
|
|
278
|
-
try {
|
|
279
|
-
const stats = loadStats();
|
|
280
|
-
const session = stats.sessions[sessionId];
|
|
281
|
-
// Estimate context usage from total tool calls (rough heuristic)
|
|
282
|
-
const estimatedContextRatio = session ? Math.min(session.total_calls / 200, 1.0) : 0;
|
|
283
|
-
|
|
284
|
-
const clearResult = checkClearSuggestion({
|
|
285
|
-
sessionId,
|
|
286
|
-
directory,
|
|
287
|
-
toolName,
|
|
288
|
-
toolOutput,
|
|
289
|
-
contextUsageRatio: estimatedContextRatio,
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
if (clearResult.shouldSuggest && clearResult.message) {
|
|
293
|
-
clearSuggestionMessage = clearResult.message;
|
|
294
|
-
}
|
|
295
|
-
} catch {
|
|
296
|
-
// Clear suggestion check failed - continue without it
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
265
|
// Build response - use hookSpecificOutput.additionalContext for PostToolUse
|
|
301
266
|
const response = { continue: true };
|
|
302
|
-
const contextMessage =
|
|
267
|
+
const contextMessage = message;
|
|
303
268
|
if (contextMessage) {
|
|
304
269
|
response.hookSpecificOutput = {
|
|
305
270
|
hookEventName: 'PostToolUse',
|
|
@@ -26,7 +26,8 @@ try {
|
|
|
26
26
|
|
|
27
27
|
// Constants (used by fallback)
|
|
28
28
|
const USER_SKILLS_DIR = join(homedir(), '.claude', 'skills', 'omc-learned');
|
|
29
|
-
const
|
|
29
|
+
const GLOBAL_SKILLS_DIR = join(homedir(), '.omc', 'skills');
|
|
30
|
+
const PROJECT_SKILLS_SUBDIR = join('.omc', 'skills');
|
|
30
31
|
const SKILL_EXTENSION = '.md';
|
|
31
32
|
const MAX_SKILLS_PER_SESSION = 5;
|
|
32
33
|
|
|
@@ -92,26 +93,29 @@ function findSkillFilesFallback(directory) {
|
|
|
92
93
|
}
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
// User-level skills
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
// User-level skills (search both global and legacy directories)
|
|
97
|
+
const userDirs = [GLOBAL_SKILLS_DIR, USER_SKILLS_DIR];
|
|
98
|
+
for (const userDir of userDirs) {
|
|
99
|
+
if (existsSync(userDir)) {
|
|
100
|
+
try {
|
|
101
|
+
const files = readdirSync(userDir, { withFileTypes: true });
|
|
102
|
+
for (const file of files) {
|
|
103
|
+
if (file.isFile() && file.name.endsWith(SKILL_EXTENSION)) {
|
|
104
|
+
const fullPath = join(userDir, file.name);
|
|
105
|
+
try {
|
|
106
|
+
const realPath = realpathSync(fullPath);
|
|
107
|
+
if (!seenPaths.has(realPath)) {
|
|
108
|
+
seenPaths.add(realPath);
|
|
109
|
+
candidates.push({ path: fullPath, scope: 'user' });
|
|
110
|
+
}
|
|
111
|
+
} catch {
|
|
112
|
+
// Ignore symlink resolution errors
|
|
107
113
|
}
|
|
108
|
-
} catch {
|
|
109
|
-
// Ignore symlink resolution errors
|
|
110
114
|
}
|
|
111
115
|
}
|
|
116
|
+
} catch {
|
|
117
|
+
// Ignore directory read errors
|
|
112
118
|
}
|
|
113
|
-
} catch {
|
|
114
|
-
// Ignore directory read errors
|
|
115
119
|
}
|
|
116
120
|
}
|
|
117
121
|
|
package/skills/cancel/SKILL.md
CHANGED
|
@@ -153,11 +153,13 @@ function isUserAbort(data) {
|
|
|
153
153
|
if (data.user_requested || data.userRequested) return true;
|
|
154
154
|
|
|
155
155
|
const reason = (data.stop_reason || data.stopReason || '').toLowerCase();
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
];
|
|
160
|
-
|
|
156
|
+
// Exact-match patterns: short generic words that cause false positives with .includes()
|
|
157
|
+
const exactPatterns = ['aborted', 'abort', 'cancel', 'interrupt'];
|
|
158
|
+
// Substring patterns: compound words safe for .includes() matching
|
|
159
|
+
const substringPatterns = ['user_cancel', 'user_interrupt', 'ctrl_c', 'manual_stop'];
|
|
160
|
+
|
|
161
|
+
return exactPatterns.some(p => reason === p) ||
|
|
162
|
+
substringPatterns.some(p => reason.includes(p));
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
async function main() {
|