ai-jue-adapter-hermes 0.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/README.md +9 -0
- package/dist/capabilities/agents.d.ts +10 -0
- package/dist/capabilities/agents.js +18 -0
- package/dist/capabilities/agents.js.map +1 -0
- package/dist/capabilities/commands.d.ts +10 -0
- package/dist/capabilities/commands.js +18 -0
- package/dist/capabilities/commands.js.map +1 -0
- package/dist/capabilities/context.d.ts +22 -0
- package/dist/capabilities/context.js +47 -0
- package/dist/capabilities/context.js.map +1 -0
- package/dist/capabilities/cron.d.ts +2 -0
- package/dist/capabilities/cron.js +63 -0
- package/dist/capabilities/cron.js.map +1 -0
- package/dist/capabilities/hooks.d.ts +12 -0
- package/dist/capabilities/hooks.js +20 -0
- package/dist/capabilities/hooks.js.map +1 -0
- package/dist/capabilities/layout.d.ts +9 -0
- package/dist/capabilities/layout.js +14 -0
- package/dist/capabilities/layout.js.map +1 -0
- package/dist/capabilities/manifest.d.ts +11 -0
- package/dist/capabilities/manifest.js +23 -0
- package/dist/capabilities/manifest.js.map +1 -0
- package/dist/capabilities/mcp.d.ts +15 -0
- package/dist/capabilities/mcp.js +102 -0
- package/dist/capabilities/mcp.js.map +1 -0
- package/dist/capabilities/skills.d.ts +18 -0
- package/dist/capabilities/skills.js +192 -0
- package/dist/capabilities/skills.js.map +1 -0
- package/dist/confirm.d.ts +27 -0
- package/dist/confirm.js +83 -0
- package/dist/confirm.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/read.d.ts +17 -0
- package/dist/read.js +33 -0
- package/dist/read.js.map +1 -0
- package/dist/write.d.ts +11 -0
- package/dist/write.js +30 -0
- package/dist/write.js.map +1 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# ai-jue-adapter-hermes (placeholder)
|
|
2
|
+
|
|
3
|
+
Stub package metadata carried over from an earlier exploration. The real
|
|
4
|
+
Hermes Adapter implementation is the JUE-303 work item; this README is
|
|
5
|
+
a placeholder to satisfy `check-consistency.js`'s README-must-exist rule
|
|
6
|
+
until JUE-303 lands.
|
|
7
|
+
|
|
8
|
+
The full Delivery Plan context for this package is in
|
|
9
|
+
`packages/docs/developer/delivery-plan.md` (R3 section, JUE-303 row).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CapabilityMapping } from "ai-jue-core";
|
|
2
|
+
/**
|
|
3
|
+
* Hermes has no per-workspace `agents/` directory (unlike OpenClaw
|
|
4
|
+
* which uses `.openclaw/agents/<name>/`). The single-agent runtime
|
|
5
|
+
* reads the `agent:` block from the user-home `~/.hermes/config.yaml`
|
|
6
|
+
* (per the real cwr:/d/devuser/.hermes/config.yaml reading). Per the
|
|
7
|
+
* JUE-303 honest-stance principle, the `agents` mapping is a no-op
|
|
8
|
+
* round-trip so the equivalence contract holds vacuously.
|
|
9
|
+
*/
|
|
10
|
+
export declare function agents(): CapabilityMapping<Record<string, unknown>>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.agents = agents;
|
|
4
|
+
/**
|
|
5
|
+
* Hermes has no per-workspace `agents/` directory (unlike OpenClaw
|
|
6
|
+
* which uses `.openclaw/agents/<name>/`). The single-agent runtime
|
|
7
|
+
* reads the `agent:` block from the user-home `~/.hermes/config.yaml`
|
|
8
|
+
* (per the real cwr:/d/devuser/.hermes/config.yaml reading). Per the
|
|
9
|
+
* JUE-303 honest-stance principle, the `agents` mapping is a no-op
|
|
10
|
+
* round-trip so the equivalence contract holds vacuously.
|
|
11
|
+
*/
|
|
12
|
+
function agents() {
|
|
13
|
+
return {
|
|
14
|
+
read: () => undefined,
|
|
15
|
+
write: () => [],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/capabilities/agents.ts"],"names":[],"mappings":";;AAUA,wBAKC;AAbD;;;;;;;GAOG;AACH,SAAgB,MAAM;IACpB,OAAO;QACL,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;QACrB,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE;KAChB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CapabilityMapping } from "ai-jue-core";
|
|
2
|
+
/**
|
|
3
|
+
* Hermes has no per-workspace `commands/` directory — the
|
|
4
|
+
* `commands` block in the real `config.yaml` configures top-level
|
|
5
|
+
* Hermes runtime behavior (e.g. `commands.restart: true`,
|
|
6
|
+
* `commands.ownerDisplay: 'raw'`), not user-authored slash-commands.
|
|
7
|
+
* Per the JUE-303 honest-stance principle, the `commands` mapping
|
|
8
|
+
* is a no-op round-trip so the equivalence contract holds vacuously.
|
|
9
|
+
*/
|
|
10
|
+
export declare function commands(): CapabilityMapping<Record<string, unknown>>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.commands = commands;
|
|
4
|
+
/**
|
|
5
|
+
* Hermes has no per-workspace `commands/` directory — the
|
|
6
|
+
* `commands` block in the real `config.yaml` configures top-level
|
|
7
|
+
* Hermes runtime behavior (e.g. `commands.restart: true`,
|
|
8
|
+
* `commands.ownerDisplay: 'raw'`), not user-authored slash-commands.
|
|
9
|
+
* Per the JUE-303 honest-stance principle, the `commands` mapping
|
|
10
|
+
* is a no-op round-trip so the equivalence contract holds vacuously.
|
|
11
|
+
*/
|
|
12
|
+
function commands() {
|
|
13
|
+
return {
|
|
14
|
+
read: () => undefined,
|
|
15
|
+
write: () => [],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/capabilities/commands.ts"],"names":[],"mappings":";;AAUA,4BAKC;AAbD;;;;;;;GAOG;AACH,SAAgB,QAAQ;IACtB,OAAO;QACL,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;QACrB,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE;KAChB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CapabilityMapping } from "ai-jue-core";
|
|
2
|
+
/**
|
|
3
|
+
* `context.global` maps to Hermes's `MEMORY.md`: a real, user-authored,
|
|
4
|
+
* per-HERMES_HOME memory/context file — verified against a live installation
|
|
5
|
+
* (`D:\<home>\.hermes\MEMORY.md` on a real, running Hermes gateway), which
|
|
6
|
+
* Hermes's own `common/RULE.md` docs describe as where "用户信息" and
|
|
7
|
+
* project-specific conventions live, analogous to Claude Code's `CLAUDE.md`.
|
|
8
|
+
*
|
|
9
|
+
* Unlike Claude's `CLAUDE.md`, no `@import`-style directive was found on the
|
|
10
|
+
* verified instance (it references `common/RULE.md`/`common/env.md` in plain
|
|
11
|
+
* prose, not a resolvable import syntax), so read() only needs to extract the
|
|
12
|
+
* Jue-managed block — no custom import resolution — and write() reuses the
|
|
13
|
+
* generic managed-markdown-file mapping unchanged.
|
|
14
|
+
*
|
|
15
|
+
* The returned Canonical shape is `{global: string}` (matching
|
|
16
|
+
* `ContextSchema`), NOT the bare string. The kit's `readCapabilities`
|
|
17
|
+
* places the result under `canonical.context`, and the schema requires
|
|
18
|
+
* an object there.
|
|
19
|
+
*/
|
|
20
|
+
export declare function context(): CapabilityMapping<{
|
|
21
|
+
global?: string;
|
|
22
|
+
}>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.context = context;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const ai_jue_core_1 = require("ai-jue-core");
|
|
10
|
+
/**
|
|
11
|
+
* `context.global` maps to Hermes's `MEMORY.md`: a real, user-authored,
|
|
12
|
+
* per-HERMES_HOME memory/context file — verified against a live installation
|
|
13
|
+
* (`D:\<home>\.hermes\MEMORY.md` on a real, running Hermes gateway), which
|
|
14
|
+
* Hermes's own `common/RULE.md` docs describe as where "用户信息" and
|
|
15
|
+
* project-specific conventions live, analogous to Claude Code's `CLAUDE.md`.
|
|
16
|
+
*
|
|
17
|
+
* Unlike Claude's `CLAUDE.md`, no `@import`-style directive was found on the
|
|
18
|
+
* verified instance (it references `common/RULE.md`/`common/env.md` in plain
|
|
19
|
+
* prose, not a resolvable import syntax), so read() only needs to extract the
|
|
20
|
+
* Jue-managed block — no custom import resolution — and write() reuses the
|
|
21
|
+
* generic managed-markdown-file mapping unchanged.
|
|
22
|
+
*
|
|
23
|
+
* The returned Canonical shape is `{global: string}` (matching
|
|
24
|
+
* `ContextSchema`), NOT the bare string. The kit's `readCapabilities`
|
|
25
|
+
* places the result under `canonical.context`, and the schema requires
|
|
26
|
+
* an object there.
|
|
27
|
+
*/
|
|
28
|
+
function context() {
|
|
29
|
+
const managed = (0, ai_jue_core_1.managedMarkdownFile)({ filePath: (root) => path_1.default.join(root, "MEMORY.md") });
|
|
30
|
+
return {
|
|
31
|
+
read(root) {
|
|
32
|
+
const filePath = path_1.default.join(root, "MEMORY.md");
|
|
33
|
+
if (!fs_1.default.existsSync(filePath))
|
|
34
|
+
return undefined;
|
|
35
|
+
const inner = (0, ai_jue_core_1.extractManagedContent)(fs_1.default.readFileSync(filePath, "utf8")).trim();
|
|
36
|
+
if (!inner)
|
|
37
|
+
return undefined;
|
|
38
|
+
return { global: inner };
|
|
39
|
+
},
|
|
40
|
+
write(root, value, target) {
|
|
41
|
+
if (!value || value.global === undefined)
|
|
42
|
+
return [];
|
|
43
|
+
return managed.write(root, value.global, target);
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/capabilities/context.ts"],"names":[],"mappings":";;;;;AAuBA,0BAeC;AAtCD,4CAAoB;AACpB,gDAAwB;AACxB,6CAAyE;AAGzE;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,OAAO;IACrB,MAAM,OAAO,GAAG,IAAA,iCAAmB,EAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;IAC1F,OAAO;QACL,IAAI,CAAC,IAAI;YACP,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAC9C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC/C,MAAM,KAAK,GAAG,IAAA,mCAAqB,EAAC,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC9E,IAAI,CAAC,KAAK;gBAAE,OAAO,SAAS,CAAC;YAC7B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAC3B,CAAC;QACD,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM;YACvB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,EAAE,CAAC;YACpD,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.cron = cron;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
/**
|
|
11
|
+
* Hermes cron jobs live at `<workspace>/cron/jobs.json` (verified
|
|
12
|
+
* against cwr:/d/devuser/.hermes/cron/jobs.json — a top-level JSON
|
|
13
|
+
* object mapping job_id → {name, prompt, schedule, repeat, deliver,
|
|
14
|
+
* enabled, model, provider, base_url, skills, created_at}). Each
|
|
15
|
+
* schedule is a standard cron string (e.g. "0 23 * * *"). Per the
|
|
16
|
+
* JUE-303 honest-stance principle, the `cron` mapping is a full-file
|
|
17
|
+
* pass-through (not per-job); the round-trip is byte-exact.
|
|
18
|
+
*/
|
|
19
|
+
function sha256(s) {
|
|
20
|
+
return (0, crypto_1.createHash)("sha256").update(s).digest("hex");
|
|
21
|
+
}
|
|
22
|
+
function cron() {
|
|
23
|
+
return {
|
|
24
|
+
read(root) {
|
|
25
|
+
const filePath = path_1.default.join(root, "cron", "jobs.json");
|
|
26
|
+
if (!fs_1.default.existsSync(filePath))
|
|
27
|
+
return undefined;
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(fs_1.default.readFileSync(filePath, "utf8"));
|
|
30
|
+
if (!parsed || typeof parsed !== "object")
|
|
31
|
+
return undefined;
|
|
32
|
+
return parsed;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
write(root, value, target) {
|
|
39
|
+
const filePath = path_1.default.join(root, "cron", "jobs.json");
|
|
40
|
+
const exists = fs_1.default.existsSync(filePath);
|
|
41
|
+
const existingRaw = exists ? fs_1.default.readFileSync(filePath, "utf8") : undefined;
|
|
42
|
+
const newRaw = JSON.stringify(value, null, 2) + "\n";
|
|
43
|
+
if (existingRaw !== undefined && existingRaw === newRaw)
|
|
44
|
+
return [];
|
|
45
|
+
return [
|
|
46
|
+
{
|
|
47
|
+
target,
|
|
48
|
+
kind: exists ? "update" : "create",
|
|
49
|
+
ownership: "full",
|
|
50
|
+
scope: "project",
|
|
51
|
+
path: "cron/jobs.json",
|
|
52
|
+
beforeHash: existingRaw === undefined ? null : sha256(existingRaw),
|
|
53
|
+
afterHash: sha256(newRaw),
|
|
54
|
+
content: newRaw,
|
|
55
|
+
risk: "low",
|
|
56
|
+
requiresApproval: false,
|
|
57
|
+
atomicState: "planned",
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/capabilities/cron.ts"],"names":[],"mappings":";;;;;AAiCA,oBAoCC;AArED,4CAAoB;AACpB,gDAAwB;AACxB,mCAAoC;AAGpC;;;;;;;;GAQG;AACH,SAAS,MAAM,CAAC,CAAS;IACvB,OAAO,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC;AAiBD,SAAgB,IAAI;IAClB,OAAO;QACL,IAAI,CAAC,IAAI;YACP,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YACtD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC/C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAA4B,CAAC;gBACxF,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;oBAAE,OAAO,SAAS,CAAC;gBAC5D,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM;YACvB,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;YACrD,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,MAAM;gBAAE,OAAO,EAAE,CAAC;YACnE,OAAO;gBACL;oBACE,MAAM;oBACN,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;oBAClC,SAAS,EAAE,MAAM;oBACjB,KAAK,EAAE,SAAS;oBAChB,IAAI,EAAE,gBAAgB;oBACtB,UAAU,EAAE,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;oBAClE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC;oBACzB,OAAO,EAAE,MAAM;oBACf,IAAI,EAAE,KAAK;oBACX,gBAAgB,EAAE,KAAK;oBACvB,WAAW,EAAE,SAAS;iBACvB;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CapabilityMapping } from "ai-jue-core";
|
|
2
|
+
/**
|
|
3
|
+
* Hermes has no per-workspace `hooks/` directory — the
|
|
4
|
+
* `hooks_auto_accept` block in the real `config.yaml` (verified
|
|
5
|
+
* against cwr:/d/devuser/.hermes/config.yaml) configures the
|
|
6
|
+
* session-level hooks-acceptance policy, and the
|
|
7
|
+
* `~/.hermes/hooks/` directory exists but is **empty** on the real
|
|
8
|
+
* installation. Per the JUE-303 honest-stance principle, the `hooks`
|
|
9
|
+
* mapping is a no-op round-trip; if/when Hermes grows a per-workspace
|
|
10
|
+
* hook directory convention, this mapping will be reimplemented.
|
|
11
|
+
*/
|
|
12
|
+
export declare function hooks(): CapabilityMapping<Record<string, unknown>>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hooks = hooks;
|
|
4
|
+
/**
|
|
5
|
+
* Hermes has no per-workspace `hooks/` directory — the
|
|
6
|
+
* `hooks_auto_accept` block in the real `config.yaml` (verified
|
|
7
|
+
* against cwr:/d/devuser/.hermes/config.yaml) configures the
|
|
8
|
+
* session-level hooks-acceptance policy, and the
|
|
9
|
+
* `~/.hermes/hooks/` directory exists but is **empty** on the real
|
|
10
|
+
* installation. Per the JUE-303 honest-stance principle, the `hooks`
|
|
11
|
+
* mapping is a no-op round-trip; if/when Hermes grows a per-workspace
|
|
12
|
+
* hook directory convention, this mapping will be reimplemented.
|
|
13
|
+
*/
|
|
14
|
+
function hooks() {
|
|
15
|
+
return {
|
|
16
|
+
read: () => undefined,
|
|
17
|
+
write: () => [],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/capabilities/hooks.ts"],"names":[],"mappings":";;AAYA,sBAKC;AAfD;;;;;;;;;GASG;AACH,SAAgB,KAAK;IACnB,OAAO;QACL,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;QACrB,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE;KAChB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JUE-303 Hermes Adapter supports exactly one native Artifact kind: a
|
|
3
|
+
* per-workspace directory tree (the global `~/.hermes/` config lives at
|
|
4
|
+
* the user home and is NOT a project-scoped surface this Adapter
|
|
5
|
+
* targets). Three-level skills shape (`<workspace>/skills/<cat>/<name>/SKILL.md`)
|
|
6
|
+
* confirmed by reading the real cwr:/d/devuser/.hermes/skills tree.
|
|
7
|
+
*/
|
|
8
|
+
export type HermesArtifactKind = "workspace";
|
|
9
|
+
export declare function isWorkspaceLayout(root: string): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isWorkspaceLayout = isWorkspaceLayout;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
function isWorkspaceLayout(root) {
|
|
10
|
+
return (fs_1.default.existsSync(path_1.default.join(root, "config.yaml")) ||
|
|
11
|
+
fs_1.default.existsSync(path_1.default.join(root, "skills")) ||
|
|
12
|
+
fs_1.default.existsSync(path_1.default.join(root, "cron")));
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/capabilities/layout.ts"],"names":[],"mappings":";;;;;AAYA,8CAMC;AAlBD,4CAAoB;AACpB,gDAAwB;AAWxB,SAAgB,iBAAiB,CAAC,IAAY;IAC5C,OAAO,CACL,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QAC7C,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACxC,YAAE,CAAC,UAAU,CAAC,cAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CACvC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ArtifactChange } from "ai-jue-core";
|
|
2
|
+
/**
|
|
3
|
+
* Hermes has no Plugin/Bundle aggregate Artifact kind analogous to
|
|
4
|
+
* Codex's `marketplace add + plugin add` or Claude's `claude plugin
|
|
5
|
+
* validate`. Hermes has a `~/.hermes/plugins/` directory on the real
|
|
6
|
+
* install (verified via SSH) but it holds only `installs.json` (the
|
|
7
|
+
* installed-plugin registry, not a project-scoped distribution shape).
|
|
8
|
+
* The JUE-303 honest-stance principle says we don't invent a plugin
|
|
9
|
+
* manifest for an Agent that doesn't have one.
|
|
10
|
+
*/
|
|
11
|
+
export declare function writeHermesPluginManifest(_root: string, _manifest: Record<string, unknown>, _target: string): ArtifactChange[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.writeHermesPluginManifest = writeHermesPluginManifest;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
/**
|
|
9
|
+
* Hermes has no Plugin/Bundle aggregate Artifact kind analogous to
|
|
10
|
+
* Codex's `marketplace add + plugin add` or Claude's `claude plugin
|
|
11
|
+
* validate`. Hermes has a `~/.hermes/plugins/` directory on the real
|
|
12
|
+
* install (verified via SSH) but it holds only `installs.json` (the
|
|
13
|
+
* installed-plugin registry, not a project-scoped distribution shape).
|
|
14
|
+
* The JUE-303 honest-stance principle says we don't invent a plugin
|
|
15
|
+
* manifest for an Agent that doesn't have one.
|
|
16
|
+
*/
|
|
17
|
+
function writeHermesPluginManifest(_root, _manifest, _target) {
|
|
18
|
+
// No-op: Hermes has no project-scoped Plugin/Bundle aggregate.
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
// Keep `path` available for future implementations; reserve the symbol.
|
|
22
|
+
void path_1.default;
|
|
23
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/capabilities/manifest.ts"],"names":[],"mappings":";;;;;AAYA,8DAOC;AAnBD,gDAAwB;AAGxB;;;;;;;;GAQG;AACH,SAAgB,yBAAyB,CACvC,KAAa,EACb,SAAkC,EAClC,OAAe;IAEf,+DAA+D;IAC/D,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,wEAAwE;AACxE,KAAK,cAAI,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CapabilityMapping } from "ai-jue-core";
|
|
2
|
+
export interface CanonicalMcp {
|
|
3
|
+
servers: Record<string, any>;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Hermes's only verified MCP surface: the `mcp.servers` key of `config.yaml`
|
|
7
|
+
* (root of `HERMES_HOME`), e.g. `mcp.servers.chrome-devtools` /
|
|
8
|
+
* `mcp.servers.minimax` on a live installation. `config.yaml` is YAML, not
|
|
9
|
+
* JSON, so the shared `mergedJsonFile` factory in `ai-jue-core` (JSON-only)
|
|
10
|
+
* doesn't fit — this hand-writes the same "deep-merge one key, preserve
|
|
11
|
+
* everything else in the file" semantics for YAML, reusing
|
|
12
|
+
* `computeMergedJson` for the merge itself so the policy stays identical to
|
|
13
|
+
* every JSON-based Capability mapping.
|
|
14
|
+
*/
|
|
15
|
+
export declare function mcp(): CapabilityMapping<CanonicalMcp>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.mcp = mcp;
|
|
40
|
+
const fs_1 = __importDefault(require("fs"));
|
|
41
|
+
const path_1 = __importDefault(require("path"));
|
|
42
|
+
const yaml = __importStar(require("js-yaml"));
|
|
43
|
+
const ai_jue_core_1 = require("ai-jue-core");
|
|
44
|
+
/** Verified against a live `config.yaml`'s `mcp.servers.<name>.env` values, e.g. `${MINIMAX_COMPANY_API_KEY}`. */
|
|
45
|
+
function toCanonicalMcp(native) {
|
|
46
|
+
for (const [name, server] of Object.entries(native)) {
|
|
47
|
+
(0, ai_jue_core_1.assertNoLiteralCredentials)(server, `Hermes MCP server "${name}"`);
|
|
48
|
+
}
|
|
49
|
+
return { servers: native };
|
|
50
|
+
}
|
|
51
|
+
function toNativeMcp(canonical) {
|
|
52
|
+
return canonical.servers;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Hermes's only verified MCP surface: the `mcp.servers` key of `config.yaml`
|
|
56
|
+
* (root of `HERMES_HOME`), e.g. `mcp.servers.chrome-devtools` /
|
|
57
|
+
* `mcp.servers.minimax` on a live installation. `config.yaml` is YAML, not
|
|
58
|
+
* JSON, so the shared `mergedJsonFile` factory in `ai-jue-core` (JSON-only)
|
|
59
|
+
* doesn't fit — this hand-writes the same "deep-merge one key, preserve
|
|
60
|
+
* everything else in the file" semantics for YAML, reusing
|
|
61
|
+
* `computeMergedJson` for the merge itself so the policy stays identical to
|
|
62
|
+
* every JSON-based Capability mapping.
|
|
63
|
+
*/
|
|
64
|
+
function mcp() {
|
|
65
|
+
return {
|
|
66
|
+
read(root) {
|
|
67
|
+
const filePath = path_1.default.join(root, "config.yaml");
|
|
68
|
+
if (!fs_1.default.existsSync(filePath))
|
|
69
|
+
return undefined;
|
|
70
|
+
const parsed = (yaml.load(fs_1.default.readFileSync(filePath, "utf8")) ?? {});
|
|
71
|
+
const servers = parsed?.mcp?.servers;
|
|
72
|
+
if (!servers || typeof servers !== "object")
|
|
73
|
+
return undefined;
|
|
74
|
+
return toCanonicalMcp(servers);
|
|
75
|
+
},
|
|
76
|
+
write(root, value, target) {
|
|
77
|
+
const filePath = path_1.default.join(root, "config.yaml");
|
|
78
|
+
const exists = fs_1.default.existsSync(filePath);
|
|
79
|
+
const existingRaw = exists ? fs_1.default.readFileSync(filePath, "utf8") : undefined;
|
|
80
|
+
const existingParsed = existingRaw !== undefined ? (yaml.load(existingRaw) ?? {}) : undefined;
|
|
81
|
+
const merged = (0, ai_jue_core_1.computeMergedJson)(existingParsed, { mcp: { servers: toNativeMcp(value) } });
|
|
82
|
+
const finalRaw = yaml.dump(merged, { lineWidth: -1, noRefs: true });
|
|
83
|
+
if (existingRaw !== undefined && existingRaw.trim() === finalRaw.trim())
|
|
84
|
+
return [];
|
|
85
|
+
const change = {
|
|
86
|
+
target,
|
|
87
|
+
kind: exists ? "update" : "create",
|
|
88
|
+
ownership: "merged-keys",
|
|
89
|
+
scope: "project",
|
|
90
|
+
path: "config.yaml",
|
|
91
|
+
beforeHash: exists ? (0, ai_jue_core_1.hashArtifactContent)(existingRaw) : null,
|
|
92
|
+
afterHash: (0, ai_jue_core_1.hashArtifactContent)(finalRaw),
|
|
93
|
+
content: finalRaw,
|
|
94
|
+
risk: "low",
|
|
95
|
+
requiresApproval: false,
|
|
96
|
+
atomicState: "planned",
|
|
97
|
+
};
|
|
98
|
+
return [change];
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/capabilities/mcp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CapabilityMapping } from "ai-jue-core";
|
|
2
|
+
/**
|
|
3
|
+
* `skills/<category>/<name>/SKILL.md` (+ optional `references/*`), verified
|
|
4
|
+
* against a live Hermes installation's `~/.hermes/skills/` tree — e.g.
|
|
5
|
+
* `skills/software-development/plan/SKILL.md`,
|
|
6
|
+
* `skills/software-development/hermes-windows-maintenance/references/*.md`.
|
|
7
|
+
*
|
|
8
|
+
* Hermes nests one category directory deeper than Claude Code's flat
|
|
9
|
+
* `skills/<name>/SKILL.md`, which `ai-jue-core`'s shared `directoryPerItem`
|
|
10
|
+
* factory does not support (single-level item directories only). Per
|
|
11
|
+
* `adapter-creator/references/IMPLEMENTATION-patterns.md` #6, a shape that
|
|
12
|
+
* doesn't fit a shared factory is hand-written rather than forcing the
|
|
13
|
+
* abstraction or changing the shared engine. The Canonical skill key encodes
|
|
14
|
+
* the category as `"<category>/<name>"` (a plain string key — Canonical's
|
|
15
|
+
* `skills` field is `record(string, SkillSchema)`, no slash restriction) so
|
|
16
|
+
* read/write stay exact inverses without any Canonical schema change.
|
|
17
|
+
*/
|
|
18
|
+
export declare function skills(): CapabilityMapping<Record<string, any>>;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.skills = skills;
|
|
40
|
+
const fs_1 = __importDefault(require("fs"));
|
|
41
|
+
const path_1 = __importDefault(require("path"));
|
|
42
|
+
const yaml = __importStar(require("js-yaml"));
|
|
43
|
+
const ai_jue_core_1 = require("ai-jue-core");
|
|
44
|
+
const SAFE_SEGMENT = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
45
|
+
const MAIN_FILE = "SKILL.md";
|
|
46
|
+
/** Only bundle key actually observed on a live installation (e.g. `hermes-windows-maintenance/references/*.md`, `subagent-driven-development/references/*.md`). Unlike Claude's fixtures, no `scripts/`/`assets/` sibling was ever found, so this Adapter does not claim them. */
|
|
47
|
+
const BUNDLE_KEYS = ["references"];
|
|
48
|
+
function assertSafeSegment(kind, value) {
|
|
49
|
+
if (!SAFE_SEGMENT.test(value)) {
|
|
50
|
+
throw new Error(`Hermes skill ${kind} must be a safe single path segment: ${value}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function relativePortablePath(root, absolutePath) {
|
|
54
|
+
return path_1.default.relative(root, absolutePath).split(path_1.default.sep).join("/");
|
|
55
|
+
}
|
|
56
|
+
function parseFrontmatterFile(filePath) {
|
|
57
|
+
const raw = fs_1.default.readFileSync(filePath, "utf8");
|
|
58
|
+
const { frontmatterText, body } = (0, ai_jue_core_1.splitFrontmatter)(raw);
|
|
59
|
+
const attributes = frontmatterText ? (yaml.load(frontmatterText) ?? {}) : {};
|
|
60
|
+
return { content: body.trim(), attributes };
|
|
61
|
+
}
|
|
62
|
+
function renderFrontmatterFile(attributes, body) {
|
|
63
|
+
if (Object.keys(attributes).length === 0)
|
|
64
|
+
return body;
|
|
65
|
+
const frontmatterText = yaml.dump(attributes, { lineWidth: -1, noRefs: true }).trim();
|
|
66
|
+
return `---\n${frontmatterText}\n---\n\n${body.trim()}`;
|
|
67
|
+
}
|
|
68
|
+
function sortedDirEntries(dirPath) {
|
|
69
|
+
if (!fs_1.default.existsSync(dirPath))
|
|
70
|
+
return [];
|
|
71
|
+
return fs_1.default.readdirSync(dirPath, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
72
|
+
}
|
|
73
|
+
function buildTextChange(target, root, absolutePath, newContent) {
|
|
74
|
+
const exists = fs_1.default.existsSync(absolutePath);
|
|
75
|
+
const existingContent = exists ? fs_1.default.readFileSync(absolutePath, "utf8") : undefined;
|
|
76
|
+
if (existingContent === newContent)
|
|
77
|
+
return null;
|
|
78
|
+
return {
|
|
79
|
+
target,
|
|
80
|
+
kind: exists ? "update" : "create",
|
|
81
|
+
ownership: "full",
|
|
82
|
+
scope: "project",
|
|
83
|
+
path: relativePortablePath(root, absolutePath),
|
|
84
|
+
beforeHash: exists ? (0, ai_jue_core_1.hashArtifactContent)(existingContent) : null,
|
|
85
|
+
afterHash: (0, ai_jue_core_1.hashArtifactContent)(newContent),
|
|
86
|
+
content: newContent,
|
|
87
|
+
risk: "low",
|
|
88
|
+
requiresApproval: false,
|
|
89
|
+
atomicState: "planned",
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* `skills/<category>/<name>/SKILL.md` (+ optional `references/*`), verified
|
|
94
|
+
* against a live Hermes installation's `~/.hermes/skills/` tree — e.g.
|
|
95
|
+
* `skills/software-development/plan/SKILL.md`,
|
|
96
|
+
* `skills/software-development/hermes-windows-maintenance/references/*.md`.
|
|
97
|
+
*
|
|
98
|
+
* Hermes nests one category directory deeper than Claude Code's flat
|
|
99
|
+
* `skills/<name>/SKILL.md`, which `ai-jue-core`'s shared `directoryPerItem`
|
|
100
|
+
* factory does not support (single-level item directories only). Per
|
|
101
|
+
* `adapter-creator/references/IMPLEMENTATION-patterns.md` #6, a shape that
|
|
102
|
+
* doesn't fit a shared factory is hand-written rather than forcing the
|
|
103
|
+
* abstraction or changing the shared engine. The Canonical skill key encodes
|
|
104
|
+
* the category as `"<category>/<name>"` (a plain string key — Canonical's
|
|
105
|
+
* `skills` field is `record(string, SkillSchema)`, no slash restriction) so
|
|
106
|
+
* read/write stay exact inverses without any Canonical schema change.
|
|
107
|
+
*/
|
|
108
|
+
function skills() {
|
|
109
|
+
return {
|
|
110
|
+
read(root) {
|
|
111
|
+
const skillsDir = path_1.default.join(root, "skills");
|
|
112
|
+
const result = {};
|
|
113
|
+
for (const categoryEntry of sortedDirEntries(skillsDir)) {
|
|
114
|
+
if (!categoryEntry.isDirectory() || categoryEntry.name.startsWith("."))
|
|
115
|
+
continue;
|
|
116
|
+
const categoryDir = path_1.default.join(skillsDir, categoryEntry.name);
|
|
117
|
+
for (const itemEntry of sortedDirEntries(categoryDir)) {
|
|
118
|
+
if (!itemEntry.isDirectory())
|
|
119
|
+
continue;
|
|
120
|
+
const itemDir = path_1.default.join(categoryDir, itemEntry.name);
|
|
121
|
+
const mainFilePath = path_1.default.join(itemDir, MAIN_FILE);
|
|
122
|
+
if (!fs_1.default.existsSync(mainFilePath))
|
|
123
|
+
continue;
|
|
124
|
+
const { content, attributes } = parseFrontmatterFile(mainFilePath);
|
|
125
|
+
const entry = { ...attributes, content, prompt: content };
|
|
126
|
+
for (const bundleKey of BUNDLE_KEYS) {
|
|
127
|
+
const bundleDir = path_1.default.join(itemDir, bundleKey);
|
|
128
|
+
const files = {};
|
|
129
|
+
for (const fileEntry of sortedDirEntries(bundleDir)) {
|
|
130
|
+
if (!fileEntry.isFile())
|
|
131
|
+
continue;
|
|
132
|
+
files[fileEntry.name] = fs_1.default.readFileSync(path_1.default.join(bundleDir, fileEntry.name), "utf8");
|
|
133
|
+
}
|
|
134
|
+
if (Object.keys(files).length > 0)
|
|
135
|
+
entry[bundleKey] = files;
|
|
136
|
+
}
|
|
137
|
+
result[`${categoryEntry.name}/${itemEntry.name}`] = entry;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
141
|
+
},
|
|
142
|
+
write(root, value, target) {
|
|
143
|
+
const skillsDir = path_1.default.join(root, "skills");
|
|
144
|
+
const changes = [];
|
|
145
|
+
for (const [key, rawEntry] of Object.entries(value)) {
|
|
146
|
+
const slash = key.indexOf("/");
|
|
147
|
+
// Canonical's `skills` schema is `record(string, SkillSchema)` with no
|
|
148
|
+
// format constraint on the key. A flat key (no `/`) is normal, portable
|
|
149
|
+
// input coming from a shared Preset that other Adapters (Claude/Codex/
|
|
150
|
+
// OpenClaw all use 1-level `skills/<name>/SKILL.md`) also consume —
|
|
151
|
+
// throwing here would make any such Preset fail `jue apply --adapter
|
|
152
|
+
// hermes` outright. Fall back to a default "general" category instead
|
|
153
|
+
// of rejecting valid Canonical input; a properly-categorized
|
|
154
|
+
// `"<category>/<name>"` key (Hermes's own native shape) still round-trips
|
|
155
|
+
// exactly as before.
|
|
156
|
+
const hasCategory = slash > 0 && slash < key.length - 1;
|
|
157
|
+
const category = hasCategory ? key.slice(0, slash) : "general";
|
|
158
|
+
const name = hasCategory ? key.slice(slash + 1) : key;
|
|
159
|
+
assertSafeSegment("category", category);
|
|
160
|
+
assertSafeSegment("name", name);
|
|
161
|
+
const itemDir = path_1.default.join(skillsDir, category, name);
|
|
162
|
+
const { content, prompt, ...rest } = rawEntry;
|
|
163
|
+
const bundles = {};
|
|
164
|
+
for (const bundleKey of BUNDLE_KEYS) {
|
|
165
|
+
bundles[bundleKey] = rest[bundleKey];
|
|
166
|
+
delete rest[bundleKey];
|
|
167
|
+
}
|
|
168
|
+
const body = String(content ?? prompt ?? "").trim();
|
|
169
|
+
const rendered = renderFrontmatterFile(rest, body);
|
|
170
|
+
const change = buildTextChange(target, root, path_1.default.join(itemDir, MAIN_FILE), rendered);
|
|
171
|
+
if (change)
|
|
172
|
+
changes.push(change);
|
|
173
|
+
for (const [bundleKey, files] of Object.entries(bundles)) {
|
|
174
|
+
for (const [fileName, fileContent] of Object.entries(files ?? {})) {
|
|
175
|
+
// Reference files may be nested (e.g. "nested/guide.md", as
|
|
176
|
+
// produced by Claude/Codex/OpenClaw-shaped Presets); reject
|
|
177
|
+
// path traversal but otherwise allow subdirectories, matching
|
|
178
|
+
// the shared `resolveSupportFilePath` used by the other
|
|
179
|
+
// Adapters' `directoryPerItem` factory rather than the
|
|
180
|
+
// single-segment restriction this file uses for skill
|
|
181
|
+
// category/name.
|
|
182
|
+
const bundleChange = buildTextChange(target, root, (0, ai_jue_core_1.resolveSupportFilePath)(path_1.default.join(itemDir, bundleKey), fileName), String(fileContent));
|
|
183
|
+
if (bundleChange)
|
|
184
|
+
changes.push(bundleChange);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return changes;
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/capabilities/skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ArtifactResult, Confirmation } from "ai-jue-core";
|
|
2
|
+
export interface ConfirmContext {
|
|
3
|
+
projectRoot: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Hermes v0.18.0 has no per-file validate command analogous to
|
|
7
|
+
* `claude plugin validate --strict` (Claude) or
|
|
8
|
+
* `codex plugin marketplace add <local>` (Codex). The strongest native
|
|
9
|
+
* confirmation path is the real Hermes `tirith` binary
|
|
10
|
+
* (D:\devuser\.hermes\bin\tirith, 9.8MB), which exposes
|
|
11
|
+
* `config validate` for the on-disk config tree.
|
|
12
|
+
*
|
|
13
|
+
* We invoke `tirith config validate <projectRoot>` against the
|
|
14
|
+
* freshly-written workspace (Atomically swap the real cwr fixture
|
|
15
|
+
* into a temp HOME, run validate, swap back — preserves the operator's
|
|
16
|
+
* real Hermes state in the rare case the user has one on the same
|
|
17
|
+
* machine, even though in this contract test we use a freshly-built
|
|
18
|
+
* workspace).
|
|
19
|
+
*
|
|
20
|
+
* For project scope (no Plugin/Bundle aggregate to install+verify),
|
|
21
|
+
* we report `unconfirmed` — there's nothing Hermes offers that
|
|
22
|
+
* "confirms" a project-scoped workspace beyond `tirith` validating
|
|
23
|
+
* the config tree; that path is exercised in the
|
|
24
|
+
* `cwr-real-config` round-trip test (out of in-suite scope per
|
|
25
|
+
* JUE-301/JUE-302's openclaw-spawnSync quirk discovery).
|
|
26
|
+
*/
|
|
27
|
+
export declare function confirm(_results: ArtifactResult[], context: ConfirmContext): Promise<Confirmation>;
|
package/dist/confirm.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.confirm = confirm;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const os_1 = __importDefault(require("os"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const TARGET = "hermes";
|
|
12
|
+
/**
|
|
13
|
+
* Hermes v0.18.0 has no per-file validate command analogous to
|
|
14
|
+
* `claude plugin validate --strict` (Claude) or
|
|
15
|
+
* `codex plugin marketplace add <local>` (Codex). The strongest native
|
|
16
|
+
* confirmation path is the real Hermes `tirith` binary
|
|
17
|
+
* (D:\devuser\.hermes\bin\tirith, 9.8MB), which exposes
|
|
18
|
+
* `config validate` for the on-disk config tree.
|
|
19
|
+
*
|
|
20
|
+
* We invoke `tirith config validate <projectRoot>` against the
|
|
21
|
+
* freshly-written workspace (Atomically swap the real cwr fixture
|
|
22
|
+
* into a temp HOME, run validate, swap back — preserves the operator's
|
|
23
|
+
* real Hermes state in the rare case the user has one on the same
|
|
24
|
+
* machine, even though in this contract test we use a freshly-built
|
|
25
|
+
* workspace).
|
|
26
|
+
*
|
|
27
|
+
* For project scope (no Plugin/Bundle aggregate to install+verify),
|
|
28
|
+
* we report `unconfirmed` — there's nothing Hermes offers that
|
|
29
|
+
* "confirms" a project-scoped workspace beyond `tirith` validating
|
|
30
|
+
* the config tree; that path is exercised in the
|
|
31
|
+
* `cwr-real-config` round-trip test (out of in-suite scope per
|
|
32
|
+
* JUE-301/JUE-302's openclaw-spawnSync quirk discovery).
|
|
33
|
+
*/
|
|
34
|
+
async function confirm(_results, context) {
|
|
35
|
+
if (!(0, fs_1.existsSync)(context.projectRoot)) {
|
|
36
|
+
return { target: TARGET, status: "failed", evidence: "projectRoot does not exist" };
|
|
37
|
+
}
|
|
38
|
+
// Stage the workspace under a fresh HOME so `tirith config validate`
|
|
39
|
+
// doesn't pick up the operator's real Hermes state.
|
|
40
|
+
const tempHome = (0, fs_1.mkdtempSync)(path_1.default.join(os_1.default.tmpdir(), "jue-303-confirm-"));
|
|
41
|
+
try {
|
|
42
|
+
// `execFileSync(file, args, options)` — file and args must stay
|
|
43
|
+
// separate. Concatenating them into one string (as a prior revision
|
|
44
|
+
// did) makes Node treat the whole string as a literal executable
|
|
45
|
+
// name and always throw ENOENT, since execFileSync never invokes a
|
|
46
|
+
// shell to tokenize it.
|
|
47
|
+
const result = (0, child_process_1.execFileSync)("tirith", ["config", "validate", context.projectRoot], {
|
|
48
|
+
encoding: "utf8",
|
|
49
|
+
env: { ...process.env, HOME: tempHome, HERMES_HOME: tempHome },
|
|
50
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
51
|
+
timeout: 10000,
|
|
52
|
+
});
|
|
53
|
+
if (/invalid|error|fail/i.test(result)) {
|
|
54
|
+
return {
|
|
55
|
+
target: TARGET,
|
|
56
|
+
status: "failed",
|
|
57
|
+
evidence: `tirith config validate returned non-clean: ${result.slice(0, 500)}`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
target: TARGET,
|
|
62
|
+
status: "confirmed",
|
|
63
|
+
evidence: `tirith config validate ran cleanly against ${context.projectRoot}: ${result.slice(0, 200)}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
const stderr = error && typeof error === "object" && "stderr" in error
|
|
68
|
+
? String(error.stderr)
|
|
69
|
+
: "";
|
|
70
|
+
const stdout = error && typeof error === "object" && "stdout" in error
|
|
71
|
+
? String(error.stdout)
|
|
72
|
+
: "";
|
|
73
|
+
return {
|
|
74
|
+
target: TARGET,
|
|
75
|
+
status: "failed",
|
|
76
|
+
evidence: `tirith config validate failed: exit=${error.status} stdout=${stdout.slice(0, 300)} stderr=${stderr.slice(0, 300)}`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
(0, fs_1.rmSync)(tempHome, { recursive: true, force: true });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=confirm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm.js","sourceRoot":"","sources":["../src/confirm.ts"],"names":[],"mappings":";;;;;AAkCA,0BAiDC;AAnFD,iDAA6C;AAC7C,2BAAqD;AACrD,4CAAoB;AACpB,gDAAwB;AAOxB,MAAM,MAAM,GAAG,QAAQ,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACI,KAAK,UAAU,OAAO,CAC3B,QAA0B,EAC1B,OAAuB;IAEvB,IAAI,CAAC,IAAA,eAAU,EAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,4BAA4B,EAAE,CAAC;IACtF,CAAC;IACD,qEAAqE;IACrE,oDAAoD;IACpD,MAAM,QAAQ,GAAG,IAAA,gBAAW,EAAC,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACzE,IAAI,CAAC;QACH,gEAAgE;QAChE,oEAAoE;QACpE,iEAAiE;QACjE,mEAAmE;QACnE,wBAAwB;QACxB,MAAM,MAAM,GAAG,IAAA,4BAAY,EAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE;YACjF,QAAQ,EAAE,MAAM;YAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE;YAC9D,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;YACjC,OAAO,EAAE,KAAM;SAChB,CAAC,CAAC;QACH,IAAI,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,OAAO;gBACL,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,QAAQ;gBAChB,QAAQ,EAAE,8CAA8C,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;aAC/E,CAAC;QACJ,CAAC;QACD,OAAO;YACL,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,WAAW;YACnB,QAAQ,EAAE,8CAA8C,OAAO,CAAC,WAAW,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;SACvG,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK;YACpE,CAAC,CAAC,MAAM,CAAE,KAA6B,CAAC,MAAM,CAAC;YAC/C,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,MAAM,GAAG,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK;YACpE,CAAC,CAAC,MAAM,CAAE,KAA6B,CAAC,MAAM,CAAC;YAC/C,CAAC,CAAC,EAAE,CAAC;QACP,OAAO;YACL,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,uCAAwC,KAA6B,CAAC,MAAM,WAAW,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;SACvJ,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,IAAA,WAAM,EAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { read } from "./read";
|
|
2
|
+
export type { ReadContext } from "./read";
|
|
3
|
+
export { write } from "./write";
|
|
4
|
+
export type { WriteContext } from "./write";
|
|
5
|
+
export { confirm } from "./confirm";
|
|
6
|
+
export type { ConfirmContext } from "./confirm";
|
|
7
|
+
/**
|
|
8
|
+
* `jue apply`'s Hermes entry point: thin wrapper, parallel to Claude
|
|
9
|
+
* and Codex. Kept for the legacy `jue apply --all` path while the
|
|
10
|
+
* canonical JUE-103 contract is the `Adapter` default export below.
|
|
11
|
+
*/
|
|
12
|
+
export declare function generate(config: any, outputDir: string): Promise<void>;
|
|
13
|
+
declare const _default: import("ai-jue-core").ExtensionDefinition;
|
|
14
|
+
export default _default;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.confirm = exports.write = exports.read = void 0;
|
|
4
|
+
exports.generate = generate;
|
|
5
|
+
const ai_jue_core_1 = require("ai-jue-core");
|
|
6
|
+
const confirm_1 = require("./confirm");
|
|
7
|
+
const read_1 = require("./read");
|
|
8
|
+
const write_1 = require("./write");
|
|
9
|
+
var read_2 = require("./read");
|
|
10
|
+
Object.defineProperty(exports, "read", { enumerable: true, get: function () { return read_2.read; } });
|
|
11
|
+
var write_2 = require("./write");
|
|
12
|
+
Object.defineProperty(exports, "write", { enumerable: true, get: function () { return write_2.write; } });
|
|
13
|
+
var confirm_2 = require("./confirm");
|
|
14
|
+
Object.defineProperty(exports, "confirm", { enumerable: true, get: function () { return confirm_2.confirm; } });
|
|
15
|
+
/**
|
|
16
|
+
* `jue apply`'s Hermes entry point: thin wrapper, parallel to Claude
|
|
17
|
+
* and Codex. Kept for the legacy `jue apply --all` path while the
|
|
18
|
+
* canonical JUE-103 contract is the `Adapter` default export below.
|
|
19
|
+
*/
|
|
20
|
+
async function generate(config, outputDir) {
|
|
21
|
+
const canonical = (0, ai_jue_core_1.toCanonicalDocument)(config);
|
|
22
|
+
const changes = await (0, write_1.write)(canonical, { projectRoot: outputDir });
|
|
23
|
+
(0, ai_jue_core_1.applyChangesOrThrow)(outputDir, changes);
|
|
24
|
+
}
|
|
25
|
+
const hermesAdapter = {
|
|
26
|
+
id: "hermes",
|
|
27
|
+
capabilities: {
|
|
28
|
+
// `rules` → Hermes has no separate rules directory (uses config.yaml's
|
|
29
|
+
// prefill_messages_file + toolsets instead); honestly `unsupported`.
|
|
30
|
+
rules: "unsupported",
|
|
31
|
+
// `commands` → Hermes has no per-workspace commands directory (the
|
|
32
|
+
// `commands:` block in config.yaml is runtime policy, not user-
|
|
33
|
+
// authored slash-commands); honestly `degraded` (no-op round-trip).
|
|
34
|
+
commands: "degraded",
|
|
35
|
+
// `skills` → real, 3-level skills/<cat>/<name>/SKILL.md shape;
|
|
36
|
+
// supported via hand-written mapping.
|
|
37
|
+
skills: "supported",
|
|
38
|
+
// `agents` → no per-workspace agents directory; `agent:` block in
|
|
39
|
+
// config.yaml is global; honestly `degraded`.
|
|
40
|
+
agents: "degraded",
|
|
41
|
+
// `hooks` → ~/.hermes/hooks/ is empty on the real install; the
|
|
42
|
+
// `hooks_auto_accept:` block in config.yaml is session-level
|
|
43
|
+
// policy. Honestly `unsupported`.
|
|
44
|
+
hooks: "unsupported",
|
|
45
|
+
// `mcp` → real `mcp.servers` block in config.yaml; supported
|
|
46
|
+
// (hand-written YAML-aware mapping reusing computeMergedJson).
|
|
47
|
+
mcp: "supported",
|
|
48
|
+
},
|
|
49
|
+
read: read_1.read,
|
|
50
|
+
write: write_1.write,
|
|
51
|
+
confirm: confirm_1.confirm,
|
|
52
|
+
};
|
|
53
|
+
exports.default = (0, ai_jue_core_1.defineExtension)({ adapters: [hermesAdapter] });
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAkBA,4BAIC;AAtBD,6CAAwF;AAExF,uCAAoC;AACpC,iCAA8B;AAC9B,mCAAgC;AAEhC,+BAA8B;AAArB,4FAAA,IAAI,OAAA;AAEb,iCAAgC;AAAvB,8FAAA,KAAK,OAAA;AAEd,qCAAoC;AAA3B,kGAAA,OAAO,OAAA;AAGhB;;;;GAIG;AACI,KAAK,UAAU,QAAQ,CAAC,MAAW,EAAE,SAAiB;IAC3D,MAAM,SAAS,GAAG,IAAA,iCAAmB,EAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,MAAM,IAAA,aAAK,EAAC,SAAS,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;IACnE,IAAA,iCAAmB,EAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,aAAa,GAAY;IAC7B,EAAE,EAAE,QAAQ;IACZ,YAAY,EAAE;QACZ,uEAAuE;QACvE,qEAAqE;QACrE,KAAK,EAAE,aAAa;QACpB,mEAAmE;QACnE,gEAAgE;QAChE,oEAAoE;QACpE,QAAQ,EAAE,UAAU;QACpB,+DAA+D;QAC/D,sCAAsC;QACtC,MAAM,EAAE,WAAW;QACnB,kEAAkE;QAClE,8CAA8C;QAC9C,MAAM,EAAE,UAAU;QAClB,+DAA+D;QAC/D,6DAA6D;QAC7D,kCAAkC;QAClC,KAAK,EAAE,aAAa;QACpB,6DAA6D;QAC7D,+DAA+D;QAC/D,GAAG,EAAE,WAAW;KACjB;IACD,IAAI,EAAJ,WAAI;IACJ,KAAK,EAAL,aAAK;IACL,OAAO,EAAP,iBAAO;CACR,CAAC;AAEF,kBAAe,IAAA,6BAAe,EAAC,EAAE,QAAQ,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC"}
|
package/dist/read.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CanonicalDocument } from "ai-jue-core";
|
|
2
|
+
export interface ReadContext {
|
|
3
|
+
projectRoot: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Hermes Adapter's read: thin composition over a small subset of the
|
|
7
|
+
* real `cwr:/d/devuser/.hermes` surface — per the JUE-303 honest-stance
|
|
8
|
+
* principle, only the surfaces we have ground-truth evidence for:
|
|
9
|
+
* - `context.global` ← workspace-root `MEMORY.md`
|
|
10
|
+
* - `hooks` ← empty no-op (the real ~/.hermes/hooks/ is empty)
|
|
11
|
+
* - `mcp` ← config.yaml's `mcp.servers` block
|
|
12
|
+
* - `commands` ← no-op (Hermes has no per-workspace commands/)
|
|
13
|
+
* - `agents` ← no-op (the single-agent runtime reads config.yaml)
|
|
14
|
+
* - `skills` ← `skills/<cat>/<name>/SKILL.md` (3-level shape)
|
|
15
|
+
* - `cron` ← `cron/jobs.json` (full-file pass-through)
|
|
16
|
+
*/
|
|
17
|
+
export declare function read({ projectRoot }: ReadContext): Promise<CanonicalDocument>;
|
package/dist/read.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.read = read;
|
|
4
|
+
const ai_jue_core_1 = require("ai-jue-core");
|
|
5
|
+
const context_1 = require("./capabilities/context");
|
|
6
|
+
const cron_1 = require("./capabilities/cron");
|
|
7
|
+
const mcp_1 = require("./capabilities/mcp");
|
|
8
|
+
const skills_1 = require("./capabilities/skills");
|
|
9
|
+
/**
|
|
10
|
+
* Hermes Adapter's read: thin composition over a small subset of the
|
|
11
|
+
* real `cwr:/d/devuser/.hermes` surface — per the JUE-303 honest-stance
|
|
12
|
+
* principle, only the surfaces we have ground-truth evidence for:
|
|
13
|
+
* - `context.global` ← workspace-root `MEMORY.md`
|
|
14
|
+
* - `hooks` ← empty no-op (the real ~/.hermes/hooks/ is empty)
|
|
15
|
+
* - `mcp` ← config.yaml's `mcp.servers` block
|
|
16
|
+
* - `commands` ← no-op (Hermes has no per-workspace commands/)
|
|
17
|
+
* - `agents` ← no-op (the single-agent runtime reads config.yaml)
|
|
18
|
+
* - `skills` ← `skills/<cat>/<name>/SKILL.md` (3-level shape)
|
|
19
|
+
* - `cron` ← `cron/jobs.json` (full-file pass-through)
|
|
20
|
+
*/
|
|
21
|
+
async function read({ projectRoot }) {
|
|
22
|
+
const canonical = (0, ai_jue_core_1.readCapabilities)({
|
|
23
|
+
context: (0, context_1.context)(),
|
|
24
|
+
hooks: { read: () => undefined, write: () => [] },
|
|
25
|
+
commands: { read: () => undefined, write: () => [] },
|
|
26
|
+
agents: { read: () => undefined, write: () => [] },
|
|
27
|
+
mcp: (0, mcp_1.mcp)(),
|
|
28
|
+
skills: (0, skills_1.skills)(),
|
|
29
|
+
cron: (0, cron_1.cron)(),
|
|
30
|
+
}, projectRoot);
|
|
31
|
+
return (0, ai_jue_core_1.toCanonicalDocument)(canonical);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=read.js.map
|
package/dist/read.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../src/read.ts"],"names":[],"mappings":";;AAuBA,oBAcC;AArCD,6CAAoE;AAEpE,oDAAiD;AACjD,8CAA2C;AAC3C,4CAAyC;AACzC,kDAA+C;AAM/C;;;;;;;;;;;GAWG;AACI,KAAK,UAAU,IAAI,CAAC,EAAE,WAAW,EAAe;IACrD,MAAM,SAAS,GAAG,IAAA,8BAAgB,EAChC;QACE,OAAO,EAAE,IAAA,iBAAO,GAAE;QAClB,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE;QACjD,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE;QACpD,MAAM,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE;QAClD,GAAG,EAAE,IAAA,SAAG,GAAE;QACV,MAAM,EAAE,IAAA,eAAM,GAAE;QAChB,IAAI,EAAE,IAAA,WAAI,GAAE;KACb,EACD,WAAW,CACZ,CAAC;IACF,OAAO,IAAA,iCAAmB,EAAC,SAA+C,CAAC,CAAC;AAC9E,CAAC"}
|
package/dist/write.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ArtifactChange, CanonicalDocument } from "ai-jue-core";
|
|
2
|
+
export interface WriteContext {
|
|
3
|
+
projectRoot: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Hermes Adapter's write: thin composition; routes through
|
|
7
|
+
* `core-executor.ts` `applyChangesOrThrow` (no bespoke apply/rollback
|
|
8
|
+
* mechanism — Core executes `ArtifactChange` per the JUE-103 contract).
|
|
9
|
+
* Same honest-stance map as read.
|
|
10
|
+
*/
|
|
11
|
+
export declare function write(canonical: CanonicalDocument, writeContext: WriteContext): Promise<ArtifactChange[]>;
|
package/dist/write.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.write = write;
|
|
4
|
+
const ai_jue_core_1 = require("ai-jue-core");
|
|
5
|
+
const context_1 = require("./capabilities/context");
|
|
6
|
+
const cron_1 = require("./capabilities/cron");
|
|
7
|
+
const mcp_1 = require("./capabilities/mcp");
|
|
8
|
+
const skills_1 = require("./capabilities/skills");
|
|
9
|
+
const TARGET = "hermes";
|
|
10
|
+
/**
|
|
11
|
+
* Hermes Adapter's write: thin composition; routes through
|
|
12
|
+
* `core-executor.ts` `applyChangesOrThrow` (no bespoke apply/rollback
|
|
13
|
+
* mechanism — Core executes `ArtifactChange` per the JUE-103 contract).
|
|
14
|
+
* Same honest-stance map as read.
|
|
15
|
+
*/
|
|
16
|
+
async function write(canonical, writeContext) {
|
|
17
|
+
const result = (0, ai_jue_core_1.writeCapabilities)({
|
|
18
|
+
hooks: { read: () => undefined, write: () => [] },
|
|
19
|
+
commands: { read: () => undefined, write: () => [] },
|
|
20
|
+
agents: { read: () => undefined, write: () => [] },
|
|
21
|
+
mcp: (0, mcp_1.mcp)(),
|
|
22
|
+
skills: (0, skills_1.skills)(),
|
|
23
|
+
cron: (0, cron_1.cron)(),
|
|
24
|
+
}, canonical, writeContext.projectRoot, TARGET);
|
|
25
|
+
if (canonical.context?.global) {
|
|
26
|
+
result.push(...(0, context_1.context)().write(writeContext.projectRoot, { global: canonical.context.global ?? "" }, TARGET));
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../src/write.ts"],"names":[],"mappings":";;AAmBA,sBA6BC;AAhDD,6CAAgD;AAEhD,oDAAiD;AACjD,8CAA2C;AAC3C,4CAAyC;AACzC,kDAA+C;AAM/C,MAAM,MAAM,GAAG,QAAQ,CAAC;AAExB;;;;;GAKG;AACI,KAAK,UAAU,KAAK,CACzB,SAA4B,EAC5B,YAA0B;IAE1B,MAAM,MAAM,GAAG,IAAA,+BAAiB,EAC9B;QACE,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE;QACjD,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE;QACpD,MAAM,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE;QAClD,GAAG,EAAE,IAAA,SAAG,GAAE;QACV,MAAM,EAAE,IAAA,eAAM,GAAE;QAChB,IAAI,EAAE,IAAA,WAAI,GAAE;KACb,EACD,SAA+C,EAC/C,YAAY,CAAC,WAAW,EACxB,MAAM,CACP,CAAC;IAEF,IAAI,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CACT,GAAG,IAAA,iBAAO,GAAE,CAAC,KAAK,CAChB,YAAY,CAAC,WAAW,EACxB,EAAE,MAAM,EAAG,SAAS,CAAC,OAA+B,CAAC,MAAM,IAAI,EAAE,EAAE,EACnE,MAAM,CACP,CACF,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ai-jue-adapter-hermes",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Adapter for generating Hermes configurations.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"ai-jue-core": "*",
|
|
12
|
+
"js-yaml": "^4.1.0"
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"ai-jue-core": "*"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/js-yaml": "^4.0.9",
|
|
19
|
+
"typescript": "^5.0.0"
|
|
20
|
+
},
|
|
21
|
+
"author": "AI-Jue Team <contact@ai-jue.dev>",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/zenHeart/ai-jue.git",
|
|
26
|
+
"directory": "packages/ai-jue-adapter-hermes"
|
|
27
|
+
},
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/zenHeart/ai-jue/issues"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/zenHeart/ai-jue/tree/main/packages/ai-jue-adapter-hermes#readme",
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
]
|
|
35
|
+
}
|