opencode-rules-md 0.6.5
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/LICENSE +21 -0
- package/README.md +650 -0
- package/dist/cli.mjs +374 -0
- package/dist/src/active-rules-state.d.ts +12 -0
- package/dist/src/active-rules-state.d.ts.map +1 -0
- package/dist/src/active-rules-state.js +118 -0
- package/dist/src/active-rules-state.js.map +1 -0
- package/dist/src/cli/config.d.ts +62 -0
- package/dist/src/cli/config.d.ts.map +1 -0
- package/dist/src/cli/config.js +246 -0
- package/dist/src/cli/config.js.map +1 -0
- package/dist/src/cli/install.d.ts +21 -0
- package/dist/src/cli/install.d.ts.map +1 -0
- package/dist/src/cli/install.js +63 -0
- package/dist/src/cli/install.js.map +1 -0
- package/dist/src/cli/main.d.ts +19 -0
- package/dist/src/cli/main.d.ts.map +1 -0
- package/dist/src/cli/main.js +135 -0
- package/dist/src/cli/main.js.map +1 -0
- package/dist/src/cli/real-fs.d.ts +26 -0
- package/dist/src/cli/real-fs.d.ts.map +1 -0
- package/dist/src/cli/real-fs.js +42 -0
- package/dist/src/cli/real-fs.js.map +1 -0
- package/dist/src/cli/status.d.ts +19 -0
- package/dist/src/cli/status.d.ts.map +1 -0
- package/dist/src/cli/status.js +58 -0
- package/dist/src/cli/status.js.map +1 -0
- package/dist/src/debug.d.ts +3 -0
- package/dist/src/debug.d.ts.map +1 -0
- package/dist/src/debug.js +8 -0
- package/dist/src/debug.js.map +1 -0
- package/dist/src/git-branch.d.ts +2 -0
- package/dist/src/git-branch.d.ts.map +1 -0
- package/dist/src/git-branch.js +30 -0
- package/dist/src/git-branch.js.map +1 -0
- package/dist/src/index.d.ts +26 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +55 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp-tools.d.ts +8 -0
- package/dist/src/mcp-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools.js +18 -0
- package/dist/src/mcp-tools.js.map +1 -0
- package/dist/src/message-context.d.ts +55 -0
- package/dist/src/message-context.d.ts.map +1 -0
- package/dist/src/message-context.js +110 -0
- package/dist/src/message-context.js.map +1 -0
- package/dist/src/message-paths.d.ts +34 -0
- package/dist/src/message-paths.d.ts.map +1 -0
- package/dist/src/message-paths.js +112 -0
- package/dist/src/message-paths.js.map +1 -0
- package/dist/src/project-fingerprint.d.ts +2 -0
- package/dist/src/project-fingerprint.d.ts.map +1 -0
- package/dist/src/project-fingerprint.js +61 -0
- package/dist/src/project-fingerprint.js.map +1 -0
- package/dist/src/rule-discovery.d.ts +49 -0
- package/dist/src/rule-discovery.d.ts.map +1 -0
- package/dist/src/rule-discovery.js +143 -0
- package/dist/src/rule-discovery.js.map +1 -0
- package/dist/src/rule-filter.d.ts +61 -0
- package/dist/src/rule-filter.d.ts.map +1 -0
- package/dist/src/rule-filter.js +180 -0
- package/dist/src/rule-filter.js.map +1 -0
- package/dist/src/rule-metadata.d.ts +29 -0
- package/dist/src/rule-metadata.d.ts.map +1 -0
- package/dist/src/rule-metadata.js +100 -0
- package/dist/src/rule-metadata.js.map +1 -0
- package/dist/src/runtime-chat.d.ts +34 -0
- package/dist/src/runtime-chat.d.ts.map +1 -0
- package/dist/src/runtime-chat.js +39 -0
- package/dist/src/runtime-chat.js.map +1 -0
- package/dist/src/runtime-context.d.ts +25 -0
- package/dist/src/runtime-context.d.ts.map +1 -0
- package/dist/src/runtime-context.js +109 -0
- package/dist/src/runtime-context.js.map +1 -0
- package/dist/src/runtime.d.ts +31 -0
- package/dist/src/runtime.d.ts.map +1 -0
- package/dist/src/runtime.js +238 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/session-store.d.ts +34 -0
- package/dist/src/session-store.d.ts.map +1 -0
- package/dist/src/session-store.js +90 -0
- package/dist/src/session-store.js.map +1 -0
- package/dist/src/utils.d.ts +15 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +19 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/tui/data/rules.d.ts +63 -0
- package/dist/tui/data/rules.d.ts.map +1 -0
- package/dist/tui/data/rules.js +173 -0
- package/dist/tui/data/rules.js.map +1 -0
- package/dist/tui/index.d.ts +8 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +13 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/slots/sidebar-content.d.ts +11 -0
- package/dist/tui/slots/sidebar-content.d.ts.map +1 -0
- package/dist/tui/slots/sidebar-content.js +150 -0
- package/dist/tui/slots/sidebar-content.js.map +1 -0
- package/package.json +101 -0
- package/src/active-rules-state.ts +166 -0
- package/src/cli/config.ts +312 -0
- package/src/cli/install.ts +94 -0
- package/src/cli/main.ts +167 -0
- package/src/cli/real-fs.ts +65 -0
- package/src/cli/status.ts +80 -0
- package/src/debug.ts +9 -0
- package/src/git-branch.ts +37 -0
- package/src/index.ts +68 -0
- package/src/mcp-tools.ts +24 -0
- package/src/message-context.ts +139 -0
- package/src/message-paths.ts +153 -0
- package/src/project-fingerprint.ts +72 -0
- package/src/rule-discovery.ts +205 -0
- package/src/rule-filter.ts +269 -0
- package/src/rule-metadata.ts +161 -0
- package/src/runtime-chat.ts +68 -0
- package/src/runtime-context.ts +136 -0
- package/src/runtime.ts +369 -0
- package/src/session-store.ts +129 -0
- package/src/utils.ts +36 -0
- package/tui/.atl/.skill-registry.cache.json +3 -0
- package/tui/.atl/skill-registry.md +57 -0
- package/tui/data/rules.ts +230 -0
- package/tui/index.tsx +23 -0
- package/tui/slots/sidebar-content.tsx +364 -0
- package/tui/types/opencode-plugin-tui.d.ts +78 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* status command: read-only probe that reports install state.
|
|
3
|
+
*
|
|
4
|
+
* Reports:
|
|
5
|
+
* - installed: yes/no
|
|
6
|
+
* - specifier: the registered opencode-rules-md entry (or undefined)
|
|
7
|
+
* - path: config file path
|
|
8
|
+
* - version: bundled CLI version from package.json
|
|
9
|
+
*/
|
|
10
|
+
import { loadGlobalConfig } from './config.js';
|
|
11
|
+
import { realFs } from './real-fs.js';
|
|
12
|
+
import * as fs from 'node:fs';
|
|
13
|
+
import * as path from 'node:path';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Run status
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
export function runStatus(fs = realFs) {
|
|
18
|
+
const loadResult = loadGlobalConfig(fs);
|
|
19
|
+
const configPath = loadResult.path;
|
|
20
|
+
// Surface parse errors as installed=false
|
|
21
|
+
if (loadResult.parseError) {
|
|
22
|
+
return {
|
|
23
|
+
installed: false,
|
|
24
|
+
path: configPath,
|
|
25
|
+
version: getVersion(),
|
|
26
|
+
parseError: loadResult.parseError,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const config = loadResult.config;
|
|
30
|
+
const pluginList = Array.isArray(config['plugin']) ? config['plugin'] : [];
|
|
31
|
+
// Find the opencode-rules-md entry (exact match for idempotency)
|
|
32
|
+
const specifier = pluginList.find(p => p.startsWith('opencode-rules-md'));
|
|
33
|
+
const result = {
|
|
34
|
+
installed: specifier !== undefined,
|
|
35
|
+
path: configPath,
|
|
36
|
+
version: getVersion(),
|
|
37
|
+
};
|
|
38
|
+
if (specifier) {
|
|
39
|
+
result.specifier = specifier;
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Internal helpers
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
function getVersion() {
|
|
47
|
+
try {
|
|
48
|
+
// Read package.json relative to the project root
|
|
49
|
+
const pkgPath = path.resolve(process.cwd(), 'package.json');
|
|
50
|
+
const content = fs.readFileSync(pkgPath, 'utf-8');
|
|
51
|
+
const pkg = JSON.parse(content);
|
|
52
|
+
return pkg.version ?? 'unknown';
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return 'unknown';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAclC,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,MAAM,UAAU,SAAS,CAAC,KAAY,MAAM;IAC1C,MAAM,UAAU,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC;IAEnC,0CAA0C;IAC1C,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;QAC1B,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,UAAU,EAAE;YACrB,UAAU,EAAE,UAAU,CAAC,UAAU;SAClC,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IACjC,MAAM,UAAU,GAAa,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,MAAM,CAAC,QAAQ,CAAc,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnG,iEAAiE;IACjE,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAE1E,MAAM,MAAM,GAAiB;QAC3B,SAAS,EAAE,SAAS,KAAK,SAAS;QAClC,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,UAAU,EAAE;KACtB,CAAC;IAEF,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;IAC/B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,iDAAiD;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;QAC5D,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAyB,CAAC;QACxD,OAAO,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/debug.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAEjD,wBAAgB,cAAc,CAAC,MAAM,SAAwB,GAAG,QAAQ,CAMvE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/debug.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc,CAAC,MAAM,GAAG,qBAAqB;IAC3D,OAAO,CAAC,OAAe,EAAQ,EAAE;QAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;YACrC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-branch.d.ts","sourceRoot":"","sources":["../../src/git-branch.ts"],"names":[],"mappings":"AAIA,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA8B7B"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { execFile } from 'child_process';
|
|
2
|
+
const GIT_TIMEOUT_MS = 5000;
|
|
3
|
+
export async function getGitBranch(projectDir) {
|
|
4
|
+
try {
|
|
5
|
+
const branch = await new Promise(resolve => {
|
|
6
|
+
const opts = {
|
|
7
|
+
cwd: projectDir,
|
|
8
|
+
timeout: GIT_TIMEOUT_MS,
|
|
9
|
+
killSignal: 'SIGTERM',
|
|
10
|
+
};
|
|
11
|
+
execFile('git', ['rev-parse', '--abbrev-ref', 'HEAD'], opts, (error, stdout) => {
|
|
12
|
+
if (error) {
|
|
13
|
+
resolve(undefined);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const trimmed = String(stdout).trim();
|
|
17
|
+
if (!trimmed || trimmed === 'HEAD') {
|
|
18
|
+
resolve(undefined);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
resolve(trimmed);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
return branch;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=git-branch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-branch.js","sourceRoot":"","sources":["../../src/git-branch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAwB,MAAM,eAAe,CAAC;AAE/D,MAAM,cAAc,GAAG,IAAI,CAAC;AAE5B,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAkB;IAElB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAqB,OAAO,CAAC,EAAE;YAC7D,MAAM,IAAI,GAAoB;gBAC5B,GAAG,EAAE,UAAU;gBACf,OAAO,EAAE,cAAc;gBACvB,UAAU,EAAE,SAAS;aACtB,CAAC;YACF,QAAQ,CACN,KAAK,EACL,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EACrC,IAAI,EACJ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;gBAChB,IAAI,KAAK,EAAE,CAAC;oBACV,OAAO,CAAC,SAAS,CAAC,CAAC;oBACnB,OAAO;gBACT,CAAC;gBACD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;gBACtC,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;oBACnC,OAAO,CAAC,SAAS,CAAC,CAAC;oBACnB,OAAO;gBACT,CAAC;gBACD,OAAO,CAAC,OAAO,CAAC,CAAC;YACnB,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode Rules Plugin
|
|
3
|
+
*
|
|
4
|
+
* Discovers markdown rule files and injects them into the system prompt.
|
|
5
|
+
*/
|
|
6
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
7
|
+
import { type SessionState } from './session-store.js';
|
|
8
|
+
/**
|
|
9
|
+
* Test-only exports for accessing internal state and functions.
|
|
10
|
+
* @internal - Test utilities only. Not part of public API.
|
|
11
|
+
*/
|
|
12
|
+
declare const __testOnly: (() => Promise<{}>) & {
|
|
13
|
+
setSessionStateLimit: (limit: number) => void;
|
|
14
|
+
getSessionStateIDs: () => string[];
|
|
15
|
+
getSessionStateSnapshot: (sessionID: string) => SessionState | undefined;
|
|
16
|
+
upsertSessionState: (sessionID: string, mutator: (state: SessionState) => void) => void;
|
|
17
|
+
resetSessionState: () => void;
|
|
18
|
+
getSeedCount: (sessionID: string) => number;
|
|
19
|
+
};
|
|
20
|
+
declare const _default: {
|
|
21
|
+
id: "opencode-rules-md";
|
|
22
|
+
server: (pluginInput: PluginInput) => Promise<Record<string, unknown>>;
|
|
23
|
+
};
|
|
24
|
+
export default _default;
|
|
25
|
+
export { __testOnly };
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAU,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAG/D,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAuB3E;;;GAGG;AAGH,QAAA,MAAM,UAAU;kCAEkB,MAAM,KAAG,IAAI;8BAGnB,MAAM,EAAE;yCAGK,MAAM,KAAG,YAAY,GAAG,SAAS;oCAIzD,MAAM,WACR,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,KACrC,IAAI;6BAGgB,IAAI;8BAGD,MAAM,KAAG,MAAM;CAI5C,CAAC;;;0BA9C8C,WAAW;;AAkD3D,wBAA8B;AAC9B,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode Rules Plugin
|
|
3
|
+
*
|
|
4
|
+
* Discovers markdown rule files and injects them into the system prompt.
|
|
5
|
+
*/
|
|
6
|
+
import { discoverRuleFiles } from './utils.js';
|
|
7
|
+
import { OpenCodeRulesRuntime } from './runtime.js';
|
|
8
|
+
import { createSessionStore } from './session-store.js';
|
|
9
|
+
const sessionStore = createSessionStore();
|
|
10
|
+
import { createDebugLog } from './debug.js';
|
|
11
|
+
const debugLog = createDebugLog();
|
|
12
|
+
const openCodeRulesPlugin = async (pluginInput) => {
|
|
13
|
+
const ruleFiles = await discoverRuleFiles(pluginInput.directory);
|
|
14
|
+
debugLog(`Discovered ${ruleFiles.length} rule file(s)`);
|
|
15
|
+
const runtime = new OpenCodeRulesRuntime({
|
|
16
|
+
client: pluginInput.client,
|
|
17
|
+
directory: pluginInput.directory,
|
|
18
|
+
projectDirectory: pluginInput.directory,
|
|
19
|
+
ruleFiles,
|
|
20
|
+
sessionStore,
|
|
21
|
+
debugLog,
|
|
22
|
+
});
|
|
23
|
+
return runtime.createHooks();
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Test-only exports for accessing internal state and functions.
|
|
27
|
+
* @internal - Test utilities only. Not part of public API.
|
|
28
|
+
*/
|
|
29
|
+
// NOTE: OpenCode's plugin loader calls every named export as a plugin initializer.
|
|
30
|
+
// To avoid runtime crashes, __testOnly must be callable.
|
|
31
|
+
const __testOnly = Object.freeze(Object.assign(async () => ({}), {
|
|
32
|
+
setSessionStateLimit: (limit) => {
|
|
33
|
+
sessionStore.setMax(limit);
|
|
34
|
+
},
|
|
35
|
+
getSessionStateIDs: () => {
|
|
36
|
+
return sessionStore.ids();
|
|
37
|
+
},
|
|
38
|
+
getSessionStateSnapshot: (sessionID) => {
|
|
39
|
+
return sessionStore.snapshot(sessionID);
|
|
40
|
+
},
|
|
41
|
+
upsertSessionState: (sessionID, mutator) => {
|
|
42
|
+
sessionStore.upsert(sessionID, mutator);
|
|
43
|
+
},
|
|
44
|
+
resetSessionState: () => {
|
|
45
|
+
sessionStore.reset();
|
|
46
|
+
},
|
|
47
|
+
getSeedCount: (sessionID) => {
|
|
48
|
+
return sessionStore.get(sessionID)?.seedCount ?? 0;
|
|
49
|
+
},
|
|
50
|
+
}));
|
|
51
|
+
const id = 'opencode-rules-md';
|
|
52
|
+
const server = openCodeRulesPlugin;
|
|
53
|
+
export default { id, server };
|
|
54
|
+
export { __testOnly };
|
|
55
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAqB,MAAM,oBAAoB,CAAC;AAE3E,MAAM,YAAY,GAAG,kBAAkB,EAAE,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;AAElC,MAAM,mBAAmB,GAAG,KAAK,EAAE,WAAwB,EAAE,EAAE;IAC7D,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACjE,QAAQ,CAAC,cAAc,SAAS,CAAC,MAAM,eAAe,CAAC,CAAC;IAExD,MAAM,OAAO,GAAG,IAAI,oBAAoB,CAAC;QACvC,MAAM,EAAE,WAAW,CAAC,MAAM;QAC1B,SAAS,EAAE,WAAW,CAAC,SAAS;QAChC,gBAAgB,EAAE,WAAW,CAAC,SAAS;QACvC,SAAS;QACT,YAAY;QACZ,QAAQ;KACT,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC;AAC/B,CAAC,CAAC;AAEF;;;GAGG;AACH,mFAAmF;AACnF,yDAAyD;AACzD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAC9B,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE;IAC9B,oBAAoB,EAAE,CAAC,KAAa,EAAQ,EAAE;QAC5C,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,kBAAkB,EAAE,GAAa,EAAE;QACjC,OAAO,YAAY,CAAC,GAAG,EAAE,CAAC;IAC5B,CAAC;IACD,uBAAuB,EAAE,CAAC,SAAiB,EAA4B,EAAE;QACvE,OAAO,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IACD,kBAAkB,EAAE,CAClB,SAAiB,EACjB,OAAsC,EAChC,EAAE;QACR,YAAY,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IACD,iBAAiB,EAAE,GAAS,EAAE;QAC5B,YAAY,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IACD,YAAY,EAAE,CAAC,SAAiB,EAAU,EAAE;QAC1C,OAAO,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,SAAS,IAAI,CAAC,CAAC;IACrD,CAAC;CACF,CAAC,CACH,CAAC;AAEF,MAAM,EAAE,GAAG,mBAA4B,CAAC;AACxC,MAAM,MAAM,GAAG,mBAAoC,CAAC;AACpD,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-tools.d.ts","sourceRoot":"","sources":["../../src/mcp-tools.ts"],"names":[],"mappings":"AAAA,UAAU,YAAY;IACpB,CAAC,UAAU,EAAE,MAAM,GAAG;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACvD;AAMD,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GACtC,MAAM,EAAE,CAaV"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function sanitizeMcpClientName(name) {
|
|
2
|
+
return name.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
3
|
+
}
|
|
4
|
+
export function extractConnectedMcpCapabilityIDs(status) {
|
|
5
|
+
if (!status || typeof status !== 'object' || Array.isArray(status))
|
|
6
|
+
return [];
|
|
7
|
+
const out = [];
|
|
8
|
+
for (const [clientName, clientStatus] of Object.entries(status)) {
|
|
9
|
+
if (clientStatus?.status === 'connected') {
|
|
10
|
+
const sanitized = sanitizeMcpClientName(clientName);
|
|
11
|
+
if (sanitized) {
|
|
12
|
+
out.push(`mcp_${sanitized}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=mcp-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-tools.js","sourceRoot":"","sources":["../../src/mcp-tools.ts"],"names":[],"mappings":"AAIA,SAAS,qBAAqB,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC9C,MAAuC;IAEvC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IAE9E,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAChE,IAAI,YAAY,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;YACpD,IAAI,SAAS,EAAE,CAAC;gBACd,GAAG,CAAC,IAAI,CAAC,OAAO,SAAS,EAAE,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Message } from './message-paths.js';
|
|
2
|
+
export interface MessagePartWithSession {
|
|
3
|
+
type?: string;
|
|
4
|
+
text?: string;
|
|
5
|
+
sessionID?: string;
|
|
6
|
+
synthetic?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface MessageWithInfo {
|
|
9
|
+
role?: string;
|
|
10
|
+
parts?: MessagePartWithSession[];
|
|
11
|
+
info?: {
|
|
12
|
+
sessionID?: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Extract and join text content from message parts.
|
|
17
|
+
* Skips synthetic parts and parts without text content.
|
|
18
|
+
* Returns an empty string if no text is extracted.
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractTextFromParts(parts: Array<{
|
|
21
|
+
type?: string;
|
|
22
|
+
text?: string;
|
|
23
|
+
synthetic?: boolean;
|
|
24
|
+
}>): string;
|
|
25
|
+
/**
|
|
26
|
+
* Normalize paths to repo-relative POSIX format.
|
|
27
|
+
* If path is absolute and under baseDir, convert to relative POSIX path.
|
|
28
|
+
* Otherwise return path as-is.
|
|
29
|
+
*/
|
|
30
|
+
export declare function normalizeContextPath(p: string, baseDir: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Sanitize a file path for safe inclusion in context strings.
|
|
33
|
+
* Prevents prompt injection by removing control characters and limiting length.
|
|
34
|
+
*/
|
|
35
|
+
export declare function sanitizePathForContext(p: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Extract sessionID from messages array.
|
|
38
|
+
*/
|
|
39
|
+
export declare function extractSessionID(messages: MessageWithInfo[]): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Extract the latest user message text from messages array.
|
|
42
|
+
*/
|
|
43
|
+
export declare function extractLatestUserPrompt(messages: MessageWithInfo[]): string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Convert MessageWithInfo[] to Message[] by filtering out messages
|
|
46
|
+
* that lack required fields (role, non-empty parts array).
|
|
47
|
+
*/
|
|
48
|
+
export declare function toExtractableMessages(messages: MessageWithInfo[]): Message[];
|
|
49
|
+
/**
|
|
50
|
+
* Extract the leading slash command from a user prompt.
|
|
51
|
+
* Returns the first whitespace-delimited token if it starts with '/'
|
|
52
|
+
* and contains at least one non-slash character after the leading slash.
|
|
53
|
+
*/
|
|
54
|
+
export declare function extractSlashCommand(prompt?: string): string | undefined;
|
|
55
|
+
//# sourceMappingURL=message-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-context.d.ts","sourceRoot":"","sources":["../../src/message-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,oBAAoB,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACjC,IAAI,CAAC,EAAE;QACL,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAClE,MAAM,CAiBR;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAIvE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,eAAe,EAAE,GAC1B,MAAM,GAAG,SAAS,CAcpB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,eAAe,EAAE,GAC1B,MAAM,GAAG,SAAS,CAapB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,OAAO,EAAE,CAe5E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQvE"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Extract and join text content from message parts.
|
|
4
|
+
* Skips synthetic parts and parts without text content.
|
|
5
|
+
* Returns an empty string if no text is extracted.
|
|
6
|
+
*/
|
|
7
|
+
export function extractTextFromParts(parts) {
|
|
8
|
+
const textParts = [];
|
|
9
|
+
for (const part of parts) {
|
|
10
|
+
if (part.synthetic)
|
|
11
|
+
continue;
|
|
12
|
+
if (part.type === 'text' && part.text) {
|
|
13
|
+
textParts.push(part.text);
|
|
14
|
+
}
|
|
15
|
+
else if (typeof part.text === 'string' && !part.type) {
|
|
16
|
+
textParts.push(part.text);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return textParts
|
|
20
|
+
.map(t => t.trim())
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.join(' ')
|
|
23
|
+
.trim();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Normalize paths to repo-relative POSIX format.
|
|
27
|
+
* If path is absolute and under baseDir, convert to relative POSIX path.
|
|
28
|
+
* Otherwise return path as-is.
|
|
29
|
+
*/
|
|
30
|
+
export function normalizeContextPath(p, baseDir) {
|
|
31
|
+
if (!path.isAbsolute(p))
|
|
32
|
+
return p;
|
|
33
|
+
const rel = path.relative(baseDir, p);
|
|
34
|
+
return rel.split(path.sep).join('/');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Sanitize a file path for safe inclusion in context strings.
|
|
38
|
+
* Prevents prompt injection by removing control characters and limiting length.
|
|
39
|
+
*/
|
|
40
|
+
export function sanitizePathForContext(p) {
|
|
41
|
+
return p.replace(/[\r\n\t]/g, ' ').slice(0, 300);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract sessionID from messages array.
|
|
45
|
+
*/
|
|
46
|
+
export function extractSessionID(messages) {
|
|
47
|
+
for (const message of messages) {
|
|
48
|
+
if (message.info?.sessionID) {
|
|
49
|
+
return message.info.sessionID;
|
|
50
|
+
}
|
|
51
|
+
if (message.parts) {
|
|
52
|
+
for (const part of message.parts) {
|
|
53
|
+
if (part.sessionID) {
|
|
54
|
+
return part.sessionID;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Extract the latest user message text from messages array.
|
|
63
|
+
*/
|
|
64
|
+
export function extractLatestUserPrompt(messages) {
|
|
65
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
66
|
+
const message = messages[i];
|
|
67
|
+
if (message.role && message.role !== 'user')
|
|
68
|
+
continue;
|
|
69
|
+
const parts = message.parts || [];
|
|
70
|
+
const userPrompt = extractTextFromParts(parts);
|
|
71
|
+
if (userPrompt) {
|
|
72
|
+
return userPrompt;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Convert MessageWithInfo[] to Message[] by filtering out messages
|
|
79
|
+
* that lack required fields (role, non-empty parts array).
|
|
80
|
+
*/
|
|
81
|
+
export function toExtractableMessages(messages) {
|
|
82
|
+
const result = [];
|
|
83
|
+
for (const msg of messages) {
|
|
84
|
+
if (typeof msg.role === 'string' &&
|
|
85
|
+
Array.isArray(msg.parts) &&
|
|
86
|
+
msg.parts.length > 0) {
|
|
87
|
+
result.push({
|
|
88
|
+
role: msg.role,
|
|
89
|
+
parts: msg.parts,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Extract the leading slash command from a user prompt.
|
|
97
|
+
* Returns the first whitespace-delimited token if it starts with '/'
|
|
98
|
+
* and contains at least one non-slash character after the leading slash.
|
|
99
|
+
*/
|
|
100
|
+
export function extractSlashCommand(prompt) {
|
|
101
|
+
if (!prompt)
|
|
102
|
+
return undefined;
|
|
103
|
+
const first = prompt.trim().split(/\s+/, 1)[0];
|
|
104
|
+
// Must start with '/' and have at least one additional character
|
|
105
|
+
if (first.length > 1 && first.startsWith('/')) {
|
|
106
|
+
return first;
|
|
107
|
+
}
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=message-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-context.js","sourceRoot":"","sources":["../../src/message-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message path extraction utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Message part types from OpenCode plugin API
|
|
6
|
+
*/
|
|
7
|
+
interface ToolInvocationPart {
|
|
8
|
+
type: 'tool-invocation';
|
|
9
|
+
toolInvocation: {
|
|
10
|
+
toolName: string;
|
|
11
|
+
args: Record<string, unknown>;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
interface TextPart {
|
|
15
|
+
type: 'text';
|
|
16
|
+
text: string;
|
|
17
|
+
}
|
|
18
|
+
export type MessagePart = ToolInvocationPart | TextPart | {
|
|
19
|
+
type: string;
|
|
20
|
+
};
|
|
21
|
+
export interface Message {
|
|
22
|
+
role: string;
|
|
23
|
+
parts: MessagePart[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Extract file paths from conversation messages for conditional rule filtering.
|
|
27
|
+
* Parses tool call arguments and scans message content for path-like strings.
|
|
28
|
+
*
|
|
29
|
+
* @param messages - Array of conversation messages
|
|
30
|
+
* @returns Deduplicated array of file paths found in messages
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractFilePathsFromMessages(messages: Message[]): string[];
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=message-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-paths.d.ts","sourceRoot":"","sources":["../../src/message-paths.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,UAAU,kBAAkB;IAC1B,IAAI,EAAE,iBAAiB,CAAC;IACxB,cAAc,EAAE;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B,CAAC;CACH;AAED,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,WAAW,GAAG,kBAAkB,GAAG,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAoB1E"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message path extraction utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Extract file paths from conversation messages for conditional rule filtering.
|
|
6
|
+
* Parses tool call arguments and scans message content for path-like strings.
|
|
7
|
+
*
|
|
8
|
+
* @param messages - Array of conversation messages
|
|
9
|
+
* @returns Deduplicated array of file paths found in messages
|
|
10
|
+
*/
|
|
11
|
+
export function extractFilePathsFromMessages(messages) {
|
|
12
|
+
const paths = new Set();
|
|
13
|
+
for (const message of messages) {
|
|
14
|
+
for (const part of message.parts) {
|
|
15
|
+
// Extract from tool invocations
|
|
16
|
+
if (part.type === 'tool-invocation') {
|
|
17
|
+
const toolPart = part;
|
|
18
|
+
extractPathsFromToolCall(toolPart, paths);
|
|
19
|
+
}
|
|
20
|
+
// Extract from text content
|
|
21
|
+
if (part.type === 'text') {
|
|
22
|
+
const textPart = part;
|
|
23
|
+
extractPathsFromText(textPart.text, paths);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return Array.from(paths);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Extract file paths from tool call arguments
|
|
31
|
+
*/
|
|
32
|
+
function extractPathsFromToolCall(part, paths) {
|
|
33
|
+
const { toolName, args } = part.toolInvocation;
|
|
34
|
+
// Tools that have a direct file path argument
|
|
35
|
+
const pathArgTools = {
|
|
36
|
+
read: ['filePath'],
|
|
37
|
+
edit: ['filePath'],
|
|
38
|
+
write: ['filePath'],
|
|
39
|
+
glob: ['pattern', 'path'],
|
|
40
|
+
grep: ['path'],
|
|
41
|
+
};
|
|
42
|
+
const argNames = pathArgTools[toolName];
|
|
43
|
+
if (argNames) {
|
|
44
|
+
for (const argName of argNames) {
|
|
45
|
+
const value = args[argName];
|
|
46
|
+
if (typeof value === 'string' && value.length > 0) {
|
|
47
|
+
// For glob patterns, extract the directory part
|
|
48
|
+
if (argName === 'pattern') {
|
|
49
|
+
const dirPart = extractDirFromGlob(value);
|
|
50
|
+
if (dirPart)
|
|
51
|
+
paths.add(dirPart);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
paths.add(value);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Extract directory path from a glob pattern
|
|
62
|
+
*/
|
|
63
|
+
function extractDirFromGlob(pattern) {
|
|
64
|
+
// Find the first glob character
|
|
65
|
+
const globChars = ['*', '?', '[', '{'];
|
|
66
|
+
let firstGlobIndex = pattern.length;
|
|
67
|
+
for (const char of globChars) {
|
|
68
|
+
const idx = pattern.indexOf(char);
|
|
69
|
+
if (idx !== -1 && idx < firstGlobIndex) {
|
|
70
|
+
firstGlobIndex = idx;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (firstGlobIndex === 0)
|
|
74
|
+
return null;
|
|
75
|
+
// Get the directory part before the glob
|
|
76
|
+
const beforeGlob = pattern.substring(0, firstGlobIndex);
|
|
77
|
+
const lastSlash = beforeGlob.lastIndexOf('/');
|
|
78
|
+
if (lastSlash === -1) {
|
|
79
|
+
// If no slash and pattern has glob characters, it's just a file prefix, not a directory
|
|
80
|
+
if (firstGlobIndex < pattern.length)
|
|
81
|
+
return null;
|
|
82
|
+
return beforeGlob;
|
|
83
|
+
}
|
|
84
|
+
return beforeGlob.substring(0, lastSlash);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Extract file paths from text content using regex
|
|
88
|
+
*/
|
|
89
|
+
function extractPathsFromText(text, paths) {
|
|
90
|
+
// Match paths that look like file paths:
|
|
91
|
+
// - Start with ./, ../, /, or a word character
|
|
92
|
+
// - Contain at least one /
|
|
93
|
+
// - End with a file extension or directory
|
|
94
|
+
const pathRegex = /(?:^|[\s"'`(])((\.{0,2}\/)?[\w./-]+\/[\w./-]+(?:\.\w+)?)/gm;
|
|
95
|
+
let match;
|
|
96
|
+
while ((match = pathRegex.exec(text)) !== null) {
|
|
97
|
+
let potentialPath = match[1];
|
|
98
|
+
// Trim trailing punctuation that likely belongs to prose, not the path
|
|
99
|
+
potentialPath = potentialPath.replace(/[.,!?:;]+$/, '');
|
|
100
|
+
// Filter out URLs and other non-paths
|
|
101
|
+
if (potentialPath.includes('://') ||
|
|
102
|
+
potentialPath.startsWith('http') ||
|
|
103
|
+
potentialPath.includes('@')) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
// Must have a reasonable structure (not just slashes)
|
|
107
|
+
if (potentialPath.replace(/[/.]/g, '').length > 0) {
|
|
108
|
+
paths.add(potentialPath);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=message-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-paths.js","sourceRoot":"","sources":["../../src/message-paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-fingerprint.d.ts","sourceRoot":"","sources":["../../src/project-fingerprint.ts"],"names":[],"mappings":"AA8CA,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAyB7E"}
|