@openape/ape-agent 2.1.0 → 2.2.0
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/default-skills/bash/SKILL.md +3 -1
- package/default-skills/file/SKILL.md +3 -1
- package/default-skills/http/SKILL.md +3 -1
- package/default-skills/mail/SKILL.md +9 -1
- package/default-skills/tasks/SKILL.md +9 -1
- package/default-skills/time/SKILL.md +3 -1
- package/dist/bridge.mjs +48 -33
- package/package.json +2 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bash
|
|
3
3
|
description: When a task can't be done with the other curated tools (file.read, http.get, tasks.create, mail.list, etc.), use bash — runs any shell command on the agent host through the DDISA grant cycle.
|
|
4
|
-
|
|
4
|
+
metadata:
|
|
5
|
+
openape:
|
|
6
|
+
requires_tools: [bash]
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# Shell access via ape-shell
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: file
|
|
3
3
|
description: When the user asks you to read, write, or check a file in your home directory, use the file.read / file.write tools — they're $HOME-jailed and safer than bash cat.
|
|
4
|
-
|
|
4
|
+
metadata:
|
|
5
|
+
openape:
|
|
6
|
+
requires_tools: [file.read]
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# Files in $HOME
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: http
|
|
3
3
|
description: When the user asks to fetch a webpage, hit a REST API, or POST JSON to an endpoint, use the http.get / http.post tools — never invent URLs.
|
|
4
|
-
|
|
4
|
+
metadata:
|
|
5
|
+
openape:
|
|
6
|
+
requires_tools: [http.get]
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# HTTP fetch
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mail
|
|
3
3
|
description: When the user asks about their inbox — what's there, search for an email, recent unread — use mail.list / mail.search.
|
|
4
|
-
|
|
4
|
+
metadata:
|
|
5
|
+
openape:
|
|
6
|
+
requires_tools: [mail.list]
|
|
7
|
+
openclaw:
|
|
8
|
+
# If the o365-cli binary isn't on PATH the underlying tool fails
|
|
9
|
+
# at runtime — skip the skill from the prompt so the LLM doesn't
|
|
10
|
+
# try to use it on a host where it can't run.
|
|
11
|
+
requires:
|
|
12
|
+
bins: [o365-cli]
|
|
5
13
|
---
|
|
6
14
|
|
|
7
15
|
# Inbox (o365-cli)
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tasks
|
|
3
3
|
description: When the user wants to see, create, or schedule a task/reminder/wiedervorlage on their personal task list, use tasks.list / tasks.create.
|
|
4
|
-
|
|
4
|
+
metadata:
|
|
5
|
+
openape:
|
|
6
|
+
requires_tools: [tasks.list]
|
|
7
|
+
openclaw:
|
|
8
|
+
# The bash escape-hatch path uses ape-tasks; surface it as a soft
|
|
9
|
+
# dependency so on a host without ape-tasks the LLM is told this
|
|
10
|
+
# skill doesn't apply.
|
|
11
|
+
requires:
|
|
12
|
+
bins: [ape-tasks]
|
|
5
13
|
---
|
|
6
14
|
|
|
7
15
|
# Personal tasks (ape-tasks)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: time
|
|
3
3
|
description: When the user asks for the current time, date, or wants a sanity-check that the runtime is alive, use the time.now tool — never guess.
|
|
4
|
-
|
|
4
|
+
metadata:
|
|
5
|
+
openape:
|
|
6
|
+
requires_tools: [time.now]
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# Time and date
|
package/dist/bridge.mjs
CHANGED
|
@@ -3800,10 +3800,12 @@ function shouldAutoAccept(peerEmail, identity, allowlist) {
|
|
|
3800
3800
|
}
|
|
3801
3801
|
|
|
3802
3802
|
// src/skills.ts
|
|
3803
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
3803
3804
|
import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync7, statSync } from "fs";
|
|
3804
3805
|
import { homedir as homedir8 } from "os";
|
|
3805
3806
|
import { dirname as dirname2, join as join8, resolve as resolve2 } from "path";
|
|
3806
3807
|
import { fileURLToPath } from "url";
|
|
3808
|
+
import { parse as parseYaml } from "yaml";
|
|
3807
3809
|
var SKILLS_SUBDIR = [".openape", "agent", "skills"];
|
|
3808
3810
|
var SOUL_PATH_PARTS = [".openape", "agent", "SOUL.md"];
|
|
3809
3811
|
function soulPath(home = homedir8()) {
|
|
@@ -3828,40 +3830,48 @@ function parseFrontmatter(content) {
|
|
|
3828
3830
|
const closeIdx = trimmed.indexOf("\n---", 3);
|
|
3829
3831
|
if (closeIdx < 0) return null;
|
|
3830
3832
|
const fmBlock = trimmed.slice(3, closeIdx).trim();
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
if (inlineArray) {
|
|
3856
|
-
fields[key] = inlineArray[1].split(",").map((s2) => s2.trim().replace(/^["']|["']$/g, "")).filter(Boolean).join(",");
|
|
3857
|
-
continue;
|
|
3833
|
+
let parsed;
|
|
3834
|
+
try {
|
|
3835
|
+
parsed = parseYaml(fmBlock);
|
|
3836
|
+
} catch {
|
|
3837
|
+
return null;
|
|
3838
|
+
}
|
|
3839
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
3840
|
+
const fields = parsed;
|
|
3841
|
+
const name = typeof fields.name === "string" ? fields.name.trim() : "";
|
|
3842
|
+
const description = typeof fields.description === "string" ? fields.description.trim() : "";
|
|
3843
|
+
if (!name || !description) return null;
|
|
3844
|
+
function asStringArray(v2) {
|
|
3845
|
+
if (!Array.isArray(v2)) return void 0;
|
|
3846
|
+
const out = v2.map((x2) => typeof x2 === "string" ? x2.trim() : "").filter((s2) => s2.length > 0);
|
|
3847
|
+
return out.length > 0 ? out : void 0;
|
|
3848
|
+
}
|
|
3849
|
+
const meta = fields.metadata && typeof fields.metadata === "object" && !Array.isArray(fields.metadata) ? fields.metadata : {};
|
|
3850
|
+
const openapeMeta = meta.openape && typeof meta.openape === "object" && !Array.isArray(meta.openape) ? meta.openape : {};
|
|
3851
|
+
const openclawMeta = meta.openclaw && typeof meta.openclaw === "object" && !Array.isArray(meta.openclaw) ? meta.openclaw : {};
|
|
3852
|
+
const requiresTools = asStringArray(openapeMeta.requires_tools) ?? asStringArray(fields.requires_tools);
|
|
3853
|
+
function readRequiresBins(scope) {
|
|
3854
|
+
const requires = scope.requires;
|
|
3855
|
+
if (requires && typeof requires === "object" && !Array.isArray(requires)) {
|
|
3856
|
+
return asStringArray(requires.bins);
|
|
3858
3857
|
}
|
|
3859
|
-
|
|
3858
|
+
return void 0;
|
|
3859
|
+
}
|
|
3860
|
+
const requiresBins = readRequiresBins(openclawMeta) ?? readRequiresBins(openapeMeta) ?? asStringArray(fields.requires_bins);
|
|
3861
|
+
return { name, description, requiresTools, requiresBins };
|
|
3862
|
+
}
|
|
3863
|
+
var binCheckCache = /* @__PURE__ */ new Map();
|
|
3864
|
+
function hasBinaryOnPath(bin) {
|
|
3865
|
+
const cached = binCheckCache.get(bin);
|
|
3866
|
+
if (cached !== void 0) return cached;
|
|
3867
|
+
let found = false;
|
|
3868
|
+
try {
|
|
3869
|
+
execFileSync3("/usr/bin/which", [bin], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
3870
|
+
found = true;
|
|
3871
|
+
} catch {
|
|
3860
3872
|
}
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
const requiresTools = fields.requires_tools ? fields.requires_tools.split(",").map((s2) => s2.trim()).filter(Boolean) : void 0;
|
|
3864
|
-
return { name: fields.name, description: fields.description, requiresTools };
|
|
3873
|
+
binCheckCache.set(bin, found);
|
|
3874
|
+
return found;
|
|
3865
3875
|
}
|
|
3866
3876
|
function scanSkillsDir(dir) {
|
|
3867
3877
|
if (!existsSync6(dir)) return [];
|
|
@@ -3894,7 +3904,8 @@ function scanSkillsDir(dir) {
|
|
|
3894
3904
|
name: fm.name,
|
|
3895
3905
|
description: fm.description,
|
|
3896
3906
|
filePath: skillPath,
|
|
3897
|
-
requiresTools: fm.requiresTools
|
|
3907
|
+
requiresTools: fm.requiresTools,
|
|
3908
|
+
requiresBins: fm.requiresBins
|
|
3898
3909
|
});
|
|
3899
3910
|
}
|
|
3900
3911
|
return out;
|
|
@@ -3914,6 +3925,10 @@ function composeSkills(home, enabledTools) {
|
|
|
3914
3925
|
const allPresent = s2.requiresTools.every((t2) => enabled.has(t2));
|
|
3915
3926
|
if (!allPresent) continue;
|
|
3916
3927
|
}
|
|
3928
|
+
if (s2.requiresBins && s2.requiresBins.length > 0) {
|
|
3929
|
+
const allBinsPresent = s2.requiresBins.every((b2) => hasBinaryOnPath(b2));
|
|
3930
|
+
if (!allBinsPresent) continue;
|
|
3931
|
+
}
|
|
3917
3932
|
out.push(s2);
|
|
3918
3933
|
}
|
|
3919
3934
|
out.sort((a2, b2) => a2.name.localeCompare(b2.name));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openape/ape-agent",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "OpenApe agent runtime: per-agent process that connects to chat.openape.ai, runs the LLM loop with tools + cron tasks, and streams replies back to owners.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"jose": "^5.9.0",
|
|
22
22
|
"ofetch": "^1.4.1",
|
|
23
23
|
"ws": "^8.18.0",
|
|
24
|
+
"yaml": "^2.8.0",
|
|
24
25
|
"@openape/apes": "1.22.0",
|
|
25
26
|
"@openape/cli-auth": "0.4.0"
|
|
26
27
|
},
|