@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,533 @@
1
+ /**
2
+ * Tests for Source Specifier Parser
3
+ */
4
+ import * as path from "path";
5
+ import { describe, expect, it } from "vitest";
6
+ import { isGitHubSource, isLocalSource, parseSourceSpecifier, SourceParseError, stringifySourceSpecifier, } from "../source-specifier.js";
7
+ // =============================================================================
8
+ // GitHub Source Tests
9
+ // =============================================================================
10
+ describe("parseSourceSpecifier - GitHub sources", () => {
11
+ describe("basic GitHub sources", () => {
12
+ it("should parse basic github:owner/repo format", () => {
13
+ const result = parseSourceSpecifier("github:user/repo");
14
+ expect(result.type).toBe("github");
15
+ expect(isGitHubSource(result)).toBe(true);
16
+ if (isGitHubSource(result)) {
17
+ expect(result.owner).toBe("user");
18
+ expect(result.repo).toBe("repo");
19
+ expect(result.ref).toBeUndefined();
20
+ }
21
+ });
22
+ it("should parse GitHub source with organization owner", () => {
23
+ const result = parseSourceSpecifier("github:herdctl-examples/website-monitor-agent");
24
+ expect(result.type).toBe("github");
25
+ if (isGitHubSource(result)) {
26
+ expect(result.owner).toBe("herdctl-examples");
27
+ expect(result.repo).toBe("website-monitor-agent");
28
+ }
29
+ });
30
+ it("should parse GitHub source with underscores in names", () => {
31
+ const result = parseSourceSpecifier("github:my_org/my_repo");
32
+ expect(result.type).toBe("github");
33
+ if (isGitHubSource(result)) {
34
+ expect(result.owner).toBe("my_org");
35
+ expect(result.repo).toBe("my_repo");
36
+ }
37
+ });
38
+ it("should parse GitHub source with dots in names", () => {
39
+ const result = parseSourceSpecifier("github:user.name/repo.name");
40
+ expect(result.type).toBe("github");
41
+ if (isGitHubSource(result)) {
42
+ expect(result.owner).toBe("user.name");
43
+ expect(result.repo).toBe("repo.name");
44
+ }
45
+ });
46
+ it("should parse GitHub source with numeric names", () => {
47
+ const result = parseSourceSpecifier("github:user123/repo456");
48
+ expect(result.type).toBe("github");
49
+ if (isGitHubSource(result)) {
50
+ expect(result.owner).toBe("user123");
51
+ expect(result.repo).toBe("repo456");
52
+ }
53
+ });
54
+ it("should parse GitHub source with single character names", () => {
55
+ const result = parseSourceSpecifier("github:a/b");
56
+ expect(result.type).toBe("github");
57
+ if (isGitHubSource(result)) {
58
+ expect(result.owner).toBe("a");
59
+ expect(result.repo).toBe("b");
60
+ }
61
+ });
62
+ });
63
+ describe("GitHub sources with tag ref", () => {
64
+ it("should parse GitHub source with semver tag", () => {
65
+ const result = parseSourceSpecifier("github:user/repo@v1.0.0");
66
+ expect(result.type).toBe("github");
67
+ if (isGitHubSource(result)) {
68
+ expect(result.owner).toBe("user");
69
+ expect(result.repo).toBe("repo");
70
+ expect(result.ref).toBe("v1.0.0");
71
+ }
72
+ });
73
+ it("should parse GitHub source with tag without v prefix", () => {
74
+ const result = parseSourceSpecifier("github:user/repo@1.2.3");
75
+ expect(result.type).toBe("github");
76
+ if (isGitHubSource(result)) {
77
+ expect(result.ref).toBe("1.2.3");
78
+ }
79
+ });
80
+ it("should parse GitHub source with prerelease tag", () => {
81
+ const result = parseSourceSpecifier("github:user/repo@v2.0.0-beta.1");
82
+ expect(result.type).toBe("github");
83
+ if (isGitHubSource(result)) {
84
+ expect(result.ref).toBe("v2.0.0-beta.1");
85
+ }
86
+ });
87
+ });
88
+ describe("GitHub sources with branch ref", () => {
89
+ it("should parse GitHub source with main branch", () => {
90
+ const result = parseSourceSpecifier("github:user/repo@main");
91
+ expect(result.type).toBe("github");
92
+ if (isGitHubSource(result)) {
93
+ expect(result.ref).toBe("main");
94
+ }
95
+ });
96
+ it("should parse GitHub source with feature branch", () => {
97
+ const result = parseSourceSpecifier("github:user/repo@feature/new-feature");
98
+ expect(result.type).toBe("github");
99
+ if (isGitHubSource(result)) {
100
+ expect(result.ref).toBe("feature/new-feature");
101
+ }
102
+ });
103
+ it("should parse GitHub source with branch containing hyphens", () => {
104
+ const result = parseSourceSpecifier("github:user/repo@fix-bug-123");
105
+ expect(result.type).toBe("github");
106
+ if (isGitHubSource(result)) {
107
+ expect(result.ref).toBe("fix-bug-123");
108
+ }
109
+ });
110
+ it("should parse GitHub source with branch containing dots", () => {
111
+ const result = parseSourceSpecifier("github:user/repo@release.2024.01");
112
+ expect(result.type).toBe("github");
113
+ if (isGitHubSource(result)) {
114
+ expect(result.ref).toBe("release.2024.01");
115
+ }
116
+ });
117
+ });
118
+ describe("GitHub sources with commit SHA ref", () => {
119
+ it("should parse GitHub source with short commit SHA", () => {
120
+ const result = parseSourceSpecifier("github:user/repo@abc1234");
121
+ expect(result.type).toBe("github");
122
+ if (isGitHubSource(result)) {
123
+ expect(result.ref).toBe("abc1234");
124
+ }
125
+ });
126
+ it("should parse GitHub source with full commit SHA", () => {
127
+ const result = parseSourceSpecifier("github:user/repo@abc1234567890def1234567890abc1234567890de");
128
+ expect(result.type).toBe("github");
129
+ if (isGitHubSource(result)) {
130
+ expect(result.ref).toBe("abc1234567890def1234567890abc1234567890de");
131
+ }
132
+ });
133
+ });
134
+ describe("GitHub source error cases", () => {
135
+ it("should throw for github: with no repo", () => {
136
+ expect(() => parseSourceSpecifier("github:")).toThrow(SourceParseError);
137
+ expect(() => parseSourceSpecifier("github:")).toThrow("owner/repo");
138
+ });
139
+ it("should throw for github:owner/ missing repo", () => {
140
+ expect(() => parseSourceSpecifier("github:owner/")).toThrow(SourceParseError);
141
+ expect(() => parseSourceSpecifier("github:owner/")).toThrow("cannot be empty");
142
+ });
143
+ it("should throw for github:/repo missing owner", () => {
144
+ expect(() => parseSourceSpecifier("github:/repo")).toThrow(SourceParseError);
145
+ expect(() => parseSourceSpecifier("github:/repo")).toThrow("cannot be empty");
146
+ });
147
+ it("should throw for github:owner (no slash)", () => {
148
+ expect(() => parseSourceSpecifier("github:owner")).toThrow(SourceParseError);
149
+ expect(() => parseSourceSpecifier("github:owner")).toThrow("owner/repo");
150
+ });
151
+ it("should throw for github:owner/repo@ with empty ref", () => {
152
+ expect(() => parseSourceSpecifier("github:owner/repo@")).toThrow(SourceParseError);
153
+ expect(() => parseSourceSpecifier("github:owner/repo@")).toThrow('cannot be empty after "@"');
154
+ });
155
+ it("should throw for nested paths (github:owner/repo/subdir)", () => {
156
+ expect(() => parseSourceSpecifier("github:owner/repo/subdir")).toThrow(SourceParseError);
157
+ expect(() => parseSourceSpecifier("github:owner/repo/subdir")).toThrow("Nested paths are not supported");
158
+ });
159
+ it("should throw for owner starting with dot", () => {
160
+ expect(() => parseSourceSpecifier("github:.hidden/repo")).toThrow(SourceParseError);
161
+ expect(() => parseSourceSpecifier("github:.hidden/repo")).toThrow("cannot start with a dot");
162
+ });
163
+ it("should throw for repo starting with dot", () => {
164
+ expect(() => parseSourceSpecifier("github:owner/.hidden")).toThrow(SourceParseError);
165
+ });
166
+ it("should throw for owner ending with .git", () => {
167
+ expect(() => parseSourceSpecifier("github:owner.git/repo")).toThrow(SourceParseError);
168
+ expect(() => parseSourceSpecifier("github:owner.git/repo")).toThrow('cannot end with ".git"');
169
+ });
170
+ it("should throw for repo ending with .git", () => {
171
+ expect(() => parseSourceSpecifier("github:owner/repo.git")).toThrow(SourceParseError);
172
+ expect(() => parseSourceSpecifier("github:owner/repo.git")).toThrow('cannot end with ".git"');
173
+ });
174
+ it("should throw for owner with invalid characters", () => {
175
+ expect(() => parseSourceSpecifier("github:owner!/repo")).toThrow(SourceParseError);
176
+ expect(() => parseSourceSpecifier("github:owner@name/repo")).toThrow(SourceParseError);
177
+ expect(() => parseSourceSpecifier("github:owner name/repo")).toThrow(SourceParseError);
178
+ });
179
+ it("should throw for repo with invalid characters", () => {
180
+ expect(() => parseSourceSpecifier("github:owner/repo!")).toThrow(SourceParseError);
181
+ expect(() => parseSourceSpecifier("github:owner/repo name")).toThrow(SourceParseError);
182
+ });
183
+ });
184
+ });
185
+ // =============================================================================
186
+ // Local Source Tests
187
+ // =============================================================================
188
+ describe("parseSourceSpecifier - Local sources", () => {
189
+ describe("relative paths", () => {
190
+ it("should parse ./ relative path", () => {
191
+ const result = parseSourceSpecifier("./local/path");
192
+ expect(result.type).toBe("local");
193
+ expect(isLocalSource(result)).toBe(true);
194
+ if (isLocalSource(result)) {
195
+ expect(result.path).toBe(path.resolve("./local/path"));
196
+ expect(path.isAbsolute(result.path)).toBe(true);
197
+ }
198
+ });
199
+ it("should parse ../ relative path", () => {
200
+ const result = parseSourceSpecifier("../parent/path");
201
+ expect(result.type).toBe("local");
202
+ if (isLocalSource(result)) {
203
+ expect(result.path).toBe(path.resolve("../parent/path"));
204
+ expect(path.isAbsolute(result.path)).toBe(true);
205
+ }
206
+ });
207
+ it("should parse path with multiple ../", () => {
208
+ const result = parseSourceSpecifier("../../grandparent/path");
209
+ expect(result.type).toBe("local");
210
+ if (isLocalSource(result)) {
211
+ expect(result.path).toBe(path.resolve("../../grandparent/path"));
212
+ }
213
+ });
214
+ it("should resolve . in path components", () => {
215
+ const result = parseSourceSpecifier("./a/./b/./c");
216
+ expect(result.type).toBe("local");
217
+ if (isLocalSource(result)) {
218
+ // path.resolve normalizes away the . components
219
+ expect(result.path).toContain("a");
220
+ expect(result.path).toContain("b");
221
+ expect(result.path).toContain("c");
222
+ }
223
+ });
224
+ it("should resolve .. in path components", () => {
225
+ const result = parseSourceSpecifier("./a/b/../c");
226
+ expect(result.type).toBe("local");
227
+ if (isLocalSource(result)) {
228
+ // path.resolve normalizes a/b/../c to a/c
229
+ expect(result.path).toContain("a");
230
+ expect(result.path).toContain("c");
231
+ expect(result.path).not.toMatch(/a[/\\]b[/\\]c/); // Should not have a/b/c
232
+ }
233
+ });
234
+ });
235
+ describe("absolute paths", () => {
236
+ it("should parse Unix absolute path", () => {
237
+ const result = parseSourceSpecifier("/absolute/path/to/agent");
238
+ expect(result.type).toBe("local");
239
+ if (isLocalSource(result)) {
240
+ expect(result.path).toBe("/absolute/path/to/agent");
241
+ expect(path.isAbsolute(result.path)).toBe(true);
242
+ }
243
+ });
244
+ it("should parse root path", () => {
245
+ const result = parseSourceSpecifier("/");
246
+ expect(result.type).toBe("local");
247
+ if (isLocalSource(result)) {
248
+ expect(result.path).toBe("/");
249
+ }
250
+ });
251
+ });
252
+ describe("edge cases", () => {
253
+ it("should handle path with spaces", () => {
254
+ const result = parseSourceSpecifier("./path with spaces/agent");
255
+ expect(result.type).toBe("local");
256
+ if (isLocalSource(result)) {
257
+ expect(result.path).toContain("path with spaces");
258
+ }
259
+ });
260
+ it("should handle path with special characters", () => {
261
+ const result = parseSourceSpecifier("./path-with_special.chars/agent");
262
+ expect(result.type).toBe("local");
263
+ if (isLocalSource(result)) {
264
+ expect(result.path).toContain("path-with_special.chars");
265
+ }
266
+ });
267
+ it("should handle deeply nested path", () => {
268
+ const result = parseSourceSpecifier("./a/b/c/d/e/f/g/agent");
269
+ expect(result.type).toBe("local");
270
+ if (isLocalSource(result)) {
271
+ expect(result.path).toContain("a");
272
+ expect(result.path).toContain("agent");
273
+ }
274
+ });
275
+ });
276
+ });
277
+ // =============================================================================
278
+ // GitHub Shorthand Tests
279
+ // =============================================================================
280
+ describe("parseSourceSpecifier - GitHub shorthand", () => {
281
+ describe("valid owner/repo shorthand", () => {
282
+ it("should parse owner/repo as GitHub source", () => {
283
+ const result = parseSourceSpecifier("user/repo");
284
+ expect(result.type).toBe("github");
285
+ expect(isGitHubSource(result)).toBe(true);
286
+ if (isGitHubSource(result)) {
287
+ expect(result.owner).toBe("user");
288
+ expect(result.repo).toBe("repo");
289
+ expect(result.ref).toBeUndefined();
290
+ }
291
+ });
292
+ it("should parse owner/repo with ref", () => {
293
+ const result = parseSourceSpecifier("user/repo@v1.0.0");
294
+ expect(result.type).toBe("github");
295
+ if (isGitHubSource(result)) {
296
+ expect(result.owner).toBe("user");
297
+ expect(result.repo).toBe("repo");
298
+ expect(result.ref).toBe("v1.0.0");
299
+ }
300
+ });
301
+ it("should parse owner/repo with branch ref", () => {
302
+ const result = parseSourceSpecifier("user/repo@main");
303
+ expect(result.type).toBe("github");
304
+ if (isGitHubSource(result)) {
305
+ expect(result.owner).toBe("user");
306
+ expect(result.repo).toBe("repo");
307
+ expect(result.ref).toBe("main");
308
+ }
309
+ });
310
+ it("should parse org/repo with hyphens", () => {
311
+ const result = parseSourceSpecifier("herdctl-examples/website-monitor-agent");
312
+ expect(result.type).toBe("github");
313
+ if (isGitHubSource(result)) {
314
+ expect(result.owner).toBe("herdctl-examples");
315
+ expect(result.repo).toBe("website-monitor-agent");
316
+ }
317
+ });
318
+ it("should parse owner/repo with underscores", () => {
319
+ const result = parseSourceSpecifier("my_org/my_repo");
320
+ expect(result.type).toBe("github");
321
+ if (isGitHubSource(result)) {
322
+ expect(result.owner).toBe("my_org");
323
+ expect(result.repo).toBe("my_repo");
324
+ }
325
+ });
326
+ it("should be equivalent to github: prefix form", () => {
327
+ const shorthand = parseSourceSpecifier("user/repo@v1.0.0");
328
+ const explicit = parseSourceSpecifier("github:user/repo@v1.0.0");
329
+ expect(shorthand).toEqual(explicit);
330
+ });
331
+ });
332
+ describe("unrecognized bare names", () => {
333
+ it("should throw for bare name without slash", () => {
334
+ expect(() => parseSourceSpecifier("competitive-analysis")).toThrow(SourceParseError);
335
+ expect(() => parseSourceSpecifier("competitive-analysis")).toThrow("Unrecognized source format");
336
+ });
337
+ it("should throw for single word", () => {
338
+ expect(() => parseSourceSpecifier("myagent")).toThrow(SourceParseError);
339
+ expect(() => parseSourceSpecifier("myagent")).toThrow("Unrecognized source format");
340
+ });
341
+ it("should throw for name with special characters", () => {
342
+ expect(() => parseSourceSpecifier("invalid!name")).toThrow(SourceParseError);
343
+ expect(() => parseSourceSpecifier("invalid@name")).toThrow(SourceParseError);
344
+ });
345
+ it("should throw for backslash-separated names", () => {
346
+ expect(() => parseSourceSpecifier("invalid\\name")).toThrow(SourceParseError);
347
+ });
348
+ });
349
+ });
350
+ // =============================================================================
351
+ // General Error Cases
352
+ // =============================================================================
353
+ describe("parseSourceSpecifier - Error cases", () => {
354
+ it("should throw for empty string", () => {
355
+ expect(() => parseSourceSpecifier("")).toThrow(SourceParseError);
356
+ expect(() => parseSourceSpecifier("")).toThrow("cannot be empty");
357
+ });
358
+ it("should throw for whitespace-only string", () => {
359
+ expect(() => parseSourceSpecifier(" ")).toThrow(SourceParseError);
360
+ expect(() => parseSourceSpecifier(" ")).toThrow("cannot be empty");
361
+ });
362
+ it("should throw for null-like values", () => {
363
+ expect(() => parseSourceSpecifier(null)).toThrow(SourceParseError);
364
+ expect(() => parseSourceSpecifier(undefined)).toThrow(SourceParseError);
365
+ });
366
+ it("should trim whitespace from input", () => {
367
+ const result = parseSourceSpecifier(" github:user/repo ");
368
+ expect(result.type).toBe("github");
369
+ if (isGitHubSource(result)) {
370
+ expect(result.owner).toBe("user");
371
+ expect(result.repo).toBe("repo");
372
+ }
373
+ });
374
+ it("should include source in error for debugging", () => {
375
+ try {
376
+ parseSourceSpecifier("github:invalid!");
377
+ }
378
+ catch (error) {
379
+ expect(error).toBeInstanceOf(SourceParseError);
380
+ if (error instanceof SourceParseError) {
381
+ expect(error.source).toBe("github:invalid!");
382
+ }
383
+ }
384
+ });
385
+ });
386
+ // =============================================================================
387
+ // Type Guard Tests
388
+ // =============================================================================
389
+ describe("Type guards", () => {
390
+ describe("isGitHubSource", () => {
391
+ it("should return true for GitHub source", () => {
392
+ const specifier = parseSourceSpecifier("github:user/repo");
393
+ expect(isGitHubSource(specifier)).toBe(true);
394
+ });
395
+ it("should return true for GitHub shorthand", () => {
396
+ const specifier = parseSourceSpecifier("user/repo");
397
+ expect(isGitHubSource(specifier)).toBe(true);
398
+ });
399
+ it("should return false for local source", () => {
400
+ const specifier = parseSourceSpecifier("./local/path");
401
+ expect(isGitHubSource(specifier)).toBe(false);
402
+ });
403
+ });
404
+ describe("isLocalSource", () => {
405
+ it("should return true for local source", () => {
406
+ const specifier = parseSourceSpecifier("./local/path");
407
+ expect(isLocalSource(specifier)).toBe(true);
408
+ });
409
+ it("should return false for GitHub source", () => {
410
+ const specifier = parseSourceSpecifier("github:user/repo");
411
+ expect(isLocalSource(specifier)).toBe(false);
412
+ });
413
+ it("should return false for GitHub shorthand", () => {
414
+ const specifier = parseSourceSpecifier("user/repo");
415
+ expect(isLocalSource(specifier)).toBe(false);
416
+ });
417
+ });
418
+ });
419
+ // =============================================================================
420
+ // stringifySourceSpecifier Tests
421
+ // =============================================================================
422
+ describe("stringifySourceSpecifier", () => {
423
+ describe("GitHub sources", () => {
424
+ it("should stringify basic GitHub source", () => {
425
+ const specifier = {
426
+ type: "github",
427
+ owner: "user",
428
+ repo: "repo",
429
+ };
430
+ expect(stringifySourceSpecifier(specifier)).toBe("github:user/repo");
431
+ });
432
+ it("should stringify GitHub source with ref", () => {
433
+ const specifier = {
434
+ type: "github",
435
+ owner: "user",
436
+ repo: "repo",
437
+ ref: "v1.0.0",
438
+ };
439
+ expect(stringifySourceSpecifier(specifier)).toBe("github:user/repo@v1.0.0");
440
+ });
441
+ it("should stringify GitHub source with branch ref", () => {
442
+ const specifier = {
443
+ type: "github",
444
+ owner: "user",
445
+ repo: "repo",
446
+ ref: "feature/new-feature",
447
+ };
448
+ expect(stringifySourceSpecifier(specifier)).toBe("github:user/repo@feature/new-feature");
449
+ });
450
+ });
451
+ describe("Local sources", () => {
452
+ it("should stringify local source", () => {
453
+ const specifier = {
454
+ type: "local",
455
+ path: "/absolute/path/to/agent",
456
+ };
457
+ expect(stringifySourceSpecifier(specifier)).toBe("/absolute/path/to/agent");
458
+ });
459
+ });
460
+ describe("Round-trip", () => {
461
+ it("should round-trip GitHub source", () => {
462
+ const original = "github:user/repo@v1.0.0";
463
+ const parsed = parseSourceSpecifier(original);
464
+ const stringified = stringifySourceSpecifier(parsed);
465
+ expect(stringified).toBe(original);
466
+ });
467
+ it("should round-trip GitHub shorthand via explicit form", () => {
468
+ const parsed = parseSourceSpecifier("user/repo@v1.0.0");
469
+ const stringified = stringifySourceSpecifier(parsed);
470
+ // Shorthand round-trips to the explicit github: form
471
+ expect(stringified).toBe("github:user/repo@v1.0.0");
472
+ });
473
+ // Note: Local paths don't round-trip exactly because they're resolved to absolute
474
+ it("should produce valid specifier on local source round-trip", () => {
475
+ const original = "./local/path";
476
+ const parsed = parseSourceSpecifier(original);
477
+ const stringified = stringifySourceSpecifier(parsed);
478
+ // The stringified version is absolute, but should parse back to same path
479
+ const reparsed = parseSourceSpecifier(stringified);
480
+ expect(reparsed.type).toBe("local");
481
+ if (isLocalSource(parsed) && isLocalSource(reparsed)) {
482
+ expect(reparsed.path).toBe(parsed.path);
483
+ }
484
+ });
485
+ });
486
+ });
487
+ // =============================================================================
488
+ // SourceSpecifier Type Tests (compile-time)
489
+ // =============================================================================
490
+ describe("SourceSpecifier types", () => {
491
+ it("should have correct type structure for GitHubSource", () => {
492
+ const specifier = {
493
+ type: "github",
494
+ owner: "user",
495
+ repo: "repo",
496
+ ref: "v1.0.0",
497
+ };
498
+ // Type assertions - these are compile-time checks
499
+ const _type = specifier.type;
500
+ const _owner = specifier.owner;
501
+ const _repo = specifier.repo;
502
+ const _ref = specifier.ref;
503
+ expect(_type).toBe("github");
504
+ expect(_owner).toBe("user");
505
+ expect(_repo).toBe("repo");
506
+ expect(_ref).toBe("v1.0.0");
507
+ });
508
+ it("should have correct type structure for LocalSource", () => {
509
+ const specifier = {
510
+ type: "local",
511
+ path: "/some/path",
512
+ };
513
+ const _type = specifier.type;
514
+ const _path = specifier.path;
515
+ expect(_type).toBe("local");
516
+ expect(_path).toBe("/some/path");
517
+ });
518
+ it("should allow discrimination via type field", () => {
519
+ const specifier = parseSourceSpecifier("github:user/repo");
520
+ // This tests that the type discriminator works correctly
521
+ switch (specifier.type) {
522
+ case "github":
523
+ expect(specifier.owner).toBe("user");
524
+ expect(specifier.repo).toBe("repo");
525
+ break;
526
+ case "local":
527
+ // TypeScript knows specifier.path exists here
528
+ expect(specifier.path).toBeDefined();
529
+ break;
530
+ }
531
+ });
532
+ });
533
+ //# sourceMappingURL=source-specifier.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-specifier.test.js","sourceRoot":"","sources":["../../../src/distribution/__tests__/source-specifier.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
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 { FleetManagerError, type FleetManagerErrorCode } from "../fleet-manager/errors.js";
9
+ import { type InstallationMetadata } from "./installation-metadata.js";
10
+ /**
11
+ * Information about a discovered agent
12
+ */
13
+ export interface DiscoveredAgent {
14
+ /** Agent name (from agent.yaml or directory name) */
15
+ name: string;
16
+ /** Whether this agent was installed via herdctl agent add (has metadata.json) */
17
+ installed: boolean;
18
+ /** Installation metadata (only for installed agents) */
19
+ metadata?: InstallationMetadata;
20
+ /** Absolute path to the agent directory */
21
+ path: string;
22
+ /** Relative path to agent.yaml (as referenced in fleet config) */
23
+ configPath: string;
24
+ /** Agent description (from agent.yaml if available) */
25
+ description?: string;
26
+ /** Agent version (from metadata.json source, or herdctl.json) */
27
+ version?: string;
28
+ }
29
+ /**
30
+ * Options for discovering agents
31
+ */
32
+ export interface DiscoveryOptions {
33
+ /** Path to herdctl.yaml */
34
+ configPath: string;
35
+ /** Base directory of the project (defaults to dirname of configPath) */
36
+ baseDir?: string;
37
+ }
38
+ /**
39
+ * Result of agent discovery
40
+ */
41
+ export interface DiscoveryResult {
42
+ /** All discovered agents (installed + manual) */
43
+ agents: DiscoveredAgent[];
44
+ }
45
+ /** Error code: herdctl.yaml doesn't exist */
46
+ export declare const DISCOVERY_CONFIG_NOT_FOUND: FleetManagerErrorCode;
47
+ /** Error code: herdctl.yaml is invalid */
48
+ export declare const DISCOVERY_CONFIG_INVALID: FleetManagerErrorCode;
49
+ /**
50
+ * Error thrown when agent discovery fails
51
+ */
52
+ export declare class AgentDiscoveryError extends FleetManagerError {
53
+ constructor(message: string, code: FleetManagerErrorCode);
54
+ }
55
+ /**
56
+ * Discover agents referenced in the fleet configuration
57
+ *
58
+ * This function:
59
+ * 1. Reads herdctl.yaml and extracts agent references
60
+ * 2. For each reference, checks if the agent directory exists
61
+ * 3. Reads agent.yaml to get name and description
62
+ * 4. Checks for metadata.json to determine if installed via herdctl
63
+ * 5. Returns all discovered agents sorted by name
64
+ *
65
+ * @param options - Discovery options including config path
66
+ * @returns Discovery result with list of agents
67
+ * @throws {AgentDiscoveryError} When discovery fails
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * const result = await discoverAgents({
72
+ * configPath: "/path/to/herdctl.yaml"
73
+ * });
74
+ *
75
+ * for (const agent of result.agents) {
76
+ * console.log(`${agent.name}: ${agent.installed ? 'installed' : 'manual'}`);
77
+ * }
78
+ * ```
79
+ */
80
+ export declare function discoverAgents(options: DiscoveryOptions): Promise<DiscoveryResult>;
81
+ //# sourceMappingURL=agent-discovery.d.ts.map