@herdctl/core 5.4.3 → 5.6.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/dist/config/__tests__/schema.test.js +19 -0
- package/dist/config/__tests__/schema.test.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +3 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/schema.d.ts +10 -18
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +4 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/distribution/__tests__/agent-discovery.test.d.ts +7 -0
- package/dist/distribution/__tests__/agent-discovery.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/agent-discovery.test.js +443 -0
- package/dist/distribution/__tests__/agent-discovery.test.js.map +1 -0
- package/dist/distribution/__tests__/agent-info.test.d.ts +7 -0
- package/dist/distribution/__tests__/agent-info.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/agent-info.test.js +568 -0
- package/dist/distribution/__tests__/agent-info.test.js.map +1 -0
- package/dist/distribution/__tests__/agent-remover.test.d.ts +7 -0
- package/dist/distribution/__tests__/agent-remover.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/agent-remover.test.js +498 -0
- package/dist/distribution/__tests__/agent-remover.test.js.map +1 -0
- package/dist/distribution/__tests__/agent-repo-metadata.test.d.ts +5 -0
- package/dist/distribution/__tests__/agent-repo-metadata.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/agent-repo-metadata.test.js +500 -0
- package/dist/distribution/__tests__/agent-repo-metadata.test.js.map +1 -0
- package/dist/distribution/__tests__/env-scanner.test.d.ts +5 -0
- package/dist/distribution/__tests__/env-scanner.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/env-scanner.test.js +576 -0
- package/dist/distribution/__tests__/env-scanner.test.js.map +1 -0
- package/dist/distribution/__tests__/file-installer.test.d.ts +7 -0
- package/dist/distribution/__tests__/file-installer.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/file-installer.test.js +714 -0
- package/dist/distribution/__tests__/file-installer.test.js.map +1 -0
- package/dist/distribution/__tests__/fleet-config-updater.test.d.ts +7 -0
- package/dist/distribution/__tests__/fleet-config-updater.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/fleet-config-updater.test.js +531 -0
- package/dist/distribution/__tests__/fleet-config-updater.test.js.map +1 -0
- package/dist/distribution/__tests__/installation-metadata.test.d.ts +2 -0
- package/dist/distribution/__tests__/installation-metadata.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/installation-metadata.test.js +292 -0
- package/dist/distribution/__tests__/installation-metadata.test.js.map +1 -0
- package/dist/distribution/__tests__/integration.test.d.ts +10 -0
- package/dist/distribution/__tests__/integration.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/integration.test.js +522 -0
- package/dist/distribution/__tests__/integration.test.js.map +1 -0
- package/dist/distribution/__tests__/repository-fetcher.test.d.ts +5 -0
- package/dist/distribution/__tests__/repository-fetcher.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/repository-fetcher.test.js +386 -0
- package/dist/distribution/__tests__/repository-fetcher.test.js.map +1 -0
- package/dist/distribution/__tests__/repository-validator.test.d.ts +7 -0
- package/dist/distribution/__tests__/repository-validator.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/repository-validator.test.js +447 -0
- package/dist/distribution/__tests__/repository-validator.test.js.map +1 -0
- package/dist/distribution/__tests__/source-specifier.test.d.ts +5 -0
- package/dist/distribution/__tests__/source-specifier.test.d.ts.map +1 -0
- package/dist/distribution/__tests__/source-specifier.test.js +533 -0
- package/dist/distribution/__tests__/source-specifier.test.js.map +1 -0
- package/dist/distribution/agent-discovery.d.ts +81 -0
- package/dist/distribution/agent-discovery.d.ts.map +1 -0
- package/dist/distribution/agent-discovery.js +264 -0
- package/dist/distribution/agent-discovery.js.map +1 -0
- package/dist/distribution/agent-info.d.ts +86 -0
- package/dist/distribution/agent-info.d.ts.map +1 -0
- package/dist/distribution/agent-info.js +225 -0
- package/dist/distribution/agent-info.js.map +1 -0
- package/dist/distribution/agent-remover.d.ts +83 -0
- package/dist/distribution/agent-remover.d.ts.map +1 -0
- package/dist/distribution/agent-remover.js +222 -0
- package/dist/distribution/agent-remover.js.map +1 -0
- package/dist/distribution/agent-repo-metadata.d.ts +181 -0
- package/dist/distribution/agent-repo-metadata.d.ts.map +1 -0
- package/dist/distribution/agent-repo-metadata.js +143 -0
- package/dist/distribution/agent-repo-metadata.js.map +1 -0
- package/dist/distribution/env-scanner.d.ts +78 -0
- package/dist/distribution/env-scanner.d.ts.map +1 -0
- package/dist/distribution/env-scanner.js +144 -0
- package/dist/distribution/env-scanner.js.map +1 -0
- package/dist/distribution/file-installer.d.ts +80 -0
- package/dist/distribution/file-installer.d.ts.map +1 -0
- package/dist/distribution/file-installer.js +268 -0
- package/dist/distribution/file-installer.js.map +1 -0
- package/dist/distribution/fleet-config-updater.d.ts +96 -0
- package/dist/distribution/fleet-config-updater.d.ts.map +1 -0
- package/dist/distribution/fleet-config-updater.js +266 -0
- package/dist/distribution/fleet-config-updater.js.map +1 -0
- package/dist/distribution/index.d.ts +23 -0
- package/dist/distribution/index.d.ts.map +1 -0
- package/dist/distribution/index.js +42 -0
- package/dist/distribution/index.js.map +1 -0
- package/dist/distribution/installation-metadata.d.ts +191 -0
- package/dist/distribution/installation-metadata.d.ts.map +1 -0
- package/dist/distribution/installation-metadata.js +100 -0
- package/dist/distribution/installation-metadata.js.map +1 -0
- package/dist/distribution/repository-fetcher.d.ts +104 -0
- package/dist/distribution/repository-fetcher.d.ts.map +1 -0
- package/dist/distribution/repository-fetcher.js +246 -0
- package/dist/distribution/repository-fetcher.js.map +1 -0
- package/dist/distribution/repository-validator.d.ts +86 -0
- package/dist/distribution/repository-validator.d.ts.map +1 -0
- package/dist/distribution/repository-validator.js +296 -0
- package/dist/distribution/repository-validator.js.map +1 -0
- package/dist/distribution/source-specifier.d.ts +106 -0
- package/dist/distribution/source-specifier.d.ts.map +1 -0
- package/dist/distribution/source-specifier.js +247 -0
- package/dist/distribution/source-specifier.js.map +1 -0
- package/dist/fleet-manager/errors.d.ts +15 -0
- package/dist/fleet-manager/errors.d.ts.map +1 -1
- package/dist/fleet-manager/errors.js +16 -0
- package/dist/fleet-manager/errors.js.map +1 -1
- package/dist/fleet-manager/fleet-manager.d.ts.map +1 -1
- package/dist/fleet-manager/fleet-manager.js +32 -9
- package/dist/fleet-manager/fleet-manager.js.map +1 -1
- package/dist/hooks/types.d.ts +2 -3
- package/dist/hooks/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/runner/job-executor.js +10 -10
- package/dist/runner/job-executor.js.map +1 -1
- package/dist/runner/message-processor.d.ts.map +1 -1
- package/dist/runner/message-processor.js +7 -2
- package/dist/runner/message-processor.js.map +1 -1
- package/dist/runner/runtime/cli-runtime.d.ts +3 -2
- package/dist/runner/runtime/cli-runtime.d.ts.map +1 -1
- package/dist/runner/runtime/cli-session-path.d.ts +0 -20
- package/dist/runner/runtime/cli-session-path.d.ts.map +1 -1
- package/dist/runner/runtime/cli-session-path.js +1 -1
- package/dist/runner/runtime/cli-session-path.js.map +1 -1
- package/dist/runner/runtime/container-manager.js +1 -1
- package/dist/runner/runtime/container-manager.js.map +1 -1
- package/dist/runner/runtime/container-runner.d.ts.map +1 -1
- package/dist/runner/runtime/container-runner.js +5 -1
- package/dist/runner/runtime/container-runner.js.map +1 -1
- package/dist/runner/runtime/factory.d.ts +2 -1
- package/dist/runner/runtime/factory.d.ts.map +1 -1
- package/dist/runner/runtime/index.d.ts +4 -10
- package/dist/runner/runtime/index.d.ts.map +1 -1
- package/dist/runner/runtime/index.js +4 -13
- package/dist/runner/runtime/index.js.map +1 -1
- package/dist/scheduler/errors.d.ts +15 -0
- package/dist/scheduler/errors.d.ts.map +1 -1
- package/dist/state/schemas/session-info.d.ts +2 -1
- package/dist/state/schemas/session-info.d.ts.map +1 -1
- package/dist/state/schemas/session-info.js +1 -1
- package/dist/state/schemas/session-info.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-discovery.d.ts","sourceRoot":"","sources":["../../src/distribution/agent-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAAE,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAE3F,OAAO,EAAE,KAAK,oBAAoB,EAA8B,MAAM,4BAA4B,CAAC;AAQnG;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAC;IACnB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,iDAAiD;IACjD,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAMD,6CAA6C;AAC7C,eAAO,MAAM,0BAA0B,EAAE,qBAAoD,CAAC;AAE9F,0CAA0C;AAC1C,eAAO,MAAM,wBAAwB,EAAE,qBAAkD,CAAC;AAE1F;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,iBAAiB;gBAC5C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB;CAIzD;AAkID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAyHxF"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Discovery for herdctl
|
|
3
|
+
*
|
|
4
|
+
* Scans the filesystem to discover agents referenced in herdctl.yaml.
|
|
5
|
+
* Identifies which agents were installed via `herdctl agent add` (have metadata.json)
|
|
6
|
+
* vs manually created agents.
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from "node:fs/promises";
|
|
9
|
+
import { dirname, join, resolve } from "node:path";
|
|
10
|
+
import { parse as parseYaml } from "yaml";
|
|
11
|
+
import { FleetManagerError } from "../fleet-manager/errors.js";
|
|
12
|
+
import { createLogger } from "../utils/logger.js";
|
|
13
|
+
import { InstallationMetadataSchema } from "./installation-metadata.js";
|
|
14
|
+
const logger = createLogger("distribution:discovery");
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Error Classes
|
|
17
|
+
// =============================================================================
|
|
18
|
+
/** Error code: herdctl.yaml doesn't exist */
|
|
19
|
+
export const DISCOVERY_CONFIG_NOT_FOUND = "DISCOVERY_CONFIG_NOT_FOUND";
|
|
20
|
+
/** Error code: herdctl.yaml is invalid */
|
|
21
|
+
export const DISCOVERY_CONFIG_INVALID = "DISCOVERY_CONFIG_INVALID";
|
|
22
|
+
/**
|
|
23
|
+
* Error thrown when agent discovery fails
|
|
24
|
+
*/
|
|
25
|
+
export class AgentDiscoveryError extends FleetManagerError {
|
|
26
|
+
constructor(message, code) {
|
|
27
|
+
super(message, { code });
|
|
28
|
+
this.name = "AgentDiscoveryError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// =============================================================================
|
|
32
|
+
// Helper Functions
|
|
33
|
+
// =============================================================================
|
|
34
|
+
/**
|
|
35
|
+
* Check if a path exists
|
|
36
|
+
*/
|
|
37
|
+
async function pathExists(filePath) {
|
|
38
|
+
try {
|
|
39
|
+
await fs.access(filePath);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Safely read and parse a JSON file
|
|
48
|
+
*/
|
|
49
|
+
async function readJsonFile(filePath) {
|
|
50
|
+
try {
|
|
51
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
52
|
+
return JSON.parse(content);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Safely read and parse a YAML file
|
|
60
|
+
*/
|
|
61
|
+
async function readYamlFile(filePath) {
|
|
62
|
+
try {
|
|
63
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
64
|
+
const parsed = parseYaml(content);
|
|
65
|
+
if (parsed && typeof parsed === "object") {
|
|
66
|
+
return parsed;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Parse agent reference from fleet config
|
|
76
|
+
*
|
|
77
|
+
* Fleet config agents can be:
|
|
78
|
+
* - Object form: { path: "./agents/my-agent/agent.yaml" }
|
|
79
|
+
* - String form: "./agents/my-agent/agent.yaml" (less common)
|
|
80
|
+
*/
|
|
81
|
+
function parseAgentReference(entry) {
|
|
82
|
+
if (typeof entry === "string") {
|
|
83
|
+
return entry;
|
|
84
|
+
}
|
|
85
|
+
if (entry && typeof entry === "object" && "path" in entry) {
|
|
86
|
+
const pathValue = entry.path;
|
|
87
|
+
if (typeof pathValue === "string") {
|
|
88
|
+
return pathValue;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
function extractAgentYamlInfo(parsed) {
|
|
94
|
+
const name = parsed.name;
|
|
95
|
+
if (typeof name !== "string" || name.trim() === "") {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const result = { name };
|
|
99
|
+
// Extract description if present
|
|
100
|
+
const description = parsed.description;
|
|
101
|
+
if (typeof description === "string" && description.trim() !== "") {
|
|
102
|
+
result.description = description;
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Read and validate installation metadata from metadata.json
|
|
108
|
+
*/
|
|
109
|
+
async function readInstallationMetadata(agentDir) {
|
|
110
|
+
const metadataPath = join(agentDir, "metadata.json");
|
|
111
|
+
const raw = await readJsonFile(metadataPath);
|
|
112
|
+
if (!raw) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
// Validate with Zod schema
|
|
116
|
+
const result = InstallationMetadataSchema.safeParse(raw);
|
|
117
|
+
if (!result.success) {
|
|
118
|
+
logger.debug("Invalid metadata.json, skipping", { path: metadataPath });
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
return result.data;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Read version from herdctl.json if present
|
|
125
|
+
*/
|
|
126
|
+
async function readHerdctlJsonVersion(agentDir) {
|
|
127
|
+
const herdctlJsonPath = join(agentDir, "herdctl.json");
|
|
128
|
+
const parsed = await readJsonFile(herdctlJsonPath);
|
|
129
|
+
if (parsed && typeof parsed.version === "string") {
|
|
130
|
+
return parsed.version;
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
// =============================================================================
|
|
135
|
+
// Main Discovery Function
|
|
136
|
+
// =============================================================================
|
|
137
|
+
/**
|
|
138
|
+
* Discover agents referenced in the fleet configuration
|
|
139
|
+
*
|
|
140
|
+
* This function:
|
|
141
|
+
* 1. Reads herdctl.yaml and extracts agent references
|
|
142
|
+
* 2. For each reference, checks if the agent directory exists
|
|
143
|
+
* 3. Reads agent.yaml to get name and description
|
|
144
|
+
* 4. Checks for metadata.json to determine if installed via herdctl
|
|
145
|
+
* 5. Returns all discovered agents sorted by name
|
|
146
|
+
*
|
|
147
|
+
* @param options - Discovery options including config path
|
|
148
|
+
* @returns Discovery result with list of agents
|
|
149
|
+
* @throws {AgentDiscoveryError} When discovery fails
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* const result = await discoverAgents({
|
|
154
|
+
* configPath: "/path/to/herdctl.yaml"
|
|
155
|
+
* });
|
|
156
|
+
*
|
|
157
|
+
* for (const agent of result.agents) {
|
|
158
|
+
* console.log(`${agent.name}: ${agent.installed ? 'installed' : 'manual'}`);
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
export async function discoverAgents(options) {
|
|
163
|
+
const { configPath } = options;
|
|
164
|
+
const baseDir = options.baseDir ?? dirname(configPath);
|
|
165
|
+
logger.debug("Starting agent discovery", { configPath, baseDir });
|
|
166
|
+
// ==========================================================================
|
|
167
|
+
// Step 1: Read fleet config
|
|
168
|
+
// ==========================================================================
|
|
169
|
+
if (!(await pathExists(configPath))) {
|
|
170
|
+
throw new AgentDiscoveryError(`Fleet config not found at ${configPath}. Run 'herdctl init fleet' to create one.`, DISCOVERY_CONFIG_NOT_FOUND);
|
|
171
|
+
}
|
|
172
|
+
const fleetConfig = await readYamlFile(configPath);
|
|
173
|
+
if (!fleetConfig) {
|
|
174
|
+
throw new AgentDiscoveryError(`Failed to parse fleet config at ${configPath}`, DISCOVERY_CONFIG_INVALID);
|
|
175
|
+
}
|
|
176
|
+
// ==========================================================================
|
|
177
|
+
// Step 2: Extract agent references
|
|
178
|
+
// ==========================================================================
|
|
179
|
+
const agentsArray = fleetConfig.agents;
|
|
180
|
+
if (!Array.isArray(agentsArray)) {
|
|
181
|
+
logger.debug("No agents array in fleet config, returning empty result");
|
|
182
|
+
return { agents: [] };
|
|
183
|
+
}
|
|
184
|
+
const agents = [];
|
|
185
|
+
// ==========================================================================
|
|
186
|
+
// Step 3: Process each agent reference
|
|
187
|
+
// ==========================================================================
|
|
188
|
+
for (const entry of agentsArray) {
|
|
189
|
+
const agentPath = parseAgentReference(entry);
|
|
190
|
+
if (!agentPath) {
|
|
191
|
+
logger.debug("Skipping invalid agent reference", { entry });
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
// Resolve the agent.yaml path relative to baseDir
|
|
195
|
+
const absoluteAgentYamlPath = resolve(baseDir, agentPath);
|
|
196
|
+
const agentDir = dirname(absoluteAgentYamlPath);
|
|
197
|
+
// Check if agent directory exists
|
|
198
|
+
if (!(await pathExists(agentDir))) {
|
|
199
|
+
logger.debug("Agent directory not found, skipping", { path: agentDir });
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
// Read agent.yaml
|
|
203
|
+
const agentYaml = await readYamlFile(absoluteAgentYamlPath);
|
|
204
|
+
let name;
|
|
205
|
+
let description;
|
|
206
|
+
if (agentYaml) {
|
|
207
|
+
const info = extractAgentYamlInfo(agentYaml);
|
|
208
|
+
if (info) {
|
|
209
|
+
name = info.name;
|
|
210
|
+
description = info.description;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// Fallback to directory name if agent.yaml doesn't have valid name
|
|
214
|
+
name = dirname(agentPath).split("/").pop() ?? "unknown";
|
|
215
|
+
logger.debug("agent.yaml missing name, using directory name", { name, path: agentPath });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
// agent.yaml doesn't exist or is invalid, use directory name
|
|
220
|
+
name = dirname(agentPath).split("/").pop() ?? "unknown";
|
|
221
|
+
logger.debug("agent.yaml not found or invalid, using directory name", {
|
|
222
|
+
name,
|
|
223
|
+
path: agentPath,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
// Check for metadata.json (indicates installed via herdctl)
|
|
227
|
+
const metadata = await readInstallationMetadata(agentDir);
|
|
228
|
+
const installed = metadata !== null;
|
|
229
|
+
// Get version from metadata or herdctl.json
|
|
230
|
+
let version;
|
|
231
|
+
if (metadata?.source?.version) {
|
|
232
|
+
version = metadata.source.version;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
version = await readHerdctlJsonVersion(agentDir);
|
|
236
|
+
}
|
|
237
|
+
agents.push({
|
|
238
|
+
name,
|
|
239
|
+
installed,
|
|
240
|
+
metadata: metadata ?? undefined,
|
|
241
|
+
path: agentDir,
|
|
242
|
+
configPath: agentPath,
|
|
243
|
+
description,
|
|
244
|
+
version,
|
|
245
|
+
});
|
|
246
|
+
logger.debug("Discovered agent", {
|
|
247
|
+
name,
|
|
248
|
+
installed,
|
|
249
|
+
path: agentDir,
|
|
250
|
+
version,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
// ==========================================================================
|
|
254
|
+
// Step 4: Sort by name and return
|
|
255
|
+
// ==========================================================================
|
|
256
|
+
agents.sort((a, b) => a.name.localeCompare(b.name));
|
|
257
|
+
logger.info("Agent discovery complete", {
|
|
258
|
+
total: agents.length,
|
|
259
|
+
installed: agents.filter((a) => a.installed).length,
|
|
260
|
+
manual: agents.filter((a) => !a.installed).length,
|
|
261
|
+
});
|
|
262
|
+
return { agents };
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=agent-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-discovery.js","sourceRoot":"","sources":["../../src/distribution/agent-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Information Module
|
|
3
|
+
*
|
|
4
|
+
* Provides detailed information about a specific agent in the fleet.
|
|
5
|
+
* Gathers data from multiple sources:
|
|
6
|
+
* - agent.yaml (name, description, schedules)
|
|
7
|
+
* - metadata.json (installation info for installed agents)
|
|
8
|
+
* - herdctl.json (repository metadata)
|
|
9
|
+
* - Environment variable scanning
|
|
10
|
+
* - File listing
|
|
11
|
+
*/
|
|
12
|
+
import { type AgentRepoMetadata } from "./agent-repo-metadata.js";
|
|
13
|
+
import { type EnvScanResult } from "./env-scanner.js";
|
|
14
|
+
import type { InstallationMetadata } from "./installation-metadata.js";
|
|
15
|
+
/**
|
|
16
|
+
* Detailed information about an agent
|
|
17
|
+
*/
|
|
18
|
+
export interface AgentDetailedInfo {
|
|
19
|
+
/** Agent name */
|
|
20
|
+
name: string;
|
|
21
|
+
/** Agent description (from agent.yaml) */
|
|
22
|
+
description?: string;
|
|
23
|
+
/** Whether installed via herdctl agent add */
|
|
24
|
+
installed: boolean;
|
|
25
|
+
/** Full installation metadata (source, timestamp, etc.) */
|
|
26
|
+
metadata?: InstallationMetadata;
|
|
27
|
+
/** Full path to agent directory */
|
|
28
|
+
path: string;
|
|
29
|
+
/** Relative config path (e.g., ./agents/my-agent/agent.yaml) */
|
|
30
|
+
configPath: string;
|
|
31
|
+
/** Version (from metadata source or herdctl.json) */
|
|
32
|
+
version?: string;
|
|
33
|
+
/** herdctl.json metadata if present */
|
|
34
|
+
repoMetadata?: AgentRepoMetadata;
|
|
35
|
+
/** Environment variables scanned from agent.yaml */
|
|
36
|
+
envVariables?: EnvScanResult;
|
|
37
|
+
/** Schedules configured in agent.yaml (record of name -> schedule config) */
|
|
38
|
+
schedules?: Record<string, unknown>;
|
|
39
|
+
/** Whether a workspace directory exists */
|
|
40
|
+
hasWorkspace: boolean;
|
|
41
|
+
/** List of files in the agent directory */
|
|
42
|
+
files: string[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Options for getting agent information
|
|
46
|
+
*/
|
|
47
|
+
export interface AgentInfoOptions {
|
|
48
|
+
/** Agent name to look up */
|
|
49
|
+
name: string;
|
|
50
|
+
/** Path to herdctl.yaml */
|
|
51
|
+
configPath: string;
|
|
52
|
+
/** Base directory of the project */
|
|
53
|
+
baseDir?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get detailed information about a specific agent
|
|
57
|
+
*
|
|
58
|
+
* This function:
|
|
59
|
+
* 1. Uses discoverAgents() to find the agent by name
|
|
60
|
+
* 2. If not found, returns null
|
|
61
|
+
* 3. If found, gathers additional details:
|
|
62
|
+
* - Scans agent.yaml for environment variables
|
|
63
|
+
* - Extracts schedules from agent.yaml
|
|
64
|
+
* - Reads herdctl.json if present
|
|
65
|
+
* - Checks for workspace directory
|
|
66
|
+
* - Lists all files in the agent directory
|
|
67
|
+
*
|
|
68
|
+
* @param options - Options including agent name and config path
|
|
69
|
+
* @returns Detailed agent information or null if not found
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const info = await getAgentInfo({
|
|
74
|
+
* name: "website-monitor",
|
|
75
|
+
* configPath: "/path/to/herdctl.yaml"
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* if (info) {
|
|
79
|
+
* console.log(`Agent: ${info.name}`);
|
|
80
|
+
* console.log(`Installed: ${info.installed}`);
|
|
81
|
+
* console.log(`Has workspace: ${info.hasWorkspace}`);
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare function getAgentInfo(options: AgentInfoOptions): Promise<AgentDetailedInfo | null>;
|
|
86
|
+
//# sourceMappingURL=agent-info.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-info.d.ts","sourceRoot":"","sources":["../../src/distribution/agent-info.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,EAAE,KAAK,iBAAiB,EAA2B,MAAM,0BAA0B,CAAC;AAC3F,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,kBAAkB,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAQvE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,SAAS,EAAE,OAAO,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,oDAAoD;IACpD,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,2CAA2C;IAC3C,YAAY,EAAE,OAAO,CAAC;IACtB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA2FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CA2G/F"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Information Module
|
|
3
|
+
*
|
|
4
|
+
* Provides detailed information about a specific agent in the fleet.
|
|
5
|
+
* Gathers data from multiple sources:
|
|
6
|
+
* - agent.yaml (name, description, schedules)
|
|
7
|
+
* - metadata.json (installation info for installed agents)
|
|
8
|
+
* - herdctl.json (repository metadata)
|
|
9
|
+
* - Environment variable scanning
|
|
10
|
+
* - File listing
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from "node:fs/promises";
|
|
13
|
+
import { join, relative } from "node:path";
|
|
14
|
+
import { parse as parseYaml } from "yaml";
|
|
15
|
+
import { createLogger } from "../utils/logger.js";
|
|
16
|
+
import { discoverAgents } from "./agent-discovery.js";
|
|
17
|
+
import { AgentRepoMetadataSchema } from "./agent-repo-metadata.js";
|
|
18
|
+
import { scanEnvVariables } from "./env-scanner.js";
|
|
19
|
+
const logger = createLogger("distribution:agent-info");
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// Helper Functions
|
|
22
|
+
// =============================================================================
|
|
23
|
+
/**
|
|
24
|
+
* Check if a path exists
|
|
25
|
+
*/
|
|
26
|
+
async function pathExists(filePath) {
|
|
27
|
+
try {
|
|
28
|
+
await fs.access(filePath);
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Read a file as text, returning null if it fails
|
|
37
|
+
*/
|
|
38
|
+
async function readTextFile(filePath) {
|
|
39
|
+
try {
|
|
40
|
+
return await fs.readFile(filePath, "utf-8");
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Safely read and parse a JSON file
|
|
48
|
+
*/
|
|
49
|
+
async function readJsonFile(filePath) {
|
|
50
|
+
try {
|
|
51
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
52
|
+
return JSON.parse(content);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Recursively list files in a directory
|
|
60
|
+
* Excludes .git and node_modules directories
|
|
61
|
+
*/
|
|
62
|
+
async function listFilesRecursive(dir, baseDir = dir, excludeDirs = new Set([".git", "node_modules"])) {
|
|
63
|
+
const files = [];
|
|
64
|
+
try {
|
|
65
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
66
|
+
for (const entry of entries) {
|
|
67
|
+
const fullPath = join(dir, entry.name);
|
|
68
|
+
const relativePath = relative(baseDir, fullPath);
|
|
69
|
+
if (entry.isDirectory()) {
|
|
70
|
+
if (!excludeDirs.has(entry.name)) {
|
|
71
|
+
const subFiles = await listFilesRecursive(fullPath, baseDir, excludeDirs);
|
|
72
|
+
files.push(...subFiles);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else if (entry.isFile()) {
|
|
76
|
+
files.push(relativePath);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Directory might not exist or be readable
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
return files.sort();
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Extract schedules from parsed agent.yaml
|
|
88
|
+
*/
|
|
89
|
+
function extractSchedules(agentYaml) {
|
|
90
|
+
const schedules = agentYaml.schedules;
|
|
91
|
+
if (!schedules || typeof schedules !== "object") {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
return schedules;
|
|
95
|
+
}
|
|
96
|
+
// =============================================================================
|
|
97
|
+
// Main Function
|
|
98
|
+
// =============================================================================
|
|
99
|
+
/**
|
|
100
|
+
* Get detailed information about a specific agent
|
|
101
|
+
*
|
|
102
|
+
* This function:
|
|
103
|
+
* 1. Uses discoverAgents() to find the agent by name
|
|
104
|
+
* 2. If not found, returns null
|
|
105
|
+
* 3. If found, gathers additional details:
|
|
106
|
+
* - Scans agent.yaml for environment variables
|
|
107
|
+
* - Extracts schedules from agent.yaml
|
|
108
|
+
* - Reads herdctl.json if present
|
|
109
|
+
* - Checks for workspace directory
|
|
110
|
+
* - Lists all files in the agent directory
|
|
111
|
+
*
|
|
112
|
+
* @param options - Options including agent name and config path
|
|
113
|
+
* @returns Detailed agent information or null if not found
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const info = await getAgentInfo({
|
|
118
|
+
* name: "website-monitor",
|
|
119
|
+
* configPath: "/path/to/herdctl.yaml"
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* if (info) {
|
|
123
|
+
* console.log(`Agent: ${info.name}`);
|
|
124
|
+
* console.log(`Installed: ${info.installed}`);
|
|
125
|
+
* console.log(`Has workspace: ${info.hasWorkspace}`);
|
|
126
|
+
* }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export async function getAgentInfo(options) {
|
|
130
|
+
const { name, configPath, baseDir } = options;
|
|
131
|
+
logger.debug("Getting agent info", { name, configPath });
|
|
132
|
+
// ==========================================================================
|
|
133
|
+
// Step 1: Find the agent using discovery
|
|
134
|
+
// ==========================================================================
|
|
135
|
+
let discoveryResult;
|
|
136
|
+
try {
|
|
137
|
+
discoveryResult = await discoverAgents({ configPath, baseDir });
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
logger.debug("Discovery failed", { error });
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
// Find the agent by name
|
|
144
|
+
const agent = discoveryResult.agents.find((a) => a.name === name);
|
|
145
|
+
if (!agent) {
|
|
146
|
+
logger.debug("Agent not found", { name });
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
logger.debug("Agent found, gathering additional info", { name, path: agent.path });
|
|
150
|
+
// ==========================================================================
|
|
151
|
+
// Step 2: Read agent.yaml for env vars and schedules
|
|
152
|
+
// ==========================================================================
|
|
153
|
+
const agentYamlPath = join(agent.path, "agent.yaml");
|
|
154
|
+
const agentYamlContent = await readTextFile(agentYamlPath);
|
|
155
|
+
let envVariables;
|
|
156
|
+
let schedules;
|
|
157
|
+
if (agentYamlContent) {
|
|
158
|
+
// Scan for environment variables
|
|
159
|
+
envVariables = scanEnvVariables(agentYamlContent);
|
|
160
|
+
if (envVariables.variables.length === 0) {
|
|
161
|
+
envVariables = undefined;
|
|
162
|
+
}
|
|
163
|
+
// Parse YAML to extract schedules
|
|
164
|
+
try {
|
|
165
|
+
const parsed = parseYaml(agentYamlContent);
|
|
166
|
+
if (parsed && typeof parsed === "object") {
|
|
167
|
+
schedules = extractSchedules(parsed);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
logger.debug("Failed to parse agent.yaml for schedules", { path: agentYamlPath });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// ==========================================================================
|
|
175
|
+
// Step 3: Read herdctl.json if present
|
|
176
|
+
// ==========================================================================
|
|
177
|
+
const herdctlJsonPath = join(agent.path, "herdctl.json");
|
|
178
|
+
let repoMetadata;
|
|
179
|
+
const herdctlJsonRaw = await readJsonFile(herdctlJsonPath);
|
|
180
|
+
if (herdctlJsonRaw) {
|
|
181
|
+
const result = AgentRepoMetadataSchema.safeParse(herdctlJsonRaw);
|
|
182
|
+
if (result.success) {
|
|
183
|
+
repoMetadata = result.data;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
logger.debug("herdctl.json failed schema validation", { path: herdctlJsonPath });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// ==========================================================================
|
|
190
|
+
// Step 4: Check for workspace directory
|
|
191
|
+
// ==========================================================================
|
|
192
|
+
const workspacePath = join(agent.path, "workspace");
|
|
193
|
+
const hasWorkspace = await pathExists(workspacePath);
|
|
194
|
+
// ==========================================================================
|
|
195
|
+
// Step 5: List files in agent directory
|
|
196
|
+
// ==========================================================================
|
|
197
|
+
const files = await listFilesRecursive(agent.path);
|
|
198
|
+
// ==========================================================================
|
|
199
|
+
// Step 6: Assemble and return the result
|
|
200
|
+
// ==========================================================================
|
|
201
|
+
const info = {
|
|
202
|
+
name: agent.name,
|
|
203
|
+
description: agent.description,
|
|
204
|
+
installed: agent.installed,
|
|
205
|
+
metadata: agent.metadata,
|
|
206
|
+
path: agent.path,
|
|
207
|
+
configPath: agent.configPath,
|
|
208
|
+
version: agent.version,
|
|
209
|
+
repoMetadata,
|
|
210
|
+
envVariables,
|
|
211
|
+
schedules,
|
|
212
|
+
hasWorkspace,
|
|
213
|
+
files,
|
|
214
|
+
};
|
|
215
|
+
logger.debug("Agent info gathered", {
|
|
216
|
+
name: info.name,
|
|
217
|
+
installed: info.installed,
|
|
218
|
+
hasWorkspace: info.hasWorkspace,
|
|
219
|
+
fileCount: info.files.length,
|
|
220
|
+
hasEnvVars: !!info.envVariables,
|
|
221
|
+
hasSchedules: !!info.schedules,
|
|
222
|
+
});
|
|
223
|
+
return info;
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=agent-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-info.js","sourceRoot":"","sources":["../../src/distribution/agent-info.ts"],"names":[],"mappings":"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"}
|