@axisagent/cli 0.1.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 +61 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +115 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/localServer.d.ts +11 -0
- package/dist/localServer.js +333 -0
- package/dist/packageWriter.d.ts +41 -0
- package/dist/packageWriter.js +48 -0
- package/dist/relayClient.d.ts +17 -0
- package/dist/relayClient.js +109 -0
- package/dist/schema.d.ts +115 -0
- package/dist/schema.js +73 -0
- package/dist/skillRegistry.d.ts +99 -0
- package/dist/skillRegistry.js +707 -0
- package/package.json +60 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { access, readdir } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { getRegistryStats } from "./skillRegistry.js";
|
|
5
|
+
async function pathExists(path) {
|
|
6
|
+
try {
|
|
7
|
+
await access(path);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function countSkillDirs(path) {
|
|
15
|
+
try {
|
|
16
|
+
const entries = await readdir(path, { withFileTypes: true });
|
|
17
|
+
return entries.filter((entry) => entry.isDirectory()).length;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function detectAgents(baseDir) {
|
|
24
|
+
const home = homedir();
|
|
25
|
+
const codexSkills = join(home, ".codex", "skills");
|
|
26
|
+
const claudeSkills = join(home, "Library", "Application Support", "Claude", "skills");
|
|
27
|
+
const openClawWorkspaceSkills = join(baseDir, ".openclaw", "skills");
|
|
28
|
+
const openClawHomeSkills = join(home, ".openclaw", "skills");
|
|
29
|
+
const openClawSkills = (await pathExists(openClawWorkspaceSkills)) ? openClawWorkspaceSkills : openClawHomeSkills;
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
id: "codex-local",
|
|
33
|
+
name: "Codex Local",
|
|
34
|
+
status: (await pathExists(codexSkills)) ? "ready" : "not-detected",
|
|
35
|
+
skillsPath: codexSkills,
|
|
36
|
+
installedSkills: await countSkillDirs(codexSkills)
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "claude-desktop",
|
|
40
|
+
name: "Claude Desktop",
|
|
41
|
+
status: (await pathExists(claudeSkills)) ? "ready" : "not-detected",
|
|
42
|
+
skillsPath: claudeSkills,
|
|
43
|
+
installedSkills: await countSkillDirs(claudeSkills)
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "openclaw",
|
|
47
|
+
name: "OpenClaw",
|
|
48
|
+
status: (await pathExists(openClawSkills)) ? "ready" : "not-detected",
|
|
49
|
+
skillsPath: openClawSkills,
|
|
50
|
+
installedSkills: await countSkillDirs(openClawSkills)
|
|
51
|
+
}
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
function normalizeApiUrl(apiUrl) {
|
|
55
|
+
return apiUrl.replace(/\/$/, "");
|
|
56
|
+
}
|
|
57
|
+
function delay(ms) {
|
|
58
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
59
|
+
}
|
|
60
|
+
async function postJson(url, body, token) {
|
|
61
|
+
const response = await fetch(url, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: {
|
|
64
|
+
"content-type": "application/json",
|
|
65
|
+
...(token ? { authorization: `Bearer ${token}` } : {})
|
|
66
|
+
},
|
|
67
|
+
body: JSON.stringify(body)
|
|
68
|
+
});
|
|
69
|
+
const payload = await response.json().catch(() => null);
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
const message = payload && typeof payload === "object" && "error" in payload ? payload.error : `Axis API returned ${response.status}`;
|
|
72
|
+
throw new Error(message);
|
|
73
|
+
}
|
|
74
|
+
return payload;
|
|
75
|
+
}
|
|
76
|
+
async function createRelayPayload(baseDir, pairingCode) {
|
|
77
|
+
return {
|
|
78
|
+
pairingCode,
|
|
79
|
+
connector: {
|
|
80
|
+
name: "Axis Local Connector",
|
|
81
|
+
version: "0.1.0",
|
|
82
|
+
baseDir,
|
|
83
|
+
runtime: `node ${process.version}`,
|
|
84
|
+
capabilities: ["heartbeat", "skill-install", "skill-scan", "axis-check", "approval-ticket"]
|
|
85
|
+
},
|
|
86
|
+
agents: await detectAgents(baseDir),
|
|
87
|
+
registry: getRegistryStats()
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
export async function connectRelay(options) {
|
|
91
|
+
const apiUrl = normalizeApiUrl(options.apiUrl);
|
|
92
|
+
const pairingCode = options.pairingCode.toUpperCase();
|
|
93
|
+
const payload = await createRelayPayload(options.baseDir, pairingCode);
|
|
94
|
+
const connected = await postJson(`${apiUrl}/v1/relay/connect`, payload);
|
|
95
|
+
console.log(`Axis Relay connected: ${connected.session.pairingCode}`);
|
|
96
|
+
console.log(`Status: ${connected.session.status}`);
|
|
97
|
+
console.log(`API: ${apiUrl}`);
|
|
98
|
+
console.log(`Expires: ${connected.session.expiresAt}`);
|
|
99
|
+
if (options.once) {
|
|
100
|
+
return connected;
|
|
101
|
+
}
|
|
102
|
+
console.log("Keeping relay alive. Press Ctrl+C to stop.");
|
|
103
|
+
while (true) {
|
|
104
|
+
await delay(options.heartbeatIntervalMs);
|
|
105
|
+
const heartbeatPayload = await createRelayPayload(options.baseDir, pairingCode);
|
|
106
|
+
const heartbeat = await postJson(`${apiUrl}/v1/relay/${pairingCode}/heartbeat`, heartbeatPayload, connected.relayToken);
|
|
107
|
+
console.log(`[${heartbeat.session.lastSeenAt}] relay ${heartbeat.session.status}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const riskSchema: z.ZodEnum<{
|
|
3
|
+
low: "low";
|
|
4
|
+
medium: "medium";
|
|
5
|
+
high: "high";
|
|
6
|
+
critical: "critical";
|
|
7
|
+
}>;
|
|
8
|
+
export declare const executionModeSchema: z.ZodEnum<{
|
|
9
|
+
"read-only": "read-only";
|
|
10
|
+
"approval-required": "approval-required";
|
|
11
|
+
"live-execution": "live-execution";
|
|
12
|
+
}>;
|
|
13
|
+
export declare const permissionSchema: z.ZodEnum<{
|
|
14
|
+
network: "network";
|
|
15
|
+
"market-data": "market-data";
|
|
16
|
+
"wallet-read": "wallet-read";
|
|
17
|
+
"wallet-signature": "wallet-signature";
|
|
18
|
+
"transaction-preview": "transaction-preview";
|
|
19
|
+
trading: "trading";
|
|
20
|
+
"api-key": "api-key";
|
|
21
|
+
notifications: "notifications";
|
|
22
|
+
"contract-call": "contract-call";
|
|
23
|
+
"filesystem-read": "filesystem-read";
|
|
24
|
+
"filesystem-write": "filesystem-write";
|
|
25
|
+
"secrets-read": "secrets-read";
|
|
26
|
+
"paid-api": "paid-api";
|
|
27
|
+
governance: "governance";
|
|
28
|
+
browser: "browser";
|
|
29
|
+
}>;
|
|
30
|
+
export declare const policySchema: z.ZodObject<{
|
|
31
|
+
defaultMode: z.ZodEnum<{
|
|
32
|
+
"read-only": "read-only";
|
|
33
|
+
"approval-required": "approval-required";
|
|
34
|
+
"live-execution": "live-execution";
|
|
35
|
+
}>;
|
|
36
|
+
requiresApproval: z.ZodBoolean;
|
|
37
|
+
networkAccess: z.ZodBoolean;
|
|
38
|
+
walletWrite: z.ZodBoolean;
|
|
39
|
+
secrets: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
40
|
+
allowedChains: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
41
|
+
maxSpendUsd: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
42
|
+
sessionLimitMinutes: z.ZodDefault<z.ZodNumber>;
|
|
43
|
+
humanReadableRule: z.ZodString;
|
|
44
|
+
}, z.core.$strip>;
|
|
45
|
+
export declare const skillDefinitionSchema: z.ZodObject<{
|
|
46
|
+
id: z.ZodString;
|
|
47
|
+
title: z.ZodString;
|
|
48
|
+
category: z.ZodString;
|
|
49
|
+
summary: z.ZodString;
|
|
50
|
+
useWhen: z.ZodString;
|
|
51
|
+
chains: z.ZodArray<z.ZodString>;
|
|
52
|
+
protocols: z.ZodArray<z.ZodString>;
|
|
53
|
+
risk: z.ZodEnum<{
|
|
54
|
+
low: "low";
|
|
55
|
+
medium: "medium";
|
|
56
|
+
high: "high";
|
|
57
|
+
critical: "critical";
|
|
58
|
+
}>;
|
|
59
|
+
executionMode: z.ZodEnum<{
|
|
60
|
+
"read-only": "read-only";
|
|
61
|
+
"approval-required": "approval-required";
|
|
62
|
+
"live-execution": "live-execution";
|
|
63
|
+
}>;
|
|
64
|
+
permissions: z.ZodArray<z.ZodEnum<{
|
|
65
|
+
network: "network";
|
|
66
|
+
"market-data": "market-data";
|
|
67
|
+
"wallet-read": "wallet-read";
|
|
68
|
+
"wallet-signature": "wallet-signature";
|
|
69
|
+
"transaction-preview": "transaction-preview";
|
|
70
|
+
trading: "trading";
|
|
71
|
+
"api-key": "api-key";
|
|
72
|
+
notifications: "notifications";
|
|
73
|
+
"contract-call": "contract-call";
|
|
74
|
+
"filesystem-read": "filesystem-read";
|
|
75
|
+
"filesystem-write": "filesystem-write";
|
|
76
|
+
"secrets-read": "secrets-read";
|
|
77
|
+
"paid-api": "paid-api";
|
|
78
|
+
governance: "governance";
|
|
79
|
+
browser: "browser";
|
|
80
|
+
}>>;
|
|
81
|
+
installTargets: z.ZodArray<z.ZodEnum<{
|
|
82
|
+
codex: "codex";
|
|
83
|
+
claude: "claude";
|
|
84
|
+
openclaw: "openclaw";
|
|
85
|
+
cursor: "cursor";
|
|
86
|
+
"generic-mcp": "generic-mcp";
|
|
87
|
+
}>>;
|
|
88
|
+
source: z.ZodString;
|
|
89
|
+
tokenUtility: z.ZodString;
|
|
90
|
+
auditNotes: z.ZodArray<z.ZodString>;
|
|
91
|
+
operations: z.ZodArray<z.ZodString>;
|
|
92
|
+
tests: z.ZodArray<z.ZodString>;
|
|
93
|
+
policy: z.ZodObject<{
|
|
94
|
+
defaultMode: z.ZodEnum<{
|
|
95
|
+
"read-only": "read-only";
|
|
96
|
+
"approval-required": "approval-required";
|
|
97
|
+
"live-execution": "live-execution";
|
|
98
|
+
}>;
|
|
99
|
+
requiresApproval: z.ZodBoolean;
|
|
100
|
+
networkAccess: z.ZodBoolean;
|
|
101
|
+
walletWrite: z.ZodBoolean;
|
|
102
|
+
secrets: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
103
|
+
allowedChains: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
104
|
+
maxSpendUsd: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
105
|
+
sessionLimitMinutes: z.ZodDefault<z.ZodNumber>;
|
|
106
|
+
humanReadableRule: z.ZodString;
|
|
107
|
+
}, z.core.$strip>;
|
|
108
|
+
}, z.core.$strip>;
|
|
109
|
+
export type SkillRisk = z.infer<typeof riskSchema>;
|
|
110
|
+
export type ExecutionMode = z.infer<typeof executionModeSchema>;
|
|
111
|
+
export type Permission = z.infer<typeof permissionSchema>;
|
|
112
|
+
export type SkillPolicy = z.infer<typeof policySchema>;
|
|
113
|
+
export type SkillDefinition = z.infer<typeof skillDefinitionSchema>;
|
|
114
|
+
export declare function assertSkillDefinition(value: unknown): SkillDefinition;
|
|
115
|
+
export declare function validateSafetyRules(skill: SkillDefinition): string[];
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const riskSchema = z.enum(["low", "medium", "high", "critical"]);
|
|
3
|
+
export const executionModeSchema = z.enum(["read-only", "approval-required", "live-execution"]);
|
|
4
|
+
export const permissionSchema = z.enum([
|
|
5
|
+
"network",
|
|
6
|
+
"market-data",
|
|
7
|
+
"wallet-read",
|
|
8
|
+
"wallet-signature",
|
|
9
|
+
"transaction-preview",
|
|
10
|
+
"trading",
|
|
11
|
+
"api-key",
|
|
12
|
+
"notifications",
|
|
13
|
+
"contract-call",
|
|
14
|
+
"filesystem-read",
|
|
15
|
+
"filesystem-write",
|
|
16
|
+
"secrets-read",
|
|
17
|
+
"paid-api",
|
|
18
|
+
"governance",
|
|
19
|
+
"browser"
|
|
20
|
+
]);
|
|
21
|
+
export const policySchema = z.object({
|
|
22
|
+
defaultMode: executionModeSchema,
|
|
23
|
+
requiresApproval: z.boolean(),
|
|
24
|
+
networkAccess: z.boolean(),
|
|
25
|
+
walletWrite: z.boolean(),
|
|
26
|
+
secrets: z.array(z.string()).default([]),
|
|
27
|
+
allowedChains: z.array(z.string()).default([]),
|
|
28
|
+
maxSpendUsd: z.number().nonnegative().nullable().default(null),
|
|
29
|
+
sessionLimitMinutes: z.number().int().positive().default(30),
|
|
30
|
+
humanReadableRule: z.string().min(12)
|
|
31
|
+
});
|
|
32
|
+
export const skillDefinitionSchema = z.object({
|
|
33
|
+
id: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
|
|
34
|
+
title: z.string().min(3),
|
|
35
|
+
category: z.string().min(3),
|
|
36
|
+
summary: z.string().min(24),
|
|
37
|
+
useWhen: z.string().min(24),
|
|
38
|
+
chains: z.array(z.string()).min(1),
|
|
39
|
+
protocols: z.array(z.string()).min(1),
|
|
40
|
+
risk: riskSchema,
|
|
41
|
+
executionMode: executionModeSchema,
|
|
42
|
+
permissions: z.array(permissionSchema).min(1),
|
|
43
|
+
installTargets: z.array(z.enum(["codex", "claude", "openclaw", "cursor", "generic-mcp"])).min(1),
|
|
44
|
+
source: z.string().url(),
|
|
45
|
+
tokenUtility: z.string().min(12),
|
|
46
|
+
auditNotes: z.array(z.string()).min(2),
|
|
47
|
+
operations: z.array(z.string()).min(3),
|
|
48
|
+
tests: z.array(z.string()).min(2),
|
|
49
|
+
policy: policySchema
|
|
50
|
+
});
|
|
51
|
+
export function assertSkillDefinition(value) {
|
|
52
|
+
return skillDefinitionSchema.parse(value);
|
|
53
|
+
}
|
|
54
|
+
export function validateSafetyRules(skill) {
|
|
55
|
+
const findings = [];
|
|
56
|
+
const moneyMoving = skill.permissions.some((permission) => ["trading", "wallet-signature", "contract-call", "paid-api"].includes(permission));
|
|
57
|
+
if (moneyMoving && skill.executionMode !== "approval-required") {
|
|
58
|
+
findings.push("Money-moving skills must use approval-required mode.");
|
|
59
|
+
}
|
|
60
|
+
if (moneyMoving && !skill.policy.requiresApproval) {
|
|
61
|
+
findings.push("Money-moving skills must require human approval.");
|
|
62
|
+
}
|
|
63
|
+
if (skill.risk === "critical" && !skill.policy.requiresApproval) {
|
|
64
|
+
findings.push("Critical skills must require approval.");
|
|
65
|
+
}
|
|
66
|
+
if (skill.policy.walletWrite && !skill.permissions.includes("wallet-signature")) {
|
|
67
|
+
findings.push("walletWrite policies must include wallet-signature permission.");
|
|
68
|
+
}
|
|
69
|
+
if (skill.permissions.includes("secrets-read") && skill.policy.secrets.length === 0) {
|
|
70
|
+
findings.push("secrets-read permissions must declare expected secret names.");
|
|
71
|
+
}
|
|
72
|
+
return findings;
|
|
73
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { SkillDefinition } from "./schema.js";
|
|
2
|
+
export declare const skills: SkillDefinition[];
|
|
3
|
+
export declare function getSkillById(id: string): {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
category: string;
|
|
7
|
+
summary: string;
|
|
8
|
+
useWhen: string;
|
|
9
|
+
chains: string[];
|
|
10
|
+
protocols: string[];
|
|
11
|
+
risk: "low" | "medium" | "high" | "critical";
|
|
12
|
+
executionMode: "read-only" | "approval-required" | "live-execution";
|
|
13
|
+
permissions: ("network" | "market-data" | "wallet-read" | "wallet-signature" | "transaction-preview" | "trading" | "api-key" | "notifications" | "contract-call" | "filesystem-read" | "filesystem-write" | "secrets-read" | "paid-api" | "governance" | "browser")[];
|
|
14
|
+
installTargets: ("codex" | "claude" | "openclaw" | "cursor" | "generic-mcp")[];
|
|
15
|
+
source: string;
|
|
16
|
+
tokenUtility: string;
|
|
17
|
+
auditNotes: string[];
|
|
18
|
+
operations: string[];
|
|
19
|
+
tests: string[];
|
|
20
|
+
policy: {
|
|
21
|
+
defaultMode: "read-only" | "approval-required" | "live-execution";
|
|
22
|
+
requiresApproval: boolean;
|
|
23
|
+
networkAccess: boolean;
|
|
24
|
+
walletWrite: boolean;
|
|
25
|
+
secrets: string[];
|
|
26
|
+
allowedChains: string[];
|
|
27
|
+
maxSpendUsd: number | null;
|
|
28
|
+
sessionLimitMinutes: number;
|
|
29
|
+
humanReadableRule: string;
|
|
30
|
+
};
|
|
31
|
+
} | undefined;
|
|
32
|
+
export declare function getSkillsByChain(chain: string): {
|
|
33
|
+
id: string;
|
|
34
|
+
title: string;
|
|
35
|
+
category: string;
|
|
36
|
+
summary: string;
|
|
37
|
+
useWhen: string;
|
|
38
|
+
chains: string[];
|
|
39
|
+
protocols: string[];
|
|
40
|
+
risk: "low" | "medium" | "high" | "critical";
|
|
41
|
+
executionMode: "read-only" | "approval-required" | "live-execution";
|
|
42
|
+
permissions: ("network" | "market-data" | "wallet-read" | "wallet-signature" | "transaction-preview" | "trading" | "api-key" | "notifications" | "contract-call" | "filesystem-read" | "filesystem-write" | "secrets-read" | "paid-api" | "governance" | "browser")[];
|
|
43
|
+
installTargets: ("codex" | "claude" | "openclaw" | "cursor" | "generic-mcp")[];
|
|
44
|
+
source: string;
|
|
45
|
+
tokenUtility: string;
|
|
46
|
+
auditNotes: string[];
|
|
47
|
+
operations: string[];
|
|
48
|
+
tests: string[];
|
|
49
|
+
policy: {
|
|
50
|
+
defaultMode: "read-only" | "approval-required" | "live-execution";
|
|
51
|
+
requiresApproval: boolean;
|
|
52
|
+
networkAccess: boolean;
|
|
53
|
+
walletWrite: boolean;
|
|
54
|
+
secrets: string[];
|
|
55
|
+
allowedChains: string[];
|
|
56
|
+
maxSpendUsd: number | null;
|
|
57
|
+
sessionLimitMinutes: number;
|
|
58
|
+
humanReadableRule: string;
|
|
59
|
+
};
|
|
60
|
+
}[];
|
|
61
|
+
export declare function getRegistryStats(): {
|
|
62
|
+
totalSkills: number;
|
|
63
|
+
baseSkills: number;
|
|
64
|
+
criticalSkills: number;
|
|
65
|
+
approvalRequired: number;
|
|
66
|
+
readOnly: number;
|
|
67
|
+
chains: string[];
|
|
68
|
+
};
|
|
69
|
+
export declare function validateRegistry(): {
|
|
70
|
+
ok: boolean;
|
|
71
|
+
findings: string[];
|
|
72
|
+
stats: {
|
|
73
|
+
totalSkills: number;
|
|
74
|
+
baseSkills: number;
|
|
75
|
+
criticalSkills: number;
|
|
76
|
+
approvalRequired: number;
|
|
77
|
+
readOnly: number;
|
|
78
|
+
chains: string[];
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
export declare function toSkillMarkdown(skill: SkillDefinition): string;
|
|
82
|
+
export declare function toPolicyJson(skill: SkillDefinition): string;
|
|
83
|
+
export declare function summarizeSkill(skill: SkillDefinition): {
|
|
84
|
+
id: string;
|
|
85
|
+
title: string;
|
|
86
|
+
category: string;
|
|
87
|
+
summary: string;
|
|
88
|
+
useWhen: string;
|
|
89
|
+
chains: string[];
|
|
90
|
+
protocols: string[];
|
|
91
|
+
risk: "low" | "medium" | "high" | "critical";
|
|
92
|
+
executionMode: "read-only" | "approval-required" | "live-execution";
|
|
93
|
+
permissions: ("network" | "market-data" | "wallet-read" | "wallet-signature" | "transaction-preview" | "trading" | "api-key" | "notifications" | "contract-call" | "filesystem-read" | "filesystem-write" | "secrets-read" | "paid-api" | "governance" | "browser")[];
|
|
94
|
+
tokenUtility: string;
|
|
95
|
+
auditNotes: string[];
|
|
96
|
+
operations: string[];
|
|
97
|
+
installCommand: string;
|
|
98
|
+
source: string;
|
|
99
|
+
};
|