@herdctl/core 5.5.0 → 5.7.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.
Files changed (172) hide show
  1. package/dist/config/__tests__/merge.test.js +1 -1
  2. package/dist/config/__tests__/merge.test.js.map +1 -1
  3. package/dist/config/index.d.ts +1 -1
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/index.js +3 -1
  6. package/dist/config/index.js.map +1 -1
  7. package/dist/config/schema.d.ts +10 -2
  8. package/dist/config/schema.d.ts.map +1 -1
  9. package/dist/config/schema.js +6 -2
  10. package/dist/config/schema.js.map +1 -1
  11. package/dist/distribution/__tests__/agent-discovery.test.d.ts +7 -0
  12. package/dist/distribution/__tests__/agent-discovery.test.d.ts.map +1 -0
  13. package/dist/distribution/__tests__/agent-discovery.test.js +443 -0
  14. package/dist/distribution/__tests__/agent-discovery.test.js.map +1 -0
  15. package/dist/distribution/__tests__/agent-info.test.d.ts +7 -0
  16. package/dist/distribution/__tests__/agent-info.test.d.ts.map +1 -0
  17. package/dist/distribution/__tests__/agent-info.test.js +568 -0
  18. package/dist/distribution/__tests__/agent-info.test.js.map +1 -0
  19. package/dist/distribution/__tests__/agent-remover.test.d.ts +7 -0
  20. package/dist/distribution/__tests__/agent-remover.test.d.ts.map +1 -0
  21. package/dist/distribution/__tests__/agent-remover.test.js +498 -0
  22. package/dist/distribution/__tests__/agent-remover.test.js.map +1 -0
  23. package/dist/distribution/__tests__/agent-repo-metadata.test.d.ts +5 -0
  24. package/dist/distribution/__tests__/agent-repo-metadata.test.d.ts.map +1 -0
  25. package/dist/distribution/__tests__/agent-repo-metadata.test.js +500 -0
  26. package/dist/distribution/__tests__/agent-repo-metadata.test.js.map +1 -0
  27. package/dist/distribution/__tests__/env-scanner.test.d.ts +5 -0
  28. package/dist/distribution/__tests__/env-scanner.test.d.ts.map +1 -0
  29. package/dist/distribution/__tests__/env-scanner.test.js +576 -0
  30. package/dist/distribution/__tests__/env-scanner.test.js.map +1 -0
  31. package/dist/distribution/__tests__/file-installer.test.d.ts +7 -0
  32. package/dist/distribution/__tests__/file-installer.test.d.ts.map +1 -0
  33. package/dist/distribution/__tests__/file-installer.test.js +714 -0
  34. package/dist/distribution/__tests__/file-installer.test.js.map +1 -0
  35. package/dist/distribution/__tests__/fleet-config-updater.test.d.ts +7 -0
  36. package/dist/distribution/__tests__/fleet-config-updater.test.d.ts.map +1 -0
  37. package/dist/distribution/__tests__/fleet-config-updater.test.js +531 -0
  38. package/dist/distribution/__tests__/fleet-config-updater.test.js.map +1 -0
  39. package/dist/distribution/__tests__/installation-metadata.test.d.ts +2 -0
  40. package/dist/distribution/__tests__/installation-metadata.test.d.ts.map +1 -0
  41. package/dist/distribution/__tests__/installation-metadata.test.js +292 -0
  42. package/dist/distribution/__tests__/installation-metadata.test.js.map +1 -0
  43. package/dist/distribution/__tests__/integration.test.d.ts +10 -0
  44. package/dist/distribution/__tests__/integration.test.d.ts.map +1 -0
  45. package/dist/distribution/__tests__/integration.test.js +522 -0
  46. package/dist/distribution/__tests__/integration.test.js.map +1 -0
  47. package/dist/distribution/__tests__/repository-fetcher.test.d.ts +5 -0
  48. package/dist/distribution/__tests__/repository-fetcher.test.d.ts.map +1 -0
  49. package/dist/distribution/__tests__/repository-fetcher.test.js +386 -0
  50. package/dist/distribution/__tests__/repository-fetcher.test.js.map +1 -0
  51. package/dist/distribution/__tests__/repository-validator.test.d.ts +7 -0
  52. package/dist/distribution/__tests__/repository-validator.test.d.ts.map +1 -0
  53. package/dist/distribution/__tests__/repository-validator.test.js +447 -0
  54. package/dist/distribution/__tests__/repository-validator.test.js.map +1 -0
  55. package/dist/distribution/__tests__/source-specifier.test.d.ts +5 -0
  56. package/dist/distribution/__tests__/source-specifier.test.d.ts.map +1 -0
  57. package/dist/distribution/__tests__/source-specifier.test.js +533 -0
  58. package/dist/distribution/__tests__/source-specifier.test.js.map +1 -0
  59. package/dist/distribution/agent-discovery.d.ts +81 -0
  60. package/dist/distribution/agent-discovery.d.ts.map +1 -0
  61. package/dist/distribution/agent-discovery.js +264 -0
  62. package/dist/distribution/agent-discovery.js.map +1 -0
  63. package/dist/distribution/agent-info.d.ts +86 -0
  64. package/dist/distribution/agent-info.d.ts.map +1 -0
  65. package/dist/distribution/agent-info.js +225 -0
  66. package/dist/distribution/agent-info.js.map +1 -0
  67. package/dist/distribution/agent-remover.d.ts +83 -0
  68. package/dist/distribution/agent-remover.d.ts.map +1 -0
  69. package/dist/distribution/agent-remover.js +222 -0
  70. package/dist/distribution/agent-remover.js.map +1 -0
  71. package/dist/distribution/agent-repo-metadata.d.ts +181 -0
  72. package/dist/distribution/agent-repo-metadata.d.ts.map +1 -0
  73. package/dist/distribution/agent-repo-metadata.js +143 -0
  74. package/dist/distribution/agent-repo-metadata.js.map +1 -0
  75. package/dist/distribution/env-scanner.d.ts +78 -0
  76. package/dist/distribution/env-scanner.d.ts.map +1 -0
  77. package/dist/distribution/env-scanner.js +144 -0
  78. package/dist/distribution/env-scanner.js.map +1 -0
  79. package/dist/distribution/file-installer.d.ts +80 -0
  80. package/dist/distribution/file-installer.d.ts.map +1 -0
  81. package/dist/distribution/file-installer.js +268 -0
  82. package/dist/distribution/file-installer.js.map +1 -0
  83. package/dist/distribution/fleet-config-updater.d.ts +96 -0
  84. package/dist/distribution/fleet-config-updater.d.ts.map +1 -0
  85. package/dist/distribution/fleet-config-updater.js +266 -0
  86. package/dist/distribution/fleet-config-updater.js.map +1 -0
  87. package/dist/distribution/index.d.ts +23 -0
  88. package/dist/distribution/index.d.ts.map +1 -0
  89. package/dist/distribution/index.js +42 -0
  90. package/dist/distribution/index.js.map +1 -0
  91. package/dist/distribution/installation-metadata.d.ts +191 -0
  92. package/dist/distribution/installation-metadata.d.ts.map +1 -0
  93. package/dist/distribution/installation-metadata.js +100 -0
  94. package/dist/distribution/installation-metadata.js.map +1 -0
  95. package/dist/distribution/repository-fetcher.d.ts +104 -0
  96. package/dist/distribution/repository-fetcher.d.ts.map +1 -0
  97. package/dist/distribution/repository-fetcher.js +246 -0
  98. package/dist/distribution/repository-fetcher.js.map +1 -0
  99. package/dist/distribution/repository-validator.d.ts +86 -0
  100. package/dist/distribution/repository-validator.d.ts.map +1 -0
  101. package/dist/distribution/repository-validator.js +296 -0
  102. package/dist/distribution/repository-validator.js.map +1 -0
  103. package/dist/distribution/source-specifier.d.ts +106 -0
  104. package/dist/distribution/source-specifier.d.ts.map +1 -0
  105. package/dist/distribution/source-specifier.js +247 -0
  106. package/dist/distribution/source-specifier.js.map +1 -0
  107. package/dist/fleet-manager/errors.d.ts +15 -0
  108. package/dist/fleet-manager/errors.d.ts.map +1 -1
  109. package/dist/fleet-manager/errors.js +16 -0
  110. package/dist/fleet-manager/errors.js.map +1 -1
  111. package/dist/fleet-manager/fleet-manager.d.ts.map +1 -1
  112. package/dist/fleet-manager/fleet-manager.js +31 -9
  113. package/dist/fleet-manager/fleet-manager.js.map +1 -1
  114. package/dist/index.d.ts +1 -0
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +2 -0
  117. package/dist/index.js.map +1 -1
  118. package/dist/runner/message-processor.d.ts.map +1 -1
  119. package/dist/runner/message-processor.js +7 -2
  120. package/dist/runner/message-processor.js.map +1 -1
  121. package/dist/runner/runtime/container-manager.js +1 -1
  122. package/dist/runner/runtime/container-manager.js.map +1 -1
  123. package/dist/scheduler/errors.d.ts +15 -0
  124. package/dist/scheduler/errors.d.ts.map +1 -1
  125. package/dist/scheduler/schedule-runner.d.ts.map +1 -1
  126. package/dist/scheduler/schedule-runner.js +6 -5
  127. package/dist/scheduler/schedule-runner.js.map +1 -1
  128. package/dist/state/__tests__/jsonl-parser.test.d.ts +5 -0
  129. package/dist/state/__tests__/jsonl-parser.test.d.ts.map +1 -0
  130. package/dist/state/__tests__/jsonl-parser.test.js +307 -0
  131. package/dist/state/__tests__/jsonl-parser.test.js.map +1 -0
  132. package/dist/state/__tests__/session-attribution.test.d.ts +2 -0
  133. package/dist/state/__tests__/session-attribution.test.d.ts.map +1 -0
  134. package/dist/state/__tests__/session-attribution.test.js +567 -0
  135. package/dist/state/__tests__/session-attribution.test.js.map +1 -0
  136. package/dist/state/__tests__/session-discovery.test.d.ts +2 -0
  137. package/dist/state/__tests__/session-discovery.test.d.ts.map +1 -0
  138. package/dist/state/__tests__/session-discovery.test.js +941 -0
  139. package/dist/state/__tests__/session-discovery.test.js.map +1 -0
  140. package/dist/state/__tests__/session-metadata.test.d.ts +2 -0
  141. package/dist/state/__tests__/session-metadata.test.d.ts.map +1 -0
  142. package/dist/state/__tests__/session-metadata.test.js +422 -0
  143. package/dist/state/__tests__/session-metadata.test.js.map +1 -0
  144. package/dist/state/__tests__/tool-parsing.test.d.ts +5 -0
  145. package/dist/state/__tests__/tool-parsing.test.d.ts.map +1 -0
  146. package/dist/state/__tests__/tool-parsing.test.js +315 -0
  147. package/dist/state/__tests__/tool-parsing.test.js.map +1 -0
  148. package/dist/state/index.d.ts +5 -0
  149. package/dist/state/index.d.ts.map +1 -1
  150. package/dist/state/index.js +10 -0
  151. package/dist/state/index.js.map +1 -1
  152. package/dist/state/jsonl-parser.d.ts +115 -0
  153. package/dist/state/jsonl-parser.d.ts.map +1 -0
  154. package/dist/state/jsonl-parser.js +437 -0
  155. package/dist/state/jsonl-parser.js.map +1 -0
  156. package/dist/state/session-attribution.d.ts +35 -0
  157. package/dist/state/session-attribution.d.ts.map +1 -0
  158. package/dist/state/session-attribution.js +179 -0
  159. package/dist/state/session-attribution.js.map +1 -0
  160. package/dist/state/session-discovery.d.ts +188 -0
  161. package/dist/state/session-discovery.d.ts.map +1 -0
  162. package/dist/state/session-discovery.js +513 -0
  163. package/dist/state/session-discovery.js.map +1 -0
  164. package/dist/state/session-metadata.d.ts +186 -0
  165. package/dist/state/session-metadata.d.ts.map +1 -0
  166. package/dist/state/session-metadata.js +297 -0
  167. package/dist/state/session-metadata.js.map +1 -0
  168. package/dist/state/tool-parsing.d.ts +88 -0
  169. package/dist/state/tool-parsing.d.ts.map +1 -0
  170. package/dist/state/tool-parsing.js +199 -0
  171. package/dist/state/tool-parsing.js.map +1 -0
  172. package/package.json +1 -1
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Installation metadata schema for agent distribution
3
+ *
4
+ * Validates the `metadata.json` file that lives in each installed agent's
5
+ * directory root. This file tracks where an agent was installed from and when.
6
+ *
7
+ * The schema is intentionally extensible (no .strict()) to support future
8
+ * features like agentic initialization without breaking existing installs.
9
+ */
10
+ import { z } from "zod";
11
+ // =============================================================================
12
+ // Source Type Schema
13
+ // =============================================================================
14
+ /**
15
+ * Source types for installed agents
16
+ *
17
+ * - `github`: Installed from a GitHub repository
18
+ * - `local`: Installed from a local filesystem path
19
+ */
20
+ export const SourceTypeSchema = z.enum(["github", "local"]);
21
+ // =============================================================================
22
+ // Source Schema
23
+ // =============================================================================
24
+ /**
25
+ * Source information schema
26
+ *
27
+ * Tracks the origin of an installed agent. The `type` field is required,
28
+ * while other fields are optional and depend on the source type:
29
+ *
30
+ * - `url`: The original source URL or path (GitHub URL, local path)
31
+ * - `ref`: Git reference (tag, branch, commit SHA) for GitHub sources
32
+ * - `version`: Version from herdctl.json at install time
33
+ */
34
+ export const InstallationSourceSchema = z
35
+ .object({
36
+ /** The type of source (github or local) */
37
+ type: SourceTypeSchema,
38
+ /** The original source URL or path */
39
+ url: z.string().optional(),
40
+ /** Git reference (tag, branch, commit) for version-controlled sources */
41
+ ref: z.string().optional(),
42
+ /** Version from herdctl.json at install time */
43
+ version: z.string().optional(),
44
+ })
45
+ .passthrough();
46
+ // =============================================================================
47
+ // ISO 8601 Timestamp Schema
48
+ // =============================================================================
49
+ /**
50
+ * ISO 8601 timestamp pattern
51
+ *
52
+ * Matches formats like:
53
+ * - 2024-01-15T10:30:00Z
54
+ * - 2024-01-15T10:30:00.123Z
55
+ * - 2024-01-15T10:30:00+00:00
56
+ * - 2024-01-15T10:30:00-05:00
57
+ */
58
+ const ISO8601_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
59
+ /**
60
+ * Schema for ISO 8601 formatted timestamps
61
+ */
62
+ export const ISO8601TimestampSchema = z.string().regex(ISO8601_PATTERN, {
63
+ message: "Timestamp must be in ISO 8601 format (e.g., 2024-01-15T10:30:00Z or 2024-01-15T10:30:00+00:00)",
64
+ });
65
+ // =============================================================================
66
+ // Installation Metadata Schema
67
+ // =============================================================================
68
+ /**
69
+ * Installation metadata schema
70
+ *
71
+ * This schema validates the `metadata.json` file that tracks installation
72
+ * information for each agent. It is intentionally extensible (uses default
73
+ * Zod behavior, not .strict()) to allow adding future fields like
74
+ * `initialization` without breaking existing installs.
75
+ *
76
+ * @example
77
+ * ```json
78
+ * {
79
+ * "source": {
80
+ * "type": "github",
81
+ * "url": "https://github.com/user/agent-repo",
82
+ * "ref": "v1.0.0",
83
+ * "version": "1.0.0"
84
+ * },
85
+ * "installed_at": "2024-01-15T10:30:00Z",
86
+ * "installed_by": "herdctl@0.5.0"
87
+ * }
88
+ * ```
89
+ */
90
+ export const InstallationMetadataSchema = z
91
+ .object({
92
+ /** Source information - where the agent was installed from */
93
+ source: InstallationSourceSchema,
94
+ /** ISO 8601 timestamp of when the agent was installed */
95
+ installed_at: ISO8601TimestampSchema,
96
+ /** herdctl version that performed the installation (e.g., "herdctl@0.5.0") */
97
+ installed_by: z.string().optional(),
98
+ })
99
+ .passthrough();
100
+ //# sourceMappingURL=installation-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installation-metadata.js","sourceRoot":"","sources":["../../src/distribution/installation-metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gFAAgF;AAChF,qBAAqB;AACrB,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAK5D,gFAAgF;AAChF,gBAAgB;AAChB,gFAAgF;AAEhF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC;KACtC,MAAM,CAAC;IACN,2CAA2C;IAC3C,IAAI,EAAE,gBAAgB;IAEtB,sCAAsC;IACtC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAE1B,yEAAyE;IACzE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAE1B,gDAAgD;IAChD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC;KACD,WAAW,EAAE,CAAC;AAKjB,gFAAgF;AAChF,4BAA4B;AAC5B,gFAAgF;AAEhF;;;;;;;;GAQG;AACH,MAAM,eAAe,GAAG,sEAAsE,CAAC;AAE/F;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,EAAE;IACtE,OAAO,EACL,gGAAgG;CACnG,CAAC,CAAC;AAEH,gFAAgF;AAChF,+BAA+B;AAC/B,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC;KACxC,MAAM,CAAC;IACN,8DAA8D;IAC9D,MAAM,EAAE,wBAAwB;IAEhC,yDAAyD;IACzD,YAAY,EAAE,sBAAsB;IAEpC,8EAA8E;IAC9E,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC;KACD,WAAW,EAAE,CAAC"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Repository fetching for agent distribution
3
+ *
4
+ * Fetches agent repositories from various sources (GitHub, local paths) and
5
+ * provides them in a temporary directory for validation and installation.
6
+ */
7
+ import { FleetManagerError } from "../fleet-manager/errors.js";
8
+ /**
9
+ * GitHub source specifier
10
+ */
11
+ export interface GitHubFetchSource {
12
+ type: "github";
13
+ owner: string;
14
+ repo: string;
15
+ ref?: string;
16
+ }
17
+ /**
18
+ * Local filesystem source specifier
19
+ */
20
+ export interface LocalFetchSource {
21
+ type: "local";
22
+ path: string;
23
+ }
24
+ /**
25
+ * Union of all fetch source types
26
+ */
27
+ export type FetchSource = GitHubFetchSource | LocalFetchSource;
28
+ /**
29
+ * Result of fetching a repository
30
+ *
31
+ * Note: Named RepositoryFetchResult to avoid collision with work-sources FetchResult
32
+ */
33
+ export interface RepositoryFetchResult {
34
+ /** Path to the fetched repository contents */
35
+ path: string;
36
+ /** Cleanup function to remove the temporary directory */
37
+ cleanup: () => Promise<void>;
38
+ }
39
+ /**
40
+ * Base error for repository fetching failures
41
+ */
42
+ export declare class RepositoryFetchError extends FleetManagerError {
43
+ readonly source: FetchSource;
44
+ constructor(message: string, source: FetchSource, cause?: Error);
45
+ }
46
+ /**
47
+ * Error when GitHub authentication fails during clone
48
+ *
49
+ * Note: Named GitHubCloneAuthError to avoid collision with work-sources GitHubAuthError
50
+ */
51
+ export declare class GitHubCloneAuthError extends RepositoryFetchError {
52
+ constructor(source: GitHubFetchSource, cause?: Error);
53
+ }
54
+ /**
55
+ * Error when a GitHub repository is not found
56
+ */
57
+ export declare class GitHubRepoNotFoundError extends RepositoryFetchError {
58
+ constructor(source: GitHubFetchSource, cause?: Error);
59
+ }
60
+ /**
61
+ * Error when a network operation fails
62
+ */
63
+ export declare class NetworkError extends RepositoryFetchError {
64
+ constructor(source: FetchSource, cause?: Error);
65
+ }
66
+ /**
67
+ * Error when a local path doesn't exist or isn't a directory
68
+ */
69
+ export declare class LocalPathError extends RepositoryFetchError {
70
+ constructor(source: LocalFetchSource, reason: string, cause?: Error);
71
+ }
72
+ /**
73
+ * Fetch a repository from a source specifier
74
+ *
75
+ * Clones or copies the repository to a temporary directory and returns
76
+ * the path along with a cleanup function.
77
+ *
78
+ * @param source - The source specifier (GitHub or local)
79
+ * @returns The path to the fetched repository and a cleanup function
80
+ * @throws {GitHubCloneAuthError} When GitHub authentication fails
81
+ * @throws {GitHubRepoNotFoundError} When the GitHub repository doesn't exist
82
+ * @throws {NetworkError} When a network operation fails
83
+ * @throws {LocalPathError} When the local path is invalid
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * const result = await fetchRepository({
88
+ * type: 'github',
89
+ * owner: 'herdctl',
90
+ * repo: 'example-agent',
91
+ * ref: 'v1.0.0'
92
+ * });
93
+ *
94
+ * try {
95
+ * // Use result.path to access the repository files
96
+ * const agentYaml = await readFile(join(result.path, 'agent.yaml'));
97
+ * } finally {
98
+ * // Always clean up when done
99
+ * await result.cleanup();
100
+ * }
101
+ * ```
102
+ */
103
+ export declare function fetchRepository(source: FetchSource): Promise<RepositoryFetchResult>;
104
+ //# sourceMappingURL=repository-fetcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository-fetcher.d.ts","sourceRoot":"","sources":["../../src/distribution/repository-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAU/D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAMD;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,iBAAiB;aAGvC,MAAM,EAAE,WAAW;gBADnC,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,WAAW,EACnC,KAAK,CAAC,EAAE,KAAK;CAKhB;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,oBAAoB;gBAChD,MAAM,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,KAAK;CAUrD;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,oBAAoB;gBACnD,MAAM,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,KAAK;CASrD;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,oBAAoB;gBACxC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,KAAK;CAW/C;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,oBAAoB;gBAC1C,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAIpE;AAgKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAczF"}
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Repository fetching for agent distribution
3
+ *
4
+ * Fetches agent repositories from various sources (GitHub, local paths) and
5
+ * provides them in a temporary directory for validation and installation.
6
+ */
7
+ import { execFile } from "node:child_process";
8
+ import { cp, mkdtemp, rm, stat } from "node:fs/promises";
9
+ import { tmpdir } from "node:os";
10
+ import { join } from "node:path";
11
+ import { promisify } from "node:util";
12
+ import { FleetManagerError } from "../fleet-manager/errors.js";
13
+ import { createLogger } from "../utils/logger.js";
14
+ const execFileAsync = promisify(execFile);
15
+ const logger = createLogger("distribution");
16
+ // =============================================================================
17
+ // Error Classes
18
+ // =============================================================================
19
+ /**
20
+ * Base error for repository fetching failures
21
+ */
22
+ export class RepositoryFetchError extends FleetManagerError {
23
+ source;
24
+ constructor(message, source, cause) {
25
+ super(message, { cause, code: "REPOSITORY_FETCH_ERROR" });
26
+ this.source = source;
27
+ this.name = "RepositoryFetchError";
28
+ }
29
+ }
30
+ /**
31
+ * Error when GitHub authentication fails during clone
32
+ *
33
+ * Note: Named GitHubCloneAuthError to avoid collision with work-sources GitHubAuthError
34
+ */
35
+ export class GitHubCloneAuthError extends RepositoryFetchError {
36
+ constructor(source, cause) {
37
+ super(`Authentication failed for github:${source.owner}/${source.repo}. ` +
38
+ `Make sure your Git credentials are configured correctly. ` +
39
+ `For private repos, set up a GitHub personal access token or SSH key.`, source, cause);
40
+ this.name = "GitHubCloneAuthError";
41
+ }
42
+ }
43
+ /**
44
+ * Error when a GitHub repository is not found
45
+ */
46
+ export class GitHubRepoNotFoundError extends RepositoryFetchError {
47
+ constructor(source, cause) {
48
+ super(`Repository not found: github:${source.owner}/${source.repo}. ` +
49
+ `Check that the owner and repository name are correct, and that you have access to the repo.`, source, cause);
50
+ this.name = "GitHubRepoNotFoundError";
51
+ }
52
+ }
53
+ /**
54
+ * Error when a network operation fails
55
+ */
56
+ export class NetworkError extends RepositoryFetchError {
57
+ constructor(source, cause) {
58
+ const sourceStr = source.type === "github" ? `github:${source.owner}/${source.repo}` : source.type;
59
+ super(`Network error while fetching ${sourceStr}. ` +
60
+ `Check your internet connection and try again.`, source, cause);
61
+ this.name = "NetworkError";
62
+ }
63
+ }
64
+ /**
65
+ * Error when a local path doesn't exist or isn't a directory
66
+ */
67
+ export class LocalPathError extends RepositoryFetchError {
68
+ constructor(source, reason, cause) {
69
+ super(`Local source error for "${source.path}": ${reason}`, source, cause);
70
+ this.name = "LocalPathError";
71
+ }
72
+ }
73
+ // =============================================================================
74
+ // Implementation
75
+ // =============================================================================
76
+ /**
77
+ * Create a temporary directory for fetching
78
+ */
79
+ async function createTempDir(prefix) {
80
+ const base = join(tmpdir(), `herdctl-${prefix}-`);
81
+ return mkdtemp(base);
82
+ }
83
+ /**
84
+ * Fetch a repository from GitHub via shallow clone
85
+ */
86
+ async function fetchFromGitHub(source) {
87
+ const url = `https://github.com/${source.owner}/${source.repo}.git`;
88
+ const tempDir = await createTempDir("github");
89
+ logger.debug("Cloning GitHub repository", {
90
+ owner: source.owner,
91
+ repo: source.repo,
92
+ ref: source.ref,
93
+ tempDir,
94
+ });
95
+ const args = ["clone", "--depth", "1"];
96
+ if (source.ref) {
97
+ args.push("--branch", source.ref);
98
+ }
99
+ args.push(url, tempDir);
100
+ try {
101
+ await execFileAsync("git", args, {
102
+ env: {
103
+ ...process.env,
104
+ // Prevent interactive auth prompts from hanging
105
+ GIT_TERMINAL_PROMPT: "0",
106
+ },
107
+ timeout: 120000, // 2 minute timeout
108
+ });
109
+ logger.info("Successfully cloned repository", {
110
+ source: `github:${source.owner}/${source.repo}`,
111
+ ref: source.ref,
112
+ });
113
+ return {
114
+ path: tempDir,
115
+ cleanup: async () => {
116
+ logger.debug("Cleaning up temporary directory", { path: tempDir });
117
+ await rm(tempDir, { recursive: true, force: true });
118
+ },
119
+ };
120
+ }
121
+ catch (err) {
122
+ // Clean up temp dir on failure
123
+ await rm(tempDir, { recursive: true, force: true }).catch(() => {
124
+ /* ignore cleanup errors */
125
+ });
126
+ const error = err;
127
+ const stderr = error.stderr?.toLowerCase() ?? "";
128
+ // Node.js execFile returns exit code as number, but handle string for safety
129
+ const exitCode = typeof error.code === "number" ? error.code : parseInt(String(error.code), 10);
130
+ // Check specific error patterns FIRST before falling back to generic exit code checks.
131
+ // Git exit code 128 is used for multiple failure modes (auth, not found, etc.),
132
+ // so we must check message content to distinguish between them.
133
+ // Check for repository not found errors (specific patterns first)
134
+ if (stderr.includes("repository not found") ||
135
+ stderr.includes("does not exist") ||
136
+ stderr.includes("not found")) {
137
+ throw new GitHubRepoNotFoundError(source, error);
138
+ }
139
+ // Check for network errors
140
+ if (stderr.includes("could not resolve host") ||
141
+ stderr.includes("network") ||
142
+ stderr.includes("connection")) {
143
+ throw new NetworkError(source, error);
144
+ }
145
+ // Check for authentication errors - either explicit auth messages or
146
+ // exit code 128 with credential-related messages
147
+ if (stderr.includes("authentication") ||
148
+ stderr.includes("could not read") ||
149
+ exitCode === 128) {
150
+ throw new GitHubCloneAuthError(source, error);
151
+ }
152
+ // Generic error
153
+ throw new RepositoryFetchError(`Failed to clone github:${source.owner}/${source.repo}: ${error.message}`, source, error);
154
+ }
155
+ }
156
+ /**
157
+ * Fetch from a local filesystem path by copying to a temp directory
158
+ */
159
+ async function fetchFromLocal(source) {
160
+ logger.debug("Copying local directory", { path: source.path });
161
+ // Validate the source path exists
162
+ let stats;
163
+ try {
164
+ stats = await stat(source.path);
165
+ }
166
+ catch (err) {
167
+ const error = err;
168
+ if (error.code === "ENOENT") {
169
+ throw new LocalPathError(source, "Path does not exist");
170
+ }
171
+ throw new LocalPathError(source, `Cannot access path: ${error.message}`, error);
172
+ }
173
+ // Validate it's a directory
174
+ if (!stats.isDirectory()) {
175
+ throw new LocalPathError(source, "Path is not a directory");
176
+ }
177
+ // Copy to temp directory
178
+ const tempDir = await createTempDir("local");
179
+ try {
180
+ await cp(source.path, tempDir, { recursive: true });
181
+ logger.info("Successfully copied local directory", {
182
+ source: source.path,
183
+ dest: tempDir,
184
+ });
185
+ return {
186
+ path: tempDir,
187
+ cleanup: async () => {
188
+ logger.debug("Cleaning up temporary directory", { path: tempDir });
189
+ await rm(tempDir, { recursive: true, force: true });
190
+ },
191
+ };
192
+ }
193
+ catch (err) {
194
+ // Clean up temp dir on failure
195
+ await rm(tempDir, { recursive: true, force: true }).catch(() => {
196
+ /* ignore cleanup errors */
197
+ });
198
+ const error = err;
199
+ throw new LocalPathError(source, `Failed to copy directory: ${error.message}`, error);
200
+ }
201
+ }
202
+ /**
203
+ * Fetch a repository from a source specifier
204
+ *
205
+ * Clones or copies the repository to a temporary directory and returns
206
+ * the path along with a cleanup function.
207
+ *
208
+ * @param source - The source specifier (GitHub or local)
209
+ * @returns The path to the fetched repository and a cleanup function
210
+ * @throws {GitHubCloneAuthError} When GitHub authentication fails
211
+ * @throws {GitHubRepoNotFoundError} When the GitHub repository doesn't exist
212
+ * @throws {NetworkError} When a network operation fails
213
+ * @throws {LocalPathError} When the local path is invalid
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * const result = await fetchRepository({
218
+ * type: 'github',
219
+ * owner: 'herdctl',
220
+ * repo: 'example-agent',
221
+ * ref: 'v1.0.0'
222
+ * });
223
+ *
224
+ * try {
225
+ * // Use result.path to access the repository files
226
+ * const agentYaml = await readFile(join(result.path, 'agent.yaml'));
227
+ * } finally {
228
+ * // Always clean up when done
229
+ * await result.cleanup();
230
+ * }
231
+ * ```
232
+ */
233
+ export async function fetchRepository(source) {
234
+ switch (source.type) {
235
+ case "github":
236
+ return fetchFromGitHub(source);
237
+ case "local":
238
+ return fetchFromLocal(source);
239
+ default: {
240
+ // Exhaustive check
241
+ const _exhaustive = source;
242
+ throw new Error(`Unknown source type: ${_exhaustive.type}`);
243
+ }
244
+ }
245
+ }
246
+ //# sourceMappingURL=repository-fetcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository-fetcher.js","sourceRoot":"","sources":["../../src/distribution/repository-fetcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Repository Validation for Agent Distribution
3
+ *
4
+ * Validates that a directory is a valid agent repository by checking:
5
+ * - agent.yaml exists and is valid YAML conforming to AgentConfigSchema
6
+ * - docker.network is not "none" (agents need network access for Anthropic API)
7
+ * - herdctl.json is valid if present
8
+ * - Optional files like CLAUDE.md and README.md
9
+ */
10
+ import { type AgentConfig } from "../config/schema.js";
11
+ import { type AgentRepoMetadata } from "./agent-repo-metadata.js";
12
+ /**
13
+ * Validation message representing an error or warning
14
+ */
15
+ export interface ValidationMessage {
16
+ /** Machine-readable code like 'MISSING_AGENT_YAML', 'INVALID_AGENT_YAML' */
17
+ code: string;
18
+ /** Human-readable description of the issue */
19
+ message: string;
20
+ /** File path relative to repository root (if applicable) */
21
+ path?: string;
22
+ }
23
+ /**
24
+ * Result of repository validation
25
+ */
26
+ export interface ValidationResult {
27
+ /** Whether the repository is valid for installation */
28
+ valid: boolean;
29
+ /** Agent name from agent.yaml (if valid) */
30
+ agentName: string | null;
31
+ /** Parsed agent configuration (if valid) */
32
+ agentConfig: AgentConfig | null;
33
+ /** Parsed repository metadata from herdctl.json (if present and valid) */
34
+ repoMetadata: AgentRepoMetadata | null;
35
+ /** Errors that prevent installation */
36
+ errors: ValidationMessage[];
37
+ /** Warnings the user should know about */
38
+ warnings: ValidationMessage[];
39
+ }
40
+ /** Error: agent.yaml not found */
41
+ export declare const MISSING_AGENT_YAML = "MISSING_AGENT_YAML";
42
+ /** Error: agent.yaml is not valid YAML */
43
+ export declare const YAML_PARSE_ERROR = "YAML_PARSE_ERROR";
44
+ /** Error: agent.yaml fails schema validation */
45
+ export declare const INVALID_AGENT_YAML = "INVALID_AGENT_YAML";
46
+ /** Error: docker.network is set to "none" */
47
+ export declare const DOCKER_NETWORK_NONE = "DOCKER_NETWORK_NONE";
48
+ /** Error: herdctl.json is not valid JSON */
49
+ export declare const JSON_PARSE_ERROR = "JSON_PARSE_ERROR";
50
+ /** Error: herdctl.json fails schema validation */
51
+ export declare const INVALID_HERDCTL_JSON = "INVALID_HERDCTL_JSON";
52
+ /** Warning: no herdctl.json (optional but recommended) */
53
+ export declare const MISSING_HERDCTL_JSON = "MISSING_HERDCTL_JSON";
54
+ /** Warning: name in agent.yaml differs from name in herdctl.json */
55
+ export declare const NAME_MISMATCH = "NAME_MISMATCH";
56
+ /** Warning: no CLAUDE.md file (optional but recommended) */
57
+ export declare const MISSING_CLAUDE_MD = "MISSING_CLAUDE_MD";
58
+ /** Warning: no README.md (optional but recommended) */
59
+ export declare const MISSING_README = "MISSING_README";
60
+ /**
61
+ * Validate a directory as an agent repository
62
+ *
63
+ * Checks that the directory contains valid agent repository files:
64
+ * - agent.yaml (required) - must be valid YAML conforming to AgentConfigSchema
65
+ * - herdctl.json (optional) - if present, must be valid JSON conforming to AgentRepoMetadataSchema
66
+ * - CLAUDE.md (optional) - recommended for agent identity
67
+ * - README.md (optional) - recommended for documentation
68
+ *
69
+ * Also performs safety checks:
70
+ * - docker.network cannot be "none" (agents need network for Anthropic API)
71
+ *
72
+ * @param dirPath - Absolute path to the directory to validate
73
+ * @returns Validation result with errors, warnings, and parsed configurations
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const result = await validateRepository("/tmp/my-agent");
78
+ * if (result.valid) {
79
+ * console.log(`Agent ${result.agentName} is valid`);
80
+ * } else {
81
+ * console.error("Validation errors:", result.errors);
82
+ * }
83
+ * ```
84
+ */
85
+ export declare function validateRepository(dirPath: string): Promise<ValidationResult>;
86
+ //# sourceMappingURL=repository-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository-validator.d.ts","sourceRoot":"","sources":["../../src/distribution/repository-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,qBAAqB,CAAC;AAE1E,OAAO,EAAE,KAAK,iBAAiB,EAA2B,MAAM,0BAA0B,CAAC;AAQ3F;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,KAAK,EAAE,OAAO,CAAC;IACf,4CAA4C;IAC5C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,4CAA4C;IAC5C,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,0EAA0E;IAC1E,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACvC,uCAAuC;IACvC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,0CAA0C;IAC1C,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAMD,kCAAkC;AAClC,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AACvD,0CAA0C;AAC1C,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AACnD,gDAAgD;AAChD,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AACvD,6CAA6C;AAC7C,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AACzD,4CAA4C;AAC5C,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AACnD,kDAAkD;AAClD,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAE3D,0DAA0D;AAC1D,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAC3D,oEAAoE;AACpE,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAC7C,4DAA4D;AAC5D,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,uDAAuD;AACvD,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAwE/C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2LnF"}