freeturtle 0.1.29 → 0.1.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/freeturtle.js +26 -2
- package/dist/bin/freeturtle.js.map +1 -1
- package/dist/src/approval.test.d.ts +1 -0
- package/dist/src/approval.test.js +110 -0
- package/dist/src/approval.test.js.map +1 -0
- package/dist/src/cli/daemon-utils.d.ts +3 -0
- package/dist/src/cli/daemon-utils.js +49 -0
- package/dist/src/cli/daemon-utils.js.map +1 -0
- package/dist/src/cli/daemon-utils.test.d.ts +1 -0
- package/dist/src/cli/daemon-utils.test.js +46 -0
- package/dist/src/cli/daemon-utils.test.js.map +1 -0
- package/dist/src/cli/restart.d.ts +1 -0
- package/dist/src/cli/restart.js +23 -0
- package/dist/src/cli/restart.js.map +1 -0
- package/dist/src/cli/skills.d.ts +1 -0
- package/dist/src/cli/skills.js +28 -0
- package/dist/src/cli/skills.js.map +1 -0
- package/dist/src/cli/stop.d.ts +1 -0
- package/dist/src/cli/stop.js +11 -0
- package/dist/src/cli/stop.js.map +1 -0
- package/dist/src/cli/update.js +12 -56
- package/dist/src/cli/update.js.map +1 -1
- package/dist/src/config.d.ts +2 -0
- package/dist/src/config.js +9 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/config.test.d.ts +1 -0
- package/dist/src/config.test.js +34 -0
- package/dist/src/config.test.js.map +1 -0
- package/dist/src/daemon.js +7 -1
- package/dist/src/daemon.js.map +1 -1
- package/dist/src/modules/loader.js +12 -0
- package/dist/src/modules/loader.js.map +1 -1
- package/dist/src/modules/shell/index.d.ts +12 -0
- package/dist/src/modules/shell/index.js +298 -0
- package/dist/src/modules/shell/index.js.map +1 -0
- package/dist/src/modules/shell/index.test.d.ts +1 -0
- package/dist/src/modules/shell/index.test.js +65 -0
- package/dist/src/modules/shell/index.test.js.map +1 -0
- package/dist/src/policy.js +2 -0
- package/dist/src/policy.js.map +1 -1
- package/dist/src/policy.test.d.ts +1 -0
- package/dist/src/policy.test.js +57 -0
- package/dist/src/policy.test.js.map +1 -0
- package/dist/src/redaction.test.d.ts +1 -0
- package/dist/src/redaction.test.js +32 -0
- package/dist/src/redaction.test.js.map +1 -0
- package/dist/src/reliability.test.d.ts +1 -0
- package/dist/src/reliability.test.js +30 -0
- package/dist/src/reliability.test.js.map +1 -0
- package/dist/src/rpc/protocol.test.d.ts +1 -0
- package/dist/src/rpc/protocol.test.js +47 -0
- package/dist/src/rpc/protocol.test.js.map +1 -0
- package/dist/src/runner.d.ts +3 -0
- package/dist/src/runner.js +13 -1
- package/dist/src/runner.js.map +1 -1
- package/dist/src/skills/index.d.ts +3 -0
- package/dist/src/skills/index.js +3 -0
- package/dist/src/skills/index.js.map +1 -0
- package/dist/src/skills/loader.d.ts +33 -0
- package/dist/src/skills/loader.js +211 -0
- package/dist/src/skills/loader.js.map +1 -0
- package/dist/src/skills/parser.d.ts +13 -0
- package/dist/src/skills/parser.js +84 -0
- package/dist/src/skills/parser.js.map +1 -0
- package/dist/src/skills/types.d.ts +52 -0
- package/dist/src/skills/types.js +7 -0
- package/dist/src/skills/types.js.map +1 -0
- package/package.json +8 -3
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SKILL.md frontmatter parser.
|
|
3
|
+
* Parses YAML frontmatter between --- markers without external dependencies.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Parse a SKILL.md file into frontmatter + body.
|
|
7
|
+
* Returns null if the file doesn't have valid frontmatter.
|
|
8
|
+
*/
|
|
9
|
+
export function parseSkillMd(raw) {
|
|
10
|
+
const trimmed = raw.trimStart();
|
|
11
|
+
if (!trimmed.startsWith("---"))
|
|
12
|
+
return null;
|
|
13
|
+
const secondFence = trimmed.indexOf("---", 3);
|
|
14
|
+
if (secondFence === -1)
|
|
15
|
+
return null;
|
|
16
|
+
const yamlBlock = trimmed.slice(3, secondFence).trim();
|
|
17
|
+
const body = trimmed.slice(secondFence + 3).trim();
|
|
18
|
+
const frontmatter = parseSimpleYaml(yamlBlock);
|
|
19
|
+
if (!frontmatter.name && !frontmatter.description)
|
|
20
|
+
return null;
|
|
21
|
+
return { frontmatter: frontmatter, body };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Minimal YAML parser for flat key-value frontmatter.
|
|
25
|
+
* Handles strings, booleans, and simple nested metadata maps.
|
|
26
|
+
* Does NOT handle arrays, multi-line values, or complex YAML.
|
|
27
|
+
*/
|
|
28
|
+
function parseSimpleYaml(yaml) {
|
|
29
|
+
const result = {};
|
|
30
|
+
let currentKey = null;
|
|
31
|
+
let currentMap = null;
|
|
32
|
+
for (const line of yaml.split("\n")) {
|
|
33
|
+
// Blank line
|
|
34
|
+
if (line.trim() === "")
|
|
35
|
+
continue;
|
|
36
|
+
// Check indentation — if indented and we're in a map, it's a nested value
|
|
37
|
+
const indent = line.length - line.trimStart().length;
|
|
38
|
+
if (indent > 0 && currentMap !== null && currentKey !== null) {
|
|
39
|
+
const kvMatch = line.trim().match(/^([a-zA-Z0-9_.-]+):\s*(.*)/);
|
|
40
|
+
if (kvMatch) {
|
|
41
|
+
currentMap[kvMatch[1]] = unquote(kvMatch[2].trim());
|
|
42
|
+
}
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
// Close any open map
|
|
46
|
+
if (currentMap !== null && currentKey !== null) {
|
|
47
|
+
result[currentKey] = currentMap;
|
|
48
|
+
currentMap = null;
|
|
49
|
+
currentKey = null;
|
|
50
|
+
}
|
|
51
|
+
// Top-level key: value
|
|
52
|
+
const kvMatch = line.match(/^([a-zA-Z0-9_-]+):\s*(.*)/);
|
|
53
|
+
if (!kvMatch)
|
|
54
|
+
continue;
|
|
55
|
+
const key = kvMatch[1];
|
|
56
|
+
const rawValue = kvMatch[2].trim();
|
|
57
|
+
// Empty value — could be a map start
|
|
58
|
+
if (rawValue === "") {
|
|
59
|
+
currentKey = key;
|
|
60
|
+
currentMap = {};
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
result[key] = parseValue(rawValue);
|
|
64
|
+
}
|
|
65
|
+
// Close trailing map
|
|
66
|
+
if (currentMap !== null && currentKey !== null) {
|
|
67
|
+
result[currentKey] = currentMap;
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
function parseValue(raw) {
|
|
72
|
+
if (raw === "true")
|
|
73
|
+
return true;
|
|
74
|
+
if (raw === "false")
|
|
75
|
+
return false;
|
|
76
|
+
return unquote(raw);
|
|
77
|
+
}
|
|
78
|
+
function unquote(s) {
|
|
79
|
+
if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) {
|
|
80
|
+
return s.slice(1, -1);
|
|
81
|
+
}
|
|
82
|
+
return s;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../src/skills/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Skills specification types.
|
|
3
|
+
* Compatible with OpenClaw, Claude Code, Codex, and ClawHub.
|
|
4
|
+
* Spec: https://agentskills.io/specification
|
|
5
|
+
*/
|
|
6
|
+
export interface SkillFrontmatter {
|
|
7
|
+
/** 1-64 chars, lowercase alphanumeric + hyphens, must match directory name */
|
|
8
|
+
name: string;
|
|
9
|
+
/** 1-1024 chars, describes what skill does and when to use it */
|
|
10
|
+
description: string;
|
|
11
|
+
/** License name or reference to bundled file */
|
|
12
|
+
license?: string;
|
|
13
|
+
/** Max 500 chars, environment requirements */
|
|
14
|
+
compatibility?: string;
|
|
15
|
+
/** Arbitrary key-value metadata (string to string) */
|
|
16
|
+
metadata?: Record<string, string>;
|
|
17
|
+
/** Space-delimited list of pre-approved tools */
|
|
18
|
+
"allowed-tools"?: string;
|
|
19
|
+
/** Expose as slash command (default: true) */
|
|
20
|
+
"user-invocable"?: boolean;
|
|
21
|
+
/** Prevent auto-invocation by LLM (default: false) */
|
|
22
|
+
"disable-model-invocation"?: boolean;
|
|
23
|
+
"argument-hint"?: string;
|
|
24
|
+
model?: string;
|
|
25
|
+
context?: string;
|
|
26
|
+
agent?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface LoadedSkill {
|
|
29
|
+
/** Skill name (from frontmatter or directory name) */
|
|
30
|
+
name: string;
|
|
31
|
+
/** Short description for metadata-level loading */
|
|
32
|
+
description: string;
|
|
33
|
+
/** Full SKILL.md body (markdown after frontmatter) */
|
|
34
|
+
body: string;
|
|
35
|
+
/** Parsed frontmatter */
|
|
36
|
+
frontmatter: SkillFrontmatter;
|
|
37
|
+
/** Absolute path to skill directory */
|
|
38
|
+
dir: string;
|
|
39
|
+
/** Where the skill was loaded from */
|
|
40
|
+
source: "workspace" | "managed" | "bundled" | "extra";
|
|
41
|
+
/** Whether the LLM can auto-invoke this skill */
|
|
42
|
+
modelInvocable: boolean;
|
|
43
|
+
/** Whether the user can invoke as a slash command */
|
|
44
|
+
userInvocable: boolean;
|
|
45
|
+
/** Pre-approved tool names */
|
|
46
|
+
allowedTools: string[];
|
|
47
|
+
}
|
|
48
|
+
export interface SkillsConfig {
|
|
49
|
+
enabled: boolean;
|
|
50
|
+
/** Additional directories to scan for skills */
|
|
51
|
+
extra_dirs?: string[];
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/skills/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "freeturtle",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.31",
|
|
4
4
|
"description": "An open-source framework for deploying autonomous AI CEOs that run onchain businesses.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/bin/freeturtle.js",
|
|
@@ -17,7 +17,10 @@
|
|
|
17
17
|
"build": "tsc",
|
|
18
18
|
"dev": "tsc --watch",
|
|
19
19
|
"lint": "eslint .",
|
|
20
|
-
"lint:fix": "eslint . --fix"
|
|
20
|
+
"lint:fix": "eslint . --fix",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"test:coverage": "vitest run --coverage"
|
|
21
24
|
},
|
|
22
25
|
"keywords": [
|
|
23
26
|
"ai",
|
|
@@ -36,9 +39,11 @@
|
|
|
36
39
|
"@types/pg": "^8.18.0",
|
|
37
40
|
"@types/qrcode-terminal": "^0.12.2",
|
|
38
41
|
"@types/ws": "^8.18.1",
|
|
42
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
39
43
|
"eslint": "^10.0.2",
|
|
40
44
|
"typescript": "^5.9.3",
|
|
41
|
-
"typescript-eslint": "^8.56.1"
|
|
45
|
+
"typescript-eslint": "^8.56.1",
|
|
46
|
+
"vitest": "^4.0.18"
|
|
42
47
|
},
|
|
43
48
|
"dependencies": {
|
|
44
49
|
"@anthropic-ai/sdk": "^0.78.0",
|