@poping/yome 0.0.2
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/README.md +54 -0
- package/bin/yome.js +2 -0
- package/dist/agent.d.ts +43 -0
- package/dist/agent.js +140 -0
- package/dist/agent.js.map +1 -0
- package/dist/config.d.ts +41 -0
- package/dist/config.js +108 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +1 -0
- package/dist/context.js +101 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/llm.d.ts +13 -0
- package/dist/llm.js +317 -0
- package/dist/llm.js.map +1 -0
- package/dist/loops/chain.d.ts +15 -0
- package/dist/loops/chain.js +105 -0
- package/dist/loops/chain.js.map +1 -0
- package/dist/loops/evaluator.d.ts +12 -0
- package/dist/loops/evaluator.js +100 -0
- package/dist/loops/evaluator.js.map +1 -0
- package/dist/loops/index.d.ts +12 -0
- package/dist/loops/index.js +39 -0
- package/dist/loops/index.js.map +1 -0
- package/dist/loops/orchestrator.d.ts +13 -0
- package/dist/loops/orchestrator.js +107 -0
- package/dist/loops/orchestrator.js.map +1 -0
- package/dist/loops/parallel.d.ts +6 -0
- package/dist/loops/parallel.js +48 -0
- package/dist/loops/parallel.js.map +1 -0
- package/dist/loops/route.d.ts +13 -0
- package/dist/loops/route.js +88 -0
- package/dist/loops/route.js.map +1 -0
- package/dist/loops/simple.d.ts +6 -0
- package/dist/loops/simple.js +46 -0
- package/dist/loops/simple.js.map +1 -0
- package/dist/loops/types.d.ts +32 -0
- package/dist/loops/types.js +9 -0
- package/dist/loops/types.js.map +1 -0
- package/dist/permissions/checker.d.ts +18 -0
- package/dist/permissions/checker.js +89 -0
- package/dist/permissions/checker.js.map +1 -0
- package/dist/permissions/index.d.ts +4 -0
- package/dist/permissions/index.js +4 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/loader.d.ts +22 -0
- package/dist/permissions/loader.js +104 -0
- package/dist/permissions/loader.js.map +1 -0
- package/dist/permissions/ruleParser.d.ts +23 -0
- package/dist/permissions/ruleParser.js +59 -0
- package/dist/permissions/ruleParser.js.map +1 -0
- package/dist/permissions/types.d.ts +37 -0
- package/dist/permissions/types.js +2 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/sessions.d.ts +20 -0
- package/dist/sessions.js +119 -0
- package/dist/sessions.js.map +1 -0
- package/dist/skills/index.d.ts +2 -0
- package/dist/skills/index.js +2 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/loader.d.ts +4 -0
- package/dist/skills/loader.js +125 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/types.d.ts +22 -0
- package/dist/skills/types.js +2 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/subagent/agentTool.d.ts +7 -0
- package/dist/subagent/agentTool.js +121 -0
- package/dist/subagent/agentTool.js.map +1 -0
- package/dist/subagent/builtinAgents.d.ts +3 -0
- package/dist/subagent/builtinAgents.js +23 -0
- package/dist/subagent/builtinAgents.js.map +1 -0
- package/dist/subagent/index.d.ts +6 -0
- package/dist/subagent/index.js +5 -0
- package/dist/subagent/index.js.map +1 -0
- package/dist/subagent/loadAgents.d.ts +2 -0
- package/dist/subagent/loadAgents.js +98 -0
- package/dist/subagent/loadAgents.js.map +1 -0
- package/dist/subagent/runAgent.d.ts +18 -0
- package/dist/subagent/runAgent.js +115 -0
- package/dist/subagent/runAgent.js.map +1 -0
- package/dist/subagent/types.d.ts +20 -0
- package/dist/subagent/types.js +2 -0
- package/dist/subagent/types.js.map +1 -0
- package/dist/toggleState.d.ts +6 -0
- package/dist/toggleState.js +58 -0
- package/dist/toggleState.js.map +1 -0
- package/dist/tools/bash.d.ts +2 -0
- package/dist/tools/bash.js +78 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.js +103 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/glob.d.ts +2 -0
- package/dist/tools/glob.js +44 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.d.ts +2 -0
- package/dist/tools/grep.js +89 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/index.d.ts +15 -0
- package/dist/tools/index.js +99 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/ls.d.ts +2 -0
- package/dist/tools/ls.js +47 -0
- package/dist/tools/ls.js.map +1 -0
- package/dist/tools/read.d.ts +2 -0
- package/dist/tools/read.js +52 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/write.d.ts +2 -0
- package/dist/tools/write.js +46 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/AgentPicker.d.ts +12 -0
- package/dist/ui/AgentPicker.js +32 -0
- package/dist/ui/AgentPicker.js.map +1 -0
- package/dist/ui/App.d.ts +6 -0
- package/dist/ui/App.js +327 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/Banner.d.ts +1 -0
- package/dist/ui/Banner.js +14 -0
- package/dist/ui/Banner.js.map +1 -0
- package/dist/ui/InputBar.d.ts +17 -0
- package/dist/ui/InputBar.js +93 -0
- package/dist/ui/InputBar.js.map +1 -0
- package/dist/ui/Markdown.d.ts +4 -0
- package/dist/ui/Markdown.js +97 -0
- package/dist/ui/Markdown.js.map +1 -0
- package/dist/ui/MessageList.d.ts +17 -0
- package/dist/ui/MessageList.js +50 -0
- package/dist/ui/MessageList.js.map +1 -0
- package/dist/ui/ModelPicker.d.ts +9 -0
- package/dist/ui/ModelPicker.js +70 -0
- package/dist/ui/ModelPicker.js.map +1 -0
- package/dist/ui/PermissionPrompt.d.ts +10 -0
- package/dist/ui/PermissionPrompt.js +37 -0
- package/dist/ui/PermissionPrompt.js.map +1 -0
- package/dist/ui/SessionPicker.d.ts +8 -0
- package/dist/ui/SessionPicker.js +64 -0
- package/dist/ui/SessionPicker.js.map +1 -0
- package/dist/ui/Spinner.d.ts +3 -0
- package/dist/ui/Spinner.js +15 -0
- package/dist/ui/Spinner.js.map +1 -0
- package/dist/ui/TogglePicker.d.ts +16 -0
- package/dist/ui/TogglePicker.js +35 -0
- package/dist/ui/TogglePicker.js.map +1 -0
- package/dist/ui/ToolResult.d.ts +6 -0
- package/dist/ui/ToolResult.js +59 -0
- package/dist/ui/ToolResult.js.map +1 -0
- package/dist/utils/imagePaste.d.ts +12 -0
- package/dist/utils/imagePaste.js +54 -0
- package/dist/utils/imagePaste.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
2
|
+
import { join, resolve } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
import { parseRuleValue } from './ruleParser.js';
|
|
5
|
+
const USER_CONFIG_DIR = join(homedir(), '.yome');
|
|
6
|
+
const USER_SETTINGS_FILE = join(USER_CONFIG_DIR, 'settings.json');
|
|
7
|
+
function readJsonFile(filePath) {
|
|
8
|
+
try {
|
|
9
|
+
if (!existsSync(filePath))
|
|
10
|
+
return null;
|
|
11
|
+
const raw = readFileSync(filePath, 'utf-8').trim();
|
|
12
|
+
if (!raw)
|
|
13
|
+
return null;
|
|
14
|
+
return JSON.parse(raw);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function getProjectSettingsPath() {
|
|
21
|
+
return resolve(process.cwd(), '.yome', 'settings.json');
|
|
22
|
+
}
|
|
23
|
+
function loadRulesFromSettings(data, source) {
|
|
24
|
+
if (!data?.permissions)
|
|
25
|
+
return [];
|
|
26
|
+
const rules = [];
|
|
27
|
+
const behaviors = ['allow', 'deny'];
|
|
28
|
+
for (const behavior of behaviors) {
|
|
29
|
+
const entries = data.permissions[behavior];
|
|
30
|
+
if (!Array.isArray(entries))
|
|
31
|
+
continue;
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
rules.push({
|
|
34
|
+
source,
|
|
35
|
+
ruleBehavior: behavior,
|
|
36
|
+
ruleValue: parseRuleValue(entry),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return rules;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Load all permission rules from user settings (~/.yome/settings.json)
|
|
44
|
+
* and project settings (.yome/settings.json).
|
|
45
|
+
*/
|
|
46
|
+
export function loadAllPermissionRules() {
|
|
47
|
+
const rules = [];
|
|
48
|
+
const userData = readJsonFile(USER_SETTINGS_FILE);
|
|
49
|
+
rules.push(...loadRulesFromSettings(userData, 'userSettings'));
|
|
50
|
+
const projData = readJsonFile(getProjectSettingsPath());
|
|
51
|
+
rules.push(...loadRulesFromSettings(projData, 'projectSettings'));
|
|
52
|
+
return rules;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Load the default permission mode from settings.
|
|
56
|
+
*/
|
|
57
|
+
export function loadDefaultMode() {
|
|
58
|
+
const userData = readJsonFile(USER_SETTINGS_FILE);
|
|
59
|
+
const mode = userData?.permissions?.defaultMode;
|
|
60
|
+
if (mode === 'acceptEdits' || mode === 'bypassPermissions')
|
|
61
|
+
return mode;
|
|
62
|
+
return 'default';
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Build an initial ToolPermissionContext from disk settings and CLI args.
|
|
66
|
+
*/
|
|
67
|
+
export function initializePermissionContext(opts) {
|
|
68
|
+
const mode = opts?.mode ?? loadDefaultMode();
|
|
69
|
+
const rules = loadAllPermissionRules();
|
|
70
|
+
const allowRules = {};
|
|
71
|
+
const denyRules = {};
|
|
72
|
+
for (const rule of rules) {
|
|
73
|
+
const bucket = rule.ruleBehavior === 'allow' ? allowRules : denyRules;
|
|
74
|
+
if (!bucket[rule.source])
|
|
75
|
+
bucket[rule.source] = [];
|
|
76
|
+
bucket[rule.source].push(rule.ruleValue.ruleContent
|
|
77
|
+
? `${rule.ruleValue.toolName}(${rule.ruleValue.ruleContent})`
|
|
78
|
+
: rule.ruleValue.toolName);
|
|
79
|
+
}
|
|
80
|
+
if (opts?.allowedTools?.length) {
|
|
81
|
+
allowRules.cliArg = [...(allowRules.cliArg ?? []), ...opts.allowedTools];
|
|
82
|
+
}
|
|
83
|
+
if (opts?.disallowedTools?.length) {
|
|
84
|
+
denyRules.cliArg = [...(denyRules.cliArg ?? []), ...opts.disallowedTools];
|
|
85
|
+
}
|
|
86
|
+
return { mode, allowRules, denyRules };
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Persist a new allow/deny rule to user settings.
|
|
90
|
+
*/
|
|
91
|
+
export function addPermissionRuleToUserSettings(ruleString, behavior) {
|
|
92
|
+
mkdirSync(USER_CONFIG_DIR, { recursive: true });
|
|
93
|
+
const data = readJsonFile(USER_SETTINGS_FILE) ?? {};
|
|
94
|
+
if (!data.permissions)
|
|
95
|
+
data.permissions = {};
|
|
96
|
+
if (!data.permissions[behavior])
|
|
97
|
+
data.permissions[behavior] = [];
|
|
98
|
+
const list = data.permissions[behavior];
|
|
99
|
+
if (!list.includes(ruleString)) {
|
|
100
|
+
list.push(ruleString);
|
|
101
|
+
}
|
|
102
|
+
writeFileSync(USER_SETTINGS_FILE, JSON.stringify(data, null, 2), 'utf-8');
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/permissions/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { PermissionRuleValue } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a permission rule string like "Bash" or "Bash(npm publish:*)" into a
|
|
4
|
+
* PermissionRuleValue.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseRuleValue(ruleString: string): PermissionRuleValue;
|
|
7
|
+
/**
|
|
8
|
+
* Serialize a PermissionRuleValue back to string.
|
|
9
|
+
*/
|
|
10
|
+
export declare function serializeRuleValue(rule: PermissionRuleValue): string;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a tool matches a rule.
|
|
13
|
+
* - Rule "Bash" matches tool "Bash"
|
|
14
|
+
* - Rule "Bash(npm:*)" does NOT match at the tool level (has content)
|
|
15
|
+
*/
|
|
16
|
+
export declare function toolMatchesRule(toolName: string, ruleValue: PermissionRuleValue): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Check if a command/path matches a rule's content using prefix matching.
|
|
19
|
+
* - "npm publish:*" matches "npm publish ..." (prefix)
|
|
20
|
+
* - "npm:*" matches "npm ..."
|
|
21
|
+
* - Exact match also works
|
|
22
|
+
*/
|
|
23
|
+
export declare function contentMatchesRule(toolName: string, content: string, ruleValue: PermissionRuleValue): boolean;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a permission rule string like "Bash" or "Bash(npm publish:*)" into a
|
|
3
|
+
* PermissionRuleValue.
|
|
4
|
+
*/
|
|
5
|
+
export function parseRuleValue(ruleString) {
|
|
6
|
+
const trimmed = ruleString.trim();
|
|
7
|
+
const parenIdx = trimmed.indexOf('(');
|
|
8
|
+
if (parenIdx === -1) {
|
|
9
|
+
return { toolName: trimmed };
|
|
10
|
+
}
|
|
11
|
+
const toolName = trimmed.slice(0, parenIdx).trim();
|
|
12
|
+
const endParen = trimmed.lastIndexOf(')');
|
|
13
|
+
const ruleContent = trimmed.slice(parenIdx + 1, endParen === -1 ? undefined : endParen).trim();
|
|
14
|
+
if (!ruleContent || ruleContent === '*') {
|
|
15
|
+
return { toolName };
|
|
16
|
+
}
|
|
17
|
+
return { toolName, ruleContent };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Serialize a PermissionRuleValue back to string.
|
|
21
|
+
*/
|
|
22
|
+
export function serializeRuleValue(rule) {
|
|
23
|
+
if (rule.ruleContent) {
|
|
24
|
+
return `${rule.toolName}(${rule.ruleContent})`;
|
|
25
|
+
}
|
|
26
|
+
return rule.toolName;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if a tool matches a rule.
|
|
30
|
+
* - Rule "Bash" matches tool "Bash"
|
|
31
|
+
* - Rule "Bash(npm:*)" does NOT match at the tool level (has content)
|
|
32
|
+
*/
|
|
33
|
+
export function toolMatchesRule(toolName, ruleValue) {
|
|
34
|
+
if (ruleValue.ruleContent !== undefined) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return ruleValue.toolName === toolName;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if a command/path matches a rule's content using prefix matching.
|
|
41
|
+
* - "npm publish:*" matches "npm publish ..." (prefix)
|
|
42
|
+
* - "npm:*" matches "npm ..."
|
|
43
|
+
* - Exact match also works
|
|
44
|
+
*/
|
|
45
|
+
export function contentMatchesRule(toolName, content, ruleValue) {
|
|
46
|
+
if (ruleValue.toolName !== toolName)
|
|
47
|
+
return false;
|
|
48
|
+
if (ruleValue.ruleContent === undefined)
|
|
49
|
+
return true;
|
|
50
|
+
const rc = ruleValue.ruleContent;
|
|
51
|
+
// Wildcard suffix: "npm:*" or "npm publish:*"
|
|
52
|
+
if (rc.endsWith(':*')) {
|
|
53
|
+
const prefix = rc.slice(0, -2);
|
|
54
|
+
return content.startsWith(prefix);
|
|
55
|
+
}
|
|
56
|
+
// Exact match
|
|
57
|
+
return content === rc;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=ruleParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ruleParser.js","sourceRoot":"","sources":["../../src/permissions/ruleParser.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC/B,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,EAAE,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/F,IAAI,CAAC,WAAW,IAAI,WAAW,KAAK,GAAG,EAAE,CAAC;QACxC,OAAO,EAAE,QAAQ,EAAE,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAyB;IAC1D,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC;IACjD,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,SAA8B;IAC9E,IAAI,SAAS,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,SAAS,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,OAAe,EAAE,SAA8B;IAClG,IAAI,SAAS,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClD,IAAI,SAAS,CAAC,WAAW,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAErD,MAAM,EAAE,GAAG,SAAS,CAAC,WAAW,CAAC;IAEjC,8CAA8C;IAC9C,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/B,OAAO,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,cAAc;IACd,OAAO,OAAO,KAAK,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type PermissionMode = 'default' | 'acceptEdits' | 'bypassPermissions';
|
|
2
|
+
export type PermissionBehavior = 'allow' | 'deny' | 'ask';
|
|
3
|
+
export type PermissionRuleSource = 'userSettings' | 'projectSettings' | 'cliArg' | 'session';
|
|
4
|
+
export interface PermissionRuleValue {
|
|
5
|
+
toolName: string;
|
|
6
|
+
ruleContent?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PermissionRule {
|
|
9
|
+
source: PermissionRuleSource;
|
|
10
|
+
ruleBehavior: PermissionBehavior;
|
|
11
|
+
ruleValue: PermissionRuleValue;
|
|
12
|
+
}
|
|
13
|
+
export interface PermissionAllowDecision {
|
|
14
|
+
behavior: 'allow';
|
|
15
|
+
updatedInput?: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export interface PermissionAskDecision {
|
|
18
|
+
behavior: 'ask';
|
|
19
|
+
message: string;
|
|
20
|
+
}
|
|
21
|
+
export interface PermissionDenyDecision {
|
|
22
|
+
behavior: 'deny';
|
|
23
|
+
message: string;
|
|
24
|
+
}
|
|
25
|
+
export type PermissionDecision = PermissionAllowDecision | PermissionAskDecision | PermissionDenyDecision;
|
|
26
|
+
export type PermissionResult = PermissionDecision | {
|
|
27
|
+
behavior: 'passthrough';
|
|
28
|
+
message: string;
|
|
29
|
+
};
|
|
30
|
+
export type PermissionRulesBySource = {
|
|
31
|
+
[T in PermissionRuleSource]?: string[];
|
|
32
|
+
};
|
|
33
|
+
export interface ToolPermissionContext {
|
|
34
|
+
readonly mode: PermissionMode;
|
|
35
|
+
readonly allowRules: PermissionRulesBySource;
|
|
36
|
+
readonly denyRules: PermissionRulesBySource;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/permissions/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentMessage } from './types.js';
|
|
2
|
+
export interface SessionEntry {
|
|
3
|
+
type: 'message' | 'title';
|
|
4
|
+
timestamp: string;
|
|
5
|
+
sessionId: string;
|
|
6
|
+
message?: AgentMessage;
|
|
7
|
+
title?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SessionInfo {
|
|
10
|
+
sessionId: string;
|
|
11
|
+
title: string;
|
|
12
|
+
firstPrompt: string;
|
|
13
|
+
lastModified: Date;
|
|
14
|
+
messageCount: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function createSessionId(): string;
|
|
17
|
+
export declare function appendMessage(sessionId: string, message: AgentMessage): void;
|
|
18
|
+
export declare function setSessionTitle(sessionId: string, title: string): void;
|
|
19
|
+
export declare function loadSessionMessages(sessionId: string): AgentMessage[];
|
|
20
|
+
export declare function listSessions(): SessionInfo[];
|
package/dist/sessions.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { readFileSync, mkdirSync, readdirSync, appendFileSync, statSync } from 'fs';
|
|
2
|
+
import { join, basename } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
import { randomUUID } from 'crypto';
|
|
5
|
+
const SESSIONS_DIR = join(homedir(), '.yome', 'projects');
|
|
6
|
+
function sanitizePath(p) {
|
|
7
|
+
return p.replace(/[^a-zA-Z0-9]/g, '-');
|
|
8
|
+
}
|
|
9
|
+
function getProjectSessionDir() {
|
|
10
|
+
const cwd = process.cwd();
|
|
11
|
+
const dir = join(SESSIONS_DIR, sanitizePath(cwd));
|
|
12
|
+
mkdirSync(dir, { recursive: true });
|
|
13
|
+
return dir;
|
|
14
|
+
}
|
|
15
|
+
function getSessionFilePath(sessionId) {
|
|
16
|
+
return join(getProjectSessionDir(), `${sessionId}.jsonl`);
|
|
17
|
+
}
|
|
18
|
+
export function createSessionId() {
|
|
19
|
+
return randomUUID();
|
|
20
|
+
}
|
|
21
|
+
export function appendMessage(sessionId, message) {
|
|
22
|
+
const entry = {
|
|
23
|
+
type: 'message',
|
|
24
|
+
timestamp: new Date().toISOString(),
|
|
25
|
+
sessionId,
|
|
26
|
+
message,
|
|
27
|
+
};
|
|
28
|
+
appendFileSync(getSessionFilePath(sessionId), JSON.stringify(entry) + '\n', 'utf-8');
|
|
29
|
+
}
|
|
30
|
+
export function setSessionTitle(sessionId, title) {
|
|
31
|
+
const entry = {
|
|
32
|
+
type: 'title',
|
|
33
|
+
timestamp: new Date().toISOString(),
|
|
34
|
+
sessionId,
|
|
35
|
+
title,
|
|
36
|
+
};
|
|
37
|
+
appendFileSync(getSessionFilePath(sessionId), JSON.stringify(entry) + '\n', 'utf-8');
|
|
38
|
+
}
|
|
39
|
+
export function loadSessionMessages(sessionId) {
|
|
40
|
+
const filePath = getSessionFilePath(sessionId);
|
|
41
|
+
try {
|
|
42
|
+
const content = readFileSync(filePath, 'utf-8').trim();
|
|
43
|
+
if (!content)
|
|
44
|
+
return [];
|
|
45
|
+
const messages = [];
|
|
46
|
+
for (const line of content.split('\n')) {
|
|
47
|
+
try {
|
|
48
|
+
const entry = JSON.parse(line);
|
|
49
|
+
if (entry.type === 'message' && entry.message) {
|
|
50
|
+
messages.push(entry.message);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch { /* skip malformed lines */ }
|
|
54
|
+
}
|
|
55
|
+
return messages;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function readLiteMetadata(filePath) {
|
|
62
|
+
let firstPrompt = '';
|
|
63
|
+
let title = '';
|
|
64
|
+
let messageCount = 0;
|
|
65
|
+
try {
|
|
66
|
+
const content = readFileSync(filePath, 'utf-8').trim();
|
|
67
|
+
if (!content)
|
|
68
|
+
return { firstPrompt, title, messageCount };
|
|
69
|
+
for (const line of content.split('\n')) {
|
|
70
|
+
try {
|
|
71
|
+
const entry = JSON.parse(line);
|
|
72
|
+
if (entry.type === 'message' && entry.message) {
|
|
73
|
+
messageCount++;
|
|
74
|
+
if (!firstPrompt && entry.message.role === 'user') {
|
|
75
|
+
const text = typeof entry.message.content === 'string'
|
|
76
|
+
? entry.message.content
|
|
77
|
+
: entry.message.content
|
|
78
|
+
.filter((b) => b.type === 'text')
|
|
79
|
+
.map((b) => b.text)
|
|
80
|
+
.join(' ');
|
|
81
|
+
firstPrompt = text.slice(0, 100);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else if (entry.type === 'title' && entry.title) {
|
|
85
|
+
title = entry.title;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch { /* skip */ }
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch { /* file read error */ }
|
|
92
|
+
return { firstPrompt, title, messageCount };
|
|
93
|
+
}
|
|
94
|
+
export function listSessions() {
|
|
95
|
+
const dir = getProjectSessionDir();
|
|
96
|
+
const sessions = [];
|
|
97
|
+
try {
|
|
98
|
+
const files = readdirSync(dir).filter((f) => f.endsWith('.jsonl'));
|
|
99
|
+
for (const file of files) {
|
|
100
|
+
const filePath = join(dir, file);
|
|
101
|
+
const sessionId = basename(file, '.jsonl');
|
|
102
|
+
const stat = statSync(filePath);
|
|
103
|
+
const { firstPrompt, title, messageCount } = readLiteMetadata(filePath);
|
|
104
|
+
if (messageCount === 0)
|
|
105
|
+
continue;
|
|
106
|
+
sessions.push({
|
|
107
|
+
sessionId,
|
|
108
|
+
title: title || firstPrompt || '(untitled)',
|
|
109
|
+
firstPrompt,
|
|
110
|
+
lastModified: stat.mtime,
|
|
111
|
+
messageCount,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch { /* dir doesn't exist yet */ }
|
|
116
|
+
sessions.sort((a, b) => b.lastModified.getTime() - a.lastModified.getTime());
|
|
117
|
+
return sessions;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/skills/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
import { isSkillDisabled } from '../toggleState.js';
|
|
5
|
+
function parseFrontmatter(raw) {
|
|
6
|
+
const match = raw.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);
|
|
7
|
+
if (!match)
|
|
8
|
+
return { frontmatter: {}, content: raw };
|
|
9
|
+
const fm = {};
|
|
10
|
+
const lines = match[1].split('\n');
|
|
11
|
+
let currentKey = '';
|
|
12
|
+
let inArray = false;
|
|
13
|
+
const arrayBuf = [];
|
|
14
|
+
for (const line of lines) {
|
|
15
|
+
// Array item under a key
|
|
16
|
+
if (inArray && /^\s+-\s+/.test(line)) {
|
|
17
|
+
arrayBuf.push(line.replace(/^\s+-\s+/, '').trim());
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
// Flush array
|
|
21
|
+
if (inArray) {
|
|
22
|
+
fm[currentKey] = arrayBuf.length === 1 ? arrayBuf[0] : [...arrayBuf];
|
|
23
|
+
inArray = false;
|
|
24
|
+
arrayBuf.length = 0;
|
|
25
|
+
}
|
|
26
|
+
const kvMatch = line.match(/^(\S[\w-]*)\s*:\s*(.*)$/);
|
|
27
|
+
if (!kvMatch)
|
|
28
|
+
continue;
|
|
29
|
+
const key = kvMatch[1];
|
|
30
|
+
const value = kvMatch[2].trim();
|
|
31
|
+
if (value === '' || value === '|') {
|
|
32
|
+
currentKey = key;
|
|
33
|
+
inArray = true;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
// Remove quotes
|
|
37
|
+
const cleaned = value.replace(/^["']|["']$/g, '');
|
|
38
|
+
fm[key] = cleaned;
|
|
39
|
+
}
|
|
40
|
+
if (inArray && arrayBuf.length > 0) {
|
|
41
|
+
fm[currentKey] = arrayBuf.length === 1 ? arrayBuf[0] : [...arrayBuf];
|
|
42
|
+
}
|
|
43
|
+
return { frontmatter: fm, content: match[2] };
|
|
44
|
+
}
|
|
45
|
+
function parseAllowedTools(raw) {
|
|
46
|
+
if (!raw)
|
|
47
|
+
return [];
|
|
48
|
+
if (Array.isArray(raw))
|
|
49
|
+
return raw;
|
|
50
|
+
return raw.split(',').map((s) => s.trim()).filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
function loadSkillsFromDir(basePath, source) {
|
|
53
|
+
const skills = [];
|
|
54
|
+
let entries;
|
|
55
|
+
try {
|
|
56
|
+
entries = readdirSync(basePath).filter((e) => {
|
|
57
|
+
try {
|
|
58
|
+
return statSync(join(basePath, e)).isDirectory();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
for (const dirName of entries) {
|
|
69
|
+
const skillDir = join(basePath, dirName);
|
|
70
|
+
const skillFile = join(skillDir, 'SKILL.md');
|
|
71
|
+
let raw;
|
|
72
|
+
try {
|
|
73
|
+
raw = readFileSync(skillFile, 'utf-8');
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const { frontmatter, content } = parseFrontmatter(raw);
|
|
79
|
+
const name = dirName;
|
|
80
|
+
const description = frontmatter.description
|
|
81
|
+
|| content.split('\n').find((l) => l.trim().length > 0 && !l.startsWith('#'))?.trim()
|
|
82
|
+
|| `Skill: ${name}`;
|
|
83
|
+
skills.push({
|
|
84
|
+
name,
|
|
85
|
+
description,
|
|
86
|
+
allowedTools: parseAllowedTools(frontmatter['allowed-tools']),
|
|
87
|
+
argumentHint: frontmatter['argument-hint'],
|
|
88
|
+
whenToUse: frontmatter.when_to_use,
|
|
89
|
+
model: frontmatter.model,
|
|
90
|
+
context: frontmatter.context === 'fork' ? 'fork' : 'inline',
|
|
91
|
+
source,
|
|
92
|
+
skillDir,
|
|
93
|
+
markdownContent: content,
|
|
94
|
+
getPrompt(args) {
|
|
95
|
+
let prompt = `Base directory for this skill: ${skillDir}\n\n${content}`;
|
|
96
|
+
if (args) {
|
|
97
|
+
prompt += `\n\n## User Arguments\n\n${args}`;
|
|
98
|
+
}
|
|
99
|
+
return prompt;
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return skills;
|
|
104
|
+
}
|
|
105
|
+
export function getUserSkillsDir() {
|
|
106
|
+
return join(homedir(), '.yome', 'skills');
|
|
107
|
+
}
|
|
108
|
+
export function getProjectSkillsDir() {
|
|
109
|
+
return join(process.cwd(), '.yome', 'skills');
|
|
110
|
+
}
|
|
111
|
+
export function loadAllSkills(includeDisabled = false) {
|
|
112
|
+
const userSkills = loadSkillsFromDir(getUserSkillsDir(), 'user');
|
|
113
|
+
const projectSkills = loadSkillsFromDir(getProjectSkillsDir(), 'project');
|
|
114
|
+
// Deduplicate: project skills override user skills with same name
|
|
115
|
+
const byName = new Map();
|
|
116
|
+
for (const s of userSkills)
|
|
117
|
+
byName.set(s.name, s);
|
|
118
|
+
for (const s of projectSkills)
|
|
119
|
+
byName.set(s.name, s);
|
|
120
|
+
const all = Array.from(byName.values());
|
|
121
|
+
if (includeDisabled)
|
|
122
|
+
return all;
|
|
123
|
+
return all.filter((s) => !isSkillDisabled(s.name));
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/skills/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface SkillFrontmatter {
|
|
2
|
+
name?: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
'allowed-tools'?: string | string[];
|
|
5
|
+
'argument-hint'?: string;
|
|
6
|
+
when_to_use?: string;
|
|
7
|
+
model?: string;
|
|
8
|
+
context?: 'inline' | 'fork';
|
|
9
|
+
}
|
|
10
|
+
export interface Skill {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
allowedTools: string[];
|
|
14
|
+
argumentHint?: string;
|
|
15
|
+
whenToUse?: string;
|
|
16
|
+
model?: string;
|
|
17
|
+
context: 'inline' | 'fork';
|
|
18
|
+
source: 'user' | 'project';
|
|
19
|
+
skillDir: string;
|
|
20
|
+
markdownContent: string;
|
|
21
|
+
getPrompt: (args: string) => string;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/skills/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ToolDef } from '../types.js';
|
|
2
|
+
import type { YomeConfig } from '../config.js';
|
|
3
|
+
import type { AgentDefinition } from './types.js';
|
|
4
|
+
export declare function getActiveAgents(): AgentDefinition[];
|
|
5
|
+
export declare function getAllAgents(): AgentDefinition[];
|
|
6
|
+
export declare function clearAgentCache(): void;
|
|
7
|
+
export declare function createAgentTool(config: YomeConfig): ToolDef;
|